From acd61d619e8a26c7e5960afb1883d7147aef74a4 Mon Sep 17 00:00:00 2001 From: "Carl.Kenner" Date: Sat, 2 May 2009 21:03:37 +0000 Subject: [PATCH] DOSBox 0.50 --- AUTHORS | 19 +- COPYING | 680 +- ChangeLog | 512 +- INSTALL | 133 +- Makefile.am | 11 +- Makefile.in | 428 + NEWS | 553 +- README | 1327 +-- THANKS | 34 +- VERSION | 1 - acinclude.m4 | 557 +- aclocal.m4 | 992 ++ autogen.sh | 32 +- config.guess | 1368 +++ config.h.in | 65 + config.sub | 1443 +++ configure | 5512 ++++++++++ configure.in | 580 +- depcomp | 436 + docs/Makefile.am | 8 - docs/PORTING | 44 - docs/README.video | 35 - docs/dosbox.1 | 337 - include/Makefile.am | 68 +- include/Makefile.in | 269 + include/bios.h | 247 +- include/bios_disk.h | 85 - include/callback.h | 155 +- include/control.h | 87 - include/cpu.h | 591 +- include/cross.h | 162 +- include/debug.h | 59 +- include/dma.h | 141 +- include/dos_inc.h | 918 +- include/dos_system.h | 374 +- include/dosbox.h | 139 +- include/fpu.h | 155 +- include/hardware.h | 94 +- include/inout.h | 126 +- include/ipx.h | 161 - include/ipxserver.h | 48 - include/joystick.h | 75 +- include/keyboard.h | 107 +- include/logging.h | 67 - include/mapper.h | 39 - include/mem.h | 427 +- include/mixer.h | 156 +- include/modules.h | 360 +- include/mouse.h | 70 +- include/paging.h | 366 - include/pic.h | 111 +- include/programs.h | 148 +- include/regs.h | 286 +- include/render.h | 123 +- include/serialport.h | 361 - include/setup.h | 374 +- include/shell.h | 144 - include/support.h | 123 +- include/timer.h | 91 +- include/vga.h | 509 - include/video.h | 135 +- install-sh | 251 + missing | 336 + mkinstalldirs | 101 + scripts/dosbox-installer.nsi | 149 - scripts/ega-switch.pl | 32 - scripts/font-switch.pl | 25 - settings.h | 26 + src/Makefile.am | 30 +- src/Makefile.in | 420 + src/cpu/Makefile.am | 12 +- src/cpu/Makefile.in | 401 + src/cpu/callback.cpp | 747 +- src/cpu/core_16/Makefile.am | 3 + src/cpu/core_16/Makefile.in | 244 + src/cpu/core_16/helpers.h | 76 + src/cpu/core_16/instructions.h | 593 + src/cpu/core_16/main.h | 1488 +++ src/cpu/core_16/prefix_66.h | 469 + src/cpu/core_16/prefix_66_of.h | 124 + src/cpu/core_16/prefix_of.h | 188 + .../risc_armv4le.h => core_16/start.h} | 51 +- src/{ints/xms.h => cpu/core_16/stop.h} | 53 +- src/cpu/core_16/support.h | 191 + src/cpu/core_16/table_ea.h | 283 + src/cpu/core_dyn_x86.cpp | 476 - src/cpu/core_dyn_x86/Makefile.am | 2 - src/cpu/core_dyn_x86/cache.h | 528 - src/cpu/core_dyn_x86/decoder.h | 2680 ----- src/cpu/core_dyn_x86/dyn_fpu.h | 665 -- src/cpu/core_dyn_x86/dyn_fpu_dh.h | 494 - src/cpu/core_dyn_x86/helpers.h | 69 - src/cpu/core_dyn_x86/risc_x86.h | 1072 -- src/cpu/core_dyn_x86/string.h | 164 - src/cpu/core_dynrec.cpp | 327 - src/cpu/core_dynrec/Makefile.am | 5 - src/cpu/core_dynrec/cache.h | 665 -- src/cpu/core_dynrec/decoder.h | 599 - src/cpu/core_dynrec/decoder_basic.h | 1239 --- src/cpu/core_dynrec/decoder_opcodes.h | 1427 --- src/cpu/core_dynrec/dyn_fpu.h | 681 -- src/cpu/core_dynrec/operators.h | 1995 ---- src/cpu/core_dynrec/risc_armv4le-common.h | 102 - src/cpu/core_dynrec/risc_armv4le-o3.h | 982 -- src/cpu/core_dynrec/risc_armv4le-s3.h | 817 -- src/cpu/core_dynrec/risc_armv4le-thumb-iw.h | 1289 --- src/cpu/core_dynrec/risc_armv4le-thumb-niw.h | 1286 --- src/cpu/core_dynrec/risc_armv4le-thumb.h | 1078 -- src/cpu/core_dynrec/risc_mipsel32.h | 748 -- src/cpu/core_dynrec/risc_x64.h | 679 -- src/cpu/core_dynrec/risc_x86.h | 513 - src/cpu/core_full.cpp | 99 - src/cpu/core_full/Makefile.am | 3 - src/cpu/core_full/ea_lookup.h | 237 - src/cpu/core_full/load.h | 489 - src/cpu/core_full/loadwrite.h | 39 - src/cpu/core_full/op.h | 645 -- src/cpu/core_full/optable.h | 814 -- src/cpu/core_full/save.h | 99 - src/cpu/core_full/string.h | 227 - src/cpu/core_full/support.h | 248 - src/cpu/core_normal.cpp | 209 - src/cpu/core_normal/Makefile.am | 3 - src/cpu/core_normal/helpers.h | 162 - src/cpu/core_normal/prefix_0f.h | 558 - src/cpu/core_normal/prefix_66.h | 718 -- src/cpu/core_normal/prefix_66_0f.h | 441 - src/cpu/core_normal/prefix_none.h | 1176 -- src/cpu/core_normal/string.h | 232 - src/cpu/core_normal/support.h | 96 - src/cpu/core_normal/table_ea.h | 185 - src/cpu/core_prefetch.cpp | 315 - src/cpu/core_simple.cpp | 206 - src/cpu/cpu.cpp | 2595 +---- src/cpu/flags.cpp | 1770 +-- src/cpu/instructions.h | 960 -- src/cpu/lazyflags.h | 132 - src/cpu/modrm.cpp | 420 +- src/cpu/modrm.h | 140 +- src/cpu/paging.cpp | 891 -- src/cpu/slow_16.cpp | 120 + src/debug/Makefile.am | 9 +- src/debug/Makefile.in | 312 + src/debug/debug.cpp | 2585 +---- src/debug/debug_disasm.cpp | 2229 ++-- src/debug/debug_gui.cpp | 415 +- src/debug/debug_inc.h | 113 +- src/debug/debug_win32.cpp | 149 +- src/debug/disasm_tables.h | 382 +- src/dos/Makefile.am | 17 +- src/dos/Makefile.in | 334 + src/dos/cdrom.cpp | 219 - src/dos/cdrom.h | 364 - src/dos/cdrom_aspi_win32.cpp | 765 -- src/dos/cdrom_image.cpp | 691 -- src/dos/cdrom_ioctl_linux.cpp | 97 - src/dos/cdrom_ioctl_os2.cpp | 153 - src/dos/cdrom_ioctl_win32.cpp | 608 - src/dos/dev_con.h | 521 +- src/dos/dos.cpp | 1950 ++-- src/dos/dos_classes.cpp | 677 +- src/dos/dos_codepages.h | 1131 -- src/dos/dos_devices.cpp | 269 +- src/dos/dos_execute.cpp | 941 +- src/dos/dos_files.cpp | 1833 ++-- src/dos/dos_ioctl.cpp | 286 +- src/dos/dos_keyboard_layout.cpp | 1292 --- src/dos/dos_keyboard_layout_data.h | 5393 --------- src/dos/dos_memory.cpp | 623 +- src/dos/dos_misc.cpp | 285 +- src/dos/dos_mscdex.cpp | 1289 --- src/dos/dos_programs.cpp | 1754 +-- src/dos/dos_tables.cpp | 225 +- src/dos/drive_cache.cpp | 764 -- src/dos/drive_fat.cpp | 1260 --- src/dos/drive_iso.cpp | 576 - src/dos/drive_local.cpp | 927 +- src/dos/drive_virtual.cpp | 480 +- src/dos/drives.cpp | 260 +- src/dos/drives.h | 470 +- src/dos/scsidefs.h | 288 - src/dos/wnaspi32.h | 354 - src/dosbox.cpp | 975 +- src/dosbox.lang | 75 + src/fpu/Makefile.am | 9 +- src/fpu/Makefile.in | 307 + src/fpu/fpu.cpp | 689 +- src/fpu/fpu_instructions.h | 596 - src/fpu/fpu_instructions_x86.h | 1489 --- src/fpu/fpu_load.h | 21 + src/gui/Makefile.am | 16 +- src/gui/Makefile.in | 303 + src/gui/dosbox_logo.h | 541 - src/gui/midi.cpp | 217 - src/gui/midi_alsa.h | 196 - src/gui/midi_coreaudio.h | 105 - src/gui/midi_coremidi.h | 105 - src/gui/midi_oss.h | 76 - src/gui/midi_win32.h | 95 - src/gui/render.cpp | 794 +- src/gui/render_loops.h | 157 - src/gui/render_scalers.cpp | 440 - src/gui/render_scalers.h | 139 - src/gui/render_simple.h | 122 - src/gui/render_templates.h | 580 - src/gui/render_templates_hq.h | 85 - src/gui/render_templates_hq2x.h | 1896 ---- src/gui/render_templates_hq3x.h | 2872 ----- src/gui/render_templates_sai.h | 229 - src/gui/sdl_gui.cpp | 632 -- src/gui/sdl_mapper.cpp | 2469 ----- src/gui/sdlmain.cpp | 2185 +--- src/hardware/Makefile.am | 26 +- src/hardware/Makefile.in | 356 + src/hardware/adlib.cpp | 1028 +- src/hardware/adlib.h | 153 - src/hardware/cmos.cpp | 327 - src/hardware/dbopl.cpp | 1474 --- src/hardware/dbopl.h | 247 - src/hardware/disney.cpp | 371 - src/hardware/dma.cpp | 606 +- src/hardware/ega-switch.h | 9730 +++++++++++++++++ src/hardware/fmopl.c | 4402 ++++---- src/hardware/fmopl.h | 302 +- src/hardware/font-switch.h | 2562 +++++ src/hardware/gameblaster.cpp | 717 +- src/hardware/gus.cpp | 888 -- src/hardware/hardware.cpp | 789 +- src/hardware/iohandler.cpp | 530 +- src/hardware/ipx.cpp | 1200 -- src/hardware/ipxserver.cpp | 233 - src/hardware/joystick.cpp | 332 +- src/hardware/keyboard.cpp | 649 +- src/hardware/memory.cpp | 912 +- src/hardware/mixer.cpp | 925 +- src/hardware/mpu401.cpp | 644 -- src/hardware/opl.cpp | 1452 --- src/hardware/opl.h | 194 - src/hardware/pcspeaker.cpp | 442 +- src/hardware/pic.cpp | 972 +- src/hardware/sblaster.cpp | 2182 ++-- src/hardware/serialport/Makefile.am | 10 - src/hardware/serialport/directserial_os2.cpp | 515 - src/hardware/serialport/directserial_os2.h | 82 - .../serialport/directserial_posix.cpp | 361 - src/hardware/serialport/directserial_posix.h | 69 - .../serialport/directserial_win32.cpp | 394 - src/hardware/serialport/directserial_win32.h | 69 - src/hardware/serialport/misc_util.cpp | 304 - src/hardware/serialport/misc_util.h | 103 - src/hardware/serialport/nullmodem.cpp | 501 - src/hardware/serialport/nullmodem.h | 105 - src/hardware/serialport/serialdummy.cpp | 103 - src/hardware/serialport/serialdummy.h | 49 - src/hardware/serialport/serialport.cpp | 1242 --- src/hardware/serialport/softmodem.cpp | 803 -- src/hardware/serialport/softmodem.h | 250 - src/hardware/tandy_sound.cpp | 524 +- src/hardware/timer.cpp | 765 +- src/hardware/vga.cpp | 423 +- src/hardware/vga.h | 255 + src/hardware/vga_attr.cpp | 391 +- src/hardware/vga_crtc.cpp | 764 +- src/hardware/vga_dac.cpp | 403 +- src/hardware/vga_draw.cpp | 1541 +-- src/hardware/vga_fonts.cpp | 1254 +++ src/hardware/vga_gfx.cpp | 457 +- src/hardware/vga_memory.cpp | 1162 +- src/hardware/vga_misc.cpp | 225 +- src/hardware/vga_other.cpp | 583 - src/hardware/vga_paradise.cpp | 242 - src/hardware/vga_s3.cpp | 566 - src/hardware/vga_seq.cpp | 284 +- src/hardware/vga_tseng.cpp | 804 -- src/hardware/vga_xga.cpp | 1320 --- src/hardware/ymf262.c | 2746 ----- src/hardware/ymf262.h | 53 - src/ints/Makefile.am | 13 +- src/ints/Makefile.in | 333 + src/ints/bios.cpp | 1303 +-- src/ints/bios_disk.cpp | 618 +- src/ints/bios_keyboard.cpp | 1024 +- src/ints/ems.cpp | 1548 +-- src/ints/int10.cpp | 1001 +- src/ints/int10.h | 438 +- src/ints/int10_char.cpp | 1022 +- src/ints/int10_memory.cpp | 2750 +++-- src/ints/int10_misc.cpp | 447 +- src/ints/int10_modes.cpp | 1762 +-- src/ints/int10_pal.cpp | 410 +- src/ints/int10_put_pixel.cpp | 291 +- src/ints/int10_vesa.cpp | 521 - src/ints/int10_video_state.cpp | 384 - src/ints/int10_vptable.cpp | 705 -- src/ints/mouse.cpp | 1371 +-- src/ints/xms.cpp | 667 +- src/libs/Makefile.am | 3 - src/libs/gui_tk/Doxyfile | 238 - src/libs/gui_tk/Makefile.am | 4 - src/libs/gui_tk/gui_tk.cpp | 1707 --- src/libs/gui_tk/gui_tk.h | 2225 ---- src/libs/zmbv/Makefile.am | 1 - src/libs/zmbv/drvproc.cpp | 212 - src/libs/zmbv/resource.h | 21 - src/libs/zmbv/zmbv.cpp | 549 - src/libs/zmbv/zmbv.def | 4 - src/libs/zmbv/zmbv.h | 118 - src/libs/zmbv/zmbv.inf | 105 - src/libs/zmbv/zmbv.sln | 21 - src/libs/zmbv/zmbv.vcproj | 141 - src/libs/zmbv/zmbv_vfw.cpp | 397 - src/libs/zmbv/zmbv_vfw.h | 61 - src/libs/zmbv/zmbv_vfw.rc | 123 - src/misc/Makefile.am | 8 +- src/misc/Makefile.in | 309 + src/misc/cross.cpp | 240 - src/misc/messages.cpp | 248 +- src/misc/plugins.cpp | 159 + src/misc/programs.cpp | 566 +- src/misc/setup.cpp | 1032 +- src/misc/support.cpp | 409 +- src/platform/Makefile.am | 4 +- src/platform/Makefile.in | 326 + src/platform/sdl-win32.diff | 55 - src/platform/visualc/Makefile.am | 2 +- src/platform/visualc/Makefile.in | 205 + src/platform/visualc/config.h | 82 +- src/platform/visualc/dirent.c | 190 +- src/platform/visualc/dirent.h | 116 +- src/platform/visualc/ntddcdrm.h | 320 - src/platform/visualc/ntddscsi.h | 174 - src/platform/visualc/unistd.h | 20 +- src/shell/Makefile.am | 8 +- src/shell/Makefile.in | 312 + src/shell/shell.cpp | 813 +- src/shell/shell_batch.cpp | 325 +- src/shell/shell_cmds.cpp | 1445 +-- src/shell/shell_inc.h | 102 + src/shell/shell_misc.cpp | 833 +- src/winres.rc | 37 - visualc/Makefile.am | 1 + visualc/Makefile.in | 205 + visualc/dosbox.dsp | 639 ++ visualc/dosbox.dsw | 29 + visualc_net/Makefile.am | 1 - visualc_net/dosbox.sln | 21 - visualc_net/dosbox.vcproj | 892 -- 347 files changed, 57061 insertions(+), 145839 deletions(-) create mode 100644 Makefile.in delete mode 100644 VERSION create mode 100644 aclocal.m4 create mode 100644 config.guess create mode 100644 config.h.in create mode 100644 config.sub create mode 100644 configure create mode 100644 depcomp delete mode 100644 docs/Makefile.am delete mode 100644 docs/PORTING delete mode 100644 docs/README.video delete mode 100644 docs/dosbox.1 create mode 100644 include/Makefile.in delete mode 100644 include/bios_disk.h delete mode 100644 include/control.h delete mode 100644 include/ipx.h delete mode 100644 include/ipxserver.h delete mode 100644 include/logging.h delete mode 100644 include/mapper.h delete mode 100644 include/paging.h delete mode 100644 include/serialport.h delete mode 100644 include/shell.h delete mode 100644 include/vga.h create mode 100644 install-sh create mode 100644 missing create mode 100644 mkinstalldirs delete mode 100644 scripts/dosbox-installer.nsi delete mode 100644 scripts/ega-switch.pl delete mode 100644 scripts/font-switch.pl create mode 100644 settings.h create mode 100644 src/Makefile.in create mode 100644 src/cpu/Makefile.in create mode 100644 src/cpu/core_16/Makefile.am create mode 100644 src/cpu/core_16/Makefile.in create mode 100644 src/cpu/core_16/helpers.h create mode 100644 src/cpu/core_16/instructions.h create mode 100644 src/cpu/core_16/main.h create mode 100644 src/cpu/core_16/prefix_66.h create mode 100644 src/cpu/core_16/prefix_66_of.h create mode 100644 src/cpu/core_16/prefix_of.h rename src/cpu/{core_dynrec/risc_armv4le.h => core_16/start.h} (59%) rename src/{ints/xms.h => cpu/core_16/stop.h} (50%) create mode 100644 src/cpu/core_16/support.h create mode 100644 src/cpu/core_16/table_ea.h delete mode 100644 src/cpu/core_dyn_x86.cpp delete mode 100644 src/cpu/core_dyn_x86/Makefile.am delete mode 100644 src/cpu/core_dyn_x86/cache.h delete mode 100644 src/cpu/core_dyn_x86/decoder.h delete mode 100644 src/cpu/core_dyn_x86/dyn_fpu.h delete mode 100644 src/cpu/core_dyn_x86/dyn_fpu_dh.h delete mode 100644 src/cpu/core_dyn_x86/helpers.h delete mode 100644 src/cpu/core_dyn_x86/risc_x86.h delete mode 100644 src/cpu/core_dyn_x86/string.h delete mode 100644 src/cpu/core_dynrec.cpp delete mode 100644 src/cpu/core_dynrec/Makefile.am delete mode 100644 src/cpu/core_dynrec/cache.h delete mode 100644 src/cpu/core_dynrec/decoder.h delete mode 100644 src/cpu/core_dynrec/decoder_basic.h delete mode 100644 src/cpu/core_dynrec/decoder_opcodes.h delete mode 100644 src/cpu/core_dynrec/dyn_fpu.h delete mode 100644 src/cpu/core_dynrec/operators.h delete mode 100644 src/cpu/core_dynrec/risc_armv4le-common.h delete mode 100644 src/cpu/core_dynrec/risc_armv4le-o3.h delete mode 100644 src/cpu/core_dynrec/risc_armv4le-s3.h delete mode 100644 src/cpu/core_dynrec/risc_armv4le-thumb-iw.h delete mode 100644 src/cpu/core_dynrec/risc_armv4le-thumb-niw.h delete mode 100644 src/cpu/core_dynrec/risc_armv4le-thumb.h delete mode 100644 src/cpu/core_dynrec/risc_mipsel32.h delete mode 100644 src/cpu/core_dynrec/risc_x64.h delete mode 100644 src/cpu/core_dynrec/risc_x86.h delete mode 100644 src/cpu/core_full.cpp delete mode 100644 src/cpu/core_full/Makefile.am delete mode 100644 src/cpu/core_full/ea_lookup.h delete mode 100644 src/cpu/core_full/load.h delete mode 100644 src/cpu/core_full/loadwrite.h delete mode 100644 src/cpu/core_full/op.h delete mode 100644 src/cpu/core_full/optable.h delete mode 100644 src/cpu/core_full/save.h delete mode 100644 src/cpu/core_full/string.h delete mode 100644 src/cpu/core_full/support.h delete mode 100644 src/cpu/core_normal.cpp delete mode 100644 src/cpu/core_normal/Makefile.am delete mode 100644 src/cpu/core_normal/helpers.h delete mode 100644 src/cpu/core_normal/prefix_0f.h delete mode 100644 src/cpu/core_normal/prefix_66.h delete mode 100644 src/cpu/core_normal/prefix_66_0f.h delete mode 100644 src/cpu/core_normal/prefix_none.h delete mode 100644 src/cpu/core_normal/string.h delete mode 100644 src/cpu/core_normal/support.h delete mode 100644 src/cpu/core_normal/table_ea.h delete mode 100644 src/cpu/core_prefetch.cpp delete mode 100644 src/cpu/core_simple.cpp delete mode 100644 src/cpu/instructions.h delete mode 100644 src/cpu/lazyflags.h delete mode 100644 src/cpu/paging.cpp create mode 100644 src/cpu/slow_16.cpp create mode 100644 src/debug/Makefile.in create mode 100644 src/dos/Makefile.in delete mode 100644 src/dos/cdrom.cpp delete mode 100644 src/dos/cdrom.h delete mode 100644 src/dos/cdrom_aspi_win32.cpp delete mode 100644 src/dos/cdrom_image.cpp delete mode 100644 src/dos/cdrom_ioctl_linux.cpp delete mode 100644 src/dos/cdrom_ioctl_os2.cpp delete mode 100644 src/dos/cdrom_ioctl_win32.cpp delete mode 100644 src/dos/dos_codepages.h delete mode 100644 src/dos/dos_keyboard_layout.cpp delete mode 100644 src/dos/dos_keyboard_layout_data.h delete mode 100644 src/dos/dos_mscdex.cpp delete mode 100644 src/dos/drive_cache.cpp delete mode 100644 src/dos/drive_fat.cpp delete mode 100644 src/dos/drive_iso.cpp delete mode 100644 src/dos/scsidefs.h delete mode 100644 src/dos/wnaspi32.h create mode 100644 src/dosbox.lang create mode 100644 src/fpu/Makefile.in delete mode 100644 src/fpu/fpu_instructions.h delete mode 100644 src/fpu/fpu_instructions_x86.h create mode 100644 src/fpu/fpu_load.h create mode 100644 src/gui/Makefile.in delete mode 100644 src/gui/dosbox_logo.h delete mode 100644 src/gui/midi.cpp delete mode 100644 src/gui/midi_alsa.h delete mode 100644 src/gui/midi_coreaudio.h delete mode 100644 src/gui/midi_coremidi.h delete mode 100644 src/gui/midi_oss.h delete mode 100644 src/gui/midi_win32.h delete mode 100644 src/gui/render_loops.h delete mode 100644 src/gui/render_scalers.cpp delete mode 100644 src/gui/render_scalers.h delete mode 100644 src/gui/render_simple.h delete mode 100644 src/gui/render_templates.h delete mode 100644 src/gui/render_templates_hq.h delete mode 100644 src/gui/render_templates_hq2x.h delete mode 100644 src/gui/render_templates_hq3x.h delete mode 100644 src/gui/render_templates_sai.h delete mode 100644 src/gui/sdl_gui.cpp delete mode 100644 src/gui/sdl_mapper.cpp create mode 100644 src/hardware/Makefile.in delete mode 100644 src/hardware/adlib.h delete mode 100644 src/hardware/cmos.cpp delete mode 100644 src/hardware/dbopl.cpp delete mode 100644 src/hardware/dbopl.h delete mode 100644 src/hardware/disney.cpp create mode 100644 src/hardware/ega-switch.h create mode 100644 src/hardware/font-switch.h delete mode 100644 src/hardware/gus.cpp delete mode 100644 src/hardware/ipx.cpp delete mode 100644 src/hardware/ipxserver.cpp delete mode 100644 src/hardware/mpu401.cpp delete mode 100644 src/hardware/opl.cpp delete mode 100644 src/hardware/opl.h delete mode 100644 src/hardware/serialport/Makefile.am delete mode 100644 src/hardware/serialport/directserial_os2.cpp delete mode 100644 src/hardware/serialport/directserial_os2.h delete mode 100644 src/hardware/serialport/directserial_posix.cpp delete mode 100644 src/hardware/serialport/directserial_posix.h delete mode 100644 src/hardware/serialport/directserial_win32.cpp delete mode 100644 src/hardware/serialport/directserial_win32.h delete mode 100644 src/hardware/serialport/misc_util.cpp delete mode 100644 src/hardware/serialport/misc_util.h delete mode 100644 src/hardware/serialport/nullmodem.cpp delete mode 100644 src/hardware/serialport/nullmodem.h delete mode 100644 src/hardware/serialport/serialdummy.cpp delete mode 100644 src/hardware/serialport/serialdummy.h delete mode 100644 src/hardware/serialport/serialport.cpp delete mode 100644 src/hardware/serialport/softmodem.cpp delete mode 100644 src/hardware/serialport/softmodem.h create mode 100644 src/hardware/vga.h create mode 100644 src/hardware/vga_fonts.cpp delete mode 100644 src/hardware/vga_other.cpp delete mode 100644 src/hardware/vga_paradise.cpp delete mode 100644 src/hardware/vga_s3.cpp delete mode 100644 src/hardware/vga_tseng.cpp delete mode 100644 src/hardware/vga_xga.cpp delete mode 100644 src/hardware/ymf262.c delete mode 100644 src/hardware/ymf262.h create mode 100644 src/ints/Makefile.in delete mode 100644 src/ints/int10_vesa.cpp delete mode 100644 src/ints/int10_video_state.cpp delete mode 100644 src/ints/int10_vptable.cpp delete mode 100644 src/libs/Makefile.am delete mode 100644 src/libs/gui_tk/Doxyfile delete mode 100644 src/libs/gui_tk/Makefile.am delete mode 100644 src/libs/gui_tk/gui_tk.cpp delete mode 100644 src/libs/gui_tk/gui_tk.h delete mode 100644 src/libs/zmbv/Makefile.am delete mode 100644 src/libs/zmbv/drvproc.cpp delete mode 100644 src/libs/zmbv/resource.h delete mode 100644 src/libs/zmbv/zmbv.cpp delete mode 100644 src/libs/zmbv/zmbv.def delete mode 100644 src/libs/zmbv/zmbv.h delete mode 100644 src/libs/zmbv/zmbv.inf delete mode 100644 src/libs/zmbv/zmbv.sln delete mode 100644 src/libs/zmbv/zmbv.vcproj delete mode 100644 src/libs/zmbv/zmbv_vfw.cpp delete mode 100644 src/libs/zmbv/zmbv_vfw.h delete mode 100644 src/libs/zmbv/zmbv_vfw.rc create mode 100644 src/misc/Makefile.in delete mode 100644 src/misc/cross.cpp create mode 100644 src/misc/plugins.cpp create mode 100644 src/platform/Makefile.in delete mode 100644 src/platform/sdl-win32.diff create mode 100644 src/platform/visualc/Makefile.in delete mode 100644 src/platform/visualc/ntddcdrm.h delete mode 100644 src/platform/visualc/ntddscsi.h create mode 100644 src/shell/Makefile.in create mode 100644 src/shell/shell_inc.h delete mode 100644 src/winres.rc create mode 100644 visualc/Makefile.am create mode 100644 visualc/Makefile.in create mode 100644 visualc/dosbox.dsp create mode 100644 visualc/dosbox.dsw delete mode 100644 visualc_net/Makefile.am delete mode 100644 visualc_net/dosbox.sln delete mode 100644 visualc_net/dosbox.vcproj diff --git a/AUTHORS b/AUTHORS index ef20cdf..9873d58 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,11 +1,8 @@ -The DOSBox Team ---------------- - -Sjoerd v.d. Berg -Peter Veenstra -Ulf Wohlers -Tommy Frössman -Dean Beeler -Sebastian Strohhäcker - -nick_without_<> @ users.sourceforge.net +The DOSBox Team +--------------- + +Sjoerd v.d. Berg +Peter Veenstra + + + diff --git a/COPYING b/COPYING index fbdd65f..d60c31a 100644 --- a/COPYING +++ b/COPYING @@ -1,340 +1,340 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog index a0506cd..051d4d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,509 +1,3 @@ -0.72 - - Fixed unitialized variable in joystick. (Fixes crashes on Vista and - Mac OS X) - - Some bugfixes and speedups to the 64 bit recompiling core. - - Fixed sign flag on soundblaster dma transfers (Space Quest 6 intro) - - Fixed a bug in keyboard layout processing code and fixed certain - layouts. - - Fixed Dreamweb. - - Improved speed unlocking when running cycles=max. - - Fixed a crash related to the tab completion in the shell. - - Improved aspect correction code. Should now be like how a real monitor - handles it. - - Fixed a bug in the xms status report code. (Blake Stone 1.0 shareware) - - Added a lot more keyboard layouts. - - Fix crash related to changing the scaler before a screen was created. - - Hopefully fixed compilation on *bsd. - - Enabled auto cpu core selection for recompiling core as well. - - Made the used joystick selectable when 4axis is specified. - - Added some hints for inexperienced DOS users to the shell. - -0.71 - - Add a new recompiling cpu core, which should be easier to port. - - Add 64 bit version of the recompiling core. - - Add mipsel 32 bit version of the recompiling core. - - Fix a few small problems with FCBs. (fixes Jewels of darkness and - cyrus chess) - - Raise some more exceptions. (fixes vbdos) - - Fix a few problems with the dynamic core. (fixes Inner Words, - Archmimedean Dynasty and others) - - Improve/Fix fallback code for certain graphics cards. - - Fix a few cd audio related bugs. - - Add an undocumented MSCDEX feature. (Fixes Ultimate Domain) - - Fix some pcspeaker mode. (fixes Test Drive and similar games) - - Improve dos keyinput handling. (fixes Wing Commander 3 exit dialog) - - Remove Exit condition on fully nested mode. (fixes some demo) - - Add image file size detection. - - Add/Fix some ansi codes. (fixes PC Larn and certain versions of - infocom games) - - Several general DOS fixes. (fixes nba95, hexit and various other games) - - Add some valid input checks. (fixes 3d body adventure and similar - games) - - Fix digital joystick centering problem. - - Reenable textmode 54 and 55. - - Fix a pelmask problem with univbe 5.0 lite. (fixes Panzer General) - - Fix minor mixer underflow. - - Some general image and bios disk emulation fixes. - - Hopefully fix compilation on BSD and darwin. - - Try using ioctl cdrom access by default if possible. - - Fix some svga detection routine. (fixes Grandest Fleet 2 and Bobby Fischer - Teaches Chess) - - You can now close DOSBox using the status window in win32. - - Add support for NX enabled systems. - - Fix a casting error which only showed with certain compilers. (fixes - various games under mac os x and 64 bit linux) - - Improve timer and add gate 2 support. (fixes various games and - joystick problems) - - Improve mouse. Add undocumented backdoor. (fixes Last half of Darkness, - PC-BLOX and others) - - Add/improve support for ~ and ~username in all commands. - - Fix a font problem with the pcjr/tandy. (fixes personal deskmate 2) - - Change dma routine a bit. (fixes ticks in sound in various games) - - Allow read-only diskimages to be booted. (fixes various booter - games) - - Add basic hidden file support on cdrom images. (fixes Player - Manager 2) - - Add some rarely used functionality to the int10 mode setup. (fixes - WW2 Battles of the South pacific) - - Add ability to force scaler usage. - - Speed up flag generation and make it more 386-like. - - Some colourful feedback in the mapper. - - General code cleanup. - -0.70 - - Improve register handling and support with XMS. - - Fix some issues with deleting open files.(windows only issue) - - Add dummy LPT1 class. (windows only issue) - - Improve some of the internal dos commands. (choice, copy and shift) - - Improve ROM area. (for games that use it for random numbers or - overwrite it as some sort of detection thing) - - Improve compatibility of dynamic core by making it handle certain - pagefaults earlier. - - Move internal dos tables around so we have more umb memory. - - Add some dos tables. - - Dynamic core supports io exceptions. - - Move some interrupt handlers to XT Bios locations. - - Add a dynamic fpu on x86. - - Improve fpu on non-x86. - - Trapflag gets strict priority over hardware IRQs. - - Trapflag support for the dynamic core. - - Add dummy TRx handling. - - Fix a few rarely used character functions. - - Improve auto cycle guessing code. - - Improve and extend the joystick support. - - Add autofire support. - - Improve the mapper so you can map keys to the joystick and vice versa. - - A few game specific video card fixes. - - Fix some 64 bit cpu bugs. - - Add support for certain cdrom detection schemes. - - Improve HSG/Red Book support. - - Improve MSCDEX. - - Improve dynamic core support under intel macs. - - Add basic support for clipper programs. - - Add support for different keyboard layouts. - - Add auto core guessing. - - Fix a few flags bugs. - - Fix a few small cpu bugs. - - Improve soundblaster detection rate by various programs. - - Improve EMS emulation. (allow mapping of non standard regions) - - Improve keyboard input codes on various OS-es. - - Fix problems with filenames having stackdata in them. - - Changed a few basic operations in DOSBox so they take emulated time. - - Improve dos ioctl functions. - - Extend cpu core so they are capable of detecting and raising a few - more exception types. - - Improve DOS functions when dealing with virtual drive. - - Improve FAT drives. - - Better handling of volume-labels in file functions. - - Image disk cycling capability. (prompt) - - Try to reduce the impact of using an analog joystick. - - Several measures to avoid code invalidation on certain types - of self modification in the dynamic core. - - Add dynamic core memory function inlining. - - A few small mouse improvements. (some games are using things they - shouldn't) - - Add nullmodem emulation.(h-a-l-9000) - - Some small cga and hercules fixes. - - Add more scalers (hq2x/hq3x/sai). (Kronuz) - - Change configuration file loading support. It now supports - multiple configuration files. - - Make dynamic core capable of running some win32s programs. - - Fix and add some rare soundblaster modes. (Srecko) - - Better soundblaster mixer controls. (Srecko) - - Make soundblaster installation under windows much easier. - - Add device control channel handling. - - GEMMIS support (ems under windows). - - Support more colours in win 3. (vasyl) - - Don't show unmounted drives in windows filemanager. - - Fix some bugs in the int13 handler. - - Simulate some side-effects of bios interrupt handlers on flags. - - Add IPX functions needed by netbios. - - Make ports take emulated time. - - Tabcompletion is now aware of the CD command. - - Add suppport for the dac pel mask. - - Fixes to hercules emulation, better detection and bank switching. - - Fixes to tandy emulation, 640x200x16 mode and different sizes bank. - - EGA/VGA memory changes detection for faster rendering. - - Gus 16 bit fixes. - - Many timer improvements. - - Some pcjr fixes. - - Some booter fixes. - - Many small fixes. - -0.65 - - Fixed FAT writing. - - Added some more missing DOS functions. - - Improved PIC so that it actually honours irq 2/9. - - Improved intelligent MPU-401 mode so that more games work with it. - - Some mouse fixes. - - Changed DMA transfers a bit so they bypass the paging tables. - - Added S3 XGA functionality. - - Improved paging so that read and write faults are handled differently. - - Rewrote exception handling a bit (no exception 0x0B with dos4gw anymore). - - Added IO exceptions in all but the dynamic core. - - Some ems improvements. - - Added midi-device selection code for the windows hosts. - - Fix crashes/segfaults related to the disabling of the pcspeaker. - - Added some more FILES=XX detection tricks. - - Fixed some vga detection schemes. - - Fixed screenshot corruption when using -noconsole in a read-only directory. - - Fix wrong scaled screenshots. - - Added some hidden file functions when using diskimages. (helps with cdrom - detection schemes) - - Fixed a bug in the mixer code, that muted the music in certain games. - - Added an assembly fpu core. - - Made the shell more flexible for batch files. - - Check for unaligned memory acces fixes hangups on ARM processors. - - Some 64 bit fixes. - - Added code to change configuration at runtime. - - Improved ADPCM emulation. - - Fixed a few cpu instructions. - - Always report vesa 2.0 and fix some colour issues with vesa games. - - Fix video mode 0x06 and 0x0a. - - Improvements to the joystick emulation. 4 buttons are supported as well. - - Add VCPI emulation for Origin games. - - Fixed a lot of things in the boot code. Most booters work now. - - Lots of improvements to the IPX emulation. - - Rewritten modem emulation. Should work with more games. - - Improvements to the dos memory managment routines. - - Add UMB (upper memory blocks) support. - - Emulate the pause key. - - Improve Composite CGA mode emulation. - - Lots of vga compatibility changes. - - Improved support for chained video modes. - - Improved mode and palette handling in cga modes. - - Mount accepts ~ now. - - Added a few of the EGA RIL functions. - - Added TandyDAC emulation. - - OS/2 support. - - Improved and speed up the dynamic cpu core. - - Fix some errors in the CD-ROM emulation layer. - - Added an automatic work-around for some graphics chipsets. - - Add PCjr support. - - Allow mousedriver to be replaced. Fixes a few games that come with their - own (internal) driver. - - Improved dynamic cpu core so it can handle pagefaults and some obscure - types of self-modifying code. - - Added -noautoexec switch to skip the contents of [autoexec] in the - configuration file. - - Improved v86 mode emulation (mainly for Strike Commander). - - Improved timer behavior. - - Improved extended keyboard support. - - Enhanced and added several DOS tables. - - Made core_full endian safe. - - Made pagefaults endian safe. - - Add support for moviecapturing - - Add support for 15/16/32 bit videomodes. - - Add some more VESA modi (4 bit). - - Add 1024x768 output. - - Changed screenrendering so it only draws changes to the screen. - - Allow remapping of the EMS page when the dma transfer was started from - the page frame - - Made EMS and DMA work together when playing from a mapped memory page. - - Renamed several configuration options, so that they are unique. - - Merged mpu and intelligent into one option. - - Merged fullfixed and fullresolution. - - Extended keys should be handled better. - - F11 and F12 work. - - Compilation fixes for various platforms. - - Fix a few crashes when giving bad input. - - Removed interp2x and added few new scalers. - - Reintroduce the lockfree mouse. (autolock=false) - - Add a larger cache for the dynamic cpu core. - - Improved soundblaster DSP, so it gets detected by creative tools. - - Lots of bugfixes. - - Even more bugfixes. - -0.63 - - Fixed crash with keymapper (ctrl-f1) and output=surface. - - Added unmounting. - - Fixed multiple issues with drive labels. - - Fixed most if not all FILES=XX problems. - - Added redirection in the shell. - - Fixed crashes with subst. - - Fixed multiple crashes with the drive images support. - - Added a missing fpu instruction. - - Fixed some cpu and fpu instructions. - - Fixed a small bug related to font loading. - - Rewrote the devices support. - - Added capslock/numlock checks on startup. - - Fixed wave writing. - - A few internal DOS fixes. - - Timer fixes for the hybrid loader. - - Some small soundblaster fixes. - - The drive cache can now be cleared by a keycombo. (CTRL-F4) - - A few keyboard fixes. - - Compilation fixes on various platforms. - - Quite some debugger improvements. - - Fixed dir only showing files after the first run on cdrom drives. - - Added some cdrom detection checks. - - Enabled insert in the shell. (Easier editing of commands) - - Changed order in which executables appear with tab-completion. - - Fixed some issues with raw opl recording and using a slightly different - format - -0.62 - - Added blinking support in the shell and some color fixes. - - Fixed commandline parsing when .bat files involved (fixes -exit) - - Fixed issues with tabs in commandline not being processed correctly. - - Cleaned/improved shutdown sequence. - - Added some more bios functions (wait and delay functions). - - Made our XMS driver conform the specs better. (c2woody) - - Added support for some more ems functions. - - Added intelligent mpu401 emulation. (Srecko) - - Added soundblaster 16 emulation. - - Rewrote GUS emulation to sound more authentic. - - Improved pc speaker emulation. - - Added an internal (programmable) mixer. - - Added support a few soundblaster/adlib detection routines. - - Fixed lot's of bugs related to DMA transfers. - - Added interpolating prebuffering mixer routines. - - Added recording of OPL commands and raw midi. - - Fixed some bugs with the wave recording. - - Changed sensitivity settings of the mouse. - - Added ps2 mouse-emulation in bios interrupts (c2woody). - - Fixed some bugs with mouse emulation limits. - - Fixed a bug with an unterminated string in the drivelabel. - - Changed file search routines a bit to be more compatible. - - Added support for attribute-searching with fcb's. - - Added basic SDA. - - Added TPA and DIB. - - Added Lot's of missing dos tables (c2woody). - - Changed psp and dta functions to use dta. - - Returned filename in ds:dx in create-random-file (c2woody). - - Fixed a bug with date and time used on open files. - - Some mscdex fixes. - - Added the -version switch, which makes dosbox report its version. - - Added a keymapper. - - Added basic IPX emulation. - - Added cdrom iso support and floppy images support. - - Added the possibity to boot another dos version. - - Added Serial passthrough support (win32 only). - - Added the possibility to pause dosbox. - - Changed OpenGL so that it is initialized only when used. - - Make dosbox run at higher priority when active and lower when inactive. - - Added direct draw output support (win32 only). - - Added current running program to title bar. - - Rewrote video emulation to support new scalers. - - Added new graphics scalers like advmame3x,tv2x. - - Added a support for a few anti-debugger tricks. - - Improved the handling of the tab-key. - - Improved support for the numeric keyboard. - - Fixed a few cpu opcodes. - - Added cpu core simple (for lowerend machines) - - Fixed some nasty bugs in the dynamic cpu core. - - Added a few (rarely used) fpu opcodes. - - Fixed various issues with GCC 3.4. - - Many internal timer improvements (PIT and PIC). - - Added some more PIC commands (c2woody). - - Added BCD counting to the timers. - - Fix some vesa functions. - - Add some basic support for 132x25 and 132x45 textmodes. - - Improved Tandy emulation a lot. - - Lowered cpu usage when dosbox is idle. - - Allow virtualisation of some basic IO-ports (c2woody). - - -0.61 - - Added a beta dynamic cpu for x86 hosts (very unstable) - - Added opengl and hardware overlay display output - - Rewrote the vga screen updates to go in lines - - Added paging and v86 support to cpu emulation - - Added a config option to simulate a certain type of machine - - Added hercules graphics emulation - - Made CGA/TANDY modes more compatible - - Updated textmode drawing routines to support blinking colors - - Fixed VESA set page function that was documented wrong - - Fixed some wrongly emulated cpu opcodes. - - improved exception handling - - debugger: fixes; logging of gdt,lgt,idt, new commands(Fizzban) - - fixed some mscdex issues (drive letter header error, added get directory entry) - - added/fixed some bios funcs - - added some rarely used xms functions (thanks c2woody!) - - implemented GUS emulation - - Added 16-bit DMA support (for GUS and eventually SB16) - - Fixed many small bugs in filehandling routines - - Many small FPU fixes (c2woody/Fizzban) - - Some keyboard improvements (pharlab games) - - Some Timer and cmos/rtc fixes (Mirek/Srecko/Others) - - Lot's of mouse fixes (Help from various people) - - Enabled internal modem - - Made the DOS parsing routines a bit more flexible - - Added Subst (Srecko) - - Added cdrom ioctl support for linux (prompt) - - Many internal DOS fixes: memory/files/datastructures. - - Got some help from c2woody in allowing more than 1 irq being served - - Disabled DPMI (not needed anymore. DOSBox handles almost every extender) - - Search configfile in $HOME directory if none present in current directory - - Added another way to switch to protected mode. (Thanks Morten Eriksen!) - - Fixed some odd badly documented behaviour with PSP/DTA - - Added some warnings on opening of readonly files in writemode(DOS default). - - Many shell enhanchements - - Fixed a win32 specific bug dealing with filenames starting with a "." - - Fixed some bugs with the directory structure: not found/can't save errors - -0.60 - - rewrote memory system for future paging support - - fixed several EMS and XMS bugs and rewrite for new memory system - - added some support for tandy video modes - - added MAME Tandy 3 voice emulation - - added MAME CMS/GameBlaster emulation - - added serial port emulation with virtual tcp/ip modem (somewhat buggy) - - sound blaster emulation is now sb pro 2.0 compatible - - added basic support for 32-bit protected mode - - VGA now tries to emulate an S3 Trio 64 card with 2 MB - - VESA 2.0 support for some 256 color modes - - rewrote large piece of video bios code for better compatibility - - added support for the not inheritance flags. - - created functions for creating child psp. - - updated errorcodes of findfirst (thanks Mirek!) - - rewrote loggingsystem to generate less warnings - - added dos protected mode interface (dpmi) - - added cdrom label support - - improved cdrom audio playing - - fixed and improved directory cache - - debugger shows selector- and cpu mode info - - added SELINFO (selector information) command to debugger - - added reference counting for dos files - - added tab-completion - - added basic fpu support. - - fixed several bugs with case sensitive filesystems. - - added more shell commands and improved their behaviour. - - mouse improvements. - - real time clock improvements. - - DMA fixes. - - Improved .BAT file support. - -0.58 - - fixed date and time issues with fcbs - - added more commands to the internal Shell - - corrected config system when a old configfile was used - - fixed cga put and get pixel - - fixed some vga register getting reset to wrong values - - improved support for foreign keyboards - - improved joystick support - - made dosbox multithreaded again - - lot's of soundblaster fixes - - dma fixes - - cdrom support - - midi support - - added scale2x - - reenabled screenshot support - - joystick support fixes - - mouse improvements - - support for writing wavefiles - - added directory cache and longfilename support (longfilenames will be mangled) - - mouse fixes - - date and time updates at z:\ - - added (partial) direct disk support. (works probably only if directory is mounted under a:\) - - added support for env variables. (must be set before starting dosbox: DOSBOX_SECTION_PROPERTY=value - like DOSBOX_SBLASTER_IRQ=1) -0.57 - - added support for command /C - - fixed all fcb-write functions - - fixed fcb-parseline - - added debugger under linux/freebsd - - added debugger memory breakpoints and autolog function (heavy debug) - - added loadfix.com program that eats up memory (default 64kb) - Usage : loadfix [-option] [programname] [parameters]... - Example: loadfix mm2 (Allocates 64kb and starts executable mm2) - loadfix -32 mm2 (Allocates 32kb and starts executable mm2) - loadfix -128 (Allocates 128kb) - loadfix -f (frees all previous allocated memory) - - added echoing of characters for input function - - added support for backspace for input function - - added partial support for int10:01 set cursortype - - fixed most of the problems/bugs with character input. - - fixed allocationinfo call.(darksun series) - - improved dos support for non-existant functions - - Split screen support - - prefix 66 67 support - - rewrote timingscheme so 1000 hz timers don't cause problems anymore - - update adlib emulation - - fixed some isues with the mouse (double clicks and visible when it shouldn't be) - - improved mouse behaviour (mickey/pixel rate) and detection routines. - - basic ansi.sys support - - Disney sound system emulation - - rewrote upcase/lowcase functions so they work fine with gcc3.2 - - SHELL: added rename and delete - - added support for command /C. Fixed crashes in the shell - - fixed various bugs when exiting dosbox - - fixed a bug in XMS - - fixed a bug with the joystick when pressing a button - - create nicer configfiles. - - bios_disk function improved. - - trapflag support - - improved vertical retrace timing. - - PIT Timer improvements and many bug fixes - - Many many bug fixes to the DOS subsystem - - Support for memory allocation strategy - - rewrote cpu mainloop to act more like a real cpu - -0.56 - - added support for a configclass/configfile - - added support for writing out the configclass into a configfile - - removed the language file and made it internal - - added support for writing the language file (will override the internal one) - - improved mousesupport - - updated readme - - support for screenshots - - some cpu-bug fixes - - dma changes - - Real Sound support - - EMM fixes and new functions. - - VGA fixes - - new wildcompare - - support for size and disktype at mount. - - added new debugger functionalities: start/trace into INTs, write processor status log, - step over rep and loop instructions, breakpoint support without using INT 03 (heavy debugging switch) - - Added more cpu instructions and changed the string operations. - - Added classes for most of the internal dos structures. - - Rewrote most of the fcb calls to use normal dos calls. - -0.55 - - fixed the errors/warnings in prefix_66.h and prefix_66_of.h (decimal too large becomming unsigned). - - fixed compilation error on FreeBSD when #disable_joystick was defined - - int10_writechar has been updated to move the cursor position. - - changed the basedir routines to use the current working dir instead of argv[0]. This will fix and brake things :) - - illegal command, now displays the command - - wildcmp updated to be case insensitive - - added fcb:open,close,findfirst, findnext. - - fixed rename in drive_local - - added new features to the debugger: breakpoint support / data view / command line - - partial support of list of lists (dos info block) - - full emm 3.2 support - - partial emm 4.0 support - - fixes to graphics core fonts (text in sierra games is now correct) - - improved support for user mousehandlers - - fixed EGA graphics - - fixed VGA graphics - - fixed write with size 0 - - changed memory management. - - fixed and cleaned up the cpu flags. - - changed interrupt handler. - - speeded up the graphics. - - speeded up the cpu-core - - changed dma - - improved dma streams from emm memory - - added some cga videomodes - - added more funtions to the keyboard handler + - fixed the errors/warnings in prefix_66.h and prefix_66_of.h (decimal too large becomming unsigned). + + diff --git a/INSTALL b/INSTALL index a555fa1..ad94ba9 100644 --- a/INSTALL +++ b/INSTALL @@ -1,97 +1,36 @@ -Things needed for compilation. - -SDL - The Simple DirectMedia Library available at http://www.libsdl.org - The dll distributed with the windows version of DOSBox is slightly - modified. You can find the changes in the sourcepackage of DOSBox - (src/platform/sdl-win32.diff). If you want the patched sourcetree - send us an email. (see README) - Licensed under LGPL - -Curses (optional) - If you want to enable the debugger you need a curses library. - ncurses should be installed on just about every unix distro. - For win32 get pdcurses at http://pdcurses.sourceforge.net - License: Open source - -Libpng (optional) - Needed for the screenshots. - For win32 get libpng from http://gnuwin32.sourceforge.net/packages.html - See http://www.libpng.org/pub/png/ for more details. - License: Open Source - -Zlib (optional) - Needed by libpng. - For win32 get libz (rename to zlib) from http://gnuwin32.sourceforge.net/packages.html - See http://www.zlib.net for more details. - License: Open Source - -SDL_Net (optional) - For modem/ipx support. Get it from http://www.libsdl.org/projects/SDL_net/ - Licensed under LGPL - -SDL_Sound - For compressed audio on diskimages. (optional) - This is for cue/bin cdrom images with compressed (mp3/ogg) audio tracks. - Get it from http://icculus.org/SDL_sound - Licenced under LGPL - -ALSA_Headers - (optional) - for Alsa support under linux. Part of the linux kernel sources - Licensed under LGPL - -If you want compile from the CVS under a unix system, you'll also need -automake (>=1.6), autoconf(>=2.50). Should be available at http://www.gnu.org - -For building on unix systems. -If you are building from the cvs run ./autogen.sh first before doing the following. - -1. ./configure -2. make - -In step 1 you could add the following switches: ---enable-debug - enables the internal debugger. --enable-debug=heavy enables even more - debug options. Dosbox should then be run from a xterm and when the sdl- - window is active press alt-pause to enter the debugger. - ---enable-core-inline - enables some memory increasing inlines. This greatly increases - compiletime for maybe a increase in speed. - ---disable-fpu - disables the emulated fpu. Although the fpu emulation code isn't - finished and isn't entirely accurate it's advised to leave it on. - ---disable-fpu-x86 - disables the assembly fpu core. Although relatively new the x86 fpu - core has more accuracy then the regular fpu core. - ---disable-dynamic-x86 - disables the dynamic x86 specific cpu core. Although it might be - be a bit unstable, it can greatly improve the speed of dosbox on x86 - hosts. - Please note that this option on x86 will result in a different - dynamic/recompiling cpu core being compiled then the default. - For more information see the option --disable-dynrec - ---disable-dynrec - disables the recompiling cpu core. Currently x86 and x86_64 only. - You can activate this core on x86 by disabling the dynamic-x86 core. - ---disable-dynamic-core - disables all dynamic cores. (same effect as - --disable-dynamic-x86 --disable-dynrec) - ---disable-unaligned-memory - disables unaligned memory access. - -Check the src subdir for the binary. - -NOTE: If capslock and numlock appear to be broken. open -src/ints/bios_keyboard.cpp and go to line 30 and read there how to fix it. - - -Build instructions for VC++6 -Don't use VC++ 6:it creates faulty code in core_normal.cpp +First of all if you are running a non-x86 machine this will not work, +code only works for big-endian machines for now :) + +Things needed for compilation. + +SDL + The Simple DirectMedia Library available at http://www.libsdl.org + +Curses + If you want to enable the debugger you need a curses library. + ncurses should be installed on just about every unix distro. + For win32 get pdcurses at http://pdcurses.sourceforge.net + +If you want compile from the CVS under a unix system, you'll also need +automake, autoconf. Should be available at http://www.gnu.org + +For building on unix systems. +If you are building from the cvs run ./autogen.sh first before doing the following. + +1. ./configure +2. Check settings.h for some setup options. +3. make + +Check the src subdir for the binary and dosbox.lang file. +These 2 files should be in the same dir if you want to run dosbox. + +Compiling on FreeBSD might be a problem since SDL has no joystick support there. +To get around this edit sdlmain.cpp to enable some #define. +Let's hope someday the sdl people will just report 0 joysticks in freebsd or get it working some other way :) + + +Build instructions for VC++6 + +Open the workspace in the visualc subdir and build from there. +Copy the src/dosbox.lang file to the same dir as your executable. + diff --git a/Makefile.am b/Makefile.am index 1ace83b..2a94591 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,7 @@ -# Main Makefile for DOSBox - -EXTRA_DIST = autogen.sh -SUBDIRS = src include docs visualc_net +# Main Makefile for DOSBox + +EXTRA_DIST = settings.h autogen.sh +SUBDIRS = src include visualc + + + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..b780a8c --- /dev/null +++ b/Makefile.in @@ -0,0 +1,428 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Main Makefile for DOSBox +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +EXTRA_DIST = settings.h autogen.sh +SUBDIRS = src include visualc +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ + Makefile.in NEWS THANKS acinclude.m4 aclocal.m4 config.guess \ + config.h.in config.sub configure configure.in depcomp \ + install-sh missing mkinstalldirs +DIST_SUBDIRS = $(SUBDIRS) +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe) + +$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +$(ACLOCAL_M4): configure.in acinclude.m4 + cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h + +$(srcdir)/config.h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOHEADER) + touch $(srcdir)/config.h.in + +distclean-hdr: + -rm -f config.h +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = . +distdir = $(PACKAGE)-$(VERSION) + +am__remove_distdir = \ + { test ! -d $(distdir) \ + || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr $(distdir); }; } + +GZIP_ENV = --best +distcleancheck_listfiles = find . -type f -print + +distdir: $(DISTFILES) + @if sed 15q $(srcdir)/NEWS | fgrep -e "$(VERSION)" >/dev/null; \ + then :; else \ + echo "NEWS not updated; not releasing" 1>&2; \ + exit 1; \ + fi + $(am__remove_distdir) + mkdir $(distdir) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done + -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r $(distdir) +dist-gzip: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist dist-all: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + $(am__remove_distdir) + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + chmod a-w $(distdir) + dc_install_base=`$(am__cd) $(distdir)/=inst && pwd` \ + && cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && (test `find $$dc_install_base -type f -print | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + find $$dc_install_base -type f -print ; \ + exit 1; } >&2 ) \ + && $(MAKE) $(AM_MAKEFLAGS) dist-gzip \ + && rm -f $(distdir).tar.gz \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck + $(am__remove_distdir) + @echo "$(distdir).tar.gz is ready for distribution" | \ + sed 'h;s/./=/g;p;x;p;x' +distcleancheck: distclean + if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f config.status config.cache config.log +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-recursive dist dist-all dist-gzip distcheck \ + distclean distclean-generic distclean-hdr distclean-recursive \ + distclean-tags distcleancheck distdir dvi dvi-am dvi-recursive \ + info info-am info-recursive install install-am install-data \ + install-data-am install-data-recursive install-exec \ + install-exec-am install-exec-recursive install-info \ + install-info-am install-info-recursive install-man \ + install-recursive install-strip installcheck installcheck-am \ + installdirs installdirs-am installdirs-recursive \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-recursive tags tags-recursive uninstall \ + uninstall-am uninstall-info-am uninstall-info-recursive \ + uninstall-recursive + +# 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/NEWS b/NEWS index 41c520e..ba304e2 100644 --- a/NEWS +++ b/NEWS @@ -1,530 +1,23 @@ -0.72 - - Fixed unitialized variable in joystick. (Fixes crashes on Vista and - Mac OS X) - - Some bugfixes and speedups to the 64 bit recompiling core. - - Fixed sign flag on soundblaster dma transfers (Space Quest 6 intro) - - Fixed a bug in keyboard layout processing code and fixed certain - layouts. - - Fixed Dreamweb. - - Improved speed unlocking when running cycles=max. - - Fixed a crash related to the tab completion in the shell. - - Improved aspect correction code. Should now be like how a real monitor - handles it. - - Fixed a bug in the xms status report code. (Blake Stone 1.0 shareware) - - Added a lot more keyboard layouts. - - Fix crash related to changing the scaler before a screen was created. - - Hopefully fixed compilation on *bsd. - - Enabled auto cpu core selection for recompiling core as well. - - Made the used joystick selectable when 4axis is specified. - - Added some hints for inexperienced DOS users to the shell. - -0.71 - - Add a new recompiling cpu core, which should be easier to port. - - Add 64 bit version of the recompiling core. - - Add mipsel 32 bit version of the recompiling core. - - Fix a few small problems with FCBs. (fixes Jewels of darkness and - cyrus chess) - - Raise some more exceptions. (fixes vbdos) - - Fix a few problems with the dynamic core. (fixes Inner Words, - Archmimedean Dynasty and others) - - Improve/Fix fallback code for certain graphics cards. - - Fix a few cd audio related bugs. - - Add an undocumented MSCDEX feature. (Fixes Ultimate Domain) - - Fix some pcspeaker mode. (fixes Test Drive and similar games) - - Improve dos keyinput handling. (fixes Wing Commander 3 exit dialog) - - Remove Exit condition on fully nested mode. (fixes some demo) - - Add image file size detection. - - Add/Fix some ansi codes. (fixes PC Larn and certain versions of - infocom games) - - Several general DOS fixes. (fixes nba95, hexit and various other games) - - Add some valid input checks. (fixes 3d body adventure and similar - games) - - Fix digital joystick centering problem. - - Reenable textmode 54 and 55. - - Fix a pelmask problem with univbe 5.0 lite. (fixes Panzer General) - - Fix minor mixer underflow. - - Some general image and bios disk emulation fixes. - - Hopefully fix compilation on BSD and darwin. - - Try using ioctl cdrom access by default if possible. - - Fix some svga detection routine. (fixes Grandest Fleet 2 and Bobby Fischer - Teaches Chess) - - You can now close DOSBox using the status window in win32. - - Add support for NX enabled systems. - - Fix a casting error which only showed with certain compilers. (fixes - various games under mac os x and 64 bit linux) - - Improve timer and add gate 2 support. (fixes various games and - joystick problems) - - Improve mouse. Add undocumented backdoor. (fixes Last half of Darkness, - PC-BLOX and others) - - Add/improve support for ~ and ~username in all commands. - - Fix a font problem with the pcjr/tandy. (fixes personal deskmate 2) - - Change dma routine a bit. (fixes ticks in sound in various games) - - Allow read-only diskimages to be booted. (fixes various booter - games) - - Add basic hidden file support on cdrom images. (fixes Player - Manager 2) - - Add some rarely used functionality to the int10 mode setup. (fixes - WW2 Battles of the South pacific) - - Add ability to force scaler usage. - - Speed up flag generation and make it more 386-like. - - Some colourful feedback in the mapper. - - General code cleanup. - -0.70 - - Improve register handling and support with XMS. - - Fix some issues with deleting open files.(windows only issue) - - Add dummy LPT1 class. (windows only issue) - - Improve some of the internal dos commands. (choice, copy and shift) - - Improve ROM area. (for games that use it for random numbers or - overwrite it as some sort of detection thing) - - Improve compatibility of dynamic core by making it handle certain - pagefaults earlier. - - Move internal dos tables around so we have more umb memory. - - Add some dos tables. - - Dynamic core supports io exceptions. - - Move some interrupt handlers to XT Bios locations. - - Add a dynamic fpu on x86. - - Improve fpu on non-x86. - - Trapflag gets strict priority over hardware IRQs. - - Trapflag support for the dynamic core. - - Add dummy TRx handling. - - Fix a few rarely used character functions. - - Improve auto cycle guessing code. - - Improve and extend the joystick support. - - Add autofire support. - - Improve the mapper so you can map keys to the joystick and vice versa. - - A few game specific video card fixes. - - Fix some 64 bit cpu bugs. - - Add support for certain cdrom detection schemes. - - Improve HSG/Red Book support. - - Improve MSCDEX. - - Improve dynamic core support under intel macs. - - Add basic support for clipper programs. - - Add support for different keyboard layouts. - - Add auto core guessing. - - Fix a few flags bugs. - - Fix a few small cpu bugs. - - Improve soundblaster detection rate by various programs. - - Improve EMS emulation. (allow mapping of non standard regions) - - Improve keyboard input codes on various OS-es. - - Fix problems with filenames having stackdata in them. - - Changed a few basic operations in DOSBox so they take emulated time. - - Improve dos ioctl functions. - - Extend cpu core so they are capable of detecting and raising a few - more exception types. - - Improve DOS functions when dealing with virtual drive. - - Improve FAT drives. - - Better handling of volume-labels in file functions. - - Image disk cycling capability. (prompt) - - Try to reduce the impact of using an analog joystick. - - Several measures to avoid code invalidation on certain types - of self modification in the dynamic core. - - Add dynamic core memory function inlining. - - A few small mouse improvements. (some games are using things they - shouldn't) - - Add nullmodem emulation.(h-a-l-9000) - - Some small cga and hercules fixes. - - Add more scalers (hq2x/hq3x/sai). (Kronuz) - - Change configuration file loading support. It now supports - multiple configuration files. - - Make dynamic core capable of running some win32s programs. - - Fix and add some rare soundblaster modes. (Srecko) - - Better soundblaster mixer controls. (Srecko) - - Make soundblaster installation under windows much easier. - - Add device control channel handling. - - GEMMIS support (ems under windows). - - Support more colours in win 3. (vasyl) - - Don't show unmounted drives in windows filemanager. - - Fix some bugs in the int13 handler. - - Simulate some side-effects of bios interrupt handlers on flags. - - Add IPX functions needed by netbios. - - Make ports take emulated time. - - Tabcompletion is now aware of the CD command. - - Add suppport for the dac pel mask. - - Fixes to hercules emulation, better detection and bank switching. - - Fixes to tandy emulation, 640x200x16 mode and different sizes bank. - - EGA/VGA memory changes detection for faster rendering. - - Gus 16 bit fixes. - - Many timer improvements. - - Some pcjr fixes. - - Some booter fixes. - - Many small fixes. - -0.65 - - Fixed FAT writing. - - Added some more missing DOS functions. - - Improved PIC so that it actually honours irq 2/9. - - Improved intelligent MPU-401 mode so that more games work with it. - - Some mouse fixes. - - Changed DMA transfers a bit so they bypass the paging tables. - - Added S3 XGA functionality. - - Improved paging so that read and write faults are handled differently. - - Rewrote exception handling a bit (no exception 0x0B with dos4gw anymore). - - Added IO exceptions in all but the dynamic core. - - Some ems improvements. - - Added midi-device selection code for the windows hosts. - - Fix crashes/segfaults related to the disabling of the pcspeaker. - - Added some more FILES=XX detection tricks. - - Fixed some vga detection schemes. - - Fixed screenshot corruption when using -noconsole in a read-only directory. - - Fix wrong scaled screenshots. - - Added some hidden file functions when using diskimages. (helps with cdrom - detection schemes) - - Fixed a bug in the mixer code, that muted the music in certain games. - - Added an assembly fpu core. - - Made the shell more flexible for batch files. - - Check for unaligned memory acces fixes hangups on ARM processors. - - Some 64 bit fixes. - - Added code to change configuration at runtime. - - Improved ADPCM emulation. - - Fixed a few cpu instructions. - - Always report vesa 2.0 and fix some colour issues with vesa games. - - Fix video mode 0x06 and 0x0a. - - Improvements to the joystick emulation. 4 buttons are supported as well. - - Add VCPI emulation for Origin games. - - Fixed a lot of things in the boot code. Most booters work now. - - Lots of improvements to the IPX emulation. - - Rewritten modem emulation. Should work with more games. - - Improvements to the dos memory managment routines. - - Add UMB (upper memory blocks) support. - - Emulate the pause key. - - Improve Composite CGA mode emulation. - - Lots of vga compatibility changes. - - Improved support for chained video modes. - - Improved mode and palette handling in cga modes. - - Mount accepts ~ now. - - Added a few of the EGA RIL functions. - - Added TandyDAC emulation. - - OS/2 support. - - Improved and speed up the dynamic cpu core. - - Fix some errors in the CD-ROM emulation layer. - - Added an automatic work-around for some graphics chipsets. - - Add PCjr support. - - Allow mousedriver to be replaced. Fixes a few games that come with their - own (internal) driver. - - Improved dynamic cpu core so it can handle pagefaults and some obscure - types of self-modifying code. - - Added -noautoexec switch to skip the contents of [autoexec] in the - configuration file. - - Improved v86 mode emulation (mainly for Strike Commander). - - Improved timer behavior. - - Improved extended keyboard support. - - Enhanced and added several DOS tables. - - Made core_full endian safe. - - Made pagefaults endian safe. - - Add support for moviecapturing - - Add support for 15/16/32 bit videomodes. - - Add some more VESA modi (4 bit). - - Add 1024x768 output. - - Changed screenrendering so it only draws changes to the screen. - - Allow remapping of the EMS page when the dma transfer was started from - the page frame - - Made EMS and DMA work together when playing from a mapped memory page. - - Renamed several configuration options, so that they are unique. - - Merged mpu and intelligent into one option. - - Merged fullfixed and fullresolution. - - Extended keys should be handled better. - - F11 and F12 work. - - Compilation fixes for various platforms. - - Fix a few crashes when giving bad input. - - Removed interp2x and added few new scalers. - - Reintroduce the lockfree mouse. (autolock=false) - - Add a larger cache for the dynamic cpu core. - - Improved soundblaster DSP, so it gets detected by creative tools. - - Lots of bugfixes. - - Even more bugfixes. - -0.63 - - Fixed crash with keymapper (ctrl-f1) and output=surface. - - Added unmounting. - - Fixed multiple issues with drive labels. - - Fixed most if not all FILES=XX problems. - - Added redirection in the shell. - - Fixed crashes with subst. - - Fixed multiple crashes with the drive images support. - - Added a missing fpu instruction. - - Fixed some cpu and fpu instructions. - - Fixed a small bug related to font loading. - - Rewrote the devices support. - - Added capslock/numlock checks on startup. - - Fixed wave writing. - - A few internal DOS fixes. - - Timer fixes for the hybrid loader. - - Some small soundblaster fixes. - - The drive cache can now be cleared by a keycombo. (CTRL-F4) - - A few keyboard fixes. - - Compilation fixes on various platforms. - - Quite some debugger improvements. - - Fixed dir only showing files after the first run on cdrom drives. - - Added some cdrom detection checks. - - Enabled insert in the shell. (Easier editing of commands) - - Changed order in which executables appear with tab-completion. - - Fixed some issues with raw opl recording and using a slightly different - format - -0.62 - - Added blinking support in the shell and some color fixes. - - Fixed commandline parsing when .bat files involved (fixes -exit) - - Fixed issues with tabs in commandline not being processed correctly. - - Cleaned/improved shutdown sequence. - - Added some more bios functions (wait and delay functions). - - Made our XMS driver conform the specs better. (c2woody) - - Added support for some more ems functions. - - Added intelligent mpu401 emulation. (Srecko) - - Added soundblaster 16 emulation. - - Rewrote GUS emulation to sound more authentic. - - Improved pc speaker emulation. - - Added an internal (programmable) mixer. - - Added support a few soundblaster/adlib detection routines. - - Fixed lot's of bugs related to DMA transfers. - - Added interpolating prebuffering mixer routines. - - Added recording of OPL commands and raw midi. - - Fixed some bugs with the wave recording. - - Changed sensitivity settings of the mouse. - - Added ps2 mouse-emulation in bios interrupts (c2woody). - - Fixed some bugs with mouse emulation limits. - - Fixed a bug with an unterminated string in the drivelabel. - - Changed file search routines a bit to be more compatible. - - Added support for attribute-searching with fcb's. - - Added basic SDA. - - Added TPA and DIB. - - Added Lot's of missing dos tables (c2woody). - - Changed psp and dta functions to use dta. - - Returned filename in ds:dx in create-random-file (c2woody). - - Fixed a bug with date and time used on open files. - - Some mscdex fixes. - - Added the -version switch, which makes dosbox report its version. - - Added a keymapper. - - Added basic IPX emulation. - - Added cdrom iso support and floppy images support. - - Added the possibity to boot another dos version. - - Added Serial passthrough support (win32 only). - - Added the possibility to pause dosbox. - - Changed OpenGL so that it is initialized only when used. - - Make dosbox run at higher priority when active and lower when inactive. - - Added direct draw output support (win32 only). - - Added current running program to title bar. - - Rewrote video emulation to support new scalers. - - Added new graphics scalers like advmame3x,tv2x. - - Added a support for a few anti-debugger tricks. - - Improved the handling of the tab-key. - - Improved support for the numeric keyboard. - - Fixed a few cpu opcodes. - - Added cpu core simple (for lowerend machines) - - Fixed some nasty bugs in the dynamic cpu core. - - Added a few (rarely used) fpu opcodes. - - Fixed various issues with GCC 3.4. - - Many internal timer improvements (PIT and PIC). - - Added some more PIC commands (c2woody). - - Added BCD counting to the timers. - - Fix some vesa functions. - - Add some basic support for 132x25 and 132x45 textmodes. - - Improved Tandy emulation a lot. - - Lowered cpu usage when dosbox is idle. - - Allow virtualisation of some basic IO-ports (c2woody). - -0.61 - - Added a beta dynamic cpu for x86 hosts (very unstable) - - Added opengl and hardware overlay display output - - Rewrote the vga screen updates to go in lines - - Added paging and v86 support to cpu emulation - - Added a config option to simulate a certain type of machine - - Added hercules graphics emulation - - Made CGA/TANDY modes more compatible - - Updated textmode drawing routines to support blinking colors - - Fixed VESA set page function that was documented wrong - - Fixed some wrongly emulated cpu opcodes. - - improved exception handling - - debugger: fixes; logging of gdt,lgt,idt, new commands(Fizzban) - - fixed some mscdex issues (drive letter header error, added get directory entry) - - added/fixed some bios funcs - - added some rarely used xms functions (thanks c2woody!) - - implemented GUS emulation - - Added 16-bit DMA support (for GUS and eventually SB16) - - Fixed many small bugs in filehandling routines - - Many small FPU fixes (c2woody/Fizzban) - - Some keyboard improvements (pharlab games) - - Some Timer and cmos/rtc fixes (Mirek/Srecko/Others) - - Lot's of mouse fixes (Help from various people) - - Enabled internal modem - - Made the DOS parsing routines a bit more flexible - - Added Subst (Srecko) - - Added cdrom ioctl support for linux (prompt) - - Many internal DOS fixes: memory/files/datastructures. - - Got some help from c2woody in allowing more than 1 irq being served - - Disabled DPMI (not needed anymore. DOSBox handles almost every extender) - - Search configfile in $HOME directory if none present in current directory - - Added another way to switch to protected mode. (Thanks Morten Eriksen!) - - Fixed some odd badly documented behaviour with PSP/DTA - - Added some warnings on opening of readonly files in writemode(DOS default). - - Many shell enhanchements - - Fixed a win32 specific bug dealing with filenames starting with a "." - - Fixed some bugs with the directory structure: not found/can't save errors - -0.60 - - rewrote memory system for future paging support - - fixed several EMS and XMS bugs and rewrite for new memory system - - added some support for tandy video modes - - added MAME Tandy 3 voice emulation - - added MAME CMS/GameBlaster emulation - - added serial port emulation with virtual tcp/ip modem (somewhat buggy) - - sound blaster emulation is now sb pro 2.0 compatible - - added basic support for 32-bit protected mode - - VGA now tries to emulate an S3 Trio 64 card with 2 MB - - VESA 2.0 support for some 256 color modes - - rewrote large piece of video bios code for better compatibility - - added support for the not inheritance flags. - - created functions for creating child psp. - - updated errorcodes of findfirst (thanks Mirek!) - - rewrote loggingsystem to generate less warnings - - added dos protected mode interface (dpmi) - - added cdrom label support - - improved cdrom audio playing - - fixed and improved directory cache - - debugger shows selector- and cpu mode info - - added SELINFO (selector information) command to debugger - - added reference counting for dos files - - added tab-completion - - added basic fpu support. - - fixed several bugs with case sensitive filesystems. - - added more shell commands and improved their behaviour. - - mouse improvements. - - real time clock improvements. - - DMA fixes. - - Improved .BAT file support. - -0.58 - - fixed date and time issues with fcbs - - added more commands to the internal Shell - - corrected config system when a old configfile was used - - fixed cga put and get pixel - - fixed some vga register getting reset to wrong values - - improved support for foreign keyboards - - improved joystick support - - made dosbox multithreaded again - - lot's of soundblaster fixes - - dma fixes - - cdrom support - - midi support - - added scale2x - - reenabled screenshot support - - joystick support fixes - - mouse improvements - - support for writing wavefiles - - added directory cache and longfilename support (longfilenames will be mangled) - - mouse fixes - - -0.57 - - added support for command /C - - fixed all fcb-write functions - - fixed fcb-parseline - - added debugger under linux/freebsd - - added debugger memory breakpoints and autolog function (heavy debug) - - added loadfix.com program that eats up memory (default 64kb) - Usage : loadfix [-option] [programname] [parameters]... - Example: loadfix mm2 (Allocates 64kb and starts executable mm2) - loadfix -32 mm2 (Allocates 32kb and starts executable mm2) - loadfix -128 (Allocates 128kb) - loadfix -f (frees all previous allocated memory) - - added echoing of characters for input function - - added support for backspace for input function - - added partial support for int10:01 set cursortype - - fixed most of the problems/bugs with character input. - - fixed allocationinfo call.(darksun series) - - improved dos support for non-existant functions - - Split screen support - - prefix 66 67 support - - rewrote timingscheme so 1000 hz timers don't cause problems anymore - - update adlib emulation - - fixed some isues with the mouse (double clicks and visible when it shouldn't be) - - improved mouse behaviour (mickey/pixel rate) and detection routines. - - basic ansi.sys support - - Disney sound system emulation - - rewrote upcase/lowcase functions so they work fine with gcc3.2 - - SHELL: added rename and delete - - added support for command /C. Fixed crashes in the shell - - fixed various bugs when exiting dosbox - - fixed a bug in XMS - - fixed a bug with the joystick when pressing a button - - create nicer configfiles. - - bios_disk function improved. - - trapflag support - - improved vertical retrace timing. - - PIT Timer improvements and many bug fixes - - Many many bug fixes to the DOS subsystem - - Support for memory allocation strategy - - rewrote cpu mainloop to act more like a real cpu - -0.56 - - added support for a configclass/configfile - - added support for writing out the configclass into a configfile - - removed the language file and made it internal - - added support for writing the language file (will override the internal one) - - improved mousesupport - - updated readme - - support for screenshots - - some cpu-bug fixes - - dma changes - - Real Sound support - - EMM fixes and new functions. - - VGA fixes - - new wildcompare - - support for size and disktype at mount. - - added new debugger functionalities: start/trace into INTs, write processor status log, - step over rep and loop instructions, breakpoint support without using INT 03 (heavy debugging switch) - - Added more cpu instructions and changed the string operations. - - Added classes for most of the internal dos structures. - - Rewrote most of the fcb calls to use normal dos calls. - -0.55 - - fixed the errors/warnings in prefix_66.h and prefix_66_of.h (decimal too large becomming unsigned). - - fixed compilation error on FreeBSD when #disable_joystick was defined - - int10_writechar has been updated to move the cursor position. - - changed the basedir routines to use the current working dir instead of argv[0]. This will fix and brake things :) - - illegal command, now displays the command - - wildcmp updated to be case insensitive - - added fcb:open,close,findfirst, findnext. - - fixed rename in drive_local - - added new features to the debugger: breakpoint support / data view / command line - - partial support of list of lists (dos info block) - - full emm 3.2 support - - partial emm 4.0 support - - fixes to graphics core fonts (text in sierra games is now correct) - - improved support for user mousehandlers - - fixed EGA graphics - - fixed VGA graphics - - fixed write with size 0 - - changed memory management. - - fixed and cleaned up the cpu flags. - - changed interrupt handler. - - speeded up the graphics. - - speeded up the cpu-core - - changed dma - - improved dma streams from emm memory - - added some cga videomodes - - added more funtions to the keyboard handler - -0.50: - -added F3 to repeat the last typed command. - -made it possible to change the shellmessages(dosshell). so - you can costumize it.(dosbox.lang) - -changed cpu core. - -Fixed a lot of errors with the keyboard: shift-f1 and - alt-f1 now works. - -Fixed some division errors. - -made a plugin system. - -added a lot of real 386 mode instructions. - -made it possible to resize the screen. - -Mayor source cleanup/reorganisation. - -Complete rewrite of the graphics routines. Should make it - possible to implement more fancy things like 2xsai,interpolation. - -changed the sound playback. - -Changed the vga drawing to only draw on memory changes, instead - of drawing an entire frame. - -fixes to the soundblaster/dma code should be able to play 4-bit - adpcm compressed sounds. - -added the correct time to dir. - -bugfixes to batch-file handling. - -Lot's of small bugfixes.(Dune1&2,wolf3d, many more). - -Released the source. +0.50: + -added F3 to repeat the last typed command. + -made it possible to change the shellmessages(dosshell). so + you can costumize it.(dosbox.lang) + -changed cpu core. + -Fixed a lot of errors with the keyboard: shift-f1 and + alt-f1 now works. + -Fixed some division errors. + -made a plugin system. + -added a lot of real 386 mode instructions. + -made it possible to resize the screen. + -Mayor source cleanup/reorganisation. + -Complete rewrite of the graphics routines. Should make it + possible to implement more fancy things like 2xsai,interpolation. + -changed the sound playback. + -Changed the vga drawing to only draw on memory changes, instead + of drawing an entire frame. + -fixes to the soundblaster/dma code should be able to play 4-bit + adpcm compressed sounds. + -added the correct time to dir. + -bugfixes to batch-file handling. + -Lot's of small bugfixes.(Dune1&2,wolf3d, many more). + -Released the source. \ No newline at end of file diff --git a/README b/README index 31fcfbc..a3dd79a 100644 --- a/README +++ b/README @@ -1,1234 +1,93 @@ -DOSBox v0.72 - - -===== -NOTE: -===== - -While we are hoping that one day DOSBox will run all programs ever -made for the PC, we are not there yet. At present, DOSBox running -on a high-end machine will roughly be the equivalent of a 486 PC. -DOSBox can be configured to run a wide range of DOS games, from -CGA/Tandy/PCjr classics up to games from the Quake era. - - - -====== -INDEX: -====== -1. Quickstart -2. FAQ -3. Usage -4. Internal Programs -5. Special Keys -6. Mapper -7. Keyboard Layout -8. Serial Multiplayer feature -9. How to run resource-demanding games -10. Troubleshooting -11. The config file -12. The language file -13. Building your own version of DOSBox -14. Special thanks -15. Contact - - - -============== -1. Quickstart: -============== - -Type INTRO in DOSBox for a quick tour. -It is essential that you get familiar with the idea of mounting, -DOSBox does not automatically make any drive (or a part of it) -accessible to the emulation. -See the FAQ entry "I've got a Z instead of a C at the prompt" as -well as the description of the MOUNT command (section 4). - - - -======= -2. FAQ: -======= - -Some Frequently Asked Questions: - -Q: I've got a Z instead of a C at the prompt. -Q: Do I always have to type these commands? Automation? -Q: How do I change to fullscreen? -Q: My CD-ROM doesn't work. -Q: The game/application can't find its CD-ROM. -Q: The mouse doesn't work. -Q: There is no sound. -Q: The sound stutters or sounds stretched/weird. -Q: I can't type \ or : in DOSBox. -Q: The keyboard lags. -Q: The cursor always moves into one direction! -Q: The game/application runs much too slow! -Q: The game/application does not run at all/crashes! -Q: Can DOSBox harm my computer? -Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ. -Q: What sound hardware does DOSBox presently emulate? -Q: DOSBox crashes on startup and I'm running arts. -Q: Great README, but I still don't get it. - - - - -Q: I've got a Z instead of a C at the prompt. -A: You have to make your directories available as drives in DOSBox by using - the "mount" command. For example, in Windows "mount C D:\GAMES" will give - you a C drive in DOSBox which points to your Windows D:\GAMES directory. - In Linux, "mount c /home/username" will give you a C drive in DOSBox - which points to /home/username in Linux. - To change to the drive mounted like above, type "C:". If everything went - fine, DOSBox will display the prompt "C:\>". - - -Q: Do I always have to type these commands? Automation? -A: In the DOSBox configuration file is an [autoexec] section. The commands - present there are run when DOSBox starts, so you can use this section - for the mounting. - - -Q: How do I change to fullscreen? -A: Press alt-enter. Alternatively: Edit the configuration file of DOSBox and - change the option fullscreen=false to fullscreen=true. If fullscreen looks - wrong in your opinion: Play with the option fullresolution in the - configuration file of DOSBox. To get back from fullscreen mode: - Press alt-enter again. - - -Q: My CD-ROM doesn't work. -A: To mount your CD-ROM in DOSBox you have to specify some additional options - when mounting the CD-ROM. - To enable CD-ROM support (includes MSCDEX): - - mount d f:\ -t cdrom (windows) - - mount d /media/cdrom -t cdrom (linux) - - In some cases you might want to use a different CD-ROM interface, - for example if CD audio does not work: - To enable SDL-support (does not include low-level CD access!): - - mount d f:\ -t cdrom -usecd 0 -noioctl - To enable ioctl access using digital audio extraction for CD audio - (windows-only, useful for Vista): - - mount d f:\ -t cdrom -ioctl_dx - To enable ioctl access using MCI for CD audio (windows-only): - - mount d f:\ -t cdrom -ioctl_mci - To force ioctl-only access (windows-only): - - mount d f:\ -t cdrom -ioctl_dio - To enable low-level aspi-support (win98 with aspi-layer installed): - - mount d f:\ -t cdrom -aspi - - In the commands: - d driveletter you will get in DOSBox - - f:\ location of CD-ROM on your PC. - - 0 The number of the CD-ROM drive, reported by "mount -cd" - (note that this value is only needed when using SDL - for CD audio, otherwise it is ignored) - See also the next question: The game/application can't find its CD-ROM. - - -Q: The game/application can't find its CD-ROM. -A: Be sure to mount the CD-ROM with -t cdrom switch, this will enable the - MSCDEX interface required by DOS games to interface with CD-ROMs. - Also try adding the correct label (-label LABEL) to the mount command, - where LABEL is the CD-label (volume ID) of the CD-ROM. - Under Windows you can specify -ioctl, -aspi or -noioctl. Look at the - description of the mount command in Section 4 for their meaning and the - additional audio-CD related options -ioctl_dx, ioctl_mci, ioctl_dio. - - Try creating a CD-ROM image (preferably CUE/BIN pair) and use the - DOSBox-internal IMGMOUNT tool to mount the image (the CUE sheet). - This enables very good low-level CD-ROM support on any operating system. - - -Q: The mouse doesn't work. -A: Usually, DOSBox detects when a game uses mouse control. When you click on - the screen it should get locked (confined to the DOSBox window) and work. - With certain games, the DOSBox mouse detection doesn't work. In that case - you will have to lock the mouse manually by pressing CTRL-F10. - - -Q: There is no sound. -A: Be sure that the sound is correctly configured in the game. This might be - done during the installation or with a setup/setsound utility that - accompanies the game. First see if an autodetection option is provided. If - there is none try selecting soundblaster or soundblaster16 with the default - settings being "address=220 irq=7 dma=1". You might also want to select - midi at address 330 as music device. - The parameters of the emulated soundcards can be changed in the DOSBox - configuration file. - If you still don't get any sound set the core to normal and use some lower - fixed cycles value (like cycles=2000). Also assure that your host operating - sound does provide sound. - In certain cases it might be useful to use a different emulated sound device - like a soundblaster pro (sbtype=sbpro1 in the DOSBox configuration file) or - the gravis ultrasound (gus=true). - - -Q: The sound stutters or sounds stretched/weird. -A: You're using too much CPU power to keep DOSBox running at the current speed. - You can lower the cycles, skip frames, reduce the sampling rate of - the respective sound device (see the DOSBox configuration file) or - the mixer device. You can also increase the prebuffer in the configfile. - If you are using cycles=max or =auto, then make sure that there is no - background processes interfering! (especially if they access the harddisk) - - -Q: I can't type \ or : in DOSBox. -A: This can happen in various cases, like your host keyboard layout does not - have a matching DOS layout representation (or it was not correctly detected), - or the key mapping is wrong. - Some possible fixes: - 1. Use / instead, or ALT-58 for : and ALT-92 for \. - 2. Change the DOS keyboard layout (see Section 7: Keyboard Layout). - 3. Add the commands you want to execute to the [autoexec]-section - of the DOSBox configuration file. - 4. Open the DOSBox configuration file and change the usescancodes entry. - 5. Switch the keyboard layout of your operating system. - - Note that if the host layout can not be identified, or keyboardlayout is set - to none in the DOSBox configuration file, the standard US layout is used. - In this configuration try the keys around "enter" for the key \ (backslash), - and for the key : (colon) use shift and the keys between "enter" and "l". - - -Q: The keyboard lags. -A: Lower the priority setting in the DOSBox configuration file, for example - set "priority=normal,normal". You might also want to try lowering the cycles - (use a fixed cycle count to start with, like cycles=10000). - - -Q: The cursor always moves into one direction! -A: See if it still happens if you disable the joystick emulation, - set joysticktype=none in the [joystick] section of your DOSBox - configuration file. Maybe also try unplugging any joystick/gamepad. - If you want to use the joystick in the game, try setting timed=false - and be sure to calibrate the joystick (both in your OS as well as - in the game or the game's setup program). - - -Q: The game/application runs much too slow! -A: Look at the section "How to run resource-demanding games" for more - information. - - -Q: The game/application does not run at all/crashes! -A: Look at Section 10: Troubleshooting - - -Q: Can DOSBox harm my computer? -A: DOSBox can not harm your computer more than any other resource demanding - program. Increasing the cycles does not overclock your real CPU. - Setting the cycles too high has a negative performance effect on the - software running inside DOSBox. - - -Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ. -A: This is possible! Just create a config file: config -writeconf configfile. - Start your favourite editor and look through the settings. To start DOSBox - with your new settings: dosbox -conf configfile - See the description of the config command in Section 4 for more details. - - -Q: What sound hardware does DOSBox presently emulate? -A: DOSBox emulates several legacy sound devices: - - Internal PC speaker - This emulation includes both the tone generator and several forms of - digital sound output through the internal speaker. - - Creative CMS/Gameblaster - The is the first card released by Creative Labs(R). The default - configuration places it on port 0x220. It should be noted that enabling - this with the Adlib emulation may result in conflicts. - - Tandy 3 voice - The emulation of this sound hardware is complete with the exception of - the noise channel. The noise channel is not very well documented and as - such is only a best guess as to the sound's accuracy. - - Tandy DAC - Emulation of the Tandy DAC utilizes the soundblaster emulation, thus - be sure the soundblaster is not disabled in the DOSBox configuration - file. The Tandy DAC is only emulated at the BIOS level. - - Adlib - Borrowed from MAME, this emulation is almost perfect and includes the - Adlib's ability to almost play digitized sound. - - SoundBlaster 16 / SoundBlaster Pro I & II / SoundBlaster I & II - By default DOSBox provides Soundblaster 16 level 16-bit stereo sound. - You can select a different SoundBlaster version in the configfile of - DOSBox (See Internal Commands: CONFIG). - - Disney Soundsource - Using the printer port, this sound device outputs digital sound only. - - Gravis Ultrasound - The emulation of this hardware is nearly complete, though the MIDI - capabilities have been left out, since an MPU-401 has been - emulated in other code. - - MPU-401 - A MIDI passthrough interface is also emulated. This method of sound - output will only work when used with a General Midi or MT-32 device. - - -Q: DOSBox crashes on startup and I'm running arts. -A: This isn't really a DOSBox problem, but the solution is to set the - environment variable SDL_AUDIODRIVER to alsa or oss. - - -Q: Great README, but I still don't get it. -A: A look at "The Newbie's pictorial guide to DOSBox" located at - http://vogons.zetafleet.com/viewforum.php?f=39 might help you. - Also try the wiki of DOSBox: - http://www.dosbox.com/wiki/ - - -For more questions read the remainder of this README and/or check -the site/forum: -http://www.dosbox.com - - - -========= -3. Usage: -========= - -An overview of the command line options you can give to DOSBox. -Windows Users must open cmd.exe or command.com or edit the shortcut to -dosbox.exe for this. -The options are valid for all operating systems unless noted in the option -description: - -dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile] - [-lang languagefile] [-machine machinetype] [-noconsole] - [-startmapper] [-noautoexec] [-securemode] - [-scaler scaler | -forcescaler scaler] - [-version] - -dosbox -version - - name - If "name" is a directory it will mount that as the C: drive. - If "name" is an executable it will mount the directory of "name" - as the C: drive and execute "name". - - -exit - DOSBox will close itself when the DOS application "name" ends. - - -c command - Runs the specified command before running "name". Multiple commands - can be specified. Each command should start with "-c" though. - A command can be: an Internal Program, a DOS command or an executable - on a mounted drive. - - -fullscreen - Starts DOSBox in fullscreen mode. - - -conf configfile - Start DOSBox with the options specified in "configfile". - Multiple -conf options may be present. - See Section 11 for more details. - - -lang languagefile - Start DOSBox using the language specified in "languagefile". - - -machine machinetype - Setup DOSBox to emulate a specific type of machine. Valid choices are: - hercules, cga, pcjr, tandy, svga_s3 (default) as well as the additional - svga chipsets listed in the help of the DOSBox configuration file. - svga_s3 enables vesa emulation as well. - For some special vga effects the machinetype vgaonly can be used, - note that this disables svga capabilites and might be (considerably) - slower due to the much higher emulation precision. - The machinetype affects both the videocard and the available soundcards. - - -noconsole (Windows Only) - Start DOSBox without showing the console window. Output will - be redirected to stdout.txt and stderr.txt - - -startmapper - Enter the keymapper directly on startup. Useful for people with - keyboard problems. - - -noautoexec - Skips the [autoexec] section of the loaded configuration file. - - -securemode - Same as -noautoexec, but adds config.com -securemode at the - bottom of AUTOEXEC.BAT (which in turn disables any changes to how - the drives are mounted inside DOSBox). - - -scaler scaler - Uses the scaler specified by "scaler". See the DOSBox configuration - file for the available scalers. - - -forcescaler scaler - Similar to the -scaler parameter, but tries to force usage of - the specified scaler even if it might not fit. - - -version - output version information and exit. Useful for frontends. - -Note: If a name/command/configfile/languagefile contains a space, put - the whole name/command/configfile/languagefile between quotes - ("command or file name"). If you need to use quotes within quotes - (most likely with -c and mount): - Windows and OS/2 users can use single quotes inside the double quotes. - Other people should be able to use escaped double quotes inside the - double quotes. - Windows: -c "mount c 'c:\program files\'" - Linux: -c "mount c \"/tmp/name with space\"" - -For example (Windows): - -dosbox c:\atlantis\atlantis.exe -c "MOUNT D C:\SAVES" - This mounts c:\atlantis as c:\ and runs atlantis.exe. - Before it does that it would first mount C:\SAVES as the D drive. - -In Windows, you can also drag directories/files onto the DOSBox executable. - - - -===================== -4. Internal Programs: -===================== - -DOSBox supports most of the DOS commands found in command.com. -To get a list of the internal commands type "HELP" at the prompt. - -In addition, the following commands are available: - -MOUNT "Emulated Drive letter" "Real Drive or Directory" - [-t type] [-aspi] [-ioctl] [-noioctl] [-usecd number] [-size drivesize] - [-label drivelabel] [-freesize size_in_mb] - [-freesize size_in_kb (floppies)] -MOUNT -cd -MOUNT -u "Emulated Drive letter" - - Program to mount local directories as drives inside DOSBox. - - "Emulated Drive letter" - The driveletter inside DOSBox (eg. C). - - "Real Drive letter (usually for CD-ROMs in Windows) or Directory" - The local directory you want accessible inside DOSBox. - - -t type - Type of the mounted directory. Supported are: dir (default), - floppy, cdrom. - - -size drivesize - Sets the size of the drive, where drivesize is of the form - "bps,spc,tcl,fcl": - bps: bytes per sector, by default 512 for regular drives and - 2048 for CD-ROM drives - spc: sectors per cluster, usually between 1 and 127 - tcl: total clusters, between 1 and 65534 - fcl: total free clusters, between 1 and tcl - - -freesize size_in_mb | size_in_kb - Sets the amount of free space available on a drive in megabytes - (regular drives) or kilobytes (floppy drives). - This is a simpler version of -size. - - -label drivelabel - Sets the name of the drive to "drivelabel". Needed on some - systems if the CD-ROM label isn't read correctly (useful when a - program can't find its CD-ROM). If you don't specify a label and no - lowlevel support is selected (that is omitting the -usecd # and/or - -aspi parameters, or specifying -noioctl): - For Windows: label is extracted from "Real Drive". - For Linux: label is set to NO_LABEL. - - If you do specify a label, this label will be kept as long as the drive - is mounted. It will not be updated !! - - -aspi - Forces use of the aspi layer. Only valid if mounting a CD-ROM under - Windows systems with an ASPI-Layer. - - -ioctl (automatic selection of the CD audio interface) - -ioctl_dx (digital audio extraction used for CD audio) - -ioctl_dio (ioctl calls used for CD audio) - -ioctl_mci (MCI used for CD audio) - Forces use of ioctl commands. Only valid if mounting a CD-ROM under - a Windows OS which support them (Win2000/XP/NT). - The various choices only differ in the way CD audio is handled, - preferrably -ioctl_dio is used (lowest workload), but this might not - work on all systems so -ioctl_dx (or -ioctl_mci) can be used. - - -noioctl - Forces use of the SDL CD-ROM layer. Valid on all systems. - - -usecd number - Valid on all systems, under windows the -noioctl switch has to be - present to make use of the -usecd switch. - Enables to select the drive that should be used by SDL. Use this if - the wrong or no CD-ROM drive is mounted while using the SDL CD-ROM - interface. "number" can be found by "MOUNT -cd". - - -cd - Displays all CD-ROM drives detected by SDL, and their numbers. - See the information at the -usecd entry above. - - -u - Removes the mount. Doesn't work for Z:\. - - Note: It's possible to mount a local directory as CD-ROM drive. - Hardware support is then missing. - - Basically MOUNT allows you to connect real hardware to DOSBox's emulated PC. - So MOUNT C C:\GAMES tells DOSBox to use your C:\GAMES directory as drive C: - in DOSBox. It also allows you to change the drive letter identification - for programs that demand specific drive letters. - - For example: Touche: Adventures of The Fifth Musketeer must be run on your C: - drive. Using DOSBox and its mount command, you can trick the game into - believing it is on the C drive, while you can still place it where you - like. For example, if the game is in D:\OLDGAMES\TOUCHE, the command - MOUNT C D:\OLDGAMES will allow you to run Touche from the D drive. - - Mounting your entire C drive with MOUNT C C:\ is NOT recommended! The same - is true for mounting the root of any other drive, except for CD-ROMs (due to - their read-only nature). Otherwise if you or DOSBox make a mistake you may - lose all your files. - It is recommended to put all your applications/games into a subdirectory - and mount that. - - General MOUNT Examples: - 1. To mount c:\DirX as a floppy : - mount a c:\DirX -t floppy - 2. To mount system CD-ROM drive E as CD-ROM drive D in DOSBox: - mount d e:\ -t cdrom - 3. To mount system CD-ROM drive at mountpoint /media/cdrom as CD-ROM drive D - in DOSBox: - mount d /media/cdrom -t cdrom -usecd 0 - 4. To mount a drive with ~870 mb free diskspace (simple version): - mount c d:\ -freesize 870 - 5. To mount a drive with ~870 mb free diskspace (experts only, full control): - mount c d:\ -size 512,127,16513,13500 - 6. To mount /home/user/dirY as drive C in DOSBox: - mount c /home/user/dirY - 7. To mount the directory where DOSBox was started as D in DOSBox: - mount d . - (note the . which represents the directory where DOSBox was started) - - -MEM - Program to display the amount of free memory. - - -VER -VER set major_version [minor_version] - Display the current DOSBox version and reported DOS version - (parameterless usage). - Change the reported DOS version with the "set" parameter, - for example: "VER set 6 22" to have DOSBox report DOS 6.22 - as version number. - - -CONFIG -writeconf localfile -CONFIG -writelang localfile -CONFIG -securemode -CONFIG -set "section property=value" -CONFIG -get "section property" - - CONFIG can be used to change or query various settings of DOSBox - during runtime. It can save the current settings and language strings to - disk. Information about all possible sections and properties can - be found in Section 11 (The Config File). - - -writeconf localfile - Write the current configuration settings to file. "localfile" is - located on the local drive, not a mounted drive in DOSBox. - The configuration file controls various settings of DOSBox: - the amount of emulated memory, the emulated soundcards and many more - things. It allows access to AUTOEXEC.BAT as well. - See Section 11 (The Config File) for more information. - - -writelang localfile - Write the current language settings to file. "localfile" is - located on the local drive, not a mounted drive in DOSBox. - The language file controls all visible output of the internal commands - and the internal DOS. - - -securemode - Switches DOSBox to a more secure mode. In this mode the internal - commands MOUNT, IMGMOUNT and BOOT won't work. It's not possible either - to create a new configfile or languagefile in this mode. - (Warning: you can only undo this mode by restarting DOSBox.) - - -set "section property=value" - CONFIG will attempt to set the property to new value. Currently - CONFIG can not report whether the command succeeded or not. - - -get "section property" - The current value of the property is reported and stored in the - environment variable %CONFIG%. This can be used to store the value - when using batch files. - - Both "-set" and "-get" work from batch files and can be used to set up your - own preferences for each game. - - Examples: - 1. To create a configfile in your current directory: - config -writeconf dosbox.conf - 2. To set the cpu cycles to 10000: - config -set "cpu cycles=10000" - 3. To turn ems memory emulation off: - config -set "dos ems=off" - 4. To check which cpu core is being used. - config -get "cpu core" - - -LOADFIX [-size] [program] [program-parameters] -LOADFIX -f - Program to reduce the amount of available conventional memory. - Useful for old programs which don't expect much memory to be free. - - -size - number of kilobytes to "eat up", default = 64kb - - -f - frees all previously allocated memory - - Examples: - 1. To start mm2.exe and allocate 64kb memory - (mm2 will have 64 kb less available) : - loadfix mm2 - 2. To start mm2.exe and allocate 32kb memory : - loadfix -32 mm2 - 3. To free previous allocated memory : - loadfix -f - - -RESCAN - Make DOSBox reread the directory structure. Useful if you changed something - on a mounted drive outside of DOSBox. (CTRL - F4 does this as well!) - - -MIXER - Makes DOSBox display its current volume settings. - Here's how you can change them: - - mixer channel left:right [/NOSHOW] [/LISTMIDI] - - channel - Can be one of the following: MASTER, DISNEY, SPKR, GUS, SB, FM [, CDAUDIO]. - CDAUDIO is only available if a CD-ROM interface with volume control is - enabled (CD image, ioctl_dx). - - left:right - The volume levels in percentages. If you put a D in front it will be - in decibel (Example: mixer gus d-10). - - /NOSHOW - Prevents DOSBox from showing the result if you set one - of the volume levels. - - /LISTMIDI - Lists the available midi devices on your PC (Windows). To select a - device other than the Windows default midi-mapper, add a line - 'config=id' to the [midi] section in the configuration file, where - 'id' is the number for the device as listed by LISTMIDI. - - -IMGMOUNT - A utility to mount disk images and CD-ROM images in DOSBox. - - IMGMOUNT DRIVE [imagefile] -t [image_type] -fs [image_format] - -size [sectorsbytesize, sectorsperhead, heads, cylinders] - IMGMOUNT DRIVE [imagefile1, .. ,imagefileN] -t iso -fs iso - - imagefile - Location of the image file to mount in DOSBox. The location can - be on a mounted drive inside DOSBox, or on your real disk. It is - possible to mount CD-ROM images (ISOs or CUE/BIN) as well, if you - need CD swapping capabilities specify all images in succession - (see the next entry). - CUE/BIN pairs are the preferred CD-ROM image type as they can - store audio tracks compared to ISOs (which are data-only). For - the CUE/BIN mounting always specify the CUE sheet. - - imagefile1, .. ,imagefileN - Location of the image files to mount in DOSBox. Specifying a number - of image files is only allowed for CD-ROM images. The CD's can be - swapped with CTRL-F4 at any time. This is required for games which - use multiple CD-ROMs and require the CD to be switched during the - gameplay at some point. - - -t - The following are valid image types: - floppy: Specifies a floppy image. DOSBox will automatically identify - the disk geometry (360K, 1.2MB, 720K, 1.44MB, etc). - iso: Specifies a CD-ROM iso image. The geometry is automatic and - set for this size. This can be an iso or a cue/bin pair. - hdd: Specifies a harddrive image. The proper CHS geometry - must be set for this to work. - - -fs - The following are valid file system formats: - iso: Specifies the ISO 9660 CD-ROM format. - fat: Specifies that the image uses the FAT file system. DOSBox will attempt - to mount this image as a drive in DOSBox and make the files - available from inside DOSBox. - none: DOSBox will make no attempt to read the file system on the disk. - This is useful if you need to format it or if you want to boot - the disk using the BOOT command. When using the "none" - filesystem, you must specify the drive number (2 or 3, - where 2 = master, 3 = slave) rather than a drive letter. - For example, to mount a 70MB image as the slave drive device, - you would type (without the quotes): - "imgmount 3 d:\test.img -size 512,63,16,142 -fs none" - Compare this with a mount to be able to access the drive - within DOSBox, which would read as: - "imgmount e: d:\test.img -size 512,63,16,142" - - -size - The Cylinders, Heads and Sectors of the drive. - Required to mount hard drive images. - - An example how to mount CD-ROM images: - 1a. mount c /tmp - 1b. imgmount d c:\myiso.iso -t iso - or (which also works): - 2. imgmount d /tmp/myiso.iso -t iso - - -BOOT - Boot will start floppy images or hard disk images independent of the - operating system emulation offered by DOSBox. This will allow you to - play booter floppies or boot other operating systems inside DOSBox. - If the target emulated system is PCjr (machine=pcjr) the boot command - can be used to load PCjr cartridges (.jrc). - - BOOT [diskimg1.img diskimg2.img .. diskimgN.img] [-l driveletter] - BOOT [cart.jrc] (PCjr only) - - diskimgN.img - This can be any number of floppy disk images one wants mounted after - DOSBox boots the specified drive letter. - To swap between images, hit CTRL-F4 to change from the current disk - to the next disk in the list. The list will loop back from the last - disk image to the beginning. - - [-l driveletter] - This parameter allows you to specify the drive to boot from. - The default is the A drive, the floppy drive. You can also boot - a hard drive image mounted as master by specifying "-l C" - without the quotes, or the drive as slave by specifying "-l D" - - cart.jrc (PCjr only) - When emulation of a PCjr is enabled, cartridges can be loaded with - the BOOT command. Support is still limited. - - -IPX - - You need to enable IPX networking in the configuration file of DOSBox. - - All of the IPX networking is managed through the internal DOSBox program - IPXNET. For help on the IPX networking from inside DOSBox, type - "IPXNET HELP" (without quotes) and the program will list the commands - and relevant documentation. - - With regard to actually setting up a network, one system needs to be - the server. To set this up, type "IPXNET STARTSERVER" (without the quotes) - in a DOSBox session. The server DOSBox session will automatically add - itself to the virtual IPX network. For every additional computer that - should be part of the virtual IPX network, you'll need to type - "IPXNET CONNECT ". - For example, if your server is at bob.dosbox.com, you would type - "IPXNET CONNECT bob.dosbox.com" on every non-server system. - - To play games that need Netbios a file named NETBIOS.EXE from Novell is - needed. Establish the IPX connection as explained above, then run - "netbios.exe". - - The following is an IPXNET command reference: - - IPXNET CONNECT - - IPXNET CONNECT opens a connection to an IPX tunnelling server - running on another DOSBox session. The "address" parameter specifies - the IP address or host name of the server computer. You can also - specify the UDP port to use. By default IPXNET uses port 213 - the - assigned IANA port for IPX tunnelling - for its connection. - - The syntax for IPXNET CONNECT is: - IPXNET CONNECT address - - IPXNET DISCONNECT - - IPXNET DISCONNECT closes the connection to the IPX tunnelling server. - - The syntax for IPXNET DISCONNECT is: - IPXNET DISCONNECT - - IPXNET STARTSERVER - - IPXNET STARTSERVER starts an IPX tunnelling server on this DOSBox - session. By default, the server will accept connections on UDP port - 213, though this can be changed. Once the server is started, DOSBox - will automatically start a client connection to the IPX tunnelling server. - - The syntax for IPXNET STARTSERVER is: - IPXNET STARTSERVER - - If the server is behind a router, UDP port needs to be forwarded - to that computer. - - On Linux/Unix-based systems port numbers smaller than 1023 can only be - used with root privileges. Use ports greater than 1023 on those systems. - - IPXNET STOPSERVER - - IPXNET STOPSERVER stops the IPX tunnelling server running on this DOSBox - session. Care should be taken to ensure that all other connections have - terminated as well, since stopping the server may cause lockups on other - machines that are still using the IPX tunnelling server. - - The syntax for IPXNET STOPSERVER is: - IPXNET STOPSERVER - - IPXNET PING - - IPXNET PING broadcasts a ping request through the IPX tunnelled network. - In response, all other connected computers will respond to the ping - and report the time it took to receive and send the ping message. - - The syntax for IPXNET PING is: - IPXNET PING - - IPXNET STATUS - - IPXNET STATUS reports the current state of this DOSBox session's - IPX tunnelling network. For a list of all computers connected to the - network use the IPXNET PING command. - - The syntax for IPXNET STATUS is: - IPXNET STATUS - - -KEYB [languagecode [codepage [codepagefile]]] - Change the keyboard layout. For detailed information about keyboard - layouts please see Section 7. - - [languagecode] is a string consisting of two (in special cases more) - characters, examples are GK (Greece) or IT (Italy). It specifies - the keyboard layout to be used. - - [codepage] is the number of the codepage to be used. The keyboard layout - has to provide support for the specified codepage, otherwise the layout - loading will fail. - If no codepage is specified, an appropriate codepage for the requested - layout is chosen automatically. - - [codepagefile] can be used to load codepages that are yet not compiled - into DOSBox. This is only needed when DOSBox does not find the codepage. - - - Examples: - 1. To load the german keyboard layout (automatically uses codepage 858): - keyb gr - 2. To load the russian keyboard layout with codepage 866: - keyb ru 866 - In order to type russian characters press ALT+RIGHT-SHIFT. - 3. To load the french keyboard layout with codepage 850 (where the - codepage is defined in EGACPI.DAT): - keyb fr 850 EGACPI.DAT - 4. To load codepage 858 (without a keyboard layout): - keyb none 858 - This can be used to change the codepage for the FreeDOS keyb2 utility. - 5. To display the current codepage and, if loaded, the keyboard layout: - keyb - - - -For more information use the /? command line switch with the programs. - - - -================ -5. Special Keys: -================ - -ALT-ENTER Switch to full screen and back. -ALT-PAUSE Pause emulation (hit ALT-PAUSE again to continue). -CTRL-F1 Start the keymapper. -CTRL-F4 Change between mounted disk-images. Update directory cache for all drives! -CTRL-ALT-F5 Start/Stop creating a movie of the screen. (avi video capturing) -CTRL-F5 Save a screenshot. (PNG format) -CTRL-F6 Start/Stop recording sound output to a wave file. -CTRL-ALT-F7 Start/Stop recording of OPL commands. (DRO format) -CTRL-ALT-F8 Start/Stop the recording of raw MIDI commands. -CTRL-F7 Decrease frameskip. -CTRL-F8 Increase frameskip. -CTRL-F9 Kill DOSBox. -CTRL-F10 Capture/Release the mouse. -CTRL-F11 Slow down emulation (Decrease DOSBox Cycles). -CTRL-F12 Speed up emulation (Increase DOSBox Cycles). -ALT-F12 Unlock speed (turbo button). - -(NOTE: Once you increase your DOSBox cycles beyond your computer's maximum -capacity, it will produce the same effect as slowing down the emulation. -This maximum will vary from computer to computer.) - - -These are the default keybindings. They can be changed in the keymapper -(see Section 6: Mapper). - -Saved/recorded files can be found in current_directory/capture -(this can be changed in the DOSBox configuration file). -The directory has to exist prior to starting DOSBox, otherwise nothing -gets saved/recorded ! - - - -========== -6. Mapper: -========== - -When you start the DOSBox mapper (either with CTRL-F1 or -startmapper as -a command line argument to the DOSBox executable) you are presented with -a virtual keyboard and a virtual joystick. - -These virtual devices correspond to the keys and events DOSBox will -report to the DOS applications. If you click on a button with your mouse, -you can see in the lower left corner with which event it is associated -(EVENT) and to what events it is currently bound. - -Event: EVENT -BIND: BIND - Add Del -mod1 hold Next -mod2 -mod3 - - -EVENT - The key or joystick axis/button/hat DOSBox will report to DOS applications. -BIND - The key on your real keyboard or the axis/button/hat on your real - joystick(s) (as reported by SDL) which is connected to the EVENT. -mod1,2,3 - Modfiers. These are keys you need to have to be pressed while pressing - BIND. mod1 = CTRL and mod2 = ALT. These are generally only used when you - want to change the special keys of DOSBox. -Add - Add a new BIND to this EVENT. Basically add a key from your keyboard or an - event from the joystick (button press, axis/hat movement) which will - produce the EVENT in DOSBox. -Del - Delete the BIND to this EVENT. If an EVENT has no BINDS, then it is not - possible to trigger this event in DOSBox (that is there's no way to type - the key or use the respective action of the joystick). -Next - Go through the list of bindings which map to this EVENT. - - -Example: -Q1. You want to have the X on your keyboard to type a Z in DOSBox. - A. Click on the Z on the keyboard mapper. Click "Add". - Now press the X key on your keyboard. - -Q2. If you click "Next" a couple of times, you will notice that the Z on your - keyboard also produces an Z in DOSBox. - A. Therefore select the Z again, and click "Next" until you have the Z on - your keyboard. Now click "Del". - -Q3. If you try it out in DOSBox, you will notice that pressing X makes ZX - appear. - A. The X on your keyboard is still mapped to the X as well! Click on - the X in the keyboard mapper and search with "Next" until you find the - mapped key X. Click "Del". - - -Examples about remapping the joystick: - You have a joystick attached, it is working fine under DOSBox and you - want to play some keyboard-only game with the joystick (it is assumed - that the game is controlled by the arrows on the keyboard): - 1. Start the mapper, then click on one of the arrows in the middle - of the left part of the screen (right above the Mod1/Mod2 buttons). - EVENT should be key_left. Now click on Add and move your joystick - in the respective direction, this should add an event to the BIND. - 2. Repeat the above for the missing three directions, additionally - the buttons of the joystick can be remapped as well (fire/jump). - 3. Click on Save, then on Exit and test it with some game. - - You want to swap the y-axis of the joystick because some flightsim uses - the up/down joystick movement in a way you don't like, and it is not - configurable in the game itself: - 1. Start the mapper and click on Y- in the upper joystick field (this - is for the first joystick if you have two joysticks attached) or the - lower joystick field (second joystick or, if you have only one - joystick attached, the second axes cross). - EVENT should be jaxis_0_1- (or jaxis_1_1-). - 2. Click on Del to remove the current binding, then click Add and move - your joystick downwards. A new bind should be created. - 3. Repeat this for Y+, save the layout and finally test it with some game. - - - -If you change the default mapping, you can save your changes by clicking on -"Save". DOSBox will save the mapping to a location specified in the configuration -file (the mapperfile= entry). At startup, DOSBox will load your mapperfile, -if it is present in the DOSBox configuration file. - - - -=================== -7. Keyboard Layout: -=================== - -To switch to a different keyboard layout, either the entry "keyboardlayout" -in the [dos] section of the DOSBox configuration file can be used, or the -internal DOSBox program keyb.com. Both accept DOS conforming language codes -(see below), but only by using keyb.com a custom codepage can be specified. - -The default keyboardlayout=auto currently works under windows only, the -layout is chosen according to the OS layout. - -Layout switching - DOSBox supports a number of keyboard layouts and codepages by default, - in this case just the layout identifier needs to be specified (like - keyboardlayout=sv in the DOSBox configuration file, or using "keyb sv" - at the DOSBox command prompt). - - Some keyboard layouts (for example layout GK codepage 869 and layout RU - codepage 808) have support for dual layouts that can be activated by - pressing LEFT-ALT+RIGHT-SHIFT and deactivated by LEFT-ALT+LEFT-SHIFT. - -Supported external files - The FreeDOS .kl files are supported (FreeDOS keyb2 keyboard layoutfiles) as - well as the FreeDOS keyboard.sys/keybrd2.sys/keybrd3.sys libraries which - consist of all available .kl files. - See http://projects.freedos.net/keyb/ for precompiled keyboard layouts if - the DOSBox-integrated layouts don't work for some reason, or if updated or - new layouts become available. - - Both .CPI (MS-DOS and compatible codepage files) and .CPX (FreeDOS - UPX-compressed codepage files) can be used. Some codepages are compiled - into DOSBox, so it is mostly not needed to care about external codepage - files. If you need a different (or custom) codepage file, copy it into - the directory of the DOSBox configuration file so it is accessible for - DOSBox. - - Additional layouts can be added by copying the corresponding .kl file into - the directory of the DOSBox configuration file and using the first part of - the filename as language code. - Example: For the file UZ.KL (keyboard layout for Uzbekistan) specify - "keyboardlayout=uz" in the DOSBox configuration file. - The integration of keyboard layout packages (like keybrd2.sys) works similar. - - -Note that the keyboard layout allows foreign characters to be entered, but -there is NO support for them in filenames. Try to avoid them both inside -DOSBox as well as in files on your host operating system that are accessible -by DOSBox. - - - -============================== -8. Serial Multiplayer feature: -============================== - -DOSBox can emulate a serial nullmodem cable over network and internet. -It can be configured through the [serialports] section in the DOSBox -configuration file. - -To create a nullmodem connection, one side needs to act as the server and -one as the client. - -The server needs to be set up in the DOSBox configuration file like this: - serial1=nullmodem - -The client: - serial1=nullmodem server: - -Now start your game and choose nullmodem / serial cable / already connected -as multiplayer method on COM1. Set the same baudrate on both computers. - -Furthermore, additional parameters can be specified to control the behavior -of the nullmodem connection. These are all parameters: - - * port: - TCP port number. Default: 23 - * rxdelay: - how long (milliseconds) to delay received data if the - interface is not ready. Increase this value if you encounter - overrun errors in the DOSBox Status Window. Default: 100 - * txdelay: - how long to gather data before sending a packet. Default: 12 - (reduces Network overhead) - * server: - This nullmodem will be a client connecting to the specified - server. (No server argument: be a server.) - * transparent:1 - Only send the serial data, no RTS/DTR handshake. Use this - when connecting to anything other than a nullmodem. - * telnet:1 - Interpret Telnet data from the remote site. Automatically - sets transparent. - * usedtr:1 - The connection will not be established until DTR is switched - on by the DOS program. Useful for modem terminals. - Automatically sets transparent. - * inhsocket:1 - Use a socket passed to DOSBox by command line. Automatically - sets transparent. (Socket Inheritance: It is used for - playing old DOS door games on new BBS software.) - -Example: Be a server listening on TCP port 5000. - serial1=nullmodem server: port:5000 rxdelay:1000 - - - -======================================= -9. How to run resource-demanding games: -======================================= - -DOSBox emulates the CPU, the sound and graphic cards, and other peripherals -of a PC, all at the same time. The speed of an emulated DOS application -depends on how many instructions can be emulated, which is adjustable -(number of cycles). - -CPU Cycles - By default (cycles=auto) DOSBox tries to detect whether a game needs to - be run with as many instructions emulated per time interval as possible. - You can force this behaviour by setting cycles=max in the DOSBox - configuration file. The DOSBox window will display a line "Cpu Cyles: max" - at the top then. In this mode you can reduce the amount of cycles on a - percentage-basis (hit CTRL-F11) or raise it again (CTRL-F12). - - Sometimes manually setting the number of cycles achieves better results, - in the DOSBox configuration file specify for example cycles=30000. When - running some DOS application you can raise the cycles with CTRL-F12 even - more, but you will be limited by the power of your actual CPU. You can see - how much free time your real CPU has by looking at the Task Manager in - Windows 2000/XP and the System Monitor in Windows 95/98/ME. Once 100% of - your real CPU time is used there is no further way to speed up DOSBox - unless you reduce the load generated by the non-CPU parts of DOSBox. - -CPU Cores - On x86 architectures you can try to force the usage of a dynamically - recompiling core (set core=dynamic in the DOSBox configuration file). - This usually gives better results if the auto detection (core=auto) fails. - It is best accompanied by cycles=max. Note that there might be games - that work worse with the dynamic core, or do not work at all! - -Graphics emulation - VGA emulation is a very demanding part of DOSBox in terms of actual CPU - usage. Increase the number of frames skipped (in increments of one) by - pressing CTRL-F8. Your CPU usage should decrease when using a fixed - cycle setting. - Go back one step and repeat this until the game runs fast enough for you. - Please note that this is a trade-off: you lose in fluidity of video what - you gain in speed. - -Sound emulation - You can also try to disable the sound through the setup utility of the game - to reduce load on your CPU further. Setting nosound=true does NOT disable - the emulation of sound devices, just the output of sound will be disabled. - -Also try to close every program but DOSBox to reserve as much resources -as possible for DOSBox. - - -Advanced cycles configuration: -The cycles=auto and cycles=max settings can be parameterized to have -different startup defaults. The syntax is - cycles=auto ["realmode default"] ["protected mode default"%] - [limit "cycle limit"] - cycles=max ["protected mode default"%] [limit "cycle limit"] -Example: - cycles=auto 1000 80% limit 20000 - will use cycles=1000 for real mode games, 80% CPU throttling for - protected mode games along with a hard cycle limit of 20000 - - - -==================== -10. Troubleshooting: -==================== - -DOSBox crashes right after starting it: - - use different values for the output= entry in your DOSBox - configuration file - - try to update your graphics card driver and DirectX - -Running a certain game closes DOSBox, crashes with some message or hangs: - - see if it works with a default DOSBox installation - (unmodified configuration file) - - try it with sound disabled (use the sound configuration - program that comes with the game, additionally you can - set sbtype=none and gus=false in the DOSBox configuration file) - - change some entries of the DOSBox configuration file, especially try: - core=normal - fixed cycles (for example cycles=10000) - ems=false - xms=false - or combinations of the above settings - - use loadfix before starting the game - -The game exits to the DOSBox prompt with some error message: - - read the error message closely and try to locate the error - - try the hints at the above sections - - mount differently as some games are picky about the locations, - for example if you used "mount d d:\oldgames\game" try - "mount c d:\oldgames\game" and "mount c d:\oldgames" - - if the game requires a CD-ROM be sure you used "-t cdrom" when - mounting and try different additional parameters (the ioctl, - usecd and label switches, see the appropriate section) - - check the file permissions of the game files (remove read-only - attributes, add write permissions etc.) - - try reinstalling the game within DOSBox - - - -==================== -11. The Config File: -==================== - -A config file can be generated by CONFIG.COM, which can be found on the -internal DOSBox Z: drive when you start up DOSBox. Look in the internal -programs section of the readme for usage of CONFIG.COM. -You can edit the generated configfile to customize DOSBox. - -The file is divided into several sections (the names have [] around it). -Some sections have options you can set. -# and % indicate comment-lines. -The DOSBox configuration file contains the current settings. You can -alter them and start DOSBox with the -conf switch to load the file and -use these settings. - -DOSBox will first parse the settings in ~/.dosboxrc (Linux), -~\dosbox.conf (Win32) or "~/Library/Preferences/DOSBox Preferences" -(MACOSX). Afterwards DOSBox will parse all configfiles specified with the --conf switch. If no configfile is specified with the -conf switch, DOSBox will -look in the current directory for the DOSBox configuration file. - - - -====================== -12. The Language File: -====================== - -A language file can be generated by CONFIG.COM (CONFIG -writelang langfile). -Read it, and you will hopefully understand how to change it. -Start DOSBox with the -lang switch to use your new language file. -Alternatively, you can setup the filename in the config file in the [dosbox] -section. There's a language= entry that can be changed with the filename. - - - -======================================== -13. Building your own version of DOSBox: -======================================== - -Download the source. -Check the INSTALL in the source distribution. - - - -=================== -14. Special thanks: -=================== - -See the THANKS file. - - -============ -15. Contact: -============ - -See the site: -http://www.dosbox.com -for an email address (The Crew-page). +DOSBox v0.50 + +Usage: +====== + +With the new internal shell I've changed the command line a bit, so let's just give some +examples of what you can do now. +dosbox + With nothing on the command line you'll end up on the internal drive and from there you + can mount directories as drives. +dosbox [filename/directory] + If dosbox detects a directory it'll mount that as c:\ and then start the shell. + If dosbox doesn't detect a directory it'll assume you mean an executable this can be + .bat .com .exe. Doesn't need to have extension included. Then it'll strip the directory + from the filename and mount that as c:\ and then run the file. + +You can also add commands to be executed before the main program starts. Or you can use them +to start the program. +To add commands use the -c command line switch. +For example +dosbox c:\atlantis\atlantis.exe -c "MOUNT D C:\SAVES" "SET TEST=blah" + This would mount c:\atlanis as c:\ and run atlantis.exe from that directory but before it + does that it would first mount C:\SAVES as the D drive and set the environment variable test to blah. + +Dragging files or directories onto the DOSBox executable should also work. + + +Internal Programs: +================== + +MOUNT +Program to mount local directories as drives inside DOSBox. + +HWSET +Utility to setup the emulated hardware running inside DOSBox, only working for emulated sound cards. + +UPCASE +Utility to convert all files subdirectories of a local directory into upcase so DOSBox can use that directory +for mounting. This tool can be quite dangerous if used unproperly. You have been warned. + + +To get more information about how to use one these programs use the the /? command line switch. + + +Special Keys: +============= + +ALT-ENTER Go full screen and back. +CTRL-F10 Capture/Release the mouse. +CTRL-F11 Slowdown emulation. +CTRL-F12 Speedup emulation. + +System requirements: +==================== + +Fast machine my guess would be pentium-2 400+ to get decent emulation +of games written for an 286 machine. + +FAQ: +==== + +1.Q: I've got a Z instead of a C at the prompt. + A: In DOSBox you can mount directories as drives + in win32: mount c D:\ would give you an C in DOSBox which points + at D:\ in win32 + in linux: mount c /home/username would give you and C in DOSBox + which points at /home/username in Linux + +2.Q: The window is too small. + A: When you mouse touches the edges of the DOSBox screen you can click and drag it to + the size you prefer. + +3. Check the site/forum. + +Building your own Version DOSBox: +================================= + +Dowload the source. +Check the INSTALL in the source distribution. + +Special Thanks: +=============== + +Vlad R. of the vdmsound project for excellent sound blaster info. +Tatsuyuki Satoh of the Mame Team for making an excellent FM emulator. +The Bochs and DOSemu projects which I used for information. +Freedos for ideas in making my shell. + +Contact: +======== + +Harekiet harekiet@zophar.net +http://dosbox.zophar.net diff --git a/THANKS b/THANKS index 82284d4..fdc282e 100644 --- a/THANKS +++ b/THANKS @@ -1,26 +1,8 @@ -We would like to thank: - - -Vlad R. of the vdmsound project for excellent sound blaster info. -Tatsuyuki Satoh of the Mame Team for making an excellent FM emulator. -Jarek Burczynski for the new OPL emulator. - -The Bochs and DOSemu projects which I used for information. -Freedos for ideas in making my shell. - -Pierre-Yves Gérardy for hosting the old Beta Board. -Colin Snover for hosting our forum. - -Sourceforge for hosting our homepage and other development tools. -Mirek Luza, for his moderation of the forums. -eL_Pusher, DosFreak and MiniMax for their moderation of VOGONS forum. - -crazyc and gulikoza for their work on the dynrec core. - -Jantien for the version management. -Shawn, Johannes and Marcus for creating the MAC OS X version. -Jochen for creating the OS/2 version. -Ido Beeri for the icon. -All the people who submitted a bug. -The Beta Testers. - +We would like to thank: + + +Vlad R. of the vdmsound project for excellent sound blaster info. +Tatsuyuki Satoh of the Mame Team for making an excellent FM emulator. +The Bochs and DOSemu projects which I used for information. +Freedos for ideas in making my shell. +All the people who submitted a bug. diff --git a/VERSION b/VERSION deleted file mode 100644 index f49e2c7..0000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.72 diff --git a/acinclude.m4 b/acinclude.m4 index 5ad91a1..28772e8 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,396 +1,161 @@ -dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) -dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS -dnl -AC_DEFUN([AM_PATH_SDL], -[dnl -dnl Get the cflags and libraries from the sdl-config script -dnl -AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], - sdl_prefix="$withval", sdl_prefix="") -AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], - sdl_exec_prefix="$withval", sdl_exec_prefix="") -AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], - , enable_sdltest=yes) - - if test x$sdl_exec_prefix != x ; then - sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" - if test x${SDL_CONFIG+set} != xset ; then - SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config - fi - fi - if test x$sdl_prefix != x ; then - sdl_args="$sdl_args --prefix=$sdl_prefix" - if test x${SDL_CONFIG+set} != xset ; then - SDL_CONFIG=$sdl_prefix/bin/sdl-config - fi - fi - - AC_PATH_PROG(SDL_CONFIG, sdl-config, no) - min_sdl_version=ifelse([$1], ,0.11.0,$1) - AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) - no_sdl="" - if test "$SDL_CONFIG" = "no" ; then - no_sdl=yes - else - SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` - SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` - - sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - if test "x$enable_sdltest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $SDL_CFLAGS" - LIBS="$LIBS $SDL_LIBS" -dnl -dnl Now check if the installed SDL is sufficiently new. (Also sanity -dnl checks the results of sdl-config to some extent -dnl - rm -f conf.sdltest - AC_TRY_RUN([ -#include -#include -#include -#include "SDL.h" - -char* -my_strdup (char *str) -{ - char *new_str; - - if (str) - { - new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); - strcpy (new_str, str); - } - else - new_str = NULL; - - return new_str; -} - -int main (int argc, char *argv[]) -{ - int major, minor, micro; - char *tmp_version; - - /* This hangs on some systems (?) - system ("touch conf.sdltest"); - */ - { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } - - /* HP/UX 9 (%@#!) writes to sscanf strings */ - tmp_version = my_strdup("$min_sdl_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string\n", "$min_sdl_version"); - exit(1); - } - - if (($sdl_major_version > major) || - (($sdl_major_version == major) && ($sdl_minor_version > minor)) || - (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); - printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); - printf("*** best to upgrade to the required version.\n"); - printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); - printf("*** to point to the correct copy of sdl-config, and remove the file\n"); - printf("*** config.cache before re-running configure\n"); - return 1; - } -} - -],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - if test "x$no_sdl" = x ; then - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "$SDL_CONFIG" = "no" ; then - echo "*** The sdl-config script installed by SDL could not be found" - echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the SDL_CONFIG environment variable to the" - echo "*** full path to sdl-config." - else - if test -f conf.sdltest ; then - : - else - echo "*** Could not run SDL test program, checking why..." - CFLAGS="$CFLAGS $SDL_CFLAGS" - LIBS="$LIBS $SDL_LIBS" - AC_TRY_LINK([ -#include -#include "SDL.h" -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding SDL or finding the wrong" - echo "*** version of SDL. If it is not finding SDL, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means SDL was incorrectly installed" - echo "*** or that you have moved SDL since it was installed. In the latter case, you" - echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - SDL_CFLAGS="" - SDL_LIBS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(SDL_CFLAGS) - AC_SUBST(SDL_LIBS) - rm -f conf.sdltest -]) - -dnl Configure Paths for Alsa -dnl Some modifications by Richard Boulton -dnl Christopher Lansdown -dnl Jaroslav Kysela -dnl Last modification: alsa.m4,v 1.22 2002/05/27 11:14:20 tiwai Exp -dnl AM_PATH_ALSA([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) -dnl Test for libasound, and define ALSA_CFLAGS and ALSA_LIBS as appropriate. -dnl enables arguments --with-alsa-prefix= -dnl --with-alsa-enc-prefix= -dnl --disable-alsatest (this has no effect, as yet) -dnl -dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified, -dnl and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result. -dnl -AC_DEFUN([AM_PATH_ALSA], -[dnl Save the original CFLAGS, LDFLAGS, and LIBS -alsa_save_CFLAGS="$CFLAGS" -alsa_save_LDFLAGS="$LDFLAGS" -alsa_save_LIBS="$LIBS" -alsa_found=yes - -dnl -dnl Get the cflags and libraries for alsa -dnl -AC_ARG_WITH(alsa-prefix, -[ --with-alsa-prefix=PFX Prefix where Alsa library is installed(optional)], -[alsa_prefix="$withval"], [alsa_prefix=""]) - -AC_ARG_WITH(alsa-inc-prefix, -[ --with-alsa-inc-prefix=PFX Prefix where include libraries are (optional)], -[alsa_inc_prefix="$withval"], [alsa_inc_prefix=""]) - -dnl FIXME: this is not yet implemented -AC_ARG_ENABLE(alsatest, -[ --disable-alsatest Do not try to compile and run a test Alsa program], -[enable_alsatest=no], -[enable_alsatest=yes]) - -dnl Add any special include directories -AC_MSG_CHECKING(for ALSA CFLAGS) -if test "$alsa_inc_prefix" != "" ; then - ALSA_CFLAGS="$ALSA_CFLAGS -I$alsa_inc_prefix" - CFLAGS="$CFLAGS -I$alsa_inc_prefix" -fi -AC_MSG_RESULT($ALSA_CFLAGS) - -dnl add any special lib dirs -AC_MSG_CHECKING(for ALSA LDFLAGS) -if test "$alsa_prefix" != "" ; then - ALSA_LIBS="$ALSA_LIBS -L$alsa_prefix" - LDFLAGS="$LDFLAGS $ALSA_LIBS" -fi - -dnl add the alsa library -ALSA_LIBS="$ALSA_LIBS -lasound -lm -ldl -lpthread" -LIBS=`echo $LIBS | sed 's/-lm//'` -LIBS=`echo $LIBS | sed 's/-ldl//'` -LIBS=`echo $LIBS | sed 's/-lpthread//'` -LIBS=`echo $LIBS | sed 's/ //'` -LIBS="$ALSA_LIBS $LIBS" -AC_MSG_RESULT($ALSA_LIBS) - -dnl Check for a working version of libasound that is of the right version. -min_alsa_version=ifelse([$1], ,0.1.1,$1) -AC_MSG_CHECKING(for libasound headers version >= $min_alsa_version) -no_alsa="" - alsa_min_major_version=`echo $min_alsa_version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - alsa_min_minor_version=`echo $min_alsa_version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - alsa_min_micro_version=`echo $min_alsa_version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - -AC_LANG_SAVE -AC_LANG_C -AC_TRY_COMPILE([ -#include -], [ -/* ensure backward compatibility */ -#if !defined(SND_LIB_MAJOR) && defined(SOUNDLIB_VERSION_MAJOR) -#define SND_LIB_MAJOR SOUNDLIB_VERSION_MAJOR -#endif -#if !defined(SND_LIB_MINOR) && defined(SOUNDLIB_VERSION_MINOR) -#define SND_LIB_MINOR SOUNDLIB_VERSION_MINOR -#endif -#if !defined(SND_LIB_SUBMINOR) && defined(SOUNDLIB_VERSION_SUBMINOR) -#define SND_LIB_SUBMINOR SOUNDLIB_VERSION_SUBMINOR -#endif - -# if(SND_LIB_MAJOR > $alsa_min_major_version) - exit(0); -# else -# if(SND_LIB_MAJOR < $alsa_min_major_version) -# error not present -# endif - -# if(SND_LIB_MINOR > $alsa_min_minor_version) - exit(0); -# else -# if(SND_LIB_MINOR < $alsa_min_minor_version) -# error not present -# endif - -# if(SND_LIB_SUBMINOR < $alsa_min_micro_version) -# error not present -# endif -# endif -# endif -exit(0); -], - [AC_MSG_RESULT(found.)], - [AC_MSG_RESULT(not present.) - ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of libasound not found.)]) - alsa_found=no] -) -AC_LANG_RESTORE - -dnl Now that we know that we have the right version, let's see if we have the library and not just the headers. -AC_CHECK_LIB([asound], [snd_ctl_open],, - [ifelse([$3], , [AC_MSG_ERROR(No linkable libasound was found.)]) - alsa_found=no] -) - -if test "x$alsa_found" = "xyes" ; then - ifelse([$2], , :, [$2]) - LIBS=`echo $LIBS | sed 's/-lasound//g'` - LIBS=`echo $LIBS | sed 's/ //'` - LIBS="-lasound $LIBS" -fi -if test "x$alsa_found" = "xno" ; then - ifelse([$3], , :, [$3]) - CFLAGS="$alsa_save_CFLAGS" - LDFLAGS="$alsa_save_LDFLAGS" - LIBS="$alsa_save_LIBS" - ALSA_CFLAGS="" - ALSA_LIBS="" -fi - -dnl That should be it. Now just export out symbols: -AC_SUBST(ALSA_CFLAGS) -AC_SUBST(ALSA_LIBS) -]) - -AH_TOP([ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -]) - -AH_BOTTOM([#if C_ATTRIBUTE_ALWAYS_INLINE -#define INLINE inline __attribute__((always_inline)) -#else -#define INLINE inline -#endif]) - -AH_BOTTOM([#if C_ATTRIBUTE_FASTCALL -#define DB_FASTCALL __attribute__((fastcall)) -#else -#define DB_FASTCALL -#endif]) - - -AH_BOTTOM([#if C_HAS_ATTRIBUTE -#define GCC_ATTRIBUTE(x) __attribute__ ((x)) -#else -#define GCC_ATTRIBUTE(x) /* attribute not supported */ -#endif]) - -AH_BOTTOM([#if C_HAS_BUILTIN_EXPECT -#define GCC_UNLIKELY(x) __builtin_expect((x),0) -#else -#define GCC_UNLIKELY(x) (x) -#endif]) - -AH_BOTTOM([ -typedef double Real64; - -#if SIZEOF_UNSIGNED_CHAR != 1 -# error "sizeof (unsigned char) != 1" -#else - typedef unsigned char Bit8u; - typedef signed char Bit8s; -#endif - -#if SIZEOF_UNSIGNED_SHORT != 2 -# error "sizeof (unsigned short) != 2" -#else - typedef unsigned short Bit16u; - typedef signed short Bit16s; -#endif - -#if SIZEOF_UNSIGNED_INT == 4 - typedef unsigned int Bit32u; - typedef signed int Bit32s; -#elif SIZEOF_UNSIGNED_LONG == 4 - typedef unsigned long Bit32u; - typedef signed long Bit32s; -#else -# error "can't find sizeof(type) of 4 bytes!" -#endif - -#if SIZEOF_UNSIGNED_LONG == 8 - typedef unsigned long Bit64u; - typedef signed long Bit64s; -#elif SIZEOF_UNSIGNED_LONG_LONG == 8 - typedef unsigned long long Bit64u; - typedef signed long long Bit64s; -#else -# error "can't find data type of 8 bytes" -#endif - -#if SIZEOF_INT_P == 4 - typedef Bit32u Bitu; - typedef Bit32s Bits; - #else - typedef Bit64u Bitu; - typedef Bit64s Bits; - #endif - -]) +dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS +dnl +AC_DEFUN(AM_PATH_SDL, +[dnl +dnl Get the cflags and libraries from the sdl-config script +dnl +AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], + sdl_prefix="$withval", sdl_prefix="") +AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], + sdl_exec_prefix="$withval", sdl_exec_prefix="") +AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], + , enable_sdltest=yes) + + if test x$sdl_exec_prefix != x ; then + sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_args="$sdl_args --prefix=$sdl_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_prefix/bin/sdl-config + fi + fi + + AC_PATH_PROG(SDL_CONFIG, sdl-config, no) + min_sdl_version=ifelse([$1], ,0.11.0,$1) + AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) + no_sdl="" + if test "$SDL_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` + SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` + + sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" +dnl +dnl Now check if the installed SDL is sufficiently new. (Also sanity +dnl checks the results of sdl-config to some extent +dnl + rm -f conf.sdltest + AC_TRY_RUN([ +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); + printf("*** to point to the correct copy of sdl-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$SDL_CONFIG" = "no" ; then + echo "*** The sdl-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL_CONFIG environment variable to the" + echo "*** full path to sdl-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + AC_TRY_LINK([ +#include +#include "SDL.h" +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) + rm -f conf.sdltest +]) diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..f04491a --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,992 @@ +# aclocal.m4 generated automatically by aclocal 1.6.1 -*- Autoconf -*- + +# Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS +dnl +AC_DEFUN(AM_PATH_SDL, +[dnl +dnl Get the cflags and libraries from the sdl-config script +dnl +AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], + sdl_prefix="$withval", sdl_prefix="") +AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], + sdl_exec_prefix="$withval", sdl_exec_prefix="") +AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], + , enable_sdltest=yes) + + if test x$sdl_exec_prefix != x ; then + sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_args="$sdl_args --prefix=$sdl_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_prefix/bin/sdl-config + fi + fi + + AC_PATH_PROG(SDL_CONFIG, sdl-config, no) + min_sdl_version=ifelse([$1], ,0.11.0,$1) + AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) + no_sdl="" + if test "$SDL_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` + SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` + + sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" +dnl +dnl Now check if the installed SDL is sufficiently new. (Also sanity +dnl checks the results of sdl-config to some extent +dnl + rm -f conf.sdltest + AC_TRY_RUN([ +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); + printf("*** to point to the correct copy of sdl-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$SDL_CONFIG" = "no" ; then + echo "*** The sdl-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL_CONFIG environment variable to the" + echo "*** full path to sdl-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + AC_TRY_LINK([ +#include +#include "SDL.h" +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) + rm -f conf.sdltest +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# This macro actually does too much some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 8 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +AC_PREREQ([2.52]) + +# Autoconf 2.50 wants to disallow AM_ names. We explicitly allow +# the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl + AC_SUBST([PACKAGE], [AC_PACKAGE_TARNAME])dnl + AC_SUBST([VERSION], [AC_PACKAGE_VERSION])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_MISSING_PROG(AMTAR, tar) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl + +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_][CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_][CC], + defn([AC_PROG_][CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_][CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_][CXX], + defn([AC_PROG_][CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) +]) + +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.6"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.6.1])]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright 2001, 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 2 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# +# Check to make sure that the build environment is sane. +# + +# Copyright 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 3 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# -*- Autoconf -*- + + +# Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 3 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# AM_AUX_DIR_EXPAND + +# Copyright 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +# Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50]) + +AC_DEFUN([AM_AUX_DIR_EXPAND], [ +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. + +# Copyright 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"$am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# AM_PROG_INSTALL_STRIP + +# Copyright 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# serial 4 -*- Autoconf -*- + +# Copyright 1999, 2000, 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'] + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[rm -f .deps 2>/dev/null +mkdir .deps 2>/dev/null +if test -d .deps; then + DEPDIR=.deps +else + # MS-DOS does not allow filenames that begin with a dot. + DEPDIR=_deps +fi +rmdir .deps 2>/dev/null +AC_SUBST([DEPDIR]) +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking Speeds up one-time builds + --enable-dependency-tracking Do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH]) +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +#serial 2 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + if (sed 1q $mf | fgrep 'generated by automake') > /dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n -e '/^U = / s///p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n -e ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Copyright 2001 Free Software Foundation, Inc. -*- Autoconf -*- + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 2 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +doit: + @echo done +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST(am__include) +AC_SUBST(am__quote) +AC_MSG_RESULT($_am_result) +rm -f confinc confmf +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright 1997, 2000, 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 5 + +AC_PREREQ(2.52) + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE]) +AC_SUBST([$1_FALSE]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([conditional \"$1\" was never defined. +Usually this means the macro was only invoked conditionally.]) +fi])]) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. -*- Autoconf -*- + +# Copyright 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_PREREQ([2.52]) + +# serial 6 + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. We must strip everything past the first ":", +# and everything past the last "/". + +# _AM_DIRNAME(PATH) +# ----------------- +# Like AS_DIRNAME, only do it during macro expansion +AC_DEFUN([_AM_DIRNAME], + [m4_if(regexp([$1], [^.*[^/]//*[^/][^/]*/*$]), -1, + m4_if(regexp([$1], [^//\([^/]\|$\)]), -1, + m4_if(regexp([$1], [^/.*]), -1, + [.], + patsubst([$1], [^\(/\).*], [\1])), + patsubst([$1], [^\(//\)\([^/].*\|$\)], [\1])), + patsubst([$1], [^\(.*[^/]\)//*[^/][^/]*/*$], [\1]))[]dnl +])# _AM_DIRNAME + + +# The stamp files are numbered to have different names. +# We could number them on a directory basis, but that's additional +# complications, let's have a unique counter. +m4_define([_AM_STAMP_Count], [0]) + + +# _AM_STAMP(HEADER) +# ----------------- +# The name of the stamp file for HEADER. +AC_DEFUN([_AM_STAMP], +[m4_define([_AM_STAMP_Count], m4_incr(_AM_STAMP_Count))dnl +AS_ESCAPE(_AM_DIRNAME(patsubst([$1], + [:.*])))/stamp-h[]_AM_STAMP_Count]) + + +# _AM_CONFIG_HEADER(HEADER[:SOURCES], COMMANDS, INIT-COMMANDS) +# ------------------------------------------------------------ +# We used to try to get a real timestamp in stamp-h. But the fear is that +# that will cause unnecessary cvs conflicts. +AC_DEFUN([_AM_CONFIG_HEADER], +[# Add the stamp file to the list of files AC keeps track of, +# along with our hook. +AC_CONFIG_HEADERS([$1], + [# update the timestamp +echo 'timestamp for $1' >"_AM_STAMP([$1])" +$2], + [$3]) +])# _AM_CONFIG_HEADER + + +# AM_CONFIG_HEADER(HEADER[:SOURCES]..., COMMANDS, INIT-COMMANDS) +# -------------------------------------------------------------- +AC_DEFUN([AM_CONFIG_HEADER], +[AC_FOREACH([_AM_File], [$1], [_AM_CONFIG_HEADER(_AM_File, [$2], [$3])]) +])# AM_CONFIG_HEADER + diff --git a/autogen.sh b/autogen.sh index 2b2e66c..1c139b8 100644 --- a/autogen.sh +++ b/autogen.sh @@ -1,14 +1,18 @@ -#!/bin/sh - -echo "Generating build information using aclocal, autoheader, automake and autoconf" -echo "This may take a while ..." - -# Regenerate configuration files. - -aclocal -autoheader -automake --include-deps --add-missing --copy -autoconf - -echo "Now you are ready to run ./configure." -echo "You can also run ./configure --help for extra features to enable/disable." +#!/bin/sh +# +echo "Generating build information using aclocal, auotheader, automake and autoconf" +echo "This may take a while ..." + +# Touch the timestamps on all the files since CVS messes them up +directory=`dirname $0` +touch $directory/configure.in + +# Regenerate configuration files + +aclocal +autoheader +automake --gnits --include-deps --add-missing --copy +autoconf + +cp $directory/settings.h.cvs $directory/settings.h +echo "Now you are ready to run ./configure also check settings.h for extra build settings" diff --git a/config.guess b/config.guess new file mode 100644 index 0000000..71de137 --- /dev/null +++ b/config.guess @@ -0,0 +1,1368 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. + +timestamp='2001-03-16' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner . +# Please send patches to . +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int dummy(){}" > $dummy.c + for c in cc gcc c89 ; do + ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 + if test $? = 0 ; then + CC_FOR_BUILD="$c"; break + fi + done + rm -f $dummy.c $dummy.o $dummy.rel + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # Netbsd (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # Determine the machine/vendor (is the vendor relevant). + case "${UNAME_MACHINE}" in + amiga) machine=m68k-unknown ;; + arm32) machine=arm-unknown ;; + atari*) machine=m68k-atari ;; + sun3*) machine=m68k-sun ;; + mac68k) machine=m68k-apple ;; + macppc) machine=powerpc-apple ;; + hp3[0-9][05]) machine=m68k-hp ;; + ibmrt|romp-ibm) machine=romp-ibm ;; + *) machine=${UNAME_MACHINE}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE}" in + i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i?86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + case "${HPUX_REV}" in + 11.[0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + esac ;; + esac + fi ;; + esac + if [ "${HP_ARCH}" = "" ]; then + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + hppa*:OpenBSD:*:*) + echo hppa-unknown-openbsd + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | i?86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + cat >$dummy.c < /* for printf() prototype */ +int main (int argc, char *argv[]) { +#else +int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __MIPSEB__ + printf ("%s-unknown-linux-gnu\n", argv[1]); +#endif +#ifdef __MIPSEL__ + printf ("%sel-unknown-linux-gnu\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + ;; + ppc:Linux:*:*) + # Determine Lib Version + cat >$dummy.c < +#if defined(__GLIBC__) +extern char __libc_version[]; +extern char __libc_release[]; +#endif +main(argc, argv) + int argc; + char *argv[]; +{ +#if defined(__GLIBC__) + printf("%s %s\n", __libc_version, __libc_release); +#else + printf("unknown\n"); +#endif + return 0; +} +EOF + LIBC="" + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy | grep 1\.99 > /dev/null + if test "$?" = 0 ; then LIBC="libc1" ; fi + fi + rm -f $dummy.c $dummy + echo powerpc-unknown-linux-gnu${LIBC} + exit 0 ;; + alpha:Linux:*:*) + cat <$dummy.s + .data + \$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + .text + .globl main + .align 4 + .ent main + main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + LIBC="" + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `./$dummy` in + 0-0) UNAME_MACHINE="alpha" ;; + 1-0) UNAME_MACHINE="alphaev5" ;; + 1-1) UNAME_MACHINE="alphaev56" ;; + 1-101) UNAME_MACHINE="alphapca56" ;; + 2-303) UNAME_MACHINE="alphaev6" ;; + 2-307) UNAME_MACHINE="alphaev67" ;; + esac + objdump --private-headers $dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i?86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_supported_emulations=`cd /; ld --help 2>&1 \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + i?86linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 + ;; + elf_i?86) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + i?86coff) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 + ;; + esac + # Either a pre-BFD a.out linker (linux-gnuoldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + test -z "$ld_supported_emulations" && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >$dummy.c < +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; +# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions +# are messed up and put the nodename in both sysname and nodename. + i?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + i?86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i?86:*:5:7*) + # Fixed at (any) Pentium or better + UNAME_MACHINE=i586 + if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then + echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i?86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i?86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_MACHINE=pc + fi + echo `uname -p`-${UNAME_MACHINE}-nto-qnx + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[KW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i?86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..072298a --- /dev/null +++ b/config.h.in @@ -0,0 +1,65 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define as `__inline' if that's what the C compiler calls it, or to nothing + if it is not supported. */ +#undef inline + +/* Define to `unsigned' if does not define. */ +#undef size_t diff --git a/config.sub b/config.sub new file mode 100644 index 0000000..f365797 --- /dev/null +++ b/config.sub @@ -0,0 +1,1443 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-03-07' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dsp16xx \ + | fr30 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el | mips64vr4300 \ + | mips64vr4300el | mips64vr5000 | mips64vr5000el \ + | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ + | mipsisa32 | mipsisa64 \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ + | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ + | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3d) + basic_machine=alpha-cray + os=-unicos + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh3eb | sh4eb) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100644 index 0000000..cb5c2b5 --- /dev/null +++ b/configure @@ -0,0 +1,5512 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.53a for dosbox 0.50. +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# NLS nuisances. +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + +(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && + { $as_unset LANG || test "${LANG+set}" != set; } || + { LANG=C; export LANG; } +(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && + { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || + { LC_ALL=C; export LC_ALL; } +(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && + { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || + { LC_TIME=C; export LC_TIME; } +(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && + { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || + { LC_CTYPE=C; export LC_CTYPE; } +(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && + { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || + { LANGUAGE=C; export LANGUAGE; } +(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && + { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || + { LC_COLLATE=C; export LC_COLLATE; } +(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && + { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || + { LC_NUMERIC=C; export LC_NUMERIC; } +(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && + { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || + { LC_MESSAGES=C; export LC_MESSAGES; } + + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conftest.sh + echo "exit 0" >>conftest.sh + chmod +x conftest.sh + if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conftest.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME='dosbox' +PACKAGE_TARNAME='dosbox' +PACKAGE_VERSION='0.50' +PACKAGE_STRING='dosbox 0.50' +PACKAGE_BUGREPORT='' + +ac_unique_file="README" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures dosbox 0.50 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of dosbox 0.50:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking Speeds up one-time builds + --enable-dependency-tracking Do not reject slow dependency extractors + --disable-sdltest Do not try to compile and run a test SDL program + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-sdl-prefix=PFX Prefix where SDL is installed (optional) + --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF +dosbox configure 0.50 +generated by GNU Autoconf 2.53a + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by dosbox $as_me 0.50, which was +generated by GNU Autoconf 2.53a. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell meta-characters. +ac_configure_args= +ac_sep= +for ac_arg +do + case $ac_arg in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n ) continue ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + ac_sep=" " ;; + esac + # Get rid of the leading space. +done + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core core.* *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Make sure we can run config.sub. +$ac_config_sub sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 +echo "$as_me: error: cannot run $ac_config_sub" >&2;} + { (exit 1); exit 1; }; } + +echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6 +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_build_alias=$build_alias +test -z "$ac_cv_build_alias" && + ac_cv_build_alias=`$ac_config_guess` +test -z "$ac_cv_build_alias" && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6 +build=$ac_cv_build +build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6 +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_host_alias=$host_alias +test -z "$ac_cv_host_alias" && + ac_cv_host_alias=$ac_cv_build_alias +ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6 +host=$ac_cv_host +host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking target system type" >&5 +echo $ECHO_N "checking target system type... $ECHO_C" >&6 +if test "${ac_cv_target+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_target_alias=$target_alias +test "x$ac_cv_target_alias" = "x" && + ac_cv_target_alias=$ac_cv_host_alias +ac_cv_target=`$ac_config_sub $ac_cv_target_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_target" >&5 +echo "${ECHO_T}$ac_cv_target" >&6 +target=$ac_cv_target +target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +am__api_version="1.6" +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +test "$program_prefix" != NONE && + program_transform_name="s,^,$program_prefix,;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$,$program_suffix,;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm conftest.sed + + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$AWK" && break +done + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="${MAKE}"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + # test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +# Define the identity of the package. + PACKAGE=dosbox + VERSION=0.50 + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +install_sh=${install_sh-"$am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. + + + +# Add the stamp file to the list of files AC keeps track of, +# along with our hook. + ac_config_headers="$ac_config_headers config.h" + + + + + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="${MAKE}"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH" >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH" >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output" >&5 +echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +for ac_file in `ls a_out.exe a.exe conftest.exe 2>/dev/null; + ls a.out conftest 2>/dev/null; + ls a.* conftest.* 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + a.out ) # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool --akim. + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables" >&5 +echo "$as_me: error: C compiler cannot create executables" >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link" >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile" >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_prog_cc_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + ''\ + '#include ' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +$ac_declaration +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_declaration +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +rm -f .deps 2>/dev/null +mkdir .deps 2>/dev/null +if test -d .deps; then + DEPDIR=.deps +else + # MS-DOS does not allow filenames that begin with a dot. + DEPDIR=_deps +fi +rmdir .deps 2>/dev/null + + + ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +doit: + @echo done +END +# If we don't find an include directive, just comment out the code. +echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6 +rm -f confinc confmf + +# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval="$enable_dependency_tracking" + +fi; +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + + +depcc="$CC" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check" >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_prog_cxx_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + ''\ + '#include ' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +$ac_declaration +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_declaration +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + +SDL_VERSION=1.2.0 + + +# Check whether --with-sdl-prefix or --without-sdl-prefix was given. +if test "${with_sdl_prefix+set}" = set; then + withval="$with_sdl_prefix" + sdl_prefix="$withval" +else + sdl_prefix="" +fi; + +# Check whether --with-sdl-exec-prefix or --without-sdl-exec-prefix was given. +if test "${with_sdl_exec_prefix+set}" = set; then + withval="$with_sdl_exec_prefix" + sdl_exec_prefix="$withval" +else + sdl_exec_prefix="" +fi; +# Check whether --enable-sdltest or --disable-sdltest was given. +if test "${enable_sdltest+set}" = set; then + enableval="$enable_sdltest" + +else + enable_sdltest=yes +fi; + + if test x$sdl_exec_prefix != x ; then + sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_args="$sdl_args --prefix=$sdl_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_prefix/bin/sdl-config + fi + fi + + # Extract the first word of "sdl-config", so it can be a program name with args. +set dummy sdl-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_SDL_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $SDL_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_SDL_CONFIG="$SDL_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SDL_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_SDL_CONFIG" && ac_cv_path_SDL_CONFIG="no" + ;; +esac +fi +SDL_CONFIG=$ac_cv_path_SDL_CONFIG + +if test -n "$SDL_CONFIG"; then + echo "$as_me:$LINENO: result: $SDL_CONFIG" >&5 +echo "${ECHO_T}$SDL_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + min_sdl_version=$SDL_VERSION + echo "$as_me:$LINENO: checking for SDL - version >= $min_sdl_version" >&5 +echo $ECHO_N "checking for SDL - version >= $min_sdl_version... $ECHO_C" >&6 + no_sdl="" + if test "$SDL_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` + SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` + + sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + rm -f conf.sdltest + if test "$cross_compiling" = yes; then + echo $ac_n "cross compiling; assumed OK... $ac_c" +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); + printf("*** to point to the correct copy of sdl-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +( exit $ac_status ) +no_sdl=yes +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + : + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + if test "$SDL_CONFIG" = "no" ; then + echo "*** The sdl-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL_CONFIG environment variable to the" + echo "*** full path to sdl-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#include +#include "SDL.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 + echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl-config script: $SDL_CONFIG" +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + { { echo "$as_me:$LINENO: error: *** SDL version $SDL_VERSION not found!" >&5 +echo "$as_me: error: *** SDL version $SDL_VERSION not found!" >&2;} + { (exit 1); exit 1; }; } + + fi + + + rm -f conf.sdltest + +LIBS="$LIBS $SDL_LIBS" +CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" + + +echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + } +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_c_const=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6 +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for inline" >&5 +echo $ECHO_N "checking for inline... $ECHO_C" >&6 +if test "${ac_cv_c_inline+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_inline=$ac_kw; break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 +echo "${ECHO_T}$ac_cv_c_inline" >&6 +case $ac_cv_c_inline in + inline | yes) ;; + no) +cat >>confdefs.h <<\_ACEOF +#define inline +_ACEOF + ;; + *) cat >>confdefs.h <<_ACEOF +#define inline $ac_cv_c_inline +_ACEOF + ;; +esac + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#include +#include +#include + +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +eval "$as_ac_Header=no" +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +echo "$as_me:$LINENO: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6 +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +if ((size_t *) 0) + return 0; +if (sizeof (size_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_type_size_t=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6 +if test $ac_cv_type_size_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned +_ACEOF + +fi + +echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5 +echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6 +if test "${ac_cv_struct_tm+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#include + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +struct tm *tp; tp->tm_sec; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_struct_tm=time.h +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_struct_tm=sys/time.h +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 +echo "${ECHO_T}$ac_cv_struct_tm" >&6 +if test $ac_cv_struct_tm = sys/time.h; then + +cat >>confdefs.h <<\_ACEOF +#define TM_IN_SYS_TIME 1 +_ACEOF + +fi + + + + +#Always include the standard include dir in all makefiless + + ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_16/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/ints/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc/Makefile include/Makefile" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if cmp -s $cache_file confcache; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# NLS nuisances. +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + +(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && + { $as_unset LANG || test "${LANG+set}" != set; } || + { LANG=C; export LANG; } +(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && + { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || + { LC_ALL=C; export LC_ALL; } +(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && + { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || + { LC_TIME=C; export LC_TIME; } +(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && + { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || + { LC_CTYPE=C; export LC_CTYPE; } +(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && + { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || + { LANGUAGE=C; export LANGUAGE; } +(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && + { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || + { LC_COLLATE=C; export LC_COLLATE; } +(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && + { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || + { LC_NUMERIC=C; export LC_NUMERIC; } +(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && + { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || + { LC_MESSAGES=C; export LC_MESSAGES; } + + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conftest.sh + echo "exit 0" >>conftest.sh + chmod +x conftest.sh + if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conftest.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by dosbox $as_me 0.50, which was +generated by GNU Autoconf 2.53a. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +dosbox config.status 0.50 +configured by $0, generated by GNU Autoconf 2.53a, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion" + exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;; +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/cpu/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/cpu/Makefile" ;; + "src/cpu/core_16/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/cpu/core_16/Makefile" ;; + "src/debug/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/debug/Makefile" ;; + "src/dos/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/dos/Makefile" ;; + "src/fpu/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/fpu/Makefile" ;; + "src/gui/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/gui/Makefile" ;; + "src/hardware/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/hardware/Makefile" ;; + "src/ints/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/ints/Makefile" ;; + "src/misc/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/misc/Makefile" ;; + "src/shell/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/shell/Makefile" ;; + "src/platform/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/platform/Makefile" ;; + "src/platform/visualc/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/platform/visualc/Makefile" ;; + "visualc/Makefile" ) CONFIG_FILES="$CONFIG_FILES visualc/Makefile" ;; + "include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. +: ${TMPDIR=/tmp} +{ + tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=$TMPDIR/cs$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in $TMPDIR" >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@build@,$build,;t t +s,@build_cpu@,$build_cpu,;t t +s,@build_vendor@,$build_vendor,;t t +s,@build_os@,$build_os,;t t +s,@host@,$host,;t t +s,@host_cpu@,$host_cpu,;t t +s,@host_vendor@,$host_vendor,;t t +s,@host_os@,$host_os,;t t +s,@target@,$target,;t t +s,@target_cpu@,$target_cpu,;t t +s,@target_vendor@,$target_vendor,;t t +s,@target_os@,$target_os,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@PACKAGE@,$PACKAGE,;t t +s,@VERSION@,$VERSION,;t t +s,@ACLOCAL@,$ACLOCAL,;t t +s,@AUTOCONF@,$AUTOCONF,;t t +s,@AUTOMAKE@,$AUTOMAKE,;t t +s,@AUTOHEADER@,$AUTOHEADER,;t t +s,@MAKEINFO@,$MAKEINFO,;t t +s,@AMTAR@,$AMTAR,;t t +s,@install_sh@,$install_sh,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t +s,@AWK@,$AWK,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@DEPDIR@,$DEPDIR,;t t +s,@am__include@,$am__include,;t t +s,@am__quote@,$am__quote,;t t +s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t +s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t +s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t +s,@CCDEPMODE@,$CCDEPMODE,;t t +s,@CPP@,$CPP,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@CXXDEPMODE@,$CXXDEPMODE,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@SDL_CONFIG@,$SDL_CONFIG,;t t +s,@SDL_CFLAGS@,$SDL_CFLAGS,;t t +s,@SDL_LIBS@,$SDL_LIBS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if egrep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # egrep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if cmp -s $ac_file $tmp/config.h 2>/dev/null; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi + # Run the commands associated with the file. + case $ac_file in + config.h ) # update the timestamp +echo 'timestamp for config.h' >"./stamp-h1" + ;; + esac +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + if (sed 1q $mf | fgrep 'generated by automake') > /dev/null 2>&1; then + dirpart=`(dirname "$mf") 2>/dev/null || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + else + continue + fi + grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n -e '/^U = / s///p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n -e ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`(dirname "$file") 2>/dev/null || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p $dirpart/$fdir + else + as_dir=$dirpart/$fdir + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 +echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} + { (exit 1); exit 1; }; }; } + + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + exec 5>/dev/null + $SHELL $CONFIG_STATUS || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/configure.in b/configure.in index 0bdf342..395ff76 100644 --- a/configure.in +++ b/configure.in @@ -1,519 +1,61 @@ -dnl Init. -AC_INIT(dosbox,0.72) -AC_PREREQ(2.50) -AC_CONFIG_SRCDIR(README) - -dnl Detect the canonical host and target build environment -AC_CANONICAL_HOST -AC_CANONICAL_TARGET - -dnl Setup for automake -AM_INIT_AUTOMAKE -AM_CONFIG_HEADER(config.h) - -dnl Checks for programs. -AC_PROG_MAKE_SET -AC_PROG_CC -AC_PROG_CPP -AC_PROG_CXX -AC_PROG_INSTALL -AC_PROG_RANLIB - -dnl Some needed libaries for OS2 -dnl perharps join this with the other target depended checks. move them upwards -if test x$target = xi386-pc-os2-emx ; then - CXXFLAGS="$CXXFLAGS -Zmt" - LDFLAGS="$LDFLAGS -Zomf -Zmt" - LIBS="$LIBS -los2me" -fi - -dnl Check for SDL -SDL_VERSION=1.2.0 -AM_PATH_SDL($SDL_VERSION, - :, - AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]) -) -LIBS="$LIBS $SDL_LIBS" -CPPFLAGS="$CPPFLAGS $SDL_CFLAGS" - -dnl Check if SDL is 1.2.x (1.3 not supported) -AC_MSG_CHECKING([SDL version only being 1.2.X]) -AC_COMPILE_IFELSE([ -#include "SDL.h" -void blah(){ -#if SDL_MINOR_VERSION != 2 -#error "Only SDL 1.2 supported" -#endif -; -} -],AC_MSG_RESULT([yes]),[ - AC_MSG_RESULT([no]) - AC_MSG_ERROR([Only libSDL 1.2.X supported])]) - -dnl Checks for header files. - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_C_INLINE -AC_TYPE_SIZE_T -AC_STRUCT_TM -AC_CHECK_SIZEOF(unsigned char) -AC_CHECK_SIZEOF(unsigned short) -AC_CHECK_SIZEOF(unsigned int) -AC_CHECK_SIZEOF(unsigned long) -AC_CHECK_SIZEOF(unsigned long long) -AC_CHECK_SIZEOF(int *) - -dnl some semi complex check for sys/socket so it works on darwin as well -AC_CHECK_HEADERS([stdlib.h sys/types.h]) -AC_CHECK_HEADERS([sys/socket.h netinet/in.h pwd.h], [], [], -[#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif -]) - -dnl check for the socklen_t (darwin doesn't always have it) -AC_COMPILE_IFELSE([ -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -],[],[AC_DEFINE([socklen_t],[int],[Define to `int` if you don't have socklen_t])]) - -AC_MSG_CHECKING(if environ can be included) -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ -#include -#include ]],[[*environ;]])], -[AC_MSG_RESULT(yes);AC_DEFINE(ENVIRON_INCLUDED,1,[environ can be included])],AC_MSG_RESULT(no)) - -AC_MSG_CHECKING(if environ can be linked) -AC_LINK_IFELSE([AC_LANG_PROGRAM([[extern char ** environ;]],[[*environ;]])], -[AC_MSG_RESULT(yes);AC_DEFINE(ENVIRON_LINKED,1,[environ can be linked])],AC_MSG_RESULT(no)) - -AC_MSG_CHECKING([if dirent includes d_type]) -AC_COMPILE_IFELSE([ -#include -#include -void blah(){ -struct dirent d_test; -d_test.d_type = 0; -}],[AC_MSG_RESULT(yes);AC_DEFINE(DIRENT_HAS_D_TYPE,1,[struct dirent has d_type])],AC_MSG_RESULT(no)) - - -dnl Check for powf -if test x$target = xi386-pc-os2-emx ; then - AC_MSG_CHECKING(for powf in libm); - LIBS_BACKUP=$LIBS; - LIBS="$LIBS -lm"; - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]],[[ - powf(1.0f, 1.0f); - ]])], [AC_MSG_RESULT(yes)], [AC_DEFINE([DB_HAVE_NO_POWF],[1],[libm doesn't include powf])]) - LIBS=$LIBS_BACKUP -else -AC_CHECK_LIB([m],[powf],,[AC_DEFINE([DB_HAVE_NO_POWF],[1],[libm doesn't include powf])]) -fi - -dnl Checks for libraries. - -#Check if the compiler support attributes -AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures.]) -AC_MSG_CHECKING(if compiler allows __attribute__) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -typedef struct { } __attribute__((packed)) junk;]], -[[ ]])],[ AC_MSG_RESULT(yes);AC_DEFINE(C_HAS_ATTRIBUTE)],AC_MSG_RESULT(no)) - - -#Check if the compiler supports certain attributes -OLDCFLAGS="$CFLAGS" -CFLAGS="-Werror" - -AH_TEMPLATE([C_ATTRIBUTE_ALWAYS_INLINE],[Determines if the compilers supports always_inline attribute.]) -AC_MSG_CHECKING(if compiler allows __attribute__((always_inline)) ) -AC_COMPILE_IFELSE([ void __attribute__((always_inline)) test(){} -],[ AC_MSG_RESULT(yes);AC_DEFINE(C_ATTRIBUTE_ALWAYS_INLINE)],AC_MSG_RESULT(no)) - -AH_TEMPLATE([C_ATTRIBUTE_FASTCALL],[Determines if the compilers supports fastcall attribute.]) -AC_MSG_CHECKING(if compiler allows __attribute__((fastcall)) ) -AC_COMPILE_IFELSE([ void __attribute__((fastcall)) test(){} -],[ AC_MSG_RESULT(yes);AC_DEFINE(C_ATTRIBUTE_FASTCALL)],AC_MSG_RESULT(no)) - - -CFLAGS="$OLDCFLAGS" - - -#Check if the compiler supports __builtin_expect -#Switch language to c++ -AC_LANG_PUSH(C++) -AH_TEMPLATE([C_HAS_BUILTIN_EXPECT],[Determines if the compilers supports __builtin_expect for branch prediction.]) -AC_MSG_CHECKING(if compiler allows __builtin_expect) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[ -int x=10;if( __builtin_expect ((x==1),0) ) ; -]])], [ AC_MSG_RESULT(yes);AC_DEFINE(C_HAS_BUILTIN_EXPECT)],AC_MSG_RESULT(no)) -#switch language back -AC_LANG_POP(C++) - -dnl enable disable alsa and pass it's cflags to CXXFLAGS -AC_ARG_ENABLE(alsa-midi, -AC_HELP_STRING([--enable-alsa-midi],[compile with alsa midi support (default yes)]), -[ case "${enableval}" in - yes) alsa_midi=true;; - no) alsa_midi=false;; -esac], -[alsa_midi=true]) -if test x$alsa_midi = xtrue ; then - AM_PATH_ALSA(0.9.0, AC_DEFINE(HAVE_ALSA,1,[Define to 1 to use ALSA for MIDI]) , : ) - CXXFLAGS="$CXXFLAGS $ALSA_CFLAGS" -fi - -#Check for big endian machine, should #define WORDS_BIGENDIAN if so -AC_C_BIGENDIAN - -#Features to enable/disable -AH_TEMPLATE(C_DEBUG,[Define to 1 to enable internal debugger, requires libcurses]) -AH_TEMPLATE(C_HEAVY_DEBUG,[Define to 1 to enable heavy debugging, also have to enable C_DEBUG]) -AC_ARG_ENABLE(debug,AC_HELP_STRING([--enable-debug],[Enable debug mode]),[ - AC_CHECK_HEADER(curses.h,have_curses_h=yes,) - AC_CHECK_LIB(curses, initscr, have_curses_lib=yes, , ) - AC_CHECK_LIB(ncurses, initscr, have_ncurses_lib=yes, , ) - AC_CHECK_LIB(pdcurses, initscr, have_pdcurses_lib=yes, , ) - - if test x$enable_debug = xno; then - AC_MSG_RESULT([Debugger not enabled]) - elif test x$have_curses_lib = xyes -a x$have_curses_h = xyes ; then - LIBS="$LIBS -lcurses" - AC_DEFINE(C_DEBUG,1) - if test x$enable_debug = xheavy ; then - AC_DEFINE(C_HEAVY_DEBUG,1) - fi - elif test x$have_ncurses_lib = xyes -a x$have_curses_h = xyes ; then - LIBS="$LIBS -lncurses" - AC_DEFINE(C_DEBUG,1) - if test x$enable_debug = xheavy ; then - AC_DEFINE(C_HEAVY_DEBUG,1) - fi - elif test x$have_pdcurses_lib = xyes -a x$have_curses_h = xyes ; then - LIBS="$LIBS -lpdcurses" - AC_DEFINE(C_DEBUG,1) - if test x$enable_debug = xheavy ; then - AC_DEFINE(C_HEAVY_DEBUG,1) - fi - else - AC_MSG_ERROR([Can't find curses, which is required for debug mode]) - fi -],) - -AH_TEMPLATE(C_CORE_INLINE,[Define to 1 to use inlined memory functions in cpu core]) -AC_ARG_ENABLE(core-inline,AC_HELP_STRING([--enable-core-inline],[Enable inlined memory handling in CPU Core]),[ - if test x$enable_core_inline = xyes ; then - AC_MSG_RESULT([enabling inlined memory handling in CPU Core]) - AC_DEFINE(C_CORE_INLINE,1) - fi -],) - - -dnl The target cpu checks for dynamic cores -AH_TEMPLATE(C_TARGETCPU,[The type of cpu this target has]) -AC_MSG_CHECKING(for target cpu type) -case "$target_cpu" in - x86_64 | amd64) - AC_DEFINE(C_TARGETCPU,X86_64) - AC_MSG_RESULT(x86-64 bit compatible) - c_targetcpu="x86_64" - c_unalignedmemory=yes - ;; - i?86) - AC_DEFINE(C_TARGETCPU,X86) - AC_MSG_RESULT(x86 compatible) - c_targetcpu="x86" - c_unalignedmemory=yes - ;; - powerpc*) - AC_DEFINE(C_TARGETCPU,POWERPC) - AC_MSG_RESULT(Power PC) - c_targetcpu="powerpc" - c_unalignedmemory=yes - ;; - m68k*) - AC_DEFINE(C_TARGETCPU,M68K) - AC_MSG_RESULT(Motorola 68000) - c_targetcpu="m68k" - c_unalignedmemory=yes - ;; - *) - AC_DEFINE(C_TARGETCPU,UNKNOWN) - AC_MSG_RESULT(unknown) - c_unalignedmemory=no - ;; -esac - -AC_ARG_ENABLE(dynamic-core,AC_HELP_STRING([--disable-dynamic-core],[Disable all dynamic cores]),,enable_dynamic_core=yes) - -AH_TEMPLATE(C_DYNAMIC_X86,[Define to 1 to use x86 dynamic cpu core]) -AC_ARG_ENABLE(dynamic-x86,AC_HELP_STRING([--disable-dynamic-x86],[Disable x86 dynamic cpu core]),,enable_dynamic_x86=yes) -AC_MSG_CHECKING(whether x86 dynamic cpu core will be enabled) -if test x$enable_dynamic_x86 = xno -o x$enable_dynamic_core = xno; then - AC_MSG_RESULT(no) -else - if test x$c_targetcpu = xx86 ; then - AC_DEFINE(C_DYNAMIC_X86,1) - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT(no) - fi -fi - -AH_TEMPLATE(C_DYNREC,[Define to 1 to use recompiling cpu core. Can not be used together with the dynamic-x86 core]) -AC_ARG_ENABLE(dynrec,AC_HELP_STRING([--disable-dynrec],[Disable recompiling cpu core]),,enable_dynrec=yes) -AC_MSG_CHECKING(whether recompiling cpu core will be enabled) -if test x$enable_dynrec = xno -o x$enable_dynamic_core = xno; then - AC_MSG_RESULT(no) -else -dnl x86 only enable it if dynamic-x86 is disabled. - if test x$c_targetcpu = xx86 ; then - if test x$enable_dynamic_x86 = xno ; then - AC_DEFINE(C_DYNREC,1) - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT([no, using dynamic-x86]) - fi - else - if test x$c_targetcpu = xx86_64 ; then - AC_DEFINE(C_DYNREC,1) - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT(no) - fi - fi -fi - -AH_TEMPLATE(C_FPU,[Define to 1 to enable floating point emulation]) -AC_ARG_ENABLE(fpu,AC_HELP_STRING([--disable-fpu],[Disable fpu support]),,enable_fpu=yes) -AC_MSG_CHECKING(whether fpu emulation will be enabled) -if test x$enable_fpu = xyes ; then - AC_MSG_RESULT(yes) - AC_DEFINE(C_FPU,1) -else - AC_MSG_RESULT(no) -fi - -AH_TEMPLATE(C_FPU_X86,[Define to 1 to use a x86 assembly fpu core]) -AC_ARG_ENABLE(fpu-x86,AC_HELP_STRING([--disable-fpu-x86],[Disable x86 assembly fpu core]),,enable_fpu_x86=yes) -AC_MSG_CHECKING(whether x86 assembly fpu core will be enabled) -if test x$enable_fpu_x86 = xno ; then - AC_MSG_RESULT(no) -else - if test x$enable_fpu = xyes; then - if test x$c_targetcpu = xx86 ; then - AC_DEFINE(C_FPU_X86,1) - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT(no) - fi - else - AC_MSG_RESULT(no) - fi -fi - -AH_TEMPLATE(C_UNALIGNED_MEMORY,[Define to 1 to use a unaligned memory access]) -AC_ARG_ENABLE(unaligned_memory,AC_HELP_STRING([--disable-unaligned-memory],[Disable unaligned memory access]),,enable_unaligned_memory=yes) -AC_MSG_CHECKING(whether to enable unaligned memory access) -if test x$enable_unaligned_memory = xyes -a x$c_unalignedmemory = xyes; then - AC_DEFINE(C_UNALIGNED_MEMORY,1) - AC_MSG_RESULT(yes) -else - AC_MSG_RESULT(no) -fi - -AH_TEMPLATE(C_SSHOT,[Define to 1 to enable screenshots, requires libpng]) -AC_CHECK_HEADER(png.h,have_png_h=yes,) -AC_CHECK_LIB(png, png_check_sig, have_png_lib=yes, ,-lz) -if test x$have_png_lib = xyes -a x$have_png_h = xyes ; then - LIBS="$LIBS -lpng -lz" - AC_DEFINE(C_SSHOT,1) -else - AC_MSG_WARN([Can't find libpng, screenshot support disabled]) -fi - -AH_TEMPLATE(C_MODEM,[Define to 1 to enable internal modem support, requires SDL_net]) -AH_TEMPLATE(C_IPX,[Define to 1 to enable IPX over Internet networking, requires SDL_net]) -AC_CHECK_HEADER(SDL_net.h,have_sdl_net_h=yes,) - -if test x$target = xi386-pc-os2-emx ; then - AC_MSG_CHECKING(for SDLNet_Init in SDL_net); - LIBS_BACKUP=$LIBS; - LIBS="$LIBS -lSDL_Net"; - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]],[[ - SDLNet_Init (); - ]])], [AC_MSG_RESULT(yes); have_sdl_net_lib=yes], AC_MSG_RESULT(no)) - LIBS=$LIBS_BACKUP -else -AC_CHECK_LIB(SDL_net, SDLNet_Init, have_sdl_net_lib=yes, , ) -fi -if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then - LIBS="$LIBS -lSDL_net" - AC_DEFINE(C_MODEM,1) - AC_DEFINE(C_IPX,1) -else - AC_MSG_WARN([Can't find SDL_net, internal modem and ipx disabled]) -fi - -AH_TEMPLATE(C_OPENGL,[Define to 1 to use opengl display output support]) -AC_CHECK_LIB(GL, main, have_gl_lib=yes, have_gl_lib=no , ) -AC_CHECK_LIB(opengl32, main, have_opengl32_lib=yes,have_opengl32_lib=no , ) -AC_CHECK_HEADER(GL/gl.h, have_gl_h=yes , have_gl_h=no , ) -AC_ARG_ENABLE(opengl,AC_HELP_STRING([--disable-opengl],[Disable opengl support]),,enable_opengl=yes) -AC_MSG_CHECKING(whether opengl display output will be enabled) -if test x$enable_opengl = xyes; then -case "$target" in - *-*-darwin*) - AC_MSG_RESULT(yes) - LIBS="$LIBS -framework OpenGL" - AC_DEFINE(C_OPENGL,1) - ;; - *) - if test x$have_gl_h = xyes -a x$have_gl_lib = xyes ; then - AC_MSG_RESULT(yes) - LIBS="$LIBS -lGL" - AC_DEFINE(C_OPENGL,1) - elif test x$have_gl_h = xyes -a x$have_opengl32_lib = xyes ; then - AC_MSG_RESULT(yes) - LIBS="$LIBS -lopengl32" - AC_DEFINE(C_OPENGL,1) - else - AC_MSG_RESULT(no) - fi - ;; -esac -fi - -AH_TEMPLATE(C_SDL_SOUND,[Define to 1 to enable SDL_sound support]) -AC_CHECK_HEADER(SDL_sound.h,have_SDL_sound_h=yes,) -AC_CHECK_LIB(SDL_sound, Sound_Init, have_SDL_sound_init=yes,,) -AC_CHECK_LIB(SDL_sound, Sound_Seek, have_SDL_sound_seek=yes,,) -if test x$have_SDL_sound_h = xyes -a x$have_SDL_sound_init = xyes ; then - if test x$have_SDL_sound_seek = xyes ; then - LIBS="-lSDL_sound $LIBS" - AC_DEFINE(C_SDL_SOUND,1) - else - AC_MSG_WARN([Can't find SoundSeek in libSDL_Sound, libSDL_sound support disabled]) - fi -else - AC_MSG_WARN([Can't find libSDL_sound, libSDL_sound support disabled]) -fi - -dnl Check for mprotect. Needed for 64 bits linux -AH_TEMPLATE(C_HAVE_MPROTECT,[Define to 1 if you have the mprotect function]) -AC_CHECK_HEADER([sys/mman.h], [ -AC_CHECK_FUNC([mprotect],[AC_DEFINE(C_HAVE_MPROTECT,1)]) -]) - -dnl Setpriority -AH_TEMPLATE(C_SET_PRIORITY,[Define to 1 if you have setpriority support]) -AC_MSG_CHECKING(for setpriority support) -AC_LINK_IFELSE([ -#include -int main(int argc,char * argv[]) { - return setpriority (PRIO_PROCESS, 0,PRIO_MIN+PRIO_MAX); -}; -],AC_MSG_RESULT(yes);AC_DEFINE(C_SET_PRIORITY,1),AC_MSG_RESULT(no)) - - -dnl Some target detection and actions for them -case "$target" in - *-*-cygwin* | *-*-mingw32*) - LIBS="$LIBS -lwinmm" - AC_CHECK_HEADERS(ddraw.h) - AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2 only).]) - if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then - LIBS="$LIBS -lws2_32" - fi - ;; - *-*-darwin*) - dnl We have a problem here: both Mac OS X and Darwin report - dnl the same signature "powerpc-apple-darwin*" - so we have - dnl to do more to distinguish them. - dnl For now I am lazy and do not add proper detection code. - AC_DEFINE(MACOSX, 1, [Compiling on Mac OS X]) - LIBS="$LIBS -framework CoreMidi -framework AudioUnit -framework AudioToolbox" - AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2).]) - ;; - *-*-linux*) - AC_DEFINE(LINUX, 1, [Compiling on GNU/Linux]) - AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2).]) - ;; - *-*-freebsd* | *-*-dragonfly* | *-*-netbsd* | *-*-openbsd*) - dnl Disabled directserial for now. It doesn't do anything without - dnl specifying an extra ifdef in directserial_posix.* - dnl directserial detection should be rewritten to test for the needed - dnl functions and headers. I currently do not know - dnl which ones are needed for BSD - AC_DEFINE(BSD, 1, [Compiling on BSD]) - AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2).]) - ;; - *-*-os2-emx*) - AC_DEFINE(OS2, 1, [Compiling on OS/2 EMX]) - AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2).]) - ;; -esac - -dnl Some stuff for the icon. -case "$target" in - *-*-cygwin* | *-*-mingw32*) - dnl Some stuff for the ico - AC_CHECK_TOOL(WINDRES, windres, :) - ;; - *) - WINDRES=":" - ;; -esac - AM_CONDITIONAL(HAVE_WINDRES, test "x$WINDRES" != "x:") - AC_SUBST(WINDRES) - - -AC_CONFIG_FILES([ -Makefile -src/Makefile -src/cpu/Makefile -src/cpu/core_full/Makefile -src/cpu/core_normal/Makefile -src/cpu/core_dyn_x86/Makefile -src/cpu/core_dynrec/Makefile -src/debug/Makefile -src/dos/Makefile -src/fpu/Makefile -src/gui/Makefile -src/hardware/Makefile -src/hardware/serialport/Makefile -src/ints/Makefile -src/libs/Makefile -src/libs/zmbv/Makefile -src/libs/gui_tk/Makefile -src/misc/Makefile -src/shell/Makefile -src/platform/Makefile -src/platform/visualc/Makefile -visualc_net/Makefile -include/Makefile -docs/Makefile -]) -AC_OUTPUT +dnl Init. +AC_INIT(dosbox,0.50) +AC_CONFIG_SRCDIR(README) + +dnl Detect the canonical host and target build environment +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +dnl Setup for automake +AM_INIT_AUTOMAKE +AM_CONFIG_HEADER(config.h) + + +dnl Checks for programs. +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_RANLIB + +dnl Check for SDL +SDL_VERSION=1.2.0 +AM_PATH_SDL($SDL_VERSION, + :, + AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]) +) +LIBS="$LIBS $SDL_LIBS" +CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" + +dnl Checks for header files. + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_STRUCT_TM + +dnl Checks for library functions. + + +#Always include the standard include dir in all makefiless + +AC_OUTPUT([ +Makefile +src/Makefile +src/cpu/Makefile +src/cpu/core_16/Makefile +src/debug/Makefile +src/dos/Makefile +src/fpu/Makefile +src/gui/Makefile +src/hardware/Makefile +src/ints/Makefile +src/misc/Makefile +src/shell/Makefile +src/platform/Makefile +src/platform/visualc/Makefile +visualc/Makefile +include/Makefile +]) diff --git a/depcomp b/depcomp new file mode 100644 index 0000000..3480ce4 --- /dev/null +++ b/depcomp @@ -0,0 +1,436 @@ +#! /bin/sh + +# depcomp - compile a program generating dependencies as side-effects +# Copyright 1999, 2000 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi +# `libtool' can also be set to `yes' or `no'. + +if test -z "$depfile"; then + base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` + dir=`echo "$object" | sed 's,/.*$,/,'` + if test "$dir" = "$object"; then + dir= + fi + # FIXME: should be _deps on DOS. + depfile="$dir.deps/$base" +fi + +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. This file always lives in the current directory. + # Also, the AIX compiler puts `$object:' at the start of each line; + # $object doesn't have directory information. + stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + outname="$stripped.o" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + + base=`echo "$object" | sed -e 's/\.o$//' -e 's/\.lo$//'` + tmpdepfile1="$base.o.d" + tmpdepfile2="$base.d" + if test "$libtool" = yes; then + "$@" -Wc,-MD + else + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + else + tmpdepfile="$tmpdepfile2" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a space and a tab in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + test -z "$dashmflag" && dashmflag=-M + ( IFS=" " + case " $* " in + *" --mode=compile "*) # this is libtool, let us make it quiet + for arg + do # cycle over the arguments + case "$arg" in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + # X makedepend + ( + shift + cleared=no + for arg in "$@"; do + case $cleared in no) + set ""; shift + cleared=yes + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift;; + -*) + ;; + *) + set fnord "$@" "$arg"; shift;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + ( IFS=" " + case " $* " in + *" --mode=compile "*) + for arg + do # cycle over the arguments + case $arg in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + ( IFS=" " + case " $* " in + *" --mode=compile "*) + for arg + do # cycle over the arguments + case $arg in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 diff --git a/docs/Makefile.am b/docs/Makefile.am deleted file mode 100644 index e3c8763..0000000 --- a/docs/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -# Main Makefile for DOSBox - -man_MANS = dosbox.1 -EXTRA_DIST = $(man_MANS) README.video PORTING - - - - diff --git a/docs/PORTING b/docs/PORTING deleted file mode 100644 index cf2c07a..0000000 --- a/docs/PORTING +++ /dev/null @@ -1,44 +0,0 @@ -Some notes about porting DOSBox to systems with certain restrictions, -like handheld devices. - -If memory is a constraint: - - in paging.h out-comment the USE_FULL_TLB define to enable special - TLB linking code that uses less memory - drawback: none (the code is not heavily tested though) - gain: reduces memory requirements about ~15mb - - in render.h lower the scaler integration: - #define RENDER_USE_ADVANCED_SCALERS 1 - or - #define RENDER_USE_ADVANCED_SCALERS 0 - drawback: complex scalers and the scaler cache are disabled, - be sure to test if this affects speed! - with define RENDER_USE_ADVANCED_SCALERS==0 most simple - scalers are disabled as well, some graphics modes won't - work due to reduced cache sizes - gain: ~2mb with RENDER_USE_ADVANCED_SCALERS==1 - ~5mb with RENDER_USE_ADVANCED_SCALERS==0 - - in dos_system.h reduce the drive cache entries: - #define MAX_OPENDIRS 256 - drawback: some apps might not work with large directory trees - gain: ~1mb per mounted drive - - remove the GUS emulation (gus.cpp, especially GUSRam[1024*1024] ) - drawback: no gravis ultrasound - gain: reduces memory requirements about 1mb - - reduce the size of the emulated graphics memory: - see the memory sizing in SVGA_Setup_*, especially the defaults - in vga_s3.cpp's SVGA_Setup_S3Trio - drawback: some graphics modes won't work then - gain: reduces memory requirements - TODO: fully check this, introduce hard limits - -If speed is a constraint: - - see if the simple core is faster, possibly remove the normal core - set the simple core as default - drawback: one game is known to not work with the simple core; - the simple core does only work for games which don't use paging - (when paging is requested the normal core is used automatically) - gain: the simple core should be somewhat faster - TODO: add possibility to easily remove the normal core, use fullcore fallback - - raise the default frameskip value - drawback: minor graphics smoothness loss for some games (video playback) - gain: reduces graphics load diff --git a/docs/README.video b/docs/README.video deleted file mode 100644 index 5b4f665..0000000 --- a/docs/README.video +++ /dev/null @@ -1,35 +0,0 @@ -Starting with version 0.65, DOSBox allows you to create movies out of screen -output. - -To record a movie, you have to press CTRL-ALT-F5. -To stop/end the recording, you have to press CTRL-ALT-F5 again. - -To play the recorded movie, you need a movie player which can handle the -ZMBV codec. MS Windows users can find this codec in the start menu entry of -DOSBox. Users of Linux and other OSes should look for a movie player that -uses the ffmpeg libary (you may need to update or ask your distribution to -upgrade). - -FAQ: -Q: During the display of the movies the sound is lagging. -A: Check your display properties to see whether your refresh rate is set to -at least 70 hz. Try playing the movie in virtualdub (http://virtualdub.sf.net) - -Q: Why does the resulting movie consist of multiple files? -A: Each time the game changes resolution, DOSBox creates a new movie file, -because a movie file can only contain one resolution. - -Q: Can I set the cycles higher than my PC can handle during recording? -A: Yes. During recording, the game might play slowly and stuttering, but the -resulting movie should play at the intended speed and have no stuttering. - -Q: CTRL-ALT-F5 switches to the console under linux. -A: 1. Start DOSBox like this: dosbox -startmapper - 2. Click on Video, click on Add - 3. Press the key you want (for example scroll lock or printscreen) - 4. Click exit. - 5. You can make movies by pressing scroll lock or whichever key you - selected. - -Q: The colours are wrong and I'm using 64 bit windows -A: Look here: http://vogons.zetafleet.com/viewtopic.php?t=12133 diff --git a/docs/dosbox.1 b/docs/dosbox.1 deleted file mode 100644 index 16ddba5..0000000 --- a/docs/dosbox.1 +++ /dev/null @@ -1,337 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.TH DOSBOX 1 "Jul 01, 2007" -.\" Please adjust this date whenever revising the manpage. -.SH NAME -dosbox \- an x86/DOS emulator with sound/graphics -.SH SYNOPSIS -.B dosbox -.B [\-fullscreen] -.B [\-startmapper] -.B [\-noautoexec] -.B [\-securemode] -.BI "[\-scaler " scaler ] -.BI "[\-forcescaler " scaler ] -.BI "[\-conf " configfile ] -.BI "[\-lang " langfile ] -.B [file] -.BI "[\-c " command ] -.B [\-exit] -.BI "[\-machine " machinetype ] -.LP -.B dosbox -version -.SH DESCRIPTION -This manual page briefly documents -.BR "dosbox" ", an x86/DOS emulator." -.LP -.RB "The optional " file " argument should be a DOS executable or a" -directory. If it is a dos executable (.com .exe .bat) the program will -run automatically. If it is a directory, a DOS session will run with -the directory mounted as C:\\. -.LP -.RI "For an introduction type " INTRO -.RB "inside " dosbox . -.SH OPTIONS -A summary of options is included below. -.TP -.B \-fullscreen -.RB "Start " dosbox " in fullscreen mode." -.TP -.B \-startmapper -.RB "Start the internal keymapper on startup of " dosbox ". You can use it to change the keys " dosbox " uses." -.TP -.B \-noautoexec -Skips the [autoexec] section of the loaded configuration file. -.TP -.B \-securemode -.RB "Same as " \-noautoexec ", but adds " "config.com \-securemode" -at the end of -.I AUTOEXEC.BAT -(which in turn disables any changes to how the drives are mounted -.RB "inside " dosbox ) -.TP -.BI \-scaler " scaler" -.RI "Uses the graphical scaler specified by " scaler ". See the configuration" -file for the available scalers -.TP -.BI \-forcescaler " scaler" -.RB "Similar to the " \-scaler " parameter, but tries to force usage of" -the specified scaler even if it might not fit. -.TP -.BI \-c " command" -.RI "Runs the specified " command " before running " -.BR file . -.RI "Multiple commands can be specified. Each " command " should start with " -.BR \-c " though. A command can be:" -an Internal Program, a DOS command or an executable on a mounted drive. -.TP -.BI \-conf " configfile -.RB "Start " dosbox " with the options specified in " -.IR configfile ". This file has a section in which you can put commands you " -wish to execute on startup. Multiple -.IR configfiles " can be present at the commandline." -.TP -.BI \-lang " langfile -.RB "Start " dosbox " with the language specified in " -.IR langfile . -.TP -.B \-exit -.BR dosbox " will close itself when the DOS program specified by "file " ends." -.TP -.BI \-machine " machinetype -.RB "Setup " dosbox " to emulate a specific type of machine." -.RI "Valid choices are: " "hercules, cga, pcjr, tandy, vga(default)". -The machinetype has influence on both the videocard and the available -soundcards. -.TP -.B \-version -Output version information and exit. Useful for frontends. -.SH "INTERNAL COMMANDS" -.B dosbox -supports most of the DOS commands found in command.com. In addition, the -following extra commands are available: -.HP -.BI "MOUNT [\-t " type "] [\-size " size ] -.I driveletter sourcedirectory -.B [\-ioctl] -.BI "[\-usecd " number "] [\-label " drivelabel "] [\-freesize " freesize ] -.LP -.B MOUNT \-cd -.LP -.B MOUNT \-u driveletter -.LP -.RB "Program to mount local directories as drives inside " dosbox . -.RS -.TP -.I driveletter -The driveletter inside dosbox (eg. C). -.TP -.I sourcedirectory -The local directory you want to have inside dosbox. -.TP -.BI \-t " type" -Type of the mounted directory. Supported are: dir (standard), floppy, cdrom. -.TP -.BI \-size " drivesize" -Sets the size of the drive. See the examples in the README for details. -.TP -.BI \-freesize " size_in_mb" -Sets the amount of free space available on a drive in MB's. This is a more -.RB "simple version of " \-size . -.TP -.BI \-label " drivelabel" -.RI "Sets the name of the drive to " drivelabel ". Needed on some" -systems if the cd label isn't read correctly. Useful when a -program can't find its cdrom. If you don't specify a label and no -.RB "lowlevel support is selected (" "\-usecd #" " and/or " "\-ioctl/aspi" "):" -.RS -.LP -For win32: label is extracted from "Real Drive". -.TP -For Linux: label is set to NO_LABEL. -.TP -If you do specify a label this label will be kept as long as the drive -is mounted. It will not be updated !! -.RE -.TP -.B \-ioctl -Forces to use ioctl commands. -.TP -.BI \-usecd " number" -Forces to use SDL cdrom support for drive number. -.IR Number " can be found by " -.BR \-cd ". -.TP -.B \-cd -.RB "Displays all detected cdrom drives and their numbers. Use with " \-usecd "." -.TP -.B \-u -Unmounts a mounted drive. Doesn't work on virtual Drives (like Z:\\) -.RE -.PP -.B "Example:" -.TP -.RB "To mount your /home/dos/dosgames directory as C drive in " dosbox : -.RS -mount c /home/dos/dosgames -.RE -.TP -.B MEM -.LP -Display the amount of free memory -.TP -.B CONFIG [\-writeconf] [\-writelang] file -.LP -.B CONFIG -securemode -.LP -.RB "Write the current configuration or language settings to " file , -which is located on the local filesystem. Not a mounted drive in -.BR dosbox . -.TP -.B \-securemode -.RB Switches dosbox " to a more secure mode. In this mode the" -.RI "internal commands " MOUNT ", " IMGMOUNT " and " BOOT " won\'t work." -It\'s not possible -either to create a new configfile or languagefile in this mode. -(Warning you can only undo this mode by restarting -.BR dosbox .) -.LP -The configuration file controls various settings of -.BR dosbox ": The amount of emulated memory," -the emulated soundcards and many -.RI "more things. It futher allows acces to " AUTOEXEC.BAT . -.LP -The language file controls all visible ouput of the internal commands and -the internal dos. -.RB "See the section " FILES " for more information." -.TP -.B LOADFIX [\-size] [programname] [parameters] -.LP -.B LOADFIX \-f -.LP -Program to reduce the amount of memory available. Useful for old programs which don't expect much memory to be free. -.RS -.TP -.B [programname] -The name of the program which is executed after loadfix eats up its memory. -.TP -.B [parameters] -.RB "Parameters given to the " programname " executable." -.TP -.B \-size -The amount of memory to eat up (in kb). Example -32, -64 or -128 -.TP -.B \-f -Frees all memory eaten up by loadfix. -.RE -.TP -.B RESCAN -.LP -.RB "Make " dosbox " reread the directory structure. Useful if you changed -.RB "something on a mounted drive outside " dosbox ".(CTRL\-F4 does" -this as well!) -.TP -.B IMGMOUNT -.LP -.RB "A utility to mount disk images and CD-ROM images in " dosbox . -.TP -.RB "Read the " README " of " dosbox " for the full and correct syntax." -.RE -.TP -.B BOOT -.LP -Boot will start floppy images or hard disk images independent of the -.RB "operating system emulation offered by " dosbox ". This will allow you to play booter floppies or boot to other operating systems inside " dosbox . -.TP -.RB "Read the " README " of " dosbox " for the full and correct syntax." -.RE -.TP -.B IPX -.LP -.RB "You need to enable IPX networking in the configuration file of " dosbox . -.RB "All of the IPX networking is managed through the internal " dosbox " program -.BR IPXNET ". For help on the IPX networking from inside " dosbox ", type" -.BR "IPXNET HELP" " and the program will list out the commands and relevant documentation." -.TP -.RB "Read the " README " of " dosbox " for the full and correct syntax." -.RE -.TP -.B KEYB -.LP -Keyb can change the keyboardlayout and the codepage used inside dosbox. -.TP -.RB "Read the " README " of " dosbox " for the full and correct syntax." -.RE -.SH FILES -Configuration and language files use a format similar to Windows .ini files. -First ~/.dosboxrc (if present) will be loaded. If no -configfile is specified at the commandline, a file named -.BR dosbox.conf " (if present in the current directory) will be" -loaded automatically afterwards. If a configfile is specified at the commandline -that one will be used instead. -.SH "SPECIAL KEYS" -.TP 12m -.IP ALT\-ENTER -Go full screen and back. -.IP ALT\-PAUSE -Pause emulation. -.IP CTRL\-F1 -Start the keymapper. -.IP CTRL\-ALT\-F5 -Start/Stop creating a movie of the screen. -.IP CTRL\-F4 -Swap mounted disk-image (Only used with imgmount). Update directory cache -for all drives! -.IP CTRL\-F5 -Save a screenshot.(png) -.IP CTRL\-F6 -Start/Stop recording sound output to a wave file. -.IP CTRL\-ALT\-F7 -Start/Stop recording of OPL commands. -.IP CTRL\-ALT\-F8 -Start/Stop the recording of raw MIDI commands. -.IP CTRL\-F7 -Decrease frameskip. -.IP CTRL\-F8 -Increase frameskip. -.IP CTRL\-F9 -Kill dosbox. -.IP CTRL\-F10 -Capture/Release the mouse. -.IP CTRL\-F11 -Slow down emulation (Increase dosbox Cycles). -.IP CTRL\-F12 -Speed up emulation (Decrease dosbox Cycles). -.IP ALT\-F12 -Unlock speed (turbo button). -.PP -These are the default keybindings. They can be changed in the keymapper. -.PP -Saved/recorded files can be found in current_directory/capture -(can be changed in the configfile). -.RB "The directory has to exist prior to starting " dosbox " else nothing" -gets saved/recorded ! -.PP -.BR "Note: " "Once you increase your " dosbox " cycles beyond your computer's maximum -capacity, it will produce the same effect as slowing down the emulation. -This maximum will vary from computer to computer, there is no standard. -.SH "SYSTEM REQUIREMENTS" -Fast machine. My guess would be pentium\-2 400+ to get decent emulation -of games written for an 286 machine. -For protected mode games a 1 Ghz machine is recommended and don't expect -them to run fast though!! Be sure to read the next section on how to speed -it up somewhat. -.SS "To run resource\-demanding games" -.BR dosbox " emulates the CPU, the sound and graphic cards, and some other" -.RB " stuff, all at the same time. You can overclock " dosbox " by using CTRL\-F12, but" -you'll be limited by the power of your actual CPU. You can see how much free -time your true CPU has by various utils (top). Once 100% of your real CPU time is -.RB "used there is no further way to speed up " dosbox " unless you reduce the load" -.RB "generated by the non\-CPU parts of " dosbox . -.PP -So: -.PP -.RB "Close every program but " dosbox . -.PP -.RB "Overclock " dosbox " until 100% of your CPU is used.(CTRL\-F12)" -.PP -.RB "Since VGA emulation is the most demanding part of " dosbox " in terms of actual" -CPU usage, we'll start here. Increase the number of frames skipped (in -increments of one) by pressing CTRL\-F8. Your CPU usage should decrease. -Go back one step and repeat this until the game runs fast enough for you. -Please note that this is a trade off: you lose in fluidity of video what you -gain in speed. -.SH NOTES -.RB "While we hope that, one day, " dosbox " will run virtually all programs ever made for the PC..." -.RB "we are not there yet. At present, " dosbox " run on a 1.7 Gigahertz PC is roughly the equivalent of a 25MHz 386 PC." -While the 0.60 release has added support for "protected mode" allowing for more complex and recent programs, -but note that this support is early in development and nowhere near as complete as the support for 386 real\-mode -games (or earlier). Also note that "protected mode" games need substantially more resources and may -.RB "require a much faster processor for you to run it properly in " dosbox . -.SH BUGS -Not all DOS programs work properly. -.BR dosbox " will exit without warning if an error occurred." -.SH "SEE ALSO" -The README in /usr/share/doc/dosbox -.SH AUTHOR -This manual page was written by Peter Veenstra and James Oakley , -for the Debian system (but may be used by others). diff --git a/include/Makefile.am b/include/Makefile.am index 0f692ef..4425e6e 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,39 +1,29 @@ -noinst_HEADERS = \ -bios.h \ -bios_disk.h \ -callback.h \ -cpu.h \ -cross.h \ -control.h \ -debug.h \ -dma.h \ -dos_inc.h \ -dos_system.h \ -dosbox.h \ -fpu.h \ -hardware.h \ -inout.h \ -joystick.h \ -ipx.h \ -ipxserver.h \ -keyboard.h \ -logging.h \ -mapper.h \ -mem.h \ -mixer.h \ -modules.h \ -mouse.h \ -paging.h \ -pic.h \ -programs.h \ -render.h \ -regs.h \ -render.h \ -serialport.h \ -setup.h \ -shell.h \ -support.h \ -timer.h \ -vga.h \ -video.h - +noinst_HEADERS = \ +bios.h \ +callback.h \ +cpu.h \ +cross.h \ +debug.h \ +dma.h \ +dos_inc.h \ +dos_system.h \ +dosbox.h \ +fpu.h \ +hardware.h \ +inout.h \ +joystick.h \ +keyboard.h \ +mem.h \ +mixer.h \ +modules.h \ +mouse.h \ +pic.h \ +programs.h \ +render.h \ +regs.h \ +render.h \ +setup.h \ +support.h \ +timer.h \ +video.h + diff --git a/include/Makefile.in b/include/Makefile.in new file mode 100644 index 0000000..16604c5 --- /dev/null +++ b/include/Makefile.in @@ -0,0 +1,269 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +noinst_HEADERS = \ +bios.h \ +callback.h \ +cpu.h \ +cross.h \ +debug.h \ +dma.h \ +dos_inc.h \ +dos_system.h \ +dosbox.h \ +fpu.h \ +hardware.h \ +inout.h \ +joystick.h \ +keyboard.h \ +mem.h \ +mixer.h \ +modules.h \ +mouse.h \ +pic.h \ +programs.h \ +render.h \ +regs.h \ +render.h \ +setup.h \ +support.h \ +timer.h \ +video.h + +subdir = include +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = $(noinst_HEADERS) Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits include/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic distclean \ + distclean-generic distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic tags uninstall uninstall-am \ + uninstall-info-am + +# 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/include/bios.h b/include/bios.h index 34c4798..9d74b59 100644 --- a/include/bios.h +++ b/include/bios.h @@ -1,127 +1,120 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_BIOS_H -#define DOSBOX_BIOS_H - -#define BIOS_BASE_ADDRESS_COM1 0x400 -#define BIOS_BASE_ADDRESS_COM2 0x402 -#define BIOS_BASE_ADDRESS_COM3 0x404 -#define BIOS_BASE_ADDRESS_COM4 0x406 -#define BIOS_ADDRESS_LPT1 0x408 -#define BIOS_ADDRESS_LPT2 0x40a -#define BIOS_ADDRESS_LPT3 0x40c -/* 0x40e is reserved */ -#define BIOS_CONFIGURATION 0x410 -/* 0x412 is reserved */ -#define BIOS_MEMORY_SIZE 0x413 -#define BIOS_TRUE_MEMORY_SIZE 0x415 -/* #define bios_expansion_memory_size (*(unsigned int *) 0x415) */ -#define BIOS_KEYBOARD_STATE 0x417 -#define BIOS_KEYBOARD_FLAGS1 BIOS_KEYBOARD_STATE -#define BIOS_KEYBOARD_FLAGS2 0x418 -#define BIOS_KEYBOARD_TOKEN 0x419 -/* used for keyboard input with Alt-Number */ -#define BIOS_KEYBOARD_BUFFER_HEAD 0x41a -#define BIOS_KEYBOARD_BUFFER_TAIL 0x41c -#define BIOS_KEYBOARD_BUFFER 0x41e -/* #define bios_keyboard_buffer (*(unsigned int *) 0x41e) */ -#define BIOS_DRIVE_ACTIVE 0x43e -#define BIOS_DRIVE_RUNNING 0x43f -#define BIOS_DISK_MOTOR_TIMEOUT 0x440 -#define BIOS_DISK_STATUS 0x441 -/* #define bios_fdc_result_buffer (*(unsigned short *) 0x442) */ -#define BIOS_VIDEO_MODE 0x449 -#define BIOS_SCREEN_COLUMNS 0x44a -#define BIOS_VIDEO_MEMORY_USED 0x44c -#define BIOS_VIDEO_MEMORY_ADDRESS 0x44e -#define BIOS_VIDEO_CURSOR_POS 0x450 - - -#define BIOS_CURSOR_SHAPE 0x460 -#define BIOS_CURSOR_LAST_LINE 0x460 -#define BIOS_CURSOR_FIRST_LINE 0x461 -#define BIOS_CURRENT_SCREEN_PAGE 0x462 -#define BIOS_VIDEO_PORT 0x463 -#define BIOS_VDU_CONTROL 0x465 -#define BIOS_VDU_COLOR_REGISTER 0x466 -/* 0x467-0x468 is reserved */ -#define BIOS_TIMER 0x46c -#define BIOS_24_HOURS_FLAG 0x470 -#define BIOS_KEYBOARD_FLAGS 0x471 -#define BIOS_CTRL_ALT_DEL_FLAG 0x472 -#define BIOS_HARDDISK_COUNT 0x475 -/* 0x474, 0x476, 0x477 is reserved */ -#define BIOS_LPT1_TIMEOUT 0x478 -#define BIOS_LPT2_TIMEOUT 0x479 -#define BIOS_LPT3_TIMEOUT 0x47a -/* 0x47b is reserved */ -#define BIOS_COM1_TIMEOUT 0x47c -#define BIOS_COM2_TIMEOUT 0x47d -#define BIOS_COM3_TIMEOUT 0x47e -#define BIOS_COM4_TIMEOUT 0x47f -/* 0x47e is reserved */ //<- why that? -/* 0x47f-0x4ff is unknow for me */ -#define BIOS_KEYBOARD_BUFFER_START 0x480 -#define BIOS_KEYBOARD_BUFFER_END 0x482 - -#define BIOS_ROWS_ON_SCREEN_MINUS_1 0x484 -#define BIOS_FONT_HEIGHT 0x485 - -#define BIOS_VIDEO_INFO_0 0x487 -#define BIOS_VIDEO_INFO_1 0x488 -#define BIOS_VIDEO_INFO_2 0x489 -#define BIOS_VIDEO_COMBO 0x48a - -#define BIOS_KEYBOARD_FLAGS3 0x496 -#define BIOS_KEYBOARD_LEDS 0x497 - -#define BIOS_WAIT_FLAG_POINTER 0x498 -#define BIOS_WAIT_FLAG_COUNT 0x49c -#define BIOS_WAIT_FLAG_ACTIVE 0x4a0 -#define BIOS_WAIT_FLAG_TEMP 0x4a1 - - -#define BIOS_PRINT_SCREEN_FLAG 0x500 - -#define BIOS_VIDEO_SAVEPTR 0x4a8 - -/* maximum of scancodes handled by keyboard bios routines */ -#define MAX_SCAN_CODE 0x58 - -/* The Section handling Bios Disk Access */ -//#define BIOS_MAX_DISK 10 - -//#define MAX_SWAPPABLE_DISKS 20 - -void BIOS_ZeroExtendedSize(bool in); -void char_out(Bit8u chr,Bit32u att,Bit8u page); -void INT10_StartUp(void); -void INT16_StartUp(void); -void INT2A_StartUp(void); -void INT2F_StartUp(void); -void INT33_StartUp(void); -void INT13_StartUp(void); - -bool BIOS_AddKeyToBuffer(Bit16u code); - -void INT10_ReloadRomFonts(); - -void BIOS_SetComPorts (Bit16u baseaddr[]); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define BIOS_BASE_ADDRESS_COM1 0x400 +#define BIOS_BASE_ADDRESS_COM2 0x402 +#define BIOS_BASE_ADDRESS_COM3 0x404 +#define BIOS_BASE_ADDRESS_COM4 0x406 +#define BIOS_ADDRESS_LPT1 0x408 +#define BIOS_ADDRESS_LPT2 0x40a +#define BIOS_ADDRESS_LPT3 0x40c +/* 0x40e is reserved */ +#define BIOS_CONFIGURATION 0x410 +/* 0x412 is reserved */ +#define BIOS_MEMORY_SIZE 0x413 +/* #define bios_expansion_memory_size (*(unsigned int *) 0x415) */ +#define BIOS_KEYBOARD_STATE 0x417 +#define BIOS_KEYBOARD_FLAGS1 BIOS_KEYBOARD_STATE +#define BIOS_KEYBOARD_FLAGS2 0x418 +#define BIOS_KEYBOARD_TOKEN 0x419 +/* used for keyboard input with Alt-Number */ +#define BIOS_KEYBOARD_BUFFER_HEAD 0x41a +#define BIOS_KEYBOARD_BUFFER_TAIL 0x41c +#define BIOS_KEYBOARD_BUFFER 0x41e +/* #define bios_keyboard_buffer (*(unsigned int *) 0x41e) */ +#define BIOS_DRIVE_ACTIVE 0x43e +#define BIOS_DRIVE_RUNNING 0x43f +#define BIOS_MOTOR_NACHLAUFZEIT 0x440 +#define BIOS_DISK_STATUS 0x441 +/* #define bios_fdc_result_buffer (*(unsigned short *) 0x442) */ +#define BIOS_VIDEO_MODE 0x449 +#define BIOS_SCREEN_COLUMNS 0x44a +#define BIOS_VIDEO_MEMORY_USED 0x44c +#define BIOS_VIDEO_MEMORY_ADDRESS 0x44e +#define BIOS_VIDEO_CURSOR_POS 0x450 + + +#define BIOS_CURSOR_SHAPE 0x460 +#define BIOS_CURSOR_LAST_LINE 0x460 +#define BIOS_CURSOR_FIRST_LINE 0x461 +#define BIOS_CURRENT_SCREEN_PAGE 0x462 +#define BIOS_VIDEO_PORT 0x463 +#define BIOS_VDU_CONTROL 0x465 +#define BIOS_VDU_COLOR_REGISTER 0x466 +/* 0x467-0x468 is reserved */ +#define BIOS_TIMER 0x46c +#define BIOS_24_HOURS_FLAG 0x470 +#define BIOS_KEYBOARD_FLAGS 0x471 +#define BIOS_CTRL_ALT_DEL_FLAG 0x472 +#define BIOS_HARDDISK_COUNT 0x475 +/* 0x474, 0x476, 0x477 is reserved */ +#define BIOS_LPT1_TIMEOUT 0x478 +#define BIOS_LPT2_TIMEOUT 0x479 +#define BIOS_LPT3_TIMEOUT 0x47a +/* 0x47b is reserved */ +#define BIOS_COM1_TIMEOUT 0x47c +#define BIOS_COM2_TIMEOUT 0x47d +/* 0x47e is reserved */ +/* 0x47f-0x4ff is unknow for me */ +#define BIOS_KEYBOARD_BUFFER_START 0x480 +#define BIOS_KEYBOARD_BUFFER_END 0x482 + +#define BIOS_ROWS_ON_SCREEN_MINUS_1 0x484 +#define BIOS_FONT_HEIGHT 0x485 + +#define BIOS_VIDEO_INFO_0 0x487 +#define BIOS_VIDEO_INFO_1 0x488 +#define BIOS_VIDEO_INFO_2 0x489 +#define BIOS_VIDEO_COMBO 0x48a + +#define BIOS_KEYBOARD_FLAGS3 0x496 +#define BIOS_KEYBOARD_LEDS 0x497 +#define BIOS_PRINT_SCREEN_FLAG 0x500 + +#define BIOS_VIDEO_SAVEPTR 0x4a8 + +/* The Section handling Bios Disk Access */ +#define BIOS_MAX_DISK 10 + +class BIOS_Disk { +public: + virtual Bit8u Read_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data)=0; + virtual Bit8u Write_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data)=0; +}; + +class imageDisk : public BIOS_Disk { +public: + Bit8u Read_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data); + Bit8u Write_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data); + imageDisk(char * file); +private: + Bit16u sector_size; + Bit16u heads,cylinders,sectors; + Bit8u * image; +}; + + +void char_out(Bit8u chr,Bit32u att,Bit8u page); +void INT10_StartUp(void); +void INT16_StartUp(void); +void INT2A_StartUp(void); +void INT2F_StartUp(void); +void INT33_StartUp(void); +void INT13_StartUp(void); + + diff --git a/include/bios_disk.h b/include/bios_disk.h deleted file mode 100644 index 9a14366..0000000 --- a/include/bios_disk.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_BIOS_DISK_H -#define DOSBOX_BIOS_DISK_H - -#include -#ifndef DOSBOX_MEM_H -#include "mem.h" -#endif -#ifndef DOSBOX_DOS_INC_H -#include "dos_inc.h" -#endif -#ifndef DOSBOX_BIOS_H -#include "bios.h" -#endif - -/* The Section handling Bios Disk Access */ -#define BIOS_MAX_DISK 10 - -#define MAX_SWAPPABLE_DISKS 20 -struct diskGeo { - Bit32u ksize; /* Size in kilobytes */ - Bit16u secttrack; /* Sectors per track */ - Bit16u headscyl; /* Heads per cylinder */ - Bit16u cylcount; /* Cylinders per side */ - Bit16u biosval; /* Type to return from BIOS */ -}; -extern diskGeo DiskGeometryList[]; - -class imageDisk { -public: - Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data); - Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data); - Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data); - Bit8u Write_AbsoluteSector(Bit32u sectnum, void * data); - - void Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize); - void Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit32u *getSectSize); - Bit8u GetBiosType(void); - Bit32u getSectSize(void); - imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk); - ~imageDisk() { if(diskimg != NULL) { fclose(diskimg); } }; - - bool hardDrive; - bool active; - FILE *diskimg; - Bit8u diskname[512]; - Bit8u floppytype; - - Bit32u sector_size; - Bit32u heads,cylinders,sectors; -}; - -void updateDPT(void); - -#define MAX_HDD_IMAGES 2 - -extern imageDisk *imageDiskList[2 + MAX_HDD_IMAGES]; -extern imageDisk *diskSwap[20]; -extern Bits swapPosition; -extern Bit16u imgDTASeg; /* Real memory location of temporary DTA pointer for fat image disk access */ -extern RealPt imgDTAPtr; /* Real memory location of temporary DTA pointer for fat image disk access */ -extern DOS_DTA *imgDTA; - -void swapInDisks(void); -void swapInNextDisk(void); -bool getSwapRequest(void); - -#endif diff --git a/include/callback.h b/include/callback.h index 9d83a35..00a6745 100644 --- a/include/callback.h +++ b/include/callback.h @@ -1,99 +1,56 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: callback.h,v 1.23 2009/04/25 16:25:03 harekiet Exp $ */ - -#ifndef DOSBOX_CALLBACK_H -#define DOSBOX_CALLBACK_H - -#ifndef DOSBOX_MEM_H -#include "mem.h" -#endif - -typedef Bitu (*CallBack_Handler)(void); -extern CallBack_Handler CallBack_Handlers[]; - -enum { CB_RETN,CB_RETF,CB_RETF8,CB_IRET,CB_IRETD,CB_IRET_STI,CB_IRET_EOI_PIC1, - CB_IRQ0,CB_IRQ1,CB_IRQ9,CB_IRQ12,CB_IRQ12_RET,CB_IRQ6_PCJR,CB_MOUSE, - CB_INT29,CB_INT16,CB_HOOKABLE,CB_TDE_IRET,CB_IPXESR,CB_IPXESR_RET, - CB_INT21 }; - -#define CB_MAX 128 -#define CB_SIZE 32 -#define CB_SEG 0xF100 - -enum { - CBRET_NONE=0,CBRET_STOP=1 -}; - -extern Bit8u lastint; - -static INLINE RealPt CALLBACK_RealPointer(Bitu callback) { - return RealMake(CB_SEG,(Bit16u)(callback*CB_SIZE)); -} -static INLINE PhysPt CALLBACK_PhysPointer(Bitu callback) { - return PhysMake(CB_SEG,(Bit16u)(callback*CB_SIZE)); -} - -static INLINE PhysPt CALLBACK_GetBase(void) { - return CB_SEG << 4; -} - -Bitu CALLBACK_Allocate(); - -void CALLBACK_Idle(void); - - -void CALLBACK_RunRealInt(Bit8u intnum); -void CALLBACK_RunRealFar(Bit16u seg,Bit16u off); - -bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* descr); -Bitu CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,PhysPt addr,const char* descr); - -const char* CALLBACK_GetDescription(Bitu callback); -bool CALLBACK_Free(Bitu callback); - -void CALLBACK_SCF(bool val); -void CALLBACK_SZF(bool val); - -extern Bitu call_priv_io; - - -class CALLBACK_HandlerObject{ -private: - bool installed; - Bit16u m_callback; - enum {NONE,SETUP,SETUPAT} m_type; - struct { - RealPt old_vector; - Bit8u interrupt; - bool installed; - } vectorhandler; -public: - CALLBACK_HandlerObject():installed(false),m_type(NONE){vectorhandler.installed=false;} - ~CALLBACK_HandlerObject(); - //Install and allocate a callback. - void Install(CallBack_Handler handler,Bitu type,const char* description); - void Install(CallBack_Handler handler,Bitu type,PhysPt addr,const char* description); - //Only allocate a callback number - void Allocate(CallBack_Handler handler,const char* description=0); - Bit16u Get_callback(){return m_callback;} - RealPt Get_RealPointer(){ return CALLBACK_RealPointer(m_callback);} - void Set_RealVec(Bit8u vec); -}; -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __CALLBACK_H +#define __CALLBACK_H + +#include + +typedef Bitu (*CallBack_Handler)(void); +extern CallBack_Handler CallBack_Handlers[]; + +enum { CB_RETF,CB_IRET }; + +#define CB_MAX 1024 +#define CB_SEG 0xC800 + +enum { + CBRET_NONE=0,CBRET_STOP=1 +}; + +extern Bit8u lastint; +INLINE RealPt CALLBACK_RealPointer(Bitu callback) { + return RealMake(CB_SEG,callback << 4); +} + +Bitu CALLBACK_Allocate(); + +void CALLBACK_Idle(void); + + +void CALLBACK_RunRealInt(Bit8u intnum); +void CALLBACK_RunRealFar(Bit16u seg,Bit16u off); + +bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type); + +bool CALLBACK_Free(Bitu callback); + +void CALLBACK_SCF(bool val); +void CALLBACK_SZF(bool val); +#endif + diff --git a/include/control.h b/include/control.h deleted file mode 100644 index 827e0d1..0000000 --- a/include/control.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: control.h,v 1.1 2009/02/01 14:11:45 qbix79 Exp $ */ - -#ifndef DOSBOX_CONTROL_H -#define DOSBOX_CONTROL_H - -#ifdef _MSC_VER -#pragma warning ( disable : 4786 ) -#pragma warning ( disable : 4290 ) -#endif - -#ifndef DOSBOX_PROGRAMS_H -#include "programs.h" -#endif -#ifndef DOSBOX_SETUP_H -#include "setup.h" -#endif - -#ifndef CH_LIST -#define CH_LIST -#include -#endif - -#ifndef CH_VECTOR -#define CH_VECTOR -#include -#endif - -#ifndef CH_STRING -#define CH_STRING -#include -#endif - - - - -class Config{ -public: - CommandLine * cmdline; -private: - std::list sectionlist; - typedef std::list::iterator it; - typedef std::list::reverse_iterator reverse_it; - typedef std::list::const_iterator const_it; - typedef std::list::const_reverse_iterator const_reverse_it; - void (* _start_function)(void); - bool secure_mode; //Sandbox mode -public: - Config(CommandLine * cmd):cmdline(cmd),secure_mode(false){} - ~Config(); - - Section_line * AddSection_line(char const * const _name,void (*_initfunction)(Section*)); - Section_prop * AddSection_prop(char const * const _name,void (*_initfunction)(Section*),bool canchange=false); - - Section* GetSection(int index); - Section* GetSection(std::string const&_sectionname) const; - Section* GetSectionFromProperty(char const * const prop) const; - - void SetStartUp(void (*_function)(void)); - void Init(); - void ShutDown(); - void StartUp(); - bool PrintConfig(char const * const configfilename) const; - bool ParseConfigFile(char const * const configfilename); - void ParseEnv(char ** envp); - bool SecureMode() const { return secure_mode; } - void SwitchToSecureMode() { secure_mode = true; }//can't be undone -}; - -#endif diff --git a/include/cpu.h b/include/cpu.h index 8a32032..15e67ae 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -1,492 +1,99 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: cpu.h,v 1.56 2009/04/25 16:25:03 harekiet Exp $ */ - -#ifndef DOSBOX_CPU_H -#define DOSBOX_CPU_H - -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif -#ifndef DOSBOX_REGS_H -#include "regs.h" -#endif -#ifndef DOSBOX_MEM_H -#include "mem.h" -#endif - -#define CPU_AUTODETERMINE_NONE 0x00 -#define CPU_AUTODETERMINE_CORE 0x01 -#define CPU_AUTODETERMINE_CYCLES 0x02 - -#define CPU_AUTODETERMINE_SHIFT 0x02 -#define CPU_AUTODETERMINE_MASK 0x03 - -#define CPU_CYCLES_LOWER_LIMIT 100 - - -#define CPU_ARCHTYPE_MIXED 0xff -#define CPU_ARCHTYPE_386SLOW 0x30 -#define CPU_ARCHTYPE_386FAST 0x35 -#define CPU_ARCHTYPE_486OLDSLOW 0x40 -#define CPU_ARCHTYPE_486NEWSLOW 0x45 -#define CPU_ARCHTYPE_PENTIUMSLOW 0x50 - -/* CPU Cycle Timing */ -extern Bit32s CPU_Cycles; -extern Bit32s CPU_CycleLeft; -extern Bit32s CPU_CycleMax; -extern Bit32s CPU_OldCycleMax; -extern Bit32s CPU_CyclePercUsed; -extern Bit32s CPU_CycleLimit; -extern Bit64s CPU_IODelayRemoved; -extern bool CPU_CycleAutoAdjust; -extern bool CPU_SkipCycleAutoAdjust; -extern Bitu CPU_AutoDetermineMode; - -extern Bitu CPU_ArchitectureType; - -extern Bitu CPU_PrefetchQueueSize; - -/* Some common Defines */ -/* A CPU Handler */ -typedef Bits (CPU_Decoder)(void); -extern CPU_Decoder * cpudecoder; - -Bits CPU_Core_Normal_Run(void); -Bits CPU_Core_Normal_Trap_Run(void); -Bits CPU_Core_Simple_Run(void); -Bits CPU_Core_Full_Run(void); -Bits CPU_Core_Dyn_X86_Run(void); -Bits CPU_Core_Dyn_X86_Trap_Run(void); -Bits CPU_Core_Dynrec_Run(void); -Bits CPU_Core_Dynrec_Trap_Run(void); -Bits CPU_Core_Prefetch_Run(void); -Bits CPU_Core_Prefetch_Trap_Run(void); - -void CPU_Enable_SkipAutoAdjust(void); -void CPU_Disable_SkipAutoAdjust(void); -void CPU_Reset_AutoAdjust(void); - - -//CPU Stuff - -extern Bit16u parity_lookup[256]; - -bool CPU_LLDT(Bitu selector); -bool CPU_LTR(Bitu selector); -void CPU_LIDT(Bitu limit,Bitu base); -void CPU_LGDT(Bitu limit,Bitu base); - -Bitu CPU_STR(void); -Bitu CPU_SLDT(void); -Bitu CPU_SIDT_base(void); -Bitu CPU_SIDT_limit(void); -Bitu CPU_SGDT_base(void); -Bitu CPU_SGDT_limit(void); - -void CPU_ARPL(Bitu & dest_sel,Bitu src_sel); -void CPU_LAR(Bitu selector,Bitu & ar); -void CPU_LSL(Bitu selector,Bitu & limit); - -void CPU_SET_CRX(Bitu cr,Bitu value); -bool CPU_WRITE_CRX(Bitu cr,Bitu value); -Bitu CPU_GET_CRX(Bitu cr); -bool CPU_READ_CRX(Bitu cr,Bit32u & retvalue); - -bool CPU_WRITE_DRX(Bitu dr,Bitu value); -bool CPU_READ_DRX(Bitu dr,Bit32u & retvalue); - -bool CPU_WRITE_TRX(Bitu dr,Bitu value); -bool CPU_READ_TRX(Bitu dr,Bit32u & retvalue); - -Bitu CPU_SMSW(void); -bool CPU_LMSW(Bitu word); - -void CPU_VERR(Bitu selector); -void CPU_VERW(Bitu selector); - -void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip); -void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip); -void CPU_RET(bool use32,Bitu bytes,Bitu oldeip); -void CPU_IRET(bool use32,Bitu oldeip); -void CPU_HLT(Bitu oldeip); - -bool CPU_POPF(Bitu use32); -bool CPU_PUSHF(Bitu use32); -bool CPU_CLI(void); -bool CPU_STI(void); - -bool CPU_IO_Exception(Bitu port,Bitu size); -void CPU_RunException(void); - -void CPU_ENTER(bool use32,Bitu bytes,Bitu level); - -#define CPU_INT_SOFTWARE 0x1 -#define CPU_INT_EXCEPTION 0x2 -#define CPU_INT_HAS_ERROR 0x4 -#define CPU_INT_NOIOPLCHECK 0x8 - -void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip); -static INLINE void CPU_HW_Interrupt(Bitu num) { - CPU_Interrupt(num,0,reg_eip); -} -static INLINE void CPU_SW_Interrupt(Bitu num,Bitu oldeip) { - CPU_Interrupt(num,CPU_INT_SOFTWARE,oldeip); -} -static INLINE void CPU_SW_Interrupt_NoIOPLCheck(Bitu num,Bitu oldeip) { - CPU_Interrupt(num,CPU_INT_SOFTWARE|CPU_INT_NOIOPLCHECK,oldeip); -} - -bool CPU_PrepareException(Bitu which,Bitu error); -void CPU_Exception(Bitu which,Bitu error=0); - -bool CPU_SetSegGeneral(SegNames seg,Bitu value); -bool CPU_PopSeg(SegNames seg,bool use32); - -bool CPU_CPUID(void); -Bitu CPU_Pop16(void); -Bitu CPU_Pop32(void); -void CPU_Push16(Bitu value); -void CPU_Push32(Bitu value); - -void CPU_SetFlags(Bitu word,Bitu mask); - - -#define EXCEPTION_UD 6 -#define EXCEPTION_TS 10 -#define EXCEPTION_NP 11 -#define EXCEPTION_SS 12 -#define EXCEPTION_GP 13 -#define EXCEPTION_PF 14 - -#define CR0_PROTECTION 0x00000001 -#define CR0_MONITORPROCESSOR 0x00000002 -#define CR0_FPUEMULATION 0x00000004 -#define CR0_TASKSWITCH 0x00000008 -#define CR0_FPUPRESENT 0x00000010 -#define CR0_PAGING 0x80000000 - - -// ********************************************************************* -// Descriptor -// ********************************************************************* - -#define DESC_INVALID 0x00 -#define DESC_286_TSS_A 0x01 -#define DESC_LDT 0x02 -#define DESC_286_TSS_B 0x03 -#define DESC_286_CALL_GATE 0x04 -#define DESC_TASK_GATE 0x05 -#define DESC_286_INT_GATE 0x06 -#define DESC_286_TRAP_GATE 0x07 - -#define DESC_386_TSS_A 0x09 -#define DESC_386_TSS_B 0x0b -#define DESC_386_CALL_GATE 0x0c -#define DESC_386_INT_GATE 0x0e -#define DESC_386_TRAP_GATE 0x0f - -/* EU/ED Expand UP/DOWN RO/RW Read Only/Read Write NA/A Accessed */ -#define DESC_DATA_EU_RO_NA 0x10 -#define DESC_DATA_EU_RO_A 0x11 -#define DESC_DATA_EU_RW_NA 0x12 -#define DESC_DATA_EU_RW_A 0x13 -#define DESC_DATA_ED_RO_NA 0x14 -#define DESC_DATA_ED_RO_A 0x15 -#define DESC_DATA_ED_RW_NA 0x16 -#define DESC_DATA_ED_RW_A 0x17 - -/* N/R Readable NC/C Confirming A/NA Accessed */ -#define DESC_CODE_N_NC_A 0x18 -#define DESC_CODE_N_NC_NA 0x19 -#define DESC_CODE_R_NC_A 0x1a -#define DESC_CODE_R_NC_NA 0x1b -#define DESC_CODE_N_C_A 0x1c -#define DESC_CODE_N_C_NA 0x1d -#define DESC_CODE_R_C_A 0x1e -#define DESC_CODE_R_C_NA 0x1f - -#ifdef _MSC_VER -#pragma pack (1) -#endif - -struct S_Descriptor { -#ifdef WORDS_BIGENDIAN - Bit32u base_0_15 :16; - Bit32u limit_0_15 :16; - Bit32u base_24_31 :8; - Bit32u g :1; - Bit32u big :1; - Bit32u r :1; - Bit32u avl :1; - Bit32u limit_16_19 :4; - Bit32u p :1; - Bit32u dpl :2; - Bit32u type :5; - Bit32u base_16_23 :8; -#else - Bit32u limit_0_15 :16; - Bit32u base_0_15 :16; - Bit32u base_16_23 :8; - Bit32u type :5; - Bit32u dpl :2; - Bit32u p :1; - Bit32u limit_16_19 :4; - Bit32u avl :1; - Bit32u r :1; - Bit32u big :1; - Bit32u g :1; - Bit32u base_24_31 :8; -#endif -}GCC_ATTRIBUTE(packed); - -struct G_Descriptor { -#ifdef WORDS_BIGENDIAN - Bit32u selector: 16; - Bit32u offset_0_15 :16; - Bit32u offset_16_31 :16; - Bit32u p :1; - Bit32u dpl :2; - Bit32u type :5; - Bit32u reserved :3; - Bit32u paramcount :5; -#else - Bit32u offset_0_15 :16; - Bit32u selector :16; - Bit32u paramcount :5; - Bit32u reserved :3; - Bit32u type :5; - Bit32u dpl :2; - Bit32u p :1; - Bit32u offset_16_31 :16; -#endif -} GCC_ATTRIBUTE(packed); - -struct TSS_16 { - Bit16u back; /* Back link to other task */ - Bit16u sp0; /* The CK stack pointer */ - Bit16u ss0; /* The CK stack selector */ - Bit16u sp1; /* The parent KL stack pointer */ - Bit16u ss1; /* The parent KL stack selector */ - Bit16u sp2; /* Unused */ - Bit16u ss2; /* Unused */ - Bit16u ip; /* The instruction pointer */ - Bit16u flags; /* The flags */ - Bit16u ax, cx, dx, bx; /* The general purpose registers */ - Bit16u sp, bp, si, di; /* The special purpose registers */ - Bit16u es; /* The extra selector */ - Bit16u cs; /* The code selector */ - Bit16u ss; /* The application stack selector */ - Bit16u ds; /* The data selector */ - Bit16u ldt; /* The local descriptor table */ -} GCC_ATTRIBUTE(packed); - -struct TSS_32 { - Bit32u back; /* Back link to other task */ - Bit32u esp0; /* The CK stack pointer */ - Bit32u ss0; /* The CK stack selector */ - Bit32u esp1; /* The parent KL stack pointer */ - Bit32u ss1; /* The parent KL stack selector */ - Bit32u esp2; /* Unused */ - Bit32u ss2; /* Unused */ - Bit32u cr3; /* The page directory pointer */ - Bit32u eip; /* The instruction pointer */ - Bit32u eflags; /* The flags */ - Bit32u eax, ecx, edx, ebx; /* The general purpose registers */ - Bit32u esp, ebp, esi, edi; /* The special purpose registers */ - Bit32u es; /* The extra selector */ - Bit32u cs; /* The code selector */ - Bit32u ss; /* The application stack selector */ - Bit32u ds; /* The data selector */ - Bit32u fs; /* And another extra selector */ - Bit32u gs; /* ... and another one */ - Bit32u ldt; /* The local descriptor table */ -} GCC_ATTRIBUTE(packed); - -#ifdef _MSC_VER -#pragma pack() -#endif -class Descriptor -{ -public: - Descriptor() { saved.fill[0]=saved.fill[1]=0; } - - void Load(PhysPt address); - void Save(PhysPt address); - - PhysPt GetBase (void) { - return (saved.seg.base_24_31<<24) | (saved.seg.base_16_23<<16) | saved.seg.base_0_15; - } - Bitu GetLimit (void) { - Bitu limit = (saved.seg.limit_16_19<<16) | saved.seg.limit_0_15; - if (saved.seg.g) return (limit<<12) | 0xFFF; - return limit; - } - Bitu GetOffset(void) { - return (saved.gate.offset_16_31 << 16) | saved.gate.offset_0_15; - } - Bitu GetSelector(void) { - return saved.gate.selector; - } - Bitu Type(void) { - return saved.seg.type; - } - Bitu Conforming(void) { - return saved.seg.type & 8; - } - Bitu DPL(void) { - return saved.seg.dpl; - } - Bitu Big(void) { - return saved.seg.big; - } -public: - union { - S_Descriptor seg; - G_Descriptor gate; - Bit32u fill[2]; - } saved; -}; - -class DescriptorTable { -public: - PhysPt GetBase (void) { return table_base; } - Bitu GetLimit (void) { return table_limit; } - void SetBase (PhysPt _base) { table_base = _base; } - void SetLimit (Bitu _limit) { table_limit= _limit; } - - bool GetDescriptor (Bitu selector, Descriptor& desc) { - selector&=~7; - if (selector>=table_limit) return false; - desc.Load(table_base+(selector)); - return true; - } -protected: - PhysPt table_base; - Bitu table_limit; -}; - -class GDTDescriptorTable : public DescriptorTable { -public: - bool GetDescriptor(Bitu selector, Descriptor& desc) { - Bitu address=selector & ~7; - if (selector & 4) { - if (address>=ldt_limit) return false; - desc.Load(ldt_base+address); - return true; - } else { - if (address>=table_limit) return false; - desc.Load(table_base+address); - return true; - } - } - bool SetDescriptor(Bitu selector, Descriptor& desc) { - Bitu address=selector & ~7; - if (selector & 4) { - if (address>=ldt_limit) return false; - desc.Save(ldt_base+address); - return true; - } else { - if (address>=table_limit) return false; - desc.Save(table_base+address); - return true; - } - } - Bitu SLDT(void) { - return ldt_value; - } - bool LLDT(Bitu value) { - if ((value&0xfffc)==0) { - ldt_value=0; - ldt_base=0; - ldt_limit=0; - return true; - } - Descriptor desc; - if (!GetDescriptor(value,desc)) return !CPU_PrepareException(EXCEPTION_GP,value); - if (desc.Type()!=DESC_LDT) return !CPU_PrepareException(EXCEPTION_GP,value); - if (!desc.saved.seg.p) return !CPU_PrepareException(EXCEPTION_NP,value); - ldt_base=desc.GetBase(); - ldt_limit=desc.GetLimit(); - ldt_value=value; - return true; - } -private: - PhysPt ldt_base; - Bitu ldt_limit; - Bitu ldt_value; -}; - -class TSS_Descriptor : public Descriptor { -public: - Bitu IsBusy(void) { - return saved.seg.type & 2; - } - Bitu Is386(void) { - return saved.seg.type & 8; - } - void SetBusy(bool busy) { - if (busy) saved.seg.type|=2; - else saved.seg.type&=~2; - } -}; - - -struct CPUBlock { - Bitu cpl; /* Current Privilege */ - Bitu mpl; - Bitu cr0; - bool pmode; /* Is Protected mode enabled */ - GDTDescriptorTable gdt; - DescriptorTable idt; - struct { - Bitu mask,notmask; - bool big; - } stack; - struct { - bool big; - } code; - struct { - Bitu cs,eip; - CPU_Decoder * old_decoder; - } hlt; - struct { - Bitu which,error; - } exception; - Bits direction; - bool trap_skip; - Bit32u drx[8]; - Bit32u trx[8]; -}; - -extern CPUBlock cpu; - -static INLINE void CPU_SetFlagsd(Bitu word) { - Bitu mask=cpu.cpl ? FMASK_NORMAL : FMASK_ALL; - CPU_SetFlags(word,mask); -} - -static INLINE void CPU_SetFlagsw(Bitu word) { - Bitu mask=(cpu.cpl ? FMASK_NORMAL : FMASK_ALL) & 0xffff; - CPU_SetFlags(word,mask); -} - - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __CPU_H +#define __CPU_H + +#include +#include +#include + +/* Some common Defines */ +/* A CPU Handler */ +typedef Bitu (CPU_Decoder)(Bitu count); +extern CPU_Decoder * cpudecoder; +extern Bit32u cpu_cycles; + + +extern Bit32u hoever; + +//CPU Stuff +void SetCPU16bit(); +void SetSegment_16(Bit32u seg,Bit16u val); + + +//Types of Flag changing instructions +enum { + t_ADDb=0,t_ADDw,t_ADDd, + t_ORb,t_ORw,t_ORd, + t_ADCb,t_ADCw,t_ADCd, + t_SBBb,t_SBBw,t_SBBd, + t_ANDb,t_ANDw,t_ANDd, + t_SUBb,t_SUBw,t_SUBd, + t_XORb,t_XORw,t_XORd, + t_CMPb,t_CMPw,t_CMPd, + t_INCb,t_INCw,t_INCd, + t_DECb,t_DECw,t_DECd, + t_TESTb,t_TESTw,t_TESTd, + t_SHLb,t_SHLw,t_SHLd, + t_SHRb,t_SHRw,t_SHRd, + t_SARb,t_SARw,t_SARd, + t_ROLb,t_ROLw,t_ROLd, + t_RORb,t_RORw,t_RORd, + t_RCLb,t_RCLw,t_RCLd, + t_RCRb,t_RCRw,t_RCRd, + t_NEGb,t_NEGw,t_NEGd, + t_CF,t_ZF, + + t_DSHLw,t_DSHLd, + t_DSHRw,t_DSHRd, + t_MUL,t_DIV, + t_UNKNOWN, + t_NOTDONE, +}; + +enum { rep_NONE,rep_Z,rep_NZ }; + + +void Interrupt(Bit8u num); + +//Flag Handling +bool get_CF(void); +bool get_AF(void); +bool get_ZF(void); +bool get_SF(void); +bool get_OF(void); +bool get_PF(void); + +Bit8u get_Flags8(void); + + + + +#define LoadCF flags.cf=get_CF(); +#define LoadZF flags.zf=get_ZF(); +#define LoadSF flags.sf=get_SF(); +#define LoadOF flags.of=get_OF(); +//The opcode handlers + + +void FPU_ESC0_Normal(Bitu rm); +void FPU_ESC0_EA(Bitu func,PhysOff ea); + +#endif + diff --git a/include/cross.h b/include/cross.h index ef904bd..20d2d5a 100644 --- a/include/cross.h +++ b/include/cross.h @@ -1,108 +1,54 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: cross.h,v 1.21 2009/03/14 18:02:34 qbix79 Exp $ */ - -#ifndef DOSBOX_CROSS_H -#define DOSBOX_CROSS_H - -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif - -#include -#include -#include -#include - -#if defined (_MSC_VER) /* MS Visual C++ */ -#include -#include -#define LONGTYPE(a) a##i64 -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#else /* LINUX / GCC */ -#include -#include -#define LONGTYPE(a) a##LL -#endif - -#define CROSS_LEN 512 /* Maximum filename size */ - - -#if defined (WIN32) || defined (OS2) /* Win 32 & OS/2*/ -#define CROSS_FILENAME(blah) -#define CROSS_FILESPLIT '\\' -#define F_OK 0 -#else -#define CROSS_FILENAME(blah) strreplace(blah,'\\','/') -#define CROSS_FILESPLIT '/' -#endif - -#define CROSS_NONE 0 -#define CROSS_FILE 1 -#define CROSS_DIR 2 -#if defined (WIN32) -#define ftruncate(blah,blah2) chsize(blah,blah2) -#endif - -//Solaris maybe others -#if defined (DB_HAVE_NO_POWF) -#include -static inline float powf (float x, float y) { return (float) pow (x,y); } -#endif - -class Cross { -public: - static void GetPlatformConfigDir(std::string& in); - static void GetPlatformConfigName(std::string& in); - static void CreatePlatformConfigDir(std::string& in); - static void ResolveHomedir(std::string & temp_line); - static void CreateDir(std::string const& temp); -}; - - -#if defined (WIN32) - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from -#include - -typedef struct dir_struct { - HANDLE handle; - char base_path[MAX_PATH+4]; - WIN32_FIND_DATA search_data; -} dir_information; - -#else - -//#include //Included above -#include - -typedef struct dir_struct { - DIR* dir; - char base_path[CROSS_LEN]; -} dir_information; - -#endif - -dir_information* open_directory(const char* dirname); -bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory); -bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory); -void close_directory(dir_information* dirp); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _CROSS_H +#define _CROSS_H + +#include +#include +#include + +#if defined (_MSC_VER) /* MS Visual C++ */ +#include +#include +#else /* LINUX */ +#include +#include +#endif + +#define CROSS_LEN 512 /* Maximum filename size */ + + +#if defined (_MSC_VER) /* MS Visual C++ */ +#define CROSS_FILENAME(blah) +#define CROSS_FILESPLIT '\\' +#define F_OK 0 +#else +#define CROSS_FILENAME(blah) strreplace(blah,'\\','/') +#define CROSS_FILESPLIT '/' +#endif + +#define CROSS_NONE 0 +#define CROSS_FILE 1 +#define CROSS_DIR 2 + + +extern const char * dosbox_datadir; + +#endif + diff --git a/include/debug.h b/include/debug.h index a563f8b..20deed7 100644 --- a/include/debug.h +++ b/include/debug.h @@ -1,35 +1,24 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -void DEBUG_SetupConsole(void); -void DEBUG_DrawScreen(void); -bool DEBUG_Breakpoint(void); -bool DEBUG_IntBreakpoint(Bit8u intNum); -void DEBUG_Enable(bool pressed); -void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off); -bool DEBUG_ExitLoop(void); -void DEBUG_RefreshPage(char scroll); -Bitu DEBUG_EnableDebugger(void); - -extern Bitu cycle_count; -extern Bitu debugCallback; - -#ifdef C_HEAVY_DEBUG -bool DEBUG_HeavyIsBreakpoint(void); -void DEBUG_HeavyWriteLogInstruction(void); -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +void DEBUG_DrawScreen(void); +bool DEBUG_BreakPoint(void); +void DEBUG_Enable(void); + +extern Bitu cycle_count; + diff --git a/include/dma.h b/include/dma.h index 4e1c737..e6923da 100644 --- a/include/dma.h +++ b/include/dma.h @@ -1,117 +1,24 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dma.h,v 1.18 2008/09/13 20:04:28 c2woody Exp $ */ - -#ifndef DOSBOX_DMA_H -#define DOSBOX_DMA_H - -enum DMAEvent { - DMA_REACHED_TC, - DMA_MASKED, - DMA_UNMASKED, - DMA_TRANSFEREND -}; - -class DmaChannel; -typedef void (* DMA_CallBack)(DmaChannel * chan,DMAEvent event); - -class DmaChannel { -public: - Bit32u pagebase; - Bit16u baseaddr; - Bit16u curraddr; - Bit16u basecnt; - Bit16u currcnt; - Bit8u channum; - Bit8u pagenum; - Bit8u DMA16; - bool increment; - bool autoinit; - Bit8u trantype; - bool masked; - bool tcount; - bool request; - DMA_CallBack callback; - - DmaChannel(Bit8u num, bool dma16); - void DoCallBack(DMAEvent event) { - if (callback) (*callback)(this,event); - } - void SetMask(bool _mask) { - masked=_mask; - DoCallBack(masked ? DMA_MASKED : DMA_UNMASKED); - } - void Register_Callback(DMA_CallBack _cb) { - callback = _cb; - SetMask(masked); - if (callback) Raise_Request(); - else Clear_Request(); - } - void ReachedTC(void) { - tcount=true; - DoCallBack(DMA_REACHED_TC); - } - void SetPage(Bit8u val) { - pagenum=val; - pagebase=(pagenum >> DMA16) << (16+DMA16); - } - void Raise_Request(void) { - request=true; - } - void Clear_Request(void) { - request=false; - } - Bitu Read(Bitu size, Bit8u * buffer); - Bitu Write(Bitu size, Bit8u * buffer); -}; - -class DmaController { -private: - Bit8u ctrlnum; - bool flipflop; - DmaChannel *DmaChannels[4]; -public: - IO_ReadHandleObject DMA_ReadHandler[0x11]; - IO_WriteHandleObject DMA_WriteHandler[0x11]; - DmaController(Bit8u num) { - flipflop = false; - ctrlnum = num; /* first or second DMA controller */ - for(Bit8u i=0;i<4;i++) { - DmaChannels[i] = new DmaChannel(i+ctrlnum*4,ctrlnum==1); - } - } - ~DmaController(void) { - for(Bit8u i=0;i<4;i++) { - delete DmaChannels[i]; - } - } - DmaChannel * GetChannel(Bit8u chan) { - if (chan<4) return DmaChannels[chan]; - else return NULL; - } - void WriteControllerReg(Bitu reg,Bitu val,Bitu len); - Bitu ReadControllerReg(Bitu reg,Bitu len); -}; - -DmaChannel * GetDMAChannel(Bit8u chan); - -void CloseSecondDMAController(void); -bool SecondDMAControllerAvailable(void); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +void DMA_8_Read(Bit32u channel,Bit8u * buffer,Bit16u count); +void DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count); + +void DMA_16_Read(Bit32u channel,Bit8u * buffer,Bit16u count); +void DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count); + diff --git a/include/dos_inc.h b/include/dos_inc.h index fa128d9..32414ca 100644 --- a/include/dos_inc.h +++ b/include/dos_inc.h @@ -1,643 +1,275 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos_inc.h,v 1.77 2009/04/25 16:25:03 harekiet Exp $ */ - -#ifndef DOSBOX_DOS_INC_H -#define DOSBOX_DOS_INC_H - -#ifndef DOSBOX_DOS_SYSTEM_H -#include "dos_system.h" -#endif -#ifndef DOSBOX_MEM_H -#include "mem.h" -#endif - -#ifdef _MSC_VER -#pragma pack (1) -#endif -struct CommandTail{ - Bit8u count; /* number of bytes returned */ - char buffer[127]; /* the buffer itself */ -} GCC_ATTRIBUTE(packed); -#ifdef _MSC_VER -#pragma pack () -#endif - -struct DOS_Date { - Bit16u year; - Bit8u month; - Bit8u day; -}; - -struct DOS_Version { - Bit8u major,minor,revision; -}; - - -#ifdef _MSC_VER -#pragma pack (1) -#endif -union bootSector { - struct entries { - Bit8u jump[3]; - Bit8u oem_name[8]; - Bit16u bytesect; - Bit8u sectclust; - Bit16u reserve_sect; - Bit8u misc[496]; - } bootdata; - Bit8u rawdata[512]; -} GCC_ATTRIBUTE(packed); -#ifdef _MSC_VER -#pragma pack () -#endif - - -enum { MCB_FREE=0x0000,MCB_DOS=0x0008 }; -enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3}; - -#define DOS_FILES 127 -#define DOS_DRIVES 26 -#define DOS_DEVICES 10 - - -// dos swappable area is 0x320 bytes beyond the sysvars table -// device driver chain is inside sysvars -#define DOS_INFOBLOCK_SEG 0x80 // sysvars (list of lists) -#define DOS_CONDRV_SEG 0xa0 -#define DOS_CONSTRING_SEG 0xa8 -#define DOS_SDA_SEG 0xb2 // dos swappable area -#define DOS_SDA_OFS 0 -#define DOS_CDS_SEG 0x108 -#define DOS_FIRST_SHELL 0x118 -#define DOS_MEM_START 0x158 //First Segment that DOS can use - -#define DOS_PRIVATE_SEGMENT 0xc800 -#define DOS_PRIVATE_SEGMENT_END 0xd000 - -/* internal Dos Tables */ - -extern DOS_File * Files[DOS_FILES]; -extern DOS_Drive * Drives[DOS_DRIVES]; -extern DOS_Device * Devices[DOS_DEVICES]; - -extern Bit8u dos_copybuf[0x10000]; - - -void DOS_SetError(Bit16u code); - -/* File Handling Routines */ - -enum { STDIN=0,STDOUT=1,STDERR=2,STDAUX=3,STDPRN=4}; -enum { HAND_NONE=0,HAND_FILE,HAND_DEVICE}; - -/* Routines for File Class */ -void DOS_SetupFiles (void); -bool DOS_ReadFile(Bit16u handle,Bit8u * data,Bit16u * amount); -bool DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount); -bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type); -bool DOS_CloseFile(Bit16u handle); -bool DOS_FlushFile(Bit16u handle); -bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry); -bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry); -bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate); - -/* Routines for Drive Class */ -bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry); -bool DOS_OpenFileExtended(char const * name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status); -bool DOS_CreateFile(char const * name,Bit16u attribute,Bit16u * entry); -bool DOS_UnlinkFile(char const * const name); -bool DOS_FindFirst(char *search,Bit16u attr,bool fcb_findfirst=false); -bool DOS_FindNext(void); -bool DOS_Canonicalize(char const * const name,char * const big); -bool DOS_CreateTempFile(char * const name,Bit16u * entry); -bool DOS_FileExists(char const * const name); - -/* Helper Functions */ -bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive); -/* Drive Handing Routines */ -Bit8u DOS_GetDefaultDrive(void); -void DOS_SetDefaultDrive(Bit8u drive); -bool DOS_SetDrive(Bit8u drive); -bool DOS_GetCurrentDir(Bit8u drive,char * const buffer); -bool DOS_ChangeDir(char const * const dir); -bool DOS_MakeDir(char const * const dir); -bool DOS_RemoveDir(char const * const dir); -bool DOS_Rename(char const * const oldname,char const * const newname); -bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * clusters,Bit16u * free); -bool DOS_GetFileAttr(char const * const name,Bit16u * attr); -bool DOS_SetFileAttr(char const * const name,Bit16u attr); - -/* IOCTL Stuff */ -bool DOS_IOCTL(void); -bool DOS_GetSTDINStatus(); -Bit8u DOS_FindDevice(char const * name); -void DOS_SetupDevices(void); - -/* Execute and new process creation */ -bool DOS_NewPSP(Bit16u pspseg,Bit16u size); -bool DOS_ChildPSP(Bit16u pspseg,Bit16u size); -bool DOS_Execute(char * name,PhysPt block,Bit8u flags); -bool DOS_Terminate(bool tsr,Bit8u exitcode); - -/* Memory Handling Routines */ -void DOS_SetupMemory(void); -bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks); -bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks); -bool DOS_FreeMemory(Bit16u segment); -void DOS_FreeProcessMemory(Bit16u pspseg); -Bit16u DOS_GetMemory(Bit16u pages); -bool DOS_SetMemAllocStrategy(Bit16u strat); -Bit16u DOS_GetMemAllocStrategy(void); -void DOS_BuildUMBChain(bool umb_active,bool ems_active); -bool DOS_LinkUMBsToMemChain(Bit16u linkstate); - -/* FCB stuff */ -bool DOS_FCBOpen(Bit16u seg,Bit16u offset); -bool DOS_FCBCreate(Bit16u seg,Bit16u offset); -bool DOS_FCBClose(Bit16u seg,Bit16u offset); -bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset); -bool DOS_FCBFindNext(Bit16u seg,Bit16u offset); -Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset, Bit16u numBlocks); -Bit8u DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u numBlocks); -Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore); -Bit8u DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore); -bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset); -bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset); -bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset); -void DOS_FCBSetRandomRecord(Bit16u seg, Bit16u offset); -Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change); -bool DOS_GetAllocationInfo(Bit8u drive,Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters); - -/* Extra DOS Interrupts */ -void DOS_SetupMisc(void); - -/* The DOS Tables */ -void DOS_SetupTables(void); - -/* Internal DOS Setup Programs */ -void DOS_SetupPrograms(void); - -/* Initialize Keyboard Layout */ -void DOS_KeyboardLayout_Init(Section* sec); - -bool DOS_LayoutKey(Bitu key, Bit8u flags1, Bit8u flags2, Bit8u flags3); - -enum { - KEYB_NOERROR=0, - KEYB_FILENOTFOUND, - KEYB_INVALIDFILE, - KEYB_LAYOUTNOTFOUND, - KEYB_INVALIDCPFILE -}; - - -static INLINE Bit16u long2para(Bit32u size) { - if (size>0xFFFF0) return 0xffff; - if (size&0xf) return (Bit16u)((size>>4)+1); - else return (Bit16u)(size>>4); -} - - -static INLINE Bit16u DOS_PackTime(Bit16u hour,Bit16u min,Bit16u sec) { - return (hour&0x1f)<<11 | (min&0x3f) << 5 | ((sec/2)&0x1f); -} - -static INLINE Bit16u DOS_PackDate(Bit16u year,Bit16u mon,Bit16u day) { - return ((year-1980)&0x7f)<<9 | (mon&0x3f) << 5 | (day&0x1f); -} - -/* Dos Error Codes */ -#define DOSERR_NONE 0 -#define DOSERR_FUNCTION_NUMBER_INVALID 1 -#define DOSERR_FILE_NOT_FOUND 2 -#define DOSERR_PATH_NOT_FOUND 3 -#define DOSERR_TOO_MANY_OPEN_FILES 4 -#define DOSERR_ACCESS_DENIED 5 -#define DOSERR_INVALID_HANDLE 6 -#define DOSERR_MCB_DESTROYED 7 -#define DOSERR_INSUFFICIENT_MEMORY 8 -#define DOSERR_MB_ADDRESS_INVALID 9 -#define DOSERR_ENVIRONMENT_INVALID 10 -#define DOSERR_FORMAT_INVALID 11 -#define DOSERR_ACCESS_CODE_INVALID 12 -#define DOSERR_DATA_INVALID 13 -#define DOSERR_RESERVED 14 -#define DOSERR_FIXUP_OVERFLOW 14 -#define DOSERR_INVALID_DRIVE 15 -#define DOSERR_REMOVE_CURRENT_DIRECTORY 16 -#define DOSERR_NOT_SAME_DEVICE 17 -#define DOSERR_NO_MORE_FILES 18 -#define DOSERR_FILE_ALREADY_EXISTS 80 - - -/* Remains some classes used to access certain things */ -#define sOffset(s,m) ((char*)&(((s*)NULL)->m)-(char*)NULL) -#define sGet(s,m) GetIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m)) -#define sSave(s,m,val) SaveIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m),val) - -class MemStruct { -public: - Bitu GetIt(Bitu size,PhysPt addr) { - switch (size) { - case 1:return mem_readb(pt+addr); - case 2:return mem_readw(pt+addr); - case 4:return mem_readd(pt+addr); - } - return 0; - } - void SaveIt(Bitu size,PhysPt addr,Bitu val) { - switch (size) { - case 1:mem_writeb(pt+addr,(Bit8u)val);break; - case 2:mem_writew(pt+addr,(Bit16u)val);break; - case 4:mem_writed(pt+addr,(Bit32u)val);break; - } - } - void SetPt(Bit16u seg) { pt=PhysMake(seg,0);} - void SetPt(Bit16u seg,Bit16u off) { pt=PhysMake(seg,off);} - void SetPt(RealPt addr) { pt=Real2Phys(addr);} -protected: - PhysPt pt; -}; - -class DOS_PSP :public MemStruct { -public: - DOS_PSP (Bit16u segment) { SetPt(segment);seg=segment;}; - void MakeNew (Bit16u memSize); - void CopyFileTable (DOS_PSP* srcpsp,bool createchildpsp); - Bit16u FindFreeFileEntry (void); - void CloseFiles (void); - - void SaveVectors (void); - void RestoreVectors (void); - void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); }; - Bit16u GetSize (void) { return (Bit16u)sGet(sPSP,next_seg); }; - void SetEnvironment (Bit16u envseg) { sSave(sPSP,environment,envseg); }; - Bit16u GetEnvironment (void) { return (Bit16u)sGet(sPSP,environment); }; - Bit16u GetSegment (void) { return seg; }; - void SetFileHandle (Bit16u index, Bit8u handle); - Bit8u GetFileHandle (Bit16u index); - void SetParent (Bit16u parent) { sSave(sPSP,psp_parent,parent); }; - Bit16u GetParent (void) { return (Bit16u)sGet(sPSP,psp_parent); }; - void SetStack (RealPt stackpt) { sSave(sPSP,stack,stackpt); }; - RealPt GetStack (void) { return sGet(sPSP,stack); }; - void SetInt22 (RealPt int22pt) { sSave(sPSP,int_22,int22pt); }; - RealPt GetInt22 (void) { return sGet(sPSP,int_22); }; - void SetFCB1 (RealPt src); - void SetFCB2 (RealPt src); - void SetCommandTail (RealPt src); - bool SetNumFiles (Bit16u fileNum); - Bit16u FindEntryByHandle (Bit8u handle); - -private: - #ifdef _MSC_VER - #pragma pack(1) - #endif - struct sPSP { - Bit8u exit[2]; /* CP/M-like exit poimt */ - Bit16u next_seg; /* Segment of first byte beyond memory allocated or program */ - Bit8u fill_1; /* single char fill */ - Bit8u far_call; /* far call opcode */ - RealPt cpm_entry; /* CPM Service Request address*/ - RealPt int_22; /* Terminate Address */ - RealPt int_23; /* Break Address */ - RealPt int_24; /* Critical Error Address */ - Bit16u psp_parent; /* Parent PSP Segment */ - Bit8u files[20]; /* File Table - 0xff is unused */ - Bit16u environment; /* Segment of evironment table */ - RealPt stack; /* SS:SP Save point for int 0x21 calls */ - Bit16u max_files; /* Maximum open files */ - RealPt file_table; /* Pointer to File Table PSP:0x18 */ - RealPt prev_psp; /* Pointer to previous PSP */ - Bit8u interim_flag; - Bit8u truename_flag; - Bit16u nn_flags; - Bit16u dos_version; - Bit8u fill_2[14]; /* Lot's of unused stuff i can't care aboue */ - Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */ - Bit8u fill_3[9]; /* This has some blocks with FCB info */ - Bit8u fcb1[16]; /* first FCB */ - Bit8u fcb2[16]; /* second FCB */ - Bit8u fill_4[4]; /* unused */ - CommandTail cmdtail; - } GCC_ATTRIBUTE(packed); - #ifdef _MSC_VER - #pragma pack() - #endif - Bit16u seg; -public: - static Bit16u rootpsp; -}; - -class DOS_ParamBlock:public MemStruct { -public: - DOS_ParamBlock(PhysPt addr) {pt=addr;} - void Clear(void); - void LoadData(void); - void SaveData(void); /* Save it as an exec block */ - #ifdef _MSC_VER - #pragma pack (1) - #endif - struct sOverlay { - Bit16u loadseg; - Bit16u relocation; - } GCC_ATTRIBUTE(packed); - struct sExec { - Bit16u envseg; - RealPt cmdtail; - RealPt fcb1; - RealPt fcb2; - RealPt initsssp; - RealPt initcsip; - }GCC_ATTRIBUTE(packed); - #ifdef _MSC_VER - #pragma pack() - #endif - sExec exec; - sOverlay overlay; -}; - -class DOS_InfoBlock:public MemStruct { -public: - DOS_InfoBlock () {}; - void SetLocation(Bit16u seg); - void SetFirstMCB(Bit16u _first_mcb); - void SetBuffers(Bit16u x,Bit16u y); - void SetCurDirStruct(Bit32u _curdirstruct); - void SetFCBTable(Bit32u _fcbtable); - void SetDeviceChainStart(Bit32u _devchain); - void SetDiskBufferHeadPt(Bit32u _dbheadpt); - void SetStartOfUMBChain(Bit16u _umbstartseg); - void SetUMBChainState(Bit8u _umbchaining); - Bit16u GetStartOfUMBChain(void); - Bit8u GetUMBChainState(void); - RealPt GetPointer(void); - Bit32u GetDeviceChain(void); - - #ifdef _MSC_VER - #pragma pack(1) - #endif - struct sDIB { - Bit8u unknown1[4]; - Bit16u magicWord; // -0x22 needs to be 1 - Bit8u unknown2[8]; - Bit16u regCXfrom5e; // -0x18 CX from last int21/ah=5e - Bit16u countLRUcache; // -0x16 LRU counter for FCB caching - Bit16u countLRUopens; // -0x14 LRU counter for FCB openings - Bit8u stuff[6]; // -0x12 some stuff, hopefully never used.... - Bit16u sharingCount; // -0x0c sharing retry count - Bit16u sharingDelay; // -0x0a sharing retry delay - RealPt diskBufPtr; // -0x08 pointer to disk buffer - Bit16u ptrCONinput; // -0x04 pointer to con input - Bit16u firstMCB; // -0x02 first memory control block - RealPt firstDPB; // 0x00 first drive parameter block - RealPt firstFileTable; // 0x04 first system file table - RealPt activeClock; // 0x08 active clock device header - RealPt activeCon; // 0x0c active console device header - Bit16u maxSectorLength; // 0x10 maximum bytes per sector of any block device; - RealPt diskInfoBuffer; // 0x12 pointer to disk info buffer - RealPt curDirStructure; // 0x16 pointer to current array of directory structure - RealPt fcbTable; // 0x1a pointer to system FCB table - Bit16u protFCBs; // 0x1e protected fcbs - Bit8u blockDevices; // 0x20 installed block devices - Bit8u lastdrive; // 0x21 lastdrive - Bit32u nulNextDriver; // 0x22 NUL driver next pointer - Bit16u nulAttributes; // 0x26 NUL driver aattributes - Bit32u nulStrategy; // 0x28 NUL driver strategy routine - Bit8u nulString[8]; // 0x2c NUL driver name string - Bit8u joindedDrives; // 0x34 joined drives - Bit16u specialCodeSeg; // 0x35 special code segment - RealPt setverPtr; // 0x37 pointer to setver - Bit16u a20FixOfs; // 0x3b a20 fix routine offset - Bit16u pspLastIfHMA; // 0x3d psp of last program (if dos in hma) - Bit16u buffers_x; // 0x3f x in BUFFERS x,y - Bit16u buffers_y; // 0x41 y in BUFFERS x,y - Bit8u bootDrive; // 0x43 boot drive - Bit8u useDwordMov; // 0x44 use dword moves - Bit16u extendedSize; // 0x45 size of extended memory - Bit32u diskBufferHeadPt; // 0x47 pointer to least-recently used buffer header - Bit16u dirtyDiskBuffers; // 0x4b number of dirty disk buffers - Bit32u lookaheadBufPt; // 0x4d pointer to lookahead buffer - Bit16u lookaheadBufNumber; // 0x51 number of lookahead buffers - Bit8u bufferLocation; // 0x53 workspace buffer location - Bit32u workspaceBuffer; // 0x54 pointer to workspace buffer - Bit8u unknown3[11]; // 0x58 - Bit8u chainingUMB; // 0x63 bit0: UMB chain linked to MCB chain - Bit16u minMemForExec; // 0x64 minimum paragraphs needed for current program - Bit16u startOfUMBChain; // 0x66 segment of first UMB-MCB - Bit16u memAllocScanStart; // 0x68 start paragraph for memory allocation - } GCC_ATTRIBUTE(packed); - #ifdef _MSC_VER - #pragma pack () - #endif - Bit16u seg; -}; - -class DOS_DTA:public MemStruct{ -public: - DOS_DTA(RealPt addr) { SetPt(addr); } - - void SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * _pattern); - void SetResult(const char * _name,Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr); - - Bit8u GetSearchDrive(void); - void GetSearchParams(Bit8u & _sattr,char * _spattern); - void GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr); - - void SetDirID(Bit16u entry) { sSave(sDTA,dirID,entry); }; - void SetDirIDCluster(Bit16u entry) { sSave(sDTA,dirCluster,entry); }; - Bit16u GetDirID(void) { return (Bit16u)sGet(sDTA,dirID); }; - Bit16u GetDirIDCluster(void) { return (Bit16u)sGet(sDTA,dirCluster); }; -private: - #ifdef _MSC_VER - #pragma pack(1) - #endif - struct sDTA { - Bit8u sdrive; /* The Drive the search is taking place */ - Bit8u sname[8]; /* The Search pattern for the filename */ - Bit8u sext[3]; /* The Search pattern for the extenstion */ - Bit8u sattr; /* The Attributes that need to be found */ - Bit16u dirID; /* custom: dir-search ID for multiple searches at the same time */ - Bit16u dirCluster; /* custom (drive_fat only): cluster number for multiple searches at the same time */ - Bit8u fill[4]; - Bit8u attr; - Bit16u time; - Bit16u date; - Bit32u size; - char name[DOS_NAMELENGTH_ASCII]; - } GCC_ATTRIBUTE(packed); - #ifdef _MSC_VER - #pragma pack() - #endif -}; - -class DOS_FCB: public MemStruct { -public: - DOS_FCB(Bit16u seg,Bit16u off); - void Create(bool _extended); - void SetName(Bit8u _drive,char * _fname,char * _ext); - void SetSizeDateTime(Bit32u _size,Bit16u _date,Bit16u _time); - void GetSizeDateTime(Bit32u & _size,Bit16u & _date,Bit16u & _time); - void GetName(char * fillname); - void FileOpen(Bit8u _fhandle); - void FileClose(Bit8u & _fhandle); - void GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec); - void SetRecord(Bit16u _cur_block,Bit8u _cur_rec); - void GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size); - void GetRandom(Bit32u & _random); - void SetRandom(Bit32u _random); - Bit8u GetDrive(void); - bool Extended(void); - void GetAttr(Bit8u & attr); - void SetAttr(Bit8u attr); - bool Valid(void); -private: - bool extended; - PhysPt real_pt; - #ifdef _MSC_VER - #pragma pack (1) - #endif - struct sFCB { - Bit8u drive; /* Drive number 0=default, 1=A, etc */ - Bit8u filename[8]; /* Space padded name */ - Bit8u ext[3]; /* Space padded extension */ - Bit16u cur_block; /* Current Block */ - Bit16u rec_size; /* Logical record size */ - Bit32u filesize; /* File Size */ - Bit16u date; - Bit16u time; - /* Reserved Block should be 8 bytes */ - Bit8u sft_entries; - Bit8u share_attributes; - Bit8u extra_info; - Bit8u file_handle; - Bit8u reserved[4]; - /* end */ - Bit8u cur_rec; /* Current record in current block */ - Bit32u rndm; /* Current relative record number */ - } GCC_ATTRIBUTE(packed); - #ifdef _MSC_VER - #pragma pack () - #endif -}; - -class DOS_MCB : public MemStruct{ -public: - DOS_MCB(Bit16u seg) { SetPt(seg); } - void SetFileName(char const * const _name) { MEM_BlockWrite(pt+offsetof(sMCB,filename),_name,8); } - void GetFileName(char * const _name) { MEM_BlockRead(pt+offsetof(sMCB,filename),_name,8);_name[8]=0;} - void SetType(Bit8u _type) { sSave(sMCB,type,_type);} - void SetSize(Bit16u _size) { sSave(sMCB,size,_size);} - void SetPSPSeg(Bit16u _pspseg) { sSave(sMCB,psp_segment,_pspseg);} - Bit8u GetType(void) { return (Bit8u)sGet(sMCB,type);} - Bit16u GetSize(void) { return (Bit16u)sGet(sMCB,size);} - Bit16u GetPSPSeg(void) { return (Bit16u)sGet(sMCB,psp_segment);} -private: - #ifdef _MSC_VER - #pragma pack (1) - #endif - struct sMCB { - Bit8u type; - Bit16u psp_segment; - Bit16u size; - Bit8u unused[3]; - Bit8u filename[8]; - } GCC_ATTRIBUTE(packed); - #ifdef _MSC_VER - #pragma pack () - #endif -}; - -class DOS_SDA : public MemStruct { -public: - DOS_SDA(Bit16u _seg,Bit16u _offs) { SetPt(_seg,_offs); } - void Init(); - void SetDrive(Bit8u _drive) { sSave(sSDA,current_drive, _drive); } - void SetDTA(Bit32u _dta) { sSave(sSDA,current_dta, _dta); } - void SetPSP(Bit16u _psp) { sSave(sSDA,current_psp, _psp); } - Bit8u GetDrive(void) { return (Bit8u)sGet(sSDA,current_drive); } - Bit16u GetPSP(void) { return (Bit16u)sGet(sSDA,current_psp); } - Bit32u GetDTA(void) { return (Bit32u)sGet(sSDA,current_dta); } - - -private: - #ifdef _MSC_VER - #pragma pack (1) - #endif - struct sSDA { - Bit8u crit_error_flag; /* 0x00 Critical Error Flag */ - Bit8u inDOS_flag; /* 0x01 InDOS flag (count of active INT 21 calls) */ - Bit8u drive_crit_error; /* 0x02 Drive on which current critical error occurred or FFh */ - Bit8u locus_of_last_error; /* 0x03 locus of last error */ - Bit16u extended_error_code; /* 0x04 extended error code of last error */ - Bit8u suggested_action; /* 0x06 suggested action for last error */ - Bit8u error_class; /* 0x07 class of last error*/ - Bit32u last_error_pointer; /* 0x08 ES:DI pointer for last error */ - Bit32u current_dta; /* 0x0C current DTA (Disk Transfer Address) */ - Bit16u current_psp; /* 0x10 current PSP */ - Bit16u sp_int_23; /* 0x12 stores SP across an INT 23 */ - Bit16u return_code; /* 0x14 return code from last process termination (zerod after reading with AH=4Dh) */ - Bit8u current_drive; /* 0x16 current drive */ - Bit8u extended_break_flag; /* 0x17 extended break flag */ - Bit8u fill[2]; /* 0x18 flag: code page switching || flag: copy of previous byte in case of INT 24 Abort*/ - } GCC_ATTRIBUTE(packed); - #ifdef _MSC_VER - #pragma pack() - #endif -}; -extern DOS_InfoBlock dos_infoblock; - -struct DOS_Block { - DOS_Date date; - DOS_Version version; - Bit16u firstMCB; - Bit16u errorcode; - Bit16u psp(){return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetPSP();}; - void psp(Bit16u _seg){ DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetPSP(_seg);}; - Bit16u env; - RealPt cpmentry; - RealPt dta(){return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetDTA();}; - void dta(RealPt _dta){DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetDTA(_dta);}; - Bit8u return_code,return_mode; - - Bit8u current_drive; - bool verify; - bool breakcheck; - bool echo; // if set to true dev_con::read will echo input - struct { - RealPt mediaid; - RealPt tempdta; - RealPt tempdta_fcbdelete; - RealPt dbcs; - RealPt filenamechar; - RealPt collatingseq; - Bit8u* country;//Will be copied to dos memory. resides in real mem - Bit16u dpb; //Fake Disk parameter system using only the first entry so the drive letter matches - } tables; - Bit16u loaded_codepage; -}; - -extern DOS_Block dos; - -static Bit8u RealHandle(Bit16u handle) { - DOS_PSP psp(dos.psp()); - return psp.GetFileHandle(handle); -} - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef DOS_H_ +#define DOS_H_ + +#include +#include + +#pragma pack(1) + +struct CommandTail{ + Bit8u count; /* number of bytes returned */ + char buffer[127]; /* the buffer itself */ +}; + +struct PSP { + Bit8u exit[2]; /* CP/M-like exit poimt */ + Bit16u mem_size; /* memory size in paragraphs */ + Bit8u fill_1; /* single char fill */ + +/* CPM Stuff dunno what this is*/ +//TODO Add some checks for people using this i think + Bit8u far_call; /* far call opcode */ + RealPt cpm_entry; /* CPM Service Request address*/ + RealPt int_22; /* Terminate Address */ + RealPt int_23; /* Break Address */ + RealPt int_24; /* Critical Error Address */ + Bit16u psp_parent; /* Parent PSP Segment */ + Bit8u files[20]; /* File Table - 0xff is unused */ + Bit16u environment; /* Segment of evironment table */ + RealPt stack; /* SS:SP Save point for int 0x21 calls */ + Bit16u max_files; /* Maximum open files */ + RealPt file_table; /* Pointer to File Table PSP:0x18 */ + RealPt prev_psp; /* Pointer to previous PSP */ + RealPt dta; /* Pointer to current Process DTA */ + Bit8u fill_2[16]; /* Lot's of unused stuff i can't care aboue */ + Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */ + Bit8u fill_3[45]; /* This has some blocks with FCB info */ + + CommandTail cmdtail; + +}; + +struct ParamBlock { + union { + struct { + Bit16u loadseg; + Bit16u relocation; + } overlay; + struct { + Bit16u envseg; + RealPt cmdtail; + RealPt fcb1; + RealPt fcb2; + RealPt initsssp; + RealPt initcsip; + } exec; + }; +}; + +struct MCB { + Bit8u type; + Bit16u psp_segment; + Bit16u size; + Bit8u unused[3]; + Bit8u filename[8]; +}; + +struct FCB { + Bit8u drive; //0 is current drive. when opened 0 is replaced by drivenumber + Bit8u filename[8]; //spacepadded to fit + Bit8u ext[3]; //spacepadded to fit + Bit16u current_block; // set to 0 by open + Bit16u record_size; // used by reads Set to 80h by OPEN function + Bit32u filesize; //in bytes In this field, the first word is the low-order part of the size + Bit16u date; + Bit16u time; + Bit8u reserved[8]; + Bit8u current_relative_record_number; //open doesn't set this + Bit32u rel_record; //open does not handle this +}; + +#pragma pack() + +struct DOS_Date { + Bit16u year; + Bit8u month; + Bit8u day; +}; + + +struct DOS_Version { + Bit8u major,minor,revision; +}; + +struct DOS_Block { + DOS_Date date; + DOS_Version version; + Bit16u firstMCB; + Bit16u errorcode; + Bit16u psp; + Bit16u env; + RealPt cpmentry; + RealPt dta; + Bit8u return_code,return_mode; + + bool verify; + bool breakcheck; + struct { + RealPt indosflag; + } tables; + +}; + +enum { MCB_FREE=0x0000,MCB_DOS=0x0008 }; +enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3}; + +#define DOS_FILES 50 +#define DOS_DRIVES 26 + +/* internal Dos Tables */ +extern DOS_Block dos; +extern DOS_File * Files[DOS_FILES]; +extern DOS_Drive * Drives[DOS_DRIVES]; + + +void DOS_SetError(Bit16u code); + +/* File Handling Routines */ + +enum { STDIN=0,STDOUT=1,STDERR=2,STDAUX=3,STDNUL=4,STDPRN=5}; +enum { HAND_NONE=0,HAND_FILE,HAND_DEVICE}; + + + +/* Routines for File Class */ +void DOS_SetupFiles (void); + +bool DOS_ReadFile(Bit16u handle,Bit8u * data,Bit16u * amount); +bool DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount); +bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type); +bool DOS_CloseFile(Bit16u handle); +bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry); +/* Routines for Drive Class */ +bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry); +bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry); +bool DOS_UnlinkFile(char * name); +bool DOS_FindFirst(char *search,Bit16u attr); +bool DOS_FindNext(void); +bool DOS_Canonicalize(char * small,Bit8u * big); +bool DOS_CreateTempFile(char * name,Bit16u * entry); +bool DOS_FileExists(char * name); +/* Drive Handing Routines */ +Bit8u DOS_GetDefaultDrive(void); +void DOS_SetDefaultDrive(Bit8u drive); +bool DOS_SetDrive(Bit8u drive); +bool DOS_GetCurrentDir(Bit8u drive,Bit8u * buffer); +bool DOS_ChangeDir(char * dir); +bool DOS_MakeDir(char * dir); +bool DOS_RemoveDir(char * dir); +bool DOS_Rename(char * oldname,char * newname); +bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free); +bool DOS_GetFileAttr(char * name,Bit16u * attr); +/* IOCTL Stuff */ +bool DOS_IOCTL(Bit8u call,Bit16u entry); +bool DOS_GetSTDINStatus(); +Bit8u DOS_FindDevice(char * name); +void DOS_SetupDevices(void); +/* Execute and new process creation */ +bool DOS_NewPSP(Bit16u pspseg); +bool DOS_Execute(char * name,ParamBlock * block,Bit8u flags); +bool DOS_Terminate(bool tsr); + +/* Memory Handling Routines */ +void DOS_SetupMemory(void); +bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks); +bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks); +bool DOS_FreeMemory(Bit16u segment); +void DOS_FreeProcessMemory(Bit16u pspseg); +Bit16u DOS_GetMemory(Bit16u pages); + +/* Extra DOS Interrupts */ +void DOS_SetupMisc(void); + +/* The DOS Tables */ +void DOS_SetupTables(void); +/* Internal DOS Setup Programs */ +void DOS_SetupPrograms(void); + + +INLINE Bit16u long2para(Bit32u size) { + if (size>0xFFFF0) return 0xffff; + if (size&0xf) return (Bit16u)((size>>4)+1); + else return (Bit16u)(size>>4); +}; + +INLINE Bit8u RealHandle(Bit16u handle) { + PSP * psp=(PSP *)real_off(dos.psp,0); + if (handle>=psp->max_files) return DOS_FILES; + return mem_readb(Real2Phys(psp->file_table)+handle); +}; + +/* Dos Error Codes */ +#define DOSERR_NONE 0 +#define DOSERR_FUNCTION_NUMBER_INVALID 1 +#define DOSERR_FILE_NOT_FOUND 2 +#define DOSERR_PATH_NOT_FOUND 3 +#define DOSERR_TOO_MANY_OPEN_FILES 4 +#define DOSERR_ACCESS_DENIED 5 +#define DOSERR_INVALID_HANDLE 6 +#define DOSERR_MCB_DESTROYED 7 +#define DOSERR_INSUFFICIENT_MEMORY 8 +#define DOSERR_MB_ADDRESS_INVALID 9 +#define DOSERR_ENVIRONMENT_INVALID 10 +#define DOSERR_FORMAT_INVALID 11 +#define DOSERR_ACCESS_CODE_INVALID 12 +#define DOSERR_DATA_INVALID 13 +#define DOSERR_RESERVED 14 +#define DOSERR_FIXUP_OVERFLOW 14 +#define DOSERR_INVALID_DRIVE 15 +#define DOSERR_REMOVE_CURRENT_DIRECTORY 16 +#define DOSERR_NOT_SAME_DEVICE 17 +#define DOSERR_NO_MORE_FILES 18 + +/* Remains some classes used to access certain things */ +class DOS_FCB { +public: + DOS_FCB(PhysPt pt){ + off=pt; + } + DOS_FCB(Bit16u seg, Bit16u offset){ + off=Real2Phys(RealMake(seg,offset)); + } + void Set_drive(Bit8u a); + void Set_filename(char* a); //writes an the first 8 bytes of a as the filename + void Set_ext(char* a); + void Set_current_block(Bit16u a); + void Set_record_size(Bit16u a); + void Set_filesize(Bit32u a); + void Set_date(Bit16u a); + void Set_time(Bit16u a); + // others nog yet handled + Bit8u Get_drive(void); + void Get_filename(char* a); + void Get_ext(char* a); + Bit16u Get_current_block(void); + Bit16u Get_record_size(void); + Bit32u Get_filesize(void); + Bit16u Get_date(void); + Bit16u Get_time(void); +private: + PhysPt off; +}; + + + + +#endif + diff --git a/include/dos_system.h b/include/dos_system.h index ad6e2ce..55f210a 100644 --- a/include/dos_system.h +++ b/include/dos_system.h @@ -1,269 +1,105 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos_system.h,v 1.47 2009/03/04 21:08:22 c2woody Exp $ */ - -#ifndef DOSBOX_DOS_SYSTEM_H -#define DOSBOX_DOS_SYSTEM_H - -#include -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif -#ifndef DOSBOX_CROSS_H -#include "cross.h" -#endif -#ifndef DOSBOX_SUPPORT_H -#include "support.h" -#endif -#ifndef DOSBOX_MEM_H -#include "mem.h" -#endif - -#define DOS_NAMELENGTH 12 -#define DOS_NAMELENGTH_ASCII (DOS_NAMELENGTH+1) -#define DOS_FCBNAME 15 -#define DOS_DIRDEPTH 8 -#define DOS_PATHLENGTH 80 -#define DOS_TEMPSIZE 1024 - -enum { - DOS_ATTR_READ_ONLY= 0x01, - DOS_ATTR_HIDDEN= 0x02, - DOS_ATTR_SYSTEM= 0x04, - DOS_ATTR_VOLUME= 0x08, - DOS_ATTR_DIRECTORY= 0x10, - DOS_ATTR_ARCHIVE= 0x20, - DOS_ATTR_DEVICE= 0x40 -}; - -struct FileStat_Block { - Bit32u size; - Bit16u time; - Bit16u date; - Bit16u attr; -}; - -class DOS_DTA; - -class DOS_File { -public: - DOS_File():flags(0) { name=0; refCtr = 0; hdrive=0xff; }; - DOS_File(const DOS_File& orig); - DOS_File & operator= (const DOS_File & orig); - virtual ~DOS_File(){if(name) delete [] name;}; - virtual bool Read(Bit8u * data,Bit16u * size)=0; - virtual bool Write(Bit8u * data,Bit16u * size)=0; - virtual bool Seek(Bit32u * pos,Bit32u type)=0; - virtual bool Close()=0; - virtual Bit16u GetInformation(void)=0; - virtual void SetName(const char* _name) { if (name) delete[] name; name = new char[strlen(_name)+1]; strcpy(name,_name); } - virtual char* GetName(void) { return name; }; - virtual bool IsOpen() { return open; }; - virtual bool IsName(const char* _name) { if (!name) return false; return strcasecmp(name,_name)==0; }; - virtual void AddRef() { refCtr++; }; - virtual Bits RemoveRef() { return --refCtr; }; - virtual bool UpdateDateTimeFromHost() { return true; } - void SetDrive(Bit8u drv) { hdrive=drv;} - Bit8u GetDrive(void) { return hdrive;} - Bit32u flags; - Bit16u time; - Bit16u date; - Bit16u attr; - Bits refCtr; - bool open; - char* name; -/* Some Device Specific Stuff */ -private: - Bit8u hdrive; -}; - -class DOS_Device : public DOS_File { -public: - DOS_Device(const DOS_Device& orig):DOS_File(orig) { - devnum=orig.devnum; - open=true; - } - DOS_Device & operator= (const DOS_Device & orig) { - DOS_File::operator=(orig); - devnum=orig.devnum; - open=true; - return *this; - } - DOS_Device():DOS_File(),devnum(0){}; - virtual bool Read(Bit8u * data,Bit16u * size); - virtual bool Write(Bit8u * data,Bit16u * size); - virtual bool Seek(Bit32u * pos,Bit32u type); - virtual bool Close(); - virtual Bit16u GetInformation(void); - virtual bool ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode); - virtual bool WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode); - void SetDeviceNumber(Bitu num) { devnum=num;} -private: - Bitu devnum; -}; - -/* The following variable can be lowered to free up some memory. - * The negative side effect: The stored searches will be turned over faster. - * Should not have impact on systems with few directory entries. */ -#define MAX_OPENDIRS 2048 -//Can be high as it's only storage (16 bit variable) - -class DOS_Drive_Cache { -public: - DOS_Drive_Cache (void); - DOS_Drive_Cache (const char* path); - ~DOS_Drive_Cache (void); - - enum TDirSort { NOSORT, ALPHABETICAL, DIRALPHABETICAL, ALPHABETICALREV, DIRALPHABETICALREV }; - - void SetBaseDir (const char* path); - void SetDirSort (TDirSort sort) { sortDirType = sort; }; - bool OpenDir (const char* path, Bit16u& id); - bool ReadDir (Bit16u id, char* &result); - - void ExpandName (char* path); - char* GetExpandName (const char* path); - bool GetShortName (const char* fullname, char* shortname); - - bool FindFirst (char* path, Bitu& id); - bool FindNext (Bitu id, char* &result); - - void CacheOut (const char* path, bool ignoreLastDir = false); - void AddEntry (const char* path, bool checkExist = false); - void DeleteEntry (const char* path, bool ignoreLastDir = false); - - void EmptyCache (void); - void SetLabel (const char* name,bool cdrom,bool allowupdate); - char* GetLabel (void) { return label; }; - - class CFileInfo { - public: - CFileInfo(void) { - orgname[0] = shortname[0] = 0; - nextEntry = shortNr = 0; - isDir = false; - } - ~CFileInfo(void) { - for (Bit32u i=0; i fileList; - std::vector longNameList; - }; - -private: - - bool RemoveTrailingDot (char* shortname); - Bits GetLongName (CFileInfo* info, char* shortname); - void CreateShortName (CFileInfo* dir, CFileInfo* info); - Bitu CreateShortNameID (CFileInfo* dir, const char* name); - int CompareShortname (const char* compareName, const char* shortName); - bool SetResult (CFileInfo* dir, char * &result, Bitu entryNr); - bool IsCachedIn (CFileInfo* dir); - CFileInfo* FindDirInfo (const char* path, char* expandedPath); - bool RemoveSpaces (char* str); - bool OpenDir (CFileInfo* dir, const char* path, Bit16u& id); - void CreateEntry (CFileInfo* dir, const char* name, bool query_directory); - void CopyEntry (CFileInfo* dir, CFileInfo* from); - Bit16u GetFreeID (CFileInfo* dir); - void Clear (void); - - CFileInfo* dirBase; - char dirPath [CROSS_LEN]; - char basePath [CROSS_LEN]; - bool dirFirstTime; - TDirSort sortDirType; - CFileInfo* save_dir; - char save_path [CROSS_LEN]; - char save_expanded [CROSS_LEN]; - - Bit16u srchNr; - CFileInfo* dirSearch [MAX_OPENDIRS]; - char dirSearchName [MAX_OPENDIRS]; - bool free [MAX_OPENDIRS]; - CFileInfo* dirFindFirst [MAX_OPENDIRS]; - Bitu nextFreeFindFirst; - - char label [CROSS_LEN]; - bool updatelabel; -}; - -class DOS_Drive { -public: - DOS_Drive(); - virtual ~DOS_Drive(){}; - virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags)=0; - virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes)=0; - virtual bool FileUnlink(char * _name)=0; - virtual bool RemoveDir(char * _dir)=0; - virtual bool MakeDir(char * _dir)=0; - virtual bool TestDir(char * _dir)=0; - virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false)=0; - virtual bool FindNext(DOS_DTA & dta)=0; - virtual bool GetFileAttr(char * name,Bit16u * attr)=0; - virtual bool Rename(char * oldname,char * newname)=0; - virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters)=0; - virtual bool FileExists(const char* name)=0; - virtual bool FileStat(const char* name, FileStat_Block * const stat_block)=0; - virtual Bit8u GetMediaByte(void)=0; - virtual void SetDir(const char* path) { strcpy(curdir,path); }; - virtual void EmptyCache(void) { dirCache.EmptyCache(); }; - virtual bool isRemote(void)=0; - virtual bool isRemovable(void)=0; - virtual Bits UnMount(void)=0; - - char * GetInfo(void); - char curdir[DOS_PATHLENGTH]; - char info[256]; - /* Can be overridden for example in iso images */ - virtual char const * GetLabel(){return dirCache.GetLabel();}; - - DOS_Drive_Cache dirCache; - - // disk cycling functionality (request resources) - virtual void Activate(void) {}; -}; - -enum { OPEN_READ=0,OPEN_WRITE=1,OPEN_READWRITE=2, DOS_NOT_INHERIT=128}; -enum { DOS_SEEK_SET=0,DOS_SEEK_CUR=1,DOS_SEEK_END=2}; - - -/* - A multiplex handler should read the registers to check what function is being called - If the handler returns false dos will stop checking other handlers -*/ - -typedef bool (MultiplexHandler)(void); -void DOS_AddMultiplexHandler(MultiplexHandler * handler); -void DOS_DelMultiplexHandler(MultiplexHandler * handler); - -/* AddDevice stores the pointer to a created device */ -void DOS_AddDevice(DOS_Device * adddev); -/* DelDevice destroys the device that is pointed to. */ -void DOS_DelDevice(DOS_Device * dev); - -void VFILE_Register(const char * name,Bit8u * data,Bit32u size); -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef DOSSYSTEM_H_ +#define DOSSYSTEM_H_ + +#include + +#define DOS_NAMELENGTH 12 +#define DOS_DIRDEPTH 16 +#define DOS_PATHLENGTH (DOS_DIRDEPTH+1)*(DOS_NAMELENGTH+2) +#define DOS_TEMPSIZE 1024 + +enum { + DOS_ATTR_READ_ONLY= 0x01, + DOS_ATTR_HIDDEN= 0x02, + DOS_ATTR_SYSTEM= 0x04, + DOS_ATTR_VOLUME= 0x08, + DOS_ATTR_DIRECTORY= 0x10, + DOS_ATTR_ARCHIVE= 0x20 +}; + +#pragma pack (1) +struct DTA_FindBlock { + Bit8u sdrive; /* The Drive the search is taking place */ + Bit16u sattr; /* The attributes that need to be found */ + Bit8u fill[18]; + Bit8u attr; + Bit16u time; + Bit16u date; + Bit32u size; + char name[DOS_NAMELENGTH]; +}; +#pragma pack () + +class DOS_File { +public: + virtual bool Read(Bit8u * data,Bit16u * size)=0; + virtual bool Write(Bit8u * data,Bit16u * size)=0; + virtual bool Seek(Bit32u * pos,Bit32u type)=0; + virtual bool Close()=0; + virtual Bit16u GetInformation(void)=0; + Bit8u type;Bit32u flags; +/* Some Device Specific Stuff */ +}; + +class DOS_Device : public DOS_File { +public: +/* Some Device Specific Stuff */ + char * name; + Bit8u fhandle; +}; + + + +class DOS_Drive { +public: + DOS_Drive(); + virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags)=0; + virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes)=0; + virtual bool FileUnlink(char * name)=0; + virtual bool RemoveDir(char * dir)=0; + virtual bool MakeDir(char * dir)=0; + virtual bool TestDir(char * dir)=0; + virtual bool FindFirst(char * search,DTA_FindBlock * dta)=0; + virtual bool FindNext(DTA_FindBlock * dta)=0; + virtual bool GetFileAttr(char * name,Bit16u * attr)=0; + virtual bool Rename(char * oldname,char * newname)=0; + virtual bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free)=0; + char * GetInfo(void); + char curdir[DOS_PATHLENGTH]; + char info[256]; +}; + +enum { OPEN_READ=0,OPEN_WRITE=1,OPEN_READWRITE=2 }; +enum { DOS_SEEK_SET=0,DOS_SEEK_CUR=1,DOS_SEEK_END=2}; + + +/* + A multiplex handler should read the registers to check what function is being called + If the handler returns false dos will stop checking other handlers +*/ + +typedef bool (MultiplexHandler)(void); +void DOS_AddMultiplexHandler(MultiplexHandler * handler); + +void DOS_AddDevice(DOS_Device * adddev); +void VFILE_Register(char * name,Bit8u * data,Bit32u size); +#endif + diff --git a/include/dosbox.h b/include/dosbox.h index d4c6079..8b7e26c 100644 --- a/include/dosbox.h +++ b/include/dosbox.h @@ -1,76 +1,63 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dosbox.h,v 1.31 2008/01/09 20:34:21 c2woody Exp $ */ - -#ifndef DOSBOX_DOSBOX_H -#define DOSBOX_DOSBOX_H - -#include "config.h" - -void E_Exit(const char * message,...) GCC_ATTRIBUTE( __format__(__printf__, 1, 2)); - -void MSG_Add(const char*,const char*); //add messages to the internal langaugefile -const char* MSG_Get(char const *); //get messages from the internal langaugafile - -class Section; - -typedef Bitu (LoopHandler)(void); - -void DOSBOX_RunMachine(); -void DOSBOX_SetLoop(LoopHandler * handler); -void DOSBOX_SetNormalLoop(); - -void DOSBOX_Init(void); - -class Config; -extern Config * control; - -enum MachineType { - MCH_HERC, - MCH_CGA, - MCH_TANDY, - MCH_PCJR, - MCH_EGA, - MCH_VGA -}; - -enum SVGACards { - SVGA_None, - SVGA_S3Trio, - SVGA_TsengET4K, - SVGA_TsengET3K, - SVGA_ParadisePVGA1A -}; - -extern SVGACards svgaCard; -extern MachineType machine; -extern bool SDLNetInited; - -#define IS_TANDY_ARCH ((machine==MCH_TANDY) || (machine==MCH_PCJR)) -#define IS_EGAVGA_ARCH ((machine==MCH_EGA) || (machine==MCH_VGA)) -#define IS_VGA_ARCH (machine==MCH_VGA) -#define TANDY_ARCH_CASE MCH_TANDY: case MCH_PCJR -#define EGAVGA_ARCH_CASE MCH_EGA: case MCH_VGA -#define VGA_ARCH_CASE MCH_VGA - -#ifndef DOSBOX_LOGGING_H -#include "logging.h" -#endif // the logging system. - -#endif /* DOSBOX_DOSBOX_H */ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if !defined __DOSBOX_H +#define __DOSBOX_H + +typedef unsigned char Bit8u; +typedef signed char Bit8s; +typedef unsigned short Bit16u; +typedef signed short Bit16s; +typedef unsigned long Bit32u; +typedef signed long Bit32s; +#if defined(_MSC_VER) +typedef unsigned __int64 Bit64u; +typedef signed __int64 Bit64s; +#else +typedef unsigned long long int Bit64u; +typedef signed long long int Bit64s; +#endif + +typedef unsigned int Bitu; +typedef signed int Bits; + +#include + +void E_Exit(char * message,...); + +void S_Warn(char * message,...); + + +#include "../settings.h" /* General extra setting */ +#if defined (_MSC_VER) +#include "../src/platform/visualc/config.h" +#else +#include "../config.h" +#define INLINE inline +#endif + + +typedef Bitu (LoopHandler)(void); + +void DOSBOX_RunMachine(); +void DOSBOX_SetLoop(LoopHandler * handler); + +void DOSBOX_Init(int argc, char* argv[]); +void DOSBOX_StartUp(void); +#endif + diff --git a/include/fpu.h b/include/fpu.h index e906440..8b13789 100644 --- a/include/fpu.h +++ b/include/fpu.h @@ -1,154 +1 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_FPU_H -#define DOSBOX_FPU_H - -#ifndef DOSBOX_MEM_H -#include "mem.h" -#endif - -void FPU_ESC0_Normal(Bitu rm); -void FPU_ESC0_EA(Bitu func,PhysPt ea); -void FPU_ESC1_Normal(Bitu rm); -void FPU_ESC1_EA(Bitu func,PhysPt ea); -void FPU_ESC2_Normal(Bitu rm); -void FPU_ESC2_EA(Bitu func,PhysPt ea); -void FPU_ESC3_Normal(Bitu rm); -void FPU_ESC3_EA(Bitu func,PhysPt ea); -void FPU_ESC4_Normal(Bitu rm); -void FPU_ESC4_EA(Bitu func,PhysPt ea); -void FPU_ESC5_Normal(Bitu rm); -void FPU_ESC5_EA(Bitu func,PhysPt ea); -void FPU_ESC6_Normal(Bitu rm); -void FPU_ESC6_EA(Bitu func,PhysPt ea); -void FPU_ESC7_Normal(Bitu rm); -void FPU_ESC7_EA(Bitu func,PhysPt ea); - - -typedef union { - double d; -#ifndef WORDS_BIGENDIAN - struct { - Bit32u lower; - Bit32s upper; - } l; -#else - struct { - Bit32s upper; - Bit32u lower; - } l; -#endif - Bit64s ll; -} FPU_Reg; - -typedef struct { - Bit32u m1; - Bit32u m2; - Bit16u m3; - - Bit16u d1; - Bit32u d2; -} FPU_P_Reg; - -enum FPU_Tag { - TAG_Valid = 0, - TAG_Zero = 1, - TAG_Weird = 2, - TAG_Empty = 3 -}; - -enum FPU_Round { - ROUND_Nearest = 0, - ROUND_Down = 1, - ROUND_Up = 2, - ROUND_Chop = 3 -}; - -typedef struct { - FPU_Reg regs[9]; - FPU_P_Reg p_regs[9]; - FPU_Tag tags[9]; - Bit16u cw,cw_mask_all; - Bit16u sw; - Bitu top; - FPU_Round round; -} FPU_rec; - - -//get pi from a real library -#define PI 3.14159265358979323846 -#define L2E 1.4426950408889634 -#define L2T 3.3219280948873623 -#define LN2 0.69314718055994531 -#define LG2 0.3010299956639812 - - -extern FPU_rec fpu; - -#define TOP fpu.top -#define STV(i) ( (fpu.top+ (i) ) & 7 ) - - -Bit16u FPU_GetTag(void); -void FPU_FLDCW(PhysPt addr); - -static INLINE void FPU_SetTag(Bit16u tag){ - for(Bitu i=0;i<8;i++) - fpu.tags[i] = static_cast((tag >>(2*i))&3); -} - -static INLINE void FPU_SetCW(Bitu word){ - fpu.cw = (Bit16u)word; - fpu.cw_mask_all = (Bit16u)(word | 0x3f); - fpu.round = (FPU_Round)((word >> 10) & 3); -} - - -static INLINE Bitu FPU_GET_TOP(void) { - return (fpu.sw & 0x3800)>>11; -} - -static INLINE void FPU_SET_TOP(Bitu val){ - fpu.sw &= ~0x3800; - fpu.sw |= (val&7)<<11; -} - - -static INLINE void FPU_SET_C0(Bitu C){ - fpu.sw &= ~0x0100; - if(C) fpu.sw |= 0x0100; -} - -static INLINE void FPU_SET_C1(Bitu C){ - fpu.sw &= ~0x0200; - if(C) fpu.sw |= 0x0200; -} - -static INLINE void FPU_SET_C2(Bitu C){ - fpu.sw &= ~0x0400; - if(C) fpu.sw |= 0x0400; -} - -static INLINE void FPU_SET_C3(Bitu C){ - fpu.sw &= ~0x4000; - if(C) fpu.sw |= 0x4000; -} - - -#endif + diff --git a/include/hardware.h b/include/hardware.h index 073cabe..5edfa4b 100644 --- a/include/hardware.h +++ b/include/hardware.h @@ -1,50 +1,44 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_HARDWARE_H -#define DOSBOX_HARDWARE_H - -#include - -class Section; -enum OPL_Mode { - OPL_none,OPL_cms,OPL_opl2,OPL_dualopl2,OPL_opl3 -}; -#define CAPTURE_WAVE 0x01 -#define CAPTURE_OPL 0x02 -#define CAPTURE_MIDI 0x04 -#define CAPTURE_IMAGE 0x08 -#define CAPTURE_VIDEO 0x10 - -extern Bitu CaptureState; - -void OPL_Init(Section* sec,OPL_Mode mode); -void CMS_Init(Section* sec); -void OPL_ShutDown(Section* sec); -void CMS_ShutDown(Section* sec); - -extern Bit8u adlib_commandreg; -FILE * OpenCaptureFile(const char * type,const char * ext); - -void CAPTURE_AddWave(Bit32u freq, Bit32u len, Bit16s * data); -#define CAPTURE_FLAG_DBLW 0x1 -#define CAPTURE_FLAG_DBLH 0x2 -void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags, float fps, Bit8u * data, Bit8u * pal); -void CAPTURE_AddMidi(bool sysex, Bitu len, Bit8u * data); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _HARDWARE_H_ +#define _HARDWARE_H_ + +#include +#include +#include + +typedef void (* HW_OutputHandler)(char * towrite); +typedef void (* HW_InputHandler)(char * line); + +struct HWBlock { + char * dev_name; /* 8 characters max dev name */ + char * full_name; /* 60 characters full name */ + char * help; + HW_InputHandler get_input; + HW_OutputHandler show_status; /* Supplied with a string to display 50 chars of status info in */ + HWBlock * next; +}; + + +void HW_Register(HWBlock * block); + + +#endif + + diff --git a/include/inout.h b/include/inout.h index 4bd858d..91f00a8 100644 --- a/include/inout.h +++ b/include/inout.h @@ -1,78 +1,48 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: inout.h,v 1.12 2009/04/25 16:25:03 harekiet Exp $ */ - -#ifndef DOSBOX_INOUT_H -#define DOSBOX_INOUT_H - -#define IO_MAX (64*1024+3) - -#define IO_MB 0x1 -#define IO_MW 0x2 -#define IO_MD 0x4 -#define IO_MA (IO_MB | IO_MW | IO_MD ) - -typedef Bitu IO_ReadHandler(Bitu port,Bitu iolen); -typedef void IO_WriteHandler(Bitu port,Bitu val,Bitu iolen); - -extern IO_WriteHandler * io_writehandlers[3][IO_MAX]; -extern IO_ReadHandler * io_readhandlers[3][IO_MAX]; - -void IO_RegisterReadHandler(Bitu port,IO_ReadHandler * handler,Bitu mask,Bitu range=1); -void IO_RegisterWriteHandler(Bitu port,IO_WriteHandler * handler,Bitu mask,Bitu range=1); - -void IO_FreeReadHandler(Bitu port,Bitu mask,Bitu range=1); -void IO_FreeWriteHandler(Bitu port,Bitu mask,Bitu range=1); - -void IO_WriteB(Bitu port,Bitu val); -void IO_WriteW(Bitu port,Bitu val); -void IO_WriteD(Bitu port,Bitu val); - -Bitu IO_ReadB(Bitu port); -Bitu IO_ReadW(Bitu port); -Bitu IO_ReadD(Bitu port); - -/* Classes to manage the IO objects created by the various devices. - * The io objects will remove itself on destruction.*/ -class IO_Base{ -protected: - bool installed; - Bitu m_port, m_mask,m_range; -public: - IO_Base():installed(false){}; -}; -class IO_ReadHandleObject: private IO_Base{ -public: - void Install(Bitu port,IO_ReadHandler * handler,Bitu mask,Bitu range=1); - ~IO_ReadHandleObject(); -}; -class IO_WriteHandleObject: private IO_Base{ -public: - void Install(Bitu port,IO_WriteHandler * handler,Bitu mask,Bitu range=1); - ~IO_WriteHandleObject(); -}; - -static INLINE void IO_Write(Bitu port,Bit8u val) { - IO_WriteB(port,val); -} -static INLINE Bit8u IO_Read(Bitu port){ - return (Bit8u)IO_ReadB(port); -} - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +typedef Bit8u (IO_ReadHandler)(Bit32u port); +typedef void (IO_WriteHandler)(Bit32u port,Bit8u value); + +#define IO_MAX 1024 + +struct IO_ReadBlock{ + IO_ReadHandler * handler; + char * name; +}; + +struct IO_WriteBlock{ + IO_WriteHandler * handler; + char * name; +}; + +extern IO_ReadBlock IO_ReadTable[IO_MAX]; +extern IO_WriteBlock IO_WriteTable[IO_MAX]; + + + +void IO_Write(Bitu num,Bit8u val); +Bit8u IO_Read(Bitu num); + +void IO_RegisterReadHandler(Bit32u port,IO_ReadHandler * handler,char * name); +void IO_RegisterWriteHandler(Bit32u port,IO_WriteHandler * handler,char * name); + +void IO_FreeReadHandler(Bit32u port); +void IO_FreeWriteHandler(Bit32u port); + + diff --git a/include/ipx.h b/include/ipx.h deleted file mode 100644 index ca56be4..0000000 --- a/include/ipx.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: ipx.h,v 1.12 2007/01/13 08:35:49 qbix79 Exp $ */ - -#ifndef DOSBOX_IPX_H -#define DOSBOX_IPX_H - -// Uncomment this for a lot of debug messages: -//#define IPX_DEBUGMSG - -#ifdef IPX_DEBUGMSG -#define LOG_IPX LOG_MSG -#else -#if defined (_MSC_VER) -#define LOG_IPX -#else -#define LOG_IPX(...) -#endif -#endif - -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif -#ifndef DOSBOX_MEM_H -#include "mem.h" -#endif - -// In Use Flag codes -#define USEFLAG_AVAILABLE 0x00 -#define USEFLAG_AESTEMP 0xe0 -#define USEFLAG_IPXCRIT 0xf8 -#define USEFLAG_SPXLISTEN 0xf9 -#define USEFLAG_PROCESSING 0xfa -#define USEFLAG_HOLDING 0xfb -#define USEFLAG_AESWAITING 0xfc -#define USEFLAG_AESCOUNT 0xfd -#define USEFLAG_LISTENING 0xfe -#define USEFLAG_SENDING 0xff - -// Completion codes -#define COMP_SUCCESS 0x00 -#define COMP_REMOTETERM 0xec -#define COMP_DISCONNECT 0xed -#define COMP_INVALIDID 0xee -#define COMP_SPXTABLEFULL 0xef -#define COMP_EVENTNOTCANCELED 0xf9 -#define COMP_NOCONNECTION 0xfa -#define COMP_CANCELLED 0xfc -#define COMP_MALFORMED 0xfd -#define COMP_UNDELIVERABLE 0xfe -#define COMP_HARDWAREERROR 0xff - -#ifdef _MSC_VER -#pragma pack(1) -#endif - -// For Uint8 type -#include "SDL_net.h" - -struct PackedIP { - Uint32 host; - Uint16 port; -} GCC_ATTRIBUTE(packed); - -struct nodeType { - Uint8 node[6]; -} GCC_ATTRIBUTE(packed) ; - -struct IPXHeader { - Uint8 checkSum[2]; - Uint8 length[2]; - Uint8 transControl; // Transport control - Uint8 pType; // Packet type - - struct transport { - Uint8 network[4]; - union addrtype { - nodeType byNode; - PackedIP byIP ; - } GCC_ATTRIBUTE(packed) addr; - Uint8 socket[2]; - } dest, src; -} GCC_ATTRIBUTE(packed); - -struct fragmentDescriptor { - Bit16u offset; - Bit16u segment; - Bit16u size; -}; - -#define IPXBUFFERSIZE 1424 - -class ECBClass { -public: - RealPt ECBAddr; - bool isInESRList; - ECBClass *prevECB; // Linked List - ECBClass *nextECB; - - Bit8u iuflag; // Need to save data since we are not always in - Bit16u mysocket; // real mode - - Bit8u* databuffer; // received data is stored here until we get called - Bitu buflen; // by Interrupt - -#ifdef IPX_DEBUGMSG - Bitu SerialNumber; -#endif - - ECBClass(Bit16u segment, Bit16u offset); - Bit16u getSocket(void); - - Bit8u getInUseFlag(void); - - void setInUseFlag(Bit8u flagval); - - void setCompletionFlag(Bit8u flagval); - - Bit16u getFragCount(void); - - bool writeData(); - void writeDataBuffer(Bit8u* buffer, Bit16u length); - - void getFragDesc(Bit16u descNum, fragmentDescriptor *fragDesc); - RealPt getESRAddr(void); - - void NotifyESR(void); - - void setImmAddress(Bit8u *immAddr); - void getImmAddress(Bit8u* immAddr); - - ~ECBClass(); -}; - -// The following routines may not be needed on all systems. On my build of SDL the IPaddress structure is 8 octects -// and therefore screws up my IPXheader structure since it needs to be packed. - -void UnpackIP(PackedIP ipPack, IPaddress * ipAddr); -void PackIP(IPaddress ipAddr, PackedIP *ipPack); - -#ifdef _MSC_VER -#pragma pack() -#endif - -#endif diff --git a/include/ipxserver.h b/include/ipxserver.h deleted file mode 100644 index db0850e..0000000 --- a/include/ipxserver.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_IPXSERVER_H_ -#define DOSBOX_IPXSERVER_H_ - -#if C_IPX - -#include "SDL_net.h" - -struct packetBuffer { - Bit8u buffer[1024]; - Bit16s packetSize; // Packet size remaining in read - Bit16s packetRead; // Bytes read of total packet - bool inPacket; // In packet reception flag - bool connected; // Connected flag - bool waitsize; -}; - -#define SOCKETTABLESIZE 16 -#define CONVIP(hostvar) hostvar & 0xff, (hostvar >> 8) & 0xff, (hostvar >> 16) & 0xff, (hostvar >> 24) & 0xff -#define CONVIPX(hostvar) hostvar[0], hostvar[1], hostvar[2], hostvar[3], hostvar[4], hostvar[5] - - -void IPX_StopServer(); -bool IPX_StartServer(Bit16u portnum); -bool IPX_isConnectedToServer(Bits tableNum, IPaddress ** ptrAddr); - -Bit8u packetCRC(Bit8u *buffer, Bit16u bufSize); - -#endif - -#endif diff --git a/include/joystick.h b/include/joystick.h index 6e5b6c6..3317db1 100644 --- a/include/joystick.h +++ b/include/joystick.h @@ -1,50 +1,25 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: joystick.h,v 1.12 2007/08/12 10:23:35 c2woody Exp $ */ -#ifndef DOSBOX_JOYSTICK_H -#define DOSBOX_JOYSTICK_H -void JOYSTICK_Enable(Bitu which,bool enabled); - -void JOYSTICK_Button(Bitu which,Bitu num,bool pressed); - -void JOYSTICK_Move_X(Bitu which,float x); - -void JOYSTICK_Move_Y(Bitu which,float y); - -bool JOYSTICK_IsEnabled(Bitu which); - -bool JOYSTICK_GetButton(Bitu which, Bitu num); - -float JOYSTICK_GetMove_X(Bitu which); - -float JOYSTICK_GetMove_Y(Bitu which); - -enum JoystickType { - JOY_NONE, - JOY_AUTO, - JOY_2AXIS, - JOY_4AXIS, - JOY_4AXIS_2, - JOY_FCS, - JOY_CH -}; - -extern JoystickType joytype; -extern bool button_wrapping_enabled; -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +void JOYSTICK_Enable(Bitu which,bool enabled); + +void JOYSTICK_Button(Bitu which,Bitu num,bool pressed); + +void JOYSTICK_Move_X(Bitu which,float x); + +void JOYSTICK_Move_Y(Bitu which,float y); \ No newline at end of file diff --git a/include/keyboard.h b/include/keyboard.h index 1c0de21..ec495d0 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -1,53 +1,54 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_KEYBOARD_H -#define DOSBOX_KEYBOARD_H - -enum KBD_KEYS { - KBD_NONE, - KBD_1, KBD_2, KBD_3, KBD_4, KBD_5, KBD_6, KBD_7, KBD_8, KBD_9, KBD_0, - KBD_q, KBD_w, KBD_e, KBD_r, KBD_t, KBD_y, KBD_u, KBD_i, KBD_o, KBD_p, - KBD_a, KBD_s, KBD_d, KBD_f, KBD_g, KBD_h, KBD_j, KBD_k, KBD_l, KBD_z, - KBD_x, KBD_c, KBD_v, KBD_b, KBD_n, KBD_m, - KBD_f1, KBD_f2, KBD_f3, KBD_f4, KBD_f5, KBD_f6, KBD_f7, KBD_f8, KBD_f9, KBD_f10,KBD_f11,KBD_f12, - - /*Now the weirder keys */ - - KBD_esc,KBD_tab,KBD_backspace,KBD_enter,KBD_space, - KBD_leftalt,KBD_rightalt,KBD_leftctrl,KBD_rightctrl,KBD_leftshift,KBD_rightshift, - KBD_capslock,KBD_scrolllock,KBD_numlock, - - KBD_grave,KBD_minus,KBD_equals,KBD_backslash,KBD_leftbracket,KBD_rightbracket, - KBD_semicolon,KBD_quote,KBD_period,KBD_comma,KBD_slash,KBD_extra_lt_gt, - - KBD_printscreen,KBD_pause, - KBD_insert,KBD_home,KBD_pageup,KBD_delete,KBD_end,KBD_pagedown, - KBD_left,KBD_up,KBD_down,KBD_right, - - KBD_kp1,KBD_kp2,KBD_kp3,KBD_kp4,KBD_kp5,KBD_kp6,KBD_kp7,KBD_kp8,KBD_kp9,KBD_kp0, - KBD_kpdivide,KBD_kpmultiply,KBD_kpminus,KBD_kpplus,KBD_kpenter,KBD_kpperiod, - - - KBD_LAST -}; - -void KEYBOARD_ClrBuffer(void); -void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +typedef void(KEYBOARD_EventHandler)(void); +void KEYBOARD_AddCode(Bit8u code); +void KEYBOARD_AddKey(Bitu keytype,bool pressed); +void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler); + + +#define ALT_PRESSED 0x1 +#define CTRL_PRESSED 0x2 +#define SHIFT_PRESSED 0x4 + +enum { + KBD_1, KBD_2, KBD_3, KBD_4, KBD_5, KBD_6, KBD_7, KBD_8, KBD_9, KBD_0, + KBD_q, KBD_w, KBD_e, KBD_r, KBD_t, KBD_y, KBD_u, KBD_i, KBD_o, KBD_p, + KBD_a, KBD_s, KBD_d, KBD_f, KBD_g, KBD_h, KBD_j, KBD_k, KBD_l, KBD_z, + KBD_x, KBD_c, KBD_v, KBD_b, KBD_n, KBD_m, + KBD_f1, KBD_f2, KBD_f3, KBD_f4, KBD_f5, KBD_f6, KBD_f7, KBD_f8, KBD_f9, KBD_f10,KBD_f11,KBD_f12, + + /*Now the weirder keys */ + + KBD_esc,KBD_tab,KBD_backspace,KBD_enter,KBD_space, + KBD_leftalt,KBD_rightalt,KBD_leftctrl,KBD_rightctrl,KBD_leftshift,KBD_rightshift, + KBD_capslock,KBD_scrolllock,KBD_numlock, + + KBD_grave,KBD_minus,KBD_equals,KBD_backslash,KBD_leftbracket,KBD_rightbracket, + KBD_semicolon,KBD_quote,KBD_period,KBD_comma,KBD_slash, + + KBD_insert,KBD_home,KBD_pageup,KBD_delete,KBD_end,KBD_pagedown, + KBD_left,KBD_up,KBD_down,KBD_right, + + KBD_kp1,KBD_kp2,KBD_kp3,KBD_kp4,KBD_kp5,KBD_kp6,KBD_kp7,KBD_kp8,KBD_kp9,KBD_kp0, + KBD_kpslash,KBD_kpmultiply,KBD_kpminus,KBD_kpplus,KBD_kpenter,KBD_kpperiod, + + KBD_LAST +}; + + diff --git a/include/logging.h b/include/logging.h deleted file mode 100644 index 53005c8..0000000 --- a/include/logging.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef DOSBOX_LOGGING_H -#define DOSBOX_LOGGING_H -enum LOG_TYPES { - LOG_ALL, - LOG_VGA, LOG_VGAGFX,LOG_VGAMISC,LOG_INT10, - LOG_SB,LOG_DMACONTROL, - LOG_FPU,LOG_CPU,LOG_PAGING, - LOG_FCB,LOG_FILES,LOG_IOCTL,LOG_EXEC,LOG_DOSMISC, - LOG_PIT,LOG_KEYBOARD,LOG_PIC, - LOG_MOUSE,LOG_BIOS,LOG_GUI,LOG_MISC, - LOG_IO, - LOG_MAX -}; - -enum LOG_SEVERITIES { - LOG_NORMAL, - LOG_WARN, - LOG_ERROR -}; - -#if C_DEBUG -class LOG -{ - LOG_TYPES d_type; - LOG_SEVERITIES d_severity; -public: - - LOG (LOG_TYPES type , LOG_SEVERITIES severity): - d_type(type), - d_severity(severity) - {} - void operator() (char const* buf, ...) GCC_ATTRIBUTE(__format__(__printf__, 2, 3)); //../src/debug/debug_gui.cpp - -}; - -void DEBUG_ShowMsg(char const* format,...) GCC_ATTRIBUTE(__format__(__printf__, 1, 2)); -#define LOG_MSG DEBUG_ShowMsg - -#else //C_DEBUG - -struct LOG -{ - LOG(LOG_TYPES , LOG_SEVERITIES ) { } - void operator()(char const* ) { } - void operator()(char const* , double ) { } - void operator()(char const* , double , double ) { } - void operator()(char const* , double , double , double ) { } - void operator()(char const* , double , double , double , double ) { } - void operator()(char const* , double , double , double , double , double ) { } - - void operator()(char const* , char const* ) { } - void operator()(char const* , char const* , double ) { } - void operator()(char const* , char const* , double ,double ) { } - void operator()(char const* , double , char const* ) { } - void operator()(char const* , double , double, char const* ) { } - void operator()(char const* , char const*, char const*) { } - - -}; //add missing operators to here - //try to avoid anything smaller than bit32... -void GFX_ShowMsg(char const* format,...) GCC_ATTRIBUTE(__format__(__printf__, 1, 2)); -#define LOG_MSG GFX_ShowMsg - -#endif //C_DEBUG - - -#endif //DOSBOX_LOGGING_H diff --git a/include/mapper.h b/include/mapper.h deleted file mode 100644 index 9f606b7..0000000 --- a/include/mapper.h +++ /dev/null @@ -1,39 +0,0 @@ - /* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_MAPPER_H -#define DOSBOX_MAPPER_H - -enum MapKeys { - MK_f1,MK_f2,MK_f3,MK_f4,MK_f5,MK_f6,MK_f7,MK_f8,MK_f9,MK_f10,MK_f11,MK_f12, - MK_return,MK_kpminus,MK_scrolllock,MK_printscreen,MK_pause - -}; - -typedef void (MAPPER_Handler)(bool pressed); -void MAPPER_AddHandler(MAPPER_Handler * handler,MapKeys key,Bitu mods,char const * const eventname,char const * const buttonname); -void MAPPER_Init(void); -void MAPPER_StartUp(Section * sec); -void MAPPER_Run(bool pressed); -void MAPPER_LosingFocus(void); - - -#define MMOD1 0x1 -#define MMOD2 0x2 - -#endif diff --git a/include/mem.h b/include/mem.h index 5bbb636..1fa0856 100644 --- a/include/mem.h +++ b/include/mem.h @@ -1,219 +1,208 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_MEM_H -#define DOSBOX_MEM_H - -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif - -typedef Bit32u PhysPt; -typedef Bit8u * HostPt; -typedef Bit32u RealPt; - -typedef Bit32s MemHandle; - -#define MEM_PAGESIZE 4096 - -extern HostPt MemBase; -HostPt GetMemBase(void); - -bool MEM_A20_Enabled(void); -void MEM_A20_Enable(bool enable); - -/* Memory management / EMS mapping */ -HostPt MEM_GetBlockPage(void); -Bitu MEM_FreeTotal(void); //Free 4 kb pages -Bitu MEM_FreeLargest(void); //Largest free 4 kb pages block -Bitu MEM_TotalPages(void); //Total amount of 4 kb pages -Bitu MEM_AllocatedPages(MemHandle handle); // amount of allocated pages of handle -MemHandle MEM_AllocatePages(Bitu pages,bool sequence); -MemHandle MEM_GetNextFreePage(void); -PhysPt MEM_AllocatePage(void); -void MEM_ReleasePages(MemHandle handle); -bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence); - -MemHandle MEM_NextHandle(MemHandle handle); -MemHandle MEM_NextHandleAt(MemHandle handle,Bitu where); - -/* - The folowing six functions are used everywhere in the end so these should be changed for - Working on big or little endian machines -*/ - -#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) - -static INLINE Bit8u host_readb(HostPt off) { - return off[0]; -} -static INLINE Bit16u host_readw(HostPt off) { - return off[0] | (off[1] << 8); -} -static INLINE Bit32u host_readd(HostPt off) { - return off[0] | (off[1] << 8) | (off[2] << 16) | (off[3] << 24); -} -static INLINE void host_writeb(HostPt off,Bit8u val) { - off[0]=val; -} -static INLINE void host_writew(HostPt off,Bit16u val) { - off[0]=(Bit8u)(val); - off[1]=(Bit8u)(val >> 8); -} -static INLINE void host_writed(HostPt off,Bit32u val) { - off[0]=(Bit8u)(val); - off[1]=(Bit8u)(val >> 8); - off[2]=(Bit8u)(val >> 16); - off[3]=(Bit8u)(val >> 24); -} - -#else - -static INLINE Bit8u host_readb(HostPt off) { - return *(Bit8u *)off; -} -static INLINE Bit16u host_readw(HostPt off) { - return *(Bit16u *)off; -} -static INLINE Bit32u host_readd(HostPt off) { - return *(Bit32u *)off; -} -static INLINE void host_writeb(HostPt off,Bit8u val) { - *(Bit8u *)(off)=val; -} -static INLINE void host_writew(HostPt off,Bit16u val) { - *(Bit16u *)(off)=val; -} -static INLINE void host_writed(HostPt off,Bit32u val) { - *(Bit32u *)(off)=val; -} - -#endif - - -static INLINE void var_write(Bit8u * var, Bit8u val) { - host_writeb((HostPt)var, val); -} - -static INLINE void var_write(Bit16u * var, Bit16u val) { - host_writew((HostPt)var, val); -} - -static INLINE void var_write(Bit32u * var, Bit32u val) { - host_writed((HostPt)var, val); -} - -/* The Folowing six functions are slower but they recognize the paged memory system */ - -Bit8u mem_readb(PhysPt pt); -Bit16u mem_readw(PhysPt pt); -Bit32u mem_readd(PhysPt pt); - -void mem_writeb(PhysPt pt,Bit8u val); -void mem_writew(PhysPt pt,Bit16u val); -void mem_writed(PhysPt pt,Bit32u val); - -static INLINE void phys_writeb(PhysPt addr,Bit8u val) { - host_writeb(MemBase+addr,val); -} -static INLINE void phys_writew(PhysPt addr,Bit16u val){ - host_writew(MemBase+addr,val); -} -static INLINE void phys_writed(PhysPt addr,Bit32u val){ - host_writed(MemBase+addr,val); -} - -static INLINE Bit8u phys_readb(PhysPt addr) { - return host_readb(MemBase+addr); -} -static INLINE Bit16u phys_readw(PhysPt addr){ - return host_readw(MemBase+addr); -} -static INLINE Bit32u phys_readd(PhysPt addr){ - return host_readd(MemBase+addr); -} - -/* These don't check for alignment, better be sure it's correct */ - -void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size); -void MEM_BlockRead(PhysPt pt,void * data,Bitu size); -void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size); -void MEM_StrCopy(PhysPt pt,char * data,Bitu size); - -void mem_memcpy(PhysPt dest,PhysPt src,Bitu size); -Bitu mem_strlen(PhysPt pt); -void mem_strcpy(PhysPt dest,PhysPt src); - -/* The folowing functions are all shortcuts to the above functions using physical addressing */ - -static INLINE Bit8u real_readb(Bit16u seg,Bit16u off) { - return mem_readb((seg<<4)+off); -} -static INLINE Bit16u real_readw(Bit16u seg,Bit16u off) { - return mem_readw((seg<<4)+off); -} -static INLINE Bit32u real_readd(Bit16u seg,Bit16u off) { - return mem_readd((seg<<4)+off); -} - -static INLINE void real_writeb(Bit16u seg,Bit16u off,Bit8u val) { - mem_writeb(((seg<<4)+off),val); -} -static INLINE void real_writew(Bit16u seg,Bit16u off,Bit16u val) { - mem_writew(((seg<<4)+off),val); -} -static INLINE void real_writed(Bit16u seg,Bit16u off,Bit32u val) { - mem_writed(((seg<<4)+off),val); -} - - -static INLINE Bit16u RealSeg(RealPt pt) { - return (Bit16u)(pt>>16); -} - -static INLINE Bit16u RealOff(RealPt pt) { - return (Bit16u)(pt&0xffff); -} - -static INLINE PhysPt Real2Phys(RealPt pt) { - return (RealSeg(pt)<<4) +RealOff(pt); -} - -static INLINE PhysPt PhysMake(Bit16u seg,Bit16u off) { - return (seg<<4)+off; -} - -static INLINE RealPt RealMake(Bit16u seg,Bit16u off) { - return (seg<<16)+off; -} - -static INLINE void RealSetVec(Bit8u vec,RealPt pt) { - mem_writed(vec<<2,pt); -} - -static INLINE void RealSetVec(Bit8u vec,RealPt pt,RealPt &old) { - old = mem_readd(vec<<2); - mem_writed(vec<<2,pt); -} - -static INLINE RealPt RealGetVec(Bit8u vec) { - return mem_readd(vec<<2); -} - -#endif - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if !defined __MEM_H +#define __MEM_H +#include + +enum { MEMORY_HANDLER=1,MEMORY_RELOCATE=2}; + +#define bmemcpy(mem1,mem2,size) memcpy((void *)mem1,(void *)mem2,size) + +typedef Bit8u (MEMORY_ReadHandler)(Bit32u start); +typedef void (MEMORY_WriteHandler)(Bit32u start,Bit8u val); + +typedef Bit32u PhysOff; +typedef Bit32u PhysPt; +typedef Bit8u * HostOff; +typedef Bit8u * HostPt; +typedef Bit32u RealPt; + +struct PageEntry { + Bit8u type; + PhysOff base; /* Used to calculate relative offset */ + struct { + MEMORY_WriteHandler * write; + MEMORY_ReadHandler * read; + } handler; + HostOff relocate; /* This points to host machine address */ +}; + +struct EMM_Handle { + Bit16u next; + Bit16u size; /* Size in pages */ + PhysOff phys_base; + HostOff host_base; + bool active; + bool free; +}; + +INLINE Bit16u PAGES(Bit32u bytes) { + if ((bytes & 4095) == 0) return (Bit16u)(bytes>>12); + return (Bit16u)(1+(bytes>>12)); +} + +extern Bit8u * memory; +extern EMM_Handle EMM_Handles[]; +extern PageEntry * PageEntries[]; /* Number of pages */ + +bool MEMORY_TestSpecial(PhysOff off); +void MEMORY_SetupHandler(Bit32u page,Bit32u extra,PageEntry * handler); +void MEMORY_ResetHandler(Bit32u page,Bit32u pages); + + +void EMM_GetFree(Bit16u * maxblock,Bit16u * total); +void EMM_Allocate(Bit16u size,Bit16u * handle); +void EMM_Free(Bit16u handle); + + +/* + The folowing six functions are used everywhere in the end so these should be changed for + Working on big or little endian machines +*/ + + +INLINE Bit8u readb(HostOff off) { + return *(Bit8u *)off; +}; +INLINE Bit16u readw(HostOff off) { + return *(Bit16u *)off; +}; +INLINE Bit32u readd(HostOff off) { + return *(Bit32u *)off; +}; +INLINE void writeb(HostOff off,Bit8u val) { + *(Bit8u *)(off)=val; +}; +INLINE void writew(HostOff off,Bit16u val) { + *(Bit16u *)(off)=val; +}; +INLINE void writed(HostOff off,Bit32u val) { + *(Bit32u *)(off)=val; +}; + + +/* The Folowing six functions are slower but they recognize the paged memory system */ +//TODO maybe make em inline to go a bit faster + +Bit8u mem_readb(PhysOff off); +Bit16u mem_readw(PhysOff off); +Bit32u mem_readd(PhysOff off); + +void mem_writeb(PhysOff off,Bit8u val); +void mem_writew(PhysOff off,Bit16u val); +void mem_writed(PhysOff off,Bit32u val); + + + + + +void MEM_BlockWrite(PhysOff off,void * data,Bitu size); +void MEM_BlockRead(PhysOff off,void * data,Bitu size); +void MEM_BlockCopy(PhysOff dest,PhysOff src,Bitu size); +void MEM_StrCopy(PhysOff off,char * data,Bitu size); + + + +/* The folowing functions are all shortcuts to the above functions using physical addressing */ + +INLINE HostOff real_off(Bit16u seg,Bit32u off) { + return memory+(seg<<4)+off; +}; + +INLINE HostOff real_host(Bit16u seg,Bit32u off) { + return memory+(seg<<4)+off; +}; +INLINE PhysOff real_phys(Bit16u seg,Bit32u off) { + return (seg<<4)+off; +}; + +INLINE Bit8u real_readb(Bit16u seg,Bit16u off) { + return mem_readb((seg<<4)+off); +} +INLINE Bit16u real_readw(Bit16u seg,Bit16u off) { + return mem_readw((seg<<4)+off); +} +INLINE Bit32u real_readd(Bit16u seg,Bit16u off) { + return mem_readd((seg<<4)+off); +} +//#define real_readb(seg,off) mem_readb(((seg)<<4)+(off)) +//#define real_readw(seg,off) mem_readw(((seg)<<4)+(off)) +//#define real_readd(seg,off) mem_readd(((seg)<<4)+(off)) + +INLINE void real_writeb(Bit16u seg,Bit16u off,Bit8u val) { + mem_writeb(((seg<<4)+off),val); +} +INLINE void real_writew(Bit16u seg,Bit16u off,Bit16u val) { + mem_writew(((seg<<4)+off),val); +} +INLINE void real_writed(Bit16u seg,Bit16u off,Bit32u val) { + mem_writed(((seg<<4)+off),val); +} + + +//#define real_writeb(seg,off,val) mem_writeb((((seg)<<4)+(off)),val) +//#define real_writew(seg,off,val) mem_writew((((seg)<<4)+(off)),val) +//#define real_writed(seg,off,val) mem_writed((((seg)<<4)+(off)),val) + +inline Bit32u real_getvec(Bit8u num) { + return real_readd(0,(num<<2)); +} +/* +inline void real_setvec(Bit8u num,Bit32u addr) { + real_writed(0,(num<<2),addr); +}; + +*/ + +INLINE Bit16u RealSeg(RealPt pt) { + return (Bit16u)(pt>>16); +} + +INLINE Bit16u RealOff(RealPt pt) { + return (Bit16u)(pt&0xffff); +} + +INLINE PhysPt Real2Phys(RealPt pt) { + return (RealSeg(pt)<<4) +RealOff(pt); +} + + +INLINE HostPt Real2Host(RealPt pt) { + return memory+(RealSeg(pt)<<4) +RealOff(pt); +} + + +INLINE RealPt RealMake(Bit16u seg,Bit16u off) { + return (seg<<16)+off; +} + + +INLINE void RealSetVec(Bit8u vec,RealPt pt) { + mem_writed(vec<<2,pt); +} + +INLINE RealPt RealGetVec(Bit8u vec) { + return mem_readd(vec<<2); +} + + + + +#endif + diff --git a/include/mixer.h b/include/mixer.h index a0b6dc9..e41b183 100644 --- a/include/mixer.h +++ b/include/mixer.h @@ -1,114 +1,42 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: mixer.h,v 1.19 2009/04/28 21:48:24 harekiet Exp $ */ - -#ifndef DOSBOX_MIXER_H -#define DOSBOX_MIXER_H - -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif - -typedef void (*MIXER_MixHandler)(Bit8u * sampdate,Bit32u len); -typedef void (*MIXER_Handler)(Bitu len); - -enum BlahModes { - MIXER_8MONO,MIXER_8STEREO, - MIXER_16MONO,MIXER_16STEREO -}; - -enum MixerModes { - M_8M,M_8S, - M_16M,M_16S -}; - -#define MIXER_BUFSIZE (16*1024) -#define MIXER_BUFMASK (MIXER_BUFSIZE-1) -extern Bit8u MixTemp[MIXER_BUFSIZE]; - -#define MAX_AUDIO ((1<<(16-1))-1) -#define MIN_AUDIO -(1<<(16-1)) - -class MixerChannel { -public: - void SetVolume(float _left,float _right); - void SetScale( float f ); - void UpdateVolume(void); - void SetFreq(Bitu _freq); - void Mix(Bitu _needed); - void AddSilence(void); //Fill up until needed - - template - void AddSamples(Bitu len, const Type* data); - - void AddSamples_m8(Bitu len, const Bit8u * data); - void AddSamples_s8(Bitu len, const Bit8u * data); - void AddSamples_m8s(Bitu len, const Bit8s * data); - void AddSamples_s8s(Bitu len, const Bit8s * data); - void AddSamples_m16(Bitu len, const Bit16s * data); - void AddSamples_s16(Bitu len, const Bit16s * data); - void AddSamples_m16u(Bitu len, const Bit16u * data); - void AddSamples_s16u(Bitu len, const Bit16u * data); - void AddSamples_m32(Bitu len, const Bit32s * data); - void AddSamples_s32(Bitu len, const Bit32s * data); - void AddSamples_m16_nonnative(Bitu len, const Bit16s * data); - void AddSamples_s16_nonnative(Bitu len, const Bit16s * data); - void AddSamples_m16u_nonnative(Bitu len, const Bit16u * data); - void AddSamples_s16u_nonnative(Bitu len, const Bit16u * data); - void AddSamples_m32_nonnative(Bitu len, const Bit32s * data); - void AddSamples_s32_nonnative(Bitu len, const Bit32s * data); - - void AddStretched(Bitu len,Bit16s * data); //Strech block up into needed data - void FillUp(void); - void Enable(bool _yesno); - MIXER_Handler handler; - float volmain[2]; - float scale; - Bit32s volmul[2]; - Bitu freq_add,freq_index; - Bitu done,needed; - Bits last[2]; - const char * name; - bool enabled; - MixerChannel * next; -}; - -MixerChannel * MIXER_AddChannel(MIXER_Handler handler,Bitu freq,const char * name); -MixerChannel * MIXER_FindChannel(const char * name); -/* Find the device you want to delete with findchannel "delchan gets deleted" */ -void MIXER_DelChannel(MixerChannel* delchan); - -/* Object to maintain a mixerchannel; As all objects it registers itself with create - * and removes itself when destroyed. */ -class MixerObject{ -private: - bool installed; - char m_name[32]; -public: - MixerObject():installed(false){}; - MixerChannel* Install(MIXER_Handler handler,Bitu freq,const char * name); - ~MixerObject(); -}; - - -/* PC Speakers functions, tightly related to the timer functions */ -void PCSPEAKER_SetCounter(Bitu cntr,Bitu mode); -void PCSPEAKER_SetType(Bitu mode); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +typedef void (*MIXER_MixHandler)(Bit8u * sampdate,Bit32u len); + +#define MIXER_8MONO 0 +#define MIXER_8STEREO 1 +#define MIXER_16MONO 2 +#define MIXER_16STEREO 3 + +#define MAX_AUDIO ((1<<(16-1))-1) +#define MIN_AUDIO -(1<<(16-1)) + + + +struct MIXER_Channel; + + +MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * name); +void MIXER_SetVolume(MIXER_Channel * chan,Bit8u vol); +void MIXER_SetFreq(MIXER_Channel * chan,Bit32u freq); +void MIXER_SetMode(MIXER_Channel * chan,Bit8u mode); +void MIXER_Enable(MIXER_Channel * chan,bool enable); + +void PCSPEAKER_Enable(bool enable); +void PCSPEAKER_SetFreq(Bit32u freq); + diff --git a/include/modules.h b/include/modules.h index 5c35a7b..6bbeffc 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1,180 +1,180 @@ -/* Standard data types used */ - -typedef unsigned char Bit8u; -typedef signed char Bit8s; -typedef unsigned short Bit16u; -typedef signed short Bit16s; -typedef unsigned long Bit32u; -typedef signed long Bit32s; -#if defined(_MSC_VER) -typedef unsigned __int64 Bit64u; -typedef signed __int64 Bit64s; -#else -typedef unsigned long long int Bit64u; -typedef signed long long int Bit64s; -#endif - - - -/* Setting up pointers to all subfunctions */ -#ifdef MODULE_WANT_IO_READ -typedef Bit8u (* IO_ReadHandler)(Bit32u port); -static void (* IO_RegisterReadHandler)(Bit32u port,IO_ReadHandler handler,char * name); -static void (* IO_FreeReadHandler)(Bit32u port); -#endif - -#ifdef MODULE_WANT_IO_WRITE -typedef void (* IO_WriteHandler)(Bit32u port,Bit8u value); -static void (* IO_RegisterWriteHandler)(Bit32u port,IO_WriteHandler handler,char * name); -static void (* IO_FreeWriteHandler)(Bit32u port); -#endif - -#ifdef MODULE_WANT_IRQ_EOI -typedef void (* IRQ_EOIHandler)(void); -static void (* IRQ_RegisterEOIHandler)(Bit32u irq,IRQ_EOIHandler handler,char * name); -static void (* IRQ_FreeEOIHandler)(Bit32u irq); -#endif - -#ifdef MODULE_WANT_IRQ -static void (* IRQ_Activate)(Bit32u irq); -static void (* IRQ_Deactivate)(Bit32u irq); -#endif - -#ifdef MODULE_WANT_TIMER -typedef void (* TIMER_MicroHandler)(void); -static void (* TIMER_RegisterMicroHandler)(TIMER_MicroHandler handler,Bit32u micro); -#endif - -#ifdef MODULE_WANT_TIMER_TICK -typedef void (* TIMER_TickHandler)(Bit32u ticks); -static void (* TIMER_RegisterTickHandler)(TIMER_TickHandler handler); -#endif - -/* - 4 8-bit and 4 16-bit channels you can read data from - 16-bit reads are word sized -*/ - -#ifdef MODULE_WANT_DMA_READ -static void (* DMA_8_Read)(Bit32u chan,Bit8u * data,Bit16u size); -static void (* DMA_16_Read)(Bit32u chan,Bit8u * data,Bit16u size); -#endif - -/* - 4 8-bit and 4 16-bit channels you can write data from - 16-bit writes are word sized -*/ - -#ifdef MODULE_WANT_DMA_READ -static void (* DMA_8_Write)(Bit32u chan,Bit8u * data,Bit16u size); -static void (* DMA_16_Write)(Bit32u chan,Bit8u * data,Bit16u size); -#endif - - -#ifdef MODULE_WANT_MIXER -/* The len here means the amount of samples needed not the buffersize it needed to fill */ -typedef void (* MIXER_MixHandler)(Bit8u * sampdate,Bit32u len); - -/* Different types if modes a mixer channel can work in */ -#define MIXER_8MONO 0 -#define MIXER_8STEREO 1 -#define MIXER_16MONO 2 -#define MIXER_16STEREO 3 -struct MIXER_Channel; - -#define MAX_AUDIO ((1<<(16-1))-1) -#define MIN_AUDIO -(1<<(16-1)) - -MIXER_Channel *(* MIXER_AddChannel)(MIXER_MixHandler handler,Bit32u freq,char * name); -void (* MIXER_SetVolume)(MIXER_Channel * chan,Bit8u vol); -void (* MIXER_SetFreq)(MIXER_Channel * chan,Bit32u freq); -void (* MIXER_SetMode)(MIXER_Channel * chan,Bit8u mode); -void (* MIXER_Enable)(MIXER_Channel * chan,bool enable); -#endif - -typedef bool (* MODULE_FindHandler)(char * name,void * * function); -typedef char *(* MODULE_StartHandler)(MODULE_FindHandler find_handler); - -#define MODULE_START_PROC "ModuleStart" - -#ifdef MODULE_START_FUNCTION -#include - -#define GET_FUNCTION(a) \ - if (!find_handler(#a ,(void * *) &a)) { \ - return "Can't find requested function"; \ - }; - - -#if defined (WIN32) -#include -BOOL APIENTRY DllMain( HANDLE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) -{ - return TRUE; -} - -extern "C" { -__declspec(dllexport) -#endif -char * ModuleStart (MODULE_FindHandler find_handler) { - -#ifdef MODULE_WANT_IRQ_EOI -GET_FUNCTION(IRQ_RegisterEOIHandler); -GET_FUNCTION(IRQ_FreeEOIHandler); -#endif - -#ifdef MODULE_WANT_IRQ -GET_FUNCTION(IRQ_Activate); -GET_FUNCTION(IRQ_Deactivate); -#endif - -#ifdef MODULE_WANT_IO_READ -GET_FUNCTION(IO_RegisterReadHandler); -GET_FUNCTION(IO_FreeReadHandler); -#endif - -#ifdef MODULE_WANT_IO_WRITE -GET_FUNCTION(IO_RegisterWriteHandler); -GET_FUNCTION(IO_FreeWriteHandler); -#endif - -#ifdef MODULE_WANT_TIMER -GET_FUNCTION(TIMER_RegisterMicroHandler); -#endif - -#ifdef MODULE_WANT_TIMER_TICKS -GET_FUNCTION(TIMER_RegisterTickHandler); -#endif - -#ifdef MODULE_WANT_DMA_READ -GET_FUNCTION(DMA_8_Read); -GET_FUNCTION(DMA_16_Read); -#endif - -#ifdef MODULE_WANT_DMA_WRITE -GET_FUNCTION(DMA_8_Write); -GET_FUNCTION(DMA_16_Write); -#endif - -#ifdef MODULE_WANT_MIXER -GET_FUNCTION(MIXER_AddChannel); -GET_FUNCTION(MIXER_SetVolume); -GET_FUNCTION(MIXER_SetFreq); -GET_FUNCTION(MIXER_SetMode); -GET_FUNCTION(MIXER_Enable); -#endif - -return MODULE_START_FUNCTION; - -} -#if defined (WIN32) -} -#endif - - - -#endif - +/* Standard data types used */ + +typedef unsigned char Bit8u; +typedef signed char Bit8s; +typedef unsigned short Bit16u; +typedef signed short Bit16s; +typedef unsigned long Bit32u; +typedef signed long Bit32s; +#if defined(_MSC_VER) +typedef unsigned __int64 Bit64u; +typedef signed __int64 Bit64s; +#else +typedef unsigned long long int Bit64u; +typedef signed long long int Bit64s; +#endif + + + +/* Setting up pointers to all subfunctions */ +#ifdef MODULE_WANT_IO_READ +typedef Bit8u (* IO_ReadHandler)(Bit32u port); +static void (* IO_RegisterReadHandler)(Bit32u port,IO_ReadHandler handler,char * name); +static void (* IO_FreeReadHandler)(Bit32u port); +#endif + +#ifdef MODULE_WANT_IO_WRITE +typedef void (* IO_WriteHandler)(Bit32u port,Bit8u value); +static void (* IO_RegisterWriteHandler)(Bit32u port,IO_WriteHandler handler,char * name); +static void (* IO_FreeWriteHandler)(Bit32u port); +#endif + +#ifdef MODULE_WANT_IRQ_EOI +typedef void (* IRQ_EOIHandler)(void); +static void (* IRQ_RegisterEOIHandler)(Bit32u irq,IRQ_EOIHandler handler,char * name); +static void (* IRQ_FreeEOIHandler)(Bit32u irq); +#endif + +#ifdef MODULE_WANT_IRQ +static void (* IRQ_Activate)(Bit32u irq); +static void (* IRQ_Deactivate)(Bit32u irq); +#endif + +#ifdef MODULE_WANT_TIMER +typedef void (* TIMER_MicroHandler)(void); +static void (* TIMER_RegisterMicroHandler)(TIMER_MicroHandler handler,Bit32u micro); +#endif + +#ifdef MODULE_WANT_TIMER_TICK +typedef void (* TIMER_TickHandler)(Bit32u ticks); +static void (* TIMER_RegisterTickHandler)(TIMER_TickHandler handler); +#endif + +/* + 4 8-bit and 4 16-bit channels you can read data from + 16-bit reads are word sized +*/ + +#ifdef MODULE_WANT_DMA_READ +static void (* DMA_8_Read)(Bit32u chan,Bit8u * data,Bit16u size); +static void (* DMA_16_Read)(Bit32u chan,Bit8u * data,Bit16u size); +#endif + +/* + 4 8-bit and 4 16-bit channels you can write data from + 16-bit writes are word sized +*/ + +#ifdef MODULE_WANT_DMA_READ +static void (* DMA_8_Write)(Bit32u chan,Bit8u * data,Bit16u size); +static void (* DMA_16_Write)(Bit32u chan,Bit8u * data,Bit16u size); +#endif + + +#ifdef MODULE_WANT_MIXER +/* The len here means the amount of samples needed not the buffersize it needed to fill */ +typedef void (* MIXER_MixHandler)(Bit8u * sampdate,Bit32u len); + +/* Different types if modes a mixer channel can work in */ +#define MIXER_8MONO 0 +#define MIXER_8STEREO 1 +#define MIXER_16MONO 2 +#define MIXER_16STEREO 3 +struct MIXER_Channel; + +#define MAX_AUDIO ((1<<(16-1))-1) +#define MIN_AUDIO -(1<<(16-1)) + +MIXER_Channel *(* MIXER_AddChannel)(MIXER_MixHandler handler,Bit32u freq,char * name); +void (* MIXER_SetVolume)(MIXER_Channel * chan,Bit8u vol); +void (* MIXER_SetFreq)(MIXER_Channel * chan,Bit32u freq); +void (* MIXER_SetMode)(MIXER_Channel * chan,Bit8u mode); +void (* MIXER_Enable)(MIXER_Channel * chan,bool enable); +#endif + +typedef bool (* MODULE_FindHandler)(char * name,void * * function); +typedef char *(* MODULE_StartHandler)(MODULE_FindHandler find_handler); + +#define MODULE_START_PROC "ModuleStart" + +#ifdef MODULE_START_FUNCTION +#include + +#define GET_FUNCTION(a) \ + if (!find_handler(#a ,(void * *) &a)) { \ + return "Can't find requested function"; \ + }; + + +#if defined (WIN32) +#include +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + return TRUE; +} + +extern "C" { +__declspec(dllexport) +#endif +char * ModuleStart (MODULE_FindHandler find_handler) { + +#ifdef MODULE_WANT_IRQ_EOI +GET_FUNCTION(IRQ_RegisterEOIHandler); +GET_FUNCTION(IRQ_FreeEOIHandler); +#endif + +#ifdef MODULE_WANT_IRQ +GET_FUNCTION(IRQ_Activate); +GET_FUNCTION(IRQ_Deactivate); +#endif + +#ifdef MODULE_WANT_IO_READ +GET_FUNCTION(IO_RegisterReadHandler); +GET_FUNCTION(IO_FreeReadHandler); +#endif + +#ifdef MODULE_WANT_IO_WRITE +GET_FUNCTION(IO_RegisterWriteHandler); +GET_FUNCTION(IO_FreeWriteHandler); +#endif + +#ifdef MODULE_WANT_TIMER +GET_FUNCTION(TIMER_RegisterMicroHandler); +#endif + +#ifdef MODULE_WANT_TIMER_TICKS +GET_FUNCTION(TIMER_RegisterTickHandler); +#endif + +#ifdef MODULE_WANT_DMA_READ +GET_FUNCTION(DMA_8_Read); +GET_FUNCTION(DMA_16_Read); +#endif + +#ifdef MODULE_WANT_DMA_WRITE +GET_FUNCTION(DMA_8_Write); +GET_FUNCTION(DMA_16_Write); +#endif + +#ifdef MODULE_WANT_MIXER +GET_FUNCTION(MIXER_AddChannel); +GET_FUNCTION(MIXER_SetVolume); +GET_FUNCTION(MIXER_SetFreq); +GET_FUNCTION(MIXER_SetMode); +GET_FUNCTION(MIXER_Enable); +#endif + +return MODULE_START_FUNCTION; + +} +#if defined (WIN32) +} +#endif + + + +#endif + diff --git a/include/mouse.h b/include/mouse.h index 06a46ad..4d0c932 100644 --- a/include/mouse.h +++ b/include/mouse.h @@ -1,42 +1,28 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: mouse.h,v 1.14 2008/03/08 22:04:44 c2woody Exp $ */ - - -#ifndef DOSBOX_MOUSE_H -#define DOSBOX_MOUSE_H - - -void Mouse_ShowCursor(void); -void Mouse_HideCursor(void); - -bool Mouse_SetPS2State(bool use); - -void Mouse_ChangePS2Callback(Bit16u pseg, Bit16u pofs); - - -void Mouse_CursorMoved(float xrel,float yrel,float x,float y,bool emulate); -void Mouse_CursorSet(float x,float y); -void Mouse_ButtonPressed(Bit8u button); -void Mouse_ButtonReleased(Bit8u button); - -void Mouse_AutoLock(bool enable); -void Mouse_NewVideoMode(void); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +void Mouse_ShowCursor(void); +void Mouse_HideCursor(void); + + +void Mouse_CursorMoved(float x,float y); +void Mouse_CursorSet(float x,float y); +void Mouse_ButtonPressed(Bit8u button); +void Mouse_ButtonReleased(Bit8u button); + + diff --git a/include/paging.h b/include/paging.h deleted file mode 100644 index f6fb81e..0000000 --- a/include/paging.h +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: paging.h,v 1.32 2009/04/25 16:25:03 harekiet Exp $ */ - -#ifndef DOSBOX_PAGING_H -#define DOSBOX_PAGING_H - -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif -#ifndef DOSBOX_MEM_H -#include "mem.h" -#endif - -// disable this to reduce the size of the TLB -// NOTE: does not work with the dynamic core (dynrec is fine) -#define USE_FULL_TLB - -class PageDirectory; - -#define MEM_PAGE_SIZE (4096) -#define XMS_START (0x110) - -#if defined(USE_FULL_TLB) -#define TLB_SIZE (1024*1024) -#else -#define TLB_SIZE 65536 // This must a power of 2 and greater then LINK_START -#define BANK_SHIFT 28 -#define BANK_MASK 0xffff // always the same as TLB_SIZE-1? -#define TLB_BANKS ((1024*1024/TLB_SIZE)-1) -#endif - -#define PFLAG_READABLE 0x1 -#define PFLAG_WRITEABLE 0x2 -#define PFLAG_HASROM 0x4 -#define PFLAG_HASCODE 0x8 //Page contains dynamic code -#define PFLAG_NOCODE 0x10 //No dynamic code can be generated here -#define PFLAG_INIT 0x20 //No dynamic code can be generated here - -#define LINK_START ((1024+64)/4) //Start right after the HMA - -//Allow 128 mb of memory to be linked -#define PAGING_LINKS (128*1024/4) - -class PageHandler { -public: - virtual ~PageHandler(void) { } - virtual Bitu readb(PhysPt addr); - virtual Bitu readw(PhysPt addr); - virtual Bitu readd(PhysPt addr); - virtual void writeb(PhysPt addr,Bitu val); - virtual void writew(PhysPt addr,Bitu val); - virtual void writed(PhysPt addr,Bitu val); - virtual HostPt GetHostReadPt(Bitu phys_page); - virtual HostPt GetHostWritePt(Bitu phys_page); - virtual bool readb_checked(PhysPt addr,Bit8u * val); - virtual bool readw_checked(PhysPt addr,Bit16u * val); - virtual bool readd_checked(PhysPt addr,Bit32u * val); - virtual bool writeb_checked(PhysPt addr,Bitu val); - virtual bool writew_checked(PhysPt addr,Bitu val); - virtual bool writed_checked(PhysPt addr,Bitu val); - Bitu flags; -}; - -/* Some other functions */ -void PAGING_Enable(bool enabled); -bool PAGING_Enabled(void); - -Bitu PAGING_GetDirBase(void); -void PAGING_SetDirBase(Bitu cr3); -void PAGING_InitTLB(void); -void PAGING_ClearTLB(void); - -void PAGING_LinkPage(Bitu lin_page,Bitu phys_page); -void PAGING_LinkPage_ReadOnly(Bitu lin_page,Bitu phys_page); -void PAGING_UnlinkPages(Bitu lin_page,Bitu pages); -/* This maps the page directly, only use when paging is disabled */ -void PAGING_MapPage(Bitu lin_page,Bitu phys_page); -bool PAGING_MakePhysPage(Bitu & page); -bool PAGING_ForcePageInit(Bitu lin_addr); - -void MEM_SetLFB(Bitu page, Bitu pages, PageHandler *handler, PageHandler *mmiohandler); -void MEM_SetPageHandler(Bitu phys_page, Bitu pages, PageHandler * handler); -void MEM_ResetPageHandler(Bitu phys_page, Bitu pages); - - -#ifdef _MSC_VER -#pragma pack (1) -#endif -struct X86_PageEntryBlock{ -#ifdef WORDS_BIGENDIAN - Bit32u base:20; - Bit32u avl:3; - Bit32u g:1; - Bit32u pat:1; - Bit32u d:1; - Bit32u a:1; - Bit32u pcd:1; - Bit32u pwt:1; - Bit32u us:1; - Bit32u wr:1; - Bit32u p:1; -#else - Bit32u p:1; - Bit32u wr:1; - Bit32u us:1; - Bit32u pwt:1; - Bit32u pcd:1; - Bit32u a:1; - Bit32u d:1; - Bit32u pat:1; - Bit32u g:1; - Bit32u avl:3; - Bit32u base:20; -#endif -} GCC_ATTRIBUTE(packed); -#ifdef _MSC_VER -#pragma pack () -#endif - - -union X86PageEntry { - Bit32u load; - X86_PageEntryBlock block; -}; - -#if !defined(USE_FULL_TLB) -typedef struct { - HostPt read; - HostPt write; - PageHandler * readhandler; - PageHandler * writehandler; - Bit32u phys_page; -} tlb_entry; -#endif - -struct PagingBlock { - Bitu cr3; - Bitu cr2; - struct { - Bitu page; - PhysPt addr; - } base; -#if defined(USE_FULL_TLB) - struct { - HostPt read[TLB_SIZE]; - HostPt write[TLB_SIZE]; - PageHandler * readhandler[TLB_SIZE]; - PageHandler * writehandler[TLB_SIZE]; - Bit32u phys_page[TLB_SIZE]; - } tlb; -#else - tlb_entry tlbh[TLB_SIZE]; - tlb_entry *tlbh_banks[TLB_BANKS]; -#endif - struct { - Bitu used; - Bit32u entries[PAGING_LINKS]; - } links; - Bit32u firstmb[LINK_START]; - bool enabled; -}; - -extern PagingBlock paging; - -/* Some support functions */ - -PageHandler * MEM_GetPageHandler(Bitu phys_page); - - -/* Unaligned address handlers */ -Bit16u mem_unalignedreadw(PhysPt address); -Bit32u mem_unalignedreadd(PhysPt address); -void mem_unalignedwritew(PhysPt address,Bit16u val); -void mem_unalignedwrited(PhysPt address,Bit32u val); - -bool mem_unalignedreadw_checked(PhysPt address,Bit16u * val); -bool mem_unalignedreadd_checked(PhysPt address,Bit32u * val); -bool mem_unalignedwritew_checked(PhysPt address,Bit16u val); -bool mem_unalignedwrited_checked(PhysPt address,Bit32u val); - -#if defined(USE_FULL_TLB) - -static INLINE HostPt get_tlb_read(PhysPt address) { - return paging.tlb.read[address>>12]; -} -static INLINE HostPt get_tlb_write(PhysPt address) { - return paging.tlb.write[address>>12]; -} -static INLINE PageHandler* get_tlb_readhandler(PhysPt address) { - return paging.tlb.readhandler[address>>12]; -} -static INLINE PageHandler* get_tlb_writehandler(PhysPt address) { - return paging.tlb.writehandler[address>>12]; -} - -/* Use these helper functions to access linear addresses in readX/writeX functions */ -static INLINE PhysPt PAGING_GetPhysicalPage(PhysPt linePage) { - return (paging.tlb.phys_page[linePage>>12]<<12); -} - -static INLINE PhysPt PAGING_GetPhysicalAddress(PhysPt linAddr) { - return (paging.tlb.phys_page[linAddr>>12]<<12)|(linAddr&0xfff); -} - -#else - -void PAGING_InitTLBBank(tlb_entry **bank); - -static INLINE tlb_entry *get_tlb_entry(PhysPt address) { - Bitu index=(address>>12); - if (TLB_BANKS && (index > TLB_SIZE)) { - Bitu bank=(address>>BANK_SHIFT) - 1; - if (!paging.tlbh_banks[bank]) - PAGING_InitTLBBank(&paging.tlbh_banks[bank]); - return &paging.tlbh_banks[bank][index & BANK_MASK]; - } - return &paging.tlbh[index]; -} - -static INLINE HostPt get_tlb_read(PhysPt address) { - return get_tlb_entry(address)->read; -} -static INLINE HostPt get_tlb_write(PhysPt address) { - return get_tlb_entry(address)->write; -} -static INLINE PageHandler* get_tlb_readhandler(PhysPt address) { - return get_tlb_entry(address)->readhandler; -} -static INLINE PageHandler* get_tlb_writehandler(PhysPt address) { - return get_tlb_entry(address)->writehandler; -} - -/* Use these helper functions to access linear addresses in readX/writeX functions */ -static INLINE PhysPt PAGING_GetPhysicalPage(PhysPt linePage) { - tlb_entry *entry = get_tlb_entry(linePage); - return (entry->phys_page<<12); -} - -static INLINE PhysPt PAGING_GetPhysicalAddress(PhysPt linAddr) { - tlb_entry *entry = get_tlb_entry(linAddr); - return (entry->phys_page<<12)|(linAddr&0xfff); -} -#endif - -/* Special inlined memory reading/writing */ - -static INLINE Bit8u mem_readb_inline(PhysPt address) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) return host_readb(tlb_addr+address); - else return (Bit8u)(get_tlb_readhandler(address))->readb(address); -} - -static INLINE Bit16u mem_readw_inline(PhysPt address) { - if ((address & 0xfff)<0xfff) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) return host_readw(tlb_addr+address); - else return (Bit16u)(get_tlb_readhandler(address))->readw(address); - } else return mem_unalignedreadw(address); -} - -static INLINE Bit32u mem_readd_inline(PhysPt address) { - if ((address & 0xfff)<0xffd) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) return host_readd(tlb_addr+address); - else return (get_tlb_readhandler(address))->readd(address); - } else return mem_unalignedreadd(address); -} - -static INLINE void mem_writeb_inline(PhysPt address,Bit8u val) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) host_writeb(tlb_addr+address,val); - else (get_tlb_writehandler(address))->writeb(address,val); -} - -static INLINE void mem_writew_inline(PhysPt address,Bit16u val) { - if ((address & 0xfff)<0xfff) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) host_writew(tlb_addr+address,val); - else (get_tlb_writehandler(address))->writew(address,val); - } else mem_unalignedwritew(address,val); -} - -static INLINE void mem_writed_inline(PhysPt address,Bit32u val) { - if ((address & 0xfff)<0xffd) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) host_writed(tlb_addr+address,val); - else (get_tlb_writehandler(address))->writed(address,val); - } else mem_unalignedwrited(address,val); -} - - -static INLINE bool mem_readb_checked(PhysPt address, Bit8u * val) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) { - *val=host_readb(tlb_addr+address); - return false; - } else return (get_tlb_readhandler(address))->readb_checked(address, val); -} - -static INLINE bool mem_readw_checked(PhysPt address, Bit16u * val) { - if ((address & 0xfff)<0xfff) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) { - *val=host_readw(tlb_addr+address); - return false; - } else return (get_tlb_readhandler(address))->readw_checked(address, val); - } else return mem_unalignedreadw_checked(address, val); -} - -static INLINE bool mem_readd_checked(PhysPt address, Bit32u * val) { - if ((address & 0xfff)<0xffd) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) { - *val=host_readd(tlb_addr+address); - return false; - } else return (get_tlb_readhandler(address))->readd_checked(address, val); - } else return mem_unalignedreadd_checked(address, val); -} - -static INLINE bool mem_writeb_checked(PhysPt address,Bit8u val) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) { - host_writeb(tlb_addr+address,val); - return false; - } else return (get_tlb_writehandler(address))->writeb_checked(address,val); -} - -static INLINE bool mem_writew_checked(PhysPt address,Bit16u val) { - if ((address & 0xfff)<0xfff) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) { - host_writew(tlb_addr+address,val); - return false; - } else return (get_tlb_writehandler(address))->writew_checked(address,val); - } else return mem_unalignedwritew_checked(address,val); -} - -static INLINE bool mem_writed_checked(PhysPt address,Bit32u val) { - if ((address & 0xfff)<0xffd) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) { - host_writed(tlb_addr+address,val); - return false; - } else return (get_tlb_writehandler(address))->writed_checked(address,val); - } else return mem_unalignedwrited_checked(address,val); -} - - -#endif diff --git a/include/pic.h b/include/pic.h index 5021aa6..44a2f76 100644 --- a/include/pic.h +++ b/include/pic.h @@ -1,67 +1,44 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_PIC_H -#define DOSBOX_PIC_H - - -/* CPU Cycle Timing */ -extern Bit32s CPU_Cycles; -extern Bit32s CPU_CycleLeft; -extern Bit32s CPU_CycleMax; - -typedef void (PIC_EOIHandler) (void); -typedef void (* PIC_EventHandler)(Bitu val); - - -#define PIC_MAXIRQ 15 -#define PIC_NOIRQ 0xFF - -extern Bitu PIC_IRQCheck; -extern Bitu PIC_IRQActive; -extern Bitu PIC_Ticks; - -static INLINE float PIC_TickIndex(void) { - return (CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)/(float)CPU_CycleMax; -} - -static INLINE Bits PIC_TickIndexND(void) { - return CPU_CycleMax-CPU_CycleLeft-CPU_Cycles; -} - -static INLINE Bits PIC_MakeCycles(double amount) { - return (Bits)(CPU_CycleMax*amount); -} - -static INLINE double PIC_FullIndex(void) { - return PIC_Ticks+(double)PIC_TickIndex(); -} - -void PIC_ActivateIRQ(Bitu irq); -void PIC_DeActivateIRQ(Bitu irq); - -void PIC_runIRQs(void); -bool PIC_RunQueue(void); - -//Delay in milliseconds -void PIC_AddEvent(PIC_EventHandler handler,float delay,Bitu val=0); -void PIC_RemoveEvents(PIC_EventHandler handler); -void PIC_RemoveSpecificEvents(PIC_EventHandler handler, Bitu val); - -void PIC_SetIRQMask(Bitu irq, bool masked); -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PIC_H +#define __PIC_H + +typedef void (PIC_EOIHandler) (void); +typedef void (PIC_Function)(void); + +extern Bit32u PIC_IRQCheck; + +void PIC_ActivateIRQ(Bit32u irq); + +void PIC_DeActivateIRQ(Bit32u irq); + +void PIC_runIRQs(void); + +void PIC_RegisterIRQ(Bit32u irq,PIC_EOIHandler handler,char * name); +void PIC_FreeIRQ(Bit32u irq); + +bool PIC_IRQActive(Bit32u irq); + +/* A Queued function should never queue itself again this will go horribly wrong */ +void PIC_QueueFunction(PIC_Function * function); + + + +#endif + diff --git a/include/programs.h b/include/programs.h index 3be183f..d716510 100644 --- a/include/programs.h +++ b/include/programs.h @@ -1,90 +1,58 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: programs.h,v 1.18 2009/03/11 20:18:37 qbix79 Exp $ */ - -#ifndef DOSBOX_PROGRAMS_H -#define DOSBOX_PROGRAMS_H - -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif -#ifndef DOSBOX_DOS_INC_H -#include "dos_inc.h" -#endif - -#ifndef CH_LIST -#define CH_LIST -#include -#endif - -#ifndef CH_STRING -#define CH_STRING -#include -#endif - -class CommandLine { -public: - CommandLine(int argc,char const * const argv[]); - CommandLine(char const * const name,char const * const cmdline); - const char * GetFileName(){ return file_name.c_str();} - - bool FindExist(char const * const name,bool remove=false); - bool FindHex(char const * const name,int & value,bool remove=false); - bool FindInt(char const * const name,int & value,bool remove=false); - bool FindString(char const * const name,std::string & value,bool remove=false); - bool FindCommand(unsigned int which,std::string & value); - bool FindStringBegin(char const * const begin,std::string & value, bool remove=false); - bool FindStringRemain(char const * const name,std::string & value); - bool GetStringRemain(std::string & value); - unsigned int GetCount(void); - void Shift(unsigned int amount=1); - Bit16u Get_arglength(); - -private: - typedef std::list::iterator cmd_it; - std::list cmds; - std::string file_name; - bool FindEntry(char const * const name,cmd_it & it,bool neednext=false); -}; - -class Program { -public: - Program(); - virtual ~Program(){ - delete cmd; - delete psp; - } - std::string temp_line; - CommandLine * cmd; - DOS_PSP * psp; - virtual void Run(void)=0; - bool GetEnvStr(const char * entry,std::string & result); - bool GetEnvNum(Bitu num,std::string & result); - Bitu GetEnvCount(void); - bool SetEnv(const char * entry,const char * new_string); - void WriteOut(const char * format,...); /* Write to standard output */ - void WriteOut_NoParsing(const char * format); /* Write to standard output, no parsing */ - void ChangeToLongCmd(); - -}; - -typedef void (PROGRAMS_Main)(Program * * make); -void PROGRAMS_MakeFile(char const * const name,PROGRAMS_Main * main); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __PROGRAM_H +#define __PROGRAM_H +#include +#include + + +char * MSG_Get(char * msg); + +struct PROGRAM_Info { + Bit16u psp_seg; + PSP psp_copy; + char full_name[32]; //Enough space for programs only on the z:\ drive + char * cmd_line; +}; + +typedef void (PROGRAMS_Main)(PROGRAM_Info * info); +void PROGRAMS_MakeFile(char * name,PROGRAMS_Main * main); + +class Program { +public: + Program(PROGRAM_Info * program_info); + virtual void Run(void)=0; + char * GetEnvStr(char * env_entry); + char * GetEnvNum(Bit32u num); + Bit32u GetEnvCount(void); + bool SetEnv(char * env_entry,char * new_string); + void WriteOut(char * format,...); /* Write to standard output */ + PROGRAM_Info * prog_info; + +}; + +void SHELL_AddAutoexec(char * line,...); + + + + + + +#endif + diff --git a/include/regs.h b/include/regs.h index a6a2ea2..ec1778e 100644 --- a/include/regs.h +++ b/include/regs.h @@ -1,169 +1,117 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_REGS_H -#define DOSBOX_REGS_H - -#ifndef DOSBOX_MEM_H -#include "mem.h" -#endif - -#define FLAG_CF 0x00000001 -#define FLAG_PF 0x00000004 -#define FLAG_AF 0x00000010 -#define FLAG_ZF 0x00000040 -#define FLAG_SF 0x00000080 -#define FLAG_OF 0x00000800 - -#define FLAG_TF 0x00000100 -#define FLAG_IF 0x00000200 -#define FLAG_DF 0x00000400 - -#define FLAG_IOPL 0x00003000 -#define FLAG_NT 0x00004000 -#define FLAG_VM 0x00020000 -#define FLAG_AC 0x00040000 -#define FLAG_ID 0x00200000 - -#define FMASK_TEST (FLAG_CF | FLAG_PF | FLAG_AF | FLAG_ZF | FLAG_SF | FLAG_OF) -#define FMASK_NORMAL (FMASK_TEST | FLAG_DF | FLAG_TF | FLAG_IF | FLAG_AC ) -#define FMASK_ALL (FMASK_NORMAL | FLAG_IOPL | FLAG_NT) - -#define SETFLAGBIT(TYPE,TEST) if (TEST) reg_flags|=FLAG_ ## TYPE; else reg_flags&=~FLAG_ ## TYPE - -#define GETFLAG(TYPE) (reg_flags & FLAG_ ## TYPE) -#define GETFLAGBOOL(TYPE) ((reg_flags & FLAG_ ## TYPE) ? true : false ) - -#define GETFLAG_IOPL ((reg_flags & FLAG_IOPL) >> 12) - -struct Segment { - Bit16u val; - PhysPt phys; /* The phyiscal address start in emulated machine */ -}; - -enum SegNames { es=0,cs,ss,ds,fs,gs}; - -struct Segments { - Bitu val[8]; - PhysPt phys[8]; -}; - -union GenReg32 { - Bit32u dword[1]; - Bit16u word[2]; - Bit8u byte[4]; -}; - -#ifdef WORDS_BIGENDIAN - -#define DW_INDEX 0 -#define W_INDEX 1 -#define BH_INDEX 2 -#define BL_INDEX 3 - -#else - -#define DW_INDEX 0 -#define W_INDEX 0 -#define BH_INDEX 1 -#define BL_INDEX 0 - -#endif - -struct CPU_Regs { - GenReg32 regs[8],ip; - Bitu flags; -}; - -extern Segments Segs; -extern CPU_Regs cpu_regs; - -static INLINE PhysPt SegPhys(SegNames index) { - return Segs.phys[index]; -} - -static INLINE Bit16u SegValue(SegNames index) { - return (Bit16u)Segs.val[index]; -} - -static INLINE RealPt RealMakeSeg(SegNames index,Bit16u off) { - return RealMake(SegValue(index),off); -} - - -static INLINE void SegSet16(Bitu index,Bit16u val) { - Segs.val[index]=val; - Segs.phys[index]=val << 4; -} - -enum { - REGI_AX, REGI_CX, REGI_DX, REGI_BX, - REGI_SP, REGI_BP, REGI_SI, REGI_DI -}; - -enum { - REGI_AL, REGI_CL, REGI_DL, REGI_BL, - REGI_AH, REGI_CH, REGI_DH, REGI_BH -}; - - -//macros to convert a 3-bit register index to the correct register -#define reg_8l(reg) (cpu_regs.regs[(reg)].byte[BL_INDEX]) -#define reg_8h(reg) (cpu_regs.regs[(reg)].byte[BH_INDEX]) -#define reg_8(reg) ((reg) & 4 ? reg_8h((reg) & 3) : reg_8l((reg) & 3)) -#define reg_16(reg) (cpu_regs.regs[(reg)].word[W_INDEX]) -#define reg_32(reg) (cpu_regs.regs[(reg)].dword[DW_INDEX]) - -#define reg_al cpu_regs.regs[REGI_AX].byte[BL_INDEX] -#define reg_ah cpu_regs.regs[REGI_AX].byte[BH_INDEX] -#define reg_ax cpu_regs.regs[REGI_AX].word[W_INDEX] -#define reg_eax cpu_regs.regs[REGI_AX].dword[DW_INDEX] - -#define reg_bl cpu_regs.regs[REGI_BX].byte[BL_INDEX] -#define reg_bh cpu_regs.regs[REGI_BX].byte[BH_INDEX] -#define reg_bx cpu_regs.regs[REGI_BX].word[W_INDEX] -#define reg_ebx cpu_regs.regs[REGI_BX].dword[DW_INDEX] - -#define reg_cl cpu_regs.regs[REGI_CX].byte[BL_INDEX] -#define reg_ch cpu_regs.regs[REGI_CX].byte[BH_INDEX] -#define reg_cx cpu_regs.regs[REGI_CX].word[W_INDEX] -#define reg_ecx cpu_regs.regs[REGI_CX].dword[DW_INDEX] - -#define reg_dl cpu_regs.regs[REGI_DX].byte[BL_INDEX] -#define reg_dh cpu_regs.regs[REGI_DX].byte[BH_INDEX] -#define reg_dx cpu_regs.regs[REGI_DX].word[W_INDEX] -#define reg_edx cpu_regs.regs[REGI_DX].dword[DW_INDEX] - -#define reg_si cpu_regs.regs[REGI_SI].word[W_INDEX] -#define reg_esi cpu_regs.regs[REGI_SI].dword[DW_INDEX] - -#define reg_di cpu_regs.regs[REGI_DI].word[W_INDEX] -#define reg_edi cpu_regs.regs[REGI_DI].dword[DW_INDEX] - -#define reg_sp cpu_regs.regs[REGI_SP].word[W_INDEX] -#define reg_esp cpu_regs.regs[REGI_SP].dword[DW_INDEX] - -#define reg_bp cpu_regs.regs[REGI_BP].word[W_INDEX] -#define reg_ebp cpu_regs.regs[REGI_BP].dword[DW_INDEX] - -#define reg_ip cpu_regs.ip.word[W_INDEX] -#define reg_eip cpu_regs.ip.dword[DW_INDEX] - -#define reg_flags cpu_regs.flags - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if !defined __REGS_H +#define __REGS_H + +#include + +struct Flag_Info { + union { + Bit8u b; + Bit8u bs; + Bit16u w; + Bit16s ws; + Bit32u d; + Bit32s ds; + } var1,var2,result; + Bitu type; + Bitu prev_type; + bool cf,sf,pf,af,zf,of,df,tf,intf; + bool nt; + Bit8u io; + bool oldcf; +}; + + + +struct Segment { + Bit16u value; + bool special; /* Signal for pointing to special memory */ + HostOff host; /* The address of start in host memory */ + PhysOff phys; /* The phyiscal address start in emulated machine */ +}; + + + + +enum { cs=0,ds,es,fs,gs,ss}; + +extern Segment Segs[6]; +extern Flag_Info flags; +//extern Regs regs; + +void SetSegment_16(Bit32u seg,Bit16u val); + + +struct CPU_Regs { + union { + Bit32u d; + Bit16u w; + struct { + Bit8u l,h; + }b; + } ax,bx,cx,dx,si,di,sp,bp,ip; +}; + +extern CPU_Regs cpu_regs; + +#define reg_al cpu_regs.ax.b.l + +//extern Bit8u & reg_al=cpu_regs.ax.b.l; + +#define reg_ah cpu_regs.ax.b.h +#define reg_ax cpu_regs.ax.w +#define reg_eax cpu_regs.ax.d + +#define reg_bl cpu_regs.bx.b.l +#define reg_bh cpu_regs.bx.b.h +#define reg_bx cpu_regs.bx.w +#define reg_ebx cpu_regs.bx.d + +#define reg_cl cpu_regs.cx.b.l +#define reg_ch cpu_regs.cx.b.h +#define reg_cx cpu_regs.cx.w +#define reg_ecx cpu_regs.cx.d + +#define reg_dl cpu_regs.dx.b.l +#define reg_dh cpu_regs.dx.b.h +#define reg_dx cpu_regs.dx.w +#define reg_edx cpu_regs.dx.d + +#define reg_si cpu_regs.si.w +#define reg_esi cpu_regs.si.d + +#define reg_di cpu_regs.di.w +#define reg_edi cpu_regs.di.d + +#define reg_sp cpu_regs.sp.w +#define reg_esp cpu_regs.sp.d + +#define reg_bp cpu_regs.bp.w +#define reg_ebp cpu_regs.bp.d + +#define reg_ip cpu_regs.ip.w +#define reg_eip cpu_regs.ip.d + + + + + +#endif + diff --git a/include/render.h b/include/render.h index 94af7bb..74b8aa1 100644 --- a/include/render.h +++ b/include/render.h @@ -1,98 +1,25 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_RENDER_H -#define DOSBOX_RENDER_H - -// 0: complex scalers off, scaler cache off, some simple scalers off, memory requirements reduced -// 1: complex scalers off, scaler cache off, all simple scalers on -// 2: complex scalers off, scaler cache on -// 3: complex scalers on -#define RENDER_USE_ADVANCED_SCALERS 3 - -#include "../src/gui/render_scalers.h" - -#define RENDER_SKIP_CACHE 16 -//Enable this for scalers to support 0 input for empty lines -//#define RENDER_NULL_INPUT - -typedef struct { - struct { - Bit8u red; - Bit8u green; - Bit8u blue; - Bit8u unused; - } rgb[256]; - union { - Bit16u b16[256]; - Bit32u b32[256]; - } lut; - bool changed; - Bit8u modified[256]; - Bitu first; - Bitu last; -} RenderPal_t; - -typedef struct { - struct { - Bitu width, start; - Bitu height; - Bitu bpp; - bool dblw,dblh; - double ratio; - float fps; - } src; - struct { - Bitu count; - Bitu max; - Bitu index; - Bit8u hadSkip[RENDER_SKIP_CACHE]; - } frameskip; - struct { - Bitu size; - scalerMode_t inMode; - scalerMode_t outMode; - scalerOperation_t op; - bool clearCache; - bool forced; - ScalerLineHandler_t lineHandler; - ScalerLineHandler_t linePalHandler; - ScalerComplexHandler_t complexHandler; - Bitu blocks, lastBlock; - Bitu outPitch; - Bit8u *outWrite; - Bitu cachePitch; - Bit8u *cacheRead; - Bitu inHeight, inLine, outLine; - } scale; - RenderPal_t pal; - bool updating; - bool active; - bool aspect; - bool fullFrame; -} Render_t; - -extern Render_t render; -extern ScalerLineHandler_t RENDER_DrawLine; -void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double ratio,bool dblw,bool dblh); -bool RENDER_StartUpdate(void); -void RENDER_EndUpdate( ); -void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue); - - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +typedef void RENDER_Handler(Bit8u * * data); + + +void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags, RENDER_Handler * handler); + +void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue); diff --git a/include/serialport.h b/include/serialport.h deleted file mode 100644 index 0b2ef48..0000000 --- a/include/serialport.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: serialport.h,v 1.16 2009/02/01 14:11:45 qbix79 Exp $ */ - -#ifndef DOSBOX_SERIALPORT_H -#define DOSBOX_SERIALPORT_H - -#define SERIAL_DEBUG 0 - -// Uncomment this for a lot of debug messages: -//#define LOG_UART - -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif -#ifndef DOSBOX_INOUT_H -#include "inout.h" -#endif -#ifndef DOSBOX_TIMER_H -#include "timer.h" -#endif -#ifndef DOSBOX_DOS_INC_H -#include "dos_inc.h" -#endif -#ifndef DOSBOX_PROGRAMS_H -#include "programs.h" -#endif - -#if SERIAL_DEBUG -#include "hardware.h" -#endif - -// Serial port interface - -class CSerial { -public: - -#if SERIAL_DEBUG - FILE * debugfp; - bool dbg_modemcontrol; // RTS,CTS,DTR,DSR,RI,CD - bool dbg_serialtraffic; - bool dbg_register; - bool dbg_interrupt; - bool dbg_aux; - -#endif - - static bool getBituSubstring(const char* name,Bitu* data, CommandLine* cmd); - - bool InstallationSuccessful;// check after constructing. If - // something was wrong, delete it right away. - - // Constructor takes com port number (0-3) - CSerial(Bitu id, CommandLine* cmd); - - virtual ~CSerial(); - - IO_ReadHandleObject ReadHandler[8]; - IO_WriteHandleObject WriteHandler[8]; - - float bytetime; // how long a byte takes to transmit/receive in milliseconds - void changeLineProperties(); - Bitu idnumber; - - void setEvent(Bit16u type, float duration); - void removeEvent(Bit16u type); - void handleEvent(Bit16u type); - virtual void handleUpperEvent(Bit16u type)=0; - - // defines for event type -#define SERIAL_TX_LOOPBACK_EVENT 0 -#define SERIAL_THR_LOOPBACK_EVENT 1 -#define SERIAL_ERRMSG_EVENT 2 - -#define SERIAL_TX_EVENT 3 -#define SERIAL_RX_EVENT 4 -#define SERIAL_POLLING_EVENT 5 -#define SERIAL_THR_EVENT 6 - -#define SERIAL_BASE_EVENT_COUNT 6 - -#define COMNUMBER idnumber+1 - - Bitu irq; - - // CSerial requests an update of the input lines - virtual void updateMSR()=0; - - // Control lines from prepherial to serial port - bool getDTR(); - bool getRTS(); - - bool getRI(); - bool getCD(); - bool getDSR(); - bool getCTS(); - - void setRI(bool value); - void setDSR(bool value); - void setCD(bool value); - void setCTS(bool value); - - // From serial port to prepherial - // set output lines - virtual void setRTSDTR(bool rts, bool dtr)=0; - virtual void setRTS(bool val)=0; - virtual void setDTR(bool val)=0; - - // Register access - void Write_THR(Bit8u data); - void Write_IER(Bit8u data); - void Write_FCR(Bit8u data); - void Write_LCR(Bit8u data); - void Write_MCR(Bit8u data); - // Really old hardware seems to have the delta part of this register writable - void Write_MSR(Bit8u data); - void Write_SPR(Bit8u data); - void Write_reserved(Bit8u data, Bit8u address); - - Bitu Read_RHR(); - Bitu Read_IER(); - Bitu Read_ISR(); - Bitu Read_LCR(); - Bitu Read_MCR(); - Bitu Read_LSR(); - Bitu Read_MSR(); - Bitu Read_SPR(); - - // If a byte comes from loopback or prepherial, put it in here. - void receiveByte(Bit8u data); - - // If an error was received, put it here (in LSR register format) - void receiveError(Bit8u errorword); - - // depratched - // connected device checks, if port can receive data: - bool CanReceiveByte(); - - // when THR was shifted to TX - void ByteTransmitting(); - - // When done sending, notify here - void ByteTransmitted(); - - // Transmit byte to prepherial - virtual void transmitByte(Bit8u val, bool first)=0; - - // switch break state to the passed value - virtual void setBreak(bool value)=0; - - // change baudrate, number of bits, parity, word length al at once - virtual void updatePortConfig(Bit16u divider, Bit8u lcr)=0; - - void Init_Registers(); - - bool Putchar(Bit8u data, bool wait_dtr, bool wait_rts, Bitu timeout); - bool Getchar(Bit8u* data, Bit8u* lsr, bool wait_dsr, Bitu timeout); - - -private: - - DOS_Device* mydosdevice; - - // I used this spec: http://www.exar.com/products/st16c450v420.pdf - - void ComputeInterrupts(); - - // a sub-interrupt is triggered - void rise(Bit8u priority); - - // clears the pending sub-interrupt - void clear(Bit8u priority); - - #define ERROR_PRIORITY 4 // overrun, parity error, frame error, break - #define RX_PRIORITY 1 // a byte has been received - #define TX_PRIORITY 2 // tx buffer has become empty - #define MSR_PRIORITY 8 // CRS, DSR, RI, DCD change - #define NONE_PRIORITY 0 - - Bit8u waiting_interrupts; // these are on, but maybe not enabled - - // 16C450 (no FIFO) - // read/write name - - Bit16u baud_divider; - Bit8u RHR; // r Receive Holding Register, also LSB of Divisor Latch (r/w) - #define RHR_OFFSET 0 - // Data: whole byte - - Bit8u THR; // w Transmit Holding Register - #define THR_OFFSET 0 - // Data: whole byte - - Bit8u IER; // r/w Interrupt Enable Register, also MSB of Divisor Latch - #define IER_OFFSET 1 - - bool irq_active; - - #define RHR_INT_Enable_MASK 0x1 - #define THR_INT_Enable_MASK 0x2 - #define Receive_Line_INT_Enable_MASK 0x4 - #define Modem_Status_INT_Enable_MASK 0x8 - - Bit8u ISR; // r Interrupt Status Register - #define ISR_OFFSET 2 - - #define ISR_CLEAR_VAL 0x1 - #define ISR_ERROR_VAL 0x6 - #define ISR_RX_VAL 0x4 - #define ISR_TX_VAL 0x2 - #define ISR_MSR_VAL 0x0 -public: - Bit8u LCR; // r/w Line Control Register -private: - #define LCR_OFFSET 3 - // bit0: word length bit0 - // bit1: word length bit1 - // bit2: stop bits - // bit3: parity enable - // bit4: even parity - // bit5: set parity - // bit6: set break - // bit7: divisor latch enable - - - #define LCR_BREAK_MASK 0x40 - #define LCR_DIVISOR_Enable_MASK 0x80 - #define LCR_PORTCONFIG_MASK 0x3F - - #define LCR_PARITY_NONE 0x0 - #define LCR_PARITY_ODD 0x8 - #define LCR_PARITY_EVEN 0x18 - #define LCR_PARITY_MARK 0x28 - #define LCR_PARITY_SPACE 0x38 - - #define LCR_DATABITS_5 0x0 - #define LCR_DATABITS_6 0x1 - #define LCR_DATABITS_7 0x2 - #define LCR_DATABITS_8 0x3 - - #define LCR_STOPBITS_1 0x0 - #define LCR_STOPBITS_MORE_THAN_1 0x4 - - // Modem Control Register - // r/w - #define MCR_OFFSET 4 - bool dtr; // bit0: DTR - bool rts; // bit1: RTS - bool op1; // bit2: OP1 - bool op2; // bit3: OP2 - bool loopback; // bit4: loop back enable - - #define MCR_DTR_MASK 0x1 - #define MCR_RTS_MASK 0x2 - #define MCR_OP1_MASK 0x4 - #define MCR_OP2_MASK 0x8 - #define MCR_LOOPBACK_Enable_MASK 0x10 -public: - Bit8u LSR; // r Line Status Register -private: - - #define LSR_OFFSET 5 - - #define LSR_RX_DATA_READY_MASK 0x1 - #define LSR_OVERRUN_ERROR_MASK 0x2 - #define LSR_PARITY_ERROR_MASK 0x4 - #define LSR_FRAMING_ERROR_MASK 0x8 - #define LSR_RX_BREAK_MASK 0x10 - #define LSR_TX_HOLDING_EMPTY_MASK 0x20 - #define LSR_TX_EMPTY_MASK 0x40 - - #define LSR_ERROR_MASK 0x1e - - // error printing - bool errormsg_pending; - Bitu framingErrors; - Bitu parityErrors; - Bitu overrunErrors; - Bitu overrunIF0; - Bitu breakErrors; - - - // Modem Status Register - // r - #define MSR_OFFSET 6 - bool d_cts; // bit0: deltaCTS - bool d_dsr; // bit1: deltaDSR - bool d_ri; // bit2: deltaRI - bool d_cd; // bit3: deltaCD - bool cts; // bit4: CTS - bool dsr; // bit5: DSR - bool ri; // bit6: RI - bool cd; // bit7: CD - - #define MSR_delta_MASK 0xf - #define MSR_LINE_MASK 0xf0 - - #define MSR_dCTS_MASK 0x1 - #define MSR_dDSR_MASK 0x2 - #define MSR_dRI_MASK 0x4 - #define MSR_dCD_MASK 0x8 - #define MSR_CTS_MASK 0x10 - #define MSR_DSR_MASK 0x20 - #define MSR_RI_MASK 0x40 - #define MSR_CD_MASK 0x80 - - Bit8u SPR; // r/w Scratchpad Register - #define SPR_OFFSET 7 - - - // For loopback purposes... - Bit8u loopback_data; - void transmitLoopbackByte(Bit8u val, bool value); - - // 16C550 (FIFO) - // TODO - #define FCR_OFFSET 2 - bool fifo_warn; - //Bit8u FCR; // FIFO Control Register - -}; - -extern CSerial* serialports[]; -const Bit8u serial_defaultirq[4] = { 4, 3, 4, 3 }; -const Bit16u serial_baseaddr[4] = {0x3f8,0x2f8,0x3e8,0x2e8}; -const char* const serial_comname[]={"COM1","COM2","COM3","COM4"}; - -// the COM devices - -class device_COM : public DOS_Device { -public: - // Creates a COM device that communicates with the num-th parallel port, i.e. is LPTnum - device_COM(class CSerial* sc); - ~device_COM(); - bool Read(Bit8u * data,Bit16u * size); - bool Write(Bit8u * data,Bit16u * size); - bool Seek(Bit32u * pos,Bit32u type); - bool Close(); - Bit16u GetInformation(void); -private: - CSerial* sclass; -}; - -#endif - diff --git a/include/setup.h b/include/setup.h index fd3352d..ec82011 100644 --- a/include/setup.h +++ b/include/setup.h @@ -1,331 +1,43 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: setup.h,v 1.40 2009/02/15 20:01:08 qbix79 Exp $ */ - -#ifndef DOSBOX_SETUP_H -#define DOSBOX_SETUP_H - -#ifdef _MSC_VER -#pragma warning ( disable : 4786 ) -#pragma warning ( disable : 4290 ) -#endif - - -#ifndef CH_LIST -#define CH_LIST -#include -#endif - -#ifndef CH_VECTOR -#define CH_VECTOR -#include -#endif - -#ifndef CH_STRING -#define CH_STRING -#include -#endif - - -class Hex { -private: - int _hex; -public: - Hex(int in):_hex(in) { }; - Hex():_hex(0) { }; - bool operator==(Hex const& other) {return _hex == other._hex;} - operator int () const { return _hex; } - -}; - -class Value { -/* - * Multitype storage container that is aware of the currently stored type in it. - * Value st = "hello"; - * Value in = 1; - * st = 12 //Exception - * in = 12 //works - */ -private: - Hex _hex; - bool _bool; - int _int; - std::string* _string; - double _double; -public: - class WrongType { }; // Conversion error class - enum Etype { V_NONE, V_HEX, V_BOOL, V_INT, V_STRING, V_DOUBLE,V_CURRENT} type; - - /* Constructors */ - Value() :_string(0), type(V_NONE) { }; - Value(Hex in) :_hex(in), type(V_HEX) { }; - Value(int in) :_int(in), type(V_INT) { }; - Value(bool in) :_bool(in), type(V_BOOL) { }; - Value(double in) :_double(in), type(V_DOUBLE) { }; - Value(std::string const& in) :_string(new std::string(in)),type(V_STRING) { }; - Value(char const * const in) :_string(new std::string(in)),type(V_STRING) { }; - Value(Value const& in):_string(0) {plaincopy(in);} - ~Value() { destroy();}; - Value(std::string const& in,Etype _t) :_string(0),type(V_NONE) {SetValue(in,_t);} - - /* Assigment operators */ - Value& operator= (Hex in) throw(WrongType) { return copy(Value(in));} - Value& operator= (int in) throw(WrongType) { return copy(Value(in));} - Value& operator= (bool in) throw(WrongType) { return copy(Value(in));} - Value& operator= (double in) throw(WrongType) { return copy(Value(in));} - Value& operator= (std::string const& in) throw(WrongType) { return copy(Value(in));} - Value& operator= (char const * const in) throw(WrongType) { return copy(Value(in));} - Value& operator= (Value const& in) throw(WrongType) { return copy(Value(in));} - - bool operator== (Value const & other); - operator bool () const throw(WrongType); - operator Hex () const throw(WrongType); - operator int () const throw(WrongType); - operator double () const throw(WrongType); - operator char const* () const throw(WrongType); - void SetValue(std::string const& in,Etype _type = V_CURRENT) throw(WrongType); - std::string ToString() const; - -private: - void destroy() throw(); - Value& copy(Value const& in) throw(WrongType); - void plaincopy(Value const& in) throw(); - void set_hex(std::string const& in); - void set_int(std::string const&in); - void set_bool(std::string const& in); - void set_string(std::string const& in); - void set_double(std::string const& in); -}; - -class Property { -public: - struct Changeable { enum Value {Always, WhenIdle,OnlyAtStart};}; - const std::string propname; - - Property(std::string const& _propname, Changeable::Value when):propname(_propname),change(when) { } - void Set_values(const char * const * in); - void Set_help(std::string const& str); - char const* Get_help(); - virtual void SetValue(std::string const& str)=0; - Value const& GetValue() const { return value;} - Value const& Get_Default_Value() const { return default_value; } - //CheckValue returns true if value is in suggested_values; - //Type specific properties are encouraged to override this and check for type - //specific features. - virtual bool CheckValue(Value const& in, bool warn); - //Set interval value to in or default if in is invalid. force always sets the value. - void SetVal(Value const& in, bool forced,bool warn=true) {if(forced || CheckValue(in,warn)) value = in; else value = default_value;} - virtual ~Property(){ } - virtual const std::vector& GetValues() const; - Value::Etype Get_type(){return default_value.type;} - -protected: - Value value; - std::vector suggested_values; - typedef std::vector::iterator iter; - Value default_value; - const Changeable::Value change; -}; - -class Prop_int:public Property { -public: - Prop_int(std::string const& _propname,Changeable::Value when, int _value) - :Property(_propname,when) { - default_value = value = _value; - min = max = -1; - } - Prop_int(std::string const& _propname,Changeable::Value when, int _min,int _max,int _value) - :Property(_propname,when) { - default_value = value = _value; - min = _min; - max = _max; - } - void SetMinMax(Value const& min,Value const& max) {this->min = min; this->max=max;} - void SetValue(std::string const& in); - ~Prop_int(){ } - virtual bool CheckValue(Value const& in, bool warn); -private: - Value min,max; -}; - -class Prop_double:public Property { -public: - Prop_double(std::string const & _propname, Changeable::Value when, double _value) - :Property(_propname,when){ - default_value = value = _value; - } - void SetValue(std::string const& input); - ~Prop_double(){ } -}; - -class Prop_bool:public Property { -public: - Prop_bool(std::string const& _propname, Changeable::Value when, bool _value) - :Property(_propname,when) { - default_value = value = _value; - } - void SetValue(std::string const& in); - ~Prop_bool(){ } -}; - -class Prop_string:public Property{ -public: - Prop_string(std::string const& _propname, Changeable::Value when, char const * const _value) - :Property(_propname,when) { - default_value = value = _value; - } - void SetValue(std::string const& in); - virtual bool CheckValue(Value const& in, bool warn); - ~Prop_string(){ } -}; -class Prop_path:public Prop_string{ -public: - std::string realpath; - Prop_path(std::string const& _propname, Changeable::Value when, char const * const _value) - :Prop_string(_propname,when,_value) { - default_value = value = _value; - realpath = _value; - } - void SetValue(std::string const& in); - ~Prop_path(){ } -}; - -class Prop_hex:public Property { -public: - Prop_hex(std::string const& _propname, Changeable::Value when, Hex _value) - :Property(_propname,when) { - default_value = value = _value; - } - void SetValue(std::string const& in); - ~Prop_hex(){ } -}; - -#define NO_SUCH_PROPERTY "PROP_NOT_EXIST" -class Section { -private: - typedef void (*SectionFunction)(Section*); - /* Wrapper class around startup and shutdown functions. the variable - * canchange indicates it can be called on configuration changes */ - struct Function_wrapper { - SectionFunction function; - bool canchange; - Function_wrapper(SectionFunction const _fun,bool _ch){ - function=_fun; - canchange=_ch; - } - }; - std::list initfunctions; - std::list destroyfunctions; - std::string sectionname; -public: - Section(std::string const& _sectionname):sectionname(_sectionname) { } - - void AddInitFunction(SectionFunction func,bool canchange=false); - void AddDestroyFunction(SectionFunction func,bool canchange=false); - void ExecuteInit(bool initall=true); - void ExecuteDestroy(bool destroyall=true); - const char* GetName() const {return sectionname.c_str();} - - virtual std::string GetPropValue(std::string const& _property) const =0; - virtual void HandleInputline(std::string const& _line)=0; - virtual void PrintData(FILE* outfile) const =0; - virtual ~Section() { /*Children must call executedestroy ! */} -}; - -class Prop_multival; -class Prop_multival_remain; -class Section_prop:public Section { -private: - std::list properties; - typedef std::list::iterator it; - typedef std::list::const_iterator const_it; - -public: - Section_prop(std::string const& _sectionname):Section(_sectionname){} - Prop_int* Add_int(std::string const& _propname, Property::Changeable::Value when, int _value=0); - Prop_string* Add_string(std::string const& _propname, Property::Changeable::Value when, char const * const _value=NULL); - Prop_path* Add_path(std::string const& _propname, Property::Changeable::Value when, char const * const _value=NULL); - Prop_bool* Add_bool(std::string const& _propname, Property::Changeable::Value when, bool _value=false); - Prop_hex* Add_hex(std::string const& _propname, Property::Changeable::Value when, Hex _value=0); -// void Add_double(char const * const _propname, double _value=0.0); - Prop_multival *Add_multi(std::string const& _propname, Property::Changeable::Value when,std::string const& sep); - Prop_multival_remain *Add_multiremain(std::string const& _propname, Property::Changeable::Value when,std::string const& sep); - - Property* Get_prop(int index); - int Get_int(std::string const& _propname) const; - const char* Get_string(std::string const& _propname) const; - bool Get_bool(std::string const& _propname) const; - Hex Get_hex(std::string const& _propname) const; - double Get_double(std::string const& _propname) const; - Prop_path* Get_path(std::string const& _propname) const; - Prop_multival* Get_multival(std::string const& _propname) const; - Prop_multival_remain* Get_multivalremain(std::string const& _propname) const; - void HandleInputline(std::string const& gegevens); - void PrintData(FILE* outfile) const; - virtual std::string GetPropValue(std::string const& _property) const; - //ExecuteDestroy should be here else the destroy functions use destroyed properties - virtual ~Section_prop(); -}; - -class Prop_multival:public Property{ -protected: - Section_prop* section; - std::string seperator; - void make_default_value(); -public: - Prop_multival(std::string const& _propname, Changeable::Value when,std::string const& sep):Property(_propname,when), section(new Section_prop("")),seperator(sep) { - default_value = value = ""; - } - Section_prop *GetSection() { return section; } - const Section_prop *GetSection() const { return section; } - virtual void SetValue(std::string const& input); - virtual const std::vector& GetValues() const; - ~Prop_multival() { delete section; } -}; //value bevat totale string. setvalue zet elk van de sub properties en checked die. - -class Prop_multival_remain:public Prop_multival{ -public: - Prop_multival_remain(std::string const& _propname, Changeable::Value when,std::string const& sep):Prop_multival(_propname,when,sep){ } - - virtual void SetValue(std::string const& input); -}; - - -class Section_line: public Section{ -public: - Section_line(std::string const& _sectionname):Section(_sectionname){} - ~Section_line(){ExecuteDestroy(true);} - void HandleInputline(std::string const& gegevens); - void PrintData(FILE* outfile) const; - virtual std::string GetPropValue(std::string const& _property) const; - std::string data; -}; - -class Module_base { - /* Base for all hardware and software "devices" */ -protected: - Section* m_configuration; -public: - Module_base(Section* configuration){m_configuration=configuration;}; -// Module_base(Section* configuration, SaveState* state) {}; - virtual ~Module_base(){/*LOG_MSG("executed")*/;};//Destructors are required - /* Returns true if succesful.*/ - virtual bool Change_Config(Section* /*newconfig*/) {return false;} ; -}; -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _SETUP_H_ +#define _SETUP_H_ + +#include +enum { S_STRING,S_HEX,S_INT,S_BOOL}; + +typedef char *(String_Handler)(char * input); +typedef char *(Hex_Handler)(Bitu * input); +typedef char *(Int_Handler)(Bits * input); +typedef char *(Bool_Handler)(bool input); + +class Setup { + + +private: + int argc; + char * * argv; + +}; + + + +extern char dosbox_basedir[CROSS_LEN]; + +#endif diff --git a/include/shell.h b/include/shell.h deleted file mode 100644 index 7edc944..0000000 --- a/include/shell.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: shell.h,v 1.26 2009/03/23 10:55:35 qbix79 Exp $ */ - -#ifndef DOSBOX_SHELL_H -#define DOSBOX_SHELL_H - -#include -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif -#ifndef DOSBOX_PROGRAMS_H -#include "programs.h" -#endif - -#include -#include - -#define CMD_MAXLINE 4096 -#define CMD_MAXCMDS 20 -#define CMD_OLDSIZE 4096 -extern Bitu call_shellstop; -/* first_shell is used to add and delete stuff from the shell env - * by "external" programs. (config) */ -extern Program * first_shell; - -class DOS_Shell; - -class BatchFile { -public: - BatchFile(DOS_Shell * host,char const* const name, char const * const cmd_line); - virtual ~BatchFile(); - virtual bool ReadLine(char * line); - bool Goto(char * where); - void Shift(void); - Bit16u file_handle; - Bit32u location; - bool echo; - DOS_Shell * shell; - BatchFile * prev; - CommandLine * cmd; -}; - -class AutoexecEditor; -class DOS_Shell : public Program { -private: - friend class AutoexecEditor; - std::list l_history, l_completion; - - char *completion_start; - Bit16u completion_index; - -public: - - DOS_Shell(); - - void Run(void); - void RunInternal(void); //for command /C -/* A load of subfunctions */ - void ParseLine(char * line); - Bitu GetRedirection(char *s, char **ifn, char **ofn,bool * append); - void InputCommand(char * line); - void ShowPrompt(); - void DoCommand(char * cmd); - bool Execute(char * name,char * args); - /* Checks if it matches a hardware-property */ - bool CheckConfig(char* cmd_in,char*line); -/* Some internal used functions */ - char * Which(char * name); -/* Some supported commands */ - void CMD_HELP(char * args); - void CMD_CLS(char * args); - void CMD_COPY(char * args); - void CMD_DIR(char * args); - void CMD_DELETE(char * args); - void CMD_ECHO(char * args); - void CMD_EXIT(char * args); - void CMD_MKDIR(char * args); - void CMD_CHDIR(char * args); - void CMD_RMDIR(char * args); - void CMD_SET(char * args); - void CMD_IF(char * args); - void CMD_GOTO(char * args); - void CMD_TYPE(char * args); - void CMD_REM(char * args); - void CMD_RENAME(char * args); - void CMD_CALL(char * args); - void SyntaxError(void); - void CMD_PAUSE(char * args); - void CMD_SUBST(char* args); - void CMD_LOADHIGH(char* args); - void CMD_CHOICE(char * args); - void CMD_ATTRIB(char * args); - void CMD_PATH(char * args); - void CMD_SHIFT(char * args); - void CMD_VER(char * args); - /* The shell's variables */ - Bit16u input_handle; - BatchFile * bf; - bool echo; - bool exit; - bool call; -}; - -struct SHELL_Cmd { - const char * name; /* Command name*/ - Bit32u flags; /* Flags about the command */ - void (DOS_Shell::*handler)(char * args); /* Handler for this command */ - const char * help; /* String with command help */ -}; - -/* Object to manage lines in the autoexec.bat The lines get removed from - * the file if the object gets destroyed. The environment is updated - * as well if the line set a a variable */ -class AutoexecObject{ -private: - bool installed; - std::string buf; -public: - AutoexecObject():installed(false){ }; - void Install(std::string const &in); - void InstallBefore(std::string const &in); - ~AutoexecObject(); -private: - void CreateAutoexec(void); -}; - -#endif diff --git a/include/support.h b/include/support.h index e0b913f..00079ee 100644 --- a/include/support.h +++ b/include/support.h @@ -1,60 +1,63 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: support.h,v 1.17 2009/04/25 16:25:03 harekiet Exp $ */ - -#ifndef DOSBOX_SUPPORT_H -#define DOSBOX_SUPPORT_H - -#include -#include -#include -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif - -#if defined (_MSC_VER) /* MS Visual C++ */ -#define strcasecmp(a,b) stricmp(a,b) -#define strncasecmp(a,b,n) _strnicmp(a,b,n) -#endif - -#define safe_strncpy(a,b,n) do { strncpy((a),(b),(n)-1); (a)[(n)-1] = 0; } while (0) - -#ifdef HAVE_STRINGS_H -#include -#endif - -void strreplace(char * str,char o,char n); -char *ltrim(char *str); -char *rtrim(char *str); -char *trim(char * str); -char * upcase(char * str); -char * lowcase(char * str); - -bool ScanCMDBool(char * cmd,char const * const check); -char * ScanCMDRemain(char * cmd); -char * StripWord(char *&cmd); -bool IsDecWord(char * word); -bool IsHexWord(char * word); -Bits ConvDecWord(char * word); -Bits ConvHexWord(char * word); - -void upcase(std::string &str); -void lowcase(std::string &str); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if !defined __SUPPORT_H +#define __SUPPORT_H + + +#include +#include +#include + +#if defined (_MSC_VER) /* MS Visual C++ */ +#define strcasecmp(a,b) stricmp(a,b) +#define strncasecmp(a,b,n) _strnicmp(a,b,n) +// if (stricmp(name,devices[index]->name)==0) return index; +#else +//if (strcasecmp(name,devices[index]->name)==0) return index; +//#define nocasestrcmp(a,b) stricmp(a,b) +#endif + + +void strreplace(char * str,char o,char n); +char *ltrim(char *str); +void rtrim(char * const str); +char *trim(char *str); + +bool wildcmp(char *wild, char *string); + +bool ScanCMDBool(char * cmd,char * check); +char * ScanCMDRemain(char * cmd); +bool ScanCMDHex(char * cmd,char * check,Bits * result); +char * StripWord(char * cmd); + +INLINE char * upcase(char * str) { + char * oldstr=str; + while (*str) *str++=toupper(*str); + return oldstr; +} + +INLINE char * lowcase(char * str) { + char * oldstr=str; + while (*str) *str++=tolower(*str); + return oldstr; +} + + +#endif + diff --git a/include/timer.h b/include/timer.h index 556778a..a481d59 100644 --- a/include/timer.h +++ b/include/timer.h @@ -1,38 +1,53 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef DOSBOX_TIMER_H -#define DOSBOX_TIMER_H - -/* underlying clock rate in HZ */ -#include - -#define PIT_TICK_RATE 1193182 - -#define GetTicks() SDL_GetTicks() - -typedef void (*TIMER_TickHandler)(void); - -/* Register a function that gets called everytime if 1 or more ticks pass */ -void TIMER_AddTickHandler(TIMER_TickHandler handler); -void TIMER_DelTickHandler(TIMER_TickHandler handler); - -/* This will add 1 milliscond to all timers */ -void TIMER_AddTick(void); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _TIMER_H_ +#define _TIMER_H_ +/* underlying clock rate in HZ */ +#include + +extern Bit32u LastTicks; +#define GetTicks() SDL_GetTicks() + +typedef void (*TIMER_TickHandler)(Bitu ticks); +typedef void (*TIMER_MicroHandler)(void); +typedef void (*TIMER_DelayHandler)(void); + +typedef void TIMER_Block; + + +/* Register a function that gets called everytime if 1 or more ticks pass */ +TIMER_Block * TIMER_RegisterTickHandler(TIMER_TickHandler handler); +/* Register a function to be called every x microseconds */ +TIMER_Block * TIMER_RegisterMicroHandler(TIMER_MicroHandler handler,Bitu micro); +/* Register a function to be called once after x microseconds */ +TIMER_Block * TIMER_RegisterDelayHandler(TIMER_DelayHandler handler,Bitu delay); + +/* Set the microseconds value to a new value */ +void TIMER_SetNewMicro(TIMER_Block * block,Bitu micro); + + +/* This function should be called very often to support very high res timers + Although with the new timer code it doesn't matter that much */ +void TIMER_CheckPIT(void); +/* This will add ms ticks to support the timer handlers */ +void TIMER_AddTicks(Bit32u ticks); + + +#endif + diff --git a/include/vga.h b/include/vga.h deleted file mode 100644 index 0992688..0000000 --- a/include/vga.h +++ /dev/null @@ -1,509 +0,0 @@ - /* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga.h,v 1.46 2009/03/15 11:28:34 c2woody Exp $ */ - -#ifndef DOSBOX_VGA_H -#define DOSBOX_VGA_H - -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif - -//Don't enable keeping changes and mapping lfb probably... -#define VGA_LFB_MAPPED -//#define VGA_KEEP_CHANGES -#define VGA_CHANGE_SHIFT 9 - -class PageHandler; - - -enum VGAModes { - M_CGA2, M_CGA4, - M_EGA, M_VGA, - M_LIN4, M_LIN8, M_LIN15, M_LIN16, M_LIN32, - M_TEXT, - M_HERC_GFX, M_HERC_TEXT, - M_CGA16, M_TANDY2, M_TANDY4, M_TANDY16, M_TANDY_TEXT, - M_ERROR -}; - - -#define CLK_25 25175 -#define CLK_28 28322 - -#define MIN_VCO 180000 -#define MAX_VCO 360000 - -#define S3_CLOCK_REF 14318 /* KHz */ -#define S3_CLOCK(_M,_N,_R) ((S3_CLOCK_REF * ((_M) + 2)) / (((_N) + 2) * (1 << (_R)))) -#define S3_MAX_CLOCK 150000 /* KHz */ - -#define S3_XGA_1024 0x00 -#define S3_XGA_1152 0x01 -#define S3_XGA_640 0x40 -#define S3_XGA_800 0x80 -#define S3_XGA_1280 0xc0 -#define S3_XGA_WMASK (S3_XGA_640|S3_XGA_800|S3_XGA_1024|S3_XGA_1152|S3_XGA_1280) - -#define S3_XGA_8BPP 0x00 -#define S3_XGA_16BPP 0x10 -#define S3_XGA_32BPP 0x30 -#define S3_XGA_CMASK (S3_XGA_8BPP|S3_XGA_16BPP|S3_XGA_32BPP) - -typedef struct { - bool attrindex; -} VGA_Internal; - -typedef struct { -/* Memory handlers */ - Bitu mh_mask; - -/* Video drawing */ - Bitu display_start; - Bitu real_start; - bool retrace; /* A retrace is active */ - Bitu scan_len; - Bitu cursor_start; - -/* Some other screen related variables */ - Bitu line_compare; - bool chained; /* Enable or Disabled Chain 4 Mode */ - bool compatible_chain4; - - /* Pixel Scrolling */ - Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */ - Bit8u hlines_skip; - Bit8u bytes_skip; - Bit8u addr_shift; - -/* Specific stuff memory write/read handling */ - - Bit8u read_mode; - Bit8u write_mode; - Bit8u read_map_select; - Bit8u color_dont_care; - Bit8u color_compare; - Bit8u data_rotate; - Bit8u raster_op; - - Bit32u full_bit_mask; - Bit32u full_map_mask; - Bit32u full_not_map_mask; - Bit32u full_set_reset; - Bit32u full_not_enable_set_reset; - Bit32u full_enable_set_reset; - Bit32u full_enable_and_set_reset; -} VGA_Config; - -typedef struct { - bool resizing; - Bitu width; - Bitu height; - Bitu blocks; - Bitu address; - Bitu panning; - Bitu bytes_skip; - Bit8u *linear_base; - Bitu linear_mask; - Bitu address_add; - Bitu line_length; - Bitu address_line_total; - Bitu address_line; - Bitu lines_total; - Bitu lines_done; - Bitu lines_scaled; - Bitu split_line; - Bitu parts_total; - Bitu parts_lines; - Bitu parts_left; - Bitu byte_panning_shift; - struct { - double framestart; - double vrstart, vrend; // V-retrace - double hrstart, hrend; // H-retrace - double hblkstart, hblkend; // H-blanking - double vblkstart, vblkend; // V-Blanking - double vdend, vtotal; - double hdend, htotal; - double parts; - } delay; - double aspect_ratio; - bool double_scan; - bool doublewidth,doubleheight; - Bit8u font[64*1024]; - Bit8u * font_tables[2]; - Bitu blinking; - struct { - Bitu address; - Bit8u sline,eline; - Bit8u count,delay; - Bit8u enabled; - } cursor; - bool vret_triggered; -} VGA_Draw; - -typedef struct { - Bit8u curmode; - Bit16u originx, originy; - Bit8u fstackpos, bstackpos; - Bit8u forestack[3]; - Bit8u backstack[3]; - Bit16u startaddr; - Bit8u posx, posy; - Bit8u mc[64][64]; -} VGA_HWCURSOR; - -typedef struct { - Bit8u reg_lock1; - Bit8u reg_lock2; - Bit8u reg_31; - Bit8u reg_35; - Bit8u reg_36; // RAM size - Bit8u reg_3a; // 4/8/doublepixel bit in there - Bit8u reg_40; // 8415/A functionality register - Bit8u reg_41; // BIOS flags - Bit8u reg_43; - Bit8u reg_45; // Hardware graphics cursor - Bit8u reg_50; - Bit8u reg_51; - Bit8u reg_52; - Bit8u reg_55; - Bit8u reg_58; - Bit8u reg_6b; // LFB BIOS scratchpad - Bit8u ex_hor_overflow; - Bit8u ex_ver_overflow; - Bit16u la_window; - Bit8u misc_control_2; - Bit8u ext_mem_ctrl; - Bitu xga_screen_width; - VGAModes xga_color_mode; - struct { - Bit8u r; - Bit8u n; - Bit8u m; - } clk[4],mclk; - struct { - Bit8u lock; - Bit8u cmd; - } pll; - VGA_HWCURSOR hgc; -} VGA_S3; - -typedef struct { - Bit8u mode_control; - Bit8u enable_bits; -} VGA_HERC; - -typedef struct { - Bit8u index; - Bit8u htotal; - Bit8u hdend; - Bit8u hsyncp; - Bit8u syncw; - Bit8u vtotal; - Bit8u vdend; - Bit8u vadjust; - Bit8u vsyncp; - Bit8u vsyncw; - Bit8u max_scanline; - Bit8u lpen_low, lpen_high; - Bit8u cursor_start; - Bit8u cursor_end; -} VGA_OTHER; - -typedef struct { - Bit8u pcjr_flipflop; - Bit8u mode_control; - Bit8u color_select; - Bit8u disp_bank; - Bit8u reg_index; - Bit8u gfx_control; - Bit8u palette_mask; - Bit8u extended_ram; - Bit8u border_color; - Bit8u line_mask, line_shift; - Bit8u draw_bank, mem_bank; - Bit8u *draw_base, *mem_base; - Bitu addr_mask; -} VGA_TANDY; - -typedef struct { - Bit8u index; - Bit8u reset; - Bit8u clocking_mode; - Bit8u map_mask; - Bit8u character_map_select; - Bit8u memory_mode; -} VGA_Seq; - -typedef struct { - Bit8u palette[16]; - Bit8u mode_control; - Bit8u horizontal_pel_panning; - Bit8u overscan_color; - Bit8u color_plane_enable; - Bit8u color_select; - Bit8u index; - Bit8u enabled; -} VGA_Attr; - -typedef struct { - Bit8u horizontal_total; - Bit8u horizontal_display_end; - Bit8u start_horizontal_blanking; - Bit8u end_horizontal_blanking; - Bit8u start_horizontal_retrace; - Bit8u end_horizontal_retrace; - Bit8u vertical_total; - Bit8u overflow; - Bit8u preset_row_scan; - Bit8u maximum_scan_line; - Bit8u cursor_start; - Bit8u cursor_end; - Bit8u start_address_high; - Bit8u start_address_low; - Bit8u cursor_location_high; - Bit8u cursor_location_low; - Bit8u vertical_retrace_start; - Bit8u vertical_retrace_end; - Bit8u vertical_display_end; - Bit8u offset; - Bit8u underline_location; - Bit8u start_vertical_blanking; - Bit8u end_vertical_blanking; - Bit8u mode_control; - Bit8u line_compare; - - Bit8u index; - bool read_only; -} VGA_Crtc; - -typedef struct { - Bit8u index; - Bit8u set_reset; - Bit8u enable_set_reset; - Bit8u color_compare; - Bit8u data_rotate; - Bit8u read_map_select; - Bit8u mode; - Bit8u miscellaneous; - Bit8u color_dont_care; - Bit8u bit_mask; -} VGA_Gfx; - -typedef struct { - Bit8u red; - Bit8u green; - Bit8u blue; -} RGBEntry; - -typedef struct { - Bit8u bits; /* DAC bits, usually 6 or 8 */ - Bit8u pel_mask; - Bit8u pel_index; - Bit8u state; - Bit8u write_index; - Bit8u read_index; - Bitu first_changed; - Bit8u combine[16]; - RGBEntry rgb[0x100]; - Bit16u xlat16[256]; -} VGA_Dac; - -typedef struct { - Bitu readStart, writeStart; - Bitu bankMask; - Bitu bank_read_full; - Bitu bank_write_full; - Bit8u bank_read; - Bit8u bank_write; - Bitu bank_size; -} VGA_SVGA; - -typedef union { - Bit32u d; - Bit8u b[4]; -} VGA_Latch; - -typedef struct { - Bit8u* linear; - Bit8u* linear_orgptr; -} VGA_Memory; - -typedef struct { - //Add a few more just to be safe - Bit8u* map; /* allocated dynamically: [(VGA_MEMORY >> VGA_CHANGE_SHIFT) + 32] */ - Bit8u checkMask, frame, writeMask; - bool active; - Bit32u clearMask; - Bit32u start, last; - Bit32u lastAddress; -} VGA_Changes; - -typedef struct { - Bit32u page; - Bit32u addr; - Bit32u mask; - PageHandler *handler; -} VGA_LFB; - -typedef struct { - VGAModes mode; /* The mode the vga system is in */ - VGAModes lastmode; - Bits screenflip; - Bit8u misc_output; - VGA_Draw draw; - VGA_Config config; - VGA_Internal internal; -/* Internal module groups */ - VGA_Seq seq; - VGA_Attr attr; - VGA_Crtc crtc; - VGA_Gfx gfx; - VGA_Dac dac; - VGA_Latch latch; - VGA_S3 s3; - VGA_SVGA svga; - VGA_HERC herc; - VGA_TANDY tandy; - VGA_OTHER other; - VGA_Memory mem; - Bit32u vmemwrap; /* this is assumed to be power of 2 */ - Bit8u* fastmem; /* memory for fast (usually 16-color) rendering, always twice as big as vmemsize */ - Bit8u* fastmem_orgptr; - Bit32u vmemsize; -#ifdef VGA_KEEP_CHANGES - VGA_Changes changes; -#endif - VGA_LFB lfb; -} VGA_Type; - - - -/* Functions for different resolutions */ -void VGA_SetMode(VGAModes mode); -void VGA_DetermineMode(void); -void VGA_SetupHandlers(void); -void VGA_StartResize(Bitu delay=50); -void VGA_SetupDrawing(Bitu val); -void VGA_CheckScanLength(void); -void VGA_ChangedBank(void); - -/* Some DAC/Attribute functions */ -void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal); -void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue); -void VGA_ATTR_SetPalette(Bit8u index,Bit8u val); - -/* The VGA Subfunction startups */ -void VGA_SetupAttr(void); -void VGA_SetupMemory(Section* sec); -void VGA_SetupDAC(void); -void VGA_SetupCRTC(void); -void VGA_SetupMisc(void); -void VGA_SetupGFX(void); -void VGA_SetupSEQ(void); -void VGA_SetupOther(void); -void VGA_SetupXGA(void); - -/* Some Support Functions */ -void VGA_SetClock(Bitu which,Bitu target); -void VGA_DACSetEntirePalette(void); -void VGA_StartRetrace(void); -void VGA_StartUpdateLFB(void); -void VGA_SetBlinking(Bitu enabled); -void VGA_SetCGA2Table(Bit8u val0,Bit8u val1); -void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3); -void VGA_ActivateHardwareCursor(void); -void VGA_KillDrawing(void); - -extern VGA_Type vga; - -/* Support for modular SVGA implementation */ -/* Video mode extra data to be passed to FinishSetMode_SVGA(). - This structure will be in flux until all drivers (including S3) - are properly separated. Right now it contains only three overflow - fields in S3 format and relies on drivers re-interpreting those. - For reference: - ver_overflow:X|line_comp10|X|vretrace10|X|vbstart10|vdispend10|vtotal10 - hor_overflow:X|X|X|hretrace8|X|hblank8|hdispend8|htotal8 - offset is not currently used by drivers (useful only for S3 itself) - It also contains basic int10 mode data - number, vtotal, htotal - */ -typedef struct { - Bit8u ver_overflow; - Bit8u hor_overflow; - Bitu offset; - Bitu modeNo; - Bitu htotal; - Bitu vtotal; -} VGA_ModeExtraData; - -// Vector function prototypes -typedef void (*tWritePort)(Bitu reg,Bitu val,Bitu iolen); -typedef Bitu (*tReadPort)(Bitu reg,Bitu iolen); -typedef void (*tFinishSetMode)(Bitu crtc_base, VGA_ModeExtraData* modeData); -typedef void (*tDetermineMode)(); -typedef void (*tSetClock)(Bitu which,Bitu target); -typedef Bitu (*tGetClock)(); -typedef bool (*tHWCursorActive)(); -typedef bool (*tAcceptsMode)(Bitu modeNo); - -struct SVGA_Driver { - tWritePort write_p3d5; - tReadPort read_p3d5; - tWritePort write_p3c5; - tReadPort read_p3c5; - tWritePort write_p3c0; - tReadPort read_p3c1; - tWritePort write_p3cf; - tReadPort read_p3cf; - - tFinishSetMode set_video_mode; - tDetermineMode determine_mode; - tSetClock set_clock; - tGetClock get_clock; - tHWCursorActive hardware_cursor_active; - tAcceptsMode accepts_mode; -}; - -extern SVGA_Driver svga; - -void SVGA_Setup_S3Trio(void); -void SVGA_Setup_TsengET4K(void); -void SVGA_Setup_TsengET3K(void); -void SVGA_Setup_ParadisePVGA1A(void); -void SVGA_Setup_Driver(void); - -// Amount of video memory required for a mode, implemented in int10_modes.cpp -Bitu VideoModeMemSize(Bitu mode); - -extern Bit32u ExpandTable[256]; -extern Bit32u FillTable[16]; -extern Bit32u CGA_2_Table[16]; -extern Bit32u CGA_4_Table[256]; -extern Bit32u CGA_4_HiRes_Table[256]; -extern Bit32u CGA_16_Table[256]; -extern Bit32u TXT_Font_Table[16]; -extern Bit32u TXT_FG_Table[16]; -extern Bit32u TXT_BG_Table[16]; -extern Bit32u Expand16Table[4][16]; -extern Bit32u Expand16BigTable[0x10000]; - - -#endif diff --git a/include/video.h b/include/video.h index c690ffe..2519949 100644 --- a/include/video.h +++ b/include/video.h @@ -1,85 +1,50 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: video.h,v 1.25 2008/08/24 16:43:06 qbix79 Exp $ */ - -#ifndef DOSBOX_VIDEO_H -#define DOSBOX_VIDEO_H - -#define REDUCE_JOYSTICK_POLLING - -typedef enum { - GFX_CallBackReset, - GFX_CallBackStop, - GFX_CallBackRedraw -} GFX_CallBackFunctions_t; - -typedef void (*GFX_CallBack_t)( GFX_CallBackFunctions_t function ); - -struct GFX_PalEntry { - Bit8u r; - Bit8u g; - Bit8u b; - Bit8u unused; -}; - -#define GFX_CAN_8 0x0001 -#define GFX_CAN_15 0x0002 -#define GFX_CAN_16 0x0004 -#define GFX_CAN_32 0x0008 - -#define GFX_LOVE_8 0x0010 -#define GFX_LOVE_15 0x0020 -#define GFX_LOVE_16 0x0040 -#define GFX_LOVE_32 0x0080 - -#define GFX_RGBONLY 0x0100 - -#define GFX_SCALING 0x1000 -#define GFX_HARDWARE 0x2000 - -#define GFX_CAN_RANDOM 0x4000 //If the interface can also do random access surface - -void GFX_Events(void); -void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries); -Bitu GFX_GetBestMode(Bitu flags); -Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue); -Bitu GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_CallBack_t cb); - -void GFX_ResetScreen(void); -void GFX_Start(void); -void GFX_Stop(void); -void GFX_SwitchFullScreen(void); -bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch); -void GFX_EndUpdate( const Bit16u *changedLines ); -void GFX_GetSize(int &width, int &height, bool &fullscreen); -void GFX_LosingFocus(void); - -#if defined (WIN32) -bool GFX_SDLUsingWinDIB(void); -#endif - -#if defined (REDUCE_JOYSTICK_POLLING) -void MAPPER_UpdateJoysticks(void); -#endif - -/* Mouse related */ -void GFX_CaptureMouse(void); -extern bool mouselocked; //true if mouse is confined to window - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __VIDEO_H +#define __VIDEO_H + +typedef void (GFX_DrawHandler)(Bit8u * vidstart); +/* Used to reply to the renderer what size to set */ +typedef void (GFX_ResizeHandler)(Bitu * width,Bitu * height); + +struct GFX_PalEntry { + Bit8u r; + Bit8u g; + Bit8u b; + Bit8u unused; +}; + +struct GFX_Info { + Bitu width,height,bpp,pitch; +}; + +extern GFX_Info gfx_info; + +void GFX_Events(void); +void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries); +void GFX_SetDrawHandler(GFX_DrawHandler * handler); +void GFX_Resize(Bitu width,Bitu height,Bitu bpp,GFX_ResizeHandler * resize); + +void GFX_Start(void); +void GFX_Stop(void); +void GFX_SwitchFullScreen(void); + + +#endif + diff --git a/install-sh b/install-sh new file mode 100644 index 0000000..398a88e --- /dev/null +++ b/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + : +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=$mkdirprog + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + : + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + : + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + : + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' + ' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + : + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + : + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/missing b/missing new file mode 100644 index 0000000..dd58370 --- /dev/null +++ b/missing @@ -0,0 +1,336 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing 0.4 - GNU automake" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. + You can get \`$1Help2man' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then + # We have makeinfo, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + fi + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar ${1+"$@"} && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar ${1+"$@"} && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" ${1+"$@"} && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" ${1+"$@"} && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100644 index 0000000..f9c37af --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,101 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." + +# process command line arguments +while test $# -gt 0 ; do + case "${1}" in + -h | --help | --h* ) # -h for help + echo "${usage}" 1>&2; exit 0 ;; + -m ) # -m PERM arg + shift + test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } + dirmode="${1}" + shift ;; + -- ) shift; break ;; # stop option processing + -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option + * ) break ;; # first non-opt arg + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in +0) exit 0 ;; +esac + +case $dirmode in +'') + if mkdir -p -- . 2>/dev/null; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + fi ;; +*) + if mkdir -m "$dirmode" -p -- . 2>/dev/null; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + fi ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 3 +# End: +# mkinstalldirs ends here diff --git a/scripts/dosbox-installer.nsi b/scripts/dosbox-installer.nsi deleted file mode 100644 index 0aa15a1..0000000 --- a/scripts/dosbox-installer.nsi +++ /dev/null @@ -1,149 +0,0 @@ -!define VER_MAYOR 0 -!define VER_MINOR 72 -!define APP_NAME "DOSBox ${VER_MAYOR}.${VER_MINOR} Installer" -!define COMP_NAME "DOSBox Team" -!define COPYRIGHT "Copyright © 2002-2008 DOSBox Team" -!define DESCRIPTION "DOSBox Installer" - -VIProductVersion "${VER_MAYOR}.${VER_MINOR}.0.0" -VIAddVersionKey "ProductName" "${APP_NAME}" -VIAddVersionKey "CompanyName" "${COMP_NAME}" -VIAddVersionKey "FileDescription" "${DESCRIPTION}" -VIAddVersionKey "FileVersion" "${VER_MAYOR}.${VER_MINOR}.0.0" -VIAddVersionKey "ProductVersion" "${VER_MAYOR}, ${VER_MINOR}, 0, 0" -VIAddVersionKey "LegalCopyright" "${COPYRIGHT}" - -; The name of the installer -Name "${APP_NAME}" - -; The file to write -OutFile "DOSBox${VER_MAYOR}.${VER_MINOR}-win32-installer.exe" - -; The default installation directory -InstallDir "$PROGRAMFILES\DOSBox-${VER_MAYOR}.${VER_MINOR}" - -; The text to prompt the user to enter a directory -DirText "This will install DOSBox v${VER_MAYOR}.${VER_MINOR} on your computer. Choose a directory" -SetCompressor /solid lzma - - -LicenseData COPYING -LicenseText "DOSBox v${VER_MAYOR}.${VER_MINOR} License" "Next >" - -; Else vista enables compatibility mode -RequestExecutionLevel admin - -ComponentText "Select components for DOSBox" -; The stuff to install -Section "!Core files" Core - ; Set output path to the installation directory. - ClearErrors - SetOutPath $INSTDIR - IfErrors error_createdir - SectionIn RO - - ; Put file there - - CreateDirectory "$INSTDIR\capture" - CreateDirectory "$INSTDIR\zmbv" - File /oname=README.txt README - File /oname=COPYING.txt COPYING - File /oname=THANKS.txt THANKS - File /oname=NEWS.txt NEWS - File /oname=AUTHORS.txt AUTHORS - File /oname=INSTALL.txt INSTALL - File DOSBox.exe - File dosbox.conf - File SDL.dll - File SDL_net.dll - File /oname=zmbv\zmbv.dll zmbv.dll - File /oname=zmbv\zmbv.inf zmbv.inf - File /oname=zmbv\README.txt README.video - - CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}" - CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video" - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.lnk" "$INSTDIR\DOSBox.exe" "-conf $\"$INSTDIR\dosbox.conf$\"" "$INSTDIR\DOSBox.exe" 0 - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox (noconsole).lnk" "$INSTDIR\DOSBox.exe" "-noconsole -conf $\"$INSTDIR\dosbox.conf$\"" "$INSTDIR\DOSBox.exe" 0 - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\README.lnk" "$INSTDIR\README.txt" - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.conf.lnk" "notepad.exe" "$INSTDIR\dosbox.conf" - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Capture folder.lnk" "$INSTDIR\capture" - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Video instructions.lnk" "$INSTDIR\zmbv\README.txt" -;change outpath so the working directory gets set to zmbv -SetOutPath "$INSTDIR\zmbv" - ; Shortcut creation depends on wether we are 9x of NT - ClearErrors - ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion - IfErrors we_9x we_nt -we_nt: - ;shortcut for win NT - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Install movie codec.lnk" "rundll32" "setupapi,InstallHinfSection DefaultInstall 128 $INSTDIR\zmbv\zmbv.inf" - goto end -we_9x: - ;shortcut for we_9x - CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Install movie codec.lnk" "rundll" "setupx.dll,InstallHinfSection DefaultInstall 128 $INSTDIR\zmbv\zmbv.inf" -end: -SetOutPath $INSTDIR -WriteUninstaller "uninstall.exe" - - goto end_section - -error_createdir: - MessageBox MB_OK "Can't create DOSBox program directory, aborting." - Abort - goto end_section - -end_section: -SectionEnd ; end the section - -Section "Desktop Shortcut" SecDesktop - -CreateShortCut "$DESKTOP\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" "$INSTDIR\DOSBox.exe" "-conf $\"$INSTDIR\dosbox.conf$\"" "$INSTDIR\DOSBox.exe" 0 - - SectionEnd ; end the section - - -UninstallText "This will uninstall DOSBox v${VER_MAYOR}.${VER_MINOR}. Hit next to continue." - -Section "Uninstall" - Delete "$DESKTOP\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" - ; remove registry keys - ; remove files - Delete $INSTDIR\README.txt - Delete $INSTDIR\COPYING.txt - Delete $INSTDIR\THANKS.txt - Delete $INSTDIR\NEWS.txt - Delete $INSTDIR\AUTHORS.txt - Delete $INSTDIR\INSTALL.txt - Delete $INSTDIR\DOSBox.exe - Delete $INSTDIR\dosbox.conf - Delete $INSTDIR\SDL.dll - Delete $INSTDIR\SDL_net.dll - Delete $INSTDIR\zmbv\zmbv.dll - Delete $INSTDIR\zmbv\zmbv.inf - Delete $INSTDIR\zmbv\README.txt - ;Files left by sdl taking over the console - Delete $INSTDIR\stdout.txt - Delete $INSTDIR\stderr.txt - - ; MUST REMOVE UNINSTALLER, too - Delete $INSTDIR\uninstall.exe - - ; remove shortcuts, if any. - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Uninstall.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\README.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox (noconsole).lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.conf.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Capture folder.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Install movie codec.lnk" - Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Video instructions.lnk" -; remove directories used. - RMDir "$INSTDIR\zmbv" - RMDir "$INSTDIR\capture" - RMDir "$INSTDIR" - RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video" - RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}" -SectionEnd - -; eof diff --git a/scripts/ega-switch.pl b/scripts/ega-switch.pl deleted file mode 100644 index 936ad28..0000000 --- a/scripts/ega-switch.pl +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/perl -use integer; -open (THEFILE,'>','../src/hardware/ega-switch.h') - or die "Can't open my file $!"; - -print THEFILE "switch (bit_mask) {\n"; -for ($i = 0; $i < 256; $i++) { - print THEFILE "\tcase $i:\n"; - $b=128; - $add=0; - do { - if ($i & $b) { - print THEFILE "\t{\n"; - print THEFILE "\t\tBit8u color=0;\n"; - print THEFILE "\t\tif (pixels.b[0] & $b) color|=1;\n"; - print THEFILE "\t\tif (pixels.b[1] & $b) color|=2;\n"; - print THEFILE "\t\tif (pixels.b[2] & $b) color|=4;\n"; - print THEFILE "\t\tif (pixels.b[3] & $b) color|=8;\n"; - print THEFILE "\t\t*(write_pixels+$add)=color;\n"; - print THEFILE "\t\t*(write_pixels+$add+512*1024)=color;\n"; - print THEFILE "\t}\n"; - } - - $b=$b >> 1; - $add=$add+1; - } until ($b == 0); - print THEFILE "\tbreak;\n"; -} -print THEFILE "}\n"; - - -close (THEFILE); diff --git a/scripts/font-switch.pl b/scripts/font-switch.pl deleted file mode 100644 index 6ad629c..0000000 --- a/scripts/font-switch.pl +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/perl -use integer; -open (THEFILE,'>','../src/hardware/font-switch.h') - or die "Can't open my file $!"; - -print THEFILE "switch (bit_mask) {\n"; -for ($i = 0; $i < 256; $i++) { - print THEFILE "\tcase $i:\n"; - $b=128; - $add=0; - do { - if ($i & $b) { - print THEFILE "\t\t*(draw+$add)=fg;\n"; - } else { - print THEFILE "\t\t*(draw+$add)=bg;\n"; - } - $b=$b >> 1; - $add=$add+1; - } until ($b == 0); - print THEFILE "\tbreak;\n"; -} -print THEFILE "}\n"; - - -close (THEFILE); diff --git a/settings.h b/settings.h new file mode 100644 index 0000000..f7fefd0 --- /dev/null +++ b/settings.h @@ -0,0 +1,26 @@ +/* Enable the debugger */ +//#define C_DEBUG + +/* Enable logging of debug information */ +//#define C_LOGGING + +/* Use multi threading to speed up things on multi cpu's, also gives a nice frame-skipping effect :) */ +#define C_THREADED + +/* Enable debugging for several modules, requires C_LOGGING */ +#define DEBUG_SBLASTER /* SoundBlaster Debugging*/ +#define DEBUG_DMA /* DMA Debugging */ +#define DEBUG_DOS /* DOS Debugging */ + + +#define LOG_MSG S_Warn + +#ifdef C_LOGGING +#define LOG_DEBUG S_Warn +#define LOG_WARN S_Warn +#define LOG_ERROR S_Warn +#else +#define LOG_DEBUG +#define LOG_WARN +#define LOG_ERROR +#endif \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am index 3634a4a..0b960ea 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,20 +1,10 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include - -SUBDIRS = cpu debug dos fpu gui hardware libs ints misc shell platform - -bin_PROGRAMS = dosbox - -if HAVE_WINDRES -ico_stuff = winres.rc -endif - -.rc.o: - $(WINDRES) -o $@ $< - -dosbox_SOURCES = dosbox.cpp $(ico_stuff) -dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \ - ints/libints.a misc/libmisc.a shell/libshell.a hardware/serialport/libserial.a libs/gui_tk/libgui_tk.a - -EXTRA_DIST = winres.rc dosbox.ico - - +AM_CPPFLAGS = -I$(top_srcdir)/include + +SUBDIRS = cpu debug dos fpu gui hardware ints misc shell platform + +bin_PROGRAMS = dosbox + +dosbox_SOURCES = dosbox.cpp +dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \ + ints/libints.a misc/libmisc.a shell/libshell.a -lcurses +EXTRA_DIST = dosbox.lang \ No newline at end of file diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..0283c01 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,420 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +AM_CPPFLAGS = -I$(top_srcdir)/include + +SUBDIRS = cpu debug dos fpu gui hardware ints misc shell platform + +bin_PROGRAMS = dosbox + +dosbox_SOURCES = dosbox.cpp +dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \ + ints/libints.a misc/libmisc.a shell/libshell.a -lcurses + +EXTRA_DIST = dosbox.lang +subdir = src +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +bin_PROGRAMS = dosbox$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) + +am_dosbox_OBJECTS = dosbox.$(OBJEXT) +dosbox_OBJECTS = $(am_dosbox_OBJECTS) +dosbox_DEPENDENCIES = cpu/libcpu.a debug/libdebug.a dos/libdos.a \ + fpu/libfpu.a hardware/libhardware.a gui/libgui.a ints/libints.a \ + misc/libmisc.a shell/libshell.a +dosbox_LDFLAGS = + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dosbox.Po +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +CXXFLAGS = @CXXFLAGS@ +DIST_SOURCES = $(dosbox_SOURCES) + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = Makefile.am Makefile.in +DIST_SUBDIRS = $(SUBDIRS) +SOURCES = $(dosbox_SOURCES) + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + p1=`echo "$$p1" | sed -e 's,^.*/,,'`; \ + f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \ + $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + f=`echo "$$f" | sed -e 's,^.*/,,'`; \ + echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ + rm -f $(DESTDIR)$(bindir)/$$f; \ + done + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +dosbox$(EXEEXT): $(dosbox_OBJECTS) $(dosbox_DEPENDENCIES) + @rm -f dosbox$(EXEEXT) + $(CXXLINK) $(dosbox_LDFLAGS) $(dosbox_OBJECTS) $(dosbox_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dosbox.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `cygpath -w $<` +CXXDEPMODE = @CXXDEPMODE@ +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(bindir) + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-binPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-recursive + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-recursive distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-recursive distclean-tags distdir dvi dvi-am \ + dvi-recursive info info-am info-recursive install install-am \ + install-binPROGRAMS install-data install-data-am \ + install-data-recursive install-exec install-exec-am \ + install-exec-recursive install-info install-info-am \ + install-info-recursive install-man install-recursive \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am installdirs-recursive maintainer-clean \ + maintainer-clean-generic maintainer-clean-recursive mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-recursive \ + tags tags-recursive uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-info-am \ + uninstall-info-recursive uninstall-recursive + +# 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/cpu/Makefile.am b/src/cpu/Makefile.am index e67d382..5a8f26a 100644 --- a/src/cpu/Makefile.am +++ b/src/cpu/Makefile.am @@ -1,7 +1,5 @@ -SUBDIRS = core_full core_normal core_dyn_x86 core_dynrec -AM_CPPFLAGS = -I$(top_srcdir)/include - -noinst_LIBRARIES = libcpu.a -libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \ - paging.cpp lazyflags.h core_normal.cpp core_simple.cpp core_prefetch.cpp \ - core_dyn_x86.cpp core_dynrec.cpp +SUBDIRS = core_16 +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libcpu.a +libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h slow_16.cpp \ No newline at end of file diff --git a/src/cpu/Makefile.in b/src/cpu/Makefile.in new file mode 100644 index 0000000..043f52b --- /dev/null +++ b/src/cpu/Makefile.in @@ -0,0 +1,401 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +SUBDIRS = core_16 +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libcpu.a +libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h slow_16.cpp +subdir = src/cpu +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libcpu_a_AR = $(AR) cru +libcpu_a_LIBADD = +am_libcpu_a_OBJECTS = callback.$(OBJEXT) cpu.$(OBJEXT) flags.$(OBJEXT) \ + modrm.$(OBJEXT) slow_16.$(OBJEXT) +libcpu_a_OBJECTS = $(am_libcpu_a_OBJECTS) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/callback.Po ./$(DEPDIR)/cpu.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/flags.Po ./$(DEPDIR)/modrm.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/slow_16.Po +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +CXXFLAGS = @CXXFLAGS@ +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libcpu_a_SOURCES) + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = Makefile.am Makefile.in +DIST_SUBDIRS = $(SUBDIRS) +SOURCES = $(libcpu_a_SOURCES) + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/cpu/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +AR = ar + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libcpu.a: $(libcpu_a_OBJECTS) $(libcpu_a_DEPENDENCIES) + -rm -f libcpu.a + $(libcpu_a_AR) libcpu.a $(libcpu_a_OBJECTS) $(libcpu_a_LIBADD) + $(RANLIB) libcpu.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flags.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modrm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slow_16.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `cygpath -w $<` +CXXDEPMODE = @CXXDEPMODE@ +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LIBRARIES) +installdirs: installdirs-recursive +installdirs-am: + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-recursive + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-noinstLIBRARIES clean-recursive distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-recursive distclean-tags distdir dvi dvi-am \ + dvi-recursive info info-am info-recursive install install-am \ + install-data install-data-am install-data-recursive \ + install-exec install-exec-am install-exec-recursive \ + install-info install-info-am install-info-recursive install-man \ + install-recursive install-strip installcheck installcheck-am \ + installdirs installdirs-am installdirs-recursive \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-recursive tags tags-recursive \ + uninstall uninstall-am uninstall-info-am \ + uninstall-info-recursive uninstall-recursive + +# 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/cpu/callback.cpp b/src/cpu/callback.cpp index f134df2..5794bd4 100644 --- a/src/cpu/callback.cpp +++ b/src/cpu/callback.cpp @@ -1,575 +1,172 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: callback.cpp,v 1.40 2009/03/03 18:30:41 c2woody Exp $ */ - -#include -#include - -#include "dosbox.h" -#include "callback.h" -#include "mem.h" -#include "cpu.h" - -/* CallBack are located at 0xF100:0 (see CB_SEG in callback.h) - And they are 16 bytes each and you can define them to behave in certain ways like a - far return or and IRET -*/ - -CallBack_Handler CallBack_Handlers[CB_MAX]; -char* CallBack_Description[CB_MAX]; - -static Bitu call_stop,call_idle,call_default,call_default2; -Bitu call_priv_io; - -static Bitu illegal_handler(void) { - E_Exit("Illegal CallBack Called"); - return 1; -} - -Bitu CALLBACK_Allocate(void) { - for (Bitu i=1;(i0) - CPU_Cycles=0; -} - -static Bitu default_handler(void) { - LOG(LOG_CPU,LOG_ERROR)("Illegal Unhandled Interrupt Called %X",lastint); - return CBRET_NONE; -} - -static Bitu stop_handler(void) { - return CBRET_STOP; -} - - - -void CALLBACK_RunRealFar(Bit16u seg,Bit16u off) { - reg_sp-=4; - mem_writew(SegPhys(ss)+reg_sp,call_stop*CB_SIZE); - mem_writew(SegPhys(ss)+reg_sp+2,CB_SEG); - Bit32u oldeip=reg_eip; - Bit16u oldcs=SegValue(cs); - reg_eip=off; - SegSet16(cs,seg); - DOSBOX_RunMachine(); - reg_eip=oldeip; - SegSet16(cs,oldcs); -} - -void CALLBACK_RunRealInt(Bit8u intnum) { - Bit32u oldeip=reg_eip; - Bit16u oldcs=SegValue(cs); - reg_eip=(CB_MAX*CB_SIZE)+(intnum*6); - SegSet16(cs,CB_SEG); - DOSBOX_RunMachine(); - reg_eip=oldeip; - SegSet16(cs,oldcs); -} - -void CALLBACK_SZF(bool val) { - Bit16u tempf=mem_readw(SegPhys(ss)+reg_sp+4) & 0xFFBF; - Bit16u newZF=(val==true) << 6; - mem_writew(SegPhys(ss)+reg_sp+4,(tempf | newZF)); -} - -void CALLBACK_SCF(bool val) { - Bit16u tempf=mem_readw(SegPhys(ss)+reg_sp+4) & 0xFFFE; - Bit16u newCF=(val==true); - mem_writew(SegPhys(ss)+reg_sp+4,(tempf | newCF)); -} - -void CALLBACK_SetDescription(Bitu nr, const char* descr) { - if (descr) { - CallBack_Description[nr] = new char[strlen(descr)+1]; - strcpy(CallBack_Description[nr],descr); - } else - CallBack_Description[nr] = 0; -} - -const char* CALLBACK_GetDescription(Bitu nr) { - if (nr>=CB_MAX) return 0; - return CallBack_Description[nr]; -} - -Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_cb=true) { - if (callback>=CB_MAX) - return 0; - switch (type) { - case CB_RETN: - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02, callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0xC3); //A RETN Instruction - return (use_cb?5:1); - case CB_RETF: - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02, callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0xCB); //A RETF Instruction - return (use_cb?5:1); - case CB_RETF8: - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02, callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0xCA); //A RETF 8 Instruction - phys_writew(physAddress+0x01,(Bit16u)0x0008); - return (use_cb?7:3); - case CB_IRET: - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02,callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0xCF); //An IRET Instruction - return (use_cb?5:1); - case CB_IRETD: - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02,callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0x66); //An IRETD Instruction - phys_writeb(physAddress+0x01,(Bit8u)0xCF); - return (use_cb?6:2); - case CB_IRET_STI: - phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI - if (use_cb) { - phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x03, callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction - return (use_cb?6:2); - case CB_IRET_EOI_PIC1: - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02,callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax - phys_writeb(physAddress+0x01,(Bit8u)0xb0); // mov al, 0x20 - phys_writeb(physAddress+0x02,(Bit8u)0x20); - phys_writeb(physAddress+0x03,(Bit8u)0xe6); // out 0x20, al - phys_writeb(physAddress+0x04,(Bit8u)0x20); - phys_writeb(physAddress+0x05,(Bit8u)0x58); // pop ax - phys_writeb(physAddress+0x06,(Bit8u)0xcf); //An IRET Instruction - return (use_cb?0x0b:0x07); - case CB_IRQ0: // timer int8 - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02,callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax - phys_writeb(physAddress+0x01,(Bit8u)0x52); // push dx - phys_writeb(physAddress+0x02,(Bit8u)0x1e); // push ds - phys_writew(physAddress+0x03,(Bit16u)0x1ccd); // int 1c - phys_writeb(physAddress+0x05,(Bit8u)0xfa); // cli - phys_writeb(physAddress+0x06,(Bit8u)0x1f); // pop ds - phys_writeb(physAddress+0x07,(Bit8u)0x5a); // pop dx - phys_writew(physAddress+0x08,(Bit16u)0x20b0); // mov al, 0x20 - phys_writew(physAddress+0x0a,(Bit16u)0x20e6); // out 0x20, al - phys_writeb(physAddress+0x0c,(Bit8u)0x58); // pop ax - phys_writeb(physAddress+0x0d,(Bit8u)0xcf); //An IRET Instruction - return (use_cb?0x12:0x0e); - case CB_IRQ1: // keyboard int9 - phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax - phys_writew(physAddress+0x01,(Bit16u)0x60e4); // in al, 0x60 - phys_writew(physAddress+0x03,(Bit16u)0x4fb4); // mov ah, 0x4f - phys_writeb(physAddress+0x05,(Bit8u)0xf9); // stc - phys_writew(physAddress+0x06,(Bit16u)0x15cd); // int 15 - if (use_cb) { - phys_writew(physAddress+0x08,(Bit16u)0x0473); // jc skip - phys_writeb(physAddress+0x0a,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x0b,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x0c,callback); //The immediate word - // jump here to (skip): - physAddress+=6; - } - phys_writeb(physAddress+0x08,(Bit8u)0xfa); // cli - phys_writew(physAddress+0x09,(Bit16u)0x20b0); // mov al, 0x20 - phys_writew(physAddress+0x0b,(Bit16u)0x20e6); // out 0x20, al - phys_writeb(physAddress+0x0d,(Bit8u)0x58); // pop ax - phys_writeb(physAddress+0x0e,(Bit8u)0xcf); //An IRET Instruction - return (use_cb?0x15:0x0f); - case CB_IRQ9: // pic cascade interrupt - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02,callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax - phys_writew(physAddress+0x01,(Bit16u)0x61b0); // mov al, 0x61 - phys_writew(physAddress+0x03,(Bit16u)0xa0e6); // out 0xa0, al - phys_writew(physAddress+0x05,(Bit16u)0x0acd); // int a - phys_writeb(physAddress+0x07,(Bit8u)0xfa); // cli - phys_writeb(physAddress+0x08,(Bit8u)0x58); // pop ax - phys_writeb(physAddress+0x09,(Bit8u)0xcf); //An IRET Instruction - return (use_cb?0x0e:0x0a); - case CB_IRQ12: // ps2 mouse int74 - if (!use_cb) E_Exit("int74 callback must implement a callback handler!"); - phys_writeb(physAddress+0x00,(Bit8u)0x1e); // push ds - phys_writeb(physAddress+0x01,(Bit8u)0x06); // push es - phys_writew(physAddress+0x02,(Bit16u)0x6066); // pushad - phys_writeb(physAddress+0x04,(Bit8u)0xfc); // cld - phys_writeb(physAddress+0x05,(Bit8u)0xfb); // sti - phys_writeb(physAddress+0x06,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x07,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x08,callback); //The immediate word - return 0x0a; - case CB_IRQ12_RET: // ps2 mouse int74 return - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02,callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0xfa); // cli - phys_writew(physAddress+0x01,(Bit16u)0x20b0); // mov al, 0x20 - phys_writew(physAddress+0x03,(Bit16u)0xa0e6); // out 0xa0, al - phys_writew(physAddress+0x05,(Bit16u)0x20e6); // out 0x20, al - phys_writew(physAddress+0x07,(Bit16u)0x6166); // popad - phys_writeb(physAddress+0x09,(Bit8u)0x07); // pop es - phys_writeb(physAddress+0x0a,(Bit8u)0x1f); // pop ds - phys_writeb(physAddress+0x0b,(Bit8u)0xcf); //An IRET Instruction - return (use_cb?0x10:0x0c); - case CB_IRQ6_PCJR: // pcjr keyboard interrupt - phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax - phys_writew(physAddress+0x01,(Bit16u)0x60e4); // in al, 0x60 - phys_writew(physAddress+0x03,(Bit16u)0xe03c); // cmp al, 0xe0 - if (use_cb) { - phys_writew(physAddress+0x05,(Bit16u)0x0674); // je skip - phys_writeb(physAddress+0x07,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x08,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x09,callback); //The immediate word - physAddress+=4; - } else { - phys_writew(physAddress+0x05,(Bit16u)0x0274); // je skip - } - phys_writew(physAddress+0x07,(Bit16u)0x09cd); // int 9 - // jump here to (skip): - phys_writeb(physAddress+0x09,(Bit8u)0xfa); // cli - phys_writew(physAddress+0x0a,(Bit16u)0x20b0); // mov al, 0x20 - phys_writew(physAddress+0x0c,(Bit16u)0x20e6); // out 0x20, al - phys_writeb(physAddress+0x0e,(Bit8u)0x58); // pop ax - phys_writeb(physAddress+0x0f,(Bit8u)0xcf); //An IRET Instruction - return (use_cb?0x14:0x10); - case CB_MOUSE: - phys_writew(physAddress+0x00,(Bit16u)0x07eb); // jmp i33hd - physAddress+=9; - // jump here to (i33hd): - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02,callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0xCF); //An IRET Instruction - return (use_cb?0x0e:0x0a); - case CB_INT16: - phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI - if (use_cb) { - phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x03, callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction - for (Bitu i=0;i<=0x0b;i++) phys_writeb(physAddress+0x02+i,0x90); - phys_writew(physAddress+0x0e,(Bit16u)0xedeb); //jmp callback - return (use_cb?0x10:0x0c); - case CB_INT29: // fast console output - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02,callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax - phys_writew(physAddress+0x01,(Bit16u)0x0eb4); // mov ah, 0x0e - phys_writew(physAddress+0x03,(Bit16u)0x10cd); // int 10 - phys_writeb(physAddress+0x05,(Bit8u)0x58); // pop ax - phys_writeb(physAddress+0x06,(Bit8u)0xcf); //An IRET Instruction - return (use_cb?0x0b:0x07); - case CB_HOOKABLE: - phys_writeb(physAddress+0x00,(Bit8u)0xEB); //jump near - phys_writeb(physAddress+0x01,(Bit8u)0x03); //offset - phys_writeb(physAddress+0x02,(Bit8u)0x90); //NOP - phys_writeb(physAddress+0x03,(Bit8u)0x90); //NOP - phys_writeb(physAddress+0x04,(Bit8u)0x90); //NOP - if (use_cb) { - phys_writeb(physAddress+0x05,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x06,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x07,callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x05,(Bit8u)0xCB); //A RETF Instruction - return (use_cb?0x0a:0x06); - case CB_TDE_IRET: // TandyDAC end transfer - if (use_cb) { - phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x02,callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x00,(Bit8u)0x50); // push ax - phys_writeb(physAddress+0x01,(Bit8u)0xb8); // mov ax, 0x91fb - phys_writew(physAddress+0x02,(Bit16u)0x91fb); - phys_writew(physAddress+0x04,(Bit16u)0x15cd); // int 15 - phys_writeb(physAddress+0x06,(Bit8u)0xfa); // cli - phys_writew(physAddress+0x07,(Bit16u)0x20b0); // mov al, 0x20 - phys_writew(physAddress+0x09,(Bit16u)0x20e6); // out 0x20, al - phys_writeb(physAddress+0x0b,(Bit8u)0x58); // pop ax - phys_writeb(physAddress+0x0c,(Bit8u)0xcf); //An IRET Instruction - return (use_cb?0x11:0x0d); -/* case CB_IPXESR: // IPX ESR - if (!use_cb) E_Exit("ipx esr must implement a callback handler!"); - phys_writeb(physAddress+0x00,(Bit8u)0x1e); // push ds - phys_writeb(physAddress+0x01,(Bit8u)0x06); // push es - phys_writew(physAddress+0x02,(Bit16u)0xa00f); // push fs - phys_writew(physAddress+0x04,(Bit16u)0xa80f); // push gs - phys_writeb(physAddress+0x06,(Bit8u)0x60); // pusha - phys_writeb(physAddress+0x07,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x08,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x09,callback); //The immediate word - phys_writeb(physAddress+0x0b,(Bit8u)0xCB); //A RETF Instruction - return 0x0c; - case CB_IPXESR_RET: // IPX ESR return - if (use_cb) E_Exit("ipx esr return must not implement a callback handler!"); - phys_writeb(physAddress+0x00,(Bit8u)0xfa); // cli - phys_writew(physAddress+0x01,(Bit16u)0x20b0); // mov al, 0x20 - phys_writew(physAddress+0x03,(Bit16u)0xa0e6); // out 0xa0, al - phys_writew(physAddress+0x05,(Bit16u)0x20e6); // out 0x20, al - phys_writeb(physAddress+0x07,(Bit8u)0x61); // popa - phys_writew(physAddress+0x08,(Bit16u)0xA90F); // pop gs - phys_writew(physAddress+0x0a,(Bit16u)0xA10F); // pop fs - phys_writeb(physAddress+0x0c,(Bit8u)0x07); // pop es - phys_writeb(physAddress+0x0d,(Bit8u)0x1f); // pop ds - phys_writeb(physAddress+0x0e,(Bit8u)0xcf); //An IRET Instruction - return 0x0f; */ - case CB_INT21: - phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI - if (use_cb) { - phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4 - phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction - phys_writew(physAddress+0x03, callback); //The immediate word - physAddress+=4; - } - phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction - phys_writeb(physAddress+0x02,(Bit8u)0xCB); //A RETF Instruction - return (use_cb?7:3); - - default: - E_Exit("CALLBACK:Setup:Illegal type %d",type); - } - return 0; -} - -bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* descr) { - if (callback>=CB_MAX) return false; - CALLBACK_SetupExtra(callback,type,CALLBACK_PhysPointer(callback)+0,(handler!=NULL)); - CallBack_Handlers[callback]=handler; - CALLBACK_SetDescription(callback,descr); - return true; -} - -Bitu CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,PhysPt addr,const char* descr) { - if (callback>=CB_MAX) return 0; - Bitu csize=CALLBACK_SetupExtra(callback,type,addr,(handler!=NULL)); - if (csize>0) { - CallBack_Handlers[callback]=handler; - CALLBACK_SetDescription(callback,descr); - } - return csize; -} - -void CALLBACK_RemoveSetup(Bitu callback) { - for (Bitu i = 0;i < 16;i++) { - phys_writeb(CALLBACK_PhysPointer(callback)+i ,(Bit8u) 0x00); - } -} - -CALLBACK_HandlerObject::~CALLBACK_HandlerObject(){ - if(!installed) return; - if(m_type == CALLBACK_HandlerObject::SETUP) { - if(vectorhandler.installed){ - //See if we are the current handler. if so restore the old one - if(RealGetVec(vectorhandler.interrupt) == Get_RealPointer()) { - RealSetVec(vectorhandler.interrupt,vectorhandler.old_vector); - } else - LOG(LOG_MISC,LOG_WARN)("Interrupt vector changed on %X %s",vectorhandler.interrupt,CALLBACK_GetDescription(m_callback)); - } - CALLBACK_RemoveSetup(m_callback); - } else if(m_type == CALLBACK_HandlerObject::SETUPAT){ - E_Exit("Callback:SETUP at not handled yet."); - } else if(m_type == CALLBACK_HandlerObject::NONE){ - //Do nothing. Merely DeAllocate the callback - } else E_Exit("what kind of callback is this!"); - if(CallBack_Description[m_callback]) delete [] CallBack_Description[m_callback]; - CallBack_Description[m_callback] = 0; - CALLBACK_DeAllocate(m_callback); -} - -void CALLBACK_HandlerObject::Install(CallBack_Handler handler,Bitu type,const char* description){ - if(!installed) { - installed=true; - m_type=SETUP; - m_callback=CALLBACK_Allocate(); - CALLBACK_Setup(m_callback,handler,type,description); - } else E_Exit("Allready installed"); -} -void CALLBACK_HandlerObject::Install(CallBack_Handler handler,Bitu type,PhysPt addr,const char* description){ - if(!installed) { - installed=true; - m_type=SETUP; - m_callback=CALLBACK_Allocate(); - CALLBACK_Setup(m_callback,handler,type,addr,description); - } else E_Exit("Allready installed"); -} - -void CALLBACK_HandlerObject::Allocate(CallBack_Handler handler,const char* description) { - if(!installed) { - installed=true; - m_type=NONE; - m_callback=CALLBACK_Allocate(); - CALLBACK_SetDescription(m_callback,description); - CallBack_Handlers[m_callback]=handler; - } else E_Exit("Allready installed"); -} - -void CALLBACK_HandlerObject::Set_RealVec(Bit8u vec){ - if(!vectorhandler.installed) { - vectorhandler.installed=true; - vectorhandler.interrupt=vec; - RealSetVec(vec,Get_RealPointer(),vectorhandler.old_vector); - } else E_Exit ("double usage of vector handler"); -} - -void CALLBACK_Init(Section* sec) { - Bitu i; - for (i=0;i +#include + +#include "dosbox.h" +#include "callback.h" +#include "mem.h" +#include "cpu.h" + + +/* CallBack are located at 0xC800:0 + And they are 16 bytes each and you can define them to behave in certain ways like a + far return or and IRET +*/ + + +CallBack_Handler CallBack_Handlers[CB_MAX]; +static Bitu call_runint16,call_idle,call_default,call_runfar16; + +static Bitu illegal_handler(void) { + E_Exit("Illegal CallBack Called"); + return 1; +} + +/* when this returns -1 all CallBacks are taken */ +Bitu CALLBACK_Allocate(void) { + for (Bitu i=0;(i=CB_MAX) return false; + switch (type) { + case CB_RETF: + real_writeb((Bit16u)CB_SEG,(callback<<4),(Bit8u)0xFE); //GRP 4 + real_writeb((Bit16u)CB_SEG,(callback<<4)+1,(Bit8u)0x38); //Extra Callback instruction + real_writew((Bit16u)CB_SEG,(callback<<4)+2,callback); //The immediate word + real_writeb((Bit16u)CB_SEG,(callback<<4)+4,(Bit8u)0xCB); //A RETF Instruction + break; + case CB_IRET: + real_writeb((Bit16u)CB_SEG,(callback<<4),(Bit8u)0xFE); //GRP 4 + real_writeb((Bit16u)CB_SEG,(callback<<4)+1,(Bit8u)0x38); //Extra Callback instruction + real_writew((Bit16u)CB_SEG,(callback<<4)+2,callback); //The immediate word + real_writeb((Bit16u)CB_SEG,(callback<<4)+4,(Bit8u)0xCF); //An IRET Instruction + break; + default: + E_Exit("CALLBACK:Setup:Illegal type %d",type); + + } + CallBack_Handlers[callback]=handler; + return true; +} + +void CALLBACK_Init(void) { + Bitu i; + for (i=0;i= 0xc0 ) {GetEArb;inst(*earb,*rmrb,LoadRb,SaveRb);} \ + else {GetEAa;inst(eaa,*rmrb,LoadMb,SaveMb);} \ + } + +#define RMGbEb(inst) \ + { \ + GetRMrb; \ + if (rm >= 0xc0 ) {GetEArb;inst(*rmrb,*earb,LoadRb,SaveRb);} \ + else {GetEAa;inst(*rmrb,LoadMb(eaa),LoadRb,SaveRb);} \ + } + +#define RMEwGw(inst) \ + { \ + GetRMrw; \ + if (rm >= 0xc0 ) {GetEArw;inst(*earw,*rmrw,LoadRw,SaveRw);} \ + else {GetEAa;inst(eaa,*rmrw,LoadMw,SaveMw);} \ + } + +#define RMGwEw(inst) \ + { \ + GetRMrw; \ + if (rm >= 0xc0 ) {GetEArw;inst(*rmrw,*earw,LoadRw,SaveRw);} \ + else {GetEAa;inst(*rmrw,LoadMw(eaa),LoadRw,SaveRw);} \ + } + +#define RMEdGd(inst) \ + { \ + GetRMrd; \ + if (rm >= 0xc0 ) {GetEArd;inst(*eard,*rmrd,LoadRd,SaveRd);} \ + else {GetEAa;inst(eaa,*rmrd,LoadMd,SaveMd);} \ + } + +#define RMGdEd(inst) \ + { \ + GetRMrd; \ + if (rm >= 0xc0 ) {GetEArd;inst(*rmrd,*eard,LoadRd,SaveRd);} \ + else {GetEAa;inst(*rmrd,LoadMd(eaa),LoadRd,SaveRd);} \ + } + +#define ALIb(inst) \ + { inst(reg_al,Fetchb(),LoadRb,SaveRb)} + +#define AXIw(inst) \ + { inst(reg_ax,Fetchw(),LoadRw,SaveRw);} + +#define EAXId(inst) \ + { inst(reg_eax,Fetchd(),LoadRd,SaveRd);} diff --git a/src/cpu/core_16/instructions.h b/src/cpu/core_16/instructions.h new file mode 100644 index 0000000..d0a5fd9 --- /dev/null +++ b/src/cpu/core_16/instructions.h @@ -0,0 +1,593 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* Jumps */ + +/* + Could perhaps do some things with 8 and 16 bit operations like shifts, doing them in 32 bit regs +*/ + +#define JumpSIb(blah) \ + if (blah) { \ + ADDIPFAST(Fetchbs()); \ + } else { \ + ADDIPFAST(1); \ + } + +#define JumpSIw(blah) \ + if (blah) { \ + ADDIPFAST(Fetchws()); \ + } else { \ + ADDIPFAST(2); \ + } + +#define INTERRUPT(blah) \ + { \ + Bit8u new_num=blah; \ + SAVEIP; \ + Interrupt(new_num); \ + LOADIP; \ + } + + + +/* All Byte genereal instructions */ +#define ADDB(op1,op2,load,save) \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b+flags.var2.b; \ + save(op1,flags.result.b); \ + flags.type=t_ADDb; + +#define ADCB(op1,op2,load,save) \ + flags.oldcf=get_CF(); \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b+flags.var2.b+flags.oldcf; \ + save(op1,flags.result.b); \ + flags.type=t_ADCb; + +#define SBBB(op1,op2,load,save) \ + flags.oldcf=get_CF(); \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b-(flags.var2.b+flags.oldcf); \ + save(op1,flags.result.b); \ + flags.type=t_SBBb; + +#define SUBB(op1,op2,load,save) \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b-flags.var2.b; \ + save(op1,flags.result.b); \ + flags.type=t_SUBb; + +#define ORB(op1,op2,load,save) \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b | flags.var2.b; \ + save(op1,flags.result.b); \ + flags.type=t_ORb; + +#define XORB(op1,op2,load,save) \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b ^ flags.var2.b; \ + save(op1,flags.result.b); \ + flags.type=t_XORb; + +#define ANDB(op1,op2,load,save) \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b & flags.var2.b; \ + save(op1,flags.result.b); \ + flags.type=t_ANDb; + +#define CMPB(op1,op2,load,save) \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b-flags.var2.b; \ + flags.type=t_CMPb; + +#define TESTB(op1,op2,load,save) \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b & flags.var2.b; \ + flags.type=t_TESTb; + +/* All Word General instructions */ + +#define ADDW(op1,op2,load,save) \ + flags.var1.w=load(op1);flags.var2.w=op2; \ + flags.result.w=flags.var1.w+flags.var2.w; \ + save(op1,flags.result.w); \ + flags.type=t_ADDw; + +#define ADCW(op1,op2,load,save) \ + flags.oldcf=get_CF(); \ + flags.var1.w=load(op1);flags.var2.w=op2; \ + flags.result.w=flags.var1.w+flags.var2.w+flags.oldcf; \ + save(op1,flags.result.w); \ + flags.type=t_ADCw; + +#define SBBW(op1,op2,load,save) \ + flags.oldcf=get_CF(); \ + flags.var1.w=load(op1);flags.var2.w=op2; \ + flags.result.w=flags.var1.w-(flags.var2.w+flags.oldcf); \ + save(op1,flags.result.w); \ + flags.type=t_SBBw; + +#define SUBW(op1,op2,load,save) \ + flags.var1.w=load(op1);flags.var2.w=op2; \ + flags.result.w=flags.var1.w-flags.var2.w; \ + save(op1,flags.result.w); \ + flags.type=t_SUBw; + +#define ORW(op1,op2,load,save) \ + flags.var1.w=load(op1);flags.var2.w=op2; \ + flags.result.w=flags.var1.w | flags.var2.w; \ + save(op1,flags.result.w); \ + flags.type=t_ORw; + +#define XORW(op1,op2,load,save) \ + flags.var1.w=load(op1);flags.var2.w=op2; \ + flags.result.w=flags.var1.w ^ flags.var2.w; \ + save(op1,flags.result.w); \ + flags.type=t_XORw; + +#define ANDW(op1,op2,load,save) \ + flags.var1.w=load(op1);flags.var2.w=op2; \ + flags.result.w=flags.var1.w & flags.var2.w; \ + save(op1,flags.result.w); \ + flags.type=t_ANDw; + +#define CMPW(op1,op2,load,save) \ + flags.var1.w=load(op1);flags.var2.w=op2; \ + flags.result.w=flags.var1.w-flags.var2.w; \ + flags.type=t_CMPw; + +#define TESTW(op1,op2,load,save) \ + flags.var1.w=load(op1);flags.var2.w=op2; \ + flags.result.w=flags.var1.w & flags.var2.w; \ + flags.type=t_TESTw; + +/* All DWORD General Instructions */ + +#define ADDD(op1,op2,load,save) \ + flags.var1.d=load(op1);flags.var2.d=op2; \ + flags.result.d=flags.var1.d+flags.var2.d; \ + save(op1,flags.result.d); \ + flags.type=t_ADDd; + +#define ADCD(op1,op2,load,save) \ + flags.oldcf=get_CF(); \ + flags.var1.d=load(op1);flags.var2.d=op2; \ + flags.result.d=flags.var1.d+flags.var2.d+flags.oldcf; \ + save(op1,flags.result.d); \ + flags.type=t_ADCd; + +#define SBBD(op1,op2,load,save) \ + flags.oldcf=get_CF(); \ + flags.var1.d=load(op1);flags.var2.d=op2; \ + flags.result.d=flags.var1.d-(flags.var2.d+flags.oldcf); \ + save(op1,flags.result.d); \ + flags.type=t_SBBd; + +#define SUBD(op1,op2,load,save) \ + flags.var1.d=load(op1);flags.var2.d=op2; \ + flags.result.d=flags.var1.d-flags.var2.d; \ + save(op1,flags.result.d); \ + flags.type=t_SUBd; + +#define ORD(op1,op2,load,save) \ + flags.var1.d=load(op1);flags.var2.d=op2; \ + flags.result.d=flags.var1.d | flags.var2.d; \ + save(op1,flags.result.d); \ + flags.type=t_ORd; + +#define XORD(op1,op2,load,save) \ + flags.var1.d=load(op1);flags.var2.d=op2; \ + flags.result.d=flags.var1.d ^ flags.var2.d; \ + save(op1,flags.result.d); \ + flags.type=t_XORd; + +#define ANDD(op1,op2,load,save) \ + flags.var1.d=load(op1);flags.var2.d=op2; \ + flags.result.d=flags.var1.d & flags.var2.d; \ + save(op1,flags.result.d); \ + flags.type=t_ANDd; + +#define CMPD(op1,op2,load,save) \ + flags.var1.d=load(op1);flags.var2.d=op2; \ + flags.result.d=flags.var1.d-flags.var2.d; \ + flags.type=t_CMPd; + + +#define TESTD(op1,op2,load,save) \ + flags.var1.d=load(op1);flags.var2.d=op2; \ + flags.result.d=flags.var1.d & flags.var2.d; \ + flags.type=t_TESTd; + + + + +#define INCB(op1,load,save) \ + LoadCF;flags.result.b=load(op1)+1; \ + save(op1,flags.result.b); \ + flags.type=t_INCb; \ + +#define INCW(op1,load,save) \ + LoadCF;flags.result.w=load(op1)+1; \ + save(op1,flags.result.w); \ + flags.type=t_INCw; + +#define INCD(op1,load,save) \ + LoadCF;flags.result.d=load(op1)+1; \ + save(op1,flags.result.d); \ + flags.type=t_INCd; + +#define DECB(op1,load,save) \ + LoadCF;flags.result.b=load(op1)-1; \ + save(op1,flags.result.b); \ + flags.type=t_DECb; + +#define DECW(op1,load,save) \ + LoadCF;flags.result.w=load(op1)-1; \ + save(op1,flags.result.w); \ + flags.type=t_DECw; + +#define DECD(op1,load,save) \ + LoadCF;flags.result.d=load(op1)-1; \ + save(op1,flags.result.d); \ + flags.type=t_DECd; + +#define NOTDONE \ + SUBIP(1);E_Exit("CPU:Opcode %2X Unhandled",Fetchb()); + +#define NOTDONE66 \ + SUBIP(1);E_Exit("CPU:Opcode 66:%2X Unhandled",Fetchb()); + + +//TODO Maybe make this into a bigger split up because of the rm >=0xc0 this seems make it a bit slower +//TODO set Zero and Sign flag in one run +#define ROLB(op1,op2,load,save) \ + if (!(op2&0x07)) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.var1.b=load(op1);flags.var2.b=op2&0x07; \ + flags.result.b=(flags.var1.b << flags.var2.b) | \ + (flags.var1.b >> (8-flags.var2.b)); \ + save(op1,flags.result.b); \ + flags.type=t_ROLb; + +#define ROLW(op1,op2,load,save) \ + if (!(op2&0x0F)) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.var1.w=load(op1);flags.var2.b=op2&0x0F; \ + flags.result.w=(flags.var1.w << flags.var2.b) | \ + (flags.var1.w >> (16-flags.var2.b)); \ + save(op1,flags.result.w); \ + flags.type=t_ROLw; + + +#define ROLD(op1,op2,load,save) \ + if (!(op2&0x0F)) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.var1.d=load(op1);flags.var2.b=op2&0x0F; \ + flags.result.d=(flags.var1.d << flags.var2.b) | \ + (flags.var1.d >> (32-flags.var2.b)); \ + save(op1,flags.result.d); \ + flags.type=t_ROLd; + + +#define RORB(op1,op2,load,save) \ + if (!(op2&0x07)) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.var1.b=load(op1);flags.var2.b=op2&0x07; \ + flags.result.b=(flags.var1.b >> flags.var2.b) | \ + (flags.var1.b << (8-flags.var2.b)); \ + save(op1,flags.result.b); \ + flags.type=t_RORb; + + +#define RORW(op1,op2,load,save) \ + if (!(op2&0x0F)) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.var1.w=load(op1);flags.var2.b=op2&0x0F; \ + flags.result.w=(flags.var1.w >> flags.var2.b) | \ + (flags.var1.w << (16-flags.var2.b)); \ + save(op1,flags.result.w); \ + flags.type=t_RORw; + +#define RORD(op1,op2,load,save) \ + if (!(op2&0x0F)) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.var1.d=load(op1);flags.var2.b=op2&0x0F; \ + flags.result.d=(flags.var1.d >> flags.var2.b) | \ + (flags.var1.d << (32-flags.var2.b)); \ + save(op1,flags.result.d); \ + flags.type=t_RORd; + +#define RCLB(op1,op2,load,save) \ + if (!(op2%9)) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.cf=get_CF();flags.type=t_RCLb; \ + flags.var1.b=load(op1);flags.var2.b=op2%9; \ + flags.result.b=(flags.var1.b << flags.var2.b) | \ + (flags.cf << (flags.var2.b-1)) | \ + (flags.var1.b >> (9-flags.var2.b)); \ + save(op1,flags.result.b); + +#define RCLW(op1,op2,load,save) \ + if (!(op2%17)) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.cf=get_CF();flags.type=t_RCLw; \ + flags.var1.w=load(op1);flags.var2.b=op2%17; \ + flags.result.w=(flags.var1.w << flags.var2.b) | \ + (flags.cf << (flags.var2.b-1)) | \ + (flags.var1.w >> (17-flags.var2.b)); \ + save(op1,flags.result.w); + +#define RCLD(op1,op2,load,save) \ + if (!op2) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.cf=get_CF();flags.type=t_RCLd; \ + flags.var1.d=load(op1);flags.var2.b=op2; \ + if (flags.var2.b==1) { \ + flags.result.d=flags.var1.d << 1 | flags.cf; \ + } else { \ + flags.result.d=(flags.var1.d << flags.var2.b) | \ + (flags.cf << (flags.var2.b-1)) | \ + (flags.var1.d >> (33-flags.var2.b)); \ + } \ + save(op1,flags.result.d); + +#define RCRB(op1,op2,load,save) \ + if (!(op2%9)) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.cf=get_CF();flags.type=t_RCRb; \ + flags.var1.b=load(op1);flags.var2.b=op2%9; \ + flags.result.b=(flags.var1.b >> flags.var2.b) | \ + (flags.cf << (8-flags.var2.b)) | \ + (flags.var1.b << (9-flags.var2.b)); \ + save(op1,flags.result.b); + +#define RCRW(op1,op2,load,save) \ + if (!(op2%17)) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.cf=get_CF();flags.type=t_RCRw; \ + flags.var1.w=load(op1);flags.var2.b=op2%17; \ + flags.result.w=(flags.var1.w >> flags.var2.b) | \ + (flags.cf << (16-flags.var2.b)) | \ + (flags.var1.w << (17-flags.var2.b)); \ + save(op1,flags.result.w); + + +#define RCRD(op1,op2,load,save) \ + if (!op2) break; \ + flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ + flags.cf=get_CF();flags.type=t_RCRd; \ + flags.var1.d=load(op1);flags.var2.b=op2; \ + if (flags.var2.b==1) { \ + flags.result.d=flags.var1.d >> 1 | flags.cf << 31; \ + } else { \ + flags.result.d=(flags.var1.d >> flags.var2.b) | \ + (flags.cf << (32-flags.var2.b)) | \ + (flags.var1.d << (33-flags.var2.b)); \ + } \ + save(op1,flags.result.d); + +#define SHLB(op1,op2,load,save) \ + if (!op2) break; \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b << flags.var2.b; \ + save(op1,flags.result.b); \ + flags.type=t_SHLb; + +#define SHLW(op1,op2,load,save) \ + if (!op2) break; \ + flags.var1.w=load(op1);flags.var2.b=op2; \ + flags.result.w=flags.var1.w << flags.var2.b; \ + save(op1,flags.result.w); \ + flags.type=t_SHLw; + +#define SHLD(op1,op2,load,save) \ + if (!op2) break; \ + flags.var1.d=load(op1);flags.var2.b=op2; \ + flags.result.d=flags.var1.d << flags.var2.b; \ + save(op1,flags.result.d); \ + flags.type=t_SHLd; + +#define SHRB(op1,op2,load,save) \ + if (!op2) break; \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + flags.result.b=flags.var1.b >> flags.var2.b; \ + save(op1,flags.result.b); \ + flags.type=t_SHRb; + +#define SHRW(op1,op2,load,save) \ + if (!op2) break; \ + flags.var1.w=load(op1);flags.var2.b=op2; \ + flags.result.w=flags.var1.w >> flags.var2.b; \ + save(op1,flags.result.w); \ + flags.type=t_SHRw; + +#define SHRD(op1,op2,load,save) \ + if (!op2) break; \ + flags.var1.d=load(op1);flags.var2.b=op2; \ + flags.result.d=flags.var1.d >> flags.var2.b; \ + save(op1,flags.result.d); \ + flags.type=t_SHRd; + +#define SARB(op1,op2,load,save) \ + if (!op2) break; \ + flags.var1.b=load(op1);flags.var2.b=op2; \ + if (flags.var2.b>8) flags.var2.b=8; \ + if (flags.var1.b & 0x80) { \ + flags.result.b=(flags.var1.b >> flags.var2.b)| \ + (0xff << (8 - flags.var2.b)); \ + } else { \ + flags.result.b=flags.var1.b >> flags.var2.b; \ + } \ + save(op1,flags.result.b); \ + flags.type=t_SARb; + +#define SARW(op1,op2,load,save) \ + if (!op2) break; \ + flags.var1.w=load(op1);flags.var2.b=op2; \ + if (flags.var2.b>16) flags.var2.b=16; \ + if (flags.var1.w & 0x8000) { \ + flags.result.w=(flags.var1.w >> flags.var2.b)| \ + (0xffff << (16 - flags.var2.b)); \ + } else { \ + flags.result.w=flags.var1.w >> flags.var2.b; \ + } \ + save(op1,flags.result.w); \ + flags.type=t_SARw; + +#define SARD(op1,op2,load,save) \ + if (!op2) break; \ + flags.var1.d=load(op1);flags.var2.b=op2; \ + if (flags.var1.d & 0x80000000) { \ + flags.result.d=(flags.var1.d >> flags.var2.b)| \ + (0xffffffff << (32 - flags.var2.b)); \ + } else { \ + flags.result.d=flags.var1.d >> flags.var2.b; \ + } \ + save(op1,flags.result.d); \ + flags.type=t_SARd; + + + +#define GRP2B(blah) \ +{ \ + GetRM; \ + if (rm >= 0xc0) { \ + GetEArb; \ + Bit8u val=blah & 0x1f; \ + switch (rm&0x38) { \ + case 0x00:ROLB(*earb,val,LoadRb,SaveRb);break; \ + case 0x08:RORB(*earb,val,LoadRb,SaveRb);break; \ + case 0x10:RCLB(*earb,val,LoadRb,SaveRb);break; \ + case 0x18:RCRB(*earb,val,LoadRb,SaveRb);break; \ + case 0x20:/* SHL and SAL are the same */ \ + case 0x30:SHLB(*earb,val,LoadRb,SaveRb);break; \ + case 0x28:SHRB(*earb,val,LoadRb,SaveRb);break; \ + case 0x38:SARB(*earb,val,LoadRb,SaveRb);break; \ + } \ + } else { \ + GetEAa; \ + Bit8u val=blah & 0x1f; \ + switch (rm & 0x38) { \ + case 0x00:ROLB(eaa,val,LoadMb,SaveMb);break; \ + case 0x08:RORB(eaa,val,LoadMb,SaveMb);break; \ + case 0x10:RCLB(eaa,val,LoadMb,SaveMb);break; \ + case 0x18:RCRB(eaa,val,LoadMb,SaveMb);break; \ + case 0x20:/* SHL and SAL are the same */ \ + case 0x30:SHLB(eaa,val,LoadMb,SaveMb);break; \ + case 0x28:SHRB(eaa,val,LoadMb,SaveMb);break; \ + case 0x38:SARB(eaa,val,LoadMb,SaveMb);break; \ + } \ + } \ +} + + + +#define GRP2W(blah) \ +{ \ + GetRM; \ + if (rm >= 0xc0) { \ + GetEArw; \ + Bit8u val=blah & 0x1f; \ + switch (rm&0x38) { \ + case 0x00:ROLW(*earw,val,LoadRw,SaveRw);break; \ + case 0x08:RORW(*earw,val,LoadRw,SaveRw);break; \ + case 0x10:RCLW(*earw,val,LoadRw,SaveRw);break; \ + case 0x18:RCRW(*earw,val,LoadRw,SaveRw);break; \ + case 0x20:/* SHL and SAL are the same */ \ + case 0x30:SHLW(*earw,val,LoadRw,SaveRw);break; \ + case 0x28:SHRW(*earw,val,LoadRw,SaveRw);break; \ + case 0x38:SARW(*earw,val,LoadRw,SaveRw);break; \ + } \ + } else { \ + GetEAa; \ + Bit8u val=blah & 0x1f; \ + switch (rm & 0x38) { \ + case 0x00:ROLW(eaa,val,LoadMw,SaveMw);break; \ + case 0x08:RORW(eaa,val,LoadMw,SaveMw);break; \ + case 0x10:RCLW(eaa,val,LoadMw,SaveMw);break; \ + case 0x18:RCRW(eaa,val,LoadMw,SaveMw);break; \ + case 0x20:/* SHL and SAL are the same */ \ + case 0x30:SHLW(eaa,val,LoadMw,SaveMw);break; \ + case 0x28:SHRW(eaa,val,LoadMw,SaveMw);break; \ + case 0x38:SARW(eaa,val,LoadMw,SaveMw);break; \ + } \ + } \ +} + + +#define GRP2D(blah) \ +{ \ + GetRM; \ + if (rm >= 0xc0) { \ + GetEArd; \ + Bit8u val=blah & 0x1f; \ + switch (rm&0x38) { \ + case 0x00:ROLD(*eard,val,LoadRd,SaveRd);break; \ + case 0x08:RORD(*eard,val,LoadRd,SaveRd);break; \ + case 0x10:RCLD(*eard,val,LoadRd,SaveRd);break; \ + case 0x18:RCRD(*eard,val,LoadRd,SaveRd);break; \ + case 0x20:/* SHL and SAL are the same */ \ + case 0x30:SHLD(*eard,val,LoadRd,SaveRd);break; \ + case 0x28:SHRD(*eard,val,LoadRd,SaveRd);break; \ + case 0x38:SARD(*eard,val,LoadRd,SaveRd);break; \ + } \ + } else { \ + GetEAa; \ + Bit8u val=blah & 0x1f; \ + switch (rm & 0x38) { \ + case 0x00:ROLD(eaa,val,LoadMd,SaveMd);break; \ + case 0x08:RORD(eaa,val,LoadMd,SaveMd);break; \ + case 0x10:RCLD(eaa,val,LoadMd,SaveMd);break; \ + case 0x18:RCRD(eaa,val,LoadMd,SaveMd);break; \ + case 0x20:/* SHL and SAL are the same */ \ + case 0x30:SHLD(eaa,val,LoadMd,SaveMd);break; \ + case 0x28:SHRD(eaa,val,LoadMd,SaveMd);break; \ + case 0x38:SARD(eaa,val,LoadMd,SaveMd);break; \ + } \ + } \ +} + +/* let's hope bochs has it correct with the higher than 16 shifts */ +#define DSHLW(op1,op2,op3,load,save) \ + flags.var1.d=(load(op1)<<16)|op2;flags.var2.b=op3; \ + Bit32u tempd=flags.var1.d << flags.var2.b; \ + if (flags.var2.b>16) tempd |= (op2 << (flags.var2.b - 16)); \ + flags.result.w=(Bit16u)(tempd >> 16); \ + save(op1,flags.result.w); \ + flags.type=t_DSHLw; + +#define DSHLD(op1,op2,op3,load,save) \ + flags.var1.d=load(op1);flags.var2.b=op3; \ + flags.result.d=(flags.var1.d << flags.var2.b) | (op2 >> (32-flags.var2.b)); \ + save(op1,flags.result.d); \ + flags.type=t_DSHLd; + +#define DSHRW(op1,op2,op3,load,save) \ + flags.var1.d=(load(op1)<<16)|op2;flags.var2.b=op3; \ + Bit32u tempd=flags.var1.d >> flags.var2.b; \ + if (flags.var2.b>16) tempd |= (op2 << (32-flags.var2.b )); \ + flags.result.w=(Bit16u)(tempd); \ + save(op1,flags.result.w); \ + flags.type=t_DSHRw; + +#define DSHRD(op1,op2,op3,load,save) \ + flags.var1.d=load(op1);flags.var2.b=op3; \ + flags.result.d=(flags.var1.d >> flags.var2.b) | (op2 << (32-flags.var2.b)); \ + save(op1,flags.result.d); \ + flags.type=t_DSHRd; diff --git a/src/cpu/core_16/main.h b/src/cpu/core_16/main.h new file mode 100644 index 0000000..2e9dd4b --- /dev/null +++ b/src/cpu/core_16/main.h @@ -0,0 +1,1488 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +bool repcheck; +restart: + switch(Fetchb()) { + case 0x00: /* ADD Eb,Gb */ + RMEbGb(ADDB);break; + case 0x01: /* ADD Ew,Gw */ + RMEwGw(ADDW);break; + case 0x02: /* ADD Gb,Eb */ + RMGbEb(ADDB);break; + case 0x03: /* ADD Gw,Ew */ + RMGwEw(ADDW);break; + case 0x04: /* ADD AL,Ib */ + ALIb(ADDB);break; + case 0x05: /* ADD AX,Iw */ + AXIw(ADDW);break; + case 0x06: /* PUSH ES */ + Push_16(Segs[es].value);break; + case 0x07: /* POP ES */ + SetSegment_16(es,Pop_16());break; + case 0x08: /* OR Eb,Gb */ + RMEbGb(ORB);break; + case 0x09: /* OR Ew,Gw */ + RMEwGw(ORW);break; + case 0x0a: /* OR Gb,Eb */ + RMGbEb(ORB);break; + case 0x0b: /* OR Gw,Ew */ + RMGwEw(ORW);break; + case 0x0c: /* OR AL,Ib */ + ALIb(ORB);break; + case 0x0d: /* OR AX,Iw */ + AXIw(ORW);break; + case 0x0e: /* PUSH CS */ + Push_16(Segs[cs].value);break; + case 0x0f: /* 2 byte opcodes*/ + #include "prefix_of.h" + break; + case 0x10: /* ADC Eb,Gb */ + RMEbGb(ADCB);break; + case 0x11: /* ADC Ew,Gw */ + RMEwGw(ADCW);break; + case 0x12: /* ADC Gb,Eb */ + RMGbEb(ADCB);break; + case 0x13: /* ADC Gw,Ew */ + RMGwEw(ADCW);break; + case 0x14: /* ADC AL,Ib */ + ALIb(ADCB);break; + case 0x15: /* ADC AX,Iw */ + AXIw(ADCW);break; + case 0x16: /* PUSH SS */ + Push_16(Segs[ss].value);break; + case 0x17: /* POP SS */ + SetSegment_16(ss,Pop_16());break; + case 0x18: /* SBB Eb,Gb */ + RMEbGb(SBBB);break; + case 0x19: /* SBB Ew,Gw */ + RMEwGw(SBBW);break; + case 0x1a: /* SBB Gb,Eb */ + RMGbEb(SBBB);break; + case 0x1b: /* SBB Gw,Ew */ + RMGwEw(SBBW);break; + case 0x1c: /* SBB AL,Ib */ + ALIb(SBBB);break; + case 0x1d: /* SBB AX,Iw */ + AXIw(SBBW);break; + case 0x1e: /* PUSH DS */ + Push_16(Segs[ds].value);break; + case 0x1f: /* POP DS */ + SetSegment_16(ds,Pop_16());break; + case 0x20: /* AND Eb,Gb */ + RMEbGb(ANDB);break; + case 0x21: /* AND Ew,Gw */ + RMEwGw(ANDW);break; + case 0x22: /* AND Gb,Eb */ + RMGbEb(ANDB);break; + case 0x23: /* AND Gw,Ew */ + RMGwEw(ANDW);break; + case 0x24: /* AND AL,Ib */ + ALIb(ANDB);break; + case 0x25: /* AND AX,Iw */ + AXIw(ANDW);break; + case 0x26: /* SEG ES: */ + SegPrefix(es);break; + case 0x27: /* DAA */ + if (((reg_al & 0x0F)>0x09) || get_AF()) { + reg_al+=0x06; + flags.af=true; + } else { + flags.af=false; + } + flags.cf=get_CF(); + if ((reg_al > 0x9F) || flags.cf) { + reg_al+=0x60; + flags.cf=true; + } + flags.sf=(reg_al>>7)>0; + flags.zf=(reg_al==0); + flags.type=t_UNKNOWN; + break; + case 0x28: /* SUB Eb,Gb */ + RMEbGb(SUBB);break; + case 0x29: /* SUB Ew,Gw */ + RMEwGw(SUBW);break; + case 0x2a: /* SUB Gb,Eb */ + RMGbEb(SUBB);break; + case 0x2b: /* SUB Gw,Ew */ + RMGwEw(SUBW);break; + case 0x2c: /* SUB AL,Ib */ + ALIb(SUBB);break; + case 0x2d: /* SUB AX,Iw */ + AXIw(SUBW);break; + case 0x2e: /* SEG CS: */ + SegPrefix(cs);break; + case 0x2f: /* DAS */ + if (((reg_al & 0x0f) > 9) || get_AF()) { + reg_al-=6; + flags.af=true; + } else { + flags.af=false; + } + if ((reg_al>0x9f) || get_CF()) { + reg_al-=0x60; + flags.cf=true; + } else { + flags.cf=false; + } + flags.type=t_UNKNOWN; + break; + case 0x30: /* XOR Eb,Gb */ + RMEbGb(XORB);break; + case 0x31: /* XOR Ew,Gw */ + RMEwGw(XORW);break; + case 0x32: /* XOR Gb,Eb */ + RMGbEb(XORB);break; + case 0x33: /* XOR Gw,Ew */ + RMGwEw(XORW);break; + case 0x34: /* XOR AL,Ib */ + ALIb(XORB);break; + case 0x35: /* XOR AX,Iw */ + AXIw(XORW);break; + case 0x36: /* SEG SS: */ + SegPrefix(ss);break; + case 0x37: /* AAA */ + if (get_AF() || ((reg_al & 0xf) > 9)) + { + reg_al += 6; + reg_ah += 1; + flags.af=true; + flags.cf=true; + } else { + flags.af=false; + flags.cf=false; + } + reg_al &= 0x0F; + flags.type=t_UNKNOWN; + break; + case 0x38: /* CMP Eb,Gb */ + RMEbGb(CMPB);break; + case 0x39: /* CMP Ew,Gw */ + RMEwGw(CMPW);break; + case 0x3a: /* CMP Gb,Eb */ + RMGbEb(CMPB);break; + case 0x3b: /* CMP Gw,Ew */ + RMGwEw(CMPW);break; + case 0x3c: /* CMP AL,Ib */ + ALIb(CMPB);break; + case 0x3d: /* CMP AX,Iw */ + AXIw(CMPW);break; + case 0x3e: /* SEG DS: */ + SegPrefix(ds);break; + case 0x3f: /* AAS */ + if (((reg_al & 0x0f)>9) || get_AF()) { + reg_al=(reg_al-6) & 0xF; + reg_ah--; + flags.af=flags.cf=true; + } else { + flags.af=flags.cf=false; + } + flags.type=t_UNKNOWN; + break; + case 0x40: /* INC AX */ + INCW(reg_ax,LoadRw,SaveRw);break; + case 0x41: /* INC CX */ + INCW(reg_cx,LoadRw,SaveRw);break; + case 0x42: /* INC DX */ + INCW(reg_dx,LoadRw,SaveRw);break; + case 0x43: /* INC BX */ + INCW(reg_bx,LoadRw,SaveRw);break; + case 0x44: /* INC SP */ + INCW(reg_sp,LoadRw,SaveRw);break; + case 0x45: /* INC BP */ + INCW(reg_bp,LoadRw,SaveRw);break; + case 0x46: /* INC SI */ + INCW(reg_si,LoadRw,SaveRw);break; + case 0x47: /* INC DI */ + INCW(reg_di,LoadRw,SaveRw);break; + case 0x48: /* DEC AX */ + DECW(reg_ax,LoadRw,SaveRw);break; + case 0x49: /* DEC CX */ + DECW(reg_cx,LoadRw,SaveRw);break; + case 0x4a: /* DEC DX */ + DECW(reg_dx,LoadRw,SaveRw);break; + case 0x4b: /* DEC BX */ + DECW(reg_bx,LoadRw,SaveRw);break; + case 0x4c: /* DEC SP */ + DECW(reg_sp,LoadRw,SaveRw);break; + case 0x4d: /* DEC BP */ + DECW(reg_bp,LoadRw,SaveRw);break; + case 0x4e: /* DEC SI */ + DECW(reg_si,LoadRw,SaveRw);break; + case 0x4f: /* DEC DI */ + DECW(reg_di,LoadRw,SaveRw);break; + case 0x50: /* PUSH AX */ + Push_16(reg_ax);break; + case 0x51: /* PUSH CX */ + Push_16(reg_cx);break; + case 0x52: /* PUSH DX */ + Push_16(reg_dx);break; + case 0x53: /* PUSH BX */ + Push_16(reg_bx);break; + case 0x54: /* PUSH SP */ +//TODO Check if this is correct i think it's SP+2 or something + Push_16(reg_sp);break; + case 0x55: /* PUSH BP */ + Push_16(reg_bp);break; + case 0x56: /* PUSH SI */ + Push_16(reg_si);break; + case 0x57: /* PUSH DI */ + Push_16(reg_di);break; + case 0x58: /* POP AX */ + reg_ax=Pop_16();break; + case 0x59: /* POP CX */ + reg_cx=Pop_16();break; + case 0x5a: /* POP DX */ + reg_dx=Pop_16();break; + case 0x5b: /* POP BX */ + reg_bx=Pop_16();break; + case 0x5c: /* POP SP */ + reg_sp=Pop_16();break; + case 0x5d: /* POP BP */ + reg_bp=Pop_16();break; + case 0x5e: /* POP SI */ + reg_si=Pop_16();break; + case 0x5f: /* POP DI */ + reg_di=Pop_16();break; + case 0x60: /* PUSHA */ + Push_16(reg_ax);Push_16(reg_cx);Push_16(reg_dx);Push_16(reg_bx); + Push_16(reg_sp);Push_16(reg_bp);Push_16(reg_si);Push_16(reg_di); + break; + case 0x61: /* POPA */ + reg_di=Pop_16();reg_si=Pop_16();reg_bp=Pop_16();Pop_16();//Don't save SP + reg_bx=Pop_16();reg_dx=Pop_16();reg_cx=Pop_16();reg_ax=Pop_16(); + break; + case 0x62: /* BOUND */ + { + Bit16s bound_min, bound_max; + GetRMrw;GetEAa; + bound_min=LoadMw(eaa); + bound_max=LoadMw(eaa+2); + if ( (*rmrw < bound_min) || (*rmrw > bound_max) ) { + INTERRUPT(5); + } + } + break; + case 0x63: /* ARPL */ + NOTDONE;break; +#ifdef CPU_386 + case 0x64: /* SEG FS: */ + SegPrefix(fs);break; + case 0x65: /* SEG GS: */ + SegPrefix(gs);break; + case 0x66: /* Operand Size Prefix */ + #include "prefix_66.h" + break; + case 0x67: /* Address Size Prefix */ + NOTDONE; + break; +#endif + case 0x68: /* PUSH Iw */ + Push_16(Fetchw());break; + case 0x69: /* IMUL Gw,Ew,Iw */ + { + GetRMrw; + Bit32s res; + if (rm >= 0xc0 ) {GetEArw;res=(Bit32s)(*earws) * (Bit32s)Fetchws();} + else {GetEAa;res=(Bit32s)LoadMws(eaa) * (Bit32s)Fetchws();} + *rmrw=res & 0xFFFF; + flags.type=t_MUL; + if ((res> -32768) && (res<32767)) {flags.cf=false;flags.of=false;} + else {flags.cf=true;flags.of=true;} + break; + }; + case 0x6a: /* PUSH Ib */ + Push_16(Fetchbs());break; + case 0x6b: /* IMUL Gw,Ew,Ib */ + { + GetRMrw;Bit32s res; + if (rm >= 0xc0 ) {GetEArw;res=(Bit32s)(*earws) * (Bit32s)Fetchbs();} + else {GetEAa;res=(Bit32s)LoadMws(eaa) * (Bit32s)Fetchbs();} + *rmrw=res & 0xFFFF; + flags.type=t_MUL; + if ((res> -32768) && (res<32767)) {flags.cf=false;flags.of=false;} + else {flags.cf=true;flags.of=true;} + break; + } + case 0x6c: /* INSB */ + { + stringDI; + SaveMb(to,IO_Read(reg_dx)); + if (flags.df) reg_di--; else reg_di++; + break; + } + case 0x6d: /* INSW */ + { + stringDI; + SaveMb(to,IO_Read(reg_dx)); + SaveMb((to+1),IO_Read(reg_dx+1)); + if (flags.df) reg_di-=2; else reg_di+=2; + break; + } + case 0x6e: /* OUTSB */ + { + stringSI; + IO_Write(reg_dx,LoadMb(from)); + if (flags.df) reg_si--; else reg_si++; + break; + } + case 0x6f: /* OUTSW */ + { + stringSI; + IO_Write(reg_dx,LoadMb(from)); + IO_Write(reg_dx+1,LoadMb(from+1)); + if (flags.df) reg_si-=2; else reg_si+=2; + break; + } + case 0x70: /* JO */ + JumpSIb(get_OF());break; + case 0x71: /* JNO */ + JumpSIb(!get_OF());break; + case 0x72: /* JB */ + JumpSIb(get_CF());break; + case 0x73: /* JNB */ + JumpSIb(!get_CF());break; + case 0x74: /* JZ */ + JumpSIb(get_ZF());break; + case 0x75: /* JNZ */ + JumpSIb(!get_ZF()); break; + case 0x76: /* JBE */ + JumpSIb(get_CF() || get_ZF());break; + case 0x77: /* JNBE */ + JumpSIb(!get_CF() && !get_ZF());break; + case 0x78: /* JS */ + JumpSIb(get_SF());break; + case 0x79: /* JNS */ + JumpSIb(!get_SF());break; + case 0x7a: /* JP */ + JumpSIb(get_PF());break; + case 0x7b: /* JNP */ + JumpSIb(!get_PF());break; + case 0x7c: /* JL */ + JumpSIb(get_SF() != get_OF());break; + case 0x7d: /* JNL */ + JumpSIb(get_SF() == get_OF());break; + case 0x7e: /* JLE */ + JumpSIb(get_ZF() || (get_SF() != get_OF()));break; + case 0x7f: /* JNLE */ + JumpSIb((get_SF() == get_OF()) && !get_ZF());break; + case 0x80: /* Grpl Eb,Ib */ + case 0x82: /* Grpl Eb,Ib Mirror instruction*/ + { + GetRM; + if (rm>= 0xc0) { + GetEArb;Bit8u ib=Fetchb(); + switch (rm & 0x38) { + case 0x00:ADDB(*earb,ib,LoadRb,SaveRb);break; + case 0x08: ORB(*earb,ib,LoadRb,SaveRb);break; + case 0x10:ADCB(*earb,ib,LoadRb,SaveRb);break; + case 0x18:SBBB(*earb,ib,LoadRb,SaveRb);break; + case 0x20:ANDB(*earb,ib,LoadRb,SaveRb);break; + case 0x28:SUBB(*earb,ib,LoadRb,SaveRb);break; + case 0x30:XORB(*earb,ib,LoadRb,SaveRb);break; + case 0x38:CMPB(*earb,ib,LoadRb,SaveRb);break; + } + } else { + GetEAa;Bit8u ib=Fetchb(); + switch (rm & 0x38) { + case 0x00:ADDB(eaa,ib,LoadMb,SaveMb);break; + case 0x08: ORB(eaa,ib,LoadMb,SaveMb);break; + case 0x10:ADCB(eaa,ib,LoadMb,SaveMb);break; + case 0x18:SBBB(eaa,ib,LoadMb,SaveMb);break; + case 0x20:ANDB(eaa,ib,LoadMb,SaveMb);break; + case 0x28:SUBB(eaa,ib,LoadMb,SaveMb);break; + case 0x30:XORB(eaa,ib,LoadMb,SaveMb);break; + case 0x38:CMPB(eaa,ib,LoadMb,SaveMb);break; + } + } + break; + } + case 0x81: /* Grpl Ew,Iw */ + { + GetRM; + if (rm>= 0xc0) { + GetEArw;Bit16u iw=Fetchw(); + switch (rm & 0x38) { + case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break; + case 0x08: ORW(*earw,iw,LoadRw,SaveRw);break; + case 0x10:ADCW(*earw,iw,LoadRw,SaveRw);break; + case 0x18:SBBW(*earw,iw,LoadRw,SaveRw);break; + case 0x20:ANDW(*earw,iw,LoadRw,SaveRw);break; + case 0x28:SUBW(*earw,iw,LoadRw,SaveRw);break; + case 0x30:XORW(*earw,iw,LoadRw,SaveRw);break; + case 0x38:CMPW(*earw,iw,LoadRw,SaveRw);break; + } + } else { + GetEAa;Bit16u iw=Fetchw(); + switch (rm & 0x38) { + case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break; + case 0x08: ORW(eaa,iw,LoadMw,SaveMw);break; + case 0x10:ADCW(eaa,iw,LoadMw,SaveMw);break; + case 0x18:SBBW(eaa,iw,LoadMw,SaveMw);break; + case 0x20:ANDW(eaa,iw,LoadMw,SaveMw);break; + case 0x28:SUBW(eaa,iw,LoadMw,SaveMw);break; + case 0x30:XORW(eaa,iw,LoadMw,SaveMw);break; + case 0x38:CMPW(eaa,iw,LoadMw,SaveMw);break; + } + } + break; + } + case 0x83: /* Grpl Ew,Ix */ + { + GetRM; + if (rm>= 0xc0) { + GetEArw;Bit16u iw=(Bit16s)Fetchbs(); + switch (rm & 0x38) { + case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break; + case 0x08: ORW(*earw,iw,LoadRw,SaveRw);break; + case 0x10:ADCW(*earw,iw,LoadRw,SaveRw);break; + case 0x18:SBBW(*earw,iw,LoadRw,SaveRw);break; + case 0x20:ANDW(*earw,iw,LoadRw,SaveRw);break; + case 0x28:SUBW(*earw,iw,LoadRw,SaveRw);break; + case 0x30:XORW(*earw,iw,LoadRw,SaveRw);break; + case 0x38:CMPW(*earw,iw,LoadRw,SaveRw);break; + } + } else { + GetEAa;Bit16u iw=(Bit16s)Fetchbs(); + switch (rm & 0x38) { + case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break; + case 0x08: ORW(eaa,iw,LoadMw,SaveMw);break; + case 0x10:ADCW(eaa,iw,LoadMw,SaveMw);break; + case 0x18:SBBW(eaa,iw,LoadMw,SaveMw);break; + case 0x20:ANDW(eaa,iw,LoadMw,SaveMw);break; + case 0x28:SUBW(eaa,iw,LoadMw,SaveMw);break; + case 0x30:XORW(eaa,iw,LoadMw,SaveMw);break; + case 0x38:CMPW(eaa,iw,LoadMw,SaveMw);break; + } + } + break; + } + case 0x84: /* TEST Eb,Gb */ + RMEbGb(TESTB);break; + case 0x85: /* TEST Ew,Gw */ + RMEwGw(TESTW);break; + case 0x86: /* XCHG Eb,Gb */ + { + GetRMrb;Bit8u oldrmrb=*rmrb; + if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;*earb=oldrmrb;} + else {GetEAa;*rmrb=LoadMb(eaa);SaveMb(eaa,oldrmrb);} + break; + } + case 0x87: /* XCHG Ew,Gw */ + { + GetRMrw;Bit16u oldrmrw=*rmrw; + if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;*earw=oldrmrw;} + else {GetEAa;*rmrw=LoadMw(eaa);SaveMw(eaa,oldrmrw);} + break; + } + case 0x88: /* MOV Eb,Gb */ + { + GetRMrb; + if (rm >= 0xc0 ) {GetEArb;*earb=*rmrb;} + else {GetEAa;SaveMb(eaa,*rmrb);} + break; + } + case 0x89: /* MOV Ew,Gw */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArw;*earw=*rmrw;} + else {GetEAa;SaveMw(eaa,*rmrw);} + break; + } + case 0x8a: /* MOV Gb,Eb */ + { + GetRMrb; + if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;} + else {GetEAa;*rmrb=LoadMb(eaa);} + break; + } + case 0x8b: /* MOV Gw,Ew */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;} + else {GetEAa;*rmrw=LoadMw(eaa);} + break; + } + case 0x8c: /* Mov Ew,Sw */ + { + GetRM;Bit16u val; + switch (rm & 0x38) { + case 0x00: /* MOV Ew,ES */ + val=Segs[es].value;break; + case 0x08: /* MOV Ew,CS */ + val=Segs[cs].value;break; + case 0x10: /* MOV Ew,SS */ + val=Segs[ss].value;break; + case 0x18: /* MOV Ew,DS */ + val=Segs[ds].value;break; + case 0x20: /* MOV Ew,FS */ + val=Segs[fs].value;break; + case 0x28: /* MOV Ew,GS */ + val=Segs[gs].value;break; + default: + val=0; + E_Exit("CPU:8c:Illegal RM Byte"); + } + if (rm >= 0xc0 ) {GetEArw;*earw=val;} + else {GetEAa;SaveMw(eaa,val);} + break; + } + case 0x8d: /* LEA */ + { + GetRMrw; + switch (rm & 0xC7) { + case 0x00:*rmrw=reg_bx+reg_si;break; + case 0x01:*rmrw=reg_bx+reg_di;break; + case 0x02:*rmrw=reg_bp+reg_si;break; + case 0x03:*rmrw=reg_bp+reg_di;break; + case 0x04:*rmrw=reg_si;break; + case 0x05:*rmrw=reg_di;break; + case 0x06:*rmrw=Fetchw();break; + case 0x07:*rmrw=reg_bx;break; + case 0x40:*rmrw=reg_bx+reg_si+Fetchbs();break; + case 0x41:*rmrw=reg_bx+reg_di+Fetchbs();break; + case 0x42:*rmrw=reg_bp+reg_si+Fetchbs();break; + case 0x43:*rmrw=reg_bp+reg_di+Fetchbs();break; + case 0x44:*rmrw=reg_si+Fetchbs();break; + case 0x45:*rmrw=reg_di+Fetchbs();break; + case 0x46:*rmrw=reg_bp+Fetchbs();break; + case 0x47:*rmrw=reg_bx+Fetchbs();break; + case 0x80:*rmrw=reg_bx+reg_si+Fetchw();break; + case 0x81:*rmrw=reg_bx+reg_di+Fetchw();break; + case 0x82:*rmrw=reg_bp+reg_si+Fetchw();break; + case 0x83:*rmrw=reg_bp+reg_di+Fetchw();break; + case 0x84:*rmrw=reg_si+Fetchw();break; + case 0x85:*rmrw=reg_di+Fetchw();break; + case 0x86:*rmrw=reg_bp+Fetchw();break; + case 0x87:*rmrw=reg_bx+Fetchw();break; + default: + E_Exit("CPU:8d:Illegal LEA RM Byte"); + } + break; + } + case 0x8e: /* MOV Sw,Ew */ + { + GetRM;Bit16u val; + if (rm >= 0xc0 ) {GetEArw;val=*earw;} + else {GetEAa;val=LoadMw(eaa);} + switch (rm & 0x38) { + case 0x00: /* MOV ES,Ew */ + SetSegment_16(es,val);break; + case 0x08: /* MOV CS,Ew Illegal*/ + E_Exit("CPU:Illegal MOV CS Call"); + break; + case 0x10: /* MOV SS,Ew */ + SetSegment_16(ss,val);break; + case 0x18: /* MOV DS,Ew */ + SetSegment_16(ds,val);break; + case 0x20: /* MOV FS,Ew */ + SetSegment_16(fs,val);break; + case 0x28: /* MOV GS,Ew */ + SetSegment_16(gs,val);break; + default: + E_Exit("CPU:8e:Illegal RM Byte"); + } + break; + } + case 0x8f: /* POP Ew */ + { + GetRM; + if (rm >= 0xc0 ) {GetEArw;*earw=Pop_16();} + else {GetEAa;SaveMw(eaa,Pop_16());} + break; + } + case 0x90: /* NOP */ + break; + case 0x91: /* XCHG CX,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_cx;reg_cx=temp; } + break; + case 0x92: /* XCHG DX,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_dx;reg_dx=temp; } + break; + case 0x93: /* XCHG BX,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_bx;reg_bx=temp; } + break; + case 0x94: /* XCHG SP,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_sp;reg_sp=temp; } + break; + case 0x95: /* XCHG BP,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_bp;reg_bp=temp; } + break; + case 0x96: /* XCHG SI,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_si;reg_si=temp; } + break; + case 0x97: /* XCHG DI,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_di;reg_di=temp; } + break; + case 0x98: /* CBW */ + reg_ax=(Bit8s)reg_al;break; + case 0x99: /* CWD */ + if (reg_ax & 0x8000) reg_dx=0xffff; + else reg_dx=0; + break; + case 0x9a: /* CALL Ap */ + { + Bit16u newip=Fetchw();Bit16u newcs=Fetchw(); + Push_16(Segs[cs].value);Push_16(GETIP); + SetSegment_16(cs,newcs);SETIP(newip); + break; + } + case 0x9b: /* WAIT */ + break; /* No waiting here */ + case 0x9c: /* PUSHF */ + { + Bit16u pflags= + (get_CF() << 0) | (get_PF() << 2) | (get_AF() << 4) | + (get_ZF() << 6) | (get_SF() << 7) | (flags.tf << 8) | + (flags.intf << 9) |(flags.df << 10) | (get_OF() << 11) | + (flags.io << 12) | (flags.nt <<14); + Push_16(pflags); + break; + } + case 0x9d: /* POPF */ + { + Bit16u bits=Pop_16(); + Save_Flagsw(bits); + break; + } + case 0x9e: /* SAHF */ + flags.of =get_OF(); + flags.type=t_UNKNOWN; + flags.cf =(reg_ah & 0x001)!=0;flags.pf =(reg_ah & 0x004)!=0; + flags.af =(reg_ah & 0x010)!=0;flags.zf =(reg_ah & 0x040)!=0; + flags.sf =(reg_ah & 0x080)!=0; + break; + case 0x9f: /* LAHF */ + { + reg_ah=(get_CF() << 0) | (get_PF() << 2) | (get_AF() << 4) | + (get_ZF() << 6) | (get_SF() << 7); + break; + } + case 0xa0: /* MOV AL,Ob */ + if (segprefix_on) { + reg_al=LoadMb(segprefix_base+Fetchw()); + SegPrefixReset; + } else { + reg_al=LoadMb(SegBase(ds)+Fetchw()); + } + break; + case 0xa1: /* MOV AX,Ow */ + if (segprefix_on) { + reg_ax=LoadMw(segprefix_base+Fetchw()); + SegPrefixReset; + } else { + reg_ax=LoadMw(SegBase(ds)+Fetchw()); + } + break; + case 0xa2: /* MOV Ob,AL */ + if (segprefix_on) { + SaveMb((segprefix_base+Fetchw()),reg_al); + SegPrefixReset; + } else { + SaveMb((SegBase(ds)+Fetchw()),reg_al); + } + break; + case 0xa3: /* MOV Ow,AX */ + if (segprefix_on) { + SaveMw((segprefix_base+Fetchw()),reg_ax); + SegPrefixReset; + } else { + SaveMw((SegBase(ds)+Fetchw()),reg_ax); + } + break; + case 0xa4: /* MOVSB */ + { + stringSI;stringDI; + SaveMb(to,LoadMb(from));; + if (flags.df) { reg_si--;reg_di--; } + else {reg_si++;reg_di++;} + break; + } + case 0xa5: /* MOVSW */ + { + stringSI;stringDI; + SaveMw(to,LoadMw(from)); + if (flags.df) { reg_si-=2;reg_di-=2; } + else {reg_si+=2;reg_di+=2;} + break; + } + case 0xa6: /* CMPSB */ + { + stringSI;stringDI; + CMPB(from,LoadMb(to),LoadMb,0); + if (flags.df) { reg_si--;reg_di--; } + else {reg_si++;reg_di++;} + break; + } + case 0xa7: /* CMPSW */ + { + stringSI;stringDI; + CMPW(from,LoadMw(to),LoadMw,0); + if (flags.df) { reg_si-=2;reg_di-=2; } + else {reg_si+=2;reg_di+=2;} + break; + } + case 0xa8: /* TEST AL,Ib */ + ALIb(TESTB);break; + case 0xa9: /* TEST AX,Iw */ + AXIw(TESTW);break; + case 0xaa: /* STOSB */ + { + stringDI; + SaveMb(to,reg_al); + if (flags.df) { reg_di--; } + else {reg_di++;} + break; + } + case 0xab: /* STOSW */ + { + stringDI; + SaveMw(to,reg_ax); + if (flags.df) { reg_di-=2; } + else {reg_di+=2;} + break; + } + case 0xac: /* LODSB */ + { + stringSI; + reg_al=LoadMb(from); + if (flags.df) { reg_si--; } + else {reg_si++;} + break; + } + case 0xad: /* LODSW */ + { + stringSI; + reg_ax=LoadMw(from); + if (flags.df) { reg_si-=2;} + else {reg_si+=2;} + break; + } + case 0xae: /* SCASB */ + { + stringDI; + CMPB(reg_al,LoadMb(to),LoadRb,0); + if (flags.df) { reg_di--; } + else {reg_di++;} + break; + } + case 0xaf: /* SCASW */ + { + stringDI; + CMPW(reg_ax,LoadMw(to),LoadRw,0); + if (flags.df) { reg_di-=2; } + else {reg_di+=2;} + break; + } + case 0xb0: /* MOV AL,Ib */ + reg_al=Fetchb();break; + case 0xb1: /* MOV CL,Ib */ + reg_cl=Fetchb();break; + case 0xb2: /* MOV DL,Ib */ + reg_dl=Fetchb();break; + case 0xb3: /* MOV BL,Ib */ + reg_bl=Fetchb();break; + case 0xb4: /* MOV AH,Ib */ + reg_ah=Fetchb();break; + case 0xb5: /* MOV CH,Ib */ + reg_ch=Fetchb();break; + case 0xb6: /* MOV DH,Ib */ + reg_dh=Fetchb();break; + case 0xb7: /* MOV BH,Ib */ + reg_bh=Fetchb();break; + case 0xb8: /* MOV AX,Iw */ + reg_ax=Fetchw();break; + case 0xb9: /* MOV CX,Iw */ + reg_cx=Fetchw();break; + case 0xba: /* MOV DX,Iw */ + reg_dx=Fetchw();break; + case 0xbb: /* MOV BX,Iw */ + reg_bx=Fetchw();break; + case 0xbc: /* MOV SP,Iw */ + reg_sp=Fetchw();break; + case 0xbd: /* MOV BP.Iw */ + reg_bp=Fetchw();break; + case 0xbe: /* MOV SI,Iw */ + reg_si=Fetchw();break; + case 0xbf: /* MOV DI,Iw */ + reg_di=Fetchw();break; + case 0xc0: /* GRP2 Eb,Ib */ + GRP2B(Fetchb());break; + case 0xc1: /* GRP2 Ew,Ib */ + GRP2W(Fetchb());break; + case 0xc2: /* RETN Iw */ + { + Bit16u addsp=Fetchw(); + SETIP(Pop_16());reg_sp+=addsp; + break; + } + case 0xc3: /* RETN */ + SETIP(Pop_16()); + break; + case 0xc4: /* LES */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);SetSegment_16(es,LoadMw(eaa+2)); + break; + } + case 0xc5: /* LDS */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);SetSegment_16(ds,LoadMw(eaa+2)); + break; + } + case 0xc6: /* MOV Eb,Ib */ + { + GetRM; + if (rm>0xc0) {GetEArb;*earb=Fetchb();} + else {GetEAa;SaveMb(eaa,Fetchb());} + break; + } + case 0xc7: /* MOV EW,Iw */ + { + GetRM; + if (rm>0xc0) {GetEArw;*earw=Fetchw();} + else {GetEAa;SaveMw(eaa,Fetchw());} + break; + } + case 0xc8: /* ENTER Iw,Ib */ + { + Bit16u bytes=Fetchw();Bit8u level=Fetchb(); + Push_16(reg_bp);reg_bp=reg_sp;reg_sp-=bytes; + EAPoint reader=SegBase(ss)+reg_bp; + for (Bit8u i=1;i 0; + flags.zf=(reg_ax == 0); + //TODO PF + flags.pf=0; + } + break; + case 0xd5: /* AAD Ib */ + reg_al=reg_ah*Fetchb()+reg_al; + reg_ah=0; + flags.cf=(reg_al>=0x80); + flags.zf=(reg_al==0); + //TODO PF + flags.type=t_UNKNOWN; + break; + case 0xd6: /* Not in intel specs */ + NOTDONE; + break; + case 0xd7: /* XLAT */ + if (segprefix_on) { + reg_al=LoadMb(segprefix_base+(Bit16u)(reg_bx+reg_al)); + SegPrefixReset; + } else { + reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al)); + } + break; + case 0xd8: /* FPU ESC 0 */ + case 0xd9: /* FPU ESC 1 */ + case 0xda: /* FPU ESC 2 */ + case 0xdb: /* FPU ESC 3 */ + case 0xdc: /* FPU ESC 4 */ + case 0xdd: /* FPU ESC 5 */ + case 0xde: /* FPU ESC 6 */ + case 0xdf: /* FPU ESC 7 */ + { + Bit8u rm=Fetchb(); + if (rm>=0xc0) { + FPU_ESC0_Normal(rm); + } else { + GetEAa;FPU_ESC0_EA(rm,eaa); + } + break; + } + + break; + case 0xe0: /* LOOPNZ */ + if ((--reg_cx) && !get_ZF()) ADDIPFAST(Fetchbs()); + else ADDIPFAST(1); + break; + case 0xe1: /* LOOPZ */ + if ((--reg_cx) && get_ZF()) ADDIPFAST(Fetchbs()); + else ADDIPFAST(1); + break; + case 0xe2: /* LOOP */ + if ((--reg_cx)) ADDIPFAST(Fetchbs()); + else ADDIPFAST(1); + break; + case 0xe3: /* JCXZ */ + if (!reg_cx) ADDIPFAST(Fetchbs()); + else ADDIPFAST(1); + break; + case 0xe4: /* IN AL,Ib */ + { Bit16u port=Fetchb();reg_al=IO_Read(port);} + break; + case 0xe5: /* IN AX,Ib */ + { Bit16u port=Fetchb();reg_al=IO_Read(port);reg_ah=IO_Read(port+1);} + break; + case 0xe6: /* OUT Ib,AL */ + { Bit16u port=Fetchb();IO_Write(port,reg_al);} + break; + case 0xe7: /* OUT Ib,AX */ + { Bit16u port=Fetchb();IO_Write(port,reg_al);IO_Write(port+1,reg_ah);} + break; + case 0xe8: /* CALL Jw */ + { + Bit16s newip=Fetchws(); + Push_16(GETIP); + ADDIP(newip); + break; + } + case 0xe9: /* JMP Jw */ + ADDIP(Fetchws()); + break; + case 0xea: /* JMP Ap */ + { + Bit16u newip=Fetchw(); + Bit16u newcs=Fetchw(); + SetSegment_16(cs,newcs); + SETIP(newip); + break; + } + case 0xeb: /* JMP Jb*/ + ADDIPFAST(Fetchbs()); + break; + case 0xec: /* IN AL,DX */ + reg_al=IO_Read(reg_dx); + break; + case 0xed: /* IN AX,DX */ + reg_al=IO_Read(reg_dx); + reg_ah=IO_Read(reg_dx+1); + break; + case 0xee: /* OUT DX,AL */ + IO_Write(reg_dx,reg_al); + break; + case 0xef: /* OUT DX,AX */ + IO_Write(reg_dx,reg_al); + IO_Write(reg_dx+1,reg_ah); + break; + case 0xf0: /* LOCK */ + LOG_ERROR("CPU:LOCK"); + break; + case 0xf1: /* Weird call undocumented */ + E_Exit("CPU:F1:Not Handled"); + break; + case 0xf2: /* REPNZ */ + repcheck=false; + goto repstart; + case 0xf3: /* REPZ */ + repcheck=true; + repstart: + { + EAPoint to=SegBase(es); + EAPoint from; + if (segprefix_on) { + from=(segprefix_base); + SegPrefixReset; + } else { + from=SegBase(ds); + } + Bit16s direct; + if (flags.df) direct=-1; + else direct=1; + reploop: + Bit8u repcode=Fetchb(); + switch (repcode) { + case 0x26: /* ES Prefix */ + from=SegBase(es); + goto reploop; + case 0x2e: /* CS Prefix */ + from=SegBase(cs); + goto reploop; + case 0x36: /* SS Prefix */ + from=SegBase(ss); + goto reploop; + case 0x3e: /* DS Prefix */ + from=SegBase(ds); + goto reploop; +#ifdef CPU_386 + case 0x66: + Rep_66(direct,from,to); + break; +#endif + + case 0x6c: /* REP INSB */ + { + for (Bit32u temp=reg_cx;temp>0;temp--) { + SaveMb(to,IO_Read(reg_dx)); + to+=direct; + }; + reg_di+=Bit16s(reg_cx*direct);reg_cx=0; + break; + } + case 0x6d: /* REP INSW */ + { + for (Bit32u temp=reg_cx;temp>0;temp--) { + SaveMb(to,IO_Read(reg_dx)); + SaveMb((to+1),IO_Read(reg_dx+1)); + to+=direct*2; + } + reg_di+=Bit16s(reg_cx*direct*2);reg_cx=0; + break; + } + case 0x6e: /* REP OUTSB */ + for (;reg_cx>0;reg_cx--) { + IO_Write(reg_dx,LoadMb(from+reg_si)); + reg_si+=direct; + } + break; + case 0x6f: /* REP OUTSW */ + for (;reg_cx>0;reg_cx--) { + IO_Write(reg_dx,LoadMb(from+reg_si)); + IO_Write(reg_dx+1,LoadMb(from+reg_si+1)); + reg_si+=direct*2; + } + break; + case 0xa4: /* REP MOVSB */ + for (;reg_cx>0;reg_cx--) { + SaveMb(to+reg_di,LoadMb(from+reg_si)); + reg_di+=direct; + reg_si+=direct; + } + break; + case 0xa5: /* REP MOVSW */ + for (;reg_cx>0;reg_cx--) { + SaveMw(to+reg_di,LoadMw(from+reg_si)); + reg_di+=direct*2; + reg_si+=direct*2; + } + break; + case 0xa6: /* REP CMPSB */ + if (!reg_cx) break; + for (;reg_cx>0;) { + reg_cx--; + if ((LoadMb(from+reg_si)==LoadMb(to+reg_di))!=repcheck) { + reg_di+=direct; + reg_si+=direct; + break; + } + reg_di+=direct; + reg_si+=direct; + } + CMPB(from+(reg_si-direct),LoadMb(to+(reg_di-direct)),LoadMb,0); + break; + case 0xa7: /* REP CMPSW */ + if (!reg_cx) break; + for (;reg_cx>0;) { + reg_cx--; + if ((LoadMw(from+reg_si)==LoadMw(to+reg_di))!=repcheck) { + reg_di+=direct*2; + reg_si+=direct*2; + break; + } + reg_di+=direct*2; + reg_si+=direct*2; + } + CMPW(from+(reg_si-direct*2),LoadMw(to+(reg_di-direct*2)),LoadMw,0); + break; + case 0xaa: /* REP STOSB */ + for (;reg_cx>0;reg_cx--) { + SaveMb(to+reg_di,reg_al); + reg_di+=direct; + } + break; + case 0xab: /* REP STOSW */ + for (;reg_cx>0;reg_cx--) { + SaveMw(to+reg_di,reg_ax); + reg_di+=direct*2; + } + break; + case 0xac: /* REP LODSB */ + for (;reg_cx>0;reg_cx--) { + reg_al=LoadMb(from+reg_si); + reg_si+=direct; + } + break; + case 0xad: /* REP LODSW */ + for (;reg_cx>0;reg_cx--) { + reg_ax=LoadMw(from+reg_si); + reg_si+=direct*2; + } + break; + case 0xae: /* REP SCASB */ + if (!reg_cx) break; + for (;reg_cx>0;) { + reg_cx--; + if ((reg_al==LoadMb(to+reg_di))!=repcheck) { + reg_di+=direct; + break; + } + reg_di+=direct; + } + CMPB(reg_al,LoadMb(to+(reg_di-direct)),LoadRb,0); + break; + case 0xaf: /* REP SCASW */ + if (!reg_cx) break; + for (;reg_cx>0;) { + reg_cx--; + if ((reg_ax==LoadMw(to+reg_di))!=repcheck) { + reg_di+=direct*2; + break; + } + reg_di+=direct*2; + } + CMPW(reg_ax,LoadMw(to+(reg_di-direct*2)),LoadRw,0); + break; + default: + E_Exit("Illegal REP prefix %2X",repcode); + } + break; + } + case 0xf4: /* HLT */ + break; + case 0xf5: /* CMC */ + flags.cf=!get_CF(); + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + break; + case 0xf6: /* GRP3 Eb(,Ib) */ + { + GetRM; + switch (rm & 0x38) { + case 0x00: /* TEST Eb,Ib */ + case 0x08: /* TEST Eb,Ib Undocumented*/ + { + if (rm >= 0xc0 ) {GetEArb;TESTB(*earb,Fetchb(),LoadRb,0)} + else {GetEAa;TESTB(eaa,Fetchb(),LoadMb,0);} + break; + } + case 0x10: /* NOT Eb */ + { + if (rm >= 0xc0 ) {GetEArb;*earb=~*earb;} + else {GetEAa;SaveMb(eaa,~LoadMb(eaa));} + break; + } + case 0x18: /* NEG Eb */ + { + flags.type=t_NEGb; + if (rm >= 0xc0 ) { + GetEArb;flags.var1.b=*earb;flags.result.b=0-flags.var1.b; + *earb=flags.result.b; + } else { + GetEAa;flags.var1.b=LoadMb(eaa);flags.result.b=0-flags.var1.b; + SaveMb(eaa,flags.result.b); + } + break; + } + case 0x20: /* MUL AL,Eb */ + { + flags.type=t_MUL; + if (rm >= 0xc0 ) {GetEArb;reg_ax=reg_al * (*earb);} + else {GetEAa;reg_ax=reg_al * LoadMb(eaa);} + flags.cf=flags.of=((reg_ax & 0xff00) !=0); + break; + } + case 0x28: /* IMUL AL,Eb */ + { + flags.type=t_MUL; + if (rm >= 0xc0 ) {GetEArb;reg_ax=(Bit8s)reg_al * (*earbs);} + else {GetEAa;reg_ax=((Bit8s)reg_al) * LoadMbs(eaa);} + flags.cf=flags.of=!((reg_ax & 0xff80)==0xff80 || (reg_ax & 0xff80)==0x0000); + break; + } + case 0x30: /* DIV Eb */ + { +// flags.type=t_DIV; + Bit8u val; + if (rm >= 0xc0 ) {GetEArb;val=*earb;} + else {GetEAa;val=LoadMb(eaa);} + if (val==0) {INTERRUPT(0);break;} + Bit16u quotientu=reg_ax / val; + reg_ah=(Bit8u)(reg_ax % val); + reg_al=quotientu & 0xff; + if (quotientu!=reg_al) + INTERRUPT(0); + break; + } + case 0x38: /* IDIV Eb */ + { +// flags.type=t_DIV; + Bit8s val; + if (rm >= 0xc0 ) {GetEArb;val=*earbs;} + else {GetEAa;val=LoadMbs(eaa);} + if (val==0) {INTERRUPT(0);break;} + Bit16s quotients=((Bit16s)reg_ax) / val; + reg_ah=(Bit8s)(((Bit16s)reg_ax) % val); + reg_al=quotients & 0xff; + if (quotients!=(Bit8s)reg_al) + INTERRUPT(0); + break; + } + } + break;} + case 0xf7: /* GRP3 Ew(,Iw) */ + { GetRM; + switch (rm & 0x38) { + case 0x00: /* TEST Ew,Iw */ + case 0x08: /* TEST Ew,Iw Undocumented*/ + { + if (rm >= 0xc0 ) {GetEArw;TESTW(*earw,Fetchw(),LoadRw,SaveRw);} + else {GetEAa;TESTW(eaa,Fetchw(),LoadMw,SaveMw);} + break; + } + case 0x10: /* NOT Ew */ + { + if (rm >= 0xc0 ) {GetEArw;*earw=~*earw;} + else {GetEAa;SaveMw(eaa,~LoadMw(eaa));} + break; + } + case 0x18: /* NEG Ew */ + { + flags.type=t_NEGw; + if (rm >= 0xc0 ) { + GetEArw;flags.var1.w=*earw;flags.result.w=0-flags.var1.w; + *earw=flags.result.w; + } else { + GetEAa;flags.var1.w=LoadMw(eaa);flags.result.w=0-flags.var1.w; + SaveMw(eaa,flags.result.w); + } + break; + } + case 0x20: /* MUL AX,Ew */ + { + flags.type=t_MUL;Bit32u tempu; + if (rm >= 0xc0 ) {GetEArw;tempu=reg_ax * (*earw);} + else {GetEAa;tempu=reg_ax * LoadMw(eaa);} + reg_ax=(Bit16u)(tempu & 0xffff);reg_dx=(Bit16u)(tempu >> 16); + flags.cf=flags.of=(reg_dx !=0); + break; + } + case 0x28: /* IMUL AX,Ew */ + { + flags.type=t_MUL;Bit32s temps; + if (rm >= 0xc0 ) {GetEArw;temps=((Bit16s)reg_ax) * (*earws);} + else {GetEAa;temps=((Bit16s)reg_ax) * LoadMws(eaa);} + reg_ax=Bit16u(temps & 0xffff);reg_dx=(Bit16u)(temps >> 16); + if ( (reg_dx==0xffff) && (reg_ax & 0x8000) ) { + flags.cf=flags.of=false; + } else if ( (reg_dx==0x0000) && (reg_ax<0x8000) ) { + flags.cf=flags.of=false; + } else { + flags.cf=flags.of=true; + } + break; + } + case 0x30: /* DIV Ew */ + { +// flags.type=t_DIV; + Bit16u val; + if (rm >= 0xc0 ) {GetEArw;val=*earw;} + else {GetEAa;val=LoadMw(eaa);} + if (val==0) {INTERRUPT(0);break;} + Bit32u tempu=(reg_dx<<16)|reg_ax; + Bit32u quotientu=tempu/val; + reg_dx=(Bit16u)(tempu % val); + reg_ax=(Bit16u)(quotientu & 0xffff); + if (quotientu>0xffff) + INTERRUPT(0); + break; + } + case 0x38: /* IDIV Ew */ + { +// flags.type=t_DIV; + Bit16s val; + if (rm >= 0xc0 ) {GetEArw;val=*earws;} + else {GetEAa;val=LoadMws(eaa);} + if (val==0) {INTERRUPT(0);break;} + Bit32s temps=(reg_dx<<16)|reg_ax; + Bit32s quotients=temps/val; + reg_dx=(Bit16s)(temps % val); + reg_ax=(Bit16s)quotients; + if (quotients!=(Bit16s)reg_ax) + INTERRUPT(0); + break; + } + + } + break; + } + case 0xf8: /* CLC */ + flags.cf=false; + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + break; + case 0xf9: /* STC */ + flags.cf=true; + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + break; + case 0xfa: /* CLI */ + flags.intf=false; + break; + case 0xfb: /* STI */ + flags.intf=true; + if (flags.intf && PIC_IRQCheck) { + SAVEIP; + PIC_runIRQs(); + LOADIP; + }; + break; + case 0xfc: /* CLD */ + flags.df=false; + break; + case 0xfd: /* STD */ + flags.df=true; + break; + case 0xfe: /* GRP4 Eb */ + { + GetRM; + switch (rm & 0x38) { + case 0x00: /* INC Eb */ + flags.cf=get_CF();flags.type=t_INCb; + if (rm >= 0xc0 ) {GetEArb;flags.result.b=*earb+=1;} + else {GetEAa;flags.result.b=LoadMb(eaa)+1;SaveMb(eaa,flags.result.b);} + break; + case 0x08: /* DEC Eb */ + flags.cf=get_CF();flags.type=t_DECb; + if (rm >= 0xc0 ) {GetEArb;flags.result.b=*earb-=1;} + else {GetEAa;flags.result.b=LoadMb(eaa)-1;SaveMb(eaa,flags.result.b);} + break; + case 0x38: /* CallBack */ + { + Bit32u ret; + Bit16u call=Fetchw(); + SAVEIP; + if (call>3) & 7); + break; + } + break; + } + case 0xff: /* GRP5 Ew */ + { + GetRM; + switch (rm & 0x38) { + case 0x00: /* INC Ew */ + flags.cf=get_CF();flags.type=t_INCw; + if (rm >= 0xc0 ) {GetEArw;flags.result.w=*earw+=1;} + else {GetEAa;flags.result.w=LoadMw(eaa)+1;SaveMw(eaa,flags.result.w);} + break; + case 0x08: /* DEC Ew */ + flags.cf=get_CF();flags.type=t_DECw; + if (rm >= 0xc0 ) {GetEArw;flags.result.w=*earw-=1;} + else {GetEAa;flags.result.w=LoadMw(eaa)-1;SaveMw(eaa,flags.result.w);} + break; + case 0x10: /* CALL Ev */ + if (rm >= 0xc0 ) {GetEArw;Push_16(GETIP);SETIP(*earw);} + else {GetEAa;Push_16(GETIP);SETIP(LoadMw(eaa));} + break; + case 0x18: /* CALL Ep */ + { + Push_16(Segs[cs].value); + GetEAa;Push_16(GETIP); + Bit16u newip=LoadMw(eaa); + Bit16u newcs=LoadMw(eaa+2); + SetSegment_16(cs,newcs); + SETIP(newip); + } + break; + case 0x20: /* JMP Ev */ + if (rm >= 0xc0 ) {GetEArw;SETIP(*earw);} + else {GetEAa;SETIP(LoadMw(eaa));} + break; + case 0x28: /* JMP Ep */ + { + GetEAa; + Bit16u newip=LoadMw(eaa); + Bit16u newcs=LoadMw(eaa+2); + SetSegment_16(cs,newcs); + SETIP(newip); + } + break; + case 0x30: /* PUSH Ev */ + if (rm >= 0xc0 ) {GetEArw;Push_16(*earw);} + else {GetEAa;Push_16(LoadMw(eaa));} + break; + default: + E_Exit("CPU:GRP5:Illegal Call %2X",rm & 0x38); + break; + } + break; + } + } + diff --git a/src/cpu/core_16/prefix_66.h b/src/cpu/core_16/prefix_66.h new file mode 100644 index 0000000..5af2a12 --- /dev/null +++ b/src/cpu/core_16/prefix_66.h @@ -0,0 +1,469 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +restart_66: +switch(Fetchb()) { + case 0x01: /* ADD Ed,Gd */ + RMEdGd(ADDD);break; + case 0x03: /* ADD Gd,Ed */ + RMGdEd(ADDD);break; + case 0x05: /* ADD EAX,Id */ + EAXId(ADDD);break; + case 0x09: /* OR Ew,Gw */ + RMEdGd(ORD);break; + case 0x0b: /* OR Gd,Ed */ + RMGdEd(ORD);break; + case 0x0d: /* OR EAX,Id */ + EAXId(ORD);break; + case 0x0f: /* 2 Byte opcodes */ +#include "prefix_66_of.h" + break; + case 0x11: /* ADC Ed,Gd */ + RMEdGd(ADCD);break; + case 0x13: /* ADC Gd,Ed */ + RMGdEd(ADCD);break; + case 0x15: /* ADC EAX,Id */ + EAXId(ADCD);break; + case 0x19: /* SBB Ed,Gd */ + RMEdGd(SBBD);break; + case 0x1b: /* SBB Gd,Ed */ + RMGdEd(SBBD);break; + case 0x1d: /* SBB EAX,Id */ + EAXId(SBBD);break; + case 0x21: /* AND Ed,Gd */ + RMEdGd(ANDD);break; + case 0x23: /* AND Gd,Ed */ + RMGdEd(ANDD);break; + case 0x25: /* AND EAX,Id */ + EAXId(ANDD);break; + case 0x29: /* SUB Ed,Gd */ + RMEdGd(SUBD);break; + case 0x2b: /* SUB Gd,Ed */ + RMGdEd(SUBD);break; + case 0x2d: /* SUB EAX,Id */ + EAXId(SUBD);break; + case 0x31: /* XOR Ed,Gd */ + RMEdGd(XORD);break; + case 0x33: /* XOR Gd,Ed */ + RMGdEd(XORD);break; + case 0x35: /* XOR EAX,Id */ + EAXId(XORD);break; + case 0x39: /* CMP Ed,Gd */ + RMEdGd(CMPD);break; + case 0x3b: /* CMP Gd,Ed */ + RMGdEd(CMPD);break; + case 0x3d: /* CMP EAX,Id */ + EAXId(CMPD);break; + + + case 0x26: /* SEG ES: */ + SegPrefix_66(es);break; + case 0x2e: /* SEG CS: */ + SegPrefix_66(cs);break; + case 0x36: /* SEG SS: */ + SegPrefix_66(ss);break; + case 0x3e: /* SEG DS: */ + SegPrefix_66(ds);break; + case 0x40: /* INC EAX */ + INCD(reg_eax,LoadRd,SaveRd);break; + case 0x41: /* INC ECX */ + INCD(reg_ecx,LoadRd,SaveRd);break; + case 0x42: /* INC EDX */ + INCD(reg_edx,LoadRd,SaveRd);break; + case 0x43: /* INC EBX */ + INCD(reg_ebx,LoadRd,SaveRd);break; + case 0x44: /* INC ESP */ + INCD(reg_esp,LoadRd,SaveRd);break; + case 0x45: /* INC EBP */ + INCD(reg_ebp,LoadRd,SaveRd);break; + case 0x46: /* INC ESI */ + INCD(reg_esi,LoadRd,SaveRd);break; + case 0x47: /* INC EDI */ + INCD(reg_edi,LoadRd,SaveRd);break; + case 0x48: /* DEC EAX */ + DECD(reg_eax,LoadRd,SaveRd);break; + case 0x49: /* DEC ECX */ + DECD(reg_ecx,LoadRd,SaveRd);break; + case 0x4a: /* DEC EDX */ + DECD(reg_edx,LoadRd,SaveRd);break; + case 0x4b: /* DEC EBX */ + DECD(reg_ebx,LoadRd,SaveRd);break; + case 0x4c: /* DEC ESP */ + DECD(reg_esp,LoadRd,SaveRd);break; + case 0x4d: /* DEC EBP */ + DECD(reg_ebp,LoadRd,SaveRd);break; + case 0x4e: /* DEC ESI */ + DECD(reg_esi,LoadRd,SaveRd);break; + case 0x4f: /* DEC EDI */ + DECD(reg_edi,LoadRd,SaveRd);break; + case 0x50: /* PUSH EAX */ + Push_32(reg_eax);break; + case 0x51: /* PUSH ECX */ + Push_32(reg_ecx);break; + case 0x52: /* PUSH EDX */ + Push_32(reg_edx);break; + case 0x53: /* PUSH EBX */ + Push_32(reg_ebx);break; + case 0x54: /* PUSH ESP */ + Push_32(reg_esp);break; + case 0x55: /* PUSH EBP */ + Push_32(reg_ebp);break; + case 0x56: /* PUSH ESI */ + Push_32(reg_esi);break; + case 0x57: /* PUSH EDI */ + Push_32(reg_edi);break; + case 0x58: /* POP EAX */ + reg_eax=Pop_32();break; + case 0x59: /* POP ECX */ + reg_ecx=Pop_32();break; + case 0x5a: /* POP EDX */ + reg_edx=Pop_32();break; + case 0x5b: /* POP EBX */ + reg_ebx=Pop_32();break; + case 0x5c: /* POP ESP */ + reg_esp=Pop_32();break; + case 0x5d: /* POP EBP */ + reg_ebp=Pop_32();break; + case 0x5e: /* POP ESI */ + reg_esi=Pop_32();break; + case 0x5f: /* POP EDI */ + reg_edi=Pop_32();break; + case 0x60: /* PUSHAD */ + Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx); + Push_32(reg_esp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi); + break; + case 0x61: /* POPAD */ + reg_edi=Pop_32();reg_edi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP + reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32(); + break; + case 0x68: /* PUSH Id */ + Push_32(Fetchd());break; + case 0x69: /* IMUL Gd,Ed,Id */ + { + GetRMrd; + Bit64s res; + if (rm >= 0xc0 ) {GetEArd;res=(Bit64s)(*eards) * (Bit64s)Fetchds();} + else {GetEAa;res=(Bit64s)LoadMds(eaa) * (Bit64s)Fetchds();} + *rmrd=(Bit32s)(res); + flags.type=t_MUL; + if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;} + else {flags.cf=true;flags.of=true;} + break; + }; + + + + case 0x6a: /* PUSH Ib */ + Push_32(Fetchbs());break; + case 0x81: /* Grpl Ed,Id */ + { + GetRM; + if (rm>= 0xc0) { + GetEArd;Bit32u id=Fetchd(); + switch (rm & 0x38) { + case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break; + case 0x08: ORD(*eard,id,LoadRd,SaveRd);break; + case 0x10:ADCD(*eard,id,LoadRd,SaveRd);break; + case 0x18:SBBD(*eard,id,LoadRd,SaveRd);break; + case 0x20:ANDD(*eard,id,LoadRd,SaveRd);break; + case 0x28:SUBD(*eard,id,LoadRd,SaveRd);break; + case 0x30:XORD(*eard,id,LoadRd,SaveRd);break; + case 0x38:CMPD(*eard,id,LoadRd,SaveRd);break; + } + } else { + GetEAa;Bit32u id=Fetchb(); + switch (rm & 0x38) { + case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; + case 0x08: ORD(eaa,id,LoadMd,SaveMd);break; + case 0x10:ADCD(eaa,id,LoadMd,SaveMd);break; + case 0x18:SBBD(eaa,id,LoadMd,SaveMd);break; + case 0x20:ANDD(eaa,id,LoadMd,SaveMd);break; + case 0x28:SUBD(eaa,id,LoadMd,SaveMd);break; + case 0x30:XORD(eaa,id,LoadMd,SaveMd);break; + case 0x38:CMPD(eaa,id,LoadMd,SaveMd);break; + } + } + } + break; + case 0x83: /* Grpl Ed,Ix */ + { + GetRM; + if (rm>= 0xc0) { + GetEArd;Bit32u id=(Bit32s)Fetchbs(); + switch (rm & 0x38) { + case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break; + case 0x08: ORD(*eard,id,LoadRd,SaveRd);break; + case 0x10:ADCD(*eard,id,LoadRd,SaveRd);break; + case 0x18:SBBD(*eard,id,LoadRd,SaveRd);break; + case 0x20:ANDD(*eard,id,LoadRd,SaveRd);break; + case 0x28:SUBD(*eard,id,LoadRd,SaveRd);break; + case 0x30:XORD(*eard,id,LoadRd,SaveRd);break; + case 0x38:CMPD(*eard,id,LoadRd,SaveRd);break; + } + } else { + GetEAa;Bit32u id=(Bit32s)Fetchbs(); + switch (rm & 0x38) { + case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; + case 0x08: ORD(eaa,id,LoadMd,SaveMd);break; + case 0x10:ADCD(eaa,id,LoadMd,SaveMd);break; + case 0x18:SBBD(eaa,id,LoadMd,SaveMd);break; + case 0x20:ANDD(eaa,id,LoadMd,SaveMd);break; + case 0x28:SUBD(eaa,id,LoadMd,SaveMd);break; + case 0x30:XORD(eaa,id,LoadMd,SaveMd);break; + case 0x38:CMPD(eaa,id,LoadMd,SaveMd);break; + } + } + } + break; + case 0x8f: /* POP Ed */ + { + GetRM; + if (rm >= 0xc0 ) {GetEArd;*eard=Pop_32();} + else {GetEAa;SaveMd(eaa,Pop_32());} + break; + } + + case 0x89: /* MOV Ed,Gd */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArd;*eard=*rmrd;} + else {GetEAa;SaveMd(eaa,*rmrd);} + break; + } + case 0x99: /* CDQ */ + if (reg_eax & 0x80000000) reg_edx=0xffffffff; + else reg_edx=0; + break; + case 0x8b: /* MOV Gd,Ed */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;} + else {GetEAa;*rmrd=LoadMd(eaa);} + break; + } + case 0x8c: + LOG_WARN("CPU:66:8c looped back"); + break; + case 0x9c: /* PUSHFD */ + { + Bit32u pflags= + (get_CF() << 0) | (get_PF() << 2) | (get_AF() << 4) | + (get_ZF() << 6) | (get_SF() << 7) | (flags.tf << 8) | + (flags.intf << 9) |(flags.df << 10) | (get_OF() << 11) | + (flags.io << 12) | (flags.nt <<14); + Push_32(pflags); + break; + } + case 0x9d: /* POPFD */ + { + Save_Flagsw((Bit16u)(Pop_32()&0xffff)); + break; + } + case 0xa1: /* MOV EAX,Ow */ + if (segprefix_on) { + reg_eax=LoadMd(segprefix_base+Fetchw()); + SegPrefixReset; + } else { + reg_eax=LoadMd(SegBase(ds)+Fetchw()); + } + break; + case 0xa3: /* MOV Ow,EAX */ + if (segprefix_on) { + SaveMd((segprefix_base+Fetchw()),reg_eax); + SegPrefixReset; + } else { + SaveMd((SegBase(ds)+Fetchw()),reg_eax); + } + break; + case 0xa5: /* MOVSD */ + { + stringSI;stringDI;SaveMd(to,LoadMd(from)); + if (flags.df) { reg_si-=4;reg_di-=4; } + else { reg_si+=4;reg_di+=4;} + } + break; + case 0xab: /* STOSD */ + { + stringDI; + SaveMd(to,reg_eax); + if (flags.df) { reg_di-=4; } + else {reg_di+=4;} + break; + } + case 0xad: /* LODSD */ + { + stringSI; + reg_eax=LoadMd(from); + if (flags.df) { reg_si-=4;} + else {reg_si+=4;} + break; + } + case 0xaf: /* SCASD */ + { + stringDI; + CMPD(reg_eax,LoadMd(to),LoadRd,0); + if (flags.df) { reg_di-=4; } + else {reg_di+=4;} + break; + } + case 0xb8: /* MOV EAX,Id */ + reg_eax=Fetchd();break; + case 0xb9: /* MOV ECX,Id */ + reg_ecx=Fetchd();break; + case 0xba: /* MOV EDX,Iw */ + reg_edx=Fetchd();break; + case 0xbb: /* MOV EBX,Id */ + reg_ebx=Fetchd();break; + case 0xbc: /* MOV ESP,Id */ + reg_esp=Fetchd();break; + case 0xbd: /* MOV EBP.Id */ + reg_ebp=Fetchd();break; + case 0xbe: /* MOV ESI,Id */ + reg_esi=Fetchd();break; + case 0xbf: /* MOV EDI,Id */ + reg_edi=Fetchd();break; + case 0xc1: /* GRP2 Ed,Ib */ + GRP2D(Fetchb());break; + case 0xc7: /* MOV Ed,Id */ + { + GetRM; + if (rm>0xc0) {GetEArd;*eard=Fetchd();} + else {GetEAa;SaveMd(eaa,Fetchd());} + break; + } + case 0xd1: /* GRP2 Ed,1 */ + GRP2D(1);break; + case 0xd3: /* GRP2 Ed,CL */ + GRP2D(reg_cl);break; + case 0xf7: /* GRP3 Ed(,Id) */ + { + union { Bit64u u;Bit64s s;} temp; + union {Bit64u u;Bit64s s;} quotient; + GetRM; + switch (rm & 0x38) { + case 0x00: /* TEST Ed,Id */ + case 0x08: /* TEST Ed,Id Undocumented*/ + { + if (rm >= 0xc0 ) {GetEArd;TESTD(*eard,Fetchd(),LoadRd,SaveRd);} + else {GetEAa;TESTD(eaa,Fetchd(),LoadMd,SaveMd);} + break; + } + case 0x10: /* NOT Ed */ + { + if (rm >= 0xc0 ) {GetEArd;*eard=~*eard;} + else {GetEAa;SaveMd(eaa,~LoadMd(eaa));} + break; + } + case 0x18: /* NEG Ed */ + { + flags.type=t_NEGd; + if (rm >= 0xc0 ) { + GetEArd;flags.var1.d=*eard;flags.result.d=0-flags.var1.d; + *eard=flags.result.d; + } else { + GetEAa;flags.var1.d=LoadMd(eaa);flags.result.d=0-flags.var1.d; + SaveMd(eaa,flags.result.d); + } + break; + } + case 0x20: /* MUL EAX,Ed */ + { + flags.type=t_MUL; + if (rm >= 0xc0 ) {GetEArd;temp.u=(Bit64s)reg_eax * (Bit64u)(*eard);} + else {GetEAa;temp.u=(Bit64u)reg_eax * (Bit64u)LoadMd(eaa);} + reg_eax=(Bit32u)(temp.u & 0xffffffff);reg_eax=(Bit32u)(temp.u >> 32); + flags.cf=flags.of=(reg_edx !=0); + break; + } + case 0x28: /* IMUL EAX,Ed */ + { + flags.type=t_MUL; + if (rm >= 0xc0 ) {GetEArd;temp.s=(Bit64s)reg_eax * (Bit64s)(*eards);} + else {GetEAa;temp.s=(Bit64s)reg_eax * (Bit64s)LoadMds(eaa);} + reg_eax=Bit32u(temp.u & 0xffffffff);reg_edx=(Bit32u)(temp.u >> 32); + if ( (reg_edx==0xffffffff) && (reg_eax & 0x80000000) ) { + flags.cf=flags.of=false; + } else if ( (reg_edx==0x00000000) && (reg_eax<0x80000000) ) { + flags.cf=flags.of=false; + } else { + flags.cf=flags.of=true; + } + break; + } + case 0x30: /* DIV Ed */ + { +// flags.type=t_DIV; + Bit32u val; + if (rm >= 0xc0 ) {GetEArd;val=*eard;} + else {GetEAa;val=LoadMd(eaa);} + if (val==0) {Interrupt(0);break;} + temp.u=(((Bit64u)reg_edx)<<32)|reg_eax; + quotient.u=temp.u/val; + reg_edx=(Bit32u)(temp.u % val); + reg_eax=(Bit32u)(quotient.u & 0xffffffff); + if (quotient.u>0xffffffff) + Interrupt(0); + break; + } + case 0x38: /* IDIV Ed */ + { +// flags.type=t_DIV; + Bit32s val; + if (rm >= 0xc0 ) {GetEArd;val=*eards;} + else {GetEAa;val=LoadMds(eaa);} + if (val==0) {Interrupt(0);break;} + temp.s=(((Bit64u)reg_edx)<<32)|reg_eax; + quotient.s=(temp.s/val); + reg_edx=(Bit32s)(temp.s % val); + reg_eax=(Bit32s)(quotient.s); + if (quotient.s!=(Bit32s)reg_eax) + Interrupt(0); + break; + } + } + break; + } + case 0xff: /* Group 5 */ + { + GetRM; + switch (rm & 0x38) { + case 0x00: /* INC Ew */ + flags.cf=get_CF();flags.type=t_INCd; + if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard+=1;} + else {GetEAa;flags.result.d=LoadMd(eaa)+1;SaveMd(eaa,flags.result.d);} + break; + case 0x08: /* DEC Ew */ + flags.cf=get_CF();flags.type=t_DECd; + if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard-=1;} + else {GetEAa;flags.result.d=LoadMd(eaa)-1;SaveMd(eaa,flags.result.d);} + break; + case 0x30: /* Push Ed */ + if (rm >= 0xc0 ) {GetEArd;Push_32(*eard);} + else {GetEAa;Push_32(LoadMd(eaa));} + break; + default: + E_Exit("CPU:66:GRP5:Illegal call %2X",rm & 0x38); + break; + } + break; + } + default: + NOTDONE66; + } + + diff --git a/src/cpu/core_16/prefix_66_of.h b/src/cpu/core_16/prefix_66_of.h new file mode 100644 index 0000000..676f000 --- /dev/null +++ b/src/cpu/core_16/prefix_66_of.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +switch (Fetchb()) { + + + case 0xa4: /* SHLD Ed,Gd,Ib */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArd;DSHLD(*eard,*rmrd,Fetchb(),LoadRd,SaveRd);} + else {GetEAa;DSHLD(eaa,*rmrd,Fetchb(),LoadMd,SaveMd);} + break; + } + case 0xac: /* SHRD Ed,Gd,Ib */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArd;DSHRD(*eard,*rmrd,Fetchb(),LoadRd,SaveRd);} + else {GetEAa;DSHRD(eaa,*rmrd,Fetchb(),LoadMd,SaveMd);} + break; + } + case 0xb6: /* MOVZX Gd,Eb */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArb;*rmrd=*earb;} + else {GetEAa;*rmrd=LoadMb(eaa);} + break; + } + case 0xaf: /* IMUL Gd,Ed */ + { + GetRMrd; + Bit64s res; + if (rm >= 0xc0 ) {GetEArd;res=(Bit64s)(*rmrd) * (Bit64s)(*eards);} + else {GetEAa;res=(Bit64s)(*rmrd) * (Bit64s)LoadMds(eaa);} + *rmrd=(Bit32s)(res); + flags.type=t_MUL; + if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;} + else {flags.cf=true;flags.of=true;} + break; + }; + case 0xb7: /* MOVXZ Gd,Ew */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArw;*rmrd=*earw;} + else {GetEAa;*rmrd=LoadMw(eaa);} + break; + } + case 0xba: /* GRP8 Ed,Ib */ + { + GetRM; + if (rm >= 0xc0 ) { + GetEArd; + Bit32u mask=1 << (Fetchb() & 31); + flags.cf=(*eard & mask)>0; + switch (rm & 0x38) { + case 0x20: /* BT */ + break; + case 0x28: /* BTS */ + *eard|=mask; + break; + case 0x30: /* BTR */ + *eard&=~mask; + break; + case 0x38: /* BTC */ + if (flags.cf) *eard&=~mask; + else *eard|=mask; + break; + } + } else { + GetEAa;Bit32u old=LoadMd(eaa); + Bit32u mask=1 << (Fetchb() & 31); + flags.cf=(old & mask)>0; + switch (rm & 0x38) { + case 0x20: /* BT */ + break; + case 0x28: /* BTS */ + SaveMd(eaa,old|mask); + break; + case 0x30: /* BTR */ + SaveMd(eaa,old & ~mask); + break; + case 0x38: /* BTC */ + if (flags.cf) old&=~mask; + else old|=mask; + SaveMd(eaa,old); + break; + } + } + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + break; + } + case 0xbe: /* MOVSX Gd,Eb */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArb;*rmrd=*earbs;} + else {GetEAa;*rmrd=LoadMbs(eaa);} + break; + } + case 0xbf: /* MOVSX Gd,Ew */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArw;*rmrd=*earws;} + else {GetEAa;*rmrd=LoadMws(eaa);} + break; + } + default: + SUBIP(1); + E_Exit("CPU:Opcode 66:0F:%2X Unhandled",Fetchb()); +} diff --git a/src/cpu/core_16/prefix_of.h b/src/cpu/core_16/prefix_of.h new file mode 100644 index 0000000..f402499 --- /dev/null +++ b/src/cpu/core_16/prefix_of.h @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +switch(Fetchb()) { + case 0x01: /* GRP 7 */ + { + GetRM; + switch (rm & 0x38) { + case 0x20: /* SMSW */ + /* Let's seriously fake this call */ + if (rm>0xc0) {GetEArw;*earw=0;} + else {GetEAa;SaveMw(eaa,0);} + break; + default: + E_Exit("CPU:GRP7:Illegal call %2X",rm); + } + } + break; + case 0x80: /* JO */ + JumpSIw(get_OF());break; + case 0x81: /* JNO */ + JumpSIw(!get_OF());break; + case 0x82: /* JB */ + JumpSIw(get_CF());break; + case 0x83: /* JNB */ + JumpSIw(!get_CF());break; + case 0x84: /* JZ */ + JumpSIw(get_ZF());break; + case 0x85: /* JNZ */ + JumpSIw(!get_ZF()); break; + case 0x86: /* JBE */ + JumpSIw(get_CF() || get_ZF());break; + case 0x87: /* JNBE */ + JumpSIw(!get_CF() && !get_ZF());break; + case 0x88: /* JS */ + JumpSIw(get_SF());break; + case 0x89: /* JNS */ + JumpSIw(!get_SF());break; + case 0x8a: /* JP */ + JumpSIw(get_PF());break; + case 0x8b: /* JNP */ + JumpSIw(!get_PF());break; + case 0x8c: /* JL */ + JumpSIw(get_SF() != get_OF());break; + case 0x8d: /* JNL */ + JumpSIw(get_SF() == get_OF());break; + case 0x8e: /* JLE */ + JumpSIw(get_ZF() || (get_SF() != get_OF()));break; + case 0x8f: /* JNLE */ + JumpSIw((get_SF() == get_OF()) && !get_ZF());break; + case 0xa0: /* PUSH FS */ + Push_16(Segs[fs].value);break; + case 0xa1: /* POP FS */ + SetSegment_16(fs,Pop_16());break; + case 0xa4: /* SHLD Ew,Gw,Ib */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArw;DSHLW(*earw,*rmrw,Fetchb(),LoadRw,SaveRw);} + else {GetEAa;DSHLW(eaa,*rmrw,Fetchb(),LoadMw,SaveMw);} + break; + } + case 0xa5: /* SHLD Ew,Gw,CL */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArw;DSHLW(*earw,*rmrw,reg_cl,LoadRw,SaveRw);} + else {GetEAa;DSHLW(eaa,*rmrw,reg_cl,LoadMw,SaveMw);} + break; + } + case 0xa8: /* PUSH GS */ + Push_16(Segs[gs].value);break; + case 0xa9: /* POP GS */ + SetSegment_16(gs,Pop_16());break; + case 0xac: /* SHRD Ew,Gw,Ib */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArw;DSHRW(*earw,*rmrw,Fetchb(),LoadRw,SaveRw);} + else {GetEAa;DSHRW(eaa,*rmrw,Fetchb(),LoadMw,SaveMw);} + break; + } + case 0xad: /* SHRD Ew,Gw,CL */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArw;DSHRW(*earw,*rmrw,reg_cl,LoadRw,SaveRw);} + else {GetEAa;DSHRW(eaa,*rmrw,reg_cl,LoadMw,SaveMw);} + break; + } + case 0xaf: /* IMUL Gw,Ew */ + { + GetRMrw; + Bit32s res; + if (rm >= 0xc0 ) {GetEArw;res=(Bit32s)(*rmrw) * (Bit32s)(*earws);} + else {GetEAa;res=(Bit32s)(*rmrw) *(Bit32s)LoadMws(eaa);} + *rmrw=res & 0xFFFF; + flags.type=t_MUL; + if ((res> -32768) && (res<32767)) {flags.cf=false;flags.of=false;} + else {flags.cf=true;flags.of=true;} + break; + } + case 0xb4: /* LFS */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);SetSegment_16(fs,LoadMw(eaa+2)); + break; + } + case 0xb5: /* LGS */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);SetSegment_16(gs,LoadMw(eaa+2)); + break; + } + case 0xb6: /* MOVZX Gw,Eb */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArb;*rmrw=*earb;} + else {GetEAa;*rmrw=LoadMb(eaa);} + break; + } + case 0xba: /* GRP8 Ew,Ib */ + { + GetRM; + if (rm >= 0xc0 ) { + GetEArw; + Bit16u mask=1 << (Fetchb() & 15); + flags.cf=(*earw & mask)>0; + switch (rm & 0x38) { + case 0x20: /* BT */ + break; + case 0x28: /* BTS */ + *earw|=mask; + break; + case 0x30: /* BTR */ + *earw&=~mask; + break; + case 0x38: /* BTC */ + if (flags.cf) *earw&=~mask; + else *earw|=mask; + break; + } + } else { + GetEAa;Bit16u old=LoadMw(eaa); + Bit16u mask=1 << (Fetchb() & 15); + flags.cf=(old & mask)>0; + switch (rm & 0x38) { + case 0x20: /* BT */ + break; + case 0x28: /* BTS */ + SaveMw(eaa,old|mask); + break; + case 0x30: /* BTR */ + SaveMw(eaa,old & ~mask); + break; + case 0x38: /* BTC */ + if (flags.cf) old&=~mask; + else old|=mask; + SaveMw(eaa,old); + break; + } + } + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + break; + } + case 0xbe: /* MOVSX Gw,Eb */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArb;*rmrw=*earbs;} + else {GetEAa;*rmrw=LoadMbs(eaa);} + break; + } + default: + SUBIP(1); + E_Exit("CPU:Opcode 0F:%2X Unhandled",Fetchb()); + } diff --git a/src/cpu/core_dynrec/risc_armv4le.h b/src/cpu/core_16/start.h similarity index 59% rename from src/cpu/core_dynrec/risc_armv4le.h rename to src/cpu/core_16/start.h index 4427fc1..f54a1e2 100644 --- a/src/cpu/core_dynrec/risc_armv4le.h +++ b/src/cpu/core_16/start.h @@ -1,31 +1,20 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_armv4le.h,v 1.2 2008/09/02 20:44:41 c2woody Exp $ */ - - -/* ARMv4 (little endian) backend (switcher) by M-HT */ - -#include "risc_armv4le-common.h" - -// choose your destiny: -#include "risc_armv4le-thumb-niw.h" -//#include "risc_armv4le-thumb-iw.h" -//#include "risc_armv4le-thumb.h" -//#include "risc_armv4le-s3.h" -//#include "risc_armv4le-o3.h" +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* Setup the CS:IP and SS:SP Pointers */ +LOADIP; diff --git a/src/ints/xms.h b/src/cpu/core_16/stop.h similarity index 50% rename from src/ints/xms.h rename to src/cpu/core_16/stop.h index 8c72978..297949e 100644 --- a/src/ints/xms.h +++ b/src/cpu/core_16/stop.h @@ -1,34 +1,19 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __XMS_H__ -#define __XMS_H__ - -Bitu XMS_QueryFreeMemory (Bit16u& largestFree, Bit16u& totalFree); -Bitu XMS_AllocateMemory (Bitu size, Bit16u& handle); -Bitu XMS_FreeMemory (Bitu handle); -Bitu XMS_MoveMemory (PhysPt bpt); -Bitu XMS_LockMemory (Bitu handle, Bit32u& address); -Bitu XMS_UnlockMemory (Bitu handle); -Bitu XMS_GetHandleInformation(Bitu handle, Bit8u& lockCount, Bit8u& numFree, Bit16u& size); -Bitu XMS_ResizeMemory (Bitu handle, Bitu newSize); - -Bitu XMS_EnableA20 (bool enable); -Bitu XMS_GetEnabledA20 (void); - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +SAVEIP; diff --git a/src/cpu/core_16/support.h b/src/cpu/core_16/support.h new file mode 100644 index 0000000..8ee2482 --- /dev/null +++ b/src/cpu/core_16/support.h @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +EAPoint IPPoint; + + +#define SUBIP(a) IPPoint-=a +#define SETIP(a) IPPoint=SegBase(cs)+a +#define GETIP (Bit16u)(IPPoint-SegBase(cs)) +#define SAVEIP reg_ip=GETIP +#define LOADIP IPPoint=SegBase(cs)+reg_ip +/* +#define ADDIP(a) { \ + Bit16u add_ip=(Bit16u)(IPPoint-SegBase(cs)); \ + add_ip+=a; \ + IPPoint=SegBase(cs)+add_ip; \ + } +*/ + +static INLINE void ADDIP(Bit16u add) { + +// Bit16u oldip=(IPPoint-SegBase(cs)); +// oldip+=add; +// IPPoint=SegBase(cs)+oldip; + IPPoint=SegBase(cs)+((Bit16u)(((Bit16u)(IPPoint-SegBase(cs)))+(Bit16u)add)); +} + +static INLINE void ADDIPFAST(Bit16s blah) { + IPPoint+=blah; +} + +#define ERRORRETURN(a) { error_ret=a;goto errorreturn; } + + +static INLINE Bit8u Fetchb() { + Bit8u temp=LoadMb(IPPoint); + IPPoint+=1; + return temp; +} + +static INLINE Bit16u Fetchw() { + Bit16u temp=LoadMw(IPPoint); + IPPoint+=2; + return temp; +} +static INLINE Bit32u Fetchd() { + Bit32u temp=LoadMd(IPPoint); + IPPoint+=4; + return temp; +} + +static INLINE Bit8s Fetchbs() { + return Fetchb(); +} +static INLINE Bit16s Fetchws() { + return Fetchw(); +} + +static INLINE Bit32s Fetchds() { + return Fetchd(); +} + + +static INLINE void Push_16(Bit16u blah) { + reg_sp-=2; + SaveMw(SegBase(ss)+reg_sp,blah); +}; + +static INLINE void Push_32(Bit32u blah) { + reg_sp-=4; + SaveMd(SegBase(ss)+reg_sp,blah); +}; + +static INLINE Bit16u Pop_16() { + Bit16u temp=LoadMw(SegBase(ss)+reg_sp); + reg_sp+=2; + return temp; +}; + +static INLINE Bit32u Pop_32() { + Bit32u temp=LoadMd(SegBase(ss)+reg_sp); + reg_sp+=4; + return temp; +}; + + + + + + + +#define stringDI \ + EAPoint to; \ + to=SegBase(es)+reg_di + +#define stringSI \ + EAPoint from; \ + if (segprefix_on) { \ + from=(segprefix_base+reg_si); \ + SegPrefixReset; \ + } else { \ + from=SegBase(ds)+reg_si; \ + } + + +#include "helpers.h" +#include "table_ea.h" +#include "../modrm.h" +#include "instructions.h" + + +static INLINE void Rep_66(Bit16s direct,EAPoint from,EAPoint to) { + bool again; + do { + again=false; + Bit8u repcode=Fetchb(); + switch (repcode) { + case 0x26: /* ES Prefix */ + again=true; + from=SegBase(es); + break; + case 0x2e: /* CS Prefix */ + again=true; + from=SegBase(cs); + break; + case 0x36: /* SS Prefix */ + again=true; + from=SegBase(ss); + break; + case 0x3e: /* DS Prefix */ + again=true; + from=SegBase(ds); + break; + case 0xa5: /* REP MOVSD */ + for (;reg_cx>0;reg_cx--) { + SaveMd(to+reg_di,LoadMd(from+reg_si)); + reg_di+=direct*4; + reg_si+=direct*4; + } + break; + case 0xab: /* REP STOSW */ + for (;reg_cx>0;reg_cx--) { + SaveMd(to+reg_di,reg_eax); + reg_di+=direct*4; + } + break; + default: + E_Exit("CPU:Opcode 66:Illegal REP prefix %2X",repcode); + } + } while (again); +} + +//flags.io and nt shouldn't be compiled for 386 +#define Save_Flagsw(FLAGW) \ +{ \ + flags.type=t_UNKNOWN; \ + flags.cf =(FLAGW & 0x001)>0;flags.pf =(FLAGW & 0x004)>0; \ + flags.af =(FLAGW & 0x010)>0;flags.zf =(FLAGW & 0x040)>0; \ + flags.sf =(FLAGW & 0x080)>0;flags.tf =(FLAGW & 0x100)>0; \ + flags.intf =(FLAGW & 0x200)>0; \ + flags.df =(FLAGW & 0x400)>0;flags.of =(FLAGW & 0x800)>0; \ + flags.io =(FLAGW >> 12) & 0x03; \ + flags.nt =(FLAGW & 0x4000)>0; \ + if (flags.intf && PIC_IRQCheck) { \ + SAVEIP; \ + PIC_runIRQs(); \ + LOADIP; \ + } \ + if (flags.tf) E_Exit("CPU:Trap Flag not supported"); \ +} + + +// if (flags.tf) { \ +// cpudecoder=CPU_Real_16_Slow_Decode_Special; \ +// return CBRET_NONE; \ +// } \ diff --git a/src/cpu/core_16/table_ea.h b/src/cpu/core_16/table_ea.h new file mode 100644 index 0000000..a1d8655 --- /dev/null +++ b/src/cpu/core_16/table_ea.h @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* Some variables for EA Loolkup */ + +typedef EAPoint (*GetEATable[256])(void); +static GetEATable * lookupEATable; + +static EAPoint segprefix_base; +static bool segprefix_on=false; + +#define SegPrefix(blah) \ + segprefix_base=SegBase(blah); \ + segprefix_on=true; \ + lookupEATable=&GetEA_16_s; \ + goto restart; \ + +#define SegPrefix_66(blah) \ + segprefix_base=SegBase(blah); \ + segprefix_on=true; \ + lookupEATable=&GetEA_16_s; \ + goto restart_66; \ + + + +#define SegPrefixReset \ + segprefix_on=false;lookupEATable=&GetEA_16_n; + + +/* The MOD/RM Decoder for EA for this decoder's addressing modes */ +static EAPoint EA_16_00_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si); } +static EAPoint EA_16_01_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di); } +static EAPoint EA_16_02_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si); } +static EAPoint EA_16_03_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di); } +static EAPoint EA_16_04_n(void) { return SegBase(ds)+(Bit16u)(reg_si); } +static EAPoint EA_16_05_n(void) { return SegBase(ds)+(Bit16u)(reg_di); } +static EAPoint EA_16_06_n(void) { return SegBase(ds)+(Bit16u)(Fetchw());} +static EAPoint EA_16_07_n(void) { return SegBase(ds)+(Bit16u)(reg_bx); } + +static EAPoint EA_16_40_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); } +static EAPoint EA_16_41_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); } +static EAPoint EA_16_42_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); } +static EAPoint EA_16_43_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); } +static EAPoint EA_16_44_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchbs()); } +static EAPoint EA_16_45_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchbs()); } +static EAPoint EA_16_46_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchbs()); } +static EAPoint EA_16_47_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchbs()); } + +static EAPoint EA_16_80_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); } +static EAPoint EA_16_81_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); } +static EAPoint EA_16_82_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); } +static EAPoint EA_16_83_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); } +static EAPoint EA_16_84_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchws()); } +static EAPoint EA_16_85_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchws()); } +static EAPoint EA_16_86_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchws()); } +static EAPoint EA_16_87_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchws()); } + +static GetEATable GetEA_16_n={ +/* 00 */ + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, +/* 01 */ + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, +/* 10 */ + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, +/* 11 These are illegal so make em 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + +#define prefixed(val) EAPoint ret=segprefix_base+val;SegPrefixReset;return ret; + +static EAPoint EA_16_00_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_si)) } +static EAPoint EA_16_01_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_di)) } +static EAPoint EA_16_02_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_si)) } +static EAPoint EA_16_03_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_di)) } +static EAPoint EA_16_04_s(void) { prefixed((Bit16u)(reg_si)) } +static EAPoint EA_16_05_s(void) { prefixed((Bit16u)(reg_di)) } +static EAPoint EA_16_06_s(void) { prefixed((Bit16u)(Fetchw())) } +static EAPoint EA_16_07_s(void) { prefixed((Bit16u)(reg_bx)) } + +static EAPoint EA_16_40_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs())) } +static EAPoint EA_16_41_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs())) } +static EAPoint EA_16_42_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs())) } +static EAPoint EA_16_43_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs())) } +static EAPoint EA_16_44_s(void) { prefixed((Bit16u)(reg_si+Fetchbs())) } +static EAPoint EA_16_45_s(void) { prefixed((Bit16u)(reg_di+Fetchbs())) } +static EAPoint EA_16_46_s(void) { prefixed((Bit16u)(reg_bp+Fetchbs())) } +static EAPoint EA_16_47_s(void) { prefixed((Bit16u)(reg_bx+Fetchbs())) } + +static EAPoint EA_16_80_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws())) } +static EAPoint EA_16_81_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws())) } +static EAPoint EA_16_82_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws())) } +static EAPoint EA_16_83_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws())) } +static EAPoint EA_16_84_s(void) { prefixed((Bit16u)(reg_si+Fetchws())) } +static EAPoint EA_16_85_s(void) { prefixed((Bit16u)(reg_di+Fetchws())) } +static EAPoint EA_16_86_s(void) { prefixed((Bit16u)(reg_bp+Fetchws())) } +static EAPoint EA_16_87_s(void) { prefixed((Bit16u)(reg_bx+Fetchws())) } + +static GetEATable GetEA_16_s={ +/* 00 */ + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, +/* 01 */ + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, +/* 10 */ + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, +/* 11 These are illegal so make em 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + +INLINE EAPoint Sib(Bitu mode) { + Bit8u sib=Fetchb(); + EAPoint base; + switch (sib&7) { + case 0: /* EAX Base */ + base=SegBase(ds)+reg_eax;break; + case 1: /* ECX Base */ + base=SegBase(ds)+reg_ecx;break; + case 2: /* EDX Base */ + base=SegBase(ds)+reg_edx;break; + case 3: /* EBX Base */ + base=SegBase(ds)+reg_ebx;break; + case 4: /* ESP Base */ + base=SegBase(ds)+reg_esp;break; + case 5: /* #1 Base */ + if (!mode) { + base=SegBase(ds)+Fetchd();break; + } else { + base=SegBase(ss)+reg_ebp;break; + } + case 6: /* ESI Base */ + base=SegBase(ds)+reg_esi;break; + case 7: /* EDI Base */ + base=SegBase(ds)+reg_edi;break; + } + Bitu shift=sib >> 6; + switch ((sib >>3) &7) { + case 0: /* EAX Index */ + base+=(Bit32s)reg_eax< -#include -#include -#include -#include -#include - -#if defined (WIN32) -#include -#include -#endif - -#if (C_HAVE_MPROTECT) -#include - -#include -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif -#endif /* C_HAVE_MPROTECT */ - -#include "callback.h" -#include "regs.h" -#include "mem.h" -#include "cpu.h" -#include "debug.h" -#include "paging.h" -#include "inout.h" -#include "fpu.h" - -#define CACHE_MAXSIZE (4096*3) -#define CACHE_TOTAL (1024*1024*8) -#define CACHE_PAGES (512) -#define CACHE_BLOCKS (64*1024) -#define CACHE_ALIGN (16) -#define DYN_HASH_SHIFT (4) -#define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT) -#define DYN_LINKS (16) - -#if 0 -#define DYN_LOG LOG_MSG -#else -#define DYN_LOG -#endif - -#if C_FPU -#define CPU_FPU 1 //Enable FPU escape instructions -#endif - -enum { - G_EAX,G_ECX,G_EDX,G_EBX, - G_ESP,G_EBP,G_ESI,G_EDI, - G_ES,G_CS,G_SS,G_DS,G_FS,G_GS, - G_FLAGS,G_NEWESP,G_EIP, - G_EA,G_STACK,G_CYCLES, - G_TMPB,G_TMPW,G_SHIFT, - G_EXIT, - G_MAX, -}; - -enum SingleOps { - SOP_INC,SOP_DEC, - SOP_NOT,SOP_NEG, -}; - -enum DualOps { - DOP_ADD,DOP_ADC, - DOP_SUB,DOP_SBB, - DOP_CMP,DOP_XOR, - DOP_AND,DOP_OR, - DOP_TEST, - DOP_MOV, - DOP_XCHG, -}; - -enum ShiftOps { - SHIFT_ROL,SHIFT_ROR, - SHIFT_RCL,SHIFT_RCR, - SHIFT_SHL,SHIFT_SHR, - SHIFT_SAL,SHIFT_SAR, -}; - -enum BranchTypes { - BR_O,BR_NO,BR_B,BR_NB, - BR_Z,BR_NZ,BR_BE,BR_NBE, - BR_S,BR_NS,BR_P,BR_NP, - BR_L,BR_NL,BR_LE,BR_NLE -}; - - -enum BlockReturn { - BR_Normal=0, - BR_Cycles, - BR_Link1,BR_Link2, - BR_Opcode, -#if (C_DEBUG) - BR_OpcodeFull, -#endif - BR_Iret, - BR_CallBack, - BR_SMCBlock -}; - -#define SMC_CURRENT_BLOCK 0xffff - - -#define DYNFLG_HAS16 0x1 //Would like 8-bit host reg support -#define DYNFLG_HAS8 0x2 //Would like 16-bit host reg support -#define DYNFLG_LOAD 0x4 //Load value when accessed -#define DYNFLG_SAVE 0x8 //Needs to be saved back at the end of block -#define DYNFLG_CHANGED 0x10 //Value is in a register and changed from load -#define DYNFLG_ACTIVE 0x20 //Register has an active value - -class GenReg; -class CodePageHandler; - -struct DynReg { - Bitu flags; - GenReg * genreg; - void * data; -}; - -enum DynAccess { - DA_d,DA_w, - DA_bh,DA_bl -}; - -enum ByteCombo { - BC_ll,BC_lh, - BC_hl,BC_hh, -}; - -static DynReg DynRegs[G_MAX]; -#define DREG(_WHICH_) &DynRegs[G_ ## _WHICH_ ] - -static struct { - Bitu ea,tmpb,tmpd,stack,shift,newesp; -} extra_regs; - -static void IllegalOption(const char* msg) { - E_Exit("DynCore: illegal option in %s",msg); -} - -#include "core_dyn_x86/cache.h" - -static struct { - Bitu callback; - Bit32u readdata; -} core_dyn; - -static struct { - Bit32u state[32]; - FPU_P_Reg temp,temp2; - Bit32u dh_fpu_enabled; - Bit32u state_used; - Bit32u cw,host_cw; - Bit8u temp_state[128]; -} dyn_dh_fpu; - - -#include "core_dyn_x86/risc_x86.h" - -struct DynState { - DynReg regs[G_MAX]; -}; - -static void dyn_flags_host_to_gen(void) { - gen_dop_word(DOP_MOV,true,DREG(EXIT),DREG(FLAGS)); - gen_dop_word_imm(DOP_AND,true,DREG(EXIT),FMASK_TEST); - gen_load_flags(DREG(EXIT)); - gen_releasereg(DREG(EXIT)); - gen_releasereg(DREG(FLAGS)); -} - -static void dyn_flags_gen_to_host(void) { - gen_save_flags(DREG(EXIT)); - gen_dop_word_imm(DOP_AND,true,DREG(EXIT),FMASK_TEST); - gen_dop_word_imm(DOP_AND,true,DREG(FLAGS),~FMASK_TEST); - gen_dop_word(DOP_OR,true,DREG(FLAGS),DREG(EXIT)); //flags are marked for save - gen_releasereg(DREG(EXIT)); - gen_releasereg(DREG(FLAGS)); -} - -static void dyn_savestate(DynState * state) { - for (Bitu i=0;iregs[i].flags=DynRegs[i].flags; - state->regs[i].genreg=DynRegs[i].genreg; - } -} - -static void dyn_loadstate(DynState * state) { - for (Bitu i=0;iregs[i]); - } -} - -static void dyn_synchstate(DynState * state) { - for (Bitu i=0;iregs[i]); - } -} - -static void dyn_saveregister(DynReg * src_reg, DynReg * dst_reg) { - dst_reg->flags=src_reg->flags; - dst_reg->genreg=src_reg->genreg; -} - -static void dyn_restoreregister(DynReg * src_reg, DynReg * dst_reg) { - dst_reg->flags=src_reg->flags; - dst_reg->genreg=src_reg->genreg; - dst_reg->genreg->dynreg=dst_reg; // necessary when register has been released -} - -#include "core_dyn_x86/decoder.h" - -#if defined (_MSC_VER) -#define DH_FPU_SAVE_REINIT \ -{ \ - __asm { \ - __asm fnsave dyn_dh_fpu.state[0] \ - } \ - dyn_dh_fpu.state_used=false; \ - dyn_dh_fpu.state[0]|=0x3f; \ -} -#else -#define DH_FPU_SAVE_REINIT \ -{ \ - __asm__ volatile ( \ - "fnsave %0 \n" \ - : \ - : "m" (dyn_dh_fpu.state[0]) \ - : "memory" \ - ); \ - dyn_dh_fpu.state_used=false; \ - dyn_dh_fpu.state[0]|=0x3f; \ -} -#endif - - -Bits CPU_Core_Dyn_X86_Run(void) { - /* Determine the linear address of CS:EIP */ -restart_core: - PhysPt ip_point=SegPhys(cs)+reg_eip; - #if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; - #endif - CodePageHandler * chandler=0; - if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) { - CPU_Exception(cpu.exception.which,cpu.exception.error); - goto restart_core; - } - if (!chandler) { - if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT - return CPU_Core_Normal_Run(); - } - /* Find correct Dynamic Block to run */ - CacheBlock * block=chandler->FindCacheBlock(ip_point&4095); - if (!block) { - if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) { - block=CreateCacheBlock(chandler,ip_point,32); - } else { - Bitu old_cycles=CPU_Cycles; - CPU_Cycles=1; - Bits nc_retcode=CPU_Core_Normal_Run(); - if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT - if (!nc_retcode) { - CPU_Cycles=old_cycles-1; - goto restart_core; - } - CPU_CycleLeft+=old_cycles; - return nc_retcode; - } - } -run_block: - cache.block.running=0; - BlockReturn ret=gen_runcode(block->cache.start); - switch (ret) { - case BR_Iret: -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) { - if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT - return debugCallback; - } -#endif - if (!GETFLAG(TF)) goto restart_core; - cpudecoder=CPU_Core_Dyn_X86_Trap_Run; - if (!dyn_dh_fpu.state_used) return CBRET_NONE; - DH_FPU_SAVE_REINIT - return CBRET_NONE; - case BR_Normal: - /* Maybe check if we staying in the same page? */ -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; -#endif - goto restart_core; - case BR_Cycles: -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; -#endif - if (!dyn_dh_fpu.state_used) return CBRET_NONE; - DH_FPU_SAVE_REINIT - return CBRET_NONE; - case BR_CallBack: - if (!dyn_dh_fpu.state_used) return core_dyn.callback; - DH_FPU_SAVE_REINIT - return core_dyn.callback; - case BR_SMCBlock: -// LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip); - cpu.exception.which=0; - // fallthrough, let the normal core handle the block-modifying instruction - case BR_Opcode: - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=1; - if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT - return CPU_Core_Normal_Run(); -#if (C_DEBUG) - case BR_OpcodeFull: - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=1; - if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT - return CPU_Core_Full_Run(); -#endif - case BR_Link1: - case BR_Link2: - { - Bitu temp_ip=SegPhys(cs)+reg_eip; - CodePageHandler * temp_handler=(CodePageHandler *)get_tlb_readhandler(temp_ip); - if (temp_handler->flags & PFLAG_HASCODE) { - block=temp_handler->FindCacheBlock(temp_ip & 4095); - if (!block) goto restart_core; - cache.block.running->LinkTo(ret==BR_Link2,block); - goto run_block; - } - } - goto restart_core; - } - if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT - return CBRET_NONE; -} - -Bits CPU_Core_Dyn_X86_Trap_Run(void) { - Bits oldCycles = CPU_Cycles; - CPU_Cycles = 1; - cpu.trap_skip = false; - - Bits ret=CPU_Core_Normal_Run(); - if (!cpu.trap_skip) CPU_HW_Interrupt(1); - CPU_Cycles = oldCycles-1; - cpudecoder = &CPU_Core_Dyn_X86_Run; - - return ret; -} - -void CPU_Core_Dyn_X86_Init(void) { - Bits i; - /* Setup the global registers and their flags */ - for (i=0;ilink[index].from; - toblock->link[index].from=this; - } - struct { - Bit16u start,end; //Where the page is the original code - CodePageHandler * handler; //Page containing this code - } page; - struct { - Bit8u * start; //Where in the cache are we - Bitu size; - CacheBlock * next; - Bit8u * wmapmask; - Bit16u maskstart; - Bit16u masklen; - } cache; - struct { - Bitu index; - CacheBlock * next; - } hash; - struct { - CacheBlock * to; - CacheBlock * next; - CacheBlock * from; - } link[2]; - CacheBlock * crossblock; -}; - -static struct { - struct { - CacheBlock * first; - CacheBlock * active; - CacheBlock * free; - CacheBlock * running; - } block; - Bit8u * pos; - CodePageHandler * free_pages; - CodePageHandler * used_pages; - CodePageHandler * last_page; -} cache; - -static CacheBlock link_blocks[2]; - -class CodePageHandler : public PageHandler { -public: - CodePageHandler() { - invalidation_map=NULL; - } - void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) { - phys_page=_phys_page; - old_pagehandler=_old_pagehandler; - flags=old_pagehandler->flags|PFLAG_HASCODE; - flags&=~PFLAG_WRITEABLE; - active_blocks=0; - active_count=16; - memset(&hash_map,0,sizeof(hash_map)); - memset(&write_map,0,sizeof(write_map)); - if (invalidation_map!=NULL) { - free(invalidation_map); - invalidation_map=NULL; - } - } - bool InvalidateRange(Bitu start,Bitu end) { - Bits index=1+(end>>DYN_HASH_SHIFT); - bool is_current_block=false; - Bit32u ip_point=SegPhys(cs)+reg_eip; - ip_point=(PAGING_GetPhysicalPage(ip_point)-(phys_page<<12))+(ip_point&0xfff); - while (index>=0) { - Bitu map=0; - for (Bitu count=start;count<=end;count++) map+=write_map[count]; - if (!map) return is_current_block; - CacheBlock * block=hash_map[index]; - while (block) { - CacheBlock * nextblock=block->hash.next; - if (start<=block->page.end && end>=block->page.start) { - if (ip_point<=block->page.end && ip_point>=block->page.start) is_current_block=true; - block->Clear(); - } - block=nextblock; - } - index--; - } - return is_current_block; - } - void writeb(PhysPt addr,Bitu val){ - addr&=4095; - if (host_readb(hostmem+addr)==(Bit8u)val) return; - host_writeb(hostmem+addr,val); - if (!*(Bit8u*)&write_map[addr]) { - if (active_blocks) return; - active_count--; - if (!active_count) Release(); - return; - } else if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } - invalidation_map[addr]++; - InvalidateRange(addr,addr); - } - void writew(PhysPt addr,Bitu val){ - addr&=4095; - if (host_readw(hostmem+addr)==(Bit16u)val) return; - host_writew(hostmem+addr,val); - if (!*(Bit16u*)&write_map[addr]) { - if (active_blocks) return; - active_count--; - if (!active_count) Release(); - return; - } else if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } - (*(Bit16u*)&invalidation_map[addr])+=0x101; - InvalidateRange(addr,addr+1); - } - void writed(PhysPt addr,Bitu val){ - addr&=4095; - if (host_readd(hostmem+addr)==(Bit32u)val) return; - host_writed(hostmem+addr,val); - if (!*(Bit32u*)&write_map[addr]) { - if (active_blocks) return; - active_count--; - if (!active_count) Release(); - return; - } else if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } - (*(Bit32u*)&invalidation_map[addr])+=0x1010101; - InvalidateRange(addr,addr+3); - } - bool writeb_checked(PhysPt addr,Bitu val) { - addr&=4095; - if (host_readb(hostmem+addr)==(Bit8u)val) return false; - if (!*(Bit8u*)&write_map[addr]) { - if (!active_blocks) { - active_count--; - if (!active_count) Release(); - } - } else { - if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } - invalidation_map[addr]++; - if (InvalidateRange(addr,addr)) { - cpu.exception.which=SMC_CURRENT_BLOCK; - return true; - } - } - host_writeb(hostmem+addr,val); - return false; - } - bool writew_checked(PhysPt addr,Bitu val) { - addr&=4095; - if (host_readw(hostmem+addr)==(Bit16u)val) return false; - if (!*(Bit16u*)&write_map[addr]) { - if (!active_blocks) { - active_count--; - if (!active_count) Release(); - } - } else { - if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } - (*(Bit16u*)&invalidation_map[addr])+=0x101; - if (InvalidateRange(addr,addr+1)) { - cpu.exception.which=SMC_CURRENT_BLOCK; - return true; - } - } - host_writew(hostmem+addr,val); - return false; - } - bool writed_checked(PhysPt addr,Bitu val) { - addr&=4095; - if (host_readd(hostmem+addr)==(Bit32u)val) return false; - if (!*(Bit32u*)&write_map[addr]) { - if (!active_blocks) { - active_count--; - if (!active_count) Release(); - } - } else { - if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } - (*(Bit32u*)&invalidation_map[addr])+=0x1010101; - if (InvalidateRange(addr,addr+3)) { - cpu.exception.which=SMC_CURRENT_BLOCK; - return true; - } - } - host_writed(hostmem+addr,val); - return false; - } - void AddCacheBlock(CacheBlock * block) { - Bitu index=1+(block->page.start>>DYN_HASH_SHIFT); - block->hash.next=hash_map[index]; - block->hash.index=index; - hash_map[index]=block; - block->page.handler=this; - active_blocks++; - } - void AddCrossBlock(CacheBlock * block) { - block->hash.next=hash_map[0]; - block->hash.index=0; - hash_map[0]=block; - block->page.handler=this; - active_blocks++; - } - void DelCacheBlock(CacheBlock * block) { - active_blocks--; - active_count=16; - CacheBlock * * where=&hash_map[block->hash.index]; - while (*where!=block) { - where=&((*where)->hash.next); - //Will crash if a block isn't found, which should never happen. - } - *where=block->hash.next; - if (GCC_UNLIKELY(block->cache.wmapmask!=NULL)) { - for (Bitu i=block->page.start;icache.maskstart;i++) { - if (write_map[i]) write_map[i]--; - } - Bitu maskct=0; - for (Bitu i=block->cache.maskstart;i<=block->page.end;i++,maskct++) { - if (write_map[i]) { - if ((maskct>=block->cache.masklen) || (!block->cache.wmapmask[maskct])) write_map[i]--; - } - } - free(block->cache.wmapmask); - block->cache.wmapmask=NULL; - } else { - for (Bitu i=block->page.start;i<=block->page.end;i++) { - if (write_map[i]) write_map[i]--; - } - } - } - void Release(void) { - MEM_SetPageHandler(phys_page,1,old_pagehandler); - PAGING_ClearTLB(); - if (prev) prev->next=next; - else cache.used_pages=next; - if (next) next->prev=prev; - else cache.last_page=prev; - next=cache.free_pages; - cache.free_pages=this; - prev=0; - } - void ClearRelease(void) { - for (Bitu index=0;index<(1+DYN_PAGE_HASH);index++) { - CacheBlock * block=hash_map[index]; - while (block) { - CacheBlock * nextblock=block->hash.next; - block->page.handler=0; //No need, full clear - block->Clear(); - block=nextblock; - } - } - Release(); - } - CacheBlock * FindCacheBlock(Bitu start) { - CacheBlock * block=hash_map[1+(start>>DYN_HASH_SHIFT)]; - while (block) { - if (block->page.start==start) return block; - block=block->hash.next; - } - return 0; - } - HostPt GetHostReadPt(Bitu phys_page) { - hostmem=old_pagehandler->GetHostReadPt(phys_page); - return hostmem; - } - HostPt GetHostWritePt(Bitu phys_page) { - return GetHostReadPt( phys_page ); - } -public: - Bit8u write_map[4096]; - Bit8u * invalidation_map; - CodePageHandler * next, * prev; -private: - PageHandler * old_pagehandler; - CacheBlock * hash_map[1+DYN_PAGE_HASH]; - Bitu active_blocks; - Bitu active_count; - HostPt hostmem; - Bitu phys_page; -}; - - -static INLINE void cache_addunsedblock(CacheBlock * block) { - block->cache.next=cache.block.free; - cache.block.free=block; -} - -static CacheBlock * cache_getblock(void) { - CacheBlock * ret=cache.block.free; - if (!ret) E_Exit("Ran out of CacheBlocks" ); - cache.block.free=ret->cache.next; - ret->cache.next=0; - return ret; -} - -void CacheBlock::Clear(void) { - Bitu ind; - /* Check if this is not a cross page block */ - if (hash.index) for (ind=0;ind<2;ind++) { - CacheBlock * fromlink=link[ind].from; - link[ind].from=0; - while (fromlink) { - CacheBlock * nextlink=fromlink->link[ind].next; - fromlink->link[ind].next=0; - fromlink->link[ind].to=&link_blocks[ind]; - fromlink=nextlink; - } - if (link[ind].to!=&link_blocks[ind]) { - CacheBlock * * wherelink=&link[ind].to->link[ind].from; - while (*wherelink != this && *wherelink) { - wherelink = &(*wherelink)->link[ind].next; - } - if(*wherelink) - *wherelink = (*wherelink)->link[ind].next; - else - LOG(LOG_CPU,LOG_ERROR)("Cache anomaly. please investigate"); - } - } else - cache_addunsedblock(this); - if (crossblock) { - crossblock->crossblock=0; - crossblock->Clear(); - crossblock=0; - } - if (page.handler) { - page.handler->DelCacheBlock(this); - page.handler=0; - } - if (cache.wmapmask){ - free(cache.wmapmask); - cache.wmapmask=NULL; - } -} - - -static CacheBlock * cache_openblock(void) { - CacheBlock * block=cache.block.active; - /* check for enough space in this block */ - Bitu size=block->cache.size; - CacheBlock * nextblock=block->cache.next; - if (block->page.handler) - block->Clear(); - while (sizecache.size; - CacheBlock * tempblock=nextblock->cache.next; - if (nextblock->page.handler) - nextblock->Clear(); - cache_addunsedblock(nextblock); - nextblock=tempblock; - } -skipresize: - block->cache.size=size; - block->cache.next=nextblock; - cache.pos=block->cache.start; - return block; -} - -static void cache_closeblock(void) { - CacheBlock * block=cache.block.active; - block->link[0].to=&link_blocks[0]; - block->link[1].to=&link_blocks[1]; - block->link[0].from=0; - block->link[1].from=0; - block->link[0].next=0; - block->link[1].next=0; - /* Close the block with correct alignments */ - Bitu written=cache.pos-block->cache.start; - if (written>block->cache.size) { - if (!block->cache.next) { - if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun 1 %d",written-block->cache.size); - } else E_Exit("CacheBlock overrun 2 written %d size %d",written,block->cache.size); - } else { - Bitu new_size; - Bitu left=block->cache.size-written; - /* Smaller than cache align then don't bother to resize */ - if (left>CACHE_ALIGN) { - new_size=((written-1)|(CACHE_ALIGN-1))+1; - CacheBlock * newblock=cache_getblock(); - newblock->cache.start=block->cache.start+new_size; - newblock->cache.size=block->cache.size-new_size; - newblock->cache.next=block->cache.next; - block->cache.next=newblock; - block->cache.size=new_size; - } - } - /* Advance the active block pointer */ - if (!block->cache.next) { -// LOG_MSG("Cache full restarting"); - cache.block.active=cache.block.first; - } else { - cache.block.active=block->cache.next; - } -} - -static INLINE void cache_addb(Bit8u val) { - *cache.pos++=val; -} - -static INLINE void cache_addw(Bit16u val) { - *(Bit16u*)cache.pos=val; - cache.pos+=2; -} - -static INLINE void cache_addd(Bit32u val) { - *(Bit32u*)cache.pos=val; - cache.pos+=4; -} - - -static void gen_return(BlockReturn retcode); - -static Bit8u * cache_code_start_ptr=NULL; -static Bit8u * cache_code=NULL; -static Bit8u * cache_code_link_blocks=NULL; -static CacheBlock * cache_blocks=NULL; - -/* Define temporary pagesize so the MPROTECT case and the regular case share as much code as possible */ -#if (C_HAVE_MPROTECT) -#define PAGESIZE_TEMP PAGESIZE -#else -#define PAGESIZE_TEMP 4096 -#endif - -static bool cache_initialized = false; - -static void cache_init(bool enable) { - Bits i; - if (enable) { - if (cache_initialized) return; - cache_initialized = true; - if (cache_blocks == NULL) { - cache_blocks=(CacheBlock*)malloc(CACHE_BLOCKS*sizeof(CacheBlock)); - if(!cache_blocks) E_Exit("Allocating cache_blocks has failed"); - memset(cache_blocks,0,sizeof(CacheBlock)*CACHE_BLOCKS); - cache.block.free=&cache_blocks[0]; - for (i=0;icache.start=&cache_code[0]; - block->cache.size=CACHE_TOTAL; - block->cache.next=0; //Last block in the list - } - /* Setup the default blocks for block linkage returns */ - cache.pos=&cache_code_link_blocks[0]; - link_blocks[0].cache.start=cache.pos; - gen_return(BR_Link1); - cache.pos=&cache_code_link_blocks[32]; - link_blocks[1].cache.start=cache.pos; - gen_return(BR_Link2); - cache.free_pages=0; - cache.last_page=0; - cache.used_pages=0; - /* Setup the code pages */ - for (i=0;inext=cache.free_pages; - cache.free_pages=newpage; - } - } -} - -static void cache_close(void) { -/* for (;;) { - if (cache.used_pages) { - CodePageHandler * cpage=cache.used_pages; - CodePageHandler * npage=cache.used_pages->next; - cpage->ClearRelease(); - delete cpage; - cache.used_pages=npage; - } else break; - } - if (cache_blocks != NULL) { - free(cache_blocks); - cache_blocks = NULL; - } - if (cache_code_start_ptr != NULL) { - ### care: under windows VirtualFree() has to be used if - ### VirtualAlloc was used for memory allocation - free(cache_code_start_ptr); - cache_code_start_ptr = NULL; - } - cache_code = NULL; - cache_code_link_blocks = NULL; - cache_initialized = false; */ -} diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h deleted file mode 100644 index d4ad1be..0000000 --- a/src/cpu/core_dyn_x86/decoder.h +++ /dev/null @@ -1,2680 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: decoder.h,v 1.57 2009/03/29 17:32:20 qbix79 Exp $ */ - -#define X86_DYNFPU_DH_ENABLED -#define X86_INLINED_MEMACCESS - - -enum REP_Type { - REP_NONE=0,REP_NZ,REP_Z -}; - -static struct DynDecode { - PhysPt code; - PhysPt code_start; - PhysPt op_start; - bool big_op; - bool big_addr; - REP_Type rep; - Bitu cycles; - CacheBlock * block; - CacheBlock * active_block; - struct { - CodePageHandler * code; - Bitu index; - Bit8u * wmap; - Bit8u * invmap; - Bitu first; - } page; - struct { - Bitu val; - Bitu mod; - Bitu rm; - Bitu reg; - } modrm; - DynReg * segprefix; -} decode; - -static bool MakeCodePage(Bitu lin_addr,CodePageHandler * &cph) { - Bit8u rdval; - //Ensure page contains memory: - if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true; - PageHandler * handler=get_tlb_readhandler(lin_addr); - if (handler->flags & PFLAG_HASCODE) { - cph=( CodePageHandler *)handler; - return false; - } - if (handler->flags & PFLAG_NOCODE) { - if (PAGING_ForcePageInit(lin_addr)) { - handler=get_tlb_readhandler(lin_addr); - if (handler->flags & PFLAG_HASCODE) { - cph=( CodePageHandler *)handler; - return false; - } - } - if (handler->flags & PFLAG_NOCODE) { - LOG_MSG("DYNX86:Can't run code in this page!"); - cph=0; return false; - } - } - Bitu lin_page=lin_addr >> 12; - Bitu phys_page=lin_page; - if (!PAGING_MakePhysPage(phys_page)) { - LOG_MSG("DYNX86:Can't find physpage"); - cph=0; return false; - } - /* Find a free CodePage */ - if (!cache.free_pages) { - if (cache.used_pages!=decode.page.code) cache.used_pages->ClearRelease(); - else { - if ((cache.used_pages->next) && (cache.used_pages->next!=decode.page.code)) - cache.used_pages->next->ClearRelease(); - else { - LOG_MSG("DYNX86:Invalid cache links"); - cache.used_pages->ClearRelease(); - } - } - } - CodePageHandler * cpagehandler=cache.free_pages; - cache.free_pages=cache.free_pages->next; - cpagehandler->prev=cache.last_page; - cpagehandler->next=0; - if (cache.last_page) cache.last_page->next=cpagehandler; - cache.last_page=cpagehandler; - if (!cache.used_pages) cache.used_pages=cpagehandler; - cpagehandler->SetupAt(phys_page,handler); - MEM_SetPageHandler(phys_page,1,cpagehandler); - PAGING_UnlinkPages(lin_page,1); - cph=cpagehandler; - return false; -} - -static Bit8u decode_fetchb(void) { - if (GCC_UNLIKELY(decode.page.index>=4096)) { - /* Advance to the next page */ - decode.active_block->page.end=4095; - /* trigger possible page fault here */ - decode.page.first++; - Bitu fetchaddr=decode.page.first << 12; - mem_readb(fetchaddr); - MakeCodePage(fetchaddr,decode.page.code); - CacheBlock * newblock=cache_getblock(); - decode.active_block->crossblock=newblock; - newblock->crossblock=decode.active_block; - decode.active_block=newblock; - decode.active_block->page.start=0; - decode.page.code->AddCrossBlock(decode.active_block); - decode.page.wmap=decode.page.code->write_map; - decode.page.invmap=decode.page.code->invalidation_map; - decode.page.index=0; - } - decode.page.wmap[decode.page.index]+=0x01; - decode.page.index++; - decode.code+=1; - return mem_readb(decode.code-1); -} -static Bit16u decode_fetchw(void) { - if (GCC_UNLIKELY(decode.page.index>=4095)) { - Bit16u val=decode_fetchb(); - val|=decode_fetchb() << 8; - return val; - } - *(Bit16u *)&decode.page.wmap[decode.page.index]+=0x0101; - decode.code+=2;decode.page.index+=2; - return mem_readw(decode.code-2); -} -static Bit32u decode_fetchd(void) { - if (GCC_UNLIKELY(decode.page.index>=4093)) { - Bit32u val=decode_fetchb(); - val|=decode_fetchb() << 8; - val|=decode_fetchb() << 16; - val|=decode_fetchb() << 24; - return val; - /* Advance to the next page */ - } - *(Bit32u *)&decode.page.wmap[decode.page.index]+=0x01010101; - decode.code+=4;decode.page.index+=4; - return mem_readd(decode.code-4); -} - -#define START_WMMEM 64 - -static INLINE void decode_increase_wmapmask(Bitu size) { - Bitu mapidx; - CacheBlock* activecb=decode.active_block; - if (GCC_UNLIKELY(!activecb->cache.wmapmask)) { - activecb->cache.wmapmask=(Bit8u*)malloc(START_WMMEM); - memset(activecb->cache.wmapmask,0,START_WMMEM); - activecb->cache.maskstart=decode.page.index; - activecb->cache.masklen=START_WMMEM; - mapidx=0; - } else { - mapidx=decode.page.index-activecb->cache.maskstart; - if (GCC_UNLIKELY(mapidx+size>=activecb->cache.masklen)) { - Bitu newmasklen=activecb->cache.masklen*4; - if (newmasklencache.wmapmask,activecb->cache.masklen); - free(activecb->cache.wmapmask); - activecb->cache.wmapmask=tempmem; - activecb->cache.masklen=newmasklen; - } - } - switch (size) { - case 1 : activecb->cache.wmapmask[mapidx]+=0x01; break; - case 2 : (*(Bit16u*)&activecb->cache.wmapmask[mapidx])+=0x0101; break; - case 4 : (*(Bit32u*)&activecb->cache.wmapmask[mapidx])+=0x01010101; break; - } -} - -static bool decode_fetchb_imm(Bitu & val) { - if (decode.page.index<4096) { - HostPt tlb_addr=get_tlb_read(decode.code); - if (tlb_addr) { - val=(Bitu)(tlb_addr+decode.code); - decode_increase_wmapmask(1); - decode.code++; - decode.page.index++; - return true; - } - } - val=(Bit32u)decode_fetchb(); - return false; -} -static bool decode_fetchw_imm(Bitu & val) { - if (decode.page.index<4095) { - HostPt tlb_addr=get_tlb_read(decode.code); - if (tlb_addr) { - val=(Bitu)(tlb_addr+decode.code); - decode_increase_wmapmask(2); - decode.code+=2; - decode.page.index+=2; - return true; - } - } - val=decode_fetchw(); - return false; -} -static bool decode_fetchd_imm(Bitu & val) { - if (decode.page.index<4093) { - HostPt tlb_addr=get_tlb_read(decode.code); - if (tlb_addr) { - val=(Bitu)(tlb_addr+decode.code); - decode_increase_wmapmask(4); - decode.code+=4; - decode.page.index+=4; - return true; - } - } - val=decode_fetchd(); - return false; -} - - -static void dyn_reduce_cycles(void) { - gen_protectflags(); - if (!decode.cycles) decode.cycles++; - gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles); -} - -static void dyn_save_noncritical_regs(void) { - gen_releasereg(DREG(EAX)); - gen_releasereg(DREG(ECX)); - gen_releasereg(DREG(EDX)); - gen_releasereg(DREG(EBX)); - gen_releasereg(DREG(ESP)); - gen_releasereg(DREG(EBP)); - gen_releasereg(DREG(ESI)); - gen_releasereg(DREG(EDI)); -} - -static void dyn_save_critical_regs(void) { - dyn_save_noncritical_regs(); - gen_releasereg(DREG(FLAGS)); - gen_releasereg(DREG(EIP)); - gen_releasereg(DREG(CYCLES)); -} - -static void dyn_set_eip_last_end(DynReg * endreg) { - gen_protectflags(); - gen_lea(endreg,DREG(EIP),0,0,decode.code-decode.code_start); - gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start); -} - -static INLINE void dyn_set_eip_end(void) { - gen_protectflags(); - gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.code-decode.code_start); -} - -static INLINE void dyn_set_eip_end(DynReg * endreg) { - gen_protectflags(); - if (cpu.code.big) gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EIP)); - else gen_extend_word(false,DREG(TMPW),DREG(EIP)); - gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(TMPW),decode.code-decode.code_start); -} - -static INLINE void dyn_set_eip_last(void) { - gen_protectflags(); - gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.op_start-decode.code_start); -} - - -enum save_info_type {db_exception, cycle_check, normal, fpu_restore}; - - -static struct { - save_info_type type; - DynState state; - Bit8u * branch_pos; - Bit32u eip_change; - Bitu cycles; - Bit8u * return_pos; -} save_info[512]; - -Bitu used_save_info=0; - - -static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags) { - reg_flags=(dflags&FMASK_TEST) | (reg_flags&(~FMASK_TEST)); - reg_eip+=eip_add; - CPU_Cycles-=cycle_sub; - if (cpu.exception.which==SMC_CURRENT_BLOCK) return BR_SMCBlock; - CPU_Exception(cpu.exception.which,cpu.exception.error); - return BR_Normal; -} - -static void dyn_check_bool_exception(DynReg * check) { - gen_dop_byte(DOP_OR,check,0,check,0); - save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ); - dyn_savestate(&save_info[used_save_info].state); - if (!decode.cycles) decode.cycles++; - save_info[used_save_info].cycles=decode.cycles; - save_info[used_save_info].eip_change=decode.op_start-decode.code_start; - if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff; - save_info[used_save_info].type=db_exception; - used_save_info++; -} - -static void dyn_check_bool_exception_al(void) { - cache_addw(0xc00a); // or al, al - save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ); - dyn_savestate(&save_info[used_save_info].state); - if (!decode.cycles) decode.cycles++; - save_info[used_save_info].cycles=decode.cycles; - save_info[used_save_info].eip_change=decode.op_start-decode.code_start; - if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff; - save_info[used_save_info].type=db_exception; - used_save_info++; -} - -#include "pic.h" - -static void dyn_check_irqrequest(void) { - gen_load_host(&PIC_IRQCheck,DREG(TMPB),4); - gen_dop_word(DOP_OR,true,DREG(TMPB),DREG(TMPB)); - save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ); - gen_releasereg(DREG(TMPB)); - dyn_savestate(&save_info[used_save_info].state); - if (!decode.cycles) decode.cycles++; - save_info[used_save_info].cycles=decode.cycles; - save_info[used_save_info].eip_change=decode.code-decode.code_start; - if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff; - save_info[used_save_info].type=normal; - used_save_info++; -} - -static void dyn_check_bool_exception_ne(void) { - save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z); - dyn_savestate(&save_info[used_save_info].state); - if (!decode.cycles) decode.cycles++; - save_info[used_save_info].cycles=decode.cycles; - save_info[used_save_info].eip_change=decode.op_start-decode.code_start; - if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff; - save_info[used_save_info].type=db_exception; - used_save_info++; -} - -static void dyn_fill_blocks(void) { - for (Bitu sct=0; sctindex<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.state_used))); - gen_releasereg(DREG(TMPB)); - dyn_synchstate(&save_info[sct].state); - gen_create_jump(save_info[sct].return_pos); - break; - } - } - used_save_info=0; -} - - -#if !defined(X86_INLINED_MEMACCESS) -static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) { - gen_protectflags(); - gen_call_function((void *)&mem_readb_checked,"%Dd%Id",addr,&core_dyn.readdata); - dyn_check_bool_exception_al(); - gen_mov_host(&core_dyn.readdata,dst,1,high); -} -static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) { - gen_protectflags(); - if (high) gen_call_function((void *)&mem_writeb_checked,"%Dd%Dh",addr,val); - else gen_call_function((void *)&mem_writeb_checked,"%Dd%Dd",addr,val); - dyn_check_bool_exception_al(); -} -static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) { - gen_protectflags(); - if (dword) gen_call_function((void *)&mem_readd_checked,"%Dd%Id",addr,&core_dyn.readdata); - else gen_call_function((void *)&mem_readw_checked,"%Dd%Id",addr,&core_dyn.readdata); - dyn_check_bool_exception_al(); - gen_mov_host(&core_dyn.readdata,dst,dword?4:2); -} -static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) { - gen_protectflags(); - if (dword) gen_call_function((void *)&mem_writed_checked,"%Dd%Dd",addr,val); - else gen_call_function((void *)&mem_writew_checked,"%Dd%Dd",addr,val); - dyn_check_bool_exception_al(); -} -static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) { - gen_protectflags(); - gen_call_function((void *)&mem_readb_checked,"%Ddr%Id",addr,&core_dyn.readdata); - dyn_check_bool_exception_al(); - gen_mov_host(&core_dyn.readdata,dst,1,high); -} -static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) { - gen_protectflags(); - if (high) gen_call_function((void *)&mem_writeb_checked,"%Ddr%Dh",addr,val); - else gen_call_function((void *)&mem_writeb_checked,"%Ddr%Dd",addr,val); - dyn_check_bool_exception_al(); -} -static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) { - gen_protectflags(); - if (dword) gen_call_function((void *)&mem_readd_checked,"%Ddr%Id",addr,&core_dyn.readdata); - else gen_call_function((void *)&mem_readw_checked,"%Ddr%Id",addr,&core_dyn.readdata); - dyn_check_bool_exception_al(); - gen_mov_host(&core_dyn.readdata,dst,dword?4:2); -} -static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) { - gen_protectflags(); - if (dword) gen_call_function((void *)&mem_writed_checked,"%Ddr%Dd",addr,val); - else gen_call_function((void *)&mem_writew_checked,"%Ddr%Dd",addr,val); - dyn_check_bool_exception_al(); -} - -#else - -static void dyn_read_intro(DynReg * addr,bool release_addr=true) { - gen_protectflags(); - - if (addr->genreg) { - // addr already in a register - Bit8u reg_idx=(Bit8u)addr->genreg->index; - x86gen.regs[X86_REG_ECX]->Clear(); - if (reg_idx!=1) { - cache_addw(0xc88b+(reg_idx<<8)); //Mov ecx,reg - } - x86gen.regs[X86_REG_EAX]->Clear(); - if (release_addr) gen_releasereg(addr); - } else { - // addr still in memory, directly move into ecx - x86gen.regs[X86_REG_EAX]->Clear(); - x86gen.regs[X86_REG_ECX]->Clear(); - cache_addw(0x0d8b); //Mov ecx,[data] - cache_addd((Bit32u)addr->data); - } - x86gen.regs[X86_REG_EDX]->Clear(); - - cache_addw(0xc18b); // mov eax,ecx -} - -bool mem_readb_checked_dcx86(PhysPt address) { - return get_tlb_readhandler(address)->readb_checked(address, (Bit8u*)(&core_dyn.readdata)); -} - -static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) { - dyn_read_intro(addr,false); - - cache_addw(0xe8c1); // shr eax,0x0c - cache_addb(0x0c); - cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u] - cache_addb(0x85); - cache_addd((Bit32u)(&paging.tlb.read[0])); - cache_addw(0xc085); // test eax,eax - Bit8u* je_loc=gen_create_branch(BR_Z); - - - cache_addw(0x048a); // mov al,[eax+ecx] - cache_addb(0x08); - - Bit8u* jmp_loc=gen_create_jump(); - gen_fill_branch(je_loc); - cache_addb(0x51); // push ecx - cache_addb(0xe8); - cache_addd(((Bit32u)&mem_readb_checked_dcx86) - (Bit32u)cache.pos-4); - cache_addw(0xc483); // add esp,4 - cache_addb(0x04); - cache_addw(0x012c); // sub al,1 - - dyn_check_bool_exception_ne(); - - cache_addw(0x058a); //mov al,[] - cache_addd((Bit32u)(&core_dyn.readdata)); - - gen_fill_jump(jmp_loc); - - x86gen.regs[X86_REG_EAX]->notusable=true; - GenReg * genreg=FindDynReg(dst); - x86gen.regs[X86_REG_EAX]->notusable=false; - cache_addw(0xc08a+(genreg->index<<11)+(high?0x2000:0)); - dst->flags|=DYNFLG_CHANGED; -} - -static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) { - dyn_read_intro(addr); - - cache_addw(0xe8c1); // shr eax,0x0c - cache_addb(0x0c); - cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u] - cache_addb(0x85); - cache_addd((Bit32u)(&paging.tlb.read[0])); - cache_addw(0xc085); // test eax,eax - Bit8u* je_loc=gen_create_branch(BR_Z); - - - cache_addw(0x048a); // mov al,[eax+ecx] - cache_addb(0x08); - - Bit8u* jmp_loc=gen_create_jump(); - gen_fill_branch(je_loc); - cache_addb(0x51); // push ecx - cache_addb(0xe8); - cache_addd(((Bit32u)&mem_readb_checked_dcx86) - (Bit32u)cache.pos-4); - cache_addw(0xc483); // add esp,4 - cache_addb(0x04); - cache_addw(0x012c); // sub al,1 - - dyn_check_bool_exception_ne(); - - cache_addw(0x058a); //mov al,[] - cache_addd((Bit32u)(&core_dyn.readdata)); - - gen_fill_jump(jmp_loc); - - x86gen.regs[X86_REG_EAX]->notusable=true; - GenReg * genreg=FindDynReg(dst); - x86gen.regs[X86_REG_EAX]->notusable=false; - cache_addw(0xc08a+(genreg->index<<11)+(high?0x2000:0)); - dst->flags|=DYNFLG_CHANGED; -} - -bool mem_readd_checked_dcx86(PhysPt address) { - if ((address & 0xfff)<0xffd) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) { - core_dyn.readdata=host_readd(tlb_addr+address); - return false; - } else { - return get_tlb_readhandler(address)->readd_checked(address, &core_dyn.readdata); - } - } else return mem_unalignedreadd_checked(address, &core_dyn.readdata); -} - -static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) { - if (dword) { - dyn_read_intro(addr,false); - - cache_addw(0xe8d1); // shr eax,0x1 - Bit8u* jb_loc1=gen_create_branch(BR_B); - cache_addw(0xe8d1); // shr eax,0x1 - Bit8u* jb_loc2=gen_create_branch(BR_B); - cache_addw(0xe8c1); // shr eax,0x0a - cache_addb(0x0a); - cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u] - cache_addb(0x85); - cache_addd((Bit32u)(&paging.tlb.read[0])); - cache_addw(0xc085); // test eax,eax - Bit8u* je_loc=gen_create_branch(BR_Z); - - GenReg * genreg=FindDynReg(dst,true); - - cache_addw(0x048b+(genreg->index <<(8+3))); // mov dest,[eax+ecx] - cache_addb(0x08); - - Bit8u* jmp_loc=gen_create_jump(); - gen_fill_branch(jb_loc1); - gen_fill_branch(jb_loc2); - gen_fill_branch(je_loc); - cache_addb(0x51); // push ecx - cache_addb(0xe8); - cache_addd(((Bit32u)&mem_readd_checked_dcx86) - (Bit32u)cache.pos-4); - cache_addw(0xc483); // add esp,4 - cache_addb(0x04); - cache_addw(0x012c); // sub al,1 - - dyn_check_bool_exception_ne(); - - gen_mov_host(&core_dyn.readdata,dst,4); - dst->flags|=DYNFLG_CHANGED; - - gen_fill_jump(jmp_loc); - } else { - gen_protectflags(); - gen_call_function((void *)&mem_readw_checked,"%Dd%Id",addr,&core_dyn.readdata); - dyn_check_bool_exception_al(); - gen_mov_host(&core_dyn.readdata,dst,2); - } -} - -static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) { - if (dword) { - dyn_read_intro(addr); - - cache_addw(0xe8d1); // shr eax,0x1 - Bit8u* jb_loc1=gen_create_branch(BR_B); - cache_addw(0xe8d1); // shr eax,0x1 - Bit8u* jb_loc2=gen_create_branch(BR_B); - cache_addw(0xe8c1); // shr eax,0x0a - cache_addb(0x0a); - cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u] - cache_addb(0x85); - cache_addd((Bit32u)(&paging.tlb.read[0])); - cache_addw(0xc085); // test eax,eax - Bit8u* je_loc=gen_create_branch(BR_Z); - - GenReg * genreg=FindDynReg(dst,true); - - cache_addw(0x048b+(genreg->index <<(8+3))); // mov dest,[eax+ecx] - cache_addb(0x08); - - Bit8u* jmp_loc=gen_create_jump(); - gen_fill_branch(jb_loc1); - gen_fill_branch(jb_loc2); - gen_fill_branch(je_loc); - cache_addb(0x51); // push ecx - cache_addb(0xe8); - cache_addd(((Bit32u)&mem_readd_checked_dcx86) - (Bit32u)cache.pos-4); - cache_addw(0xc483); // add esp,4 - cache_addb(0x04); - cache_addw(0x012c); // sub al,1 - - dyn_check_bool_exception_ne(); - - gen_mov_host(&core_dyn.readdata,dst,4); - dst->flags|=DYNFLG_CHANGED; - - gen_fill_jump(jmp_loc); - } else { - gen_protectflags(); - gen_call_function((void *)&mem_readw_checked,"%Ddr%Id",addr,&core_dyn.readdata); - dyn_check_bool_exception_al(); - gen_mov_host(&core_dyn.readdata,dst,2); - } -} - -static void dyn_write_intro(DynReg * addr,bool release_addr=true) { - gen_protectflags(); - - if (addr->genreg) { - // addr in a register - Bit8u reg_idx_addr=(Bit8u)addr->genreg->index; - - x86gen.regs[X86_REG_EAX]->Clear(); - x86gen.regs[X86_REG_EAX]->notusable=true; - x86gen.regs[X86_REG_ECX]->Clear(); - x86gen.regs[X86_REG_ECX]->notusable=true; - - if (reg_idx_addr) { - // addr!=eax - cache_addb(0x8b); //Mov eax,reg - cache_addb(0xc0+reg_idx_addr); - } - if (release_addr) gen_releasereg(addr); - } else { - // addr still in memory, directly move into eax - x86gen.regs[X86_REG_EAX]->Clear(); - x86gen.regs[X86_REG_EAX]->notusable=true; - x86gen.regs[X86_REG_ECX]->Clear(); - x86gen.regs[X86_REG_ECX]->notusable=true; - cache_addb(0xa1); //Mov eax,[data] - cache_addd((Bit32u)addr->data); - } - - cache_addw(0xc88b); // mov ecx,eax -} - -static void dyn_write_byte(DynReg * addr,DynReg * val,bool high) { - dyn_write_intro(addr,false); - - GenReg * genreg=FindDynReg(val); - cache_addw(0xe9c1); // shr ecx,0x0c - cache_addb(0x0c); - cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u] - cache_addb(0x8d); - cache_addd((Bit32u)(&paging.tlb.write[0])); - cache_addw(0xc985); // test ecx,ecx - Bit8u* je_loc=gen_create_branch(BR_Z); - - cache_addw(0x0488+(genreg->index<<11)+(high?0x2000:0)); // mov [eax+ecx],reg - cache_addb(0x08); - - Bit8u* jmp_loc=gen_create_jump(); - gen_fill_branch(je_loc); - - if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8)); - cache_addb(0x52); // push edx - cache_addb(0x50+genreg->index); - cache_addb(0x50); // push eax - if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8)); - cache_addb(0xe8); - cache_addd(((Bit32u)&mem_writeb_checked) - (Bit32u)cache.pos-4); - cache_addw(0xc483); // add esp,8 - cache_addb(0x08); - cache_addw(0x012c); // sub al,1 - cache_addb(0x5a); // pop edx - - // Restore registers to be used again - x86gen.regs[X86_REG_EAX]->notusable=false; - x86gen.regs[X86_REG_ECX]->notusable=false; - - dyn_check_bool_exception_ne(); - - gen_fill_jump(jmp_loc); -} - -static void dyn_write_byte_release(DynReg * addr,DynReg * val,bool high) { - dyn_write_intro(addr); - - GenReg * genreg=FindDynReg(val); - cache_addw(0xe9c1); // shr ecx,0x0c - cache_addb(0x0c); - cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u] - cache_addb(0x8d); - cache_addd((Bit32u)(&paging.tlb.write[0])); - cache_addw(0xc985); // test ecx,ecx - Bit8u* je_loc=gen_create_branch(BR_Z); - - cache_addw(0x0488+(genreg->index<<11)+(high?0x2000:0)); // mov [eax+ecx],reg - cache_addb(0x08); - - Bit8u* jmp_loc=gen_create_jump(); - gen_fill_branch(je_loc); - - cache_addb(0x52); // push edx - if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8)); - cache_addb(0x50+genreg->index); - cache_addb(0x50); // push eax - if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8)); - cache_addb(0xe8); - cache_addd(((Bit32u)&mem_writeb_checked) - (Bit32u)cache.pos-4); - cache_addw(0xc483); // add esp,8 - cache_addb(0x08); - cache_addw(0x012c); // sub al,1 - cache_addb(0x5a); // pop edx - - // Restore registers to be used again - x86gen.regs[X86_REG_EAX]->notusable=false; - x86gen.regs[X86_REG_ECX]->notusable=false; - - dyn_check_bool_exception_ne(); - - gen_fill_jump(jmp_loc); -} - -static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) { - if (dword) { - dyn_write_intro(addr,false); - - GenReg * genreg=FindDynReg(val); - cache_addw(0xe9d1); // shr ecx,0x1 - Bit8u* jb_loc1=gen_create_branch(BR_B); - cache_addw(0xe9d1); // shr ecx,0x1 - Bit8u* jb_loc2=gen_create_branch(BR_B); - cache_addw(0xe9c1); // shr ecx,0x0a - cache_addb(0x0a); - cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u] - cache_addb(0x8d); - cache_addd((Bit32u)(&paging.tlb.write[0])); - cache_addw(0xc985); // test ecx,ecx - Bit8u* je_loc=gen_create_branch(BR_Z); - - cache_addw(0x0489+(genreg->index <<(8+3))); // mov [eax+ecx],reg - cache_addb(0x08); - - Bit8u* jmp_loc=gen_create_jump(); - gen_fill_branch(jb_loc1); - gen_fill_branch(jb_loc2); - gen_fill_branch(je_loc); - - cache_addb(0x52); // push edx - cache_addb(0x50+genreg->index); - cache_addb(0x50); // push eax - cache_addb(0xe8); - cache_addd(((Bit32u)&mem_writed_checked) - (Bit32u)cache.pos-4); - cache_addw(0xc483); // add esp,8 - cache_addb(0x08); - cache_addw(0x012c); // sub al,1 - cache_addb(0x5a); // pop edx - - // Restore registers to be used again - x86gen.regs[X86_REG_EAX]->notusable=false; - x86gen.regs[X86_REG_ECX]->notusable=false; - - dyn_check_bool_exception_ne(); - - gen_fill_jump(jmp_loc); - } else { - gen_protectflags(); - gen_call_function((void *)&mem_writew_checked,"%Dd%Dd",addr,val); - dyn_check_bool_exception_al(); - } -} - -static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) { - if (dword) { - dyn_write_intro(addr); - - GenReg * genreg=FindDynReg(val); - cache_addw(0xe9d1); // shr ecx,0x1 - Bit8u* jb_loc1=gen_create_branch(BR_B); - cache_addw(0xe9d1); // shr ecx,0x1 - Bit8u* jb_loc2=gen_create_branch(BR_B); - cache_addw(0xe9c1); // shr ecx,0x0a - cache_addb(0x0a); - cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u] - cache_addb(0x8d); - cache_addd((Bit32u)(&paging.tlb.write[0])); - cache_addw(0xc985); // test ecx,ecx - Bit8u* je_loc=gen_create_branch(BR_Z); - - cache_addw(0x0489+(genreg->index <<(8+3))); // mov [eax+ecx],reg - cache_addb(0x08); - - Bit8u* jmp_loc=gen_create_jump(); - gen_fill_branch(jb_loc1); - gen_fill_branch(jb_loc2); - gen_fill_branch(je_loc); - - cache_addb(0x52); // push edx - cache_addb(0x50+genreg->index); - cache_addb(0x50); // push eax - cache_addb(0xe8); - cache_addd(((Bit32u)&mem_writed_checked) - (Bit32u)cache.pos-4); - cache_addw(0xc483); // add esp,8 - cache_addb(0x08); - cache_addw(0x012c); // sub al,1 - cache_addb(0x5a); // pop edx - - // Restore registers to be used again - x86gen.regs[X86_REG_EAX]->notusable=false; - x86gen.regs[X86_REG_ECX]->notusable=false; - - dyn_check_bool_exception_ne(); - - gen_fill_jump(jmp_loc); - } else { - gen_protectflags(); - gen_call_function((void *)&mem_writew_checked,"%Ddr%Dd",addr,val); - dyn_check_bool_exception_al(); - } -} - -#endif - - -static void dyn_push_unchecked(DynReg * dynreg) { - gen_protectflags(); - gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?(-4):(-2)); - gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask); - gen_dop_word_var(DOP_AND,true,DREG(ESP),&cpu.stack.notmask); - gen_dop_word(DOP_OR,true,DREG(ESP),DREG(STACK)); - gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS)); - if (decode.big_op) { - gen_call_function((void *)&mem_writed,"%Drd%Dd",DREG(STACK),dynreg); - } else { - //Can just push the whole 32-bit word as operand - gen_call_function((void *)&mem_writew,"%Drd%Dd",DREG(STACK),dynreg); - } -} - -static void dyn_push(DynReg * dynreg) { - gen_protectflags(); - gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?(-4):(-2)); - gen_dop_word(DOP_MOV,true,DREG(NEWESP),DREG(ESP)); - gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask); - gen_dop_word_var(DOP_AND,true,DREG(NEWESP),&cpu.stack.notmask); - gen_dop_word(DOP_OR,true,DREG(NEWESP),DREG(STACK)); - gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS)); - if (decode.big_op) { - gen_call_function((void *)&mem_writed_checked,"%Drd%Dd",DREG(STACK),dynreg); - } else { - //Can just push the whole 32-bit word as operand - gen_call_function((void *)&mem_writew_checked,"%Drd%Dd",DREG(STACK),dynreg); - } - dyn_check_bool_exception_al(); - /* everything was ok, change register now */ - gen_dop_word(DOP_MOV,true,DREG(ESP),DREG(NEWESP)); - gen_releasereg(DREG(NEWESP)); -} - -static void dyn_pop(DynReg * dynreg,bool checked=true) { - gen_protectflags(); - gen_dop_word(DOP_MOV,true,DREG(STACK),DREG(ESP)); - gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask); - gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS)); - if (checked) { - if (decode.big_op) { - gen_call_function((void *)&mem_readd_checked,"%Drd%Id",DREG(STACK),&core_dyn.readdata); - } else { - gen_call_function((void *)&mem_readw_checked,"%Drd%Id",DREG(STACK),&core_dyn.readdata); - } - dyn_check_bool_exception_al(); - gen_mov_host(&core_dyn.readdata,dynreg,decode.big_op?4:2); - } else { - if (decode.big_op) { - gen_call_function((void *)&mem_readd,"%Rd%Drd",dynreg,DREG(STACK)); - } else { - gen_call_function((void *)&mem_readw,"%Rw%Drd",dynreg,DREG(STACK)); - } - } - if (dynreg!=DREG(ESP)) { - gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?4:2); - gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask); - gen_dop_word_var(DOP_AND,true,DREG(ESP),&cpu.stack.notmask); - gen_dop_word(DOP_OR,true,DREG(ESP),DREG(STACK)); - } -} - -static INLINE void dyn_get_modrm(void) { - decode.modrm.val=decode_fetchb(); - decode.modrm.mod=(decode.modrm.val >> 6) & 3; - decode.modrm.reg=(decode.modrm.val >> 3) & 7; - decode.modrm.rm=(decode.modrm.val & 7); -} - -static void dyn_fill_ea(bool addseg=true, DynReg * reg_ea=DREG(EA)) { - DynReg * segbase; - if (!decode.big_addr) { - Bits imm; - switch (decode.modrm.mod) { - case 0:imm=0;break; - case 1:imm=(Bit8s)decode_fetchb();break; - case 2:imm=(Bit16s)decode_fetchw();break; - } - DynReg * extend_src=reg_ea; - switch (decode.modrm.rm) { - case 0:/* BX+SI */ - gen_lea(reg_ea,DREG(EBX),DREG(ESI),0,imm); - segbase=DREG(DS); - break; - case 1:/* BX+DI */ - gen_lea(reg_ea,DREG(EBX),DREG(EDI),0,imm); - segbase=DREG(DS); - break; - case 2:/* BP+SI */ - gen_lea(reg_ea,DREG(EBP),DREG(ESI),0,imm); - segbase=DREG(SS); - break; - case 3:/* BP+DI */ - gen_lea(reg_ea,DREG(EBP),DREG(EDI),0,imm); - segbase=DREG(SS); - break; - case 4:/* SI */ - if (imm) gen_lea(reg_ea,DREG(ESI),0,0,imm); - else extend_src=DREG(ESI); - segbase=DREG(DS); - break; - case 5:/* DI */ - if (imm) gen_lea(reg_ea,DREG(EDI),0,0,imm); - else extend_src=DREG(EDI); - segbase=DREG(DS); - break; - case 6:/* imm/BP */ - if (!decode.modrm.mod) { - imm=decode_fetchw(); - gen_dop_word_imm(DOP_MOV,true,reg_ea,imm); - segbase=DREG(DS); - goto skip_extend_word; - } else { - gen_lea(reg_ea,DREG(EBP),0,0,imm); - segbase=DREG(SS); - } - break; - case 7: /* BX */ - if (imm) gen_lea(reg_ea,DREG(EBX),0,0,imm); - else extend_src=DREG(EBX); - segbase=DREG(DS); - break; - } - gen_extend_word(false,reg_ea,extend_src); -skip_extend_word: - if (addseg) { - gen_lea(reg_ea,reg_ea,decode.segprefix ? decode.segprefix : segbase,0,0); - } - } else { - Bits imm=0; - DynReg * base=0;DynReg * scaled=0;Bitu scale=0; - switch (decode.modrm.rm) { - case 0:base=DREG(EAX);segbase=DREG(DS);break; - case 1:base=DREG(ECX);segbase=DREG(DS);break; - case 2:base=DREG(EDX);segbase=DREG(DS);break; - case 3:base=DREG(EBX);segbase=DREG(DS);break; - case 4: /* SIB */ - { - Bitu sib=decode_fetchb(); - static DynReg * scaledtable[8]={ - DREG(EAX),DREG(ECX),DREG(EDX),DREG(EBX), - 0,DREG(EBP),DREG(ESI),DREG(EDI), - }; - scaled=scaledtable[(sib >> 3) &7]; - scale=(sib >> 6); - switch (sib & 7) { - case 0:base=DREG(EAX);segbase=DREG(DS);break; - case 1:base=DREG(ECX);segbase=DREG(DS);break; - case 2:base=DREG(EDX);segbase=DREG(DS);break; - case 3:base=DREG(EBX);segbase=DREG(DS);break; - case 4:base=DREG(ESP);segbase=DREG(SS);break; - case 5: - if (decode.modrm.mod) { - base=DREG(EBP);segbase=DREG(SS); - } else { - segbase=DREG(DS); - Bitu val; - if (decode_fetchd_imm(val)) { - gen_mov_host((void*)val,DREG(EA),4); - if (!addseg) { - gen_lea(reg_ea,DREG(EA),scaled,scale,0); - } else { - DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase; - gen_lea(DREG(EA),DREG(EA),scaled,scale,0); - gen_lea(reg_ea,DREG(EA),*seg,0,0); - } - return; - } - imm=(Bit32s)val; - } - break; - case 6:base=DREG(ESI);segbase=DREG(DS);break; - case 7:base=DREG(EDI);segbase=DREG(DS);break; - } - } - break; /* SIB Break */ - case 5: - if (decode.modrm.mod) { - base=DREG(EBP);segbase=DREG(SS); - } else { - imm=(Bit32s)decode_fetchd();segbase=DREG(DS); - } - break; - case 6:base=DREG(ESI);segbase=DREG(DS);break; - case 7:base=DREG(EDI);segbase=DREG(DS);break; - } - switch (decode.modrm.mod) { - case 1:imm=(Bit8s)decode_fetchb();break; - case 2: { - Bitu val; - if (decode_fetchd_imm(val)) { - gen_mov_host((void*)val,DREG(EA),4); - if (!addseg) { - gen_lea(DREG(EA),DREG(EA),scaled,scale,0); - gen_lea(reg_ea,DREG(EA),base,0,0); - } else { - DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase; - if (!base) { - gen_lea(DREG(EA),DREG(EA),scaled,scale,0); - gen_lea(reg_ea,DREG(EA),*seg,0,0); - } else if (!scaled) { - gen_lea(DREG(EA),DREG(EA),*seg,0,0); - gen_lea(reg_ea,DREG(EA),base,0,0); - } else { - gen_lea(DREG(EA),DREG(EA),scaled,scale,0); - gen_lea(DREG(EA),DREG(EA),base,0,0); - gen_lea(reg_ea,DREG(EA),decode.segprefix ? decode.segprefix : segbase,0,0); - } - } - return; - } - - imm=(Bit32s)val; - break; - } - } - if (!addseg) { - gen_lea(reg_ea,base,scaled,scale,imm); - } else { - DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase; - if (!base) gen_lea(reg_ea,*seg,scaled,scale,imm); - else if (!scaled) gen_lea(reg_ea,base,*seg,0,imm); - else { - gen_lea(DREG(EA),base,scaled,scale,imm); - gen_lea(reg_ea,DREG(EA),decode.segprefix ? decode.segprefix : segbase,0,0); - } - } - } -} - - -static void dyn_dop_word_imm(DualOps op,bool dword,DynReg * dr1) { - Bitu val; - if (dword) { - if (decode_fetchd_imm(val)) { - gen_dop_word_imm_mem(op,true,dr1,(void*)val); - return; - } - } else { - if (decode_fetchw_imm(val)) { - gen_dop_word_imm_mem(op,false,dr1,(void*)val); - return; - } - } - gen_dop_word_imm(op,dword,dr1,val); -} - -static void dyn_dop_byte_imm(DualOps op,DynReg * dr1,Bit8u di1) { - Bitu val; - if (decode_fetchb_imm(val)) { - gen_dop_byte_imm_mem(op,dr1,di1,(void*)val); - } else { - gen_dop_byte_imm(op,dr1,di1,(Bit8u)val); - } -} - - -#include "helpers.h" -#include "string.h" - - -static void dyn_dop_ebgb(DualOps op) { - dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3]; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true); - dyn_read_byte(DREG(EA),DREG(TMPB),false); - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else set_skipflags(false); - } - gen_dop_byte(op,DREG(TMPB),0,rm_reg,decode.modrm.reg&4); - if (op!=DOP_CMP) dyn_write_byte_release(DREG(EA),DREG(TMPB),false); - else gen_releasereg(DREG(EA)); - gen_releasereg(DREG(TMPB)); - } else { - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else gen_discardflags(); - } - gen_dop_byte(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,decode.modrm.reg&4); - } -} - - -static void dyn_dop_gbeb(DualOps op) { - dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3]; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true); - dyn_read_byte_release(DREG(EA),DREG(TMPB),false); - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else set_skipflags(false); - } - gen_dop_byte(op,rm_reg,decode.modrm.reg&4,DREG(TMPB),0); - gen_releasereg(DREG(TMPB)); - } else { - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else gen_discardflags(); - } - gen_dop_byte(op,rm_reg,decode.modrm.reg&4,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); - } -} - -static void dyn_mov_ebib(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(); - gen_call_write(DREG(EA),decode_fetchb(),1); - dyn_check_bool_exception_al(); - } else { - gen_dop_byte_imm(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb()); - } -} - -static void dyn_mov_ebgb(void) { - dyn_get_modrm(); - DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_write_byte_release(DREG(EA),rm_reg,rm_regi==4); - } else { - gen_dop_byte(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,rm_regi); - } -} - -static void dyn_mov_gbeb(void) { - dyn_get_modrm(); - DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_read_byte_release(DREG(EA),rm_reg,rm_regi); - } else { - gen_dop_byte(DOP_MOV,rm_reg,rm_regi,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); - } -} - -static void dyn_dop_evgv(DualOps op) { - dyn_get_modrm(); - DynReg * rm_reg=&DynRegs[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true); - dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else set_skipflags(false); - } - gen_dop_word(op,decode.big_op,DREG(TMPW),rm_reg); - if (op!=DOP_CMP) dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op); - else gen_releasereg(DREG(EA)); - gen_releasereg(DREG(TMPW)); - } else { - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else gen_discardflags(); - } - gen_dop_word(op,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg); - } -} - -static void dyn_imul_gvev(Bitu immsize) { - dyn_get_modrm();DynReg * src; - DynReg * rm_reg=&DynRegs[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea();dyn_read_word_release(DREG(EA),DREG(TMPW),decode.big_op); - src=DREG(TMPW); - } else { - src=&DynRegs[decode.modrm.rm]; - } - gen_needflags(); - switch (immsize) { - case 0:gen_imul_word(decode.big_op,rm_reg,src);break; - case 1:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit8s)decode_fetchb());break; - case 2:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit16s)decode_fetchw());break; - case 4:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit32s)decode_fetchd());break; - } - gen_releasereg(DREG(TMPW)); -} - -static void dyn_dop_gvev(DualOps op) { - dyn_get_modrm(); - DynReg * rm_reg=&DynRegs[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true); - dyn_read_word_release(DREG(EA),DREG(TMPW),decode.big_op); - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else set_skipflags(false); - } - gen_dop_word(op,decode.big_op,rm_reg,DREG(TMPW)); - gen_releasereg(DREG(TMPW)); - } else { - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else gen_discardflags(); - } - gen_dop_word(op,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm]); - } -} - -static void dyn_mov_evgv(void) { - dyn_get_modrm(); - DynReg * rm_reg=&DynRegs[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_write_word_release(DREG(EA),rm_reg,decode.big_op); - } else { - gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg); - } -} - -static void dyn_mov_gvev(void) { - dyn_get_modrm(); - DynReg * rm_reg=&DynRegs[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_read_word_release(DREG(EA),rm_reg,decode.big_op); - } else { - gen_dop_word(DOP_MOV,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm]); - } -} -static void dyn_mov_eviv(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(); - gen_call_write(DREG(EA),decode.big_op ? decode_fetchd() : decode_fetchw(),decode.big_op?4:2); - dyn_check_bool_exception_al(); - } else { - gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],decode.big_op ? decode_fetchd() : decode_fetchw()); - } -} - -static void dyn_mov_ev_gb(bool sign) { - dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_read_byte_release(DREG(EA),DREG(TMPB),false); - gen_extend_byte(sign,decode.big_op,rm_reg,DREG(TMPB),0); - gen_releasereg(DREG(TMPB)); - } else { - gen_extend_byte(sign,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); - } -} - -static void dyn_mov_ev_gw(bool sign) { - if (!decode.big_op) { - dyn_mov_gvev(); - return; - } - dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_read_word_release(DREG(EA),DREG(TMPW),false); - gen_extend_word(sign,rm_reg,DREG(TMPW)); - gen_releasereg(DREG(TMPW)); - } else { - gen_extend_word(sign,rm_reg,&DynRegs[decode.modrm.rm]); - } -} - -static void dyn_cmpxchg_evgv(void) { - dyn_get_modrm(); - DynReg * rm_reg=&DynRegs[decode.modrm.reg]; - gen_protectflags(); - if (decode.modrm.mod<3) { - gen_releasereg(DREG(EAX)); - gen_releasereg(DREG(TMPB)); - gen_releasereg(rm_reg); - - dyn_fill_ea(); - dyn_read_word(DREG(EA),DREG(TMPB),decode.big_op); - gen_dop_word(DOP_CMP,decode.big_op,DREG(EAX),DREG(TMPB)); - Bit8u * branch=gen_create_branch(BR_NZ); - - // eax==mem -> mem:=rm_reg - dyn_write_word_release(DREG(EA),rm_reg,decode.big_op); - gen_setzeroflag(); - gen_releasereg(DREG(EAX)); - gen_releasereg(DREG(TMPB)); - gen_releasereg(rm_reg); - - Bit8u * jump=gen_create_jump(); - - gen_fill_branch(branch); - // eax!=mem -> eax:=mem - dyn_write_word_release(DREG(EA),DREG(TMPB),decode.big_op); // cmpxchg always issues write - gen_dop_word(DOP_MOV,decode.big_op,DREG(EAX),DREG(TMPB)); - gen_clearzeroflag(); - gen_releasereg(DREG(EAX)); - gen_releasereg(DREG(TMPB)); - gen_releasereg(rm_reg); - - gen_fill_jump(jump); - } else { - gen_releasereg(DREG(EAX)); - gen_releasereg(&DynRegs[decode.modrm.rm]); - gen_releasereg(rm_reg); - - gen_dop_word(DOP_CMP,decode.big_op,DREG(EAX),&DynRegs[decode.modrm.rm]); - Bit8u * branch=gen_create_branch(BR_NZ); - - // eax==rm -> rm:=rm_reg - gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg); - gen_setzeroflag(); - gen_releasereg(DREG(EAX)); - gen_releasereg(&DynRegs[decode.modrm.rm]); - gen_releasereg(rm_reg); - - Bit8u * jump=gen_create_jump(); - - gen_fill_branch(branch); - // eax!=rm -> eax:=rm - gen_dop_word(DOP_MOV,decode.big_op,DREG(EAX),&DynRegs[decode.modrm.rm]); - gen_clearzeroflag(); - gen_releasereg(DREG(EAX)); - gen_releasereg(&DynRegs[decode.modrm.rm]); - gen_releasereg(rm_reg); - - gen_fill_jump(jump); - } -} - -static void dyn_dshift_ev_gv(bool left,bool immediate) { - dyn_get_modrm(); - DynReg * rm_reg=&DynRegs[decode.modrm.reg]; - DynReg * ea_reg; - if (decode.modrm.mod<3) { - dyn_fill_ea();ea_reg=DREG(TMPW); - dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); - } else ea_reg=&DynRegs[decode.modrm.rm]; - gen_needflags(); - if (immediate) gen_dshift_imm(decode.big_op,left,ea_reg,rm_reg,decode_fetchb()); - else gen_dshift_cl(decode.big_op,left,ea_reg,rm_reg,DREG(ECX)); - if (decode.modrm.mod<3) { - dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op); - gen_releasereg(DREG(TMPW)); - } -} - - -static DualOps grp1_table[8]={DOP_ADD,DOP_OR,DOP_ADC,DOP_SBB,DOP_AND,DOP_SUB,DOP_XOR,DOP_CMP}; -static void dyn_grp1_eb_ib(void) { - dyn_get_modrm(); - DualOps op=grp1_table[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true); - dyn_read_byte(DREG(EA),DREG(TMPB),false); - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else set_skipflags(false); - } - gen_dop_byte_imm(op,DREG(TMPB),0,decode_fetchb()); - if (op!=DOP_CMP) dyn_write_byte_release(DREG(EA),DREG(TMPB),false); - else gen_releasereg(DREG(EA)); - gen_releasereg(DREG(TMPB)); - } else { - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else gen_discardflags(); - } - dyn_dop_byte_imm(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); - } -} - -static void dyn_grp1_ev_ivx(bool withbyte) { - dyn_get_modrm(); - DualOps op=grp1_table[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true); - dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else set_skipflags(false); - } - if (!withbyte) { - dyn_dop_word_imm(op,decode.big_op,DREG(TMPW)); - } else { - gen_dop_word_imm(op,decode.big_op,DREG(TMPW),(Bit8s)decode_fetchb()); - } - if (op!=DOP_CMP) dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op); - else gen_releasereg(DREG(EA)); - gen_releasereg(DREG(TMPW)); - } else { - if (op<=DOP_TEST) { - if (op==DOP_ADC || op==DOP_SBB) gen_needcarry(); - else gen_discardflags(); - } - if (!withbyte) { - dyn_dop_word_imm(op,decode.big_op,&DynRegs[decode.modrm.rm]); - } else { - gen_dop_word_imm(op,decode.big_op,&DynRegs[decode.modrm.rm],(Bit8s)decode_fetchb()); - } - } -} - -enum grp2_types { - grp2_1,grp2_imm,grp2_cl, -}; - -static void dyn_grp2_eb(grp2_types type) { - dyn_get_modrm();DynReg * src;Bit8u src_i; - if (decode.modrm.mod<3) { - dyn_fill_ea();dyn_read_byte(DREG(EA),DREG(TMPB),false); - src=DREG(TMPB); - src_i=0; - } else { - src=&DynRegs[decode.modrm.rm&3]; - src_i=decode.modrm.rm&4; - } - switch (type) { - case grp2_1: - /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */ - if (decode.modrm.reg < 4) gen_needflags(); - else gen_discardflags(); - gen_shift_byte_imm(decode.modrm.reg,src,src_i,1); - break; - case grp2_imm: { - Bit8u imm=decode_fetchb(); - if (imm) { - /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */ - if (decode.modrm.reg < 4) gen_needflags(); - else gen_discardflags(); - gen_shift_byte_imm(decode.modrm.reg,src,src_i,imm); - } else return; - } - break; - case grp2_cl: - gen_needflags(); /* flags must not be changed on ecx==0 */ - gen_shift_byte_cl (decode.modrm.reg,src,src_i,DREG(ECX)); - break; - } - if (decode.modrm.mod<3) { - dyn_write_byte_release(DREG(EA),src,false); - gen_releasereg(src); - } -} - -static void dyn_grp2_ev(grp2_types type) { - dyn_get_modrm();DynReg * src; - if (decode.modrm.mod<3) { - dyn_fill_ea();dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); - src=DREG(TMPW); - } else { - src=&DynRegs[decode.modrm.rm]; - } - switch (type) { - case grp2_1: - /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */ - if (decode.modrm.reg < 4) gen_needflags(); - else gen_discardflags(); - gen_shift_word_imm(decode.modrm.reg,decode.big_op,src,1); - break; - case grp2_imm: { - Bitu val; - if (decode_fetchb_imm(val)) { - if (decode.modrm.reg < 4) gen_needflags(); - else gen_discardflags(); - gen_load_host((void*)val,DREG(TMPB),1); - gen_shift_word_cl(decode.modrm.reg,decode.big_op,src,DREG(TMPB)); - gen_releasereg(DREG(TMPB)); - break; - } - Bit8u imm=(Bit8u)val; - if (imm) { - /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */ - if (decode.modrm.reg < 4) gen_needflags(); - else gen_discardflags(); - gen_shift_word_imm(decode.modrm.reg,decode.big_op,src,imm); - } else return; - } - break; - case grp2_cl: - gen_needflags(); /* flags must not be changed on ecx==0 */ - gen_shift_word_cl (decode.modrm.reg,decode.big_op,src,DREG(ECX)); - break; - } - if (decode.modrm.mod<3) { - dyn_write_word_release(DREG(EA),src,decode.big_op); - gen_releasereg(src); - } -} - -static void dyn_grp3_eb(void) { - dyn_get_modrm();DynReg * src;Bit8u src_i; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - if ((decode.modrm.reg==0) || (decode.modrm.reg==3)) set_skipflags(true); - dyn_read_byte(DREG(EA),DREG(TMPB),false); - src=DREG(TMPB);src_i=0; - } else { - src=&DynRegs[decode.modrm.rm&3]; - src_i=decode.modrm.rm&4; - } - switch (decode.modrm.reg) { - case 0x0: /* test eb,ib */ - set_skipflags(false);gen_dop_byte_imm(DOP_TEST,src,src_i,decode_fetchb()); - goto skipsave; - case 0x2: /* NOT Eb */ - gen_sop_byte(SOP_NOT,src,src_i); - break; - case 0x3: /* NEG Eb */ - set_skipflags(false);gen_sop_byte(SOP_NEG,src,src_i); - break; - case 0x4: /* mul Eb */ - gen_needflags();gen_mul_byte(false,DREG(EAX),src,src_i); - goto skipsave; - case 0x5: /* imul Eb */ - gen_needflags();gen_mul_byte(true,DREG(EAX),src,src_i); - goto skipsave; - case 0x6: /* div Eb */ - case 0x7: /* idiv Eb */ - /* EAX could be used, so precache it */ - if (decode.modrm.mod==3) - gen_dop_byte(DOP_MOV,DREG(TMPB),0,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); - gen_releasereg(DREG(EAX)); - gen_call_function((decode.modrm.reg==6) ? (void *)&dyn_helper_divb : (void *)&dyn_helper_idivb, - "%Rd%Dd",DREG(TMPB),DREG(TMPB)); - dyn_check_bool_exception(DREG(TMPB)); - goto skipsave; - } - /* Save the result if memory op */ - if (decode.modrm.mod<3) dyn_write_byte_release(DREG(EA),src,false); -skipsave: - gen_releasereg(DREG(TMPB));gen_releasereg(DREG(EA)); -} - -static void dyn_grp3_ev(void) { - dyn_get_modrm();DynReg * src; - if (decode.modrm.mod<3) { - dyn_fill_ea();src=DREG(TMPW); - if ((decode.modrm.reg==0) || (decode.modrm.reg==3)) set_skipflags(true); - dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); - } else src=&DynRegs[decode.modrm.rm]; - switch (decode.modrm.reg) { - case 0x0: /* test ev,iv */ - set_skipflags(false);gen_dop_word_imm(DOP_TEST,decode.big_op,src,decode.big_op ? decode_fetchd() : decode_fetchw()); - goto skipsave; - case 0x2: /* NOT Ev */ - gen_sop_word(SOP_NOT,decode.big_op,src); - break; - case 0x3: /* NEG Eb */ - set_skipflags(false);gen_sop_word(SOP_NEG,decode.big_op,src); - break; - case 0x4: /* mul Eb */ - gen_needflags();gen_mul_word(false,DREG(EAX),DREG(EDX),decode.big_op,src); - goto skipsave; - case 0x5: /* imul Eb */ - gen_needflags();gen_mul_word(true,DREG(EAX),DREG(EDX),decode.big_op,src); - goto skipsave; - case 0x6: /* div Eb */ - case 0x7: /* idiv Eb */ - /* EAX could be used, so precache it */ - if (decode.modrm.mod==3) - gen_dop_word(DOP_MOV,decode.big_op,DREG(TMPW),&DynRegs[decode.modrm.rm]); - gen_releasereg(DREG(EAX));gen_releasereg(DREG(EDX)); - void * func=(decode.modrm.reg==6) ? - (decode.big_op ? (void *)&dyn_helper_divd : (void *)&dyn_helper_divw) : - (decode.big_op ? (void *)&dyn_helper_idivd : (void *)&dyn_helper_idivw); - gen_call_function(func,"%Rd%Dd",DREG(TMPB),DREG(TMPW)); - dyn_check_bool_exception(DREG(TMPB)); - gen_releasereg(DREG(TMPB)); - goto skipsave; - } - /* Save the result if memory op */ - if (decode.modrm.mod<3) dyn_write_word_release(DREG(EA),src,decode.big_op); -skipsave: - gen_releasereg(DREG(TMPW));gen_releasereg(DREG(EA)); -} - -static void dyn_mov_ev_seg(void) { - dyn_get_modrm(); - gen_load_host(&Segs.val[decode.modrm.reg],DREG(TMPW),2); - if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_write_word_release(DREG(EA),DREG(TMPW),false); - } else { - gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW)); - } - gen_releasereg(DREG(TMPW)); -} - -static void dyn_load_seg(SegNames seg,DynReg * src) { - gen_call_function((void *)&CPU_SetSegGeneral,"%Rd%Id%Drw",DREG(TMPB),seg,src); - dyn_check_bool_exception(DREG(TMPB)); - gen_releasereg(DREG(TMPB)); - gen_releasereg(&DynRegs[G_ES+seg]); -} - -static void dyn_load_seg_off_ea(SegNames seg) { - if (decode.modrm.mod<3) { - dyn_fill_ea(); - gen_lea(DREG(TMPB),DREG(EA),0,0,decode.big_op ? 4:2); - dyn_read_word(DREG(TMPB),DREG(TMPB),false); - dyn_read_word_release(DREG(EA),DREG(TMPW),decode.big_op); - dyn_load_seg(seg,DREG(TMPB));gen_releasereg(DREG(TMPB)); - gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.reg],DREG(TMPW)); - } else { - IllegalOption("dyn_load_seg_off_ea"); - } -} - -static void dyn_mov_seg_ev(void) { - dyn_get_modrm(); - SegNames seg=(SegNames)decode.modrm.reg; - if (GCC_UNLIKELY(seg==cs)) IllegalOption("dyn_mov_seg_ev"); - if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_read_word(DREG(EA),DREG(EA),false); - dyn_load_seg(seg,DREG(EA)); - gen_releasereg(DREG(EA)); - } else { - dyn_load_seg(seg,&DynRegs[decode.modrm.rm]); - } -} - -static void dyn_push_seg(SegNames seg) { - gen_load_host(&Segs.val[seg],DREG(TMPW),2); - dyn_push(DREG(TMPW)); - gen_releasereg(DREG(TMPW)); -} - -static void dyn_pop_seg(SegNames seg) { - gen_releasereg(DREG(ESP)); - gen_call_function((void *)&CPU_PopSeg,"%Rd%Id%Id",DREG(TMPB),seg,decode.big_op); - dyn_check_bool_exception(DREG(TMPB)); - gen_releasereg(DREG(TMPB)); - gen_releasereg(&DynRegs[G_ES+seg]); - gen_releasereg(DREG(ESP)); -} - -static void dyn_pop_ev(void) { - dyn_pop(DREG(TMPW)); - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(); -// dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op); - if (decode.big_op) gen_call_function((void *)&mem_writed_inline,"%Ddr%Dd",DREG(EA),DREG(TMPW)); - else gen_call_function((void *)&mem_writew_inline,"%Ddr%Dd",DREG(EA),DREG(TMPW)); - } else { - gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW)); - } - gen_releasereg(DREG(TMPW)); -} - -static void dyn_enter(void) { - gen_releasereg(DREG(ESP)); - gen_releasereg(DREG(EBP)); - Bitu bytes=decode_fetchw(); - Bitu level=decode_fetchb(); - gen_call_function((void *)&CPU_ENTER,"%Id%Id%Id",decode.big_op,bytes,level); -} - -static void dyn_leave(void) { - gen_protectflags(); - gen_dop_word_var(DOP_MOV,true,DREG(TMPW),&cpu.stack.mask); - gen_sop_word(SOP_NOT,true,DREG(TMPW)); - gen_dop_word(DOP_AND,true,DREG(ESP),DREG(TMPW)); - gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EBP)); - gen_dop_word_var(DOP_AND,true,DREG(TMPW),&cpu.stack.mask); - gen_dop_word(DOP_OR,true,DREG(ESP),DREG(TMPW)); - dyn_pop(DREG(EBP),false); - gen_releasereg(DREG(TMPW)); -} - -static void dyn_segprefix(SegNames seg) { -// if (GCC_UNLIKELY((Bitu)(decode.segprefix))) IllegalOption("dyn_segprefix"); - decode.segprefix=&DynRegs[G_ES+seg]; -} - -static void dyn_closeblock(void) { - //Shouldn't create empty block normally but let's do it like this - gen_protectflags(); - dyn_fill_blocks(); - cache_closeblock(); -} - -static void dyn_normal_exit(BlockReturn code) { - gen_protectflags(); - dyn_reduce_cycles(); - dyn_set_eip_last(); - dyn_save_critical_regs(); - gen_return(code); - dyn_closeblock(); -} - -static void dyn_exit_link(Bits eip_change) { - gen_protectflags(); - gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),(decode.code-decode.code_start)+eip_change); - dyn_reduce_cycles(); - dyn_save_critical_regs(); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); - dyn_closeblock(); -} - -static void dyn_branched_exit(BranchTypes btype,Bit32s eip_add) { - Bitu eip_base=decode.code-decode.code_start; - gen_needflags(); - gen_protectflags(); - dyn_save_noncritical_regs(); - gen_releasereg(DREG(FLAGS)); - gen_releasereg(DREG(EIP)); - - gen_preloadreg(DREG(CYCLES)); - gen_preloadreg(DREG(EIP)); - DynReg save_cycles,save_eip; - dyn_saveregister(DREG(CYCLES),&save_cycles); - dyn_saveregister(DREG(EIP),&save_eip); - Bit8u * data=gen_create_branch(btype); - - /* Branch not taken */ - dyn_reduce_cycles(); - gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),eip_base); - gen_releasereg(DREG(CYCLES)); - gen_releasereg(DREG(EIP)); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); - gen_fill_branch(data); - - /* Branch taken */ - dyn_restoreregister(&save_cycles,DREG(CYCLES)); - dyn_restoreregister(&save_eip,DREG(EIP)); - dyn_reduce_cycles(); - gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),eip_base+eip_add); - gen_releasereg(DREG(CYCLES)); - gen_releasereg(DREG(EIP)); - gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlock,cache.start)); - dyn_closeblock(); -} - -enum LoopTypes { - LOOP_NONE,LOOP_NE,LOOP_E,LOOP_JCXZ -}; - -static void dyn_loop(LoopTypes type) { - dyn_reduce_cycles(); - Bits eip_add=(Bit8s)decode_fetchb(); - Bitu eip_base=decode.code-decode.code_start; - Bit8u * branch1=0;Bit8u * branch2=0; - dyn_save_critical_regs(); - switch (type) { - case LOOP_E: - gen_needflags(); - branch1=gen_create_branch(BR_NZ); - break; - case LOOP_NE: - gen_needflags(); - branch1=gen_create_branch(BR_Z); - break; - } - gen_protectflags(); - switch (type) { - case LOOP_E: - case LOOP_NE: - case LOOP_NONE: - gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); - gen_releasereg(DREG(ECX)); - branch2=gen_create_branch(BR_Z); - break; - case LOOP_JCXZ: - gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX)); - gen_releasereg(DREG(ECX)); - branch2=gen_create_branch(BR_NZ); - break; - } - gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base+eip_add); - gen_releasereg(DREG(EIP)); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); - if (branch1) { - gen_fill_branch(branch1); - gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); - gen_releasereg(DREG(ECX)); - } - /* Branch taken */ - gen_fill_branch(branch2); - gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base); - gen_releasereg(DREG(EIP)); - gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlock,cache.start)); - dyn_closeblock(); -} - -static void dyn_ret_near(Bitu bytes) { - gen_protectflags(); - dyn_reduce_cycles(); - dyn_pop(DREG(EIP)); - if (bytes) gen_dop_word_imm(DOP_ADD,true,DREG(ESP),bytes); - dyn_save_critical_regs(); - gen_return(BR_Normal); - dyn_closeblock(); -} - -static void dyn_call_near_imm(void) { - Bits imm; - if (decode.big_op) imm=(Bit32s)decode_fetchd(); - else imm=(Bit16s)decode_fetchw(); - dyn_set_eip_end(DREG(TMPW)); - dyn_push(DREG(TMPW)); - gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(TMPW),imm); - if (cpu.code.big) gen_dop_word(DOP_MOV,true,DREG(EIP),DREG(TMPW)); - else gen_extend_word(false,DREG(EIP),DREG(TMPW)); - dyn_reduce_cycles(); - dyn_save_critical_regs(); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); - dyn_closeblock(); -} - -static void dyn_ret_far(Bitu bytes) { - gen_protectflags(); - dyn_reduce_cycles(); - dyn_set_eip_last_end(DREG(TMPW)); - dyn_flags_gen_to_host(); - dyn_save_critical_regs(); - gen_call_function((void*)&CPU_RET,"%Id%Id%Drd",decode.big_op,bytes,DREG(TMPW)); - gen_return_fast(BR_Normal); - dyn_closeblock(); -} - -static void dyn_call_far_imm(void) { - Bitu sel,off; - off=decode.big_op ? decode_fetchd() : decode_fetchw(); - sel=decode_fetchw(); - dyn_reduce_cycles(); - dyn_set_eip_last_end(DREG(TMPW)); - dyn_flags_gen_to_host(); - dyn_save_critical_regs(); - gen_call_function((void*)&CPU_CALL,"%Id%Id%Id%Drd",decode.big_op,sel,off,DREG(TMPW)); - gen_return_fast(BR_Normal); - dyn_closeblock(); -} - -static void dyn_jmp_far_imm(void) { - Bitu sel,off; - gen_protectflags(); - off=decode.big_op ? decode_fetchd() : decode_fetchw(); - sel=decode_fetchw(); - dyn_reduce_cycles(); - dyn_set_eip_last_end(DREG(TMPW)); - dyn_flags_gen_to_host(); - dyn_save_critical_regs(); - gen_call_function((void*)&CPU_JMP,"%Id%Id%Id%Drd",decode.big_op,sel,off,DREG(TMPW)); - gen_return_fast(BR_Normal); - dyn_closeblock(); -} - -static void dyn_iret(void) { - gen_protectflags(); - dyn_flags_gen_to_host(); - dyn_reduce_cycles(); - dyn_set_eip_last_end(DREG(TMPW)); - dyn_save_critical_regs(); - gen_call_function((void*)&CPU_IRET,"%Id%Drd",decode.big_op,DREG(TMPW)); - gen_return_fast(BR_Iret); - dyn_closeblock(); -} - -static void dyn_interrupt(Bitu num) { - gen_protectflags(); - dyn_flags_gen_to_host(); - dyn_reduce_cycles(); - dyn_set_eip_last_end(DREG(TMPW)); - dyn_save_critical_regs(); - gen_call_function((void*)&CPU_Interrupt,"%Id%Id%Drd",num,CPU_INT_SOFTWARE,DREG(TMPW)); - gen_return_fast(BR_Normal); - dyn_closeblock(); -} - -static void dyn_add_iocheck(Bitu access_size) { - gen_call_function((void *)&CPU_IO_Exception,"%Dw%Id",DREG(EDX),access_size); - dyn_check_bool_exception_al(); -} - -static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) { - gen_call_function((void *)&CPU_IO_Exception,"%Id%Id",accessed_port,access_size); - dyn_check_bool_exception_al(); -} - -#ifdef X86_DYNFPU_DH_ENABLED -#include "dyn_fpu_dh.h" -#define dh_fpu_startup() { \ - fpu_used=true; \ - gen_protectflags(); \ - gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4); \ - gen_dop_word_imm(DOP_CMP,true,DREG(TMPB),0); \ - gen_releasereg(DREG(TMPB)); \ - save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z); \ - dyn_savestate(&save_info[used_save_info].state); \ - save_info[used_save_info].return_pos=cache.pos; \ - save_info[used_save_info].type=fpu_restore; \ - used_save_info++; \ -} -#endif -#include "dyn_fpu.h" - -static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bitu max_opcodes) { - Bits i; -/* Init a load of variables */ - decode.code_start=start; - decode.code=start; - Bitu cycles=0; - decode.page.code=codepage; - decode.page.index=start&4095; - decode.page.wmap=codepage->write_map; - decode.page.invmap=codepage->invalidation_map; - decode.page.first=start >> 12; - decode.active_block=decode.block=cache_openblock(); - decode.block->page.start=decode.page.index; - codepage->AddCacheBlock(decode.block); - - gen_save_host_direct(&cache.block.running,(Bit32u)decode.block); - for (i=0;i=4)) goto illegalopcode; - opcode=decode_fetchb(); - } else { - opcode=decode_fetchb(); - if (GCC_UNLIKELY(decode.page.invmap && - (decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode; - } - } - switch (opcode) { - - case 0x00:dyn_dop_ebgb(DOP_ADD);break; - case 0x01:dyn_dop_evgv(DOP_ADD);break; - case 0x02:dyn_dop_gbeb(DOP_ADD);break; - case 0x03:dyn_dop_gvev(DOP_ADD);break; - case 0x04:gen_discardflags();gen_dop_byte_imm(DOP_ADD,DREG(EAX),0,decode_fetchb());break; - case 0x05:gen_discardflags();dyn_dop_word_imm(DOP_ADD,decode.big_op,DREG(EAX));break; - case 0x06:dyn_push_seg(es);break; - case 0x07:dyn_pop_seg(es);break; - - case 0x08:dyn_dop_ebgb(DOP_OR);break; - case 0x09:dyn_dop_evgv(DOP_OR);break; - case 0x0a:dyn_dop_gbeb(DOP_OR);break; - case 0x0b:dyn_dop_gvev(DOP_OR);break; - case 0x0c:gen_discardflags();gen_dop_byte_imm(DOP_OR,DREG(EAX),0,decode_fetchb());break; - case 0x0d:gen_discardflags();gen_dop_word_imm(DOP_OR,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x0e:dyn_push_seg(cs);break; - case 0x0f: - { - Bitu dual_code=decode_fetchb(); - switch (dual_code) { - /* Short conditional jumps */ - case 0x80:case 0x81:case 0x82:case 0x83:case 0x84:case 0x85:case 0x86:case 0x87: - case 0x88:case 0x89:case 0x8a:case 0x8b:case 0x8c:case 0x8d:case 0x8e:case 0x8f: - dyn_branched_exit((BranchTypes)(dual_code&0xf), - decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); - goto finish_block; - /* PUSH/POP FS */ - case 0xa0:dyn_push_seg(fs);break; - case 0xa1:dyn_pop_seg(fs);break; - /* SHLD Imm/cl*/ - case 0xa4:dyn_dshift_ev_gv(true,true);break; - case 0xa5:dyn_dshift_ev_gv(true,false);break; - /* PUSH/POP GS */ - case 0xa8:dyn_push_seg(gs);break; - case 0xa9:dyn_pop_seg(gs);break; - /* SHRD Imm/cl*/ - case 0xac:dyn_dshift_ev_gv(false,true);break; - case 0xad:dyn_dshift_ev_gv(false,false);break; - /* Imul Ev,Gv */ - case 0xaf:dyn_imul_gvev(0);break; - /* CMPXCHG */ - case 0xb1:dyn_cmpxchg_evgv();break; - /* LFS,LGS */ - case 0xb4: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(fs); - break; - case 0xb5: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(gs); - break; - /* MOVZX Gv,Eb/Ew */ - case 0xb6:dyn_mov_ev_gb(false);break; - case 0xb7:dyn_mov_ev_gw(false);break; - /* MOVSX Gv,Eb/Ew */ - case 0xbe:dyn_mov_ev_gb(true);break; - case 0xbf:dyn_mov_ev_gw(true);break; - - default: - DYN_LOG("Unhandled dual opcode 0F%02X",dual_code); - goto illegalopcode; - } - }break; - - case 0x10:dyn_dop_ebgb(DOP_ADC);break; - case 0x11:dyn_dop_evgv(DOP_ADC);break; - case 0x12:dyn_dop_gbeb(DOP_ADC);break; - case 0x13:dyn_dop_gvev(DOP_ADC);break; - case 0x14:gen_needcarry();gen_dop_byte_imm(DOP_ADC,DREG(EAX),0,decode_fetchb());break; - case 0x15:gen_needcarry();gen_dop_word_imm(DOP_ADC,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x16:dyn_push_seg(ss);break; - case 0x17:dyn_pop_seg(ss);break; - - case 0x18:dyn_dop_ebgb(DOP_SBB);break; - case 0x19:dyn_dop_evgv(DOP_SBB);break; - case 0x1a:dyn_dop_gbeb(DOP_SBB);break; - case 0x1b:dyn_dop_gvev(DOP_SBB);break; - case 0x1c:gen_needcarry();gen_dop_byte_imm(DOP_SBB,DREG(EAX),0,decode_fetchb());break; - case 0x1d:gen_needcarry();gen_dop_word_imm(DOP_SBB,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x1e:dyn_push_seg(ds);break; - case 0x1f:dyn_pop_seg(ds);break; - case 0x20:dyn_dop_ebgb(DOP_AND);break; - case 0x21:dyn_dop_evgv(DOP_AND);break; - case 0x22:dyn_dop_gbeb(DOP_AND);break; - case 0x23:dyn_dop_gvev(DOP_AND);break; - case 0x24:gen_discardflags();gen_dop_byte_imm(DOP_AND,DREG(EAX),0,decode_fetchb());break; - case 0x25:gen_discardflags();dyn_dop_word_imm(DOP_AND,decode.big_op,DREG(EAX));break; - case 0x26:dyn_segprefix(es);goto restart_prefix; - - case 0x28:dyn_dop_ebgb(DOP_SUB);break; - case 0x29:dyn_dop_evgv(DOP_SUB);break; - case 0x2a:dyn_dop_gbeb(DOP_SUB);break; - case 0x2b:dyn_dop_gvev(DOP_SUB);break; - case 0x2c:gen_discardflags();gen_dop_byte_imm(DOP_SUB,DREG(EAX),0,decode_fetchb());break; - case 0x2d:gen_discardflags();gen_dop_word_imm(DOP_SUB,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x2e:dyn_segprefix(cs);goto restart_prefix; - - case 0x30:dyn_dop_ebgb(DOP_XOR);break; - case 0x31:dyn_dop_evgv(DOP_XOR);break; - case 0x32:dyn_dop_gbeb(DOP_XOR);break; - case 0x33:dyn_dop_gvev(DOP_XOR);break; - case 0x34:gen_discardflags();gen_dop_byte_imm(DOP_XOR,DREG(EAX),0,decode_fetchb());break; - case 0x35:gen_discardflags();gen_dop_word_imm(DOP_XOR,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x36:dyn_segprefix(ss);goto restart_prefix; - - case 0x38:dyn_dop_ebgb(DOP_CMP);break; - case 0x39:dyn_dop_evgv(DOP_CMP);break; - case 0x3a:dyn_dop_gbeb(DOP_CMP);break; - case 0x3b:dyn_dop_gvev(DOP_CMP);break; - case 0x3c:gen_discardflags();gen_dop_byte_imm(DOP_CMP,DREG(EAX),0,decode_fetchb());break; - case 0x3d:gen_discardflags();gen_dop_word_imm(DOP_CMP,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x3e:dyn_segprefix(ds);goto restart_prefix; - - /* INC/DEC general register */ - case 0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47: - gen_needcarry();gen_sop_word(SOP_INC,decode.big_op,&DynRegs[opcode&7]); - break; - case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f: - gen_needcarry();gen_sop_word(SOP_DEC,decode.big_op,&DynRegs[opcode&7]); - break; - /* PUSH/POP General register */ - case 0x50:case 0x51:case 0x52:case 0x53:case 0x55:case 0x56:case 0x57: - dyn_push(&DynRegs[opcode&7]); - break; - case 0x54: /* PUSH SP is special */ - gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(ESP)); - dyn_push(DREG(TMPW)); - gen_releasereg(DREG(TMPW)); - break; - case 0x58:case 0x59:case 0x5a:case 0x5b:case 0x5c:case 0x5d:case 0x5e:case 0x5f: - dyn_pop(&DynRegs[opcode&7]); - break; - case 0x60: /* PUSHA */ - gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(ESP)); - for (i=G_EAX;i<=G_EDI;i++) { - dyn_push_unchecked((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW)); - } - gen_releasereg(DREG(TMPW)); - break; - case 0x61: /* POPA */ - for (i=G_EDI;i>=G_EAX;i--) { - dyn_pop((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW),false); - } - gen_releasereg(DREG(TMPW)); - break; - //segprefix FS,GS - case 0x64:dyn_segprefix(fs);goto restart_prefix; - case 0x65:dyn_segprefix(gs);goto restart_prefix; - //Push immediates - //Operand size - case 0x66:decode.big_op=!cpu.code.big;goto restart_prefix; - //Address size - case 0x67:decode.big_addr=!cpu.code.big;goto restart_prefix; - case 0x68: /* PUSH Iv */ - gen_dop_word_imm(DOP_MOV,decode.big_op,DREG(TMPW),decode.big_op ? decode_fetchd() : decode_fetchw()); - dyn_push(DREG(TMPW)); - gen_releasereg(DREG(TMPW)); - break; - /* Imul Ivx */ - case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break; - case 0x6a: /* PUSH Ibx */ - gen_dop_word_imm(DOP_MOV,true,DREG(TMPW),(Bit8s)decode_fetchb()); - dyn_push(DREG(TMPW)); - gen_releasereg(DREG(TMPW)); - break; - /* Imul Ibx */ - case 0x6b:dyn_imul_gvev(1);break; - /* Short conditional jumps */ - case 0x70:case 0x71:case 0x72:case 0x73:case 0x74:case 0x75:case 0x76:case 0x77: - case 0x78:case 0x79:case 0x7a:case 0x7b:case 0x7c:case 0x7d:case 0x7e:case 0x7f: - dyn_branched_exit((BranchTypes)(opcode&0xf),(Bit8s)decode_fetchb()); - goto finish_block; - /* Group 1 */ - case 0x80:dyn_grp1_eb_ib();break; - case 0x81:dyn_grp1_ev_ivx(false);break; - case 0x82:dyn_grp1_eb_ib();break; - case 0x83:dyn_grp1_ev_ivx(true);break; - /* TEST Gb,Eb Gv,Ev */ - case 0x84:dyn_dop_gbeb(DOP_TEST);break; - case 0x85:dyn_dop_gvev(DOP_TEST);break; - /* XCHG Eb,Gb Ev,Gv */ - case 0x86:dyn_dop_ebgb(DOP_XCHG);break; - case 0x87:dyn_dop_evgv(DOP_XCHG);break; - /* MOV e,g and g,e */ - case 0x88:dyn_mov_ebgb();break; - case 0x89:dyn_mov_evgv();break; - case 0x8a:dyn_mov_gbeb();break; - case 0x8b:dyn_mov_gvev();break; - /* MOV ev,seg */ - case 0x8c:dyn_mov_ev_seg();break; - /* LEA Gv */ - case 0x8d: - dyn_get_modrm(); - if (decode.big_op) { - dyn_fill_ea(false,&DynRegs[decode.modrm.reg]); - } else { - dyn_fill_ea(false); - gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.reg],DREG(EA)); - gen_releasereg(DREG(EA)); - } - break; - /* Mov seg,ev */ - case 0x8e:dyn_mov_seg_ev();break; - /* POP Ev */ - case 0x8f:dyn_pop_ev();break; - case 0x90: //NOP - case 0x9b: //WAIT/FWAIT - break; - //XCHG ax,reg - case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97: - gen_dop_word(DOP_XCHG,decode.big_op,DREG(EAX),&DynRegs[opcode&07]); - break; - /* CBW/CWDE */ - case 0x98: - gen_cbw(decode.big_op,DREG(EAX)); - break; - /* CWD/CDQ */ - case 0x99: - gen_cwd(decode.big_op,DREG(EAX),DREG(EDX)); - break; - /* CALL FAR Ip */ - case 0x9a:dyn_call_far_imm();goto finish_block; - case 0x9c: //PUSHF - gen_protectflags(); - gen_releasereg(DREG(ESP)); - dyn_flags_gen_to_host(); - gen_call_function((void *)&CPU_PUSHF,"%Rd%Id",DREG(TMPB),decode.big_op); - dyn_check_bool_exception(DREG(TMPB)); - gen_releasereg(DREG(TMPB)); - break; - case 0x9d: //POPF - gen_releasereg(DREG(ESP)); - gen_releasereg(DREG(FLAGS)); - gen_call_function((void *)&CPU_POPF,"%Rd%Id",DREG(TMPB),decode.big_op); - dyn_check_bool_exception(DREG(TMPB)); - dyn_flags_host_to_gen(); - gen_releasereg(DREG(TMPB)); - dyn_check_irqrequest(); - break; - /* MOV AL,direct addresses */ - case 0xa0: - gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0, - decode.big_addr ? decode_fetchd() : decode_fetchw()); - dyn_read_byte_release(DREG(EA),DREG(EAX),false); - break; - /* MOV AX,direct addresses */ - case 0xa1: - gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0, - decode.big_addr ? decode_fetchd() : decode_fetchw()); - dyn_read_word_release(DREG(EA),DREG(EAX),decode.big_op); - break; - /* MOV direct address,AL */ - case 0xa2: - if (decode.big_addr) { - Bitu val; - if (decode_fetchd_imm(val)) { - gen_lea_imm_mem(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),(void*)val); - } else { - gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,(Bits)val); - } - dyn_write_byte_release(DREG(EA),DREG(EAX),false); - } else { - gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,decode_fetchw()); - dyn_write_byte_release(DREG(EA),DREG(EAX),false); - } - break; - /* MOV direct addresses,AX */ - case 0xa3: - gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0, - decode.big_addr ? decode_fetchd() : decode_fetchw()); - dyn_write_word_release(DREG(EA),DREG(EAX),decode.big_op); - break; - /* MOVSB/W/D*/ - case 0xa4:dyn_string(STR_MOVSB);break; - case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break; - /* TEST AL,AX Imm */ - case 0xa8:gen_discardflags();gen_dop_byte_imm(DOP_TEST,DREG(EAX),0,decode_fetchb());break; - case 0xa9:gen_discardflags();gen_dop_word_imm(DOP_TEST,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; - /* STOSB/W/D*/ - case 0xaa:dyn_string(STR_STOSB);break; - case 0xab:dyn_string(decode.big_op ? STR_STOSD : STR_STOSW);break; - /* LODSB/W/D*/ - case 0xac:dyn_string(STR_LODSB);break; - case 0xad:dyn_string(decode.big_op ? STR_LODSD : STR_LODSW);break; - //Mov Byte reg,Imm byte - case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7: - gen_dop_byte_imm(DOP_MOV,&DynRegs[opcode&3],opcode&4,decode_fetchb()); - break; - //Mov word reg imm byte,word, - case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf: - if (decode.big_op) { - dyn_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[opcode&7]);break; - } else { - gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[opcode&7],decode_fetchw());break; - } - break; - //GRP2 Eb/Ev,Ib - case 0xc0:dyn_grp2_eb(grp2_imm);break; - case 0xc1:dyn_grp2_ev(grp2_imm);break; - //RET near Iw / Ret - case 0xc2:dyn_ret_near(decode_fetchw());goto finish_block; - case 0xc3:dyn_ret_near(0);goto finish_block; - //LES - case 0xc4: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(es); - break; - //LDS - case 0xc5: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(ds); - break; - // MOV Eb/Ev,Ib/Iv - case 0xc6:dyn_mov_ebib();break; - case 0xc7:dyn_mov_eviv();break; - //ENTER and LEAVE - case 0xc8:dyn_enter();break; - case 0xc9:dyn_leave();break; - //RET far Iw / Ret - case 0xca:dyn_ret_far(decode_fetchw());goto finish_block; - case 0xcb:dyn_ret_far(0);goto finish_block; - /* Interrupt */ -// case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block; - /* IRET */ - case 0xcf:dyn_iret();goto finish_block; - - //GRP2 Eb/Ev,1 - case 0xd0:dyn_grp2_eb(grp2_1);break; - case 0xd1:dyn_grp2_ev(grp2_1);break; - //GRP2 Eb/Ev,CL - case 0xd2:dyn_grp2_eb(grp2_cl);break; - case 0xd3:dyn_grp2_ev(grp2_cl);break; - //FPU -#ifdef CPU_FPU - case 0xd8: -#ifdef X86_DYNFPU_DH_ENABLED - if (dyn_dh_fpu.dh_fpu_enabled) { - if (fpu_used) dh_fpu_esc0(); - else { - dh_fpu_startup(); - dh_fpu_esc0(); - } - } else -#endif - dyn_fpu_esc0(); - break; - case 0xd9: -#ifdef X86_DYNFPU_DH_ENABLED - if (dyn_dh_fpu.dh_fpu_enabled) { - if (fpu_used) dh_fpu_esc1(); - else { - dh_fpu_startup(); - dh_fpu_esc1(); - } - } else -#endif - dyn_fpu_esc1(); - break; - case 0xda: -#ifdef X86_DYNFPU_DH_ENABLED - if (dyn_dh_fpu.dh_fpu_enabled) { - if (fpu_used) dh_fpu_esc2(); - else { - dh_fpu_startup(); - dh_fpu_esc2(); - } - } else -#endif - dyn_fpu_esc2(); - break; - case 0xdb: -#ifdef X86_DYNFPU_DH_ENABLED - if (dyn_dh_fpu.dh_fpu_enabled) { - if (fpu_used) dh_fpu_esc3(); - else { - dh_fpu_startup(); - dh_fpu_esc3(); - } - } else -#endif - dyn_fpu_esc3(); - break; - case 0xdc: -#ifdef X86_DYNFPU_DH_ENABLED - if (dyn_dh_fpu.dh_fpu_enabled) { - if (fpu_used) dh_fpu_esc4(); - else { - dh_fpu_startup(); - dh_fpu_esc4(); - } - } else -#endif - dyn_fpu_esc4(); - break; - case 0xdd: -#ifdef X86_DYNFPU_DH_ENABLED - if (dyn_dh_fpu.dh_fpu_enabled) { - if (fpu_used) dh_fpu_esc5(); - else { - dh_fpu_startup(); - dh_fpu_esc5(); - } - } else -#endif - dyn_fpu_esc5(); - break; - case 0xde: -#ifdef X86_DYNFPU_DH_ENABLED - if (dyn_dh_fpu.dh_fpu_enabled) { - if (fpu_used) dh_fpu_esc6(); - else { - dh_fpu_startup(); - dh_fpu_esc6(); - } - } else -#endif - dyn_fpu_esc6(); - break; - case 0xdf: -#ifdef X86_DYNFPU_DH_ENABLED - if (dyn_dh_fpu.dh_fpu_enabled) { - if (fpu_used) dh_fpu_esc7(); - else { - dh_fpu_startup(); - dh_fpu_esc7(); - } - } else -#endif - dyn_fpu_esc7(); - break; -#endif - //Loops - case 0xe2:dyn_loop(LOOP_NONE);goto finish_block; - case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block; - //IN AL/AX,imm - case 0xe4: { - Bitu port=decode_fetchb(); - dyn_add_iocheck_var(port,1); - gen_call_function((void*)&IO_ReadB,"%Id%Rl",port,DREG(EAX)); - } break; - case 0xe5: { - Bitu port=decode_fetchb(); - dyn_add_iocheck_var(port,decode.big_op?4:2); - if (decode.big_op) { - gen_call_function((void*)&IO_ReadD,"%Id%Rd",port,DREG(EAX)); - } else { - gen_call_function((void*)&IO_ReadW,"%Id%Rw",port,DREG(EAX)); - } - } break; - //OUT imm,AL - case 0xe6: { - Bitu port=decode_fetchb(); - dyn_add_iocheck_var(port,1); - gen_call_function((void*)&IO_WriteB,"%Id%Dl",port,DREG(EAX)); - } break; - case 0xe7: { - Bitu port=decode_fetchb(); - dyn_add_iocheck_var(port,decode.big_op?4:2); - if (decode.big_op) { - gen_call_function((void*)&IO_WriteD,"%Id%Dd",port,DREG(EAX)); - } else { - gen_call_function((void*)&IO_WriteW,"%Id%Dw",port,DREG(EAX)); - } - } break; - case 0xe8: /* CALL Ivx */ - dyn_call_near_imm(); - goto finish_block; - case 0xe9: /* Jmp Ivx */ - dyn_exit_link(decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); - goto finish_block; - case 0xea: /* JMP FAR Ip */ - dyn_jmp_far_imm(); - goto finish_block; - /* Jmp Ibx */ - case 0xeb:dyn_exit_link((Bit8s)decode_fetchb());goto finish_block; - /* IN AL/AX,DX*/ - case 0xec: - dyn_add_iocheck(1); - gen_call_function((void*)&IO_ReadB,"%Dw%Rl",DREG(EDX),DREG(EAX)); - break; - case 0xed: - dyn_add_iocheck(decode.big_op?4:2); - if (decode.big_op) { - gen_call_function((void*)&IO_ReadD,"%Dw%Rd",DREG(EDX),DREG(EAX)); - } else { - gen_call_function((void*)&IO_ReadW,"%Dw%Rw",DREG(EDX),DREG(EAX)); - } - break; - /* OUT DX,AL/AX */ - case 0xee: - dyn_add_iocheck(1); - gen_call_function((void*)&IO_WriteB,"%Dw%Dl",DREG(EDX),DREG(EAX)); - break; - case 0xef: - dyn_add_iocheck(decode.big_op?4:2); - if (decode.big_op) { - gen_call_function((void*)&IO_WriteD,"%Dw%Dd",DREG(EDX),DREG(EAX)); - } else { - gen_call_function((void*)&IO_WriteW,"%Dw%Dw",DREG(EDX),DREG(EAX)); - } - break; - case 0xf0: //LOCK - break; - case 0xf2: //REPNE/NZ - decode.rep=REP_NZ; - goto restart_prefix; - case 0xf3: //REPE/Z - decode.rep=REP_Z; - goto restart_prefix; - /* Change carry flag */ - case 0xf5: //CMC - case 0xf8: //CLC - case 0xf9: //STC - gen_needflags(); - cache_addb(opcode);break; - /* GRP 3 Eb/EV */ - case 0xf6:dyn_grp3_eb();break; - case 0xf7:dyn_grp3_ev();break; - /* Change interrupt flag */ - case 0xfa: //CLI - gen_releasereg(DREG(FLAGS)); - gen_call_function((void *)&CPU_CLI,"%Rd",DREG(TMPB)); - dyn_check_bool_exception(DREG(TMPB)); - gen_releasereg(DREG(TMPB)); - break; - case 0xfb: //STI - gen_releasereg(DREG(FLAGS)); - gen_call_function((void *)&CPU_STI,"%Rd",DREG(TMPB)); - dyn_check_bool_exception(DREG(TMPB)); - gen_releasereg(DREG(TMPB)); - dyn_check_irqrequest(); - if (max_opcodes<=0) max_opcodes=1; //Allow 1 extra opcode - break; - case 0xfc: //CLD - gen_protectflags(); - gen_dop_word_imm(DOP_AND,true,DREG(FLAGS),~FLAG_DF); - gen_save_host_direct(&cpu.direction,1); - break; - case 0xfd: //STD - gen_protectflags(); - gen_dop_word_imm(DOP_OR,true,DREG(FLAGS),FLAG_DF); - gen_save_host_direct(&cpu.direction,-1); - break; - /* GRP 4 Eb and callback's */ - case 0xfe: - dyn_get_modrm(); - switch (decode.modrm.reg) { - case 0x0://INC Eb - case 0x1://DEC Eb - if (decode.modrm.mod<3) { - dyn_fill_ea();dyn_read_byte(DREG(EA),DREG(TMPB),false); - gen_needcarry(); - gen_sop_byte(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,DREG(TMPB),0); - dyn_write_byte_release(DREG(EA),DREG(TMPB),false); - gen_releasereg(DREG(TMPB)); - } else { - gen_needcarry(); - gen_sop_byte(decode.modrm.reg==0 ? SOP_INC : SOP_DEC, - &DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); - } - break; - case 0x7: //CALBACK Iw - gen_save_host_direct(&core_dyn.callback,decode_fetchw()); - dyn_set_eip_end(); - dyn_reduce_cycles(); - dyn_save_critical_regs(); - gen_return(BR_CallBack); - dyn_closeblock(); - goto finish_block; - } - break; - - case 0xff: - { - dyn_get_modrm();DynReg * src; - if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); - src=DREG(TMPW); - } else src=&DynRegs[decode.modrm.rm]; - switch (decode.modrm.reg) { - case 0x0://INC Ev - case 0x1://DEC Ev - gen_needcarry(); - gen_sop_word(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,decode.big_op,src); - if (decode.modrm.mod<3){ - dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op); - gen_releasereg(DREG(TMPW)); - } - break; - case 0x2: /* CALL Ev */ - gen_lea(DREG(TMPB),DREG(EIP),0,0,decode.code-decode.code_start); - dyn_push(DREG(TMPB)); - gen_releasereg(DREG(TMPB)); - gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),src); - goto core_close_block; - case 0x4: /* JMP Ev */ - gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),src); - goto core_close_block; - case 0x3: /* CALL Ep */ - case 0x5: /* JMP Ep */ - gen_protectflags(); - dyn_flags_gen_to_host(); - gen_lea(DREG(EA),DREG(EA),0,0,decode.big_op ? 4: 2); - dyn_read_word(DREG(EA),DREG(EA),false); - dyn_set_eip_last_end(DREG(TMPB)); - dyn_save_critical_regs(); - gen_call_function( - decode.modrm.reg == 3 ? (void*)&CPU_CALL : (void*)&CPU_JMP, - decode.big_op ? "%Id%Drw%Drd%Drd" : "%Id%Drw%Drw%Drd", - decode.big_op,DREG(EA),DREG(TMPW),DREG(TMPB)); - dyn_flags_host_to_gen(); - goto core_close_block; - case 0x6: /* PUSH Ev */ - gen_releasereg(DREG(EA)); - dyn_push(src); - break; - default: - IllegalOption("opcode 0xff"); - }} - break; - default: -// DYN_LOG("Dynamic unhandled opcode %X",opcode); - goto illegalopcode; - } - } - /* Normal exit because of max opcodes reached */ - dyn_set_eip_end(); -core_close_block: - dyn_reduce_cycles(); - dyn_save_critical_regs(); - gen_return(BR_Normal); - dyn_closeblock(); - goto finish_block; -illegalopcode: - dyn_set_eip_last(); - dyn_reduce_cycles(); - dyn_save_critical_regs(); - gen_return(BR_Opcode); - dyn_closeblock(); - goto finish_block; -#if (C_DEBUG) - dyn_set_eip_last(); - dyn_reduce_cycles(); - dyn_save_critical_regs(); - gen_return(BR_OpcodeFull); - dyn_closeblock(); - goto finish_block; -#endif -finish_block: - /* Setup the correct end-address */ - decode.active_block->page.end=--decode.page.index; -// LOG_MSG("Created block size %d start %d end %d",decode.block->cache.size,decode.block->page.start,decode.block->page.end); - return decode.block; -} diff --git a/src/cpu/core_dyn_x86/dyn_fpu.h b/src/cpu/core_dyn_x86/dyn_fpu.h deleted file mode 100644 index b2db1e8..0000000 --- a/src/cpu/core_dyn_x86/dyn_fpu.h +++ /dev/null @@ -1,665 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dyn_fpu.h,v 1.3 2007/06/14 17:47:24 c2woody Exp $ */ - -#include "dosbox.h" -#if C_FPU - -#include -#include -#include "cross.h" -#include "mem.h" -#include "fpu.h" -#include "cpu.h" - - -static void FPU_FDECSTP(){ - TOP = (TOP - 1) & 7; -} - -static void FPU_FINCSTP(){ - TOP = (TOP + 1) & 7; -} - -static void FPU_FNSTCW(PhysPt addr){ - mem_writew(addr,fpu.cw); -} - -static void FPU_FFREE(Bitu st) { - fpu.tags[st]=TAG_Empty; -} - - -#if C_FPU_X86 -#include "../../fpu/fpu_instructions_x86.h" -#else -#include "../../fpu/fpu_instructions.h" -#endif - - -#define dyn_fpu_top() { \ - gen_protectflags(); \ - gen_load_host(&TOP,DREG(EA),4); \ - gen_dop_word_imm(DOP_ADD,true,DREG(EA),decode.modrm.rm); \ - gen_dop_word_imm(DOP_AND,true,DREG(EA),7); \ - gen_load_host(&TOP,DREG(TMPB),4); \ -} - -static void dyn_eatree() { - Bitu group=(decode.modrm.val >> 3) & 7; - switch (group){ - case 0x00: /* FADD ST,STi */ - gen_call_function((void*)&FPU_FADD_EA,"%Ddr",DREG(TMPB)); - break; - case 0x01: /* FMUL ST,STi */ - gen_call_function((void*)&FPU_FMUL_EA,"%Ddr",DREG(TMPB)); - break; - case 0x02: /* FCOM STi */ - gen_call_function((void*)&FPU_FCOM_EA,"%Ddr",DREG(TMPB)); - break; - case 0x03: /* FCOMP STi */ - gen_call_function((void*)&FPU_FCOM_EA,"%Ddr",DREG(TMPB)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x04: /* FSUB ST,STi */ - gen_call_function((void*)&FPU_FSUB_EA,"%Ddr",DREG(TMPB)); - break; - case 0x05: /* FSUBR ST,STi */ - gen_call_function((void*)&FPU_FSUBR_EA,"%Ddr",DREG(TMPB)); - break; - case 0x06: /* FDIV ST,STi */ - gen_call_function((void*)&FPU_FDIV_EA,"%Ddr",DREG(TMPB)); - break; - case 0x07: /* FDIVR ST,STi */ - gen_call_function((void*)&FPU_FDIVR_EA,"%Ddr",DREG(TMPB)); - break; - default: - break; - } -} - -static void dyn_fpu_esc0(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - dyn_fpu_top(); - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - switch (group){ - case 0x00: //FADD ST,STi / - gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x01: // FMUL ST,STi / - gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x02: // FCOM STi / - gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x03: // FCOMP STi / - gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x04: // FSUB ST,STi / - gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x05: // FSUBR ST,STi / - gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x06: // FDIV ST,STi / - gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x07: // FDIVR ST,STi / - gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - default: - break; - } - } else { - dyn_fill_ea(); - gen_call_function((void*)&FPU_FLD_F32_EA,"%Ddr",DREG(EA)); - gen_load_host(&TOP,DREG(TMPB),4); - dyn_eatree(); - } -} - -static void dyn_fpu_esc1(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - switch (group){ - case 0x00: /* FLD STi */ - gen_protectflags(); - gen_load_host(&TOP,DREG(EA),4); - gen_dop_word_imm(DOP_ADD,true,DREG(EA),decode.modrm.rm); - gen_dop_word_imm(DOP_AND,true,DREG(EA),7); - gen_call_function((void*)&FPU_PREP_PUSH,""); - gen_load_host(&TOP,DREG(TMPB),4); - gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x01: /* FXCH STi */ - dyn_fpu_top(); - gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x02: /* FNOP */ - gen_call_function((void*)&FPU_FNOP,""); - break; - case 0x03: /* FSTP STi */ - dyn_fpu_top(); - gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x04: - switch(sub){ - case 0x00: /* FCHS */ - gen_call_function((void*)&FPU_FCHS,""); - break; - case 0x01: /* FABS */ - gen_call_function((void*)&FPU_FABS,""); - break; - case 0x02: /* UNKNOWN */ - case 0x03: /* ILLEGAL */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - case 0x04: /* FTST */ - gen_call_function((void*)&FPU_FTST,""); - break; - case 0x05: /* FXAM */ - gen_call_function((void*)&FPU_FXAM,""); - break; - case 0x06: /* FTSTP (cyrix)*/ - case 0x07: /* UNKNOWN */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - } - break; - case 0x05: - switch(sub){ - case 0x00: /* FLD1 */ - gen_call_function((void*)&FPU_FLD1,""); - break; - case 0x01: /* FLDL2T */ - gen_call_function((void*)&FPU_FLDL2T,""); - break; - case 0x02: /* FLDL2E */ - gen_call_function((void*)&FPU_FLDL2E,""); - break; - case 0x03: /* FLDPI */ - gen_call_function((void*)&FPU_FLDPI,""); - break; - case 0x04: /* FLDLG2 */ - gen_call_function((void*)&FPU_FLDLG2,""); - break; - case 0x05: /* FLDLN2 */ - gen_call_function((void*)&FPU_FLDLN2,""); - break; - case 0x06: /* FLDZ*/ - gen_call_function((void*)&FPU_FLDZ,""); - break; - case 0x07: /* ILLEGAL */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - } - break; - case 0x06: - switch(sub){ - case 0x00: /* F2XM1 */ - gen_call_function((void*)&FPU_F2XM1,""); - break; - case 0x01: /* FYL2X */ - gen_call_function((void*)&FPU_FYL2X,""); - break; - case 0x02: /* FPTAN */ - gen_call_function((void*)&FPU_FPTAN,""); - break; - case 0x03: /* FPATAN */ - gen_call_function((void*)&FPU_FPATAN,""); - break; - case 0x04: /* FXTRACT */ - gen_call_function((void*)&FPU_FXTRACT,""); - break; - case 0x05: /* FPREM1 */ - gen_call_function((void*)&FPU_FPREM1,""); - break; - case 0x06: /* FDECSTP */ - gen_call_function((void*)&FPU_FDECSTP,""); - break; - case 0x07: /* FINCSTP */ - gen_call_function((void*)&FPU_FINCSTP,""); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - } - break; - case 0x07: - switch(sub){ - case 0x00: /* FPREM */ - gen_call_function((void*)&FPU_FPREM,""); - break; - case 0x01: /* FYL2XP1 */ - gen_call_function((void*)&FPU_FYL2XP1,""); - break; - case 0x02: /* FSQRT */ - gen_call_function((void*)&FPU_FSQRT,""); - break; - case 0x03: /* FSINCOS */ - gen_call_function((void*)&FPU_FSINCOS,""); - break; - case 0x04: /* FRNDINT */ - gen_call_function((void*)&FPU_FRNDINT,""); - break; - case 0x05: /* FSCALE */ - gen_call_function((void*)&FPU_FSCALE,""); - break; - case 0x06: /* FSIN */ - gen_call_function((void*)&FPU_FSIN,""); - break; - case 0x07: /* FCOS */ - gen_call_function((void*)&FPU_FCOS,""); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - } - } else { - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - dyn_fill_ea(); - switch(group){ - case 0x00: /* FLD float*/ - gen_protectflags(); - gen_call_function((void*)&FPU_PREP_PUSH,""); - gen_load_host(&TOP,DREG(TMPB),4); - gen_call_function((void*)&FPU_FLD_F32,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x01: /* UNKNOWN */ - LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FST float*/ - gen_call_function((void*)&FPU_FST_F32,"%Ddr",DREG(EA)); - break; - case 0x03: /* FSTP float*/ - gen_call_function((void*)&FPU_FST_F32,"%Ddr",DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x04: /* FLDENV */ - gen_call_function((void*)&FPU_FLDENV,"%Ddr",DREG(EA)); - break; - case 0x05: /* FLDCW */ - gen_call_function((void *)&FPU_FLDCW,"%Ddr",DREG(EA)); - break; - case 0x06: /* FSTENV */ - gen_call_function((void *)&FPU_FSTENV,"%Ddr",DREG(EA)); - break; - case 0x07: /* FNSTCW*/ - gen_call_function((void *)&FPU_FNSTCW,"%Ddr",DREG(EA)); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub); - break; - } - } -} - -static void dyn_fpu_esc2(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - switch(group){ - case 0x05: - switch(sub){ - case 0x01: /* FUCOMPP */ - gen_protectflags(); - gen_load_host(&TOP,DREG(EA),4); - gen_dop_word_imm(DOP_ADD,true,DREG(EA),1); - gen_dop_word_imm(DOP_AND,true,DREG(EA),7); - gen_load_host(&TOP,DREG(TMPB),4); - gen_call_function((void *)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - gen_call_function((void *)&FPU_FPOP,""); - gen_call_function((void *)&FPU_FPOP,""); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub); - break; - } - } else { - dyn_fill_ea(); - gen_call_function((void*)&FPU_FLD_I32_EA,"%Ddr",DREG(EA)); - gen_load_host(&TOP,DREG(TMPB),4); - dyn_eatree(); - } -} - -static void dyn_fpu_esc3(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - switch (group) { - case 0x04: - switch (sub) { - case 0x00: //FNENI - case 0x01: //FNDIS - LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion :%d",sub); - break; - case 0x02: //FNCLEX FCLEX - gen_call_function((void*)&FPU_FCLEX,""); - break; - case 0x03: //FNINIT FINIT - gen_call_function((void*)&FPU_FINIT,""); - break; - case 0x04: //FNSETPM - case 0x05: //FRSTPM -// LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); - break; - default: - E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",group,sub); - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",group,sub); - break; - } - } else { - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - dyn_fill_ea(); - switch(group){ - case 0x00: /* FILD */ - gen_call_function((void*)&FPU_PREP_PUSH,""); - gen_protectflags(); - gen_load_host(&TOP,DREG(TMPB),4); - gen_call_function((void*)&FPU_FLD_I32,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x01: /* FISTTP */ - LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FIST */ - gen_call_function((void*)&FPU_FST_I32,"%Ddr",DREG(EA)); - break; - case 0x03: /* FISTP */ - gen_call_function((void*)&FPU_FST_I32,"%Ddr",DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x05: /* FLD 80 Bits Real */ - gen_call_function((void*)&FPU_PREP_PUSH,""); - gen_call_function((void*)&FPU_FLD_F80,"%Ddr",DREG(EA)); - break; - case 0x07: /* FSTP 80 Bits Real */ - gen_call_function((void*)&FPU_FST_F80,"%Ddr",DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub); - } - } -} - -static void dyn_fpu_esc4(){ - dyn_get_modrm(); - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - if (decode.modrm.val >= 0xc0) { - dyn_fpu_top(); - switch(group){ - case 0x00: /* FADD STi,ST*/ - gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x01: /* FMUL STi,ST*/ - gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x02: /* FCOM*/ - gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x03: /* FCOMP*/ - gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x04: /* FSUBR STi,ST*/ - gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x05: /* FSUB STi,ST*/ - gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x06: /* FDIVR STi,ST*/ - gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x07: /* FDIV STi,ST*/ - gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - default: - break; - } - } else { - dyn_fill_ea(); - gen_call_function((void*)&FPU_FLD_F64_EA,"%Ddr",DREG(EA)); - gen_load_host(&TOP,DREG(TMPB),4); - dyn_eatree(); - } -} - -static void dyn_fpu_esc5(){ - dyn_get_modrm(); - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - if (decode.modrm.val >= 0xc0) { - dyn_fpu_top(); - switch(group){ - case 0x00: /* FFREE STi */ - gen_call_function((void*)&FPU_FFREE,"%Ddr",DREG(EA)); - break; - case 0x01: /* FXCH STi*/ - gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x02: /* FST STi */ - gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x03: /* FSTP STi*/ - gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x04: /* FUCOM STi */ - gen_call_function((void*)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x05: /*FUCOMP STi */ - gen_call_function((void*)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",group,sub); - break; - } - gen_releasereg(DREG(EA)); - gen_releasereg(DREG(TMPB)); - } else { - dyn_fill_ea(); - switch(group){ - case 0x00: /* FLD double real*/ - gen_call_function((void*)&FPU_PREP_PUSH,""); - gen_protectflags(); - gen_load_host(&TOP,DREG(TMPB),4); - gen_call_function((void*)&FPU_FLD_F64,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x01: /* FISTTP longint*/ - LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FST double real*/ - gen_call_function((void*)&FPU_FST_F64,"%Ddr",DREG(EA)); - break; - case 0x03: /* FSTP double real*/ - gen_call_function((void*)&FPU_FST_F64,"%Ddr",DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x04: /* FRSTOR */ - gen_call_function((void*)&FPU_FRSTOR,"%Ddr",DREG(EA)); - break; - case 0x06: /* FSAVE */ - gen_call_function((void*)&FPU_FSAVE,"%Ddr",DREG(EA)); - break; - case 0x07: /*FNSTSW */ - gen_protectflags(); - gen_load_host(&TOP,DREG(TMPB),4); - gen_call_function((void*)&FPU_SET_TOP,"%Dd",DREG(TMPB)); - gen_load_host(&fpu.sw,DREG(TMPB),4); - gen_call_function((void*)&mem_writew,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub); - } - } -} - -static void dyn_fpu_esc6(){ - dyn_get_modrm(); - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - if (decode.modrm.val >= 0xc0) { - dyn_fpu_top(); - switch(group){ - case 0x00: /*FADDP STi,ST*/ - gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x01: /* FMULP STi,ST*/ - gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x02: /* FCOMP5*/ - gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; /* TODO IS THIS ALLRIGHT ????????? */ - case 0x03: /*FCOMPP*/ - if(sub != 1) { - LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",group,sub); - return; - } - gen_load_host(&TOP,DREG(EA),4); - gen_dop_word_imm(DOP_ADD,true,DREG(EA),1); - gen_dop_word_imm(DOP_AND,true,DREG(EA),7); - gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); /* extra pop at the bottom*/ - break; - case 0x04: /* FSUBRP STi,ST*/ - gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x05: /* FSUBP STi,ST*/ - gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x06: /* FDIVRP STi,ST*/ - gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x07: /* FDIVP STi,ST*/ - gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - default: - break; - } - gen_call_function((void*)&FPU_FPOP,""); - } else { - dyn_fill_ea(); - gen_call_function((void*)&FPU_FLD_I16_EA,"%Ddr",DREG(EA)); - gen_load_host(&TOP,DREG(TMPB),4); - dyn_eatree(); - } -} - -static void dyn_fpu_esc7(){ - dyn_get_modrm(); - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - if (decode.modrm.val >= 0xc0) { - switch (group){ - case 0x01: /* FXCH STi*/ - dyn_fpu_top(); - gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - break; - case 0x02: /* FSTP STi*/ - case 0x03: /* FSTP STi*/ - dyn_fpu_top(); - gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x04: - switch(sub){ - case 0x00: /* FNSTSW AX*/ - gen_load_host(&TOP,DREG(TMPB),4); - gen_call_function((void*)&FPU_SET_TOP,"%Ddr",DREG(TMPB)); - gen_mov_host(&fpu.sw,DREG(EAX),2); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub); - break; - } - } else { - dyn_fill_ea(); - switch(group){ - case 0x00: /* FILD Bit16s */ - gen_call_function((void*)&FPU_PREP_PUSH,""); - gen_load_host(&TOP,DREG(TMPB),4); - gen_call_function((void*)&FPU_FLD_I16,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x01: - LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FIST Bit16s */ - gen_call_function((void*)&FPU_FST_I16,"%Ddr",DREG(EA)); - break; - case 0x03: /* FISTP Bit16s */ - gen_call_function((void*)&FPU_FST_I16,"%Ddr",DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x04: /* FBLD packed BCD */ - gen_call_function((void*)&FPU_PREP_PUSH,""); - gen_load_host(&TOP,DREG(TMPB),4); - gen_call_function((void*)&FPU_FBLD,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x05: /* FILD Bit64s */ - gen_call_function((void*)&FPU_PREP_PUSH,""); - gen_load_host(&TOP,DREG(TMPB),4); - gen_call_function((void*)&FPU_FLD_I64,"%Ddr%Ddr",DREG(EA),DREG(TMPB)); - break; - case 0x06: /* FBSTP packed BCD */ - gen_call_function((void*)&FPU_FBST,"%Ddr",DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - case 0x07: /* FISTP Bit64s */ - gen_call_function((void*)&FPU_FST_I64,"%Ddr",DREG(EA)); - gen_call_function((void*)&FPU_FPOP,""); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub); - break; - } - } -} - -#endif diff --git a/src/cpu/core_dyn_x86/dyn_fpu_dh.h b/src/cpu/core_dyn_x86/dyn_fpu_dh.h deleted file mode 100644 index 193f664..0000000 --- a/src/cpu/core_dyn_x86/dyn_fpu_dh.h +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dyn_fpu_dh.h,v 1.5 2007/09/29 13:23:59 c2woody Exp $ */ - -#include "dosbox.h" -#if C_FPU - -static void FPU_FLD_16(PhysPt addr) { - dyn_dh_fpu.temp.m1 = (Bit32u)mem_readw(addr); -} - -static void FPU_FST_16(PhysPt addr) { - mem_writew(addr,(Bit16u)dyn_dh_fpu.temp.m1); -} - -static void FPU_FLD_32(PhysPt addr) { - dyn_dh_fpu.temp.m1 = mem_readd(addr); -} - -static void FPU_FST_32(PhysPt addr) { - mem_writed(addr,dyn_dh_fpu.temp.m1); -} - -static void FPU_FLD_64(PhysPt addr) { - dyn_dh_fpu.temp.m1 = mem_readd(addr); - dyn_dh_fpu.temp.m2 = mem_readd(addr+4); -} - -static void FPU_FST_64(PhysPt addr) { - mem_writed(addr,dyn_dh_fpu.temp.m1); - mem_writed(addr+4,dyn_dh_fpu.temp.m2); -} - -static void FPU_FLD_80(PhysPt addr) { - dyn_dh_fpu.temp.m1 = mem_readd(addr); - dyn_dh_fpu.temp.m2 = mem_readd(addr+4); - dyn_dh_fpu.temp.m3 = mem_readw(addr+8); -} - -static void FPU_FST_80(PhysPt addr) { - mem_writed(addr,dyn_dh_fpu.temp.m1); - mem_writed(addr+4,dyn_dh_fpu.temp.m2); - mem_writew(addr+8,dyn_dh_fpu.temp.m3); -} - -static void FPU_FLDCW_DH(PhysPt addr){ - dyn_dh_fpu.cw = mem_readw(addr); - dyn_dh_fpu.temp.m1 = (Bit32u)(dyn_dh_fpu.cw|0x3f); -} - -static void FPU_FNSTCW_DH(PhysPt addr){ - mem_writew(addr,(Bit16u)(dyn_dh_fpu.cw&0xffff)); -} - -static void FPU_FNINIT_DH(void){ - dyn_dh_fpu.cw = 0x37f; -} - -static void FPU_FSTENV_DH(PhysPt addr){ - if(!cpu.code.big) { - mem_writew(addr+0,(Bit16u)dyn_dh_fpu.cw); - mem_writew(addr+2,(Bit16u)dyn_dh_fpu.temp.m2); - mem_writew(addr+4,dyn_dh_fpu.temp.m3); - } else { - mem_writed(addr+0,dyn_dh_fpu.temp.m1); - mem_writew(addr+0,(Bit16u)dyn_dh_fpu.cw); - mem_writed(addr+4,dyn_dh_fpu.temp.m2); - mem_writed(addr+8,dyn_dh_fpu.temp.m3); - } -} - -static void FPU_FLDENV_DH(PhysPt addr){ - if(!cpu.code.big) { - dyn_dh_fpu.cw = (Bit32u)mem_readw(addr); - dyn_dh_fpu.temp.m1 = dyn_dh_fpu.cw|0x3f; - dyn_dh_fpu.temp.m2 = (Bit32u)mem_readw(addr+2); - dyn_dh_fpu.temp.m3 = mem_readw(addr+4); - } else { - dyn_dh_fpu.cw = (Bit32u)mem_readw(addr); - dyn_dh_fpu.temp.m1 = mem_readd(addr)|0x3f; - dyn_dh_fpu.temp.m2 = mem_readd(addr+4); - dyn_dh_fpu.temp.m3 = mem_readw(addr+8); - dyn_dh_fpu.temp.d1 = mem_readw(addr+10); - } -} - -static void FPU_FSAVE_DH(PhysPt addr){ - if (!cpu.code.big) { - mem_writew(addr,(Bit16u)dyn_dh_fpu.cw); - addr+=2; - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x04]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x05]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x08]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x09]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x0c]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x0d]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x10]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x11]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x14]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x15]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x18]); - mem_writeb(addr++,dyn_dh_fpu.temp_state[0x19]); - for(Bitu i=28;i<108;i++) mem_writeb(addr++,dyn_dh_fpu.temp_state[i]); - } else { - mem_writew(addr,(Bit16u)dyn_dh_fpu.cw); - addr+=2; - for(Bitu i=2;i<108;i++) mem_writeb(addr++,dyn_dh_fpu.temp_state[i]); - } -} - -static void FPU_FRSTOR_DH(PhysPt addr){ - if (!cpu.code.big) { - dyn_dh_fpu.cw = (Bit32u)mem_readw(addr); - dyn_dh_fpu.temp_state[0x00] = mem_readb(addr++)|0x3f; - dyn_dh_fpu.temp_state[0x01] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x04] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x05] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x08] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x09] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x0c] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x0d] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x10] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x11] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x14] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x15] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x18] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0x19] = mem_readb(addr++); - for(Bitu i=28;i<108;i++) dyn_dh_fpu.temp_state[i] = mem_readb(addr++); - } else { - dyn_dh_fpu.cw = (Bit32u)mem_readw(addr); - for(Bitu i=0;i<108;i++) dyn_dh_fpu.temp_state[i] = mem_readb(addr++); - dyn_dh_fpu.temp_state[0]|=0x3f; - } -} - -static void dh_fpu_esc0(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - cache_addb(0xd8); - cache_addb(decode.modrm.val); - } else { - dyn_fill_ea(); - gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA)); - cache_addb(0xd8); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - } -} - -static void dh_fpu_esc1(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - cache_addb(0xd9); - cache_addb(decode.modrm.val); - } else { - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - dyn_fill_ea(); - switch(group){ - case 0x00: /* FLD float*/ - gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA)); - cache_addb(0xd9); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - break; - case 0x01: /* UNKNOWN */ - LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FST float*/ - cache_addb(0xd9); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA)); - break; - case 0x03: /* FSTP float*/ - cache_addb(0xd9); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA)); - break; - case 0x04: /* FLDENV */ - gen_call_function((void*)&FPU_FLDENV_DH,"%Ddr",DREG(EA)); - cache_addb(0xd9); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - break; - case 0x05: /* FLDCW */ - gen_call_function((void *)&FPU_FLDCW_DH,"%Ddr",DREG(EA)); - cache_addb(0xd9); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - break; - case 0x06: /* FSTENV */ - cache_addb(0xd9); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FSTENV_DH,"%Ddr",DREG(EA)); - break; - case 0x07: /* FNSTCW*/ - gen_call_function((void*)&FPU_FNSTCW_DH,"%Ddr",DREG(EA)); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub); - break; - } - } -} - -static void dh_fpu_esc2(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - cache_addb(0xda); - cache_addb(decode.modrm.val); - } else { - dyn_fill_ea(); - gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA)); - cache_addb(0xda); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - } -} - -static void dh_fpu_esc3(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - switch (group) { - case 0x04: - switch (sub) { - case 0x00: //FNENI - case 0x01: //FNDIS - LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion :%d",sub); - break; - case 0x02: //FNCLEX FCLEX - cache_addb(0xdb); - cache_addb(decode.modrm.val); - break; - case 0x03: //FNINIT FINIT - gen_call_function((void*)&FPU_FNINIT_DH,""); - cache_addb(0xdb); - cache_addb(decode.modrm.val); - break; - case 0x04: //FNSETPM - case 0x05: //FRSTPM -// LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); - break; - default: - E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",group,sub); - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",group,sub); - break; - } - } else { - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - dyn_fill_ea(); - switch(group){ - case 0x00: /* FILD */ - gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA)); - cache_addb(0xdb); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - break; - case 0x01: /* FISTTP */ - LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FIST */ - cache_addb(0xdb); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA)); - break; - case 0x03: /* FISTP */ - cache_addb(0xdb); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA)); - break; - case 0x05: /* FLD 80 Bits Real */ - gen_call_function((void*)&FPU_FLD_80,"%Ddr",DREG(EA)); - cache_addb(0xdb); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - break; - case 0x07: /* FSTP 80 Bits Real */ - cache_addb(0xdb); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_80,"%Ddr",DREG(EA)); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub); - } - } -} - -static void dh_fpu_esc4(){ - dyn_get_modrm(); - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - if (decode.modrm.val >= 0xc0) { - cache_addb(0xdc); - cache_addb(decode.modrm.val); - } else { - dyn_fill_ea(); - gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA)); - cache_addb(0xdc); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - } -} - -static void dh_fpu_esc5(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - cache_addb(0xdd); - cache_addb(decode.modrm.val); - } else { - dyn_fill_ea(); - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - switch(group){ - case 0x00: /* FLD double real*/ - gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA)); - cache_addb(0xdd); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - break; - case 0x01: /* FISTTP longint*/ - LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FST double real*/ - cache_addb(0xdd); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA)); - break; - case 0x03: /* FSTP double real*/ - cache_addb(0xdd); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA)); - break; - case 0x04: /* FRSTOR */ - gen_call_function((void*)&FPU_FRSTOR_DH,"%Ddr",DREG(EA)); - cache_addb(0xdd); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp_state[0]))); - break; - case 0x06: /* FSAVE */ - cache_addb(0xdd); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp_state[0]))); - gen_call_function((void*)&FPU_FSAVE_DH,"%Ddr",DREG(EA)); - cache_addb(0xdb); - cache_addb(0xe3); - break; - case 0x07: /* FNSTSW */ - cache_addb(0xdd); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA)); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub); - } - } -} - -static void dh_fpu_esc6(){ - dyn_get_modrm(); - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - if (decode.modrm.val >= 0xc0) { - cache_addb(0xde); - cache_addb(decode.modrm.val); - } else { - dyn_fill_ea(); - gen_call_function((void*)&FPU_FLD_16,"%Ddr",DREG(EA)); - cache_addb(0xde); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - } -} - -static void dh_fpu_esc7(){ - dyn_get_modrm(); - Bitu group=(decode.modrm.val >> 3) & 7; - Bitu sub=(decode.modrm.val & 7); - if (decode.modrm.val >= 0xc0) { - switch (group){ - case 0x01: /* FXCH STi*/ - cache_addb(0xdf); - cache_addb(decode.modrm.val); - break; - case 0x02: /* FSTP STi*/ - case 0x03: /* FSTP STi*/ - cache_addb(0xdf); - cache_addb(decode.modrm.val); - break; - case 0x04: - switch(sub){ - case 0x00: /* FNSTSW AX*/ - cache_addb(0xdd); - cache_addb(0x05|(0x07<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_load_host(&(dyn_dh_fpu.temp.m1),DREG(TMPB),4); - gen_dop_word(DOP_MOV,false,DREG(EAX),DREG(TMPB)); - gen_releasereg(DREG(TMPB)); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub); - break; - } - } else { - dyn_fill_ea(); - switch(group){ - case 0x00: /* FILD Bit16s */ - gen_call_function((void*)&FPU_FLD_16,"%Ddr",DREG(EA)); - cache_addb(0xdf); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - break; - case 0x01: - LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FIST Bit16s */ - cache_addb(0xdf); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA)); - break; - case 0x03: /* FISTP Bit16s */ - cache_addb(0xdf); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA)); - break; - case 0x04: /* FBLD packed BCD */ - gen_call_function((void*)&FPU_FLD_80,"%Ddr",DREG(EA)); - cache_addb(0xdf); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - break; - case 0x05: /* FILD Bit64s */ - gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA)); - cache_addb(0xdf); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - break; - case 0x06: /* FBSTP packed BCD */ - cache_addb(0xdf); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_80,"%Ddr",DREG(EA)); - break; - case 0x07: /* FISTP Bit64s */ - cache_addb(0xdf); - cache_addb(0x05|(decode.modrm.reg<<3)); - cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1))); - gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA)); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub); - break; - } - } -} - -#endif diff --git a/src/cpu/core_dyn_x86/helpers.h b/src/cpu/core_dyn_x86/helpers.h deleted file mode 100644 index 5e718a5..0000000 --- a/src/cpu/core_dyn_x86/helpers.h +++ /dev/null @@ -1,69 +0,0 @@ -static bool dyn_helper_divb(Bit8u val) { - if (!val) return CPU_PrepareException(0,0); - Bitu quo=reg_ax / val; - Bit8u rem=(Bit8u)(reg_ax % val); - Bit8u quo8=(Bit8u)(quo&0xff); - if (quo>0xff) return CPU_PrepareException(0,0); - reg_ah=rem; - reg_al=quo8; - return false; -} - -static bool dyn_helper_idivb(Bit8s val) { - if (!val) return CPU_PrepareException(0,0); - Bits quo=(Bit16s)reg_ax / val; - Bit8s rem=(Bit8s)((Bit16s)reg_ax % val); - Bit8s quo8s=(Bit8s)(quo&0xff); - if (quo!=(Bit16s)quo8s) return CPU_PrepareException(0,0); - reg_ah=rem; - reg_al=quo8s; - return false; -} - -static bool dyn_helper_divw(Bit16u val) { - if (!val) return CPU_PrepareException(0,0); - Bitu num=(reg_dx<<16)|reg_ax; - Bitu quo=num/val; - Bit16u rem=(Bit16u)(num % val); - Bit16u quo16=(Bit16u)(quo&0xffff); - if (quo!=(Bit32u)quo16) return CPU_PrepareException(0,0); - reg_dx=rem; - reg_ax=quo16; - return false; -} - -static bool dyn_helper_idivw(Bit16s val) { - if (!val) return CPU_PrepareException(0,0); - Bits num=(reg_dx<<16)|reg_ax; - Bits quo=num/val; - Bit16s rem=(Bit16s)(num % val); - Bit16s quo16s=(Bit16s)quo; - if (quo!=(Bit32s)quo16s) return CPU_PrepareException(0,0); - reg_dx=rem; - reg_ax=quo16s; - return false; -} - -static bool dyn_helper_divd(Bit32u val) { - if (!val) return CPU_PrepareException(0,0); - Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax; - Bit64u quo=num/val; - Bit32u rem=(Bit32u)(num % val); - Bit32u quo32=(Bit32u)(quo&0xffffffff); - if (quo!=(Bit64u)quo32) return CPU_PrepareException(0,0); - reg_edx=rem; - reg_eax=quo32; - return false; -} - -static bool dyn_helper_idivd(Bit32s val) { - if (!val) return CPU_PrepareException(0,0); - Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax; - Bit64s quo=num/val; - Bit32s rem=(Bit32s)(num % val); - Bit32s quo32s=(Bit32s)(quo&0xffffffff); - if (quo!=(Bit64s)quo32s) return CPU_PrepareException(0,0); - reg_edx=rem; - reg_eax=quo32s; - return false; -} diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h deleted file mode 100644 index 1e96e5c..0000000 --- a/src/cpu/core_dyn_x86/risc_x86.h +++ /dev/null @@ -1,1072 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_x86.h,v 1.31 2008/08/06 18:31:26 c2woody Exp $ */ - -static void gen_init(void); - -/* End of needed */ - -#define X86_REGS 7 -#define X86_REG_EAX 0x00 -#define X86_REG_ECX 0x01 -#define X86_REG_EDX 0x02 -#define X86_REG_EBX 0x03 -#define X86_REG_EBP 0x04 -#define X86_REG_ESI 0x05 -#define X86_REG_EDI 0x06 - -#define X86_REG_MASK(_REG_) (1 << X86_REG_ ## _REG_) - -static struct { - bool flagsactive; - Bitu last_used; - GenReg * regs[X86_REGS]; -} x86gen; - -class GenReg { -public: - GenReg(Bit8u _index) { - index=_index; - notusable=false;dynreg=0; - } - DynReg * dynreg; - Bitu last_used; //Keeps track of last assigned regs - Bit8u index; - bool notusable; - void Load(DynReg * _dynreg,bool stale=false) { - if (!_dynreg) return; - if (GCC_UNLIKELY((Bitu)dynreg)) Clear(); - dynreg=_dynreg; - last_used=x86gen.last_used; - dynreg->flags&=~DYNFLG_CHANGED; - dynreg->genreg=this; - if ((!stale) && (dynreg->flags & (DYNFLG_LOAD|DYNFLG_ACTIVE))) { - cache_addw(0x058b+(index << (8+3))); //Mov reg,[data] - cache_addd((Bit32u)dynreg->data); - } - dynreg->flags|=DYNFLG_ACTIVE; - } - void Save(void) { - if (GCC_UNLIKELY(!((Bitu)dynreg))) IllegalOption("GenReg->Save"); - dynreg->flags&=~DYNFLG_CHANGED; - cache_addw(0x0589+(index << (8+3))); //Mov [data],reg - cache_addd((Bit32u)dynreg->data); - } - void Release(void) { - if (GCC_UNLIKELY(!((Bitu)dynreg))) return; - if (dynreg->flags&DYNFLG_CHANGED && dynreg->flags&DYNFLG_SAVE) { - Save(); - } - dynreg->flags&=~(DYNFLG_CHANGED|DYNFLG_ACTIVE); - dynreg->genreg=0;dynreg=0; - } - void Clear(void) { - if (!dynreg) return; - if (dynreg->flags&DYNFLG_CHANGED) { - Save(); - } - dynreg->genreg=0;dynreg=0; - } -}; - -static BlockReturn gen_runcode(Bit8u * code) { - BlockReturn retval; -#if defined (_MSC_VER) - __asm { -/* Prepare the flags */ - mov eax,[code] - push ebx - push ebp - push esi - push edi - mov ebx,[reg_flags] - and ebx,FMASK_TEST - push offset(return_address) - push ebx - jmp eax -/* Restore the flags */ -return_address: - /* return here with flags in ecx */ - and dword ptr [reg_flags],~FMASK_TEST - and ecx,FMASK_TEST - or [reg_flags],ecx - pop edi - pop esi - pop ebp - pop ebx - mov [retval],eax - } -#elif defined (MACOSX) - register Bit32u tempflags=reg_flags & FMASK_TEST; - __asm__ volatile ( - "pushl %%ebx \n" - "pushl %%ebp \n" - "pushl $(run_return_adress) \n" - "pushl %2 \n" - "jmp *%3 \n" - "run_return_adress: \n" - "popl %%ebp \n" - "popl %%ebx \n" - :"=a" (retval), "=c" (tempflags) - :"r" (tempflags),"r" (code) - :"%edx","%edi","%esi","cc","memory" - ); - reg_flags=(reg_flags & ~FMASK_TEST) | (tempflags & FMASK_TEST); -#else - register Bit32u tempflags=reg_flags & FMASK_TEST; - __asm__ volatile ( - "pushl %%ebp \n" - "pushl $(run_return_adress) \n" - "pushl %2 \n" - "jmp *%3 \n" - "run_return_adress: \n" - "popl %%ebp \n" - :"=a" (retval), "=c" (tempflags) - :"r" (tempflags),"r" (code) - :"%edx","%ebx","%edi","%esi","cc","memory" - ); - reg_flags=(reg_flags & ~FMASK_TEST) | (tempflags & FMASK_TEST); -#endif - return retval; -} - -static GenReg * FindDynReg(DynReg * dynreg,bool stale=false) { - x86gen.last_used++; - if (dynreg->genreg) { - dynreg->genreg->last_used=x86gen.last_used; - return dynreg->genreg; - } - /* Find best match for selected global reg */ - Bits i; - Bits first_used,first_index; - first_used=-1; - if (dynreg->flags & DYNFLG_HAS8) { - /* Has to be eax,ebx,ecx,edx */ - for (i=first_index=0;i<=X86_REG_EBX;i++) { - GenReg * genreg=x86gen.regs[i]; - if (genreg->notusable) continue; - if (!(genreg->dynreg)) { - genreg->Load(dynreg,stale); - return genreg; - } - if (genreg->last_used<(Bitu)first_used) { - first_used=genreg->last_used; - first_index=i; - } - } - } else { - for (i=first_index=X86_REGS-1;i>=0;i--) { - GenReg * genreg=x86gen.regs[i]; - if (genreg->notusable) continue; - if (!(genreg->dynreg)) { - genreg->Load(dynreg,stale); - return genreg; - } - if (genreg->last_used<(Bitu)first_used) { - first_used=genreg->last_used; - first_index=i; - } - } - } - /* No free register found use earliest assigned one */ - GenReg * newreg=x86gen.regs[first_index]; - newreg->Load(dynreg,stale); - return newreg; -} - -static GenReg * ForceDynReg(GenReg * genreg,DynReg * dynreg) { - genreg->last_used=++x86gen.last_used; - if (dynreg->genreg==genreg) return genreg; - if (genreg->dynreg) genreg->Clear(); - if (dynreg->genreg) dynreg->genreg->Clear(); - genreg->Load(dynreg); - return genreg; -} - -static void gen_preloadreg(DynReg * dynreg) { - FindDynReg(dynreg); -} - -static void gen_releasereg(DynReg * dynreg) { - GenReg * genreg=dynreg->genreg; - if (genreg) genreg->Release(); - else dynreg->flags&=~(DYNFLG_ACTIVE|DYNFLG_CHANGED); -} - -static void gen_setupreg(DynReg * dnew,DynReg * dsetup) { - dnew->flags=dsetup->flags; - if (dnew->genreg==dsetup->genreg) return; - /* Not the same genreg must be wrong */ - if (dnew->genreg) { - /* Check if the genreg i'm changing is actually linked to me */ - if (dnew->genreg->dynreg==dnew) dnew->genreg->dynreg=0; - } - dnew->genreg=dsetup->genreg; - if (dnew->genreg) dnew->genreg->dynreg=dnew; -} - -static void gen_synchreg(DynReg * dnew,DynReg * dsynch) { - /* First make sure the registers match */ - if (dnew->genreg!=dsynch->genreg) { - if (dnew->genreg) dnew->genreg->Clear(); - if (dsynch->genreg) { - dsynch->genreg->Load(dnew); - } - } - /* Always use the loadonce flag from either state */ - dnew->flags|=(dsynch->flags & dnew->flags&DYNFLG_ACTIVE); - if ((dnew->flags ^ dsynch->flags) & DYNFLG_CHANGED) { - /* Ensure the changed value gets saved */ - if (dnew->flags & DYNFLG_CHANGED) { - dnew->genreg->Save(); - } else dnew->flags|=DYNFLG_CHANGED; - } -} - -static void gen_needflags(void) { - if (!x86gen.flagsactive) { - x86gen.flagsactive=true; - cache_addb(0x9d); //POPFD - } -} - -static void gen_protectflags(void) { - if (x86gen.flagsactive) { - x86gen.flagsactive=false; - cache_addb(0x9c); //PUSHFD - } -} - -static void gen_discardflags(void) { - if (!x86gen.flagsactive) { - x86gen.flagsactive=true; - cache_addw(0xc483); //ADD ESP,4 - cache_addb(0x4); - } -} - -static void gen_needcarry(void) { - if (!x86gen.flagsactive) { - x86gen.flagsactive=true; - cache_addw(0x2cd1); //SHR DWORD [ESP],1 - cache_addb(0x24); - cache_addd(0x0424648d); //LEA ESP,[ESP+4] - } -} - -static void gen_setzeroflag(void) { - if (x86gen.flagsactive) IllegalOption("gen_setzeroflag"); - cache_addw(0x0c83); //OR DWORD [ESP],0x40 - cache_addw(0x4024); -} - -static void gen_clearzeroflag(void) { - if (x86gen.flagsactive) IllegalOption("gen_clearzeroflag"); - cache_addw(0x2483); //AND DWORD [ESP],~0x40 - cache_addw(0xbf24); -} - -static bool skip_flags=false; - -static void set_skipflags(bool state) { - if (!state) gen_discardflags(); - skip_flags=state; -} - -static void gen_reinit(void) { - x86gen.last_used=0; - x86gen.flagsactive=false; - for (Bitu i=0;idynreg=0; - } -} - - -static void gen_load_host(void * data,DynReg * dr1,Bitu size) { - GenReg * gr1=FindDynReg(dr1,true); - switch (size) { - case 1:cache_addw(0xb60f);break; //movzx byte - case 2:cache_addw(0xb70f);break; //movzx word - case 4:cache_addb(0x8b);break; //mov - default: - IllegalOption("gen_load_host"); - } - cache_addb(0x5+(gr1->index<<3)); - cache_addd((Bit32u)data); - dr1->flags|=DYNFLG_CHANGED; -} - -static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bit8u di1=0) { - GenReg * gr1=FindDynReg(dr1,(size==4)); - switch (size) { - case 1:cache_addb(0x8a);break; //mov byte - case 2:cache_addb(0x66); //mov word - case 4:cache_addb(0x8b);break; //mov - default: - IllegalOption("gen_load_host"); - } - cache_addb(0x5+((gr1->index+(di1?4:0))<<3)); - cache_addd((Bit32u)data); - dr1->flags|=DYNFLG_CHANGED; -} - - -static void gen_dop_byte(DualOps op,DynReg * dr1,Bit8u di1,DynReg * dr2,Bit8u di2) { - GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2); - Bit8u tmp; - switch (op) { - case DOP_ADD: tmp=0x02; break; - case DOP_ADC: tmp=0x12; break; - case DOP_SUB: tmp=0x2a; break; - case DOP_SBB: tmp=0x1a; break; - case DOP_CMP: tmp=0x3a; goto nochange; - case DOP_XOR: tmp=0x32; break; - case DOP_AND: tmp=0x22; if ((dr1==dr2) && (di1==di2)) goto nochange; break; - case DOP_OR: tmp=0x0a; if ((dr1==dr2) && (di1==di2)) goto nochange; break; - case DOP_TEST: tmp=0x84; goto nochange; - case DOP_MOV: if ((dr1==dr2) && (di1==di2)) return; tmp=0x8a; break; - case DOP_XCHG: tmp=0x86; dr2->flags|=DYNFLG_CHANGED; break; - default: - IllegalOption("gen_dop_byte"); - } - dr1->flags|=DYNFLG_CHANGED; -nochange: - cache_addw(tmp|(0xc0+((gr1->index+di1)<<3)+gr2->index+di2)<<8); -} - -static void gen_dop_byte_imm(DualOps op,DynReg * dr1,Bit8u di1,Bitu imm) { - GenReg * gr1=FindDynReg(dr1); - Bit16u tmp; - switch (op) { - case DOP_ADD: tmp=0xc080; break; - case DOP_ADC: tmp=0xd080; break; - case DOP_SUB: tmp=0xe880; break; - case DOP_SBB: tmp=0xd880; break; - case DOP_CMP: tmp=0xf880; goto nochange; //Doesn't change - case DOP_XOR: tmp=0xf080; break; - case DOP_AND: tmp=0xe080; break; - case DOP_OR: tmp=0xc880; break; - case DOP_TEST: tmp=0xc0f6; goto nochange; //Doesn't change - case DOP_MOV: cache_addb(0xb0+gr1->index+di1); - dr1->flags|=DYNFLG_CHANGED; - goto finish; - default: - IllegalOption("gen_dop_byte_imm"); - } - dr1->flags|=DYNFLG_CHANGED; -nochange: - cache_addw(tmp+((gr1->index+di1)<<8)); -finish: - cache_addb(imm); -} - -static void gen_dop_byte_imm_mem(DualOps op,DynReg * dr1,Bit8u di1,void* data) { - GenReg * gr1=FindDynReg(dr1); - Bit16u tmp; - switch (op) { - case DOP_ADD: tmp=0x0502; break; - case DOP_ADC: tmp=0x0512; break; - case DOP_SUB: tmp=0x052a; break; - case DOP_SBB: tmp=0x051a; break; - case DOP_CMP: tmp=0x053a; goto nochange; //Doesn't change - case DOP_XOR: tmp=0x0532; break; - case DOP_AND: tmp=0x0522; break; - case DOP_OR: tmp=0x050a; break; - case DOP_TEST: tmp=0x0584; goto nochange; //Doesn't change - case DOP_MOV: tmp=0x0585; break; - default: - IllegalOption("gen_dop_byte_imm_mem"); - } - dr1->flags|=DYNFLG_CHANGED; -nochange: - cache_addw(tmp+((gr1->index+di1)<<11)); - cache_addd((Bit32u)data); -} - -static void gen_sop_byte(SingleOps op,DynReg * dr1,Bit8u di1) { - GenReg * gr1=FindDynReg(dr1); - Bit16u tmp; - switch (op) { - case SOP_INC: tmp=0xc0FE; break; - case SOP_DEC: tmp=0xc8FE; break; - case SOP_NOT: tmp=0xd0f6; break; - case SOP_NEG: tmp=0xd8f6; break; - default: - IllegalOption("gen_sop_byte"); - } - cache_addw(tmp + ((gr1->index+di1)<<8)); - dr1->flags|=DYNFLG_CHANGED; -} - - -static void gen_extend_word(bool sign,DynReg * ddr,DynReg * dsr) { - GenReg * gsr=FindDynReg(dsr); - GenReg * gdr=FindDynReg(ddr,true); - if (sign) cache_addw(0xbf0f); - else cache_addw(0xb70f); - cache_addb(0xc0+(gdr->index<<3)+(gsr->index)); - ddr->flags|=DYNFLG_CHANGED; -} - -static void gen_extend_byte(bool sign,bool dword,DynReg * ddr,DynReg * dsr,Bit8u dsi) { - GenReg * gsr=FindDynReg(dsr); - GenReg * gdr=FindDynReg(ddr,dword); - if (!dword) cache_addb(0x66); - if (sign) cache_addw(0xbe0f); - else cache_addw(0xb60f); - cache_addb(0xc0+(gdr->index<<3)+(gsr->index+dsi)); - ddr->flags|=DYNFLG_CHANGED; -} - -static void gen_lea(DynReg * ddr,DynReg * dsr1,DynReg * dsr2,Bitu scale,Bits imm) { - GenReg * gdr=FindDynReg(ddr); - Bitu imm_size; - Bit8u rm_base=(gdr->index << 3); - if (dsr1) { - GenReg * gsr1=FindDynReg(dsr1); - if (!imm && (gsr1->index!=0x5)) { - imm_size=0; rm_base+=0x0; //no imm - } else if ((imm>=-128 && imm<=127)) { - imm_size=1;rm_base+=0x40; //Signed byte imm - } else { - imm_size=4;rm_base+=0x80; //Signed dword imm - } - if (dsr2) { - GenReg * gsr2=FindDynReg(dsr2); - cache_addb(0x8d); //LEA - cache_addb(rm_base+0x4); //The sib indicator - Bit8u sib=(gsr1->index)+(gsr2->index<<3)+(scale<<6); - cache_addb(sib); - } else { - if ((ddr==dsr1) && !imm_size) return; - cache_addb(0x8d); //LEA - cache_addb(rm_base+gsr1->index); - } - } else { - if (dsr2) { - GenReg * gsr2=FindDynReg(dsr2); - cache_addb(0x8d); //LEA - cache_addb(rm_base+0x4); //The sib indicator - Bit8u sib=(5+(gsr2->index<<3)+(scale<<6)); - cache_addb(sib); - imm_size=4; - } else { - cache_addb(0x8d); //LEA - cache_addb(rm_base+0x05); //dword imm - imm_size=4; - } - } - switch (imm_size) { - case 0: break; - case 1:cache_addb(imm);break; - case 4:cache_addd(imm);break; - } - ddr->flags|=DYNFLG_CHANGED; -} - -static void gen_lea_imm_mem(DynReg * ddr,DynReg * dsr,void* data) { - GenReg * gdr=FindDynReg(ddr); - Bit8u rm_base=(gdr->index << 3); - cache_addw(0x058b+(rm_base<<8)); - cache_addd((Bit32u)data); - GenReg * gsr=FindDynReg(dsr); - cache_addb(0x8d); //LEA - cache_addb(rm_base+0x44); - cache_addb(rm_base+gsr->index); - cache_addb(0x00); - ddr->flags|=DYNFLG_CHANGED; -} - -static void gen_dop_word(DualOps op,bool dword,DynReg * dr1,DynReg * dr2) { - GenReg * gr2=FindDynReg(dr2); - GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV); - Bit8u tmp; - switch (op) { - case DOP_ADD: tmp=0x03; break; - case DOP_ADC: tmp=0x13; break; - case DOP_SUB: tmp=0x2b; break; - case DOP_SBB: tmp=0x1b; break; - case DOP_CMP: tmp=0x3b; goto nochange; - case DOP_XOR: tmp=0x33; break; - case DOP_AND: tmp=0x23; if (dr1==dr2) goto nochange; break; - case DOP_OR: tmp=0x0b; if (dr1==dr2) goto nochange; break; - case DOP_TEST: tmp=0x85; goto nochange; - case DOP_MOV: if (dr1==dr2) return; tmp=0x8b; break; - case DOP_XCHG: - dr2->flags|=DYNFLG_CHANGED; - if (dword && !((dr1->flags&DYNFLG_HAS8) ^ (dr2->flags&DYNFLG_HAS8))) { - dr1->genreg=gr2;dr1->genreg->dynreg=dr1; - dr2->genreg=gr1;dr2->genreg->dynreg=dr2; - dr1->flags|=DYNFLG_CHANGED; - return; - } - tmp=0x87; - break; - default: - IllegalOption("gen_dop_word"); - } - dr1->flags|=DYNFLG_CHANGED; -nochange: - if (!dword) cache_addb(0x66); - cache_addw(tmp|(0xc0+(gr1->index<<3)+gr2->index)<<8); -} - -static void gen_dop_word_imm(DualOps op,bool dword,DynReg * dr1,Bits imm) { - GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV); - Bit16u tmp; - if (!dword) cache_addb(0x66); - switch (op) { - case DOP_ADD: tmp=0xc081; break; - case DOP_ADC: tmp=0xd081; break; - case DOP_SUB: tmp=0xe881; break; - case DOP_SBB: tmp=0xd881; break; - case DOP_CMP: tmp=0xf881; goto nochange; //Doesn't change - case DOP_XOR: tmp=0xf081; break; - case DOP_AND: tmp=0xe081; break; - case DOP_OR: tmp=0xc881; break; - case DOP_TEST: tmp=0xc0f7; goto nochange; //Doesn't change - case DOP_MOV: cache_addb(0xb8+(gr1->index)); dr1->flags|=DYNFLG_CHANGED; goto finish; - default: - IllegalOption("gen_dop_word_imm"); - } - dr1->flags|=DYNFLG_CHANGED; -nochange: - cache_addw(tmp+(gr1->index<<8)); -finish: - if (dword) cache_addd(imm); - else cache_addw(imm); -} - -static void gen_dop_word_imm_mem(DualOps op,bool dword,DynReg * dr1,void* data) { - GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV); - Bit16u tmp; - switch (op) { - case DOP_ADD: tmp=0x0503; break; - case DOP_ADC: tmp=0x0513; break; - case DOP_SUB: tmp=0x052b; break; - case DOP_SBB: tmp=0x051b; break; - case DOP_CMP: tmp=0x053b; goto nochange; //Doesn't change - case DOP_XOR: tmp=0x0533; break; - case DOP_AND: tmp=0x0523; break; - case DOP_OR: tmp=0x050b; break; - case DOP_TEST: tmp=0x0585; goto nochange; //Doesn't change - case DOP_MOV: - gen_mov_host(data,dr1,dword?4:2); - dr1->flags|=DYNFLG_CHANGED; - return; - default: - IllegalOption("gen_dop_word_imm_mem"); - } - dr1->flags|=DYNFLG_CHANGED; -nochange: - if (!dword) cache_addb(0x66); - cache_addw(tmp+(gr1->index<<11)); - cache_addd((Bit32u)data); -} - -static void gen_dop_word_var(DualOps op,bool dword,DynReg * dr1,void* drd) { - GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV); - Bit8u tmp; - switch (op) { - case DOP_ADD: tmp=0x03; break; - case DOP_ADC: tmp=0x13; break; - case DOP_SUB: tmp=0x2b; break; - case DOP_SBB: tmp=0x1b; break; - case DOP_CMP: tmp=0x3b; break; - case DOP_XOR: tmp=0x33; break; - case DOP_AND: tmp=0x23; break; - case DOP_OR: tmp=0x0b; break; - case DOP_TEST: tmp=0x85; break; - case DOP_MOV: tmp=0x8b; break; - case DOP_XCHG: tmp=0x87; break; - default: - IllegalOption("gen_dop_word_var"); - } - if (!dword) cache_addb(0x66); - cache_addw(tmp|(0x05+((gr1->index)<<3))<<8); - cache_addd((Bit32u)drd); -} - -static void gen_imul_word(bool dword,DynReg * dr1,DynReg * dr2) { - GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2); - dr1->flags|=DYNFLG_CHANGED; - if (!dword) { - cache_addd(0xaf0f66|(0xc0+(gr1->index<<3)+gr2->index)<<24); - } else { - cache_addw(0xaf0f); - cache_addb(0xc0+(gr1->index<<3)+gr2->index); - } -} - -static void gen_imul_word_imm(bool dword,DynReg * dr1,DynReg * dr2,Bits imm) { - GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2); - if (!dword) cache_addb(0x66); - if ((imm>=-128 && imm<=127)) { - cache_addb(0x6b); - cache_addb(0xc0+(gr1->index<<3)+gr2->index); - cache_addb(imm); - } else { - cache_addb(0x69); - cache_addb(0xc0+(gr1->index<<3)+gr2->index); - if (dword) cache_addd(imm); - else cache_addw(imm); - } - dr1->flags|=DYNFLG_CHANGED; -} - - -static void gen_sop_word(SingleOps op,bool dword,DynReg * dr1) { - GenReg * gr1=FindDynReg(dr1); - if (!dword) cache_addb(0x66); - switch (op) { - case SOP_INC:cache_addb(0x40+gr1->index);break; - case SOP_DEC:cache_addb(0x48+gr1->index);break; - case SOP_NOT:cache_addw(0xd0f7+(gr1->index<<8));break; - case SOP_NEG:cache_addw(0xd8f7+(gr1->index<<8));break; - default: - IllegalOption("gen_sop_word"); - } - dr1->flags|=DYNFLG_CHANGED; -} - -static void gen_shift_byte_cl(Bitu op,DynReg * dr1,Bit8u di1,DynReg * drecx) { - ForceDynReg(x86gen.regs[X86_REG_ECX],drecx); - GenReg * gr1=FindDynReg(dr1); - cache_addw(0xc0d2+(((Bit16u)op) << 11)+ ((gr1->index+di1)<<8)); - dr1->flags|=DYNFLG_CHANGED; -} - -static void gen_shift_byte_imm(Bitu op,DynReg * dr1,Bit8u di1,Bit8u imm) { - GenReg * gr1=FindDynReg(dr1); - cache_addw(0xc0c0+(((Bit16u)op) << 11) + ((gr1->index+di1)<<8)); - cache_addb(imm); - dr1->flags|=DYNFLG_CHANGED; -} - -static void gen_shift_word_cl(Bitu op,bool dword,DynReg * dr1,DynReg * drecx) { - ForceDynReg(x86gen.regs[X86_REG_ECX],drecx); - GenReg * gr1=FindDynReg(dr1); - if (!dword) cache_addb(0x66); - cache_addw(0xc0d3+(((Bit16u)op) << 11) + ((gr1->index)<<8)); - dr1->flags|=DYNFLG_CHANGED; -} - -static void gen_shift_word_imm(Bitu op,bool dword,DynReg * dr1,Bit8u imm) { - GenReg * gr1=FindDynReg(dr1); - dr1->flags|=DYNFLG_CHANGED; - if (!dword) { - cache_addd(0x66|((0xc0c1+((Bit16u)op << 11) + (gr1->index<<8))|imm<<16)<<8); - } else { - cache_addw(0xc0c1+((Bit16u)op << 11) + (gr1->index<<8)); - cache_addb(imm); - } -} - -static void gen_cbw(bool dword,DynReg * dyn_ax) { - ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); - if (!dword) cache_addb(0x66); - cache_addb(0x98); - dyn_ax->flags|=DYNFLG_CHANGED; -} - -static void gen_cwd(bool dword,DynReg * dyn_ax,DynReg * dyn_dx) { - ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); - ForceDynReg(x86gen.regs[X86_REG_EDX],dyn_dx); - dyn_ax->flags|=DYNFLG_CHANGED; - dyn_dx->flags|=DYNFLG_CHANGED; - if (!dword) cache_addw(0x9966); - else cache_addb(0x99); -} - -static void gen_mul_byte(bool imul,DynReg * dyn_ax,DynReg * dr1,Bit8u di1) { - ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); - GenReg * gr1=FindDynReg(dr1); - if (imul) cache_addw(0xe8f6+((gr1->index+di1)<<8)); - else cache_addw(0xe0f6+((gr1->index+di1)<<8)); - dyn_ax->flags|=DYNFLG_CHANGED; -} - -static void gen_mul_word(bool imul,DynReg * dyn_ax,DynReg * dyn_dx,bool dword,DynReg * dr1) { - ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); - ForceDynReg(x86gen.regs[X86_REG_EDX],dyn_dx); - GenReg * gr1=FindDynReg(dr1); - if (!dword) cache_addb(0x66); - if (imul) cache_addw(0xe8f7+(gr1->index<<8)); - else cache_addw(0xe0f7+(gr1->index<<8)); - dyn_ax->flags|=DYNFLG_CHANGED; - dyn_dx->flags|=DYNFLG_CHANGED; -} - -static void gen_dshift_imm(bool dword,bool left,DynReg * dr1,DynReg * dr2,Bitu imm) { - GenReg * gr1=FindDynReg(dr1); - GenReg * gr2=FindDynReg(dr2); - if (!dword) cache_addb(0x66); - if (left) cache_addw(0xa40f); //SHLD IMM - else cache_addw(0xac0f); //SHRD IMM - cache_addb(0xc0+gr1->index+(gr2->index<<3)); - cache_addb(imm); - dr1->flags|=DYNFLG_CHANGED; -} - -static void gen_dshift_cl(bool dword,bool left,DynReg * dr1,DynReg * dr2,DynReg * drecx) { - ForceDynReg(x86gen.regs[X86_REG_ECX],drecx); - GenReg * gr1=FindDynReg(dr1); - GenReg * gr2=FindDynReg(dr2); - if (!dword) cache_addb(0x66); - if (left) cache_addw(0xa50f); //SHLD CL - else cache_addw(0xad0f); //SHRD CL - cache_addb(0xc0+gr1->index+(gr2->index<<3)); - dr1->flags|=DYNFLG_CHANGED; -} - -static void gen_call_function(void * func,char const* ops,...) { - Bits paramcount=0; - bool release_flags=false; - struct ParamInfo { - const char * line; - Bitu value; - } pinfo[32]; - ParamInfo * retparam=0; - /* Clear the EAX Genreg for usage */ - x86gen.regs[X86_REG_EAX]->Clear(); - x86gen.regs[X86_REG_EAX]->notusable=true; - /* Save the flags */ - if (GCC_UNLIKELY(!skip_flags)) gen_protectflags(); - /* Scan for the amount of params */ - if (ops) { - va_list params; - va_start(params,ops); -#if defined (MACOSX) - Bitu stack_used=0; - bool free_flags=false; -#endif - Bits pindex=0; - while (*ops) { - if (*ops=='%') { - pinfo[pindex].line=ops+1; - pinfo[pindex].value=va_arg(params,Bitu); -#if defined (MACOSX) - const char * scan=pinfo[pindex].line; - if ((*scan=='I') || (*scan=='D')) stack_used+=4; - else if (*scan=='F') free_flags=true; -#endif - pindex++; - } - ops++; - } - -#if defined (MACOSX) - /* align stack */ - stack_used+=4; // saving esp on stack as well - - cache_addw(0xc48b); // mov eax,esp - cache_addb(0x2d); // sub eax,stack_used - cache_addd(stack_used); - cache_addw(0xe083); // and eax,0xfffffff0 - cache_addb(0xf0); - cache_addb(0x05); // sub eax,stack_used - cache_addd(stack_used); - cache_addb(0x94); // xchg eax,esp - if (free_flags) { - cache_addw(0xc083); // add eax,4 - cache_addb(0x04); - } - cache_addb(0x50); // push eax (==old esp) -#endif - - paramcount=0; - while (pindex) { - pindex--; - const char * scan=pinfo[pindex].line; - switch (*scan++) { - case 'I': /* immediate value */ - paramcount++; - cache_addb(0x68); //Push immediate - cache_addd(pinfo[pindex].value); //Push value - break; - case 'D': /* Dynamic register */ - { - bool release=false; - paramcount++; - DynReg * dynreg=(DynReg *)pinfo[pindex].value; - GenReg * genreg=FindDynReg(dynreg); - scanagain: - switch (*scan++) { - case 'd': - cache_addb(0x50+genreg->index); //Push reg - break; - case 'w': - cache_addw(0xb70f); //MOVZX EAX,reg - cache_addb(0xc0+genreg->index); - cache_addb(0x50); //Push EAX - break; - case 'l': - cache_addw(0xb60f); //MOVZX EAX,reg[0] - cache_addb(0xc0+genreg->index); - cache_addb(0x50); //Push EAX - break; - case 'h': - cache_addw(0xb60f); //MOVZX EAX,reg[1] - cache_addb(0xc4+genreg->index); - cache_addb(0x50); //Push EAX - break; - case 'r': /* release the reg afterwards */ - release=true; - goto scanagain; - default: - IllegalOption("gen_call_function param:DREG"); - } - if (release) gen_releasereg(dynreg); - } - break; - case 'R': /* Dynamic register to get the return value */ - retparam =&pinfo[pindex]; - pinfo[pindex].line=scan; - break; - case 'F': /* Release flags from stack */ - release_flags=true; - break; - default: - IllegalOption("gen_call_function unknown param"); - } - } -#if defined (MACOSX) - if (free_flags) release_flags=false; - } else { - /* align stack */ - Bit32u stack_used=8; // saving esp and return address on the stack - - cache_addw(0xc48b); // mov eax,esp - cache_addb(0x2d); // sub eax,stack_used - cache_addd(stack_used); - cache_addw(0xe083); // and eax,0xfffffff0 - cache_addb(0xf0); - cache_addb(0x05); // sub eax,stack_used - cache_addd(stack_used); - cache_addb(0x94); // xchg eax,esp - cache_addb(0x50); // push esp (==old esp) -#endif - } - - /* Clear some unprotected registers */ - x86gen.regs[X86_REG_ECX]->Clear(); - x86gen.regs[X86_REG_EDX]->Clear(); - /* Do the actual call to the procedure */ - cache_addb(0xe8); - cache_addd((Bit32u)func - (Bit32u)cache.pos-4); - /* Restore the params of the stack */ - if (paramcount) { - cache_addw(0xc483); //add ESP,imm byte - cache_addb(paramcount*4+(release_flags?4:0)); - } else if (release_flags) { - cache_addw(0xc483); //add ESP,imm byte - cache_addb(4); - } - /* Save the return value in correct register */ - if (retparam) { - DynReg * dynreg=(DynReg *)retparam->value; - GenReg * genreg=FindDynReg(dynreg); - if (genreg->index) // test for (e)ax/al - switch (*retparam->line) { - case 'd': - cache_addw(0xc08b+(genreg->index <<(8+3))); //mov reg,eax - break; - case 'w': - cache_addb(0x66); - cache_addw(0xc08b+(genreg->index <<(8+3))); //mov reg,eax - break; - case 'l': - cache_addw(0xc08a+(genreg->index <<(8+3))); //mov reg,eax - break; - case 'h': - cache_addw(0xc08a+((genreg->index+4) <<(8+3))); //mov reg,eax - break; - } - dynreg->flags|=DYNFLG_CHANGED; - } - /* Restore EAX registers to be used again */ - x86gen.regs[X86_REG_EAX]->notusable=false; - -#if defined (MACOSX) - /* restore stack */ - cache_addb(0x5c); // pop esp -#endif -} - -static void gen_call_write(DynReg * dr,Bit32u val,Bitu write_size) { - /* Clear the EAX Genreg for usage */ - x86gen.regs[X86_REG_EAX]->Clear(); - x86gen.regs[X86_REG_EAX]->notusable=true; - gen_protectflags(); - -#if defined (MACOSX) - /* align stack */ - Bitu stack_used=12; - - cache_addw(0xc48b); // mov eax,esp - cache_addb(0x2d); // sub eax,stack_used - cache_addd(stack_used); - cache_addw(0xe083); // and eax,0xfffffff0 - cache_addb(0xf0); - cache_addb(0x05); // sub eax,stack_used - cache_addd(stack_used); - cache_addb(0x94); // xchg eax,esp - cache_addb(0x50); // push eax (==old esp) -#endif - - cache_addb(0x68); //PUSH val - cache_addd(val); - GenReg * genreg=FindDynReg(dr); - cache_addb(0x50+genreg->index); //PUSH reg - - /* Clear some unprotected registers */ - x86gen.regs[X86_REG_ECX]->Clear(); - x86gen.regs[X86_REG_EDX]->Clear(); - /* Do the actual call to the procedure */ - cache_addb(0xe8); - switch (write_size) { - case 1: cache_addd((Bit32u)mem_writeb_checked - (Bit32u)cache.pos-4); break; - case 2: cache_addd((Bit32u)mem_writew_checked - (Bit32u)cache.pos-4); break; - case 4: cache_addd((Bit32u)mem_writed_checked - (Bit32u)cache.pos-4); break; - default: IllegalOption("gen_call_write"); - } - - cache_addw(0xc483); //ADD ESP,8 - cache_addb(2*4); - x86gen.regs[X86_REG_EAX]->notusable=false; - gen_releasereg(dr); - -#if defined (MACOSX) - /* restore stack */ - cache_addb(0x5c); // pop esp -#endif -} - -static Bit8u * gen_create_branch(BranchTypes type) { - /* First free all registers */ - cache_addw(0x70+type); - return (cache.pos-1); -} - -static void gen_fill_branch(Bit8u * data,Bit8u * from=cache.pos) { -#if C_DEBUG - Bits len=from-data; - if (len<0) len=-len; - if (len>126) LOG_MSG("Big jump %d",len); -#endif - *data=(from-data-1); -} - -static Bit8u * gen_create_branch_long(BranchTypes type) { - cache_addw(0x800f+(type<<8)); - cache_addd(0); - return (cache.pos-4); -} - -static void gen_fill_branch_long(Bit8u * data,Bit8u * from=cache.pos) { - *(Bit32u*)data=(from-data-4); -} - -static Bit8u * gen_create_jump(Bit8u * to=0) { - /* First free all registers */ - cache_addb(0xe9); - cache_addd(to-(cache.pos+4)); - return (cache.pos-4); -} - -static void gen_fill_jump(Bit8u * data,Bit8u * to=cache.pos) { - *(Bit32u*)data=(to-data-4); -} - - -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - cache_addb(0xa1); - cache_addd((Bit32u)ptr); - cache_addb(0xff); //JMP EA - if (!imm) { //NO EBP - cache_addb(0x20); - } else if ((imm>=-128 && imm<=127)) { - cache_addb(0x60); - cache_addb(imm); - } else { - cache_addb(0xa0); - cache_addd(imm); - } -} - -static void gen_save_flags(DynReg * dynreg) { - if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_save_flags"); - GenReg * genreg=FindDynReg(dynreg); - cache_addb(0x8b); //MOV REG,[esp] - cache_addw(0x2404+(genreg->index << 3)); - dynreg->flags|=DYNFLG_CHANGED; -} - -static void gen_load_flags(DynReg * dynreg) { - if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_load_flags"); - cache_addw(0xc483); //ADD ESP,4 - cache_addb(0x4); - GenReg * genreg=FindDynReg(dynreg); - cache_addb(0x50+genreg->index); //PUSH 32 -} - -static void gen_save_host_direct(void * data,Bits imm) { - cache_addw(0x05c7); //MOV [],dword - cache_addd((Bit32u)data); - cache_addd(imm); -} - -static void gen_return(BlockReturn retcode) { - gen_protectflags(); - cache_addb(0x59); //POP ECX, the flags - if (retcode==0) cache_addw(0xc033); //MOV EAX, 0 - else { - cache_addb(0xb8); //MOV EAX, retcode - cache_addd(retcode); - } - cache_addb(0xc3); //RET -} - -static void gen_return_fast(BlockReturn retcode,bool ret_exception=false) { - if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_return_fast"); - cache_addw(0x0d8b); //MOV ECX, the flags - cache_addd((Bit32u)&cpu_regs.flags); - if (!ret_exception) { - cache_addw(0xc483); //ADD ESP,4 - cache_addb(0x4); - if (retcode==0) cache_addw(0xc033); //MOV EAX, 0 - else { - cache_addb(0xb8); //MOV EAX, retcode - cache_addd(retcode); - } - } - cache_addb(0xc3); //RET -} - -static void gen_init(void) { - x86gen.regs[X86_REG_EAX]=new GenReg(0); - x86gen.regs[X86_REG_ECX]=new GenReg(1); - x86gen.regs[X86_REG_EDX]=new GenReg(2); - x86gen.regs[X86_REG_EBX]=new GenReg(3); - x86gen.regs[X86_REG_EBP]=new GenReg(5); - x86gen.regs[X86_REG_ESI]=new GenReg(6); - x86gen.regs[X86_REG_EDI]=new GenReg(7); -} - - diff --git a/src/cpu/core_dyn_x86/string.h b/src/cpu/core_dyn_x86/string.h deleted file mode 100644 index 7bb7ebb..0000000 --- a/src/cpu/core_dyn_x86/string.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -enum STRING_OP { - STR_OUTSB=0,STR_OUTSW,STR_OUTSD, - STR_INSB=4,STR_INSW,STR_INSD, - STR_MOVSB=8,STR_MOVSW,STR_MOVSD, - STR_LODSB=12,STR_LODSW,STR_LODSD, - STR_STOSB=16,STR_STOSW,STR_STOSD, - STR_SCASB=20,STR_SCASW,STR_SCASD, - STR_CMPSB=24,STR_CMPSW,STR_CMPSD -}; - -static void dyn_string(STRING_OP op) { - DynReg * si_base=decode.segprefix ? decode.segprefix : DREG(DS); - DynReg * di_base=DREG(ES); - DynReg * tmp_reg;bool usesi;bool usedi; - gen_protectflags(); - if (decode.rep) { - gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles); - gen_releasereg(DREG(CYCLES)); - decode.cycles=0; - } - /* Check what each string operation will be using */ - switch (op) { - case STR_MOVSB: case STR_MOVSW: case STR_MOVSD: - case STR_CMPSB: case STR_CMPSW: case STR_CMPSD: - tmp_reg=DREG(TMPB);usesi=true;usedi=true;break; - case STR_LODSB: case STR_LODSW: case STR_LODSD: - tmp_reg=DREG(EAX);usesi=true;usedi=false;break; - case STR_OUTSB: case STR_OUTSW: case STR_OUTSD: - tmp_reg=DREG(TMPB);usesi=true;usedi=false;break; - case STR_SCASB: case STR_SCASW: case STR_SCASD: - case STR_STOSB: case STR_STOSW: case STR_STOSD: - tmp_reg=DREG(EAX);usesi=false;usedi=true;break; - case STR_INSB: case STR_INSW: case STR_INSD: - tmp_reg=DREG(TMPB);usesi=false;usedi=true;break; - default: - IllegalOption("dyn_string op"); - } - gen_load_host(&cpu.direction,DREG(TMPW),4); - switch (op & 3) { - case 0:break; - case 1:gen_shift_word_imm(SHIFT_SHL,true,DREG(TMPW),1);break; - case 2:gen_shift_word_imm(SHIFT_SHL,true,DREG(TMPW),2);break; - default: - IllegalOption("dyn_string shift"); - - } - if (usesi) { - gen_preloadreg(DREG(ESI)); - DynRegs[G_ESI].flags|=DYNFLG_CHANGED; - gen_preloadreg(si_base); - } - if (usedi) { - gen_preloadreg(DREG(EDI)); - DynRegs[G_EDI].flags|=DYNFLG_CHANGED; - gen_preloadreg(di_base); - } - if (decode.rep) { - gen_preloadreg(DREG(ECX)); - DynRegs[G_ECX].flags|=DYNFLG_CHANGED; - } - DynState rep_state; - dyn_savestate(&rep_state); - Bit8u * rep_start=cache.pos; - Bit8u * rep_ecx_jmp; - /* Check if ECX!=zero */ - if (decode.rep) { - gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX)); - rep_ecx_jmp=gen_create_branch_long(BR_Z); - } - if (usesi) { - if (!decode.big_addr) { - gen_extend_word(false,DREG(EA),DREG(ESI)); - gen_lea(DREG(EA),si_base,DREG(EA),0,0); - } else { - gen_lea(DREG(EA),si_base,DREG(ESI),0,0); - } - switch (op&3) { - case 0:dyn_read_byte(DREG(EA),tmp_reg,false);break; - case 1:dyn_read_word(DREG(EA),tmp_reg,false);break; - case 2:dyn_read_word(DREG(EA),tmp_reg,true);break; - } - switch (op) { - case STR_OUTSB: - gen_call_function((void*)&IO_WriteB,"%Id%Dl",DREG(EDX),tmp_reg);break; - case STR_OUTSW: - gen_call_function((void*)&IO_WriteW,"%Id%Dw",DREG(EDX),tmp_reg);break; - case STR_OUTSD: - gen_call_function((void*)&IO_WriteD,"%Id%Dd",DREG(EDX),tmp_reg);break; - } - } - if (usedi) { - if (!decode.big_addr) { - gen_extend_word(false,DREG(EA),DREG(EDI)); - gen_lea(DREG(EA),di_base,DREG(EA),0,0); - } else { - gen_lea(DREG(EA),di_base,DREG(EDI),0,0); - } - /* Maybe something special to be done to fill the value */ - switch (op) { - case STR_INSB: - gen_call_function((void*)&IO_ReadB,"%Dw%Rl",DREG(EDX),tmp_reg); - case STR_MOVSB: - case STR_STOSB: - dyn_write_byte(DREG(EA),tmp_reg,false); - break; - case STR_INSW: - gen_call_function((void*)&IO_ReadW,"%Dw%Rw",DREG(EDX),tmp_reg); - case STR_MOVSW: - case STR_STOSW: - dyn_write_word(DREG(EA),tmp_reg,false); - break; - case STR_INSD: - gen_call_function((void*)&IO_ReadD,"%Dw%Rd",DREG(EDX),tmp_reg); - case STR_MOVSD: - case STR_STOSD: - dyn_write_word(DREG(EA),tmp_reg,true); - break; - default: - IllegalOption("dyn_string op"); - } - } - gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); - - /* update registers */ - if (usesi) gen_dop_word(DOP_ADD,decode.big_addr,DREG(ESI),DREG(TMPW)); - if (usedi) gen_dop_word(DOP_ADD,decode.big_addr,DREG(EDI),DREG(TMPW)); - - if (decode.rep) { - gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); - gen_sop_word(SOP_DEC,true,DREG(CYCLES)); - gen_releasereg(DREG(CYCLES)); - dyn_savestate(&save_info[used_save_info].state); - save_info[used_save_info].branch_pos=gen_create_branch_long(BR_LE); - save_info[used_save_info].eip_change=decode.op_start-decode.code_start; - save_info[used_save_info].type=normal; - used_save_info++; - - /* Jump back to start of ECX check */ - dyn_synchstate(&rep_state); - gen_create_jump(rep_start); - - dyn_loadstate(&rep_state); - gen_fill_branch_long(rep_ecx_jmp); - } - gen_releasereg(DREG(TMPW)); -} diff --git a/src/cpu/core_dynrec.cpp b/src/cpu/core_dynrec.cpp deleted file mode 100644 index a0be1e9..0000000 --- a/src/cpu/core_dynrec.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: core_dynrec.cpp,v 1.11 2008/09/19 16:48:02 c2woody Exp $ */ - -#include "dosbox.h" - -#if (C_DYNREC) - -#include -#include -#include -#include -#include -#include - -#if defined (WIN32) -#include -#include -#endif - -#if (C_HAVE_MPROTECT) -#include - -#include -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif -#endif /* C_HAVE_MPROTECT */ - -#include "callback.h" -#include "regs.h" -#include "mem.h" -#include "cpu.h" -#include "debug.h" -#include "paging.h" -#include "inout.h" -#include "lazyflags.h" - -#define CACHE_MAXSIZE (4096*2) -#define CACHE_TOTAL (1024*1024*8) -#define CACHE_PAGES (512) -#define CACHE_BLOCKS (128*1024) -#define CACHE_ALIGN (16) -#define DYN_HASH_SHIFT (4) -#define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT) -#define DYN_LINKS (16) - -#if 0 -#define DYN_LOG LOG_MSG -#else -#define DYN_LOG -#endif - -#if C_FPU -#define CPU_FPU 1 //Enable FPU escape instructions -#endif - - -// the emulated x86 registers -#define DRC_REG_EAX 0 -#define DRC_REG_ECX 1 -#define DRC_REG_EDX 2 -#define DRC_REG_EBX 3 -#define DRC_REG_ESP 4 -#define DRC_REG_EBP 5 -#define DRC_REG_ESI 6 -#define DRC_REG_EDI 7 - -// the emulated x86 segment registers -#define DRC_SEG_ES 0 -#define DRC_SEG_CS 1 -#define DRC_SEG_SS 2 -#define DRC_SEG_DS 3 -#define DRC_SEG_FS 4 -#define DRC_SEG_GS 5 - - -// access to a general register -#define DRCD_REG_VAL(reg) (&cpu_regs.regs[reg].dword) -// access to a segment register -#define DRCD_SEG_VAL(seg) (&Segs.val[seg]) -// access to the physical value of a segment register/selector -#define DRCD_SEG_PHYS(seg) (&Segs.phys[seg]) - -// access to an 8bit general register -#define DRCD_REG_BYTE(reg,idx) (&cpu_regs.regs[reg].byte[idx]) -// access to 16/32bit general registers -#define DRCD_REG_WORD(reg,dwrd) ((dwrd)?((void*)(&cpu_regs.regs[reg].dword)):((void*)(&cpu_regs.regs[reg].word))) - - -enum BlockReturn { - BR_Normal=0, - BR_Cycles, - BR_Link1,BR_Link2, - BR_Opcode, -#if (C_DEBUG) - BR_OpcodeFull, -#endif - BR_Iret, - BR_CallBack, - BR_SMCBlock -}; - -// identificator to signal self-modification of the currently executed block -#define SMC_CURRENT_BLOCK 0xffff - - -static void IllegalOptionDynrec(const char* msg) { - E_Exit("DynrecCore: illegal option in %s",msg); -} - -static struct { - BlockReturn (*runcode)(Bit8u*); // points to code that can start a block - Bitu callback; // the occurred callback - Bitu readdata; // spare space used when reading from memory - Bit32u protected_regs[8]; // space to save/restore register values -} core_dynrec; - - -#include "core_dynrec/cache.h" - -#define X86 0x01 -#define X86_64 0x02 -#define MIPSEL 0x03 -#define ARMV4LE 0x04 - -#if C_TARGETCPU == X86_64 -#include "core_dynrec/risc_x64.h" -#elif C_TARGETCPU == X86 -#include "core_dynrec/risc_x86.h" -#elif C_TARGETCPU == MIPSEL -#include "core_dynrec/risc_mipsel32.h" -#elif C_TARGETCPU == ARMV4LE -#include "core_dynrec/risc_armv4le.h" -#endif - -#include "core_dynrec/decoder.h" - -CacheBlockDynRec * LinkBlocks(BlockReturn ret) { - CacheBlockDynRec * block=NULL; - // the last instruction was a control flow modifying instruction - Bitu temp_ip=SegPhys(cs)+reg_eip; - CodePageHandlerDynRec * temp_handler=(CodePageHandlerDynRec *)get_tlb_readhandler(temp_ip); - if (temp_handler->flags & PFLAG_HASCODE) { - // see if the target is an already translated block - block=temp_handler->FindCacheBlock(temp_ip & 4095); - if (!block) return NULL; - - // found it, link the current block to - cache.block.running->LinkTo(ret==BR_Link2,block); - return block; - } - return NULL; -} - -/* - The core tries to find the block that should be executed next. - If such a block is found, it is run, otherwise the instruction - stream starting at ip_point is translated (see decoder.h) and - makes up a new code block that will be run. - When control is returned to CPU_Core_Dynrec_Run (which might - be right after the block is run, or somewhen long after that - due to the direct cacheblock linking) the returncode decides - the next action. This might be continuing the translation and - execution process, or returning from the core etc. -*/ - -Bits CPU_Core_Dynrec_Run(void) { - for (;;) { - // Determine the linear address of CS:EIP - PhysPt ip_point=SegPhys(cs)+reg_eip; - #if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; - #endif - - CodePageHandlerDynRec * chandler=0; - // see if the current page is present and contains code - if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) { - // page not present, throw the exception - CPU_Exception(cpu.exception.which,cpu.exception.error); - continue; - } - - // page doesn't contain code or is special - if (GCC_UNLIKELY(!chandler)) return CPU_Core_Normal_Run(); - - // find correct Dynamic Block to run - CacheBlockDynRec * block=chandler->FindCacheBlock(ip_point&4095); - if (!block) { - // no block found, thus translate the instruction stream - // unless the instruction is known to be modified - if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) { - // translate up to 32 instructions - block=CreateCacheBlock(chandler,ip_point,32); - } else { - // let the normal core handle this instruction to avoid zero-sized blocks - Bitu old_cycles=CPU_Cycles; - CPU_Cycles=1; - Bits nc_retcode=CPU_Core_Normal_Run(); - if (!nc_retcode) { - CPU_Cycles=old_cycles-1; - continue; - } - CPU_CycleLeft+=old_cycles; - return nc_retcode; - } - } - -run_block: - cache.block.running=0; - // now we're ready to run the dynamic code block -// BlockReturn ret=((BlockReturn (*)(void))(block->cache.start))(); - BlockReturn ret=core_dynrec.runcode(block->cache.start); - - switch (ret) { - case BR_Iret: -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; -#endif - if (!GETFLAG(TF)) break; - // trapflag is set, switch to the trap-aware decoder - cpudecoder=CPU_Core_Dynrec_Trap_Run; - return CBRET_NONE; - - case BR_Normal: - // the block was exited due to a non-predictable control flow - // modifying instruction (like ret) or some nontrivial cpu state - // changing instruction (for example switch to/from pmode), - // or the maximal number of instructions to translate was reached -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; -#endif - break; - - case BR_Cycles: - // cycles went negative, return from the core to handle - // external events, schedule the pic... -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; -#endif - return CBRET_NONE; - - case BR_CallBack: - // the callback code is executed in dosbox.conf, return the callback number - FillFlags(); - return core_dynrec.callback; - - case BR_SMCBlock: -// LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip); - cpu.exception.which=0; - // fallthrough, let the normal core handle the block-modifying instruction - case BR_Opcode: - // some instruction has been encountered that could not be translated - // (thus it is not part of the code block), the normal core will - // handle this instruction - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=1; - return CPU_Core_Normal_Run(); - -#if (C_DEBUG) - case BR_OpcodeFull: - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=1; - return CPU_Core_Full_Run(); -#endif - - case BR_Link1: - case BR_Link2: - block=LinkBlocks(ret); - if (block) goto run_block; - break; - - default: - E_Exit("Invalid return code %d", ret); - } - } - return CBRET_NONE; -} - -Bits CPU_Core_Dynrec_Trap_Run(void) { - Bits oldCycles = CPU_Cycles; - CPU_Cycles = 1; - cpu.trap_skip = false; - - // let the normal core execute the next (only one!) instruction - Bits ret=CPU_Core_Normal_Run(); - - // trap to int1 unless the last instruction deferred this - // (allows hardware interrupts to be served without interaction) - if (!cpu.trap_skip) CPU_HW_Interrupt(1); - - CPU_Cycles = oldCycles-1; - // continue (either the trapflag was clear anyways, or the int1 cleared it) - cpudecoder = &CPU_Core_Dynrec_Run; - - return ret; -} - -void CPU_Core_Dynrec_Init(void) { -} - -void CPU_Core_Dynrec_Cache_Init(bool enable_cache) { - // Initialize code cache and dynamic blocks - cache_init(enable_cache); -} - -void CPU_Core_Dynrec_Cache_Close(void) { - cache_close(); -} - -#endif diff --git a/src/cpu/core_dynrec/Makefile.am b/src/cpu/core_dynrec/Makefile.am deleted file mode 100644 index 923a3d0..0000000 --- a/src/cpu/core_dynrec/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -noinst_HEADERS = cache.h decoder.h decoder_basic.h decoder_opcodes.h \ - dyn_fpu.h operators.h risc_x64.h risc_x86.h risc_mipsel32.h \ - risc_armv4le.h risc_armv4le-common.h \ - risc_armv4le-s3.h risc_armv4le-o3.h risc_armv4le-thumb.h \ - risc_armv4le-thumb-iw.h risc_armv4le-thumb-niw.h diff --git a/src/cpu/core_dynrec/cache.h b/src/cpu/core_dynrec/cache.h deleted file mode 100644 index 6bae16c..0000000 --- a/src/cpu/core_dynrec/cache.h +++ /dev/null @@ -1,665 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -class CodePageHandlerDynRec; // forward - -// basic cache block representation -class CacheBlockDynRec { -public: - void Clear(void); - // link this cache block to another block, index specifies the code - // path (always zero for unconditional links, 0/1 for conditional ones - void LinkTo(Bitu index,CacheBlockDynRec * toblock) { - assert(toblock); - link[index].to=toblock; - link[index].next=toblock->link[index].from; // set target block - toblock->link[index].from=this; // remember who links me - } - struct { - Bit16u start,end; // where in the page is the original code - CodePageHandlerDynRec * handler; // page containing this code - } page; - struct { - Bit8u * start; // where in the cache are we - Bitu size; - CacheBlockDynRec * next; - // writemap masking maskpointer/start/length - // to allow holes in the writemap - Bit8u * wmapmask; - Bit16u maskstart; - Bit16u masklen; - } cache; - struct { - Bitu index; - CacheBlockDynRec * next; - } hash; - struct { - CacheBlockDynRec * to; // this block can transfer control to the to-block - CacheBlockDynRec * next; - CacheBlockDynRec * from; // the from-block can transfer control to this block - } link[2]; // maximal two links (conditional jumps) - CacheBlockDynRec * crossblock; -}; - -static struct { - struct { - CacheBlockDynRec * first; // the first cache block in the list - CacheBlockDynRec * active; // the current cache block - CacheBlockDynRec * free; // pointer to the free list - CacheBlockDynRec * running; // the last block that was entered for execution - } block; - Bit8u * pos; // position in the cache block - CodePageHandlerDynRec * free_pages; // pointer to the free list - CodePageHandlerDynRec * used_pages; // pointer to the list of used pages - CodePageHandlerDynRec * last_page; // the last used page -} cache; - - -// cache memory pointers, to be malloc'd later -static Bit8u * cache_code_start_ptr=NULL; -static Bit8u * cache_code=NULL; -static Bit8u * cache_code_link_blocks=NULL; - -static CacheBlockDynRec * cache_blocks=NULL; -static CacheBlockDynRec link_blocks[2]; // default linking (specially marked) - - -// the CodePageHandlerDynRec class provides access to the contained -// cache blocks and intercepts writes to the code for special treatment -class CodePageHandlerDynRec : public PageHandler { -public: - CodePageHandlerDynRec() { - invalidation_map=NULL; - } - - void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) { - // initialize this codepage handler - phys_page=_phys_page; - // save the old pagehandler to provide direct read access to the memory, - // and to be able to restore it later on - old_pagehandler=_old_pagehandler; - - // adjust flags - flags=old_pagehandler->flags|PFLAG_HASCODE; - flags&=~PFLAG_WRITEABLE; - - active_blocks=0; - active_count=16; - - // initialize the maps with zero (no cache blocks as well as code present) - memset(&hash_map,0,sizeof(hash_map)); - memset(&write_map,0,sizeof(write_map)); - if (invalidation_map!=NULL) { - free(invalidation_map); - invalidation_map=NULL; - } - } - - // clear out blocks that contain code which has been modified - bool InvalidateRange(Bitu start,Bitu end) { - Bits index=1+(end>>DYN_HASH_SHIFT); - bool is_current_block=false; // if the current block is modified, it has to be exited as soon as possible - - Bit32u ip_point=SegPhys(cs)+reg_eip; - ip_point=(PAGING_GetPhysicalPage(ip_point)-(phys_page<<12))+(ip_point&0xfff); - while (index>=0) { - Bitu map=0; - // see if there is still some code in the range - for (Bitu count=start;count<=end;count++) map+=write_map[count]; - if (!map) return is_current_block; // no more code, finished - - CacheBlockDynRec * block=hash_map[index]; - while (block) { - CacheBlockDynRec * nextblock=block->hash.next; - // test if this block is in the range - if (start<=block->page.end && end>=block->page.start) { - if (ip_point<=block->page.end && ip_point>=block->page.start) is_current_block=true; - block->Clear(); // clear the block, decrements the write_map accordingly - } - block=nextblock; - } - index--; - } - return is_current_block; - } - - // the following functions will clean all cache blocks that are invalid now due to the write - void writeb(PhysPt addr,Bitu val){ - addr&=4095; - if (host_readb(hostmem+addr)==(Bit8u)val) return; - host_writeb(hostmem+addr,val); - // see if there's code where we are writing to - if (!host_readb(&write_map[addr])) { - if (active_blocks) return; // still some blocks in this page - active_count--; - if (!active_count) Release(); // delay page releasing until active_count is zero - return; - } else if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } - invalidation_map[addr]++; - InvalidateRange(addr,addr); - } - void writew(PhysPt addr,Bitu val){ - addr&=4095; - if (host_readw(hostmem+addr)==(Bit16u)val) return; - host_writew(hostmem+addr,val); - // see if there's code where we are writing to - if (!host_readw(&write_map[addr])) { - if (active_blocks) return; // still some blocks in this page - active_count--; - if (!active_count) Release(); // delay page releasing until active_count is zero - return; - } else if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } -#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) - host_writew(&invalidation_map[addr], - host_readw(&invalidation_map[addr])+0x101); -#else - (*(Bit16u*)&invalidation_map[addr])+=0x101; -#endif - InvalidateRange(addr,addr+1); - } - void writed(PhysPt addr,Bitu val){ - addr&=4095; - if (host_readd(hostmem+addr)==(Bit32u)val) return; - host_writed(hostmem+addr,val); - // see if there's code where we are writing to - if (!host_readd(&write_map[addr])) { - if (active_blocks) return; // still some blocks in this page - active_count--; - if (!active_count) Release(); // delay page releasing until active_count is zero - return; - } else if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } -#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) - host_writed(&invalidation_map[addr], - host_readd(&invalidation_map[addr])+0x1010101); -#else - (*(Bit32u*)&invalidation_map[addr])+=0x1010101; -#endif - InvalidateRange(addr,addr+3); - } - bool writeb_checked(PhysPt addr,Bitu val) { - addr&=4095; - if (host_readb(hostmem+addr)==(Bit8u)val) return false; - // see if there's code where we are writing to - if (!host_readb(&write_map[addr])) { - if (!active_blocks) { - // no blocks left in this page, still delay the page releasing a bit - active_count--; - if (!active_count) Release(); - } - } else { - if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } - invalidation_map[addr]++; - if (InvalidateRange(addr,addr)) { - cpu.exception.which=SMC_CURRENT_BLOCK; - return true; - } - } - host_writeb(hostmem+addr,val); - return false; - } - bool writew_checked(PhysPt addr,Bitu val) { - addr&=4095; - if (host_readw(hostmem+addr)==(Bit16u)val) return false; - // see if there's code where we are writing to - if (!host_readw(&write_map[addr])) { - if (!active_blocks) { - // no blocks left in this page, still delay the page releasing a bit - active_count--; - if (!active_count) Release(); - } - } else { - if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } -#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) - host_writew(&invalidation_map[addr], - host_readw(&invalidation_map[addr])+0x101); -#else - (*(Bit16u*)&invalidation_map[addr])+=0x101; -#endif - if (InvalidateRange(addr,addr+1)) { - cpu.exception.which=SMC_CURRENT_BLOCK; - return true; - } - } - host_writew(hostmem+addr,val); - return false; - } - bool writed_checked(PhysPt addr,Bitu val) { - addr&=4095; - if (host_readd(hostmem+addr)==(Bit32u)val) return false; - // see if there's code where we are writing to - if (!host_readd(&write_map[addr])) { - if (!active_blocks) { - // no blocks left in this page, still delay the page releasing a bit - active_count--; - if (!active_count) Release(); - } - } else { - if (!invalidation_map) { - invalidation_map=(Bit8u*)malloc(4096); - memset(invalidation_map,0,4096); - } -#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) - host_writed(&invalidation_map[addr], - host_readd(&invalidation_map[addr])+0x1010101); -#else - (*(Bit32u*)&invalidation_map[addr])+=0x1010101; -#endif - if (InvalidateRange(addr,addr+3)) { - cpu.exception.which=SMC_CURRENT_BLOCK; - return true; - } - } - host_writed(hostmem+addr,val); - return false; - } - - // add a cache block to this page and note it in the hash map - void AddCacheBlock(CacheBlockDynRec * block) { - Bitu index=1+(block->page.start>>DYN_HASH_SHIFT); - block->hash.next=hash_map[index]; // link to old block at index from the new block - block->hash.index=index; - hash_map[index]=block; // put new block at hash position - block->page.handler=this; - active_blocks++; - } - // there's a block whose code started in a different page - void AddCrossBlock(CacheBlockDynRec * block) { - block->hash.next=hash_map[0]; - block->hash.index=0; - hash_map[0]=block; - block->page.handler=this; - active_blocks++; - } - // remove a cache block - void DelCacheBlock(CacheBlockDynRec * block) { - active_blocks--; - active_count=16; - CacheBlockDynRec * * bwhere=&hash_map[block->hash.index]; - while (*bwhere!=block) { - bwhere=&((*bwhere)->hash.next); - //Will crash if a block isn't found, which should never happen. - } - *bwhere=block->hash.next; - - // remove the cleared block from the write map - if (GCC_UNLIKELY(block->cache.wmapmask!=NULL)) { - // first part is not influenced by the mask - for (Bitu i=block->page.start;icache.maskstart;i++) { - if (write_map[i]) write_map[i]--; - } - Bitu maskct=0; - // last part sticks to the writemap mask - for (Bitu i=block->cache.maskstart;i<=block->page.end;i++,maskct++) { - if (write_map[i]) { - // only adjust writemap if it isn't masked - if ((maskct>=block->cache.masklen) || (!block->cache.wmapmask[maskct])) write_map[i]--; - } - } - free(block->cache.wmapmask); - block->cache.wmapmask=NULL; - } else { - for (Bitu i=block->page.start;i<=block->page.end;i++) { - if (write_map[i]) write_map[i]--; - } - } - } - - void Release(void) { - MEM_SetPageHandler(phys_page,1,old_pagehandler); // revert to old handler - PAGING_ClearTLB(); - - // remove page from the lists - if (prev) prev->next=next; - else cache.used_pages=next; - if (next) next->prev=prev; - else cache.last_page=prev; - next=cache.free_pages; - cache.free_pages=this; - prev=0; - } - void ClearRelease(void) { - // clear out all cache blocks in this page - for (Bitu index=0;index<(1+DYN_PAGE_HASH);index++) { - CacheBlockDynRec * block=hash_map[index]; - while (block) { - CacheBlockDynRec * nextblock=block->hash.next; - block->page.handler=0; // no need, full clear - block->Clear(); - block=nextblock; - } - } - Release(); // now can release this page - } - - CacheBlockDynRec * FindCacheBlock(Bitu start) { - CacheBlockDynRec * block=hash_map[1+(start>>DYN_HASH_SHIFT)]; - // see if there's a cache block present at the start address - while (block) { - if (block->page.start==start) return block; // found - block=block->hash.next; - } - return 0; // none found - } - - HostPt GetHostReadPt(Bitu phys_page) { - hostmem=old_pagehandler->GetHostReadPt(phys_page); - return hostmem; - } - HostPt GetHostWritePt(Bitu phys_page) { - return GetHostReadPt( phys_page ); - } -public: - // the write map, there are write_map[i] cache blocks that cover the byte at address i - Bit8u write_map[4096]; - Bit8u * invalidation_map; - CodePageHandlerDynRec * next, * prev; // page linking -private: - PageHandler * old_pagehandler; - - // hash map to quickly find the cache blocks in this page - CacheBlockDynRec * hash_map[1+DYN_PAGE_HASH]; - - Bitu active_blocks; // the number of cache blocks in this page - Bitu active_count; // delaying parameter to not immediately release a page - HostPt hostmem; - Bitu phys_page; -}; - - -static INLINE void cache_addunusedblock(CacheBlockDynRec * block) { - // block has become unused, add it to the freelist - block->cache.next=cache.block.free; - cache.block.free=block; -} - -static CacheBlockDynRec * cache_getblock(void) { - // get a free cache block and advance the free pointer - CacheBlockDynRec * ret=cache.block.free; - if (!ret) E_Exit("Ran out of CacheBlocks" ); - cache.block.free=ret->cache.next; - ret->cache.next=0; - return ret; -} - -void CacheBlockDynRec::Clear(void) { - Bitu ind; - // check if this is not a cross page block - if (hash.index) for (ind=0;ind<2;ind++) { - CacheBlockDynRec * fromlink=link[ind].from; - link[ind].from=0; - while (fromlink) { - CacheBlockDynRec * nextlink=fromlink->link[ind].next; - // clear the next-link and let the block point to the standard linkcode - fromlink->link[ind].next=0; - fromlink->link[ind].to=&link_blocks[ind]; - - fromlink=nextlink; - } - if (link[ind].to!=&link_blocks[ind]) { - // not linked to the standard linkcode, find the block that links to this block - CacheBlockDynRec * * wherelink=&link[ind].to->link[ind].from; - while (*wherelink != this && *wherelink) { - wherelink = &(*wherelink)->link[ind].next; - } - // now remove the link - if(*wherelink) - *wherelink = (*wherelink)->link[ind].next; - else { - LOG(LOG_CPU,LOG_ERROR)("Cache anomaly. please investigate"); - } - } - } else - cache_addunusedblock(this); - if (crossblock) { - // clear out the crossblock (in the page before) as well - crossblock->crossblock=0; - crossblock->Clear(); - crossblock=0; - } - if (page.handler) { - // clear out the code page handler - page.handler->DelCacheBlock(this); - page.handler=0; - } - if (cache.wmapmask){ - free(cache.wmapmask); - cache.wmapmask=NULL; - } -} - - -static CacheBlockDynRec * cache_openblock(void) { - CacheBlockDynRec * block=cache.block.active; - // check for enough space in this block - Bitu size=block->cache.size; - CacheBlockDynRec * nextblock=block->cache.next; - if (block->page.handler) - block->Clear(); - // block size must be at least CACHE_MAXSIZE - while (sizecache.size; - CacheBlockDynRec * tempblock=nextblock->cache.next; - if (nextblock->page.handler) - nextblock->Clear(); - // block is free now - cache_addunusedblock(nextblock); - nextblock=tempblock; - } -skipresize: - // adjust parameters and open this block - block->cache.size=size; - block->cache.next=nextblock; - cache.pos=block->cache.start; - return block; -} - -static void cache_closeblock(void) { - CacheBlockDynRec * block=cache.block.active; - // links point to the default linking code - block->link[0].to=&link_blocks[0]; - block->link[1].to=&link_blocks[1]; - block->link[0].from=0; - block->link[1].from=0; - block->link[0].next=0; - block->link[1].next=0; - // close the block with correct alignment - Bitu written=(Bitu)(cache.pos-block->cache.start); - if (written>block->cache.size) { - if (!block->cache.next) { - if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun 1 %d",written-block->cache.size); - } else E_Exit("CacheBlock overrun 2 written %d size %d",written,block->cache.size); - } else { - Bitu new_size; - Bitu left=block->cache.size-written; - // smaller than cache align then don't bother to resize - if (left>CACHE_ALIGN) { - new_size=((written-1)|(CACHE_ALIGN-1))+1; - CacheBlockDynRec * newblock=cache_getblock(); - // align block now to CACHE_ALIGN - newblock->cache.start=block->cache.start+new_size; - newblock->cache.size=block->cache.size-new_size; - newblock->cache.next=block->cache.next; - block->cache.next=newblock; - block->cache.size=new_size; - } - } - // advance the active block pointer - if (!block->cache.next || (block->cache.next->cache.start>(cache_code_start_ptr + CACHE_TOTAL - CACHE_MAXSIZE))) { -// LOG_MSG("Cache full restarting"); - cache.block.active=cache.block.first; - } else { - cache.block.active=block->cache.next; - } -} - - -// place an 8bit value into the cache -static INLINE void cache_addb(Bit8u val) { - *cache.pos++=val; -} - -// place a 16bit value into the cache -static INLINE void cache_addw(Bit16u val) { - *(Bit16u*)cache.pos=val; - cache.pos+=2; -} - -// place a 32bit value into the cache -static INLINE void cache_addd(Bit32u val) { - *(Bit32u*)cache.pos=val; - cache.pos+=4; -} - -// place a 64bit value into the cache -static INLINE void cache_addq(Bit64u val) { - *(Bit64u*)cache.pos=val; - cache.pos+=8; -} - - -static void dyn_return(BlockReturn retcode,bool ret_exception); -static void dyn_run_code(void); - - -/* Define temporary pagesize so the MPROTECT case and the regular case share as much code as possible */ -#if (C_HAVE_MPROTECT) -#define PAGESIZE_TEMP PAGESIZE -#else -#define PAGESIZE_TEMP 4096 -#endif - -static bool cache_initialized = false; - -static void cache_init(bool enable) { - Bits i; - if (enable) { - // see if cache is already initialized - if (cache_initialized) return; - cache_initialized = true; - if (cache_blocks == NULL) { - // allocate the cache blocks memory - cache_blocks=(CacheBlockDynRec*)malloc(CACHE_BLOCKS*sizeof(CacheBlockDynRec)); - if(!cache_blocks) E_Exit("Allocating cache_blocks has failed"); - memset(cache_blocks,0,sizeof(CacheBlockDynRec)*CACHE_BLOCKS); - cache.block.free=&cache_blocks[0]; - // initialize the cache blocks - for (i=0;icache.start=&cache_code[0]; - block->cache.size=CACHE_TOTAL; - block->cache.next=0; // last block in the list - } - // setup the default blocks for block linkage returns - cache.pos=&cache_code_link_blocks[0]; - link_blocks[0].cache.start=cache.pos; - // link code that returns with a special return code - dyn_return(BR_Link1,false); - cache.pos=&cache_code_link_blocks[32]; - link_blocks[1].cache.start=cache.pos; - // link code that returns with a special return code - dyn_return(BR_Link2,false); - - cache.pos=&cache_code_link_blocks[64]; - core_dynrec.runcode=(BlockReturn (*)(Bit8u*))cache.pos; -// link_blocks[1].cache.start=cache.pos; - dyn_run_code(); - - cache.free_pages=0; - cache.last_page=0; - cache.used_pages=0; - // setup the code pages - for (i=0;inext=cache.free_pages; - cache.free_pages=newpage; - } - } -} - -static void cache_close(void) { -/* for (;;) { - if (cache.used_pages) { - CodePageHandler * cpage=cache.used_pages; - CodePageHandler * npage=cache.used_pages->next; - cpage->ClearRelease(); - delete cpage; - cache.used_pages=npage; - } else break; - } - if (cache_blocks != NULL) { - free(cache_blocks); - cache_blocks = NULL; - } - if (cache_code_start_ptr != NULL) { - ### care: under windows VirtualFree() has to be used if - ### VirtualAlloc was used for memory allocation - free(cache_code_start_ptr); - cache_code_start_ptr = NULL; - } - cache_code = NULL; - cache_code_link_blocks = NULL; - cache_initialized = false; */ -} diff --git a/src/cpu/core_dynrec/decoder.h b/src/cpu/core_dynrec/decoder.h deleted file mode 100644 index 6c0a6bd..0000000 --- a/src/cpu/core_dynrec/decoder.h +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: decoder.h,v 1.5 2008/09/19 16:48:02 c2woody Exp $ */ - - -#include "decoder_basic.h" -#include "operators.h" -#include "decoder_opcodes.h" - -#include "dyn_fpu.h" - -/* - The function CreateCacheBlock translates the instruction stream - until either an unhandled instruction is found, the maximal - number of translated instructions is reached or some critical - instruction is encountered. -*/ - -static CacheBlockDynRec * CreateCacheBlock(CodePageHandlerDynRec * codepage,PhysPt start,Bitu max_opcodes) { - // initialize a load of variables - decode.code_start=start; - decode.code=start; - decode.page.code=codepage; - decode.page.index=start&4095; - decode.page.wmap=codepage->write_map; - decode.page.invmap=codepage->invalidation_map; - decode.page.first=start >> 12; - decode.active_block=decode.block=cache_openblock(); - decode.block->page.start=(Bit16u)decode.page.index; - codepage->AddCacheBlock(decode.block); - - InitFlagsOptimization(); - - // every codeblock that is run sets cache.block.running to itself - // so the block linking knows the last executed block - gen_mov_direct_ptr(&cache.block.running,(DRC_PTR_SIZE_IM)decode.block); - - // start with the cycles check - gen_mov_word_to_reg(FC_RETOP,&CPU_Cycles,true); - save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_leqzero(FC_RETOP); - save_info_dynrec[used_save_info_dynrec].type=cycle_check; - used_save_info_dynrec++; - - decode.cycles=0; - while (max_opcodes--) { - // Init prefixes - decode.big_addr=cpu.code.big; - decode.big_op=cpu.code.big; - decode.seg_prefix=0; - decode.seg_prefix_used=false; - decode.rep=REP_NONE; - decode.cycles++; - decode.op_start=decode.code; -restart_prefix: - Bitu opcode; - if (!decode.page.invmap) opcode=decode_fetchb(); - else { - // some entries in the invalidation map, see if the next - // instruction is known to be modified a lot - if (decode.page.index<4096) { - if (GCC_UNLIKELY(decode.page.invmap[decode.page.index]>=4)) goto illegalopcode; - opcode=decode_fetchb(); - } else { - // switch to the next page - opcode=decode_fetchb(); - if (GCC_UNLIKELY(decode.page.invmap && - (decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode; - } - } - switch (opcode) { - // instructions 'op reg8,reg8' and 'op [],reg8' - case 0x00:dyn_dop_ebgb(DOP_ADD);break; - case 0x08:dyn_dop_ebgb(DOP_OR);break; - case 0x10:dyn_dop_ebgb(DOP_ADC);break; - case 0x18:dyn_dop_ebgb(DOP_SBB);break; - case 0x20:dyn_dop_ebgb(DOP_AND);break; - case 0x28:dyn_dop_ebgb(DOP_SUB);break; - case 0x30:dyn_dop_ebgb(DOP_XOR);break; - case 0x38:dyn_dop_ebgb(DOP_CMP);break; - - // instructions 'op reg8,reg8' and 'op reg8,[]' - case 0x02:dyn_dop_gbeb(DOP_ADD);break; - case 0x0a:dyn_dop_gbeb(DOP_OR);break; - case 0x12:dyn_dop_gbeb(DOP_ADC);break; - case 0x1a:dyn_dop_gbeb(DOP_SBB);break; - case 0x22:dyn_dop_gbeb(DOP_AND);break; - case 0x2a:dyn_dop_gbeb(DOP_SUB);break; - case 0x32:dyn_dop_gbeb(DOP_XOR);break; - case 0x3a:dyn_dop_gbeb(DOP_CMP);break; - - // instructions 'op reg16/32,reg16/32' and 'op [],reg16/32' - case 0x01:dyn_dop_evgv(DOP_ADD);break; - case 0x09:dyn_dop_evgv(DOP_OR);break; - case 0x11:dyn_dop_evgv(DOP_ADC);break; - case 0x19:dyn_dop_evgv(DOP_SBB);break; - case 0x21:dyn_dop_evgv(DOP_AND);break; - case 0x29:dyn_dop_evgv(DOP_SUB);break; - case 0x31:dyn_dop_evgv(DOP_XOR);break; - case 0x39:dyn_dop_evgv(DOP_CMP);break; - - // instructions 'op reg16/32,reg16/32' and 'op reg16/32,[]' - case 0x03:dyn_dop_gvev(DOP_ADD);break; - case 0x0b:dyn_dop_gvev(DOP_OR);break; - case 0x13:dyn_dop_gvev(DOP_ADC);break; - case 0x1b:dyn_dop_gvev(DOP_SBB);break; - case 0x23:dyn_dop_gvev(DOP_AND);break; - case 0x2b:dyn_dop_gvev(DOP_SUB);break; - case 0x33:dyn_dop_gvev(DOP_XOR);break; - case 0x3b:dyn_dop_gvev(DOP_CMP);break; - - // instructions 'op reg8,imm8' - case 0x04:dyn_dop_byte_imm(DOP_ADD,DRC_REG_EAX,0);break; - case 0x0c:dyn_dop_byte_imm(DOP_OR,DRC_REG_EAX,0);break; - case 0x14:dyn_dop_byte_imm(DOP_ADC,DRC_REG_EAX,0);break; - case 0x1c:dyn_dop_byte_imm(DOP_SBB,DRC_REG_EAX,0);break; - case 0x24:dyn_dop_byte_imm(DOP_AND,DRC_REG_EAX,0);break; - case 0x2c:dyn_dop_byte_imm(DOP_SUB,DRC_REG_EAX,0);break; - case 0x34:dyn_dop_byte_imm(DOP_XOR,DRC_REG_EAX,0);break; - case 0x3c:dyn_dop_byte_imm(DOP_CMP,DRC_REG_EAX,0);break; - - // instructions 'op reg16/32,imm16/32' - case 0x05:dyn_dop_word_imm(DOP_ADD,DRC_REG_EAX);break; - case 0x0d:dyn_dop_word_imm_old(DOP_OR,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x15:dyn_dop_word_imm_old(DOP_ADC,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x1d:dyn_dop_word_imm_old(DOP_SBB,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x25:dyn_dop_word_imm(DOP_AND,DRC_REG_EAX);break; - case 0x2d:dyn_dop_word_imm_old(DOP_SUB,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x35:dyn_dop_word_imm_old(DOP_XOR,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - case 0x3d:dyn_dop_word_imm_old(DOP_CMP,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - - // push segment register onto stack - case 0x06:dyn_push_seg(DRC_SEG_ES);break; - case 0x0e:dyn_push_seg(DRC_SEG_CS);break; - case 0x16:dyn_push_seg(DRC_SEG_SS);break; - case 0x1e:dyn_push_seg(DRC_SEG_DS);break; - - // pop segment register from stack - case 0x07:dyn_pop_seg(DRC_SEG_ES);break; - case 0x17:dyn_pop_seg(DRC_SEG_SS);break; - case 0x1f:dyn_pop_seg(DRC_SEG_DS);break; - - // segment prefixes - case 0x26:dyn_segprefix(DRC_SEG_ES);goto restart_prefix; - case 0x2e:dyn_segprefix(DRC_SEG_CS);goto restart_prefix; - case 0x36:dyn_segprefix(DRC_SEG_SS);goto restart_prefix; - case 0x3e:dyn_segprefix(DRC_SEG_DS);goto restart_prefix; - case 0x64:dyn_segprefix(DRC_SEG_FS);goto restart_prefix; - case 0x65:dyn_segprefix(DRC_SEG_GS);goto restart_prefix; - -// case 0x27: DAA missing -// case 0x2f: DAS missing -// case 0x37: AAA missing -// case 0x3f: AAS missing - - // dual opcodes - case 0x0f: - { - Bitu dual_code=decode_fetchb(); - switch (dual_code) { - case 0x00: - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; - dyn_grp6(); - break; - case 0x01: - if (dyn_grp7()) goto finish_block; - break; -/* case 0x02: - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; - dyn_larlsl(true); - break; - case 0x03: - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; - dyn_larlsl(false); - break; */ - - case 0x20:dyn_mov_from_crx();break; - case 0x22:dyn_mov_to_crx();goto finish_block; - - // short conditional jumps - case 0x80:case 0x81:case 0x82:case 0x83:case 0x84:case 0x85:case 0x86:case 0x87: - case 0x88:case 0x89:case 0x8a:case 0x8b:case 0x8c:case 0x8d:case 0x8e:case 0x8f: - dyn_branched_exit((BranchTypes)(dual_code&0xf), - decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); - goto finish_block; - - // conditional byte set instructions -/* case 0x90:case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97: - case 0x98:case 0x99:case 0x9a:case 0x9b:case 0x9c:case 0x9d:case 0x9e:case 0x9f: - dyn_set_byte_on_condition((BranchTypes)(dual_code&0xf)); - AcquireFlags(FMASK_TEST); - break; */ - - // push/pop segment registers - case 0xa0:dyn_push_seg(DRC_SEG_FS);break; - case 0xa1:dyn_pop_seg(DRC_SEG_FS);break; - case 0xa8:dyn_push_seg(DRC_SEG_GS);break; - case 0xa9:dyn_pop_seg(DRC_SEG_GS);break; - - // double shift instructions - case 0xa4:dyn_dshift_ev_gv(true,true);break; - case 0xa5:dyn_dshift_ev_gv(true,false);break; - case 0xac:dyn_dshift_ev_gv(false,true);break; - case 0xad:dyn_dshift_ev_gv(false,false);break; - - case 0xaf:dyn_imul_gvev(0);break; - - // lfs - case 0xb4: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(DRC_SEG_FS); - break; - // lgs - case 0xb5: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(DRC_SEG_GS); - break; - - // zero-extending moves - case 0xb6:dyn_movx_ev_gb(false);break; - case 0xb7:dyn_movx_ev_gw(false);break; - - // sign-extending moves - case 0xbe:dyn_movx_ev_gb(true);break; - case 0xbf:dyn_movx_ev_gw(true);break; - - default: -// DYN_LOG("Unhandled dual opcode 0F%02X",dual_code); - goto illegalopcode; - } - break; - } - - // 'inc/dec reg16/32' - case 0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47: - dyn_sop_word(SOP_INC,opcode&7); - break; - case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f: - dyn_sop_word(SOP_DEC,opcode&7); - break; - - // 'push/pop reg16/32' - case 0x50:case 0x51:case 0x52:case 0x53:case 0x54:case 0x55:case 0x56:case 0x57: - dyn_push_reg(opcode&7); - break; - case 0x58:case 0x59:case 0x5a:case 0x5b:case 0x5c:case 0x5d:case 0x5e:case 0x5f: - dyn_pop_reg(opcode&7); - break; - - case 0x60: - if (decode.big_op) gen_call_function_raw((void *)&dynrec_pusha_dword); - else gen_call_function_raw((void *)&dynrec_pusha_word); - break; - case 0x61: - if (decode.big_op) gen_call_function_raw((void *)&dynrec_popa_dword); - else gen_call_function_raw((void *)&dynrec_popa_word); - break; - -// case 0x62: BOUND missing -// case 0x61: ARPL missing - - case 0x66:decode.big_op=!cpu.code.big;goto restart_prefix; - case 0x67:decode.big_addr=!cpu.code.big;goto restart_prefix; - - // 'push imm8/16/32' - case 0x68: - dyn_push_word_imm(decode.big_op ? decode_fetchd() : decode_fetchw()); - break; - case 0x6a: - dyn_push_byte_imm((Bit8s)decode_fetchb()); - break; - - // signed multiplication - case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break; - case 0x6b:dyn_imul_gvev(1);break; - -// case 0x6c to 0x6f missing (ins/outs) - - // short conditional jumps - case 0x70:case 0x71:case 0x72:case 0x73:case 0x74:case 0x75:case 0x76:case 0x77: - case 0x78:case 0x79:case 0x7a:case 0x7b:case 0x7c:case 0x7d:case 0x7e:case 0x7f: - dyn_branched_exit((BranchTypes)(opcode&0xf),(Bit8s)decode_fetchb()); - goto finish_block; - - // 'op []/reg8,imm8' - case 0x80: - case 0x82:dyn_grp1_eb_ib();break; - - // 'op []/reg16/32,imm16/32' - case 0x81:dyn_grp1_ev_iv(false);break; - case 0x83:dyn_grp1_ev_iv(true);break; - - // 'test []/reg8/16/32,reg8/16/32' - case 0x84:dyn_dop_gbeb(DOP_TEST);break; - case 0x85:dyn_dop_gvev(DOP_TEST);break; - - // 'xchg reg8/16/32,[]/reg8/16/32' - case 0x86:dyn_dop_ebgb_xchg();break; - case 0x87:dyn_dop_evgv_xchg();break; - - // 'mov []/reg8/16/32,reg8/16/32' - case 0x88:dyn_dop_ebgb_mov();break; - case 0x89:dyn_dop_evgv_mov();break; - // 'mov reg8/16/32,[]/reg8/16/32' - case 0x8a:dyn_dop_gbeb_mov();break; - case 0x8b:dyn_dop_gvev_mov();break; - - // move segment register into memory or a 16bit register - case 0x8c:dyn_mov_ev_seg();break; - - // load effective address - case 0x8d:dyn_lea();break; - - // move a value from memory or a 16bit register into a segment register - case 0x8e:dyn_mov_seg_ev();break; - - // 'pop []' - case 0x8f:dyn_pop_ev();break; - - case 0x90: // nop - case 0x9b: // wait - case 0xf0: // lock - break; - - case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97: - dyn_xchg_ax(opcode&7); - break; - - // sign-extend al into ax/sign-extend ax into eax - case 0x98:dyn_cbw();break; - // sign-extend ax into dx:ax/sign-extend eax into edx:eax - case 0x99:dyn_cwd();break; - - case 0x9a:dyn_call_far_imm();goto finish_block; - - case 0x9c: // pushf - AcquireFlags(FMASK_TEST); - gen_call_function_I((void *)&CPU_PUSHF,decode.big_op); - dyn_check_exception(FC_RETOP); - break; - case 0x9d: // popf - gen_call_function_I((void *)&CPU_POPF,decode.big_op); - dyn_check_exception(FC_RETOP); - InvalidateFlags(); - break; - - case 0x9e:dyn_sahf();break; -// case 0x9f: LAHF missing - - // 'mov al/ax,[]' - case 0xa0: - dyn_mov_byte_al_direct(decode.big_addr ? decode_fetchd() : decode_fetchw()); - break; - case 0xa1: - dyn_mov_byte_ax_direct(decode.big_addr ? decode_fetchd() : decode_fetchw()); - break; - // 'mov [],al/ax' - case 0xa2: - dyn_mov_byte_direct_al(); - break; - case 0xa3: - dyn_mov_byte_direct_ax(decode.big_addr ? decode_fetchd() : decode_fetchw()); - break; - - -// case 0xa6 to 0xaf string operations, some missing - - // movsb/w/d - case 0xa4:dyn_string(STR_MOVSB);break; - case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break; - - // stosb/w/d - case 0xaa:dyn_string(STR_STOSB);break; - case 0xab:dyn_string(decode.big_op ? STR_STOSD : STR_STOSW);break; - - // lodsb/w/d - case 0xac:dyn_string(STR_LODSB);break; - case 0xad:dyn_string(decode.big_op ? STR_LODSD : STR_LODSW);break; - - - // 'test reg8/16/32,imm8/16/32' - case 0xa8:dyn_dop_byte_imm(DOP_TEST,DRC_REG_EAX,0);break; - case 0xa9:dyn_dop_word_imm_old(DOP_TEST,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; - - // 'mov reg8/16/32,imm8/16/32' - case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7: - dyn_mov_byte_imm(opcode&3,(opcode>>2)&1,decode_fetchb()); - break; - case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf: - dyn_mov_word_imm(opcode&7);break; - break; - - // 'shiftop []/reg8,imm8/1/cl' - case 0xc0:dyn_grp2_eb(grp2_imm);break; - case 0xd0:dyn_grp2_eb(grp2_1);break; - case 0xd2:dyn_grp2_eb(grp2_cl);break; - - // 'shiftop []/reg16/32,imm8/1/cl' - case 0xc1:dyn_grp2_ev(grp2_imm);break; - case 0xd1:dyn_grp2_ev(grp2_1);break; - case 0xd3:dyn_grp2_ev(grp2_cl);break; - - // retn [param] - case 0xc2:dyn_ret_near(decode_fetchw());goto finish_block; - case 0xc3:dyn_ret_near(0);goto finish_block; - - // les - case 0xc4: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(DRC_SEG_ES); - break; - // lds - case 0xc5: - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode; - dyn_load_seg_off_ea(DRC_SEG_DS);break; - - // 'mov []/reg8/16/32,imm8/16/32' - case 0xc6:dyn_dop_ebib_mov();break; - case 0xc7:dyn_dop_eviv_mov();break; - - case 0xc8:dyn_enter();break; - case 0xc9:dyn_leave();break; - - // retf [param] - case 0xca:dyn_ret_far(decode_fetchw());goto finish_block; - case 0xcb:dyn_ret_far(0);goto finish_block; - - // int/iret - case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block; - case 0xcf:dyn_iret();goto finish_block; - -// case 0xd4: AAM missing -// case 0xd5: AAD missing - -// case 0xd6: SALC missing -// case 0xd7: XLAT missing - - -#ifdef CPU_FPU - // floating point instructions - case 0xd8: - dyn_fpu_esc0(); - break; - case 0xd9: - dyn_fpu_esc1(); - break; - case 0xda: - dyn_fpu_esc2(); - break; - case 0xdb: - dyn_fpu_esc3(); - break; - case 0xdc: - dyn_fpu_esc4(); - break; - case 0xdd: - dyn_fpu_esc5(); - break; - case 0xde: - dyn_fpu_esc6(); - break; - case 0xdf: - dyn_fpu_esc7(); - break; -#endif - - - // loop instructions - case 0xe0:dyn_loop(LOOP_NE);goto finish_block; - case 0xe1:dyn_loop(LOOP_E);goto finish_block; - case 0xe2:dyn_loop(LOOP_NONE);goto finish_block; - case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block; - - - // 'in al/ax/eax,port_imm' - case 0xe4:dyn_read_port_byte_direct(decode_fetchb());break; - case 0xe5:dyn_read_port_word_direct(decode_fetchb());break; - // 'out port_imm,al/ax/eax' - case 0xe6:dyn_write_port_byte_direct(decode_fetchb());break; - case 0xe7:dyn_write_port_word_direct(decode_fetchb());break; - - // 'in al/ax/eax,port_dx' - case 0xec:dyn_read_port_byte();break; - case 0xed:dyn_read_port_word();break; - // 'out port_dx,al/ax/eax' - case 0xee:dyn_write_port_byte();break; - case 0xef:dyn_write_port_word();break; - - - // 'call near imm16/32' - case 0xe8: - dyn_call_near_imm(); - goto finish_block; - // 'jmp near imm16/32' - case 0xe9: - dyn_exit_link(decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); - goto finish_block; - // 'jmp far' - case 0xea: - dyn_jmp_far_imm(); - goto finish_block; - // 'jmp short imm8' - case 0xeb: - dyn_exit_link((Bit8s)decode_fetchb()); - goto finish_block; - - - // repeat prefixes - case 0xf2: - decode.rep=REP_NZ; - goto restart_prefix; - case 0xf3: - decode.rep=REP_Z; - goto restart_prefix; - - case 0xf5: //CMC - gen_call_function_raw((void*)dynrec_cmc); - break; - case 0xf8: //CLC - gen_call_function_raw((void*)dynrec_clc); - break; - case 0xf9: //STC - gen_call_function_raw((void*)dynrec_stc); - break; - - case 0xf6:dyn_grp3_eb();break; - case 0xf7:dyn_grp3_ev();break; - - case 0xfa: //CLI - gen_call_function_raw((void *)&CPU_CLI); - dyn_check_exception(FC_RETOP); - break; - case 0xfb: //STI - gen_call_function_raw((void *)&CPU_STI); - dyn_check_exception(FC_RETOP); - if (max_opcodes<=0) max_opcodes=1; //Allow 1 extra opcode - break; - - case 0xfc: //CLD - gen_call_function_raw((void*)dynrec_cld); - break; - case 0xfd: //STD - gen_call_function_raw((void*)dynrec_std); - break; - - case 0xfe: - if (dyn_grp4_eb()) goto finish_block; - break; - case 0xff: - if (dyn_grp4_ev()) goto core_close_block; - break; - - default: -// DYN_LOG("Dynrec unhandled opcode %X",opcode); - goto illegalopcode; - } - } - // normal exit because the maximal number of opcodes has been reached - dyn_set_eip_end(); -core_close_block: - dyn_reduce_cycles(); - dyn_return(BR_Normal); - dyn_closeblock(); - goto finish_block; -illegalopcode: - // some unhandled opcode has been encountered - dyn_set_eip_last(); - dyn_reduce_cycles(); - dyn_return(BR_Opcode); // tell the core what happened - dyn_closeblock(); - goto finish_block; -finish_block: - - // setup the correct end-address - decode.page.index--; - decode.active_block->page.end=(Bit16u)decode.page.index; -// LOG_MSG("Created block size %d start %d end %d",decode.block->cache.size,decode.block->page.start,decode.block->page.end); - - return decode.block; -} diff --git a/src/cpu/core_dynrec/decoder_basic.h b/src/cpu/core_dynrec/decoder_basic.h deleted file mode 100644 index 65d442d..0000000 --- a/src/cpu/core_dynrec/decoder_basic.h +++ /dev/null @@ -1,1239 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: decoder_basic.h,v 1.14 2009/03/29 17:32:20 qbix79 Exp $ */ - - -/* - This file provides some definitions and basic level functions - that use code generating functions from risc_?.h - Important is the function call generation including parameter - loading, the effective address calculation and the memory - access functions. -*/ - - -// instructions that use one operand -enum SingleOps { - SOP_INC,SOP_DEC, - SOP_NOT,SOP_NEG -}; - -// instructions that use two operand -enum DualOps { - DOP_ADD,DOP_ADC, - DOP_SUB,DOP_SBB, - DOP_CMP,DOP_XOR, - DOP_AND,DOP_OR, - DOP_TEST, - DOP_MOV, - DOP_XCHG -}; - -// shift and rotate functions -enum ShiftOps { - SHIFT_ROL,SHIFT_ROR, - SHIFT_RCL,SHIFT_RCR, - SHIFT_SHL,SHIFT_SHR, - SHIFT_SAL,SHIFT_SAR -}; - -// branch conditions -enum BranchTypes { - BR_O,BR_NO,BR_B,BR_NB, - BR_Z,BR_NZ,BR_BE,BR_NBE, - BR_S,BR_NS,BR_P,BR_NP, - BR_L,BR_NL,BR_LE,BR_NLE -}; - -// string instructions -enum StringOps { - STR_OUTSB=0,STR_OUTSW,STR_OUTSD, - STR_INSB=4,STR_INSW,STR_INSD, - STR_MOVSB=8,STR_MOVSW,STR_MOVSD, - STR_LODSB=12,STR_LODSW,STR_LODSD, - STR_STOSB=16,STR_STOSW,STR_STOSD, - STR_SCASB=20,STR_SCASW,STR_SCASD, - STR_CMPSB=24,STR_CMPSW,STR_CMPSD -}; - -// repeat prefix type (for string operations) -enum REP_Type { - REP_NONE=0,REP_NZ,REP_Z -}; - -// loop type -enum LoopTypes { - LOOP_NONE,LOOP_NE,LOOP_E,LOOP_JCXZ -}; - -// rotate operand type -enum grp2_types { - grp2_1,grp2_imm,grp2_cl -}; - -// opcode mapping for group1 instructions -static DualOps grp1_table[8]={ - DOP_ADD,DOP_OR,DOP_ADC,DOP_SBB,DOP_AND,DOP_SUB,DOP_XOR,DOP_CMP -}; - - -// decoding information used during translation of a code block -static struct DynDecode { - PhysPt code; // pointer to next byte in the instruction stream - PhysPt code_start; // pointer to the start of the current code block - PhysPt op_start; // pointer to the start of the current instruction - bool big_op; // operand modifier - bool big_addr; // address modifier - REP_Type rep; // current repeat prefix - Bitu cycles; // number cycles used by currently translated code - bool seg_prefix_used; // segment overridden - Bit8u seg_prefix; // segment prefix (if seg_prefix_used==true) - - // block that contains the first instruction translated - CacheBlockDynRec * block; - // block that contains the current byte of the instruction stream - CacheBlockDynRec * active_block; - - // the active page (containing the current byte of the instruction stream) - struct { - CodePageHandlerDynRec * code; - Bitu index; // index to the current byte of the instruction stream - Bit8u * wmap; // write map that indicates code presence for every byte of this page - Bit8u * invmap; // invalidation map - Bitu first; // page number - } page; - - // modrm state of the current instruction (if used) - struct { - Bitu val; - Bitu mod; - Bitu rm; - Bitu reg; - } modrm; -} decode; - - -static bool MakeCodePage(Bitu lin_addr,CodePageHandlerDynRec * &cph) { - Bit8u rdval; - //Ensure page contains memory: - if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true; - - PageHandler * handler=get_tlb_readhandler(lin_addr); - if (handler->flags & PFLAG_HASCODE) { - // this is a codepage handler, and the one that we're looking for - cph=(CodePageHandlerDynRec *)handler; - return false; - } - if (handler->flags & PFLAG_NOCODE) { - if (PAGING_ForcePageInit(lin_addr)) { - handler=get_tlb_readhandler(lin_addr); - if (handler->flags & PFLAG_HASCODE) { - cph=(CodePageHandlerDynRec *)handler; - return false; - } - } - if (handler->flags & PFLAG_NOCODE) { - LOG_MSG("DYNREC:Can't run code in this page"); - cph=0; - return false; - } - } - Bitu lin_page=lin_addr>>12; - Bitu phys_page=lin_page; - // find the physical page that the linear page is mapped to - if (!PAGING_MakePhysPage(phys_page)) { - LOG_MSG("DYNREC:Can't find physpage"); - cph=0; - return false; - } - // find a free CodePage - if (!cache.free_pages) { - if (cache.used_pages!=decode.page.code) cache.used_pages->ClearRelease(); - else { - // try another page to avoid clearing our source-crosspage - if ((cache.used_pages->next) && (cache.used_pages->next!=decode.page.code)) - cache.used_pages->next->ClearRelease(); - else { - LOG_MSG("DYNREC:Invalid cache links"); - cache.used_pages->ClearRelease(); - } - } - } - CodePageHandlerDynRec * cpagehandler=cache.free_pages; - cache.free_pages=cache.free_pages->next; - - // adjust previous and next page pointer - cpagehandler->prev=cache.last_page; - cpagehandler->next=0; - if (cache.last_page) cache.last_page->next=cpagehandler; - cache.last_page=cpagehandler; - if (!cache.used_pages) cache.used_pages=cpagehandler; - - // initialize the code page handler and add the handler to the memory page - cpagehandler->SetupAt(phys_page,handler); - MEM_SetPageHandler(phys_page,1,cpagehandler); - PAGING_UnlinkPages(lin_page,1); - cph=cpagehandler; - return false; -} - -static void decode_advancepage(void) { - // Advance to the next page - decode.active_block->page.end=4095; - // trigger possible page fault here - decode.page.first++; - Bitu faddr=decode.page.first << 12; - mem_readb(faddr); - MakeCodePage(faddr,decode.page.code); - CacheBlockDynRec * newblock=cache_getblock(); - decode.active_block->crossblock=newblock; - newblock->crossblock=decode.active_block; - decode.active_block=newblock; - decode.active_block->page.start=0; - decode.page.code->AddCrossBlock(decode.active_block); - decode.page.wmap=decode.page.code->write_map; - decode.page.invmap=decode.page.code->invalidation_map; - decode.page.index=0; -} - -// fetch the next byte of the instruction stream -static Bit8u decode_fetchb(void) { - if (GCC_UNLIKELY(decode.page.index>=4096)) { - decode_advancepage(); - } - decode.page.wmap[decode.page.index]+=0x01; - decode.page.index++; - decode.code+=1; - return mem_readb(decode.code-1); -} -// fetch the next word of the instruction stream -static Bit16u decode_fetchw(void) { - if (GCC_UNLIKELY(decode.page.index>=4095)) { - Bit16u val=decode_fetchb(); - val|=decode_fetchb() << 8; - return val; - } - *(Bit16u *)&decode.page.wmap[decode.page.index]+=0x0101; - decode.code+=2;decode.page.index+=2; - return mem_readw(decode.code-2); -} -// fetch the next dword of the instruction stream -static Bit32u decode_fetchd(void) { - if (GCC_UNLIKELY(decode.page.index>=4093)) { - Bit32u val=decode_fetchb(); - val|=decode_fetchb() << 8; - val|=decode_fetchb() << 16; - val|=decode_fetchb() << 24; - return val; - /* Advance to the next page */ - } - *(Bit32u *)&decode.page.wmap[decode.page.index]+=0x01010101; - decode.code+=4;decode.page.index+=4; - return mem_readd(decode.code-4); -} - -#define START_WMMEM 64 - -// adjust writemap mask to care for map holes due to special -// codefetch functions -static void INLINE decode_increase_wmapmask(Bitu size) { - Bitu mapidx; - CacheBlockDynRec* activecb=decode.active_block; - if (GCC_UNLIKELY(!activecb->cache.wmapmask)) { - // no mask memory yet allocated, start with a small buffer - activecb->cache.wmapmask=(Bit8u*)malloc(START_WMMEM); - memset(activecb->cache.wmapmask,0,START_WMMEM); - activecb->cache.maskstart=decode.page.index; // start of buffer is current code position - activecb->cache.masklen=START_WMMEM; - mapidx=0; - } else { - mapidx=decode.page.index-activecb->cache.maskstart; - if (GCC_UNLIKELY(mapidx+size>=activecb->cache.masklen)) { - // mask buffer too small, increase - Bitu newmasklen=activecb->cache.masklen*4; - if (newmasklencache.wmapmask,activecb->cache.masklen); - free(activecb->cache.wmapmask); - activecb->cache.wmapmask=tempmem; - activecb->cache.masklen=newmasklen; - } - } - // update mask entries - switch (size) { - case 1 : activecb->cache.wmapmask[mapidx]+=0x01; break; - case 2 : (*(Bit16u*)&activecb->cache.wmapmask[mapidx])+=0x0101; break; - case 4 : (*(Bit32u*)&activecb->cache.wmapmask[mapidx])+=0x01010101; break; - } -} - -// fetch a byte, val points to the code location if possible, -// otherwise val contains the current value read from the position -static bool decode_fetchb_imm(Bitu & val) { - if (GCC_UNLIKELY(decode.page.index>=4096)) { - decode_advancepage(); - } - HostPt tlb_addr=get_tlb_read(decode.code); - // see if position is directly accessible - if (tlb_addr) { - val=(Bitu)(tlb_addr+decode.code); - decode_increase_wmapmask(1); - decode.code++; - decode.page.index++; - return true; - } - // not directly accessible, just fetch the value - val=(Bit32u)decode_fetchb(); - return false; -} - -// fetch a word, val points to the code location if possible, -// otherwise val contains the current value read from the position -static bool decode_fetchw_imm(Bitu & val) { - if (decode.page.index<4095) { - HostPt tlb_addr=get_tlb_read(decode.code); - // see if position is directly accessible - if (tlb_addr) { - val=(Bitu)(tlb_addr+decode.code); - decode_increase_wmapmask(2); - decode.code+=2; - decode.page.index+=2; - return true; - } - } - // not directly accessible, just fetch the value - val=decode_fetchw(); - return false; -} - -// fetch a dword, val points to the code location if possible, -// otherwise val contains the current value read from the position -static bool decode_fetchd_imm(Bitu & val) { - if (decode.page.index<4093) { - HostPt tlb_addr=get_tlb_read(decode.code); - // see if position is directly accessible - if (tlb_addr) { - val=(Bitu)(tlb_addr+decode.code); - decode_increase_wmapmask(4); - decode.code+=4; - decode.page.index+=4; - return true; - } - } - // not directly accessible, just fetch the value - val=decode_fetchd(); - return false; -} - - -// modrm decoding helper -static void INLINE dyn_get_modrm(void) { - decode.modrm.val=decode_fetchb(); - decode.modrm.mod=(decode.modrm.val >> 6) & 3; - decode.modrm.reg=(decode.modrm.val >> 3) & 7; - decode.modrm.rm=(decode.modrm.val & 7); -} - - -#ifdef DRC_USE_SEGS_ADDR - -#define MOV_SEG_VAL_TO_HOST_REG(host_reg, seg_index) gen_mov_seg16_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_SEG_VAL(seg_index)) - (DRC_PTR_SIZE_IM)(&Segs)) - -#define MOV_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_mov_seg32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_SEG_PHYS(seg_index)) - (DRC_PTR_SIZE_IM)(&Segs)) -#define ADD_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_add_seg32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_SEG_PHYS(seg_index)) - (DRC_PTR_SIZE_IM)(&Segs)) - -#else - -#define MOV_SEG_VAL_TO_HOST_REG(host_reg, seg_index) gen_mov_word_to_reg(host_reg,DRCD_SEG_VAL(seg_index),false) - -#define MOV_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_mov_word_to_reg(host_reg,DRCD_SEG_PHYS(seg_index),true) -#define ADD_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_add(host_reg,DRCD_SEG_PHYS(seg_index)) - -#endif - - -#ifdef DRC_USE_REGS_ADDR - -#define MOV_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_mov_regval32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_VAL(reg_index)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define ADD_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_add_regval32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_VAL(reg_index)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) - -#define MOV_REG_WORD16_TO_HOST_REG(host_reg, reg_index) gen_mov_regval16_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,false)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_WORD32_TO_HOST_REG(host_reg, reg_index) gen_mov_regval32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,true)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_WORD_TO_HOST_REG(host_reg, reg_index, dword) gen_mov_regword_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,dword)) - (DRC_PTR_SIZE_IM)(&cpu_regs), dword) - -#define MOV_REG_WORD16_FROM_HOST_REG(host_reg, reg_index) gen_mov_regval16_from_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,false)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_WORD32_FROM_HOST_REG(host_reg, reg_index) gen_mov_regval32_from_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,true)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_WORD_FROM_HOST_REG(host_reg, reg_index, dword) gen_mov_regword_from_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,dword)) - (DRC_PTR_SIZE_IM)(&cpu_regs), dword) - -#define MOV_REG_BYTE_TO_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_regbyte_to_reg_low(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(host_reg, reg_index, high_byte) gen_mov_regbyte_to_reg_low_canuseword(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) -#define MOV_REG_BYTE_FROM_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_regbyte_from_reg_low(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs)) - -#else - -#define MOV_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_mov_word_to_reg(host_reg,DRCD_REG_VAL(reg_index),true) -#define ADD_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_add(host_reg,DRCD_REG_VAL(reg_index)) - -#define MOV_REG_WORD16_TO_HOST_REG(host_reg, reg_index) gen_mov_word_to_reg(host_reg,DRCD_REG_WORD(reg_index,false),false) -#define MOV_REG_WORD32_TO_HOST_REG(host_reg, reg_index) gen_mov_word_to_reg(host_reg,DRCD_REG_WORD(reg_index,true),true) -#define MOV_REG_WORD_TO_HOST_REG(host_reg, reg_index, dword) gen_mov_word_to_reg(host_reg,DRCD_REG_WORD(reg_index,dword),dword) - -#define MOV_REG_WORD16_FROM_HOST_REG(host_reg, reg_index) gen_mov_word_from_reg(host_reg,DRCD_REG_WORD(reg_index,false),false) -#define MOV_REG_WORD32_FROM_HOST_REG(host_reg, reg_index) gen_mov_word_from_reg(host_reg,DRCD_REG_WORD(reg_index,true),true) -#define MOV_REG_WORD_FROM_HOST_REG(host_reg, reg_index, dword) gen_mov_word_from_reg(host_reg,DRCD_REG_WORD(reg_index,dword),dword) - -#define MOV_REG_BYTE_TO_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_byte_to_reg_low(host_reg,DRCD_REG_BYTE(reg_index,high_byte)) -#define MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(host_reg, reg_index, high_byte) gen_mov_byte_to_reg_low_canuseword(host_reg,DRCD_REG_BYTE(reg_index,high_byte)) -#define MOV_REG_BYTE_FROM_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_byte_from_reg_low(host_reg,DRCD_REG_BYTE(reg_index,high_byte)) - -#endif - - -#define DYN_LEA_MEM_MEM(ea_reg, op1, op2, scale, imm) dyn_lea_mem_mem(ea_reg,op1,op2,scale,imm) - -#if defined(DRC_USE_REGS_ADDR) && defined(DRC_USE_SEGS_ADDR) - -#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_segphys_regval(ea_reg,op1_index,op2_index,scale,imm) -#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_regval_regval(ea_reg,op1_index,op2_index,scale,imm) -#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_regval(ea_reg,op1,op2_index,scale,imm) - -#elif defined(DRC_USE_REGS_ADDR) - -#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_regval(ea_reg,DRCD_SEG_PHYS(op1_index),op2_index,scale,imm) -#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_regval_regval(ea_reg,op1_index,op2_index,scale,imm) -#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_regval(ea_reg,op1,op2_index,scale,imm) - -#elif defined(DRC_USE_SEGS_ADDR) - -#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_segphys_mem(ea_reg,op1_index,DRCD_REG_VAL(op2_index),scale,imm) -#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,DRCD_REG_VAL(op1_index),DRCD_REG_VAL(op2_index),scale,imm) -#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,op1,DRCD_REG_VAL(op2_index),scale,imm) - -#else - -#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,DRCD_SEG_PHYS(op1_index),DRCD_REG_VAL(op2_index),scale,imm) -#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,DRCD_REG_VAL(op1_index),DRCD_REG_VAL(op2_index),scale,imm) -#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,op1,DRCD_REG_VAL(op2_index),scale,imm) - -#endif - - - -// adjust CPU_Cycles value -static void dyn_reduce_cycles(void) { - if (!decode.cycles) decode.cycles++; - gen_sub_direct_word(&CPU_Cycles,decode.cycles,true); -} - - -// set reg to the start of the next instruction -// set reg_eip to the start of the current instruction -static INLINE void dyn_set_eip_last_end(HostReg reg) { - gen_mov_word_to_reg(reg,®_eip,true); - gen_add_imm(reg,(Bit32u)(decode.code-decode.code_start)); - gen_add_direct_word(®_eip,decode.op_start-decode.code_start,decode.big_op); -} - -// set reg_eip to the start of the current instruction -static INLINE void dyn_set_eip_last(void) { - gen_add_direct_word(®_eip,decode.op_start-decode.code_start,cpu.code.big); -} - -// set reg_eip to the start of the next instruction -static INLINE void dyn_set_eip_end(void) { - gen_add_direct_word(®_eip,decode.code-decode.code_start,cpu.code.big); -} - -// set reg_eip to the start of the next instruction plus an offset (imm) -static INLINE void dyn_set_eip_end(HostReg reg,Bit32u imm=0) { - gen_mov_word_to_reg(reg,®_eip,decode.big_op); - gen_add_imm(reg,(Bit32u)(decode.code-decode.code_start+imm)); - if (!decode.big_op) gen_extend_word(false,reg); -} - - - -// the following functions generate function calls -// parameters are loaded by generating code using gen_load_param_ which -// is architecture dependent -// R=host register; I=32bit immediate value; A=address value; m=memory - -static DRC_PTR_SIZE_IM INLINE gen_call_function_R(void * func,Bitu op) { - gen_load_param_reg(op,0); - return gen_call_function_setup(func, 1); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_R3(void * func,Bitu op) { - gen_load_param_reg(op,2); - return gen_call_function_setup(func, 3, true); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_RI(void * func,Bitu op1,Bitu op2) { - gen_load_param_imm(op2,1); - gen_load_param_reg(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_RA(void * func,Bitu op1,DRC_PTR_SIZE_IM op2) { - gen_load_param_addr(op2,1); - gen_load_param_reg(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_RR(void * func,Bitu op1,Bitu op2) { - gen_load_param_reg(op2,1); - gen_load_param_reg(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_IR(void * func,Bitu op1,Bitu op2) { - gen_load_param_reg(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_I(void * func,Bitu op) { - gen_load_param_imm(op,0); - return gen_call_function_setup(func, 1); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_II(void * func,Bitu op1,Bitu op2) { - gen_load_param_imm(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_III(void * func,Bitu op1,Bitu op2,Bitu op3) { - gen_load_param_imm(op3,2); - gen_load_param_imm(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 3); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_IA(void * func,Bitu op1,DRC_PTR_SIZE_IM op2) { - gen_load_param_addr(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 2); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_IIR(void * func,Bitu op1,Bitu op2,Bitu op3) { - gen_load_param_reg(op3,2); - gen_load_param_imm(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 3); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_IIIR(void * func,Bitu op1,Bitu op2,Bitu op3,Bitu op4) { - gen_load_param_reg(op4,3); - gen_load_param_imm(op3,2); - gen_load_param_imm(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 4); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_IRRR(void * func,Bitu op1,Bitu op2,Bitu op3,Bitu op4) { - gen_load_param_reg(op4,3); - gen_load_param_reg(op3,2); - gen_load_param_reg(op2,1); - gen_load_param_imm(op1,0); - return gen_call_function_setup(func, 4); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_m(void * func,Bitu op) { - gen_load_param_mem(op,2); - return gen_call_function_setup(func, 3, true); -} - -static DRC_PTR_SIZE_IM INLINE gen_call_function_mm(void * func,Bitu op1,Bitu op2) { - gen_load_param_mem(op2,3); - gen_load_param_mem(op1,2); - return gen_call_function_setup(func, 4, true); -} - - - -enum save_info_type {db_exception, cycle_check, string_break}; - - -// function that is called on exceptions -static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub) { - reg_eip+=eip_add; - CPU_Cycles-=cycle_sub; - if (cpu.exception.which==SMC_CURRENT_BLOCK) return BR_SMCBlock; - CPU_Exception(cpu.exception.which,cpu.exception.error); - return BR_Normal; -} - - -// array with information about code that is generated at the -// end of a cache block because it is rarely reached (like exceptions) -static struct { - save_info_type type; - DRC_PTR_SIZE_IM branch_pos; - Bit32u eip_change; - Bitu cycles; -} save_info_dynrec[512]; - -Bitu used_save_info_dynrec=0; - - -// return from current block, with returncode -static void dyn_return(BlockReturn retcode,bool ret_exception=false) { - if (!ret_exception) { - gen_mov_dword_to_reg_imm(FC_RETOP,retcode); - } - gen_return_function(); -} - -static void dyn_run_code(void) { - gen_run_code(); - gen_return_function(); -} - -// fill in code at the end of the block that contains rarely-executed code -// which is executed conditionally (like exceptions) -static void dyn_fill_blocks(void) { - for (Bitu sct=0; sctcache.start,decode.block->cache.size); -} - - -// add a check that can branch to the exception handling -static void dyn_check_exception(HostReg reg) { - save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_nonzero(reg,false); - if (!decode.cycles) decode.cycles++; - save_info_dynrec[used_save_info_dynrec].cycles=decode.cycles; - // in case of an exception eip will point to the start of the current instruction - save_info_dynrec[used_save_info_dynrec].eip_change=decode.op_start-decode.code_start; - if (!cpu.code.big) save_info_dynrec[used_save_info_dynrec].eip_change&=0xffff; - save_info_dynrec[used_save_info_dynrec].type=db_exception; - used_save_info_dynrec++; -} - - - -bool DRC_CALL_CONV mem_readb_checked_drc(PhysPt address) DRC_FC; -bool DRC_CALL_CONV mem_readb_checked_drc(PhysPt address) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) { - *((Bit8u*)(&core_dynrec.readdata))=host_readb(tlb_addr+address); - return false; - } else { - return get_tlb_readhandler(address)->readb_checked(address, (Bit8u*)(&core_dynrec.readdata)); - } -} - -bool DRC_CALL_CONV mem_writeb_checked_drc(PhysPt address,Bit8u val) DRC_FC; -bool DRC_CALL_CONV mem_writeb_checked_drc(PhysPt address,Bit8u val) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) { - host_writeb(tlb_addr+address,val); - return false; - } else return get_tlb_writehandler(address)->writeb_checked(address,val); -} - -bool DRC_CALL_CONV mem_readw_checked_drc(PhysPt address) DRC_FC; -bool DRC_CALL_CONV mem_readw_checked_drc(PhysPt address) { - if ((address & 0xfff)<0xfff) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) { - *((Bit16u*)(&core_dynrec.readdata))=host_readw(tlb_addr+address); - return false; - } else return get_tlb_readhandler(address)->readw_checked(address, (Bit16u*)(&core_dynrec.readdata)); - } else return mem_unalignedreadw_checked(address, ((Bit16u*)(&core_dynrec.readdata))); -} - -bool DRC_CALL_CONV mem_readd_checked_drc(PhysPt address) DRC_FC; -bool DRC_CALL_CONV mem_readd_checked_drc(PhysPt address) { - if ((address & 0xfff)<0xffd) { - HostPt tlb_addr=get_tlb_read(address); - if (tlb_addr) { - *((Bit32u*)(&core_dynrec.readdata))=host_readd(tlb_addr+address); - return false; - } else return get_tlb_readhandler(address)->readd_checked(address, (Bit32u*)(&core_dynrec.readdata)); - } else return mem_unalignedreadd_checked(address, ((Bit32u*)(&core_dynrec.readdata))); -} - -bool DRC_CALL_CONV mem_writew_checked_drc(PhysPt address,Bit16u val) DRC_FC; -bool DRC_CALL_CONV mem_writew_checked_drc(PhysPt address,Bit16u val) { - if ((address & 0xfff)<0xfff) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) { - host_writew(tlb_addr+address,val); - return false; - } else return get_tlb_writehandler(address)->writew_checked(address,val); - } else return mem_unalignedwritew_checked(address,val); -} - -bool DRC_CALL_CONV mem_writed_checked_drc(PhysPt address,Bit32u val) DRC_FC; -bool DRC_CALL_CONV mem_writed_checked_drc(PhysPt address,Bit32u val) { - if ((address & 0xfff)<0xffd) { - HostPt tlb_addr=get_tlb_write(address); - if (tlb_addr) { - host_writed(tlb_addr+address,val); - return false; - } else return get_tlb_writehandler(address)->writed_checked(address,val); - } else return mem_unalignedwrited_checked(address,val); -} - - -// functions that enable access to the memory - -// read a byte from a given address and store it in reg_dst -static void dyn_read_byte(HostReg reg_addr,HostReg reg_dst) { - gen_mov_regs(FC_OP1,reg_addr); - gen_call_function_raw((void *)&mem_readb_checked_drc); - dyn_check_exception(FC_RETOP); - gen_mov_byte_to_reg_low(reg_dst,&core_dynrec.readdata); -} -static void dyn_read_byte_canuseword(HostReg reg_addr,HostReg reg_dst) { - gen_mov_regs(FC_OP1,reg_addr); - gen_call_function_raw((void *)&mem_readb_checked_drc); - dyn_check_exception(FC_RETOP); - gen_mov_byte_to_reg_low_canuseword(reg_dst,&core_dynrec.readdata); -} - -// write a byte from reg_val into the memory given by the address -static void dyn_write_byte(HostReg reg_addr,HostReg reg_val) { - gen_mov_regs(FC_OP2,reg_val); - gen_mov_regs(FC_OP1,reg_addr); - gen_call_function_raw((void *)&mem_writeb_checked_drc); - dyn_check_exception(FC_RETOP); -} - -// read a 32bit (dword=true) or 16bit (dword=false) value -// from a given address and store it in reg_dst -static void dyn_read_word(HostReg reg_addr,HostReg reg_dst,bool dword) { - gen_mov_regs(FC_OP1,reg_addr); - if (dword) gen_call_function_raw((void *)&mem_readd_checked_drc); - else gen_call_function_raw((void *)&mem_readw_checked_drc); - dyn_check_exception(FC_RETOP); - gen_mov_word_to_reg(reg_dst,&core_dynrec.readdata,dword); -} - -// write a 32bit (dword=true) or 16bit (dword=false) value -// from reg_val into the memory given by the address -static void dyn_write_word(HostReg reg_addr,HostReg reg_val,bool dword) { -// if (!dword) gen_extend_word(false,reg_val); - gen_mov_regs(FC_OP2,reg_val); - gen_mov_regs(FC_OP1,reg_addr); - if (dword) gen_call_function_raw((void *)&mem_writed_checked_drc); - else gen_call_function_raw((void *)&mem_writew_checked_drc); - dyn_check_exception(FC_RETOP); -} - - - -// effective address calculation helper, op2 has to be present! -// loads op1 into ea_reg and adds the scaled op2 and the immediate to it -static void dyn_lea_mem_mem(HostReg ea_reg,void* op1,void* op2,Bitu scale,Bits imm) { - if (scale || imm) { - if (op1!=NULL) { - gen_mov_word_to_reg(ea_reg,op1,true); - gen_mov_word_to_reg(TEMP_REG_DRC,op2,true); - - gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); - } else { - gen_mov_word_to_reg(ea_reg,op2,true); - gen_lea(ea_reg,scale,imm); - } - } else { - gen_mov_word_to_reg(ea_reg,op2,true); - if (op1!=NULL) gen_add(ea_reg,op1); - } -} - -#ifdef DRC_USE_REGS_ADDR -// effective address calculation helper -// loads op1 into ea_reg and adds the scaled op2 and the immediate to it -// op1 is cpu_regs[op1_index], op2 is cpu_regs[op2_index] -static void dyn_lea_regval_regval(HostReg ea_reg,Bitu op1_index,Bitu op2_index,Bitu scale,Bits imm) { - if (scale || imm) { - MOV_REG_VAL_TO_HOST_REG(ea_reg,op1_index); - MOV_REG_VAL_TO_HOST_REG(TEMP_REG_DRC,op2_index); - - gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); - } else { - MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index); - ADD_REG_VAL_TO_HOST_REG(ea_reg,op1_index); - } -} - -// effective address calculation helper -// loads op1 into ea_reg and adds the scaled op2 and the immediate to it -// op2 is cpu_regs[op2_index] -static void dyn_lea_mem_regval(HostReg ea_reg,void* op1,Bitu op2_index,Bitu scale,Bits imm) { - if (scale || imm) { - if (op1!=NULL) { - gen_mov_word_to_reg(ea_reg,op1,true); - MOV_REG_VAL_TO_HOST_REG(TEMP_REG_DRC,op2_index); - - gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); - } else { - MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index); - gen_lea(ea_reg,scale,imm); - } - } else { - MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index); - if (op1!=NULL) gen_add(ea_reg,op1); - } -} -#endif - -#ifdef DRC_USE_SEGS_ADDR -#ifdef DRC_USE_REGS_ADDR -// effective address calculation helper -// loads op1 into ea_reg and adds the scaled op2 and the immediate to it -// op1 is Segs[op1_index], op2 is cpu_regs[op2_index] -static void dyn_lea_segphys_regval(HostReg ea_reg,Bitu op1_index,Bitu op2_index,Bitu scale,Bits imm) { - if (scale || imm) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index); - MOV_REG_VAL_TO_HOST_REG(TEMP_REG_DRC,op2_index); - - gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); - } else { - MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index); - ADD_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index); - } -} - -#else - -// effective address calculation helper, op2 has to be present! -// loads op1 into ea_reg and adds the scaled op2 and the immediate to it -// op1 is Segs[op1_index] -static void dyn_lea_segphys_mem(HostReg ea_reg,Bitu op1_index,void* op2,Bitu scale,Bits imm) { - if (scale || imm) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index); - gen_mov_word_to_reg(TEMP_REG_DRC,op2,true); - - gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); - } else { - gen_mov_word_to_reg(ea_reg,op2,true); - ADD_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index); - } -} -#endif -#endif - -// calculate the effective address and store it in ea_reg -static void dyn_fill_ea(HostReg ea_reg,bool addseg=true) { - Bit8u seg_base=DRC_SEG_DS; - if (!decode.big_addr) { - Bits imm; - switch (decode.modrm.mod) { - case 0:imm=0;break; - case 1:imm=(Bit8s)decode_fetchb();break; - case 2:imm=(Bit16s)decode_fetchw();break; - } - switch (decode.modrm.rm) { - case 0:// BX+SI - DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBX,DRC_REG_ESI,0,imm); - break; - case 1:// BX+DI - DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBX,DRC_REG_EDI,0,imm); - break; - case 2:// BP+SI - DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBP,DRC_REG_ESI,0,imm); - seg_base=DRC_SEG_SS; - break; - case 3:// BP+DI - DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBP,DRC_REG_EDI,0,imm); - seg_base=DRC_SEG_SS; - break; - case 4:// SI - MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_ESI); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - break; - case 5:// DI - MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_EDI); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - break; - case 6:// imm/BP - if (!decode.modrm.mod) { - imm=decode_fetchw(); - gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm); - goto skip_extend_word; - } else { - MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_EBP); - gen_add_imm(ea_reg,(Bit32u)imm); - seg_base=DRC_SEG_SS; - } - break; - case 7: // BX - MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_EBX); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - break; - } - // zero out the high 16bit so ea_reg can be used as full register - gen_extend_word(false,ea_reg); -skip_extend_word: - if (addseg) { - // add the physical segment value if requested - ADD_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - } - } else { - Bits imm=0; - Bit8u base_reg; - Bit8u scaled_reg; - Bitu scale=0; - switch (decode.modrm.rm) { - case 0:base_reg=DRC_REG_EAX;break; - case 1:base_reg=DRC_REG_ECX;break; - case 2:base_reg=DRC_REG_EDX;break; - case 3:base_reg=DRC_REG_EBX;break; - case 4: // SIB - { - Bitu sib=decode_fetchb(); - bool scaled_reg_used=false; - static Bit8u scaledtable[8]={ - DRC_REG_EAX,DRC_REG_ECX,DRC_REG_EDX,DRC_REG_EBX, - 0,DRC_REG_EBP,DRC_REG_ESI,DRC_REG_EDI - }; - // see if scaling should be used and which register is to be scaled in this case - if (((sib >> 3) &7)!=4) scaled_reg_used=true; - scaled_reg=scaledtable[(sib >> 3) &7]; - scale=(sib >> 6); - - switch (sib & 7) { - case 0:base_reg=DRC_REG_EAX;break; - case 1:base_reg=DRC_REG_ECX;break; - case 2:base_reg=DRC_REG_EDX;break; - case 3:base_reg=DRC_REG_EBX;break; - case 4:base_reg=DRC_REG_ESP;seg_base=DRC_SEG_SS;break; - case 5: - if (decode.modrm.mod) { - base_reg=DRC_REG_EBP;seg_base=DRC_SEG_SS; - } else { - // no basereg, maybe scalereg - Bitu val; - // try to get a pointer to the next dword code position - if (decode_fetchd_imm(val)) { - // succeeded, use the pointer to avoid code invalidation - if (!addseg) { - if (!scaled_reg_used) { - gen_mov_word_to_reg(ea_reg,(void*)val,true); - } else { - DYN_LEA_MEM_REG_VAL(ea_reg,NULL,scaled_reg,scale,0); - gen_add(ea_reg,(void*)val); - } - } else { - if (!scaled_reg_used) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - } else { - DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,0); - } - gen_add(ea_reg,(void*)val); - } - return; - } - // couldn't get a pointer, use the current value - imm=(Bit32s)val; - - if (!addseg) { - if (!scaled_reg_used) { - gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm); - } else { - DYN_LEA_MEM_REG_VAL(ea_reg,NULL,scaled_reg,scale,imm); - } - } else { - if (!scaled_reg_used) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - } else { - DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,imm); - } - } - - return; - } - break; - case 6:base_reg=DRC_REG_ESI;break; - case 7:base_reg=DRC_REG_EDI;break; - } - // basereg, maybe scalereg - switch (decode.modrm.mod) { - case 1: - imm=(Bit8s)decode_fetchb(); - break; - case 2: { - Bitu val; - // try to get a pointer to the next dword code position - if (decode_fetchd_imm(val)) { - // succeeded, use the pointer to avoid code invalidation - if (!addseg) { - if (!scaled_reg_used) { - MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - gen_add(ea_reg,(void*)val); - } else { - DYN_LEA_REG_VAL_REG_VAL(ea_reg,base_reg,scaled_reg,scale,0); - gen_add(ea_reg,(void*)val); - } - } else { - if (!scaled_reg_used) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - } else { - DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,0); - } - ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - gen_add(ea_reg,(void*)val); - } - return; - } - // couldn't get a pointer, use the current value - imm=(Bit32s)val; - break; - } - } - - if (!addseg) { - if (!scaled_reg_used) { - MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - gen_add_imm(ea_reg,(Bit32u)imm); - } else { - DYN_LEA_REG_VAL_REG_VAL(ea_reg,base_reg,scaled_reg,scale,imm); - } - } else { - if (!scaled_reg_used) { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - } else { - DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,imm); - ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - } - } - - return; - } - break; // SIB Break - case 5: - if (decode.modrm.mod) { - base_reg=DRC_REG_EBP;seg_base=DRC_SEG_SS; - } else { - // no base, no scalereg - - imm=(Bit32s)decode_fetchd(); - if (!addseg) { - gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm); - } else { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - } - - return; - } - break; - case 6:base_reg=DRC_REG_ESI;break; - case 7:base_reg=DRC_REG_EDI;break; - } - - // no scalereg, but basereg - - switch (decode.modrm.mod) { - case 1: - imm=(Bit8s)decode_fetchb(); - break; - case 2: { - Bitu val; - // try to get a pointer to the next dword code position - if (decode_fetchd_imm(val)) { - // succeeded, use the pointer to avoid code invalidation - if (!addseg) { - MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - gen_add(ea_reg,(void*)val); - } else { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - gen_add(ea_reg,(void*)val); - } - return; - } - // couldn't get a pointer, use the current value - imm=(Bit32s)val; - break; - } - } - - if (!addseg) { - MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - } else { - MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); - ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg); - if (imm) gen_add_imm(ea_reg,(Bit32u)imm); - } - } -} - - - -// add code that checks if port access is allowed -// the port is given in a register -static void dyn_add_iocheck(HostReg reg_port,Bitu access_size) { - if (cpu.pmode) { - gen_call_function_RI((void *)&CPU_IO_Exception,reg_port,access_size); - dyn_check_exception(FC_RETOP); - } -} - -// add code that checks if port access is allowed -// the port is a constant -static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) { - if (cpu.pmode) { - gen_call_function_II((void *)&CPU_IO_Exception,accessed_port,access_size); - dyn_check_exception(FC_RETOP); - } -} - - - -// save back the address register -static void gen_protect_addr_reg(void) { -#ifdef DRC_PROTECT_ADDR_REG - gen_mov_word_from_reg(FC_ADDR,&core_dynrec.protected_regs[FC_ADDR],true); -#endif -} - -// restore the address register -static void gen_restore_addr_reg(void) { -#ifdef DRC_PROTECT_ADDR_REG - gen_mov_word_to_reg(FC_ADDR,&core_dynrec.protected_regs[FC_ADDR],true); -#endif -} - -// save back an arbitrary register -static void gen_protect_reg(HostReg reg) { - gen_mov_word_from_reg(reg,&core_dynrec.protected_regs[reg],true); -} - -// restore an arbitrary register -static void gen_restore_reg(HostReg reg) { - gen_mov_word_to_reg(reg,&core_dynrec.protected_regs[reg],true); -} - -// restore an arbitrary register into a different register -static void gen_restore_reg(HostReg reg,HostReg dest_reg) { - gen_mov_word_to_reg(dest_reg,&core_dynrec.protected_regs[reg],true); -} - - - -// flags optimization functions -// they try to find out if a function can be replaced by another -// one that does not generate any flags at all - -static Bitu mf_functions_num=0; -static struct { - Bit8u* pos; - void* fct_ptr; - Bitu ftype; -} mf_functions[64]; - -static void InitFlagsOptimization(void) { - mf_functions_num=0; -} - -// replace all queued functions with their simpler variants -// because the current instruction destroys all condition flags and -// the flags are not required before -static void InvalidateFlags(void) { -#ifdef DRC_FLAGS_INVALIDATION - for (Bitu ct=0; ct>2)&1); - dyn_dop_byte_gencall(op); - - if ((op!=DOP_CMP) && (op!=DOP_TEST)) { - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_RETOP); - } - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - dyn_dop_byte_gencall(op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_dop_ebgb_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - dyn_write_byte(FC_ADDR,FC_TMP_BA1); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_dop_ebib_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,decode_fetchb()); - dyn_write_byte(FC_ADDR,FC_TMP_BA1); - } else { - gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,decode_fetchb()); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_dop_ebgb_xchg(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_byte(FC_ADDR,FC_TMP_BA1); - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_TMP_BA2); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_dop_gbeb(DualOps op) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_byte_canuseword(FC_ADDR,FC_OP2); - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - dyn_dop_byte_gencall(op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - dyn_dop_byte_gencall(op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - } -} - -static void dyn_dop_gbeb_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_byte(FC_ADDR,FC_TMP_BA1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1); - } -} - -static void dyn_dop_evgv(DualOps op) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - gen_protect_addr_reg(); - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } -} - -static void dyn_dop_evgv_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } -} - -static void dyn_dop_eviv_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,decode_fetchd()); - else gen_mov_word_to_reg_imm(FC_OP1,decode_fetchw()); - dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,decode_fetchd()); - else gen_mov_word_to_reg_imm(FC_OP1,decode_fetchw()); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } -} - -static void dyn_dop_evgv_xchg(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - - gen_protect_reg(FC_OP1); - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_OP2,decode.big_op); - gen_restore_reg(FC_OP1); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP2,decode.modrm.rm,decode.big_op); - } -} - -static void dyn_xchg_ax(Bit8u reg) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP2,reg,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,reg,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP2,DRC_REG_EAX,decode.big_op); -} - -static void dyn_dop_gvev(DualOps op) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP2,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) { - gen_restore_addr_reg(); - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op); - } - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.rm,decode.big_op); - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op); - } -} - -static void dyn_dop_gvev_mov(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } -} - -static void dyn_dop_byte_imm(DualOps op,Bit8u reg,Bit8u idx) { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,reg,idx); - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); - dyn_dop_byte_gencall(op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,reg,idx); -} - -static void dyn_dop_byte_imm_mem(DualOps op,Bit8u reg,Bit8u idx) { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,reg,idx); - Bitu val; - if (decode_fetchb_imm(val)) { - gen_mov_byte_to_reg_low_canuseword(FC_OP2,(void*)val); - } else { - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,(Bit8u)val); - } - dyn_dop_byte_gencall(op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,reg,idx); -} - -static void dyn_prep_word_imm(Bit8u reg) { - Bitu val; - if (decode.big_op) { - if (decode_fetchd_imm(val)) { - gen_mov_word_to_reg(FC_OP2,(void*)val,true); - return; - } - } else { - if (decode_fetchw_imm(val)) { - gen_mov_word_to_reg(FC_OP2,(void*)val,false); - return; - } - } - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)val); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)val); -} - -static void dyn_dop_word_imm(DualOps op,Bit8u reg) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); - dyn_prep_word_imm(reg); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); -} - -static void dyn_dop_word_imm_old(DualOps op,Bit8u reg,Bitu imm) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)imm); - dyn_dop_word_gencall(op,decode.big_op); - if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); -} - -static void dyn_mov_byte_imm(Bit8u reg,Bit8u idx,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,imm); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,reg,idx); -} - -static void dyn_mov_word_imm(Bit8u reg) { - Bitu val; - if (decode.big_op) { - if (decode_fetchd_imm(val)) { - gen_mov_word_to_reg(FC_OP1,(void*)val,true); - MOV_REG_WORD32_FROM_HOST_REG(FC_OP1,reg); - return; - } - } else { - if (decode_fetchw_imm(val)) { - gen_mov_word_to_reg(FC_OP1,(void*)val,false); - MOV_REG_WORD16_FROM_HOST_REG(FC_OP1,reg); - return; - } - } - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)val); - else gen_mov_word_to_reg_imm(FC_OP1,(Bit16u)val); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,reg,decode.big_op); -} - - -static void dyn_sop_word(SingleOps op,Bit8u reg) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); - dyn_sop_word_gencall(op,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); -} - - -static void dyn_mov_byte_al_direct(Bitu imm) { - MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); - gen_add_imm(FC_ADDR,imm); - dyn_read_byte(FC_ADDR,FC_TMP_BA1); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,DRC_REG_EAX,0); -} - -static void dyn_mov_byte_ax_direct(Bitu imm) { - MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); - gen_add_imm(FC_ADDR,imm); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); -} - -static void dyn_mov_byte_direct_al() { - MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); - if (decode.big_addr) { - Bitu val; - if (decode_fetchd_imm(val)) { - gen_add(FC_ADDR,(void*)val); - } else { - gen_add_imm(FC_ADDR,(Bit32u)val); - } - } else { - gen_add_imm(FC_ADDR,decode_fetchw()); - } - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,DRC_REG_EAX,0); - dyn_write_byte(FC_ADDR,FC_TMP_BA1); -} - -static void dyn_mov_byte_direct_ax(Bitu imm) { - MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); - gen_add_imm(FC_ADDR,imm); - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); - dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); -} - - -static void dyn_movx_ev_gb(bool sign) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_byte(FC_ADDR,FC_TMP_BA1); - gen_extend_byte(sign,FC_TMP_BA1); - MOV_REG_WORD_FROM_HOST_REG(FC_TMP_BA1,decode.modrm.reg,decode.big_op); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - gen_extend_byte(sign,FC_TMP_BA1); - MOV_REG_WORD_FROM_HOST_REG(FC_TMP_BA1,decode.modrm.reg,decode.big_op); - } -} - -static void dyn_movx_ev_gw(bool sign) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_OP1,false); - gen_extend_word(sign,FC_OP1); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } else { - MOV_REG_WORD16_TO_HOST_REG(FC_OP1,decode.modrm.rm); - gen_extend_word(sign,FC_OP1); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } -} - - -static void dyn_mov_ev_seg(void) { - dyn_get_modrm(); - MOV_SEG_VAL_TO_HOST_REG(FC_OP1,decode.modrm.reg); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_write_word(FC_ADDR,FC_OP1,false); - } else { - if (decode.big_op) gen_extend_word(false,FC_OP1); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } -} - - -static void dyn_lea(void) { - dyn_get_modrm(); - dyn_fill_ea(FC_ADDR,false); - MOV_REG_WORD_FROM_HOST_REG(FC_ADDR,decode.modrm.reg,decode.big_op); -} - - -static void dyn_push_seg(Bit8u seg) { - MOV_SEG_VAL_TO_HOST_REG(FC_OP1,seg); - if (decode.big_op) { - gen_extend_word(false,FC_OP1); - gen_call_function_raw((void*)&dynrec_push_dword); - } else { - gen_call_function_raw((void*)&dynrec_push_word); - } -} - -static void dyn_pop_seg(Bit8u seg) { - gen_call_function_II((void *)&CPU_PopSeg,seg,decode.big_op); - dyn_check_exception(FC_RETOP); -} - -static void dyn_push_reg(Bit8u reg) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); - if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); - else gen_call_function_raw((void*)&dynrec_push_word); -} - -static void dyn_pop_reg(Bit8u reg) { - if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); - else gen_call_function_raw((void*)&dynrec_pop_word); - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); -} - -static void dyn_push_byte_imm(Bit8s imm) { - gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)imm); - if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); - else gen_call_function_raw((void*)&dynrec_push_word); -} - -static void dyn_push_word_imm(Bitu imm) { - if (decode.big_op) { - gen_mov_dword_to_reg_imm(FC_OP1,imm); - gen_call_function_raw((void*)&dynrec_push_dword); - } else { - gen_mov_word_to_reg_imm(FC_OP1,(Bit16u)imm); - gen_call_function_raw((void*)&dynrec_push_word); - } -} - -static void dyn_pop_ev(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { -/* dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); // dummy read to trigger possible page faults */ - if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); - else gen_call_function_raw((void*)&dynrec_pop_word); - dyn_fill_ea(FC_ADDR); -// gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } else { - if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); - else gen_call_function_raw((void*)&dynrec_pop_word); - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } -} - - -static void dyn_segprefix(Bit8u seg) { -// if (GCC_UNLIKELY(decode.seg_prefix_used)) IllegalOptionDynrec("dyn_segprefix"); - decode.seg_prefix=seg; - decode.seg_prefix_used=true; -} - - static void dyn_mov_seg_ev(void) { - dyn_get_modrm(); - if (GCC_UNLIKELY(decode.modrm.reg==DRC_SEG_CS)) IllegalOptionDynrec("dyn_mov_seg_ev"); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_RETOP,false); - } else { - MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); - } - gen_call_function_IR((void *)&CPU_SetSegGeneral,decode.modrm.reg,FC_RETOP); - dyn_check_exception(FC_RETOP); -} - -static void dyn_load_seg_off_ea(Bit8u seg) { - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - gen_protect_reg(FC_OP1); - - gen_restore_addr_reg(); - gen_add_imm(FC_ADDR,decode.big_op ? 4:2); - dyn_read_word(FC_ADDR,FC_RETOP,false); - - gen_call_function_IR((void *)&CPU_SetSegGeneral,seg,FC_RETOP); - dyn_check_exception(FC_RETOP); - - gen_restore_reg(FC_OP1); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); - } else { - IllegalOptionDynrec("dyn_load_seg_off_ea"); - } -} - - - -static void dyn_imul_gvev(Bitu immsize) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } - - switch (immsize) { - case 0: - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - break; - case 1: - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit8s)decode_fetchb()); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit8s)decode_fetchb()); - break; - case 2: - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit16s)decode_fetchw()); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit16s)decode_fetchw()); - break; - case 4: - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32s)decode_fetchd()); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)((Bit32s)decode_fetchd())); - break; - } - - if (decode.big_op) gen_call_function_raw((void*)dynrec_dimul_dword); - else gen_call_function_raw((void*)dynrec_dimul_word); - - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op); -} - -static void dyn_dshift_ev_gv(bool left,bool immediate) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } - MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - if (immediate) gen_mov_byte_to_reg_low_imm(FC_RETOP,decode_fetchb()); - else MOV_REG_BYTE_TO_HOST_REG_LOW(FC_RETOP,DRC_REG_ECX,0); - if (decode.big_op) dyn_dpshift_dword_gencall(left); - else dyn_dpshift_word_gencall(left); - - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } else { - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } -} - - -static void dyn_grp1_eb_ib(void) { - dyn_get_modrm(); - DualOps op=grp1_table[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_byte_canuseword(FC_ADDR,FC_OP1); - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); - dyn_dop_byte_gencall(op); - - if ((op!=DOP_CMP) && (op!=DOP_TEST)) { - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_RETOP); - } - } else { - dyn_dop_byte_imm_mem(op,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_grp1_ev_iv(bool withbyte) { - dyn_get_modrm(); - DualOps op=grp1_table[decode.modrm.reg]; - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - - if (!withbyte) { - dyn_prep_word_imm(FC_OP2); - } else { - Bits imm=(Bit8s)decode_fetchb(); - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm); - else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)imm); - } - - dyn_dop_word_gencall(op,decode.big_op); - - if ((op!=DOP_CMP) && (op!=DOP_TEST)) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } - } else { - if (!withbyte) { - dyn_dop_word_imm(op,decode.modrm.rm); - } else { - Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw()); - dyn_dop_word_imm_old(op,decode.modrm.rm,imm); - } - } -} - - -static void dyn_grp2_eb(grp2_types type) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_byte_canuseword(FC_ADDR,FC_OP1); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } - switch (type) { - case grp2_1: - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,1); - dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); - break; - case grp2_imm: { - Bit8u imm=decode_fetchb(); - if (imm) { - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,imm&0x1f); - dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); - } else return; - } - break; - case grp2_cl: - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,DRC_REG_ECX,0); - gen_and_imm(FC_OP2,0x1f); - dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); - break; - } - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_RETOP); - } else { - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_grp2_ev(grp2_types type) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } - switch (type) { - case grp2_1: - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,1); - dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); - break; - case grp2_imm: { - Bitu val; - if (decode_fetchb_imm(val)) { - gen_mov_byte_to_reg_low_canuseword(FC_OP2,(void*)val); - gen_and_imm(FC_OP2,0x1f); - dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); - break; - } - Bit8u imm=(Bit8u)val; - if (imm) { - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,imm&0x1f); - dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); - } else return; - } - break; - case grp2_cl: - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,DRC_REG_ECX,0); - gen_and_imm(FC_OP2,0x1f); - dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); - break; - } - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } else { - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } -} - - -static void dyn_grp3_eb(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - if ((decode.modrm.reg==2) || (decode.modrm.reg==3)) gen_protect_addr_reg(); - dyn_read_byte_canuseword(FC_ADDR,FC_OP1); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } - switch (decode.modrm.reg) { - case 0x0: // test eb,ib - gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); - dyn_dop_byte_gencall(DOP_TEST); - return; - case 0x2: // NOT Eb - dyn_sop_byte_gencall(SOP_NOT); - break; - case 0x3: // NEG Eb - dyn_sop_byte_gencall(SOP_NEG); - break; - case 0x4: // mul Eb - gen_call_function_raw((void*)&dynrec_mul_byte); - return; - case 0x5: // imul Eb - gen_call_function_raw((void*)&dynrec_imul_byte); - return; - case 0x6: // div Eb - gen_call_function_raw((void*)&dynrec_div_byte); - dyn_check_exception(FC_RETOP); - return; - case 0x7: // idiv Eb - gen_call_function_raw((void*)&dynrec_idiv_byte); - dyn_check_exception(FC_RETOP); - return; - } - // Save the result if memory op - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_RETOP); - } else { - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} - -static void dyn_grp3_ev(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - if ((decode.modrm.reg==2) || (decode.modrm.reg==3)) gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } - switch (decode.modrm.reg) { - case 0x0: // test ev,iv - if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,decode_fetchd()); - else gen_mov_word_to_reg_imm(FC_OP2,decode_fetchw()); - dyn_dop_word_gencall(DOP_TEST,decode.big_op); - return; - case 0x2: // NOT Ev - dyn_sop_word_gencall(SOP_NOT,decode.big_op); - break; - case 0x3: // NEG Eb - dyn_sop_word_gencall(SOP_NEG,decode.big_op); - break; - case 0x4: // mul Eb - if (decode.big_op) gen_call_function_raw((void*)&dynrec_mul_dword); - else gen_call_function_raw((void*)&dynrec_mul_word); - return; - case 0x5: // imul Eb - if (decode.big_op) gen_call_function_raw((void*)&dynrec_imul_dword); - else gen_call_function_raw((void*)&dynrec_imul_word); - return; - case 0x6: // div Eb - if (decode.big_op) gen_call_function_raw((void*)&dynrec_div_dword); - else gen_call_function_raw((void*)&dynrec_div_word); - dyn_check_exception(FC_RETOP); - return; - case 0x7: // idiv Eb - if (decode.big_op) gen_call_function_raw((void*)&dynrec_idiv_dword); - else gen_call_function_raw((void*)&dynrec_idiv_word); - dyn_check_exception(FC_RETOP); - return; - } - // Save the result if memory op - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } else { - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } -} - - -static bool dyn_grp4_eb(void) { - dyn_get_modrm(); - switch (decode.modrm.reg) { - case 0x0://INC Eb - case 0x1://DEC Eb - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_byte_canuseword(FC_ADDR,FC_OP1); - dyn_sop_byte_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC); - gen_restore_addr_reg(); - dyn_write_byte(FC_ADDR,FC_RETOP); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - dyn_sop_byte_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC); - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } - break; - case 0x7: //CALBACK Iw - gen_mov_direct_dword(&core_dynrec.callback,decode_fetchw()); - dyn_set_eip_end(); - dyn_reduce_cycles(); - dyn_return(BR_CallBack); - dyn_closeblock(); - return true; - default: - IllegalOptionDynrec("dyn_grp4_eb"); - break; - } - return false; -} - -static bool dyn_grp4_ev(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - if ((decode.modrm.reg<2) || (decode.modrm.reg==3) || (decode.modrm.reg==5)) gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); - } else { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); - } - switch (decode.modrm.reg) { - case 0x0://INC Ev - case 0x1://DEC Ev - dyn_sop_word_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,decode.big_op); - if (decode.modrm.mod<3) { - gen_restore_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); - } else { - MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); - } - break; - case 0x2: // CALL Ev - gen_mov_regs(FC_ADDR,FC_OP1); - gen_protect_addr_reg(); - gen_mov_word_to_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); - gen_add_imm(FC_OP1,(Bit32u)(decode.code-decode.code_start)); - if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); - else gen_call_function_raw((void*)&dynrec_push_word); - - gen_restore_addr_reg(); - gen_mov_word_from_reg(FC_ADDR,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); - return true; - case 0x4: // JMP Ev - gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); - return true; - case 0x3: // CALL Ep - case 0x5: // JMP Ep - if (!decode.big_op) gen_extend_word(false,FC_OP1); - if (decode.modrm.mod<3) gen_restore_addr_reg(); - gen_protect_reg(FC_OP1); - gen_add_imm(FC_ADDR,decode.big_op?4:2); - dyn_read_word(FC_ADDR,FC_OP2,decode.big_op); - gen_extend_word(false,FC_OP2); - - dyn_set_eip_last_end(FC_RETOP); - gen_restore_reg(FC_OP1,FC_ADDR); - gen_call_function_IRRR(decode.modrm.reg == 3 ? (void*)(&CPU_CALL) : (void*)(&CPU_JMP), - decode.big_op,FC_OP2,FC_ADDR,FC_RETOP); - return true; - case 0x6: // PUSH Ev - if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); - else gen_call_function_raw((void*)&dynrec_push_word); - break; - default: - IllegalOptionDynrec("dyn_grp4_ev"); - } - return false; -} - - -static bool dyn_grp6(void) { - dyn_get_modrm(); - switch (decode.modrm.reg) { - case 0x00: // SLDT - case 0x01: // STR - if (decode.modrm.reg==0) gen_call_function_raw((void*)CPU_SLDT); - else gen_call_function_raw((void*)CPU_STR); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_write_word(FC_ADDR,FC_RETOP,false); - } else { - MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,decode.modrm.rm); - } - break; - case 0x02: // LLDT - case 0x03: // LTR - case 0x04: // VERR - case 0x05: // VERW - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_RETOP,false); - } else { - MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); - } - gen_extend_word(false,FC_RETOP); - switch (decode.modrm.reg) { - case 0x02: // LLDT -// if (cpu.cpl) return CPU_PrepareException(EXCEPTION_GP,0); - if (cpu.cpl) E_Exit("lldt cpl>0"); - gen_call_function_R((void*)CPU_LLDT,FC_RETOP); - dyn_check_exception(FC_RETOP); - break; - case 0x03: // LTR -// if (cpu.cpl) return CPU_PrepareException(EXCEPTION_GP,0); - if (cpu.cpl) E_Exit("ltr cpl>0"); - gen_call_function_R((void*)CPU_LTR,FC_RETOP); - dyn_check_exception(FC_RETOP); - break; - case 0x04: // VERR - gen_call_function_R((void*)CPU_VERR,FC_RETOP); - break; - case 0x05: // VERW - gen_call_function_R((void*)CPU_VERW,FC_RETOP); - break; - } - break; - default: IllegalOptionDynrec("dyn_grp6"); - } - return false; -} - -static bool dyn_grp7(void) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - switch (decode.modrm.reg) { - case 0x00: // SGDT - gen_call_function_raw((void*)CPU_SGDT_limit); - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,false); - gen_call_function_raw((void*)CPU_SGDT_base); - gen_restore_addr_reg(); - gen_add_imm(FC_ADDR,2); - dyn_write_word(FC_ADDR,FC_RETOP,true); - break; - case 0x01: // SIDT - gen_call_function_raw((void*)CPU_SIDT_limit); - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_write_word(FC_ADDR,FC_RETOP,false); - gen_call_function_raw((void*)CPU_SIDT_base); - gen_restore_addr_reg(); - gen_add_imm(FC_ADDR,2); - dyn_write_word(FC_ADDR,FC_RETOP,true); - break; - case 0x02: // LGDT - case 0x03: // LIDT -// if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - if (cpu.pmode && cpu.cpl) IllegalOptionDynrec("lgdt nonpriviledged"); - dyn_fill_ea(FC_ADDR); - gen_protect_addr_reg(); - dyn_read_word(FC_ADDR,FC_OP1,false); - gen_extend_word(false,FC_OP1); - gen_protect_reg(FC_OP1); - - gen_restore_addr_reg(); - gen_add_imm(FC_ADDR,2); - dyn_read_word(FC_ADDR,FC_OP2,true); - if (!decode.big_op) gen_and_imm(FC_OP2,0xffffff); - - gen_restore_reg(FC_OP1); - if (decode.modrm.reg==2) gen_call_function_RR((void*)CPU_LGDT,FC_OP1,FC_OP2); - else gen_call_function_RR((void*)CPU_LIDT,FC_OP1,FC_OP2); - break; - case 0x04: // SMSW - gen_call_function_raw((void*)CPU_SMSW); - dyn_fill_ea(FC_ADDR); - dyn_write_word(FC_ADDR,FC_RETOP,false); - break; - case 0x06: // LMSW - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_RETOP,false); - gen_call_function_R((void*)CPU_LMSW,FC_RETOP); - dyn_check_exception(FC_RETOP); - dyn_set_eip_end(); - dyn_reduce_cycles(); - dyn_return(BR_Normal); - dyn_closeblock(); - return true; - case 0x07: // INVLPG -// if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - if (cpu.pmode && cpu.cpl) IllegalOptionDynrec("invlpg nonpriviledged"); - gen_call_function_raw((void*)PAGING_ClearTLB); - break; - default: IllegalOptionDynrec("dyn_grp7_1"); - } - } else { - switch (decode.modrm.reg) { - case 0x04: // SMSW - gen_call_function_raw((void*)CPU_SMSW); - MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,decode.modrm.rm); - break; - case 0x06: // LMSW - MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); - gen_call_function_R((void*)CPU_LMSW,FC_RETOP); - dyn_check_exception(FC_RETOP); - dyn_set_eip_end(); - dyn_reduce_cycles(); - dyn_return(BR_Normal); - dyn_closeblock(); - return true; - default: IllegalOptionDynrec("dyn_grp7_2"); - } - } - return false; -} - - -/* -static void dyn_larlsl(bool is_lar) { - dyn_get_modrm(); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_read_word(FC_ADDR,FC_RETOP,false); - } else { - MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); - } - gen_extend_word(false,FC_RETOP); - if (is_lar) gen_call_function((void*)CPU_LAR,"%R%A",FC_RETOP,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); - else gen_call_function((void*)CPU_LSL,"%R%A",FC_RETOP,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); - DRC_PTR_SIZE_IM brnz=gen_create_branch_on_nonzero(FC_RETOP,true); - gen_mov_word_to_reg(FC_OP2,&core_dynrec.readdata,true); - MOV_REG_WORD_FROM_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); - gen_fill_branch(brnz); -} -*/ - - -static void dyn_mov_from_crx(void) { - dyn_get_modrm(); - gen_call_function_IA((void*)CPU_READ_CRX,decode.modrm.reg,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); - dyn_check_exception(FC_RETOP); - gen_mov_word_to_reg(FC_OP2,&core_dynrec.readdata,true); - MOV_REG_WORD32_FROM_HOST_REG(FC_OP2,decode.modrm.rm); -} - -static void dyn_mov_to_crx(void) { - dyn_get_modrm(); - MOV_REG_WORD32_TO_HOST_REG(FC_RETOP,decode.modrm.rm); - gen_call_function_IR((void*)CPU_WRITE_CRX,decode.modrm.reg,FC_RETOP); - dyn_check_exception(FC_RETOP); - dyn_set_eip_end(); - dyn_reduce_cycles(); - dyn_return(BR_Normal); - dyn_closeblock(); -} - - -static void dyn_cbw(void) { - if (decode.big_op) { - MOV_REG_WORD16_TO_HOST_REG(FC_OP1,DRC_REG_EAX); - gen_call_function_raw((void *)&dynrec_cwde); - MOV_REG_WORD32_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX); - } else { - MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,DRC_REG_EAX,0); - gen_call_function_raw((void *)&dynrec_cbw); - MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX); - } -} - -static void dyn_cwd(void) { - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); - if (decode.big_op) { - gen_call_function_raw((void *)&dynrec_cdq); - MOV_REG_WORD32_FROM_HOST_REG(FC_RETOP,DRC_REG_EDX); - } else { - gen_call_function_raw((void *)&dynrec_cwd); - MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,DRC_REG_EDX); - } -} - -static void dyn_sahf(void) { - MOV_REG_WORD16_TO_HOST_REG(FC_OP1,DRC_REG_EAX); - gen_call_function_raw((void *)&dynrec_sahf); - InvalidateFlags(); -} - - -static void dyn_exit_link(Bits eip_change) { - gen_add_direct_word(®_eip,(decode.code-decode.code_start)+eip_change,decode.big_op); - dyn_reduce_cycles(); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); - dyn_closeblock(); -} - - -static void dyn_branched_exit(BranchTypes btype,Bit32s eip_add) { - Bitu eip_base=decode.code-decode.code_start; - dyn_reduce_cycles(); - - dyn_branchflag_to_reg(btype); - DRC_PTR_SIZE_IM data=gen_create_branch_on_nonzero(FC_RETOP,true); - - // Branch not taken - gen_add_direct_word(®_eip,eip_base,decode.big_op); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); - gen_fill_branch(data); - - // Branch taken - gen_add_direct_word(®_eip,eip_base+eip_add,decode.big_op); - gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlockDynRec,cache.start)); - dyn_closeblock(); -} - -/* -static void dyn_set_byte_on_condition(BranchTypes btype) { - dyn_get_modrm(); - dyn_branchflag_to_reg(btype); - gen_and_imm(FC_RETOP,1); - if (decode.modrm.mod<3) { - dyn_fill_ea(FC_ADDR); - dyn_write_byte(FC_ADDR,FC_RETOP); - } else { - MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); - } -} -*/ - -static void dyn_loop(LoopTypes type) { - dyn_reduce_cycles(); - Bits eip_add=(Bit8s)decode_fetchb(); - Bitu eip_base=decode.code-decode.code_start; - DRC_PTR_SIZE_IM branch1=0; - DRC_PTR_SIZE_IM branch2=0; - switch (type) { - case LOOP_E: - dyn_branchflag_to_reg(BR_NZ); - branch1=gen_create_branch_on_nonzero(FC_RETOP,true); - break; - case LOOP_NE: - dyn_branchflag_to_reg(BR_Z); - branch1=gen_create_branch_on_nonzero(FC_RETOP,true); - break; - } - switch (type) { - case LOOP_E: - case LOOP_NE: - case LOOP_NONE: - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - gen_add_imm(FC_OP1,(Bit32u)(-1)); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - branch2=gen_create_branch_on_zero(FC_OP1,decode.big_addr); - break; - case LOOP_JCXZ: - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - branch2=gen_create_branch_on_nonzero(FC_OP1,decode.big_addr); - break; - } - gen_add_direct_word(®_eip,eip_base+eip_add,true); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); - if (branch1) { - gen_fill_branch(branch1); - MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - gen_add_imm(FC_OP1,(Bit32u)(-1)); - MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - } - // Branch taken - gen_fill_branch(branch2); - gen_add_direct_word(®_eip,eip_base,decode.big_op); - gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlockDynRec,cache.start)); - dyn_closeblock(); -} - - -static void dyn_ret_near(Bitu bytes) { - dyn_reduce_cycles(); - - if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); - else { - gen_call_function_raw((void*)&dynrec_pop_word); - gen_extend_word(false,FC_RETOP); - } - gen_mov_word_from_reg(FC_RETOP,decode.big_op?(void*)(®_eip):(void*)(®_ip),true); - - if (bytes) gen_add_direct_word(®_esp,bytes,true); - dyn_return(BR_Normal); - dyn_closeblock(); -} - -static void dyn_call_near_imm(void) { - Bits imm; - if (decode.big_op) imm=(Bit32s)decode_fetchd(); - else imm=(Bit16s)decode_fetchw(); - dyn_set_eip_end(FC_OP1); - if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); - else gen_call_function_raw((void*)&dynrec_push_word); - - dyn_set_eip_end(FC_OP1,imm); - gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); - - dyn_reduce_cycles(); - gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); - dyn_closeblock(); -} - -static void dyn_ret_far(Bitu bytes) { - dyn_reduce_cycles(); - dyn_set_eip_last_end(FC_RETOP); - gen_call_function_IIR((void*)&CPU_RET,decode.big_op,bytes,FC_RETOP); - dyn_return(BR_Normal); - dyn_closeblock(); -} - -static void dyn_call_far_imm(void) { - Bitu sel,off; - off=decode.big_op ? decode_fetchd() : decode_fetchw(); - sel=decode_fetchw(); - dyn_reduce_cycles(); - dyn_set_eip_last_end(FC_RETOP); - gen_call_function_IIIR((void*)&CPU_CALL,decode.big_op,sel,off,FC_RETOP); - dyn_return(BR_Normal); - dyn_closeblock(); -} - -static void dyn_jmp_far_imm(void) { - Bitu sel,off; - off=decode.big_op ? decode_fetchd() : decode_fetchw(); - sel=decode_fetchw(); - dyn_reduce_cycles(); - dyn_set_eip_last_end(FC_RETOP); - gen_call_function_IIIR((void*)&CPU_JMP,decode.big_op,sel,off,FC_RETOP); - dyn_return(BR_Normal); - dyn_closeblock(); -} - -static void dyn_iret(void) { - dyn_reduce_cycles(); - dyn_set_eip_last_end(FC_RETOP); - gen_call_function_IR((void*)&CPU_IRET,decode.big_op,FC_RETOP); - dyn_return(BR_Iret); - dyn_closeblock(); -} - -static void dyn_interrupt(Bit8u num) { - dyn_reduce_cycles(); - dyn_set_eip_last_end(FC_RETOP); - gen_call_function_IIR((void*)&CPU_Interrupt,num,CPU_INT_SOFTWARE,FC_RETOP); - dyn_return(BR_Normal); - dyn_closeblock(); -} - - - -static void dyn_string(StringOps op) { - if (decode.rep) MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); - else gen_mov_dword_to_reg_imm(FC_OP1,1); - gen_mov_word_to_reg(FC_OP2,&cpu.direction,true); - Bit8u di_base_addr=decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS; - switch (op) { - case STR_MOVSB: - if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsb_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_mm((void*)&dynrec_movsb_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - case STR_MOVSW: - if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsw_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_mm((void*)&dynrec_movsw_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - case STR_MOVSD: - if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsd_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_mm((void*)&dynrec_movsd_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - - case STR_LODSB: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsb_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - else gen_call_function_m((void*)&dynrec_lodsb_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - break; - case STR_LODSW: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsw_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - else gen_call_function_m((void*)&dynrec_lodsw_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - break; - case STR_LODSD: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsd_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - else gen_call_function_m((void*)&dynrec_lodsd_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); - break; - - case STR_STOSB: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosb_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_m((void*)&dynrec_stosb_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - case STR_STOSW: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosw_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_m((void*)&dynrec_stosw_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - case STR_STOSD: - if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosd_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - else gen_call_function_m((void*)&dynrec_stosd_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); - break; - default: IllegalOptionDynrec("dyn_string"); - } - if (decode.rep) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,DRC_REG_ECX,decode.big_addr); - - if (op -#include -#include "cross.h" -#include "mem.h" -#include "fpu.h" -#include "cpu.h" - - -static void FPU_FDECSTP(){ - TOP = (TOP - 1) & 7; -} - -static void FPU_FINCSTP(){ - TOP = (TOP + 1) & 7; -} - -static void FPU_FNSTCW(PhysPt addr){ - mem_writew(addr,fpu.cw); -} - -static void FPU_FFREE(Bitu st) { - fpu.tags[st]=TAG_Empty; -} - - -#if C_FPU_X86 -#include "../../fpu/fpu_instructions_x86.h" -#else -#include "../../fpu/fpu_instructions.h" -#endif - - -static INLINE void dyn_fpu_top() { - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_add_imm(FC_OP2,decode.modrm.rm); - gen_and_imm(FC_OP2,7); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); -} - -static INLINE void dyn_fpu_top_swapped() { - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_add_imm(FC_OP1,decode.modrm.rm); - gen_and_imm(FC_OP1,7); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); -} - -static void dyn_eatree() { - Bitu group=(decode.modrm.val >> 3) & 7; - switch (group){ - case 0x00: // FADD ST,STi - gen_call_function_R((void*)&FPU_FADD_EA,FC_OP1); - break; - case 0x01: // FMUL ST,STi - gen_call_function_R((void*)&FPU_FMUL_EA,FC_OP1); - break; - case 0x02: // FCOM STi - gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1); - break; - case 0x03: // FCOMP STi - gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: // FSUB ST,STi - gen_call_function_R((void*)&FPU_FSUB_EA,FC_OP1); - break; - case 0x05: // FSUBR ST,STi - gen_call_function_R((void*)&FPU_FSUBR_EA,FC_OP1); - break; - case 0x06: // FDIV ST,STi - gen_call_function_R((void*)&FPU_FDIV_EA,FC_OP1); - break; - case 0x07: // FDIVR ST,STi - gen_call_function_R((void*)&FPU_FDIVR_EA,FC_OP1); - break; - default: - break; - } -} - -static void dyn_fpu_esc0(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - dyn_fpu_top(); - switch (decode.modrm.reg){ - case 0x00: //FADD ST,STi - gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); - break; - case 0x01: // FMUL ST,STi - gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); - break; - case 0x02: // FCOM STi - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - break; - case 0x03: // FCOMP STi - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: // FSUB ST,STi - gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); - break; - case 0x05: // FSUBR ST,STi - gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); - break; - case 0x06: // FDIV ST,STi - gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); - break; - case 0x07: // FDIVR ST,STi - gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); - break; - default: - break; - } - } else { - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLD_F32_EA,FC_ADDR); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - dyn_eatree(); - } -} - - -static void dyn_fpu_esc1(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch (decode.modrm.reg){ - case 0x00: /* FLD STi */ - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_add_imm(FC_OP1,decode.modrm.rm); - gen_and_imm(FC_OP1,7); - gen_protect_reg(FC_OP1); - gen_call_function_raw((void*)&FPU_PREP_PUSH); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_restore_reg(FC_OP1); - gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); - break; - case 0x01: /* FXCH STi */ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); - break; - case 0x02: /* FNOP */ - gen_call_function_raw((void*)&FPU_FNOP); - break; - case 0x03: /* FSTP STi */ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: - switch(decode.modrm.rm){ - case 0x00: /* FCHS */ - gen_call_function_raw((void*)&FPU_FCHS); - break; - case 0x01: /* FABS */ - gen_call_function_raw((void*)&FPU_FABS); - break; - case 0x02: /* UNKNOWN */ - case 0x03: /* ILLEGAL */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - case 0x04: /* FTST */ - gen_call_function_raw((void*)&FPU_FTST); - break; - case 0x05: /* FXAM */ - gen_call_function_raw((void*)&FPU_FXAM); - break; - case 0x06: /* FTSTP (cyrix)*/ - case 0x07: /* UNKNOWN */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - case 0x05: - switch(decode.modrm.rm){ - case 0x00: /* FLD1 */ - gen_call_function_raw((void*)&FPU_FLD1); - break; - case 0x01: /* FLDL2T */ - gen_call_function_raw((void*)&FPU_FLDL2T); - break; - case 0x02: /* FLDL2E */ - gen_call_function_raw((void*)&FPU_FLDL2E); - break; - case 0x03: /* FLDPI */ - gen_call_function_raw((void*)&FPU_FLDPI); - break; - case 0x04: /* FLDLG2 */ - gen_call_function_raw((void*)&FPU_FLDLG2); - break; - case 0x05: /* FLDLN2 */ - gen_call_function_raw((void*)&FPU_FLDLN2); - break; - case 0x06: /* FLDZ*/ - gen_call_function_raw((void*)&FPU_FLDZ); - break; - case 0x07: /* ILLEGAL */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - case 0x06: - switch(decode.modrm.rm){ - case 0x00: /* F2XM1 */ - gen_call_function_raw((void*)&FPU_F2XM1); - break; - case 0x01: /* FYL2X */ - gen_call_function_raw((void*)&FPU_FYL2X); - break; - case 0x02: /* FPTAN */ - gen_call_function_raw((void*)&FPU_FPTAN); - break; - case 0x03: /* FPATAN */ - gen_call_function_raw((void*)&FPU_FPATAN); - break; - case 0x04: /* FXTRACT */ - gen_call_function_raw((void*)&FPU_FXTRACT); - break; - case 0x05: /* FPREM1 */ - gen_call_function_raw((void*)&FPU_FPREM1); - break; - case 0x06: /* FDECSTP */ - gen_call_function_raw((void*)&FPU_FDECSTP); - break; - case 0x07: /* FINCSTP */ - gen_call_function_raw((void*)&FPU_FINCSTP); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - case 0x07: - switch(decode.modrm.rm){ - case 0x00: /* FPREM */ - gen_call_function_raw((void*)&FPU_FPREM); - break; - case 0x01: /* FYL2XP1 */ - gen_call_function_raw((void*)&FPU_FYL2XP1); - break; - case 0x02: /* FSQRT */ - gen_call_function_raw((void*)&FPU_FSQRT); - break; - case 0x03: /* FSINCOS */ - gen_call_function_raw((void*)&FPU_FSINCOS); - break; - case 0x04: /* FRNDINT */ - gen_call_function_raw((void*)&FPU_FRNDINT); - break; - case 0x05: /* FSCALE */ - gen_call_function_raw((void*)&FPU_FSCALE); - break; - case 0x06: /* FSIN */ - gen_call_function_raw((void*)&FPU_FSIN); - break; - case 0x07: /* FCOS */ - gen_call_function_raw((void*)&FPU_FCOS); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); - break; - } - } else { - switch(decode.modrm.reg){ - case 0x00: /* FLD float*/ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FLD_F32,FC_OP1,FC_OP2); - break; - case 0x01: /* UNKNOWN */ - LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - case 0x02: /* FST float*/ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR); - break; - case 0x03: /* FSTP float*/ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: /* FLDENV */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLDENV,FC_ADDR); - break; - case 0x05: /* FLDCW */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void *)&FPU_FLDCW,FC_ADDR); - break; - case 0x06: /* FSTENV */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void *)&FPU_FSTENV,FC_ADDR); - break; - case 0x07: /* FNSTCW*/ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void *)&FPU_FNSTCW,FC_ADDR); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } -} - -static void dyn_fpu_esc2(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch(decode.modrm.reg){ - case 0x05: - switch(decode.modrm.rm){ - case 0x01: /* FUCOMPP */ - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_add_imm(FC_OP2,1); - gen_and_imm(FC_OP2,7); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_call_function_RR((void *)&FPU_FUCOM,FC_OP1,FC_OP2); - gen_call_function_raw((void *)&FPU_FPOP); - gen_call_function_raw((void *)&FPU_FPOP); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } else { - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLD_I32_EA,FC_ADDR); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - dyn_eatree(); - } -} - -static void dyn_fpu_esc3(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch (decode.modrm.reg) { - case 0x04: - switch (decode.modrm.rm) { - case 0x00: //FNENI - case 0x01: //FNDIS - LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion: %d",decode.modrm.rm); - break; - case 0x02: //FNCLEX FCLEX - gen_call_function_raw((void*)&FPU_FCLEX); - break; - case 0x03: //FNINIT FINIT - gen_call_function_raw((void*)&FPU_FINIT); - break; - case 0x04: //FNSETPM - case 0x05: //FRSTPM -// LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); - break; - default: - E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } else { - switch(decode.modrm.reg){ - case 0x00: /* FILD */ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FLD_I32,FC_OP1,FC_OP2); - break; - case 0x01: /* FISTTP */ - LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - case 0x02: /* FIST */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR); - break; - case 0x03: /* FISTP */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x05: /* FLD 80 Bits Real */ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLD_F80,FC_ADDR); - break; - case 0x07: /* FSTP 80 Bits Real */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_F80,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - } - } -} - -static void dyn_fpu_esc4(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch(decode.modrm.reg){ - case 0x00: /* FADD STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); - break; - case 0x01: /* FMUL STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); - break; - case 0x02: /* FCOM*/ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - break; - case 0x03: /* FCOMP*/ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: /* FSUBR STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); - break; - case 0x05: /* FSUB STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); - break; - case 0x06: /* FDIVR STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); - break; - case 0x07: /* FDIV STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); - break; - default: - break; - } - } else { - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLD_F64_EA,FC_ADDR); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - dyn_eatree(); - } -} - -static void dyn_fpu_esc5(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - dyn_fpu_top(); - switch(decode.modrm.reg){ - case 0x00: /* FFREE STi */ - gen_call_function_R((void*)&FPU_FFREE,FC_OP2); - break; - case 0x01: /* FXCH STi*/ - gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); - break; - case 0x02: /* FST STi */ - gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); - break; - case 0x03: /* FSTP STi*/ - gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: /* FUCOM STi */ - gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2); - break; - case 0x05: /*FUCOMP STi */ - gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } else { - switch(decode.modrm.reg){ - case 0x00: /* FLD double real*/ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FLD_F64,FC_OP1,FC_OP2); - break; - case 0x01: /* FISTTP longint*/ - LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - case 0x02: /* FST double real*/ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR); - break; - case 0x03: /* FSTP double real*/ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: /* FRSTOR */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FRSTOR,FC_ADDR); - break; - case 0x06: /* FSAVE */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FSAVE,FC_ADDR); - break; - case 0x07: /*FNSTSW */ - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&fpu.sw),true); - gen_call_function_RR((void*)&mem_writew,FC_OP1,FC_OP2); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - } - } -} - -static void dyn_fpu_esc6(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch(decode.modrm.reg){ - case 0x00: /*FADDP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); - break; - case 0x01: /* FMULP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); - break; - case 0x02: /* FCOMP5*/ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - break; /* TODO IS THIS ALLRIGHT ????????? */ - case 0x03: /*FCOMPP*/ - if(decode.modrm.rm != 1) { - LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - return; - } - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_add_imm(FC_OP2,1); - gen_and_imm(FC_OP2,7); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); /* extra pop at the bottom*/ - break; - case 0x04: /* FSUBRP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); - break; - case 0x05: /* FSUBP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); - break; - case 0x06: /* FDIVRP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); - break; - case 0x07: /* FDIVP STi,ST*/ - dyn_fpu_top_swapped(); - gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); - break; - default: - break; - } - gen_call_function_raw((void*)&FPU_FPOP); - } else { - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FLD_I16_EA,FC_ADDR); - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - dyn_eatree(); - } -} - -static void dyn_fpu_esc7(){ - dyn_get_modrm(); - if (decode.modrm.val >= 0xc0) { - switch (decode.modrm.reg){ - case 0x01: /* FXCH STi*/ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); - break; - case 0x02: /* FSTP STi*/ - case 0x03: /* FSTP STi*/ - dyn_fpu_top(); - gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: - switch(decode.modrm.rm){ - case 0x00: /* FNSTSW AX*/ - gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); - gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1); - gen_mov_word_to_reg(FC_OP1,(void*)(&fpu.sw),false); - MOV_REG_WORD16_FROM_HOST_REG(FC_OP1,DRC_REG_EAX); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } else { - switch(decode.modrm.reg){ - case 0x00: /* FILD Bit16s */ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FLD_I16,FC_OP1,FC_OP2); - break; - case 0x01: - LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - case 0x02: /* FIST Bit16s */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR); - break; - case 0x03: /* FISTP Bit16s */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x04: /* FBLD packed BCD */ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FBLD,FC_OP1,FC_OP2); - break; - case 0x05: /* FILD Bit64s */ - gen_call_function_raw((void*)&FPU_PREP_PUSH); - dyn_fill_ea(FC_OP1); - gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); - gen_call_function_RR((void*)&FPU_FLD_I64,FC_OP1,FC_OP2); - break; - case 0x06: /* FBSTP packed BCD */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FBST,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - case 0x07: /* FISTP Bit64s */ - dyn_fill_ea(FC_ADDR); - gen_call_function_R((void*)&FPU_FST_I64,FC_ADDR); - gen_call_function_raw((void*)&FPU_FPOP); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); - break; - } - } -} - -#endif diff --git a/src/cpu/core_dynrec/operators.h b/src/cpu/core_dynrec/operators.h deleted file mode 100644 index 45289a6..0000000 --- a/src/cpu/core_dynrec/operators.h +++ /dev/null @@ -1,1995 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -static Bit8u DRC_CALL_CONV dynrec_add_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_add_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=(Bit8u)(lf_var1b+lf_var2b); - lflags.type=t_ADDb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_add_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_add_byte_simple(Bit8u op1,Bit8u op2) { - return op1+op2; -} - -static Bit8u DRC_CALL_CONV dynrec_adc_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_adc_byte(Bit8u op1,Bit8u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1b=op1; - lf_var2b=op2; - lf_resb=(Bit8u)(lf_var1b+lf_var2b+lflags.oldcf); - lflags.type=t_ADCb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_adc_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_adc_byte_simple(Bit8u op1,Bit8u op2) { - return (Bit8u)(op1+op2+(Bitu)(get_CF()!=0)); -} - -static Bit8u DRC_CALL_CONV dynrec_sub_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sub_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=(Bit8u)(lf_var1b-lf_var2b); - lflags.type=t_SUBb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_sub_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sub_byte_simple(Bit8u op1,Bit8u op2) { - return op1-op2; -} - -static Bit8u DRC_CALL_CONV dynrec_sbb_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sbb_byte(Bit8u op1,Bit8u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1b=op1; - lf_var2b=op2; - lf_resb=(Bit8u)(lf_var1b-(lf_var2b+lflags.oldcf)); - lflags.type=t_SBBb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_sbb_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sbb_byte_simple(Bit8u op1,Bit8u op2) { - return (Bit8u)(op1-(op2+(Bitu)(get_CF()!=0))); -} - -static void DRC_CALL_CONV dynrec_cmp_byte(Bit8u op1,Bit8u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=(Bit8u)(lf_var1b-lf_var2b); - lflags.type=t_CMPb; -} - -static void DRC_CALL_CONV dynrec_cmp_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_byte_simple(Bit8u op1,Bit8u op2) { -} - -static Bit8u DRC_CALL_CONV dynrec_xor_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_xor_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b ^ lf_var2b; - lflags.type=t_XORb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_xor_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_xor_byte_simple(Bit8u op1,Bit8u op2) { - return op1 ^ op2; -} - -static Bit8u DRC_CALL_CONV dynrec_and_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_and_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b & lf_var2b; - lflags.type=t_ANDb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_and_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_and_byte_simple(Bit8u op1,Bit8u op2) { - return op1 & op2; -} - -static Bit8u DRC_CALL_CONV dynrec_or_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_or_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b | lf_var2b; - lflags.type=t_ORb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_or_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_or_byte_simple(Bit8u op1,Bit8u op2) { - return op1 | op2; -} - -static void DRC_CALL_CONV dynrec_test_byte(Bit8u op1,Bit8u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_byte(Bit8u op1,Bit8u op2) { - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b & lf_var2b; - lflags.type=t_TESTb; -} - -static void DRC_CALL_CONV dynrec_test_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_byte_simple(Bit8u op1,Bit8u op2) { -} - -static Bit16u DRC_CALL_CONV dynrec_add_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_add_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=(Bit16u)(lf_var1w+lf_var2w); - lflags.type=t_ADDw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_add_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_add_word_simple(Bit16u op1,Bit16u op2) { - return op1+op2; -} - -static Bit16u DRC_CALL_CONV dynrec_adc_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_adc_word(Bit16u op1,Bit16u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1w=op1; - lf_var2w=op2; - lf_resw=(Bit16u)(lf_var1w+lf_var2w+lflags.oldcf); - lflags.type=t_ADCw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_adc_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_adc_word_simple(Bit16u op1,Bit16u op2) { - return (Bit16u)(op1+op2+(Bitu)(get_CF()!=0)); -} - -static Bit16u DRC_CALL_CONV dynrec_sub_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sub_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=(Bit16u)(lf_var1w-lf_var2w); - lflags.type=t_SUBw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_sub_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sub_word_simple(Bit16u op1,Bit16u op2) { - return op1-op2; -} - -static Bit16u DRC_CALL_CONV dynrec_sbb_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sbb_word(Bit16u op1,Bit16u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1w=op1; - lf_var2w=op2; - lf_resw=(Bit16u)(lf_var1w-(lf_var2w+lflags.oldcf)); - lflags.type=t_SBBw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_sbb_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sbb_word_simple(Bit16u op1,Bit16u op2) { - return (Bit16u)(op1-(op2+(Bitu)(get_CF()!=0))); -} - -static void DRC_CALL_CONV dynrec_cmp_word(Bit16u op1,Bit16u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=(Bit16u)(lf_var1w-lf_var2w); - lflags.type=t_CMPw; -} - -static void DRC_CALL_CONV dynrec_cmp_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_word_simple(Bit16u op1,Bit16u op2) { -} - -static Bit16u DRC_CALL_CONV dynrec_xor_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_xor_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=lf_var1w ^ lf_var2w; - lflags.type=t_XORw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_xor_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_xor_word_simple(Bit16u op1,Bit16u op2) { - return op1 ^ op2; -} - -static Bit16u DRC_CALL_CONV dynrec_and_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_and_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=lf_var1w & lf_var2w; - lflags.type=t_ANDw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_and_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_and_word_simple(Bit16u op1,Bit16u op2) { - return op1 & op2; -} - -static Bit16u DRC_CALL_CONV dynrec_or_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_or_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=lf_var1w | lf_var2w; - lflags.type=t_ORw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_or_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_or_word_simple(Bit16u op1,Bit16u op2) { - return op1 | op2; -} - -static void DRC_CALL_CONV dynrec_test_word(Bit16u op1,Bit16u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_word(Bit16u op1,Bit16u op2) { - lf_var1w=op1; - lf_var2w=op2; - lf_resw=lf_var1w & lf_var2w; - lflags.type=t_TESTw; -} - -static void DRC_CALL_CONV dynrec_test_word_simple(Bit16u op1,Bit16u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_word_simple(Bit16u op1,Bit16u op2) { -} - -static Bit32u DRC_CALL_CONV dynrec_add_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_add_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d+lf_var2d; - lflags.type=t_ADDd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_add_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_add_dword_simple(Bit32u op1,Bit32u op2) { - return op1 + op2; -} - -static Bit32u DRC_CALL_CONV dynrec_adc_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_adc_dword(Bit32u op1,Bit32u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d+lf_var2d+lflags.oldcf; - lflags.type=t_ADCd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_adc_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_adc_dword_simple(Bit32u op1,Bit32u op2) { - return op1+op2+(Bitu)(get_CF()!=0); -} - -static Bit32u DRC_CALL_CONV dynrec_sub_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sub_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d-lf_var2d; - lflags.type=t_SUBd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_sub_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sub_dword_simple(Bit32u op1,Bit32u op2) { - return op1-op2; -} - -static Bit32u DRC_CALL_CONV dynrec_sbb_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sbb_dword(Bit32u op1,Bit32u op2) { - lflags.oldcf=get_CF()!=0; - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d-(lf_var2d+lflags.oldcf); - lflags.type=t_SBBd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_sbb_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sbb_dword_simple(Bit32u op1,Bit32u op2) { - return op1-(op2+(Bitu)(get_CF()!=0)); -} - -static void DRC_CALL_CONV dynrec_cmp_dword(Bit32u op1,Bit32u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d-lf_var2d; - lflags.type=t_CMPd; -} - -static void DRC_CALL_CONV dynrec_cmp_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_cmp_dword_simple(Bit32u op1,Bit32u op2) { -} - -static Bit32u DRC_CALL_CONV dynrec_xor_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_xor_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d ^ lf_var2d; - lflags.type=t_XORd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_xor_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_xor_dword_simple(Bit32u op1,Bit32u op2) { - return op1 ^ op2; -} - -static Bit32u DRC_CALL_CONV dynrec_and_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_and_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d & lf_var2d; - lflags.type=t_ANDd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_and_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_and_dword_simple(Bit32u op1,Bit32u op2) { - return op1 & op2; -} - -static Bit32u DRC_CALL_CONV dynrec_or_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_or_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d | lf_var2d; - lflags.type=t_ORd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_or_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_or_dword_simple(Bit32u op1,Bit32u op2) { - return op1 | op2; -} - -static void DRC_CALL_CONV dynrec_test_dword(Bit32u op1,Bit32u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_dword(Bit32u op1,Bit32u op2) { - lf_var1d=op1; - lf_var2d=op2; - lf_resd=lf_var1d & lf_var2d; - lflags.type=t_TESTd; -} - -static void DRC_CALL_CONV dynrec_test_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; -static void DRC_CALL_CONV dynrec_test_dword_simple(Bit32u op1,Bit32u op2) { -} - - -static void dyn_dop_byte_gencall(DualOps op) { - switch (op) { - case DOP_ADD: - InvalidateFlags((void*)&dynrec_add_byte_simple,t_ADDb); - gen_call_function_raw((void*)&dynrec_add_byte); - break; - case DOP_ADC: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_adc_byte_simple,t_ADCb); - gen_call_function_raw((void*)&dynrec_adc_byte); - break; - case DOP_SUB: - InvalidateFlags((void*)&dynrec_sub_byte_simple,t_SUBb); - gen_call_function_raw((void*)&dynrec_sub_byte); - break; - case DOP_SBB: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_sbb_byte_simple,t_SBBb); - gen_call_function_raw((void*)&dynrec_sbb_byte); - break; - case DOP_CMP: - InvalidateFlags((void*)&dynrec_cmp_byte_simple,t_CMPb); - gen_call_function_raw((void*)&dynrec_cmp_byte); - break; - case DOP_XOR: - InvalidateFlags((void*)&dynrec_xor_byte_simple,t_XORb); - gen_call_function_raw((void*)&dynrec_xor_byte); - break; - case DOP_AND: - InvalidateFlags((void*)&dynrec_and_byte_simple,t_ANDb); - gen_call_function_raw((void*)&dynrec_and_byte); - break; - case DOP_OR: - InvalidateFlags((void*)&dynrec_or_byte_simple,t_ORb); - gen_call_function_raw((void*)&dynrec_or_byte); - break; - case DOP_TEST: - InvalidateFlags((void*)&dynrec_test_byte_simple,t_TESTb); - gen_call_function_raw((void*)&dynrec_test_byte); - break; - default: IllegalOptionDynrec("dyn_dop_byte_gencall"); - } -} - -static void dyn_dop_word_gencall(DualOps op,bool dword) { - if (dword) { - switch (op) { - case DOP_ADD: - InvalidateFlags((void*)&dynrec_add_dword_simple,t_ADDd); - gen_call_function_raw((void*)&dynrec_add_dword); - break; - case DOP_ADC: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_adc_dword_simple,t_ADCd); - gen_call_function_raw((void*)&dynrec_adc_dword); - break; - case DOP_SUB: - InvalidateFlags((void*)&dynrec_sub_dword_simple,t_SUBd); - gen_call_function_raw((void*)&dynrec_sub_dword); - break; - case DOP_SBB: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_sbb_dword_simple,t_SBBd); - gen_call_function_raw((void*)&dynrec_sbb_dword); - break; - case DOP_CMP: - InvalidateFlags((void*)&dynrec_cmp_dword_simple,t_CMPd); - gen_call_function_raw((void*)&dynrec_cmp_dword); - break; - case DOP_XOR: - InvalidateFlags((void*)&dynrec_xor_dword_simple,t_XORd); - gen_call_function_raw((void*)&dynrec_xor_dword); - break; - case DOP_AND: - InvalidateFlags((void*)&dynrec_and_dword_simple,t_ANDd); - gen_call_function_raw((void*)&dynrec_and_dword); - break; - case DOP_OR: - InvalidateFlags((void*)&dynrec_or_dword_simple,t_ORd); - gen_call_function_raw((void*)&dynrec_or_dword); - break; - case DOP_TEST: - InvalidateFlags((void*)&dynrec_test_dword_simple,t_TESTd); - gen_call_function_raw((void*)&dynrec_test_dword); - break; - default: IllegalOptionDynrec("dyn_dop_dword_gencall"); - } - } else { - switch (op) { - case DOP_ADD: - InvalidateFlags((void*)&dynrec_add_word_simple,t_ADDw); - gen_call_function_raw((void*)&dynrec_add_word); - break; - case DOP_ADC: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_adc_word_simple,t_ADCw); - gen_call_function_raw((void*)&dynrec_adc_word); - break; - case DOP_SUB: - InvalidateFlags((void*)&dynrec_sub_word_simple,t_SUBw); - gen_call_function_raw((void*)&dynrec_sub_word); - break; - case DOP_SBB: - AcquireFlags(FLAG_CF); - InvalidateFlagsPartially((void*)&dynrec_sbb_word_simple,t_SBBw); - gen_call_function_raw((void*)&dynrec_sbb_word); - break; - case DOP_CMP: - InvalidateFlags((void*)&dynrec_cmp_word_simple,t_CMPw); - gen_call_function_raw((void*)&dynrec_cmp_word); - break; - case DOP_XOR: - InvalidateFlags((void*)&dynrec_xor_word_simple,t_XORw); - gen_call_function_raw((void*)&dynrec_xor_word); - break; - case DOP_AND: - InvalidateFlags((void*)&dynrec_and_word_simple,t_ANDw); - gen_call_function_raw((void*)&dynrec_and_word); - break; - case DOP_OR: - InvalidateFlags((void*)&dynrec_or_word_simple,t_ORw); - gen_call_function_raw((void*)&dynrec_or_word); - break; - case DOP_TEST: - InvalidateFlags((void*)&dynrec_test_word_simple,t_TESTw); - gen_call_function_raw((void*)&dynrec_test_word); - break; - default: IllegalOptionDynrec("dyn_dop_word_gencall"); - } - } -} - - -static Bit8u DRC_CALL_CONV dynrec_inc_byte(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_inc_byte(Bit8u op) { - LoadCF; - lf_var1b=op; - lf_resb=lf_var1b+1; - lflags.type=t_INCb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_inc_byte_simple(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_inc_byte_simple(Bit8u op) { - return op+1; -} - -static Bit8u DRC_CALL_CONV dynrec_dec_byte(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_dec_byte(Bit8u op) { - LoadCF; - lf_var1b=op; - lf_resb=lf_var1b-1; - lflags.type=t_DECb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_dec_byte_simple(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_dec_byte_simple(Bit8u op) { - return op-1; -} - -static Bit8u DRC_CALL_CONV dynrec_not_byte(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_not_byte(Bit8u op) { - return ~op; -} - -static Bit8u DRC_CALL_CONV dynrec_neg_byte(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_neg_byte(Bit8u op) { - lf_var1b=op; - lf_resb=0-lf_var1b; - lflags.type=t_NEGb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_neg_byte_simple(Bit8u op) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_neg_byte_simple(Bit8u op) { - return 0-op; -} - -static Bit16u DRC_CALL_CONV dynrec_inc_word(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_inc_word(Bit16u op) { - LoadCF; - lf_var1w=op; - lf_resw=lf_var1w+1; - lflags.type=t_INCw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_inc_word_simple(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_inc_word_simple(Bit16u op) { - return op+1; -} - -static Bit16u DRC_CALL_CONV dynrec_dec_word(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dec_word(Bit16u op) { - LoadCF; - lf_var1w=op; - lf_resw=lf_var1w-1; - lflags.type=t_DECw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_dec_word_simple(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dec_word_simple(Bit16u op) { - return op-1; -} - -static Bit16u DRC_CALL_CONV dynrec_not_word(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_not_word(Bit16u op) { - return ~op; -} - -static Bit16u DRC_CALL_CONV dynrec_neg_word(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_neg_word(Bit16u op) { - lf_var1w=op; - lf_resw=0-lf_var1w; - lflags.type=t_NEGw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_neg_word_simple(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_neg_word_simple(Bit16u op) { - return 0-op; -} - -static Bit32u DRC_CALL_CONV dynrec_inc_dword(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_inc_dword(Bit32u op) { - LoadCF; - lf_var1d=op; - lf_resd=lf_var1d+1; - lflags.type=t_INCd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_inc_dword_simple(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_inc_dword_simple(Bit32u op) { - return op+1; -} - -static Bit32u DRC_CALL_CONV dynrec_dec_dword(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dec_dword(Bit32u op) { - LoadCF; - lf_var1d=op; - lf_resd=lf_var1d-1; - lflags.type=t_DECd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_dec_dword_simple(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dec_dword_simple(Bit32u op) { - return op-1; -} - -static Bit32u DRC_CALL_CONV dynrec_not_dword(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_not_dword(Bit32u op) { - return ~op; -} - -static Bit32u DRC_CALL_CONV dynrec_neg_dword(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_neg_dword(Bit32u op) { - lf_var1d=op; - lf_resd=0-lf_var1d; - lflags.type=t_NEGd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_neg_dword_simple(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_neg_dword_simple(Bit32u op) { - return 0-op; -} - - -static void dyn_sop_byte_gencall(SingleOps op) { - switch (op) { - case SOP_INC: - InvalidateFlagsPartially((void*)&dynrec_inc_byte_simple,t_INCb); - gen_call_function_raw((void*)&dynrec_inc_byte); - break; - case SOP_DEC: - InvalidateFlagsPartially((void*)&dynrec_dec_byte_simple,t_DECb); - gen_call_function_raw((void*)&dynrec_dec_byte); - break; - case SOP_NOT: - gen_call_function_raw((void*)&dynrec_not_byte); - break; - case SOP_NEG: - InvalidateFlags((void*)&dynrec_neg_byte_simple,t_NEGb); - gen_call_function_raw((void*)&dynrec_neg_byte); - break; - default: IllegalOptionDynrec("dyn_sop_byte_gencall"); - } -} - -static void dyn_sop_word_gencall(SingleOps op,bool dword) { - if (dword) { - switch (op) { - case SOP_INC: - InvalidateFlagsPartially((void*)&dynrec_inc_dword_simple,t_INCd); - gen_call_function_raw((void*)&dynrec_inc_dword); - break; - case SOP_DEC: - InvalidateFlagsPartially((void*)&dynrec_dec_dword_simple,t_DECd); - gen_call_function_raw((void*)&dynrec_dec_dword); - break; - case SOP_NOT: - gen_call_function_raw((void*)&dynrec_not_dword); - break; - case SOP_NEG: - InvalidateFlags((void*)&dynrec_neg_dword_simple,t_NEGd); - gen_call_function_raw((void*)&dynrec_neg_dword); - break; - default: IllegalOptionDynrec("dyn_sop_dword_gencall"); - } - } else { - switch (op) { - case SOP_INC: - InvalidateFlagsPartially((void*)&dynrec_inc_word_simple,t_INCw); - gen_call_function_raw((void*)&dynrec_inc_word); - break; - case SOP_DEC: - InvalidateFlagsPartially((void*)&dynrec_dec_word_simple,t_DECw); - gen_call_function_raw((void*)&dynrec_dec_word); - break; - case SOP_NOT: - gen_call_function_raw((void*)&dynrec_not_word); - break; - case SOP_NEG: - InvalidateFlags((void*)&dynrec_neg_word_simple,t_NEGw); - gen_call_function_raw((void*)&dynrec_neg_word); - break; - default: IllegalOptionDynrec("dyn_sop_word_gencall"); - } - } -} - - -static Bit8u DRC_CALL_CONV dynrec_rol_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_rol_byte(Bit8u op1,Bit8u op2) { - if (!(op2&0x7)) { - if (op2&0x18) { - FillFlagsNoCFOF(); - SETFLAGBIT(CF,op1 & 1); - SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7)); - } - return op1; - } - FillFlagsNoCFOF(); - lf_var1b=op1; - lf_var2b=op2&0x07; - lf_resb=(lf_var1b << lf_var2b) | (lf_var1b >> (8-lf_var2b)); - SETFLAGBIT(CF,lf_resb & 1); - SETFLAGBIT(OF,(lf_resb & 1) ^ (lf_resb >> 7)); - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_rol_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_rol_byte_simple(Bit8u op1,Bit8u op2) { - if (!(op2&0x7)) return op1; - return (op1 << (op2&0x07)) | (op1 >> (8-(op2&0x07))); -} - -static Bit8u DRC_CALL_CONV dynrec_ror_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_ror_byte(Bit8u op1,Bit8u op2) { - if (!(op2&0x7)) { - if (op2&0x18) { - FillFlagsNoCFOF(); - SETFLAGBIT(CF,op1>>7); - SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1)); - } - return op1; - } - FillFlagsNoCFOF(); - lf_var1b=op1; - lf_var2b=op2&0x07; - lf_resb=(lf_var1b >> lf_var2b) | (lf_var1b << (8-lf_var2b)); - SETFLAGBIT(CF,lf_resb & 0x80); - SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_ror_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_ror_byte_simple(Bit8u op1,Bit8u op2) { - if (!(op2&0x7)) return op1; - return (op1 >> (op2&0x07)) | (op1 << (8-(op2&0x07))); -} - -static Bit8u DRC_CALL_CONV dynrec_rcl_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_rcl_byte(Bit8u op1,Bit8u op2) { - if (op2%9) { - Bit8u cf=(Bit8u)FillFlags()&0x1; - lf_var1b=op1; - lf_var2b=op2%9; - lf_resb=(lf_var1b << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1b >> (9-lf_var2b)); - SETFLAGBIT(CF,((lf_var1b >> (8-lf_var2b)) & 1)); - SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resb >> 7)); - return lf_resb; - } else return op1; -} - -static Bit8u DRC_CALL_CONV dynrec_rcr_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_rcr_byte(Bit8u op1,Bit8u op2) { - if (op2%9) { - Bit8u cf=(Bit8u)FillFlags()&0x1; - lf_var1b=op1; - lf_var2b=op2%9; - lf_resb=(lf_var1b >> lf_var2b) | (cf << (8-lf_var2b)) | (lf_var1b << (9-lf_var2b)); \ - SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1); - SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); - return lf_resb; - } else return op1; -} - -static Bit8u DRC_CALL_CONV dynrec_shl_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_shl_byte(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b << lf_var2b; - lflags.type=t_SHLb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_shl_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_shl_byte_simple(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - return op1 << op2; -} - -static Bit8u DRC_CALL_CONV dynrec_shr_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_shr_byte(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1b=op1; - lf_var2b=op2; - lf_resb=lf_var1b >> lf_var2b; - lflags.type=t_SHRb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_shr_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_shr_byte_simple(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - return op1 >> op2; -} - -static Bit8u DRC_CALL_CONV dynrec_sar_byte(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sar_byte(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1b=op1; - lf_var2b=op2; - if (lf_var2b>8) lf_var2b=8; - if (lf_var1b & 0x80) { - lf_resb=(lf_var1b >> lf_var2b)| (0xff << (8 - lf_var2b)); - } else { - lf_resb=lf_var1b >> lf_var2b; - } - lflags.type=t_SARb; - return lf_resb; -} - -static Bit8u DRC_CALL_CONV dynrec_sar_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; -static Bit8u DRC_CALL_CONV dynrec_sar_byte_simple(Bit8u op1,Bit8u op2) { - if (!op2) return op1; - if (op2>8) op2=8; - if (op1 & 0x80) return (op1 >> op2) | (0xff << (8 - op2)); - else return op1 >> op2; -} - -static Bit16u DRC_CALL_CONV dynrec_rol_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_rol_word(Bit16u op1,Bit8u op2) { - if (!(op2&0xf)) { - if (op2&0x10) { - FillFlagsNoCFOF(); - SETFLAGBIT(CF,op1 & 1); - SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 15)); - } - return op1; - } - FillFlagsNoCFOF(); - lf_var1w=op1; - lf_var2b=op2&0xf; - lf_resw=(lf_var1w << lf_var2b) | (lf_var1w >> (16-lf_var2b)); - SETFLAGBIT(CF,lf_resw & 1); - SETFLAGBIT(OF,(lf_resw & 1) ^ (lf_resw >> 15)); - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_rol_word_simple(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_rol_word_simple(Bit16u op1,Bit8u op2) { - if (!(op2&0xf)) return op1; - return (op1 << (op2&0xf)) | (op1 >> (16-(op2&0xf))); -} - -static Bit16u DRC_CALL_CONV dynrec_ror_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_ror_word(Bit16u op1,Bit8u op2) { - if (!(op2&0xf)) { - if (op2&0x10) { - FillFlagsNoCFOF(); - SETFLAGBIT(CF,op1>>15); - SETFLAGBIT(OF,(op1>>15) ^ ((op1>>14) & 1)); - } - return op1; - } - FillFlagsNoCFOF(); - lf_var1w=op1; - lf_var2b=op2&0xf; - lf_resw=(lf_var1w >> lf_var2b) | (lf_var1w << (16-lf_var2b)); - SETFLAGBIT(CF,lf_resw & 0x8000); - SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_ror_word_simple(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_ror_word_simple(Bit16u op1,Bit8u op2) { - if (!(op2&0xf)) return op1; - return (op1 >> (op2&0xf)) | (op1 << (16-(op2&0xf))); -} - -static Bit16u DRC_CALL_CONV dynrec_rcl_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_rcl_word(Bit16u op1,Bit8u op2) { - if (op2%17) { - Bit16u cf=(Bit16u)FillFlags()&0x1; - lf_var1w=op1; - lf_var2b=op2%17; - lf_resw=(lf_var1w << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1w >> (17-lf_var2b)); - SETFLAGBIT(CF,((lf_var1w >> (16-lf_var2b)) & 1)); - SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resw >> 15)); - return lf_resw; - } else return op1; -} - -static Bit16u DRC_CALL_CONV dynrec_rcr_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_rcr_word(Bit16u op1,Bit8u op2) { - if (op2%17) { - Bit16u cf=(Bit16u)FillFlags()&0x1; - lf_var1w=op1; - lf_var2b=op2%17; - lf_resw=(lf_var1w >> lf_var2b) | (cf << (16-lf_var2b)) | (lf_var1w << (17-lf_var2b)); - SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1); - SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); - return lf_resw; - } else return op1; -} - -static Bit16u DRC_CALL_CONV dynrec_shl_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_shl_word(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1w=op1; - lf_var2b=op2; - lf_resw=lf_var1w << lf_var2b; - lflags.type=t_SHLw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_shl_word_simple(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_shl_word_simple(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - return op1 << op2; -} - -static Bit16u DRC_CALL_CONV dynrec_shr_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_shr_word(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1w=op1; - lf_var2b=op2; - lf_resw=lf_var1w >> lf_var2b; - lflags.type=t_SHRw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_shr_word_simple(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_shr_word_simple(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - return op1 >> op2; -} - -static Bit16u DRC_CALL_CONV dynrec_sar_word(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sar_word(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1w=op1; - lf_var2b=op2; - if (lf_var2b>16) lf_var2b=16; - if (lf_var1w & 0x8000) { - lf_resw=(lf_var1w >> lf_var2b) | (0xffff << (16 - lf_var2b)); - } else { - lf_resw=lf_var1w >> lf_var2b; - } - lflags.type=t_SARw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_sar_word_simple(Bit16u op1,Bit8u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_sar_word_simple(Bit16u op1,Bit8u op2) { - if (!op2) return op1; - if (op2>16) op2=16; - if (op1 & 0x8000) return (op1 >> op2) | (0xffff << (16 - op2)); - else return op1 >> op2; -} - -static Bit32u DRC_CALL_CONV dynrec_rol_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_rol_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - FillFlagsNoCFOF(); - lf_var1d=op1; - lf_var2b=op2; - lf_resd=(lf_var1d << lf_var2b) | (lf_var1d >> (32-lf_var2b)); - SETFLAGBIT(CF,lf_resd & 1); - SETFLAGBIT(OF,(lf_resd & 1) ^ (lf_resd >> 31)); - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_rol_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_rol_dword_simple(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - return (op1 << op2) | (op1 >> (32-op2)); -} - -static Bit32u DRC_CALL_CONV dynrec_ror_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_ror_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - FillFlagsNoCFOF(); - lf_var1d=op1; - lf_var2b=op2; - lf_resd=(lf_var1d >> lf_var2b) | (lf_var1d << (32-lf_var2b)); - SETFLAGBIT(CF,lf_resd & 0x80000000); - SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_ror_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_ror_dword_simple(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - return (op1 >> op2) | (op1 << (32-op2)); -} - -static Bit32u DRC_CALL_CONV dynrec_rcl_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_rcl_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - Bit32u cf=(Bit32u)FillFlags()&0x1; - lf_var1d=op1; - lf_var2b=op2; - if (lf_var2b==1) { - lf_resd=(lf_var1d << 1) | cf; - } else { - lf_resd=(lf_var1d << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1d >> (33-lf_var2b)); - } - SETFLAGBIT(CF,((lf_var1d >> (32-lf_var2b)) & 1)); - SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resd >> 31)); - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_rcr_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_rcr_dword(Bit32u op1,Bit8u op2) { - if (op2) { - Bit32u cf=(Bit32u)FillFlags()&0x1; - lf_var1d=op1; - lf_var2b=op2; - if (lf_var2b==1) { - lf_resd=lf_var1d >> 1 | cf << 31; - } else { - lf_resd=(lf_var1d >> lf_var2b) | (cf << (32-lf_var2b)) | (lf_var1d << (33-lf_var2b)); - } - SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1); - SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); - return lf_resd; - } else return op1; -} - -static Bit32u DRC_CALL_CONV dynrec_shl_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_shl_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1d=op1; - lf_var2b=op2; - lf_resd=lf_var1d << lf_var2b; - lflags.type=t_SHLd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_shl_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_shl_dword_simple(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - return op1 << op2; -} - -static Bit32u DRC_CALL_CONV dynrec_shr_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_shr_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - lf_var1d=op1; - lf_var2b=op2; - lf_resd=lf_var1d >> lf_var2b; - lflags.type=t_SHRd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_shr_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_shr_dword_simple(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - return op1 >> op2; -} - -static Bit32u DRC_CALL_CONV dynrec_sar_dword(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sar_dword(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - lf_var2b=op2; - lf_var1d=op1; - if (lf_var1d & 0x80000000) { - lf_resd=(lf_var1d >> lf_var2b) | (0xffffffff << (32 - lf_var2b)); - } else { - lf_resd=lf_var1d >> lf_var2b; - } - lflags.type=t_SARd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_sar_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_sar_dword_simple(Bit32u op1,Bit8u op2) { - if (!op2) return op1; - if (op1 & 0x80000000) return (op1 >> op2) | (0xffffffff << (32 - op2)); - else return op1 >> op2; -} - -static void dyn_shift_byte_gencall(ShiftOps op) { - switch (op) { - case SHIFT_ROL: - InvalidateFlagsPartially((void*)&dynrec_rol_byte_simple,t_ROLb); - gen_call_function_raw((void*)&dynrec_rol_byte); - break; - case SHIFT_ROR: - InvalidateFlagsPartially((void*)&dynrec_ror_byte_simple,t_RORb); - gen_call_function_raw((void*)&dynrec_ror_byte); - break; - case SHIFT_RCL: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcl_byte); - break; - case SHIFT_RCR: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcr_byte); - break; - case SHIFT_SHL: - case SHIFT_SAL: - InvalidateFlagsPartially((void*)&dynrec_shl_byte_simple,t_SHLb); - gen_call_function_raw((void*)&dynrec_shl_byte); - break; - case SHIFT_SHR: - InvalidateFlagsPartially((void*)&dynrec_shr_byte_simple,t_SHRb); - gen_call_function_raw((void*)&dynrec_shr_byte); - break; - case SHIFT_SAR: - InvalidateFlagsPartially((void*)&dynrec_sar_byte_simple,t_SARb); - gen_call_function_raw((void*)&dynrec_sar_byte); - break; - default: IllegalOptionDynrec("dyn_shift_byte_gencall"); - } -} - -static void dyn_shift_word_gencall(ShiftOps op,bool dword) { - if (dword) { - switch (op) { - case SHIFT_ROL: - InvalidateFlagsPartially((void*)&dynrec_rol_dword_simple,t_ROLd); - gen_call_function_raw((void*)&dynrec_rol_dword); - break; - case SHIFT_ROR: - InvalidateFlagsPartially((void*)&dynrec_ror_dword_simple,t_RORd); - gen_call_function_raw((void*)&dynrec_ror_dword); - break; - case SHIFT_RCL: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcl_dword); - break; - case SHIFT_RCR: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcr_dword); - break; - case SHIFT_SHL: - case SHIFT_SAL: - InvalidateFlagsPartially((void*)&dynrec_shl_dword_simple,t_SHLd); - gen_call_function_raw((void*)&dynrec_shl_dword); - break; - case SHIFT_SHR: - InvalidateFlagsPartially((void*)&dynrec_shr_dword_simple,t_SHRd); - gen_call_function_raw((void*)&dynrec_shr_dword); - break; - case SHIFT_SAR: - InvalidateFlagsPartially((void*)&dynrec_sar_dword_simple,t_SARd); - gen_call_function_raw((void*)&dynrec_sar_dword); - break; - default: IllegalOptionDynrec("dyn_shift_dword_gencall"); - } - } else { - switch (op) { - case SHIFT_ROL: - InvalidateFlagsPartially((void*)&dynrec_rol_word_simple,t_ROLw); - gen_call_function_raw((void*)&dynrec_rol_word); - break; - case SHIFT_ROR: - InvalidateFlagsPartially((void*)&dynrec_ror_word_simple,t_RORw); - gen_call_function_raw((void*)&dynrec_ror_word); - break; - case SHIFT_RCL: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcl_word); - break; - case SHIFT_RCR: - AcquireFlags(FLAG_CF); - gen_call_function_raw((void*)&dynrec_rcr_word); - break; - case SHIFT_SHL: - case SHIFT_SAL: - InvalidateFlagsPartially((void*)&dynrec_shl_word_simple,t_SHLw); - gen_call_function_raw((void*)&dynrec_shl_word); - break; - case SHIFT_SHR: - InvalidateFlagsPartially((void*)&dynrec_shr_word_simple,t_SHRw); - gen_call_function_raw((void*)&dynrec_shr_word); - break; - case SHIFT_SAR: - InvalidateFlagsPartially((void*)&dynrec_sar_word_simple,t_SARw); - gen_call_function_raw((void*)&dynrec_sar_word); - break; - default: IllegalOptionDynrec("dyn_shift_word_gencall"); - } - } -} - -static Bit16u DRC_CALL_CONV dynrec_dshl_word(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dshl_word(Bit16u op1,Bit16u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - lf_var2b=val; - lf_var1d=(op1<<16)|op2; - Bit32u tempd=lf_var1d << lf_var2b; - if (lf_var2b>16) tempd |= (op2 << (lf_var2b - 16)); - lf_resw=(Bit16u)(tempd >> 16); - lflags.type=t_DSHLw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_dshl_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dshl_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - Bit32u tempd=(Bit32u)((((Bit32u)op1)<<16)|op2) << val; - if (val>16) tempd |= (op2 << (val - 16)); - return (Bit16u)(tempd >> 16); -} - -static Bit32u DRC_CALL_CONV dynrec_dshl_dword(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dshl_dword(Bit32u op1,Bit32u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - lf_var2b=val; - lf_var1d=op1; - lf_resd=(lf_var1d << lf_var2b) | (op2 >> (32-lf_var2b)); - lflags.type=t_DSHLd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_dshl_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dshl_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - return (op1 << val) | (op2 >> (32-val)); -} - -static Bit16u DRC_CALL_CONV dynrec_dshr_word(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dshr_word(Bit16u op1,Bit16u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - lf_var2b=val; - lf_var1d=(op2<<16)|op1; - Bit32u tempd=lf_var1d >> lf_var2b; - if (lf_var2b>16) tempd |= (op2 << (32-lf_var2b )); - lf_resw=(Bit16u)(tempd); - lflags.type=t_DSHRw; - return lf_resw; -} - -static Bit16u DRC_CALL_CONV dynrec_dshr_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dshr_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - Bit32u tempd=(Bit32u)((((Bit32u)op2)<<16)|op1) >> val; - if (val>16) tempd |= (op2 << (32-val)); - return (Bit16u)(tempd); -} - -static Bit32u DRC_CALL_CONV dynrec_dshr_dword(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dshr_dword(Bit32u op1,Bit32u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - lf_var2b=val; - lf_var1d=op1; - lf_resd=(lf_var1d >> lf_var2b) | (op2 << (32-lf_var2b)); - lflags.type=t_DSHRd; - return lf_resd; -} - -static Bit32u DRC_CALL_CONV dynrec_dshr_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dshr_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) { - Bit8u val=op3 & 0x1f; - if (!val) return op1; - return (op1 >> val) | (op2 << (32-val)); -} - -static void dyn_dpshift_word_gencall(bool left) { - if (left) { - DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshl_word,FC_RETOP); - InvalidateFlagsPartially((void*)&dynrec_dshl_word_simple,proc_addr,t_DSHLw); - } else { - DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshr_word,FC_RETOP); - InvalidateFlagsPartially((void*)&dynrec_dshr_word_simple,proc_addr,t_DSHRw); - } -} - -static void dyn_dpshift_dword_gencall(bool left) { - if (left) { - DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshl_dword,FC_RETOP); - InvalidateFlagsPartially((void*)&dynrec_dshl_dword_simple,proc_addr,t_DSHLd); - } else { - DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshr_dword,FC_RETOP); - InvalidateFlagsPartially((void*)&dynrec_dshr_dword_simple,proc_addr,t_DSHRd); - } -} - - - -static Bit32u DRC_CALL_CONV dynrec_get_of(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_of(void) { return TFLG_O; } -static Bit32u DRC_CALL_CONV dynrec_get_nof(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_nof(void) { return TFLG_NO; } -static Bit32u DRC_CALL_CONV dynrec_get_cf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_cf(void) { return TFLG_B; } -static Bit32u DRC_CALL_CONV dynrec_get_ncf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_ncf(void) { return TFLG_NB; } -static Bit32u DRC_CALL_CONV dynrec_get_zf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_zf(void) { return TFLG_Z; } -static Bit32u DRC_CALL_CONV dynrec_get_nzf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_nzf(void) { return TFLG_NZ; } -static Bit32u DRC_CALL_CONV dynrec_get_sf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_sf(void) { return TFLG_S; } -static Bit32u DRC_CALL_CONV dynrec_get_nsf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_nsf(void) { return TFLG_NS; } -static Bit32u DRC_CALL_CONV dynrec_get_pf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_pf(void) { return TFLG_P; } -static Bit32u DRC_CALL_CONV dynrec_get_npf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_npf(void) { return TFLG_NP; } - -static Bit32u DRC_CALL_CONV dynrec_get_cf_or_zf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_cf_or_zf(void) { return TFLG_BE; } -static Bit32u DRC_CALL_CONV dynrec_get_ncf_and_nzf(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_ncf_and_nzf(void) { return TFLG_NBE; } -static Bit32u DRC_CALL_CONV dynrec_get_sf_neq_of(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_sf_neq_of(void) { return TFLG_L; } -static Bit32u DRC_CALL_CONV dynrec_get_sf_eq_of(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_sf_eq_of(void) { return TFLG_NL; } -static Bit32u DRC_CALL_CONV dynrec_get_zf_or_sf_neq_of(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_zf_or_sf_neq_of(void) { return TFLG_LE; } -static Bit32u DRC_CALL_CONV dynrec_get_nzf_and_sf_eq_of(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_get_nzf_and_sf_eq_of(void) { return TFLG_NLE; } - - -static void dyn_branchflag_to_reg(BranchTypes btype) { - switch (btype) { - case BR_O:gen_call_function_raw((void*)&dynrec_get_of);break; - case BR_NO:gen_call_function_raw((void*)&dynrec_get_nof);break; - case BR_B:gen_call_function_raw((void*)&dynrec_get_cf);break; - case BR_NB:gen_call_function_raw((void*)&dynrec_get_ncf);break; - case BR_Z:gen_call_function_raw((void*)&dynrec_get_zf);break; - case BR_NZ:gen_call_function_raw((void*)&dynrec_get_nzf);break; - case BR_BE:gen_call_function_raw((void*)&dynrec_get_cf_or_zf);break; - case BR_NBE:gen_call_function_raw((void*)&dynrec_get_ncf_and_nzf);break; - - case BR_S:gen_call_function_raw((void*)&dynrec_get_sf);break; - case BR_NS:gen_call_function_raw((void*)&dynrec_get_nsf);break; - case BR_P:gen_call_function_raw((void*)&dynrec_get_pf);break; - case BR_NP:gen_call_function_raw((void*)&dynrec_get_npf);break; - case BR_L:gen_call_function_raw((void*)&dynrec_get_sf_neq_of);break; - case BR_NL:gen_call_function_raw((void*)&dynrec_get_sf_eq_of);break; - case BR_LE:gen_call_function_raw((void*)&dynrec_get_zf_or_sf_neq_of);break; - case BR_NLE:gen_call_function_raw((void*)&dynrec_get_nzf_and_sf_eq_of);break; - } -} - - -static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) DRC_FC; -static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) { - FillFlagsNoCFOF(); - reg_ax=reg_al*op; - SETFLAGBIT(ZF,reg_al == 0); - if (reg_ax & 0xff00) { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } else { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } -} - -static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) DRC_FC; -static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) { - FillFlagsNoCFOF(); - reg_ax=((Bit8s)reg_al) * ((Bit8s)op); - if ((reg_ax & 0xff80)==0xff80 || (reg_ax & 0xff80)==0x0000) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } -} - -static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) DRC_FC; -static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) { - FillFlagsNoCFOF(); - Bitu tempu=(Bitu)reg_ax*(Bitu)op; - reg_ax=(Bit16u)(tempu); - reg_dx=(Bit16u)(tempu >> 16); - SETFLAGBIT(ZF,reg_ax == 0); - if (reg_dx) { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } else { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } -} - -static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) DRC_FC; -static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) { - FillFlagsNoCFOF(); - Bits temps=((Bit16s)reg_ax)*((Bit16s)op); - reg_ax=(Bit16s)(temps); - reg_dx=(Bit16s)(temps >> 16); - if (((temps & 0xffff8000)==0xffff8000 || (temps & 0xffff8000)==0x0000)) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } -} - -static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) DRC_FC; -static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) { - FillFlagsNoCFOF(); - Bit64u tempu=(Bit64u)reg_eax*(Bit64u)op; - reg_eax=(Bit32u)(tempu); - reg_edx=(Bit32u)(tempu >> 32); - SETFLAGBIT(ZF,reg_eax == 0); - if (reg_edx) { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } else { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } -} - -static void DRC_CALL_CONV dynrec_imul_dword(Bit32u op) DRC_FC; -static void DRC_CALL_CONV dynrec_imul_dword(Bit32u op) { - FillFlagsNoCFOF(); - Bit64s temps=((Bit64s)((Bit32s)reg_eax))*((Bit64s)((Bit32s)op)); - reg_eax=(Bit32u)(temps); - reg_edx=(Bit32u)(temps >> 32); - if ((reg_edx==0xffffffff) && (reg_eax & 0x80000000) ) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else if ( (reg_edx==0x00000000) && (reg_eax< 0x80000000) ) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } -} - - -static bool DRC_CALL_CONV dynrec_div_byte(Bit8u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_div_byte(Bit8u op) { - Bitu val=op; - if (val==0) return CPU_PrepareException(0,0); - Bitu quo=reg_ax / val; - Bit8u rem=(Bit8u)(reg_ax % val); - Bit8u quo8=(Bit8u)(quo&0xff); - if (quo>0xff) return CPU_PrepareException(0,0); - reg_ah=rem; - reg_al=quo8; - return false; -} - -static bool DRC_CALL_CONV dynrec_idiv_byte(Bit8u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_idiv_byte(Bit8u op) { - Bits val=(Bit8s)op; - if (val==0) return CPU_PrepareException(0,0); - Bits quo=((Bit16s)reg_ax) / val; - Bit8s rem=(Bit8s)((Bit16s)reg_ax % val); - Bit8s quo8s=(Bit8s)(quo&0xff); - if (quo!=(Bit16s)quo8s) return CPU_PrepareException(0,0); - reg_ah=rem; - reg_al=quo8s; - return false; -} - -static bool DRC_CALL_CONV dynrec_div_word(Bit16u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_div_word(Bit16u op) { - Bitu val=op; - if (val==0) return CPU_PrepareException(0,0); - Bitu num=((Bit32u)reg_dx<<16)|reg_ax; - Bitu quo=num/val; - Bit16u rem=(Bit16u)(num % val); - Bit16u quo16=(Bit16u)(quo&0xffff); - if (quo!=(Bit32u)quo16) return CPU_PrepareException(0,0); - reg_dx=rem; - reg_ax=quo16; - return false; -} - -static bool DRC_CALL_CONV dynrec_idiv_word(Bit16u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_idiv_word(Bit16u op) { - Bits val=(Bit16s)op; - if (val==0) return CPU_PrepareException(0,0); - Bits num=(Bit32s)((reg_dx<<16)|reg_ax); - Bits quo=num/val; - Bit16s rem=(Bit16s)(num % val); - Bit16s quo16s=(Bit16s)quo; - if (quo!=(Bit32s)quo16s) return CPU_PrepareException(0,0); - reg_dx=rem; - reg_ax=quo16s; - return false; -} - -static bool DRC_CALL_CONV dynrec_div_dword(Bit32u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_div_dword(Bit32u op) { - Bitu val=op; - if (val==0) return CPU_PrepareException(0,0); - Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax; - Bit64u quo=num/val; - Bit32u rem=(Bit32u)(num % val); - Bit32u quo32=(Bit32u)(quo&0xffffffff); - if (quo!=(Bit64u)quo32) return CPU_PrepareException(0,0); - reg_edx=rem; - reg_eax=quo32; - return false; -} - -static bool DRC_CALL_CONV dynrec_idiv_dword(Bit32u op) DRC_FC; -static bool DRC_CALL_CONV dynrec_idiv_dword(Bit32u op) { - Bits val=(Bit32s)op; - if (val==0) return CPU_PrepareException(0,0); - Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax; - Bit64s quo=num/val; - Bit32s rem=(Bit32s)(num % val); - Bit32s quo32s=(Bit32s)(quo&0xffffffff); - if (quo!=(Bit64s)quo32s) return CPU_PrepareException(0,0); - reg_edx=rem; - reg_eax=quo32s; - return false; -} - - -static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) { - FillFlagsNoCFOF(); - Bits res=((Bit16s)op1) * ((Bit16s)op2); - if ((res>-32768) && (res<32767)) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } - return (Bit16u)(res & 0xffff); -} - -static Bit32u DRC_CALL_CONV dynrec_dimul_dword(Bit32u op1,Bit32u op2) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_dimul_dword(Bit32u op1,Bit32u op2) { - FillFlagsNoCFOF(); - Bit64s res=((Bit64s)((Bit32s)op1))*((Bit64s)((Bit32s)op2)); - if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) { - SETFLAGBIT(CF,false); - SETFLAGBIT(OF,false); - } else { - SETFLAGBIT(CF,true); - SETFLAGBIT(OF,true); - } - return (Bit32s)res; -} - - - -static Bit16u DRC_CALL_CONV dynrec_cbw(Bit8u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_cbw(Bit8u op) { - return (Bit8s)op; -} - -static Bit32u DRC_CALL_CONV dynrec_cwde(Bit16u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_cwde(Bit16u op) { - return (Bit16s)op; -} - -static Bit16u DRC_CALL_CONV dynrec_cwd(Bit16u op) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_cwd(Bit16u op) { - if (op & 0x8000) return 0xffff; - else return 0; -} - -static Bit32u DRC_CALL_CONV dynrec_cdq(Bit32u op) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_cdq(Bit32u op) { - if (op & 0x80000000) return 0xffffffff; - else return 0; -} - - -static void DRC_CALL_CONV dynrec_sahf(Bit16u op) DRC_FC; -static void DRC_CALL_CONV dynrec_sahf(Bit16u op) { - SETFLAGBIT(OF,get_OF()); - lflags.type=t_UNKNOWN; - CPU_SetFlags(op>>8,FMASK_NORMAL & 0xff); -} - - -static void DRC_CALL_CONV dynrec_cmc(void) DRC_FC; -static void DRC_CALL_CONV dynrec_cmc(void) { - FillFlags(); - SETFLAGBIT(CF,!(reg_flags & FLAG_CF)); -} -static void DRC_CALL_CONV dynrec_clc(void) DRC_FC; -static void DRC_CALL_CONV dynrec_clc(void) { - FillFlags(); - SETFLAGBIT(CF,false); -} -static void DRC_CALL_CONV dynrec_stc(void) DRC_FC; -static void DRC_CALL_CONV dynrec_stc(void) { - FillFlags(); - SETFLAGBIT(CF,true); -} -static void DRC_CALL_CONV dynrec_cld(void) DRC_FC; -static void DRC_CALL_CONV dynrec_cld(void) { - SETFLAGBIT(DF,false); - cpu.direction=1; -} -static void DRC_CALL_CONV dynrec_std(void) DRC_FC; -static void DRC_CALL_CONV dynrec_std(void) { - SETFLAGBIT(DF,true); - cpu.direction=-1; -} - - -static Bit16u DRC_CALL_CONV dynrec_movsb_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_movsb_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - mem_writeb(di_base+reg_di,mem_readb(si_base+reg_si)); - reg_si+=add_index; - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_movsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_movsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - mem_writeb(di_base+reg_edi,mem_readb(si_base+reg_esi)); - reg_esi+=add_index; - reg_edi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_movsw_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_movsw_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - mem_writew(di_base+reg_di,mem_readw(si_base+reg_si)); - reg_si+=add_index; - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_movsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_movsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - mem_writew(di_base+reg_edi,mem_readw(si_base+reg_esi)); - reg_esi+=add_index; - reg_edi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_movsd_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_movsd_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - mem_writed(di_base+reg_di,mem_readd(si_base+reg_si)); - reg_si+=add_index; - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_movsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_movsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - mem_writed(di_base+reg_edi,mem_readd(si_base+reg_esi)); - reg_esi+=add_index; - reg_edi+=add_index; - } - return count_left; -} - - -static Bit16u DRC_CALL_CONV dynrec_lodsb_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_lodsb_word(Bit16u count,Bit16s add_index,PhysPt si_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - reg_al=mem_readb(si_base+reg_si); - reg_si+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_lodsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_lodsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - reg_al=mem_readb(si_base+reg_esi); - reg_esi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_lodsw_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_lodsw_word(Bit16u count,Bit16s add_index,PhysPt si_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - reg_ax=mem_readw(si_base+reg_si); - reg_si+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_lodsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_lodsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - reg_ax=mem_readw(si_base+reg_esi); - reg_esi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_lodsd_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_lodsd_word(Bit16u count,Bit16s add_index,PhysPt si_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - reg_eax=mem_readd(si_base+reg_si); - reg_si+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_lodsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_lodsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - reg_eax=mem_readd(si_base+reg_esi); - reg_esi+=add_index; - } - return count_left; -} - - -static Bit16u DRC_CALL_CONV dynrec_stosb_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_stosb_word(Bit16u count,Bit16s add_index,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - mem_writeb(di_base+reg_di,reg_al); - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_stosb_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_stosb_dword(Bit32u count,Bit32s add_index,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - for (;count>0;count--) { - mem_writeb(di_base+reg_edi,reg_al); - reg_edi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_stosw_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_stosw_word(Bit16u count,Bit16s add_index,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - mem_writew(di_base+reg_di,reg_ax); - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_stosw_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_stosw_dword(Bit32u count,Bit32s add_index,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=1; - for (;count>0;count--) { - mem_writew(di_base+reg_edi,reg_ax); - reg_edi+=add_index; - } - return count_left; -} - -static Bit16u DRC_CALL_CONV dynrec_stosd_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_stosd_word(Bit16u count,Bit16s add_index,PhysPt di_base) { - Bit16u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=(Bit16u)(count-CPU_Cycles); - count=(Bit16u)CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - mem_writed(di_base+reg_di,reg_eax); - reg_di+=add_index; - } - return count_left; -} - -static Bit32u DRC_CALL_CONV dynrec_stosd_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_stosd_dword(Bit32u count,Bit32s add_index,PhysPt di_base) { - Bit32u count_left; - if (count<(Bitu)CPU_Cycles) { - count_left=0; - } else { - count_left=count-CPU_Cycles; - count=CPU_Cycles; - CPU_Cycles=0; - } - add_index<<=2; - for (;count>0;count--) { - mem_writed(di_base+reg_edi,reg_eax); - reg_edi+=add_index; - } - return count_left; -} - - -static void DRC_CALL_CONV dynrec_push_word(Bit16u value) DRC_FC; -static void DRC_CALL_CONV dynrec_push_word(Bit16u value) { - Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-2)&cpu.stack.mask); - mem_writew(SegPhys(ss) + (new_esp & cpu.stack.mask),value); - reg_esp=new_esp; -} - -static void DRC_CALL_CONV dynrec_push_dword(Bit32u value) DRC_FC; -static void DRC_CALL_CONV dynrec_push_dword(Bit32u value) { - Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-4)&cpu.stack.mask); - mem_writed(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value); - reg_esp=new_esp; -} - -static Bit16u DRC_CALL_CONV dynrec_pop_word(void) DRC_FC; -static Bit16u DRC_CALL_CONV dynrec_pop_word(void) { - Bit16u val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask); - return val; -} - -static Bit32u DRC_CALL_CONV dynrec_pop_dword(void) DRC_FC; -static Bit32u DRC_CALL_CONV dynrec_pop_dword(void) { - Bit32u val=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask); - return val; -} diff --git a/src/cpu/core_dynrec/risc_armv4le-common.h b/src/cpu/core_dynrec/risc_armv4le-common.h deleted file mode 100644 index e0efa6a..0000000 --- a/src/cpu/core_dynrec/risc_armv4le-common.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_armv4le-common.h,v 1.2 2008/09/19 16:48:02 c2woody Exp $ */ - - -/* ARMv4 (little endian) backend by M-HT (common data/functions) */ - - -// some configuring defines that specify the capabilities of this architecture -// or aspects of the recompiling - -// protect FC_ADDR over function calls if necessaray -// #define DRC_PROTECT_ADDR_REG - -// try to use non-flags generating functions if possible -#define DRC_FLAGS_INVALIDATION -// try to replace _simple functions by code -#define DRC_FLAGS_INVALIDATION_DCODE - -// type with the same size as a pointer -#define DRC_PTR_SIZE_IM Bit32u - -// calling convention modifier -#define DRC_CALL_CONV /* nothing */ -#define DRC_FC /* nothing */ - -// use FC_REGS_ADDR to hold the address of "cpu_regs" and to access it using FC_REGS_ADDR -#define DRC_USE_REGS_ADDR -// use FC_SEGS_ADDR to hold the address of "Segs" and to access it using FC_SEGS_ADDR -#define DRC_USE_SEGS_ADDR - -// register mapping -typedef Bit8u HostReg; - -// "lo" registers -#define HOST_r0 0 -#define HOST_r1 1 -#define HOST_r2 2 -#define HOST_r3 3 -#define HOST_r4 4 -#define HOST_r5 5 -#define HOST_r6 6 -#define HOST_r7 7 -// "hi" registers -#define HOST_r8 8 -#define HOST_r9 9 -#define HOST_r10 10 -#define HOST_r11 11 -#define HOST_r12 12 -#define HOST_r13 13 -#define HOST_r14 14 -#define HOST_r15 15 - -// register aliases -// "lo" registers -#define HOST_a1 HOST_r0 -#define HOST_a2 HOST_r1 -#define HOST_a3 HOST_r2 -#define HOST_a4 HOST_r3 -#define HOST_v1 HOST_r4 -#define HOST_v2 HOST_r5 -#define HOST_v3 HOST_r6 -#define HOST_v4 HOST_r7 -// "hi" registers -#define HOST_v5 HOST_r8 -#define HOST_v6 HOST_r9 -#define HOST_v7 HOST_r10 -#define HOST_v8 HOST_r11 -#define HOST_ip HOST_r12 -#define HOST_sp HOST_r13 -#define HOST_lr HOST_r14 -#define HOST_pc HOST_r15 - - -static void cache_block_closing(Bit8u* block_start,Bitu block_size) { -// GP2X BEGIN - //flush cache - register unsigned long _beg __asm ("a1") = (unsigned long)(block_start); // block start - register unsigned long _end __asm ("a2") = (unsigned long)(block_start+block_size); // block end - register unsigned long _flg __asm ("a3") = 0; - __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" - : // no outputs - : "r" (_beg), "r" (_end), "r" (_flg) - ); -// GP2X END -} diff --git a/src/cpu/core_dynrec/risc_armv4le-o3.h b/src/cpu/core_dynrec/risc_armv4le-o3.h deleted file mode 100644 index 8c0c37c..0000000 --- a/src/cpu/core_dynrec/risc_armv4le-o3.h +++ /dev/null @@ -1,982 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_armv4le-o3.h,v 1.3 2008/09/19 16:48:02 c2woody Exp $ */ - - -/* ARMv4 (little endian) backend by M-HT (size-tweaked arm version) */ - - -// temporary registers -#define temp1 HOST_ip -#define temp2 HOST_v5 -#define temp3 HOST_v4 - -// register that holds function return values -#define FC_RETOP HOST_v3 - -// register used for address calculations, -#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a1 - -// register that holds the second parameter -#define FC_OP2 HOST_a2 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_a2 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_v2 - -#ifdef DRC_USE_REGS_ADDR -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_v7 -#endif - -#ifdef DRC_USE_SEGS_ADDR -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_v8 -#endif - -// helper macro -#define ROTATE_SCALE(x) ( (x)?(32 - x):(0) ) - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_addd(0xe1a00000 + (reg_dst << 12) + reg_src); // mov reg_dst, reg_src -} - -// helper function -static Bits get_imm_gen_len(Bit32u imm) { - Bits ret; - if (imm == 0) { - return 1; - } else { - ret = 0; - while (imm) { - while ((imm & 3) == 0) { - imm>>=2; - } - ret++; - imm>>=8; - } - return ret; - } -} - -// helper function -static Bits get_method_imm_gen_len(Bit32u imm, Bits preffer00, Bits *num) { - Bits num00, num15, numadd, numsub, numret, ret; - num00 = get_imm_gen_len(imm); - num15 = get_imm_gen_len(~imm); - numadd = get_imm_gen_len(imm - ((Bit32u)cache.pos+8)); - numsub = get_imm_gen_len(((Bit32u)cache.pos+8) - imm); - if (numsub < numadd && numsub < num00 && numsub < num15) { - ret = 0; - numret = numsub; - } else if (numadd < num00 && numadd < num15) { - ret = 1; - numret = numadd; - } else if (num00 < num15 || (num00 == num15 && preffer00)) { - ret = 2; - numret = num00; - } else { - ret = 3; - numret = num15; - } - if (num != NULL) *num = numret; - return ret; -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - Bits first, method, scale; - Bit32u imm2, dist; - if (imm == 0) { - cache_addd(0xe3a00000 + (dest_reg << 12)); // mov dest_reg, #0 - } else if (imm == 0xffffffff) { - cache_addd(0xe3e00000 + (dest_reg << 12)); // mvn dest_reg, #0 - } else { - method = get_method_imm_gen_len(imm, 1, NULL); - - scale = 0; - first = 1; - if (method == 0) { - dist = ((Bit32u)cache.pos+8) - imm; - while (dist) { - while ((dist & 3) == 0) { - dist>>=2; - scale+=2; - } - if (first) { - cache_addd(0xe2400000 + (dest_reg << 12) + (HOST_pc << 16) + (ROTATE_SCALE(scale) << 7) + (dist & 0xff)); // sub dest_reg, pc, #((dist & 0xff) << scale) - first = 0; - } else { - cache_addd(0xe2400000 + (dest_reg << 12) + (dest_reg << 16) + (ROTATE_SCALE(scale) << 7) + (dist & 0xff)); // sub dest_reg, dest_reg, #((dist & 0xff) << scale) - } - dist>>=8; - scale+=8; - } - } else if (method == 1) { - dist = imm - ((Bit32u)cache.pos+8); - if (dist == 0) { - cache_addd(0xe1a00000 + (dest_reg << 12) + HOST_pc); // mov dest_reg, pc - } else { - while (dist) { - while ((dist & 3) == 0) { - dist>>=2; - scale+=2; - } - if (first) { - cache_addd(0xe2800000 + (dest_reg << 12) + (HOST_pc << 16) + (ROTATE_SCALE(scale) << 7) + (dist & 0xff)); // add dest_reg, pc, #((dist & 0xff) << scale) - first = 0; - } else { - cache_addd(0xe2800000 + (dest_reg << 12) + (dest_reg << 16) + (ROTATE_SCALE(scale) << 7) + (dist & 0xff)); // add dest_reg, dest_reg, #((dist & 0xff) << scale) - } - dist>>=8; - scale+=8; - } - } - } else if (method == 2) { - while (imm) { - while ((imm & 3) == 0) { - imm>>=2; - scale+=2; - } - if (first) { - cache_addd(0xe3a00000 + (dest_reg << 12) + (ROTATE_SCALE(scale) << 7) + (imm & 0xff)); // mov dest_reg, #((imm & 0xff) << scale) - first = 0; - } else { - cache_addd(0xe3800000 + (dest_reg << 12) + (dest_reg << 16) + (ROTATE_SCALE(scale) << 7) + (imm & 0xff)); // orr dest_reg, dest_reg, #((imm & 0xff) << scale) - } - imm>>=8; - scale+=8; - } - } else { - imm2 = ~imm; - while (imm2) { - while ((imm2 & 3) == 0) { - imm2>>=2; - scale+=2; - } - if (first) { - cache_addd(0xe3e00000 + (dest_reg << 12) + (ROTATE_SCALE(scale) << 7) + (imm2 & 0xff)); // mvn dest_reg, #((imm2 & 0xff) << scale) - first = 0; - } else { - cache_addd(0xe3c00000 + (dest_reg << 12) + (dest_reg << 16) + (ROTATE_SCALE(scale) << 7) + (imm2 & 0xff)); // bic dest_reg, dest_reg, #((imm2 & 0xff) << scale) - } - imm2>>=8; - scale+=8; - } - } - } -} - -// helper function for gen_mov_word_to_reg -static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)data & 3) { - if ( ((Bit32u)data & 3) == 2 ) { - cache_addd(0xe1d000b0 + (dest_reg << 12) + (data_reg << 16)); // ldrh dest_reg, [data_reg] - cache_addd(0xe1d000b2 + (temp2 << 12) + (data_reg << 16)); // ldrh temp2, [data_reg, #2] - cache_addd(0xe1800800 + (dest_reg << 12) + (dest_reg << 16) + (temp2)); // orr dest_reg, dest_reg, temp2, lsl #16 - } else { - cache_addd(0xe5d00000 + (dest_reg << 12) + (data_reg << 16)); // ldrb dest_reg, [data_reg] - cache_addd(0xe1d000b1 + (temp2 << 12) + (data_reg << 16)); // ldrh temp2, [data_reg, #1] - cache_addd(0xe1800400 + (dest_reg << 12) + (dest_reg << 16) + (temp2)); // orr dest_reg, dest_reg, temp2, lsl #8 - cache_addd(0xe5d00003 + (temp2 << 12) + (data_reg << 16)); // ldrb temp2, [data_reg, #3] - cache_addd(0xe1800c00 + (dest_reg << 12) + (dest_reg << 16) + (temp2)); // orr dest_reg, dest_reg, temp2, lsl #24 - } - } else { - cache_addd(0xe5900000 + (dest_reg << 12) + (data_reg << 16)); // ldr dest_reg, [data_reg] - } - } else { - if ((Bit32u)data & 1) { - cache_addd(0xe5d00000 + (dest_reg << 12) + (data_reg << 16)); // ldrb dest_reg, [data_reg] - cache_addd(0xe5d00001 + (temp2 << 12) + (data_reg << 16)); // ldrb temp2, [data_reg, #1] - cache_addd(0xe1800400 + (dest_reg << 12) + (dest_reg << 16) + (temp2)); // orr dest_reg, dest_reg, temp2, lsl #8 - } else { - cache_addd(0xe1d000b0 + (dest_reg << 12) + (data_reg << 16)); // ldrh dest_reg, [data_reg] - } - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)data); - gen_mov_word_to_reg_helper(dest_reg, data, dword, temp1); -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - Bits first, scale; - Bit32u imm2; - if (imm == 0) { - cache_addd(0xe3a00000 + (dest_reg << 12)); // mov dest_reg, #0 - } else { - scale = 0; - first = 1; - imm2 = (Bit32u)imm; - while (imm2) { - while ((imm2 & 3) == 0) { - imm2>>=2; - scale+=2; - } - if (first) { - cache_addd(0xe3a00000 + (dest_reg << 12) + (ROTATE_SCALE(scale) << 7) + (imm2 & 0xff)); // mov dest_reg, #((imm2 & 0xff) << scale) - first = 0; - } else { - cache_addd(0xe3800000 + (dest_reg << 12) + (dest_reg << 16) + (ROTATE_SCALE(scale) << 7) + (imm2 & 0xff)); // orr dest_reg, dest_reg, #((imm2 & 0xff) << scale) - } - imm2>>=8; - scale+=8; - } - } -} - -// helper function for gen_mov_word_from_reg -static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)dest & 3) { - if ( ((Bit32u)dest & 3) == 2 ) { - cache_addd(0xe1c000b0 + (src_reg << 12) + (data_reg << 16)); // strh src_reg, [data_reg] - cache_addd(0xe1a00820 + (temp2 << 12) + (src_reg)); // mov temp2, src_reg, lsr #16 - cache_addd(0xe1c000b2 + (temp2 << 12) + (data_reg << 16)); // strh temp2, [data_reg, #2] - } else { - cache_addd(0xe5c00000 + (src_reg << 12) + (data_reg << 16)); // strb src_reg, [data_reg] - cache_addd(0xe1a00420 + (temp2 << 12) + (src_reg)); // mov temp2, src_reg, lsr #8 - cache_addd(0xe1c000b1 + (temp2 << 12) + (data_reg << 16)); // strh temp2, [data_reg, #1] - cache_addd(0xe1a00820 + (temp2 << 12) + (temp2)); // mov temp2, temp2, lsr #16 - cache_addd(0xe5c00003 + (temp2 << 12) + (data_reg << 16)); // strb temp2, [data_reg, #3] - } - } else { - cache_addd(0xe5800000 + (src_reg << 12) + (data_reg << 16)); // str src_reg, [data_reg] - } - } else { - if ((Bit32u)dest & 1) { - cache_addd(0xe5c00000 + (src_reg << 12) + (data_reg << 16)); // strb src_reg, [data_reg] - cache_addd(0xe1a00420 + (temp2 << 12) + (src_reg)); // mov temp2, src_reg, lsr #8 - cache_addd(0xe5c00001 + (temp2 << 12) + (data_reg << 16)); // strb temp2, [data_reg, #1] - } else { - cache_addd(0xe1c000b0 + (src_reg << 12) + (data_reg << 16)); // strh src_reg, [data_reg] - } - } -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_from_reg_helper(src_reg, dest, dword, temp1); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)data); - cache_addd(0xe5d00000 + (dest_reg << 12) + (temp1 << 16)); // ldrb dest_reg, [temp1] -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_addd(0xe3a00000 + (dest_reg << 12) + (imm)); // mov dest_reg, #(imm) -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - cache_addd(0xe5c00000 + (src_reg << 12) + (temp1 << 16)); // strb src_reg, [temp1] -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - if (sign) { - cache_addd(0xe1a00c00 + (reg << 12) + (reg)); // mov reg, reg, lsl #24 - cache_addd(0xe1a00c40 + (reg << 12) + (reg)); // mov reg, reg, asr #24 - } else { - cache_addd(0xe20000ff + (reg << 12) + (reg << 16)); // and reg, reg, #0xff - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - if (sign) { - cache_addd(0xe1a00800 + (reg << 12) + (reg)); // mov reg, reg, lsl #16 - cache_addd(0xe1a00840 + (reg << 12) + (reg)); // mov reg, reg, asr #16 - } else { - cache_addd(0xe1a00800 + (reg << 12) + (reg)); // mov reg, reg, lsl #16 - cache_addd(0xe1a00820 + (reg << 12) + (reg)); // mov reg, reg, lsr #16 - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - gen_mov_word_to_reg(temp3, op, 1); - cache_addd(0xe0800000 + (reg << 12) + (reg << 16) + (temp3)); // add reg, reg, temp3 -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - Bits method1, method2, num1, num2, scale, sub; - if(!imm) return; - if (imm == 1) { - cache_addd(0xe2800001 + (reg << 12) + (reg << 16)); // add reg, reg, #1 - } else if (imm == 0xffffffff) { - cache_addd(0xe2400001 + (reg << 12) + (reg << 16)); // sub reg, reg, #1 - } else { - method1 = get_method_imm_gen_len(imm, 1, &num1); - method2 = get_method_imm_gen_len(-((Bit32s)imm), 1, &num2); - if (num2 < num1) { - method1 = method2; - imm = (Bit32u)(-((Bit32s)imm)); - sub = 1; - } else sub = 0; - - if (method1 != 2) { - gen_mov_dword_to_reg_imm(temp3, imm); - if (sub) { - cache_addd(0xe0400000 + (reg << 12) + (reg << 16) + (temp3)); // sub reg, reg, temp3 - } else { - cache_addd(0xe0800000 + (reg << 12) + (reg << 16) + (temp3)); // add reg, reg, temp3 - } - } else { - scale = 0; - while (imm) { - while ((imm & 3) == 0) { - imm>>=2; - scale+=2; - } - if (sub) { - cache_addd(0xe2400000 + (reg << 12) + (reg << 16) + (ROTATE_SCALE(scale) << 7) + (imm & 0xff)); // sub reg, reg, #((imm & 0xff) << scale) - } else { - cache_addd(0xe2800000 + (reg << 12) + (reg << 16) + (ROTATE_SCALE(scale) << 7) + (imm & 0xff)); // add reg, reg, #((imm & 0xff) << scale) - } - imm>>=8; - scale+=8; - } - } - } -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - Bits method, scale; - Bit32u imm2; - imm2 = ~imm; - if(!imm2) return; - if (!imm) { - cache_addd(0xe3a00000 + (reg << 12)); // mov reg, #0 - } else { - method = get_method_imm_gen_len(imm, 0, NULL); - if (method != 3) { - gen_mov_dword_to_reg_imm(temp3, imm); - cache_addd(0xe0000000 + (reg << 12) + (reg << 16) + (temp3)); // and reg, reg, temp3 - } else { - scale = 0; - while (imm2) { - while ((imm2 & 3) == 0) { - imm2>>=2; - scale+=2; - } - cache_addd(0xe3c00000 + (reg << 12) + (reg << 16) + (ROTATE_SCALE(scale) << 7) + (imm2 & 0xff)); // bic reg, reg, #((imm2 & 0xff) << scale) - imm2>>=8; - scale+=8; - } - } - } -} - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - gen_mov_dword_to_reg_imm(temp3, imm); - gen_mov_word_from_reg(temp3, dest, 1); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add an 8bit constant value to a dword memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, 1, temp1); - if (imm >= 0) { - cache_addd(0xe2800000 + (temp3 << 12) + (temp3 << 16) + ((Bit32s)imm)); // add temp3, temp3, #(imm) - } else { - cache_addd(0xe2400000 + (temp3 << 12) + (temp3 << 16) + (-((Bit32s)imm))); // sub temp3, temp3, #(-imm) - } - gen_mov_word_from_reg_helper(temp3, dest, 1, temp1); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_add_direct_byte(dest,(Bit8s)imm); - return; - } - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, dword, temp1); - // maybe use function gen_add_imm - if (dword) { - gen_mov_dword_to_reg_imm(temp2, imm); - } else { - gen_mov_word_to_reg_imm(temp2, (Bit16u)imm); - } - cache_addd(0xe0800000 + (temp3 << 12) + (temp3 << 16) + (temp2)); // add temp3, temp3, temp2 - gen_mov_word_from_reg_helper(temp3, dest, dword, temp1); -} - -// subtract an 8bit constant value from a dword memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, 1, temp1); - if (imm >= 0) { - cache_addd(0xe2400000 + (temp3 << 12) + (temp3 << 16) + ((Bit32s)imm)); // sub temp3, temp3, #(imm) - } else { - cache_addd(0xe2800000 + (temp3 << 12) + (temp3 << 16) + (-((Bit32s)imm))); // add temp3, temp3, #(-imm) - } - gen_mov_word_from_reg_helper(temp3, dest, 1, temp1); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_sub_direct_byte(dest,(Bit8s)imm); - return; - } - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, dword, temp1); - // maybe use function gen_add_imm/gen_sub_imm - if (dword) { - gen_mov_dword_to_reg_imm(temp2, imm); - } else { - gen_mov_word_to_reg_imm(temp2, (Bit16u)imm); - } - cache_addd(0xe0400000 + (temp3 << 12) + (temp3 << 16) + (temp2)); // sub temp3, temp3, temp2 - gen_mov_word_from_reg_helper(temp3, dest, dword, temp1); -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - cache_addd(0xe0800000 + (dest_reg << 12) + (dest_reg << 16) + (scale_reg) + (scale << 7)); // add dest_reg, dest_reg, scale_reg, lsl #(scale) - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addd(0xe1a00000 + (dest_reg << 12) + (dest_reg) + (scale << 7)); // mov dest_reg, dest_reg, lsl #(scale) - } - gen_add_imm(dest_reg, imm); -} - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_addd(0xe5900004 + (temp1 << 12) + (HOST_pc << 16)); // ldr temp1, [pc, #4] - cache_addd(0xe2800004 + (HOST_lr << 12) + (HOST_pc << 16)); // add lr, pc, #4 - cache_addd(0xe12fff10 + (temp1)); // bx temp1 - cache_addd((Bit32u)func); // .int func - cache_addd(0xe1a00000 + (FC_RETOP << 12) + HOST_a1); // mov FC_RETOP, a1 -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_raw(func); - return proc_addr; -} - -#if (1) -// max of 4 parameters in a1-a4 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param, (void *)mem, 1); -} -#else - other arm abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - Bits num1, num2, scale, sub; - Bitu imm2; - gen_mov_word_to_reg(temp3, ptr, 1); - - if (imm) { - num1 = get_imm_gen_len(imm); - num2 = get_imm_gen_len(-imm); - - if (num2 < num1) { - imm = -imm; - sub = 1; - } else sub = 0; - - scale = 0; - imm2 = (Bitu)imm; - while (imm2) { - while ((imm2 & 3) == 0) { - imm2>>=2; - scale+=2; - } - if (sub) { - cache_addd(0xe2400000 + (temp3 << 12) + (temp3 << 16) + (ROTATE_SCALE(scale) << 7) + (imm2 & 0xff)); // sub temp3, temp3, #((imm2 & 0xff) << scale) - } else { - cache_addd(0xe2800000 + (temp3 << 12) + (temp3 << 16) + (ROTATE_SCALE(scale) << 7) + (imm2 & 0xff)); // add temp3, temp3, #((imm2 & 0xff) << scale) - } - imm2>>=8; - scale+=8; - } - } - -#if (1) -// (*ptr) should be word aligned - if ((imm & 0x03) == 0) { - cache_addd(0xe5900000 + (temp1 << 12) + (temp3 << 16)); // ldr temp1, [temp3] - } else -#endif - { - cache_addd(0xe5d00000 + (temp1 << 12) + (temp3 << 16)); // ldrb temp1, [temp3] - cache_addd(0xe5d00001 + (temp2 << 12) + (temp3 << 16)); // ldrb temp2, [temp3, #1] - cache_addd(0xe1800400 + (temp1 << 12) + (temp1 << 16) + (temp2)); // orr temp1, temp1, temp2, lsl #8 - cache_addd(0xe5d00002 + (temp2 << 12) + (temp3 << 16)); // ldrb temp2, [temp3, #2] - cache_addd(0xe1800800 + (temp1 << 12) + (temp1 << 16) + (temp2)); // orr temp1, temp1, temp2, lsl #16 - cache_addd(0xe5d00003 + (temp2 << 12) + (temp3 << 16)); // ldrb temp2, [temp3, #3] - cache_addd(0xe1800c00 + (temp1 << 12) + (temp1 << 16) + (temp2)); // orr temp1, temp1, temp2, lsl #24 - } - - cache_addd(0xe12fff10 + (temp1)); // bx temp1 -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - if (dword) { - cache_addd(0xe3500000 + (reg << 16)); // cmp reg, #0 - } else { - cache_addd(0xe1b00800 + (temp1 << 12) + (reg)); // movs temp1, reg, lsl #16 - } - cache_addd(0x0a000000); // beq j - return ((Bit32u)cache.pos-4); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - if (dword) { - cache_addd(0xe3500000 + (reg << 16)); // cmp reg, #0 - } else { - cache_addd(0xe1b00800 + (temp1 << 12) + (reg)); // movs temp1, reg, lsl #16 - } - cache_addd(0x1a000000); // bne j - return ((Bit32u)cache.pos-4); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-(data+8); - if (len<0) len=-len; - if (len>0x02000000) LOG_MSG("Big jump %d",len); -#endif - *(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff ); -} - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - if (isdword) { - cache_addd(0xe3500000 + (reg << 16)); // cmp reg, #0 - } else { - cache_addd(0xe31000ff + (reg << 16)); // tst reg, #0xff - } - cache_addd(0x0a000002); // beq nobranch - cache_addd(0xe5900000 + (temp1 << 12) + (HOST_pc << 16)); // ldr temp1, [pc, #0] - cache_addd(0xe12fff10 + (temp1)); // bx temp1 - cache_addd(0); // fill j - // nobranch: - return ((Bit32u)cache.pos-4); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - cache_addd(0xe3500000 + (reg << 16)); // cmp reg, #0 - cache_addd(0xca000002); // bgt nobranch - cache_addd(0xe5900000 + (temp1 << 12) + (HOST_pc << 16)); // ldr temp1, [pc, #0] - cache_addd(0xe12fff10 + (temp1)); // bx temp1 - cache_addd(0); // fill j - // nobranch: - return ((Bit32u)cache.pos-4); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - // this is an absolute branch - *(Bit32u*)data=(Bit32u)cache.pos; -} - -static void gen_run_code(void) { - cache_addd(0xe92d4000); // stmfd sp!, {lr} - cache_addd(0xe92d0df0); // stmfd sp!, {v1-v5,v7,v8} - - // adr: 8 - cache_addd(0xe5900000 + (FC_SEGS_ADDR << 12) + (HOST_pc << 16) + (64 - (8 + 8))); // ldr FC_SEGS_ADDR, [pc, #(&Segs)] - // adr: 12 - cache_addd(0xe5900000 + (FC_REGS_ADDR << 12) + (HOST_pc << 16) + (68 - (12 + 8))); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)] - cache_addd(0xe28fe004); // add lr, pc, #4 - cache_addd(0xe92d4000); // stmfd sp!, {lr} - cache_addd(0xe12fff10); // bx r0 - cache_addd(0xe8bd0df0); // ldmfd sp!, {v1-v5,v7,v8} - - cache_addd(0xe8bd4000); // ldmfd sp!, {lr} - cache_addd(0xe12fff1e); // bx lr - // fill up to 64 bytes - cache_addd(0xe1a00000); // nop - cache_addd(0xe1a00000); // nop - cache_addd(0xe1a00000); // nop - cache_addd(0xe1a00000); // nop - cache_addd(0xe1a00000); // nop - cache_addd(0xe1a00000); // nop - - // adr: 64 - cache_addd((Bit32u)&Segs); // address of "Segs" - // adr: 68 - cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs" -} - -// return from a function -static void gen_return_function(void) { - cache_addd(0xe1a00000 + (HOST_a1 << 12) + FC_RETOP); // mov a1, FC_RETOP - cache_addd(0xe8bd4000); // ldmfd sp!, {lr} - cache_addd(0xe12fff1e); // bx lr -} - -#ifdef DRC_FLAGS_INVALIDATION - -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit32u*)pos=0xe0800000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (HOST_a2); // add FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit32u*)pos=0xe1800000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (HOST_a2); // orr FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit32u*)pos=0xe0000000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (HOST_a2); // and FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit32u*)pos=0xe0400000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (HOST_a2); // sub FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit32u*)pos=0xe0200000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (HOST_a2); // eor FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit32u*)pos=0xea000000 + (3); // b (pc+3*4) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit32u*)pos=0xe2800000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (1); // add FC_RETOP, a1, #1 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit32u*)pos=0xe2400000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (1); // sub FC_RETOP, a1, #1 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit32u*)pos=0xe1a00010 + (FC_RETOP << 12) + (HOST_a1) + (HOST_a2 << 8); // mov FC_RETOP, a1, lsl a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_SHRb: - *(Bit32u*)pos=0xe2000000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (0xff); // and FC_RETOP, a1, #0xff - *(Bit32u*)(pos+4)=0xe1a00030 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, lsr a2 - *(Bit32u*)(pos+8)=0xe1a00000; // nop - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_SHRw: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (16 << 7); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=0xe1a00020 + (FC_RETOP << 12) + (FC_RETOP) + (16 << 7); // mov FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+8)=0xe1a00030 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, lsr a2 - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_SHRd: - *(Bit32u*)pos=0xe1a00030 + (FC_RETOP << 12) + (HOST_a1) + (HOST_a2 << 8); // mov FC_RETOP, a1, lsr a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_SARb: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (24 << 7); // mov FC_RETOP, a1, lsl #24 - *(Bit32u*)(pos+4)=0xe1a00040 + (FC_RETOP << 12) + (FC_RETOP) + (24 << 7); // mov FC_RETOP, FC_RETOP, asr #24 - *(Bit32u*)(pos+8)=0xe1a00050 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, asr a2 - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_SARw: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (16 << 7); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=0xe1a00040 + (FC_RETOP << 12) + (FC_RETOP) + (16 << 7); // mov FC_RETOP, FC_RETOP, asr #16 - *(Bit32u*)(pos+8)=0xe1a00050 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, asr a2 - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_SARd: - *(Bit32u*)pos=0xe1a00050 + (FC_RETOP << 12) + (HOST_a1) + (HOST_a2 << 8); // mov FC_RETOP, a1, asr a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_RORb: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (24 << 7); // mov FC_RETOP, a1, lsl #24 - *(Bit32u*)(pos+4)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (8 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #8 - *(Bit32u*)(pos+8)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (16 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+12)=0xe1a00070 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, ror a2 - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_RORw: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (16 << 7); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (16 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+8)=0xe1a00070 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, ror a2 - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_RORd: - *(Bit32u*)pos=0xe1a00070 + (FC_RETOP << 12) + (HOST_a1) + (HOST_a2 << 8); // mov FC_RETOP, a1, ror a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_ROLb: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (24 << 7); // mov FC_RETOP, a1, lsl #24 - *(Bit32u*)(pos+4)=0xe2600000 + (HOST_a2 << 12) + (HOST_a2 << 16) + (32); // rsb a2, a2, #32 - *(Bit32u*)(pos+8)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (8 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #8 - *(Bit32u*)(pos+12)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (16 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+16)=0xe1a00070 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, ror a2 - break; - case t_ROLw: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (16 << 7); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=0xe2600000 + (HOST_a2 << 12) + (HOST_a2 << 16) + (32); // rsb a2, a2, #32 - *(Bit32u*)(pos+8)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (16 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+12)=0xe1a00070 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, ror a2 - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_ROLd: - *(Bit32u*)pos=0xe2600000 + (HOST_a2 << 12) + (HOST_a2 << 16) + (32); // rsb a2, a2, #32 - *(Bit32u*)(pos+4)=0xe1a00070 + (FC_RETOP << 12) + (HOST_a1) + (HOST_a2 << 8); // mov FC_RETOP, a1, ror a2 - *(Bit32u*)(pos+8)=0xe1a00000; // nop - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit32u*)pos=0xe2600000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (0); // rsb FC_RETOP, a1, #0 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - default: - *(Bit32u*)(pos+12)=(Bit32u)fct_ptr; // simple_func - break; - - } -#else - *(Bit32u*)(pos+12)=(Bit32u)fct_ptr; // simple_func -#endif -} -#endif - -static void cache_block_before_close(void) { } - - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { - cache_addd(0xe1d000b0 + (dest_reg << 12) + (FC_SEGS_ADDR << 16) + ((index & 0xf0) << 4) + (index & 0x0f)); // ldrh dest_reg, [FC_SEGS_ADDR, #index] -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { - cache_addd(0xe5900000 + (dest_reg << 12) + (FC_SEGS_ADDR << 16) + (index)); // ldr dest_reg, [FC_SEGS_ADDR, #index] -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { - cache_addd(0xe5900000 + (temp1 << 12) + (FC_SEGS_ADDR << 16) + (index)); // ldr temp1, [FC_SEGS_ADDR, #index] - cache_addd(0xe0800000 + (reg << 12) + (reg << 16) + (temp1)); // add reg, reg, temp1 -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { - cache_addd(0xe1d000b0 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + ((index & 0xf0) << 4) + (index & 0x0f)); // ldrh dest_reg, [FC_REGS_ADDR, #index] -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { - cache_addd(0xe5900000 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // ldr dest_reg, [FC_REGS_ADDR, #index] -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { - if (dword) { - cache_addd(0xe5900000 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // ldr dest_reg, [FC_REGS_ADDR, #index] - } else { - cache_addd(0xe1d000b0 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + ((index & 0xf0) << 4) + (index & 0x0f)); // ldrh dest_reg, [FC_REGS_ADDR, #index] - } -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { - cache_addd(0xe5d00000 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // ldrb dest_reg, [FC_REGS_ADDR, #index] -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { - cache_addd(0xe5d00000 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // ldrb dest_reg, [FC_REGS_ADDR, #index] -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { - cache_addd(0xe5900000 + (temp2 << 12) + (FC_REGS_ADDR << 16) + (index)); // ldr temp2, [FC_REGS_ADDR, #index] - cache_addd(0xe0800000 + (reg << 12) + (reg << 16) + (temp2)); // add reg, reg, temp2 -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { - cache_addd(0xe1c000b0 + (src_reg << 12) + (FC_REGS_ADDR << 16) + ((index & 0xf0) << 4) + (index & 0x0f)); // strh src_reg, [FC_REGS_ADDR, #index] -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { - cache_addd(0xe5800000 + (src_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // str src_reg, [FC_REGS_ADDR, #index] -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { - if (dword) { - cache_addd(0xe5800000 + (src_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // str src_reg, [FC_REGS_ADDR, #index] - } else { - cache_addd(0xe1c000b0 + (src_reg << 12) + (FC_REGS_ADDR << 16) + ((index & 0xf0) << 4) + (index & 0x0f)); // strh src_reg, [FC_REGS_ADDR, #index] - } -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { - cache_addd(0xe5c00000 + (src_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // strb src_reg, [FC_REGS_ADDR, #index] -} - -#endif diff --git a/src/cpu/core_dynrec/risc_armv4le-s3.h b/src/cpu/core_dynrec/risc_armv4le-s3.h deleted file mode 100644 index 42f6a01..0000000 --- a/src/cpu/core_dynrec/risc_armv4le-s3.h +++ /dev/null @@ -1,817 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_armv4le-s3.h,v 1.3 2008/09/19 16:48:02 c2woody Exp $ */ - - -/* ARMv4 (little endian) backend by M-HT (speed-tweaked arm version) */ - - -// temporary registers -#define temp1 HOST_ip -#define temp2 HOST_v5 -#define temp3 HOST_v4 - -// register that holds function return values -#define FC_RETOP HOST_v3 - -// register used for address calculations, -#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a1 - -// register that holds the second parameter -#define FC_OP2 HOST_a2 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_a2 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_v2 - -#ifdef DRC_USE_REGS_ADDR -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_v7 -#endif - -#ifdef DRC_USE_SEGS_ADDR -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_v8 -#endif - -// helper macro -#define ROTATE_SCALE(x) ( (x)?(32 - x):(0) ) - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_addd(0xe1a00000 + (reg_dst << 12) + reg_src); // mov reg_dst, reg_src -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - Bits first, scale; - if (imm == 0) { - cache_addd(0xe3a00000 + (dest_reg << 12)); // mov dest_reg, #0 - } else { - scale = 0; - first = 1; - while (imm) { - while ((imm & 3) == 0) { - imm>>=2; - scale+=2; - } - if (first) { - cache_addd(0xe3a00000 + (dest_reg << 12) + (ROTATE_SCALE(scale) << 7) + (imm & 0xff)); // mov dest_reg, #((imm & 0xff) << scale) - first = 0; - } else { - cache_addd(0xe3800000 + (dest_reg << 12) + (dest_reg << 16) + (ROTATE_SCALE(scale) << 7) + (imm & 0xff)); // orr dest_reg, dest_reg, #((imm & 0xff) << scale) - } - imm>>=8; - scale+=8; - } - } -} - -// helper function for gen_mov_word_to_reg -static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)data & 3) { - if ( ((Bit32u)data & 3) == 2 ) { - cache_addd(0xe1d000b0 + (dest_reg << 12) + (data_reg << 16)); // ldrh dest_reg, [data_reg] - cache_addd(0xe1d000b2 + (temp2 << 12) + (data_reg << 16)); // ldrh temp2, [data_reg, #2] - cache_addd(0xe1800800 + (dest_reg << 12) + (dest_reg << 16) + (temp2)); // orr dest_reg, dest_reg, temp2, lsl #16 - } else { - cache_addd(0xe5d00000 + (dest_reg << 12) + (data_reg << 16)); // ldrb dest_reg, [data_reg] - cache_addd(0xe1d000b1 + (temp2 << 12) + (data_reg << 16)); // ldrh temp2, [data_reg, #1] - cache_addd(0xe1800400 + (dest_reg << 12) + (dest_reg << 16) + (temp2)); // orr dest_reg, dest_reg, temp2, lsl #8 - cache_addd(0xe5d00003 + (temp2 << 12) + (data_reg << 16)); // ldrb temp2, [data_reg, #3] - cache_addd(0xe1800c00 + (dest_reg << 12) + (dest_reg << 16) + (temp2)); // orr dest_reg, dest_reg, temp2, lsl #24 - } - } else { - cache_addd(0xe5900000 + (dest_reg << 12) + (data_reg << 16)); // ldr dest_reg, [data_reg] - } - } else { - if ((Bit32u)data & 1) { - cache_addd(0xe5d00000 + (dest_reg << 12) + (data_reg << 16)); // ldrb dest_reg, [data_reg] - cache_addd(0xe5d00001 + (temp2 << 12) + (data_reg << 16)); // ldrb temp2, [data_reg, #1] - cache_addd(0xe1800400 + (dest_reg << 12) + (dest_reg << 16) + (temp2)); // orr dest_reg, dest_reg, temp2, lsl #8 - } else { - cache_addd(0xe1d000b0 + (dest_reg << 12) + (data_reg << 16)); // ldrh dest_reg, [data_reg] - } - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)data); - gen_mov_word_to_reg_helper(dest_reg, data, dword, temp1); -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm); -} - -// helper function for gen_mov_word_from_reg -static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)dest & 3) { - if ( ((Bit32u)dest & 3) == 2 ) { - cache_addd(0xe1c000b0 + (src_reg << 12) + (data_reg << 16)); // strh src_reg, [data_reg] - cache_addd(0xe1a00820 + (temp2 << 12) + (src_reg)); // mov temp2, src_reg, lsr #16 - cache_addd(0xe1c000b2 + (temp2 << 12) + (data_reg << 16)); // strh temp2, [data_reg, #2] - } else { - cache_addd(0xe5c00000 + (src_reg << 12) + (data_reg << 16)); // strb src_reg, [data_reg] - cache_addd(0xe1a00420 + (temp2 << 12) + (src_reg)); // mov temp2, src_reg, lsr #8 - cache_addd(0xe1c000b1 + (temp2 << 12) + (data_reg << 16)); // strh temp2, [data_reg, #1] - cache_addd(0xe1a00820 + (temp2 << 12) + (temp2)); // mov temp2, temp2, lsr #16 - cache_addd(0xe5c00003 + (temp2 << 12) + (data_reg << 16)); // strb temp2, [data_reg, #3] - } - } else { - cache_addd(0xe5800000 + (src_reg << 12) + (data_reg << 16)); // str src_reg, [data_reg] - } - } else { - if ((Bit32u)dest & 1) { - cache_addd(0xe5c00000 + (src_reg << 12) + (data_reg << 16)); // strb src_reg, [data_reg] - cache_addd(0xe1a00420 + (temp2 << 12) + (src_reg)); // mov temp2, src_reg, lsr #8 - cache_addd(0xe5c00001 + (temp2 << 12) + (data_reg << 16)); // strb temp2, [data_reg, #1] - } else { - cache_addd(0xe1c000b0 + (src_reg << 12) + (data_reg << 16)); // strh src_reg, [data_reg] - } - } -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_from_reg_helper(src_reg, dest, dword, temp1); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)data); - cache_addd(0xe5d00000 + (dest_reg << 12) + (temp1 << 16)); // ldrb dest_reg, [temp1] -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_addd(0xe3a00000 + (dest_reg << 12) + (imm)); // mov dest_reg, #(imm) -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - cache_addd(0xe5c00000 + (src_reg << 12) + (temp1 << 16)); // strb src_reg, [temp1] -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - if (sign) { - cache_addd(0xe1a00c00 + (reg << 12) + (reg)); // mov reg, reg, lsl #24 - cache_addd(0xe1a00c40 + (reg << 12) + (reg)); // mov reg, reg, asr #24 - } else { - cache_addd(0xe20000ff + (reg << 12) + (reg << 16)); // and reg, reg, #0xff - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - if (sign) { - cache_addd(0xe1a00800 + (reg << 12) + (reg)); // mov reg, reg, lsl #16 - cache_addd(0xe1a00840 + (reg << 12) + (reg)); // mov reg, reg, asr #16 - } else { - cache_addd(0xe1a00800 + (reg << 12) + (reg)); // mov reg, reg, lsl #16 - cache_addd(0xe1a00820 + (reg << 12) + (reg)); // mov reg, reg, lsr #16 - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - gen_mov_word_to_reg(temp3, op, 1); - cache_addd(0xe0800000 + (reg << 12) + (reg << 16) + (temp3)); // add reg, reg, temp3 -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - Bits scale; - if(!imm) return; - if (imm == 0xffffffff) { - cache_addd(0xe2400001 + (reg << 12) + (reg << 16)); // sub reg, reg, #1 - } else { - scale = 0; - while (imm) { - while ((imm & 3) == 0) { - imm>>=2; - scale+=2; - } - cache_addd(0xe2800000 + (reg << 12) + (reg << 16) + (ROTATE_SCALE(scale) << 7) + (imm & 0xff)); // add reg, reg, #((imm & 0xff) << scale) - imm>>=8; - scale+=8; - } - } -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - Bits scale; - Bit32u imm2; - imm2 = ~imm; - if(!imm2) return; - if (!imm) { - cache_addd(0xe3a00000 + (reg << 12)); // mov reg, #0 - } else { - scale = 0; - while (imm2) { - while ((imm2 & 3) == 0) { - imm2>>=2; - scale+=2; - } - cache_addd(0xe3c00000 + (reg << 12) + (reg << 16) + (ROTATE_SCALE(scale) << 7) + (imm2 & 0xff)); // bic reg, reg, #((imm2 & 0xff) << scale) - imm2>>=8; - scale+=8; - } - } -} - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - gen_mov_dword_to_reg_imm(temp3, imm); - gen_mov_word_from_reg(temp3, dest, 1); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add an 8bit constant value to a dword memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, 1, temp1); - if (imm >= 0) { - cache_addd(0xe2800000 + (temp3 << 12) + (temp3 << 16) + ((Bit32s)imm)); // add temp3, temp3, #(imm) - } else { - cache_addd(0xe2400000 + (temp3 << 12) + (temp3 << 16) + (-((Bit32s)imm))); // sub temp3, temp3, #(-imm) - } - gen_mov_word_from_reg_helper(temp3, dest, 1, temp1); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_add_direct_byte(dest,(Bit8s)imm); - return; - } - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, dword, temp1); - // maybe use function gen_add_imm - if (dword) { - gen_mov_dword_to_reg_imm(temp2, imm); - } else { - gen_mov_word_to_reg_imm(temp2, (Bit16u)imm); - } - cache_addd(0xe0800000 + (temp3 << 12) + (temp3 << 16) + (temp2)); // add temp3, temp3, temp2 - gen_mov_word_from_reg_helper(temp3, dest, dword, temp1); -} - -// subtract an 8bit constant value from a dword memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, 1, temp1); - if (imm >= 0) { - cache_addd(0xe2400000 + (temp3 << 12) + (temp3 << 16) + ((Bit32s)imm)); // sub temp3, temp3, #(imm) - } else { - cache_addd(0xe2800000 + (temp3 << 12) + (temp3 << 16) + (-((Bit32s)imm))); // add temp3, temp3, #(-imm) - } - gen_mov_word_from_reg_helper(temp3, dest, 1, temp1); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_sub_direct_byte(dest,(Bit8s)imm); - return; - } - gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest); - gen_mov_word_to_reg_helper(temp3, dest, dword, temp1); - // maybe use function gen_add_imm/gen_sub_imm - if (dword) { - gen_mov_dword_to_reg_imm(temp2, imm); - } else { - gen_mov_word_to_reg_imm(temp2, (Bit16u)imm); - } - cache_addd(0xe0400000 + (temp3 << 12) + (temp3 << 16) + (temp2)); // sub temp3, temp3, temp2 - gen_mov_word_from_reg_helper(temp3, dest, dword, temp1); -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - cache_addd(0xe0800000 + (dest_reg << 12) + (dest_reg << 16) + (scale_reg) + (scale << 7)); // add dest_reg, dest_reg, scale_reg, lsl #(scale) - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addd(0xe1a00000 + (dest_reg << 12) + (dest_reg) + (scale << 7)); // mov dest_reg, dest_reg, lsl #(scale) - } - gen_add_imm(dest_reg, imm); -} - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_addd(0xe5900004 + (temp1 << 12) + (HOST_pc << 16)); // ldr temp1, [pc, #4] - cache_addd(0xe2800004 + (HOST_lr << 12) + (HOST_pc << 16)); // add lr, pc, #4 - cache_addd(0xe12fff10 + (temp1)); // bx temp1 - cache_addd((Bit32u)func); // .int func - cache_addd(0xe1a00000 + (FC_RETOP << 12) + HOST_a1); // mov FC_RETOP, a1 -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_raw(func); - return proc_addr; -} - -#if (1) -// max of 4 parameters in a1-a4 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param, (void *)mem, 1); -} -#else - other arm abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - Bits scale; - Bitu imm2; - gen_mov_word_to_reg(temp3, ptr, 1); - - if (imm) { - scale = 0; - imm2 = (Bitu)imm; - while (imm2) { - while ((imm2 & 3) == 0) { - imm2>>=2; - scale+=2; - } - cache_addd(0xe2800000 + (temp3 << 12) + (temp3 << 16) + (ROTATE_SCALE(scale) << 7) + (imm2 & 0xff)); // add temp3, temp3, #((imm2 & 0xff) << scale) - imm2>>=8; - scale+=8; - } - } - -#if (1) -// (*ptr) should be word aligned - if ((imm & 0x03) == 0) { - cache_addd(0xe5900000 + (temp1 << 12) + (temp3 << 16)); // ldr temp1, [temp3] - } else -#endif - { - cache_addd(0xe5d00000 + (temp1 << 12) + (temp3 << 16)); // ldrb temp1, [temp3] - cache_addd(0xe5d00001 + (temp2 << 12) + (temp3 << 16)); // ldrb temp2, [temp3, #1] - cache_addd(0xe1800400 + (temp1 << 12) + (temp1 << 16) + (temp2)); // orr temp1, temp1, temp2, lsl #8 - cache_addd(0xe5d00002 + (temp2 << 12) + (temp3 << 16)); // ldrb temp2, [temp3, #2] - cache_addd(0xe1800800 + (temp1 << 12) + (temp1 << 16) + (temp2)); // orr temp1, temp1, temp2, lsl #16 - cache_addd(0xe5d00003 + (temp2 << 12) + (temp3 << 16)); // ldrb temp2, [temp3, #3] - cache_addd(0xe1800c00 + (temp1 << 12) + (temp1 << 16) + (temp2)); // orr temp1, temp1, temp2, lsl #24 - } - - cache_addd(0xe12fff10 + (temp1)); // bx temp1 -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - if (dword) { - cache_addd(0xe3500000 + (reg << 16)); // cmp reg, #0 - } else { - cache_addd(0xe1b00800 + (temp1 << 12) + (reg)); // movs temp1, reg, lsl #16 - } - cache_addd(0x0a000000); // beq j - return ((Bit32u)cache.pos-4); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - if (dword) { - cache_addd(0xe3500000 + (reg << 16)); // cmp reg, #0 - } else { - cache_addd(0xe1b00800 + (temp1 << 12) + (reg)); // movs temp1, reg, lsl #16 - } - cache_addd(0x1a000000); // bne j - return ((Bit32u)cache.pos-4); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-(data+8); - if (len<0) len=-len; - if (len>0x02000000) LOG_MSG("Big jump %d",len); -#endif - *(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff ); -} - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - if (isdword) { - cache_addd(0xe3500000 + (reg << 16)); // cmp reg, #0 - } else { - cache_addd(0xe31000ff + (reg << 16)); // tst reg, #0xff - } - cache_addd(0x0a000002); // beq nobranch - cache_addd(0xe5900000 + (temp1 << 12) + (HOST_pc << 16)); // ldr temp1, [pc, #0] - cache_addd(0xe12fff10 + (temp1)); // bx temp1 - cache_addd(0); // fill j - // nobranch: - return ((Bit32u)cache.pos-4); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - cache_addd(0xe3500000 + (reg << 16)); // cmp reg, #0 - cache_addd(0xca000002); // bgt nobranch - cache_addd(0xe5900000 + (temp1 << 12) + (HOST_pc << 16)); // ldr temp1, [pc, #0] - cache_addd(0xe12fff10 + (temp1)); // bx temp1 - cache_addd(0); // fill j - // nobranch: - return ((Bit32u)cache.pos-4); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - // this is an absolute branch - *(Bit32u*)data=(Bit32u)cache.pos; -} - -static void gen_run_code(void) { - cache_addd(0xe92d4000); // stmfd sp!, {lr} - cache_addd(0xe92d0df0); // stmfd sp!, {v1-v5,v7,v8} - - // adr: 8 - cache_addd(0xe5900000 + (FC_SEGS_ADDR << 12) + (HOST_pc << 16) + (64 - (8 + 8))); // ldr FC_SEGS_ADDR, [pc, #(&Segs)] - // adr: 12 - cache_addd(0xe5900000 + (FC_REGS_ADDR << 12) + (HOST_pc << 16) + (68 - (12 + 8))); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)] - cache_addd(0xe28fe004); // add lr, pc, #4 - cache_addd(0xe92d4000); // stmfd sp!, {lr} - cache_addd(0xe12fff10); // bx r0 - cache_addd(0xe8bd0df0); // ldmfd sp!, {v1-v5,v7,v8} - cache_addd(0xe8bd4000); // ldmfd sp!, {lr} - cache_addd(0xe12fff1e); // bx lr - // fill up to 64 bytes - cache_addd(0xe1a00000); // nop - cache_addd(0xe1a00000); // nop - cache_addd(0xe1a00000); // nop - cache_addd(0xe1a00000); // nop - cache_addd(0xe1a00000); // nop - cache_addd(0xe1a00000); // nop - - // adr: 64 - cache_addd((Bit32u)&Segs); // address of "Segs" - // adr: 68 - cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs" -} - -// return from a function -static void gen_return_function(void) { - cache_addd(0xe1a00000 + (HOST_a1 << 12) + FC_RETOP); // mov a1, FC_RETOP - cache_addd(0xe8bd4000); // ldmfd sp!, {lr} - cache_addd(0xe12fff1e); // bx lr -} - -#ifdef DRC_FLAGS_INVALIDATION - -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit32u*)pos=0xe0800000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (HOST_a2); // add FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit32u*)pos=0xe1800000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (HOST_a2); // orr FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit32u*)pos=0xe0000000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (HOST_a2); // and FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit32u*)pos=0xe0400000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (HOST_a2); // sub FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit32u*)pos=0xe0200000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (HOST_a2); // eor FC_RETOP, a1, a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit32u*)pos=0xea000000 + (3); // b (pc+3*4) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit32u*)pos=0xe2800000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (1); // add FC_RETOP, a1, #1 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit32u*)pos=0xe2400000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (1); // sub FC_RETOP, a1, #1 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit32u*)pos=0xe1a00010 + (FC_RETOP << 12) + (HOST_a1) + (HOST_a2 << 8); // mov FC_RETOP, a1, lsl a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_SHRb: - *(Bit32u*)pos=0xe2000000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (0xff); // and FC_RETOP, a1, #0xff - *(Bit32u*)(pos+4)=0xe1a00030 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, lsr a2 - *(Bit32u*)(pos+8)=0xe1a00000; // nop - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_SHRw: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (16 << 7); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=0xe1a00020 + (FC_RETOP << 12) + (FC_RETOP) + (16 << 7); // mov FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+8)=0xe1a00030 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, lsr a2 - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_SHRd: - *(Bit32u*)pos=0xe1a00030 + (FC_RETOP << 12) + (HOST_a1) + (HOST_a2 << 8); // mov FC_RETOP, a1, lsr a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_SARb: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (24 << 7); // mov FC_RETOP, a1, lsl #24 - *(Bit32u*)(pos+4)=0xe1a00040 + (FC_RETOP << 12) + (FC_RETOP) + (24 << 7); // mov FC_RETOP, FC_RETOP, asr #24 - *(Bit32u*)(pos+8)=0xe1a00050 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, asr a2 - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_SARw: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (16 << 7); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=0xe1a00040 + (FC_RETOP << 12) + (FC_RETOP) + (16 << 7); // mov FC_RETOP, FC_RETOP, asr #16 - *(Bit32u*)(pos+8)=0xe1a00050 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, asr a2 - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_SARd: - *(Bit32u*)pos=0xe1a00050 + (FC_RETOP << 12) + (HOST_a1) + (HOST_a2 << 8); // mov FC_RETOP, a1, asr a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_RORb: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (24 << 7); // mov FC_RETOP, a1, lsl #24 - *(Bit32u*)(pos+4)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (8 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #8 - *(Bit32u*)(pos+8)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (16 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+12)=0xe1a00070 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, ror a2 - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_RORw: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (16 << 7); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (16 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+8)=0xe1a00070 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, ror a2 - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_RORd: - *(Bit32u*)pos=0xe1a00070 + (FC_RETOP << 12) + (HOST_a1) + (HOST_a2 << 8); // mov FC_RETOP, a1, ror a2 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - case t_ROLb: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (24 << 7); // mov FC_RETOP, a1, lsl #24 - *(Bit32u*)(pos+4)=0xe2600000 + (HOST_a2 << 12) + (HOST_a2 << 16) + (32); // rsb a2, a2, #32 - *(Bit32u*)(pos+8)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (8 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #8 - *(Bit32u*)(pos+12)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (16 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+16)=0xe1a00070 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, ror a2 - break; - case t_ROLw: - *(Bit32u*)pos=0xe1a00000 + (FC_RETOP << 12) + (HOST_a1) + (16 << 7); // mov FC_RETOP, a1, lsl #16 - *(Bit32u*)(pos+4)=0xe2600000 + (HOST_a2 << 12) + (HOST_a2 << 16) + (32); // rsb a2, a2, #32 - *(Bit32u*)(pos+8)=0xe1800020 + (FC_RETOP << 12) + (FC_RETOP << 16) + (FC_RETOP) + (16 << 7); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16 - *(Bit32u*)(pos+12)=0xe1a00070 + (FC_RETOP << 12) + (FC_RETOP) + (HOST_a2 << 8); // mov FC_RETOP, FC_RETOP, ror a2 - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_ROLd: - *(Bit32u*)pos=0xe2600000 + (HOST_a2 << 12) + (HOST_a2 << 16) + (32); // rsb a2, a2, #32 - *(Bit32u*)(pos+4)=0xe1a00070 + (FC_RETOP << 12) + (HOST_a1) + (HOST_a2 << 8); // mov FC_RETOP, a1, ror a2 - *(Bit32u*)(pos+8)=0xe1a00000; // nop - *(Bit32u*)(pos+12)=0xe1a00000; // nop - *(Bit32u*)(pos+16)=0xe1a00000; // nop - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit32u*)pos=0xe2600000 + (FC_RETOP << 12) + (HOST_a1 << 16) + (0); // rsb FC_RETOP, a1, #0 - *(Bit32u*)(pos+4)=0xea000000 + (2); // b (pc+2*4) - break; - default: - *(Bit32u*)(pos+12)=(Bit32u)fct_ptr; // simple_func - break; - - } -#else - *(Bit32u*)(pos+12)=(Bit32u)fct_ptr; // simple_func -#endif -} -#endif - -static void cache_block_before_close(void) { } - - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { - cache_addd(0xe1d000b0 + (dest_reg << 12) + (FC_SEGS_ADDR << 16) + ((index & 0xf0) << 4) + (index & 0x0f)); // ldrh dest_reg, [FC_SEGS_ADDR, #index] -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { - cache_addd(0xe5900000 + (dest_reg << 12) + (FC_SEGS_ADDR << 16) + (index)); // ldr dest_reg, [FC_SEGS_ADDR, #index] -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { - cache_addd(0xe5900000 + (temp1 << 12) + (FC_SEGS_ADDR << 16) + (index)); // ldr temp1, [FC_SEGS_ADDR, #index] - cache_addd(0xe0800000 + (reg << 12) + (reg << 16) + (temp1)); // add reg, reg, temp1 -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { - cache_addd(0xe1d000b0 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + ((index & 0xf0) << 4) + (index & 0x0f)); // ldrh dest_reg, [FC_REGS_ADDR, #index] -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { - cache_addd(0xe5900000 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // ldr dest_reg, [FC_REGS_ADDR, #index] -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { - if (dword) { - cache_addd(0xe5900000 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // ldr dest_reg, [FC_REGS_ADDR, #index] - } else { - cache_addd(0xe1d000b0 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + ((index & 0xf0) << 4) + (index & 0x0f)); // ldrh dest_reg, [FC_REGS_ADDR, #index] - } -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { - cache_addd(0xe5d00000 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // ldrb dest_reg, [FC_REGS_ADDR, #index] -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { - cache_addd(0xe5d00000 + (dest_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // ldrb dest_reg, [FC_REGS_ADDR, #index] -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { - cache_addd(0xe5900000 + (temp2 << 12) + (FC_REGS_ADDR << 16) + (index)); // ldr temp2, [FC_REGS_ADDR, #index] - cache_addd(0xe0800000 + (reg << 12) + (reg << 16) + (temp2)); // add reg, reg, temp2 -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { - cache_addd(0xe1c000b0 + (src_reg << 12) + (FC_REGS_ADDR << 16) + ((index & 0xf0) << 4) + (index & 0x0f)); // strh src_reg, [FC_REGS_ADDR, #index] -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { - cache_addd(0xe5800000 + (src_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // str src_reg, [FC_REGS_ADDR, #index] -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { - if (dword) { - cache_addd(0xe5800000 + (src_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // str src_reg, [FC_REGS_ADDR, #index] - } else { - cache_addd(0xe1c000b0 + (src_reg << 12) + (FC_REGS_ADDR << 16) + ((index & 0xf0) << 4) + (index & 0x0f)); // strh src_reg, [FC_REGS_ADDR, #index] - } -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { - cache_addd(0xe5c00000 + (src_reg << 12) + (FC_REGS_ADDR << 16) + (index)); // strb src_reg, [FC_REGS_ADDR, #index] -} - -#endif diff --git a/src/cpu/core_dynrec/risc_armv4le-thumb-iw.h b/src/cpu/core_dynrec/risc_armv4le-thumb-iw.h deleted file mode 100644 index 01ebb28..0000000 --- a/src/cpu/core_dynrec/risc_armv4le-thumb-iw.h +++ /dev/null @@ -1,1289 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_armv4le-thumb-iw.h,v 1.2 2008/09/19 16:48:02 c2woody Exp $ */ - - -/* ARMv4 (little endian) backend by M-HT (thumb version with data pool, requires -mthumb-interwork switch when compiling dosbox) */ - - -// temporary "lo" registers -#define templo1 HOST_v3 -#define templo2 HOST_v4 - -// temporary "lo" register - value must be preserved when using it -#define templosav HOST_a3 - -// temporary "hi" register -#define temphi1 HOST_ip - -// register that holds function return values -#define FC_RETOP HOST_v2 - -// register used for address calculations, -#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a1 - -// register that holds the second parameter -#define FC_OP2 HOST_a2 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_a2 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_a4 - -#ifdef DRC_USE_REGS_ADDR -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_v7 -#endif - -#ifdef DRC_USE_SEGS_ADDR -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_v8 -#endif - - -// data pool defines -#define CACHE_DATA_JUMP (2) -#define CACHE_DATA_ALIGN (32) -#define CACHE_DATA_MIN (32) -#define CACHE_DATA_MAX (288) - -// data pool variables -static Bit8u * cache_datapos = NULL; // position of data pool in the cache block -static Bit32u cache_datasize = 0; // total size of data pool -static Bit32u cache_dataindex = 0; // used size of data pool = index of free data item (in bytes) in data pool - -// forwarded function -static void INLINE gen_create_branch_short(void * func); - -// function to check distance to data pool -// if too close, then generate jump after data pool -static void cache_checkinstr(Bit32u size) { - if (cache_datasize == 0) { - if (cache_datapos != NULL) { - if (cache.pos + size + CACHE_DATA_JUMP >= cache_datapos) { - cache_datapos = NULL; - } - } - return; - } - - if (cache.pos + size + CACHE_DATA_JUMP <= cache_datapos) return; - - { - register Bit8u * newcachepos; - - newcachepos = cache_datapos + cache_datasize; - gen_create_branch_short(newcachepos); - cache.pos = newcachepos; - } - - if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size && - cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size) - { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1)); - } else { - register Bit32u cachemodsize; - - cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1); - - if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE || - cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE) - { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } else { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1)); - } - } - - cache_datasize = 0; - cache_dataindex = 0; -} - -// function to reserve item in data pool -// returns address of item -static Bit8u * cache_reservedata(void) { - // if data pool not yet initialized, then initialize data pool - if (GCC_UNLIKELY(cache_datapos == NULL)) { - if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN < cache.block.active->cache.start + CACHE_DATA_MAX) { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } - } - - // if data pool not yet used, then set data pool - if (cache_datasize == 0) { - // set data pool address is too close (or behind) cache.pos then set new data pool size - if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_JUMP /*+ CACHE_DATA_ALIGN*/ > cache_datapos) { - if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size && - cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size) - { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1)); - } else { - register Bit32u cachemodsize; - - cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1); - - if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE || - cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE) - { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } else { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1)); - } - } - } - // set initial data pool size - cache_datasize = CACHE_DATA_ALIGN; - } - - // if data pool is full, then enlarge data pool - if (cache_dataindex == cache_datasize) { - cache_datasize += CACHE_DATA_ALIGN; - } - - cache_dataindex += 4; - return (cache_datapos + (cache_dataindex - 4)); -} - -static void cache_block_before_close(void) { - // if data pool in use, then resize cache block to include the data pool - if (cache_datasize != 0) - { - cache.pos = cache_datapos + cache_dataindex; - } - - // clear the values before next use - cache_datapos = NULL; - cache_datasize = 0; - cache_dataindex = 0; -} - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_checkinstr(2); - cache_addw(0x1c00 + reg_dst + (reg_src << 3)); // mov reg_dst, reg_src -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - if ((imm & 0xffffff00) == 0) { - cache_checkinstr(2); - cache_addw(0x2000 + (dest_reg << 8) + imm); // mov dest_reg, #(imm) - } else if ((imm & 0xffff00ff) == 0) { - cache_checkinstr(4); - cache_addw(0x2000 + (dest_reg << 8) + (imm >> 8)); // mov dest_reg, #(imm >> 8) - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (8 << 6)); // lsl dest_reg, dest_reg, #8 - } else if ((imm & 0xff00ffff) == 0) { - cache_checkinstr(4); - cache_addw(0x2000 + (dest_reg << 8) + (imm >> 16)); // mov dest_reg, #(imm >> 16) - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (16 << 6)); // lsl dest_reg, dest_reg, #16 - } else if ((imm & 0x00ffffff) == 0) { - cache_checkinstr(4); - cache_addw(0x2000 + (dest_reg << 8) + (imm >> 24)); // mov dest_reg, #(imm >> 24) - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (24 << 6)); // lsl dest_reg, dest_reg, #24 - } else { - Bit32u diff; - - cache_checkinstr(4); - - diff = imm - ((Bit32u)cache.pos+4); - - if ((diff < 1024) && ((imm & 0x03) == 0)) { - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0xa000 + (dest_reg << 8) + (diff >> 2)); // add dest_reg, pc, #(diff >> 2) - } else { - cache_addw(0x46c0); // nop - cache_addw(0xa000 + (dest_reg << 8) + ((diff - 2) >> 2)); // add dest_reg, pc, #((diff - 2) >> 2) - } - } else { - Bit8u *datapos; - - datapos = cache_reservedata(); - *(Bit32u*)datapos=imm; - - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0x4800 + (dest_reg << 8) + ((datapos - (cache.pos + 4)) >> 2)); // ldr dest_reg, [pc, datapos] - } else { - cache_addw(0x4800 + (dest_reg << 8) + ((datapos - (cache.pos + 2)) >> 2)); // ldr dest_reg, [pc, datapos] - } - } - } -} - -// helper function for gen_mov_word_to_reg -static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)data & 3) { - if ( ((Bit32u)data & 3) == 2 ) { - cache_checkinstr(8); - cache_addw(0x8800 + dest_reg + (data_reg << 3)); // ldrh dest_reg, [data_reg] - cache_addw(0x8800 + templo1 + (data_reg << 3) + (2 << 5)); // ldrh templo1, [data_reg, #2] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (16 << 6)); // lsl templo1, templo1, #16 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - } else { - cache_checkinstr(16); - cache_addw(0x7800 + dest_reg + (data_reg << 3)); // ldrb dest_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (data_reg << 3) + (1 << 6)); // add templo1, data_reg, #1 - cache_addw(0x8800 + templo1 + (templo1 << 3)); // ldrh templo1, [templo1] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (8 << 6)); // lsl templo1, templo1, #8 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - cache_addw(0x7800 + templo1 + (data_reg << 3) + (3 << 6)); // ldrb templo1, [data_reg, #3] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (24 << 6)); // lsl templo1, templo1, #24 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - } - } else { - cache_checkinstr(2); - cache_addw(0x6800 + dest_reg + (data_reg << 3)); // ldr dest_reg, [data_reg] - } - } else { - if ((Bit32u)data & 1) { - cache_checkinstr(8); - cache_addw(0x7800 + dest_reg + (data_reg << 3)); // ldrb dest_reg, [data_reg] - cache_addw(0x7800 + templo1 + (data_reg << 3) + (1 << 6)); // ldrb templo1, [data_reg, #1] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (8 << 6)); // lsl templo1, templo1, #8 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - } else { - cache_checkinstr(2); - cache_addw(0x8800 + dest_reg + (data_reg << 3)); // ldrh dest_reg, [data_reg] - } - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)data); - gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2); -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm); -} - -// helper function for gen_mov_word_from_reg -static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)dest & 3) { - if ( ((Bit32u)dest & 3) == 2 ) { - cache_checkinstr(8); - cache_addw(0x8000 + src_reg + (data_reg << 3)); // strh src_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (16 << 6)); // lsr templo1, templo1, #16 - cache_addw(0x8000 + templo1 + (data_reg << 3) + (2 << 5)); // strh templo1, [data_reg, #2] - } else { - cache_checkinstr(20); - cache_addw(0x7000 + src_reg + (data_reg << 3)); // strb src_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (8 << 6)); // lsr templo1, templo1, #8 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (1 << 6)); // strb templo1, [data_reg, #1] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (16 << 6)); // lsr templo1, templo1, #16 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (2 << 6)); // strb templo1, [data_reg, #2] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (24 << 6)); // lsr templo1, templo1, #24 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (3 << 6)); // strb templo1, [data_reg, #3] - } - } else { - cache_checkinstr(2); - cache_addw(0x6000 + src_reg + (data_reg << 3)); // str src_reg, [data_reg] - } - } else { - if ((Bit32u)dest & 1) { - cache_checkinstr(8); - cache_addw(0x7000 + src_reg + (data_reg << 3)); // strb src_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (8 << 6)); // lsr templo1, templo1, #8 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (1 << 6)); // strb templo1, [data_reg, #1] - } else { - cache_checkinstr(2); - cache_addw(0x8000 + src_reg + (data_reg << 3)); // strh src_reg, [data_reg] - } - } -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)data); - cache_checkinstr(2); - cache_addw(0x7800 + dest_reg + (templo1 << 3)); // ldrb dest_reg, [templo1] -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_checkinstr(2); - cache_addw(0x2000 + (dest_reg << 8) + imm); // mov dest_reg, #(imm) -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest); - cache_checkinstr(2); - cache_addw(0x7000 + src_reg + (templo1 << 3)); // strb src_reg, [templo1] -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - cache_checkinstr(4); - cache_addw(0x0000 + reg + (reg << 3) + (24 << 6)); // lsl reg, reg, #24 - - if (sign) { - cache_addw(0x1000 + reg + (reg << 3) + (24 << 6)); // asr reg, reg, #24 - } else { - cache_addw(0x0800 + reg + (reg << 3) + (24 << 6)); // lsr reg, reg, #24 - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - cache_checkinstr(4); - cache_addw(0x0000 + reg + (reg << 3) + (16 << 6)); // lsl reg, reg, #16 - - if (sign) { - cache_addw(0x1000 + reg + (reg << 3) + (16 << 6)); // asr reg, reg, #16 - } else { - cache_addw(0x0800 + reg + (reg << 3) + (16 << 6)); // lsr reg, reg, #16 - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (reg << 3)); // mov temphi1, reg - gen_mov_word_to_reg(reg, op, 1); - cache_checkinstr(2); - cache_addw(0x4440 + (reg) + ((temphi1 - HOST_r8) << 3)); // add reg, temphi1 -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - if(!imm) return; - gen_mov_dword_to_reg_imm(templo1, imm); - cache_checkinstr(2); - cache_addw(0x1800 + reg + (reg << 3) + (templo1 << 6)); // add reg, reg, templo1 -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - if(imm == 0xffffffff) return; - gen_mov_dword_to_reg_imm(templo1, imm); - cache_checkinstr(2); - cache_addw(0x4000 + reg + (templo1<< 3)); // and reg, templo1 -} - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templosav, imm); - gen_mov_word_from_reg(templosav, dest, 1); - cache_checkinstr(2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add an 8bit constant value to a dword memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, 1, templo2); - cache_checkinstr(2); - if (imm >= 0) { - cache_addw(0x3000 + (templosav << 8) + ((Bit32s)imm)); // add templosav, #(imm) - } else { - cache_addw(0x3800 + (templosav << 8) + (-((Bit32s)imm))); // sub templosav, #(-imm) - } - gen_mov_word_from_reg_helper(templosav, dest, 1, templo2); - cache_checkinstr(2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_add_direct_byte(dest,(Bit8s)imm); - return; - } - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, dword, templo2); - if (dword) { - gen_mov_dword_to_reg_imm(templo1, imm); - } else { - gen_mov_word_to_reg_imm(templo1, (Bit16u)imm); - } - cache_checkinstr(2); - cache_addw(0x1800 + templosav + (templosav << 3) + (templo1 << 6)); // add templosav, templosav, templo1 - gen_mov_word_from_reg_helper(templosav, dest, dword, templo2); - cache_checkinstr(2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// subtract an 8bit constant value from a dword memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, 1, templo2); - cache_checkinstr(2); - if (imm >= 0) { - cache_addw(0x3800 + (templosav << 8) + ((Bit32s)imm)); // sub templosav, #(imm) - } else { - cache_addw(0x3000 + (templosav << 8) + (-((Bit32s)imm))); // add templosav, #(-imm) - } - gen_mov_word_from_reg_helper(templosav, dest, 1, templo2); - cache_checkinstr(2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_sub_direct_byte(dest,(Bit8s)imm); - return; - } - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, dword, templo2); - if (dword) { - gen_mov_dword_to_reg_imm(templo1, imm); - } else { - gen_mov_word_to_reg_imm(templo1, (Bit16u)imm); - } - cache_checkinstr(2); - cache_addw(0x1a00 + templosav + (templosav << 3) + (templo1 << 6)); // sub templosav, templosav, templo1 - gen_mov_word_from_reg_helper(templosav, dest, dword, templo2); - cache_checkinstr(2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - if (scale) { - cache_checkinstr(4); - cache_addw(0x0000 + templo1 + (scale_reg << 3) + (scale << 6)); // lsl templo1, scale_reg, #(scale) - cache_addw(0x1800 + dest_reg + (dest_reg << 3) + (templo1 << 6)); // add dest_reg, dest_reg, templo1 - } else { - cache_checkinstr(2); - cache_addw(0x1800 + dest_reg + (dest_reg << 3) + (scale_reg << 6)); // add dest_reg, dest_reg, scale_reg - } - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_checkinstr(2); - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (scale << 6)); // lsl dest_reg, dest_reg, #(scale) - } - gen_add_imm(dest_reg, imm); -} - -// helper function for gen_call_function_raw and gen_call_function_setup -static void gen_call_function_helper(void * func) { - Bit8u *datapos; - - datapos = cache_reservedata(); - *(Bit32u*)datapos=(Bit32u)func; - - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 4)) >> 2)); // ldr templo1, [pc, datapos] - cache_addw(0xa000 + (templo2 << 8) + (8 >> 2)); // adr templo2, after_call (add templo2, pc, #8) - cache_addw(0x3000 + (templo2 << 8) + (1)); // add templo2, #1 - cache_addw(0x4680 + (HOST_lr - HOST_r8) + (templo2 << 3)); // mov lr, templo2 - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 --- switch to arm state - cache_addw(0x46c0); // nop - } else { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 2)) >> 2)); // ldr templo1, [pc, datapos] - cache_addw(0xa000 + (templo2 << 8) + (4 >> 2)); // adr templo2, after_call (add templo2, pc, #4) - cache_addw(0x3000 + (templo2 << 8) + (1)); // add templo2, #1 - cache_addw(0x4680 + (HOST_lr - HOST_r8) + (templo2 << 3)); // mov lr, templo2 - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 --- switch to arm state - } - // after_call: - - // thumb state from now on - cache_addw(0x1c00 + FC_RETOP + (HOST_a1 << 3)); // mov FC_RETOP, a1 -} - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_checkinstr(14); - gen_call_function_helper(func); -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - cache_checkinstr(14); - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_helper(func); - return proc_addr; - // if proc_addr is on word boundary ((proc_addr & 0x03) == 0) - // then length of generated code is 14 bytes - // otherwise length of generated code is 12 bytes -} - -#if (1) -// max of 4 parameters in a1-a4 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param, (void *)mem, 1); -} -#else - other arm abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_word_to_reg(templosav, ptr, 1); - - if (imm) { - gen_mov_dword_to_reg_imm(templo2, imm); - cache_checkinstr(2); - cache_addw(0x1800 + templosav + (templosav << 3) + (templo2 << 6)); // add templosav, templosav, templo2 - } - -#if (1) -// (*ptr) should be word aligned - if ((imm & 0x03) == 0) { - cache_checkinstr(8); - cache_addw(0x6800 + templo2 + (templosav << 3)); // ldr templo2, [templosav] - } else -#endif - { - cache_checkinstr(26); - cache_addw(0x7800 + templo2 + (templosav << 3)); // ldrb templo2, [templosav] - cache_addw(0x7800 + templo1 + (templosav << 3) + (1 << 6)); // ldrb templo1, [templosav, #1] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (8 << 6)); // lsl templo1, templo1, #8 - cache_addw(0x4300 + templo2 + (templo1 << 3)); // orr templo2, templo1 - cache_addw(0x7800 + templo1 + (templosav << 3) + (2 << 6)); // ldrb templo1, [templosav, #2] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (16 << 6)); // lsl templo1, templo1, #16 - cache_addw(0x4300 + templo2 + (templo1 << 3)); // orr templo2, templo1 - cache_addw(0x7800 + templo1 + (templosav << 3) + (3 << 6)); // ldrb templo1, [templosav, #3] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (24 << 6)); // lsl templo1, templo1, #24 - cache_addw(0x4300 + templo2 + (templo1 << 3)); // orr templo2, templo1 - } - - // increase jmp address to keep thumb state - cache_addw(0x1c00 + templo2 + (templo2 << 3) + (1 << 6)); // add templo2, templo2, #1 - - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 - - cache_addw(0x4700 + (templo2 << 3)); // bx templo2 -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - cache_checkinstr(4); - if (dword) { - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - } else { - cache_addw(0x0000 + templo1 + (reg << 3) + (16 << 6)); // lsl templo1, reg, #16 - } - cache_addw(0xd000); // beq j - return ((Bit32u)cache.pos-2); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - cache_checkinstr(4); - if (dword) { - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - } else { - cache_addw(0x0000 + templo1 + (reg << 3) + (16 << 6)); // lsl templo1, reg, #16 - } - cache_addw(0xd100); // bne j - return ((Bit32u)cache.pos-2); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-(data+4); - if (len<0) len=-len; - if (len>252) LOG_MSG("Big jump %d",len); -#endif - *(Bit8u*)data=(Bit8u)( ((Bit32u)cache.pos-(data+4)) >> 1 ); -} - - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - Bit8u *datapos; - - cache_checkinstr(8); - datapos = cache_reservedata(); - - if (isdword) { - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - } else { - cache_addw(0x0000 + templo2 + (reg << 3) + (24 << 6)); // lsl templo2, reg, #24 - } - cache_addw(0xd000 + (2 >> 1)); // beq nobranch (pc+2) - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 4)) >> 2)); // ldr templo1, [pc, datapos] - } else { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 2)) >> 2)); // ldr templo1, [pc, datapos] - } - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 - // nobranch: - return ((Bit32u)datapos); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - Bit8u *datapos; - - cache_checkinstr(8); - datapos = cache_reservedata(); - - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - cache_addw(0xdc00 + (2 >> 1)); // bgt nobranch (pc+2) - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 4)) >> 2)); // ldr templo1, [pc, datapos] - } else { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 2)) >> 2)); // ldr templo1, [pc, datapos] - } - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 - // nobranch: - return ((Bit32u)datapos); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - // this is an absolute branch - *(Bit32u*)data=((Bit32u)cache.pos) + 1; // add 1 to keep processor in thumb state -} - -static void gen_run_code(void) { - // switch from arm to thumb state - cache_addd(0xe2800000 + (HOST_r3 << 12) + (HOST_pc << 16) + (1)); // add r3, pc, #1 - cache_addd(0xe12fff10 + (HOST_r3)); // bx r3 - - // thumb state from now on - cache_addw(0xb500); // push {lr} - cache_addw(0x4640 + HOST_r3 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov r3, FC_SEGS_ADDR - cache_addw(0x4640 + HOST_r2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov r2, FC_REGS_ADDR - cache_addw(0xb4fc); // push {r2,r3,v1-v4} - - // adr: 16 - cache_addw(0x4800 + (HOST_r3 << 8) + ((64 - (16 + 4)) >> 2)); // ldr r3, [pc, #(&Segs)] - // adr: 18 - cache_addw(0x4800 + (HOST_r2 << 8) + ((68 - (18 + 2)) >> 2)); // ldr r2, [pc, #(&cpu_regs)] - cache_addw(0x4680 + (FC_SEGS_ADDR - HOST_r8) + (HOST_r3 << 3)); // mov FC_SEGS_ADDR, r3 - cache_addw(0x4680 + (FC_REGS_ADDR - HOST_r8) + (HOST_r2 << 3)); // mov FC_REGS_ADDR, r2 - - // align 4 - - cache_addw(0xa302); // add r3, pc, #8 - cache_addw(0x3001); // add r0, #1 - cache_addw(0x3301); // add r3, #1 - cache_addw(0xb408); // push {r3} - cache_addw(0x4700); // bx r0 - cache_addw(0x46c0); // nop - - // align 4 - cache_addw(0xbcfc); // pop {r2,r3,v1-v4} - cache_addw(0x4680 + (FC_SEGS_ADDR - HOST_r8) + (HOST_r3 << 3)); // mov FC_SEGS_ADDR, r3 - cache_addw(0x4680 + (FC_REGS_ADDR - HOST_r8) + (HOST_r2 << 3)); // mov FC_REGS_ADDR, r2 - - cache_addw(0xbc08); // pop {r3} - cache_addw(0x4718); // bx r3 - // fill up to 64 bytes - cache_addw(0x46c0); // nop - cache_addd(0x46c046c0); // nop, nop - cache_addd(0x46c046c0); // nop, nop - cache_addd(0x46c046c0); // nop, nop - cache_addd(0x46c046c0); // nop, nop - - // adr: 64 - cache_addd((Bit32u)&Segs); // address of "Segs" - // adr: 68 - cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs" -} - -// return from a function -static void gen_return_function(void) { - cache_checkinstr(6); - cache_addw(0x1c00 + HOST_a1 + (FC_RETOP << 3)); // mov a1, FC_RETOP - cache_addw(0xbc08); // pop {r3} - cache_addw(0x4718); // bx r3 -} - - -// short unconditional jump (over data pool) -// must emit at most CACHE_DATA_JUMP bytes -static void INLINE gen_create_branch_short(void * func) { - cache_addw(0xe000 + (((Bit32u)func - ((Bit32u)cache.pos + 4)) >> 1) ); // b func -} - - -#ifdef DRC_FLAGS_INVALIDATION - -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { - if ((*(Bit16u*)pos & 0xf000) == 0xe000) { - if ((*(Bit16u*)pos & 0x0fff) >= ((CACHE_DATA_ALIGN / 2) - 1) && - (*(Bit16u*)pos & 0x0fff) < 0x0800) - { - pos = (Bit8u *) ( ( ( (Bit32u)(*(Bit16u*)pos & 0x0fff) ) << 1 ) + ((Bit32u)pos + 4) ); - } - } - -#ifdef DRC_FLAGS_INVALIDATION_DCODE - if (((Bit32u)pos & 0x03) == 0) - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=0x1800 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // add FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4300 + FC_RETOP + (HOST_a2 << 3); // orr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4000 + FC_RETOP + (HOST_a2 << 3); // and FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=0x1a00 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // sub FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4040 + FC_RETOP + (HOST_a2 << 3); // eor FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // add FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=0x1e00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // sub FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4080 + FC_RETOP + (HOST_a2 << 3); // lsl FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_SHRb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // lsr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+4)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_SHRw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // lsr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+4)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_SHRd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_SARb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // asr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+4)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_SARw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // asr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+4)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_SARd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_RORb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+4)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+6)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x46c0; // nop - *(Bit16u*)(pos+12)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - break; - case t_RORw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x46c0; // nop - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+6)=0x46c0; // nop - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x46c0; // nop - *(Bit16u*)(pos+12)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - break; - case t_RORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - /*case t_ROLb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+10)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+12)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+14)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - break;*/ - case t_ROLw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x46c0; // nop - *(Bit16u*)(pos+12)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - break; - case t_ROLd: - *(Bit16u*)pos=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+2)=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+4)=0x46c0; // nop - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x46c0; // nop - *(Bit16u*)(pos+10)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+12)=0x46c0; // nop - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=0x4240 + FC_RETOP + (HOST_a1 << 3); // neg FC_RETOP, a1 - *(Bit16u*)(pos+2)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - default: - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr; // simple_func - break; - } - } - else - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=0x1800 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // add FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4300 + FC_RETOP + (HOST_a2 << 3); // orr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4000 + FC_RETOP + (HOST_a2 << 3); // and FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=0x1a00 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // sub FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4040 + FC_RETOP + (HOST_a2 << 3); // eor FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // add FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=0x1e00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // sub FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4080 + FC_RETOP + (HOST_a2 << 3); // lsl FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_SHRb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x46c0; // nop - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // lsr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+6)=0x46c0; // nop - *(Bit16u*)(pos+8)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+10)=0x46c0; // nop - break; - case t_SHRw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x46c0; // nop - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // lsr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+6)=0x46c0; // nop - *(Bit16u*)(pos+8)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+10)=0x46c0; // nop - break; - case t_SHRd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_SARb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x46c0; // nop - *(Bit16u*)(pos+4)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // asr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+6)=0x46c0; // nop - *(Bit16u*)(pos+8)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+10)=0x46c0; // nop - break; - case t_SARw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x46c0; // nop - *(Bit16u*)(pos+4)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // asr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+6)=0x46c0; // nop - *(Bit16u*)(pos+8)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+10)=0x46c0; // nop - break; - case t_SARd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_RORb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+4)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+6)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - break; - case t_RORw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+4)=0x46c0; // nop - *(Bit16u*)(pos+6)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+8)=0x46c0; // nop - *(Bit16u*)(pos+10)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - break; - case t_RORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - /*case t_ROLb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+10)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+12)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+14)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - break;*/ - case t_ROLw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - break; - case t_ROLd: - *(Bit16u*)pos=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+2)=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+4)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+6)=0x46c0; // nop - *(Bit16u*)(pos+8)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+10)=0x46c0; // nop - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=0x4240 + FC_RETOP + (HOST_a1 << 3); // neg FC_RETOP, a1 - *(Bit16u*)(pos+2)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - default: - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr; // simple_func - break; - } - - } -#else - if (((Bit32u)pos & 0x03) == 0) - { - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr; // simple_func - } - else - { - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr; // simple_func - } -#endif -} -#endif - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_SEGS_ADDR - cache_addw(0x8800 + dest_reg + (templo1 << 3) + (index << 5)); // ldrh dest_reg, [templo1, #index] -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_SEGS_ADDR - cache_addw(0x6800 + dest_reg + (templo1 << 3) + (index << 4)); // ldr dest_reg, [templo1, #index] -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { - cache_checkinstr(6); - cache_addw(0x4640 + templo1 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_SEGS_ADDR - cache_addw(0x6800 + templo2 + (templo1 << 3) + (index << 4)); // ldr templo2, [templo1, #index] - cache_addw(0x1800 + reg + (reg << 3) + (templo2 << 6)); // add reg, reg, templo2 -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x8800 + dest_reg + (templo2 << 3) + (index << 5)); // ldrh dest_reg, [templo2, #index] -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x6800 + dest_reg + (templo2 << 3) + (index << 4)); // ldr dest_reg, [templo2, #index] -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { - cache_checkinstr(4); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - if (dword) { - cache_addw(0x6800 + dest_reg + (templo2 << 3) + (index << 4)); // ldr dest_reg, [templo2, #index] - } else { - cache_addw(0x8800 + dest_reg + (templo2 << 3) + (index << 5)); // ldrh dest_reg, [templo2, #index] - } -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x7800 + dest_reg + (templo2 << 3) + (index << 6)); // ldrb dest_reg, [templo2, #index] -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x7800 + dest_reg + (templo2 << 3) + (index << 6)); // ldrb dest_reg, [templo2, #index] -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { - cache_checkinstr(6); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x6800 + templo1 + (templo2 << 3) + (index << 4)); // ldr templo1, [templo2, #index] - cache_addw(0x1800 + reg + (reg << 3) + (templo1 << 6)); // add reg, reg, templo1 -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - cache_addw(0x8000 + src_reg + (templo1 << 3) + (index << 5)); // strh src_reg, [templo1, #index] -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - cache_addw(0x6000 + src_reg + (templo1 << 3) + (index << 4)); // str src_reg, [templo1, #index] -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - if (dword) { - cache_addw(0x6000 + src_reg + (templo1 << 3) + (index << 4)); // str src_reg, [templo1, #index] - } else { - cache_addw(0x8000 + src_reg + (templo1 << 3) + (index << 5)); // strh src_reg, [templo1, #index] - } -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - cache_addw(0x7000 + src_reg + (templo1 << 3) + (index << 6)); // strb src_reg, [templo1, #index] -} -#endif diff --git a/src/cpu/core_dynrec/risc_armv4le-thumb-niw.h b/src/cpu/core_dynrec/risc_armv4le-thumb-niw.h deleted file mode 100644 index 0853b8e..0000000 --- a/src/cpu/core_dynrec/risc_armv4le-thumb-niw.h +++ /dev/null @@ -1,1286 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_armv4le-thumb-niw.h,v 1.2 2008/09/19 16:48:02 c2woody Exp $ */ - - -/* ARMv4 (little endian) backend by M-HT (thumb version with data pool) */ - - -// temporary "lo" registers -#define templo1 HOST_v3 -#define templo2 HOST_v4 - -// temporary "lo" register - value must be preserved when using it -#define templosav HOST_a3 - -// temporary "hi" register -#define temphi1 HOST_ip - -// register that holds function return values -#define FC_RETOP HOST_v2 - -// register used for address calculations, -#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a1 - -// register that holds the second parameter -#define FC_OP2 HOST_a2 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_a2 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_a4 - -#ifdef DRC_USE_REGS_ADDR -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_v7 -#endif - -#ifdef DRC_USE_SEGS_ADDR -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_v8 -#endif - - -// data pool defines -#define CACHE_DATA_JUMP (2) -#define CACHE_DATA_ALIGN (32) -#define CACHE_DATA_MIN (32) -#define CACHE_DATA_MAX (288) - -// data pool variables -static Bit8u * cache_datapos = NULL; // position of data pool in the cache block -static Bit32u cache_datasize = 0; // total size of data pool -static Bit32u cache_dataindex = 0; // used size of data pool = index of free data item (in bytes) in data pool - -// forwarded function -static void INLINE gen_create_branch_short(void * func); - -// function to check distance to data pool -// if too close, then generate jump after data pool -static void cache_checkinstr(Bit32u size) { - if (cache_datasize == 0) { - if (cache_datapos != NULL) { - if (cache.pos + size + CACHE_DATA_JUMP >= cache_datapos) { - cache_datapos = NULL; - } - } - return; - } - - if (cache.pos + size + CACHE_DATA_JUMP <= cache_datapos) return; - - { - register Bit8u * newcachepos; - - newcachepos = cache_datapos + cache_datasize; - gen_create_branch_short(newcachepos); - cache.pos = newcachepos; - } - - if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size && - cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size) - { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1)); - } else { - register Bit32u cachemodsize; - - cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1); - - if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE || - cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE) - { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } else { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1)); - } - } - - cache_datasize = 0; - cache_dataindex = 0; -} - -// function to reserve item in data pool -// returns address of item -static Bit8u * cache_reservedata(void) { - // if data pool not yet initialized, then initialize data pool - if (GCC_UNLIKELY(cache_datapos == NULL)) { - if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN < cache.block.active->cache.start + CACHE_DATA_MAX) { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } - } - - // if data pool not yet used, then set data pool - if (cache_datasize == 0) { - // set data pool address is too close (or behind) cache.pos then set new data pool size - if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_JUMP /*+ CACHE_DATA_ALIGN*/ > cache_datapos) { - if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size && - cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size) - { - cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1)); - } else { - register Bit32u cachemodsize; - - cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1); - - if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE || - cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE) - { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1)); - } else { - cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1)); - } - } - } - // set initial data pool size - cache_datasize = CACHE_DATA_ALIGN; - } - - // if data pool is full, then enlarge data pool - if (cache_dataindex == cache_datasize) { - cache_datasize += CACHE_DATA_ALIGN; - } - - cache_dataindex += 4; - return (cache_datapos + (cache_dataindex - 4)); -} - -static void cache_block_before_close(void) { - // if data pool in use, then resize cache block to include the data pool - if (cache_datasize != 0) - { - cache.pos = cache_datapos + cache_dataindex; - } - - // clear the values before next use - cache_datapos = NULL; - cache_datasize = 0; - cache_dataindex = 0; -} - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_checkinstr(2); - cache_addw(0x1c00 + reg_dst + (reg_src << 3)); // mov reg_dst, reg_src -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - if ((imm & 0xffffff00) == 0) { - cache_checkinstr(2); - cache_addw(0x2000 + (dest_reg << 8) + imm); // mov dest_reg, #(imm) - } else if ((imm & 0xffff00ff) == 0) { - cache_checkinstr(4); - cache_addw(0x2000 + (dest_reg << 8) + (imm >> 8)); // mov dest_reg, #(imm >> 8) - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (8 << 6)); // lsl dest_reg, dest_reg, #8 - } else if ((imm & 0xff00ffff) == 0) { - cache_checkinstr(4); - cache_addw(0x2000 + (dest_reg << 8) + (imm >> 16)); // mov dest_reg, #(imm >> 16) - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (16 << 6)); // lsl dest_reg, dest_reg, #16 - } else if ((imm & 0x00ffffff) == 0) { - cache_checkinstr(4); - cache_addw(0x2000 + (dest_reg << 8) + (imm >> 24)); // mov dest_reg, #(imm >> 24) - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (24 << 6)); // lsl dest_reg, dest_reg, #24 - } else { - Bit32u diff; - - cache_checkinstr(4); - - diff = imm - ((Bit32u)cache.pos+4); - - if ((diff < 1024) && ((imm & 0x03) == 0)) { - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0xa000 + (dest_reg << 8) + (diff >> 2)); // add dest_reg, pc, #(diff >> 2) - } else { - cache_addw(0x46c0); // nop - cache_addw(0xa000 + (dest_reg << 8) + ((diff - 2) >> 2)); // add dest_reg, pc, #((diff - 2) >> 2) - } - } else { - Bit8u *datapos; - - datapos = cache_reservedata(); - *(Bit32u*)datapos=imm; - - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0x4800 + (dest_reg << 8) + ((datapos - (cache.pos + 4)) >> 2)); // ldr dest_reg, [pc, datapos] - } else { - cache_addw(0x4800 + (dest_reg << 8) + ((datapos - (cache.pos + 2)) >> 2)); // ldr dest_reg, [pc, datapos] - } - } - } -} - -// helper function for gen_mov_word_to_reg -static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)data & 3) { - if ( ((Bit32u)data & 3) == 2 ) { - cache_checkinstr(8); - cache_addw(0x8800 + dest_reg + (data_reg << 3)); // ldrh dest_reg, [data_reg] - cache_addw(0x8800 + templo1 + (data_reg << 3) + (2 << 5)); // ldrh templo1, [data_reg, #2] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (16 << 6)); // lsl templo1, templo1, #16 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - } else { - cache_checkinstr(16); - cache_addw(0x7800 + dest_reg + (data_reg << 3)); // ldrb dest_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (data_reg << 3) + (1 << 6)); // add templo1, data_reg, #1 - cache_addw(0x8800 + templo1 + (templo1 << 3)); // ldrh templo1, [templo1] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (8 << 6)); // lsl templo1, templo1, #8 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - cache_addw(0x7800 + templo1 + (data_reg << 3) + (3 << 6)); // ldrb templo1, [data_reg, #3] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (24 << 6)); // lsl templo1, templo1, #24 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - } - } else { - cache_checkinstr(2); - cache_addw(0x6800 + dest_reg + (data_reg << 3)); // ldr dest_reg, [data_reg] - } - } else { - if ((Bit32u)data & 1) { - cache_checkinstr(8); - cache_addw(0x7800 + dest_reg + (data_reg << 3)); // ldrb dest_reg, [data_reg] - cache_addw(0x7800 + templo1 + (data_reg << 3) + (1 << 6)); // ldrb templo1, [data_reg, #1] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (8 << 6)); // lsl templo1, templo1, #8 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - } else { - cache_checkinstr(2); - cache_addw(0x8800 + dest_reg + (data_reg << 3)); // ldrh dest_reg, [data_reg] - } - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)data); - gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2); -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm); -} - -// helper function for gen_mov_word_from_reg -static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)dest & 3) { - if ( ((Bit32u)dest & 3) == 2 ) { - cache_checkinstr(8); - cache_addw(0x8000 + src_reg + (data_reg << 3)); // strh src_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (16 << 6)); // lsr templo1, templo1, #16 - cache_addw(0x8000 + templo1 + (data_reg << 3) + (2 << 5)); // strh templo1, [data_reg, #2] - } else { - cache_checkinstr(20); - cache_addw(0x7000 + src_reg + (data_reg << 3)); // strb src_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (8 << 6)); // lsr templo1, templo1, #8 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (1 << 6)); // strb templo1, [data_reg, #1] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (16 << 6)); // lsr templo1, templo1, #16 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (2 << 6)); // strb templo1, [data_reg, #2] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (24 << 6)); // lsr templo1, templo1, #24 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (3 << 6)); // strb templo1, [data_reg, #3] - } - } else { - cache_checkinstr(2); - cache_addw(0x6000 + src_reg + (data_reg << 3)); // str src_reg, [data_reg] - } - } else { - if ((Bit32u)dest & 1) { - cache_checkinstr(8); - cache_addw(0x7000 + src_reg + (data_reg << 3)); // strb src_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (8 << 6)); // lsr templo1, templo1, #8 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (1 << 6)); // strb templo1, [data_reg, #1] - } else { - cache_checkinstr(2); - cache_addw(0x8000 + src_reg + (data_reg << 3)); // strh src_reg, [data_reg] - } - } -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)data); - cache_checkinstr(2); - cache_addw(0x7800 + dest_reg + (templo1 << 3)); // ldrb dest_reg, [templo1] -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_checkinstr(2); - cache_addw(0x2000 + (dest_reg << 8) + imm); // mov dest_reg, #(imm) -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest); - cache_checkinstr(2); - cache_addw(0x7000 + src_reg + (templo1 << 3)); // strb src_reg, [templo1] -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - cache_checkinstr(4); - cache_addw(0x0000 + reg + (reg << 3) + (24 << 6)); // lsl reg, reg, #24 - - if (sign) { - cache_addw(0x1000 + reg + (reg << 3) + (24 << 6)); // asr reg, reg, #24 - } else { - cache_addw(0x0800 + reg + (reg << 3) + (24 << 6)); // lsr reg, reg, #24 - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - cache_checkinstr(4); - cache_addw(0x0000 + reg + (reg << 3) + (16 << 6)); // lsl reg, reg, #16 - - if (sign) { - cache_addw(0x1000 + reg + (reg << 3) + (16 << 6)); // asr reg, reg, #16 - } else { - cache_addw(0x0800 + reg + (reg << 3) + (16 << 6)); // lsr reg, reg, #16 - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (reg << 3)); // mov temphi1, reg - gen_mov_word_to_reg(reg, op, 1); - cache_checkinstr(2); - cache_addw(0x4440 + (reg) + ((temphi1 - HOST_r8) << 3)); // add reg, temphi1 -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - if(!imm) return; - gen_mov_dword_to_reg_imm(templo1, imm); - cache_checkinstr(2); - cache_addw(0x1800 + reg + (reg << 3) + (templo1 << 6)); // add reg, reg, templo1 -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - if(imm == 0xffffffff) return; - gen_mov_dword_to_reg_imm(templo1, imm); - cache_checkinstr(2); - cache_addw(0x4000 + reg + (templo1<< 3)); // and reg, templo1 -} - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templosav, imm); - gen_mov_word_from_reg(templosav, dest, 1); - cache_checkinstr(2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add an 8bit constant value to a dword memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, 1, templo2); - cache_checkinstr(2); - if (imm >= 0) { - cache_addw(0x3000 + (templosav << 8) + ((Bit32s)imm)); // add templosav, #(imm) - } else { - cache_addw(0x3800 + (templosav << 8) + (-((Bit32s)imm))); // sub templosav, #(-imm) - } - gen_mov_word_from_reg_helper(templosav, dest, 1, templo2); - cache_checkinstr(2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_add_direct_byte(dest,(Bit8s)imm); - return; - } - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, dword, templo2); - if (dword) { - gen_mov_dword_to_reg_imm(templo1, imm); - } else { - gen_mov_word_to_reg_imm(templo1, (Bit16u)imm); - } - cache_checkinstr(2); - cache_addw(0x1800 + templosav + (templosav << 3) + (templo1 << 6)); // add templosav, templosav, templo1 - gen_mov_word_from_reg_helper(templosav, dest, dword, templo2); - cache_checkinstr(2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// subtract an 8bit constant value from a dword memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, 1, templo2); - cache_checkinstr(2); - if (imm >= 0) { - cache_addw(0x3800 + (templosav << 8) + ((Bit32s)imm)); // sub templosav, #(imm) - } else { - cache_addw(0x3000 + (templosav << 8) + (-((Bit32s)imm))); // add templosav, #(-imm) - } - gen_mov_word_from_reg_helper(templosav, dest, 1, templo2); - cache_checkinstr(2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_sub_direct_byte(dest,(Bit8s)imm); - return; - } - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, dword, templo2); - if (dword) { - gen_mov_dword_to_reg_imm(templo1, imm); - } else { - gen_mov_word_to_reg_imm(templo1, (Bit16u)imm); - } - cache_checkinstr(2); - cache_addw(0x1a00 + templosav + (templosav << 3) + (templo1 << 6)); // sub templosav, templosav, templo1 - gen_mov_word_from_reg_helper(templosav, dest, dword, templo2); - cache_checkinstr(2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - if (scale) { - cache_checkinstr(4); - cache_addw(0x0000 + templo1 + (scale_reg << 3) + (scale << 6)); // lsl templo1, scale_reg, #(scale) - cache_addw(0x1800 + dest_reg + (dest_reg << 3) + (templo1 << 6)); // add dest_reg, dest_reg, templo1 - } else { - cache_checkinstr(2); - cache_addw(0x1800 + dest_reg + (dest_reg << 3) + (scale_reg << 6)); // add dest_reg, dest_reg, scale_reg - } - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_checkinstr(2); - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (scale << 6)); // lsl dest_reg, dest_reg, #(scale) - } - gen_add_imm(dest_reg, imm); -} - -// helper function for gen_call_function_raw and gen_call_function_setup -static void gen_call_function_helper(void * func) { - Bit8u *datapos; - - datapos = cache_reservedata(); - *(Bit32u*)datapos=(Bit32u)func; - - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 4)) >> 2)); // ldr templo1, [pc, datapos] - cache_addw(0xa000 + (templo2 << 8) + (4 >> 2)); // adr templo2, after_call (add templo2, pc, #4) - cache_addw(0x4680 + (HOST_lr - HOST_r8) + (templo2 << 3)); // mov lr, templo2 - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 --- switch to arm state - } else { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 2)) >> 2)); // ldr templo1, [pc, datapos] - cache_addw(0xa000 + (templo2 << 8) + (4 >> 2)); // adr templo2, after_call (add templo2, pc, #4) - cache_addw(0x4680 + (HOST_lr - HOST_r8) + (templo2 << 3)); // mov lr, templo2 - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 --- switch to arm state - cache_addw(0x46c0); // nop - } - // after_call: - - // switch from arm to thumb state - cache_addd(0xe2800000 + (templo1 << 12) + (HOST_pc << 16) + (1)); // add templo1, pc, #1 - cache_addd(0xe12fff10 + (templo1)); // bx templo1 - - // thumb state from now on - cache_addw(0x1c00 + FC_RETOP + (HOST_a1 << 3)); // mov FC_RETOP, a1 -} - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_checkinstr(20); - gen_call_function_helper(func); -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - cache_checkinstr(20); - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_helper(func); - return proc_addr; - // if proc_addr is on word boundary ((proc_addr & 0x03) == 0) - // then length of generated code is 18 bytes - // otherwise length of generated code is 20 bytes -} - -#if (1) -// max of 4 parameters in a1-a4 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param, (void *)mem, 1); -} -#else - other arm abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - cache_checkinstr(2); - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_word_to_reg(templosav, ptr, 1); - - if (imm) { - gen_mov_dword_to_reg_imm(templo2, imm); - cache_checkinstr(2); - cache_addw(0x1800 + templosav + (templosav << 3) + (templo2 << 6)); // add templosav, templosav, templo2 - } - -#if (1) -// (*ptr) should be word aligned - if ((imm & 0x03) == 0) { - cache_checkinstr(8); - cache_addw(0x6800 + templo2 + (templosav << 3)); // ldr templo2, [templosav] - } else -#endif - { - cache_checkinstr(26); - cache_addw(0x7800 + templo2 + (templosav << 3)); // ldrb templo2, [templosav] - cache_addw(0x7800 + templo1 + (templosav << 3) + (1 << 6)); // ldrb templo1, [templosav, #1] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (8 << 6)); // lsl templo1, templo1, #8 - cache_addw(0x4300 + templo2 + (templo1 << 3)); // orr templo2, templo1 - cache_addw(0x7800 + templo1 + (templosav << 3) + (2 << 6)); // ldrb templo1, [templosav, #2] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (16 << 6)); // lsl templo1, templo1, #16 - cache_addw(0x4300 + templo2 + (templo1 << 3)); // orr templo2, templo1 - cache_addw(0x7800 + templo1 + (templosav << 3) + (3 << 6)); // ldrb templo1, [templosav, #3] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (24 << 6)); // lsl templo1, templo1, #24 - cache_addw(0x4300 + templo2 + (templo1 << 3)); // orr templo2, templo1 - } - - // increase jmp address to keep thumb state - cache_addw(0x1c00 + templo2 + (templo2 << 3) + (1 << 6)); // add templo2, templo2, #1 - - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 - - cache_addw(0x4700 + (templo2 << 3)); // bx templo2 -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - cache_checkinstr(4); - if (dword) { - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - } else { - cache_addw(0x0000 + templo1 + (reg << 3) + (16 << 6)); // lsl templo1, reg, #16 - } - cache_addw(0xd000); // beq j - return ((Bit32u)cache.pos-2); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - cache_checkinstr(4); - if (dword) { - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - } else { - cache_addw(0x0000 + templo1 + (reg << 3) + (16 << 6)); // lsl templo1, reg, #16 - } - cache_addw(0xd100); // bne j - return ((Bit32u)cache.pos-2); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-(data+4); - if (len<0) len=-len; - if (len>252) LOG_MSG("Big jump %d",len); -#endif - *(Bit8u*)data=(Bit8u)( ((Bit32u)cache.pos-(data+4)) >> 1 ); -} - - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - Bit8u *datapos; - - cache_checkinstr(8); - datapos = cache_reservedata(); - - if (isdword) { - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - } else { - cache_addw(0x0000 + templo2 + (reg << 3) + (24 << 6)); // lsl templo2, reg, #24 - } - cache_addw(0xd000 + (2 >> 1)); // beq nobranch (pc+2) - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 4)) >> 2)); // ldr templo1, [pc, datapos] - } else { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 2)) >> 2)); // ldr templo1, [pc, datapos] - } - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 - // nobranch: - return ((Bit32u)datapos); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - Bit8u *datapos; - - cache_checkinstr(8); - datapos = cache_reservedata(); - - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - cache_addw(0xdc00 + (2 >> 1)); // bgt nobranch (pc+2) - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 4)) >> 2)); // ldr templo1, [pc, datapos] - } else { - cache_addw(0x4800 + (templo1 << 8) + ((datapos - (cache.pos + 2)) >> 2)); // ldr templo1, [pc, datapos] - } - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 - // nobranch: - return ((Bit32u)datapos); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - // this is an absolute branch - *(Bit32u*)data=((Bit32u)cache.pos) + 1; // add 1 to keep processor in thumb state -} - -static void gen_run_code(void) { - // switch from arm to thumb state - cache_addd(0xe2800000 + (HOST_r3 << 12) + (HOST_pc << 16) + (1)); // add r3, pc, #1 - cache_addd(0xe12fff10 + (HOST_r3)); // bx r3 - - // thumb state from now on - cache_addw(0xb500); // push {lr} - cache_addw(0x4640 + HOST_r3 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov r3, FC_SEGS_ADDR - cache_addw(0x4640 + HOST_r2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov r2, FC_REGS_ADDR - cache_addw(0xb4fc); // push {r2,r3,v1-v4} - - // adr: 16 - cache_addw(0x4800 + (HOST_r3 << 8) + ((64 - (16 + 4)) >> 2)); // ldr r3, [pc, #(&Segs)] - // adr: 18 - cache_addw(0x4800 + (HOST_r2 << 8) + ((68 - (18 + 2)) >> 2)); // ldr r2, [pc, #(&cpu_regs)] - cache_addw(0x4680 + (FC_SEGS_ADDR - HOST_r8) + (HOST_r3 << 3)); // mov FC_SEGS_ADDR, r3 - cache_addw(0x4680 + (FC_REGS_ADDR - HOST_r8) + (HOST_r2 << 3)); // mov FC_REGS_ADDR, r2 - - // align 4 - - cache_addw(0xa302); // add r3, pc, #8 - cache_addw(0x3001); // add r0, #1 - cache_addw(0x3301); // add r3, #1 - cache_addw(0xb408); // push {r3} - cache_addw(0x4700); // bx r0 - cache_addw(0x46c0); // nop - - // align 4 - cache_addw(0xbcfc); // pop {r2,r3,v1-v4} - cache_addw(0x4680 + (FC_SEGS_ADDR - HOST_r8) + (HOST_r3 << 3)); // mov FC_SEGS_ADDR, r3 - cache_addw(0x4680 + (FC_REGS_ADDR - HOST_r8) + (HOST_r2 << 3)); // mov FC_REGS_ADDR, r2 - - cache_addw(0xbc08); // pop {r3} - cache_addw(0x4718); // bx r3 - // fill up to 64 bytes - cache_addw(0x46c0); // nop - cache_addd(0x46c046c0); // nop, nop - cache_addd(0x46c046c0); // nop, nop - cache_addd(0x46c046c0); // nop, nop - cache_addd(0x46c046c0); // nop, nop - - // adr: 64 - cache_addd((Bit32u)&Segs); // address of "Segs" - // adr: 68 - cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs" -} - -// return from a function -static void gen_return_function(void) { - cache_checkinstr(6); - cache_addw(0x1c00 + HOST_a1 + (FC_RETOP << 3)); // mov a1, FC_RETOP - cache_addw(0xbc08); // pop {r3} - cache_addw(0x4718); // bx r3 -} - - -// short unconditional jump (over data pool) -// must emit at most CACHE_DATA_JUMP bytes -static void INLINE gen_create_branch_short(void * func) { - cache_addw(0xe000 + (((Bit32u)func - ((Bit32u)cache.pos + 4)) >> 1) ); // b func -} - - -#ifdef DRC_FLAGS_INVALIDATION - -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { - if ((*(Bit16u*)pos & 0xf000) == 0xe000) { - if ((*(Bit16u*)pos & 0x0fff) >= ((CACHE_DATA_ALIGN / 2) - 1) && - (*(Bit16u*)pos & 0x0fff) < 0x0800) - { - pos = (Bit8u *) ( ( ( (Bit32u)(*(Bit16u*)pos & 0x0fff) ) << 1 ) + ((Bit32u)pos + 4) ); - } - } - -#ifdef DRC_FLAGS_INVALIDATION_DCODE - if (((Bit32u)pos & 0x03) == 0) - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=0x1800 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // add FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4300 + FC_RETOP + (HOST_a2 << 3); // orr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4000 + FC_RETOP + (HOST_a2 << 3); // and FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=0x1a00 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // sub FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4040 + FC_RETOP + (HOST_a2 << 3); // eor FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // add FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=0x1e00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // sub FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4080 + FC_RETOP + (HOST_a2 << 3); // lsl FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_SHRb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // lsr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+4)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_SHRw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // lsr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+4)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_SHRd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_SARb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // asr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+4)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_SARw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // asr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+4)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_SARd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_RORb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+4)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+6)=0x46c0; // nop - *(Bit16u*)(pos+8)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+10)=0x46c0; // nop - *(Bit16u*)(pos+12)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+14)=0x46c0; // nop - *(Bit16u*)(pos+16)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - break; - case t_RORw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+4)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+6)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+8)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_RORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_ROLb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+10)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+12)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+14)=0x46c0; // nop - *(Bit16u*)(pos+16)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - break; - case t_ROLw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x46c0; // nop - *(Bit16u*)(pos+12)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+14)=0x46c0; // nop - *(Bit16u*)(pos+16)=0x46c0; // nop - break; - case t_ROLd: - *(Bit16u*)pos=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+2)=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+4)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+6)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+8)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=0x4240 + FC_RETOP + (HOST_a1 << 3); // neg FC_RETOP, a1 - *(Bit16u*)(pos+2)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - default: - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr; // simple_func - break; - } - } - else - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=0x1800 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // add FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4300 + FC_RETOP + (HOST_a2 << 3); // orr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4000 + FC_RETOP + (HOST_a2 << 3); // and FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=0x1a00 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // sub FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4040 + FC_RETOP + (HOST_a2 << 3); // eor FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // add FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=0x1e00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // sub FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4080 + FC_RETOP + (HOST_a2 << 3); // lsl FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_SHRb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // lsr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+4)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_SHRw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // lsr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+4)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_SHRd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_SARb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // asr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+4)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_SARw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // asr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+4)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_SARd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_RORb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+4)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+6)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+12)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_RORw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+4)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+6)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+8)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_RORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_ROLb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+10)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+12)=0x46c0; // nop - *(Bit16u*)(pos+14)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+16)=0x46c0; // nop - *(Bit16u*)(pos+18)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - break; - case t_ROLw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+12)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_ROLd: - *(Bit16u*)pos=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+2)=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+4)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+6)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+8)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=0x4240 + FC_RETOP + (HOST_a1 << 3); // neg FC_RETOP, a1 - *(Bit16u*)(pos+2)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - default: - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr; // simple_func - break; - } - - } -#else - if (((Bit32u)pos & 0x03) == 0) - { - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr; // simple_func - } - else - { - *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr; // simple_func - } -#endif -} -#endif - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_SEGS_ADDR - cache_addw(0x8800 + dest_reg + (templo1 << 3) + (index << 5)); // ldrh dest_reg, [templo1, #index] -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_SEGS_ADDR - cache_addw(0x6800 + dest_reg + (templo1 << 3) + (index << 4)); // ldr dest_reg, [templo1, #index] -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { - cache_checkinstr(6); - cache_addw(0x4640 + templo1 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_SEGS_ADDR - cache_addw(0x6800 + templo2 + (templo1 << 3) + (index << 4)); // ldr templo2, [templo1, #index] - cache_addw(0x1800 + reg + (reg << 3) + (templo2 << 6)); // add reg, reg, templo2 -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x8800 + dest_reg + (templo2 << 3) + (index << 5)); // ldrh dest_reg, [templo2, #index] -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x6800 + dest_reg + (templo2 << 3) + (index << 4)); // ldr dest_reg, [templo2, #index] -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { - cache_checkinstr(4); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - if (dword) { - cache_addw(0x6800 + dest_reg + (templo2 << 3) + (index << 4)); // ldr dest_reg, [templo2, #index] - } else { - cache_addw(0x8800 + dest_reg + (templo2 << 3) + (index << 5)); // ldrh dest_reg, [templo2, #index] - } -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x7800 + dest_reg + (templo2 << 3) + (index << 6)); // ldrb dest_reg, [templo2, #index] -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x7800 + dest_reg + (templo2 << 3) + (index << 6)); // ldrb dest_reg, [templo2, #index] -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { - cache_checkinstr(6); - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x6800 + templo1 + (templo2 << 3) + (index << 4)); // ldr templo1, [templo2, #index] - cache_addw(0x1800 + reg + (reg << 3) + (templo1 << 6)); // add reg, reg, templo1 -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - cache_addw(0x8000 + src_reg + (templo1 << 3) + (index << 5)); // strh src_reg, [templo1, #index] -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - cache_addw(0x6000 + src_reg + (templo1 << 3) + (index << 4)); // str src_reg, [templo1, #index] -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - if (dword) { - cache_addw(0x6000 + src_reg + (templo1 << 3) + (index << 4)); // str src_reg, [templo1, #index] - } else { - cache_addw(0x8000 + src_reg + (templo1 << 3) + (index << 5)); // strh src_reg, [templo1, #index] - } -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { - cache_checkinstr(4); - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - cache_addw(0x7000 + src_reg + (templo1 << 3) + (index << 6)); // strb src_reg, [templo1, #index] -} -#endif diff --git a/src/cpu/core_dynrec/risc_armv4le-thumb.h b/src/cpu/core_dynrec/risc_armv4le-thumb.h deleted file mode 100644 index 4ed007b..0000000 --- a/src/cpu/core_dynrec/risc_armv4le-thumb.h +++ /dev/null @@ -1,1078 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_armv4le-thumb.h,v 1.3 2008/09/19 16:48:03 c2woody Exp $ */ - - -/* ARMv4 (little endian) backend by M-HT (thumb version) */ - - -// temporary "lo" registers -#define templo1 HOST_v3 -#define templo2 HOST_v4 - -// temporary "lo" register - value must be preserved when using it -#define templosav HOST_a3 - -// temporary "hi" register -#define temphi1 HOST_ip - -// register that holds function return values -#define FC_RETOP HOST_v2 - -// register used for address calculations, -#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a1 - -// register that holds the second parameter -#define FC_OP2 HOST_a2 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_a2 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_a4 - -#ifdef DRC_USE_REGS_ADDR -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_v7 -#endif - -#ifdef DRC_USE_SEGS_ADDR -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_v8 -#endif - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_addw(0x1c00 + reg_dst + (reg_src << 3)); // mov reg_dst, reg_src -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - if ((imm & 0xffffff00) == 0) { - cache_addw(0x2000 + (dest_reg << 8) + (Bit8u)(imm & 0xff)); // mov dest_reg, #(imm) - } else if ((imm & 0xffff00ff) == 0) { - cache_addw(0x2000 + (dest_reg << 8) + (Bit8u)(imm >> 8)); // mov dest_reg, #(imm >> 8) - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (8 << 6)); // lsl dest_reg, dest_reg, #8 - } else if ((imm & 0xff00ffff) == 0) { - cache_addw(0x2000 + (dest_reg << 8) + (imm >> 16)); // mov dest_reg, #(imm >> 16) - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (16 << 6)); // lsl dest_reg, dest_reg, #16 - } else if ((imm & 0x00ffffff) == 0) { - cache_addw(0x2000 + (dest_reg << 8) + (imm >> 24)); // mov dest_reg, #(imm >> 24) - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (24 << 6)); // lsl dest_reg, dest_reg, #24 - } else { - Bit32u diff; - - diff = imm - ((Bit32u)cache.pos+4); - - if ((diff < 1024) && ((imm & 0x03) == 0)) { - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0xa000 + (dest_reg << 8) + (Bit8u)(diff >> 2)); // add dest_reg, pc, #(dist >> 2) - } else { - cache_addw(0x46c0); // nop - cache_addw(0xa000 + (dest_reg << 8) + (Bit8u)((diff - 2) >> 2)); // add dest_reg, pc, #((dist - 2) >> 2) - } - } else { - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0x4800 + (dest_reg << 8)); // ldr dest_reg, [pc, #0] - cache_addw(0xe000 + (2 >> 1)); // b next_code (pc+2) - cache_addd(imm); // .int imm - // next_code: - } else { - cache_addw(0x4800 + (dest_reg << 8) + (4 >> 2)); // ldr dest_reg, [pc, #4] - cache_addw(0xe000 + (4 >> 1)); // b next_code (pc+4) - cache_addw(0x46c0); // nop - cache_addd(imm); // .int imm - // next_code: - } - } - } -} - -// helper function for gen_mov_word_to_reg -static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)data & 3) { - if ( ((Bit32u)data & 3) == 2 ) { - cache_addw(0x8800 + dest_reg + (data_reg << 3)); // ldrh dest_reg, [data_reg] - cache_addw(0x8800 + templo1 + (data_reg << 3) + (2 << 5)); // ldrh templo1, [data_reg, #2] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (16 << 6)); // lsl templo1, templo1, #16 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - } else { - cache_addw(0x7800 + dest_reg + (data_reg << 3)); // ldrb dest_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (data_reg << 3) + (1 << 6)); // add templo1, data_reg, #1 - cache_addw(0x8800 + templo1 + (templo1 << 3)); // ldrh templo1, [templo1] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (8 << 6)); // lsl templo1, templo1, #8 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - cache_addw(0x7800 + templo1 + (data_reg << 3) + (3 << 6)); // ldrb templo1, [data_reg, #3] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (24 << 6)); // lsl templo1, templo1, #24 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - } - } else { - cache_addw(0x6800 + dest_reg + (data_reg << 3)); // ldr dest_reg, [data_reg] - } - } else { - if ((Bit32u)data & 1) { - cache_addw(0x7800 + dest_reg + (data_reg << 3)); // ldrb dest_reg, [data_reg] - cache_addw(0x7800 + templo1 + (data_reg << 3) + (1 << 6)); // ldrb templo1, [data_reg, #1] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (8 << 6)); // lsl templo1, templo1, #8 - cache_addw(0x4300 + dest_reg + (templo1 << 3)); // orr dest_reg, templo1 - } else { - cache_addw(0x8800 + dest_reg + (data_reg << 3)); // ldrh dest_reg, [data_reg] - } - } -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)data); - gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2); -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm); -} - -// helper function for gen_mov_word_from_reg -static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) { - // alignment.... - if (dword) { - if ((Bit32u)dest & 3) { - if ( ((Bit32u)dest & 3) == 2 ) { - cache_addw(0x8000 + src_reg + (data_reg << 3)); // strh src_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (16 << 6)); // lsr templo1, templo1, #16 - cache_addw(0x8000 + templo1 + (data_reg << 3) + (2 << 5)); // strh templo1, [data_reg, #2] - } else { - cache_addw(0x7000 + src_reg + (data_reg << 3)); // strb src_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (8 << 6)); // lsr templo1, templo1, #8 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (1 << 6)); // strb templo1, [data_reg, #1] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (16 << 6)); // lsr templo1, templo1, #16 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (2 << 6)); // strb templo1, [data_reg, #2] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (24 << 6)); // lsr templo1, templo1, #24 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (3 << 6)); // strb templo1, [data_reg, #3] - } - } else { - cache_addw(0x6000 + src_reg + (data_reg << 3)); // str src_reg, [data_reg] - } - } else { - if ((Bit32u)dest & 1) { - cache_addw(0x7000 + src_reg + (data_reg << 3)); // strb src_reg, [data_reg] - cache_addw(0x1c00 + templo1 + (src_reg << 3)); // mov templo1, src_reg - cache_addw(0x0800 + templo1 + (templo1 << 3) + (8 << 6)); // lsr templo1, templo1, #8 - cache_addw(0x7000 + templo1 + (data_reg << 3) + (1 << 6)); // strb templo1, [data_reg, #1] - } else { - cache_addw(0x8000 + src_reg + (data_reg << 3)); // strh src_reg, [data_reg] - } - } -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)data); - cache_addw(0x7800 + dest_reg + (templo1 << 3)); // ldrb dest_reg, [templo1] -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_addw(0x2000 + (dest_reg << 8) + imm); // mov dest_reg, #(imm) -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest); - cache_addw(0x7000 + src_reg + (templo1 << 3)); // strb src_reg, [templo1] -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - cache_addw(0x0000 + reg + (reg << 3) + (24 << 6)); // lsl reg, reg, #24 - - if (sign) { - cache_addw(0x1000 + reg + (reg << 3) + (24 << 6)); // asr reg, reg, #24 - } else { - cache_addw(0x0800 + reg + (reg << 3) + (24 << 6)); // lsr reg, reg, #24 - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - cache_addw(0x0000 + reg + (reg << 3) + (16 << 6)); // lsl reg, reg, #16 - - if (sign) { - cache_addw(0x1000 + reg + (reg << 3) + (16 << 6)); // asr reg, reg, #16 - } else { - cache_addw(0x0800 + reg + (reg << 3) + (16 << 6)); // lsr reg, reg, #16 - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - cache_addw(0x4680 + (temphi1 - HOST_r8) + (reg << 3)); // mov temphi1, reg - gen_mov_word_to_reg(reg, op, 1); - cache_addw(0x4440 + (reg) + ((temphi1 - HOST_r8) << 3)); // add reg, temphi1 -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - if(!imm) return; - gen_mov_dword_to_reg_imm(templo1, imm); - cache_addw(0x1800 + reg + (reg << 3) + (templo1 << 6)); // add reg, reg, templo1 -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - if(imm == 0xffffffff) return; - gen_mov_dword_to_reg_imm(templo1, imm); - cache_addw(0x4000 + reg + (templo1<< 3)); // and reg, templo1 -} - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templosav, imm); - gen_mov_word_from_reg(templosav, dest, 1); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add an 8bit constant value to a dword memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, 1, templo2); - if (imm >= 0) { - cache_addw(0x3000 + (templosav << 8) + ((Bit32s)imm)); // add templosav, #(imm) - } else { - cache_addw(0x3800 + (templosav << 8) + (-((Bit32s)imm))); // sub templosav, #(-imm) - } - gen_mov_word_from_reg_helper(templosav, dest, 1, templo2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_add_direct_byte(dest,(Bit8s)imm); - return; - } - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, dword, templo2); - if (dword) { - gen_mov_dword_to_reg_imm(templo1, imm); - } else { - gen_mov_word_to_reg_imm(templo1, (Bit16u)imm); - } - cache_addw(0x1800 + templosav + (templosav << 3) + (templo1 << 6)); // add templosav, templosav, templo1 - gen_mov_word_from_reg_helper(templosav, dest, dword, templo2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// subtract an 8bit constant value from a dword memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - if(!imm) return; - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, 1, templo2); - if (imm >= 0) { - cache_addw(0x3800 + (templosav << 8) + ((Bit32s)imm)); // sub templosav, #(imm) - } else { - cache_addw(0x3000 + (templosav << 8) + (-((Bit32s)imm))); // add templosav, #(-imm) - } - gen_mov_word_from_reg_helper(templosav, dest, 1, templo2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) { - gen_sub_direct_byte(dest,(Bit8s)imm); - return; - } - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest); - gen_mov_word_to_reg_helper(templosav, dest, dword, templo2); - if (dword) { - gen_mov_dword_to_reg_imm(templo1, imm); - } else { - gen_mov_word_to_reg_imm(templo1, (Bit16u)imm); - } - cache_addw(0x1a00 + templosav + (templosav << 3) + (templo1 << 6)); // sub templosav, templosav, templo1 - gen_mov_word_from_reg_helper(templosav, dest, dword, templo2); - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addw(0x0000 + templo1 + (scale_reg << 3) + (scale << 6)); // lsl templo1, scale_reg, #(scale) - cache_addw(0x1800 + dest_reg + (dest_reg << 3) + (templo1 << 6)); // add dest_reg, dest_reg, templo1 - } else { - cache_addw(0x1800 + dest_reg + (dest_reg << 3) + (scale_reg << 6)); // add dest_reg, dest_reg, scale_reg - } - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addw(0x0000 + dest_reg + (dest_reg << 3) + (scale << 6)); // lsl dest_reg, dest_reg, #(scale) - } - gen_add_imm(dest_reg, imm); -} - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0x4800 + (templo1 << 8) + (4 >> 2)); // ldr templo1, [pc, #4] - cache_addw(0xa000 + (templo2 << 8) + (8 >> 2)); // adr templo2, after_call (add templo2, pc, #8) - cache_addw(0x4680 + (HOST_lr - HOST_r8) + (templo2 << 3)); // mov lr, templo2 - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 --- switch to arm state - } else { - cache_addw(0x4800 + (templo1 << 8) + (8 >> 2)); // ldr templo1, [pc, #8] - cache_addw(0xa000 + (templo2 << 8) + (8 >> 2)); // adr templo2, after_call (add templo2, pc, #8) - cache_addw(0x4680 + (HOST_lr - HOST_r8) + (templo2 << 3)); // mov lr, templo2 - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 --- switch to arm state - cache_addw(0x46c0); // nop - } - cache_addd((Bit32u)func); // .int func - // after_call: - - // switch from arm to thumb state - cache_addd(0xe2800000 + (templo1 << 12) + (HOST_pc << 16) + (1)); // add templo1, pc, #1 - cache_addd(0xe12fff10 + (templo1)); // bx templo1 - - // thumb state from now on - cache_addw(0x1c00 + FC_RETOP + (HOST_a1 << 3)); // mov FC_RETOP, a1 -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_raw(func); - return proc_addr; - // if proc_addr is on word boundary ((proc_addr & 0x03) == 0) - // then length of generated code is 22 bytes - // otherwise length of generated code is 24 bytes -} - -#if (1) -// max of 4 parameters in a1-a4 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param, (void *)mem, 1); -} -#else - other arm abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - cache_addw(0x4680 + (temphi1 - HOST_r8) + (templosav << 3)); // mov temphi1, templosav - gen_mov_word_to_reg(templosav, ptr, 1); - - if (imm) { - gen_mov_dword_to_reg_imm(templo2, imm); - cache_addw(0x1800 + templosav + (templosav << 3) + (templo2 << 6)); // add templosav, templosav, templo2 - } - -#if (1) -// (*ptr) should be word aligned - if ((imm & 0x03) == 0) { - cache_addw(0x6800 + templo2 + (templosav << 3)); // ldr templo2, [templosav] - } else -#endif - { - cache_addw(0x7800 + templo2 + (templosav << 3)); // ldrb templo2, [templosav] - cache_addw(0x7800 + templo1 + (templosav << 3) + (1 << 6)); // ldrb templo1, [templosav, #1] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (8 << 6)); // lsl templo1, templo1, #8 - cache_addw(0x4300 + templo2 + (templo1 << 3)); // orr templo2, templo1 - cache_addw(0x7800 + templo1 + (templosav << 3) + (2 << 6)); // ldrb templo1, [templosav, #2] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (16 << 6)); // lsl templo1, templo1, #16 - cache_addw(0x4300 + templo2 + (templo1 << 3)); // orr templo2, templo1 - cache_addw(0x7800 + templo1 + (templosav << 3) + (3 << 6)); // ldrb templo1, [templosav, #3] - cache_addw(0x0000 + templo1 + (templo1 << 3) + (24 << 6)); // lsl templo1, templo1, #24 - cache_addw(0x4300 + templo2 + (templo1 << 3)); // orr templo2, templo1 - } - - // increase jmp address to keep thumb state - cache_addw(0x1c00 + templo2 + (templo2 << 3) + (1 << 6)); // add templo2, templo2, #1 - - cache_addw(0x4640 + templosav + ((temphi1 - HOST_r8) << 3)); // mov templosav, temphi1 - - cache_addw(0x4700 + (templo2 << 3)); // bx templo2 -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - if (dword) { - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - } else { - cache_addw(0x0000 + templo1 + (reg << 3) + (16 << 6)); // lsl templo1, reg, #16 - } - cache_addw(0xd000); // beq j - return ((Bit32u)cache.pos-2); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - if (dword) { - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - } else { - cache_addw(0x0000 + templo1 + (reg << 3) + (16 << 6)); // lsl templo1, reg, #16 - } - cache_addw(0xd100); // bne j - return ((Bit32u)cache.pos-2); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-(data+4); - if (len<0) len=-len; - if (len>252) LOG_MSG("Big jump %d",len); -#endif - *(Bit8u*)data=(Bit8u)( ((Bit32u)cache.pos-(data+4)) >> 1 ); -} - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - if (isdword) { - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - } else { - cache_addw(0x0000 + templo2 + (reg << 3) + (24 << 6)); // lsl templo2, reg, #24 - } - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0xd000 + (8 >> 1)); // beq nobranch (pc+8) - cache_addw(0x4800 + (templo1 << 8) + (4 >> 2)); // ldr templo1, [pc, #4] - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 - cache_addw(0x46c0); // nop - } else { - cache_addw(0xd000 + (6 >> 1)); // beq nobranch (pc+6) - cache_addw(0x4800 + (templo1 << 8)); // ldr templo1, [pc, #0] - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 - } - cache_addd(0); // fill j - // nobranch: - return ((Bit32u)cache.pos-4); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - cache_addw(0x2800 + (reg << 8)); // cmp reg, #0 - if (((Bit32u)cache.pos & 0x03) == 0) { - cache_addw(0xdc00 + (8 >> 1)); // bgt nobranch (pc+8) - cache_addw(0x4800 + (templo1 << 8) + (4 >> 2)); // ldr templo1, [pc, #4] - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 - cache_addw(0x46c0); // nop - } else { - cache_addw(0xdc00 + (6 >> 1)); // bgt nobranch (pc+6) - cache_addw(0x4800 + (templo1 << 8)); // ldr templo1, [pc, #0] - cache_addw(0x4700 + (templo1 << 3)); // bx templo1 - } - cache_addd(0); // fill j - // nobranch: - return ((Bit32u)cache.pos-4); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - // this is an absolute branch - *(Bit32u*)data=((Bit32u)cache.pos) + 1; // add 1 to keep processor in thumb state -} - -static void gen_run_code(void) { - // switch from arm to thumb state - cache_addd(0xe2800000 + (HOST_r3 << 12) + (HOST_pc << 16) + (1)); // add r3, pc, #1 - cache_addd(0xe12fff10 + (HOST_r3)); // bx r3 - - // thumb state from now on - cache_addw(0xb500); // push {lr} - cache_addw(0x4640 + HOST_r3 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov r3, FC_SEGS_ADDR - cache_addw(0x4640 + HOST_r2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov r2, FC_REGS_ADDR - cache_addw(0xb4fc); // push {r2,r3,v1-v4} - - // adr: 16 - cache_addw(0x4800 + (HOST_r3 << 8) + ((64 - (16 + 4)) >> 2)); // ldr r3, [pc, #(&Segs)] - // adr: 18 - cache_addw(0x4800 + (HOST_r2 << 8) + ((68 - (18 + 2)) >> 2)); // ldr r2, [pc, #(&cpu_regs)] - cache_addw(0x4680 + (FC_SEGS_ADDR - HOST_r8) + (HOST_r3 << 3)); // mov FC_SEGS_ADDR, r3 - cache_addw(0x4680 + (FC_REGS_ADDR - HOST_r8) + (HOST_r2 << 3)); // mov FC_REGS_ADDR, r2 - - // align 4 - - cache_addw(0xa302); // add r3, pc, #8 - cache_addw(0x3001); // add r0, #1 - cache_addw(0x3301); // add r3, #1 - cache_addw(0xb408); // push {r3} - cache_addw(0x4700); // bx r0 - cache_addw(0x46c0); // nop - - // align 4 - cache_addw(0xbcfc); // pop {r2,r3,v1-v4} - cache_addw(0x4680 + (FC_SEGS_ADDR - HOST_r8) + (HOST_r3 << 3)); // mov FC_SEGS_ADDR, r3 - cache_addw(0x4680 + (FC_REGS_ADDR - HOST_r8) + (HOST_r2 << 3)); // mov FC_REGS_ADDR, r2 - - cache_addw(0xbc08); // pop {r3} - cache_addw(0x4718); // bx r3 - // fill up to 64 bytes - cache_addw(0x46c0); // nop - cache_addd(0x46c046c0); // nop, nop - cache_addd(0x46c046c0); // nop, nop - cache_addd(0x46c046c0); // nop, nop - cache_addd(0x46c046c0); // nop, nop - - // adr: 64 - cache_addd((Bit32u)&Segs); // address of "Segs" - // adr: 68 - cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs" -} - -// return from a function -static void gen_return_function(void) { - cache_addw(0x1c00 + HOST_a1 + (FC_RETOP << 3)); // mov a1, FC_RETOP - cache_addw(0xbc08); // pop {r3} - cache_addw(0x4718); // bx r3 -} - -#ifdef DRC_FLAGS_INVALIDATION - -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - if (((Bit32u)pos & 0x03) == 0) - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=0x1800 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // add FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4300 + FC_RETOP + (HOST_a2 << 3); // orr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4000 + FC_RETOP + (HOST_a2 << 3); // and FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=0x1a00 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // sub FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4040 + FC_RETOP + (HOST_a2 << 3); // eor FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=0xe000 + (18 >> 1); // b after_call (pc+18) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // add FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=0x1e00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // sub FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4080 + FC_RETOP + (HOST_a2 << 3); // lsl FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_SHRb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // lsr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+4)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_SHRw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // lsr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+4)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_SHRd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_SARb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // asr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+4)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_SARw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // asr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+4)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_SARd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_RORb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+4)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+6)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+12)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_RORw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+4)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+6)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+8)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_RORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_ROLb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+10)=0x46c0; // nop - *(Bit16u*)(pos+12)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+14)=0x46c0; // nop - *(Bit16u*)(pos+16)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+18)=0x46c0; // nop - *(Bit16u*)(pos+20)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - break; - case t_ROLw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+12)=0xe000 + (6 >> 1); // b after_call (pc+6) - break; - case t_ROLd: - *(Bit16u*)pos=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+2)=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+4)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+6)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+8)=0xe000 + (10 >> 1); // b after_call (pc+10) - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=0x4240 + FC_RETOP + (HOST_a1 << 3); // neg FC_RETOP, a1 - *(Bit16u*)(pos+2)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - default: - *(Bit32u*)(pos+8)=(Bit32u)fct_ptr; // simple_func - break; - } - } - else - { - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit16u*)pos=0x1800 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // add FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (18 >> 1); // b after_call (pc+18) - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4300 + FC_RETOP + (HOST_a2 << 3); // orr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4000 + FC_RETOP + (HOST_a2 << 3); // and FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit16u*)pos=0x1a00 + FC_RETOP + (HOST_a1 << 3) + (HOST_a2 << 6); // sub FC_RETOP, a1, a2 - *(Bit16u*)(pos+2)=0xe000 + (18 >> 1); // b after_call (pc+18) - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4040 + FC_RETOP + (HOST_a2 << 3); // eor FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit16u*)pos=0xe000 + (20 >> 1); // b after_call (pc+20) - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // add FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (18 >> 1); // b after_call (pc+18) - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit16u*)pos=0x1e00 + FC_RETOP + (HOST_a1 << 3) + (1 << 6); // sub FC_RETOP, a1, #1 - *(Bit16u*)(pos+2)=0xe000 + (18 >> 1); // b after_call (pc+18) - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4080 + FC_RETOP + (HOST_a2 << 3); // lsl FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_SHRb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // lsr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+4)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_SHRw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // lsr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+4)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_SHRd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x40c0 + FC_RETOP + (HOST_a2 << 3); // lsr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_SARb: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (24 << 6); // lsl FC_RETOP, a1, #24 - *(Bit16u*)(pos+2)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (24 << 6); // asr FC_RETOP, FC_RETOP, #24 - *(Bit16u*)(pos+4)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_SARw: - *(Bit16u*)pos=0x0000 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsl FC_RETOP, a1, #16 - *(Bit16u*)(pos+2)=0x1000 + FC_RETOP + (FC_RETOP << 3) + (16 << 6); // asr FC_RETOP, FC_RETOP, #16 - *(Bit16u*)(pos+4)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+6)=0xe000 + (14 >> 1); // b after_call (pc+14) - break; - case t_SARd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x4100 + FC_RETOP + (HOST_a2 << 3); // asr FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_RORb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+4)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+6)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+12)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_RORw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+4)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+6)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+8)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_RORd: - *(Bit16u*)pos=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+2)=0x41c0 + FC_RETOP + (HOST_a2 << 3); // ror FC_RETOP, a2 - *(Bit16u*)(pos+4)=0xe000 + (16 >> 1); // b after_call (pc+16) - break; - case t_ROLb: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (24 << 6); // lsl a1, a1, #24 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (8 << 6); // lsr FC_RETOP, a1, #8 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + HOST_a1 + (FC_RETOP << 3); // orr a1, FC_RETOP - *(Bit16u*)(pos+10)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+12)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+14)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+16)=0xe000 + (4 >> 1); // b after_call (pc+4) - break; - case t_ROLw: - *(Bit16u*)pos=0x0000 + HOST_a1 + (HOST_a1 << 3) + (16 << 6); // lsl a1, a1, #16 - *(Bit16u*)(pos+2)=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+4)=0x0800 + FC_RETOP + (HOST_a1 << 3) + (16 << 6); // lsr FC_RETOP, a1, #16 - *(Bit16u*)(pos+6)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+8)=0x4300 + FC_RETOP + (HOST_a1 << 3); // orr FC_RETOP, a1 - *(Bit16u*)(pos+10)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+12)=0xe000 + (8 >> 1); // b after_call (pc+8) - break; - case t_ROLd: - *(Bit16u*)pos=0x4240 + templo1 + (HOST_a2 << 3); // neg templo1, a2 - *(Bit16u*)(pos+2)=0x1c00 + FC_RETOP + (HOST_a1 << 3); // mov FC_RETOP, a1 - *(Bit16u*)(pos+4)=0x3000 + (templo1 << 8) + (32); // add templo1, #32 - *(Bit16u*)(pos+6)=0x41c0 + FC_RETOP + (templo1 << 3); // ror FC_RETOP, templo1 - *(Bit16u*)(pos+8)=0xe000 + (12 >> 1); // b after_call (pc+12) - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit16u*)pos=0x4240 + FC_RETOP + (HOST_a1 << 3); // neg FC_RETOP, a1 - *(Bit16u*)(pos+2)=0xe000 + (18 >> 1); // b after_call (pc+18) - break; - default: - *(Bit32u*)(pos+10)=(Bit32u)fct_ptr; // simple_func - break; - } - - } -#else - if (((Bit32u)pos & 0x03) == 0) - { - *(Bit32u*)(pos+8)=(Bit32u)fct_ptr; // simple_func - } - else - { - *(Bit32u*)(pos+10)=(Bit32u)fct_ptr; // simple_func - } -#endif -} -#endif - -static void cache_block_before_close(void) { } - - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { - cache_addw(0x4640 + templo1 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_SEGS_ADDR - cache_addw(0x8800 + dest_reg + (templo1 << 3) + (index << 5)); // ldrh dest_reg, [templo1, #index] -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { - cache_addw(0x4640 + templo1 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_SEGS_ADDR - cache_addw(0x6800 + dest_reg + (templo1 << 3) + (index << 4)); // ldr dest_reg, [templo1, #index] -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { - cache_addw(0x4640 + templo1 + ((FC_SEGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_SEGS_ADDR - cache_addw(0x6800 + templo2 + (templo1 << 3) + (index << 4)); // ldr templo2, [templo1, #index] - cache_addw(0x1800 + reg + (reg << 3) + (templo2 << 6)); // add reg, reg, templo2 -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x8800 + dest_reg + (templo2 << 3) + (index << 5)); // ldrh dest_reg, [templo2, #index] -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x6800 + dest_reg + (templo2 << 3) + (index << 4)); // ldr dest_reg, [templo2, #index] -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - if (dword) { - cache_addw(0x6800 + dest_reg + (templo2 << 3) + (index << 4)); // ldr dest_reg, [templo2, #index] - } else { - cache_addw(0x8800 + dest_reg + (templo2 << 3) + (index << 5)); // ldrh dest_reg, [templo2, #index] - } -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x7800 + dest_reg + (templo2 << 3) + (index << 6)); // ldrb dest_reg, [templo2, #index] -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x7800 + dest_reg + (templo2 << 3) + (index << 6)); // ldrb dest_reg, [templo2, #index] -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { - cache_addw(0x4640 + templo2 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo2, FC_REGS_ADDR - cache_addw(0x6800 + templo1 + (templo2 << 3) + (index << 4)); // ldr templo1, [templo2, #index] - cache_addw(0x1800 + reg + (reg << 3) + (templo1 << 6)); // add reg, reg, templo1 -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - cache_addw(0x8000 + src_reg + (templo1 << 3) + (index << 5)); // strh src_reg, [templo1, #index] -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - cache_addw(0x6000 + src_reg + (templo1 << 3) + (index << 4)); // str src_reg, [templo1, #index] -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - if (dword) { - cache_addw(0x6000 + src_reg + (templo1 << 3) + (index << 4)); // str src_reg, [templo1, #index] - } else { - cache_addw(0x8000 + src_reg + (templo1 << 3) + (index << 5)); // strh src_reg, [templo1, #index] - } -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { - cache_addw(0x4640 + templo1 + ((FC_REGS_ADDR - HOST_r8) << 3)); // mov templo1, FC_REGS_ADDR - cache_addw(0x7000 + src_reg + (templo1 << 3) + (index << 6)); // strb src_reg, [templo1, #index] -} - -#endif diff --git a/src/cpu/core_dynrec/risc_mipsel32.h b/src/cpu/core_dynrec/risc_mipsel32.h deleted file mode 100644 index 1ddbf0c..0000000 --- a/src/cpu/core_dynrec/risc_mipsel32.h +++ /dev/null @@ -1,748 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_mipsel32.h,v 1.4 2008/09/19 16:48:03 c2woody Exp $ */ - - -/* MIPS32 (little endian) backend by crazyc */ - - -// some configuring defines that specify the capabilities of this architecture -// or aspects of the recompiling - -// protect FC_ADDR over function calls if necessaray -// #define DRC_PROTECT_ADDR_REG - -// try to use non-flags generating functions if possible -#define DRC_FLAGS_INVALIDATION -// try to replace _simple functions by code -#define DRC_FLAGS_INVALIDATION_DCODE - -// type with the same size as a pointer -#define DRC_PTR_SIZE_IM Bit32u - -// calling convention modifier -#define DRC_CALL_CONV /* nothing */ -#define DRC_FC /* nothing */ - -// use FC_REGS_ADDR to hold the address of "cpu_regs" and to access it using FC_REGS_ADDR -//#define DRC_USE_REGS_ADDR -// use FC_SEGS_ADDR to hold the address of "Segs" and to access it using FC_SEGS_ADDR -//#define DRC_USE_SEGS_ADDR - -// register mapping -typedef Bit8u HostReg; - -#define HOST_v0 2 -#define HOST_v1 3 -#define HOST_a0 4 -#define HOST_a1 5 -#define HOST_t4 12 -#define HOST_t5 13 -#define HOST_t6 14 -#define HOST_t7 15 -#define HOST_s0 16 -#define HOST_t8 24 -#define HOST_t9 25 -#define temp1 HOST_v1 -#define temp2 HOST_t9 - -// register that holds function return values -#define FC_RETOP HOST_v0 - -// register used for address calculations, -#define FC_ADDR HOST_s0 // has to be saved across calls, see DRC_PROTECT_ADDR_REG - -// register that holds the first parameter -#define FC_OP1 HOST_a0 - -// register that holds the second parameter -#define FC_OP2 HOST_a1 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_t5 - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_t6 - -// temporary register for LEA -#define TEMP_REG_DRC HOST_t7 - -#ifdef DRC_USE_REGS_ADDR -// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code -#define FC_REGS_ADDR HOST_??? -#endif - -#ifdef DRC_USE_SEGS_ADDR -// used to hold the address of "Segs" - preferably filled in function gen_run_code -#define FC_SEGS_ADDR HOST_??? -#endif - -// save some state to improve code gen -static bool temp1_valid = false; -static Bit32u temp1_value; - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - if(reg_src == reg_dst) return; - cache_addw((reg_dst<<11)+0x21); // addu reg_dst, $0, reg_src - cache_addw(reg_src); -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - if(imm < 65536) { - cache_addw((Bit16u)imm); // ori dest_reg, $0, imm - cache_addw(0x3400+dest_reg); - } else if(((Bit32s)imm < 0) && ((Bit32s)imm >= -32768)) { - cache_addw((Bit16u)imm); // addiu dest_reg, $0, imm - cache_addw(0x2400+dest_reg); - } else if(!(imm & 0xffff)) { - cache_addw((Bit16u)(imm >> 16)); // lui dest_reg, %hi(imm) - cache_addw(0x3c00+dest_reg); - } else { - cache_addw((Bit16u)(imm >> 16)); // lui dest_reg, %hi(imm) - cache_addw(0x3c00+dest_reg); - cache_addw((Bit16u)imm); // ori dest_reg, dest_reg, %lo(imm) - cache_addw(0x3400+(dest_reg<<5)+dest_reg); - } -} - -// this is the only place temp1 should be modified -static void INLINE mov_imm_to_temp1(Bit32u imm) { - if (temp1_valid && (temp1_value == imm)) return; - gen_mov_dword_to_reg_imm(temp1, imm); - temp1_valid = true; - temp1_value = imm; -} - -static Bit16s gen_addr_temp1(Bit32u addr) { - Bit32u hihalf = addr & 0xffff0000; - Bit16s lohalf = addr & 0xffff; - if (lohalf > 32764) { // [l,s]wl will overflow - hihalf = addr; - lohalf = 0; - } else if(lohalf < 0) hihalf += 0x10000; - mov_imm_to_temp1(hihalf); - return lohalf; -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - Bit16s lohalf = gen_addr_temp1((Bit32u)data); - // alignment.... - if (dword) { - if ((Bit32u)data & 3) { - cache_addw(lohalf+3); // lwl dest_reg, 3(temp1) - cache_addw(0x8800+(temp1<<5)+dest_reg); - cache_addw(lohalf); // lwr dest_reg, 0(temp1) - cache_addw(0x9800+(temp1<<5)+dest_reg); - } else { - cache_addw(lohalf); // lw dest_reg, 0(temp1) - cache_addw(0x8C00+(temp1<<5)+dest_reg); - } - } else { - if ((Bit32u)data & 1) { - cache_addw(lohalf); // lbu dest_reg, 0(temp1) - cache_addw(0x9000+(temp1<<5)+dest_reg); - cache_addw(lohalf+1); // lbu temp2, 1(temp1) - cache_addw(0x9000+(temp1<<5)+temp2); -#if (_MIPS_ISA==MIPS32R2) || defined(PSP) - cache_addw(0x7a04); // ins dest_reg, temp2, 8, 8 - cache_addw(0x7c00+(temp2<<5)+dest_reg); -#else - cache_addw((temp2<<11)+0x200); // sll temp2, temp2, 8 - cache_addw(temp2); - cache_addw((dest_reg<<11)+0x25); // or dest_reg, temp2, dest_reg - cache_addw((temp2<<5)+dest_reg); -#endif - } else { - cache_addw(lohalf); // lhu dest_reg, 0(temp1); - cache_addw(0x9400+(temp1<<5)+dest_reg); - } - } -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - cache_addw(imm); // ori dest_reg, $0, imm - cache_addw(0x3400+dest_reg); -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - Bit16s lohalf = gen_addr_temp1((Bit32u)dest); - // alignment.... - if (dword) { - if ((Bit32u)dest & 3) { - cache_addw(lohalf+3); // swl src_reg, 3(temp1) - cache_addw(0xA800+(temp1<<5)+src_reg); - cache_addw(lohalf); // swr src_reg, 0(temp1) - cache_addw(0xB800+(temp1<<5)+src_reg); - } else { - cache_addw(lohalf); // sw src_reg, 0(temp1) - cache_addw(0xAC00+(temp1<<5)+src_reg); - } - } else { - if((Bit32u)dest & 1) { - cache_addw(lohalf); // sb src_reg, 0(temp1) - cache_addw(0xA000+(temp1<<5)+src_reg); - cache_addw((temp2<<11)+0x202); // srl temp2, src_reg, 8 - cache_addw(src_reg); - cache_addw(lohalf+1); // sb temp2, 1(temp1) - cache_addw(0xA000+(temp1<<5)+temp2); - } else { - cache_addw(lohalf); // sh src_reg, 0(temp1); - cache_addw(0xA400+(temp1<<5)+src_reg); - } - } -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - Bit16s lohalf = gen_addr_temp1((Bit32u)data); - cache_addw(lohalf); // lbu dest_reg, 0(temp1) - cache_addw(0x9000+(temp1<<5)+dest_reg); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - gen_mov_byte_to_reg_low(dest_reg, data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - gen_mov_word_to_reg_imm(dest_reg, imm); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - gen_mov_byte_to_reg_low_imm(dest_reg, imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - Bit16s lohalf = gen_addr_temp1((Bit32u)dest); - cache_addw(lohalf); // sb src_reg, 0(temp1) - cache_addw(0xA000+(temp1<<5)+src_reg); -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - if (sign) { -#if (_MIPS_ISA==MIPS32R2) || defined(PSP) - cache_addw((reg<<11)+0x420); // seb reg, reg - cache_addw(0x7c00+reg); -#else - arch that lacks seb -#endif - } else { - cache_addw(0xff); // andi reg, reg, 0xff - cache_addw(0x3000+(reg<<5)+reg); - } -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - if (sign) { -#if (_MIPS_ISA==MIPS32R2) || defined(PSP) - cache_addw((reg<<11)+0x620); // seh reg, reg - cache_addw(0x7c00+reg); -#else - arch that lacks seh -#endif - } else { - cache_addw(0xffff); // andi reg, reg, 0xffff - cache_addw(0x3000+(reg<<5)+reg); - } -} - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - gen_mov_word_to_reg(temp2, op, 1); - cache_addw((reg<<11)+0x21); // addu reg, reg, temp2 - cache_addw((reg<<5)+temp2); -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - if(!imm) return; - if(((Bit32s)imm >= -32768) && ((Bit32s)imm < 32768)) { - cache_addw((Bit16u)imm); // addiu reg, reg, imm - cache_addw(0x2400+(reg<<5)+reg); - } else { - mov_imm_to_temp1(imm); - cache_addw((reg<<11)+0x21); // addu reg, reg, temp1 - cache_addw((reg<<5)+temp1); - } -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - if(imm < 65536) { - cache_addw((Bit16u)imm); // andi reg, reg, imm - cache_addw(0x3000+(reg<<5)+reg); - } else { - mov_imm_to_temp1((Bit32u)imm); - cache_addw((reg<<11)+0x24); // and reg, temp1, reg - cache_addw((temp1<<5)+reg); - } -} - - -// move a 32bit constant value into memory -static void INLINE gen_mov_direct_dword(void* dest,Bit32u imm) { - gen_mov_dword_to_reg_imm(temp2, imm); - gen_mov_word_from_reg(temp2, dest, 1); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void INLINE gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if(!imm) return; - gen_mov_word_to_reg(temp2, dest, dword); - gen_add_imm(temp2, imm); - gen_mov_word_from_reg(temp2, dest, dword); -} - -// add an 8bit constant value to a dword memory value -static void INLINE gen_add_direct_byte(void* dest,Bit8s imm) { - gen_add_direct_word(dest, (Bit32s)imm, 1); -} - -// subtract an 8bit constant value from a dword memory value -static void INLINE gen_sub_direct_byte(void* dest,Bit8s imm) { - gen_add_direct_word(dest, -((Bit32s)imm), 1); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void INLINE gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - gen_add_direct_word(dest, -(Bit32s)imm, dword); -} - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addw((scale_reg<<11)+(scale<<6)); // sll scale_reg, scale_reg, scale - cache_addw(scale_reg); - } - cache_addw((dest_reg<<11)+0x21); // addu dest_reg, dest_reg, scale_reg - cache_addw((dest_reg<<5)+scale_reg); - gen_add_imm(dest_reg, imm); -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - if (scale) { - cache_addw((dest_reg<<11)+(scale<<6)); // sll dest_reg, dest_reg, scale - cache_addw(dest_reg); - } - gen_add_imm(dest_reg, imm); -} - -#define DELAY cache_addd(0) // nop - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { -#if C_DEBUG - if ((cache.pos ^ func) & 0xf0000000) LOG_MSG("jump overflow\n"); -#endif - temp1_valid = false; - cache_addd(0x0c000000+(((Bit32u)func>>2)&0x3ffffff)); // jal func - DELAY; -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - Bit32u proc_addr = (Bit32u)cache.pos; - gen_call_function_raw(func); - return proc_addr; -} - -#ifdef __mips_eabi -// max of 8 parameters in $a0-$a3 and $t0-$t3 - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - gen_mov_dword_to_reg_imm(param+4, imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - gen_mov_dword_to_reg_imm(param+4, addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - gen_mov_regs(param+4, reg); -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - gen_mov_word_to_reg(param+4, (void *)mem, 1); -} -#else - other mips abis -#endif - -// jump to an address pointed at by ptr, offset is in imm -static void INLINE gen_jmp_ptr(void * ptr,Bits imm=0) { - gen_mov_word_to_reg(temp2, ptr, 1); - if((imm < -32768) || (imm >= 32768)) { - gen_add_imm(temp2, imm); - imm = 0; - } - temp1_valid = false; - cache_addw((Bit16u)imm); // lw temp2, imm(temp2) - cache_addw(0x8C00+(temp2<<5)+temp2); - cache_addd((temp2<<21)+8); // jr temp2 - DELAY; -} - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u INLINE gen_create_branch_on_zero(HostReg reg,bool dword) { - temp1_valid = false; - if(!dword) { - cache_addw(0xffff); // andi temp1, reg, 0xffff - cache_addw(0x3000+(reg<<5)+temp1); - } - cache_addw(0); // beq $0, reg, 0 - cache_addw(0x1000+(dword?reg:temp1)); - DELAY; - return ((Bit32u)cache.pos-8); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u INLINE gen_create_branch_on_nonzero(HostReg reg,bool dword) { - temp1_valid = false; - if(!dword) { - cache_addw(0xffff); // andi temp1, reg, 0xffff - cache_addw(0x3000+(reg<<5)+temp1); - } - cache_addw(0); // bne $0, reg, 0 - cache_addw(0x1400+(dword?reg:temp1)); - DELAY; - return ((Bit32u)cache.pos-8); -} - -// calculate relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-data; - if (len<0) len=-len; - if (len>126) LOG_MSG("Big jump %d",len); -#endif - temp1_valid = false; // this is a branch target - *(Bit16u*)data=((Bit16u)((Bit32u)cache.pos-data-4)>>2); -} - -#if 0 // assume for the moment no branch will go farther then +/- 128KB - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - temp1_valid = false; - if (!isdword) { - cache_addw(0xff); // andi temp1, reg, 0xff - cache_addw(0x3000+(reg<<5)+temp1); - } - cache_addw(3); // beq $0, reg, +12 - cache_addw(0x1000+(isdword?reg:temp1)); - DELAY; - cache_addd(0x00000000); // fill j - DELAY; - return ((Bit32u)cache.pos-8); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u INLINE gen_create_branch_long_leqzero(HostReg reg) { - temp1_valid = false; - cache_addw(3); // bgtz reg, +12 - cache_addw(0x1c00+(reg<<5)); - DELAY; - cache_addd(0x00000000); // fill j - DELAY; - return ((Bit32u)cache.pos-8); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - temp1_valid = false; - // this is an absolute branch - *(Bit32u*)data=0x08000000+(((Bit32u)cache.pos>>2)&0x3ffffff); -} -#else -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - temp1_valid = false; - if (!isdword) { - cache_addw(0xff); // andi temp1, reg, 0xff - cache_addw(0x3000+(reg<<5)+temp1); - } - cache_addw(0); // bne $0, reg, 0 - cache_addw(0x1400+(isdword?reg:temp1)); - DELAY; - return ((Bit32u)cache.pos-8); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u INLINE gen_create_branch_long_leqzero(HostReg reg) { - temp1_valid = false; - cache_addw(0); // blez reg, 0 - cache_addw(0x1800+(reg<<5)); - DELAY; - return ((Bit32u)cache.pos-8); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void INLINE gen_fill_branch_long(Bit32u data) { - gen_fill_branch(data); -} -#endif - -static void gen_run_code(void) { - temp1_valid = false; - cache_addd(0x27bdfff0); // addiu $sp, $sp, -16 - cache_addd(0xafb00004); // sw $s0, 4($sp) - cache_addd(0x00800008); // jr $a0 - cache_addd(0xafbf0000); // sw $ra, 0($sp) -} - -// return from a function -static void gen_return_function(void) { - temp1_valid = false; - cache_addd(0x8fbf0000); // lw $ra, 0($sp) - cache_addd(0x8fb00004); // lw $s0, 4($sp) - cache_addd(0x03e00008); // jr $ra - cache_addd(0x27bd0010); // addiu $sp, $sp, 16 -} - -#ifdef DRC_FLAGS_INVALIDATION -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit32u*)pos=0x00851021; // addu $v0, $a0, $a1 - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit32u*)pos=0x00851025; // or $v0, $a0, $a1 - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit32u*)pos=0x00851024; // and $v0, $a0, $a1 - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit32u*)pos=0x00851023; // subu $v0, $a0, $a1 - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit32u*)pos=0x00851026; // xor $v0, $a0, $a1 - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit32u*)pos=0; // nop - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit32u*)pos=0x24820001; // addiu $v0, $a0, 1 - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit32u*)pos=0x2482ffff; // addiu $v0, $a0, -1 - break; - case t_SHLb: - case t_SHLw: - case t_SHLd: - *(Bit32u*)pos=0x00a41004; // sllv $v0, $a0, $a1 - break; - case t_SHRb: - case t_SHRw: - case t_SHRd: - *(Bit32u*)pos=0x00a41006; // srlv $v0, $a0, $a1 - break; - case t_SARd: - *(Bit32u*)pos=0x00a41007; // srav $v0, $a0, $a1 - break; -#if (_MIPS_ISA==MIPS32R2) || defined(PSP) - case t_RORd: - *(Bit32u*)pos=0x00a41046; // rotr $v0, $a0, $a1 - break; -#endif - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit32u*)pos=0x00041023; // subu $v0, $0, $a0 - break; - default: - *(Bit32u*)pos=0x0c000000+((((Bit32u)fct_ptr)>>2)&0x3ffffff); // jal simple_func - break; - } -#else - *(Bit32u*)pos=0x0c000000+(((Bit32u)fct_ptr)>>2)&0x3ffffff); // jal simple_func -#endif -} -#endif - -static void cache_block_closing(Bit8u* block_start,Bitu block_size) { -#ifdef PSP -// writeback dcache and invalidate icache - Bit32u inval_start = ((Bit32u)block_start) & ~63; - Bit32u inval_end = (((Bit32u)block_start) + block_size + 64) & ~63; - for (;inval_start < inval_end; inval_start+=64) { - __builtin_allegrex_cache(0x1a, inval_start); - __builtin_allegrex_cache(0x08, inval_start); - } -#endif -} - -static void cache_block_before_close(void) { } - - -#ifdef DRC_USE_SEGS_ADDR - -// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) { -// stub -} - -// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) { -// stub -} - -// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero) -static void gen_add_seg32_to_reg(HostReg reg,Bitu index) { -// stub -} - -#endif - -#ifdef DRC_USE_REGS_ADDR - -// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) { -// stub -} - -// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) { -// stub -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) { -// stub -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) { -// stub -} - -// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) { -// stub -} - - -// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_add_regval32_to_reg(HostReg reg,Bitu index) { -// stub -} - - -// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero) -static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) { -// stub -} - -// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero) -static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) { -// stub -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero) -static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) { -// stub -} - -// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR -static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) { -// stub -} - -#endif diff --git a/src/cpu/core_dynrec/risc_x64.h b/src/cpu/core_dynrec/risc_x64.h deleted file mode 100644 index 74de7f4..0000000 --- a/src/cpu/core_dynrec/risc_x64.h +++ /dev/null @@ -1,679 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_x64.h,v 1.11 2008/09/02 20:44:41 c2woody Exp $ */ - - -// some configuring defines that specify the capabilities of this architecture -// or aspects of the recompiling - -// protect FC_ADDR over function calls if necessaray -// #define DRC_PROTECT_ADDR_REG - -// try to use non-flags generating functions if possible -#define DRC_FLAGS_INVALIDATION -// try to replace _simple functions by code -#define DRC_FLAGS_INVALIDATION_DCODE - -// type with the same size as a pointer -#define DRC_PTR_SIZE_IM Bit64u - -// calling convention modifier -#define DRC_CALL_CONV /* nothing */ -#define DRC_FC /* nothing */ - - -// register mapping -typedef Bit8u HostReg; - -#define HOST_EAX 0 -#define HOST_ECX 1 -#define HOST_EDX 2 -#define HOST_EBX 3 -#define HOST_ESI 6 -#define HOST_EDI 7 - - -// register that holds function return values -#define FC_RETOP HOST_EAX - -// register used for address calculations, if the ABI does not -// state that this register is preserved across function calls -// then define DRC_PROTECT_ADDR_REG above -#define FC_ADDR HOST_EBX - -// register that holds the first parameter -#define FC_OP1 HOST_EDI - -// register that holds the second parameter -#define FC_OP2 HOST_ESI - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_ECX - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_EDX - - -// temporary register for LEA -#define TEMP_REG_DRC HOST_ESI - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - cache_addb(0x8b); // mov reg_dst,reg_src - cache_addb(0xc0+(reg_dst<<3)+reg_src); -} - - -static INLINE void gen_memaddr(HostReg reg,void* data) { - Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+5); - if ((diff<0x80000000LL) && (diff>-0x80000000LL)) { - cache_addb(0x05+(reg<<3)); - // RIP-relative addressing is offset after the instruction - cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL)); - } else if ((Bit64u)data<0x100000000LL) { - cache_addw(0x2504+(reg<<3)); - cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL)); - } else { - E_Exit("DRC64:Unhandled memory reference"); - } -} - - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x8b); // mov reg,[data] - gen_memaddr(dest_reg,data); -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - cache_addb(0x66); - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addw(imm); -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addd(imm); -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x89); // mov [data],reg - gen_memaddr(src_reg,dest); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - cache_addb(0x8a); // mov reg,[data] - gen_memaddr(dest_reg,data); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - cache_addb(0x66); - cache_addb(0x8b); // mov reg,[data] - gen_memaddr(dest_reg,data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_addb(0xb0+dest_reg); // mov reg,imm - cache_addb(imm); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - cache_addb(0x66); - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addw(imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - cache_addb(0x88); // mov [data],reg - gen_memaddr(src_reg,dest); -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - cache_addw(0xb60f+(sign?0x800:0)); // movsx/movzx - cache_addb(0xc0+(reg<<3)+reg); -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - cache_addw(0xb70f+(sign?0x800:0)); // movsx/movzx - cache_addb(0xc0+(reg<<3)+reg); -} - - - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - cache_addb(0x03); // add reg,[data] - gen_memaddr(reg,op); -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - cache_addw(0xc081+(reg<<8)); // add reg,imm - cache_addd(imm); -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - cache_addw(0xe081+(reg<<8)); // and reg,imm - cache_addd(imm); -} - - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - cache_addw(0x04c7); // mov [data],imm - cache_addb(0x25); - cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); - cache_addd(imm); -} - -// move a 64bit constant value into a full register -static void gen_mov_reg_qword(HostReg dest_reg,Bit64u imm) { - cache_addb(0x48); - cache_addb(0xb8+dest_reg); // mov dest_reg,imm - cache_addq(imm); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_reg_qword(HOST_EAX,imm); - cache_addb(0x48); - gen_mov_word_from_reg(HOST_EAX,dest,true); -} - - -// add an 8bit constant value to a memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - cache_addw(0x0483); // add [data],imm - cache_addb(0x25); - cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); - cache_addb(imm); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if ((imm<128) && dword) { - gen_add_direct_byte(dest,(Bit8s)imm); - return; - } - if (!dword) cache_addb(0x66); - cache_addw(0x0481); // add [data],imm - cache_addb(0x25); - cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); - if (dword) cache_addd((Bit32u)imm); - else cache_addw((Bit16u)imm); -} - -// subtract an 8bit constant value from a memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - cache_addw(0x2c83); // sub [data],imm - cache_addb(0x25); - cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); - cache_addb(imm); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - if ((imm<128) && dword) { - gen_sub_direct_byte(dest,(Bit8s)imm); - return; - } - if (!dword) cache_addb(0x66); - cache_addw(0x2c81); // sub [data],imm - cache_addb(0x25); - cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); - if (dword) cache_addd((Bit32u)imm); - else cache_addw((Bit16u)imm); -} - - - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - Bit8u rm_base; - Bitu imm_size; - if (!imm) { - imm_size=0; rm_base=0x0; //no imm - } else if ((imm>=-128 && imm<=127)) { - imm_size=1; rm_base=0x40; //Signed byte imm - } else { - imm_size=4; rm_base=0x80; //Signed dword imm - } - - // ea_reg := ea_reg+TEMP_REG_DRC*(2^scale)+imm - // ea_reg := op1 + op2 *(2^scale)+imm - cache_addb(0x48); - cache_addb(0x8d); //LEA - cache_addb(0x04+(dest_reg << 3)+rm_base); //The sib indicator - cache_addb(dest_reg+(TEMP_REG_DRC<<3)+(scale<<6)); - - switch (imm_size) { - case 0: break; - case 1:cache_addb(imm);break; - case 4:cache_addd(imm);break; - } -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - // ea_reg := ea_reg*(2^scale)+imm - // ea_reg := op2 *(2^scale)+imm - cache_addb(0x48); - cache_addb(0x8d); //LEA - cache_addb(0x04+(dest_reg<<3)); - cache_addb(0x05+(dest_reg<<3)+(scale<<6)); - - cache_addd(imm); // always add dword immediate -} - - - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_addb(0x48); - cache_addb(0xb8); // mov reg,imm64 - cache_addq((Bit64u)func); - cache_addw(0xd0ff); -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit64u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - // align the stack - cache_addb(0x48); - cache_addw(0xc48b); // mov rax,rsp - - cache_addb(0x48); - cache_addw(0xec83); // sub rsp,0x08 - cache_addb(0x08); // 0x08==return address pushed onto stack by call - - cache_addb(0x48); - cache_addw(0xe483); // and esp,0xfffffffffffffff0 - cache_addb(0xf0); - - cache_addb(0x48); - cache_addw(0xc483); // add rsp,0x08 - cache_addb(0x08); - - cache_addb(0x50); // push rax (==old rsp) - - Bit64u proc_addr=(Bit64u)cache.pos; - - // Do the actual call to the procedure - cache_addb(0x48); - cache_addb(0xb8); // mov reg,imm64 - cache_addq((Bit64u)func); - - cache_addw(0xd0ff); - - // restore stack - cache_addb(0x5c); // pop rsp - - return proc_addr; -} - - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - // move an immediate 32bit value into a 64bit param reg - switch (param) { - case 0: // mov param1,imm32 - gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)imm); - break; - case 1: // mov param2,imm32 - gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm); - break; -#if defined (_MSC_VER) - case 2: // mov r8,imm32 - cache_addw(0xb849); - cache_addq((Bit32u)imm); - break; - case 3: // mov r9,imm32 - cache_addw(0xb949); - cache_addq((Bit32u)imm); - break; -#else - case 2: // mov rdx,imm32 - gen_mov_dword_to_reg_imm(HOST_EDX,(Bit32u)imm); - break; - case 3: // mov rcx,imm32 - gen_mov_dword_to_reg_imm(HOST_ECX,(Bit32u)imm); - break; -#endif - default: - E_Exit("I(mm) >4 params unsupported"); - break; - } -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(DRC_PTR_SIZE_IM addr,Bitu param) { - // move an immediate 64bit value into a 64bit param reg - switch (param) { - case 0: // mov param1,addr64 - gen_mov_reg_qword(FC_OP1,addr); - break; - case 1: // mov param2,addr64 - gen_mov_reg_qword(FC_OP2,addr); - break; -#if defined (_MSC_VER) - case 2: // mov r8,addr64 - cache_addw(0xb849); - cache_addq(addr); - break; - case 3: // mov r9,addr64 - cache_addw(0xb949); - cache_addq(addr); - break; -#else - case 2: // mov rdx,addr64 - gen_mov_reg_qword(HOST_EDX,addr); - break; - case 3: // mov rcx,addr64 - gen_mov_reg_qword(HOST_ECX,addr); - break; -#endif - default: - E_Exit("A(ddr) >4 params unsupported"); - break; - } -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - // move a register into a 64bit param reg, {inputregs}!={outputregs} - switch (param) { - case 0: // mov param1,reg&7 - gen_mov_regs(FC_OP1,reg&7); - break; - case 1: // mov param2,reg&7 - gen_mov_regs(FC_OP2,reg&7); - break; -#if defined (_MSC_VER) - case 2: // mov r8,reg&7 - cache_addb(0x49); - gen_mov_regs(0,reg&7); - break; - case 3: // mov r9,reg&7 - cache_addb(0x49); - gen_mov_regs(1,reg&7); - break; -#else - case 2: // mov rdx,reg&7 - gen_mov_regs(HOST_EDX,reg&7); - break; - case 3: // mov rcx,reg&7 - gen_mov_regs(HOST_ECX,reg&7); - break; -#endif - default: - E_Exit("R(eg) >4 params unsupported"); - break; - } -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - // move memory content into a 64bit param reg - switch (param) { - case 0: // mov param1,[mem] - gen_mov_word_to_reg(FC_OP1,(void*)mem,true); - break; - case 1: // mov param2,[mem] - gen_mov_word_to_reg(FC_OP2,(void*)mem,true); - break; -#if defined (_MSC_VER) - case 2: // mov r8,[mem] - cache_addb(0x49); - gen_mov_word_to_reg(0,(void*)mem,true); - break; - case 3: // mov r9,[mem] - cache_addb(0x49); - gen_mov_word_to_reg(1,(void*)mem,true); - break; -#else - case 2: // mov rdx,[mem] - gen_mov_word_to_reg(HOST_EDX,(void*)mem,true); - break; - case 3: // mov rcx,[mem] - gen_mov_word_to_reg(HOST_ECX,(void*)mem,true); - break; -#endif - default: - E_Exit("R(eg) >4 params unsupported"); - break; - } -} - - - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - cache_addw(0xa148); // mov rax,[data] - cache_addq((Bit64u)ptr); - - cache_addb(0xff); // jmp [rax+imm] - if (!imm) { - cache_addb(0x20); - } else if ((imm>=-128 && imm<=127)) { - cache_addb(0x60); - cache_addb(imm); - } else { - cache_addb(0xa0); - cache_addd(imm); - } -} - - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit64u gen_create_branch_on_zero(HostReg reg,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x0b); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x0074); // jz addr - return ((Bit64u)cache.pos-1); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit64u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x0b); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x0075); // jnz addr - return ((Bit64u)cache.pos-1); -} - -// calculate relative offset and fill it into the location pointed to by data -static void gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bit64s len=(Bit64u)cache.pos-data; - if (len<0) len=-len; - if (len>126) LOG_MSG("Big jump %d",len); -#endif - *(Bit8u*)data=(Bit8u)((Bit64u)cache.pos-data-1); -} - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit64u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - // isdword: cmp reg32,0 - // not isdword: cmp reg8,0 - cache_addb(0x0a+(isdword?1:0)); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x850f); // jnz - cache_addd(0); - return ((Bit64u)cache.pos-4); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit64u gen_create_branch_long_leqzero(HostReg reg) { - cache_addw(0xf883+(reg<<8)); - cache_addb(0x00); // cmp reg,0 - - cache_addw(0x8e0f); // jle - cache_addd(0); - return ((Bit64u)cache.pos-4); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void gen_fill_branch_long(Bit64u data) { - *(Bit32u*)data=(Bit32u)((Bit64u)cache.pos-data-4); -} - - -static void gen_run_code(void) { - cache_addb(0x53); // push rbx - cache_addw(0xd0ff+(FC_OP1<<8)); // call rdi - cache_addb(0x5b); // pop rbx -} - -// return from a function -static void gen_return_function(void) { - cache_addb(0xc3); // ret -} - -#ifdef DRC_FLAGS_INVALIDATION -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit32u*)(pos+0)=0xf001f889; // mov eax,edi; add eax,esi - *(Bit32u*)(pos+4)=0x909006eb; // skip - *(Bit32u*)(pos+8)=0x90909090; - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit32u*)(pos+0)=0xf009f889; // mov eax,edi; or eax,esi - *(Bit32u*)(pos+4)=0x909006eb; // skip - *(Bit32u*)(pos+8)=0x90909090; - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit32u*)(pos+0)=0xf021f889; // mov eax,edi; and eax,esi - *(Bit32u*)(pos+4)=0x909006eb; // skip - *(Bit32u*)(pos+8)=0x90909090; - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit32u*)(pos+0)=0xf029f889; // mov eax,edi; sub eax,esi - *(Bit32u*)(pos+4)=0x909006eb; // skip - *(Bit32u*)(pos+8)=0x90909090; - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit32u*)(pos+0)=0xf031f889; // mov eax,edi; xor eax,esi - *(Bit32u*)(pos+4)=0x909006eb; // skip - *(Bit32u*)(pos+8)=0x90909090; - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit32u*)(pos+0)=0x90900aeb; // skip - *(Bit32u*)(pos+4)=0x90909090; - *(Bit32u*)(pos+8)=0x90909090; - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit32u*)(pos+0)=0xc0fff889; // mov eax,edi; inc eax - *(Bit32u*)(pos+4)=0x909006eb; // skip - *(Bit32u*)(pos+8)=0x90909090; - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit32u*)(pos+0)=0xc8fff889; // mov eax,edi; dec eax - *(Bit32u*)(pos+4)=0x909006eb; // skip - *(Bit32u*)(pos+8)=0x90909090; - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit32u*)(pos+0)=0xd8f7f889; // mov eax,edi; neg eax - *(Bit32u*)(pos+4)=0x909006eb; // skip - *(Bit32u*)(pos+8)=0x90909090; - break; - default: - *(Bit64u*)(pos+2)=(Bit64u)fct_ptr; // fill function pointer - break; - } -#else - *(Bit64u*)(pos+2)=(Bit64u)fct_ptr; -#endif -} -#endif - -static void cache_block_closing(Bit8u* block_start,Bitu block_size) { } - -static void cache_block_before_close(void) { } diff --git a/src/cpu/core_dynrec/risc_x86.h b/src/cpu/core_dynrec/risc_x86.h deleted file mode 100644 index 3a8d598..0000000 --- a/src/cpu/core_dynrec/risc_x86.h +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: risc_x86.h,v 1.8 2008/09/02 20:44:41 c2woody Exp $ */ - - -// some configuring defines that specify the capabilities of this architecture -// or aspects of the recompiling - -// protect FC_ADDR over function calls if necessaray -// #define DRC_PROTECT_ADDR_REG - -// try to use non-flags generating functions if possible -#define DRC_FLAGS_INVALIDATION -// try to replace _simple functions by code -#define DRC_FLAGS_INVALIDATION_DCODE - -// type with the same size as a pointer -#define DRC_PTR_SIZE_IM Bit32u - -// calling convention modifier -#if defined (WIN32) -#define DRC_CALL_CONV _fastcall -#define DRC_FC /* nothing */ -#else -#define DRC_CALL_CONV /* nothing */ -#define DRC_FC GCC_ATTRIBUTE(fastcall) -#endif - - -// register mapping -enum HostReg { - HOST_EAX=0, - HOST_ECX, - HOST_EDX, - HOST_EBX, - HOST_ESP, - HOST_EBP, - HOST_ESI, - HOST_EDI -}; - - -// register that holds function return values -#define FC_RETOP HOST_EAX - -// register used for address calculations, if the ABI does not -// state that this register is preserved across function calls -// then define DRC_PROTECT_ADDR_REG above -#define FC_ADDR HOST_EBX - -// register that holds the first parameter -#define FC_OP1 HOST_ECX - -// register that holds the second parameter -#define FC_OP2 HOST_EDX - -// register that holds byte-accessible temporary values -#define FC_TMP_BA1 HOST_ECX - -// register that holds byte-accessible temporary values -#define FC_TMP_BA2 HOST_EDX - - -// temporary register for LEA -#define TEMP_REG_DRC HOST_ESI - - -// move a full register from reg_src to reg_dst -static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { - cache_addb(0x8b); // mov reg_dst,reg_src - cache_addb(0xc0+(reg_dst<<3)+reg_src); -} - -// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg -// 16bit moves may destroy the upper 16bit of the destination register -static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { - if (!dword) cache_addb(0x66); - cache_addw(0x058b+(dest_reg<<11)); // mov reg,[data] - cache_addd((Bit32u)data); -} - -// move a 16bit constant value into dest_reg -// the upper 16bit of the destination register may be destroyed -static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { - cache_addb(0x66); - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addw(imm); -} - -// move a 32bit constant value into dest_reg -static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addd(imm); -} - -// move 32bit (dword==true) or 16bit (dword==false) of a register into memory -static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { - if (!dword) cache_addb(0x66); - cache_addw(0x0589+(src_reg<<11)); // mov [data],reg - cache_addd((Bit32u)dest); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { - cache_addw(0x058a+(dest_reg<<11)); // mov reg,[data] - cache_addd((Bit32u)data); -} - -// move an 8bit value from memory into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { - cache_addb(0x66); - cache_addw(0x058b+(dest_reg<<11)); // mov reg,[data] - cache_addd((Bit32u)data); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function does not use FC_OP1/FC_OP2 as dest_reg as these -// registers might not be directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { - cache_addb(0xb0+dest_reg); // mov reg,imm - cache_addb(imm); -} - -// move an 8bit constant value into dest_reg -// the upper 24bit of the destination register can be destroyed -// this function can use FC_OP1/FC_OP2 as dest_reg which are -// not directly byte-accessible on some architectures -static void gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { - cache_addb(0x66); - cache_addb(0xb8+dest_reg); // mov reg,imm - cache_addw(imm); -} - -// move the lowest 8bit of a register into memory -static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { - cache_addw(0x0588+(src_reg<<11)); // mov [data],reg - cache_addd((Bit32u)dest); -} - - - -// convert an 8bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_byte(bool sign,HostReg reg) { - cache_addw(0xb60f+(sign?0x800:0)); // movsx/movzx - cache_addb(0xc0+(reg<<3)+reg); -} - -// convert a 16bit word to a 32bit dword -// the register is zero-extended (sign==false) or sign-extended (sign==true) -static void gen_extend_word(bool sign,HostReg reg) { - cache_addw(0xb70f+(sign?0x800:0)); // movsx/movzx - cache_addb(0xc0+(reg<<3)+reg); -} - - - -// add a 32bit value from memory to a full register -static void gen_add(HostReg reg,void* op) { - cache_addw(0x0503+(reg<<11)); // add reg,[data] - cache_addd((Bit32u)op); -} - -// add a 32bit constant value to a full register -static void gen_add_imm(HostReg reg,Bit32u imm) { - cache_addw(0xc081+(reg<<8)); // add reg,imm - cache_addd(imm); -} - -// and a 32bit constant value with a full register -static void gen_and_imm(HostReg reg,Bit32u imm) { - cache_addw(0xe081+(reg<<8)); // and reg,imm - cache_addd(imm); -} - - - -// move a 32bit constant value into memory -static void gen_mov_direct_dword(void* dest,Bit32u imm) { - cache_addw(0x05c7); // mov [data],imm - cache_addd((Bit32u)dest); - cache_addd(imm); -} - -// move an address into memory -static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { - gen_mov_direct_dword(dest,(Bit32u)imm); -} - - -// add an 8bit constant value to a memory value -static void gen_add_direct_byte(void* dest,Bit8s imm) { - cache_addw(0x0583); // add [data],imm - cache_addd((Bit32u)dest); - cache_addb(imm); -} - -// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value -static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) { - if ((imm<128) && dword) { - gen_add_direct_byte(dest,(Bit8s)imm); - return; - } - if (!dword) cache_addb(0x66); - cache_addw(0x0581); // add [data],imm - cache_addd((Bit32u)dest); - if (dword) cache_addd((Bit32u)imm); - else cache_addw((Bit16u)imm); -} - -// subtract an 8bit constant value from a memory value -static void gen_sub_direct_byte(void* dest,Bit8s imm) { - cache_addw(0x2d83); // sub [data],imm - cache_addd((Bit32u)dest); - cache_addb(imm); -} - -// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value -static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { - if ((imm<128) && dword) { - gen_sub_direct_byte(dest,(Bit8s)imm); - return; - } - if (!dword) cache_addb(0x66); - cache_addw(0x2d81); // sub [data],imm - cache_addd((Bit32u)dest); - if (dword) cache_addd((Bit32u)imm); - else cache_addw((Bit16u)imm); -} - - - -// effective address calculation, destination is dest_reg -// scale_reg is scaled by scale (scale_reg*(2^scale)) and -// added to dest_reg, then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) { - Bit8u rm_base; - Bitu imm_size; - if (!imm) { - imm_size=0; rm_base=0x0; //no imm - } else if ((imm>=-128 && imm<=127)) { - imm_size=1; rm_base=0x40; //Signed byte imm - } else { - imm_size=4; rm_base=0x80; //Signed dword imm - } - - // ea_reg := ea_reg+TEMP_REG_DRC*(2^scale)+imm - // ea_reg := op1 + op2 *(2^scale)+imm - cache_addb(0x8d); //LEA - cache_addb(0x04+(dest_reg << 3)+rm_base); //The sib indicator - cache_addb(dest_reg+(TEMP_REG_DRC<<3)+(scale<<6)); - - switch (imm_size) { - case 0: break; - case 1:cache_addb(imm);break; - case 4:cache_addd(imm);break; - } -} - -// effective address calculation, destination is dest_reg -// dest_reg is scaled by scale (dest_reg*(2^scale)), -// then the immediate value is added -static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) { - // ea_reg := ea_reg*(2^scale)+imm - // ea_reg := op2 *(2^scale)+imm - cache_addb(0x8d); //LEA - cache_addb(0x04+(dest_reg<<3)); - cache_addb(0x05+(dest_reg<<3)+(scale<<6)); - - cache_addd(imm); // always add dword immediate -} - - - -// generate a call to a parameterless function -static void INLINE gen_call_function_raw(void * func) { - cache_addb(0xe8); - cache_addd((Bit32u)func - (Bit32u)cache.pos-4); -} - -// generate a call to a function with paramcount parameters -// note: the parameters are loaded in the architecture specific way -// using the gen_load_param_ functions below -static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) { - Bit32u proc_addr=(Bit32u)cache.pos; - // Do the actual call to the procedure - cache_addb(0xe8); - cache_addd((Bit32u)func - (Bit32u)cache.pos-4); - - // Restore the params of the stack - if (paramcount) { - cache_addw(0xc483); //add ESP,imm byte - cache_addb((!fastcall)?paramcount*4:0); - } - return proc_addr; -} - - -// load an immediate value as param'th function parameter -static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { - cache_addb(0x68); // push immediate - cache_addd(imm); -} - -// load an address as param'th function parameter -static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { - cache_addb(0x68); // push immediate (address) - cache_addd(addr); -} - -// load a host-register as param'th function parameter -static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { - cache_addb(0x50+(reg&7)); // push reg -} - -// load a value from memory as param'th function parameter -static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { - cache_addw(0x35ff); // push [] - cache_addd(mem); -} - - - -// jump to an address pointed at by ptr, offset is in imm -static void gen_jmp_ptr(void * ptr,Bits imm=0) { - gen_mov_word_to_reg(HOST_EAX,ptr,true); - cache_addb(0xff); // jmp [eax+imm] - if (!imm) { - cache_addb(0x20); - } else if ((imm>=-128 && imm<=127)) { - cache_addb(0x60); - cache_addb(imm); - } else { - cache_addb(0xa0); - cache_addd(imm); - } -} - - -// short conditional jump (+-127 bytes) if register is zero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x0b); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x0074); // jz addr - return ((Bit32u)cache.pos-1); -} - -// short conditional jump (+-127 bytes) if register is nonzero -// the destination is set by gen_fill_branch() later -static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) { - if (!dword) cache_addb(0x66); - cache_addb(0x0b); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x0075); // jnz addr - return ((Bit32u)cache.pos-1); -} - -// calculate relative offset and fill it into the location pointed to by data -static void gen_fill_branch(DRC_PTR_SIZE_IM data) { -#if C_DEBUG - Bits len=(Bit32u)cache.pos-data; - if (len<0) len=-len; - if (len>126) LOG_MSG("Big jump %d",len); -#endif - *(Bit8u*)data=(Bit8u)((Bit32u)cache.pos-data-1); -} - -// conditional jump if register is nonzero -// for isdword==true the 32bit of the register are tested -// for isdword==false the lowest 8bit of the register are tested -static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { - // isdword: cmp reg32,0 - // not isdword: cmp reg8,0 - cache_addb(0x0a+(isdword?1:0)); // or reg,reg - cache_addb(0xc0+reg+(reg<<3)); - - cache_addw(0x850f); // jnz - cache_addd(0); - return ((Bit32u)cache.pos-4); -} - -// compare 32bit-register against zero and jump if value less/equal than zero -static Bit32u gen_create_branch_long_leqzero(HostReg reg) { - cache_addw(0xf883+(reg<<8)); - cache_addb(0x00); // cmp reg,0 - - cache_addw(0x8e0f); // jle - cache_addd(0); - return ((Bit32u)cache.pos-4); -} - -// calculate long relative offset and fill it into the location pointed to by data -static void gen_fill_branch_long(Bit32u data) { - *(Bit32u*)data=((Bit32u)cache.pos-data-4); -} - - -static void gen_run_code(void) { - cache_addd(0x0424448b); // mov eax,[esp+4] - cache_addb(0x53); // push ebx - cache_addw(0xd0ff); // call eax - cache_addb(0x5b); // pop ebx -} - -// return from a function -static void gen_return_function(void) { - cache_addb(0xc3); // ret -} - -#ifdef DRC_FLAGS_INVALIDATION -// called when a call to a function can be replaced by a -// call to a simpler function -static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { -#ifdef DRC_FLAGS_INVALIDATION_DCODE - // try to avoid function calls but rather directly fill in code - switch (flags_type) { - case t_ADDb: - case t_ADDw: - case t_ADDd: - *(Bit32u*)pos=0xc203c18b; // mov eax,ecx; add eax,edx - *(pos+4)=0x90; - break; - case t_ORb: - case t_ORw: - case t_ORd: - *(Bit32u*)pos=0xc20bc18b; // mov eax,ecx; or eax,edx - *(pos+4)=0x90; - break; - case t_ANDb: - case t_ANDw: - case t_ANDd: - *(Bit32u*)pos=0xc223c18b; // mov eax,ecx; and eax,edx - *(pos+4)=0x90; - break; - case t_SUBb: - case t_SUBw: - case t_SUBd: - *(Bit32u*)pos=0xc22bc18b; // mov eax,ecx; sub eax,edx - *(pos+4)=0x90; - break; - case t_XORb: - case t_XORw: - case t_XORd: - *(Bit32u*)pos=0xc233c18b; // mov eax,ecx; xor eax,edx - *(pos+4)=0x90; - break; - case t_CMPb: - case t_CMPw: - case t_CMPd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - *(Bit32u*)pos=0x909003eb; // skip - *(pos+4)=0x90; - break; - case t_INCb: - case t_INCw: - case t_INCd: - *(Bit32u*)pos=0x9040c18b; // mov eax,ecx; inc eax - *(pos+4)=0x90; - break; - case t_DECb: - case t_DECw: - case t_DECd: - *(Bit32u*)pos=0x9048c18b; // mov eax,ecx; dec eax - *(pos+4)=0x90; - break; - case t_NEGb: - case t_NEGw: - case t_NEGd: - *(Bit32u*)pos=0xd8f7c18b; // mov eax,ecx; neg eax - *(pos+4)=0x90; - break; - default: - *(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4)); // fill function pointer - break; - } -#else - *(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4)); // fill function pointer -#endif -} -#endif - -static void cache_block_closing(Bit8u* block_start,Bitu block_size) { } - -static void cache_block_before_close(void) { } diff --git a/src/cpu/core_full.cpp b/src/cpu/core_full.cpp deleted file mode 100644 index 43282b0..0000000 --- a/src/cpu/core_full.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "dosbox.h" - -#include "pic.h" -#include "regs.h" -#include "cpu.h" -#include "lazyflags.h" -#include "paging.h" -#include "fpu.h" -#include "debug.h" -#include "inout.h" -#include "callback.h" - - -typedef PhysPt EAPoint; -#define SegBase(c) SegPhys(c) - -#define LoadMb(off) mem_readb_inline(off) -#define LoadMw(off) mem_readw_inline(off) -#define LoadMd(off) mem_readd_inline(off) - -#define LoadMbs(off) (Bit8s)(LoadMb(off)) -#define LoadMws(off) (Bit16s)(LoadMw(off)) -#define LoadMds(off) (Bit32s)(LoadMd(off)) - -#define SaveMb(off,val) mem_writeb_inline(off,val) -#define SaveMw(off,val) mem_writew_inline(off,val) -#define SaveMd(off,val) mem_writed_inline(off,val) - -#define LoadD(reg) reg -#define SaveD(reg,val) reg=val - - - -#include "core_full/loadwrite.h" -#include "core_full/support.h" -#include "core_full/optable.h" -#include "instructions.h" - -#define EXCEPTION(blah) \ - { \ - Bit8u new_num=blah; \ - CPU_Exception(new_num,0); \ - continue; \ - } - -Bits CPU_Core_Full_Run(void) { - FullData inst; - while (CPU_Cycles-->0) { -#if C_DEBUG - cycle_count++; -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) { - FillFlags(); - return debugCallback; - }; -#endif -#endif - LoadIP(); - inst.entry=cpu.code.big*0x200; - inst.prefix=cpu.code.big; -restartopcode: - inst.entry=(inst.entry & 0xffffff00) | Fetchb(); - inst.code=OpCodeTable[inst.entry]; - #include "core_full/load.h" - #include "core_full/op.h" - #include "core_full/save.h" -nextopcode:; - SaveIP(); - continue; -illegalopcode: - LOG(LOG_CPU,LOG_NORMAL)("Illegal opcode"); - CPU_Exception(0x6,0); - } - FillFlags(); - return CBRET_NONE; -} - - -void CPU_Core_Full_Init(void) { - -} diff --git a/src/cpu/core_full/Makefile.am b/src/cpu/core_full/Makefile.am deleted file mode 100644 index f14506d..0000000 --- a/src/cpu/core_full/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ - -noinst_HEADERS = ea_lookup.h load.h loadwrite.h op.h optable.h save.h \ - string.h support.h diff --git a/src/cpu/core_full/ea_lookup.h b/src/cpu/core_full/ea_lookup.h deleted file mode 100644 index b10d9b5..0000000 --- a/src/cpu/core_full/ea_lookup.h +++ /dev/null @@ -1,237 +0,0 @@ -{ - EAPoint seg_base; - Bit16u off; - switch ((inst.rm_mod<<3)|inst.rm_eai) { - case 0x00: - off=reg_bx+reg_si; - seg_base=SegBase(ds); - break; - case 0x01: - off=reg_bx+reg_di; - seg_base=SegBase(ds); - break; - case 0x02: - off=reg_bp+reg_si; - seg_base=SegBase(ss); - break; - case 0x03: - off=reg_bp+reg_di; - seg_base=SegBase(ss); - break; - case 0x04: - off=reg_si; - seg_base=SegBase(ds); - break; - case 0x05: - off=reg_di; - seg_base=SegBase(ds); - break; - case 0x06: - off=Fetchw(); - seg_base=SegBase(ds); - break; - case 0x07: - off=reg_bx; - seg_base=SegBase(ds); - break; - - case 0x08: - off=reg_bx+reg_si+Fetchbs(); - seg_base=SegBase(ds); - break; - case 0x09: - off=reg_bx+reg_di+Fetchbs(); - seg_base=SegBase(ds); - break; - case 0x0a: - off=reg_bp+reg_si+Fetchbs(); - seg_base=SegBase(ss); - break; - case 0x0b: - off=reg_bp+reg_di+Fetchbs(); - seg_base=SegBase(ss); - break; - case 0x0c: - off=reg_si+Fetchbs(); - seg_base=SegBase(ds); - break; - case 0x0d: - off=reg_di+Fetchbs(); - seg_base=SegBase(ds); - break; - case 0x0e: - off=reg_bp+Fetchbs(); - seg_base=SegBase(ss); - break; - case 0x0f: - off=reg_bx+Fetchbs(); - seg_base=SegBase(ds); - break; - - case 0x10: - off=reg_bx+reg_si+Fetchws(); - seg_base=SegBase(ds); - break; - case 0x11: - off=reg_bx+reg_di+Fetchws(); - seg_base=SegBase(ds); - break; - case 0x12: - off=reg_bp+reg_si+Fetchws(); - seg_base=SegBase(ss); - break; - case 0x13: - off=reg_bp+reg_di+Fetchws(); - seg_base=SegBase(ss); - break; - case 0x14: - off=reg_si+Fetchws(); - seg_base=SegBase(ds); - break; - case 0x15: - off=reg_di+Fetchws(); - seg_base=SegBase(ds); - break; - case 0x16: - off=reg_bp+Fetchws(); - seg_base=SegBase(ss); - break; - case 0x17: - off=reg_bx+Fetchws(); - seg_base=SegBase(ds); - break; - } - inst.rm_off=off; - if (inst.prefix & PREFIX_SEG) { - inst.rm_eaa=inst.seg.base+off; - } else { - inst.rm_eaa=seg_base+off; - } -} else { - - -#define SIB(MODE) { \ - Bitu sib=Fetchb(); \ - switch (sib&7) { \ - case 0:seg_base=SegBase(ds);off=reg_eax;break; \ - case 1:seg_base=SegBase(ds);off=reg_ecx;break; \ - case 2:seg_base=SegBase(ds);off=reg_edx;break; \ - case 3:seg_base=SegBase(ds);off=reg_ebx;break; \ - case 4:seg_base=SegBase(ss);off=reg_esp;break; \ - case 5:if (!MODE) { seg_base=SegBase(ds);off=Fetchd();break; \ - } else { seg_base=SegBase(ss);off=reg_ebp;break;} \ - case 6:seg_base=SegBase(ds);off=reg_esi;break; \ - case 7:seg_base=SegBase(ds);off=reg_edi;break; \ - } \ - off+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); \ -}; - static Bit32u SIBZero=0; - static Bit32u * SIBIndex[8]= { ®_eax,®_ecx,®_edx,®_ebx,&SIBZero,®_ebp,®_esi,®_edi }; - EAPoint seg_base; - Bit32u off; - switch ((inst.rm_mod<<3)|inst.rm_eai) { - case 0x00: - off=reg_eax; - seg_base=SegBase(ds); - break; - case 0x01: - off=reg_ecx; - seg_base=SegBase(ds); - break; - case 0x02: - off=reg_edx; - seg_base=SegBase(ds); - break; - case 0x03: - off=reg_ebx; - seg_base=SegBase(ds); - break; - case 0x04: - SIB(0); - break; - case 0x05: - off=Fetchd(); - seg_base=SegBase(ds); - break; - case 0x06: - off=reg_esi; - seg_base=SegBase(ds); - break; - case 0x07: - off=reg_edi; - seg_base=SegBase(ds); - break; - - case 0x08: - off=reg_eax+Fetchbs(); - seg_base=SegBase(ds); - break; - case 0x09: - off=reg_ecx+Fetchbs(); - seg_base=SegBase(ds); - break; - case 0x0a: - off=reg_edx+Fetchbs(); - seg_base=SegBase(ds); - break; - case 0x0b: - off=reg_ebx+Fetchbs(); - seg_base=SegBase(ds); - break; - case 0x0c: - SIB(1); - off+=Fetchbs(); - break; - case 0x0d: - off=reg_ebp+Fetchbs(); - seg_base=SegBase(ss); - break; - case 0x0e: - off=reg_esi+Fetchbs(); - seg_base=SegBase(ds); - break; - case 0x0f: - off=reg_edi+Fetchbs(); - seg_base=SegBase(ds); - break; - - case 0x10: - off=reg_eax+Fetchds(); - seg_base=SegBase(ds); - break; - case 0x11: - off=reg_ecx+Fetchds(); - seg_base=SegBase(ds); - break; - case 0x12: - off=reg_edx+Fetchds(); - seg_base=SegBase(ds); - break; - case 0x13: - off=reg_ebx+Fetchds(); - seg_base=SegBase(ds); - break; - case 0x14: - SIB(1); - off+=Fetchds(); - break; - case 0x15: - off=reg_ebp+Fetchds(); - seg_base=SegBase(ss); - break; - case 0x16: - off=reg_esi+Fetchds(); - seg_base=SegBase(ds); - break; - case 0x17: - off=reg_edi+Fetchds(); - seg_base=SegBase(ds); - break; - } - inst.rm_off=off; - if (inst.prefix & PREFIX_SEG) { - inst.rm_eaa=inst.seg.base+off; - } else { - inst.rm_eaa=seg_base+off; - } -} diff --git a/src/cpu/core_full/load.h b/src/cpu/core_full/load.h deleted file mode 100644 index 6e3fa8d..0000000 --- a/src/cpu/core_full/load.h +++ /dev/null @@ -1,489 +0,0 @@ -switch (inst.code.load) { -/* General loading */ - case L_POPwRM: - inst_op1_w = Pop_16(); - goto case_L_MODRM; - case L_POPdRM: - inst_op1_d = Pop_32(); - goto case_L_MODRM; - case L_MODRM_NVM: - if ((reg_flags & FLAG_VM) || !cpu.pmode) goto illegalopcode; - goto case_L_MODRM; -case_L_MODRM: - case L_MODRM: - inst.rm=Fetchb(); - inst.rm_index=(inst.rm >> 3) & 7; - inst.rm_eai=inst.rm&07; - inst.rm_mod=inst.rm>>6; - /* Decode address of mod/rm if needed */ - if (inst.rm<0xc0) { - if (!(inst.prefix & PREFIX_ADDR)) - #include "ea_lookup.h" - } -l_MODRMswitch: - switch (inst.code.extra) { -/* Byte */ - case M_Ib: - inst_op1_d=Fetchb(); - break; - case M_Ebx: - if (inst.rm<0xc0) inst_op1_ds=(Bit8s)LoadMb(inst.rm_eaa); - else inst_op1_ds=(Bit8s)reg_8(inst.rm_eai); - break; - case M_EbIb: - inst_op2_d=Fetchb(); - case M_Eb: - if (inst.rm<0xc0) inst_op1_d=LoadMb(inst.rm_eaa); - else inst_op1_d=reg_8(inst.rm_eai); - break; - case M_EbGb: - if (inst.rm<0xc0) inst_op1_d=LoadMb(inst.rm_eaa); - else inst_op1_d=reg_8(inst.rm_eai); - inst_op2_d=reg_8(inst.rm_index); - break; - case M_GbEb: - if (inst.rm<0xc0) inst_op2_d=LoadMb(inst.rm_eaa); - else inst_op2_d=reg_8(inst.rm_eai); - case M_Gb: - inst_op1_d=reg_8(inst.rm_index);; - break; -/* Word */ - case M_Iw: - inst_op1_d=Fetchw(); - break; - case M_EwxGwx: - inst_op2_ds=(Bit16s)reg_16(inst.rm_index); - goto l_M_Ewx; - case M_EwxIbx: - inst_op2_ds=Fetchbs(); - goto l_M_Ewx; - case M_EwxIwx: - inst_op2_ds=Fetchws(); -l_M_Ewx: - case M_Ewx: - if (inst.rm<0xc0) inst_op1_ds=(Bit16s)LoadMw(inst.rm_eaa); - else inst_op1_ds=(Bit16s)reg_16(inst.rm_eai); - break; - case M_EwIb: - inst_op2_d=Fetchb(); - goto l_M_Ew; - case M_EwIbx: - inst_op2_ds=Fetchbs(); - goto l_M_Ew; - case M_EwIw: - inst_op2_d=Fetchw(); - goto l_M_Ew; - case M_EwGwCL: - inst_imm_d=reg_cl; - goto l_M_EwGw; - case M_EwGwIb: - inst_imm_d=Fetchb(); - goto l_M_EwGw; - case M_EwGwt: - inst_op2_d=reg_16(inst.rm_index); - inst.rm_eaa+=((Bit16s)inst_op2_d >> 4) * 2; - goto l_M_Ew; -l_M_EwGw: - case M_EwGw: - inst_op2_d=reg_16(inst.rm_index); -l_M_Ew: - case M_Ew: - if (inst.rm<0xc0) inst_op1_d=LoadMw(inst.rm_eaa); - else inst_op1_d=reg_16(inst.rm_eai); - break; - case M_GwEw: - if (inst.rm<0xc0) inst_op2_d=LoadMw(inst.rm_eaa); - else inst_op2_d=reg_16(inst.rm_eai); - case M_Gw: - inst_op1_d=reg_16(inst.rm_index);; - break; -/* DWord */ - case M_Id: - inst_op1_d=Fetchd(); - break; - case M_EdxGdx: - inst_op2_ds=(Bit32s)reg_32(inst.rm_index); - case M_Edx: - if (inst.rm<0xc0) inst_op1_d=(Bit32s)LoadMd(inst.rm_eaa); - else inst_op1_d=(Bit32s)reg_32(inst.rm_eai); - break; - case M_EdIb: - inst_op2_d=Fetchb(); - goto l_M_Ed; - case M_EdIbx: - inst_op2_ds=Fetchbs(); - goto l_M_Ed; - case M_EdId: - inst_op2_d=Fetchd(); - goto l_M_Ed; - case M_EdGdCL: - inst_imm_d=reg_cl; - goto l_M_EdGd; - case M_EdGdt: - inst_op2_d=reg_32(inst.rm_index); - inst.rm_eaa+=((Bit32s)inst_op2_d >> 5) * 4; - goto l_M_Ed; - case M_EdGdIb: - inst_imm_d=Fetchb(); - goto l_M_EdGd; -l_M_EdGd: - case M_EdGd: - inst_op2_d=reg_32(inst.rm_index); -l_M_Ed: - case M_Ed: - if (inst.rm<0xc0) inst_op1_d=LoadMd(inst.rm_eaa); - else inst_op1_d=reg_32(inst.rm_eai); - break; - case M_GdEd: - if (inst.rm<0xc0) inst_op2_d=LoadMd(inst.rm_eaa); - else inst_op2_d=reg_32(inst.rm_eai); - case M_Gd: - inst_op1_d=reg_32(inst.rm_index); - break; -/* Others */ - - case M_SEG: - //TODO Check for limit - inst_op1_d=SegValue((SegNames)inst.rm_index); - break; - case M_Efw: - if (inst.rm>=0xc0) goto illegalopcode; - inst_op1_d=LoadMw(inst.rm_eaa); - inst_op2_d=LoadMw(inst.rm_eaa+2); - break; - case M_Efd: - if (inst.rm>=0xc0) goto illegalopcode; - inst_op1_d=LoadMd(inst.rm_eaa); - inst_op2_d=LoadMw(inst.rm_eaa+4); - break; - case M_EA: - inst_op1_d=inst.rm_off; - break; - case M_POPw: - inst_op1_d = Pop_16(); - break; - case M_POPd: - inst_op1_d = Pop_32(); - break; - case M_GRP: - inst.code=Groups[inst.code.op][inst.rm_index]; - goto l_MODRMswitch; - case M_GRP_Ib: - inst_op2_d=Fetchb(); - inst.code=Groups[inst.code.op][inst.rm_index]; - goto l_MODRMswitch; - case M_GRP_CL: - inst_op2_d=reg_cl; - inst.code=Groups[inst.code.op][inst.rm_index]; - goto l_MODRMswitch; - case M_GRP_1: - inst_op2_d=1; - inst.code=Groups[inst.code.op][inst.rm_index]; - goto l_MODRMswitch; - case 0: - break; - default: - LOG(LOG_CPU,LOG_ERROR)("MODRM:Unhandled load %d entry %x",inst.code.extra,inst.entry); - break; - } - break; - case L_POPw: - inst_op1_d = Pop_16(); - break; - case L_POPd: - inst_op1_d = Pop_32(); - break; - case L_POPfw: - inst_op1_d = Pop_16(); - inst_op2_d = Pop_16(); - break; - case L_POPfd: - inst_op1_d = Pop_32(); - inst_op2_d = Pop_16(); - break; - case L_Ib: - inst_op1_d=Fetchb(); - break; - case L_Ibx: - inst_op1_ds=Fetchbs(); - break; - case L_Iw: - inst_op1_d=Fetchw(); - break; - case L_Iwx: - inst_op1_ds=Fetchws(); - break; - case L_Idx: - case L_Id: - inst_op1_d=Fetchd(); - break; - case L_Ifw: - inst_op1_d=Fetchw(); - inst_op2_d=Fetchw(); - break; - case L_Ifd: - inst_op1_d=Fetchd(); - inst_op2_d=Fetchw(); - break; -/* Direct load of registers */ - case L_REGbIb: - inst_op2_d=Fetchb(); - case L_REGb: - inst_op1_d=reg_8(inst.code.extra); - break; - case L_REGwIw: - inst_op2_d=Fetchw(); - case L_REGw: - inst_op1_d=reg_16(inst.code.extra); - break; - case L_REGdId: - inst_op2_d=Fetchd(); - case L_REGd: - inst_op1_d=reg_32(inst.code.extra); - break; - case L_SEG: - inst_op1_d=SegValue((SegNames)inst.code.extra); - break; -/* Depending on addressize */ - case L_OP: - if (inst.prefix & PREFIX_ADDR) { - inst.rm_eaa=Fetchd(); - } else { - inst.rm_eaa=Fetchw(); - } - if (inst.prefix & PREFIX_SEG) { - inst.rm_eaa+=inst.seg.base; - } else { - inst.rm_eaa+=SegBase(ds); - } - break; - /* Special cases */ - case L_DOUBLE: - inst.entry|=0x100; - goto restartopcode; - case L_PRESEG: - inst.prefix|=PREFIX_SEG; - inst.seg.base=SegBase((SegNames)inst.code.extra); - goto restartopcode; - case L_PREREPNE: - inst.prefix|=PREFIX_REP; - inst.repz=false; - goto restartopcode; - case L_PREREP: - inst.prefix|=PREFIX_REP; - inst.repz=true; - goto restartopcode; - case L_PREOP: - inst.entry=(cpu.code.big ^1) * 0x200; - goto restartopcode; - case L_PREADD: - inst.prefix=(inst.prefix & ~1) | (cpu.code.big ^ 1); - goto restartopcode; - case L_VAL: - inst_op1_d=inst.code.extra; - break; - case L_INTO: - if (!get_OF()) goto nextopcode; - inst_op1_d=4; - break; - case D_IRETw: - CPU_IRET(false,GetIP()); - if (GETFLAG(IF) && PIC_IRQCheck) { - return CBRET_NONE; - } - continue; - case D_IRETd: - CPU_IRET(true,GetIP()); - if (GETFLAG(IF) && PIC_IRQCheck) - return CBRET_NONE; - continue; - case D_RETFwIw: - { - Bitu words=Fetchw(); - FillFlags(); - CPU_RET(false,words,GetIP()); - continue; - } - case D_RETFw: - FillFlags(); - CPU_RET(false,0,GetIP()); - continue; - case D_RETFdIw: - { - Bitu words=Fetchw(); - FillFlags(); - CPU_RET(true,words,GetIP()); - continue; - } - case D_RETFd: - FillFlags(); - CPU_RET(true,0,GetIP()); - continue; -/* Direct operations */ - case L_STRING: - #include "string.h" - goto nextopcode; - case D_PUSHAw: - { - Bit16u old_sp=reg_sp; - Push_16(reg_ax);Push_16(reg_cx);Push_16(reg_dx);Push_16(reg_bx); - Push_16(old_sp);Push_16(reg_bp);Push_16(reg_si);Push_16(reg_di); - } - goto nextopcode; - case D_PUSHAd: - { - Bit32u old_esp=reg_esp; - Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx); - Push_32(old_esp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi); - } - goto nextopcode; - case D_POPAw: - reg_di=Pop_16();reg_si=Pop_16();reg_bp=Pop_16();Pop_16();//Don't save SP - reg_bx=Pop_16();reg_dx=Pop_16();reg_cx=Pop_16();reg_ax=Pop_16(); - goto nextopcode; - case D_POPAd: - reg_edi=Pop_32();reg_esi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP - reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32(); - goto nextopcode; - case D_POPSEGw: - if (CPU_PopSeg((SegNames)inst.code.extra,false)) RunException(); - goto nextopcode; - case D_POPSEGd: - if (CPU_PopSeg((SegNames)inst.code.extra,true)) RunException(); - goto nextopcode; - case D_SETALC: - reg_al = get_CF() ? 0xFF : 0; - goto nextopcode; - case D_XLAT: - if (inst.prefix & PREFIX_SEG) { - if (inst.prefix & PREFIX_ADDR) { - reg_al=LoadMb(inst.seg.base+(Bit32u)(reg_ebx+reg_al)); - } else { - reg_al=LoadMb(inst.seg.base+(Bit16u)(reg_bx+reg_al)); - } - } else { - if (inst.prefix & PREFIX_ADDR) { - reg_al=LoadMb(SegBase(ds)+(Bit32u)(reg_ebx+reg_al)); - } else { - reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al)); - } - } - goto nextopcode; - case D_CBW: - reg_ax=(Bit8s)reg_al; - goto nextopcode; - case D_CWDE: - reg_eax=(Bit16s)reg_ax; - goto nextopcode; - case D_CWD: - if (reg_ax & 0x8000) reg_dx=0xffff; - else reg_dx=0; - goto nextopcode; - case D_CDQ: - if (reg_eax & 0x80000000) reg_edx=0xffffffff; - else reg_edx=0; - goto nextopcode; - case D_CLI: - if (CPU_CLI()) RunException(); - goto nextopcode; - case D_STI: - if (CPU_STI()) RunException(); - goto nextopcode; - case D_STC: - FillFlags();SETFLAGBIT(CF,true); - goto nextopcode; - case D_CLC: - FillFlags();SETFLAGBIT(CF,false); - goto nextopcode; - case D_CMC: - FillFlags(); - SETFLAGBIT(CF,!(reg_flags & FLAG_CF)); - goto nextopcode; - case D_CLD: - SETFLAGBIT(DF,false); - cpu.direction=1; - goto nextopcode; - case D_STD: - SETFLAGBIT(DF,true); - cpu.direction=-1; - goto nextopcode; - case D_PUSHF: - if (CPU_PUSHF(inst.code.extra)) RunException(); - goto nextopcode; - case D_POPF: - if (CPU_POPF(inst.code.extra)) RunException(); - if (GETFLAG(IF) && PIC_IRQCheck) { - SaveIP(); - return CBRET_NONE; - } - goto nextopcode; - case D_SAHF: - SETFLAGSb(reg_ah); - goto nextopcode; - case D_LAHF: - FillFlags(); - reg_ah=reg_flags&0xff; - goto nextopcode; - case D_WAIT: - case D_NOP: - goto nextopcode; - case D_LOCK: /* FIXME: according to intel, LOCK should raise an exception if it's not followed by one of a small set of instructions; - probably doesn't matter for our purposes as it is a pentium prefix anyhow */ - LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK"); - goto nextopcode; - case D_ENTERw: - { - Bitu bytes=Fetchw(); - Bitu level=Fetchb(); - CPU_ENTER(false,bytes,level); - goto nextopcode; - } - case D_ENTERd: - { - Bitu bytes=Fetchw(); - Bitu level=Fetchb(); - CPU_ENTER(true,bytes,level); - goto nextopcode; - } - case D_LEAVEw: - reg_esp&=cpu.stack.notmask; - reg_esp|=(reg_ebp&cpu.stack.mask); - reg_bp=Pop_16(); - goto nextopcode; - case D_LEAVEd: - reg_esp&=cpu.stack.notmask; - reg_esp|=(reg_ebp&cpu.stack.mask); - reg_ebp=Pop_32(); - goto nextopcode; - case D_DAA: - DAA(); - goto nextopcode; - case D_DAS: - DAS(); - goto nextopcode; - case D_AAA: - AAA(); - goto nextopcode; - case D_AAS: - AAS(); - goto nextopcode; - case D_CPUID: - if (!CPU_CPUID()) goto illegalopcode; - goto nextopcode; - case D_HLT: - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - FillFlags(); - CPU_HLT(GetIP()); - return CBRET_NONE; - case D_CLTS: - if (cpu.pmode && cpu.cpl) goto illegalopcode; - cpu.cr0&=(~CR0_TASKSWITCH); - goto nextopcode; - case D_ICEBP: - CPU_SW_Interrupt_NoIOPLCheck(1,GetIP()); - continue; - default: - LOG(LOG_CPU,LOG_ERROR)("LOAD:Unhandled code %d opcode %X",inst.code.load,inst.entry); - goto illegalopcode; -} - diff --git a/src/cpu/core_full/loadwrite.h b/src/cpu/core_full/loadwrite.h deleted file mode 100644 index 887c2a9..0000000 --- a/src/cpu/core_full/loadwrite.h +++ /dev/null @@ -1,39 +0,0 @@ -#define SaveIP() reg_eip=(Bit32u)(inst.cseip-SegBase(cs)); -#define LoadIP() inst.cseip=SegBase(cs)+reg_eip; -#define GetIP() (inst.cseip-SegBase(cs)) - -#define RunException() { \ - CPU_Exception(cpu.exception.which,cpu.exception.error); \ - continue; \ -} - -static INLINE Bit8u the_Fetchb(EAPoint & loc) { - Bit8u temp=LoadMb(loc); - loc+=1; - return temp; -} - -static INLINE Bit16u the_Fetchw(EAPoint & loc) { - Bit16u temp=LoadMw(loc); - loc+=2; - return temp; -} -static INLINE Bit32u the_Fetchd(EAPoint & loc) { - Bit32u temp=LoadMd(loc); - loc+=4; - return temp; -} - -#define Fetchb() the_Fetchb(inst.cseip) -#define Fetchw() the_Fetchw(inst.cseip) -#define Fetchd() the_Fetchd(inst.cseip) - -#define Fetchbs() (Bit8s)the_Fetchb(inst.cseip) -#define Fetchws() (Bit16s)the_Fetchw(inst.cseip) -#define Fetchds() (Bit32s)the_Fetchd(inst.cseip) - -#define Push_16 CPU_Push16 -#define Push_32 CPU_Push32 -#define Pop_16 CPU_Pop16 -#define Pop_32 CPU_Pop32 - diff --git a/src/cpu/core_full/op.h b/src/cpu/core_full/op.h deleted file mode 100644 index 9226252..0000000 --- a/src/cpu/core_full/op.h +++ /dev/null @@ -1,645 +0,0 @@ -/* Do the actual opcode */ -switch (inst.code.op) { - case t_ADDb: case t_ADDw: case t_ADDd: - lf_var1d=inst_op1_d; - lf_var2d=inst_op2_d; - inst_op1_d=lf_resd=lf_var1d + lf_var2d; - lflags.type=inst.code.op; - break; - case t_CMPb: case t_CMPw: case t_CMPd: - case t_SUBb: case t_SUBw: case t_SUBd: - lf_var1d=inst_op1_d; - lf_var2d=inst_op2_d; - inst_op1_d=lf_resd=lf_var1d - lf_var2d; - lflags.type=inst.code.op; - break; - case t_ORb: case t_ORw: case t_ORd: - lf_var1d=inst_op1_d; - lf_var2d=inst_op2_d; - inst_op1_d=lf_resd=lf_var1d | lf_var2d; - lflags.type=inst.code.op; - break; - case t_XORb: case t_XORw: case t_XORd: - lf_var1d=inst_op1_d; - lf_var2d=inst_op2_d; - inst_op1_d=lf_resd=lf_var1d ^ lf_var2d; - lflags.type=inst.code.op; - break; - case t_TESTb: case t_TESTw: case t_TESTd: - case t_ANDb: case t_ANDw: case t_ANDd: - lf_var1d=inst_op1_d; - lf_var2d=inst_op2_d; - inst_op1_d=lf_resd=lf_var1d & lf_var2d; - lflags.type=inst.code.op; - break; - case t_ADCb: case t_ADCw: case t_ADCd: - lflags.oldcf=(get_CF()!=0); - lf_var1d=inst_op1_d; - lf_var2d=inst_op2_d; - inst_op1_d=lf_resd=lf_var1d + lf_var2d + lflags.oldcf; - lflags.type=inst.code.op; - break; - case t_SBBb: case t_SBBw: case t_SBBd: - lflags.oldcf=(get_CF()!=0); - lf_var1d=inst_op1_d; - lf_var2d=inst_op2_d; - inst_op1_d=lf_resd=lf_var1d - lf_var2d - lflags.oldcf; - lflags.type=inst.code.op; - break; - case t_INCb: case t_INCw: case t_INCd: - LoadCF; - lf_var1d=inst_op1_d; - inst_op1_d=lf_resd=inst_op1_d+1; - lflags.type=inst.code.op; - break; - case t_DECb: case t_DECw: case t_DECd: - LoadCF; - lf_var1d=inst_op1_d; - inst_op1_d=lf_resd=inst_op1_d-1; - lflags.type=inst.code.op; - break; -/* Using the instructions.h defines */ - case t_ROLb: - ROLB(inst_op1_b,inst_op2_b,LoadD,SaveD); - break; - case t_ROLw: - ROLW(inst_op1_w,inst_op2_b,LoadD,SaveD); - break; - case t_ROLd: - ROLD(inst_op1_d,inst_op2_b,LoadD,SaveD); - break; - - case t_RORb: - RORB(inst_op1_b,inst_op2_b,LoadD,SaveD); - break; - case t_RORw: - RORW(inst_op1_w,inst_op2_b,LoadD,SaveD); - break; - case t_RORd: - RORD(inst_op1_d,inst_op2_b,LoadD,SaveD); - break; - - case t_RCLb: - RCLB(inst_op1_b,inst_op2_b,LoadD,SaveD); - break; - case t_RCLw: - RCLW(inst_op1_w,inst_op2_b,LoadD,SaveD); - break; - case t_RCLd: - RCLD(inst_op1_d,inst_op2_b,LoadD,SaveD); - break; - - case t_RCRb: - RCRB(inst_op1_b,inst_op2_b,LoadD,SaveD); - break; - case t_RCRw: - RCRW(inst_op1_w,inst_op2_b,LoadD,SaveD); - break; - case t_RCRd: - RCRD(inst_op1_d,inst_op2_b,LoadD,SaveD); - break; - - case t_SHLb: - SHLB(inst_op1_b,inst_op2_b,LoadD,SaveD); - break; - case t_SHLw: - SHLW(inst_op1_w,inst_op2_b,LoadD,SaveD); - break; - case t_SHLd: - SHLD(inst_op1_d,inst_op2_b,LoadD,SaveD); - break; - - case t_SHRb: - SHRB(inst_op1_b,inst_op2_b,LoadD,SaveD); - break; - case t_SHRw: - SHRW(inst_op1_w,inst_op2_b,LoadD,SaveD); - break; - case t_SHRd: - SHRD(inst_op1_d,inst_op2_b,LoadD,SaveD); - break; - - case t_SARb: - SARB(inst_op1_b,inst_op2_b,LoadD,SaveD); - break; - case t_SARw: - SARW(inst_op1_w,inst_op2_b,LoadD,SaveD); - break; - case t_SARd: - SARD(inst_op1_d,inst_op2_b,LoadD,SaveD); - break; - - case O_DSHLw: - { - DSHLW(inst_op1_w,inst_op2_w,inst_imm_b,LoadD,SaveD); - break; - } - case O_DSHRw: - { - DSHRW(inst_op1_w,inst_op2_w,inst_imm_b,LoadD,SaveD); - break; - } - case O_DSHLd: - { - DSHLD(inst_op1_d,inst_op2_d,inst_imm_b,LoadD,SaveD); - break; - } - case O_DSHRd: - { - DSHRD(inst_op1_d,inst_op2_d,inst_imm_b,LoadD,SaveD); - break; - } - - case t_NEGb: - lf_var1b=inst_op1_b; - inst_op1_b=lf_resb=0-inst_op1_b; - lflags.type=t_NEGb; - break; - case t_NEGw: - lf_var1w=inst_op1_w; - inst_op1_w=lf_resw=0-inst_op1_w; - lflags.type=t_NEGw; - break; - case t_NEGd: - lf_var1d=inst_op1_d; - inst_op1_d=lf_resd=0-inst_op1_d; - lflags.type=t_NEGd; - break; - - case O_NOT: - inst_op1_d=~inst_op1_d; - break; - - /* Special instructions */ - case O_IMULRw: - DIMULW(inst_op1_ws,inst_op1_ws,inst_op2_ws,LoadD,SaveD); - break; - case O_IMULRd: - DIMULD(inst_op1_ds,inst_op1_ds,inst_op2_ds,LoadD,SaveD); - break; - case O_MULb: - MULB(inst_op1_b,LoadD,0); - goto nextopcode; - case O_MULw: - MULW(inst_op1_w,LoadD,0); - goto nextopcode; - case O_MULd: - MULD(inst_op1_d,LoadD,0); - goto nextopcode; - case O_IMULb: - IMULB(inst_op1_b,LoadD,0); - goto nextopcode; - case O_IMULw: - IMULW(inst_op1_w,LoadD,0); - goto nextopcode; - case O_IMULd: - IMULD(inst_op1_d,LoadD,0); - goto nextopcode; - case O_DIVb: - DIVB(inst_op1_b,LoadD,0); - goto nextopcode; - case O_DIVw: - DIVW(inst_op1_w,LoadD,0); - goto nextopcode; - case O_DIVd: - DIVD(inst_op1_d,LoadD,0); - goto nextopcode; - case O_IDIVb: - IDIVB(inst_op1_b,LoadD,0); - goto nextopcode; - case O_IDIVw: - IDIVW(inst_op1_w,LoadD,0); - goto nextopcode; - case O_IDIVd: - IDIVD(inst_op1_d,LoadD,0); - goto nextopcode; - case O_AAM: - AAM(inst_op1_b); - goto nextopcode; - case O_AAD: - AAD(inst_op1_b); - goto nextopcode; - - case O_C_O: inst.cond=TFLG_O; break; - case O_C_NO: inst.cond=TFLG_NO; break; - case O_C_B: inst.cond=TFLG_B; break; - case O_C_NB: inst.cond=TFLG_NB; break; - case O_C_Z: inst.cond=TFLG_Z; break; - case O_C_NZ: inst.cond=TFLG_NZ; break; - case O_C_BE: inst.cond=TFLG_BE; break; - case O_C_NBE: inst.cond=TFLG_NBE; break; - case O_C_S: inst.cond=TFLG_S; break; - case O_C_NS: inst.cond=TFLG_NS; break; - case O_C_P: inst.cond=TFLG_P; break; - case O_C_NP: inst.cond=TFLG_NP; break; - case O_C_L: inst.cond=TFLG_L; break; - case O_C_NL: inst.cond=TFLG_NL; break; - case O_C_LE: inst.cond=TFLG_LE; break; - case O_C_NLE: inst.cond=TFLG_NLE; break; - - case O_ALOP: - reg_al=LoadMb(inst.rm_eaa); - goto nextopcode; - case O_AXOP: - reg_ax=LoadMw(inst.rm_eaa); - goto nextopcode; - case O_EAXOP: - reg_eax=LoadMd(inst.rm_eaa); - goto nextopcode; - case O_OPAL: - SaveMb(inst.rm_eaa,reg_al); - goto nextopcode; - case O_OPAX: - SaveMw(inst.rm_eaa,reg_ax); - goto nextopcode; - case O_OPEAX: - SaveMd(inst.rm_eaa,reg_eax); - goto nextopcode; - case O_SEGDS: - inst.code.extra=ds; - break; - case O_SEGES: - inst.code.extra=es; - break; - case O_SEGFS: - inst.code.extra=fs; - break; - case O_SEGGS: - inst.code.extra=gs; - break; - case O_SEGSS: - inst.code.extra=ss; - break; - - case O_LOOP: - if (inst.prefix & PREFIX_ADDR) { - if (--reg_ecx) break; - } else { - if (--reg_cx) break; - } - goto nextopcode; - case O_LOOPZ: - if (inst.prefix & PREFIX_ADDR) { - if (--reg_ecx && get_ZF()) break; - } else { - if (--reg_cx && get_ZF()) break; - } - goto nextopcode; - case O_LOOPNZ: - if (inst.prefix & PREFIX_ADDR) { - if (--reg_ecx && !get_ZF()) break; - } else { - if (--reg_cx && !get_ZF()) break; - } - goto nextopcode; - case O_JCXZ: - if (inst.prefix & PREFIX_ADDR) { - if (reg_ecx) goto nextopcode; - } else { - if (reg_cx) goto nextopcode; - } - break; - case O_XCHG_AX: - { - Bit16u temp=reg_ax; - reg_ax=inst_op1_w; - inst_op1_w=temp; - break; - } - case O_XCHG_EAX: - { - Bit32u temp=reg_eax; - reg_eax=inst_op1_d; - inst_op1_d=temp; - break; - } - case O_CALLNw: - SaveIP(); - Push_16(reg_ip); - break; - case O_CALLNd: - SaveIP(); - Push_32(reg_eip); - break; - case O_CALLFw: - FillFlags(); - CPU_CALL(false,inst_op2_d,inst_op1_d,GetIP()); - continue; - case O_CALLFd: - FillFlags(); - CPU_CALL(true,inst_op2_d,inst_op1_d,GetIP()); - continue; - case O_JMPFw: - FillFlags(); - CPU_JMP(false,inst_op2_d,inst_op1_d,GetIP()); - continue; - case O_JMPFd: - FillFlags(); - CPU_JMP(true,inst_op2_d,inst_op1_d,GetIP()); - continue; - case O_INT: -#if C_DEBUG - FillFlags(); - if (((inst.entry & 0xFF)==0xcc) && DEBUG_Breakpoint()) - return debugCallback; - else if (DEBUG_IntBreakpoint(inst_op1_b)) - return debugCallback; -#endif - CPU_SW_Interrupt(inst_op1_b,GetIP()); - continue; - case O_INb: - if (CPU_IO_Exception(inst_op1_d,1)) RunException(); - reg_al=IO_ReadB(inst_op1_d); - goto nextopcode; - case O_INw: - if (CPU_IO_Exception(inst_op1_d,2)) RunException(); - reg_ax=IO_ReadW(inst_op1_d); - goto nextopcode; - case O_INd: - if (CPU_IO_Exception(inst_op1_d,4)) RunException(); - reg_eax=IO_ReadD(inst_op1_d); - goto nextopcode; - case O_OUTb: - if (CPU_IO_Exception(inst_op1_d,1)) RunException(); - IO_WriteB(inst_op1_d,reg_al); - goto nextopcode; - case O_OUTw: - if (CPU_IO_Exception(inst_op1_d,2)) RunException(); - IO_WriteW(inst_op1_d,reg_ax); - goto nextopcode; - case O_OUTd: - if (CPU_IO_Exception(inst_op1_d,4)) RunException(); - IO_WriteD(inst_op1_d,reg_eax); - goto nextopcode; - case O_CBACK: - FillFlags();SaveIP(); - return inst_op1_d; - case O_GRP6w: - case O_GRP6d: - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; - switch (inst.rm_index) { - case 0x00: /* SLDT */ - inst_op1_d=(Bit32u)CPU_SLDT(); - break; - case 0x01: /* STR */ - inst_op1_d=(Bit32u)CPU_STR(); - break; - case 0x02: /* LLDT */ - if (cpu.cpl) EXCEPTION(EXCEPTION_GP); - if (CPU_LLDT(inst_op1_d)) RunException(); - goto nextopcode; /* Else value will saved */ - case 0x03: /* LTR */ - if (cpu.cpl) EXCEPTION(EXCEPTION_GP); - if (CPU_LTR(inst_op1_d)) RunException(); - goto nextopcode; /* Else value will saved */ - case 0x04: /* VERR */ - CPU_VERR(inst_op1_d); - goto nextopcode; /* Else value will saved */ - case 0x05: /* VERW */ - CPU_VERW(inst_op1_d); - goto nextopcode; /* Else value will saved */ - default: - LOG(LOG_CPU,LOG_ERROR)("Group 6 Illegal subfunction %X",inst.rm_index); - goto illegalopcode; - } - break; - case O_GRP7w: - case O_GRP7d: - switch (inst.rm_index) { - case 0: /* SGDT */ - SaveMw(inst.rm_eaa,CPU_SGDT_limit()); - SaveMd(inst.rm_eaa+2,CPU_SGDT_base()); - goto nextopcode; - case 1: /* SIDT */ - SaveMw(inst.rm_eaa,CPU_SIDT_limit()); - SaveMd(inst.rm_eaa+2,CPU_SIDT_base()); - goto nextopcode; - case 2: /* LGDT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - CPU_LGDT(LoadMw(inst.rm_eaa),LoadMd(inst.rm_eaa+2)&((inst.code.op == O_GRP7w) ? 0xFFFFFF : 0xFFFFFFFF)); - goto nextopcode; - case 3: /* LIDT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - CPU_LIDT(LoadMw(inst.rm_eaa),LoadMd(inst.rm_eaa+2)&((inst.code.op == O_GRP7w) ? 0xFFFFFF : 0xFFFFFFFF)); - goto nextopcode; - case 4: /* SMSW */ - inst_op1_d=CPU_SMSW(); - break; - case 6: /* LMSW */ - FillFlags(); - if (CPU_LMSW(inst_op1_w)) RunException(); - goto nextopcode; - case 7: /* INVLPG */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - FillFlags(); - PAGING_ClearTLB(); - goto nextopcode; - default: - LOG(LOG_CPU,LOG_ERROR)("Group 7 Illegal subfunction %X",inst.rm_index); - goto illegalopcode; - } - break; - case O_M_CRx_Rd: - if (CPU_WRITE_CRX(inst.rm_index,inst_op1_d)) RunException(); - break; - case O_M_Rd_CRx: - if (CPU_READ_CRX(inst.rm_index,inst_op1_d)) RunException(); - break; - case O_M_DRx_Rd: - if (CPU_WRITE_DRX(inst.rm_index,inst_op1_d)) RunException(); - break; - case O_M_Rd_DRx: - if (CPU_READ_DRX(inst.rm_index,inst_op1_d)) RunException(); - break; - case O_M_TRx_Rd: - if (CPU_WRITE_TRX(inst.rm_index,inst_op1_d)) RunException(); - break; - case O_M_Rd_TRx: - if (CPU_READ_TRX(inst.rm_index,inst_op1_d)) RunException(); - break; - case O_LAR: - { - Bitu ar=inst_op2_d; - CPU_LAR(inst_op1_w,ar); - inst_op1_d=(Bit32u)ar; - } - break; - case O_LSL: - { - Bitu limit=inst_op2_d; - CPU_LSL(inst_op1_w,limit); - inst_op1_d=(Bit32u)limit; - } - break; - case O_ARPL: - { - Bitu new_sel=inst_op1_d; - CPU_ARPL(new_sel,inst_op2_d); - inst_op1_d=(Bit32u)new_sel; - } - break; - case O_BSFw: - { - FillFlags(); - if (!inst_op1_w) { - SETFLAGBIT(ZF,true); - goto nextopcode; - } else { - Bitu count=0; - while (1) { - if (inst_op1_w & 0x1) break; - count++;inst_op1_w>>=1; - } - inst_op1_d=count; - SETFLAGBIT(ZF,false); - } - } - break; - case O_BSFd: - { - FillFlags(); - if (!inst_op1_d) { - SETFLAGBIT(ZF,true); - goto nextopcode; - } else { - Bitu count=0; - while (1) { - if (inst_op1_d & 0x1) break; - count++;inst_op1_d>>=1; - } - inst_op1_d=count; - SETFLAGBIT(ZF,false); - } - } - break; - case O_BSRw: - { - FillFlags(); - if (!inst_op1_w) { - SETFLAGBIT(ZF,true); - goto nextopcode; - } else { - Bitu count=15; - while (1) { - if (inst_op1_w & 0x8000) break; - count--;inst_op1_w<<=1; - } - inst_op1_d=count; - SETFLAGBIT(ZF,false); - } - } - break; - case O_BSRd: - { - FillFlags(); - if (!inst_op1_d) { - SETFLAGBIT(ZF,true); - goto nextopcode; - } else { - Bitu count=31; - while (1) { - if (inst_op1_d & 0x80000000) break; - count--;inst_op1_d<<=1; - } - inst_op1_d=count; - SETFLAGBIT(ZF,false); - } - } - break; - case O_BTw: - FillFlags(); - SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 15)))); - break; - case O_BTSw: - FillFlags(); - SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 15)))); - inst_op1_d|=(1 << (inst_op2_d & 15)); - break; - case O_BTCw: - FillFlags(); - SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 15)))); - inst_op1_d^=(1 << (inst_op2_d & 15)); - break; - case O_BTRw: - FillFlags(); - SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 15)))); - inst_op1_d&=~(1 << (inst_op2_d & 15)); - break; - case O_BTd: - FillFlags(); - SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 31)))); - break; - case O_BTSd: - FillFlags(); - SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 31)))); - inst_op1_d|=(1 << (inst_op2_d & 31)); - break; - case O_BTCd: - FillFlags(); - SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 31)))); - inst_op1_d^=(1 << (inst_op2_d & 31)); - break; - case O_BTRd: - FillFlags(); - SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 31)))); - inst_op1_d&=~(1 << (inst_op2_d & 31)); - break; - case O_BSWAP: - if (CPU_ArchitectureType=0xc0) << 3) | inst.code.save) { - case 0x00: FPU_ESC0_EA(inst.rm,inst.rm_eaa);break; - case 0x01: FPU_ESC1_EA(inst.rm,inst.rm_eaa);break; - case 0x02: FPU_ESC2_EA(inst.rm,inst.rm_eaa);break; - case 0x03: FPU_ESC3_EA(inst.rm,inst.rm_eaa);break; - case 0x04: FPU_ESC4_EA(inst.rm,inst.rm_eaa);break; - case 0x05: FPU_ESC5_EA(inst.rm,inst.rm_eaa);break; - case 0x06: FPU_ESC6_EA(inst.rm,inst.rm_eaa);break; - case 0x07: FPU_ESC7_EA(inst.rm,inst.rm_eaa);break; - - case 0x08: FPU_ESC0_Normal(inst.rm);break; - case 0x09: FPU_ESC1_Normal(inst.rm);break; - case 0x0a: FPU_ESC2_Normal(inst.rm);break; - case 0x0b: FPU_ESC3_Normal(inst.rm);break; - case 0x0c: FPU_ESC4_Normal(inst.rm);break; - case 0x0d: FPU_ESC5_Normal(inst.rm);break; - case 0x0e: FPU_ESC6_Normal(inst.rm);break; - case 0x0f: FPU_ESC7_Normal(inst.rm);break; - } - goto nextopcode; -#else - LOG(LOG_CPU,LOG_ERROR)("Unhandled FPU ESCAPE %d",inst.code.save); - goto nextopcode; -#endif - case O_BOUNDw: - { - Bit16s bound_min, bound_max; - bound_min=LoadMw(inst.rm_eaa); - bound_max=LoadMw(inst.rm_eaa+2); - if ( (((Bit16s)inst_op1_w) < bound_min) || (((Bit16s)inst_op1_w) > bound_max) ) { - EXCEPTION(5); - } - } - break; - case 0: - break; - default: - LOG(LOG_CPU,LOG_ERROR)("OP:Unhandled code %d entry %X",inst.code.op,inst.entry); - -} diff --git a/src/cpu/core_full/optable.h b/src/cpu/core_full/optable.h deleted file mode 100644 index fa594fc..0000000 --- a/src/cpu/core_full/optable.h +++ /dev/null @@ -1,814 +0,0 @@ -/* Big ass opcode table normal,double, 66 normal, 66 double */ -static OpCode OpCodeTable[1024]={ -/* 0x00 - 0x07 */ -{L_MODRM ,t_ADDb ,S_Eb ,M_EbGb },{L_MODRM ,t_ADDw ,S_Ew ,M_EwGw }, -{L_MODRM ,t_ADDb ,S_Gb ,M_GbEb },{L_MODRM ,t_ADDw ,S_Gw ,M_GwEw }, -{L_REGbIb ,t_ADDb ,S_REGb ,REGI_AL },{L_REGwIw ,t_ADDw ,S_REGw ,REGI_AX }, -{L_SEG ,0 ,S_PUSHw,es },{D_POPSEGw,0 ,0 ,es }, -/* 0x08 - 0x0f */ -{L_MODRM ,t_ORb ,S_Eb ,M_EbGb },{L_MODRM ,t_ORw ,S_Ew ,M_EwGw }, -{L_MODRM ,t_ORb ,S_Gb ,M_GbEb },{L_MODRM ,t_ORw ,S_Gw ,M_GwEw }, -{L_REGbIb ,t_ORb ,S_REGb ,REGI_AL },{L_REGwIw ,t_ORw ,S_REGw ,REGI_AX }, -{L_SEG ,0 ,S_PUSHw,cs },{L_DOUBLE ,0 ,0 ,0 }, - -/* 0x10 - 0x17 */ -{L_MODRM ,t_ADCb ,S_Eb ,M_EbGb },{L_MODRM ,t_ADCw ,S_Ew ,M_EwGw }, -{L_MODRM ,t_ADCb ,S_Gb ,M_GbEb },{L_MODRM ,t_ADCw ,S_Gw ,M_GwEw }, -{L_REGbIb ,t_ADCb ,S_REGb ,REGI_AL },{L_REGwIw ,t_ADCw ,S_REGw ,REGI_AX }, -{L_SEG ,0 ,S_PUSHw,ss },{D_POPSEGw,0 ,0 ,ss }, -/* 0x18 - 0x1f */ -{L_MODRM ,t_SBBb ,S_Eb ,M_EbGb },{L_MODRM ,t_SBBw ,S_Ew ,M_EwGw }, -{L_MODRM ,t_SBBb ,S_Gb ,M_GbEb },{L_MODRM ,t_SBBw ,S_Gw ,M_GwEw }, -{L_REGbIb ,t_SBBb ,S_REGb ,REGI_AL },{L_REGwIw ,t_SBBw ,S_REGw ,REGI_AX }, -{L_SEG ,0 ,S_PUSHw,ds },{D_POPSEGw,0 ,0 ,ds }, - -/* 0x20 - 0x27 */ -{L_MODRM ,t_ANDb ,S_Eb ,M_EbGb },{L_MODRM ,t_ANDw ,S_Ew ,M_EwGw }, -{L_MODRM ,t_ANDb ,S_Gb ,M_GbEb },{L_MODRM ,t_ANDw ,S_Gw ,M_GwEw }, -{L_REGbIb ,t_ANDb ,S_REGb ,REGI_AL },{L_REGwIw ,t_ANDw ,S_REGw ,REGI_AX }, -{L_PRESEG ,0 ,0 ,es },{D_DAA ,0 ,0 ,0 }, -/* 0x28 - 0x2f */ -{L_MODRM ,t_SUBb ,S_Eb ,M_EbGb },{L_MODRM ,t_SUBw ,S_Ew ,M_EwGw }, -{L_MODRM ,t_SUBb ,S_Gb ,M_GbEb },{L_MODRM ,t_SUBw ,S_Gw ,M_GwEw }, -{L_REGbIb ,t_SUBb ,S_REGb ,REGI_AL },{L_REGwIw ,t_SUBw ,S_REGw ,REGI_AX }, -{L_PRESEG ,0 ,0 ,cs },{D_DAS ,0 ,0 ,0 }, - -/* 0x30 - 0x37 */ -{L_MODRM ,t_XORb ,S_Eb ,M_EbGb },{L_MODRM ,t_XORw ,S_Ew ,M_EwGw }, -{L_MODRM ,t_XORb ,S_Gb ,M_GbEb },{L_MODRM ,t_XORw ,S_Gw ,M_GwEw }, -{L_REGbIb ,t_XORb ,S_REGb ,REGI_AL },{L_REGwIw ,t_XORw ,S_REGw ,REGI_AX }, -{L_PRESEG ,0 ,0 ,ss },{D_AAA ,0 ,0 ,0 }, -/* 0x38 - 0x3f */ -{L_MODRM ,t_CMPb ,0 ,M_EbGb },{L_MODRM ,t_CMPw ,0 ,M_EwGw }, -{L_MODRM ,t_CMPb ,0 ,M_GbEb },{L_MODRM ,t_CMPw ,0 ,M_GwEw }, -{L_REGbIb ,t_CMPb ,0 ,REGI_AL },{L_REGwIw ,t_CMPw ,0 ,REGI_AX }, -{L_PRESEG ,0 ,0 ,ds },{D_AAS ,0 ,0 ,0 }, - -/* 0x40 - 0x47 */ -{L_REGw ,t_INCw ,S_REGw ,REGI_AX},{L_REGw ,t_INCw ,S_REGw ,REGI_CX}, -{L_REGw ,t_INCw ,S_REGw ,REGI_DX},{L_REGw ,t_INCw ,S_REGw ,REGI_BX}, -{L_REGw ,t_INCw ,S_REGw ,REGI_SP},{L_REGw ,t_INCw ,S_REGw ,REGI_BP}, -{L_REGw ,t_INCw ,S_REGw ,REGI_SI},{L_REGw ,t_INCw ,S_REGw ,REGI_DI}, -/* 0x48 - 0x4f */ -{L_REGw ,t_DECw ,S_REGw ,REGI_AX},{L_REGw ,t_DECw ,S_REGw ,REGI_CX}, -{L_REGw ,t_DECw ,S_REGw ,REGI_DX},{L_REGw ,t_DECw ,S_REGw ,REGI_BX}, -{L_REGw ,t_DECw ,S_REGw ,REGI_SP},{L_REGw ,t_DECw ,S_REGw ,REGI_BP}, -{L_REGw ,t_DECw ,S_REGw ,REGI_SI},{L_REGw ,t_DECw ,S_REGw ,REGI_DI}, - -/* 0x50 - 0x57 */ -{L_REGw ,0 ,S_PUSHw,REGI_AX},{L_REGw ,0 ,S_PUSHw,REGI_CX}, -{L_REGw ,0 ,S_PUSHw,REGI_DX},{L_REGw ,0 ,S_PUSHw,REGI_BX}, -{L_REGw ,0 ,S_PUSHw,REGI_SP},{L_REGw ,0 ,S_PUSHw,REGI_BP}, -{L_REGw ,0 ,S_PUSHw,REGI_SI},{L_REGw ,0 ,S_PUSHw,REGI_DI}, -/* 0x58 - 0x5f */ -{L_POPw ,0 ,S_REGw ,REGI_AX},{L_POPw ,0 ,S_REGw ,REGI_CX}, -{L_POPw ,0 ,S_REGw ,REGI_DX},{L_POPw ,0 ,S_REGw ,REGI_BX}, -{L_POPw ,0 ,S_REGw ,REGI_SP},{L_POPw ,0 ,S_REGw ,REGI_BP}, -{L_POPw ,0 ,S_REGw ,REGI_SI},{L_POPw ,0 ,S_REGw ,REGI_DI}, - - -/* 0x60 - 0x67 */ -{D_PUSHAw ,0 ,0 ,0 },{D_POPAw ,0 ,0 ,0 }, -{L_MODRM ,O_BOUNDw ,0 ,M_Gw },{L_MODRM_NVM ,O_ARPL ,S_Ew ,M_EwGw }, -{L_PRESEG ,0 ,0 ,fs },{L_PRESEG ,0 ,0 ,gs }, -{L_PREOP ,0 ,0 ,0 },{L_PREADD ,0 ,0 ,0 }, -/* 0x68 - 0x6f */ -{L_Iw ,0 ,S_PUSHw,0 },{L_MODRM ,O_IMULRw ,S_Gw ,M_EwxIwx}, -{L_Ibx ,0 ,S_PUSHw,0 },{L_MODRM ,O_IMULRw ,S_Gw ,M_EwxIbx}, -{L_STRING ,R_INSB ,0 ,0 },{L_STRING ,R_INSW ,0 ,0 }, -{L_STRING ,R_OUTSB ,0 ,0 },{L_STRING ,R_OUTSW ,0 ,0 }, - - -/* 0x70 - 0x77 */ -{L_Ibx ,O_C_O ,S_C_AIPw,0 },{L_Ibx ,O_C_NO ,S_C_AIPw,0 }, -{L_Ibx ,O_C_B ,S_C_AIPw,0 },{L_Ibx ,O_C_NB ,S_C_AIPw,0 }, -{L_Ibx ,O_C_Z ,S_C_AIPw,0 },{L_Ibx ,O_C_NZ ,S_C_AIPw,0 }, -{L_Ibx ,O_C_BE ,S_C_AIPw,0 },{L_Ibx ,O_C_NBE ,S_C_AIPw,0 }, -/* 0x78 - 0x7f */ -{L_Ibx ,O_C_S ,S_C_AIPw,0 },{L_Ibx ,O_C_NS ,S_C_AIPw,0 }, -{L_Ibx ,O_C_P ,S_C_AIPw,0 },{L_Ibx ,O_C_NP ,S_C_AIPw,0 }, -{L_Ibx ,O_C_L ,S_C_AIPw,0 },{L_Ibx ,O_C_NL ,S_C_AIPw,0 }, -{L_Ibx ,O_C_LE ,S_C_AIPw,0 },{L_Ibx ,O_C_NLE ,S_C_AIPw,0 }, - - -/* 0x80 - 0x87 */ -{L_MODRM ,0 ,0 ,M_GRP },{L_MODRM ,1 ,0 ,M_GRP }, -{L_MODRM ,0 ,0 ,M_GRP },{L_MODRM ,3 ,0 ,M_GRP }, -{L_MODRM ,t_TESTb ,0 ,M_EbGb },{L_MODRM ,t_TESTw ,0 ,M_EwGw }, -{L_MODRM ,0 ,S_EbGb ,M_GbEb },{L_MODRM ,0 ,S_EwGw ,M_GwEw }, -/* 0x88 - 0x8f */ -{L_MODRM ,0 ,S_Eb ,M_Gb },{L_MODRM ,0 ,S_Ew ,M_Gw }, -{L_MODRM ,0 ,S_Gb ,M_Eb },{L_MODRM ,0 ,S_Gw ,M_Ew }, -{L_MODRM ,0 ,S_Ew ,M_SEG },{L_MODRM ,0 ,S_Gw ,M_EA }, -{L_MODRM ,0 ,S_SEGm ,M_Ew },{L_POPwRM ,0 ,S_Ew ,M_None }, - -/* 0x90 - 0x97 */ -{D_NOP ,0 ,0 ,0 },{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_CX}, -{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_DX},{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_BX}, -{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_SP},{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_BP}, -{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_SI},{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_DI}, -/* 0x98 - 0x9f */ -{D_CBW ,0 ,0 ,0 },{D_CWD ,0 ,0 ,0 }, -{L_Ifw ,O_CALLFw ,0 ,0 },{D_WAIT ,0 ,0 ,0 }, -{D_PUSHF ,0 ,0 ,0 },{D_POPF ,0 ,0 ,0 }, -{D_SAHF ,0 ,0 ,0 },{D_LAHF ,0 ,0 ,0 }, - - -/* 0xa0 - 0xa7 */ -{L_OP ,O_ALOP ,0 ,0 },{L_OP ,O_AXOP ,0 ,0 }, -{L_OP ,O_OPAL ,0 ,0 },{L_OP ,O_OPAX ,0 ,0 }, -{L_STRING ,R_MOVSB ,0 ,0 },{L_STRING ,R_MOVSW ,0 ,0 }, -{L_STRING ,R_CMPSB ,0 ,0 },{L_STRING ,R_CMPSW ,0 ,0 }, -/* 0xa8 - 0xaf */ -{L_REGbIb ,t_TESTb ,0 ,REGI_AL},{L_REGwIw ,t_TESTw ,0 ,REGI_AX}, -{L_STRING ,R_STOSB ,0 ,0 },{L_STRING ,R_STOSW ,0 ,0 }, -{L_STRING ,R_LODSB ,0 ,0 },{L_STRING ,R_LODSW ,0 ,0 }, -{L_STRING ,R_SCASB ,0 ,0 },{L_STRING ,R_SCASW ,0 ,0 }, - -/* 0xb0 - 0xb7 */ -{L_Ib ,0 ,S_REGb ,REGI_AL},{L_Ib ,0 ,S_REGb ,REGI_CL}, -{L_Ib ,0 ,S_REGb ,REGI_DL},{L_Ib ,0 ,S_REGb ,REGI_BL}, -{L_Ib ,0 ,S_REGb ,REGI_AH},{L_Ib ,0 ,S_REGb ,REGI_CH}, -{L_Ib ,0 ,S_REGb ,REGI_DH},{L_Ib ,0 ,S_REGb ,REGI_BH}, -/* 0xb8 - 0xbf */ -{L_Iw ,0 ,S_REGw ,REGI_AX},{L_Iw ,0 ,S_REGw ,REGI_CX}, -{L_Iw ,0 ,S_REGw ,REGI_DX},{L_Iw ,0 ,S_REGw ,REGI_BX}, -{L_Iw ,0 ,S_REGw ,REGI_SP},{L_Iw ,0 ,S_REGw ,REGI_BP}, -{L_Iw ,0 ,S_REGw ,REGI_SI},{L_Iw ,0 ,S_REGw ,REGI_DI}, - -/* 0xc0 - 0xc7 */ -{L_MODRM ,5 ,0 ,M_GRP_Ib },{L_MODRM ,6 ,0 ,M_GRP_Ib }, -{L_POPw ,0 ,S_IPIw ,0 },{L_POPw ,0 ,S_IP ,0 }, -{L_MODRM ,O_SEGES ,S_SEGGw,M_Efw },{L_MODRM ,O_SEGDS ,S_SEGGw,M_Efw }, -{L_MODRM ,0 ,S_Eb ,M_Ib },{L_MODRM ,0 ,S_Ew ,M_Iw }, -/* 0xc8 - 0xcf */ -{D_ENTERw ,0 ,0 ,0 },{D_LEAVEw ,0 ,0 ,0 }, -{D_RETFwIw ,0 ,0 ,0 },{D_RETFw ,0 ,0 ,0 }, -{L_VAL ,O_INT ,0 ,3 },{L_Ib ,O_INT ,0 ,0 }, -{L_INTO ,O_INT ,0 ,0 },{D_IRETw ,0 ,0 ,0 }, - -/* 0xd0 - 0xd7 */ -{L_MODRM ,5 ,0 ,M_GRP_1 },{L_MODRM ,6 ,0 ,M_GRP_1 }, -{L_MODRM ,5 ,0 ,M_GRP_CL },{L_MODRM ,6 ,0 ,M_GRP_CL }, -{L_Ib ,O_AAM ,0 ,0 },{L_Ib ,O_AAD ,0 ,0 }, -{D_SETALC ,0 ,0 ,0 },{D_XLAT ,0 ,0 ,0 }, -//TODO FPU -/* 0xd8 - 0xdf */ -{L_MODRM ,O_FPU ,0 ,0 },{L_MODRM ,O_FPU ,1 ,0 }, -{L_MODRM ,O_FPU ,2 ,0 },{L_MODRM ,O_FPU ,3 ,0 }, -{L_MODRM ,O_FPU ,4 ,0 },{L_MODRM ,O_FPU ,5 ,0 }, -{L_MODRM ,O_FPU ,6 ,0 },{L_MODRM ,O_FPU ,7 ,0 }, - -/* 0xe0 - 0xe7 */ -{L_Ibx ,O_LOOPNZ ,S_AIPw ,0 },{L_Ibx ,O_LOOPZ ,S_AIPw ,0 }, -{L_Ibx ,O_LOOP ,S_AIPw ,0 },{L_Ibx ,O_JCXZ ,S_AIPw ,0 }, -{L_Ib ,O_INb ,0 ,0 },{L_Ib ,O_INw ,0 ,0 }, -{L_Ib ,O_OUTb ,0 ,0 },{L_Ib ,O_OUTw ,0 ,0 }, -/* 0xe8 - 0xef */ -{L_Iw ,O_CALLNw ,S_AIPw ,0 },{L_Iwx ,0 ,S_AIPw ,0 }, -{L_Ifw ,O_JMPFw ,0 ,0 },{L_Ibx ,0 ,S_AIPw ,0 }, -{L_REGw ,O_INb ,0 ,REGI_DX},{L_REGw ,O_INw ,0 ,REGI_DX}, -{L_REGw ,O_OUTb ,0 ,REGI_DX},{L_REGw ,O_OUTw ,0 ,REGI_DX}, - -/* 0xf0 - 0xf7 */ -{D_LOCK ,0 ,0 ,0 },{D_ICEBP ,0 ,0 ,0 }, -{L_PREREPNE ,0 ,0 ,0 },{L_PREREP ,0 ,0 ,0 }, -{D_HLT ,0 ,0 ,0 },{D_CMC ,0 ,0 ,0 }, -{L_MODRM ,8 ,0 ,M_GRP },{L_MODRM ,9 ,0 ,M_GRP }, -/* 0xf8 - 0xff */ -{D_CLC ,0 ,0 ,0 },{D_STC ,0 ,0 ,0 }, -{D_CLI ,0 ,0 ,0 },{D_STI ,0 ,0 ,0 }, -{D_CLD ,0 ,0 ,0 },{D_STD ,0 ,0 ,0 }, -{L_MODRM ,0xb ,0 ,M_GRP },{L_MODRM ,0xc ,0 ,M_GRP }, - -/* 0x100 - 0x107 */ -{L_MODRM ,O_GRP6w ,S_Ew ,M_Ew },{L_MODRM ,O_GRP7w ,S_Ew ,M_Ew }, -{L_MODRM_NVM ,O_LAR ,S_Gw ,M_EwGw },{L_MODRM_NVM ,O_LSL ,S_Gw ,M_EwGw }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{D_CLTS ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x108 - 0x10f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x110 - 0x117 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x118 - 0x11f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x120 - 0x127 */ -{L_MODRM ,O_M_Rd_CRx ,S_Ed ,0 },{L_MODRM ,O_M_Rd_DRx ,S_Ed ,0 }, -{L_MODRM ,O_M_CRx_Rd ,0 ,M_Ed },{L_MODRM ,O_M_DRx_Rd ,0 ,M_Ed }, -{L_MODRM ,O_M_Rd_TRx ,S_Ed ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,O_M_TRx_Rd ,0 ,M_Ed },{0 ,0 ,0 ,0 }, - -/* 0x128 - 0x12f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x130 - 0x137 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x138 - 0x13f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x140 - 0x147 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x148 - 0x14f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x150 - 0x157 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x158 - 0x15f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x160 - 0x167 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x168 - 0x16f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - - -/* 0x170 - 0x177 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x178 - 0x17f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x180 - 0x187 */ -{L_Iwx ,O_C_O ,S_C_AIPw,0 },{L_Iwx ,O_C_NO ,S_C_AIPw,0 }, -{L_Iwx ,O_C_B ,S_C_AIPw,0 },{L_Iwx ,O_C_NB ,S_C_AIPw,0 }, -{L_Iwx ,O_C_Z ,S_C_AIPw,0 },{L_Iwx ,O_C_NZ ,S_C_AIPw,0 }, -{L_Iwx ,O_C_BE ,S_C_AIPw,0 },{L_Iwx ,O_C_NBE ,S_C_AIPw,0 }, -/* 0x188 - 0x18f */ -{L_Iwx ,O_C_S ,S_C_AIPw,0 },{L_Iwx ,O_C_NS ,S_C_AIPw,0 }, -{L_Iwx ,O_C_P ,S_C_AIPw,0 },{L_Iwx ,O_C_NP ,S_C_AIPw,0 }, -{L_Iwx ,O_C_L ,S_C_AIPw,0 },{L_Iwx ,O_C_NL ,S_C_AIPw,0 }, -{L_Iwx ,O_C_LE ,S_C_AIPw,0 },{L_Iwx ,O_C_NLE ,S_C_AIPw,0 }, - -/* 0x190 - 0x197 */ -{L_MODRM ,O_C_O ,S_C_Eb,0 },{L_MODRM ,O_C_NO ,S_C_Eb,0 }, -{L_MODRM ,O_C_B ,S_C_Eb,0 },{L_MODRM ,O_C_NB ,S_C_Eb,0 }, -{L_MODRM ,O_C_Z ,S_C_Eb,0 },{L_MODRM ,O_C_NZ ,S_C_Eb,0 }, -{L_MODRM ,O_C_BE ,S_C_Eb,0 },{L_MODRM ,O_C_NBE ,S_C_Eb,0 }, -/* 0x198 - 0x19f */ -{L_MODRM ,O_C_S ,S_C_Eb,0 },{L_MODRM ,O_C_NS ,S_C_Eb,0 }, -{L_MODRM ,O_C_P ,S_C_Eb,0 },{L_MODRM ,O_C_NP ,S_C_Eb,0 }, -{L_MODRM ,O_C_L ,S_C_Eb,0 },{L_MODRM ,O_C_NL ,S_C_Eb,0 }, -{L_MODRM ,O_C_LE ,S_C_Eb,0 },{L_MODRM ,O_C_NLE ,S_C_Eb,0 }, - -/* 0x1a0 - 0x1a7 */ -{L_SEG ,0 ,S_PUSHw ,fs },{D_POPSEGw,0 ,0 ,fs }, -{D_CPUID ,0 ,0 ,0 },{L_MODRM ,O_BTw ,S_Ew ,M_EwGwt }, -{L_MODRM ,O_DSHLw ,S_Ew,M_EwGwIb },{L_MODRM ,O_DSHLw ,S_Ew ,M_EwGwCL }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x1a8 - 0x1af */ -{L_SEG ,0 ,S_PUSHw ,gs },{D_POPSEGw,0 ,0 ,gs }, -{0 ,0 ,0 ,0 },{L_MODRM ,O_BTSw ,S_Ew ,M_EwGwt }, -{L_MODRM ,O_DSHRw ,S_Ew,M_EwGwIb },{L_MODRM ,O_DSHRw ,S_Ew ,M_EwGwCL }, -{0 ,0 ,0 ,0 },{L_MODRM ,O_IMULRw ,S_Gw ,M_EwxGwx }, - -/* 0x1b0 - 0x1b7 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,O_SEGSS ,S_SEGGw,M_Efw },{L_MODRM ,O_BTRw ,S_Ew ,M_EwGwt }, -{L_MODRM ,O_SEGFS ,S_SEGGw,M_Efw },{L_MODRM ,O_SEGGS ,S_SEGGw,M_Efw }, -{L_MODRM ,0 ,S_Gw ,M_Eb },{L_MODRM ,0 ,S_Gw ,M_Ew }, -/* 0x1b8 - 0x1bf */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,0xe ,0 ,M_GRP },{L_MODRM ,O_BTCw ,S_Ew ,M_EwGwt }, -{L_MODRM ,O_BSFw ,S_Gw ,M_Ew },{L_MODRM ,O_BSRw ,S_Gw ,M_Ew }, -{L_MODRM ,0 ,S_Gw ,M_Ebx },{L_MODRM ,0 ,S_Gw ,M_Ewx }, - -/* 0x1c0 - 0x1cc */ -{L_MODRM ,t_ADDb ,S_EbGb ,M_GbEb },{L_MODRM ,t_ADDw ,S_EwGw ,M_GwEw }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x1c8 - 0x1cf */ -{L_REGd ,O_BSWAP ,S_REGd ,REGI_AX},{L_REGd ,O_BSWAP ,S_REGd ,REGI_CX}, -{L_REGd ,O_BSWAP ,S_REGd ,REGI_DX},{L_REGd ,O_BSWAP ,S_REGd ,REGI_BX}, -{L_REGd ,O_BSWAP ,S_REGd ,REGI_SP},{L_REGd ,O_BSWAP ,S_REGd ,REGI_BP}, -{L_REGd ,O_BSWAP ,S_REGd ,REGI_SI},{L_REGd ,O_BSWAP ,S_REGd ,REGI_DI}, - -/* 0x1d0 - 0x1d7 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x1d8 - 0x1df */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x1e0 - 0x1ee */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x1e8 - 0x1ef */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x1f0 - 0x1fc */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x1f8 - 0x1ff */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - - -/* 0x200 - 0x207 */ -{L_MODRM ,t_ADDb ,S_Eb ,M_EbGb },{L_MODRM ,t_ADDd ,S_Ed ,M_EdGd }, -{L_MODRM ,t_ADDb ,S_Gb ,M_GbEb },{L_MODRM ,t_ADDd ,S_Gd ,M_GdEd }, -{L_REGbIb ,t_ADDb ,S_REGb ,REGI_AL },{L_REGdId ,t_ADDd ,S_REGd ,REGI_AX }, -{L_SEG ,0 ,S_PUSHd,es },{D_POPSEGd,0 ,0 ,es }, -/* 0x208 - 0x20f */ -{L_MODRM ,t_ORb ,S_Eb ,M_EbGb },{L_MODRM ,t_ORd ,S_Ed ,M_EdGd }, -{L_MODRM ,t_ORb ,S_Gb ,M_GbEb },{L_MODRM ,t_ORd ,S_Gd ,M_GdEd }, -{L_REGbIb ,t_ORb ,S_REGb ,REGI_AL },{L_REGdId ,t_ORd ,S_REGd ,REGI_AX }, -{L_SEG ,0 ,S_PUSHd,cs },{L_DOUBLE ,0 ,0 ,0 }, - -/* 0x210 - 0x217 */ -{L_MODRM ,t_ADCb ,S_Eb ,M_EbGb },{L_MODRM ,t_ADCd ,S_Ed ,M_EdGd }, -{L_MODRM ,t_ADCb ,S_Gb ,M_GbEb },{L_MODRM ,t_ADCd ,S_Gd ,M_GdEd }, -{L_REGbIb ,t_ADCb ,S_REGb ,REGI_AL },{L_REGdId ,t_ADCd ,S_REGd ,REGI_AX }, -{L_SEG ,0 ,S_PUSHd,ss },{D_POPSEGd,0 ,0 ,ss }, -/* 0x218 - 0x21f */ -{L_MODRM ,t_SBBb ,S_Eb ,M_EbGb },{L_MODRM ,t_SBBd ,S_Ed ,M_EdGd }, -{L_MODRM ,t_SBBb ,S_Gb ,M_GbEb },{L_MODRM ,t_SBBd ,S_Gd ,M_GdEd }, -{L_REGbIb ,t_SBBb ,S_REGb ,REGI_AL },{L_REGdId ,t_SBBd ,S_REGd ,REGI_AX }, -{L_SEG ,0 ,S_PUSHd,ds },{D_POPSEGd,0 ,0 ,ds }, - -/* 0x220 - 0x227 */ -{L_MODRM ,t_ANDb ,S_Eb ,M_EbGb },{L_MODRM ,t_ANDd ,S_Ed ,M_EdGd }, -{L_MODRM ,t_ANDb ,S_Gb ,M_GbEb },{L_MODRM ,t_ANDd ,S_Gd ,M_GdEd }, -{L_REGbIb ,t_ANDb ,S_REGb ,REGI_AL },{L_REGdId ,t_ANDd ,S_REGd ,REGI_AX }, -{L_PRESEG ,0 ,0 ,es },{D_DAA ,0 ,0 ,0 }, -/* 0x228 - 0x22f */ -{L_MODRM ,t_SUBb ,S_Eb ,M_EbGb },{L_MODRM ,t_SUBd ,S_Ed ,M_EdGd }, -{L_MODRM ,t_SUBb ,S_Gb ,M_GbEb },{L_MODRM ,t_SUBd ,S_Gd ,M_GdEd }, -{L_REGbIb ,t_SUBb ,S_REGb ,REGI_AL },{L_REGdId ,t_SUBd ,S_REGd ,REGI_AX }, -{L_PRESEG ,0 ,0 ,cs },{D_DAS ,0 ,0 ,0 }, - -/* 0x230 - 0x237 */ -{L_MODRM ,t_XORb ,S_Eb ,M_EbGb },{L_MODRM ,t_XORd ,S_Ed ,M_EdGd }, -{L_MODRM ,t_XORb ,S_Gb ,M_GbEb },{L_MODRM ,t_XORd ,S_Gd ,M_GdEd }, -{L_REGbIb ,t_XORb ,S_REGb ,REGI_AL },{L_REGdId ,t_XORd ,S_REGd ,REGI_AX }, -{L_PRESEG ,0 ,0 ,ss },{D_AAA ,0 ,0 ,0 }, -/* 0x238 - 0x23f */ -{L_MODRM ,t_CMPb ,0 ,M_EbGb },{L_MODRM ,t_CMPd ,0 ,M_EdGd }, -{L_MODRM ,t_CMPb ,0 ,M_GbEb },{L_MODRM ,t_CMPd ,0 ,M_GdEd }, -{L_REGbIb ,t_CMPb ,0 ,REGI_AL },{L_REGdId ,t_CMPd ,0 ,REGI_AX }, -{L_PRESEG ,0 ,0 ,ds },{D_AAS ,0 ,0 ,0 }, - -/* 0x240 - 0x247 */ -{L_REGd ,t_INCd ,S_REGd ,REGI_AX},{L_REGd ,t_INCd ,S_REGd ,REGI_CX}, -{L_REGd ,t_INCd ,S_REGd ,REGI_DX},{L_REGd ,t_INCd ,S_REGd ,REGI_BX}, -{L_REGd ,t_INCd ,S_REGd ,REGI_SP},{L_REGd ,t_INCd ,S_REGd ,REGI_BP}, -{L_REGd ,t_INCd ,S_REGd ,REGI_SI},{L_REGd ,t_INCd ,S_REGd ,REGI_DI}, -/* 0x248 - 0x24f */ -{L_REGd ,t_DECd ,S_REGd ,REGI_AX},{L_REGd ,t_DECd ,S_REGd ,REGI_CX}, -{L_REGd ,t_DECd ,S_REGd ,REGI_DX},{L_REGd ,t_DECd ,S_REGd ,REGI_BX}, -{L_REGd ,t_DECd ,S_REGd ,REGI_SP},{L_REGd ,t_DECd ,S_REGd ,REGI_BP}, -{L_REGd ,t_DECd ,S_REGd ,REGI_SI},{L_REGd ,t_DECd ,S_REGd ,REGI_DI}, - -/* 0x250 - 0x257 */ -{L_REGd ,0 ,S_PUSHd,REGI_AX},{L_REGd ,0 ,S_PUSHd,REGI_CX}, -{L_REGd ,0 ,S_PUSHd,REGI_DX},{L_REGd ,0 ,S_PUSHd,REGI_BX}, -{L_REGd ,0 ,S_PUSHd,REGI_SP},{L_REGd ,0 ,S_PUSHd,REGI_BP}, -{L_REGd ,0 ,S_PUSHd,REGI_SI},{L_REGd ,0 ,S_PUSHd,REGI_DI}, -/* 0x258 - 0x25f */ -{L_POPd ,0 ,S_REGd ,REGI_AX},{L_POPd ,0 ,S_REGd ,REGI_CX}, -{L_POPd ,0 ,S_REGd ,REGI_DX},{L_POPd ,0 ,S_REGd ,REGI_BX}, -{L_POPd ,0 ,S_REGd ,REGI_SP},{L_POPd ,0 ,S_REGd ,REGI_BP}, -{L_POPd ,0 ,S_REGd ,REGI_SI},{L_POPd ,0 ,S_REGd ,REGI_DI}, - -/* 0x260 - 0x267 */ -{D_PUSHAd ,0 ,0 ,0 },{D_POPAd ,0 ,0 ,0 }, -{L_MODRM ,O_BOUNDd ,0 ,0 },{0 ,0 ,0 ,0 }, -{L_PRESEG ,0 ,0 ,fs },{L_PRESEG ,0 ,0 ,gs }, -{L_PREOP ,0 ,0 ,0 },{L_PREADD ,0 ,0 ,0 }, -/* 0x268 - 0x26f */ -{L_Id ,0 ,S_PUSHd,0 },{L_MODRM ,O_IMULRd ,S_Gd ,M_EdId}, -{L_Ibx ,0 ,S_PUSHd,0 },{L_MODRM ,O_IMULRd ,S_Gd ,M_EdIbx}, -{L_STRING ,R_INSB ,0 ,0 },{L_STRING ,R_INSD ,0 ,0 }, -{L_STRING ,R_OUTSB ,0 ,0 },{L_STRING ,R_OUTSD ,0 ,0 }, - -/* 0x270 - 0x277 */ -{L_Ibx ,O_C_O ,S_C_AIPd,0 },{L_Ibx ,O_C_NO ,S_C_AIPd,0 }, -{L_Ibx ,O_C_B ,S_C_AIPd,0 },{L_Ibx ,O_C_NB ,S_C_AIPd,0 }, -{L_Ibx ,O_C_Z ,S_C_AIPd,0 },{L_Ibx ,O_C_NZ ,S_C_AIPd,0 }, -{L_Ibx ,O_C_BE ,S_C_AIPd,0 },{L_Ibx ,O_C_NBE ,S_C_AIPd,0 }, -/* 0x278 - 0x27f */ -{L_Ibx ,O_C_S ,S_C_AIPd,0 },{L_Ibx ,O_C_NS ,S_C_AIPd,0 }, -{L_Ibx ,O_C_P ,S_C_AIPd,0 },{L_Ibx ,O_C_NP ,S_C_AIPd,0 }, -{L_Ibx ,O_C_L ,S_C_AIPd,0 },{L_Ibx ,O_C_NL ,S_C_AIPd,0 }, -{L_Ibx ,O_C_LE ,S_C_AIPd,0 },{L_Ibx ,O_C_NLE ,S_C_AIPd,0 }, - -/* 0x280 - 0x287 */ -{L_MODRM ,0 ,0 ,M_GRP },{L_MODRM ,2 ,0 ,M_GRP }, -{L_MODRM ,0 ,0 ,M_GRP },{L_MODRM ,4 ,0 ,M_GRP }, -{L_MODRM ,t_TESTb ,0 ,M_EbGb },{L_MODRM ,t_TESTd ,0 ,M_EdGd }, -{L_MODRM ,0 ,S_EbGb ,M_GbEb },{L_MODRM ,0 ,S_EdGd ,M_GdEd }, -/* 0x288 - 0x28f */ -{L_MODRM ,0 ,S_Eb ,M_Gb },{L_MODRM ,0 ,S_Ed ,M_Gd }, -{L_MODRM ,0 ,S_Gb ,M_Eb },{L_MODRM ,0 ,S_Gd ,M_Ed }, -{L_MODRM ,0 ,S_EdMw ,M_SEG },{L_MODRM ,0 ,S_Gd ,M_EA }, -{L_MODRM ,0 ,S_SEGm ,M_Ew },{L_POPdRM ,0 ,S_Ed ,M_None }, - -/* 0x290 - 0x297 */ -{D_NOP ,0 ,0 ,0 },{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_CX}, -{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_DX},{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_BX}, -{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_SP},{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_BP}, -{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_SI},{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_DI}, -/* 0x298 - 0x29f */ -{D_CWDE ,0 ,0 ,0 },{D_CDQ ,0 ,0 ,0 }, -{L_Ifd ,O_CALLFd ,0 ,0 },{D_WAIT ,0 ,0 ,0 }, -{D_PUSHF ,0 ,0 ,true },{D_POPF ,0 ,0 ,true }, -{D_SAHF ,0 ,0 ,0 },{D_LAHF ,0 ,0 ,0 }, - -/* 0x2a0 - 0x2a7 */ -{L_OP ,O_ALOP ,0 ,0 },{L_OP ,O_EAXOP ,0 ,0 }, -{L_OP ,O_OPAL ,0 ,0 },{L_OP ,O_OPEAX ,0 ,0 }, -{L_STRING ,R_MOVSB ,0 ,0 },{L_STRING ,R_MOVSD ,0 ,0 }, -{L_STRING ,R_CMPSB ,0 ,0 },{L_STRING ,R_CMPSD ,0 ,0 }, -/* 0x2a8 - 0x2af */ -{L_REGbIb ,t_TESTb ,0 ,REGI_AL},{L_REGdId ,t_TESTd ,0 ,REGI_AX}, -{L_STRING ,R_STOSB ,0 ,0 },{L_STRING ,R_STOSD ,0 ,0 }, -{L_STRING ,R_LODSB ,0 ,0 },{L_STRING ,R_LODSD ,0 ,0 }, -{L_STRING ,R_SCASB ,0 ,0 },{L_STRING ,R_SCASD ,0 ,0 }, - -/* 0x2b0 - 0x2b7 */ -{L_Ib ,0 ,S_REGb ,REGI_AL},{L_Ib ,0 ,S_REGb ,REGI_CL}, -{L_Ib ,0 ,S_REGb ,REGI_DL},{L_Ib ,0 ,S_REGb ,REGI_BL}, -{L_Ib ,0 ,S_REGb ,REGI_AH},{L_Ib ,0 ,S_REGb ,REGI_CH}, -{L_Ib ,0 ,S_REGb ,REGI_DH},{L_Ib ,0 ,S_REGb ,REGI_BH}, -/* 0x2b8 - 0x2bf */ -{L_Id ,0 ,S_REGd ,REGI_AX},{L_Id ,0 ,S_REGd ,REGI_CX}, -{L_Id ,0 ,S_REGd ,REGI_DX},{L_Id ,0 ,S_REGd ,REGI_BX}, -{L_Id ,0 ,S_REGd ,REGI_SP},{L_Id ,0 ,S_REGd ,REGI_BP}, -{L_Id ,0 ,S_REGd ,REGI_SI},{L_Id ,0 ,S_REGd ,REGI_DI}, - -/* 0x2c0 - 0x2c7 */ -{L_MODRM ,5 ,0 ,M_GRP_Ib },{L_MODRM ,7 ,0 ,M_GRP_Ib }, -{L_POPd ,0 ,S_IPIw ,0 },{L_POPd ,0 ,S_IP ,0 }, -{L_MODRM ,O_SEGES ,S_SEGGd,M_Efd },{L_MODRM ,O_SEGDS ,S_SEGGd,M_Efd }, -{L_MODRM ,0 ,S_Eb ,M_Ib },{L_MODRM ,0 ,S_Ed ,M_Id }, -/* 0x2c8 - 0x2cf */ -{D_ENTERd ,0 ,0 ,0 },{D_LEAVEd ,0 ,0 ,0 }, -{D_RETFdIw ,0 ,0 ,0 },{D_RETFd ,0 ,0 ,0 }, -{L_VAL ,O_INT ,0 ,3 },{L_Ib ,O_INT ,0 ,0 }, -{L_INTO ,O_INT ,0 ,0 },{D_IRETd ,0 ,0 ,0 }, - -/* 0x2d0 - 0x2d7 */ -{L_MODRM ,5 ,0 ,M_GRP_1 },{L_MODRM ,7 ,0 ,M_GRP_1 }, -{L_MODRM ,5 ,0 ,M_GRP_CL },{L_MODRM ,7 ,0 ,M_GRP_CL }, -{L_Ib ,O_AAM ,0 ,0 },{L_Ib ,O_AAD ,0 ,0 }, -{D_SETALC ,0 ,0 ,0 },{D_XLAT ,0 ,0 ,0 }, -/* 0x2d8 - 0x2df */ -{L_MODRM ,O_FPU ,0 ,0 },{L_MODRM ,O_FPU ,1 ,0 }, -{L_MODRM ,O_FPU ,2 ,0 },{L_MODRM ,O_FPU ,3 ,0 }, -{L_MODRM ,O_FPU ,4 ,0 },{L_MODRM ,O_FPU ,5 ,0 }, -{L_MODRM ,O_FPU ,6 ,0 },{L_MODRM ,O_FPU ,7 ,0 }, - -/* 0x2e0 - 0x2e7 */ -{L_Ibx ,O_LOOPNZ ,S_AIPd ,0 },{L_Ibx ,O_LOOPZ ,S_AIPd ,0 }, -{L_Ibx ,O_LOOP ,S_AIPd ,0 },{L_Ibx ,O_JCXZ ,S_AIPd ,0 }, -{L_Ib ,O_INb ,0 ,0 },{L_Ib ,O_INd ,0 ,0 }, -{L_Ib ,O_OUTb ,0 ,0 },{L_Ib ,O_OUTd ,0 ,0 }, -/* 0x2e8 - 0x2ef */ -{L_Id ,O_CALLNd ,S_AIPd ,0 },{L_Idx ,0 ,S_AIPd ,0 }, -{L_Ifd ,O_JMPFd ,0 ,0 },{L_Ibx ,0 ,S_AIPd ,0 }, -{L_REGw ,O_INb ,0 ,REGI_DX},{L_REGw ,O_INd ,0 ,REGI_DX}, -{L_REGw ,O_OUTb ,0 ,REGI_DX},{L_REGw ,O_OUTd ,0 ,REGI_DX}, - -/* 0x2f0 - 0x2f7 */ -{D_LOCK ,0 ,0 ,0 },{D_ICEBP ,0 ,0 ,0 }, -{L_PREREPNE ,0 ,0 ,0 },{L_PREREP ,0 ,0 ,0 }, -{D_HLT ,0 ,0 ,0 },{D_CMC ,0 ,0 ,0 }, -{L_MODRM ,8 ,0 ,M_GRP },{L_MODRM ,0xa ,0 ,M_GRP }, -/* 0x2f8 - 0x2ff */ -{D_CLC ,0 ,0 ,0 },{D_STC ,0 ,0 ,0 }, -{D_CLI ,0 ,0 ,0 },{D_STI ,0 ,0 ,0 }, -{D_CLD ,0 ,0 ,0 },{D_STD ,0 ,0 ,0 }, -{L_MODRM ,0xb ,0 ,M_GRP },{L_MODRM ,0xd ,0 ,M_GRP }, - - -/* 0x300 - 0x307 */ -{L_MODRM ,O_GRP6d ,S_Ew ,M_Ew },{L_MODRM ,O_GRP7d ,S_Ew ,M_Ew }, -{L_MODRM_NVM ,O_LAR ,S_Gd ,M_EdGd },{L_MODRM_NVM ,O_LSL ,S_Gd ,M_EdGd }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{D_CLTS ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x308 - 0x30f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x310 - 0x317 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x318 - 0x31f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x320 - 0x327 */ -{L_MODRM ,O_M_Rd_CRx ,S_Ed ,0 },{L_MODRM ,O_M_Rd_DRx ,S_Ed ,0 }, -{L_MODRM ,O_M_CRx_Rd ,0 ,M_Ed },{L_MODRM ,O_M_DRx_Rd ,0 ,M_Ed }, -{L_MODRM ,O_M_Rd_TRx ,S_Ed ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,O_M_TRx_Rd ,0 ,M_Ed },{0 ,0 ,0 ,0 }, - -/* 0x328 - 0x32f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x330 - 0x337 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x338 - 0x33f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x340 - 0x347 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x348 - 0x34f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x350 - 0x357 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x358 - 0x35f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x360 - 0x367 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x368 - 0x36f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - - -/* 0x370 - 0x377 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x378 - 0x37f */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x380 - 0x387 */ -{L_Idx ,O_C_O ,S_C_AIPd,0 },{L_Idx ,O_C_NO ,S_C_AIPd,0 }, -{L_Idx ,O_C_B ,S_C_AIPd,0 },{L_Idx ,O_C_NB ,S_C_AIPd,0 }, -{L_Idx ,O_C_Z ,S_C_AIPd,0 },{L_Idx ,O_C_NZ ,S_C_AIPd,0 }, -{L_Idx ,O_C_BE ,S_C_AIPd,0 },{L_Idx ,O_C_NBE ,S_C_AIPd,0 }, -/* 0x388 - 0x38f */ -{L_Idx ,O_C_S ,S_C_AIPd,0 },{L_Idx ,O_C_NS ,S_C_AIPd,0 }, -{L_Idx ,O_C_P ,S_C_AIPd,0 },{L_Idx ,O_C_NP ,S_C_AIPd,0 }, -{L_Idx ,O_C_L ,S_C_AIPd,0 },{L_Idx ,O_C_NL ,S_C_AIPd,0 }, -{L_Idx ,O_C_LE ,S_C_AIPd,0 },{L_Idx ,O_C_NLE ,S_C_AIPd,0 }, - -/* 0x390 - 0x397 */ -{L_MODRM ,O_C_O ,S_C_Eb,0 },{L_MODRM ,O_C_NO ,S_C_Eb,0 }, -{L_MODRM ,O_C_B ,S_C_Eb,0 },{L_MODRM ,O_C_NB ,S_C_Eb,0 }, -{L_MODRM ,O_C_Z ,S_C_Eb,0 },{L_MODRM ,O_C_NZ ,S_C_Eb,0 }, -{L_MODRM ,O_C_BE ,S_C_Eb,0 },{L_MODRM ,O_C_NBE ,S_C_Eb,0 }, -/* 0x398 - 0x39f */ -{L_MODRM ,O_C_S ,S_C_Eb,0 },{L_MODRM ,O_C_NS ,S_C_Eb,0 }, -{L_MODRM ,O_C_P ,S_C_Eb,0 },{L_MODRM ,O_C_NP ,S_C_Eb,0 }, -{L_MODRM ,O_C_L ,S_C_Eb,0 },{L_MODRM ,O_C_NL ,S_C_Eb,0 }, -{L_MODRM ,O_C_LE ,S_C_Eb,0 },{L_MODRM ,O_C_NLE ,S_C_Eb,0 }, - -/* 0x3a0 - 0x3a7 */ -{L_SEG ,0 ,S_PUSHd ,fs },{D_POPSEGd,0 ,0 ,fs }, -{D_CPUID ,0 ,0 ,0 },{L_MODRM ,O_BTd ,S_Ed ,M_EdGdt }, -{L_MODRM ,O_DSHLd ,S_Ed,M_EdGdIb },{L_MODRM ,O_DSHLd ,S_Ed ,M_EdGdCL }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x3a8 - 0x3af */ -{L_SEG ,0 ,S_PUSHd ,gs },{D_POPSEGd,0 ,0 ,gs }, -{0 ,0 ,0 ,0 },{L_MODRM ,O_BTSd ,S_Ed ,M_EdGdt }, -{L_MODRM ,O_DSHRd ,S_Ed,M_EdGdIb },{L_MODRM ,O_DSHRd ,S_Ed ,M_EdGdCL }, -{0 ,0 ,0 ,0 },{L_MODRM ,O_IMULRd ,S_Gd ,M_EdxGdx }, - -/* 0x3b0 - 0x3b7 */ -{0 ,0 ,0 ,0 },{L_MODRM ,O_CMPXCHG ,S_Ed ,M_Ed }, -{L_MODRM ,O_SEGSS ,S_SEGGd,M_Efd },{L_MODRM ,O_BTRd ,S_Ed ,M_EdGdt }, -{L_MODRM ,O_SEGFS ,S_SEGGd,M_Efd },{L_MODRM ,O_SEGGS ,S_SEGGd,M_Efd }, -{L_MODRM ,0 ,S_Gd ,M_Eb },{L_MODRM ,0 ,S_Gd ,M_Ew }, -/* 0x3b8 - 0x3bf */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,0xf ,0 ,M_GRP },{L_MODRM ,O_BTCd ,S_Ed ,M_EdGdt }, -{L_MODRM ,O_BSFd ,S_Gd ,M_Ed },{L_MODRM ,O_BSRd ,S_Gd ,M_Ed }, -{L_MODRM ,0 ,S_Gd ,M_Ebx },{L_MODRM ,0 ,S_Gd ,M_Ewx }, - -/* 0x3c0 - 0x3cc */ -{L_MODRM ,t_ADDb ,S_EbGb ,M_GbEb },{L_MODRM ,t_ADDd ,S_EdGd ,M_GdEd }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x3c8 - 0x3cf */ -{L_REGd ,O_BSWAP ,S_REGd ,REGI_AX},{L_REGd ,O_BSWAP ,S_REGd ,REGI_CX}, -{L_REGd ,O_BSWAP ,S_REGd ,REGI_DX},{L_REGd ,O_BSWAP ,S_REGd ,REGI_BX}, -{L_REGd ,O_BSWAP ,S_REGd ,REGI_SP},{L_REGd ,O_BSWAP ,S_REGd ,REGI_BP}, -{L_REGd ,O_BSWAP ,S_REGd ,REGI_SI},{L_REGd ,O_BSWAP ,S_REGd ,REGI_DI}, - -/* 0x3d0 - 0x3d7 */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x3d8 - 0x3df */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x3e0 - 0x3ee */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x3e8 - 0x3ef */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -/* 0x3f0 - 0x3fc */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -/* 0x3f8 - 0x3ff */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, - -}; - -static OpCode Groups[16][8]={ -{ /* 0x00 Group 1 Eb,Ib */ -{0 ,t_ADDb ,S_Eb ,M_EbIb },{0 ,t_ORb ,S_Eb ,M_EbIb }, -{0 ,t_ADCb ,S_Eb ,M_EbIb },{0 ,t_SBBb ,S_Eb ,M_EbIb }, -{0 ,t_ANDb ,S_Eb ,M_EbIb },{0 ,t_SUBb ,S_Eb ,M_EbIb }, -{0 ,t_XORb ,S_Eb ,M_EbIb },{0 ,t_CMPb ,0 ,M_EbIb }, -},{ /* 0x01 Group 1 Ew,Iw */ -{0 ,t_ADDw ,S_Ew ,M_EwIw },{0 ,t_ORw ,S_Ew ,M_EwIw }, -{0 ,t_ADCw ,S_Ew ,M_EwIw },{0 ,t_SBBw ,S_Ew ,M_EwIw }, -{0 ,t_ANDw ,S_Ew ,M_EwIw },{0 ,t_SUBw ,S_Ew ,M_EwIw }, -{0 ,t_XORw ,S_Ew ,M_EwIw },{0 ,t_CMPw ,0 ,M_EwIw }, -},{ /* 0x02 Group 1 Ed,Id */ -{0 ,t_ADDd ,S_Ed ,M_EdId },{0 ,t_ORd ,S_Ed ,M_EdId }, -{0 ,t_ADCd ,S_Ed ,M_EdId },{0 ,t_SBBd ,S_Ed ,M_EdId }, -{0 ,t_ANDd ,S_Ed ,M_EdId },{0 ,t_SUBd ,S_Ed ,M_EdId }, -{0 ,t_XORd ,S_Ed ,M_EdId },{0 ,t_CMPd ,0 ,M_EdId }, -},{ /* 0x03 Group 1 Ew,Ibx */ -{0 ,t_ADDw ,S_Ew ,M_EwIbx },{0 ,t_ORw ,S_Ew ,M_EwIbx }, -{0 ,t_ADCw ,S_Ew ,M_EwIbx },{0 ,t_SBBw ,S_Ew ,M_EwIbx }, -{0 ,t_ANDw ,S_Ew ,M_EwIbx },{0 ,t_SUBw ,S_Ew ,M_EwIbx }, -{0 ,t_XORw ,S_Ew ,M_EwIbx },{0 ,t_CMPw ,0 ,M_EwIbx }, -},{ /* 0x04 Group 1 Ed,Ibx */ -{0 ,t_ADDd ,S_Ed ,M_EdIbx },{0 ,t_ORd ,S_Ed ,M_EdIbx }, -{0 ,t_ADCd ,S_Ed ,M_EdIbx },{0 ,t_SBBd ,S_Ed ,M_EdIbx }, -{0 ,t_ANDd ,S_Ed ,M_EdIbx },{0 ,t_SUBd ,S_Ed ,M_EdIbx }, -{0 ,t_XORd ,S_Ed ,M_EdIbx },{0 ,t_CMPd ,0 ,M_EdIbx }, - -},{ /* 0x05 Group 2 Eb,XXX */ -{0 ,t_ROLb ,S_Eb ,M_Eb },{0 ,t_RORb ,S_Eb ,M_Eb }, -{0 ,t_RCLb ,S_Eb ,M_Eb },{0 ,t_RCRb ,S_Eb ,M_Eb }, -{0 ,t_SHLb ,S_Eb ,M_Eb },{0 ,t_SHRb ,S_Eb ,M_Eb }, -{0 ,t_SHLb ,S_Eb ,M_Eb },{0 ,t_SARb ,S_Eb ,M_Eb }, -},{ /* 0x06 Group 2 Ew,XXX */ -{0 ,t_ROLw ,S_Ew ,M_Ew },{0 ,t_RORw ,S_Ew ,M_Ew }, -{0 ,t_RCLw ,S_Ew ,M_Ew },{0 ,t_RCRw ,S_Ew ,M_Ew }, -{0 ,t_SHLw ,S_Ew ,M_Ew },{0 ,t_SHRw ,S_Ew ,M_Ew }, -{0 ,t_SHLw ,S_Ew ,M_Ew },{0 ,t_SARw ,S_Ew ,M_Ew }, -},{ /* 0x07 Group 2 Ed,XXX */ -{0 ,t_ROLd ,S_Ed ,M_Ed },{0 ,t_RORd ,S_Ed ,M_Ed }, -{0 ,t_RCLd ,S_Ed ,M_Ed },{0 ,t_RCRd ,S_Ed ,M_Ed }, -{0 ,t_SHLd ,S_Ed ,M_Ed },{0 ,t_SHRd ,S_Ed ,M_Ed }, -{0 ,t_SHLd ,S_Ed ,M_Ed },{0 ,t_SARd ,S_Ed ,M_Ed }, - - -},{ /* 0x08 Group 3 Eb */ -{0 ,t_TESTb ,0 ,M_EbIb },{0 ,t_TESTb ,0 ,M_EbIb }, -{0 ,O_NOT ,S_Eb ,M_Eb },{0 ,t_NEGb ,S_Eb ,M_Eb }, -{0 ,O_MULb ,0 ,M_Eb },{0 ,O_IMULb ,0 ,M_Eb }, -{0 ,O_DIVb ,0 ,M_Eb },{0 ,O_IDIVb ,0 ,M_Eb }, -},{ /* 0x09 Group 3 Ew */ -{0 ,t_TESTw ,0 ,M_EwIw },{0 ,t_TESTw ,0 ,M_EwIw }, -{0 ,O_NOT ,S_Ew ,M_Ew },{0 ,t_NEGw ,S_Ew ,M_Ew }, -{0 ,O_MULw ,0 ,M_Ew },{0 ,O_IMULw ,0 ,M_Ew }, -{0 ,O_DIVw ,0 ,M_Ew },{0 ,O_IDIVw ,0 ,M_Ew }, -},{ /* 0x0a Group 3 Ed */ -{0 ,t_TESTd ,0 ,M_EdId },{0 ,t_TESTd ,0 ,M_EdId }, -{0 ,O_NOT ,S_Ed ,M_Ed },{0 ,t_NEGd ,S_Ed ,M_Ed }, -{0 ,O_MULd ,0 ,M_Ed },{0 ,O_IMULd ,0 ,M_Ed }, -{0 ,O_DIVd ,0 ,M_Ed },{0 ,O_IDIVd ,0 ,M_Ed }, - -},{ /* 0x0b Group 4 Eb */ -{0 ,t_INCb ,S_Eb ,M_Eb },{0 ,t_DECb ,S_Eb ,M_Eb }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,O_CBACK ,0 ,M_Iw }, -},{ /* 0x0c Group 5 Ew */ -{0 ,t_INCw ,S_Ew ,M_Ew },{0 ,t_DECw ,S_Ew ,M_Ew }, -{0 ,O_CALLNw ,S_IP ,M_Ew },{0 ,O_CALLFw ,0 ,M_Efw }, -{0 ,0 ,S_IP ,M_Ew },{0 ,O_JMPFw ,0 ,M_Efw }, -{0 ,0 ,S_PUSHw,M_Ew },{0 ,0 ,0 ,0 }, -},{ /* 0x0d Group 5 Ed */ -{0 ,t_INCd ,S_Ed ,M_Ed },{0 ,t_DECd ,S_Ed ,M_Ed }, -{0 ,O_CALLNd ,S_IP ,M_Ed },{0 ,O_CALLFd ,0 ,M_Efd }, -{0 ,0 ,S_IP ,M_Ed },{0 ,O_JMPFd ,0 ,M_Efd }, -{0 ,0 ,S_PUSHd,M_Ed },{0 ,0 ,0 ,0 }, - - -},{ /* 0x0e Group 8 Ew */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,O_BTw ,S_Ew ,M_EwIb },{0 ,O_BTSw ,S_Ew ,M_EwIb }, -{0 ,O_BTRw ,S_Ew ,M_EwIb },{0 ,O_BTCw ,S_Ew ,M_EwIb }, -},{ /* 0x0f Group 8 Ed */ -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,O_BTd ,S_Ed ,M_EdIb },{0 ,O_BTSd ,S_Ed ,M_EdIb }, -{0 ,O_BTRd ,S_Ed ,M_EdIb },{0 ,O_BTCd ,S_Ed ,M_EdIb }, - - - -} -}; - - - diff --git a/src/cpu/core_full/save.h b/src/cpu/core_full/save.h deleted file mode 100644 index c79ab26..0000000 --- a/src/cpu/core_full/save.h +++ /dev/null @@ -1,99 +0,0 @@ -/* Write the data from the opcode */ -switch (inst.code.save) { -/* Byte */ - case S_C_Eb: - inst_op1_b=inst.cond ? 1 : 0; - case S_Eb: - if (inst.rm<0xc0) SaveMb(inst.rm_eaa,inst_op1_b); - else reg_8(inst.rm_eai)=inst_op1_b; - break; - case S_Gb: - reg_8(inst.rm_index)=inst_op1_b; - break; - case S_EbGb: - if (inst.rm<0xc0) SaveMb(inst.rm_eaa,inst_op1_b); - else reg_8(inst.rm_eai)=inst_op1_b; - reg_8(inst.rm_index)=inst_op2_b; - break; -/* Word */ - case S_Ew: - if (inst.rm<0xc0) SaveMw(inst.rm_eaa,inst_op1_w); - else reg_16(inst.rm_eai)=inst_op1_w; - break; - case S_Gw: - reg_16(inst.rm_index)=inst_op1_w; - break; - case S_EwGw: - if (inst.rm<0xc0) SaveMw(inst.rm_eaa,inst_op1_w); - else reg_16(inst.rm_eai)=inst_op1_w; - reg_16(inst.rm_index)=inst_op2_w; - break; -/* Dword */ - case S_Ed: - if (inst.rm<0xc0) SaveMd(inst.rm_eaa,inst_op1_d); - else reg_32(inst.rm_eai)=inst_op1_d; - break; - case S_EdMw: /* Special one 16 to memory, 32 zero extend to reg */ - if (inst.rm<0xc0) SaveMw(inst.rm_eaa,inst_op1_w); - else reg_32(inst.rm_eai)=inst_op1_d; - break; - case S_Gd: - reg_32(inst.rm_index)=inst_op1_d; - break; - case S_EdGd: - if (inst.rm<0xc0) SaveMd(inst.rm_eaa,inst_op1_d); - else reg_32(inst.rm_eai)=inst_op1_d; - reg_32(inst.rm_index)=inst_op2_d; - break; - - case S_REGb: - reg_8(inst.code.extra)=inst_op1_b; - break; - case S_REGw: - reg_16(inst.code.extra)=inst_op1_w; - break; - case S_REGd: - reg_32(inst.code.extra)=inst_op1_d; - break; - case S_SEGm: - if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst_op1_w)) RunException(); - break; - case S_SEGGw: - if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst_op2_w)) RunException(); - reg_16(inst.rm_index)=inst_op1_w; - break; - case S_SEGGd: - if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst_op2_w)) RunException(); - reg_32(inst.rm_index)=inst_op1_d; - break; - case S_PUSHw: - Push_16(inst_op1_w); - break; - case S_PUSHd: - Push_32(inst_op1_d); - break; - - case S_C_AIPw: - if (!inst.cond) goto nextopcode; - case S_AIPw: - SaveIP(); - reg_eip+=inst_op1_d; - reg_eip&=0xffff; - continue; - case S_C_AIPd: - if (!inst.cond) goto nextopcode; - case S_AIPd: - SaveIP(); - reg_eip+=inst_op1_d; - continue; - case S_IPIw: - reg_esp+=Fetchw(); - case S_IP: - SaveIP(); - reg_eip=inst_op1_d; - continue; - case 0: - break; - default: - LOG(LOG_CPU,LOG_ERROR)("SAVE:Unhandled code %d entry %X",inst.code.save,inst.entry); -} diff --git a/src/cpu/core_full/string.h b/src/cpu/core_full/string.h deleted file mode 100644 index 709a155..0000000 --- a/src/cpu/core_full/string.h +++ /dev/null @@ -1,227 +0,0 @@ -{ - EAPoint si_base,di_base; - Bitu si_index,di_index; - Bitu add_mask; - Bitu count,count_left; - Bits add_index; - - if (inst.prefix & PREFIX_SEG) si_base=inst.seg.base; - else si_base=SegBase(ds); - di_base=SegBase(es); - if (inst.prefix & PREFIX_ADDR) { - add_mask=0xFFFFFFFF; - si_index=reg_esi; - di_index=reg_edi; - count=reg_ecx; - } else { - add_mask=0xFFFF; - si_index=reg_si; - di_index=reg_di; - count=reg_cx; - } - if (!(inst.prefix & PREFIX_REP)) { - count=1; - } else { - /* Calculate amount of ops to do before cycles run out */ - CPU_Cycles++; - if ((count>(Bitu)CPU_Cycles) && (inst.code.op0;count--) { - IO_WriteB(reg_dx,LoadMb(si_base+si_index)); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_OUTSW: - add_index<<=1; - for (;count>0;count--) { - IO_WriteW(reg_dx,LoadMw(si_base+si_index)); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_OUTSD: - add_index<<=2; - for (;count>0;count--) { - IO_WriteD(reg_dx,LoadMd(si_base+si_index)); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_INSB: - for (;count>0;count--) { - SaveMb(di_base+di_index,IO_ReadB(reg_dx)); - di_index=(di_index+add_index) & add_mask; - } - break; - case R_INSW: - add_index<<=1; - for (;count>0;count--) { - SaveMw(di_base+di_index,IO_ReadW(reg_dx)); - di_index=(di_index+add_index) & add_mask; - } - break; - case R_STOSB: - for (;count>0;count--) { - SaveMb(di_base+di_index,reg_al); - di_index=(di_index+add_index) & add_mask; - } - break; - case R_STOSW: - add_index<<=1; - for (;count>0;count--) { - SaveMw(di_base+di_index,reg_ax); - di_index=(di_index+add_index) & add_mask; - } - break; - case R_STOSD: - add_index<<=2; - for (;count>0;count--) { - SaveMd(di_base+di_index,reg_eax); - di_index=(di_index+add_index) & add_mask; - } - break; - case R_MOVSB: - for (;count>0;count--) { - SaveMb(di_base+di_index,LoadMb(si_base+si_index)); - di_index=(di_index+add_index) & add_mask; - si_index=(si_index+add_index) & add_mask; - } - break; - case R_MOVSW: - add_index<<=1; - for (;count>0;count--) { - SaveMw(di_base+di_index,LoadMw(si_base+si_index)); - di_index=(di_index+add_index) & add_mask; - si_index=(si_index+add_index) & add_mask; - } - break; - case R_MOVSD: - add_index<<=2; - for (;count>0;count--) { - SaveMd(di_base+di_index,LoadMd(si_base+si_index)); - di_index=(di_index+add_index) & add_mask; - si_index=(si_index+add_index) & add_mask; - } - break; - case R_LODSB: - for (;count>0;count--) { - reg_al=LoadMb(si_base+si_index); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_LODSW: - add_index<<=1; - for (;count>0;count--) { - reg_ax=LoadMw(si_base+si_index); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_LODSD: - add_index<<=2; - for (;count>0;count--) { - reg_eax=LoadMd(si_base+si_index); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_SCASB: - { - Bit8u val2; - for (;count>0;) { - count--;CPU_Cycles--; - val2=LoadMb(di_base+di_index); - di_index=(di_index+add_index) & add_mask; - if ((reg_al==val2)!=inst.repz) break; - } - CMPB(reg_al,val2,LoadD,0); - } - break; - case R_SCASW: - { - add_index<<=1;Bit16u val2; - for (;count>0;) { - count--;CPU_Cycles--; - val2=LoadMw(di_base+di_index); - di_index=(di_index+add_index) & add_mask; - if ((reg_ax==val2)!=inst.repz) break; - } - CMPW(reg_ax,val2,LoadD,0); - } - break; - case R_SCASD: - { - add_index<<=2;Bit32u val2; - for (;count>0;) { - count--;CPU_Cycles--; - val2=LoadMd(di_base+di_index); - di_index=(di_index+add_index) & add_mask; - if ((reg_eax==val2)!=inst.repz) break; - } - CMPD(reg_eax,val2,LoadD,0); - } - break; - case R_CMPSB: - { - Bit8u val1,val2; - for (;count>0;) { - count--;CPU_Cycles--; - val1=LoadMb(si_base+si_index); - val2=LoadMb(di_base+di_index); - si_index=(si_index+add_index) & add_mask; - di_index=(di_index+add_index) & add_mask; - if ((val1==val2)!=inst.repz) break; - } - CMPB(val1,val2,LoadD,0); - } - break; - case R_CMPSW: - { - add_index<<=1;Bit16u val1,val2; - for (;count>0;) { - count--;CPU_Cycles--; - val1=LoadMw(si_base+si_index); - val2=LoadMw(di_base+di_index); - si_index=(si_index+add_index) & add_mask; - di_index=(di_index+add_index) & add_mask; - if ((val1==val2)!=inst.repz) break; - } - CMPW(val1,val2,LoadD,0); - } - break; - case R_CMPSD: - { - add_index<<=2;Bit32u val1,val2; - for (;count>0;) { - count--;CPU_Cycles--; - val1=LoadMd(si_base+si_index); - val2=LoadMd(di_base+di_index); - si_index=(si_index+add_index) & add_mask; - di_index=(di_index+add_index) & add_mask; - if ((val1==val2)!=inst.repz) break; - } - CMPD(val1,val2,LoadD,0); - } - break; - default: - LOG(LOG_CPU,LOG_ERROR)("Unhandled string %d entry %X",inst.code.op,inst.entry); - } - /* Clean up after certain amount of instructions */ - reg_esi&=(~add_mask); - reg_esi|=(si_index & add_mask); - reg_edi&=(~add_mask); - reg_edi|=(di_index & add_mask); - if (inst.prefix & PREFIX_REP) { - count+=count_left; - reg_ecx&=(~add_mask); - reg_ecx|=(count & add_mask); - } -} diff --git a/src/cpu/core_full/support.h b/src/cpu/core_full/support.h deleted file mode 100644 index c205216..0000000 --- a/src/cpu/core_full/support.h +++ /dev/null @@ -1,248 +0,0 @@ -enum { - L_N=0, - L_SKIP, - /* Grouped ones using MOD/RM */ - L_MODRM,L_MODRM_NVM,L_POPwRM,L_POPdRM, - - L_Ib,L_Iw,L_Id, - L_Ibx,L_Iwx,L_Idx, //Sign extend - L_Ifw,L_Ifd, - L_OP, - - L_REGb,L_REGw,L_REGd, - L_REGbIb,L_REGwIw,L_REGdId, - L_POPw,L_POPd, - L_POPfw,L_POPfd, - L_SEG, - - L_INTO, - - L_VAL, - L_PRESEG, - L_DOUBLE, - L_PREOP,L_PREADD,L_PREREP,L_PREREPNE, - L_STRING, - -/* Direct ones */ - D_IRETw,D_IRETd, - D_PUSHAw,D_PUSHAd, - D_POPAw,D_POPAd, - D_POPSEGw,D_POPSEGd, - D_DAA,D_DAS, - D_AAA,D_AAS, - D_CBW,D_CWDE, - D_CWD,D_CDQ, - D_SETALC, - D_XLAT, - D_CLI,D_STI,D_STC,D_CLC,D_CMC,D_CLD,D_STD, - D_NOP,D_WAIT, - D_ENTERw,D_ENTERd, - D_LEAVEw,D_LEAVEd, - - D_RETFw,D_RETFd, - D_RETFwIw,D_RETFdIw, - D_POPF,D_PUSHF, - D_SAHF,D_LAHF, - D_CPUID, - D_HLT,D_CLTS, - D_LOCK,D_ICEBP, - L_ERROR -}; - - -enum { - O_N=t_LASTFLAG, - O_COND, - O_XCHG_AX,O_XCHG_EAX, - O_IMULRw,O_IMULRd, - O_BOUNDw,O_BOUNDd, - O_CALLNw,O_CALLNd, - O_CALLFw,O_CALLFd, - O_JMPFw,O_JMPFd, - - O_OPAL,O_ALOP, - O_OPAX,O_AXOP, - O_OPEAX,O_EAXOP, - O_INT, - O_SEGDS,O_SEGES,O_SEGFS,O_SEGGS,O_SEGSS, - O_LOOP,O_LOOPZ,O_LOOPNZ,O_JCXZ, - O_INb,O_INw,O_INd, - O_OUTb,O_OUTw,O_OUTd, - - O_NOT,O_AAM,O_AAD, - O_MULb,O_MULw,O_MULd, - O_IMULb,O_IMULw,O_IMULd, - O_DIVb,O_DIVw,O_DIVd, - O_IDIVb,O_IDIVw,O_IDIVd, - O_CBACK, - - - O_DSHLw,O_DSHLd, - O_DSHRw,O_DSHRd, - O_C_O ,O_C_NO ,O_C_B ,O_C_NB ,O_C_Z ,O_C_NZ ,O_C_BE ,O_C_NBE, - O_C_S ,O_C_NS ,O_C_P ,O_C_NP ,O_C_L ,O_C_NL ,O_C_LE ,O_C_NLE, - - O_GRP6w,O_GRP6d, - O_GRP7w,O_GRP7d, - O_M_CRx_Rd,O_M_Rd_CRx, - O_M_DRx_Rd,O_M_Rd_DRx, - O_M_TRx_Rd,O_M_Rd_TRx, - O_LAR,O_LSL, - O_ARPL, - - O_BTw,O_BTSw,O_BTRw,O_BTCw, - O_BTd,O_BTSd,O_BTRd,O_BTCd, - O_BSFw,O_BSRw,O_BSFd,O_BSRd, - - O_BSWAP,O_CMPXCHG, - O_FPU - - -}; - -enum { - S_N=0, - S_C_Eb, - S_Eb,S_Gb,S_EbGb, - S_Ew,S_Gw,S_EwGw, - S_Ed,S_Gd,S_EdGd,S_EdMw, - - - S_REGb,S_REGw,S_REGd, - S_PUSHw,S_PUSHd, - S_SEGm, - S_SEGGw,S_SEGGd, - - - S_AIPw,S_C_AIPw, - S_AIPd,S_C_AIPd, - - S_IP,S_IPIw -}; - -enum { - R_OUTSB,R_OUTSW,R_OUTSD, - R_INSB,R_INSW,R_INSD, - R_MOVSB,R_MOVSW,R_MOVSD, - R_LODSB,R_LODSW,R_LODSD, - R_STOSB,R_STOSW,R_STOSD, - R_SCASB,R_SCASW,R_SCASD, - R_CMPSB,R_CMPSW,R_CMPSD -}; - -enum { - M_None=0, - M_Ebx,M_Eb,M_Gb,M_EbGb,M_GbEb, - M_Ewx,M_Ew,M_Gw,M_EwGw,M_GwEw,M_EwxGwx,M_EwGwt, - M_Edx,M_Ed,M_Gd,M_EdGd,M_GdEd,M_EdxGdx,M_EdGdt, - - M_EbIb,M_EwIb,M_EdIb, - M_EwIw,M_EwIbx,M_EwxIbx,M_EwxIwx,M_EwGwIb,M_EwGwCL, - M_EdId,M_EdIbx,M_EdGdIb,M_EdGdCL, - - M_Efw,M_Efd, - - M_Ib,M_Iw,M_Id, - - - M_SEG,M_EA, - M_GRP, - M_GRP_Ib,M_GRP_CL,M_GRP_1, - - M_POPw,M_POPd -}; - -struct OpCode { - Bit8u load,op,save,extra; -}; - -struct FullData { - Bitu entry; - Bitu rm; - EAPoint rm_eaa; - Bitu rm_off; - Bitu rm_eai; - Bitu rm_index; - Bitu rm_mod; - OpCode code; - EAPoint cseip; -#ifdef WORDS_BIGENDIAN - union { - Bit32u dword[1]; - Bit32s dwords[1]; - Bit16u word[2]; - Bit16s words[2]; - Bit8u byte[4]; - Bit8s bytes[4]; - } blah1,blah2,blah_imm; -#else - union { - Bit8u b;Bit8s bs; - Bit16u w;Bit16s ws; - Bit32u d;Bit32s ds; - } op1,op2,imm; -#endif - Bitu new_flags; - struct { - EAPoint base; - } seg; - Bitu cond; - bool repz; - Bitu prefix; -}; - -/* Some defines to get the names correct. */ -#ifdef WORDS_BIGENDIAN - -#define inst_op1_b inst.blah1.byte[3] -#define inst_op1_bs inst.blah1.bytes[3] -#define inst_op1_w inst.blah1.word[1] -#define inst_op1_ws inst.blah1.words[1] -#define inst_op1_d inst.blah1.dword[0] -#define inst_op1_ds inst.blah1.dwords[0] - -#define inst_op2_b inst.blah2.byte[3] -#define inst_op2_bs inst.blah2.bytes[3] -#define inst_op2_w inst.blah2.word[1] -#define inst_op2_ws inst.blah2.words[1] -#define inst_op2_d inst.blah2.dword[0] -#define inst_op2_ds inst.blah2.dwords[0] - -#define inst_imm_b inst.blah_imm.byte[3] -#define inst_imm_bs inst.blah_imm.bytes[3] -#define inst_imm_w inst.blah_imm.word[1] -#define inst_imm_ws inst.blah_imm.words[1] -#define inst_imm_d inst.blah_imm.dword[0] -#define inst_imm_ds inst.blah_imm.dwords[0] - -#else - -#define inst_op1_b inst.op1.b -#define inst_op1_bs inst.op1.bs -#define inst_op1_w inst.op1.w -#define inst_op1_ws inst.op1.ws -#define inst_op1_d inst.op1.d -#define inst_op1_ds inst.op1.ds - -#define inst_op2_b inst.op2.b -#define inst_op2_bs inst.op2.bs -#define inst_op2_w inst.op2.w -#define inst_op2_ws inst.op2.ws -#define inst_op2_d inst.op2.d -#define inst_op2_ds inst.op2.ds - -#define inst_imm_b inst.imm.b -#define inst_imm_bs inst.imm.bs -#define inst_imm_w inst.imm.w -#define inst_imm_ws inst.imm.ws -#define inst_imm_d inst.imm.d -#define inst_imm_ds inst.imm.ds - -#endif - - -#define PREFIX_NONE 0x0 -#define PREFIX_ADDR 0x1 -#define PREFIX_SEG 0x2 -#define PREFIX_REP 0x4 - diff --git a/src/cpu/core_normal.cpp b/src/cpu/core_normal.cpp deleted file mode 100644 index fb2f2c8..0000000 --- a/src/cpu/core_normal.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include - -#include "dosbox.h" -#include "mem.h" -#include "cpu.h" -#include "lazyflags.h" -#include "inout.h" -#include "callback.h" -#include "pic.h" -#include "fpu.h" -#include "paging.h" - -#if C_DEBUG -#include "debug.h" -#endif - -#if (!C_CORE_INLINE) -#define LoadMb(off) mem_readb(off) -#define LoadMw(off) mem_readw(off) -#define LoadMd(off) mem_readd(off) -#define SaveMb(off,val) mem_writeb(off,val) -#define SaveMw(off,val) mem_writew(off,val) -#define SaveMd(off,val) mem_writed(off,val) -#else -#include "paging.h" -#define LoadMb(off) mem_readb_inline(off) -#define LoadMw(off) mem_readw_inline(off) -#define LoadMd(off) mem_readd_inline(off) -#define SaveMb(off,val) mem_writeb_inline(off,val) -#define SaveMw(off,val) mem_writew_inline(off,val) -#define SaveMd(off,val) mem_writed_inline(off,val) -#endif - -extern Bitu cycle_count; - -#if C_FPU -#define CPU_FPU 1 //Enable FPU escape instructions -#endif - -#define CPU_PIC_CHECK 1 -#define CPU_TRAP_CHECK 1 - -#define OPCODE_NONE 0x000 -#define OPCODE_0F 0x100 -#define OPCODE_SIZE 0x200 - -#define PREFIX_ADDR 0x1 -#define PREFIX_REP 0x2 - -#define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR) -#define TEST_PREFIX_REP (core.prefixes & PREFIX_REP) - -#define DO_PREFIX_SEG(_SEG) \ - BaseDS=SegBase(_SEG); \ - BaseSS=SegBase(_SEG); \ - core.base_val_ds=_SEG; \ - goto restart_opcode; - -#define DO_PREFIX_ADDR() \ - core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \ - (cpu.code.big ^ PREFIX_ADDR); \ - core.ea_table=&EATable[(core.prefixes&1) * 256]; \ - goto restart_opcode; - -#define DO_PREFIX_REP(_ZERO) \ - core.prefixes|=PREFIX_REP; \ - core.rep_zero=_ZERO; \ - goto restart_opcode; - -typedef PhysPt (*GetEAHandler)(void); - -static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff}; - -static struct { - Bitu opcode_index; - PhysPt cseip; - PhysPt base_ds,base_ss; - SegNames base_val_ds; - bool rep_zero; - Bitu prefixes; - GetEAHandler * ea_table; -} core; - -#define GETIP (core.cseip-SegBase(cs)) -#define SAVEIP reg_eip=GETIP; -#define LOADIP core.cseip=(SegBase(cs)+reg_eip); - -#define SegBase(c) SegPhys(c) -#define BaseDS core.base_ds -#define BaseSS core.base_ss - -static INLINE Bit8u Fetchb() { - Bit8u temp=LoadMb(core.cseip); - core.cseip+=1; - return temp; -} - -static INLINE Bit16u Fetchw() { - Bit16u temp=LoadMw(core.cseip); - core.cseip+=2; - return temp; -} -static INLINE Bit32u Fetchd() { - Bit32u temp=LoadMd(core.cseip); - core.cseip+=4; - return temp; -} - -#define Push_16 CPU_Push16 -#define Push_32 CPU_Push32 -#define Pop_16 CPU_Pop16 -#define Pop_32 CPU_Pop32 - -#include "instructions.h" -#include "core_normal/support.h" -#include "core_normal/string.h" - - -#define EALookupTable (core.ea_table) - -Bits CPU_Core_Normal_Run(void) { - while (CPU_Cycles-->0) { - LOADIP; - core.opcode_index=cpu.code.big*0x200; - core.prefixes=cpu.code.big; - core.ea_table=&EATable[cpu.code.big*256]; - BaseDS=SegBase(ds); - BaseSS=SegBase(ss); - core.base_val_ds=ds; -#if C_DEBUG -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) { - FillFlags(); - return debugCallback; - }; -#endif - cycle_count++; -#endif -restart_opcode: - switch (core.opcode_index+Fetchb()) { - #include "core_normal/prefix_none.h" - #include "core_normal/prefix_0f.h" - #include "core_normal/prefix_66.h" - #include "core_normal/prefix_66_0f.h" - default: - illegal_opcode: -#if C_DEBUG - { - Bitu len=(GETIP-reg_eip); - LOADIP; - if (len>16) len=16; - char tempcode[16*2+1];char * writecode=tempcode; - for (;len>0;len--) { - sprintf(writecode,"%02X",mem_readb(core.cseip++)); - writecode+=2; - } - LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode); - } -#endif - CPU_Exception(6,0); - continue; - } - SAVEIP; - } - FillFlags(); - return CBRET_NONE; -decode_end: - SAVEIP; - FillFlags(); - return CBRET_NONE; -} - -Bits CPU_Core_Normal_Trap_Run(void) { - Bits oldCycles = CPU_Cycles; - CPU_Cycles = 1; - cpu.trap_skip = false; - - Bits ret=CPU_Core_Normal_Run(); - if (!cpu.trap_skip) CPU_HW_Interrupt(1); - CPU_Cycles = oldCycles-1; - cpudecoder = &CPU_Core_Normal_Run; - - return ret; -} - - - -void CPU_Core_Normal_Init(void) { - -} - diff --git a/src/cpu/core_normal/Makefile.am b/src/cpu/core_normal/Makefile.am deleted file mode 100644 index 44f5f05..0000000 --- a/src/cpu/core_normal/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ - -noinst_HEADERS = helpers.h prefix_none.h prefix_66.h prefix_0f.h support.h table_ea.h \ - prefix_66_0f.h string.h diff --git a/src/cpu/core_normal/helpers.h b/src/cpu/core_normal/helpers.h deleted file mode 100644 index a5cfd2f..0000000 --- a/src/cpu/core_normal/helpers.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -#define GetEAa \ - PhysPt eaa=EALookupTable[rm](); - -#define GetRMEAa \ - GetRM; \ - GetEAa; - - -#define RMEbGb(inst) \ - { \ - GetRMrb; \ - if (rm >= 0xc0 ) {GetEArb;inst(*earb,*rmrb,LoadRb,SaveRb);} \ - else {GetEAa;inst(eaa,*rmrb,LoadMb,SaveMb);} \ - } - -#define RMGbEb(inst) \ - { \ - GetRMrb; \ - if (rm >= 0xc0 ) {GetEArb;inst(*rmrb,*earb,LoadRb,SaveRb);} \ - else {GetEAa;inst(*rmrb,LoadMb(eaa),LoadRb,SaveRb);} \ - } - -#define RMEb(inst) \ - { \ - if (rm >= 0xc0 ) {GetEArb;inst(*earb,LoadRb,SaveRb);} \ - else {GetEAa;inst(eaa,LoadMb,SaveMb);} \ - } - -#define RMEwGw(inst) \ - { \ - GetRMrw; \ - if (rm >= 0xc0 ) {GetEArw;inst(*earw,*rmrw,LoadRw,SaveRw);} \ - else {GetEAa;inst(eaa,*rmrw,LoadMw,SaveMw);} \ - } - -#define RMEwGwOp3(inst,op3) \ - { \ - GetRMrw; \ - if (rm >= 0xc0 ) {GetEArw;inst(*earw,*rmrw,op3,LoadRw,SaveRw);} \ - else {GetEAa;inst(eaa,*rmrw,op3,LoadMw,SaveMw);} \ - } - -#define RMGwEw(inst) \ - { \ - GetRMrw; \ - if (rm >= 0xc0 ) {GetEArw;inst(*rmrw,*earw,LoadRw,SaveRw);} \ - else {GetEAa;inst(*rmrw,LoadMw(eaa),LoadRw,SaveRw);} \ - } - -#define RMGwEwOp3(inst,op3) \ - { \ - GetRMrw; \ - if (rm >= 0xc0 ) {GetEArw;inst(*rmrw,*earw,op3,LoadRw,SaveRw);} \ - else {GetEAa;inst(*rmrw,LoadMw(eaa),op3,LoadRw,SaveRw);} \ - } - -#define RMEw(inst) \ - { \ - if (rm >= 0xc0 ) {GetEArw;inst(*earw,LoadRw,SaveRw);} \ - else {GetEAa;inst(eaa,LoadMw,SaveMw);} \ - } - -#define RMEdGd(inst) \ - { \ - GetRMrd; \ - if (rm >= 0xc0 ) {GetEArd;inst(*eard,*rmrd,LoadRd,SaveRd);} \ - else {GetEAa;inst(eaa,*rmrd,LoadMd,SaveMd);} \ - } - -#define RMEdGdOp3(inst,op3) \ - { \ - GetRMrd; \ - if (rm >= 0xc0 ) {GetEArd;inst(*eard,*rmrd,op3,LoadRd,SaveRd);} \ - else {GetEAa;inst(eaa,*rmrd,op3,LoadMd,SaveMd);} \ - } - - -#define RMGdEd(inst) \ - { \ - GetRMrd; \ - if (rm >= 0xc0 ) {GetEArd;inst(*rmrd,*eard,LoadRd,SaveRd);} \ - else {GetEAa;inst(*rmrd,LoadMd(eaa),LoadRd,SaveRd);} \ - } - -#define RMGdEdOp3(inst,op3) \ - { \ - GetRMrd; \ - if (rm >= 0xc0 ) {GetEArd;inst(*rmrd,*eard,op3,LoadRd,SaveRd);} \ - else {GetEAa;inst(*rmrd,LoadMd(eaa),op3,LoadRd,SaveRd);} \ - } - - - - -#define RMEw(inst) \ - { \ - if (rm >= 0xc0 ) {GetEArw;inst(*earw,LoadRw,SaveRw);} \ - else {GetEAa;inst(eaa,LoadMw,SaveMw);} \ - } - -#define RMEd(inst) \ - { \ - if (rm >= 0xc0 ) {GetEArd;inst(*eard,LoadRd,SaveRd);} \ - else {GetEAa;inst(eaa,LoadMd,SaveMd);} \ - } - -#define ALIb(inst) \ - { inst(reg_al,Fetchb(),LoadRb,SaveRb)} - -#define AXIw(inst) \ - { inst(reg_ax,Fetchw(),LoadRw,SaveRw);} - -#define EAXId(inst) \ - { inst(reg_eax,Fetchd(),LoadRd,SaveRd);} - -#define FPU_ESC(code) { \ - Bit8u rm=Fetchb(); \ - if (rm >= 0xc0) { \ - FPU_ESC ## code ## _Normal(rm); \ - } else { \ - GetEAa;FPU_ESC ## code ## _EA(rm,eaa); \ - } \ -} - -#define CASE_W(_WHICH) \ - case (OPCODE_NONE+_WHICH): - -#define CASE_D(_WHICH) \ - case (OPCODE_SIZE+_WHICH): - -#define CASE_B(_WHICH) \ - CASE_W(_WHICH) \ - CASE_D(_WHICH) - -#define CASE_0F_W(_WHICH) \ - case ((OPCODE_0F|OPCODE_NONE)+_WHICH): - -#define CASE_0F_D(_WHICH) \ - case ((OPCODE_0F|OPCODE_SIZE)+_WHICH): - -#define CASE_0F_B(_WHICH) \ - CASE_0F_W(_WHICH) \ - CASE_0F_D(_WHICH) diff --git a/src/cpu/core_normal/prefix_0f.h b/src/cpu/core_normal/prefix_0f.h deleted file mode 100644 index 9ce8df7..0000000 --- a/src/cpu/core_normal/prefix_0f.h +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - CASE_0F_W(0x00) /* GRP 6 Exxx */ - { - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - GetRM;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* SLDT */ - case 0x01: /* STR */ - { - Bitu saveval; - if (!which) saveval=CPU_SLDT(); - else saveval=CPU_STR(); - if (rm >= 0xc0) {GetEArw;*earw=saveval;} - else {GetEAa;SaveMw(eaa,saveval);} - } - break; - case 0x02:case 0x03:case 0x04:case 0x05: - { - Bitu loadval; - if (rm >= 0xc0 ) {GetEArw;loadval=*earw;} - else {GetEAa;loadval=LoadMw(eaa);} - switch (which) { - case 0x02: - if (cpu.cpl) EXCEPTION(EXCEPTION_GP); - if (CPU_LLDT(loadval)) RUNEXCEPTION(); - break; - case 0x03: - if (cpu.cpl) EXCEPTION(EXCEPTION_GP); - if (CPU_LTR(loadval)) RUNEXCEPTION(); - break; - case 0x04: - CPU_VERR(loadval); - break; - case 0x05: - CPU_VERW(loadval); - break; - } - } - break; - default: - goto illegal_opcode; - } - } - break; - CASE_0F_W(0x01) /* Group 7 Ew */ - { - GetRM;Bitu which=(rm>>3)&7; - if (rm < 0xc0) { //First ones all use EA - GetEAa;Bitu limit; - switch (which) { - case 0x00: /* SGDT */ - SaveMw(eaa,CPU_SGDT_limit()); - SaveMd(eaa+2,CPU_SGDT_base()); - break; - case 0x01: /* SIDT */ - SaveMw(eaa,CPU_SIDT_limit()); - SaveMd(eaa+2,CPU_SIDT_base()); - break; - case 0x02: /* LGDT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - CPU_LGDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF); - break; - case 0x03: /* LIDT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF); - break; - case 0x04: /* SMSW */ - SaveMw(eaa,CPU_SMSW()); - break; - case 0x06: /* LMSW */ - limit=LoadMw(eaa); - if (CPU_LMSW(limit)) RUNEXCEPTION(); - break; - case 0x07: /* INVLPG */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - PAGING_ClearTLB(); - break; - } - } else { - GetEArw; - switch (which) { - case 0x02: /* LGDT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - goto illegal_opcode; - case 0x03: /* LIDT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - goto illegal_opcode; - case 0x04: /* SMSW */ - *earw=CPU_SMSW(); - break; - case 0x06: /* LMSW */ - if (CPU_LMSW(*earw)) RUNEXCEPTION(); - break; - default: - goto illegal_opcode; - } - } - } - break; - CASE_0F_W(0x02) /* LAR Gw,Ew */ - { - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - GetRMrw;Bitu ar=*rmrw; - if (rm >= 0xc0) { - GetEArw;CPU_LAR(*earw,ar); - } else { - GetEAa;CPU_LAR(LoadMw(eaa),ar); - } - *rmrw=(Bit16u)ar; - } - break; - CASE_0F_W(0x03) /* LSL Gw,Ew */ - { - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - GetRMrw;Bitu limit=*rmrw; - if (rm >= 0xc0) { - GetEArw;CPU_LSL(*earw,limit); - } else { - GetEAa;CPU_LSL(LoadMw(eaa),limit); - } - *rmrw=(Bit16u)limit; - } - break; - CASE_0F_B(0x06) /* CLTS */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - cpu.cr0&=(~CR0_TASKSWITCH); - break; - CASE_0F_B(0x08) /* INVD */ - CASE_0F_B(0x09) /* WBINVD */ - if (CPU_ArchitectureType> 3) & 7; - if (rm < 0xc0 ) { - rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%u with non-register",which); - } - GetEArd; - Bit32u crx_value; - if (CPU_READ_CRX(which,crx_value)) RUNEXCEPTION(); - *eard=crx_value; - } - break; - CASE_0F_B(0x21) /* MOV Rd,DRx */ - { - GetRM; - Bitu which=(rm >> 3) & 7; - if (rm < 0xc0 ) { - rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV XXX,DR%u with non-register",which); - } - GetEArd; - Bit32u drx_value; - if (CPU_READ_DRX(which,drx_value)) RUNEXCEPTION(); - *eard=drx_value; - } - break; - CASE_0F_B(0x22) /* MOV CRx,Rd */ - { - GetRM; - Bitu which=(rm >> 3) & 7; - if (rm < 0xc0 ) { - rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%u with non-register",which); - } - GetEArd; - if (CPU_WRITE_CRX(which,*eard)) RUNEXCEPTION(); - } - break; - CASE_0F_B(0x23) /* MOV DRx,Rd */ - { - GetRM; - Bitu which=(rm >> 3) & 7; - if (rm < 0xc0 ) { - rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV DR%u,XXX with non-register",which); - } - GetEArd; - if (CPU_WRITE_DRX(which,*eard)) RUNEXCEPTION(); - } - break; - CASE_0F_B(0x24) /* MOV Rd,TRx */ - { - GetRM; - Bitu which=(rm >> 3) & 7; - if (rm < 0xc0 ) { - rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV XXX,TR%u with non-register",which); - } - GetEArd; - Bit32u trx_value; - if (CPU_READ_TRX(which,trx_value)) RUNEXCEPTION(); - *eard=trx_value; - } - break; - CASE_0F_B(0x26) /* MOV TRx,Rd */ - { - GetRM; - Bitu which=(rm >> 3) & 7; - if (rm < 0xc0 ) { - rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV TR%u,XXX with non-register",which); - } - GetEArd; - if (CPU_WRITE_TRX(which,*eard)) RUNEXCEPTION(); - } - break; - CASE_0F_B(0x31) /* RDTSC */ - { - if (CPU_ArchitectureType>32); - reg_eax=(Bit32u)(tsc&0xffffffff); - } - break; - CASE_0F_W(0x80) /* JO */ - JumpCond16_w(TFLG_O);break; - CASE_0F_W(0x81) /* JNO */ - JumpCond16_w(TFLG_NO);break; - CASE_0F_W(0x82) /* JB */ - JumpCond16_w(TFLG_B);break; - CASE_0F_W(0x83) /* JNB */ - JumpCond16_w(TFLG_NB);break; - CASE_0F_W(0x84) /* JZ */ - JumpCond16_w(TFLG_Z);break; - CASE_0F_W(0x85) /* JNZ */ - JumpCond16_w(TFLG_NZ);break; - CASE_0F_W(0x86) /* JBE */ - JumpCond16_w(TFLG_BE);break; - CASE_0F_W(0x87) /* JNBE */ - JumpCond16_w(TFLG_NBE);break; - CASE_0F_W(0x88) /* JS */ - JumpCond16_w(TFLG_S);break; - CASE_0F_W(0x89) /* JNS */ - JumpCond16_w(TFLG_NS);break; - CASE_0F_W(0x8a) /* JP */ - JumpCond16_w(TFLG_P);break; - CASE_0F_W(0x8b) /* JNP */ - JumpCond16_w(TFLG_NP);break; - CASE_0F_W(0x8c) /* JL */ - JumpCond16_w(TFLG_L);break; - CASE_0F_W(0x8d) /* JNL */ - JumpCond16_w(TFLG_NL);break; - CASE_0F_W(0x8e) /* JLE */ - JumpCond16_w(TFLG_LE);break; - CASE_0F_W(0x8f) /* JNLE */ - JumpCond16_w(TFLG_NLE);break; - CASE_0F_B(0x90) /* SETO */ - SETcc(TFLG_O);break; - CASE_0F_B(0x91) /* SETNO */ - SETcc(TFLG_NO);break; - CASE_0F_B(0x92) /* SETB */ - SETcc(TFLG_B);break; - CASE_0F_B(0x93) /* SETNB */ - SETcc(TFLG_NB);break; - CASE_0F_B(0x94) /* SETZ */ - SETcc(TFLG_Z);break; - CASE_0F_B(0x95) /* SETNZ */ - SETcc(TFLG_NZ); break; - CASE_0F_B(0x96) /* SETBE */ - SETcc(TFLG_BE);break; - CASE_0F_B(0x97) /* SETNBE */ - SETcc(TFLG_NBE);break; - CASE_0F_B(0x98) /* SETS */ - SETcc(TFLG_S);break; - CASE_0F_B(0x99) /* SETNS */ - SETcc(TFLG_NS);break; - CASE_0F_B(0x9a) /* SETP */ - SETcc(TFLG_P);break; - CASE_0F_B(0x9b) /* SETNP */ - SETcc(TFLG_NP);break; - CASE_0F_B(0x9c) /* SETL */ - SETcc(TFLG_L);break; - CASE_0F_B(0x9d) /* SETNL */ - SETcc(TFLG_NL);break; - CASE_0F_B(0x9e) /* SETLE */ - SETcc(TFLG_LE);break; - CASE_0F_B(0x9f) /* SETNLE */ - SETcc(TFLG_NLE);break; - - CASE_0F_W(0xa0) /* PUSH FS */ - Push_16(SegValue(fs));break; - CASE_0F_W(0xa1) /* POP FS */ - if (CPU_PopSeg(fs,false)) RUNEXCEPTION(); - break; - CASE_0F_B(0xa2) /* CPUID */ - if (!CPU_CPUID()) goto illegal_opcode; - break; - CASE_0F_W(0xa3) /* BT Ew,Gw */ - { - FillFlags();GetRMrw; - Bit16u mask=1 << (*rmrw & 15); - if (rm >= 0xc0 ) { - GetEArw; - SETFLAGBIT(CF,(*earw & mask)); - } else { - GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2; - Bit16u old=LoadMw(eaa); - SETFLAGBIT(CF,(old & mask)); - } - break; - } - CASE_0F_W(0xa4) /* SHLD Ew,Gw,Ib */ - RMEwGwOp3(DSHLW,Fetchb()); - break; - CASE_0F_W(0xa5) /* SHLD Ew,Gw,CL */ - RMEwGwOp3(DSHLW,reg_cl); - break; - CASE_0F_W(0xa8) /* PUSH GS */ - Push_16(SegValue(gs));break; - CASE_0F_W(0xa9) /* POP GS */ - if (CPU_PopSeg(gs,false)) RUNEXCEPTION(); - break; - CASE_0F_W(0xab) /* BTS Ew,Gw */ - { - FillFlags();GetRMrw; - Bit16u mask=1 << (*rmrw & 15); - if (rm >= 0xc0 ) { - GetEArw; - SETFLAGBIT(CF,(*earw & mask)); - *earw|=mask; - } else { - GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2; - Bit16u old=LoadMw(eaa); - SETFLAGBIT(CF,(old & mask)); - SaveMw(eaa,old | mask); - } - break; - } - CASE_0F_W(0xac) /* SHRD Ew,Gw,Ib */ - RMEwGwOp3(DSHRW,Fetchb()); - break; - CASE_0F_W(0xad) /* SHRD Ew,Gw,CL */ - RMEwGwOp3(DSHRW,reg_cl); - break; - CASE_0F_W(0xaf) /* IMUL Gw,Ew */ - RMGwEwOp3(DIMULW,*rmrw); - break; - CASE_0F_W(0xb2) /* LSS Ew */ - { - GetRMrw; - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - if (CPU_SetSegGeneral(ss,LoadMw(eaa+2))) RUNEXCEPTION(); - *rmrw=LoadMw(eaa); - break; - } - CASE_0F_W(0xb3) /* BTR Ew,Gw */ - { - FillFlags();GetRMrw; - Bit16u mask=1 << (*rmrw & 15); - if (rm >= 0xc0 ) { - GetEArw; - SETFLAGBIT(CF,(*earw & mask)); - *earw&= ~mask; - } else { - GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2; - Bit16u old=LoadMw(eaa); - SETFLAGBIT(CF,(old & mask)); - SaveMw(eaa,old & ~mask); - } - break; - } - CASE_0F_W(0xb4) /* LFS Ew */ - { - GetRMrw; - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - if (CPU_SetSegGeneral(fs,LoadMw(eaa+2))) RUNEXCEPTION(); - *rmrw=LoadMw(eaa); - break; - } - CASE_0F_W(0xb5) /* LGS Ew */ - { - GetRMrw; - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - if (CPU_SetSegGeneral(gs,LoadMw(eaa+2))) RUNEXCEPTION(); - *rmrw=LoadMw(eaa); - break; - } - CASE_0F_W(0xb6) /* MOVZX Gw,Eb */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArb;*rmrw=*earb;} - else {GetEAa;*rmrw=LoadMb(eaa);} - break; - } - CASE_0F_W(0xb7) /* MOVZX Gw,Ew */ - CASE_0F_W(0xbf) /* MOVSX Gw,Ew */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;} - else {GetEAa;*rmrw=LoadMw(eaa);} - break; - } - CASE_0F_W(0xba) /* GRP8 Ew,Ib */ - { - FillFlags();GetRM; - if (rm >= 0xc0 ) { - GetEArw; - Bit16u mask=1 << (Fetchb() & 15); - SETFLAGBIT(CF,(*earw & mask)); - switch (rm & 0x38) { - case 0x20: /* BT */ - break; - case 0x28: /* BTS */ - *earw|=mask; - break; - case 0x30: /* BTR */ - *earw&= ~mask; - break; - case 0x38: /* BTC */ - *earw^=mask; - break; - default: - E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38); - } - } else { - GetEAa;Bit16u old=LoadMw(eaa); - Bit16u mask=1 << (Fetchb() & 15); - SETFLAGBIT(CF,(old & mask)); - switch (rm & 0x38) { - case 0x20: /* BT */ - break; - case 0x28: /* BTS */ - SaveMw(eaa,old|mask); - break; - case 0x30: /* BTR */ - SaveMw(eaa,old & ~mask); - break; - case 0x38: /* BTC */ - SaveMw(eaa,old ^ mask); - break; - default: - E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38); - } - } - break; - } - CASE_0F_W(0xbb) /* BTC Ew,Gw */ - { - FillFlags();GetRMrw; - Bit16u mask=1 << (*rmrw & 15); - if (rm >= 0xc0 ) { - GetEArw; - SETFLAGBIT(CF,(*earw & mask)); - *earw^=mask; - } else { - GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2; - Bit16u old=LoadMw(eaa); - SETFLAGBIT(CF,(old & mask)); - SaveMw(eaa,old ^ mask); - } - break; - } - CASE_0F_W(0xbc) /* BSF Gw,Ew */ - { - GetRMrw; - Bit16u result,value; - if (rm >= 0xc0) { GetEArw; value=*earw; } - else { GetEAa; value=LoadMw(eaa); } - if (value==0) { - SETFLAGBIT(ZF,true); - } else { - result = 0; - while ((value & 0x01)==0) { result++; value>>=1; } - SETFLAGBIT(ZF,false); - *rmrw = result; - } - lflags.type=t_UNKNOWN; - break; - } - CASE_0F_W(0xbd) /* BSR Gw,Ew */ - { - GetRMrw; - Bit16u result,value; - if (rm >= 0xc0) { GetEArw; value=*earw; } - else { GetEAa; value=LoadMw(eaa); } - if (value==0) { - SETFLAGBIT(ZF,true); - } else { - result = 15; // Operandsize-1 - while ((value & 0x8000)==0) { result--; value<<=1; } - SETFLAGBIT(ZF,false); - *rmrw = result; - } - lflags.type=t_UNKNOWN; - break; - } - CASE_0F_W(0xbe) /* MOVSX Gw,Eb */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArb;*rmrw=*(Bit8s *)earb;} - else {GetEAa;*rmrw=LoadMbs(eaa);} - break; - } - CASE_0F_B(0xc0) /* XADD Gb,Eb */ - { - if (CPU_ArchitectureType= 0xc0 ) {GetEArb;*rmrb=*earb;*earb+=oldrmrb;} - else {GetEAa;*rmrb=LoadMb(eaa);SaveMb(eaa,LoadMb(eaa)+oldrmrb);} - break; - } - CASE_0F_W(0xc1) /* XADD Gw,Ew */ - { - if (CPU_ArchitectureType= 0xc0 ) {GetEArw;*rmrw=*earw;*earw+=oldrmrw;} - else {GetEAa;*rmrw=LoadMw(eaa);SaveMw(eaa,LoadMw(eaa)+oldrmrw);} - break; - } - CASE_0F_B(0xc8) /* BSWAP EAX */ - if (CPU_ArchitectureType bound_max) ) { - EXCEPTION(5); - } - } - break; - CASE_D(0x63) /* ARPL Ed,Rd */ - { - if (((cpu.pmode) && (reg_flags & FLAG_VM)) || (!cpu.pmode)) goto illegal_opcode; - GetRMrw; - if (rm >= 0xc0 ) { - GetEArd;Bitu new_sel=(Bit16u)*eard; - CPU_ARPL(new_sel,*rmrw); - *eard=(Bit32u)new_sel; - } else { - GetEAa;Bitu new_sel=LoadMw(eaa); - CPU_ARPL(new_sel,*rmrw); - SaveMd(eaa,(Bit32u)new_sel); - } - } - break; - CASE_D(0x68) /* PUSH Id */ - Push_32(Fetchd());break; - CASE_D(0x69) /* IMUL Gd,Ed,Id */ - RMGdEdOp3(DIMULD,Fetchds()); - break; - CASE_D(0x6a) /* PUSH Ib */ - Push_32(Fetchbs());break; - CASE_D(0x6b) /* IMUL Gd,Ed,Ib */ - RMGdEdOp3(DIMULD,Fetchbs()); - break; - CASE_D(0x6d) /* INSD */ - if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION(); - DoString(R_INSD);break; - CASE_D(0x6f) /* OUTSD */ - if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION(); - DoString(R_OUTSD);break; - CASE_D(0x70) /* JO */ - JumpCond32_b(TFLG_O);break; - CASE_D(0x71) /* JNO */ - JumpCond32_b(TFLG_NO);break; - CASE_D(0x72) /* JB */ - JumpCond32_b(TFLG_B);break; - CASE_D(0x73) /* JNB */ - JumpCond32_b(TFLG_NB);break; - CASE_D(0x74) /* JZ */ - JumpCond32_b(TFLG_Z);break; - CASE_D(0x75) /* JNZ */ - JumpCond32_b(TFLG_NZ);break; - CASE_D(0x76) /* JBE */ - JumpCond32_b(TFLG_BE);break; - CASE_D(0x77) /* JNBE */ - JumpCond32_b(TFLG_NBE);break; - CASE_D(0x78) /* JS */ - JumpCond32_b(TFLG_S);break; - CASE_D(0x79) /* JNS */ - JumpCond32_b(TFLG_NS);break; - CASE_D(0x7a) /* JP */ - JumpCond32_b(TFLG_P);break; - CASE_D(0x7b) /* JNP */ - JumpCond32_b(TFLG_NP);break; - CASE_D(0x7c) /* JL */ - JumpCond32_b(TFLG_L);break; - CASE_D(0x7d) /* JNL */ - JumpCond32_b(TFLG_NL);break; - CASE_D(0x7e) /* JLE */ - JumpCond32_b(TFLG_LE);break; - CASE_D(0x7f) /* JNLE */ - JumpCond32_b(TFLG_NLE);break; - CASE_D(0x81) /* Grpl Ed,Id */ - { - GetRM;Bitu which=(rm>>3)&7; - if (rm >= 0xc0) { - GetEArd;Bit32u id=Fetchd(); - switch (which) { - case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break; - case 0x01: ORD(*eard,id,LoadRd,SaveRd);break; - case 0x02:ADCD(*eard,id,LoadRd,SaveRd);break; - case 0x03:SBBD(*eard,id,LoadRd,SaveRd);break; - case 0x04:ANDD(*eard,id,LoadRd,SaveRd);break; - case 0x05:SUBD(*eard,id,LoadRd,SaveRd);break; - case 0x06:XORD(*eard,id,LoadRd,SaveRd);break; - case 0x07:CMPD(*eard,id,LoadRd,SaveRd);break; - } - } else { - GetEAa;Bit32u id=Fetchd(); - switch (which) { - case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; - case 0x01: ORD(eaa,id,LoadMd,SaveMd);break; - case 0x02:ADCD(eaa,id,LoadMd,SaveMd);break; - case 0x03:SBBD(eaa,id,LoadMd,SaveMd);break; - case 0x04:ANDD(eaa,id,LoadMd,SaveMd);break; - case 0x05:SUBD(eaa,id,LoadMd,SaveMd);break; - case 0x06:XORD(eaa,id,LoadMd,SaveMd);break; - case 0x07:CMPD(eaa,id,LoadMd,SaveMd);break; - } - } - } - break; - CASE_D(0x83) /* Grpl Ed,Ix */ - { - GetRM;Bitu which=(rm>>3)&7; - if (rm >= 0xc0) { - GetEArd;Bit32u id=(Bit32s)Fetchbs(); - switch (which) { - case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break; - case 0x01: ORD(*eard,id,LoadRd,SaveRd);break; - case 0x02:ADCD(*eard,id,LoadRd,SaveRd);break; - case 0x03:SBBD(*eard,id,LoadRd,SaveRd);break; - case 0x04:ANDD(*eard,id,LoadRd,SaveRd);break; - case 0x05:SUBD(*eard,id,LoadRd,SaveRd);break; - case 0x06:XORD(*eard,id,LoadRd,SaveRd);break; - case 0x07:CMPD(*eard,id,LoadRd,SaveRd);break; - } - } else { - GetEAa;Bit32u id=(Bit32s)Fetchbs(); - switch (which) { - case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; - case 0x01: ORD(eaa,id,LoadMd,SaveMd);break; - case 0x02:ADCD(eaa,id,LoadMd,SaveMd);break; - case 0x03:SBBD(eaa,id,LoadMd,SaveMd);break; - case 0x04:ANDD(eaa,id,LoadMd,SaveMd);break; - case 0x05:SUBD(eaa,id,LoadMd,SaveMd);break; - case 0x06:XORD(eaa,id,LoadMd,SaveMd);break; - case 0x07:CMPD(eaa,id,LoadMd,SaveMd);break; - } - } - } - break; - CASE_D(0x85) /* TEST Ed,Gd */ - RMEdGd(TESTD);break; - CASE_D(0x87) /* XCHG Ed,Gd */ - { - GetRMrd;Bit32u oldrmrd=*rmrd; - if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;*eard=oldrmrd;} - else {GetEAa;*rmrd=LoadMd(eaa);SaveMd(eaa,oldrmrd);} - break; - } - CASE_D(0x89) /* MOV Ed,Gd */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArd;*eard=*rmrd;} - else {GetEAa;SaveMd(eaa,*rmrd);} - break; - } - CASE_D(0x8b) /* MOV Gd,Ed */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;} - else {GetEAa;*rmrd=LoadMd(eaa);} - break; - } - CASE_D(0x8c) /* Mov Ew,Sw */ - { - GetRM;Bit16u val;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* MOV Ew,ES */ - val=SegValue(es);break; - case 0x01: /* MOV Ew,CS */ - val=SegValue(cs);break; - case 0x02: /* MOV Ew,SS */ - val=SegValue(ss);break; - case 0x03: /* MOV Ew,DS */ - val=SegValue(ds);break; - case 0x04: /* MOV Ew,FS */ - val=SegValue(fs);break; - case 0x05: /* MOV Ew,GS */ - val=SegValue(gs);break; - default: - LOG(LOG_CPU,LOG_ERROR)("CPU:8c:Illegal RM Byte"); - goto illegal_opcode; - } - if (rm >= 0xc0 ) {GetEArd;*eard=val;} - else {GetEAa;SaveMw(eaa,val);} - break; - } - CASE_D(0x8d) /* LEA Gd */ - { - //Little hack to always use segprefixed version - GetRMrd; - BaseDS=BaseSS=0; - if (TEST_PREFIX_ADDR) { - *rmrd=(Bit32u)(*EATable[256+rm])(); - } else { - *rmrd=(Bit32u)(*EATable[rm])(); - } - break; - } - CASE_D(0x8f) /* POP Ed */ - { - Bit32u val=Pop_32(); - GetRM; - if (rm >= 0xc0 ) {GetEArd;*eard=val;} - else {GetEAa;SaveMd(eaa,val);} - break; - } - CASE_D(0x91) /* XCHG ECX,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_ecx;reg_ecx=temp;break;} - CASE_D(0x92) /* XCHG EDX,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_edx;reg_edx=temp;break;} - break; - CASE_D(0x93) /* XCHG EBX,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_ebx;reg_ebx=temp;break;} - break; - CASE_D(0x94) /* XCHG ESP,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_esp;reg_esp=temp;break;} - break; - CASE_D(0x95) /* XCHG EBP,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_ebp;reg_ebp=temp;break;} - break; - CASE_D(0x96) /* XCHG ESI,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_esi;reg_esi=temp;break;} - break; - CASE_D(0x97) /* XCHG EDI,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_edi;reg_edi=temp;break;} - break; - CASE_D(0x98) /* CWDE */ - reg_eax=(Bit16s)reg_ax;break; - CASE_D(0x99) /* CDQ */ - if (reg_eax & 0x80000000) reg_edx=0xffffffff; - else reg_edx=0; - break; - CASE_D(0x9a) /* CALL FAR Ad */ - { - Bit32u newip=Fetchd();Bit16u newcs=Fetchw(); - FillFlags(); - CPU_CALL(true,newcs,newip,GETIP); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - return CBRET_NONE; - } -#endif - continue; - } - CASE_D(0x9c) /* PUSHFD */ - if (CPU_PUSHF(true)) RUNEXCEPTION(); - break; - CASE_D(0x9d) /* POPFD */ - if (CPU_POPF(true)) RUNEXCEPTION(); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - goto decode_end; - } -#endif -#if CPU_PIC_CHECK - if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; -#endif - break; - CASE_D(0xa1) /* MOV EAX,Od */ - { - GetEADirect; - reg_eax=LoadMd(eaa); - } - break; - CASE_D(0xa3) /* MOV Od,EAX */ - { - GetEADirect; - SaveMd(eaa,reg_eax); - } - break; - CASE_D(0xa5) /* MOVSD */ - DoString(R_MOVSD);break; - CASE_D(0xa7) /* CMPSD */ - DoString(R_CMPSD);break; - CASE_D(0xa9) /* TEST EAX,Id */ - EAXId(TESTD);break; - CASE_D(0xab) /* STOSD */ - DoString(R_STOSD);break; - CASE_D(0xad) /* LODSD */ - DoString(R_LODSD);break; - CASE_D(0xaf) /* SCASD */ - DoString(R_SCASD);break; - CASE_D(0xb8) /* MOV EAX,Id */ - reg_eax=Fetchd();break; - CASE_D(0xb9) /* MOV ECX,Id */ - reg_ecx=Fetchd();break; - CASE_D(0xba) /* MOV EDX,Iw */ - reg_edx=Fetchd();break; - CASE_D(0xbb) /* MOV EBX,Id */ - reg_ebx=Fetchd();break; - CASE_D(0xbc) /* MOV ESP,Id */ - reg_esp=Fetchd();break; - CASE_D(0xbd) /* MOV EBP.Id */ - reg_ebp=Fetchd();break; - CASE_D(0xbe) /* MOV ESI,Id */ - reg_esi=Fetchd();break; - CASE_D(0xbf) /* MOV EDI,Id */ - reg_edi=Fetchd();break; - CASE_D(0xc1) /* GRP2 Ed,Ib */ - GRP2D(Fetchb());break; - CASE_D(0xc2) /* RETN Iw */ - reg_eip=Pop_32(); - reg_esp+=Fetchw(); - continue; - CASE_D(0xc3) /* RETN */ - reg_eip=Pop_32(); - continue; - CASE_D(0xc4) /* LES */ - { - GetRMrd; - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - if (CPU_SetSegGeneral(es,LoadMw(eaa+4))) RUNEXCEPTION(); - *rmrd=LoadMd(eaa); - break; - } - CASE_D(0xc5) /* LDS */ - { - GetRMrd; - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - if (CPU_SetSegGeneral(ds,LoadMw(eaa+4))) RUNEXCEPTION(); - *rmrd=LoadMd(eaa); - break; - } - CASE_D(0xc7) /* MOV Ed,Id */ - { - GetRM; - if (rm >= 0xc0) {GetEArd;*eard=Fetchd();} - else {GetEAa;SaveMd(eaa,Fetchd());} - break; - } - CASE_D(0xc8) /* ENTER Iw,Ib */ - { - Bitu bytes=Fetchw(); - Bitu level=Fetchb(); - CPU_ENTER(true,bytes,level); - } - break; - CASE_D(0xc9) /* LEAVE */ - reg_esp&=cpu.stack.notmask; - reg_esp|=(reg_ebp&cpu.stack.mask); - reg_ebp=Pop_32(); - break; - CASE_D(0xca) /* RETF Iw */ - { - Bitu words=Fetchw(); - FillFlags(); - CPU_RET(true,words,GETIP); - continue; - } - CASE_D(0xcb) /* RETF */ - { - FillFlags(); - CPU_RET(true,0,GETIP); - continue; - } - CASE_D(0xcf) /* IRET */ - { - CPU_IRET(true,GETIP); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - return CBRET_NONE; - } -#endif -#if CPU_PIC_CHECK - if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; -#endif - continue; - } - CASE_D(0xd1) /* GRP2 Ed,1 */ - GRP2D(1);break; - CASE_D(0xd3) /* GRP2 Ed,CL */ - GRP2D(reg_cl);break; - CASE_D(0xe0) /* LOOPNZ */ - if (TEST_PREFIX_ADDR) { - JumpCond32_b(--reg_ecx && !get_ZF()); - } else { - JumpCond32_b(--reg_cx && !get_ZF()); - } - break; - CASE_D(0xe1) /* LOOPZ */ - if (TEST_PREFIX_ADDR) { - JumpCond32_b(--reg_ecx && get_ZF()); - } else { - JumpCond32_b(--reg_cx && get_ZF()); - } - break; - CASE_D(0xe2) /* LOOP */ - if (TEST_PREFIX_ADDR) { - JumpCond32_b(--reg_ecx); - } else { - JumpCond32_b(--reg_cx); - } - break; - CASE_D(0xe3) /* JCXZ */ - JumpCond32_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR])); - break; - CASE_D(0xe5) /* IN EAX,Ib */ - { - Bitu port=Fetchb(); - if (CPU_IO_Exception(port,4)) RUNEXCEPTION(); - reg_eax=IO_ReadD(port); - break; - } - CASE_D(0xe7) /* OUT Ib,EAX */ - { - Bitu port=Fetchb(); - if (CPU_IO_Exception(port,4)) RUNEXCEPTION(); - IO_WriteD(port,reg_eax); - break; - } - CASE_D(0xe8) /* CALL Jd */ - { - Bit32s addip=Fetchds(); - SAVEIP; - Push_32(reg_eip); - reg_eip+=addip; - continue; - } - CASE_D(0xe9) /* JMP Jd */ - { - Bit32s addip=Fetchds(); - SAVEIP; - reg_eip+=addip; - continue; - } - CASE_D(0xea) /* JMP Ad */ - { - Bit32u newip=Fetchd(); - Bit16u newcs=Fetchw(); - FillFlags(); - CPU_JMP(true,newcs,newip,GETIP); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - return CBRET_NONE; - } -#endif - continue; - } - CASE_D(0xeb) /* JMP Jb */ - { - Bit32s addip=Fetchbs(); - SAVEIP; - reg_eip+=addip; - continue; - } - CASE_D(0xed) /* IN EAX,DX */ - reg_eax=IO_ReadD(reg_dx); - break; - CASE_D(0xef) /* OUT DX,EAX */ - IO_WriteD(reg_dx,reg_eax); - break; - CASE_D(0xf7) /* GRP3 Ed(,Id) */ - { - GetRM;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* TEST Ed,Id */ - case 0x01: /* TEST Ed,Id Undocumented*/ - { - if (rm >= 0xc0 ) {GetEArd;TESTD(*eard,Fetchd(),LoadRd,SaveRd);} - else {GetEAa;TESTD(eaa,Fetchd(),LoadMd,SaveMd);} - break; - } - case 0x02: /* NOT Ed */ - { - if (rm >= 0xc0 ) {GetEArd;*eard=~*eard;} - else {GetEAa;SaveMd(eaa,~LoadMd(eaa));} - break; - } - case 0x03: /* NEG Ed */ - { - lflags.type=t_NEGd; - if (rm >= 0xc0 ) { - GetEArd;lf_var1d=*eard;lf_resd=0-lf_var1d; - *eard=lf_resd; - } else { - GetEAa;lf_var1d=LoadMd(eaa);lf_resd=0-lf_var1d; - SaveMd(eaa,lf_resd); - } - break; - } - case 0x04: /* MUL EAX,Ed */ - RMEd(MULD); - break; - case 0x05: /* IMUL EAX,Ed */ - RMEd(IMULD); - break; - case 0x06: /* DIV Ed */ - RMEd(DIVD); - break; - case 0x07: /* IDIV Ed */ - RMEd(IDIVD); - break; - } - break; - } - CASE_D(0xff) /* GRP 5 Ed */ - { - GetRM;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* INC Ed */ - RMEd(INCD); - break; - case 0x01: /* DEC Ed */ - RMEd(DECD); - break; - case 0x02: /* CALL NEAR Ed */ - if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;} - else {GetEAa;reg_eip=LoadMd(eaa);} - Push_32(GETIP); - continue; - case 0x03: /* CALL FAR Ed */ - { - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - Bit32u newip=LoadMd(eaa); - Bit16u newcs=LoadMw(eaa+4); - FillFlags(); - CPU_CALL(true,newcs,newip,GETIP); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - return CBRET_NONE; - } -#endif - continue; - } - case 0x04: /* JMP NEAR Ed */ - if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;} - else {GetEAa;reg_eip=LoadMd(eaa);} - continue; - case 0x05: /* JMP FAR Ed */ - { - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - Bit32u newip=LoadMd(eaa); - Bit16u newcs=LoadMw(eaa+4); - FillFlags(); - CPU_JMP(true,newcs,newip,GETIP); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - return CBRET_NONE; - } -#endif - continue; - } - break; - case 0x06: /* Push Ed */ - if (rm >= 0xc0 ) {GetEArd;Push_32(*eard);} - else {GetEAa;Push_32(LoadMd(eaa));} - break; - default: - E_Exit("CPU:66:GRP5:Illegal call %2X",which); - break; - } - break; - } - - diff --git a/src/cpu/core_normal/prefix_66_0f.h b/src/cpu/core_normal/prefix_66_0f.h deleted file mode 100644 index 7163f11..0000000 --- a/src/cpu/core_normal/prefix_66_0f.h +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - CASE_0F_D(0x00) /* GRP 6 Exxx */ - { - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - GetRM;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* SLDT */ - case 0x01: /* STR */ - { - Bitu saveval; - if (!which) saveval=CPU_SLDT(); - else saveval=CPU_STR(); - if (rm >= 0xc0) {GetEArw;*earw=(Bit16u)saveval;} - else {GetEAa;SaveMw(eaa,saveval);} - } - break; - case 0x02:case 0x03:case 0x04:case 0x05: - { - /* Just use 16-bit loads since were only using selectors */ - Bitu loadval; - if (rm >= 0xc0 ) {GetEArw;loadval=*earw;} - else {GetEAa;loadval=LoadMw(eaa);} - switch (which) { - case 0x02: - if (cpu.cpl) EXCEPTION(EXCEPTION_GP); - if (CPU_LLDT(loadval)) RUNEXCEPTION(); - break; - case 0x03: - if (cpu.cpl) EXCEPTION(EXCEPTION_GP); - if (CPU_LTR(loadval)) RUNEXCEPTION(); - break; - case 0x04: - CPU_VERR(loadval); - break; - case 0x05: - CPU_VERW(loadval); - break; - } - } - break; - default: - LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which); - goto illegal_opcode; - } - } - break; - CASE_0F_D(0x01) /* Group 7 Ed */ - { - GetRM;Bitu which=(rm>>3)&7; - if (rm < 0xc0) { //First ones all use EA - GetEAa;Bitu limit; - switch (which) { - case 0x00: /* SGDT */ - SaveMw(eaa,(Bit16u)CPU_SGDT_limit()); - SaveMd(eaa+2,(Bit32u)CPU_SGDT_base()); - break; - case 0x01: /* SIDT */ - SaveMw(eaa,(Bit16u)CPU_SIDT_limit()); - SaveMd(eaa+2,(Bit32u)CPU_SIDT_base()); - break; - case 0x02: /* LGDT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - CPU_LGDT(LoadMw(eaa),LoadMd(eaa+2)); - break; - case 0x03: /* LIDT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2)); - break; - case 0x04: /* SMSW */ - SaveMw(eaa,(Bit16u)CPU_SMSW()); - break; - case 0x06: /* LMSW */ - limit=LoadMw(eaa); - if (CPU_LMSW((Bit16u)limit)) RUNEXCEPTION(); - break; - case 0x07: /* INVLPG */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - PAGING_ClearTLB(); - break; - } - } else { - GetEArd; - switch (which) { - case 0x02: /* LGDT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - goto illegal_opcode; - case 0x03: /* LIDT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - goto illegal_opcode; - case 0x04: /* SMSW */ - *eard=(Bit32u)CPU_SMSW(); - break; - case 0x06: /* LMSW */ - if (CPU_LMSW(*eard)) RUNEXCEPTION(); - break; - default: - LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which); - goto illegal_opcode; - break; - } - - } - } - break; - CASE_0F_D(0x02) /* LAR Gd,Ed */ - { - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - GetRMrd;Bitu ar=*rmrd; - if (rm >= 0xc0) { - GetEArw;CPU_LAR(*earw,ar); - } else { - GetEAa;CPU_LAR(LoadMw(eaa),ar); - } - *rmrd=(Bit32u)ar; - } - break; - CASE_0F_D(0x03) /* LSL Gd,Ew */ - { - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - GetRMrd;Bitu limit=*rmrd; - /* Just load 16-bit values for selectors */ - if (rm >= 0xc0) { - GetEArw;CPU_LSL(*earw,limit); - } else { - GetEAa;CPU_LSL(LoadMw(eaa),limit); - } - *rmrd=(Bit32u)limit; - } - break; - CASE_0F_D(0x80) /* JO */ - JumpCond32_d(TFLG_O);break; - CASE_0F_D(0x81) /* JNO */ - JumpCond32_d(TFLG_NO);break; - CASE_0F_D(0x82) /* JB */ - JumpCond32_d(TFLG_B);break; - CASE_0F_D(0x83) /* JNB */ - JumpCond32_d(TFLG_NB);break; - CASE_0F_D(0x84) /* JZ */ - JumpCond32_d(TFLG_Z);break; - CASE_0F_D(0x85) /* JNZ */ - JumpCond32_d(TFLG_NZ);break; - CASE_0F_D(0x86) /* JBE */ - JumpCond32_d(TFLG_BE);break; - CASE_0F_D(0x87) /* JNBE */ - JumpCond32_d(TFLG_NBE);break; - CASE_0F_D(0x88) /* JS */ - JumpCond32_d(TFLG_S);break; - CASE_0F_D(0x89) /* JNS */ - JumpCond32_d(TFLG_NS);break; - CASE_0F_D(0x8a) /* JP */ - JumpCond32_d(TFLG_P);break; - CASE_0F_D(0x8b) /* JNP */ - JumpCond32_d(TFLG_NP);break; - CASE_0F_D(0x8c) /* JL */ - JumpCond32_d(TFLG_L);break; - CASE_0F_D(0x8d) /* JNL */ - JumpCond32_d(TFLG_NL);break; - CASE_0F_D(0x8e) /* JLE */ - JumpCond32_d(TFLG_LE);break; - CASE_0F_D(0x8f) /* JNLE */ - JumpCond32_d(TFLG_NLE);break; - - CASE_0F_D(0xa0) /* PUSH FS */ - Push_32(SegValue(fs));break; - CASE_0F_D(0xa1) /* POP FS */ - if (CPU_PopSeg(fs,true)) RUNEXCEPTION(); - break; - CASE_0F_D(0xa3) /* BT Ed,Gd */ - { - FillFlags();GetRMrd; - Bit32u mask=1 << (*rmrd & 31); - if (rm >= 0xc0 ) { - GetEArd; - SETFLAGBIT(CF,(*eard & mask)); - } else { - GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; - Bit32u old=LoadMd(eaa); - SETFLAGBIT(CF,(old & mask)); - } - break; - } - CASE_0F_D(0xa4) /* SHLD Ed,Gd,Ib */ - RMEdGdOp3(DSHLD,Fetchb()); - break; - CASE_0F_D(0xa5) /* SHLD Ed,Gd,CL */ - RMEdGdOp3(DSHLD,reg_cl); - break; - CASE_0F_D(0xa8) /* PUSH GS */ - Push_32(SegValue(gs));break; - CASE_0F_D(0xa9) /* POP GS */ - if (CPU_PopSeg(gs,true)) RUNEXCEPTION(); - break; - CASE_0F_D(0xab) /* BTS Ed,Gd */ - { - FillFlags();GetRMrd; - Bit32u mask=1 << (*rmrd & 31); - if (rm >= 0xc0 ) { - GetEArd; - SETFLAGBIT(CF,(*eard & mask)); - *eard|=mask; - } else { - GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; - Bit32u old=LoadMd(eaa); - SETFLAGBIT(CF,(old & mask)); - SaveMd(eaa,old | mask); - } - break; - } - - CASE_0F_D(0xac) /* SHRD Ed,Gd,Ib */ - RMEdGdOp3(DSHRD,Fetchb()); - break; - CASE_0F_D(0xad) /* SHRD Ed,Gd,CL */ - RMEdGdOp3(DSHRD,reg_cl); - break; - CASE_0F_D(0xaf) /* IMUL Gd,Ed */ - { - RMGdEdOp3(DIMULD,*rmrd); - break; - } - CASE_0F_D(0xb1) /* CMPXCHG Ed,Gd */ - { - if (CPU_ArchitectureType= 0xc0) { - GetEArd; - if (*eard==reg_eax) { - *eard=*rmrd; - SETFLAGBIT(ZF,1); - } else { - reg_eax=*eard; - SETFLAGBIT(ZF,0); - } - } else { - GetEAa; - Bit32u val=LoadMd(eaa); - if (val==reg_eax) { - SaveMd(eaa,*rmrd); - SETFLAGBIT(ZF,1); - } else { - SaveMd(eaa,val); - reg_eax=val; - SETFLAGBIT(ZF,0); - } - } - break; - } - CASE_0F_D(0xb2) /* LSS Ed */ - { - GetRMrd; - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - if (CPU_SetSegGeneral(ss,LoadMw(eaa+4))) RUNEXCEPTION(); - *rmrd=LoadMd(eaa); - break; - } - CASE_0F_D(0xb3) /* BTR Ed,Gd */ - { - FillFlags();GetRMrd; - Bit32u mask=1 << (*rmrd & 31); - if (rm >= 0xc0 ) { - GetEArd; - SETFLAGBIT(CF,(*eard & mask)); - *eard&= ~mask; - } else { - GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; - Bit32u old=LoadMd(eaa); - SETFLAGBIT(CF,(old & mask)); - SaveMd(eaa,old & ~mask); - } - break; - } - CASE_0F_D(0xb4) /* LFS Ed */ - { - GetRMrd; - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - if (CPU_SetSegGeneral(fs,LoadMw(eaa+4))) RUNEXCEPTION(); - *rmrd=LoadMd(eaa); - break; - } - CASE_0F_D(0xb5) /* LGS Ed */ - { - GetRMrd; - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - if (CPU_SetSegGeneral(gs,LoadMw(eaa+4))) RUNEXCEPTION(); - *rmrd=LoadMd(eaa); - break; - } - CASE_0F_D(0xb6) /* MOVZX Gd,Eb */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArb;*rmrd=*earb;} - else {GetEAa;*rmrd=LoadMb(eaa);} - break; - } - CASE_0F_D(0xb7) /* MOVXZ Gd,Ew */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArw;*rmrd=*earw;} - else {GetEAa;*rmrd=LoadMw(eaa);} - break; - } - CASE_0F_D(0xba) /* GRP8 Ed,Ib */ - { - FillFlags();GetRM; - if (rm >= 0xc0 ) { - GetEArd; - Bit32u mask=1 << (Fetchb() & 31); - SETFLAGBIT(CF,(*eard & mask)); - switch (rm & 0x38) { - case 0x20: /* BT */ - break; - case 0x28: /* BTS */ - *eard|=mask; - break; - case 0x30: /* BTR */ - *eard&=~mask; - break; - case 0x38: /* BTC */ - if (GETFLAG(CF)) *eard&=~mask; - else *eard|=mask; - break; - default: - E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38); - } - } else { - GetEAa;Bit32u old=LoadMd(eaa); - Bit32u mask=1 << (Fetchb() & 31); - SETFLAGBIT(CF,(old & mask)); - switch (rm & 0x38) { - case 0x20: /* BT */ - break; - case 0x28: /* BTS */ - SaveMd(eaa,old|mask); - break; - case 0x30: /* BTR */ - SaveMd(eaa,old & ~mask); - break; - case 0x38: /* BTC */ - if (GETFLAG(CF)) old&=~mask; - else old|=mask; - SaveMd(eaa,old); - break; - default: - E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38); - } - } - break; - } - CASE_0F_D(0xbb) /* BTC Ed,Gd */ - { - FillFlags();GetRMrd; - Bit32u mask=1 << (*rmrd & 31); - if (rm >= 0xc0 ) { - GetEArd; - SETFLAGBIT(CF,(*eard & mask)); - *eard^=mask; - } else { - GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; - Bit32u old=LoadMd(eaa); - SETFLAGBIT(CF,(old & mask)); - SaveMd(eaa,old ^ mask); - } - break; - } - CASE_0F_D(0xbc) /* BSF Gd,Ed */ - { - GetRMrd; - Bit32u result,value; - if (rm >= 0xc0) { GetEArd; value=*eard; } - else { GetEAa; value=LoadMd(eaa); } - if (value==0) { - SETFLAGBIT(ZF,true); - } else { - result = 0; - while ((value & 0x01)==0) { result++; value>>=1; } - SETFLAGBIT(ZF,false); - *rmrd = result; - } - lflags.type=t_UNKNOWN; - break; - } - CASE_0F_D(0xbd) /* BSR Gd,Ed */ - { - GetRMrd; - Bit32u result,value; - if (rm >= 0xc0) { GetEArd; value=*eard; } - else { GetEAa; value=LoadMd(eaa); } - if (value==0) { - SETFLAGBIT(ZF,true); - } else { - result = 31; // Operandsize-1 - while ((value & 0x80000000)==0) { result--; value<<=1; } - SETFLAGBIT(ZF,false); - *rmrd = result; - } - lflags.type=t_UNKNOWN; - break; - } - CASE_0F_D(0xbe) /* MOVSX Gd,Eb */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArb;*rmrd=*(Bit8s *)earb;} - else {GetEAa;*rmrd=LoadMbs(eaa);} - break; - } - CASE_0F_D(0xbf) /* MOVSX Gd,Ew */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArw;*rmrd=*(Bit16s *)earw;} - else {GetEAa;*rmrd=LoadMws(eaa);} - break; - } - CASE_0F_D(0xc1) /* XADD Gd,Ed */ - { - if (CPU_ArchitectureType= 0xc0 ) {GetEArd;*rmrd=*eard;*eard+=oldrmrd;} - else {GetEAa;*rmrd=LoadMd(eaa);SaveMd(eaa,LoadMd(eaa)+oldrmrd);} - break; - } diff --git a/src/cpu/core_normal/prefix_none.h b/src/cpu/core_normal/prefix_none.h deleted file mode 100644 index 84bcc4a..0000000 --- a/src/cpu/core_normal/prefix_none.h +++ /dev/null @@ -1,1176 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - CASE_B(0x00) /* ADD Eb,Gb */ - RMEbGb(ADDB);break; - CASE_W(0x01) /* ADD Ew,Gw */ - RMEwGw(ADDW);break; - CASE_B(0x02) /* ADD Gb,Eb */ - RMGbEb(ADDB);break; - CASE_W(0x03) /* ADD Gw,Ew */ - RMGwEw(ADDW);break; - CASE_B(0x04) /* ADD AL,Ib */ - ALIb(ADDB);break; - CASE_W(0x05) /* ADD AX,Iw */ - AXIw(ADDW);break; - CASE_W(0x06) /* PUSH ES */ - Push_16(SegValue(es));break; - CASE_W(0x07) /* POP ES */ - if (CPU_PopSeg(es,false)) RUNEXCEPTION(); - break; - CASE_B(0x08) /* OR Eb,Gb */ - RMEbGb(ORB);break; - CASE_W(0x09) /* OR Ew,Gw */ - RMEwGw(ORW);break; - CASE_B(0x0a) /* OR Gb,Eb */ - RMGbEb(ORB);break; - CASE_W(0x0b) /* OR Gw,Ew */ - RMGwEw(ORW);break; - CASE_B(0x0c) /* OR AL,Ib */ - ALIb(ORB);break; - CASE_W(0x0d) /* OR AX,Iw */ - AXIw(ORW);break; - CASE_W(0x0e) /* PUSH CS */ - Push_16(SegValue(cs));break; - CASE_B(0x0f) /* 2 byte opcodes*/ - core.opcode_index|=OPCODE_0F; - goto restart_opcode; - break; - CASE_B(0x10) /* ADC Eb,Gb */ - RMEbGb(ADCB);break; - CASE_W(0x11) /* ADC Ew,Gw */ - RMEwGw(ADCW);break; - CASE_B(0x12) /* ADC Gb,Eb */ - RMGbEb(ADCB);break; - CASE_W(0x13) /* ADC Gw,Ew */ - RMGwEw(ADCW);break; - CASE_B(0x14) /* ADC AL,Ib */ - ALIb(ADCB);break; - CASE_W(0x15) /* ADC AX,Iw */ - AXIw(ADCW);break; - CASE_W(0x16) /* PUSH SS */ - Push_16(SegValue(ss));break; - CASE_W(0x17) /* POP SS */ - if (CPU_PopSeg(ss,false)) RUNEXCEPTION(); - CPU_Cycles++; //Always do another instruction - break; - CASE_B(0x18) /* SBB Eb,Gb */ - RMEbGb(SBBB);break; - CASE_W(0x19) /* SBB Ew,Gw */ - RMEwGw(SBBW);break; - CASE_B(0x1a) /* SBB Gb,Eb */ - RMGbEb(SBBB);break; - CASE_W(0x1b) /* SBB Gw,Ew */ - RMGwEw(SBBW);break; - CASE_B(0x1c) /* SBB AL,Ib */ - ALIb(SBBB);break; - CASE_W(0x1d) /* SBB AX,Iw */ - AXIw(SBBW);break; - CASE_W(0x1e) /* PUSH DS */ - Push_16(SegValue(ds));break; - CASE_W(0x1f) /* POP DS */ - if (CPU_PopSeg(ds,false)) RUNEXCEPTION(); - break; - CASE_B(0x20) /* AND Eb,Gb */ - RMEbGb(ANDB);break; - CASE_W(0x21) /* AND Ew,Gw */ - RMEwGw(ANDW);break; - CASE_B(0x22) /* AND Gb,Eb */ - RMGbEb(ANDB);break; - CASE_W(0x23) /* AND Gw,Ew */ - RMGwEw(ANDW);break; - CASE_B(0x24) /* AND AL,Ib */ - ALIb(ANDB);break; - CASE_W(0x25) /* AND AX,Iw */ - AXIw(ANDW);break; - CASE_B(0x26) /* SEG ES: */ - DO_PREFIX_SEG(es);break; - CASE_B(0x27) /* DAA */ - DAA();break; - CASE_B(0x28) /* SUB Eb,Gb */ - RMEbGb(SUBB);break; - CASE_W(0x29) /* SUB Ew,Gw */ - RMEwGw(SUBW);break; - CASE_B(0x2a) /* SUB Gb,Eb */ - RMGbEb(SUBB);break; - CASE_W(0x2b) /* SUB Gw,Ew */ - RMGwEw(SUBW);break; - CASE_B(0x2c) /* SUB AL,Ib */ - ALIb(SUBB);break; - CASE_W(0x2d) /* SUB AX,Iw */ - AXIw(SUBW);break; - CASE_B(0x2e) /* SEG CS: */ - DO_PREFIX_SEG(cs);break; - CASE_B(0x2f) /* DAS */ - DAS();break; - CASE_B(0x30) /* XOR Eb,Gb */ - RMEbGb(XORB);break; - CASE_W(0x31) /* XOR Ew,Gw */ - RMEwGw(XORW);break; - CASE_B(0x32) /* XOR Gb,Eb */ - RMGbEb(XORB);break; - CASE_W(0x33) /* XOR Gw,Ew */ - RMGwEw(XORW);break; - CASE_B(0x34) /* XOR AL,Ib */ - ALIb(XORB);break; - CASE_W(0x35) /* XOR AX,Iw */ - AXIw(XORW);break; - CASE_B(0x36) /* SEG SS: */ - DO_PREFIX_SEG(ss);break; - CASE_B(0x37) /* AAA */ - AAA();break; - CASE_B(0x38) /* CMP Eb,Gb */ - RMEbGb(CMPB);break; - CASE_W(0x39) /* CMP Ew,Gw */ - RMEwGw(CMPW);break; - CASE_B(0x3a) /* CMP Gb,Eb */ - RMGbEb(CMPB);break; - CASE_W(0x3b) /* CMP Gw,Ew */ - RMGwEw(CMPW);break; - CASE_B(0x3c) /* CMP AL,Ib */ - ALIb(CMPB);break; - CASE_W(0x3d) /* CMP AX,Iw */ - AXIw(CMPW);break; - CASE_B(0x3e) /* SEG DS: */ - DO_PREFIX_SEG(ds);break; - CASE_B(0x3f) /* AAS */ - AAS();break; - CASE_W(0x40) /* INC AX */ - INCW(reg_ax,LoadRw,SaveRw);break; - CASE_W(0x41) /* INC CX */ - INCW(reg_cx,LoadRw,SaveRw);break; - CASE_W(0x42) /* INC DX */ - INCW(reg_dx,LoadRw,SaveRw);break; - CASE_W(0x43) /* INC BX */ - INCW(reg_bx,LoadRw,SaveRw);break; - CASE_W(0x44) /* INC SP */ - INCW(reg_sp,LoadRw,SaveRw);break; - CASE_W(0x45) /* INC BP */ - INCW(reg_bp,LoadRw,SaveRw);break; - CASE_W(0x46) /* INC SI */ - INCW(reg_si,LoadRw,SaveRw);break; - CASE_W(0x47) /* INC DI */ - INCW(reg_di,LoadRw,SaveRw);break; - CASE_W(0x48) /* DEC AX */ - DECW(reg_ax,LoadRw,SaveRw);break; - CASE_W(0x49) /* DEC CX */ - DECW(reg_cx,LoadRw,SaveRw);break; - CASE_W(0x4a) /* DEC DX */ - DECW(reg_dx,LoadRw,SaveRw);break; - CASE_W(0x4b) /* DEC BX */ - DECW(reg_bx,LoadRw,SaveRw);break; - CASE_W(0x4c) /* DEC SP */ - DECW(reg_sp,LoadRw,SaveRw);break; - CASE_W(0x4d) /* DEC BP */ - DECW(reg_bp,LoadRw,SaveRw);break; - CASE_W(0x4e) /* DEC SI */ - DECW(reg_si,LoadRw,SaveRw);break; - CASE_W(0x4f) /* DEC DI */ - DECW(reg_di,LoadRw,SaveRw);break; - CASE_W(0x50) /* PUSH AX */ - Push_16(reg_ax);break; - CASE_W(0x51) /* PUSH CX */ - Push_16(reg_cx);break; - CASE_W(0x52) /* PUSH DX */ - Push_16(reg_dx);break; - CASE_W(0x53) /* PUSH BX */ - Push_16(reg_bx);break; - CASE_W(0x54) /* PUSH SP */ - Push_16(reg_sp);break; - CASE_W(0x55) /* PUSH BP */ - Push_16(reg_bp);break; - CASE_W(0x56) /* PUSH SI */ - Push_16(reg_si);break; - CASE_W(0x57) /* PUSH DI */ - Push_16(reg_di);break; - CASE_W(0x58) /* POP AX */ - reg_ax=Pop_16();break; - CASE_W(0x59) /* POP CX */ - reg_cx=Pop_16();break; - CASE_W(0x5a) /* POP DX */ - reg_dx=Pop_16();break; - CASE_W(0x5b) /* POP BX */ - reg_bx=Pop_16();break; - CASE_W(0x5c) /* POP SP */ - reg_sp=Pop_16();break; - CASE_W(0x5d) /* POP BP */ - reg_bp=Pop_16();break; - CASE_W(0x5e) /* POP SI */ - reg_si=Pop_16();break; - CASE_W(0x5f) /* POP DI */ - reg_di=Pop_16();break; - CASE_W(0x60) /* PUSHA */ - { - Bit16u old_sp=reg_sp; - Push_16(reg_ax);Push_16(reg_cx);Push_16(reg_dx);Push_16(reg_bx); - Push_16(old_sp);Push_16(reg_bp);Push_16(reg_si);Push_16(reg_di); - } - break; - CASE_W(0x61) /* POPA */ - reg_di=Pop_16();reg_si=Pop_16();reg_bp=Pop_16();Pop_16();//Don't save SP - reg_bx=Pop_16();reg_dx=Pop_16();reg_cx=Pop_16();reg_ax=Pop_16(); - break; - CASE_W(0x62) /* BOUND */ - { - Bit16s bound_min, bound_max; - GetRMrw;GetEAa; - bound_min=LoadMw(eaa); - bound_max=LoadMw(eaa+2); - if ( (((Bit16s)*rmrw) < bound_min) || (((Bit16s)*rmrw) > bound_max) ) { - EXCEPTION(5); - } - } - break; - CASE_W(0x63) /* ARPL Ew,Rw */ - { - if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - GetRMrw; - if (rm >= 0xc0 ) { - GetEArw;Bitu new_sel=*earw; - CPU_ARPL(new_sel,*rmrw); - *earw=(Bit16u)new_sel; - } else { - GetEAa;Bitu new_sel=LoadMw(eaa); - CPU_ARPL(new_sel,*rmrw); - SaveMw(eaa,(Bit16u)new_sel); - } - } - break; - CASE_B(0x64) /* SEG FS: */ - DO_PREFIX_SEG(fs);break; - CASE_B(0x65) /* SEG GS: */ - DO_PREFIX_SEG(gs);break; - CASE_B(0x66) /* Operand Size Prefix */ - core.opcode_index=(cpu.code.big^0x1)*0x200; - goto restart_opcode; - CASE_B(0x67) /* Address Size Prefix */ - DO_PREFIX_ADDR(); - CASE_W(0x68) /* PUSH Iw */ - Push_16(Fetchw());break; - CASE_W(0x69) /* IMUL Gw,Ew,Iw */ - RMGwEwOp3(DIMULW,Fetchws()); - break; - CASE_W(0x6a) /* PUSH Ib */ - Push_16(Fetchbs()); - break; - CASE_W(0x6b) /* IMUL Gw,Ew,Ib */ - RMGwEwOp3(DIMULW,Fetchbs()); - break; - CASE_B(0x6c) /* INSB */ - if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION(); - DoString(R_INSB);break; - CASE_W(0x6d) /* INSW */ - if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION(); - DoString(R_INSW);break; - CASE_B(0x6e) /* OUTSB */ - if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION(); - DoString(R_OUTSB);break; - CASE_W(0x6f) /* OUTSW */ - if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION(); - DoString(R_OUTSW);break; - CASE_W(0x70) /* JO */ - JumpCond16_b(TFLG_O);break; - CASE_W(0x71) /* JNO */ - JumpCond16_b(TFLG_NO);break; - CASE_W(0x72) /* JB */ - JumpCond16_b(TFLG_B);break; - CASE_W(0x73) /* JNB */ - JumpCond16_b(TFLG_NB);break; - CASE_W(0x74) /* JZ */ - JumpCond16_b(TFLG_Z);break; - CASE_W(0x75) /* JNZ */ - JumpCond16_b(TFLG_NZ);break; - CASE_W(0x76) /* JBE */ - JumpCond16_b(TFLG_BE);break; - CASE_W(0x77) /* JNBE */ - JumpCond16_b(TFLG_NBE);break; - CASE_W(0x78) /* JS */ - JumpCond16_b(TFLG_S);break; - CASE_W(0x79) /* JNS */ - JumpCond16_b(TFLG_NS);break; - CASE_W(0x7a) /* JP */ - JumpCond16_b(TFLG_P);break; - CASE_W(0x7b) /* JNP */ - JumpCond16_b(TFLG_NP);break; - CASE_W(0x7c) /* JL */ - JumpCond16_b(TFLG_L);break; - CASE_W(0x7d) /* JNL */ - JumpCond16_b(TFLG_NL);break; - CASE_W(0x7e) /* JLE */ - JumpCond16_b(TFLG_LE);break; - CASE_W(0x7f) /* JNLE */ - JumpCond16_b(TFLG_NLE);break; - CASE_B(0x80) /* Grpl Eb,Ib */ - CASE_B(0x82) /* Grpl Eb,Ib Mirror instruction*/ - { - GetRM;Bitu which=(rm>>3)&7; - if (rm>= 0xc0) { - GetEArb;Bit8u ib=Fetchb(); - switch (which) { - case 0x00:ADDB(*earb,ib,LoadRb,SaveRb);break; - case 0x01: ORB(*earb,ib,LoadRb,SaveRb);break; - case 0x02:ADCB(*earb,ib,LoadRb,SaveRb);break; - case 0x03:SBBB(*earb,ib,LoadRb,SaveRb);break; - case 0x04:ANDB(*earb,ib,LoadRb,SaveRb);break; - case 0x05:SUBB(*earb,ib,LoadRb,SaveRb);break; - case 0x06:XORB(*earb,ib,LoadRb,SaveRb);break; - case 0x07:CMPB(*earb,ib,LoadRb,SaveRb);break; - } - } else { - GetEAa;Bit8u ib=Fetchb(); - switch (which) { - case 0x00:ADDB(eaa,ib,LoadMb,SaveMb);break; - case 0x01: ORB(eaa,ib,LoadMb,SaveMb);break; - case 0x02:ADCB(eaa,ib,LoadMb,SaveMb);break; - case 0x03:SBBB(eaa,ib,LoadMb,SaveMb);break; - case 0x04:ANDB(eaa,ib,LoadMb,SaveMb);break; - case 0x05:SUBB(eaa,ib,LoadMb,SaveMb);break; - case 0x06:XORB(eaa,ib,LoadMb,SaveMb);break; - case 0x07:CMPB(eaa,ib,LoadMb,SaveMb);break; - } - } - break; - } - CASE_W(0x81) /* Grpl Ew,Iw */ - { - GetRM;Bitu which=(rm>>3)&7; - if (rm>= 0xc0) { - GetEArw;Bit16u iw=Fetchw(); - switch (which) { - case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break; - case 0x01: ORW(*earw,iw,LoadRw,SaveRw);break; - case 0x02:ADCW(*earw,iw,LoadRw,SaveRw);break; - case 0x03:SBBW(*earw,iw,LoadRw,SaveRw);break; - case 0x04:ANDW(*earw,iw,LoadRw,SaveRw);break; - case 0x05:SUBW(*earw,iw,LoadRw,SaveRw);break; - case 0x06:XORW(*earw,iw,LoadRw,SaveRw);break; - case 0x07:CMPW(*earw,iw,LoadRw,SaveRw);break; - } - } else { - GetEAa;Bit16u iw=Fetchw(); - switch (which) { - case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break; - case 0x01: ORW(eaa,iw,LoadMw,SaveMw);break; - case 0x02:ADCW(eaa,iw,LoadMw,SaveMw);break; - case 0x03:SBBW(eaa,iw,LoadMw,SaveMw);break; - case 0x04:ANDW(eaa,iw,LoadMw,SaveMw);break; - case 0x05:SUBW(eaa,iw,LoadMw,SaveMw);break; - case 0x06:XORW(eaa,iw,LoadMw,SaveMw);break; - case 0x07:CMPW(eaa,iw,LoadMw,SaveMw);break; - } - } - break; - } - CASE_W(0x83) /* Grpl Ew,Ix */ - { - GetRM;Bitu which=(rm>>3)&7; - if (rm>= 0xc0) { - GetEArw;Bit16u iw=(Bit16s)Fetchbs(); - switch (which) { - case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break; - case 0x01: ORW(*earw,iw,LoadRw,SaveRw);break; - case 0x02:ADCW(*earw,iw,LoadRw,SaveRw);break; - case 0x03:SBBW(*earw,iw,LoadRw,SaveRw);break; - case 0x04:ANDW(*earw,iw,LoadRw,SaveRw);break; - case 0x05:SUBW(*earw,iw,LoadRw,SaveRw);break; - case 0x06:XORW(*earw,iw,LoadRw,SaveRw);break; - case 0x07:CMPW(*earw,iw,LoadRw,SaveRw);break; - } - } else { - GetEAa;Bit16u iw=(Bit16s)Fetchbs(); - switch (which) { - case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break; - case 0x01: ORW(eaa,iw,LoadMw,SaveMw);break; - case 0x02:ADCW(eaa,iw,LoadMw,SaveMw);break; - case 0x03:SBBW(eaa,iw,LoadMw,SaveMw);break; - case 0x04:ANDW(eaa,iw,LoadMw,SaveMw);break; - case 0x05:SUBW(eaa,iw,LoadMw,SaveMw);break; - case 0x06:XORW(eaa,iw,LoadMw,SaveMw);break; - case 0x07:CMPW(eaa,iw,LoadMw,SaveMw);break; - } - } - break; - } - CASE_B(0x84) /* TEST Eb,Gb */ - RMEbGb(TESTB); - break; - CASE_W(0x85) /* TEST Ew,Gw */ - RMEwGw(TESTW); - break; - CASE_B(0x86) /* XCHG Eb,Gb */ - { - GetRMrb;Bit8u oldrmrb=*rmrb; - if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;*earb=oldrmrb;} - else {GetEAa;*rmrb=LoadMb(eaa);SaveMb(eaa,oldrmrb);} - break; - } - CASE_W(0x87) /* XCHG Ew,Gw */ - { - GetRMrw;Bit16u oldrmrw=*rmrw; - if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;*earw=oldrmrw;} - else {GetEAa;*rmrw=LoadMw(eaa);SaveMw(eaa,oldrmrw);} - break; - } - CASE_B(0x88) /* MOV Eb,Gb */ - { - GetRMrb; - if (rm >= 0xc0 ) {GetEArb;*earb=*rmrb;} - else { - if (cpu.pmode) { - if (GCC_UNLIKELY((rm==0x05) && (!cpu.code.big))) { - Descriptor desc; - cpu.gdt.GetDescriptor(SegValue(core.base_val_ds),desc); - if ((desc.Type()==DESC_CODE_R_NC_A) || (desc.Type()==DESC_CODE_R_NC_NA)) { - CPU_Exception(EXCEPTION_GP,SegValue(core.base_val_ds) & 0xfffc); - continue; - } - } - } - GetEAa;SaveMb(eaa,*rmrb); - } - break; - } - CASE_W(0x89) /* MOV Ew,Gw */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArw;*earw=*rmrw;} - else {GetEAa;SaveMw(eaa,*rmrw);} - break; - } - CASE_B(0x8a) /* MOV Gb,Eb */ - { - GetRMrb; - if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;} - else {GetEAa;*rmrb=LoadMb(eaa);} - break; - } - CASE_W(0x8b) /* MOV Gw,Ew */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;} - else {GetEAa;*rmrw=LoadMw(eaa);} - break; - } - CASE_W(0x8c) /* Mov Ew,Sw */ - { - GetRM;Bit16u val;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* MOV Ew,ES */ - val=SegValue(es);break; - case 0x01: /* MOV Ew,CS */ - val=SegValue(cs);break; - case 0x02: /* MOV Ew,SS */ - val=SegValue(ss);break; - case 0x03: /* MOV Ew,DS */ - val=SegValue(ds);break; - case 0x04: /* MOV Ew,FS */ - val=SegValue(fs);break; - case 0x05: /* MOV Ew,GS */ - val=SegValue(gs);break; - default: - LOG(LOG_CPU,LOG_ERROR)("CPU:8c:Illegal RM Byte"); - goto illegal_opcode; - } - if (rm >= 0xc0 ) {GetEArw;*earw=val;} - else {GetEAa;SaveMw(eaa,val);} - break; - } - CASE_W(0x8d) /* LEA Gw */ - { - //Little hack to always use segprefixed version - BaseDS=BaseSS=0; - GetRMrw; - if (TEST_PREFIX_ADDR) { - *rmrw=(Bit16u)(*EATable[256+rm])(); - } else { - *rmrw=(Bit16u)(*EATable[rm])(); - } - break; - } - CASE_B(0x8e) /* MOV Sw,Ew */ - { - GetRM;Bit16u val;Bitu which=(rm>>3)&7; - if (rm >= 0xc0 ) {GetEArw;val=*earw;} - else {GetEAa;val=LoadMw(eaa);} - switch (which) { - case 0x02: /* MOV SS,Ew */ - CPU_Cycles++; //Always do another instruction - case 0x00: /* MOV ES,Ew */ - case 0x03: /* MOV DS,Ew */ - case 0x05: /* MOV GS,Ew */ - case 0x04: /* MOV FS,Ew */ - if (CPU_SetSegGeneral((SegNames)which,val)) RUNEXCEPTION(); - break; - default: - goto illegal_opcode; - } - break; - } - CASE_W(0x8f) /* POP Ew */ - { - Bit16u val=Pop_16(); - GetRM; - if (rm >= 0xc0 ) {GetEArw;*earw=val;} - else {GetEAa;SaveMw(eaa,val);} - break; - } - CASE_B(0x90) /* NOP */ - break; - CASE_W(0x91) /* XCHG CX,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_cx;reg_cx=temp; } - break; - CASE_W(0x92) /* XCHG DX,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_dx;reg_dx=temp; } - break; - CASE_W(0x93) /* XCHG BX,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_bx;reg_bx=temp; } - break; - CASE_W(0x94) /* XCHG SP,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_sp;reg_sp=temp; } - break; - CASE_W(0x95) /* XCHG BP,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_bp;reg_bp=temp; } - break; - CASE_W(0x96) /* XCHG SI,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_si;reg_si=temp; } - break; - CASE_W(0x97) /* XCHG DI,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_di;reg_di=temp; } - break; - CASE_W(0x98) /* CBW */ - reg_ax=(Bit8s)reg_al;break; - CASE_W(0x99) /* CWD */ - if (reg_ax & 0x8000) reg_dx=0xffff;else reg_dx=0; - break; - CASE_W(0x9a) /* CALL Ap */ - { - FillFlags(); - Bit16u newip=Fetchw();Bit16u newcs=Fetchw(); - CPU_CALL(false,newcs,newip,GETIP); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - return CBRET_NONE; - } -#endif - continue; - } - CASE_B(0x9b) /* WAIT */ - break; /* No waiting here */ - CASE_W(0x9c) /* PUSHF */ - if (CPU_PUSHF(false)) RUNEXCEPTION(); - break; - CASE_W(0x9d) /* POPF */ - if (CPU_POPF(false)) RUNEXCEPTION(); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - goto decode_end; - } -#endif -#if CPU_PIC_CHECK - if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; -#endif - break; - CASE_B(0x9e) /* SAHF */ - SETFLAGSb(reg_ah); - break; - CASE_B(0x9f) /* LAHF */ - FillFlags(); - reg_ah=reg_flags&0xff; - break; - CASE_B(0xa0) /* MOV AL,Ob */ - { - GetEADirect; - reg_al=LoadMb(eaa); - } - break; - CASE_W(0xa1) /* MOV AX,Ow */ - { - GetEADirect; - reg_ax=LoadMw(eaa); - } - break; - CASE_B(0xa2) /* MOV Ob,AL */ - { - GetEADirect; - SaveMb(eaa,reg_al); - } - break; - CASE_W(0xa3) /* MOV Ow,AX */ - { - GetEADirect; - SaveMw(eaa,reg_ax); - } - break; - CASE_B(0xa4) /* MOVSB */ - DoString(R_MOVSB);break; - CASE_W(0xa5) /* MOVSW */ - DoString(R_MOVSW);break; - CASE_B(0xa6) /* CMPSB */ - DoString(R_CMPSB);break; - CASE_W(0xa7) /* CMPSW */ - DoString(R_CMPSW);break; - CASE_B(0xa8) /* TEST AL,Ib */ - ALIb(TESTB);break; - CASE_W(0xa9) /* TEST AX,Iw */ - AXIw(TESTW);break; - CASE_B(0xaa) /* STOSB */ - DoString(R_STOSB);break; - CASE_W(0xab) /* STOSW */ - DoString(R_STOSW);break; - CASE_B(0xac) /* LODSB */ - DoString(R_LODSB);break; - CASE_W(0xad) /* LODSW */ - DoString(R_LODSW);break; - CASE_B(0xae) /* SCASB */ - DoString(R_SCASB);break; - CASE_W(0xaf) /* SCASW */ - DoString(R_SCASW);break; - CASE_B(0xb0) /* MOV AL,Ib */ - reg_al=Fetchb();break; - CASE_B(0xb1) /* MOV CL,Ib */ - reg_cl=Fetchb();break; - CASE_B(0xb2) /* MOV DL,Ib */ - reg_dl=Fetchb();break; - CASE_B(0xb3) /* MOV BL,Ib */ - reg_bl=Fetchb();break; - CASE_B(0xb4) /* MOV AH,Ib */ - reg_ah=Fetchb();break; - CASE_B(0xb5) /* MOV CH,Ib */ - reg_ch=Fetchb();break; - CASE_B(0xb6) /* MOV DH,Ib */ - reg_dh=Fetchb();break; - CASE_B(0xb7) /* MOV BH,Ib */ - reg_bh=Fetchb();break; - CASE_W(0xb8) /* MOV AX,Iw */ - reg_ax=Fetchw();break; - CASE_W(0xb9) /* MOV CX,Iw */ - reg_cx=Fetchw();break; - CASE_W(0xba) /* MOV DX,Iw */ - reg_dx=Fetchw();break; - CASE_W(0xbb) /* MOV BX,Iw */ - reg_bx=Fetchw();break; - CASE_W(0xbc) /* MOV SP,Iw */ - reg_sp=Fetchw();break; - CASE_W(0xbd) /* MOV BP.Iw */ - reg_bp=Fetchw();break; - CASE_W(0xbe) /* MOV SI,Iw */ - reg_si=Fetchw();break; - CASE_W(0xbf) /* MOV DI,Iw */ - reg_di=Fetchw();break; - CASE_B(0xc0) /* GRP2 Eb,Ib */ - GRP2B(Fetchb());break; - CASE_W(0xc1) /* GRP2 Ew,Ib */ - GRP2W(Fetchb());break; - CASE_W(0xc2) /* RETN Iw */ - reg_eip=Pop_16(); - reg_esp+=Fetchw(); - continue; - CASE_W(0xc3) /* RETN */ - reg_eip=Pop_16(); - continue; - CASE_W(0xc4) /* LES */ - { - GetRMrw; - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - if (CPU_SetSegGeneral(es,LoadMw(eaa+2))) RUNEXCEPTION(); - *rmrw=LoadMw(eaa); - break; - } - CASE_W(0xc5) /* LDS */ - { - GetRMrw; - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - if (CPU_SetSegGeneral(ds,LoadMw(eaa+2))) RUNEXCEPTION(); - *rmrw=LoadMw(eaa); - break; - } - CASE_B(0xc6) /* MOV Eb,Ib */ - { - GetRM; - if (rm >= 0xc0) {GetEArb;*earb=Fetchb();} - else {GetEAa;SaveMb(eaa,Fetchb());} - break; - } - CASE_W(0xc7) /* MOV EW,Iw */ - { - GetRM; - if (rm >= 0xc0) {GetEArw;*earw=Fetchw();} - else {GetEAa;SaveMw(eaa,Fetchw());} - break; - } - CASE_W(0xc8) /* ENTER Iw,Ib */ - { - Bitu bytes=Fetchw(); - Bitu level=Fetchb(); - CPU_ENTER(false,bytes,level); - } - break; - CASE_W(0xc9) /* LEAVE */ - reg_esp&=cpu.stack.notmask; - reg_esp|=(reg_ebp&cpu.stack.mask); - reg_bp=Pop_16(); - break; - CASE_W(0xca) /* RETF Iw */ - { - Bitu words=Fetchw(); - FillFlags(); - CPU_RET(false,words,GETIP); - continue; - } - CASE_W(0xcb) /* RETF */ - FillFlags(); - CPU_RET(false,0,GETIP); - continue; - CASE_B(0xcc) /* INT3 */ -#if C_DEBUG - FillFlags(); - if (DEBUG_Breakpoint()) - return debugCallback; -#endif - CPU_SW_Interrupt_NoIOPLCheck(3,GETIP); -#if CPU_TRAP_CHECK - cpu.trap_skip=true; -#endif - continue; - CASE_B(0xcd) /* INT Ib */ - { - Bit8u num=Fetchb(); -#if C_DEBUG - FillFlags(); - if (DEBUG_IntBreakpoint(num)) { - return debugCallback; - } -#endif - CPU_SW_Interrupt(num,GETIP); -#if CPU_TRAP_CHECK - cpu.trap_skip=true; -#endif - continue; - } - CASE_B(0xce) /* INTO */ - if (get_OF()) { - CPU_SW_Interrupt(4,GETIP); -#if CPU_TRAP_CHECK - cpu.trap_skip=true; -#endif - continue; - } - break; - CASE_W(0xcf) /* IRET */ - { - CPU_IRET(false,GETIP); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - return CBRET_NONE; - } -#endif -#if CPU_PIC_CHECK - if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; -#endif - continue; - } - CASE_B(0xd0) /* GRP2 Eb,1 */ - GRP2B(1);break; - CASE_W(0xd1) /* GRP2 Ew,1 */ - GRP2W(1);break; - CASE_B(0xd2) /* GRP2 Eb,CL */ - GRP2B(reg_cl);break; - CASE_W(0xd3) /* GRP2 Ew,CL */ - GRP2W(reg_cl);break; - CASE_B(0xd4) /* AAM Ib */ - AAM(Fetchb());break; - CASE_B(0xd5) /* AAD Ib */ - AAD(Fetchb());break; - CASE_B(0xd6) /* SALC */ - reg_al = get_CF() ? 0xFF : 0; - break; - CASE_B(0xd7) /* XLAT */ - if (TEST_PREFIX_ADDR) { - reg_al=LoadMb(BaseDS+(Bit32u)(reg_ebx+reg_al)); - } else { - reg_al=LoadMb(BaseDS+(Bit16u)(reg_bx+reg_al)); - } - break; -#ifdef CPU_FPU - CASE_B(0xd8) /* FPU ESC 0 */ - FPU_ESC(0);break; - CASE_B(0xd9) /* FPU ESC 1 */ - FPU_ESC(1);break; - CASE_B(0xda) /* FPU ESC 2 */ - FPU_ESC(2);break; - CASE_B(0xdb) /* FPU ESC 3 */ - FPU_ESC(3);break; - CASE_B(0xdc) /* FPU ESC 4 */ - FPU_ESC(4);break; - CASE_B(0xdd) /* FPU ESC 5 */ - FPU_ESC(5);break; - CASE_B(0xde) /* FPU ESC 6 */ - FPU_ESC(6);break; - CASE_B(0xdf) /* FPU ESC 7 */ - FPU_ESC(7);break; -#else - CASE_B(0xd8) /* FPU ESC 0 */ - CASE_B(0xd9) /* FPU ESC 1 */ - CASE_B(0xda) /* FPU ESC 2 */ - CASE_B(0xdb) /* FPU ESC 3 */ - CASE_B(0xdc) /* FPU ESC 4 */ - CASE_B(0xdd) /* FPU ESC 5 */ - CASE_B(0xde) /* FPU ESC 6 */ - CASE_B(0xdf) /* FPU ESC 7 */ - { - LOG(LOG_CPU,LOG_NORMAL)("FPU used"); - Bit8u rm=Fetchb(); - if (rm<0xc0) GetEAa; - } - break; -#endif - CASE_W(0xe0) /* LOOPNZ */ - if (TEST_PREFIX_ADDR) { - JumpCond16_b(--reg_ecx && !get_ZF()); - } else { - JumpCond16_b(--reg_cx && !get_ZF()); - } - break; - CASE_W(0xe1) /* LOOPZ */ - if (TEST_PREFIX_ADDR) { - JumpCond16_b(--reg_ecx && get_ZF()); - } else { - JumpCond16_b(--reg_cx && get_ZF()); - } - break; - CASE_W(0xe2) /* LOOP */ - if (TEST_PREFIX_ADDR) { - JumpCond16_b(--reg_ecx); - } else { - JumpCond16_b(--reg_cx); - } - break; - CASE_W(0xe3) /* JCXZ */ - JumpCond16_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR])); - break; - CASE_B(0xe4) /* IN AL,Ib */ - { - Bitu port=Fetchb(); - if (CPU_IO_Exception(port,1)) RUNEXCEPTION(); - reg_al=IO_ReadB(port); - break; - } - CASE_W(0xe5) /* IN AX,Ib */ - { - Bitu port=Fetchb(); - if (CPU_IO_Exception(port,2)) RUNEXCEPTION(); - reg_al=IO_ReadW(port); - break; - } - CASE_B(0xe6) /* OUT Ib,AL */ - { - Bitu port=Fetchb(); - if (CPU_IO_Exception(port,1)) RUNEXCEPTION(); - IO_WriteB(port,reg_al); - break; - } - CASE_W(0xe7) /* OUT Ib,AX */ - { - Bitu port=Fetchb(); - if (CPU_IO_Exception(port,2)) RUNEXCEPTION(); - IO_WriteW(port,reg_ax); - break; - } - CASE_W(0xe8) /* CALL Jw */ - { - Bit16u addip=Fetchws(); - SAVEIP; - Push_16(reg_eip); - reg_eip=(Bit16u)(reg_eip+addip); - continue; - } - CASE_W(0xe9) /* JMP Jw */ - { - Bit16u addip=Fetchws(); - SAVEIP; - reg_eip=(Bit16u)(reg_eip+addip); - continue; - } - CASE_W(0xea) /* JMP Ap */ - { - Bit16u newip=Fetchw(); - Bit16u newcs=Fetchw(); - FillFlags(); - CPU_JMP(false,newcs,newip,GETIP); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - return CBRET_NONE; - } -#endif - continue; - } - CASE_W(0xeb) /* JMP Jb */ - { - Bit16s addip=Fetchbs(); - SAVEIP; - reg_eip=(Bit16u)(reg_eip+addip); - continue; - } - CASE_B(0xec) /* IN AL,DX */ - if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION(); - reg_al=IO_ReadB(reg_dx); - break; - CASE_W(0xed) /* IN AX,DX */ - if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION(); - reg_ax=IO_ReadW(reg_dx); - break; - CASE_B(0xee) /* OUT DX,AL */ - if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION(); - IO_WriteB(reg_dx,reg_al); - break; - CASE_W(0xef) /* OUT DX,AX */ - if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION(); - IO_WriteW(reg_dx,reg_ax); - break; - CASE_B(0xf0) /* LOCK */ - LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK"); /* FIXME: see case D_LOCK in core_full/load.h */ - break; - CASE_B(0xf1) /* ICEBP */ - CPU_SW_Interrupt_NoIOPLCheck(1,GETIP); -#if CPU_TRAP_CHECK - cpu.trap_skip=true; -#endif - continue; - CASE_B(0xf2) /* REPNZ */ - DO_PREFIX_REP(false); - break; - CASE_B(0xf3) /* REPZ */ - DO_PREFIX_REP(true); - break; - CASE_B(0xf4) /* HLT */ - if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); - FillFlags(); - CPU_HLT(GETIP); - return CBRET_NONE; //Needs to return for hlt cpu core - CASE_B(0xf5) /* CMC */ - FillFlags(); - SETFLAGBIT(CF,!(reg_flags & FLAG_CF)); - break; - CASE_B(0xf6) /* GRP3 Eb(,Ib) */ - { - GetRM;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* TEST Eb,Ib */ - case 0x01: /* TEST Eb,Ib Undocumented*/ - { - if (rm >= 0xc0 ) {GetEArb;TESTB(*earb,Fetchb(),LoadRb,0)} - else {GetEAa;TESTB(eaa,Fetchb(),LoadMb,0);} - break; - } - case 0x02: /* NOT Eb */ - { - if (rm >= 0xc0 ) {GetEArb;*earb=~*earb;} - else {GetEAa;SaveMb(eaa,~LoadMb(eaa));} - break; - } - case 0x03: /* NEG Eb */ - { - lflags.type=t_NEGb; - if (rm >= 0xc0 ) { - GetEArb;lf_var1b=*earb;lf_resb=0-lf_var1b; - *earb=lf_resb; - } else { - GetEAa;lf_var1b=LoadMb(eaa);lf_resb=0-lf_var1b; - SaveMb(eaa,lf_resb); - } - break; - } - case 0x04: /* MUL AL,Eb */ - RMEb(MULB); - break; - case 0x05: /* IMUL AL,Eb */ - RMEb(IMULB); - break; - case 0x06: /* DIV Eb */ - RMEb(DIVB); - break; - case 0x07: /* IDIV Eb */ - RMEb(IDIVB); - break; - } - break; - } - CASE_W(0xf7) /* GRP3 Ew(,Iw) */ - { - GetRM;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* TEST Ew,Iw */ - case 0x01: /* TEST Ew,Iw Undocumented*/ - { - if (rm >= 0xc0 ) {GetEArw;TESTW(*earw,Fetchw(),LoadRw,SaveRw);} - else {GetEAa;TESTW(eaa,Fetchw(),LoadMw,SaveMw);} - break; - } - case 0x02: /* NOT Ew */ - { - if (rm >= 0xc0 ) {GetEArw;*earw=~*earw;} - else {GetEAa;SaveMw(eaa,~LoadMw(eaa));} - break; - } - case 0x03: /* NEG Ew */ - { - lflags.type=t_NEGw; - if (rm >= 0xc0 ) { - GetEArw;lf_var1w=*earw;lf_resw=0-lf_var1w; - *earw=lf_resw; - } else { - GetEAa;lf_var1w=LoadMw(eaa);lf_resw=0-lf_var1w; - SaveMw(eaa,lf_resw); - } - break; - } - case 0x04: /* MUL AX,Ew */ - RMEw(MULW); - break; - case 0x05: /* IMUL AX,Ew */ - RMEw(IMULW) - break; - case 0x06: /* DIV Ew */ - RMEw(DIVW) - break; - case 0x07: /* IDIV Ew */ - RMEw(IDIVW) - break; - } - break; - } - CASE_B(0xf8) /* CLC */ - FillFlags(); - SETFLAGBIT(CF,false); - break; - CASE_B(0xf9) /* STC */ - FillFlags(); - SETFLAGBIT(CF,true); - break; - CASE_B(0xfa) /* CLI */ - if (CPU_CLI()) RUNEXCEPTION(); - break; - CASE_B(0xfb) /* STI */ - if (CPU_STI()) RUNEXCEPTION(); -#if CPU_PIC_CHECK - if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; -#endif - break; - CASE_B(0xfc) /* CLD */ - SETFLAGBIT(DF,false); - cpu.direction=1; - break; - CASE_B(0xfd) /* STD */ - SETFLAGBIT(DF,true); - cpu.direction=-1; - break; - CASE_B(0xfe) /* GRP4 Eb */ - { - GetRM;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* INC Eb */ - RMEb(INCB); - break; - case 0x01: /* DEC Eb */ - RMEb(DECB); - break; - case 0x07: /* CallBack */ - { - Bitu cb=Fetchw(); - FillFlags();SAVEIP; - return cb; - } - default: - E_Exit("Illegal GRP4 Call %d",(rm>>3) & 7); - break; - } - break; - } - CASE_W(0xff) /* GRP5 Ew */ - { - GetRM;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* INC Ew */ - RMEw(INCW); - break; - case 0x01: /* DEC Ew */ - RMEw(DECW); - break; - case 0x02: /* CALL Ev */ - if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;} - else {GetEAa;reg_eip=LoadMw(eaa);} - Push_16(GETIP); - continue; - case 0x03: /* CALL Ep */ - { - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - Bit16u newip=LoadMw(eaa); - Bit16u newcs=LoadMw(eaa+2); - FillFlags(); - CPU_CALL(false,newcs,newip,GETIP); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - return CBRET_NONE; - } -#endif - continue; - } - break; - case 0x04: /* JMP Ev */ - if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;} - else {GetEAa;reg_eip=LoadMw(eaa);} - continue; - case 0x05: /* JMP Ep */ - { - if (rm >= 0xc0) goto illegal_opcode; - GetEAa; - Bit16u newip=LoadMw(eaa); - Bit16u newcs=LoadMw(eaa+2); - FillFlags(); - CPU_JMP(false,newcs,newip,GETIP); -#if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Trap_Run; - return CBRET_NONE; - } -#endif - continue; - } - break; - case 0x06: /* PUSH Ev */ - if (rm >= 0xc0 ) {GetEArw;Push_16(*earw);} - else {GetEAa;Push_16(LoadMw(eaa));} - break; - default: - E_Exit("CPU:GRP5:Illegal Call %2X",which); - break; - } - break; - } - - - - diff --git a/src/cpu/core_normal/string.h b/src/cpu/core_normal/string.h deleted file mode 100644 index 411fad8..0000000 --- a/src/cpu/core_normal/string.h +++ /dev/null @@ -1,232 +0,0 @@ -enum STRING_OP { - R_OUTSB,R_OUTSW,R_OUTSD, - R_INSB,R_INSW,R_INSD, - R_MOVSB,R_MOVSW,R_MOVSD, - R_LODSB,R_LODSW,R_LODSD, - R_STOSB,R_STOSW,R_STOSD, - R_SCASB,R_SCASW,R_SCASD, - R_CMPSB,R_CMPSW,R_CMPSD -}; - -#define LoadD(_BLAH) _BLAH - -static void DoString(STRING_OP type) { - PhysPt si_base,di_base; - Bitu si_index,di_index; - Bitu add_mask; - Bitu count,count_left; - Bits add_index; - - si_base=BaseDS; - di_base=SegBase(es); - add_mask=AddrMaskTable[core.prefixes & PREFIX_ADDR]; - si_index=reg_esi & add_mask; - di_index=reg_edi & add_mask; - count=reg_ecx & add_mask; - if (!TEST_PREFIX_REP) { - count=1; - } else { - CPU_Cycles++; - /* Calculate amount of ops to do before cycles run out */ - if ((count>(Bitu)CPU_Cycles) && (type0;count--) { - IO_WriteB(reg_dx,LoadMb(si_base+si_index)); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_OUTSW: - add_index<<=1; - for (;count>0;count--) { - IO_WriteW(reg_dx,LoadMw(si_base+si_index)); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_OUTSD: - add_index<<=2; - for (;count>0;count--) { - IO_WriteD(reg_dx,LoadMd(si_base+si_index)); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_INSB: - for (;count>0;count--) { - SaveMb(di_base+di_index,IO_ReadB(reg_dx)); - di_index=(di_index+add_index) & add_mask; - } - break; - case R_INSW: - add_index<<=1; - for (;count>0;count--) { - SaveMw(di_base+di_index,IO_ReadW(reg_dx)); - di_index=(di_index+add_index) & add_mask; - } - break; - case R_STOSB: - for (;count>0;count--) { - SaveMb(di_base+di_index,reg_al); - di_index=(di_index+add_index) & add_mask; - } - break; - case R_STOSW: - add_index<<=1; - for (;count>0;count--) { - SaveMw(di_base+di_index,reg_ax); - di_index=(di_index+add_index) & add_mask; - } - break; - case R_STOSD: - add_index<<=2; - for (;count>0;count--) { - SaveMd(di_base+di_index,reg_eax); - di_index=(di_index+add_index) & add_mask; - } - break; - case R_MOVSB: - for (;count>0;count--) { - SaveMb(di_base+di_index,LoadMb(si_base+si_index)); - di_index=(di_index+add_index) & add_mask; - si_index=(si_index+add_index) & add_mask; - } - break; - case R_MOVSW: - add_index<<=1; - for (;count>0;count--) { - SaveMw(di_base+di_index,LoadMw(si_base+si_index)); - di_index=(di_index+add_index) & add_mask; - si_index=(si_index+add_index) & add_mask; - } - break; - case R_MOVSD: - add_index<<=2; - for (;count>0;count--) { - SaveMd(di_base+di_index,LoadMd(si_base+si_index)); - di_index=(di_index+add_index) & add_mask; - si_index=(si_index+add_index) & add_mask; - } - break; - case R_LODSB: - for (;count>0;count--) { - reg_al=LoadMb(si_base+si_index); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_LODSW: - add_index<<=1; - for (;count>0;count--) { - reg_ax=LoadMw(si_base+si_index); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_LODSD: - add_index<<=2; - for (;count>0;count--) { - reg_eax=LoadMd(si_base+si_index); - si_index=(si_index+add_index) & add_mask; - } - break; - case R_SCASB: - { - Bit8u val2; - for (;count>0;) { - count--;CPU_Cycles--; - val2=LoadMb(di_base+di_index); - di_index=(di_index+add_index) & add_mask; - if ((reg_al==val2)!=core.rep_zero) break; - } - CMPB(reg_al,val2,LoadD,0); - } - break; - case R_SCASW: - { - add_index<<=1;Bit16u val2; - for (;count>0;) { - count--;CPU_Cycles--; - val2=LoadMw(di_base+di_index); - di_index=(di_index+add_index) & add_mask; - if ((reg_ax==val2)!=core.rep_zero) break; - } - CMPW(reg_ax,val2,LoadD,0); - } - break; - case R_SCASD: - { - add_index<<=2;Bit32u val2; - for (;count>0;) { - count--;CPU_Cycles--; - val2=LoadMd(di_base+di_index); - di_index=(di_index+add_index) & add_mask; - if ((reg_eax==val2)!=core.rep_zero) break; - } - CMPD(reg_eax,val2,LoadD,0); - } - break; - case R_CMPSB: - { - Bit8u val1,val2; - for (;count>0;) { - count--;CPU_Cycles--; - val1=LoadMb(si_base+si_index); - val2=LoadMb(di_base+di_index); - si_index=(si_index+add_index) & add_mask; - di_index=(di_index+add_index) & add_mask; - if ((val1==val2)!=core.rep_zero) break; - } - CMPB(val1,val2,LoadD,0); - } - break; - case R_CMPSW: - { - add_index<<=1;Bit16u val1,val2; - for (;count>0;) { - count--;CPU_Cycles--; - val1=LoadMw(si_base+si_index); - val2=LoadMw(di_base+di_index); - si_index=(si_index+add_index) & add_mask; - di_index=(di_index+add_index) & add_mask; - if ((val1==val2)!=core.rep_zero) break; - } - CMPW(val1,val2,LoadD,0); - } - break; - case R_CMPSD: - { - add_index<<=2;Bit32u val1,val2; - for (;count>0;) { - count--;CPU_Cycles--; - val1=LoadMd(si_base+si_index); - val2=LoadMd(di_base+di_index); - si_index=(si_index+add_index) & add_mask; - di_index=(di_index+add_index) & add_mask; - if ((val1==val2)!=core.rep_zero) break; - } - CMPD(val1,val2,LoadD,0); - } - break; - default: - LOG(LOG_CPU,LOG_ERROR)("Unhandled string op %d",type); - } - /* Clean up after certain amount of instructions */ - reg_esi&=(~add_mask); - reg_esi|=(si_index & add_mask); - reg_edi&=(~add_mask); - reg_edi|=(di_index & add_mask); - if (TEST_PREFIX_REP) { - count+=count_left; - reg_ecx&=(~add_mask); - reg_ecx|=(count & add_mask); - } -} diff --git a/src/cpu/core_normal/support.h b/src/cpu/core_normal/support.h deleted file mode 100644 index cbfcfa1..0000000 --- a/src/cpu/core_normal/support.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -#define LoadMbs(off) (Bit8s)(LoadMb(off)) -#define LoadMws(off) (Bit16s)(LoadMw(off)) -#define LoadMds(off) (Bit32s)(LoadMd(off)) - -#define LoadRb(reg) reg -#define LoadRw(reg) reg -#define LoadRd(reg) reg - -#define SaveRb(reg,val) reg=val -#define SaveRw(reg,val) reg=val -#define SaveRd(reg,val) reg=val - -static INLINE Bit8s Fetchbs() { - return Fetchb(); -} -static INLINE Bit16s Fetchws() { - return Fetchw(); -} - -static INLINE Bit32s Fetchds() { - return Fetchd(); -} - - -#define RUNEXCEPTION() { \ - CPU_Exception(cpu.exception.which,cpu.exception.error); \ - continue; \ -} - -#define EXCEPTION(blah) \ - { \ - CPU_Exception(blah); \ - continue; \ - } - -//TODO Could probably make all byte operands fast? -#define JumpCond16_b(COND) { \ - SAVEIP; \ - if (COND) reg_ip+=Fetchbs(); \ - reg_ip+=1; \ - continue; \ -} - -#define JumpCond16_w(COND) { \ - SAVEIP; \ - if (COND) reg_ip+=Fetchws(); \ - reg_ip+=2; \ - continue; \ -} - -#define JumpCond32_b(COND) { \ - SAVEIP; \ - if (COND) reg_eip+=Fetchbs(); \ - reg_eip+=1; \ - continue; \ -} - -#define JumpCond32_d(COND) { \ - SAVEIP; \ - if (COND) reg_eip+=Fetchds(); \ - reg_eip+=4; \ - continue; \ -} - - -#define SETcc(cc) \ - { \ - GetRM; \ - if (rm >= 0xc0 ) {GetEArb;*earb=(cc) ? 1 : 0;} \ - else {GetEAa;SaveMb(eaa,(cc) ? 1 : 0);} \ - } - -#include "helpers.h" -#include "table_ea.h" -#include "../modrm.h" - - diff --git a/src/cpu/core_normal/table_ea.h b/src/cpu/core_normal/table_ea.h deleted file mode 100644 index 0b7190e..0000000 --- a/src/cpu/core_normal/table_ea.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -typedef PhysPt (*EA_LookupHandler)(void); - -/* The MOD/RM Decoder for EA for this decoder's addressing modes */ -static PhysPt EA_16_00_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si); } -static PhysPt EA_16_01_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di); } -static PhysPt EA_16_02_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si); } -static PhysPt EA_16_03_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di); } -static PhysPt EA_16_04_n(void) { return BaseDS+(Bit16u)(reg_si); } -static PhysPt EA_16_05_n(void) { return BaseDS+(Bit16u)(reg_di); } -static PhysPt EA_16_06_n(void) { return BaseDS+(Bit16u)(Fetchw());} -static PhysPt EA_16_07_n(void) { return BaseDS+(Bit16u)(reg_bx); } - -static PhysPt EA_16_40_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); } -static PhysPt EA_16_41_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); } -static PhysPt EA_16_42_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); } -static PhysPt EA_16_43_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); } -static PhysPt EA_16_44_n(void) { return BaseDS+(Bit16u)(reg_si+Fetchbs()); } -static PhysPt EA_16_45_n(void) { return BaseDS+(Bit16u)(reg_di+Fetchbs()); } -static PhysPt EA_16_46_n(void) { return BaseSS+(Bit16u)(reg_bp+Fetchbs()); } -static PhysPt EA_16_47_n(void) { return BaseDS+(Bit16u)(reg_bx+Fetchbs()); } - -static PhysPt EA_16_80_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); } -static PhysPt EA_16_81_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); } -static PhysPt EA_16_82_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); } -static PhysPt EA_16_83_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); } -static PhysPt EA_16_84_n(void) { return BaseDS+(Bit16u)(reg_si+Fetchws()); } -static PhysPt EA_16_85_n(void) { return BaseDS+(Bit16u)(reg_di+Fetchws()); } -static PhysPt EA_16_86_n(void) { return BaseSS+(Bit16u)(reg_bp+Fetchws()); } -static PhysPt EA_16_87_n(void) { return BaseDS+(Bit16u)(reg_bx+Fetchws()); } - -static Bit32u SIBZero=0; -static Bit32u * SIBIndex[8]= { ®_eax,®_ecx,®_edx,®_ebx,&SIBZero,®_ebp,®_esi,®_edi }; - -static INLINE PhysPt Sib(Bitu mode) { - Bit8u sib=Fetchb(); - PhysPt base; - switch (sib&7) { - case 0: /* EAX Base */ - base=BaseDS+reg_eax;break; - case 1: /* ECX Base */ - base=BaseDS+reg_ecx;break; - case 2: /* EDX Base */ - base=BaseDS+reg_edx;break; - case 3: /* EBX Base */ - base=BaseDS+reg_ebx;break; - case 4: /* ESP Base */ - base=BaseSS+reg_esp;break; - case 5: /* #1 Base */ - if (!mode) { - base=BaseDS+Fetchd();break; - } else { - base=BaseSS+reg_ebp;break; - } - case 6: /* ESI Base */ - base=BaseDS+reg_esi;break; - case 7: /* EDI Base */ - base=BaseDS+reg_edi;break; - } - base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); - return base; -} - -static PhysPt EA_32_00_n(void) { return BaseDS+reg_eax; } -static PhysPt EA_32_01_n(void) { return BaseDS+reg_ecx; } -static PhysPt EA_32_02_n(void) { return BaseDS+reg_edx; } -static PhysPt EA_32_03_n(void) { return BaseDS+reg_ebx; } -static PhysPt EA_32_04_n(void) { return Sib(0);} -static PhysPt EA_32_05_n(void) { return BaseDS+Fetchd(); } -static PhysPt EA_32_06_n(void) { return BaseDS+reg_esi; } -static PhysPt EA_32_07_n(void) { return BaseDS+reg_edi; } - -static PhysPt EA_32_40_n(void) { return BaseDS+reg_eax+Fetchbs(); } -static PhysPt EA_32_41_n(void) { return BaseDS+reg_ecx+Fetchbs(); } -static PhysPt EA_32_42_n(void) { return BaseDS+reg_edx+Fetchbs(); } -static PhysPt EA_32_43_n(void) { return BaseDS+reg_ebx+Fetchbs(); } -static PhysPt EA_32_44_n(void) { PhysPt temp=Sib(1);return temp+Fetchbs();} -//static PhysPt EA_32_44_n(void) { return Sib(1)+Fetchbs();} -static PhysPt EA_32_45_n(void) { return BaseSS+reg_ebp+Fetchbs(); } -static PhysPt EA_32_46_n(void) { return BaseDS+reg_esi+Fetchbs(); } -static PhysPt EA_32_47_n(void) { return BaseDS+reg_edi+Fetchbs(); } - -static PhysPt EA_32_80_n(void) { return BaseDS+reg_eax+Fetchds(); } -static PhysPt EA_32_81_n(void) { return BaseDS+reg_ecx+Fetchds(); } -static PhysPt EA_32_82_n(void) { return BaseDS+reg_edx+Fetchds(); } -static PhysPt EA_32_83_n(void) { return BaseDS+reg_ebx+Fetchds(); } -static PhysPt EA_32_84_n(void) { PhysPt temp=Sib(2);return temp+Fetchds();} -//static PhysPt EA_32_84_n(void) { return Sib(2)+Fetchds();} -static PhysPt EA_32_85_n(void) { return BaseSS+reg_ebp+Fetchds(); } -static PhysPt EA_32_86_n(void) { return BaseDS+reg_esi+Fetchds(); } -static PhysPt EA_32_87_n(void) { return BaseDS+reg_edi+Fetchds(); } - -static GetEAHandler EATable[512]={ -/* 00 */ - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, -/* 01 */ - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, -/* 10 */ - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, -/* 11 These are illegal so make em 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 00 */ - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, -/* 01 */ - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, -/* 10 */ - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, -/* 11 These are illegal so make em 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#define GetEADirect \ - PhysPt eaa; \ - if (TEST_PREFIX_ADDR) { \ - eaa=BaseDS+Fetchd(); \ - } else { \ - eaa=BaseDS+Fetchw(); \ - } \ - - diff --git a/src/cpu/core_prefetch.cpp b/src/cpu/core_prefetch.cpp deleted file mode 100644 index 14b420a..0000000 --- a/src/cpu/core_prefetch.cpp +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: core_prefetch.cpp,v 1.1 2008/05/21 21:29:32 c2woody Exp $ */ - -#include - -#include "dosbox.h" -#include "mem.h" -#include "cpu.h" -#include "lazyflags.h" -#include "inout.h" -#include "callback.h" -#include "pic.h" -#include "fpu.h" -#include "paging.h" - -#if C_DEBUG -#include "debug.h" -#endif - -#if (!C_CORE_INLINE) -#define LoadMb(off) mem_readb(off) -#define LoadMw(off) mem_readw(off) -#define LoadMd(off) mem_readd(off) -#define SaveMb(off,val) mem_writeb(off,val) -#define SaveMw(off,val) mem_writew(off,val) -#define SaveMd(off,val) mem_writed(off,val) -#else -#include "paging.h" -#define LoadMb(off) mem_readb_inline(off) -#define LoadMw(off) mem_readw_inline(off) -#define LoadMd(off) mem_readd_inline(off) -#define SaveMb(off,val) mem_writeb_inline(off,val) -#define SaveMw(off,val) mem_writew_inline(off,val) -#define SaveMd(off,val) mem_writed_inline(off,val) -#endif - -extern Bitu cycle_count; - -#if C_FPU -#define CPU_FPU 1 //Enable FPU escape instructions -#endif - -#define CPU_PIC_CHECK 1 -#define CPU_TRAP_CHECK 1 - -#define OPCODE_NONE 0x000 -#define OPCODE_0F 0x100 -#define OPCODE_SIZE 0x200 - -#define PREFIX_ADDR 0x1 -#define PREFIX_REP 0x2 - -#define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR) -#define TEST_PREFIX_REP (core.prefixes & PREFIX_REP) - -#define DO_PREFIX_SEG(_SEG) \ - BaseDS=SegBase(_SEG); \ - BaseSS=SegBase(_SEG); \ - core.base_val_ds=_SEG; \ - goto restart_opcode; - -#define DO_PREFIX_ADDR() \ - core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \ - (cpu.code.big ^ PREFIX_ADDR); \ - core.ea_table=&EATable[(core.prefixes&1) * 256]; \ - goto restart_opcode; - -#define DO_PREFIX_REP(_ZERO) \ - core.prefixes|=PREFIX_REP; \ - core.rep_zero=_ZERO; \ - goto restart_opcode; - -typedef PhysPt (*GetEAHandler)(void); - -static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff}; - -static struct { - Bitu opcode_index; - PhysPt cseip; - PhysPt base_ds,base_ss; - SegNames base_val_ds; - bool rep_zero; - Bitu prefixes; - GetEAHandler * ea_table; -} core; - -#define GETIP (core.cseip-SegBase(cs)) -#define SAVEIP reg_eip=GETIP; -#define LOADIP core.cseip=(SegBase(cs)+reg_eip); - -#define SegBase(c) SegPhys(c) -#define BaseDS core.base_ds -#define BaseSS core.base_ss - - -#define MAX_PQ_SIZE 32 -static Bit8u prefetch_buffer[MAX_PQ_SIZE]; -static bool pq_valid=false; -static Bitu pq_start; - -static INLINE Bit8u Fetchb() { - Bit8u temp; - if (pq_valid && (core.cseip>=pq_start) && (core.cseip=pq_start+CPU_PrefetchQueueSize-4) && - (core.cseip+1=pq_start) && (core.cseip+2=pq_start+CPU_PrefetchQueueSize-4) && - (core.cseip+2=pq_start) && (core.cseip+4=pq_start+CPU_PrefetchQueueSize-4) && - (core.cseip+40) { - if (invalidate_pq) { - pq_valid=false; - invalidate_pq=false; - } - LOADIP; - core.opcode_index=cpu.code.big*0x200; - core.prefixes=cpu.code.big; - core.ea_table=&EATable[cpu.code.big*256]; - BaseDS=SegBase(ds); - BaseSS=SegBase(ss); - core.base_val_ds=ds; -#if C_DEBUG -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) { - FillFlags(); - return debugCallback; - }; -#endif - cycle_count++; -#endif -restart_opcode: - Bit8u next_opcode=Fetchb(); - invalidate_pq=false; - if (core.opcode_index&OPCODE_0F) invalidate_pq=true; - else switch (next_opcode) { - case 0x70: case 0x71: case 0x72: case 0x73: - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7a: case 0x7b: - case 0x7c: case 0x7d: case 0x7e: case 0x7f: // jcc - case 0x9a: // call - case 0xc2: case 0xc3: // retn - case 0xc8: // enter - case 0xc9: // leave - case 0xca: case 0xcb: // retf - case 0xcc: // int3 - case 0xcd: // int - case 0xce: // into - case 0xcf: // iret - case 0xe0: // loopnz - case 0xe1: // loopz - case 0xe2: // loop - case 0xe3: // jcxz - case 0xe8: // call - case 0xe9: case 0xea: case 0xeb: // jmp - case 0xff: - invalidate_pq=true; - break; - default: - break; - } - switch (core.opcode_index+next_opcode) { - #include "core_normal/prefix_none.h" - #include "core_normal/prefix_0f.h" - #include "core_normal/prefix_66.h" - #include "core_normal/prefix_66_0f.h" - default: - illegal_opcode: -#if C_DEBUG - { - Bitu len=(GETIP-reg_eip); - LOADIP; - if (len>16) len=16; - char tempcode[16*2+1];char * writecode=tempcode; - for (;len>0;len--) { - sprintf(writecode,"%X",mem_readb(core.cseip++)); - writecode+=2; - } - LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode); - } -#endif - CPU_Exception(6,0); - invalidate_pq=true; - continue; - } - SAVEIP; - } - FillFlags(); - return CBRET_NONE; -decode_end: - SAVEIP; - FillFlags(); - return CBRET_NONE; -} - -Bits CPU_Core_Prefetch_Trap_Run(void) { - Bits oldCycles = CPU_Cycles; - CPU_Cycles = 1; - cpu.trap_skip = false; - - Bits ret=CPU_Core_Prefetch_Run(); - if (!cpu.trap_skip) CPU_HW_Interrupt(1); - CPU_Cycles = oldCycles-1; - cpudecoder = &CPU_Core_Prefetch_Run; - - return ret; -} - - - -void CPU_Core_Prefetch_Init(void) { - -} - diff --git a/src/cpu/core_simple.cpp b/src/cpu/core_simple.cpp deleted file mode 100644 index fb837e5..0000000 --- a/src/cpu/core_simple.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include - -#include "dosbox.h" -#include "mem.h" -#include "cpu.h" -#include "lazyflags.h" -#include "inout.h" -#include "callback.h" -#include "pic.h" -#include "fpu.h" - -#if C_DEBUG -#include "debug.h" -#endif - -#include "paging.h" -#define SegBase(c) SegPhys(c) -#define LoadMb(off) mem_readb(off) -#define LoadMw(off) mem_readw(off) -#define LoadMd(off) mem_readd(off) - -#define SaveMb(off,val) mem_writeb(off,val) -#define SaveMw(off,val) mem_writew(off,val) -#define SaveMd(off,val) mem_writed(off,val) - -extern Bitu cycle_count; - -#if C_FPU -#define CPU_FPU 1 //Enable FPU escape instructions -#endif - -#define CPU_PIC_CHECK 1 -#define CPU_TRAP_CHECK 1 - -#define OPCODE_NONE 0x000 -#define OPCODE_0F 0x100 -#define OPCODE_SIZE 0x200 - -#define PREFIX_ADDR 0x1 -#define PREFIX_REP 0x2 - -#define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR) -#define TEST_PREFIX_REP (core.prefixes & PREFIX_REP) - -#define DO_PREFIX_SEG(_SEG) \ - BaseDS=SegBase(_SEG); \ - BaseSS=SegBase(_SEG); \ - core.base_val_ds=_SEG; \ - goto restart_opcode; - -#define DO_PREFIX_ADDR() \ - core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \ - (cpu.code.big ^ PREFIX_ADDR); \ - core.ea_table=&EATable[(core.prefixes&1) * 256]; \ - goto restart_opcode; - -#define DO_PREFIX_REP(_ZERO) \ - core.prefixes|=PREFIX_REP; \ - core.rep_zero=_ZERO; \ - goto restart_opcode; - -typedef PhysPt (*GetEAHandler)(void); - -static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff}; - -static struct { - Bitu opcode_index; -#if defined (_MSC_VER) - volatile HostPt cseip; -#else - HostPt cseip; -#endif - PhysPt base_ds,base_ss; - SegNames base_val_ds; - bool rep_zero; - Bitu prefixes; - GetEAHandler * ea_table; -} core; - -#define GETIP (core.cseip-SegBase(cs)-MemBase) -#define SAVEIP reg_eip=GETIP; -#define LOADIP core.cseip=(MemBase+SegBase(cs)+reg_eip); - -#define SegBase(c) SegPhys(c) -#define BaseDS core.base_ds -#define BaseSS core.base_ss - -static INLINE Bit8u Fetchb() { - Bit8u temp=host_readb(core.cseip); - core.cseip+=1; - return temp; -} - -static INLINE Bit16u Fetchw() { - Bit16u temp=host_readw(core.cseip); - core.cseip+=2; - return temp; -} -static INLINE Bit32u Fetchd() { - Bit32u temp=host_readd(core.cseip); - core.cseip+=4; - return temp; -} - -#define Push_16 CPU_Push16 -#define Push_32 CPU_Push32 -#define Pop_16 CPU_Pop16 -#define Pop_32 CPU_Pop32 - -#include "instructions.h" -#include "core_normal/support.h" -#include "core_normal/string.h" - - -#define EALookupTable (core.ea_table) - -Bits CPU_Core_Simple_Run(void) { - while (CPU_Cycles-->0) { - LOADIP; - core.opcode_index=cpu.code.big*0x200; - core.prefixes=cpu.code.big; - core.ea_table=&EATable[cpu.code.big*256]; - BaseDS=SegBase(ds); - BaseSS=SegBase(ss); - core.base_val_ds=ds; -#if C_DEBUG -#if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) { - FillFlags(); - return debugCallback; - }; -#endif - cycle_count++; -#endif -restart_opcode: - switch (core.opcode_index+Fetchb()) { - - #include "core_normal/prefix_none.h" - #include "core_normal/prefix_0f.h" - #include "core_normal/prefix_66.h" - #include "core_normal/prefix_66_0f.h" - default: - illegal_opcode: -#if C_DEBUG - { - Bitu len=(GETIP-reg_eip); - LOADIP; - if (len>16) len=16; - char tempcode[16*2+1];char * writecode=tempcode; - for (;len>0;len--) { -// sprintf(writecode,"%X",mem_readb(core.cseip++)); - writecode+=2; - } - LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode); - } -#endif - CPU_Exception(6,0); - continue; - } - SAVEIP; - } - FillFlags(); - return CBRET_NONE; -decode_end: - SAVEIP; - FillFlags(); - return CBRET_NONE; -} - -// not really used -Bits CPU_Core_Simple_Trap_Run(void) { - Bits oldCycles = CPU_Cycles; - CPU_Cycles = 1; - cpu.trap_skip = false; - - Bits ret=CPU_Core_Normal_Run(); - if (!cpu.trap_skip) CPU_HW_Interrupt(1); - CPU_Cycles = oldCycles-1; - cpudecoder = &CPU_Core_Simple_Run; - - return ret; -} - - - -void CPU_Core_Simple_Init(void) { - -} diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 14f83c3..82a94c5 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -1,2410 +1,185 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: cpu.cpp,v 1.116 2009/03/16 18:10:08 c2woody Exp $ */ - -#include -#include -#include "dosbox.h" -#include "cpu.h" -#include "memory.h" -#include "debug.h" -#include "mapper.h" -#include "setup.h" -#include "programs.h" -#include "paging.h" -#include "lazyflags.h" -#include "support.h" - -Bitu DEBUG_EnableDebugger(void); -extern void GFX_SetTitle(Bit32s cycles ,Bits frameskip,bool paused); - -#if 1 -#undef LOG -#if defined (_MSC_VER) -#define LOG(X,Y) -#else -#define LOG(X,Y) CPU_LOG -#define CPU_LOG(...) -#endif -#endif - -CPU_Regs cpu_regs; -CPUBlock cpu; -Segments Segs; - -Bit32s CPU_Cycles = 0; -Bit32s CPU_CycleLeft = 0; -Bit32s CPU_CycleMax = 3000; -Bit32s CPU_OldCycleMax = 3000; -Bit32s CPU_CyclePercUsed = 100; -Bit32s CPU_CycleLimit = -1; -Bit32s CPU_CycleUp = 0; -Bit32s CPU_CycleDown = 0; -Bit64s CPU_IODelayRemoved = 0; -CPU_Decoder * cpudecoder; -bool CPU_CycleAutoAdjust = false; -bool CPU_SkipCycleAutoAdjust = false; -Bitu CPU_AutoDetermineMode = 0; - -Bitu CPU_ArchitectureType = CPU_ARCHTYPE_MIXED; - -Bitu CPU_flag_id_toggle=0; - -Bitu CPU_PrefetchQueueSize=0; - -void CPU_Core_Full_Init(void); -void CPU_Core_Normal_Init(void); -void CPU_Core_Simple_Init(void); -#if (C_DYNAMIC_X86) -void CPU_Core_Dyn_X86_Init(void); -void CPU_Core_Dyn_X86_Cache_Init(bool enable_cache); -void CPU_Core_Dyn_X86_Cache_Close(void); -void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu); -#elif (C_DYNREC) -void CPU_Core_Dynrec_Init(void); -void CPU_Core_Dynrec_Cache_Init(bool enable_cache); -void CPU_Core_Dynrec_Cache_Close(void); -#endif - -/* In debug mode exceptions are tested and dosbox exits when - * a unhandled exception state is detected. - * USE CHECK_EXCEPT to raise an exception in that case to see if that exception - * solves the problem. - * - * In non-debug mode dosbox doesn't do detection (and hence doesn't crash at - * that point). (game might crash later due to the unhandled exception) */ - -#if C_DEBUG -// #define CPU_CHECK_EXCEPT 1 -// #define CPU_CHECK_IGNORE 1 - /* Use CHECK_EXCEPT when something doesn't work to see if a exception is - * needed that isn't enabled by default.*/ -#else -/* NORMAL NO CHECKING => More Speed */ -#define CPU_CHECK_IGNORE 1 -#endif /* C_DEBUG */ - -#if defined(CPU_CHECK_IGNORE) -#define CPU_CHECK_COND(cond,msg,exc,sel) { \ - if (cond) do {} while (0); \ -} -#elif defined(CPU_CHECK_EXCEPT) -#define CPU_CHECK_COND(cond,msg,exc,sel) { \ - if (cond) { \ - CPU_Exception(exc,sel); \ - return; \ - } \ -} -#else -#define CPU_CHECK_COND(cond,msg,exc,sel) { \ - if (cond) E_Exit(msg); \ -} -#endif - - -void Descriptor::Load(PhysPt address) { - cpu.mpl=0; - Bit32u* data = (Bit32u*)&saved; - *data = mem_readd(address); - *(data+1) = mem_readd(address+4); - cpu.mpl=3; -} -void Descriptor:: Save(PhysPt address) { - cpu.mpl=0; - Bit32u* data = (Bit32u*)&saved; - mem_writed(address,*data); - mem_writed(address+4,*(data+1)); - cpu.mpl=03; -} - - -void CPU_Push16(Bitu value) { - Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-2)&cpu.stack.mask); - mem_writew(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value); - reg_esp=new_esp; -} - -void CPU_Push32(Bitu value) { - Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-4)&cpu.stack.mask); - mem_writed(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value); - reg_esp=new_esp; -} - -Bitu CPU_Pop16(void) { - Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask); - return val; -} - -Bitu CPU_Pop32(void) { - Bitu val=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask); - return val; -} - -PhysPt SelBase(Bitu sel) { - if (cpu.cr0 & CR0_PROTECTION) { - Descriptor desc; - cpu.gdt.GetDescriptor(sel,desc); - return desc.GetBase(); - } else { - return sel<<4; - } -} - - -void CPU_SetFlags(Bitu word,Bitu mask) { - mask|=CPU_flag_id_toggle; // ID-flag can be toggled on cpuid-supporting CPUs - reg_flags=(reg_flags & ~mask)|(word & mask)|2; - cpu.direction=1-((reg_flags & FLAG_DF) >> 9); -} - -bool CPU_PrepareException(Bitu which,Bitu error) { - cpu.exception.which=which; - cpu.exception.error=error; - return true; -} - -bool CPU_CLI(void) { - if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL0)) mask &= (~FLAG_IOPL); - if (cpu.pmode && !GETFLAG(VM) && (GETFLAG_IOPLdesc.DPL()) needs_invalidation=true; break; - default: break; } - if (needs_invalidation) CPU_SetSegGeneral(es,0); - - needs_invalidation=false; - if (!cpu.gdt.GetDescriptor(SegValue(ds),desc)) needs_invalidation=true; - else switch (desc.Type()) { - case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (cpu.cpl>desc.DPL()) needs_invalidation=true; break; - default: break; } - if (needs_invalidation) CPU_SetSegGeneral(ds,0); - - needs_invalidation=false; - if (!cpu.gdt.GetDescriptor(SegValue(fs),desc)) needs_invalidation=true; - else switch (desc.Type()) { - case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (cpu.cpl>desc.DPL()) needs_invalidation=true; break; - default: break; } - if (needs_invalidation) CPU_SetSegGeneral(fs,0); - - needs_invalidation=false; - if (!cpu.gdt.GetDescriptor(SegValue(gs),desc)) needs_invalidation=true; - else switch (desc.Type()) { - case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (cpu.cpl>desc.DPL()) needs_invalidation=true; break; - default: break; } - if (needs_invalidation) CPU_SetSegGeneral(gs,0); -} - - -class TaskStateSegment { -public: - TaskStateSegment() { - valid=false; - } - bool IsValid(void) { - return valid; - } - Bitu Get_back(void) { - cpu.mpl=0; - Bit16u backlink=mem_readw(base); - cpu.mpl=3; - return backlink; - } - void SaveSelector(void) { - cpu.gdt.SetDescriptor(selector,desc); - } - void Get_SSx_ESPx(Bitu level,Bitu & _ss,Bitu & _esp) { - cpu.mpl=0; - if (is386) { - PhysPt where=base+offsetof(TSS_32,esp0)+level*8; - _esp=mem_readd(where); - _ss=mem_readw(where+4); - } else { - PhysPt where=base+offsetof(TSS_16,sp0)+level*4; - _esp=mem_readw(where); - _ss=mem_readw(where+2); - } - cpu.mpl=3; - } - bool SetSelector(Bitu new_sel) { - valid=false; - if ((new_sel & 0xfffc)==0) { - selector=0; - base=0; - limit=0; - is386=1; - return true; - } - if (new_sel&4) return false; - if (!cpu.gdt.GetDescriptor(new_sel,desc)) return false; - switch (desc.Type()) { - case DESC_286_TSS_A: case DESC_286_TSS_B: - case DESC_386_TSS_A: case DESC_386_TSS_B: - break; - default: - return false; - } - if (!desc.saved.seg.p) return false; - selector=new_sel; - valid=true; - base=desc.GetBase(); - limit=desc.GetLimit(); - is386=desc.Is386(); - return true; - } - TSS_Descriptor desc; - Bitu selector; - PhysPt base; - Bitu limit; - Bitu is386; - bool valid; -}; - -TaskStateSegment cpu_tss; - -enum TSwitchType { - TSwitch_JMP,TSwitch_CALL_INT,TSwitch_IRET -}; - -bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype,Bitu old_eip) { - FillFlags(); - TaskStateSegment new_tss; - if (!new_tss.SetSelector(new_tss_selector)) - E_Exit("Illegal TSS for switch, selector=%x, switchtype=%x",new_tss_selector,tstype); - if (tstype==TSwitch_IRET) { - if (!new_tss.desc.IsBusy()) - E_Exit("TSS not busy for IRET"); - } else { - if (new_tss.desc.IsBusy()) - E_Exit("TSS busy for JMP/CALL/INT"); - } - Bitu new_cr3=0; - Bitu new_eax,new_ebx,new_ecx,new_edx,new_esp,new_ebp,new_esi,new_edi; - Bitu new_es,new_cs,new_ss,new_ds,new_fs,new_gs; - Bitu new_ldt,new_eip,new_eflags; - /* Read new context from new TSS */ - if (new_tss.is386) { - new_cr3=mem_readd(new_tss.base+offsetof(TSS_32,cr3)); - new_eip=mem_readd(new_tss.base+offsetof(TSS_32,eip)); - new_eflags=mem_readd(new_tss.base+offsetof(TSS_32,eflags)); - new_eax=mem_readd(new_tss.base+offsetof(TSS_32,eax)); - new_ecx=mem_readd(new_tss.base+offsetof(TSS_32,ecx)); - new_edx=mem_readd(new_tss.base+offsetof(TSS_32,edx)); - new_ebx=mem_readd(new_tss.base+offsetof(TSS_32,ebx)); - new_esp=mem_readd(new_tss.base+offsetof(TSS_32,esp)); - new_ebp=mem_readd(new_tss.base+offsetof(TSS_32,ebp)); - new_edi=mem_readd(new_tss.base+offsetof(TSS_32,edi)); - new_esi=mem_readd(new_tss.base+offsetof(TSS_32,esi)); - - new_es=mem_readw(new_tss.base+offsetof(TSS_32,es)); - new_cs=mem_readw(new_tss.base+offsetof(TSS_32,cs)); - new_ss=mem_readw(new_tss.base+offsetof(TSS_32,ss)); - new_ds=mem_readw(new_tss.base+offsetof(TSS_32,ds)); - new_fs=mem_readw(new_tss.base+offsetof(TSS_32,fs)); - new_gs=mem_readw(new_tss.base+offsetof(TSS_32,gs)); - new_ldt=mem_readw(new_tss.base+offsetof(TSS_32,ldt)); - } else { - E_Exit("286 task switch"); - new_cr3=0; - new_eip=0; - new_eflags=0; - new_eax=0; new_ecx=0; new_edx=0; new_ebx=0; - new_esp=0; new_ebp=0; new_edi=0; new_esi=0; - - new_es=0; new_cs=0; new_ss=0; new_ds=0; new_fs=0; new_gs=0; - new_ldt=0; - } - - /* Check if we need to clear busy bit of old TASK */ - if (tstype==TSwitch_JMP || tstype==TSwitch_IRET) { - cpu_tss.desc.SetBusy(false); - cpu_tss.SaveSelector(); - } - Bit32u old_flags = reg_flags; - if (tstype==TSwitch_IRET) old_flags &= (~FLAG_NT); - - /* Save current context in current TSS */ - if (cpu_tss.is386) { - mem_writed(cpu_tss.base+offsetof(TSS_32,eflags),old_flags); - mem_writed(cpu_tss.base+offsetof(TSS_32,eip),old_eip); - - mem_writed(cpu_tss.base+offsetof(TSS_32,eax),reg_eax); - mem_writed(cpu_tss.base+offsetof(TSS_32,ecx),reg_ecx); - mem_writed(cpu_tss.base+offsetof(TSS_32,edx),reg_edx); - mem_writed(cpu_tss.base+offsetof(TSS_32,ebx),reg_ebx); - mem_writed(cpu_tss.base+offsetof(TSS_32,esp),reg_esp); - mem_writed(cpu_tss.base+offsetof(TSS_32,ebp),reg_ebp); - mem_writed(cpu_tss.base+offsetof(TSS_32,esi),reg_esi); - mem_writed(cpu_tss.base+offsetof(TSS_32,edi),reg_edi); - - mem_writed(cpu_tss.base+offsetof(TSS_32,es),SegValue(es)); - mem_writed(cpu_tss.base+offsetof(TSS_32,cs),SegValue(cs)); - mem_writed(cpu_tss.base+offsetof(TSS_32,ss),SegValue(ss)); - mem_writed(cpu_tss.base+offsetof(TSS_32,ds),SegValue(ds)); - mem_writed(cpu_tss.base+offsetof(TSS_32,fs),SegValue(fs)); - mem_writed(cpu_tss.base+offsetof(TSS_32,gs),SegValue(gs)); - } else { - E_Exit("286 task switch"); - } - - /* Setup a back link to the old TSS in new TSS */ - if (tstype==TSwitch_CALL_INT) { - if (new_tss.is386) { - mem_writed(new_tss.base+offsetof(TSS_32,back),cpu_tss.selector); - } else { - mem_writew(new_tss.base+offsetof(TSS_16,back),cpu_tss.selector); - } - /* And make the new task's eflag have the nested task bit */ - new_eflags|=FLAG_NT; - } - /* Set the busy bit in the new task */ - if (tstype==TSwitch_JMP || tstype==TSwitch_CALL_INT) { - new_tss.desc.SetBusy(true); - new_tss.SaveSelector(); - } - -// cpu.cr0|=CR0_TASKSWITCHED; - if (new_tss_selector == cpu_tss.selector) { - reg_eip = old_eip; - new_cs = SegValue(cs); - new_ss = SegValue(ss); - new_ds = SegValue(ds); - new_es = SegValue(es); - new_fs = SegValue(fs); - new_gs = SegValue(gs); - } else { - - /* Setup the new cr3 */ - PAGING_SetDirBase(new_cr3); - - /* Load new context */ - if (new_tss.is386) { - reg_eip=new_eip; - CPU_SetFlags(new_eflags,FMASK_ALL | FLAG_VM); - reg_eax=new_eax; - reg_ecx=new_ecx; - reg_edx=new_edx; - reg_ebx=new_ebx; - reg_esp=new_esp; - reg_ebp=new_ebp; - reg_edi=new_edi; - reg_esi=new_esi; - -// new_cs=mem_readw(new_tss.base+offsetof(TSS_32,cs)); - } else { - E_Exit("286 task switch"); - } - } - /* Load the new selectors */ - if (reg_flags & FLAG_VM) { - SegSet16(cs,new_cs); - cpu.code.big=false; - cpu.cpl=3; //We don't have segment caches so this will do - } else { - /* Protected mode task */ - if (new_ldt!=0) CPU_LLDT(new_ldt); - /* Load the new CS*/ - Descriptor cs_desc; - cpu.cpl=new_cs & 3; - if (!cpu.gdt.GetDescriptor(new_cs,cs_desc)) - E_Exit("Task switch with CS beyond limits"); - if (!cs_desc.saved.seg.p) - E_Exit("Task switch with non present code-segment"); - switch (cs_desc.Type()) { - case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: - case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (cpu.cpl != cs_desc.DPL()) E_Exit("Task CS RPL != DPL"); - goto doconforming; - case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: - case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: - if (cpu.cpl < cs_desc.DPL()) E_Exit("Task CS RPL < DPL"); -doconforming: - Segs.phys[cs]=cs_desc.GetBase(); - cpu.code.big=cs_desc.Big()>0; - Segs.val[cs]=new_cs; - break; - default: - E_Exit("Task switch CS Type %d",cs_desc.Type()); - } - } - CPU_SetSegGeneral(es,new_es); - CPU_SetSegGeneral(ss,new_ss); - CPU_SetSegGeneral(ds,new_ds); - CPU_SetSegGeneral(fs,new_fs); - CPU_SetSegGeneral(gs,new_gs); - if (!cpu_tss.SetSelector(new_tss_selector)) { - LOG(LOG_CPU,LOG_NORMAL)("TaskSwitch: set tss selector %X failed",new_tss_selector); - } -// cpu_tss.desc.SetBusy(true); -// cpu_tss.SaveSelector(); -// LOG_MSG("Task CPL %X CS:%X IP:%X SS:%X SP:%X eflags %x",cpu.cpl,SegValue(cs),reg_eip,SegValue(ss),reg_esp,reg_flags); - return true; -} - -bool CPU_IO_Exception(Bitu port,Bitu size) { - if (cpu.pmode && ((GETFLAG_IOPLcpu_tss.limit) goto doexception; - bwhere=cpu_tss.base+ofs+(port/8); - Bitu map=mem_readw(bwhere); - Bitu mask=(0xffff>>(16-size)) << (port&7); - if (map & mask) goto doexception; - cpu.mpl=3; - } - return false; -doexception: - cpu.mpl=3; - LOG(LOG_CPU,LOG_NORMAL)("IO Exception port %X",port); - return CPU_PrepareException(EXCEPTION_GP,0); -} - -void CPU_Exception(Bitu which,Bitu error ) { -// LOG_MSG("Exception %d error %x",which,error); - cpu.exception.error=error; - CPU_Interrupt(which,CPU_INT_EXCEPTION | ((which>=8) ? CPU_INT_HAS_ERROR : 0),reg_eip); -} - -Bit8u lastint; -void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) { - lastint=num; - FillFlags(); -#if C_DEBUG - switch (num) { - case 0xcd: -#if C_HEAVY_DEBUG - LOG(LOG_CPU,LOG_ERROR)("Call to interrupt 0xCD this is BAD"); - DEBUG_HeavyWriteLogInstruction(); - E_Exit("Call to interrupt 0xCD this is BAD"); -#endif - break; - case 0x03: - if (DEBUG_Breakpoint()) { - CPU_Cycles=0; - return; - } - }; -#endif - if (!cpu.pmode) { - /* Save everything on a 16-bit stack */ - CPU_Push16(reg_flags & 0xffff); - CPU_Push16(SegValue(cs)); - CPU_Push16(oldeip); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - /* Get the new CS:IP from vector table */ - PhysPt base=cpu.idt.GetBase(); - reg_eip=mem_readw(base+(num << 2)); - Segs.val[cs]=mem_readw(base+(num << 2)+2); - Segs.phys[cs]=Segs.val[cs]<<4; - cpu.code.big=false; - return; - } else { - /* Protected Mode Interrupt */ - if ((reg_flags & FLAG_VM) && (type&CPU_INT_SOFTWARE) && !(type&CPU_INT_NOIOPLCHECK)) { -// LOG_MSG("Software int in v86, AH %X IOPL %x",reg_ah,(reg_flags & FLAG_IOPL) >>12); - if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { - CPU_Exception(EXCEPTION_GP,0); - return; - } - } - - Descriptor gate; - if (!cpu.idt.GetDescriptor(num<<3,gate)) { - // zone66 - CPU_Exception(EXCEPTION_GP,num*8+2+(type&CPU_INT_SOFTWARE)?0:1); - return; - } - - if ((type&CPU_INT_SOFTWARE) && (gate.DPL()cpu.cpl, - "Interrupt to higher privilege", - EXCEPTION_GP,(gate_sel & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1) - switch (cs_desc.Type()) { - case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: - case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (cs_dpl0", - EXCEPTION_GP,gate_sel & 0xfffc) - - Bitu n_ss,n_esp; - Bitu o_ss,o_esp; - o_ss=SegValue(ss); - o_esp=reg_esp; - cpu_tss.Get_SSx_ESPx(cs_dpl,n_ss,n_esp); - CPU_CHECK_COND((n_ss & 0xfffc)==0, - "INT:Gate with SS zero selector", - EXCEPTION_TS,(type&CPU_INT_SOFTWARE)?0:1) - Descriptor n_ss_desc; - CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_ss,n_ss_desc), - "INT:Gate with SS beyond limit", - EXCEPTION_TS,(n_ss & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1) - CPU_CHECK_COND(((n_ss & 3)!=cs_dpl) || (n_ss_desc.DPL()!=cs_dpl), - "INT:Inner level with CS_DPL!=SS_DPL and SS_RPL", - EXCEPTION_TS,(n_ss & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1) - - // check if stack segment is a writable data segment - switch (n_ss_desc.Type()) { - case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - break; - default: - E_Exit("INT:Inner level:Stack segment not writable."); // or #TS(ss_sel+EXT) - } - CPU_CHECK_COND(!n_ss_desc.saved.seg.p, - "INT:Inner level with nonpresent SS", - EXCEPTION_SS,(n_ss & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1) - - // commit point - Segs.phys[ss]=n_ss_desc.GetBase(); - Segs.val[ss]=n_ss; - if (n_ss_desc.Big()) { - cpu.stack.big=true; - cpu.stack.mask=0xffffffff; - cpu.stack.notmask=0; - reg_esp=n_esp; - } else { - cpu.stack.big=false; - cpu.stack.mask=0xffff; - cpu.stack.notmask=0xffff0000; - reg_sp=n_esp & 0xffff; - } - - cpu.cpl=cs_dpl; - if (gate.Type() & 0x8) { /* 32-bit Gate */ - if (reg_flags & FLAG_VM) { - CPU_Push32(SegValue(gs));SegSet16(gs,0x0); - CPU_Push32(SegValue(fs));SegSet16(fs,0x0); - CPU_Push32(SegValue(ds));SegSet16(ds,0x0); - CPU_Push32(SegValue(es));SegSet16(es,0x0); - } - CPU_Push32(o_ss); - CPU_Push32(o_esp); - } else { /* 16-bit Gate */ - if (reg_flags & FLAG_VM) E_Exit("V86 to 16-bit gate"); - CPU_Push16(o_ss); - CPU_Push16(o_esp); - } -// LOG_MSG("INT:Gate to inner level SS:%X SP:%X",n_ss,n_esp); - goto do_interrupt; - } - if (cs_dpl!=cpu.cpl) - E_Exit("Non-conforming intra privilege INT with DPL!=CPL"); - case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: - case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: - /* Prepare stack for gate to same priviledge */ - CPU_CHECK_COND(!cs_desc.saved.seg.p, - "INT:Same level:CS segment not present", - EXCEPTION_NP,(gate_sel & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1) - if ((reg_flags & FLAG_VM) && (cs_dpl0; - reg_eip=gate_off; - - if (!(gate.Type()&1)) { - SETFLAGBIT(IF,false); - } - SETFLAGBIT(TF,false); - SETFLAGBIT(NT,false); - SETFLAGBIT(VM,false); - LOG(LOG_CPU,LOG_NORMAL)("INT:Gate to %X:%X big %d %s",gate_sel,gate_off,cs_desc.Big(),gate.Type() & 0x8 ? "386" : "286"); - return; - } - case DESC_TASK_GATE: - CPU_CHECK_COND(!gate.saved.seg.p, - "INT:Gate segment not present", - EXCEPTION_NP,num*8+2+(type&CPU_INT_SOFTWARE)?0:1) - - CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT,oldeip); - if (type & CPU_INT_HAS_ERROR) { - //TODO Be sure about this, seems somewhat unclear - if (cpu_tss.is386) CPU_Push32(cpu.exception.error); - else CPU_Push16(cpu.exception.error); - } - return; - default: - E_Exit("Illegal descriptor type %X for int %X",gate.Type(),num); - } - } - assert(1); - return ; // make compiler happy -} - - -void CPU_IRET(bool use32,Bitu oldeip) { - if (!cpu.pmode) { /* RealMode IRET */ - if (use32) { - reg_eip=CPU_Pop32(); - SegSet16(cs,CPU_Pop32()); - CPU_SetFlags(CPU_Pop32(),FMASK_ALL); - } else { - reg_eip=CPU_Pop16(); - SegSet16(cs,CPU_Pop16()); - CPU_SetFlags(CPU_Pop16(),FMASK_ALL & 0xffff); - } - cpu.code.big=false; - DestroyConditionFlags(); - return; - } else { /* Protected mode IRET */ - if (reg_flags & FLAG_VM) { - if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { - // win3.x e - CPU_Exception(EXCEPTION_GP,0); - return; - } else { - if (use32) { - Bit32u new_eip=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - Bit32u tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask); - Bit32u new_cs=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)); - tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask); - Bit32u new_flags=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)); - reg_esp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask); - - reg_eip=new_eip; - SegSet16(cs,(Bit16u)(new_cs&0xffff)); - /* IOPL can not be modified in v86 mode by IRET */ - CPU_SetFlags(new_flags,FMASK_NORMAL|FLAG_NT); - } else { - Bit16u new_eip=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - Bit32u tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask); - Bit16u new_cs=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask)); - tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask); - Bit16u new_flags=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask)); - reg_esp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask); - - reg_eip=(Bit32u)new_eip; - SegSet16(cs,new_cs); - /* IOPL can not be modified in v86 mode by IRET */ - CPU_SetFlags(new_flags,FMASK_NORMAL|FLAG_NT); - } - cpu.code.big=false; - DestroyConditionFlags(); - return; - } - } - /* Check if this is task IRET */ - if (GETFLAG(NT)) { - if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set"); - CPU_CHECK_COND(!cpu_tss.IsValid(), - "TASK Iret without valid TSS", - EXCEPTION_TS,cpu_tss.selector & 0xfffc) - if (!cpu_tss.desc.IsBusy()) { - LOG(LOG_CPU,LOG_ERROR)("TASK Iret:TSS not busy"); - } - Bitu back_link=cpu_tss.Get_back(); - CPU_SwitchTask(back_link,TSwitch_IRET,oldeip); - return; - } - Bitu n_cs_sel,n_eip,n_flags; - Bit32u tempesp; - if (use32) { - n_eip=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask); - n_cs_sel=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)) & 0xffff; - tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask); - n_flags=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)); - tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask); - - if ((n_flags & FLAG_VM) && (cpu.cpl==0)) { - // commit point - reg_esp=tempesp; - reg_eip=n_eip & 0xffff; - Bitu n_ss,n_esp,n_es,n_ds,n_fs,n_gs; - n_esp=CPU_Pop32(); - n_ss=CPU_Pop32() & 0xffff; - n_es=CPU_Pop32() & 0xffff; - n_ds=CPU_Pop32() & 0xffff; - n_fs=CPU_Pop32() & 0xffff; - n_gs=CPU_Pop32() & 0xffff; - - CPU_SetFlags(n_flags,FMASK_ALL | FLAG_VM); - DestroyConditionFlags(); - cpu.cpl=3; - - CPU_SetSegGeneral(ss,n_ss); - CPU_SetSegGeneral(es,n_es); - CPU_SetSegGeneral(ds,n_ds); - CPU_SetSegGeneral(fs,n_fs); - CPU_SetSegGeneral(gs,n_gs); - reg_esp=n_esp; - cpu.code.big=false; - SegSet16(cs,n_cs_sel); - LOG(LOG_CPU,LOG_NORMAL)("IRET:Back to V86: CS:%X IP %X SS:%X SP %X FLAGS:%X",SegValue(cs),reg_eip,SegValue(ss),reg_esp,reg_flags); - return; - } - if (n_flags & FLAG_VM) E_Exit("IRET from pmode to v86 with CPL!=0"); - } else { - n_eip=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask); - n_cs_sel=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask)); - tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask); - n_flags=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask)); - n_flags|=(reg_flags & 0xffff0000); - tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask); - - if (n_flags & FLAG_VM) E_Exit("VM Flag in 16-bit iret"); - } - CPU_CHECK_COND((n_cs_sel & 0xfffc)==0, - "IRET:CS selector zero", - EXCEPTION_GP,0) - Bitu n_cs_rpl=n_cs_sel & 3; - Descriptor n_cs_desc; - CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc), - "IRET:CS selector beyond limits", - EXCEPTION_GP,n_cs_sel & 0xfffc) - CPU_CHECK_COND(n_cs_rpln_cs_rpl, - "IRET:C:DPL>RPL", - EXCEPTION_GP,n_cs_sel & 0xfffc) - break; - default: - E_Exit("IRET:Illegal descriptor type %X",n_cs_desc.Type()); - } - CPU_CHECK_COND(!n_cs_desc.saved.seg.p, - "IRET with nonpresent code segment", - EXCEPTION_NP,n_cs_sel & 0xfffc) - - if (n_cs_rpl==cpu.cpl) { - /* Return to same level */ - - // commit point - reg_esp=tempesp; - Segs.phys[cs]=n_cs_desc.GetBase(); - cpu.code.big=n_cs_desc.Big()>0; - Segs.val[cs]=n_cs_sel; - reg_eip=n_eip; - - Bitu mask=cpu.cpl ? (FMASK_NORMAL | FLAG_NT) : FMASK_ALL; - if (GETFLAG_IOPL0; - Segs.val[cs]=n_cs_sel; - - Bitu mask=cpu.cpl ? (FMASK_NORMAL | FLAG_NT) : FMASK_ALL; - if (GETFLAG_IOPLcpu.cpl, - "JMP:NC:RPL>CPL", - EXCEPTION_GP,selector & 0xfffc) - CPU_CHECK_COND(cpu.cpl!=desc.DPL(), - "JMP:NC:RPL != DPL", - EXCEPTION_GP,selector & 0xfffc) - LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:NC to %X:%X big %d",selector,offset,desc.Big()); - goto CODE_jmp; - case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: - case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: - LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:C to %X:%X big %d",selector,offset,desc.Big()); - CPU_CHECK_COND(cpu.cpl0; - Segs.val[cs]=(selector & 0xfffc) | cpu.cpl; - reg_eip=offset; - return; - case DESC_386_TSS_A: - CPU_CHECK_COND(desc.DPL()cpu.cpl, - "CALL:CODE:NC:RPL>CPL", - EXCEPTION_GP,selector & 0xfffc) - CPU_CHECK_COND(call.DPL()!=cpu.cpl, - "CALL:CODE:NC:DPL!=CPL", - EXCEPTION_GP,selector & 0xfffc) - LOG(LOG_CPU,LOG_NORMAL)("CALL:CODE:NC to %X:%X",selector,offset); - goto call_code; - case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA: - case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA: - CPU_CHECK_COND(call.DPL()>cpu.cpl, - "CALL:CODE:C:DPL>CPL", - EXCEPTION_GP,selector & 0xfffc) - LOG(LOG_CPU,LOG_NORMAL)("CALL:CODE:C to %X:%X",selector,offset); -call_code: - if (!call.saved.seg.p) { - // borland extender (RTM) - CPU_Exception(EXCEPTION_NP,selector & 0xfffc); - return; - } - // commit point - if (!use32) { - CPU_Push16(SegValue(cs)); - CPU_Push16(oldeip); - reg_eip=offset & 0xffff; - } else { - CPU_Push32(SegValue(cs)); - CPU_Push32(oldeip); - reg_eip=offset; - } - Segs.phys[cs]=call.GetBase(); - cpu.code.big=call.Big()>0; - Segs.val[cs]=(selector & 0xfffc) | cpu.cpl; - return; - case DESC_386_CALL_GATE: - case DESC_286_CALL_GATE: - { - CPU_CHECK_COND(call.DPL()cpu.cpl, - "CALL:Gate:CS DPL>CPL", - EXCEPTION_GP,n_cs_sel & 0xfffc) - - CPU_CHECK_COND(!n_cs_desc.saved.seg.p, - "CALL:Gate:CS not present", - EXCEPTION_NP,n_cs_sel & 0xfffc) - - Bitu n_eip = call.GetOffset(); - switch (n_cs_desc.Type()) { - case DESC_CODE_N_NC_A:case DESC_CODE_N_NC_NA: - case DESC_CODE_R_NC_A:case DESC_CODE_R_NC_NA: - /* Check if we goto inner priviledge */ - if (n_cs_dpl < cpu.cpl) { - /* Get new SS:ESP out of TSS */ - Bitu n_ss_sel,n_esp; - Descriptor n_ss_desc; - cpu_tss.Get_SSx_ESPx(n_cs_dpl,n_ss_sel,n_esp); - CPU_CHECK_COND((n_ss_sel & 0xfffc)==0, - "CALL:Gate:NC:SS selector zero", - EXCEPTION_TS,0) - CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_ss_sel,n_ss_desc), - "CALL:Gate:Invalid SS selector", - EXCEPTION_TS,n_ss_sel & 0xfffc) - CPU_CHECK_COND(((n_ss_sel & 3)!=n_cs_desc.DPL()) || (n_ss_desc.DPL()!=n_cs_desc.DPL()), - "CALL:Gate:Invalid SS selector privileges", - EXCEPTION_TS,n_ss_sel & 0xfffc) - - switch (n_ss_desc.Type()) { - case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - // writable data segment - break; - default: - E_Exit("Call:Gate:SS no writable data segment"); // or #TS(ss_sel) - } - CPU_CHECK_COND(!n_ss_desc.saved.seg.p, - "CALL:Gate:Stack segment not present", - EXCEPTION_SS,n_ss_sel & 0xfffc) - - /* Load the new SS:ESP and save data on it */ - Bitu o_esp = reg_esp; - Bitu o_ss = SegValue(ss); - PhysPt o_stack = SegPhys(ss)+(reg_esp & cpu.stack.mask); - - - // catch pagefaults - if (call.saved.gate.paramcount&31) { - if (call.Type()==DESC_386_CALL_GATE) { - for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) - mem_readd(o_stack+i*4); - } else { - for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) - mem_readw(o_stack+i*2); - } - } - - // commit point - Segs.val[ss]=n_ss_sel; - Segs.phys[ss]=n_ss_desc.GetBase(); - if (n_ss_desc.Big()) { - cpu.stack.big=true; - cpu.stack.mask=0xffffffff; - cpu.stack.notmask=0; - reg_esp=n_esp; - } else { - cpu.stack.big=false; - cpu.stack.mask=0xffff; - cpu.stack.notmask=0xffff0000; - reg_sp=n_esp & 0xffff; - } - - cpu.cpl = n_cs_desc.DPL(); - Bit16u oldcs = SegValue(cs); - /* Switch to new CS:EIP */ - Segs.phys[cs] = n_cs_desc.GetBase(); - Segs.val[cs] = (n_cs_sel & 0xfffc) | cpu.cpl; - cpu.code.big = n_cs_desc.Big()>0; - reg_eip = n_eip; - if (!use32) reg_eip&=0xffff; - - if (call.Type()==DESC_386_CALL_GATE) { - CPU_Push32(o_ss); //save old stack - CPU_Push32(o_esp); - if (call.saved.gate.paramcount&31) - for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) - CPU_Push32(mem_readd(o_stack+i*4)); - CPU_Push32(oldcs); - CPU_Push32(oldeip); - } else { - CPU_Push16(o_ss); //save old stack - CPU_Push16(o_esp); - if (call.saved.gate.paramcount&31) - for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) - CPU_Push16(mem_readw(o_stack+i*2)); - CPU_Push16(oldcs); - CPU_Push16(oldeip); - } - - break; - } else if (n_cs_dpl > cpu.cpl) - E_Exit("CALL:GATE:CS DPL>CPL"); // or #GP(sel) - case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA: - case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA: - // zrdx extender - - if (call.Type()==DESC_386_CALL_GATE) { - CPU_Push32(SegValue(cs)); - CPU_Push32(oldeip); - } else { - CPU_Push16(SegValue(cs)); - CPU_Push16(oldeip); - } - - /* Switch to new CS:EIP */ - Segs.phys[cs] = n_cs_desc.GetBase(); - Segs.val[cs] = (n_cs_sel & 0xfffc) | cpu.cpl; - cpu.code.big = n_cs_desc.Big()>0; - reg_eip = n_eip; - if (!use32) reg_eip&=0xffff; - break; - default: - E_Exit("CALL:GATE:CS no executable segment"); - } - } /* Call Gates */ - break; - case DESC_386_TSS_A: - CPU_CHECK_COND(call.DPL()cpu.cpl, - "RET to C segment of higher privilege", - EXCEPTION_GP,selector & 0xfffc) - break; - default: - E_Exit("RET from illegal descriptor type %X",desc.Type()); - } -RET_same_level: - if (!desc.saved.seg.p) { - // borland extender (RTM) - CPU_Exception(EXCEPTION_NP,selector & 0xfffc); - return; - } - - // commit point - if (!use32) { - offset=CPU_Pop16(); - selector=CPU_Pop16(); - } else { - offset=CPU_Pop32(); - selector=CPU_Pop32() & 0xffff; - } - - Segs.phys[cs]=desc.GetBase(); - cpu.code.big=desc.Big()>0; - Segs.val[cs]=selector; - reg_eip=offset; - if (cpu.stack.big) { - reg_esp+=bytes; - } else { - reg_sp+=bytes; - } - LOG(LOG_CPU,LOG_NORMAL)("RET - Same level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL()); - return; - } else { - /* Return to outer level */ - switch (desc.Type()) { - case DESC_CODE_N_NC_A:case DESC_CODE_N_NC_NA: - case DESC_CODE_R_NC_A:case DESC_CODE_R_NC_NA: - CPU_CHECK_COND(desc.DPL()!=rpl, - "RET to outer NC segment with DPL!=RPL", - EXCEPTION_GP,selector & 0xfffc) - break; - case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA: - case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA: - CPU_CHECK_COND(desc.DPL()>rpl, - "RET to outer C segment with DPL>RPL", - EXCEPTION_GP,selector & 0xfffc) - break; - default: - E_Exit("RET from illegal descriptor type %X",desc.Type()); // or #GP(selector) - } - - CPU_CHECK_COND(!desc.saved.seg.p, - "RET:Outer level:CS not present", - EXCEPTION_NP,selector & 0xfffc) - - // commit point - Bitu n_esp,n_ss; - if (use32) { - offset=CPU_Pop32(); - selector=CPU_Pop32() & 0xffff; - reg_esp+=bytes; - n_esp = CPU_Pop32(); - n_ss = CPU_Pop32() & 0xffff; - } else { - offset=CPU_Pop16(); - selector=CPU_Pop16(); - reg_esp+=bytes; - n_esp = CPU_Pop16(); - n_ss = CPU_Pop16(); - } - - CPU_CHECK_COND((n_ss & 0xfffc)==0, - "RET to outer level with SS selector zero", - EXCEPTION_GP,0) - - Descriptor n_ss_desc; - CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_ss,n_ss_desc), - "RET:SS beyond limits", - EXCEPTION_GP,n_ss & 0xfffc) - - CPU_CHECK_COND(((n_ss & 3)!=rpl) || (n_ss_desc.DPL()!=rpl), - "RET to outer segment with invalid SS privileges", - EXCEPTION_GP,n_ss & 0xfffc) - switch (n_ss_desc.Type()) { - case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - break; - default: - E_Exit("RET:SS selector type no writable data segment"); // or #GP(selector) - } - CPU_CHECK_COND(!n_ss_desc.saved.seg.p, - "RET:Stack segment not present", - EXCEPTION_SS,n_ss & 0xfffc) - - cpu.cpl = rpl; - Segs.phys[cs]=desc.GetBase(); - cpu.code.big=desc.Big()>0; - Segs.val[cs]=(selector&0xfffc) | cpu.cpl; - reg_eip=offset; - - Segs.val[ss]=n_ss; - Segs.phys[ss]=n_ss_desc.GetBase(); - if (n_ss_desc.Big()) { - cpu.stack.big=true; - cpu.stack.mask=0xffffffff; - cpu.stack.notmask=0; - reg_esp=n_esp+bytes; - } else { - cpu.stack.big=false; - cpu.stack.mask=0xffff; - cpu.stack.notmask=0xffff0000; - reg_sp=(n_esp & 0xffff)+bytes; - } - - CPU_CheckSegments(); - -// LOG(LOG_MISC,LOG_ERROR)("RET - Higher level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL()); - return; - } - LOG(LOG_CPU,LOG_NORMAL)("Prot ret %X:%X",selector,offset); - return; - } - assert(1); -} - - -Bitu CPU_SLDT(void) { - return cpu.gdt.SLDT(); -} - -bool CPU_LLDT(Bitu selector) { - if (!cpu.gdt.LLDT(selector)) { - LOG(LOG_CPU,LOG_ERROR)("LLDT failed, selector=%X",selector); - return true; - } - LOG(LOG_CPU,LOG_NORMAL)("LDT Set to %X",selector); - return false; -} - -Bitu CPU_STR(void) { - return cpu_tss.selector; -} - -bool CPU_LTR(Bitu selector) { - if ((selector & 0xfffc)==0) { - cpu_tss.SetSelector(selector); - return false; - } - TSS_Descriptor desc; - if ((selector & 4) || (!cpu.gdt.GetDescriptor(selector,desc))) { - LOG(LOG_CPU,LOG_ERROR)("LTR failed, selector=%X",selector); - return CPU_PrepareException(EXCEPTION_GP,selector); - } - - if ((desc.Type()==DESC_286_TSS_A) || (desc.Type()==DESC_386_TSS_A)) { - if (!desc.saved.seg.p) { - LOG(LOG_CPU,LOG_ERROR)("LTR failed, selector=%X (not present)",selector); - return CPU_PrepareException(EXCEPTION_NP,selector); - } - if (!cpu_tss.SetSelector(selector)) E_Exit("LTR failed, selector=%X",selector); - cpu_tss.desc.SetBusy(true); - cpu_tss.SaveSelector(); - } else { - /* Descriptor was no available TSS descriptor */ - LOG(LOG_CPU,LOG_NORMAL)("LTR failed, selector=%X (type=%X)",selector,desc.Type()); - return CPU_PrepareException(EXCEPTION_GP,selector); - } - return false; -} - -void CPU_LGDT(Bitu limit,Bitu base) { - LOG(LOG_CPU,LOG_NORMAL)("GDT Set to base:%X limit:%X",base,limit); - cpu.gdt.SetLimit(limit); - cpu.gdt.SetBase(base); -} - -void CPU_LIDT(Bitu limit,Bitu base) { - LOG(LOG_CPU,LOG_NORMAL)("IDT Set to base:%X limit:%X",base,limit); - cpu.idt.SetLimit(limit); - cpu.idt.SetBase(base); -} - -Bitu CPU_SGDT_base(void) { - return cpu.gdt.GetBase(); -} -Bitu CPU_SGDT_limit(void) { - return cpu.gdt.GetLimit(); -} - -Bitu CPU_SIDT_base(void) { - return cpu.idt.GetBase(); -} -Bitu CPU_SIDT_limit(void) { - return cpu.idt.GetLimit(); -} - - -void CPU_SET_CRX(Bitu cr,Bitu value) { - switch (cr) { - case 0: - { - Bitu changed=cpu.cr0 ^ value; - if (!changed) return; - cpu.cr0=value; - if (value & CR0_PROTECTION) { - cpu.pmode=true; - LOG(LOG_CPU,LOG_NORMAL)("Protected mode"); - PAGING_Enable((value & CR0_PAGING)>0); - - if (!(CPU_AutoDetermineMode&CPU_AUTODETERMINE_MASK)) break; - - if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CYCLES) { - CPU_CycleAutoAdjust=true; - CPU_CycleLeft=0; - CPU_Cycles=0; - CPU_OldCycleMax=CPU_CycleMax; - GFX_SetTitle(CPU_CyclePercUsed,-1,false); - } else { - GFX_SetTitle(-1,-1,false); - } -#if (C_DYNAMIC_X86) - if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CORE) { - CPU_Core_Dyn_X86_Cache_Init(true); - cpudecoder=&CPU_Core_Dyn_X86_Run; - } -#elif (C_DYNREC) - if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CORE) { - CPU_Core_Dynrec_Cache_Init(true); - cpudecoder=&CPU_Core_Dynrec_Run; - } -#endif - CPU_AutoDetermineMode<<=CPU_AUTODETERMINE_SHIFT; - } else { - cpu.pmode=false; - if (value & CR0_PAGING) LOG_MSG("Paging requested without PE=1"); - PAGING_Enable(false); - LOG(LOG_CPU,LOG_NORMAL)("Real mode"); - } - break; - } - case 2: - paging.cr2=value; - break; - case 3: - PAGING_SetDirBase(value); - break; - default: - LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV CR%d,%X",cr,value); - break; - } -} - -bool CPU_WRITE_CRX(Bitu cr,Bitu value) { - /* Check if privileged to access control registers */ - if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); - if ((cr==1) || (cr>4)) return CPU_PrepareException(EXCEPTION_UD,0); - if (CPU_ArchitectureType=CPU_ARCHTYPE_PENTIUMSLOW) return cpu.cr0; - else if (CPU_ArchitectureType>=CPU_ARCHTYPE_486OLDSLOW) return (cpu.cr0 & 0xe005003f); - else return (cpu.cr0 | 0x7ffffff0); - case 2: - return paging.cr2; - case 3: - return PAGING_GetDirBase() & 0xfffff000; - default: - LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV XXX, CR%d",cr); - break; - } - return 0; -} - -bool CPU_READ_CRX(Bitu cr,Bit32u & retvalue) { - /* Check if privileged to access control registers */ - if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); - if ((cr==1) || (cr>4)) return CPU_PrepareException(EXCEPTION_UD,0); - retvalue=CPU_GET_CRX(cr); - return false; -} - - -bool CPU_WRITE_DRX(Bitu dr,Bitu value) { - /* Check if privileged to access control registers */ - if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); - switch (dr) { - case 0: - case 1: - case 2: - case 3: - cpu.drx[dr]=value; - break; - case 4: - case 6: - cpu.drx[6]=(value|0xffff0ff0) & 0xffffefff; - break; - case 5: - case 7: - if (CPU_ArchitectureType0)) return CPU_PrepareException(EXCEPTION_GP,0); - switch (dr) { - case 0: - case 1: - case 2: - case 3: - case 6: - case 7: - retvalue=cpu.drx[dr]; - break; - case 4: - retvalue=cpu.drx[6]; - break; - case 5: - retvalue=cpu.drx[7]; - break; - default: - LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV XXX, DR%d",dr); - retvalue=0; - break; - } - return false; -} - -bool CPU_WRITE_TRX(Bitu tr,Bitu value) { - /* Check if privileged to access control registers */ - if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); - switch (tr) { -// case 3: - case 6: - case 7: - cpu.trx[tr]=value; - return false; - default: - LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV TR%d,%X",tr,value); - break; - } - return CPU_PrepareException(EXCEPTION_UD,0); -} - -bool CPU_READ_TRX(Bitu tr,Bit32u & retvalue) { - /* Check if privileged to access control registers */ - if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); - switch (tr) { -// case 3: - case 6: - case 7: - retvalue=cpu.trx[tr]; - return false; - default: - LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV XXX, TR%d",tr); - break; - } - return CPU_PrepareException(EXCEPTION_UD,0); -} - - -Bitu CPU_SMSW(void) { - return cpu.cr0; -} - -bool CPU_LMSW(Bitu word) { - if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); - word&=0xf; - if (cpu.cr0 & 1) word|=1; - word|=(cpu.cr0&0xfffffff0); - CPU_SET_CRX(0,word); - return false; -} - -void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) { - FillFlags(); - if ((dest_sel & 3) < (src_sel & 3)) { - dest_sel=(dest_sel & 0xfffc) + (src_sel & 3); -// dest_sel|=0xff3f0000; - SETFLAGBIT(ZF,true); - } else { - SETFLAGBIT(ZF,false); - } -} - -void CPU_LAR(Bitu selector,Bitu & ar) { - FillFlags(); - if (selector == 0) { - SETFLAGBIT(ZF,false); - return; - } - Descriptor desc;Bitu rpl=selector & 3; - if (!cpu.gdt.GetDescriptor(selector,desc)){ - SETFLAGBIT(ZF,false); - return; - } - switch (desc.Type()){ - case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: - case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: - break; - - case DESC_286_INT_GATE: case DESC_286_TRAP_GATE: { - case DESC_386_INT_GATE: case DESC_386_TRAP_GATE: - SETFLAGBIT(ZF,false); - return; - } - - case DESC_LDT: - case DESC_TASK_GATE: - - case DESC_286_TSS_A: case DESC_286_TSS_B: - case DESC_286_CALL_GATE: - - case DESC_386_TSS_A: case DESC_386_TSS_B: - case DESC_386_CALL_GATE: - - - case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: - case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: - case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: - case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: - case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: - case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (desc.DPL()desc.DPL()) || (cpu.cpl>desc.DPL())) { - // extreme pinball - return CPU_PrepareException(EXCEPTION_GP,value & 0xfffc); - } - break; - case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: - break; - default: - // gabriel knight - return CPU_PrepareException(EXCEPTION_GP,value & 0xfffc); - - } - if (!desc.saved.seg.p) { - // win - return CPU_PrepareException(EXCEPTION_NP,value & 0xfffc); - } - - Segs.val[seg]=value; - Segs.phys[seg]=desc.GetBase(); - } - - return false; - } -} - -bool CPU_PopSeg(SegNames seg,bool use32) { - Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - if (CPU_SetSegGeneral(seg,val)) return true; - Bitu addsp=use32?0x04:0x02; - reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+addsp)&cpu.stack.mask); - return false; -} - -bool CPU_CPUID(void) { - if (CPU_ArchitectureType100) CPU_CyclePercUsed=100; - LOG_MSG("CPU:%d percent",CPU_CyclePercUsed); - GFX_SetTitle(CPU_CyclePercUsed,-1,false); - } else { - Bit32s old_cycles=CPU_CycleMax; - if (CPU_CycleUp < 100) { - CPU_CycleMax = (Bit32s)(CPU_CycleMax * (1 + (float)CPU_CycleUp / 100.0)); - } else { - CPU_CycleMax = (Bit32s)(CPU_CycleMax + CPU_CycleUp); - } - - CPU_CycleLeft=0;CPU_Cycles=0; - if (CPU_CycleMax==old_cycles) CPU_CycleMax++; - LOG_MSG("CPU:%d cycles",CPU_CycleMax); - GFX_SetTitle(CPU_CycleMax,-1,false); - } -} - -static void CPU_CycleDecrease(bool pressed) { - if (!pressed) return; - if (CPU_CycleAutoAdjust) { - CPU_CyclePercUsed-=5; - if (CPU_CyclePercUsed<=0) CPU_CyclePercUsed=1; - LOG_MSG("CPU:%d percent",CPU_CyclePercUsed); - GFX_SetTitle(CPU_CyclePercUsed,-1,false); - } else { - if (CPU_CycleDown < 100) { - CPU_CycleMax = (Bit32s)(CPU_CycleMax / (1 + (float)CPU_CycleDown / 100.0)); - } else { - CPU_CycleMax = (Bit32s)(CPU_CycleMax - CPU_CycleDown); - } - CPU_CycleLeft=0;CPU_Cycles=0; - if (CPU_CycleMax <= 0) CPU_CycleMax=1; - LOG_MSG("CPU:%d cycles",CPU_CycleMax); - GFX_SetTitle(CPU_CycleMax,-1,false); - } -} - -void CPU_Enable_SkipAutoAdjust(void) { - if (CPU_CycleAutoAdjust) { - CPU_CycleMax /= 2; - if (CPU_CycleMax < CPU_CYCLES_LOWER_LIMIT) - CPU_CycleMax = CPU_CYCLES_LOWER_LIMIT; - } - CPU_SkipCycleAutoAdjust=true; -} - -void CPU_Disable_SkipAutoAdjust(void) { - CPU_SkipCycleAutoAdjust=false; -} - - -extern Bit32s ticksDone; -extern Bit32u ticksScheduled; - -void CPU_Reset_AutoAdjust(void) { - CPU_IODelayRemoved = 0; - ticksDone = 0; - ticksScheduled = 0; -} - -class CPU: public Module_base { -private: - static bool inited; -public: - CPU(Section* configuration):Module_base(configuration) { - if(inited) { - Change_Config(configuration); - return; - } -// Section_prop * section=static_cast(configuration); - inited=true; - reg_eax=0; - reg_ebx=0; - reg_ecx=0; - reg_edx=0; - reg_edi=0; - reg_esi=0; - reg_ebp=0; - reg_esp=0; - - SegSet16(cs,0); - SegSet16(ds,0); - SegSet16(es,0); - SegSet16(fs,0); - SegSet16(gs,0); - SegSet16(ss,0); - - CPU_SetFlags(FLAG_IF,FMASK_ALL); //Enable interrupts - cpu.cr0=0xffffffff; - CPU_SET_CRX(0,0); //Initialize - cpu.code.big=false; - cpu.stack.mask=0xffff; - cpu.stack.notmask=0xffff0000; - cpu.stack.big=false; - cpu.trap_skip=false; - cpu.idt.SetBase(0); - cpu.idt.SetLimit(1023); - - for (Bitu i=0; i<7; i++) { - cpu.drx[i]=0; - cpu.trx[i]=0; - } - if (CPU_ArchitectureType==CPU_ARCHTYPE_PENTIUMSLOW) { - cpu.drx[6]=0xffff0ff0; - } else { - cpu.drx[6]=0xffff1ff0; - } - cpu.drx[7]=0x00000400; - - /* Init the cpu cores */ - CPU_Core_Normal_Init(); - CPU_Core_Simple_Init(); - CPU_Core_Full_Init(); -#if (C_DYNAMIC_X86) - CPU_Core_Dyn_X86_Init(); -#elif (C_DYNREC) - CPU_Core_Dynrec_Init(); -#endif - MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles"); - MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup" ,"Inc Cycles"); - Change_Config(configuration); - CPU_JMP(false,0,0,0); //Setup the first cpu core - } - bool Change_Config(Section* newconfig){ - Section_prop * section=static_cast(newconfig); - CPU_AutoDetermineMode=CPU_AUTODETERMINE_NONE; - CPU_CycleLeft=0;//needed ? - CPU_Cycles=0; - CPU_SkipCycleAutoAdjust=false; - - Prop_multival* p = section->Get_multival("cycles"); - std::string type = p->GetSection()->Get_string("type"); - std::string str ; - CommandLine cmd(0,p->GetSection()->Get_string("parameters")); - if (type=="max") { - CPU_CycleMax=0; - CPU_CyclePercUsed=100; - CPU_CycleAutoAdjust=true; - CPU_CycleLimit=-1; - for (Bitu cmdnum=1; cmdnum<=cmd.GetCount(); cmdnum++) { - if (cmd.FindCommand(cmdnum,str)) { - if (str.find('%')==str.length()-1) { - str.erase(str.find('%')); - int percval=0; - std::istringstream stream(str); - stream >> percval; - if ((percval>0) && (percval<=100)) CPU_CyclePercUsed=(Bit32s)percval; - } else if (str=="limit") { - cmdnum++; - if (cmd.FindCommand(cmdnum,str)) { - int cyclimit=0; - std::istringstream stream(str); - stream >> cyclimit; - if (cyclimit>0) CPU_CycleLimit=cyclimit; - } - } - } - } - } else { - if (type=="auto") { - CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CYCLES; - CPU_CycleMax=3000; - CPU_OldCycleMax=3000; - CPU_CyclePercUsed=100; - for (Bitu cmdnum=0; cmdnum<=cmd.GetCount(); cmdnum++) { - if (cmd.FindCommand(cmdnum,str)) { - if (str.find('%')==str.length()-1) { - str.erase(str.find('%')); - int percval=0; - std::istringstream stream(str); - stream >> percval; - if ((percval>0) && (percval<=100)) CPU_CyclePercUsed=(Bit32s)percval; - } else if (str=="limit") { - cmdnum++; - if (cmd.FindCommand(cmdnum,str)) { - int cyclimit=0; - std::istringstream stream(str); - stream >> cyclimit; - if (cyclimit>0) CPU_CycleLimit=cyclimit; - } - } else { - int rmdval=0; - std::istringstream stream(str); - stream >> rmdval; - if (rmdval>0) { - CPU_CycleMax=(Bit32s)rmdval; - CPU_OldCycleMax=(Bit32s)rmdval; - } - } - } - } - } else if(type =="fixed") { - cmd.FindCommand(1,str); - int rmdval=0; - std::istringstream stream(str); - stream >> rmdval; - CPU_CycleMax=(Bit32s)rmdval; - } else { - std::istringstream stream(type); - int rmdval=0; - stream >> rmdval; - if(rmdval) CPU_CycleMax=(Bit32s)rmdval; - } - CPU_CycleAutoAdjust=false; - } - - CPU_CycleUp=section->Get_int("cycleup"); - CPU_CycleDown=section->Get_int("cycledown"); - std::string core(section->Get_string("core")); - cpudecoder=&CPU_Core_Normal_Run; - if (core == "normal") { - cpudecoder=&CPU_Core_Normal_Run; - } else if (core =="simple") { - cpudecoder=&CPU_Core_Simple_Run; - } else if (core == "full") { - cpudecoder=&CPU_Core_Full_Run; - } else if (core == "auto") { - cpudecoder=&CPU_Core_Normal_Run; -#if (C_DYNAMIC_X86) - CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CORE; - } - else if (core == "dynamic") { - cpudecoder=&CPU_Core_Dyn_X86_Run; - CPU_Core_Dyn_X86_SetFPUMode(true); - } else if (core == "dynamic_nodhfpu") { - cpudecoder=&CPU_Core_Dyn_X86_Run; - CPU_Core_Dyn_X86_SetFPUMode(false); -#elif (C_DYNREC) - CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CORE; - } - else if (core == "dynamic") { - cpudecoder=&CPU_Core_Dynrec_Run; -#else - -#endif - } - -#if (C_DYNAMIC_X86) - CPU_Core_Dyn_X86_Cache_Init((core == "dynamic") || (core == "dynamic_nodhfpu")); -#elif (C_DYNREC) - CPU_Core_Dynrec_Cache_Init( core == "dynamic" ); -#endif - - CPU_ArchitectureType = CPU_ARCHTYPE_MIXED; - std::string cputype(section->Get_string("cputype")); - if (cputype == "auto") { - CPU_ArchitectureType = CPU_ARCHTYPE_MIXED; - } else if (cputype == "386") { - CPU_ArchitectureType = CPU_ARCHTYPE_386FAST; - } else if (cputype == "386_prefetch") { - CPU_ArchitectureType = CPU_ARCHTYPE_386FAST; - if (core == "normal") { - cpudecoder=&CPU_Core_Prefetch_Run; - CPU_PrefetchQueueSize = 16; - } else if (core == "auto") { - cpudecoder=&CPU_Core_Prefetch_Run; - CPU_PrefetchQueueSize = 16; - CPU_AutoDetermineMode&=(~CPU_AUTODETERMINE_CORE); - } else { - E_Exit("prefetch queue emulation requires the normal core setting."); - } - } else if (cputype == "386_slow") { - CPU_ArchitectureType = CPU_ARCHTYPE_386SLOW; - } else if (cputype == "486_slow") { - CPU_ArchitectureType = CPU_ARCHTYPE_486NEWSLOW; - } else if (cputype == "486_prefetch") { - CPU_ArchitectureType = CPU_ARCHTYPE_486NEWSLOW; - if (core == "normal") { - cpudecoder=&CPU_Core_Prefetch_Run; - CPU_PrefetchQueueSize = 32; - } else if (core == "auto") { - cpudecoder=&CPU_Core_Prefetch_Run; - CPU_PrefetchQueueSize = 32; - CPU_AutoDetermineMode&=(~CPU_AUTODETERMINE_CORE); - } else { - E_Exit("prefetch queue emulation requires the normal core setting."); - } - } else if (cputype == "pentium_slow") { - CPU_ArchitectureType = CPU_ARCHTYPE_PENTIUMSLOW; - } - - if (CPU_ArchitectureType>=CPU_ARCHTYPE_486NEWSLOW) CPU_flag_id_toggle=FLAG_ID; - else CPU_flag_id_toggle=0; - - - if(CPU_CycleMax <= 0) CPU_CycleMax = 3000; - if(CPU_CycleUp <= 0) CPU_CycleUp = 500; - if(CPU_CycleDown <= 0) CPU_CycleDown = 20; - if (CPU_CycleAutoAdjust) GFX_SetTitle(CPU_CyclePercUsed,-1,false); - else GFX_SetTitle(CPU_CycleMax,-1,false); - return true; - } - ~CPU(){ /* empty */}; -}; - -static CPU * test; - -void CPU_ShutDown(Section* sec) { -#if (C_DYNAMIC_X86) - CPU_Core_Dyn_X86_Cache_Close(); -#elif (C_DYNREC) - CPU_Core_Dynrec_Cache_Close(); -#endif - delete test; -} - -void CPU_Init(Section* sec) { - test = new CPU(sec); - sec->AddDestroyFunction(&CPU_ShutDown,true); -} -//initialize static members -bool CPU::inited=false; +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "cpu.h" +#include "memory.h" +#include "debug.h" +#include "keyboard.h" + +//Regs regs; + +Flag_Info flags; + +CPU_Regs cpu_regs; + + + +Segment Segs[6]; +Bit32u cpu_cycles; + +CPU_Decoder * cpudecoder; + + +static void CPU_CycleIncrease(void) { + Bit32u old_cycles=cpu_cycles; + cpu_cycles=(Bit32u)(cpu_cycles*1.2); + if (cpu_cycles==old_cycles) cpu_cycles++; + LOG_MSG("CPU:%d cycles",cpu_cycles); + +} + +static void CPU_CycleDecrease(void) { + cpu_cycles=(Bit32u)(cpu_cycles/1.2); + if (!cpu_cycles) cpu_cycles=1; + LOG_MSG("CPU:%d cycles",cpu_cycles); + +} + +Bit8u lastint; +void Interrupt(Bit8u num) { + lastint=num; +//DEBUG THINGIE to check fucked ints + + switch (num) { + case 0x00: + LOG_WARN("Divide Error"); + break; + case 0x06: + break; + case 0x07: + LOG_WARN("Co Processor Exception"); + break; + case 0x08: + case 0x09: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x16: + case 0x15: + case 0x1A: + case 0x17: + case 0x1C: + case 0x21: + case 0x2a: + case 0x2f: + case 0x33: + case 0x67: + case 0x74: + break; + case 0xcd: + E_Exit("Call to interrupt 0xCD this is BAD"); + case 0x03: +#ifdef C_DEBUG + if (DEBUG_BreakPoint()) return; +#endif + break; + case 0x05: + LOG_MSG("CPU:Out Of Bounds interrupt"); + break; + default: +// LOG_WARN("Call to unsupported INT %02X call %02X",num,reg_ah); + + break; + }; +/* Check for 16-bit or 32-bit and then setup everything for the interrupt to start */ + Bit16u pflags; + pflags= + (get_CF() << 0) | + (get_PF() << 2) | + (get_AF() << 4) | + (get_ZF() << 6) | + (get_SF() << 7) | + (flags.tf << 8) | + (flags.intf << 9) | + (flags.df << 10) | + (get_OF() << 11) | + (flags.io << 12) | + (flags.nt <<14); + + flags.intf=false; + flags.tf=false; +/* Save everything on a 16-bit stack */ + reg_sp-=2; + mem_writew(Segs[ss].phys+reg_sp,pflags); + reg_sp-=2; + mem_writew(Segs[ss].phys+reg_sp,Segs[cs].value); + reg_sp-=2; + mem_writew(Segs[ss].phys+reg_sp,reg_ip); +/* Get the new CS:IP from vector table */ + Bit16u newip=mem_readw(num << 2); + Bit16u newcs=mem_readw((num <<2)+2); + SetSegment_16(cs,newcs); + reg_ip=newip; +} + +void CPU_Real_16_Slow_Start(void); + +void SetCPU16bit() +{ + CPU_Real_16_Slow_Start(); +} + +void SetSegment_16(Bit32u seg,Bit16u val) { + Segs[seg].value=val; + Bit32u off=(val << 4); + Segs[seg].host=memory+off; + Segs[seg].phys=off; + //TODO Maybe use this feature one day :) + // Segs[seg].special=MEMORY_TestSpecial(off); +}; + + +void CPU_Init(void) { + reg_eax=0; + reg_ebx=0; + reg_ecx=0; + reg_edx=0; + reg_edi=0; + reg_esi=0; + reg_ebp=0; + reg_esp=0; + + SetSegment_16(cs,0); + SetSegment_16(ds,0); + SetSegment_16(es,0); + SetSegment_16(fs,0); + SetSegment_16(gs,0); + SetSegment_16(ss,0); + + reg_eip=0; + flags.type=t_UNKNOWN; + flags.af=0; + flags.cf=0; + flags.cf=0; + flags.sf=0; + flags.zf=0; + flags.intf=true; + flags.nt=0; + flags.io=0; + + SetCPU16bit(); + cpu_cycles=2000; + KEYBOARD_AddEvent(KBD_f11,CTRL_PRESSED,CPU_CycleDecrease); + KEYBOARD_AddEvent(KBD_f12,CTRL_PRESSED,CPU_CycleIncrease); + + reg_al=0; + reg_ah=0; +} + diff --git a/src/cpu/flags.cpp b/src/cpu/flags.cpp index 0ca45f3..fdaca11 100644 --- a/src/cpu/flags.cpp +++ b/src/cpu/flags.cpp @@ -1,1188 +1,582 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - Lazy flag system was designed after the same kind of system used in Bochs. - Probably still some bugs left in here. -*/ - -#include "dosbox.h" -#include "cpu.h" -#include "lazyflags.h" -#include "pic.h" - -LazyFlags lflags; - -/* CF Carry Flag -- Set on high-order bit carry or borrow; cleared - otherwise. -*/ -Bit32u get_CF(void) { - - switch (lflags.type) { - case t_UNKNOWN: - case t_INCb: - case t_INCw: - case t_INCd: - case t_DECb: - case t_DECw: - case t_DECd: - case t_MUL: - return GETFLAG(CF); - case t_ADDb: - return (lf_resb8) return false; - else return (lf_var1b >> (8-lf_var2b)) & 1; - case t_SHLw: - if (lf_var2b>16) return false; - else return (lf_var1w >> (16-lf_var2b)) & 1; - case t_SHLd: - case t_DSHLw: /* Hmm this is not correct for shift higher than 16 */ - case t_DSHLd: - return (lf_var1d >> (32 - lf_var2b)) & 1; - case t_RCRb: - case t_SHRb: - return (lf_var1b >> (lf_var2b - 1)) & 1; - case t_RCRw: - case t_SHRw: - return (lf_var1w >> (lf_var2b - 1)) & 1; - case t_RCRd: - case t_SHRd: - case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */ - case t_DSHRd: - return (lf_var1d >> (lf_var2b - 1)) & 1; - case t_SARb: - return (((Bit8s) lf_var1b) >> (lf_var2b - 1)) & 1; - case t_SARw: - return (((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1; - case t_SARd: - return (((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1; - case t_NEGb: - return lf_var1b; - case t_NEGw: - return lf_var1w; - case t_NEGd: - return lf_var1d; - case t_ORb: - case t_ORw: - case t_ORd: - case t_ANDb: - case t_ANDw: - case t_ANDd: - case t_XORb: - case t_XORw: - case t_XORd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - return false; /* Set to false */ - case t_DIV: - return false; /* Unkown */ - default: - LOG(LOG_CPU,LOG_ERROR)("get_CF Unknown %d",lflags.type); - } - return 0; -} - -/* AF Adjust flag -- Set on carry from or borrow to the low order - four bits of AL; cleared otherwise. Used for decimal - arithmetic. -*/ -Bit32u get_AF(void) { - Bitu type=lflags.type; - switch (type) { - case t_UNKNOWN: - return GETFLAG(AF); - case t_ADDb: - case t_ADCb: - case t_SBBb: - case t_SUBb: - case t_CMPb: - return ((lf_var1b ^ lf_var2b) ^ lf_resb) & 0x10; - case t_ADDw: - case t_ADCw: - case t_SBBw: - case t_SUBw: - case t_CMPw: - return ((lf_var1w ^ lf_var2w) ^ lf_resw) & 0x10; - case t_ADCd: - case t_ADDd: - case t_SBBd: - case t_SUBd: - case t_CMPd: - return ((lf_var1d ^ lf_var2d) ^ lf_resd) & 0x10; - case t_INCb: - return (lf_resb & 0x0f) == 0; - case t_INCw: - return (lf_resw & 0x0f) == 0; - case t_INCd: - return (lf_resd & 0x0f) == 0; - case t_DECb: - return (lf_resb & 0x0f) == 0x0f; - case t_DECw: - return (lf_resw & 0x0f) == 0x0f; - case t_DECd: - return (lf_resd & 0x0f) == 0x0f; - case t_NEGb: - return lf_var1b & 0x0f; - case t_NEGw: - return lf_var1w & 0x0f; - case t_NEGd: - return lf_var1d & 0x0f; - case t_SHLb: - case t_SHRb: - case t_SARb: - return lf_var2b & 0x1f; - case t_SHLw: - case t_SHRw: - case t_SARw: - return lf_var2w & 0x1f; - case t_SHLd: - case t_SHRd: - case t_SARd: - return lf_var2d & 0x1f; - case t_ORb: - case t_ORw: - case t_ORd: - case t_ANDb: - case t_ANDw: - case t_ANDd: - case t_XORb: - case t_XORw: - case t_XORd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - case t_DSHLw: - case t_DSHLd: - case t_DSHRw: - case t_DSHRd: - case t_DIV: - case t_MUL: - return false; /* Unkown */ - default: - LOG(LOG_CPU,LOG_ERROR)("get_AF Unknown %d",lflags.type); - } - return 0; -} - -/* ZF Zero Flag -- Set if result is zero; cleared otherwise. -*/ - -Bit32u get_ZF(void) { - Bitu type=lflags.type; - switch (type) { - case t_UNKNOWN: - return GETFLAG(ZF); - case t_ADDb: - case t_ORb: - case t_ADCb: - case t_SBBb: - case t_ANDb: - case t_XORb: - case t_SUBb: - case t_CMPb: - case t_INCb: - case t_DECb: - case t_TESTb: - case t_SHLb: - case t_SHRb: - case t_SARb: - case t_NEGb: - return (lf_resb==0); - case t_ADDw: - case t_ORw: - case t_ADCw: - case t_SBBw: - case t_ANDw: - case t_XORw: - case t_SUBw: - case t_CMPw: - case t_INCw: - case t_DECw: - case t_TESTw: - case t_SHLw: - case t_SHRw: - case t_SARw: - case t_DSHLw: - case t_DSHRw: - case t_NEGw: - return (lf_resw==0); - case t_ADDd: - case t_ORd: - case t_ADCd: - case t_SBBd: - case t_ANDd: - case t_XORd: - case t_SUBd: - case t_CMPd: - case t_INCd: - case t_DECd: - case t_TESTd: - case t_SHLd: - case t_SHRd: - case t_SARd: - case t_DSHLd: - case t_DSHRd: - case t_NEGd: - return (lf_resd==0); - case t_DIV: - case t_MUL: - return false; /* Unkown */ - default: - LOG(LOG_CPU,LOG_ERROR)("get_ZF Unknown %d",lflags.type); - } - return false; -} -/* SF Sign Flag -- Set equal to high-order bit of result (0 is - positive, 1 if negative). -*/ -Bit32u get_SF(void) { - Bitu type=lflags.type; - switch (type) { - case t_UNKNOWN: - return GETFLAG(SF); - case t_ADDb: - case t_ORb: - case t_ADCb: - case t_SBBb: - case t_ANDb: - case t_XORb: - case t_SUBb: - case t_CMPb: - case t_INCb: - case t_DECb: - case t_TESTb: - case t_SHLb: - case t_SHRb: - case t_SARb: - case t_NEGb: - return (lf_resb&0x80); - case t_ADDw: - case t_ORw: - case t_ADCw: - case t_SBBw: - case t_ANDw: - case t_XORw: - case t_SUBw: - case t_CMPw: - case t_INCw: - case t_DECw: - case t_TESTw: - case t_SHLw: - case t_SHRw: - case t_SARw: - case t_DSHLw: - case t_DSHRw: - case t_NEGw: - return (lf_resw&0x8000); - case t_ADDd: - case t_ORd: - case t_ADCd: - case t_SBBd: - case t_ANDd: - case t_XORd: - case t_SUBd: - case t_CMPd: - case t_INCd: - case t_DECd: - case t_TESTd: - case t_SHLd: - case t_SHRd: - case t_SARd: - case t_DSHLd: - case t_DSHRd: - case t_NEGd: - return (lf_resd&0x80000000); - case t_DIV: - case t_MUL: - return false; /* Unkown */ - default: - LOG(LOG_CPU,LOG_ERROR)("get_SF Unkown %d",lflags.type); - } - return false; - -} -Bit32u get_OF(void) { - Bitu type=lflags.type; - switch (type) { - case t_UNKNOWN: - case t_MUL: - return GETFLAG(OF); - case t_ADDb: - case t_ADCb: - return ((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var2b)) & 0x80; - case t_ADDw: - case t_ADCw: - return ((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var2w)) & 0x8000; - case t_ADDd: - case t_ADCd: - return ((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var2d)) & 0x80000000; - case t_SBBb: - case t_SUBb: - case t_CMPb: - return ((lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb)) & 0x80; - case t_SBBw: - case t_SUBw: - case t_CMPw: - return ((lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw)) & 0x8000; - case t_SBBd: - case t_SUBd: - case t_CMPd: - return ((lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd)) & 0x80000000; - case t_INCb: - return (lf_resb == 0x80); - case t_INCw: - return (lf_resw == 0x8000); - case t_INCd: - return (lf_resd == 0x80000000); - case t_DECb: - return (lf_resb == 0x7f); - case t_DECw: - return (lf_resw == 0x7fff); - case t_DECd: - return (lf_resd == 0x7fffffff); - case t_NEGb: - return (lf_var1b == 0x80); - case t_NEGw: - return (lf_var1w == 0x8000); - case t_NEGd: - return (lf_var1d == 0x80000000); - case t_SHLb: - return (lf_resb ^ lf_var1b) & 0x80; - case t_SHLw: - case t_DSHRw: - case t_DSHLw: - return (lf_resw ^ lf_var1w) & 0x8000; - case t_SHLd: - case t_DSHRd: - case t_DSHLd: - return (lf_resd ^ lf_var1d) & 0x80000000; - case t_SHRb: - if ((lf_var2b&0x1f)==1) return (lf_var1b > 0x80); - else return false; - case t_SHRw: - if ((lf_var2b&0x1f)==1) return (lf_var1w > 0x8000); - else return false; - case t_SHRd: - if ((lf_var2b&0x1f)==1) return (lf_var1d > 0x80000000); - else return false; - case t_ORb: - case t_ORw: - case t_ORd: - case t_ANDb: - case t_ANDw: - case t_ANDd: - case t_XORb: - case t_XORw: - case t_XORd: - case t_TESTb: - case t_TESTw: - case t_TESTd: - case t_SARb: - case t_SARw: - case t_SARd: - return false; /* Return false */ - case t_DIV: - return false; /* Unkown */ - default: - LOG(LOG_CPU,LOG_ERROR)("get_OF Unkown %d",lflags.type); - } - return false; -} - -Bit16u parity_lookup[256] = { - FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, - 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, - 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, - FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, - 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, - FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, - FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, - 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, - 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, - FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, - FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, - 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, - FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, - 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, - 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, - FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF - }; - -Bit32u get_PF(void) { - switch (lflags.type) { - case t_UNKNOWN: - return GETFLAG(PF); - default: - return (parity_lookup[lf_resb]); - }; - return 0; -} - - -#if 0 - -Bitu FillFlags(void) { -// if (lflags.type==t_UNKNOWN) return reg_flags; - Bitu new_word=(reg_flags & ~FLAG_MASK); - if (get_CF()) new_word|=FLAG_CF; - if (get_PF()) new_word|=FLAG_PF; - if (get_AF()) new_word|=FLAG_AF; - if (get_ZF()) new_word|=FLAG_ZF; - if (get_SF()) new_word|=FLAG_SF; - if (get_OF()) new_word|=FLAG_OF; - reg_flags=new_word; - lflags.type=t_UNKNOWN; - return reg_flags; -} - -#else - -#define DOFLAG_PF reg_flags=(reg_flags & ~FLAG_PF) | parity_lookup[lf_resb]; - -#define DOFLAG_AF reg_flags=(reg_flags & ~FLAG_AF) | (((lf_var1b ^ lf_var2b) ^ lf_resb) & 0x10); - -#define DOFLAG_ZFb SETFLAGBIT(ZF,lf_resb==0); -#define DOFLAG_ZFw SETFLAGBIT(ZF,lf_resw==0); -#define DOFLAG_ZFd SETFLAGBIT(ZF,lf_resd==0); - -#define DOFLAG_SFb reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resb & 0x80) >> 0); -#define DOFLAG_SFw reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resw & 0x8000) >> 8); -#define DOFLAG_SFd reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resd & 0x80000000) >> 24); - -#define SETCF(NEWBIT) reg_flags=(reg_flags & ~FLAG_CF)|(NEWBIT); - -#define SET_FLAG SETFLAGBIT - -Bitu FillFlags(void) { - switch (lflags.type) { - case t_UNKNOWN: - break; - case t_ADDb: - SET_FLAG(CF,(lf_resb8) SET_FLAG(CF,false); - else SET_FLAG(CF,(lf_var1b >> (8-lf_var2b)) & 1); - DOFLAG_ZFb; - DOFLAG_SFb; - SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); - DOFLAG_PF; - SET_FLAG(AF,(lf_var2b&0x1f)); - break; - case t_SHLw: - if (lf_var2b>16) SET_FLAG(CF,false); - else SET_FLAG(CF,(lf_var1w >> (16-lf_var2b)) & 1); - DOFLAG_ZFw; - DOFLAG_SFw; - SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); - DOFLAG_PF; - SET_FLAG(AF,(lf_var2w&0x1f)); - break; - case t_SHLd: - SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1); - DOFLAG_ZFd; - DOFLAG_SFd; - SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); - DOFLAG_PF; - SET_FLAG(AF,(lf_var2d&0x1f)); - break; - - - case t_DSHLw: - SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1); - DOFLAG_ZFw; - DOFLAG_SFw; - SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); - DOFLAG_PF; - break; - case t_DSHLd: - SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1); - DOFLAG_ZFd; - DOFLAG_SFd; - SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); - DOFLAG_PF; - break; - - - case t_SHRb: - SET_FLAG(CF,(lf_var1b >> (lf_var2b - 1)) & 1); - DOFLAG_ZFb; - DOFLAG_SFb; - if ((lf_var2b&0x1f)==1) SET_FLAG(OF,(lf_var1b >= 0x80)); - else SET_FLAG(OF,false); - DOFLAG_PF; - SET_FLAG(AF,(lf_var2b&0x1f)); - break; - case t_SHRw: - SET_FLAG(CF,(lf_var1w >> (lf_var2b - 1)) & 1); - DOFLAG_ZFw; - DOFLAG_SFw; - if ((lf_var2w&0x1f)==1) SET_FLAG(OF,(lf_var1w >= 0x8000)); - else SET_FLAG(OF,false); - DOFLAG_PF; - SET_FLAG(AF,(lf_var2w&0x1f)); - break; - case t_SHRd: - SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1); - DOFLAG_ZFd; - DOFLAG_SFd; - if ((lf_var2d&0x1f)==1) SET_FLAG(OF,(lf_var1d >= 0x80000000)); - else SET_FLAG(OF,false); - DOFLAG_PF; - SET_FLAG(AF,(lf_var2d&0x1f)); - break; - - - case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */ - SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1); - DOFLAG_ZFw; - DOFLAG_SFw; - SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); - DOFLAG_PF; - break; - case t_DSHRd: - SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1); - DOFLAG_ZFd; - DOFLAG_SFd; - SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); - DOFLAG_PF; - break; - - - case t_SARb: - SET_FLAG(CF,(((Bit8s) lf_var1b) >> (lf_var2b - 1)) & 1); - DOFLAG_ZFb; - DOFLAG_SFb; - SET_FLAG(OF,false); - DOFLAG_PF; - SET_FLAG(AF,(lf_var2b&0x1f)); - break; - case t_SARw: - SET_FLAG(CF,(((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1); - DOFLAG_ZFw; - DOFLAG_SFw; - SET_FLAG(OF,false); - DOFLAG_PF; - SET_FLAG(AF,(lf_var2w&0x1f)); - break; - case t_SARd: - SET_FLAG(CF,(((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1); - DOFLAG_ZFd; - DOFLAG_SFd; - SET_FLAG(OF,false); - DOFLAG_PF; - SET_FLAG(AF,(lf_var2d&0x1f)); - break; - - case t_INCb: - SET_FLAG(AF,(lf_resb & 0x0f) == 0); - DOFLAG_ZFb; - DOFLAG_SFb; - SET_FLAG(OF,(lf_resb == 0x80)); - DOFLAG_PF; - break; - case t_INCw: - SET_FLAG(AF,(lf_resw & 0x0f) == 0); - DOFLAG_ZFw; - DOFLAG_SFw; - SET_FLAG(OF,(lf_resw == 0x8000)); - DOFLAG_PF; - break; - case t_INCd: - SET_FLAG(AF,(lf_resd & 0x0f) == 0); - DOFLAG_ZFd; - DOFLAG_SFd; - SET_FLAG(OF,(lf_resd == 0x80000000)); - DOFLAG_PF; - break; - - case t_DECb: - SET_FLAG(AF,(lf_resb & 0x0f) == 0x0f); - DOFLAG_ZFb; - DOFLAG_SFb; - SET_FLAG(OF,(lf_resb == 0x7f)); - DOFLAG_PF; - break; - case t_DECw: - SET_FLAG(AF,(lf_resw & 0x0f) == 0x0f); - DOFLAG_ZFw; - DOFLAG_SFw; - SET_FLAG(OF,(lf_resw == 0x7fff)); - DOFLAG_PF; - break; - case t_DECd: - SET_FLAG(AF,(lf_resd & 0x0f) == 0x0f); - DOFLAG_ZFd; - DOFLAG_SFd; - SET_FLAG(OF,(lf_resd == 0x7fffffff)); - DOFLAG_PF; - break; - - case t_NEGb: - SET_FLAG(CF,(lf_var1b!=0)); - SET_FLAG(AF,(lf_resb & 0x0f) != 0); - DOFLAG_ZFb; - DOFLAG_SFb; - SET_FLAG(OF,(lf_var1b == 0x80)); - DOFLAG_PF; - break; - case t_NEGw: - SET_FLAG(CF,(lf_var1w!=0)); - SET_FLAG(AF,(lf_resw & 0x0f) != 0); - DOFLAG_ZFw; - DOFLAG_SFw; - SET_FLAG(OF,(lf_var1w == 0x8000)); - DOFLAG_PF; - break; - case t_NEGd: - SET_FLAG(CF,(lf_var1d!=0)); - SET_FLAG(AF,(lf_resd & 0x0f) != 0); - DOFLAG_ZFd; - DOFLAG_SFd; - SET_FLAG(OF,(lf_var1d == 0x80000000)); - DOFLAG_PF; - break; - - - case t_DIV: - case t_MUL: - break; - - default: - LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",lflags.type); - return 0; - } - lflags.type=t_UNKNOWN; - return reg_flags; -} - -void FillFlagsNoCFOF(void) { - switch (lflags.type) { - case t_UNKNOWN: - return; - case t_ADDb: - DOFLAG_AF; - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - break; - case t_ADDw: - DOFLAG_AF; - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_ADDd: - DOFLAG_AF; - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - case t_ADCb: - DOFLAG_AF; - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - break; - case t_ADCw: - DOFLAG_AF; - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_ADCd: - DOFLAG_AF; - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - - case t_SBBb: - DOFLAG_AF; - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - break; - case t_SBBw: - DOFLAG_AF; - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_SBBd: - DOFLAG_AF; - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - - case t_SUBb: - case t_CMPb: - DOFLAG_AF; - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - break; - case t_SUBw: - case t_CMPw: - DOFLAG_AF; - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_SUBd: - case t_CMPd: - DOFLAG_AF; - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - - case t_ORb: - SET_FLAG(AF,false); - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - break; - case t_ORw: - SET_FLAG(AF,false); - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_ORd: - SET_FLAG(AF,false); - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - - case t_TESTb: - case t_ANDb: - SET_FLAG(AF,false); - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - break; - case t_TESTw: - case t_ANDw: - SET_FLAG(AF,false); - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_TESTd: - case t_ANDd: - SET_FLAG(AF,false); - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - - case t_XORb: - SET_FLAG(AF,false); - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - break; - case t_XORw: - SET_FLAG(AF,false); - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_XORd: - SET_FLAG(AF,false); - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - - case t_SHLb: - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - SET_FLAG(AF,(lf_var2b&0x1f)); - break; - case t_SHLw: - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - SET_FLAG(AF,(lf_var2w&0x1f)); - break; - case t_SHLd: - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - SET_FLAG(AF,(lf_var2d&0x1f)); - break; - - - case t_DSHLw: - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_DSHLd: - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - - case t_SHRb: - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - SET_FLAG(AF,(lf_var2b&0x1f)); - break; - case t_SHRw: - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - SET_FLAG(AF,(lf_var2w&0x1f)); - break; - case t_SHRd: - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - SET_FLAG(AF,(lf_var2d&0x1f)); - break; - - - case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */ - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_DSHRd: - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - - case t_SARb: - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - SET_FLAG(AF,(lf_var2b&0x1f)); - break; - case t_SARw: - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - SET_FLAG(AF,(lf_var2w&0x1f)); - break; - case t_SARd: - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - SET_FLAG(AF,(lf_var2d&0x1f)); - break; - - case t_INCb: - SET_FLAG(AF,(lf_resb & 0x0f) == 0); - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - break; - case t_INCw: - SET_FLAG(AF,(lf_resw & 0x0f) == 0); - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_INCd: - SET_FLAG(AF,(lf_resd & 0x0f) == 0); - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - case t_DECb: - SET_FLAG(AF,(lf_resb & 0x0f) == 0x0f); - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - break; - case t_DECw: - SET_FLAG(AF,(lf_resw & 0x0f) == 0x0f); - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_DECd: - SET_FLAG(AF,(lf_resd & 0x0f) == 0x0f); - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - case t_NEGb: - SET_FLAG(AF,(lf_resb & 0x0f) != 0); - DOFLAG_ZFb; - DOFLAG_SFb; - DOFLAG_PF; - break; - case t_NEGw: - SET_FLAG(AF,(lf_resw & 0x0f) != 0); - DOFLAG_ZFw; - DOFLAG_SFw; - DOFLAG_PF; - break; - case t_NEGd: - SET_FLAG(AF,(lf_resd & 0x0f) != 0); - DOFLAG_ZFd; - DOFLAG_SFd; - DOFLAG_PF; - break; - - - case t_DIV: - case t_MUL: - break; - - default: - LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",lflags.type); - break; - } - lflags.type=t_UNKNOWN; -} - -void DestroyConditionFlags(void) { - lflags.type=t_UNKNOWN; -} - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Lazy flag system was designed after the same kind of system used in Bochs. + Probably still some bugs left in here. +*/ + +#include "dosbox.h" +#include "cpu.h" +#include "pic.h" + + +/* CF Carry Flag -- Set on high-order bit carry or borrow; cleared + otherwise. +*/ +bool get_CF(void) { + + switch (flags.type) { + case t_UNKNOWN: + case t_CF: + case t_INCb: + case t_INCw: + case t_INCd: + case t_DECb: + case t_DECw: + case t_DECd: + case t_MUL: + return flags.cf; + break; + + case t_ADDb: + return (flags.result.b=8) return false; + else return (flags.var1.b >> (8-flags.var2.b)) & 1; + case t_SHLw: + if (flags.var2.b>=16) return false; + else return (flags.var1.w >> (16-flags.var2.b)) & 1; + case t_SHLd: + return (flags.var1.d >> (32 - flags.var2.b)) & 0x01; + case t_DSHLw: /* Hmm this is not correct for shift higher than 16 */ + return (flags.var1.d >> (32 - flags.var2.b)) & 0x01; + case t_DSHLd: + return (flags.var1.d >> (32 - flags.var2.b)) & 0x01; + + case t_SHRb: + return (flags.var1.b >> (flags.var2.b - 1)) & 0x01; + case t_SHRw: + return (flags.var1.w >> (flags.var2.b - 1)) & 0x01; + case t_SHRd: + return (flags.var1.d >> (flags.var2.b - 1)) & 0x01; + case t_SARb: + return (flags.var1.b >> (flags.var2.b - 1)) & 0x01; + case t_SARw: + return (flags.var1.w >> (flags.var2.b - 1)) & 0x01; + case t_SARd: + return (flags.var1.d >> (flags.var2.b - 1)) & 0x01; + case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */ + return (flags.var1.d >> (flags.var2.b - 1)) & 0x01; + case t_DSHRd: + return (flags.var1.d >> (flags.var2.b - 1)) & 0x01; + case t_NEGb: + return (flags.var1.b!=0); + case t_NEGw: + return (flags.var1.w!=0); + case t_NEGd: + return (flags.var1.d!=0); + case t_ROLb: + return (flags.result.b & 1)>0; + case t_ROLw: + return (flags.result.w & 1)>0; + case t_ROLd: + return (flags.result.d & 1)>0; + case t_RORb: + return (flags.result.b & 0x80)>0; + case t_RORw: + return (flags.result.w & 0x8000)>0; + case t_RORd: + return (flags.result.d & 0x80000000)>0; + case t_RCLb: + return ((flags.var1.b >> (8-flags.var2.b))&1)>0; + case t_RCLw: + return ((flags.var1.w >> (16-flags.var2.b))&1)>0; + case t_RCLd: + return ((flags.var1.d >> (32-flags.var2.b))&1)>0; + case t_RCRb: + return ((flags.var1.b >> (flags.var2.b-1))&1)>0; + case t_RCRw: + return ((flags.var1.w >> (flags.var2.b-1))&1)>0; + case t_RCRd: + return ((flags.var1.d >> (flags.var2.b-1))&1)>0; + case t_ORb: + case t_ORw: + case t_ORd: + case t_ANDb: + case t_ANDw: + case t_ANDd: + case t_XORb: + case t_XORw: + case t_XORd: + case t_TESTb: + case t_TESTw: + case t_TESTd: + case t_DIV: + return false; + + + default: + E_Exit("get_CF Unknown %d",flags.type); + } + return 0; +} + +/* AF Adjust flag -- Set on carry from or borrow to the low order + four bits of AL; cleared otherwise. Used for decimal + arithmetic. +*/ +bool get_AF(void) { + Bitu type=flags.type; +again: + switch (type) { + case t_UNKNOWN: + case t_ROLb: + case t_RORb: + case t_RCLb: + case t_RCRb: + case t_ROLw: + case t_RORw: + case t_RCLw: + case t_RCRw: + case t_ROLd: + case t_RORd: + case t_RCLd: + case t_RCRd: + return flags.af; + case t_CF: + type=flags.prev_type; + goto again; + + case t_ADDb: + case t_ADCb: + case t_SBBb: + case t_SUBb: + case t_CMPb: + return (((flags.var1.b ^ flags.var2.b) ^ flags.result.b) & 0x10)>0; + case t_ADDw: + case t_ADCw: + case t_SBBw: + case t_SUBw: + case t_CMPw: + return (((flags.var1.w ^ flags.var2.w) ^ flags.result.w) & 0x10)>0; + case t_ADCd: + case t_ADDd: + case t_SBBd: + case t_SUBd: + case t_CMPd: + return (((flags.var1.d ^ flags.var2.d) ^ flags.result.d) & 0x10)>0; + case t_INCb: + return (flags.result.b & 0x0f) == 0; + case t_INCw: + return (flags.result.w & 0x0f) == 0; + case t_INCd: + return (flags.result.d & 0x0f) == 0; + case t_DECb: + return (flags.result.b & 0x0f) == 0x0f; + case t_DECw: + return (flags.result.w & 0x0f) == 0x0f; + case t_DECd: + return (flags.result.d & 0x0f) == 0x0f; + case t_NEGb: + return (flags.var1.b & 0x0f) > 0; + case t_NEGw: + return (flags.var1.w & 0x0f) > 0; + case t_NEGd: + return (flags.var1.d & 0x0f) > 0; + case t_ORb: + case t_ORw: + case t_ORd: + case t_ANDb: + case t_ANDw: + case t_ANDd: + case t_XORb: + case t_XORw: + case t_XORd: + case t_TESTb: + case t_TESTw: + case t_TESTd: + case t_SHLb: + case t_SHLw: + case t_SHLd: + case t_SHRb: + case t_SHRw: + case t_SHRd: + case t_SARb: + case t_SARw: + case t_DSHLw: + case t_DSHLd: + case t_DSHRw: + case t_DSHRd: + case t_DIV: + case t_MUL: + return false; /* undefined */ + default: + E_Exit("get_AF Unknown %d",flags.type); + } + return 0; +} + +/* ZF Zero Flag -- Set if result is zero; cleared otherwise. +*/ + +bool get_ZF(void) { + Bitu type=flags.type; +again: + switch (type) { + case t_UNKNOWN: + case t_ROLb: + case t_RORb: + case t_RCLb: + case t_RCRb: + case t_ROLw: + case t_RORw: + case t_RCLw: + case t_RCRw: + case t_ROLd: + case t_RORd: + case t_RCLd: + case t_RCRd: + return flags.zf; + case t_CF: + type=flags.prev_type; + goto again; + case t_ADDb: + case t_ORb: + case t_ADCb: + case t_SBBb: + case t_ANDb: + case t_XORb: + case t_SUBb: + case t_CMPb: + case t_INCb: + case t_DECb: + case t_TESTb: + case t_SHLb: + case t_SHRb: + case t_SARb: + case t_NEGb: + return (flags.result.b==0); + case t_ADDw: + case t_ORw: + case t_ADCw: + case t_SBBw: + case t_ANDw: + case t_XORw: + case t_SUBw: + case t_CMPw: + case t_INCw: + case t_DECw: + case t_TESTw: + case t_SHLw: + case t_SHRw: + case t_SARw: + case t_DSHLw: + case t_DSHRw: + case t_NEGw: + return (flags.result.w==0); + case t_ADDd: + case t_ORd: + case t_ADCd: + case t_SBBd: + case t_ANDd: + case t_XORd: + case t_SUBd: + case t_CMPd: + case t_INCd: + case t_DECd: + case t_TESTd: + case t_SHLd: + case t_SHRd: + case t_SARd: + case t_DSHLd: + case t_DSHRd: + case t_NEGd: + return (flags.result.d==0); + case t_DIV: + case t_MUL: + return false; + default: + E_Exit("get_ZF Unknown %d",flags.type); + } + return false; +} +/* SF Sign Flag -- Set equal to high-order bit of result (0 is + positive, 1 if negative). +*/ +bool get_SF(void) { + Bitu type=flags.type; +again: + switch (type) { + case t_UNKNOWN: + case t_ROLb: + case t_RORb: + case t_RCLb: + case t_RCRb: + case t_ROLw: + case t_RORw: + case t_RCLw: + case t_RCRw: + case t_ROLd: + case t_RORd: + case t_RCLd: + case t_RCRd: + return flags.sf; + case t_CF: + type=flags.prev_type; + goto again; + + case t_ADDb: + case t_ORb: + case t_ADCb: + case t_SBBb: + case t_ANDb: + case t_XORb: + case t_SUBb: + case t_CMPb: + case t_INCb: + case t_DECb: + case t_TESTb: + case t_SHLb: + case t_SHRb: + case t_SARb: + case t_NEGb: + return (flags.result.b>=0x80); + case t_ADDw: + case t_ORw: + case t_ADCw: + case t_SBBw: + case t_ANDw: + case t_XORw: + case t_SUBw: + case t_CMPw: + case t_INCw: + case t_DECw: + case t_TESTw: + case t_SHLw: + case t_SHRw: + case t_SARw: + case t_DSHLw: + case t_DSHRw: + case t_NEGw: + return (flags.result.w>=0x8000); + case t_ADDd: + case t_ORd: + case t_ADCd: + case t_SBBd: + case t_ANDd: + case t_XORd: + case t_SUBd: + case t_CMPd: + case t_INCd: + case t_DECd: + case t_TESTd: + case t_SHLd: + case t_SHRd: + case t_SARd: + case t_DSHLd: + case t_DSHRd: + case t_NEGd: + return (flags.result.d>=0x80000000); + case t_DIV: + case t_MUL: + return false; + default: + E_Exit("get_SF Unkown %d",flags.type); + } + return false; + +} +bool get_OF(void) { + Bit8u var1b7, var2b7, resultb7; + Bit16u var1w15, var2w15, resultw15; + Bit32u var1d31, var2d31, resultd31; + + Bitu type=flags.type; +again: + switch (type) { + case t_UNKNOWN: + case t_MUL: + return flags.of; + case t_CF: + type=flags.prev_type; + goto again; + case t_ADDb: + case t_ADCb: +// return (((flags.result.b) ^ (flags.var2.b)) & ((flags.result.b) ^ (flags.var1.b)) & 0x80)>0; + var1b7 = flags.var1.b & 0x80; + var2b7 = flags.var2.b & 0x80; + resultb7 = flags.result.b & 0x80; + return (var1b7 == var2b7) && (resultb7 ^ var2b7); + case t_ADDw: + case t_ADCw: +// return (((flags.result.w) ^ (flags.var2.w)) & ((flags.result.w) ^ (flags.var1.w)) & 0x8000)>0; + var1w15 = flags.var1.w & 0x8000; + var2w15 = flags.var2.w & 0x8000; + resultw15 = flags.result.w & 0x8000; + return (var1w15 == var2w15) && (resultw15 ^ var2w15); + case t_ADDd: + case t_ADCd: +//TODO fix dword Overflow + var1d31 = flags.var1.d & 0x8000; + var2d31 = flags.var2.d & 0x8000; + resultd31 = flags.result.d & 0x8000; + return (var1d31 == var2d31) && (resultd31 ^ var2d31); + case t_SBBb: + case t_SUBb: + case t_CMPb: +// return (((flags.var1.b) ^ (flags.var2.b)) & ((flags.var1.b) ^ (flags.result.b)) & 0x80)>0; + var1b7 = flags.var1.b & 0x80; + var2b7 = flags.var2.b & 0x80; + resultb7 = flags.result.b & 0x80; + return (var1b7 ^ var2b7) && (var1b7 ^ resultb7); + case t_SBBw: + case t_SUBw: + case t_CMPw: +// return (((flags.var1.w) ^ (flags.var2.w)) & ((flags.var1.w) ^ (flags.result.w)) & 0x8000)>0; + var1w15 = flags.var1.w & 0x8000; + var2w15 = flags.var2.w & 0x8000; + resultw15 = flags.result.w & 0x8000; + return (var1w15 ^ var2w15) && (var1w15 ^ resultw15); + case t_SBBd: + case t_SUBd: + case t_CMPd: + var1d31 = flags.var1.d & 0x8000; + var2d31 = flags.var2.d & 0x8000; + resultd31 = flags.result.d & 0x8000; + return (var1d31 ^ var2d31) && (var1d31 ^ resultd31); + case t_INCb: + return (flags.result.b == 0x80); + case t_INCw: + return (flags.result.w == 0x8000); + case t_INCd: + return (flags.result.d == 0x80000000); + case t_DECb: + return (flags.result.b == 0x7f); + case t_DECw: + return (flags.result.w == 0x7fff); + case t_DECd: + return (flags.result.d == 0x7fffffff); + case t_NEGb: + return (flags.var1.b == 0x80); + case t_NEGw: + return (flags.var1.w == 0x8000); + case t_NEGd: + return (flags.var1.d == 0x80000000); + case t_ROLb: + case t_RORb: + case t_RCLb: + case t_RCRb: + case t_SHLb: + if (flags.var2.b==1) return ((flags.var1.b ^ flags.result.b) & 0x80) >0; + break; + case t_ROLw: + case t_RORw: + case t_RCLw: + case t_RCRw: + case t_SHLw: + case t_DSHLw: //TODO This is euhm inccorect i think but let's keep it for now + if (flags.var2.b==1) return ((flags.var1.w ^ flags.result.w) & 0x8000) >0; + break; + case t_ROLd: + case t_RORd: + case t_RCLd: + case t_RCRd: + case t_SHLd: + case t_DSHLd: + if (flags.var2.b==1) return ((flags.var1.d ^ flags.result.d) & 0x80000000) >0; + break; + case t_SHRb: + if (flags.var2.b==1) return (flags.var1.b >= 0x80); + break; + case t_SHRw: + case t_DSHRw: //TODO + if (flags.var2.b==1) return (flags.var1.w >= 0x8000); + break; + case t_SHRd: + case t_DSHRd: //TODO + if (flags.var2.b==1) return (flags.var1.d >= 0x80000000); + break; + case t_SARb: + case t_SARw: + case t_SARd: + case t_ORb: + case t_ORw: + case t_ORd: + case t_ANDb: + case t_ANDw: + case t_ANDd: + case t_XORb: + case t_XORw: + case t_XORd: + case t_TESTb: + case t_TESTw: + case t_TESTd: + case t_DIV: + return false; + default: + E_Exit("get_OF Unkown %d",flags.type); + } + return false; +} + +static bool parity_lookup[256] = { + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 + }; + +bool get_PF(void) { + switch (flags.type) { + case t_UNKNOWN: + return flags.pf; + default: + return (parity_lookup[flags.result.b]);; + }; + return false; +} + + diff --git a/src/cpu/instructions.h b/src/cpu/instructions.h deleted file mode 100644 index 6b21b84..0000000 --- a/src/cpu/instructions.h +++ /dev/null @@ -1,960 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* Jumps */ - -/* All Byte general instructions */ -#define ADDB(op1,op2,load,save) \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b+lf_var2b; \ - save(op1,lf_resb); \ - lflags.type=t_ADDb; - -#define ADCB(op1,op2,load,save) \ - lflags.oldcf=get_CF()!=0; \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b+lf_var2b+lflags.oldcf; \ - save(op1,lf_resb); \ - lflags.type=t_ADCb; - -#define SBBB(op1,op2,load,save) \ - lflags.oldcf=get_CF()!=0; \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b-(lf_var2b+lflags.oldcf); \ - save(op1,lf_resb); \ - lflags.type=t_SBBb; - -#define SUBB(op1,op2,load,save) \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b-lf_var2b; \ - save(op1,lf_resb); \ - lflags.type=t_SUBb; - -#define ORB(op1,op2,load,save) \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b | lf_var2b; \ - save(op1,lf_resb); \ - lflags.type=t_ORb; - -#define XORB(op1,op2,load,save) \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b ^ lf_var2b; \ - save(op1,lf_resb); \ - lflags.type=t_XORb; - -#define ANDB(op1,op2,load,save) \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b & lf_var2b; \ - save(op1,lf_resb); \ - lflags.type=t_ANDb; - -#define CMPB(op1,op2,load,save) \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b-lf_var2b; \ - lflags.type=t_CMPb; - -#define TESTB(op1,op2,load,save) \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b & lf_var2b; \ - lflags.type=t_TESTb; - -/* All Word General instructions */ - -#define ADDW(op1,op2,load,save) \ - lf_var1w=load(op1);lf_var2w=op2; \ - lf_resw=lf_var1w+lf_var2w; \ - save(op1,lf_resw); \ - lflags.type=t_ADDw; - -#define ADCW(op1,op2,load,save) \ - lflags.oldcf=get_CF()!=0; \ - lf_var1w=load(op1);lf_var2w=op2; \ - lf_resw=lf_var1w+lf_var2w+lflags.oldcf; \ - save(op1,lf_resw); \ - lflags.type=t_ADCw; - -#define SBBW(op1,op2,load,save) \ - lflags.oldcf=get_CF()!=0; \ - lf_var1w=load(op1);lf_var2w=op2; \ - lf_resw=lf_var1w-(lf_var2w+lflags.oldcf); \ - save(op1,lf_resw); \ - lflags.type=t_SBBw; - -#define SUBW(op1,op2,load,save) \ - lf_var1w=load(op1);lf_var2w=op2; \ - lf_resw=lf_var1w-lf_var2w; \ - save(op1,lf_resw); \ - lflags.type=t_SUBw; - -#define ORW(op1,op2,load,save) \ - lf_var1w=load(op1);lf_var2w=op2; \ - lf_resw=lf_var1w | lf_var2w; \ - save(op1,lf_resw); \ - lflags.type=t_ORw; - -#define XORW(op1,op2,load,save) \ - lf_var1w=load(op1);lf_var2w=op2; \ - lf_resw=lf_var1w ^ lf_var2w; \ - save(op1,lf_resw); \ - lflags.type=t_XORw; - -#define ANDW(op1,op2,load,save) \ - lf_var1w=load(op1);lf_var2w=op2; \ - lf_resw=lf_var1w & lf_var2w; \ - save(op1,lf_resw); \ - lflags.type=t_ANDw; - -#define CMPW(op1,op2,load,save) \ - lf_var1w=load(op1);lf_var2w=op2; \ - lf_resw=lf_var1w-lf_var2w; \ - lflags.type=t_CMPw; - -#define TESTW(op1,op2,load,save) \ - lf_var1w=load(op1);lf_var2w=op2; \ - lf_resw=lf_var1w & lf_var2w; \ - lflags.type=t_TESTw; - -/* All DWORD General Instructions */ - -#define ADDD(op1,op2,load,save) \ - lf_var1d=load(op1);lf_var2d=op2; \ - lf_resd=lf_var1d+lf_var2d; \ - save(op1,lf_resd); \ - lflags.type=t_ADDd; - -#define ADCD(op1,op2,load,save) \ - lflags.oldcf=get_CF()!=0; \ - lf_var1d=load(op1);lf_var2d=op2; \ - lf_resd=lf_var1d+lf_var2d+lflags.oldcf; \ - save(op1,lf_resd); \ - lflags.type=t_ADCd; - -#define SBBD(op1,op2,load,save) \ - lflags.oldcf=get_CF()!=0; \ - lf_var1d=load(op1);lf_var2d=op2; \ - lf_resd=lf_var1d-(lf_var2d+lflags.oldcf); \ - save(op1,lf_resd); \ - lflags.type=t_SBBd; - -#define SUBD(op1,op2,load,save) \ - lf_var1d=load(op1);lf_var2d=op2; \ - lf_resd=lf_var1d-lf_var2d; \ - save(op1,lf_resd); \ - lflags.type=t_SUBd; - -#define ORD(op1,op2,load,save) \ - lf_var1d=load(op1);lf_var2d=op2; \ - lf_resd=lf_var1d | lf_var2d; \ - save(op1,lf_resd); \ - lflags.type=t_ORd; - -#define XORD(op1,op2,load,save) \ - lf_var1d=load(op1);lf_var2d=op2; \ - lf_resd=lf_var1d ^ lf_var2d; \ - save(op1,lf_resd); \ - lflags.type=t_XORd; - -#define ANDD(op1,op2,load,save) \ - lf_var1d=load(op1);lf_var2d=op2; \ - lf_resd=lf_var1d & lf_var2d; \ - save(op1,lf_resd); \ - lflags.type=t_ANDd; - -#define CMPD(op1,op2,load,save) \ - lf_var1d=load(op1);lf_var2d=op2; \ - lf_resd=lf_var1d-lf_var2d; \ - lflags.type=t_CMPd; - - -#define TESTD(op1,op2,load,save) \ - lf_var1d=load(op1);lf_var2d=op2; \ - lf_resd=lf_var1d & lf_var2d; \ - lflags.type=t_TESTd; - - - - -#define INCB(op1,load,save) \ - LoadCF;lf_var1b=load(op1); \ - lf_resb=lf_var1b+1; \ - save(op1,lf_resb); \ - lflags.type=t_INCb; \ - -#define INCW(op1,load,save) \ - LoadCF;lf_var1w=load(op1); \ - lf_resw=lf_var1w+1; \ - save(op1,lf_resw); \ - lflags.type=t_INCw; - -#define INCD(op1,load,save) \ - LoadCF;lf_var1d=load(op1); \ - lf_resd=lf_var1d+1; \ - save(op1,lf_resd); \ - lflags.type=t_INCd; - -#define DECB(op1,load,save) \ - LoadCF;lf_var1b=load(op1); \ - lf_resb=lf_var1b-1; \ - save(op1,lf_resb); \ - lflags.type=t_DECb; - -#define DECW(op1,load,save) \ - LoadCF;lf_var1w=load(op1); \ - lf_resw=lf_var1w-1; \ - save(op1,lf_resw); \ - lflags.type=t_DECw; - -#define DECD(op1,load,save) \ - LoadCF;lf_var1d=load(op1); \ - lf_resd=lf_var1d-1; \ - save(op1,lf_resd); \ - lflags.type=t_DECd; - - - -#define ROLB(op1,op2,load,save) \ - if (!(op2&0x7)) { \ - if (op2&0x18) { \ - FillFlagsNoCFOF(); \ - SETFLAGBIT(CF,op1 & 1); \ - SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7)); \ - } \ - break; \ - } \ - FillFlagsNoCFOF(); \ - lf_var1b=load(op1); \ - lf_var2b=op2&0x07; \ - lf_resb=(lf_var1b << lf_var2b) | \ - (lf_var1b >> (8-lf_var2b)); \ - save(op1,lf_resb); \ - SETFLAGBIT(CF,lf_resb & 1); \ - SETFLAGBIT(OF,(lf_resb & 1) ^ (lf_resb >> 7)); - -#define ROLW(op1,op2,load,save) \ - if (!(op2&0xf)) { \ - if (op2&0x10) { \ - FillFlagsNoCFOF(); \ - SETFLAGBIT(CF,op1 & 1); \ - SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 15)); \ - } \ - break; \ - } \ - FillFlagsNoCFOF(); \ - lf_var1w=load(op1); \ - lf_var2b=op2&0xf; \ - lf_resw=(lf_var1w << lf_var2b) | \ - (lf_var1w >> (16-lf_var2b)); \ - save(op1,lf_resw); \ - SETFLAGBIT(CF,lf_resw & 1); \ - SETFLAGBIT(OF,(lf_resw & 1) ^ (lf_resw >> 15)); - -#define ROLD(op1,op2,load,save) \ - if (!op2) break; \ - FillFlagsNoCFOF(); \ - lf_var1d=load(op1); \ - lf_var2b=op2; \ - lf_resd=(lf_var1d << lf_var2b) | \ - (lf_var1d >> (32-lf_var2b)); \ - save(op1,lf_resd); \ - SETFLAGBIT(CF,lf_resd & 1); \ - SETFLAGBIT(OF,(lf_resd & 1) ^ (lf_resd >> 31)); - - -#define RORB(op1,op2,load,save) \ - if (!(op2&0x7)) { \ - if (op2&0x18) { \ - FillFlagsNoCFOF(); \ - SETFLAGBIT(CF,op1>>7); \ - SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1)); \ - } \ - break; \ - } \ - FillFlagsNoCFOF(); \ - lf_var1b=load(op1); \ - lf_var2b=op2&0x07; \ - lf_resb=(lf_var1b >> lf_var2b) | \ - (lf_var1b << (8-lf_var2b)); \ - save(op1,lf_resb); \ - SETFLAGBIT(CF,lf_resb & 0x80); \ - SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); - -#define RORW(op1,op2,load,save) \ - if (!(op2&0xf)) { \ - if (op2&0x10) { \ - FillFlagsNoCFOF(); \ - SETFLAGBIT(CF,op1>>15); \ - SETFLAGBIT(OF,(op1>>15) ^ ((op1>>14) & 1)); \ - } \ - break; \ - } \ - FillFlagsNoCFOF(); \ - lf_var1w=load(op1); \ - lf_var2b=op2&0xf; \ - lf_resw=(lf_var1w >> lf_var2b) | \ - (lf_var1w << (16-lf_var2b)); \ - save(op1,lf_resw); \ - SETFLAGBIT(CF,lf_resw & 0x8000); \ - SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); - -#define RORD(op1,op2,load,save) \ - if (!op2) break; \ - FillFlagsNoCFOF(); \ - lf_var1d=load(op1); \ - lf_var2b=op2; \ - lf_resd=(lf_var1d >> lf_var2b) | \ - (lf_var1d << (32-lf_var2b)); \ - save(op1,lf_resd); \ - SETFLAGBIT(CF,lf_resd & 0x80000000); \ - SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); - - -#define RCLB(op1,op2,load,save) \ - if (!(op2%9)) break; \ -{ Bit8u cf=(Bit8u)FillFlags()&0x1; \ - lf_var1b=load(op1); \ - lf_var2b=op2%9; \ - lf_resb=(lf_var1b << lf_var2b) | \ - (cf << (lf_var2b-1)) | \ - (lf_var1b >> (9-lf_var2b)); \ - save(op1,lf_resb); \ - SETFLAGBIT(CF,((lf_var1b >> (8-lf_var2b)) & 1)); \ - SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resb >> 7)); \ -} - -#define RCLW(op1,op2,load,save) \ - if (!(op2%17)) break; \ -{ Bit16u cf=(Bit16u)FillFlags()&0x1; \ - lf_var1w=load(op1); \ - lf_var2b=op2%17; \ - lf_resw=(lf_var1w << lf_var2b) | \ - (cf << (lf_var2b-1)) | \ - (lf_var1w >> (17-lf_var2b)); \ - save(op1,lf_resw); \ - SETFLAGBIT(CF,((lf_var1w >> (16-lf_var2b)) & 1)); \ - SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resw >> 15)); \ -} - -#define RCLD(op1,op2,load,save) \ - if (!op2) break; \ -{ Bit32u cf=(Bit32u)FillFlags()&0x1; \ - lf_var1d=load(op1); \ - lf_var2b=op2; \ - if (lf_var2b==1) { \ - lf_resd=(lf_var1d << 1) | cf; \ - } else { \ - lf_resd=(lf_var1d << lf_var2b) | \ - (cf << (lf_var2b-1)) | \ - (lf_var1d >> (33-lf_var2b)); \ - } \ - save(op1,lf_resd); \ - SETFLAGBIT(CF,((lf_var1d >> (32-lf_var2b)) & 1)); \ - SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resd >> 31)); \ -} - - - -#define RCRB(op1,op2,load,save) \ - if (op2%9) { \ - Bit8u cf=(Bit8u)FillFlags()&0x1; \ - lf_var1b=load(op1); \ - lf_var2b=op2%9; \ - lf_resb=(lf_var1b >> lf_var2b) | \ - (cf << (8-lf_var2b)) | \ - (lf_var1b << (9-lf_var2b)); \ - save(op1,lf_resb); \ - SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1); \ - SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); \ - } - -#define RCRW(op1,op2,load,save) \ - if (op2%17) { \ - Bit16u cf=(Bit16u)FillFlags()&0x1; \ - lf_var1w=load(op1); \ - lf_var2b=op2%17; \ - lf_resw=(lf_var1w >> lf_var2b) | \ - (cf << (16-lf_var2b)) | \ - (lf_var1w << (17-lf_var2b)); \ - save(op1,lf_resw); \ - SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1); \ - SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); \ - } - -#define RCRD(op1,op2,load,save) \ - if (op2) { \ - Bit32u cf=(Bit32u)FillFlags()&0x1; \ - lf_var1d=load(op1); \ - lf_var2b=op2; \ - if (lf_var2b==1) { \ - lf_resd=lf_var1d >> 1 | cf << 31; \ - } else { \ - lf_resd=(lf_var1d >> lf_var2b) | \ - (cf << (32-lf_var2b)) | \ - (lf_var1d << (33-lf_var2b)); \ - } \ - save(op1,lf_resd); \ - SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1); \ - SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); \ - } - - -#define SHLB(op1,op2,load,save) \ - if (!op2) break; \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b << lf_var2b; \ - save(op1,lf_resb); \ - lflags.type=t_SHLb; - -#define SHLW(op1,op2,load,save) \ - if (!op2) break; \ - lf_var1w=load(op1);lf_var2b=op2 ; \ - lf_resw=lf_var1w << lf_var2b; \ - save(op1,lf_resw); \ - lflags.type=t_SHLw; - -#define SHLD(op1,op2,load,save) \ - if (!op2) break; \ - lf_var1d=load(op1);lf_var2b=op2; \ - lf_resd=lf_var1d << lf_var2b; \ - save(op1,lf_resd); \ - lflags.type=t_SHLd; - - -#define SHRB(op1,op2,load,save) \ - if (!op2) break; \ - lf_var1b=load(op1);lf_var2b=op2; \ - lf_resb=lf_var1b >> lf_var2b; \ - save(op1,lf_resb); \ - lflags.type=t_SHRb; - -#define SHRW(op1,op2,load,save) \ - if (!op2) break; \ - lf_var1w=load(op1);lf_var2b=op2; \ - lf_resw=lf_var1w >> lf_var2b; \ - save(op1,lf_resw); \ - lflags.type=t_SHRw; - -#define SHRD(op1,op2,load,save) \ - if (!op2) break; \ - lf_var1d=load(op1);lf_var2b=op2; \ - lf_resd=lf_var1d >> lf_var2b; \ - save(op1,lf_resd); \ - lflags.type=t_SHRd; - - -#define SARB(op1,op2,load,save) \ - if (!op2) break; \ - lf_var1b=load(op1);lf_var2b=op2; \ - if (lf_var2b>8) lf_var2b=8; \ - if (lf_var1b & 0x80) { \ - lf_resb=(lf_var1b >> lf_var2b)| \ - (0xff << (8 - lf_var2b)); \ - } else { \ - lf_resb=lf_var1b >> lf_var2b; \ - } \ - save(op1,lf_resb); \ - lflags.type=t_SARb; - -#define SARW(op1,op2,load,save) \ - if (!op2) break; \ - lf_var1w=load(op1);lf_var2b=op2; \ - if (lf_var2b>16) lf_var2b=16; \ - if (lf_var1w & 0x8000) { \ - lf_resw=(lf_var1w >> lf_var2b)| \ - (0xffff << (16 - lf_var2b)); \ - } else { \ - lf_resw=lf_var1w >> lf_var2b; \ - } \ - save(op1,lf_resw); \ - lflags.type=t_SARw; - -#define SARD(op1,op2,load,save) \ - if (!op2) break; \ - lf_var2b=op2;lf_var1d=load(op1); \ - if (lf_var1d & 0x80000000) { \ - lf_resd=(lf_var1d >> lf_var2b)| \ - (0xffffffff << (32 - lf_var2b)); \ - } else { \ - lf_resd=lf_var1d >> lf_var2b; \ - } \ - save(op1,lf_resd); \ - lflags.type=t_SARd; - - - -#define DAA() \ - if (((reg_al & 0x0F)>0x09) || get_AF()) { \ - if ((reg_al > 0x99) || get_CF()) { \ - reg_al+=0x60; \ - SETFLAGBIT(CF,true); \ - } else { \ - SETFLAGBIT(CF,false); \ - } \ - reg_al+=0x06; \ - SETFLAGBIT(AF,true); \ - } else { \ - if ((reg_al > 0x99) || get_CF()) { \ - reg_al+=0x60; \ - SETFLAGBIT(CF,true); \ - } else { \ - SETFLAGBIT(CF,false); \ - } \ - SETFLAGBIT(AF,false); \ - } \ - SETFLAGBIT(SF,(reg_al&0x80)); \ - SETFLAGBIT(ZF,(reg_al==0)); \ - SETFLAGBIT(PF,parity_lookup[reg_al]); \ - lflags.type=t_UNKNOWN; - - -#define DAS() \ -{ \ - Bit8u osigned=reg_al & 0x80; \ - if (((reg_al & 0x0f) > 9) || get_AF()) { \ - if ((reg_al>0x99) || get_CF()) { \ - reg_al-=0x60; \ - SETFLAGBIT(CF,true); \ - } else { \ - SETFLAGBIT(CF,(reg_al<=0x05)); \ - } \ - reg_al-=6; \ - SETFLAGBIT(AF,true); \ - } else { \ - if ((reg_al>0x99) || get_CF()) { \ - reg_al-=0x60; \ - SETFLAGBIT(CF,true); \ - } else { \ - SETFLAGBIT(CF,false); \ - } \ - SETFLAGBIT(AF,false); \ - } \ - SETFLAGBIT(OF,osigned && ((reg_al&0x80)==0)); \ - SETFLAGBIT(SF,(reg_al&0x80)); \ - SETFLAGBIT(ZF,(reg_al==0)); \ - SETFLAGBIT(PF,parity_lookup[reg_al]); \ - lflags.type=t_UNKNOWN; \ -} - - -#define AAA() \ - SETFLAGBIT(SF,((reg_al>=0x7a) && (reg_al<=0xf9))); \ - if ((reg_al & 0xf) > 9) { \ - SETFLAGBIT(OF,(reg_al&0xf0)==0x70); \ - reg_ax += 0x106; \ - SETFLAGBIT(CF,true); \ - SETFLAGBIT(ZF,(reg_al == 0)); \ - SETFLAGBIT(AF,true); \ - } else if (get_AF()) { \ - reg_ax += 0x106; \ - SETFLAGBIT(OF,false); \ - SETFLAGBIT(CF,true); \ - SETFLAGBIT(ZF,false); \ - SETFLAGBIT(AF,true); \ - } else { \ - SETFLAGBIT(OF,false); \ - SETFLAGBIT(CF,false); \ - SETFLAGBIT(ZF,(reg_al == 0)); \ - SETFLAGBIT(AF,false); \ - } \ - SETFLAGBIT(PF,parity_lookup[reg_al]); \ - reg_al &= 0x0F; \ - lflags.type=t_UNKNOWN; - -#define AAS() \ - if ((reg_al & 0x0f)>9) { \ - SETFLAGBIT(SF,(reg_al>0x85)); \ - reg_ax -= 0x106; \ - SETFLAGBIT(OF,false); \ - SETFLAGBIT(CF,true); \ - SETFLAGBIT(AF,true); \ - } else if (get_AF()) { \ - SETFLAGBIT(OF,((reg_al>=0x80) && (reg_al<=0x85))); \ - SETFLAGBIT(SF,(reg_al<0x06) || (reg_al>0x85)); \ - reg_ax -= 0x106; \ - SETFLAGBIT(CF,true); \ - SETFLAGBIT(AF,true); \ - } else { \ - SETFLAGBIT(SF,(reg_al>=0x80)); \ - SETFLAGBIT(OF,false); \ - SETFLAGBIT(CF,false); \ - SETFLAGBIT(AF,false); \ - } \ - SETFLAGBIT(ZF,(reg_al == 0)); \ - SETFLAGBIT(PF,parity_lookup[reg_al]); \ - reg_al &= 0x0F; \ - lflags.type=t_UNKNOWN; - -#define AAM(op1) \ -{ \ - Bit8u dv=op1; \ - if (dv!=0) { \ - reg_ah=reg_al / dv; \ - reg_al=reg_al % dv; \ - SETFLAGBIT(SF,(reg_al & 0x80)); \ - SETFLAGBIT(ZF,(reg_al == 0)); \ - SETFLAGBIT(PF,parity_lookup[reg_al]); \ - SETFLAGBIT(CF,false); \ - SETFLAGBIT(OF,false); \ - SETFLAGBIT(AF,false); \ - lflags.type=t_UNKNOWN; \ - } else EXCEPTION(0); \ -} - - -//Took this from bochs, i seriously hate these weird bcd opcodes -#define AAD(op1) \ - { \ - Bit16u ax1 = reg_ah * op1; \ - Bit16u ax2 = ax1 + reg_al; \ - reg_al = (Bit8u) ax2; \ - reg_ah = 0; \ - SETFLAGBIT(CF,false); \ - SETFLAGBIT(OF,false); \ - SETFLAGBIT(AF,false); \ - SETFLAGBIT(SF,reg_al >= 0x80); \ - SETFLAGBIT(ZF,reg_al == 0); \ - SETFLAGBIT(PF,parity_lookup[reg_al]); \ - lflags.type=t_UNKNOWN; \ - } - -#define MULB(op1,load,save) \ - reg_ax=reg_al*load(op1); \ - FillFlagsNoCFOF(); \ - SETFLAGBIT(ZF,reg_al == 0); \ - if (reg_ax & 0xff00) { \ - SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ - } else { \ - SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ - } - -#define MULW(op1,load,save) \ -{ \ - Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \ - reg_ax=(Bit16u)(tempu); \ - reg_dx=(Bit16u)(tempu >> 16); \ - FillFlagsNoCFOF(); \ - SETFLAGBIT(ZF,reg_ax == 0); \ - if (reg_dx) { \ - SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ - } else { \ - SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ - } \ -} - -#define MULD(op1,load,save) \ -{ \ - Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \ - reg_eax=(Bit32u)(tempu); \ - reg_edx=(Bit32u)(tempu >> 32); \ - FillFlagsNoCFOF(); \ - SETFLAGBIT(ZF,reg_eax == 0); \ - if (reg_edx) { \ - SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ - } else { \ - SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ - } \ -} - -#define DIVB(op1,load,save) \ -{ \ - Bitu val=load(op1); \ - if (val==0) EXCEPTION(0); \ - Bitu quo=reg_ax / val; \ - Bit8u rem=(Bit8u)(reg_ax % val); \ - Bit8u quo8=(Bit8u)(quo&0xff); \ - if (quo>0xff) EXCEPTION(0); \ - reg_ah=rem; \ - reg_al=quo8; \ -} - - -#define DIVW(op1,load,save) \ -{ \ - Bitu val=load(op1); \ - if (val==0) EXCEPTION(0); \ - Bitu num=((Bit32u)reg_dx<<16)|reg_ax; \ - Bitu quo=num/val; \ - Bit16u rem=(Bit16u)(num % val); \ - Bit16u quo16=(Bit16u)(quo&0xffff); \ - if (quo!=(Bit32u)quo16) EXCEPTION(0); \ - reg_dx=rem; \ - reg_ax=quo16; \ -} - -#define DIVD(op1,load,save) \ -{ \ - Bitu val=load(op1); \ - if (val==0) EXCEPTION(0); \ - Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax; \ - Bit64u quo=num/val; \ - Bit32u rem=(Bit32u)(num % val); \ - Bit32u quo32=(Bit32u)(quo&0xffffffff); \ - if (quo!=(Bit64u)quo32) EXCEPTION(0); \ - reg_edx=rem; \ - reg_eax=quo32; \ -} - - -#define IDIVB(op1,load,save) \ -{ \ - Bits val=(Bit8s)(load(op1)); \ - if (val==0) EXCEPTION(0); \ - Bits quo=((Bit16s)reg_ax) / val; \ - Bit8s rem=(Bit8s)((Bit16s)reg_ax % val); \ - Bit8s quo8s=(Bit8s)(quo&0xff); \ - if (quo!=(Bit16s)quo8s) EXCEPTION(0); \ - reg_ah=rem; \ - reg_al=quo8s; \ -} - - -#define IDIVW(op1,load,save) \ -{ \ - Bits val=(Bit16s)(load(op1)); \ - if (val==0) EXCEPTION(0); \ - Bits num=(Bit32s)((reg_dx<<16)|reg_ax); \ - Bits quo=num/val; \ - Bit16s rem=(Bit16s)(num % val); \ - Bit16s quo16s=(Bit16s)quo; \ - if (quo!=(Bit32s)quo16s) EXCEPTION(0); \ - reg_dx=rem; \ - reg_ax=quo16s; \ -} - -#define IDIVD(op1,load,save) \ -{ \ - Bits val=(Bit32s)(load(op1)); \ - if (val==0) EXCEPTION(0); \ - Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax; \ - Bit64s quo=num/val; \ - Bit32s rem=(Bit32s)(num % val); \ - Bit32s quo32s=(Bit32s)(quo&0xffffffff); \ - if (quo!=(Bit64s)quo32s) EXCEPTION(0); \ - reg_edx=rem; \ - reg_eax=quo32s; \ -} - -#define IMULB(op1,load,save) \ -{ \ - reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \ - FillFlagsNoCFOF(); \ - if ((reg_ax & 0xff80)==0xff80 || \ - (reg_ax & 0xff80)==0x0000) { \ - SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ - } else { \ - SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ - } \ -} - - -#define IMULW(op1,load,save) \ -{ \ - Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \ - reg_ax=(Bit16s)(temps); \ - reg_dx=(Bit16s)(temps >> 16); \ - FillFlagsNoCFOF(); \ - if (((temps & 0xffff8000)==0xffff8000 || \ - (temps & 0xffff8000)==0x0000)) { \ - SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ - } else { \ - SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ - } \ -} - -#define IMULD(op1,load,save) \ -{ \ - Bit64s temps=((Bit64s)((Bit32s)reg_eax))* \ - ((Bit64s)((Bit32s)(load(op1)))); \ - reg_eax=(Bit32u)(temps); \ - reg_edx=(Bit32u)(temps >> 32); \ - FillFlagsNoCFOF(); \ - if ((reg_edx==0xffffffff) && \ - (reg_eax & 0x80000000) ) { \ - SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ - } else if ( (reg_edx==0x00000000) && \ - (reg_eax< 0x80000000) ) { \ - SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ - } else { \ - SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ - } \ -} - -#define DIMULW(op1,op2,op3,load,save) \ -{ \ - Bits res=((Bit16s)op2) * ((Bit16s)op3); \ - save(op1,res & 0xffff); \ - FillFlagsNoCFOF(); \ - if ((res> -32768) && (res<32767)) { \ - SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ - } else { \ - SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ - } \ -} - -#define DIMULD(op1,op2,op3,load,save) \ -{ \ - Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \ - save(op1,(Bit32s)res); \ - FillFlagsNoCFOF(); \ - if ((res>-((Bit64s)(2147483647)+1)) && \ - (res<(Bit64s)2147483647)) { \ - SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ - } else { \ - SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ - } \ -} - -#define GRP2B(blah) \ -{ \ - GetRM;Bitu which=(rm>>3)&7; \ - if (rm >= 0xc0) { \ - GetEArb; \ - Bit8u val=blah & 0x1f; \ - switch (which) { \ - case 0x00:ROLB(*earb,val,LoadRb,SaveRb);break; \ - case 0x01:RORB(*earb,val,LoadRb,SaveRb);break; \ - case 0x02:RCLB(*earb,val,LoadRb,SaveRb);break; \ - case 0x03:RCRB(*earb,val,LoadRb,SaveRb);break; \ - case 0x04:/* SHL and SAL are the same */ \ - case 0x06:SHLB(*earb,val,LoadRb,SaveRb);break; \ - case 0x05:SHRB(*earb,val,LoadRb,SaveRb);break; \ - case 0x07:SARB(*earb,val,LoadRb,SaveRb);break; \ - } \ - } else { \ - GetEAa; \ - Bit8u val=blah & 0x1f; \ - switch (which) { \ - case 0x00:ROLB(eaa,val,LoadMb,SaveMb);break; \ - case 0x01:RORB(eaa,val,LoadMb,SaveMb);break; \ - case 0x02:RCLB(eaa,val,LoadMb,SaveMb);break; \ - case 0x03:RCRB(eaa,val,LoadMb,SaveMb);break; \ - case 0x04:/* SHL and SAL are the same */ \ - case 0x06:SHLB(eaa,val,LoadMb,SaveMb);break; \ - case 0x05:SHRB(eaa,val,LoadMb,SaveMb);break; \ - case 0x07:SARB(eaa,val,LoadMb,SaveMb);break; \ - } \ - } \ -} - - - -#define GRP2W(blah) \ -{ \ - GetRM;Bitu which=(rm>>3)&7; \ - if (rm >= 0xc0) { \ - GetEArw; \ - Bit8u val=blah & 0x1f; \ - switch (which) { \ - case 0x00:ROLW(*earw,val,LoadRw,SaveRw);break; \ - case 0x01:RORW(*earw,val,LoadRw,SaveRw);break; \ - case 0x02:RCLW(*earw,val,LoadRw,SaveRw);break; \ - case 0x03:RCRW(*earw,val,LoadRw,SaveRw);break; \ - case 0x04:/* SHL and SAL are the same */ \ - case 0x06:SHLW(*earw,val,LoadRw,SaveRw);break; \ - case 0x05:SHRW(*earw,val,LoadRw,SaveRw);break; \ - case 0x07:SARW(*earw,val,LoadRw,SaveRw);break; \ - } \ - } else { \ - GetEAa; \ - Bit8u val=blah & 0x1f; \ - switch (which) { \ - case 0x00:ROLW(eaa,val,LoadMw,SaveMw);break; \ - case 0x01:RORW(eaa,val,LoadMw,SaveMw);break; \ - case 0x02:RCLW(eaa,val,LoadMw,SaveMw);break; \ - case 0x03:RCRW(eaa,val,LoadMw,SaveMw);break; \ - case 0x04:/* SHL and SAL are the same */ \ - case 0x06:SHLW(eaa,val,LoadMw,SaveMw);break; \ - case 0x05:SHRW(eaa,val,LoadMw,SaveMw);break; \ - case 0x07:SARW(eaa,val,LoadMw,SaveMw);break; \ - } \ - } \ -} - - -#define GRP2D(blah) \ -{ \ - GetRM;Bitu which=(rm>>3)&7; \ - if (rm >= 0xc0) { \ - GetEArd; \ - Bit8u val=blah & 0x1f; \ - switch (which) { \ - case 0x00:ROLD(*eard,val,LoadRd,SaveRd);break; \ - case 0x01:RORD(*eard,val,LoadRd,SaveRd);break; \ - case 0x02:RCLD(*eard,val,LoadRd,SaveRd);break; \ - case 0x03:RCRD(*eard,val,LoadRd,SaveRd);break; \ - case 0x04:/* SHL and SAL are the same */ \ - case 0x06:SHLD(*eard,val,LoadRd,SaveRd);break; \ - case 0x05:SHRD(*eard,val,LoadRd,SaveRd);break; \ - case 0x07:SARD(*eard,val,LoadRd,SaveRd);break; \ - } \ - } else { \ - GetEAa; \ - Bit8u val=blah & 0x1f; \ - switch (which) { \ - case 0x00:ROLD(eaa,val,LoadMd,SaveMd);break; \ - case 0x01:RORD(eaa,val,LoadMd,SaveMd);break; \ - case 0x02:RCLD(eaa,val,LoadMd,SaveMd);break; \ - case 0x03:RCRD(eaa,val,LoadMd,SaveMd);break; \ - case 0x04:/* SHL and SAL are the same */ \ - case 0x06:SHLD(eaa,val,LoadMd,SaveMd);break; \ - case 0x05:SHRD(eaa,val,LoadMd,SaveMd);break; \ - case 0x07:SARD(eaa,val,LoadMd,SaveMd);break; \ - } \ - } \ -} - -/* let's hope bochs has it correct with the higher than 16 shifts */ -/* double-precision shift left has low bits in second argument */ -#define DSHLW(op1,op2,op3,load,save) \ - Bit8u val=op3 & 0x1F; \ - if (!val) break; \ - lf_var2b=val;lf_var1d=(load(op1)<<16)|op2; \ - Bit32u tempd=lf_var1d << lf_var2b; \ - if (lf_var2b>16) tempd |= (op2 << (lf_var2b - 16)); \ - lf_resw=(Bit16u)(tempd >> 16); \ - save(op1,lf_resw); \ - lflags.type=t_DSHLw; - -#define DSHLD(op1,op2,op3,load,save) \ - Bit8u val=op3 & 0x1F; \ - if (!val) break; \ - lf_var2b=val;lf_var1d=load(op1); \ - lf_resd=(lf_var1d << lf_var2b) | (op2 >> (32-lf_var2b)); \ - save(op1,lf_resd); \ - lflags.type=t_DSHLd; - -/* double-precision shift right has high bits in second argument */ -#define DSHRW(op1,op2,op3,load,save) \ - Bit8u val=op3 & 0x1F; \ - if (!val) break; \ - lf_var2b=val;lf_var1d=(op2<<16)|load(op1); \ - Bit32u tempd=lf_var1d >> lf_var2b; \ - if (lf_var2b>16) tempd |= (op2 << (32-lf_var2b )); \ - lf_resw=(Bit16u)(tempd); \ - save(op1,lf_resw); \ - lflags.type=t_DSHRw; - -#define DSHRD(op1,op2,op3,load,save) \ - Bit8u val=op3 & 0x1F; \ - if (!val) break; \ - lf_var2b=val;lf_var1d=load(op1); \ - lf_resd=(lf_var1d >> lf_var2b) | (op2 << (32-lf_var2b)); \ - save(op1,lf_resd); \ - lflags.type=t_DSHRd; - -#define BSWAP(op1) \ - op1 = (op1>>24)|((op1>>8)&0xFF00)|((op1<<8)&0xFF0000)|((op1<<24)&0xFF000000); diff --git a/src/cpu/lazyflags.h b/src/cpu/lazyflags.h deleted file mode 100644 index 81eacd6..0000000 --- a/src/cpu/lazyflags.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#if !defined __LAZYFLAGS_H -#define __LAZYFLAG_H - -//Flag Handling -Bit32u get_CF(void); -Bit32u get_AF(void); -Bit32u get_ZF(void); -Bit32u get_SF(void); -Bit32u get_OF(void); -Bit32u get_PF(void); - -Bitu FillFlags(void); -void FillFlagsNoCFOF(void); -void DestroyConditionFlags(void); - -#include "regs.h" - -struct LazyFlags { - GenReg32 var1,var2,res; - Bitu type; - Bitu prev_type; - Bitu oldcf; -}; - -extern LazyFlags lfags; - -#define lf_var1b lflags.var1.byte[BL_INDEX] -#define lf_var2b lflags.var2.byte[BL_INDEX] -#define lf_resb lflags.res.byte[BL_INDEX] - -#define lf_var1w lflags.var1.word[W_INDEX] -#define lf_var2w lflags.var2.word[W_INDEX] -#define lf_resw lflags.res.word[W_INDEX] - -#define lf_var1d lflags.var1.dword[DW_INDEX] -#define lf_var2d lflags.var2.dword[DW_INDEX] -#define lf_resd lflags.res.dword[DW_INDEX] - - -extern LazyFlags lflags; - -#define SETFLAGSb(FLAGB) \ -{ \ - SETFLAGBIT(OF,get_OF()); \ - lflags.type=t_UNKNOWN; \ - CPU_SetFlags(FLAGB,FMASK_NORMAL & 0xff); \ -} - -#define SETFLAGSw(FLAGW) \ -{ \ - lflags.type=t_UNKNOWN; \ - CPU_SetFlagsw(FLAGW); \ -} - -#define SETFLAGSd(FLAGD) \ -{ \ - lflags.type=t_UNKNOWN; \ - CPU_SetFlagsd(FLAGD); \ -} - -#define LoadCF SETFLAGBIT(CF,get_CF()); -#define LoadZF SETFLAGBIT(ZF,get_ZF()); -#define LoadSF SETFLAGBIT(SF,get_SF()); -#define LoadOF SETFLAGBIT(OF,get_OF()); -#define LoadAF SETFLAGBIT(AF,get_AF()); - -#define TFLG_O (get_OF()) -#define TFLG_NO (!get_OF()) -#define TFLG_B (get_CF()) -#define TFLG_NB (!get_CF()) -#define TFLG_Z (get_ZF()) -#define TFLG_NZ (!get_ZF()) -#define TFLG_BE (get_CF() || get_ZF()) -#define TFLG_NBE (!get_CF() && !get_ZF()) -#define TFLG_S (get_SF()) -#define TFLG_NS (!get_SF()) -#define TFLG_P (get_PF()) -#define TFLG_NP (!get_PF()) -#define TFLG_L ((get_SF()!=0) != (get_OF()!=0)) -#define TFLG_NL ((get_SF()!=0) == (get_OF()!=0)) -#define TFLG_LE (get_ZF() || ((get_SF()!=0) != (get_OF()!=0))) -#define TFLG_NLE (!get_ZF() && ((get_SF()!=0) == (get_OF()!=0))) - -//Types of Flag changing instructions -enum { - t_UNKNOWN=0, - t_ADDb,t_ADDw,t_ADDd, - t_ORb,t_ORw,t_ORd, - t_ADCb,t_ADCw,t_ADCd, - t_SBBb,t_SBBw,t_SBBd, - t_ANDb,t_ANDw,t_ANDd, - t_SUBb,t_SUBw,t_SUBd, - t_XORb,t_XORw,t_XORd, - t_CMPb,t_CMPw,t_CMPd, - t_INCb,t_INCw,t_INCd, - t_DECb,t_DECw,t_DECd, - t_TESTb,t_TESTw,t_TESTd, - t_SHLb,t_SHLw,t_SHLd, - t_SHRb,t_SHRw,t_SHRd, - t_SARb,t_SARw,t_SARd, - t_ROLb,t_ROLw,t_ROLd, - t_RORb,t_RORw,t_RORd, - t_RCLb,t_RCLw,t_RCLd, - t_RCRb,t_RCRw,t_RCRd, - t_NEGb,t_NEGw,t_NEGd, - - t_DSHLw,t_DSHLd, - t_DSHRw,t_DSHRd, - t_MUL,t_DIV, - t_NOTDONE, - t_LASTFLAG -}; - -#endif diff --git a/src/cpu/modrm.cpp b/src/cpu/modrm.cpp index a348d2f..56a695e 100644 --- a/src/cpu/modrm.cpp +++ b/src/cpu/modrm.cpp @@ -1,210 +1,210 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "cpu.h" - - -Bit8u * lookupRMregb[]= -{ - ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al, - ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl, - ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl, - ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl, - ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah, - ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch, - ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh, - ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh, - - ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al, - ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl, - ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl, - ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl, - ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah, - ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch, - ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh, - ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh, - - ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al, - ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl, - ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl, - ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl, - ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah, - ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch, - ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh, - ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh, - - ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al, - ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl, - ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl, - ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl, - ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah, - ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch, - ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh, - ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh -}; - -Bit16u * lookupRMregw[]={ - ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax, - ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx, - ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx, - ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx, - ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp, - ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp, - ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si, - ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di, - - ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax, - ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx, - ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx, - ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx, - ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp, - ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp, - ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si, - ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di, - - ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax, - ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx, - ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx, - ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx, - ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp, - ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp, - ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si, - ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di, - - ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax, - ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx, - ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx, - ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx, - ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp, - ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp, - ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si, - ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di -}; - -Bit32u * lookupRMregd[256]={ - ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax, - ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx, - ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx, - ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx, - ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp, - ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp, - ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi, - ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi, - - ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax, - ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx, - ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx, - ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx, - ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp, - ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp, - ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi, - ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi, - - ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax, - ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx, - ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx, - ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx, - ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp, - ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp, - ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi, - ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi, - - ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax, - ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx, - ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx, - ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx, - ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp, - ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp, - ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi, - ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi -}; - - -Bit8u * lookupRMEAregb[256]={ -/* 12 lines of 16*0 should give nice errors when used */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, - ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, - ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, - ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, - ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, - ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, - ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, - ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh -}; - -Bit16u * lookupRMEAregw[256]={ -/* 12 lines of 16*0 should give nice errors when used */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, - ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, - ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, - ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, - ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, - ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, - ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, - ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di -}; - -Bit32u * lookupRMEAregd[256]={ -/* 12 lines of 16*0 should give nice errors when used */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, - ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, - ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, - ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, - ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, - ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, - ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, - ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi -}; - - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "cpu.h" + + +Bit8u * lookupRMregb[]= +{ + ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al, + ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl, + ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl, + ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl, + ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah, + ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch, + ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh, + ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh, + + ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al, + ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl, + ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl, + ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl, + ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah, + ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch, + ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh, + ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh, + + ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al, + ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl, + ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl, + ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl, + ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah, + ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch, + ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh, + ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh, + + ®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al, + ®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl, + ®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl, + ®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl, + ®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah, + ®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch, + ®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh, + ®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh +}; + +Bit16u * lookupRMregw[]={ + ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax, + ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx, + ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx, + ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx, + ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp, + ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp, + ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si, + ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di, + + ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax, + ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx, + ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx, + ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx, + ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp, + ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp, + ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si, + ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di, + + ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax, + ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx, + ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx, + ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx, + ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp, + ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp, + ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si, + ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di, + + ®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax, + ®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx, + ®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx, + ®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx, + ®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp, + ®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp, + ®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si, + ®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di +}; + +Bit32u * lookupRMregd[256]={ + ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax, + ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx, + ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx, + ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx, + ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp, + ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp, + ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi, + ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi, + + ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax, + ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx, + ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx, + ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx, + ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp, + ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp, + ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi, + ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi, + + ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax, + ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx, + ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx, + ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx, + ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp, + ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp, + ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi, + ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi, + + ®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax, + ®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx, + ®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx, + ®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx, + ®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp, + ®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp, + ®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi, + ®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi +}; + + +Bit8u * lookupRMEAregb[256]={ +/* 12 lines of 16*0 should give nice errors when used */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, + ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, + ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, + ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, + ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, + ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, + ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh, + ®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh +}; + +Bit16u * lookupRMEAregw[256]={ +/* 12 lines of 16*0 should give nice errors when used */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, + ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, + ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, + ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, + ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, + ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, + ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di, + ®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di +}; + +Bit32u * lookupRMEAregd[256]={ +/* 12 lines of 16*0 should give nice errors when used */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, + ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, + ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, + ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, + ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, + ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, + ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi, + ®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi +}; + + diff --git a/src/cpu/modrm.h b/src/cpu/modrm.h index 1954af4..ad0da0d 100644 --- a/src/cpu/modrm.h +++ b/src/cpu/modrm.h @@ -1,64 +1,76 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -extern Bit8u * lookupRMregb[]; -extern Bit16u * lookupRMregw[]; -extern Bit32u * lookupRMregd[]; -extern Bit8u * lookupRMEAregb[256]; -extern Bit16u * lookupRMEAregw[256]; -extern Bit32u * lookupRMEAregd[256]; - -#define GetRM \ - Bit8u rm=Fetchb(); - -#define Getrb \ - Bit8u * rmrb; \ - rmrb=lookupRMregb[rm]; - -#define Getrw \ - Bit16u * rmrw; \ - rmrw=lookupRMregw[rm]; - -#define Getrd \ - Bit32u * rmrd; \ - rmrd=lookupRMregd[rm]; - - -#define GetRMrb \ - GetRM; \ - Getrb; - -#define GetRMrw \ - GetRM; \ - Getrw; - -#define GetRMrd \ - GetRM; \ - Getrd; - - -#define GetEArb \ - Bit8u * earb=lookupRMEAregb[rm]; - -#define GetEArw \ - Bit16u * earw=lookupRMEAregw[rm]; - -#define GetEArd \ - Bit32u * eard=lookupRMEAregd[rm]; - - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +extern Bit8u * lookupRMregb[]; +extern Bit16u * lookupRMregw[]; +extern Bit32u * lookupRMregd[]; +extern Bit8u * lookupRMEAregb[256]; +extern Bit16u * lookupRMEAregw[256]; +extern Bit32u * lookupRMEAregd[256]; + +#define GetRM \ + Bit8u rm=Fetchb(); + +#define Getrb \ + Bit8u * rmrb; \ + rmrb=lookupRMregb[rm]; + +#define Getrw \ + Bit16u * rmrw; \ + rmrw=lookupRMregw[rm]; + +#define Getrd \ + Bit32u * rmrd; \ + rmrd=lookupRMregd[rm]; + + +#define GetRMrb \ + GetRM; \ + Getrb; + +#define GetRMrw \ + GetRM; \ + Getrw; + +#define GetRMrd \ + GetRM; \ + Getrd; + + +#define GetEArb \ + union { \ + Bit8u * earb; \ + Bit8s * earbs; \ + }; \ + earb=lookupRMEAregb[rm]; + +#define GetEArw \ + union { \ + Bit16u * earw; \ + Bit16s * earws; \ + }; \ + earw=lookupRMEAregw[rm]; + +#define GetEArd \ + union { \ + Bit32u * eard; \ + Bit32s * eards; \ + }; \ + eard=lookupRMEAregd[rm]; + + diff --git a/src/cpu/paging.cpp b/src/cpu/paging.cpp deleted file mode 100644 index 3aa4d0a..0000000 --- a/src/cpu/paging.cpp +++ /dev/null @@ -1,891 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: paging.cpp,v 1.35 2008/12/04 21:09:32 c2woody Exp $ */ - -#include -#include -#include - -#include "dosbox.h" -#include "mem.h" -#include "paging.h" -#include "regs.h" -#include "lazyflags.h" -#include "cpu.h" -#include "debug.h" -#include "setup.h" - -#define LINK_TOTAL (64*1024) - -#define USERWRITE_PROHIBITED ((cpu.cpl&cpu.mpl)==3) - - -PagingBlock paging; - - -Bitu PageHandler::readb(PhysPt addr) { - E_Exit("No byte handler for read from %d",addr); - return 0; -} -Bitu PageHandler::readw(PhysPt addr) { - return - (readb(addr+0) << 0) | - (readb(addr+1) << 8); -} -Bitu PageHandler::readd(PhysPt addr) { - return - (readb(addr+0) << 0) | - (readb(addr+1) << 8) | - (readb(addr+2) << 16) | - (readb(addr+3) << 24); -} - -void PageHandler::writeb(PhysPt addr,Bitu /*val*/) { - E_Exit("No byte handler for write to %d",addr); -} - -void PageHandler::writew(PhysPt addr,Bitu val) { - writeb(addr+0,(Bit8u) (val >> 0)); - writeb(addr+1,(Bit8u) (val >> 8)); -} -void PageHandler::writed(PhysPt addr,Bitu val) { - writeb(addr+0,(Bit8u) (val >> 0)); - writeb(addr+1,(Bit8u) (val >> 8)); - writeb(addr+2,(Bit8u) (val >> 16)); - writeb(addr+3,(Bit8u) (val >> 24)); -} - -HostPt PageHandler::GetHostReadPt(Bitu /*phys_page*/) { - return 0; -} - -HostPt PageHandler::GetHostWritePt(Bitu /*phys_page*/) { - return 0; -} - -bool PageHandler::readb_checked(PhysPt addr, Bit8u * val) { - *val=(Bit8u)readb(addr); return false; -} -bool PageHandler::readw_checked(PhysPt addr, Bit16u * val) { - *val=(Bit16u)readw(addr); return false; -} -bool PageHandler::readd_checked(PhysPt addr, Bit32u * val) { - *val=(Bit32u)readd(addr); return false; -} -bool PageHandler::writeb_checked(PhysPt addr,Bitu val) { - writeb(addr,val); return false; -} -bool PageHandler::writew_checked(PhysPt addr,Bitu val) { - writew(addr,val); return false; -} -bool PageHandler::writed_checked(PhysPt addr,Bitu val) { - writed(addr,val); return false; -} - - - -struct PF_Entry { - Bitu cs; - Bitu eip; - Bitu page_addr; - Bitu mpl; -}; - -#define PF_QUEUESIZE 16 -static struct { - Bitu used; - PF_Entry entries[PF_QUEUESIZE]; -} pf_queue; - -static Bits PageFaultCore(void) { - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=1; - Bits ret=CPU_Core_Full_Run(); - CPU_CycleLeft+=CPU_Cycles; - if (ret<0) E_Exit("Got a dosbox close machine in pagefault core?"); - if (ret) - return ret; - if (!pf_queue.used) E_Exit("PF Core without PF"); - PF_Entry * entry=&pf_queue.entries[pf_queue.used-1]; - X86PageEntry pentry; - pentry.load=phys_readd(entry->page_addr); - if (pentry.block.p && entry->cs == SegValue(cs) && entry->eip==reg_eip) { - cpu.mpl=entry->mpl; - return -1; - } - return 0; -} -#if C_DEBUG -Bitu DEBUG_EnableDebugger(void); -#endif - -bool first=false; - -void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu faultcode) { - /* Save the state of the cpu cores */ - LazyFlags old_lflags; - memcpy(&old_lflags,&lflags,sizeof(LazyFlags)); - CPU_Decoder * old_cpudecoder; - old_cpudecoder=cpudecoder; - cpudecoder=&PageFaultCore; - paging.cr2=lin_addr; - PF_Entry * entry=&pf_queue.entries[pf_queue.used++]; - LOG(LOG_PAGING,LOG_NORMAL)("PageFault at %X type [%x] queue %d",lin_addr,faultcode,pf_queue.used); -// LOG_MSG("EAX:%04X ECX:%04X EDX:%04X EBX:%04X",reg_eax,reg_ecx,reg_edx,reg_ebx); -// LOG_MSG("CS:%04X EIP:%08X SS:%04x SP:%08X",SegValue(cs),reg_eip,SegValue(ss),reg_esp); - entry->cs=SegValue(cs); - entry->eip=reg_eip; - entry->page_addr=page_addr; - entry->mpl=cpu.mpl; - cpu.mpl=3; - - CPU_Exception(EXCEPTION_PF,faultcode); -#if C_DEBUG -// DEBUG_EnableDebugger(); -#endif - DOSBOX_RunMachine(); - pf_queue.used--; - LOG(LOG_PAGING,LOG_NORMAL)("Left PageFault for %x queue %d",lin_addr,pf_queue.used); - memcpy(&lflags,&old_lflags,sizeof(LazyFlags)); - cpudecoder=old_cpudecoder; -// LOG_MSG("SS:%04x SP:%08X",SegValue(ss),reg_esp); -} - -static INLINE void InitPageUpdateLink(Bitu relink,PhysPt addr) { - if (relink==0) return; - if (paging.links.used) { - if (paging.links.entries[paging.links.used-1]==(addr>>12)) { - paging.links.used--; - PAGING_UnlinkPages(addr>>12,1); - } - } - if (relink>1) PAGING_LinkPage_ReadOnly(addr>>12,relink); -} - -static INLINE void InitPageCheckPresence(PhysPt lin_addr,bool writing,X86PageEntry& table,X86PageEntry& entry) { - Bitu lin_page=lin_addr >> 12; - Bitu d_index=lin_page >> 10; - Bitu t_index=lin_page & 0x3ff; - Bitu table_addr=(paging.base.page<<12)+d_index*4; - table.load=phys_readd(table_addr); - if (!table.block.p) { - LOG(LOG_PAGING,LOG_NORMAL)("NP Table"); - PAGING_PageFault(lin_addr,table_addr, - (writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04)); - table.load=phys_readd(table_addr); - if (GCC_UNLIKELY(!table.block.p)) - E_Exit("Pagefault didn't correct table"); - } - Bitu entry_addr=(table.block.base<<12)+t_index*4; - entry.load=phys_readd(entry_addr); - if (!entry.block.p) { -// LOG(LOG_PAGING,LOG_NORMAL)("NP Page"); - PAGING_PageFault(lin_addr,entry_addr, - (writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04)); - entry.load=phys_readd(entry_addr); - if (GCC_UNLIKELY(!entry.block.p)) - E_Exit("Pagefault didn't correct page"); - } -} - -static INLINE bool InitPageCheckPresence_CheckOnly(PhysPt lin_addr,bool writing,X86PageEntry& table,X86PageEntry& entry) { - Bitu lin_page=lin_addr >> 12; - Bitu d_index=lin_page >> 10; - Bitu t_index=lin_page & 0x3ff; - Bitu table_addr=(paging.base.page<<12)+d_index*4; - table.load=phys_readd(table_addr); - if (!table.block.p) { - paging.cr2=lin_addr; - cpu.exception.which=EXCEPTION_PF; - cpu.exception.error=(writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04); - return false; - } - Bitu entry_addr=(table.block.base<<12)+t_index*4; - entry.load=phys_readd(entry_addr); - if (!entry.block.p) { - paging.cr2=lin_addr; - cpu.exception.which=EXCEPTION_PF; - cpu.exception.error=(writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04); - return false; - } - return true; -} - -// check if a user-level memory access would trigger a privilege page fault -static INLINE bool InitPage_CheckUseraccess(Bitu u1,Bitu u2) { - switch (CPU_ArchitectureType) { - case CPU_ARCHTYPE_MIXED: - case CPU_ARCHTYPE_386SLOW: - case CPU_ARCHTYPE_386FAST: - default: - return ((u1)==0) && ((u2)==0); - case CPU_ARCHTYPE_486OLDSLOW: - case CPU_ARCHTYPE_486NEWSLOW: - case CPU_ARCHTYPE_PENTIUMSLOW: - return ((u1)==0) || ((u2)==0); - } -} - - -class InitPageHandler : public PageHandler { -public: - InitPageHandler() { - flags=PFLAG_INIT|PFLAG_NOCODE; - } - Bitu readb(PhysPt addr) { - Bitu needs_reset=InitPage(addr,false); - Bit8u val=mem_readb(addr); - InitPageUpdateLink(needs_reset,addr); - return val; - } - Bitu readw(PhysPt addr) { - Bitu needs_reset=InitPage(addr,false); - Bit16u val=mem_readw(addr); - InitPageUpdateLink(needs_reset,addr); - return val; - } - Bitu readd(PhysPt addr) { - Bitu needs_reset=InitPage(addr,false); - Bit32u val=mem_readd(addr); - InitPageUpdateLink(needs_reset,addr); - return val; - } - void writeb(PhysPt addr,Bitu val) { - Bitu needs_reset=InitPage(addr,true); - mem_writeb(addr,val); - InitPageUpdateLink(needs_reset,addr); - } - void writew(PhysPt addr,Bitu val) { - Bitu needs_reset=InitPage(addr,true); - mem_writew(addr,val); - InitPageUpdateLink(needs_reset,addr); - } - void writed(PhysPt addr,Bitu val) { - Bitu needs_reset=InitPage(addr,true); - mem_writed(addr,val); - InitPageUpdateLink(needs_reset,addr); - } - bool readb_checked(PhysPt addr, Bit8u * val) { - if (InitPageCheckOnly(addr,false)) { - *val=mem_readb(addr); - return false; - } else return true; - } - bool readw_checked(PhysPt addr, Bit16u * val) { - if (InitPageCheckOnly(addr,false)){ - *val=mem_readw(addr); - return false; - } else return true; - } - bool readd_checked(PhysPt addr, Bit32u * val) { - if (InitPageCheckOnly(addr,false)) { - *val=mem_readd(addr); - return false; - } else return true; - } - bool writeb_checked(PhysPt addr,Bitu val) { - if (InitPageCheckOnly(addr,true)) { - mem_writeb(addr,val); - return false; - } else return true; - } - bool writew_checked(PhysPt addr,Bitu val) { - if (InitPageCheckOnly(addr,true)) { - mem_writew(addr,val); - return false; - } else return true; - } - bool writed_checked(PhysPt addr,Bitu val) { - if (InitPageCheckOnly(addr,true)) { - mem_writed(addr,val); - return false; - } else return true; - } - Bitu InitPage(Bitu lin_addr,bool writing) { - Bitu lin_page=lin_addr >> 12; - Bitu phys_page; - if (paging.enabled) { - X86PageEntry table; - X86PageEntry entry; - InitPageCheckPresence(lin_addr,writing,table,entry); - - // 0: no action - // 1: can (but currently does not) fail a user-level access privilege check - // 2: can (but currently does not) fail a write privilege check - // 3: fails a privilege check - Bitu priv_check=0; - if (InitPage_CheckUseraccess(entry.block.us,table.block.us)) { - if ((cpu.cpl&cpu.mpl)==3) priv_check=3; - else { - switch (CPU_ArchitectureType) { - case CPU_ARCHTYPE_MIXED: - case CPU_ARCHTYPE_386FAST: - default: -// priv_check=0; // default - break; - case CPU_ARCHTYPE_386SLOW: - case CPU_ARCHTYPE_486OLDSLOW: - case CPU_ARCHTYPE_486NEWSLOW: - case CPU_ARCHTYPE_PENTIUMSLOW: - priv_check=1; - break; - } - } - } - if ((entry.block.wr==0) || (table.block.wr==0)) { - // page is write-protected for user mode - if (priv_check==0) { - switch (CPU_ArchitectureType) { - case CPU_ARCHTYPE_MIXED: - case CPU_ARCHTYPE_386FAST: - default: -// priv_check=0; // default - break; - case CPU_ARCHTYPE_386SLOW: - case CPU_ARCHTYPE_486OLDSLOW: - case CPU_ARCHTYPE_486NEWSLOW: - case CPU_ARCHTYPE_PENTIUMSLOW: - priv_check=2; - break; - } - } - // check if actually failing the write-protected check - if (writing && USERWRITE_PROHIBITED) priv_check=3; - } - if (priv_check==3) { - LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x", - cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr); - PAGING_PageFault(lin_addr,(table.block.base<<12)+(lin_page & 0x3ff)*4,0x05 | (writing?0x02:0x00)); - priv_check=0; - } - - if (!table.block.a) { - table.block.a=1; // set page table accessed - phys_writed((paging.base.page<<12)+(lin_page >> 10)*4,table.load); - } - if ((!entry.block.a) || (!entry.block.d)) { - entry.block.a=1; // set page accessed - - // page is dirty if we're writing to it, or if we're reading but the - // page will be fully linked so we can't track later writes - if (writing || (priv_check==0)) entry.block.d=1; // mark page as dirty - - phys_writed((table.block.base<<12)+(lin_page & 0x3ff)*4,entry.load); - } - - phys_page=entry.block.base; - - // now see how the page should be linked best, if we need to catch privilege - // checks later on it should be linked as read-only page - if (priv_check==0) { - // if reading we could link the page as read-only to later cacth writes, - // will slow down pretty much but allows catching all dirty events - PAGING_LinkPage(lin_page,phys_page); - } else { - if (priv_check==1) { - PAGING_LinkPage(lin_page,phys_page); - return 1; - } else if (writing) { - PageHandler * handler=MEM_GetPageHandler(phys_page); - PAGING_LinkPage(lin_page,phys_page); - if (!(handler->flags & PFLAG_READABLE)) return 1; - if (!(handler->flags & PFLAG_WRITEABLE)) return 1; - if (get_tlb_read(lin_addr)!=get_tlb_write(lin_addr)) return 1; - if (phys_page>1) return phys_page; - else return 1; - } else { - PAGING_LinkPage_ReadOnly(lin_page,phys_page); - } - } - } else { - if (lin_page> 12; - if (paging.enabled) { - X86PageEntry table; - X86PageEntry entry; - if (!InitPageCheckPresence_CheckOnly(lin_addr,writing,table,entry)) return false; - - if (!USERWRITE_PROHIBITED) return true; - - if (InitPage_CheckUseraccess(entry.block.us,table.block.us) || - (((entry.block.wr==0) || (table.block.wr==0)) && writing)) { - LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x", - cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr); - paging.cr2=lin_addr; - cpu.exception.which=EXCEPTION_PF; - cpu.exception.error=0x05 | (writing?0x02:0x00); - return false; - } - } else { - Bitu phys_page; - if (lin_page> 12; - Bitu phys_page; - if (paging.enabled) { - X86PageEntry table; - X86PageEntry entry; - InitPageCheckPresence(lin_addr,false,table,entry); - - if (!table.block.a) { - table.block.a=1; //Set access - phys_writed((paging.base.page<<12)+(lin_page >> 10)*4,table.load); - } - if (!entry.block.a) { - entry.block.a=1; //Set access - phys_writed((table.block.base<<12)+(lin_page & 0x3ff)*4,entry.load); - } - phys_page=entry.block.base; - // maybe use read-only page here if possible - } else { - if (lin_page1) tlb_addr=get_tlb_read(addr); - else tlb_addr=get_tlb_write(addr); - host_writeb(tlb_addr+addr,(Bit8u)(val&0xff)); - return false; - } - return true; - } - bool writew_checked(PhysPt addr,Bitu val) { - Bitu writecode=InitPageCheckOnly(addr,(Bit16u)(val&0xffff)); - if (writecode) { - HostPt tlb_addr; - if (writecode>1) tlb_addr=get_tlb_read(addr); - else tlb_addr=get_tlb_write(addr); - host_writew(tlb_addr+addr,(Bit16u)(val&0xffff)); - return false; - } - return true; - } - bool writed_checked(PhysPt addr,Bitu val) { - Bitu writecode=InitPageCheckOnly(addr,(Bit32u)val); - if (writecode) { - HostPt tlb_addr; - if (writecode>1) tlb_addr=get_tlb_read(addr); - else tlb_addr=get_tlb_write(addr); - host_writed(tlb_addr+addr,(Bit32u)val); - return false; - } - return true; - } - void InitPage(Bitu lin_addr,Bitu val) { - Bitu lin_page=lin_addr >> 12; - Bitu phys_page; - if (paging.enabled) { - if (!USERWRITE_PROHIBITED) return; - - X86PageEntry table; - X86PageEntry entry; - InitPageCheckPresence(lin_addr,true,table,entry); - - LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x", - cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr); - PAGING_PageFault(lin_addr,(table.block.base<<12)+(lin_page & 0x3ff)*4,0x07); - - if (!table.block.a) { - table.block.a=1; //Set access - phys_writed((paging.base.page<<12)+(lin_page >> 10)*4,table.load); - } - if ((!entry.block.a) || (!entry.block.d)) { - entry.block.a=1; //Set access - entry.block.d=1; //Set dirty - phys_writed((table.block.base<<12)+(lin_page & 0x3ff)*4,entry.load); - } - phys_page=entry.block.base; - PAGING_LinkPage(lin_page,phys_page); - } else { - if (lin_page> 12; - if (paging.enabled) { - if (!USERWRITE_PROHIBITED) return 2; - - X86PageEntry table; - X86PageEntry entry; - if (!InitPageCheckPresence_CheckOnly(lin_addr,true,table,entry)) return 0; - - if (InitPage_CheckUseraccess(entry.block.us,table.block.us) || (((entry.block.wr==0) || (table.block.wr==0)))) { - LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x", - cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr); - paging.cr2=lin_addr; - cpu.exception.which=EXCEPTION_PF; - cpu.exception.error=0x07; - return 0; - } - PAGING_LinkPage(lin_page,entry.block.base); - } else { - Bitu phys_page; - if (lin_page> 12; - Bitu phys_page; - if (paging.enabled) { - X86PageEntry table; - X86PageEntry entry; - InitPageCheckPresence(lin_addr,true,table,entry); - - if (!table.block.a) { - table.block.a=1; //Set access - phys_writed((paging.base.page<<12)+(lin_page >> 10)*4,table.load); - } - if (!entry.block.a) { - entry.block.a=1; //Set access - phys_writed((table.block.base<<12)+(lin_page & 0x3ff)*4,entry.load); - } - phys_page=entry.block.base; - } else { - if (lin_page> 10; - Bitu t_index=page & 0x3ff; - X86PageEntry table; - table.load=phys_readd((paging.base.page<<12)+d_index*4); - if (!table.block.p) return false; - X86PageEntry entry; - entry.load=phys_readd((table.block.base<<12)+t_index*4); - if (!entry.block.p) return false; - page=entry.block.base; - } else { - if (page>12,1); - init_page_handler_userro.InitPageForced(lin_addr); - return true; - } - return false; -} - -#if defined(USE_FULL_TLB) -void PAGING_InitTLB(void) { - for (Bitu i=0;i0;paging.links.used--) { - Bitu page=*entries++; - paging.tlb.read[page]=0; - paging.tlb.write[page]=0; - paging.tlb.readhandler[page]=&init_page_handler; - paging.tlb.writehandler[page]=&init_page_handler; - } - paging.links.used=0; -} - -void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) { - for (;pages>0;pages--) { - paging.tlb.read[lin_page]=0; - paging.tlb.write[lin_page]=0; - paging.tlb.readhandler[lin_page]=&init_page_handler; - paging.tlb.writehandler[lin_page]=&init_page_handler; - lin_page++; - } -} - -void PAGING_MapPage(Bitu lin_page,Bitu phys_page) { - if (lin_page=TLB_SIZE || phys_page>=TLB_SIZE) - E_Exit("Illegal page"); - - if (paging.links.used>=PAGING_LINKS) { - LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache"); - PAGING_ClearTLB(); - } - - paging.tlb.phys_page[lin_page]=phys_page; - if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=handler->GetHostReadPt(phys_page)-lin_base; - else paging.tlb.read[lin_page]=0; - if (handler->flags & PFLAG_WRITEABLE) paging.tlb.write[lin_page]=handler->GetHostWritePt(phys_page)-lin_base; - else paging.tlb.write[lin_page]=0; - - paging.links.entries[paging.links.used++]=lin_page; - paging.tlb.readhandler[lin_page]=handler; - paging.tlb.writehandler[lin_page]=handler; -} - -void PAGING_LinkPage_ReadOnly(Bitu lin_page,Bitu phys_page) { - PageHandler * handler=MEM_GetPageHandler(phys_page); - Bitu lin_base=lin_page << 12; - if (lin_page>=TLB_SIZE || phys_page>=TLB_SIZE) - E_Exit("Illegal page"); - - if (paging.links.used>=PAGING_LINKS) { - LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache"); - PAGING_ClearTLB(); - } - - paging.tlb.phys_page[lin_page]=phys_page; - if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=handler->GetHostReadPt(phys_page)-lin_base; - else paging.tlb.read[lin_page]=0; - paging.tlb.write[lin_page]=0; - - paging.links.entries[paging.links.used++]=lin_page; - paging.tlb.readhandler[lin_page]=handler; - paging.tlb.writehandler[lin_page]=&init_page_handler_userro; -} - -#else - -static INLINE void InitTLBInt(tlb_entry *bank) { - for (Bitu i=0;i0;paging.links.used--) { - Bitu page=*entries++; - tlb_entry *entry = get_tlb_entry(page<<12); - entry->read=0; - entry->write=0; - entry->readhandler=&init_page_handler; - entry->writehandler=&init_page_handler; - } - paging.links.used=0; -} - -void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) { - for (;pages>0;pages--) { - tlb_entry *entry = get_tlb_entry(lin_page<<12); - entry->read=0; - entry->write=0; - entry->readhandler=&init_page_handler; - entry->writehandler=&init_page_handler; - lin_page++; - } -} - -void PAGING_MapPage(Bitu lin_page,Bitu phys_page) { - if (lin_page=(TLB_SIZE*(TLB_BANKS+1)) || phys_page>=(TLB_SIZE*(TLB_BANKS+1))) - E_Exit("Illegal page"); - - if (paging.links.used>=PAGING_LINKS) { - LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache"); - PAGING_ClearTLB(); - } - - tlb_entry *entry = get_tlb_entry(lin_base); - entry->phys_page=phys_page; - if (handler->flags & PFLAG_READABLE) entry->read=handler->GetHostReadPt(phys_page)-lin_base; - else entry->read=0; - if (handler->flags & PFLAG_WRITEABLE) entry->write=handler->GetHostWritePt(phys_page)-lin_base; - else entry->write=0; - - paging.links.entries[paging.links.used++]=lin_page; - entry->readhandler=handler; - entry->writehandler=handler; -} - -void PAGING_LinkPage_ReadOnly(Bitu lin_page,Bitu phys_page) { - PageHandler * handler=MEM_GetPageHandler(phys_page); - Bitu lin_base=lin_page << 12; - if (lin_page>=(TLB_SIZE*(TLB_BANKS+1)) || phys_page>=(TLB_SIZE*(TLB_BANKS+1))) - E_Exit("Illegal page"); - - if (paging.links.used>=PAGING_LINKS) { - LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache"); - PAGING_ClearTLB(); - } - - tlb_entry *entry = get_tlb_entry(lin_base); - entry->phys_page=phys_page; - if (handler->flags & PFLAG_READABLE) entry->read=handler->GetHostReadPt(phys_page)-lin_base; - else entry->read=0; - entry->write=0; - - paging.links.entries[paging.links.used++]=lin_page; - entry->readhandler=handler; - entry->writehandler=&init_page_handler_userro; -} - -#endif - - -void PAGING_SetDirBase(Bitu cr3) { - paging.cr3=cr3; - - paging.base.page=cr3 >> 12; - paging.base.addr=cr3 & ~4095; -// LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,paging.base.page); - if (paging.enabled) { - PAGING_ClearTLB(); - } -} - -void PAGING_Enable(bool enabled) { - /* If paging is disable we work from a default paging table */ - if (paging.enabled==enabled) return; - paging.enabled=enabled; - if (enabled) { - if (GCC_UNLIKELY(cpudecoder==CPU_Core_Simple_Run)) { -// LOG_MSG("CPU core simple won't run this game,switching to normal"); - cpudecoder=CPU_Core_Normal_Run; - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=0; - } -// LOG(LOG_PAGING,LOG_NORMAL)("Enabled"); - PAGING_SetDirBase(paging.cr3); - } - PAGING_ClearTLB(); -} - -bool PAGING_Enabled(void) { - return paging.enabled; -} - -class PAGING:public Module_base{ -public: - PAGING(Section* configuration):Module_base(configuration){ - /* Setup default Page Directory, force it to update */ - paging.enabled=false; - PAGING_InitTLB(); - Bitu i; - for (i=0;i0) { + if (flags.tf) { + Interrupt(3); + cpudecoder=&CPU_Real_16_Slow_Decode; + return CBRET_NONE; + } + CPU_Real_16_Slow_Decode(1); + if (!flags.tf) { + cpudecoder=&CPU_Real_16_Slow_Decode; + return CBRET_NONE; + }; + count--; + } + + return CBRET_NONE; +} + +void CPU_Real_16_Slow_Start(void) { + + lookupEATable=&GetEA_16_n; + segprefix_base=0; + segprefix_on=false; + cpudecoder=&CPU_Real_16_Slow_Decode; + +}; diff --git a/src/debug/Makefile.am b/src/debug/Makefile.am index 95cab04..a939db1 100644 --- a/src/debug/Makefile.am +++ b/src/debug/Makefile.am @@ -1,4 +1,5 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include - -noinst_LIBRARIES = libdebug.a -libdebug_a_SOURCES = debug.cpp debug_gui.cpp debug_disasm.cpp debug_inc.h disasm_tables.h debug_win32.cpp \ No newline at end of file +AM_CPPFLAGS = -I$(top_srcdir)/include + +EXTRA_DIST = debug_win32.cpp +noinst_LIBRARIES = libdebug.a +libdebug_a_SOURCES = debug.cpp debug_gui.cpp debug_disasm.cpp debug_inc.h disasm_tables.h \ No newline at end of file diff --git a/src/debug/Makefile.in b/src/debug/Makefile.in new file mode 100644 index 0000000..4280ba0 --- /dev/null +++ b/src/debug/Makefile.in @@ -0,0 +1,312 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +AM_CPPFLAGS = -I$(top_srcdir)/include + +EXTRA_DIST = debug_win32.cpp +noinst_LIBRARIES = libdebug.a +libdebug_a_SOURCES = debug.cpp debug_gui.cpp debug_disasm.cpp debug_inc.h disasm_tables.h +subdir = src/debug +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libdebug_a_AR = $(AR) cru +libdebug_a_LIBADD = +am_libdebug_a_OBJECTS = debug.$(OBJEXT) debug_gui.$(OBJEXT) \ + debug_disasm.$(OBJEXT) +libdebug_a_OBJECTS = $(am_libdebug_a_OBJECTS) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/debug.Po ./$(DEPDIR)/debug_disasm.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/debug_gui.Po +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +CXXFLAGS = @CXXFLAGS@ +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libdebug_a_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libdebug_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/debug/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +AR = ar + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libdebug.a: $(libdebug_a_OBJECTS) $(libdebug_a_DEPENDENCIES) + -rm -f libdebug.a + $(libdebug_a_AR) libdebug.a $(libdebug_a_OBJECTS) $(libdebug_a_LIBADD) + $(RANLIB) libdebug.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug_disasm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug_gui.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `cygpath -w $<` +CXXDEPMODE = @CXXDEPMODE@ +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic tags uninstall uninstall-am \ + uninstall-info-am + +# 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/debug/debug.cpp b/src/debug/debug.cpp index 1101b5f..2d800be 100644 --- a/src/debug/debug.cpp +++ b/src/debug/debug.cpp @@ -1,2333 +1,252 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: debug.cpp,v 1.97 2009/04/11 19:49:52 c2woody Exp $ */ - -#include "dosbox.h" -#if C_DEBUG - -#include -#include -#include -#include -#include -#include -#include -using namespace std; - -#include "debug.h" -#include "cross.h" //snprintf -#include "cpu.h" -#include "video.h" -#include "pic.h" -#include "mapper.h" -#include "cpu.h" -#include "callback.h" -#include "inout.h" -#include "mixer.h" -#include "timer.h" -#include "paging.h" -#include "support.h" -#include "shell.h" -#include "programs.h" -#include "debug_inc.h" -#include "../cpu/lazyflags.h" -#include "keyboard.h" -#include "setup.h" - -#ifdef WIN32 -void WIN32_Console(); -#else -#include -#include -static struct termios consolesettings; -#endif -int old_cursor_state; - -// Forwards -static void DrawCode(void); -static void DEBUG_RaiseTimerIrq(void); -static void SaveMemory(Bitu seg, Bitu ofs1, Bit32u num); -static void SaveMemoryBin(Bitu seg, Bitu ofs1, Bit32u num); -static void LogGDT(void); -static void LogLDT(void); -static void LogIDT(void); -static void LogPages(char* selname); -static void LogCPUInfo(void); -static void OutputVecTable(char* filename); -static void DrawVariables(void); - -char* AnalyzeInstruction(char* inst, bool saveSelector); -Bit32u GetHexValue(char* str, char*& hex); - -class DebugPageHandler : public PageHandler { -public: - Bitu readb(PhysPt /*addr*/) { - } - Bitu readw(PhysPt /*addr*/) { - } - Bitu readd(PhysPt /*addr*/) { - } - void writeb(PhysPt /*addr*/,Bitu /*val*/) { - } - void writew(PhysPt /*addr*/,Bitu /*val*/) { - } - void writed(PhysPt /*addr*/,Bitu /*val*/) { - } - - - -}; - - -class DEBUG; - -DEBUG* pDebugcom = 0; -bool exitLoop = false; - - -// Heavy Debugging Vars for logging -#if C_HEAVY_DEBUG -static ofstream cpuLogFile; -static bool cpuLog = false; -static int cpuLogCounter = 0; -static int cpuLogType = 1; // log detail -static bool zeroProtect = false; -bool logHeavy = false; -#endif - - - -static struct { - Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip; -} oldregs; - -static char curSelectorName[3] = { 0,0,0 }; - -static Segment oldsegs[6]; -static Bitu oldflags,oldcpucpl; -DBGBlock dbg; -static Bitu input_count; -Bitu cycle_count; -static bool debugging; - - -static void SetColor(Bitu test) { - if (test) { - if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));} - } else { - if (has_colors()) { wattrset(dbg.win_reg,0);} - } -} - -struct SCodeViewData { - int cursorPos; - Bit16u firstInstSize; - Bit16u useCS; - Bit32u useEIPlast, useEIPmid; - Bit32u useEIP; - Bit16u cursorSeg; - Bit32u cursorOfs; - bool inputMode; - char inputStr[255]; - -} codeViewData; - -static Bit16u dataSeg; -static Bit32u dataOfs; -static bool showExtend = true; - -/***********/ -/* Helpers */ -/***********/ - -Bit32u PhysMakeProt(Bit16u selector, Bit32u offset) -{ - Descriptor desc; - if (cpu.gdt.GetDescriptor(selector,desc)) return desc.GetBase()+offset; - return 0; -}; - -Bit32u GetAddress(Bit16u seg, Bit32u offset) -{ - if (seg==SegValue(cs)) return SegPhys(cs)+offset; - if (cpu.pmode && !(reg_flags & FLAG_VM)) { - Descriptor desc; - if (cpu.gdt.GetDescriptor(seg,desc)) return PhysMakeProt(seg,offset); - } - return (seg<<4)+offset; -} - -static char empty_sel[] = { ' ',' ',0 }; - -bool GetDescriptorInfo(char* selname, char* out1, char* out2) -{ - Bitu sel; - Descriptor desc; - - if (strstr(selname,"cs") || strstr(selname,"CS")) sel = SegValue(cs); - else if (strstr(selname,"ds") || strstr(selname,"DS")) sel = SegValue(ds); - else if (strstr(selname,"es") || strstr(selname,"ES")) sel = SegValue(es); - else if (strstr(selname,"fs") || strstr(selname,"FS")) sel = SegValue(fs); - else if (strstr(selname,"gs") || strstr(selname,"GS")) sel = SegValue(gs); - else if (strstr(selname,"ss") || strstr(selname,"SS")) sel = SegValue(ss); - else { - sel = GetHexValue(selname,selname); - if (*selname==0) selname=empty_sel; - } - if (cpu.gdt.GetDescriptor(sel,desc)) { - switch (desc.Type()) { - case DESC_TASK_GATE: - sprintf(out1,"%s: s:%08X type:%02X p",selname,desc.GetSelector(),desc.saved.gate.type); - sprintf(out2," TaskGate dpl : %01X %1X",desc.saved.gate.dpl,desc.saved.gate.p); - return true; - case DESC_LDT: - case DESC_286_TSS_A: - case DESC_286_TSS_B: - case DESC_386_TSS_A: - case DESC_386_TSS_B: - sprintf(out1,"%s: b:%08X type:%02X pag",selname,desc.GetBase(),desc.saved.seg.type); - sprintf(out2," l:%08X dpl : %01X %1X%1X%1X",desc.GetLimit(),desc.saved.seg.dpl,desc.saved.seg.p,desc.saved.seg.avl,desc.saved.seg.g); - return true; - case DESC_286_CALL_GATE: - case DESC_386_CALL_GATE: - sprintf(out1,"%s: s:%08X type:%02X p params: %02X",selname,desc.GetSelector(),desc.saved.gate.type,desc.saved.gate.paramcount); - sprintf(out2," o:%08X dpl : %01X %1X",desc.GetOffset(),desc.saved.gate.dpl,desc.saved.gate.p); - return true; - case DESC_286_INT_GATE: - case DESC_286_TRAP_GATE: - case DESC_386_INT_GATE: - case DESC_386_TRAP_GATE: - sprintf(out1,"%s: s:%08X type:%02X p",selname,desc.GetSelector(),desc.saved.gate.type); - sprintf(out2," o:%08X dpl : %01X %1X",desc.GetOffset(),desc.saved.gate.dpl,desc.saved.gate.p); - return true; - } - sprintf(out1,"%s: b:%08X type:%02X parbg",selname,desc.GetBase(),desc.saved.seg.type); - sprintf(out2," l:%08X dpl : %01X %1X%1X%1X%1X%1X",desc.GetLimit(),desc.saved.seg.dpl,desc.saved.seg.p,desc.saved.seg.avl,desc.saved.seg.r,desc.saved.seg.big,desc.saved.seg.g); - return true; - } else { - strcpy(out1," "); - strcpy(out2," "); - } - return false; -}; - -/********************/ -/* DebugVar stuff */ -/********************/ - -class CDebugVar -{ -public: - CDebugVar(char* _name, PhysPt _adr) { adr=_adr; safe_strncpy(name,_name,16); }; - - char* GetName(void) { return name; }; - PhysPt GetAdr (void) { return adr; }; - -private: - PhysPt adr; - char name[16]; - -public: - static void InsertVariable (char* name, PhysPt adr); - static CDebugVar* FindVar (PhysPt adr); - static void DeleteAll (); - static bool SaveVars (char* name); - static bool LoadVars (char* name); - - static std::list varList; -}; - -std::list CDebugVar::varList; - - -/********************/ -/* Breakpoint stuff */ -/********************/ - -bool skipFirstInstruction = false; - -enum EBreakpoint { BKPNT_UNKNOWN, BKPNT_PHYSICAL, BKPNT_INTERRUPT, BKPNT_MEMORY, BKPNT_MEMORY_PROT, BKPNT_MEMORY_LINEAR }; - -#define BPINT_ALL 0x100 - -class CBreakpoint -{ -public: - - CBreakpoint(void); - void SetAddress (Bit16u seg, Bit32u off) { location = GetAddress(seg,off); type = BKPNT_PHYSICAL; segment = seg; offset = off; }; - void SetAddress (PhysPt adr) { location = adr; type = BKPNT_PHYSICAL; }; - void SetInt (Bit8u _intNr, Bit16u ah) { intNr = _intNr, ahValue = ah; type = BKPNT_INTERRUPT; }; - void SetOnce (bool _once) { once = _once; }; - void SetType (EBreakpoint _type) { type = _type; }; - void SetValue (Bit8u value) { ahValue = value; }; - - bool IsActive (void) { return active; }; - void Activate (bool _active); - - EBreakpoint GetType (void) { return type; }; - bool GetOnce (void) { return once; }; - PhysPt GetLocation (void) { if (GetType()!=BKPNT_INTERRUPT) return location; else return 0; }; - Bit16u GetSegment (void) { return segment; }; - Bit32u GetOffset (void) { return offset; }; - Bit8u GetIntNr (void) { if (GetType()==BKPNT_INTERRUPT) return intNr; else return 0; }; - Bit16u GetValue (void) { if (GetType()!=BKPNT_PHYSICAL) return ahValue; else return 0; }; - - // statics - static CBreakpoint* AddBreakpoint (Bit16u seg, Bit32u off, bool once); - static CBreakpoint* AddIntBreakpoint (Bit8u intNum, Bit16u ah, bool once); - static CBreakpoint* AddMemBreakpoint (Bit16u seg, Bit32u off); - static void ActivateBreakpoints (PhysPt adr, bool activate); - static bool CheckBreakpoint (PhysPt adr); - static bool CheckBreakpoint (Bitu seg, Bitu off); - static bool CheckIntBreakpoint (PhysPt adr, Bit8u intNr, Bit16u ahValue); - static bool IsBreakpoint (PhysPt where); - static bool IsBreakpointDrawn (PhysPt where); - static bool DeleteBreakpoint (PhysPt where); - static bool DeleteByIndex (Bit16u index); - static void DeleteAll (void); - static void ShowList (void); - - -private: - EBreakpoint type; - // Physical - PhysPt location; - Bit8u oldData; - Bit16u segment; - Bit32u offset; - // Int - Bit8u intNr; - Bit16u ahValue; - // Shared - bool active; - bool once; - - static std::list BPoints; -public: - static CBreakpoint* ignoreOnce; -}; - -CBreakpoint::CBreakpoint(void): -location(0), -active(false),once(false), -segment(0),offset(0),intNr(0),ahValue(0), -type(BKPNT_UNKNOWN) { }; - -void CBreakpoint::Activate(bool _active) -{ -#if !C_HEAVY_DEBUG - if (GetType()==BKPNT_PHYSICAL) { - if (_active) { - // Set 0xCC and save old value - Bit8u data = mem_readb(location); - if (data!=0xCC) { - oldData = data; - mem_writeb(location,0xCC); - }; - } else { - // Remove 0xCC and set old value - if (mem_readb (location)==0xCC) { - mem_writeb(location,oldData); - }; - } - } -#endif - active = _active; -}; - -// Statics -std::list CBreakpoint::BPoints; -CBreakpoint* CBreakpoint::ignoreOnce = 0; -Bitu ignoreAddressOnce = 0; - -CBreakpoint* CBreakpoint::AddBreakpoint(Bit16u seg, Bit32u off, bool once) -{ - CBreakpoint* bp = new CBreakpoint(); - bp->SetAddress (seg,off); - bp->SetOnce (once); - BPoints.push_front (bp); - return bp; -}; - -CBreakpoint* CBreakpoint::AddIntBreakpoint(Bit8u intNum, Bit16u ah, bool once) -{ - CBreakpoint* bp = new CBreakpoint(); - bp->SetInt (intNum,ah); - bp->SetOnce (once); - BPoints.push_front (bp); - return bp; -}; - -CBreakpoint* CBreakpoint::AddMemBreakpoint(Bit16u seg, Bit32u off) -{ - CBreakpoint* bp = new CBreakpoint(); - bp->SetAddress (seg,off); - bp->SetOnce (false); - bp->SetType (BKPNT_MEMORY); - BPoints.push_front (bp); - return bp; -}; - -void CBreakpoint::ActivateBreakpoints(PhysPt adr, bool activate) -{ - // activate all breakpoints - std::list::iterator i; - CBreakpoint* bp; - for(i=BPoints.begin(); i != BPoints.end(); i++) { - bp = (*i); - // Do not activate, when bp is an actual adress - if (activate && (bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) { - // Do not activate :) - continue; - } - bp->Activate(activate); - }; -}; - -bool CBreakpoint::CheckBreakpoint(Bitu seg, Bitu off) -// Checks if breakpoint is valid an should stop execution -{ - if ((ignoreAddressOnce!=0) && (GetAddress(seg,off)==ignoreAddressOnce)) { - ignoreAddressOnce = 0; - return false; - } else - ignoreAddressOnce = 0; - - // Search matching breakpoint - std::list::iterator i; - CBreakpoint* bp; - for(i=BPoints.begin(); i != BPoints.end(); i++) { - bp = (*i); - if ((bp->GetType()==BKPNT_PHYSICAL) && bp->IsActive() && (bp->GetSegment()==seg) && (bp->GetOffset()==off)) { - // Ignore Once ? - if (ignoreOnce==bp) { - ignoreOnce=0; - bp->Activate(true); - return false; - }; - // Found, - if (bp->GetOnce()) { - // delete it, if it should only be used once - (BPoints.erase)(i); - bp->Activate(false); - delete bp; - } else { - ignoreOnce = bp; - }; - return true; - } -#if C_HEAVY_DEBUG - // Memory breakpoint support - else if (bp->IsActive()) { - if ((bp->GetType()==BKPNT_MEMORY) || (bp->GetType()==BKPNT_MEMORY_PROT) || (bp->GetType()==BKPNT_MEMORY_LINEAR)) { - // Watch Protected Mode Memoryonly in pmode - if (bp->GetType()==BKPNT_MEMORY_PROT) { - // Check if pmode is active - if (!cpu.pmode) return false; - // Check if descriptor is valid - Descriptor desc; - if (!cpu.gdt.GetDescriptor(bp->GetSegment(),desc)) return false; - if (desc.GetLimit()==0) return false; - } - - Bitu address; - if (bp->GetType()==BKPNT_MEMORY_LINEAR) address = bp->GetOffset(); - else address = GetAddress(bp->GetSegment(),bp->GetOffset()); - Bit8u value=0; - if (mem_readb_checked(address,&value)) return false; - if (bp->GetValue() != value) { - // Yup, memory value changed - DEBUG_ShowMsg("DEBUG: Memory breakpoint %s: %04X:%04X - %02X -> %02X\n",(bp->GetType()==BKPNT_MEMORY_PROT)?"(Prot)":"",bp->GetSegment(),bp->GetOffset(),bp->GetValue(),value); - bp->SetValue(value); - return true; - }; - } - }; -#endif - }; - return false; -}; - -bool CBreakpoint::CheckIntBreakpoint(PhysPt adr, Bit8u intNr, Bit16u ahValue) -// Checks if interrupt breakpoint is valid an should stop execution -{ - if ((ignoreAddressOnce!=0) && (adr==ignoreAddressOnce)) { - ignoreAddressOnce = 0; - return false; - } else - ignoreAddressOnce = 0; - - // Search matching breakpoint - std::list::iterator i; - CBreakpoint* bp; - for(i=BPoints.begin(); i != BPoints.end(); i++) { - bp = (*i); - if ((bp->GetType()==BKPNT_INTERRUPT) && bp->IsActive() && (bp->GetIntNr()==intNr)) { - if ((bp->GetValue()==BPINT_ALL) || (bp->GetValue()==ahValue)) { - // Ignoie it once ? - if (ignoreOnce==bp) { - ignoreOnce=0; - bp->Activate(true); - return false; - }; - // Found - if (bp->GetOnce()) { - // delete it, if it should only be used once - (BPoints.erase)(i); - bp->Activate(false); - delete bp; - } else { - ignoreOnce = bp; - } - return true; - } - }; - }; - return false; -}; - -void CBreakpoint::DeleteAll() -{ - std::list::iterator i; - CBreakpoint* bp; - for(i=BPoints.begin(); i != BPoints.end(); i++) { - bp = (*i); - bp->Activate(false); - delete bp; - }; - (BPoints.clear)(); -}; - - -bool CBreakpoint::DeleteByIndex(Bit16u index) -{ - // Search matching breakpoint - int nr = 0; - std::list::iterator i; - CBreakpoint* bp; - for(i=BPoints.begin(); i != BPoints.end(); i++) { - if (nr==index) { - bp = (*i); - (BPoints.erase)(i); - bp->Activate(false); - delete bp; - return true; - } - nr++; - }; - return false; -}; - -bool CBreakpoint::DeleteBreakpoint(PhysPt where) -{ - // Search matching breakpoint - std::list::iterator i; - CBreakpoint* bp; - for(i=BPoints.begin(); i != BPoints.end(); i++) { - bp = (*i); - if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==where)) { - (BPoints.erase)(i); - bp->Activate(false); - delete bp; - return true; - } - }; - return false; -}; - -bool CBreakpoint::IsBreakpoint(PhysPt adr) -// is there a breakpoint at address ? -{ - // Search matching breakpoint - std::list::iterator i; - CBreakpoint* bp; - for(i=BPoints.begin(); i != BPoints.end(); i++) { - bp = (*i); - if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetSegment()==adr)) { - return true; - }; - if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) { - return true; - }; - }; - return false; -}; - -bool CBreakpoint::IsBreakpointDrawn(PhysPt adr) -// valid breakpoint, that should be drawn ? -{ - // Search matching breakpoint - std::list::iterator i; - CBreakpoint* bp; - for(i=BPoints.begin(); i != BPoints.end(); i++) { - bp = (*i); - if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) { - // Only draw, if breakpoint is not only once, - return !bp->GetOnce(); - }; - }; - return false; -}; - -void CBreakpoint::ShowList(void) -{ - // iterate list - int nr = 0; - std::list::iterator i; - for(i=BPoints.begin(); i != BPoints.end(); i++) { - CBreakpoint* bp = (*i); - if (bp->GetType()==BKPNT_PHYSICAL) { - DEBUG_ShowMsg("%02X. BP %04X:%04X\n",nr,bp->GetSegment(),bp->GetOffset()); - } else if (bp->GetType()==BKPNT_INTERRUPT) { - if (bp->GetValue()==BPINT_ALL) DEBUG_ShowMsg("%02X. BPINT %02X\n",nr,bp->GetIntNr()); - else DEBUG_ShowMsg("%02X. BPINT %02X AH=%02X\n",nr,bp->GetIntNr(),bp->GetValue()); - } else if (bp->GetType()==BKPNT_MEMORY) { - DEBUG_ShowMsg("%02X. BPMEM %04X:%04X (%02X)\n",nr,bp->GetSegment(),bp->GetOffset(),bp->GetValue()); - } else if (bp->GetType()==BKPNT_MEMORY_PROT) { - DEBUG_ShowMsg("%02X. BPPM %04X:%08X (%02X)\n",nr,bp->GetSegment(),bp->GetOffset(),bp->GetValue()); - } else if (bp->GetType()==BKPNT_MEMORY_LINEAR ) { - DEBUG_ShowMsg("%02X. BPLM %08X (%02X)\n",nr,bp->GetOffset(),bp->GetValue()); - }; - nr++; - } -}; - -bool DEBUG_Breakpoint(void) -{ - /* First get the phyiscal address and check for a set Breakpoint */ - if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) return false; - // Found. Breakpoint is valid - PhysPt where=GetAddress(SegValue(cs),reg_eip); - CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints - return true; -}; - -bool DEBUG_IntBreakpoint(Bit8u intNum) -{ - /* First get the phyiscal address and check for a set Breakpoint */ - PhysPt where=GetAddress(SegValue(cs),reg_eip); - if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah)) return false; - // Found. Breakpoint is valid - CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints - return true; -}; - -static bool StepOver() -{ - exitLoop = false; - PhysPt start=GetAddress(SegValue(cs),reg_eip); - char dline[200];Bitu size; - size=DasmI386(dline, start, reg_eip, cpu.code.big); - - if (strstr(dline,"call") || strstr(dline,"int") || strstr(dline,"loop") || strstr(dline,"rep")) { - CBreakpoint::AddBreakpoint (SegValue(cs),reg_eip+size, true); - CBreakpoint::ActivateBreakpoints(start, true); - debugging=false; - DrawCode(); - DOSBOX_SetNormalLoop(); - return true; - } - return false; -}; - -bool DEBUG_ExitLoop(void) -{ -#if C_HEAVY_DEBUG - DrawVariables(); -#endif - - if (exitLoop) { - exitLoop = false; - return true; - } - return false; -}; - -/********************/ -/* Draw windows */ -/********************/ - -static void DrawData(void) { - - Bit8u ch; - Bit32u add = dataOfs; - Bit32u address; - /* Data win */ - for (int y=0; y<8; y++) { - // Adress - if (add<0x10000) mvwprintw (dbg.win_data,1+y,0,"%04X:%04X ",dataSeg,add); - else mvwprintw (dbg.win_data,1+y,0,"%04X:%08X ",dataSeg,add); - for (int x=0; x<16; x++) { - address = GetAddress(dataSeg,add); - if (mem_readb_checked(address,&ch)) ch=0; - mvwprintw (dbg.win_data,1+y,14+3*x,"%02X",ch); - if (ch<32 || !isprint(*reinterpret_cast(&ch))) ch='.'; - mvwprintw (dbg.win_data,1+y,63+x,"%c",ch); - add++; - }; - } - wrefresh(dbg.win_data); -}; - -static void DrawRegisters(void) { - /* Main Registers */ - SetColor(reg_eax!=oldregs.eax);oldregs.eax=reg_eax;mvwprintw (dbg.win_reg,0,4,"%08X",reg_eax); - SetColor(reg_ebx!=oldregs.ebx);oldregs.ebx=reg_ebx;mvwprintw (dbg.win_reg,1,4,"%08X",reg_ebx); - SetColor(reg_ecx!=oldregs.ecx);oldregs.ecx=reg_ecx;mvwprintw (dbg.win_reg,2,4,"%08X",reg_ecx); - SetColor(reg_edx!=oldregs.edx);oldregs.edx=reg_edx;mvwprintw (dbg.win_reg,3,4,"%08X",reg_edx); - - SetColor(reg_esi!=oldregs.esi);oldregs.esi=reg_esi;mvwprintw (dbg.win_reg,0,18,"%08X",reg_esi); - SetColor(reg_edi!=oldregs.edi);oldregs.edi=reg_edi;mvwprintw (dbg.win_reg,1,18,"%08X",reg_edi); - SetColor(reg_ebp!=oldregs.ebp);oldregs.ebp=reg_ebp;mvwprintw (dbg.win_reg,2,18,"%08X",reg_ebp); - SetColor(reg_esp!=oldregs.esp);oldregs.esp=reg_esp;mvwprintw (dbg.win_reg,3,18,"%08X",reg_esp); - SetColor(reg_eip!=oldregs.eip);oldregs.eip=reg_eip;mvwprintw (dbg.win_reg,1,42,"%08X",reg_eip); - - SetColor(SegValue(ds)!=oldsegs[ds].val);oldsegs[ds].val=SegValue(ds);mvwprintw (dbg.win_reg,0,31,"%04X",SegValue(ds)); - SetColor(SegValue(es)!=oldsegs[es].val);oldsegs[es].val=SegValue(es);mvwprintw (dbg.win_reg,0,41,"%04X",SegValue(es)); - SetColor(SegValue(fs)!=oldsegs[fs].val);oldsegs[fs].val=SegValue(fs);mvwprintw (dbg.win_reg,0,51,"%04X",SegValue(fs)); - SetColor(SegValue(gs)!=oldsegs[gs].val);oldsegs[gs].val=SegValue(gs);mvwprintw (dbg.win_reg,0,61,"%04X",SegValue(gs)); - SetColor(SegValue(ss)!=oldsegs[ss].val);oldsegs[ss].val=SegValue(ss);mvwprintw (dbg.win_reg,0,71,"%04X",SegValue(ss)); - SetColor(SegValue(cs)!=oldsegs[cs].val);oldsegs[cs].val=SegValue(cs);mvwprintw (dbg.win_reg,1,31,"%04X",SegValue(cs)); - - /*Individual flags*/ - Bitu changed_flags = reg_flags ^ oldflags; - oldflags = reg_flags; - - SetColor(changed_flags&FLAG_CF); - mvwprintw (dbg.win_reg,1,53,"%01X",GETFLAG(CF) ? 1:0); - SetColor(changed_flags&FLAG_ZF); - mvwprintw (dbg.win_reg,1,56,"%01X",GETFLAG(ZF) ? 1:0); - SetColor(changed_flags&FLAG_SF); - mvwprintw (dbg.win_reg,1,59,"%01X",GETFLAG(SF) ? 1:0); - SetColor(changed_flags&FLAG_OF); - mvwprintw (dbg.win_reg,1,62,"%01X",GETFLAG(OF) ? 1:0); - SetColor(changed_flags&FLAG_AF); - mvwprintw (dbg.win_reg,1,65,"%01X",GETFLAG(AF) ? 1:0); - SetColor(changed_flags&FLAG_PF); - mvwprintw (dbg.win_reg,1,68,"%01X",GETFLAG(PF) ? 1:0); - - - SetColor(changed_flags&FLAG_DF); - mvwprintw (dbg.win_reg,1,71,"%01X",GETFLAG(DF) ? 1:0); - SetColor(changed_flags&FLAG_IF); - mvwprintw (dbg.win_reg,1,74,"%01X",GETFLAG(IF) ? 1:0); - SetColor(changed_flags&FLAG_TF); - mvwprintw (dbg.win_reg,1,77,"%01X",GETFLAG(TF) ? 1:0); - - SetColor(changed_flags&FLAG_IOPL); - mvwprintw (dbg.win_reg,2,72,"%01X",GETFLAG(IOPL)>>12); - - - SetColor(cpu.cpl ^ oldcpucpl); - mvwprintw (dbg.win_reg,2,78,"%01X",cpu.cpl); - oldcpucpl=cpu.cpl; - - if (cpu.pmode) { - if (reg_flags & FLAG_VM) mvwprintw(dbg.win_reg,0,76,"VM86"); - else if (cpu.code.big) mvwprintw(dbg.win_reg,0,76,"Pr32"); - else mvwprintw(dbg.win_reg,0,76,"Pr16"); - } else - mvwprintw(dbg.win_reg,0,76,"Real"); - - // Selector info, if available - if ((cpu.pmode) && curSelectorName[0]) { - char out1[200], out2[200]; - GetDescriptorInfo(curSelectorName,out1,out2); - mvwprintw(dbg.win_reg,2,28,out1); - mvwprintw(dbg.win_reg,3,28,out2); - } - - wattrset(dbg.win_reg,0); - mvwprintw(dbg.win_reg,3,60,"%u ",cycle_count); - wrefresh(dbg.win_reg); -}; - -static void DrawCode(void) { - bool saveSel; - Bit32u disEIP = codeViewData.useEIP; - PhysPt start = GetAddress(codeViewData.useCS,codeViewData.useEIP); - char dline[200];Bitu size;Bitu c; - static char line20[21] = " "; - - for (int i=0;i<10;i++) { - saveSel = false; - if (has_colors()) { - if ((codeViewData.useCS==SegValue(cs)) && (disEIP == reg_eip)) { - wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREEN_BLACK)); - if (codeViewData.cursorPos==-1) { - codeViewData.cursorPos = i; // Set Cursor - codeViewData.cursorSeg = SegValue(cs); - codeViewData.cursorOfs = disEIP; - } - saveSel = (i == codeViewData.cursorPos); - } else if (i == codeViewData.cursorPos) { - wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY)); - codeViewData.cursorSeg = codeViewData.useCS; - codeViewData.cursorOfs = disEIP; - saveSel = true; - } else if (CBreakpoint::IsBreakpointDrawn(start)) { - wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED)); - } else { - wattrset(dbg.win_code,0); - } - } - - - Bitu drawsize=size=DasmI386(dline, start, disEIP, cpu.code.big); - bool toolarge = false; - mvwprintw(dbg.win_code,i,0,"%04X:%04X ",codeViewData.useCS,disEIP); - - if (drawsize>10) { toolarge = true; drawsize = 9; }; - for (c=0;c %s_ ",codeViewData.inputStr); - } - - wrefresh(dbg.win_code); -} - -static void SetCodeWinStart() -{ - if ((SegValue(cs)==codeViewData.useCS) && (reg_eip>=codeViewData.useEIP) && (reg_eip<=codeViewData.useEIPlast)) { - // in valid window - scroll ? - if (reg_eip>=codeViewData.useEIPmid) codeViewData.useEIP += codeViewData.firstInstSize; - - } else { - // totally out of range. - codeViewData.useCS = SegValue(cs); - codeViewData.useEIP = reg_eip; - } - codeViewData.cursorPos = -1; // Recalc Cursor position -}; - -/********************/ -/* User input */ -/********************/ - -Bit32u GetHexValue(char* str, char*& hex) -{ - Bit32u value = 0; - Bit32u regval = 0; - hex = str; - while (*hex==' ') hex++; - if (strstr(hex,"EAX")==hex) { hex+=3; regval = reg_eax; }; - if (strstr(hex,"EBX")==hex) { hex+=3; regval = reg_ebx; }; - if (strstr(hex,"ECX")==hex) { hex+=3; regval = reg_ecx; }; - if (strstr(hex,"EDX")==hex) { hex+=3; regval = reg_edx; }; - if (strstr(hex,"ESI")==hex) { hex+=3; regval = reg_esi; }; - if (strstr(hex,"EDI")==hex) { hex+=3; regval = reg_edi; }; - if (strstr(hex,"EBP")==hex) { hex+=3; regval = reg_ebp; }; - if (strstr(hex,"ESP")==hex) { hex+=3; regval = reg_esp; }; - if (strstr(hex,"EIP")==hex) { hex+=3; regval = reg_eip; }; - if (strstr(hex,"AX")==hex) { hex+=2; regval = reg_ax; }; - if (strstr(hex,"BX")==hex) { hex+=2; regval = reg_bx; }; - if (strstr(hex,"CX")==hex) { hex+=2; regval = reg_cx; }; - if (strstr(hex,"DX")==hex) { hex+=2; regval = reg_dx; }; - if (strstr(hex,"SI")==hex) { hex+=2; regval = reg_si; }; - if (strstr(hex,"DI")==hex) { hex+=2; regval = reg_di; }; - if (strstr(hex,"BP")==hex) { hex+=2; regval = reg_bp; }; - if (strstr(hex,"SP")==hex) { hex+=2; regval = reg_sp; }; - if (strstr(hex,"IP")==hex) { hex+=2; regval = reg_ip; }; - if (strstr(hex,"CS")==hex) { hex+=2; regval = SegValue(cs); }; - if (strstr(hex,"DS")==hex) { hex+=2; regval = SegValue(ds); }; - if (strstr(hex,"ES")==hex) { hex+=2; regval = SegValue(es); }; - if (strstr(hex,"FS")==hex) { hex+=2; regval = SegValue(fs); }; - if (strstr(hex,"GS")==hex) { hex+=2; regval = SegValue(gs); }; - if (strstr(hex,"SS")==hex) { hex+=2; regval = SegValue(ss); }; - - while (*hex) { - if ((*hex>='0') && (*hex<='9')) value = (value<<4)+*hex-'0'; - else if ((*hex>='A') && (*hex<='F')) value = (value<<4)+*hex-'A'+10; - else { - if(*hex == '+') {hex++;return regval + value + GetHexValue(hex,hex); }; - if(*hex == '-') {hex++;return regval + value - GetHexValue(hex,hex); }; - break; // No valid char - } - hex++; - }; - return regval + value; -}; - -bool ChangeRegister(char* str) -{ - char* hex = str; - while (*hex==' ') hex++; - if (strstr(hex,"EAX")==hex) { hex+=3; reg_eax = GetHexValue(hex,hex); } else - if (strstr(hex,"EBX")==hex) { hex+=3; reg_ebx = GetHexValue(hex,hex); } else - if (strstr(hex,"ECX")==hex) { hex+=3; reg_ecx = GetHexValue(hex,hex); } else - if (strstr(hex,"EDX")==hex) { hex+=3; reg_edx = GetHexValue(hex,hex); } else - if (strstr(hex,"ESI")==hex) { hex+=3; reg_esi = GetHexValue(hex,hex); } else - if (strstr(hex,"EDI")==hex) { hex+=3; reg_edi = GetHexValue(hex,hex); } else - if (strstr(hex,"EBP")==hex) { hex+=3; reg_ebp = GetHexValue(hex,hex); } else - if (strstr(hex,"ESP")==hex) { hex+=3; reg_esp = GetHexValue(hex,hex); } else - if (strstr(hex,"EIP")==hex) { hex+=3; reg_eip = GetHexValue(hex,hex); } else - if (strstr(hex,"AX")==hex) { hex+=2; reg_ax = (Bit16u)GetHexValue(hex,hex); } else - if (strstr(hex,"BX")==hex) { hex+=2; reg_bx = (Bit16u)GetHexValue(hex,hex); } else - if (strstr(hex,"CX")==hex) { hex+=2; reg_cx = (Bit16u)GetHexValue(hex,hex); } else - if (strstr(hex,"DX")==hex) { hex+=2; reg_dx = (Bit16u)GetHexValue(hex,hex); } else - if (strstr(hex,"SI")==hex) { hex+=2; reg_si = (Bit16u)GetHexValue(hex,hex); } else - if (strstr(hex,"DI")==hex) { hex+=2; reg_di = (Bit16u)GetHexValue(hex,hex); } else - if (strstr(hex,"BP")==hex) { hex+=2; reg_bp = (Bit16u)GetHexValue(hex,hex); } else - if (strstr(hex,"SP")==hex) { hex+=2; reg_sp = (Bit16u)GetHexValue(hex,hex); } else - if (strstr(hex,"IP")==hex) { hex+=2; reg_ip = (Bit16u)GetHexValue(hex,hex); } else - if (strstr(hex,"CS")==hex) { hex+=2; SegSet16(cs,(Bit16u)GetHexValue(hex,hex)); } else - if (strstr(hex,"DS")==hex) { hex+=2; SegSet16(ds,(Bit16u)GetHexValue(hex,hex)); } else - if (strstr(hex,"ES")==hex) { hex+=2; SegSet16(es,(Bit16u)GetHexValue(hex,hex)); } else - if (strstr(hex,"FS")==hex) { hex+=2; SegSet16(fs,(Bit16u)GetHexValue(hex,hex)); } else - if (strstr(hex,"GS")==hex) { hex+=2; SegSet16(gs,(Bit16u)GetHexValue(hex,hex)); } else - if (strstr(hex,"SS")==hex) { hex+=2; SegSet16(ss,(Bit16u)GetHexValue(hex,hex)); } else - if (strstr(hex,"AF")==hex) { hex+=2; SETFLAGBIT(AF,GetHexValue(hex,hex)); } else - if (strstr(hex,"CF")==hex) { hex+=2; SETFLAGBIT(CF,GetHexValue(hex,hex)); } else - if (strstr(hex,"DF")==hex) { hex+=2; SETFLAGBIT(DF,GetHexValue(hex,hex)); } else - if (strstr(hex,"IF")==hex) { hex+=2; SETFLAGBIT(IF,GetHexValue(hex,hex)); } else - if (strstr(hex,"OF")==hex) { hex+=2; SETFLAGBIT(OF,GetHexValue(hex,hex)); } else - if (strstr(hex,"ZF")==hex) { hex+=2; SETFLAGBIT(ZF,GetHexValue(hex,hex)); } else - if (strstr(hex,"PF")==hex) { hex+=2; SETFLAGBIT(PF,GetHexValue(hex,hex)); } else - if (strstr(hex,"SF")==hex) { hex+=2; SETFLAGBIT(SF,GetHexValue(hex,hex)); } else - { return false; }; - return true; -}; - -bool ParseCommand(char* str) { - char* found = str; - for(char* idx = found;*idx != 0; idx++) - *idx = toupper(*idx); - - found = trim(found); - string s_found(found); - istringstream stream(s_found); - string command; - stream >> command; - string::size_type next = s_found.find_first_not_of(' ',command.size()); - if(next == string::npos) next = command.size(); - (s_found.erase)(0,next); - found = const_cast(s_found.c_str()); - - if (command == "MEMDUMP") { // Dump memory to file - Bit16u seg = (Bit16u)GetHexValue(found,found); found++; - Bit32u ofs = GetHexValue(found,found); found++; - Bit32u num = GetHexValue(found,found); found++; - SaveMemory(seg,ofs,num); - return true; - }; - - if (command == "MEMDUMPBIN") { // Dump memory to file bineary - Bit16u seg = (Bit16u)GetHexValue(found,found); found++; - Bit32u ofs = GetHexValue(found,found); found++; - Bit32u num = GetHexValue(found,found); found++; - SaveMemoryBin(seg,ofs,num); - return true; - }; - - if (command == "IV") { // Insert variable - Bit16u seg = (Bit16u)GetHexValue(found,found); found++; - Bit32u ofs = (Bit16u)GetHexValue(found,found); found++; - char name[16]; - for (int i=0; i<16; i++) { - if (found[i] && (found[i]!=' ')) name[i] = found[i]; - else { name[i] = 0; break; }; - }; - name[15] = 0; - - if(!name[0]) return false; - DEBUG_ShowMsg("DEBUG: Created debug var %s at %04X:%04X\n",name,seg,ofs); - CDebugVar::InsertVariable(name,GetAddress(seg,ofs)); - return true; - }; - - if (command == "SV") { // Save variables - char name[13]; - for (int i=0; i<12; i++) { - if (found[i] && (found[i]!=' ')) name[i] = found[i]; - else { name[i] = 0; break; }; - }; - name[12] = 0; - if(!name[0]) return false; - DEBUG_ShowMsg("DEBUG: Variable list save (%s) : %s.\n",name,(CDebugVar::SaveVars(name)?"ok":"failure")); - return true; - }; - - if (command == "LV") { // load variables - char name[13]; - for (int i=0; i<12; i++) { - if (found[i] && (found[i]!=' ')) name[i] = found[i]; - else { name[i] = 0; break; }; - }; - name[12] = 0; - if(!name[0]) return false; - DEBUG_ShowMsg("DEBUG: Variable list load (%s) : %s.\n",name,(CDebugVar::LoadVars(name)?"ok":"failure")); - return true; - }; - - if (command == "SR") { // Set register value - DEBUG_ShowMsg("DEBUG: Set Register %s.\n",(ChangeRegister(found)?"success":"failure")); - return true; - }; - - if (command == "SM") { // Set memory with following values - Bit16u seg = (Bit16u)GetHexValue(found,found); found++; - Bit32u ofs = GetHexValue(found,found); found++; - Bit16u count = 0; - while (*found) { - while (*found==' ') found++; - if (*found) { - Bit8u value = (Bit8u)GetHexValue(found,found); - if(*found) found++; - mem_writeb_checked(GetAddress(seg,ofs+count),value); - count++; - } - }; - DEBUG_ShowMsg("DEBUG: Memory changed.\n"); - return true; - }; - - if (command == "BP") { // Add new breakpoint - Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":" - Bit32u ofs = GetHexValue(found,found); - CBreakpoint::AddBreakpoint(seg,ofs,false); - DEBUG_ShowMsg("DEBUG: Set breakpoint at %04X:%04X\n",seg,ofs); - return true; - }; - -#if C_HEAVY_DEBUG - - if (command == "BPM") { // Add new breakpoint - Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":" - Bit32u ofs = GetHexValue(found,found); - CBreakpoint::AddMemBreakpoint(seg,ofs); - DEBUG_ShowMsg("DEBUG: Set memory breakpoint at %04X:%04X\n",seg,ofs); - return true; - }; - - if (command == "BPPM") { // Add new breakpoint - Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":" - Bit32u ofs = GetHexValue(found,found); - CBreakpoint* bp = CBreakpoint::AddMemBreakpoint(seg,ofs); - if (bp) { - bp->SetType(BKPNT_MEMORY_PROT); - DEBUG_ShowMsg("DEBUG: Set prot-mode memory breakpoint at %04X:%08X\n",seg,ofs); - } - return true; - }; - - if (command == "BPLM") { // Add new breakpoint - Bit32u ofs = GetHexValue(found,found); - CBreakpoint* bp = CBreakpoint::AddMemBreakpoint(0,ofs); - if (bp) bp->SetType(BKPNT_MEMORY_LINEAR); - DEBUG_ShowMsg("DEBUG: Set linear memory breakpoint at %08X\n",ofs); - return true; - }; - -#endif - - if (command == "BPINT") { // Add Interrupt Breakpoint - Bit8u intNr = (Bit8u)GetHexValue(found,found); - bool all = !(*found);found++; - Bit8u valAH = (Bit8u)GetHexValue(found,found); - if ((valAH==0x00) && (*found=='*' || all)) { - CBreakpoint::AddIntBreakpoint(intNr,BPINT_ALL,false); - DEBUG_ShowMsg("DEBUG: Set interrupt breakpoint at INT %02X\n",intNr); - } else { - CBreakpoint::AddIntBreakpoint(intNr,valAH,false); - DEBUG_ShowMsg("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X\n",intNr,valAH); - } - return true; - }; - - if (command == "BPLIST") { - DEBUG_ShowMsg("Breakpoint list:\n"); - DEBUG_ShowMsg("-------------------------------------------------------------------------\n"); - CBreakpoint::ShowList(); - return true; - }; - - if (command == "BPDEL") { // Delete Breakpoints - Bit8u bpNr = (Bit8u)GetHexValue(found,found); - if ((bpNr==0x00) && (*found=='*')) { // Delete all - CBreakpoint::DeleteAll(); - DEBUG_ShowMsg("DEBUG: Breakpoints deleted.\n"); - } else { - // delete single breakpoint - DEBUG_ShowMsg("DEBUG: Breakpoint deletion %s.\n",(CBreakpoint::DeleteByIndex(bpNr)?"success":"failure")); - } - return true; - }; - - if (command == "C") { // Set code overview - Bit16u codeSeg = (Bit16u)GetHexValue(found,found); found++; - Bit32u codeOfs = GetHexValue(found,found); - DEBUG_ShowMsg("DEBUG: Set code overview to %04X:%04X\n",codeSeg,codeOfs); - codeViewData.useCS = codeSeg; - codeViewData.useEIP = codeOfs; - return true; - }; - - if (command == "D") { // Set data overview - dataSeg = (Bit16u)GetHexValue(found,found); found++; - dataOfs = GetHexValue(found,found); - DEBUG_ShowMsg("DEBUG: Set data overview to %04X:%04X\n",dataSeg,dataOfs); - return true; - }; - -#if C_HEAVY_DEBUG - - if (command == "LOG") { // Create Cpu normal log file - cpuLogType = 1; - command = "logcode"; - } - - if (command == "LOGS") { // Create Cpu short log file - cpuLogType = 0; - command = "logcode"; - } - - if (command == "LOGL") { // Create Cpu long log file - cpuLogType = 2; - command = "logcode"; - } - - if (command == "logcode") { //Shared code between all logs - DEBUG_ShowMsg("DEBUG: Starting log\n"); - cpuLogFile.open("LOGCPU.TXT"); - if (!cpuLogFile.is_open()) { - DEBUG_ShowMsg("DEBUG: Logfile couldn't be created.\n"); - return false; - } - //Initialize log object - cpuLogFile << hex << noshowbase << setfill('0') << uppercase; - cpuLog = true; - cpuLogCounter = GetHexValue(found,found); - - debugging = false; - CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true); - ignoreAddressOnce = SegPhys(cs)+reg_eip; - DOSBOX_SetNormalLoop(); - return true; - }; - -#endif - - if (command == "INTT") { //trace int. - Bit8u intNr = (Bit8u)GetHexValue(found,found); - DEBUG_ShowMsg("DEBUG: Tracing INT %02X\n",intNr); - CPU_HW_Interrupt(intNr); - SetCodeWinStart(); - return true; - }; - - if (command == "INT") { // start int. - Bit8u intNr = (Bit8u)GetHexValue(found,found); - DEBUG_ShowMsg("DEBUG: Starting INT %02X\n",intNr); - CBreakpoint::AddBreakpoint(SegValue(cs),reg_eip, true); - CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip-1,true); - debugging = false; - DrawCode(); - DOSBOX_SetNormalLoop(); - CPU_HW_Interrupt(intNr); - return true; - }; - - if (command == "SELINFO") { - while (found[0] == ' ') found++; - char out1[200],out2[200]; - GetDescriptorInfo(found,out1,out2); - DEBUG_ShowMsg("SelectorInfo %s:\n%s\n%s\n",found,out1,out2); - return true; - }; - - if (command == "GDT") {LogGDT(); return true;} - - if (command == "LDT") {LogLDT(); return true;} - - if (command == "IDT") {LogIDT(); return true;} - - if (command == "PAGING") {LogPages(found); return true;} - - if (command == "CPU") {LogCPUInfo(); return true;} - - if (command == "INTVEC") { - if (found[0] != 0) { - OutputVecTable(found); - return true; - } - }; - - if (command == "INTHAND") { - if (found[0] != 0) { - Bit8u intNr = (Bit8u)GetHexValue(found,found); - DEBUG_ShowMsg("DEBUG: Set code overview to interrupt handler %X\n",intNr); - codeViewData.useCS = mem_readw(intNr*4+2); - codeViewData.useEIP = mem_readw(intNr*4); - return true; - } - }; - - if(command == "EXTEND") { //Toggle additional data. - showExtend = !showExtend; - return true; - }; - - if(command == "TIMERIRQ") { //Start a timer irq - DEBUG_RaiseTimerIrq(); - DEBUG_ShowMsg("Debug: Timer Int started.\n"); - return true; - }; - - -#if C_HEAVY_DEBUG - if (command == "HEAVYLOG") { // Create Cpu log file - logHeavy = !logHeavy; - DEBUG_ShowMsg("DEBUG: Heavy cpu logging %s.\n",logHeavy?"on":"off"); - return true; - }; - - if (command == "ZEROPROTECT") { //toggle zero protection - zeroProtect = !zeroProtect; - DEBUG_ShowMsg("DEBUG: Zero code execution protection %s.\n",zeroProtect?"on":"off"); - return true; - }; - -#endif - if (command == "HELP" || command == "?") { - DEBUG_ShowMsg("Debugger commands (enter all values in hex or as register):\n"); - DEBUG_ShowMsg("--------------------------------------------------------------------------\n"); - DEBUG_ShowMsg("F5 - Run.\n"); - DEBUG_ShowMsg("F9 - Set/Remove breakpoint.\n"); - DEBUG_ShowMsg("F10/F11 - Step over / trace into instruction.\n"); - DEBUG_ShowMsg("ALT + D/E/S/X/B - Set data view to DS:SI/ES:DI/SS:SP/DS:DX/ES:BX.\n"); - DEBUG_ShowMsg("Escape - Clear input line."); - DEBUG_ShowMsg("Up/Down - Move code view cursor.\n"); - DEBUG_ShowMsg("Page Up/Down - Scroll data view.\n"); - DEBUG_ShowMsg("Home/End - Scroll log messages.\n"); - DEBUG_ShowMsg("BP [segment]:[offset] - Set breakpoint.\n"); - DEBUG_ShowMsg("BPINT [intNr] * - Set interrupt breakpoint.\n"); - DEBUG_ShowMsg("BPINT [intNr] [ah] - Set interrupt breakpoint with ah.\n"); -#if C_HEAVY_DEBUG - DEBUG_ShowMsg("BPM [segment]:[offset] - Set memory breakpoint (memory change).\n"); - DEBUG_ShowMsg("BPPM [selector]:[offset]- Set pmode-memory breakpoint (memory change).\n"); - DEBUG_ShowMsg("BPLM [linear address] - Set linear memory breakpoint (memory change).\n"); -#endif - DEBUG_ShowMsg("BPLIST - List breakpoints.\n"); - DEBUG_ShowMsg("BPDEL [bpNr] / * - Delete breakpoint nr / all.\n"); - DEBUG_ShowMsg("C / D [segment]:[offset] - Set code / data view address.\n"); - DEBUG_ShowMsg("INT [nr] / INTT [nr] - Execute / Trace into interrupt.\n"); -#if C_HEAVY_DEBUG - DEBUG_ShowMsg("LOG [num] - Write cpu log file.\n"); - DEBUG_ShowMsg("LOGS/LOGL [num] - Write short/long cpu log file.\n"); - DEBUG_ShowMsg("HEAVYLOG - Enable/Disable automatic cpu log when dosbox exits.\n"); - DEBUG_ShowMsg("ZEROPROTECT - Enable/Disable zero code execution detecion.\n"); -#endif - DEBUG_ShowMsg("SR [reg] [value] - Set register value.\n"); - DEBUG_ShowMsg("SM [seg]:[off] [val] [.]..- Set memory with following values.\n"); - - DEBUG_ShowMsg("IV [seg]:[off] [name] - Create var name for memory address.\n"); - DEBUG_ShowMsg("SV [filename] - Save var list in file.\n"); - DEBUG_ShowMsg("LV [filename] - Load var list from file.\n"); - - DEBUG_ShowMsg("MEMDUMP [seg]:[off] [len] - Write memory to file memdump.txt.\n"); - DEBUG_ShowMsg("MEMDUMPBIN [s]:[o] [len] - Write memory to file memdump.bin.\n"); - DEBUG_ShowMsg("SELINFO [segName] - Show selector info.\n"); - - DEBUG_ShowMsg("INTVEC [filename] - Writes interrupt vector table to file.\n"); - DEBUG_ShowMsg("INTHAND [intNum] - Set code view to interrupt handler.\n"); - - DEBUG_ShowMsg("CPU - Display CPU status information.\n"); - DEBUG_ShowMsg("GDT - Lists descriptors of the GDT.\n"); - DEBUG_ShowMsg("LDT - Lists descriptors of the LDT.\n"); - DEBUG_ShowMsg("IDT - Lists descriptors of the IDT.\n"); - DEBUG_ShowMsg("PAGING [page] - Display content of page table.\n"); - DEBUG_ShowMsg("EXTEND - Toggle additional info.\n"); - DEBUG_ShowMsg("TIMERIRQ - Run the system timer.\n"); - - DEBUG_ShowMsg("HELP - Help\n"); - - return true; - }; - return false; -}; - -char* AnalyzeInstruction(char* inst, bool saveSelector) { - static char result[256]; - - char instu[256]; - char prefix[3]; - Bit16u seg; - - strcpy(instu,inst); - upcase(instu); - - result[0] = 0; - char* pos = strchr(instu,'['); - if (pos) { - // Segment prefix ? - if (*(pos-1)==':') { - char* segpos = pos-3; - prefix[0] = tolower(*segpos); - prefix[1] = tolower(*(segpos+1)); - prefix[2] = 0; - seg = (Bit16u)GetHexValue(segpos,segpos); - } else { - if (strstr(pos,"SP") || strstr(pos,"BP")) { - seg = SegValue(ss); - strcpy(prefix,"ss"); - } else { - seg = SegValue(ds); - strcpy(prefix,"ds"); - }; - }; - - pos++; - Bit32u adr = GetHexValue(pos,pos); - while (*pos!=']') { - if (*pos=='+') { - pos++; - adr += GetHexValue(pos,pos); - } else if (*pos=='-') { - pos++; - adr -= GetHexValue(pos,pos); - } else - pos++; - }; - Bit32u address = GetAddress(seg,adr); - if (!(get_tlb_readhandler(address)->flags & PFLAG_INIT)) { - static char outmask[] = "%s:[%04X]=%02X"; - - if (cpu.pmode) outmask[6] = '8'; - switch (DasmLastOperandSize()) { - case 8 : { Bit8u val = mem_readb(address); - outmask[12] = '2'; - sprintf(result,outmask,prefix,adr,val); - } break; - case 16: { Bit16u val = mem_readw(address); - outmask[12] = '4'; - sprintf(result,outmask,prefix,adr,val); - } break; - case 32: { Bit32u val = mem_readd(address); - outmask[12] = '8'; - sprintf(result,outmask,prefix,adr,val); - } break; - } - } else { - sprintf(result,"[illegal]"); - } - // Variable found ? - CDebugVar* var = CDebugVar::FindVar(address); - if (var) { - // Replace occurance - char* pos1 = strchr(inst,'['); - char* pos2 = strchr(inst,']'); - if (pos1 && pos2) { - char temp[256]; - strcpy(temp,pos2); // save end - pos1++; *pos1 = 0; // cut after '[' - strcat(inst,var->GetName()); // add var name - strcat(inst,temp); // add end - }; - }; - // show descriptor info, if available - if ((cpu.pmode) && saveSelector) { - strcpy(curSelectorName,prefix); - }; - }; - // If it is a callback add additional info - pos = strstr(inst,"callback"); - if (pos) { - pos += 9; - Bitu nr = GetHexValue(pos,pos); - const char* descr = CALLBACK_GetDescription(nr); - if (descr) { - strcat(inst," ("); strcat(inst,descr); strcat(inst,")"); - } - }; - // Must be a jump - if (instu[0] == 'J') - { - bool jmp = false; - switch (instu[1]) { - case 'A' : { jmp = (get_CF()?false:true) && (get_ZF()?false:true); // JA - } break; - case 'B' : { if (instu[2] == 'E') { - jmp = (get_CF()?true:false) || (get_ZF()?true:false); // JBE - } else { - jmp = get_CF()?true:false; // JB - } - } break; - case 'C' : { if (instu[2] == 'X') { - jmp = reg_cx == 0; // JCXZ - } else { - jmp = get_CF()?true:false; // JC - } - } break; - case 'E' : { jmp = get_ZF()?true:false; // JE - } break; - case 'G' : { if (instu[2] == 'E') { - jmp = (get_SF()?true:false)==(get_OF()?true:false); // JGE - } else { - jmp = (get_ZF()?false:true) && ((get_SF()?true:false)==(get_OF()?true:false)); // JG - } - } break; - case 'L' : { if (instu[2] == 'E') { - jmp = (get_ZF()?true:false) || ((get_SF()?true:false)!=(get_OF()?true:false)); // JLE - } else { - jmp = (get_SF()?true:false)!=(get_OF()?true:false); // JL - } - } break; - case 'M' : { jmp = true; // JMP - } break; - case 'N' : { switch (instu[2]) { - case 'B' : - case 'C' : { jmp = get_CF()?false:true; // JNB / JNC - } break; - case 'E' : { jmp = get_ZF()?false:true; // JNE - } break; - case 'O' : { jmp = get_OF()?false:true; // JNO - } break; - case 'P' : { jmp = get_PF()?false:true; // JNP - } break; - case 'S' : { jmp = get_SF()?false:true; // JNS - } break; - case 'Z' : { jmp = get_ZF()?false:true; // JNZ - } break; - } - } break; - case 'O' : { jmp = get_OF()?true:false; // JO - } break; - case 'P' : { if (instu[2] == 'O') { - jmp = get_PF()?false:true; // JPO - } else { - jmp = get_SF()?true:false; // JP / JPE - } - } break; - case 'S' : { jmp = get_SF()?true:false; // JS - } break; - case 'Z' : { jmp = get_ZF()?true:false; // JZ - } break; - } - if (jmp) { - pos = strchr(instu,'$'); - if (pos) { - pos = strchr(instu,'+'); - if (pos) { - strcpy(result,"(down)"); - } else { - strcpy(result,"(up)"); - } - } - } else { - sprintf(result,"(no jmp)"); - } - } - return result; -}; - - -Bit32u DEBUG_CheckKeys(void) { - Bits ret=0; - int key=getch(); - if (key>0) { -#if defined(WIN32) && defined(__PDCURSES__) - switch (key) { - case ALT_D: - if (ungetch('D') != ERR) key=27; - break; - case ALT_E: - if (ungetch('E') != ERR) key=27; - break; - case ALT_X: - if (ungetch('X') != ERR) key=27; - break; - case ALT_B: - if (ungetch('B') != ERR) key=27; - break; - case ALT_S: - if (ungetch('S') != ERR) key=27; - break; - } -#endif - switch (toupper(key)) { - case 27: // escape (a bit slow): Clears line. and processes alt commands. - key=getch(); - if(key < 0) { //Purely escape Clear line - codeViewData.inputStr[0] = 0; - break; - } - - switch(toupper(key)) { - case 'D' : // ALT - D: DS:SI - dataSeg = SegValue(ds); - if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_esi; - else dataOfs = reg_si; - break; - case 'E' : //ALT - E: es:di - dataSeg = SegValue(es); - if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_edi; - else dataOfs = reg_di; - break; - case 'X': //ALT - X: ds:dx - dataSeg = SegValue(ds); - if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_edx; - else dataOfs = reg_dx; - break; - case 'B' : //ALT -B: es:bx - dataSeg = SegValue(es); - if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_ebx; - else dataOfs = reg_bx; - break; - case 'S': //ALT - S: ss:sp - dataSeg = SegValue(ss); - if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_esp; - else dataOfs = reg_sp; - break; - default: - break; - } - break; - case KEY_PPAGE : dataOfs -= 16; break; - case KEY_NPAGE : dataOfs += 16; break; - - case KEY_DOWN: // down - if (codeViewData.cursorPos<9) codeViewData.cursorPos++; - else codeViewData.useEIP += codeViewData.firstInstSize; - break; - case KEY_UP: // up - if (codeViewData.cursorPos>0) codeViewData.cursorPos--; - else { - Bitu bytes = 0; - char dline[200]; - Bitu size = 0; - Bit32u newEIP = codeViewData.useEIP - 1; - if(codeViewData.useEIP) { - for (; bytes < 10; bytes++) { - PhysPt start = GetAddress(codeViewData.useCS,newEIP); - size = DasmI386(dline, start, newEIP, cpu.code.big); - if(codeViewData.useEIP == newEIP+size) break; - newEIP--; - } - if (bytes>=10) newEIP = codeViewData.useEIP - 1; - } - codeViewData.useEIP = newEIP; - } - break; - case KEY_HOME: // Home: scroll log page up - DEBUG_RefreshPage(-1); - break; - case KEY_END: // End: scroll log page down - DEBUG_RefreshPage(1); - break; - case KEY_F(5): // Run Programm - debugging=false; - CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true); - ignoreAddressOnce = SegPhys(cs)+reg_eip; - DOSBOX_SetNormalLoop(); - break; - case KEY_F(9): // Set/Remove TBreakpoint - { PhysPt ptr = GetAddress(codeViewData.cursorSeg,codeViewData.cursorOfs); - if (CBreakpoint::IsBreakpoint(ptr)) CBreakpoint::DeleteBreakpoint(ptr); - else CBreakpoint::AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false); - } - break; - case KEY_F(10): // Step over inst - if (StepOver()) return 0; - else { - exitLoop = false; - skipFirstInstruction = true; // for heavy debugger - CPU_Cycles = 1; - ret=(*cpudecoder)(); - SetCodeWinStart(); - CBreakpoint::ignoreOnce = 0; - } - break; - case KEY_F(11): // trace into - exitLoop = false; - skipFirstInstruction = true; // for heavy debugger - CPU_Cycles = 1; - ret = (*cpudecoder)(); - SetCodeWinStart(); - CBreakpoint::ignoreOnce = 0; - break; - case 0x0A: //Parse typed Command - codeViewData.inputMode = true; - if(ParseCommand(codeViewData.inputStr)) codeViewData.inputStr[0] = 0; - break; - case 0x107: //backspace (linux) - case 0x7f: //backspace in some terminal emulators (linux) - case 0x08: // delete - if (strlen(codeViewData.inputStr)>0) codeViewData.inputStr[strlen(codeViewData.inputStr)-1] = 0; - break; - default : if ((key>=32) && (key<=128) && (strlen(codeViewData.inputStr)<253)) { - Bit32u len = strlen(codeViewData.inputStr); - codeViewData.inputStr[len] = char(key); - codeViewData.inputStr[len+1] = 0; - } - break; - - } - if (ret<0) return ret; - if (ret>0) { - ret=(*CallBack_Handlers[ret])(); - if (ret) { - exitLoop=true; - CPU_Cycles=CPU_CycleLeft=0; - return ret; - } - } - ret=0; - DEBUG_DrawScreen(); - } - return ret; -}; - -Bitu DEBUG_Loop(void) { -//TODO Disable sound - GFX_Events(); - // Interrupt started ? - then skip it - Bit16u oldCS = SegValue(cs); - Bit32u oldEIP = reg_eip; - PIC_runIRQs(); - SDL_Delay(1); - if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) { - CBreakpoint::AddBreakpoint(oldCS,oldEIP,true); - CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true); - debugging=false; - DOSBOX_SetNormalLoop(); - return 0; - } - return DEBUG_CheckKeys(); -} - -void DEBUG_Enable(bool pressed) { - if (!pressed) - return; - static bool showhelp=false; - debugging=true; - SetCodeWinStart(); - DEBUG_DrawScreen(); - DOSBOX_SetLoop(&DEBUG_Loop); - if(!showhelp) { - showhelp=true; - DEBUG_ShowMsg("***| TYPE HELP (+ENTER) TO GET AN OVERVIEW OF ALL COMMANDS |***\n"); - } - KEYBOARD_ClrBuffer(); -} - -void DEBUG_DrawScreen(void) { - DrawData(); - DrawCode(); - DrawRegisters(); - DrawVariables(); -} - -static void DEBUG_RaiseTimerIrq(void) { - PIC_ActivateIRQ(0); -} - -static void LogGDT(void) -{ - char out1[512]; - Descriptor desc; - Bitu length = cpu.gdt.GetLimit(); - PhysPt address = cpu.gdt.GetBase(); - PhysPt max = address + length; - Bitu i = 0; - LOG(LOG_MISC,LOG_ERROR)("GDT Base:%08X Limit:%08X",address,length); - while (address> 10)*4; - X86PageEntry table; - table.load=phys_readd(table_addr); - if (table.block.p) { - X86PageEntry entry; - Bitu entry_addr=(table.block.base<<12)+(i & 0x3ff)*4; - entry.load=phys_readd(entry_addr); - if (entry.block.p) { - sprintf(out1,"page %05Xxxx -> %04Xxxx flags [uw] %x:%x::%x:%x [d=%x|a=%x]", - i,entry.block.base,entry.block.us,table.block.us, - entry.block.wr,table.block.wr,entry.block.d,entry.block.a); - LOG(LOG_MISC,LOG_ERROR)(out1); - } - } - } - } else { - Bitu table_addr=(paging.base.page<<12)+(sel >> 10)*4; - X86PageEntry table; - table.load=phys_readd(table_addr); - if (table.block.p) { - X86PageEntry entry; - Bitu entry_addr=(table.block.base<<12)+(sel & 0x3ff)*4; - entry.load=phys_readd(entry_addr); - sprintf(out1,"page %05Xxxx -> %04Xxxx flags [puw] %x:%x::%x:%x::%x:%x",sel,entry.block.base,entry.block.p,table.block.p,entry.block.us,table.block.us,entry.block.wr,table.block.wr); - LOG(LOG_MISC,LOG_ERROR)(out1); - } else { - sprintf(out1,"pagetable %03X not present, flags [puw] %x::%x::%x",(sel >> 10),table.block.p,table.block.us,table.block.wr); - LOG(LOG_MISC,LOG_ERROR)(out1); - } - } - } -}; - -static void LogCPUInfo(void) { - char out1[512]; - sprintf(out1,"cr0:%08X cr2:%08X cr3:%08X cpl=%x",cpu.cr0,paging.cr2,paging.cr3,cpu.cpl); - LOG(LOG_MISC,LOG_ERROR)(out1); - sprintf(out1,"eflags:%08X [vm=%x iopl=%x nt=%x]",reg_flags,GETFLAG(VM)>>17,GETFLAG(IOPL)>>12,GETFLAG(NT)>>14); - LOG(LOG_MISC,LOG_ERROR)(out1); - sprintf(out1,"GDT base=%08X limit=%08X",cpu.gdt.GetBase(),cpu.gdt.GetLimit()); - LOG(LOG_MISC,LOG_ERROR)(out1); - sprintf(out1,"IDT base=%08X limit=%08X",cpu.idt.GetBase(),cpu.idt.GetLimit()); - LOG(LOG_MISC,LOG_ERROR)(out1); - - Bitu sel=CPU_STR(); - Descriptor desc; - if (cpu.gdt.GetDescriptor(sel,desc)) { - sprintf(out1,"TR selector=%04X, base=%08X limit=%08X*%X",sel,desc.GetBase(),desc.GetLimit(),desc.saved.seg.g?0x4000:1); - LOG(LOG_MISC,LOG_ERROR)(out1); - } - sel=CPU_SLDT(); - if (cpu.gdt.GetDescriptor(sel,desc)) { - sprintf(out1,"LDT selector=%04X, base=%08X limit=%08X*%X",sel,desc.GetBase(),desc.GetLimit(),desc.saved.seg.g?0x4000:1); - LOG(LOG_MISC,LOG_ERROR)(out1); - } -}; - -#if C_HEAVY_DEBUG -static void LogInstruction(Bit16u segValue, Bit32u eipValue, ofstream& out) { - static char empty[23] = { 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0 }; - - PhysPt start = GetAddress(segValue,eipValue); - char dline[200];Bitu size; - size = DasmI386(dline, start, reg_eip, cpu.code.big); - char* res = empty; - if (showExtend && (cpuLogType > 0) ) { - res = AnalyzeInstruction(dline,false); - if (!res || !(*res)) res = empty; - Bitu reslen = strlen(res); - if (reslen<22) for (Bitu i=0; i<22-reslen; i++) res[reslen+i] = ' '; res[22] = 0; - }; - Bitu len = strlen(dline); - if (len<30) for (Bitu i=0; i<30-len; i++) dline[len + i] = ' '; dline[30] = 0; - - // Get register values - - if(cpuLogType == 0) { - out << setw(4) << SegValue(cs) << ":" << setw(4) << reg_eip << " " << dline; - } else if (cpuLogType == 1) { - out << setw(4) << SegValue(cs) << ":" << setw(8) << reg_eip << " " << dline << " " << res; - } else if (cpuLogType == 2) { - char ibytes[200]=""; char tmpc[200]; - for (Bitu i=0; i0) << " Z" << (get_ZF()>0) - << " S" << (get_SF()>0) << " O" << (get_OF()>0) << " I" << GETFLAGBOOL(IF); - } else { - out << " FS:" << setw(4) << SegValue(fs) << " GS:" << setw(4) << SegValue(gs) - << " SS:" << setw(4) << SegValue(ss) - << " CF:" << (get_CF()>0) << " ZF:" << (get_ZF()>0) << " SF:" << (get_SF()>0) - << " OF:" << (get_OF()>0) << " AF:" << (get_AF()>0) << " PF:" << (get_PF()>0) - << " IF:" << GETFLAGBOOL(IF); - } - if(cpuLogType == 2) { - out << " TF:" << GETFLAGBOOL(TF) << " VM:" << GETFLAGBOOL(VM) <<" FLG:" << setw(8) << reg_flags - << " CR0:" << setw(8) << cpu.cr0; - } - out << endl; -}; -#endif - -// DEBUG.COM stuff - -class DEBUG : public Program { -public: - DEBUG() { pDebugcom = this; active = false; }; - ~DEBUG() { pDebugcom = 0; }; - - bool IsActive() { return active; }; - - void Run(void) - { - if(cmd->FindExist("/NOMOUSE",false)) { - real_writed(0,0x33<<2,0); - return; - } - - char filename[128]; - char args[256]; - - cmd->FindCommand(1,temp_line); - safe_strncpy(filename,temp_line.c_str(),128); - // Read commandline - Bit16u i =2; - bool ok = false; - args[0] = 0; - for (;cmd->FindCommand(i++,temp_line)==true;) { - strncat(args,temp_line.c_str(),256); - strncat(args," ",256); - } - // Start new shell and execute prog - active = true; - // Save cpu state.... - Bit16u oldcs = SegValue(cs); - Bit32u oldeip = reg_eip; - Bit16u oldss = SegValue(ss); - Bit32u oldesp = reg_esp; - - // Workaround : Allocate Stack Space - Bit16u segment; - Bit16u size = 0x200 / 0x10; - if (DOS_AllocateMemory(&segment,&size)) { - SegSet16(ss,segment); - reg_sp = 0x200; - // Start shell - DOS_Shell shell; - shell.Execute(filename,args); - DOS_FreeMemory(segment); - } - // set old reg values - SegSet16(ss,oldss); - reg_esp = oldesp; - SegSet16(cs,oldcs); - reg_eip = oldeip; - }; - -private: - bool active; -}; - -void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off) -{ - if (pDebugcom && pDebugcom->IsActive()) { - CBreakpoint::AddBreakpoint(seg,off,true); - CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true); - pDebugcom = 0; - }; -}; - -Bitu DEBUG_EnableDebugger(void) -{ - exitLoop = true; - DEBUG_Enable(true); - CPU_Cycles=CPU_CycleLeft=0; - return 0; -}; - -static void DEBUG_ProgramStart(Program * * make) { - *make=new DEBUG; -} - -// INIT - -void DEBUG_SetupConsole(void) { - #ifdef WIN32 - WIN32_Console(); - #else - tcgetattr(0,&consolesettings); - printf("\e[8;50;80t"); //resize terminal - fflush(NULL); - #endif - memset((void *)&dbg,0,sizeof(dbg)); - debugging=false; - dbg.active_win=3; - input_count=0; - /* Start the Debug Gui */ - DBGUI_StartUp(); -} - -static void DEBUG_ShutDown(Section * /*sec*/) { - CBreakpoint::DeleteAll(); - CDebugVar::DeleteAll(); - curs_set(old_cursor_state); - #ifndef WIN32 - tcsetattr(0, TCSANOW,&consolesettings); -// printf("\e[0m\e[2J"); //Seems to destroy scrolling - printf("\ec"); - fflush(NULL); - #endif -} - -Bitu debugCallback; - -void DEBUG_Init(Section* sec) { - - MSG_Add("DEBUG_CONFIGFILE_HELP","Debugger related options.\n"); - DEBUG_DrawScreen(); - /* Add some keyhandlers */ - MAPPER_AddHandler(DEBUG_Enable,MK_pause,MMOD2,"debugger","Debugger"); - /* Clear the TBreakpoint list */ - memset((void*)&codeViewData,0,sizeof(codeViewData)); - /* setup debug.com */ - PROGRAMS_MakeFile("DEBUG.COM",DEBUG_ProgramStart); - /* Setup callback */ - debugCallback=CALLBACK_Allocate(); - CALLBACK_Setup(debugCallback,DEBUG_EnableDebugger,CB_RETF,"debugger"); - /* shutdown function */ - sec->AddDestroyFunction(&DEBUG_ShutDown); -} - -// DEBUGGING VAR STUFF - -void CDebugVar::InsertVariable(char* name, PhysPt adr) -{ - varList.push_back(new CDebugVar(name,adr)); -}; - -void CDebugVar::DeleteAll(void) -{ - std::list::iterator i; - CDebugVar* bp; - for(i=varList.begin(); i != varList.end(); i++) { - bp = static_cast(*i); - delete bp; - }; - (varList.clear)(); -}; - -CDebugVar* CDebugVar::FindVar(PhysPt pt) -{ - std::list::iterator i; - CDebugVar* bp; - for(i=varList.begin(); i != varList.end(); i++) { - bp = static_cast(*i); - if (bp->GetAdr()==pt) return bp; - }; - return 0; -}; - -bool CDebugVar::SaveVars(char* name) -{ - FILE* f = fopen(name,"wb+"); - if (!f) return false; - if (varList.size()>65535) return false; - - // write number of vars - Bit16u num = (Bit16u)varList.size(); - fwrite(&num,1,sizeof(num),f); - - std::list::iterator i; - CDebugVar* bp; - for(i=varList.begin(); i != varList.end(); i++) { - bp = static_cast(*i); - // name - fwrite(bp->GetName(),1,16,f); - // adr - PhysPt adr = bp->GetAdr(); - fwrite(&adr,1,sizeof(adr),f); - }; - fclose(f); - return true; -}; - -bool CDebugVar::LoadVars(char* name) -{ - FILE* f = fopen(name,"rb"); - if (!f) return false; - - // read number of vars - Bit16u num; - fread(&num,1,sizeof(num),f); - - for (Bit16u i=0; i16) { - sprintf(buffer,"%04X:%04X ",seg,ofs1); - for (Bit16u x=0; x<16; x++) { - Bit8u value; - if (mem_readb_checked(GetAddress(seg,ofs1+x),&value)) sprintf(temp,"?? ",value); - else sprintf(temp,"%02X ",value); - strcat(buffer,temp); - } - ofs1+=16; - num-=16; - - fprintf(f,"%s\n",buffer); - } - if (num>0) { - sprintf(buffer,"%04X:%04X ",seg,ofs1); - for (Bit16u x=0; x::iterator i; - CDebugVar *dv; - char buffer[DEBUG_VAR_BUF_LEN]; - - int idx = 0; - for(i=CDebugVar::varList.begin(); i != CDebugVar::varList.end(); i++, idx++) { - - if (idx == 4*3) { - /* too many variables */ - break; - } - - dv = static_cast(*i); - - Bit16u value; - if (mem_readw_checked(dv->GetAdr(),&value)) - snprintf(buffer,DEBUG_VAR_BUF_LEN, "??????", value); - else - snprintf(buffer,DEBUG_VAR_BUF_LEN, "0x%04x", value); - - int y = idx / 3; - int x = (idx % 3) * 26; - mvwprintw(dbg.win_var, y, x, dv->GetName()); - mvwprintw(dbg.win_var, y, (x + DEBUG_VAR_BUF_LEN + 1) , buffer); - } - - wrefresh(dbg.win_var); -}; -#undef DEBUG_VAR_BUF_LEN -// HEAVY DEBUGGING STUFF - -#if C_HEAVY_DEBUG - -const Bit32u LOGCPUMAX = 20000; - -static Bit16u logCpuCS [LOGCPUMAX]; -static Bit32u logCpuEIP[LOGCPUMAX]; -static Bit32u logCount = 0; - -struct TLogInst { - Bit16u s_cs; - Bit32u eip; - Bit32u eax; - Bit32u ebx; - Bit32u ecx; - Bit32u edx; - Bit32u esi; - Bit32u edi; - Bit32u ebp; - Bit32u esp; - Bit16u s_ds; - Bit16u s_es; - Bit16u s_fs; - Bit16u s_gs; - Bit16u s_ss; - bool c; - bool z; - bool s; - bool o; - bool a; - bool p; - bool i; - char dline[31]; - char res[23]; -}; - -TLogInst logInst[LOGCPUMAX]; - -void DEBUG_HeavyLogInstruction(void) { - - static char empty[23] = { 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0 }; - - PhysPt start = GetAddress(SegValue(cs),reg_eip); - char dline[200]; - Bitu size = DasmI386(dline, start, reg_eip, cpu.code.big); - char* res = empty; - if (showExtend) { - res = AnalyzeInstruction(dline,false); - if (!res || !(*res)) res = empty; - Bitu reslen = strlen(res); - if (reslen<22) for (Bitu i=0; i<22-reslen; i++) res[reslen+i] = ' '; res[22] = 0; - }; - - Bitu len = strlen(dline); - if (len < 30) for (Bitu i=0; i < 30-len; i++) dline[len+i] = ' '; - dline[30] = 0; - - TLogInst & inst = logInst[logCount]; - strcpy(inst.dline,dline); - inst.s_cs = SegValue(cs); - inst.eip = reg_eip; - strcpy(inst.res,res); - inst.eax = reg_eax; - inst.ebx = reg_ebx; - inst.ecx = reg_ecx; - inst.edx = reg_edx; - inst.esi = reg_esi; - inst.edi = reg_edi; - inst.ebp = reg_ebp; - inst.esp = reg_esp; - inst.s_ds = SegValue(ds); - inst.s_es = SegValue(es); - inst.s_fs = SegValue(fs); - inst.s_gs = SegValue(gs); - inst.s_ss = SegValue(ss); - inst.c = get_CF()>0; - inst.z = get_ZF()>0; - inst.s = get_SF()>0; - inst.o = get_OF()>0; - inst.a = get_AF()>0; - inst.p = get_PF()>0; - inst.i = GETFLAGBOOL(IF); - - if (++logCount >= LOGCPUMAX) logCount = 0; -}; - -void DEBUG_HeavyWriteLogInstruction(void) { - if (!logHeavy) return; - logHeavy = false; - - DEBUG_ShowMsg("DEBUG: Creating cpu log LOGCPU_INT_CD.TXT\n"); - - ofstream out("LOGCPU_INT_CD.TXT"); - if (!out.is_open()) { - DEBUG_ShowMsg("DEBUG: Failed.\n"); - return; - } - out << hex << noshowbase << setfill('0') << uppercase; - Bit32u startLog = logCount; - do { - // Write Intructions - TLogInst & inst = logInst[startLog]; - out << setw(4) << inst.s_cs << ":" << setw(8) << inst.eip << " " - << inst.dline << " " << inst.res << " EAX:" << setw(8)<< inst.eax - << " EBX:" << setw(8) << inst.ebx << " ECX:" << setw(8) << inst.ecx - << " EDX:" << setw(8) << inst.edx << " ESI:" << setw(8) << inst.esi - << " EDI:" << setw(8) << inst.edi << " EBP:" << setw(8) << inst.ebp - << " ESP:" << setw(8) << inst.esp << " DS:" << setw(4) << inst.s_ds - << " ES:" << setw(4) << inst.s_es<< " FS:" << setw(4) << inst.s_fs - << " GS:" << setw(4) << inst.s_gs<< " SS:" << setw(4) << inst.s_ss - << " CF:" << inst.c << " ZF:" << inst.z << " SF:" << inst.s - << " OF:" << inst.o << " AF:" << inst.a << " PF:" << inst.p - << " IF:" << inst.i << endl; - -/* fprintf(f,"%04X:%08X %s %s EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X EBP:%08X ESP:%08X DS:%04X ES:%04X FS:%04X GS:%04X SS:%04X CF:%01X ZF:%01X SF:%01X OF:%01X AF:%01X PF:%01X IF:%01X\n", - logInst[startLog].s_cs,logInst[startLog].eip,logInst[startLog].dline,logInst[startLog].res,logInst[startLog].eax,logInst[startLog].ebx,logInst[startLog].ecx,logInst[startLog].edx,logInst[startLog].esi,logInst[startLog].edi,logInst[startLog].ebp,logInst[startLog].esp, - logInst[startLog].s_ds,logInst[startLog].s_es,logInst[startLog].s_fs,logInst[startLog].s_gs,logInst[startLog].s_ss, - logInst[startLog].c,logInst[startLog].z,logInst[startLog].s,logInst[startLog].o,logInst[startLog].a,logInst[startLog].p,logInst[startLog].i);*/ - if (++startLog >= LOGCPUMAX) startLog = 0; - } while (startLog != logCount); - - out.close(); - DEBUG_ShowMsg("DEBUG: Done.\n"); -}; - -bool DEBUG_HeavyIsBreakpoint(void) { - static Bitu zero_count = 0; - if (cpuLog) { - if (cpuLogCounter>0) { - LogInstruction(SegValue(cs),reg_eip,cpuLogFile); - cpuLogCounter--; - } - if (cpuLogCounter<=0) { - cpuLogFile.close(); - DEBUG_ShowMsg("DEBUG: cpu log LOGCPU.TXT created\n"); - cpuLog = false; - DEBUG_EnableDebugger(); - return true; - } - } - // LogInstruction - if (logHeavy) DEBUG_HeavyLogInstruction(); - if (zeroProtect) { - Bit32u value=0; - if (!mem_readd_checked(SegPhys(cs)+reg_eip,&value)) { - if (value == 0) zero_count++; - else zero_count = 0; - } - if (GCC_UNLIKELY(zero_count == 10)) E_Exit("running zeroed code"); - } - - if (skipFirstInstruction) { - skipFirstInstruction = false; - return false; - } - if (CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) { - return true; - } - return false; -} - -#endif // HEAVY DEBUG - - -#endif // DEBUG - - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include + +#include "dosbox.h" +#ifdef C_DEBUG +#include "debug.h" +#include "cpu.h" +#include "video.h" +#include "pic.h" +#include "keyboard.h" +#include "cpu.h" +#include "callback.h" +#include "inout.h" +#include "mixer.h" +#include "debug_inc.h" + +#ifdef WIN32 +void WIN32_Console(); +#endif +static struct { + Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip; +} oldregs; + + + +static Segment oldsegs[6]; +static Flag_Info oldflags; +DBGBlock dbg; + +static char input_line[256]; +static Bitu input_count; +Bitu cycle_count; + +static bool debugging; + +static void SetColor(bool test) { + if (test) { + if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));} + } else { + if (has_colors()) { wattrset(dbg.win_reg,0);} + } +} +#define MAX_BREAKPOINT 10 + +enum { BKPNT_REALMODE,BKPNT_PHYSICAL }; + +struct BreakPoint { + PhysOff location; + Bit8u olddata; + Bit16u seg; + Bit16u off_16; + Bit32u off_32; + Bit8u type; + bool enabled; + bool active; +}; + +BreakPoint bpoints[MAX_BREAKPOINT]; + +static void DrawRegisters(void) { + /* Main Registers */ + SetColor(reg_eax!=oldregs.eax);oldregs.eax=reg_eax;mvwprintw (dbg.win_reg,0,4,"%08X",reg_eax); + SetColor(reg_ebx!=oldregs.ebx);oldregs.ebx=reg_ebx;mvwprintw (dbg.win_reg,1,4,"%08X",reg_ebx); + SetColor(reg_ecx!=oldregs.ecx);oldregs.ecx=reg_ecx;mvwprintw (dbg.win_reg,2,4,"%08X",reg_ecx); + SetColor(reg_edx!=oldregs.edx);oldregs.edx=reg_edx;mvwprintw (dbg.win_reg,3,4,"%08X",reg_edx); + + SetColor(reg_esi!=oldregs.esi);oldregs.esi=reg_esi;mvwprintw (dbg.win_reg,0,18,"%08X",reg_esi); + SetColor(reg_edi!=oldregs.edi);oldregs.edi=reg_edi;mvwprintw (dbg.win_reg,1,18,"%08X",reg_edi); + SetColor(reg_ebp!=oldregs.ebp);oldregs.ebp=reg_ebp;mvwprintw (dbg.win_reg,2,18,"%08X",reg_ebp); + SetColor(reg_esp!=oldregs.esp);oldregs.esp=reg_esp;mvwprintw (dbg.win_reg,3,18,"%08X",reg_esp); + SetColor(reg_eip!=oldregs.eip);oldregs.eip=reg_eip;mvwprintw (dbg.win_reg,1,42,"%08X",reg_eip); + + SetColor(Segs[ds].value!=oldsegs[ds].value);oldsegs[ds].value=Segs[ds].value;mvwprintw (dbg.win_reg,0,31,"%04X",Segs[ds].value); + SetColor(Segs[es].value!=oldsegs[es].value);oldsegs[es].value=Segs[es].value;mvwprintw (dbg.win_reg,0,41,"%04X",Segs[es].value); + SetColor(Segs[fs].value!=oldsegs[fs].value);oldsegs[fs].value=Segs[fs].value;mvwprintw (dbg.win_reg,0,51,"%04X",Segs[fs].value); + SetColor(Segs[gs].value!=oldsegs[gs].value);oldsegs[gs].value=Segs[gs].value;mvwprintw (dbg.win_reg,0,61,"%04X",Segs[gs].value); + SetColor(Segs[ss].value!=oldsegs[ss].value);oldsegs[ss].value=Segs[ss].value;mvwprintw (dbg.win_reg,0,71,"%04X",Segs[ss].value); + SetColor(Segs[cs].value!=oldsegs[cs].value);oldsegs[cs].value=Segs[cs].value;mvwprintw (dbg.win_reg,1,31,"%04X",Segs[cs].value); + + /*Individual flags*/ + + flags.cf=get_CF();SetColor(flags.cf!=oldflags.cf);oldflags.cf=flags.cf;mvwprintw (dbg.win_reg,1,53,"%01X",flags.cf); + flags.zf=get_ZF();SetColor(flags.zf!=oldflags.zf);oldflags.zf=flags.zf;mvwprintw (dbg.win_reg,1,56,"%01X",flags.zf); + flags.sf=get_SF();SetColor(flags.sf!=oldflags.sf);oldflags.sf=flags.sf;mvwprintw (dbg.win_reg,1,59,"%01X",flags.sf); + flags.of=get_OF();SetColor(flags.of!=oldflags.of);oldflags.of=flags.of;mvwprintw (dbg.win_reg,1,62,"%01X",flags.of); + flags.af=get_AF();SetColor(flags.af!=oldflags.af);oldflags.af=flags.af;mvwprintw (dbg.win_reg,1,65,"%01X",flags.af); + flags.pf=get_PF();SetColor(flags.pf!=oldflags.pf);oldflags.pf=flags.pf;mvwprintw (dbg.win_reg,1,68,"%01X",flags.pf); + + + SetColor(flags.df!=oldflags.df);oldflags.df=flags.df;mvwprintw (dbg.win_reg,1,71,"%01X",flags.df); + SetColor(flags.intf!=oldflags.intf);oldflags.intf=flags.intf;mvwprintw (dbg.win_reg,1,74,"%01X",flags.intf); + SetColor(flags.tf!=oldflags.tf);oldflags.tf=flags.tf;mvwprintw (dbg.win_reg,1,77,"%01X",flags.tf); + + wattrset(dbg.win_reg,0); + mvwprintw(dbg.win_reg,3,60,"%d ",cycle_count); + wrefresh(dbg.win_reg); +}; + + +static void DrawCode(void) { + PhysOff start=Segs[cs].phys+reg_eip; + char dline[200];Bitu size;Bitu c; + for (Bit32u i=0;i<10;i++) { +// size=DEBUG_Disasm(start,false,dline); + size=DasmI386(dline, start, reg_eip, false); + mvwprintw(dbg.win_code,i,0,"%02X:%04X ",Segs[cs].value,(start-Segs[cs].phys)); + for (c=0;c=size*2;c--) waddch(dbg.win_code,' '); + waddstr(dbg.win_code,dline); + for (c=30-strlen(dline);c>0;c--) waddch(dbg.win_code,' '); + start+=size; + } + wrefresh(dbg.win_code); +} +/* This clears all breakpoints by replacing their 0xcc by the original byte */ +static void ClearBreakPoints(void) { + for (Bit32u i=0;i0) { + switch (key) { + case '1': + ret=(*cpudecoder)(100); + break; + case '2': + ret=(*cpudecoder)(500); + break; + case '3': + ret=(*cpudecoder)(1000); + break; + case '4': + ret=(*cpudecoder)(5000); + break; + case '5': + ret=(*cpudecoder)(10000); + break; + case 'q': + ret=(*cpudecoder)(5); + break; + + default: + ret=(*cpudecoder)(1); + }; + DEBUG_DrawScreen(); + } + return ret; +}; + + +Bitu DEBUG_Loop(void) { +//TODO Disable sound + GFX_Events(); + PIC_runIRQs(); + return DEBUG_CheckKeys(); +} + +void DEBUG_Enable(void) { + DEBUG_DrawScreen(); + debugging=true; + DOSBOX_SetLoop(&DEBUG_Loop); +} + + +void DEBUG_DrawScreen(void) { + DrawRegisters(); + DrawCode(); +} +static void DEBUG_RaiseTimerIrq(void) { + PIC_ActivateIRQ(0); +} + +void DEBUG_Init(void) { + #ifdef WIN32 + WIN32_Console(); + #endif + memset((void *)&dbg,0,sizeof(dbg)); + debugging=false; + dbg.active_win=3; + input_count=0; + /* Start the Debug Gui */ + DBGUI_StartUp(); + DEBUG_DrawScreen(); + /* Add some keyhandlers */ + KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable); + KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq); +} +#endif \ No newline at end of file diff --git a/src/debug/debug_disasm.cpp b/src/debug/debug_disasm.cpp index 1a1db2e..78aa210 100644 --- a/src/debug/debug_disasm.cpp +++ b/src/debug/debug_disasm.cpp @@ -1,1117 +1,1112 @@ - -/* - Ripped out some stuff from the mame releae to only make it for 386's - Changed some variables to use the standard DOSBox data types - Added my callback opcode - -*/ - -/* - * 2asm: Convert binary files to 80*86 assembler. Version 1.00 - * Adapted by Andrea Mazzoleni for use with MAME - * HJB 990321: - * Changed output of hex values from 0xxxxh to $xxxx format - * Removed "ptr" from "byte ptr", "word ptr" and "dword ptr" -*/ - -/* 2asm comments - -License: - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -Comments: - - The code was originally snaffled from the GNU C++ debugger, as ported - to DOS by DJ Delorie and Kent Williams (williams@herky.cs.uiowa.edu). - Extensively modified by Robin Hilliard in Jan and May 1992. - - This source compiles under Turbo C v2.01. The disassembler is entirely - table driven so it's fairly easy to change to suit your own tastes. - - The instruction table has been modified to correspond with that in - `Programmer's Technical Reference: The Processor and Coprocessor', - Robert L. Hummel, Ziff-Davis Press, 1992. Missing (read "undocumented") - instructions were added and many mistakes and omissions corrected. - - -Health warning: - - When writing and degbugging this code, I didn't have (and still don't have) - a 32-bit disassembler to compare this guy's output with. It's therefore - quite likely that bugs will appear when disassembling instructions which use - the 386 and 486's native 32 bit mode. It seems to work fine in 16 bit mode. - -Any comments/updates/bug reports to: - - Robin Hilliard, Lough Guitane, Killarney, Co. Kerry, Ireland. - Tel: [+353] 64-54014 - Internet: softloft@iruccvax.ucc.ie - Compu$erve: 100042, 1237 - - If you feel like registering, and possibly get notices of updates and - other items of software, then send me a post card of your home town. - - Thanks and enjoy! - -*/ -#include "dosbox.h" -#if C_DEBUG -#include -#include -#include -#include -#include "mem.h" - -typedef Bit8u UINT8; -typedef Bit16u UINT16; -typedef Bit32u UINT32; - -typedef Bit8s INT8; -typedef Bit16s INT16; -typedef Bit32s INT32; - - -/* Little endian uint read */ -#define le_uint8(ptr) (*(UINT8*)ptr) - -INLINE UINT16 le_uint16(const void* ptr) { - const UINT8* ptr8 = (const UINT8*)ptr; - return (UINT16)ptr8[0] | (UINT16)ptr8[1] << 8; -} -INLINE UINT32 le_uint32(const void* ptr) { - const UINT8* ptr8 = (const UINT8*)ptr; - return (UINT32)ptr8[0] | (UINT32)ptr8[1] << 8 | (UINT32)ptr8[2] << 16 | (UINT32)ptr8[3] << 24; -} - -/* Little endian int read */ -#define le_int8(ptr) ((INT8)le_uint8(ptr)) -#define le_int16(ptr) ((INT16)le_uint16(ptr)) -#define le_int32(ptr) ((INT32)le_uint32(ptr)) - -#define fp_segment(dw) ((dw >> 16) & 0xFFFFU) -#define fp_offset(dw) (dw & 0xFFFFU) -#define fp_addr(seg, off) ( (seg<<4)+off ) - -static UINT8 must_do_size; /* used with size of operand */ -static int wordop; /* dealing with word or byte operand */ - -static int instruction_offset; -//static UINT16 instruction_segment; - -static char* ubufs; /* start of buffer */ -static char* ubufp; /* last position of buffer */ -static int invalid_opcode = 0; -static int first_space = 1; - -static int prefix; /* segment override prefix byte */ -static int modrmv; /* flag for getting modrm byte */ -static int sibv; /* flag for getting sib byte */ -static int opsize; /* just like it says ... */ -static int addrsize; -static int addr32bit=0; - -/* some defines for extracting instruction bit fields from bytes */ - -#define MOD(a) (((a)>>6)&7) -#define REG(a) (((a)>>3)&7) -#define RM(a) ((a)&7) -#define SCALE(a) (((a)>>6)&7) -#define INDEX(a) (((a)>>3)&7) -#define BASE(a) ((a)&7) - -/* Percent tokens in strings: - First char after '%': - A - direct address - C - reg of r/m picks control register - D - reg of r/m picks debug register - E - r/m picks operand - F - flags register - G - reg of r/m picks general register - I - immediate data - J - relative IP offset -+ K - call/jmp distance - M - r/m picks memory - O - no r/m, offset only - R - mod of r/m picks register only - S - reg of r/m picks segment register - T - reg of r/m picks test register - X - DS:ESI - Y - ES:EDI - 2 - prefix of two-byte opcode -+ e - put in 'e' if use32 (second char is part of reg name) -+ put in 'w' for use16 or 'd' for use32 (second char is 'w') -+ j - put in 'e' in jcxz if prefix==0x66 - f - floating point (second char is esc value) - g - do r/m group 'n', n==0..7 - p - prefix - s - size override (second char is a,o) -+ d - put d if double arg, nothing otherwise (pushfd, popfd &c) -+ w - put w if word, d if double arg, nothing otherwise (lodsw/lodsd) -+ P - simple prefix - - Second char after '%': - a - two words in memory (BOUND) - b - byte - c - byte or word - d - dword -+ f - far call/jmp -+ n - near call/jmp - p - 32 or 48 bit pointer -+ q - byte/word thingy - s - six byte pseudo-descriptor - v - word or dword - w - word -+ x - sign extended byte - F - use floating regs in mod/rm - 1-8 - group number, esc value, etc -*/ - -/* watch out for aad && aam with odd operands */ - -static char const* (*opmap1)[256]; - -static char const * op386map1[256] = { -/* 0 */ - "add %Eb,%Gb", "add %Ev,%Gv", "add %Gb,%Eb", "add %Gv,%Ev", - "add al,%Ib", "add %eax,%Iv", "push es", "pop es", - "or %Eb,%Gb", "or %Ev,%Gv", "or %Gb,%Eb", "or %Gv,%Ev", - "or al,%Ib", "or %eax,%Iv", "push cs", "%2 ", -/* 1 */ - "adc %Eb,%Gb", "adc %Ev,%Gv", "adc %Gb,%Eb", "adc %Gv,%Ev", - "adc al,%Ib", "adc %eax,%Iv", "push ss", "pop ss", - "sbb %Eb,%Gb", "sbb %Ev,%Gv", "sbb %Gb,%Eb", "sbb %Gv,%Ev", - "sbb al,%Ib", "sbb %eax,%Iv", "push ds", "pop ds", -/* 2 */ - "and %Eb,%Gb", "and %Ev,%Gv", "and %Gb,%Eb", "and %Gv,%Ev", - "and al,%Ib", "and %eax,%Iv", "%pe", "daa", - "sub %Eb,%Gb", "sub %Ev,%Gv", "sub %Gb,%Eb", "sub %Gv,%Ev", - "sub al,%Ib", "sub %eax,%Iv", "%pc", "das", -/* 3 */ - "xor %Eb,%Gb", "xor %Ev,%Gv", "xor %Gb,%Eb", "xor %Gv,%Ev", - "xor al,%Ib", "xor %eax,%Iv", "%ps", "aaa", - "cmp %Eb,%Gb", "cmp %Ev,%Gv", "cmp %Gb,%Eb", "cmp %Gv,%Ev", - "cmp al,%Ib", "cmp %eax,%Iv", "%pd", "aas", -/* 4 */ - "inc %eax", "inc %ecx", "inc %edx", "inc %ebx", - "inc %esp", "inc %ebp", "inc %esi", "inc %edi", - "dec %eax", "dec %ecx", "dec %edx", "dec %ebx", - "dec %esp", "dec %ebp", "dec %esi", "dec %edi", -/* 5 */ - "push %eax", "push %ecx", "push %edx", "push %ebx", - "push %esp", "push %ebp", "push %esi", "push %edi", - "pop %eax", "pop %ecx", "pop %edx", "pop %ebx", - "pop %esp", "pop %ebp", "pop %esi", "pop %edi", -/* 6 */ - "pusha%d ", "popa%d ", "bound %Gv,%Ma", "arpl %Ew,%Rw", - "%pf", "%pg", "%so", "%sa", - "push %Iv", "imul %Gv,%Ev,%Iv","push %Ix", "imul %Gv,%Ev,%Ib", - "insb", "ins%ew", "outsb", "outs%ew", -/* 7 */ - "jo %Jb", "jno %Jb", "jc %Jb", "jnc %Jb", - "je %Jb", "jne %Jb", "jbe %Jb", "ja %Jb", - "js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb", - "jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb", -/* 8 */ - "%g0 %Eb,%Ib", "%g0 %Ev,%Iv", "%g0 %Eb,%Ib", "%g0 %Ev,%Ix", - "test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv", - "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev", - "mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev", -/* 9 */ - "nop", "xchg %ecx,%eax", "xchg %edx,%eax", "xchg %ebx,%eax", - "xchg %esp,%eax", "xchg %ebp,%eax", "xchg %esi,%eax", "xchg %edi,%eax", - "cbw", "cwd", "call %Ap", "fwait", - "pushf%d ", "popf%d ", "sahf", "lahf", -/* a */ - "mov al,%Oc", "mov %eax,%Ov", "mov %Oc,al", "mov %Ov,%eax", - "%P movsb", "%P movs%w", "%P cmpsb", "%P cmps%w ", - "test al,%Ib", "test %eax,%Iv", "%P stosb", "%P stos%w ", - "%P lodsb", "%P lods%w ", "%P scasb", "%P scas%w ", -/* b */ - "mov al,%Ib", "mov cl,%Ib", "mov dl,%Ib", "mov bl,%Ib", - "mov ah,%Ib", "mov ch,%Ib", "mov dh,%Ib", "mov bh,%Ib", - "mov %eax,%Iv", "mov %ecx,%Iv", "mov %edx,%Iv", "mov %ebx,%Iv", - "mov %esp,%Iv", "mov %ebp,%Iv", "mov %esi,%Iv", "mov %edi,%Iv", -/* c */ - "%g1 %Eb,%Ib", "%g1 %Ev,%Ib", "ret %Iw", "ret", - "les %Gv,%Mp", "lds %Gv,%Mp", "mov %Eb,%Ib", "mov %Ev,%Iv", - "enter %Iw,%Ib", "leave", "retf %Iw", "retf", - "int 03", "int %Ib", "into", "iret", -/* d */ - "%g1 %Eb,1", "%g1 %Ev,1", "%g1 %Eb,cl", "%g1 %Ev,cl", - "aam ; %Ib", "aad ; %Ib", "setalc", "xlat", -#if 0 - "esc 0,%Ib", "esc 1,%Ib", "esc 2,%Ib", "esc 3,%Ib", - "esc 4,%Ib", "esc 5,%Ib", "esc 6,%Ib", "esc 7,%Ib", -#else - "%f0", "%f1", "%f2", "%f3", - "%f4", "%f5", "%f6", "%f7", -#endif -/* e */ - "loopne %Jb", "loope %Jb", "loop %Jb", "j%j cxz %Jb", - "in al,%Ib", "in %eax,%Ib", "out %Ib,al", "out %Ib,%eax", - "call %Jv", "jmp %Jv", "jmp %Ap", "jmp %Ks%Jb", - "in al,dx", "in %eax,dx", "out dx,al", "out dx,%eax", -/* f */ - "lock %p ", "icebp", "repne %p ", "repe %p ", - "hlt", "cmc", "%g2", "%g2", - "clc", "stc", "cli", "sti", - "cld", "std", "%g3", "%g4" -}; - -static char const *second[] = { -/* 0 */ - "%g5", "%g6", "lar %Gv,%Ew", "lsl %Gv,%Ew", - 0, "[loadall]", "clts", "[loadall]", - "invd", "wbinvd", 0, "UD2", - 0, 0, 0, 0, -/* 1 */ - "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev", - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -/* 2 */ - "mov %Rd,%Cd", "mov %Rd,%Dd", "mov %Cd,%Rd", "mov %Dd,%Rd", - "mov %Rd,%Td", 0, "mov %Td,%Rd", 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -/* 3 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -/* 4 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -/* 5 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -/* 6 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -/* 7 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -/* 8 */ - "jo %Jv", "jno %Jv", "jb %Jv", "jnb %Jv", - "jz %Jv", "jnz %Jv", "jbe %Jv", "ja %Jv", - "js %Jv", "jns %Jv", "jp %Jv", "jnp %Jv", - "jl %Jv", "jge %Jv", "jle %Jv", "jg %Jv", -/* 9 */ - "seto %Eb", "setno %Eb", "setc %Eb", "setnc %Eb", - "setz %Eb", "setnz %Eb", "setbe %Eb", "setnbe %Eb", - "sets %Eb", "setns %Eb", "setp %Eb", "setnp %Eb", - "setl %Eb", "setge %Eb", "setle %Eb", "setg %Eb", -/* a */ - "push fs", "pop fs", "cpuid", "bt %Ev,%Gv", - "shld %Ev,%Gv,%Ib", "shld %Ev,%Gv,cl", 0, 0, - "push gs", "pop gs", 0, "bts %Ev,%Gv", - "shrd %Ev,%Gv,%Ib", "shrd %Ev,%Gv,cl", 0, "imul %Gv,%Ev", -/* b */ - "cmpxchg %Eb,%Gb", "cmpxchg %Ev,%Gv", "lss %Mp", "btr %Ev,%Gv", - "lfs %Mp", "lgs %Mp", "movzx %Gv,%Eb", "movzx %Gv,%Ew", - 0, 0, "%g7 %Ev,%Ib", "btc %Ev,%Gv", - "bsf %Gv,%Ev", "bsr %Gv,%Ev", "movsx %Gv,%Eb", "movsx %Gv,%Ew", -/* c */ - "xadd %Eb,%Gb", "xadd %Ev,%Gv", 0, 0, - 0, 0, 0, 0, - "bswap eax", "bswap ecx", "bswap edx", "bswap ebx", - "bswap esp", "bswap ebp", "bswap esi", "bswap edi", -/* d */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -/* e */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -/* f */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static char const *groups[][8] = { /* group 0 is group 3 for %Ev set */ -/* 0 */ - { "add", "or", "adc", "sbb", - "and", "sub", "xor", "cmp" }, -/* 1 */ - { "rol", "ror", "rcl", "rcr", - "shl", "shr", "shl", "sar" }, -/* 2 */ /* v v*/ - { "test %Eq,%Iq", "test %Eq,%Iq", "not %Ec", "neg %Ec", - "mul %Ec", "imul %Ec", "div %Ec", "idiv %Ec" }, -/* 3 */ - { "inc %Eb", "dec %Eb", 0, 0, - 0, 0, 0, "callback %Iw" }, -/* 4 */ - { "inc %Ev", "dec %Ev", "call %Kn%Ev", "call %Kf%Ep", - "jmp %Kn%Ev", "jmp %Kf%Ep", "push %Ev", 0 }, -/* 5 */ - { "sldt %Ew", "str %Ew", "lldt %Ew", "ltr %Ew", - "verr %Ew", "verw %Ew", 0, 0 }, -/* 6 */ - { "sgdt %Ms", "sidt %Ms", "lgdt %Ms", "lidt %Ms", - "smsw %Ew", 0, "lmsw %Ew", "invlpg" }, -/* 7 */ - { 0, 0, 0, 0, - "bt", "bts", "btr", "btc" } -}; - -/* zero here means invalid. If first entry starts with '*', use st(i) */ -/* no assumed %EFs here. Indexed by RM(modrm()) */ -static char const *f0[] = { 0, 0, 0, 0, 0, 0, 0, 0}; -static char const *fop_8[] = { "*fld st,%GF" }; -static char const *fop_9[] = { "*fxch st,%GF" }; -static char const *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 }; -static char const *fop_11[] = { "*fst st,%GF" }; -static char const *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 }; -static char const *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi", - "fldlg2", "fldln2", "fldz", 0 }; -static char const *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan", - "fxtract", "fprem1", "fdecstp", "fincstp" }; -static char const *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos", - "frndint", "fscale", "fsin", "fcos" }; -static char const *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 }; -static char const *fop_28[] = { "[fneni]", "[fndis]", "fclex", "finit", "[fnsetpm]", "[frstpm]", 0, 0 }; -static char const *fop_32[] = { "*fadd %GF,st" }; -static char const *fop_33[] = { "*fmul %GF,st" }; -static char const *fop_34[] = { "*fcom %GF,st" }; -static char const *fop_35[] = { "*fcomp %GF,st" }; -static char const *fop_36[] = { "*fsubr %GF,st" }; -static char const *fop_37[] = { "*fsub %GF,st" }; -static char const *fop_38[] = { "*fdivr %GF,st" }; -static char const *fop_39[] = { "*fdiv %GF,st" }; -static char const *fop_40[] = { "*ffree %GF" }; -static char const *fop_41[] = { "*fxch %GF" }; -static char const *fop_42[] = { "*fst %GF" }; -static char const *fop_43[] = { "*fstp %GF" }; -static char const *fop_44[] = { "*fucom %GF" }; -static char const *fop_45[] = { "*fucomp %GF" }; -static char const *fop_48[] = { "*faddp %GF,st" }; -static char const *fop_49[] = { "*fmulp %GF,st" }; -static char const *fop_50[] = { "*fcomp %GF,st" }; -static char const *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 }; -static char const *fop_52[] = { "*fsubrp %GF,st" }; -static char const *fop_53[] = { "*fsubp %GF,st" }; -static char const *fop_54[] = { "*fdivrp %GF,st" }; -static char const *fop_55[] = { "*fdivp %GF,st" }; -static char const *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 }; - -static char const **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */ - 0, 0, 0, 0, 0, 0, 0, 0, - fop_8, fop_9, fop_10, fop_11, fop_12, fop_13, fop_14, fop_15, - f0, f0, f0, f0, f0, fop_21, f0, f0, - f0, f0, f0, f0, fop_28, f0, f0, f0, - fop_32, fop_33, fop_34, fop_35, fop_36, fop_37, fop_38, fop_39, - fop_40, fop_41, fop_42, fop_43, fop_44, fop_45, f0, f0, - fop_48, fop_49, fop_50, fop_51, fop_52, fop_53, fop_54, fop_55, - f0, f0, f0, f0, fop_60, f0, f0, f0, -}; - -static const char *floatops[] = { /* assumed " %EF" at end of each. mod != 3 only */ -/*00*/ "fadd", "fmul", "fcom", "fcomp", - "fsub", "fsubr", "fdiv", "fdivr", -/*08*/ "fld", 0, "fst", "fstp", - "fldenv", "fldcw", "fstenv", "fstcw", -/*16*/ "fiadd", "fimul", "ficomw", "ficompw", - "fisub", "fisubr", "fidiv", "fidivr", -/*24*/ "fild", 0, "fist", "fistp", - "frstor", "fldt", 0, "fstpt", -/*32*/ "faddq", "fmulq", "fcomq", "fcompq", - "fsubq", "fsubrq", "fdivq", "fdivrq", -/*40*/ "fldq", 0, "fstq", "fstpq", - 0, 0, "fsave", "fstsw", -/*48*/ "fiaddw", "fimulw", "ficomw", "ficompw", - "fisubw", "fisubrw", "fidivw", "fidivr", -/*56*/ "fildw", 0, "fistw", "fistpw", - "fbldt", "fildq", "fbstpt", "fistpq" -}; - -static char *addr_to_hex(UINT32 addr, int splitup) { - static char buffer[11]; - - if (splitup) { - if (fp_segment(addr)==0 || fp_offset(addr)==0xffff) /* 'coz of wraparound */ - sprintf(buffer, "%04X", (unsigned)fp_offset(addr) ); - else - sprintf(buffer, "%04X:%04X", (unsigned)fp_segment(addr), (unsigned)fp_offset(addr) ); - } else { -#if 0 - /* Pet outcommented, reducing address size to 4 - when segment is 0 or 0xffff */ - if (fp_segment(addr)==0 || fp_segment(addr)==0xffff) /* 'coz of wraparound */ - sprintf(buffer, "%04X", (unsigned)fp_offset(addr) ); - else -#endif - - sprintf(buffer, "%08X", addr ); - - } - - return buffer; -} - -static PhysPt getbyte_mac; -static PhysPt startPtr; - -static UINT8 getbyte(void) { - return mem_readb(getbyte_mac++); -} - -/* - only one modrm or sib byte per instruction, tho' they need to be - returned a few times... -*/ - -static int modrm(void) -{ - if (modrmv == -1) - modrmv = getbyte(); - return modrmv; -} - -static int sib(void) -{ - if (sibv == -1) - sibv = getbyte(); - return sibv; -} - -/*------------------------------------------------------------------------*/ - -static void uprintf(char const *s, ...) -{ - va_list arg_ptr; - va_start (arg_ptr, s); - vsprintf(ubufp, s, arg_ptr); - while (*ubufp) - ubufp++; -} - -static void uputchar(char c) -{ - *ubufp++ = c; - *ubufp = 0; -} - -/*------------------------------------------------------------------------*/ - -static int bytes(char c) -{ - switch (c) { - case 'b': - return 1; - case 'w': - return 2; - case 'd': - return 4; - case 'v': - if (opsize == 32) - return 4; - else - return 2; - } - return 0; -} - -/*------------------------------------------------------------------------*/ -static void outhex(char subtype, int extend, int optional, int defsize, int sign) -{ - int n=0, s=0, i; - INT32 delta = 0; - unsigned char buff[6]; - char *name; - char signchar; - - switch (subtype) { - case 'q': - if (wordop) { - if (opsize==16) { - n = 2; - } else { - n = 4; - } - } else { - n = 1; - } - break; - - case 'a': - break; - case 'x': - extend = 2; - n = 1; - break; - case 'b': - n = 1; - break; - case 'w': - n = 2; - break; - case 'd': - n = 4; - break; - case 's': - n = 6; - break; - case 'c': - case 'v': - if (defsize == 32) - n = 4; - else - n = 2; - break; - case 'p': - if (defsize == 32) - n = 6; - else - n = 4; - s = 1; - break; - } - for (i=0; i n) { - if (subtype!='x') { - if (delta<0) { - delta = -delta; - signchar = '-'; - } else - signchar = '+'; - if (delta || !optional) - uprintf("%c%0*lX", (char)signchar, (int)(extend), (long)delta); - } else { - if (extend==2) - delta = (UINT16)delta; - uprintf("%0.*lX", (int)(2*extend), (long)delta ); - } - return; - } - if ((n == 4) && !sign) { - name = addr_to_hex(delta, 0); - uprintf("%s", name); - return; - } - switch (n) { - case 1: - if (sign && (char)delta<0) { - delta = -delta; - signchar = '-'; - } else - signchar = '+'; - if (sign) - uprintf("%c%02lX", (char)signchar, delta & 0xFFL); - else - uprintf("%02lX", delta & 0xFFL); - break; - - case 2: - if (sign && delta<0) { - signchar = '-'; - delta = -delta; - } else - signchar = '+'; - if (sign) - uprintf("%c%04lX", (char)signchar, delta & 0xFFFFL); - else - uprintf("%04lX", delta & 0xFFFFL); - break; - - case 4: - if (sign && delta<0) { - delta = -delta; - signchar = '-'; - } else - signchar = '+'; - if (sign) - uprintf("%c%08lX", (char)signchar, delta & 0xFFFFFFFFL); - else - uprintf("%08lX", delta & 0xFFFFFFFFL); - break; - } -} - - -/*------------------------------------------------------------------------*/ - -static void reg_name(int regnum, char size) -{ - if (size == 'F') { /* floating point register? */ - uprintf("st(%d)", regnum); - return; - } - if ((((size == 'c') || (size == 'v')) && (opsize == 32)) || (size == 'd')) - uputchar('e'); - if ((size=='q' || size == 'b' || size=='c') && !wordop) { - uputchar("acdbacdb"[regnum]); - uputchar("llllhhhh"[regnum]); - } else { - uputchar("acdbsbsd"[regnum]); - uputchar("xxxxppii"[regnum]); - } -} - - -/*------------------------------------------------------------------------*/ - -static void ua_str(char const *str); - -static void do_sib(int m) -{ - int s, i, b; - - s = SCALE(sib()); - i = INDEX(sib()); - b = BASE(sib()); - switch (b) { /* pick base */ - case 0: ua_str("%p:[eax"); break; - case 1: ua_str("%p:[ecx"); break; - case 2: ua_str("%p:[edx"); break; - case 3: ua_str("%p:[ebx"); break; - case 4: ua_str("%p:[esp"); break; - case 5: - if (m == 0) { - ua_str("%p:["); - outhex('d', 4, 0, addrsize, 0); - } else { - ua_str("%p:[ebp"); - } - break; - case 6: ua_str("%p:[esi"); break; - case 7: ua_str("%p:[edi"); break; - } - switch (i) { /* and index */ - case 0: uprintf("+eax"); break; - case 1: uprintf("+ecx"); break; - case 2: uprintf("+edx"); break; - case 3: uprintf("+ebx"); break; - case 4: break; - case 5: uprintf("+ebp"); break; - case 6: uprintf("+esi"); break; - case 7: uprintf("+edi"); break; - } - if (i != 4) { - switch (s) { /* and scale */ - case 0: /*uprintf("");*/ break; - case 1: uprintf("*2"); break; - case 2: uprintf("*4"); break; - case 3: uprintf("*8"); break; - } - } -} - - - -/*------------------------------------------------------------------------*/ -static void do_modrm(char subtype) -{ - int mod = MOD(modrm()); - int rm = RM(modrm()); - int extend = (addrsize == 32) ? 4 : 2; - - if (mod == 3) { /* specifies two registers */ - reg_name(rm, subtype); - return; - } - if (must_do_size) { - if (wordop) { - if (addrsize==32 || opsize==32) { /* then must specify size */ - ua_str("dword "); - } else { - ua_str("word "); - } - } else { - ua_str("byte "); - } - } - if ((mod == 0) && (rm == 5) && (addrsize == 32)) {/* mem operand with 32 bit ofs */ - ua_str("%p:["); - outhex('d', extend, 0, addrsize, 0); - uputchar(']'); - return; - } - if ((mod == 0) && (rm == 6) && (addrsize == 16)) { /* 16 bit dsplcmnt */ - ua_str("%p:["); - outhex('w', extend, 0, addrsize, 0); - uputchar(']'); - return; - } - if ((addrsize != 32) || (rm != 4)) - ua_str("%p:["); - if (addrsize == 16) { - switch (rm) { - case 0: uprintf("bx+si"); break; - case 1: uprintf("bx+di"); break; - case 2: uprintf("bp+si"); break; - case 3: uprintf("bp+di"); break; - case 4: uprintf("si"); break; - case 5: uprintf("di"); break; - case 6: uprintf("bp"); break; - case 7: uprintf("bx"); break; - } - } else { - switch (rm) { - case 0: uprintf("eax"); break; - case 1: uprintf("ecx"); break; - case 2: uprintf("edx"); break; - case 3: uprintf("ebx"); break; - case 4: do_sib(mod); break; - case 5: uprintf("ebp"); break; - case 6: uprintf("esi"); break; - case 7: uprintf("edi"); break; - } - } - switch (mod) { - case 1: - outhex('b', extend, 1, addrsize, 0); - break; - case 2: - outhex('v', extend, 1, addrsize, 1); - break; - } - uputchar(']'); -} - - - -/*------------------------------------------------------------------------*/ -static void floating_point(int e1) -{ - int esc = e1*8 + REG(modrm()); - - if ((MOD(modrm()) == 3)&&fspecial[esc]) { - if (fspecial[esc][0]) { - if (fspecial[esc][0][0] == '*') { - ua_str(fspecial[esc][0]+1); - } else { - ua_str(fspecial[esc][RM(modrm())]); - } - } else { - ua_str(floatops[esc]); - ua_str(" %EF"); - } - } else { - ua_str(floatops[esc]); - ua_str(" %EF"); - } -} - - -/*------------------------------------------------------------------------*/ -/* Main table driver */ - -#define INSTRUCTION_SIZE (int)getbyte_mac - (int)startPtr - -static void percent(char type, char subtype) -{ - INT32 vofs = 0; - char *name=NULL; - int extend = (addrsize == 32) ? 4 : 2; - UINT8 c; - - switch (type) { - case 'A': /* direct address */ - outhex(subtype, extend, 0, addrsize, 0); - break; - - case 'C': /* reg(r/m) picks control reg */ - uprintf("CR%d", REG(modrm())); - must_do_size = 0; - break; - - case 'D': /* reg(r/m) picks debug reg */ - uprintf("DR%d", REG(modrm())); - must_do_size = 0; - break; - - case 'E': /* r/m picks operand */ - do_modrm(subtype); - break; - - case 'G': /* reg(r/m) picks register */ - if (subtype == 'F') /* 80*87 operand? */ - reg_name(RM(modrm()), subtype); - else - reg_name(REG(modrm()), subtype); - must_do_size = 0; - break; - - case 'I': /* immed data */ - outhex(subtype, 0, 0, opsize, 0); - break; - - case 'J': /* relative IP offset */ - switch (bytes(subtype)) { /* sizeof offset value */ - case 1: - vofs = (INT8)getbyte(); - name = addr_to_hex(vofs+instruction_offset+INSTRUCTION_SIZE,0); - break; - case 2: - vofs = getbyte(); - vofs += getbyte()<<8; - vofs = (INT16)vofs; - name = addr_to_hex(vofs+instruction_offset+INSTRUCTION_SIZE,0); - break; - /* i386 */ - case 4: - vofs = (UINT32)getbyte(); /* yuk! */ - vofs |= (UINT32)getbyte() << 8; - vofs |= (UINT32)getbyte() << 16; - vofs |= (UINT32)getbyte() << 24; - name = addr_to_hex(vofs+instruction_offset+INSTRUCTION_SIZE,(addrsize == 32)?0:1); - break; - } - if (vofs<0) - uprintf("%s ($-%x)", name, -vofs); - else - uprintf("%s ($+%x)", name, vofs); - break; - - case 'K': - switch (subtype) { - case 'f': - ua_str("far "); - break; - case 'n': - ua_str("near "); - break; - case 's': - ua_str("short "); - break; - } - break; - - case 'M': /* r/m picks memory */ - do_modrm(subtype); - break; - - case 'O': /* offset only */ - ua_str("%p:["); - outhex(subtype, extend, 0, addrsize, 0); - uputchar(']'); - break; - - case 'P': /* prefix byte (rh) */ - ua_str("%p:"); - break; - - case 'R': /* mod(r/m) picks register */ - reg_name(RM(modrm()), subtype); /* rh */ - must_do_size = 0; - break; - - case 'S': /* reg(r/m) picks segment reg */ - uputchar("ecsdfg"[REG(modrm())]); - uputchar('s'); - must_do_size = 0; - break; - - case 'T': /* reg(r/m) picks T reg */ - uprintf("tr%d", REG(modrm())); - must_do_size = 0; - break; - - case 'X': /* ds:si type operator */ - uprintf("ds:["); - if (addrsize == 32) - uputchar('e'); - uprintf("si]"); - break; - - case 'Y': /* es:di type operator */ - uprintf("es:["); - if (addrsize == 32) - uputchar('e'); - uprintf("di]"); - break; - - case '2': /* old [pop cs]! now indexes */ - ua_str(second[getbyte()]); /* instructions in 386/486 */ - break; - - case 'g': /* modrm group `subtype' (0--7) */ - ua_str(groups[subtype-'0'][REG(modrm())]); - break; - - case 'd': /* sizeof operand==dword? */ - if (opsize == 32) - uputchar('d'); - uputchar(subtype); - break; - - case 'w': /* insert explicit size specifier */ - if (opsize == 32) - uputchar('d'); - else - uputchar('w'); - uputchar(subtype); - break; - - case 'e': /* extended reg name */ - if (opsize == 32) { - if (subtype == 'w') - uputchar('d'); - else { - uputchar('e'); - uputchar(subtype); - } - } else - uputchar(subtype); - break; - - case 'f': /* '87 opcode */ - floating_point(subtype-'0'); - break; - - case 'j': - if (addrsize==32 || opsize==32) /* both of them?! */ - uputchar('e'); - break; - - case 'p': /* prefix byte */ - switch (subtype) { - case 'c': - case 'd': - case 'e': - case 'f': - case 'g': - case 's': - prefix = subtype; - c = getbyte(); - wordop = c & 1; - ua_str((*opmap1)[c]); - break; - case ':': - if (prefix) - uprintf("%cs:", prefix); - break; - case ' ': - c = getbyte(); - wordop = c & 1; - ua_str((*opmap1)[c]); - break; - } - break; - - case 's': /* size override */ - switch (subtype) { - case 'a': - addrsize = 48 - addrsize; - c = getbyte(); - wordop = c & 1; - ua_str((*opmap1)[c]); -/* ua_str(opmap1[getbyte()]); */ - break; - case 'o': - opsize = 48 - opsize; - c = getbyte(); - wordop = c & 1; - ua_str((*opmap1)[c]); -/* ua_str(opmap1[getbyte()]); */ - break; - } - break; - } -} - - -static void ua_str(char const *str) -{ - char c; - - if (str == 0) { - invalid_opcode = 1; - uprintf("?"); - return; - } - - if (strpbrk(str, "CDFGRST")) /* specifiers for registers=>no size 2b specified */ - must_do_size = 0; - - while ((c = *str++) != 0) { - if (c == ' ' && first_space) - { - first_space = 0; - do - { - uputchar(' '); - } while ( (int)(ubufp - ubufs) < 5 ); - } - else - if (c == '%') { - c = *str++; - percent(c, *str++); - } else { - uputchar(c); - } - } -} - - -Bitu DasmI386(char* buffer, PhysPt pc, Bitu cur_ip, bool bit32) -{ - Bitu c; - - - instruction_offset = cur_ip; - /* input buffer */ - startPtr = pc; - getbyte_mac = pc; - - /* output buffer */ - ubufs = buffer; - ubufp = buffer; - first_space = 1; - - addr32bit=1; - - prefix = 0; - modrmv = sibv = -1; /* set modrm and sib flags */ - if (bit32) opsize = addrsize = 32; - else opsize = addrsize = 16; - c = getbyte(); - wordop = c & 1; - must_do_size = 1; - invalid_opcode = 0; - opmap1=&op386map1; - ua_str(op386map1[c]); - - if (invalid_opcode) { - /* restart output buffer */ - ubufp = buffer; - /* invalid instruction, use db xx */ - uprintf("db %02X", (unsigned)c); - return 1; - } - - return getbyte_mac-pc; -} - -int DasmLastOperandSize() -{ - return opsize; -}; - - -#endif - + +/* + Ripped out some stuff from the mame releae to only make it for 386's + Changed some variables to use the standard DOSBox data types + Added my callback opcode + +*/ + +/* + * 2asm: Convert binary files to 80*86 assembler. Version 1.00 + * Adapted by Andrea Mazzoleni for use with MAME + * HJB 990321: + * Changed output of hex values from 0xxxxh to $xxxx format + * Removed "ptr" from "byte ptr", "word ptr" and "dword ptr" +*/ + +/* 2asm comments + +License: + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +Comments: + + The code was originally snaffled from the GNU C++ debugger, as ported + to DOS by DJ Delorie and Kent Williams (williams@herky.cs.uiowa.edu). + Extensively modified by Robin Hilliard in Jan and May 1992. + + This source compiles under Turbo C v2.01. The disassembler is entirely + table driven so it's fairly easy to change to suit your own tastes. + + The instruction table has been modified to correspond with that in + `Programmer's Technical Reference: The Processor and Coprocessor', + Robert L. Hummel, Ziff-Davis Press, 1992. Missing (read "undocumented") + instructions were added and many mistakes and omissions corrected. + + +Health warning: + + When writing and degbugging this code, I didn't have (and still don't have) + a 32-bit disassembler to compare this guy's output with. It's therefore + quite likely that bugs will appear when disassembling instructions which use + the 386 and 486's native 32 bit mode. It seems to work fine in 16 bit mode. + +Any comments/updates/bug reports to: + + Robin Hilliard, Lough Guitane, Killarney, Co. Kerry, Ireland. + Tel: [+353] 64-54014 + Internet: softloft@iruccvax.ucc.ie + Compu$erve: 100042, 1237 + + If you feel like registering, and possibly get notices of updates and + other items of software, then send me a post card of your home town. + + Thanks and enjoy! + +*/ +#include "dosbox.h" +#ifdef C_DEBUG +#include +#include +#include +#include +#include "mem.h" + +typedef Bit8u UINT8; +typedef Bit16u UINT16; +typedef Bit32u UINT32; + +typedef Bit8s INT8; +typedef Bit16s INT16; +typedef Bit32s INT32; + + +/* Little endian uint read */ +#define le_uint8(ptr) (*(UINT8*)ptr) + +INLINE UINT16 le_uint16(const void* ptr) { + const UINT8* ptr8 = (const UINT8*)ptr; + return (UINT16)ptr8[0] | (UINT16)ptr8[1] << 8; +} +INLINE UINT32 le_uint32(const void* ptr) { + const UINT8* ptr8 = (const UINT8*)ptr; + return (UINT32)ptr8[0] | (UINT32)ptr8[1] << 8 | (UINT32)ptr8[2] << 16 | (UINT32)ptr8[3] << 24; +} + +/* Little endian int read */ +#define le_int8(ptr) ((INT8)le_uint8(ptr)) +#define le_int16(ptr) ((INT16)le_uint16(ptr)) +#define le_int32(ptr) ((INT32)le_uint32(ptr)) + +#define fp_segment(dw) ((dw >> 16) & 0xFFFFU) +#define fp_offset(dw) (dw & 0xFFFFU) +#define fp_addr(seg, off) ( (seg<<4)+off ) + +static UINT8 must_do_size; /* used with size of operand */ +static int wordop; /* dealing with word or byte operand */ + +static int instruction_offset; +//static UINT16 instruction_segment; + +static char* ubufs; /* start of buffer */ +static char* ubufp; /* last position of buffer */ +static int invalid_opcode = 0; +static int first_space = 1; + +static int prefix; /* segment override prefix byte */ +static int modrmv; /* flag for getting modrm byte */ +static int sibv; /* flag for getting sib byte */ +static int opsize; /* just like it says ... */ +static int addrsize; +static int addr20bit=0; +static int addr24bit=0; +static int addr32bit=0; + +/* some defines for extracting instruction bit fields from bytes */ + +#define MOD(a) (((a)>>6)&7) +#define REG(a) (((a)>>3)&7) +#define RM(a) ((a)&7) +#define SCALE(a) (((a)>>6)&7) +#define INDEX(a) (((a)>>3)&7) +#define BASE(a) ((a)&7) + +/* Percent tokens in strings: + First char after '%': + A - direct address + C - reg of r/m picks control register + D - reg of r/m picks debug register + E - r/m picks operand + F - flags register + G - reg of r/m picks general register + I - immediate data + J - relative IP offset ++ K - call/jmp distance + M - r/m picks memory + O - no r/m, offset only + R - mod of r/m picks register only + S - reg of r/m picks segment register + T - reg of r/m picks test register + X - DS:ESI + Y - ES:EDI + 2 - prefix of two-byte opcode ++ e - put in 'e' if use32 (second char is part of reg name) ++ put in 'w' for use16 or 'd' for use32 (second char is 'w') ++ j - put in 'e' in jcxz if prefix==0x66 + f - floating point (second char is esc value) + g - do r/m group 'n', n==0..7 + p - prefix + s - size override (second char is a,o) ++ d - put d if double arg, nothing otherwise (pushfd, popfd &c) ++ w - put w if word, d if double arg, nothing otherwise (lodsw/lodsd) ++ P - simple prefix + + Second char after '%': + a - two words in memory (BOUND) + b - byte + c - byte or word + d - dword ++ f - far call/jmp ++ n - near call/jmp + p - 32 or 48 bit pointer ++ q - byte/word thingy + s - six byte pseudo-descriptor + v - word or dword + w - word ++ x - sign extended byte + F - use floating regs in mod/rm + 1-8 - group number, esc value, etc +*/ + +/* watch out for aad && aam with odd operands */ + +static char *(*opmap1)[256]; + +static char *op386map1[256] = { +/* 0 */ + "add %Eb,%Gb", "add %Ev,%Gv", "add %Gb,%Eb", "add %Gv,%Ev", + "add al,%Ib", "add %eax,%Iv", "push es", "pop es", + "or %Eb,%Gb", "or %Ev,%Gv", "or %Gb,%Eb", "or %Gv,%Ev", + "or al,%Ib", "or %eax,%Iv", "push cs", "%2 ", +/* 1 */ + "adc %Eb,%Gb", "adc %Ev,%Gv", "adc %Gb,%Eb", "adc %Gv,%Ev", + "adc al,%Ib", "adc %eax,%Iv", "push ss", "pop ss", + "sbb %Eb,%Gb", "sbb %Ev,%Gv", "sbb %Gb,%Eb", "sbb %Gv,%Ev", + "sbb al,%Ib", "sbb %eax,%Iv", "push ds", "pop ds", +/* 2 */ + "and %Eb,%Gb", "and %Ev,%Gv", "and %Gb,%Eb", "and %Gv,%Ev", + "and al,%Ib", "and %eax,%Iv", "%pe", "daa", + "sub %Eb,%Gb", "sub %Ev,%Gv", "sub %Gb,%Eb", "sub %Gv,%Ev", + "sub al,%Ib", "sub %eax,%Iv", "%pc", "das", +/* 3 */ + "xor %Eb,%Gb", "xor %Ev,%Gv", "xor %Gb,%Eb", "xor %Gv,%Ev", + "xor al,%Ib", "xor %eax,%Iv", "%ps", "aaa", + "cmp %Eb,%Gb", "cmp %Ev,%Gv", "cmp %Gb,%Eb", "cmp %Gv,%Ev", + "cmp al,%Ib", "cmp %eax,%Iv", "%pd", "aas", +/* 4 */ + "inc %eax", "inc %ecx", "inc %edx", "inc %ebx", + "inc %esp", "inc %ebp", "inc %esi", "inc %edi", + "dec %eax", "dec %ecx", "dec %edx", "dec %ebx", + "dec %esp", "dec %ebp", "dec %esi", "dec %edi", +/* 5 */ + "push %eax", "push %ecx", "push %edx", "push %ebx", + "push %esp", "push %ebp", "push %esi", "push %edi", + "pop %eax", "pop %ecx", "pop %edx", "pop %ebx", + "pop %esp", "pop %ebp", "pop %esi", "pop %edi", +/* 6 */ + "pusha%d ", "popa%d ", "bound %Gv,%Ma", "arpl %Ew,%Rw", + "%pf", "%pg", "%so", "%sa", + "push %Iv", "imul %Gv,%Ev,%Iv","push %Ix", "imul %Gv,%Ev,%Ib", + "insb", "ins%ew", "outsb", "outs%ew", +/* 7 */ + "jo %Jb", "jno %Jb", "jc %Jb", "jnc %Jb", + "je %Jb", "jne %Jb", "jbe %Jb", "ja %Jb", + "js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb", + "jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb", +/* 8 */ +/* "%g0 %Eb,%Ib", "%g0 %Ev,%Iv", "%g0 %Ev,%Ib", "%g0 %Ev,%Ib", */ + "%g0 %Eb,%Ib", "%g0 %Ev,%Iv", "%g0 %Ev,%Ix", "%g0 %Ev,%Ix", + "test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv", + "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev", + "mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev", +/* 9 */ + "nop", "xchg %ecx,%eax", "xchg %edx,%eax", "xchg %ebx,%eax", + "xchg %esp,%eax", "xchg %ebp,%eax", "xchg %esi,%eax", "xchg %edi,%eax", + "cbw", "cwd", "call %Ap", "fwait", + "pushf%d ", "popf%d ", "sahf", "lahf", +/* a */ + "mov al,%Oc", "mov %eax,%Ov", "mov %Oc,al", "mov %Ov,%eax", + "%P movsb", "%P movs%w", "%P cmpsb", "%P cmps%w ", + "test al,%Ib", "test %eax,%Iv", "%P stosb", "%P stos%w ", + "%P lodsb", "%P lods%w ", "%P scasb", "%P scas%w ", +/* b */ + "mov al,%Ib", "mov cl,%Ib", "mov dl,%Ib", "mov bl,%Ib", + "mov ah,%Ib", "mov ch,%Ib", "mov dh,%Ib", "mov bh,%Ib", + "mov %eax,%Iv", "mov %ecx,%Iv", "mov %edx,%Iv", "mov %ebx,%Iv", + "mov %esp,%Iv", "mov %ebp,%Iv", "mov %esi,%Iv", "mov %edi,%Iv", +/* c */ + "%g1 %Eb,%Ib", "%g1 %Ev,%Ib", "ret %Iw", "ret", + "les %Gv,%Mp", "lds %Gv,%Mp", "mov %Eb,%Ib", "mov %Ev,%Iv", + "enter %Iw,%Ib", "leave", "retf %Iw", "retf", + "int 03", "int %Ib", "into", "iret", +/* d */ + "%g1 %Eb,1", "%g1 %Ev,1", "%g1 %Eb,cl", "%g1 %Ev,cl", + "aam ; %Ib", "aad ; %Ib", "setalc", "xlat", +#if 0 + "esc 0,%Ib", "esc 1,%Ib", "esc 2,%Ib", "esc 3,%Ib", + "esc 4,%Ib", "esc 5,%Ib", "esc 6,%Ib", "esc 7,%Ib", +#else + "%f0", "%f1", "%f2", "%f3", + "%f4", "%f5", "%f6", "%f7", +#endif +/* e */ + "loopne %Jb", "loope %Jb", "loop %Jb", "j%j cxz %Jb", + "in al,%Ib", "in %eax,%Ib", "out %Ib,al", "out %Ib,%eax", + "call %Jv", "jmp %Jv", "jmp %Ap", "jmp %Ks%Jb", + "in al,dx", "in %eax,dx", "out dx,al", "out dx,%eax", +/* f */ + "lock %p ", 0, "repne %p ", "repe %p ", + "hlt", "cmc", "%g2", "%g2", + "clc", "stc", "cli", "sti", + "cld", "std", "%g3", "%g4" +}; + +static char *second[] = { +/* 0 */ + "%g5", "%g6", "lar %Gv,%Ew", "lsl %Gv,%Ew", + 0, "loadall", "clts", "loadall", + "invd", "wbinvd", 0, 0, + 0, 0, 0, 0, +/* 1 */ + "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev", + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +/* 2 */ + "mov %Rd,%Cd", "mov %Rd,%Dd", "mov %Cd,%Rd", "mov %Dd,%Rd", + "mov %Rd,%Td", 0, "mov %Td,%Rd", 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +/* 3 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +/* 4 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +/* 5 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +/* 6 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +/* 7 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +/* 8 */ + "jo %Jv", "jno %Jv", "jb %Jv", "jnb %Jv", + "jz %Jv", "jnz %Jv", "jbe %Jv", "ja %Jv", + "js %Jv", "jns %Jv", "jp %Jv", "jnp %Jv", + "jl %Jv", "jge %Jv", "jle %Jv", "jg %Jv", +/* 9 */ + "seto %Eb", "setno %Eb", "setc %Eb", "setnc %Eb", + "setz %Eb", "setnz %Eb", "setbe %Eb", "setnbe %Eb", + "sets %Eb", "setns %Eb", "setp %Eb", "setnp %Eb", + "setl %Eb", "setge %Eb", "setle %Eb", "setg %Eb", +/* a */ + "push fs", "pop fs", 0, "bt %Ev,%Gv", + "shld %Ev,%Gv,%Ib", "shld %Ev,%Gv,cl", 0, 0, + "push gs", "pop gs", 0, "bts %Ev,%Gv", + "shrd %Ev,%Gv,%Ib", "shrd %Ev,%Gv,cl", 0, "imul %Gv,%Ev", +/* b */ + "cmpxchg %Eb,%Gb", "cmpxchg %Ev,%Gv", "lss %Mp", "btr %Ev,%Gv", + "lfs %Mp", "lgs %Mp", "movzx %Gv,%Eb", "movzx %Gv,%Ew", + 0, 0, "%g7 %Ev,%Ib", "btc %Ev,%Gv", + "bsf %Gv,%Ev", "bsr %Gv,%Ev", "movsx %Gv,%Eb", "movsx %Gv,%Ew", +/* c */ + "xadd %Eb,%Gb", "xadd %Ev,%Gv", 0, 0, + 0, 0, 0, 0, + "bswap eax", "bswap ecx", "bswap edx", "bswap ebx", + "bswap esp", "bswap ebp", "bswap esi", "bswap edi", +/* d */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +/* e */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +/* f */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static char *groups[][8] = { /* group 0 is group 3 for %Ev set */ +/* 0 */ + { "add", "or", "adc", "sbb", + "and", "sub", "xor", "cmp" }, +/* 1 */ + { "rol", "ror", "rcl", "rcr", + "shl", "shr", "shl", "sar" }, +/* 2 */ /* v v*/ + { "test %Eq,%Iq", "test %Eq,%Iq", "not %Ec", "neg %Ev", + "mul %Ec", "imul %Ec", "div %Ec", "idiv %Ec" }, +/* 3 */ + { "inc %Eb", "dec %Eb", 0, 0, + 0, 0, 0, "callback %Iw" }, +/* 4 */ + { "inc %Ev", "dec %Ev", "call %Kn%Ev", "call %Kf%Ep", + "jmp %Kn%Ev", "jmp %Kf%Ep", "push %Ev", 0 }, +/* 5 */ + { "sldt %Ew", "str %Ew", "lldt %Ew", "ltr %Ew", + "verr %Ew", "verw %Ew", 0, 0 }, +/* 6 */ + { "sgdt %Ms", "sidt %Ms", "lgdt %Ms", "lidt %Ms", + "smsw %Ew", 0, "lmsw %Ew", 0 }, +/* 7 */ + { 0, 0, 0, 0, + "bt", "bts", "btr", "btc" } +}; + +/* zero here means invalid. If first entry starts with '*', use st(i) */ +/* no assumed %EFs here. Indexed by RM(modrm()) */ +static char *f0[] = { 0, 0, 0, 0, 0, 0, 0, 0}; +static char *fop_9[] = { "*fxch st,%GF" }; +static char *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 }; +static char *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 }; +static char *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi", + "fldlg2", "fldln2", "fldz", 0 }; +static char *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan", + "fxtract", "fprem1", "fdecstp", "fincstp" }; +static char *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos", + "frndint", "fscale", "fsin", "fcos" }; +static char *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 }; +static char *fop_28[] = { 0, 0, "fclex", "finit", 0, 0, 0, 0 }; +static char *fop_32[] = { "*fadd %GF,st" }; +static char *fop_33[] = { "*fmul %GF,st" }; +static char *fop_36[] = { "*fsubr %GF,st" }; +static char *fop_37[] = { "*fsub %GF,st" }; +static char *fop_38[] = { "*fdivr %GF,st" }; +static char *fop_39[] = { "*fdiv %GF,st" }; +static char *fop_40[] = { "*ffree %GF" }; +static char *fop_42[] = { "*fst %GF" }; +static char *fop_43[] = { "*fstp %GF" }; +static char *fop_44[] = { "*fucom %GF" }; +static char *fop_45[] = { "*fucomp %GF" }; +static char *fop_48[] = { "*faddp %GF,st" }; +static char *fop_49[] = { "*fmulp %GF,st" }; +static char *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 }; +static char *fop_52[] = { "*fsubrp %GF,st" }; +static char *fop_53[] = { "*fsubp %GF,st" }; +static char *fop_54[] = { "*fdivrp %GF,st" }; +static char *fop_55[] = { "*fdivp %GF,st" }; +static char *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 }; + +static char **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15, + f0, f0, f0, f0, f0, fop_21, f0, f0, + f0, f0, f0, f0, fop_28, f0, f0, f0, + fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39, + fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0, + fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55, + f0, f0, f0, f0, fop_60, f0, f0, f0, +}; + +static char *floatops[] = { /* assumed " %EF" at end of each. mod != 3 only */ +/*00*/ "fadd", "fmul", "fcom", "fcomp", + "fsub", "fsubr", "fdiv", "fdivr", +/*08*/ "fld", 0, "fst", "fstp", + "fldenv", "fldcw", "fstenv", "fstcw", +/*16*/ "fiadd", "fimul", "ficomw", "ficompw", + "fisub", "fisubr", "fidiv", "fidivr", +/*24*/ "fild", 0, "fist", "fistp", + "frstor", "fldt", 0, "fstpt", +/*32*/ "faddq", "fmulq", "fcomq", "fcompq", + "fsubq", "fsubrq", "fdivq", "fdivrq", +/*40*/ "fldq", 0, "fstq", "fstpq", + 0, 0, "fsave", "fstsw", +/*48*/ "fiaddw", "fimulw", "ficomw", "ficompw", + "fisubw", "fisubrw", "fidivw", "fidivr", +/*56*/ "fildw", 0, "fistw", "fistpw", + "fbldt", "fildq", "fbstpt", "fistpq" +}; + +static char *addr_to_hex(UINT32 addr, int splitup) { + static char buffer[11]; + + if (splitup) { + if (fp_segment(addr)==0 || fp_offset(addr)==0xffff) /* 'coz of wraparound */ + sprintf(buffer, "%04X", (unsigned)fp_offset(addr) ); + else + sprintf(buffer, "%04X:%04X", (unsigned)fp_segment(addr), (unsigned)fp_offset(addr) ); + } else { +#if 0 + /* Pet outcommented, reducing address size to 4 + when segment is 0 or 0xffff */ + if (fp_segment(addr)==0 || fp_segment(addr)==0xffff) /* 'coz of wraparound */ + sprintf(buffer, "%04X", (unsigned)fp_offset(addr) ); + else +#endif + + if (addr20bit) { + sprintf(buffer, "%05X", addr&0xfffff ); + } else if (addr24bit) { + sprintf(buffer, "%06X", addr&0xffffff ); + } else if (addr32bit) { + sprintf(buffer, "%08X", addr ); + } + } + + return buffer; +} + +static PhysOff getbyte_mac; + + +static UINT8 getbyte(void) { + return mem_readb(getbyte_mac++); +} + +/* + only one modrm or sib byte per instruction, tho' they need to be + returned a few times... +*/ + +static int modrm(void) +{ + if (modrmv == -1) + modrmv = getbyte(); + return modrmv; +} + +static int sib(void) +{ + if (sibv == -1) + sibv = getbyte(); + return sibv; +} + +/*------------------------------------------------------------------------*/ + +static void uprintf(char *s, ...) +{ + va_list arg_ptr; + va_start (arg_ptr, s); + vsprintf(ubufp, s, arg_ptr); + while (*ubufp) + ubufp++; +} + +static void uputchar(char c) +{ + *ubufp++ = c; + *ubufp = 0; +} + +/*------------------------------------------------------------------------*/ + +static int bytes(char c) +{ + switch (c) { + case 'b': + return 1; + case 'w': + return 2; + case 'd': + return 4; + case 'v': + if (opsize == 32) + return 4; + else + return 2; + } + return 0; +} + +/*------------------------------------------------------------------------*/ +static void outhex(char subtype, int extend, int optional, int defsize, int sign) +{ + int n=0, s=0, i; + INT32 delta = 0; + unsigned char buff[6]; + char *name; + char signchar; + + switch (subtype) { + case 'q': + if (wordop) { + if (opsize==16) { + n = 2; + } else { + n = 4; + } + } else { + n = 1; + } + break; + + case 'a': + break; + case 'x': + extend = 2; + n = 1; + break; + case 'b': + n = 1; + break; + case 'w': + n = 2; + break; + case 'd': + n = 4; + break; + case 's': + n = 6; + break; + case 'c': + case 'v': + if (defsize == 32) + n = 4; + else + n = 2; + break; + case 'p': + if (defsize == 32) + n = 6; + else + n = 4; + s = 1; + break; + } + for (i=0; i n) { + if (subtype!='x') { + if (delta<0) { + delta = -delta; + signchar = '-'; + } else + signchar = '+'; + if (delta || !optional) + uprintf("%c%0*lX", (char)signchar, (int)(extend), (long)delta); + } else { + if (extend==2) + delta = (UINT16)delta; + uprintf("%0.*lX", (int)(2*extend), (long)delta ); + } + return; + } + if ((n == 4) && !sign) { + name = addr_to_hex(delta, 0); + uprintf("%s", name); + return; + } + switch (n) { + case 1: + if (sign && (char)delta<0) { + delta = -delta; + signchar = '-'; + } else + signchar = '+'; + if (sign) + uprintf("%c%02lX", (char)signchar, delta & 0xFFL); + else + uprintf("%02lX", delta & 0xFFL); + break; + + case 2: + if (sign && delta<0) { + signchar = '-'; + delta = -delta; + } else + signchar = '+'; + if (sign) + uprintf("%c%04lX", (char)signchar, delta & 0xFFFFL); + else + uprintf("%04lX", delta & 0xFFFFL); + break; + + case 4: + if (sign && delta<0) { + delta = -delta; + signchar = '-'; + } else + signchar = '+'; + if (sign) + uprintf("%c%08lX", (char)signchar, delta & 0xFFFFFFFFL); + else + uprintf("%08lX", delta & 0xFFFFFFFFL); + break; + } +} + + +/*------------------------------------------------------------------------*/ + +static void reg_name(int regnum, char size) +{ + if (size == 'F') { /* floating point register? */ + uprintf("st(%d)", regnum); + return; + } + if (((size == 'v') && (opsize == 32)) || (size == 'd')) + uputchar('e'); + if ((size=='q' || size == 'b' || size=='c') && !wordop) { + uputchar("acdbacdb"[regnum]); + uputchar("llllhhhh"[regnum]); + } else { + uputchar("acdbsbsd"[regnum]); + uputchar("xxxxppii"[regnum]); + } +} + + +/*------------------------------------------------------------------------*/ + +static void ua_str(char *str); + +static void do_sib(int m) +{ + int s, i, b; + + s = SCALE(sib()); + i = INDEX(sib()); + b = BASE(sib()); + switch (b) { /* pick base */ + case 0: ua_str("%p:[eax"); break; + case 1: ua_str("%p:[ecx"); break; + case 2: ua_str("%p:[edx"); break; + case 3: ua_str("%p:[ebx"); break; + case 4: ua_str("%p:[esp"); break; + case 5: + if (m == 0) { + ua_str("%p:["); + outhex('d', 4, 0, addrsize, 0); + } else { + ua_str("%p:[ebp"); + } + break; + case 6: ua_str("%p:[esi"); break; + case 7: ua_str("%p:[edi"); break; + } + switch (i) { /* and index */ + case 0: uprintf("+eax"); break; + case 1: uprintf("+ecx"); break; + case 2: uprintf("+edx"); break; + case 3: uprintf("+ebx"); break; + case 4: break; + case 5: uprintf("+ebp"); break; + case 6: uprintf("+esi"); break; + case 7: uprintf("+edi"); break; + } + if (i != 4) { + switch (s) { /* and scale */ + case 0: /*uprintf("");*/ break; + case 1: uprintf("*2"); break; + case 2: uprintf("*4"); break; + case 3: uprintf("*8"); break; + } + } +} + + + +/*------------------------------------------------------------------------*/ +static void do_modrm(char subtype) +{ + int mod = MOD(modrm()); + int rm = RM(modrm()); + int extend = (addrsize == 32) ? 4 : 2; + + if (mod == 3) { /* specifies two registers */ + reg_name(rm, subtype); + return; + } + if (must_do_size) { + if (wordop) { + if (addrsize==32 || opsize==32) { /* then must specify size */ + ua_str("dword "); + } else { + ua_str("word "); + } + } else { + ua_str("byte "); + } + } + if ((mod == 0) && (rm == 5) && (addrsize == 32)) {/* mem operand with 32 bit ofs */ + ua_str("%p:["); + outhex('d', extend, 0, addrsize, 0); + uputchar(']'); + return; + } + if ((mod == 0) && (rm == 6) && (addrsize == 16)) { /* 16 bit dsplcmnt */ + ua_str("%p:["); + outhex('w', extend, 0, addrsize, 0); + uputchar(']'); + return; + } + if ((addrsize != 32) || (rm != 4)) + ua_str("%p:["); + if (addrsize == 16) { + switch (rm) { + case 0: uprintf("bx+si"); break; + case 1: uprintf("bx+di"); break; + case 2: uprintf("bp+si"); break; + case 3: uprintf("bp+di"); break; + case 4: uprintf("si"); break; + case 5: uprintf("di"); break; + case 6: uprintf("bp"); break; + case 7: uprintf("bx"); break; + } + } else { + switch (rm) { + case 0: uprintf("eax"); break; + case 1: uprintf("ecx"); break; + case 2: uprintf("edx"); break; + case 3: uprintf("ebx"); break; + case 4: do_sib(mod); break; + case 5: uprintf("ebp"); break; + case 6: uprintf("esi"); break; + case 7: uprintf("edi"); break; + } + } + switch (mod) { + case 1: + outhex('b', extend, 1, addrsize, 0); + break; + case 2: + outhex('v', extend, 1, addrsize, 1); + break; + } + uputchar(']'); +} + + + +/*------------------------------------------------------------------------*/ +static void floating_point(int e1) +{ + int esc = e1*8 + REG(modrm()); + + if ((MOD(modrm()) == 3)&&fspecial[esc]) { + if (fspecial[esc][0]) { + if (fspecial[esc][0][0] == '*') { + ua_str(fspecial[esc][0]+1); + } else { + ua_str(fspecial[esc][RM(modrm())]); + } + } else { + ua_str(floatops[esc]); + ua_str(" %EF"); + } + } else { + ua_str(floatops[esc]); + ua_str(" %EF"); + } +} + + +/*------------------------------------------------------------------------*/ +/* Main table driver */ + +static void percent(char type, char subtype) +{ + INT32 vofs = 0; + char *name=NULL; + int extend = (addrsize == 32) ? 4 : 2; + UINT8 c; + + switch (type) { + case 'A': /* direct address */ + outhex(subtype, extend, 0, addrsize, 0); + break; + + case 'C': /* reg(r/m) picks control reg */ + uprintf("C%d", REG(modrm())); + must_do_size = 0; + break; + + case 'D': /* reg(r/m) picks debug reg */ + uprintf("D%d", REG(modrm())); + must_do_size = 0; + break; + + case 'E': /* r/m picks operand */ + do_modrm(subtype); + break; + + case 'G': /* reg(r/m) picks register */ + if (subtype == 'F') /* 80*87 operand? */ + reg_name(RM(modrm()), subtype); + else + reg_name(REG(modrm()), subtype); + must_do_size = 0; + break; + + case 'I': /* immed data */ + outhex(subtype, 0, 0, opsize, 0); + break; + + case 'J': /* relative IP offset */ + switch (bytes(subtype)) { /* sizeof offset value */ + case 1: + vofs = (INT8)getbyte(); + name = addr_to_hex(vofs+instruction_offset,0); + break; + case 2: + vofs = getbyte(); + vofs += getbyte()<<8; + vofs = (INT16)vofs; + name = addr_to_hex(vofs+instruction_offset,0); + break; +#if 0 + /* i386 */ + case 4: + vofs = (UINT32)getbyte(); /* yuk! */ + vofs |= (UINT32)getbyte() << 8; + vofs |= (UINT32)getbyte() << 16; + vofs |= (UINT32)getbyte() << 24; + name = addr_to_hex(vofs+instruction_offset,1); + break; +#endif + } + if (vofs<0) + uprintf("%s ($-%x)", name, -vofs); + else + uprintf("%s ($+%x)", name, vofs); + break; + + case 'K': + switch (subtype) { + case 'f': + ua_str("far "); + break; + case 'n': + ua_str("near "); + break; + case 's': + ua_str("short "); + break; + } + break; + + case 'M': /* r/m picks memory */ + do_modrm(subtype); + break; + + case 'O': /* offset only */ + ua_str("%p:["); + outhex(subtype, extend, 0, addrsize, 0); + uputchar(']'); + break; + + case 'P': /* prefix byte (rh) */ + ua_str("%p:"); + break; + + case 'R': /* mod(r/m) picks register */ + reg_name(REG(modrm()), subtype); /* rh */ + must_do_size = 0; + break; + + case 'S': /* reg(r/m) picks segment reg */ + uputchar("ecsdfg"[REG(modrm())]); + uputchar('s'); + must_do_size = 0; + break; + + case 'T': /* reg(r/m) picks T reg */ + uprintf("tr%d", REG(modrm())); + must_do_size = 0; + break; + + case 'X': /* ds:si type operator */ + uprintf("ds:["); + if (addrsize == 32) + uputchar('e'); + uprintf("si]"); + break; + + case 'Y': /* es:di type operator */ + uprintf("es:["); + if (addrsize == 32) + uputchar('e'); + uprintf("di]"); + break; + + case '2': /* old [pop cs]! now indexes */ + ua_str(second[getbyte()]); /* instructions in 386/486 */ + break; + + case 'g': /* modrm group `subtype' (0--7) */ + ua_str(groups[subtype-'0'][REG(modrm())]); + break; + + case 'd': /* sizeof operand==dword? */ + if (opsize == 32) + uputchar('d'); + uputchar(subtype); + break; + + case 'w': /* insert explicit size specifier */ + if (opsize == 32) + uputchar('d'); + else + uputchar('w'); + uputchar(subtype); + break; + + case 'e': /* extended reg name */ + if (opsize == 32) { + if (subtype == 'w') + uputchar('d'); + else { + uputchar('e'); + uputchar(subtype); + } + } else + uputchar(subtype); + break; + + case 'f': /* '87 opcode */ + floating_point(subtype-'0'); + break; + + case 'j': + if (addrsize==32 || opsize==32) /* both of them?! */ + uputchar('e'); + break; + + case 'p': /* prefix byte */ + switch (subtype) { + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 's': + prefix = subtype; + c = getbyte(); + wordop = c & 1; + ua_str((*opmap1)[c]); + break; + case ':': + if (prefix) + uprintf("%cs:", prefix); + break; + case ' ': + c = getbyte(); + wordop = c & 1; + ua_str((*opmap1)[c]); + break; + } + break; + + case 's': /* size override */ + switch (subtype) { + case 'a': + addrsize = 48 - addrsize; + c = getbyte(); + wordop = c & 1; + ua_str((*opmap1)[c]); +/* ua_str(opmap1[getbyte()]); */ + break; + case 'o': + opsize = 48 - opsize; + c = getbyte(); + wordop = c & 1; + ua_str((*opmap1)[c]); +/* ua_str(opmap1[getbyte()]); */ + break; + } + break; + } +} + + +static void ua_str(char *str) +{ + char c; + + if (str == 0) { + invalid_opcode = 1; + uprintf("?"); + return; + } + + if (strpbrk(str, "CDFGRST")) /* specifiers for registers=>no size 2b specified */ + must_do_size = 0; + + while ((c = *str++) != 0) { + if (c == ' ' && first_space) + { + first_space = 0; + do + { + uputchar(' '); + } while ( (int)(ubufp - ubufs) < 5 ); + } + else + if (c == '%') { + c = *str++; + percent(c, *str++); + } else { + uputchar(c); + } + } +} + + +Bitu DasmI386(char* buffer, PhysOff pc, Bitu cur_ip, bool bit32) +{ + Bitu c; + + + instruction_offset = cur_ip; + /* input buffer */ + getbyte_mac = pc; + + /* output buffer */ + ubufs = buffer; + ubufp = buffer; + first_space = 1; + + addr32bit=1;addr20bit=addr24bit=0; + + prefix = 0; + modrmv = sibv = -1; /* set modrm and sib flags */ + if (bit32) opsize = addrsize = 32; + else opsize = addrsize = 16; + c = getbyte(); + wordop = c & 1; + must_do_size = 1; + invalid_opcode = 0; + opmap1=&op386map1; + ua_str(op386map1[c]); + + if (invalid_opcode) { + /* restart output buffer */ + ubufp = buffer; + /* invalid instruction, use db xx */ + uprintf("db %02X", (unsigned)c); + return 1; + } + + return getbyte_mac-pc; +} + + +#endif \ No newline at end of file diff --git a/src/debug/debug_gui.cpp b/src/debug/debug_gui.cpp index 4130c84..c13f306 100644 --- a/src/debug/debug_gui.cpp +++ b/src/debug/debug_gui.cpp @@ -1,285 +1,130 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: debug_gui.cpp,v 1.37 2009/02/01 19:28:58 qbix79 Exp $ */ - -#include "dosbox.h" - -#if C_DEBUG -#include "control.h" -#include -#include -#include -#include -#include - -#include "support.h" -#include "regs.h" -#include "debug.h" -#include "debug_inc.h" - -struct _LogGroup { - char const* front; - bool enabled; -}; -#include -#include -using namespace std; - -#define MAX_LOG_BUFFER 500 -static list logBuff; -static list::iterator logBuffPos = logBuff.end(); - -static _LogGroup loggrp[LOG_MAX]={{"",true},{0,false}}; -static FILE* debuglog; - -extern int old_cursor_state; - - - -void DEBUG_ShowMsg(char const* format,...) { - - char buf[512]; - va_list msg; - va_start(msg,format); - vsprintf(buf,format,msg); - va_end(msg); - - /* Add newline if not present */ - Bitu len=strlen(buf); - if(buf[len-1]!='\n') strcat(buf,"\n"); - - if(debuglog) fprintf(debuglog,"%s",buf); - - if (logBuffPos!=logBuff.end()) { - logBuffPos=logBuff.end(); - DEBUG_RefreshPage(0); -// mvwprintw(dbg.win_out,dbg.win_out->_maxy-1, 0, ""); - } - logBuff.push_back(buf); - if (logBuff.size() > MAX_LOG_BUFFER) - logBuff.pop_front(); - - logBuffPos = logBuff.end(); - wprintw(dbg.win_out,"%s",buf); - wrefresh(dbg.win_out); -} - -void DEBUG_RefreshPage(char scroll) { - if (scroll==-1 && logBuffPos!=logBuff.begin()) logBuffPos--; - else if (scroll==1 && logBuffPos!=logBuff.end()) logBuffPos++; - - list::iterator i = logBuffPos; - int maxy, maxx; getmaxyx(dbg.win_out,maxy,maxx); - int rem_lines = maxy; - - wclear(dbg.win_out); - - while (rem_lines > 0 && i!=logBuff.begin()) { - --i; - for (string::size_type posf=0, posl; (posl=(*i).find('\n',posf)) != string::npos ;posf=posl+1) - rem_lines -= (int) ((posl-posf) / maxx) + 1; // len=(posl+1)-posf-1 - /* Const cast is needed for pdcurses which has no const char in mvwprintw (bug maybe) */ - mvwprintw(dbg.win_out,rem_lines-1, 0, const_cast((*i).c_str())); - } - mvwprintw(dbg.win_out,maxy-1, 0, ""); - wrefresh(dbg.win_out); -} - -void LOG::operator() (char const* format, ...){ - char buf[512]; - va_list msg; - va_start(msg,format); - vsprintf(buf,format,msg); - va_end(msg); - - if (d_type>=LOG_MAX) return; - if ((d_severity!=LOG_ERROR) && (!loggrp[d_type].enabled)) return; - DEBUG_ShowMsg("%10u: %s:%s\n",cycle_count,loggrp[d_type].front,buf); -} - - -static void Draw_RegisterLayout(void) { - mvwaddstr(dbg.win_reg,0,0,"EAX="); - mvwaddstr(dbg.win_reg,1,0,"EBX="); - mvwaddstr(dbg.win_reg,2,0,"ECX="); - mvwaddstr(dbg.win_reg,3,0,"EDX="); - - mvwaddstr(dbg.win_reg,0,14,"ESI="); - mvwaddstr(dbg.win_reg,1,14,"EDI="); - mvwaddstr(dbg.win_reg,2,14,"EBP="); - mvwaddstr(dbg.win_reg,3,14,"ESP="); - - mvwaddstr(dbg.win_reg,0,28,"DS="); - mvwaddstr(dbg.win_reg,0,38,"ES="); - mvwaddstr(dbg.win_reg,0,48,"FS="); - mvwaddstr(dbg.win_reg,0,58,"GS="); - mvwaddstr(dbg.win_reg,0,68,"SS="); - - mvwaddstr(dbg.win_reg,1,28,"CS="); - mvwaddstr(dbg.win_reg,1,38,"EIP="); - - mvwaddstr(dbg.win_reg,2,75,"CPL"); - mvwaddstr(dbg.win_reg,2,68,"IOPL"); - - mvwaddstr(dbg.win_reg,1,52,"C Z S O A P D I T "); -} - - -static void DrawBars(void) { - if (has_colors()) { - attrset(COLOR_PAIR(PAIR_BLACK_BLUE)); - } - /* Show the Register bar */ - mvaddstr(dbg.win_reg->_begy-1,0, "---(Register Overview )---"); - /* Show the Data Overview bar perhaps with more special stuff in the end */ - mvaddstr(dbg.win_data->_begy-1,0,"---(Data Overview Scroll: page up/down)---"); - /* Show the Code Overview perhaps with special stuff in bar too */ - mvaddstr(dbg.win_code->_begy-1,0,"---(Code Overview Scroll: up/down )---"); - /* Show the Variable Overview bar */ - mvaddstr(dbg.win_var->_begy-1,0, "---(Variable Overview )---"); - /* Show the Output OverView */ - mvaddstr(dbg.win_out->_begy-1,0, "---(OutPut/Input Scroll: home/end )---"); - attrset(0); -} - - - -static void MakeSubWindows(void) { - /* The Std output win should go in bottem */ - /* Make all the subwindows */ - int win_main_maxy, win_main_maxx; getmaxyx(dbg.win_main,win_main_maxy,win_main_maxx); - int outy=1; - /* The Register window */ - dbg.win_reg=subwin(dbg.win_main,4,win_main_maxx,outy,0); - outy+=5; - /* The Data Window */ - dbg.win_data=subwin(dbg.win_main,10,win_main_maxx,outy,0); - outy+=11; - /* The Code Window */ - dbg.win_code=subwin(dbg.win_main,11,win_main_maxx,outy,0); - outy+=12; - /* The Variable Window */ - dbg.win_var=subwin(dbg.win_main,4,win_main_maxx,outy,0); - outy+=5; - /* The Output Window */ - dbg.win_out=subwin(dbg.win_main,win_main_maxy-outy-1,win_main_maxx,outy,0); - dbg.input_y=win_main_maxy-1; - scrollok(dbg.win_out,TRUE); - DrawBars(); - Draw_RegisterLayout(); - refresh(); -} - -static void MakePairs(void) { - init_pair(PAIR_BLACK_BLUE, COLOR_BLACK, COLOR_CYAN); - init_pair(PAIR_BYELLOW_BLACK, COLOR_YELLOW /*| FOREGROUND_INTENSITY */, COLOR_BLACK); - init_pair(PAIR_GREEN_BLACK, COLOR_GREEN /*| FOREGROUND_INTENSITY */, COLOR_BLACK); - init_pair(PAIR_BLACK_GREY, COLOR_BLACK /*| FOREGROUND_INTENSITY */, COLOR_WHITE); - init_pair(PAIR_GREY_RED, COLOR_WHITE/*| FOREGROUND_INTENSITY */, COLOR_RED); -} -static void LOG_Destroy(Section*) { - if(debuglog) fclose(debuglog); -} - -static void LOG_Init(Section * sec) { - Section_prop * sect=static_cast(sec); - const char * blah=sect->Get_string("logfile"); - if(blah && blah[0] &&(debuglog = fopen(blah,"wt+"))){ - }else{ - debuglog=0; - } - sect->AddDestroyFunction(&LOG_Destroy); - char buf[1024]; - for (Bitu i=1;iGet_bool(buf); - } -} - - -void LOG_StartUp(void) { - /* Setup logging groups */ - loggrp[LOG_ALL].front="ALL"; - loggrp[LOG_VGA].front="VGA"; - loggrp[LOG_VGAGFX].front="VGAGFX"; - loggrp[LOG_VGAMISC].front="VGAMISC"; - loggrp[LOG_INT10].front="INT10"; - loggrp[LOG_SB].front="SBLASTER"; - loggrp[LOG_DMACONTROL].front="DMA_CONTROL"; - - loggrp[LOG_FPU].front="FPU"; - loggrp[LOG_CPU].front="CPU"; - loggrp[LOG_PAGING].front="PAGING"; - - loggrp[LOG_FCB].front="FCB"; - loggrp[LOG_FILES].front="FILES"; - loggrp[LOG_IOCTL].front="IOCTL"; - loggrp[LOG_EXEC].front="EXEC"; - loggrp[LOG_DOSMISC].front="DOSMISC"; - - loggrp[LOG_PIT].front="PIT"; - loggrp[LOG_KEYBOARD].front="KEYBOARD"; - loggrp[LOG_PIC].front="PIC"; - - loggrp[LOG_MOUSE].front="MOUSE"; - loggrp[LOG_BIOS].front="BIOS"; - loggrp[LOG_GUI].front="GUI"; - loggrp[LOG_MISC].front="MISC"; - - loggrp[LOG_IO].front="IO"; - - /* Register the log section */ - Section_prop * sect=control->AddSection_prop("log",LOG_Init); - Prop_string* Pstring = sect->Add_string("logfile",Property::Changeable::Always,""); - Pstring->Set_help("file where the log messages will be saved to"); - char buf[1024]; - for (Bitu i=1;iAdd_bool(buf,Property::Changeable::Always,true); - Pbool->Set_help("Enable/Disable logging of this type."); - } - MSG_Add("LOG_CONFIGFILE_HELP","Logging related options for the debugger.\n"); -} - - - - -void DBGUI_StartUp(void) { - /* Start the main window */ - dbg.win_main=initscr(); - cbreak(); /* take input chars one at a time, no wait for \n */ - noecho(); /* don't echo input */ - nodelay(dbg.win_main,true); - keypad(dbg.win_main,true); - #ifndef WIN32 - resizeterm(50,80); - touchwin(dbg.win_main); - #endif - old_cursor_state = curs_set(0); - start_color(); - cycle_count=0; - MakePairs(); - MakeSubWindows(); - -} - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + + +#include "dosbox.h" +#ifdef C_DEBUG + +#include +#include +#include +#include +#include + +#include "regs.h" +#include "debug.h" +#include "debug_inc.h" + +void DEBUG_ShowMsg(char * msg) { + char buf[1024]; + strcpy(buf,msg); + strcat(buf,"\n"); + + waddstr(dbg.win_out,buf); + wprintw(dbg.win_out," %d\n",cycle_count); + wrefresh(dbg.win_out); +} + + + +static void Draw_RegisterLayout(void) { + mvwaddstr(dbg.win_reg,0,0,"EAX="); + mvwaddstr(dbg.win_reg,1,0,"EBX="); + mvwaddstr(dbg.win_reg,2,0,"ECX="); + mvwaddstr(dbg.win_reg,3,0,"EDX="); + + mvwaddstr(dbg.win_reg,0,14,"ESI="); + mvwaddstr(dbg.win_reg,1,14,"EDI="); + mvwaddstr(dbg.win_reg,2,14,"EBP="); + mvwaddstr(dbg.win_reg,3,14,"ESP="); + + mvwaddstr(dbg.win_reg,0,28,"DS="); + mvwaddstr(dbg.win_reg,0,38,"ES="); + mvwaddstr(dbg.win_reg,0,48,"FS="); + mvwaddstr(dbg.win_reg,0,58,"GS="); + mvwaddstr(dbg.win_reg,0,68,"SS="); + + mvwaddstr(dbg.win_reg,1,28,"CS="); + mvwaddstr(dbg.win_reg,1,38,"EIP="); + + + mvwaddstr(dbg.win_reg,1,52,"C Z S O A P D I T "); +} + + +static void DrawBars(void) { + if (has_colors()) { + attrset(COLOR_PAIR(PAIR_BLACK_BLUE)); + } + /* Show the Register bar */ + mvaddstr(dbg.win_reg->_begy-1,0,"---[F1](Register Overview)---"); + /* Show the Data Overview bar perhaps with more special stuff in the end */ + mvaddstr(dbg.win_data->_begy-1,0,"---[F2](Data Overview)---"); + /* Show the Code Overview perhaps with special stuff in bar too */ + mvaddstr(dbg.win_code->_begy-1,0,"---[F3](Code Overview)---"); + /* Show the Output OverView */ + mvaddstr(dbg.win_out->_begy-1,0,"---[F4](OutPut/Input)---"); + attrset(0); +} + + + +static void MakeSubWindows(void) { + /* The Std output win should go in bottem */ + /* Make all the subwindows */ + int outy=1; + /* The Register window */ + dbg.win_reg=subwin(dbg.win_main,4,dbg.win_main->_maxx,outy,0); + outy+=5; + /* The Data Window */ + dbg.win_data=subwin(dbg.win_main,10,dbg.win_main->_maxx,outy,0); + outy+=11; + /* The Code Window */ + dbg.win_code=subwin(dbg.win_main,10,dbg.win_main->_maxx,outy,0); + outy+=11; + /* The output Window */ + dbg.win_out=subwin(dbg.win_main,dbg.win_main->_maxy-outy-1,dbg.win_main->_maxx,outy,0); + dbg.input_y=dbg.win_main->_maxy-1; + scrollok(dbg.win_out,TRUE); + DrawBars(); + Draw_RegisterLayout(); + refresh(); +} + +static void MakePairs(void) { + init_pair(PAIR_BLACK_BLUE, COLOR_BLACK, COLOR_CYAN); + init_pair(PAIR_BYELLOW_BLACK, COLOR_YELLOW /*| FOREGROUND_INTENSITY */, COLOR_BLACK); +} + + +void DBGUI_StartUp(void) { + /* Start the main window */ + dbg.win_main=initscr(); + cbreak(); /* take input chars one at a time, no wait for \n */ + noecho(); /* don't echo input */ + nodelay(dbg.win_main,true); + keypad(dbg.win_main,true); + cycle_count=0; + MakePairs(); + MakeSubWindows(); + + +} + +#endif diff --git a/src/debug/debug_inc.h b/src/debug/debug_inc.h index 7530fde..f7276a7 100644 --- a/src/debug/debug_inc.h +++ b/src/debug/debug_inc.h @@ -1,61 +1,52 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* Local Debug Function */ - -/* $Id: debug_inc.h,v 1.11 2007/01/08 19:45:39 qbix79 Exp $ */ - -#include -#include "mem.h" - -#define PAIR_BLACK_BLUE 1 -#define PAIR_BYELLOW_BLACK 2 -#define PAIR_GREEN_BLACK 3 -#define PAIR_BLACK_GREY 4 -#define PAIR_GREY_RED 5 - - -void DBGUI_StartUp(void); - -struct DBGBlock { - WINDOW * win_main; /* The Main Window */ - WINDOW * win_reg; /* Register Window */ - WINDOW * win_data; /* Data Output window */ - WINDOW * win_code; /* Disassembly/Debug point Window */ - WINDOW * win_var; /* Variable Window */ - WINDOW * win_out; /* Text Output Window */ - Bit32u active_win; /* Current active window */ - Bit32u input_y; - Bit32u global_mask; /* Current msgmask */ -}; - - -struct DASMLine { - Bit32u pc; - char dasm[80]; - PhysPt ea; - Bit16u easeg; - Bit32u eaoff; -}; - -extern DBGBlock dbg; - -/* Local Debug Stuff */ -Bitu DasmI386(char* buffer, PhysPt pc, Bitu cur_ip, bool bit32); -int DasmLastOperandSize(void); - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* Local Debug Function */ +#include +#include "mem.h" + +#define PAIR_BLACK_BLUE 1 +#define PAIR_BYELLOW_BLACK 2 + + +void DBGUI_StartUp(void); + +struct DBGBlock { + WINDOW * win_main; /* The Main Window */ + WINDOW * win_reg; /* Register Window */ + WINDOW * win_data; /* Data Output window */ + WINDOW * win_code; /* Disassembly/Debug point Window */ + WINDOW * win_out; /* Text Output Window */ + Bit32u active_win; /* Current active window */ + Bit32u input_y; +}; + + +struct DASMLine { + Bit32u pc; + char dasm[80]; + PhysOff ea; + Bit16u easeg; + Bit32u eaoff; +}; + +extern DBGBlock dbg; + + +/* Local Debug Stuff */ +Bitu DasmI386(char* buffer, PhysOff pc, Bitu cur_ip, bool bit32); diff --git a/src/debug/debug_win32.cpp b/src/debug/debug_win32.cpp index ee58add..28f9471 100644 --- a/src/debug/debug_win32.cpp +++ b/src/debug/debug_win32.cpp @@ -1,75 +1,74 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef WIN32 - -#include -#include -#include - -/* - Have to remember where i ripped this code sometime ago. - -*/ -static void ResizeConsole( HANDLE hConsole, SHORT xSize, SHORT ySize ) { - CONSOLE_SCREEN_BUFFER_INFO csbi; // Hold Current Console Buffer Info - BOOL bSuccess; - SMALL_RECT srWindowRect; // Hold the New Console Size - COORD coordScreen; - - bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi ); - - // Get the Largest Size we can size the Console Window to - coordScreen = GetLargestConsoleWindowSize( hConsole ); - - // Define the New Console Window Size and Scroll Position - srWindowRect.Right = (SHORT)(min(xSize, coordScreen.X) - 1); - srWindowRect.Bottom = (SHORT)(min(ySize, coordScreen.Y) - 1); - srWindowRect.Left = srWindowRect.Top = (SHORT)0; - - // Define the New Console Buffer Size - coordScreen.X = xSize; - coordScreen.Y = ySize; - - // If the Current Buffer is Larger than what we want, Resize the - // Console Window First, then the Buffer - if( (DWORD)csbi.dwSize.X * csbi.dwSize.Y > (DWORD) xSize * ySize) - { - bSuccess = SetConsoleWindowInfo( hConsole, TRUE, &srWindowRect ); - bSuccess = SetConsoleScreenBufferSize( hConsole, coordScreen ); - } - - // If the Current Buffer is Smaller than what we want, Resize the - // Buffer First, then the Console Window - if( (DWORD)csbi.dwSize.X * csbi.dwSize.Y < (DWORD) xSize * ySize ) - { - bSuccess = SetConsoleScreenBufferSize( hConsole, coordScreen ); - bSuccess = SetConsoleWindowInfo( hConsole, TRUE, &srWindowRect ); - } - - // If the Current Buffer *is* the Size we want, Don't do anything! - return; - } - - -void WIN32_Console() { - AllocConsole(); - SetConsoleTitle("DOSBox Debugger"); - ResizeConsole(GetStdHandle(STD_OUTPUT_HANDLE),80,50); -} -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +/* + Have to remember where i ripped this code sometime ago. + +*/ +static void ResizeConsole( HANDLE hConsole, SHORT xSize, SHORT ySize ) { + CONSOLE_SCREEN_BUFFER_INFO csbi; // Hold Current Console Buffer Info + BOOL bSuccess; + SMALL_RECT srWindowRect; // Hold the New Console Size + COORD coordScreen; + + bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi ); + + // Get the Largest Size we can size the Console Window to + coordScreen = GetLargestConsoleWindowSize( hConsole ); + + // Define the New Console Window Size and Scroll Position + srWindowRect.Right = (SHORT)(min(xSize, coordScreen.X) - 1); + srWindowRect.Bottom = (SHORT)(min(ySize, coordScreen.Y) - 1); + srWindowRect.Left = srWindowRect.Top = (SHORT)0; + + // Define the New Console Buffer Size + coordScreen.X = xSize; + coordScreen.Y = ySize; + + // If the Current Buffer is Larger than what we want, Resize the + // Console Window First, then the Buffer + if( (DWORD)csbi.dwSize.X * csbi.dwSize.Y > (DWORD) xSize * ySize) + { + bSuccess = SetConsoleWindowInfo( hConsole, TRUE, &srWindowRect ); + bSuccess = SetConsoleScreenBufferSize( hConsole, coordScreen ); + } + + // If the Current Buffer is Smaller than what we want, Resize the + // Buffer First, then the Console Window + if( (DWORD)csbi.dwSize.X * csbi.dwSize.Y < (DWORD) xSize * ySize ) + { + bSuccess = SetConsoleScreenBufferSize( hConsole, coordScreen ); + bSuccess = SetConsoleWindowInfo( hConsole, TRUE, &srWindowRect ); + } + + // If the Current Buffer *is* the Size we want, Don't do anything! + return; + } + + +void WIN32_Console() { + ResizeConsole(GetStdHandle(STD_OUTPUT_HANDLE),80,50); + + +} + + diff --git a/src/debug/disasm_tables.h b/src/debug/disasm_tables.h index 5361236..0ed79e8 100644 --- a/src/debug/disasm_tables.h +++ b/src/debug/disasm_tables.h @@ -1,191 +1,191 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -char * RegTable_16[8]= {"ax","cx","dx","bx","sp","bp","si","di"}; -char * RegTable_8[8]= {"al","cl","dl","bl","ah","ch","dh","bh"}; -char * SegTable[8]= {"es","cs","ss","ds","fs","gs","iseg","iseg"}; - - -#define MAX_INFO 3 - -enum { - Eb,Ev,Ew,Ep, - Gb,Gv, - Rb,Rw,Rv, - Ob,Ov, - Sw, - Mp, - Ib,Ibs,Iw,Iv,Ap, - Jb,Jv, - Bd,Bw, - XBnd,Xlea, -/* specials */ - b2,p_es,p_ss,p_cs,p_ds,p_fs,p_gs,p_size,p_addr,p_rep, - s_ax,s_cx,s_dx,s_bx,s_sp,s_bp,s_si,s_di, - s_al,s_cl,s_dl,s_bl,s_ah,s_ch,s_dh,s_bh, - s_1, - Cj, - G1,G2,G3b,G3v,G4,G5, - no=0xff -}; - -enum { - s_jo, s_jno, s_jc, s_jnc, s_je, s_jne, s_jbe, s_jnbe, - s_js, s_jns, s_jp, s_jnp, s_jl, s_jnl, s_jle, s_jnle -}; - - -struct Dentry { - char * start; - Bit8u info[MAX_INFO]; -}; - -static char * G1_Table[8]={"add ","or ","adc ","sbb ","and ","sub ","xor ","cmp "}; -static char * G2_Table[8]={"rol ","ror ","rcl ","rcr ","shl ","shr ","sal ","sar "}; - -static Dentry G3b_Table[8]={ - "test ",Eb,Ib,no, - "test ",Eb,Ib,no, - "not ",Eb,no,no, - "neg ",Eb,no,no, - "mul al,",Eb,no,no, - "imul al,",Eb,no,no, - "div ax,",Eb,no,no, - "idiv ax,",Eb,no,no -}; - -static Dentry G3v_Table[8]={ - "test ",Ev,Iv,no, - "test ",Ev,Iv,no, - "not ",Ev,no,no, - "neg ",Ev,no,no, - "mul ax,",Ev,no,no, - "imul ax,",Ev,no,no, - "div dx:ax,",Ev,no,no, - "idiv dx:ax,",Ev,no,no -}; - -static char * G4_Table[8]={ - "inc ", - "dec ", - "illegal", - "illegal", - "illegal", - "illegal", - "illegal", - "illegal" -}; - -static Dentry G5_Table[8]={ - "inc ",Ev,no,no, - "dec ",Ev,no,no, - "call ",Ev,no,no, - "call ",Ep,no,no, - "jmp ",Ev,no,no, - "jmp ",Ep,no,no, - "push ,",Ev,no,no, - "illegal",no,no,no -}; - - - -static Dentry DTable[256]={ -/* 0 */ - "add ",Eb,Gb,no, "add ",Ev,Gv,no, "add ",Gb,Eb,no, "add ",Gv,Ev,no, - "add ",s_al,Ib,no, "add ",s_ax,Iv,no, "push es",no,no,no, "pop es",no,no,no, - "or ",Eb,Gb,no, "or ",Ev,Gv,no, "or ",Gb,Eb,no, "or ",Gv,Ev,no, - "or ",s_al,Ib,no, "or ",s_ax,Iv,no, "push cs",no,no,no, "",b2,no,no, -/* 1 */ - "adc ",Eb,Gb,no, "adc ",Ev,Gv,no, "adc ",Gb,Eb,no, "adc ",Gv,Ev,no, - "adc ",s_al,Ib,no, "adc ",s_ax,Iv,no, "push ss",no,no,no, "pop ss",no,no,no, - "sbb ",Eb,Gb,no, "sbb ",Ev,Gv,no, "sbb ",Gb,Eb,no, "sbb ",Gv,Ev,no, - "sbb ",s_al,Ib,no, "sbb ",s_ax,Iv,no, "push ds",no,no,no, "pop ds",no,no,no, -/* 2 */ - "and ",Eb,Gb,no, "and ",Ev,Gv,no, "and ",Gb,Eb,no, "and ",Gv,Ev,no, - "and ",s_al,Ib,no, "and ",s_ax,Iv,no, "",p_es,no,no, "daa",no,no,no, - "sub ",Eb,Gb,no, "sub ",Ev,Gv,no, "sub ",Gb,Eb,no, "sub ",Gv,Ev,no, - "sub ",s_al,Ib,no, "sub ",s_ax,Iv,no, "",p_ss,no,no, "das",no,no,no, -/* 3 */ - "xor ",Eb,Gb,no, "xor ",Ev,Gv,no, "xor ",Gb,Eb,no, "xor ",Gv,Ev,no, - "xor ",s_al,Ib,no, "xor ",s_ax,Iv,no, "",p_ss,no,no, "aaa",no,no,no, - "cmp ",Eb,Gb,no, "cmp ",Ev,Gv,no, "cmp ",Gb,Eb,no, "cmp ",Gv,Ev,no, - "cmp ",s_al,Ib,no, "cmp ",s_ax,Iv,no, "",p_ds,no,no, "aas",no,no,no, -/* 4 */ - "inc ",s_ax,no,no, "inc ",s_cx,no,no, "inc ",s_dx,no,no, "inc ",s_bx,no,no, - "inc ",s_sp,no,no, "inc ",s_bp,no,no, "inc ",s_si,no,no, "inc ",s_di,no,no, - "dec ",s_ax,no,no, "dec ",s_cx,no,no, "dec ",s_dx,no,no, "dec ",s_bx,no,no, - "dec ",s_sp,no,no, "dec ",s_bp,no,no, "dec ",s_si,no,no, "dec ",s_di,no,no, -/* 5 */ - "push ",s_ax,no,no, "push ",s_cx,no,no, "push ",s_dx,no,no, "push ",s_bx,no,no, - "push ",s_sp,no,no, "push ",s_bp,no,no, "push ",s_si,no,no, "push ",s_di,no,no, - "pop ",s_ax,no,no, "pop ",s_cx,no,no, "pop ",s_dx,no,no, "pop ",s_bx,no,no, - "pop ",s_sp,no,no, "pop ",s_bp,no,no, "pop ",s_si,no,no, "pop ",s_di,no,no, -/* 6 */ - "pusha",Bd,no,no, "popa",Bd,no,no, "bound",XBnd,no,no, "arpl",Ew,Rw,no, - "",p_fs,no,no, "",p_gs,no,no, "",p_size,no,no, "",p_addr,no,no, - "push ",Iv,no,no, "imul ",Gv,Ev,Iv, "push ",Ibs,no,no, "imul ",Gv,Ev,Ib, - "insb",no,no,no, "ins",Bw,no,no, "oustb",no,no,no, "outs",Bw,no,no, -/* 7 */ - "jo ",Cj,s_jo,no, "jno ",Cj,s_jno,no, "jc ",Cj,s_jc,no, "jnc ",Cj,s_jnc,no, - "je ",Cj,s_je,no, "jne ",Cj,s_jne,no, "jbe ",Cj,s_jbe,no, "jnbe ",Cj,s_jnbe,no, - "js ",Cj,s_js,no, "jns ",Cj,s_jns,no, "jp ",Cj,s_jp,no, "jnp ",Cj,s_jnp,no, - "jl ",Cj,s_jl,no, "jnl ",Cj,s_jnl,no, "jle ",Cj,s_jle,no, "jnle ",Cj,s_jnle,no, -/* 8 */ - "",G1,Eb,Ib, "",G1,Ev,Iv, "",G1,Eb,Ib, "",G1,Ev,Ibs, - "test ",Eb,Gb,no, "test ",Ev,Gv,no, "xchg ",Eb,Gb,no, "xchg ",Ev,Gv,no, - "mov ",Eb,Gb,no, "mov ",Ev,Gv,no, "mov ",Gb,Eb,no, "mov ",Gv,Ev,no, - "mov ",Ew,Sw,no, "lea ",Gv,Xlea,no, "mov ",Sw,Ew,no, "pop ",Ev,no,no, -/* 9 */ - "nop",no,no,no, "xchg ",s_ax,s_cx,no,"xchg ",s_ax,s_dx,no,"xchg ",s_ax,s_bx,no, - "xchg ",s_ax,s_sp,no,"xchg ",s_ax,s_bp,no,"xchg ",s_ax,s_si,no,"xchg ",s_ax,s_di,no, - "cbw",no,no,no, "cwd",no,no,no, "call ",Ap,no,no, "fwait",no,no,no, - "pushf",Bd,no,no, "popf",Bd,no,no, "sahf",no,no,no, "lahf",no,no,no, -/* a */ - "mov ",s_al,Ob,no, "mov ",s_ax,Ov,no, "mov ",Ob,s_al,no, "mov ",Ov,s_ax,no, - "movsb",no,no,no, "movs",Bw,no,no, "cmpsb",no,no,no, "cmps",Bw,no,no, - "test ",s_al,Ib,no, "test ",s_ax,Iv,no, "stosb",no,no,no, "stos",Bw,no,no, - "lodsb",no,no,no, "lods",Bw,no,no, "scasb",no,no,no, "scas",Bw,no,no, -/* b */ - "mov ",s_al,Ib,no, "mov ",s_cl,Ib,no, "mov ",s_dl,Ib,no, "mov ",s_bl,Ib,no, - "mov ",s_ah,Ib,no, "mov ",s_ch,Ib,no, "mov ",s_dh,Ib,no, "mov ",s_bh,Ib,no, - "mov ",s_ax,Iv,no, "mov ",s_cx,Iv,no, "mov ",s_dx,Iv,no, "mov ",s_bx,Iv,no, - "mov ",s_sp,Iv,no, "mov ",s_bp,Iv,no, "mov ",s_si,Iv,no, "mov ",s_di,Iv,no, -/* c */ - "",G2,Eb,Ib, "",G2,Ev,Ib, "ret ",Iw,no,no, "ret",no,no,no, - "les ",Gv,Mp,no, "lds ",Gv,Mp,no, "mov ",Eb,Ib,no, "mov ",Ev,Iv,no, - "enter ",Iw,Ib,no, "leave",no,no,no, "retf ",Iw,no,no, "retf",no,no,no, - "int 03",no,no,no, "int ",Ib,no,no, "into",no,no,no, "iret",Bd,no,no, -/* d */ - "",G2,Eb,s_1, "",G2,Ev,s_1, "",G2,Eb,s_cl, "",G2,Ev,s_cl, - "aam",no,no,no, "aad",no,no,no, "setalc",no,no,no, "xlat",no,no,no, - "esc 0",Ib,no,no, "esc 1",Ib,no,no, "esc 2",Ib,no,no, "esc 3",Ib,no,no, - "esc 4",Ib,no,no, "esc 5",Ib,no,no, "esc 6",Ib,no,no, "esc 7",Ib,no,no, -/* e */ - "loopne ",Jb,no,no, "loope ",Jb,no,no, "loop ",Jb,no,no, "jcxz ",Jb,no,no, - "in ",s_al,Ib,no, "in ",s_ax,Ib,no, "out ",Ib,s_al,no, "out ",Ib,s_ax,no, - "call ",Jv,no,no, "jmp ",Jv,no,no, "jmp",Ap,no,no, "jmp ",Jb,no,no, - "in ",s_al,s_dx,no, "in ",s_ax,s_dx,no, "out ",s_dx,s_al,no,"out ",s_dx,s_ax,no, -/* f */ - "lock",no,no,no, "cb ",Iw,no,no, "repne ",p_rep,no,no,"repe ",p_rep,no,no, - "hlt",no,no,no, "cmc",no,no,no, "",G3b,no,no, "",G3v,no,no, - "clc",no,no,no, "stc",no,no,no, "cli",no,no,no, "sti",no,no,no, - "cld",no,no,no, "std",no,no,no, "",G4,Eb,no, "",G5,no,no, -}; - - - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +char * RegTable_16[8]= {"ax","cx","dx","bx","sp","bp","si","di"}; +char * RegTable_8[8]= {"al","cl","dl","bl","ah","ch","dh","bh"}; +char * SegTable[8]= {"es","cs","ss","ds","fs","gs","iseg","iseg"}; + + +#define MAX_INFO 3 + +enum { + Eb,Ev,Ew,Ep, + Gb,Gv, + Rb,Rw,Rv, + Ob,Ov, + Sw, + Mp, + Ib,Ibs,Iw,Iv,Ap, + Jb,Jv, + Bd,Bw, + XBnd,Xlea, +/* specials */ + b2,p_es,p_ss,p_cs,p_ds,p_fs,p_gs,p_size,p_addr,p_rep, + s_ax,s_cx,s_dx,s_bx,s_sp,s_bp,s_si,s_di, + s_al,s_cl,s_dl,s_bl,s_ah,s_ch,s_dh,s_bh, + s_1, + Cj, + G1,G2,G3b,G3v,G4,G5, + no=0xff +}; + +enum { + s_jo, s_jno, s_jc, s_jnc, s_je, s_jne, s_jbe, s_jnbe, + s_js, s_jns, s_jp, s_jnp, s_jl, s_jnl, s_jle, s_jnle +}; + + +struct Dentry { + char * start; + Bit8u info[MAX_INFO]; +}; + +static char * G1_Table[8]={"add ","or ","adc ","sbb ","and ","sub ","xor ","cmp "}; +static char * G2_Table[8]={"rol ","ror ","rcl ","rcr ","shl ","shr ","sal ","sar "}; + +static Dentry G3b_Table[8]={ + "test ",Eb,Ib,no, + "test ",Eb,Ib,no, + "not ",Eb,no,no, + "neg ",Eb,no,no, + "mul al,",Eb,no,no, + "imul al,",Eb,no,no, + "div ax,",Eb,no,no, + "idiv ax,",Eb,no,no +}; + +static Dentry G3v_Table[8]={ + "test ",Ev,Iv,no, + "test ",Ev,Iv,no, + "not ",Ev,no,no, + "neg ",Ev,no,no, + "mul ax,",Ev,no,no, + "imul ax,",Ev,no,no, + "div dx:ax,",Ev,no,no, + "idiv dx:ax,",Ev,no,no +}; + +static char * G4_Table[8]={ + "inc ", + "dec ", + "illegal", + "illegal", + "illegal", + "illegal", + "illegal", + "illegal" +}; + +static Dentry G5_Table[8]={ + "inc ",Ev,no,no, + "dec ",Ev,no,no, + "call ",Ev,no,no, + "call ",Ep,no,no, + "jmp ",Ev,no,no, + "jmp ",Ep,no,no, + "push ,",Ev,no,no, + "illegal",no,no,no +}; + + + +static Dentry DTable[256]={ +/* 0 */ + "add ",Eb,Gb,no, "add ",Ev,Gv,no, "add ",Gb,Eb,no, "add ",Gv,Ev,no, + "add ",s_al,Ib,no, "add ",s_ax,Iv,no, "push es",no,no,no, "pop es",no,no,no, + "or ",Eb,Gb,no, "or ",Ev,Gv,no, "or ",Gb,Eb,no, "or ",Gv,Ev,no, + "or ",s_al,Ib,no, "or ",s_ax,Iv,no, "push cs",no,no,no, "",b2,no,no, +/* 1 */ + "adc ",Eb,Gb,no, "adc ",Ev,Gv,no, "adc ",Gb,Eb,no, "adc ",Gv,Ev,no, + "adc ",s_al,Ib,no, "adc ",s_ax,Iv,no, "push ss",no,no,no, "pop ss",no,no,no, + "sbb ",Eb,Gb,no, "sbb ",Ev,Gv,no, "sbb ",Gb,Eb,no, "sbb ",Gv,Ev,no, + "sbb ",s_al,Ib,no, "sbb ",s_ax,Iv,no, "push ds",no,no,no, "pop ds",no,no,no, +/* 2 */ + "and ",Eb,Gb,no, "and ",Ev,Gv,no, "and ",Gb,Eb,no, "and ",Gv,Ev,no, + "and ",s_al,Ib,no, "and ",s_ax,Iv,no, "",p_es,no,no, "daa",no,no,no, + "sub ",Eb,Gb,no, "sub ",Ev,Gv,no, "sub ",Gb,Eb,no, "sub ",Gv,Ev,no, + "sub ",s_al,Ib,no, "sub ",s_ax,Iv,no, "",p_ss,no,no, "das",no,no,no, +/* 3 */ + "xor ",Eb,Gb,no, "xor ",Ev,Gv,no, "xor ",Gb,Eb,no, "xor ",Gv,Ev,no, + "xor ",s_al,Ib,no, "xor ",s_ax,Iv,no, "",p_ss,no,no, "aaa",no,no,no, + "cmp ",Eb,Gb,no, "cmp ",Ev,Gv,no, "cmp ",Gb,Eb,no, "cmp ",Gv,Ev,no, + "cmp ",s_al,Ib,no, "cmp ",s_ax,Iv,no, "",p_ds,no,no, "aas",no,no,no, +/* 4 */ + "inc ",s_ax,no,no, "inc ",s_cx,no,no, "inc ",s_dx,no,no, "inc ",s_bx,no,no, + "inc ",s_sp,no,no, "inc ",s_bp,no,no, "inc ",s_si,no,no, "inc ",s_di,no,no, + "dec ",s_ax,no,no, "dec ",s_cx,no,no, "dec ",s_dx,no,no, "dec ",s_bx,no,no, + "dec ",s_sp,no,no, "dec ",s_bp,no,no, "dec ",s_si,no,no, "dec ",s_di,no,no, +/* 5 */ + "push ",s_ax,no,no, "push ",s_cx,no,no, "push ",s_dx,no,no, "push ",s_bx,no,no, + "push ",s_sp,no,no, "push ",s_bp,no,no, "push ",s_si,no,no, "push ",s_di,no,no, + "pop ",s_ax,no,no, "pop ",s_cx,no,no, "pop ",s_dx,no,no, "pop ",s_bx,no,no, + "pop ",s_sp,no,no, "pop ",s_bp,no,no, "pop ",s_si,no,no, "pop ",s_di,no,no, +/* 6 */ + "pusha",Bd,no,no, "popa",Bd,no,no, "bound",XBnd,no,no, "arpl",Ew,Rw,no, + "",p_fs,no,no, "",p_gs,no,no, "",p_size,no,no, "",p_addr,no,no, + "push ",Iv,no,no, "imul ",Gv,Ev,Iv, "push ",Ibs,no,no, "imul ",Gv,Ev,Ib, + "insb",no,no,no, "ins",Bw,no,no, "oustb",no,no,no, "outs",Bw,no,no, +/* 7 */ + "jo ",Cj,s_jo,no, "jno ",Cj,s_jno,no, "jc ",Cj,s_jc,no, "jnc ",Cj,s_jnc,no, + "je ",Cj,s_je,no, "jne ",Cj,s_jne,no, "jbe ",Cj,s_jbe,no, "jnbe ",Cj,s_jnbe,no, + "js ",Cj,s_js,no, "jns ",Cj,s_jns,no, "jp ",Cj,s_jp,no, "jnp ",Cj,s_jnp,no, + "jl ",Cj,s_jl,no, "jnl ",Cj,s_jnl,no, "jle ",Cj,s_jle,no, "jnle ",Cj,s_jnle,no, +/* 8 */ + "",G1,Eb,Ib, "",G1,Ev,Iv, "",G1,Eb,Ib, "",G1,Ev,Ibs, + "test ",Eb,Gb,no, "test ",Ev,Gv,no, "xchg ",Eb,Gb,no, "xchg ",Ev,Gv,no, + "mov ",Eb,Gb,no, "mov ",Ev,Gv,no, "mov ",Gb,Eb,no, "mov ",Gv,Ev,no, + "mov ",Ew,Sw,no, "lea ",Gv,Xlea,no, "mov ",Sw,Ew,no, "pop ",Ev,no,no, +/* 9 */ + "nop",no,no,no, "xchg ",s_ax,s_cx,no,"xchg ",s_ax,s_dx,no,"xchg ",s_ax,s_bx,no, + "xchg ",s_ax,s_sp,no,"xchg ",s_ax,s_bp,no,"xchg ",s_ax,s_si,no,"xchg ",s_ax,s_di,no, + "cbw",no,no,no, "cwd",no,no,no, "call ",Ap,no,no, "fwait",no,no,no, + "pushf",Bd,no,no, "popf",Bd,no,no, "sahf",no,no,no, "lahf",no,no,no, +/* a */ + "mov ",s_al,Ob,no, "mov ",s_ax,Ov,no, "mov ",Ob,s_al,no, "mov ",Ov,s_ax,no, + "movsb",no,no,no, "movs",Bw,no,no, "cmpsb",no,no,no, "cmps",Bw,no,no, + "test ",s_al,Ib,no, "test ",s_ax,Iv,no, "stosb",no,no,no, "stos",Bw,no,no, + "lodsb",no,no,no, "lods",Bw,no,no, "scasb",no,no,no, "scas",Bw,no,no, +/* b */ + "mov ",s_al,Ib,no, "mov ",s_cl,Ib,no, "mov ",s_dl,Ib,no, "mov ",s_bl,Ib,no, + "mov ",s_ah,Ib,no, "mov ",s_ch,Ib,no, "mov ",s_dh,Ib,no, "mov ",s_bh,Ib,no, + "mov ",s_ax,Iv,no, "mov ",s_cx,Iv,no, "mov ",s_dx,Iv,no, "mov ",s_bx,Iv,no, + "mov ",s_sp,Iv,no, "mov ",s_bp,Iv,no, "mov ",s_si,Iv,no, "mov ",s_di,Iv,no, +/* c */ + "",G2,Eb,Ib, "",G2,Ev,Ib, "ret ",Iw,no,no, "ret",no,no,no, + "les ",Gv,Mp,no, "lds ",Gv,Mp,no, "mov ",Eb,Ib,no, "mov ",Ev,Iv,no, + "enter ",Iw,Ib,no, "leave",no,no,no, "retf ",Iw,no,no, "retf",no,no,no, + "int 03",no,no,no, "int ",Ib,no,no, "into",no,no,no, "iret",Bd,no,no, +/* d */ + "",G2,Eb,s_1, "",G2,Ev,s_1, "",G2,Eb,s_cl, "",G2,Ev,s_cl, + "aam",no,no,no, "aad",no,no,no, "setalc",no,no,no, "xlat",no,no,no, + "esc 0",Ib,no,no, "esc 1",Ib,no,no, "esc 2",Ib,no,no, "esc 3",Ib,no,no, + "esc 4",Ib,no,no, "esc 5",Ib,no,no, "esc 6",Ib,no,no, "esc 7",Ib,no,no, +/* e */ + "loopne ",Jb,no,no, "loope ",Jb,no,no, "loop ",Jb,no,no, "jcxz ",Jb,no,no, + "in ",s_al,Ib,no, "in ",s_ax,Ib,no, "out ",Ib,s_al,no, "out ",Ib,s_ax,no, + "call ",Jv,no,no, "jmp ",Jv,no,no, "jmp",Ap,no,no, "jmp ",Jb,no,no, + "in ",s_al,s_dx,no, "in ",s_ax,s_dx,no, "out ",s_dx,s_al,no,"out ",s_dx,s_ax,no, +/* f */ + "lock",no,no,no, "cb ",Iw,no,no, "repne ",p_rep,no,no,"repe ",p_rep,no,no, + "hlt",no,no,no, "cmc",no,no,no, "",G3b,no,no, "",G3v,no,no, + "clc",no,no,no, "stc",no,no,no, "cli",no,no,no, "sti",no,no,no, + "cld",no,no,no, "std",no,no,no, "",G4,Eb,no, "",G5,no,no, +}; + + + diff --git a/src/dos/Makefile.am b/src/dos/Makefile.am index 4bd56f3..1a41482 100644 --- a/src/dos/Makefile.am +++ b/src/dos/Makefile.am @@ -1,10 +1,7 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include - -noinst_LIBRARIES = libdos.a -EXTRA_DIST = scsidefs.h wnaspi32.h dos_codepages.h dos_keyboard_layout_data.h -libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \ - dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \ - drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \ - drive_iso.cpp dev_con.h dos_mscdex.cpp dos_keyboard_layout.cpp \ - cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp \ - cdrom_ioctl_os2.cpp +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libdos.a +libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \ + dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \ + drives.cpp drives.h drive_virtual.cpp drive_local.cpp \ + dev_con.h diff --git a/src/dos/Makefile.in b/src/dos/Makefile.in new file mode 100644 index 0000000..a1e3579 --- /dev/null +++ b/src/dos/Makefile.in @@ -0,0 +1,334 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libdos.a +libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \ + dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \ + drives.cpp drives.h drive_virtual.cpp drive_local.cpp \ + dev_con.h + +subdir = src/dos +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libdos_a_AR = $(AR) cru +libdos_a_LIBADD = +am_libdos_a_OBJECTS = dos.$(OBJEXT) dos_devices.$(OBJEXT) \ + dos_execute.$(OBJEXT) dos_files.$(OBJEXT) dos_ioctl.$(OBJEXT) \ + dos_memory.$(OBJEXT) dos_misc.$(OBJEXT) dos_classes.$(OBJEXT) \ + dos_programs.$(OBJEXT) dos_tables.$(OBJEXT) drives.$(OBJEXT) \ + drive_virtual.$(OBJEXT) drive_local.$(OBJEXT) +libdos_a_OBJECTS = $(am_libdos_a_OBJECTS) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dos.Po ./$(DEPDIR)/dos_classes.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/dos_devices.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/dos_execute.Po ./$(DEPDIR)/dos_files.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/dos_ioctl.Po ./$(DEPDIR)/dos_memory.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/dos_misc.Po ./$(DEPDIR)/dos_programs.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/dos_tables.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/drive_local.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/drive_virtual.Po ./$(DEPDIR)/drives.Po +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +CXXFLAGS = @CXXFLAGS@ +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libdos_a_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libdos_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/dos/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +AR = ar + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libdos.a: $(libdos_a_OBJECTS) $(libdos_a_DEPENDENCIES) + -rm -f libdos.a + $(libdos_a_AR) libdos.a $(libdos_a_OBJECTS) $(libdos_a_LIBADD) + $(RANLIB) libdos.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_classes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_devices.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_execute.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_files.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_ioctl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_memory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_misc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_programs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_tables.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_local.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_virtual.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drives.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `cygpath -w $<` +CXXDEPMODE = @CXXDEPMODE@ +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic tags uninstall uninstall-am \ + uninstall-info-am + +# 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/dos/cdrom.cpp b/src/dos/cdrom.cpp deleted file mode 100644 index 0b219ae..0000000 --- a/src/dos/cdrom.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: cdrom.cpp,v 1.27 2009/04/26 18:24:36 qbix79 Exp $ */ - -// ****************************************************** -// SDL CDROM -// ****************************************************** - -#include -#include -#include - -#include "dosbox.h" -#include "SDL.h" -#include "support.h" -#include "cdrom.h" - -CDROM_Interface_SDL::CDROM_Interface_SDL(void) { - driveID = 0; - oldLeadOut = 0; - cd = 0; -} - -CDROM_Interface_SDL::~CDROM_Interface_SDL(void) { - StopAudio(); - SDL_CDClose(cd); - cd = 0; -} - -bool CDROM_Interface_SDL::SetDevice(char* path, int forceCD) { - char buffer[512]; - strcpy(buffer,path); - upcase(buffer); - - int num = SDL_CDNumDrives(); - if ((forceCD>=0) && (forceCDnumtracks; - FRAMES_TO_MSF(cd->track[cd->numtracks].offset,&leadOut.min,&leadOut.sec,&leadOut.fr); - } - return CD_INDRIVE(SDL_CDStatus(cd)); -} - -bool CDROM_Interface_SDL::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) { - if (CD_INDRIVE(SDL_CDStatus(cd))) { - FRAMES_TO_MSF(cd->track[track-1].offset,&start.min,&start.sec,&start.fr); - attr = cd->track[track-1].type<<4;//sdl uses 0 for audio and 4 for data. instead of 0x00 and 0x40 - } - return CD_INDRIVE(SDL_CDStatus(cd)); -} - -bool CDROM_Interface_SDL::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) { - if (CD_INDRIVE(SDL_CDStatus(cd))) { - track = cd->cur_track; - index = cd->cur_track; - attr = cd->track[track].type<<4; - FRAMES_TO_MSF(cd->cur_frame,&relPos.min,&relPos.sec,&relPos.fr); - FRAMES_TO_MSF(cd->cur_frame+cd->track[track].offset,&absPos.min,&absPos.sec,&absPos.fr); - } - return CD_INDRIVE(SDL_CDStatus(cd)); -} - -bool CDROM_Interface_SDL::GetAudioStatus(bool& playing, bool& pause){ - if (CD_INDRIVE(SDL_CDStatus(cd))) { - playing = (cd->status==CD_PLAYING); - pause = (cd->status==CD_PAUSED); - } - return CD_INDRIVE(SDL_CDStatus(cd)); -} - -bool CDROM_Interface_SDL::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) { - SDL_CDStatus(cd); - mediaPresent = (cd->status!=CD_TRAYEMPTY) && (cd->status!=CD_ERROR); - mediaChanged = (oldLeadOut!=cd->track[cd->numtracks].offset); - trayOpen = !mediaPresent; - oldLeadOut = cd->track[cd->numtracks].offset; - if (mediaChanged) SDL_CDStatus(cd); - return true; -} - -bool CDROM_Interface_SDL::PlayAudioSector(unsigned long start,unsigned long len) { - // Has to be there, otherwise wrong cd status report (dunno why, sdl bug ?) - SDL_CDClose(cd); - cd = SDL_CDOpen(driveID); - bool success = (SDL_CDPlay(cd,start+150,len)==0); - return success; -} - -bool CDROM_Interface_SDL::PauseAudio(bool resume) { - bool success; - if (resume) success = (SDL_CDResume(cd)==0); - else success = (SDL_CDPause (cd)==0); - return success; -} - -bool CDROM_Interface_SDL::StopAudio(void) { - // Has to be there, otherwise wrong cd status report (dunno why, sdl bug ?) - SDL_CDClose(cd); - cd = SDL_CDOpen(driveID); - bool success = (SDL_CDStop(cd)==0); - return success; -} - -bool CDROM_Interface_SDL::LoadUnloadMedia(bool unload) { - bool success = (SDL_CDEject(cd)==0); - return success; -} - -int CDROM_GetMountType(char* path, int forceCD) { -// 0 - physical CDROM -// 1 - Iso file -// 2 - subdirectory - // 1. Smells like a real cdrom - // if ((strlen(path)<=3) && (path[2]=='\\') && (strchr(path,'\\')==strrchr(path,'\\')) && (GetDriveType(path)==DRIVE_CDROM)) return 0; - - const char* cdName; - char buffer[512]; - strcpy(buffer,path); -#if defined (WIN32) || defined(OS2) - upcase(buffer); -#endif - - int num = SDL_CDNumDrives(); - // If cd drive is forced then check if its in range and return 0 - if ((forceCD>=0) && (forceCD1) return false; - start.min = start.fr = 0; - start.sec = 2; - attr = 0x60; // data / permitted - return true; -} - -bool CDROM_Interface_Fake :: GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos){ - attr = 0; - track = index = 1; - relPos.min = relPos.fr = 0; relPos.sec = 2; - absPos.min = absPos.fr = 0; absPos.sec = 2; - return true; -} - -bool CDROM_Interface_Fake :: GetAudioStatus(bool& playing, bool& pause) { - playing = pause = false; - return true; -} - -bool CDROM_Interface_Fake :: GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) { - mediaPresent = true; - mediaChanged = false; - trayOpen = false; - return true; -} - - diff --git a/src/dos/cdrom.h b/src/dos/cdrom.h deleted file mode 100644 index 50fa504..0000000 --- a/src/dos/cdrom.h +++ /dev/null @@ -1,364 +0,0 @@ - -#ifndef __CDROM_INTERFACE__ -#define __CDROM_INTERFACE__ - -#define MAX_ASPI_CDROM 5 - -#include -#include -#include -#include -#include -#include -#include "dosbox.h" -#include "mem.h" -#include "mixer.h" -#include "SDL.h" -#include "SDL_thread.h" - -#if defined(C_SDL_SOUND) -#include "SDL_sound.h" -#endif - -#define RAW_SECTOR_SIZE 2352 -#define COOKED_SECTOR_SIZE 2048 - -enum { CDROM_USE_SDL, CDROM_USE_ASPI, CDROM_USE_IOCTL_DIO, CDROM_USE_IOCTL_DX, CDROM_USE_IOCTL_MCI }; - -typedef struct SMSF { - unsigned char min; - unsigned char sec; - unsigned char fr; -} TMSF; - -extern int CDROM_GetMountType(char* path, int force); - -class CDROM_Interface -{ -public: -// CDROM_Interface (void); - virtual ~CDROM_Interface (void) {}; - - virtual bool SetDevice (char* path, int forceCD) = 0; - - virtual bool GetUPC (unsigned char& attr, char* upc) = 0; - - virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut) = 0; - virtual bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr) = 0; - virtual bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) = 0; - virtual bool GetAudioStatus (bool& playing, bool& pause) = 0; - virtual bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen) = 0; - - virtual bool PlayAudioSector (unsigned long start,unsigned long len) = 0; - virtual bool PauseAudio (bool resume) = 0; - virtual bool StopAudio (void) = 0; - - virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) = 0; - - virtual bool LoadUnloadMedia (bool unload) = 0; - - virtual void InitNewMedia (void) {}; -}; - -class CDROM_Interface_SDL : public CDROM_Interface -{ -public: - CDROM_Interface_SDL (void); - virtual ~CDROM_Interface_SDL(void); - - virtual bool SetDevice (char* path, int forceCD); - virtual bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; }; - virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); - virtual bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); - virtual bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); - virtual bool GetAudioStatus (bool& playing, bool& pause); - virtual bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); - virtual bool PlayAudioSector (unsigned long start,unsigned long len); - virtual bool PauseAudio (bool resume); - virtual bool StopAudio (void); - virtual bool ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return false; }; - virtual bool LoadUnloadMedia (bool unload); - -private: - bool Open (void); - void Close (void); - - SDL_CD* cd; - int driveID; - Uint32 oldLeadOut; -}; - -class CDROM_Interface_Fake : public CDROM_Interface -{ -public: - bool SetDevice (char* /*path*/, int /*forceCD*/) { return true; }; - bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; }; - bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); - bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); - bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); - bool GetAudioStatus (bool& playing, bool& pause); - bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); - bool PlayAudioSector (unsigned long /*start*/,unsigned long /*len*/) { return true; }; - bool PauseAudio (bool /*resume*/) { return true; }; - bool StopAudio (void) { return true; }; - bool ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return true; }; - bool LoadUnloadMedia (bool /*unload*/) { return true; }; -}; - -class CDROM_Interface_Image : public CDROM_Interface -{ -private: - class TrackFile { - public: - virtual bool read(Bit8u *buffer, int seek, int count) = 0; - virtual int getLength() = 0; - virtual ~TrackFile() { }; - }; - - class BinaryFile : public TrackFile { - public: - BinaryFile(const char *filename, bool &error); - ~BinaryFile(); - bool read(Bit8u *buffer, int seek, int count); - int getLength(); - private: - BinaryFile(); - std::ifstream *file; - }; - - #if defined(C_SDL_SOUND) - class AudioFile : public TrackFile { - public: - AudioFile(const char *filename, bool &error); - ~AudioFile(); - bool read(Bit8u *buffer, int seek, int count); - int getLength(); - private: - AudioFile(); - Sound_Sample *sample; - int lastCount; - int lastSeek; - }; - #endif - - struct Track { - int number; - int attr; - int start; - int length; - int skip; - int sectorSize; - bool mode2; - TrackFile *file; - }; - -public: - CDROM_Interface_Image (Bit8u subUnit); - virtual ~CDROM_Interface_Image (void); - void InitNewMedia (void); - bool SetDevice (char* path, int forceCD); - bool GetUPC (unsigned char& attr, char* upc); - bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); - bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); - bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); - bool GetAudioStatus (bool& playing, bool& pause); - bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); - bool PlayAudioSector (unsigned long start,unsigned long len); - bool PauseAudio (bool resume); - bool StopAudio (void); - bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num); - bool LoadUnloadMedia (bool unload); - bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector); - bool HasDataTrack (void); - -static CDROM_Interface_Image* images[26]; - -private: - // player -static void CDAudioCallBack(Bitu len); - int GetTrack(int sector); - -static struct imagePlayer { - CDROM_Interface_Image *cd; - MixerChannel *channel; - SDL_mutex *mutex; - Bit8u buffer[8192]; - int bufLen; - int currFrame; - int targetFrame; - bool isPlaying; - bool isPaused; - } player; - - void ClearTracks(); - bool LoadIsoFile(char *filename); - bool CanReadPVD(TrackFile *file, int sectorSize, bool mode2); - // cue sheet processing - bool LoadCueSheet(char *cuefile); - bool GetRealFileName(std::string& filename, std::string& pathname); - bool GetCueKeyword(std::string &keyword, std::istream &in); - bool GetCueFrame(int &frames, std::istream &in); - bool GetCueString(std::string &str, std::istream &in); - bool AddTrack(Track &curr, int &shift, int prestart, int &totalPregap, int currPregap); - -static int refCount; - std::vector tracks; -typedef std::vector::iterator track_it; - std::string mcn; - Bit8u subUnit; -}; - -#if defined (WIN32) /* Win 32 */ - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers - -#include -#include "wnaspi32.h" // Aspi stuff - -class CDROM_Interface_Aspi : public CDROM_Interface -{ -public: - CDROM_Interface_Aspi (void); - virtual ~CDROM_Interface_Aspi(void); - - bool SetDevice (char* path, int forceCD); - - bool GetUPC (unsigned char& attr, char* upc); - - bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); - bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); - bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); - bool GetAudioStatus (bool& playing, bool& pause); - bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); - - bool PlayAudioSector (unsigned long start,unsigned long len); - bool PauseAudio (bool resume); - bool StopAudio (void); - - bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num); - - bool LoadUnloadMedia (bool unload); - -private: - DWORD GetTOC (LPTOC toc); - HANDLE OpenIOCTLFile (char cLetter, BOOL bAsync); - void GetIOCTLAdapter (HANDLE hF,int * iDA,int * iDT,int * iDL); - bool ScanRegistryFindKey (HKEY& hKeyBase); - bool ScanRegistry (HKEY& hKeyBase); - BYTE GetHostAdapter (char* hardwareID); - bool GetVendor (BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, char* szBuffer); - - // ASPI stuff - BYTE haId; - BYTE target; - BYTE lun; - char letter; - - // Windows stuff - HINSTANCE hASPI; - HANDLE hEvent; // global event - DWORD (*pGetASPI32SupportInfo) (void); // ptrs to aspi funcs - DWORD (*pSendASPI32Command) (LPSRB); - TMSF oldLeadOut; -}; - -class CDROM_Interface_Ioctl : public CDROM_Interface -{ -public: - enum cdioctl_cdatype { CDIOCTL_CDA_DIO, CDIOCTL_CDA_MCI, CDIOCTL_CDA_DX }; - cdioctl_cdatype cdioctl_cda_selected; - - CDROM_Interface_Ioctl (cdioctl_cdatype ioctl_cda); - virtual ~CDROM_Interface_Ioctl(void); - - bool SetDevice (char* path, int forceCD); - - bool GetUPC (unsigned char& attr, char* upc); - - bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); - bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); - bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); - bool GetAudioStatus (bool& playing, bool& pause); - bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); - - bool PlayAudioSector (unsigned long start,unsigned long len); - bool PauseAudio (bool resume); - bool StopAudio (void); - - bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector); - bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num); - - bool LoadUnloadMedia (bool unload); - - void InitNewMedia (void) { Close(); Open(); }; -private: - - bool Open (void); - void Close (void); - - char pathname[32]; - HANDLE hIOCTL; - TMSF oldLeadOut; - - - /* track start/length data */ - bool track_start_valid; - int track_start_first,track_start_last; - int track_start[128]; - - bool GetAudioTracksAll (void); - - - /* mci audio cd interface */ - bool use_mciplay; - int mci_devid; - - bool mci_CDioctl (UINT msg, DWORD flags, void *arg); - bool mci_CDOpen (char drive); - bool mci_CDClose (void); - bool mci_CDPlay (int start, int length); - bool mci_CDPause (void); - bool mci_CDResume (void); - bool mci_CDStop (void); - int mci_CDStatus (void); - bool mci_CDPosition (int *position); - - - /* digital audio extraction cd interface */ - static void dx_CDAudioCallBack(Bitu len); - - bool use_dxplay; - static struct dxPlayer { - CDROM_Interface_Ioctl *cd; - MixerChannel *channel; - SDL_mutex *mutex; - Bit8u buffer[8192]; - int bufLen; - int currFrame; - int targetFrame; - bool isPlaying; - bool isPaused; - } player; - -}; - -#endif /* WIN 32 */ - -#if defined (LINUX) || defined(OS2) - -class CDROM_Interface_Ioctl : public CDROM_Interface_SDL -{ -public: - CDROM_Interface_Ioctl (void); - - bool SetDevice (char* path, int forceCD); - bool GetUPC (unsigned char& attr, char* upc); - bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num); - -private: - char device_name[512]; -}; - -#endif /* LINUX */ - -#endif /* __CDROM_INTERFACE__ */ diff --git a/src/dos/cdrom_aspi_win32.cpp b/src/dos/cdrom_aspi_win32.cpp deleted file mode 100644 index 9bc63f2..0000000 --- a/src/dos/cdrom_aspi_win32.cpp +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: cdrom_aspi_win32.cpp,v 1.20 2008/09/07 10:55:14 c2woody Exp $ */ - -#if defined (WIN32) - -#include - -#include "dosbox.h" -#include "cdrom.h" -#include "support.h" - -//Are actually system includes but leave for now -#include "wnaspi32.h" - -#if defined (_MSC_VER) -#include // Ioctl stuff -#include -#include // Ioctl stuff -#else -#include "ddk/ntddcdrm.h" // Ioctl stuff -#include "ddk/ntddscsi.h" -#endif - -#include "scsidefs.h" - -// always use a buffer of the maximum struct size (like the union of all 'SRB_*' struct types) -// Thanx SaPu -typedef union { - SRB_HAInquiry hainquiry; - SRB_GDEVBlock gdevblock; - SRB_ExecSCSICmd execscsicmd; - SRB_Abort abort; - SRB_BusDeviceReset busdevicereset; - SRB_GetDiskInfo getdiskinfo; - SRB_RescanPort rescanport; - SRB_GetSetTimeouts getsettimeouts; -} ASPI_SRB; - -// ***************************************************************** -// Windows ASPI functions (should work for all WIN with ASPI layer) -// ***************************************************************** - -CDROM_Interface_Aspi::CDROM_Interface_Aspi(void) -{ - hASPI = NULL; - hEvent = NULL; - pGetASPI32SupportInfo = NULL; - pSendASPI32Command = NULL; - memset(&oldLeadOut,0,sizeof(oldLeadOut)); -}; - -CDROM_Interface_Aspi::~CDROM_Interface_Aspi(void) -{ - // Stop Audio - StopAudio(); - - pGetASPI32SupportInfo = NULL; // clear funcs - pSendASPI32Command = NULL; - - if (hASPI) { // free aspi - FreeLibrary(hASPI); - hASPI=NULL; - } -}; - -bool GetRegistryValue(HKEY& hKey,char* valueName, char* buffer, ULONG bufferSize) -// hKey has to be open -{ - // Read subkey - ULONG valType; - ULONG result; - result = RegQueryValueEx(hKey,valueName,NULL,&valType,(unsigned char*)&buffer[0],&bufferSize); - return (result == ERROR_SUCCESS); -}; - -BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID) -{ - ASPI_SRB sh; - ASPI_SRB sd; - DWORD d = pGetASPI32SupportInfo(); - int cnt = LOBYTE(LOWORD(d)); - int i,j,k,max; - - for(i=0; i4)) { - if (GetDriveType(path)==DRIVE_CDROM) { - // WIN XP/NT/2000 - int iDA,iDT,iDL; - letter = path[0]; - HANDLE hF = OpenIOCTLFile(letter,FALSE); - GetIOCTLAdapter(hF,&iDA,&iDT,&iDL); - CloseHandle(hF); - // Set SCSI IDs - haId = iDA; - target = iDT; - lun = iDL; - return true; - } - } else { - // win 95/98/ME have to scan the registry... - // lets hope the layout is always the same... i dunno... - char key[2048]; - HKEY hKeyBase; - bool found = false; - strcpy(key,"ENUM\\SCSI"); - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,key,0,KEY_READ,&hKeyBase)==ERROR_SUCCESS) { - found = ScanRegistry(hKeyBase); - }; - RegCloseKey(hKeyBase); - return found; - } - return false; -}; - -bool CDROM_Interface_Aspi::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut) -{ - TOC toc; - if (GetTOC((LPTOC)&toc) == SS_COMP) { - stTrack = toc.cFirstTrack; - endTrack = toc.cLastTrack; - leadOut.min = (unsigned char)(toc.tracks[endTrack].lAddr >> 8) &0xFF; - leadOut.sec = (unsigned char)(toc.tracks[endTrack].lAddr >> 16) &0xFF; - leadOut.fr = (unsigned char)(toc.tracks[endTrack].lAddr >> 24) &0xFF; - return true; - } - return false; -}; - -bool CDROM_Interface_Aspi::GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr) -{ - TOC toc; - if (GetTOC((LPTOC)&toc) == SS_COMP) { - start.min = (unsigned char)(toc.tracks[track-1].lAddr >> 8) &0xFF; - start.sec = (unsigned char)(toc.tracks[track-1].lAddr >> 16) &0xFF; - start.fr = (unsigned char)(toc.tracks[track-1].lAddr >> 24) &0xFF; - attr = (toc.tracks[track-1].cAdrCtrl << 4) & 0xEF; - return true; - }; - return false; -}; - -HANDLE CDROM_Interface_Aspi::OpenIOCTLFile(char cLetter,BOOL bAsync) -{ - HANDLE hF; - char szFName[16]; - OSVERSIONINFO ov; - DWORD dwFlags; - DWORD dwIOCTLAttr; -// if(bAsync) dwIOCTLAttr=FILE_FLAG_OVERLAPPED; -// else - dwIOCTLAttr=0; - - memset(&ov,0,sizeof(OSVERSIONINFO)); - ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); - GetVersionEx(&ov); - - if ((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion>4)) - dwFlags = GENERIC_READ|GENERIC_WRITE; // add gen write on W2k/XP - else - dwFlags = GENERIC_READ; - - wsprintf(szFName, "\\\\.\\%c:",cLetter); - - hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // open drive - NULL,OPEN_EXISTING,dwIOCTLAttr,NULL); - - if (hF==INVALID_HANDLE_VALUE) { - dwFlags^=GENERIC_WRITE; // mmm... no success - hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // -> open drive again - NULL,OPEN_EXISTING,dwIOCTLAttr,NULL); - if (hF==INVALID_HANDLE_VALUE) return NULL; - } - return hF; -} - -void CDROM_Interface_Aspi::GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * iDL) -{ - char szBuf[1024]; - PSCSI_ADDRESS pSA; - DWORD dwRet; - - *iDA=*iDT=*iDL=-1; - if(hF==NULL) return; - - memset(szBuf,0,1024); - - pSA=(PSCSI_ADDRESS)szBuf; - pSA->Length=sizeof(SCSI_ADDRESS); - - if(!DeviceIoControl(hF,IOCTL_SCSI_GET_ADDRESS,NULL, - 0,pSA,sizeof(SCSI_ADDRESS), - &dwRet,NULL)) - return; - - *iDA = pSA->PortNumber; - *iDT = pSA->TargetId; - *iDL = pSA->Lun; -} - -DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc) -{ -// SRB_ExecSCSICmd s; - ASPI_SRB s; - DWORD dwStatus; - - hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - - memset(&s,0,sizeof(s)); - - s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.execscsicmd.SRB_HaId = haId; - s.execscsicmd.SRB_Target = target; - s.execscsicmd.SRB_Lun = lun; - s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.execscsicmd.SRB_BufLen = sizeof(*toc); - s.execscsicmd.SRB_BufPointer = (BYTE FAR *)toc; - s.execscsicmd.SRB_SenseLen = SENSE_LEN; - s.execscsicmd.SRB_CDBLen = 0x0A; - s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - s.execscsicmd.CDBByte[0] = SCSI_READ_TOC; - s.execscsicmd.CDBByte[1] = 0x02; // 0x02 for MSF - s.execscsicmd.CDBByte[7] = 0x03; - s.execscsicmd.CDBByte[8] = 0x24; - - ResetEvent(hEvent); - dwStatus=pSendASPI32Command((LPSRB)&s); - - if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000); - - CloseHandle(hEvent); - - return (s.execscsicmd.SRB_Status==SS_COMP); -} - -bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len) -{ -// SRB_ExecSCSICmd s; - ASPI_SRB s; - DWORD dwStatus; - - hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - - memset(&s,0,sizeof(s)); - s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.execscsicmd.SRB_HaId = haId; - s.execscsicmd.SRB_Target = target; - s.execscsicmd.SRB_Lun = lun; - s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.execscsicmd.SRB_BufLen = 0; - s.execscsicmd.SRB_BufPointer = 0; - s.execscsicmd.SRB_SenseLen = SENSE_LEN; - s.execscsicmd.SRB_CDBLen = 12; - s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - - s.execscsicmd.CDBByte[0] = SCSI_PLAYAUD_12; - s.execscsicmd.CDBByte[1] = lun << 5; - s.execscsicmd.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF); - s.execscsicmd.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF); - s.execscsicmd.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF); - s.execscsicmd.CDBByte[5] = (unsigned char)((start & 0xFF)); - s.execscsicmd.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF); - s.execscsicmd.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF); - s.execscsicmd.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF); - s.execscsicmd.CDBByte[9] = (unsigned char)(len & 0xFF); - - ResetEvent(hEvent); - - dwStatus = pSendASPI32Command((LPSRB)&s); - - if(dwStatus==SS_PENDING) WaitForSingleObject(hEvent,10000); - - CloseHandle(hEvent); - - return s.execscsicmd.SRB_Status==SS_COMP; -} - -bool CDROM_Interface_Aspi::StopAudio(void) -{ - return PauseAudio(false); -}; - -bool CDROM_Interface_Aspi::PauseAudio(bool resume) -{ - //SRB_ExecSCSICmd s; - ASPI_SRB s; - DWORD dwStatus; - - hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - - memset(&s,0,sizeof(s)); - - s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.execscsicmd.SRB_HaId = haId; - s.execscsicmd.SRB_Target = target; - s.execscsicmd.SRB_Lun = lun; - s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.execscsicmd.SRB_BufLen = 0x00; - s.execscsicmd.SRB_SenseLen = SENSE_LEN; - s.execscsicmd.SRB_CDBLen = 0x0A; - s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - s.execscsicmd.CDBByte[0] = 0x4B; - s.execscsicmd.CDBByte[8] = (unsigned char)resume; // Pause - - ResetEvent(hEvent); - dwStatus=pSendASPI32Command((LPSRB)&s); - - if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000); - - CloseHandle(hEvent); - - return (s.execscsicmd.SRB_Status==SS_COMP); -}; - -bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) -{ - SUB_Q_CURRENT_POSITION pos; -// SRB_ExecSCSICmd s; - ASPI_SRB s; - DWORD dwStatus; - - hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - - memset(&s,0,sizeof(s)); - - s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.execscsicmd.SRB_HaId = haId; - s.execscsicmd.SRB_Target = target; - s.execscsicmd.SRB_Lun = lun; - s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.execscsicmd.SRB_SenseLen = SENSE_LEN; - - s.execscsicmd.SRB_BufLen = sizeof(pos); - s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&pos; - s.execscsicmd.SRB_CDBLen = 10; - s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - - s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL; - s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf - s.execscsicmd.CDBByte[2] = 0x40; // subq - s.execscsicmd.CDBByte[3] = 0x01; // curr pos info - s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored) - s.execscsicmd.CDBByte[7] = 0; // alloc len - s.execscsicmd.CDBByte[8] = sizeof(pos); - - ResetEvent(hEvent); - - dwStatus = pSendASPI32Command((LPSRB)&s); - - if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF); - - CloseHandle(hEvent); - - if (s.execscsicmd.SRB_Status!=SS_COMP) return false; - - attr = (pos.Control<<4) &0xEF; - track = pos.TrackNumber; - index = pos.IndexNumber; - absPos.min = pos.AbsoluteAddress[1]; - absPos.sec = pos.AbsoluteAddress[2]; - absPos.fr = pos.AbsoluteAddress[3]; - relPos.min = pos.TrackRelativeAddress[1]; - relPos.sec = pos.TrackRelativeAddress[2]; - relPos.fr = pos.TrackRelativeAddress[3]; - - return true; -}; - -bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata) -{ - SUB_Q_MEDIA_CATALOG_NUMBER upc; - ASPI_SRB s; - //SRB_ExecSCSICmd s; - DWORD dwStatus; - - hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - - memset(&s,0,sizeof(s)); - - s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.execscsicmd.SRB_HaId = haId; - s.execscsicmd.SRB_Target = target; - s.execscsicmd.SRB_Lun = lun; - s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.execscsicmd.SRB_SenseLen = SENSE_LEN; - - s.execscsicmd.SRB_BufLen = sizeof(upc); - s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&upc; - s.execscsicmd.SRB_CDBLen = 10; - s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - - s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL; - s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf - s.execscsicmd.CDBByte[2] = 0x40; // subq - s.execscsicmd.CDBByte[3] = 0x02; // get upc - s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored) - s.execscsicmd.CDBByte[7] = 0; // alloc len - s.execscsicmd.CDBByte[8] = sizeof(upc); - - ResetEvent(hEvent); - - dwStatus = pSendASPI32Command((LPSRB)&s); - - if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF); - - CloseHandle(hEvent); - - if (s.execscsicmd.SRB_Status!=SS_COMP) return false; - -// attr = (upc.ADR<<4) | upc.Control; - attr = 0; - // Convert to mscdex format - for (int i=0; i<7; i++) upcdata[i] = upc.MediaCatalog[i]; - for (int i=0; i<7; i++) upcdata[i] = (upc.MediaCatalog[i*2] << 4) | (upc.MediaCatalog[i*2+1] & 0x0F); - - return true; -}; - -bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause) -{ - playing = pause = false; - - SUB_Q_HEADER sub; -// SRB_ExecSCSICmd s; - ASPI_SRB s; - DWORD dwStatus; - - hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - - memset(&s,0,sizeof(s)); - - s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.execscsicmd.SRB_HaId = haId; - s.execscsicmd.SRB_Target = target; - s.execscsicmd.SRB_Lun = lun; - s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.execscsicmd.SRB_SenseLen = SENSE_LEN; - - s.execscsicmd.SRB_BufLen = sizeof(sub); - s.execscsicmd.SRB_BufPointer = (BYTE FAR *)⊂ - s.execscsicmd.SRB_CDBLen = 10; - s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - - s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL; - s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf - s.execscsicmd.CDBByte[2] = 0x00; // no subq - s.execscsicmd.CDBByte[3] = 0x00; // dont care - s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored) - s.execscsicmd.CDBByte[7] = 0; // alloc len - s.execscsicmd.CDBByte[8] = sizeof(sub); - - ResetEvent(hEvent); - - dwStatus = pSendASPI32Command((LPSRB)&s); - - if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF); - - CloseHandle(hEvent); - - if (s.execscsicmd.SRB_Status!=SS_COMP) return false; - - playing = (sub.AudioStatus==0x11); - pause = (sub.AudioStatus==0x12); - - return true; -}; - -bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload) -{ - //SRB_ExecSCSICmd s; - ASPI_SRB s; - DWORD dwStatus; - - hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - - memset(&s,0,sizeof(s)); - - s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.execscsicmd.SRB_HaId = haId; - s.execscsicmd.SRB_Target = target; - s.execscsicmd.SRB_Lun = lun; - s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.execscsicmd.SRB_SenseLen = SENSE_LEN; - - s.execscsicmd.SRB_BufLen = 0; - s.execscsicmd.SRB_BufPointer = 0; - s.execscsicmd.SRB_CDBLen = 6; // 14; - s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - - s.execscsicmd.CDBByte[0] = SCSI_LOAD_UN; - s.execscsicmd.CDBByte[1] = (lun<<5)|1; // lun & immediate - s.execscsicmd.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media - - ResetEvent(hEvent); - - dwStatus = pSendASPI32Command((LPSRB)&s); - - if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF); - - CloseHandle(hEvent); - - if (s.execscsicmd.SRB_Status!=SS_COMP) return false; - - return true; -}; - -bool CDROM_Interface_Aspi::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) -{ - // Seems not possible to get this values using ioctl... - int track1,track2; - TMSF leadOut; - // If we can read, there's a media - mediaPresent = GetAudioTracks(track1, track2, leadOut), - trayOpen = !mediaPresent; - mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr); - // Save old values - oldLeadOut.min = leadOut.min; - oldLeadOut.sec = leadOut.sec; - oldLeadOut.fr = leadOut.fr; - // always success - return true; -}; - -bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) -{ - //SRB_ExecSCSICmd s; - ASPI_SRB s; - DWORD dwStatus; - - hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); - - memset(&s,0,sizeof(s)); - - Bitu buflen = raw?2352*num:2048*num; - Bit8u* bufdata = new Bit8u[buflen]; - - s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.execscsicmd.SRB_HaId = haId; - s.execscsicmd.SRB_Target = target; - s.execscsicmd.SRB_Lun = lun; - s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.execscsicmd.SRB_SenseLen = SENSE_LEN; - - s.execscsicmd.SRB_BufLen = buflen; - s.execscsicmd.SRB_BufPointer = (BYTE FAR*)bufdata; - s.execscsicmd.SRB_CDBLen = 12; - s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - - s.execscsicmd.CDBByte[0] = 0xBE; - s.execscsicmd.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF); - s.execscsicmd.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF); - s.execscsicmd.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF); - s.execscsicmd.CDBByte[5] = (unsigned char)((sector & 0xFF)); - s.execscsicmd.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF); - s.execscsicmd.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF); - s.execscsicmd.CDBByte[8] = (unsigned char) (num & 0xFF); - s.execscsicmd.CDBByte[9] = (raw?0xF0:0x10); - - ResetEvent(hEvent); - - dwStatus = pSendASPI32Command((LPSRB)&s); - - if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF); - - CloseHandle(hEvent); - - // Copy to PhysPt - MEM_BlockWrite(buffer,bufdata,buflen); - - delete[] bufdata; - - return (s.execscsicmd.SRB_Status==SS_COMP); -}; - -#endif diff --git a/src/dos/cdrom_image.cpp b/src/dos/cdrom_image.cpp deleted file mode 100644 index 794f708..0000000 --- a/src/dos/cdrom_image.cpp +++ /dev/null @@ -1,691 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: cdrom_image.cpp,v 1.24 2009/03/19 20:45:42 c2woody Exp $ */ - -#include -#include -#include -#include -#include -#include -#include //GCC 2.95 -#include -#include -#include -#include "cdrom.h" -#include "drives.h" -#include "support.h" -#include "setup.h" - -#if !defined(WIN32) -#include -#else -#include -#endif - -using namespace std; - -#define MAX_LINE_LENGTH 512 -#define MAX_FILENAME_LENGTH 256 - -CDROM_Interface_Image::BinaryFile::BinaryFile(const char *filename, bool &error) -{ - file = new ifstream(filename, ios::in | ios::binary); - error = (file == NULL) || (file->fail()); -} - -CDROM_Interface_Image::BinaryFile::~BinaryFile() -{ - delete file; -} - -bool CDROM_Interface_Image::BinaryFile::read(Bit8u *buffer, int seek, int count) -{ - file->seekg(seek, ios::beg); - file->read((char*)buffer, count); - return !(file->fail()); -} - -int CDROM_Interface_Image::BinaryFile::getLength() -{ - file->seekg(0, ios::end); - int length = (int)file->tellg(); - if (file->fail()) return -1; - return length; -} - -#if defined(C_SDL_SOUND) -CDROM_Interface_Image::AudioFile::AudioFile(const char *filename, bool &error) -{ - Sound_AudioInfo desired = {AUDIO_S16, 2, 44100}; - sample = Sound_NewSampleFromFile(filename, &desired, RAW_SECTOR_SIZE); - lastCount = RAW_SECTOR_SIZE; - lastSeek = 0; - error = (sample == NULL); -} - -CDROM_Interface_Image::AudioFile::~AudioFile() -{ - Sound_FreeSample(sample); -} - -bool CDROM_Interface_Image::AudioFile::read(Bit8u *buffer, int seek, int count) -{ - if (lastCount != count) { - int success = Sound_SetBufferSize(sample, count); - if (!success) return false; - } - if (lastSeek != (seek - count)) { - int success = Sound_Seek(sample, (int)((double)(seek) / 176.4f)); - if (!success) return false; - } - lastSeek = seek; - int bytes = Sound_Decode(sample); - if (bytes < count) { - memcpy(buffer, sample->buffer, bytes); - memset(buffer + bytes, 0, count - bytes); - } else { - memcpy(buffer, sample->buffer, count); - } - - return !(sample->flags & SOUND_SAMPLEFLAG_ERROR); -} - -int CDROM_Interface_Image::AudioFile::getLength() -{ - int time = 1; - int shift = 0; - if (!(sample->flags & SOUND_SAMPLEFLAG_CANSEEK)) return -1; - - while (true) { - int success = Sound_Seek(sample, (unsigned int)(shift + time)); - if (!success) { - if (time == 1) return lround((double)shift * 176.4f); - shift += time >> 1; - time = 1; - } else { - if (time > ((numeric_limits::max() - shift) / 2)) return -1; - time = time << 1; - } - } -} -#endif - -// initialize static members -int CDROM_Interface_Image::refCount = 0; -CDROM_Interface_Image* CDROM_Interface_Image::images[26]; -CDROM_Interface_Image::imagePlayer CDROM_Interface_Image::player = { - NULL, NULL, NULL, {0}, 0, 0, 0, false, false }; - - -CDROM_Interface_Image::CDROM_Interface_Image(Bit8u subUnit) -{ - images[subUnit] = this; - if (refCount == 0) { - player.mutex = SDL_CreateMutex(); - if (!player.channel) { - player.channel = MIXER_AddChannel(&CDAudioCallBack, 44100, "CDAUDIO"); - } - player.channel->Enable(true); - } - refCount++; -} - -CDROM_Interface_Image::~CDROM_Interface_Image() -{ - refCount--; - if (player.cd == this) player.cd = NULL; - ClearTracks(); - if (refCount == 0) { - SDL_DestroyMutex(player.mutex); - player.channel->Enable(false); - } -} - -void CDROM_Interface_Image::InitNewMedia() -{ -} - -bool CDROM_Interface_Image::SetDevice(char* path, int forceCD) -{ - if (LoadCueSheet(path)) return true; - if (LoadIsoFile(path)) return true; - - // print error message on dosbox console - char buf[MAX_LINE_LENGTH]; - snprintf(buf, MAX_LINE_LENGTH, "Could not load image file: %s\n", path); - Bit16u size = (Bit16u)strlen(buf); - DOS_WriteFile(STDOUT, (Bit8u*)buf, &size); - return false; -} - -bool CDROM_Interface_Image::GetUPC(unsigned char& attr, char* upc) -{ - attr = 0; - strcpy(upc, this->mcn.c_str()); - return true; -} - -bool CDROM_Interface_Image::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut) -{ - stTrack = 1; - end = (int)(tracks.size() - 1); - FRAMES_TO_MSF(tracks[tracks.size() - 1].start + 150, &leadOut.min, &leadOut.sec, &leadOut.fr); - return true; -} - -bool CDROM_Interface_Image::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) -{ - if (track < 1 || track > (int)tracks.size()) return false; - FRAMES_TO_MSF(tracks[track - 1].start + 150, &start.min, &start.sec, &start.fr); - attr = tracks[track - 1].attr; - return true; -} - -bool CDROM_Interface_Image::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) -{ - int cur_track = GetTrack(player.currFrame); - if (cur_track < 1) return false; - track = (unsigned char)cur_track; - attr = tracks[track - 1].attr; - index = 1; - FRAMES_TO_MSF(player.currFrame + 150, &absPos.min, &absPos.sec, &absPos.fr); - FRAMES_TO_MSF(player.currFrame - tracks[track - 1].start + 150, &relPos.min, &relPos.sec, &relPos.fr); - return true; -} - -bool CDROM_Interface_Image::GetAudioStatus(bool& playing, bool& pause) -{ - playing = player.isPlaying; - pause = player.isPaused; - return true; -} - -bool CDROM_Interface_Image::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) -{ - mediaPresent = true; - mediaChanged = false; - trayOpen = false; - return true; -} - -bool CDROM_Interface_Image::PlayAudioSector(unsigned long start,unsigned long len) -{ - SDL_mutexP(player.mutex); - player.cd = this; - player.currFrame = start; - player.targetFrame = start + len; - player.isPlaying = true; - player.isPaused = false; - SDL_mutexV(player.mutex); - return true; -} - -bool CDROM_Interface_Image::PauseAudio(bool resume) -{ - player.isPaused = !resume; - return true; -} - -bool CDROM_Interface_Image::StopAudio(void) -{ - player.isPlaying = false; - player.isPaused = false; - return true; -} - -bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) -{ - int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - Bitu buflen = num * sectorSize; - Bit8u* buf = new Bit8u[buflen]; - - bool success = true; //Gobliiins reads 0 sectors - for(unsigned long i = 0; i < num; i++) { - success = ReadSector(&buf[i * sectorSize], raw, sector + i); - if (!success) break; - } - - MEM_BlockWrite(buffer, buf, buflen); - delete[] buf; - - return success; -} - -bool CDROM_Interface_Image::LoadUnloadMedia(bool unload) -{ - return true; -} - -int CDROM_Interface_Image::GetTrack(int sector) -{ - vector::iterator i = tracks.begin(); - vector::iterator end = tracks.end() - 1; - - while(i != end) { - Track &curr = *i; - Track &next = *(i + 1); - if (curr.start <= sector && sector < next.start) return curr.number; - i++; - } - return -1; -} - -bool CDROM_Interface_Image::ReadSector(Bit8u *buffer, bool raw, unsigned long sector) -{ - int track = GetTrack(sector) - 1; - if (track < 0) return false; - - int seek = tracks[track].skip + (sector - tracks[track].start) * tracks[track].sectorSize; - int length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE); - if (tracks[track].sectorSize != RAW_SECTOR_SIZE && raw) return false; - if (tracks[track].sectorSize == RAW_SECTOR_SIZE && !tracks[track].mode2 && !raw) seek += 16; - if (tracks[track].mode2 && !raw) seek += 24; - - return tracks[track].file->read(buffer, seek, length); -} - -void CDROM_Interface_Image::CDAudioCallBack(Bitu len) -{ - len *= 4; // 16 bit, stereo - if (!len) return; - if (!player.isPlaying || player.isPaused) { - player.channel->AddSilence(); - return; - } - - SDL_mutexP(player.mutex); - while (player.bufLen < (Bits)len) { - bool success; - if (player.targetFrame > player.currFrame) - success = player.cd->ReadSector(&player.buffer[player.bufLen], true, player.currFrame); - else success = false; - - if (success) { - player.currFrame++; - player.bufLen += RAW_SECTOR_SIZE; - } else { - memset(&player.buffer[player.bufLen], 0, len - player.bufLen); - player.bufLen = len; - player.isPlaying = false; - } - } - SDL_mutexV(player.mutex); -#if defined(WORDS_BIGENDIAN) - player.channel->AddSamples_s16_nonnative(len/4,(Bit16s *)player.buffer); -#else - player.channel->AddSamples_s16(len/4,(Bit16s *)player.buffer); -#endif - memmove(player.buffer, &player.buffer[len], player.bufLen - len); - player.bufLen -= len; -} - -bool CDROM_Interface_Image::LoadIsoFile(char* filename) -{ - tracks.clear(); - - // data track - Track track = {0, 0, 0, 0, 0, 0, false, NULL}; - bool error; - track.file = new BinaryFile(filename, error); - if (error) { - delete track.file; - return false; - } - track.number = 1; - track.attr = 0x40;//data - - // try to detect iso type - if (CanReadPVD(track.file, COOKED_SECTOR_SIZE, false)) { - track.sectorSize = COOKED_SECTOR_SIZE; - track.mode2 = false; - } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, false)) { - track.sectorSize = RAW_SECTOR_SIZE; - track.mode2 = false; - } else if (CanReadPVD(track.file, 2336, true)) { - track.sectorSize = 2336; - track.mode2 = true; - } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, true)) { - track.sectorSize = RAW_SECTOR_SIZE; - track.mode2 = true; - } else return false; - - track.length = track.file->getLength() / track.sectorSize; - tracks.push_back(track); - - // leadout track - track.number = 2; - track.attr = 0; - track.start = track.length; - track.length = 0; - track.file = NULL; - tracks.push_back(track); - - return true; -} - -bool CDROM_Interface_Image::CanReadPVD(TrackFile *file, int sectorSize, bool mode2) -{ - Bit8u pvd[COOKED_SECTOR_SIZE]; - int seek = 16 * sectorSize; // first vd is located at sector 16 - if (sectorSize == RAW_SECTOR_SIZE && !mode2) seek += 16; - if (mode2) seek += 24; - file->read(pvd, seek, COOKED_SECTOR_SIZE); - // pvd[0] = descriptor type, pvd[1..5] = standard identifier, pvd[6] = iso version - return (pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1); -} - -#if defined(WIN32) -static string dirname(char * file) { - char * sep = strrchr(file, '\\'); - if (sep == NULL) - sep = strrchr(file, '/'); - if (sep == NULL) - return ""; - else { - int len = (int)(sep - file); - char tmp[MAX_FILENAME_LENGTH]; - safe_strncpy(tmp, file, len+1); - return tmp; - } -} -#endif - -bool CDROM_Interface_Image::LoadCueSheet(char *cuefile) -{ - Track track = {0, 0, 0, 0, 0, 0, false, NULL}; - tracks.clear(); - int shift = 0; - int currPregap = 0; - int totalPregap = 0; - int prestart = 0; - bool success; - bool canAddTrack = false; - char tmp[MAX_FILENAME_LENGTH]; // dirname can change its argument - safe_strncpy(tmp, cuefile, MAX_FILENAME_LENGTH); - string pathname(dirname(tmp)); - ifstream in; - in.open(cuefile, ios::in); - if (in.fail()) return false; - - while(!in.eof()) { - // get next line - char buf[MAX_LINE_LENGTH]; - in.getline(buf, MAX_LINE_LENGTH); - if (in.fail() && !in.eof()) return false; // probably a binary file - istringstream line(buf); - - string command; - GetCueKeyword(command, line); - - if (command == "TRACK") { - if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap); - else success = true; - - track.start = 0; - track.skip = 0; - currPregap = 0; - prestart = 0; - - line >> track.number; - string type; - GetCueKeyword(type, line); - - if (type == "AUDIO") { - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = 0; - track.mode2 = false; - } else if (type == "MODE1/2048") { - track.sectorSize = COOKED_SECTOR_SIZE; - track.attr = 0x40; - track.mode2 = false; - } else if (type == "MODE1/2352") { - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = 0x40; - track.mode2 = false; - } else if (type == "MODE2/2336") { - track.sectorSize = 2336; - track.attr = 0x40; - track.mode2 = true; - } else if (type == "MODE2/2352") { - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = 0x40; - track.mode2 = true; - } else success = false; - - canAddTrack = true; - } - else if (command == "INDEX") { - int index; - line >> index; - int frame; - success = GetCueFrame(frame, line); - - if (index == 1) track.start = frame; - else if (index == 0) prestart = frame; - // ignore other indices - } - else if (command == "FILE") { - if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap); - else success = true; - canAddTrack = false; - - string filename; - GetCueString(filename, line); - GetRealFileName(filename, pathname); - string type; - GetCueKeyword(type, line); - - track.file = NULL; - bool error = true; - if (type == "BINARY") { - track.file = new BinaryFile(filename.c_str(), error); - } -#if defined(C_SDL_SOUND) - else if (type == "WAVE" || type == "AIFF" || type == "MP3") { - track.file = new AudioFile(filename.c_str(), error); - } -#endif - if (error) { - delete track.file; - success = false; - } - } - else if (command == "PREGAP") success = GetCueFrame(currPregap, line); - else if (command == "CATALOG") success = GetCueString(mcn, line); - // ignored commands - else if (command == "CDTEXTFILE" || command == "FLAGS" || command == "ISRC" - || command == "PERFORMER" || command == "POSTGAP" || command == "REM" - || command == "SONGWRITER" || command == "TITLE" || command == "") success = true; - // failure - else success = false; - - if (!success) return false; - } - // add last track - if (!AddTrack(track, shift, prestart, totalPregap, currPregap)) return false; - - // add leadout track - track.number++; - track.attr = 0;//sync with load iso - track.start = 0; - track.length = 0; - track.file = NULL; - if(!AddTrack(track, shift, 0, totalPregap, 0)) return false; - - return true; -} - -bool CDROM_Interface_Image::AddTrack(Track &curr, int &shift, int prestart, int &totalPregap, int currPregap) -{ - // frames between index 0(prestart) and 1(curr.start) must be skipped - int skip; - if (prestart > 0) { - if (prestart > curr.start) return false; - skip = curr.start - prestart; - } else skip = 0; - - // first track (track number must be 1) - if (tracks.empty()) { - if (curr.number != 1) return false; - curr.skip = skip * curr.sectorSize; - curr.start += currPregap; - totalPregap = currPregap; - tracks.push_back(curr); - return true; - } - - Track &prev = *(tracks.end() - 1); - - // current track consumes data from the same file as the previous - if (prev.file == curr.file) { - curr.start += shift; - prev.length = curr.start + totalPregap - prev.start - skip; - curr.skip += prev.skip + prev.length * prev.sectorSize + skip * curr.sectorSize; - totalPregap += currPregap; - curr.start += totalPregap; - // current track uses a different file as the previous track - } else { - int tmp = prev.file->getLength() - prev.skip; - prev.length = tmp / prev.sectorSize; - if (tmp % prev.sectorSize != 0) prev.length++; // padding - - curr.start += prev.start + prev.length + currPregap; - curr.skip = skip * curr.sectorSize; - shift += prev.start + prev.length; - totalPregap = currPregap; - } - - // error checks - if (curr.number <= 1) return false; - if (prev.number + 1 != curr.number) return false; - if (curr.start < prev.start + prev.length) return false; - if (curr.length < 0) return false; - - tracks.push_back(curr); - return true; -} - -bool CDROM_Interface_Image::HasDataTrack(void) -{ - //Data track has attribute 0x40 - for(track_it it = tracks.begin(); it != tracks.end(); it++) { - if ((*it).attr == 0x40) return true; - } - return false; -} - - -bool CDROM_Interface_Image::GetRealFileName(string &filename, string &pathname) -{ - // check if file exists - struct stat test; - if (stat(filename.c_str(), &test) == 0) return true; - - // check if file with path relative to cue file exists - string tmpstr(pathname + "/" + filename); - if (stat(tmpstr.c_str(), &test) == 0) { - filename = tmpstr; - return true; - } - // finally check if file is in a dosbox local drive - char fullname[CROSS_LEN]; - char tmp[CROSS_LEN]; - safe_strncpy(tmp, filename.c_str(), CROSS_LEN); - Bit8u drive; - if (!DOS_MakeName(tmp, fullname, &drive)) return false; - - localDrive *ldp = dynamic_cast(Drives[drive]); - if (ldp) { - ldp->GetSystemFilename(tmp, fullname); - if (stat(tmp, &test) == 0) { - filename = tmp; - return true; - } - } - - return false; -} - -bool CDROM_Interface_Image::GetCueKeyword(string &keyword, istream &in) -{ - in >> keyword; - for(Bitu i = 0; i < keyword.size(); i++) keyword[i] = toupper(keyword[i]); - - return true; -} - -bool CDROM_Interface_Image::GetCueFrame(int &frames, istream &in) -{ - string msf; - in >> msf; - int min, sec, fr; - bool success = sscanf(msf.c_str(), "%d:%d:%d", &min, &sec, &fr) == 3; - frames = MSF_TO_FRAMES(min, sec, fr); - - return success; -} - -bool CDROM_Interface_Image::GetCueString(string &str, istream &in) -{ - int pos = (int)in.tellg(); - in >> str; - if (str[0] == '\"') { - if (str[str.size() - 1] == '\"') { - str.assign(str, 1, str.size() - 2); - } else { - in.seekg(pos, ios::beg); - char buffer[MAX_FILENAME_LENGTH]; - in.getline(buffer, MAX_FILENAME_LENGTH, '\"'); // skip - in.getline(buffer, MAX_FILENAME_LENGTH, '\"'); - str = buffer; - } - } - return true; -} - -void CDROM_Interface_Image::ClearTracks() -{ - vector::iterator i = tracks.begin(); - vector::iterator end = tracks.end(); - - TrackFile* last = NULL; - while(i != end) { - Track &curr = *i; - if (curr.file != last) { - delete curr.file; - last = curr.file; - } - i++; - } - tracks.clear(); -} - -void CDROM_Image_Destroy(Section*) { -#if defined(C_SDL_SOUND) - Sound_Quit(); -#endif -} - -void CDROM_Image_Init(Section* section) { -#if defined(C_SDL_SOUND) - Sound_Init(); - section->AddDestroyFunction(CDROM_Image_Destroy, false); -#endif -} diff --git a/src/dos/cdrom_ioctl_linux.cpp b/src/dos/cdrom_ioctl_linux.cpp deleted file mode 100644 index 8d1334e..0000000 --- a/src/dos/cdrom_ioctl_linux.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -#include -#include "cdrom.h" -#include "support.h" - -#if defined (LINUX) -#include -#include -#include -#include -#include -#include - -CDROM_Interface_Ioctl::CDROM_Interface_Ioctl(void) : CDROM_Interface_SDL() -{ - strcpy(device_name, ""); -} - -bool CDROM_Interface_Ioctl::GetUPC(unsigned char& attr, char* upc) -{ - int cdrom_fd = open(device_name, O_RDONLY | O_NONBLOCK); - if (cdrom_fd <= 0) return false; - - struct cdrom_mcn cdrom_mcn; - int ret = ioctl(cdrom_fd, CDROM_GET_MCN, &cdrom_mcn); - - close(cdrom_fd); - - if (ret > 0) { - attr = 0; - safe_strncpy(upc, (char*)cdrom_mcn.medium_catalog_number, 14); - } - - return (ret > 0); -} - -bool CDROM_Interface_Ioctl::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) -{ - int cdrom_fd = open(device_name, O_RDONLY | O_NONBLOCK); - if (cdrom_fd <= 0) return false; - - Bits buflen = raw ? num * CD_FRAMESIZE_RAW : num * CD_FRAMESIZE; - Bit8u* buf = new Bit8u[buflen]; - int ret; - - if (raw) { - struct cdrom_read cdrom_read; - cdrom_read.cdread_lba = sector; - cdrom_read.cdread_bufaddr = (char*)buf; - cdrom_read.cdread_buflen = buflen; - - ret = ioctl(cdrom_fd, CDROMREADRAW, &cdrom_read); - } else { - ret = lseek(cdrom_fd, sector * CD_FRAMESIZE, SEEK_SET); - if (ret >= 0) ret = read(cdrom_fd, buf, buflen); - if (ret != buflen) ret = -1; - } - close(cdrom_fd); - - MEM_BlockWrite(buffer, buf, buflen); - delete[] buf; - - return (ret > 0); -} - -bool CDROM_Interface_Ioctl::SetDevice(char* path, int forceCD) -{ - bool success = CDROM_Interface_SDL::SetDevice(path, forceCD); - - if (success) { - const char* tmp = SDL_CDName(forceCD); - if (tmp) safe_strncpy(device_name, tmp, 512); - else success = false; - } - - return success; -} - -#endif diff --git a/src/dos/cdrom_ioctl_os2.cpp b/src/dos/cdrom_ioctl_os2.cpp deleted file mode 100644 index f2fe632..0000000 --- a/src/dos/cdrom_ioctl_os2.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: cdrom_ioctl_os2.cpp,v 1.3 2007/01/08 19:45:39 qbix79 Exp $ */ - -#include -#include "dosbox.h" -#include "cdrom.h" - -#if defined (OS2) -#define INCL_DOSFILEMGR -#define INCL_DOSERRORS -#define INCL_DOSDEVICES -#define INCL_DOSDEVIOCTL -#include "os2.h" - -// Ripped from linux/cdrom.h -#define CD_FRAMESIZE_RAW 2352 -#define CD_FRAMESIZE 2048 - -CDROM_Interface_Ioctl::CDROM_Interface_Ioctl(void) : CDROM_Interface_SDL(){ - strcpy(device_name, ""); -} - -bool CDROM_Interface_Ioctl::GetUPC(unsigned char& attr, char* upc){ - HFILE cdrom_fd = 0; - ULONG ulAction = 0; - APIRET rc = DosOpen((unsigned char*)device_name, &cdrom_fd, &ulAction, 0L, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS, - OPEN_FLAGS_DASD | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, 0L); - if (rc != NO_ERROR) { - return false; - } - char data[50]; - ULONG len = sizeof(data); - char sig[] = {'C', 'D', '0', '1'}; - ULONG sigsize = 4; - rc = DosDevIOCtl(cdrom_fd, IOCTL_CDROMDISK, CDROMDISK_GETUPC, sig, sigsize, &sigsize, - data, len, &len); - if (rc != NO_ERROR) { - return false; - } - rc = DosClose(cdrom_fd); - return rc == NO_ERROR; -} - -bool CDROM_Interface_Ioctl::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num){ - HFILE cdrom_fd = 0; - ULONG ulAction = 0; - APIRET rc = DosOpen((unsigned char*)device_name, &cdrom_fd, &ulAction, 0L, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS, - OPEN_FLAGS_DASD | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, 0L); - if (rc != NO_ERROR) { - return false; - } - - Bitu buflen = raw ? num * CD_FRAMESIZE_RAW : num * CD_FRAMESIZE; - Bit8u* buf = new Bit8u[buflen]; - int ret = NO_ERROR; - - if (raw) { - struct paramseek { - UCHAR sig[4]; - UCHAR mode; - ULONG sec; - - paramseek(ULONG sector) - { - sig[0] = 'C'; sig[1] = 'D'; sig[2] = '0'; sig[3] = '1'; - sec = sector; - } - } param_seek(sector); - ULONG paramsize = sizeof (paramseek); - rc = DosDevIOCtl(cdrom_fd, IOCTL_CDROMDISK, CDROMDISK_SEEK, ¶m_seek, paramsize, ¶msize, - 0, 0, 0); - if (rc != NO_ERROR) { - return false; - } - - struct paramread { - UCHAR sig[4]; - UCHAR mode; - USHORT number; - BYTE sec; - BYTE reserved; - BYTE interleave; - - paramread(USHORT num) - { - sig[0] = 'C'; sig[1] = 'D'; sig[2] = '0'; sig[3] = '1'; - mode = 0; number = num; - sec = interleave = 0; - } - } param_read(num); - paramsize = sizeof (paramread); - ULONG len = buflen; - rc = DosDevIOCtl(cdrom_fd, IOCTL_CDROMDISK, CDROMDISK_READLONG, ¶m_read, paramsize, ¶msize, - buf, len, &len); - if (rc != NO_ERROR) { - return false; - } - } else { - ULONG pos = 0; - rc = DosSetFilePtr(cdrom_fd, sector * CD_FRAMESIZE, FILE_BEGIN, &pos); - if (rc != NO_ERROR) { - return false; - } - ULONG read = 0; - rc = DosRead(cdrom_fd, buf, buflen, &read); - if (rc != NO_ERROR || read != buflen) { - return false; - } - } - rc = DosClose(cdrom_fd); - MEM_BlockWrite(buffer, buf, buflen); - delete[] buf; - - return (ret == NO_ERROR); -} - -bool CDROM_Interface_Ioctl::SetDevice(char* path, int forceCD) { - bool success = CDROM_Interface_SDL::SetDevice(path, forceCD); - - if (success) { - char temp[3] = {0, 0, 0}; - if (path[1] == ':') { - temp[0] = path[0]; - temp[1] = path[1]; - temp[2] = 0; - } - strncpy(device_name, temp, 512); - } else { - strcpy(device_name, ""); - success = false; - } - - return success; -} - -#endif diff --git a/src/dos/cdrom_ioctl_win32.cpp b/src/dos/cdrom_ioctl_win32.cpp deleted file mode 100644 index 9c77865..0000000 --- a/src/dos/cdrom_ioctl_win32.cpp +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: cdrom_ioctl_win32.cpp,v 1.16 2009/01/07 22:39:18 c2woody Exp $ */ - -#if defined (WIN32) - -// ***************************************************************** -// Windows IOCTL functions (not suitable for 95/98/Me) -// ***************************************************************** - -#include -#include - -#if defined (_MSC_VER) -#include // Ioctl stuff -#include // Ioctl stuff -#else -#include "ddk/ntddcdrm.h" // Ioctl stuff -#endif - -#include - -#include "cdrom.h" - -// for a more sophisticated implementation of the mci cdda functionality -// see the SDL sources, which the mci_ functions are based on - -/* General ioctl() CD-ROM command function */ -bool CDROM_Interface_Ioctl::mci_CDioctl(UINT msg, DWORD flags, void *arg) { - MCIERROR mci_error = mciSendCommand(mci_devid, msg, flags, (DWORD_PTR)arg); - if (mci_error!=MMSYSERR_NOERROR) { - char error[256]; - mciGetErrorString(mci_error, error, 256); - LOG_MSG("mciSendCommand() error: %s", error); - return true; - } - return false; -} - -bool CDROM_Interface_Ioctl::mci_CDOpen(char drive) { - MCI_OPEN_PARMS mci_open; - MCI_SET_PARMS mci_set; - char device[3]; - DWORD flags; - - /* Open the requested device */ - mci_open.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO; - device[0] = drive; - device[1] = ':'; - device[2] = '\0'; - mci_open.lpstrElementName = device; - flags = (MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT); - if (mci_CDioctl(MCI_OPEN, flags, &mci_open)) { - flags &= ~MCI_OPEN_SHAREABLE; - if (mci_CDioctl(MCI_OPEN, flags, &mci_open)) { - return true; - } - } - mci_devid = mci_open.wDeviceID; - - /* Set the minute-second-frame time format */ - mci_set.dwTimeFormat = MCI_FORMAT_MSF; - mci_CDioctl(MCI_SET, MCI_SET_TIME_FORMAT, &mci_set); - - return false; -} - -bool CDROM_Interface_Ioctl::mci_CDClose(void) { - return mci_CDioctl(MCI_CLOSE, MCI_WAIT, NULL); -} - -bool CDROM_Interface_Ioctl::mci_CDPlay(int start, int length) { - DWORD flags = MCI_FROM | MCI_TO | MCI_NOTIFY; - MCI_PLAY_PARMS mci_play; - mci_play.dwCallback = 0; - - int m, s, f; - FRAMES_TO_MSF(start, &m, &s, &f); - mci_play.dwFrom = MCI_MAKE_MSF(m, s, f); - - FRAMES_TO_MSF(start+length, &m, &s, &f); - mci_play.dwTo = MCI_MAKE_MSF(m, s, f); - - return mci_CDioctl(MCI_PLAY, flags, &mci_play); -} - -bool CDROM_Interface_Ioctl::mci_CDPause(void) { - return mci_CDioctl(MCI_PAUSE, MCI_WAIT, NULL); -} - -bool CDROM_Interface_Ioctl::mci_CDResume(void) { - return mci_CDioctl(MCI_RESUME, MCI_WAIT, NULL); -} - -bool CDROM_Interface_Ioctl::mci_CDStop(void) { - return mci_CDioctl(MCI_STOP, MCI_WAIT, NULL); -} - -int CDROM_Interface_Ioctl::mci_CDStatus(void) { - int status; - MCI_STATUS_PARMS mci_status; - - DWORD flags = MCI_STATUS_ITEM | MCI_WAIT; - mci_status.dwItem = MCI_STATUS_MODE; - if (mci_CDioctl(MCI_STATUS, flags, &mci_status)) { - status = -1; - } else { - switch (mci_status.dwReturn) { - case MCI_MODE_NOT_READY: - case MCI_MODE_OPEN: - status = 0; - break; - case MCI_MODE_STOP: - status = 1; - break; - case MCI_MODE_PLAY: - status = 2; - break; - case MCI_MODE_PAUSE: - status = 3; - break; - default: - status = -1; - break; - } - } - - return status; -} - -bool CDROM_Interface_Ioctl::mci_CDPosition(int *position) { - *position = 0; - - DWORD flags = MCI_STATUS_ITEM | MCI_WAIT; - - MCI_STATUS_PARMS mci_status; - mci_status.dwItem = MCI_STATUS_MODE; - if (mci_CDioctl(MCI_STATUS, flags, &mci_status)) return true; - switch (mci_status.dwReturn) { - case MCI_MODE_NOT_READY: - case MCI_MODE_OPEN: - case MCI_MODE_STOP: - return true; // not ready/undefined status - case MCI_MODE_PLAY: - case MCI_MODE_PAUSE: - mci_status.dwItem = MCI_STATUS_POSITION; - if (!mci_CDioctl(MCI_STATUS, flags, &mci_status)) { - *position = MSF_TO_FRAMES( - MCI_MSF_MINUTE(mci_status.dwReturn), - MCI_MSF_SECOND(mci_status.dwReturn), - MCI_MSF_FRAME(mci_status.dwReturn)); - } - return false; // no error, position read - default: - break; - } - return false; -} - - -CDROM_Interface_Ioctl::dxPlayer CDROM_Interface_Ioctl::player = { - NULL, NULL, NULL, 0, 0, 0, 0, 0, false, false }; - -CDROM_Interface_Ioctl::CDROM_Interface_Ioctl(cdioctl_cdatype ioctl_cda) { - pathname[0] = 0; - hIOCTL = INVALID_HANDLE_VALUE; - memset(&oldLeadOut,0,sizeof(oldLeadOut)); - cdioctl_cda_selected = ioctl_cda; -} - -CDROM_Interface_Ioctl::~CDROM_Interface_Ioctl() { - StopAudio(); - if (use_mciplay) mci_CDStop(); - Close(); - if (use_mciplay) mci_CDClose(); -} - -bool CDROM_Interface_Ioctl::GetUPC(unsigned char& attr, char* upc) { - // FIXME : To Do - return true; -} - -bool CDROM_Interface_Ioctl::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut) { - CDROM_TOC toc; - DWORD byteCount; - BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, - &toc, sizeof(toc), &byteCount,NULL); - if (!bStat) return false; - - stTrack = toc.FirstTrack; - endTrack = toc.LastTrack; - leadOut.min = toc.TrackData[endTrack].Address[1]; - leadOut.sec = toc.TrackData[endTrack].Address[2]; - leadOut.fr = toc.TrackData[endTrack].Address[3]; - - if ((use_mciplay || use_dxplay) && (!track_start_valid)) { - Bits track_num = 0; - // get track start address of all tracks - for (Bits i=toc.FirstTrack; i<=toc.LastTrack+1; i++) { - if (((toc.TrackData[i].Control&1)==0) || (i==toc.LastTrack+1)) { - track_start[track_num] = MSF_TO_FRAMES(toc.TrackData[track_num].Address[1],toc.TrackData[track_num].Address[2],toc.TrackData[track_num].Address[3])-150; - track_start[track_num] += 150; - track_num++; - } - } - track_start_first = 0; - track_start_last = track_num-1; - track_start_valid = true; - } - - return true; -} - -bool CDROM_Interface_Ioctl::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) { - CDROM_TOC toc; - DWORD byteCount; - BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, - &toc, sizeof(toc), &byteCount,NULL); - if (!bStat) return false; - - attr = (toc.TrackData[track-1].Control << 4) & 0xEF; - start.min = toc.TrackData[track-1].Address[1]; - start.sec = toc.TrackData[track-1].Address[2]; - start.fr = toc.TrackData[track-1].Address[3]; - return true; -} - -bool CDROM_Interface_Ioctl::GetAudioTracksAll(void) { - if (track_start_valid) return true; - - CDROM_TOC toc; - DWORD byteCount; - BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, - &toc, sizeof(toc), &byteCount,NULL); - if (!bStat) return false; - - Bits track_num = 0; - // get track start address of all tracks - for (Bits i=toc.FirstTrack; i<=toc.LastTrack+1; i++) { - if (((toc.TrackData[i].Control&1)==0) || (i==toc.LastTrack+1)) { - track_start[track_num] = MSF_TO_FRAMES(toc.TrackData[track_num].Address[1],toc.TrackData[track_num].Address[2],toc.TrackData[track_num].Address[3])-150; - track_start[track_num] += 150; - track_num++; - } - } - track_start_first = 0; - track_start_last = track_num-1; - track_start_valid = true; - return true; -} - -bool CDROM_Interface_Ioctl::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) { - if (use_dxplay) { - track = 1; - FRAMES_TO_MSF(player.currFrame + 150, &absPos.min, &absPos.sec, &absPos.fr); - FRAMES_TO_MSF(player.currFrame + 150, &relPos.min, &relPos.sec, &relPos.fr); - - if (GetAudioTracksAll()) { - // get track number from current frame - for (int i=track_start_first; i<=track_start_last; i++) { - if ((player.currFrame + 150=track_start[i])) { - // track found, calculate relative position - track = i; - FRAMES_TO_MSF(player.currFrame + 150-track_start[i],&relPos.min,&relPos.sec,&relPos.fr); - break; - } - } - } - - return true; - } - - CDROM_SUB_Q_DATA_FORMAT insub; - SUB_Q_CHANNEL_DATA sub; - DWORD byteCount; - - insub.Format = IOCTL_CDROM_CURRENT_POSITION; - - BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), - &sub, sizeof(sub), &byteCount,NULL); - if (!bStat) return false; - - attr = (sub.CurrentPosition.Control << 4) & 0xEF; - track = sub.CurrentPosition.TrackNumber; - index = sub.CurrentPosition.IndexNumber; - relPos.min = sub.CurrentPosition.TrackRelativeAddress[1]; - relPos.sec = sub.CurrentPosition.TrackRelativeAddress[2]; - relPos.fr = sub.CurrentPosition.TrackRelativeAddress[3]; - absPos.min = sub.CurrentPosition.AbsoluteAddress[1]; - absPos.sec = sub.CurrentPosition.AbsoluteAddress[2]; - absPos.fr = sub.CurrentPosition.AbsoluteAddress[3]; - - if (use_mciplay) { - int cur_pos; - if (!mci_CDPosition(&cur_pos)) { - // absolute position read, try to calculate the track-relative position - if (GetAudioTracksAll()) { - for (int i=track_start_first; i<=track_start_last; i++) { - if ((cur_pos=track_start[i])) { - // track found, calculate relative position - FRAMES_TO_MSF(cur_pos-track_start[i],&relPos.min,&relPos.sec,&relPos.fr); - break; - } - } - } - FRAMES_TO_MSF(cur_pos,&absPos.min,&absPos.sec,&absPos.fr); - } - } - - return true; -} - -bool CDROM_Interface_Ioctl::GetAudioStatus(bool& playing, bool& pause) { - if (use_mciplay) { - int status = mci_CDStatus(); - if (status<0) return false; - playing = (status==2); - pause = (status==3); - return true; - } - if (use_dxplay) { - playing = player.isPlaying; - pause = player.isPaused; - return true; - } - - CDROM_SUB_Q_DATA_FORMAT insub; - SUB_Q_CHANNEL_DATA sub; - DWORD byteCount; - - insub.Format = IOCTL_CDROM_CURRENT_POSITION; - - BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), - &sub, sizeof(sub), &byteCount,NULL); - if (!bStat) return false; - - playing = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS); - pause = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_PAUSED); - - return true; -} - -bool CDROM_Interface_Ioctl::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) { - // Seems not possible to get this values using ioctl... - int track1,track2; - TMSF leadOut; - // If we can read, there's a media - mediaPresent = GetAudioTracks(track1, track2, leadOut), - trayOpen = !mediaPresent; - mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr); - if (mediaChanged) { - Close(); - if (use_mciplay) mci_CDClose(); - // Open new medium - Open(); - - if (cdioctl_cda_selected == CDIOCTL_CDA_MCI) { - // check this (what to do if cd is ejected): - use_mciplay = false; - if (!mci_CDOpen(pathname[4])) use_mciplay = true; - } - track_start_valid = false; - } - // Save old values - oldLeadOut.min = leadOut.min; - oldLeadOut.sec = leadOut.sec; - oldLeadOut.fr = leadOut.fr; - // always success - return true; -} - -bool CDROM_Interface_Ioctl::PlayAudioSector (unsigned long start,unsigned long len) { - if (use_mciplay) { - if (!mci_CDPlay(start+150, len)) return true; - if (!mci_CDPlay(start+150, len-1)) return true; - return false; - } - if (use_dxplay) { - SDL_mutexP(player.mutex); - player.cd = this; - player.currFrame = start; - player.targetFrame = start + len; - player.isPlaying = true; - player.isPaused = false; - SDL_mutexV(player.mutex); - return true; - } - - CDROM_PLAY_AUDIO_MSF audio; - DWORD byteCount; - // Start - unsigned long addr = start + 150; - audio.StartingF = (UCHAR)(addr%75); addr/=75; - audio.StartingS = (UCHAR)(addr%60); - audio.StartingM = (UCHAR)(addr/60); - // End - addr = start + len + 150; - audio.EndingF = (UCHAR)(addr%75); addr/=75; - audio.EndingS = (UCHAR)(addr%60); - audio.EndingM = (UCHAR)(addr/60); - - BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PLAY_AUDIO_MSF, &audio, sizeof(audio), - NULL, 0, &byteCount,NULL); - return bStat>0; -} - -bool CDROM_Interface_Ioctl::PauseAudio(bool resume) { - if (use_mciplay) { - if (resume) { - if (!mci_CDResume()) return true; - } else { - if (!mci_CDPause()) return true; - } - return false; - } - if (use_dxplay) { - player.isPaused = !resume; - return true; - } - - BOOL bStat; - DWORD byteCount; - if (resume) bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RESUME_AUDIO, NULL, 0, - NULL, 0, &byteCount,NULL); - else bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, - NULL, 0, &byteCount,NULL); - return bStat>0; -} - -bool CDROM_Interface_Ioctl::StopAudio(void) { - if (use_mciplay) { - if (!mci_CDStop()) return true; - return false; - } - if (use_dxplay) { - player.isPlaying = false; - player.isPaused = false; - return true; - } - - BOOL bStat; - DWORD byteCount; - bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_STOP_AUDIO, NULL, 0, - NULL, 0, &byteCount,NULL); - return bStat>0; -} - -bool CDROM_Interface_Ioctl::LoadUnloadMedia(bool unload) { - BOOL bStat; - DWORD byteCount; - if (unload) bStat = DeviceIoControl(hIOCTL,IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, - NULL, 0, &byteCount,NULL); - else bStat = DeviceIoControl(hIOCTL,IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, - NULL, 0, &byteCount,NULL); - track_start_valid = false; - return bStat>0; -} - -bool CDROM_Interface_Ioctl::ReadSector(Bit8u *buffer, bool raw, unsigned long sector) { - BOOL bStat; - DWORD byteCount = 0; - - Bitu buflen = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - - if (!raw) { - // Cooked - int success = 0; - DWORD newPos = SetFilePointer(hIOCTL, sector*COOKED_SECTOR_SIZE, 0, FILE_BEGIN); - if (newPos != 0xFFFFFFFF) success = ReadFile(hIOCTL, buffer, buflen, &byteCount, NULL); - bStat = (success!=0); - } else { - // Raw - RAW_READ_INFO in; - in.DiskOffset.LowPart = sector*COOKED_SECTOR_SIZE; - in.DiskOffset.HighPart = 0; - in.SectorCount = 1; - in.TrackMode = CDDA; - bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RAW_READ, &in, sizeof(in), - buffer, buflen, &byteCount,NULL); - } - - return (byteCount==buflen) && (bStat>0); -} - -bool CDROM_Interface_Ioctl::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { - BOOL bStat; - DWORD byteCount = 0; - - Bitu buflen = raw ? num*RAW_SECTOR_SIZE : num*COOKED_SECTOR_SIZE; - Bit8u* bufdata = new Bit8u[buflen]; - - if (!raw) { - // Cooked - int success = 0; - DWORD newPos = SetFilePointer(hIOCTL, sector*COOKED_SECTOR_SIZE, 0, FILE_BEGIN); - if (newPos != 0xFFFFFFFF) success = ReadFile(hIOCTL, bufdata, buflen, &byteCount, NULL); - bStat = (success!=0); - } else { - // Raw - RAW_READ_INFO in; - in.DiskOffset.LowPart = sector*COOKED_SECTOR_SIZE; - in.DiskOffset.HighPart = 0; - in.SectorCount = num; - in.TrackMode = CDDA; - bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RAW_READ, &in, sizeof(in), - bufdata, buflen, &byteCount,NULL); - } - - MEM_BlockWrite(buffer,bufdata,buflen); - delete[] bufdata; - - return (byteCount==buflen) && (bStat>0); -} - -void CDROM_Interface_Ioctl::dx_CDAudioCallBack(Bitu len) { - len *= 4; // 16 bit, stereo - if (!len) return; - if (!player.isPlaying || player.isPaused) { - player.channel->AddSilence(); - return; - } - SDL_mutexP(player.mutex); - while (player.bufLen < (Bits)len) { - bool success; - if (player.targetFrame > player.currFrame) - success = player.cd->ReadSector(&player.buffer[player.bufLen], true, player.currFrame); - else success = false; - - if (success) { - player.currFrame++; - player.bufLen += RAW_SECTOR_SIZE; - } else { - memset(&player.buffer[player.bufLen], 0, len - player.bufLen); - player.bufLen = len; - player.isPlaying = false; - } - } - SDL_mutexV(player.mutex); - player.channel->AddSamples_s16(len/4,(Bit16s *)player.buffer); - memmove(player.buffer, &player.buffer[len], player.bufLen - len); - player.bufLen -= len; -} - -bool CDROM_Interface_Ioctl::SetDevice(char* path, int forceCD) { - mci_devid = 0; - use_mciplay = false; - use_dxplay = false; - track_start_valid = false; - if (GetDriveType(path)==DRIVE_CDROM) { - char letter [3] = { 0, ':', 0 }; - letter[0] = path[0]; - strcpy(pathname,"\\\\.\\"); - strcat(pathname,letter); - if (Open()) { - if (cdioctl_cda_selected == CDIOCTL_CDA_MCI) { - // check if MCI-interface can be used for cd audio - if (!mci_CDOpen(path[0])) use_mciplay = true; - } - if (!use_mciplay) { - if (cdioctl_cda_selected == CDIOCTL_CDA_DX) { - // use direct sector access for cd audio routines - player.mutex = SDL_CreateMutex(); - if (!player.channel) { - player.channel = MIXER_AddChannel(&dx_CDAudioCallBack, 44100, "CDAUDIO"); - } - player.channel->Enable(true); - use_dxplay = true; - } - } - return true; - }; - } - return false; -} - -bool CDROM_Interface_Ioctl::Open(void) { - hIOCTL = CreateFile(pathname, // drive to open - GENERIC_READ, // read access - FILE_SHARE_READ | // share mode - FILE_SHARE_WRITE, - NULL, // default security attributes - OPEN_EXISTING, // disposition - 0, // file attributes - NULL); // do not copy file attributes - return (hIOCTL!=INVALID_HANDLE_VALUE); -} - -void CDROM_Interface_Ioctl::Close(void) { - CloseHandle(hIOCTL); -} - -#endif diff --git a/src/dos/dev_con.h b/src/dos/dev_con.h index 22ac8e9..003c15e 100644 --- a/src/dos/dev_con.h +++ b/src/dos/dev_con.h @@ -1,416 +1,105 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dev_con.h,v 1.34 2008/10/05 14:44:52 qbix79 Exp $ */ - -#include "dos_inc.h" -#include "../ints/int10.h" -#include - -#define NUMBER_ANSI_DATA 10 - -class device_CON : public DOS_Device { -public: - device_CON(); - bool Read(Bit8u * data,Bit16u * size); - bool Write(Bit8u * data,Bit16u * size); - bool Seek(Bit32u * pos,Bit32u type); - bool Close(); - void ClearAnsi(void); - Bit16u GetInformation(void); - bool ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode){return false;} - bool WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode){return false;} -private: - Bit8u readcache; - Bit8u lastwrite; - struct ansi { /* should create a constructor which fills them with the appriorate values */ - bool esc; - bool sci; - bool enabled; - Bit8u attr; - Bit8u data[NUMBER_ANSI_DATA]; - Bit8u numberofarg; - Bit16u nrows; - Bit16u ncols; - Bit8s savecol; - Bit8s saverow; - bool warned; - } ansi; -}; - -bool device_CON::Read(Bit8u * data,Bit16u * size) { - Bit16u oldax=reg_ax; - Bit16u count=0; - if ((readcache) && (*size)) { - data[count++]=readcache; - if(dos.echo) INT10_TeletypeOutput(readcache,7); - readcache=0; - } - while (*size>count) { - reg_ah=(IS_EGAVGA_ARCH)?0x10:0x0; - CALLBACK_RunRealInt(0x16); - switch(reg_al) { - case 13: - data[count++]=0x0D; - if (*size>count) data[count++]=0x0A; // it's only expanded if there is room for it. (NO cache) - *size=count; - reg_ax=oldax; - if(dos.echo) { - INT10_TeletypeOutput(13,7); //maybe don't do this ( no need for it actually ) (but it's compatible) - INT10_TeletypeOutput(10,7); - } - return true; - break; - case 8: - if(*size==1) data[count++]=reg_al; //one char at the time so give back that BS - else if(count) { //Remove data if it exists (extended keys don't go right) - data[count--]=0; - INT10_TeletypeOutput(8,7); - INT10_TeletypeOutput(' ',7); - } else { - continue; //no data read yet so restart whileloop. - } - break; - case 0xe0: /* Extended keys in the int 16 0x10 case */ - if(!reg_ah) { /*extended key if reg_ah isn't 0 */ - data[count++] = reg_al; - } else { - data[count++] = 0; - if (*size>count) data[count++] = reg_ah; - else readcache = reg_ah; - } - break; - case 0: /* Extended keys in the int 16 0x0 case */ - data[count++]=reg_al; - if (*size>count) data[count++]=reg_ah; - else readcache=reg_ah; - break; - default: - data[count++]=reg_al; - break; - } - if(dos.echo) { //what to do if *size==1 and character is BS ????? - INT10_TeletypeOutput(reg_al,7); - } - } - *size=count; - reg_ax=oldax; - return true; -} - - -bool device_CON::Write(Bit8u * data,Bit16u * size) { - Bit16u count=0; - Bitu i; - Bit8u col,row; - Bit8u tempdata; - while (*size>count) { - if (!ansi.esc){ - if(data[count]=='\033') { - /*clear the datastructure */ - ClearAnsi(); - /* start the sequence */ - ansi.esc=true; - count++; - continue; - } else { - /* Some sort of "hack" now that \n doesn't set col to 0 (int10_char.cpp old chessgame) */ - if((data[count] == '\n') && (lastwrite != '\r')) INT10_TeletypeOutputAttr('\r',ansi.attr,ansi.enabled); - /* pass attribute only if ansi is enabled */ - INT10_TeletypeOutputAttr(data[count],ansi.attr,ansi.enabled); - lastwrite = data[count++]; - continue; - } - } - - if(!ansi.sci){ - - switch(data[count]){ - case '[': - ansi.sci=true; - break; - case '7': /* save cursor pos + attr */ - case '8': /* restore this (Wonder if this is actually used) */ - case 'D':/* scrolling DOWN*/ - case 'M':/* scrolling UP*/ - default: - LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unknown char %c after a esc",data[count]); /*prob () */ - ClearAnsi(); - break; - } - count++; - continue; - } - /*ansi.esc and ansi.sci are true */ - Bit8u page = real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); - switch(data[count]){ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - ansi.data[ansi.numberofarg]=10*ansi.data[ansi.numberofarg]+(data[count]-'0'); - break; - case ';': /* till a max of NUMBER_ANSI_DATA */ - ansi.numberofarg++; - break; - case 'm': /* SGR */ - for(i=0;i<=ansi.numberofarg;i++){ - ansi.enabled=true; - switch(ansi.data[i]){ - case 0: /* normal */ - ansi.attr=0x07;//Real ansi does this as well. (should do current defaults) - ansi.enabled=false; - break; - case 1: /* bold mode on*/ - ansi.attr|=0x08; - break; - case 4: /* underline */ - LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet"); - break; - case 5: /* blinking */ - ansi.attr|=0x80; - break; - case 7: /* reverse */ - ansi.attr=0x70;//Just like real ansi. (should do use current colors reversed) - break; - case 30: /* fg color black */ - ansi.attr&=0xf8; - ansi.attr|=0x0; - break; - case 31: /* fg color red */ - ansi.attr&=0xf8; - ansi.attr|=0x4; - break; - case 32: /* fg color green */ - ansi.attr&=0xf8; - ansi.attr|=0x2; - break; - case 33: /* fg color yellow */ - ansi.attr&=0xf8; - ansi.attr|=0x6; - break; - case 34: /* fg color blue */ - ansi.attr&=0xf8; - ansi.attr|=0x1; - break; - case 35: /* fg color magenta */ - ansi.attr&=0xf8; - ansi.attr|=0x5; - break; - case 36: /* fg color cyan */ - ansi.attr&=0xf8; - ansi.attr|=0x3; - break; - case 37: /* fg color white */ - ansi.attr&=0xf8; - ansi.attr|=0x7; - break; - case 40: - ansi.attr&=0x8f; - ansi.attr|=0x0; - break; - case 41: - ansi.attr&=0x8f; - ansi.attr|=0x40; - break; - case 42: - ansi.attr&=0x8f; - ansi.attr|=0x20; - break; - case 43: - ansi.attr&=0x8f; - ansi.attr|=0x60; - break; - case 44: - ansi.attr&=0x8f; - ansi.attr|=0x10; - break; - case 45: - ansi.attr&=0x8f; - ansi.attr|=0x50; - break; - case 46: - ansi.attr&=0x8f; - ansi.attr|=0x30; - break; - case 47: - ansi.attr&=0x8f; - ansi.attr|=0x70; - break; - default: - break; - } - } - ClearAnsi(); - break; - case 'f': - case 'H':/* Cursor Pos*/ - if(!ansi.warned) { //Inform the debugger that ansi is used. - ansi.warned = true; - LOG(LOG_IOCTL,LOG_WARN)("ANSI SEQUENCES USED"); - } - /* Turn them into positions that are on the screen */ - if(ansi.data[0] == 0) ansi.data[0] = 1; - if(ansi.data[1] == 0) ansi.data[1] = 1; - if(ansi.data[0] > ansi.nrows) ansi.data[0] = (Bit8u)ansi.nrows; - if(ansi.data[1] > ansi.ncols) ansi.data[1] = (Bit8u)ansi.ncols; - INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),page); /*ansi=1 based, int10 is 0 based */ - ClearAnsi(); - break; - /* cursor up down and forward and backward only change the row or the col not both */ - case 'A': /* cursor up*/ - col=CURSOR_POS_COL(page) ; - row=CURSOR_POS_ROW(page) ; - tempdata = (ansi.data[0]? ansi.data[0] : 1); - if(tempdata > row) { row=0; } - else { row-=tempdata;} - INT10_SetCursorPos(row,col,page); - ClearAnsi(); - break; - case 'B': /*cursor Down */ - col=CURSOR_POS_COL(page) ; - row=CURSOR_POS_ROW(page) ; - tempdata = (ansi.data[0]? ansi.data[0] : 1); - if(tempdata + static_cast(row) >= ansi.nrows) - { row = ansi.nrows - 1;} - else { row += tempdata; } - INT10_SetCursorPos(row,col,page); - ClearAnsi(); - break; - case 'C': /*cursor forward */ - col=CURSOR_POS_COL(page); - row=CURSOR_POS_ROW(page); - tempdata=(ansi.data[0]? ansi.data[0] : 1); - if(tempdata + static_cast(col) >= ansi.ncols) - { col = ansi.ncols - 1;} - else { col += tempdata;} - INT10_SetCursorPos(row,col,page); - ClearAnsi(); - break; - case 'D': /*Cursor Backward */ - col=CURSOR_POS_COL(page); - row=CURSOR_POS_ROW(page); - tempdata=(ansi.data[0]? ansi.data[0] : 1); - if(tempdata > col) {col = 0;} - else { col -= tempdata;} - INT10_SetCursorPos(row,col,page); - ClearAnsi(); - break; - case 'J': /*erase screen and move cursor home*/ - if(ansi.data[0]==0) ansi.data[0]=2; - if(ansi.data[0]!=2) {/* every version behaves like type 2 */ - LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported handling as 2",ansi.data[0]); - } - INT10_ScrollWindow(0,0,255,255,0,ansi.attr,page); - ClearAnsi(); - INT10_SetCursorPos(0,0,page); - break; - case 'h': /* SET MODE (if code =7 enable linewrap) */ - case 'I': /* RESET MODE */ - LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: set/reset mode called(not supported)"); - ClearAnsi(); - break; - case 'u': /* Restore Cursor Pos */ - INT10_SetCursorPos(ansi.saverow,ansi.savecol,page); - ClearAnsi(); - break; - case 's': /* SAVE CURSOR POS */ - ansi.savecol=CURSOR_POS_COL(page); - ansi.saverow=CURSOR_POS_ROW(page); - ClearAnsi(); - break; - case 'K': /* erase till end of line (don't touch cursor) */ - col = CURSOR_POS_COL(page); - row = CURSOR_POS_ROW(page); - INT10_WriteChar(' ',ansi.attr,page,ansi.ncols-col,true); //Use this one to prevent scrolling when end of screen is reached - //for(i = col;i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true); - INT10_SetCursorPos(row,col,page); - ClearAnsi(); - break; - case 'M': /* delete line (NANSI) */ - col = CURSOR_POS_COL(page); - row = CURSOR_POS_ROW(page); - INT10_ScrollWindow(row,0,ansi.nrows-1,ansi.ncols-1,ansi.data[0]? -ansi.data[0] : -1,ansi.attr,0xFF); - ClearAnsi(); - break; - case 'l':/* (if code =7) disable linewrap */ - case 'p':/* reassign keys (needs strings) */ - case 'i':/* printer stuff */ - default: - LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unhandled char %c in esc[",data[count]); - ClearAnsi(); - break; - } - count++; - } - *size=count; - return true; -} - -bool device_CON::Seek(Bit32u * pos,Bit32u type) { - // seek is valid - *pos = 0; - return true; -} - -bool device_CON::Close() { - return true; -} - -Bit16u device_CON::GetInformation(void) { - Bit16u head=mem_readw(BIOS_KEYBOARD_BUFFER_HEAD); - Bit16u tail=mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); - - if ((head==tail) && !readcache) return 0x80D3; /* No Key Available */ - if (readcache || real_readw(0x40,head)) return 0x8093; /* Key Available */ - - /* remove the zero from keyboard buffer */ - Bit16u start=mem_readw(BIOS_KEYBOARD_BUFFER_START); - Bit16u end =mem_readw(BIOS_KEYBOARD_BUFFER_END); - head+=2; - if (head>=end) head=start; - mem_writew(BIOS_KEYBOARD_BUFFER_HEAD,head); - return 0x80D3; /* No Key Available */ -} - -device_CON::device_CON() { - SetName("CON"); - readcache=0; - lastwrite=0; - ansi.enabled=false; - ansi.attr=0x7; - ansi.ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); //should be updated once set/reset mode is implemented - ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1; - ansi.saverow=0; - ansi.savecol=0; - ansi.warned=false; - ClearAnsi(); -} - -void device_CON::ClearAnsi(void){ - for(Bit8u i=0; icount) { + reg_ah=0; + CALLBACK_RunRealInt(0x16); + switch(reg_al) { + case 13: + data[count++]=0x0D; +// if (*size>count) data[count++]=0x0A; +// else cache=0x0A; + *size=count; + reg_ax=oldax; + return true; + default: + data[count++]=reg_al; + break; + case 0: + data[count++]=reg_al; + if (*size>count) data[count++]=reg_ah; + else cache=reg_ah; + break; + } + } + *size=count; + reg_ax=oldax; + return true; +} + +extern void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page); +bool device_CON::Write(Bit8u * data,Bit16u * size) { +//TODO Hack a way to call int 0x10 + Bit16u oldax=reg_ax;Bit16u oldbx=reg_bx; + Bit16u count=0; + while (*size>count) { +/* + reg_al=data[count]; + reg_ah=0x0e; + reg_bx=0x0007; + CALLBACK_RunRealInt(0x10); +*/ + INT10_TeletypeOutput(data[count],7,false,0); + count++; + } + *size=count; +// reg_ax=oldax;reg_bx=oldbx; + return true; +} + +bool device_CON::Seek(Bit32u * pos,Bit32u type) { + return false; +} + +bool device_CON::Close() { + return false; +} + +Bit16u device_CON::GetInformation(void) { + Bit16u head=mem_readw(BIOS_KEYBOARD_BUFFER_HEAD); + Bit16u tail=mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); + + if ((head==tail) && !cache) return 0x80D3; /* No Key Available */ + return 0x8093; /* Key Available */ +}; + + +device_CON::device_CON() { + name="CON"; + cache=0; +} + diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index b69066f..4a93f32 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.cpp @@ -1,1160 +1,790 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos.cpp,v 1.117 2009/04/16 12:16:52 qbix79 Exp $ */ - -#include -#include -#include -#include -#include "dosbox.h" -#include "bios.h" -#include "mem.h" -#include "callback.h" -#include "regs.h" -#include "dos_inc.h" -#include "setup.h" -#include "support.h" -#include "serialport.h" - -DOS_Block dos; -DOS_InfoBlock dos_infoblock; - -#define DOS_COPYBUFSIZE 0x10000 -Bit8u dos_copybuf[DOS_COPYBUFSIZE]; - -void DOS_SetError(Bit16u code) { - dos.errorcode=code; -} - -#define DATA_TRANSFERS_TAKE_CYCLES 1 -#ifdef DATA_TRANSFERS_TAKE_CYCLES -#include "cpu.h" -static inline void modify_cycles(Bits value) { - if((4*value+5) < CPU_Cycles) { - CPU_Cycles -= 4*value; - CPU_IODelayRemoved += 4*value; - } else { - CPU_IODelayRemoved += CPU_Cycles/*-5*/; //don't want to mess with negative - CPU_Cycles = 5; - } -} -#else -static inline void modify_cycles(Bits /* value */) { - return; -} -#endif - -#define DOSNAMEBUF 256 -static Bitu DOS_21Handler(void) { - if (((reg_ah != 0x50) && (reg_ah != 0x51) && (reg_ah != 0x62) && (reg_ah != 0x64)) && (reg_ah<0x6c)) { - DOS_PSP psp(dos.psp()); - psp.SetStack(RealMake(SegValue(ss),reg_sp-18)); - } - - char name1[DOSNAMEBUF+2+DOS_NAMELENGTH_ASCII]; - char name2[DOSNAMEBUF+2+DOS_NAMELENGTH_ASCII]; - switch (reg_ah) { - case 0x01: /* Read character from STDIN, with echo */ - { - Bit8u c;Bit16u n=1; - dos.echo=true; - DOS_ReadFile(STDIN,&c,&n); - reg_al=c; - dos.echo=false; - } - break; - case 0x02: /* Write character to STDOUT */ - { - Bit8u c=reg_dl;Bit16u n=1; - DOS_WriteFile(STDOUT,&c,&n); - } - break; - case 0x03: /* Read character from STDAUX */ - { - Bit16u port = real_readw(0x40,0); - if(port!=0 && serialports[0]) { - Bit8u status; - // RTS/DTR on - IO_WriteB(port+4,0x3); - serialports[0]->Getchar(®_al, &status, true, 0xFFFFFFFF); - } - } - break; - case 0x04: /* Write Character to STDAUX */ - { - Bit16u port = real_readw(0x40,0); - if(port!=0 && serialports[0]) { - // RTS/DTR on - IO_WriteB(port+4,0x3); - serialports[0]->Putchar(reg_dl,true,true, 0xFFFFFFFF); - // RTS off - IO_WriteB(port+4,0x1); - } - } - break; - case 0x05: /* Write Character to PRINTER */ - E_Exit("DOS:Unhandled call %02X",reg_ah); - break; - case 0x06: /* Direct Console Output / Input */ - switch (reg_dl) { - case 0xFF: /* Input */ - { -//TODO Make this better according to standards - if (!DOS_GetSTDINStatus()) { - reg_al=0; - CALLBACK_SZF(true); - break; - } - Bit8u c;Bit16u n=1; - DOS_ReadFile(STDIN,&c,&n); - reg_al=c; - CALLBACK_SZF(false); - break; - } - default: - { - Bit8u c = reg_dl;Bit16u n = 1; - DOS_WriteFile(STDOUT,&c,&n); - reg_al = reg_dl; - } - break; - }; - break; - case 0x07: /* Character Input, without echo */ - { - Bit8u c;Bit16u n=1; - DOS_ReadFile (STDIN,&c,&n); - reg_al=c; - break; - }; - case 0x08: /* Direct Character Input, without echo (checks for breaks officially :)*/ - { - Bit8u c;Bit16u n=1; - DOS_ReadFile (STDIN,&c,&n); - reg_al=c; - break; - }; - case 0x09: /* Write string to STDOUT */ - { - Bit8u c;Bit16u n=1; - PhysPt buf=SegPhys(ds)+reg_dx; - while ((c=mem_readb(buf++))!='$') { - DOS_WriteFile(STDOUT,&c,&n); - } - } - break; - case 0x0a: /* Buffered Input */ - { - //TODO ADD Break checkin in STDIN but can't care that much for it - PhysPt data=SegPhys(ds)+reg_dx; - Bit8u free=mem_readb(data); - Bit8u read=0;Bit8u c;Bit16u n=1; - if (!free) break; - for(;;) { - DOS_ReadFile(STDIN,&c,&n); - if (c == 8) { // Backspace - if (read) { //Something to backspace. - // STDOUT treats backspace as non-destructive. - DOS_WriteFile(STDOUT,&c,&n); - c = ' '; DOS_WriteFile(STDOUT,&c,&n); - c = 8; DOS_WriteFile(STDOUT,&c,&n); - --read; - } - continue; - } - if (read >= free) { // Keyboard buffer full - Bit8u bell = 7; - DOS_WriteFile(STDOUT, &bell, &n); - continue; - } - DOS_WriteFile(STDOUT,&c,&n); - mem_writeb(data+read+2,c); - if (c==13) - break; - read++; - }; - mem_writeb(data+1,read); - break; - }; - case 0x0b: /* Get STDIN Status */ - if (!DOS_GetSTDINStatus()) {reg_al=0x00;} - else {reg_al=0xFF;} - break; - case 0x0c: /* Flush Buffer and read STDIN call */ - { - /* flush STDIN-buffer */ - Bit8u c;Bit16u n; - while (DOS_GetSTDINStatus()) { - n=1; DOS_ReadFile(STDIN,&c,&n); - } - switch (reg_al) { - case 0x1: - case 0x6: - case 0x7: - case 0x8: - case 0xa: - { - Bit8u oldah=reg_ah; - reg_ah=reg_al; - DOS_21Handler(); - reg_ah=oldah; - } - break; - default: -// LOG_ERROR("DOS:0C:Illegal Flush STDIN Buffer call %d",reg_al); - reg_al=0; - break; - } - } - break; -//TODO Find out the values for when reg_al!=0 -//TODO Hope this doesn't do anything special - case 0x0d: /* Disk Reset */ -//Sure let's reset a virtual disk - break; - case 0x0e: /* Select Default Drive */ - DOS_SetDefaultDrive(reg_dl); - reg_al=DOS_DRIVES; - break; - case 0x0f: /* Open File using FCB */ - if(DOS_FCBOpen(SegValue(ds),reg_dx)){ - reg_al=0; - }else{ - reg_al=0xff; - } - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x0f FCB-fileopen used, result:al=%d",reg_al); - break; - case 0x10: /* Close File using FCB */ - if(DOS_FCBClose(SegValue(ds),reg_dx)){ - reg_al=0; - }else{ - reg_al=0xff; - } - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x10 FCB-fileclose used, result:al=%d",reg_al); - break; - case 0x11: /* Find First Matching File using FCB */ - if(DOS_FCBFindFirst(SegValue(ds),reg_dx)) reg_al = 0x00; - else reg_al = 0xFF; - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x11 FCB-FindFirst used, result:al=%d",reg_al); - break; - case 0x12: /* Find Next Matching File using FCB */ - if(DOS_FCBFindNext(SegValue(ds),reg_dx)) reg_al = 0x00; - else reg_al = 0xFF; - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x12 FCB-FindNext used, result:al=%d",reg_al); - break; - case 0x13: /* Delete File using FCB */ - if (DOS_FCBDeleteFile(SegValue(ds),reg_dx)) reg_al = 0x00; - else reg_al = 0xFF; - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x16 FCB-Delete used, result:al=%d",reg_al); - break; - case 0x14: /* Sequential read from FCB */ - reg_al = DOS_FCBRead(SegValue(ds),reg_dx,0); - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x14 FCB-Read used, result:al=%d",reg_al); - break; - case 0x15: /* Sequential write to FCB */ - reg_al=DOS_FCBWrite(SegValue(ds),reg_dx,0); - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x15 FCB-Write used, result:al=%d",reg_al); - break; - case 0x16: /* Create or truncate file using FCB */ - if (DOS_FCBCreate(SegValue(ds),reg_dx)) reg_al = 0x00; - else reg_al = 0xFF; - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x16 FCB-Create used, result:al=%d",reg_al); - break; - case 0x17: /* Rename file using FCB */ - if (DOS_FCBRenameFile(SegValue(ds),reg_dx)) reg_al = 0x00; - else reg_al = 0xFF; - break; - case 0x1b: /* Get allocation info for default drive */ - if (!DOS_GetAllocationInfo(0,®_cx,®_al,®_dx)) reg_al=0xff; - break; - case 0x1c: /* Get allocation info for specific drive */ - if (!DOS_GetAllocationInfo(reg_dl,®_cx,®_al,®_dx)) reg_al=0xff; - break; - case 0x21: /* Read random record from FCB */ - reg_al = DOS_FCBRandomRead(SegValue(ds),reg_dx,1,true); - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x21 FCB-Random read used, result:al=%d",reg_al); - break; - case 0x22: /* Write random record to FCB */ - reg_al=DOS_FCBRandomWrite(SegValue(ds),reg_dx,1,true); - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x22 FCB-Random write used, result:al=%d",reg_al); - break; - case 0x23: /* Get file size for FCB */ - if (DOS_FCBGetFileSize(SegValue(ds),reg_dx)) reg_al = 0x00; - else reg_al = 0xFF; - break; - case 0x24: /* Set Random Record number for FCB */ - DOS_FCBSetRandomRecord(SegValue(ds),reg_dx); - break; - case 0x27: /* Random block read from FCB */ - reg_al = DOS_FCBRandomRead(SegValue(ds),reg_dx,reg_cx,false); - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x27 FCB-Random(block) read used, result:al=%d",reg_al); - break; - case 0x28: /* Random Block write to FCB */ - reg_al=DOS_FCBRandomWrite(SegValue(ds),reg_dx,reg_cx,false); - LOG(LOG_FCB,LOG_NORMAL)("DOS:0x28 FCB-Random(block) write used, result:al=%d",reg_al); - break; - case 0x29: /* Parse filename into FCB */ - { - Bit8u difference; - char string[1024]; - MEM_StrCopy(SegPhys(ds)+reg_si,string,1023); // 1024 toasts the stack - reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference); - reg_si+=difference; - } - LOG(LOG_FCB,LOG_NORMAL)("DOS:29:FCB Parse Filename, result:al=%d",reg_al); - break; - case 0x19: /* Get current default drive */ - reg_al=DOS_GetDefaultDrive(); - break; - case 0x1a: /* Set Disk Transfer Area Address */ - dos.dta(RealMakeSeg(ds,reg_dx)); - break; - case 0x25: /* Set Interrupt Vector */ - RealSetVec(reg_al,RealMakeSeg(ds,reg_dx)); - break; - case 0x26: /* Create new PSP */ - DOS_NewPSP(reg_dx,DOS_PSP(dos.psp()).GetSize()); - break; - case 0x2a: /* Get System Date */ - { - int a = (14 - dos.date.month)/12; - int y = dos.date.year - a; - int m = dos.date.month + 12*a - 2; - reg_al=(dos.date.day+y+(y/4)-(y/100)+(y/400)+(31*m)/12) % 7; - reg_cx=dos.date.year; - reg_dh=dos.date.month; - reg_dl=dos.date.day; - } - break; - case 0x2b: /* Set System Date */ - if (reg_cx<1980) { reg_al=0xff;break;} - if ((reg_dh>12) || (reg_dh==0)) { reg_al=0xff;break;} - if ((reg_dl>31) || (reg_dl==0)) { reg_al=0xff;break;} - dos.date.year=reg_cx; - dos.date.month=reg_dh; - dos.date.day=reg_dl; - reg_al=0; - break; - case 0x2c: /* Get System Time */ -//TODO Get time through bios calls date is fixed - { -/* Calculate how many miliseconds have passed */ - Bitu ticks=5*mem_readd(BIOS_TIMER); - ticks = ((ticks / 59659u) << 16) + ((ticks % 59659u) << 16) / 59659u; - Bitu seconds=(ticks/100); - reg_ch=(Bit8u)(seconds/3600); - reg_cl=(Bit8u)((seconds % 3600)/60); - reg_dh=(Bit8u)(seconds % 60); - reg_dl=(Bit8u)(ticks % 100); - } - break; - case 0x2d: /* Set System Time */ - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Set System Time not supported"); - //Check input parameters nonetheless - if( reg_ch > 23 || reg_cl > 59 || reg_dh > 59 || reg_dl > 99 ) - reg_al = 0xff; - else reg_al = 0; - break; - case 0x2e: /* Set Verify flag */ - dos.verify=(reg_al==1); - break; - case 0x2f: /* Get Disk Transfer Area */ - SegSet16(es,RealSeg(dos.dta())); - reg_bx=RealOff(dos.dta()); - break; - case 0x30: /* Get DOS Version */ - if (reg_al==0) reg_bh=0xFF; /* Fake Microsoft DOS */ - if (reg_al==1) reg_bh=0x10; /* DOS is in HMA */ - reg_al=dos.version.major; - reg_ah=dos.version.minor; - /* Serialnumber */ - reg_bl=0x00; - reg_cx=0x0000; - break; - case 0x31: /* Terminate and stay resident */ - //TODO First get normal files executing - // Important: This service does not set the carry flag! - DOS_ResizeMemory(dos.psp(),®_dx); - DOS_Terminate(true,reg_al); - dos.return_mode=RETURN_TSR; - break; - case 0x1f: /* Get drive parameter block for default drive */ - case 0x32: /* Get drive parameter block for specific drive */ - { /* Officially a dpb should be returned as well. The disk detection part is implemented */ - Bitu drive=reg_dl;if(!drive || reg_ah==0x1f) drive = DOS_GetDefaultDrive();else drive--; - if(Drives[drive]) { - reg_al = 0x00; - SegSet16(ds,dos.tables.dpb); - reg_bx = drive;//Faking only the first entry (that is the driveletter) - LOG(LOG_DOSMISC,LOG_ERROR)("Get drive parameter block."); - } else { - reg_al=0xff; - } - } - break; - case 0x33: /* Extended Break Checking */ - switch (reg_al) { - case 0:reg_dl=dos.breakcheck;break; /* Get the breakcheck flag */ - case 1:dos.breakcheck=(reg_dl>0);break; /* Set the breakcheck flag */ - case 2:{bool old=dos.breakcheck;dos.breakcheck=(reg_dl>0);reg_dl=old;}break; - case 3: /* Get cpsw */ - /* Fallthrough */ - case 4: /* Set cpsw */ - LOG(LOG_DOSMISC,LOG_ERROR)("Someone playing with cpsw %x",reg_ax); - break; - case 5:reg_dl=3;break;//TODO should be z /* Always boot from c: :) */ - case 6: /* Get true version number */ - reg_bl=dos.version.major; - reg_bh=dos.version.minor; - reg_dl=dos.version.revision; - reg_dh=0x10; /* Dos in HMA */ - break; - default: - E_Exit("DOS:Illegal 0x33 Call %2X",reg_al); - } - break; - case 0x34: /* Get INDos Flag */ - SegSet16(es,DOS_SDA_SEG); - reg_bx=DOS_SDA_OFS + 0x01; - break; - case 0x35: /* Get interrupt vector */ - reg_bx=real_readw(0,((Bit16u)reg_al)*4); - SegSet16(es,real_readw(0,((Bit16u)reg_al)*4+2)); - break; - case 0x36: /* Get Free Disk Space */ - { - Bit16u bytes,clusters,free; - Bit8u sectors; - if (DOS_GetFreeDiskSpace(reg_dl,&bytes,§ors,&clusters,&free)) { - reg_ax=sectors; - reg_bx=free; - reg_cx=bytes; - reg_dx=clusters; - } else { - Bit8u drive=reg_dl; - if (drive==0) drive=DOS_GetDefaultDrive(); - else drive--; - if (drive<2) { - // floppy drive, non-present drivesdisks issue floppy check through int24 - // (critical error handler); needed for Mixed up Mother Goose (hook) -// CALLBACK_RunRealInt(0x24); - } - reg_ax=0xffff; // invalid drive specified - } - } - break; - case 0x37: /* Get/Set Switch char Get/Set Availdev thing */ -//TODO Give errors for these functions to see if anyone actually uses this shit- - switch (reg_al) { - case 0: - reg_al=0;reg_dl=0x2f;break; /* always return '/' like dos 5.0+ */ - case 1: - reg_al=0;break; - case 2: - reg_al=0;reg_dl=0x2f;break; - case 3: - reg_al=0;break; - }; - LOG(LOG_MISC,LOG_ERROR)("DOS:0x37:Call for not supported switchchar"); - break; - case 0x38: /* Set Country Code */ - if (reg_al==0) { /* Get country specidic information */ - PhysPt dest = SegPhys(ds)+reg_dx; - MEM_BlockWrite(dest,dos.tables.country,0x18); - reg_ax = reg_bx = 0x01; - CALLBACK_SCF(false); - break; - } else { /* Set country code */ - LOG(LOG_MISC,LOG_ERROR)("DOS:Setting country code not supported"); - } - CALLBACK_SCF(true); - break; - case 0x39: /* MKDIR Create directory */ - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - if (DOS_MakeDir(name1)) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x3a: /* RMDIR Remove directory */ - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - if (DOS_RemoveDir(name1)) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - LOG(LOG_MISC,LOG_NORMAL)("Remove dir failed on %s with error %X",name1,dos.errorcode); - } - break; - case 0x3b: /* CHDIR Set current directory */ - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - if (DOS_ChangeDir(name1)) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x3c: /* CREATE Create of truncate file */ - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - if (DOS_CreateFile(name1,reg_cx,®_ax)) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x3d: /* OPEN Open existing file */ - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - if (DOS_OpenFile(name1,reg_al,®_ax)) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x3e: /* CLOSE Close file */ - if (DOS_CloseFile(reg_bx)) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x3f: /* READ Read from file or device */ - { - Bit16u toread=reg_cx; - dos.echo=true; - if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) { - MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread); - reg_ax=toread; - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - modify_cycles(reg_ax); - dos.echo=false; - break; - } - case 0x40: /* WRITE Write to file or device */ - { - Bit16u towrite=reg_cx; - MEM_BlockRead(SegPhys(ds)+reg_dx,dos_copybuf,towrite); - if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) { - reg_ax=towrite; - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - modify_cycles(reg_ax); - break; - }; - case 0x41: /* UNLINK Delete file */ - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - if (DOS_UnlinkFile(name1)) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x42: /* LSEEK Set current file position */ - { - Bit32u pos=(reg_cx<<16) + reg_dx; - if (DOS_SeekFile(reg_bx,&pos,reg_al)) { - reg_dx=(Bit16u)(pos >> 16); - reg_ax=(Bit16u)(pos & 0xFFFF); - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - } - case 0x43: /* Get/Set file attributes */ - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - switch (reg_al) { - case 0x00: /* Get */ - { - Bit16u attr_val=reg_cx; - if (DOS_GetFileAttr(name1,&attr_val)) { - reg_cx=attr_val; - reg_ax=attr_val; /* Undocumented */ - CALLBACK_SCF(false); - } else { - CALLBACK_SCF(true); - reg_ax=dos.errorcode; - } - break; - }; - case 0x01: /* Set */ - LOG(LOG_MISC,LOG_ERROR)("DOS:Set File Attributes for %s not supported",name1); - if (DOS_SetFileAttr(name1,reg_cx)) { - reg_ax=0x202; /* ax destroyed */ - CALLBACK_SCF(false); - } else { - CALLBACK_SCF(true); - reg_ax=dos.errorcode; - } - break; - default: - LOG(LOG_MISC,LOG_ERROR)("DOS:0x43:Illegal subfunction %2X",reg_al); - reg_ax=1; - CALLBACK_SCF(true); - break; - } - break; - case 0x44: /* IOCTL Functions */ - if (DOS_IOCTL()) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x45: /* DUP Duplicate file handle */ - if (DOS_DuplicateEntry(reg_bx,®_ax)) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x46: /* DUP2,FORCEDUP Force duplicate file handle */ - if (DOS_ForceDuplicateEntry(reg_bx,reg_cx)) { - reg_ax=reg_cx; //Not all sources agree on it. - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x47: /* CWD Get current directory */ - if (DOS_GetCurrentDir(reg_dl,name1)) { - MEM_BlockWrite(SegPhys(ds)+reg_si,name1,(Bitu)(strlen(name1)+1)); - reg_ax=0x0100; - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x48: /* Allocate memory */ - { - Bit16u size=reg_bx;Bit16u seg; - if (DOS_AllocateMemory(&seg,&size)) { - reg_ax=seg; - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - reg_bx=size; - CALLBACK_SCF(true); - } - break; - } - case 0x49: /* Free memory */ - if (DOS_FreeMemory(SegValue(es))) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x4a: /* Resize memory block */ - { - Bit16u size=reg_bx; - if (DOS_ResizeMemory(SegValue(es),&size)) { - reg_ax=SegValue(es); - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - reg_bx=size; - CALLBACK_SCF(true); - } - break; - } - case 0x4b: /* EXEC Load and/or execute program */ - { - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - LOG(LOG_EXEC,LOG_ERROR)("Execute %s %d",name1,reg_al); - if (!DOS_Execute(name1,SegPhys(es)+reg_bx,reg_al)) { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - } - break; -//TODO Check for use of execution state AL=5 - case 0x00: - reg_ax=0x4c00; /* Terminate Program */ - case 0x4c: /* EXIT Terminate with return code */ - { - if (DOS_Terminate(false,reg_al)) { - /* This can't ever return false normally */ - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - } - case 0x4d: /* Get Return code */ - reg_al=dos.return_code;/* Officially read from SDA and clear when read */ - reg_ah=dos.return_mode; - break; - case 0x4e: /* FINDFIRST Find first matching file */ - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - if (DOS_FindFirst(name1,reg_cx)) { - CALLBACK_SCF(false); - reg_ax=0; /* Undocumented */ - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - }; - break; - case 0x4f: /* FINDNEXT Find next matching file */ - if (DOS_FindNext()) { - CALLBACK_SCF(false); - /* reg_ax=0xffff;*/ /* Undocumented */ - reg_ax=0; /* Undocumented:Qbix Willy beamish */ - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - }; - break; - case 0x50: /* Set current PSP */ - dos.psp(reg_bx); - break; - case 0x51: /* Get current PSP */ - reg_bx=dos.psp(); - break; - case 0x52: { /* Get list of lists */ - RealPt addr=dos_infoblock.GetPointer(); - SegSet16(es,RealSeg(addr)); - reg_bx=RealOff(addr); - LOG(LOG_DOSMISC,LOG_NORMAL)("Call is made for list of lists - let's hope for the best"); - break; } -//TODO Think hard how shit this is gonna be -//And will any game ever use this :) - case 0x53: /* Translate BIOS parameter block to drive parameter block */ - E_Exit("Unhandled Dos 21 call %02X",reg_ah); - break; - case 0x54: /* Get verify flag */ - reg_al=dos.verify?1:0; - break; - case 0x55: /* Create Child PSP*/ - DOS_ChildPSP(reg_dx,reg_si); - dos.psp(reg_dx); - break; - case 0x56: /* RENAME Rename file */ - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - MEM_StrCopy(SegPhys(es)+reg_di,name2,DOSNAMEBUF); - if (DOS_Rename(name1,name2)) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x57: /* Get/Set File's Date and Time */ - if (reg_al==0x00) { - if (DOS_GetFileDate(reg_bx,®_cx,®_dx)) { - CALLBACK_SCF(false); - } else { - CALLBACK_SCF(true); - } - } else if (reg_al==0x01) { - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:57:Set File Date Time Faked"); - CALLBACK_SCF(false); - } else { - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:57:Unsupported subtion %X",reg_al); - } - break; - case 0x58: /* Get/Set Memory allocation strategy */ - switch (reg_al) { - case 0: /* Get Strategy */ - reg_ax=DOS_GetMemAllocStrategy(); - break; - case 1: /* Set Strategy */ - if (DOS_SetMemAllocStrategy(reg_bx)) CALLBACK_SCF(false); - else { - reg_ax=1; - CALLBACK_SCF(true); - } - break; - case 2: /* Get UMB Link Status */ - reg_al=dos_infoblock.GetUMBChainState()&1; - CALLBACK_SCF(false); - break; - case 3: /* Set UMB Link Status */ - if (DOS_LinkUMBsToMemChain(reg_bx)) CALLBACK_SCF(false); - else { - reg_ax=1; - CALLBACK_SCF(true); - } - break; - default: - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:58:Not Supported Set//Get memory allocation call %X",reg_al); - } - break; - case 0x59: /* Get Extended error information */ - reg_ax=dos.errorcode; - reg_bh=0; //Unkown error class - reg_bl=1; //Retry retry retry - reg_ch=0; //Unkown error locus - break; - case 0x5a: /* Create temporary file */ - { - Bit16u handle; - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - if (DOS_CreateTempFile(name1,&handle)) { - reg_ax=handle; - MEM_BlockWrite(SegPhys(ds)+reg_dx,name1,(Bitu)(strlen(name1)+1)); - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - } - break; - case 0x5b: /* Create new file */ - { - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - Bit16u handle; - if (DOS_OpenFile(name1,0,&handle)) { - DOS_CloseFile(handle); - DOS_SetError(DOSERR_FILE_ALREADY_EXISTS); - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - break; - } - if (DOS_CreateFile(name1,reg_cx,&handle)) { - reg_ax=handle; - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - } - case 0x5c: /* FLOCK File region locking */ - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - reg_ax = dos.errorcode; - CALLBACK_SCF(true); - break; - case 0x5d: /* Network Functions */ - if(reg_al == 0x06) { - SegSet16(ds,DOS_SDA_SEG); - reg_si = DOS_SDA_OFS; - reg_cx = 0x80; // swap if in dos - reg_dx = 0x1a; // swap always - LOG(LOG_DOSMISC,LOG_ERROR)("Get SDA, Let's hope for the best!"); - } - break; - case 0x5f: /* Network redirection */ - reg_ax=0x0001; //Failing it - CALLBACK_SCF(true); - break; - case 0x60: /* Canonicalize filename or path */ - MEM_StrCopy(SegPhys(ds)+reg_si,name1,DOSNAMEBUF); - if (DOS_Canonicalize(name1,name2)) { - MEM_BlockWrite(SegPhys(es)+reg_di,name2,(Bitu)(strlen(name2)+1)); - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x62: /* Get Current PSP Address */ - reg_bx=dos.psp(); - break; - case 0x63: /* DOUBLE BYTE CHARACTER SET */ - if(reg_al == 0) { - SegSet16(ds,RealSeg(dos.tables.dbcs)); - reg_si=RealOff(dos.tables.dbcs); - reg_al = 0; - CALLBACK_SCF(false); //undocumented - } else reg_al = 0xff; //Doesn't officially touch carry flag - break; - case 0x64: /* Set device driver lookahead flag */ - LOG(LOG_DOSMISC,LOG_NORMAL)("set driver look ahead flag"); - break; - case 0x65: /* Get extented country information and a lot of other useless shit*/ - { /* Todo maybe fully support this for now we set it standard for USA */ - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:65:Extended country information call %X",reg_ax); - if((reg_al <= 0x07) && (reg_cx < 0x05)) { - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - CALLBACK_SCF(true); - break; - } - Bitu len = 0; /* For 0x21 and 0x22 */ - PhysPt data=SegPhys(es)+reg_di; - switch (reg_al) { - case 0x01: - mem_writeb(data + 0x00,reg_al); - mem_writew(data + 0x01,0x26); - mem_writew(data + 0x03,1); - if(reg_cx > 0x06 ) mem_writew(data+0x05,dos.loaded_codepage); - if(reg_cx > 0x08 ) { - Bitu amount = (reg_cx>=0x29)?0x22:(reg_cx-7); - MEM_BlockWrite(data + 0x07,dos.tables.country,amount); - reg_cx=(reg_cx>=0x29)?0x29:reg_cx; - } - CALLBACK_SCF(false); - break; - case 0x05: // Get pointer to filename terminator table - mem_writeb(data + 0x00, reg_al); - mem_writed(data + 0x01, dos.tables.filenamechar); - reg_cx = 5; - CALLBACK_SCF(false); - break; - case 0x06: // Get pointer to collating sequence table - mem_writeb(data + 0x00, reg_al); - mem_writed(data + 0x01, dos.tables.collatingseq); - reg_cx = 5; - CALLBACK_SCF(false); - break; - case 0x02: // Get pointer to uppercase table - case 0x03: // Get pointer to lowercase table - case 0x04: // Get pointer to filename uppercase table - case 0x07: // Get pointer to double byte char set table - mem_writeb(data + 0x00, reg_al); - mem_writed(data + 0x01, dos.tables.dbcs); //used to be 0 - reg_cx = 5; - CALLBACK_SCF(false); - break; - case 0x20: /* Capitalize Character */ - { - int in = reg_dl; - int out = toupper(in); - reg_dl = out; - } - CALLBACK_SCF(false); - break; - case 0x21: /* Capitalize String (cx=length) */ - case 0x22: /* Capatilize ASCIZ string */ - data = SegPhys(ds) + reg_dx; - if(reg_al == 0x21) len = reg_cx; - else len = mem_strlen(data); /* Is limited to 1024 */ - - if(len > DOS_COPYBUFSIZE - 1) E_Exit("DOS:0x65 Buffer overflow"); - if(len) { - MEM_BlockRead(data,dos_copybuf,len); - dos_copybuf[len] = 0; - //No upcase as String(0x21) might be multiple asciz strings - for(Bitu count = 0; count < len;count++) - dos_copybuf[count] = toupper(*reinterpret_cast(dos_copybuf+count)); - MEM_BlockWrite(data,dos_copybuf,len); - } - CALLBACK_SCF(false); - break; - default: - E_Exit("DOS:0x65:Unhandled country information call %2X",reg_al); - }; - break; - } - case 0x66: /* Get/Set global code page table */ - if (reg_al==1) { - LOG(LOG_DOSMISC,LOG_ERROR)("Getting global code page table"); - reg_bx=reg_dx=dos.loaded_codepage; - CALLBACK_SCF(false); - break; - } - LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Setting code page table is not supported"); - break; - case 0x67: /* Set handle count */ - /* Weird call to increase amount of file handles needs to allocate memory if >20 */ - { - DOS_PSP psp(dos.psp()); - psp.SetNumFiles(reg_bx); - CALLBACK_SCF(false); - break; - }; - case 0x68: /* FFLUSH Commit file */ - if(DOS_FlushFile(reg_bl)) { - CALLBACK_SCF(false); - } else { - reg_ax = dos.errorcode; - CALLBACK_SCF(true); - } - break; - case 0x69: /* Get/Set disk serial number */ - { - switch(reg_al) { - case 0x00: /* Get */ - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Get Disk serial number"); - CALLBACK_SCF(true); - break; - case 0x01: - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Set Disk serial number"); - default: - E_Exit("DOS:Illegal Get Serial Number call %2X",reg_al); - } - break; - } - case 0x6c: /* Extended Open/Create */ - MEM_StrCopy(SegPhys(ds)+reg_si,name1,DOSNAMEBUF); - if (DOS_OpenFileExtended(name1,reg_bx,reg_cx,reg_dx,®_ax,®_cx)) { - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - break; - - case 0x71: /* Unknown probably 4dos detection */ - reg_ax=0x7100; - CALLBACK_SCF(true); - LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Windows long file name support call %2X",reg_al); - break; - - case 0xE0: - case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */ - case 0x1d: /* NULL Function for CP/M compatibility or Extended rename FCB */ - case 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */ - case 0x20: /* NULL Function for CP/M compatibility or Extended rename FCB */ - case 0x6b: /* NULL Function */ - case 0x61: /* UNUSED */ - case 0xEF: /* Used in Ancient Art Of War CGA */ - case 0x5e: /* More Network Functions */ - default: - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Unhandled call %02X al=%02X. Set al to default of 0",reg_ah,reg_al); - reg_al=0x00; /* default value */ - break; - }; - return CBRET_NONE; -} - - -static Bitu DOS_20Handler(void) { - reg_ax=0x4c00; - DOS_21Handler(); - return CBRET_NONE; -} - -static Bitu DOS_27Handler(void) { - // Terminate & stay resident - Bit16u para = (reg_dx/16)+((reg_dx % 16)>0); - if (DOS_ResizeMemory(dos.psp(),¶)) DOS_Terminate(true,0); - return CBRET_NONE; -} - -static Bitu DOS_25Handler(void) { - if(Drives[reg_al]==0){ - reg_ax=0x8002; - SETFLAGBIT(CF,true); - }else{ - SETFLAGBIT(CF,false); - if((reg_cx != 1) ||(reg_dx != 1)) - LOG(LOG_DOSMISC,LOG_NORMAL)("int 25 called but not as diskdetection drive %X",reg_al); - - reg_ax=0; - } - return CBRET_NONE; -} -static Bitu DOS_26Handler(void) { - LOG(LOG_DOSMISC,LOG_NORMAL)("int 26 called: hope for the best!"); - if(Drives[reg_al]==0){ - reg_ax=0x8002; - SETFLAGBIT(CF,true); - }else{ - SETFLAGBIT(CF,false); - reg_ax=0; - } - return CBRET_NONE; -} - - -class DOS:public Module_base{ -private: - CALLBACK_HandlerObject callback[7]; -public: - DOS(Section* configuration):Module_base(configuration){ - callback[0].Install(DOS_20Handler,CB_IRET,"DOS Int 20"); - callback[0].Set_RealVec(0x20); - - callback[1].Install(DOS_21Handler,CB_INT21,"DOS Int 21"); - callback[1].Set_RealVec(0x21); - //Pseudo code for int 21 - // sti - // callback - // iret - // retf <- int 21 4c jumps here to mimic a retf Cyber - - callback[2].Install(DOS_25Handler,CB_RETF,"DOS Int 25"); - callback[2].Set_RealVec(0x25); - - callback[3].Install(DOS_26Handler,CB_RETF,"DOS Int 26"); - callback[3].Set_RealVec(0x26); - - callback[4].Install(DOS_27Handler,CB_IRET,"DOS Int 27"); - callback[4].Set_RealVec(0x27); - - callback[5].Install(NULL,CB_IRET,"DOS Int 28"); - callback[5].Set_RealVec(0x28); - - callback[6].Install(NULL,CB_INT29,"CON Output Int 29"); - callback[6].Set_RealVec(0x29); - // pseudocode for CB_INT29: - // push ax - // mov ah, 0x0e - // int 0x10 - // pop ax - // iret - - DOS_SetupFiles(); /* Setup system File tables */ - DOS_SetupDevices(); /* Setup dos devices */ - DOS_SetupTables(); - DOS_SetupMemory(); /* Setup first MCB */ - DOS_SetupPrograms(); - DOS_SetupMisc(); /* Some additional dos interrupts */ - DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetDrive(25); /* Else the next call gives a warning. */ - DOS_SetDefaultDrive(25); - - dos.version.major=5; - dos.version.minor=0; - - /* Setup time and date */ - time_t curtime;struct tm *loctime; - curtime = time (NULL);loctime = localtime (&curtime); - - dos.date.day=(Bit8u)loctime->tm_mday; - dos.date.month=(Bit8u)loctime->tm_mon+1; - dos.date.year=(Bit16u)loctime->tm_year+1900; - Bit32u ticks=(Bit32u)((loctime->tm_hour*3600+loctime->tm_min*60+loctime->tm_sec)*(float)PIT_TICK_RATE/65536.0); - mem_writed(BIOS_TIMER,ticks); - } - ~DOS(){ - for (Bit16u i=0;iAddDestroyFunction(&DOS_ShutDown,false); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include "dosbox.h" +#include "bios.h" +#include "mem.h" +#include "callback.h" +#include "regs.h" +#include "dos_inc.h" + +DOS_Block dos; +static Bit8u dos_copybuf[0x10000]; +static Bitu call_20,call_21,call_theend; + +void DOS_SetError(Bit16u code) { + dos.errorcode=code; +}; + + +#define DOSNAMEBUF 256 +static Bitu DOS_21Handler(void) { +//TODO KEYBOARD Check for break + char name1[DOSNAMEBUF+1]; + char name2[DOSNAMEBUF+1]; + switch (reg_ah) { + case 0x00: /* Terminate Program */ + E_Exit("DOS:Unhandled call %02X",reg_ah); + break; + case 0x01: /* Read character from STDIN, with echo */ + { + Bit8u c;Bit16u n=1; + DOS_ReadFile(STDIN,&c,&n); + reg_al=c; + DOS_WriteFile(STDOUT,&c,&n); + } + break; + case 0x02: /* Write character to STDOUT */ + { + Bit8u c=reg_dl;Bit16u n=1; + DOS_WriteFile(STDOUT,&c,&n); + } + break; + case 0x03: /* Read character from STDAUX */ + case 0x04: /* Write Character to STDAUX */ + case 0x05: /* Write Character to PRINTER */ + E_Exit("DOS:Unhandled call %02X",reg_ah); + break; + case 0x06: /* Direct Console Output / Input */ + switch (reg_dl) { + case 0xFF: /* Input */ + { +//TODO Make this better according to standards + if (!DOS_GetSTDINStatus()) { + CALLBACK_SZF(true); + break; + } + Bit8u c;Bit16u n=1; + DOS_ReadFile(STDIN,&c,&n); + reg_al=c; + CALLBACK_SZF(false); + break; + } + default: + { + Bit8u c=reg_dl;Bit16u n=1; + DOS_WriteFile(STDOUT,&c,&n); + } + break; + }; + break; + case 0x07: /* Character Input, without echo */ + { + Bit8u c;Bit16u n=1; + DOS_ReadFile (STDIN,&c,&n); + reg_al=c; + break; + }; + case 0x08: /* Direct Character Input, without echo */ + { + Bit8u c;Bit16u n=1; + DOS_ReadFile (STDIN,&c,&n); + reg_al=c; + break; + }; + case 0x09: /* Write string to STDOUT */ + { + Bit8u c;Bit16u n=1; + PhysOff buf=real_phys(Segs[ds].value,reg_dx); + while ((c=mem_readb(buf++))!='$') { + DOS_WriteFile(STDOUT,&c,&n); + } + } + break; + case 0x0a: /* Buffered Input */ + { + //TODO ADD Break checkin in STDIN but can't care that much for it + PhysOff data=real_phys(Segs[ds].value,reg_dx); + Bit8u free=mem_readb(data); + Bit8u read=0;Bit8u c;Bit16u n=1; + if (!free) break; + while (read12) || (reg_dh==0)) { reg_al=0xff;break;} + if ((reg_dl>31) || (reg_dl==0)) { reg_al=0xff;break;} + dos.date.year=reg_cx; + dos.date.month=reg_dh; + dos.date.day=reg_dl; + reg_al=0; + break; + case 0x2c: /* Get System Time */ +//TODO Get time through bios calls date is fixed + { + Bit32u ticks=mem_readd(BIOS_TIMER); + Bit32u seconds=(ticks*10)/182; + reg_ch=(Bit8u)(seconds/3600); + reg_cl=(Bit8u)(seconds % 3600)/60; + reg_dh=(Bit8u)(seconds % 60); + reg_dl=(Bit8u)(ticks % 19)*5; + } + break; + case 0x2d: /* Set System Time */ + LOG_DEBUG("DOS:Set System Time not supported"); + reg_al=0; /* Noone is changing system time */ + break; + case 0x2e: /* Set Verify flag */ + dos.verify=(reg_al==1); + break; + case 0x2f: /* Get Disk Transfer Area */ + SetSegment_16(es,RealSeg(dos.dta)); + reg_bx=RealOff(dos.dta); + break; + case 0x30: /* Get DOS Version */ + if (reg_al==0) reg_bh=0xFF; /* Fake Microsoft DOS */ + if (reg_al==1) reg_bh=0x10; /* DOS is in HMA */ + reg_al=dos.version.major; + reg_ah=dos.version.minor; + break; + case 0x31: /* Terminate and stay resident */ +//TODO First get normal files executing + DOS_ResizeMemory(dos.psp,®_dx); + if (DOS_Terminate(true)) { + dos.return_code=reg_al; + dos.return_mode=RETURN_TSR; + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x33: /* Extended Break Checking */ + switch (reg_al) { + case 0:reg_dl=dos.breakcheck;break; /* Get the breakcheck flag */ + case 1:dos.breakcheck=(reg_dl>0);break; /* Set the breakcheck flag */ + case 2:{bool old=dos.breakcheck;dos.breakcheck=(reg_dl>0);reg_dl=old;}break; + case 5:reg_dl=3;break; /* Always boot from c: :) */ + case 6: /* Get true version number */ + reg_bl=dos.version.major; + reg_bh=dos.version.minor; + reg_dl=dos.version.revision; + reg_dh=0x10; /* Dos in HMA */ + break; + default: + E_Exit("DOS:Illegal 0x33 Call %2X",reg_al); + } + break; + case 0x34: /* Get INDos Flag */ + SetSegment_16(es,RealSeg(dos.tables.indosflag)); + reg_bx=RealOff(dos.tables.indosflag); + break; + case 0x35: /* Get interrupt vector */ + reg_bx=real_readw(0,((Bit16u)reg_al)*4); + SetSegment_16(es,real_readw(0,((Bit16u)reg_al)*4+2)); + break; + case 0x36: /* Get Free Disk Space */ + { + Bit16u bytes,sectors,clusters,free; + if (DOS_GetFreeDiskSpace(reg_dl,&bytes,§ors,&clusters,&free)) { + reg_ax=sectors; + reg_bx=free; + reg_cx=bytes; + reg_dx=clusters; + } else { + reg_ax=0xffff; + } + } + break; + case 0x37: /* Get/Set Switch char Get/Set Availdev thing */ +//TODO Give errors for these functions to see if anyone actually uses this shit- + switch (reg_al) { + case 0: + reg_al=0;reg_dl=0x2f;break; /* always return '/' like dos 5.0+ */ + case 1: + reg_al=0;break; + case 2: + reg_al=0;reg_dl=0x2f;break; + case 3: + reg_al=0;break; + }; + LOG_DEBUG("DOS:0x37:Call for not supported switchchar"); + break; + case 0x38: /* Set Country Code */ + LOG_DEBUG("DOS:Setting country code not supported"); + CALLBACK_SCF(true); + break; + if (reg_al==0) { /* Get country specidic information */ + + } else { /* Set country code */ + + + } + break; + case 0x39: /* MKDIR Create directory */ + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + if (DOS_MakeDir(name1)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x3a: /* RMDIR Remove directory */ + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + if (DOS_RemoveDir(name1)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x3b: /* CHDIR Set current directory */ + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + if (DOS_ChangeDir(name1)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x3c: /* CREATE Create of truncate file */ + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + if (DOS_CreateFile(name1,reg_cx,®_ax)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x3d: /* OPEN Open existing file */ + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + if (DOS_OpenFile(name1,reg_al,®_ax)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x3e: /* CLOSE Close file */ + if (DOS_CloseFile(reg_bx)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x3f: /* READ Read from file or device */ + { + Bit16u toread=reg_cx; + if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) { + MEM_BlockWrite(real_phys(Segs[ds].value,reg_dx),dos_copybuf,toread); + reg_ax=toread; + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + } + case 0x40: /* WRITE Write to file or device */ + { + Bit16u towrite=reg_cx; + MEM_BlockRead(real_phys(Segs[ds].value,reg_dx),dos_copybuf,towrite); + if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) { + reg_ax=towrite; + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + }; + case 0x41: /* UNLINK Delete file */ + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + if (DOS_UnlinkFile(name1)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x42: /* LSEEK Set current file position */ + { + Bit32u pos=(reg_cx<<16) + reg_dx; + if (DOS_SeekFile(reg_bx,&pos,reg_al)) { + reg_dx=(Bit16u)(pos >> 16); + reg_ax=(Bit16u)(pos & 0xFFFF); + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + } + case 0x43: /* Get/Set file attributes */ +//TODO FIX THIS HACK + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + switch (reg_al) + case 0x00: /* Get */ + { + if (DOS_GetFileAttr(name1,®_cx)) { + CALLBACK_SCF(false); + } else { + CALLBACK_SCF(true); + reg_ax=dos.errorcode; + } + break; + case 0x01: /* Set */ + LOG_DEBUG("DOS:Set File Attributes for %s not supported",name1); + CALLBACK_SCF(false); + break; + default: + E_Exit("DOS:0x43:Illegal subfunction %2X",reg_al); + } + break; + case 0x44: /* IOCTL Functions */ + if (DOS_IOCTL(reg_al,reg_bx)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x45: /* DUP Duplicate file handle */ + if (DOS_DuplicateEntry(reg_bx,®_ax)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x46: /* DUP2,FORCEDUP Force duplicate file handle */ + E_Exit("Unhandled Dos 21 call %02X",reg_ah); + break; + case 0x47: /* CWD Get current directory */ + //TODO Memory + if (DOS_GetCurrentDir(reg_dl,real_off(Segs[ds].value,reg_si))) { + reg_ax=0x0100; + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x48: /* Allocate memory */ + { + Bit16u size=reg_bx;Bit16u seg; + if (DOS_AllocateMemory(&seg,&size)) { + reg_ax=seg; + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + reg_bx=size; + CALLBACK_SCF(true); + } + break; + } + case 0x49: /* Free memory */ + if (DOS_FreeMemory(Segs[es].value)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x4a: /* Resize memory block */ + { + Bit16u size=reg_bx; + if (DOS_ResizeMemory(Segs[es].value,&size)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + reg_bx=size; + CALLBACK_SCF(true); + } + break; + } + case 0x4b: /* EXEC Load and/or execute program */ + { + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + if (DOS_Execute(name1,(ParamBlock *)real_off(Segs[es].value,reg_bx),reg_al)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + } + break; +//TODO Check for use of execution state AL=5 + case 0x4c: /* EXIT Terminate with return code */ + { + if (DOS_Terminate(false)) { + dos.return_code=reg_al; + dos.return_mode=RETURN_EXIT; + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + } + case 0x4d: /* Get Return code */ + reg_al=dos.return_code; + reg_ah=dos.return_mode; + break; + case 0x4e: /* FINDFIRST Find first matching file */ + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + if (DOS_FindFirst(name1,reg_cx)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + }; + break; + case 0x4f: /* FINDNEXT Find next matching file */ + if (DOS_FindNext()) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + }; + break; + case 0x50: /* Set current PSP */ + dos.psp=reg_bx; + break; + case 0x51: /* Get current PSP */ + reg_bx=dos.psp; + break; + case 0x52: /* Get list of lists */ + SetSegment_16(es,0); + reg_bx=0; + LOG_ERROR("Call is made for list of lists not supported let's hope for the best"); + break; +//TODO Think hard how shit this is gonna be +//And will any game ever use this :) + case 0x53: /* Translate BIOS parameter block to drive parameter block */ +//YEAH RIGHT + case 0x54: /* Get verify flag */ + case 0x55: /* Create Child PSP*/ + E_Exit("Unhandled Dos 21 call %02X",reg_ah); + break; + case 0x56: /* RENAME Rename file */ + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + MEM_StrCopy(real_phys(Segs[es].value,reg_di),name2,DOSNAMEBUF); + if (DOS_Rename(name1,name2)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x57: /* Get/Set File's Date and Time */ + reg_cx=0; + reg_dx=0; + LOG_DEBUG("DOS:57:Getting/Setting File Date is faked",reg_ah); + break; + case 0x58: /* Get/Set Memory allocation strategy */ + LOG_DEBUG("DOS:58:Not Supported Set//Get memory allocation"); + break; + case 0x59: /* Get Extended error information */ + E_Exit("Unhandled Dos 21 call %02X",reg_ah); + break; + case 0x5a: /* Create temporary file */ + { + Bit16u handle; + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + if (DOS_CreateTempFile(name1,&handle)) { + reg_ax=handle; + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + } + break; + case 0x5b: /* Create new file */ + { + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + Bit16u handle; + if (DOS_OpenFile(name1,0,&handle)) { + DOS_CloseFile(handle); + DOS_SetError(DOSERR_ACCESS_DENIED); + reg_ax=dos.errorcode; + CALLBACK_SCF(false); + break; + } + if (DOS_CreateFile(name1,reg_cx,&handle)) { + reg_ax=handle; + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + } + case 0x5c: /* FLOCK File region locking */ + case 0x5d: /* Network Functions */ + case 0x5e: /* More Network Functions */ + case 0x5f: /* And Even More Network Functions */ + E_Exit("DOS:Unhandled call %02X",reg_ah); + break; + case 0x60: /* Canonicalize filename or path */ + MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF); + if (DOS_Canonicalize(name1,real_off(Segs[es].value,reg_di))) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + break; + case 0x62: /* Get Current PSP Address */ + reg_bx=dos.psp; + break; + case 0x63: /* Weirdo double byte stuff */ + reg_al=0xff; + LOG_WARN("DOS:0x63:Doubly byte characters not supported"); + break; + case 0x64: /* Set device driver lookahead flag */ + E_Exit("Unhandled Dos 21 call %02X",reg_ah); + break; + case 0x65: /* Get extented country information and a lot of other useless shit*/ + /* Todo maybe fully support this for now we set it standard for USA */ + { + LOG_DEBUG("DOS:65:Extended country information call"); + Bit8u * data=real_off(Segs[es].value,reg_di); + switch (reg_al) { + case 1: + real_writeb(Segs[es].value,reg_di,reg_al); + real_writew(Segs[es].value,reg_di+1,4); + real_writew(Segs[es].value,reg_di+3,1); + real_writew(Segs[es].value,reg_di+5,37); + reg_cx=4; + CALLBACK_SCF(false); + break; + default: + E_Exit("DOS:0x65:Unhandled country information call %2X",reg_al); + }; + break; + } + case 0x66: /* Get/Set global code page table */ + if (reg_al==1) { + LOG_DEBUG("Getting global code page table"); + reg_bx=reg_dx=437; + CALLBACK_SCF(false); + break; + } + LOG_ERROR("DOS:Setting code page table is not supported"); + break; + case 0x67: /* Set handle countr */ + /* Weird call to increase amount of file handles needs to allocate memory if >20 */ + LOG_DEBUG("DOS:67:Set Handle Count not working"); + CALLBACK_SCF(false); + break; + case 0x68: /* FFLUSH Commit file */ + E_Exit("Unhandled Dos 21 call %02X",reg_ah); + break; + case 0x69: /* Get/Set disk serial number */ + { + Bit8u * temp=real_off(Segs[ds].value,reg_dx); + switch(reg_al) { + case 0x00: /* Get */ + LOG_DEBUG("DOS:Get Disk serial number"); + CALLBACK_SCF(true); + break; + case 0x01: + LOG_DEBUG("DOS:Set Disk serial number"); + default: + E_Exit("DOS:Illegal Get Serial Number call %2X",reg_al); + } + break; + } + case 0x6c: /* Extended Open/Create */ + E_Exit("Unhandled Dos 21 call %02X",reg_ah); + break; + case 0x71: /* Unknown probably 4dos detection */ + reg_ax=0x7100; + CALLBACK_SCF(true); + LOG_WARN("DOS:Windows long file name support call %2X",reg_al); + break; + case 0xE0: + LOG_DEBUG("DOS:E0:Unhandled, what should this call do?"); + break; + default: + E_Exit("DOS:Unhandled call %02X",reg_ah); + break; + }; + return CBRET_NONE; +/* That's it now let's get it working */ +}; + + + +static Bitu DOS_20Handler(void) { + + reg_ax=0x4c00; + DOS_21Handler(); + return CBRET_NONE; +} + + +void DOS_Init(void) { + call_20=CALLBACK_Allocate(); + CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET); + RealSetVec(0x20,CALLBACK_RealPointer(call_20)); + + call_21=CALLBACK_Allocate(); + CALLBACK_Setup(call_21,DOS_21Handler,CB_IRET); + RealSetVec(0x21,CALLBACK_RealPointer(call_21)); + + DOS_SetupFiles(); /* Setup system File tables */ + DOS_SetupDevices(); /* Setup dos devices */ + DOS_SetupMemory(); /* Setup first MCB */ + DOS_SetupTables(); + DOS_SetupPrograms(); + DOS_SetupMisc(); /* Some additional dos interrupts */ + DOS_SetDefaultDrive(25); + /* Execute the file that should be */ + dos.version.major=5; + dos.version.minor=0; +// DOS_RunProgram(startname); +}; diff --git a/src/dos/dos_classes.cpp b/src/dos/dos_classes.cpp index 9d2fe6f..8a357b1 100644 --- a/src/dos/dos_classes.cpp +++ b/src/dos/dos_classes.cpp @@ -1,496 +1,181 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos_classes.cpp,v 1.56 2009/04/16 12:16:52 qbix79 Exp $ */ - -#include -#include -#include "dosbox.h" -#include "mem.h" -#include "dos_inc.h" -#include "support.h" - - -void DOS_ParamBlock::Clear(void) { - memset(&exec,0,sizeof(exec)); - memset(&overlay,0,sizeof(overlay)); -} - -void DOS_ParamBlock::LoadData(void) { - exec.envseg=sGet(sExec,envseg); - exec.cmdtail=sGet(sExec,cmdtail); - exec.fcb1=sGet(sExec,fcb1); - exec.fcb2=sGet(sExec,fcb2); - exec.initsssp=sGet(sExec,initsssp); - exec.initcsip=sGet(sExec,initcsip); - overlay.loadseg=sGet(sOverlay,loadseg); - overlay.relocation=sGet(sOverlay,relocation); -} - -void DOS_ParamBlock::SaveData(void) { - sSave(sExec,envseg,exec.envseg); - sSave(sExec,cmdtail,exec.cmdtail); - sSave(sExec,fcb1,exec.fcb1); - sSave(sExec,fcb2,exec.fcb2); - sSave(sExec,initsssp,exec.initsssp); - sSave(sExec,initcsip,exec.initcsip); -} - - -void DOS_InfoBlock::SetLocation(Bit16u segment) { - seg = segment; - pt=PhysMake(seg,0); - /* Clear the initial Block */ - for(Bitu i=0;i=sGet(sPSP,max_files)) return 0xff; - PhysPt files=Real2Phys(sGet(sPSP,file_table)); - return mem_readb(files+index); -} - -void DOS_PSP::SetFileHandle(Bit16u index, Bit8u handle) { - if (indexGetFileHandle(i); - if(createchildpsp) - { //copy obeying not inherit flag.(but dont duplicate them) - bool allowCopy = true;//(handle==0) || ((handle>0) && (FindEntryByHandle(handle)==0xff)); - if((handleflags & DOS_NOT_INHERIT) && allowCopy) - { - Files[handle]->AddRef(); - SetFileHandle(i,handle); - } - else - { - SetFileHandle(i,0xff); - } - } - else - { //normal copy so don't mind the inheritance - SetFileHandle(i,handle); - } - } -} - -void DOS_PSP::CloseFiles(void) { - for (Bit16u i=0;i20) { - // Allocate needed paragraphs - fileNum+=2; // Add a few more files for safety - Bit16u para = (fileNum/16)+((fileNum%16)>0); - RealPt data = RealMake(DOS_GetMemory(para),0); - sSave(sPSP,file_table,data); - sSave(sPSP,max_files,fileNum); - Bit16u i; - for (i=0; i<20; i++) SetFileHandle(i,sGet(sPSP,files[i])); - for (i=20; i8) size=8; - MEM_BlockWrite(pt+offsetof(sDTA,sname),pattern,size); - find_ext++; - MEM_BlockWrite(pt+offsetof(sDTA,sext),find_ext,(strlen(find_ext)>3) ? 3 : (Bitu)strlen(find_ext)); - } else { - MEM_BlockWrite(pt+offsetof(sDTA,sname),pattern,(strlen(pattern) > 8) ? 8 : (Bitu)strlen(pattern)); - } -} - -void DOS_DTA::SetResult(const char * _name,Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr) { - MEM_BlockWrite(pt+offsetof(sDTA,name),(void *)_name,DOS_NAMELENGTH_ASCII); - sSave(sDTA,size,_size); - sSave(sDTA,date,_date); - sSave(sDTA,time,_time); - sSave(sDTA,attr,_attr); -} - - -void DOS_DTA::GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr) { - MEM_BlockRead(pt+offsetof(sDTA,name),_name,DOS_NAMELENGTH_ASCII); - _size=sGet(sDTA,size); - _date=sGet(sDTA,date); - _time=sGet(sDTA,time); - _attr=sGet(sDTA,attr); -} - -Bit8u DOS_DTA::GetSearchDrive(void) { - return sGet(sDTA,sdrive); -} - -void DOS_DTA::GetSearchParams(Bit8u & attr,char * pattern) { - attr=sGet(sDTA,sattr); - char temp[11]; - MEM_BlockRead(pt+offsetof(sDTA,sname),temp,11); - memcpy(pattern,temp,8); - pattern[8]='.'; - memcpy(&pattern[9],&temp[8],3); - pattern[12]=0; - -} - -DOS_FCB::DOS_FCB(Bit16u seg,Bit16u off) { - SetPt(seg,off); - real_pt=pt; - if (sGet(sFCB,drive)==0xff) { - pt+=7; - extended=true; - } else extended=false; -} - -bool DOS_FCB::Extended(void) { - return extended; -} - -void DOS_FCB::Create(bool _extended) { - Bitu fill; - if (_extended) fill=36+7; - else fill=36; - Bitu i; - for (i=0;iSeek(&size,DOS_SEEK_END); - sSave(sFCB,filesize,size); - size = 0; - Files[temp]->Seek(&size,DOS_SEEK_SET); - sSave(sFCB,time,Files[temp]->time); - sSave(sFCB,date,Files[temp]->date); -} - -bool DOS_FCB::Valid() { - //Very simple check for Oubliette - if(sGet(sFCB,filename[0]) == 0 && sGet(sFCB,file_handle) == 0) return false; - return true; -} - -void DOS_FCB::FileClose(Bit8u & _fhandle) { - _fhandle=sGet(sFCB,file_handle); - sSave(sFCB,file_handle,0xff); -} - -Bit8u DOS_FCB::GetDrive(void) { - Bit8u drive=sGet(sFCB,drive); - if (!drive) return DOS_GetDefaultDrive(); - else return drive-1; -} - -void DOS_FCB::GetName(char * fillname) { - fillname[0]=GetDrive()+'A'; - fillname[1]=':'; - MEM_BlockRead(pt+offsetof(sFCB,filename),&fillname[2],8); - fillname[10]='.'; - MEM_BlockRead(pt+offsetof(sFCB,ext),&fillname[11],3); - fillname[14]=0; -} - -void DOS_FCB::GetAttr(Bit8u& attr) { - if(extended) attr=mem_readb(pt - 1); -} - -void DOS_FCB::SetAttr(Bit8u attr) { - if(extended) mem_writeb(pt - 1,attr); -} - -void DOS_SDA::Init() { - /* Clear */ - for(Bitu i=0;i +#include +#include "dosbox.h" +#include "mem.h" +#include "dos_inc.h" + +/* + Work in progress, making classes for handling certain internal memory structures in dos + This should make it somewhat easier for porting to other endian machines and make + dos work a bit easier. +*/ + + +struct sPSP { + Bit8u exit[2]; /* CP/M-like exit poimt */ + Bit16u next_seg; /* Segment of first byte beyond memory allocated or program */ + Bit8u fill_1; /* single char fill */ + +/* CPM Stuff dunno what this is*/ +//TODO Add some checks for people using this i think + Bit8u far_call; /* far call opcode */ + RealPt cpm_entry; /* CPM Service Request address*/ + RealPt int_22; /* Terminate Address */ + RealPt int_23; /* Break Address */ + RealPt int_24; /* Critical Error Address */ + Bit16u psp_parent; /* Parent PSP Segment */ + Bit8u files[20]; /* File Table - 0xff is unused */ + Bit16u environment; /* Segment of evironment table */ + RealPt stack; /* SS:SP Save point for int 0x21 calls */ + Bit16u max_files; /* Maximum open files */ + RealPt file_table; /* Pointer to File Table PSP:0x18 */ + RealPt prev_psp; /* Pointer to previous PSP */ + RealPt dta; /* Pointer to current Process DTA */ + Bit8u fill_2[16]; /* Lot's of unused stuff i can't care aboue */ + Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */ + Bit8u fill_3[45]; /* This has some blocks with FCB info */ + + CommandTail cmdtail; + +}; + + + +class DOS_PSP { +public: + DOS_PSP(Bit16u segment); + + void MakeNew(Bit16u env,Bit16u memsize); + + + Bit16u base_seg; + +private: + PhysOff off; +}; + +DOS_PSP::DOS_PSP(Bit16u segment) { + base_seg=segment; + off=Real2Phys(RealMake(segment,0)); +}; + +void DOS_PSP::MakeNew(Bit16u env,Bit16u next_para) { + Bitu i; + for (i=0;i<256;i++) mem_writeb(off+i,0); +/* Standard blocks */ + mem_writeb(off+offsetof(sPSP,exit[0]),0xcd); + mem_writeb(off+offsetof(sPSP,exit[1]),0x20); + + mem_writeb(off+offsetof(sPSP,service[0]),0xcd); + mem_writeb(off+offsetof(sPSP,service[1]),0x21); + mem_writeb(off+offsetof(sPSP,service[2]),0xcb); + + mem_writew(off+offsetof(sPSP,next_seg),next_para); + + +// mem_writew(off+offsetof(sPSP,psp_parent),dos.psp->base_seg); + + /* Setup initial file table */ + mem_writed(off+offsetof(sPSP,int_22),RealGetVec(0x22)); + mem_writed(off+offsetof(sPSP,int_23),RealGetVec(0x23)); + mem_writed(off+offsetof(sPSP,int_24),RealGetVec(0x24)); + + +#if 0 + + newpsp->mem_size=prevpsp->mem_size; + newpsp->environment=0; + + newpsp->int_22.full=real_getvec(0x22); + newpsp->int_23.full=real_getvec(0x23); + newpsp->int_24.full=real_getvec(0x24); + + newpsp->psp_parent=dos.psp; + newpsp->prev_psp.full=0xFFFFFFFF; + + Bit32u i; + Bit8u * prevfile=real_off(prevpsp->file_table.seg,prevpsp->file_table.off); + for (i=0;i<20;i++) newpsp->files[i]=prevfile[i]; + + newpsp->max_files=20; + newpsp->file_table.seg=pspseg; + newpsp->file_table.off=offsetof(PSP,files); + /* Save the old DTA in this psp */ + newpsp->dta.seg=dos.dta.seg; + newpsp->dta.off=dos.dta.off; + /* Setup the DTA */ + dos.dta.seg=pspseg; + dos.dta.off=0x80; + return; +#endif + + +} + + +void DOS_FCB::Set_drive(Bit8u a){ + mem_writeb(off+offsetof(FCB,drive),a); +} +void DOS_FCB::Set_filename(char * a){ + MEM_BlockWrite(off+offsetof(FCB,filename),a,8); +} +void DOS_FCB::Set_ext(char * a) { + MEM_BlockWrite(off+offsetof(FCB,ext),a,3); +} +void DOS_FCB::Set_current_block(Bit16u a){ + mem_writew(off+offsetof(FCB,current_block),a); +} +void DOS_FCB::Set_record_size(Bit16u a){ + mem_writew(off+offsetof(FCB,record_size),a); +} +void DOS_FCB::Set_filesize(Bit32u a){ + mem_writed(off+offsetof(FCB,filesize),a); +} +void DOS_FCB::Set_date(Bit16u a){ + mem_writew(off+offsetof(FCB,date),a); +} +void DOS_FCB::Set_time(Bit16u a){ + mem_writew(off+offsetof(FCB,time),a); +} +Bit8u DOS_FCB::Get_drive(void){ + return mem_readb(off+offsetof(FCB,drive)); +} +void DOS_FCB::Get_filename(char * a){ + MEM_BlockRead(off+offsetof(FCB,filename),a,8); +} +void DOS_FCB::Get_ext(char * a){ + MEM_BlockRead(off+offsetof(FCB,ext),a,3); +} +Bit16u DOS_FCB::Get_current_block(void){ + return mem_readw(off+offsetof(FCB,current_block)); +} +Bit16u DOS_FCB::Get_record_size(void){ + return mem_readw(off+offsetof(FCB,record_size)); +} +Bit32u DOS_FCB::Get_filesize(void){ + return mem_readd(off+offsetof(FCB,filesize)); +} +Bit16u DOS_FCB::Get_date(void){ + return mem_readw(off+offsetof(FCB,date)); +} +Bit16u DOS_FCB::Get_time(void){ + return mem_readw(off+offsetof(FCB,time)); +} diff --git a/src/dos/dos_codepages.h b/src/dos/dos_codepages.h deleted file mode 100644 index bb28852..0000000 --- a/src/dos/dos_codepages.h +++ /dev/null @@ -1,1131 +0,0 @@ -/* - * Copyright (C) Henrique Peron - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -/* This file contains data of .CPI/.CPX-files. They have been - generated by Henrique Peron */ - -/* The font files have been created/edited with CPIadd V1.20 - Copyright (C) 1993-1996 by kostis@acm.org (Kosta Kostis) */ - -/* This file contains data of UPX-compressed CPI files. - UPX, The Ultimate Packer for eXecutables - Copyright (c) 1996-2002 Markus Oberhumer & Laszlo Molnar - http://upx.sourceforge.net */ - - -Bit8u font_ega_cpx[6322] = { -0x81, 0xfc, 0xce, 0xe7, 0x77, 0x02, 0xcd, 0x20, 0xb9, 0xb2, 0x18, 0xbe, 0xb2, 0x19, 0xbf, 0x6e, -0xe7, 0xbb, 0x00, 0x80, 0xfd, 0xf3, 0xa4, 0xfc, 0x87, 0xf7, 0x83, 0xee, 0xc6, 0x19, 0xed, 0x57, -0x57, 0xe9, 0xed, 0xe5, 0x55, 0x50, 0x58, 0x21, 0x0b, 0x01, 0x04, 0x08, 0x6c, 0xfa, 0x36, 0x54, -0x99, 0xe8, 0x0b, 0xa9, 0x00, 0xe6, 0x1a, 0x18, 0x06, 0x74, 0xbb, 0xfc, 0xff, 0x46, 0x4f, 0x4e, -0x54, 0x20, 0x00, 0x00, 0x01, 0x6e, 0x39, 0x01, 0x17, 0x06, 0xfd, 0xfd, 0x06, 0x00, 0x1c, 0x00, -0x4d, 0x26, 0x0e, 0x45, 0x47, 0x41, 0xc9, 0xcd, 0x1e, 0x20, 0xb5, 0x01, 0xfe, 0xd8, 0x35, 0x24, -0x03, 0x00, 0x12, 0x26, 0x10, 0x08, 0x95, 0xc5, 0x0a, 0x00, 0x6d, 0xff, 0x7e, 0x81, 0xa5, 0x81, -0x81, 0xbd, 0x99, 0x03, 0x7e, 0xfe, 0x83, 0x0f, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, -0xe6, 0x77, 0x00, 0x6c, 0xfe, 0x3e, 0xec, 0x7c, 0x38, 0x10, 0x30, 0x10, 0x38, 0x7c, 0xfd, 0xc0, -0x0e, 0x18, 0x3c, 0x3c, 0xe7, 0xb2, 0xb6, 0x00, 0x18, 0x06, 0x0f, 0x65, 0x6e, 0x7e, 0x3b, 0x0f, -0xb3, 0xb3, 0x22, 0x18, 0x09, 0xde, 0xb1, 0xff, 0x00, 0xe7, 0xc3, 0x5f, 0x3f, 0xf6, 0x00, 0x1f, -0x3c, 0x66, 0x42, 0x42, 0x66, 0xff, 0x92, 0x3c, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xfe, 0x21, -0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xde, 0xeb, 0x00, 0x78, 0x20, 0x2d, 0xb9, 0xe6, 0x00, 0x4f, -0x61, 0xbb, 0x9f, 0x0f, 0x3f, 0x33, 0x3f, 0x30, 0x00, 0x70, 0xf0, 0xf9, 0xc8, 0xe0, 0x00, 0x7f, -0x63, 0x7f, 0x63, 0x9e, 0xbd, 0x67, 0xe7, 0xe6, 0xc0, 0x7c, 0x18, 0xdb, 0x87, 0xdd, 0xa0, 0x3c, -0xdb, 0x2e, 0x80, 0xbb, 0xfd, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0x2d, 0xc0, 0x80, 0xbf, 0xfe, -0x1f, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x6b, 0x49, 0x2b, 0x5e, -0x7c, 0x67, 0x3c, 0x00, 0x66, 0x98, 0x9b, 0x07, 0x5f, 0xe7, 0x36, 0xdb, 0x00, 0x7b, 0x1b, 0xff, -0x9b, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0x06, 0xe4, 0xc6, 0x7c, -0x00, 0xfe, 0x43, 0x66, 0x4f, 0x7e, 0x6f, 0x60, 0x0f, 0x00, 0xbd, 0x60, 0x0f, 0x00, 0xfe, 0x96, -0x70, 0x11, 0x0c, 0xfe, 0x0c, 0x77, 0xc9, 0x0c, 0x00, 0x30, 0x60, 0xfe, 0x06, 0xe4, 0x60, 0x30, -0x00, 0xc0, 0x61, 0x56, 0x5c, 0xa1, 0x76, 0x39, 0x28, 0x6c, 0x28, 0x0e, 0x50, 0x58, 0x9f, 0xb2, -0xb7, 0xa0, 0x7c, 0x7d, 0x8a, 0x0e, 0x5b, 0x0e, 0x38, 0xaf, 0xbc, 0xc0, 0x00, 0x18, 0x3c, 0x66, -0xaf, 0x8c, 0x8f, 0x21, 0xeb, 0xe9, 0x24, 0x20, 0x8b, 0xb9, 0x6c, 0x5e, 0x03, 0xad, 0xfe, 0x36, -0xf1, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0x1e, 0xd6, 0xef, 0xc1, 0xc2, 0xc6, 0x26, 0xdf, 0xae, -0x30, 0x60, 0xc6, 0x86, 0x2e, 0x14, 0x0e, 0x0c, 0x76, 0xdc, 0xc1, 0x1a, 0xaf, 0x76, 0xbd, 0x81, -0x6d, 0x00, 0x60, 0x4e, 0x8b, 0xb9, 0x2b, 0x00, 0xe5, 0xb9, 0x59, 0x0f, 0x08, 0x96, 0x8d, 0x00, -0x18, 0xe2, 0x15, 0x16, 0xde, 0xff, 0xe5, 0x84, 0x81, 0xa2, 0xed, 0x06, 0xb6, 0x14, 0x6c, 0xc0, -0x31, 0xfe, 0xd7, 0x96, 0xad, 0x31, 0xf9, 0x15, 0xe2, 0x9f, 0xc0, 0x80, 0xf8, 0x30, 0xae, 0xd6, -0xd6, 0x0e, 0x76, 0xb2, 0x27, 0x38, 0x78, 0x59, 0x10, 0x81, 0x2e, 0xf6, 0xe4, 0x7c, 0xc6, 0xc6, -0xfe, 0x0f, 0xd8, 0x4e, 0x06, 0x3c, 0x02, 0x06, 0xfd, 0x43, 0xdf, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, -0xfe, 0x9c, 0xd0, 0xb0, 0x1e, 0x8d, 0xfe, 0x03, 0xd6, 0xfc, 0x1f, 0x38, 0x90, 0xbb, 0x60, 0x0f, -0xc6, 0xc6, 0xc6, 0x66, 0xee, 0xfe, 0x3f, 0xf3, 0x73, 0xc3, 0x4f, 0x1a, 0x1f, 0x7d, 0x01, 0x0b, -0x7e, 0x0b, 0xdb, 0x3f, 0x0c, 0x78, 0xba, 0x0b, 0x7b, 0x04, 0x0f, 0x62, 0x93, 0x30, 0x9e, 0x92, -0x1a, 0x35, 0x06, 0xc2, 0xc9, 0xde, 0x02, 0x00, 0xf6, 0x62, 0x1b, 0x23, 0x5f, 0x25, 0x4c, 0x0c, -0xdf, 0xb6, 0xb3, 0x10, 0xde, 0x00, 0xdc, 0x61, 0x14, 0xc4, 0x2e, 0x3b, 0xdb, 0x6c, 0x90, 0xfe, -0x0f, 0x6c, 0x3c, 0xfc, 0x66, 0xf1, 0x7c, 0x86, 0xf4, 0xfc, 0x6f, 0xd4, 0x15, 0xef, 0x00, 0xc2, -0xf2, 0xe9, 0xa1, 0x10, 0xf8, 0x6c, 0x3f, 0x7b, 0x6c, 0xf8, 0x0f, 0xfe, 0x66, 0x62, 0x68, 0x84, -0xfc, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0xc0, 0xb6, 0x00, 0xf0, 0x3f, 0x4d, 0x7e, 0xde, 0xc6, -0xc6, 0x66, 0x3a, 0x61, 0xef, 0x69, 0x6e, 0x6f, 0x6b, 0xc2, 0x3c, 0x7d, 0x30, 0x31, 0x26, 0x1e, -0x0d, 0x77, 0x49, 0xef, 0xe6, 0x6a, 0xb3, 0x6e, 0x78, 0x78, 0x74, 0xe6, 0x0f, 0xb3, 0xd8, 0xf0, -0x60, 0x00, 0x6f, 0x92, 0x7f, 0x4f, 0xee, 0xfe, 0xfe, 0xd6, 0xf2, 0xdb, 0x0f, 0xe6, 0xf6, 0xfe, -0xde, 0xce, 0x79, 0x58, 0x6f, 0xc6, 0x9b, 0x2d, 0xdf, 0x41, 0x27, 0xec, 0xf0, 0x1f, 0xd6, 0xde, -0x97, 0xe4, 0x7c, 0x0c, 0x0e, 0xe3, 0x29, 0xd9, 0xe6, 0x1f, 0xe2, 0xb2, 0x42, 0x50, 0x3f, 0x09, -0x7b, 0x7e, 0x7e, 0x5a, 0xaf, 0x16, 0xb2, 0xc6, 0x5f, 0x0f, 0x25, 0x0f, 0x6c, 0x38, 0x10, 0x43, -0xfe, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x6b, 0xa6, 0x6c, 0x8e, 0x61, 0x9f, 0x66, 0x0d, 0xce, -0x0b, 0xcb, 0x4f, 0x1b, 0x86, 0x21, 0x1f, 0x7f, 0xc2, 0x16, 0xec, 0x3c, 0x30, 0x00, 0x1f, 0xfe, -0x0a, 0xc1, 0x70, 0x38, 0x1c, 0x76, 0xb2, 0xaf, 0x3c, 0x0c, 0x00, 0x62, 0x0c, 0x3c, 0xdc, 0x8d, -0x90, 0xe6, 0xec, 0x34, 0x6c, 0xff, 0x18, 0xe9, 0x03, 0x78, 0x0c, 0x7c, 0xaf, 0x16, 0x2e, 0xe0, -0x19, 0x78, 0x66, 0x11, 0xe2, 0xcf, 0x1c, 0x13, 0x02, 0x00, 0xb9, 0xc3, 0xdf, 0x1c, 0x69, 0x2d, -0x2b, 0x00, 0x2f, 0x80, 0x8c, 0x1f, 0xfe, 0xc6, 0xfb, 0x36, 0x32, 0x30, 0x78, 0xaf, 0xcf, 0xf0, -0x5d, 0x76, 0x2e, 0xcc, 0xdf, 0xa1, 0x5f, 0xd2, 0x5f, 0x6c, 0x32, 0x9e, 0x76, 0xe6, 0xdc, 0x03, -0x61, 0x38, 0x4f, 0x6b, 0x4b, 0x09, 0x00, 0xdb, 0x00, 0xcc, 0x10, 0x17, 0x2f, 0x71, 0xc6, 0x00, -0xe6, 0x90, 0x9c, 0x2f, 0x38, 0x35, 0xba, 0x00, 0xec, 0x00, 0x4c, 0xd6, 0x00, 0xc6, 0x0f, 0xdc, -0xcb, 0x66, 0xa1, 0x9f, 0x6c, 0x09, 0x9f, 0x1f, 0xf6, 0xb1, 0x04, 0xf0, 0x9f, 0x90, 0x16, 0xd2, -0x19, 0xed, 0xdc, 0x9f, 0x1f, 0x4c, 0x60, 0xe4, 0x76, 0x09, 0xdf, 0x10, 0xd9, 0xb2, 0xdf, 0xfc, -0xde, 0x36, 0x1c, 0x1f, 0x10, 0x5e, 0x3d, 0x0f, 0x82, 0x31, 0x00, 0x47, 0xc0, 0x0f, 0x00, 0xb7, -0x84, 0x9a, 0x1b, 0x30, 0x53, 0x38, 0x75, 0x2f, 0xd4, 0xb5, 0x04, 0x0c, 0x03, 0x87, 0x52, 0xcc, -0x4f, 0xcd, 0xd9, 0xfe, 0xef, 0x0e, 0x70, 0x64, 0x3d, 0x0e, 0xf7, 0x09, 0x83, 0x3f, 0xda, 0x7b, -0x1b, 0x23, 0x24, 0x40, 0xf8, 0xc9, 0xdc, 0xdf, 0x8b, 0x34, 0xe2, 0x4f, 0x17, 0xd2, 0xcf, 0x18, -0xd8, 0x59, 0x72, 0xcc, 0xbf, 0xe0, 0x4a, 0x39, 0xb8, 0x84, 0xcf, 0x3b, 0x6e, 0x61, 0x1f, 0x2f, -0x7c, 0x60, 0x0f, 0xc0, 0x60, 0x30, 0xb6, 0x84, 0x2e, 0x38, 0x46, 0xc8, 0x2f, 0x3f, 0xde, 0x4b, -0x6f, 0x4f, 0x5c, 0xc2, 0x5f, 0xfd, 0x57, 0xc2, 0x0f, 0xbd, 0x18, 0x32, 0x1f, 0x66, 0x5a, 0xc2, -0x1f, 0x06, 0xde, 0xc2, 0x0f, 0x2f, 0x6b, 0xc0, 0x0f, 0xc6, 0xcf, 0x73, 0x0b, 0x8d, 0x0f, 0x72, -0x09, 0xdc, 0xc7, 0xc8, 0xaf, 0x3f, 0x4e, 0xfe, 0x36, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x3e, 0x1e, -0x3a, 0xdc, 0xfe, 0x0f, 0xce, 0x18, 0xc9, 0xff, 0x3f, 0x84, 0x5d, 0xc6, 0x0f, 0x65, 0xb3, 0xaf, -0x0f, 0x08, 0x8d, 0xf6, 0x4f, 0x71, 0x58, 0x1f, 0xc2, 0x85, 0x1f, 0xc6, 0xef, 0x59, 0x07, 0xc6, -0x9f, 0x65, 0x0d, 0xc6, 0x4f, 0x70, 0x22, 0x71, 0x37, 0xe1, 0x0d, 0xef, 0xd2, 0x70, 0xe0, 0x64, -0x60, 0x03, 0xa1, 0x21, 0x9f, 0x0c, 0xc9, 0x38, 0x7e, 0x0f, 0xdb, 0xb7, 0xf8, 0x69, 0xf8, 0xc4, -0xcc, 0xde, 0x05, 0xc6, 0xe5, 0x19, 0x1f, 0x0e, 0x1b, 0x70, 0x9a, 0x7e, 0xd8, 0x0b, 0xe1, 0x01, -0xaf, 0x42, 0x6a, 0x84, 0x7f, 0xcb, 0xde, 0x0f, 0xcf, 0x21, 0x7b, 0x2f, 0xbf, 0x92, 0x1c, 0x62, -0x5f, 0x04, 0xdc, 0x0c, 0x6f, 0x6e, 0x8d, 0x1c, 0x6c, 0x36, 0x0c, 0x0c, 0x8e, 0xd6, 0x5e, 0x0f, -0x51, 0x0f, 0x98, 0x58, 0x07, 0x48, 0x5d, 0x11, 0xc0, 0x8f, 0x7a, 0x1c, 0xfe, 0x90, 0x34, 0x10, -0x3c, 0xc1, 0xe0, 0xfd, 0xcc, 0xa6, 0x85, 0xe0, 0xa8, 0x6c, 0x0d, 0xac, 0x81, 0xdc, 0x14, 0x3e, -0x0f, 0x60, 0xbf, 0x66, 0xce, 0x9a, 0x3f, 0x22, 0xe8, 0xb9, 0xf7, 0xbc, 0x63, 0xc9, 0x62, 0x85, -0x36, 0xcb, 0xcc, 0x6c, 0xd8, 0x00, 0x6d, 0x76, 0x0d, 0x6c, 0xd8, 0x11, 0x44, 0xe4, 0x85, 0x01, -0x55, 0xaa, 0x21, 0x2f, 0xdd, 0x77, 0x05, 0x76, 0x18, 0x00, 0x0b, 0xd9, 0xf8, 0x0d, 0x0f, 0xcf, -0x26, 0x36, 0x00, 0xf6, 0x36, 0xb0, 0x20, 0xd0, 0x4b, 0xd8, 0x0f, 0x2f, 0xce, 0x23, 0xf6, 0x06, -0x96, 0xc0, 0x00, 0x3d, 0x85, 0x6c, 0x1f, 0x25, 0xa3, 0x2f, 0xba, 0xc9, 0x82, 0x11, 0x0f, 0xac, -0x61, 0x8f, 0x00, 0xc8, 0x86, 0xf8, 0xbf, 0x27, 0x6c, 0x1f, 0x2f, 0x18, 0x18, 0x19, 0x92, 0xff, -0xff, 0x58, 0x23, 0x72, 0x59, 0x5b, 0x1f, 0x3f, 0x21, 0x1b, 0x2d, 0x86, 0x84, 0x1f, 0x0f, 0x37, -0x7b, 0xc2, 0xbf, 0x37, 0x30, 0x3f, 0x6d, 0x52, 0x09, 0xbf, 0xbb, 0xb0, 0x1f, 0xf7, 0x5f, 0x83, -0x2d, 0x6d, 0xf7, 0x2c, 0x64, 0x3f, 0x2f, 0x6c, 0x96, 0x1f, 0x2f, 0x6c, 0xb6, 0x3f, 0x2f, 0x0c, -0xb6, 0xdd, 0xff, 0x2c, 0x24, 0x2f, 0x5f, 0xc8, 0x8e, 0xff, 0xdf, 0x42, 0xc2, 0x86, 0x61, 0xc9, -0xaf, 0xdf, 0x97, 0xb0, 0x3f, 0xef, 0xb9, 0xb0, 0x3f, 0x3f, 0x64, 0x21, 0x4f, 0x10, 0x84, 0x2d, -0x84, 0x91, 0x5f, 0xaf, 0x93, 0x8d, 0x4f, 0xff, 0x2c, 0x64, 0x00, 0x9f, 0x1c, 0x36, 0x00, 0xf0, -0xc9, 0x90, 0x0f, 0x0b, 0x0b, 0x36, 0xf2, 0x61, 0x00, 0x76, 0xdc, 0xd8, 0x08, 0xd2, 0xdc, 0xcf, -0xd3, 0x06, 0x5b, 0xd8, 0xcc, 0xbe, 0x86, 0x45, 0xcc, 0x7f, 0x48, 0x07, 0xad, 0x91, 0x9d, 0x4a, -0xff, 0x35, 0xcc, 0x00, 0x1f, 0xcb, 0xc0, 0xf2, 0x9f, 0x78, 0x7e, 0x00, 0x7e, 0xd8, 0x70, 0x64, -0x92, 0x5f, 0x66, 0x0c, 0x3b, 0xc0, 0x6f, 0x2b, 0x20, 0x1c, 0x8b, 0x20, 0x40, 0xc1, 0x2f, 0xa9, -0x8f, 0xfe, 0xc6, 0x83, 0x25, 0xab, 0xd1, 0x17, 0x6e, 0xee, 0xd6, 0x9c, 0xce, 0x1e, 0x3e, 0x31, -0xb0, 0x2c, 0x6f, 0xb2, 0x0a, 0x82, 0x61, 0x6c, 0xf7, 0x03, 0x06, 0x0f, 0xf3, 0x7e, 0x6c, 0x68, -0x3b, 0x1c, 0x9a, 0x60, 0x09, 0x7d, 0xdf, 0x30, 0x1c, 0xff, 0x25, 0x0b, 0xcd, 0xb2, 0x9a, 0x02, -0x5d, 0x4a, 0x36, 0x50, 0x59, 0x90, 0x3e, 0x10, 0x41, 0x2a, 0x6e, 0x07, 0x66, 0x0f, 0x4f, 0x01, -0xac, 0x1b, 0x11, 0x77, 0x60, 0xff, 0x18, 0x2a, 0x12, 0x42, 0x18, 0x6e, 0x0c, 0x24, 0x97, 0xac, -0x0e, 0x0f, 0xac, 0x61, 0x81, 0x42, 0xf3, 0xb0, 0x00, 0x0f, 0x0c, 0x60, 0xdb, 0xec, 0x34, 0x3c, -0xcf, 0x06, 0xd6, 0x6c, 0x58, 0x5b, 0x24, 0xcf, 0xa0, 0x32, 0xbe, 0x64, 0xbc, 0x00, 0x7e, 0x40, -0x4e, 0x00, 0x2f, 0x18, 0x0e, 0x05, 0x84, 0x05, 0x03, 0x58, 0x70, 0x7e, 0x01, 0x12, 0x1c, 0x7e, -0xff, 0x82, 0x00, 0x12, 0x4c, 0xfd, 0xfb, 0x09, 0x56, 0xf9, 0x04, 0x29, 0x92, 0xe0, 0xf7, 0xf5, -0x49, 0x30, 0xf3, 0x92, 0x60, 0xf1, 0x49, 0x30, 0xef, 0x60, 0x76, 0x78, 0x27, 0xc1, 0x92, 0xec, -0x24, 0x38, 0xeb, 0xea, 0x4e, 0xb0, 0xe9, 0xc1, 0x09, 0xe8, 0x2a, 0x25, 0xe7, 0x4a, 0x60, 0x24, -0xe5, 0x2c, 0x09, 0xe4, 0xa9, 0x12, 0xe3, 0x32, 0x25, 0xc1, 0xe1, 0x90, 0x20, 0xde, 0x48, 0x90, -0xdd, 0x90, 0x60, 0xdb, 0x24, 0xc1, 0xda, 0x82, 0x72, 0x00, 0xde, 0x48, 0xd7, 0x0d, 0xc1, 0x32, -0xe4, 0x20, 0x24, 0xd2, 0x12, 0x9c, 0xd1, 0xcf, 0x82, 0x10, 0x12, 0x4c, 0xcd, 0xcb, 0x09, 0x56, -0xc9, 0x49, 0x30, 0xc7, 0x09, 0x52, 0xc3, 0x02, 0x17, 0x76, 0x12, 0x4c, 0xc1, 0xbe, 0x82, 0x10, -0x12, 0x4c, 0xbd, 0xbc, 0x27, 0x58, 0xbb, 0x20, 0xc1, 0x66, 0xc6, 0xb9, 0x49, 0x70, 0x76, 0x5f, -0x24, 0x48, 0xb5, 0x82, 0xd3, 0x06, 0x64, 0x4b, 0xb3, 0x20, 0x70, 0x82, 0xb0, 0x02, 0x49, 0xae, -0x63, 0xc0, 0x4b, 0xfe, 0xfb, 0x41, 0x08, 0x6b, 0x25, 0xa5, 0x14, 0x49, 0x30, 0xa3, 0x49, 0x70, -0x7e, 0xa1, 0xc1, 0x6b, 0x80, 0x87, 0x25, 0x9f, 0xa3, 0x97, 0x04, 0x9d, 0x1e, 0x80, 0x04, 0x9b, -0x12, 0xbc, 0x1b, 0x99, 0xc1, 0x5b, 0x0d, 0x30, 0x3b, 0x97, 0xd4, 0x1c, 0x48, 0x95, 0x7c, 0x02, -0x12, 0x93, 0x04, 0x8f, 0xaf, 0x82, 0x95, 0x90, 0x58, 0x40, 0x8e, 0xb3, 0x04, 0xaf, 0x1e, 0x82, -0x95, 0x8b, 0x41, 0x42, 0x88, 0xf0, 0x22, 0x87, 0x3c, 0x4a, 0x49, 0x84, 0x41, 0x32, 0xa3, 0x75, -0x20, 0x81, 0xfc, 0x82, 0x25, 0xaf, 0x13, 0x4c, 0x7e, 0x7d, 0x4b, 0x82, 0x7c, 0x68, 0x46, 0xcb, -0x5a, 0xf6, 0xca, 0x0d, 0x12, 0xbc, 0xb8, 0x77, 0x27, 0x58, 0x76, 0x96, 0x04, 0x75, 0x03, 0x09, -0x73, 0x40, 0x82, 0x3c, 0x71, 0x93, 0xe0, 0x78, 0x6f, 0x80, 0x1b, 0x06, 0x78, 0x6c, 0x82, 0x41, -0x6e, 0xf0, 0x04, 0x4b, 0x6c, 0x92, 0xe0, 0x6b, 0x6a, 0x92, 0xd0, 0xf9, 0x26, 0x04, 0x67, 0x7c, -0x03, 0x09, 0x65, 0xc1, 0xb2, 0xf0, 0x1b, 0x24, 0x30, 0x62, 0x61, 0x09, 0x0e, 0xe6, 0x5f, 0x86, -0x2d, 0x37, 0xd9, 0x09, 0x5d, 0x99, 0x42, 0x2a, 0x0a, 0x21, 0xc1, 0x58, 0x91, 0x20, 0x57, 0xb1, -0x19, 0xd7, 0x0d, 0xf0, 0x4a, 0x1c, 0x66, 0x1b, 0x48, 0x53, 0x45, 0xc1, 0x36, 0xf7, 0x8c, 0x82, -0x25, 0x50, 0x82, 0x41, 0x4f, 0x3c, 0xc1, 0x4a, 0x4c, 0xc1, 0x20, 0x4b, 0x3c, 0x0c, 0x24, 0x49, -0xff, 0x01, 0x12, 0x45, 0x18, 0xa9, 0x53, 0x76, 0x0d, 0x24, 0x41, 0xa9, 0x64, 0x35, 0xc0, 0x48, -0x30, 0x3d, 0x97, 0x1d, 0x76, 0x1b, 0xfe, 0x82, 0x24, 0x24, 0x58, 0x39, 0x7c, 0x38, 0x03, 0x06, -0x76, 0x96, 0x48, 0x10, 0x35, 0x12, 0x0c, 0xe6, 0x33, 0x04, 0x07, 0x3c, 0x09, 0x96, 0x31, 0x2f, -0x08, 0x09, 0xbf, 0x5e, 0x6c, 0x26, 0x29, 0x09, 0x09, 0x2b, 0x84, 0x04, 0x09, 0xc3, 0xb2, 0x8b, -0x6b, 0x98, 0xb0, 0x1b, 0x7c, 0x58, 0x76, 0xc1, 0x8b, 0x0e, 0x24, 0x21, 0xf0, 0xc9, 0xcb, 0x37, -0x70, 0x1c, 0x4c, 0x82, 0x1d, 0x58, 0x12, 0x1c, 0x24, 0x24, 0x1a, 0xb3, 0x25, 0xbf, 0x0d, 0x80, -0x04, 0x16, 0x12, 0xb8, 0x19, 0x14, 0x04, 0x58, 0x22, 0x92, 0xe0, 0x7c, 0x11, 0x82, 0x47, 0x83, -0x82, 0x4b, 0x0f, 0x0e, 0x41, 0x42, 0x0d, 0x70, 0x20, 0x0b, 0x70, 0x12, 0x48, 0x09, 0x48, 0x93, -0x66, 0x55, 0xdc, 0x5b, 0x2b, 0xa5, 0x53, 0xc0, 0xa7, 0xb2, 0xb7, 0x04, 0x95, 0x33, 0x0d, 0x84, -0xdb, 0xb4, 0xcc, 0x29, 0x0d, 0xb0, 0xcc, 0xf8, 0x0d, 0x30, 0x19, 0xf9, 0x76, 0xbd, 0x85, 0xf7, -0x61, 0xb7, 0xec, 0x45, 0x53, 0xdd, 0xd7, 0x32, 0x0d, 0x26, 0x98, 0xb0, 0x1b, 0x66, 0x5a, 0x40, -0xdb, 0x05, 0xde, 0xc0, 0x0d, 0x29, 0x01, 0xc9, 0x0d, 0x03, 0x96, 0xe9, 0xe7, 0x5e, 0x09, 0x94, -0x10, 0xb2, 0x19, 0x86, 0x1e, 0xe3, 0xf5, 0xc0, 0x80, 0x6e, 0xe1, 0x30, 0xe0, 0xce, 0xdf, 0x03, -0x36, 0x99, 0xc6, 0x37, 0x90, 0xc6, 0x0d, 0xcb, 0x80, 0xd9, 0x84, 0x65, 0xfb, 0xdb, 0x12, 0x26, -0xc6, 0xb1, 0x09, 0xeb, 0xc6, 0x0b, 0x84, 0xa4, 0xc6, 0xc5, 0x83, 0x07, 0xcf, 0x7f, 0x06, 0x24, -0xcd, 0x30, 0x6b, 0xeb, 0x2b, 0x19, 0xcb, 0x43, 0xde, 0x0e, 0x7c, 0xc1, 0x6f, 0x66, 0xf3, 0x01, -0x03, 0xc7, 0x60, 0x42, 0x66, 0x09, 0x33, 0xc5, 0xb1, 0x2d, 0x61, 0x17, 0xb7, 0xec, 0x0d, 0xb5, -0x29, 0xc0, 0xb2, 0xa7, 0x80, 0x65, 0xbd, 0x40, 0xc2, 0xbb, 0x60, 0x65, 0xb9, 0x90, 0x30, 0xb7, -0xb3, 0x18, 0xb5, 0x53, 0x48, 0x06, 0x5a, 0x24, 0x0c, 0xb1, 0x73, 0x06, 0xaf, 0x63, 0xb0, 0x6d, -0x6e, 0xc3, 0x85, 0x1f, 0x0d, 0x0c, 0xf8, 0x36, 0x6e, 0xda, 0xac, 0x03, 0xdc, 0xd8, 0xaa, 0x01, -0x0b, 0x32, 0xe0, 0xa8, 0xa6, 0x19, 0x10, 0xa3, 0x03, 0x02, 0x9f, 0xe0, 0x2a, 0xf8, 0xb0, 0x32, -0x9b, 0x5b, 0x18, 0x99, 0xb6, 0x03, 0xce, 0x95, 0x01, 0x2b, 0x60, 0x90, 0x93, 0xb0, 0x32, 0x8f, -0x03, 0x1e, 0x8d, 0x8b, 0x01, 0x29, 0x80, 0x95, 0x89, 0x60, 0xc8, 0x87, 0x1f, 0xac, 0x30, 0x83, -0x42, 0x06, 0x51, 0x2b, 0x03, 0x7d, 0x94, 0x01, 0x7b, 0xd9, 0x80, 0x77, 0x1f, 0xc0, 0x08, 0x03, -0x66, 0x75, 0x73, 0x01, 0x2b, 0x30, 0xe0, 0x71, 0x6f, 0x07, 0x8c, 0x6d, 0xca, 0x80, 0x6b, 0x65, -0x40, 0x69, 0xc8, 0x80, 0x67, 0x65, 0xc0, 0x65, 0x01, 0x6e, 0x1b, 0x70, 0x85, 0x61, 0x3f, 0x46, -0x18, 0x5d, 0x18, 0xf0, 0xd1, 0x59, 0x01, 0x53, 0xff, 0x70, 0x85, 0x55, 0xf8, 0x02, 0x18, 0x51, -0x20, 0x03, 0x4d, 0x64, 0x40, 0x49, 0x0c, 0x08, 0x47, 0x30, 0xad, 0x3f, 0x38, 0x0c, 0x44, 0x78, -0xb0, 0x0c, 0x42, 0x60, 0x19, 0x41, 0x90, 0x30, 0x3f, 0x20, 0x19, 0x3d, 0x18, 0x30, 0x3c, 0x7e, -0x0c, 0x0c, 0x3a, 0x60, 0x06, 0x38, 0x30, 0x30, 0x37, 0x6b, 0x19, 0x35, 0x1d, 0x93, 0x91, 0x1d, -0xfe, 0x03, 0x26, 0x31, 0x03, 0x2e, 0xee, 0x2f, 0x80, 0x03, 0x3c, 0x80, 0xc9, 0x2c, 0x7e, 0x96, -0xc0, 0x2a, 0x29, 0x6b, 0xad, 0x78, 0x0b, 0x8f, 0xc2, 0x62, 0x1e, 0xbf, 0x65, 0x40, 0x25, 0x32, -0x60, 0x22, 0x65, 0xc0, 0x20, 0x32, 0x20, 0x1e, 0x60, 0xc0, 0x1c, 0x0c, 0x48, 0x19, 0x01, 0x23, -0x03, 0x96, 0x17, 0x15, 0x64, 0xc0, 0x12, 0x06, 0x0c, 0x18, 0x0f, 0x80, 0x43, 0x3c, 0x1c, 0xc0, -0xca, 0x0d, 0x20, 0x64, 0x0b, 0x2e, 0x30, 0x08, 0x08, 0x2c, 0x03, 0x05, 0x80, 0x03, 0xfc, 0x0c, -0x70, 0xfb, 0xf6, 0xa0, 0x01, 0xf5, 0x6c, 0x00, 0x13, 0xee, 0xda, 0x82, 0xe9, 0x06, 0x38, 0x6b, -0x85, 0x61, 0x0d, 0x0f, 0xd0, 0xda, 0x10, 0x05, 0x20, 0x08, 0xd7, 0x40, 0x10, 0xd1, 0x80, 0x20, -0xcb, 0xf0, 0x41, 0xc5, 0x0f, 0x07, 0x0f, 0x7d, 0x01, 0x0c, 0xbf, 0xba, 0x03, 0x04, 0xb4, 0x50, -0x80, 0xb3, 0xc0, 0x0f, 0xae, 0x67, 0xe6, 0xc0, 0x06, 0x30, 0xa7, 0xa8, 0x75, 0x80, 0x80, 0xa1, -0x03, 0x2c, 0xef, 0x02, 0x9b, 0x38, 0xc0, 0x02, 0x42, 0x00, 0x06, 0x33, 0x06, 0x98, 0x8f, 0x8a, -0xc0, 0x00, 0x89, 0xbb, 0xdb, 0xae, 0x61, 0x49, 0x3c, 0x86, 0x7c, 0xd0, 0xef, 0x05, 0x27, 0x26, -0x4d, 0x80, 0xff, 0x72, 0xc0, 0x3b, 0x35, 0x0f, 0x80, 0x24, 0x65, 0x09, 0x70, 0x5f, 0x59, 0x03, -0x7c, 0x24, 0x66, 0xff, 0x12, 0xf1, 0x80, 0x9f, 0xc0, 0x8b, 0xef, 0x2e, 0x6f, 0x20, 0x3d, 0x46, -0x00, 0x1d, 0x7c, 0x24, 0x8f, 0x86, 0x31, 0x57, 0xdb, 0xea, 0x18, 0x3e, 0x60, 0x58, 0x7c, 0x29, -0x80, 0x86, 0xd7, 0x07, 0x78, 0x23, 0x38, 0x1e, 0x24, 0xab, 0x76, 0xcc, 0xc3, 0x34, 0xf9, 0x30, -0x0f, 0x00, 0xe6, 0x0c, 0x01, 0x92, 0x06, 0x00, 0x83, 0x2d, 0x2b, 0x7e, 0x1a, 0x08, 0xd6, 0xc7, -0xb0, 0xe8, 0xb7, 0xab, 0x47, 0xd6, 0xc3, 0xdd, 0xab, 0x58, 0xc2, 0xc9, 0xf7, 0xe2, 0x1c, 0xe5, -0x07, 0xea, 0x55, 0x3c, 0xb3, 0x0f, 0xce, 0xca, 0x1e, 0x6a, 0x5c, 0xbd, 0xfc, 0x0f, 0xbf, 0xa6, -0xae, 0xbe, 0x7c, 0x43, 0x3d, 0x62, 0x79, 0xb1, 0xab, 0xef, 0x02, 0x07, 0x7e, 0xab, 0xab, 0x17, -0x74, 0x62, 0xbc, 0x37, 0x77, 0x67, 0xb2, 0x7a, 0xaa, 0x94, 0xab, 0x47, 0xa6, 0x8d, 0xcd, 0xea, -0x7c, 0x88, 0xed, 0xca, 0x07, 0x82, 0xc0, 0x78, 0xc4, 0xe2, 0x87, 0x37, 0xaf, 0x4e, 0x6f, 0x75, -0x60, 0x68, 0xc3, 0x38, 0xf5, 0xca, 0xd0, 0x6b, 0x58, 0x7c, 0x69, 0xfe, 0x4a, 0xa1, 0xd9, 0xfe, -0x07, 0xf5, 0x57, 0x9f, 0x1f, 0xce, 0x57, 0x05, 0x2b, 0x52, 0x2d, 0x58, 0x4d, 0x2f, 0x06, 0xab, -0x1e, 0x45, 0xe6, 0x1a, 0x8c, 0x7f, 0xf0, 0x55, 0xb0, 0x39, 0x27, 0x26, 0xa1, 0x6d, 0xa0, 0x13, -0x6c, 0x7a, 0xc3, 0x5e, 0x6f, 0xfc, 0x3d, 0x45, 0x0f, 0xce, 0x7c, 0x0e, 0xda, 0x8b, 0x37, 0x5f, -0x2b, 0xe7, 0xa8, 0x7f, 0x0b, 0x2c, 0xde, 0x57, 0x3d, 0x08, 0x35, 0x56, 0x41, 0x2a, 0xf8, 0x53, -0xbd, 0x00, 0x0c, 0x46, 0x7a, 0x0f, 0x67, 0x27, 0xea, 0x9e, 0xe7, 0x32, 0x6f, 0x3c, 0x40, 0x90, -0xdf, 0x99, 0x3a, 0x97, 0xd9, 0xc5, 0x49, 0xd5, 0x3c, 0x40, 0xe0, 0xe9, 0x91, 0xa9, 0xc3, 0xba, -0xbc, 0xa9, 0x01, 0x76, 0x39, 0x35, 0x80, 0x75, 0xdc, 0x87, 0x09, 0xb8, 0x7f, 0x86, 0x44, 0x26, -0xbb, 0x87, 0x9e, 0x7c, 0x97, 0x60, 0xf8, 0x75, 0x46, 0xf5, 0x76, 0xca, 0x35, 0x09, 0xf8, 0x2f, -0x8b, 0x76, 0x92, 0xaf, 0x7c, 0x15, 0xde, 0x7f, 0x69, 0x70, 0x4f, 0x84, 0x3c, 0x17, 0x24, 0x7a, -0x00, 0xe6, 0x56, 0x22, 0xb5, 0x74, 0x30, 0xa4, 0x52, 0x2c, 0x18, 0x6d, 0x0f, 0x9a, 0x6c, 0x7c, -0x4f, 0x1e, 0x67, 0x91, 0x56, 0x5f, 0x7e, 0xa1, 0x04, 0xa3, 0x87, 0xea, 0x54, 0x4a, 0x58, 0x4c, -0x49, 0xbf, 0x90, 0x62, 0x26, 0x86, 0x54, 0x37, 0x63, 0x11, 0x00, 0x17, 0x7e, 0x83, 0x73, 0x2f, -0x37, 0xdf, 0xf5, 0x54, 0x7e, 0x21, 0x70, 0x90, 0x3a, 0x1f, 0x19, 0xe5, 0xde, 0x0c, 0x12, 0x92, -0x9a, 0x6b, 0x07, 0xa3, 0xc3, 0xc6, 0xff, 0x36, 0x1b, 0xcc, 0x5f, 0x3b, 0x46, 0xb3, 0xe7, 0xf0, -0xb3, 0x6e, 0x6f, 0xcc, 0x07, 0xb6, 0xc9, 0x60, 0x30, 0x17, 0x38, 0x09, 0x4d, 0xbf, 0x82, 0xd1, -0x70, 0xd2, 0x9d, 0x19, 0x97, 0x07, 0x30, 0x8c, 0x82, 0x3f, 0xc0, 0x98, 0x1b, 0x3c, 0x1f, 0x07, -0x8e, 0xb9, 0x17, 0x07, 0xc6, 0x10, 0x73, 0x33, 0x68, 0x47, 0x27, 0x33, 0x81, 0x0d, 0x2c, 0x3a, -0x69, 0xf8, 0xa1, 0xec, 0xa3, 0x85, 0x7f, 0x6e, 0x97, 0xd4, 0xd1, 0x96, 0xce, 0xa3, 0x60, 0x90, -0x47, 0x9b, 0x0d, 0x57, 0x07, 0x82, 0x91, 0x7e, 0x9d, 0xf0, 0x8f, 0x0f, 0xc6, 0x70, 0x9a, 0xf7, -0x98, 0x7a, 0xef, 0x17, 0x0e, 0x27, 0xa6, 0x66, 0x4a, 0x55, 0x80, 0x23, 0x47, 0x5a, 0x59, 0xc8, -0x11, 0x1d, 0x42, 0xc5, 0x53, 0x18, 0x1d, 0xfd, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, 0x48, 0x3c, 0xa3, -0x47, 0x47, 0x42, 0xb3, 0x37, 0xf7, 0x9f, 0xf6, 0x62, 0xff, 0x3f, 0x5f, 0x30, 0x0a, 0x2a, 0x31, -0xdc, 0x07, 0xb8, 0x4a, 0x46, 0x1f, 0xd1, 0x30, 0x19, 0x93, 0x9b, 0x12, 0x08, 0xa1, 0x0d, 0xa3, -0x06, 0xe6, 0xbf, 0x07, 0x63, 0xe6, 0x6c, 0x7e, 0x33, 0x66, 0xcc, 0x0f, 0xa1, 0xf6, 0x7a, 0x36, -0x6a, 0xdf, 0x11, 0xf4, 0xee, 0x35, 0x10, 0x16, 0xdd, 0xc3, 0x66, 0x33, 0xcf, 0x66, 0x09, 0x22, -0x42, 0xb3, 0x88, 0x01, 0xd9, 0x10, 0x1a, 0xd4, 0x95, 0xd0, 0xca, 0x34, 0xa1, 0x9a, 0xa1, 0x21, -0xbe, 0xb8, 0x08, 0x0d, 0xb2, 0x48, 0x68, 0xac, 0x96, 0xd0, 0xa0, 0xd0, 0x84, 0x9a, 0x84, 0x86, -0x94, 0x8e, 0x84, 0x0e, 0xf8, 0x82, 0x08, 0x05, 0x7c, 0x08, 0x1d, 0xff, 0x70, 0x16, 0x0b, 0x0f, -0x1f, 0x10, 0x1a, 0x5e, 0x3c, 0x14, 0x52, 0x37, 0xa1, 0x84, 0x4c, 0x25, 0x34, 0x46, 0xd0, 0xa1, -0x40, 0x84, 0x96, 0x3a, 0x34, 0x21, 0x34, 0x2e, 0x0d, 0xa1, 0x28, 0x6e, 0x09, 0x22, 0x0f, 0xa1, -0x61, 0x6f, 0x10, 0x42, 0x01, 0x0a, 0x31, 0x5b, 0x77, 0x6f, 0x60, 0xfe, 0x27, 0x06, 0x16, 0xf2, -0x78, 0xc3, 0xd7, 0x27, 0x31, 0xb0, 0xdd, 0x62, 0x60, 0xd7, 0xc4, 0xc0, 0xcb, 0x17, 0x93, 0x81, -0xc8, 0xc1, 0x88, 0x45, 0x78, 0xbc, 0xb3, 0xd8, 0x5d, 0xfe, 0xb6, 0x18, 0x16, 0xb0, 0x16, 0xb1, -0xab, 0xa9, 0x60, 0x71, 0x7e, 0xa3, 0xe2, 0x8b, 0x9c, 0xc0, 0x16, 0xc3, 0x98, 0x92, 0xf1, 0x22, -0x91, 0xc7, 0xe9, 0xd6, 0x97, 0x86, 0xe2, 0x8b, 0x85, 0x0e, 0x2c, 0xc6, 0x80, 0x3c, 0x7a, 0xef, -0xd5, 0x8f, 0x07, 0x0b, 0x17, 0x73, 0x6f, 0xf5, 0xa2, 0x7e, 0x6d, 0xde, 0x9b, 0xff, 0x66, 0x01, -0x36, 0x0c, 0x2e, 0x29, 0x17, 0x81, 0x9e, 0x07, 0x5e, 0x38, 0x05, 0x4f, 0x25, 0x2c, 0x4b, 0xcc, -0xe2, 0x7f, 0x3e, 0x63, 0x59, 0x38, 0x87, 0x90, 0xc5, 0x2c, 0x2c, 0xbe, 0x06, 0x0f, 0x1f, 0x62, -0x31, 0x1b, 0xc2, 0xbd, 0xdd, 0x50, 0x5d, 0x45, 0x3d, 0x79, 0x3c, 0x88, 0x24, 0x20, 0x37, 0x33, -0x81, 0x4c, 0x1c, 0x39, 0x52, 0x03, 0x69, 0x26, 0x11, 0x84, 0x20, 0x90, 0x16, 0x22, 0x00, 0x78, -0xf9, 0x04, 0x7c, 0xce, 0xd6, 0xe6, 0x7c, 0x40, 0x2b, 0x83, 0x33, 0xda, 0x7b, 0x1c, 0x1d, 0x1e, -0x50, 0xc3, 0x1f, 0x10, 0xe7, 0x7c, 0x01, 0x61, 0x33, 0x76, 0x3f, 0x7c, 0x82, 0xb2, 0xaa, 0xaa, -0x02, 0x82, 0x7c, 0xc2, 0x20, 0x33, 0xd4, 0x2a, 0x2c, 0xa2, 0x8d, 0xa3, 0x85, 0x85, 0x0f, 0x2d, -0xe4, 0x60, 0x30, 0xdd, 0xc5, 0xef, 0x9a, 0xa2, 0x00, 0x9a, 0x20, 0x62, 0xef, 0x84, 0xca, 0x33, -0x95, 0x45, 0x53, 0xb2, 0x88, 0x43, 0x06, 0x11, 0x33, 0x1a, 0x44, 0x11, 0xb3, 0xd0, 0xb9, 0x64, -0x93, 0x0c, 0x88, 0x84, 0xff, 0x28, 0x32, 0x33, 0x6a, 0x52, 0x0f, 0x82, 0x31, 0x41, 0xc6, 0xf3, -0xb1, 0x83, 0x34, 0x18, 0x2c, 0x06, 0x92, 0xa0, 0x03, 0x43, 0xe4, 0xf6, 0xbf, 0x30, 0x8a, 0x53, -0x0b, 0xbb, 0xc6, 0x0f, 0x30, 0x8a, 0x30, 0x73, 0x46, 0x0c, 0x1c, 0xe4, 0x48, 0x0f, 0x5a, 0x12, -0x03, 0x61, 0x06, 0xc4, 0x0f, 0x42, 0x72, 0x00, 0xca, 0x20, 0x33, 0x9b, 0x85, 0x40, 0x47, 0xec, -0x05, 0x9f, 0x7f, 0x85, 0x85, 0x36, 0x04, 0xbd, 0x9f, 0x88, 0x91, 0x43, 0xde, 0x32, 0x33, 0xff, -0xec, 0xc2, 0x1f, 0x30, 0x2f, 0x30, 0xac, 0xd2, 0x16, 0xa4, 0xf4, 0x0c, 0x31, 0x5b, 0x0f, 0x56, -0x06, 0x33, 0xfa, 0x00, 0xc3, 0x7c, 0x01, 0x01, 0xa3, 0x14, 0xb3, 0xf0, 0x0e, 0x90, 0xef, 0x2c, -0x8f, 0xc6, 0x49, 0x37, 0x7f, 0xc6, 0x09, 0x0b, 0x0f, 0xe2, 0x55, 0x11, 0xb7, 0xa4, 0x73, 0x0c, -0x90, 0x20, 0x73, 0x85, 0x91, 0x39, 0x81, 0xbd, 0x5f, 0x00, 0x2d, 0x21, 0xbb, 0x42, 0x16, 0x10, -0x09, 0xa1, 0xe7, 0x8a, 0x6f, 0xbd, 0x30, 0x62, 0x36, 0xec, 0xd1, 0x32, 0xa3, 0x56, 0x59, 0x33, -0xc8, 0x20, 0x33, 0x59, 0xd1, 0x0b, 0x59, 0x34, 0x78, 0x1d, 0xcd, 0x18, 0x94, 0xb0, 0x95, 0x2a, -0x0a, 0x1e, 0x11, 0xd0, 0x82, 0xcb, 0x0f, 0x7c, 0x20, 0x9a, 0x21, 0x7c, 0x22, 0xc0, 0x33, 0x45, -0x8a, 0x03, 0x5a, 0x1d, 0xcf, 0x83, 0xb8, 0xe6, 0x7c, 0x80, 0x33, 0x01, 0x23, 0x0c, 0x98, 0xcb, -0xca, 0x02, 0x90, 0x13, 0x0c, 0x62, 0x33, 0x8c, 0x02, 0x00, 0x07, 0xb3, 0x06, 0xf1, 0xb2, 0x33, -0x02, 0x05, 0x01, 0x03, 0x9b, 0x84, 0x01, 0x99, 0xc2, 0x80, 0x97, 0x65, 0x40, 0x95, 0xf1, 0x80, -0x94, 0x44, 0x06, 0x33, 0x2c, 0x22, 0x0f, 0x07, 0x8c, 0x89, 0x41, 0x98, 0x02, 0x90, 0x33, 0x2e, -0x03, 0x79, 0x76, 0x03, 0x03, 0x77, 0x83, 0x70, 0xdf, 0x33, 0xa4, 0x0a, 0x4b, 0x06, 0x67, 0x03, -0x60, 0x40, 0x65, 0x04, 0x68, 0xe9, 0x16, 0x99, 0xf6, 0x95, 0x10, 0x8a, 0xcf, 0x03, 0x3b, 0xc6, -0x0d, 0x12, 0x8a, 0x30, 0xeb, 0x42, 0xb1, 0x0b, 0x32, 0x60, 0x59, 0x90, 0xdf, 0x0d, 0x3c, 0x66, -0x09, 0x39, 0x00, 0x64, 0x10, 0x33, 0xc4, 0x42, 0x38, 0x80, 0x20, 0x57, 0xec, 0xc0, 0x49, 0x3c, -0x22, 0x03, 0xce, 0x45, 0x88, 0x23, 0x7c, 0x10, 0x32, 0x33, 0x60, 0x19, 0x41, 0x64, 0x26, 0x56, -0x29, 0x30, 0x60, 0x30, 0xb7, 0x6c, 0x7c, 0x0a, 0x0d, 0x32, 0x88, 0x33, 0x1e, 0xb0, 0x37, 0xe4, -0x03, 0x35, 0xe0, 0x1e, 0x30, 0x34, 0x2e, 0x03, 0x33, 0x7c, 0x42, 0xc6, 0x6f, 0xc6, 0x60, 0x59, -0x0d, 0xc5, 0x32, 0x2d, 0x03, 0x1c, 0xcb, 0x2b, 0x13, 0x2c, 0x1a, 0xca, 0x80, 0x27, 0x56, 0x34, -0x56, 0x80, 0x14, 0x78, 0xc0, 0x1f, 0x63, 0x36, 0xec, 0x34, 0xa3, 0x15, 0x54, 0x46, 0x73, 0xc0, -0x80, 0x19, 0x06, 0x3c, 0x18, 0x70, 0x15, 0x32, 0x60, 0x13, 0x03, 0x06, 0x18, 0x0f, 0xc0, 0x02, -0x20, 0x62, 0x0d, 0x00, 0xc2, 0x33, 0x47, 0x83, 0x5f, 0xc4, 0xa3, 0x5e, 0x3d, 0x18, 0x33, 0x00, -0x3a, 0x6c, 0x30, 0xda, 0x0f, 0x6c, 0xb8, 0x4e, 0x18, 0xc4, 0x33, 0x28, 0x14, 0x0e, 0xcd, 0x0c, -0x39, 0xc2, 0x20, 0x33, 0x68, 0x09, 0x97, 0x16, 0x89, 0x6b, 0x9c, 0xc9, 0xb3, 0x07, 0x60, 0x30, -0xd0, 0xa1, 0xb2, 0x0c, 0xe2, 0xb1, 0x33, 0x11, 0xa1, 0x88, 0x20, 0x43, 0x44, 0x90, 0x3b, 0x10, -0x19, 0x33, 0x30, 0xa1, 0x5e, 0xc4, 0xec, 0x17, 0x7f, 0x10, 0x19, 0x33, 0xdf, 0xa1, 0x28, 0xcd, -0x76, 0xe2, 0xd0, 0x18, 0x6c, 0x22, 0x95, 0x8f, 0x9b, 0xf6, 0x22, 0x0e, 0x19, 0xb1, 0xd6, 0x44, -0x59, 0x06, 0x45, 0x6c, 0x07, 0x30, 0x10, 0x92, 0x53, 0x9f, 0x22, 0x50, 0xe6, 0x16, 0x2c, 0xfb, -0x06, 0x10, 0x6e, 0x07, 0x0a, 0x65, 0x33, 0x1b, 0x24, 0x20, 0x30, 0x3f, 0x86, 0x05, 0x1b, 0x1c, -0x11, 0x57, 0x12, 0xc1, 0x20, 0x33, 0xf0, 0x0e, 0x5f, 0x0f, 0x16, 0xef, 0x5f, 0x07, 0x9f, 0x8b, -0x0d, 0x7c, 0xef, 0x27, 0x19, 0xc4, 0x33, 0x3c, 0x8a, 0x5a, 0x2f, 0x5e, 0x89, 0x93, 0x45, 0x73, -0x07, 0x47, 0x98, 0x9b, 0x6f, 0xbf, 0x07, 0x23, 0xd8, 0x30, 0x0f, 0x4f, 0x5f, 0x84, 0xd3, 0x0c, -0xf1, 0x0e, 0x79, 0x77, 0x63, 0x65, 0x6b, 0x4d, 0x19, 0xc4, 0x33, 0xc1, 0x22, 0x53, 0x40, 0xff, -0xe1, 0x32, 0xe4, 0x3a, 0xf6, 0x2a, 0x5f, 0x86, 0xa0, 0x20, 0x34, 0x45, 0x12, 0x33, 0x8b, 0x81, -0x3e, 0x35, 0x8b, 0x87, 0x87, 0x2e, 0x8b, 0x21, 0x18, 0x21, 0x20, 0x0e, 0x3c, 0x6c, 0xf1, 0x2b, -0x7a, 0x78, 0x90, 0x41, 0x33, 0x01, 0x39, 0xb5, 0x72, 0xc1, 0x93, 0x54, 0x9d, 0x4c, 0x44, 0x56, -0x67, 0x4a, 0x52, 0x09, 0x80, 0x68, 0x44, 0x35, 0xca, 0x2a, 0xa7, 0x05, 0xe6, 0xc0, 0x5a, 0x59, -0x67, 0x80, 0x1f, 0xff, 0x1a, 0x1e, 0x1c, 0x8b, 0x8d, 0x37, 0x58, 0xd6, 0x56, 0xc1, 0x67, 0xa5, -0x46, 0x49, 0x64, 0x01, 0x83, 0x4c, 0x36, 0x33, 0x12, 0x7c, 0x65, 0x15, 0x67, 0x10, 0x6e, 0x6c, -0x60, 0x49, 0x97, 0x29, 0xab, 0x67, 0x88, 0x70, 0x1f, 0x05, 0x4b, 0x27, 0x4b, 0x59, 0x67, 0x37, -0x16, 0x44, 0xb7, 0xac, 0x12, 0x3f, 0x48, 0x16, 0x5f, 0xca, 0x2a, 0x67, 0x65, 0x9f, 0x00, 0xf6, -0x62, 0x64, 0x3f, 0xc8, 0xbb, 0x00, 0x76, 0x32, 0x34, 0x30, 0x88, 0xd9, 0x78, 0x4f, 0x2c, 0x2c, -0xa7, 0x80, 0x38, 0x1f, 0x05, 0xcb, 0xb7, 0x17, 0x59, 0x67, 0x36, 0x2c, 0x88, 0x1c, 0xd7, 0x88, -0x87, 0x06, 0x12, 0x34, 0x0d, 0x0c, 0xe7, 0x93, 0xbf, 0xbf, 0x64, 0x6c, 0x78, 0x70, 0xe0, 0xe0, -0x65, 0x10, 0x33, 0x09, 0x20, 0xd6, 0x58, 0x82, 0x8f, 0xca, 0x2a, 0x67, 0x25, 0xac, 0x5f, 0x09, -0xd5, 0x18, 0xa1, 0xdc, 0xb0, 0x4f, 0x0f, 0x90, 0xd0, 0x6d, 0x8f, 0x41, 0xbc, 0x7f, 0x21, 0x21, -0x37, 0x7f, 0x92, 0x2d, 0x3f, 0x59, 0x10, 0xff, 0x0f, 0x57, 0x85, 0xaf, 0x29, 0x1e, 0x54, 0xf0, -0xe8, 0x65, 0xc3, 0x8f, 0x3f, 0x21, 0xb8, 0xf4, 0xcf, 0x0b, 0x22, 0x07, 0x1e, 0x03, 0x5f, 0xc8, -0x20, 0x33, 0x25, 0x8b, 0x41, 0x0b, 0xfd, 0x18, 0x59, 0x63, 0x70, 0xcb, 0x0f, 0xaf, 0x2a, 0x83, -0x33, 0xc8, 0x18, 0x18, 0xff, 0x84, 0xd9, 0x12, 0x2f, 0x19, 0xc4, 0x33, 0x6d, 0x15, 0xd4, 0x68, -0x61, 0xff, 0x61, 0x9c, 0x49, 0x1f, 0x30, 0x88, 0x33, 0x9c, 0x00, 0x0c, 0x7e, 0x21, 0x45, 0x27, -0x0c, 0x22, 0x33, 0xe2, 0xb0, 0xaf, 0x0b, 0x81, 0x47, 0x91, 0x90, 0xc6, 0x29, 0xc2, 0x7f, 0x67, -0xe2, 0x2d, 0x2f, 0x2c, 0x09, 0x67, 0x95, 0x41, 0x33, 0x0e, 0x69, 0x8f, 0xfe, 0x06, 0x71, 0x33, -0x62, 0x55, 0x03, 0x2b, 0xf7, 0x06, 0x1c, 0x4f, 0x8d, 0x62, 0x59, 0x3f, 0xaa, 0x0c, 0x33, 0xc2, -0xdc, 0x2f, 0xdf, 0x62, 0x52, 0x8f, 0x2d, 0x29, 0xc7, 0xb7, 0xec, 0xcf, 0x0f, 0x0d, 0x8d, 0x2c, -0xef, 0xcd, 0x9a, 0xef, 0xef, 0x81, 0xe2, 0x4f, 0xc7, 0x20, 0x26, 0xf6, 0xd8, 0xca, 0x33, 0x5f, -0x29, 0x22, 0xe7, 0x78, 0x30, 0x0f, 0x08, 0x83, 0x33, 0x15, 0xb1, 0x86, 0x80, 0x07, 0x0f, 0x65, -0x10, 0x33, 0x98, 0x0b, 0x5f, 0x00, 0x96, 0x56, 0x43, 0x3c, 0x12, 0x00, 0xfc, 0x51, 0x10, 0x88, -0x85, 0x71, 0x28, 0x30, 0x33, 0xa4, 0xec, 0x18, 0x37, 0x04, 0x1e, 0xff, 0x7f, 0x04, 0xb7, 0x3a, -0x3f, 0x96, 0xb0, 0x7f, 0x05, 0x13, 0x2f, 0x45, 0x59, 0x67, 0x68, 0x14, 0x55, 0x60, 0x6d, 0xcc, -0x91, 0x9f, 0xc0, 0xb2, 0x0a, 0x67, 0x18, 0x30, 0xf5, 0xf0, 0x22, 0xa4, 0x84, 0x55, 0x67, 0xcb, -0x80, 0xf1, 0xc0, 0x80, 0x7c, 0xef, 0xab, 0xe0, 0x7c, 0x67, 0x70, 0x21, 0x5e, 0x40, 0x82, 0x31, -0x65, 0x40, 0xe9, 0x41, 0xbc, 0x1b, 0x82, 0x65, 0x8f, 0x2c, 0xac, 0x67, 0x1b, 0x06, 0xe3, 0x0d, -0x19, 0x10, 0xe1, 0x55, 0x70, 0x3c, 0x20, 0x94, 0x67, 0x62, 0x33, 0xdb, 0x37, 0x2e, 0x03, 0xd9, -0x78, 0x2c, 0x03, 0xd7, 0x96, 0x10, 0x9b, 0x30, 0x20, 0x6d, 0x56, 0xc1, 0x67, 0x80, 0x15, 0x80, -0xcb, 0xcf, 0x3c, 0x40, 0xc0, 0xcd, 0x6f, 0x67, 0xcc, 0x78, 0x08, 0x3c, 0x38, 0x70, 0xa2, 0xd0, -0xf2, 0x36, 0x3f, 0x8d, 0x0c, 0x33, 0x87, 0x19, 0x47, 0x4f, 0x59, 0x05, 0x67, 0x84, 0x41, 0x33, -0x00, 0x94, 0xcd, 0x82, 0xb6, 0x45, 0x82, 0xa1, 0x0d, 0xca, 0x5d, 0x0c, 0x58, 0xb7, 0x61, 0xb6, -0xfb, 0x4f, 0x86, 0x2d, 0x37, 0x62, 0x13, 0xbf, 0x0d, 0x3b, 0x03, 0xb1, 0x66, 0x7d, 0x86, 0x25, -0x37, 0x96, 0xe0, 0xd5, 0x95, 0x92, 0x20, 0x93, 0x88, 0xc7, 0x13, 0xaa, 0x30, 0x33, 0x02, 0x49, -0x56, 0xf0, 0xed, 0x9d, 0x12, 0x06, 0xcd, 0x20, 0x5a, 0x99, 0x86, 0xc8, 0x33, 0x18, 0xb6, 0x30, -0x9f, 0x10, 0x31, 0x61, 0x09, 0x15, 0x06, 0x33, 0x0c, 0x58, 0x79, 0x06, 0x04, 0x77, 0x10, 0x07, -0x76, 0x01, 0x65, 0x33, 0xc1, 0x80, 0x65, 0x32, 0x88, 0x76, 0x33, 0x19, 0x10, 0x61, 0x10, 0x2f, -0x0d, 0x20, 0x61, 0x33, 0xe0, 0x32, 0x5d, 0x76, 0x91, 0x30, 0x5b, 0x45, 0x06, 0x33, 0x19, 0xa4, -0x1d, 0xfe, 0x19, 0xc4, 0x33, 0x88, 0x14, 0xb1, 0xa4, 0xe5, 0x32, 0xa0, 0x05, 0x49, 0x0c, 0xe2, -0x7c, 0x33, 0x40, 0x8a, 0x20, 0x60, 0x3f, 0x90, 0x30, 0x3d, 0x4b, 0x18, 0x3b, 0x0b, 0x16, 0xd6, -0x51, 0x66, 0xcd, 0xd1, 0x51, 0x2e, 0x03, 0x35, 0xe6, 0xc8, 0x20, 0x33, 0x65, 0x40, 0x31, 0x78, -0xc0, 0xf0, 0x2f, 0x02, 0x83, 0x33, 0x14, 0x11, 0x88, 0x97, 0x13, 0x0c, 0x38, 0x04, 0x32, 0x33, -0x14, 0x06, 0x23, 0x0c, 0xf8, 0x30, 0x1c, 0x6c, 0x38, 0x1d, 0x10, 0x2b, 0x01, 0x60, 0x33, 0xc0, -0x8c, 0xf5, 0x63, 0x65, 0x0f, 0x21, 0x80, 0x30, 0x17, 0xcb, 0x80, 0x0b, 0xac, 0x82, 0xf0, 0x67, -0x08, 0x02, 0x70, 0x10, 0x09, 0xc9, 0x2a, 0x87, 0xb1, 0x07, 0x61, 0x05, 0x87, 0x5c, 0xb5, 0xac, -0xab, 0xe0, 0x30, 0x70, 0xdc, 0x67, 0x0a, 0x06, 0x63, 0x18, 0x4d, 0x73, 0xc0, 0x55, 0x30, 0x7c, -0xfe, 0x83, 0x67, 0x0c, 0x18, 0xfe, 0x86, 0x1c, 0x70, 0xc2, 0xfe, 0x68, 0x41, 0x0f, 0xc4, 0x2a, -0xe1, 0x60, 0x15, 0x67, 0x67, 0xe8, 0x0c, 0xd8, 0x21, 0x07, 0xc6, 0x68, 0x06, 0x6c, 0xa5, 0x3c, -0xb2, 0x0a, 0x67, 0xef, 0x16, 0x07, 0xc2, 0xc4, 0x1f, 0xa3, 0x02, 0x88, 0x8d, 0x60, 0x17, 0x37, -0x7e, 0xc2, 0x0b, 0xdc, 0x17, 0x86, 0xfc, 0xdb, 0x00, 0x5e, 0x10, 0x08, 0xb2, 0x0a, 0x67, 0x78, -0x14, 0x63, 0xed, 0xb1, 0x2d, 0x23, 0x61, 0xf2, 0x2e, 0x1b, 0x88, 0x68, 0xd9, 0x3c, 0x78, 0xc3, -0xe8, 0xf0, 0x30, 0x3e, 0x4e, 0x31, 0x6b, 0x04, 0xc1, 0x50, 0x06, 0x33, 0x1e, 0xbd, 0xad, 0x27, -0x1e, 0xcd, 0x25, 0x21, 0xe2, 0xcd, 0xc7, 0x5f, 0x99, 0x01, 0xcf, 0xbd, 0x8b, 0xb9, 0x1f, 0xfd, -0x07, 0x7c, 0x74, 0x7c, 0xc2, 0x05, 0xc2, 0xc5, 0x1e, 0x67, 0x1f, 0xd9, 0xac, 0x27, 0xe7, 0xa5, -0x10, 0x86, 0x2f, 0x05, 0x60, 0x33, 0x40, 0xb8, 0xbf, 0x3c, 0xe1, 0x5b, 0x05, 0x30, 0xe0, 0x95, -0x41, 0x33, 0xf2, 0x2c, 0xb7, 0x18, 0x18, 0x0c, 0x62, 0x33, 0x43, 0x88, 0xf9, 0xc9, 0x87, 0x11, -0xc6, 0x7c, 0x32, 0x88, 0x33, 0x12, 0xa1, 0xc8, 0x98, 0xd0, 0x3e, 0x9f, 0x30, 0x83, 0x33, 0xc4, -0x60, 0xcd, 0xfc, 0x3f, 0x18, 0x33, 0x00, 0x3b, 0x19, 0x1a, 0x78, 0xc2, 0xc4, 0xd8, 0xd8, 0x18, -0x11, 0x0b, 0xa0, 0x42, 0x06, 0x33, 0x38, 0x1c, 0xc7, 0x79, 0x28, 0x83, 0x33, 0x4e, 0x6a, 0x7e, -0x0d, 0x38, 0x18, 0x2c, 0xd1, 0x7c, 0x28, 0x83, 0x33, 0xcc, 0x5a, 0x17, 0x6f, 0xbd, 0x5f, 0x56, -0xe6, 0xc6, 0x11, 0x13, 0x86, 0x07, 0x71, 0x11, 0x0c, 0xff, 0xd1, 0x6e, 0x6b, 0x1f, 0xaa, 0xfc, -0x39, 0x32, 0x88, 0x0c, 0x23, 0x63, 0x7b, 0xce, 0xf0, 0xe0, 0xb8, 0x63, 0x88, 0x19, 0xc4, 0x33, -0xf1, 0x5d, 0x18, 0x88, 0x0e, 0x0c, 0xa2, 0x07, 0x33, 0x58, 0x84, 0x5f, 0xf1, 0x58, 0x67, 0x62, -0x61, 0x4d, 0x08, 0x0c, 0x33, 0x6f, 0x42, 0xb1, 0x4f, 0xb9, 0x19, 0xbf, 0x1c, 0xb6, 0xf6, 0xa0, -0xce, 0x07, 0x97, 0xd8, 0x06, 0x61, 0x33, 0xc9, 0x53, 0xe9, 0x74, 0x50, 0x7a, 0x72, 0x55, 0xd1, -0x72, 0xc8, 0x88, 0x9b, 0x49, 0x8a, 0x01, 0x50, 0x85, 0x24, 0x22, 0x06, 0x83, 0x51, 0x0f, 0x33, -0x55, 0x19, 0x9b, 0xf1, 0x68, 0x5f, 0x40, 0x06, 0x33, 0x36, 0xa1, 0x6a, 0xaf, 0x98, 0x5b, 0x0c, -0x2f, 0x88, 0x4a, 0xa1, 0xc0, 0x9b, 0x30, 0x82, 0x18, 0x53, 0x11, 0xb5, 0x2f, 0x95, 0x9b, 0x7f, -0x09, 0x54, 0xdb, 0xab, 0x60, 0x67, 0x7a, 0x0b, 0xdf, 0x4b, 0xa2, 0xfb, 0x65, 0x10, 0x33, 0x57, -0x7c, 0x08, 0x1c, 0x36, 0x88, 0x2c, 0x22, 0x7d, 0x46, 0xd4, 0x9b, 0x0b, 0x15, 0x34, 0x1b, 0x99, -0x8f, 0x12, 0x6e, 0x99, 0xbf, 0xcc, 0x59, 0x54, 0x9b, 0x54, 0x6f, 0xcc, 0x1b, 0x19, 0xab, 0x00, -0x44, 0x2d, 0x6e, 0x65, 0x9b, 0xcc, 0x5e, 0x54, 0xbb, 0x06, 0x71, 0x33, 0x56, 0x05, 0xb3, 0x0a, -0x67, 0x20, 0x22, 0xaa, 0xc8, 0x33, 0x0a, 0xda, 0xeb, 0x52, 0xc8, 0x33, 0x3f, 0xaf, 0x60, 0x33, -0x60, 0x10, 0x33, 0x2c, 0x01, 0x00, 0x28, 0x23, 0xc2, 0x2a, 0x67, 0x59, 0x80, 0xbf, 0x2a, 0x08, -0xa1, 0xc2, 0x67, 0x4a, 0x6a, 0x55, 0xdf, 0x92, 0x5c, 0x12, 0xdf, 0x56, 0xc1, 0x67, 0xd9, 0x52, -0x0c, 0xff, 0x0d, 0x6b, 0x7e, 0x2f, 0x25, 0x3d, 0xd1, 0xf8, 0xef, 0xac, 0x82, 0x67, 0xc4, 0x28, -0x21, 0x73, 0x41, 0xbf, 0xc2, 0x72, 0x74, 0x9f, 0x57, 0x41, 0x67, 0x15, 0xc8, 0x18, 0xa6, 0x8c, -0x02, 0x6c, 0x55, 0x2a, 0x84, 0x37, 0xbb, 0x77, 0xec, 0xb8, 0xae, 0xc4, 0xb1, 0x2c, 0xef, 0x45, -0x06, 0x33, 0x04, 0x4b, 0x00, 0x65, 0x15, 0x67, 0x55, 0x41, 0x31, 0xa3, 0xe9, 0xa8, 0x07, 0x33, -0x8a, 0x8c, 0x9b, 0x08, 0x37, 0x26, 0x8c, 0x30, 0x33, 0x48, 0x06, 0xe3, 0x16, 0x23, 0x51, 0x29, -0x88, 0x5a, 0x21, 0xc0, 0x9b, 0x97, 0x01, 0xd5, 0x3c, 0x64, 0x10, 0x33, 0x35, 0x4b, 0x6f, 0x96, -0x40, 0x73, 0xb2, 0x0a, 0x67, 0x64, 0xc0, 0xcb, 0xc1, 0xa3, 0x5a, 0x56, 0x56, 0x67, 0x12, 0xa8, -0x81, 0x46, 0xd4, 0x9b, 0x4b, 0x05, 0x2d, 0x5b, 0x98, 0x7d, 0x10, 0x6e, 0x98, 0xa7, 0xb2, 0x96, -0x01, 0xb4, 0x2c, 0x03, 0xb3, 0x52, 0x06, 0xb2, 0x30, 0xa2, 0x9b, 0x19, 0x30, 0xad, 0x06, 0x71, -0x78, 0x33, 0x12, 0x01, 0x33, 0x03, 0x97, 0x32, 0x88, 0x33, 0x90, 0x00, 0x63, 0x18, 0x79, 0x67, -0x15, 0x2c, 0x83, 0x98, 0x73, 0x33, 0x0d, 0x28, 0x24, 0x58, 0x5e, 0x9c, 0xc9, 0x60, 0x15, 0x67, -0x60, 0x50, 0x38, 0x33, 0x49, 0xc2, 0x2a, 0x67, 0x59, 0x03, 0x7b, 0xb7, 0xa4, 0x63, 0x10, 0xb0, -0xac, 0x0b, 0x85, 0x55, 0x67, 0xc3, 0x80, 0x37, 0x81, 0x01, 0x35, 0x56, 0xc1, 0xe6, 0x67, 0x20, -0x10, 0xd9, 0x32, 0x2d, 0xa7, 0x01, 0xa6, 0x86, 0xc1, 0x85, 0x2a, 0x18, 0x55, 0x56, 0x67, 0xc0, -0x80, 0x21, 0x1e, 0xb0, 0x20, 0x2c, 0x03, 0x1f, 0x90, 0x41, 0x33, 0x03, 0x12, 0x0d, 0x55, 0x30, -0x54, 0x80, 0x67, 0x20, 0x06, 0x44, 0xcd, 0x33, 0x17, 0x65, 0x9b, 0x7e, 0x30, 0x88, 0xc3, 0x33, -0xcc, 0x95, 0xe1, 0x51, 0x19, 0xc4, 0x4b, 0x8c, 0xa8, 0x9b, 0x51, 0x08, 0x10, 0x83, 0x75, 0x3c, -0x2e, 0x64, 0x33, 0x3f, 0x5e, 0x51, 0x3b, 0xb0, 0x0a, 0x67, 0xcc, 0x5d, 0x4f, 0x7e, 0xc0, 0xce, -0x1e, 0x8c, 0x4e, 0x1e, 0x33, 0x00, 0x82, 0x87, 0x93, 0x78, 0x28, 0xac, 0x67, 0xc5, 0x5c, 0x41, -0x47, 0x51, 0xcc, 0x07, 0x5f, 0xc7, 0xc0, 0xaf, 0xa1, 0x0e, 0xdb, 0xc0, 0x6d, 0xb5, 0xf8, 0x30, -0x15, 0x4c, 0x92, 0xff, 0x64, 0x67, 0x70, 0xd8, 0x07, 0x03, 0x03, 0x73, 0x63, 0x30, 0x88, 0x3e, -0x33, 0x41, 0x28, 0x08, 0x56, 0x67, 0x22, 0x83, 0x33, 0xbe, 0x87, 0x7c, 0x82, 0x7c, 0x71, 0x7c, -0x62, 0x8e, 0xd5, 0xd1, 0xca, 0x20, 0x33, 0x90, 0x8d, 0x00, 0xac, 0x82, 0x67, 0x16, 0x22, 0x5f, -0x2a, 0x18, 0x85, 0xc2, 0x67, 0xc2, 0xd0, 0xf1, 0xc6, 0xef, 0x09, 0x05, 0xe9, 0xef, 0x8c, 0xa8, -0x9b, 0x70, 0x31, 0x99, 0x58, 0xbc, 0x98, 0x93, 0x55, 0x30, 0xe6, 0x23, 0x84, 0x67, 0xc1, 0xe4, -0xc7, 0x4f, 0xcc, 0x78, 0x98, 0xc5, 0x00, 0xca, 0x2a, 0x67, 0x58, 0xc2, 0x00, 0xc5, 0xbf, 0x56, -0xbc, 0xc0, 0x40, 0x80, 0x83, 0x88, 0xea, 0x33, 0x16, 0x22, 0x00, 0x2a, 0x48, 0x3c, 0xca, 0x67, -0x1d, 0xbf, 0xc9, 0x80, 0x59, 0xa2, 0xe0, 0x05, 0x99, 0x8a, 0xc8, 0xcf, 0x50, 0x49, 0x24, 0x41, -0x14, 0x8a, 0xa0, 0x04, 0xbf, 0xc2, 0xa2, 0xcf, 0xc4, 0x0a, 0x54, 0x18, 0x33, 0x8f, 0xa8, 0x9b, -0x02, 0x21, 0x30, 0x0a, 0xc7, 0x54, 0x30, 0x88, 0x85, 0x87, 0xa8, 0x32, 0x33, 0x46, 0xd4, 0x9b, -0x40, 0x56, 0x84, 0xa2, 0x49, 0x15, 0x5f, 0xaa, 0x08, 0x41, 0xcc, 0x71, 0x18, 0x91, 0x33, 0x43, -0x82, 0x17, 0x18, 0x51, 0x9b, 0x16, 0x04, 0xe2, 0xcc, 0x00, 0xad, 0x8c, 0xd3, 0x61, 0x44, 0x9b, -0x20, 0x52, 0xb1, 0x0c, 0xbf, 0x65, 0x00, 0x1f, 0x23, 0x6a, 0x9b, 0x0d, 0x02, 0x23, 0xca, 0x00, -0x9b, 0x80, 0x00, 0x47, 0x89, 0xa1, 0x8b, 0x02, 0xcf, 0x03, 0x02, 0x61, 0x10, 0x33, 0xa2, 0x02, -0x80, 0x38, 0x9b, 0x28, 0x58, 0x05, 0xcb, 0xfb, 0x08, 0x49, 0xa3, 0x22, 0x83, 0x33, 0x44, 0x25, -0x64, 0x64, 0x9b, 0xaa, 0x00, 0x61, 0x40, 0x65, 0x33, 0x20, 0x63, 0x61, 0x10, 0x33, 0x20, 0x46, -0x54, 0x30, 0xc1, 0x54, 0x46, 0x9b, 0x03, 0x02, 0x35, 0x01, 0x2b, 0x23, 0xea, 0x34, 0x9b, 0x31, -0x08, 0x58, 0x52, 0x65, 0x12, 0x80, 0x75, 0x11, 0x15, 0x4b, 0x95, 0x9b, 0x00, 0x46, 0x94, 0x9b, -0x40, 0x10, 0x42, 0x0e, 0x00, 0x00, 0x10, 0x09, 0x0a, 0x61, 0x33, 0xc2, 0x88, 0x9b, 0x02, 0x11, -0x63, 0x81, 0x08, 0xc3, 0x41, 0x04, 0x0a, 0x95, 0x33, 0xc0, 0x88, 0x9b, 0x14, 0xaa, 0x74, 0x22, -0x23, 0x20, 0x26, 0x1d, 0x31, 0xc2, 0x33, 0x82, 0x00, 0xbf, 0x30, 0xa2, 0x9b, 0x11, 0x02, 0x62, -0x64, 0x92, 0x21, 0x0c, 0x33, 0x20, 0x14, 0x2b, 0xa9, 0x82, 0x77, 0x44, 0x05, 0x06, 0x60, 0x9b, -0x11, 0xe5, 0x00, 0x53, 0x90, 0x9b, 0x51, 0x30, 0x88, 0xe5, 0x33, 0x3c, 0x19, 0x5a, 0x39, 0xbf, -0x59, 0x14, 0xcf, 0x59, 0x11, 0xa8, 0x00, 0x25, 0x09, 0x42, 0x05, 0xc0, 0x20, 0x33, 0x10, 0x2a, -0x64, 0x51, 0xcf, 0x50, 0x41, 0x0c, 0x22, 0x33, 0x04, 0xaa, 0x58, 0x14, 0xcf, 0x01, 0x00, 0x83, -0x18, 0x33, 0xa1, 0x00, 0x16, 0x05, 0xcf, 0x43, 0x40, 0x0d, 0xdb, 0xff, 0x0a, 0x54, 0x68, 0x69, -0x73, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x04, 0x69, 0x7f, 0xfb, 0x6c, 0x65, 0x20, 0x68, 0x61, 0x0d, -0x62, 0x65, 0x65, 0x6e, 0x20, 0x63, 0xdb, 0xfe, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x02, -0x69, 0x06, 0xfd, 0x9b, 0x13, 0x79, 0x20, 0x43, 0x50, 0x49, 0x61, 0x64, 0x6f, 0xbf, 0x09, 0x56, -0x31, 0x2e, 0x32, 0x30, 0x37, 0x43, 0x6f, 0x70, 0x7f, 0xf9, 0x79, 0x72, 0x69, 0x67, 0x68, 0x28, -0x43, 0x29, 0x20, 0x31, 0x39, 0xbf, 0xee, 0x39, 0x33, 0x2d, 0x04, 0x36, 0x28, 0x6b, 0x6f, 0xfe, -0xdb, 0x73, 0x74, 0x54, 0x40, 0x61, 0x63, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0xbb, 0xdb, 0x1f, 0x4b, -0x0f, 0x61, 0x20, 0x4b, 0x15, 0x07, 0x1b, 0x29, 0x71, 0x70, 0x72, 0xbb, 0xff, 0x6f, 0x67, 0x72, -0x61, 0x6d, 0x20, 0x6d, 0x61, 0x79, 0x6f, 0x20, 0x75, 0xd6, 0xba, 0x73, 0x63, 0x66, 0x72, 0x09, -0x6b, 0xed, 0x6f, 0x66, 0x7a, 0x84, 0x36, 0xdf, 0x5a, 0x09, 0x7e, 0x20, 0x79, 0x6f, 0x75, 0xd6, -0xb6, 0x72, 0x11, 0x77, 0x8d, 0x69, 0x00, 0xfc, 0x73, 0x6b, 0x2e, 0x0d, 0x0a, 0x00, 0x00, 0x00, -0x00, 0x00, 0x12, 0xff, 0xa4, 0xe8, 0x3a, 0x00, 0x72, 0xfa, 0x41, 0xe8, 0x2f, 0x00, 0xe3, 0x3b, -0x73, 0xf9, 0x83, 0xe9, 0x03, 0x72, 0x06, 0x88, 0xcc, 0xac, 0xf7, 0xd0, 0x95, 0x31, 0xc9, 0xe8, -0x1b, 0x00, 0x11, 0xc9, 0x75, 0x08, 0x41, 0xe8, 0x13, 0x00, 0x73, 0xfb, 0x41, 0x41, 0x81, 0xfd, -0x00, 0xf3, 0x83, 0xd1, 0x01, 0x8d, 0x03, 0x96, 0xf3, 0xa4, 0x96, 0xeb, 0xc8, 0xe8, 0x02, 0x00, -0x11, 0xc9, 0x01, 0xdb, 0x75, 0x04, 0xad, 0x11, 0xc0, 0x93, 0xc3, 0x5e, 0xb9, 0x01, 0x00, 0xac, -0x2c, 0xe8, 0x3c, 0x01, 0x77, 0xf9, 0x8b, 0x1c, 0x86, 0xdf, 0x29, 0xf3, 0x89, 0x1c, 0xad, 0xe2, -0xee, 0xc3 }; - -Bit8u font_ega3_cpx[5455] = { -0x81, 0xfc, 0xce, 0xe7, 0x77, 0x02, 0xcd, 0x20, 0xb9, 0x4f, 0x15, 0xbe, 0x4f, 0x16, 0xbf, 0x6e, -0xe7, 0xbb, 0x00, 0x80, 0xfd, 0xf3, 0xa4, 0xfc, 0x87, 0xf7, 0x83, 0xee, 0xc6, 0x19, 0xed, 0x57, -0x57, 0xe9, 0xed, 0xe5, 0x55, 0x50, 0x58, 0x21, 0x0b, 0x01, 0x04, 0x08, 0x10, 0x40, 0x37, 0xe4, -0x59, 0xc7, 0x7f, 0x53, 0x00, 0xe6, 0xb7, 0x14, 0x06, 0x45, 0xbb, 0xfc, 0xff, 0x46, 0x4f, 0x4e, -0x54, 0x20, 0x00, 0x00, 0x01, 0x6e, 0x39, 0x01, 0x17, 0x06, 0xfd, 0xfd, 0x06, 0x00, 0x1c, 0x00, -0x4d, 0x26, 0x0e, 0x45, 0x47, 0x41, 0xc9, 0xcd, 0x1e, 0x20, 0x03, 0x03, 0xb7, 0xd8, 0x35, 0x24, -0x0c, 0x12, 0x26, 0xb2, 0xd8, 0x10, 0x08, 0x0a, 0x00, 0xed, 0xbf, 0x7e, 0x81, 0xa5, 0x81, 0x81, -0xbd, 0x99, 0x03, 0x7f, 0xb0, 0x7e, 0x0f, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xfc, 0xce, 0xff, -0xff, 0x00, 0x6c, 0xfe, 0x87, 0xdd, 0x7c, 0x38, 0x10, 0x30, 0x10, 0x1f, 0xd8, 0x38, 0x7c, 0x0e, -0x18, 0x3c, 0x3c, 0xd6, 0xb6, 0xe7, 0x00, 0x18, 0x06, 0x0f, 0xcc, 0x4d, 0x7e, 0x3b, 0x0f, 0x76, -0xb6, 0x22, 0x18, 0x09, 0x3b, 0x76, 0xff, 0x00, 0xe7, 0xc3, 0x5f, 0xc7, 0xde, 0x00, 0x1f, 0x3c, -0x66, 0x5f, 0xf2, 0x42, 0x42, 0x66, 0x3c, 0xc3, 0x99, 0xbd, 0x3f, 0xe4, 0xbd, 0x99, 0xc3, 0x1e, -0x0e, 0x1a, 0x32, 0x7b, 0xdd, 0x78, 0xcc, 0x00, 0x78, 0x20, 0x2d, 0xd7, 0xdc, 0x00, 0x4f, 0x61, -0xf7, 0x33, 0x0f, 0x3f, 0x33, 0x3f, 0x30, 0x00, 0x1f, 0x79, 0x70, 0xf0, 0xe0, 0x00, 0x7f, 0x63, -0x7f, 0x63, 0xb3, 0x37, 0x67, 0xe7, 0xe6, 0xc0, 0x7c, 0xb0, 0xdb, 0x18, 0xdb, 0xa0, 0x3c, 0xdb, -0x2e, 0xb7, 0xff, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0x2d, 0xc0, 0x80, 0xff, 0x63, 0xbf, -0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x2d, 0xc9, 0x06, 0x02, 0x2b, 0xef, 0x6c, -0x5e, 0x3c, 0x00, 0x73, 0x93, 0x66, 0x07, 0x5f, 0xdc, 0x06, 0xdb, 0x00, 0x7b, 0x1b, 0x7f, 0xf3, -0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x80, 0xfc, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, -0xc8, 0xcc, 0xfe, 0x4f, 0x0d, 0x6c, 0x7e, 0x0f, 0x17, 0xec, 0x00, 0x0f, 0x00, 0xdf, 0xb2, 0x70, -0x11, 0x0c, 0x2e, 0xd9, 0xfe, 0x0c, 0x0c, 0x00, 0x80, 0xfc, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, -0xcc, 0xca, 0xc0, 0x5c, 0x2e, 0x27, 0xa1, 0x28, 0x6c, 0x28, 0x0a, 0xcb, 0x0e, 0x9f, 0xf6, 0x16, -0xa0, 0x7c, 0x7d, 0x8a, 0x61, 0x4b, 0x0e, 0x38, 0xaf, 0x17, 0xd8, 0x00, 0x18, 0xec, 0x95, 0x3c, -0x8c, 0x8f, 0x64, 0xdd, 0xe9, 0x24, 0x20, 0x31, 0x37, 0x6c, 0x5e, 0x03, 0xdf, 0x66, 0xad, 0xf1, -0xc2, 0xc0, 0x7c, 0x06, 0xc3, 0xda, 0x06, 0x86, 0xef, 0xc1, 0xe4, 0xdb, 0xc2, 0xc6, 0xae, 0x30, -0x60, 0xc6, 0x86, 0x85, 0xc2, 0x0e, 0x0c, 0x58, 0xc3, 0x76, 0xdc, 0xaf, 0x76, 0xbd, 0xb0, 0x2d, -0x00, 0x60, 0x4e, 0x31, 0x37, 0x2b, 0x00, 0x37, 0x6b, 0xe5, 0x0f, 0x08, 0xb2, 0x31, 0x00, 0x18, -0xe2, 0xc2, 0xc2, 0xde, 0xff, 0xe5, 0x30, 0xb0, 0xa2, 0xc0, 0x96, 0xed, 0x14, 0x0d, 0xd8, 0x31, -0xfe, 0xb2, 0x95, 0xd7, 0x31, 0xbf, 0xc2, 0xe2, 0x9f, 0xc0, 0x80, 0x1f, 0x26, 0xae, 0xd6, 0xd6, -0xc1, 0x0e, 0xb2, 0x27, 0x0b, 0xc2, 0x38, 0x78, 0x81, 0x2e, 0x9e, 0x3c, 0x7c, 0xc6, 0xc6, 0xfe, -0xdb, 0xc9, 0x0f, 0x06, 0x3c, 0x02, 0x06, 0x7f, 0x08, 0xdf, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0x13, -0xba, 0xfe, 0xb0, 0x1e, 0x8d, 0xc0, 0x9a, 0xfe, 0xfc, 0x1f, 0x72, 0x77, 0x38, 0x60, 0x0f, 0xc6, -0xc6, 0xc6, 0xcc, 0x1d, 0xfe, 0x3f, 0xf3, 0x6e, 0xd8, 0x4f, 0x1a, 0x2f, 0x60, 0x1f, 0x0b, 0x61, -0xbb, 0x7e, 0x3f, 0x0c, 0x78, 0xba, 0x61, 0x6f, 0x04, 0x0f, 0x6c, 0x72, 0x30, 0x9e, 0x52, 0x43, -0x35, 0x06, 0xc2, 0xd9, 0x5b, 0x02, 0x00, 0x5e, 0x2c, 0x1b, 0x23, 0x84, 0xc9, 0x5f, 0x0c, 0xdf, -0x76, 0xb6, 0x10, 0xde, 0x00, 0x8c, 0xc2, 0xdc, 0xc4, 0x2e, 0x67, 0x3b, 0x6c, 0x90, 0xfe, 0x8d, -0x67, 0x0f, 0xfc, 0x66, 0xf1, 0x90, 0x9e, 0x7c, 0xfc, 0x6f, 0xba, 0xc2, 0xef, 0x00, 0xc2, 0x3e, -0x9d, 0xa1, 0x10, 0xf8, 0x6c, 0x67, 0x4f, 0x6c, 0xf8, 0x0f, 0xfe, 0x90, 0xff, 0x66, 0x62, 0x68, -0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0xd8, 0x96, 0x00, 0xf0, 0x3f, 0xc9, 0x0f, 0xde, 0xc6, 0xc6, -0x66, 0x3a, 0xec, 0xbd, 0x69, 0x6e, 0x6f, 0x4d, 0x38, 0x3c, 0x7d, 0xc6, 0x64, 0x30, 0x1e, 0x0d, -0x2e, 0x29, 0xef, 0xe6, 0xd6, 0xed, 0x6a, 0x78, 0x78, 0x74, 0xe6, 0x0f, 0x16, 0x7b, 0xf0, 0x60, -0x00, 0x6f, 0xf2, 0x6f, 0x4f, 0xee, 0xfe, 0xfe, 0xd6, 0x7e, 0x5b, 0x0f, 0xe6, 0xf6, 0xfe, 0xde, -0xce, 0x0f, 0x4b, 0x6f, 0xc6, 0xb3, 0x25, 0xdf, 0x84, 0x7d, 0x41, 0xf0, 0x1f, 0x92, 0xfc, 0xd6, -0xde, 0x7c, 0x0c, 0x0e, 0x25, 0xfb, 0xe3, 0xe6, 0x1f, 0x56, 0x28, 0xe2, 0x50, 0x3f, 0x61, 0x4f, -0x7e, 0x7e, 0x5a, 0xaf, 0x42, 0x36, 0xc6, 0x5f, 0xe4, 0xc1, 0x0f, 0x6c, 0x38, 0x10, 0xc8, 0xbf, -0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0xcd, 0x74, 0x6c, 0x8e, 0x61, 0xac, 0x61, 0x9f, 0xce, 0x61, -0xd9, 0x4f, 0x1b, 0xe4, 0x63, 0x86, 0x7f, 0xc2, 0x82, 0x3d, 0x3c, 0x30, 0x00, 0x5f, 0xc1, 0x1f, -0xc1, 0x70, 0x4e, 0xd6, 0x38, 0x1c, 0xaf, 0x3c, 0x0c, 0x8c, 0xc1, 0x00, 0x3c, 0xdc, 0x11, 0x52, -0xe6, 0x9d, 0xa6, 0x6c, 0xff, 0x7d, 0x80, 0x18, 0x78, 0x0c, 0x7c, 0xc2, 0x25, 0xaf, 0xe0, 0x19, -0x2c, 0xc2, 0x78, 0xe2, 0xcf, 0x63, 0xc2, 0x02, 0x00, 0x77, 0x98, 0xdf, 0x1c, 0x69, 0x65, 0x25, -0x00, 0x2f, 0x90, 0xb1, 0x1f, 0xfe, 0x78, 0x1f, 0x36, 0x32, 0x30, 0x78, 0xaf, 0xbe, 0xcb, 0xcf, -0x76, 0x2e, 0xcc, 0x3b, 0x14, 0x5f, 0xd2, 0x5f, 0xc6, 0xf3, 0x6c, 0x76, 0xe6, 0xdc, 0x20, 0x4c, -0x38, 0x4f, 0x6d, 0x69, 0x09, 0x00, 0xdb, 0x19, 0x62, 0x00, 0x17, 0xce, 0x98, 0x2f, 0x00, 0xe6, -0x92, 0x33, 0x2f, 0x38, 0x46, 0x17, 0x00, 0xec, 0x00, 0xc9, 0xba, 0x00, 0xc6, 0x0f, 0xd9, 0x8c, -0xdc, 0xa1, 0x9f, 0x2d, 0x61, 0x9f, 0x3e, 0x96, 0x1f, 0x04, 0xf0, 0xd2, 0xc2, 0x9f, 0xd2, 0xa3, -0x1d, 0xdc, 0x9f, 0x1f, 0x09, 0x2c, 0xe4, 0x2e, 0x81, 0xdf, 0x10, 0xf6, 0xdb, 0xd9, 0xfc, 0xde, -0x36, 0x1c, 0x1f, 0xc2, 0x4b, 0x3d, 0x0f, 0x30, 0x06, 0x00, 0x08, 0x58, 0x0f, 0x96, 0xf0, 0x00, -0x9a, 0x66, 0xea, 0x1b, 0x38, 0x75, 0x2f, 0xba, 0x16, 0x04, 0x0c, 0xe0, 0x90, 0x52, 0xcc, 0x39, -0x7b, 0x4f, 0xfe, 0xef, 0x0e, 0xac, 0xa7, 0x70, 0x0e, 0xf7, 0x61, 0x90, 0x3f, 0x7b, 0x2f, 0x1b, -0x23, 0x24, 0x08, 0x5f, 0xc9, 0xdc, 0xdf, 0x91, 0x06, 0xe2, 0xf4, 0x61, 0x4f, 0x1e, 0x36, 0x66, -0xf9, 0x84, 0xef, 0xfe, 0x62, 0x60, 0x60, 0x25, 0x2d, 0xff, 0x92, 0x69, 0xcf, 0x71, 0x4b, 0x76, -0xf0, 0x3f, 0x00, 0x2d, 0x31, 0xa7, 0x81, 0x1b, 0x20, 0xff, 0xe9, 0x6b, 0x70, 0x54, 0x54, 0x70, -0x03, 0x04, 0x5a, 0x07, 0x3f, 0x77, 0x0b, 0x78, 0xce, 0xde, 0xf6, 0x73, 0xb3, 0xe6, 0x7f, 0x14, -0x0f, 0x48, 0x09, 0xef, 0x1d, 0xce, 0x6c, 0xef, 0xd2, 0x85, 0x6f, 0xc6, 0xef, 0xac, 0x10, 0x4f, -0x14, 0xd2, 0xef, 0x58, 0xb3, 0x1b, 0xdf, 0x52, 0x5b, 0xe0, 0xff, 0xb1, 0x12, 0xdf, 0x13, 0x49, -0xdf, 0x7e, 0xc7, 0x65, 0xbf, 0x7c, 0x6b, 0xe4, 0xa5, 0xcf, 0x7c, 0x10, 0x38, 0x64, 0x0b, 0x6e, -0xec, 0xd0, 0xff, 0x84, 0x3f, 0xc8, 0xb6, 0x00, 0x00, 0x76, 0xc8, 0xd6, 0xfe, 0x0f, 0xc1, 0x42, -0x2f, 0x6e, 0xe9, 0xf8, 0xb0, 0xb0, 0xea, 0x36, 0x00, 0x0e, 0x58, 0x4f, 0xf6, 0xde, 0xcb, 0xea, -0x00, 0xf6, 0xff, 0x18, 0x08, 0x9f, 0x4b, 0x6e, 0x5f, 0x26, 0x3e, 0x26, 0x7b, 0xba, 0xcc, 0x4f, -0xf6, 0xcc, 0xcf, 0x7a, 0x04, 0xda, 0x40, 0x7a, 0xb0, 0xce, 0xef, 0x18, 0xbc, 0x06, 0x7c, 0xaf, -0x4e, 0x58, 0x22, 0x7c, 0x18, 0xc9, 0x5f, 0x22, 0x12, 0xd2, 0x62, 0x0f, 0x3d, 0x1c, 0x92, 0xff, -0xc3, 0xe4, 0x25, 0x5f, 0xfe, 0xc0, 0xf0, 0xb1, 0x02, 0x7c, 0xcc, 0x92, 0xff, 0xa2, 0x01, 0x6b, -0x01, 0x1f, 0x2c, 0x08, 0xf1, 0x0f, 0x16, 0xf2, 0xc6, 0x7c, 0x26, 0x3d, 0x02, 0xef, 0x59, 0xc8, -0x6f, 0x0f, 0xd2, 0x63, 0x02, 0xef, 0x30, 0x06, 0x01, 0x14, 0x52, 0xef, 0x9e, 0xbd, 0x1c, 0x1f, -0x11, 0x44, 0xf2, 0xc2, 0x01, 0x55, 0xaa, 0x90, 0x17, 0xdd, 0x77, 0x02, 0xbb, 0x18, 0x00, 0x85, -0xec, 0xf8, 0x0d, 0x67, 0x93, 0x0f, 0x36, 0x00, 0xf6, 0x58, 0x90, 0x36, 0x80, 0x25, 0x6c, 0x0f, -0xe7, 0x91, 0x2f, 0xf6, 0x06, 0x4b, 0x60, 0x00, 0x3d, 0x42, 0x36, 0x1f, 0x64, 0xd1, 0x2f, 0xee, -0x59, 0xb0, 0x11, 0x0f, 0x35, 0x2c, 0x8f, 0xd9, 0x90, 0x00, 0xf8, 0xbf, 0x84, 0x0d, 0x1f, 0x2f, -0x43, 0xf2, 0x18, 0x18, 0xff, 0xff, 0x6b, 0x24, 0x72, 0x6b, 0x0b, 0x1f, 0x3f, 0x64, 0x23, 0x2d, -0x90, 0x30, 0x1f, 0x0f, 0x4f, 0xd8, 0x37, 0xbf, 0x37, 0x30, 0x3f, 0x2a, 0x61, 0x6d, 0x17, 0x56, -0xbf, 0x1f, 0xf7, 0xb0, 0x65, 0x5f, 0x6d, 0x85, 0x6c, 0xf7, 0x3f, 0xcd, 0x92, 0x2f, 0x1f, 0xcd, -0x96, 0x2f, 0x3f, 0xc1, 0x96, 0x2f, 0xdd, 0x85, 0x84, 0xff, 0x2f, 0xd9, 0x91, 0x5f, 0xff, 0xdf, -0x48, 0x18, 0x86, 0x2c, 0x59, 0xaf, 0xdf, 0x12, 0x36, 0x3f, 0x17, 0xf6, 0xef, 0x3f, 0x3f, 0x2c, -0x24, 0x4f, 0x82, 0x90, 0x2d, 0x30, 0x12, 0x5f, 0xb2, 0x91, 0xaf, 0x4f, 0x85, 0x6c, 0xff, 0x00, -0x48, 0x08, 0xaf, 0x90, 0x36, 0x24, 0x1e, 0xcf, 0x03, 0x97, 0x0f, 0x94, 0x90, 0x90, 0xaf, 0xc4, -0x8b, 0x87, 0x30, 0x98, 0xbf, 0xff, 0x91, 0xad, 0x1f, 0x38, 0x81, 0x01, 0x3c, 0x90, 0x32, 0x9f, -0x93, 0x27, 0x02, 0x38, 0x10, 0x0c, 0xca, 0x7c, 0x10, 0xcf, 0x59, 0x83, 0xcf, 0x7a, 0xb3, 0x0f, -0x3d, 0xd6, 0x32, 0xaf, 0xff, 0xcb, 0x12, 0x0f, 0x81, 0x64, 0x2f, 0x02, 0xcc, 0x80, 0x01, 0x8f, -0x26, 0xb0, 0x01, 0x09, 0xbc, 0xff, 0x02, 0x09, 0x2b, 0x9f, 0x20, 0x5d, 0x5f, 0x3e, 0x23, 0x70, -0xcc, 0x01, 0xcc, 0x81, 0x65, 0xcf, 0x01, 0x32, 0x1a, 0xce, 0xaf, 0x98, 0x30, 0x3f, 0xdc, 0xb2, -0xbf, 0x0f, 0x65, 0xd0, 0xf5, 0xcf, 0x60, 0x2e, 0x12, 0x1f, 0x23, 0xa3, 0xaf, 0x2c, 0x66, 0x3f, -0xbf, 0x05, 0xb7, 0x0f, 0x08, 0x46, 0x46, 0x2f, 0x16, 0x13, 0x7f, 0x3f, 0x32, 0x58, 0x1f, 0x2c, -0xde, 0x6f, 0x3f, 0xf4, 0x25, 0x0f, 0xfe, 0x6d, 0x64, 0x4f, 0x1f, 0xd8, 0x90, 0xfc, 0x4d, 0x23, -0xa3, 0x1f, 0xb0, 0x78, 0x5f, 0x2f, 0x33, 0x97, 0xee, 0x00, 0x06, 0x90, 0x00, 0x0e, 0xc1, 0x0b, -0x05, 0x1c, 0x61, 0x03, 0x7e, 0x07, 0x16, 0x01, 0x7e, 0x80, 0x04, 0xff, 0x93, 0x20, 0xfd, 0x95, -0x04, 0xfb, 0x4a, 0x82, 0xf9, 0x38, 0x41, 0xf7, 0x8c, 0x24, 0xf5, 0x58, 0x12, 0xf3, 0x8c, 0x24, -0xf1, 0x5d, 0x12, 0xef, 0x78, 0x24, 0x98, 0x27, 0xec, 0x4e, 0xb0, 0xeb, 0x2c, 0x09, 0xea, 0x82, -0x13, 0xe9, 0x49, 0x70, 0xe8, 0xe7, 0x98, 0x4a, 0x24, 0x82, 0x12, 0xe5, 0x04, 0x4b, 0xe4, 0x70, -0xaa, 0xe3, 0x32, 0x48, 0x49, 0xe1, 0x24, 0x24, 0xde, 0x18, 0x12, 0xdd, 0x30, 0x24, 0xdb, 0x1c, -0x49, 0xda, 0x00, 0x92, 0xa0, 0xd7, 0xac, 0x37, 0x0d, 0x01, 0x49, 0xb0, 0xd2, 0x27, 0x08, 0xd1, -0x84, 0x04, 0xcf, 0x93, 0x20, 0xcd, 0x95, 0x04, 0xcb, 0x4c, 0x82, 0xc9, 0x54, 0x12, 0xc7, 0x45, -0x82, 0xc3, 0x93, 0xc0, 0x76, 0xc1, 0x84, 0x04, 0xbe, 0x93, 0x20, 0xbd, 0x96, 0x04, 0xbc, 0xd0, -0x09, 0xbb, 0x92, 0xe0, 0x5a, 0xb9, 0x92, 0xe0, 0x76, 0x5f, 0x48, 0x90, 0xb5, 0x04, 0x2d, 0xc8, -0xb2, 0x80, 0xb3, 0x20, 0x38, 0x41, 0xb0, 0x81, 0x24, 0xae, 0x30, 0x60, 0x4b, 0xfe, 0x16, 0x48, -0xa8, 0x2b, 0x09, 0xa5, 0x60, 0x52, 0x44, 0xe0, 0x92, 0xa3, 0x7e, 0x11, 0x90, 0xa1, 0xcb, 0xe8, -0xf0, 0x5f, 0x09, 0x0e, 0xa3, 0x9d, 0x09, 0x2e, 0x1e, 0x9b, 0x78, 0x01, 0x1b, 0xb7, 0x24, 0x99, -0x0d, 0x76, 0x82, 0x97, 0xd4, 0x90, 0x60, 0x95, 0x24, 0x38, 0x7c, 0x93, 0x49, 0xb0, 0x92, 0x93, -0x20, 0x80, 0x95, 0x04, 0x8e, 0x04, 0xb1, 0xb3, 0x92, 0xc0, 0x71, 0x8b, 0x48, 0xb0, 0x88, 0x24, -0x48, 0x87, 0x09, 0x5e, 0x3c, 0x84, 0x02, 0x29, 0xd3, 0x90, 0x4a, 0x81, 0x24, 0x98, 0xfc, 0x7f, -0x21, 0xb0, 0xce, 0x70, 0x82, 0x7d, 0xb2, 0x4e, 0x7c, 0xcb, 0xb2, 0xd7, 0xaa, 0x0d, 0xe0, 0xc0, -0xd5, 0xf5, 0x92, 0x77, 0x66, 0x3a, 0x6b, 0x21, 0x25, 0xc3, 0x82, 0x09, 0x3c, 0xea, 0x40, 0x71, -0x78, 0x52, 0x4b, 0x7f, 0x7e, 0x12, 0x4c, 0xf0, 0x6c, 0x1d, 0x5a, 0x78, 0x60, 0x49, 0x7a, 0xd9, -0x92, 0x69, 0xd1, 0x26, 0xac, 0xb6, 0xfc, 0x25, 0xa4, 0x64, 0x9c, 0xe0, 0x1b, 0x62, 0x07, 0x12, -0x61, 0xe6, 0x96, 0x04, 0x5f, 0x53, 0xc3, 0x37, 0x7d, 0xc0, 0xb2, 0x99, 0x82, 0x85, 0x0a, 0x41, -0x42, 0x58, 0x33, 0x22, 0x57, 0xd7, 0x95, 0x62, 0x0d, 0x1c, 0x90, 0xe0, 0x66, 0x53, 0x6d, 0x36, -0x45, 0xf7, 0x2c, 0x81, 0x8c, 0x30, 0x1c, 0x12, 0x4f, 0x3c, 0x56, 0x12, 0x4c, 0x06, 0x09, 0x4b, -0x3c, 0x20, 0x09, 0x49, 0x90, 0x60, 0xff, 0x45, 0x48, 0x0c, 0x83, 0x20, 0xc1, 0x76, 0x41, 0x12, -0x6f, 0xb5, 0x5f, 0xc1, 0x4b, 0xc3, 0xd9, 0x25, 0x3d, 0x76, 0x1b, 0x48, 0x72, 0xfe, 0x82, 0x25, -0x39, 0x7c, 0x60, 0x40, 0x38, 0x76, 0x04, 0x31, 0x96, 0xc1, 0x80, 0x35, 0xe6, 0x70, 0x20, 0x33, -0x3c, 0x60, 0x49, 0x31, 0x90, 0x90, 0x2f, 0xc5, 0x86, 0xbf, 0x26, 0x90, 0xe0, 0x29, 0x2b, 0x61, -0x91, 0x09, 0x42, 0x6a, 0x37, 0x26, 0x6c, 0x7c, 0x1b, 0x7c, 0x96, 0x1d, 0xc1, 0x8b, 0x03, 0x09, -0x21, 0xf2, 0xb2, 0xf0, 0x37, 0x70, 0x1c, 0x93, 0x60, 0x1d, 0x96, 0x04, 0x1c, 0x09, 0x09, 0x1a, -0x6c, 0x09, 0xbf, 0x0d, 0x20, 0xc1, 0x16, 0x16, 0x2e, 0x19, 0x44, 0x2c, 0x02, 0x72, 0x24, 0x18, -0x7c, 0x11, 0xe0, 0x91, 0x83, 0xe0, 0x92, 0x0f, 0x0e, 0x90, 0x90, 0x0d, 0x1c, 0x48, 0x0b, 0x70, -0x04, 0x12, 0x09, 0xc1, 0xa4, 0x66, 0x2a, 0x21, 0x05, 0x00, 0xc1, 0xe0, 0x4a, 0x9a, 0x52, 0x7f, -0x61, 0xc0, 0xff, 0xe0, 0xbd, 0xed, 0x37, 0xd2, 0x32, 0xfc, 0x7f, 0xd0, 0x42, 0xcc, 0xac, 0x19, -0xf8, 0x97, 0x06, 0xac, 0xe5, 0x0c, 0x48, 0xf3, 0x25, 0x25, 0x71, 0x98, 0x6c, 0x61, 0xc6, 0x25, -0x0c, 0xed, 0x69, 0x25, 0xc5, 0x71, 0x01, 0x21, 0x90, 0x86, 0xe7, 0x7f, 0x72, 0x2d, 0x43, 0xb0, -0x42, 0x63, 0x28, 0x19, 0xde, 0x80, 0x43, 0xda, 0x38, 0x01, 0xc9, 0xdb, 0x03, 0x86, 0xda, 0xd8, -0x01, 0x09, 0x03, 0x86, 0xd7, 0xd4, 0x24, 0xa4, 0x00, 0x13, 0x06, 0xd2, 0xf0, 0x32, 0xe0, 0xf0, -0xb0, 0xbc, 0xd0, 0x61, 0x40, 0xce, 0x82, 0x2b, 0x5f, 0x79, 0x0c, 0x58, 0xcb, 0x80, 0xd9, 0x8b, -0xa0, 0xf9, 0xc9, 0xf6, 0xcc, 0x3a, 0x30, 0xc7, 0xce, 0x10, 0x40, 0x71, 0x8c, 0x19, 0xc3, 0xbb, -0x0c, 0xb8, 0xfc, 0xc0, 0x07, 0x0c, 0xbf, 0x65, 0xc0, 0xf0, 0x4d, 0xf4, 0x80, 0xbc, 0xb1, 0x94, -0x7f, 0xb8, 0x92, 0x0a, 0xc1, 0x1d, 0x92, 0xdb, 0x1b, 0x1c, 0x06, 0x65, 0xc0, 0xa4, 0x65, 0x87, -0xc2, 0x0d, 0x49, 0x87, 0xc2, 0x71, 0x36, 0x6c, 0x61, 0x0d, 0x60, 0x48, 0xc2, 0x63, 0x19, 0xac, -0x75, 0x25, 0x2d, 0x71, 0xb0, 0x60, 0xc6, 0x64, 0x40, 0xa3, 0x0c, 0x08, 0x9f, 0x80, 0xab, 0xf8, -0xc0, 0xca, 0x9b, 0x6f, 0x61, 0x99, 0x70, 0x0c, 0x38, 0x95, 0x06, 0xac, 0x93, 0x80, 0x41, 0xc0, -0xca, 0x8f, 0x0c, 0x78, 0x8d, 0x8b, 0x06, 0xa4, 0x89, 0x03, 0x56, 0x87, 0x80, 0x21, 0x1f, 0xb0, -0xc2, 0x83, 0x08, 0x19, 0x51, 0xac, 0x0c, 0x7d, 0x52, 0x06, 0x7b, 0x64, 0x03, 0x77, 0x1f, 0x01, -0x23, 0x0c, 0x98, 0x75, 0x73, 0x07, 0xac, 0x71, 0xc2, 0x80, 0x6f, 0x1e, 0x30, 0x6d, 0x29, 0x03, -0x6b, 0x96, 0x01, 0x69, 0x23, 0x03, 0x67, 0x95, 0x01, 0x65, 0x06, 0xb8, 0x1b, 0x61, 0xc0, 0x15, -0x3f, 0x1b, 0x61, 0x5d, 0xd1, 0x61, 0xc0, 0x59, 0x06, 0x4c, 0xff, 0x55, 0xc0, 0x15, 0xf8, 0x08, -0x60, 0x51, 0x29, 0x0c, 0x4d, 0xa4, 0x03, 0x4f, 0x55, 0x81, 0xb6, 0x0d, 0xc1, 0x96, 0x85, 0x79, -0x2c, 0x03, 0x47, 0x46, 0x18, 0x1f, 0xd6, 0xc2, 0x1b, 0x61, 0x24, 0x30, 0x3c, 0xcb, 0x19, 0x30, -0xfc, 0x3d, 0xc0, 0x6b, 0x61, 0x60, 0x84, 0xf5, 0xc0, 0x30, 0x38, 0x2b, 0x61, 0x36, 0x5f, 0x92, -0x2d, 0x0d, 0x58, 0xc9, 0x29, 0x61, 0x40, 0xb2, 0x7d, 0x30, 0x61, 0x2e, 0xf0, 0x1c, 0x18, 0x2c, -0xfc, 0xb3, 0x06, 0x2a, 0x89, 0xae, 0x59, 0x62, 0x61, 0xc0, 0x80, 0xcc, 0x27, 0x42, 0xe8, 0xce, -0x59, 0xac, 0xc3, 0x17, 0x27, 0xa0, 0xbd, 0x30, 0x1c, 0xd6, 0x5c, 0x48, 0xf5, 0x10, 0x08, 0xcd, -0x1b, 0x59, 0xc4, 0x5b, 0x37, 0xd6, 0x96, 0xa7, 0x0d, 0xe6, 0x0b, 0x8b, 0xe9, 0x89, 0x09, 0x4f, -0x37, 0x85, 0xc5, 0xe9, 0x49, 0xbc, 0x37, 0x37, 0xd1, 0x6e, 0x0d, 0xfe, 0x00, 0x2c, 0x64, 0xc0, -0x1b, 0x8b, 0x17, 0x43, 0xdb, 0x78, 0x0b, 0x53, 0xc0, 0x92, 0x29, 0x80, 0x61, 0x09, 0xe4, 0xc8, -0x05, 0x08, 0x0e, 0xb0, 0xfc, 0xc0, 0x01, 0xfb, 0x06, 0x30, 0xf6, 0xf5, 0x4c, 0x80, 0x6c, 0xee, -0x0b, 0x02, 0xe9, 0x06, 0xe6, 0x60, 0x38, 0x83, 0x0d, 0x1c, 0xbe, 0x0f, 0xfe, 0xb7, 0x60, 0x02, -0xd7, 0x40, 0x10, 0xd1, 0x80, 0x20, 0xcb, 0xf0, 0x41, 0xc5, 0x0f, 0x07, 0x0f, 0x7d, 0x01, 0x0c, -0xbf, 0xba, 0x03, 0x04, 0xb4, 0x50, 0x80, 0xb3, 0xc0, 0x0f, 0xae, 0x67, 0xe6, 0xc0, 0x06, 0x30, -0xa7, 0xa8, 0x75, 0x80, 0x80, 0xa1, 0x03, 0x2c, 0xef, 0x02, 0x9b, 0x38, 0xc0, 0x02, 0x42, 0x00, -0x06, 0x33, 0x06, 0x98, 0x8f, 0x8a, 0xdd, 0x00, 0x89, 0x00, 0x3e, 0x61, 0xde, 0xdb, 0x49, 0x3c, -0x86, 0xfd, 0xd0, 0xc0, 0xf7, 0x27, 0x26, 0xff, 0x9d, 0x26, 0x72, 0x35, 0x12, 0xe0, 0x0f, 0x65, -0x38, 0x40, 0x5f, 0xb8, 0x04, 0x59, 0x24, 0x03, 0x14, 0xed, 0x12, 0xf0, 0x80, 0x9f, 0xf0, 0x1e, -0x72, 0x2e, 0x1b, 0x08, 0x3d, 0x46, 0xf0, 0xda, 0x72, 0x25, 0xa3, 0x09, 0x31, 0x57, 0x94, 0xf8, -0x18, 0x3e, 0x60, 0xc0, 0x68, 0x28, 0x90, 0x9c, 0xcc, 0x80, 0x07, 0x23, 0x38, 0xb2, 0x7a, 0x1e, -0x76, 0xcc, 0x8b, 0x55, 0x3e, 0x74, 0x22, 0x40, 0x0d, 0x09, 0xf0, 0x13, 0x06, 0x4b, 0x80, 0x00, -0x84, 0x61, 0x2b, 0x83, 0x2b, 0xb7, 0x18, 0xe8, 0x74, 0x0c, 0xf7, 0xd6, 0xb9, 0x72, 0xfe, 0xdd, -0x3e, 0x88, 0xc2, 0xfd, 0x1c, 0x02, 0x1d, 0xbb, 0x2e, 0xb3, 0x0a, 0xca, 0xef, 0xab, 0x1e, 0xc5, -0xfc, 0x0f, 0x47, 0x57, 0xbf, 0xfc, 0x05, 0x62, 0x85, 0xf3, 0x79, 0xef, 0x3d, 0x4f, 0x02, 0x07, -0x17, 0xab, 0x7e, 0xab, 0x74, 0x37, 0xab, 0x62, 0x77, 0x5e, 0xbd, 0x67, 0x81, 0x95, 0xac, 0x94, -0xbe, 0x7a, 0x8f, 0x8d, 0x7c, 0xdc, 0xac, 0x88, 0x07, 0xde, 0x26, 0x86, 0xc0, 0x78, 0x87, 0x02, -0xbd, 0x01, 0xf6, 0x43, 0x1b, 0xc3, 0x38, 0x57, 0x06, 0xd0, 0x6b, 0xe3, 0xab, 0x69, 0xfe, 0xee, -0x34, 0x1b, 0xfe, 0x07, 0xab, 0xcf, 0xef, 0x1f, 0xce, 0x57, 0x20, 0x90, 0x76, 0xdb, 0x8c, 0xf3, -0x2f, 0x1e, 0x0d, 0x56, 0x45, 0xe6, 0x35, 0x18, 0x7f, 0xf0, 0x2c, 0x66, 0x39, 0xc3, 0x7a, 0x35, -0x2f, 0x02, 0xbd, 0x2e, 0x9e, 0xc4, 0x1b, 0x6f, 0xe4, 0xef, 0x97, 0x0f, 0xce, 0x7c, 0x0e, 0xd7, -0x5e, 0x37, 0x5f, 0xa8, 0xb0, 0x3a, 0x7f, 0x7e, 0x45, 0x1a, 0x46, 0xfd, 0x15, 0x84, 0x56, 0xde, -0x20, 0xf8, 0x00, 0x0c, 0x1e, 0x2f, 0x9b, 0x67, 0xf7, 0xf4, 0x27, 0x0b, 0x32, 0x6f, 0x82, 0x54, -0x3c, 0xdf, 0xd4, 0x01, 0x97, 0x4e, 0xca, 0xd9, 0xd5, 0x3c, 0x18, 0xb8, 0xea, 0x61, 0x71, 0x48, -0xba, 0x86, 0x65, 0x4a, 0xd7, 0x1a, 0x8b, 0xe0, 0x8a, 0xdc, 0x3a, 0xcc, 0xcc, 0x7f, 0x34, 0x24, -0x26, 0x62, 0xf7, 0xe0, 0x7c, 0x97, 0x60, 0xf8, 0xa6, 0xce, 0x47, 0x76, 0x09, 0x4e, 0xb9, 0xf8, -0x2f, 0x92, 0xef, 0xd4, 0xaf, 0xe4, 0x7f, 0xa7, 0x0a, 0x69, 0x84, 0x3d, 0xb8, 0x3c, 0x17, 0x00, -0xe6, 0x5a, 0x46, 0xd6, 0x02, 0x91, 0x74, 0x32, 0x0c, 0x18, 0x6d, 0x36, 0x16, 0x0f, 0x7c, 0x4f, -0x48, 0x4d, 0x1e, 0x56, 0xb5, 0xb3, 0x5f, 0x7e, 0x6d, 0x9d, 0x72, 0xa3, 0x4a, 0xa9, 0x49, 0x49, -0x43, 0x46, 0x0d, 0x56, 0x90, 0x0a, 0x37, 0x2c, 0xc2, 0x00, 0x17, 0x9c, 0x40, 0x5d, 0x7e, 0x4f, -0x35, 0xdf, 0x7e, 0x21, 0x70, 0xa9, 0x53, 0x1f, 0x19, 0xee, 0x0d, 0x0c, 0x12, 0xa9, 0x53, 0x11, -0x07, 0xa9, 0x09, 0x3e, 0x02, 0xc0, 0x35, 0xcf, 0x21, 0x4c, 0x21, 0xff, 0x1e, 0xb9, 0x0f, 0x39, -0x34, 0x3d, 0x7f, 0x0a, 0xc6, 0x81, 0x24, 0xff, 0xb5, 0x71, 0xa8, 0x38, 0x1d, 0x8c, 0x86, 0x9f, -0xc4, 0x30, 0x3b, 0x7c, 0x07, 0x8c, 0x92, 0xf7, 0xc1, 0x2d, 0xe1, 0xc6, 0xf7, 0x4b, 0x88, 0x66, -0xf7, 0xc1, 0x78, 0x0c, 0x6f, 0x2b, 0x62, 0xff, 0x7e, 0x58, 0x31, 0x76, 0xb0, 0x62, 0x6b, 0xcc, -0x60, 0x7c, 0x27, 0xac, 0x24, 0xe7, 0xf6, 0x51, 0x61, 0xfe, 0x65, 0x8c, 0x86, 0x77, 0x71, 0x60, -0x30, 0x0a, 0xc5, 0xa3, 0x67, 0xac, 0x78, 0x36, 0x2e, 0x59, 0x11, 0x26, 0xc3, 0x8a, 0x1e, 0x98, -0x15, 0x16, 0xb0, 0xac, 0x0e, 0x54, 0x9a, 0xf7, 0xe3, 0x33, 0x9a, 0x57, 0x36, 0x1c, 0x0e, 0x47, -0x01, 0x88, 0x3d, 0x87, 0x3c, 0xff, 0xe1, 0x4d, 0xff, 0x1f, 0x00, 0x66, 0x14, 0x18, 0x9a, 0xc5, -0x2f, 0xf8, 0x51, 0x30, 0x0c, 0xfa, 0x82, 0x06, 0x07, 0x3e, 0x41, 0x10, 0xff, 0x10, 0x3a, 0x2f, -0xf4, 0x58, 0xc2, 0xf7, 0x66, 0x4f, 0x01, 0x22, 0x88, 0x01, 0x34, 0x84, 0xd9, 0xa1, 0x21, 0xd4, -0xca, 0x42, 0x2b, 0x9a, 0x43, 0x68, 0xbe, 0x1a, 0x42, 0xb8, 0xd0, 0x10, 0xb2, 0xa1, 0x91, 0xac, -0xa0, 0x09, 0x2d, 0x9a, 0x0d, 0xa1, 0x94, 0x1d, 0x08, 0x8e, 0xf8, 0x0a, 0x08, 0x82, 0x3a, 0x10, -0x7c, 0xff, 0x16, 0x10, 0x70, 0x0f, 0x34, 0x2c, 0x1f, 0x28, 0x20, 0x5e, 0x09, 0x79, 0x52, 0x37, -0x68, 0x42, 0x4c, 0x43, 0x4b, 0x46, 0x40, 0x2d, 0xa1, 0x3a, 0x68, 0x08, 0x34, 0x42, 0x43, 0x2e, -0x28, 0x12, 0x1a, 0x22, 0xc3, 0xdc, 0x0f, 0x6f, 0x02, 0x42, 0x10, 0xb6, 0x84, 0x0a, 0x77, 0xc0, -0x62, 0xfe, 0x2c, 0xde, 0x27, 0xf2, 0x87, 0x0d, 0xd7, 0x1f, 0x02, 0x16, 0xe3, 0x4c, 0xb3, 0xd6, -0x07, 0x17, 0x11, 0xe5, 0xd1, 0x4a, 0xaf, 0xb8, 0x9f, 0x69, 0x24, 0x89, 0xc0, 0x7f, 0x36, 0x19, -0xfc, 0x0f, 0xf4, 0x48, 0x81, 0x33, 0xe0, 0xaf, 0x79, 0x8d, 0x17, 0xaa, 0x80, 0x08, 0x48, 0x67, -0x9b, 0xcd, 0x7f, 0x1f, 0x07, 0x86, 0xc5, 0x91, 0x68, 0x33, 0x7f, 0x00, 0x71, 0xf6, 0x80, 0x3f, -0xf6, 0xce, 0xc2, 0x7f, 0x7a, 0xfc, 0x17, 0x2c, 0x74, 0x07, 0x16, 0x8d, 0x81, 0x6d, 0x78, 0x71, -0x7e, 0x67, 0x39, 0xd8, 0x52, 0xf8, 0x9f, 0x14, 0xc3, 0x9f, 0x5d, 0x19, 0xec, 0xa2, 0x11, 0x18, -0xb0, 0x38, 0x3c, 0x39, 0x8b, 0x57, 0x5e, 0x41, 0x5b, 0x3c, 0x7e, 0xc2, 0x2f, 0x86, 0x06, 0xae, -0xfc, 0x11, 0x98, 0xc9, 0x22, 0x2f, 0x0b, 0x16, 0x29, 0x88, 0x86, 0x40, 0x57, 0xbf, 0xcd, 0x11, -0x2f, 0xfe, 0x86, 0x1c, 0x70, 0xc2, 0x66, 0x99, 0xfe, 0x17, 0xd2, 0x35, 0xce, 0x00, 0x00, 0x83, -0x18, 0x33, 0x03, 0x72, 0x81, 0x4c, 0x04, 0x90, 0x27, 0x69, 0x26, 0x32, 0x82, 0x14, 0x11, 0x0a, -0x06, 0x41, 0x48, 0xc3, 0x48, 0x49, 0xb3, 0x2c, 0x23, 0x83, 0x95, 0x11, 0x93, 0x32, 0x88, 0x33, -0x15, 0xa1, 0x23, 0x98, 0xa5, 0xb3, 0xc4, 0x0a, 0x11, 0x19, 0x33, 0xa4, 0x20, 0x13, 0x14, 0x8c, -0x88, 0x85, 0x03, 0x28, 0x32, 0x33, 0x49, 0x41, 0x63, 0x81, 0x48, 0x63, 0x10, 0x09, 0x48, 0x20, -0x53, 0x24, 0x2b, 0x43, 0x95, 0x15, 0x33, 0xb0, 0x82, 0x23, 0x56, 0x30, 0x13, 0x0a, 0x56, 0x41, -0xc2, 0x03, 0x58, 0x48, 0xf3, 0x21, 0x29, 0xe3, 0x61, 0x10, 0x33, 0xf9, 0x56, 0x00, 0xff, 0x48, -0x0e, 0xf0, 0x85, 0x64, 0x0f, 0x88, 0x84, 0x36, 0x00, 0x30, 0x33, 0x90, 0x06, 0x6c, 0x7f, 0x88, -0xb0, 0x91, 0x96, 0x6c, 0xff, 0xc6, 0xfc, 0x4d, 0x08, 0xe9, 0x1a, 0x02, 0xe7, 0x37, 0x21, 0xa2, -0x0f, 0x90, 0xa2, 0x4b, 0xad, 0xbd, 0x24, 0x48, 0x01, 0x05, 0x25, 0x05, 0xc1, 0x90, 0x2e, 0x2a, -0x18, 0x4a, 0x11, 0xac, 0x24, 0x29, 0xaf, 0xe8, 0x14, 0x99, 0x2b, 0x8c, 0xe0, 0xb0, 0x61, 0x42, -0x00, 0xdb, 0xf3, 0x0f, 0x0c, 0xec, 0x34, 0x3c, 0x46, 0xb0, 0x1c, 0x76, 0xf8, 0x23, 0x58, 0x1b, -0xd8, 0x36, 0xa0, 0x32, 0x9b, 0x30, 0x88, 0x33, 0x08, 0x80, 0x18, 0xb0, 0x9b, 0x2b, 0x08, 0x03, -0x05, 0x29, 0x20, 0x20, 0x15, 0x24, 0xa4, 0x07, 0x91, 0x41, 0x33, 0x0c, 0x08, 0x8b, 0x49, 0xc1, -0x23, 0x83, 0x58, 0x33, 0x04, 0x20, 0x85, 0x14, 0x77, 0x90, 0x82, 0x69, 0x06, 0x31, 0x33, 0x48, -0x15, 0x21, 0x29, 0xbd, 0x20, 0x10, 0x7d, 0x04, 0x22, 0x6f, 0x15, 0xac, 0x0a, 0x86, 0x81, 0xc1, -0xc8, 0x73, 0x60, 0x59, 0x65, 0x8c, 0xac, 0x57, 0x80, 0x15, 0x49, 0xb2, 0x82, 0x3b, 0x59, 0xc1, -0x2d, 0x83, 0x08, 0x33, 0x30, 0x08, 0x60, 0x19, 0x4d, 0x05, 0x32, 0x49, 0x31, 0x99, 0x30, 0x45, -0x06, 0x33, 0x10, 0x57, 0x6c, 0x79, 0x61, 0x17, 0x00, 0x6c, 0x06, 0x24, 0x20, 0x03, 0x42, 0x1e, -0x03, 0xce, 0x1b, 0x40, 0x2a, 0x03, 0x66, 0x19, 0x17, 0x01, 0x2b, 0x30, 0xe0, 0x15, 0x12, 0x03, -0xae, 0x18, 0x0f, 0xc0, 0x21, 0x3c, 0x1c, 0x60, 0x65, 0x0d, 0xc2, 0x3c, 0x0b, 0x2a, 0x0c, 0x33, -0x10, 0x08, 0x60, 0x56, 0xfb, 0x30, 0xac, 0xf3, 0x60, 0x56, 0x59, 0x31, 0xac, 0x63, 0x50, 0x06, -0x33, 0x10, 0xa1, 0x94, 0x58, 0x56, 0x73, 0x22, 0x83, 0x33, 0x26, 0x14, 0x4d, 0xc9, 0x0a, 0x9b, -0x64, 0x10, 0x33, 0x0a, 0x42, 0x10, 0xc1, 0xcb, 0x88, 0x20, 0xcb, 0xc4, 0x10, 0xc3, 0x6c, 0x08, -0x3b, 0x09, 0x02, 0x11, 0x2b, 0x04, 0x62, 0x23, 0x02, 0x11, 0x1b, 0x81, 0x08, 0x13, 0x40, 0x04, -0x20, 0x82, 0x0b, 0x11, 0xc2, 0x33, 0x8b, 0x61, 0xda, 0xd1, 0x61, 0x23, 0x1b, 0x32, 0x88, 0x33, -0x45, 0xa8, 0x50, 0xdc, 0x64, 0x62, 0x78, 0x60, 0x62, 0xb6, 0x8b, 0x6c, 0xef, 0x62, 0xf1, 0x57, -0x55, 0x64, 0xe1, 0x05, 0x4f, 0x16, 0xef, 0xcc, 0x66, 0x01, 0x3e, 0x2c, 0x42, 0x38, 0x78, 0x11, -0x33, 0x17, 0xb2, 0x2c, 0x06, 0x86, 0xc5, 0x0f, 0x1f, 0x51, 0x2c, 0x1b, 0x17, 0xee, 0x88, 0x50, -0xb9, 0x32, 0x88, 0x33, 0x80, 0x3c, 0xb5, 0x72, 0xe0, 0xc9, 0x28, 0x9d, 0x4c, 0x22, 0xab, 0x67, -0x24, 0x29, 0x41, 0x15, 0x0c, 0x62, 0x33, 0xa1, 0x22, 0xbc, 0x05, 0xbf, 0xc8, 0xf8, 0xc8, 0x85, -0x45, 0x43, 0x56, 0x88, 0x9c, 0x0f, 0x44, 0x71, 0x66, 0x82, 0x91, 0x17, 0x88, 0x58, 0xf2, 0x38, -0xc9, 0xc3, 0x97, 0xc6, 0x7c, 0x0d, 0x1b, 0x12, 0xe2, 0x50, 0x3b, 0xaa, 0x0c, 0x33, 0x15, 0xff, -0xcf, 0xcd, 0xef, 0xec, 0xff, 0xdc, 0x8b, 0x0c, 0xc8, 0x27, 0xd1, 0x05, 0x9c, 0xf0, 0x0a, 0x1c, -0x4c, 0x80, 0xb0, 0x67, 0xb2, 0x08, 0x00, 0x01, 0x0c, 0x62, 0x33, 0x01, 0x0a, 0x98, 0x01, 0x21, -0x4b, 0x80, 0x55, 0x34, 0x01, 0xbb, 0x7e, 0x07, 0x06, 0x1d, 0x3c, 0x81, 0x01, 0x1b, 0xc0, 0xb9, -0x0d, 0x2d, 0x96, 0x30, 0x18, 0x10, 0x3c, 0x60, 0x15, 0x91, 0x41, 0x33, 0x0c, 0x58, 0x0d, 0x19, -0x30, 0x0b, 0x34, 0x60, 0x0a, 0x61, 0x15, 0x67, 0x40, 0x50, 0x28, 0x90, 0x41, 0x84, 0x51, 0x84, -0x33, 0xc9, 0xa0, 0x66, 0xc5, 0x17, 0x50, 0x7e, 0x17, 0x83, 0x4c, 0x3c, 0x55, 0xd1, 0x5e, 0x38, -0x07, 0x19, 0xe7, 0x66, 0x2d, 0x21, 0x08, 0x19, 0xc4, 0x7c, 0x33, 0x16, 0x47, 0x8f, 0x1b, 0xd8, -0xc5, 0xfc, 0x19, 0x7c, 0xc2, 0x10, 0xbf, 0x13, 0xc2, 0x7c, 0x3c, 0x65, 0x33, 0xe9, 0x74, 0x50, -0x27, 0x97, 0x57, 0xd1, 0x22, 0x92, 0x72, 0x50, 0x92, 0x5f, 0x50, 0x60, 0x60, 0xf8, 0x18, 0x41, -0x0f, 0x5d, 0xf0, 0xe6, 0x06, 0x06, 0x77, 0xfc, 0xac, 0xa0, 0x60, 0xf6, 0x83, 0xea, 0xec, 0xf9, -0x44, 0x05, 0xa2, 0x78, 0xae, 0xea, 0x45, 0x9c, 0x0c, 0x2c, 0x23, 0x9b, 0x25, 0x10, 0x97, 0x81, -0x20, 0xb7, 0x01, 0x2b, 0x60, 0x20, 0x63, 0x25, 0x27, 0x83, 0x89, 0x20, 0x97, 0x02, 0xd5, 0xfb, -0xa2, 0x56, 0xb0, 0xb2, 0xab, 0x41, 0x12, 0xa3, 0x93, 0x80, 0xc3, 0x59, 0x51, 0xdb, 0xa8, 0x02, -0x17, 0x32, 0xeb, 0xf2, 0xd8, 0xf6, 0x58, 0x5c, 0x5a, 0x00, 0xdc, 0x0c, 0xb2, 0x77, 0x58, 0x0e, -0x0f, 0xe5, 0x5d, 0x00, 0xd8, 0xd8, 0xfc, 0xda, 0xde, 0xb0, 0xdc, 0x0c, 0x0e, 0x09, 0xcb, 0x0f, -0x3e, 0x8c, 0xa0, 0x7c, 0xec, 0x90, 0x3f, 0x0f, 0xea, 0xb0, 0x3f, 0x2d, 0x21, 0x5b, 0x29, 0xea, -0x0c, 0x6b, 0x05, 0x2c, 0x80, 0x91, 0x43, 0xb7, 0xb2, 0x63, 0x00, 0xd9, 0x67, 0xee, 0x6c, 0xfe, -0x10, 0x0c, 0xd4, 0x6c, 0x0f, 0x56, 0x02, 0x7b, 0x32, 0xa2, 0x8b, 0x00, 0x95, 0xa8, 0x84, 0xdb, -0x92, 0x8d, 0xeb, 0xf0, 0x46, 0xd4, 0x9b, 0xa2, 0x56, 0x15, 0xb2, 0xab, 0x90, 0x11, 0xab, 0x44, -0x8d, 0x0c, 0x6a, 0x09, 0xb8, 0x2b, 0x03, 0x7b, 0x49, 0x51, 0x8b, 0x88, 0x0a, 0x54, 0xc8, 0xbb, -0x42, 0x56, 0xcb, 0x32, 0xa2, 0xcb, 0x94, 0x11, 0x3f, 0x0c, 0xa8, 0xfb, 0x45, 0x2d, 0x2a, 0x64, -0x0b, 0x21, 0x29, 0x2b, 0x4a, 0x19, 0x9f, 0xfd, 0xab, 0x05, 0x6c, 0xd8, 0x6c, 0x36, 0xb9, 0x80, -0x0f, 0x0d, 0x23, 0xaa, 0x11, 0x9b, 0xad, 0x02, 0x25, 0x41, 0x9b, 0x2b, 0x6a, 0xab, 0x51, 0x21, -0x1a, 0x49, 0x8b, 0x4b, 0xa0, 0x8b, 0x59, 0x05, 0x67, 0xa8, 0x55, 0xb5, 0xa4, 0xdb, 0x95, 0x40, -0xeb, 0xac, 0x82, 0x67, 0xb5, 0x8a, 0x90, 0x15, 0x5b, 0xb0, 0x8c, 0xff, 0x91, 0x55, 0x67, 0x10, -0x56, 0x21, 0x21, 0x46, 0xce, 0x0f, 0x66, 0x2c, 0x92, 0x32, 0xa8, 0xfb, 0x15, 0xb5, 0xaa, 0x95, -0xfb, 0x8d, 0x24, 0x0b, 0x24, 0x50, 0x0b, 0x8b, 0x28, 0x2f, 0x40, 0x35, 0x6a, 0x84, 0x1b, 0x35, -0x89, 0x2b, 0x95, 0x40, 0x2b, 0xac, 0x82, 0x67, 0xd5, 0xaa, 0x56, 0x12, 0x7b, 0x93, 0x82, 0x63, -0xa7, 0xa0, 0x3c, 0x64, 0x93, 0x60, 0x36, 0x18, 0x54, 0xab, 0xa2, 0x46, 0xd5, 0x32, 0xab, 0x52, -0x12, 0xbb, 0x3c, 0xa2, 0xbb, 0x89, 0xea, 0xcb, 0x51, 0x2b, 0x5a, 0x19, 0xcb, 0x75, 0xa2, 0xdb, -0x85, 0x11, 0xdb, 0x2b, 0x6b, 0xef, 0x19, 0x54, 0xcb, 0x8b, 0x6a, 0xdb, 0x54, 0x2b, 0xaa, 0x49, -0x2b, 0x23, 0x84, 0x3b, 0x19, 0x51, 0xab, 0xa2, 0x0a, 0x44, 0x48, 0xbb, 0x0a, 0x09, 0x63, 0x4a, -0x82, 0x20, 0x06, 0xd0, 0xcc, 0x8b, 0x6a, 0x0b, 0x54, 0x2b, 0x5a, 0x49, 0x5b, 0x4d, 0xa8, 0x6b, -0xaa, 0x85, 0xbf, 0x01, 0x2c, 0x6b, 0xa4, 0xa8, 0xfe, 0x3b, 0x51, 0xad, 0x6a, 0x65, 0x4b, 0x21, -0x29, 0x9b, 0xea, 0x65, 0x3f, 0x07, 0x07, 0x2b, 0x29, 0xdb, 0x58, 0x54, 0xeb, 0x02, 0x58, 0x38, -0x13, 0x1b, 0x28, 0x83, 0x33, 0x04, 0x22, 0x48, 0x12, 0x04, 0x04, 0x27, 0x03, 0x09, 0x96, 0x02, -0x01, 0x03, 0x26, 0xf0, 0xff, 0x82, 0x03, 0xf0, 0x8c, 0x0c, 0x71, 0x64, 0x10, 0x8d, 0x2c, 0x60, -0x3d, 0x16, 0xb0, 0x59, 0x51, 0x67, 0x48, 0x49, 0xc1, 0x4b, 0x28, 0x81, 0x59, 0x51, 0x69, 0x0b, -0x18, 0x75, 0xc0, 0x08, 0xa2, 0x66, 0xeb, 0x85, 0xb0, 0x93, 0x65, 0x50, 0x61, 0xcb, 0x80, 0xe5, -0xc0, 0x80, 0xdc, 0xe3, 0x30, 0xe0, 0xdc, 0xe1, 0x0c, 0x38, 0xdc, 0xdf, 0x12, 0x0e, 0xdc, 0x17, -0x03, 0xce, 0xdb, 0x80, 0x03, 0xe6, 0x53, 0xcb, 0xd9, 0xc8, 0xc3, 0x80, 0xd7, 0x82, 0x53, 0xd6, -0x10, 0x12, 0x01, 0x46, 0x42, 0x1d, 0x30, 0x03, 0xc4, 0xbd, 0x19, 0xc0, 0x0a, 0x80, 0x9a, 0x0d, -0x54, 0xca, 0x1f, 0x5a, 0x46, 0x8d, 0xc8, 0x80, 0x73, 0x46, 0xd4, 0xe1, 0x88, 0x5a, 0xc0, 0xc8, -0x9b, 0x94, 0x79, 0xc3, 0x57, 0x46, 0xa9, 0xfe, 0x90, 0x01, 0xbe, 0xa4, 0xa8, 0x5f, 0x9a, 0x85, -0x0d, 0xc8, 0x88, 0xb7, 0x56, 0xd4, 0x85, 0x88, 0x5a, 0xc2, 0xc8, 0xc5, 0xf7, 0xa0, 0x42, 0x35, -0x90, 0x6f, 0x96, 0x14, 0xdd, 0x92, 0xa2, 0x19, 0x90, 0x31, 0x4b, 0xc8, 0x80, 0xa8, 0x7a, 0xc0, -0xa6, 0xc0, 0x88, 0x9b, 0x50, 0x21, 0x1a, 0x49, 0xfb, 0xcb, 0x8a, 0x69, 0x49, 0x51, 0x6d, 0x0c, -0x48, 0x35, 0x55, 0x10, 0x1a, 0x94, 0x67, 0x4b, 0x8a, 0xb3, 0x89, 0x01, 0x89, 0x55, 0x10, 0x16, -0x90, 0x67, 0xb0, 0xa2, 0x23, 0x96, 0x91, 0x9f, 0xb0, 0x0a, 0x67, 0xd8, 0xaa, 0xfd, 0x30, 0x20, -0x66, 0xea, 0x31, 0x40, 0x2b, 0x83, 0x6f, 0x59, 0x51, 0xaf, 0x0e, 0x08, 0x5f, 0x8a, 0x3a, 0xc0, -0xca, 0xbd, 0xa2, 0x66, 0x5b, 0x0c, 0xb0, 0xcb, 0xa8, 0x07, 0x57, 0xac, 0xac, 0xd9, 0x64, 0x15, -0x67, 0x03, 0x42, 0x4b, 0x51, 0x03, 0x0b, 0x09, 0xad, 0x30, 0x66, 0x0b, 0x18, 0xb0, 0x03, 0x63, -0xcc, 0xce, 0x95, 0x55, 0x75, 0xc1, 0x80, 0x41, 0x84, 0xaa, 0xf0, 0x9b, 0x06, 0xac, 0x3d, 0x11, -0x35, 0xc2, 0xaa, 0x95, 0xc5, 0x85, 0x24, 0x33, 0x2f, 0x59, 0xf7, 0x2b, 0x5a, 0x59, 0x51, 0xcb, -0xa0, 0x45, 0x59, 0x54, 0x13, 0x83, 0x6a, 0x99, 0x72, 0x23, 0x8b, 0x44, 0x4d, 0xfd, 0x6a, 0x65, -0xa9, 0x2c, 0x89, 0x17, 0x91, 0x40, 0x7d, 0xc8, 0x80, 0x24, 0x65, 0xc0, 0x22, 0xc8, 0x80, 0x20, -0x06, 0xd5, 0xc3, 0x0c, 0x58, 0x1d, 0x6a, 0xd9, 0xa7, 0x2b, 0x89, 0xb1, 0xa4, 0xa8, 0xfe, 0x27, -0x51, 0xad, 0xa8, 0x25, 0x95, 0x8d, 0xa4, 0x7b, 0x51, 0xe7, 0x37, 0x58, 0x49, 0xb3, 0x90, 0x0c, -0x0d, 0x26, 0x01, 0x4b, 0x41, 0x4c, 0x10, 0x80, 0x33, 0x05, 0x02, 0x9f, 0xd0, 0x58, 0xfe, 0x0c, -0xa1, 0xcf, 0xe5, 0x07, 0x6c, 0xd3, 0xf6, 0xa2, 0x7e, 0x9c, 0x07, 0x5e, 0x8b, 0xe7, 0x00, 0xb0, -0x08, 0xff, 0x0a, 0x5a, 0x06, 0x04, 0x31, 0xcf, 0xa8, 0x60, 0xcb, 0x51, 0x4b, 0xde, 0xa8, 0x48, -0x43, 0x45, 0x4d, 0xce, 0xa3, 0x21, 0xa3, 0xa5, 0x19, 0xc1, 0xeb, 0x8c, 0x60, 0xfb, 0xa3, 0x36, -0x69, 0xa0, 0xa8, 0x96, 0x9e, 0x34, 0xac, 0xc3, 0x16, 0x7f, 0x97, 0x5e, 0x5b, 0xde, 0x15, 0x9a, -0xd1, 0x58, 0xa9, 0xb9, 0x3f, 0x8b, 0xfe, 0xdb, 0xde, 0x05, 0xb0, 0x19, 0x9d, 0xa0, 0xc6, 0x5a, -0x1f, 0x9f, 0x66, 0x11, 0x65, 0xfc, 0xed, 0xfc, 0x07, 0xc6, 0xcc, 0xf8, 0xf8, 0xcc, 0xc6, 0x82, -0x14, 0x3b, 0x41, 0x0a, 0x4b, 0x0d, 0x12, 0x2e, 0x38, 0xd4, 0x8b, 0x06, 0x07, 0x6a, 0x16, 0x0b, -0xd4, 0x12, 0x2e, 0xa3, 0x17, 0x3b, 0x49, 0xf5, 0x91, 0x48, 0x3c, 0x86, 0x11, 0x9b, 0x90, 0xa2, -0xa3, 0x46, 0x54, 0xa3, 0x29, 0x6a, 0xab, 0xa2, 0x0e, 0x00, 0x7b, 0x91, 0x0b, 0x05, 0x07, 0x46, -0xd4, 0xab, 0x8a, 0x1a, 0x11, 0x75, 0xb3, 0xa2, 0x96, 0xb3, 0x50, 0x93, 0xbb, 0x6a, 0x58, 0xcb, -0x35, 0x29, 0x53, 0x86, 0x11, 0xe3, 0x27, 0xf1, 0x05, 0x0d, 0x33, 0x1b, 0x05, 0x33, 0x33, 0xca, -0x7d, 0x97, 0x66, 0x09, 0x02, 0x23, 0x9b, 0x10, 0x15, 0xa2, 0x86, 0x1b, 0x42, 0x93, 0xa3, 0xb8, -0x24, 0x1a, 0xf6, 0x55, 0x10, 0x28, 0x94, 0x67, 0xb3, 0x49, 0x94, 0x7c, 0x06, 0x59, 0x05, 0x67, -0xa8, 0x10, 0x34, 0xa4, 0x7b, 0x82, 0x49, 0xde, 0x88, 0xac, 0x67, 0x84, 0x5e, 0x91, 0x27, 0x53, -0xd4, 0xc3, 0xac, 0xa8, 0xcb, 0x14, 0x95, 0x10, 0x9a, 0xcb, 0x11, 0x86, 0xd0, 0x0a, 0x2d, 0x89, -0x6e, 0xa2, 0x08, 0x60, 0x16, 0x4b, 0x5e, 0xaf, 0xab, 0x20, 0x67, 0x51, 0x28, 0xa8, 0x25, 0x6e, -0x61, 0x8f, 0x13, 0x1b, 0xac, 0xa8, 0xa3, 0x11, 0xb5, 0xf5, 0xe2, 0xa3, 0x2b, 0x81, 0x11, 0xab, -0xf5, 0xa0, 0xf6, 0x96, 0x11, 0xb3, 0x11, 0xf5, 0x05, 0x8b, 0x80, 0xbb, 0x9d, 0x45, 0x2d, 0xa8, -0x62, 0xb3, 0x66, 0x13, 0xbb, 0x4f, 0x12, 0xa8, 0xeb, 0x46, 0xd4, 0xa3, 0xb3, 0x08, 0x6f, 0x10, -0x88, 0x7c, 0xcb, 0xf2, 0x45, 0x5c, 0x7e, 0x06, 0x5d, 0xf6, 0x86, 0x8a, 0x5a, 0x19, 0xf4, 0xfb, -0x76, 0xcc, 0x62, 0x35, 0x6a, 0x59, 0x3d, 0x1d, 0x23, 0xeb, 0xf8, 0x0c, 0x8b, 0xd7, 0x06, 0x0c, -0xfa, 0x1c, 0x61, 0x11, 0x32, 0x55, 0xb0, 0x9f, 0x1a, 0x02, 0xc3, 0x49, 0xa8, 0xdb, 0x59, 0x05, -0x67, 0x40, 0x0e, 0x1d, 0xbf, 0xf2, 0x64, 0x62, 0x05, 0x99, 0x52, 0x44, 0x0a, 0x4a, 0x21, 0x0b, -0x50, 0x45, 0x00, 0x90, 0x14, 0xa1, 0xc1, 0x39, 0x13, 0x50, 0x56, 0x67, 0x09, 0x44, 0x00, 0x08, -0x94, 0x84, 0x22, 0x11, 0x30, 0x2f, 0xb7, 0xc0, 0x2a, 0x67, 0x01, 0x08, 0x45, 0x21, 0x40, 0x42, -0x11, 0x02, 0x48, 0x12, 0xa3, 0x21, 0x83, 0x33, 0x0c, 0xc8, 0x51, 0xe5, 0x68, 0x0a, 0x9e, 0x39, -0xbf, 0x22, 0xb2, 0x67, 0x50, 0xb2, 0x49, 0x50, 0xa2, 0x02, 0x41, 0x85, 0xc1, 0x39, 0xbb, 0x50, -0x56, 0x67, 0x12, 0x45, 0xbc, 0xa0, 0x17, 0xab, 0xc0, 0x67, 0x02, 0x02, 0x51, 0xa1, 0x20, 0x08, -0x2b, 0x0a, 0xab, 0x67, 0x7f, 0xa8, 0x0d, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x7f, 0xfb, 0x20, 0x66, -0x6f, 0x6e, 0x74, 0x04, 0x69, 0x6c, 0x65, 0x20, 0x68, 0x61, 0xff, 0x6f, 0x0d, 0x62, 0x65, 0x65, -0x6e, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0xdb, 0x64, 0x2f, 0x02, 0x69, 0x06, 0x13, -0xb7, 0x7f, 0x79, 0x20, 0x43, 0x50, 0x49, 0x61, 0x64, 0x09, 0x56, 0x31, 0xff, 0xed, 0x2e, 0x32, -0x30, 0x37, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0xfd, 0x2f, 0x28, 0x43, 0x29, 0x20, -0x31, 0x39, 0x39, 0x33, 0x2d, 0xfb, 0xd7, 0x04, 0x36, 0x28, 0x6b, 0x6f, 0x73, 0x74, 0x54, 0xdb, -0x7f, 0x40, 0x61, 0x63, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x1f, 0x4b, 0x63, 0x77, 0x0f, 0x61, 0x20, -0x4b, 0x15, 0x29, 0xff, 0x60, 0x71, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x77, 0xf7, 0x20, -0x6d, 0x61, 0x79, 0x6f, 0x20, 0x75, 0x73, 0x63, 0xdd, 0x5a, 0x66, 0x72, 0x09, 0x6f, 0x66, 0x6b, -0xad, 0x7a, 0x84, 0x36, 0x09, 0xf6, 0x5b, 0x7e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x11, 0xdf, 0xda, -0x77, 0x8d, 0x69, 0x73, 0x6b, 0x2e, 0x0d, 0x00, 0x80, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, -0xff, 0xa4, 0xe8, 0x3a, 0x00, 0x72, 0xfa, 0x41, 0xe8, 0x2f, 0x00, 0xe3, 0x3b, 0x73, 0xf9, 0x83, -0xe9, 0x03, 0x72, 0x06, 0x88, 0xcc, 0xac, 0xf7, 0xd0, 0x95, 0x31, 0xc9, 0xe8, 0x1b, 0x00, 0x11, -0xc9, 0x75, 0x08, 0x41, 0xe8, 0x13, 0x00, 0x73, 0xfb, 0x41, 0x41, 0x81, 0xfd, 0x00, 0xf3, 0x83, -0xd1, 0x01, 0x8d, 0x03, 0x96, 0xf3, 0xa4, 0x96, 0xeb, 0xc8, 0xe8, 0x02, 0x00, 0x11, 0xc9, 0x01, -0xdb, 0x75, 0x04, 0xad, 0x11, 0xc0, 0x93, 0xc3, 0x5e, 0xb9, 0x01, 0x00, 0xac, 0x2c, 0xe8, 0x3c, -0x01, 0x77, 0xf9, 0x8b, 0x1c, 0x86, 0xdf, 0x29, 0xf3, 0x89, 0x1c, 0xad, 0xe2, 0xee, 0xc3 }; - -Bit8u font_ega5_cpx[5720] = { -0x81, 0xfc, 0x9a, 0xc1, 0x77, 0x02, 0xcd, 0x20, 0xb9, 0x58, 0x16, 0xbe, 0x58, 0x17, 0xbf, 0x3a, -0xc1, 0xbb, 0x00, 0x80, 0xfd, 0xf3, 0xa4, 0xfc, 0x87, 0xf7, 0x83, 0xee, 0xc6, 0x19, 0xed, 0x57, -0x57, 0xe9, 0xb9, 0xbf, 0x55, 0x50, 0x58, 0x21, 0x0b, 0x01, 0x04, 0x08, 0xcf, 0xfc, 0xfe, 0x92, -0xf9, 0xe1, 0xc2, 0x32, 0xcc, 0xbf, 0xc0, 0x15, 0x06, 0xcf, 0xbb, 0xfc, 0xff, 0x46, 0x4f, 0x4e, -0x54, 0x20, 0x00, 0x00, 0x01, 0x6e, 0x39, 0x01, 0x17, 0x06, 0xfd, 0xfd, 0x05, 0x00, 0x1c, 0x00, -0x4d, 0x26, 0x0e, 0x45, 0x47, 0x41, 0xc9, 0xcd, 0x1e, 0x20, 0xe1, 0x02, 0xfe, 0xd8, 0x35, 0x24, -0x03, 0x00, 0x12, 0x26, 0x10, 0x08, 0x95, 0xc5, 0x0a, 0x00, 0x6d, 0xff, 0x7e, 0x81, 0xa5, 0x81, -0x81, 0xbd, 0x99, 0x03, 0x7e, 0xfe, 0x83, 0x0f, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, -0xe6, 0x77, 0x00, 0x6c, 0xfe, 0x3e, 0xec, 0x7c, 0x38, 0x10, 0x30, 0x10, 0x38, 0x7c, 0xfd, 0xc0, -0x0e, 0x18, 0x3c, 0x3c, 0xe7, 0xb2, 0xb6, 0x00, 0x18, 0x06, 0x0f, 0x65, 0x6e, 0x7e, 0x3b, 0x0f, -0xb3, 0xb3, 0x22, 0x18, 0x09, 0xde, 0xb1, 0xff, 0x00, 0xe7, 0xc3, 0x5f, 0x3f, 0xf6, 0x00, 0x1f, -0x3c, 0x66, 0x42, 0x42, 0x66, 0xff, 0x92, 0x3c, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xfe, 0x21, -0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xde, 0xeb, 0x00, 0x78, 0x20, 0x2d, 0xb9, 0xe6, 0x00, 0x4f, -0x61, 0xbb, 0x9f, 0x0f, 0x3f, 0x33, 0x3f, 0x30, 0x00, 0x70, 0xf0, 0xf9, 0xc8, 0xe0, 0x00, 0x7f, -0x63, 0x7f, 0x63, 0x9e, 0xbd, 0x67, 0xe7, 0xe6, 0xc0, 0x7c, 0x18, 0xdb, 0x87, 0xdd, 0xa0, 0x3c, -0xdb, 0x2e, 0x80, 0xbb, 0xfd, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0x2d, 0xc0, 0x80, 0xbf, 0xfe, -0x1f, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x6b, 0x49, 0x2b, 0x5e, -0x7c, 0x67, 0x3c, 0x00, 0x66, 0x98, 0x9b, 0x07, 0x5f, 0xe7, 0x36, 0xdb, 0x00, 0x7b, 0x1b, 0xff, -0x9b, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0x06, 0xe4, 0xc6, 0x7c, -0x00, 0xfe, 0x43, 0x66, 0x4f, 0x7e, 0x6f, 0x60, 0x0f, 0x00, 0xbd, 0x60, 0x0f, 0x00, 0xfe, 0x96, -0x70, 0x11, 0x0c, 0xfe, 0x0c, 0x77, 0xc9, 0x0c, 0x00, 0x30, 0x60, 0xfe, 0x06, 0xe4, 0x60, 0x30, -0x00, 0xc0, 0x61, 0x56, 0x5c, 0xa1, 0x76, 0x39, 0x28, 0x6c, 0x28, 0x0e, 0x50, 0x58, 0x9f, 0xb2, -0xb7, 0xa0, 0x7c, 0x7d, 0x8a, 0x0e, 0x5b, 0x0e, 0x38, 0xaf, 0xbc, 0xc0, 0x00, 0x18, 0x3c, 0x66, -0xaf, 0x8c, 0x8f, 0x21, 0xeb, 0xe9, 0x24, 0x20, 0x8b, 0xb9, 0x6c, 0x5e, 0x03, 0xad, 0xfe, 0x36, -0xf1, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0x1e, 0xd6, 0xef, 0xc1, 0xc2, 0xc6, 0x26, 0xdf, 0xae, -0x30, 0x60, 0xc6, 0x86, 0x2e, 0x14, 0x0e, 0x0c, 0x76, 0xdc, 0xc1, 0x1a, 0xaf, 0x76, 0xbd, 0x81, -0x6d, 0x00, 0x60, 0x4e, 0x8b, 0xb9, 0x2b, 0x00, 0xe5, 0xb9, 0x59, 0x0f, 0x08, 0x96, 0x8d, 0x00, -0x18, 0xe2, 0x15, 0x16, 0xde, 0xff, 0xe5, 0x84, 0x81, 0xa2, 0xed, 0x06, 0xb6, 0x14, 0x6c, 0xc0, -0x31, 0xfe, 0xd7, 0x96, 0xad, 0x31, 0xf9, 0x15, 0xe2, 0x9f, 0xc0, 0x80, 0xf8, 0x30, 0xae, 0xd6, -0xd6, 0x0e, 0x76, 0xb2, 0x27, 0x38, 0x78, 0x59, 0x10, 0x81, 0x2e, 0xf6, 0xe4, 0x7c, 0xc6, 0xc6, -0xfe, 0x0f, 0xd8, 0x4e, 0x06, 0x3c, 0x02, 0x06, 0xfd, 0x43, 0xdf, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, -0xfe, 0x9c, 0xd0, 0xb0, 0x1e, 0x8d, 0xfe, 0x03, 0xd6, 0xfc, 0x1f, 0x38, 0x90, 0xbb, 0x60, 0x0f, -0xc6, 0xc6, 0xc6, 0x66, 0xee, 0xfe, 0x3f, 0xf3, 0x73, 0xc3, 0x4f, 0x1a, 0x1f, 0x7d, 0x01, 0x0b, -0x7e, 0x0b, 0xdb, 0x3f, 0x0c, 0x78, 0xba, 0x0b, 0x7b, 0x04, 0x0f, 0x62, 0x93, 0x30, 0x9e, 0x92, -0x1a, 0x35, 0x06, 0xc2, 0xc9, 0xde, 0x02, 0x00, 0xf6, 0x62, 0x1b, 0x23, 0x5f, 0x25, 0x4c, 0x0c, -0xdf, 0xb6, 0xb3, 0x10, 0xde, 0x00, 0xdc, 0x61, 0x14, 0xc4, 0x2e, 0x3b, 0xdb, 0x6c, 0x90, 0xfe, -0x0f, 0x6c, 0x3c, 0xfc, 0x66, 0xf1, 0x7c, 0x86, 0xf4, 0xfc, 0x6f, 0xd4, 0x15, 0xef, 0x00, 0xc2, -0xf2, 0xe9, 0xa1, 0x10, 0xf8, 0x6c, 0x3f, 0x7b, 0x6c, 0xf8, 0x0f, 0xfe, 0x66, 0x62, 0x68, 0x84, -0xfc, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0xc0, 0xb6, 0x00, 0xf0, 0x3f, 0x4d, 0x7e, 0xde, 0xc6, -0xc6, 0x66, 0x3a, 0x61, 0xef, 0x69, 0x6e, 0x6f, 0x6b, 0xc2, 0x3c, 0x7d, 0x30, 0x31, 0x26, 0x1e, -0x0d, 0x77, 0x49, 0xef, 0xe6, 0x6a, 0xb3, 0x6e, 0x78, 0x78, 0x74, 0xe6, 0x0f, 0xb3, 0xd8, 0xf0, -0x60, 0x00, 0x6f, 0x92, 0x7f, 0x4f, 0xee, 0xfe, 0xfe, 0xd6, 0xf2, 0xdb, 0x0f, 0xe6, 0xf6, 0xfe, -0xde, 0xce, 0x79, 0x58, 0x6f, 0xc6, 0x9b, 0x2d, 0xdf, 0x41, 0x27, 0xec, 0xf0, 0x1f, 0xd6, 0xde, -0x97, 0xe4, 0x7c, 0x0c, 0x0e, 0xe3, 0x29, 0xd9, 0xe6, 0x1f, 0xe2, 0xb2, 0x42, 0x50, 0x3f, 0x09, -0x7b, 0x7e, 0x7e, 0x5a, 0xaf, 0x16, 0xb2, 0xc6, 0x5f, 0x0f, 0x25, 0x0f, 0x6c, 0x38, 0x10, 0x43, -0xfe, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x6b, 0xa6, 0x6c, 0x8e, 0x61, 0x9f, 0x66, 0x0d, 0xce, -0x0b, 0xcb, 0x4f, 0x1b, 0x86, 0x21, 0x1f, 0x7f, 0xc2, 0x16, 0xec, 0x3c, 0x30, 0x00, 0x1f, 0xfe, -0x0a, 0xc1, 0x70, 0x38, 0x1c, 0x76, 0xb2, 0xaf, 0x3c, 0x0c, 0x00, 0x62, 0x0c, 0x3c, 0xdc, 0x8d, -0x90, 0xe6, 0xec, 0x34, 0x6c, 0xff, 0x18, 0xe9, 0x03, 0x78, 0x0c, 0x7c, 0xaf, 0x16, 0x2e, 0xe0, -0x19, 0x78, 0x66, 0x11, 0xe2, 0xcf, 0x1c, 0x13, 0x02, 0x00, 0xb9, 0xc3, 0xdf, 0x1c, 0x69, 0x2d, -0x2b, 0x00, 0x2f, 0x80, 0x8c, 0x1f, 0xfe, 0xc6, 0xfb, 0x36, 0x32, 0x30, 0x78, 0xaf, 0xcf, 0xf0, -0x5d, 0x76, 0x2e, 0xcc, 0xdf, 0xa1, 0x5f, 0xd2, 0x5f, 0x6c, 0x32, 0x9e, 0x76, 0xe6, 0xdc, 0x03, -0x61, 0x38, 0x4f, 0x6b, 0x4b, 0x09, 0x00, 0xdb, 0x00, 0xcc, 0x10, 0x17, 0x2f, 0x71, 0xc6, 0x00, -0xe6, 0x90, 0x9c, 0x2f, 0x38, 0x35, 0xba, 0x00, 0xec, 0x00, 0x4c, 0xd6, 0x00, 0xc6, 0x0f, 0xdc, -0xcb, 0x66, 0xa1, 0x9f, 0x6c, 0x09, 0x9f, 0x1f, 0xf6, 0xb1, 0x04, 0xf0, 0x9f, 0x90, 0x16, 0xd2, -0x19, 0xed, 0xdc, 0x9f, 0x1f, 0x4c, 0x60, 0xe4, 0x76, 0x09, 0xdf, 0x10, 0xd9, 0xb2, 0xdf, 0xfc, -0xde, 0x36, 0x1c, 0x1f, 0x10, 0x5e, 0x3d, 0x0f, 0x82, 0x31, 0x00, 0x47, 0xc0, 0x0f, 0x00, 0xb7, -0x84, 0x9a, 0x1b, 0x30, 0x53, 0x38, 0x75, 0x2f, 0xd4, 0xb5, 0x04, 0x0c, 0x03, 0x87, 0x52, 0xcc, -0x4f, 0xcd, 0xd9, 0xfe, 0xef, 0x0e, 0x70, 0x64, 0x3d, 0x0e, 0xf7, 0x09, 0x83, 0x3f, 0xda, 0x7b, -0x1b, 0x23, 0x24, 0x40, 0xf8, 0xc9, 0xdc, 0xdf, 0x8b, 0x34, 0xe2, 0x4f, 0x95, 0x34, 0xef, 0x76, -0x7a, 0xfe, 0x62, 0x1c, 0xff, 0xe6, 0x5e, 0x10, 0x10, 0xab, 0x3f, 0x2b, 0x69, 0xef, 0x5a, 0x19, -0xaf, 0x69, 0x4a, 0xdf, 0x7c, 0xef, 0x40, 0x0e, 0x7c, 0x91, 0xb4, 0xdf, 0x69, 0xb2, 0x6f, 0xc6, -0xdf, 0x52, 0x08, 0xe0, 0x30, 0x48, 0xde, 0x6d, 0xed, 0x82, 0x63, 0x5b, 0x82, 0x02, 0xa9, 0x07, -0xef, 0x0e, 0xe9, 0xfe, 0xff, 0xc6, 0xb6, 0x40, 0x1f, 0x6b, 0xe0, 0x62, 0x30, 0x5b, 0x62, 0xbf, -0x56, 0xd2, 0xdf, 0xb4, 0x92, 0x9f, 0xf6, 0xb1, 0xd7, 0x7c, 0x6d, 0x7c, 0xa6, 0x0b, 0xa4, 0xcf, -0xd8, 0x7b, 0x1c, 0x1e, 0x1f, 0x17, 0x61, 0x7b, 0x24, 0x2f, 0x69, 0x28, 0xee, 0x0f, 0xdc, 0xd8, -0x60, 0x6c, 0x00, 0xdc, 0x2f, 0xe0, 0x8b, 0xdb, 0xd8, 0x3c, 0xf8, 0x30, 0xfc, 0xa1, 0xbe, 0x64, -0x1f, 0x35, 0x7c, 0xda, 0x04, 0x3f, 0x9e, 0x21, 0xc5, 0xd3, 0x8f, 0x24, 0x3b, 0x78, 0xc0, 0xdf, -0x61, 0x3a, 0x7d, 0x9f, 0x61, 0x34, 0x94, 0x3c, 0xff, 0x90, 0x69, 0x49, 0x6b, 0x9d, 0x2f, 0x3e, -0xbd, 0xc4, 0x2b, 0xd9, 0x3f, 0x4f, 0x97, 0x31, 0xbf, 0xc6, 0x6f, 0xf6, 0xcc, 0xf8, 0xf8, 0xcc, -0xbf, 0x8f, 0x78, 0x5f, 0x4b, 0x6c, 0x0f, 0xee, 0xc2, 0xdf, 0xf6, 0x63, 0x21, 0x09, 0xb2, 0xb3, -0x06, 0xa1, 0x30, 0x4f, 0x38, 0x63, 0x17, 0x4a, 0x3c, 0x60, 0x7f, 0x1c, 0x42, 0x48, 0x6f, 0x72, -0x2f, 0x3f, 0x00, 0x6c, 0x48, 0x8f, 0xfc, 0x4f, 0xe3, 0x9d, 0x7e, 0xd8, 0x00, 0xbf, 0x86, 0xc1, -0x32, 0xb2, 0xe6, 0x1a, 0x54, 0x4f, 0x21, 0x69, 0xfe, 0x6f, 0x03, 0x7b, 0x7f, 0xcf, 0x3a, 0x84, -0x5c, 0x72, 0x10, 0x9d, 0x40, 0x5f, 0x10, 0xd6, 0xb0, 0x93, 0x1f, 0x11, 0x44, 0x01, 0x85, 0xbc, -0x55, 0xaa, 0x2e, 0xe4, 0xdd, 0x77, 0x18, 0xbb, 0xc0, 0x00, 0xf8, 0x0d, 0x64, 0x21, 0x0f, 0xe4, -0xd9, 0x36, 0x00, 0xf6, 0x36, 0x1b, 0x16, 0xc0, 0x0f, 0x64, 0x09, 0x2f, 0xd8, 0x79, 0xf6, 0x06, -0x00, 0xcd, 0x12, 0x3d, 0xb4, 0x90, 0x1f, 0x2f, 0x2c, 0x59, 0xee, 0x11, 0x4b, 0x16, 0x0f, 0x8f, -0x64, 0x0d, 0x00, 0x43, 0x36, 0xf8, 0xbf, 0x1f, 0x3c, 0x61, 0x2f, 0x18, 0x18, 0xff, 0xc9, 0x90, -0xff, 0xc2, 0x1a, 0x72, 0xc8, 0xda, 0x1f, 0x3f, 0x0c, 0xd9, 0x2d, 0x1f, 0x36, 0x24, 0x0f, 0x37, -0xbf, 0xd8, 0x13, 0x37, 0x30, 0x3f, 0x6d, 0x95, 0x4a, 0xbf, 0xd9, 0x85, 0x1f, 0xf7, 0x5f, 0x1b, -0x6c, 0x6d, 0xf7, 0x3f, 0x64, 0x21, 0x2f, 0x65, 0xb3, 0x1f, 0x2f, 0x65, 0xb3, 0x3f, 0x2f, 0x61, -0xb0, 0xdd, 0xff, 0x2f, 0x64, 0x21, 0x5f, 0x46, 0x76, 0xff, 0xdf, 0x16, 0x12, 0x86, 0xaf, 0x0d, -0x4b, 0xdf, 0xbd, 0x84, 0x3f, 0xef, 0xc9, 0x85, 0x3f, 0x3f, 0x24, 0x0b, 0x4f, 0x84, 0x20, 0x2d, -0x5f, 0x24, 0x8c, 0xaf, 0x9b, 0x6c, 0x4f, 0xff, 0x00, 0x61, 0x21, 0x9f, 0xe4, 0xb0, 0x00, 0xf0, -0x48, 0x86, 0x0f, 0x58, 0x58, 0x36, 0xe4, 0x30, 0x8f, 0x44, 0x58, 0x0f, 0x08, 0x10, 0x8f, 0x96, -0x5b, 0x0f, 0x5f, 0xe5, 0x12, 0x0f, 0x1e, 0x96, 0x4f, 0xf5, 0x66, 0xb2, 0x41, 0x0e, 0x1f, 0x12, -0x56, 0x4f, 0x81, 0xf4, 0x3f, 0xff, 0x21, 0xe9, 0x04, 0x08, 0xaf, 0xb7, 0xb0, 0x66, 0x0f, 0x2f, -0x1c, 0x30, 0x8f, 0x40, 0x80, 0x5b, 0x18, 0x9f, 0x0f, 0x68, 0x60, 0x7e, 0xaa, 0x78, 0xcd, 0x1e, -0xaf, 0x7e, 0x0f, 0x2c, 0xf6, 0x3a, 0x7e, 0x40, 0x0f, 0x85, 0xc1, 0x4f, 0x08, 0xb4, 0x0f, 0xff, -0x3b, 0x5b, 0x2f, 0x3c, 0x1f, 0x02, 0x01, 0x8f, 0xac, 0x52, 0x5d, 0x96, 0xd4, 0x41, 0x16, 0xa4, -0x3e, 0x10, 0x90, 0x4a, 0x6e, 0xf6, 0x5e, 0x0f, 0xbc, 0x6f, 0x06, 0x17, 0x66, 0x1f, 0xe7, 0x52, -0x50, 0x2a, 0x02, 0x0f, 0x09, 0xee, 0x90, 0x58, 0x97, 0x0c, 0x30, 0x1f, 0x81, 0xac, 0xac, 0xb0, -0x61, 0x42, 0x00, 0xdb, 0xf3, 0x0f, 0x0c, 0xec, 0x34, 0x3c, 0x35, 0x08, 0x5f, 0x6c, 0x81, 0x81, -0x58, 0x2c, 0xd9, 0x16, 0xa0, 0x32, 0xbc, 0x93, 0x2f, 0x00, 0x7e, 0x06, 0x90, 0x00, 0x0e, 0xc1, -0x0b, 0x05, 0x1c, 0x61, 0x03, 0x7e, 0x07, 0x16, 0x01, 0x7e, 0x80, 0x04, 0xff, 0x93, 0x20, 0xfd, -0x95, 0x04, 0xfb, 0x4a, 0x82, 0xf9, 0x38, 0x41, 0xf7, 0x8c, 0x24, 0xf5, 0x58, 0x12, 0xf3, 0x8c, -0x24, 0xf1, 0x5d, 0x12, 0xef, 0x78, 0x24, 0x98, 0x27, 0xec, 0x4e, 0xb0, 0xeb, 0x2c, 0x09, 0xea, -0x82, 0x13, 0xe9, 0x49, 0x70, 0xe8, 0xe7, 0x98, 0x4a, 0x24, 0x82, 0x12, 0xe5, 0x04, 0x4b, 0xe4, -0x70, 0xaa, 0xe3, 0x32, 0x48, 0x49, 0xe1, 0x24, 0x24, 0xde, 0x18, 0x12, 0xdd, 0x30, 0x24, 0xdb, -0x1c, 0x49, 0xda, 0x00, 0x92, 0xa0, 0xd7, 0xac, 0x37, 0x0d, 0x01, 0x49, 0xb0, 0xd2, 0x27, 0x08, -0xd1, 0x84, 0x04, 0xcf, 0x93, 0x20, 0xcd, 0x95, 0x04, 0xcb, 0x4c, 0x82, 0xc9, 0x54, 0x12, 0xc7, -0x45, 0x82, 0xc3, 0x93, 0xc0, 0x76, 0xc1, 0x84, 0x04, 0xbe, 0x93, 0x20, 0xbd, 0x96, 0x04, 0xbc, -0xf0, 0x09, 0xbb, 0x66, 0xc6, 0x1c, 0x48, 0xb9, 0x76, 0x52, 0x12, 0x5f, 0x34, 0x09, 0xb5, 0x92, -0xe0, 0x06, 0xb3, 0x20, 0xd9, 0x20, 0x12, 0x9c, 0xb0, 0xae, 0xb0, 0x40, 0x4b, 0xc2, 0x18, 0xfe, -0xfb, 0x49, 0x10, 0xa5, 0x93, 0x5a, 0x44, 0x97, 0x04, 0xa3, 0x7e, 0x96, 0x04, 0xa1, 0x04, 0xa7, -0x20, 0x1c, 0x96, 0x9f, 0xa3, 0x5c, 0x12, 0x9d, 0x1e, 0x02, 0x12, 0x9b, 0x49, 0xf0, 0x1b, 0x99, -0x04, 0x6f, 0x0d, 0xc1, 0xec, 0x97, 0xd4, 0x70, 0x20, 0x95, 0x7c, 0x60, 0x49, 0x93, 0x41, 0x92, -0x92, 0x09, 0x26, 0x80, 0x8e, 0x62, 0x2b, 0xb3, 0x12, 0xbc, 0x1e, 0x8b, 0x09, 0x56, 0x88, 0x04, -0x09, 0xc1, 0x8b, 0x87, 0x3c, 0x2b, 0x25, 0x84, 0xf3, 0x48, 0x25, 0x91, 0x12, 0x4c, 0xfc, 0x7f, -0x24, 0x58, 0x7e, 0x4e, 0x10, 0x7d, 0xd4, 0x09, 0x7c, 0xa7, 0x96, 0x8b, 0x8a, 0xa3, 0x65, 0x0d, -0xd8, 0x25, 0xc1, 0x77, 0x42, 0xea, 0x66, 0x3a, 0x95, 0x84, 0xd4, 0x83, 0x20, 0xc1, 0x3c, 0x71, -0xea, 0x6c, 0xed, 0xe6, 0x64, 0x59, 0x8e, 0x6c, 0x6c, 0x24, 0x18, 0xf0, 0x6c, 0x3a, 0xb5, 0x8b, -0x35, 0x90, 0x8a, 0x75, 0x21, 0x88, 0x7c, 0xc8, 0x20, 0x65, 0x7c, 0x96, 0x4d, 0xf0, 0x1b, 0x81, -0x09, 0x62, 0x70, 0x20, 0x61, 0xe6, 0x6c, 0x49, 0x5f, 0x37, 0x3b, 0x35, 0x7d, 0x99, 0x48, 0x2d, -0xca, 0x24, 0x58, 0x58, 0x12, 0x24, 0x57, 0x36, 0x23, 0xd7, 0x0d, 0x5e, 0x29, 0x1c, 0x66, 0x25, -0xa4, 0xb3, 0x6a, 0x9b, 0x45, 0xf7, 0x8c, 0x04, 0xcb, 0xa0, 0x04, 0x87, 0x4f, 0x3c, 0x82, 0x95, -0x4c, 0x82, 0x41, 0x4b, 0x3c, 0x18, 0x48, 0x49, 0xff, 0x03, 0x24, 0x45, 0xf0, 0x04, 0x43, 0x76, -0x1c, 0x48, 0x41, 0x7c, 0x02, 0x12, 0x3f, 0x49, 0xf0, 0xc3, 0x3d, 0x5c, 0x76, 0x76, 0x1b, 0xfe, -0x09, 0x92, 0x39, 0x90, 0x60, 0x7c, 0x38, 0x0c, 0x18, 0x76, 0x96, 0x20, 0x41, 0x35, 0x48, 0x30, -0xe6, 0x33, 0x12, 0x1c, 0x3c, 0x31, 0x24, 0x58, 0x2f, 0x21, 0x24, 0xbf, 0x78, 0xb1, 0x26, 0x29, -0x24, 0x24, 0x2b, 0x12, 0x12, 0x09, 0x26, 0xa4, 0x97, 0x7c, 0x61, 0xc2, 0x1b, 0x7c, 0xc1, 0x60, -0xd9, 0x8b, 0x3b, 0x90, 0x21, 0xf0, 0x37, 0x26, 0x2f, 0x70, 0x1c, 0xd4, 0x09, 0x1d, 0x82, 0x84, -0xac, 0x42, 0x42, 0x1a, 0xbf, 0x31, 0x5b, 0x0d, 0xab, 0x65, 0x86, 0xf5, 0x80, 0x0d, 0x29, 0x82, -0xa7, 0x83, 0x7c, 0x1e, 0x49, 0x11, 0x83, 0x2e, 0x09, 0x0f, 0x0e, 0x09, 0x09, 0x0d, 0x81, 0x04, -0x0b, 0x20, 0xc1, 0x70, 0x09, 0x4d, 0x4a, 0x66, 0x1b, 0x20, 0x71, 0x08, 0xac, 0x98, 0x03, 0x35, -0x20, 0x96, 0x00, 0x3b, 0x30, 0x8f, 0xfe, 0x1b, 0x04, 0x26, 0xf0, 0xb1, 0xcd, 0x9a, 0xfe, 0xb3, -0x29, 0xe9, 0x0d, 0x63, 0x83, 0x01, 0xf7, 0x7c, 0x60, 0x65, 0xa7, 0x0d, 0x16, 0x70, 0xd8, 0xc3, -0x18, 0xf0, 0xf0, 0xd8, 0xcc, 0xc6, 0xf1, 0x4a, 0x4a, 0x63, 0xbe, 0x97, 0x67, 0x4f, 0xfe, 0xb0, -0x92, 0x71, 0x2c, 0x19, 0xe7, 0xd1, 0x48, 0xb6, 0xc3, 0x01, 0x0f, 0xe3, 0x61, 0x87, 0xe2, 0x7e, -0x8b, 0xc9, 0x22, 0xbf, 0x96, 0x01, 0xdd, 0x04, 0x03, 0xdc, 0x76, 0x38, 0xad, 0x94, 0x53, 0x10, -0x60, 0x65, 0xa1, 0x97, 0x16, 0x46, 0x0c, 0x03, 0x71, 0x91, 0x8c, 0x44, 0x03, 0x3e, 0xbf, 0xf8, -0xcc, 0xd2, 0xc0, 0x2d, 0x47, 0x06, 0x3c, 0xd0, 0xcf, 0x40, 0x5a, 0x1d, 0xc0, 0x64, 0x70, 0xc7, -0x64, 0xcb, 0x78, 0xf3, 0xb1, 0x8c, 0x9f, 0x32, 0xc0, 0xe0, 0xc7, 0x4a, 0x46, 0xc9, 0xc0, 0x32, -0x74, 0xb0, 0x64, 0xc3, 0x7d, 0x61, 0x40, 0xc0, 0x30, 0x60, 0xbe, 0x65, 0x41, 0x70, 0x20, 0xd8, -0x30, 0x6f, 0x80, 0xd6, 0x13, 0x01, 0x25, 0xcd, 0xba, 0x01, 0x31, 0x60, 0xb7, 0x4c, 0x48, 0x1d, -0xfc, 0x07, 0x06, 0xb3, 0x70, 0x96, 0x01, 0xb1, 0x2e, 0x09, 0x80, 0xfe, 0x97, 0x90, 0x01, 0x6f, -0x18, 0x30, 0xb5, 0x5c, 0x18, 0x41, 0x44, 0xf3, 0x08, 0x03, 0x10, 0x60, 0x32, 0x60, 0xa3, 0x06, -0x04, 0x9f, 0xc0, 0x55, 0xf8, 0x60, 0x65, 0x9b, 0xc0, 0x32, 0x99, 0x20, 0x65, 0x97, 0xc0, 0x32, -0x95, 0x58, 0x64, 0x93, 0xac, 0x0c, 0x8f, 0x80, 0x07, 0x8d, 0x40, 0xca, 0x8b, 0x60, 0x65, 0x89, -0x18, 0x32, 0x87, 0x1f, 0x2b, 0x0c, 0x83, 0x90, 0x01, 0x51, 0xca, 0x80, 0x7d, 0x65, 0xc0, 0x7b, -0x36, 0x20, 0x77, 0x1f, 0x30, 0x42, 0x80, 0x19, 0x75, 0xc0, 0xca, 0x73, 0x0c, 0x78, 0x71, 0x6f, -0x01, 0x23, 0x32, 0xe0, 0x6d, 0x6b, 0x19, 0x90, 0x69, 0x32, 0x60, 0x67, 0x19, 0x30, 0x65, 0x80, -0x5b, 0x1b, 0x5c, 0x61, 0x61, 0x3f, 0x11, 0x06, 0x5d, 0x06, 0xbc, 0xd1, 0x59, 0xc0, 0x14, 0xff, -0x5c, 0x61, 0x55, 0xf8, 0x00, 0x06, 0x51, 0xc2, 0x80, 0x4d, 0x18, 0xb0, 0x4b, 0x0c, 0x58, 0x47, -0x81, 0xa9, 0x44, 0xbd, 0x49, 0x2f, 0x08, 0x10, 0xfd, 0x49, 0x6f, 0x0d, 0xd3, 0x49, 0x6f, 0x0d, -0xc5, 0x32, 0x60, 0x3d, 0x30, 0x60, 0x0e, 0x3b, 0x2d, 0x3b, 0x1c, 0x37, 0x03, 0x26, 0x7f, 0x37, -0x52, 0x2c, 0x86, 0x2d, 0x0b, 0x0d, 0xb0, 0xec, 0x29, 0x7d, 0x60, 0x19, 0x31, 0x38, 0x30, 0x2f, -0x7e, 0x25, 0x0c, 0x2d, 0x49, 0x88, 0x0d, 0x1c, 0x81, 0x01, 0x29, 0x61, 0xc0, 0x7c, 0x27, 0x56, -0x2c, 0x0d, 0xdd, 0x0c, 0x58, 0x22, 0x06, 0xa4, 0x20, 0x0c, 0x58, 0x1e, 0xe0, 0x2d, 0xdc, 0x92, -0x4b, 0x5b, 0x66, 0x19, 0x10, 0x19, 0x0c, 0x08, 0x17, 0x1e, 0xb0, 0x15, 0x20, 0x03, 0x12, 0x32, -0x60, 0x18, 0x0f, 0x06, 0x1c, 0x3c, 0x1c, 0x0d, 0x03, 0x56, 0x0b, 0x01, 0x21, 0x70, 0x81, 0x08, -0x08, 0x60, 0x19, 0x05, 0x03, 0x1c, 0xfc, 0xfb, 0x60, 0x80, 0xf6, 0x00, 0x0d, 0xf5, 0x6c, 0x04, -0x98, 0xee, 0xe9, 0xd0, 0x16, 0x06, 0x38, 0x5f, 0x2b, 0x81, 0x0d, 0x0f, 0xfe, 0x80, 0x07, 0x19, -0x02, 0x4c, 0xd7, 0xd1, 0x04, 0x08, 0xcb, 0x08, 0x10, 0xc5, 0x01, 0x3e, 0x0f, 0x07, 0x0f, 0x7d, -0xbf, 0x20, 0x80, 0xba, 0x70, 0x80, 0xb4, 0x01, 0x0a, 0xb3, 0xae, 0x06, 0xf8, 0x67, 0xe6, 0xc0, -0xa7, 0xd0, 0x00, 0xa8, 0x80, 0x0d, 0x0e, 0xa1, 0x20, 0x78, 0x80, 0x02, 0x9b, 0x02, 0x00, 0x07, -0x42, 0x13, 0xc0, 0x33, 0x8f, 0xc0, 0x00, 0x8a, 0xbb, 0x1b, 0x89, 0x00, 0x3e, 0x61, 0x49, 0x3c, -0x86, 0x5e, 0xb0, 0x7c, 0xd0, 0x27, 0x04, 0xf8, 0x26, 0xff, 0x72, 0xbc, 0xc3, 0x72, 0x0f, 0x48, -0x02, 0x65, 0x00, 0x07, 0x5f, 0xc0, 0x97, 0x59, 0x24, 0x66, 0xff, 0x0f, 0x38, 0x12, 0x9f, 0xbc, -0x18, 0xef, 0x2e, 0x06, 0x02, 0x3d, 0xd0, 0xf0, 0x46, 0xad, 0x24, 0x68, 0x08, 0x31, 0x56, 0xfc, -0x57, 0x18, 0x3e, 0x83, 0xf0, 0xe0, 0x7c, 0x18, 0x5b, 0x00, 0x0f, 0x23, 0x38, 0x64, 0xf5, 0x1e, -0x76, 0xcc, 0x98, 0x86, 0xf9, 0x30, 0xc0, 0x7c, 0x0f, 0x0c, 0x40, 0x12, 0x06, 0xb0, 0x25, 0x00, -0x2b, 0x03, 0x61, 0x7e, 0xd6, 0x18, 0x56, 0xe8, 0xbd, 0xea, 0x63, 0xd6, 0xe1, 0xc5, 0x5a, 0xdd, -0xc2, 0x17, 0x5f, 0xc9, 0x1c, 0xe5, 0xaf, 0xba, 0x07, 0x3c, 0xb3, 0x71, 0x56, 0xca, 0x1e, 0xe0, -0x7d, 0x73, 0xfc, 0x0f, 0xf1, 0xe8, 0xa9, 0xfc, 0xad, 0x53, 0xac, 0xea, 0x79, 0x2c, 0xf5, 0xbd, -0x02, 0x07, 0x7e, 0xf5, 0x62, 0xab, 0x74, 0xf7, 0x66, 0x62, 0x77, 0x67, 0x56, 0x8f, 0xaa, 0x94, -0xf5, 0x48, 0xa6, 0x59, 0x7d, 0x8d, 0x7c, 0x88, 0x5c, 0xb9, 0x07, 0x82, 0x7a, 0x25, 0x6b, 0x87, -0xac, 0x46, 0x3d, 0xfc, 0x76, 0xcc, 0x60, 0xfc, 0xcc, 0xbd, 0x32, 0xd0, 0x6b, 0x56, 0x5f, 0x69, -0xfe, 0x64, 0x68, 0x36, 0xfe, 0x07, 0xd5, 0x67, 0xf5, 0x1f, 0xce, 0xc1, 0xc2, 0x57, 0xe0, 0x0b, -0x56, 0x4d, 0x2f, 0xc1, 0x6a, 0x1e, 0x45, 0x06, 0xa3, 0xe6, 0x7f, 0xf0, 0x14, 0xac, 0x39, 0x8b, -0x49, 0xc1, 0xcb, 0xe2, 0xc5, 0xca, 0xde, 0x30, 0x1e, 0x6f, 0x7f, 0x8f, 0x45, 0x0f, 0xce, 0x7c, -0x0e, 0xf1, 0x22, 0x37, 0xca, 0x7d, 0x21, 0x0c, 0x7f, 0xa4, 0xf7, 0x0b, 0x57, 0xa5, 0x08, 0x35, -0x56, 0x41, 0x2a, 0xf8, 0x22, 0x16, 0x9d, 0x9d, 0xf4, 0x9b, 0x64, 0x3c, 0xdd, 0x48, 0xe7, 0x32, -0x6f, 0x3c, 0x08, 0x52, 0xdf, 0x53, 0x07, 0x97, 0xd9, 0x3a, 0x29, 0xd5, 0x3c, 0x61, 0xe0, 0x26, -0x61, 0xd4, 0x21, 0xba, 0xd4, 0x80, 0xbc, 0x76, 0x1a, 0xc0, 0x39, 0x75, 0xdc, 0xc3, 0xa4, 0xb0, -0x7f, 0x43, 0xaa, 0x16, 0xdd, 0x53, 0xa4, 0x7c, 0x97, 0x60, 0x3a, 0xa3, 0xf8, 0xf5, 0x76, 0xe5, -0x9a, 0x09, 0xf8, 0x2f, 0x54, 0x3b, 0x92, 0xaf, 0x0a, 0xef, 0x8c, 0x7f, 0x69, 0xb8, 0xa7, 0x84, -0x3c, 0x17, 0x46, 0x3d, 0x00, 0xe6, 0xd6, 0x91, 0x5a, 0x74, 0x18, 0x16, 0xce, 0x16, 0x0c, 0x6d, -0x0f, 0x4d, 0x36, 0x7c, 0x4f, 0x1e, 0xb3, 0x48, 0x56, 0x5f, 0x82, 0x8b, 0x7e, 0x4b, 0x87, 0xc5, -0xa9, 0x4a, 0x90, 0x9a, 0x47, 0x43, 0x60, 0xd4, 0x56, 0x30, 0xac, 0xfb, 0x1b, 0x8b, 0x00, 0x17, -0x7e, 0x2f, 0x1a, 0x9c, 0x37, 0xdf, 0x7e, 0x81, 0xa7, 0x21, 0x70, 0x61, 0x1b, 0xd6, 0x89, 0x0c, -0xb3, 0xdc, 0x12, 0x6b, 0x58, 0x46, 0xfc, 0x54, 0x4a, 0xf7, 0x91, 0x3b, 0xf9, 0x7f, 0x25, 0x9c, -0x8e, 0xfe, 0xf7, 0xc2, 0x84, 0x57, 0xef, 0x23, 0x4c, 0x7c, 0xf7, 0x7c, 0x84, 0x24, 0xef, 0x60, -0x34, 0xc6, 0xa5, 0x84, 0xef, 0xd4, 0x42, 0xa0, 0x38, 0x49, 0x28, 0x9f, 0xf7, 0x08, 0x46, 0xa9, -0x6c, 0x49, 0xff, 0x0f, 0x60, 0x84, 0x13, 0xcd, 0xef, 0x86, 0x30, 0xcf, 0x10, 0x8c, 0x8a, 0xa1, -0x92, 0xe7, 0x76, 0xe0, 0x05, 0x0c, 0xa0, 0x4d, 0x99, 0xd2, 0xd1, 0xf6, 0x73, 0x57, 0xfc, 0x37, -0x8b, 0x69, 0x26, 0x97, 0x53, 0x21, 0xd3, 0x17, 0x37, 0xa3, 0x5a, 0x6f, 0x42, 0xa6, 0x38, 0xe1, -0xe8, 0x61, 0x7f, 0x06, 0x0c, 0xe8, 0x1f, 0x7e, 0xed, 0x87, 0xc1, 0x7b, 0xc6, 0xa3, 0x47, 0xad, -0x37, 0xcd, 0xe8, 0x3c, 0xeb, 0xa3, 0x18, 0x2e, 0x2a, 0x47, 0x07, 0x38, 0x7e, 0x23, 0x12, 0x5e, -0xe0, 0x3f, 0xb7, 0x8b, 0xd1, 0x18, 0x0f, 0x66, 0x14, 0x0f, 0xbd, 0x8f, 0x0c, 0x70, 0x07, 0x08, -0x83, 0x67, 0xfe, 0xb7, 0x60, 0x30, 0xe6, 0xb1, 0x12, 0xde, 0x5c, 0xb8, 0xaf, 0x76, 0xec, 0x10, -0xc8, 0x22, 0x88, 0x01, 0x43, 0x68, 0xd9, 0x1a, 0x42, 0xd4, 0xb4, 0x12, 0xca, 0x84, 0x26, 0x9a, -0xbe, 0x21, 0x34, 0xb8, 0x0d, 0xa1, 0xb2, 0x1a, 0x09, 0xac, 0xd0, 0x12, 0xa0, 0x10, 0x9a, 0x9a, -0x94, 0x81, 0xd0, 0x8e, 0x80, 0xd0, 0xf8, 0x82, 0x03, 0xa1, 0x7c, 0x01, 0xa1, 0xff, 0x70, 0xc3, -0x62, 0x0f, 0x1f, 0x02, 0x42, 0x5e, 0x90, 0x87, 0x52, 0x37, 0x26, 0x94, 0x4c, 0xb4, 0x84, 0x46, -0x12, 0x3a, 0x40, 0x3a, 0x86, 0xd0, 0x34, 0x34, 0x84, 0x2e, 0xa1, 0x21, 0x28, 0x22, 0xcc, 0x2d, -0x0f, 0x6f, 0x20, 0x34, 0x10, 0x4b, 0x28, 0x0a, 0x2c, 0x66, 0x77, 0xfe, 0xe2, 0x0d, 0x27, 0xd8, -0xc0, 0xf2, 0xd7, 0x16, 0x6f, 0x27, 0xdd, 0x2c, 0x06, 0xd7, 0x58, 0x0c, 0xcb, 0xb0, 0x18, 0xc2, -0x8b, 0xd3, 0x47, 0xbc, 0xb8, 0xc7, 0x47, 0x07, 0xe1, 0x62, 0x2f, 0x07, 0x93, 0x98, 0x27, 0xcd, -0x06, 0x8b, 0x0e, 0xa4, 0x1c, 0x44, 0xc6, 0x1f, 0xc6, 0x66, 0x27, 0xd7, 0x66, 0x07, 0x3a, 0xe6, -0x0f, 0x47, 0x40, 0xb8, 0x5c, 0x4f, 0x4f, 0x40, 0xbe, 0x7c, 0xd9, 0xde, 0x02, 0x3e, 0x40, 0xb6, -0xa7, 0x3e, 0x9b, 0xb4, 0x40, 0xbc, 0x27, 0x07, 0x62, 0x50, 0xf6, 0xef, 0xf6, 0x17, 0x4c, 0x08, -0x1c, 0x2f, 0x83, 0x18, 0xc7, 0x2e, 0x3c, 0x38, 0x7e, 0x47, 0xb8, 0x58, 0x55, 0x05, 0x83, 0x5e, -0x4f, 0x6a, 0x72, 0x30, 0x51, 0x59, 0x4c, 0x0f, 0x3e, 0xcc, 0x62, 0x38, 0x18, 0x58, 0x33, 0x45, -0x32, 0x6e, 0x2f, 0x82, 0x21, 0x1f, 0x6b, 0x16, 0x1b, 0xdd, 0xab, 0xdc, 0x50, 0x4a, 0x48, 0x17, -0x00, 0x00, 0x0d, 0x62, 0x33, 0x0e, 0xc8, 0x81, 0x4c, 0x52, 0x03, 0x21, 0x47, 0x69, 0x26, 0x64, -0x04, 0x82, 0xa2, 0x46, 0x11, 0x03, 0x02, 0x4d, 0x18, 0x99, 0x06, 0x31, 0xcc, 0xf3, 0x03, 0x06, -0x68, 0x58, 0x44, 0x03, 0x06, 0x18, 0x69, 0x65, 0x11, 0x53, 0x84, 0xbd, 0x2f, 0x0f, 0x56, 0x80, -0x98, 0x0f, 0x09, 0x12, 0x58, 0x08, 0x59, 0x2f, 0x0d, 0x8b, 0x73, 0x61, 0xef, 0x6f, 0x4f, 0x5f, -0x66, 0x2a, 0x48, 0x0f, 0x01, 0x12, 0xe7, 0x0c, 0x59, 0x1f, 0x66, 0x81, 0x45, 0x53, 0x85, 0xb5, -0x06, 0x0f, 0x80, 0xbd, 0x2f, 0x0f, 0x48, 0xc4, 0xc6, 0x13, 0x98, 0x4b, 0x8d, 0x0f, 0x84, 0x4b, -0xdc, 0x08, 0x19, 0xf3, 0x42, 0x06, 0xd2, 0x5a, 0xac, 0xa9, 0xf5, 0x6e, 0x0c, 0x16, 0xea, 0x3e, -0xd2, 0xfe, 0xc9, 0x1e, 0x0f, 0xce, 0xff, 0x21, 0x10, 0x03, 0x32, 0x20, 0xf4, 0x6c, 0x59, 0xaf, -0x0f, 0x21, 0xbc, 0x30, 0x78, 0x4f, 0xd9, 0x61, 0x1f, 0x0f, 0x2e, 0x62, 0x23, 0xd9, 0x92, 0xc6, -0x4c, 0xd9, 0x2c, 0x3f, 0x1c, 0x30, 0x68, 0xba, 0xae, 0x1e, 0x04, 0x7c, 0xce, 0x64, 0x07, 0xe1, -0xe6, 0x7c, 0x40, 0x60, 0x64, 0x60, 0xca, 0x04, 0x8d, 0x73, 0xb3, 0x52, 0x1c, 0x1d, 0xcd, 0xda, -0x1e, 0x1f, 0x53, 0x42, 0x7c, 0x0e, 0x1a, 0xa3, 0x1b, 0x93, 0x18, 0x0e, 0xb1, 0xd4, 0x01, 0xb0, -0x10, 0xaf, 0x03, 0xe1, 0xef, 0x4f, 0x2d, 0x7b, 0x0f, 0xcf, 0x85, 0xec, 0x2f, 0xbf, 0x28, 0x1c, -0xad, 0x70, 0x49, 0x93, 0x0c, 0x21, 0xa9, 0xa3, 0x62, 0xa3, 0x3c, 0xc9, 0x36, 0xd1, 0x12, 0x23, -0x24, 0x9b, 0xd9, 0xcb, 0x3b, 0x03, 0xa7, 0x02, 0x60, 0xc0, 0x24, 0x40, 0x33, 0xa2, 0xfb, 0x82, -0xb2, 0xaa, 0xaa, 0x02, 0x82, 0xb5, 0x0c, 0x63, 0x00, 0x4c, 0x01, 0x16, 0x4e, 0x77, 0xe0, 0xa8, -0x6c, 0x62, 0x0b, 0xe8, 0xdc, 0xb2, 0x2d, 0x98, 0x3e, 0x0f, 0x9a, 0xfd, 0x66, 0xce, 0x9a, 0x3f, -0x22, 0xe8, 0x9d, 0x2e, 0xbc, 0x36, 0x2c, 0x96, 0x85, 0xcc, 0x3c, 0x36, 0x6c, 0xd8, 0x00, 0x66, -0xb7, 0x0d, 0x6c, 0xd8, 0x60, 0x10, 0x33, 0xb4, 0x50, 0x94, 0x6c, 0x64, 0x6f, 0x0f, 0x21, 0x2f, -0x60, 0x30, 0x77, 0x6c, 0xef, 0x9a, 0xa2, 0x00, 0x88, 0x58, 0x9a, 0xef, 0xa1, 0x32, 0x33, 0x9d, -0x62, 0xff, 0x5e, 0x92, 0x04, 0xc1, 0x10, 0x29, 0xa8, 0x0c, 0xe2, 0xf1, 0x33, 0xb1, 0x8a, 0xcb, -0x98, 0x12, 0x5f, 0x09, 0x73, 0x0c, 0xff, 0x64, 0x10, 0x33, 0xa4, 0x50, 0x0f, 0x62, 0xd0, 0x89, -0x7e, 0x10, 0x7f, 0x34, 0x18, 0x2c, 0x06, 0x3e, 0x04, 0x3d, 0xbe, 0x22, 0x97, 0x03, 0xf6, 0x64, -0x1d, 0xbf, 0x1f, 0x17, 0x36, 0xc6, 0x0f, 0x30, 0x12, 0x58, 0x3f, 0xc7, 0x92, 0x3f, 0x0f, 0xb0, -0x02, 0x53, 0xcc, 0x35, 0xac, 0x0f, 0x48, 0x26, 0x00, 0x19, 0x44, 0x33, 0xb3, 0x50, 0x40, 0xbd, -0x60, 0x47, 0x9f, 0xb0, 0x90, 0x7f, 0x36, 0xac, 0xb7, 0x9f, 0x6f, 0x51, 0x84, 0xb6, 0x9c, 0xb3, -0xcc, 0xcc, 0xff, 0x26, 0x6c, 0x1f, 0x30, 0xc3, 0xca, 0x2f, 0xd2, 0xb6, 0x2c, 0x1f, 0x0c, 0x01, -0x4a, 0x93, 0x90, 0x03, 0x66, 0x0c, 0x60, 0xc0, 0xc3, 0x04, 0x68, 0x7c, 0xa3, 0xcc, 0x06, 0xf0, -0x0e, 0xbe, 0x53, 0x2c, 0x8f, 0xc6, 0xdd, 0x40, 0x7f, 0xc6, 0x32, 0x24, 0xc6, 0xbc, 0x16, 0x9f, -0x6e, 0x09, 0x3f, 0x0c, 0x21, 0x10, 0xb3, 0x0b, 0x23, 0x39, 0x02, 0x7b, 0x5f, 0x00, 0x5a, 0x42, -0xbb, 0x85, 0x2c, 0x10, 0x12, 0x42, 0xe7, 0x58, 0xdf, 0xbd, 0x30, 0x62, 0x36, 0xec, 0x6f, 0x2b, -0x4a, 0x33, 0x51, 0x2a, 0xca, 0x66, 0x19, 0x00, 0xe8, 0x41, 0xff, 0x11, 0xb2, 0x1d, 0x2b, 0x9b, -0x94, 0x2a, 0x22, 0x60, 0x0a, 0x12, 0xb1, 0x90, 0x4c, 0x29, 0x58, 0x21, 0x0c, 0xa2, 0x7c, 0x33, -0xaa, 0xa0, 0x42, 0x11, 0x89, 0x09, 0x1e, 0x18, 0x70, 0x03, 0x09, 0x2e, 0x76, 0x01, 0x13, 0x01, -0xd0, 0xcb, 0x80, 0xff, 0xd9, 0x7b, 0x1b, 0x29, 0x0d, 0x32, 0x60, 0xfb, 0x30, 0x60, 0x76, 0xf9, -0x8b, 0x38, 0x76, 0x2b, 0x7b, 0x09, 0x61, 0x45, 0x62, 0xd9, 0x53, 0x5b, 0x76, 0xf6, 0x0d, 0x44, -0x60, 0x59, 0x6f, 0xe0, 0x32, 0xef, 0x3c, 0x37, 0x30, 0xed, 0x0d, 0x96, 0xbd, 0x29, 0x0d, 0x2c, -0x03, 0xe9, 0x12, 0x06, 0xe7, 0x2d, 0x03, 0xe5, 0x60, 0x19, 0xa4, 0x42, 0x35, 0xe3, 0x18, 0x60, -0xc0, 0x6e, 0xe1, 0x18, 0x70, 0xce, 0xdf, 0x01, 0x1b, 0x99, 0x1b, 0xc8, 0xc6, 0xc6, 0x0d, 0x65, -0xc0, 0xd9, 0xd9, 0xb2, 0xfb, 0x0d, 0x11, 0x6f, 0x37, 0xb3, 0x24, 0xe5, 0x42, 0xf4, 0x66, 0x37, -0x18, 0x70, 0x64, 0x20, 0x02, 0xc0, 0x1d, 0xcf, 0xe6, 0x7c, 0x80, 0x80, 0x65, 0xcd, 0x19, 0xf0, -0xcc, 0xcb, 0xcb, 0x80, 0xca, 0xe0, 0x54, 0x63, 0x9c, 0x30, 0xc7, 0xd8, 0x70, 0x58, 0x06, 0xc5, -0x09, 0x4b, 0xb1, 0x17, 0x65, 0x6f, 0x0d, 0xb5, 0x96, 0xbd, 0x29, 0xa7, 0x2c, 0x03, 0xbd, 0x12, -0x06, 0xbb, 0x2b, 0x03, 0xb9, 0x84, 0x01, 0xb7, 0xc5, 0x80, 0xb5, 0x0f, 0x98, 0x53, 0xb3, 0x84, -0x01, 0xb2, 0xe0, 0x80, 0xb1, 0xcd, 0x19, 0xaf, 0x63, 0x6e, 0xc3, 0xb6, 0xc3, 0x85, 0x1f, 0x0d, -0xcc, 0xe8, 0x36, 0x6e, 0xda, 0x3c, 0x80, 0x07, 0xab, 0x18, 0xf0, 0xaa, 0xa8, 0x03, 0x16, 0xa6, -0x06, 0x31, 0x33, 0x60, 0x55, 0xb0, 0x30, 0x9b, 0x48, 0x18, 0x99, 0x24, 0x0c, 0x97, 0x58, 0x06, -0x95, 0x10, 0x0f, 0x94, 0x42, 0x64, 0x33, 0x30, 0x03, 0x8b, 0x03, 0x1e, 0x8a, 0x89, 0x10, 0x09, -0x00, 0x64, 0x33, 0xcb, 0x80, 0x79, 0xc0, 0x80, 0x76, 0x77, 0x20, 0xdc, 0xdf, 0xa9, 0xc2, 0x33, -0x92, 0x01, 0x67, 0x18, 0xd0, 0x03, 0x65, 0x01, 0x1a, 0xe9, 0x45, 0x26, 0xf6, 0x09, 0xa9, 0x95, -0x9b, 0x3a, 0xb0, 0xc6, 0x0d, 0x30, 0xc6, 0x4a, 0xb7, 0xd7, 0x0c, 0x48, 0x59, 0x64, 0xb7, 0x0d, -0x3c, 0x66, 0x42, 0x0e, 0x00, 0x19, 0x44, 0x33, 0xb1, 0x10, 0x38, 0x3b, 0x73, 0x0e, 0x06, 0x30, -0x6f, 0x61, 0x09, 0x30, 0xd2, 0x69, 0x60, 0xd3, 0x01, 0x13, 0x78, 0xbd, 0x92, 0x42, 0x4e, 0x64, -0x97, 0x1b, 0x30, 0x29, 0x30, 0x60, 0x30, 0xc0, 0x6c, 0x7c, 0x0a, 0x20, 0x64, 0x3a, 0x01, 0x33, -0x28, 0x03, 0x96, 0x37, 0x35, 0x30, 0x64, 0xe0, 0x03, 0x1e, 0x34, 0x33, 0xc6, 0x2e, 0x7c, 0x6f, -0xc6, 0x59, 0x42, 0x0d, 0x35, 0x6b, 0x0b, 0x03, 0x92, 0x97, 0x2b, 0x13, 0x2c, 0x1a, 0xca, 0x80, -0x27, 0x0c, 0x38, 0xfe, 0x22, 0x01, 0x8b, 0xa9, 0x8c, 0x1f, 0x63, 0xe1, 0x46, 0x34, 0x73, 0x80, -0x54, 0x30, 0xc0, 0x19, 0xbc, 0x62, 0x81, 0x6d, 0x40, 0x06, 0x13, 0x60, 0xc0, 0x18, 0x0f, 0x0c, -0x58, 0x0d, 0x18, 0x44, 0x33, 0x40, 0x01, 0x26, 0x62, 0xfa, 0x28, 0x46, 0xff, 0x8c, 0x4e, 0xd6, -0x76, 0xf6, 0x30, 0x1a, 0x7c, 0xf0, 0x63, 0x6e, 0x76, 0x17, 0x07, 0x60, 0x6c, 0x93, 0x30, 0x17, -0x38, 0x93, 0x98, 0xe3, 0x05, 0xa3, 0x70, 0xd2, 0xba, 0x09, 0xef, 0x07, 0x30, 0x46, 0xc1, 0x3f, -0xc0, 0xcc, 0x0d, 0x3c, 0x1f, 0x07, 0xc7, 0x5c, 0x17, 0x07, 0xc6, 0x10, 0x62, 0x10, 0xa4, 0x28, -0xe7, 0x47, 0x27, 0xb1, 0x19, 0x41, 0x2c, 0xf8, 0x35, 0x42, 0xd5, 0xec, 0x47, 0x0b, 0x7f, 0x6e, -0x97, 0xa0, 0xa3, 0x96, 0xce, 0x46, 0xc1, 0x41, 0x47, 0x37, 0x1b, 0x57, 0x07, 0x37, 0x23, 0x7e, -0x8f, 0x70, 0xb3, 0x07, 0x1f, 0xda, 0x89, 0x2b, 0x06, 0x17, 0x29, 0x81, 0x0e, 0x1e, 0xbd, 0x27, -0x5f, 0x47, 0x8f, 0x5e, 0x5a, 0x3d, 0x23, 0x59, 0x3a, 0x6c, 0x30, 0xda, 0x0f, 0x6c, 0xb8, 0x4e, -0xd4, 0xd1, 0x48, 0x3c, 0x33, 0x7a, 0x47, 0x42, 0x30, 0x7b, 0xf7, 0x9f, 0xe6, 0x66, 0xd5, 0xd9, -0x5f, 0x30, 0x0a, 0x2a, 0x20, 0xdc, 0x07, 0x64, 0xf4, 0xfc, 0x1f, 0x0d, 0xa3, 0x19, 0xd1, 0x19, -0x12, 0x7c, 0x31, 0x9a, 0x0c, 0x0b, 0xed, 0x83, 0xfe, 0x04, 0x63, 0x6b, 0xbd, 0xfb, 0x7e, 0x33, -0x66, 0xcc, 0x0f, 0x07, 0x7a, 0x36, 0x6a, 0xdf, 0x4c, 0xa8, 0x11, 0xf4, 0xed, 0x0e, 0xc1, 0x16, -0x66, 0x33, 0x70, 0x5f, 0x44, 0x66, 0x09, 0x02, 0x83, 0x33, 0x84, 0x16, 0x97, 0x37, 0xcf, 0xda, -0x9c, 0x07, 0x60, 0x30, 0x87, 0x26, 0xb2, 0x88, 0x43, 0xb1, 0x84, 0x32, 0x33, 0x14, 0x1c, 0xbc, -0x65, 0x0e, 0x1c, 0xbf, 0xfa, 0x62, 0x42, 0x8d, 0x82, 0x0c, 0x33, 0x98, 0xd0, 0x5e, 0x62, 0x76, -0x17, 0x7f, 0x88, 0x0c, 0x33, 0xef, 0x50, 0x28, 0xcd, 0x71, 0xe8, 0x76, 0x18, 0x6c, 0x22, 0xca, -0x47, 0x9b, 0xf6, 0x7b, 0x18, 0xf7, 0x10, 0x59, 0x38, 0x63, 0x00, 0x17, 0x30, 0x08, 0xcb, 0x1f, -0x9f, 0x11, 0x28, 0xe6, 0x0b, 0x16, 0xfb, 0x06, 0x08, 0x37, 0x07, 0x85, 0x32, 0x33, 0x0d, 0x12, -0x20, 0x30, 0xc3, 0x82, 0x3f, 0x1b, 0x3d, 0x0e, 0x57, 0x37, 0xc6, 0xa2, 0xd5, 0xbc, 0xcc, 0xe1, -0x1d, 0x5f, 0x0f, 0x5f, 0x2c, 0xde, 0x07, 0x9f, 0xc5, 0x1b, 0x7c, 0xef, 0x8b, 0x09, 0xab, 0x82, -0x8f, 0xe2, 0xc0, 0x5a, 0x8b, 0x17, 0x89, 0x93, 0xd1, 0xdc, 0x07, 0x47, 0xb3, 0x98, 0x77, 0x89, -0xcd, 0x1e, 0xaf, 0x0f, 0x38, 0xa3, 0x17, 0x9f, 0x0c, 0x8b, 0x77, 0x79, 0x77, 0x6b, 0x62, 0x00, -0x7e, 0x62, 0xcb, 0x5d, 0x0a, 0xfd, 0x1f, 0x2a, 0xe1, 0x32, 0xe4, 0x3a, 0xf6, 0x2a, 0x5f, 0x86, -0x82, 0x00, 0x34, 0x49, 0x80, 0x33, 0x06, 0x16, 0x3e, 0x78, 0x98, 0xb7, 0x87, 0x18, 0xb2, 0x2e, -0x18, 0xe2, 0xb0, 0x21, 0x3c, 0x16, 0x0f, 0x2b, 0x7a, 0x19, 0xc4, 0x78, 0x33, 0x90, 0x03, 0xb5, -0x72, 0x3c, 0x19, 0x53, 0x9d, 0x4c, 0x14, 0x91, 0x82, 0x92, 0xc8, 0x82, 0x20, 0x51, 0x21, 0x83, -0x27, 0x61, 0x10, 0x33, 0x82, 0x50, 0x84, 0x0c, 0x87, 0x85, 0x41, 0x33, 0x0c, 0x82, 0x97, 0x64, -0xa3, 0x00, 0x83, 0x60, 0xa7, 0x10, 0x21, 0x08, 0x65, 0x33, 0xc8, 0x20, 0xc7, 0x19, 0x44, 0x33, -0x08, 0x42, 0x11, 0x32, 0xe7, 0x54, 0x06, 0x33, 0x2c, 0x82, 0x07, 0x41, 0x84, 0x08, 0x96, 0x33, -0xac, 0xb2, 0x17, 0x65, 0x11, 0x07, 0x8b, 0x20, 0x27, 0xd9, 0x09, 0x04, 0x08, 0x0f, 0x11, 0x9c, -0x58, 0x65, 0x27, 0xc8, 0x80, 0xa7, 0x10, 0xa3, 0x22, 0x64, 0x33, 0x2a, 0x03, 0xb7, 0x19, 0x44, -0x33, 0x62, 0x10, 0x2a, 0x09, 0x27, 0x06, 0x11, 0x33, 0x62, 0x55, 0x28, 0x09, 0x67, 0x19, 0x44, -0x33, 0x22, 0x14, 0x20, 0x09, 0xd7, 0x19, 0xc4, 0x33, 0x22, 0x14, 0x02, 0x0b, 0x47, 0x10, 0xa1, -0x46, 0x65, 0x33, 0xb6, 0x20, 0x87, 0x60, 0xb6, 0x42, 0x36, 0x31, 0x09, 0x95, 0x05, 0x97, 0xae, -0x04, 0xcf, 0x61, 0x10, 0x33, 0x20, 0x42, 0x2b, 0xb0, 0xc7, 0x60, 0x10, 0x33, 0x82, 0x08, 0x10, -0xcb, 0xd7, 0x1c, 0x65, 0x33, 0x66, 0x88, 0x94, 0xb1, 0x0c, 0x07, 0x95, 0x00, 0x97, 0x20, 0xb6, -0xce, 0xc6, 0x84, 0x10, 0xa7, 0x94, 0x41, 0x33, 0x02, 0x11, 0xa9, 0x40, 0x96, 0x01, 0xf9, 0xc2, -0x20, 0x33, 0x04, 0x0b, 0x48, 0x48, 0x43, 0xb0, 0x0c, 0xe9, 0x91, 0x44, 0x51, 0x30, 0x60, 0xe1, -0x20, 0x86, 0x7c, 0xb0, 0xc8, 0x33, 0x62, 0x19, 0xdb, 0x8b, 0x0c, 0x33, 0x48, 0x04, 0x97, 0x83, -0x48, 0x33, 0x41, 0x22, 0x12, 0x16, 0x93, 0xcb, 0x20, 0x33, 0x59, 0x04, 0xa1, 0x08, 0x16, 0xc1, -0xb2, 0x93, 0x42, 0x16, 0xaf, 0x04, 0x87, 0x13, 0x56, 0x59, 0xaf, 0x32, 0x20, 0x5f, 0x44, 0x00, -0x48, 0x18, 0x33, 0xc8, 0x80, 0x6d, 0x06, 0x91, 0x33, 0x58, 0x14, 0xc8, 0x80, 0xcf, 0x41, 0x84, -0x58, 0x91, 0x33, 0x48, 0x82, 0x07, 0x06, 0x11, 0x33, 0x48, 0x15, 0x42, 0x82, 0x69, 0x06, 0x31, -0x33, 0x48, 0x15, 0x40, 0x82, 0xcb, 0x44, 0x20, 0x11, 0x19, 0x33, 0x2c, 0x88, 0x03, 0x66, 0x2b, -0x30, 0x41, 0x4c, 0x41, 0x64, 0x11, 0x83, 0x78, 0x08, 0x10, 0x33, 0xb1, 0x02, 0x95, 0x05, 0x3b, -0x0c, 0x62, 0x33, 0x41, 0xac, 0x88, 0x64, 0x49, 0x0c, 0x32, 0x33, 0x56, 0x06, 0x13, 0x12, 0x20, -0xd3, 0x02, 0xc4, 0x71, 0xf1, 0x5a, 0xdb, 0x81, 0x00, 0x7f, 0x0c, 0x22, 0x33, 0x80, 0x00, 0x14, -0x12, 0xa1, 0x20, 0x47, 0x41, 0x04, 0x08, 0x85, 0x33, 0x41, 0x28, 0x77, 0x60, 0x10, 0x33, 0x84, -0x82, 0x7f, 0x19, 0x85, 0x98, 0xa1, 0x20, 0x87, 0x06, 0x31, 0x33, 0x0a, 0x42, 0x44, 0x10, 0x97, -0x08, 0x19, 0x33, 0x41, 0x28, 0xa7, 0x64, 0x10, 0x33, 0xa3, 0x20, 0x37, 0x41, 0x04, 0x0a, 0x82, -0x33, 0x10, 0x32, 0x3f, 0x82, 0x51, 0x37, 0x30, 0x0a, 0x47, 0xc1, 0xec, 0xd3, 0x07, 0x46, 0x46, -0x47, 0x12, 0x20, 0x87, 0x10, 0x0b, 0x88, 0x60, 0x33, 0x8c, 0x04, 0x8f, 0x90, 0x41, 0x33, 0x80, -0x58, 0x11, 0x4a, 0xc7, 0x50, 0x06, 0x33, 0x04, 0x88, 0xe7, 0x41, 0x8c, 0x58, 0x90, 0x33, 0xc8, -0x80, 0x1f, 0x19, 0x44, 0x33, 0x88, 0x11, 0x08, 0x0c, 0x57, 0x06, 0xb1, 0x33, 0x88, 0x50, 0x85, -0x0c, 0x77, 0x20, 0x86, 0x1b, 0x88, 0x32, 0x7f, 0x98, 0x45, 0x68, 0x2b, 0x83, 0x33, 0x18, 0x10, -0x97, 0x20, 0x16, 0x10, 0xc9, 0x33, 0x88, 0x18, 0x9f, 0x10, 0x32, 0x33, 0x20, 0x0e, 0xf1, 0xc1, -0x12, 0x37, 0x1c, 0x56, 0xff, 0xd3, 0x21, 0x40, 0x07, 0x0c, 0x22, 0x33, 0x92, 0xa7, 0xe9, 0x74, -0x50, 0xf0, 0xe4, 0x5a, 0xd1, 0x72, 0x91, 0x55, 0x67, 0x92, 0x14, 0x80, 0xa0, 0x15, 0xc8, 0x22, -0x15, 0xa3, 0x16, 0x7a, 0xf8, 0x4e, 0xab, 0xa0, 0x66, 0x67, 0x20, 0x28, 0x01, 0xab, 0x15, 0x9c, -0x5b, 0x66, 0x15, 0x60, 0x67, 0x7a, 0x50, 0x7c, 0xc2, 0x05, 0x1f, 0x03, 0xc2, 0x7c, 0x41, 0x58, -0x67, 0x90, 0x53, 0x1d, 0xbf, 0x3c, 0x19, 0x65, 0x05, 0x99, 0x91, 0x41, 0x33, 0x92, 0x14, 0x82, -0x82, 0x42, 0xde, 0x00, 0x05, 0x2b, 0x48, 0x59, 0x67, 0x2d, 0x21, 0x53, 0x25, 0x00, 0x6a, 0x0b, -0x6a, 0x8b, 0x54, 0x21, 0xb2, 0x60, 0x34, 0x07, 0x5b, 0xf6, 0x10, 0x08, 0x28, 0x0f, 0x49, 0xd0, -0xa6, 0xab, 0x60, 0x67, 0x54, 0x2b, 0x20, 0x61, 0xad, 0x2a, 0xab, 0x67, 0x45, 0x70, 0x66, 0x00, -0x4b, 0x24, 0x0f, 0xef, 0xc0, 0x2a, 0x82, 0x03, 0x8b, 0x0a, 0x23, 0xdf, 0xde, 0xff, 0x3c, 0x42, -0x99, 0xa5, 0xa1, 0xa5, 0x99, 0x42, 0x0e, 0xb2, 0x0a, 0x67, 0x05, 0x90, 0x28, 0x65, 0x83, 0x32, -0x03, 0x6d, 0xac, 0x82, 0x67, 0x00, 0x2a, 0x01, 0x10, 0xb0, 0xec, 0x09, 0x00, 0x95, 0x55, 0x67, -0x46, 0x00, 0x0a, 0x03, 0xf9, 0x10, 0x0c, 0x70, 0x92, 0xef, 0x07, 0x18, 0xf4, 0xfe, 0x84, 0x01, -0xf2, 0x60, 0xc0, 0x00, 0xef, 0x0c, 0x18, 0xed, 0x55, 0xb0, 0x80, 0x91, 0x67, 0x05, 0xcb, 0xe9, -0x17, 0x59, 0x67, 0x66, 0x29, 0x82, 0x00, 0xc7, 0x40, 0x0a, 0x16, 0x60, 0xdb, 0xa4, 0x08, 0x9d, -0x50, 0xaf, 0x38, 0x44, 0xb1, 0x5f, 0xcd, 0x44, 0x38, 0x2a, 0xac, 0x82, 0xb8, 0x67, 0x19, 0xb0, -0xd3, 0x0f, 0x08, 0xd1, 0x2a, 0x30, 0x00, 0xc2, 0x67, 0x01, 0x2b, 0x82, 0x81, 0x17, 0x02, 0xac, -0x67, 0x94, 0xa0, 0x52, 0x61, 0xe0, 0xb3, 0x0a, 0x67, 0x20, 0x05, 0xc3, 0x01, 0xa3, 0xd2, 0x0e, -0x51, 0x93, 0x14, 0x8c, 0xbf, 0xa3, 0x64, 0xc1, 0xbb, 0x15, 0x0c, 0xa3, 0x60, 0x67, 0xb0, 0x15, -0x0c, 0x2a, 0x64, 0x67, 0x14, 0x1c, 0x82, 0x6c, 0x09, 0xef, 0x77, 0x15, 0xa4, 0x0a, 0x66, 0x67, -0x15, 0x04, 0xd7, 0x82, 0x10, 0x93, 0x0c, 0x0a, 0x0f, 0x04, 0x35, 0xd0, 0x9b, 0x7b, 0x07, 0x02, -0x13, 0xc9, 0x28, 0xac, 0x67, 0x74, 0xa8, 0x08, 0xd3, 0x2a, 0x98, 0x18, 0x87, 0xca, 0x67, 0x0d, -0x0a, 0xb7, 0xff, 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x04, 0x69, 0x6c, 0xff, -0xf6, 0x65, 0x20, 0x68, 0x61, 0x0d, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x63, 0x72, 0xb7, 0xfd, 0x65, -0x61, 0x74, 0x65, 0x64, 0x2f, 0x02, 0x69, 0x06, 0xfb, 0x37, 0x13, 0x79, 0x20, 0x43, 0x50, 0x49, -0x61, 0x64, 0x09, 0xdf, 0x7e, 0x56, 0x31, 0x2e, 0x32, 0x30, 0x37, 0x43, 0x6f, 0x70, 0x79, 0xff, -0xf2, 0x72, 0x69, 0x67, 0x68, 0x28, 0x43, 0x29, 0x20, 0x31, 0x39, 0x39, 0x7f, 0xdd, 0x33, 0x2d, -0x04, 0x36, 0x28, 0x6b, 0x6f, 0x73, 0xfd, 0xb7, 0x74, 0x54, 0x40, 0x61, 0x63, 0x6d, 0x2e, 0x6f, -0x72, 0x67, 0x76, 0xb7, 0x1f, 0x4b, 0x0f, 0x61, 0x20, 0x4b, 0x15, 0x0f, 0x36, 0x29, 0x71, 0x70, -0x72, 0x6f, 0x77, 0xff, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x79, 0x6f, 0x20, 0x75, 0x73, -0xad, 0x75, 0x63, 0x66, 0x72, 0x09, 0xd6, 0xda, 0x6f, 0x66, 0x7a, 0x84, 0x36, 0xbf, 0xb5, 0x09, -0x7e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0xad, 0x6d, 0x11, 0x77, 0x8d, 0x69, 0x00, 0xf8, 0x73, 0x6b, -0x2e, 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xff, 0xa4, 0xe8, 0x3a, 0x00, 0x72, 0xfa, -0x41, 0xe8, 0x2f, 0x00, 0xe3, 0x3b, 0x73, 0xf9, 0x83, 0xe9, 0x03, 0x72, 0x06, 0x88, 0xcc, 0xac, -0xf7, 0xd0, 0x95, 0x31, 0xc9, 0xe8, 0x1b, 0x00, 0x11, 0xc9, 0x75, 0x08, 0x41, 0xe8, 0x13, 0x00, -0x73, 0xfb, 0x41, 0x41, 0x81, 0xfd, 0x00, 0xf3, 0x83, 0xd1, 0x01, 0x8d, 0x03, 0x96, 0xf3, 0xa4, -0x96, 0xeb, 0xc8, 0xe8, 0x02, 0x00, 0x11, 0xc9, 0x01, 0xdb, 0x75, 0x04, 0xad, 0x11, 0xc0, 0x93, -0xc3, 0x5e, 0xb9, 0x01, 0x00, 0xac, 0x2c, 0xe8, 0x3c, 0x01, 0x77, 0xf9, 0x8b, 0x1c, 0x86, 0xdf, -0x29, 0xf3, 0x89, 0x1c, 0xad, 0xe2, 0xee, 0xc3 }; diff --git a/src/dos/dos_devices.cpp b/src/dos/dos_devices.cpp index 0edb426..ae2630b 100644 --- a/src/dos/dos_devices.cpp +++ b/src/dos/dos_devices.cpp @@ -1,192 +1,77 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos_devices.cpp,v 1.21 2008/12/11 20:45:43 qbix79 Exp $ */ - -#include -#include "dosbox.h" -#include "callback.h" -#include "regs.h" -#include "mem.h" -#include "bios.h" -#include "dos_inc.h" -#include "support.h" -#include "drives.h" //Wildcmp -/* Include all the devices */ - -#include "dev_con.h" - - -DOS_Device * Devices[DOS_DEVICES]; - -class device_NUL : public DOS_Device { -public: - device_NUL() { SetName("NUL"); }; - virtual bool Read(Bit8u * data,Bit16u * size) { - for(Bitu i = 0; i < *size;i++) - data[i]=0; - LOG(LOG_IOCTL,LOG_NORMAL)("%s:READ",GetName()); - return true; - } - virtual bool Write(Bit8u * data,Bit16u * size) { - LOG(LOG_IOCTL,LOG_NORMAL)("%s:WRITE",GetName()); - return true; - } - virtual bool Seek(Bit32u * pos,Bit32u type) { - LOG(LOG_IOCTL,LOG_NORMAL)("%s:SEEK",GetName()); - return true; - } - virtual bool Close() { return true; } - virtual Bit16u GetInformation(void) { return 0x8084; } - virtual bool ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode){return false;} - virtual bool WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode){return false;} -}; - -class device_LPT1 : public device_NUL { -public: - device_LPT1() { SetName("LPT1");} - Bit16u GetInformation(void) { return 0x80A0; } -}; - -bool DOS_Device::Read(Bit8u * data,Bit16u * size) { - return Devices[devnum]->Read(data,size); -} - -bool DOS_Device::Write(Bit8u * data,Bit16u * size) { - return Devices[devnum]->Write(data,size); -} - -bool DOS_Device::Seek(Bit32u * pos,Bit32u type) { - return Devices[devnum]->Seek(pos,type); -} - -bool DOS_Device::Close() { - return Devices[devnum]->Close(); -} - -Bit16u DOS_Device::GetInformation(void) { - return Devices[devnum]->GetInformation(); -} - -bool DOS_Device::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { - return Devices[devnum]->ReadFromControlChannel(bufptr,size,retcode); -} - -bool DOS_Device::WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { - return Devices[devnum]->WriteToControlChannel(bufptr,size,retcode); -} - -DOS_File::DOS_File(const DOS_File& orig) { - flags=orig.flags; - time=orig.time; - date=orig.date; - attr=orig.attr; - refCtr=orig.refCtr; - open=orig.open; - name=0; - if(orig.name) { - name=new char [strlen(orig.name) + 1];strcpy(name,orig.name); - } -} - -DOS_File & DOS_File::operator= (const DOS_File & orig) { - flags=orig.flags; - time=orig.time; - date=orig.date; - attr=orig.attr; - refCtr=orig.refCtr; - open=orig.open; - if(name) { - delete [] name; name=0; - } - if(orig.name) { - name=new char [strlen(orig.name) + 1];strcpy(name,orig.name); - } - return *this; -} - -Bit8u DOS_FindDevice(char const * name) { - /* should only check for the names before the dot and spacepadded */ - char fullname[DOS_PATHLENGTH];Bit8u drive; -// if(!name || !(*name)) return DOS_DEVICES; //important, but makename does it - if (!DOS_MakeName(name,fullname,&drive)) return DOS_DEVICES; - - char* name_part = strrchr(fullname,'\\'); - if(name_part) { - *name_part++ = 0; - //Check validity of leading directory. - if(!Drives[drive]->TestDir(fullname)) return DOS_DEVICES; - } else name_part = fullname; - - char* dot = strrchr(name_part,'.'); - if(dot) *dot = 0; //no ext checking - - static char com[5] = { 'C','O','M','1',0 }; - static char lpt[5] = { 'L','P','T','1',0 }; - // AUX is alias for COM1 and PRN for LPT1 - // A bit of a hack. (but less then before). - // no need for casecmp as makename returns uppercase - if (strcmp(name_part, "AUX") == 0) name_part = com; - if (strcmp(name_part, "PRN") == 0) name_part = lpt; - - /* loop through devices */ - for(Bit8u index = 0;index < DOS_DEVICES;index++) { - if (Devices[index]) { - if (WildFileCmp(name_part,Devices[index]->name)) return index; - } - } - return DOS_DEVICES; -} - - -void DOS_AddDevice(DOS_Device * adddev) { -//Caller creates the device. We store a pointer to it -//TODO Give the Device a real handler in low memory that responds to calls - for(Bitu i = 0; i < DOS_DEVICES;i++) { - if(!Devices[i]){ - Devices[i] = adddev; - Devices[i]->SetDeviceNumber(i); - return; - } - } - E_Exit("DOS:Too many devices added"); -} - -void DOS_DelDevice(DOS_Device * dev) { -// We will destroy the device if we find it in our list. -// TODO:The file table is not checked to see the device is opened somewhere! - for (Bitu i = 0; i name,dev->name)){ - delete Devices[i]; - Devices[i] = 0; - return; - } - } -} - -void DOS_SetupDevices(void) { - DOS_Device * newdev; - newdev=new device_CON(); - DOS_AddDevice(newdev); - DOS_Device * newdev2; - newdev2=new device_NUL(); - DOS_AddDevice(newdev2); - DOS_Device * newdev3; - newdev3=new device_LPT1(); - DOS_AddDevice(newdev3); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "dosbox.h" +#include "callback.h" +#include "cpu.h" +#include "mem.h" +#include "bios.h" +#include "dos_inc.h" +#include "support.h" + +#define MAX_DEVICES 10 +/* Include all the devices */ + +#include "dev_con.h" + + +static DOS_Device * devices[MAX_DEVICES]; +static Bit32u device_count; + +Bit8u DOS_FindDevice(char * name) { + /* loop through devices */ + Bit8u index=0; + while (indexname)==0) return index; + } + index++; + } + return 255; +} + + +void DOS_AddDevice(DOS_Device * adddev) { +//TODO Give the Device a real handler in low memory that responds to calls + if (device_countfhandle=handle; + } else { + E_Exit("DOS:Too many devices added"); + } +} + +void DOS_SetupDevices(void) { + device_count=0; + DOS_Device * newdev; + newdev=new device_CON(); + DOS_AddDevice(newdev); +} + diff --git a/src/dos/dos_execute.cpp b/src/dos/dos_execute.cpp index c186b4d..fd3fb54 100644 --- a/src/dos/dos_execute.cpp +++ b/src/dos/dos_execute.cpp @@ -1,502 +1,439 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos_execute.cpp,v 1.66 2009/01/14 22:16:00 qbix79 Exp $ */ - -#include -#include -#include "dosbox.h" -#include "mem.h" -#include "dos_inc.h" -#include "regs.h" -#include "callback.h" -#include "debug.h" -#include "cpu.h" - -const char * RunningProgram="DOSBOX"; - -#ifdef _MSC_VER -#pragma pack(1) -#endif -struct EXE_Header { - Bit16u signature; /* EXE Signature MZ or ZM */ - Bit16u extrabytes; /* Bytes on the last page */ - Bit16u pages; /* Pages in file */ - Bit16u relocations; /* Relocations in file */ - Bit16u headersize; /* Paragraphs in header */ - Bit16u minmemory; /* Minimum amount of memory */ - Bit16u maxmemory; /* Maximum amount of memory */ - Bit16u initSS; - Bit16u initSP; - Bit16u checksum; - Bit16u initIP; - Bit16u initCS; - Bit16u reloctable; - Bit16u overlay; -} GCC_ATTRIBUTE(packed); -#ifdef _MSC_VER -#pragma pack() -#endif - -#define MAGIC1 0x5a4d -#define MAGIC2 0x4d5a -#define MAXENV 32768u -#define ENV_KEEPFREE 83 /* keep unallocated by environment variables */ - /* The '65' added to nEnvSize does not cover the additional stuff: - + 2 bytes: number of strings - + 80 bytes: maximum absolute filename - + 1 byte: '\0' - -- 1999/04/21 ska */ -#define LOADNGO 0 -#define LOAD 1 -#define OVERLAY 3 - - - -static void SaveRegisters(void) { - reg_sp-=18; - mem_writew(SegPhys(ss)+reg_sp+ 0,reg_ax); - mem_writew(SegPhys(ss)+reg_sp+ 2,reg_cx); - mem_writew(SegPhys(ss)+reg_sp+ 4,reg_dx); - mem_writew(SegPhys(ss)+reg_sp+ 6,reg_bx); - mem_writew(SegPhys(ss)+reg_sp+ 8,reg_si); - mem_writew(SegPhys(ss)+reg_sp+10,reg_di); - mem_writew(SegPhys(ss)+reg_sp+12,reg_bp); - mem_writew(SegPhys(ss)+reg_sp+14,SegValue(ds)); - mem_writew(SegPhys(ss)+reg_sp+16,SegValue(es)); -} - -static void RestoreRegisters(void) { - reg_ax=mem_readw(SegPhys(ss)+reg_sp+ 0); - reg_cx=mem_readw(SegPhys(ss)+reg_sp+ 2); - reg_dx=mem_readw(SegPhys(ss)+reg_sp+ 4); - reg_bx=mem_readw(SegPhys(ss)+reg_sp+ 6); - reg_si=mem_readw(SegPhys(ss)+reg_sp+ 8); - reg_di=mem_readw(SegPhys(ss)+reg_sp+10); - reg_bp=mem_readw(SegPhys(ss)+reg_sp+12); - SegSet16(ds,mem_readw(SegPhys(ss)+reg_sp+14)); - SegSet16(es,mem_readw(SegPhys(ss)+reg_sp+16)); - reg_sp+=18; -} - -extern void GFX_SetTitle(Bit32s cycles,Bits frameskip,bool paused); -void DOS_UpdatePSPName(void) { - DOS_MCB mcb(dos.psp()-1); - static char name[9]; - mcb.GetFileName(name); - if (!strlen(name)) strcpy(name,"DOSBOX"); - RunningProgram=name; - GFX_SetTitle(-1,-1,false); -} - -bool DOS_Terminate(bool tsr,Bit8u exitcode) { - - dos.return_code=exitcode; - dos.return_mode=RETURN_EXIT; - - Bit16u mempsp = dos.psp(); - - DOS_PSP curpsp(mempsp); - if (mempsp==curpsp.GetParent()) return true; - /* Free Files owned by process */ - if (!tsr) curpsp.CloseFiles(); - - /* Get the termination address */ - RealPt old22 = curpsp.GetInt22(); - /* Restore vector 22,23,24 */ - curpsp.RestoreVectors(); - /* Set the parent PSP */ - dos.psp(curpsp.GetParent()); - DOS_PSP parentpsp(curpsp.GetParent()); - - /* Restore the SS:SP to the previous one */ - SegSet16(ss,RealSeg(parentpsp.GetStack())); - reg_sp = RealOff(parentpsp.GetStack()); - /* Restore the old CS:IP from int 22h */ - RestoreRegisters(); - /* Set the CS:IP stored in int 0x22 back on the stack */ - mem_writew(SegPhys(ss)+reg_sp+0,RealOff(old22)); - mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(old22)); - /* set IOPL=3 (Strike Commander), nested task set, - interrupts enabled, test flags cleared */ - mem_writew(SegPhys(ss)+reg_sp+4,0x7202); - // Free memory owned by process - if (!tsr) DOS_FreeProcessMemory(mempsp); - DOS_UpdatePSPName(); - - if ((!(CPU_AutoDetermineMode>>CPU_AUTODETERMINE_SHIFT)) || (cpu.pmode)) return true; - - CPU_AutoDetermineMode>>=CPU_AUTODETERMINE_SHIFT; - if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CYCLES) { - CPU_CycleAutoAdjust=false; - CPU_CycleLeft=0; - CPU_Cycles=0; - CPU_CycleMax=CPU_OldCycleMax; - GFX_SetTitle(CPU_OldCycleMax,-1,false); - } else { - GFX_SetTitle(-1,-1,false); - } -#if (C_DYNAMIC_X86) || (C_DYNREC) - if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CORE) { - cpudecoder=&CPU_Core_Normal_Run; - CPU_CycleLeft=0; - CPU_Cycles=0; - } -#endif - - return true; -} - -static bool MakeEnv(char * name,Bit16u * segment) { - /* If segment to copy environment is 0 copy the caller's environment */ - DOS_PSP psp(dos.psp()); - PhysPt envread,envwrite; - Bit16u envsize=1; - bool parentenv=true; - - if (*segment==0) { - if (!psp.GetEnvironment()) parentenv=false; //environment seg=0 - envread=PhysMake(psp.GetEnvironment(),0); - } else { - if (!*segment) parentenv=false; //environment seg=0 - envread=PhysMake(*segment,0); - } - - if (parentenv) { - for (envsize=0; ;envsize++) { - if (envsize>=MAXENV - ENV_KEEPFREE) { - DOS_SetError(DOSERR_ENVIRONMENT_INVALID); - return false; - } - if (mem_readw(envread+envsize)==0) break; - } - envsize += 2; /* account for trailing \0\0 */ - } - Bit16u size=long2para(envsize+ENV_KEEPFREE); - if (!DOS_AllocateMemory(segment,&size)) return false; - envwrite=PhysMake(*segment,0); - if (parentenv) { - MEM_BlockCopy(envwrite,envread,envsize); -// mem_memcpy(envwrite,envread,envsize); - envwrite+=envsize; - } else { - mem_writeb(envwrite++,0); - } - mem_writew(envwrite,1); - envwrite+=2; - char namebuf[DOS_PATHLENGTH]; - if (DOS_Canonicalize(name,namebuf)) { - MEM_BlockWrite(envwrite,namebuf,(Bitu)(strlen(namebuf)+1)); - return true; - } else return false; -} - -bool DOS_NewPSP(Bit16u segment, Bit16u size) { - DOS_PSP psp(segment); - psp.MakeNew(size); - Bit16u parent_psp_seg=psp.GetParent(); - DOS_PSP psp_parent(parent_psp_seg); - psp.CopyFileTable(&psp_parent,false); - // copy command line as well (Kings Quest AGI -cga switch) - psp.SetCommandTail(RealMake(parent_psp_seg,0x80)); - return true; -} - -bool DOS_ChildPSP(Bit16u segment, Bit16u size) { - DOS_PSP psp(segment); - psp.MakeNew(size); - DOS_PSP psp_parent(psp.GetParent()); - psp.CopyFileTable(&psp_parent,true); - psp.SetEnvironment(psp_parent.GetEnvironment()); - psp.SetSize(size); - return true; -} - -static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { - /* Fix the PSP for psp and environment MCB's */ - DOS_MCB mcb((Bit16u)(pspseg-1)); - mcb.SetPSPSeg(pspseg); - mcb.SetPt((Bit16u)(envseg-1)); - mcb.SetPSPSeg(pspseg); - - DOS_PSP psp(pspseg); - psp.MakeNew(memsize); - psp.SetEnvironment(envseg); - - /* Copy file handles */ - DOS_PSP oldpsp(dos.psp()); - psp.CopyFileTable(&oldpsp,true); - -} - -static void SetupCMDLine(Bit16u pspseg,DOS_ParamBlock & block) { - DOS_PSP psp(pspseg); - // if cmdtail==0 it will inited as empty in SetCommandTail - psp.SetCommandTail(block.exec.cmdtail); -} - -bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { - EXE_Header head;Bitu i; - Bit16u fhandle;Bit16u len;Bit32u pos; - Bit16u pspseg,envseg,loadseg,memsize,readsize; - PhysPt loadaddress;RealPt relocpt; - Bitu headersize=0,imagesize=0; - DOS_ParamBlock block(block_pt); - - block.LoadData(); - //Remove the loadhigh flag for the moment! - if(flags&0x80) LOG(LOG_EXEC,LOG_ERROR)("using loadhigh flag!!!!!. dropping it"); - flags &= 0x7f; - if (flags!=LOADNGO && flags!=OVERLAY && flags!=LOAD) { - DOS_SetError(DOSERR_FORMAT_INVALID); - return false; -// E_Exit("DOS:Not supported execute mode %d for file %s",flags,name); - } - /* Check for EXE or COM File */ - bool iscom=false; - if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) { - DOS_SetError(DOSERR_FILE_NOT_FOUND); - return false; - } - len=sizeof(EXE_Header); - if (!DOS_ReadFile(fhandle,(Bit8u *)&head,&len)) { - DOS_CloseFile(fhandle); - return false; - } - if (len 1 MB"); - head.pages&=0x07ff; - headersize = head.headersize*16; - imagesize = head.pages*512-headersize; - if (imagesize+headersize<512) imagesize = 512-headersize; - } - } - Bit8u * loadbuf=(Bit8u *)new Bit8u[0x10000]; - if (flags!=OVERLAY) { - /* Create an environment block */ - envseg=block.exec.envseg; - if (!MakeEnv(name,&envseg)) { - DOS_CloseFile(fhandle); - return false; - } - /* Get Memory */ - Bit16u minsize,maxsize;Bit16u maxfree=0xffff;DOS_AllocateMemory(&pspseg,&maxfree); - if (iscom) { - minsize=0x1000;maxsize=0xffff; - if (machine==MCH_PCJR) { - /* try to load file into memory below 96k */ - pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET); - Bit16u dataread=0x1800; - DOS_ReadFile(fhandle,loadbuf,&dataread); - if (dataread<0x1800) maxsize=dataread; - if (minsize>maxsize) minsize=maxsize; - } - } else { /* Exe size calculated from header */ - minsize=long2para(imagesize+(head.minmemory<<4)+256); - if (head.maxmemory!=0) maxsize=long2para(imagesize+(head.maxmemory<<4)+256); - else maxsize=0xffff; - } - if (maxfree>4)+0x20; - } - if (maxfree0x7FFF) { - readsize=0x8000;DOS_ReadFile(fhandle,loadbuf,&readsize); - MEM_BlockWrite(loadaddress,loadbuf,readsize); -// if (readsize!=0x8000) LOG(LOG_EXEC,LOG_NORMAL)("Illegal header"); - loadaddress+=0x8000;imagesize-=0x8000; - } - if (imagesize>0) { - readsize=(Bit16u)imagesize;DOS_ReadFile(fhandle,loadbuf,&readsize); - MEM_BlockWrite(loadaddress,loadbuf,readsize); -// if (readsize!=imagesize) LOG(LOG_EXEC,LOG_NORMAL)("Illegal header"); - } - /* Relocate the exe image */ - Bit16u relocate; - if (flags==OVERLAY) relocate=block.overlay.relocation; - else relocate=loadseg; - pos=head.reloctable;DOS_SeekFile(fhandle,&pos,0); - for (i=0;i +#include "dosbox.h" +#include "mem.h" +#include "dos_inc.h" +#include "cpu.h" +#pragma pack(1) + + +struct EXE_Header { + + Bit16u signature; /* EXE Signature MZ or ZM */ + Bit16u extrabytes; /* Bytes on the last page */ + Bit16u pages; /* Pages in file */ + Bit16u relocations; /* Relocations in file */ + Bit16u headersize; /* Paragraphs in header */ + Bit16u minmemory; /* Minimum amount of memory */ + Bit16u maxmemory; /* Maximum amount of memory */ + Bit16u initSS; + Bit16u initSP; + Bit16u checksum; + Bit16u initIP; + Bit16u initCS; + Bit16u reloctable; + Bit16u overlay; +}; +#pragma pack() + +#define MAGIC1 0x5a4d +#define MAGIC2 0x4d5a +#define MAXENV 32768u +#define ENV_KEEPFREE 83 /* keep unallocated by environment variables */ + /* The '65' added to nEnvSize does not cover the additional stuff: + + 2 bytes: number of strings + + 80 bytes: maximum absolute filename + + 1 byte: '\0' + -- 1999/04/21 ska */ +#define LOADNGO 0 +#define LOAD 1 +#define OVERLAY 3 + + +bool DOS_Terminate(bool tsr) { + PSP * psp=(PSP *)real_off(dos.psp,0); + if (!tsr) { + /* Free Files owned by process */ + for (Bit16u i=0;imax_files;i++) { + DOS_CloseFile(i); + } + DOS_FreeProcessMemory(dos.psp); + }; + dos.psp=psp->psp_parent; + PSP * oldpsp=(PSP *)real_off(dos.psp,0); + /* Restore the DTA */ + dos.dta=psp->dta; + /* Restore the old CS:IP from int 22h */ + RealPt old22; + old22=RealGetVec(0x22); + SetSegment_16(cs,RealSeg(old22)); + reg_ip=RealOff(old22); + /* Restore the SS:SP to the previous one */ + SetSegment_16(ss,RealSeg(oldpsp->stack)); + reg_sp=RealOff(oldpsp->stack); + /* Restore interrupt 22,23,24 */ + RealSetVec(0x22,psp->int_22); + RealSetVec(0x23,psp->int_23); + RealSetVec(0x24,psp->int_24); + + return true; +} + + + +static bool MakeEnv(char * name,Bit16u * segment) { + + /* If segment to copy environment is 0 copy the caller's environment */ + PSP * psp=(PSP *)real_off(dos.psp,0); + Bit8u * envread,*envwrite; + Bit16u envsize=1; + bool parentenv=true; + + if (*segment==0) { + if (!psp->environment) parentenv=false; //environment seg=0 + envread=real_off(psp->environment,0); + } else { + if (!*segment) parentenv=false; //environment seg=0 + envread=real_off(*segment,0); + } + + //TODO Make a good DOS first psp + if (parentenv) { + for (envsize=0; ;envsize++) { + if (envsize>=MAXENV - ENV_KEEPFREE) { + DOS_SetError(DOSERR_ENVIRONMENT_INVALID); + return false; + } + if (readw(envread+envsize)==0) break; + } + envsize += 2; /* account for trailing \0\0 */ + } + Bit16u size=long2para(envsize+ENV_KEEPFREE); + if (!DOS_AllocateMemory(segment,&size)) return false; + envwrite=real_off(*segment,0); + if (parentenv) { + bmemcpy(envwrite,envread,envsize); + envwrite+=envsize; + } else { + *envwrite++=0; + } + *((Bit16u *) envwrite)=1; + envwrite+=2; + //TODO put the filename here + return DOS_Canonicalize(name,envwrite); +}; + +bool DOS_NewPSP(Bit16u pspseg) { + PSP * newpsp=(PSP *)real_off(pspseg,0); + PSP * prevpsp=(PSP *)real_off(dos.psp,0); + + memset((void *)newpsp,0,sizeof(PSP)); + newpsp->exit[0]=0xcd;newpsp->exit[1]=0x20; + newpsp->service[0]=0xcd;newpsp->service[0]=0x21;newpsp->service[0]=0xcb; + + newpsp->mem_size=prevpsp->mem_size; + newpsp->environment=0; + + newpsp->int_22=RealGetVec(0x22); + newpsp->int_23=RealGetVec(0x23); + newpsp->int_24=RealGetVec(0x24); + + newpsp->psp_parent=dos.psp; + newpsp->prev_psp=0xFFFFFFFF; + + Bit32u i; + Bit8u * prevfile=Real2Host(prevpsp->file_table); + for (i=0;i<20;i++) newpsp->files[i]=prevfile[i]; + + newpsp->max_files=20; + newpsp->file_table=RealMake(pspseg,offsetof(PSP,files)); + /* Save the old DTA in this psp */ + newpsp->dta=dos.dta; + /* Setup the DTA */ + dos.dta=RealMake(pspseg,0x80); + return true; +}; + +static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { + + PSP * psp=(PSP *)real_off(pspseg,0); + /* Fix the PSP index of this MCB */ + MCB * pspmcb=(MCB *)real_off(pspseg-1,0); + pspmcb->psp_segment=pspseg; + MCB * envmcb=(MCB *)real_off(envseg-1,0); + envmcb->psp_segment=pspseg; + + memset((void *)psp,0,sizeof(PSP)); + Bit32u i; + + psp->exit[0]=0xcd;psp->exit[1]=0x20; + psp->mem_size=memsize+pspseg; + psp->environment=envseg; + + psp->int_22=RealGetVec(0x22); + psp->int_23=RealGetVec(0x23); + psp->int_24=RealGetVec(0x24); + + psp->service[0]=0xcd;psp->service[0]=0x21;psp->service[0]=0xcb; + + psp->psp_parent=dos.psp; + psp->prev_psp=RealMake(dos.psp,0); + + for (i=0;i<20;i++) psp->files[i]=0xff; + psp->files[STDIN]=DOS_FindDevice("CON"); + psp->files[STDOUT]=DOS_FindDevice("CON"); + psp->files[STDERR]=DOS_FindDevice("CON"); + psp->files[STDAUX]=DOS_FindDevice("CON"); + psp->files[STDNUL]=DOS_FindDevice("CON"); + psp->files[STDPRN]=DOS_FindDevice("CON"); + + psp->max_files=20; + psp->file_table=RealMake(pspseg,offsetof(PSP,files)); + /* Save old DTA in psp */ + psp->dta=dos.dta; + + /* Setup the DTA */ + dos.dta=RealMake(pspseg,0x80); +} + +static void SetupCMDLine(Bit16u pspseg,ParamBlock * block) { + PSP * psp=(PSP *)real_off(pspseg,0); + + if (block->exec.cmdtail) { + memcpy((void *)&psp->cmdtail,(void *)Real2Host(block->exec.cmdtail),128); + } else { + char temp[]=""; + psp->cmdtail.count=strlen(temp); + strcpy((char *)&psp->cmdtail.buffer,temp); + psp->cmdtail.buffer[0]=0x0d; + + } +} + + + + +static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) { + Bit16u fhandle; + Bit16u size;Bit16u readsize; + Bit16u envseg,comseg; + Bit32u pos; + + PSP * callpsp=(PSP *)real_off(dos.psp,0); + + if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false; + if (flag!=OVERLAY) { + /* Allocate a new Environment */ + envseg=block->exec.envseg; + if (!MakeEnv(name,&envseg)) return false; + /* Allocate max memory for COM file and PSP */ + size=0xffff; + DOS_AllocateMemory(&comseg,&size); + //TODO Errors check for minimun of 64kb in pages + if (Bit32u(size <<4)<0x1000) { + DOS_SetError(DOSERR_INSUFFICIENT_MEMORY); + DOS_FreeMemory(envseg); + return false; + } + DOS_AllocateMemory(&comseg,&size); + } else { + comseg=block->overlay.loadseg; + } + /* Memory allocated now load the program */ + /* Now copy the File into allocated memory */ + pos=0; + DOS_SeekFile(fhandle,&pos,0); + readsize=0xffff-256; + if (flag==OVERLAY) { + DOS_ReadFile(fhandle,real_host(comseg,0),&readsize); + } else { + DOS_ReadFile(fhandle,real_host(comseg,256),&readsize); + } + DOS_CloseFile(fhandle); + if (flag==OVERLAY) /* Everything what should be done for Overlays */ + return true; + SetupPSP(comseg,size,envseg); + SetupCMDLine(comseg,block); + /* Setup termination Address */ + RealSetVec(0x22,RealMake(Segs[cs].value,reg_ip)); + /* Everything setup somewhat setup CS:IP and SS:SP */ + /* First save the SS:SP of program that called execute */ + callpsp->stack=RealMake(Segs[ss].value,reg_sp); + /* Clear out first Stack entry to point to int 20h at psp:0 */ + real_writew(comseg,0xfffe,0); + dos.psp=comseg; + switch (flag) { + case LOADNGO: + SetSegment_16(cs,comseg); + SetSegment_16(ss,comseg); + SetSegment_16(ds,comseg); + SetSegment_16(es,comseg); + flags.intf=true; + reg_ip=0x100; + reg_sp=0xFFFE; + reg_ax=0; + reg_bx=reg_cx=reg_dx=reg_si=reg_di=reg_bp=0; + return true; + case LOAD: + block->exec.initsssp=RealMake(comseg,0xfffe); + block->exec.initcsip=RealMake(comseg,0x100); + return true; + } + return false; + +} + + +static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) { + + EXE_Header header; + Bit16u fhandle;Bit32u i; + Bit16u size,minsize,maxsize,freesize;Bit16u readsize; + Bit16u envseg,pspseg,exeseg; + Bit32u imagesize,headersize; + + PSP * callpsp=(PSP *)real_off(dos.psp,0); + + if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false; + if (flag!=OVERLAY) { + /* Allocate a new Environment */ + envseg=block->exec.envseg; + if (!MakeEnv(name,&envseg)) return false; + }; + + /* First Read the EXE Header */ + readsize=sizeof(EXE_Header); + DOS_ReadFile(fhandle,(Bit8u*)&header,&readsize); + /* Calculate the size of the image to load */ + headersize=header.headersize*16; + imagesize=header.pages*512-headersize; + if (flag!=OVERLAY) { + minsize=long2para(imagesize+(header.minmemory<<4)+256); + if (header.maxmemory!=0) maxsize=long2para(imagesize+(header.maxmemory<<4)+256); + else maxsize=0xffff; + freesize=0xffff; + /* Check for enough free memory */ + DOS_AllocateMemory(&exeseg,&freesize); + if (minsize>freesize) { + DOS_SetError(DOSERR_INSUFFICIENT_MEMORY); + DOS_FreeMemory(envseg); + return false; + } + if (maxsize>freesize) { + size=freesize; + } else size=maxsize; + if ((header.minmemory|header.maxmemory)==0) { + size=freesize; + E_Exit("Special case exe header max and min=0"); + } + if (!DOS_AllocateMemory(&pspseg,&size)) { + DOS_SetError(DOSERR_INSUFFICIENT_MEMORY); + DOS_FreeMemory(envseg); + return false; + } + SetupPSP(pspseg,size,envseg); + SetupCMDLine(pspseg,block); + exeseg=pspseg+16; + } else { + /* For OVERLAY */ + exeseg=block->overlay.loadseg; + } + /* Load the image in 32k blocks */ + DOS_SeekFile(fhandle,&headersize,0); + Bit8u * imageoff=real_off(exeseg,0); +//TODO File size checking and remove size + // Remove psp size +// imagesize=256; + // Maybe remove final page and add last bytes on page + if (header.extrabytes) { + imagesize-=512; + imagesize+=header.extrabytes; + }; + while (imagesize>0x7FFF) { + readsize=0x8000; + DOS_ReadFile(fhandle,imageoff,&readsize); + if (readsize!=0x8000) { + E_Exit("Illegal header"); + } + imageoff+=0x8000; + imagesize-=0x8000; + } + if (imagesize>0) { + readsize=(Bit16u) imagesize; + DOS_ReadFile(fhandle,imageoff,&readsize); + } + headersize=header.reloctable; + DOS_SeekFile(fhandle,&headersize,0); + RealPt reloc; + for (i=0;ioverlay.relocation; + } else { + change+=exeseg; + }; + mem_writew(address,change); + + }; + DOS_CloseFile(fhandle); + if (flag==OVERLAY) return true; + + /* Setup termination Address */ + RealSetVec(0x22,RealMake(Segs[cs].value,reg_ip)); + /* Start up the actual EXE if we need to */ + //TODO check for load and return + callpsp->stack=RealMake(Segs[ss].value,reg_sp); + dos.psp=pspseg; + SetSegment_16(cs,exeseg+header.initCS); + SetSegment_16(ss,exeseg+header.initSS); + SetSegment_16(ds,pspseg); + SetSegment_16(es,pspseg); + reg_ip=header.initIP; + reg_sp=header.initSP; + reg_ax=0; + reg_bx=reg_cx=reg_dx=reg_si=reg_di=reg_bp=0; + flags.intf=true; + return true; +}; + + +bool DOS_Execute(char * name,ParamBlock * block,Bit8u flags) { + + EXE_Header head; + Bit16u fhandle; + Bit16u size; + bool iscom=false; + if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false; + + size=sizeof(EXE_Header); + if (!DOS_ReadFile(fhandle,(Bit8u *)&head,&size)) { + DOS_CloseFile(fhandle); + return false; + } + if (!DOS_CloseFile(fhandle)) return false; + if (size -#include -#include -#include - -#include "dosbox.h" -#include "bios.h" -#include "mem.h" -#include "regs.h" -#include "dos_inc.h" -#include "drives.h" -#include "cross.h" - -#define DOS_FILESTART 4 - -#define FCB_SUCCESS 0 -#define FCB_READ_NODATA 1 -#define FCB_READ_PARTIAL 3 -#define FCB_ERR_NODATA 1 -#define FCB_ERR_EOF 3 -#define FCB_ERR_WRITE 1 - - -DOS_File * Files[DOS_FILES]; -DOS_Drive * Drives[DOS_DRIVES]; - -Bit8u DOS_GetDefaultDrive(void) { -// return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetDrive(); - Bit8u d = DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetDrive(); - if( d != dos.current_drive ) LOG(LOG_DOSMISC,LOG_ERROR)("SDA drive %d not the same as dos.current_drive %d",d,dos.current_drive); - return dos.current_drive; -} - -void DOS_SetDefaultDrive(Bit8u drive) { -// if (drive<=DOS_DRIVES && ((drive<2) || Drives[drive])) DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetDrive(drive); - if (drive<=DOS_DRIVES && ((drive<2) || Drives[drive])) {dos.current_drive = drive; DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetDrive(drive);} -} - -bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive) { - if(!name || *name == 0 || *name == ' ') { - /* Both \0 and space are seperators and - * empty filenames report file not found */ - DOS_SetError(DOSERR_FILE_NOT_FOUND); - return false; - } - const char * name_int = name; - char tempdir[DOS_PATHLENGTH]; - char upname[DOS_PATHLENGTH]; - Bitu r,w; - *drive = DOS_GetDefaultDrive(); - /* First get the drive */ - if (name_int[1]==':') { - *drive=(name_int[0] | 0x20)-'a'; - name_int+=2; - } - if (*drive>=DOS_DRIVES || !Drives[*drive]) { - DOS_SetError(DOSERR_PATH_NOT_FOUND); - return false; - } - r=0;w=0; - while (name_int[r]!=0 && (r='a') && (c<='z')) {upname[w++]=c-32;continue;} - if ((c>='A') && (c<='Z')) {upname[w++]=c;continue;} - if ((c>='0') && (c<='9')) {upname[w++]=c;continue;} - switch (c) { - case '/': - upname[w++]='\\'; - break; - case ' ': /* should be seperator */ - break; - case '\\': case '$': case '#': case '@': case '(': case ')': - case '!': case '%': case '{': case '}': case '`': case '~': - case '_': case '-': case '.': case '*': case '?': case '&': - case '\'': case '+': case '^': case 246: case 255: case 0xa0: - case 0xe5: - upname[w++]=c; - break; - default: - LOG(LOG_FILES,LOG_NORMAL)("Makename encountered an illegal char %c hex:%X in %s!",c,c,name); - DOS_SetError(DOSERR_PATH_NOT_FOUND);return false; - break; - } - } - if (r>=DOS_PATHLENGTH) { DOS_SetError(DOSERR_PATH_NOT_FOUND);return false; } - upname[w]=0; - /* Now parse the new file name to make the final filename */ - if (upname[0]!='\\') strcpy(fullname,Drives[*drive]->curdir); - else fullname[0]=0; - Bit32u lastdir=0;Bit32u t=0; - while (fullname[t]!=0) { - if ((fullname[t]=='\\') && (fullname[t+1]!=0)) lastdir=t; - t++; - }; - r=0;w=0; - tempdir[0]=0; - bool stop=false; - while (!stop) { - if (upname[r]==0) stop=true; - if ((upname[r]=='\\') || (upname[r]==0)){ - tempdir[w]=0; - if (tempdir[0]==0) { w=0;r++;continue;} - if (strcmp(tempdir,".")==0) { - tempdir[0]=0; - w=0;r++; - continue; - } - - Bit32s iDown; - bool dots = true; - Bit32s templen=(Bit32s)strlen(tempdir); - for(iDown=0;(iDown < templen) && dots;iDown++) - if(tempdir[iDown] != '.') - dots = false; - - // only dots? - if (dots && (templen > 1)) { - Bit32s cDots = templen - 1; - for(iDown=(Bit32s)strlen(fullname)-1;iDown>=0;iDown--) { - if(fullname[iDown]=='\\' || iDown==0) { - lastdir = iDown; - cDots--; - if(cDots==0) - break; - } - } - fullname[lastdir]=0; - t=0;lastdir=0; - while (fullname[t]!=0) { - if ((fullname[t]=='\\') && (fullname[t+1]!=0)) lastdir=t; - t++; - } - tempdir[0]=0; - w=0;r++; - continue; - } - - - lastdir=(Bit32u)strlen(fullname); - - if (lastdir!=0) strcat(fullname,"\\"); - char * ext=strchr(tempdir,'.'); - if (ext) { - if(strchr(ext+1,'.')) { - //another dot in the extension =>file not found - //Or path not found depending on wether - //we are still in dir check stage or file stage - if(stop) - DOS_SetError(DOSERR_FILE_NOT_FOUND); - else - DOS_SetError(DOSERR_PATH_NOT_FOUND); - return false; - } - - ext[4] = 0; - if((strlen(tempdir) - strlen(ext)) > 8) memmove(tempdir + 8, ext, 5); - } else tempdir[8]=0; - strcat(fullname,tempdir); - tempdir[0]=0; - w=0;r++; - continue; - } - tempdir[w++]=upname[r++]; - } - return true; -} - -bool DOS_GetCurrentDir(Bit8u drive,char * const buffer) { - if (drive==0) drive=DOS_GetDefaultDrive(); - else drive--; - if ((drive>DOS_DRIVES) || (!Drives[drive])) { - DOS_SetError(DOSERR_INVALID_DRIVE); - return false; - } - strcpy(buffer,Drives[drive]->curdir); - return true; -} - -bool DOS_ChangeDir(char const * const dir) { - Bit8u drive;char fulldir[DOS_PATHLENGTH]; - if (!DOS_MakeName(dir,fulldir,&drive)) return false; - - if (Drives[drive]->TestDir(fulldir)) { - strcpy(Drives[drive]->curdir,fulldir); - return true; - } else { - DOS_SetError(DOSERR_PATH_NOT_FOUND); - } - return false; -} - -bool DOS_MakeDir(char const * const dir) { - Bit8u drive;char fulldir[DOS_PATHLENGTH]; - size_t len = strlen(dir); - if(!len || dir[len-1] == '\\') { - DOS_SetError(DOSERR_PATH_NOT_FOUND); - return false; - } - if (!DOS_MakeName(dir,fulldir,&drive)) return false; - if(Drives[drive]->MakeDir(fulldir)) return true; - - /* Determine reason for failing */ - if(Drives[drive]->TestDir(fulldir)) - DOS_SetError(DOSERR_ACCESS_DENIED); - else - DOS_SetError(DOSERR_PATH_NOT_FOUND); - return false; -} - -bool DOS_RemoveDir(char const * const dir) { -/* We need to do the test before the removal as can not rely on - * the host to forbid removal of the current directory. - * We never change directory. Everything happens in the drives. - */ - Bit8u drive;char fulldir[DOS_PATHLENGTH]; - if (!DOS_MakeName(dir,fulldir,&drive)) return false; - /* Check if exists */ - if(!Drives[drive]->TestDir(fulldir)) { - DOS_SetError(DOSERR_PATH_NOT_FOUND); - return false; - } - /* See if it's current directory */ - char currdir[DOS_PATHLENGTH]= { 0 }; - DOS_GetCurrentDir(drive + 1 ,currdir); - if(strcmp(currdir,fulldir) == 0) { - DOS_SetError(DOSERR_REMOVE_CURRENT_DIRECTORY); - return false; - } - - if(Drives[drive]->RemoveDir(fulldir)) return true; - - /* Failed. We know it exists and it's not the current dir */ - /* Assume non empty */ - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool DOS_Rename(char const * const oldname,char const * const newname) { - Bit8u driveold;char fullold[DOS_PATHLENGTH]; - Bit8u drivenew;char fullnew[DOS_PATHLENGTH]; - if (!DOS_MakeName(oldname,fullold,&driveold)) return false; - if (!DOS_MakeName(newname,fullnew,&drivenew)) return false; - /* No tricks with devices */ - if ( (DOS_FindDevice(oldname) != DOS_DEVICES) || - (DOS_FindDevice(newname) != DOS_DEVICES) ) { - DOS_SetError(DOSERR_FILE_NOT_FOUND); - return false; - } - /* Must be on the same drive */ - if(driveold != drivenew) { - DOS_SetError(DOSERR_NOT_SAME_DEVICE); - return false; - } - /*Test if target exists => no access */ - Bit16u attr; - if(Drives[drivenew]->GetFileAttr(fullnew,&attr)) { - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; - } - /* Source must exist, check for path ? */ - if (!Drives[driveold]->GetFileAttr( fullold, &attr ) ) { - DOS_SetError(DOSERR_FILE_NOT_FOUND); - return false; - } - - if (Drives[drivenew]->Rename(fullold,fullnew)) return true; - /* If it still fails. which error should we give ? PATH NOT FOUND or EACCESS */ - LOG(LOG_FILES,LOG_NORMAL)("Rename fails for %s to %s, no proper errorcode returned.",oldname,newname); - DOS_SetError(DOSERR_FILE_NOT_FOUND); - return false; -} - -bool DOS_FindFirst(char * search,Bit16u attr,bool fcb_findfirst) { - DOS_DTA dta(dos.dta()); - Bit8u drive;char fullsearch[DOS_PATHLENGTH]; - char dir[DOS_PATHLENGTH];char pattern[DOS_PATHLENGTH]; - size_t len = strlen(search); - if(len && search[len - 1] == '\\' && !( (len > 2) && (search[len - 2] == ':') && (attr == DOS_ATTR_VOLUME) )) { - //Dark Forces installer, but c:\ is allright for volume labels(exclusively set) - DOS_SetError(DOSERR_NO_MORE_FILES); - return false; - } - if (!DOS_MakeName(search,fullsearch,&drive)) return false; - //Check for devices. FindDevice checks for leading subdir as well - bool device = (DOS_FindDevice(search) != DOS_DEVICES); - - /* Split the search in dir and pattern */ - char * find_last; - find_last=strrchr(fullsearch,'\\'); - if (!find_last) { /*No dir */ - strcpy(pattern,fullsearch); - dir[0]=0; - } else { - *find_last=0; - strcpy(pattern,find_last+1); - strcpy(dir,fullsearch); - } - - dta.SetupSearch(drive,(Bit8u)attr,pattern); - - if(device) { - find_last = strrchr(pattern,'.'); - if(find_last) *find_last = 0; - //TODO use current date and time - dta.SetResult(pattern,0,0,0,DOS_ATTR_DEVICE); - LOG(LOG_DOSMISC,LOG_WARN)("finding device %s",pattern); - return true; - } - - if (Drives[drive]->FindFirst(dir,dta,fcb_findfirst)) return true; - - return false; -} - -bool DOS_FindNext(void) { - DOS_DTA dta(dos.dta()); - Bit8u i = dta.GetSearchDrive(); - if(i >= DOS_DRIVES || !Drives[i]) { - /* Corrupt search. */ - LOG(LOG_FILES,LOG_ERROR)("Corrupt search!!!!"); - DOS_SetError(DOSERR_NO_MORE_FILES); - return false; - } - if (Drives[i]->FindNext(dta)) return true; - return false; -} - - -bool DOS_ReadFile(Bit16u entry,Bit8u * data,Bit16u * amount) { - Bit32u handle=RealHandle(entry); - if (handle>=DOS_FILES) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - if (!Files[handle] || !Files[handle]->IsOpen()) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; -//TODO maybe another code :) -/* - if (!(Files[handle]->flags & OPEN_READ)) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - } -*/ - Bit16u toread=*amount; - bool ret=Files[handle]->Read(data,&toread); - *amount=toread; - return ret; -} - -bool DOS_WriteFile(Bit16u entry,Bit8u * data,Bit16u * amount) { - Bit32u handle=RealHandle(entry); - if (handle>=DOS_FILES) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - if (!Files[handle] || !Files[handle]->IsOpen()) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; -//TODO maybe another code :) -/* - if (!(Files[handle]->flags & OPEN_WRITE)) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - } -*/ - Bit16u towrite=*amount; - bool ret=Files[handle]->Write(data,&towrite); - *amount=towrite; - return ret; -} - -bool DOS_SeekFile(Bit16u entry,Bit32u * pos,Bit32u type) { - Bit32u handle=RealHandle(entry); - if (handle>=DOS_FILES) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - if (!Files[handle] || !Files[handle]->IsOpen()) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - return Files[handle]->Seek(pos,type); -} - -bool DOS_CloseFile(Bit16u entry) { - Bit32u handle=RealHandle(entry); - if (handle>=DOS_FILES) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - if (!Files[handle]) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - if (Files[handle]->IsOpen()) { - Files[handle]->Close(); - } - DOS_PSP psp(dos.psp()); - psp.SetFileHandle(entry,0xff); - if (Files[handle]->RemoveRef()<=0) { - delete Files[handle]; - Files[handle]=0; - } - return true; -} - -bool DOS_FlushFile(Bit16u entry) { - Bit32u handle=RealHandle(entry); - if (handle>=DOS_FILES) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - if (!Files[handle] || !Files[handle]->IsOpen()) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - LOG(LOG_DOSMISC,LOG_NORMAL)("FFlush used."); - return true; -} - -static bool PathExists(char const * const name) { - const char* leading = strrchr(name,'\\'); - if(!leading) return true; - char temp[CROSS_LEN]; - strcpy(temp,name); - char * lead = strrchr(temp,'\\'); - if (lead == temp) return true; - *lead = 0; - Bit8u drive;char fulldir[DOS_PATHLENGTH]; - if (!DOS_MakeName(temp,fulldir,&drive)) return false; - if(!Drives[drive]->TestDir(fulldir)) return false; - return true; -} - - -bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry) { - // Creation of a device is the same as opening it - // Tc201 installer - if (DOS_FindDevice(name) != DOS_DEVICES) - return DOS_OpenFile(name, OPEN_READ, entry); - - LOG(LOG_FILES,LOG_NORMAL)("file create attributes %X file %s",attributes,name); - char fullname[DOS_PATHLENGTH];Bit8u drive; - DOS_PSP psp(dos.psp()); - if (!DOS_MakeName(name,fullname,&drive)) return false; - /* Check for a free file handle */ - Bit8u handle=DOS_FILES;Bit8u i; - for (i=0;iFileCreate(&Files[handle],fullname,attributes); - if (foundit) { - Files[handle]->SetDrive(drive); - Files[handle]->AddRef(); - psp.SetFileHandle(*entry,handle); - return true; - } else { - if(!PathExists(name)) DOS_SetError(DOSERR_PATH_NOT_FOUND); - else DOS_SetError(DOSERR_FILE_NOT_FOUND); - return false; - } -} - -bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry) { - /* First check for devices */ - if (flags>2) LOG(LOG_FILES,LOG_ERROR)("Special file open command %X file %s",flags,name); - else LOG(LOG_FILES,LOG_NORMAL)("file open command %X file %s",flags,name); - - DOS_PSP psp(dos.psp()); - Bit16u attr = 0; - Bit8u devnum = DOS_FindDevice(name); - bool device = (devnum != DOS_DEVICES); - if(!device && DOS_GetFileAttr(name,&attr)) { - //DON'T ALLOW directories to be openened.(skip test if file is device). - if((attr & DOS_ATTR_DIRECTORY) || (attr & DOS_ATTR_VOLUME)){ - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; - } - } - - char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i; - /* First check if the name is correct */ - if (!DOS_MakeName(name,fullname,&drive)) return false; - Bit8u handle=255; - /* Check for a free file handle */ - for (i=0;iFileOpen(&Files[handle],fullname,flags); - if (exists) Files[handle]->SetDrive(drive); - } - if (exists || device ) { - Files[handle]->AddRef(); - psp.SetFileHandle(*entry,handle); - return true; - } else { - //Test if file exists, but opened in read-write mode (and writeprotected) - if(((flags&3) != OPEN_READ) && Drives[drive]->FileExists(fullname)) - DOS_SetError(DOSERR_ACCESS_DENIED); - else { - if(!PathExists(name)) DOS_SetError(DOSERR_PATH_NOT_FOUND); - else DOS_SetError(DOSERR_FILE_NOT_FOUND); - } - return false; - } -} - -bool DOS_OpenFileExtended(char const * name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status) { -// FIXME: Not yet supported : Bit 13 of flags (int 0x24 on critical error) - Bit16u result = 0; - if (action==0) { - // always fail setting - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - } else { - if (((action & 0x0f)>2) || ((action & 0xf0)>0x10)) { - // invalid action parameter - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - } - } - if (DOS_OpenFile(name, (Bit8u)(flags&0xff), entry)) { - // File already exists - switch (action & 0x0f) { - case 0x00: // failed - DOS_SetError(DOSERR_FILE_ALREADY_EXISTS); - return false; - case 0x01: // file open (already done) - result = 1; - break; - case 0x02: // replace - DOS_CloseFile(*entry); - if (!DOS_CreateFile(name, createAttr, entry)) return false; - result = 3; - break; - default: - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - E_Exit("DOS: OpenFileExtended: Unknown action."); - break; - } - } else { - // File doesn't exist - if ((action & 0xf0)==0) { - // uses error code from failed open - return false; - } - // Create File - if (!DOS_CreateFile(name, createAttr, entry)) { - // uses error code from failed create - return false; - } - result = 2; - } - // success - *status = result; - return true; -} - -bool DOS_UnlinkFile(char const * const name) { - char fullname[DOS_PATHLENGTH];Bit8u drive; - if (!DOS_MakeName(name,fullname,&drive)) return false; - if(Drives[drive]->FileUnlink(fullname)){ - return true; - } else { - DOS_SetError(DOSERR_FILE_NOT_FOUND); - return false; - } -} - -bool DOS_GetFileAttr(char const * const name,Bit16u * attr) { - char fullname[DOS_PATHLENGTH];Bit8u drive; - if (!DOS_MakeName(name,fullname,&drive)) return false; - if (Drives[drive]->GetFileAttr(fullname,attr)) { - return true; - } else { - DOS_SetError(DOSERR_FILE_NOT_FOUND); - return false; - } -} - -bool DOS_SetFileAttr(char const * const name,Bit16u /*attr*/) -// this function does not change the file attributs -// it just does some tests if file is available -// returns false when using on cdrom (stonekeep) -{ - Bit16u attrTemp; - char fullname[DOS_PATHLENGTH];Bit8u drive; - if (!DOS_MakeName(name,fullname,&drive)) return false; - if (strncmp(Drives[drive]->GetInfo(),"CDRom ",6)==0 || strncmp(Drives[drive]->GetInfo(),"isoDrive ",9)==0) { - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; - } - return Drives[drive]->GetFileAttr(fullname,&attrTemp); -} - -bool DOS_Canonicalize(char const * const name,char * const big) { -//TODO Add Better support for devices and shit but will it be needed i doubt it :) - Bit8u drive; - char fullname[DOS_PATHLENGTH]; - if (!DOS_MakeName(name,fullname,&drive)) return false; - big[0]=drive+'A'; - big[1]=':'; - big[2]='\\'; - strcpy(&big[3],fullname); - return true; -} - -bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * clusters,Bit16u * free) { - if (drive==0) drive=DOS_GetDefaultDrive(); - else drive--; - if ((drive>DOS_DRIVES) || (!Drives[drive])) { - DOS_SetError(DOSERR_INVALID_DRIVE); - return false; - } - return Drives[drive]->AllocationInfo(bytes,sectors,clusters,free); -} - -bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) { - // Dont duplicate console handles -/* if (entry<=STDPRN) { - *newentry = entry; - return true; - }; -*/ - Bit8u handle=RealHandle(entry); - if (handle>=DOS_FILES) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - if (!Files[handle] || !Files[handle]->IsOpen()) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - DOS_PSP psp(dos.psp()); - *newentry = psp.FindFreeFileEntry(); - if (*newentry==0xff) { - DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); - return false; - } - Files[handle]->AddRef(); - psp.SetFileHandle(*newentry,handle); - return true; -} - -bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry) { - if(entry == newentry) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - } - Bit8u orig = RealHandle(entry); - if (orig >= DOS_FILES) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - if (!Files[orig] || !Files[orig]->IsOpen()) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - Bit8u newone = RealHandle(newentry); - if (newone < DOS_FILES && Files[newone]) { - DOS_CloseFile(newentry); - } - DOS_PSP psp(dos.psp()); - Files[orig]->AddRef(); - psp.SetFileHandle(newentry,orig); - return true; -} - - -bool DOS_CreateTempFile(char * const name,Bit16u * entry) { - size_t namelen=strlen(name); - char * tempname=name+namelen; - if (namelen==0) { - // temp file created in root directory - tempname[0]='\\'; - tempname++; - } else { - if ((name[namelen-1]!='\\') && (name[namelen-1]!='/')) { - tempname[0]='\\'; - tempname++; - } - } - dos.errorcode=0; - /* add random crap to the end of the name and try to open */ - do { - Bit32u i; - for (i=0;i<8;i++) { - tempname[i]=(rand()%26)+'A'; - } - tempname[8]=0; - } while ((!DOS_CreateFile(name,0,entry)) && (dos.errorcode==DOSERR_FILE_ALREADY_EXISTS)); - if (dos.errorcode) return false; - return true; -} - -#define FCB_SEP ":.;,=+" -#define ILLEGAL ":.;,=+ \t/\"[]<>|" - -static bool isvalid(const char in){ - const char ill[]=ILLEGAL; - return (Bit8u(in)>0x1F) && (!strchr(ill,in)); -} - -#define PARSE_SEP_STOP 0x01 -#define PARSE_DFLT_DRIVE 0x02 -#define PARSE_BLNK_FNAME 0x04 -#define PARSE_BLNK_FEXT 0x08 - -#define PARSE_RET_NOWILD 0 -#define PARSE_RET_WILD 1 -#define PARSE_RET_BADDRIVE 0xff - -Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change) { - char * string_begin=string;Bit8u ret=0; - DOS_FCB fcb(seg,offset); - bool hasdrive,hasname,hasext,finished; - hasdrive=hasname=hasext=finished=false; - Bitu index=0;Bit8u fill=' '; -/* First get the old data from the fcb */ -#ifdef _MSC_VER -#pragma pack (1) -#endif - union { - struct { - char drive[2]; - char name[9]; - char ext[4]; - } GCC_ATTRIBUTE (packed) part; - char full[DOS_FCBNAME]; - } fcb_name; -#ifdef _MSC_VER -#pragma pack() -#endif - /* Get the old information from the previous fcb */ - fcb.GetName(fcb_name.full); - fcb_name.part.drive[0]-='A'-1;fcb_name.part.drive[1]=0; - fcb_name.part.name[8]=0;fcb_name.part.ext[3]=0; - /* Strip of the leading sepetaror */ - if((parser & PARSE_SEP_STOP) && *string) { //ignore leading seperator - char sep[] = FCB_SEP;char a[2]; - a[0]= *string;a[1]='\0'; - if (strcspn(a,sep)==0) string++; - } - /* strip leading spaces */ - while((*string==' ')||(*string=='\t')) string++; - /* Check for a drive */ - if (string[1]==':') { - fcb_name.part.drive[0]=0; - hasdrive=true; - if (isalpha(string[0]) && Drives[toupper(string[0])-'A']) { - fcb_name.part.drive[0]=(char)(toupper(string[0])-'A'+1); - } else ret=0xff; - string+=2; - } - /* Special checks for . and .. */ - if (string[0]=='.') { - string++; - if (!string[0]) { - hasname=true; - ret=PARSE_RET_NOWILD; - strcpy(fcb_name.part.name,". "); - goto savefcb; - } - if (string[1]=='.' && !string[1]) { - string++; - hasname=true; - ret=PARSE_RET_NOWILD; - strcpy(fcb_name.part.name,".. "); - goto savefcb; - } - goto checkext; - } - /* Copy the name */ - hasname=true;finished=false;fill=' ';index=0; - while (index<8) { - if (!finished) { - if (string[0]=='*') {fill='?';fcb_name.part.name[index]='?';if (!ret) ret=1;finished=true;} - else if (string[0]=='?') {fcb_name.part.name[index]='?';if (!ret) ret=1;} - else if (isvalid(string[0])) {fcb_name.part.name[index]=(char)(toupper(string[0]));} - else { finished=true;continue; } - string++; - } else { - fcb_name.part.name[index]=fill; - } - index++; - } - if (!(string[0]=='.')) goto savefcb; - string++; -checkext: - /* Copy the extension */ - hasext=true;finished=false;fill=' ';index=0; - while (index<3) { - if (!finished) { - if (string[0]=='*') {fill='?';fcb_name.part.ext[index]='?';finished=true;} - else if (string[0]=='?') {fcb_name.part.ext[index]='?';if (!ret) ret=1;} - else if (isvalid(string[0])) {fcb_name.part.ext[index]=(char)(toupper(string[0]));} - else { finished=true;continue; } - string++; - } else { - fcb_name.part.ext[index]=fill; - } - index++; - } -savefcb: - if (!hasdrive & !(parser & PARSE_DFLT_DRIVE)) fcb_name.part.drive[0] = 0; - if (!hasname & !(parser & PARSE_BLNK_FNAME)) strcpy(fcb_name.part.name," "); - if (!hasext & !(parser & PARSE_BLNK_FEXT)) strcpy(fcb_name.part.ext," "); - fcb.SetName(fcb_name.part.drive[0],fcb_name.part.name,fcb_name.part.ext); - *change=(Bit8u)(string-string_begin); - return ret; -} - -static void DTAExtendName(char * const name,char * const filename,char * const ext) { - char * find=strchr(name,'.'); - if (find) { - strcpy(ext,find+1); - *find=0; - } else ext[0]=0; - strcpy(filename,name); - size_t i; - for (i=strlen(name);i<8;i++) filename[i]=' '; - filename[8]=0; - for (i=strlen(ext);i<3;i++) ext[i]=' '; - ext[3]=0; -} - -static void SaveFindResult(DOS_FCB & find_fcb) { - DOS_DTA find_dta(dos.tables.tempdta); - char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr;Bit8u drive; - char file_name[9];char ext[4]; - find_dta.GetResult(name,size,date,time,attr); - drive=find_fcb.GetDrive()+1; - /* Create a correct file and extention */ - DTAExtendName(name,file_name,ext); - DOS_FCB fcb(RealSeg(dos.dta()),RealOff(dos.dta()));//TODO - fcb.Create(find_fcb.Extended()); - fcb.SetName(drive,file_name,ext); - fcb.SetAttr(attr); /* Only adds attribute if fcb is extended */ - fcb.SetSizeDateTime(size,date,time); -} - -bool DOS_FCBCreate(Bit16u seg,Bit16u offset) { - DOS_FCB fcb(seg,offset); - char shortname[DOS_FCBNAME];Bit16u handle; - fcb.GetName(shortname); - if (!DOS_CreateFile(shortname,DOS_ATTR_ARCHIVE,&handle)) return false; - fcb.FileOpen((Bit8u)handle); - return true; -} - -bool DOS_FCBOpen(Bit16u seg,Bit16u offset) { - DOS_FCB fcb(seg,offset); - char shortname[DOS_FCBNAME];Bit16u handle; - fcb.GetName(shortname); - - /* First check if the name is correct */ - Bit8u drive; - char fullname[DOS_PATHLENGTH]; - if (!DOS_MakeName(shortname,fullname,&drive)) return false; - - /* Check, if file is already opened */ - for (Bit8u i=0;iIsOpen() && Files[i]->IsName(fullname)) { - handle = psp.FindEntryByHandle(i); - if (handle==0xFF) { - // This shouldnt happen - LOG(LOG_FILES,LOG_ERROR)("DOS: File %s is opened but has no psp entry.",shortname); - return false; - } - fcb.FileOpen((Bit8u)handle); - return true; - } - } - - if (!DOS_OpenFile(shortname,OPEN_READWRITE,&handle)) return false; - fcb.FileOpen((Bit8u)handle); - return true; -} - -bool DOS_FCBClose(Bit16u seg,Bit16u offset) { - DOS_FCB fcb(seg,offset); - if(!fcb.Valid()) return false; - Bit8u fhandle; - fcb.FileClose(fhandle); - DOS_CloseFile(fhandle); - return true; -} - -bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset) { - DOS_FCB fcb(seg,offset); - RealPt old_dta=dos.dta();dos.dta(dos.tables.tempdta); - char name[DOS_FCBNAME];fcb.GetName(name); - Bit8u attr = DOS_ATTR_ARCHIVE; - fcb.GetAttr(attr); /* Gets search attributes if extended */ - bool ret=DOS_FindFirst(name,attr,true); - dos.dta(old_dta); - if (ret) SaveFindResult(fcb); - return ret; -} - -bool DOS_FCBFindNext(Bit16u seg,Bit16u offset) { - DOS_FCB fcb(seg,offset); - RealPt old_dta=dos.dta();dos.dta(dos.tables.tempdta); - bool ret=DOS_FindNext(); - dos.dta(old_dta); - if (ret) SaveFindResult(fcb); - return ret; -} - -Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset,Bit16u recno) { - DOS_FCB fcb(seg,offset); - Bit8u fhandle,cur_rec;Bit16u cur_block,rec_size; - fcb.GetSeqData(fhandle,rec_size); - fcb.GetRecord(cur_block,cur_rec); - Bit32u pos=((cur_block*128)+cur_rec)*rec_size; - if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET)) return FCB_READ_NODATA; - Bit16u toread=rec_size; - if (!DOS_ReadFile(fhandle,dos_copybuf,&toread)) return FCB_READ_NODATA; - if (toread==0) return FCB_READ_NODATA; - if (toread < rec_size) { //Zero pad copybuffer to rec_size - Bitu i = toread; - while(i < rec_size) dos_copybuf[i++] = 0; - } - MEM_BlockWrite(Real2Phys(dos.dta())+recno*rec_size,dos_copybuf,rec_size); - if (++cur_rec>127) { cur_block++;cur_rec=0; } - fcb.SetRecord(cur_block,cur_rec); - if (toread==rec_size) return FCB_SUCCESS; - if (toread==0) return FCB_READ_NODATA; - return FCB_READ_PARTIAL; -} - -Bit8u DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u recno) { - DOS_FCB fcb(seg,offset); - Bit8u fhandle,cur_rec;Bit16u cur_block,rec_size; - fcb.GetSeqData(fhandle,rec_size); - fcb.GetRecord(cur_block,cur_rec); - Bit32u pos=((cur_block*128)+cur_rec)*rec_size; - if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET)) return FCB_ERR_WRITE; - MEM_BlockRead(Real2Phys(dos.dta())+recno*rec_size,dos_copybuf,rec_size); - Bit16u towrite=rec_size; - if (!DOS_WriteFile(fhandle,dos_copybuf,&towrite)) return FCB_ERR_WRITE; - Bit32u size;Bit16u date,time; - fcb.GetSizeDateTime(size,date,time); - if (pos+towrite>size) size=pos+towrite; - //time doesn't keep track of endofday - date = DOS_PackDate(dos.date.year,dos.date.month,dos.date.day); - Bit32u ticks = mem_readd(BIOS_TIMER); - Bit32u seconds = (ticks*10)/182; - Bit16u hour = (Bit16u)(seconds/3600); - Bit16u min = (Bit16u)((seconds % 3600)/60); - Bit16u sec = (Bit16u)(seconds % 60); - time = DOS_PackTime(hour,min,sec); - Bit8u temp=RealHandle(fhandle); - Files[temp]->time=time; - Files[temp]->date=date; - fcb.SetSizeDateTime(size,date,time); - if (++cur_rec>127) { cur_block++;cur_rec=0; } - fcb.SetRecord(cur_block,cur_rec); - return FCB_SUCCESS; -} - -Bit8u DOS_FCBIncreaseSize(Bit16u seg,Bit16u offset) { - DOS_FCB fcb(seg,offset); - Bit8u fhandle,cur_rec;Bit16u cur_block,rec_size; - fcb.GetSeqData(fhandle,rec_size); - fcb.GetRecord(cur_block,cur_rec); - Bit32u pos=((cur_block*128)+cur_rec)*rec_size; - if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET)) return FCB_ERR_WRITE; - Bit16u towrite=0; - if (!DOS_WriteFile(fhandle,dos_copybuf,&towrite)) return FCB_ERR_WRITE; - Bit32u size;Bit16u date,time; - fcb.GetSizeDateTime(size,date,time); - if (pos+towrite>size) size=pos+towrite; - //time doesn't keep track of endofday - date = DOS_PackDate(dos.date.year,dos.date.month,dos.date.day); - Bit32u ticks = mem_readd(BIOS_TIMER); - Bit32u seconds = (ticks*10)/182; - Bit16u hour = (Bit16u)(seconds/3600); - Bit16u min = (Bit16u)((seconds % 3600)/60); - Bit16u sec = (Bit16u)(seconds % 60); - time = DOS_PackTime(hour,min,sec); - Bit8u temp=RealHandle(fhandle); - Files[temp]->time=time; - Files[temp]->date=date; - fcb.SetSizeDateTime(size,date,time); - fcb.SetRecord(cur_block,cur_rec); - return FCB_SUCCESS; -} - -Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) { -/* if restore is true :random read else random blok read. - * random read updates old block and old record to reflect the random data - * before the read!!!!!!!!! and the random data is not updated! (user must do this) - * Random block read updates these fields to reflect the state after the read! - */ - -/* BUG: numRec should return the amount of records read! - * Not implemented yet as I'm unsure how to count on error states (partial/failed) - */ - - DOS_FCB fcb(seg,offset); - Bit32u random;Bit16u old_block;Bit8u old_rec; - Bit8u error=0; - - /* Set the correct record from the random data */ - fcb.GetRandom(random); - fcb.SetRecord((Bit16u)(random / 128),(Bit8u)(random & 127)); - if (restore) fcb.GetRecord(old_block,old_rec);//store this for after the read. - // Read records - for (int i=0; i0) { - /* Write records */ - for (int i=0; iSeek(&size,DOS_SEEK_END); - DOS_CloseFile(entry);fcb.GetSeqData(handle,rec_size); - Bit32u random=(size/rec_size); - if (size % rec_size) random++; - fcb.SetRandom(random); - return true; -} - -bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset){ -/* FCB DELETE honours wildcards. it will return true if one or more - * files get deleted. - * To get this: the dta is set to temporary dta in which found files are - * stored. This can not be the tempdta as that one is used by fcbfindfirst - */ - RealPt old_dta=dos.dta();dos.dta(dos.tables.tempdta_fcbdelete); - DOS_FCB fcb(RealSeg(dos.dta()),RealOff(dos.dta())); - bool nextfile = false; - bool return_value = false; - nextfile = DOS_FCBFindFirst(seg,offset); - while(nextfile) { - char shortname[DOS_FCBNAME] = { 0 }; - fcb.GetName(shortname); - bool res=DOS_UnlinkFile(shortname); - if(!return_value && res) return_value = true; //at least one file deleted - nextfile = DOS_FCBFindNext(seg,offset); - } - dos.dta(old_dta); /*Restore dta */ - return return_value; -} - -bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset){ - DOS_FCB fcbold(seg,offset); - DOS_FCB fcbnew(seg,offset+16); - char oldname[DOS_FCBNAME]; - char newname[DOS_FCBNAME]; - fcbold.GetName(oldname);fcbnew.GetName(newname); - return DOS_Rename(oldname,newname); -} - -void DOS_FCBSetRandomRecord(Bit16u seg, Bit16u offset) { - DOS_FCB fcb(seg,offset); - Bit16u block;Bit8u rec; - fcb.GetRecord(block,rec); - fcb.SetRandom(block*128+rec); -} - - -bool DOS_FileExists(char const * const name) { - char fullname[DOS_PATHLENGTH];Bit8u drive; - if (!DOS_MakeName(name,fullname,&drive)) return false; - return Drives[drive]->FileExists(fullname); -} - -bool DOS_GetAllocationInfo(Bit8u drive,Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters) { - if (!drive) drive = DOS_GetDefaultDrive(); - else drive--; - if (drive >= DOS_DRIVES || !Drives[drive]) return false; - Bit16u _free_clusters; - Drives[drive]->AllocationInfo(_bytes_sector,_sectors_cluster,_total_clusters,&_free_clusters); - SegSet16(ds,RealSeg(dos.tables.mediaid)); - reg_bx=RealOff(dos.tables.mediaid+drive*2); - return true; -} - -bool DOS_SetDrive(Bit8u drive) { - if (Drives[drive]) { - DOS_SetDefaultDrive(drive); - return true; - } else { - return false; - } -} - -bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate) { - Bit32u handle=RealHandle(entry); - if (handle>=DOS_FILES) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - if (!Files[handle] || !Files[handle]->IsOpen()) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - }; - if (!Files[handle]->UpdateDateTimeFromHost()) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - } - *otime = Files[handle]->time; - *odate = Files[handle]->date; - return true; -} - -void DOS_SetupFiles (void) { - /* Setup the File Handles */ - Bit32u i; - for (i=0;i +#include +#include "dosbox.h" +#include "mem.h" +#include "cpu.h" +#include "dos_inc.h" +#include "drives.h" + +#define DOS_FILESTART 4 + + +DOS_File * Files[DOS_FILES]; +DOS_Drive * Drives[DOS_DRIVES]; +static Bit8u CurrentDrive=2; //Init on C: + + +Bit8u DOS_GetDefaultDrive(void) { + return CurrentDrive; +} + +void DOS_SetDefaultDrive(Bit8u drive) { + CurrentDrive=drive; +} + +bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { +//TODO Hope this is ok :) + char upname[DOS_PATHLENGTH]; + Bit32u r=0;Bit32u w=0;Bit32u namestart=0; + bool hasdrive=false; + *drive=CurrentDrive; + char tempdir[DOS_NAMELENGTH]; +//TODO Maybe check for illegal characters + while (name[r]!=0 && (r='a') && (c<='z')) {upname[w++]=c-32;continue;} + if ((c>='A') && (c<='Z')) {upname[w++]=c;continue;} + if ((c>='0') && (c<='9')) {upname[w++]=c;continue;} + switch (c) { + case ':': + if (hasdrive) { DOS_SetError(DOSERR_PATH_NOT_FOUND);return false; } + else hasdrive=true; + if ((upname[0]>='A') && (upname[0]<='Z')) { + *drive=upname[0]-'A'; + w=0; + } else { + DOS_SetError(DOSERR_PATH_NOT_FOUND);return false; + } + break; + case '/': + upname[w++]='\\'; + break; + case ' ': + break; + case '\\': case '$': case '#': case '@': case '(': case ')': + case '!': case '%': case '{': case '}': case '`': case '~': + case '_': case '-': case '.': case '*': case '?': case '&': + upname[w++]=c; + break; + default: + DOS_SetError(DOSERR_PATH_NOT_FOUND);return false; + break; + } + } + upname[w]=0; + /* This should get us an upcase filename and no incorrect chars */ + /* Now parse the new file name to make the final filename */ + if ((*drive>=26)) { + DOS_SetError(DOSERR_INVALID_DRIVE);return false; + }; + if (!Drives[*drive]) { + DOS_SetError(DOSERR_INVALID_DRIVE);return false; + }; + if (upname[0]!='\\') strcpy(fullname,Drives[*drive]->curdir); + else fullname[0]=0; + Bit32u lastdir=0;Bit32u t=0; + while (fullname[t]!=0) { + if ((fullname[t]=='\\') && (fullname[t+1]!=0))lastdir=t; + t++; + }; + r=0;w=0; + tempdir[0]=0; + bool stop=false; + while (!stop) { + if (upname[r]==0) stop=true; + if ((upname[r]=='\\') || (upname[r]==0)){ + tempdir[w]=0; + if (tempdir[0]==0) { w=0;r++;continue;} + if (strcmp(tempdir,".")==0) { + tempdir[0]=0; + w=0;r++; + continue; + } + if (strcmp(tempdir,"..")==0) { + fullname[lastdir]=0; + Bit32u t=0;lastdir=0; + while (fullname[t]!=0) { + if ((fullname[t]=='\\') && (fullname[t+1]!=0))lastdir=t; + t++; + } + tempdir[0]=0; + w=0;r++; + continue; + } + lastdir=strlen(fullname); + //TODO Maybe another check for correct type because of .... stuff + if (lastdir!=0) strcat(fullname,"\\"); + strcat(fullname,tempdir); + + tempdir[0]=0; + w=0;r++; + continue; + } + tempdir[w++]=upname[r++]; + } + return true; +} + +bool DOS_GetCurrentDir(Bit8u drive,Bit8u * buffer) { + if (drive==0) drive=DOS_GetDefaultDrive(); + else drive--; + if ((drive>DOS_DRIVES) || (!Drives[drive])) { + DOS_SetError(DOSERR_INVALID_DRIVE); + return false; + } + strcpy((char *) buffer,Drives[drive]->curdir); + return true; +} + +bool DOS_ChangeDir(char * dir) { + Bit8u drive;char fulldir[DOS_PATHLENGTH]; + if (!DOS_MakeName(dir,fulldir,&drive)) return false; + if (Drives[drive]->TestDir(fulldir)) { + strcpy(Drives[drive]->curdir,fulldir); + return true; + } else { + DOS_SetError(DOSERR_PATH_NOT_FOUND); + } + return false; +} + +bool DOS_MakeDir(char * dir) { + Bit8u drive;char fulldir[DOS_PATHLENGTH]; + if (!DOS_MakeName(dir,fulldir,&drive)) return false; + return Drives[drive]->MakeDir(fulldir); +} + +bool DOS_RemoveDir(char * dir) { + Bit8u drive;char fulldir[DOS_PATHLENGTH]; + if (!DOS_MakeName(dir,fulldir,&drive)) return false; + return Drives[drive]->RemoveDir(fulldir); +} + +bool DOS_Rename(char * oldname,char * newname) { + Bit8u driveold;char fullold[DOS_PATHLENGTH]; + Bit8u drivenew;char fullnew[DOS_PATHLENGTH]; + if (!DOS_MakeName(oldname,fullold,&driveold)) return false; + if (!DOS_MakeName(newname,fullnew,&drivenew)) return false; + //TODO Test for different drives maybe + if (Drives[drivenew]->Rename(fullold,fullnew)) return true; + DOS_SetError(DOSERR_FILE_NOT_FOUND); + return false; +}; + +bool DOS_FindFirst(char * search,Bit16u attr) { + Bit8u drive;char fullsearch[DOS_PATHLENGTH]; + if (!DOS_MakeName(search,fullsearch,&drive)) return false; + DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta); + dtablock->sattr=attr | DOS_ATTR_ARCHIVE; + dtablock->sdrive=drive; + return Drives[drive]->FindFirst(fullsearch,dtablock); +}; + +bool DOS_FindNext(void) { + DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta); + return Drives[dtablock->sdrive]->FindNext(dtablock); +}; + + +bool DOS_ReadFile(Bit16u entry,Bit8u * data,Bit16u * amount) { + Bit32u handle=RealHandle(entry); + if (handle>=DOS_FILES) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + if (!Files[handle]) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; +//TODO maybe another code :) +/* + if (!(Files[handle]->flags & OPEN_READ)) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + } +*/ + Bit16u toread=*amount; + bool ret=Files[handle]->Read(data,&toread); + *amount=toread; + return ret; +}; + +bool DOS_WriteFile(Bit16u entry,Bit8u * data,Bit16u * amount) { + Bit32u handle=RealHandle(entry); + if (handle>=DOS_FILES) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + if (!Files[handle]) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; +//TODO maybe another code :) +/* + if (!(Files[handle]->flags & OPEN_WRITE)) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + } +*/ + Bit16u towrite=*amount; + bool ret=Files[handle]->Write(data,&towrite); + *amount=towrite; + return ret; +}; + +bool DOS_SeekFile(Bit16u entry,Bit32u * pos,Bit32u type) { + Bit32u handle=RealHandle(entry); + if (handle>=DOS_FILES) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + if (!Files[handle]) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + return Files[handle]->Seek(pos,type); +}; + +bool DOS_CloseFile(Bit16u entry) { + Bit32u handle=RealHandle(entry); + if (handle>=DOS_FILES) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + if (!Files[handle]) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; +//TODO Figure this out with devices :) + + PSP * psp=(PSP *)real_off(dos.psp,0); + Bit8u * table=Real2Host(psp->file_table); + table[entry]=0xFF; + /* Devices won't allow themselves to be closed or killed */ + if (Files[handle]->Close()) { + delete Files[handle]; + Files[handle]=0; + } + return true; +} + +bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) { + char fullname[DOS_PATHLENGTH];Bit8u drive; + PSP * psp=(PSP *)real_off(dos.psp,0); + if (!DOS_MakeName(name,fullname,&drive)) return false; + /* Check for a free file handle */ + Bit8u handle=DOS_FILES;Bit8u i; + for (i=0;ifile_table); + *entry=0xff; + for (i=0;imax_files;i++) { + if (table[i]==0xFF) { + *entry=i; + break; + } + } + if (*entry==0xff) { + DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); + return false; + } + bool foundit=Drives[drive]->FileCreate(&Files[handle],fullname,attributes); + if (foundit) { + table[*entry]=handle; + return true; + } else { + return false; + } +} + +bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) { + /* First check for devices */ + PSP * psp=(PSP *)real_off(dos.psp,0); + Bit8u handle=DOS_FindDevice((char *)name); + bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i; + if (handle!=255) { + device=true; + } else { + /* First check if the name is correct */ + if (!DOS_MakeName(name,fullname,&drive)) return false; + /* Check for a free file handle */ + for (i=0;ifile_table); + *entry=0xff; + for (i=0;imax_files;i++) { + if (table[i]==0xFF) { + *entry=i; + break; + } + } + if (*entry==0xff) { + DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); + return false; + } + bool exists=false; + if (!device) exists=Drives[drive]->FileOpen(&Files[handle],fullname,flags); + if (exists || device ) { + table[*entry]=handle; + return true; + } else { + DOS_SetError(DOSERR_FILE_NOT_FOUND); + return false; + } +} + +bool DOS_UnlinkFile(char * name) { + char fullname[DOS_PATHLENGTH];Bit8u drive; + if (!DOS_MakeName(name,fullname,&drive)) return false; + return Drives[drive]->FileUnlink(fullname); +} + +bool DOS_GetFileAttr(char * name,Bit16u * attr) { + char fullname[DOS_PATHLENGTH];Bit8u drive; + if (!DOS_MakeName(name,fullname,&drive)) return false; + if (Drives[drive]->GetFileAttr(fullname,attr)) { + return true; + } else { + DOS_SetError(DOSERR_FILE_NOT_FOUND); + return false; + } +} + +bool DOS_Canonicalize(char * name,Bit8u * big) { +//TODO Add Better support for devices and shit but will it be needed i doubt it :) + Bit8u drive; + char fullname[DOS_PATHLENGTH]; + if (!DOS_MakeName(name,fullname,&drive)) return false; + big[0]=drive+'A'; + big[1]=':'; + big[2]='\\'; + strcpy((char *)&big[3],fullname); + return true; +}; + +bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) { + if (drive==0) drive=DOS_GetDefaultDrive(); + else drive--; + if ((drive>DOS_DRIVES) || (!Drives[drive])) { + DOS_SetError(DOSERR_INVALID_DRIVE); + return false; + } + return Drives[drive]->FreeSpace(bytes,sectors,clusters,free); +} + +bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) { + Bit8u handle=RealHandle(entry); + if (handle>=DOS_FILES) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + if (!Files[handle]) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + PSP * psp=(PSP *)real_off(dos.psp,0); + Bit8u * table=Real2Host(psp->file_table); + *newentry=0xff; + for (Bit16u i=0;imax_files;i++) { + if (table[i]==0xFF) { + *newentry=i; + break; + } + } + if (*newentry==0xff) { + DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); + return false; + } + table[*newentry]=handle; + return true; +}; + + +bool DOS_CreateTempFile(char * name,Bit16u * entry) { + +/* First add random crap to the end of the name and try to open */ + /* Todo maybe check for euhm existence of the path name */ + char * tempname; + tempname=name+strlen(name); + do { + Bit32u i; + for (i=0;i<8;i++) { + tempname[i]=(rand()%26)+'A'; + } + tempname[8]='.'; + for (i=9;i<12;i++) { + tempname[i]=(rand()%26)+'A'; + } + tempname[13]=0; + } while (!DOS_CreateFile(name,0,entry)); + return true; +} +#if 0 +void FCB_MakeName (DOS_FCB* fcb, char* outname, Bit8u* outdrive){ + char naam[15]; + Bit8u drive=fcb->Get_drive(); + if(drive!=0){ + naam[0]=(drive-1)+'A'; + naam[1]=':'; + naam[2]='\0';} + else{ + naam[0]='\0'; + }; + char temp[9]; + fcb->Get_filename(temp); + temp[9]='.'; + strncat(naam,temp,9); + char ext[3]; + fcb->Get_ext(ext); + if(drive!=0) { + strncat(&naam[11],ext,3); + naam[14]='\0'; + }else{ + strncat(&naam[9],ext,3); + naam[12]='\0'; + }; + DOS_MakeName(naam,outname, outdrive); + return; +} + + +bool DOS_FCBOpen(Bit16u seg,Bit16u offset) { + DOS_FCB fcb(seg,offset); + Bit8u drive; + char fullname[DOS_PATHLENGTH]; + FCB_MakeName (&fcb, fullname, &drive); + if(DOS_FileExists(fullname)==false) return false; + + + struct stat stat_block; + stat(fullname, &stat_block); + fcb.Set_filesize((Bit32u)stat_block.st_size); + Bit16u constant =0; + fcb.Set_current_block(constant); + constant=0x80; + fcb.Set_record_size(constant); + struct tm *time; + time=localtime(&stat_block.st_mtime); + + constant=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */ + fcb->Set_time(constant); + constant=((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday); + fcb->Set_date(constant); + fcb->Set_drive(drive +1); + return true; + } + +bool FCB_Close(void) +{ return true;} + +bool FCB_FindFirst(Bit16u seg,Bit16u offset) +{FCB* fcb = new FCB(seg,offset); + Bit8u drive; + Bitu i; + char fullname[DOS_PATHLENGTH]; + FCB_MakeName (fcb, fullname, &drive); + DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta); + if(Drives[drive]->FindFirst(fullname,dtablock)==false) return false; + + char naam[8]; + char ext[3]; + char * point=strrchr(dtablock->name,'.'); + if(point==NULL|| *(point+1)=='\0') { + ext[0]=' '; + ext[1]=' '; + ext[2]=' '; + }else + {strcpy(ext,point+1); + Bitu i; + i=strlen(point+1); + while(i!=3) ext[i-1]=' '; + } + + if(point!=NULL) *point='\0'; + + strcpy (naam,dtablock->name); + i=strlen(dtablock->name); + while(i!=8) naam[i-1]=' '; + FCB* fcbout= new FCB((PhysPt)Real2Host(dos.dta)); + fcbout->Set_drive(drive +1); + fcbout->Set_filename(naam); + fcbout->Set_ext(ext); + return true; + } +bool FCB_FindNext(Bit16u seg,Bit16u offset) +{FCB* fcb = new FCB(seg,offset); + Bit8u drive; + Bitu i; + char fullname[DOS_PATHLENGTH]; + FCB_MakeName (fcb, fullname, &drive); + DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta); + if(Drives[dtablock->sdrive]->FindNext(dtablock)==false) return false; + char naam[8]; + char ext[3]; + char * point=strrchr(dtablock->name,'.'); + if(point==NULL|| *(point+1)=='\0') { + ext[0]=' '; + ext[1]=' '; + ext[2]=' '; + }else + {strcpy(ext,point+1); + Bitu i; + i=strlen(point+1); + while(i!=3) ext[i-1]=' '; + } + + if(point!=NULL) *point='\0'; + + strcpy (naam,dtablock->name); + i=strlen(dtablock->name); + while(i!=8) naam[i-1]=' '; + FCB* fcbout= new FCB((PhysPt)Real2Host(dos.dta)); + fcbout->Set_drive(drive +1); + fcbout->Set_filename(naam); + fcbout->Set_ext(ext); + return true; + } + +#endif + +bool DOS_FileExists(char * name) { + Bit16u handle; + if (DOS_OpenFile(name,0,&handle)) { + DOS_CloseFile(handle); + return true; + } + return false; +} + + +bool DOS_SetDrive(Bit8u drive) { + if (Drives[drive]) { + DOS_SetDefaultDrive(drive); + return true; + + } else { + return false; + } +}; + + +void DOS_SetupFiles (void) { + /* Setup the File Handles */ + Bit32u i; + for (i=0;i -#include "dosbox.h" -#include "callback.h" -#include "mem.h" -#include "regs.h" -#include "dos_inc.h" - -bool DOS_IOCTL(void) { - Bitu handle=0;Bit8u drive=0; - /* calls 0-4,6,7,10,12,16 use a file handle */ - if ((reg_al<4) || (reg_al==0x06) || (reg_al==0x07) || (reg_al==0x0a) || (reg_al==0x0c) || (reg_al==0x10)) { - handle=RealHandle(reg_bx); - if (handle>=DOS_FILES) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - } - if (!Files[handle]) { - DOS_SetError(DOSERR_INVALID_HANDLE); - return false; - } - } else if (reg_al<0x12) { /* those use a diskdrive except 0x0b */ - if (reg_al!=0x0b) { - drive=reg_bl;if (!drive) drive = DOS_GetDefaultDrive();else drive--; - if( !(( drive < DOS_DRIVES ) && Drives[drive]) ) { - DOS_SetError(DOSERR_INVALID_DRIVE); - return false; - } - } - } else { - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:IOCTL Call %2X unhandled",reg_al); - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - } - switch(reg_al) { - case 0x00: /* Get Device Information */ - if (Files[handle]->GetInformation() & 0x8000) { //Check for device - reg_dx=Files[handle]->GetInformation(); - } else { - Bit8u hdrive=Files[handle]->GetDrive(); - if (hdrive==0xff) { - LOG(LOG_IOCTL,LOG_NORMAL)("00:No drive set"); - hdrive=2; // defaulting to C: - } - /* return drive number in lower 5 bits for block devices */ - reg_dx=(Files[handle]->GetInformation()&0xffe0)|hdrive; - } - reg_ax=reg_dx; //Destroyed officially - return true; - case 0x01: /* Set Device Information */ - if (reg_dh != 0) { - DOS_SetError(DOSERR_DATA_INVALID); - return false; - } else { - if (Files[handle]->GetInformation() & 0x8000) { //Check for device - reg_al=(Bit8u)(Files[handle]->GetInformation() & 0xff); - } else { - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - } - } - return true; - case 0x02: /* Read from Device Control Channel */ - if (Files[handle]->GetInformation() & 0xc000) { - /* is character device with IOCTL support */ - PhysPt bufptr=PhysMake(SegValue(ds),reg_dx); - Bit16u retcode=0; - if (((DOS_Device*)(Files[handle]))->ReadFromControlChannel(bufptr,reg_cx,&retcode)) { - reg_ax=retcode; - return true; - } - } - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - case 0x03: /* Write to Device Control Channel */ - if (Files[handle]->GetInformation() & 0xc000) { - /* is character device with IOCTL support */ - PhysPt bufptr=PhysMake(SegValue(ds),reg_dx); - Bit16u retcode=0; - if (((DOS_Device*)(Files[handle]))->WriteToControlChannel(bufptr,reg_cx,&retcode)) { - reg_ax=retcode; - return true; - } - } - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - case 0x06: /* Get Input Status */ - if (Files[handle]->GetInformation() & 0x8000) { //Check for device - reg_al=(Files[handle]->GetInformation() & 0x40) ? 0x0 : 0xff; - } else { // FILE - Bit32u oldlocation=0; - Files[handle]->Seek(&oldlocation, DOS_SEEK_CUR); - Bit32u endlocation=0; - Files[handle]->Seek(&endlocation, DOS_SEEK_END); - if(oldlocation < endlocation){//Still data available - reg_al=0xff; - } else { - reg_al=0x0; //EOF or beyond - } - Files[handle]->Seek(&oldlocation, DOS_SEEK_SET); //restore filelocation - LOG(LOG_IOCTL,LOG_NORMAL)("06:Used Get Input Status on regular file with handle %d",handle); - } - return true; - case 0x07: /* Get Output Status */ - LOG(LOG_IOCTL,LOG_NORMAL)("07:Fakes output status is ready for handle %d",handle); - reg_al=0xff; - return true; - case 0x08: /* Check if block device removable */ - /* cdrom drives and drive a&b are removable */ - if (drive < 2) reg_ax=0; - else if (!Drives[drive]->isRemovable()) reg_ax=1; - else { - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - } - return true; - case 0x09: /* Check if block device remote */ - if (Drives[drive]->isRemote()) { - reg_dx=0x1000; // device is remote - // undocumented bits always clear - } else { - reg_dx=0x0802; // Open/Close supported; 32bit access supported (any use? fixes Fable installer) - // undocumented bits from device attribute word - // TODO Set bit 9 on drives that don't support direct I/O - } - reg_ax=0x300; - return true; - case 0x0B: /* Set sharing retry count */ - if (reg_dx==0) { - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - } - return true; - case 0x0D: /* Generic block device request */ - { - if (Drives[drive]->isRemovable()) { - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - } - PhysPt ptr = SegPhys(ds)+reg_dx; - switch (reg_cl) { - case 0x60: /* Get Device parameters */ - mem_writeb(ptr ,0x03); // special function - mem_writeb(ptr+1,(drive>=2)?0x05:0x14); // fixed disc(5), 1.44 floppy(14) - mem_writew(ptr+2,drive>=2); // nonremovable ? - mem_writew(ptr+4,0x0000); // num of cylinders - mem_writeb(ptr+6,0x00); // media type (00=other type) - // drive parameter block following - mem_writeb(ptr+7,drive); // drive - mem_writeb(ptr+8,0x00); // unit number - mem_writed(ptr+0x1f,0xffffffff); // next parameter block - break; - case 0x46: - case 0x66: /* Volume label */ - { - char const* bufin=Drives[drive]->GetLabel(); - char buffer[11] ={' '}; - - char const* find_ext=strchr(bufin,'.'); - if (find_ext) { - Bitu size=(Bitu)(find_ext-bufin); - if (size>8) size=8; - memcpy(buffer,bufin,size); - find_ext++; - memcpy(buffer+size,find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext)); - } else { - memcpy(buffer,bufin,(strlen(bufin) > 8) ? 8 : strlen(bufin)); - } - - char buf2[8]={ 'F','A','T','1','6',' ',' ',' '}; - if(drive<2) buf2[4] = '2'; //FAT12 for floppies - - mem_writew(ptr+0,0); // 0 - mem_writed(ptr+2,0x1234); //Serial number - MEM_BlockWrite(ptr+6,buffer,11);//volumename - if(reg_cl == 0x66) MEM_BlockWrite(ptr+0x11, buf2,8);//filesystem - } - break; - default : - LOG(LOG_IOCTL,LOG_ERROR)("DOS:IOCTL Call 0D:%2X Drive %2X unhandled",reg_cl,drive); - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - } - return true; - } - case 0x0E: /* Get Logical Drive Map */ - if (Drives[drive]->isRemovable()) { - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - return false; - } - reg_al = 0; /* Only 1 logical drive assigned */ - return true; - default: - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:IOCTL Call %2X unhandled",reg_al); - DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); - break; - } - return false; -} - - -bool DOS_GetSTDINStatus(void) { - Bit32u handle=RealHandle(STDIN); - if (handle==0xFF) return false; - if (Files[handle] && (Files[handle]->GetInformation() & 64)) return false; - return true; -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "dosbox.h" +#include "callback.h" +#include "mem.h" +#include "cpu.h" +#include "dos_inc.h" + +#define MAX_DEVICE 20 +static DOS_File * dos_devices[MAX_DEVICE]; + +bool DOS_IOCTL(Bit8u call,Bit16u entry) { + Bit32u handle=RealHandle(entry); + if (handle>=DOS_FILES) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + if (!Files[handle]) { + DOS_SetError(DOSERR_INVALID_HANDLE); + return false; + }; + switch(reg_al) { + case 0x00: /* Get Device Information */ + reg_dx=Files[handle]->GetInformation(); + return true; + case 0x07: /* Get Output Status */ + LOG_DEBUG("DOS:IOCTL:07:Fakes output status is ready for handle %d",handle); + reg_al=0xff; + return true; + default: + LOG_ERROR("DOS:IOCTL Call %2X Handle %2X unhandled",reg_al,handle); + return false; + }; + return false; +}; + + +bool DOS_GetSTDINStatus(void) { + Bit32u handle=RealHandle(STDIN); + if (Files[handle]->GetInformation() & 64) return false; + return true; +}; + diff --git a/src/dos/dos_keyboard_layout.cpp b/src/dos/dos_keyboard_layout.cpp deleted file mode 100644 index 75fb832..0000000 --- a/src/dos/dos_keyboard_layout.cpp +++ /dev/null @@ -1,1292 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos_keyboard_layout.cpp,v 1.21 2009/04/01 18:30:41 c2woody Exp $ */ - -#include "dosbox.h" -#include "bios.h" -#include "bios_disk.h" -#include "setup.h" -#include "support.h" -#include "../ints/int10.h" -#include "regs.h" -#include "callback.h" -#include "mapper.h" -#include "drives.h" -#include "dos_inc.h" - -#include "dos_codepages.h" -#include "dos_keyboard_layout_data.h" - -#if defined (WIN32) -#include -#endif - - -static FILE* OpenDosboxFile(const char* name) { - Bit8u drive; - char fullname[DOS_PATHLENGTH]; - - localDrive* ldp=0; - // try to build dos name - if (DOS_MakeName(name,fullname,&drive)) { - try { - // try to open file on mounted drive first - ldp=dynamic_cast(Drives[drive]); - if (ldp) { - FILE *tmpfile=ldp->GetSystemFilePtr(fullname, "rb"); - if (tmpfile != NULL) return tmpfile; - } - } - catch(...) {} - } - FILE *tmpfile=fopen(name, "rb"); - return tmpfile; -} - - -class keyboard_layout { -public: - keyboard_layout() { - this->reset(); - language_codes=NULL; - use_foreign_layout=false; - sprintf(current_keyboard_file_name, "none"); - }; - - ~keyboard_layout(); - - // read in a codepage from a .cpi-file - Bitu read_codepage_file(const char* codepage_file_name, Bit32s codepage_id); - Bit16u extract_codepage(const char* keyboard_file_name); - // read in a keyboard layout from a .kl-file - Bitu read_keyboard_file(const char* keyboard_file_name, Bit32s req_cp); - - // call layout_key to apply the current language layout - bool layout_key(Bitu key, Bit8u flags1, Bit8u flags2, Bit8u flags3); - - Bitu switch_keyboard_layout(const char* new_layout, keyboard_layout* &created_layout); - void switch_foreign_layout(); - const char* get_layout_name(); - const char* main_language_code(); - - -private: - static const Bit8u layout_pages=12; - Bit16u current_layout[(MAX_SCAN_CODE+1)*layout_pages]; - struct { - Bit16u required_flags,forbidden_flags; - Bit16u required_userflags,forbidden_userflags; - } current_layout_planes[layout_pages-4]; - Bit8u additional_planes,used_lock_modifiers; - - // diacritics table - Bit8u diacritics[2048]; - Bit16u diacritics_entries; - Bit16u diacritics_character; - Bit16u user_keys; - - char current_keyboard_file_name[256]; - bool use_foreign_layout; - - // language code storage used when switching layouts - char** language_codes; - Bitu language_code_count; - - void reset(); - void read_keyboard_file(Bit32s specific_layout); - Bitu read_keyboard_file(const char* keyboard_file_name, Bit32s specific_layout, Bit32s requested_codepage); - bool map_key(Bitu key, Bit16u layouted_key, bool is_command, bool is_keypair); -}; - - -keyboard_layout::~keyboard_layout() { - if (language_codes) { - for (Bitu i=0; iread_keyboard_file(keyboard_file_name, -1, req_cp); -} - -// switch to a different layout -void keyboard_layout::read_keyboard_file(Bit32s specific_layout) { - if (strcmp(current_keyboard_file_name,"none")) - this->read_keyboard_file(current_keyboard_file_name, specific_layout, dos.loaded_codepage); -} - -static Bit32u read_kcl_file(const char* kcl_file_name, const char* layout_id, bool first_id_only) { - FILE* tempfile = OpenDosboxFile(kcl_file_name); - if (tempfile==0) return 0; - - static Bit8u rbuf[8192]; - - // check ID-bytes of file - Bit32u dr=(Bit32u)fread(rbuf, sizeof(Bit8u), 7, tempfile); - if ((dr<7) || (rbuf[0]!=0x4b) || (rbuf[1]!=0x43) || (rbuf[2]!=0x46)) { - fclose(tempfile); - return 0; - } - - fseek(tempfile, 7+rbuf[6], SEEK_SET); - - for (;;) { - Bit32u cur_pos=(Bit32u)(ftell(tempfile)); - dr=(Bit32u)fread(rbuf, sizeof(Bit8u), 5, tempfile); - if (dr<5) break; - Bit16u len=host_readw(&rbuf[0]); - - Bit8u data_len=rbuf[2]; - - char lng_codes[258]; - fseek(tempfile, -2, SEEK_CUR); - // get all language codes for this layout - for (Bitu i=0; ikcl_data_size) break; - Bit32u cur_pos=dpos; - Bit16u len=host_readw(&kcl_data[dpos]); - Bit8u data_len=kcl_data[dpos+2]; - dpos+=5; - - char lng_codes[258]; - // get all language codes for this layout - for (Bitu i=0; ikcl_data_size) break; - char lc=(char)kcl_data[dpos]; - dpos++; - i++; - if (lc==',') break; - lng_codes[lcpos++]=lc; - } - lng_codes[lcpos]=0; - if (strcasecmp(lng_codes, layout_id)==0) { - // language ID found, return position - return cur_pos; - } - if (first_id_only) break; - if (lcnum) { - sprintf(&lng_codes[lcpos],"%d",lcnum); - if (strcasecmp(lng_codes, layout_id)==0) { - // language ID found, return position - return cur_pos; - } - } - dpos+=2; - } - dpos=cur_pos+3+len; - } - return 0; -} - -Bitu keyboard_layout::read_keyboard_file(const char* keyboard_file_name, Bit32s specific_layout, Bit32s requested_codepage) { - this->reset(); - - if (specific_layout==-1) strcpy(current_keyboard_file_name, keyboard_file_name); - if (!strcmp(keyboard_file_name,"none")) return KEYB_NOERROR; - - static Bit8u read_buf[65535]; - Bit32u read_buf_size, read_buf_pos, bytes_read; - Bit32u start_pos=5; - - char nbuf[512]; - read_buf_size = 0; - sprintf(nbuf, "%s.kl", keyboard_file_name); - FILE* tempfile = OpenDosboxFile(nbuf); - if (tempfile==NULL) { - // try keyboard layout libraries next - if ((start_pos=read_kcl_file("keyboard.sys",keyboard_file_name,true))) { - tempfile = OpenDosboxFile("keyboard.sys"); - } else if ((start_pos=read_kcl_file("keybrd2.sys",keyboard_file_name,true))) { - tempfile = OpenDosboxFile("keybrd2.sys"); - } else if ((start_pos=read_kcl_file("keybrd3.sys",keyboard_file_name,true))) { - tempfile = OpenDosboxFile("keybrd3.sys"); - } else if ((start_pos=read_kcl_file("keyboard.sys",keyboard_file_name,false))) { - tempfile = OpenDosboxFile("keyboard.sys"); - } else if ((start_pos=read_kcl_file("keybrd2.sys",keyboard_file_name,false))) { - tempfile = OpenDosboxFile("keybrd2.sys"); - } else if ((start_pos=read_kcl_file("keybrd3.sys",keyboard_file_name,false))) { - tempfile = OpenDosboxFile("keybrd3.sys"); - } else if ((start_pos=read_kcl_data(layout_keyboardsys,33196,keyboard_file_name,true))) { - read_buf_size=0; - for (Bitu ct=start_pos+2; ct<33196; ct++) read_buf[read_buf_size++]=layout_keyboardsys[ct]; - } else if ((start_pos=read_kcl_data(layout_keybrd2sys,25431,keyboard_file_name,true))) { - read_buf_size=0; - for (Bitu ct=start_pos+2; ct<25431; ct++) read_buf[read_buf_size++]=layout_keybrd2sys[ct]; - } else if ((start_pos=read_kcl_data(layout_keybrd3sys,27122,keyboard_file_name,true))) { - read_buf_size=0; - for (Bitu ct=start_pos+2; ct<27122; ct++) read_buf[read_buf_size++]=layout_keybrd3sys[ct]; - } else if ((start_pos=read_kcl_data(layout_keyboardsys,33196,keyboard_file_name,false))) { - read_buf_size=0; - for (Bitu ct=start_pos+2; ct<33196; ct++) read_buf[read_buf_size++]=layout_keyboardsys[ct]; - } else if ((start_pos=read_kcl_data(layout_keybrd2sys,25431,keyboard_file_name,false))) { - read_buf_size=0; - for (Bitu ct=start_pos+2; ct<25431; ct++) read_buf[read_buf_size++]=layout_keybrd2sys[ct]; - } else if ((start_pos=read_kcl_data(layout_keybrd3sys,27122,keyboard_file_name,false))) { - read_buf_size=0; - for (Bitu ct=start_pos+2; ct<27122; ct++) read_buf[read_buf_size++]=layout_keybrd3sys[ct]; - } else { - LOG(LOG_BIOS,LOG_ERROR)("Keyboard layout file %s not found",keyboard_file_name); - return KEYB_FILENOTFOUND; - } - if (tempfile) { - fseek(tempfile, start_pos+2, SEEK_SET); - read_buf_size=(Bit32u)fread(read_buf, sizeof(Bit8u), 65535, tempfile); - fclose(tempfile); - } - start_pos=0; - } else { - // check ID-bytes of file - Bit32u dr=(Bit32u)fread(read_buf, sizeof(Bit8u), 4, tempfile); - if ((dr<4) || (read_buf[0]!=0x4b) || (read_buf[1]!=0x4c) || (read_buf[2]!=0x46)) { - LOG(LOG_BIOS,LOG_ERROR)("Invalid keyboard layout file %s",keyboard_file_name); - return KEYB_INVALIDFILE; - } - - fseek(tempfile, 0, SEEK_SET); - read_buf_size=(Bit32u)fread(read_buf, sizeof(Bit8u), 65535, tempfile); - fclose(tempfile); - } - - Bit8u data_len,submappings; - data_len=read_buf[start_pos++]; - - language_codes=new char*[data_len]; - language_code_count=0; - // get all language codes for this layout - for (Bitu i=0; i(layout_pages-4)) additional_planes=(layout_pages-4); - - // seek to plane descriptor - read_buf_pos=start_pos+0x14+submappings*8; - for (Bit16u cplane=0; cplane0)) { - // add all available mappings - for (Bit16u addmap=0; addmapadditional_planes+2) break; - Bitu charptr=read_buf_pos+addmap*((read_buf[read_buf_pos-2]&0x80)?2:1); - Bit16u kchar=read_buf[charptr]; - - if (kchar!=0) { // key remapped - if (read_buf[read_buf_pos-2]&0x80) kchar|=read_buf[charptr+1]<<8; // scancode/char pair - // overwrite mapping - current_layout[scan*layout_pages+addmap]=kchar; - // clear command bit - current_layout[scan*layout_pages+layout_pages-2]&=~(1<use_foreign_layout=true; - return KEYB_NOERROR; - } - - LOG(LOG_BIOS,LOG_ERROR)("No matching keyboard layout found in %s",keyboard_file_name); - - // reset layout data (might have been changed by general layout) - this->reset(); - - return KEYB_LAYOUTNOTFOUND; -} - -bool keyboard_layout::layout_key(Bitu key, Bit8u flags1, Bit8u flags2, Bit8u flags3) { - if (key>MAX_SCAN_CODE) return false; - if (!this->use_foreign_layout) return false; - - bool is_special_pair=(current_layout[key*layout_pages+layout_pages-1] & 0x80)==0x80; - - if ((((flags1&used_lock_modifiers)&0x7c)==0) && ((flags3&2)==0)) { - // check if shift/caps is active: - // (left_shift OR right_shift) XOR (key_affected_by_caps AND caps_locked) - if ((((flags1&2)>>1) | (flags1&1)) ^ (((current_layout[key*layout_pages+layout_pages-1] & 0x40) & (flags1 & 0x40))>>6)) { - // shift plane - if (current_layout[key*layout_pages+1]!=0) { - // check if command-bit is set for shift plane - bool is_command=(current_layout[key*layout_pages+layout_pages-2]&2)!=0; - if (this->map_key(key, current_layout[key*layout_pages+1], - is_command, is_special_pair)) return true; - } - } else { - // normal plane - if (current_layout[key*layout_pages]!=0) { - // check if command-bit is set for normal plane - bool is_command=(current_layout[key*layout_pages+layout_pages-2]&1)!=0; - if (this->map_key(key, current_layout[key*layout_pages], - is_command, is_special_pair)) return true; - } - } - } - - // calculate current flags - Bit16u current_flags=(flags1&0x7f) | (((flags2&3) | (flags3&0xc))<<8); - if (flags1&3) current_flags|=0x4000; // either shift key active - if (flags3&2) current_flags|=0x1000; // e0 prefixed - - // check all planes if flags fit - for (Bit16u cplane=0; cplane>(cplane+2))&1)!=0; - if (this->map_key(key, current_layout[key*layout_pages+2+cplane], - is_command, is_special_pair)) return true; - } else break; // abort plane checking - } - } - - if (diacritics_character>0) { - // ignore state-changing keys - switch(key) { - case 0x1d: /* Ctrl Pressed */ - case 0x2a: /* Left Shift Pressed */ - case 0x36: /* Right Shift Pressed */ - case 0x38: /* Alt Pressed */ - case 0x3a: /* Caps Lock */ - case 0x45: /* Num Lock */ - case 0x46: /* Scroll Lock */ - break; - default: - if (diacritics_character-200>=diacritics_entries) { - diacritics_character=0; - return true; - } - Bit16u diacritics_start=0; - // search start of subtable - for (Bit16u i=0; i=200) && (key_command<235)) { - // diacritics command - diacritics_character=key_command; - if (diacritics_character-200>=diacritics_entries) diacritics_character=0; - return true; - } else if ((key_command>=120) && (key_command<140)) { - // switch layout command - this->read_keyboard_file(key_command-119); - return true; - } else if ((key_command>=180) && (key_command<188)) { - // switch user key off - user_keys&=~(1<<(key_command-180)); - return true; - } else if ((key_command>=188) && (key_command<196)) { - // switch user key on - user_keys|=(1<<(key_command-188)); - return true; - } else if (key_command==160) return true; // nop command - } else { - // non-command - if (diacritics_character>0) { - if (diacritics_character-200>=diacritics_entries) diacritics_character = 0; - else { - Bit16u diacritics_start=0; - // search start of subtable - for (Bit16u i=0; i(&nbuf[strsz-1])); - if (plc=='I') { - // try CPX-extension as well - nbuf[strsz-1]='X'; - tempfile=OpenDosboxFile(nbuf); - } else if (plc=='X') { - // try CPI-extension as well - nbuf[strsz-1]='I'; - tempfile=OpenDosboxFile(nbuf); - } - } - } - - static Bit8u cpi_buf[65536]; - Bit32u cpi_buf_size=0,size_of_cpxdata=0;; - bool upxfound=false; - Bit16u found_at_pos=5; - if (tempfile==NULL) { - // check if build-in codepage is available - switch (codepage_id) { - case 437: case 850: case 852: case 853: case 857: case 858: - for (Bitu bct=0; bct<6322; bct++) cpi_buf[bct]=font_ega_cpx[bct]; - cpi_buf_size=6322; - break; - case 771: case 772: case 808: case 855: case 866: case 872: - for (Bitu bct=0; bct<5455; bct++) cpi_buf[bct]=font_ega3_cpx[bct]; - cpi_buf_size=5455; - break; - case 737: case 851: case 869: - for (Bitu bct=0; bct<5720; bct++) cpi_buf[bct]=font_ega5_cpx[bct]; - cpi_buf_size=5720; - break; - default: - return KEYB_INVALIDCPFILE; - break; - } - upxfound=true; - found_at_pos=0x29; - size_of_cpxdata=cpi_buf_size; - } else { - Bit32u dr=(Bit32u)fread(cpi_buf, sizeof(Bit8u), 5, tempfile); - // check if file is valid - if (dr<5) { - LOG(LOG_BIOS,LOG_ERROR)("Codepage file %s invalid",cp_filename); - return KEYB_INVALIDCPFILE; - } - // check if non-compressed cpi file - if ((cpi_buf[0]!=0xff) || (cpi_buf[1]!=0x46) || (cpi_buf[2]!=0x4f) || - (cpi_buf[3]!=0x4e) || (cpi_buf[4]!=0x54)) { - // check if dr-dos custom cpi file - if ((cpi_buf[0]==0x7f) && (cpi_buf[1]!=0x44) && (cpi_buf[2]!=0x52) && - (cpi_buf[3]!=0x46) && (cpi_buf[4]!=0x5f)) { - LOG(LOG_BIOS,LOG_ERROR)("Codepage file %s has unsupported DR-DOS format",cp_filename); - return KEYB_INVALIDCPFILE; - } - // check if compressed cpi file - Bit8u next_byte=0; - for (Bitu i=0; i<100; i++) { - fread(&next_byte, sizeof(Bit8u), 1, tempfile); found_at_pos++; - while (next_byte==0x55) { - fread(&next_byte, sizeof(Bit8u), 1, tempfile); found_at_pos++; - if (next_byte==0x50) { - fread(&next_byte, sizeof(Bit8u), 1, tempfile); found_at_pos++; - if (next_byte==0x58) { - fread(&next_byte, sizeof(Bit8u), 1, tempfile); found_at_pos++; - if (next_byte==0x21) { - // read version ID - fread(&next_byte, sizeof(Bit8u), 1, tempfile); - found_at_pos++; - upxfound=true; - break; - } - } - } - } - if (upxfound) break; - } - if (!upxfound) { - LOG(LOG_BIOS,LOG_ERROR)("Codepage file %s invalid: %x",cp_filename,cpi_buf[0]); - return KEYB_INVALIDCPFILE; - } else { - if (next_byte<10) E_Exit("UPX-compressed cpi file, but upx-version too old"); - - // read in compressed CPX-file - fseek(tempfile, 0, SEEK_SET); - size_of_cpxdata=(Bitu)fread(cpi_buf, sizeof(Bit8u), 65536, tempfile); - } - } else { - // standard uncompressed cpi-file - fseek(tempfile, 0, SEEK_SET); - cpi_buf_size=(Bit32u)fread(cpi_buf, sizeof(Bit8u), 65536, tempfile); - } - } - - if (upxfound) { - if (size_of_cpxdata>0xfe00) E_Exit("Size of cpx-compressed data too big"); - - found_at_pos+=19; - // prepare for direct decompression - cpi_buf[found_at_pos]=0xcb; - - Bit16u seg=0; - Bit16u size=0x1500; - if (!DOS_AllocateMemory(&seg,&size)) E_Exit("Not enough free low memory to unpack data"); - MEM_BlockWrite((seg<<4)+0x100,cpi_buf,size_of_cpxdata); - - // setup segments - Bit16u save_ds=SegValue(ds); - Bit16u save_es=SegValue(es); - Bit16u save_ss=SegValue(ss); - Bit32u save_esp=reg_esp; - SegSet16(ds,seg); - SegSet16(es,seg); - SegSet16(ss,seg+0x1000); - reg_esp=0xfffe; - - // let UPX unpack the file - CALLBACK_RunRealFar(seg,0x100); - - SegSet16(ds,save_ds); - SegSet16(es,save_es); - SegSet16(ss,save_ss); - reg_esp=save_esp; - - // get unpacked content - MEM_BlockRead((seg<<4)+0x100,cpi_buf,65536); - cpi_buf_size=65536; - - DOS_FreeMemory(seg); - } - - - start_pos=host_readd(&cpi_buf[0x13]); - number_of_codepages=host_readw(&cpi_buf[start_pos]); - start_pos+=4; - - // search if codepage is provided by file - for (Bit16u test_codepage=0; test_codepagetype==M_TEXT) && (IS_EGAVGA_ARCH)) { - if (IS_VGA_ARCH) INT10_LoadFont(Real2Phys(int10.rom.font_16),true,256,0,0,16); - else INT10_LoadFont(Real2Phys(int10.rom.font_14),true,256,0,0,14); - } - INT10_SetupRomMemoryChecksum(); - - return KEYB_NOERROR; - } - - start_pos=host_readd(&cpi_buf[start_pos]); - start_pos+=2; - } - - LOG(LOG_BIOS,LOG_ERROR)("Codepage %i not found",codepage_id); - - return KEYB_INVALIDCPFILE; -} - -Bitu keyboard_layout::switch_keyboard_layout(const char* new_layout, keyboard_layout*& created_layout) { - if (strncasecmp(new_layout,"US",2)) { - // switch to a foreign layout - char tbuf[256]; - strcpy(tbuf, new_layout); - size_t newlen=strlen(tbuf); - - bool language_code_found=false; - // check if language code is present in loaded foreign layout - for (Bitu i=0; iuse_foreign_layout) { - // switch to foreign layout - this->use_foreign_layout=true; - diacritics_character=0; - LOG(LOG_BIOS,LOG_NORMAL)("Switched to layout %s",tbuf); - } - } else { - keyboard_layout * temp_layout=new keyboard_layout(); - Bitu req_codepage=temp_layout->extract_codepage(new_layout); - Bitu kerrcode=temp_layout->read_keyboard_file(new_layout, req_codepage); - if (kerrcode) { - delete temp_layout; - return kerrcode; - } - // ...else keyboard layout loaded successfully, change codepage accordingly - kerrcode=temp_layout->read_codepage_file("auto", req_codepage); - if (kerrcode) { - delete temp_layout; - return kerrcode; - } - // Everything went fine, switch to new layout - created_layout=temp_layout; - } - } else if (this->use_foreign_layout) { - // switch to the US layout - this->use_foreign_layout=false; - diacritics_character=0; - LOG(LOG_BIOS,LOG_NORMAL)("Switched to US layout"); - } - return KEYB_NOERROR; -} - -void keyboard_layout::switch_foreign_layout() { - this->use_foreign_layout=!this->use_foreign_layout; - diacritics_character=0; - if (this->use_foreign_layout) LOG(LOG_BIOS,LOG_NORMAL)("Switched to foreign layout"); - else LOG(LOG_BIOS,LOG_NORMAL)("Switched to US layout"); -} - -const char* keyboard_layout::get_layout_name() { - // get layout name (language ID or NULL if default layout) - if (use_foreign_layout) { - if (strcmp(current_keyboard_file_name,"none") != 0) { - return (const char*)¤t_keyboard_file_name; - } - } - return NULL; -} - -const char* keyboard_layout::main_language_code() { - if (language_codes) { - return language_codes[0]; - } - return NULL; -} - - -static keyboard_layout* loaded_layout=NULL; - -// CTRL-ALT-F2 switches between foreign and US-layout using this function -/* static void switch_keyboard_layout(bool pressed) { - if (!pressed) - return; - if (loaded_layout) loaded_layout->switch_foreign_layout(); -} */ - -// called by int9-handler -bool DOS_LayoutKey(Bitu key, Bit8u flags1, Bit8u flags2, Bit8u flags3) { - if (loaded_layout) return loaded_layout->layout_key(key, flags1, flags2, flags3); - else return false; -} - -Bitu DOS_LoadKeyboardLayout(const char * layoutname, Bit32s codepage, const char * codepagefile) { - keyboard_layout * temp_layout=new keyboard_layout(); - // try to read the layout for the specified codepage - Bitu kerrcode=temp_layout->read_keyboard_file(layoutname, codepage); - if (kerrcode) { - delete temp_layout; - return kerrcode; - } - // ...else keyboard layout loaded successfully, change codepage accordingly - kerrcode=temp_layout->read_codepage_file(codepagefile, codepage); - if (kerrcode) { - delete temp_layout; - return kerrcode; - } - // Everything went fine, switch to new layout - loaded_layout=temp_layout; - return KEYB_NOERROR; -} - -Bitu DOS_SwitchKeyboardLayout(const char* new_layout) { - if (loaded_layout) { - keyboard_layout* changed_layout=NULL; - Bitu ret_code=loaded_layout->switch_keyboard_layout(new_layout, changed_layout); - if (changed_layout) { - // Remove old layout, activate new layout - delete loaded_layout; - loaded_layout=changed_layout; - } - return ret_code; - } else return 0xff; -} - -// get currently loaded layout name (NULL if no layout is loaded) -const char* DOS_GetLoadedLayout(void) { - if (loaded_layout) { - return loaded_layout->get_layout_name(); - } - return NULL; -} - - -class DOS_KeyboardLayout: public Module_base { -public: - DOS_KeyboardLayout(Section* configuration):Module_base(configuration){ - Section_prop * section=static_cast(configuration); - dos.loaded_codepage=437; // US codepage already initialized - loaded_layout=new keyboard_layout(); - - const char * layoutname=section->Get_string("keyboardlayout"); - - Bits wants_dos_codepage = -1; - if (!strncmp(layoutname,"auto",4)) { -#if defined (WIN32) - WORD cur_kb_layout = LOWORD(GetKeyboardLayout(0)); - WORD cur_kb_subID = 0; - char layoutID_string[KL_NAMELENGTH]; - if (GetKeyboardLayoutName(layoutID_string)) { - if (strlen(layoutID_string) == 8) { - int cur_kb_layout_by_name = ConvHexWord((char*)&layoutID_string[4]); - layoutID_string[4] = 0; - int subID = ConvHexWord((char*)&layoutID_string[0]); - if ((cur_kb_layout_by_name>0) && (cur_kb_layout_by_name<65536)) { - // use layout ID extracted from the layout string - cur_kb_layout = (WORD)cur_kb_layout_by_name; - } - if ((subID>=0) && (subID<100)) { - // use sublanguage ID extracted from the layout string - cur_kb_subID = (WORD)subID; - } - } - } - // try to match emulated keyboard layout with host-keyboardlayout - // codepage 437 (standard) is preferred - switch (cur_kb_layout) { -/* case 1026: - layoutname = "bg241"; - break; */ - case 1029: - layoutname = "cz243"; - break; - case 1030: - layoutname = "dk"; - break; - case 1031: - layoutname = "gr"; - wants_dos_codepage = 437; - break; - case 1033: - // US - return; - case 1032: - layoutname = "gk"; - break; - case 1034: - layoutname = "sp"; - wants_dos_codepage = 437; - break; - case 1035: - layoutname = "su"; - wants_dos_codepage = 437; - break; - case 1036: - layoutname = "fr"; - wants_dos_codepage = 437; - break; - case 1038: - if (cur_kb_subID==1) layoutname = "hu"; - else layoutname = "hu208"; - break; - case 1039: - layoutname = "is161"; - break; - case 1040: - layoutname = "it"; - wants_dos_codepage = 437; - break; - case 1043: - layoutname = "nl"; - wants_dos_codepage = 437; - break; - case 1044: - layoutname = "no"; - break; - case 1045: - layoutname = "pl"; - break; - case 1046: - layoutname = "br"; - wants_dos_codepage = 437; - break; -/* case 1048: - layoutname = "ro446"; - break; */ - case 1049: - layoutname = "ru"; - wants_dos_codepage = 437; - break; - case 1050: - layoutname = "hr"; - break; - case 1051: - layoutname = "sk"; - break; -/* case 1052: - layoutname = "sq448"; - break; */ - case 1053: - layoutname = "sv"; - wants_dos_codepage = 437; - break; - case 1055: - layoutname = "tr"; - break; - case 1058: - layoutname = "ur"; - wants_dos_codepage = 437; - break; - case 1059: - layoutname = "bl"; - break; - case 1060: - layoutname = "si"; - break; - case 1061: - layoutname = "et"; - break; -/* case 1062: - layoutname = "lv"; - break; */ -/* case 1063: - layoutname = "lt221"; - break; */ -/* case 1064: - layoutname = "tj"; - break; - case 1066: - layoutname = "vi"; - break; - case 1067: - layoutname = "hy"; - break; */ - case 2055: - layoutname = "sg"; - wants_dos_codepage = 437; - break; - case 2070: - layoutname = "po"; - break; - case 4108: - layoutname = "sf"; - wants_dos_codepage = 437; - break; - default: - break; - } -#endif - } - - bool extract_codepage = true; - if (wants_dos_codepage>0) { - if ((loaded_layout->read_codepage_file("auto", (Bitu)wants_dos_codepage)) == KEYB_NOERROR) { - // preselected codepage was successfully loaded - extract_codepage = false; - } - } - if (extract_codepage) { - // try to find a good codepage for the requested layout - Bitu req_codepage = loaded_layout->extract_codepage(layoutname); - loaded_layout->read_codepage_file("auto", req_codepage); - } - -/* if (strncmp(layoutname,"auto",4) && strncmp(layoutname,"none",4)) { - LOG_MSG("Loading DOS keyboard layout %s ...",layoutname); - } */ - if (loaded_layout->read_keyboard_file(layoutname, dos.loaded_codepage)) { - if (strncmp(layoutname,"auto",4)) { - LOG_MSG("Error loading keyboard layout %s",layoutname); - } - } else { - const char* lcode = loaded_layout->main_language_code(); - if (lcode) { - LOG_MSG("DOS keyboard layout loaded with main language code %s for layout %s",lcode,layoutname); - } - } - } - - ~DOS_KeyboardLayout(){ - if ((dos.loaded_codepage!=437) && (CurMode->type==M_TEXT)) { - INT10_ReloadRomFonts(); - dos.loaded_codepage=437; // US codepage - } - if (loaded_layout) { - delete loaded_layout; - loaded_layout=NULL; - } - } -}; - -static DOS_KeyboardLayout* test; - -void DOS_KeyboardLayout_ShutDown(Section* /*sec*/) { - delete test; -} - -void DOS_KeyboardLayout_Init(Section* sec) { - test = new DOS_KeyboardLayout(sec); - sec->AddDestroyFunction(&DOS_KeyboardLayout_ShutDown,true); -// MAPPER_AddHandler(switch_keyboard_layout,MK_f2,MMOD1|MMOD2,"sw_layout","Switch Layout"); -} diff --git a/src/dos/dos_keyboard_layout_data.h b/src/dos/dos_keyboard_layout_data.h deleted file mode 100644 index 937c5e4..0000000 --- a/src/dos/dos_keyboard_layout_data.h +++ /dev/null @@ -1,5393 +0,0 @@ -/* - * Copyright (C) Henrique Peron - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -/* This file contains data of .KL-files. They have been generated - by Henrique Peron using FreeDOS KC and are combined into .SYS files. */ - -/* KC: compiles keyboard descriptors in KEY language to a KeybCB, - wrapped in a KL file (for use of FD-KEYB 2.X) - Copyright (C) 2004 by Aitor SANTAMARIA_MERINO */ - - -Bit8u layout_keyboardsys[33196] = { -0x4b, 0x43, 0x46, 0x00, 0x01, 0x01, 0x2e, 0x48, 0x65, 0x6e, 0x72, 0x69, 0x71, 0x75, 0x65, 0x20, -0x50, 0x65, 0x72, 0x6f, 0x6e, 0xff, 0x44, 0x4f, 0x53, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x70, 0x61, -0x67, 0x65, 0x73, 0x20, 0x2d, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x23, 0x31, -0x20, 0x6f, 0x66, 0x20, 0x33, 0xa0, 0x03, 0x0e, 0x00, 0x00, 0x42, 0x45, 0x2c, 0x78, 0x00, 0x42, -0x45, 0x2c, 0x78, 0x00, 0x46, 0x52, 0x06, 0x04, 0x2c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, -0x00, 0x00, 0x5a, 0x03, 0x0f, 0x03, 0x16, 0x03, 0x00, 0x00, 0x5b, 0x03, 0x5e, 0x01, 0x96, 0x01, -0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x16, 0x03, 0x00, 0x00, 0xb5, 0x01, 0x13, 0x02, 0x1e, 0x02, -0x00, 0x00, 0x37, 0x75, 0x6d, 0x02, 0xba, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, -0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x42, 0x00, 0x26, 0x31, 0x7c, -0x03, 0x42, 0x00, 0x82, 0x32, 0x40, 0x04, 0x42, 0x00, 0x22, 0x33, 0x23, 0x05, 0x41, 0x00, 0x27, -0x34, 0x06, 0x41, 0x00, 0x28, 0x35, 0x07, 0x42, 0x00, 0xf5, 0x36, 0x5e, 0x08, 0x41, 0x00, 0x8a, -0x37, 0x09, 0x41, 0x00, 0x21, 0x38, 0x0a, 0x42, 0x00, 0x87, 0x39, 0x7b, 0x0b, 0x42, 0x00, 0x85, -0x30, 0x7d, 0x0c, 0x41, 0x00, 0x29, 0xf8, 0x0d, 0x44, 0x0c, 0x2d, 0x5f, 0x00, 0x00, 0x1f, 0x10, -0xc5, 0x00, 0x61, 0x1e, 0x41, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x01, 0x1e, 0x00, 0x1e, 0x11, 0xc5, -0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x12, 0x41, 0x00, -0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, -0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x42, 0x03, 0xca, 0xcc, 0x5b, 0x1b, 0x42, 0x00, 0x24, -0x2a, 0x5d, 0x1e, 0xc5, 0x00, 0x71, 0x10, 0x51, 0x10, 0x00, 0x10, 0x00, 0x10, 0x11, 0x10, 0x00, -0x10, 0x27, 0xc5, 0x00, 0x6d, 0x32, 0x4d, 0x32, 0x00, 0x32, 0x00, 0x32, 0x0d, 0x32, 0x00, 0x32, -0x28, 0x43, 0x0c, 0x97, 0x25, 0xcb, 0xcb, 0x29, 0x41, 0x00, 0xfd, 0xfc, 0x2b, 0x43, 0x0c, 0xe6, -0x9c, 0xc8, 0xc8, 0x2c, 0xc5, 0x00, 0x77, 0x11, 0x57, 0x11, 0x00, 0x11, 0x00, 0x11, 0x17, 0x11, -0x00, 0x11, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x44, 0x08, 0x2c, -0x3f, 0x5c, 0x00, 0x1c, 0x33, 0x42, 0x00, 0x3b, 0x2e, 0x3c, 0x34, 0x42, 0x00, 0x3a, 0x2f, 0x3e, -0x35, 0x43, 0x0c, 0x3d, 0x2b, 0xc9, 0xc9, 0x39, 0x00, 0x00, 0x20, 0x56, 0x44, 0x08, 0x3c, 0x3e, -0x5c, 0x00, 0x1c, 0x00, 0x10, 0xc5, 0x00, 0x61, 0x1e, 0x41, 0x1e, 0x91, 0x1e, 0x92, 0x1e, 0x01, -0x1e, 0x00, 0x1e, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x18, 0x43, 0x03, 0x00, 0x00, 0xab, 0xac, -0x1f, 0x42, 0x03, 0x00, 0x00, 0xe1, 0x2c, 0xc5, 0x00, 0x77, 0x11, 0x57, 0x11, 0xae, 0x11, 0x00, -0x11, 0x17, 0x11, 0x00, 0x11, 0x2d, 0x42, 0x03, 0x00, 0x00, 0xaf, 0x00, 0x60, 0x0b, 0x61, 0x85, -0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, -0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, -0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x27, 0x0f, 0x61, 0xa0, -0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, 0x80, -0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0x22, 0x0d, 0x61, 0x84, -0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, -0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x00, 0x07, 0x41, 0x02, 0x15, 0x00, 0x29, 0x41, -0x03, 0x00, 0xa0, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, -0x20, 0x60, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, -0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x09, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, -0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x43, 0x80, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, -0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, -0x20, 0x22, 0x00, 0x05, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x10, 0xc5, 0x00, 0x61, 0x1e, 0x41, 0x1e, -0x86, 0x1e, 0x8f, 0x1e, 0x01, 0x1e, 0x00, 0x1e, 0x11, 0xc5, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x91, -0x2c, 0x92, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x12, 0x43, 0x03, 0x00, 0x00, 0xe4, 0xe5, 0x18, 0x43, -0x03, 0x00, 0x00, 0xab, 0xac, 0x2b, 0x41, 0x03, 0x00, 0xa0, 0x2c, 0xc5, 0x00, 0x77, 0x11, 0x57, -0x11, 0xae, 0x11, 0x00, 0x11, 0x17, 0x11, 0x00, 0x11, 0x2d, 0x42, 0x03, 0x00, 0x00, 0xaf, 0x00, -0x60, 0x07, 0x61, 0x85, 0x65, 0x8a, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x55, 0xeb, 0x20, 0x60, -0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, -0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, -0x27, 0x05, 0x63, 0x87, 0x65, 0x82, 0x43, 0x80, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0b, 0x61, 0x84, -0x65, 0x89, 0x69, 0x8b, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x55, 0x9a, -0x59, 0xf3, 0x20, 0x22, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, -0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, -0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, -0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0f, 0x61, 0xa0, -0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, 0x80, -0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, -0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, -0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0xf7, 0xe7, 0x01, 0x09, 0x00, 0x00, 0x42, 0x52, 0x2c, -0x13, 0x01, 0x42, 0x52, 0x04, 0x03, 0x2c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x5a, 0x03, 0x5d, 0x01, 0x66, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00, -0xb5, 0x01, 0xf9, 0x00, 0x12, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, -0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x02, 0x03, 0x00, 0x00, 0xfb, 0x03, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x04, 0x02, 0x03, 0x00, -0x00, 0xfc, 0x05, 0x02, 0x03, 0x00, 0x00, 0x9c, 0x06, 0x02, 0x03, 0x00, 0x00, 0xbd, 0x07, 0x02, -0x03, 0x00, 0xcc, 0xaa, 0x08, 0x02, 0x03, 0x00, 0x00, 0x2f, 0x09, 0x02, 0x03, 0x00, 0x00, 0x7c, -0x0a, 0x02, 0x03, 0x00, 0x00, 0x3f, 0x0b, 0x02, 0x03, 0x00, 0x00, 0xf8, 0x0d, 0x02, 0x03, 0x00, -0x00, 0xf5, 0x10, 0x42, 0x03, 0x00, 0x00, 0x2f, 0x11, 0x42, 0x03, 0x00, 0x00, 0x3f, 0x12, 0x42, -0x00, 0x65, 0x45, 0xf8, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, -0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x01, 0x03, 0xcb, 0xc8, 0x1b, 0x03, 0x00, -0x5b, 0x7b, 0xa6, 0x1b, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x41, 0x00, 0x87, 0x80, 0x28, 0x03, -0x07, 0xc9, 0xca, 0x00, 0x1e, 0x29, 0x01, 0x00, 0x27, 0x22, 0x2b, 0x03, 0x00, 0x5d, 0x7d, 0xa7, -0x1d, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x35, 0x03, 0x00, 0x3b, 0x3a, 0x5c, 0x1c, 0x39, 0x00, 0x00, -0x20, 0x73, 0x02, 0x00, 0x2f, 0x3f, 0xf8, 0x7e, 0x01, 0x00, 0x2e, 0x2e, 0x00, 0x02, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0x9b, 0x0d, -0x02, 0x03, 0x00, 0x00, 0x15, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, -0x75, 0x97, 0x20, 0x60, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, -0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x07, 0x61, 0xa0, 0x65, 0x82, -0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, -0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, -0x00, 0x12, 0x44, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, -0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, -0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, -0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, -0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, -0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, -0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, -0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, -0x00, 0xfa, 0x56, 0x01, 0x04, 0x12, 0x01, 0x42, 0x52, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xcf, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, -0x00, 0xd6, 0x00, 0x00, 0x00, 0xb5, 0x01, 0x79, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x03, 0x00, 0xca, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, -0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, -0x00, 0x6f, 0x4f, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x28, 0x02, 0x03, 0xcb, 0xcc, 0xf9, 0x29, 0x01, -0x03, 0xc8, 0xc9, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x39, 0x00, 0x00, -0x20, 0x00, 0x28, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, -0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, -0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x09, 0x61, -0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x43, 0x80, 0x45, 0x90, 0x20, -0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, -0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, -0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, -0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, -0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, -0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x27, -0x0f, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, -0xb5, 0x43, 0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0x22, -0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, -0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0xc6, 0x08, 0x04, 0x13, 0x00, 0x00, -0x43, 0x46, 0x2c, 0x00, 0x00, 0x43, 0x41, 0x2c, 0x3a, 0x00, 0x43, 0x46, 0x2c, 0x3a, 0x00, 0x43, -0x41, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0x2a, -0x01, 0x31, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x31, 0x01, 0x00, 0x00, 0x5f, 0x03, 0x70, -0x03, 0xa7, 0x03, 0x00, 0x00, 0x5b, 0x03, 0xa0, 0x01, 0xd4, 0x01, 0x00, 0x00, 0x46, 0x75, 0x45, -0x02, 0xaf, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, -0x00, 0x00, 0xf1, 0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x01, 0x00, 0x2f, 0x9c, 0x05, -0x02, 0x03, 0x00, 0x00, 0xbd, 0x06, 0x02, 0x03, 0x00, 0x00, 0xcf, 0x07, 0x02, 0x01, 0x00, 0x3f, -0xaa, 0x08, 0x02, 0x03, 0x00, 0x00, 0xdd, 0x09, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x0a, 0x02, 0x03, -0x00, 0x00, 0xfc, 0x0b, 0x02, 0x03, 0x00, 0x00, 0xac, 0x0c, 0x02, 0x03, 0x00, 0x00, 0xab, 0x0d, -0x02, 0x03, 0x00, 0x00, 0xf3, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, -0x41, 0x00, 0x75, 0x55, 0x17, 0x42, 0x00, 0x69, 0x49, 0xfb, 0x18, 0x42, 0x00, 0x6f, 0x4f, 0xf5, -0x19, 0x42, 0x03, 0x00, 0x00, 0xf4, 0x1a, 0x02, 0x03, 0xc9, 0xc9, 0x5b, 0x1b, 0x02, 0x03, 0xcc, -0xcb, 0x5d, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x28, 0x02, 0x03, -0xc8, 0xc8, 0x7b, 0x29, 0x04, 0x08, 0x23, 0x7c, 0x5c, 0x00, 0x1c, 0x2b, 0x02, 0x00, 0x3c, 0x3e, -0x7d, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x2f, 0x42, 0x03, 0x00, 0x00, 0xae, 0x30, 0x42, 0x03, 0x00, -0x00, 0xaf, 0x31, 0x42, 0x03, 0x00, 0x00, 0xf8, 0x32, 0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x02, -0x01, 0x00, 0x27, 0xee, 0x34, 0x02, 0x01, 0x00, 0x2e, 0x2d, 0x35, 0x42, 0x04, 0x82, 0x90, 0xca, -0x39, 0x00, 0x00, 0x20, 0x56, 0x02, 0x00, 0xae, 0xaf, 0xf8, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, -0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, -0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, -0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, -0x20, 0x5e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, -0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, -0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, -0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, -0x00, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x1e, -0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x24, 0x03, 0x03, 0x00, 0x00, 0xa4, 0xa5, 0x26, 0x03, 0x03, -0x00, 0x00, 0xab, 0xac, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, -0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x5e, 0x0b, 0x61, -0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, -0xe2, 0x55, 0xea, 0x20, 0x5e, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, -0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, -0x27, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, -0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x2c, 0x03, 0x63, -0x87, 0x43, 0x80, 0x20, 0x2c, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x15, 0x03, 0x03, 0x00, -0x00, 0xe7, 0xe8, 0x17, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x19, 0x03, 0x03, 0x00, 0x00, 0xab, 0xac, -0x1e, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x26, 0x03, 0x03, 0x00, 0x00, 0xd0, 0xd1, 0x2b, 0x01, -0x03, 0xce, 0xcf, 0x33, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x34, 0x02, 0x07, 0x00, 0x00, 0xcd, 0x00, -0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, -0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, -0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, -0x27, 0x0b, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, -0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x20, 0x27, 0x22, 0x09, 0x65, 0x89, 0x69, 0x8b, 0x75, 0x81, -0x79, 0x98, 0x45, 0xd3, 0x49, 0xd8, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x2c, 0x0d, 0x61, 0x84, -0x65, 0x9e, 0x69, 0xa6, 0x6f, 0x94, 0x75, 0xa8, 0x41, 0x8e, 0x45, 0x9f, 0x49, 0xa7, 0x4f, 0x99, -0x55, 0xa9, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, 0x2d, 0x0b, 0x61, 0xc6, 0x65, 0xec, 0x69, 0xf4, -0x6f, 0xe4, 0x6e, 0xa4, 0x41, 0xc7, 0x45, 0xed, 0x49, 0xf6, 0x4f, 0xe5, 0x4e, 0xa5, 0x20, 0x2d, -0x3c, 0x0b, 0x61, 0xfa, 0x65, 0xf1, 0x69, 0xe1, 0x6f, 0xfc, 0x75, 0xf7, 0x41, 0xfb, 0x45, 0xf2, -0x49, 0xee, 0x4f, 0xfd, 0x55, 0xef, 0x20, 0x3c, 0x3e, 0x0b, 0x61, 0x86, 0x65, 0xbd, 0x69, 0xf9, -0x6f, 0x9b, 0x75, 0xb8, 0x41, 0x8f, 0x45, 0xbe, 0x49, 0xdd, 0x4f, 0x9d, 0x55, 0xad, 0x20, 0x3e, -0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0x9b, 0x06, 0x02, 0x03, 0x00, 0x00, 0x98, 0x08, 0x02, 0x03, -0x00, 0x00, 0xa0, 0x0a, 0x02, 0x03, 0x00, 0x00, 0xa6, 0x0d, 0x02, 0x03, 0x00, 0x00, 0xad, 0x17, -0x42, 0x07, 0x00, 0x00, 0xa0, 0x18, 0x42, 0x03, 0x00, 0x00, 0x8f, 0x19, 0x42, 0x03, 0x00, 0x00, -0x86, 0x33, 0x02, 0x03, 0x00, 0x00, 0xa7, 0x00, 0x60, 0x07, 0x61, 0x85, 0x65, 0x8a, 0x75, 0x97, -0x41, 0x8e, 0x45, 0x91, 0x55, 0x9d, 0x20, 0x60, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, -0x6f, 0x93, 0x75, 0x96, 0x41, 0x84, 0x45, 0x92, 0x49, 0xa8, 0x4f, 0x99, 0x55, 0x9e, 0x20, 0x5e, -0xa1, 0x05, 0x65, 0x82, 0x6f, 0xa2, 0x75, 0xa3, 0x45, 0x90, 0x20, 0xa1, 0xa4, 0x07, 0x65, 0x89, -0x69, 0x8b, 0x75, 0x81, 0x45, 0x94, 0x49, 0x95, 0x55, 0x9a, 0x20, 0xa4, 0xa5, 0x03, 0x63, 0x87, -0x43, 0x80, 0x20, 0xa5, 0x00, 0x9a, 0x44, 0x07, 0x09, 0xbd, 0x01, 0x43, 0x46, 0x2c, 0xbd, 0x01, -0x43, 0x41, 0x0a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, -0x1b, 0x01, 0xfc, 0x02, 0x00, 0x00, 0x5a, 0x03, 0x2a, 0x01, 0xfc, 0x02, 0x00, 0x00, 0x52, 0x03, -0x0e, 0x02, 0xfc, 0x02, 0x00, 0x00, 0x52, 0x03, 0x17, 0x02, 0xfc, 0x02, 0x00, 0x00, 0x5f, 0x03, -0x83, 0x03, 0x7b, 0x04, 0x00, 0x00, 0x5f, 0x03, 0xa0, 0x03, 0x7b, 0x04, 0x00, 0x00, 0x5b, 0x03, -0xba, 0x05, 0xb1, 0x06, 0x00, 0x00, 0x5b, 0x03, 0xd0, 0x05, 0xb1, 0x06, 0x00, 0x00, 0x46, 0x75, -0xc8, 0x04, 0xfd, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, -0x01, 0x00, 0x3f, 0x08, 0x02, 0x03, 0x00, 0x00, 0x7b, 0x09, 0x02, 0x03, 0x00, 0x00, 0x7d, 0x0a, -0x04, 0x0b, 0x00, 0x00, 0x5b, 0x00, 0x1b, 0x0b, 0x04, 0x0b, 0x00, 0x00, 0x5d, 0x00, 0x1d, 0x0d, -0x02, 0x03, 0x00, 0x00, 0xaa, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, -0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x04, -0x0f, 0xca, 0xcc, 0xc8, 0x00, 0x1e, 0x1b, 0x42, 0x00, 0x87, 0x80, 0x7e, 0x1e, 0x41, 0x00, 0x61, -0x41, 0x27, 0x02, 0x03, 0x00, 0x00, 0xf8, 0x28, 0x41, 0x00, 0x8a, 0xd4, 0x29, 0x04, 0x08, 0x2f, -0x5c, 0x7c, 0x00, 0x1c, 0x2b, 0x41, 0x00, 0x85, 0xb7, 0x2c, 0x42, 0x03, 0x00, 0x00, 0xae, 0x2d, -0x42, 0x03, 0x00, 0x00, 0xaf, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x33, -0x02, 0x01, 0x00, 0x27, 0x3c, 0x34, 0x02, 0x01, 0x00, 0x22, 0x3e, 0x35, 0x41, 0x00, 0x82, 0x90, -0x39, 0x00, 0x00, 0x20, 0x56, 0x44, 0x0c, 0x97, 0xeb, 0x00, 0x00, 0x1c, 0x00, 0x12, 0x42, 0x03, -0x00, 0x00, 0xd5, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x02, 0x01, 0x00, 0xfb, -0xad, 0x03, 0x01, 0x02, 0xfd, 0xa0, 0x04, 0x01, 0x00, 0xfc, 0x9c, 0x05, 0x01, 0x00, 0xac, 0xcf, -0x06, 0x01, 0x02, 0xab, 0xa0, 0x07, 0x01, 0x02, 0xf3, 0xa0, 0x08, 0x10, 0x00, 0x00, 0x09, 0x10, -0x00, 0x00, 0x0a, 0x01, 0x00, 0xf1, 0xf1, 0x0b, 0x10, 0x00, 0x00, 0x0c, 0x01, 0x00, 0xa8, 0xa8, -0x0d, 0x01, 0x03, 0xce, 0xa0, 0x10, 0x10, 0x00, 0x00, 0x11, 0x10, 0x00, 0x00, 0x12, 0x10, 0x00, -0x00, 0x13, 0x01, 0x00, 0xf4, 0xa9, 0x14, 0x10, 0x00, 0x00, 0x15, 0x01, 0x00, 0xbe, 0xbe, 0x16, -0x10, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x18, 0x41, 0x00, 0x9b, 0x9d, 0x19, 0x41, 0x00, 0xe7, -0xe8, 0x1a, 0x01, 0x03, 0xa0, 0xcd, 0x1b, 0x01, 0x01, 0xc9, 0xee, 0x1e, 0x41, 0x00, 0x91, 0x92, -0x1f, 0x01, 0x00, 0xe1, 0xf5, 0x20, 0x41, 0x00, 0xd0, 0xd1, 0x21, 0x01, 0x00, 0xa6, 0xa6, 0x22, -0x10, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x25, 0x10, 0x00, 0x00, 0x26, -0x10, 0x00, 0x00, 0x27, 0x01, 0x03, 0xcb, 0xa0, 0x28, 0x10, 0x00, 0x00, 0x29, 0x01, 0x00, 0x2d, -0xc4, 0x2b, 0x10, 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x2d, 0x10, 0x00, 0x00, 0x2e, 0x01, 0x00, -0xbd, 0xb8, 0x2f, 0x10, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x32, 0x01, -0x00, 0xe6, 0xa7, 0x33, 0x01, 0x00, 0x9e, 0x9e, 0x34, 0x01, 0x00, 0xfa, 0xf6, 0x35, 0x01, 0x02, -0x2f, 0xa0, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x01, 0x02, 0xdd, 0xa0, 0x00, -0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x02, 0x01, 0x00, 0xfb, 0xad, 0x03, 0x01, -0x02, 0xfd, 0xa0, 0x04, 0x01, 0x00, 0xfc, 0x9c, 0x05, 0x01, 0x00, 0xac, 0xcf, 0x06, 0x01, 0x02, -0xab, 0xa0, 0x07, 0x01, 0x02, 0xf3, 0xa0, 0x08, 0x10, 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x0a, -0x01, 0x00, 0xf1, 0xf1, 0x0b, 0x10, 0x00, 0x00, 0x0c, 0x01, 0x00, 0xa8, 0xa8, 0x0d, 0x01, 0x03, -0xce, 0xa0, 0x10, 0x10, 0x00, 0x00, 0x11, 0x10, 0x00, 0x00, 0x12, 0x10, 0x00, 0x00, 0x13, 0x01, -0x00, 0xf4, 0xa9, 0x14, 0x10, 0x00, 0x00, 0x15, 0x01, 0x00, 0xbe, 0xbe, 0x16, 0x10, 0x00, 0x00, -0x17, 0x01, 0x01, 0xa0, 0xd5, 0x18, 0x41, 0x00, 0x9b, 0x9d, 0x19, 0x41, 0x00, 0xe7, 0xe8, 0x1a, -0x01, 0x03, 0xa0, 0xcd, 0x1b, 0x01, 0x01, 0xc9, 0xee, 0x1e, 0x41, 0x00, 0x91, 0x92, 0x1f, 0x01, -0x00, 0xe1, 0xf5, 0x20, 0x41, 0x00, 0xd0, 0xd1, 0x21, 0x01, 0x00, 0xa6, 0xa6, 0x22, 0x10, 0x00, -0x00, 0x23, 0x10, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x25, 0x10, 0x00, 0x00, 0x26, 0x10, 0x00, -0x00, 0x27, 0x01, 0x03, 0xcb, 0xa0, 0x28, 0x10, 0x00, 0x00, 0x29, 0x01, 0x00, 0x2d, 0xc4, 0x2b, -0x10, 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x2d, 0x10, 0x00, 0x00, 0x2e, 0x01, 0x00, 0xbd, 0xb8, -0x2f, 0x10, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x32, 0x01, 0x00, 0xe6, -0xa7, 0x33, 0x01, 0x00, 0x9e, 0x9e, 0x34, 0x01, 0x00, 0xfa, 0xf6, 0x35, 0x01, 0x02, 0x2f, 0xa0, -0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x56, 0x01, 0x02, 0xdd, 0xa0, 0x00, 0x60, 0x0b, -0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, -0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, -0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, -0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0d, -0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, -0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, -0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, -0x55, 0x9a, 0x20, 0xf9, 0xf8, 0x03, 0x61, 0x86, 0x41, 0x8f, 0x20, 0xf8, 0xf7, 0x03, 0x63, 0x87, -0x43, 0x80, 0x20, 0xf7, 0x00, 0x1a, 0x01, 0x03, 0x00, 0xc9, 0x28, 0x41, 0x00, 0x8a, 0x91, 0x2a, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x2b, 0x41, 0x00, 0x85, 0x8e, 0x56, 0x41, 0x00, 0x97, -0x9d, 0x00, 0x02, 0x10, 0x00, 0x00, 0x03, 0x01, 0x02, 0xfd, 0xa0, 0x04, 0x01, 0x00, 0xa6, 0x9c, -0x05, 0x01, 0x00, 0xac, 0x98, 0x06, 0x01, 0x02, 0xab, 0xa0, 0x07, 0x01, 0x02, 0xad, 0xa0, 0x08, -0x10, 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x0a, 0x01, 0x00, 0xf1, 0xf1, 0x0b, 0x10, 0x00, 0x00, -0x0c, 0x10, 0x00, 0x00, 0x0d, 0x01, 0x03, 0xcc, 0xa0, 0x10, 0x10, 0x00, 0x00, 0x11, 0x10, 0x00, -0x00, 0x12, 0x10, 0x00, 0x00, 0x13, 0x01, 0x02, 0x86, 0xa0, 0x14, 0x10, 0x00, 0x00, 0x15, 0x10, -0x00, 0x00, 0x16, 0x10, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x18, 0x10, 0x00, 0x00, 0x19, 0x10, -0x00, 0x00, 0x1a, 0x01, 0x01, 0xa0, 0xf8, 0x1b, 0x01, 0x00, 0x7e, 0xa7, 0x1e, 0x10, 0x00, 0x00, -0x1f, 0x01, 0x00, 0xe1, 0x8f, 0x20, 0x10, 0x00, 0x00, 0x21, 0x10, 0x00, 0x00, 0x22, 0x10, 0x00, -0x00, 0x23, 0x10, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x25, 0x10, 0x00, 0x00, 0x26, 0x10, 0x00, -0x00, 0x27, 0x01, 0x03, 0xcb, 0xa0, 0x28, 0x10, 0x00, 0x00, 0x29, 0x01, 0x00, 0x2d, 0xc4, 0x2b, -0x10, 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x2d, 0x10, 0x00, 0x00, 0x2e, 0x01, 0x02, 0x9b, 0xa0, -0x2f, 0x10, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x32, 0x01, 0x02, 0xe6, -0xa0, 0x33, 0x10, 0x00, 0x00, 0x34, 0x01, 0x00, 0xfa, 0xf6, 0x35, 0x01, 0x02, 0x2f, 0xa0, 0x36, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x56, 0x01, 0x02, 0xa0, 0xa0, 0x00, 0x60, 0x07, 0x61, -0x85, 0x65, 0x8a, 0x75, 0x97, 0x41, 0x8e, 0x45, 0x91, 0x55, 0x9d, 0x20, 0x60, 0xa4, 0x07, 0x65, -0x89, 0x69, 0x8b, 0x75, 0x81, 0x45, 0x94, 0x49, 0x95, 0x55, 0x9a, 0x20, 0xa4, 0x5e, 0x0b, 0x61, -0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0x84, 0x45, 0x92, 0x49, 0xa8, 0x4f, -0x99, 0x55, 0x9e, 0x20, 0x5e, 0xa1, 0x05, 0x65, 0x82, 0x6f, 0xa2, 0x75, 0xa3, 0x45, 0x90, 0x20, -0xa1, 0xa5, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xa5, 0x00, 0x07, 0x03, 0x03, 0x00, 0x00, 0xe7, -0xe8, 0x12, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x18, 0x03, 0x03, 0x00, 0x00, 0xab, 0xac, 0x1b, 0x02, -0x07, 0x00, 0x00, 0xc9, 0x1e, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x26, 0x03, 0x03, 0x00, 0x00, -0xd0, 0xd1, 0x33, 0x02, 0x07, 0x00, 0xcb, 0xcd, 0x34, 0x02, 0x07, 0x00, 0xce, 0xcf, 0x00, 0x60, -0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, -0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x0b, 0x61, 0xc6, 0x65, 0xec, 0x69, 0xf4, 0x6f, -0xe4, 0x6e, 0xa4, 0x41, 0xc7, 0x45, 0xed, 0x49, 0xf6, 0x4f, 0xe5, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, -0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, -0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x27, 0x0b, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, -0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x20, 0x27, 0x22, -0x09, 0x65, 0x89, 0x69, 0x8b, 0x75, 0x81, 0x79, 0x98, 0x45, 0xd3, 0x49, 0xd8, 0x55, 0x9a, 0x59, -0xf3, 0x20, 0x22, 0x3c, 0x0b, 0x61, 0xfa, 0x65, 0xf1, 0x69, 0xe1, 0x6f, 0xfc, 0x75, 0xf7, 0x41, -0xfb, 0x45, 0xf2, 0x49, 0xee, 0x4f, 0xfd, 0x55, 0xef, 0x20, 0x3c, 0x22, 0x0b, 0x61, 0x84, 0x65, -0x9e, 0x69, 0xa6, 0x6f, 0x94, 0x75, 0xa8, 0x41, 0x8e, 0x45, 0x9f, 0x49, 0xa7, 0x4f, 0x99, 0x55, -0xa9, 0x20, 0x22, 0x3e, 0x0b, 0x61, 0x86, 0x65, 0xbd, 0x69, 0xf9, 0x6f, 0x9b, 0x75, 0xb8, 0x41, -0x8f, 0x45, 0xbe, 0x49, 0xdd, 0x4f, 0x9d, 0x55, 0xad, 0x20, 0x3e, 0x00, 0x12, 0x42, 0x03, 0x00, -0x00, 0xd5, 0x18, 0x43, 0x03, 0x00, 0x00, 0xab, 0xac, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x7f, 0x00, 0x02, 0x01, 0x00, 0xfb, 0xad, 0x03, 0x01, 0x02, 0xfd, 0xa0, 0x04, 0x01, 0x00, 0xfc, -0x9c, 0x05, 0x01, 0x01, 0xa0, 0xcf, 0x06, 0x10, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x08, 0x10, -0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x0a, 0x01, 0x00, 0xf1, 0xf1, 0x0b, 0x10, 0x00, 0x00, 0x0c, -0x01, 0x00, 0xa8, 0xa8, 0x0d, 0x01, 0x03, 0xce, 0xa0, 0x10, 0x10, 0x00, 0x00, 0x11, 0x10, 0x00, -0x00, 0x12, 0x10, 0x00, 0x00, 0x13, 0x01, 0x00, 0xf4, 0xa9, 0x14, 0x10, 0x00, 0x00, 0x15, 0x01, -0x00, 0xbe, 0xbe, 0x16, 0x10, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x18, 0x41, 0x00, 0x9b, 0x9d, -0x19, 0x41, 0x00, 0xe7, 0xe8, 0x1a, 0x01, 0x03, 0xa0, 0xcd, 0x1b, 0x01, 0x01, 0xc9, 0xee, 0x1e, -0x41, 0x00, 0x91, 0x92, 0x1f, 0x01, 0x00, 0xe1, 0xf5, 0x20, 0x41, 0x00, 0xd0, 0xd1, 0x21, 0x01, -0x00, 0xa6, 0xa6, 0x22, 0x10, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x25, -0x10, 0x00, 0x00, 0x26, 0x10, 0x00, 0x00, 0x27, 0x01, 0x03, 0xcb, 0xa0, 0x28, 0x10, 0x00, 0x00, -0x29, 0x01, 0x00, 0x2d, 0xc4, 0x2b, 0x10, 0x00, 0x00, 0x2c, 0x10, 0x00, 0x00, 0x2d, 0x10, 0x00, -0x00, 0x2e, 0x01, 0x00, 0xbd, 0xb8, 0x2f, 0x10, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x31, 0x10, -0x00, 0x00, 0x32, 0x01, 0x00, 0xe6, 0xa7, 0x33, 0x01, 0x00, 0x9e, 0x9e, 0x34, 0x01, 0x00, 0xfa, -0xf6, 0x35, 0x01, 0x02, 0x2f, 0xa0, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x56, 0x10, -0x00, 0x00, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, -0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, -0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, -0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, -0xea, 0x20, 0x5e, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, -0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0x22, -0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, -0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0xf8, 0x03, 0x61, 0x86, 0x41, -0x8f, 0x20, 0xf8, 0x2c, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, 0x00, 0x50, 0xaa, 0x04, 0x04, -0xf5, 0x01, 0x43, 0x46, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x5a, 0x03, 0x58, 0x01, 0x5f, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, -0x5f, 0x03, 0xd8, 0x03, 0x58, 0x04, 0x00, 0x00, 0x5b, 0x03, 0xde, 0x01, 0xfe, 0x01, 0x00, 0x00, -0x46, 0x75, 0x7f, 0x02, 0x17, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, -0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x03, 0x03, 0x00, 0x00, 0xfb, 0xad, 0x03, 0x03, 0x01, 0x00, 0x22, 0x40, 0xfd, 0x04, 0x03, -0x03, 0x00, 0x00, 0xfc, 0x9c, 0x05, 0x03, 0x03, 0x00, 0x00, 0xac, 0xcf, 0x06, 0x02, 0x03, 0x00, -0x00, 0xab, 0x07, 0x02, 0x01, 0x00, 0x3f, 0xf3, 0x08, 0x02, 0x03, 0x00, 0x00, 0x7b, 0x09, 0x04, -0x03, 0x00, 0x00, 0x5b, 0xf1, 0x1b, 0x0a, 0x04, 0x0b, 0x00, 0x00, 0x5d, 0x00, 0x1d, 0x0b, 0x02, -0x03, 0x00, 0x00, 0x7d, 0x0c, 0x03, 0x03, 0x00, 0x00, 0x7c, 0xa8, 0x0d, 0x02, 0x07, 0x00, 0x00, -0xcc, 0x12, 0x41, 0x00, 0x65, 0x45, 0x13, 0x43, 0x03, 0x00, 0x00, 0xf4, 0xa9, 0x15, 0x42, 0x00, -0x79, 0x59, 0xbe, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x43, 0x00, -0x6f, 0x4f, 0x9b, 0x9d, 0x19, 0x43, 0x03, 0x00, 0x00, 0xe7, 0xe8, 0x1a, 0x04, 0x0b, 0xca, 0xca, -0xf8, 0x00, 0x1e, 0x1b, 0x43, 0x0c, 0x87, 0x80, 0xc9, 0xcd, 0x1e, 0x43, 0x00, 0x61, 0x41, 0x91, -0x92, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xe1, 0xf5, 0x20, 0x43, 0x03, 0x00, 0x00, 0xd0, 0xd1, 0x21, -0x42, 0x03, 0x00, 0x00, 0xa6, 0x27, 0x03, 0x0f, 0x00, 0x00, 0xcb, 0xcb, 0x28, 0x41, 0x00, 0x8a, -0xd4, 0x29, 0x02, 0x00, 0xf8, 0xf8, 0xaa, 0x2b, 0x43, 0x0c, 0x85, 0xb7, 0xc8, 0xc8, 0x2c, 0x42, -0x03, 0x00, 0x00, 0xae, 0x2d, 0x42, 0x03, 0x00, 0x00, 0xaf, 0x2e, 0x43, 0x00, 0x63, 0x43, 0xbd, -0xb8, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x43, 0x03, 0x00, 0x00, 0xe6, 0xa7, 0x33, 0x02, 0x01, -0x00, 0x27, 0x3c, 0x34, 0x02, 0x01, 0x00, 0x2e, 0x3e, 0x35, 0x42, 0x00, 0x82, 0x90, 0x2f, 0x39, -0x00, 0x00, 0x20, 0x56, 0x44, 0x00, 0x97, 0xeb, 0x5c, 0x7c, 0x1c, 0x00, 0x12, 0x42, 0x03, 0x00, -0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, -0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, -0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, -0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, -0xea, 0x20, 0x5e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, -0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf7, -0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, -0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, -0xf9, 0x00, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x07, 0x02, -0x05, 0x00, 0x3f, 0xa0, 0x12, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x17, 0x03, 0x03, 0x00, 0x00, 0xab, -0xac, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, -0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, -0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, -0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, -0x20, 0x5e, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, -0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0x2c, 0x03, -0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, -0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, -0x20, 0x22, 0x00, 0x02, 0x03, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x03, 0x03, 0x0f, 0x00, 0x00, 0x00, -0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x07, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x03, 0x0f, 0x00, 0x00, 0x00, 0xa0, -0x0c, 0x03, 0x0f, 0x00, 0x00, 0x00, 0xa0, 0x12, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x13, 0x03, 0x0f, -0x00, 0x00, 0xa0, 0xa0, 0x14, 0x03, 0x03, 0x00, 0x00, 0xe7, 0xe8, 0x15, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x17, 0x03, 0x03, 0x00, 0x00, 0xab, 0xac, 0x18, 0x03, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x19, -0x03, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x1f, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x20, 0x03, 0x0f, 0x00, -0x00, 0xa0, 0xa0, 0x21, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x26, 0x03, 0x03, 0x00, 0x00, 0xd0, 0xd1, -0x2e, 0x03, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x32, 0x03, 0x0f, 0x00, 0x00, 0x00, 0xa0, 0x33, 0x02, -0x07, 0x00, 0x00, 0xce, 0x34, 0x02, 0x07, 0x00, 0x00, 0xcf, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, -0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, -0xeb, 0x20, 0x60, 0x7e, 0x0b, 0x61, 0xc6, 0x65, 0xec, 0x69, 0xf4, 0x6f, 0xe4, 0x6e, 0xa4, 0x41, -0xc7, 0x45, 0xed, 0x49, 0xf6, 0x4f, 0xe5, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, -0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, -0xea, 0x20, 0x5e, 0x27, 0x0b, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, -0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x20, 0x27, 0x2c, 0x0d, 0x61, 0x84, 0x65, -0x9e, 0x69, 0xa6, 0x6f, 0x94, 0x75, 0xa8, 0x41, 0x8e, 0x45, 0x9f, 0x49, 0xa7, 0x4f, 0x99, 0x55, -0xa9, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, 0x22, 0x09, 0x65, 0x89, 0x69, 0x8b, 0x75, 0x81, 0x79, -0x98, 0x45, 0xd3, 0x49, 0xd8, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x3c, 0x0b, 0x61, 0xfa, 0x65, -0xf1, 0x69, 0xe1, 0x6f, 0xfc, 0x75, 0xf7, 0x41, 0xfb, 0x45, 0xf2, 0x49, 0xee, 0x4f, 0xfd, 0x55, -0xef, 0x20, 0x3c, 0x3e, 0x0b, 0x61, 0x86, 0x65, 0xbd, 0x69, 0xf9, 0x6f, 0x9b, 0x75, 0xb8, 0x41, -0x8f, 0x45, 0xbe, 0x49, 0xdd, 0x4f, 0x9d, 0x55, 0xad, 0x20, 0x3e, 0x00, 0x02, 0x03, 0x0f, 0x00, -0x00, 0xa0, 0xa0, 0x04, 0x02, 0x03, 0x00, 0x00, 0xa6, 0x05, 0x03, 0x07, 0x00, 0x00, 0x00, 0x98, -0x07, 0x02, 0x03, 0x00, 0x00, 0xad, 0x0c, 0x03, 0x0f, 0x00, 0x00, 0x00, 0xa0, 0x13, 0x43, 0x0b, -0x00, 0x00, 0x86, 0xa0, 0x15, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x18, 0x43, 0x0f, 0x00, 0x00, 0xa0, -0xa0, 0x19, 0x43, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x1b, 0x43, 0x0b, 0x00, 0x00, 0x7e, 0xc9, 0x1e, -0x43, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x1f, 0x43, 0x07, 0x00, 0x00, 0x00, 0x8f, 0x20, 0x43, 0x0f, -0x00, 0x00, 0xa0, 0xa0, 0x21, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x28, 0x41, 0x00, 0x8a, 0x91, 0x2b, -0x41, 0x00, 0x85, 0x8e, 0x2e, 0x43, 0x0b, 0x00, 0x00, 0x9b, 0xa0, 0x32, 0x43, 0x0f, 0x00, 0x00, -0x00, 0xa0, 0x39, 0x00, 0x00, 0x20, 0x56, 0x41, 0x00, 0x97, 0x9d, 0x00, 0x60, 0x07, 0x61, 0x85, -0x65, 0x8a, 0x75, 0x97, 0x41, 0x8e, 0x45, 0x91, 0x55, 0x9d, 0x20, 0x60, 0xa4, 0x07, 0x65, 0x89, -0x69, 0x8b, 0x75, 0x81, 0x45, 0x94, 0x49, 0x95, 0x55, 0x9a, 0x20, 0xa4, 0x5e, 0x0b, 0x61, 0x83, -0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0x84, 0x45, 0x92, 0x49, 0xa8, 0x4f, 0x99, -0x55, 0x9e, 0x20, 0x5e, 0xa1, 0x05, 0x65, 0x82, 0x6f, 0xa2, 0x75, 0xa3, 0x45, 0x90, 0x20, 0xa1, -0xa5, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xa5, 0x00, 0x8c, 0x0b, 0x03, 0x04, 0x00, 0x00, 0x43, -0x5a, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, 0x66, -0x01, 0xb6, 0x01, 0x00, 0x00, 0x5a, 0x03, 0x08, 0x01, 0x0f, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, -0x00, 0x0f, 0x01, 0x00, 0x00, 0x63, 0x03, 0x4b, 0x02, 0x99, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, -0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, -0x2b, 0x31, 0x21, 0x03, 0x02, 0x01, 0xa0, 0x32, 0x40, 0x04, 0x02, 0x01, 0xa0, 0x33, 0x23, 0x05, -0x02, 0x01, 0xa0, 0x34, 0x24, 0x06, 0x02, 0x01, 0xa0, 0x35, 0x25, 0x07, 0x02, 0x01, 0xa0, 0x36, -0x5e, 0x08, 0x02, 0x00, 0xec, 0x37, 0x26, 0x09, 0x02, 0x00, 0xa0, 0x38, 0x2a, 0x0a, 0x02, 0x00, -0xa1, 0x39, 0x28, 0x0b, 0x02, 0x00, 0x82, 0x30, 0x29, 0x0c, 0x03, 0x00, 0x3d, 0x25, 0x2d, 0x5f, -0x0d, 0x03, 0x03, 0xc8, 0xa0, 0x3d, 0x2b, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, -0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, -0x1a, 0x03, 0x00, 0xa3, 0x2f, 0x5b, 0x7b, 0x1b, 0x03, 0x00, 0x29, 0x28, 0x5d, 0x7d, 0x1e, 0x41, -0x00, 0x61, 0x41, 0x27, 0x03, 0x01, 0xa0, 0x22, 0x3b, 0x3a, 0x28, 0x03, 0x08, 0xf5, 0x21, 0xcf, -0xcb, 0x29, 0x03, 0x02, 0x3b, 0xca, 0x60, 0x7e, 0x2b, 0x03, 0x01, 0xc9, 0x27, 0x5c, 0x7c, 0x2e, -0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x33, 0x03, 0x01, 0x00, 0x3f, 0x3c, 0x9e, -0x34, 0x03, 0x01, 0x00, 0x3a, 0x3e, 0xf6, 0x35, 0x03, 0x00, 0x2d, 0x5f, 0x2f, 0x3f, 0x39, 0x00, -0x00, 0x20, 0x56, 0x02, 0x00, 0x26, 0x2a, 0xe1, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, -0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, -0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, -0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, -0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf8, 0x03, 0x61, 0x86, 0x41, 0x8f, 0x20, 0xf8, 0x5e, 0x0b, -0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, -0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x00, 0x03, 0x00, 0x00, 0xd8, 0x04, 0x00, 0x00, 0xe7, 0x05, -0x00, 0x00, 0x9f, 0x06, 0x00, 0x00, 0xfd, 0x07, 0x00, 0x00, 0xa7, 0x0d, 0x01, 0x03, 0x00, 0xcb, -0x12, 0x42, 0x03, 0x00, 0x00, 0xaa, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, 0x54, -0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, 0x41, 0x00, 0x64, 0x44, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x27, -0x00, 0x00, 0x85, 0x28, 0x03, 0x0f, 0x00, 0x00, 0x00, 0xcc, 0x2c, 0x41, 0x00, 0x7a, 0x5a, 0x56, -0x03, 0x0f, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x27, 0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, -0xa1, 0x6c, 0x92, 0x6e, 0xe4, 0x6f, 0xa2, 0x72, 0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, -0xab, 0x41, 0xb5, 0x43, 0x8f, 0x45, 0x90, 0x49, 0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, -0xe8, 0x53, 0x97, 0x55, 0xe9, 0x59, 0xed, 0x5a, 0x8d, 0x20, 0xef, 0xf9, 0x09, 0x61, 0x84, 0x65, -0x89, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x45, 0xd3, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf8, -0x03, 0x75, 0x85, 0x55, 0xde, 0x20, 0xf8, 0xf3, 0x13, 0x63, 0x9f, 0x64, 0xd4, 0x65, 0xd8, 0x6c, -0x96, 0x6e, 0xe5, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa7, 0x43, 0xac, 0x44, 0xd2, 0x45, -0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, 0xa6, 0x20, 0xf3, 0x5e, -0x07, 0x61, 0x83, 0x69, 0x8c, 0x6f, 0x93, 0x41, 0xb6, 0x49, 0xd7, 0x4f, 0xe2, 0x20, 0x5e, 0xf1, -0x05, 0x6f, 0x8b, 0x75, 0xfb, 0x4f, 0x8a, 0x55, 0xeb, 0x20, 0xf1, 0x00, 0x03, 0x00, 0x00, 0x88, -0x04, 0x00, 0x00, 0xa8, 0x05, 0x00, 0x00, 0x87, 0x06, 0x00, 0x00, 0xa9, 0x07, 0x00, 0x00, 0x91, -0x08, 0x00, 0x00, 0x98, 0x0d, 0x01, 0x03, 0x00, 0xcb, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, -0x00, 0x74, 0x54, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, 0x41, 0x00, 0x64, 0x44, 0x26, 0x41, 0x00, -0x6c, 0x4c, 0x27, 0x00, 0x00, 0x96, 0x28, 0x03, 0x0e, 0xad, 0x00, 0xa0, 0xcc, 0x2c, 0x41, 0x00, -0x7a, 0x5a, 0x33, 0x03, 0x0f, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x27, 0x11, 0x61, 0xa0, 0x65, 0x82, -0x69, 0xa1, 0x6c, 0x8d, 0x6f, 0xa2, 0x72, 0xaa, 0x75, 0xa3, 0x79, 0x98, 0x41, 0x8f, 0x45, 0x90, -0x49, 0x8b, 0x4c, 0x8a, 0x4f, 0x95, 0x52, 0xab, 0x55, 0x97, 0x59, 0x9d, 0x20, 0x27, 0x22, 0x07, -0x61, 0x84, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0xf8, 0x03, -0x75, 0x96, 0x55, 0xa6, 0x20, 0xf8, 0x76, 0x13, 0x63, 0x87, 0x64, 0x83, 0x65, 0x88, 0x6c, 0x8c, -0x6e, 0xa4, 0x72, 0xa9, 0x73, 0xa8, 0x74, 0x9f, 0x7a, 0x91, 0x43, 0x80, 0x44, 0x85, 0x45, 0x89, -0x4c, 0x9c, 0x4e, 0xa5, 0x52, 0x9e, 0x53, 0x9b, 0x54, 0x86, 0x5a, 0x92, 0x20, 0x76, 0x5e, 0x03, -0x6f, 0x93, 0x4f, 0xa7, 0x20, 0x5e, 0x00, 0x19, 0xfa, 0x03, 0x04, 0xf3, 0x00, 0x43, 0x5a, 0x05, -0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, 0x4a, 0x01, 0xcc, -0x01, 0x00, 0x00, 0x5a, 0x03, 0x8d, 0x02, 0x94, 0x02, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x94, -0x02, 0x00, 0x00, 0x63, 0x03, 0x1b, 0x03, 0x88, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x2b, 0x31, 0xc8, 0x03, 0x01, 0x01, 0xa0, 0x32, 0x04, 0x03, -0x05, 0xa0, 0x33, 0xc9, 0x1e, 0x05, 0x01, 0x01, 0xa0, 0x34, 0x06, 0x02, 0x05, 0xa0, 0x35, 0xca, -0x07, 0x01, 0x01, 0xa0, 0x36, 0x08, 0x02, 0x04, 0xec, 0x37, 0xcb, 0x09, 0x02, 0x00, 0xa0, 0x38, -0xfa, 0x0a, 0x02, 0x04, 0xa1, 0x39, 0xcc, 0x0b, 0x01, 0x00, 0x82, 0x30, 0x0c, 0x02, 0x04, 0x3d, -0x25, 0xcd, 0x0d, 0x02, 0x07, 0xcc, 0xa0, 0xce, 0x10, 0x42, 0x03, 0x00, 0x00, 0x5c, 0x11, 0x42, -0x03, 0x00, 0x00, 0x7c, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0xc4, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, -0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, -0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x02, 0x00, 0xa3, 0x2f, 0xf6, 0x1b, 0x02, 0x00, 0x29, 0x28, -0x9e, 0x1e, 0x42, 0x00, 0x61, 0x41, 0x3c, 0x21, 0x42, 0x03, 0x00, 0x00, 0x5b, 0x22, 0x42, 0x03, -0x00, 0x00, 0x5d, 0x27, 0x02, 0x01, 0xa0, 0x22, 0x24, 0x28, 0x02, 0x00, 0xf5, 0x21, 0xe1, 0x29, -0x01, 0x02, 0x3b, 0xca, 0x2b, 0x02, 0x01, 0xcd, 0x27, 0xcf, 0x2c, 0xc4, 0x00, 0x79, 0x15, 0x59, -0x15, 0x3e, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x42, 0x03, 0x00, 0x00, 0x23, 0x2e, 0x42, 0x00, -0x63, 0x43, 0x26, 0x2f, 0x42, 0x03, 0x00, 0x00, 0x40, 0x30, 0x42, 0x03, 0x00, 0x00, 0x7b, 0x31, -0x42, 0x00, 0x6e, 0x4e, 0x7d, 0x32, 0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x01, 0x01, 0x00, 0x3f, -0x34, 0x02, 0x01, 0x00, 0x3a, 0x2a, 0x35, 0x03, 0x04, 0x2d, 0x5f, 0x00, 0x1f, 0x39, 0x00, 0x00, -0x20, 0x56, 0x03, 0x00, 0x26, 0x2a, 0x3c, 0x1c, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x03, -0x02, 0x06, 0xd8, 0x00, 0xc8, 0x04, 0x00, 0x00, 0xe7, 0x05, 0x02, 0x06, 0x9f, 0x00, 0xca, 0x06, -0x02, 0x06, 0xfd, 0x00, 0xcb, 0x07, 0x02, 0x06, 0xa7, 0x00, 0xcc, 0x08, 0x02, 0x03, 0x00, 0x00, -0x60, 0x09, 0x02, 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xce, 0x0b, 0x02, 0x07, -0x00, 0x00, 0xcf, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xd0, 0x0d, 0x02, 0x07, 0xce, 0xc8, 0xd1, 0x12, -0x42, 0x03, 0x00, 0x00, 0xaa, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, 0x54, 0x1f, -0x42, 0x00, 0x73, 0x53, 0xd0, 0x20, 0x42, 0x00, 0x64, 0x44, 0xd1, 0x25, 0x42, 0x03, 0x00, 0x00, -0x88, 0x26, 0x42, 0x00, 0x6c, 0x4c, 0x9d, 0x27, 0x00, 0x00, 0x85, 0x29, 0x01, 0x03, 0x00, 0xcb, -0x2b, 0x00, 0x01, 0xd0, 0x32, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x00, 0xf3, 0x13, 0x63, 0x9f, 0x64, -0xd4, 0x65, 0xd8, 0x6c, 0x96, 0x6e, 0xe5, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa7, 0x43, -0xac, 0x44, 0xd2, 0x45, 0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, -0xa6, 0x20, 0xf3, 0x5e, 0x07, 0x61, 0x83, 0x69, 0x8c, 0x6f, 0x93, 0x41, 0xb6, 0x49, 0xd7, 0x4f, -0xe2, 0x20, 0x5e, 0xf4, 0x03, 0x61, 0xc7, 0x41, 0xc6, 0x20, 0xf4, 0xf8, 0x03, 0x75, 0x85, 0x55, -0xde, 0x20, 0xf8, 0xf2, 0x05, 0x61, 0xa5, 0x65, 0xa9, 0x41, 0xa4, 0x45, 0xa8, 0x20, 0xf2, 0xfa, -0x03, 0x7a, 0xbe, 0x5a, 0xbd, 0x20, 0xfa, 0x27, 0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, -0xa1, 0x6c, 0x92, 0x6e, 0xe4, 0x6f, 0xa2, 0x72, 0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, -0xab, 0x41, 0xb5, 0x43, 0x8f, 0x45, 0x90, 0x49, 0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, -0xe8, 0x53, 0x97, 0x55, 0xe9, 0x59, 0xed, 0x5a, 0x8d, 0x20, 0xef, 0xf1, 0x05, 0x6f, 0x8b, 0x75, -0xfb, 0x4f, 0x8a, 0x55, 0xeb, 0x20, 0xf1, 0xf9, 0x09, 0x61, 0x84, 0x65, 0x89, 0x6f, 0x94, 0x75, -0x81, 0x41, 0x8e, 0x45, 0xd3, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf7, 0x07, 0x63, 0x87, 0x73, -0xad, 0x74, 0xee, 0x43, 0x80, 0x53, 0xb8, 0x54, 0xdd, 0x20, 0xf7, 0x00, 0x12, 0x42, 0x03, 0x00, -0x00, 0xd5, 0x00, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, -0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, -0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf8, 0x03, 0x61, 0x86, 0x41, -0x8f, 0x20, 0xf8, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, -0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0xef, 0x0d, 0x61, 0xa0, 0x65, -0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, -0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, -0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, -0xf9, 0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7e, -0x03, 0x02, 0x06, 0x88, 0x00, 0xc8, 0x04, 0x00, 0x00, 0xa8, 0x05, 0x00, 0x00, 0x87, 0x06, 0x00, -0x00, 0xa9, 0x07, 0x00, 0x00, 0x91, 0x08, 0x02, 0x02, 0x98, 0x00, 0x60, 0x09, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xcb, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x0d, 0x02, -0x07, 0xcb, 0xc8, 0xa0, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, 0x54, 0x1b, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, 0x41, 0x00, 0x64, 0x44, 0x26, 0x41, -0x00, 0x6c, 0x4c, 0x27, 0x00, 0x00, 0x96, 0x28, 0x00, 0x00, 0xad, 0x29, 0x01, 0x03, 0x00, 0xca, -0x2b, 0x02, 0x07, 0xcc, 0x00, 0xa0, 0x00, 0x76, 0x13, 0x63, 0x87, 0x64, 0x83, 0x65, 0x88, 0x6c, -0x8c, 0x6e, 0xa4, 0x72, 0xa9, 0x73, 0xa8, 0x74, 0x9f, 0x7a, 0x91, 0x43, 0x80, 0x44, 0x85, 0x45, -0x89, 0x4c, 0x9c, 0x4e, 0xa5, 0x52, 0x9e, 0x53, 0x9b, 0x54, 0x86, 0x5a, 0x92, 0x20, 0x76, 0x5e, -0x03, 0x6f, 0x93, 0x4f, 0xa7, 0x20, 0x5e, 0xf8, 0x03, 0x75, 0x96, 0x55, 0xa6, 0x20, 0xf8, 0x27, -0x11, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6c, 0x8d, 0x6f, 0xa2, 0x72, 0xaa, 0x75, 0xa3, 0x79, -0x98, 0x41, 0x8f, 0x45, 0x90, 0x49, 0x8b, 0x4c, 0x8a, 0x4f, 0x95, 0x52, 0xab, 0x55, 0x97, 0x59, -0x9d, 0x20, 0x27, 0x22, 0x07, 0x61, 0x84, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x4f, 0x99, 0x55, -0x9a, 0x20, 0x22, 0x00, 0xe5, 0x77, 0x02, 0x09, 0x00, 0x00, 0x44, 0x4b, 0x2c, 0x9f, 0x00, 0x44, -0x4b, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xfd, -0x00, 0x0a, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x61, 0x03, 0x85, -0x01, 0x90, 0x01, 0x00, 0x00, 0x34, 0x75, 0xdf, 0x01, 0x18, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, -0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, -0x9c, 0x05, 0x02, 0x01, 0x00, 0xcf, 0x24, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, 0x02, 0x01, 0x00, -0x2f, 0x7b, 0x09, 0x03, 0x01, 0x00, 0x28, 0x5b, 0x1b, 0x0a, 0x03, 0x01, 0x00, 0x29, 0x5d, 0x1d, -0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, 0x01, 0x00, 0x2b, 0x3f, 0x0d, 0x02, 0x03, 0xcb, 0xc8, -0x7c, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, -0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x41, 0x00, 0x86, 0x8f, 0x1b, -0x03, 0x07, 0xcc, 0xca, 0xc9, 0x1e, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x41, 0x00, 0x91, 0x92, -0x28, 0x41, 0x00, 0x9b, 0x9d, 0x29, 0x01, 0x00, 0xab, 0xf5, 0x2b, 0x01, 0x00, 0x27, 0x2a, 0x2e, -0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, -0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, 0x01, 0x00, 0x3a, 0x3e, 0x35, 0x03, 0x00, 0x2d, 0x5f, -0x5c, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, 0x03, 0x00, 0x3c, 0x3e, 0x5c, 0x1c, 0x00, 0x06, 0x02, -0x03, 0x00, 0x00, 0xd5, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, -0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, -0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, -0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, -0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0f, 0x61, 0xa0, 0x63, -0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, 0x80, 0x45, -0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, -0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, -0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0x05, 0x01, 0x01, 0x00, 0xaf, 0x29, 0x01, 0x01, 0x00, 0x15, -0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, 0x7e, -0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, -0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x09, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, -0xa2, 0x75, 0xa3, 0x43, 0x80, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, -0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, -0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x0d, 0x01, 0x03, 0xca, 0xa0, 0x12, 0x02, 0x03, 0x00, 0x00, -0xd5, 0x1b, 0x03, 0x07, 0xcb, 0xc9, 0xc8, 0x1e, 0x1f, 0x02, 0x03, 0x00, 0x00, 0xe1, 0x20, 0x04, -0x0b, 0x00, 0x00, 0xd0, 0x00, 0xd1, 0x25, 0x02, 0x03, 0x00, 0x00, 0xf2, 0x2c, 0x02, 0x03, 0x00, -0x00, 0xae, 0x2d, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x00, 0x7e, 0x07, 0x61, 0xc6, 0x69, 0x8d, 0x75, -0x97, 0x41, 0xc7, 0x49, 0xde, 0x55, 0xeb, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, -0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, -0x5e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, -0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x07, 0x61, -0x84, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0x8d, 0x20, -0x02, 0x17, 0x00, 0x00, 0x44, 0x56, 0x2c, 0x00, 0x00, 0x55, 0x53, 0x44, 0x56, 0x2c, 0x67, 0x00, -0x44, 0x56, 0x2c, 0x67, 0x00, 0x55, 0x53, 0x44, 0x56, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x84, 0x00, 0x5b, 0x1a, 0x7b, 0x1a, 0x1b, 0x1a, 0x00, 0x1a, -0x00, 0x1a, 0x0d, 0x84, 0x00, 0x5d, 0x1b, 0x7d, 0x1b, 0x1d, 0x1b, 0x00, 0x1b, 0x00, 0x1b, 0x10, -0x84, 0x00, 0x27, 0x28, 0x22, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x11, 0x84, 0x00, 0x2c, -0x33, 0x3c, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x12, 0x84, 0x00, 0x2e, 0x34, 0x3e, 0x34, -0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x13, 0xc4, 0x00, 0x70, 0x19, 0x50, 0x19, 0x10, 0x19, 0x00, -0x19, 0x00, 0x19, 0x14, 0xc4, 0x00, 0x79, 0x15, 0x59, 0x15, 0x19, 0x15, 0x00, 0x15, 0x00, 0x15, -0x15, 0xc4, 0x00, 0x66, 0x21, 0x46, 0x21, 0x06, 0x21, 0x00, 0x21, 0x00, 0x21, 0x16, 0xc4, 0x00, -0x67, 0x22, 0x47, 0x22, 0x07, 0x22, 0x00, 0x22, 0x00, 0x22, 0x17, 0xc4, 0x00, 0x63, 0x2e, 0x43, -0x2e, 0x03, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x18, 0xc4, 0x00, 0x72, 0x13, 0x52, 0x13, 0x12, 0x13, -0x00, 0x13, 0x00, 0x13, 0x19, 0xc4, 0x00, 0x6c, 0x26, 0x4c, 0x26, 0x0c, 0x26, 0x00, 0x26, 0x00, -0x26, 0x1a, 0x84, 0x00, 0x2f, 0x35, 0x3f, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x1b, 0x84, -0x00, 0x3d, 0x0d, 0x2b, 0x0d, 0x00, 0x0d, 0x00, 0x83, 0x00, 0x83, 0x1f, 0xc4, 0x00, 0x6f, 0x18, -0x4f, 0x18, 0x0f, 0x18, 0x00, 0x18, 0x00, 0x18, 0x20, 0xc4, 0x00, 0x65, 0x12, 0x45, 0x12, 0x05, -0x12, 0x00, 0x12, 0x00, 0x12, 0x21, 0xc4, 0x00, 0x75, 0x16, 0x55, 0x16, 0x15, 0x16, 0x00, 0x16, -0x00, 0x16, 0x22, 0xc4, 0x00, 0x69, 0x17, 0x49, 0x17, 0x09, 0x17, 0x00, 0x17, 0x00, 0x17, 0x23, -0xc4, 0x00, 0x64, 0x20, 0x44, 0x20, 0x04, 0x20, 0x00, 0x20, 0x00, 0x20, 0x24, 0xc4, 0x00, 0x68, -0x23, 0x48, 0x23, 0x08, 0x23, 0x00, 0x23, 0x00, 0x23, 0x25, 0xc4, 0x00, 0x74, 0x14, 0x54, 0x14, -0x14, 0x14, 0x00, 0x14, 0x00, 0x14, 0x26, 0xc4, 0x00, 0x6e, 0x31, 0x4e, 0x31, 0x0e, 0x31, 0x00, -0x31, 0x00, 0x31, 0x27, 0xc4, 0x00, 0x73, 0x1f, 0x53, 0x1f, 0x13, 0x1f, 0x00, 0x1f, 0x00, 0x1f, -0x28, 0x84, 0x00, 0x2d, 0x0c, 0x5f, 0x0c, 0x1f, 0x0c, 0x00, 0x82, 0x00, 0x82, 0x2c, 0x84, 0x00, -0x3b, 0x27, 0x3a, 0x27, 0x00, 0x27, 0x00, 0x27, 0x00, 0x27, 0x2d, 0xc4, 0x00, 0x71, 0x10, 0x51, -0x10, 0x11, 0x10, 0x00, 0x10, 0x00, 0x10, 0x2e, 0xc4, 0x00, 0x6a, 0x24, 0x4a, 0x24, 0x0a, 0x24, -0x00, 0x24, 0x00, 0x24, 0x2f, 0xc4, 0x00, 0x6b, 0x25, 0x4b, 0x25, 0x0b, 0x25, 0x00, 0x25, 0x00, -0x25, 0x30, 0xc4, 0x00, 0x78, 0x2d, 0x58, 0x2d, 0x18, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x31, 0xc4, -0x00, 0x62, 0x30, 0x42, 0x30, 0x02, 0x30, 0x00, 0x30, 0x00, 0x30, 0x33, 0xc4, 0x00, 0x77, 0x11, -0x57, 0x11, 0x17, 0x11, 0x00, 0x11, 0x00, 0x11, 0x34, 0xc4, 0x00, 0x76, 0x2f, 0x56, 0x2f, 0x16, -0x2f, 0x00, 0x2f, 0x00, 0x2f, 0x35, 0xc4, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, -0x00, 0x2c, 0x00, 0x20, 0xc4, 0x00, 0x65, 0x12, 0x45, 0x12, 0x05, 0x12, 0xd5, 0x12, 0x00, 0x12, -0x00, 0x9d, 0xdb, 0x02, 0x09, 0x00, 0x00, 0x46, 0x52, 0x2c, 0xbd, 0x00, 0x46, 0x52, 0x06, 0x04, -0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xa0, 0x01, 0xa7, 0x01, -0x00, 0x00, 0x5b, 0x03, 0x02, 0x02, 0x3f, 0x02, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0xa7, 0x01, -0x00, 0x00, 0xb5, 0x01, 0x54, 0x01, 0x65, 0x01, 0x00, 0x00, 0x45, 0x75, 0x9c, 0x02, 0xb8, 0x02, -0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x02, 0x41, 0x00, 0x26, 0x31, 0x03, 0x42, 0x04, 0x82, 0x32, 0xc9, 0x04, 0x42, 0x00, -0x22, 0x33, 0x23, 0x05, 0x42, 0x00, 0x27, 0x34, 0x7b, 0x06, 0x43, 0x00, 0x28, 0x35, 0x5b, 0x1b, -0x07, 0x43, 0x00, 0x2d, 0x36, 0x7c, 0x1f, 0x08, 0x42, 0x04, 0x8a, 0x37, 0xc8, 0x09, 0x43, 0x00, -0x5f, 0x38, 0x5c, 0x1c, 0x0a, 0x42, 0x00, 0x87, 0x39, 0x5e, 0x0b, 0x42, 0x00, 0x85, 0x30, 0x40, -0x0c, 0x43, 0x00, 0x29, 0xf8, 0x5d, 0x1d, 0x0d, 0x42, 0x03, 0x00, 0x00, 0x7d, 0x10, 0xc5, 0x00, -0x61, 0x1e, 0x41, 0x1e, 0x00, 0x1e, 0x01, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x11, 0xc5, 0x00, 0x7a, -0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x12, 0x41, 0x00, 0x65, 0x45, -0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, -0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x43, 0x07, 0xca, 0xcb, 0x00, 0x1e, 0x1b, 0x42, 0x00, 0x24, 0x9c, -0xcf, 0x1e, 0xc5, 0x00, 0x71, 0x10, 0x51, 0x10, 0x00, 0x10, 0x11, 0x10, 0x00, 0x10, 0x00, 0x10, -0x27, 0xc5, 0x00, 0x6d, 0x32, 0x4d, 0x32, 0x00, 0x32, 0x0d, 0x32, 0x00, 0x32, 0x00, 0x32, 0x28, -0x41, 0x00, 0x97, 0x25, 0x29, 0x41, 0x00, 0xfd, 0xfc, 0x2b, 0x41, 0x00, 0x2a, 0xe6, 0x2c, 0xc5, -0x00, 0x77, 0x11, 0x57, 0x11, 0x00, 0x11, 0x17, 0x11, 0x00, 0x11, 0x00, 0x11, 0x31, 0x41, 0x00, -0x6e, 0x4e, 0x32, 0x41, 0x00, 0x2c, 0x3f, 0x33, 0x42, 0x00, 0x3b, 0x2e, 0x3c, 0x34, 0x42, 0x00, -0x3a, 0x2f, 0x3e, 0x35, 0x41, 0x00, 0x21, 0xf5, 0x39, 0x00, 0x00, 0x20, 0x56, 0x41, 0x00, 0x3c, -0x3e, 0x00, 0x1b, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x29, 0x41, 0x03, 0x00, 0xa0, 0x35, 0x41, 0x01, -0x00, 0x15, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, -0x60, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, 0x69, -0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, -0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x12, 0x42, -0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, -0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, -0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, -0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, -0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, -0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, -0x10, 0xc5, 0x00, 0x61, 0x1e, 0x41, 0x1e, 0x91, 0x1e, 0x01, 0x1e, 0x92, 0x1e, 0x00, 0x1e, 0x12, -0x44, 0x0b, 0x00, 0x00, 0xd5, 0x00, 0x90, 0x18, 0x44, 0x0b, 0x00, 0x00, 0xab, 0x00, 0xac, 0x2c, -0xc5, 0x00, 0x77, 0x11, 0x57, 0x11, 0xae, 0x11, 0x17, 0x11, 0x00, 0x11, 0x00, 0x11, 0x2d, 0x42, -0x03, 0x00, 0x00, 0xaf, 0x2e, 0x44, 0x0b, 0x00, 0x00, 0x87, 0x00, 0x80, 0x00, 0x60, 0x0b, 0x61, -0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, -0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, -0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, -0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x22, 0x0d, 0x61, -0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, -0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x00, 0x03, 0x42, 0x07, 0x00, 0x00, 0xa0, -0x08, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x1a, 0x41, 0x03, 0xc8, -0xa0, 0x29, 0x10, 0x00, 0x00, 0x00, 0x5e, 0x0b, 0x61, 0xee, 0x65, 0xd0, 0x69, 0xf6, 0x6f, 0xfa, -0x75, 0xfc, 0x41, 0xef, 0x45, 0xd1, 0x49, 0xf7, 0x4f, 0xfb, 0x55, 0xfd, 0x20, 0x5e, 0x00, 0xff, -0x3c, 0x05, 0x13, 0x00, 0x00, 0x47, 0x52, 0x2c, 0x00, 0x00, 0x44, 0x45, 0x2c, 0x81, 0x00, 0x47, -0x52, 0x2c, 0x81, 0x00, 0x44, 0x45, 0x09, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, -0x00, 0x00, 0x5a, 0x03, 0x4f, 0x01, 0x56, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x56, 0x01, -0x00, 0x00, 0x5b, 0x03, 0xa7, 0x01, 0xeb, 0x01, 0x00, 0x00, 0xb5, 0x01, 0x40, 0x02, 0x47, 0x02, -0x00, 0x00, 0x54, 0x03, 0x78, 0x02, 0xfc, 0x02, 0x00, 0x00, 0x55, 0x03, 0x5d, 0x03, 0x7a, 0x03, -0x00, 0x00, 0x39, 0x75, 0x97, 0x03, 0x03, 0x04, 0x00, 0x00, 0x44, 0x75, 0x58, 0x04, 0x93, 0x04, -0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7c, 0x03, 0x02, 0x01, 0x00, 0x22, 0xfd, 0x04, 0x02, -0x01, 0x00, 0xf5, 0xfc, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, 0x02, 0x01, 0x00, 0x2f, 0x7b, 0x09, -0x04, 0x09, 0x00, 0x28, 0x5b, 0x00, 0x1b, 0x0a, 0x04, 0x09, 0x00, 0x29, 0x5d, 0x00, 0x1d, 0x0b, -0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, 0x04, 0x08, 0xe1, 0x3f, 0x5c, 0x00, 0x1c, 0x0d, 0x01, 0x03, -0xca, 0xc8, 0x10, 0x42, 0x03, 0x00, 0x00, 0x40, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0xc5, 0x00, -0x7a, 0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0x75, -0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x41, 0x00, 0x81, 0x9a, -0x1b, 0x02, 0x00, 0x2b, 0x2a, 0x7e, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x41, 0x00, 0x94, 0x99, -0x28, 0x41, 0x00, 0x84, 0x8e, 0x29, 0x04, 0x0d, 0xc9, 0xf8, 0x00, 0x00, 0x1e, 0x2b, 0x01, 0x00, -0x23, 0x27, 0x2c, 0xc5, 0x00, 0x79, 0x15, 0x59, 0x15, 0x3c, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, -0x15, 0x2d, 0x42, 0x03, 0x00, 0x00, 0x3e, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x42, 0x03, 0x00, -0x00, 0x23, 0x32, 0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x01, 0x01, 0x00, 0x3b, 0x34, 0x01, 0x01, -0x00, 0x3a, 0x35, 0x04, 0x0c, 0x2d, 0x5f, 0x00, 0x00, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, 0x02, -0x00, 0x3c, 0x3e, 0x7c, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, -0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, -0x55, 0xeb, 0x20, 0x60, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0f, 0x61, 0xa0, -0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, 0x80, -0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0x00, 0x03, 0x01, 0x03, -0x00, 0xcb, 0x09, 0x03, 0x07, 0x00, 0x00, 0x00, 0xae, 0x0a, 0x03, 0x07, 0x00, 0x00, 0x00, 0xaf, -0x12, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x18, 0x03, 0x03, 0x00, 0x00, 0xab, 0xac, 0x1e, 0x03, 0x03, -0x00, 0x00, 0x86, 0x8f, 0x27, 0x03, 0x03, 0x00, 0x00, 0x9b, 0x9d, 0x28, 0x03, 0x03, 0x00, 0x00, -0x91, 0x92, 0x2e, 0x03, 0x03, 0x00, 0x00, 0x87, 0x80, 0x31, 0x03, 0x03, 0x00, 0x00, 0xa4, 0xa5, -0x00, 0x60, 0x07, 0x61, 0x85, 0x65, 0x8a, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x55, 0xeb, 0x20, -0x60, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, -0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x27, 0x07, 0x61, 0xa0, 0x65, 0x82, 0x6f, -0xa2, 0x41, 0xb5, 0x45, 0x90, 0x4f, 0xe0, 0x20, 0x27, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, -0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, -0x9a, 0x59, 0xf3, 0x20, 0x22, 0x00, 0x04, 0x02, 0x05, 0x00, 0x15, 0xa0, 0x00, 0x60, 0x06, 0x61, -0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, 0x5e, 0x06, 0x61, 0x83, 0x65, -0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x09, 0x61, 0xa0, 0x63, 0x87, 0x65, -0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x43, 0x80, 0x45, 0x90, 0x20, 0x27, 0x00, 0x03, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, 0x03, 0x00, 0x00, 0xaa, -0x09, 0x03, 0x07, 0x00, 0x00, 0x00, 0xae, 0x0a, 0x03, 0x07, 0x00, 0x00, 0x00, 0xaf, 0x0d, 0x01, -0x03, 0xc8, 0xa0, 0x12, 0x03, 0x03, 0x00, 0x00, 0xa9, 0xa8, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, -0x41, 0x00, 0x74, 0x54, 0x15, 0xc5, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0xbe, 0x2c, 0xbd, 0x2c, 0x1a, -0x2c, 0x00, 0x2c, 0x16, 0x03, 0x03, 0x00, 0x00, 0xfb, 0xeb, 0x17, 0x03, 0x03, 0x00, 0x00, 0x85, -0xde, 0x18, 0x03, 0x03, 0x00, 0x00, 0x8b, 0x8a, 0x1e, 0x03, 0x03, 0x00, 0x00, 0xa5, 0xa4, 0x1f, -0x41, 0x00, 0x73, 0x53, 0x20, 0x43, 0x00, 0x64, 0x44, 0xd0, 0xd1, 0x26, 0x43, 0x00, 0x6c, 0x4c, -0x88, 0x9d, 0x29, 0x00, 0x01, 0xc9, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x00, 0xef, 0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, 0xa1, 0x6c, 0x92, 0x6e, 0xe4, -0x6f, 0xa2, 0x72, 0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, 0xab, 0x41, 0xb5, 0x43, 0x8f, -0x45, 0x90, 0x49, 0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, 0xe8, 0x53, 0x97, 0x55, 0xe9, -0x59, 0xed, 0x5a, 0x8d, 0x20, 0xef, 0x5e, 0x15, 0x63, 0x9f, 0x64, 0xd4, 0x65, 0xd8, 0x6c, 0x96, -0x6e, 0xe5, 0x6f, 0x93, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa7, 0x43, 0xac, 0x44, 0xd2, -0x45, 0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x4f, 0xe2, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, 0xa6, -0x20, 0x5e, 0x00, 0x0d, 0x10, 0x00, 0x00, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x22, 0x41, 0x00, 0x67, -0x47, 0x23, 0x41, 0x00, 0x68, 0x48, 0x24, 0x41, 0x00, 0x6a, 0x4a, 0x29, 0x00, 0x01, 0xc8, 0x00, -0x5e, 0x0d, 0x63, 0x86, 0x67, 0x9b, 0x68, 0xa9, 0x6a, 0x9f, 0x73, 0xc7, 0x75, 0xed, 0x43, 0x8f, -0x47, 0x9d, 0x48, 0xa8, 0x4a, 0xac, 0x53, 0xc6, 0x55, 0xec, 0x20, 0x5e, 0x00, 0x03, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x00, 0x01, 0xa0, 0x0d, 0x00, 0x01, -0xc8, 0x12, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, -0x54, 0x17, 0x03, 0x03, 0x00, 0x00, 0x8b, 0xd8, 0x19, 0x41, 0x00, 0x70, 0x50, 0x1e, 0x03, 0x03, -0x00, 0x00, 0xc6, 0xc7, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, 0x41, 0x00, 0x64, 0x44, 0x22, 0x41, -0x00, 0x67, 0x47, 0x23, 0x41, 0x00, 0x68, 0x48, 0x25, 0x41, 0x00, 0x6b, 0x4b, 0x26, 0x41, 0x00, -0x6c, 0x4c, 0x28, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x29, 0x00, 0x01, 0xc9, 0x31, 0x41, 0x00, -0x6e, 0x4e, 0x32, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x00, 0xef, 0x0b, 0x63, 0x86, 0x67, 0xd0, 0x72, -0xe8, 0x73, 0xfa, 0x7a, 0xaa, 0x43, 0x8f, 0x47, 0xd1, 0x52, 0xf6, 0x53, 0xfb, 0x5a, 0xab, 0x20, -0xef, 0x5e, 0x1d, 0x63, 0xac, 0x64, 0x8a, 0x65, 0x88, 0x67, 0xdd, 0x68, 0xbd, 0x69, 0x8c, 0x6b, -0x85, 0x6c, 0xf2, 0x6e, 0xe4, 0x70, 0x9d, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa8, 0x43, -0xad, 0x44, 0xd4, 0x45, 0xd2, 0x47, 0xde, 0x48, 0xbe, 0x49, 0xd7, 0x4b, 0xb7, 0x4c, 0xf1, 0x4e, -0xe5, 0x50, 0xe1, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, 0xa9, 0x20, 0x5e, 0x00, 0x02, 0x02, -0x07, 0x00, 0x00, 0xcc, 0x03, 0x01, 0x03, 0x00, 0xcb, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x17, -0x43, 0x03, 0x00, 0x00, 0x9e, 0x9f, 0x18, 0x43, 0x03, 0x00, 0x00, 0xab, 0xac, 0x1b, 0x02, 0x07, -0x00, 0x00, 0xcd, 0x1e, 0x43, 0x03, 0x00, 0x00, 0x86, 0x8f, 0x27, 0x43, 0x03, 0x00, 0x00, 0x9b, -0x9d, 0x28, 0x43, 0x03, 0x00, 0x00, 0x91, 0x92, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, -0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, -0x60, 0x5e, 0x0d, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x79, 0xbd, 0x41, -0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x59, 0xbe, 0x20, 0x5e, 0x27, 0x0d, 0x61, -0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, -0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, -0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, -0x9a, 0x59, 0xf3, 0x20, 0x22, 0x7c, 0x0b, 0x61, 0x87, 0x65, 0xd0, 0x69, 0xe7, 0x6f, 0xf9, 0x75, -0xf7, 0x41, 0x80, 0x45, 0xd1, 0x49, 0xe8, 0x4f, 0xdd, 0x55, 0xef, 0x20, 0x7c, 0x7e, 0x07, 0x65, -0xc6, 0x6f, 0xa4, 0x94, 0xe4, 0x45, 0xc7, 0x4f, 0xa5, 0x99, 0xe5, 0x20, 0x7e, 0x00, 0xc8, 0xc6, -0x08, 0x09, 0xc5, 0x01, 0x47, 0x52, 0x2c, 0xc5, 0x01, 0x44, 0x45, 0x0c, 0x04, 0x00, 0x00, 0x00, -0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0x5d, 0x01, 0x75, 0x03, 0x00, 0x00, 0x5a, -0x03, 0x6c, 0x01, 0x75, 0x03, 0x00, 0x00, 0x52, 0x03, 0x6c, 0x02, 0x75, 0x03, 0x00, 0x00, 0x52, -0x03, 0x75, 0x02, 0x75, 0x03, 0x00, 0x00, 0xb5, 0x01, 0xfc, 0x03, 0x05, 0x05, 0x00, 0x00, 0xb5, -0x01, 0x0a, 0x04, 0x05, 0x05, 0x00, 0x00, 0x54, 0x03, 0x01, 0x06, 0x7b, 0x06, 0x00, 0x00, 0x55, -0x03, 0xdc, 0x06, 0x03, 0x07, 0x00, 0x00, 0x5b, 0x03, 0x60, 0x05, 0x9c, 0x05, 0x00, 0x00, 0x39, -0x75, 0x20, 0x07, 0x91, 0x07, 0x00, 0x00, 0x44, 0x75, 0xe6, 0x07, 0x27, 0x08, 0x00, 0x00, 0x00, -0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, -0x02, 0x03, 0x00, 0x00, 0x7c, 0x03, 0x02, 0x01, 0x00, 0x22, 0xfd, 0x04, 0x02, 0x01, 0x00, 0xf5, -0xfc, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, 0x02, 0x01, 0x00, 0x2f, 0x7b, 0x09, 0x04, 0x09, 0x00, -0x28, 0x5b, 0x00, 0x1b, 0x0a, 0x04, 0x09, 0x00, 0x29, 0x5d, 0x00, 0x1d, 0x0b, 0x02, 0x01, 0x00, -0x3d, 0x7d, 0x0c, 0x04, 0x08, 0xe1, 0x3f, 0x5c, 0x00, 0x1c, 0x0d, 0x02, 0x07, 0xcb, 0xc8, 0xce, -0x10, 0x42, 0x03, 0x00, 0x00, 0x40, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0xc5, 0x00, 0x7a, 0x2c, -0x5a, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, -0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x41, 0x00, 0x81, 0x9a, 0x1b, 0x02, -0x04, 0x2b, 0x2a, 0xc9, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x41, 0x00, 0x94, 0x99, 0x28, 0x41, -0x00, 0x84, 0x8e, 0x29, 0x04, 0x0c, 0x27, 0xf8, 0xca, 0x00, 0x1e, 0x2c, 0xc5, 0x00, 0x79, 0x15, -0x59, 0x15, 0x3c, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x42, 0x03, 0x00, 0x00, 0x3e, -0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x42, 0x00, 0x6e, 0x4e, 0x23, 0x32, 0x42, 0x03, 0x00, 0x00, -0xe6, 0x33, 0x01, 0x01, 0x00, 0x3b, 0x34, 0x01, 0x01, 0x00, 0x3a, 0x35, 0x04, 0x0c, 0x2d, 0x5f, -0x00, 0x00, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x2a, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x02, 0x01, 0x00, 0xfb, 0xad, 0x03, 0x01, 0x02, 0xfd, -0xa0, 0x04, 0x01, 0x00, 0xfc, 0x9c, 0x05, 0x01, 0x00, 0xac, 0xcf, 0x06, 0x01, 0x02, 0xab, 0xa0, -0x07, 0x01, 0x02, 0xf3, 0xa0, 0x08, 0x01, 0x02, 0x7b, 0xa0, 0x09, 0x01, 0x02, 0x5b, 0xa0, 0x0a, -0x01, 0x00, 0x5d, 0xf1, 0x0b, 0x01, 0x00, 0x7d, 0xf8, 0x0c, 0x01, 0x00, 0x5c, 0xa8, 0x0d, 0x01, -0x03, 0xce, 0xa0, 0x10, 0x01, 0x02, 0x40, 0xa0, 0x11, 0x10, 0x00, 0x00, 0x12, 0x10, 0x00, 0x00, -0x13, 0x01, 0x00, 0xf4, 0xa9, 0x14, 0x41, 0x00, 0xe7, 0xe8, 0x15, 0x85, 0x02, 0xbe, 0x2c, 0xa0, -0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x10, 0x00, 0x00, 0x17, 0x10, 0x00, -0x00, 0x18, 0x41, 0x00, 0x9b, 0x9d, 0x19, 0x10, 0x00, 0x00, 0x1a, 0x01, 0x03, 0xcc, 0xcd, 0x1b, -0x01, 0x01, 0xc9, 0xee, 0x1e, 0x41, 0x00, 0x91, 0x92, 0x1f, 0x01, 0x00, 0xe1, 0xf5, 0x20, 0x41, -0x00, 0xd0, 0xd1, 0x21, 0x01, 0x02, 0xa6, 0xa0, 0x22, 0x10, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, -0x24, 0x10, 0x00, 0x00, 0x25, 0x01, 0x02, 0x26, 0xa0, 0x26, 0x01, 0x03, 0xc8, 0xa0, 0x27, 0x01, -0x03, 0xcb, 0xa0, 0x28, 0x01, 0x03, 0xca, 0xa0, 0x29, 0x01, 0x00, 0xaa, 0xdd, 0x2b, 0x10, 0x00, -0x00, 0x2c, 0x85, 0x00, 0xae, 0x15, 0x3c, 0x15, 0x3c, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, -0x2d, 0x01, 0x00, 0xaf, 0x3e, 0x2e, 0x01, 0x00, 0xbd, 0xb8, 0x2f, 0x10, 0x00, 0x00, 0x30, 0x10, -0x00, 0x00, 0x31, 0x01, 0x02, 0x23, 0xa0, 0x32, 0x01, 0x00, 0xe6, 0xa7, 0x33, 0x01, 0x02, 0x9e, -0xa0, 0x34, 0x01, 0x00, 0xfa, 0xf6, 0x35, 0x10, 0x00, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x78, 0x56, 0x10, 0x00, 0x00, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, -0x02, 0x01, 0x00, 0xfb, 0xad, 0x03, 0x01, 0x02, 0xfd, 0xa0, 0x04, 0x01, 0x00, 0xfc, 0x9c, 0x05, -0x01, 0x00, 0xac, 0xcf, 0x06, 0x01, 0x02, 0xab, 0xa0, 0x07, 0x01, 0x02, 0xf3, 0xa0, 0x08, 0x01, -0x02, 0x7b, 0xa0, 0x09, 0x01, 0x02, 0x5b, 0xa0, 0x0a, 0x01, 0x00, 0x5d, 0xf1, 0x0b, 0x01, 0x00, -0x7d, 0xf8, 0x0c, 0x01, 0x00, 0x5c, 0xa8, 0x0d, 0x01, 0x03, 0xce, 0xa0, 0x10, 0x01, 0x02, 0x40, -0xa0, 0x11, 0x10, 0x00, 0x00, 0x12, 0x10, 0x00, 0x00, 0x13, 0x01, 0x00, 0xf4, 0xa9, 0x14, 0x41, -0x00, 0xe7, 0xe8, 0x15, 0x85, 0x02, 0xbe, 0x2c, 0xa0, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, -0x00, 0x2c, 0x16, 0x10, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x18, 0x41, 0x00, 0x9b, 0x9d, 0x19, -0x10, 0x00, 0x00, 0x1a, 0x01, 0x03, 0xcc, 0xcd, 0x1b, 0x01, 0x01, 0xc9, 0xee, 0x1e, 0x41, 0x00, -0x91, 0x92, 0x1f, 0x01, 0x00, 0xe1, 0xf5, 0x20, 0x41, 0x00, 0xd0, 0xd1, 0x21, 0x01, 0x02, 0xa6, -0xa0, 0x22, 0x10, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x25, 0x01, 0x02, -0x26, 0xa0, 0x26, 0x01, 0x03, 0xc8, 0xa0, 0x27, 0x01, 0x03, 0xcb, 0xa0, 0x28, 0x01, 0x03, 0xca, -0xa0, 0x29, 0x01, 0x00, 0xaa, 0xdd, 0x2b, 0x10, 0x00, 0x00, 0x2c, 0x85, 0x00, 0xae, 0x15, 0x3c, -0x15, 0x3c, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x01, 0x00, 0xaf, 0x3e, 0x2e, 0x01, -0x00, 0xbd, 0xb8, 0x2f, 0x10, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x31, 0x01, 0x02, 0x23, 0xa0, -0x32, 0x01, 0x00, 0xe6, 0xa7, 0x33, 0x01, 0x02, 0x9e, 0xa0, 0x34, 0x01, 0x00, 0xfa, 0xf6, 0x35, -0x10, 0x00, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x56, 0x10, 0x00, 0x00, 0x00, -0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, -0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, -0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, -0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, -0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, -0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, -0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, -0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf8, 0x03, 0x61, 0x86, 0x41, 0x8f, 0x20, 0xf8, 0xf7, 0x03, -0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, 0x00, 0x04, 0x01, 0x01, 0x00, 0x15, 0x2a, 0x04, 0x1f, 0x00, -0x00, 0x00, 0x00, 0x7d, 0x00, 0x02, 0x01, 0x01, 0xa0, 0xad, 0x03, 0x01, 0x02, 0xfd, 0xa0, 0x04, -0x01, 0x01, 0xa0, 0x9c, 0x05, 0x01, 0x02, 0xac, 0xa0, 0x06, 0x01, 0x02, 0xab, 0xa0, 0x07, 0x10, -0x00, 0x00, 0x08, 0x01, 0x02, 0x7b, 0xa0, 0x09, 0x01, 0x02, 0x5b, 0xa0, 0x0a, 0x01, 0x00, 0x5d, -0xf1, 0x0b, 0x01, 0x00, 0x7d, 0xf8, 0x0c, 0x01, 0x00, 0x5c, 0xa8, 0x0d, 0x01, 0x03, 0xce, 0xa0, -0x10, 0x01, 0x02, 0x40, 0xa0, 0x11, 0x10, 0x00, 0x00, 0x12, 0x10, 0x00, 0x00, 0x13, 0x01, 0x02, -0x14, 0xa0, 0x14, 0x10, 0x00, 0x00, 0x15, 0x85, 0x02, 0x9d, 0x2c, 0xa0, 0x2c, 0x00, 0x2c, 0x00, -0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x10, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x18, 0x10, 0x00, -0x00, 0x19, 0x10, 0x00, 0x00, 0x1a, 0x01, 0x03, 0xcc, 0xcd, 0x1b, 0x01, 0x03, 0xc9, 0xa0, 0x1e, -0x41, 0x00, 0x91, 0x92, 0x1f, 0x01, 0x00, 0xe1, 0x15, 0x20, 0x10, 0x00, 0x00, 0x21, 0x01, 0x02, -0xa6, 0xa0, 0x22, 0x10, 0x00, 0x00, 0x23, 0x10, 0x00, 0x00, 0x24, 0x10, 0x00, 0x00, 0x25, 0x01, -0x02, 0x26, 0xa0, 0x26, 0x01, 0x03, 0xc8, 0xa0, 0x27, 0x01, 0x03, 0xcb, 0xa0, 0x28, 0x01, 0x03, -0xca, 0xa0, 0x29, 0x01, 0x02, 0xaa, 0xa0, 0x2b, 0x10, 0x00, 0x00, 0x2c, 0x85, 0x00, 0xae, 0x15, -0x3c, 0x15, 0x3c, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x01, 0x00, 0xaf, 0x3e, 0x2e, -0x01, 0x02, 0x9b, 0xa0, 0x2f, 0x10, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x31, 0x01, 0x02, 0x23, -0xa0, 0x32, 0x01, 0x00, 0xe6, 0xa7, 0x33, 0x10, 0x00, 0x00, 0x34, 0x01, 0x00, 0xfa, 0xf6, 0x35, -0x10, 0x00, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x56, 0x10, 0x00, 0x00, 0x00, -0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, 0x7e, 0x03, -0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, -0x75, 0x96, 0x20, 0x5e, 0x27, 0x07, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, -0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, -0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0xf8, 0x03, 0x61, 0x86, 0x41, 0x8f, -0x20, 0xf8, 0x2c, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, 0x00, 0x03, 0x01, 0x03, 0x00, 0xcc, -0x09, 0x03, 0x07, 0x00, 0x00, 0x00, 0xae, 0x0a, 0x03, 0x07, 0x00, 0x00, 0x00, 0xaf, 0x0d, 0x02, -0x07, 0x00, 0x00, 0xcd, 0x12, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x18, 0x03, 0x03, 0x00, 0x00, 0xab, -0xac, 0x1e, 0x03, 0x03, 0x00, 0x00, 0x86, 0x8f, 0x27, 0x03, 0x03, 0x00, 0x00, 0x9b, 0x9d, 0x28, -0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x00, 0x60, 0x07, 0x61, 0x85, 0x65, 0x8a, 0x75, 0x97, 0x41, -0xb7, 0x45, 0xd4, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, -0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, -0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x27, 0x07, 0x61, 0xa0, 0x65, 0x82, 0x6f, 0xa2, 0x41, -0xb5, 0x45, 0x90, 0x4f, 0xe0, 0x20, 0x27, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, -0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, -0xf3, 0x20, 0x22, 0x2c, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, 0x00, 0x03, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, 0x03, 0x00, 0x00, 0xaa, 0x0d, 0x02, -0x07, 0xc8, 0xc9, 0xa0, 0x12, 0x03, 0x03, 0x00, 0x00, 0xa9, 0xa8, 0x13, 0x41, 0x00, 0x72, 0x52, -0x14, 0x41, 0x00, 0x74, 0x54, 0x15, 0xc5, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0xbe, 0x2c, 0xbd, 0x2c, -0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x03, 0x03, 0x00, 0x00, 0xfb, 0xeb, 0x17, 0x03, 0x03, 0x00, 0x00, -0x85, 0xde, 0x18, 0x03, 0x03, 0x00, 0x00, 0x8b, 0x8a, 0x1b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x1e, -0x03, 0x03, 0x00, 0x00, 0xa5, 0xa4, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, 0x43, 0x00, 0x64, 0x44, -0xd0, 0xd1, 0x26, 0x43, 0x00, 0x6c, 0x4c, 0x88, 0x9d, 0x29, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x32, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x00, 0xef, 0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, 0xa1, -0x6c, 0x92, 0x6e, 0xe4, 0x6f, 0xa2, 0x72, 0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, 0xab, -0x41, 0xb5, 0x43, 0x8f, 0x45, 0x90, 0x49, 0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, 0xe8, -0x53, 0x97, 0x55, 0xe9, 0x59, 0xed, 0x5a, 0x8d, 0x20, 0xef, 0x60, 0x15, 0x63, 0x9f, 0x64, 0xd4, -0x65, 0xd8, 0x6c, 0x96, 0x6e, 0xe5, 0x6f, 0x93, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa7, -0x43, 0xac, 0x44, 0xd2, 0x45, 0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x4f, 0xe2, 0x52, 0xfc, 0x53, 0xe6, -0x54, 0x9b, 0x5a, 0xa6, 0x20, 0x60, 0x00, 0x0d, 0x02, 0x07, 0xc8, 0xa0, 0xa0, 0x1b, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x22, 0x41, 0x00, 0x67, 0x47, 0x23, 0x41, 0x00, -0x68, 0x48, 0x24, 0x41, 0x00, 0x6a, 0x4a, 0x29, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x00, 0x5e, 0x0d, -0x63, 0x86, 0x67, 0x9b, 0x68, 0xa9, 0x6a, 0x9f, 0x73, 0xc7, 0x75, 0xed, 0x43, 0x8f, 0x47, 0x9d, -0x48, 0xa8, 0x4a, 0xac, 0x53, 0xc6, 0x55, 0xec, 0x20, 0x5e, 0x00, 0x03, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x00, 0x01, 0xa0, 0x0d, 0x02, 0x07, 0xc8, 0xc9, -0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, -0x54, 0x17, 0x43, 0x03, 0x00, 0x00, 0x8b, 0xd8, 0x19, 0x41, 0x00, 0x70, 0x50, 0x1b, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x1e, 0x43, 0x03, 0x00, 0x00, 0xc6, 0xc7, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, -0x41, 0x00, 0x64, 0x44, 0x22, 0x41, 0x00, 0x67, 0x47, 0x23, 0x41, 0x00, 0x68, 0x48, 0x25, 0x41, -0x00, 0x6b, 0x4b, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x28, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x29, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x32, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x00, 0xef, 0x0b, 0x63, 0x86, -0x67, 0xd0, 0x72, 0xe8, 0x73, 0xfa, 0x7a, 0xaa, 0x43, 0x8f, 0x47, 0xd1, 0x52, 0xf6, 0x53, 0xfb, -0x5a, 0xab, 0x20, 0xef, 0x60, 0x1d, 0x63, 0xac, 0x64, 0x8a, 0x65, 0x88, 0x67, 0xdd, 0x68, 0xbd, -0x69, 0x8c, 0x6b, 0x85, 0x6c, 0xf2, 0x6e, 0xe4, 0x70, 0x9d, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, -0x7a, 0xa8, 0x43, 0xad, 0x44, 0xd4, 0x45, 0xd2, 0x47, 0xde, 0x48, 0xbe, 0x49, 0xd7, 0x4b, 0xb7, -0x4c, 0xf1, 0x4e, 0xe5, 0x50, 0xe1, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, 0xa9, 0x20, 0x60, -0x00, 0x03, 0x01, 0x03, 0x00, 0xcb, 0x0d, 0x02, 0x07, 0xca, 0x00, 0xcd, 0x12, 0x02, 0x03, 0x00, -0x00, 0xd5, 0x17, 0x43, 0x03, 0x00, 0x00, 0x9e, 0x9f, 0x18, 0x43, 0x03, 0x00, 0x00, 0xab, 0xac, -0x1b, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x1e, 0x43, 0x03, 0x00, 0x00, 0x86, 0x8f, 0x27, 0x43, 0x03, -0x00, 0x00, 0x9b, 0x9d, 0x28, 0x43, 0x03, 0x00, 0x00, 0x91, 0x92, 0x29, 0x02, 0x07, 0x00, 0x00, -0xc9, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, -0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x5e, 0x0d, 0x61, 0x83, 0x65, 0x88, -0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x79, 0xbd, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, -0x55, 0xea, 0x59, 0xbe, 0x20, 0x5e, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, -0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, -0x20, 0x27, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, -0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x7e, 0x0b, -0x61, 0x87, 0x65, 0xd0, 0x69, 0xe7, 0x6f, 0xf9, 0x75, 0xf7, 0x41, 0x80, 0x45, 0xd1, 0x49, 0xe8, -0x4f, 0xdd, 0x55, 0xef, 0x20, 0x7e, 0x2c, 0x07, 0x65, 0xc6, 0x6f, 0xa4, 0x94, 0xe4, 0x45, 0xc7, -0x4f, 0xa5, 0x99, 0xe5, 0x20, 0x2c, 0x00, 0xf4, 0xc5, 0x03, 0x04, 0x00, 0x00, 0x48, 0x55, 0x05, -0x02, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, 0xd3, 0x01, 0x44, -0x02, 0x00, 0x00, 0x5a, 0x03, 0x45, 0x01, 0x4c, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x4c, -0x01, 0x00, 0x00, 0xb5, 0xe1, 0x05, 0x03, 0x5f, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07, 0x00, 0xcc, -0xc8, 0x03, 0x01, 0x03, 0x00, 0xcd, 0x04, 0x03, 0x05, 0x00, 0x2b, 0xc9, 0x1e, 0x05, 0x01, 0x01, -0x00, 0x21, 0x06, 0x02, 0x07, 0x00, 0x00, 0xca, 0x07, 0x01, 0x01, 0x00, 0x2f, 0x08, 0x02, 0x05, -0x00, 0x3d, 0xcb, 0x09, 0x02, 0x01, 0x00, 0x28, 0xfa, 0x0a, 0x02, 0x01, 0x00, 0x29, 0xef, 0x0b, -0x41, 0x00, 0x94, 0x99, 0x0c, 0x42, 0x00, 0x81, 0x9a, 0xf9, 0x0d, 0xc2, 0x04, 0xa2, 0x0d, 0xe0, -0x00, 0xce, 0x83, 0x10, 0x42, 0x03, 0x00, 0x00, 0x5c, 0x11, 0x42, 0x03, 0x00, 0x00, 0x7c, 0x12, -0x42, 0x00, 0x65, 0x45, 0x8e, 0x13, 0x42, 0x03, 0x00, 0x00, 0xf5, 0x14, 0x42, 0x03, 0x00, 0x00, -0xcf, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x42, 0x00, 0x69, 0x49, -0xd6, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x42, 0x03, 0xa0, 0xa0, 0xf6, 0x1b, 0x42, 0x00, 0xa3, -0xe9, 0x9e, 0x1e, 0x42, 0x00, 0x61, 0x41, 0x84, 0x21, 0x42, 0x03, 0x00, 0x00, 0x5b, 0x22, 0x42, -0x03, 0x00, 0x00, 0x5d, 0x24, 0x42, 0x03, 0x00, 0x00, 0xa1, 0x27, 0x42, 0x00, 0x82, 0x90, 0x24, -0x28, 0x42, 0x00, 0xa0, 0xb5, 0xe1, 0x29, 0x42, 0x00, 0xa1, 0xd6, 0x30, 0x2b, 0x42, 0x03, 0xa0, -0xa0, 0x5c, 0x2c, 0x42, 0x00, 0x7a, 0x5a, 0x3e, 0x2d, 0x42, 0x03, 0x00, 0x00, 0x23, 0x2e, 0x42, -0x00, 0x63, 0x43, 0x26, 0x2f, 0x42, 0x03, 0x00, 0x00, 0x40, 0x30, 0x42, 0x03, 0x00, 0x00, 0x7b, -0x31, 0x42, 0x00, 0x6e, 0x4e, 0x7d, 0x32, 0x42, 0x03, 0x00, 0x00, 0x3c, 0x33, 0x02, 0x00, 0x2c, -0x3f, 0x3b, 0x34, 0x02, 0x00, 0x2e, 0x3a, 0x3e, 0x35, 0x03, 0x00, 0x2d, 0x5f, 0x2a, 0x1f, 0x39, -0x00, 0x00, 0x20, 0x00, 0x16, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x7e, 0x07, 0x61, 0xc6, 0x6e, -0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, -0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, -0xea, 0x20, 0x5e, 0xf8, 0x03, 0x61, 0x86, 0x41, 0x8f, 0x20, 0xf8, 0x60, 0x0b, 0x61, 0x85, 0x65, -0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, -0xeb, 0x20, 0x60, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, -0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0x22, -0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, -0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, -0xf7, 0x00, 0x02, 0x02, 0x03, 0x00, 0xce, 0x7e, 0x03, 0x02, 0x07, 0x00, 0xd0, 0xc8, 0x04, 0x01, -0x03, 0x00, 0xcf, 0x05, 0x02, 0x07, 0x00, 0x00, 0xca, 0x06, 0x02, 0x07, 0x00, 0x00, 0xcb, 0x07, -0x02, 0x07, 0x00, 0x00, 0xcc, 0x08, 0x02, 0x03, 0x00, 0x00, 0x60, 0x09, 0x02, 0x07, 0x00, 0x00, -0xcd, 0x0b, 0x42, 0x03, 0x00, 0x00, 0xf1, 0x0d, 0xc2, 0x05, 0x00, 0x0d, 0xe0, 0x00, 0xd1, 0x83, -0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, 0x54, 0x16, 0x42, 0x03, 0x00, 0x00, 0xaa, -0x1a, 0x41, 0x00, 0x8b, 0x8a, 0x1f, 0x42, 0x00, 0x73, 0x53, 0xd0, 0x20, 0x42, 0x00, 0x64, 0x44, -0xd1, 0x25, 0x42, 0x03, 0x00, 0x00, 0x88, 0x26, 0x42, 0x00, 0x6c, 0x4c, 0x9d, 0x2b, 0x41, 0x00, -0xfb, 0xeb, 0x00, 0xf3, 0x13, 0x63, 0x9f, 0x64, 0xd4, 0x65, 0xd8, 0x6c, 0x96, 0x6e, 0xe5, 0x72, -0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa7, 0x43, 0xac, 0x44, 0xd2, 0x45, 0xb7, 0x4c, 0x95, 0x4e, -0xd5, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, 0xa6, 0x20, 0xf3, 0x5e, 0x07, 0x61, 0x83, 0x69, -0x8c, 0x6f, 0x93, 0x41, 0xb6, 0x49, 0xd7, 0x4f, 0xe2, 0x20, 0x5e, 0xf4, 0x03, 0x61, 0xc7, 0x41, -0xc6, 0x20, 0xf4, 0xf8, 0x03, 0x75, 0x85, 0x55, 0xde, 0x20, 0xf8, 0xf2, 0x05, 0x61, 0xa5, 0x65, -0xa9, 0x41, 0xa4, 0x45, 0xa8, 0x20, 0xf2, 0xfa, 0x03, 0x7a, 0xbe, 0x5a, 0xbd, 0x20, 0xfa, 0x27, -0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, 0xa1, 0x6c, 0x92, 0x6e, 0xe4, 0x6f, 0xa2, 0x72, -0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, 0xab, 0x41, 0xb5, 0x43, 0x8f, 0x45, 0x90, 0x49, -0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, 0xe8, 0x53, 0x97, 0x55, 0xe9, 0x59, 0xed, 0x5a, -0x8d, 0x20, 0x27, 0x2b, 0x05, 0x6f, 0x8b, 0x75, 0xfb, 0x4f, 0x8a, 0x55, 0xeb, 0x20, 0x2b, 0x22, -0x09, 0x61, 0x84, 0x65, 0x89, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x45, 0xd3, 0x4f, 0x99, 0x55, -0x9a, 0x20, 0x22, 0xf7, 0x07, 0x63, 0x87, 0x73, 0xad, 0x74, 0xee, 0x43, 0x80, 0x53, 0xb8, 0x54, -0xdd, 0x20, 0xf7, 0x00, 0x02, 0x01, 0x03, 0x00, 0xcc, 0x03, 0x01, 0x03, 0x00, 0xce, 0x04, 0x01, -0x03, 0x00, 0xcd, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x0b, 0x42, 0x07, 0x00, 0x00, 0xcd, 0x0c, -0x42, 0x07, 0x00, 0x00, 0xce, 0x0d, 0x42, 0x05, 0x00, 0x95, 0xcf, 0x13, 0x42, 0x03, 0x00, 0x00, -0x15, 0x14, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x17, 0x42, 0x03, 0x00, 0x00, 0x8d, 0x19, 0x42, 0x03, -0x00, 0x00, 0x9f, 0x1a, 0x41, 0x00, 0x93, 0xa7, 0x1b, 0x42, 0x05, 0x00, 0x97, 0xa0, 0x28, 0x41, -0x01, 0x00, 0x8f, 0x29, 0x41, 0x01, 0x00, 0x8d, 0x2b, 0x41, 0x00, 0x96, 0x98, 0x00, 0x7e, 0x03, -0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x04, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x20, 0x5e, -0xf8, 0x02, 0x61, 0x86, 0x20, 0xf8, 0x60, 0x03, 0x61, 0x85, 0x65, 0x8a, 0x20, 0x60, 0x27, 0x0b, -0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0x8f, 0x45, 0x90, 0x49, 0x8d, -0x4f, 0x95, 0x55, 0x97, 0x20, 0x27, 0x2b, 0x05, 0x6f, 0x93, 0x75, 0x96, 0x4f, 0xa7, 0x55, 0x98, -0x20, 0x2b, 0x22, 0x09, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, -0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x2c, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, 0x00, 0x37, -0xcf, 0x03, 0x04, 0xd0, 0x00, 0x48, 0x55, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, -0x00, 0x00, 0x00, 0x54, 0x03, 0xe3, 0x01, 0x54, 0x02, 0x00, 0x00, 0x5a, 0x03, 0x55, 0x01, 0x5c, -0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0xb5, 0xe1, 0x15, 0x03, 0x69, -0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07, 0x00, 0xcc, -0xc8, 0x03, 0x01, 0x03, 0x00, 0xcd, 0x04, 0x03, 0x05, 0x00, 0x2b, 0xc9, 0x1e, 0x05, 0x01, 0x01, -0x00, 0x21, 0x06, 0x02, 0x07, 0x00, 0x00, 0xca, 0x07, 0x01, 0x01, 0x00, 0x2f, 0x08, 0x02, 0x05, -0x00, 0x3d, 0xcb, 0x09, 0x02, 0x01, 0x00, 0x28, 0xfa, 0x0a, 0x02, 0x01, 0x00, 0x29, 0xef, 0x0b, -0x41, 0x00, 0x94, 0x99, 0x0c, 0x42, 0x00, 0x81, 0x9a, 0xf9, 0x0d, 0xc2, 0x04, 0xa2, 0x0d, 0xe0, -0x00, 0xce, 0x83, 0x10, 0x42, 0x03, 0x00, 0x00, 0x5c, 0x11, 0x42, 0x03, 0x00, 0x00, 0x7c, 0x12, -0x42, 0x00, 0x65, 0x45, 0x8e, 0x15, 0xc4, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, -0x00, 0x2c, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x42, 0x00, 0x69, 0x49, 0xd6, 0x18, 0x41, 0x00, -0x6f, 0x4f, 0x1a, 0x42, 0x03, 0xa0, 0xa0, 0xf6, 0x1b, 0x42, 0x00, 0xa3, 0xe9, 0x9e, 0x1e, 0x42, -0x00, 0x61, 0x41, 0x84, 0x21, 0x42, 0x03, 0x00, 0x00, 0x5b, 0x22, 0x42, 0x03, 0x00, 0x00, 0x5d, -0x24, 0x42, 0x03, 0x00, 0x00, 0xa1, 0x27, 0x42, 0x00, 0x82, 0x90, 0x24, 0x28, 0x42, 0x00, 0xa0, -0xb5, 0xe1, 0x29, 0x01, 0x00, 0x30, 0xf5, 0x2b, 0x42, 0x03, 0xa0, 0xa0, 0xcf, 0x2c, 0xc4, 0x00, -0x79, 0x15, 0x59, 0x15, 0x3e, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x42, 0x03, 0x00, 0x00, 0x23, -0x2e, 0x42, 0x00, 0x63, 0x43, 0x26, 0x2f, 0x42, 0x03, 0x00, 0x00, 0x40, 0x30, 0x42, 0x03, 0x00, -0x00, 0x7b, 0x31, 0x42, 0x00, 0x6e, 0x4e, 0x7d, 0x32, 0x42, 0x03, 0x00, 0x00, 0x3c, 0x33, 0x02, -0x00, 0x2c, 0x3f, 0x3b, 0x34, 0x02, 0x00, 0x2e, 0x3a, 0x3e, 0x35, 0x03, 0x00, 0x2d, 0x5f, 0x2a, -0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, 0x42, 0x00, 0xa1, 0xd6, 0x3c, 0x00, 0x16, 0x42, 0x03, 0x00, -0x00, 0xd5, 0x00, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, -0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, -0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf8, 0x03, 0x61, 0x86, 0x41, -0x8f, 0x20, 0xf8, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, -0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x27, 0x0d, 0x61, 0xa0, 0x65, -0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, -0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0x22, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, -0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, -0x22, 0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, 0x00, 0x02, 0x02, 0x03, 0x00, 0xce, 0x7e, -0x03, 0x02, 0x07, 0x00, 0xd0, 0xc8, 0x04, 0x01, 0x03, 0x00, 0xcf, 0x05, 0x02, 0x07, 0x00, 0x00, -0xca, 0x06, 0x02, 0x07, 0x00, 0x00, 0xcb, 0x07, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x08, 0x02, 0x03, -0x00, 0x00, 0x60, 0x09, 0x02, 0x07, 0x00, 0x00, 0xcd, 0x0b, 0x42, 0x03, 0x00, 0x00, 0xf1, 0x0d, -0xc2, 0x05, 0x00, 0x0d, 0xe0, 0x00, 0xd1, 0x83, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, -0x74, 0x54, 0x16, 0x42, 0x03, 0x00, 0x00, 0xaa, 0x1a, 0x41, 0x00, 0x8b, 0x8a, 0x1f, 0x42, 0x00, -0x73, 0x53, 0xd0, 0x20, 0x42, 0x00, 0x64, 0x44, 0xd1, 0x25, 0x42, 0x03, 0x00, 0x00, 0x88, 0x26, -0x42, 0x00, 0x6c, 0x4c, 0x9d, 0x2b, 0x41, 0x00, 0xfb, 0xeb, 0x00, 0xf3, 0x13, 0x63, 0x9f, 0x64, -0xd4, 0x65, 0xd8, 0x6c, 0x96, 0x6e, 0xe5, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa7, 0x43, -0xac, 0x44, 0xd2, 0x45, 0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, -0xa6, 0x20, 0xf3, 0x5e, 0x07, 0x61, 0x83, 0x69, 0x8c, 0x6f, 0x93, 0x41, 0xb6, 0x49, 0xd7, 0x4f, -0xe2, 0x20, 0x5e, 0xf4, 0x03, 0x61, 0xc7, 0x41, 0xc6, 0x20, 0xf4, 0xf8, 0x03, 0x75, 0x85, 0x55, -0xde, 0x20, 0xf8, 0xf2, 0x05, 0x61, 0xa5, 0x65, 0xa9, 0x41, 0xa4, 0x45, 0xa8, 0x20, 0xf2, 0xfa, -0x03, 0x7a, 0xbe, 0x5a, 0xbd, 0x20, 0xfa, 0x27, 0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, -0xa1, 0x6c, 0x92, 0x6e, 0xe4, 0x6f, 0xa2, 0x72, 0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, -0xab, 0x41, 0xb5, 0x43, 0x8f, 0x45, 0x90, 0x49, 0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, -0xe8, 0x53, 0x97, 0x55, 0xe9, 0x59, 0xed, 0x5a, 0x8d, 0x20, 0x27, 0x2b, 0x05, 0x6f, 0x8b, 0x75, -0xfb, 0x4f, 0x8a, 0x55, 0xeb, 0x20, 0x2b, 0x22, 0x09, 0x61, 0x84, 0x65, 0x89, 0x6f, 0x94, 0x75, -0x81, 0x41, 0x8e, 0x45, 0xd3, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0xf7, 0x07, 0x63, 0x87, 0x73, -0xad, 0x74, 0xee, 0x43, 0x80, 0x53, 0xb8, 0x54, 0xdd, 0x20, 0xf7, 0x00, 0x02, 0x01, 0x03, 0x00, -0xcc, 0x03, 0x01, 0x03, 0x00, 0xce, 0x04, 0x01, 0x03, 0x00, 0xcd, 0x0a, 0x02, 0x07, 0x00, 0x00, -0xcc, 0x0b, 0x42, 0x07, 0x00, 0x00, 0xcd, 0x0c, 0x42, 0x07, 0x00, 0x00, 0xce, 0x0d, 0x42, 0x05, -0x00, 0x95, 0xcf, 0x17, 0x42, 0x03, 0x00, 0x00, 0x8d, 0x19, 0x42, 0x03, 0x00, 0x00, 0x9f, 0x1a, -0x41, 0x00, 0x93, 0xa7, 0x1b, 0x42, 0x05, 0x00, 0x97, 0xa0, 0x28, 0x41, 0x01, 0x00, 0x8f, 0x29, -0x01, 0x01, 0x00, 0x15, 0x2b, 0x42, 0x04, 0x96, 0x98, 0xa0, 0x56, 0x41, 0x01, 0x00, 0x8d, 0x00, -0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x04, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, -0x20, 0x5e, 0xf8, 0x02, 0x61, 0x86, 0x20, 0xf8, 0x60, 0x03, 0x61, 0x85, 0x65, 0x8a, 0x20, 0x60, -0x27, 0x0b, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0x8f, 0x45, 0x90, -0x49, 0x8d, 0x4f, 0x95, 0x55, 0x97, 0x20, 0x27, 0x2b, 0x05, 0x6f, 0x93, 0x75, 0x96, 0x4f, 0xa7, -0x55, 0x98, 0x20, 0x2b, 0x22, 0x09, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, -0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x2c, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, -0x00, 0x2d, 0x83, 0x03, 0x09, 0x00, 0x00, 0x49, 0x54, 0x2c, 0x8d, 0x00, 0x49, 0x54, 0x08, 0x04, -0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xfb, 0x00, 0x00, 0x00, -0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x01, 0xf5, 0x00, 0x00, 0x00, -0x00, 0x00, 0x54, 0x03, 0x16, 0x02, 0x59, 0x02, 0x00, 0x00, 0x65, 0x03, 0x6a, 0x02, 0x00, 0x00, -0x00, 0x00, 0x65, 0x03, 0x93, 0x02, 0x44, 0x03, 0x00, 0x00, 0x37, 0x75, 0x08, 0x01, 0x81, 0x01, -0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x02, 0x01, 0x00, 0x9c, 0x23, 0x07, 0x01, 0x01, -0x00, 0x26, 0x08, 0x02, 0x01, 0x00, 0x2f, 0x7b, 0x09, 0x04, 0x09, 0x00, 0x28, 0x5b, 0x00, 0x1b, -0x0a, 0x04, 0x09, 0x00, 0x29, 0x5d, 0x00, 0x1d, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, 0x01, -0x00, 0x27, 0x3f, 0x0d, 0x04, 0x08, 0x8d, 0x5e, 0x7e, 0x00, 0x1e, 0x10, 0x42, 0x03, 0x00, 0x00, -0x40, 0x1a, 0x03, 0x00, 0x8a, 0x82, 0x5b, 0x7b, 0x1b, 0x03, 0x00, 0x2b, 0x2a, 0x5d, 0x7d, 0x27, -0x02, 0x00, 0x95, 0x87, 0x40, 0x28, 0x02, 0x00, 0x85, 0xf8, 0x23, 0x29, 0x04, 0x0c, 0x5c, 0x7c, -0x00, 0x00, 0x1c, 0x2b, 0x02, 0x00, 0x97, 0xf5, 0x60, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, -0x02, 0x01, 0x00, 0x3a, 0x3e, 0x35, 0x04, 0x0c, 0x2d, 0x5f, 0x00, 0x00, 0x1f, 0x56, 0x01, 0x00, -0x3c, 0x3e, 0x00, 0x2b, 0x01, 0x01, 0x00, 0x15, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x12, -0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x03, 0x01, 0x03, 0x00, 0xc8, 0x04, 0x01, 0x03, 0x00, 0xa0, -0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x0c, 0x00, 0x01, 0xc9, 0x0d, 0x01, 0x03, 0x00, 0xca, 0x12, -0x42, 0x00, 0x65, 0x45, 0xd5, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, -0x41, 0x00, 0x69, 0x49, 0x18, 0x43, 0x00, 0x6f, 0x4f, 0xab, 0xac, 0x1e, 0x43, 0x00, 0x61, 0x41, -0x91, 0x92, 0x1f, 0x42, 0x03, 0x00, 0x00, 0xe1, 0x26, 0x43, 0x03, 0x00, 0x00, 0xf2, 0xf6, 0x28, -0x01, 0x03, 0x00, 0xcc, 0x29, 0x02, 0x03, 0x00, 0x00, 0xfa, 0x2b, 0x02, 0x07, 0x00, 0xcd, 0xcb, -0x2c, 0x42, 0x03, 0x00, 0x00, 0xae, 0x2d, 0x42, 0x03, 0x00, 0x00, 0xaf, 0x2e, 0x43, 0x03, 0x00, -0x00, 0x87, 0x80, 0x31, 0x43, 0x03, 0x00, 0x00, 0xa4, 0xa5, 0x39, 0x00, 0x00, 0x20, 0x00, 0x22, -0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, -0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x27, 0x0b, 0x61, 0xa0, 0x65, -0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, -0xe9, 0x20, 0x27, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, -0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x60, 0x0b, 0x61, 0x85, 0x65, -0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, -0xeb, 0x20, 0x60, 0xf8, 0x0b, 0x61, 0xc6, 0x65, 0xbd, 0x69, 0x9b, 0x6f, 0x9e, 0x75, 0xa9, 0x41, -0xc7, 0x45, 0xbe, 0x49, 0x9d, 0x4f, 0x9f, 0x55, 0xb8, 0x20, 0xf8, 0xf5, 0x0b, 0x61, 0xd0, 0x65, -0xdd, 0x69, 0x9c, 0x6f, 0xe7, 0x75, 0xef, 0x41, 0xd1, 0x45, 0xf9, 0x49, 0xcf, 0x4f, 0xe8, 0x55, -0xf7, 0x20, 0xf5, 0x00, 0x04, 0x01, 0x03, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0xaa, 0x0d, -0x01, 0x03, 0xa0, 0xc8, 0x12, 0x42, 0x03, 0x00, 0x00, 0xaa, 0x1a, 0x00, 0x01, 0xa0, 0x1f, 0x41, -0x00, 0x73, 0x53, 0x20, 0x43, 0x00, 0x64, 0x44, 0xd0, 0xd1, 0x27, 0x00, 0x01, 0xa0, 0x28, 0x00, -0x01, 0xa0, 0x2b, 0x00, 0x01, 0xa0, 0x2c, 0x41, 0x00, 0x7a, 0x5a, 0x2e, 0x43, 0x00, 0x63, 0x43, -0x86, 0x8f, 0x39, 0x00, 0x00, 0x20, 0x00, 0x5e, 0x07, 0x63, 0x9f, 0x73, 0xe7, 0x7a, 0xa7, 0x43, -0xac, 0x53, 0xe6, 0x5a, 0xa6, 0x20, 0x5e, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0x87, 0x0d, 0x00, -0x01, 0xa0, 0x12, 0x02, 0x03, 0x00, 0x00, 0x87, 0x27, 0x01, 0x03, 0xa0, 0xa0, 0x28, 0x01, 0x03, -0xa0, 0xa0, 0x2b, 0x01, 0x03, 0xa0, 0xa0, 0x36, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, -0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0x87, 0x0d, 0x00, 0x01, 0xa0, 0x10, 0x01, 0x00, 0x8b, 0x8c, -0x11, 0x01, 0x02, 0xed, 0xa0, 0x12, 0x42, 0x00, 0xde, 0xa8, 0x87, 0x13, 0x41, 0x00, 0xeb, 0xc7, -0x14, 0x41, 0x00, 0xee, 0xd0, 0x15, 0x41, 0x00, 0xf2, 0xd1, 0x16, 0x41, 0x00, 0xe2, 0xac, 0x17, -0x41, 0x00, 0xe3, 0xad, 0x18, 0x41, 0x00, 0xe9, 0xbe, 0x19, 0x41, 0x00, 0xea, 0xc6, 0x1a, 0x01, -0x03, 0xa0, 0xa0, 0x1e, 0x41, 0x00, 0xd6, 0xa4, 0x1f, 0x41, 0x00, 0xec, 0xcf, 0x20, 0x41, 0x00, -0xdd, 0xa7, 0x21, 0x41, 0x00, 0xf3, 0xd2, 0x22, 0x41, 0x00, 0xd8, 0xa6, 0x23, 0x41, 0x00, 0xe1, -0xaa, 0x24, 0x41, 0x00, 0xe8, 0xbd, 0x25, 0x41, 0x00, 0xe4, 0xb5, 0x26, 0x41, 0x00, 0xe5, 0xb6, -0x27, 0x01, 0x03, 0xc8, 0xa0, 0x28, 0x01, 0x03, 0xc9, 0xa0, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0x2b, 0x01, 0x03, 0xca, 0xa0, 0x2c, 0xc1, 0x00, 0xe0, 0x00, 0xa9, 0x2c, 0x2d, -0x41, 0x00, 0xf4, 0xd3, 0x2e, 0x41, 0x00, 0xf6, 0xd4, 0x2f, 0x41, 0x00, 0xfa, 0xd5, 0x30, 0x41, -0x00, 0xd7, 0xa5, 0x31, 0x41, 0x00, 0xe7, 0xb8, 0x32, 0x41, 0x00, 0xe6, 0xb7, 0x39, 0x00, 0x00, -0x20, 0x00, 0xef, 0x0f, 0xd6, 0x9b, 0xde, 0x9d, 0xe1, 0x9e, 0xe3, 0x9f, 0xe9, 0xa2, 0xf2, 0xa3, -0xfa, 0xfd, 0xa4, 0x86, 0xa8, 0x8d, 0xaa, 0x8f, 0xad, 0x90, 0xbe, 0x92, 0xd1, 0x95, 0xd5, 0x98, -0x20, 0xef, 0xf9, 0x05, 0xe3, 0xa0, 0xf2, 0xfb, 0xad, 0x91, 0xd1, 0x96, 0x20, 0xf9, 0xf7, 0x03, -0xe3, 0xa1, 0xf2, 0xfc, 0x20, 0xf7, 0x00, 0x6e, 0x79, 0x03, 0x04, 0x8e, 0x00, 0x49, 0x54, 0x08, -0x04, 0x2c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xf6, 0x00, 0x00, -0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x01, 0xf0, 0x00, 0x00, -0x00, 0x00, 0x00, 0x54, 0x03, 0x11, 0x02, 0x54, 0x02, 0x00, 0x00, 0x65, 0x03, 0x65, 0x02, 0x00, -0x00, 0x00, 0x00, 0x65, 0x03, 0x8e, 0x02, 0x3f, 0x03, 0x00, 0x00, 0x37, 0x75, 0x03, 0x01, 0x7c, -0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x02, 0x01, 0x00, 0x9c, 0x23, 0x07, 0x01, -0x01, 0x00, 0x26, 0x08, 0x02, 0x01, 0x00, 0x2f, 0x7b, 0x09, 0x04, 0x09, 0x00, 0x28, 0x5b, 0x00, -0x1b, 0x0a, 0x04, 0x09, 0x00, 0x29, 0x5d, 0x00, 0x1d, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, -0x01, 0x00, 0x27, 0x3f, 0x0d, 0x04, 0x0c, 0x8d, 0x5e, 0x00, 0x00, 0x1e, 0x10, 0x42, 0x03, 0x00, -0x00, 0x40, 0x1a, 0x01, 0x00, 0x8a, 0x82, 0x1b, 0x02, 0x00, 0x2b, 0x2a, 0x7e, 0x27, 0x01, 0x00, -0x95, 0x87, 0x28, 0x01, 0x00, 0x85, 0xf8, 0x29, 0x04, 0x0c, 0x5c, 0x7c, 0x00, 0x00, 0x1c, 0x2b, -0x02, 0x00, 0x97, 0xf5, 0x60, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, 0x01, 0x00, 0x3a, -0x3e, 0x35, 0x04, 0x0c, 0x2d, 0x5f, 0x00, 0x00, 0x1f, 0x56, 0x01, 0x00, 0x3c, 0x3e, 0x00, 0x2b, -0x01, 0x01, 0x00, 0x15, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x12, 0x42, 0x03, 0x00, 0x00, -0xd5, 0x00, 0x03, 0x01, 0x03, 0x00, 0xc8, 0x04, 0x01, 0x03, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, -0x00, 0xd5, 0x0c, 0x00, 0x01, 0xc9, 0x0d, 0x01, 0x03, 0x00, 0xca, 0x12, 0x42, 0x00, 0x65, 0x45, -0xd5, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, -0x18, 0x43, 0x00, 0x6f, 0x4f, 0xab, 0xac, 0x1e, 0x43, 0x00, 0x61, 0x41, 0x91, 0x92, 0x1f, 0x42, -0x03, 0x00, 0x00, 0xe1, 0x26, 0x43, 0x03, 0x00, 0x00, 0xf2, 0xf6, 0x28, 0x01, 0x03, 0x00, 0xcc, -0x29, 0x02, 0x03, 0x00, 0x00, 0xfa, 0x2b, 0x02, 0x07, 0x00, 0xcd, 0xcb, 0x2c, 0x42, 0x03, 0x00, -0x00, 0xae, 0x2d, 0x42, 0x03, 0x00, 0x00, 0xaf, 0x2e, 0x43, 0x03, 0x00, 0x00, 0x87, 0x80, 0x31, -0x43, 0x03, 0x00, 0x00, 0xa4, 0xa5, 0x39, 0x00, 0x00, 0x20, 0x00, 0x22, 0x0d, 0x61, 0x84, 0x65, -0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, -0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x27, 0x0b, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, -0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x20, 0x27, 0x5e, -0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, -0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, -0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0xf8, -0x0b, 0x61, 0xc6, 0x65, 0xbd, 0x69, 0x9b, 0x6f, 0x9e, 0x75, 0xa9, 0x41, 0xc7, 0x45, 0xbe, 0x49, -0x9d, 0x4f, 0x9f, 0x55, 0xb8, 0x20, 0xf8, 0xf5, 0x0b, 0x61, 0xd0, 0x65, 0xdd, 0x69, 0x9c, 0x6f, -0xe7, 0x75, 0xef, 0x41, 0xd1, 0x45, 0xf9, 0x49, 0xcf, 0x4f, 0xe8, 0x55, 0xf7, 0x20, 0xf5, 0x00, -0x04, 0x01, 0x03, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0xaa, 0x0d, 0x01, 0x03, 0xa0, 0xc8, -0x12, 0x42, 0x03, 0x00, 0x00, 0xaa, 0x1a, 0x00, 0x01, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, -0x43, 0x00, 0x64, 0x44, 0xd0, 0xd1, 0x27, 0x00, 0x01, 0xa0, 0x28, 0x00, 0x01, 0xa0, 0x2b, 0x00, -0x01, 0xa0, 0x2c, 0x41, 0x00, 0x7a, 0x5a, 0x2e, 0x43, 0x00, 0x63, 0x43, 0x86, 0x8f, 0x39, 0x00, -0x00, 0x20, 0x00, 0x5e, 0x07, 0x63, 0x9f, 0x73, 0xe7, 0x7a, 0xa7, 0x43, 0xac, 0x53, 0xe6, 0x5a, -0xa6, 0x20, 0x5e, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0x87, 0x0d, 0x00, 0x01, 0xa0, 0x12, 0x02, -0x03, 0x00, 0x00, 0x87, 0x27, 0x01, 0x03, 0xa0, 0xa0, 0x28, 0x01, 0x03, 0xa0, 0xa0, 0x2b, 0x01, -0x03, 0xa0, 0xa0, 0x36, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x06, 0x02, 0x03, -0x00, 0x00, 0x87, 0x0d, 0x00, 0x01, 0xa0, 0x10, 0x01, 0x00, 0x8b, 0x8c, 0x11, 0x01, 0x02, 0xed, -0xa0, 0x12, 0x42, 0x00, 0xde, 0xa8, 0x87, 0x13, 0x41, 0x00, 0xeb, 0xc7, 0x14, 0x41, 0x00, 0xee, -0xd0, 0x15, 0x41, 0x00, 0xf2, 0xd1, 0x16, 0x41, 0x00, 0xe2, 0xac, 0x17, 0x41, 0x00, 0xe3, 0xad, -0x18, 0x41, 0x00, 0xe9, 0xbe, 0x19, 0x41, 0x00, 0xea, 0xc6, 0x1a, 0x01, 0x03, 0xa0, 0xa0, 0x1e, -0x41, 0x00, 0xd6, 0xa4, 0x1f, 0x41, 0x00, 0xec, 0xcf, 0x20, 0x41, 0x00, 0xdd, 0xa7, 0x21, 0x41, -0x00, 0xf3, 0xd2, 0x22, 0x41, 0x00, 0xd8, 0xa6, 0x23, 0x41, 0x00, 0xe1, 0xaa, 0x24, 0x41, 0x00, -0xe8, 0xbd, 0x25, 0x41, 0x00, 0xe4, 0xb5, 0x26, 0x41, 0x00, 0xe5, 0xb6, 0x27, 0x01, 0x03, 0xc8, -0xa0, 0x28, 0x01, 0x03, 0xc9, 0xa0, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, -0x01, 0x03, 0xca, 0xa0, 0x2c, 0xc1, 0x00, 0xe0, 0x00, 0xa9, 0x2c, 0x2d, 0x41, 0x00, 0xf4, 0xd3, -0x2e, 0x41, 0x00, 0xf6, 0xd4, 0x2f, 0x41, 0x00, 0xfa, 0xd5, 0x30, 0x41, 0x00, 0xd7, 0xa5, 0x31, -0x41, 0x00, 0xe7, 0xb8, 0x32, 0x41, 0x00, 0xe6, 0xb7, 0x39, 0x00, 0x00, 0x20, 0x00, 0xef, 0x0f, -0xd6, 0x9b, 0xde, 0x9d, 0xe1, 0x9e, 0xe3, 0x9f, 0xe9, 0xa2, 0xf2, 0xa3, 0xfa, 0xfd, 0xa4, 0x86, -0xa8, 0x8d, 0xaa, 0x8f, 0xad, 0x90, 0xbe, 0x92, 0xd1, 0x95, 0xd5, 0x98, 0x20, 0xef, 0xf9, 0x05, -0xe3, 0xa0, 0xf2, 0xfb, 0xad, 0x91, 0xd1, 0x96, 0x20, 0xf9, 0xf7, 0x03, 0xe3, 0xa1, 0xf2, 0xfc, -0x20, 0xf7, 0x00, 0x8c, 0x23, 0x02, 0x0c, 0x00, 0x00, 0x4a, 0x50, 0x2c, 0x00, 0x00, 0x4a, 0x50, -0x31, 0x30, 0x36, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, -0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x0c, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0c, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x08, -0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x03, 0x0b, 0x00, 0x00, 0xc7, 0xa0, 0x03, 0x03, -0x09, 0x00, 0x22, 0xcc, 0xa0, 0x04, 0x03, 0x03, 0x00, 0x00, 0xb1, 0xa7, 0x05, 0x03, 0x03, 0x00, -0x00, 0xb3, 0xa9, 0x06, 0x03, 0x03, 0x00, 0x00, 0xb4, 0xaa, 0x07, 0x03, 0x01, 0x00, 0x26, 0xb5, -0xab, 0x08, 0x03, 0x01, 0x00, 0x27, 0xd4, 0xac, 0x09, 0x03, 0x01, 0x00, 0x28, 0xd5, 0xad, 0x0a, -0x03, 0x01, 0x00, 0x29, 0xd6, 0xae, 0x0b, 0x03, 0x01, 0x00, 0x7e, 0xdc, 0xa6, 0x0c, 0x03, 0x09, -0x00, 0x3d, 0xce, 0xa0, 0x0d, 0x04, 0x08, 0x5e, 0x7e, 0xcd, 0xa0, 0x1e, 0x10, 0x43, 0x0b, 0x00, -0x00, 0xc0, 0xa0, 0x11, 0x43, 0x0b, 0x00, 0x00, 0xc3, 0xa0, 0x12, 0x43, 0x03, 0x00, 0x00, 0xb2, -0xa8, 0x13, 0x43, 0x0b, 0x00, 0x00, 0xbd, 0xa0, 0x14, 0x43, 0x0b, 0x00, 0x00, 0xb6, 0xa0, 0x15, -0x43, 0x0b, 0x00, 0x00, 0xdd, 0xa0, 0x16, 0x43, 0x0b, 0x00, 0x00, 0xc5, 0xa0, 0x17, 0x43, 0x0b, -0x00, 0x00, 0xc6, 0xa0, 0x18, 0x43, 0x0b, 0x00, 0x00, 0xd7, 0xa0, 0x19, 0x43, 0x0b, 0x00, 0x00, -0xbe, 0xa0, 0x1a, 0x84, 0x08, 0x40, 0x1a, 0x60, 0x1a, 0xde, 0x1a, 0xa0, 0x1a, 0x00, 0x03, 0x1b, -0x04, 0x00, 0x5b, 0x7b, 0xdf, 0xa2, 0x1b, 0x1e, 0x43, 0x0b, 0x00, 0x00, 0xc1, 0xa0, 0x1f, 0x43, -0x0b, 0x00, 0x00, 0xc4, 0xa0, 0x20, 0x43, 0x0b, 0x00, 0x00, 0xbc, 0xa0, 0x21, 0x43, 0x0b, 0x00, -0x00, 0xca, 0xa0, 0x22, 0x43, 0x0b, 0x00, 0x00, 0xb7, 0xa0, 0x23, 0x43, 0x0b, 0x00, 0x00, 0xb8, -0xa0, 0x24, 0x43, 0x0b, 0x00, 0x00, 0xcf, 0xa0, 0x25, 0x43, 0x0b, 0x00, 0x00, 0xc9, 0xa0, 0x26, -0x43, 0x0b, 0x00, 0x00, 0xd8, 0xa0, 0x27, 0x03, 0x09, 0x00, 0x2b, 0xda, 0xa0, 0x28, 0x03, 0x08, -0x3a, 0x2a, 0xb9, 0xa0, 0x29, 0x86, 0x00, 0x00, 0xaf, 0x00, 0xb0, 0x00, 0xaf, 0x00, 0xb0, 0x00, -0xb1, 0x00, 0xb2, 0x00, 0xb2, 0x2b, 0x04, 0x00, 0x5d, 0x7d, 0xd1, 0xa3, 0x1d, 0x2c, 0x43, 0x03, -0x00, 0x00, 0xc2, 0xaf, 0x2d, 0x43, 0x0b, 0x00, 0x00, 0xbb, 0xa0, 0x2e, 0x43, 0x0b, 0x00, 0x00, -0xbf, 0xa0, 0x2f, 0x43, 0x0b, 0x00, 0x00, 0xcb, 0xa0, 0x30, 0x43, 0x0b, 0x00, 0x00, 0xba, 0xa0, -0x31, 0x43, 0x0b, 0x00, 0x00, 0xd0, 0xa0, 0x32, 0x43, 0x0b, 0x00, 0x00, 0xd3, 0xa0, 0x33, 0x03, -0x03, 0x00, 0x00, 0xc8, 0xa4, 0x34, 0x03, 0x03, 0x00, 0x00, 0xd9, 0xa1, 0x35, 0x03, 0x03, 0x00, -0x00, 0xd2, 0xa5, 0x3a, 0x86, 0x0a, 0x00, 0xb3, 0x00, 0x3a, 0x00, 0xb3, 0x00, 0x3a, 0x00, 0xb4, -0x00, 0xb5, 0x00, 0xb5, 0x70, 0x86, 0x60, 0x00, 0xb6, 0x00, 0xb7, 0x00, 0xb6, 0x00, 0xb7, 0x00, -0xb8, 0xc3, 0x00, 0xbb, 0x00, 0x73, 0x04, 0x00, 0x5c, 0x5f, 0xdb, 0x7c, 0x1c, 0x79, 0x86, 0x00, -0x00, 0xa7, 0x00, 0xa8, 0x00, 0xa7, 0x00, 0xa8, 0x00, 0xa9, 0x00, 0xaa, 0x00, 0xaa, 0x7b, 0x86, -0x00, 0x00, 0xab, 0x00, 0xac, 0x00, 0xab, 0x00, 0xac, 0x00, 0xad, 0x00, 0xae, 0x00, 0xae, 0x7d, -0x04, 0x08, 0x5c, 0x7c, 0xb0, 0xa0, 0x1c, 0xba, 0x86, 0x7f, 0x00, 0xb3, 0x00, 0x3a, 0xbb, 0x00, -0x00, 0x3a, 0x00, 0xb4, 0x00, 0xb5, 0x00, 0xb5, 0x00, 0xd5, 0xb3, 0x04, 0x09, 0x00, 0x00, 0x4c, -0x41, 0x2c, 0xab, 0x00, 0x4c, 0x41, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, -0x00, 0x00, 0x5a, 0x03, 0x43, 0x01, 0x4a, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x4a, 0x01, -0x00, 0x00, 0xb5, 0x01, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x33, 0x75, 0xb5, 0x01, 0x09, 0x02, -0x00, 0x00, 0x4d, 0x75, 0xaa, 0x02, 0x15, 0x03, 0x00, 0x00, 0x4e, 0x75, 0xaa, 0x03, 0x02, 0x04, -0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x07, -0x01, 0x01, 0x00, 0x26, 0x08, 0x01, 0x01, 0x00, 0x2f, 0x09, 0x01, 0x01, 0x00, 0x28, 0x0a, 0x01, -0x01, 0x00, 0x29, 0x0b, 0x01, 0x01, 0x00, 0x3d, 0x0c, 0x04, 0x08, 0x27, 0x3f, 0x5c, 0x00, 0x1c, -0x0d, 0x01, 0x00, 0xa8, 0xad, 0x10, 0x02, 0x03, 0x00, 0x00, 0x40, 0x12, 0x41, 0x00, 0x65, 0x45, -0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, -0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x01, 0x03, 0xca, 0xcb, 0x1b, 0x02, 0x00, 0x2b, 0x2a, 0x7e, 0x1e, -0x41, 0x00, 0x61, 0x41, 0x27, 0x41, 0x00, 0xa4, 0xa5, 0x28, 0x04, 0x0c, 0x7b, 0x5b, 0xc9, 0x00, -0x1b, 0x29, 0x02, 0x00, 0x7c, 0xf8, 0xaa, 0x2b, 0x04, 0x0c, 0x7d, 0x5d, 0xc8, 0x00, 0x1d, 0x2e, -0x41, 0x00, 0x63, 0x43, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, 0x01, 0x00, 0x3a, 0x3e, -0x35, 0x04, 0x0c, 0x2d, 0x5f, 0x00, 0x00, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, 0x01, 0x00, 0x3c, -0x3e, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, -0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x09, -0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x43, 0x80, 0x45, 0x90, -0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, -0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, -0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, -0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, -0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, -0xef, 0x0f, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, -0x41, 0xb5, 0x43, 0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, -0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, -0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, -0xcf, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x0d, 0x02, 0x03, 0x00, 0x00, 0x9c, 0x12, 0x03, 0x03, -0x00, 0x00, 0xbd, 0xbe, 0x17, 0x03, 0x03, 0x00, 0x00, 0x9e, 0x9f, 0x1b, 0x02, 0x07, 0x00, 0x00, -0xcc, 0x1e, 0x03, 0x03, 0x00, 0x00, 0xf4, 0xf6, 0x1f, 0x43, 0x00, 0x73, 0x53, 0xfb, 0xe6, 0x22, -0x41, 0x00, 0x67, 0x47, 0x26, 0x03, 0x03, 0x00, 0x00, 0xfc, 0xfd, 0x2c, 0x42, 0x00, 0x7a, 0x5a, -0xae, 0x2d, 0x42, 0x00, 0x78, 0x58, 0xaf, 0x31, 0x43, 0x00, 0x6e, 0x4e, 0xe1, 0xee, 0x00, 0x60, -0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, -0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x5e, 0x13, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, -0x93, 0x75, 0x96, 0x63, 0xab, 0x73, 0xf9, 0x7a, 0xf7, 0x78, 0xb8, 0x41, 0xb6, 0x45, 0xd2, 0x49, -0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x43, 0xac, 0x53, 0xdd, 0x5a, 0xef, 0x58, 0xa9, 0x20, 0x5e, 0x27, -0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, -0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0x22, 0x0f, 0x61, 0x84, 0x65, -0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x6e, 0xa6, 0x78, 0xf1, 0x41, 0x8e, 0x45, 0xd3, 0x49, -0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x4e, 0xa7, 0x58, 0xf2, 0x20, 0x22, 0x7e, 0x11, 0x61, 0xc6, 0x65, -0x86, 0x69, 0x91, 0x6f, 0xe4, 0x75, 0x9b, 0x67, 0xd0, 0x6e, 0xa4, 0x79, 0xe7, 0x41, 0xc7, 0x45, -0x8f, 0x49, 0x92, 0x4f, 0xe5, 0x55, 0x9d, 0x47, 0xd1, 0x4e, 0xa5, 0x59, 0xe8, 0x20, 0x7e, 0x00, -0x04, 0x02, 0x03, 0x00, 0x00, 0xfa, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x11, 0x03, 0x03, 0x00, -0x00, 0xf7, 0xef, 0x12, 0x03, 0x03, 0x00, 0x00, 0x87, 0x80, 0x13, 0x03, 0x03, 0x00, 0x00, 0xe6, -0xfb, 0x15, 0x03, 0x03, 0x00, 0x00, 0xf4, 0xf6, 0x16, 0x03, 0x03, 0x00, 0x00, 0xe7, 0xe8, 0x17, -0x03, 0x03, 0x00, 0x00, 0xf1, 0xf2, 0x18, 0x03, 0x03, 0x00, 0x00, 0x9b, 0x9d, 0x1f, 0x43, 0x00, -0x73, 0x53, 0xe4, 0xe5, 0x20, 0x03, 0x03, 0x00, 0x00, 0xfc, 0xfd, 0x21, 0x03, 0x03, 0x00, 0x00, -0xc6, 0xc7, 0x29, 0x01, 0x03, 0xcc, 0xcd, 0x2c, 0x02, 0x03, 0x00, 0x00, 0xae, 0x2d, 0x02, 0x03, -0x00, 0x00, 0xaf, 0x31, 0x03, 0x03, 0x00, 0x00, 0x9c, 0xcf, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, -0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, -0xeb, 0x20, 0x60, 0x5e, 0x0b, 0x61, 0x86, 0x65, 0x91, 0x69, 0x98, 0x6f, 0xe1, 0x75, 0x9e, 0x41, -0x8f, 0x45, 0x92, 0x49, 0xf3, 0x4f, 0xee, 0x55, 0x9f, 0x20, 0x5e, 0x27, 0x0b, 0x61, 0xa0, 0x65, -0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, -0xe9, 0x20, 0x27, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x73, -0xf9, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x53, 0xdd, 0x20, 0x22, 0x7c, -0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, -0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x7c, 0xf8, 0x0b, 0x61, 0xa6, 0x65, 0xab, 0x69, 0xa9, 0x6f, -0xbd, 0x75, 0xd0, 0x41, 0xa7, 0x45, 0xac, 0x49, 0xb8, 0x4f, 0xbe, 0x55, 0xd1, 0x20, 0xf8, 0x00, -0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x0c, 0x00, 0x01, 0xcc, 0x0d, 0x02, 0x03, 0x00, 0x00, 0x9c, -0x12, 0x02, 0x03, 0x00, 0x00, 0x9f, 0x14, 0x02, 0x03, 0x00, 0x00, 0xcf, 0x16, 0x02, 0x03, 0x00, -0x00, 0xfd, 0x17, 0x02, 0x03, 0x00, 0x00, 0xfb, 0x18, 0x02, 0x03, 0x00, 0x00, 0xfc, 0x19, 0x02, -0x03, 0x00, 0x00, 0xbe, 0x1e, 0x02, 0x03, 0x00, 0x00, 0x9e, 0x1f, 0x42, 0x00, 0x73, 0x53, 0xe1, -0x29, 0x01, 0x03, 0xcd, 0xce, 0x2c, 0x42, 0x00, 0x7a, 0x5a, 0xae, 0x2d, 0x02, 0x03, 0x00, 0x00, -0xaf, 0x2e, 0x02, 0x03, 0x00, 0x00, 0xbd, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, -0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, -0x5e, 0x0c, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x63, 0x87, 0x73, 0xf9, -0x7a, 0xf7, 0x43, 0x80, 0x53, 0xdd, 0x5a, 0xef, 0x20, 0x5e, 0xef, 0x0b, 0x61, 0xa0, 0x65, 0x82, -0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, -0x20, 0x27, 0x22, 0x09, 0x61, 0x84, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x49, 0xd8, -0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x27, 0x0b, 0x61, 0xb6, 0x65, 0xd2, 0x69, 0xd7, 0x6f, 0xe2, -0x75, 0xea, 0x41, 0xc6, 0x45, 0xc7, 0x49, 0xe4, 0x4f, 0xe5, 0x55, 0xe6, 0x20, 0x27, 0x7c, 0x0b, -0x61, 0xd0, 0x65, 0x89, 0x69, 0xec, 0x6f, 0xe7, 0x75, 0x98, 0x41, 0xd1, 0x45, 0xd3, 0x49, 0xed, -0x4f, 0xe8, 0x55, 0xf3, 0x20, 0x7c, 0xf8, 0x0b, 0x61, 0x86, 0x65, 0x91, 0x69, 0x9b, 0x6f, 0xab, -0x75, 0xa6, 0x41, 0x8f, 0x45, 0x92, 0x49, 0x9d, 0x4f, 0xac, 0x55, 0xa7, 0x20, 0xf8, 0x00, 0xc3, -0x7d, 0x02, 0x19, 0x00, 0x00, 0x4c, 0x48, 0x2c, 0x00, 0x00, 0x55, 0x53, 0x44, 0x56, 0x4c, 0x2c, -0x67, 0x00, 0x4c, 0x48, 0x2c, 0x67, 0x00, 0x55, 0x53, 0x44, 0x56, 0x4c, 0x04, 0x03, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0x55, 0x02, 0x00, 0x00, 0x00, 0x00, -0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x84, 0x00, 0x5b, 0x1a, 0x7b, 0x1a, 0x1b, -0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x03, 0x84, 0x00, 0x5d, 0x1b, 0x7d, 0x1b, 0x1d, 0x1b, 0x00, 0x1b, -0x00, 0x1b, 0x04, 0x84, 0x00, 0x2f, 0x35, 0x3f, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x05, -0xc4, 0x00, 0x70, 0x19, 0x50, 0x19, 0x10, 0x19, 0x00, 0x19, 0x00, 0x19, 0x06, 0xc4, 0x00, 0x66, -0x21, 0x46, 0x21, 0x06, 0x21, 0x00, 0x21, 0x00, 0x21, 0x07, 0xc4, 0x00, 0x6d, 0x32, 0x4d, 0x32, -0x0d, 0x32, 0x00, 0x32, 0x00, 0x32, 0x08, 0xc4, 0x00, 0x6c, 0x26, 0x4c, 0x26, 0x0c, 0x26, 0x00, -0x26, 0x00, 0x26, 0x09, 0xc4, 0x00, 0x6a, 0x24, 0x4a, 0x24, 0x0a, 0x24, 0x00, 0x24, 0x00, 0x24, -0x0a, 0x84, 0x00, 0x34, 0x05, 0x24, 0x05, 0x00, 0x05, 0x00, 0x7b, 0x00, 0x7b, 0x0b, 0x84, 0x00, -0x33, 0x04, 0x23, 0x04, 0x00, 0x04, 0x00, 0x7a, 0x00, 0x7a, 0x0c, 0x84, 0x00, 0x32, 0x03, 0x40, -0x03, 0x00, 0x03, 0x00, 0x79, 0x00, 0x79, 0x0d, 0x84, 0x00, 0x31, 0x02, 0x21, 0x02, 0x00, 0x02, -0x00, 0x78, 0x00, 0x78, 0x10, 0x84, 0x00, 0x3b, 0x27, 0x3a, 0x27, 0x00, 0x27, 0x00, 0x27, 0x00, -0x27, 0x11, 0xc4, 0x00, 0x71, 0x10, 0x51, 0x10, 0x11, 0x10, 0x00, 0x10, 0x00, 0x10, 0x12, 0xc4, -0x00, 0x62, 0x30, 0x42, 0x30, 0x02, 0x30, 0x00, 0x30, 0x00, 0x30, 0x13, 0xc4, 0x00, 0x79, 0x15, -0x59, 0x15, 0x19, 0x15, 0x00, 0x15, 0x00, 0x15, 0x14, 0xc4, 0x00, 0x75, 0x16, 0x55, 0x16, 0x15, -0x16, 0x00, 0x16, 0x00, 0x16, 0x15, 0xc4, 0x00, 0x72, 0x13, 0x52, 0x13, 0x12, 0x13, 0x00, 0x13, -0x00, 0x13, 0x16, 0xc4, 0x00, 0x73, 0x1f, 0x53, 0x1f, 0x13, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x17, -0xc4, 0x00, 0x6f, 0x18, 0x4f, 0x18, 0x0f, 0x18, 0x00, 0x18, 0x00, 0x18, 0x18, 0x84, 0x00, 0x2e, -0x34, 0x3e, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x19, 0x84, 0x00, 0x36, 0x07, 0x5e, 0x07, -0x1e, 0x07, 0x00, 0x7d, 0x00, 0x7d, 0x1a, 0x84, 0x00, 0x35, 0x06, 0x25, 0x06, 0x00, 0x06, 0x00, -0x7c, 0x00, 0x7c, 0x1b, 0x84, 0x00, 0x3d, 0x0d, 0x2b, 0x0d, 0x00, 0x0d, 0x00, 0x83, 0x00, 0x83, -0x1e, 0x84, 0x00, 0x2d, 0x0c, 0x5f, 0x0c, 0x1f, 0x0c, 0x00, 0x82, 0x00, 0x82, 0x1f, 0xc4, 0x00, -0x6b, 0x25, 0x4b, 0x25, 0x0b, 0x25, 0x00, 0x25, 0x00, 0x25, 0x20, 0xc4, 0x00, 0x63, 0x2e, 0x43, -0x2e, 0x03, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x21, 0xc4, 0x00, 0x64, 0x20, 0x44, 0x20, 0x04, 0x20, -0x00, 0x20, 0x00, 0x20, 0x22, 0xc4, 0x00, 0x74, 0x14, 0x54, 0x14, 0x14, 0x14, 0x00, 0x14, 0x00, -0x14, 0x24, 0xc4, 0x00, 0x65, 0x12, 0x45, 0x12, 0x05, 0x12, 0x00, 0x12, 0x00, 0x12, 0x25, 0xc4, -0x00, 0x61, 0x1e, 0x41, 0x1e, 0x01, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x26, 0xc4, 0x00, 0x7a, 0x2c, -0x5a, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x27, 0x84, 0x00, 0x38, 0x09, 0x2a, 0x09, 0x00, -0x09, 0x00, 0x7f, 0x00, 0x7f, 0x28, 0x84, 0x00, 0x37, 0x08, 0x26, 0x08, 0x00, 0x08, 0x00, 0x7e, -0x00, 0x7e, 0x2c, 0x84, 0x00, 0x27, 0x28, 0x22, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x2e, -0xc4, 0x00, 0x67, 0x22, 0x47, 0x22, 0x07, 0x22, 0x00, 0x22, 0x00, 0x22, 0x30, 0xc4, 0x00, 0x77, -0x11, 0x57, 0x11, 0x17, 0x11, 0x00, 0x11, 0x00, 0x11, 0x32, 0xc4, 0x00, 0x69, 0x17, 0x49, 0x17, -0x09, 0x17, 0x00, 0x17, 0x00, 0x17, 0x34, 0x84, 0x00, 0x30, 0x0b, 0x29, 0x0b, 0x00, 0x0b, 0x00, -0x81, 0x00, 0x81, 0x35, 0x84, 0x00, 0x39, 0x0a, 0x28, 0x0a, 0x00, 0x0a, 0x00, 0x80, 0x00, 0x80, -0x00, 0x24, 0xc4, 0x00, 0x65, 0x12, 0x45, 0x12, 0x05, 0x12, 0xd5, 0x12, 0x00, 0x12, 0x00, 0xa0, -0x19, 0x03, 0x09, 0x00, 0x00, 0x4e, 0x4c, 0x2c, 0x8f, 0x00, 0x4e, 0x4c, 0x05, 0x03, 0x00, 0x00, -0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xa9, 0x01, 0xb0, 0x01, 0x00, 0x00, -0x52, 0x03, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0xb5, 0x01, 0x2c, 0x01, 0x56, 0x01, 0x00, 0x00, -0x44, 0x75, 0x2f, 0x02, 0x7e, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, -0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x02, 0x03, 0x00, 0x00, 0xfb, 0x03, 0x02, 0x01, 0x00, 0x22, 0xfd, 0x04, 0x02, 0x03, 0x00, -0x00, 0xfc, 0x05, 0x02, 0x03, 0x00, 0x00, 0xac, 0x06, 0x02, 0x03, 0x00, 0x00, 0xab, 0x07, 0x02, -0x01, 0x00, 0x26, 0xf3, 0x08, 0x04, 0x09, 0x00, 0x5f, 0x9c, 0x00, 0x1f, 0x09, 0x02, 0x01, 0x00, -0x28, 0x7b, 0x0a, 0x02, 0x01, 0x00, 0x29, 0x7d, 0x0b, 0x01, 0x01, 0x00, 0x27, 0x0c, 0x04, 0x08, -0x2f, 0x3f, 0x5c, 0x00, 0x1c, 0x0d, 0x02, 0x06, 0xf8, 0xc9, 0xcd, 0x12, 0x41, 0x00, 0x65, 0x45, -0x13, 0x42, 0x03, 0x00, 0x00, 0xf4, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, -0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x04, 0x0f, 0xcc, 0xca, 0x00, -0x00, 0x1e, 0x1b, 0x02, 0x00, 0x2a, 0x7c, 0xdd, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x1f, 0x42, 0x03, -0x00, 0x00, 0xe1, 0x27, 0x01, 0x00, 0x2b, 0xf1, 0x28, 0x01, 0x03, 0xcb, 0xc8, 0x29, 0x02, 0x00, -0x40, 0xf5, 0xaa, 0x2b, 0x01, 0x00, 0x3c, 0x3e, 0x2c, 0x42, 0x03, 0x00, 0x00, 0xae, 0x2d, 0x42, -0x03, 0x00, 0x00, 0xaf, 0x2e, 0x42, 0x00, 0x63, 0x43, 0xbd, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, -0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x04, 0x09, 0x00, 0x3b, 0x5b, 0x00, 0x1b, 0x34, 0x02, 0x01, -0x00, 0x3a, 0xfa, 0x35, 0x04, 0x08, 0x2d, 0x3d, 0x5d, 0x00, 0x1d, 0x39, 0x00, 0x00, 0x20, 0x56, -0x04, 0x08, 0x5d, 0x5b, 0x7c, 0x00, 0x1d, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x07, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x13, 0x42, 0x03, 0x00, 0x00, 0x14, -0x1b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x29, 0x01, 0x01, 0x00, 0x15, 0x2e, 0x42, 0x03, 0x00, 0x00, -0x9b, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, -0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, -0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x07, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, -0x75, 0xa3, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, -0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x2c, 0x03, 0x63, 0x87, -0x43, 0x80, 0x20, 0x2c, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, -0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, -0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, -0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0d, 0x61, 0xa0, -0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, -0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, -0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, -0x20, 0xf9, 0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, 0x00, 0x05, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x07, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x10, 0x43, 0x03, -0x00, 0x00, 0x91, 0x92, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x17, 0x43, 0x03, 0x00, 0x00, 0x9e, -0x9f, 0x18, 0x43, 0x03, 0x00, 0x00, 0xab, 0xac, 0x19, 0x43, 0x03, 0x00, 0x00, 0x9b, 0x9d, 0x1b, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x1e, 0x43, 0x03, 0x00, 0x00, 0x86, 0x8f, 0x26, 0x43, 0x03, 0x00, -0x00, 0xe4, 0xe5, 0x2e, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, -0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, -0x20, 0x60, 0x7e, 0x0b, 0x61, 0x87, 0x65, 0xd0, 0x69, 0xe7, 0x6f, 0xf9, 0x75, 0xf7, 0x41, 0x80, -0x45, 0xd1, 0x49, 0xe8, 0x4f, 0xdd, 0x55, 0xef, 0x20, 0x7e, 0x5e, 0x0d, 0x61, 0x83, 0x65, 0x88, -0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x79, 0xbd, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, -0x55, 0xea, 0x59, 0xbe, 0x20, 0x5e, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, -0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, -0x20, 0x27, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, -0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x2c, 0x05, -0x65, 0xc6, 0x6f, 0xa4, 0x45, 0xc7, 0x4f, 0xa5, 0x20, 0x2c, 0x00, 0x78, 0x50, 0x03, 0x09, 0x00, -0x00, 0x4e, 0x4f, 0x2c, 0x9b, 0x00, 0x4e, 0x4f, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, -0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0x11, 0x01, 0x1e, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, -0x1e, 0x01, 0x00, 0x00, 0x61, 0x03, 0x99, 0x01, 0xa4, 0x01, 0x00, 0x00, 0x30, 0x75, 0xf3, 0x01, -0x00, 0x00, 0x00, 0x00, 0x30, 0x75, 0xa7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, -0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, -0x22, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x9c, 0x05, 0x02, 0x01, 0x00, 0xcf, 0x24, 0x07, 0x01, -0x01, 0x00, 0x26, 0x08, 0x02, 0x01, 0x00, 0x2f, 0x7b, 0x09, 0x04, 0x09, 0x00, 0x28, 0x5b, 0x00, -0x1b, 0x0a, 0x04, 0x09, 0x00, 0x29, 0x5d, 0x00, 0x1d, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, -0x01, 0x00, 0x2b, 0x3f, 0x0d, 0x04, 0x0e, 0x5c, 0xc8, 0xcb, 0x00, 0x1c, 0x12, 0x41, 0x00, 0x65, -0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, -0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x41, 0x00, 0x86, 0x8f, 0x1b, 0x04, 0x0f, 0xcc, 0xca, 0xc9, -0x00, 0x1e, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x41, 0x00, 0x9b, 0x9d, 0x28, 0x41, 0x00, 0x91, -0x92, 0x29, 0x01, 0x00, 0x7c, 0xf5, 0x2b, 0x01, 0x00, 0x27, 0x2a, 0x2e, 0x41, 0x00, 0x63, 0x43, -0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x02, 0x01, 0x00, 0x3b, -0x3c, 0x34, 0x02, 0x01, 0x00, 0x3a, 0x3e, 0x35, 0x04, 0x0c, 0x2d, 0x5f, 0x00, 0x00, 0x1f, 0x39, -0x00, 0x00, 0x20, 0x56, 0x01, 0x00, 0x3c, 0x3e, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x12, -0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, -0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, -0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, -0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, -0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0f, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, -0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, 0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, -0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, -0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, -0x00, 0x05, 0x01, 0x01, 0x00, 0xaf, 0x29, 0x01, 0x01, 0x00, 0x15, 0x00, 0x60, 0x06, 0x61, 0x85, -0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, -0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, -0x27, 0x09, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x43, 0x80, -0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, -0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x04, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x09, 0x03, 0x07, 0x00, 0x00, 0x00, 0xae, 0x0a, 0x03, -0x07, 0x00, 0x00, 0x00, 0xaf, 0x0d, 0x02, 0x07, 0x00, 0xa0, 0xa0, 0x10, 0x43, 0x03, 0x00, 0x00, -0x83, 0xb6, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x14, 0x43, 0x03, 0x00, 0x00, 0xab, 0x97, 0x17, -0x43, 0x03, 0x00, 0x00, 0x8b, 0xd8, 0x18, 0x43, 0x03, 0x00, 0x00, 0xe4, 0xe5, 0x1b, 0x02, 0x07, -0xa0, 0xa0, 0xa0, 0x1e, 0x43, 0x03, 0x00, 0x00, 0xa0, 0xb5, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xaa, -0x96, 0x20, 0x43, 0x03, 0x00, 0x00, 0x9f, 0x8d, 0x21, 0x43, 0x03, 0x00, 0x00, 0x90, 0x80, 0x22, -0x43, 0x03, 0x00, 0x00, 0xa1, 0xa2, 0x23, 0x43, 0x03, 0x00, 0x00, 0x85, 0x82, 0x25, 0x43, 0x03, -0x00, 0x00, 0xa6, 0xa7, 0x27, 0x43, 0x03, 0x00, 0x00, 0x94, 0x99, 0x28, 0x43, 0x03, 0x00, 0x00, -0x84, 0x8e, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xac, 0x98, 0x2e, 0x43, 0x03, 0x00, 0x00, 0x9e, 0x8c, -0x2f, 0x43, 0x03, 0x00, 0x00, 0x89, 0x8a, 0x30, 0x43, 0x03, 0x00, 0x00, 0x87, 0x88, 0x31, 0x43, -0x03, 0x00, 0x00, 0xa9, 0x95, 0x36, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x09, 0x03, 0x07, 0x00, 0x00, -0x00, 0xae, 0x0a, 0x03, 0x07, 0x00, 0x00, 0x00, 0xaf, 0x0d, 0x02, 0x07, 0x00, 0xa0, 0xa0, 0x10, -0x43, 0x00, 0xa0, 0xb5, 0x71, 0x51, 0x11, 0x43, 0x00, 0xaa, 0x96, 0x77, 0x57, 0x12, 0x42, 0x03, -0x00, 0x00, 0xd5, 0x15, 0x43, 0x00, 0xab, 0x97, 0x79, 0x59, 0x17, 0x43, 0x03, 0x00, 0x00, 0x8b, -0xd8, 0x18, 0x43, 0x03, 0x00, 0x00, 0xe4, 0xe5, 0x1b, 0x42, 0x04, 0xa9, 0x95, 0xa0, 0x1e, 0x43, -0x03, 0x00, 0x00, 0x83, 0xb6, 0x22, 0x43, 0x03, 0x00, 0x00, 0xa1, 0xa2, 0x23, 0x43, 0x03, 0x00, -0x00, 0x90, 0x80, 0x25, 0x43, 0x03, 0x00, 0x00, 0xa6, 0xa7, 0x27, 0x43, 0x03, 0x00, 0x00, 0x94, -0x99, 0x28, 0x43, 0x03, 0x00, 0x00, 0x84, 0x8e, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7b, 0x2b, 0x43, 0x00, 0x9f, 0x8d, 0x27, 0x2a, 0x2c, 0x43, 0x03, 0x00, 0x00, 0x87, 0x88, 0x2d, -0x43, 0x00, 0x9e, 0x8c, 0x78, 0x58, 0x56, 0x43, 0x00, 0xac, 0x98, 0x89, 0x8a, 0x00, 0x69, 0x5b, -0x03, 0x09, 0x00, 0x00, 0x50, 0x4c, 0x2c, 0xc9, 0x01, 0x50, 0x4c, 0x0d, 0x03, 0x00, 0x00, 0x00, -0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9c, -0x02, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x03, 0x4f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x16, -0x03, 0x4f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x02, 0x4f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, -0x03, 0x69, 0x02, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0x9c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x51, -0x03, 0x42, 0x03, 0x00, 0x00, 0x00, 0x00, 0x51, 0x03, 0x78, 0x02, 0x00, 0x00, 0x00, 0x00, 0x5a, -0x03, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, -0xe3, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, -0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, -0xc3, 0x00, 0x6f, 0x18, 0x4f, 0x18, 0xa2, 0x18, 0xe0, 0x00, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, -0x9b, 0x10, 0x43, 0x03, 0x00, 0x00, 0x84, 0x8e, 0x11, 0x43, 0x03, 0x00, 0x00, 0x82, 0x8a, 0x12, -0x43, 0x03, 0x00, 0x00, 0x91, 0x90, 0x13, 0x43, 0x03, 0x00, 0x00, 0x89, 0x83, 0x16, 0x43, 0x03, -0x00, 0x00, 0x81, 0x9a, 0x17, 0x43, 0x03, 0x00, 0x00, 0x94, 0x99, 0x18, 0x43, 0x07, 0x00, 0x00, -0x00, 0xa3, 0x19, 0x43, 0x03, 0x00, 0x00, 0x93, 0x96, 0x1e, 0x43, 0x03, 0x00, 0x00, 0x86, 0x8f, -0x1f, 0x43, 0x03, 0x00, 0x00, 0x9e, 0x98, 0x26, 0x43, 0x03, 0x00, 0x00, 0x92, 0x9c, 0x2c, 0x43, -0x03, 0x00, 0x00, 0xa7, 0xa1, 0x2d, 0x43, 0x03, 0x00, 0x00, 0xa6, 0xa0, 0x2e, 0x43, 0x03, 0x00, -0x00, 0x8d, 0x95, 0x31, 0x43, 0x03, 0x00, 0x00, 0xa4, 0xa5, 0x00, 0x12, 0x43, 0x03, 0x00, 0x00, -0xa9, 0xa8, 0x16, 0x42, 0x03, 0x00, 0x00, 0xaa, 0x1e, 0x43, 0x03, 0x00, 0x00, 0xa5, 0xa4, 0x1f, -0x43, 0x03, 0x00, 0x00, 0x98, 0x97, 0x26, 0x43, 0x03, 0x00, 0x00, 0x88, 0x9d, 0x2c, 0x43, 0x03, -0x00, 0x00, 0xbe, 0xbd, 0x2d, 0x43, 0x03, 0x00, 0x00, 0xab, 0x8d, 0x2e, 0x43, 0x03, 0x00, 0x00, -0x86, 0x8f, 0x31, 0x43, 0x03, 0x00, 0x00, 0xe4, 0xe3, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0x9b, -0x12, 0x43, 0x03, 0x00, 0x00, 0x91, 0x90, 0x18, 0x43, 0x07, 0x00, 0x00, 0x00, 0xa3, 0x1e, 0x43, -0x03, 0x00, 0x00, 0x86, 0x8f, 0x1f, 0x43, 0x03, 0x00, 0x00, 0x9e, 0x98, 0x26, 0x43, 0x03, 0x00, -0x00, 0x92, 0x9c, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xa7, 0xa1, 0x2d, 0x43, 0x03, 0x00, 0x00, 0xa6, -0xa0, 0x2e, 0x43, 0x03, 0x00, 0x00, 0x8d, 0x95, 0x31, 0x43, 0x03, 0x00, 0x00, 0xa4, 0xa5, 0x00, -0x16, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x0d, 0x43, 0x00, 0xec, 0x9c, 0x3d, 0x2b, 0x10, 0x41, -0x00, 0xef, 0x9f, 0x11, 0x41, 0x00, 0xe8, 0x98, 0x12, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x13, 0xc1, -0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xa7, 0x87, 0x16, -0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xf7, 0xf6, 0x18, 0x43, 0x0c, 0xae, 0x8e, 0xa0, 0xa0, -0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x43, 0x00, 0xa6, 0x86, 0x5b, 0x7b, 0x1b, 0x43, 0x00, 0xe7, -0x97, 0x5d, 0x7d, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, -0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xf3, 0xf2, 0x23, 0x41, 0x00, 0xa3, -0x83, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, -0x27, 0x43, 0x00, 0xf9, 0xf8, 0x3b, 0x3a, 0x28, 0x43, 0x00, 0xe9, 0x99, 0x27, 0x22, 0x29, 0x43, -0x00, 0xf5, 0xf4, 0x60, 0x7e, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x2b, 0x43, 0x00, -0xee, 0x9e, 0x5c, 0x7c, 0x2c, 0x41, 0x00, 0xa8, 0x88, 0x2d, 0x41, 0x00, 0xe5, 0x95, 0x2e, 0x41, -0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, -0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, 0x33, 0x02, 0x03, 0x00, 0x00, 0x3b, 0x34, 0x02, 0x03, -0x00, 0x00, 0x3a, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x7e, 0x00, 0x10, 0x41, 0x00, 0xef, 0x9f, 0x11, 0x41, 0x00, 0xe8, 0x98, 0x12, 0x42, 0x00, -0xa5, 0x85, 0xfb, 0x13, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, -0x41, 0x00, 0xa7, 0x87, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xf9, 0xf8, 0x18, 0x43, -0x0c, 0xae, 0x8e, 0xa0, 0xa0, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x43, 0x00, 0xa6, 0x86, 0x5b, -0x7b, 0x1b, 0x43, 0x00, 0xe7, 0x97, 0x5d, 0x7d, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, -0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xec, -0x9c, 0x23, 0x41, 0x00, 0xa3, 0x83, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, -0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, 0x43, 0x00, 0xf7, 0xf6, 0x3b, 0x3a, 0x28, 0x43, 0x00, 0xed, -0x9d, 0x27, 0x22, 0x29, 0xc3, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x60, 0x29, 0x7e, 0x29, 0x2a, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x2b, 0x43, 0x00, 0xee, 0x9e, 0x5c, 0x7c, 0x2c, 0x41, 0x00, -0xeb, 0x9b, 0x2d, 0x41, 0x00, 0xe5, 0x95, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, -0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, -0x33, 0x02, 0x03, 0x00, 0x00, 0x3b, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3a, 0x00, 0x12, 0x42, 0x03, -0x00, 0x00, 0xfb, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xa4, 0xf5, 0x08, 0x04, -0xd6, 0x00, 0x50, 0x4c, 0x0d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, -0x54, 0x03, 0x95, 0x03, 0x17, 0x04, 0x00, 0x00, 0x9c, 0x02, 0xd8, 0x04, 0x3e, 0x05, 0x00, 0x00, -0x5a, 0x03, 0xa7, 0x05, 0xae, 0x05, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0xae, 0x05, 0x00, 0x00, -0x9b, 0x02, 0x81, 0x01, 0x5a, 0x02, 0x00, 0x00, 0x16, 0x03, 0x81, 0x01, 0x5a, 0x02, 0x00, 0x00, -0xdf, 0x03, 0xe7, 0x01, 0x5a, 0x02, 0x00, 0x00, 0x50, 0x03, 0x2f, 0x07, 0x00, 0x00, 0x00, 0x00, -0x50, 0x03, 0x35, 0x06, 0x00, 0x00, 0x00, 0x00, 0x51, 0x03, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, -0x51, 0x03, 0x94, 0x07, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xe3, 0xbd, 0x02, 0x30, 0x03, 0x00, 0x00, -0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x03, 0x01, -0x01, 0x00, 0x22, 0x04, 0x03, 0x07, 0x00, 0x00, 0xc9, 0x1e, 0x05, 0x01, 0x01, 0x00, 0xcf, 0x06, -0x02, 0x07, 0x00, 0x00, 0xca, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, 0x02, 0x05, 0x00, 0x2f, 0xcb, -0x09, 0x02, 0x01, 0x00, 0x28, 0xfa, 0x0a, 0x02, 0x05, 0x00, 0x29, 0xcc, 0x0b, 0x01, 0x01, 0x00, -0x3d, 0x0c, 0x02, 0x04, 0x2b, 0x3f, 0xcd, 0x0d, 0x02, 0x04, 0x27, 0x2a, 0xce, 0x10, 0x42, 0x03, -0x00, 0x00, 0x5c, 0x11, 0x42, 0x03, 0x00, 0x00, 0x7c, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0xc4, -0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0x75, 0x55, -0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x42, 0x03, 0xa0, 0xa0, 0xf6, -0x1b, 0x43, 0x03, 0xa0, 0xa0, 0x9e, 0x1b, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x21, 0x42, 0x03, 0x00, -0x00, 0x5b, 0x22, 0x42, 0x03, 0x00, 0x00, 0x5d, 0x27, 0x43, 0x03, 0xa0, 0xa0, 0x24, 0x1d, 0x28, -0x42, 0x03, 0xa0, 0xa0, 0xe1, 0x29, 0x10, 0x00, 0x00, 0x2b, 0x41, 0x02, 0xa2, 0xa0, 0x2c, 0xc4, -0x00, 0x79, 0x15, 0x59, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2e, 0x41, 0x00, 0x63, 0x43, -0x2f, 0x42, 0x03, 0x00, 0x00, 0x40, 0x30, 0x42, 0x03, 0x00, 0x00, 0x7b, 0x31, 0x42, 0x00, 0x6e, -0x4e, 0x7d, 0x32, 0x42, 0x03, 0x00, 0x00, 0xf5, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, -0x01, 0x00, 0x3a, 0x3e, 0x35, 0x03, 0x04, 0x2d, 0x5f, 0x00, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, -0x01, 0x00, 0x3c, 0x3e, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x04, 0x02, 0x07, 0x00, 0x00, -0xc8, 0x05, 0x01, 0x03, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0xf8, 0x07, 0x02, 0x07, 0x00, -0x00, 0xc9, 0x08, 0x02, 0x07, 0x00, 0x00, 0xca, 0x09, 0x02, 0x07, 0x00, 0x00, 0xcb, 0x0a, 0x02, -0x07, 0x00, 0x00, 0xcc, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xcd, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xce, -0x1a, 0x41, 0x00, 0xa7, 0xa4, 0x1b, 0x42, 0x04, 0x9e, 0x8d, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, -0x27, 0x41, 0x00, 0x92, 0x9c, 0x28, 0x41, 0x00, 0x86, 0x91, 0x29, 0x01, 0x03, 0xc9, 0xcb, 0x2b, -0x41, 0x01, 0x00, 0xa6, 0x32, 0x42, 0x03, 0x00, 0x00, 0x15, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, -0x7e, 0x04, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x05, 0x01, 0x03, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, -0x00, 0xf8, 0x07, 0x02, 0x07, 0x00, 0x00, 0xc9, 0x08, 0x02, 0x07, 0x00, 0x00, 0xca, 0x09, 0x02, -0x07, 0x00, 0x00, 0xcb, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xcd, -0x0d, 0x02, 0x07, 0x00, 0x00, 0xce, 0x15, 0xc4, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x9b, 0x2c, 0x1a, -0x2c, 0x00, 0x2c, 0x1a, 0x41, 0x00, 0xa7, 0xa4, 0x1b, 0x42, 0x04, 0x9e, 0x8d, 0xa0, 0x1f, 0x41, -0x00, 0x73, 0x53, 0x27, 0x41, 0x00, 0x92, 0x9c, 0x28, 0x41, 0x00, 0x86, 0x91, 0x29, 0x01, 0x03, -0xc9, 0xcb, 0x2b, 0x41, 0x01, 0x00, 0xa6, 0x32, 0x42, 0x03, 0x00, 0x00, 0xa8, 0x00, 0x5e, 0x06, -0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x7e, 0x05, 0x61, 0x86, -0x65, 0x91, 0x41, 0x8f, 0x45, 0x90, 0x20, 0x7e, 0x60, 0x04, 0x61, 0x85, 0x65, 0x8a, 0x75, 0x97, -0x20, 0x60, 0xfa, 0x03, 0x7a, 0xa7, 0x5a, 0xa1, 0x20, 0xfa, 0x27, 0x0c, 0x63, 0x8d, 0x65, 0x82, -0x6e, 0xa4, 0x6f, 0xa2, 0x73, 0x9e, 0x7a, 0xa6, 0x43, 0x95, 0x4e, 0xa5, 0x4f, 0xa3, 0x53, 0x98, -0x5a, 0xa0, 0x20, 0x27, 0x22, 0x09, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, -0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x2c, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, -0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x04, 0x02, 0x07, 0x00, 0x00, 0xc9, 0x05, 0x01, 0x03, -0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0xf8, 0x07, 0x02, 0x07, 0x00, 0x00, 0xca, 0x08, 0x02, -0x07, 0x00, 0x00, 0xcb, 0x09, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xcd, -0x0c, 0x02, 0x07, 0x00, 0x00, 0xce, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xcf, 0x15, 0xc4, 0x00, 0x7a, -0x2c, 0x5a, 0x2c, 0x9b, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x1a, 0x41, 0x00, 0xa7, 0xa4, 0x1b, 0x42, -0x04, 0x9e, 0x8d, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x27, 0x41, 0x00, 0x92, 0x9c, 0x28, 0x41, -0x00, 0x86, 0x91, 0x29, 0x01, 0x03, 0xca, 0xcc, 0x2b, 0x41, 0x01, 0x00, 0xa6, 0x32, 0x42, 0x03, -0x00, 0x00, 0xa8, 0x00, 0x7e, 0x03, 0x61, 0x84, 0x41, 0x8e, 0x20, 0x7e, 0x5e, 0x05, 0x65, 0x88, -0x69, 0x8c, 0x6f, 0x93, 0x4f, 0x96, 0x20, 0x5e, 0x2c, 0x05, 0x61, 0x86, 0x65, 0x91, 0x41, 0x8f, -0x45, 0x90, 0x20, 0x2c, 0x60, 0x06, 0x61, 0x85, 0x6f, 0x94, 0x75, 0x97, 0x4f, 0x99, 0x55, 0x9a, -0x20, 0x60, 0xfa, 0x03, 0x7a, 0xa7, 0x5a, 0xa1, 0x20, 0xfa, 0x27, 0x0d, 0x63, 0x8d, 0x65, 0x82, -0x6e, 0xa4, 0x6f, 0xa2, 0x73, 0x9e, 0x7a, 0xa6, 0x43, 0x95, 0x45, 0x8a, 0x4e, 0xa5, 0x4f, 0xa3, -0x53, 0x98, 0x5a, 0xa0, 0x20, 0x27, 0x22, 0x04, 0x65, 0x89, 0x69, 0x8b, 0x45, 0x83, 0x20, 0x22, -0x2d, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x03, -0x02, 0x07, 0x00, 0x00, 0xc8, 0x05, 0x02, 0x07, 0x00, 0x00, 0xca, 0x06, 0x02, 0x07, 0x00, 0x00, -0xcb, 0x07, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x08, 0x02, 0x03, 0x00, 0x00, 0x60, 0x09, 0x02, 0x07, -0x00, 0x00, 0xcd, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xce, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xcf, 0x0c, -0x02, 0x07, 0x00, 0x00, 0xd0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xd1, 0x13, 0x41, 0x00, 0x72, 0x52, -0x14, 0x41, 0x00, 0x74, 0x54, 0x16, 0x42, 0x03, 0x00, 0x00, 0xaa, 0x1a, 0x41, 0x00, 0xbe, 0xe4, -0x1b, 0x41, 0x00, 0x98, 0x86, 0x1f, 0x42, 0x00, 0x73, 0x53, 0xd0, 0x20, 0x42, 0x00, 0x64, 0x44, -0xd1, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x27, 0x41, 0x00, 0x88, 0x9d, 0x28, 0x41, 0x00, 0xa5, 0xa9, -0x29, 0x01, 0x03, 0xcc, 0xcd, 0x2b, 0x41, 0x01, 0x00, 0xab, 0x00, 0xf3, 0x13, 0x63, 0x9f, 0x64, -0xd4, 0x65, 0xd8, 0x6c, 0x96, 0x6e, 0xe5, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa7, 0x43, -0xac, 0x44, 0xd2, 0x45, 0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, -0xa6, 0x20, 0xf3, 0x5e, 0x07, 0x61, 0x83, 0x69, 0x8c, 0x6f, 0x93, 0x41, 0xb6, 0x49, 0xd7, 0x4f, -0xe2, 0x20, 0x5e, 0xf4, 0x03, 0x61, 0xc7, 0x41, 0xc6, 0x20, 0xf4, 0xf8, 0x03, 0x75, 0x85, 0x55, -0xde, 0x20, 0xf8, 0xf2, 0x05, 0x61, 0xa5, 0x65, 0xa9, 0x41, 0xa4, 0x45, 0xa8, 0x20, 0xf2, 0xfa, -0x03, 0x7a, 0xbe, 0x5a, 0xbd, 0x20, 0xfa, 0xef, 0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, -0xa1, 0x6c, 0x92, 0x6e, 0xe4, 0x6f, 0xa2, 0x72, 0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, -0xab, 0x41, 0xb5, 0x43, 0x8f, 0x45, 0x90, 0x49, 0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, -0xe8, 0x53, 0x97, 0x55, 0xe9, 0x59, 0xed, 0x5a, 0x8d, 0x20, 0xef, 0xf1, 0x05, 0x6f, 0x8b, 0x75, -0xfb, 0x4f, 0x8a, 0x55, 0xeb, 0x20, 0xf1, 0xf9, 0x09, 0x61, 0x84, 0x65, 0x89, 0x6f, 0x94, 0x75, -0x81, 0x41, 0x8e, 0x45, 0xd3, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf7, 0x07, 0x63, 0x87, 0x73, -0xad, 0x74, 0xee, 0x43, 0x80, 0x53, 0xb8, 0x54, 0xdd, 0x20, 0xf7, 0x00, 0x02, 0x02, 0x03, 0x00, -0x00, 0x7e, 0x04, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x05, 0x01, 0x03, 0x00, 0xa0, 0x06, 0x02, 0x03, -0x00, 0x00, 0xf8, 0x07, 0x02, 0x07, 0x00, 0x00, 0xc9, 0x08, 0x02, 0x07, 0x00, 0x00, 0xca, 0x09, -0x02, 0x07, 0x00, 0x00, 0xcb, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x0c, 0x02, 0x07, 0x00, 0x00, -0xcd, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xce, 0x1a, 0x41, 0x00, 0xbe, 0xe4, 0x1b, 0x42, 0x04, 0x98, -0x86, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x27, 0x41, 0x00, 0x88, 0x9d, 0x28, 0x41, 0x00, 0xa5, -0xa9, 0x29, 0x01, 0x03, 0xc9, 0xcb, 0x2b, 0x41, 0x01, 0x00, 0xab, 0x32, 0x42, 0x03, 0x00, 0x00, -0x15, 0x00, 0x5e, 0x05, 0x61, 0x83, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x7e, 0x05, -0x61, 0xa5, 0x65, 0xa9, 0x41, 0xa4, 0x45, 0xa8, 0x20, 0x7e, 0x60, 0x04, 0x61, 0x85, 0x65, 0x8a, -0x6f, 0x95, 0x20, 0x60, 0xfa, 0x03, 0x7a, 0xbe, 0x5a, 0xbd, 0x20, 0xfa, 0x27, 0x10, 0x61, 0xa0, -0x63, 0x86, 0x65, 0x82, 0x69, 0xa1, 0x6e, 0xe4, 0x6f, 0xa2, 0x73, 0x98, 0x75, 0xa3, 0x7a, 0xab, -0x43, 0x8f, 0x45, 0x90, 0x4e, 0xe3, 0x4f, 0xe0, 0x53, 0x97, 0x5a, 0x8d, 0x20, 0x27, 0x22, 0x09, -0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, -0x20, 0x22, 0x2c, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, 0x00, 0x16, 0x42, 0x03, 0x00, 0x00, -0xd5, 0x00, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, -0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, -0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf8, 0x03, 0x61, 0x86, 0x41, 0x8f, -0x20, 0xf8, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, -0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, -0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, -0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, -0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, -0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x01, 0x03, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x10, 0x41, -0x00, 0xef, 0x9f, 0x11, 0x41, 0x00, 0xe8, 0x98, 0x12, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x13, 0xc1, -0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0xc4, 0x00, 0xa7, 0x2c, 0x87, -0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xf7, -0xf6, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x42, 0x04, 0xa6, 0x86, -0xa0, 0x1b, 0x42, 0x04, 0xe7, 0x97, 0xa0, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, -0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xf3, 0xf2, -0x23, 0x41, 0x00, 0xa3, 0x83, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, -0x41, 0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xf9, 0xf8, 0x28, 0x42, 0x04, 0xe9, 0x99, 0xa0, 0x29, -0x41, 0x00, 0xf5, 0xf4, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x2b, 0x41, 0x00, 0xee, -0x9e, 0x2c, 0xc4, 0x00, 0xa8, 0x15, 0x88, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x41, -0x00, 0xe5, 0x95, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, -0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x42, 0x04, 0xac, 0x8c, 0xa0, 0x56, 0x41, 0x00, -0xec, 0x9c, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, -0x01, 0x03, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x1a, 0x10, -0x00, 0x00, 0x1b, 0x02, 0x07, 0xa0, 0xa0, 0xa0, 0x27, 0x01, 0x03, 0xa0, 0xa0, 0x28, 0x10, 0x00, -0x00, 0x29, 0x10, 0x00, 0x00, 0x2b, 0x10, 0x00, 0x00, 0x32, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x36, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x05, 0x01, 0x03, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x10, 0x41, 0x00, -0xef, 0x9f, 0x11, 0x41, 0x00, 0xe8, 0x98, 0x12, 0x42, 0x00, 0xa5, 0x85, 0xfb, 0x13, 0xc1, 0x00, -0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0xc4, 0x00, 0xa7, 0x2c, 0x87, 0x2c, -0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xf9, 0xf8, -0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x42, 0x04, 0xa6, 0x86, 0xa0, -0x1b, 0x42, 0x04, 0xe7, 0x97, 0xa0, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, -0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xec, 0x9c, 0x23, -0x41, 0x00, 0xa3, 0x83, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, -0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xf7, 0xf6, 0x28, 0x42, 0x04, 0xed, 0x9d, 0xa0, 0x29, 0xc1, -0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x81, 0x2b, 0x41, 0x00, -0xee, 0x9e, 0x2c, 0xc4, 0x00, 0xeb, 0x15, 0x9b, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, -0x41, 0x00, 0xe5, 0x95, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, -0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x42, 0x04, 0xac, 0x8c, 0xa0, 0x00, 0x02, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x01, 0x03, 0x00, 0xa0, -0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfb, 0x1a, 0x10, 0x00, 0x00, 0x1b, 0x02, -0x07, 0xa0, 0xa0, 0xa0, 0x27, 0x01, 0x03, 0xa0, 0xa0, 0x28, 0x10, 0x00, 0x00, 0x29, 0x10, 0x00, -0x00, 0x2b, 0x10, 0x00, 0x00, 0x32, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x36, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x82, 0x00, 0xb4, 0xd1, 0x01, 0x09, 0x00, 0x00, 0x50, 0x4f, 0x2c, 0xa3, 0x00, 0x50, -0x4f, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xe3, -0x00, 0xf0, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x5c, 0x03, 0x67, -0x01, 0x6e, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, -0x9c, 0x05, 0x02, 0x03, 0x00, 0x00, 0xf5, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, 0x02, 0x01, 0x00, -0x2f, 0x7b, 0x09, 0x03, 0x01, 0x00, 0x28, 0x5b, 0x1b, 0x0a, 0x03, 0x01, 0x00, 0x29, 0x5d, 0x1d, -0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, 0x01, 0x00, 0x27, 0x3f, 0x0d, 0x01, 0x00, 0xae, 0xaf, -0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, -0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x02, 0x04, 0x2b, 0x2a, 0xcc, 0x1b, -0x01, 0x03, 0xcb, 0xc8, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x41, 0x00, 0x87, 0x80, 0x28, 0x01, -0x00, 0xa7, 0xa6, 0x29, 0x03, 0x04, 0x5c, 0x7c, 0x00, 0x1c, 0x2b, 0x03, 0x07, 0xc9, 0xca, 0x00, -0x1e, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, 0x01, 0x00, -0x3a, 0x3e, 0x35, 0x03, 0x04, 0x2d, 0x5f, 0x00, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, 0x02, 0x04, -0x3c, 0x3e, 0xcc, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, -0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, -0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, -0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, -0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, -0x5e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, -0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, -0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, -0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0x15, 0x00, 0x60, -0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0x91, 0x45, 0x92, 0x49, -0x98, 0x4f, 0xa9, 0x55, 0x9d, 0x20, 0x60, 0x7e, 0x07, 0x61, 0x84, 0x6e, 0xa4, 0x6f, 0x94, 0x41, -0x8e, 0x4e, 0xa5, 0x4f, 0x99, 0x20, 0x7e, 0x5e, 0x07, 0x61, 0x83, 0x65, 0x88, 0x6f, 0x93, 0x41, -0x8f, 0x45, 0x89, 0x4f, 0x8c, 0x20, 0x5e, 0x27, 0x0b, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, -0xa2, 0x75, 0xa3, 0x41, 0x86, 0x45, 0x90, 0x49, 0x8b, 0x4f, 0x9f, 0x55, 0x96, 0x20, 0x27, 0x22, -0x03, 0x75, 0x81, 0x55, 0x9a, 0x20, 0x22, 0x00, 0xe0, 0x70, 0x02, 0x19, 0x00, 0x00, 0x52, 0x48, -0x2c, 0x00, 0x00, 0x55, 0x53, 0x44, 0x56, 0x52, 0x2c, 0x67, 0x00, 0x52, 0x48, 0x2c, 0x67, 0x00, -0x55, 0x53, 0x44, 0x56, 0x52, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x5a, 0x03, 0x48, 0x02, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xb5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x06, 0xc4, 0x00, 0x6a, 0x24, 0x4a, 0x24, 0x0a, 0x24, 0x00, 0x24, 0x00, 0x24, 0x07, 0xc4, -0x00, 0x6c, 0x26, 0x4c, 0x26, 0x0c, 0x26, 0x00, 0x26, 0x00, 0x26, 0x08, 0xc4, 0x00, 0x6d, 0x32, -0x4d, 0x32, 0x0d, 0x32, 0x00, 0x32, 0x00, 0x32, 0x09, 0xc4, 0x00, 0x66, 0x21, 0x46, 0x21, 0x06, -0x21, 0x00, 0x21, 0x00, 0x21, 0x0a, 0xc4, 0x00, 0x70, 0x19, 0x50, 0x19, 0x10, 0x19, 0x00, 0x19, -0x00, 0x19, 0x0b, 0x84, 0x00, 0x2f, 0x35, 0x3f, 0x35, 0x00, 0x35, 0x00, 0x35, 0x00, 0x35, 0x0c, -0x84, 0x00, 0x5b, 0x1a, 0x7b, 0x1a, 0x1b, 0x1a, 0x00, 0x1a, 0x00, 0x1a, 0x0d, 0x84, 0x00, 0x5d, -0x1b, 0x7d, 0x1b, 0x1d, 0x1b, 0x00, 0x1b, 0x00, 0x1b, 0x10, 0x84, 0x00, 0x35, 0x06, 0x25, 0x06, -0x00, 0x06, 0x00, 0x7d, 0x00, 0x7d, 0x11, 0x84, 0x00, 0x36, 0x07, 0x5e, 0x07, 0x1e, 0x07, 0x00, -0x7e, 0x00, 0x7e, 0x12, 0xc4, 0x00, 0x71, 0x10, 0x51, 0x10, 0x11, 0x10, 0x00, 0x10, 0x00, 0x10, -0x13, 0x84, 0x00, 0x2e, 0x34, 0x3e, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x14, 0xc4, 0x00, -0x6f, 0x18, 0x4f, 0x18, 0x0f, 0x18, 0x00, 0x18, 0x00, 0x18, 0x15, 0xc4, 0x00, 0x72, 0x13, 0x52, -0x13, 0x12, 0x13, 0x00, 0x13, 0x00, 0x13, 0x16, 0xc4, 0x00, 0x73, 0x1f, 0x53, 0x1f, 0x13, 0x1f, -0x00, 0x1f, 0x00, 0x1f, 0x17, 0xc4, 0x00, 0x75, 0x16, 0x55, 0x16, 0x15, 0x16, 0x00, 0x16, 0x00, -0x16, 0x18, 0xc4, 0x00, 0x79, 0x15, 0x59, 0x15, 0x19, 0x15, 0x00, 0x15, 0x00, 0x15, 0x19, 0xc4, -0x00, 0x62, 0x30, 0x42, 0x30, 0x02, 0x30, 0x00, 0x30, 0x00, 0x30, 0x1a, 0x84, 0x00, 0x3b, 0x27, -0x3a, 0x27, 0x00, 0x27, 0x00, 0x27, 0x00, 0x27, 0x1b, 0x84, 0x00, 0x3d, 0x0d, 0x2b, 0x0d, 0x00, -0x0d, 0x00, 0x83, 0x00, 0x83, 0x1e, 0x84, 0x00, 0x37, 0x08, 0x26, 0x08, 0x00, 0x08, 0x00, 0x7f, -0x00, 0x7f, 0x1f, 0x84, 0x00, 0x38, 0x09, 0x2a, 0x09, 0x00, 0x09, 0x00, 0x80, 0x00, 0x80, 0x20, -0xc4, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x21, 0xc4, 0x00, 0x61, -0x1e, 0x41, 0x1e, 0x01, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x22, 0xc4, 0x00, 0x65, 0x12, 0x45, 0x12, -0x05, 0x12, 0x00, 0x12, 0x00, 0x12, 0x24, 0xc4, 0x00, 0x74, 0x14, 0x54, 0x14, 0x14, 0x14, 0x00, -0x14, 0x00, 0x14, 0x25, 0xc4, 0x00, 0x64, 0x20, 0x44, 0x20, 0x04, 0x20, 0x00, 0x20, 0x00, 0x20, -0x26, 0xc4, 0x00, 0x63, 0x2e, 0x43, 0x2e, 0x03, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x27, 0xc4, 0x00, -0x6b, 0x25, 0x4b, 0x25, 0x0b, 0x25, 0x00, 0x25, 0x00, 0x25, 0x28, 0x84, 0x00, 0x2d, 0x0c, 0x5f, -0x0c, 0x1f, 0x0c, 0x00, 0x82, 0x00, 0x82, 0x2c, 0x84, 0x00, 0x39, 0x0a, 0x28, 0x0a, 0x00, 0x0a, -0x00, 0x80, 0x00, 0x80, 0x2d, 0x84, 0x00, 0x30, 0x0b, 0x29, 0x0b, 0x00, 0x0b, 0x00, 0x81, 0x00, -0x81, 0x2e, 0xc4, 0x00, 0x78, 0x2d, 0x58, 0x2d, 0x18, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x2f, 0x84, -0x00, 0x2c, 0x33, 0x3c, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x30, 0xc4, 0x00, 0x69, 0x17, -0x49, 0x17, 0x09, 0x17, 0x00, 0x17, 0x00, 0x17, 0x32, 0xc4, 0x00, 0x77, 0x11, 0x57, 0x11, 0x17, -0x11, 0x00, 0x11, 0x00, 0x11, 0x33, 0xc4, 0x00, 0x76, 0x2f, 0x56, 0x2f, 0x16, 0x2f, 0x00, 0x2f, -0x00, 0x2f, 0x34, 0xc4, 0x00, 0x67, 0x22, 0x47, 0x22, 0x07, 0x22, 0x00, 0x22, 0x00, 0x22, 0x35, -0x84, 0x00, 0x27, 0x28, 0x22, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x22, 0xc4, 0x00, -0x65, 0x12, 0x45, 0x12, 0x05, 0x12, 0xd5, 0x12, 0x00, 0x12, 0x00, 0xc3, 0x40, 0x03, 0x09, 0x00, -0x00, 0x53, 0x46, 0x2c, 0x96, 0x00, 0x53, 0x46, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, -0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xeb, 0x01, 0xf4, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, -0xf4, 0x01, 0x00, 0x00, 0xb5, 0x01, 0x7c, 0x01, 0x9c, 0x01, 0x00, 0x00, 0x5b, 0x03, 0x6f, 0x02, -0xb9, 0x02, 0x00, 0x00, 0x40, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x0c, 0x40, -0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x09, 0x00, -0x2b, 0x2b, 0x00, 0x7c, 0x03, 0x04, 0x09, 0x00, 0x22, 0x22, 0x00, 0x40, 0x04, 0x04, 0x09, 0x00, -0x2a, 0x2a, 0x00, 0x23, 0x05, 0x04, 0x09, 0x00, 0x87, 0x87, 0x00, 0xf8, 0x06, 0x04, 0x0f, 0x00, -0x00, 0x00, 0x00, 0xf5, 0x07, 0x04, 0x09, 0x00, 0x26, 0x26, 0x00, 0xaa, 0x08, 0x04, 0x09, 0x00, -0x2f, 0x2f, 0x00, 0xdd, 0x09, 0x04, 0x09, 0x00, 0x28, 0x28, 0x00, 0xbd, 0x0a, 0x02, 0x01, 0x00, -0x29, 0x29, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x3d, 0x0c, 0x04, 0x10, 0x27, 0x3f, 0x3f, 0x27, 0xcb, -0x0d, 0x05, 0x1f, 0xca, 0xc8, 0xc8, 0xca, 0xc9, 0x1e, 0x12, 0x03, 0x00, 0x65, 0x45, 0x65, 0x45, -0x15, 0x86, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x7a, 0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, -0x2c, 0x16, 0x03, 0x00, 0x75, 0x55, 0x75, 0x55, 0x17, 0x03, 0x00, 0x69, 0x49, 0x69, 0x49, 0x18, -0x03, 0x00, 0x6f, 0x4f, 0x6f, 0x4f, 0x1a, 0x04, 0x00, 0x8a, 0x81, 0x9a, 0xd4, 0x5b, 0x1b, 0x04, -0x09, 0xcc, 0x21, 0x21, 0xcc, 0x5d, 0x1e, 0x03, 0x00, 0x61, 0x41, 0x61, 0x41, 0x1f, 0x04, 0x0f, -0x00, 0x00, 0x00, 0x00, 0xe1, 0x27, 0x03, 0x00, 0x82, 0x94, 0x99, 0x90, 0x28, 0x04, 0x00, 0x85, -0x84, 0x8e, 0xb7, 0x7b, 0x29, 0x03, 0x00, 0xf5, 0xf8, 0xf8, 0xf5, 0x2b, 0x04, 0x00, 0x24, 0x9c, -0x9c, 0x24, 0x7d, 0x2c, 0x86, 0x00, 0x79, 0x15, 0x59, 0x15, 0x79, 0x15, 0x59, 0x15, 0x00, 0x15, -0x19, 0x15, 0x00, 0x15, 0x2e, 0x03, 0x00, 0x63, 0x43, 0x63, 0x43, 0x31, 0x03, 0x00, 0x6e, 0x4e, -0x6e, 0x4e, 0x32, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x33, 0x04, 0x09, 0x00, 0x3b, 0x3b, -0x00, 0x3c, 0x34, 0x04, 0x09, 0x00, 0x3a, 0x3a, 0x00, 0x3e, 0x35, 0x05, 0x00, 0x2d, 0x5f, 0x5f, -0x2d, 0x5c, 0x1f, 0x39, 0x03, 0x06, 0x20, 0x00, 0x00, 0x20, 0x56, 0x05, 0x00, 0x3c, 0x3e, 0x3e, -0x3c, 0x5c, 0x1c, 0x00, 0x06, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x15, 0x08, 0x04, 0x1f, 0x00, -0x00, 0x00, 0x00, 0xa0, 0x09, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x29, 0x03, 0x06, 0x15, -0x00, 0x00, 0x15, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, -0x20, 0x60, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, -0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x09, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, -0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x43, 0x80, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, -0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, -0x20, 0x22, 0x00, 0x12, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, -0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, -0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, -0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0f, 0x61, 0xa0, -0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, 0x80, -0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, -0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, -0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0x08, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x10, -0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x92, 0x12, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x17, -0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xac, 0x18, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xab, 0x1e, -0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x91, 0x2c, 0x86, 0x00, 0x79, 0x15, 0x59, 0x15, 0x79, 0x15, -0x59, 0x15, 0xae, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xaf, -0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, -0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, -0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, -0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, -0x5e, 0x27, 0x0f, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, -0xec, 0x41, 0xb5, 0x43, 0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, -0x27, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, -0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x00, 0x63, 0x7b, -0x02, 0x13, 0x00, 0x00, 0x53, 0x47, 0x2c, 0x00, 0x00, 0x53, 0x44, 0x2c, 0x96, 0x00, 0x53, 0x47, -0x2c, 0x96, 0x00, 0x53, 0x44, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x5a, 0x03, 0xe3, 0x01, 0xec, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0xec, 0x01, 0x00, -0x00, 0xb5, 0x01, 0x74, 0x01, 0x94, 0x01, 0x00, 0x00, 0x40, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x00, -0x00, 0x40, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x02, 0x04, 0x09, 0x00, 0x2b, 0x2b, 0x00, 0x7c, 0x03, 0x04, 0x09, 0x00, 0x22, 0x22, 0x00, -0x40, 0x04, 0x04, 0x09, 0x00, 0x2a, 0x2a, 0x00, 0x23, 0x05, 0x04, 0x09, 0x00, 0x87, 0x87, 0x00, -0xf8, 0x06, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x07, 0x04, 0x09, 0x00, 0x26, 0x26, 0x00, -0xaa, 0x08, 0x04, 0x09, 0x00, 0x2f, 0x2f, 0x00, 0xdd, 0x09, 0x04, 0x09, 0x00, 0x28, 0x28, 0x00, -0xbd, 0x0a, 0x02, 0x01, 0x00, 0x29, 0x29, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x3d, 0x0c, 0x04, 0x10, -0x27, 0x3f, 0x3f, 0x27, 0xcb, 0x0d, 0x05, 0x1f, 0xca, 0xc8, 0xc8, 0xca, 0xc9, 0x1e, 0x12, 0x03, -0x00, 0x65, 0x45, 0x65, 0x45, 0x15, 0x86, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x7a, 0x2c, 0x5a, 0x2c, -0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x03, 0x00, 0x75, 0x55, 0x75, 0x55, 0x17, 0x03, 0x00, -0x69, 0x49, 0x69, 0x49, 0x18, 0x03, 0x00, 0x6f, 0x4f, 0x6f, 0x4f, 0x1a, 0x04, 0x00, 0x81, 0x8a, -0xd4, 0x9a, 0x5b, 0x1b, 0x04, 0x09, 0xcc, 0x21, 0x21, 0xcc, 0x5d, 0x1e, 0x03, 0x00, 0x61, 0x41, -0x61, 0x41, 0x1f, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x27, 0x03, 0x00, 0x94, 0x82, 0x90, -0x99, 0x28, 0x04, 0x00, 0x84, 0x85, 0xb7, 0x8e, 0x7b, 0x29, 0x03, 0x00, 0xf5, 0xf8, 0xf8, 0xf5, -0x2b, 0x04, 0x00, 0x24, 0x9c, 0x9c, 0x24, 0x7d, 0x2c, 0x86, 0x00, 0x79, 0x15, 0x59, 0x15, 0x79, -0x15, 0x59, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2e, 0x03, 0x00, 0x63, 0x43, 0x63, 0x43, -0x31, 0x03, 0x00, 0x6e, 0x4e, 0x6e, 0x4e, 0x32, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x33, -0x04, 0x09, 0x00, 0x3b, 0x3b, 0x00, 0x3c, 0x34, 0x04, 0x09, 0x00, 0x3a, 0x3a, 0x00, 0x3e, 0x35, -0x05, 0x00, 0x2d, 0x5f, 0x5f, 0x2d, 0x5c, 0x1f, 0x39, 0x03, 0x06, 0x20, 0x00, 0x00, 0x20, 0x56, -0x05, 0x00, 0x3c, 0x3e, 0x3e, 0x3c, 0x5c, 0x1c, 0x00, 0x06, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, -0x15, 0x08, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x09, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, -0x9b, 0x29, 0x03, 0x06, 0x15, 0x00, 0x00, 0x15, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, -0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, -0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x09, 0x61, -0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x43, 0x80, 0x45, 0x90, 0x20, -0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, -0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x12, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xd5, -0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, -0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, -0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, -0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, -0x5e, 0xef, 0x0f, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, -0xec, 0x41, 0xb5, 0x43, 0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, -0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, -0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0xef, 0xf0, 0x03, 0x09, -0x00, 0x00, 0x53, 0x4b, 0x2c, 0xf5, 0x00, 0x53, 0x4b, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, -0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, 0x49, 0x01, 0xc1, 0x01, 0x00, 0x00, 0x5a, 0x03, 0x82, -0x02, 0x89, 0x02, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x89, 0x02, 0x00, 0x00, 0x63, 0x03, 0x10, -0x03, 0x79, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, -0x2b, 0x31, 0xc8, 0x03, 0x01, 0x01, 0xa0, 0x32, 0x04, 0x03, 0x05, 0xa0, 0x33, 0xc9, 0x1e, 0x05, -0x01, 0x01, 0xa0, 0x34, 0x06, 0x02, 0x05, 0xa0, 0x35, 0xca, 0x07, 0x01, 0x01, 0xa0, 0x36, 0x08, -0x02, 0x04, 0xec, 0x37, 0xcb, 0x09, 0x02, 0x00, 0xa0, 0x38, 0xfa, 0x0a, 0x02, 0x04, 0xa1, 0x39, -0xcc, 0x0b, 0x01, 0x00, 0x82, 0x30, 0x0c, 0x02, 0x04, 0x3d, 0x25, 0xcd, 0x0d, 0x02, 0x07, 0xcc, -0xa0, 0xce, 0x10, 0x42, 0x03, 0x00, 0x00, 0x5c, 0x11, 0x42, 0x03, 0x00, 0x00, 0x7c, 0x12, 0x41, -0x00, 0x65, 0x45, 0x15, 0xc4, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, -0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x19, -0x42, 0x03, 0x00, 0x00, 0x27, 0x1a, 0x02, 0x00, 0xa3, 0x2f, 0xf6, 0x1b, 0x02, 0x00, 0x84, 0x28, -0x9e, 0x1e, 0x42, 0x00, 0x61, 0x41, 0x3c, 0x21, 0x42, 0x03, 0x00, 0x00, 0x5b, 0x22, 0x42, 0x03, -0x00, 0x00, 0x5d, 0x27, 0x02, 0x00, 0x93, 0x22, 0x24, 0x28, 0x02, 0x00, 0xf5, 0x21, 0xe1, 0x29, -0x01, 0x02, 0x3b, 0xca, 0x2b, 0x02, 0x01, 0xa0, 0x29, 0xcf, 0x2c, 0xc4, 0x00, 0x79, 0x15, 0x59, -0x15, 0x3e, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x42, 0x03, 0x00, 0x00, 0x23, 0x2e, 0x42, 0x00, -0x63, 0x43, 0x26, 0x2f, 0x42, 0x03, 0x00, 0x00, 0x40, 0x30, 0x42, 0x03, 0x00, 0x00, 0x7b, 0x31, -0x42, 0x00, 0x6e, 0x4e, 0x7d, 0x33, 0x01, 0x01, 0x00, 0x3f, 0x34, 0x02, 0x01, 0x00, 0x3a, 0x2a, -0x35, 0x03, 0x04, 0x2d, 0x5f, 0x00, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, 0x02, 0x00, 0x26, 0x2a, -0x3c, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x03, 0x02, 0x06, 0x96, 0x00, 0xc8, 0x04, 0x00, -0x00, 0xe7, 0x05, 0x02, 0x06, 0x9f, 0x00, 0xca, 0x06, 0x02, 0x06, 0x9c, 0x00, 0xcb, 0x07, 0x02, -0x06, 0xa7, 0x00, 0xcc, 0x08, 0x02, 0x03, 0x00, 0x00, 0x60, 0x09, 0x02, 0x07, 0x00, 0x00, 0xcd, -0x0a, 0x02, 0x07, 0x00, 0x00, 0xce, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xcf, 0x0c, 0x02, 0x07, 0x00, -0x00, 0xd0, 0x0d, 0x02, 0x07, 0xce, 0xc8, 0xd1, 0x12, 0x42, 0x03, 0x00, 0x00, 0xaa, 0x13, 0x41, -0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, 0x54, 0x1f, 0x42, 0x00, 0x73, 0x53, 0xd0, 0x20, 0x42, -0x00, 0x64, 0x44, 0xd1, 0x25, 0x42, 0x03, 0x00, 0x00, 0x88, 0x26, 0x42, 0x00, 0x6c, 0x4c, 0x9d, -0x29, 0x01, 0x03, 0x00, 0xcb, 0x2b, 0x00, 0x00, 0xe5, 0x00, 0xf3, 0x13, 0x63, 0x9f, 0x64, 0xd4, -0x65, 0xd8, 0x6c, 0x96, 0x6e, 0xe5, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa7, 0x43, 0xac, -0x44, 0xd2, 0x45, 0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, 0xa6, -0x20, 0xf3, 0x5e, 0x07, 0x61, 0x83, 0x69, 0x8c, 0x6f, 0x93, 0x41, 0xb6, 0x49, 0xd7, 0x4f, 0xe2, -0x20, 0x5e, 0xf4, 0x03, 0x61, 0xc7, 0x41, 0xc6, 0x20, 0xf4, 0xf8, 0x03, 0x75, 0x85, 0x55, 0xde, -0x20, 0xf8, 0xf2, 0x05, 0x61, 0xa5, 0x65, 0xa9, 0x41, 0xa4, 0x45, 0xa8, 0x20, 0xf2, 0xfa, 0x03, -0x7a, 0xbe, 0x5a, 0xbd, 0x20, 0xfa, 0xef, 0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, 0xa1, -0x6c, 0x92, 0x6e, 0xe4, 0x6f, 0xa2, 0x72, 0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, 0xab, -0x41, 0xb5, 0x43, 0x8f, 0x45, 0x90, 0x49, 0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, 0xe8, -0x53, 0x97, 0x55, 0xe9, 0x59, 0xed, 0x5a, 0x8d, 0x20, 0xef, 0xf1, 0x05, 0x6f, 0x8b, 0x75, 0xfb, -0x4f, 0x8a, 0x55, 0xeb, 0x20, 0xf1, 0xf9, 0x09, 0x61, 0x84, 0x65, 0x89, 0x6f, 0x94, 0x75, 0x81, -0x41, 0x8e, 0x45, 0xd3, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf7, 0x07, 0x63, 0x87, 0x73, 0xad, -0x74, 0xee, 0x43, 0x80, 0x53, 0xb8, 0x54, 0xdd, 0x20, 0xf7, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, -0xd5, 0x00, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, -0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, -0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf8, 0x03, 0x61, 0x86, 0x41, 0x8f, -0x20, 0xf8, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, -0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, -0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, -0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, -0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, -0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x03, -0x02, 0x06, 0x8c, 0x00, 0xc8, 0x04, 0x00, 0x00, 0xa8, 0x05, 0x00, 0x00, 0x87, 0x06, 0x00, 0x00, -0x9f, 0x07, 0x00, 0x00, 0x91, 0x08, 0x02, 0x02, 0x98, 0x00, 0x60, 0x09, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xcb, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x0d, 0x02, 0x07, -0xcb, 0xc8, 0xa0, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, 0x54, 0x1b, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, 0x41, 0x00, 0x64, 0x44, 0x26, 0x41, 0x00, -0x6c, 0x4c, 0x28, 0x00, 0x00, 0xad, 0x29, 0x01, 0x03, 0x00, 0xca, 0x2b, 0x02, 0x06, 0xa4, 0x00, -0xa0, 0x00, 0x76, 0x13, 0x63, 0x87, 0x64, 0x83, 0x65, 0x88, 0x6c, 0x8c, 0x6e, 0xa4, 0x72, 0xa9, -0x73, 0xa8, 0x74, 0x9f, 0x7a, 0x91, 0x43, 0x80, 0x44, 0x85, 0x45, 0x89, 0x4c, 0x9c, 0x4e, 0xa5, -0x52, 0x9e, 0x53, 0x9b, 0x54, 0x86, 0x5a, 0x92, 0x20, 0x76, 0x5e, 0x03, 0x6f, 0x93, 0x4f, 0xa7, -0x20, 0x5e, 0xf8, 0x03, 0x75, 0x96, 0x55, 0xa6, 0x20, 0xf8, 0x27, 0x11, 0x61, 0xa0, 0x65, 0x82, -0x69, 0xa1, 0x6c, 0x8d, 0x6f, 0xa2, 0x72, 0xaa, 0x75, 0xa3, 0x79, 0x98, 0x41, 0x8f, 0x45, 0x90, -0x49, 0x8b, 0x4c, 0x8a, 0x4f, 0x95, 0x52, 0xab, 0x55, 0x97, 0x59, 0x9d, 0x20, 0x27, 0x22, 0x07, -0x61, 0x84, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x9b, -0x44, 0x02, 0x1d, 0x00, 0x00, 0x53, 0x50, 0x2c, 0x00, 0x00, 0x45, 0x53, 0x2c, 0xac, 0x00, 0x53, -0x50, 0x2c, 0xac, 0x00, 0x45, 0x53, 0x2c, 0xad, 0x00, 0x53, 0x50, 0x2c, 0xad, 0x00, 0x45, 0x53, -0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0x40, 0x01, -0x4d, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x4d, 0x01, 0x00, 0x00, 0xb5, 0x01, 0x00, 0x00, -0xf5, 0x00, 0x00, 0x00, 0x37, 0x75, 0xc4, 0x01, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, -0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7c, 0x03, 0x02, 0x01, 0x00, 0x22, 0x40, -0x04, 0x02, 0x01, 0x00, 0xfa, 0x23, 0x05, 0x02, 0x07, 0x00, 0x00, 0xc9, 0x07, 0x02, 0x01, 0x00, -0x26, 0xaa, 0x08, 0x01, 0x01, 0x00, 0x2f, 0x09, 0x01, 0x01, 0x00, 0x28, 0x0a, 0x01, 0x01, 0x00, -0x29, 0x0b, 0x01, 0x01, 0x00, 0x3d, 0x0c, 0x01, 0x00, 0x27, 0x3f, 0x0d, 0x01, 0x00, 0xad, 0xa8, -0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, -0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x02, 0x03, 0xc8, 0xca, 0x5b, 0x1b, -0x02, 0x00, 0x2b, 0x2a, 0x5d, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x42, 0x00, 0xa4, 0xa5, 0x7e, -0x28, 0x02, 0x03, 0xcb, 0xcc, 0x7b, 0x29, 0x03, 0x00, 0xa7, 0xa6, 0x5c, 0x1c, 0x2b, 0x42, 0x00, -0x87, 0x80, 0x7d, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, -0x01, 0x00, 0x3a, 0x3e, 0x35, 0x03, 0x00, 0x2d, 0x5f, 0x5c, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, -0x01, 0x00, 0x3c, 0x3e, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, -0x97, 0x20, 0x60, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, -0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x07, 0x61, 0xa0, 0x65, 0x82, 0x69, -0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, -0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, -0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, -0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, -0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, -0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, -0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0d, 0x61, -0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, -0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, -0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, -0x9a, 0x20, 0xf9, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, -0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x1a, 0x01, 0x03, 0x00, 0xa0, 0x26, 0x04, 0x0b, 0x00, 0x00, -0xf2, 0x00, 0xf6, 0x28, 0x01, 0x03, 0xc9, 0xca, 0x2c, 0x02, 0x03, 0x00, 0x00, 0xae, 0x2d, 0x02, -0x03, 0x00, 0x00, 0xaf, 0x00, 0x60, 0x07, 0x61, 0x85, 0x65, 0x8a, 0x6f, 0x95, 0x41, 0xb7, 0x45, -0xd4, 0x4f, 0xe3, 0x20, 0x60, 0x27, 0x09, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x45, -0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x20, 0x27, 0x22, 0x05, 0x69, 0x8b, 0x75, 0x81, 0x49, -0xd8, 0x55, 0x9a, 0x20, 0x22, 0x00, 0xcc, 0x27, 0x04, 0x1d, 0x00, 0x00, 0x53, 0x55, 0x2c, 0x00, -0x00, 0x53, 0x56, 0x2c, 0x00, 0x00, 0x46, 0x49, 0x2c, 0x99, 0x00, 0x53, 0x55, 0x2c, 0x99, 0x00, -0x53, 0x56, 0x2c, 0x99, 0x00, 0x46, 0x49, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, -0x00, 0x00, 0x00, 0x5a, 0x03, 0x7a, 0x01, 0x87, 0x01, 0x00, 0x00, 0x5b, 0x03, 0x02, 0x02, 0x25, -0x02, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x87, 0x01, 0x00, 0x00, 0xb5, 0x01, 0x21, 0x01, 0x2b, -0x01, 0x00, 0x00, 0x30, 0x75, 0xae, 0x02, 0x00, 0x00, 0x00, 0x00, 0x30, 0x75, 0x66, 0x03, 0x00, -0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x9c, 0x05, -0x02, 0x01, 0x00, 0xcf, 0x24, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, 0x02, 0x01, 0x00, 0x2f, 0x7b, -0x09, 0x04, 0x09, 0x00, 0x28, 0x5b, 0x00, 0x1b, 0x0a, 0x04, 0x09, 0x00, 0x29, 0x5d, 0x00, 0x1d, -0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, 0x04, 0x08, 0x2b, 0x3f, 0x5c, 0x00, 0x1c, 0x0d, 0x02, -0x03, 0xcb, 0xc8, 0x7c, 0x10, 0x42, 0x03, 0x00, 0x00, 0x40, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, -0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, -0x00, 0x6f, 0x4f, 0x1a, 0x41, 0x00, 0x86, 0x8f, 0x1b, 0x04, 0x0f, 0xcc, 0xca, 0xc9, 0x00, 0x1e, -0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x41, 0x00, 0x94, 0x99, 0x28, 0x41, 0x00, 0x84, 0x8e, 0x29, -0x01, 0x00, 0xf5, 0xab, 0x2b, 0x01, 0x00, 0x27, 0x2a, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, -0x00, 0x6e, 0x4e, 0x32, 0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, -0x02, 0x01, 0x00, 0x3a, 0x3e, 0x35, 0x04, 0x0c, 0x2d, 0x5f, 0x00, 0x00, 0x1f, 0x39, 0x00, 0x00, -0x20, 0x56, 0x02, 0x00, 0x3c, 0x3e, 0x7c, 0x00, 0x05, 0x01, 0x03, 0x00, 0xa0, 0x29, 0x00, 0x00, -0x15, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, -0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, -0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x09, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, -0x6f, 0xa2, 0x75, 0xa3, 0x43, 0x80, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, -0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, -0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, -0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, -0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, -0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, -0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0f, -0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, -0x43, 0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, -0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, -0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x12, -0x42, 0x03, 0x00, 0x00, 0xd5, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x28, 0x42, 0x07, 0x00, 0x00, 0xcd, -0x29, 0x01, 0x03, 0x00, 0xa0, 0x2c, 0x42, 0x00, 0x7a, 0x5a, 0xaf, 0x00, 0x60, 0x0b, 0x61, 0x85, -0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, -0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, -0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x27, 0x0f, 0x61, 0xa0, -0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, 0x80, -0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0x22, 0x0d, 0x61, 0x84, -0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, -0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x76, 0x05, 0x73, 0xf9, 0x7a, 0xf7, 0x53, 0xdd, -0x5a, 0xef, 0x20, 0x76, 0x00, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, -0xd5, 0x09, 0x03, 0x07, 0x00, 0x00, 0x00, 0xae, 0x0a, 0x03, 0x07, 0x00, 0x00, 0x00, 0xaf, 0x0d, -0x01, 0x03, 0xa0, 0xa0, 0x10, 0x43, 0x03, 0x00, 0x00, 0x83, 0xb6, 0x12, 0x42, 0x03, 0x00, 0x00, -0xd5, 0x14, 0x43, 0x03, 0x00, 0x00, 0xab, 0x97, 0x17, 0x43, 0x03, 0x00, 0x00, 0x8b, 0xd8, 0x18, -0x43, 0x03, 0x00, 0x00, 0xe4, 0xe5, 0x1b, 0x02, 0x07, 0xa0, 0xa0, 0xa0, 0x1e, 0x43, 0x03, 0x00, -0x00, 0xa0, 0xb5, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xaa, 0x96, 0x20, 0x43, 0x03, 0x00, 0x00, 0x9f, -0x8d, 0x21, 0x43, 0x03, 0x00, 0x00, 0x90, 0x80, 0x22, 0x43, 0x03, 0x00, 0x00, 0xa1, 0xa2, 0x23, -0x43, 0x03, 0x00, 0x00, 0x85, 0x82, 0x25, 0x43, 0x03, 0x00, 0x00, 0xa6, 0xa7, 0x27, 0x43, 0x03, -0x00, 0x00, 0x9b, 0x9d, 0x28, 0x43, 0x03, 0x00, 0x00, 0x91, 0x92, 0x29, 0x01, 0x03, 0x00, 0xa0, -0x2c, 0x43, 0x03, 0x00, 0x00, 0xac, 0x98, 0x2e, 0x43, 0x03, 0x00, 0x00, 0x9e, 0x8c, 0x2f, 0x43, -0x03, 0x00, 0x00, 0x89, 0x8a, 0x30, 0x43, 0x03, 0x00, 0x00, 0x87, 0x88, 0x31, 0x43, 0x03, 0x00, -0x00, 0xa9, 0x95, 0x36, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x04, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x09, 0x03, 0x07, 0x00, 0x00, 0x00, 0xae, -0x0a, 0x03, 0x07, 0x00, 0x00, 0x00, 0xaf, 0x0d, 0x01, 0x03, 0xa0, 0xa0, 0x10, 0x43, 0x00, 0xa0, -0xb5, 0x71, 0x51, 0x11, 0x43, 0x00, 0xaa, 0x96, 0x77, 0x57, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, -0x15, 0x43, 0x00, 0xab, 0x97, 0x79, 0x59, 0x17, 0x43, 0x03, 0x00, 0x00, 0x8b, 0xd8, 0x18, 0x43, -0x03, 0x00, 0x00, 0xe4, 0xe5, 0x1b, 0x42, 0x04, 0xa9, 0x95, 0xa0, 0x1e, 0x43, 0x03, 0x00, 0x00, -0x83, 0xb6, 0x22, 0x43, 0x03, 0x00, 0x00, 0xa1, 0xa2, 0x23, 0x43, 0x03, 0x00, 0x00, 0x90, 0x80, -0x25, 0x43, 0x03, 0x00, 0x00, 0xa6, 0xa7, 0x27, 0x43, 0x03, 0x00, 0x00, 0x9b, 0x9d, 0x28, 0x43, -0x03, 0x00, 0x00, 0x91, 0x92, 0x29, 0x01, 0x03, 0x00, 0xa0, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7c, 0x2b, 0x43, 0x00, 0x9f, 0x8d, 0x27, 0x2a, 0x2c, 0x43, 0x03, 0x00, 0x00, 0x87, -0x88, 0x2d, 0x43, 0x00, 0x9e, 0x8c, 0x78, 0x58, 0x56, 0x43, 0x00, 0xac, 0x98, 0x89, 0x8a, 0x00, -0xd6, 0xb8, 0x03, 0x09, 0x00, 0x00, 0x55, 0x4b, 0x2c, 0xa6, 0x00, 0x55, 0x4b, 0x08, 0x03, 0x00, -0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xe7, 0x00, 0x00, 0x00, 0x00, -0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x01, 0xc4, 0x00, 0x00, 0x00, 0x00, -0x00, 0x31, 0x75, 0x84, 0x01, 0xfe, 0x01, 0x00, 0x00, 0x5b, 0x03, 0xee, 0x00, 0x43, 0x01, 0x00, -0x00, 0x55, 0x03, 0x04, 0x03, 0x61, 0x03, 0x00, 0x00, 0x54, 0x03, 0xa7, 0x02, 0xdb, 0x02, 0x00, -0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7c, 0x03, -0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0x9c, 0x12, 0x43, 0x00, 0x65, 0x45, 0x82, 0x90, -0x16, 0x43, 0x00, 0x75, 0x55, 0xa3, 0xe9, 0x17, 0x43, 0x00, 0x69, 0x49, 0xa1, 0xd6, 0x18, 0xc3, -0x00, 0x6f, 0x18, 0x4f, 0x18, 0xa2, 0x18, 0xe0, 0x00, 0x1e, 0x43, 0x00, 0x61, 0x41, 0xa0, 0xb5, -0x28, 0x01, 0x01, 0x00, 0x40, 0x29, 0x02, 0x01, 0x00, 0xaa, 0xdd, 0x2b, 0x01, 0x00, 0x23, 0x7e, -0x35, 0x04, 0x0b, 0x00, 0x00, 0x5c, 0x00, 0x1c, 0x56, 0x04, 0x0c, 0x5c, 0x7c, 0x00, 0x00, 0x1c, -0x00, 0x16, 0x43, 0x0f, 0x00, 0x00, 0x00, 0xa0, 0x17, 0x43, 0x0f, 0x00, 0x00, 0x00, 0xa0, 0x18, -0x43, 0x0f, 0x00, 0x00, 0x00, 0xa0, 0x1e, 0x43, 0x0f, 0x00, 0x00, 0x00, 0xa0, 0x29, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, -0xad, 0x03, 0x01, 0x03, 0x00, 0xca, 0x05, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x07, 0x01, 0x03, 0x00, -0xc8, 0x10, 0x43, 0x03, 0x00, 0x00, 0x91, 0x92, 0x15, 0x41, 0x00, 0x79, 0x59, 0x19, 0x43, 0x03, -0x00, 0x00, 0xab, 0xac, 0x29, 0x02, 0x03, 0xc9, 0x00, 0x7c, 0x2e, 0x43, 0x03, 0x00, 0x00, 0x87, -0x80, 0x31, 0x43, 0x03, 0x00, 0x00, 0xa4, 0xa5, 0x33, 0x02, 0x03, 0x00, 0x00, 0xae, 0x34, 0x02, -0x03, 0x00, 0x00, 0xaf, 0x35, 0x03, 0x07, 0x00, 0x00, 0x00, 0xa8, 0x39, 0x00, 0x00, 0x20, 0x00, -0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, -0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x60, 0x07, 0x61, 0x85, 0x65, 0x8a, 0x75, 0x97, -0x41, 0xb7, 0x45, 0xd4, 0x55, 0xeb, 0x20, 0x60, 0x22, 0x0b, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, -0x75, 0x81, 0x79, 0x98, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, -0x00, 0x03, 0x01, 0x03, 0x00, 0xc9, 0x05, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x07, 0x02, 0x03, 0x00, -0xca, 0x5e, 0x11, 0x43, 0x00, 0x77, 0x57, 0x86, 0x8f, 0x14, 0x41, 0x00, 0x74, 0x54, 0x15, 0x43, -0x00, 0x79, 0x59, 0xec, 0xed, 0x19, 0x41, 0x00, 0x70, 0x50, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, -0x41, 0x00, 0x64, 0x44, 0x21, 0x41, 0x00, 0x66, 0x46, 0x22, 0x41, 0x00, 0x67, 0x47, 0x28, 0x00, -0x01, 0xcb, 0x29, 0x00, 0x01, 0xc8, 0x2b, 0x01, 0x03, 0x00, 0xcc, 0x2c, 0x43, 0x03, 0x00, 0x00, -0xf9, 0xfa, 0x2e, 0x43, 0x00, 0x63, 0x43, 0x87, 0x80, 0x30, 0x41, 0x00, 0x62, 0x42, 0x31, 0x43, -0x03, 0x00, 0x00, 0xa4, 0xa5, 0x32, 0x41, 0x00, 0x6d, 0x4d, 0x33, 0x02, 0x03, 0x00, 0x00, 0xae, -0x34, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x39, 0x00, 0x00, 0x20, 0x00, 0x60, 0x0f, 0x61, 0x85, 0x65, -0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x77, 0x91, 0x79, 0xc6, 0x41, 0xb7, 0x45, 0xd4, 0x49, -0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x57, 0x92, 0x59, 0xc7, 0x20, 0x60, 0x22, 0x0f, 0x61, 0x84, 0x65, -0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x77, 0xa6, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, -0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x57, 0xa7, 0x59, 0xf3, 0x20, 0x22, 0x5e, 0x0f, 0x61, 0x83, 0x65, -0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x77, 0x9b, 0x79, 0xe4, 0x41, 0xb6, 0x45, 0xd2, 0x49, -0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x57, 0x9d, 0x59, 0xe5, 0x20, 0x5e, 0x27, 0x0f, 0x61, 0xa0, 0x65, -0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x77, 0x86, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, -0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x57, 0x8f, 0x59, 0xed, 0x20, 0x27, 0x7e, 0x13, 0x62, 0xf2, 0x63, -0xbd, 0x64, 0xd0, 0x66, 0x9f, 0x67, 0x9e, 0x6d, 0xac, 0x70, 0xa8, 0x73, 0xf4, 0x74, 0xe7, 0x42, -0xa9, 0x43, 0xb8, 0x44, 0xd1, 0x46, 0xbe, 0x47, 0xf6, 0x4d, 0xfb, 0x50, 0xad, 0x53, 0xe1, 0x54, -0xe8, 0x20, 0x7e, 0x00, 0x04, 0x01, 0x03, 0x00, 0xa0, 0x05, 0x02, 0x03, 0x00, 0x00, 0xaa, 0x1f, -0x41, 0x00, 0x73, 0x53, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x29, 0x02, 0x07, 0xc8, 0xa0, 0xa0, 0x2c, -0x41, 0x00, 0x7a, 0x5a, 0x2d, 0x41, 0x00, 0x78, 0x58, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, -0x00, 0x6e, 0x4e, 0x39, 0x00, 0x00, 0x20, 0x00, 0x2d, 0x13, 0x61, 0xa5, 0x63, 0x86, 0x65, 0xa9, -0x6c, 0x88, 0x6e, 0xe4, 0x6f, 0xa2, 0x73, 0x98, 0x78, 0xab, 0x7a, 0xbe, 0x41, 0xa4, 0x43, 0x8f, -0x45, 0xa8, 0x4c, 0x9d, 0x4e, 0xe3, 0x4f, 0xe0, 0x53, 0x97, 0x58, 0x8d, 0x5a, 0xbd, 0x20, 0x2d, -0x00, 0x03, 0x01, 0x03, 0x00, 0xca, 0x07, 0x01, 0x03, 0x00, 0xc9, 0x16, 0x43, 0x03, 0x00, 0x00, -0xed, 0xec, 0x17, 0x43, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x18, 0x43, 0x0c, 0x6f, 0x4f, 0xa0, 0xa0, -0x1e, 0x43, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x22, 0x43, 0x00, 0x67, -0x47, 0xe5, 0xe4, 0x23, 0x43, 0x00, 0x68, 0x48, 0xe8, 0xe7, 0x24, 0x41, 0x00, 0x6a, 0x4a, 0x29, -0x02, 0x03, 0xc8, 0xa0, 0x7c, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xbe, 0xbd, 0x2e, 0x43, 0x00, 0x63, -0x43, 0x91, 0x92, 0x31, 0x42, 0x03, 0x00, 0x00, 0xf3, 0x39, 0x00, 0x00, 0x20, 0x00, 0x60, 0x0b, -0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, -0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x5e, 0x13, 0x63, 0x86, 0x65, 0x88, 0x67, 0x9b, 0x68, 0xa9, -0x69, 0x8c, 0x6a, 0x9f, 0x6f, 0x93, 0x73, 0xc7, 0x75, 0x96, 0x43, 0x8f, 0x45, 0xd2, 0x47, 0x9d, -0x48, 0xa8, 0x49, 0xd7, 0x4a, 0xac, 0x4f, 0xe2, 0x53, 0xc6, 0x55, 0xea, 0x20, 0x5e, 0x22, 0x05, -0x65, 0x89, 0x69, 0x8b, 0x45, 0xd3, 0x49, 0xd8, 0x20, 0x22, 0x00, 0xfc, 0x7f, 0x04, 0x04, 0xa8, -0x00, 0x55, 0x4b, 0x08, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, -0x03, 0x0b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, -0x01, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x75, 0xe2, 0x01, 0x77, 0x02, 0x00, 0x00, 0x5b, -0x03, 0x12, 0x01, 0x89, 0x01, 0x00, 0x00, 0x55, 0x03, 0x20, 0x03, 0x9b, 0x03, 0x00, 0x00, 0x54, -0x03, 0xe8, 0x03, 0x51, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, -0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, -0x02, 0x03, 0x00, 0x00, 0xfb, 0x03, 0x02, 0x01, 0x00, 0x22, 0xfd, 0x04, 0x02, 0x01, 0x00, 0x9c, -0xfc, 0x05, 0x02, 0x03, 0x00, 0x00, 0xac, 0x06, 0x02, 0x03, 0x00, 0x00, 0xab, 0x07, 0x02, 0x01, -0x00, 0x26, 0xf3, 0x08, 0x01, 0x01, 0x00, 0x27, 0x09, 0x01, 0x01, 0x00, 0x28, 0x0a, 0x02, 0x01, -0x00, 0x29, 0xf1, 0x0b, 0x02, 0x01, 0x00, 0x23, 0xf8, 0x0c, 0x02, 0x03, 0x00, 0x00, 0x5f, 0x0d, -0x01, 0x00, 0xaa, 0xee, 0x1a, 0x01, 0x00, 0x40, 0x60, 0x1b, 0x04, 0x08, 0x5b, 0x7b, 0x7e, 0x00, -0x1b, 0x27, 0x01, 0x01, 0x00, 0x2b, 0x28, 0x04, 0x08, 0x3a, 0x2a, 0x5e, 0x00, 0x1e, 0x29, 0x04, -0x08, 0x5c, 0xdd, 0x7c, 0x00, 0x1c, 0x2b, 0x04, 0x0c, 0x5d, 0x7d, 0x00, 0x00, 0x1d, 0x32, 0x42, -0x03, 0x00, 0x00, 0xe6, 0x39, 0x00, 0x00, 0x20, 0x56, 0x04, 0x0c, 0x7c, 0x5f, 0x00, 0x00, 0x1f, -0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x07, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x0d, 0x01, 0x03, 0x00, 0xa0, 0x29, 0x01, 0x03, 0x00, 0xa0, 0x00, 0x12, 0x42, -0x03, 0x00, 0x00, 0xd5, 0x00, 0x02, 0x03, 0x07, 0x00, 0x00, 0x00, 0xad, 0x03, 0x01, 0x03, 0x00, -0xca, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x07, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x08, 0x01, 0x03, 0x00, 0xcb, 0x12, 0x42, 0x00, 0x65, 0x45, 0xd5, 0x15, 0x41, -0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x43, 0x00, -0x6f, 0x4f, 0xab, 0xac, 0x1a, 0x01, 0x03, 0x00, 0xc9, 0x1e, 0x43, 0x00, 0x61, 0x41, 0x91, 0x92, -0x28, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x29, 0x01, 0x03, 0x00, 0xa0, 0x2e, 0x43, 0x03, 0x00, 0x00, -0x87, 0x80, 0x31, 0x43, 0x03, 0x00, 0x00, 0xa4, 0xa5, 0x33, 0x02, 0x03, 0x00, 0x00, 0xae, 0x34, -0x02, 0x03, 0x00, 0x00, 0xaf, 0x35, 0x02, 0x03, 0x00, 0x00, 0xa8, 0x00, 0x5e, 0x0b, 0x61, 0x83, -0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, -0x55, 0xea, 0x20, 0x5e, 0x60, 0x07, 0x61, 0x85, 0x65, 0x8a, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, -0x55, 0xeb, 0x20, 0x60, 0x22, 0x0b, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, -0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x27, 0x0b, 0x61, 0xa0, -0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, -0x55, 0xe9, 0x20, 0x27, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x03, 0x02, 0x03, 0x00, 0xc9, -0xfd, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x07, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x01, 0x03, -0x00, 0xcb, 0x0b, 0x01, 0x03, 0x00, 0xca, 0x0d, 0x01, 0x03, 0x00, 0xcc, 0x11, 0x41, 0x00, 0x77, -0x57, 0x12, 0x42, 0x00, 0x65, 0x45, 0xd5, 0x14, 0x41, 0x00, 0x74, 0x54, 0x15, 0x43, 0x00, 0x79, -0x59, 0xf9, 0xfa, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, -0x6f, 0x4f, 0x19, 0x41, 0x00, 0x70, 0x50, 0x1a, 0x01, 0x03, 0x00, 0xc8, 0x1e, 0x41, 0x00, 0x61, -0x41, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, 0x41, 0x00, 0x64, 0x44, 0x21, 0x41, 0x00, 0x66, 0x46, -0x22, 0x41, 0x00, 0x67, 0x47, 0x2e, 0x43, 0x00, 0x63, 0x43, 0x87, 0x80, 0x30, 0x41, 0x00, 0x62, -0x42, 0x31, 0x43, 0x03, 0x00, 0x00, 0xa4, 0xa5, 0x32, 0x41, 0x00, 0x6d, 0x4d, 0x33, 0x02, 0x03, -0x00, 0x00, 0xae, 0x34, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x00, 0x60, 0x0f, 0x61, 0x85, 0x65, 0x8a, -0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x77, 0x91, 0x79, 0xc6, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, -0x4f, 0xe3, 0x55, 0xeb, 0x57, 0x92, 0x59, 0xc7, 0x20, 0x60, 0x22, 0x0f, 0x61, 0x84, 0x65, 0x89, -0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x77, 0xa6, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, -0x4f, 0x99, 0x55, 0x9a, 0x57, 0xa7, 0x59, 0xf3, 0x20, 0x22, 0x23, 0x0f, 0x61, 0x83, 0x65, 0x88, -0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x77, 0x9b, 0x79, 0xe4, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, -0x4f, 0xe2, 0x55, 0xea, 0x57, 0x9d, 0x59, 0xe5, 0x20, 0x23, 0x27, 0x0f, 0x61, 0xa0, 0x65, 0x82, -0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x77, 0x86, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, -0x4f, 0xe0, 0x55, 0xe9, 0x57, 0x8f, 0x59, 0xed, 0x20, 0x27, 0xee, 0x13, 0x62, 0xf2, 0x63, 0xbd, -0x64, 0xd0, 0x66, 0x9f, 0x67, 0x9e, 0x6d, 0xac, 0x70, 0xa8, 0x73, 0xf4, 0x74, 0xe7, 0x42, 0xa9, -0x43, 0xb8, 0x44, 0xd1, 0x46, 0xbe, 0x47, 0xf6, 0x4d, 0xfb, 0x50, 0xad, 0x53, 0xe1, 0x54, 0xe8, -0x20, 0xee, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x03, 0x01, 0x03, 0x00, 0xc8, 0x05, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x07, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x0d, 0x10, 0x00, 0x00, 0x12, 0x43, 0x00, 0x65, 0x45, 0x82, 0x90, 0x16, 0x43, 0x00, 0x75, 0x55, -0xed, 0xec, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x01, 0x03, 0x00, -0xc9, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x22, 0x43, 0x00, 0x67, 0x47, -0xe5, 0xe4, 0x23, 0x43, 0x00, 0x68, 0x48, 0xe8, 0xe7, 0x24, 0x41, 0x00, 0x6a, 0x4a, 0x28, 0x02, -0x07, 0x00, 0x00, 0xca, 0x29, 0x01, 0x01, 0x00, 0x7c, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xbe, 0xbd, -0x2e, 0x43, 0x00, 0x63, 0x43, 0x91, 0x92, 0x31, 0x42, 0x03, 0x00, 0x00, 0xf3, 0x00, 0x22, 0x05, -0x65, 0x89, 0x69, 0x8b, 0x45, 0xd3, 0x49, 0xd8, 0x20, 0x22, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, -0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, -0x20, 0x60, 0x5e, 0x13, 0x63, 0x86, 0x65, 0x88, 0x67, 0x9b, 0x68, 0xa9, 0x69, 0x8c, 0x6a, 0x9f, -0x6f, 0x93, 0x73, 0xc7, 0x75, 0x96, 0x43, 0x8f, 0x45, 0xd2, 0x47, 0x9d, 0x48, 0xa8, 0x49, 0xd7, -0x4a, 0xac, 0x4f, 0xe2, 0x53, 0xc6, 0x55, 0xea, 0x20, 0x5e, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x03, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0xa0, 0xa0, 0x05, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x07, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x01, 0x03, 0xc8, 0xa0, 0x12, 0x42, 0x00, 0x65, 0x45, 0xaa, -0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x26, -0x41, 0x00, 0x6c, 0x4c, 0x29, 0x01, 0x03, 0x00, 0xa0, 0x2c, 0x41, 0x00, 0x7a, 0x5a, 0x2d, 0x41, -0x00, 0x78, 0x58, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x42, 0x07, -0x00, 0x00, 0xa0, 0x00, 0x60, 0x13, 0x61, 0xa5, 0x63, 0x86, 0x65, 0xa9, 0x6c, 0x88, 0x6e, 0xe4, -0x6f, 0xa2, 0x73, 0x98, 0x78, 0xab, 0x7a, 0xbe, 0x41, 0xa4, 0x43, 0x8f, 0x45, 0xa8, 0x4c, 0x9d, -0x4e, 0xe3, 0x4f, 0xe0, 0x53, 0x97, 0x58, 0x8d, 0x5a, 0xbd, 0x20, 0x60, 0x00, 0x88, 0xa6, 0x02, -0x09, 0x00, 0x00, 0x55, 0x53, 0x2c, 0x67, 0x00, 0x55, 0x53, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, -0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x03, -0xdb, 0x01, 0x37, 0x02, 0x00, 0x00, 0x55, 0x03, 0x8f, 0x00, 0xce, 0x00, 0x00, 0x00, 0x52, 0x03, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x75, -0x03, 0x01, 0x08, 0x01, 0x00, 0x00, 0x47, 0x75, 0x21, 0x01, 0x66, 0x01, 0x00, 0x00, 0x00, 0x08, -0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x41, -0x00, 0x65, 0x45, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, -0x6f, 0x4f, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x39, 0x00, 0x00, 0x20, 0x00, 0x06, 0x02, 0x03, 0x00, -0x00, 0xd5, 0x12, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x07, 0x01, 0x03, 0x00, 0xc8, 0x12, 0x03, -0x03, 0x00, 0x00, 0x82, 0x90, 0x16, 0x03, 0x03, 0x00, 0x00, 0xed, 0xec, 0x1f, 0x41, 0x00, 0x73, -0x53, 0x22, 0x41, 0x00, 0x67, 0x47, 0x23, 0x41, 0x00, 0x68, 0x48, 0x24, 0x41, 0x00, 0x6a, 0x4a, -0x28, 0x01, 0x03, 0x00, 0xc9, 0x29, 0x03, 0x03, 0x00, 0x00, 0x8a, 0xd4, 0x2e, 0x41, 0x00, 0x63, -0x43, 0x31, 0x02, 0x03, 0x00, 0x00, 0xf3, 0x00, 0x5e, 0x13, 0x63, 0x86, 0x67, 0x9b, 0x68, 0xa9, -0x6a, 0x9f, 0x73, 0xc7, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x43, 0x8f, 0x47, 0x9d, -0x48, 0xa8, 0x4a, 0xac, 0x53, 0xc6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, -0x22, 0x05, 0x65, 0x89, 0x69, 0x8b, 0x45, 0xd3, 0x49, 0xd8, 0x20, 0x22, 0x00, 0x29, 0x00, 0x01, -0xc8, 0x00, 0x60, 0x0b, 0x61, 0xee, 0x65, 0xd0, 0x69, 0xf6, 0x6f, 0xfa, 0x75, 0xfc, 0x41, 0xef, -0x45, 0xd1, 0x49, 0xf7, 0x4f, 0xfb, 0x55, 0xfd, 0x20, 0x60, 0x00, 0x07, 0x01, 0x03, 0x00, 0xca, -0x12, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x14, 0x41, 0x00, 0x74, 0x54, 0x18, 0x03, 0x03, 0x00, 0x00, -0xab, 0xac, 0x1e, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, 0x41, -0x00, 0x64, 0x44, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x28, 0x01, 0x03, 0xcb, 0xcc, 0x29, 0x01, 0x03, -0xc8, 0xc9, 0x2e, 0x03, 0x03, 0x00, 0x00, 0x87, 0x80, 0x31, 0x42, 0x00, 0x6e, 0x4e, 0xf2, 0x00, -0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, -0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x03, 0x6e, 0xbd, 0x4e, 0xbe, 0x20, 0x7e, -0x5e, 0x15, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x73, 0xf9, 0x64, 0xd0, -0x6c, 0x9b, 0x6e, 0x9e, 0x74, 0xe7, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, -0x53, 0xdd, 0x44, 0xd1, 0x4c, 0x9d, 0x4e, 0x9f, 0x54, 0xe8, 0x20, 0x5e, 0x27, 0x0b, 0x61, 0xa0, -0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, -0x55, 0xe9, 0x20, 0x27, 0x22, 0x07, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x45, 0xd3, 0x49, 0xd8, -0x4f, 0x99, 0x20, 0x22, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0xad, 0x06, 0x02, 0x03, 0x00, 0x00, -0xd5, 0x07, 0x01, 0x03, 0x00, 0xc8, 0x12, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x15, 0x41, 0x00, -0x79, 0x59, 0x18, 0x03, 0x03, 0x00, 0x00, 0xab, 0xac, 0x1e, 0x03, 0x03, 0x00, 0x00, 0x86, 0x8f, -0x1f, 0x02, 0x03, 0x00, 0x00, 0xe1, 0x28, 0x01, 0x03, 0xc9, 0xca, 0x29, 0x01, 0x03, 0xcb, 0xcc, -0x2e, 0x03, 0x03, 0x00, 0x00, 0x87, 0x80, 0x31, 0x43, 0x00, 0x6e, 0x4e, 0xa4, 0xa5, 0x33, 0x02, -0x03, 0x00, 0x00, 0xae, 0x34, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x35, 0x02, 0x03, 0x00, 0x00, 0xa8, -0x00, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, -0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x27, 0x0b, 0x61, 0xa0, 0x65, 0x82, 0x69, -0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x20, -0x27, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, -0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x60, 0x07, 0x61, -0x85, 0x65, 0x8a, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x03, 0x6e, -0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x00, 0x3c, 0xf0, 0x03, 0x27, 0x00, 0x00, 0x59, 0x55, 0x2c, 0x00, -0x00, 0x42, 0x41, 0x2c, 0x00, 0x00, 0x48, 0x52, 0x2c, 0x00, 0x00, 0x53, 0x49, 0x2c, 0xea, 0x00, -0x59, 0x55, 0x2c, 0xea, 0x00, 0x42, 0x41, 0x2c, 0xea, 0x00, 0x48, 0x52, 0x2c, 0xea, 0x00, 0x53, -0x49, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, 0xf2, -0x01, 0x79, 0x02, 0x00, 0x00, 0x71, 0x00, 0x3d, 0x01, 0x93, 0x01, 0x00, 0x00, 0x5a, 0x03, 0x3a, -0x03, 0x41, 0x03, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x41, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x03, 0x01, 0x01, 0x00, 0x22, -0x04, 0x03, 0x07, 0x00, 0x00, 0xc9, 0x1e, 0x06, 0x02, 0x07, 0x00, 0x00, 0xca, 0x07, 0x01, 0x01, -0x00, 0x26, 0x08, 0x02, 0x05, 0x00, 0x2f, 0xcb, 0x09, 0x02, 0x01, 0x00, 0x28, 0xfa, 0x0a, 0x02, -0x05, 0x00, 0x29, 0xcc, 0x0b, 0x01, 0x01, 0x00, 0x3d, 0x0c, 0x02, 0x04, 0x27, 0x3f, 0xcd, 0x0d, -0x02, 0x04, 0x2b, 0x2a, 0xce, 0x10, 0x42, 0x03, 0x00, 0x00, 0x5c, 0x11, 0x42, 0x03, 0x00, 0x00, -0x7c, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0xc4, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x1a, -0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, -0x6f, 0x4f, 0x1a, 0x42, 0x03, 0xa0, 0xa0, 0xf6, 0x1b, 0x42, 0x03, 0xa0, 0xa0, 0x9e, 0x1e, 0x41, -0x00, 0x61, 0x41, 0x21, 0x42, 0x03, 0x00, 0x00, 0x5b, 0x22, 0x42, 0x03, 0x00, 0x00, 0x5d, 0x27, -0x43, 0x07, 0xa0, 0xa0, 0x00, 0x1d, 0x28, 0x42, 0x03, 0xa0, 0xa0, 0xe1, 0x29, 0x01, 0x03, 0xce, -0xcd, 0x2b, 0x42, 0x03, 0xa0, 0xa0, 0xcf, 0x2c, 0xc4, 0x00, 0x79, 0x15, 0x59, 0x15, 0x00, 0x15, -0x19, 0x15, 0x00, 0x15, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x2f, 0x42, 0x03, 0x00, 0x00, 0x40, 0x30, -0x42, 0x03, 0x00, 0x00, 0x7b, 0x31, 0x42, 0x00, 0x6e, 0x4e, 0x7d, 0x32, 0x42, 0x03, 0x00, 0x00, -0xf5, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, 0x01, 0x00, 0x3a, 0x3e, 0x35, 0x03, 0x04, -0x2d, 0x5f, 0x00, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, 0x01, 0x00, 0x3c, 0x3e, 0x00, 0x02, 0x02, -0x03, 0x00, 0x00, 0x7e, 0x03, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x06, 0x02, 0x03, 0x00, 0x00, 0xf8, -0x08, 0x02, 0x07, 0x00, 0x00, 0xca, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xcb, 0x0c, 0x02, 0x07, 0x00, -0x00, 0xcc, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xcd, 0x1a, 0x41, 0x00, 0xa4, 0xa5, 0x1b, 0x42, 0x04, -0x9b, 0x9d, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x27, 0x41, 0x00, 0x91, 0x92, 0x28, 0x41, 0x00, -0x86, 0x8f, 0x29, 0x01, 0x03, 0xcd, 0xcc, 0x2b, 0x42, 0x04, 0xa6, 0xa7, 0xa0, 0x32, 0x42, 0x03, -0x00, 0x00, 0x15, 0x00, 0x76, 0x07, 0x63, 0x91, 0x73, 0xa4, 0x7a, 0xa6, 0x43, 0x92, 0x53, 0xa5, -0x5a, 0xa7, 0x20, 0x76, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x20, 0x5e, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, -0x27, 0x09, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x43, 0x8f, -0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, -0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x2c, 0x03, 0x63, 0x87, 0x43, 0x80, -0x20, 0x2c, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x03, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x05, -0x02, 0x07, 0x00, 0x00, 0xca, 0x06, 0x02, 0x07, 0x00, 0x00, 0xcb, 0x07, 0x02, 0x07, 0x00, 0x00, -0xcc, 0x08, 0x02, 0x03, 0x00, 0x00, 0x60, 0x09, 0x02, 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x02, 0x07, -0x00, 0x00, 0xce, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xcf, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xd0, 0x0d, -0x02, 0x07, 0x00, 0x00, 0xd1, 0x12, 0x42, 0x03, 0x00, 0x00, 0xaa, 0x13, 0x41, 0x00, 0x72, 0x52, -0x14, 0x41, 0x00, 0x74, 0x54, 0x1a, 0x41, 0x00, 0xe7, 0xe6, 0x1b, 0x41, 0x00, 0xd0, 0xd1, 0x1f, -0x41, 0x00, 0x73, 0x53, 0x20, 0x41, 0x00, 0x64, 0x44, 0x25, 0x42, 0x03, 0x00, 0x00, 0x88, 0x26, -0x42, 0x00, 0x6c, 0x4c, 0x9d, 0x27, 0x41, 0x00, 0x9f, 0xac, 0x28, 0x41, 0x00, 0x86, 0x8f, 0x29, -0x01, 0x03, 0xd1, 0xd0, 0x2b, 0x41, 0x00, 0xa7, 0xa6, 0x00, 0xf3, 0x13, 0x63, 0x9f, 0x64, 0xd4, -0x65, 0xd8, 0x6c, 0x96, 0x6e, 0xe5, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa7, 0x43, 0xac, -0x44, 0xd2, 0x45, 0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, 0xa6, -0x20, 0xf3, 0x5e, 0x07, 0x61, 0x83, 0x69, 0x8c, 0x6f, 0x93, 0x41, 0xb6, 0x49, 0xd7, 0x4f, 0xe2, -0x20, 0x5e, 0xf4, 0x03, 0x61, 0xc7, 0x41, 0xc6, 0x20, 0xf4, 0xf8, 0x03, 0x75, 0x85, 0x55, 0xde, -0x20, 0xf8, 0xf2, 0x05, 0x61, 0xa5, 0x65, 0xa9, 0x41, 0xa4, 0x45, 0xa8, 0x20, 0xf2, 0xfa, 0x03, -0x7a, 0xbe, 0x5a, 0xbd, 0x20, 0xfa, 0xef, 0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, 0xa1, -0x6c, 0x92, 0x6e, 0xe4, 0x6f, 0xa2, 0x72, 0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, 0xab, -0x41, 0xb5, 0x43, 0x8f, 0x45, 0x90, 0x49, 0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, 0xe8, -0x53, 0x97, 0x55, 0xe9, 0x59, 0xed, 0x5a, 0x8d, 0x20, 0xef, 0xf1, 0x05, 0x6f, 0x8b, 0x75, 0xfb, -0x4f, 0x8a, 0x55, 0xeb, 0x20, 0xf1, 0xf9, 0x09, 0x61, 0x84, 0x65, 0x89, 0x6f, 0x94, 0x75, 0x81, -0x41, 0x8e, 0x45, 0xd3, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf7, 0x07, 0x63, 0x87, 0x73, 0xad, -0x74, 0xee, 0x43, 0x80, 0x53, 0xb8, 0x54, 0xdd, 0x20, 0xf7, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, -0xd5, 0x00, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, -0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, -0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf8, 0x03, 0x61, 0x86, 0x41, 0x8f, -0x20, 0xf8, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, -0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, -0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, -0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, -0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, -0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, 0x00, 0xad, 0x00, 0x00 }; - -Bit8u layout_keybrd2sys[25431] = { -0x4b, 0x43, 0x46, 0x00, 0x01, 0x01, 0x2e, 0x48, 0x65, 0x6e, 0x72, 0x69, 0x71, 0x75, 0x65, 0x20, -0x50, 0x65, 0x72, 0x6f, 0x6e, 0xff, 0x44, 0x4f, 0x53, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x70, 0x61, -0x67, 0x65, 0x73, 0x20, 0x2d, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x23, 0x32, -0x20, 0x6f, 0x66, 0x20, 0x33, 0xaa, 0x02, 0x09, 0x00, 0x00, 0x42, 0x47, 0x2c, 0xba, 0x01, 0x42, -0x47, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0x99, -0x01, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0x97, -0x02, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0xae, 0x01, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xa7, -0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, -0x23, 0x05, 0x02, 0x03, 0x00, 0x00, 0xcf, 0x07, 0x02, 0x03, 0x00, 0x00, 0x5e, 0x08, 0x02, 0x03, -0x00, 0x00, 0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x24, 0x1a, 0x02, 0x03, 0x00, 0x00, 0x5b, 0x1b, -0x02, 0x03, 0x00, 0x00, 0x5d, 0x2b, 0x02, 0x03, 0x00, 0x00, 0x7c, 0x33, 0x02, 0x03, 0x00, 0x00, -0x3c, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x03, -0x01, 0x01, 0x00, 0x3f, 0x04, 0x01, 0x01, 0x00, 0x2b, 0x05, 0x02, 0x05, 0x00, 0x22, 0xa0, 0x07, -0x01, 0x01, 0x00, 0x3d, 0x08, 0x01, 0x01, 0x00, 0x3a, 0x09, 0x01, 0x01, 0x00, 0x2f, 0x0a, 0x03, -0x05, 0x00, 0x5f, 0x00, 0x1f, 0x0b, 0x01, 0x01, 0x00, 0xef, 0x0c, 0x01, 0x01, 0x00, 0x49, 0x0d, -0x01, 0x00, 0x2e, 0x56, 0x10, 0x01, 0x00, 0x2c, 0xf2, 0x11, 0x41, 0x00, 0xe7, 0xe8, 0x12, 0x42, -0x00, 0xa8, 0xa9, 0xcf, 0x13, 0x41, 0x00, 0xb7, 0xb8, 0x14, 0x41, 0x00, 0xf5, 0xf6, 0x15, 0x41, -0x00, 0xf9, 0xfa, 0x16, 0x41, 0x00, 0xc6, 0xc7, 0x17, 0x41, 0x00, 0xe3, 0xe4, 0x18, 0x41, 0x00, -0xa6, 0xa7, 0x19, 0x41, 0x00, 0xf3, 0xf4, 0x1a, 0x41, 0x00, 0xa4, 0xa5, 0x1b, 0x01, 0x00, 0x3b, -0xfd, 0x1e, 0x41, 0x00, 0xed, 0xee, 0x1f, 0xc1, 0x00, 0xde, 0x1f, 0xe0, 0x00, 0x20, 0x41, 0x00, -0xa0, 0xa1, 0x21, 0x41, 0x00, 0xd6, 0xd7, 0x22, 0x41, 0x00, 0xe9, 0xea, 0x23, 0x41, 0x00, 0xac, -0xad, 0x24, 0x41, 0x00, 0xe5, 0xe6, 0x25, 0x41, 0x00, 0xd4, 0xd5, 0x26, 0x41, 0x00, 0xeb, 0xec, -0x27, 0x41, 0x00, 0xd2, 0xd3, 0x28, 0x41, 0x00, 0xfb, 0xfc, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x78, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0x9c, 0x9d, 0x2d, 0x41, 0x00, 0xbd, -0xbe, 0x2e, 0x41, 0x00, 0x9e, 0x9f, 0x2f, 0x41, 0x00, 0xf7, 0xf8, 0x30, 0x41, 0x00, 0xaa, 0xab, -0x31, 0x41, 0x00, 0xb5, 0xb6, 0x32, 0x41, 0x00, 0xd8, 0xdd, 0x33, 0x41, 0x00, 0xe1, 0xe2, 0x34, -0x41, 0x00, 0xd0, 0xd1, 0x35, 0x41, 0x00, 0xa2, 0xa3, 0x00, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x12, 0x42, 0x03, 0x00, 0x00, 0xcf, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x03, -0x01, 0x01, 0x00, 0x3f, 0x04, 0x01, 0x01, 0x00, 0x2b, 0x05, 0x01, 0x01, 0x00, 0x22, 0x07, 0x01, -0x01, 0x00, 0x3d, 0x08, 0x01, 0x01, 0x00, 0x3a, 0x09, 0x01, 0x01, 0x00, 0x2f, 0x0a, 0x03, 0x05, -0x00, 0x5f, 0x00, 0x1f, 0x0b, 0x01, 0x01, 0x00, 0xef, 0x0c, 0x01, 0x01, 0x00, 0x49, 0x0d, 0x01, -0x00, 0x2e, 0x56, 0x10, 0x01, 0x00, 0x2c, 0xf2, 0x11, 0x41, 0x00, 0xe7, 0xe8, 0x12, 0x41, 0x00, -0xa8, 0xa9, 0x13, 0x41, 0x00, 0xb7, 0xb8, 0x14, 0x41, 0x00, 0xf5, 0xf6, 0x15, 0x41, 0x00, 0xf9, -0xfa, 0x16, 0x41, 0x00, 0xc6, 0xc7, 0x17, 0x41, 0x00, 0xe3, 0xe4, 0x18, 0x41, 0x00, 0xa6, 0xa7, -0x19, 0x41, 0x00, 0xf3, 0xf4, 0x1a, 0x41, 0x00, 0xa4, 0xa5, 0x1b, 0x01, 0x00, 0x3b, 0xfd, 0x1e, -0x41, 0x00, 0xed, 0xee, 0x1f, 0xc1, 0x00, 0xde, 0x1f, 0xe0, 0x00, 0x20, 0x41, 0x00, 0xa0, 0xa1, -0x21, 0x41, 0x00, 0xd6, 0xd7, 0x22, 0x41, 0x00, 0xe9, 0xea, 0x23, 0x41, 0x00, 0xac, 0xad, 0x24, -0x41, 0x00, 0xe5, 0xe6, 0x25, 0x41, 0x00, 0xd4, 0xd5, 0x26, 0x41, 0x00, 0xeb, 0xec, 0x27, 0x41, -0x00, 0xd2, 0xd3, 0x28, 0x41, 0x00, 0xfb, 0xfc, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, -0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0x9c, 0x9d, 0x2d, 0x41, 0x00, 0xbd, 0xbe, 0x2e, -0x41, 0x00, 0x9e, 0x9f, 0x2f, 0x41, 0x00, 0xf7, 0xf8, 0x30, 0x41, 0x00, 0xaa, 0xab, 0x31, 0x41, -0x00, 0xb5, 0xb6, 0x32, 0x41, 0x00, 0xd8, 0xdd, 0x33, 0x41, 0x00, 0xe1, 0xe2, 0x34, 0x41, 0x00, -0xd0, 0xd1, 0x35, 0x41, 0x00, 0xa2, 0xa3, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, -0x00, 0x24, 0x72, 0x06, 0x04, 0xf1, 0x00, 0x42, 0x47, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0x61, 0x04, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0x78, -0x02, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0x63, 0x06, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0x7e, -0x04, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0x68, 0x02, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, -0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x21, 0x31, 0x03, 0x01, 0x00, 0x22, 0x32, 0x04, -0x01, 0x00, 0x23, 0x33, 0x05, 0x01, 0x00, 0xcf, 0x34, 0x06, 0x01, 0x00, 0x25, 0x35, 0x07, 0x01, -0x00, 0x26, 0x36, 0x08, 0x01, 0x00, 0x27, 0x37, 0x09, 0x01, 0x00, 0x28, 0x38, 0x0a, 0x01, 0x00, -0x29, 0x39, 0x0b, 0x01, 0x00, 0x24, 0x30, 0x0c, 0x01, 0x00, 0x3d, 0x2d, 0x0d, 0x02, 0x00, 0x5f, -0x5f, 0x1f, 0x10, 0xc5, 0x00, 0x6a, 0x24, 0x4a, 0x24, 0x0a, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, -0x24, 0x11, 0xc5, 0x00, 0x63, 0x2e, 0x43, 0x2e, 0x03, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x2e, -0x12, 0xc5, 0x00, 0x75, 0x16, 0x55, 0x16, 0x15, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x13, -0xc5, 0x00, 0x6b, 0x25, 0x4b, 0x25, 0x0b, 0x25, 0x00, 0x25, 0x00, 0x25, 0x00, 0x25, 0x14, 0xc5, -0x00, 0x65, 0x12, 0x45, 0x12, 0x05, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x15, 0xc5, 0x00, -0x6e, 0x31, 0x4e, 0x31, 0x0e, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x16, 0xc5, 0x00, 0x67, -0x22, 0x47, 0x22, 0x07, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x17, 0x02, 0x00, 0x5b, 0x5b, -0x1b, 0x18, 0x02, 0x00, 0x5d, 0x5d, 0x1d, 0x19, 0xc5, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x1a, 0x2c, -0x00, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x1a, 0xc5, 0x00, 0x68, 0x23, 0x48, 0x23, 0x08, 0x23, 0x00, -0x23, 0x00, 0x23, 0x00, 0x23, 0x1b, 0x04, 0x04, 0x7d, 0x7b, 0x00, 0x2a, 0x3a, 0x1e, 0xc5, 0x00, -0x66, 0x21, 0x46, 0x21, 0x06, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x1f, 0xc5, 0x00, 0x79, -0x15, 0x59, 0x15, 0x19, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x20, 0xc5, 0x00, 0x77, 0x11, -0x57, 0x11, 0x17, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x21, 0xc5, 0x00, 0x61, 0x1e, 0x41, -0x1e, 0x01, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x22, 0xc5, 0x00, 0x70, 0x19, 0x50, 0x19, -0x10, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x23, 0xc5, 0x00, 0x72, 0x13, 0x52, 0x13, 0x12, -0x13, 0x00, 0x13, 0x00, 0x13, 0x00, 0x13, 0x24, 0xc5, 0x00, 0x6f, 0x18, 0x4f, 0x18, 0x0f, 0x18, -0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x25, 0xc5, 0x00, 0x6c, 0x26, 0x4c, 0x26, 0x0c, 0x26, 0x00, -0x26, 0x00, 0x26, 0x00, 0x26, 0x26, 0xc5, 0x00, 0x64, 0x20, 0x44, 0x20, 0x04, 0x20, 0x00, 0x20, -0x00, 0x20, 0x00, 0x20, 0x27, 0xc5, 0x00, 0x76, 0x2f, 0x56, 0x2f, 0x16, 0x2f, 0x00, 0x2f, 0x00, -0x2f, 0x00, 0x2f, 0x28, 0x02, 0x00, 0x5c, 0x7c, 0x1c, 0x29, 0x01, 0x00, 0x2b, 0x3b, 0x2b, 0x01, -0x00, 0x3e, 0x2e, 0x2c, 0x02, 0x00, 0x40, 0x5e, 0x1e, 0x2d, 0xc5, 0x00, 0x73, 0x1f, 0x53, 0x1f, -0x13, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x2e, 0xc5, 0x00, 0x6d, 0x32, 0x4d, 0x32, 0x0d, -0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x2f, 0xc5, 0x00, 0x69, 0x17, 0x49, 0x17, 0x09, 0x17, -0x00, 0x17, 0x00, 0x17, 0x00, 0x17, 0x30, 0xc5, 0x00, 0x74, 0x14, 0x54, 0x14, 0x14, 0x14, 0x00, -0x14, 0x00, 0x14, 0x00, 0x14, 0x31, 0xc5, 0x00, 0x78, 0x2d, 0x58, 0x2d, 0x18, 0x2d, 0x00, 0x2d, -0x00, 0x2d, 0x00, 0x2d, 0x32, 0xc5, 0x00, 0x62, 0x30, 0x42, 0x30, 0x02, 0x30, 0x00, 0x30, 0x00, -0x30, 0x00, 0x30, 0x33, 0x10, 0x00, 0x00, 0x34, 0x01, 0x00, 0x3c, 0x2c, 0x35, 0x01, 0x00, 0x3f, -0x2f, 0x56, 0xc5, 0x00, 0x71, 0x10, 0x51, 0x10, 0x11, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, -0x00, 0x14, 0xc5, 0x00, 0x65, 0x12, 0x45, 0x12, 0x05, 0x12, 0xd5, 0x12, 0x00, 0x12, 0x00, 0x12, -0x00, 0x05, 0x00, 0x01, 0xa0, 0x0d, 0x43, 0x04, 0x9e, 0x9f, 0x00, 0x5f, 0x10, 0xc5, 0x00, 0xbd, -0x24, 0xbe, 0x24, 0x0a, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 0x24, 0x11, 0xc5, 0x00, 0xa4, 0x2e, -0xa5, 0x2e, 0x03, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x12, 0xc5, 0x00, 0xe7, 0x16, 0xe8, -0x16, 0x15, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x13, 0xc5, 0x00, 0xc6, 0x25, 0xc7, 0x25, -0x0b, 0x25, 0x00, 0x25, 0x00, 0x25, 0x00, 0x25, 0x14, 0xc5, 0x00, 0xa8, 0x12, 0xa9, 0x12, 0x05, -0x12, 0xcf, 0x12, 0x00, 0x12, 0x00, 0x12, 0x15, 0xc5, 0x00, 0xd4, 0x31, 0xd5, 0x31, 0x0e, 0x31, -0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x16, 0xc5, 0x00, 0xac, 0x22, 0xad, 0x22, 0x07, 0x22, 0x00, -0x22, 0x00, 0x22, 0x00, 0x22, 0x17, 0x43, 0x04, 0xf5, 0xf6, 0x00, 0x5b, 0x18, 0x43, 0x04, 0xf9, -0xfa, 0x00, 0x5d, 0x19, 0xc5, 0x00, 0xf3, 0x2c, 0xf4, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x00, 0x2c, -0x00, 0x2c, 0x1a, 0xc5, 0x00, 0xb5, 0x23, 0xb6, 0x23, 0x08, 0x23, 0x00, 0x23, 0x00, 0x23, 0x00, -0x23, 0x1b, 0x04, 0x04, 0x2a, 0x3a, 0x00, 0x7d, 0x7b, 0x1e, 0xc5, 0x00, 0xaa, 0x21, 0xab, 0x21, -0x06, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x1f, 0xc5, 0x00, 0xf1, 0x15, 0xf2, 0x15, 0x19, -0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x20, 0xc5, 0x00, 0xeb, 0x11, 0xec, 0x11, 0x17, 0x11, -0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x21, 0xc5, 0x00, 0xa0, 0x1e, 0xa1, 0x1e, 0x01, 0x1e, 0x00, -0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x22, 0xc5, 0x00, 0xd8, 0x19, 0xdd, 0x19, 0x10, 0x19, 0x00, 0x19, -0x00, 0x19, 0x00, 0x19, 0x23, 0xc5, 0x00, 0xe1, 0x13, 0xe2, 0x13, 0x12, 0x13, 0x00, 0x13, 0x00, -0x13, 0x00, 0x13, 0x24, 0xc5, 0x00, 0xd6, 0x18, 0xd7, 0x18, 0x0f, 0x18, 0x00, 0x18, 0x00, 0x18, -0x00, 0x18, 0x25, 0xc5, 0x00, 0xd0, 0x26, 0xd1, 0x26, 0x0c, 0x26, 0x00, 0x26, 0x00, 0x26, 0x00, -0x26, 0x26, 0xc5, 0x00, 0xa6, 0x20, 0xa7, 0x20, 0x04, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, -0x27, 0xc5, 0x00, 0xe9, 0x2f, 0xea, 0x2f, 0x16, 0x2f, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x2f, 0x28, -0x44, 0x04, 0xf7, 0xf8, 0x00, 0x5c, 0x7c, 0x29, 0x04, 0x07, 0x00, 0x00, 0x00, 0x98, 0x99, 0x2a, -0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x04, 0x07, 0x00, 0x00, 0x00, 0x84, 0x85, -0x2c, 0x44, 0x04, 0xfb, 0xfc, 0x00, 0x40, 0x5e, 0x2d, 0xc5, 0x00, 0xe3, 0x1f, 0xe4, 0x1f, 0x13, -0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x2e, 0xc5, 0x00, 0xd2, 0x32, 0xd3, 0x32, 0x0d, 0x32, -0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x2f, 0xc5, 0x00, 0xb7, 0x17, 0xb8, 0x17, 0x09, 0x17, 0x00, -0x17, 0x00, 0x17, 0x00, 0x17, 0x30, 0xc5, 0x00, 0xe5, 0x14, 0xe6, 0x14, 0x14, 0x14, 0x00, 0x14, -0x00, 0x14, 0x00, 0x14, 0x31, 0xc5, 0x00, 0xed, 0x2d, 0xee, 0x2d, 0x18, 0x2d, 0x00, 0x2d, 0x00, -0x2d, 0x00, 0x2d, 0x32, 0xc5, 0x00, 0xa2, 0x30, 0xa3, 0x30, 0x02, 0x30, 0x00, 0x30, 0x00, 0x30, -0x00, 0x30, 0x33, 0x44, 0x04, 0x9c, 0x9d, 0x00, 0x86, 0x87, 0x34, 0x04, 0x07, 0x00, 0x00, 0x00, -0x8a, 0x8b, 0x35, 0x04, 0x07, 0x00, 0x00, 0x00, 0x8c, 0x8d, 0x56, 0xc5, 0x00, 0xde, 0x10, 0xe0, -0x00, 0x11, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x05, 0x00, 0x01, 0xa0, 0x14, 0xc5, -0x00, 0x65, 0x12, 0x45, 0x12, 0x05, 0x12, 0xcf, 0x12, 0x00, 0x12, 0x00, 0x12, 0x36, 0x05, 0x3f, -0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x0d, 0x43, 0x04, 0x9e, 0x9f, 0x00, 0x5f, 0x10, 0xc5, -0x00, 0xbd, 0x24, 0xbe, 0x24, 0x0a, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 0x24, 0x11, 0xc5, 0x00, -0xa4, 0x2e, 0xa5, 0x2e, 0x03, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x2e, 0x12, 0xc5, 0x00, 0xe7, -0x16, 0xe8, 0x16, 0x15, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x13, 0xc5, 0x00, 0xc6, 0x25, -0xc7, 0x25, 0x0b, 0x25, 0x00, 0x25, 0x00, 0x25, 0x00, 0x25, 0x14, 0xc5, 0x00, 0xa8, 0x12, 0xa9, -0x12, 0x05, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x15, 0xc5, 0x00, 0xd4, 0x31, 0xd5, 0x31, -0x0e, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x16, 0xc5, 0x00, 0xac, 0x22, 0xad, 0x22, 0x07, -0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x17, 0x43, 0x04, 0xf5, 0xf6, 0x00, 0x5b, 0x18, 0x43, -0x04, 0xf9, 0xfa, 0x00, 0x5d, 0x19, 0xc5, 0x00, 0xf3, 0x2c, 0xf4, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, -0x00, 0x2c, 0x00, 0x2c, 0x1a, 0xc5, 0x00, 0xb5, 0x23, 0xb6, 0x23, 0x08, 0x23, 0x00, 0x23, 0x00, -0x23, 0x00, 0x23, 0x1b, 0x04, 0x04, 0x2a, 0x3a, 0x00, 0x7d, 0x7b, 0x1e, 0xc5, 0x00, 0xaa, 0x21, -0xab, 0x21, 0x06, 0x21, 0x00, 0x21, 0x00, 0x21, 0x00, 0x21, 0x1f, 0xc5, 0x00, 0xf1, 0x15, 0xf2, -0x15, 0x19, 0x15, 0x00, 0x15, 0x00, 0x15, 0x00, 0x15, 0x20, 0xc5, 0x00, 0xeb, 0x11, 0xec, 0x11, -0x17, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x21, 0xc5, 0x00, 0xa0, 0x1e, 0xa1, 0x1e, 0x01, -0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x22, 0xc5, 0x00, 0xd8, 0x19, 0xdd, 0x19, 0x10, 0x19, -0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x23, 0xc5, 0x00, 0xe1, 0x13, 0xe2, 0x13, 0x12, 0x13, 0x00, -0x13, 0x00, 0x13, 0x00, 0x13, 0x24, 0xc5, 0x00, 0xd6, 0x18, 0xd7, 0x18, 0x0f, 0x18, 0x00, 0x18, -0x00, 0x18, 0x00, 0x18, 0x25, 0xc5, 0x00, 0xd0, 0x26, 0xd1, 0x26, 0x0c, 0x26, 0x00, 0x26, 0x00, -0x26, 0x00, 0x26, 0x26, 0xc5, 0x00, 0xa6, 0x20, 0xa7, 0x20, 0x04, 0x20, 0x00, 0x20, 0x00, 0x20, -0x00, 0x20, 0x27, 0xc5, 0x00, 0xe9, 0x2f, 0xea, 0x2f, 0x16, 0x2f, 0x00, 0x2f, 0x00, 0x2f, 0x00, -0x2f, 0x28, 0x44, 0x04, 0xf7, 0xf8, 0x00, 0x5c, 0x7c, 0x29, 0x04, 0x07, 0x00, 0x00, 0x00, 0x98, -0x99, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x04, 0x07, 0x00, 0x00, 0x00, -0x84, 0x85, 0x2c, 0x44, 0x04, 0xfb, 0xfc, 0x00, 0x40, 0x5e, 0x2d, 0xc5, 0x00, 0xe3, 0x1f, 0xe4, -0x1f, 0x13, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x2e, 0xc5, 0x00, 0xd2, 0x32, 0xd3, 0x32, -0x0d, 0x32, 0x00, 0x32, 0x00, 0x32, 0x00, 0x32, 0x2f, 0xc5, 0x00, 0xb7, 0x17, 0xb8, 0x17, 0x09, -0x17, 0x00, 0x17, 0x00, 0x17, 0x00, 0x17, 0x30, 0xc5, 0x00, 0xe5, 0x14, 0xe6, 0x14, 0x14, 0x14, -0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x31, 0xc5, 0x00, 0xed, 0x2d, 0xee, 0x2d, 0x18, 0x2d, 0x00, -0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x32, 0xc5, 0x00, 0xa2, 0x30, 0xa3, 0x30, 0x02, 0x30, 0x00, 0x30, -0x00, 0x30, 0x00, 0x30, 0x33, 0x44, 0x04, 0x9c, 0x9d, 0x00, 0x86, 0x87, 0x34, 0x04, 0x07, 0x00, -0x00, 0x00, 0x8a, 0x8b, 0x35, 0x04, 0x07, 0x00, 0x00, 0x00, 0x8c, 0x8d, 0x56, 0xc5, 0x00, 0xde, -0x10, 0xe0, 0x00, 0x11, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x36, 0x05, 0x3f, 0x00, -0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x12, 0xe7, 0x02, 0x09, 0x00, 0x00, 0x43, 0x45, 0x2c, 0xb9, -0x01, 0x43, 0x45, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, -0x75, 0x72, 0x01, 0xe2, 0x01, 0x00, 0x00, 0x43, 0x75, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, -0x75, 0xce, 0x02, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x75, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, -0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0x40, 0x04, 0x02, 0x03, -0x00, 0x00, 0x23, 0x07, 0x02, 0x03, 0x00, 0x00, 0x5e, 0x08, 0x02, 0x03, 0x00, 0x00, 0x26, 0x09, -0x02, 0x03, 0x00, 0x00, 0x24, 0x0d, 0x02, 0x03, 0x00, 0x00, 0x3d, 0x1a, 0x02, 0x03, 0x00, 0x00, -0x5b, 0x1b, 0x02, 0x03, 0x00, 0x00, 0x5d, 0x2b, 0x02, 0x03, 0x00, 0x00, 0x7c, 0x33, 0x02, 0x03, -0x00, 0x00, 0x3c, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, -0x01, 0x01, 0x00, 0xfc, 0x05, 0x01, 0x01, 0x00, 0x3b, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, -0x01, 0x00, 0x3f, 0x0d, 0x01, 0x00, 0xfe, 0x2b, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, -0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, -0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, -0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, -0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, -0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, -0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, -0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0xc1, -0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x01, 0x01, -0x00, 0x2f, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, -0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, -0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, -0x01, 0x00, 0x2e, 0x2c, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x10, 0x43, 0x03, 0x00, 0x00, -0xd6, 0xd5, 0x12, 0x43, 0x03, 0x00, 0x00, 0xbe, 0xbd, 0x16, 0x41, 0x00, 0x75, 0x55, 0x18, 0x43, -0x00, 0x6f, 0x4f, 0xde, 0xdd, 0x1a, 0x43, 0x00, 0xf9, 0xf8, 0x5b, 0x7b, 0x1b, 0x43, 0x00, 0xd2, -0xd1, 0x5d, 0x7d, 0x1e, 0x43, 0x00, 0x61, 0x41, 0xc7, 0xc6, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xfb, -0xfa, 0x22, 0x43, 0x03, 0x00, 0x00, 0xb6, 0xb5, 0x29, 0x00, 0x01, 0xc8, 0x2c, 0x43, 0x03, 0x00, -0x00, 0xd8, 0xd7, 0x2d, 0x43, 0x03, 0x00, 0x00, 0xd4, 0xd3, 0x2e, 0x43, 0x03, 0x00, 0x00, 0xd0, -0xcf, 0x31, 0x43, 0x03, 0x00, 0x00, 0xb8, 0xb7, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, -0x39, 0x00, 0x00, 0x20, 0x00, 0x60, 0x07, 0x61, 0xf3, 0x6f, 0xf5, 0x75, 0xf7, 0x41, 0xf2, 0x4f, -0xf4, 0x55, 0xf6, 0x20, 0x60, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xfc, -0x05, 0x01, 0x01, 0x00, 0x3b, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x0d, -0x01, 0x00, 0xfe, 0x2b, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, -0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, -0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, -0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, -0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, -0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, -0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, -0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, -0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, -0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, -0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, -0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, 0x2e, 0x2c, -0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, -0xc2, 0x19, 0x03, 0x04, 0xbb, 0x01, 0x43, 0x45, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, -0x00, 0x00, 0x00, 0x00, 0x43, 0x75, 0x8a, 0x01, 0xfa, 0x01, 0x00, 0x00, 0x43, 0x75, 0x91, 0x00, -0x00, 0x00, 0x00, 0x00, 0x3b, 0x75, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x75, 0x0b, 0x02, -0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x03, 0x00, -0x00, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x23, 0x05, 0x02, 0x03, 0x00, 0x00, 0x24, 0x07, 0x02, -0x03, 0x00, 0x00, 0x5e, 0x08, 0x02, 0x03, 0x00, 0x00, 0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x2a, -0x1a, 0x02, 0x03, 0x00, 0x00, 0x5b, 0x1b, 0x02, 0x03, 0x00, 0x00, 0x5d, 0x33, 0x02, 0x03, 0x00, -0x00, 0x3c, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x00, 0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, -0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, -0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, -0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, -0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, -0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, -0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, -0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, -0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, -0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, -0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, -0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0x01, 0x00, 0x7c, 0x2b, -0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, -0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, -0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, -0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, -0x00, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x10, 0x43, 0x03, 0x00, 0x00, 0xd6, 0xd5, 0x12, -0x43, 0x03, 0x00, 0x00, 0xbe, 0xbd, 0x16, 0x41, 0x00, 0x75, 0x55, 0x18, 0x43, 0x00, 0x6f, 0x4f, -0xde, 0xdd, 0x1a, 0x43, 0x00, 0xf9, 0xf8, 0x5b, 0x7b, 0x1b, 0x43, 0x00, 0xd2, 0xd1, 0x5d, 0x7d, -0x1e, 0x43, 0x00, 0x61, 0x41, 0xc7, 0xc6, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xfb, 0xfa, 0x22, 0x43, -0x03, 0x00, 0x00, 0xb6, 0xb5, 0x29, 0x00, 0x01, 0xc8, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xd8, 0xd7, -0x2d, 0x43, 0x03, 0x00, 0x00, 0xd4, 0xd3, 0x2e, 0x43, 0x03, 0x00, 0x00, 0xd0, 0xcf, 0x31, 0x43, -0x03, 0x00, 0x00, 0xb8, 0xb7, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x39, 0x00, 0x00, -0x20, 0x00, 0x60, 0x07, 0x61, 0xf3, 0x6f, 0xf5, 0x75, 0xf7, 0x41, 0xf2, 0x4f, 0xf4, 0x55, 0xf6, -0x20, 0x60, 0x00, 0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, -0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, -0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, -0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, -0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, -0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, -0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, -0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, -0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, -0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, -0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, -0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0x02, 0x00, 0xfe, 0x2b, 0x7c, 0x2a, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x7a, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, -0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, -0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, -0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x00, 0x12, 0x42, 0x03, -0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0xc8, 0x58, 0x04, 0x13, -0x00, 0x00, 0x47, 0x4b, 0x2c, 0x00, 0x00, 0x45, 0x4c, 0x2c, 0x3f, 0x01, 0x47, 0x4b, 0x2c, 0x3f, -0x01, 0x45, 0x4c, 0x09, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, -0x03, 0x3a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x65, 0x03, 0x79, 0x01, 0x49, 0x02, 0x00, 0x00, 0xe1, -0x02, 0x24, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x02, 0x7e, 0x02, 0x2d, 0x03, 0x00, 0x00, 0x53, -0x03, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x53, 0x03, 0x5a, 0x03, 0x13, 0x04, 0x00, 0x00, 0x5a, -0x03, 0xf7, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x07, 0x01, 0x01, 0x00, -0x26, 0x08, 0x01, 0x01, 0x00, 0x2f, 0x09, 0x01, 0x01, 0x00, 0x28, 0x0a, 0x01, 0x01, 0x00, 0x29, -0x0b, 0x01, 0x01, 0x00, 0x3d, 0x0c, 0x01, 0x00, 0x27, 0x3f, 0x0d, 0x01, 0x00, 0x2b, 0x2a, 0x12, -0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, -0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x01, 0x03, -0xcb, 0xcc, 0x28, 0x01, 0x03, 0xca, 0xc9, 0x29, 0x03, 0x04, 0x5c, 0x7c, 0x00, 0x1c, 0x2b, 0x01, -0x01, 0xc8, 0x40, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x33, 0x02, 0x00, -0x2c, 0x3b, 0x3c, 0x34, 0x02, 0x00, 0x2e, 0x3a, 0x3e, 0x35, 0x03, 0x04, 0x2d, 0x5f, 0x00, 0x1f, -0x39, 0x00, 0x00, 0x20, 0x56, 0x01, 0x00, 0x3c, 0x3e, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, -0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, -0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, -0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, -0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, -0x5e, 0xef, 0x0f, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, -0xec, 0x41, 0xb5, 0x43, 0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, -0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, -0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0x04, 0x01, 0x01, 0x00, -0x9c, 0x07, 0x01, 0x01, 0x00, 0x89, 0x0c, 0x01, 0x01, 0x00, 0xf8, 0x10, 0x01, 0x00, 0x88, 0x8e, -0x11, 0x01, 0x00, 0xed, 0x8a, 0x12, 0x42, 0x00, 0xde, 0xa8, 0x87, 0x13, 0x41, 0x00, 0xeb, 0xc7, -0x14, 0x41, 0x00, 0xee, 0xd0, 0x15, 0x41, 0x00, 0xf2, 0xd1, 0x16, 0x41, 0x00, 0xe2, 0xac, 0x17, -0x41, 0x00, 0xe3, 0xad, 0x18, 0x41, 0x00, 0xe9, 0xbe, 0x19, 0x41, 0x00, 0xea, 0xc6, 0x1a, 0x01, -0x01, 0x00, 0xae, 0x1b, 0x01, 0x01, 0x00, 0xaf, 0x1e, 0x41, 0x00, 0xd6, 0xa4, 0x1f, 0x41, 0x00, -0xec, 0xcf, 0x20, 0x41, 0x00, 0xdd, 0xa7, 0x21, 0x41, 0x00, 0xf3, 0xd2, 0x22, 0x41, 0x00, 0xd8, -0xa6, 0x23, 0x41, 0x00, 0xe1, 0xaa, 0x24, 0x41, 0x00, 0xe8, 0xbd, 0x25, 0x41, 0x00, 0xe4, 0xb5, -0x26, 0x41, 0x00, 0xe5, 0xb6, 0x27, 0x02, 0x07, 0xc8, 0xc9, 0xca, 0x28, 0x01, 0x00, 0x8c, 0x8b, -0x29, 0x01, 0x00, 0xab, 0xf1, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x01, 0x00, -0x99, 0x9a, 0x2c, 0xc1, 0x00, 0xe0, 0x00, 0xa9, 0x2c, 0x2d, 0x41, 0x00, 0xf4, 0xd3, 0x2e, 0x41, -0x00, 0xf6, 0xd4, 0x2f, 0x41, 0x00, 0xfa, 0xd5, 0x30, 0x41, 0x00, 0xd7, 0xa5, 0x31, 0x41, 0x00, -0xe7, 0xb8, 0x32, 0x41, 0x00, 0xe6, 0xb7, 0x56, 0x01, 0x00, 0xf5, 0x97, 0x00, 0x12, 0x42, 0x03, -0x00, 0x00, 0x87, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0xef, 0x0f, 0xd6, 0x9b, -0xde, 0x9d, 0xe1, 0x9e, 0xe3, 0x9f, 0xe9, 0xa2, 0xf2, 0xa3, 0xfa, 0xfd, 0xa4, 0x86, 0xa8, 0x8d, -0xaa, 0x8f, 0xad, 0x90, 0xbe, 0x92, 0xd1, 0x95, 0xd5, 0x98, 0x20, 0xef, 0xf9, 0x05, 0xe3, 0xa0, -0xf2, 0xfb, 0xad, 0x91, 0xd1, 0x96, 0x20, 0xf9, 0xf7, 0x03, 0xe3, 0xa1, 0xf2, 0xfc, 0x20, 0xf7, -0x00, 0x0c, 0x01, 0x01, 0x00, 0xf8, 0x10, 0x01, 0x00, 0xf9, 0x51, 0x11, 0x01, 0x00, 0xaa, 0x57, -0x12, 0x41, 0x00, 0x9c, 0x84, 0x13, 0x41, 0x00, 0xa8, 0x90, 0x14, 0x41, 0x00, 0xab, 0x92, 0x15, -0x41, 0x00, 0xac, 0x93, 0x16, 0x41, 0x00, 0x9f, 0x87, 0x17, 0x41, 0x00, 0xa0, 0x88, 0x18, 0x41, -0x00, 0xa6, 0x8e, 0x19, 0x41, 0x00, 0xa7, 0x8f, 0x1e, 0x41, 0x00, 0x98, 0x80, 0x1f, 0x41, 0x00, -0xa9, 0x91, 0x20, 0x41, 0x00, 0x9b, 0x83, 0x21, 0x41, 0x00, 0xad, 0x94, 0x22, 0x41, 0x00, 0x9a, -0x82, 0x23, 0x41, 0x00, 0x9e, 0x86, 0x24, 0x41, 0x00, 0xa5, 0x8d, 0x25, 0x41, 0x00, 0xa1, 0x89, -0x26, 0x41, 0x00, 0xa2, 0x8a, 0x27, 0x01, 0x03, 0xc8, 0xc9, 0x29, 0x01, 0x00, 0x60, 0xf1, 0x2a, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x01, 0x00, 0xfd, 0x7c, 0x2c, 0x41, 0x00, 0x9d, -0x85, 0x2d, 0x41, 0x00, 0xae, 0x95, 0x2e, 0x41, 0x00, 0xaf, 0x96, 0x2f, 0xc1, 0x00, 0xe0, 0x00, -0x97, 0x2f, 0x30, 0x41, 0x00, 0x99, 0x81, 0x31, 0x41, 0x00, 0xa4, 0x8c, 0x32, 0x41, 0x00, 0xa3, -0x8b, 0x56, 0x01, 0x00, 0x15, 0x7c, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, -0x27, 0x0f, 0x98, 0xe1, 0x9c, 0xe2, 0x9e, 0xe3, 0xa0, 0xe5, 0xa6, 0xe6, 0xac, 0xe7, 0xe0, 0xe9, -0x80, 0xea, 0x84, 0xeb, 0x86, 0xec, 0x88, 0xed, 0x8e, 0xee, 0x93, 0xef, 0x97, 0xf0, 0x20, 0x27, -0x22, 0x05, 0xa0, 0xe4, 0xac, 0xe8, 0x88, 0xf4, 0x93, 0xf5, 0x20, 0x22, 0x00, 0x0c, 0x01, 0x01, -0x00, 0xf8, 0x10, 0x10, 0x00, 0x00, 0x11, 0x01, 0x00, 0xed, 0x7c, 0x12, 0x41, 0x00, 0xde, 0xa8, -0x13, 0x41, 0x00, 0xeb, 0xc7, 0x14, 0x41, 0x00, 0xee, 0xd0, 0x15, 0x41, 0x00, 0xf2, 0xd1, 0x16, -0x41, 0x00, 0xe2, 0xac, 0x17, 0x41, 0x00, 0xe3, 0xad, 0x18, 0x41, 0x00, 0xe9, 0xbe, 0x19, 0x41, -0x00, 0xea, 0xc6, 0x1a, 0x01, 0x01, 0x00, 0xae, 0x1b, 0x01, 0x01, 0x00, 0xaf, 0x1e, 0x41, 0x00, -0xd6, 0xa4, 0x1f, 0x41, 0x00, 0xec, 0xcf, 0x20, 0x41, 0x00, 0xdd, 0xa7, 0x21, 0x41, 0x00, 0xf3, -0xd2, 0x22, 0x41, 0x00, 0xd8, 0xa6, 0x23, 0x41, 0x00, 0xe1, 0xaa, 0x24, 0x41, 0x00, 0xe8, 0xbd, -0x25, 0x41, 0x00, 0xe4, 0xb5, 0x26, 0x41, 0x00, 0xe5, 0xb6, 0x27, 0x02, 0x07, 0xc8, 0xc9, 0xca, -0x29, 0x01, 0x00, 0xab, 0xf1, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, 0x01, 0x00, -0x5c, 0x7c, 0x2c, 0xc1, 0x00, 0xe0, 0x00, 0xa9, 0x2c, 0x2d, 0x41, 0x00, 0xf4, 0xd3, 0x2e, 0x41, -0x00, 0xf6, 0xd4, 0x2f, 0x41, 0x00, 0xfa, 0xd5, 0x30, 0x41, 0x00, 0xd7, 0xa5, 0x31, 0x41, 0x00, -0xe7, 0xb8, 0x32, 0x41, 0x00, 0xe6, 0xb7, 0x56, 0x01, 0x00, 0xf5, 0x7c, 0x00, 0x36, 0x04, 0x1f, -0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0xef, 0x0f, 0xd6, 0x9b, 0xde, 0x9d, 0xe1, 0x9e, 0xe3, 0x9f, -0xe9, 0xa2, 0xf2, 0xa3, 0xfa, 0xfd, 0xa4, 0x86, 0xa8, 0x8d, 0xaa, 0x8f, 0xad, 0x90, 0xbe, 0x92, -0xd1, 0x95, 0xd5, 0x98, 0x20, 0xef, 0xf9, 0x03, 0xe3, 0xa0, 0xf2, 0xfb, 0x20, 0xf9, 0x27, 0x03, -0xe3, 0xa1, 0xf2, 0xfc, 0x20, 0x27, 0x00, 0x42, 0xbe, 0x04, 0x09, 0xdc, 0x00, 0x47, 0x4b, 0x2c, -0xdc, 0x00, 0x45, 0x4c, 0x09, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, -0x65, 0x03, 0xdd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x65, 0x03, 0xfb, 0x00, 0x34, 0x02, 0x00, 0x00, -0xe1, 0x02, 0x3a, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x02, 0x69, 0x02, 0x79, 0x03, 0x00, 0x00, -0x53, 0x03, 0x5c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x53, 0x03, 0xa6, 0x03, 0x83, 0x04, 0x00, 0x00, -0x5a, 0x03, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x22, 0xfd, 0x04, 0x02, -0x01, 0x00, 0x7e, 0xfc, 0x05, 0x02, 0x03, 0x00, 0x00, 0x9c, 0x06, 0x02, 0x03, 0x00, 0x00, 0xf5, -0x07, 0x02, 0x01, 0x00, 0x26, 0x14, 0x08, 0x01, 0x01, 0x00, 0x2f, 0x09, 0x02, 0x01, 0x00, 0x28, -0xcf, 0x0a, 0x02, 0x01, 0x00, 0x29, 0xdd, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0xf8, 0x0c, 0x02, 0x00, -0x27, 0x3f, 0xf1, 0x0d, 0x02, 0x00, 0x5d, 0x5b, 0xab, 0x1a, 0x02, 0x00, 0x2b, 0x2a, 0xae, 0x1b, -0x02, 0x00, 0x7d, 0x7b, 0xaf, 0x27, 0x01, 0x00, 0x27, 0x60, 0x28, 0x10, 0x00, 0x00, 0x29, 0x03, -0x04, 0x5c, 0x7c, 0x00, 0x1c, 0x2b, 0x02, 0x00, 0x23, 0x40, 0xaa, 0x33, 0x02, 0x00, 0x2c, 0x3b, -0x3c, 0x34, 0x02, 0x00, 0x2e, 0x3a, 0x3e, 0x35, 0x03, 0x04, 0x2d, 0x5f, 0x00, 0x1f, 0x39, 0x00, -0x00, 0x20, 0x56, 0x01, 0x00, 0x3c, 0x3e, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x03, -0x02, 0x03, 0x00, 0x00, 0x99, 0x04, 0x02, 0x01, 0x00, 0x9c, 0x9a, 0x05, 0x02, 0x03, 0x00, 0x00, -0x9c, 0x06, 0x02, 0x03, 0x00, 0x00, 0xf5, 0x07, 0x02, 0x03, 0x00, 0x00, 0x14, 0x09, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x0a, 0x02, 0x03, 0x00, 0x00, 0x8a, 0x0b, 0x02, 0x03, 0x00, 0x00, 0xf8, 0x0c, -0x02, 0x03, 0x00, 0x00, 0xf1, 0x0d, 0x02, 0x03, 0x00, 0x00, 0xab, 0x10, 0x01, 0x00, 0x3b, 0x3a, -0x11, 0x01, 0x00, 0xed, 0x7e, 0x12, 0x42, 0x00, 0xde, 0xa8, 0x87, 0x13, 0x41, 0x00, 0xeb, 0xc7, -0x14, 0x41, 0x00, 0xee, 0xd0, 0x15, 0x41, 0x00, 0xf2, 0xd1, 0x16, 0x41, 0x00, 0xe2, 0xac, 0x17, -0x41, 0x00, 0xe3, 0xad, 0x18, 0x41, 0x00, 0xe9, 0xbe, 0x19, 0x41, 0x00, 0xea, 0xc6, 0x1e, 0x41, -0x00, 0xd6, 0xa4, 0x1f, 0x41, 0x00, 0xec, 0xcf, 0x20, 0x41, 0x00, 0xdd, 0xa7, 0x21, 0x41, 0x00, -0xf3, 0xd2, 0x22, 0x41, 0x00, 0xd8, 0xa6, 0x23, 0x41, 0x00, 0xe1, 0xaa, 0x24, 0x41, 0x00, 0xe8, -0xbd, 0x25, 0x41, 0x00, 0xe4, 0xb5, 0x26, 0x41, 0x00, 0xe5, 0xb6, 0x27, 0x02, 0x07, 0xc8, 0xc9, -0xca, 0x28, 0x02, 0x07, 0xc9, 0xca, 0xca, 0x29, 0x01, 0x00, 0xab, 0xf1, 0x2a, 0x04, 0x1f, 0x00, -0x00, 0x00, 0x00, 0x78, 0x2b, 0x02, 0x03, 0x00, 0x00, 0x89, 0x2c, 0xc1, 0x00, 0xe0, 0x00, 0xa9, -0x2c, 0x2d, 0x41, 0x00, 0xf4, 0xd3, 0x2e, 0x41, 0x00, 0xf6, 0xd4, 0x2f, 0x42, 0x00, 0xfa, 0xd5, -0x97, 0x30, 0x41, 0x00, 0xd7, 0xa5, 0x31, 0x41, 0x00, 0xe7, 0xb8, 0x32, 0x41, 0x00, 0xe6, 0xb7, -0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0x99, 0x04, 0x02, 0x03, 0x00, 0x00, 0x9a, 0x05, 0x02, 0x03, -0x00, 0x00, 0x9c, 0x06, 0x02, 0x03, 0x00, 0x00, 0xf5, 0x07, 0x02, 0x03, 0x00, 0x00, 0x14, 0x09, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x03, 0x00, 0x00, 0x8a, 0x0b, 0x02, 0x03, 0x00, 0x00, -0xf8, 0x0c, 0x02, 0x03, 0x00, 0x00, 0xf1, 0x0d, 0x02, 0x03, 0x00, 0x00, 0xab, 0x12, 0x42, 0x03, -0x00, 0x00, 0x87, 0x2b, 0x02, 0x03, 0x00, 0x00, 0x89, 0x2f, 0x42, 0x00, 0xfa, 0xd5, 0x97, 0x36, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0xef, 0x0f, 0xd6, 0x9b, 0xde, 0x9d, 0xe1, 0x9e, -0xe3, 0x9f, 0xe9, 0xa2, 0xf2, 0xa3, 0xfa, 0xfd, 0xa4, 0x86, 0xa8, 0x8d, 0xaa, 0x8f, 0xad, 0x90, -0xbe, 0x92, 0xd1, 0x95, 0xd5, 0x98, 0x20, 0xef, 0xf9, 0x05, 0xe3, 0xa0, 0xf2, 0xfb, 0xad, 0x91, -0xd1, 0x96, 0x20, 0xf9, 0xf7, 0x03, 0xe3, 0xa1, 0xf2, 0xfc, 0x20, 0xf7, 0x00, 0x04, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0x15, 0x09, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x10, 0x10, 0x00, 0x00, 0x11, 0x01, 0x00, 0xaa, 0x7e, 0x12, 0x41, 0x00, 0x9c, 0x84, 0x13, -0x41, 0x00, 0xa8, 0x90, 0x14, 0x41, 0x00, 0xab, 0x92, 0x15, 0x41, 0x00, 0xac, 0x93, 0x16, 0x41, -0x00, 0x9f, 0x87, 0x17, 0x41, 0x00, 0xa0, 0x88, 0x18, 0x41, 0x00, 0xa6, 0x8e, 0x19, 0x41, 0x00, -0xa7, 0x8f, 0x1a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x1b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x1e, 0x41, -0x00, 0x98, 0x80, 0x1f, 0x41, 0x00, 0xa9, 0x91, 0x20, 0x41, 0x00, 0x9b, 0x83, 0x21, 0x41, 0x00, -0xad, 0x94, 0x22, 0x41, 0x00, 0x9a, 0x82, 0x23, 0x41, 0x00, 0x9e, 0x86, 0x24, 0x41, 0x00, 0xa5, -0x8d, 0x25, 0x41, 0x00, 0xa1, 0x89, 0x26, 0x41, 0x00, 0xa2, 0x8a, 0x27, 0x01, 0x03, 0xc8, 0xc9, -0x28, 0x01, 0x03, 0xc9, 0xc9, 0x29, 0x01, 0x00, 0x5c, 0xf1, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x7a, 0x2b, 0x02, 0x05, 0x00, 0xf8, 0xa0, 0x2c, 0x41, 0x00, 0x9d, 0x85, 0x2d, 0x41, 0x00, -0xae, 0x95, 0x2e, 0x41, 0x00, 0xaf, 0x96, 0x2f, 0xc1, 0x00, 0xe0, 0x00, 0x97, 0x2f, 0x30, 0x41, -0x00, 0x99, 0x81, 0x31, 0x41, 0x00, 0xa4, 0x8c, 0x32, 0x41, 0x00, 0xa3, 0x8b, 0x00, 0x04, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0x15, -0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x1a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x1b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2b, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x27, 0x0f, 0x98, -0xe1, 0x9c, 0xe2, 0x9e, 0xe3, 0xa0, 0xe5, 0xa6, 0xe6, 0xac, 0xe7, 0xe0, 0xe9, 0x80, 0xea, 0x84, -0xeb, 0x86, 0xec, 0x88, 0xed, 0x8e, 0xee, 0x93, 0xef, 0x97, 0xf0, 0x20, 0x27, 0x22, 0x05, 0xa0, -0xe4, 0xac, 0xe8, 0x88, 0xf4, 0x93, 0xf5, 0x20, 0x22, 0x00, 0x03, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x10, 0x10, 0x00, 0x00, 0x11, 0x01, 0x02, 0xed, 0xa0, 0x12, 0x41, 0x00, 0xde, 0xa8, -0x13, 0x41, 0x00, 0xeb, 0xc7, 0x14, 0x41, 0x00, 0xee, 0xd0, 0x15, 0x41, 0x00, 0xf2, 0xd1, 0x16, -0x41, 0x00, 0xe2, 0xac, 0x17, 0x41, 0x00, 0xe3, 0xad, 0x18, 0x41, 0x00, 0xe9, 0xbe, 0x19, 0x41, -0x00, 0xea, 0xc6, 0x1e, 0x41, 0x00, 0xd6, 0xa4, 0x1f, 0x41, 0x00, 0xec, 0xcf, 0x20, 0x41, 0x00, -0xdd, 0xa7, 0x21, 0x41, 0x00, 0xf3, 0xd2, 0x22, 0x41, 0x00, 0xd8, 0xa6, 0x23, 0x41, 0x00, 0xe1, -0xaa, 0x24, 0x41, 0x00, 0xe8, 0xbd, 0x25, 0x41, 0x00, 0xe4, 0xb5, 0x26, 0x41, 0x00, 0xe5, 0xb6, -0x27, 0x02, 0x07, 0xc8, 0xc9, 0xca, 0x28, 0x02, 0x07, 0xc9, 0xca, 0xca, 0x2a, 0x04, 0x1f, 0x00, -0x00, 0x00, 0x00, 0x7c, 0x2b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2c, 0xc1, 0x00, 0xe0, 0x00, 0xa9, -0x2c, 0x2d, 0x41, 0x00, 0xf4, 0xd3, 0x2e, 0x41, 0x00, 0xf6, 0xd4, 0x2f, 0x41, 0x00, 0xfa, 0xd5, -0x30, 0x41, 0x00, 0xd7, 0xa5, 0x31, 0x41, 0x00, 0xe7, 0xb8, 0x32, 0x41, 0x00, 0xe6, 0xb7, 0x00, -0x03, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x36, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0xef, 0x0f, 0xd6, 0x9b, 0xde, 0x9d, 0xe1, 0x9e, 0xe3, -0x9f, 0xe9, 0xa2, 0xf2, 0xa3, 0xfa, 0xfd, 0xa4, 0x86, 0xa8, 0x8d, 0xaa, 0x8f, 0xad, 0x90, 0xbe, -0x92, 0xd1, 0x95, 0xd5, 0x98, 0x20, 0xef, 0xf9, 0x03, 0xe3, 0xa0, 0xf2, 0xfb, 0x20, 0xf9, 0x27, -0x03, 0xe3, 0xa1, 0xf2, 0xfc, 0x20, 0x27, 0x00, 0x70, 0x24, 0x06, 0x09, 0xcb, 0x01, 0x47, 0x4b, -0x2c, 0xcb, 0x01, 0x45, 0x4c, 0x09, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, -0x00, 0x65, 0x03, 0xcc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x65, 0x03, 0x12, 0x03, 0x0b, 0x04, 0x00, -0x00, 0xe1, 0x02, 0x07, 0x05, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x02, 0x40, 0x04, 0xda, 0x04, 0x00, -0x00, 0x53, 0x03, 0xf9, 0x05, 0x00, 0x00, 0x00, 0x00, 0x53, 0x03, 0x22, 0x05, 0xc8, 0x05, 0x00, -0x00, 0x5a, 0x03, 0xb0, 0x01, 0x97, 0x02, 0x00, 0x00, 0x52, 0x03, 0xcf, 0x00, 0x97, 0x02, 0x00, -0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x07, -0x02, 0x03, 0x00, 0x00, 0x14, 0x0b, 0x02, 0x03, 0x00, 0x00, 0xf8, 0x0c, 0x02, 0x03, 0x00, 0x00, -0xf1, 0x10, 0x01, 0x00, 0x3b, 0x3a, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, -0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, -0x02, 0x03, 0x00, 0x00, 0xae, 0x1b, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x1e, 0x41, 0x00, 0x61, 0x41, -0x27, 0x01, 0x03, 0xc8, 0xc9, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x39, -0x00, 0x00, 0x20, 0x00, 0x02, 0x03, 0x03, 0x00, 0x00, 0xad, 0xfb, 0x04, 0x02, 0x03, 0x00, 0x00, -0xfc, 0x05, 0x03, 0x03, 0x00, 0x00, 0xcf, 0x9c, 0x07, 0x02, 0x03, 0x00, 0xca, 0xac, 0x08, 0x02, -0x03, 0x00, 0x00, 0xab, 0x09, 0x02, 0x03, 0x00, 0x00, 0xf3, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x0c, 0x02, 0x03, 0x00, 0x00, 0xbe, 0x0d, 0x03, 0x03, 0x00, 0x00, 0x9e, 0xf6, 0x10, 0x43, 0x00, -0x71, 0x51, 0x84, 0x8e, 0x11, 0x43, 0x03, 0x00, 0x00, 0x86, 0x8f, 0x12, 0x43, 0x00, 0x65, 0x45, -0x82, 0x90, 0x13, 0x42, 0x03, 0x00, 0x00, 0xa9, 0x14, 0x43, 0x03, 0x00, 0x00, 0xe7, 0xe8, 0x15, -0x43, 0x00, 0x79, 0x59, 0x81, 0x9a, 0x16, 0x43, 0x00, 0x75, 0x55, 0xa3, 0xe9, 0x17, 0x43, 0x00, -0x69, 0x49, 0xa1, 0xd6, 0x18, 0xc3, 0x00, 0x6f, 0x18, 0x4f, 0x18, 0xa2, 0x18, 0xe0, 0x00, 0x19, -0x43, 0x03, 0x00, 0x00, 0x94, 0x99, 0x1e, 0x43, 0x00, 0x61, 0x41, 0xa0, 0xb5, 0x1f, 0x43, 0x03, -0x00, 0x00, 0xe1, 0xf5, 0x20, 0x43, 0x03, 0x00, 0x00, 0xd0, 0xd1, 0x26, 0x43, 0x03, 0x00, 0x00, -0x9b, 0x9d, 0x27, 0x03, 0x00, 0x3b, 0x3a, 0xf4, 0xf8, 0x28, 0x03, 0x0f, 0x00, 0x00, 0xcb, 0xcc, -0x29, 0x01, 0x03, 0xc8, 0xc9, 0x2b, 0x03, 0x03, 0x00, 0x00, 0xaa, 0xdd, 0x2c, 0x43, 0x03, 0x00, -0x00, 0x91, 0x92, 0x2e, 0x43, 0x00, 0x63, 0x43, 0xb8, 0xbd, 0x31, 0x43, 0x00, 0x6e, 0x4e, 0xa4, -0xa5, 0x32, 0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x03, 0x03, 0x00, 0x00, 0x87, 0x80, 0x35, 0x02, -0x03, 0x00, 0x00, 0xa8, 0x00, 0x02, 0x03, 0x03, 0x00, 0x00, 0xad, 0xfb, 0x04, 0x02, 0x03, 0x00, -0x00, 0xfc, 0x05, 0x03, 0x03, 0x00, 0x00, 0xcf, 0x9c, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x07, -0x02, 0x03, 0x00, 0xca, 0xac, 0x08, 0x02, 0x03, 0x00, 0x00, 0xab, 0x09, 0x02, 0x03, 0x00, 0x00, -0xf3, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x03, 0x00, 0x00, 0xbe, 0x0d, 0x03, 0x03, -0x00, 0x00, 0x9e, 0xf6, 0x10, 0x43, 0x00, 0x71, 0x51, 0x84, 0x8e, 0x11, 0x43, 0x03, 0x00, 0x00, -0x86, 0x8f, 0x12, 0x43, 0x00, 0x65, 0x45, 0x82, 0x90, 0x13, 0x42, 0x03, 0x00, 0x00, 0xa9, 0x14, -0x43, 0x03, 0x00, 0x00, 0xe7, 0xe8, 0x15, 0x43, 0x00, 0x79, 0x59, 0x81, 0x9a, 0x16, 0x43, 0x00, -0x75, 0x55, 0xa3, 0xe9, 0x17, 0x43, 0x00, 0x69, 0x49, 0xa1, 0xd6, 0x18, 0xc3, 0x00, 0x6f, 0x18, -0x4f, 0x18, 0xa2, 0x18, 0xe0, 0x00, 0x19, 0x43, 0x03, 0x00, 0x00, 0x94, 0x99, 0x1e, 0x43, 0x00, -0x61, 0x41, 0xa0, 0xb5, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xe1, 0xf5, 0x20, 0x43, 0x03, 0x00, 0x00, -0xd0, 0xd1, 0x26, 0x43, 0x03, 0x00, 0x00, 0x9b, 0x9d, 0x27, 0x03, 0x00, 0x3b, 0x3a, 0xf4, 0xf8, -0x28, 0x03, 0x0f, 0x00, 0x00, 0xcb, 0xcc, 0x29, 0x01, 0x03, 0xc8, 0xc9, 0x2b, 0x03, 0x03, 0x00, -0x00, 0xaa, 0xdd, 0x2c, 0x43, 0x03, 0x00, 0x00, 0x91, 0x92, 0x2e, 0x43, 0x00, 0x63, 0x43, 0xb8, -0xbd, 0x31, 0x43, 0x00, 0x6e, 0x4e, 0xa4, 0xa5, 0x32, 0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x03, -0x03, 0x00, 0x00, 0x87, 0x80, 0x35, 0x02, 0x03, 0x00, 0x00, 0xa8, 0x00, 0x60, 0x0b, 0x61, 0x85, -0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, -0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, -0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0f, 0x61, 0xa0, -0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, 0x80, -0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, -0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, -0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0x99, 0x04, 0x02, 0x03, -0x00, 0x00, 0x9a, 0x05, 0x02, 0x03, 0x00, 0x00, 0x9c, 0x06, 0x02, 0x03, 0x00, 0x00, 0xf5, 0x0a, -0x02, 0x03, 0x00, 0x00, 0x8a, 0x0d, 0x02, 0x03, 0x00, 0x00, 0xab, 0x11, 0x01, 0x02, 0xed, 0xca, -0x12, 0x42, 0x00, 0xde, 0xa8, 0x87, 0x13, 0x41, 0x00, 0xeb, 0xc7, 0x14, 0x41, 0x00, 0xee, 0xd0, -0x15, 0x41, 0x00, 0xf2, 0xd1, 0x16, 0x41, 0x00, 0xe2, 0xac, 0x17, 0x41, 0x00, 0xe3, 0xad, 0x18, -0x41, 0x00, 0xe9, 0xbe, 0x19, 0x41, 0x00, 0xea, 0xc6, 0x1e, 0x41, 0x00, 0xd6, 0xa4, 0x1f, 0x41, -0x00, 0xec, 0xcf, 0x20, 0x41, 0x00, 0xdd, 0xa7, 0x21, 0x41, 0x00, 0xf3, 0xd2, 0x22, 0x41, 0x00, -0xd8, 0xa6, 0x23, 0x41, 0x00, 0xe1, 0xaa, 0x24, 0x41, 0x00, 0xe8, 0xbd, 0x25, 0x41, 0x00, 0xe4, -0xb5, 0x26, 0x41, 0x00, 0xe5, 0xb6, 0x27, 0x02, 0x07, 0x00, 0x00, 0xca, 0x2a, 0x04, 0x1f, 0x00, -0x00, 0x00, 0x00, 0x78, 0x2b, 0x02, 0x03, 0x00, 0x00, 0x89, 0x2c, 0xc1, 0x00, 0xe0, 0x00, 0xa9, -0x2c, 0x2d, 0x41, 0x00, 0xf4, 0xd3, 0x2e, 0x42, 0x00, 0xf6, 0xd4, 0x97, 0x2f, 0x41, 0x00, 0xfa, -0xd5, 0x30, 0x41, 0x00, 0xd7, 0xa5, 0x31, 0x41, 0x00, 0xe7, 0xb8, 0x32, 0x41, 0x00, 0xe6, 0xb7, -0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0x99, 0x04, 0x02, 0x03, 0x00, 0x00, 0x9a, 0x05, 0x02, 0x03, -0x00, 0x00, 0x9c, 0x06, 0x02, 0x03, 0x00, 0x00, 0xf5, 0x0a, 0x02, 0x03, 0x00, 0x00, 0x8a, 0x0d, -0x02, 0x03, 0x00, 0x00, 0xab, 0x12, 0x42, 0x03, 0x00, 0x00, 0x87, 0x2b, 0x02, 0x03, 0x00, 0x00, -0x89, 0x2e, 0x42, 0x03, 0x00, 0x00, 0x97, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, -0xef, 0x0f, 0xd6, 0x9b, 0xde, 0x9d, 0xe1, 0x9e, 0xe3, 0x9f, 0xe9, 0xa2, 0xf2, 0xa3, 0xfa, 0xfd, -0xa4, 0x86, 0xa8, 0x8d, 0xaa, 0x8f, 0xad, 0x90, 0xbe, 0x92, 0xd1, 0x95, 0xd5, 0x98, 0x20, 0xef, -0xf9, 0x05, 0xe3, 0xa0, 0xf2, 0xfb, 0xad, 0x91, 0xd1, 0x96, 0x20, 0xf9, 0xf7, 0x03, 0xe3, 0xa1, -0xf2, 0xfc, 0x20, 0xf7, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0x15, 0x11, 0x01, 0x02, 0xaa, 0x00, -0x12, 0x41, 0x00, 0x9c, 0x84, 0x13, 0x41, 0x00, 0xa8, 0x90, 0x14, 0x41, 0x00, 0xab, 0x92, 0x15, -0x41, 0x00, 0xac, 0x93, 0x16, 0x41, 0x00, 0x9f, 0x87, 0x17, 0x41, 0x00, 0xa0, 0x88, 0x18, 0x41, -0x00, 0xa6, 0x8e, 0x19, 0x41, 0x00, 0xa7, 0x8f, 0x1a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x1b, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x1e, 0x41, 0x00, 0x98, 0x80, 0x1f, 0x41, 0x00, 0xa9, 0x91, 0x20, 0x41, -0x00, 0x9b, 0x83, 0x21, 0x41, 0x00, 0xad, 0x94, 0x22, 0x41, 0x00, 0x9a, 0x82, 0x23, 0x41, 0x00, -0x9e, 0x86, 0x24, 0x41, 0x00, 0xa5, 0x8d, 0x25, 0x41, 0x00, 0xa1, 0x89, 0x26, 0x41, 0x00, 0xa2, -0x8a, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2c, 0x41, 0x00, 0x9d, 0x85, 0x2d, 0x41, -0x00, 0xae, 0x95, 0x2e, 0x41, 0x00, 0xaf, 0x96, 0x2f, 0xc1, 0x00, 0xe0, 0x00, 0x97, 0x2f, 0x30, -0x41, 0x00, 0x99, 0x81, 0x31, 0x41, 0x00, 0xa4, 0x8c, 0x32, 0x41, 0x00, 0xa3, 0x8b, 0x00, 0x27, -0x0f, 0x98, 0xe1, 0x9c, 0xe2, 0x9e, 0xe3, 0xa0, 0xe5, 0xa6, 0xe6, 0xac, 0xe7, 0xe0, 0xe9, 0x80, -0xea, 0x84, 0xeb, 0x86, 0xec, 0x88, 0xed, 0x8e, 0xee, 0x93, 0xef, 0x97, 0xf0, 0x20, 0x27, 0x22, -0x05, 0xa0, 0xe4, 0xac, 0xe8, 0x88, 0xf4, 0x93, 0xf5, 0x20, 0x22, 0x00, 0x06, 0x02, 0x03, 0x00, -0x00, 0x15, 0x1a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x1b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x36, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x03, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, 0x03, -0x00, 0x00, 0x9c, 0x06, 0x02, 0x03, 0x00, 0x00, 0xf5, 0x0d, 0x02, 0x03, 0x00, 0x00, 0xab, 0x11, -0x01, 0x02, 0xed, 0xca, 0x12, 0x41, 0x00, 0xde, 0xa8, 0x13, 0x41, 0x00, 0xeb, 0xc7, 0x14, 0x41, -0x00, 0xee, 0xd0, 0x15, 0x41, 0x00, 0xf2, 0xd1, 0x16, 0x41, 0x00, 0xe2, 0xac, 0x17, 0x41, 0x00, -0xe3, 0xad, 0x18, 0x41, 0x00, 0xe9, 0xbe, 0x19, 0x41, 0x00, 0xea, 0xc6, 0x1e, 0x41, 0x00, 0xd6, -0xa4, 0x1f, 0x41, 0x00, 0xec, 0xcf, 0x20, 0x41, 0x00, 0xdd, 0xa7, 0x21, 0x41, 0x00, 0xf3, 0xd2, -0x22, 0x41, 0x00, 0xd8, 0xa6, 0x23, 0x41, 0x00, 0xe1, 0xaa, 0x24, 0x41, 0x00, 0xe8, 0xbd, 0x25, -0x41, 0x00, 0xe4, 0xb5, 0x26, 0x41, 0x00, 0xe5, 0xb6, 0x27, 0x02, 0x07, 0x00, 0x00, 0xca, 0x2a, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2c, 0xc1, 0x00, 0xe0, 0x00, 0xa9, 0x2c, 0x2d, 0x41, -0x00, 0xf4, 0xd3, 0x2e, 0x41, 0x00, 0xf6, 0xd4, 0x2f, 0x41, 0x00, 0xfa, 0xd5, 0x30, 0x41, 0x00, -0xd7, 0xa5, 0x31, 0x41, 0x00, 0xe7, 0xb8, 0x32, 0x41, 0x00, 0xe6, 0xb7, 0x00, 0xef, 0x0f, 0xd6, -0x9b, 0xde, 0x9d, 0xe1, 0x9e, 0xe3, 0x9f, 0xe9, 0xa2, 0xf2, 0xa3, 0xfa, 0xfd, 0xa4, 0x86, 0xa8, -0x8d, 0xaa, 0x8f, 0xad, 0x90, 0xbe, 0x92, 0xd1, 0x95, 0xd5, 0x98, 0x20, 0xef, 0xf9, 0x03, 0xe3, -0xa0, 0xf2, 0xfb, 0x20, 0xf9, 0x27, 0x03, 0xe3, 0xa1, 0xf2, 0xfc, 0x20, 0x27, 0x00, 0x03, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, 0x03, 0x00, 0x00, 0x9c, 0x06, 0x02, 0x03, 0x00, 0x00, 0xf5, -0x0d, 0x02, 0x03, 0x00, 0x00, 0xab, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x78, -0x34, 0x01, 0x09, 0x00, 0x00, 0x49, 0x53, 0x2c, 0xca, 0x01, 0x49, 0x53, 0x04, 0x02, 0x00, 0x00, -0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xd8, 0x00, 0xe5, 0x00, 0x00, 0x00, -0x52, 0x03, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x5d, 0x03, 0x02, 0x01, 0x0d, 0x01, 0x00, 0x00, -0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x9c, 0x07, 0x01, 0x01, 0x00, -0x26, 0x08, 0x02, 0x01, 0x00, 0x2f, 0x7b, 0x09, 0x03, 0x01, 0x00, 0x28, 0x5b, 0x1b, 0x0a, 0x03, -0x01, 0x00, 0x29, 0x5d, 0x1d, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, 0x43, 0x00, 0x94, 0x99, -0x5c, 0x1c, 0x0d, 0x03, 0x04, 0x2d, 0x5f, 0x00, 0x1f, 0x10, 0x42, 0x03, 0x00, 0x00, 0x40, 0x12, -0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, -0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x41, 0x00, 0xd0, 0xd1, 0x1b, 0x02, 0x00, -0x27, 0x3f, 0x7e, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x41, 0x00, 0x91, 0x92, 0x28, 0x03, 0x03, -0xc8, 0xc8, 0x5e, 0x1e, 0x29, 0x02, 0x00, 0x3c, 0x3e, 0x7c, 0x2b, 0x02, 0x00, 0x2b, 0x2a, 0x60, -0x33, 0x01, 0x01, 0x00, 0x3b, 0x34, 0x01, 0x01, 0x00, 0x3a, 0x35, 0x41, 0x00, 0xe7, 0xe8, 0x39, -0x00, 0x00, 0x20, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, -0x00, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, -0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0x00, 0x1a, 0x41, -0x00, 0x8c, 0x8b, 0x35, 0x41, 0x00, 0x95, 0x8d, 0x00, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, -0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0x98, 0x41, 0xa4, 0x45, 0x90, 0x49, 0xa5, 0x4f, 0xa6, 0x55, -0xa7, 0x59, 0x97, 0x20, 0x27, 0x00, 0xca, 0xee, 0x01, 0x09, 0xa1, 0x00, 0x49, 0x53, 0x2c, 0xc5, -0x00, 0x49, 0x53, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, -0x03, 0xf7, 0x00, 0x04, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x5d, -0x03, 0x83, 0x01, 0x99, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x03, -0x00, 0x00, 0x9c, 0x05, 0x02, 0x01, 0x00, 0xcf, 0x24, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, 0x02, -0x01, 0x00, 0x2f, 0x7b, 0x09, 0x03, 0x01, 0x00, 0x28, 0x5b, 0x1b, 0x0a, 0x03, 0x01, 0x00, 0x29, -0x5d, 0x1d, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, 0x43, 0x00, 0x94, 0x99, 0x5c, 0x1c, 0x0d, -0x03, 0x04, 0x2d, 0x5f, 0x00, 0x1f, 0x10, 0x42, 0x03, 0x00, 0x00, 0x40, 0x12, 0x41, 0x00, 0x65, -0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, -0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x41, 0x00, 0xd0, 0xd1, 0x1b, 0x02, 0x04, 0x27, 0x3f, 0xcd, -0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x41, 0x00, 0x91, 0x92, 0x28, 0x03, 0x07, 0xca, 0xca, 0xc9, -0x1e, 0x29, 0x02, 0x03, 0xcc, 0xcb, 0xf8, 0x2b, 0x02, 0x04, 0x2b, 0x2a, 0xc8, 0x2e, 0x41, 0x00, -0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x02, 0x01, -0x00, 0x3b, 0x3c, 0x34, 0x02, 0x01, 0x00, 0x3a, 0x3e, 0x35, 0x42, 0x00, 0xe7, 0xe8, 0x7c, 0x39, -0x00, 0x00, 0x20, 0x56, 0x02, 0x00, 0x3c, 0x3e, 0x7c, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, -0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, -0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x5e, -0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, -0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, -0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, -0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, -0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf8, 0x03, 0x61, -0x86, 0x41, 0x8f, 0x20, 0xf8, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, -0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x00, 0x05, 0x01, 0x03, 0x00, 0xa0, 0x1a, 0x41, 0x00, 0x8c, 0x8b, -0x1b, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x35, 0x41, 0x00, 0x95, 0x8d, 0x00, 0x60, 0x03, 0x61, 0x85, -0x65, 0x8a, 0x20, 0x60, 0x5e, 0x05, 0x61, 0x83, 0x65, 0x88, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, -0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0x98, 0x41, 0xa4, -0x45, 0x90, 0x49, 0xa5, 0x4f, 0xa6, 0x55, 0xa7, 0x59, 0x97, 0x20, 0x27, 0x22, 0x08, 0x61, 0x84, -0x65, 0x89, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0xf8, 0x03, -0x61, 0x86, 0x41, 0x8f, 0x20, 0xf8, 0x00, 0x29, 0x62, 0x08, 0x09, 0x00, 0x00, 0x52, 0x4f, 0x2c, -0x4d, 0x01, 0x52, 0x4f, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x54, 0x03, 0x0f, 0x02, 0x89, 0x02, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, -0x5a, 0x03, 0x81, 0x01, 0x88, 0x01, 0x00, 0x00, 0x50, 0x03, 0x4a, 0x04, 0x00, 0x00, 0x00, 0x00, -0x50, 0x03, 0x4a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x65, 0x04, 0xc3, 0x05, 0x00, 0x00, 0x00, 0x00, -0x65, 0x04, 0xc4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x39, 0x75, 0x37, 0x06, 0x00, 0x00, 0x00, 0x00, -0x3a, 0x75, 0xde, 0x07, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x75, 0xc0, 0x06, 0xc9, 0x07, 0x00, 0x00, -0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x04, 0x0f, 0x00, 0x00, -0xc9, 0x00, 0x1e, 0x05, 0x01, 0x01, 0x00, 0xcf, 0x06, 0x02, 0x07, 0x00, 0x00, 0xca, 0x07, 0x01, -0x01, 0x00, 0x26, 0x08, 0x02, 0x05, 0x00, 0x2f, 0xcb, 0x09, 0x02, 0x01, 0x00, 0x28, 0xfa, 0x0a, -0x02, 0x05, 0x00, 0x29, 0xcc, 0x0b, 0x01, 0x01, 0x00, 0x3d, 0x0c, 0x02, 0x04, 0x2b, 0x3f, 0xcd, -0x0d, 0x02, 0x04, 0x27, 0x2a, 0xce, 0x10, 0x42, 0x03, 0x00, 0x00, 0x5c, 0x11, 0x42, 0x03, 0x00, -0x00, 0x7c, 0x12, 0x42, 0x00, 0x65, 0x45, 0xf6, 0x13, 0x42, 0x03, 0x00, 0x00, 0x9e, 0x14, 0x42, -0x03, 0x00, 0x00, 0x24, 0x15, 0xc5, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0xe1, 0x2c, 0x00, 0x2c, 0x1a, -0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x42, 0x00, 0x69, 0x49, 0x3c, 0x18, 0x42, -0x00, 0x6f, 0x4f, 0x3e, 0x1a, 0x02, 0x03, 0xa0, 0xa0, 0xf6, 0x1b, 0x42, 0x00, 0x8c, 0xd7, 0x9e, -0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x02, 0x03, 0xa0, 0xa0, 0x24, 0x28, 0x02, 0x03, 0xa0, 0xa0, -0xe1, 0x29, 0x01, 0x00, 0x5d, 0x5b, 0x2b, 0x41, 0x00, 0x83, 0xb6, 0x2c, 0xc5, 0x00, 0x79, 0x15, -0x59, 0x15, 0x00, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x2f, -0x42, 0x03, 0x00, 0x00, 0x40, 0x30, 0x42, 0x03, 0x00, 0x00, 0x7b, 0x31, 0x42, 0x00, 0x6e, 0x4e, -0x7d, 0x32, 0x42, 0x03, 0x00, 0x00, 0xf5, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, 0x01, -0x00, 0x3a, 0x3e, 0x35, 0x04, 0x0c, 0x2d, 0x5f, 0x00, 0x00, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, -0x01, 0x00, 0x3c, 0x3e, 0x00, 0x16, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x7e, 0x07, 0x61, 0xc6, -0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, -0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, -0x55, 0xea, 0x20, 0x5e, 0xf8, 0x03, 0x61, 0x86, 0x41, 0x8f, 0x20, 0xf8, 0x60, 0x0b, 0x61, 0x85, -0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, -0x55, 0xeb, 0x20, 0x60, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, -0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, -0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, -0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, -0x20, 0xf7, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x03, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x05, -0x02, 0x07, 0x00, 0x00, 0xca, 0x06, 0x02, 0x07, 0x00, 0x00, 0xcb, 0x07, 0x02, 0x07, 0x00, 0x00, -0xcc, 0x08, 0x02, 0x03, 0x00, 0x00, 0x60, 0x09, 0x02, 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x02, 0x07, -0x00, 0x00, 0xce, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xcf, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xd0, 0x0d, -0x02, 0x07, 0x00, 0x00, 0xd1, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, 0x54, 0x16, -0x42, 0x03, 0x00, 0x00, 0xaa, 0x1a, 0x41, 0x00, 0xc7, 0xc6, 0x1f, 0x42, 0x00, 0x73, 0x53, 0xd0, -0x20, 0x42, 0x00, 0x64, 0x44, 0xd1, 0x25, 0x42, 0x03, 0x00, 0x00, 0x88, 0x26, 0x42, 0x00, 0x6c, -0x4c, 0x9d, 0x27, 0x41, 0x00, 0xad, 0xb8, 0x28, 0x41, 0x00, 0xee, 0xdd, 0x00, 0xf3, 0x13, 0x63, -0x9f, 0x64, 0xd4, 0x65, 0xd8, 0x6c, 0x96, 0x6e, 0xe5, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, -0xa7, 0x43, 0xac, 0x44, 0xd2, 0x45, 0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x52, 0xfc, 0x53, 0xe6, 0x54, -0x9b, 0x5a, 0xa6, 0x20, 0xf3, 0x5e, 0x07, 0x61, 0x83, 0x69, 0x8c, 0x6f, 0x93, 0x41, 0xb6, 0x49, -0xd7, 0x4f, 0xe2, 0x20, 0x5e, 0xf4, 0x03, 0x61, 0xc7, 0x41, 0xc6, 0x20, 0xf4, 0xf8, 0x03, 0x75, -0x85, 0x55, 0xde, 0x20, 0xf8, 0xf2, 0x05, 0x61, 0xa5, 0x65, 0xa9, 0x41, 0xa4, 0x45, 0xa8, 0x20, -0xf2, 0xfa, 0x03, 0x7a, 0xbe, 0x5a, 0xbd, 0x20, 0xfa, 0xef, 0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, -0x82, 0x69, 0xa1, 0x6c, 0x92, 0x6e, 0xe4, 0x6f, 0xa2, 0x72, 0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, -0xec, 0x7a, 0xab, 0x41, 0xb5, 0x43, 0x8f, 0x45, 0x90, 0x49, 0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, -0xe0, 0x52, 0xe8, 0x53, 0x97, 0x55, 0xe9, 0x59, 0xed, 0x5a, 0x8d, 0x20, 0xef, 0xf1, 0x05, 0x6f, -0x8b, 0x75, 0xfb, 0x4f, 0x8a, 0x55, 0xeb, 0x20, 0xf1, 0xf9, 0x09, 0x61, 0x84, 0x65, 0x89, 0x6f, -0x94, 0x75, 0x81, 0x41, 0x8e, 0x45, 0xd3, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf7, 0x07, 0x63, -0x87, 0x73, 0xad, 0x74, 0xee, 0x43, 0x80, 0x53, 0xb8, 0x54, 0xdd, 0x20, 0xf7, 0x00, 0x02, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x01, 0x03, 0x00, 0xa0, 0x06, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x43, 0x00, -0xec, 0x9c, 0x27, 0x2a, 0x10, 0x41, 0x00, 0xee, 0x9e, 0x11, 0x41, 0x00, 0xe9, 0x99, 0x12, 0x42, -0x00, 0xa5, 0x85, 0xfa, 0x13, 0xc2, 0x04, 0xe0, 0x00, 0x90, 0x13, 0xa0, 0x13, 0x14, 0x41, 0x00, -0xe2, 0x92, 0x15, 0xc5, 0x04, 0xa7, 0x2c, 0x87, 0x2c, 0xa0, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, -0x2c, 0x16, 0x42, 0x00, 0xe3, 0x93, 0xfd, 0x17, 0x41, 0x00, 0xf7, 0xf6, 0x18, 0x41, 0x00, 0xae, -0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x42, 0x00, 0xf9, 0xf8, 0xfa, 0x1b, 0x42, 0x04, 0xa8, -0x88, 0xa0, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, -0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xf3, 0xf2, 0x23, 0x41, 0x00, 0xa3, 0x83, -0x24, 0x41, 0x00, 0xa6, 0x86, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, -0x41, 0x00, 0xe8, 0x98, 0x28, 0x42, 0x04, 0xe6, 0x96, 0xa0, 0x29, 0x43, 0x00, 0xf5, 0xf4, 0x5d, -0x5b, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x2b, 0x41, 0x00, 0xef, 0x9f, 0x2c, -0xc5, 0x00, 0xa9, 0x15, 0x89, 0x15, 0x00, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x41, -0x00, 0xe5, 0x95, 0x2e, 0x41, 0x00, 0xe7, 0x97, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, -0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x42, 0x04, 0xac, 0x8c, 0xa0, 0x00, 0x02, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x01, 0x03, 0x00, 0xa0, 0x06, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x12, 0x02, 0x03, 0x00, 0x00, 0xfa, 0x13, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x15, -0xc5, 0x04, 0x7a, 0x2c, 0x5a, 0x2c, 0xa0, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x02, -0x03, 0x00, 0x00, 0xfd, 0x1a, 0x02, 0x03, 0x00, 0x00, 0xfa, 0x1b, 0x10, 0x00, 0x00, 0x28, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x2b, 0x10, 0x00, 0x00, 0x32, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x36, 0x05, -0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x05, 0x01, 0x01, 0x00, 0xfd, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x43, 0x00, 0xec, 0x9c, 0x27, 0x2a, 0x10, 0x41, -0x00, 0xee, 0x9e, 0x11, 0x41, 0x00, 0xe9, 0x99, 0x12, 0x42, 0x00, 0xa5, 0x85, 0xfa, 0x13, 0xc2, -0x04, 0xe0, 0x00, 0x90, 0x13, 0xa0, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0xc5, 0x04, 0xa7, -0x2c, 0x87, 0x2c, 0xa0, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0xe3, 0x93, -0x17, 0x41, 0x00, 0xf7, 0xf6, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, -0x42, 0x00, 0xf9, 0xf8, 0xfa, 0x1b, 0x42, 0x04, 0xa8, 0x88, 0xa0, 0x1e, 0x41, 0x00, 0xa0, 0x80, -0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, -0x41, 0x00, 0xf3, 0xf2, 0x23, 0x41, 0x00, 0xa3, 0x83, 0x24, 0x41, 0x00, 0xa6, 0x86, 0x25, 0x41, -0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xe8, 0x98, 0x28, 0x42, 0x04, -0xe6, 0x96, 0xa0, 0x29, 0x43, 0x00, 0xf5, 0xf4, 0x5d, 0x5b, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7d, 0x2b, 0x41, 0x00, 0xef, 0x9f, 0x2c, 0xc5, 0x00, 0xa9, 0x15, 0x89, 0x15, 0x00, -0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x41, 0x00, 0xe5, 0x95, 0x2e, 0x41, 0x00, 0xe7, -0x97, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, -0x32, 0x42, 0x04, 0xac, 0x8c, 0xa0, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x05, 0x01, 0x01, 0x00, 0xfd, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x02, 0x03, 0x00, -0x00, 0xfa, 0x13, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x15, 0xc5, 0x04, 0x7a, 0x2c, 0x5a, 0x2c, 0xa0, -0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x1a, 0x02, 0x03, 0x00, 0x00, 0xfa, 0x1b, 0x10, 0x00, -0x00, 0x28, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2b, 0x10, 0x00, 0x00, 0x32, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x36, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x06, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x12, 0x03, 0x03, 0x00, 0x00, 0x88, 0xd2, 0x13, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x15, 0xc5, -0x04, 0x7a, 0x2c, 0x5a, 0x2c, 0xa0, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x43, 0x03, -0x00, 0x00, 0x81, 0x9a, 0x17, 0x41, 0x01, 0x00, 0x98, 0x18, 0x43, 0x03, 0x00, 0x00, 0x94, 0x99, -0x1a, 0x42, 0x04, 0x84, 0x8e, 0xa0, 0x1b, 0x42, 0x04, 0x8d, 0x49, 0xa0, 0x22, 0x43, 0x03, 0x00, -0x00, 0xa7, 0xa6, 0x27, 0x41, 0x00, 0x9f, 0x9e, 0x28, 0x42, 0x04, 0xf3, 0xf4, 0xa0, 0x2b, 0x41, -0x00, 0x87, 0x80, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x03, 0x01, 0x03, 0x00, 0xc8, 0x04, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x01, 0x03, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x43, 0x00, 0xec, 0x9c, 0x27, 0x2a, 0x10, -0x41, 0x00, 0xee, 0x9e, 0x11, 0x41, 0x00, 0xe9, 0x99, 0x12, 0x42, 0x04, 0xa5, 0x85, 0xa0, 0x13, -0xc2, 0x04, 0xe0, 0x00, 0x90, 0x13, 0xa0, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0xc5, 0x04, -0xa7, 0x2c, 0x87, 0x2c, 0xa0, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x42, 0x00, 0xe3, -0x93, 0xfd, 0x17, 0x41, 0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, -0x8f, 0x1a, 0x42, 0x04, 0xed, 0x9d, 0xa0, 0x1b, 0x42, 0x04, 0xeb, 0x9b, 0xa0, 0x1e, 0x41, 0x00, -0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, -0x94, 0x22, 0x41, 0x00, 0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa6, 0x86, -0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xe8, 0x98, 0x28, -0x42, 0x04, 0xe6, 0x96, 0xa0, 0x29, 0x43, 0x00, 0xea, 0x9a, 0x5d, 0x5b, 0x2a, 0x05, 0x3f, 0x00, -0x00, 0x00, 0x00, 0x00, 0x80, 0x2b, 0x41, 0x00, 0xef, 0x9f, 0x2c, 0xc5, 0x00, 0xa9, 0x15, 0x89, -0x15, 0x00, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x41, 0x00, 0xfb, 0xfa, 0x2e, 0x41, -0x00, 0xe7, 0x97, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, -0xad, 0x8d, 0x32, 0x42, 0x04, 0xac, 0x8c, 0xa0, 0x39, 0x00, 0x00, 0x20, 0x00, 0x22, 0x09, 0xa0, -0xf3, 0xa5, 0xf1, 0xae, 0xf5, 0xe3, 0xf7, 0x80, 0xf2, 0x85, 0xf0, 0x8e, 0xf4, 0x93, 0xf6, 0x20, -0x22, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x01, -0x03, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x13, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x15, 0xc5, 0x04, 0x7a, 0x2c, 0x5a, 0x2c, 0xa0, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, -0x00, 0x2c, 0x16, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x1a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x1b, 0x10, -0x00, 0x00, 0x28, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2b, 0x10, 0x00, 0x00, 0x32, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x36, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0xb7, 0xbf, 0x07, 0x04, -0xbe, 0x01, 0x52, 0x4f, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x54, 0x03, 0xd7, 0x01, 0x4d, 0x02, 0x00, 0x00, 0x5a, 0x03, 0x49, 0x01, 0x50, 0x01, 0x00, 0x00, -0x52, 0x03, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x50, 0x03, 0xfb, 0x03, 0x00, 0x00, 0x00, 0x00, -0x50, 0x03, 0x0e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x65, 0x04, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, -0x65, 0x04, 0x69, 0x04, 0x00, 0x00, 0x00, 0x00, 0x39, 0x75, 0xbd, 0x05, 0x00, 0x00, 0x00, 0x00, -0x3a, 0x75, 0x4c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x75, 0x45, 0x06, 0x37, 0x07, 0x00, 0x00, -0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x04, 0x0f, 0x00, 0x00, -0xc9, 0x00, 0x1e, 0x06, 0x02, 0x07, 0x00, 0x00, 0xca, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, 0x02, -0x05, 0x00, 0x2f, 0xcb, 0x09, 0x02, 0x01, 0x00, 0x28, 0xfa, 0x0a, 0x02, 0x05, 0x00, 0x29, 0xcc, -0x0b, 0x01, 0x01, 0x00, 0x3d, 0x0c, 0x02, 0x04, 0x2b, 0x3f, 0xcd, 0x0d, 0x02, 0x04, 0x27, 0x2a, -0xce, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, -0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x42, 0x03, 0xa0, 0xa0, 0x7b, -0x1b, 0x42, 0x00, 0x8c, 0xd7, 0x7d, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x27, 0x44, 0x0b, 0xa0, 0xa0, -0x5b, 0x00, 0x1b, 0x28, 0x44, 0x0b, 0xa0, 0xa0, 0x5d, 0x00, 0x1d, 0x29, 0x42, 0x00, 0x83, 0xb6, -0x2d, 0x2b, 0x02, 0x03, 0x00, 0x00, 0xe1, 0x2c, 0x42, 0x03, 0x00, 0x00, 0x9e, 0x2d, 0x42, 0x03, -0x00, 0x00, 0xf6, 0x2e, 0x42, 0x00, 0x63, 0x43, 0xf5, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x33, 0x02, -0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, 0x01, 0x00, 0x3a, 0x3e, 0x35, 0x04, 0x08, 0x2d, 0x5f, 0x40, -0x00, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, 0x02, 0x00, 0x9e, 0xf6, 0xf5, 0x00, 0x12, 0x42, 0x03, -0x00, 0x00, 0xd5, 0x00, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, -0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf8, 0x03, 0x61, 0x86, -0x41, 0x8f, 0x20, 0xf8, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, -0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0xef, 0x0d, 0x61, 0xa0, -0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, -0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, -0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, -0x20, 0xf9, 0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, -0x7e, 0x03, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x05, 0x02, 0x07, 0x00, 0x00, 0xca, 0x06, 0x02, 0x07, -0x00, 0x00, 0xcb, 0x07, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x08, 0x02, 0x03, 0x00, 0x00, 0x60, 0x09, -0x02, 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xce, 0x0b, 0x02, 0x07, 0x00, 0x00, -0xcf, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xd0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xd1, 0x12, 0x42, 0x03, -0x00, 0x00, 0xaa, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, 0x54, 0x1a, 0x41, 0x00, -0xc7, 0xc6, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x20, 0x41, 0x00, 0x64, 0x44, 0x26, 0x41, 0x00, 0x6c, -0x4c, 0x27, 0x41, 0x00, 0xad, 0xb8, 0x28, 0x41, 0x00, 0xee, 0xdd, 0x2c, 0x41, 0x00, 0x7a, 0x5a, -0x00, 0xf3, 0x13, 0x63, 0x9f, 0x64, 0xd4, 0x65, 0xd8, 0x6c, 0x96, 0x6e, 0xe5, 0x72, 0xfd, 0x73, -0xe7, 0x74, 0x9c, 0x7a, 0xa7, 0x43, 0xac, 0x44, 0xd2, 0x45, 0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x52, -0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, 0xa6, 0x20, 0xf3, 0x5e, 0x07, 0x61, 0x83, 0x69, 0x8c, 0x6f, -0x93, 0x41, 0xb6, 0x49, 0xd7, 0x4f, 0xe2, 0x20, 0x5e, 0xf4, 0x03, 0x61, 0xc7, 0x41, 0xc6, 0x20, -0xf4, 0xf8, 0x03, 0x75, 0x85, 0x55, 0xde, 0x20, 0xf8, 0xf2, 0x05, 0x61, 0xa5, 0x65, 0xa9, 0x41, -0xa4, 0x45, 0xa8, 0x20, 0xf2, 0xfa, 0x03, 0x7a, 0xbe, 0x5a, 0xbd, 0x20, 0xfa, 0xef, 0x19, 0x61, -0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, 0xa1, 0x6c, 0x92, 0x6e, 0xe4, 0x6f, 0xa2, 0x72, 0xea, 0x73, -0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, 0xab, 0x41, 0xb5, 0x43, 0x8f, 0x45, 0x90, 0x49, 0xd6, 0x4c, -0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, 0xe8, 0x53, 0x97, 0x55, 0xe9, 0x59, 0xed, 0x5a, 0x8d, 0x20, -0xef, 0xf1, 0x05, 0x6f, 0x8b, 0x75, 0xfb, 0x4f, 0x8a, 0x55, 0xeb, 0x20, 0xf1, 0xf9, 0x09, 0x61, -0x84, 0x65, 0x89, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x45, 0xd3, 0x4f, 0x99, 0x55, 0x9a, 0x20, -0xf9, 0xf7, 0x07, 0x63, 0x87, 0x73, 0xad, 0x74, 0xee, 0x43, 0x80, 0x53, 0xb8, 0x54, 0xdd, 0x20, -0xf7, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x43, 0x00, 0xec, -0x9c, 0x27, 0x2a, 0x10, 0x41, 0x00, 0xee, 0x9e, 0x11, 0x41, 0x00, 0xe9, 0x99, 0x12, 0x42, 0x00, -0xa5, 0x85, 0xfd, 0x13, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, -0x41, 0x00, 0xa9, 0x89, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xf7, 0xf6, 0x18, 0x41, -0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xf9, 0xf8, 0x1b, 0x41, 0x00, -0xa8, 0x88, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, -0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xf3, 0xf2, 0x23, 0x41, 0x00, 0xa3, 0x83, -0x24, 0x41, 0x00, 0xa6, 0x86, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, -0x41, 0x00, 0xe8, 0x98, 0x28, 0x41, 0x00, 0xe6, 0x96, 0x29, 0x41, 0x00, 0xef, 0x9f, 0x2a, 0x05, -0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x2b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2c, 0x42, 0x04, -0xa7, 0x87, 0xa0, 0x2d, 0x42, 0x04, 0xe5, 0x95, 0xa0, 0x2e, 0x42, 0x00, 0xe7, 0x97, 0x15, 0x2f, -0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x42, -0x04, 0xac, 0x8c, 0xa0, 0x39, 0x00, 0x00, 0x20, 0x56, 0x42, 0x00, 0xf5, 0xf4, 0x15, 0x00, 0x02, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, -0x02, 0x03, 0x00, 0x00, 0xfd, 0x1b, 0x01, 0x03, 0xa0, 0xa0, 0x29, 0x01, 0x03, 0xa0, 0xa0, 0x2b, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x2c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2d, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x2e, 0x02, 0x03, 0x00, 0x00, 0x15, 0x32, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x36, 0x05, 0x3f, -0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x56, 0x02, 0x03, 0xa0, 0xa0, 0x15, 0x00, 0x02, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x43, 0x00, 0xec, 0x9c, 0x27, 0x2a, 0x10, 0x41, -0x00, 0xee, 0x9e, 0x11, 0x41, 0x00, 0xe9, 0x99, 0x12, 0x41, 0x00, 0xa5, 0x85, 0x13, 0xc1, 0x00, -0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xa9, 0x89, 0x16, 0x41, -0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xf7, 0xf6, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, -0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xf9, 0xf8, 0x1b, 0x41, 0x00, 0xa8, 0x88, 0x1e, 0x41, 0x00, 0xa0, -0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, -0x22, 0x41, 0x00, 0xf3, 0xf2, 0x23, 0x41, 0x00, 0xa3, 0x83, 0x24, 0x41, 0x00, 0xa6, 0x86, 0x25, -0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xe8, 0x98, 0x28, 0x41, -0x00, 0xe6, 0x96, 0x29, 0x41, 0x00, 0xef, 0x9f, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7d, 0x2b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2c, 0x42, 0x04, 0xa7, 0x87, 0xa0, 0x2d, 0x42, 0x04, -0xe5, 0x95, 0xa0, 0x2e, 0x42, 0x00, 0xe7, 0x97, 0x15, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, -0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x42, 0x04, 0xac, 0x8c, 0xa0, 0x39, 0x00, -0x00, 0x20, 0x56, 0x42, 0x00, 0xf5, 0xf4, 0x15, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x1b, 0x01, 0x03, 0xa0, 0xa0, 0x29, 0x01, -0x03, 0xa0, 0xa0, 0x2b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2d, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x2e, 0x02, 0x03, 0x00, 0x00, 0x15, 0x32, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x36, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x56, 0x02, 0x03, 0xa0, 0xa0, 0x15, -0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, 0x03, -0x00, 0x00, 0xd5, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x03, 0x03, 0x00, 0x00, 0x88, 0xd2, 0x16, 0x43, -0x03, 0x00, 0x00, 0x81, 0x9a, 0x17, 0x41, 0x01, 0x00, 0x98, 0x18, 0x43, 0x03, 0x00, 0x00, 0x94, -0x99, 0x1a, 0x41, 0x00, 0x84, 0x8e, 0x1b, 0x41, 0x00, 0x8d, 0x49, 0x22, 0x43, 0x03, 0x00, 0x00, -0xa7, 0xa6, 0x27, 0x41, 0x00, 0x9f, 0x9e, 0x28, 0x41, 0x00, 0xf3, 0xf4, 0x29, 0x01, 0x03, 0xa0, -0xa0, 0x2b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2d, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x56, 0x41, 0x00, 0x87, 0x80, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x03, -0x01, 0x03, 0x00, 0xc8, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x43, 0x00, 0xec, 0x9c, 0x27, 0x2a, 0x10, -0x41, 0x00, 0xee, 0x9e, 0x11, 0x41, 0x00, 0xe9, 0x99, 0x12, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x13, -0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xa9, 0x89, -0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, -0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xed, 0x9d, 0x1b, 0x41, 0x00, 0xeb, 0x9b, 0x1e, 0x41, -0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, -0xe4, 0x94, 0x22, 0x41, 0x00, 0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa6, -0x86, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xe8, 0x98, -0x28, 0x41, 0x00, 0xe6, 0x96, 0x29, 0x41, 0x00, 0xef, 0x9f, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, -0x00, 0x00, 0x80, 0x2b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2c, 0x42, 0x04, 0xa7, 0x87, 0xa0, 0x2d, -0x42, 0x04, 0xfb, 0xfa, 0xa0, 0x2e, 0x42, 0x00, 0xe7, 0x97, 0x15, 0x2f, 0x41, 0x00, 0xa2, 0x82, -0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x42, 0x04, 0xac, 0x8c, 0xa0, -0x39, 0x00, 0x00, 0x20, 0x56, 0x42, 0x00, 0xea, 0x9a, 0x15, 0x00, 0x22, 0x09, 0xa0, 0xf3, 0xa5, -0xf1, 0xae, 0xf5, 0xe3, 0xf7, 0x80, 0xf2, 0x85, 0xf0, 0x8e, 0xf4, 0x93, 0xf6, 0x20, 0x22, 0x00, -0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x08, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x12, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x1b, 0x01, 0x03, 0xa0, 0xa0, 0x29, 0x01, 0x03, 0xa0, 0xa0, -0x2b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2c, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2d, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x2e, 0x02, 0x03, 0x00, 0x00, 0x15, 0x32, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x36, 0x05, -0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x56, 0x02, 0x03, 0xa0, 0xa0, 0x15, 0x00, 0xd5, 0x6e, -0x04, 0x09, 0x00, 0x00, 0x52, 0x55, 0x2c, 0xb9, 0x01, 0x52, 0x55, 0x0c, 0x02, 0x00, 0x00, 0x00, -0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0xab, 0x01, 0x00, 0x00, 0x00, 0x00, 0x28, -0x03, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x03, 0x94, 0x02, 0x00, 0x00, 0x00, 0x00, 0x62, -0x03, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0x76, 0x03, 0x00, 0x00, 0x00, 0x00, 0x68, -0x03, 0xa2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0x5c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x57, -0x03, 0x8a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, -0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x01, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -0x02, 0x03, 0x00, 0x00, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x23, 0x05, 0x02, 0x03, 0x00, 0x00, -0xcf, 0x07, 0x02, 0x03, 0x00, 0x00, 0x5e, 0x08, 0x02, 0x03, 0x00, 0x00, 0x26, 0x09, 0x02, 0x03, -0x00, 0x00, 0x24, 0x1a, 0x02, 0x03, 0x00, 0x00, 0x5b, 0x1b, 0x02, 0x03, 0x00, 0x00, 0x5d, 0x2b, -0x02, 0x03, 0x00, 0x00, 0x7c, 0x33, 0x02, 0x03, 0x00, 0x00, 0x3c, 0x34, 0x02, 0x03, 0x00, 0x00, -0x3e, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x00, -0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xfc, 0x05, 0x02, 0x05, 0x00, 0x3b, 0xa0, -0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, -0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, -0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, -0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, -0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, -0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, -0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, -0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, -0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x01, -0x01, 0x00, 0x2f, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, -0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, -0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, -0x35, 0x01, 0x00, 0x2e, 0x2c, 0x00, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, -0x00, 0xfd, 0x36, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x79, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, -0x01, 0x01, 0x00, 0xfc, 0x05, 0x02, 0x01, 0x00, 0x3b, 0xfd, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, -0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, -0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x41, 0x00, 0xa5, 0x85, 0x15, 0x41, 0x00, -0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, -0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, -0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, -0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, -0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, -0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, -0x2a, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, 0x00, 0xef, -0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, -0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, -0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x00, 0x05, -0x02, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x03, 0x01, 0x01, -0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xef, 0x05, 0x02, 0x05, 0x00, 0x3b, 0xa0, 0x07, 0x01, 0x01, -0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xbd, 0xbe, 0x11, 0x41, 0x00, 0xa4, -0xa5, 0x12, 0x41, 0x00, 0xe7, 0xe8, 0x13, 0x41, 0x00, 0xc6, 0xc7, 0x14, 0x42, 0x00, 0xa8, 0xa9, -0xcf, 0x15, 0x41, 0x00, 0xd4, 0xd5, 0x16, 0x41, 0x00, 0xac, 0xad, 0x17, 0x41, 0x00, 0xf5, 0xf6, -0x18, 0x41, 0x00, 0xf9, 0xfa, 0x19, 0x41, 0x00, 0xf3, 0xf4, 0x1a, 0x41, 0x00, 0xb5, 0xb6, 0x1b, -0x41, 0x00, 0x9e, 0x9f, 0x1e, 0x41, 0x00, 0xaa, 0xab, 0x1f, 0x41, 0x00, 0xf1, 0xf2, 0x20, 0x41, -0x00, 0xeb, 0xec, 0x21, 0x41, 0x00, 0xa0, 0xa1, 0x22, 0x41, 0x00, 0xd8, 0xdd, 0x23, 0x41, 0x00, -0xe1, 0xe2, 0x24, 0x41, 0x00, 0xd6, 0xd7, 0x25, 0x41, 0x00, 0xd0, 0xd1, 0x26, 0x41, 0x00, 0xa6, -0xa7, 0x27, 0x41, 0x00, 0xe9, 0xea, 0x28, 0x41, 0x00, 0xf7, 0xf8, 0x29, 0x41, 0x00, 0x84, 0x85, -0x2a, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x7c, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0xc1, 0x00, 0xde, -0x2c, 0xe0, 0x00, 0x2d, 0x41, 0x00, 0xfb, 0xfc, 0x2e, 0x41, 0x00, 0xe3, 0xe4, 0x2f, 0x41, 0x00, -0xd2, 0xd3, 0x30, 0x41, 0x00, 0xb7, 0xb8, 0x31, 0x41, 0x00, 0xe5, 0xe6, 0x32, 0x41, 0x00, 0xed, -0xee, 0x33, 0x41, 0x00, 0xa2, 0xa3, 0x34, 0x41, 0x00, 0x9c, 0x9d, 0x35, 0x01, 0x00, 0x2e, 0x2c, -0x00, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xcf, 0x36, 0x03, 0x0f, -0x00, 0x00, 0x00, 0x7d, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xef, 0x05, -0x01, 0x01, 0x00, 0x3b, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, -0x00, 0xbd, 0xbe, 0x11, 0x41, 0x00, 0xa4, 0xa5, 0x12, 0x41, 0x00, 0xe7, 0xe8, 0x13, 0x41, 0x00, -0xc6, 0xc7, 0x14, 0x41, 0x00, 0xa8, 0xa9, 0x15, 0x41, 0x00, 0xd4, 0xd5, 0x16, 0x41, 0x00, 0xac, -0xad, 0x17, 0x41, 0x00, 0xf5, 0xf6, 0x18, 0x41, 0x00, 0xf9, 0xfa, 0x19, 0x41, 0x00, 0xf3, 0xf4, -0x1a, 0x41, 0x00, 0xb5, 0xb6, 0x1b, 0x41, 0x00, 0x9e, 0x9f, 0x1e, 0x41, 0x00, 0xaa, 0xab, 0x1f, -0x41, 0x00, 0xf1, 0xf2, 0x20, 0x41, 0x00, 0xeb, 0xec, 0x21, 0x41, 0x00, 0xa0, 0xa1, 0x22, 0x41, -0x00, 0xd8, 0xdd, 0x23, 0x41, 0x00, 0xe1, 0xe2, 0x24, 0x41, 0x00, 0xd6, 0xd7, 0x25, 0x41, 0x00, -0xd0, 0xd1, 0x26, 0x41, 0x00, 0xa6, 0xa7, 0x27, 0x41, 0x00, 0xe9, 0xea, 0x28, 0x41, 0x00, 0xf7, -0xf8, 0x29, 0x41, 0x00, 0x84, 0x85, 0x2a, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x7e, 0x2b, 0x01, 0x01, -0x00, 0x2f, 0x2c, 0xc1, 0x00, 0xde, 0x2c, 0xe0, 0x00, 0x2d, 0x41, 0x00, 0xfb, 0xfc, 0x2e, 0x41, -0x00, 0xe3, 0xe4, 0x2f, 0x41, 0x00, 0xd2, 0xd3, 0x30, 0x41, 0x00, 0xb7, 0xb8, 0x31, 0x41, 0x00, -0xe5, 0xe6, 0x32, 0x41, 0x00, 0xed, 0xee, 0x33, 0x41, 0x00, 0xa2, 0xa3, 0x34, 0x41, 0x00, 0x9c, -0x9d, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x00, 0x36, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x32, -0xeb, 0x04, 0x04, 0xbb, 0x01, 0x52, 0x55, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, -0x00, 0x00, 0x00, 0x28, 0x03, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0xd8, 0x00, 0x00, -0x00, 0x00, 0x00, 0x62, 0x03, 0xd8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x62, 0x03, 0xe0, 0x01, 0x00, -0x00, 0x00, 0x00, 0x68, 0x03, 0xd8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0xe1, 0x02, 0x00, -0x00, 0x00, 0x00, 0x57, 0x03, 0xdd, 0x04, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0xe7, 0x03, 0x00, -0x00, 0x00, 0x00, 0x5a, 0x03, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0xb5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x23, 0x05, -0x02, 0x03, 0x00, 0x00, 0x24, 0x07, 0x02, 0x03, 0x00, 0x00, 0x5e, 0x08, 0x02, 0x03, 0x00, 0x00, -0x26, 0x09, 0x03, 0x03, 0x00, 0x00, 0x2a, 0x1f, 0x0d, 0x03, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x1a, -0x02, 0x03, 0x00, 0x00, 0x5b, 0x1b, 0x02, 0x03, 0x00, 0x00, 0x5d, 0x33, 0x02, 0x03, 0x00, 0x00, -0x3c, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x02, -0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, -0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, -0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, -0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, -0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, -0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, -0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, -0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, -0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, -0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, -0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, -0x9d, 0x29, 0x01, 0x00, 0x7c, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x01, -0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, -0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, -0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, -0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, -0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, -0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, -0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, -0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, -0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x41, 0x00, 0xa5, 0x85, 0x15, 0x41, 0x00, 0xad, -0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, -0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, -0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, -0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, -0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, -0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0x01, 0x00, 0x7c, 0x2b, 0x2a, 0x04, 0x1f, -0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, -0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, -0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, -0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x00, 0x36, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x02, 0x01, 0x00, 0xef, 0x31, 0x03, 0x01, 0x00, -0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, -0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, -0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, -0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xbd, 0xbe, 0x11, 0x41, 0x00, 0xa4, 0xa5, 0x12, 0x41, -0x00, 0xe7, 0xe8, 0x13, 0x41, 0x00, 0xc6, 0xc7, 0x14, 0x42, 0x00, 0xa8, 0xa9, 0xcf, 0x15, 0x41, -0x00, 0xd4, 0xd5, 0x16, 0x41, 0x00, 0xac, 0xad, 0x17, 0x41, 0x00, 0xf5, 0xf6, 0x18, 0x41, 0x00, -0xf9, 0xfa, 0x19, 0x41, 0x00, 0xf3, 0xf4, 0x1a, 0x41, 0x00, 0xb5, 0xb6, 0x1b, 0x41, 0x00, 0x9e, -0x9f, 0x1e, 0x41, 0x00, 0xaa, 0xab, 0x1f, 0x41, 0x00, 0xf1, 0xf2, 0x20, 0x41, 0x00, 0xeb, 0xec, -0x21, 0x41, 0x00, 0xa0, 0xa1, 0x22, 0x41, 0x00, 0xd8, 0xdd, 0x23, 0x41, 0x00, 0xe1, 0xe2, 0x24, -0x41, 0x00, 0xd6, 0xd7, 0x25, 0x41, 0x00, 0xd0, 0xd1, 0x26, 0x41, 0x00, 0xa6, 0xa7, 0x27, 0x41, -0x00, 0xe9, 0xea, 0x28, 0x41, 0x00, 0xf7, 0xf8, 0x29, 0x01, 0x00, 0x7c, 0x2b, 0x2a, 0x04, 0x1f, -0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0xc1, 0x00, 0xde, 0x2c, 0xe0, -0x00, 0x2d, 0x41, 0x00, 0xfb, 0xfc, 0x2e, 0x41, 0x00, 0xe3, 0xe4, 0x2f, 0x41, 0x00, 0xd2, 0xd3, -0x30, 0x41, 0x00, 0xb7, 0xb8, 0x31, 0x41, 0x00, 0xe5, 0xe6, 0x32, 0x41, 0x00, 0xed, 0xee, 0x33, -0x41, 0x00, 0xa2, 0xa3, 0x34, 0x41, 0x00, 0x9c, 0x9d, 0x35, 0x41, 0x00, 0x84, 0x85, 0x00, 0x12, -0x42, 0x03, 0x00, 0x00, 0xcf, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x02, 0x01, -0x00, 0xef, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, -0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, -0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, -0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xbd, 0xbe, 0x11, -0x41, 0x00, 0xa4, 0xa5, 0x12, 0x41, 0x00, 0xe7, 0xe8, 0x13, 0x41, 0x00, 0xc6, 0xc7, 0x14, 0x41, -0x00, 0xa8, 0xa9, 0x15, 0x41, 0x00, 0xd4, 0xd5, 0x16, 0x41, 0x00, 0xac, 0xad, 0x17, 0x41, 0x00, -0xf5, 0xf6, 0x18, 0x41, 0x00, 0xf9, 0xfa, 0x19, 0x41, 0x00, 0xf3, 0xf4, 0x1a, 0x41, 0x00, 0xb5, -0xb6, 0x1b, 0x41, 0x00, 0x9e, 0x9f, 0x1e, 0x41, 0x00, 0xaa, 0xab, 0x1f, 0x41, 0x00, 0xf1, 0xf2, -0x20, 0x41, 0x00, 0xeb, 0xec, 0x21, 0x41, 0x00, 0xa0, 0xa1, 0x22, 0x41, 0x00, 0xd8, 0xdd, 0x23, -0x41, 0x00, 0xe1, 0xe2, 0x24, 0x41, 0x00, 0xd6, 0xd7, 0x25, 0x41, 0x00, 0xd0, 0xd1, 0x26, 0x41, -0x00, 0xa6, 0xa7, 0x27, 0x41, 0x00, 0xe9, 0xea, 0x28, 0x41, 0x00, 0xf7, 0xf8, 0x29, 0x01, 0x00, -0x7c, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, -0xc1, 0x00, 0xde, 0x2c, 0xe0, 0x00, 0x2d, 0x41, 0x00, 0xfb, 0xfc, 0x2e, 0x41, 0x00, 0xe3, 0xe4, -0x2f, 0x41, 0x00, 0xd2, 0xd3, 0x30, 0x41, 0x00, 0xb7, 0xb8, 0x31, 0x41, 0x00, 0xe5, 0xe6, 0x32, -0x41, 0x00, 0xed, 0xee, 0x33, 0x41, 0x00, 0xa2, 0xa3, 0x34, 0x41, 0x00, 0x9c, 0x9d, 0x35, 0x41, -0x00, 0x84, 0x85, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xbb, 0xfe, 0x07, -0x09, 0x00, 0x00, 0x52, 0x58, 0x2c, 0xb9, 0x01, 0x52, 0x58, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, -0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x75, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x75, -0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x75, 0xdb, 0x02, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x75, -0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x75, 0xda, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x75, -0xea, 0x02, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x75, 0xd1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x75, -0xe9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x75, 0xca, 0x05, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x75, -0xe0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x75, 0xc7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x40, 0x75, -0xd9, 0x05, 0x00, 0x00, 0x00, 0x00, 0x41, 0x75, 0xb4, 0x07, 0x00, 0x00, 0x00, 0x00, 0x41, 0x75, -0xd6, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, -0x03, 0x00, 0x00, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x23, 0x07, 0x02, 0x03, 0x00, 0x00, 0x5e, -0x08, 0x02, 0x03, 0x00, 0x00, 0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x24, 0x0c, 0x03, 0x03, 0x00, -0x00, 0x5b, 0x7b, 0x1a, 0x03, 0x03, 0x00, 0x00, 0x5b, 0x7b, 0x1b, 0x03, 0x03, 0x00, 0x00, 0x5d, -0x7d, 0x2b, 0x02, 0x03, 0x00, 0x00, 0x7c, 0x33, 0x02, 0x03, 0x00, 0x00, 0x3c, 0x34, 0x02, 0x03, -0x00, 0x00, 0x3e, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xfc, 0x05, 0x01, -0x01, 0x00, 0x3b, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x0d, 0x02, 0x02, -0xfe, 0x00, 0x3d, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x43, 0x00, 0xe6, 0x96, 0xf7, 0xf6, 0x12, -0x43, 0x00, 0xe3, 0x93, 0xb8, 0xb5, 0x13, 0x43, 0x00, 0xaa, 0x8a, 0xd1, 0xcf, 0x14, 0x42, 0x00, -0xa5, 0x85, 0xfd, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xfb, 0xfa, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, -0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x43, -0x00, 0xe5, 0x95, 0xc6, 0xbe, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, -0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x43, 0x00, 0xa0, 0x80, 0xd5, 0xd4, -0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, -0x8e, 0xf5, 0xf4, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, 0x00, -0xa6, 0x86, 0xf9, 0xf8, 0x28, 0x43, 0x00, 0xed, 0x9d, 0xf3, 0xf2, 0x29, 0xc1, 0x00, 0xf1, 0x29, -0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, -0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, -0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, -0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, 0x2e, -0x2c, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, -0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xfc, 0x05, 0x02, 0x01, 0x00, 0x3b, -0xfd, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x43, 0x00, 0xa9, 0x89, -0xd2, 0xd1, 0x11, 0x43, 0x00, 0xe6, 0x96, 0xb6, 0xb5, 0x12, 0x43, 0x00, 0xe3, 0x93, 0xf7, 0xf6, -0x13, 0x43, 0x00, 0xaa, 0x8a, 0xd6, 0xd5, 0x14, 0x43, 0x00, 0xa5, 0x85, 0xfb, 0xfa, 0x15, 0x43, -0x00, 0xad, 0x8d, 0xd4, 0xd3, 0x16, 0x43, 0x00, 0xa3, 0x83, 0xd8, 0xd7, 0x17, 0x43, 0x00, 0xe8, -0x98, 0xb8, 0xb7, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x43, 0x00, -0xe5, 0x95, 0xbe, 0xbd, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, -0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, -0xaf, 0x8f, 0x23, 0xc3, 0x00, 0xe0, 0x00, 0x90, 0x23, 0xf9, 0x23, 0xf8, 0x23, 0x24, 0x43, 0x00, -0xae, 0x8e, 0xf3, 0xf2, 0x25, 0x43, 0x00, 0xab, 0x8b, 0xf5, 0xf4, 0x26, 0x41, 0x00, 0xa4, 0x84, -0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, -0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, -0x00, 0xef, 0x9f, 0x2d, 0x43, 0x00, 0xe7, 0x97, 0xc7, 0xc6, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, -0x41, 0x00, 0xac, 0x8c, 0x30, 0x43, 0x00, 0xa8, 0x88, 0xd0, 0xcf, 0x31, 0x41, 0x00, 0xe2, 0x92, -0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, -0x01, 0x00, 0x2e, 0x2c, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x7b, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xfc, 0x05, 0x02, -0x01, 0x00, 0x3b, 0xfd, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, -0x00, 0xa9, 0x89, 0x11, 0x43, 0x00, 0xe6, 0x96, 0xd4, 0xd3, 0x12, 0x43, 0x00, 0xe3, 0x93, 0xb8, -0xb5, 0x13, 0x43, 0x00, 0xaa, 0x8a, 0xc7, 0xbd, 0x14, 0x43, 0x00, 0xa5, 0x85, 0xf7, 0xf6, 0x15, -0x43, 0x00, 0xad, 0x8d, 0xfb, 0xfa, 0x16, 0x43, 0x00, 0xa3, 0x83, 0xb7, 0xb6, 0x17, 0x41, 0x00, -0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x43, 0x00, 0xa7, 0x87, 0xd6, 0xd5, 0x1a, 0x43, -0x00, 0xe5, 0x95, 0xc6, 0xbe, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, -0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x43, 0x00, 0xa0, 0x80, 0xf3, 0xf2, -0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, -0x8e, 0xf5, 0xf4, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, 0x00, -0xa6, 0x86, 0xd2, 0xd1, 0x28, 0x43, 0x00, 0xed, 0x9d, 0xd0, 0xcf, 0x29, 0xc1, 0x00, 0xf1, 0x29, -0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, -0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x43, 0x00, 0xe1, 0x91, 0xd8, 0xd7, -0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, -0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, -0x00, 0x2e, 0x2c, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x7d, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xfc, 0x05, 0x01, 0x01, -0x00, 0x3b, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xa9, -0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x43, 0x00, 0xe3, 0x93, 0xf7, 0xf6, 0x13, 0x41, 0x00, -0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xd5, 0xd4, 0x16, -0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x43, -0x00, 0xa7, 0x87, 0xc6, 0xbe, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, -0x41, 0x00, 0xe4, 0x94, 0x1f, 0x43, 0x00, 0xeb, 0x9b, 0xfb, 0xfa, 0x20, 0x41, 0x00, 0xa2, 0x82, -0x21, 0x43, 0x00, 0xa0, 0x80, 0xf3, 0xf2, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, -0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, 0x8e, 0xf5, 0xf4, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, -0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, 0x00, 0xa6, 0x86, 0xb8, 0xb5, 0x28, 0x41, 0x00, 0xed, 0x9d, -0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x2b, -0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x43, 0x00, 0xe7, 0x97, 0xd1, 0xcf, -0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x43, 0x00, 0xa8, 0x88, 0xf9, -0xf8, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, -0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, -0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, -0x01, 0x01, 0x00, 0xfc, 0x05, 0x01, 0x01, 0x00, 0x3b, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, -0x01, 0x00, 0x3f, 0x10, 0x43, 0x00, 0xa9, 0x89, 0xde, 0xdd, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, -0x43, 0x00, 0xe3, 0x93, 0xf7, 0xf6, 0x13, 0x43, 0x00, 0xaa, 0x8a, 0xd5, 0xd4, 0x14, 0x42, 0x00, -0xa5, 0x85, 0xfd, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xd1, 0xcf, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, -0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, -0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, -0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x43, 0x00, 0xa0, 0x80, 0xf3, 0xf2, 0x22, 0x41, -0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, 0x8e, 0xf5, -0xf4, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, 0x00, 0xa6, 0x86, -0xfb, 0xfa, 0x28, 0x43, 0x00, 0xed, 0x9d, 0xc6, 0xbe, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, -0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x43, 0x00, -0xef, 0x9f, 0xb8, 0xb5, 0x2d, 0x43, 0x00, 0xe7, 0x97, 0xf9, 0xf8, 0x2e, 0x41, 0x00, 0xe1, 0x91, -0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, -0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, -0x00, 0x2e, 0x2c, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x81, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xfc, 0x05, 0x02, 0x01, -0x00, 0x3b, 0xfd, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, -0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x43, 0x00, 0xe3, 0x93, 0xf7, 0xf6, 0x13, 0x41, -0x00, 0xaa, 0x8a, 0x14, 0x43, 0x00, 0xa5, 0x85, 0xdd, 0xdc, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xdf, -0xde, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, -0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, -0x41, 0x00, 0xe4, 0x94, 0x1f, 0x43, 0x00, 0xeb, 0x9b, 0xfb, 0xfa, 0x20, 0x41, 0x00, 0xa2, 0x82, -0x21, 0x43, 0x00, 0xa0, 0x80, 0xf3, 0xf2, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, -0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, 0x8e, 0xf5, 0xf4, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, -0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x43, 0x00, 0xed, 0x9d, 0xc6, 0xbe, -0x29, 0xc3, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0xb8, 0x29, 0xb5, 0x29, 0x2a, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x82, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x43, 0x00, 0xef, 0x9f, 0xd5, 0xd4, 0x2d, -0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x43, -0x00, 0xa8, 0x88, 0xf9, 0xf8, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, -0x41, 0x00, 0xa1, 0x81, 0x34, 0x43, 0x00, 0xee, 0x9e, 0xd1, 0xcf, 0x35, 0x01, 0x00, 0x2e, 0x2c, -0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, -0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xfc, 0x05, 0x01, 0x01, 0x00, 0x3b, 0x07, -0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, -0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, -0xa5, 0x85, 0xfd, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xb8, 0xb5, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, -0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, -0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, -0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, -0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, 0x8e, 0xf5, 0xf4, 0x25, -0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x43, -0x00, 0xed, 0x9d, 0xc6, 0xbe, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, -0x00, 0x00, 0x00, 0x84, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, -0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x43, 0x00, -0xa8, 0x88, 0xd1, 0xcf, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, -0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x00, 0x12, 0x42, -0x03, 0x00, 0x00, 0xfd, 0x16, 0x43, 0x03, 0x00, 0x00, 0xf7, 0xf6, 0x18, 0x43, 0x03, 0x00, 0x00, -0xf5, 0xf4, 0x1e, 0x43, 0x03, 0x00, 0x00, 0xf3, 0xf2, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xfb, 0xfa, -0x2c, 0x43, 0x03, 0x00, 0x00, 0xd5, 0xd4, 0x2d, 0x43, 0x03, 0x00, 0x00, 0xde, 0xdd, 0x2e, 0x43, -0x03, 0x00, 0x00, 0xf9, 0xf8, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x92, 0xe0, -0x08, 0x04, 0xbb, 0x01, 0x52, 0x58, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3b, 0x75, 0xed, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x75, 0xe1, 0x00, 0x00, 0x00, -0x00, 0x00, 0x3c, 0x75, 0x13, 0x03, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x75, 0xfc, 0x01, 0x00, 0x00, -0x00, 0x00, 0x3d, 0x75, 0x35, 0x04, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x75, 0x22, 0x03, 0x00, 0x00, -0x00, 0x00, 0x3e, 0x75, 0x4f, 0x05, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x75, 0x44, 0x04, 0x00, 0x00, -0x00, 0x00, 0x3f, 0x75, 0x6b, 0x06, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x75, 0x5e, 0x05, 0x00, 0x00, -0x00, 0x00, 0x40, 0x75, 0x8b, 0x07, 0x00, 0x00, 0x00, 0x00, 0x40, 0x75, 0x7a, 0x06, 0x00, 0x00, -0x00, 0x00, 0x41, 0x75, 0x9b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x75, 0x9a, 0x07, 0x00, 0x00, -0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0x40, -0x04, 0x02, 0x03, 0x00, 0x00, 0x23, 0x05, 0x02, 0x03, 0x00, 0x00, 0x24, 0x07, 0x02, 0x03, 0x00, -0x00, 0x5e, 0x08, 0x02, 0x03, 0x00, 0x00, 0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x2a, 0x1a, 0x02, -0x03, 0x00, 0x00, 0x5b, 0x1b, 0x02, 0x03, 0x00, 0x00, 0x5d, 0x33, 0x02, 0x03, 0x00, 0x00, 0x3c, -0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x00, 0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, -0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, -0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, -0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, -0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x43, 0x00, 0xe6, 0x96, 0xf7, 0xf6, 0x12, -0x43, 0x00, 0xe3, 0x93, 0xb8, 0xb5, 0x13, 0x43, 0x00, 0xaa, 0x8a, 0xd1, 0xcf, 0x14, 0x42, 0x00, -0xa5, 0x85, 0xfd, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xfb, 0xfa, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, -0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x43, -0x00, 0xe5, 0x95, 0xc6, 0xbe, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, -0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x43, 0x00, 0xa0, 0x80, 0xd5, 0xd4, -0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, -0x8e, 0xf5, 0xf4, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, 0x00, -0xa6, 0x86, 0xf9, 0xf8, 0x28, 0x43, 0x00, 0xed, 0x9d, 0xf3, 0xf2, 0x29, 0x02, 0x00, 0xfe, 0x2b, -0x7c, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, -0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, -0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, -0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0xc1, 0x00, 0xf1, 0x35, -0xf0, 0x00, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x79, 0x00, 0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, -0x33, 0x05, 0x02, 0x00, 0x22, 0x34, 0xfd, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, -0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, -0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, -0x43, 0x00, 0xa9, 0x89, 0xd2, 0xd1, 0x11, 0x43, 0x00, 0xe6, 0x96, 0xb6, 0xb5, 0x12, 0x43, 0x00, -0xe3, 0x93, 0xf7, 0xf6, 0x13, 0x43, 0x00, 0xaa, 0x8a, 0xd6, 0xd5, 0x14, 0x43, 0x00, 0xa5, 0x85, -0xfb, 0xfa, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xd4, 0xd3, 0x16, 0x43, 0x00, 0xa3, 0x83, 0xd8, 0xd7, -0x17, 0x43, 0x00, 0xe8, 0x98, 0xb8, 0xb7, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, -0x87, 0x1a, 0x43, 0x00, 0xe5, 0x95, 0xbe, 0xbd, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, -0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, -0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc3, 0x00, 0xe0, 0x00, 0x90, 0x23, 0xf9, 0x23, 0xf8, -0x23, 0x24, 0x43, 0x00, 0xae, 0x8e, 0xf3, 0xf2, 0x25, 0x43, 0x00, 0xab, 0x8b, 0xf5, 0xf4, 0x26, -0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0x01, -0x00, 0x7c, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x01, 0x00, 0x29, 0x28, -0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x43, 0x00, 0xe7, 0x97, 0xc7, 0xc6, 0x2e, 0x41, 0x00, 0xe1, -0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x43, 0x00, 0xa8, 0x88, 0xd0, 0xcf, 0x31, 0x41, 0x00, -0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, -0x9e, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, -0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x02, 0x00, 0x22, 0x34, 0xfd, 0x06, 0x01, 0x00, -0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, -0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, -0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x43, 0x00, 0xe6, 0x96, 0xd4, -0xd3, 0x12, 0x43, 0x00, 0xe3, 0x93, 0xb8, 0xb5, 0x13, 0x43, 0x00, 0xaa, 0x8a, 0xc7, 0xbd, 0x14, -0x43, 0x00, 0xa5, 0x85, 0xf7, 0xf6, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xfb, 0xfa, 0x16, 0x43, 0x00, -0xa3, 0x83, 0xb7, 0xb6, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x43, -0x00, 0xa7, 0x87, 0xd6, 0xd5, 0x1a, 0x43, 0x00, 0xe5, 0x95, 0xc6, 0xbe, 0x1b, 0x41, 0x00, 0xea, -0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, -0x21, 0x43, 0x00, 0xa0, 0x80, 0xf3, 0xf2, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, -0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, 0x8e, 0xf5, 0xf4, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, -0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, 0x00, 0xa6, 0x86, 0xd2, 0xd1, 0x28, 0x43, 0x00, 0xed, 0x9d, -0xd0, 0xcf, 0x29, 0x01, 0x00, 0x7c, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, -0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x43, -0x00, 0xe1, 0x91, 0xd8, 0xd7, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, -0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, -0x00, 0xee, 0x9e, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, -0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, -0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, 0x06, 0x01, -0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, -0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, -0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, -0x12, 0x43, 0x00, 0xe3, 0x93, 0xf7, 0xf6, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, -0x85, 0xfd, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xd5, 0xd4, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, -0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x43, 0x00, 0xa7, 0x87, 0xc6, 0xbe, 0x1a, -0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x43, -0x00, 0xeb, 0x9b, 0xfb, 0xfa, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x43, 0x00, 0xa0, 0x80, 0xf3, -0xf2, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x43, 0x00, -0xae, 0x8e, 0xf5, 0xf4, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, -0x00, 0xa6, 0x86, 0xb8, 0xb5, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0x01, 0x00, 0x7c, 0x2b, 0x2a, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, -0x9f, 0x2d, 0x43, 0x00, 0xe7, 0x97, 0xd1, 0xcf, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, -0xac, 0x8c, 0x30, 0x43, 0x00, 0xa8, 0x88, 0xf9, 0xf8, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, -0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0xc1, 0x00, -0xf1, 0x35, 0xf0, 0x00, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x7f, 0x00, 0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, -0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, -0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, -0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, -0x10, 0x43, 0x00, 0xa9, 0x89, 0xde, 0xdd, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x43, 0x00, 0xe3, -0x93, 0xf7, 0xf6, 0x13, 0x43, 0x00, 0xaa, 0x8a, 0xd5, 0xd4, 0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, -0x15, 0x43, 0x00, 0xad, 0x8d, 0xd1, 0xcf, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, -0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, -0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, -0x41, 0x00, 0xa2, 0x82, 0x21, 0x43, 0x00, 0xa0, 0x80, 0xf3, 0xf2, 0x22, 0x41, 0x00, 0xaf, 0x8f, -0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, 0x8e, 0xf5, 0xf4, 0x25, 0x41, -0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, 0x00, 0xa6, 0x86, 0xfb, 0xfa, 0x28, -0x43, 0x00, 0xed, 0x9d, 0xc6, 0xbe, 0x29, 0x01, 0x00, 0x7c, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x80, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x43, 0x00, 0xef, 0x9f, 0xb8, 0xb5, 0x2d, -0x43, 0x00, 0xe7, 0x97, 0xf9, 0xf8, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, -0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, -0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, -0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, -0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, -0x02, 0x00, 0x22, 0x34, 0xfd, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, -0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, -0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, -0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x43, 0x00, 0xe3, 0x93, 0xf7, 0xf6, 0x13, 0x41, -0x00, 0xaa, 0x8a, 0x14, 0x43, 0x00, 0xa5, 0x85, 0xdd, 0xdc, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xdf, -0xde, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, -0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, -0x41, 0x00, 0xe4, 0x94, 0x1f, 0x43, 0x00, 0xeb, 0x9b, 0xfb, 0xfa, 0x20, 0x41, 0x00, 0xa2, 0x82, -0x21, 0x43, 0x00, 0xa0, 0x80, 0xf3, 0xf2, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, -0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, 0x8e, 0xf5, 0xf4, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, -0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x43, 0x00, 0xed, 0x9d, 0xc6, 0xbe, -0x29, 0x01, 0x00, 0x7c, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x82, 0x2b, 0x01, 0x00, -0x29, 0x28, 0x2c, 0x43, 0x00, 0xef, 0x9f, 0xd5, 0xd4, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, -0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x43, 0x00, 0xa8, 0x88, 0xf9, 0xf8, 0x31, -0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x43, -0x00, 0xee, 0x9e, 0xd1, 0xcf, 0x35, 0xc3, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0xb8, 0x35, 0xb5, 0x35, -0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, -0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, -0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, -0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, -0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, -0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, -0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xb8, 0xb5, 0x16, 0x41, 0x00, -0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, -0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, -0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, -0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, 0x8e, -0xf5, 0xf4, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, -0x86, 0x28, 0x43, 0x00, 0xed, 0x9d, 0xc6, 0xbe, 0x29, 0x01, 0x00, 0x7c, 0x2b, 0x2a, 0x04, 0x1f, -0x00, 0x00, 0x00, 0x00, 0x84, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, -0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x43, -0x00, 0xa8, 0x88, 0xd1, 0xcf, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, -0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, -0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x16, 0x43, 0x03, 0x00, 0x00, 0xf7, 0xf6, 0x18, 0x43, -0x03, 0x00, 0x00, 0xf5, 0xf4, 0x1e, 0x43, 0x03, 0x00, 0x00, 0xf3, 0xf2, 0x1f, 0x43, 0x03, 0x00, -0x00, 0xfb, 0xfa, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xd5, 0xd4, 0x2d, 0x43, 0x03, 0x00, 0x00, 0xde, -0xdd, 0x2e, 0x43, 0x03, 0x00, 0x00, 0xf9, 0xf8, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x85, -0x00, 0x4d, 0x4e, 0x03, 0x09, 0x00, 0x00, 0x54, 0x52, 0x2c, 0xb3, 0x00, 0x54, 0x52, 0x05, 0x04, -0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x03, 0xbb, 0x01, 0xdd, 0x01, -0x00, 0x00, 0x55, 0x03, 0x60, 0x02, 0xb7, 0x02, 0x00, 0x00, 0x5a, 0x03, 0x00, 0x00, 0x44, 0x01, -0x00, 0x00, 0x52, 0x03, 0x3d, 0x01, 0x44, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, -0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x3e, -0x03, 0x02, 0x01, 0x00, 0x27, 0x9c, 0x04, 0x03, 0x03, 0x00, 0xc8, 0x23, 0x1e, 0x05, 0x02, 0x01, -0x00, 0x2b, 0x24, 0x06, 0x02, 0x03, 0x00, 0x00, 0xab, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, 0x02, -0x01, 0x00, 0x2f, 0x7b, 0x09, 0x03, 0x01, 0x00, 0x28, 0x5b, 0x1b, 0x0a, 0x03, 0x01, 0x00, 0x29, -0x5d, 0x1d, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, 0x03, 0x00, 0x2a, 0x3f, 0x5c, 0x1c, 0x0d, -0x03, 0x00, 0x2d, 0x5f, 0x7c, 0x1f, 0x10, 0x42, 0x03, 0x00, 0x00, 0x40, 0x12, 0x42, 0x00, 0x65, -0x45, 0xd5, 0x13, 0x42, 0x03, 0x00, 0x00, 0xf4, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, -0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x19, 0x42, 0x03, 0x00, -0x00, 0x9c, 0x1a, 0x02, 0x07, 0xa0, 0xa0, 0xc9, 0x1b, 0x42, 0x04, 0x81, 0x9a, 0xca, 0x1e, 0x44, -0x08, 0x61, 0x41, 0x91, 0x00, 0x92, 0x1f, 0x42, 0x03, 0x00, 0x00, 0xe1, 0x27, 0x02, 0x07, 0xa0, -0xa0, 0xcb, 0x28, 0xc5, 0x00, 0x69, 0x17, 0x49, 0x17, 0x00, 0x17, 0x09, 0x17, 0x00, 0x17, 0x00, -0x17, 0x29, 0x02, 0x00, 0x22, 0x82, 0x3c, 0x2b, 0x02, 0x04, 0x2c, 0x3b, 0xcc, 0x2c, 0x42, 0x03, -0x00, 0x00, 0xae, 0x2d, 0x42, 0x03, 0x00, 0x00, 0xaf, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x33, 0x42, -0x00, 0x94, 0x99, 0x3c, 0x34, 0x42, 0x00, 0x87, 0x80, 0x3e, 0x35, 0x02, 0x00, 0x2e, 0x3a, 0x7c, -0x39, 0x00, 0x00, 0x20, 0x56, 0x02, 0x00, 0x3c, 0x3e, 0x7c, 0x00, 0x12, 0x42, 0x07, 0x00, 0x00, -0xa0, 0x00, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, -0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, -0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, -0x55, 0x9a, 0x20, 0xf9, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, -0x4f, 0xe5, 0x20, 0x7e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, -0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, -0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, -0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x00, 0x17, 0x44, 0x0a, 0x8d, 0x00, 0x69, 0x00, -0x98, 0x1a, 0x41, 0x00, 0xa7, 0xa6, 0x27, 0x41, 0x00, 0x9f, 0x9e, 0x28, 0xc5, 0x00, 0x69, 0x17, -0x98, 0x17, 0x00, 0x17, 0x09, 0x17, 0x00, 0x17, 0x00, 0x17, 0x00, 0x5e, 0x0d, 0x61, 0x83, 0x65, -0x88, 0x8d, 0x8c, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x98, -0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf9, 0x0e, 0x61, 0x84, 0x65, 0x89, 0x8d, 0x8b, 0x69, -0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0xed, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x98, 0xd8, 0x4f, -0x99, 0x55, 0x9a, 0x20, 0xf9, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, -0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x8d, 0xa1, 0x69, 0xa1, 0x6f, -0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x98, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x20, -0xef, 0x60, 0x0d, 0x61, 0x85, 0x65, 0x8a, 0x8d, 0xec, 0x69, 0xec, 0x6f, 0x95, 0x75, 0x97, 0x41, -0xb7, 0x45, 0xd4, 0x49, 0xde, 0x98, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x00, 0x12, 0x42, -0x07, 0x00, 0x00, 0xa0, 0x13, 0x42, 0x03, 0x00, 0x00, 0x14, 0x16, 0x44, 0x0b, 0x00, 0x00, 0xed, -0x00, 0xec, 0x17, 0x44, 0x0a, 0xd5, 0x00, 0x69, 0x00, 0x98, 0x1a, 0x41, 0x00, 0xa7, 0xa6, 0x1e, -0x44, 0x1f, 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x22, 0x41, 0x00, 0x67, -0x47, 0x23, 0x41, 0x00, 0x68, 0x48, 0x24, 0x41, 0x00, 0x6a, 0x4a, 0x27, 0x41, 0x00, 0xad, 0xb8, -0x28, 0xc5, 0x00, 0x69, 0x17, 0x98, 0x17, 0x00, 0x17, 0x09, 0x17, 0x00, 0x17, 0x00, 0x17, 0x2e, -0x41, 0x00, 0x63, 0x43, 0x00, 0x5e, 0x17, 0x61, 0x83, 0x63, 0x86, 0x65, 0x88, 0x67, 0x9b, 0x68, -0xa9, 0xd5, 0x8c, 0x69, 0x8c, 0x6a, 0x9f, 0x6f, 0x93, 0x73, 0xc7, 0x75, 0x96, 0x41, 0xb6, 0x43, -0x8f, 0x45, 0xd2, 0x47, 0x9d, 0x48, 0xa8, 0x49, 0xd7, 0x98, 0xd7, 0x4a, 0xac, 0x4f, 0xe2, 0x53, -0xc6, 0x55, 0xea, 0x20, 0x5e, 0xf9, 0x0d, 0x61, 0x84, 0x65, 0x89, 0xd5, 0x8b, 0x69, 0x8b, 0x6f, -0x94, 0x75, 0x81, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x98, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, -0xf9, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0xd5, -0xa1, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x98, 0xd6, 0x4f, -0xe0, 0x55, 0xe9, 0x20, 0xef, 0x60, 0x0d, 0x61, 0x85, 0x65, 0x8a, 0xd5, 0x8d, 0x69, 0x8d, 0x6f, -0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x98, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, -0x60, 0x00, 0x50, 0x0b, 0x05, 0x04, 0xb8, 0x01, 0x54, 0x52, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, -0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x03, 0xec, 0x02, 0x42, 0x03, 0x00, 0x00, 0x55, 0x03, -0xc5, 0x03, 0x79, 0x04, 0x00, 0x00, 0x52, 0x03, 0x65, 0x02, 0x75, 0x02, 0x00, 0x00, 0x5a, 0x03, -0x00, 0x00, 0x75, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x0b, 0x00, 0x00, 0xfb, 0x00, 0xad, 0x03, 0x02, -0x01, 0x00, 0x22, 0xfd, 0x04, 0x04, 0x03, 0x00, 0xc8, 0x23, 0x1e, 0xfc, 0x05, 0x04, 0x0b, 0x00, -0x00, 0xac, 0x00, 0xcf, 0x06, 0x02, 0x03, 0x00, 0x00, 0xab, 0x07, 0x02, 0x01, 0x00, 0x26, 0xf3, -0x08, 0x02, 0x01, 0x00, 0x27, 0x7b, 0x09, 0x03, 0x01, 0x00, 0x28, 0x5b, 0x1b, 0x0a, 0x03, 0x01, -0x00, 0x29, 0x5d, 0x1d, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, 0x04, 0x00, 0x2f, 0x3f, 0x5c, -0x1c, 0xa8, 0x0d, 0x03, 0x00, 0x2d, 0x5f, 0x7c, 0x1f, 0x10, 0xc5, 0x00, 0x66, 0x21, 0x46, 0x21, -0x40, 0x21, 0x06, 0x21, 0x00, 0x21, 0x00, 0x21, 0x11, 0xc5, 0x00, 0x67, 0x22, 0x47, 0x22, 0x00, -0x22, 0x07, 0x22, 0x00, 0x22, 0x00, 0x22, 0x12, 0x10, 0x00, 0x00, 0x13, 0xc5, 0x00, 0x69, 0x17, -0x49, 0x17, 0xf4, 0x17, 0x09, 0x17, 0xa9, 0x17, 0x00, 0x17, 0x14, 0xc5, 0x00, 0x6f, 0x18, 0x4f, -0x18, 0x00, 0x18, 0x0f, 0x18, 0x00, 0x18, 0x00, 0x18, 0x15, 0xc5, 0x00, 0x64, 0x20, 0x44, 0x20, -0xbe, 0x20, 0x04, 0x20, 0x00, 0x20, 0x00, 0x20, 0x16, 0xc5, 0x00, 0x72, 0x13, 0x52, 0x13, 0x00, -0x13, 0x12, 0x13, 0x00, 0x13, 0x00, 0x13, 0x17, 0xc5, 0x00, 0x6e, 0x31, 0x4e, 0x31, 0x00, 0x31, -0x0e, 0x31, 0x00, 0x31, 0x00, 0x31, 0x18, 0xc5, 0x00, 0x68, 0x23, 0x48, 0x23, 0x9b, 0x23, 0x08, -0x23, 0x9d, 0x23, 0x00, 0x23, 0x19, 0x42, 0x03, 0x00, 0x00, 0x9c, 0x1a, 0xc5, 0x04, 0x71, 0x10, -0x51, 0x10, 0xc9, 0x10, 0x11, 0x10, 0x00, 0x10, 0x00, 0x10, 0x1b, 0xc5, 0x04, 0x77, 0x11, 0x57, -0x11, 0xca, 0x11, 0x17, 0x11, 0x00, 0x11, 0x00, 0x11, 0x1e, 0xc5, 0x00, 0x75, 0x16, 0x55, 0x16, -0x91, 0x16, 0x15, 0x16, 0x92, 0x16, 0x00, 0x16, 0x1f, 0xc5, 0x00, 0x69, 0x17, 0x49, 0x17, 0xe1, -0x17, 0x09, 0x17, 0xf5, 0x17, 0x00, 0x17, 0x20, 0xc5, 0x00, 0x65, 0x12, 0x45, 0x12, 0xd5, 0x12, -0x05, 0x12, 0x00, 0x12, 0x00, 0x12, 0x21, 0xc5, 0x00, 0x61, 0x1e, 0x41, 0x1e, 0x00, 0x1e, 0x01, -0x1e, 0xa6, 0x1e, 0x00, 0x1e, 0x22, 0x41, 0x00, 0x81, 0x9a, 0x23, 0xc5, 0x00, 0x74, 0x14, 0x54, -0x14, 0x00, 0x14, 0x14, 0x14, 0x00, 0x14, 0x00, 0x14, 0x24, 0xc5, 0x00, 0x6b, 0x25, 0x4b, 0x25, -0x00, 0x25, 0x0b, 0x25, 0x00, 0x25, 0x00, 0x25, 0x25, 0xc5, 0x00, 0x6d, 0x32, 0x4d, 0x32, 0x00, -0x32, 0x0d, 0x32, 0x00, 0x32, 0x00, 0x32, 0x27, 0xc5, 0x04, 0x79, 0x15, 0x59, 0x15, 0xcb, 0x15, -0x19, 0x15, 0x00, 0x15, 0x00, 0x15, 0x28, 0x10, 0x00, 0x00, 0x29, 0x02, 0x00, 0x2b, 0x2a, 0xaa, -0x2b, 0xc5, 0x04, 0x78, 0x2d, 0x58, 0x2d, 0xcc, 0x2d, 0x18, 0x2d, 0x00, 0x2d, 0x00, 0x2d, 0x2c, -0xc5, 0x00, 0x6a, 0x24, 0x4a, 0x24, 0xae, 0x24, 0x0a, 0x24, 0x3c, 0x24, 0x00, 0x24, 0x2d, 0x44, -0x08, 0x94, 0x99, 0xaf, 0x00, 0x3e, 0x2e, 0xc5, 0x00, 0x76, 0x2f, 0x56, 0x2f, 0xbd, 0x2f, 0x16, -0x2f, 0xb8, 0x2f, 0x00, 0x2f, 0x2f, 0xc5, 0x00, 0x63, 0x2e, 0x43, 0x2e, 0x3c, 0x2e, 0x03, 0x2e, -0x00, 0x2e, 0x00, 0x2e, 0x30, 0x42, 0x00, 0x87, 0x80, 0x3e, 0x31, 0xc5, 0x00, 0x7a, 0x2c, 0x5a, -0x2c, 0x7c, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x32, 0xc5, 0x00, 0x73, 0x1f, 0x53, 0x1f, -0xe6, 0x1f, 0x13, 0x1f, 0xa7, 0x1f, 0x00, 0x1f, 0x33, 0xc5, 0x00, 0x62, 0x30, 0x42, 0x30, 0x9e, -0x30, 0x02, 0x30, 0x00, 0x30, 0x00, 0x30, 0x34, 0x02, 0x01, 0x00, 0x3a, 0xf6, 0x35, 0x02, 0x00, -0x2c, 0x3b, 0x2d, 0x39, 0x00, 0x00, 0x20, 0x56, 0x03, 0x00, 0x3c, 0x3e, 0x7c, 0x1c, 0x00, 0x20, -0xc5, 0x04, 0x65, 0x12, 0x45, 0x12, 0xa0, 0x12, 0x05, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x5e, -0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, -0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, -0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, -0xf9, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, -0x7e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, -0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0x60, 0x0b, 0x61, -0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, -0xe3, 0x55, 0xeb, 0x20, 0x60, 0x00, 0x12, 0x41, 0x00, 0xa7, 0xa6, 0x13, 0xc5, 0x00, 0x8d, 0x17, -0x49, 0x17, 0xf4, 0x17, 0x09, 0x17, 0xa9, 0x17, 0x00, 0x17, 0x1f, 0xc5, 0x00, 0x69, 0x17, 0x98, -0x17, 0xe1, 0x17, 0x09, 0x17, 0xf5, 0x17, 0x00, 0x17, 0x21, 0xc5, 0x10, 0x61, 0x1e, 0x41, 0x1e, -0x00, 0x1e, 0x01, 0x1e, 0xa0, 0x1e, 0x00, 0x1e, 0x28, 0x41, 0x00, 0x9f, 0x9e, 0x32, 0xc5, 0x10, -0x73, 0x1f, 0x53, 0x1f, 0xe6, 0x1f, 0x13, 0x1f, 0xa0, 0x1f, 0x00, 0x1f, 0x33, 0xc5, 0x00, 0x62, -0x30, 0x42, 0x30, 0xe8, 0x30, 0x02, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x5e, 0x0d, 0x61, 0x83, -0x65, 0x88, 0x8d, 0x8c, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, -0x98, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf9, 0x0e, 0x61, 0x84, 0x65, 0x89, 0x8d, 0x8b, -0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0xed, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x98, 0xd8, -0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, -0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x8d, 0xa1, 0x69, 0xa1, -0x6f, 0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x98, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, -0x20, 0xef, 0x60, 0x0d, 0x61, 0x85, 0x65, 0x8a, 0x8d, 0xec, 0x69, 0xec, 0x6f, 0x95, 0x75, 0x97, -0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x98, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x00, 0x02, -0x04, 0x1f, 0x00, 0x00, 0xa0, 0x00, 0xa0, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x07, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x0c, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x12, 0x41, 0x00, 0xa7, 0xa6, -0x13, 0xc5, 0x14, 0xd5, 0x17, 0x49, 0x17, 0xa0, 0x17, 0x09, 0x17, 0xa0, 0x17, 0x00, 0x17, 0x15, -0xc5, 0x04, 0x64, 0x20, 0x44, 0x20, 0xa0, 0x20, 0x04, 0x20, 0x00, 0x20, 0x00, 0x20, 0x18, 0xc5, -0x14, 0x68, 0x23, 0x48, 0x23, 0xa0, 0x23, 0x08, 0x23, 0xa0, 0x23, 0x00, 0x23, 0x1e, 0xc5, 0x00, -0x75, 0x16, 0x55, 0x16, 0xed, 0x16, 0x15, 0x16, 0xec, 0x16, 0x00, 0x16, 0x1f, 0xc5, 0x00, 0x69, -0x17, 0x98, 0x17, 0xe1, 0x17, 0x09, 0x17, 0xf5, 0x17, 0x00, 0x17, 0x20, 0xc5, 0x04, 0x65, 0x12, -0x45, 0x12, 0xa0, 0x12, 0x05, 0x12, 0x00, 0x12, 0x00, 0x12, 0x21, 0xc5, 0x10, 0x61, 0x1e, 0x41, -0x1e, 0x00, 0x1e, 0x01, 0x1e, 0xa0, 0x1e, 0x00, 0x1e, 0x28, 0x41, 0x00, 0xad, 0xb8, 0x29, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x2e, 0xc5, 0x14, 0x76, 0x2f, 0x56, 0x2f, 0xa0, 0x2f, 0x16, 0x2f, 0xa0, -0x2f, 0x00, 0x2f, 0x32, 0xc5, 0x10, 0x73, 0x1f, 0x53, 0x1f, 0xe6, 0x1f, 0x13, 0x1f, 0xa0, 0x1f, -0x00, 0x1f, 0x00, 0x5e, 0x17, 0x61, 0x83, 0x63, 0x86, 0x65, 0x88, 0x67, 0x9b, 0x68, 0xa9, 0xd5, -0x8c, 0x69, 0x8c, 0x6a, 0x9f, 0x6f, 0x93, 0x73, 0xc7, 0x75, 0x96, 0x41, 0xb6, 0x43, 0x8f, 0x45, -0xd2, 0x47, 0x9d, 0x48, 0xa8, 0x49, 0xd7, 0x98, 0xd7, 0x4a, 0xac, 0x4f, 0xe2, 0x53, 0xc6, 0x55, -0xea, 0x20, 0x5e, 0xf9, 0x0d, 0x61, 0x84, 0x65, 0x89, 0xd5, 0x8b, 0x69, 0x8b, 0x6f, 0x94, 0x75, -0x81, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x98, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x7e, -0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0xef, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0xd5, 0xa1, 0x69, -0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x98, 0xd6, 0x4f, 0xe0, 0x55, -0xe9, 0x20, 0xef, 0x60, 0x0d, 0x61, 0x85, 0x65, 0x8a, 0xd5, 0x8d, 0x69, 0x8d, 0x6f, 0x95, 0x75, -0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x98, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x00, -0x2f, 0xc4, 0x02, 0x04, 0x00, 0x00, 0x54, 0x54, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, -0x00, 0x00, 0x00, 0x00, 0x3d, 0x75, 0x6b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x75, 0x8b, 0x00, -0x00, 0x00, 0x00, 0x00, 0x42, 0x75, 0x4c, 0x02, 0xa2, 0x02, 0x00, 0x00, 0x42, 0x75, 0x7a, 0x01, -0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x03, 0x00, -0x00, 0x40, 0x05, 0x02, 0x03, 0x00, 0x00, 0x24, 0x07, 0x02, 0x03, 0x00, 0x00, 0x5e, 0x08, 0x02, -0x03, 0x00, 0x00, 0x5b, 0x09, 0x02, 0x03, 0x00, 0x00, 0x5d, 0x0a, 0x02, 0x03, 0x00, 0x00, 0x7b, -0x0b, 0x02, 0x03, 0x00, 0x00, 0x7d, 0x33, 0x02, 0x03, 0x00, 0x00, 0x3c, 0x34, 0x02, 0x03, 0x00, -0x00, 0x3e, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x05, 0x01, 0x01, 0x00, 0x3b, 0x07, 0x01, 0x01, -0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x43, 0x00, 0xf5, -0xf4, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, -0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, -0xe8, 0x98, 0x18, 0x43, 0x00, 0xd0, 0xcf, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, -0x00, 0xe5, 0x95, 0x1b, 0x43, 0x00, 0xb8, 0xb5, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, -0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, -0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, -0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, 0x00, 0xfb, 0xfa, 0xa6, 0x86, -0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0xc3, 0x00, 0xc6, 0x29, 0xbe, 0x29, 0xf1, 0x29, 0xf0, 0x00, -0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x02, 0x01, 0x00, 0x2f, 0x7c, 0x2c, 0x41, -0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, -0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x43, 0x00, 0xd2, -0xd1, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, -0x2e, 0x2c, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x79, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x05, 0x01, 0x01, 0x00, 0x3b, 0x07, 0x01, 0x01, 0x00, -0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, -0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, -0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, -0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, -0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, -0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, -0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, -0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0xc1, 0x00, 0xf1, -0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x02, 0x01, 0x00, 0x2f, -0x7c, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, -0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, -0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, -0x00, 0x2e, 0x2c, 0x00, 0x07, 0x03, 0x03, 0x00, 0x00, 0xc7, 0xc6, 0x12, 0x42, 0x00, 0x65, 0x45, -0xfd, 0x16, 0x43, 0x00, 0x75, 0x55, 0xf7, 0xf6, 0x17, 0x43, 0x00, 0x69, 0xbd, 0xbe, 0x49, 0x18, -0x43, 0x00, 0x6f, 0x4f, 0xf5, 0xf4, 0x1e, 0x43, 0x00, 0x61, 0x41, 0xf3, 0xf2, 0x1f, 0x43, 0x03, -0x00, 0x00, 0xfb, 0xfa, 0x22, 0x43, 0x03, 0x00, 0x00, 0xb6, 0xb5, 0x28, 0x00, 0x01, 0xc8, 0x2e, -0x43, 0x03, 0x00, 0x00, 0xf9, 0xf8, 0x31, 0x43, 0x03, 0x00, 0x00, 0xb8, 0xb7, 0x36, 0x04, 0x1f, -0x00, 0x00, 0x00, 0x00, 0x7b, 0x39, 0x00, 0x00, 0x20, 0x00, 0x27, 0x0d, 0x61, 0xd0, 0x65, 0xd2, -0xbe, 0xd4, 0x69, 0xd4, 0x6f, 0xd6, 0x75, 0xd8, 0x41, 0xcf, 0x45, 0xd1, 0x49, 0xd3, 0xbd, 0xd3, -0x4f, 0xd5, 0x55, 0xd7, 0x20, 0x27, 0x00, 0x17, 0x18, 0x03, 0x04, 0xbb, 0x01, 0x54, 0x54, 0x05, -0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x75, 0x8a, 0x01, 0xe0, -0x01, 0x00, 0x00, 0x42, 0x75, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x75, 0x04, 0x03, 0x00, -0x00, 0x00, 0x00, 0x3d, 0x75, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, -0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x23, 0x05, -0x02, 0x03, 0x00, 0x00, 0x24, 0x07, 0x02, 0x03, 0x00, 0x00, 0x5e, 0x08, 0x02, 0x03, 0x00, 0x00, -0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x2a, 0x1a, 0x02, 0x03, 0x00, 0x00, 0x5b, 0x1b, 0x02, 0x03, -0x00, 0x00, 0x5d, 0x33, 0x02, 0x03, 0x00, 0x00, 0x3c, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x00, -0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, -0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, -0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, -0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, -0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, -0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, -0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, -0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, -0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, -0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, -0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, -0xed, 0x9d, 0x29, 0x01, 0x00, 0x7c, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, -0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, -0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, -0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, -0x9e, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x00, 0x07, 0x03, 0x03, 0x00, 0x00, 0xc7, 0xc6, -0x12, 0x42, 0x00, 0x65, 0x45, 0xfd, 0x16, 0x43, 0x00, 0x75, 0x55, 0xf7, 0xf6, 0x17, 0x43, 0x00, -0x69, 0xbd, 0xbe, 0x49, 0x18, 0x43, 0x00, 0x6f, 0x4f, 0xf5, 0xf4, 0x1e, 0x43, 0x00, 0x61, 0x41, -0xf3, 0xf2, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xfb, 0xfa, 0x22, 0x43, 0x03, 0x00, 0x00, 0xb6, 0xb5, -0x28, 0x00, 0x01, 0xc8, 0x2e, 0x43, 0x03, 0x00, 0x00, 0xf9, 0xf8, 0x31, 0x43, 0x03, 0x00, 0x00, -0xb8, 0xb7, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x39, 0x00, 0x00, 0x20, 0x00, 0x27, -0x0d, 0x61, 0xd0, 0x65, 0xd2, 0xbe, 0xd4, 0x69, 0xd4, 0x6f, 0xd6, 0x75, 0xd8, 0x41, 0xcf, 0x45, -0xd1, 0x49, 0xd3, 0xbd, 0xd3, 0x4f, 0xd5, 0x55, 0xd7, 0x20, 0x27, 0x00, 0x02, 0x01, 0x00, 0xfc, -0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, -0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, -0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, -0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x43, 0x00, -0xf5, 0xf4, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, -0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, -0x00, 0xe8, 0x98, 0x18, 0x43, 0x00, 0xd0, 0xcf, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, -0x41, 0x00, 0xe5, 0x95, 0x1b, 0x43, 0x00, 0xb8, 0xb5, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, -0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, -0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, -0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, 0x00, 0xfb, 0xfa, 0xa6, -0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0x01, 0x00, 0x7c, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x7a, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, -0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, -0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x43, 0x00, 0xd2, 0xd1, 0xec, 0x9c, 0x33, 0x41, 0x00, -0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0xc3, 0x00, 0xc6, 0x35, 0xbe, 0x35, 0xf1, 0x35, -0xf0, 0x00, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x7b, 0x00, 0xaf, 0x72, 0x04, 0x13, 0x00, 0x00, 0x59, 0x43, 0x2c, 0x00, 0x00, 0x53, 0x52, 0x2c, -0x76, 0x00, 0x59, 0x43, 0x2c, 0x76, 0x00, 0x53, 0x52, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, -0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0xda, 0x01, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0x1b, -0x01, 0xb0, 0x02, 0x00, 0x00, 0x57, 0x03, 0xa7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0xef, -0x01, 0xb0, 0x02, 0x00, 0x00, 0x50, 0x03, 0x79, 0x03, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0xbd, -0x02, 0x00, 0x00, 0x00, 0x00, 0x65, 0x04, 0x4f, 0x04, 0x00, 0x00, 0x00, 0x00, 0x65, 0x04, 0x8e, -0x03, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, -0x00, 0x22, 0x40, 0x05, 0x02, 0x03, 0x00, 0x00, 0xcf, 0x07, 0x02, 0x01, 0x00, 0x26, 0x5e, 0x08, -0x02, 0x01, 0x00, 0x2f, 0x26, 0x09, 0x02, 0x01, 0x00, 0x28, 0x24, 0x0a, 0x02, 0x01, 0x00, 0x29, -0x3c, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x3e, 0x0c, 0x01, 0x00, 0x27, 0x3f, 0x0d, 0x01, 0x00, 0x2b, -0x2a, 0x15, 0xc4, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x1a, 0x02, -0x03, 0x00, 0x00, 0x5b, 0x1b, 0x02, 0x00, 0x5c, 0x5c, 0x5d, 0x27, 0x03, 0x04, 0x5e, 0x5e, 0x00, -0x1e, 0x28, 0x03, 0x04, 0x5d, 0x7d, 0x00, 0x1d, 0x29, 0x01, 0x00, 0x49, 0x56, 0x2b, 0x02, 0x00, -0x40, 0x40, 0x7c, 0x2c, 0xc4, 0x00, 0x79, 0x15, 0x59, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, -0x33, 0x02, 0x00, 0x2c, 0x3b, 0x3c, 0x34, 0x02, 0x00, 0x2e, 0x3a, 0x3e, 0x35, 0x03, 0x00, 0x2d, -0x5f, 0x2f, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, 0x01, 0x00, 0x3c, 0x3e, 0x00, 0x12, 0x42, 0x03, -0x00, 0x00, 0xd5, 0x00, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0c, 0x00, 0x01, 0xc8, 0x10, 0x41, -0x00, 0x90, 0x91, 0x11, 0x41, 0x00, 0x92, 0x93, 0x12, 0x42, 0x00, 0xa8, 0xa9, 0xcf, 0x13, 0x41, -0x00, 0xe1, 0xe2, 0x14, 0x41, 0x00, 0xe5, 0xe6, 0x15, 0xc4, 0x00, 0xf3, 0x2c, 0xf4, 0x2c, 0x00, -0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0xe7, 0xe8, 0x17, 0x41, 0x00, 0xb7, 0xb8, 0x18, -0x41, 0x00, 0xd6, 0xd7, 0x19, 0x41, 0x00, 0xd8, 0xdd, 0x1a, 0x41, 0x00, 0xf5, 0xf6, 0x1b, 0x41, -0x00, 0x80, 0x81, 0x1e, 0x41, 0x00, 0xa0, 0xa1, 0x1f, 0x41, 0x00, 0xe3, 0xe4, 0x20, 0x41, 0x00, -0xa6, 0xa7, 0x21, 0x41, 0x00, 0xaa, 0xab, 0x22, 0x41, 0x00, 0xac, 0xad, 0x23, 0x41, 0x00, 0xb5, -0xb6, 0x24, 0x41, 0x00, 0x8e, 0x8f, 0x25, 0x41, 0x00, 0xc6, 0xc7, 0x26, 0x41, 0x00, 0xd0, 0xd1, -0x27, 0x41, 0x00, 0xfb, 0xfc, 0x28, 0x41, 0x00, 0x94, 0x95, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x78, 0x2b, 0x41, 0x00, 0xe9, 0xea, 0x2c, 0xc4, 0x00, 0x88, 0x15, 0x89, 0x15, 0x00, 0x15, -0x19, 0x15, 0x00, 0x15, 0x2d, 0x41, 0x00, 0x9a, 0x9b, 0x2e, 0x41, 0x00, 0xa4, 0xa5, 0x2f, 0x41, -0x00, 0xeb, 0xec, 0x30, 0x41, 0x00, 0xa2, 0xa3, 0x31, 0x41, 0x00, 0xd4, 0xd5, 0x32, 0x41, 0x00, -0xd2, 0xd3, 0x00, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xcf, 0x36, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x0c, 0x00, 0x01, 0xc8, 0x10, 0x41, 0x00, 0x90, -0x91, 0x11, 0x41, 0x00, 0x92, 0x93, 0x12, 0x41, 0x00, 0xa8, 0xa9, 0x13, 0x41, 0x00, 0xe1, 0xe2, -0x14, 0x41, 0x00, 0xe5, 0xe6, 0x15, 0xc4, 0x00, 0xf3, 0x2c, 0xf4, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, -0x00, 0x2c, 0x16, 0x41, 0x00, 0xe7, 0xe8, 0x17, 0x41, 0x00, 0xb7, 0xb8, 0x18, 0x41, 0x00, 0xd6, -0xd7, 0x19, 0x41, 0x00, 0xd8, 0xdd, 0x1a, 0x41, 0x00, 0xf5, 0xf6, 0x1b, 0x41, 0x00, 0x80, 0x81, -0x1e, 0x41, 0x00, 0xa0, 0xa1, 0x1f, 0x41, 0x00, 0xe3, 0xe4, 0x20, 0x41, 0x00, 0xa6, 0xa7, 0x21, -0x41, 0x00, 0xaa, 0xab, 0x22, 0x41, 0x00, 0xac, 0xad, 0x23, 0x41, 0x00, 0xb5, 0xb6, 0x24, 0x41, -0x00, 0x8e, 0x8f, 0x25, 0x41, 0x00, 0xc6, 0xc7, 0x26, 0x41, 0x00, 0xd0, 0xd1, 0x27, 0x41, 0x00, -0xfb, 0xfc, 0x28, 0x41, 0x00, 0x94, 0x95, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, -0x41, 0x00, 0xe9, 0xea, 0x2c, 0xc4, 0x00, 0x88, 0x15, 0x89, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, -0x15, 0x2d, 0x41, 0x00, 0x9a, 0x9b, 0x2e, 0x41, 0x00, 0xa4, 0xa5, 0x2f, 0x41, 0x00, 0xeb, 0xec, -0x30, 0x41, 0x00, 0xa2, 0xa3, 0x31, 0x41, 0x00, 0xd4, 0xd5, 0x32, 0x41, 0x00, 0xd2, 0xd3, 0x00, -0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x27, 0x05, 0xac, 0x82, 0xc6, 0x96, 0xad, -0x83, 0xc7, 0x97, 0x20, 0x27, 0x00, 0x10, 0x41, 0x00, 0xef, 0x9f, 0x11, 0x41, 0x00, 0xf9, 0xf8, -0x12, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x13, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, -0xe2, 0x92, 0x15, 0xc4, 0x00, 0xa7, 0x2c, 0x87, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, -0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xf7, 0xf6, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, -0x00, 0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xe8, 0x98, 0x1b, 0x41, 0x00, 0xeb, 0x9b, 0x1e, 0x41, 0x00, -0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, -0x94, 0x22, 0x41, 0x00, 0xf3, 0xf2, 0x23, 0x41, 0x00, 0xa3, 0x83, 0x24, 0x41, 0x00, 0xa9, 0x89, -0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xe7, 0x97, 0x28, -0x41, 0x00, 0xee, 0x9e, 0x29, 0x41, 0x00, 0xec, 0x9c, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x7c, 0x2b, 0x41, 0x00, 0xa6, 0x86, 0x2c, 0xc4, 0x00, 0xa8, 0x15, 0x88, 0x15, 0x00, 0x15, 0x19, -0x15, 0x00, 0x15, 0x2d, 0x41, 0x00, 0xe5, 0x95, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, -0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, -0x8c, 0x00, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x10, 0x41, 0x00, -0xef, 0x9f, 0x11, 0x41, 0x00, 0xf9, 0xf8, 0x12, 0x41, 0x00, 0xa5, 0x85, 0x13, 0xc1, 0x00, 0xe0, -0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0xc4, 0x00, 0xa7, 0x2c, 0x87, 0x2c, 0x00, -0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xf7, 0xf6, 0x18, -0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xe8, 0x98, 0x1b, 0x41, -0x00, 0xeb, 0x9b, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, -0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xf3, 0xf2, 0x23, 0x41, 0x00, 0xa3, -0x83, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, -0x27, 0x41, 0x00, 0xe7, 0x97, 0x28, 0x41, 0x00, 0xee, 0x9e, 0x29, 0x41, 0x00, 0xec, 0x9c, 0x2a, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x2b, 0x41, 0x00, 0xa6, 0x86, 0x2c, 0xc4, 0x00, 0xa8, -0x15, 0x88, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x41, 0x00, 0xe5, 0x95, 0x2e, 0x41, -0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, -0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xae, 0x6a, 0x04, 0x09, 0xc2, 0x01, 0x59, 0x43, 0x2c, -0xc2, 0x01, 0x53, 0x52, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, -0x68, 0x03, 0xee, 0x01, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0x34, 0x01, 0x00, 0x00, 0x00, 0x00, -0x57, 0x03, 0xbb, 0x02, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, -0x50, 0x03, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0xc9, 0x02, 0x00, 0x00, 0x00, 0x00, -0x65, 0x04, 0x53, 0x04, 0x00, 0x00, 0x00, 0x00, 0x65, 0x04, 0x98, 0x03, 0x00, 0x00, 0x00, 0x00, -0x5a, 0x03, 0x2d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7e, 0x03, 0x01, -0x01, 0x00, 0x22, 0x04, 0x03, 0x01, 0x00, 0x23, 0x5e, 0x1e, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, -0x02, 0x01, 0x00, 0x2f, 0x60, 0x09, 0x01, 0x01, 0x00, 0x28, 0x0a, 0x01, 0x01, 0x00, 0x29, 0x0b, -0x01, 0x01, 0x00, 0x3d, 0x0c, 0x01, 0x00, 0x27, 0x3f, 0x0d, 0x01, 0x00, 0x2b, 0x2a, 0x10, 0x42, -0x03, 0x00, 0x00, 0x5c, 0x11, 0x42, 0x03, 0x00, 0x00, 0x7c, 0x15, 0xc4, 0x00, 0x7a, 0x2c, 0x5a, -0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x21, 0x42, 0x03, 0x00, 0x00, 0x5b, 0x22, 0x42, 0x03, -0x00, 0x00, 0x5d, 0x27, 0x03, 0x04, 0x5e, 0x5e, 0x00, 0x1e, 0x28, 0x01, 0x00, 0xf5, 0xf5, 0x29, -0x03, 0x04, 0x5c, 0x7c, 0x00, 0x1c, 0x2b, 0x01, 0x00, 0x40, 0x40, 0x2c, 0xc4, 0x00, 0x79, 0x15, -0x59, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2f, 0x42, 0x03, 0x00, 0x00, 0x40, 0x30, 0x42, -0x03, 0x00, 0x00, 0x7b, 0x31, 0x42, 0x03, 0x00, 0x00, 0x7d, 0x33, 0x01, 0x00, 0x2c, 0x3b, 0x34, -0x01, 0x00, 0x2e, 0x3a, 0x35, 0x03, 0x04, 0x2d, 0x5f, 0x00, 0x1f, 0x56, 0x01, 0x00, 0x3c, 0x3e, -0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x10, 0x41, 0x00, 0x90, 0x91, 0x11, 0x41, 0x00, -0x92, 0x93, 0x12, 0x42, 0x00, 0xa8, 0xa9, 0xcf, 0x13, 0x41, 0x00, 0xe1, 0xe2, 0x14, 0x41, 0x00, -0xe5, 0xe6, 0x15, 0xc4, 0x00, 0xf3, 0x2c, 0xf4, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, -0x41, 0x00, 0xe7, 0xe8, 0x17, 0x41, 0x00, 0xb7, 0xb8, 0x18, 0x41, 0x00, 0xd6, 0xd7, 0x19, 0x41, -0x00, 0xd8, 0xdd, 0x1a, 0x42, 0x00, 0xf5, 0xf6, 0x83, 0x1b, 0x42, 0x00, 0x80, 0x81, 0x82, 0x1e, -0x41, 0x00, 0xa0, 0xa1, 0x1f, 0x41, 0x00, 0xe3, 0xe4, 0x20, 0x41, 0x00, 0xa6, 0xa7, 0x21, 0x41, -0x00, 0xaa, 0xab, 0x22, 0x41, 0x00, 0xac, 0xad, 0x23, 0x41, 0x00, 0xb5, 0xb6, 0x24, 0x41, 0x00, -0x8e, 0x8f, 0x25, 0x41, 0x00, 0xc6, 0xc7, 0x26, 0x41, 0x00, 0xd0, 0xd1, 0x27, 0x42, 0x00, 0xfb, -0xfc, 0x97, 0x28, 0x42, 0x00, 0x94, 0x95, 0x96, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, -0x2b, 0x41, 0x00, 0xe9, 0xea, 0x2c, 0xc4, 0x00, 0x88, 0x15, 0x89, 0x15, 0x00, 0x15, 0x19, 0x15, -0x00, 0x15, 0x2d, 0x41, 0x00, 0x9a, 0x9b, 0x2e, 0x41, 0x00, 0xa4, 0xa5, 0x2f, 0x41, 0x00, 0xeb, -0xec, 0x30, 0x41, 0x00, 0xa2, 0xa3, 0x31, 0x41, 0x00, 0xd4, 0xd5, 0x32, 0x42, 0x00, 0xd2, 0xd3, -0xfd, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xcf, 0x28, 0x01, 0x00, 0xfd, 0xfd, 0x36, 0x04, 0x1f, -0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x10, 0x41, 0x00, 0x90, 0x91, 0x11, 0x41, 0x00, 0x92, 0x93, -0x12, 0x41, 0x00, 0xa8, 0xa9, 0x13, 0x41, 0x00, 0xe1, 0xe2, 0x14, 0x41, 0x00, 0xe5, 0xe6, 0x15, -0xc4, 0x00, 0xf3, 0x2c, 0xf4, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0xe7, -0xe8, 0x17, 0x41, 0x00, 0xb7, 0xb8, 0x18, 0x41, 0x00, 0xd6, 0xd7, 0x19, 0x41, 0x00, 0xd8, 0xdd, -0x1a, 0x42, 0x00, 0xf5, 0xf6, 0x83, 0x1b, 0x42, 0x00, 0x80, 0x81, 0x82, 0x1e, 0x41, 0x00, 0xa0, -0xa1, 0x1f, 0x41, 0x00, 0xe3, 0xe4, 0x20, 0x41, 0x00, 0xa6, 0xa7, 0x21, 0x41, 0x00, 0xaa, 0xab, -0x22, 0x41, 0x00, 0xac, 0xad, 0x23, 0x41, 0x00, 0xb5, 0xb6, 0x24, 0x41, 0x00, 0x8e, 0x8f, 0x25, -0x41, 0x00, 0xc6, 0xc7, 0x26, 0x41, 0x00, 0xd0, 0xd1, 0x27, 0x42, 0x00, 0xfb, 0xfc, 0x97, 0x28, -0x42, 0x00, 0x94, 0x95, 0x96, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x41, 0x00, -0xe9, 0xea, 0x2c, 0xc4, 0x00, 0x88, 0x15, 0x89, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, -0x41, 0x00, 0x9a, 0x9b, 0x2e, 0x41, 0x00, 0xa4, 0xa5, 0x2f, 0x41, 0x00, 0xeb, 0xec, 0x30, 0x41, -0x00, 0xa2, 0xa3, 0x31, 0x41, 0x00, 0xd4, 0xd5, 0x32, 0x42, 0x00, 0xd2, 0xd3, 0xfd, 0x00, 0x28, -0x01, 0x00, 0xfd, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x10, 0x41, 0x00, -0xef, 0x9f, 0x11, 0x41, 0x00, 0xf9, 0xf8, 0x12, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x13, 0xc1, 0x00, -0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0xc4, 0x00, 0xa7, 0x2c, 0x87, 0x2c, -0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xf7, 0xf6, -0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xe8, 0x98, 0x1b, -0x41, 0x00, 0xeb, 0x9b, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, -0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xf3, 0xf2, 0x23, 0x41, 0x00, -0xa3, 0x83, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, -0x8b, 0x27, 0x41, 0x00, 0xe7, 0x97, 0x28, 0x41, 0x00, 0xee, 0x9e, 0x29, 0x41, 0x00, 0xec, 0x9c, -0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, 0x41, 0x00, 0xa6, 0x86, 0x2c, 0xc4, 0x00, -0xa8, 0x15, 0x88, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x41, 0x00, 0xe5, 0x95, 0x2e, -0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, -0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x28, -0x10, 0x00, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x10, 0x41, 0x00, 0xef, -0x9f, 0x11, 0x41, 0x00, 0xf9, 0xf8, 0x12, 0x41, 0x00, 0xa5, 0x85, 0x13, 0xc1, 0x00, 0xe0, 0x00, -0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0xc4, 0x00, 0xa7, 0x2c, 0x87, 0x2c, 0x00, 0x2c, -0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xf7, 0xf6, 0x18, 0x41, -0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xe8, 0x98, 0x1b, 0x41, 0x00, -0xeb, 0x9b, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, -0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xf3, 0xf2, 0x23, 0x41, 0x00, 0xa3, 0x83, -0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, -0x41, 0x00, 0xe7, 0x97, 0x28, 0x41, 0x00, 0xee, 0x9e, 0x29, 0x41, 0x00, 0xec, 0x9c, 0x2a, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x2b, 0x41, 0x00, 0xa6, 0x86, 0x2c, 0xc4, 0x00, 0xa8, 0x15, -0x88, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x41, 0x00, 0xe5, 0x95, 0x2e, 0x41, 0x00, -0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, -0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, 0x00, 0x28, 0x10, 0x00, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x7f, 0x00, 0xaf, 0x00, 0x00 }; - -Bit8u layout_keybrd3sys[27122] = { -0x4b, 0x43, 0x46, 0x00, 0x01, 0x01, 0x2e, 0x48, 0x65, 0x6e, 0x72, 0x69, 0x71, 0x75, 0x65, 0x20, -0x50, 0x65, 0x72, 0x6f, 0x6e, 0xff, 0x44, 0x4f, 0x53, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x70, 0x61, -0x67, 0x65, 0x73, 0x20, 0x2d, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x23, 0x33, -0x20, 0x6f, 0x66, 0x20, 0x33, 0x6c, 0x02, 0x04, 0x00, 0x00, 0x41, 0x5a, 0x05, 0x03, 0x00, 0x00, -0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xeb, 0x59, 0x01, 0x00, 0x00, 0x00, 0x00, -0x62, 0xeb, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xe3, 0x5e, 0x02, 0x00, 0x00, 0x00, 0x00, -0x62, 0xe3, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, -0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x01, 0x00, 0x27, 0x23, 0x05, 0x03, 0x03, 0x00, -0xa0, 0x24, 0x4e, 0x06, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x02, 0x03, 0x00, 0x00, 0x26, 0x09, 0x02, -0x01, 0x00, 0x3b, 0x2a, 0x0a, 0x02, 0x01, 0x00, 0x3f, 0x7b, 0x0b, 0x02, 0x01, 0x00, 0x25, 0x7d, -0x29, 0x03, 0x00, 0x29, 0x28, 0x5d, 0x5b, 0x2b, 0x02, 0x00, 0x2c, 0x7c, 0x5c, 0x33, 0x02, 0x03, -0x00, 0x00, 0x3c, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x35, 0x02, 0x00, 0x2e, 0x3f, 0x2f, 0x00, -0x07, 0x01, 0x01, 0x00, 0x2c, 0x08, 0x01, 0x01, 0x00, 0x2e, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, -0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x41, -0x00, 0xa5, 0x85, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, -0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, -0x95, 0x1b, 0x41, 0x00, 0xea, 0x9a, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, -0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, -0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, -0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x2a, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, -0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, -0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, -0x41, 0x00, 0xee, 0x9e, 0x00, 0x07, 0x01, 0x01, 0x00, 0xf3, 0x08, 0x01, 0x01, 0x00, 0xf1, 0x11, -0x43, 0x00, 0xf5, 0xf4, 0x77, 0x57, 0x1a, 0x41, 0x00, 0xfc, 0xfb, 0x1b, 0x41, 0x00, 0xf7, 0xf6, -0x27, 0x41, 0x00, 0xfe, 0xfd, 0x28, 0x41, 0x00, 0xf9, 0xf8, 0x33, 0x41, 0x00, 0xf3, 0xf2, 0x34, -0xc1, 0x00, 0xf1, 0x34, 0xf0, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x07, -0x01, 0x01, 0x00, 0x2c, 0x08, 0x01, 0x01, 0x00, 0x2e, 0x10, 0x43, 0x00, 0x6a, 0x4a, 0xa9, 0x89, -0x11, 0x43, 0x00, 0xfd, 0x59, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, -0x8a, 0x14, 0x41, 0x00, 0xa5, 0x85, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, -0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x43, 0x00, 0x68, 0xfc, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, -0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x43, 0x00, 0xf3, 0xf2, 0xea, 0x9a, 0x1e, 0x41, 0x00, -0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, -0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, -0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, -0x86, 0x28, 0x43, 0x00, 0xf5, 0xf4, 0xed, 0x9d, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, -0x2c, 0x43, 0x00, 0xf7, 0xf6, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, -0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, -0x32, 0x43, 0x00, 0xf9, 0xf8, 0xec, 0x9c, 0x33, 0x43, 0x04, 0xa1, 0x81, 0x00, 0x3e, 0x34, 0xc3, -0x00, 0xf1, 0x34, 0xf0, 0x00, 0xee, 0x34, 0x9e, 0x34, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x7b, 0x00, 0xec, 0xc1, 0x04, 0x13, 0x00, 0x00, 0x42, 0x4c, 0x2c, 0x00, 0x00, 0x42, 0x59, -0x2c, 0xcf, 0x01, 0x42, 0x4c, 0x2c, 0xcf, 0x01, 0x42, 0x59, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x00, -0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x03, 0xca, 0x01, 0x00, 0x00, 0x00, 0x00, 0x51, 0x03, -0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x04, 0xc8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x04, -0xdf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0xb4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, -0xd7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0xa4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, -0xc9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, -0x03, 0x00, 0x00, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x23, 0x05, 0x02, 0x03, 0x00, 0x00, 0xcf, -0x07, 0x02, 0x03, 0x00, 0x00, 0x5e, 0x08, 0x02, 0x03, 0x00, 0x00, 0x26, 0x09, 0x02, 0x03, 0x00, -0x00, 0x24, 0x0a, 0x02, 0x03, 0x00, 0x00, 0xae, 0x0b, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x1a, 0x02, -0x03, 0x00, 0x00, 0x5b, 0x1b, 0x02, 0x03, 0x00, 0x00, 0x5d, 0x2b, 0x02, 0x03, 0x00, 0x00, 0x7c, -0x33, 0x02, 0x03, 0x00, 0x00, 0x3c, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x35, 0x02, 0x03, 0x00, -0x00, 0x2f, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x05, -0x02, 0x05, 0x00, 0x3b, 0xa0, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x0a, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x10, 0x41, 0x00, 0xa9, 0x89, -0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x42, 0x00, 0xe3, 0x93, 0xfb, 0x13, 0x41, 0x00, 0xaa, 0x8a, -0x14, 0x43, 0x00, 0xa5, 0x85, 0xf3, 0xf2, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x43, 0x00, 0xa3, -0x83, 0xfd, 0xfc, 0x17, 0x43, 0x00, 0xe8, 0x98, 0xe9, 0x99, 0x18, 0x41, 0x00, 0xf7, 0xf6, 0x19, -0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x01, 0x00, 0x27, 0x27, 0x1e, 0x41, -0x00, 0xe4, 0x94, 0x1f, 0x43, 0x00, 0xeb, 0x9b, 0xea, 0x9a, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, -0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, -0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, -0x41, 0x00, 0xa6, 0x86, 0x28, 0x43, 0x00, 0xed, 0x9d, 0xf5, 0xf4, 0x29, 0xc1, 0x00, 0xf1, 0x29, -0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, -0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, -0x00, 0xac, 0x8c, 0x30, 0x43, 0x00, 0xf9, 0xf8, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, -0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, -0x00, 0x2e, 0x2c, 0x00, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfb, -0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x05, 0x02, -0x01, 0x00, 0x3b, 0xfb, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x0a, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, -0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x43, -0x00, 0xa5, 0x85, 0xf3, 0xf2, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x43, 0x00, 0xa3, 0x83, 0xfd, -0xfc, 0x17, 0x43, 0x00, 0xe8, 0x98, 0xe9, 0x99, 0x18, 0x41, 0x00, 0xf7, 0xf6, 0x19, 0x41, 0x00, -0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x01, 0x00, 0x27, 0x27, 0x1e, 0x41, 0x00, 0xe4, -0x94, 0x1f, 0x43, 0x00, 0xeb, 0x9b, 0xea, 0x9a, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, -0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, -0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, -0xa6, 0x86, 0x28, 0x43, 0x00, 0xed, 0x9d, 0xf5, 0xf4, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, -0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, 0x00, -0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, -0x8c, 0x30, 0x43, 0x00, 0xf9, 0xf8, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, -0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, 0x2e, -0x2c, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0xfb, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, -0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xef, 0x05, 0x02, 0x05, 0x00, 0x3b, -0xa0, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xbd, 0xbe, -0x11, 0x41, 0x00, 0xa4, 0xa5, 0x12, 0x42, 0x00, 0xe7, 0xe8, 0xcf, 0x13, 0x41, 0x00, 0xc6, 0xc7, -0x14, 0x43, 0x00, 0xa8, 0xa9, 0x86, 0x87, 0x15, 0x41, 0x00, 0xd4, 0xd5, 0x16, 0x41, 0x00, 0xac, -0xad, 0x17, 0x43, 0x00, 0xf5, 0xf6, 0xf9, 0xfa, 0x18, 0x41, 0x00, 0x98, 0x99, 0x19, 0x41, 0x00, -0xf3, 0xf4, 0x1a, 0x41, 0x00, 0xb5, 0xb6, 0x1b, 0x01, 0x00, 0x27, 0x27, 0x1e, 0x41, 0x00, 0xaa, -0xab, 0x1f, 0x43, 0x00, 0xf1, 0xf2, 0x9e, 0x9f, 0x20, 0x41, 0x00, 0xeb, 0xec, 0x21, 0x41, 0x00, -0xa0, 0xa1, 0x22, 0x41, 0x00, 0xd8, 0xdd, 0x23, 0x41, 0x00, 0xe1, 0xe2, 0x24, 0x41, 0x00, 0xd6, -0xd7, 0x25, 0x41, 0x00, 0xd0, 0xd1, 0x26, 0x41, 0x00, 0xa6, 0xa7, 0x27, 0x41, 0x00, 0xe9, 0xea, -0x28, 0x41, 0x00, 0xf7, 0xf8, 0x29, 0x41, 0x00, 0x84, 0x85, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x7c, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0xc1, 0x00, 0xde, 0x2c, 0xe0, 0x00, 0x2d, 0x41, -0x00, 0xfb, 0xfc, 0x2e, 0x41, 0x00, 0xe3, 0xe4, 0x2f, 0x41, 0x00, 0xd2, 0xd3, 0x30, 0x43, 0x00, -0x8a, 0x8b, 0xb7, 0xb8, 0x31, 0x41, 0x00, 0xe5, 0xe6, 0x32, 0x41, 0x00, 0xed, 0xee, 0x33, 0x41, -0x00, 0xa2, 0xa3, 0x34, 0x41, 0x00, 0x9c, 0x9d, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x00, 0x05, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xcf, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x7d, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xef, 0x05, 0x01, 0x01, -0x00, 0x3b, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xbd, -0xbe, 0x11, 0x41, 0x00, 0xa4, 0xa5, 0x12, 0x41, 0x00, 0xe7, 0xe8, 0x13, 0x41, 0x00, 0xc6, 0xc7, -0x14, 0x43, 0x00, 0xa8, 0xa9, 0x86, 0x87, 0x15, 0x41, 0x00, 0xd4, 0xd5, 0x16, 0x41, 0x00, 0xac, -0xad, 0x17, 0x43, 0x00, 0xf5, 0xf6, 0xf9, 0xfa, 0x18, 0x41, 0x00, 0x98, 0x99, 0x19, 0x41, 0x00, -0xf3, 0xf4, 0x1a, 0x41, 0x00, 0xb5, 0xb6, 0x1b, 0x01, 0x00, 0x27, 0x27, 0x1e, 0x41, 0x00, 0xaa, -0xab, 0x1f, 0x43, 0x00, 0xf1, 0xf2, 0x9e, 0x9f, 0x20, 0x41, 0x00, 0xeb, 0xec, 0x21, 0x41, 0x00, -0xa0, 0xa1, 0x22, 0x41, 0x00, 0xd8, 0xdd, 0x23, 0x41, 0x00, 0xe1, 0xe2, 0x24, 0x41, 0x00, 0xd6, -0xd7, 0x25, 0x41, 0x00, 0xd0, 0xd1, 0x26, 0x41, 0x00, 0xa6, 0xa7, 0x27, 0x41, 0x00, 0xe9, 0xea, -0x28, 0x41, 0x00, 0xf7, 0xf8, 0x29, 0x41, 0x00, 0x84, 0x85, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x7e, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0xc1, 0x00, 0xde, 0x2c, 0xe0, 0x00, 0x2d, 0x41, -0x00, 0xfb, 0xfc, 0x2e, 0x41, 0x00, 0xe3, 0xe4, 0x2f, 0x41, 0x00, 0xd2, 0xd3, 0x30, 0x43, 0x00, -0x8a, 0x8b, 0xb7, 0xb8, 0x31, 0x41, 0x00, 0xe5, 0xe6, 0x32, 0x41, 0x00, 0xed, 0xee, 0x33, 0x41, -0x00, 0xa2, 0xa3, 0x34, 0x41, 0x00, 0x9c, 0x9d, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x00, 0x36, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x43, 0x08, 0x02, 0x04, 0x00, 0x00, 0x42, 0x4e, 0x02, -0x04, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x75, 0x44, 0x00, 0x6e, -0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x02, 0x41, 0x00, 0x26, 0x31, 0x03, 0x42, 0x00, 0x82, 0x32, 0x7e, 0x04, 0x42, -0x00, 0x22, 0x33, 0x23, 0x05, 0x42, 0x01, 0xcb, 0x34, 0x7b, 0x06, 0x44, 0x08, 0x28, 0x35, 0x5b, -0x00, 0x1b, 0x07, 0x44, 0x08, 0x2d, 0x36, 0x7c, 0x00, 0x1f, 0x08, 0x42, 0x04, 0x8a, 0x37, 0xc8, -0x09, 0x44, 0x08, 0x5f, 0x38, 0x5c, 0x00, 0x1c, 0x0a, 0x42, 0x00, 0x87, 0x39, 0x5e, 0x0b, 0x42, -0x00, 0x85, 0x30, 0x40, 0x0c, 0x44, 0x08, 0x29, 0xf8, 0x5d, 0x00, 0x1d, 0x0d, 0x42, 0x03, 0x00, -0x00, 0x7d, 0x10, 0xc5, 0x00, 0x61, 0x1e, 0x41, 0x1e, 0x91, 0x1e, 0x92, 0x1e, 0x01, 0x1e, 0x00, -0x1e, 0x11, 0xc5, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x84, 0x2c, 0x8e, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, -0x12, 0x43, 0x00, 0x65, 0x45, 0xc6, 0xc7, 0x13, 0x03, 0x03, 0x00, 0x00, 0x94, 0x99, 0x15, 0x41, -0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x43, 0x00, 0x69, 0x49, 0xe1, 0xee, 0x18, -0x43, 0x00, 0x6f, 0x4f, 0xe4, 0xe5, 0x19, 0x03, 0x03, 0x00, 0x00, 0xf7, 0xef, 0x1a, 0x44, 0x0f, -0xc9, 0xca, 0x00, 0x00, 0x1e, 0x1b, 0x43, 0x06, 0x24, 0xa0, 0x00, 0xd5, 0x1e, 0xc5, 0x00, 0x71, -0x10, 0x51, 0x10, 0x00, 0x10, 0x00, 0x10, 0x11, 0x10, 0x00, 0x10, 0x1f, 0x03, 0x03, 0x00, 0x00, -0xf9, 0xdd, 0x20, 0x03, 0x03, 0x00, 0x00, 0xa8, 0xad, 0x26, 0x03, 0x03, 0x00, 0x00, 0xab, 0xac, -0x27, 0xc5, 0x00, 0x6d, 0x32, 0x4d, 0x32, 0x00, 0x32, 0x00, 0x32, 0x0d, 0x32, 0x00, 0x32, 0x28, -0x41, 0x02, 0x97, 0xcc, 0x29, 0x41, 0x00, 0x9e, 0x9f, 0x2b, 0x43, 0x00, 0x9b, 0x9d, 0x2a, 0xe6, -0x2c, 0xc5, 0x00, 0x77, 0x11, 0x57, 0x11, 0x00, 0x11, 0x00, 0x11, 0x17, 0x11, 0x00, 0x11, 0x2e, -0x41, 0x00, 0x63, 0x43, 0x31, 0x43, 0x00, 0x6e, 0x4e, 0xa4, 0xa5, 0x32, 0x41, 0x00, 0x2c, 0x3f, -0x33, 0x43, 0x00, 0x3b, 0x2e, 0x3c, 0xae, 0x34, 0x43, 0x00, 0x3a, 0x2f, 0x3e, 0xaf, 0x35, 0x41, -0x00, 0x21, 0xf5, 0x39, 0x00, 0x00, 0x20, 0x56, 0x41, 0x00, 0x3c, 0x3e, 0x00, 0x60, 0x0f, 0x61, -0x85, 0x65, 0x8a, 0x9e, 0xd0, 0x69, 0x8d, 0x6f, 0x95, 0x9b, 0xfa, 0x75, 0x97, 0x41, 0xb7, 0x45, -0xd4, 0x9f, 0xd1, 0x49, 0xde, 0x4f, 0xe3, 0x9d, 0xfb, 0x55, 0xeb, 0x20, 0x60, 0x5e, 0x0b, 0x61, -0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, -0xe2, 0x55, 0xea, 0x20, 0x5e, 0x22, 0x09, 0x65, 0x89, 0x69, 0x8b, 0x75, 0x81, 0x79, 0x98, 0x45, -0xd3, 0x49, 0xd8, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x27, 0x13, 0x61, 0xa0, 0x65, 0x82, 0x9e, -0xf1, 0x69, 0xa1, 0x6f, 0xa2, 0x9b, 0xec, 0x75, 0xa3, 0x6e, 0x9c, 0x63, 0x87, 0x41, 0xb5, 0x45, -0x90, 0x9f, 0xf2, 0x49, 0xd6, 0x4f, 0xe0, 0x9d, 0xed, 0x55, 0xe9, 0x4e, 0xcf, 0x43, 0x80, 0x20, -0x27, 0x25, 0x0f, 0x61, 0x86, 0x65, 0xa6, 0x9e, 0xe7, 0x69, 0xa9, 0x6f, 0xbd, 0x9b, 0xfc, 0x75, -0xf4, 0x41, 0x8f, 0x45, 0xa7, 0x9f, 0xe8, 0x49, 0xb8, 0x4f, 0xbe, 0x9d, 0xfd, 0x55, 0xf6, 0x20, -0x25, 0x00, 0xcd, 0x4b, 0x03, 0x13, 0x00, 0x00, 0x45, 0x54, 0x2c, 0x00, 0x00, 0x45, 0x45, 0x2c, -0xc6, 0x01, 0x45, 0x54, 0x2c, 0xc6, 0x01, 0x45, 0x45, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x18, 0x01, 0x40, 0x01, 0x00, 0x00, 0x52, 0x03, 0xd1, -0x02, 0xd6, 0x02, 0x00, 0x00, 0x5a, 0x03, 0xc0, 0x02, 0xd6, 0x02, 0x00, 0x00, 0x5b, 0x03, 0x31, -0x02, 0x53, 0x02, 0x00, 0x00, 0x5c, 0x04, 0xb5, 0x01, 0xc4, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, -0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x01, 0x00, 0x22, 0x40, 0x40, 0x04, 0x03, 0x03, 0x00, -0x00, 0x9c, 0x9c, 0x05, 0x03, 0x01, 0x00, 0xcf, 0x24, 0x24, 0x07, 0x01, 0x01, 0x00, 0x26, 0x08, -0x03, 0x01, 0x00, 0x2f, 0x7b, 0x7b, 0x09, 0x04, 0x01, 0x00, 0x28, 0x5b, 0x5b, 0x1b, 0x0a, 0x04, -0x01, 0x00, 0x29, 0x5d, 0x5d, 0x1d, 0x0b, 0x03, 0x01, 0x00, 0x3d, 0x7d, 0x7d, 0x0c, 0x04, 0x00, -0x2b, 0x3f, 0x5c, 0x5c, 0x1c, 0x0d, 0x01, 0x03, 0xcb, 0xc8, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, -0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, -0x00, 0x6f, 0x4f, 0x1a, 0x41, 0x00, 0x81, 0x9a, 0x1b, 0x43, 0x00, 0xe4, 0xe5, 0xf5, 0xf5, 0x1e, -0x41, 0x00, 0x61, 0x41, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x27, 0x41, 0x00, 0x94, 0x99, 0x28, 0x44, -0x04, 0x84, 0x8e, 0xca, 0x5e, 0x1e, 0x29, 0x01, 0x03, 0xcc, 0xc9, 0x2b, 0x03, 0x00, 0x27, 0x2a, -0xab, 0xab, 0x2c, 0x41, 0x00, 0x7a, 0x5a, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, -0x4e, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, 0x01, 0x00, 0x3a, 0x3e, 0x35, 0x04, 0x00, -0x2d, 0x5f, 0x7c, 0x7c, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, 0x03, 0x00, 0x3c, 0x3e, 0x7c, 0x7c, -0x00, 0x05, 0x01, 0x01, 0x00, 0x9f, 0x13, 0x41, 0x00, 0x72, 0x52, 0x1f, 0x43, 0x03, 0x00, 0x00, -0xd5, 0xbe, 0x22, 0x41, 0x00, 0x67, 0x47, 0x25, 0x41, 0x00, 0x6b, 0x4b, 0x26, 0x41, 0x00, 0x6c, -0x4c, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xd8, 0xcf, 0x00, 0x60, 0x0b, 0x61, 0x83, 0x65, 0x89, 0x69, -0x8c, 0x6f, 0x93, 0x75, 0xd7, 0x41, 0xa0, 0x45, 0xed, 0x49, 0xa1, 0x4f, 0xe2, 0x55, 0xc7, 0x20, -0x60, 0x7e, 0x03, 0x6f, 0xe4, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x13, 0x61, 0xd0, 0x65, 0xd2, 0x69, -0xd4, 0x75, 0xd6, 0x67, 0x85, 0x6b, 0xe9, 0x6c, 0xeb, 0x6e, 0xec, 0x72, 0x8b, 0x41, 0xb5, 0x45, -0xb7, 0x49, 0xbd, 0x55, 0xc6, 0x47, 0x95, 0x4b, 0xe8, 0x4c, 0xea, 0x4e, 0xee, 0x52, 0x8a, 0x20, -0x5e, 0xef, 0x0d, 0x63, 0x87, 0x65, 0x82, 0x6e, 0xe7, 0x6f, 0xa2, 0x73, 0x98, 0x7a, 0xa5, 0x43, -0x80, 0x45, 0x90, 0x4e, 0xe3, 0x4f, 0xe0, 0x53, 0x97, 0x5a, 0x8d, 0x20, 0xef, 0x27, 0x07, 0x63, -0xd1, 0x73, 0xd5, 0x7a, 0xd8, 0x43, 0xb6, 0x53, 0xbe, 0x5a, 0xcf, 0x20, 0x27, 0x00, 0x1f, 0x43, -0x03, 0x00, 0x00, 0xd0, 0xd1, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xe7, 0xe8, 0x00, 0x60, 0x0b, 0x61, -0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, -0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, -0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, -0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0f, 0x61, -0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, -0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0x76, 0x05, 0x73, -0xd0, 0x7a, 0xe7, 0x53, 0xd1, 0x5a, 0xe8, 0x20, 0x76, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, -0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xf9, 0xdd, 0x2b, 0x03, 0x0f, -0x00, 0x00, 0xa0, 0xa0, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xf7, 0xef, 0x00, 0x60, 0x0b, 0x61, 0x85, -0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, -0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, -0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x27, 0x0f, 0x61, 0xa0, -0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, 0x80, -0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0x76, 0x05, 0x73, 0xf9, -0x7a, 0xf7, 0x53, 0xdd, 0x5a, 0xef, 0x20, 0x76, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x12, -0x42, 0x03, 0x00, 0x00, 0xd5, 0x29, 0x00, 0x01, 0xa0, 0x00, 0x29, 0x00, 0x01, 0xa0, 0x00, 0x60, -0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, -0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, -0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, -0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, -0x0f, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, -0xb5, 0x43, 0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0x00, -0x86, 0xe0, 0x01, 0x04, 0x00, 0x00, 0x46, 0x4f, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, -0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xef, 0x00, -0xfc, 0x00, 0x00, 0x00, 0x5d, 0x03, 0x77, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, -0x22, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x9c, 0x05, 0x02, 0x01, 0x00, 0xcf, 0x24, 0x07, 0x01, -0x01, 0x00, 0x26, 0x08, 0x02, 0x01, 0x00, 0x2f, 0x7b, 0x09, 0x03, 0x01, 0x00, 0x28, 0x5b, 0x1b, -0x0a, 0x03, 0x01, 0x00, 0x29, 0x5d, 0x1d, 0x0b, 0x02, 0x01, 0x00, 0x3d, 0x7d, 0x0c, 0x01, 0x00, -0x2b, 0x3f, 0x0d, 0x02, 0x03, 0xcb, 0xc8, 0x7c, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, -0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, -0x4f, 0x1a, 0x42, 0x04, 0x86, 0x8f, 0xcc, 0x1b, 0x42, 0x04, 0xd0, 0xd1, 0xc9, 0x1e, 0x41, 0x00, -0x61, 0x41, 0x27, 0x41, 0x00, 0x91, 0x92, 0x28, 0x43, 0x04, 0x9b, 0x9d, 0xca, 0x1e, 0x29, 0x01, -0x00, 0xab, 0xf5, 0x2b, 0x01, 0x00, 0x27, 0x2a, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, -0x6e, 0x4e, 0x32, 0x42, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, -0x01, 0x00, 0x3a, 0x3e, 0x35, 0x03, 0x00, 0x2d, 0x5f, 0x5c, 0x1f, 0x39, 0x00, 0x00, 0x20, 0x56, -0x03, 0x00, 0x3c, 0x3e, 0x5c, 0x1c, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x12, 0x42, 0x03, -0x00, 0x00, 0xd5, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, -0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, -0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, -0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, -0x55, 0xea, 0x20, 0x5e, 0xef, 0x0f, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, -0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, 0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, -0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, -0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0x05, -0x01, 0x03, 0x00, 0xa0, 0x0d, 0x00, 0x01, 0xca, 0x1a, 0x42, 0x07, 0x00, 0x00, 0xcb, 0x1b, 0x42, -0x00, 0x8c, 0x8b, 0x7e, 0x28, 0x42, 0x07, 0x00, 0x00, 0xc9, 0x29, 0x01, 0x00, 0xab, 0x15, 0x00, -0x60, 0x03, 0x61, 0x85, 0x65, 0x8a, 0x20, 0x60, 0x5e, 0x05, 0x61, 0x83, 0x65, 0x88, 0x6f, 0x93, -0x75, 0x96, 0x20, 0x5e, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, -0x79, 0x98, 0x41, 0xa4, 0x45, 0x90, 0x49, 0xa5, 0x4f, 0xa6, 0x55, 0xa7, 0x59, 0x97, 0x20, 0x27, -0x22, 0x08, 0x61, 0x84, 0x65, 0x89, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, -0x20, 0x22, 0x00, 0xfb, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x48, 0x59, 0x03, 0x03, 0x00, 0x00, 0x00, -0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x03, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x83, -0x03, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, -0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, -0x43, 0x00, 0xa5, 0xa4, 0x31, 0x21, 0x03, 0x43, 0x00, 0xe7, 0xe6, 0x32, 0x40, 0x04, 0x43, 0x00, -0x93, 0x92, 0x33, 0x23, 0x05, 0x43, 0x00, 0xa1, 0xa0, 0x34, 0x24, 0x06, 0x43, 0x00, 0xa9, 0xa8, -0x35, 0x25, 0x07, 0x42, 0x00, 0xe9, 0xe8, 0x36, 0x08, 0xc3, 0x00, 0xf1, 0x08, 0xf0, 0x00, 0x37, -0x7e, 0x26, 0x7e, 0x09, 0x43, 0x00, 0xf3, 0xf2, 0x38, 0x2a, 0x0a, 0x42, 0x00, 0x8d, 0x8c, 0x39, -0x0b, 0x42, 0x00, 0xa3, 0xa2, 0x30, 0x0d, 0x03, 0x00, 0x28, 0x29, 0x3d, 0x2b, 0x10, 0x41, 0x00, -0xf7, 0xf6, 0x11, 0x41, 0x00, 0x83, 0x82, 0x12, 0x41, 0x00, 0xeb, 0xea, 0x13, 0x41, 0x00, 0xa7, -0xa6, 0x14, 0xc1, 0x00, 0xe1, 0x14, 0xe0, 0x00, 0x15, 0x41, 0x00, 0xf5, 0xf4, 0x16, 0x41, 0x00, -0x9d, 0x9c, 0x17, 0x41, 0x00, 0x8f, 0x8e, 0x18, 0x41, 0x00, 0x91, 0x90, 0x19, 0x41, 0x00, 0x9b, -0x9a, 0x1a, 0x43, 0x00, 0xfb, 0xfa, 0x5b, 0x7b, 0x1b, 0x43, 0x00, 0xfd, 0xfc, 0x5d, 0x7d, 0x1e, -0x41, 0x00, 0xed, 0xec, 0x1f, 0x41, 0x00, 0x85, 0x84, 0x20, 0x41, 0x00, 0x89, 0x88, 0x21, 0x41, -0x00, 0x81, 0x80, 0x22, 0x41, 0x00, 0xab, 0xaa, 0x23, 0x41, 0x00, 0x95, 0x94, 0x24, 0x41, 0x00, -0xef, 0xee, 0x25, 0x41, 0x00, 0x9f, 0x9e, 0x26, 0x41, 0x00, 0xe5, 0xe4, 0x27, 0x01, 0x00, 0x3a, -0xdd, 0x28, 0x02, 0x00, 0x27, 0xfe, 0x22, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, -0x01, 0x00, 0xde, 0x15, 0x2c, 0x41, 0x00, 0x87, 0x86, 0x2d, 0x41, 0x00, 0xe3, 0xe2, 0x2e, 0x41, -0x00, 0x8b, 0x8a, 0x2f, 0x41, 0x00, 0x97, 0x96, 0x30, 0x41, 0x00, 0xf9, 0xf8, 0x31, 0x41, 0x00, -0x99, 0x98, 0x32, 0x41, 0x00, 0xad, 0xac, 0x33, 0x02, 0x01, 0x00, 0xae, 0x3c, 0x34, 0x02, 0x01, -0x00, 0xaf, 0x3e, 0x35, 0x03, 0x00, 0xdf, 0xdc, 0x2f, 0x3f, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x79, 0x00, 0x2d, 0x60, 0x03, 0x04, 0x00, 0x00, 0x4b, 0x41, 0x07, 0x03, 0x00, 0x00, -0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xe9, 0x78, 0x01, 0x00, 0x00, 0x00, 0x00, -0xb5, 0xe9, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xed, 0x55, 0x02, 0x00, 0x00, 0x00, 0x00, -0xb5, 0xed, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x38, 0x75, 0x4c, 0x03, 0x00, 0x00, 0x00, 0x00, -0x38, 0x75, 0x5e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, -0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x03, 0x02, 0x03, 0x00, 0x00, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x23, 0x07, 0x02, 0x03, 0x00, -0x00, 0x5e, 0x08, 0x02, 0x03, 0x00, 0x00, 0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x24, 0x1a, 0x02, -0x03, 0x00, 0x00, 0x5b, 0x1b, 0x02, 0x03, 0x00, 0x00, 0x5d, 0x2b, 0x02, 0x03, 0x00, 0x00, 0x7c, -0x33, 0x02, 0x03, 0x00, 0x00, 0x3c, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x35, 0x02, 0x03, 0x00, -0x00, 0x2f, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0x25, 0x05, 0x01, 0x01, -0x00, 0x3b, 0x06, 0x01, 0x01, 0x00, 0x3a, 0x07, 0x01, 0x01, 0x00, 0x2c, 0x08, 0x01, 0x01, 0x00, -0x2e, 0x10, 0x01, 0x00, 0x96, 0x96, 0x11, 0x01, 0x00, 0x9a, 0x9a, 0x12, 0x01, 0x00, 0x93, 0x93, -0x13, 0x01, 0x00, 0x89, 0x89, 0x14, 0x01, 0x00, 0x84, 0x84, 0x15, 0x01, 0x00, 0x8c, 0x8c, 0x16, -0x01, 0x00, 0x82, 0x82, 0x17, 0x01, 0x00, 0x98, 0x98, 0x18, 0x01, 0x00, 0x9c, 0x9c, 0x19, 0x01, -0x00, 0x86, 0x86, 0x1a, 0x01, 0x00, 0x9e, 0x9e, 0x1b, 0x01, 0x00, 0x9b, 0x9b, 0x1e, 0x01, 0x00, -0x94, 0x94, 0x1f, 0x01, 0x00, 0x87, 0x87, 0x20, 0x01, 0x00, 0x85, 0x85, 0x21, 0x01, 0x00, 0x80, -0x80, 0x22, 0x01, 0x00, 0x8e, 0x8e, 0x23, 0x01, 0x00, 0x90, 0x90, 0x24, 0x01, 0x00, 0x8d, 0x8d, -0x25, 0x01, 0x00, 0x8a, 0x8a, 0x26, 0x01, 0x00, 0x83, 0x83, 0x27, 0x01, 0x00, 0x8f, 0x8f, 0x28, -0x01, 0x00, 0x97, 0x97, 0x29, 0x01, 0x00, 0xa2, 0xa2, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x78, 0x2b, 0x01, 0x00, 0xa0, 0xa0, 0x2c, 0x01, 0x00, 0x9d, 0x9d, 0x2d, 0x01, 0x00, 0x99, 0x99, -0x2e, 0x01, 0x00, 0x91, 0x91, 0x2f, 0x01, 0x00, 0x8b, 0x8b, 0x30, 0x01, 0x00, 0x88, 0x88, 0x31, -0x01, 0x00, 0x92, 0x92, 0x32, 0x01, 0x00, 0x95, 0x95, 0x33, 0x01, 0x00, 0x81, 0x81, 0x34, 0x01, -0x00, 0x9f, 0x9f, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x03, 0x01, 0x01, -0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0x25, 0x05, 0x01, 0x01, 0x00, 0x3b, 0x06, 0x01, 0x01, 0x00, -0x3a, 0x07, 0x01, 0x01, 0x00, 0x2c, 0x08, 0x01, 0x01, 0x00, 0x2e, 0x10, 0x41, 0x00, 0xe6, 0x96, -0x11, 0x41, 0x00, 0xea, 0x9a, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xa9, 0x89, 0x14, -0x41, 0x00, 0xa4, 0x84, 0x15, 0x41, 0x00, 0xac, 0x8c, 0x16, 0x41, 0x00, 0xa2, 0x82, 0x17, 0x41, -0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xec, 0x9c, 0x19, 0x41, 0x00, 0xa6, 0x86, 0x1a, 0x41, 0x00, -0xee, 0x9e, 0x1b, 0x41, 0x00, 0xeb, 0x9b, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xa7, -0x87, 0x20, 0x41, 0x00, 0xa5, 0x85, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xae, 0x8e, -0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xad, 0x8d, 0x25, 0x41, 0x00, 0xaa, -0x8a, 0x26, 0x41, 0x00, 0xa3, 0x83, 0x27, 0x41, 0x00, 0xaf, 0x8f, 0x28, 0x41, 0x00, 0xe7, 0x97, -0x29, 0x10, 0x00, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0xc1, 0x00, 0xf0, -0x2b, 0xf0, 0x00, 0x2c, 0x41, 0x00, 0xed, 0x9d, 0x2d, 0x41, 0x00, 0xe9, 0x99, 0x2e, 0x41, 0x00, -0xe1, 0x91, 0x2f, 0x41, 0x00, 0xab, 0x8b, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, -0x92, 0x32, 0x41, 0x00, 0xe5, 0x95, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xef, 0x9f, -0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, -0x01, 0x01, 0x00, 0x25, 0x05, 0x01, 0x01, 0x00, 0x3b, 0x06, 0x01, 0x01, 0x00, 0x3a, 0x07, 0x01, -0x01, 0x00, 0x2c, 0x08, 0x01, 0x01, 0x00, 0x2e, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x43, 0x00, -0xe6, 0x96, 0xf6, 0xf7, 0x12, 0x43, 0x00, 0xe3, 0x93, 0xd3, 0xd4, 0x13, 0x43, 0x00, 0xaa, 0x8a, -0xd1, 0xd2, 0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x43, 0x00, -0xa3, 0x83, 0xb5, 0xb6, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x43, -0x00, 0xa7, 0x87, 0xcf, 0xd0, 0x1a, 0x43, 0x00, 0xe5, 0x95, 0xd5, 0xd6, 0x1b, 0x43, 0x00, 0xea, -0x9a, 0xf4, 0xf5, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, -0xa2, 0x82, 0x21, 0x43, 0x00, 0xa0, 0x80, 0xfa, 0xfb, 0x22, 0x43, 0x00, 0xaf, 0x8f, 0xd7, 0xd8, -0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, -0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x43, 0x00, 0xa6, 0x86, 0xb7, 0xb8, 0x28, 0x42, 0x00, -0xed, 0x9d, 0xfe, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x7c, 0x2c, 0x43, 0x00, 0xef, 0x9f, 0xc6, 0xc7, 0x2d, 0x43, 0x00, 0xe7, 0x97, 0xbd, 0xbe, -0x2e, 0x43, 0x00, 0xe1, 0x91, 0xf8, 0xf9, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, -0x88, 0x31, 0x43, 0x00, 0xe2, 0x92, 0xf2, 0xf3, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, -0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0xbc, 0x6f, 0x01, 0x04, 0x00, 0x00, 0x4b, 0x4b, 0x03, -0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe3, 0x32, 0x01, 0x00, -0x00, 0x00, 0x00, 0x28, 0xe3, 0x44, 0x00, 0x41, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, -0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x01, 0x00, 0xfc, 0x23, 0x05, -0x02, 0x05, 0x00, 0x3b, 0xa0, 0x07, 0x02, 0x01, 0x00, 0x3a, 0x5e, 0x08, 0x02, 0x01, 0x00, 0x3f, -0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x24, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, -0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, 0x85, -0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, -0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x42, 0x00, 0xe5, 0x95, 0x5b, -0x1b, 0x42, 0x00, 0xea, 0x9a, 0x5d, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, -0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, -0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, -0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, -0x83, 0x03, 0xc8, 0x29, 0x00, 0x29, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x78, 0x2b, 0x02, 0x01, 0x00, 0x2f, 0x7c, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, -0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, -0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x42, 0x00, 0xa1, 0x81, -0x3c, 0x34, 0x42, 0x00, 0xee, 0x9e, 0x3e, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x39, 0x00, 0x00, 0x20, -0x00, 0x12, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, -0x60, 0x13, 0xa0, 0xd1, 0xa3, 0xd3, 0xa8, 0xf5, 0xa9, 0xf7, 0xaa, 0xd5, 0xad, 0xd7, 0xae, 0xf3, -0xe3, 0xdd, 0xe5, 0xdf, 0x80, 0xd0, 0x83, 0xd2, 0x88, 0xf4, 0x89, 0xf6, 0x8a, 0xd4, 0x8d, 0xd6, -0x8e, 0xf2, 0x93, 0xdc, 0x95, 0xde, 0x20, 0x60, 0x00, 0x19, 0x44, 0x01, 0x04, 0x00, 0x00, 0x4b, -0x59, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe3, 0x30, -0x01, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe3, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, -0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x01, 0x00, 0xfc, -0x23, 0x05, 0x02, 0x05, 0x00, 0x3b, 0xa0, 0x07, 0x02, 0x01, 0x00, 0x3a, 0x5e, 0x08, 0x02, 0x01, -0x00, 0x3f, 0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x24, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, -0x00, 0xe6, 0x96, 0x12, 0x43, 0x00, 0xe3, 0x93, 0xdd, 0xdc, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, -0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x43, 0x00, 0xad, 0x8d, 0xd7, 0xd6, 0x16, 0x41, 0x00, 0xa3, -0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, -0x1a, 0x42, 0x00, 0xe5, 0x95, 0x5b, 0x1b, 0x42, 0x00, 0xea, 0x9a, 0x5d, 0x1e, 0x41, 0x00, 0xe4, -0x94, 0x1f, 0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, -0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x43, 0x00, 0xae, -0x8e, 0xf3, 0xf2, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, -0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x02, 0x01, 0x00, 0x2f, 0x7c, 0x2c, 0x41, 0x00, 0xef, -0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, -0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, -0x42, 0x00, 0xa1, 0x81, 0x3c, 0x34, 0x42, 0x00, 0xee, 0x9e, 0x3e, 0x35, 0x01, 0x00, 0x2e, 0x2c, -0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, -0x39, 0x60, 0x05, 0x09, 0x00, 0x00, 0x4c, 0x54, 0x2c, 0xd4, 0x00, 0x4c, 0x54, 0x0b, 0x03, 0x00, -0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0xc4, 0x00, 0x00, 0x00, 0x00, -0x00, 0x02, 0x03, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x20, 0x01, 0x00, 0x00, 0x00, -0x00, 0x06, 0x03, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x03, 0x50, 0x01, 0xc4, 0x01, 0x00, -0x00, 0x0a, 0x03, 0x55, 0x02, 0xc7, 0x02, 0x00, 0x00, 0x03, 0x03, 0x58, 0x03, 0x00, 0x00, 0x00, -0x00, 0x03, 0x03, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x57, 0x04, 0x00, 0x00, 0x00, -0x00, 0x04, 0x03, 0x8d, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, -0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x02, 0x03, 0x03, 0x00, 0x00, 0x31, 0x21, 0x03, 0x03, 0x03, 0x00, 0x00, 0x32, 0x40, 0x04, -0x03, 0x03, 0x00, 0x00, 0x33, 0x23, 0x05, 0x03, 0x03, 0x00, 0x00, 0x34, 0x24, 0x06, 0x03, 0x03, -0x00, 0x00, 0x35, 0x25, 0x07, 0x03, 0x03, 0x00, 0x00, 0x36, 0x5e, 0x08, 0x03, 0x03, 0x00, 0x00, -0x37, 0x26, 0x09, 0x03, 0x03, 0x00, 0x00, 0x38, 0x2a, 0x0d, 0x03, 0x03, 0x00, 0x00, 0x3d, 0x2b, -0x00, 0x02, 0x41, 0x00, 0xd0, 0xb5, 0x03, 0x41, 0x00, 0xd1, 0xb6, 0x04, 0x41, 0x00, 0xd2, 0xb7, -0x05, 0x41, 0x00, 0xd3, 0xb8, 0x06, 0x41, 0x00, 0xd4, 0xbd, 0x07, 0x41, 0x00, 0xd5, 0xbe, 0x08, -0x41, 0x00, 0xd6, 0xc6, 0x09, 0x41, 0x00, 0xd7, 0xc7, 0x0d, 0x41, 0x00, 0xd8, 0xcf, 0x00, 0x02, -0x41, 0x00, 0x85, 0x8f, 0x03, 0x41, 0x00, 0x87, 0x80, 0x04, 0x41, 0x00, 0x8a, 0x8b, 0x05, 0x41, -0x00, 0x82, 0x90, 0x06, 0x41, 0x00, 0x8d, 0xad, 0x07, 0x41, 0x00, 0x9e, 0x9f, 0x08, 0x41, 0x00, -0x97, 0xa7, 0x09, 0x41, 0x00, 0x96, 0xa6, 0x0d, 0x41, 0x00, 0x91, 0x92, 0x00, 0x02, 0x41, 0x00, -0xdd, 0xdc, 0x03, 0x41, 0x00, 0xdf, 0xde, 0x04, 0xc1, 0x00, 0xf1, 0x04, 0xf0, 0x00, 0x05, 0x41, -0x00, 0xf3, 0xf2, 0x06, 0x41, 0x00, 0xf5, 0xf4, 0x07, 0x41, 0x00, 0xf7, 0xf6, 0x08, 0x41, 0x00, -0xf9, 0xf8, 0x09, 0x41, 0x00, 0xfb, 0xfa, 0x0d, 0x41, 0x00, 0xfd, 0xfc, 0x00, 0x02, 0x41, 0x00, -0xdd, 0xdc, 0x03, 0x41, 0x00, 0xdf, 0xde, 0x04, 0xc1, 0x00, 0xf1, 0x04, 0xf0, 0x00, 0x05, 0x41, -0x00, 0xf3, 0xf2, 0x06, 0x41, 0x00, 0xf5, 0xf4, 0x07, 0x41, 0x00, 0xf7, 0xf6, 0x08, 0x41, 0x00, -0xf9, 0xf8, 0x09, 0x41, 0x00, 0xfb, 0xfa, 0x0d, 0x41, 0x00, 0xfd, 0xfc, 0x12, 0x41, 0x00, 0x65, -0x45, 0x13, 0x41, 0x00, 0x72, 0x52, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, -0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x24, -0x41, 0x02, 0x6a, 0x00, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x28, 0x00, 0x01, 0xca, 0x29, 0x01, 0x03, -0xc8, 0xc9, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x41, 0x00, 0x6d, 0x4d, 0x39, 0x00, 0x00, 0x20, -0x00, 0x60, 0x0b, 0x61, 0x83, 0x65, 0xa5, 0x69, 0xe9, 0x6f, 0xec, 0x75, 0x88, 0x41, 0xa0, 0x45, -0x8d, 0x49, 0xe8, 0x4f, 0xee, 0x55, 0xad, 0x20, 0x60, 0x7e, 0x21, 0x61, 0x86, 0xdd, 0xb5, 0x65, -0x85, 0xf1, 0xd6, 0xf3, 0x8b, 0x69, 0x9f, 0xf5, 0xe7, 0x6c, 0xe6, 0x6d, 0xbe, 0x6e, 0xd4, 0x6f, -0xe4, 0x72, 0xaf, 0x75, 0xc6, 0xf9, 0xef, 0xfb, 0xb8, 0x79, 0xa4, 0x41, 0x8f, 0xdc, 0xbd, 0x45, -0x95, 0xf0, 0x9c, 0xf2, 0x8a, 0x49, 0xd0, 0xf4, 0xe3, 0x4c, 0xa6, 0x4d, 0xa7, 0x4e, 0xa8, 0x4f, -0xe5, 0x52, 0xae, 0x55, 0x9e, 0xf8, 0xab, 0xfa, 0xa9, 0x59, 0xa3, 0x20, 0x7e, 0x27, 0x19, 0x61, -0x87, 0xdd, 0x89, 0x65, 0x82, 0xf1, 0xd8, 0xf3, 0x9b, 0x69, 0x8c, 0xf5, 0xeb, 0x6f, 0xa2, 0x75, -0x98, 0xf9, 0xac, 0xfb, 0x91, 0x79, 0x93, 0x41, 0x80, 0xdc, 0xed, 0x45, 0x90, 0xf0, 0x96, 0xf2, -0x9d, 0x49, 0xa1, 0xf4, 0xea, 0x4f, 0xe0, 0x55, 0x97, 0xf8, 0xaa, 0xfa, 0x92, 0x59, 0xe2, 0x20, -0x27, 0x00, 0x02, 0x41, 0x00, 0xd0, 0xb5, 0x03, 0x41, 0x00, 0xd1, 0xb6, 0x04, 0x41, 0x00, 0xd2, -0xb7, 0x05, 0x41, 0x00, 0xd3, 0xb8, 0x06, 0x41, 0x00, 0xd4, 0xbd, 0x07, 0x41, 0x00, 0xd5, 0xbe, -0x08, 0x41, 0x00, 0xd6, 0xc6, 0x09, 0x41, 0x00, 0xd7, 0xc7, 0x0d, 0x41, 0x00, 0xd8, 0xcf, 0x12, -0x41, 0x00, 0x65, 0x45, 0x13, 0x41, 0x00, 0x72, 0x52, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, -0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1e, 0x41, 0x00, -0x61, 0x41, 0x24, 0x41, 0x02, 0x6a, 0x00, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x28, 0x00, 0x01, 0xca, -0x29, 0x01, 0x03, 0xc8, 0xc9, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x41, 0x00, 0x6d, 0x4d, 0x39, -0x00, 0x00, 0x20, 0x00, 0x60, 0x0b, 0x61, 0x83, 0x65, 0xa5, 0x69, 0xe9, 0x6f, 0xec, 0x75, 0x88, -0x41, 0xa0, 0x45, 0x8d, 0x49, 0xe8, 0x4f, 0xee, 0x55, 0xad, 0x20, 0x60, 0x7e, 0x21, 0x61, 0x86, -0xd0, 0xf1, 0x65, 0x85, 0xd2, 0xfc, 0xd3, 0x8b, 0x69, 0x9f, 0xd4, 0xe7, 0x6c, 0xe6, 0x6d, 0xf5, -0x6e, 0xfb, 0x6f, 0xe4, 0x72, 0xaf, 0x75, 0xf6, 0xd6, 0xef, 0xd7, 0xf3, 0x79, 0xa4, 0x41, 0x8f, -0xb5, 0xf4, 0x45, 0x95, 0xb7, 0x9c, 0xb8, 0x8a, 0x49, 0xf8, 0xbd, 0xe3, 0x4c, 0xa6, 0x4d, 0xa7, -0x4e, 0xa8, 0x4f, 0xe5, 0x52, 0xae, 0x55, 0x9e, 0xc6, 0xab, 0xc7, 0xa9, 0x59, 0xa3, 0x20, 0x7e, -0x27, 0x19, 0x61, 0x87, 0xd0, 0x89, 0x65, 0x82, 0xd2, 0xfd, 0xd3, 0x9b, 0x69, 0x8c, 0xd4, 0xeb, -0x6f, 0xa2, 0x75, 0x98, 0xd6, 0xac, 0xd7, 0x91, 0x79, 0x93, 0x41, 0x80, 0xb5, 0xed, 0x45, 0x90, -0xb7, 0x96, 0xb8, 0x9d, 0x49, 0xa1, 0xbd, 0xea, 0x4f, 0xe0, 0x55, 0x97, 0xc6, 0xaa, 0xc7, 0x92, -0x59, 0xe2, 0x20, 0x27, 0x00, 0x02, 0x41, 0x00, 0xdd, 0xdc, 0x03, 0x41, 0x00, 0xdf, 0xde, 0x04, -0xc1, 0x00, 0xf1, 0x04, 0xf0, 0x00, 0x05, 0x41, 0x00, 0xf3, 0xf2, 0x06, 0x41, 0x00, 0xf5, 0xf4, -0x07, 0x41, 0x00, 0xf7, 0xf6, 0x08, 0x41, 0x00, 0xf9, 0xf8, 0x09, 0x41, 0x00, 0xfb, 0xfa, 0x0d, -0x41, 0x00, 0xfd, 0xfc, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x02, 0x01, 0x03, -0xa0, 0xa0, 0x03, 0x41, 0x00, 0xe7, 0x97, 0x04, 0x01, 0x03, 0xa0, 0xa0, 0x05, 0x41, 0x00, 0xed, -0x9d, 0x06, 0x01, 0x03, 0xa0, 0xa0, 0x07, 0x41, 0x00, 0xe8, 0x98, 0x08, 0x41, 0x00, 0xee, 0x9e, -0x09, 0x01, 0x03, 0xa0, 0xa0, 0x0d, 0x41, 0x00, 0xa6, 0x86, 0x10, 0x41, 0x00, 0xef, 0x9f, 0x11, -0x41, 0x00, 0xe9, 0x99, 0x12, 0x41, 0x00, 0xa5, 0x85, 0x13, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, -0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xeb, 0x9b, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, -0x41, 0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x43, -0x00, 0xea, 0x9a, 0x5b, 0x7b, 0x1b, 0x43, 0x00, 0xec, 0x9c, 0x5d, 0x7d, 0x1e, 0x41, 0x00, 0xa0, -0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, -0x22, 0x41, 0x00, 0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, -0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x7e, 0x2c, 0x41, 0x00, 0xa7, 0x87, 0x2d, 0x10, 0x00, 0x00, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, -0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, -0x00, 0xac, 0x8c, 0x00, 0x02, 0x41, 0x00, 0xd0, 0xb5, 0x03, 0x41, 0x00, 0xd1, 0xb6, 0x04, 0x41, -0x00, 0xd2, 0xb7, 0x05, 0x41, 0x00, 0xd3, 0xb8, 0x06, 0x41, 0x00, 0xd4, 0xbd, 0x07, 0x41, 0x00, -0xd5, 0xbe, 0x08, 0x41, 0x00, 0xd6, 0xc6, 0x09, 0x41, 0x00, 0xd7, 0xc7, 0x0d, 0x41, 0x00, 0xd8, -0xcf, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x02, 0x01, 0x03, 0xa0, 0xa0, 0x03, -0x41, 0x00, 0xe7, 0x97, 0x04, 0xc1, 0x00, 0xf1, 0x04, 0xf0, 0x00, 0x05, 0x41, 0x00, 0xed, 0x9d, -0x06, 0x01, 0x03, 0xa0, 0xa0, 0x07, 0x41, 0x00, 0xe8, 0x98, 0x08, 0x41, 0x00, 0xee, 0x9e, 0x09, -0x01, 0x03, 0xa0, 0xa0, 0x0d, 0x41, 0x00, 0xa6, 0x86, 0x10, 0x41, 0x00, 0xef, 0x9f, 0x11, 0x41, -0x00, 0xe9, 0x99, 0x12, 0x41, 0x00, 0xa5, 0x85, 0x13, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, -0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xeb, 0x9b, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, -0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x43, 0x00, -0xea, 0x9a, 0x5b, 0x7b, 0x1b, 0x43, 0x00, 0xec, 0x9c, 0x5d, 0x7d, 0x1e, 0x41, 0x00, 0xa0, 0x80, -0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, -0x41, 0x00, 0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, -0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80, -0x2c, 0x41, 0x00, 0xa7, 0x87, 0x2d, 0x10, 0x00, 0x00, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, -0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, -0xac, 0x8c, 0x00, 0xc1, 0x9a, 0x03, 0x04, 0xd2, 0x00, 0x4c, 0x54, 0x09, 0x03, 0x00, 0x00, 0x00, -0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, -0x03, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, -0x03, 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, -0x03, 0xa7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x71, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, -0x03, 0xc0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, -0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, -0x43, 0x03, 0x00, 0x00, 0xd7, 0xc7, 0x11, 0x43, 0x03, 0x00, 0x00, 0xd3, 0xb8, 0x12, 0x43, 0x03, -0x00, 0x00, 0xd2, 0xb7, 0x16, 0x43, 0x03, 0x00, 0x00, 0xd6, 0xc6, 0x17, 0x43, 0x03, 0x00, 0x00, -0xd4, 0xbd, 0x1e, 0x43, 0x03, 0x00, 0x00, 0xd0, 0xb5, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xd5, 0xbe, -0x28, 0x03, 0x03, 0x00, 0x00, 0xf2, 0xa6, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xd8, 0xcf, 0x2e, 0x43, -0x03, 0x00, 0x00, 0xd1, 0xb6, 0x00, 0x10, 0x43, 0x03, 0x00, 0x00, 0x96, 0xa6, 0x11, 0x43, 0x03, -0x00, 0x00, 0x82, 0x90, 0x12, 0x43, 0x03, 0x00, 0x00, 0x8a, 0x8b, 0x16, 0x43, 0x03, 0x00, 0x00, -0x97, 0xa7, 0x17, 0x43, 0x03, 0x00, 0x00, 0x8d, 0xad, 0x1e, 0x43, 0x03, 0x00, 0x00, 0x85, 0x8f, -0x1f, 0x43, 0x03, 0x00, 0x00, 0x9e, 0x9f, 0x28, 0x03, 0x03, 0x00, 0x00, 0xa9, 0x9d, 0x2c, 0x43, -0x03, 0x00, 0x00, 0x91, 0x92, 0x2e, 0x43, 0x03, 0x00, 0x00, 0x87, 0x80, 0x00, 0x10, 0x43, 0x03, -0x00, 0x00, 0xfb, 0xfa, 0x11, 0x43, 0x03, 0x00, 0x00, 0xf3, 0xf2, 0x12, 0xc3, 0x00, 0x65, 0x12, -0x45, 0x12, 0xf1, 0x12, 0xf0, 0x00, 0x16, 0x43, 0x03, 0x00, 0x00, 0xf9, 0xf8, 0x17, 0x43, 0x03, -0x00, 0x00, 0xf5, 0xf4, 0x1e, 0x43, 0x03, 0x00, 0x00, 0xdd, 0xdc, 0x1f, 0x43, 0x03, 0x00, 0x00, -0xf7, 0xf6, 0x28, 0x02, 0x03, 0x00, 0x00, 0xb7, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xfd, 0xfc, 0x2e, -0x43, 0x03, 0x00, 0x00, 0xdf, 0xde, 0x00, 0x28, 0x03, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x00, 0x10, -0x43, 0x03, 0x00, 0x00, 0xfb, 0xfa, 0x11, 0x43, 0x03, 0x00, 0x00, 0xf3, 0xf2, 0x12, 0xc3, 0x00, -0x65, 0x12, 0x45, 0x12, 0xf1, 0x12, 0xf0, 0x00, 0x16, 0x43, 0x03, 0x00, 0x00, 0xf9, 0xf8, 0x17, -0x43, 0x03, 0x00, 0x00, 0xf5, 0xf4, 0x1e, 0x43, 0x03, 0x00, 0x00, 0xdd, 0xdc, 0x1f, 0x43, 0x03, -0x00, 0x00, 0xf7, 0xf6, 0x28, 0x03, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x2c, 0x43, 0x03, 0x00, 0x00, -0xfd, 0xfc, 0x2e, 0x43, 0x03, 0x00, 0x00, 0xdf, 0xde, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x7d, 0x00, 0x0c, 0x43, 0x00, 0xea, 0x9a, 0x2d, 0x5f, 0x0d, 0x43, 0x00, 0xec, 0x9c, 0x3d, 0x2b, -0x10, 0x43, 0x0c, 0xee, 0x9e, 0xa0, 0xa0, 0x11, 0x43, 0x0c, 0xed, 0x9d, 0xa0, 0xa0, 0x12, 0x43, -0x0c, 0xa5, 0x85, 0xa0, 0xa0, 0x13, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, -0x92, 0x15, 0x41, 0x00, 0xeb, 0x9b, 0x16, 0x43, 0x0c, 0xe3, 0x93, 0xa0, 0xa0, 0x17, 0x43, 0x0c, -0xa8, 0x88, 0xa0, 0xa0, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x43, -0x00, 0xe7, 0x97, 0x5b, 0x7b, 0x1b, 0x43, 0x00, 0xe8, 0x98, 0x5d, 0x7d, 0x1e, 0x43, 0x0c, 0xa0, -0x80, 0xa0, 0xa0, 0x1f, 0x43, 0x0c, 0xe1, 0x91, 0xa0, 0xa0, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, -0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, -0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x28, 0x43, 0x00, -0xef, 0x9f, 0x27, 0x22, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, 0x43, 0x00, 0xa6, -0x86, 0x5c, 0x7c, 0x2c, 0x43, 0x0c, 0xa7, 0x87, 0xa0, 0xa0, 0x2d, 0x41, 0x00, 0xe9, 0x99, 0x2e, -0x44, 0x1c, 0xe6, 0x96, 0xa0, 0x00, 0x3c, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, -0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, 0x00, 0x10, 0x43, 0x03, 0x00, -0x00, 0xd7, 0xc7, 0x11, 0x43, 0x03, 0x00, 0x00, 0xd3, 0xb8, 0x12, 0x43, 0x03, 0x00, 0x00, 0xd2, -0xb7, 0x16, 0x43, 0x03, 0x00, 0x00, 0xd6, 0xc6, 0x17, 0x43, 0x03, 0x00, 0x00, 0xd4, 0xbd, 0x1e, -0x43, 0x03, 0x00, 0x00, 0xd0, 0xb5, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xd5, 0xbe, 0x28, 0x03, 0x03, -0x00, 0x00, 0xf4, 0xf5, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xd8, 0xcf, 0x2e, 0x43, 0x03, 0x00, 0x00, -0xd1, 0xb6, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x0c, 0x43, 0x00, 0xea, 0x9a, -0x2d, 0x5f, 0x0d, 0x43, 0x00, 0xec, 0x9c, 0x3d, 0x2b, 0x10, 0x43, 0x0c, 0xee, 0x9e, 0xa0, 0xa0, -0x11, 0x43, 0x0c, 0xed, 0x9d, 0xa0, 0xa0, 0x12, 0x43, 0x0c, 0xa5, 0x85, 0xa0, 0xa0, 0x13, 0xc1, -0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xeb, 0x9b, 0x16, -0x43, 0x0c, 0xe3, 0x93, 0xa0, 0xa0, 0x17, 0x43, 0x0c, 0xa8, 0x88, 0xa0, 0xa0, 0x18, 0x41, 0x00, -0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x43, 0x00, 0xe7, 0x97, 0x5b, 0x7b, 0x1b, 0x43, -0x00, 0xe8, 0x98, 0x5d, 0x7d, 0x1e, 0x43, 0x0c, 0xa0, 0x80, 0xa0, 0xa0, 0x1f, 0x43, 0x0c, 0xe1, -0x91, 0xa0, 0xa0, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, -0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, -0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x28, 0x43, 0x00, 0xef, 0x9f, 0x27, 0x22, 0x29, 0xc3, 0x00, -0xf1, 0x29, 0xf0, 0x00, 0x60, 0x29, 0x7e, 0x29, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, -0x2b, 0x43, 0x00, 0xa6, 0x86, 0x5c, 0x7c, 0x2c, 0x43, 0x0c, 0xa7, 0x87, 0xa0, 0xa0, 0x2d, 0x41, -0x00, 0xe9, 0x99, 0x2e, 0x44, 0x1c, 0xe6, 0x96, 0xa0, 0x00, 0x3c, 0x2f, 0x41, 0x00, 0xa2, 0x82, -0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, 0x00, -0x6f, 0x88, 0x05, 0x04, 0xd3, 0x00, 0x4c, 0x54, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, -0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x13, 0x01, -0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x46, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x7b, 0x01, -0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xc2, 0x01, -0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x7c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0xb7, 0x02, -0x00, 0x00, 0x00, 0x00, 0x09, 0x03, 0x73, 0x03, 0xed, 0x03, 0x00, 0x00, 0x0a, 0x03, 0x7e, 0x04, -0xf2, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x21, -0x31, 0x03, 0x02, 0x00, 0x22, 0x32, 0x40, 0x04, 0x02, 0x00, 0x2f, 0x33, 0x23, 0x05, 0x02, 0x00, -0x3b, 0x34, 0x24, 0x06, 0x02, 0x00, 0x3a, 0x35, 0x25, 0x07, 0x02, 0x00, 0x2c, 0x36, 0x5e, 0x08, -0x02, 0x00, 0x2e, 0x37, 0x26, 0x09, 0x02, 0x00, 0x3f, 0x38, 0x2a, 0x0a, 0x01, 0x00, 0x28, 0x39, -0x0b, 0x01, 0x00, 0x29, 0x30, 0x0c, 0x01, 0x00, 0x5f, 0x2d, 0x0d, 0x01, 0x00, 0x2b, 0x3d, 0x10, -0x43, 0x00, 0xd0, 0xb5, 0x71, 0x51, 0x11, 0x43, 0x00, 0xd8, 0xcf, 0x77, 0x57, 0x1a, 0x43, 0x00, -0xd4, 0xbd, 0x5b, 0x7b, 0x1b, 0x03, 0x00, 0xf2, 0xa6, 0x5d, 0x7d, 0x27, 0x43, 0x00, 0xd6, 0xc6, -0x3b, 0x3a, 0x28, 0x43, 0x00, 0xd3, 0xb8, 0x27, 0x22, 0x2b, 0x01, 0x00, 0x7c, 0x5c, 0x2d, 0x43, -0x00, 0xd7, 0xc7, 0x78, 0x58, 0x33, 0x43, 0x00, 0xd1, 0xb6, 0x2c, 0x3c, 0x34, 0x43, 0x00, 0xd5, -0xbe, 0x2e, 0x3e, 0x35, 0x43, 0x00, 0xd2, 0xb7, 0x2f, 0x3f, 0x00, 0x10, 0x41, 0x00, 0x85, 0x8f, -0x11, 0x41, 0x00, 0x91, 0x92, 0x1a, 0x41, 0x00, 0x8d, 0xad, 0x1b, 0x01, 0x00, 0xa9, 0x9d, 0x27, -0x41, 0x00, 0x97, 0xa7, 0x28, 0x41, 0x00, 0x82, 0x90, 0x2d, 0x41, 0x00, 0x96, 0xa6, 0x33, 0x41, -0x00, 0x87, 0x80, 0x34, 0x41, 0x00, 0x9e, 0x9f, 0x35, 0x41, 0x00, 0x8a, 0x8b, 0x00, 0x10, 0x41, -0x00, 0xdd, 0xdc, 0x11, 0x41, 0x00, 0xfd, 0xfc, 0x1a, 0x41, 0x00, 0xf5, 0xf4, 0x1b, 0x01, 0x00, -0xb7, 0xa6, 0x27, 0x41, 0x00, 0xf9, 0xf8, 0x28, 0x41, 0x00, 0xf3, 0xf2, 0x2d, 0x41, 0x00, 0xfb, -0xfa, 0x33, 0x41, 0x00, 0xdf, 0xde, 0x34, 0x41, 0x00, 0xf7, 0xf6, 0x35, 0xc1, 0x00, 0xf1, 0x35, -0xf0, 0x00, 0x00, 0x1b, 0x01, 0x03, 0xa0, 0xa0, 0x00, 0x10, 0x41, 0x00, 0xdd, 0xdc, 0x11, 0x41, -0x00, 0xfd, 0xfc, 0x1a, 0x41, 0x00, 0xf5, 0xf4, 0x1b, 0x01, 0x03, 0xa0, 0xa0, 0x27, 0x41, 0x00, -0xf9, 0xf8, 0x28, 0x41, 0x00, 0xf3, 0xf2, 0x2d, 0x41, 0x00, 0xfb, 0xfa, 0x33, 0x41, 0x00, 0xdf, -0xde, 0x34, 0x41, 0x00, 0xf7, 0xf6, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x36, 0x04, 0x1f, -0x00, 0x00, 0x00, 0x00, 0x7d, 0x56, 0x10, 0x00, 0x00, 0x00, 0x10, 0x43, 0x0c, 0xef, 0x9f, 0xa0, -0xa0, 0x11, 0x43, 0x0c, 0xa6, 0x86, 0xa0, 0xa0, 0x12, 0x41, 0x00, 0xa5, 0x85, 0x13, 0xc1, 0x00, -0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xeb, 0x9b, 0x16, 0x41, -0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, -0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xea, 0x9a, 0x1b, 0x41, 0x00, 0xec, 0x9c, 0x1e, 0x41, 0x00, 0xa0, -0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, -0x22, 0x41, 0x00, 0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, -0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xee, 0x9e, 0x28, 0x41, -0x00, 0xed, 0x9d, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2c, 0x41, 0x00, 0xa7, 0x87, -0x2d, 0x43, 0x0c, 0xe9, 0x99, 0xa0, 0xa0, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, -0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, -0x33, 0x41, 0x00, 0xe7, 0x97, 0x34, 0x41, 0x00, 0xe8, 0x98, 0x35, 0x01, 0x03, 0xa0, 0xa0, 0x56, -0x10, 0x00, 0x00, 0x00, 0x10, 0x41, 0x00, 0xd0, 0xb5, 0x11, 0x41, 0x00, 0xd8, 0xcf, 0x1a, 0x41, -0x00, 0xd4, 0xbd, 0x1b, 0x01, 0x00, 0xf4, 0xf5, 0x27, 0x41, 0x00, 0xd6, 0xc6, 0x28, 0x41, 0x00, -0xd3, 0xb8, 0x2d, 0x41, 0x00, 0xd7, 0xc7, 0x33, 0x41, 0x00, 0xd1, 0xb6, 0x34, 0x41, 0x00, 0xd5, -0xbe, 0x35, 0x41, 0x00, 0xd2, 0xb7, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x10, -0x43, 0x0c, 0xef, 0x9f, 0xa0, 0xa0, 0x11, 0x43, 0x0c, 0xa6, 0x86, 0xa0, 0xa0, 0x12, 0x41, 0x00, -0xa5, 0x85, 0x13, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, -0x00, 0xeb, 0x9b, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, -0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xea, 0x9a, 0x1b, 0x41, 0x00, 0xec, -0x9c, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, -0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, 0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, -0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, 0x41, -0x00, 0xee, 0x9e, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, -0x2c, 0x41, 0x00, 0xa7, 0x87, 0x2d, 0x43, 0x0c, 0xe9, 0x99, 0xa0, 0xa0, 0x2e, 0x41, 0x00, 0xe6, -0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, -0x32, 0x41, 0x00, 0xac, 0x8c, 0x33, 0x41, 0x00, 0xe7, 0x97, 0x34, 0x41, 0x00, 0xe8, 0x98, 0x35, -0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x56, 0x10, 0x00, 0x00, 0x00, 0x10, 0x41, 0x00, 0xdd, 0xdc, -0x11, 0x41, 0x00, 0xfd, 0xfc, 0x12, 0x41, 0x00, 0x65, 0x45, 0x13, 0x41, 0x00, 0x72, 0x52, 0x15, -0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, -0x00, 0x6f, 0x4f, 0x1a, 0x41, 0x00, 0xf5, 0xf4, 0x1b, 0x01, 0x00, 0xd5, 0xb7, 0x1e, 0x41, 0x00, -0x61, 0x41, 0x24, 0x41, 0x02, 0x6a, 0x00, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x27, 0x41, 0x00, 0xf9, -0xf8, 0x28, 0x41, 0x00, 0xf3, 0xf2, 0x29, 0x02, 0x07, 0xc8, 0xc9, 0xca, 0x2d, 0x41, 0x00, 0xfb, -0xfa, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x41, 0x00, 0x6d, 0x4d, 0x33, 0x41, 0x00, 0xdf, 0xde, -0x34, 0x41, 0x00, 0xf7, 0xf6, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x39, 0x00, 0x00, 0x20, -0x56, 0x10, 0x00, 0x00, 0x00, 0x60, 0x0b, 0x61, 0x83, 0x65, 0xa5, 0x69, 0xe9, 0x6f, 0xec, 0x75, -0x88, 0x41, 0xa0, 0x45, 0x8d, 0x49, 0xe8, 0x4f, 0xee, 0x55, 0xad, 0x20, 0x60, 0x7e, 0x21, 0x61, -0x86, 0xdd, 0xb5, 0x65, 0x85, 0xf1, 0xd6, 0xf3, 0x8b, 0x69, 0x9f, 0xf5, 0xe7, 0x6c, 0xe6, 0x6d, -0xbe, 0x6e, 0xd4, 0x6f, 0xe4, 0x72, 0xaf, 0x75, 0xc6, 0xf9, 0xef, 0xfb, 0xb8, 0x79, 0xa4, 0x41, -0x8f, 0xdc, 0xbd, 0x45, 0x95, 0xf0, 0x9c, 0xf2, 0x8a, 0x49, 0xd0, 0xf4, 0xe3, 0x4c, 0xa6, 0x4d, -0xa7, 0x4e, 0xa8, 0x4f, 0xe5, 0x52, 0xae, 0x55, 0x9e, 0xf8, 0xab, 0xfa, 0xa9, 0x59, 0xa3, 0x20, -0x7e, 0x27, 0x19, 0x61, 0x87, 0xdd, 0x89, 0x65, 0x82, 0xf1, 0xd8, 0xf3, 0x9b, 0x69, 0x8c, 0xf5, -0xeb, 0x6f, 0xa2, 0x75, 0x98, 0xf9, 0xac, 0xfb, 0x91, 0x79, 0x93, 0x41, 0x80, 0xdc, 0xed, 0x45, -0x90, 0xf0, 0x96, 0xf2, 0x9d, 0x49, 0xa1, 0xf4, 0xea, 0x4f, 0xe0, 0x55, 0x97, 0xf8, 0xaa, 0xfa, -0x92, 0x59, 0xe2, 0x20, 0x27, 0x00, 0x10, 0x41, 0x00, 0xd0, 0xb5, 0x11, 0x41, 0x00, 0xd8, 0xcf, -0x12, 0x41, 0x00, 0x65, 0x45, 0x13, 0x41, 0x00, 0x72, 0x52, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, -0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x41, -0x00, 0xd4, 0xbd, 0x1b, 0x01, 0x00, 0xf7, 0xf2, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x24, 0x41, 0x02, -0x6a, 0x00, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x27, 0x41, 0x00, 0xd6, 0xc6, 0x28, 0x41, 0x00, 0xd3, -0xb8, 0x29, 0x02, 0x07, 0xc8, 0xc9, 0xca, 0x2d, 0x41, 0x00, 0xd7, 0xc7, 0x31, 0x41, 0x00, 0x6e, -0x4e, 0x32, 0x41, 0x00, 0x6d, 0x4d, 0x33, 0x41, 0x00, 0xd1, 0xb6, 0x34, 0x41, 0x00, 0xd5, 0xbe, -0x35, 0x41, 0x00, 0xd2, 0xb7, 0x39, 0x00, 0x00, 0x20, 0x00, 0x60, 0x0b, 0x61, 0x83, 0x65, 0xa5, -0x69, 0xe9, 0x6f, 0xec, 0x75, 0x88, 0x41, 0xa0, 0x45, 0x8d, 0x49, 0xe8, 0x4f, 0xee, 0x55, 0xad, -0x20, 0x60, 0x7e, 0x21, 0x61, 0x86, 0xd0, 0xf1, 0x65, 0x85, 0xd2, 0xfc, 0xd3, 0x8b, 0x69, 0x9f, -0xd4, 0xe7, 0x6c, 0xe6, 0x6d, 0xf5, 0x6e, 0xfb, 0x6f, 0xe4, 0x72, 0xaf, 0x75, 0xf6, 0xd6, 0xef, -0xd7, 0xf3, 0x79, 0xa4, 0x41, 0x8f, 0xb5, 0xf4, 0x45, 0x95, 0xb7, 0x9c, 0xb8, 0x8a, 0x49, 0xf8, -0xbd, 0xe3, 0x4c, 0xa6, 0x4d, 0xa7, 0x4e, 0xa8, 0x4f, 0xe5, 0x52, 0xae, 0x55, 0x9e, 0xc6, 0xab, -0xc7, 0xa9, 0x59, 0xa3, 0x20, 0x7e, 0x27, 0x19, 0x61, 0x87, 0xd0, 0x89, 0x65, 0x82, 0xd2, 0xfd, -0xd3, 0x9b, 0x69, 0x8c, 0xd4, 0xeb, 0x6f, 0xa2, 0x75, 0x98, 0xd6, 0xac, 0xd7, 0x91, 0x79, 0x93, -0x41, 0x80, 0xb5, 0xed, 0x45, 0x90, 0xb7, 0x96, 0xb8, 0x9d, 0x49, 0xa1, 0xbd, 0xea, 0x4f, 0xe0, -0x55, 0x97, 0xc6, 0xaa, 0xc7, 0x92, 0x59, 0xe2, 0x20, 0x27, 0x00, 0x19, 0x22, 0x06, 0x04, 0xdd, -0x00, 0x4c, 0x54, 0x0b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, -0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, -0x03, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xda, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, -0x03, 0xc1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0xe9, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05, -0x03, 0xd2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x16, 0x04, 0x00, 0x00, 0x00, 0x00, 0x09, -0x03, 0x36, 0x04, 0xb7, 0x04, 0x00, 0x00, 0x0a, 0x03, 0x48, 0x05, 0x8c, 0x05, 0x00, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x21, 0x31, 0x40, 0x03, 0x03, 0x00, -0x2d, 0x32, 0x5f, 0x1f, 0x04, 0x02, 0x00, 0x2f, 0x33, 0x23, 0x05, 0x02, 0x00, 0x3b, 0x34, 0x24, -0x06, 0x02, 0x00, 0x3a, 0x35, 0xf5, 0x07, 0x02, 0x00, 0x2c, 0x36, 0x5e, 0x08, 0x02, 0x00, 0x2e, -0x37, 0x26, 0x09, 0x02, 0x00, 0x3d, 0x38, 0x2a, 0x0a, 0x03, 0x00, 0x28, 0x39, 0x5b, 0x1b, 0x0b, -0x03, 0x00, 0x29, 0x30, 0x5d, 0x1d, 0x0c, 0x02, 0x00, 0x3f, 0x2b, 0x27, 0x0d, 0xc4, 0x00, 0x78, -0x2d, 0x58, 0x2d, 0x25, 0x83, 0x18, 0x2d, 0x00, 0x83, 0x10, 0x41, 0x00, 0xd0, 0xb5, 0x11, 0x41, -0x00, 0xd8, 0xcf, 0x1a, 0x42, 0x00, 0xd4, 0xbd, 0x7b, 0x1b, 0xc4, 0x00, 0x77, 0x11, 0x57, 0x11, -0x7d, 0x11, 0x17, 0x11, 0x00, 0x11, 0x21, 0x41, 0x00, 0xd5, 0xbe, 0x27, 0x41, 0x00, 0xd6, 0xc6, -0x28, 0x42, 0x00, 0xd3, 0xb8, 0x22, 0x29, 0x02, 0x00, 0x60, 0x7e, 0xef, 0x2b, 0xc4, 0x00, 0x71, -0x10, 0x51, 0x10, 0x7c, 0x10, 0x11, 0x10, 0x00, 0x10, 0x2d, 0x41, 0x00, 0xd7, 0xc7, 0x33, 0x42, -0x00, 0xd1, 0xb6, 0xf7, 0x34, 0xc4, 0x00, 0x66, 0x21, 0x46, 0x21, 0xf2, 0x21, 0x06, 0x21, 0x00, -0x21, 0x35, 0x43, 0x00, 0xd2, 0xb7, 0x5c, 0x1c, 0x39, 0x00, 0x00, 0x20, 0x56, 0x02, 0x00, 0x3c, -0x3e, 0x2d, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0x15, 0x10, 0x41, 0x00, 0x85, 0x8f, 0x11, 0x41, -0x00, 0x91, 0x92, 0x1a, 0x41, 0x00, 0x8d, 0xad, 0x21, 0x41, 0x00, 0x9e, 0x9f, 0x27, 0x41, 0x00, -0x97, 0xa7, 0x28, 0x41, 0x00, 0x82, 0x90, 0x29, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x2d, 0x41, 0x00, -0x96, 0xa6, 0x33, 0x42, 0x00, 0x87, 0x80, 0x9d, 0x34, 0xc4, 0x00, 0x66, 0x21, 0x46, 0x21, 0xa9, -0x21, 0x06, 0x21, 0x00, 0x21, 0x35, 0x41, 0x00, 0x8a, 0x8b, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, -0x15, 0x10, 0x41, 0x00, 0xdd, 0xdc, 0x11, 0x41, 0x00, 0xfd, 0xfc, 0x1a, 0x41, 0x00, 0xf5, 0xf4, -0x21, 0x41, 0x00, 0xf7, 0xf6, 0x27, 0x41, 0x00, 0xf9, 0xf8, 0x28, 0x41, 0x00, 0xf3, 0xf2, 0x29, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x2d, 0x41, 0x00, 0xfb, 0xfa, 0x33, 0x42, 0x04, 0xdf, 0xde, 0xa0, -0x34, 0xc4, 0x04, 0x66, 0x21, 0x46, 0x21, 0xa0, 0x21, 0x06, 0x21, 0x00, 0x21, 0x35, 0xc1, 0x00, -0xf1, 0x35, 0xf0, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x06, 0x02, 0x03, -0x00, 0x00, 0x15, 0x0d, 0x84, 0x03, 0xa0, 0x2d, 0xa0, 0x2d, 0x25, 0x83, 0x18, 0x2d, 0x00, 0x83, -0x10, 0x41, 0x00, 0xef, 0x9f, 0x11, 0x41, 0x00, 0xa6, 0x86, 0x12, 0x41, 0x00, 0xa5, 0x85, 0x13, -0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xeb, 0x9b, -0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, -0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xea, 0x9a, 0x1b, 0xc4, 0x00, 0xec, 0x11, 0x9c, 0x11, -0x7d, 0x11, 0x17, 0x11, 0x00, 0x11, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, -0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe8, 0x98, 0x22, 0x41, 0x00, 0xa3, 0x83, 0x23, -0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, -0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xee, 0x9e, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x84, 0x03, 0xa0, 0x10, -0xa0, 0x10, 0x00, 0x10, 0x11, 0x10, 0x00, 0x10, 0x2c, 0x41, 0x00, 0xa7, 0x87, 0x2d, 0x41, 0x00, -0xe9, 0x99, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, -0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, 0x33, 0x42, 0x04, 0xe7, 0x97, -0xa0, 0x34, 0xc4, 0x04, 0xe4, 0x21, 0x94, 0x21, 0xa0, 0x21, 0x06, 0x21, 0x00, 0x21, 0x35, 0x01, -0x03, 0xa0, 0xa0, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0x15, 0x29, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x33, 0x42, 0x03, 0x00, 0x00, 0xf4, 0x34, 0xc4, 0x00, 0x66, 0x21, 0x46, 0x21, 0xf5, 0x21, 0x06, -0x21, 0x00, 0x21, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x06, 0x02, 0x03, 0x00, -0x00, 0x15, 0x0d, 0x84, 0x03, 0xa0, 0x2d, 0xa0, 0x2d, 0x25, 0x83, 0x18, 0x2d, 0x00, 0x83, 0x10, -0x41, 0x00, 0xef, 0x9f, 0x11, 0x41, 0x00, 0xa6, 0x86, 0x12, 0x41, 0x00, 0xa5, 0x85, 0x13, 0xc1, -0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xeb, 0x9b, 0x16, -0x41, 0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, -0x00, 0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xea, 0x9a, 0x1b, 0xc4, 0x00, 0xec, 0x11, 0x9c, 0x11, 0x7d, -0x11, 0x17, 0x11, 0x00, 0x11, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, 0x00, 0xe1, 0x91, 0x20, -0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe8, 0x98, 0x22, 0x41, 0x00, 0xa3, 0x83, 0x23, 0x41, -0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, -0xab, 0x8b, 0x27, 0x41, 0x00, 0xee, 0x9e, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, 0x84, 0x03, 0xa0, 0x10, 0xa0, -0x10, 0x00, 0x10, 0x11, 0x10, 0x00, 0x10, 0x2c, 0x41, 0x00, 0xa7, 0x87, 0x2d, 0x41, 0x00, 0xe9, -0x99, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, 0x00, 0xa1, 0x81, -0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, 0x33, 0x42, 0x00, 0xe7, 0x97, 0xf4, -0x34, 0xc4, 0x00, 0xe4, 0x21, 0x94, 0x21, 0xf5, 0x21, 0x06, 0x21, 0x00, 0x21, 0x35, 0xc1, 0x00, -0xf1, 0x35, 0xf0, 0x00, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0xbe, 0x10, 0x41, 0x00, 0xdd, 0xdc, -0x11, 0x41, 0x00, 0xfd, 0xfc, 0x1a, 0x41, 0x00, 0xf5, 0xf4, 0x21, 0x41, 0x00, 0xf7, 0xf6, 0x27, -0x41, 0x00, 0xf9, 0xf8, 0x28, 0x41, 0x00, 0xf3, 0xf2, 0x2d, 0x41, 0x00, 0xfb, 0xfa, 0x33, 0x42, -0x00, 0xdf, 0xde, 0xd5, 0x34, 0xc4, 0x00, 0x66, 0x21, 0x46, 0x21, 0xb7, 0x21, 0x06, 0x21, 0x00, -0x21, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0x15, 0x29, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x33, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x34, 0xc4, 0x04, 0x66, 0x21, -0x46, 0x21, 0xa0, 0x21, 0x06, 0x21, 0x00, 0x21, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, 0x15, 0x10, -0x41, 0x00, 0xdd, 0xdc, 0x11, 0x41, 0x00, 0xfd, 0xfc, 0x12, 0x41, 0x00, 0x65, 0x45, 0x13, 0x41, -0x00, 0x72, 0x52, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, -0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x41, 0x00, 0xf5, 0xf4, 0x1e, 0x41, 0x00, 0x61, -0x41, 0x21, 0x41, 0x00, 0xf7, 0xf6, 0x24, 0x41, 0x02, 0x6a, 0x00, 0x26, 0x41, 0x00, 0x6c, 0x4c, -0x27, 0x41, 0x00, 0xf9, 0xf8, 0x28, 0x41, 0x00, 0xf3, 0xf2, 0x29, 0x02, 0x07, 0xc8, 0xc9, 0xca, -0x2d, 0x41, 0x00, 0xfb, 0xfa, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x41, 0x00, 0x6d, 0x4d, 0x33, -0x42, 0x00, 0xdf, 0xde, 0xd5, 0x34, 0xc4, 0x00, 0x66, 0x21, 0x46, 0x21, 0xb7, 0x21, 0x06, 0x21, -0x00, 0x21, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x00, 0x60, 0x0b, 0x61, 0x83, 0x65, 0xa5, -0x69, 0xe9, 0x6f, 0xec, 0x75, 0x88, 0x41, 0xa0, 0x45, 0x8d, 0x49, 0xe8, 0x4f, 0xee, 0x55, 0xad, -0x20, 0x60, 0x7e, 0x21, 0x61, 0x86, 0xdd, 0xb5, 0x65, 0x85, 0xf1, 0xd6, 0xf3, 0x8b, 0x69, 0x9f, -0xf5, 0xe7, 0x6c, 0xe6, 0x6d, 0xbe, 0x6e, 0xd4, 0x6f, 0xe4, 0x72, 0xaf, 0x75, 0xc6, 0xf9, 0xef, -0xfb, 0xb8, 0x79, 0xa4, 0x41, 0x8f, 0xdc, 0xbd, 0x45, 0x95, 0xf0, 0x9c, 0xf2, 0x8a, 0x49, 0xd0, -0xf4, 0xe3, 0x4c, 0xa6, 0x4d, 0xa7, 0x4e, 0xa8, 0x4f, 0xe5, 0x52, 0xae, 0x55, 0x9e, 0xf8, 0xab, -0xfa, 0xa9, 0x59, 0xa3, 0x20, 0x7e, 0x27, 0x19, 0x61, 0x87, 0xdd, 0x89, 0x65, 0x82, 0xf1, 0xd8, -0xf3, 0x9b, 0x69, 0x8c, 0xf5, 0xeb, 0x6f, 0xa2, 0x75, 0x98, 0xf9, 0xac, 0xfb, 0x91, 0x79, 0x93, -0x41, 0x80, 0xdc, 0xed, 0x45, 0x90, 0xf0, 0x96, 0xf2, 0x9d, 0x49, 0xa1, 0xf4, 0xea, 0x4f, 0xe0, -0x55, 0x97, 0xf8, 0xaa, 0xfa, 0x92, 0x59, 0xe2, 0x20, 0x27, 0x00, 0x06, 0x02, 0x03, 0x00, 0x00, -0x15, 0x12, 0x41, 0x00, 0x65, 0x45, 0x13, 0x41, 0x00, 0x72, 0x52, 0x15, 0x41, 0x00, 0x79, 0x59, -0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1e, -0x41, 0x00, 0x61, 0x41, 0x24, 0x41, 0x02, 0x6a, 0x00, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x29, 0x02, -0x07, 0xc8, 0xc9, 0xca, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x32, 0x41, 0x00, 0x6d, 0x4d, 0x00, 0x60, -0x0b, 0x61, 0x83, 0x65, 0xa5, 0x69, 0xe9, 0x6f, 0xec, 0x75, 0x88, 0x41, 0xa0, 0x45, 0x8d, 0x49, -0xe8, 0x4f, 0xee, 0x55, 0xad, 0x20, 0x60, 0x7e, 0x21, 0x61, 0x86, 0xd0, 0xf1, 0x65, 0x85, 0xd2, -0xfc, 0xd3, 0x8b, 0x69, 0x9f, 0xd4, 0xe7, 0x6c, 0xe6, 0x6d, 0xf5, 0x6e, 0xfb, 0x6f, 0xe4, 0x72, -0xaf, 0x75, 0xf6, 0xd6, 0xef, 0xd7, 0xf3, 0x79, 0xa4, 0x41, 0x8f, 0xb5, 0xf4, 0x45, 0x95, 0xb7, -0x9c, 0xb8, 0x8a, 0x49, 0xf8, 0xbd, 0xe3, 0x4c, 0xa6, 0x4d, 0xa7, 0x4e, 0xa8, 0x4f, 0xe5, 0x52, -0xae, 0x55, 0x9e, 0xc6, 0xab, 0xc7, 0xa9, 0x59, 0xa3, 0x20, 0x7e, 0x27, 0x19, 0x61, 0x87, 0xd0, -0x89, 0x65, 0x82, 0xd2, 0xfd, 0xd3, 0x9b, 0x69, 0x8c, 0xd4, 0xeb, 0x6f, 0xa2, 0x75, 0x98, 0xd6, -0xac, 0xd7, 0x91, 0x79, 0x93, 0x41, 0x80, 0xb5, 0xed, 0x45, 0x90, 0xb7, 0x96, 0xb8, 0x9d, 0x49, -0xa1, 0xbd, 0xea, 0x4f, 0xe0, 0x55, 0x97, 0xc6, 0xaa, 0xc7, 0x92, 0x59, 0xe2, 0x20, 0x27, 0x00, -0x06, 0x5a, 0x08, 0x04, 0xc8, 0x01, 0x4c, 0x54, 0x0f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, -0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x1b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x23, 0x01, -0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x94, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0xd8, 0x01, -0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x60, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0xa4, 0x02, -0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x71, 0x03, -0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xf9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x84, 0x04, -0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x2f, 0x05, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x33, 0x06, -0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0xa8, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x4f, 0x07, -0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0xac, 0x03, 0x02, 0x03, 0x00, 0x00, 0xab, -0x04, 0x02, 0x03, 0x00, 0x00, 0xf3, 0x05, 0x02, 0x03, 0x00, 0x00, 0x9f, 0x06, 0x02, 0x03, 0x00, -0x00, 0x96, 0x07, 0x02, 0x03, 0x00, 0x00, 0xf8, 0x08, 0x02, 0x03, 0x00, 0x00, 0xf5, 0x09, 0x02, -0x03, 0x00, 0x00, 0x9e, 0x0a, 0x02, 0x03, 0x00, 0x00, 0xae, 0x0b, 0x02, 0x03, 0x00, 0x00, 0xaf, -0x0d, 0x02, 0x03, 0x00, 0x00, 0xf1, 0x10, 0x42, 0x03, 0x00, 0x00, 0xfb, 0x11, 0x42, 0x03, 0x00, -0x00, 0xfd, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfc, 0x13, 0x42, 0x03, 0x00, 0x00, 0xa9, 0x1f, 0x42, -0x03, 0x00, 0x00, 0xe1, 0x26, 0x42, 0x03, 0x00, 0x00, 0x9c, 0x31, 0x42, 0x03, 0x00, 0x00, 0xaa, -0x34, 0x02, 0x03, 0x00, 0x00, 0xfa, 0x35, 0x02, 0x03, 0x00, 0x00, 0xf6, 0x56, 0x02, 0x00, 0xfd, -0xfc, 0xfb, 0x00, 0x36, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x79, 0x00, 0x02, 0x01, 0x00, 0x21, 0x31, -0x03, 0x01, 0x00, 0x22, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x3b, 0x34, 0x06, -0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, -0x00, 0x3f, 0x38, 0x0a, 0x01, 0x00, 0x28, 0x39, 0x0b, 0x01, 0x00, 0x29, 0x30, 0x0d, 0x01, 0x00, -0x2b, 0x3d, 0x10, 0x41, 0x00, 0xd0, 0xb5, 0x11, 0x41, 0x00, 0xd8, 0xcf, 0x1a, 0x41, 0x00, 0xd4, -0xbd, 0x1b, 0x01, 0x00, 0xf7, 0xf2, 0x27, 0x41, 0x00, 0xd6, 0xc6, 0x28, 0x41, 0x00, 0xd3, 0xb8, -0x2a, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x78, 0x2d, 0x41, 0x00, 0xd7, 0xc7, 0x33, 0x41, 0x00, 0xd1, -0xb6, 0x34, 0x41, 0x00, 0xd5, 0xbe, 0x35, 0x41, 0x00, 0xd2, 0xb7, 0x00, 0x04, 0x02, 0x03, 0x00, -0x00, 0xb8, 0x07, 0x02, 0x03, 0x00, 0x00, 0xd0, 0x08, 0x02, 0x03, 0x00, 0x00, 0xbe, 0x0d, 0x02, -0x03, 0x00, 0x00, 0xb5, 0x10, 0x42, 0x03, 0x00, 0x00, 0xd4, 0x11, 0x42, 0x03, 0x00, 0x00, 0xd8, -0x12, 0x42, 0x03, 0x00, 0x00, 0xd6, 0x34, 0x02, 0x03, 0x00, 0x00, 0xd3, 0x35, 0x02, 0x03, 0x00, -0x00, 0xc6, 0x36, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x7b, 0x56, 0x02, 0x00, 0xd8, 0xd6, 0xd4, 0x00, -0x02, 0x01, 0x00, 0x21, 0x31, 0x03, 0x01, 0x00, 0x22, 0x32, 0x04, 0x02, 0x00, 0x2f, 0x33, 0xb8, -0x05, 0x01, 0x00, 0x3b, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x02, 0x00, 0x2c, 0x36, 0xd0, -0x08, 0x02, 0x00, 0x2e, 0x37, 0xbe, 0x09, 0x01, 0x00, 0x3f, 0x38, 0x0a, 0x01, 0x00, 0x28, 0x39, -0x0b, 0x01, 0x00, 0x29, 0x30, 0x0d, 0x02, 0x00, 0x2b, 0x3d, 0xb5, 0x10, 0x42, 0x00, 0xdd, 0xdc, -0xd4, 0x11, 0x42, 0x00, 0xfd, 0xfc, 0xd8, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd6, 0x1a, 0x41, 0x00, -0xf5, 0xf4, 0x1b, 0x01, 0x00, 0xd5, 0xb7, 0x27, 0x41, 0x00, 0xf9, 0xf8, 0x28, 0x41, 0x00, 0xf3, -0xf2, 0x2a, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x7a, 0x2d, 0x41, 0x00, 0xfb, 0xfa, 0x33, 0x41, 0x00, -0xdf, 0xde, 0x34, 0x42, 0x00, 0xf7, 0xf6, 0xd3, 0x35, 0xc2, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0xc6, -0x35, 0x56, 0x02, 0x00, 0xd8, 0xd6, 0xd4, 0x00, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, -0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0x9b, 0x08, 0x02, 0x03, 0x00, 0x00, 0x15, -0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x10, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x07, 0x00, -0x00, 0xa0, 0x13, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x26, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x36, 0x03, -0x0f, 0x00, 0x00, 0x00, 0x7d, 0x56, 0x02, 0x07, 0x00, 0xa0, 0xa0, 0x00, 0x02, 0x01, 0x00, 0x21, -0x31, 0x03, 0x01, 0x00, 0x22, 0x32, 0x04, 0x02, 0x04, 0x2f, 0x33, 0xa0, 0x05, 0x02, 0x04, 0x3b, -0x34, 0xa0, 0x06, 0x02, 0x00, 0x3a, 0x35, 0x9b, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x02, 0x00, -0x2e, 0x37, 0x15, 0x09, 0x02, 0x04, 0x3f, 0x38, 0xa0, 0x0a, 0x01, 0x00, 0x28, 0x39, 0x0b, 0x01, -0x00, 0x29, 0x30, 0x0d, 0x01, 0x00, 0x2b, 0x3d, 0x10, 0x42, 0x04, 0x85, 0x8f, 0xa0, 0x11, 0x41, -0x00, 0x91, 0x92, 0x12, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x13, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x1a, -0x41, 0x00, 0x8d, 0xad, 0x1b, 0x01, 0x00, 0x9d, 0xa9, 0x26, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x27, -0x41, 0x00, 0x97, 0xa7, 0x28, 0x41, 0x00, 0x82, 0x90, 0x2a, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x7c, -0x2d, 0x41, 0x00, 0x96, 0xa6, 0x33, 0x41, 0x00, 0x87, 0x80, 0x34, 0x41, 0x00, 0x9e, 0x9f, 0x35, -0x41, 0x00, 0x8a, 0x8b, 0x56, 0x02, 0x07, 0x00, 0xa0, 0xa0, 0x00, 0x04, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x03, 0x00, 0x00, 0x9b, 0x08, 0x02, 0x03, -0x00, 0x00, 0x15, 0x09, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x10, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x12, -0x42, 0x07, 0x00, 0x00, 0xa0, 0x13, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x36, 0x03, 0x0f, 0x00, 0x00, -0x00, 0x7f, 0x56, 0x02, 0x06, 0xfd, 0xa0, 0xa0, 0x00, 0x02, 0x01, 0x00, 0x21, 0x31, 0x03, 0x01, -0x00, 0x22, 0x32, 0x04, 0x02, 0x04, 0x2f, 0x33, 0xa0, 0x05, 0x02, 0x04, 0x3b, 0x34, 0xa0, 0x06, -0x02, 0x00, 0x3a, 0x35, 0x9b, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x02, 0x00, 0x2e, 0x37, 0x15, -0x09, 0x02, 0x04, 0x3f, 0x38, 0xa0, 0x0a, 0x01, 0x00, 0x28, 0x39, 0x0b, 0x01, 0x00, 0x29, 0x30, -0x0d, 0x01, 0x00, 0x2b, 0x3d, 0x10, 0x42, 0x04, 0xd0, 0xb5, 0xa0, 0x11, 0x41, 0x00, 0xd8, 0xcf, -0x12, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x13, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x1a, 0x41, 0x00, 0xd4, -0xbd, 0x1b, 0x10, 0x00, 0x00, 0x27, 0x41, 0x00, 0xd6, 0xc6, 0x28, 0x41, 0x00, 0xd3, 0xb8, 0x2a, -0x03, 0x0f, 0x00, 0x00, 0x00, 0x7e, 0x2d, 0x41, 0x00, 0xd7, 0xc7, 0x33, 0x41, 0x00, 0xd1, 0xb6, -0x34, 0x41, 0x00, 0xd5, 0xbe, 0x35, 0x41, 0x00, 0xd2, 0xb7, 0x56, 0x02, 0x07, 0x00, 0xa0, 0xa0, -0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x03, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x07, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x03, 0x00, 0x00, 0x15, 0x09, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0d, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x10, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x11, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x12, -0x42, 0x07, 0x00, 0x00, 0xa0, 0x13, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x1d, 0x03, 0x0f, 0x00, 0x00, -0x00, 0x82, 0x1f, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x26, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x31, 0x42, -0x07, 0x00, 0x00, 0xa0, 0x34, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x35, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x36, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x81, 0x56, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x21, -0x31, 0xa0, 0x03, 0x02, 0x04, 0x22, 0x32, 0xa0, 0x04, 0x02, 0x04, 0x2f, 0x33, 0xa0, 0x05, 0x02, -0x04, 0x3b, 0x34, 0xa0, 0x06, 0x02, 0x04, 0x3a, 0x35, 0xa0, 0x07, 0x02, 0x04, 0x2c, 0x36, 0xa0, -0x08, 0x02, 0x00, 0x2e, 0x37, 0x15, 0x09, 0x02, 0x04, 0x3f, 0x38, 0xa0, 0x0a, 0x02, 0x04, 0x28, -0x39, 0xa0, 0x0b, 0x02, 0x04, 0x29, 0x30, 0xa0, 0x0d, 0x02, 0x04, 0x2b, 0x3d, 0xa0, 0x10, 0x42, -0x04, 0xdd, 0xdc, 0xa0, 0x11, 0x42, 0x04, 0xfd, 0xfc, 0xa0, 0x12, 0x42, 0x07, 0x00, 0x00, 0xa0, -0x13, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x1a, 0x41, 0x00, 0xf5, 0xf4, 0x1b, 0x10, 0x00, 0x00, 0x1d, -0x03, 0x0f, 0x00, 0x00, 0x00, 0x82, 0x1f, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x26, 0x42, 0x07, 0x00, -0x00, 0xa0, 0x27, 0x41, 0x00, 0xf9, 0xf8, 0x28, 0x41, 0x00, 0xf3, 0xf2, 0x2a, 0x03, 0x0f, 0x00, -0x00, 0x00, 0x80, 0x2d, 0x41, 0x00, 0xfb, 0xfa, 0x31, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x33, 0x41, -0x00, 0xdf, 0xde, 0x34, 0x42, 0x04, 0xf7, 0xf6, 0xa0, 0x35, 0xc2, 0x04, 0xf1, 0x35, 0xf0, 0x00, -0xa0, 0x35, 0x56, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x21, 0x31, 0xa0, 0x03, 0x02, 0x04, -0x22, 0x32, 0xa0, 0x04, 0x02, 0x04, 0x2f, 0x33, 0xa0, 0x05, 0x02, 0x04, 0x3b, 0x34, 0xa0, 0x06, -0x02, 0x04, 0x3a, 0x35, 0xa0, 0x07, 0x02, 0x04, 0x2c, 0x36, 0xa0, 0x08, 0x02, 0x00, 0x2e, 0x37, -0x15, 0x09, 0x02, 0x04, 0x3f, 0x38, 0xa0, 0x0a, 0x02, 0x04, 0x28, 0x39, 0xa0, 0x0b, 0x02, 0x04, -0x29, 0x30, 0xa0, 0x0d, 0x02, 0x04, 0x2b, 0x3d, 0xa0, 0x10, 0x42, 0x04, 0xef, 0x9f, 0xa0, 0x11, -0x42, 0x04, 0xa6, 0x86, 0xa0, 0x12, 0x42, 0x04, 0xa5, 0x85, 0xa0, 0x13, 0xc2, 0x04, 0xe0, 0x00, -0x90, 0x13, 0xa0, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xeb, 0x9b, 0x16, 0x41, -0x00, 0xe3, 0x93, 0x17, 0x41, 0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, -0xaf, 0x8f, 0x1a, 0x41, 0x00, 0xea, 0x9a, 0x1b, 0x41, 0x00, 0xec, 0x9c, 0x1e, 0x41, 0x00, 0xa0, -0x80, 0x1f, 0x42, 0x04, 0xe1, 0x91, 0xa0, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, -0x94, 0x22, 0x41, 0x00, 0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa9, 0x89, -0x25, 0x41, 0x00, 0xaa, 0x8a, 0x26, 0x42, 0x04, 0xab, 0x8b, 0xa0, 0x27, 0x41, 0x00, 0xee, 0x9e, -0x28, 0x41, 0x00, 0xed, 0x9d, 0x2a, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x41, 0x00, 0xa7, -0x87, 0x2d, 0x41, 0x00, 0xe9, 0x99, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, -0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x42, 0x04, 0xad, 0x8d, 0xa0, 0x32, 0x41, 0x00, 0xac, 0x8c, -0x33, 0x41, 0x00, 0xe7, 0x97, 0x34, 0x42, 0x04, 0xe8, 0x98, 0xa0, 0x35, 0x10, 0x00, 0x00, 0x36, -0x03, 0x0f, 0x00, 0x00, 0x00, 0x81, 0x56, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x03, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x02, 0x07, -0x00, 0x00, 0xa0, 0x06, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x03, 0x00, 0x00, 0x15, 0x09, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x0b, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x10, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x07, -0x00, 0x00, 0xa0, 0x13, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x1d, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x85, -0x1f, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x26, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x31, 0x42, 0x07, 0x00, -0x00, 0xa0, 0x36, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x84, 0x56, 0x02, 0x07, 0x00, 0xa0, 0xa0, 0x00, -0x02, 0x02, 0x04, 0x21, 0x31, 0xa0, 0x03, 0x02, 0x04, 0x22, 0x32, 0xa0, 0x04, 0x02, 0x04, 0x2f, -0x33, 0xa0, 0x05, 0x02, 0x04, 0x3b, 0x34, 0xa0, 0x06, 0x02, 0x04, 0x3a, 0x35, 0xa0, 0x07, 0x01, -0x00, 0x2c, 0x36, 0x08, 0x02, 0x00, 0x2e, 0x37, 0x15, 0x09, 0x02, 0x04, 0x3f, 0x38, 0xa0, 0x0a, -0x02, 0x04, 0x28, 0x39, 0xa0, 0x0b, 0x02, 0x04, 0x29, 0x30, 0xa0, 0x0d, 0x02, 0x04, 0x2b, 0x3d, -0xa0, 0x10, 0x42, 0x04, 0xd0, 0xb5, 0xa0, 0x11, 0x41, 0x00, 0xd8, 0xcf, 0x12, 0x42, 0x07, 0x00, -0x00, 0xa0, 0x13, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x1a, 0x41, 0x00, 0xd4, 0xbd, 0x1b, 0x01, 0x00, -0xf4, 0xf5, 0x1d, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x85, 0x1f, 0x42, 0x07, 0x00, 0x00, 0xa0, 0x26, -0x42, 0x07, 0x00, 0x00, 0xa0, 0x27, 0x41, 0x00, 0xd6, 0xc6, 0x28, 0x41, 0x00, 0xd3, 0xb8, 0x2a, -0x03, 0x0f, 0x00, 0x00, 0x00, 0x83, 0x2d, 0x41, 0x00, 0xd7, 0xc7, 0x31, 0x42, 0x07, 0x00, 0x00, -0xa0, 0x33, 0x41, 0x00, 0xd1, 0xb6, 0x34, 0x41, 0x00, 0xd5, 0xbe, 0x35, 0x41, 0x00, 0xd2, 0xb7, -0x56, 0x02, 0x07, 0x00, 0xa0, 0xa0, 0x00, 0x02, 0x02, 0x04, 0x21, 0x31, 0xa0, 0x03, 0x02, 0x04, -0x22, 0x32, 0xa0, 0x04, 0x02, 0x04, 0x2f, 0x33, 0xa0, 0x05, 0x02, 0x04, 0x3b, 0x34, 0xa0, 0x06, -0x02, 0x04, 0x3a, 0x35, 0xa0, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x02, 0x00, 0x2e, 0x37, 0x15, -0x09, 0x02, 0x04, 0x3f, 0x38, 0xa0, 0x0a, 0x02, 0x04, 0x28, 0x39, 0xa0, 0x0b, 0x02, 0x04, 0x29, -0x30, 0xa0, 0x0d, 0x02, 0x04, 0x2b, 0x3d, 0xa0, 0x10, 0x42, 0x04, 0xef, 0x9f, 0xa0, 0x11, 0x41, -0x00, 0xa6, 0x86, 0x12, 0x42, 0x04, 0xa5, 0x85, 0xa0, 0x13, 0xc2, 0x04, 0xe0, 0x00, 0x90, 0x13, -0xa0, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xeb, 0x9b, 0x16, 0x41, 0x00, 0xe3, -0x93, 0x17, 0x41, 0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, -0x1a, 0x41, 0x00, 0xea, 0x9a, 0x1b, 0x41, 0x00, 0xec, 0x9c, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, -0x42, 0x04, 0xe1, 0x91, 0xa0, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, -0x41, 0x00, 0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, -0x00, 0xaa, 0x8a, 0x26, 0x42, 0x04, 0xab, 0x8b, 0xa0, 0x27, 0x41, 0x00, 0xee, 0x9e, 0x28, 0x41, -0x00, 0xed, 0x9d, 0x2a, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x83, 0x2c, 0x41, 0x00, 0xa7, 0x87, 0x2d, -0x41, 0x00, 0xe9, 0x99, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, -0x00, 0xa1, 0x81, 0x31, 0x42, 0x04, 0xad, 0x8d, 0xa0, 0x32, 0x41, 0x00, 0xac, 0x8c, 0x33, 0x41, -0x00, 0xe7, 0x97, 0x34, 0x41, 0x00, 0xe8, 0x98, 0x35, 0xc1, 0x00, 0xf1, 0x35, 0xf0, 0x00, 0x36, -0x03, 0x0f, 0x00, 0x00, 0x00, 0x84, 0x56, 0x02, 0x07, 0x00, 0xa0, 0xa0, 0x00, 0x80, 0x8a, 0x04, -0x04, 0x00, 0x00, 0x4c, 0x56, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, -0x00, 0x07, 0x03, 0xd1, 0x00, 0x1f, 0x01, 0x00, 0x00, 0x02, 0x03, 0x64, 0x01, 0xce, 0x01, 0x00, -0x00, 0x05, 0x03, 0xef, 0x01, 0x3d, 0x02, 0x00, 0x00, 0x5d, 0x04, 0x82, 0x02, 0xd0, 0x02, 0x00, -0x00, 0x62, 0xef, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x62, 0xef, 0xa0, 0x03, 0x00, 0x00, 0x00, -0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0xff, 0x03, -0x02, 0x03, 0x00, 0x00, 0xae, 0x04, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x09, 0x03, 0x07, 0x00, 0x00, -0x00, 0x9e, 0x12, 0x43, 0x00, 0x65, 0x45, 0x89, 0xed, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x43, -0x03, 0x00, 0x00, 0x8c, 0xa1, 0x18, 0x43, 0x00, 0x6f, 0x4f, 0xe4, 0xe5, 0x1e, 0x43, 0x00, 0x61, -0x41, 0x83, 0xa0, 0x1f, 0x41, 0x00, 0x73, 0x53, 0x22, 0x43, 0x03, 0x00, 0x00, 0x85, 0x95, 0x28, -0x03, 0x0f, 0x00, 0x00, 0xca, 0xcb, 0x29, 0x02, 0x03, 0x00, 0xc9, 0x2d, 0x2b, 0x02, 0x01, 0xc8, -0x7c, 0x5c, 0x2c, 0x41, 0x00, 0x7a, 0x5a, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, -0x4e, 0x39, 0x00, 0x00, 0x20, 0x00, 0x05, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf5, 0x06, 0x03, 0x07, -0x00, 0x00, 0x00, 0xf8, 0x08, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf1, 0x13, 0x43, 0x03, 0x00, 0x00, -0x8b, 0x8a, 0x16, 0x43, 0x03, 0x00, 0x00, 0xd7, 0xc7, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xd5, 0xbe, -0x25, 0x43, 0x03, 0x00, 0x00, 0xe9, 0xe8, 0x26, 0x43, 0x03, 0x00, 0x00, 0xeb, 0xea, 0x2c, 0x43, -0x03, 0x00, 0x00, 0xd8, 0xcf, 0x2e, 0x43, 0x03, 0x00, 0x00, 0xd1, 0xb6, 0x31, 0x43, 0x03, 0x00, -0x00, 0xec, 0xee, 0x00, 0xf8, 0x07, 0x61, 0x86, 0x65, 0xd3, 0x7a, 0xa4, 0x41, 0x8f, 0x45, 0xb8, -0x5a, 0xa3, 0x20, 0xf8, 0x7e, 0x03, 0x6f, 0xe4, 0x4f, 0xe5, 0x20, 0x7e, 0xef, 0x0d, 0x63, 0x87, -0x65, 0x82, 0x6e, 0xe7, 0x6f, 0xa2, 0x73, 0x98, 0x7a, 0xa5, 0x43, 0x80, 0x45, 0x90, 0x4e, 0xe3, -0x4f, 0xe0, 0x53, 0x97, 0x5a, 0x8d, 0x20, 0xef, 0x22, 0x07, 0x61, 0x84, 0x6f, 0x94, 0x75, 0x81, -0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x05, 0x03, 0x07, 0x00, 0x00, 0x00, 0x15, -0x06, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf1, 0x09, 0x03, -0x0f, 0x00, 0x00, 0x00, 0xa0, 0x12, 0x43, 0x03, 0x00, 0x00, 0x88, 0x89, 0x16, 0x43, 0x03, 0x00, -0x00, 0x96, 0xa6, 0x18, 0x43, 0x03, 0x00, 0x00, 0x93, 0x95, 0x1f, 0x43, 0x03, 0x00, 0x00, 0x9e, -0x9f, 0x22, 0x43, 0x03, 0x00, 0x00, 0x98, 0xa8, 0x25, 0x43, 0x03, 0x00, 0x00, 0xa2, 0xa3, 0x26, -0x43, 0x03, 0x00, 0x00, 0x86, 0x9c, 0x28, 0x03, 0x0f, 0x00, 0x00, 0xa0, 0xca, 0x2c, 0x43, 0x03, -0x00, 0x00, 0x91, 0x92, 0x2e, 0x43, 0x03, 0x00, 0x00, 0x87, 0x80, 0x31, 0x43, 0x03, 0x00, 0x00, -0xa4, 0xa5, 0x00, 0xfa, 0x03, 0x65, 0x82, 0x45, 0x90, 0x20, 0xfa, 0x7e, 0x03, 0x6f, 0x93, 0x4f, -0x95, 0x20, 0x7e, 0x22, 0x07, 0x61, 0x84, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x4f, 0x99, 0x55, -0x9a, 0x20, 0x22, 0x00, 0x05, 0x03, 0x07, 0x00, 0x00, 0x00, 0xbe, 0x06, 0x03, 0x07, 0x00, 0x00, -0x00, 0xd0, 0x08, 0x03, 0x07, 0x00, 0x00, 0x00, 0xb5, 0x13, 0x43, 0x03, 0x00, 0x00, 0x8b, 0x8a, -0x16, 0x43, 0x03, 0x00, 0x00, 0xfb, 0xfa, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xf7, 0xf6, 0x25, 0x43, -0x03, 0x00, 0x00, 0xe9, 0xe8, 0x26, 0x43, 0x03, 0x00, 0x00, 0xeb, 0xea, 0x2c, 0x43, 0x03, 0x00, -0x00, 0xfd, 0xfc, 0x2e, 0x43, 0x03, 0x00, 0x00, 0xdf, 0xde, 0x31, 0x43, 0x03, 0x00, 0x00, 0xec, -0xee, 0x00, 0xd3, 0x07, 0x61, 0x86, 0x65, 0xf3, 0x7a, 0xa4, 0x41, 0x8f, 0x45, 0xf2, 0x5a, 0xa3, -0x20, 0xd3, 0x7e, 0x03, 0x6f, 0xe4, 0x4f, 0xe5, 0x20, 0x7e, 0xef, 0x0d, 0x63, 0x87, 0x65, 0x82, -0x6e, 0xe7, 0x6f, 0xa2, 0x73, 0x98, 0x7a, 0xa5, 0x43, 0x80, 0x45, 0x90, 0x4e, 0xe3, 0x4f, 0xe0, -0x53, 0x97, 0x5a, 0x8d, 0x20, 0xef, 0x22, 0x07, 0x61, 0x84, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, -0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x05, 0x03, 0x07, 0x00, 0x00, 0x00, 0x15, 0x06, 0x03, -0x07, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf1, 0x13, 0x43, 0x03, 0x00, -0x00, 0xfb, 0xfc, 0x16, 0x43, 0x03, 0x00, 0x00, 0x96, 0xea, 0x1f, 0x43, 0x03, 0x00, 0x00, 0xe7, -0xe6, 0x25, 0x43, 0x03, 0x00, 0x00, 0xe9, 0xe8, 0x26, 0x43, 0x03, 0x00, 0x00, 0xec, 0x9c, 0x2c, -0x43, 0x03, 0x00, 0x00, 0xa7, 0xa6, 0x2e, 0x43, 0x03, 0x00, 0x00, 0x9f, 0xac, 0x31, 0x43, 0x03, -0x00, 0x00, 0xef, 0xee, 0x00, 0xf8, 0x07, 0x61, 0x86, 0x65, 0x8a, 0x7a, 0x92, 0x41, 0x8f, 0x45, -0xaa, 0x5a, 0x91, 0x20, 0xf8, 0x7e, 0x03, 0x6f, 0xe4, 0x4f, 0xe5, 0x20, 0x7e, 0x27, 0x0d, 0x63, -0x87, 0x65, 0x82, 0x6e, 0x9b, 0x6f, 0xa2, 0x73, 0x98, 0x7a, 0xab, 0x43, 0x80, 0x45, 0x90, 0x4e, -0xe3, 0x4f, 0xe0, 0x53, 0x97, 0x5a, 0x8d, 0x20, 0x27, 0x22, 0x07, 0x61, 0x84, 0x6f, 0x94, 0x75, -0x81, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x03, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x04, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x05, 0x03, 0x07, 0x00, 0x00, 0x00, 0x15, 0x09, 0x03, 0x0f, -0x00, 0x00, 0x00, 0xa0, 0x12, 0xc3, 0x00, 0x65, 0x12, 0x45, 0x12, 0xf1, 0x12, 0xf0, 0x00, 0x16, -0x43, 0x03, 0x00, 0x00, 0xdd, 0xde, 0x17, 0x43, 0x03, 0x00, 0x00, 0xd8, 0xd7, 0x18, 0x43, 0x0f, -0x00, 0x00, 0xa0, 0xa0, 0x1e, 0x43, 0x03, 0x00, 0x00, 0xc6, 0xb5, 0x1f, 0x43, 0x03, 0x00, 0x00, -0xfd, 0xd0, 0x22, 0x43, 0x03, 0x00, 0x00, 0xd6, 0xf2, 0x25, 0x43, 0x03, 0x00, 0x00, 0xf3, 0xf4, -0x26, 0x43, 0x03, 0x00, 0x00, 0xf5, 0xf6, 0x28, 0x03, 0x0f, 0x00, 0x00, 0xa0, 0xa0, 0x29, 0x01, -0x01, 0x00, 0x7e, 0x2b, 0x00, 0x01, 0xa0, 0x2c, 0x43, 0x03, 0x00, 0x00, 0xf7, 0xf8, 0x2e, 0x43, -0x03, 0x00, 0x00, 0xd2, 0xd3, 0x31, 0x43, 0x03, 0x00, 0x00, 0xb7, 0xfc, 0x36, 0x04, 0x1f, 0x00, -0x00, 0x00, 0x00, 0x7d, 0x00, 0x03, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x04, 0x02, 0x07, 0x00, 0x00, -0xa0, 0x05, 0x03, 0x07, 0x00, 0x00, 0x00, 0x15, 0x09, 0x03, 0x0f, 0x00, 0x00, 0x00, 0xa0, 0x10, -0x41, 0x00, 0xef, 0x9f, 0x11, 0x41, 0x00, 0xe8, 0x98, 0x12, 0x43, 0x0c, 0xa5, 0x85, 0xa0, 0xa0, -0x13, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xeb, -0x9b, 0x16, 0x41, 0x00, 0xe3, 0x93, 0x17, 0x43, 0x0c, 0xa8, 0x88, 0xa0, 0xa0, 0x18, 0x43, 0x0c, -0xae, 0x8e, 0xa0, 0xa0, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, 0x43, 0x00, 0xed, 0x9d, 0x5b, 0x7b, -0x1b, 0x43, 0x00, 0xee, 0x9e, 0x5d, 0x7d, 0x1e, 0x43, 0x0c, 0xa0, 0x80, 0xa0, 0xa0, 0x1f, 0x41, -0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x43, 0x0c, -0xa3, 0x83, 0xa0, 0xa0, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa9, 0x89, 0x25, 0x41, -0x00, 0xaa, 0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xe7, 0x97, 0x28, 0x43, 0x00, -0xec, 0x9c, 0x27, 0x22, 0x29, 0x43, 0x00, 0xea, 0x9a, 0x60, 0x7e, 0x2a, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x7c, 0x2b, 0x43, 0x00, 0xe9, 0x99, 0x5c, 0x7c, 0x2c, 0x41, 0x00, 0xa7, 0x87, 0x2d, -0x41, 0x00, 0xa6, 0x86, 0x2e, 0x41, 0x00, 0xe6, 0x96, 0x2f, 0x41, 0x00, 0xa2, 0x82, 0x30, 0x41, -0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, 0xac, 0x8c, 0x33, 0x02, 0x03, -0x00, 0x00, 0x3b, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3a, 0x00, 0x0c, 0xfd, 0x05, 0x04, 0xc7, 0x01, -0x4c, 0x56, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, -0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, -0x7a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x88, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, -0x5e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x6b, 0x02, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x04, -0x4a, 0x03, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x04, 0x58, 0x03, 0x00, 0x00, 0x00, 0x00, 0x62, 0xef, -0x37, 0x04, 0x00, 0x00, 0x00, 0x00, 0x62, 0xef, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x62, 0xef, -0x27, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x01, -0x00, 0xf8, 0xa7, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x03, 0x01, 0x01, -0x00, 0xae, 0x04, 0x01, 0x01, 0x00, 0xaf, 0x05, 0x01, 0x01, 0x00, 0xf5, 0x07, 0x01, 0x01, 0x00, -0x2f, 0x09, 0x01, 0x01, 0x00, 0x9e, 0x0d, 0x41, 0x00, 0x66, 0x46, 0x10, 0x41, 0x00, 0xd7, 0xc7, -0x11, 0x41, 0x00, 0x67, 0x47, 0x12, 0x41, 0x00, 0x6a, 0x4a, 0x13, 0x43, 0x03, 0x00, 0x00, 0x8b, -0x8a, 0x14, 0x41, 0x00, 0x6d, 0x4d, 0x15, 0x41, 0x00, 0x76, 0x56, 0x16, 0x41, 0x00, 0x6e, 0x4e, -0x17, 0x41, 0x00, 0x7a, 0x5a, 0x18, 0x41, 0x00, 0x89, 0xed, 0x19, 0x41, 0x00, 0xd1, 0xb6, 0x1a, -0x41, 0x00, 0xd8, 0xcf, 0x1b, 0x41, 0x00, 0x68, 0x48, 0x1e, 0x41, 0x00, 0xd5, 0xbe, 0x1f, 0x41, -0x00, 0x75, 0x55, 0x20, 0x41, 0x00, 0x73, 0x53, 0x21, 0x41, 0x00, 0x69, 0x49, 0x22, 0x41, 0x00, -0x6c, 0x4c, 0x23, 0x41, 0x00, 0x64, 0x44, 0x24, 0x41, 0x00, 0x61, 0x41, 0x25, 0x41, 0x00, 0x74, -0x54, 0x26, 0x41, 0x00, 0x65, 0x45, 0x27, 0x41, 0x00, 0x63, 0x43, 0x28, 0x01, 0x00, 0x27, 0xf8, -0x29, 0x01, 0x00, 0x2d, 0x3f, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x41, 0x00, -0xe9, 0xe8, 0x2c, 0x41, 0x00, 0xec, 0xee, 0x2d, 0x41, 0x00, 0x62, 0x42, 0x2e, 0x41, 0x00, 0x8c, -0xa1, 0x2f, 0x41, 0x00, 0x6b, 0x4b, 0x30, 0x41, 0x00, 0x70, 0x50, 0x31, 0x43, 0x00, 0x6f, 0x4f, -0x93, 0xe2, 0x32, 0x41, 0x00, 0x83, 0xa0, 0x33, 0x01, 0x01, 0x00, 0x3b, 0x34, 0x01, 0x01, 0x00, -0x3a, 0x35, 0x41, 0x00, 0xeb, 0xea, 0x56, 0x41, 0x00, 0x85, 0x95, 0x00, 0x2b, 0x01, 0x03, 0x00, -0xa0, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x03, 0x01, 0x01, 0x00, 0xae, 0x04, -0x01, 0x01, 0x00, 0xaf, 0x05, 0x01, 0x01, 0x00, 0x15, 0x07, 0x01, 0x01, 0x00, 0x2f, 0x09, 0x01, -0x03, 0x00, 0xa0, 0x0d, 0x41, 0x00, 0x66, 0x46, 0x10, 0x41, 0x00, 0x96, 0xa6, 0x11, 0x41, 0x00, -0x67, 0x47, 0x12, 0x41, 0x00, 0x6a, 0x4a, 0x14, 0x41, 0x00, 0x6d, 0x4d, 0x15, 0x41, 0x00, 0x76, -0x56, 0x16, 0x41, 0x00, 0x6e, 0x4e, 0x17, 0x41, 0x00, 0x7a, 0x5a, 0x18, 0x41, 0x00, 0x88, 0x89, -0x19, 0x41, 0x00, 0x87, 0x80, 0x1a, 0x41, 0x00, 0x91, 0x92, 0x1b, 0x41, 0x00, 0x68, 0x48, 0x1e, -0x41, 0x00, 0x9e, 0x9f, 0x1f, 0x41, 0x00, 0x75, 0x55, 0x20, 0x41, 0x00, 0x73, 0x53, 0x21, 0x41, -0x00, 0x69, 0x49, 0x22, 0x41, 0x00, 0x6c, 0x4c, 0x23, 0x41, 0x00, 0x64, 0x44, 0x24, 0x41, 0x00, -0x61, 0x41, 0x25, 0x41, 0x00, 0x74, 0x54, 0x26, 0x41, 0x00, 0x65, 0x45, 0x27, 0x41, 0x00, 0x63, -0x43, 0x28, 0x01, 0x00, 0x27, 0xf8, 0x29, 0x01, 0x00, 0x2d, 0x3f, 0x2a, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x7a, 0x2b, 0x41, 0x00, 0xa2, 0xa3, 0x2c, 0x41, 0x00, 0xa4, 0xa5, 0x2d, 0x41, 0x00, -0x62, 0x42, 0x2e, 0x41, 0x00, 0x8c, 0xa1, 0x2f, 0x41, 0x00, 0x6b, 0x4b, 0x30, 0x41, 0x00, 0x70, -0x50, 0x31, 0x41, 0x00, 0x6f, 0x4f, 0x32, 0x41, 0x00, 0x83, 0xa0, 0x33, 0x01, 0x01, 0x00, 0x3b, -0x34, 0x01, 0x01, 0x00, 0x3a, 0x35, 0x41, 0x00, 0x86, 0x9c, 0x56, 0x41, 0x00, 0x98, 0xa8, 0x00, -0x2b, 0x00, 0x00, 0xd0, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x03, 0x01, 0x01, -0x00, 0xae, 0x04, 0x01, 0x01, 0x00, 0xaf, 0x05, 0x01, 0x01, 0x00, 0xbe, 0x07, 0x01, 0x01, 0x00, -0x2f, 0x09, 0x01, 0x01, 0x00, 0x9e, 0x0d, 0x41, 0x00, 0x66, 0x46, 0x10, 0x41, 0x00, 0xfb, 0xfa, -0x11, 0x41, 0x00, 0x67, 0x47, 0x12, 0x41, 0x00, 0x6a, 0x4a, 0x13, 0x43, 0x03, 0x00, 0x00, 0x8b, -0x8a, 0x14, 0x41, 0x00, 0x6d, 0x4d, 0x15, 0x41, 0x00, 0x76, 0x56, 0x16, 0x41, 0x00, 0x6e, 0x4e, -0x17, 0x41, 0x00, 0x7a, 0x5a, 0x18, 0x41, 0x00, 0x89, 0xed, 0x19, 0x41, 0x00, 0xdf, 0xde, 0x1a, -0x41, 0x00, 0xfd, 0xfc, 0x1b, 0x41, 0x00, 0x68, 0x48, 0x1e, 0x41, 0x00, 0xf7, 0xf6, 0x1f, 0x41, -0x00, 0x75, 0x55, 0x20, 0x41, 0x00, 0x73, 0x53, 0x21, 0x41, 0x00, 0x69, 0x49, 0x22, 0x41, 0x00, -0x6c, 0x4c, 0x23, 0x41, 0x00, 0x64, 0x44, 0x24, 0x41, 0x00, 0x61, 0x41, 0x25, 0x41, 0x00, 0x74, -0x54, 0x26, 0x41, 0x00, 0x65, 0x45, 0x27, 0x41, 0x00, 0x63, 0x43, 0x28, 0x01, 0x00, 0x27, 0xd0, -0x29, 0x01, 0x00, 0x2d, 0x3f, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, 0x41, 0x00, -0xe9, 0xe8, 0x2c, 0x41, 0x00, 0xec, 0xee, 0x2d, 0x41, 0x00, 0x62, 0x42, 0x2e, 0x41, 0x00, 0x8c, -0xa1, 0x2f, 0x41, 0x00, 0x6b, 0x4b, 0x30, 0x41, 0x00, 0x70, 0x50, 0x31, 0x43, 0x00, 0x6f, 0x4f, -0x93, 0xe2, 0x32, 0x41, 0x00, 0x83, 0xa0, 0x33, 0x01, 0x01, 0x00, 0x3b, 0x34, 0x01, 0x01, 0x00, -0x3a, 0x35, 0x41, 0x00, 0xeb, 0xea, 0x56, 0x41, 0x00, 0x85, 0x95, 0x00, 0x2b, 0x01, 0x03, 0x00, -0xa0, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x03, 0x01, 0x01, 0x00, 0xae, 0x04, -0x01, 0x01, 0x00, 0xaf, 0x05, 0x01, 0x01, 0x00, 0x15, 0x07, 0x01, 0x01, 0x00, 0x2f, 0x09, 0x01, -0x01, 0x00, 0x9e, 0x0d, 0x41, 0x00, 0x66, 0x46, 0x10, 0x41, 0x00, 0x96, 0xea, 0x11, 0x41, 0x00, -0x67, 0x47, 0x12, 0x41, 0x00, 0x6a, 0x4a, 0x13, 0x43, 0x00, 0x72, 0x52, 0xfb, 0xfc, 0x14, 0x41, -0x00, 0x6d, 0x4d, 0x15, 0x41, 0x00, 0x76, 0x56, 0x16, 0x41, 0x00, 0x6e, 0x4e, 0x17, 0x41, 0x00, -0x7a, 0x5a, 0x18, 0x41, 0x00, 0x89, 0xed, 0x19, 0x41, 0x00, 0x9f, 0xac, 0x1a, 0x41, 0x00, 0xa7, -0xa6, 0x1b, 0x41, 0x00, 0x68, 0x48, 0x1e, 0x41, 0x00, 0xe7, 0xe6, 0x1f, 0x41, 0x00, 0x75, 0x55, -0x20, 0x41, 0x00, 0x73, 0x53, 0x21, 0x41, 0x00, 0x69, 0x49, 0x22, 0x41, 0x00, 0x6c, 0x4c, 0x23, -0x41, 0x00, 0x64, 0x44, 0x24, 0x41, 0x00, 0x61, 0x41, 0x25, 0x41, 0x00, 0x74, 0x54, 0x26, 0x41, -0x00, 0x65, 0x45, 0x27, 0x41, 0x00, 0x63, 0x43, 0x28, 0x01, 0x00, 0x27, 0xf8, 0x29, 0x01, 0x00, -0x2d, 0x3f, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x2b, 0x41, 0x00, 0xe9, 0xe8, 0x2c, -0x41, 0x00, 0xef, 0xee, 0x2d, 0x41, 0x00, 0x62, 0x42, 0x2e, 0x41, 0x00, 0x8c, 0xa1, 0x2f, 0x41, -0x00, 0x6b, 0x4b, 0x30, 0x41, 0x00, 0x70, 0x50, 0x31, 0x43, 0x00, 0x6f, 0x4f, 0x93, 0xe2, 0x32, -0x41, 0x00, 0x83, 0xa0, 0x33, 0x01, 0x01, 0x00, 0x3b, 0x34, 0x01, 0x01, 0x00, 0x3a, 0x35, 0x41, -0x00, 0xec, 0x9c, 0x56, 0x41, 0x00, 0x85, 0x95, 0x00, 0x1d, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x82, 0x28, 0x01, 0x03, 0x00, 0xa0, 0x2b, 0x10, 0x00, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x81, 0x00, 0x05, 0x01, 0x01, 0x00, 0x15, 0x07, 0x01, 0x01, 0x00, 0x2f, 0x0d, 0x41, 0x00, -0x66, 0x46, 0x10, 0x41, 0x00, 0xdd, 0xde, 0x11, 0x41, 0x00, 0x67, 0x47, 0x12, 0x41, 0x00, 0x6a, -0x4a, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x6d, 0x4d, 0x15, 0x41, 0x00, 0x76, 0x56, -0x16, 0x41, 0x00, 0x6e, 0x4e, 0x17, 0x41, 0x00, 0x7a, 0x5a, 0x18, 0xc1, 0x00, 0xf1, 0x18, 0xf0, -0x00, 0x19, 0x41, 0x00, 0xd2, 0xd3, 0x1a, 0x41, 0x00, 0xf7, 0xf8, 0x1b, 0x41, 0x00, 0x68, 0x48, -0x1d, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x82, 0x1e, 0x41, 0x00, 0xfd, 0xd0, 0x1f, 0x41, 0x00, -0x75, 0x55, 0x20, 0x41, 0x00, 0x73, 0x53, 0x21, 0x41, 0x00, 0x69, 0x49, 0x22, 0x41, 0x00, 0x6c, -0x4c, 0x23, 0x41, 0x00, 0x64, 0x44, 0x24, 0x41, 0x00, 0x61, 0x41, 0x25, 0x41, 0x00, 0x74, 0x54, -0x26, 0x41, 0x00, 0x65, 0x45, 0x27, 0x41, 0x00, 0x63, 0x43, 0x28, 0x01, 0x03, 0x00, 0xa0, 0x29, -0x01, 0x00, 0x2d, 0x3f, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2b, 0x41, 0x00, 0xf3, -0xf4, 0x2c, 0x41, 0x00, 0xb7, 0xfc, 0x2d, 0x41, 0x00, 0x62, 0x42, 0x2e, 0x41, 0x00, 0xd8, 0xd7, -0x2f, 0x41, 0x00, 0x6b, 0x4b, 0x30, 0x41, 0x00, 0x70, 0x50, 0x31, 0x41, 0x00, 0x6f, 0x4f, 0x32, -0x41, 0x00, 0xc6, 0xb5, 0x33, 0x01, 0x01, 0x00, 0x3b, 0x34, 0x01, 0x01, 0x00, 0x3a, 0x35, 0x41, -0x00, 0xf5, 0xf6, 0x56, 0x41, 0x00, 0xd6, 0xf2, 0x00, 0x05, 0x01, 0x01, 0x00, 0x15, 0x07, 0x01, -0x01, 0x00, 0x2f, 0x0d, 0x41, 0x00, 0xe4, 0x94, 0x10, 0x41, 0x00, 0xee, 0x9e, 0x11, 0x41, 0x00, -0xa3, 0x83, 0x12, 0x41, 0x00, 0xa9, 0x89, 0x13, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x13, 0x14, 0x41, -0x00, 0xac, 0x8c, 0x15, 0x41, 0x00, 0xa2, 0x82, 0x16, 0x41, 0x00, 0xad, 0x8d, 0x17, 0x41, 0x00, -0xa7, 0x87, 0x18, 0x41, 0x00, 0xed, 0x9d, 0x19, 0x41, 0x00, 0xe7, 0x97, 0x1a, 0x41, 0x00, 0xa6, -0x86, 0x1b, 0x41, 0x00, 0xe5, 0x95, 0x1e, 0x41, 0x00, 0xe8, 0x98, 0x1f, 0x41, 0x00, 0xe3, 0x93, -0x20, 0x41, 0x00, 0xe1, 0x91, 0x21, 0x41, 0x00, 0xa8, 0x88, 0x22, 0x41, 0x00, 0xab, 0x8b, 0x23, -0x41, 0x00, 0xa4, 0x84, 0x24, 0x41, 0x00, 0xa0, 0x80, 0x25, 0x41, 0x00, 0xe2, 0x92, 0x26, 0x41, -0x00, 0xa5, 0x85, 0x27, 0x41, 0x00, 0xe6, 0x96, 0x28, 0x01, 0x03, 0x00, 0xa0, 0x29, 0x01, 0x00, -0x2d, 0x3f, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2b, 0x41, 0x00, 0xea, 0x9a, 0x2c, -0x41, 0x00, 0xe9, 0x99, 0x2d, 0x41, 0x00, 0xa1, 0x81, 0x2e, 0x41, 0x00, 0xeb, 0x9b, 0x2f, 0x41, -0x00, 0xaa, 0x8a, 0x30, 0x41, 0x00, 0xaf, 0x8f, 0x31, 0x41, 0x00, 0xae, 0x8e, 0x32, 0x41, 0x00, -0xef, 0x9f, 0x33, 0x01, 0x01, 0x00, 0x3b, 0x34, 0x01, 0x01, 0x00, 0x3a, 0x35, 0x41, 0x00, 0xec, -0x9c, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0xec, 0x67, 0x03, 0x09, 0x00, 0x00, -0x4d, 0x4b, 0x2c, 0xc1, 0x01, 0x4d, 0x4b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, -0x00, 0x00, 0x00, 0x68, 0x03, 0xeb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x68, 0x03, 0x2c, 0x01, 0x00, -0x00, 0x00, 0x00, 0x57, 0x03, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x57, 0x03, 0x90, 0x02, 0x00, -0x00, 0x00, 0x00, 0x5a, 0x03, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x39, 0x75, 0x00, 0x02, 0x53, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, -0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, -0x7e, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x04, 0x09, 0x00, 0x23, 0x5e, 0x00, 0x1e, 0x07, 0x01, -0x01, 0x00, 0x26, 0x08, 0x02, 0x01, 0x00, 0x2f, 0x60, 0x09, 0x01, 0x01, 0x00, 0x28, 0x0a, 0x01, -0x01, 0x00, 0x29, 0x0b, 0x01, 0x01, 0x00, 0x3d, 0x0c, 0x01, 0x00, 0x27, 0x3f, 0x0d, 0x01, 0x00, -0x2b, 0x2a, 0x10, 0x42, 0x03, 0x00, 0x00, 0x5c, 0x11, 0x42, 0x03, 0x00, 0x00, 0x7c, 0x15, 0xc5, -0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x21, 0x42, 0x03, -0x00, 0x00, 0x5b, 0x22, 0x42, 0x03, 0x00, 0x00, 0x5d, 0x27, 0x04, 0x0c, 0x5e, 0x5e, 0x00, 0x00, -0x1e, 0x28, 0x01, 0x00, 0xf5, 0xf5, 0x29, 0x04, 0x0c, 0x5c, 0x7c, 0x00, 0x00, 0x1c, 0x2b, 0x01, -0x00, 0x40, 0x40, 0x2c, 0xc5, 0x00, 0x79, 0x15, 0x59, 0x15, 0x00, 0x15, 0x00, 0x15, 0x19, 0x15, -0x00, 0x15, 0x2f, 0x42, 0x03, 0x00, 0x00, 0x40, 0x30, 0x42, 0x03, 0x00, 0x00, 0x7b, 0x31, 0x42, -0x03, 0x00, 0x00, 0x7d, 0x33, 0x01, 0x00, 0x2c, 0x3b, 0x34, 0x01, 0x00, 0x2e, 0x3a, 0x35, 0x04, -0x0c, 0x2d, 0x5f, 0x00, 0x00, 0x1f, 0x56, 0x01, 0x00, 0x3c, 0x3e, 0x00, 0x12, 0x42, 0x03, 0x00, -0x00, 0xd5, 0x00, 0x10, 0x41, 0x00, 0x90, 0x91, 0x11, 0x41, 0x00, 0x92, 0x93, 0x12, 0x42, 0x00, -0xa8, 0xa9, 0xcf, 0x13, 0x41, 0x00, 0xe1, 0xe2, 0x14, 0x41, 0x00, 0xe5, 0xe6, 0x15, 0xc5, 0x00, -0xf3, 0x2c, 0xf4, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0xe7, -0xe8, 0x17, 0x41, 0x00, 0xb7, 0xb8, 0x18, 0x41, 0x00, 0xd6, 0xd7, 0x19, 0x41, 0x00, 0xd8, 0xdd, -0x1a, 0x42, 0x00, 0xf5, 0xf6, 0x81, 0x1b, 0x42, 0x00, 0x82, 0x83, 0x80, 0x1e, 0x41, 0x00, 0xa0, -0xa1, 0x1f, 0x41, 0x00, 0xe3, 0xe4, 0x20, 0x41, 0x00, 0xa6, 0xa7, 0x21, 0x41, 0x00, 0xaa, 0xab, -0x22, 0x41, 0x00, 0xac, 0xad, 0x23, 0x41, 0x00, 0xb5, 0xb6, 0x24, 0x41, 0x00, 0x8e, 0x8f, 0x25, -0x41, 0x00, 0xc6, 0xc7, 0x26, 0x41, 0x00, 0xd0, 0xd1, 0x27, 0x42, 0x00, 0xfb, 0xfc, 0x95, 0x28, -0x42, 0x00, 0x96, 0x97, 0x94, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x41, -0x00, 0xe9, 0xea, 0x2c, 0xc5, 0x00, 0x88, 0x15, 0x89, 0x15, 0x00, 0x15, 0x00, 0x15, 0x19, 0x15, -0x00, 0x15, 0x2d, 0x41, 0x00, 0x9a, 0x9b, 0x2e, 0x41, 0x00, 0xa4, 0xa5, 0x2f, 0x41, 0x00, 0xeb, -0xec, 0x30, 0x41, 0x00, 0xa2, 0xa3, 0x31, 0x41, 0x00, 0xd4, 0xd5, 0x32, 0x42, 0x00, 0xd2, 0xd3, -0xfd, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xcf, 0x28, 0x01, 0x00, 0xfd, 0xfd, 0x36, 0x05, 0x3f, -0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x03, 0x01, 0x03, 0x00, 0xc8, 0x0c, 0x00, 0x01, 0xc9, -0x12, 0x42, 0x00, 0x65, 0x45, 0xd5, 0x15, 0xc5, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x00, 0x2c, 0x00, -0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x43, 0x00, 0x69, 0x49, 0x8d, -0x98, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x1f, 0x43, 0x00, 0x73, 0x53, -0x9f, 0x9e, 0x22, 0x43, 0x00, 0x67, 0x47, 0xa7, 0xa6, 0x27, 0x01, 0x03, 0xca, 0xca, 0x2e, 0x43, -0x00, 0x63, 0x43, 0x87, 0x80, 0x39, 0x00, 0x00, 0x20, 0x00, 0x22, 0x09, 0x61, 0x84, 0x65, 0x89, -0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, 0x45, 0xd3, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x27, 0x05, -0x63, 0x86, 0x67, 0xd0, 0x43, 0x8f, 0x47, 0xd1, 0x20, 0x27, 0x5e, 0x0d, 0x61, 0x83, 0x63, 0xac, -0x69, 0x8c, 0x73, 0xe7, 0x75, 0x96, 0x7a, 0xa8, 0x41, 0xb6, 0x43, 0xad, 0x49, 0xd7, 0x53, 0xe6, -0x55, 0xea, 0x5a, 0xa9, 0x20, 0x5e, 0x00, 0x10, 0x41, 0x00, 0x90, 0x91, 0x11, 0x41, 0x00, 0x92, -0x93, 0x12, 0x41, 0x00, 0xa8, 0xa9, 0x13, 0x41, 0x00, 0xe1, 0xe2, 0x14, 0x41, 0x00, 0xe5, 0xe6, -0x15, 0xc5, 0x00, 0xf3, 0x2c, 0xf4, 0x2c, 0x00, 0x2c, 0x00, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, -0x41, 0x00, 0xe7, 0xe8, 0x17, 0x41, 0x00, 0xb7, 0xb8, 0x18, 0x41, 0x00, 0xd6, 0xd7, 0x19, 0x41, -0x00, 0xd8, 0xdd, 0x1a, 0x42, 0x00, 0xf5, 0xf6, 0x81, 0x1b, 0x42, 0x00, 0x82, 0x83, 0x80, 0x1e, -0x41, 0x00, 0xa0, 0xa1, 0x1f, 0x41, 0x00, 0xe3, 0xe4, 0x20, 0x41, 0x00, 0xa6, 0xa7, 0x21, 0x41, -0x00, 0xaa, 0xab, 0x22, 0x41, 0x00, 0xac, 0xad, 0x23, 0x41, 0x00, 0xb5, 0xb6, 0x24, 0x41, 0x00, -0x8e, 0x8f, 0x25, 0x41, 0x00, 0xc6, 0xc7, 0x26, 0x41, 0x00, 0xd0, 0xd1, 0x27, 0x42, 0x00, 0xfb, -0xfc, 0x95, 0x28, 0x42, 0x00, 0x96, 0x97, 0x94, 0x2a, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, -0x7a, 0x2b, 0x41, 0x00, 0xe9, 0xea, 0x2c, 0xc5, 0x00, 0x88, 0x15, 0x89, 0x15, 0x00, 0x15, 0x00, -0x15, 0x19, 0x15, 0x00, 0x15, 0x2d, 0x41, 0x00, 0x9a, 0x9b, 0x2e, 0x41, 0x00, 0xa4, 0xa5, 0x2f, -0x41, 0x00, 0xeb, 0xec, 0x30, 0x41, 0x00, 0xa2, 0xa3, 0x31, 0x41, 0x00, 0xd4, 0xd5, 0x32, 0x42, -0x00, 0xd2, 0xd3, 0xfd, 0x00, 0x28, 0x01, 0x00, 0xfd, 0xfd, 0x36, 0x05, 0x3f, 0x00, 0x00, 0x00, -0x00, 0x00, 0x7b, 0x00, 0x48, 0x61, 0x01, 0x09, 0x00, 0x00, 0x4d, 0x4e, 0x2c, 0x00, 0x00, 0x4d, -0x4f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe3, 0x48, -0x01, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe3, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0xfc, 0x31, 0x21, 0x03, 0x02, 0x00, 0x2d, 0x32, -0x40, 0x04, 0x02, 0x00, 0x22, 0x33, 0x23, 0x05, 0x02, 0x00, 0x24, 0x34, 0x3b, 0x06, 0x01, 0x00, -0x3a, 0x35, 0x07, 0x02, 0x00, 0x2e, 0x36, 0x5e, 0x08, 0x03, 0x00, 0x5f, 0x37, 0x26, 0x1f, 0x09, -0x02, 0x00, 0x2c, 0x38, 0x2a, 0x0a, 0x02, 0x00, 0x25, 0x39, 0x28, 0x0b, 0x02, 0x00, 0x3f, 0x30, -0x29, 0x0c, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x0d, 0x41, 0x00, 0xe9, 0x99, 0x10, 0x41, 0x00, 0xe4, -0x94, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xa6, 0x86, -0x14, 0x41, 0x00, 0xed, 0x9d, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, -0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xdd, 0xdc, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x42, -0x00, 0xaa, 0x8a, 0x5b, 0x1b, 0x42, 0x00, 0xea, 0x9a, 0x5d, 0x1e, 0x41, 0x00, 0xa9, 0x89, 0x1f, -0x41, 0x00, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa1, 0x81, 0x21, 0x41, 0x00, 0xf3, 0xf2, 0x22, 0x41, -0x00, 0xa0, 0x80, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x25, -0x41, 0x00, 0xae, 0x8e, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x27, 0x41, 0x00, 0xa4, 0x84, 0x28, 0x42, -0x00, 0xaf, 0x8f, 0x27, 0x29, 0x01, 0x00, 0x3d, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, -0x78, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0xc1, 0x00, 0xf1, 0x2e, -0xf0, 0x00, 0x2f, 0x41, 0x00, 0xe1, 0x91, 0x30, 0x41, 0x00, 0xac, 0x8c, 0x31, 0x41, 0x00, 0xa8, -0x88, 0x32, 0x41, 0x00, 0xe2, 0x92, 0x33, 0x42, 0x00, 0xec, 0x9c, 0x3c, 0x34, 0x42, 0x00, 0xa2, -0x82, 0x3e, 0x35, 0x42, 0x00, 0xee, 0x9e, 0x2f, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x57, 0xa8, 0x00, 0x09, 0x00, 0x00, 0x4d, 0x54, -0x2c, 0x00, 0x00, 0x4d, 0x4c, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x55, 0x03, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, -0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x7c, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x02, 0x03, 0x00, -0xa0, 0x9c, 0x12, 0x43, 0x03, 0x00, 0x00, 0x8a, 0xd4, 0x16, 0x43, 0x03, 0x00, 0x00, 0x97, 0xeb, -0x17, 0x43, 0x03, 0x00, 0x00, 0x8d, 0xde, 0x18, 0x43, 0x03, 0x00, 0x00, 0x95, 0xe3, 0x1a, 0x43, -0x00, 0xe5, 0xe4, 0x5b, 0x7b, 0x1b, 0x43, 0x00, 0xe8, 0xe7, 0x5d, 0x7d, 0x1e, 0x43, 0x03, 0x00, -0x00, 0x85, 0xb7, 0x28, 0x01, 0x01, 0x00, 0x40, 0x29, 0x42, 0x00, 0x91, 0x92, 0x60, 0x2b, 0x01, -0x00, 0x23, 0x7e, 0x35, 0x04, 0x0b, 0x00, 0x00, 0x5c, 0x00, 0x1c, 0x56, 0x43, 0x00, 0xbe, 0xbd, -0x5c, 0x7c, 0x00, 0x31, 0x7e, 0x00, 0x09, 0x2f, 0x00, 0x4d, 0x54, 0x2c, 0x2f, 0x00, 0x4d, 0x4c, -0x02, 0x02, 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, 0x55, 0x03, 0x34, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x12, 0x03, 0x03, 0x00, 0x00, 0x8a, 0xd4, 0x16, 0x03, 0x03, 0x00, 0x00, -0x97, 0xeb, 0x17, 0x03, 0x03, 0x00, 0x00, 0x8d, 0xde, 0x18, 0x03, 0x03, 0x00, 0x00, 0x95, 0xe3, -0x1a, 0x43, 0x00, 0xe5, 0xe4, 0x5b, 0x7b, 0x1b, 0x43, 0x00, 0xe8, 0xe7, 0x5d, 0x7d, 0x1e, 0x03, -0x03, 0x00, 0x00, 0x85, 0xb7, 0x29, 0x43, 0x00, 0x91, 0x92, 0x60, 0x7e, 0x2b, 0x43, 0x00, 0xbe, -0xbd, 0x5c, 0x7c, 0x00, 0xb0, 0xf4, 0x01, 0x04, 0x00, 0x00, 0x4e, 0x45, 0x02, 0x04, 0x00, 0x00, -0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x75, 0x44, 0x00, 0x8a, 0x01, 0x00, 0x00, -0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x02, 0x41, 0x00, 0x26, 0x31, 0x03, 0x42, 0x04, 0x82, 0x32, 0xc9, 0x04, 0x42, 0x00, 0x22, 0x33, -0x23, 0x05, 0x42, 0x00, 0x27, 0x34, 0x7b, 0x06, 0x44, 0x08, 0x28, 0x35, 0x5b, 0x00, 0x1b, 0x07, -0x44, 0x08, 0x2d, 0x36, 0x7c, 0x00, 0x1f, 0x08, 0x42, 0x04, 0x8a, 0x37, 0xc8, 0x09, 0x44, 0x08, -0x5f, 0x38, 0x5c, 0x00, 0x1c, 0x0a, 0x42, 0x00, 0x87, 0x39, 0x5e, 0x0b, 0x42, 0x00, 0x85, 0x30, -0x40, 0x0c, 0x44, 0x08, 0x29, 0xf8, 0x5d, 0x00, 0x1d, 0x0d, 0x42, 0x03, 0x00, 0x00, 0x7d, 0x10, -0xc5, 0x00, 0x61, 0x1e, 0x41, 0x1e, 0x91, 0x1e, 0x92, 0x1e, 0x01, 0x1e, 0x00, 0x1e, 0x11, 0xc5, -0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0xf7, 0x2c, 0xef, 0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x12, 0x43, 0x00, -0x65, 0x45, 0xe1, 0xee, 0x14, 0x03, 0x03, 0x00, 0x00, 0x9e, 0x9f, 0x15, 0x43, 0x00, 0x79, 0x59, -0xec, 0xed, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x43, 0x00, 0x6f, -0x4f, 0xab, 0xac, 0x1a, 0x44, 0x0f, 0xca, 0xcb, 0x00, 0x00, 0x1e, 0x1b, 0x43, 0x00, 0x24, 0x9c, -0xcf, 0xd5, 0x1e, 0xc5, 0x00, 0x71, 0x10, 0x51, 0x10, 0x84, 0x10, 0x8e, 0x10, 0x11, 0x10, 0x00, -0x10, 0x1f, 0x43, 0x00, 0x73, 0x53, 0x8d, 0xde, 0x20, 0x03, 0x03, 0x00, 0x00, 0x95, 0xe3, 0x21, -0x03, 0x03, 0x00, 0x00, 0xd0, 0xd1, 0x22, 0x43, 0x00, 0x67, 0x47, 0xa8, 0xad, 0x24, 0x41, 0x00, -0x6a, 0x4a, 0x25, 0x03, 0x03, 0x00, 0x00, 0xe7, 0xe8, 0x26, 0x03, 0x03, 0x00, 0x00, 0x9b, 0x9d, -0x27, 0xc5, 0x00, 0x6d, 0x32, 0x4d, 0x32, 0x00, 0x32, 0x00, 0x32, 0x0d, 0x32, 0x00, 0x32, 0x28, -0x41, 0x00, 0x97, 0x25, 0x29, 0x41, 0x00, 0x82, 0x90, 0x2b, 0x41, 0x00, 0x2a, 0xe6, 0x2c, 0xc5, -0x00, 0x77, 0x11, 0x57, 0x11, 0x00, 0x11, 0x00, 0x11, 0x17, 0x11, 0x00, 0x11, 0x2e, 0x03, 0x03, -0x00, 0x00, 0x87, 0x80, 0x30, 0x03, 0x03, 0x00, 0x00, 0xf1, 0xf2, 0x31, 0x43, 0x00, 0x6e, 0x4e, -0xfa, 0xfb, 0x32, 0x43, 0x00, 0x2c, 0x3f, 0xfc, 0xfd, 0x33, 0x43, 0x00, 0x3b, 0x2e, 0x3c, 0xae, -0x34, 0x43, 0x00, 0x3a, 0x2f, 0x3e, 0xaf, 0x35, 0x41, 0x00, 0x21, 0xf5, 0x39, 0x00, 0x00, 0x20, -0x56, 0x41, 0x00, 0x3c, 0x3e, 0x00, 0x60, 0x07, 0x61, 0x85, 0x65, 0x8a, 0x75, 0x97, 0x41, 0xb7, -0x45, 0xd4, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x0d, 0x61, 0xc6, 0x65, 0xbd, 0x69, 0xa9, 0x6f, 0xe4, -0x75, 0xf4, 0x6e, 0xa4, 0x41, 0xc7, 0x45, 0xbe, 0x49, 0xb8, 0x4f, 0xe5, 0x55, 0xf6, 0x4e, 0xa5, -0x20, 0x7e, 0x5e, 0x11, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x67, 0x86, -0x6a, 0xa6, 0x73, 0xf9, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x47, 0x8f, -0x4a, 0xa7, 0x53, 0xdd, 0x20, 0x5e, 0x22, 0x09, 0x65, 0x89, 0x69, 0x8b, 0x75, 0x81, 0x79, 0x98, -0x45, 0xd3, 0x49, 0xd8, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x00, 0x51, 0x20, 0x01, 0x04, 0x00, -0x00, 0x4e, 0x47, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, -0x75, 0x34, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, -0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00, 0xe1, 0x24, 0x9c, 0x06, 0x02, -0x03, 0x00, 0x00, 0xd5, 0x07, 0x01, 0x03, 0x00, 0xca, 0x11, 0x43, 0x03, 0x00, 0x00, 0xbd, 0xbe, -0x12, 0x43, 0x00, 0x65, 0x45, 0xf1, 0xf2, 0x15, 0x43, 0x03, 0x00, 0x00, 0xf7, 0xef, 0x16, 0x43, -0x00, 0x75, 0x55, 0x9e, 0x9f, 0x17, 0x43, 0x00, 0x69, 0x49, 0x9b, 0x9d, 0x18, 0x43, 0x00, 0x6f, -0x4f, 0xfc, 0xfd, 0x19, 0x43, 0x03, 0x00, 0x00, 0xfa, 0xfb, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x1f, -0x41, 0x00, 0x73, 0x53, 0x20, 0x43, 0x03, 0x00, 0x00, 0xd0, 0xd1, 0x24, 0x43, 0x03, 0x00, 0x00, -0x94, 0x99, 0x25, 0x43, 0x03, 0x00, 0x00, 0xe7, 0xe8, 0x28, 0x00, 0x01, 0xcb, 0x29, 0x01, 0x03, -0xc8, 0xc9, 0x30, 0x43, 0x03, 0x00, 0x00, 0xc6, 0xc7, 0x31, 0x43, 0x00, 0x6e, 0x4e, 0xa4, 0xa5, -0x39, 0x00, 0x00, 0x20, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, -0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x0d, 0x65, -0xa6, 0x69, 0x84, 0x6e, 0xe4, 0x6f, 0xa8, 0x73, 0xf9, 0x75, 0x86, 0x45, 0xa7, 0x49, 0x8e, 0x4e, -0xe5, 0x4f, 0xa9, 0x53, 0xdd, 0x55, 0x8f, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, -0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, -0x5e, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6e, 0xec, 0x6f, 0xa2, 0x75, 0xa3, 0x41, -0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4e, 0xed, 0x4f, 0xe0, 0x55, 0xe9, 0x20, 0x27, 0x00, 0xdf, 0xfc, -0x01, 0x04, 0x00, 0x00, 0x50, 0x48, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, -0x00, 0x00, 0x5a, 0x03, 0x22, 0x01, 0x29, 0x01, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x29, 0x01, -0x00, 0x00, 0xb5, 0x01, 0xa0, 0x01, 0xac, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x00, 0xa6, 0x7c, -0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x01, 0x00, 0x2f, 0x23, 0x05, 0x02, 0x01, 0x00, -0x28, 0xac, 0x06, 0x02, 0x01, 0x00, 0x29, 0xab, 0x07, 0x02, 0x01, 0x00, 0xad, 0xaa, 0x08, 0x03, -0x01, 0x00, 0x21, 0x5f, 0x1f, 0x09, 0x02, 0x01, 0x00, 0xa8, 0x23, 0x0a, 0x02, 0x01, 0x00, 0x3f, -0xf5, 0x0b, 0x03, 0x03, 0x00, 0xa0, 0x5c, 0x1c, 0x0c, 0x02, 0x00, 0x2d, 0x2b, 0x2a, 0x0d, 0x02, -0x07, 0xcc, 0xcc, 0xc9, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, -0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x02, 0x00, -0xf6, 0x9e, 0x5b, 0x1b, 0x02, 0x03, 0xc8, 0xc8, 0x5d, 0x1e, 0x42, 0x00, 0x61, 0x41, 0x24, 0x1f, -0x42, 0x03, 0x00, 0x00, 0x26, 0x20, 0x42, 0x03, 0x00, 0x00, 0x40, 0x21, 0x42, 0x03, 0x00, 0x00, -0x5b, 0x22, 0x42, 0x03, 0x00, 0x00, 0x5d, 0x23, 0x42, 0x03, 0x00, 0x00, 0x7c, 0x24, 0x42, 0x03, -0x00, 0x00, 0x9c, 0x25, 0x42, 0x03, 0x00, 0x00, 0xf1, 0x27, 0x42, 0x00, 0xa4, 0xa5, 0x7e, 0x28, -0x42, 0x00, 0x87, 0x80, 0x7b, 0x29, 0x03, 0x00, 0x27, 0xfa, 0x5c, 0x1c, 0x2b, 0x42, 0x03, 0xcb, -0xcb, 0x7d, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, 0x00, 0x6e, 0x4e, 0x33, 0x02, 0x01, 0x00, -0x3b, 0x3c, 0x34, 0x02, 0x05, 0x00, 0x3a, 0xca, 0x35, 0x02, 0x00, 0x3d, 0x25, 0x3e, 0x39, 0x00, -0x00, 0x20, 0x56, 0x01, 0x00, 0x3c, 0x3e, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x60, -0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, -0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, -0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, -0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, -0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, -0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, -0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, -0x99, 0x55, 0x9a, 0x20, 0xf9, 0x00, 0x0a, 0x02, 0x03, 0x00, 0x00, 0x15, 0x1a, 0x01, 0x03, 0x00, -0xa0, 0x00, 0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, -0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, -0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0x27, 0x07, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, -0x75, 0xa3, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, -0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0xd8, 0xb5, 0x00, -0x09, 0x00, 0x00, 0x53, 0x51, 0x2c, 0xc4, 0x01, 0x53, 0x51, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, -0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, -0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x01, -0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xf5, -0x08, 0x02, 0x03, 0x00, 0x00, 0x7b, 0x09, 0x02, 0x03, 0x00, 0x00, 0x7d, 0x0a, 0x03, 0x03, 0x00, -0x00, 0x5b, 0x1b, 0x0b, 0x03, 0x03, 0x00, 0x00, 0x5d, 0x1d, 0x1a, 0x41, 0x00, 0x89, 0xd3, 0x1b, -0x01, 0x00, 0x27, 0x40, 0x28, 0x41, 0x00, 0x87, 0x80, 0x29, 0x02, 0x00, 0x60, 0xaa, 0x7c, 0x2b, -0x03, 0x00, 0x23, 0x7e, 0x5c, 0x1c, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x12, 0x42, -0x03, 0x00, 0x00, 0xaa, 0x29, 0x01, 0x03, 0x00, 0xa0, 0x00, 0x04, 0x01, 0x01, 0x00, 0x15, 0x1a, -0x41, 0x02, 0x89, 0xa0, 0x00, 0xa8, 0x61, 0x03, 0x04, 0xc0, 0x01, 0x53, 0x51, 0x05, 0x03, 0x00, -0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, 0x30, 0x02, 0x9b, 0x02, 0x00, -0x00, 0x52, 0x03, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x5a, 0x03, 0x2f, 0x01, 0x36, 0x01, 0x00, -0x00, 0xb5, 0x01, 0xbd, 0x01, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x02, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x03, 0x07, 0x00, -0x00, 0xc9, 0x1e, 0x06, 0x02, 0x07, 0x00, 0x00, 0xca, 0x08, 0x02, 0x07, 0x00, 0x00, 0xcb, 0x09, -0x02, 0x03, 0x00, 0x00, 0xfa, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x0c, 0x02, 0x07, 0x00, 0x00, -0xcd, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xce, 0x10, 0x42, 0x03, 0x00, 0x00, 0x5c, 0x11, 0x42, 0x03, -0x00, 0x00, 0x7c, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0xc4, 0x00, 0x7a, 0x2c, 0x5a, 0x2c, 0x00, -0x2c, 0x1a, 0x2c, 0x00, 0x2c, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, -0x41, 0x00, 0x6f, 0x4f, 0x1a, 0x42, 0x00, 0x87, 0x80, 0xf6, 0x1b, 0x02, 0x00, 0x40, 0x27, 0x9e, -0x1e, 0x41, 0x00, 0x61, 0x41, 0x21, 0x42, 0x03, 0x00, 0x00, 0x5b, 0x22, 0x42, 0x03, 0x00, 0x00, -0x5d, 0x27, 0x42, 0x00, 0x89, 0xd3, 0x24, 0x28, 0x03, 0x00, 0x5b, 0x7b, 0xe1, 0x1b, 0x29, 0x03, -0x04, 0x5c, 0x7c, 0x00, 0x1c, 0x2b, 0x03, 0x00, 0x5d, 0x7d, 0xcf, 0x1d, 0x2c, 0xc4, 0x00, 0x79, -0x15, 0x59, 0x15, 0x00, 0x15, 0x19, 0x15, 0x00, 0x15, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x2f, 0x42, -0x03, 0x00, 0x00, 0x40, 0x30, 0x42, 0x03, 0x00, 0x00, 0x7b, 0x31, 0x42, 0x00, 0x6e, 0x4e, 0x7d, -0x32, 0x42, 0x03, 0x00, 0x00, 0xf5, 0x33, 0x02, 0x01, 0x00, 0x3b, 0x3c, 0x34, 0x02, 0x01, 0x00, -0x3a, 0x3e, 0x39, 0x00, 0x00, 0x20, 0x56, 0x01, 0x00, 0x3c, 0x3e, 0x00, 0x12, 0x42, 0x03, 0x00, -0x00, 0xd5, 0x00, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, -0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, -0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xf8, 0x03, 0x61, 0x86, 0x41, -0x8f, 0x20, 0xf8, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, -0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0xef, 0x0d, 0x61, 0xa0, 0x65, -0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, -0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0xef, 0xf9, 0x0c, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, -0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, -0xf9, 0xf7, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0xf7, 0x00, 0x1b, 0x02, 0x07, 0x00, 0x00, 0xa0, -0x27, 0x41, 0x02, 0x89, 0xa0, 0x2b, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x32, 0x42, 0x03, 0x00, 0x00, -0x15, 0x00, 0x7e, 0x03, 0x6e, 0xa4, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, -0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x20, 0x5e, 0xf8, 0x03, 0x61, 0x86, 0x41, 0x8f, 0x20, 0xf8, -0x60, 0x06, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, 0x27, 0x07, -0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, -0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, -0x55, 0x9a, 0x20, 0x22, 0x2c, 0x03, 0x63, 0x87, 0x43, 0x80, 0x20, 0x2c, 0x00, 0x02, 0x02, 0x03, -0x00, 0x00, 0x7e, 0x03, 0x02, 0x07, 0x00, 0x00, 0xc8, 0x05, 0x02, 0x07, 0x00, 0x00, 0xca, 0x06, -0x02, 0x07, 0x00, 0x00, 0xcb, 0x07, 0x02, 0x07, 0x00, 0x00, 0xcc, 0x08, 0x02, 0x03, 0x00, 0x00, -0x60, 0x09, 0x02, 0x07, 0x00, 0x00, 0xcd, 0x0a, 0x02, 0x07, 0x00, 0x00, 0xce, 0x0b, 0x02, 0x07, -0x00, 0x00, 0xcf, 0x0c, 0x02, 0x07, 0x00, 0x00, 0xd0, 0x0d, 0x02, 0x07, 0x00, 0x00, 0xd1, 0x12, -0x42, 0x03, 0x00, 0x00, 0xaa, 0x13, 0x41, 0x00, 0x72, 0x52, 0x14, 0x41, 0x00, 0x74, 0x54, 0x1f, -0x42, 0x00, 0x73, 0x53, 0xd0, 0x20, 0x42, 0x00, 0x64, 0x44, 0xd1, 0x25, 0x42, 0x03, 0x00, 0x00, -0x88, 0x26, 0x42, 0x00, 0x6c, 0x4c, 0x9d, 0x00, 0xf3, 0x13, 0x63, 0x9f, 0x64, 0xd4, 0x65, 0xd8, -0x6c, 0x96, 0x6e, 0xe5, 0x72, 0xfd, 0x73, 0xe7, 0x74, 0x9c, 0x7a, 0xa7, 0x43, 0xac, 0x44, 0xd2, -0x45, 0xb7, 0x4c, 0x95, 0x4e, 0xd5, 0x52, 0xfc, 0x53, 0xe6, 0x54, 0x9b, 0x5a, 0xa6, 0x20, 0xf3, -0x5e, 0x07, 0x61, 0x83, 0x69, 0x8c, 0x6f, 0x93, 0x41, 0xb6, 0x49, 0xd7, 0x4f, 0xe2, 0x20, 0x5e, -0xf4, 0x03, 0x61, 0xc7, 0x41, 0xc6, 0x20, 0xf4, 0xf8, 0x03, 0x75, 0x85, 0x55, 0xde, 0x20, 0xf8, -0xf2, 0x05, 0x61, 0xa5, 0x65, 0xa9, 0x41, 0xa4, 0x45, 0xa8, 0x20, 0xf2, 0xfa, 0x03, 0x7a, 0xbe, -0x5a, 0xbd, 0x20, 0xfa, 0xef, 0x19, 0x61, 0xa0, 0x63, 0x86, 0x65, 0x82, 0x69, 0xa1, 0x6c, 0x92, -0x6e, 0xe4, 0x6f, 0xa2, 0x72, 0xea, 0x73, 0x98, 0x75, 0xa3, 0x79, 0xec, 0x7a, 0xab, 0x41, 0xb5, -0x43, 0x8f, 0x45, 0x90, 0x49, 0xd6, 0x4c, 0x91, 0x4e, 0xe3, 0x4f, 0xe0, 0x52, 0xe8, 0x53, 0x97, -0x55, 0xe9, 0x59, 0xed, 0x5a, 0x8d, 0x20, 0xef, 0xf1, 0x05, 0x6f, 0x8b, 0x75, 0xfb, 0x4f, 0x8a, -0x55, 0xeb, 0x20, 0xf1, 0xf9, 0x09, 0x61, 0x84, 0x65, 0x89, 0x6f, 0x94, 0x75, 0x81, 0x41, 0x8e, -0x45, 0xd3, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0xf9, 0xf7, 0x07, 0x63, 0x87, 0x73, 0xad, 0x74, 0xee, -0x43, 0x80, 0x53, 0xb8, 0x54, 0xdd, 0x20, 0xf7, 0x00, 0x07, 0x55, 0x01, 0x04, 0x00, 0x00, 0x54, -0x4a, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x75, 0x41, -0x01, 0x00, 0x00, 0x00, 0x00, 0x32, 0x75, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, -0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x22, 0x40, 0x04, 0x02, 0x01, 0x00, 0xfc, -0x23, 0x05, 0x02, 0x05, 0x00, 0x3b, 0xa0, 0x07, 0x02, 0x01, 0x00, 0x3a, 0x5e, 0x08, 0x02, 0x01, -0x00, 0x3f, 0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x24, 0x0c, 0x43, 0x00, 0xf3, 0xf2, 0x2d, 0x5f, -0x0d, 0x43, 0x00, 0xf7, 0xf6, 0x3d, 0x2b, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x43, 0x00, 0xf9, -0xf8, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, -0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, -0xe8, 0x98, 0x18, 0x43, 0x00, 0xfb, 0xfa, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x42, -0x00, 0xe5, 0x95, 0x5b, 0x1b, 0x42, 0x00, 0xea, 0x9a, 0x5d, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, -0x43, 0x00, 0xde, 0xdd, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, -0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, -0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, -0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, -0x00, 0x00, 0x00, 0x78, 0x2b, 0x02, 0x01, 0x00, 0x2f, 0x7c, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, -0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, -0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x43, 0x00, 0xf5, 0xf4, 0xec, 0x9c, 0x33, -0x42, 0x00, 0xa1, 0x81, 0x3c, 0x34, 0x42, 0x00, 0xee, 0x9e, 0x3e, 0x35, 0x02, 0x00, 0x2e, 0x2c, -0x2f, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, -0x00, 0x52, 0x6f, 0x01, 0x04, 0x00, 0x00, 0x54, 0x4d, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, -0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xe7, 0x61, -0x01, 0x00, 0x00, 0x00, 0x00, 0x62, 0xe7, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, -0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x03, 0x00, 0x00, 0x5b, 0x7b, 0x1b, 0x03, 0x03, 0x00, -0x00, 0x5d, 0x7d, 0x29, 0x03, 0x03, 0x00, 0x00, 0x60, 0x7e, 0x2b, 0x03, 0x03, 0x00, 0x00, 0x5c, -0x7c, 0x00, 0x10, 0x43, 0x00, 0x84, 0x8e, 0x71, 0x51, 0x12, 0x42, 0x03, 0x00, 0x00, 0xaa, 0x1a, -0x41, 0x00, 0xe5, 0xd5, 0x1b, 0x41, 0x00, 0x94, 0x99, 0x29, 0x41, 0x00, 0xa7, 0xa6, 0x2b, 0x41, -0x00, 0xad, 0xb8, 0x2d, 0x43, 0x00, 0xec, 0xed, 0x78, 0x58, 0x2e, 0x43, 0x00, 0x87, 0x80, 0x63, -0x43, 0x2f, 0x43, 0x00, 0x81, 0x9a, 0x76, 0x56, 0x00, 0x0c, 0xc3, 0x00, 0xf1, 0x0c, 0xf0, 0x00, -0x2d, 0x82, 0x5f, 0x82, 0x0d, 0x43, 0x00, 0xeb, 0x9b, 0x3d, 0x2b, 0x10, 0x41, 0x00, 0xf3, 0xf2, -0x11, 0x41, 0x00, 0xa2, 0x82, 0x12, 0x41, 0x00, 0xa5, 0x85, 0x13, 0xc1, 0x00, 0xe0, 0x00, 0x90, -0x13, 0x14, 0x41, 0x00, 0xe2, 0x92, 0x15, 0x41, 0x00, 0xa9, 0x89, 0x16, 0x41, 0x00, 0xe3, 0x93, -0x17, 0x41, 0x00, 0xa8, 0x88, 0x18, 0x41, 0x00, 0xae, 0x8e, 0x19, 0x41, 0x00, 0xaf, 0x8f, 0x1a, -0x41, 0x00, 0xfb, 0xfa, 0x1b, 0x41, 0x00, 0xf5, 0xf4, 0x1e, 0x41, 0x00, 0xa0, 0x80, 0x1f, 0x41, -0x00, 0xe1, 0x91, 0x20, 0x41, 0x00, 0xa4, 0x84, 0x21, 0x41, 0x00, 0xe4, 0x94, 0x22, 0x41, 0x00, -0xa3, 0x83, 0x23, 0x41, 0x00, 0xe5, 0x95, 0x24, 0x41, 0x00, 0xa6, 0x86, 0x25, 0x41, 0x00, 0xaa, -0x8a, 0x26, 0x41, 0x00, 0xab, 0x8b, 0x28, 0x43, 0x00, 0xed, 0x9d, 0x27, 0x22, 0x29, 0x41, 0x00, -0xf9, 0xf8, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x2b, 0x41, 0x00, 0xe8, 0x98, 0x2c, -0x41, 0x00, 0xa7, 0x87, 0x2d, 0x41, 0x00, 0xef, 0x9f, 0x2e, 0x41, 0x00, 0xe7, 0x97, 0x2f, 0x41, -0x00, 0xf7, 0xf6, 0x30, 0x41, 0x00, 0xa1, 0x81, 0x31, 0x41, 0x00, 0xad, 0x8d, 0x32, 0x41, 0x00, -0xac, 0x8c, 0x35, 0x43, 0x00, 0xee, 0x9e, 0x2f, 0x3f, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x7a, 0x00, 0x85, 0x83, 0x06, 0x09, 0x00, 0x00, 0x55, 0x52, 0x2c, 0x00, 0x00, 0x55, 0x41, -0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0xd2, 0x01, -0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x04, 0xc4, 0x02, -0x00, 0x00, 0x00, 0x00, 0x65, 0x04, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x51, 0x03, 0xac, 0x03, -0x00, 0x00, 0x00, 0x00, 0x51, 0x03, 0xd3, 0x02, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x04, 0x99, 0x04, -0x00, 0x00, 0x00, 0x00, 0x6b, 0x04, 0xc1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0x7f, 0x05, -0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0xa8, 0x04, 0x00, 0x00, 0x00, 0x00, 0x62, 0x03, 0x6a, 0x06, -0x00, 0x00, 0x00, 0x00, 0x62, 0x03, 0x94, 0x05, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xed, 0x00, -0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, -0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0x40, 0x04, 0x02, 0x03, 0x00, 0x00, 0x23, -0x05, 0x02, 0x03, 0x00, 0x00, 0xcf, 0x07, 0x02, 0x03, 0x00, 0x00, 0x5e, 0x08, 0x02, 0x03, 0x00, -0x00, 0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x24, 0x1a, 0x02, 0x03, 0x00, 0x00, 0x5b, 0x1b, 0x02, -0x03, 0x00, 0x00, 0x5d, 0x2b, 0x02, 0x03, 0x00, 0x00, 0x7c, 0x33, 0x02, 0x03, 0x00, 0x00, 0x3c, -0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x35, 0x02, 0x03, 0x00, 0x00, 0x2f, 0x00, 0x12, 0x42, 0x03, -0x00, 0x00, 0xd5, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xfc, 0x05, 0x02, -0x05, 0x00, 0x3b, 0xa0, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, -0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, -0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x43, 0x00, -0xa3, 0x83, 0xf3, 0xf2, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, -0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xf9, 0xf8, 0x1e, 0x41, 0x00, -0xe4, 0x94, 0x1f, 0x41, 0x00, 0xf7, 0xf6, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, -0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, -0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, -0x86, 0x28, 0x41, 0x00, 0xf5, 0xf4, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, -0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, -0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, -0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, -0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x56, 0x41, 0x00, 0xf3, -0xf2, 0x00, 0x05, 0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, -0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, -0xfc, 0x05, 0x02, 0x01, 0x00, 0x3b, 0xfd, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, -0x3f, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, -0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x41, 0x00, 0xa5, 0x85, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, -0x43, 0x00, 0xa3, 0x83, 0xf3, 0xf2, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, -0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xf9, 0xf8, 0x1e, -0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xf7, 0xf6, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, -0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, -0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, -0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xf5, 0xf4, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, 0x00, 0xef, -0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, -0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, -0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x56, 0x41, -0x00, 0xf3, 0xf2, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x7b, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x05, 0x02, 0x05, 0x00, 0x3b, 0xa0, 0x07, 0x01, -0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, -0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, -0x85, 0xfb, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x43, 0x00, 0xa3, 0x83, 0xfd, 0xfc, 0x17, 0x41, -0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, -0xe5, 0x95, 0x1b, 0x41, 0x00, 0xf5, 0xf4, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xf9, -0xf8, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, -0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, -0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xf3, 0xf2, -0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, -0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, -0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, -0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, -0x9e, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x56, 0x41, 0x00, 0xfd, 0xfc, 0x00, 0x05, 0x02, 0x07, 0x00, -0x00, 0xa0, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfb, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, -0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x05, 0x02, 0x01, 0x00, 0x3b, 0xfb, 0x07, 0x01, 0x01, 0x00, -0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, -0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x41, 0x00, 0xa5, 0x85, 0x15, -0x41, 0x00, 0xad, 0x8d, 0x16, 0x43, 0x00, 0xa3, 0x83, 0xfd, 0xfc, 0x17, 0x41, 0x00, 0xe8, 0x98, -0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, -0x41, 0x00, 0xf5, 0xf4, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xf9, 0xf8, 0x20, 0x41, -0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, -0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, -0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xf3, 0xf2, 0x29, 0xc1, 0x00, -0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x2b, 0x01, 0x01, 0x00, -0x2f, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, -0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, -0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, -0x00, 0x2e, 0x2c, 0x56, 0x41, 0x00, 0xfd, 0xfc, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0xfb, 0x36, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, -0x00, 0xfc, 0x05, 0x02, 0x05, 0x00, 0x3b, 0xa0, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, -0x00, 0x3f, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, -0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, -0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, -0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xf5, 0xf4, 0x1e, -0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0x69, 0x49, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, -0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, -0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, -0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xf3, 0xf2, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, -0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, 0x00, 0xef, -0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, -0x30, 0x41, 0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, -0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x00, 0x05, -0x02, 0x07, 0x00, 0x00, 0xa0, 0x12, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, -0x00, 0x00, 0x81, 0x00, 0x03, 0x01, 0x01, 0x00, 0x22, 0x04, 0x01, 0x01, 0x00, 0xfc, 0x05, 0x02, -0x01, 0x00, 0x3b, 0xfd, 0x07, 0x01, 0x01, 0x00, 0x3a, 0x08, 0x01, 0x01, 0x00, 0x3f, 0x10, 0x41, -0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, -0xaa, 0x8a, 0x14, 0x41, 0x00, 0xa5, 0x85, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, -0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, -0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xf5, 0xf4, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, -0x41, 0x00, 0x69, 0x49, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, -0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, -0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, -0x00, 0xf3, 0xf2, 0x29, 0xc1, 0x00, 0xf1, 0x29, 0xf0, 0x00, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x82, 0x2b, 0x01, 0x01, 0x00, 0x2f, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, -0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xa8, 0x88, -0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, -0x41, 0x00, 0xee, 0x9e, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x00, 0x05, 0x02, 0x03, 0x00, 0x00, 0xfd, -0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x51, 0x07, 0x07, 0x09, 0xd1, 0x01, 0x55, -0x52, 0x2c, 0xd1, 0x01, 0x55, 0x41, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, -0x00, 0x00, 0x50, 0x03, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0x03, 0xf0, 0x00, 0x00, 0x00, -0x00, 0x00, 0x65, 0x04, 0xec, 0x02, 0x00, 0x00, 0x00, 0x00, 0x65, 0x04, 0xf6, 0x01, 0x00, 0x00, -0x00, 0x00, 0x51, 0x03, 0xec, 0x03, 0x00, 0x00, 0x00, 0x00, 0x51, 0x03, 0xf5, 0x02, 0x00, 0x00, -0x00, 0x00, 0x6b, 0x04, 0xf1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x04, 0xfb, 0x03, 0x00, 0x00, -0x00, 0x00, 0x28, 0x03, 0xf0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0xfa, 0x04, 0x00, 0x00, -0x00, 0x00, 0x62, 0x03, 0xf4, 0x06, 0x00, 0x00, 0x00, 0x00, 0x62, 0x03, 0xff, 0x05, 0x00, 0x00, -0x00, 0x00, 0x5a, 0x03, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x03, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x03, 0x00, 0x00, 0x40, -0x04, 0x02, 0x03, 0x00, 0x00, 0x23, 0x05, 0x02, 0x03, 0x00, 0x00, 0x24, 0x07, 0x02, 0x03, 0x00, -0x00, 0x5e, 0x08, 0x02, 0x03, 0x00, 0x00, 0x26, 0x09, 0x03, 0x03, 0x00, 0x00, 0x2a, 0x1f, 0x0d, -0x03, 0x07, 0x00, 0x00, 0x00, 0x1c, 0x1a, 0x02, 0x03, 0x00, 0x00, 0x5b, 0x1b, 0x02, 0x03, 0x00, -0x00, 0x5d, 0x33, 0x02, 0x03, 0x00, 0x00, 0x3c, 0x34, 0x02, 0x03, 0x00, 0x00, 0x3e, 0x00, 0x12, -0x42, 0x03, 0x00, 0x00, 0xd5, 0x00, 0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, -0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, -0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, -0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, -0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, -0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, -0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, -0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xf3, 0xf2, 0x1e, -0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xa8, 0x88, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, -0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, -0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, -0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xf5, 0xf4, 0x29, 0x01, 0x00, 0x60, 0x2b, 0x2a, 0x04, 0x1f, -0x00, 0x00, 0x00, 0x00, 0x78, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, -0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, -0x00, 0xf7, 0xf6, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, -0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x41, 0x00, 0xf9, 0xf8, 0x00, 0x12, 0x42, 0x03, -0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x02, 0x01, 0x00, 0xfc, -0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, -0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, -0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, -0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, -0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x41, 0x00, 0xa5, -0x85, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, -0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, -0x41, 0x00, 0xf3, 0xf2, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xa8, 0x88, 0x20, 0x41, -0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, -0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, -0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xf5, 0xf4, 0x29, 0x01, 0x00, -0x60, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, -0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, -0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xf7, 0xf6, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, -0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x41, 0x00, 0xf9, -0xf8, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x02, 0x01, 0x00, 0x21, 0x31, -0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, 0x06, -0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, -0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, -0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, -0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x42, 0x00, 0xa5, 0x85, -0xfb, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, -0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, -0x41, 0x00, 0xfd, 0xfc, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, 0xa8, 0x88, 0x20, 0x41, -0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, -0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, -0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xf3, 0xf2, 0x29, 0x01, 0x00, -0x60, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, -0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, -0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xf9, 0xf8, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, -0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, 0x35, 0x41, 0x00, 0xf5, -0xf4, 0x00, 0x12, 0x42, 0x03, 0x00, 0x00, 0xfb, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7d, -0x00, 0x02, 0x01, 0x00, 0x21, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, -0x05, 0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, -0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, -0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, -0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, -0x8a, 0x14, 0x41, 0x00, 0xa5, 0x85, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, -0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, -0x41, 0x00, 0xe5, 0x95, 0x1b, 0x41, 0x00, 0xfd, 0xfc, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, -0x00, 0xa8, 0x88, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, -0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, -0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, -0xf3, 0xf2, 0x29, 0x01, 0x00, 0x60, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x2b, -0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, -0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0xf9, 0xf8, 0x31, 0x41, 0x00, -0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, -0x9e, 0x35, 0x41, 0x00, 0xf5, 0xf4, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, -0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, 0x01, 0x00, 0x2f, 0x33, 0x05, -0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, 0x00, 0x2c, 0x36, 0x08, 0x01, -0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, 0x3f, 0x39, 0x0b, 0x01, 0x00, -0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, 0x5c, 0x10, 0x41, 0x00, 0xa9, -0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, -0x14, 0x42, 0x00, 0xa5, 0x85, 0xfd, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, -0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, 0x1a, -0x41, 0x00, 0xe5, 0x95, 0x1b, 0x10, 0x00, 0x00, 0x1e, 0x41, 0x00, 0xe4, 0x94, 0x1f, 0x41, 0x00, -0xa8, 0x88, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, -0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, -0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, 0x28, 0x41, 0x00, 0xf3, -0xf2, 0x29, 0x01, 0x00, 0x60, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2b, 0x01, -0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, -0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0x69, 0x49, 0x31, 0x41, 0x00, 0xe2, -0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, 0x41, 0x00, 0xee, 0x9e, -0x35, 0x41, 0x00, 0xf5, 0xf4, 0x00, 0x12, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, -0x00, 0x00, 0x00, 0x81, 0x00, 0x02, 0x01, 0x00, 0xfc, 0x31, 0x03, 0x01, 0x00, 0x2d, 0x32, 0x04, -0x01, 0x00, 0x2f, 0x33, 0x05, 0x01, 0x00, 0x22, 0x34, 0x06, 0x01, 0x00, 0x3a, 0x35, 0x07, 0x01, -0x00, 0x2c, 0x36, 0x08, 0x01, 0x00, 0x2e, 0x37, 0x09, 0x01, 0x00, 0x5f, 0x38, 0x0a, 0x01, 0x00, -0x3f, 0x39, 0x0b, 0x01, 0x00, 0x25, 0x30, 0x0c, 0x01, 0x00, 0x21, 0x3d, 0x0d, 0x01, 0x00, 0x3b, -0x5c, 0x10, 0x41, 0x00, 0xa9, 0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, -0x13, 0x41, 0x00, 0xaa, 0x8a, 0x14, 0x41, 0x00, 0xa5, 0x85, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, -0x41, 0x00, 0xa3, 0x83, 0x17, 0x41, 0x00, 0xe8, 0x98, 0x18, 0x41, 0x00, 0xe9, 0x99, 0x19, 0x41, -0x00, 0xa7, 0x87, 0x1a, 0x41, 0x00, 0xe5, 0x95, 0x1b, 0x10, 0x00, 0x00, 0x1e, 0x41, 0x00, 0xe4, -0x94, 0x1f, 0x41, 0x00, 0xa8, 0x88, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, 0xa0, 0x80, -0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, 0x00, 0xae, -0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, 0xa6, 0x86, -0x28, 0x41, 0x00, 0xf3, 0xf2, 0x29, 0x01, 0x00, 0x60, 0x2b, 0x2a, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x82, 0x2b, 0x01, 0x00, 0x29, 0x28, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, 0x41, 0x00, 0xe7, -0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, 0x00, 0x69, 0x49, -0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x41, 0x00, 0xa1, 0x81, 0x34, -0x41, 0x00, 0xee, 0x9e, 0x35, 0x41, 0x00, 0xf5, 0xf4, 0x00, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, -0x00, 0x83, 0x00, 0xfe, 0x98, 0x09, 0x09, 0x00, 0x00, 0x55, 0x58, 0x2c, 0x67, 0x00, 0x55, 0x58, -0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x03, 0xa8, 0x00, -0xad, 0x03, 0x00, 0x00, 0x52, 0x03, 0xa8, 0x01, 0xad, 0x03, 0x00, 0x00, 0xb5, 0x01, 0xa2, 0x02, -0x5e, 0x03, 0x00, 0x00, 0x45, 0x75, 0x28, 0x04, 0x8f, 0x04, 0x00, 0x00, 0x47, 0x75, 0x14, 0x05, -0xa3, 0x05, 0x00, 0x00, 0x48, 0x75, 0x38, 0x06, 0xbe, 0x06, 0x00, 0x00, 0x49, 0x75, 0x4f, 0x07, -0x06, 0x08, 0x00, 0x00, 0x4a, 0x75, 0x83, 0x08, 0xf1, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, -0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x03, 0x00, -0xca, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, 0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, -0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, 0x6f, 0x4f, 0x1e, 0x41, 0x00, 0x61, 0x41, 0x28, -0x01, 0x03, 0xcb, 0xcc, 0x29, 0x01, 0x03, 0xc8, 0xc9, 0x2e, 0x41, 0x00, 0x63, 0x43, 0x31, 0x41, -0x00, 0x6e, 0x4e, 0x39, 0x00, 0x00, 0x20, 0x00, 0x02, 0x03, 0x03, 0x00, 0x00, 0xad, 0xfb, 0x03, -0x02, 0x03, 0x00, 0x00, 0xfd, 0x04, 0x02, 0x03, 0x00, 0x00, 0xfc, 0x05, 0x03, 0x03, 0x00, 0x00, -0xcf, 0x9c, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x07, 0x02, 0x03, 0x00, 0x00, 0xac, 0x08, 0x02, -0x03, 0x00, 0x00, 0xab, 0x09, 0x02, 0x03, 0x00, 0x00, 0xf3, 0x0c, 0x02, 0x03, 0x00, 0x00, 0xbe, -0x0d, 0x03, 0x03, 0x00, 0x00, 0x9e, 0xf6, 0x10, 0x03, 0x03, 0x00, 0x00, 0x84, 0x8e, 0x11, 0x03, -0x03, 0x00, 0x00, 0x86, 0x8f, 0x12, 0x03, 0x03, 0x00, 0x00, 0x82, 0x90, 0x13, 0x02, 0x03, 0x00, -0x00, 0xa9, 0x14, 0x03, 0x03, 0x00, 0x00, 0xe7, 0xe8, 0x15, 0x03, 0x03, 0x00, 0x00, 0x81, 0x9a, -0x16, 0x03, 0x03, 0x00, 0x00, 0xa3, 0xe9, 0x17, 0x03, 0x03, 0x00, 0x00, 0xa1, 0xd6, 0x18, 0x83, -0x03, 0x00, 0x18, 0x00, 0x18, 0xa2, 0x18, 0xe0, 0x00, 0x19, 0x03, 0x03, 0x00, 0x00, 0x94, 0x99, -0x1a, 0x02, 0x03, 0x00, 0x00, 0xae, 0x1b, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x1e, 0x03, 0x03, 0x00, -0x00, 0xa0, 0xb5, 0x1f, 0x03, 0x03, 0x00, 0x00, 0xe1, 0xf5, 0x20, 0x03, 0x03, 0x00, 0x00, 0xd0, -0xd1, 0x21, 0x02, 0x03, 0x00, 0x00, 0x9f, 0x26, 0x03, 0x03, 0x00, 0x00, 0x9b, 0x9d, 0x27, 0x03, -0x03, 0x00, 0x00, 0xf4, 0xf8, 0x28, 0x03, 0x03, 0x00, 0x00, 0xef, 0xf9, 0x29, 0x02, 0x03, 0x00, -0x00, 0xee, 0x2b, 0x03, 0x03, 0x00, 0x00, 0xaa, 0xdd, 0x2c, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, -0x2e, 0x03, 0x03, 0x00, 0x00, 0xb8, 0xbd, 0x31, 0x03, 0x03, 0x00, 0x00, 0xa4, 0xa5, 0x32, 0x02, -0x03, 0x00, 0x00, 0xe6, 0x33, 0x03, 0x03, 0x00, 0x00, 0x87, 0x80, 0x34, 0x02, 0x03, 0x00, 0x00, -0xfa, 0x35, 0x02, 0x03, 0x00, 0x00, 0xa8, 0x00, 0x02, 0x03, 0x03, 0x00, 0x00, 0xad, 0xfb, 0x03, -0x02, 0x03, 0x00, 0x00, 0xfd, 0x04, 0x02, 0x03, 0x00, 0x00, 0xfc, 0x05, 0x03, 0x03, 0x00, 0x00, -0xcf, 0x9c, 0x07, 0x02, 0x03, 0x00, 0x00, 0xac, 0x08, 0x02, 0x03, 0x00, 0x00, 0xab, 0x09, 0x02, -0x03, 0x00, 0x00, 0xf3, 0x0c, 0x02, 0x03, 0x00, 0x00, 0xbe, 0x0d, 0x03, 0x03, 0x00, 0x00, 0x9e, -0xf6, 0x10, 0x03, 0x03, 0x00, 0x00, 0x84, 0x8e, 0x11, 0x03, 0x03, 0x00, 0x00, 0x86, 0x8f, 0x12, -0x03, 0x03, 0x00, 0x00, 0x82, 0x90, 0x13, 0x02, 0x03, 0x00, 0x00, 0xa9, 0x14, 0x03, 0x03, 0x00, -0x00, 0xe7, 0xe8, 0x15, 0x03, 0x03, 0x00, 0x00, 0x81, 0x9a, 0x16, 0x03, 0x03, 0x00, 0x00, 0xa3, -0xe9, 0x17, 0x03, 0x03, 0x00, 0x00, 0xa1, 0xd6, 0x18, 0x83, 0x03, 0x00, 0x18, 0x00, 0x18, 0xa2, -0x18, 0xe0, 0x00, 0x19, 0x03, 0x03, 0x00, 0x00, 0x94, 0x99, 0x1a, 0x02, 0x03, 0x00, 0x00, 0xae, -0x1b, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x1e, 0x03, 0x03, 0x00, 0x00, 0xa0, 0xb5, 0x1f, 0x03, 0x03, -0x00, 0x00, 0xe1, 0xf5, 0x20, 0x03, 0x03, 0x00, 0x00, 0xd0, 0xd1, 0x21, 0x02, 0x03, 0x00, 0x00, -0x9f, 0x26, 0x03, 0x03, 0x00, 0x00, 0x9b, 0x9d, 0x27, 0x03, 0x03, 0x00, 0x00, 0xf4, 0xf8, 0x28, -0x03, 0x03, 0x00, 0x00, 0xef, 0xf9, 0x29, 0x02, 0x03, 0x00, 0x00, 0xee, 0x2b, 0x03, 0x03, 0x00, -0x00, 0xaa, 0xdd, 0x2c, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x2e, 0x03, 0x03, 0x00, 0x00, 0xb8, -0xbd, 0x31, 0x03, 0x03, 0x00, 0x00, 0xa4, 0xa5, 0x32, 0x02, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x03, -0x03, 0x00, 0x00, 0x87, 0x80, 0x34, 0x02, 0x03, 0x00, 0x00, 0xfa, 0x35, 0x02, 0x03, 0x00, 0x00, -0xa8, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0xad, 0x03, 0x02, 0x03, 0x00, 0x00, 0xfd, 0x05, 0x03, -0x07, 0x00, 0x00, 0x00, 0x9c, 0x07, 0x02, 0x03, 0x00, 0x00, 0xac, 0x08, 0x02, 0x03, 0x00, 0x00, -0xab, 0x0c, 0x02, 0x03, 0x00, 0x00, 0x9d, 0x0d, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf6, 0x10, 0x03, -0x03, 0x00, 0x00, 0x84, 0x8e, 0x11, 0x03, 0x03, 0x00, 0x00, 0x86, 0x8f, 0x12, 0x03, 0x03, 0x00, -0x00, 0x82, 0x90, 0x15, 0x03, 0x03, 0x00, 0x00, 0x81, 0x9a, 0x16, 0x02, 0x03, 0x00, 0x00, 0xa3, -0x17, 0x02, 0x03, 0x00, 0x00, 0xa1, 0x18, 0x02, 0x03, 0x00, 0x00, 0xa2, 0x19, 0x03, 0x03, 0x00, -0x00, 0x94, 0x99, 0x1a, 0x02, 0x03, 0x00, 0x00, 0xae, 0x1b, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x1e, -0x02, 0x03, 0x00, 0x00, 0xa0, 0x1f, 0x03, 0x03, 0x00, 0x00, 0xe1, 0x15, 0x21, 0x02, 0x03, 0x00, -0x00, 0x9f, 0x27, 0x03, 0x03, 0x00, 0x00, 0x14, 0xf8, 0x2b, 0x02, 0x03, 0x00, 0x00, 0xaa, 0x2c, -0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x2e, 0x03, 0x07, 0x00, 0x00, 0x00, 0x9b, 0x31, 0x03, 0x03, -0x00, 0x00, 0xa4, 0xa5, 0x32, 0x02, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x03, 0x03, 0x00, 0x00, 0x87, -0x80, 0x34, 0x02, 0x03, 0x00, 0x00, 0xfa, 0x35, 0x02, 0x03, 0x00, 0x00, 0xa8, 0x00, 0x60, 0x06, -0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x20, 0x60, 0x7e, 0x03, 0x6e, 0xa4, -0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x06, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, -0x20, 0x5e, 0x27, 0x09, 0x61, 0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, -0x43, 0x80, 0x45, 0x90, 0x20, 0x27, 0x22, 0x0a, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, -0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x60, 0x0b, 0x61, -0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, -0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, -0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, -0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0xef, 0x0f, 0x61, -0xa0, 0x63, 0x87, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x79, 0xec, 0x41, 0xb5, 0x43, -0x80, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x59, 0xed, 0x20, 0x27, 0xf9, 0x0c, 0x61, -0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, -0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x20, 0x22, 0x00, 0x05, 0x03, 0x03, 0x00, 0x00, 0xcf, 0x9c, 0x06, -0x02, 0x03, 0x00, 0x00, 0xd5, 0x0c, 0x02, 0x03, 0x00, 0x00, 0xbe, 0x11, 0x03, 0x03, 0x00, 0x00, -0x86, 0x8f, 0x13, 0x02, 0x03, 0x00, 0x00, 0xa9, 0x18, 0x03, 0x03, 0x00, 0x00, 0xab, 0xac, 0x1a, -0x02, 0x03, 0xcc, 0x00, 0xae, 0x1b, 0x02, 0x03, 0xcd, 0x00, 0xaf, 0x1e, 0x03, 0x03, 0x00, 0x00, -0x91, 0x92, 0x1f, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf5, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x27, 0x03, -0x03, 0x00, 0x00, 0xf4, 0xf8, 0x28, 0x01, 0x02, 0x27, 0xcb, 0x2b, 0x03, 0x03, 0x00, 0x00, 0xaa, -0xdd, 0x2e, 0x03, 0x03, 0x00, 0x00, 0xb8, 0xbd, 0x32, 0x42, 0x00, 0x6d, 0x4d, 0xe6, 0x00, 0x60, -0x07, 0x61, 0x85, 0x65, 0x8a, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x55, 0xeb, 0x20, 0x60, 0x7e, -0x09, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x75, 0xe7, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x55, -0xe8, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, -0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x22, 0x09, 0x65, 0x89, 0x69, -0x8b, 0x75, 0x81, 0x79, 0x98, 0x45, 0xd3, 0x49, 0xd8, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x27, -0x0d, 0x61, 0xee, 0x65, 0xd0, 0x69, 0xf6, 0x6e, 0xec, 0x6f, 0xfa, 0x75, 0xfc, 0x41, 0xef, 0x45, -0xd1, 0x49, 0xf7, 0x4e, 0xed, 0x4f, 0xfb, 0x55, 0xfd, 0x20, 0x5b, 0x2d, 0x0b, 0x63, 0x87, 0x6c, -0x9b, 0x6d, 0x9e, 0x6e, 0xa6, 0x6f, 0xf1, 0x43, 0x80, 0x4c, 0x9d, 0x4d, 0x9f, 0x4e, 0xa7, 0x4f, -0xf2, 0x20, 0x5d, 0x00, 0x02, 0x03, 0x07, 0x00, 0x00, 0x00, 0xfb, 0x03, 0x02, 0x03, 0x00, 0x00, -0xfd, 0x04, 0x02, 0x03, 0x00, 0x00, 0xfc, 0x05, 0x03, 0x03, 0x00, 0x00, 0xcf, 0x9c, 0x06, 0x02, -0x03, 0x00, 0x00, 0xd5, 0x0d, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf6, 0x11, 0x41, 0x00, 0x77, 0x57, -0x14, 0x41, 0x00, 0x74, 0x54, 0x18, 0x03, 0x03, 0x00, 0x00, 0xab, 0xac, 0x1a, 0x02, 0x03, 0x00, -0x00, 0xa6, 0x1b, 0x02, 0x03, 0x00, 0x00, 0xa7, 0x1e, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x1f, -0x43, 0x00, 0x73, 0x53, 0xe1, 0xf5, 0x20, 0x41, 0x00, 0x64, 0x44, 0x24, 0x02, 0x03, 0x00, 0x00, -0xf2, 0x26, 0x41, 0x00, 0x6c, 0x4c, 0x27, 0x03, 0x03, 0x00, 0x00, 0xf4, 0xf8, 0x29, 0x02, 0x03, -0x00, 0x00, 0xee, 0x2b, 0x02, 0x03, 0x00, 0x00, 0xaa, 0x31, 0x03, 0x03, 0x00, 0x00, 0xbd, 0xbe, -0x32, 0x02, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x02, 0x03, 0x00, 0x00, 0xae, 0x34, 0x02, 0x03, 0x00, -0x00, 0xaf, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, -0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, -0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, 0x7e, 0x5e, 0x17, 0x61, 0x83, 0x65, -0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x77, 0xf7, 0x73, 0xf9, 0x64, 0xd0, 0x6c, 0x9b, 0x6e, -0x9e, 0x74, 0xe7, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x53, 0xdd, 0x57, -0xef, 0x44, 0xd1, 0x4c, 0x9d, 0x4e, 0x9f, 0x54, 0xe8, 0x20, 0x5e, 0x27, 0x0d, 0x61, 0xa0, 0x65, -0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x63, 0x87, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, -0xe0, 0x55, 0xe9, 0x43, 0x80, 0x20, 0x27, 0x22, 0x0f, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6e, -0xa9, 0x6f, 0x94, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4e, 0xb8, 0x4f, -0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0xad, 0x06, 0x02, -0x03, 0x00, 0x00, 0xd5, 0x12, 0x03, 0x03, 0x00, 0x00, 0xfa, 0xfb, 0x15, 0x03, 0x03, 0x00, 0x00, -0xec, 0xed, 0x18, 0x03, 0x03, 0x00, 0x00, 0xab, 0xac, 0x1a, 0x43, 0x00, 0x86, 0x8f, 0x5b, 0x7b, -0x1b, 0x43, 0x00, 0x9b, 0x9d, 0x5d, 0x7d, 0x1e, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x1f, 0x03, -0x07, 0x00, 0x00, 0x00, 0xf5, 0x20, 0x03, 0x03, 0x00, 0x00, 0xd0, 0xd1, 0x22, 0x03, 0x03, 0x00, -0x00, 0xa9, 0xb8, 0x24, 0x03, 0x03, 0x00, 0x00, 0xbd, 0xbe, 0x27, 0x03, 0x07, 0x00, 0x00, 0x00, -0xf8, 0x2b, 0x02, 0x07, 0x00, 0x00, 0xcd, 0x30, 0x03, 0x03, 0x00, 0x00, 0xe7, 0xe8, 0x31, 0x03, -0x03, 0x00, 0x00, 0xa6, 0xa7, 0x32, 0x02, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x02, 0x03, 0x00, 0x00, -0xae, 0x34, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x35, 0x02, 0x03, 0x00, 0x00, 0xa8, 0x00, 0x60, 0x0b, -0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, -0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x05, 0x61, 0xc6, 0x6e, 0xa4, 0x41, 0xc7, 0x4e, 0xa5, -0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, 0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, -0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, 0x20, 0x5e, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, -0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x63, 0x87, 0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, -0x55, 0xe9, 0x43, 0x80, 0x20, 0x27, 0x22, 0x11, 0x61, 0x84, 0x65, 0x89, 0x86, 0xf1, 0x69, 0x8b, -0x6f, 0x94, 0x9b, 0x9e, 0x75, 0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x8f, 0xf2, 0x49, 0xd8, -0x4f, 0x99, 0x9d, 0x9f, 0x55, 0x9a, 0x59, 0xf3, 0x20, 0x22, 0xaa, 0x09, 0x61, 0x9c, 0x69, 0xf4, -0x6f, 0xe1, 0x9b, 0xfc, 0x41, 0xcf, 0x49, 0xf6, 0x4f, 0xee, 0x9d, 0xfd, 0x20, 0xaa, 0x00, 0x05, -0x02, 0x03, 0x00, 0x00, 0xcf, 0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x11, 0x03, 0x03, 0x00, 0x00, -0x94, 0x99, 0x12, 0x03, 0x03, 0x00, 0x00, 0x86, 0x8f, 0x13, 0x03, 0x03, 0x00, 0x00, 0x9c, 0xe6, -0x15, 0x03, 0x03, 0x00, 0x00, 0xec, 0xed, 0x16, 0x03, 0x03, 0x00, 0x00, 0xe1, 0xee, 0x17, 0x03, -0x03, 0x00, 0x00, 0x84, 0x8e, 0x18, 0x03, 0x03, 0x00, 0x00, 0xab, 0xac, 0x19, 0x03, 0x03, 0x00, -0x00, 0x9b, 0x9d, 0x1a, 0x02, 0x03, 0x00, 0x00, 0xa6, 0x1b, 0x02, 0x03, 0x00, 0x00, 0xa7, 0x1e, -0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x1f, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf5, 0x20, 0x03, 0x03, -0x00, 0x00, 0xd0, 0xd1, 0x21, 0x03, 0x03, 0x00, 0x00, 0x9f, 0x9e, 0x22, 0x03, 0x03, 0x00, 0x00, -0xa9, 0xb8, 0x23, 0x03, 0x03, 0x00, 0x00, 0xbd, 0xbe, 0x24, 0x03, 0x03, 0x00, 0x00, 0xf7, 0xef, -0x27, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x2b, 0x02, 0x03, 0x00, 0x00, 0xaa, 0x2e, 0x03, 0x03, -0x00, 0x00, 0xfa, 0xfb, 0x2f, 0x03, 0x03, 0x00, 0x00, 0xf9, 0xdd, 0x30, 0x03, 0x03, 0x00, 0x00, -0xe7, 0xe8, 0x31, 0x03, 0x03, 0x00, 0x00, 0xa8, 0xad, 0x33, 0x02, 0x03, 0x00, 0x00, 0xae, 0x34, -0x02, 0x03, 0x00, 0x00, 0xaf, 0x00, 0x60, 0x0b, 0x61, 0x85, 0x65, 0x8a, 0x69, 0x8d, 0x6f, 0x95, -0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x49, 0xde, 0x4f, 0xe3, 0x55, 0xeb, 0x20, 0x60, 0x7e, 0x0d, -0x61, 0xc6, 0x65, 0xfc, 0x69, 0xf1, 0x6f, 0xe4, 0x75, 0xf4, 0x6e, 0xa4, 0x41, 0xc7, 0x45, 0xfd, -0x49, 0xf2, 0x4f, 0xe5, 0x55, 0xf6, 0x4e, 0xa5, 0x20, 0x7e, 0x5e, 0x0b, 0x61, 0x83, 0x65, 0x88, -0x69, 0x8c, 0x6f, 0x93, 0x75, 0x96, 0x41, 0xb6, 0x45, 0xd2, 0x49, 0xd7, 0x4f, 0xe2, 0x55, 0xea, -0x20, 0x5e, 0x27, 0x0d, 0x61, 0xa0, 0x65, 0x82, 0x69, 0xa1, 0x6f, 0xa2, 0x75, 0xa3, 0x63, 0x87, -0x41, 0xb5, 0x45, 0x90, 0x49, 0xd6, 0x4f, 0xe0, 0x55, 0xe9, 0x43, 0x80, 0x20, 0x27, 0x22, 0x09, -0x65, 0x89, 0x69, 0x8b, 0x75, 0x81, 0x79, 0x98, 0x45, 0xd3, 0x49, 0xd8, 0x55, 0x9a, 0x59, 0xf3, -0x20, 0x22, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0xad, 0x05, 0x03, 0x03, 0x00, 0x00, 0xcf, 0x9c, -0x06, 0x02, 0x03, 0x00, 0x00, 0xd5, 0x10, 0x02, 0x03, 0x00, 0x00, 0xa6, 0x18, 0x03, 0x03, 0x00, -0x00, 0xab, 0xac, 0x19, 0x02, 0x03, 0x00, 0x00, 0xa7, 0x1a, 0x43, 0x00, 0x9e, 0x9f, 0x5b, 0x7b, -0x1b, 0x43, 0x00, 0x9b, 0x9d, 0x5d, 0x7d, 0x1e, 0x03, 0x03, 0x00, 0x00, 0x91, 0x92, 0x1f, 0x03, -0x07, 0x00, 0x00, 0x00, 0xf5, 0x27, 0x03, 0x07, 0x00, 0x00, 0x00, 0xf8, 0x29, 0x02, 0x07, 0x00, -0x00, 0xcd, 0x2b, 0x02, 0x03, 0x00, 0x00, 0xaa, 0x32, 0x02, 0x03, 0x00, 0x00, 0xe6, 0x33, 0x02, -0x03, 0x00, 0x00, 0xae, 0x34, 0x02, 0x03, 0x00, 0x00, 0xaf, 0x35, 0x02, 0x03, 0x00, 0x00, 0xa8, -0x00, 0x60, 0x07, 0x61, 0x85, 0x65, 0x8a, 0x75, 0x97, 0x41, 0xb7, 0x45, 0xd4, 0x55, 0xeb, 0x20, -0x60, 0x7e, 0x07, 0x61, 0xc6, 0x6e, 0xa4, 0x6f, 0xe4, 0x41, 0xc7, 0x4e, 0xa5, 0x4f, 0xe5, 0x20, -0x7e, 0x5e, 0x0f, 0x61, 0x83, 0x65, 0x88, 0x9e, 0xd0, 0x69, 0x8c, 0x6f, 0x93, 0x9b, 0xfa, 0x75, -0x96, 0x41, 0xb6, 0x45, 0xd2, 0x9f, 0xd1, 0x49, 0xd7, 0x4f, 0xe2, 0x9d, 0xfb, 0x55, 0xea, 0x20, -0x5e, 0x27, 0x11, 0x61, 0xa0, 0x65, 0x82, 0x9e, 0xf1, 0x69, 0xa1, 0x6f, 0xa2, 0x9b, 0xec, 0x75, -0xa3, 0x63, 0x87, 0x41, 0xb5, 0x45, 0x90, 0x9f, 0xf2, 0x49, 0xd6, 0x4f, 0xe0, 0x9d, 0xed, 0x55, -0xe9, 0x43, 0x80, 0x20, 0x27, 0x22, 0x0d, 0x61, 0x84, 0x65, 0x89, 0x69, 0x8b, 0x6f, 0x94, 0x75, -0x81, 0x79, 0x98, 0x41, 0x8e, 0x45, 0xd3, 0x49, 0xd8, 0x4f, 0x99, 0x55, 0x9a, 0x59, 0xf3, 0x20, -0x22, 0xee, 0x0d, 0x61, 0x86, 0x65, 0xbd, 0x9e, 0xe7, 0x69, 0xa9, 0x6f, 0xf4, 0x9b, 0xfc, 0x41, -0x8f, 0x45, 0xbe, 0x9f, 0xe8, 0x49, 0xb8, 0x4f, 0xf6, 0x9d, 0xfd, 0x20, 0xee, 0x00, 0x49, 0x4d, -0x01, 0x04, 0x00, 0x00, 0x55, 0x5a, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x62, 0xf3, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x62, 0xf3, 0x44, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x22, 0x40, -0x04, 0x02, 0x01, 0x00, 0xfc, 0x23, 0x05, 0x02, 0x01, 0x00, 0x3b, 0xfd, 0x07, 0x02, 0x01, 0x00, -0x3a, 0x5e, 0x08, 0x02, 0x01, 0x00, 0x3f, 0x26, 0x09, 0x02, 0x03, 0x00, 0x00, 0x24, 0x0c, 0x43, -0x00, 0xf3, 0xf2, 0x2d, 0x5f, 0x0d, 0x43, 0x00, 0xf9, 0xf8, 0x3d, 0x2b, 0x10, 0x41, 0x00, 0xa9, -0x89, 0x11, 0x41, 0x00, 0xe6, 0x96, 0x12, 0x41, 0x00, 0xe3, 0x93, 0x13, 0x41, 0x00, 0xaa, 0x8a, -0x14, 0x41, 0x00, 0xa5, 0x85, 0x15, 0x41, 0x00, 0xad, 0x8d, 0x16, 0x41, 0x00, 0xa3, 0x83, 0x17, -0x41, 0x00, 0xe8, 0x98, 0x18, 0x43, 0x00, 0xf7, 0xf6, 0xe9, 0x99, 0x19, 0x41, 0x00, 0xa7, 0x87, -0x1a, 0x42, 0x00, 0xe5, 0x95, 0x5b, 0x1b, 0x42, 0x00, 0xea, 0x9a, 0x5d, 0x1e, 0x41, 0x00, 0xe4, -0x94, 0x1f, 0x43, 0x00, 0xf5, 0xf4, 0xeb, 0x9b, 0x20, 0x41, 0x00, 0xa2, 0x82, 0x21, 0x41, 0x00, -0xa0, 0x80, 0x22, 0x41, 0x00, 0xaf, 0x8f, 0x23, 0xc1, 0x00, 0xe0, 0x00, 0x90, 0x23, 0x24, 0x41, -0x00, 0xae, 0x8e, 0x25, 0x41, 0x00, 0xab, 0x8b, 0x26, 0x41, 0x00, 0xa4, 0x84, 0x27, 0x41, 0x00, -0xa6, 0x86, 0x28, 0x41, 0x00, 0xed, 0x9d, 0x29, 0x41, 0x00, 0xf1, 0xf0, 0x2a, 0x04, 0x1f, 0x00, -0x00, 0x00, 0x00, 0x78, 0x2b, 0x02, 0x01, 0x00, 0x2f, 0x7c, 0x2c, 0x41, 0x00, 0xef, 0x9f, 0x2d, -0x41, 0x00, 0xe7, 0x97, 0x2e, 0x41, 0x00, 0xe1, 0x91, 0x2f, 0x41, 0x00, 0xac, 0x8c, 0x30, 0x41, -0x00, 0xa8, 0x88, 0x31, 0x41, 0x00, 0xe2, 0x92, 0x32, 0x41, 0x00, 0xec, 0x9c, 0x33, 0x42, 0x00, -0xa1, 0x81, 0x3c, 0x34, 0x42, 0x00, 0xee, 0x9e, 0x3e, 0x35, 0x01, 0x00, 0x2e, 0x2c, 0x00, 0x05, -0x02, 0x03, 0x00, 0x00, 0xfd, 0x36, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x38, 0xbe, -0x01, 0x09, 0x00, 0x00, 0x56, 0x49, 0x2c, 0xcd, 0x01, 0x56, 0x49, 0x02, 0x02, 0x00, 0x00, 0x00, -0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x75, 0x34, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, -0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, -0x43, 0x00, 0xe5, 0xc5, 0x31, 0x21, 0x03, 0x43, 0x00, 0xe2, 0xc2, 0x32, 0x40, 0x04, 0x43, 0x00, -0xea, 0xca, 0x33, 0x23, 0x05, 0x43, 0x00, 0xf4, 0xd4, 0x34, 0x24, 0x06, 0x03, 0x03, 0xc8, 0xc8, -0x35, 0x25, 0x07, 0x03, 0x03, 0xc9, 0xc9, 0x36, 0x5e, 0x08, 0x03, 0x03, 0xca, 0xca, 0x37, 0x26, -0x09, 0x03, 0x03, 0xcb, 0xcb, 0x38, 0x2a, 0x0a, 0x03, 0x03, 0xcc, 0xcc, 0x39, 0x28, 0x0b, 0xc3, -0x00, 0xf0, 0x00, 0xd0, 0x0b, 0x30, 0x81, 0x29, 0x81, 0x12, 0x41, 0x00, 0x65, 0x45, 0x15, 0x41, -0x00, 0x79, 0x59, 0x16, 0x41, 0x00, 0x75, 0x55, 0x17, 0x41, 0x00, 0x69, 0x49, 0x18, 0x41, 0x00, -0x6f, 0x4f, 0x1a, 0x43, 0x00, 0xdf, 0xbf, 0x5b, 0x7b, 0x1b, 0x43, 0x00, 0xbd, 0xb4, 0x5d, 0x7d, -0x1e, 0x41, 0x00, 0x61, 0x41, 0x39, 0x00, 0x00, 0x20, 0x00, 0x60, 0x19, 0x61, 0xe0, 0xe5, 0xa2, -0xe2, 0xa5, 0x65, 0xe8, 0xea, 0xab, 0x69, 0xec, 0x6f, 0xf2, 0xf4, 0xb0, 0xbd, 0xb6, 0x75, 0xf9, -0xdf, 0xd7, 0x79, 0xcf, 0x41, 0xc0, 0xc5, 0x82, 0xc2, 0x85, 0x45, 0xc8, 0xca, 0x8b, 0x49, 0xcc, -0x4f, 0xd2, 0xd4, 0x90, 0xb4, 0x96, 0x55, 0xd9, 0xbf, 0xbb, 0x59, 0x9f, 0x20, 0x60, 0x22, 0x19, -0x61, 0xe4, 0xe5, 0xc6, 0xe2, 0xa6, 0x65, 0xeb, 0xea, 0xac, 0x69, 0xef, 0x6f, 0xf6, 0xf4, 0xb1, -0xbd, 0xb7, 0x75, 0xfc, 0xdf, 0xd8, 0x79, 0xd6, 0x41, 0xc4, 0xc5, 0x02, 0xc2, 0x86, 0x45, 0xcb, -0xca, 0x8c, 0x49, 0x9b, 0x4f, 0x99, 0xd4, 0x91, 0xb4, 0x97, 0x55, 0x9c, 0xbf, 0xbc, 0x59, 0x14, -0x20, 0x22, 0x7e, 0x19, 0x61, 0xe3, 0xe5, 0xc7, 0xe2, 0xe7, 0x65, 0xa8, 0xea, 0xad, 0x69, 0xee, -0x6f, 0xf5, 0xf4, 0xb2, 0xbd, 0xde, 0x75, 0xfb, 0xdf, 0xe6, 0x79, 0xdb, 0x41, 0xc3, 0xc5, 0x05, -0xc2, 0x06, 0x45, 0x88, 0xca, 0x8d, 0x49, 0xce, 0x4f, 0xa0, 0xd4, 0x92, 0xb4, 0xb3, 0x55, 0x9d, -0xbf, 0xff, 0x59, 0x19, 0x20, 0x7e, 0x27, 0x19, 0x61, 0xe1, 0xe5, 0xa1, 0xe2, 0xa4, 0x65, 0xe9, -0xea, 0xaa, 0x69, 0xed, 0x6f, 0xf3, 0xf4, 0xaf, 0xbd, 0xbe, 0x75, 0xfa, 0xdf, 0xd1, 0x79, 0xfd, -0x41, 0xc1, 0xc5, 0x81, 0xc2, 0x84, 0x45, 0xc9, 0xca, 0x8a, 0x49, 0xcd, 0x4f, 0xd3, 0xd4, 0x8f, -0xb4, 0x95, 0x55, 0xda, 0xbf, 0xba, 0x59, 0xdd, 0x20, 0x27, 0x2e, 0x19, 0x61, 0xd5, 0xe5, 0xa3, -0xe2, 0xa7, 0x65, 0xa9, 0xea, 0xae, 0x69, 0xb8, 0x6f, 0xf7, 0xf4, 0xb5, 0xbd, 0xfe, 0x75, 0xf8, -0xdf, 0xf1, 0x79, 0xdc, 0x41, 0x80, 0xc5, 0x83, 0xc2, 0x87, 0x45, 0x89, 0xca, 0x8e, 0x49, 0x98, -0x4f, 0x9a, 0xd4, 0x93, 0xb4, 0x94, 0x55, 0x9e, 0xbf, 0xb9, 0x59, 0x1e, 0x20, 0x2e, 0x00, 0x5c, -0x00, 0x00 }; diff --git a/src/dos/dos_memory.cpp b/src/dos/dos_memory.cpp index 8329aa8..5f1d90c 100644 --- a/src/dos/dos_memory.cpp +++ b/src/dos/dos_memory.cpp @@ -1,461 +1,162 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "dosbox.h" -#include "mem.h" -#include "dos_inc.h" -#include "callback.h" - -#define UMB_START_SEG 0x9fff - -static Bit16u memAllocStrategy = 0x00; - -static void DOS_CompressMemory(void) { - Bit16u mcb_segment=dos.firstMCB; - DOS_MCB mcb(mcb_segment); - DOS_MCB mcb_next(0); - - while (mcb.GetType()!=0x5a) { - mcb_next.SetPt((Bit16u)(mcb_segment+mcb.GetSize()+1)); - if ((mcb.GetPSPSeg()==0) && (mcb_next.GetPSPSeg()==0)) { - mcb.SetSize(mcb.GetSize()+mcb_next.GetSize()+1); - mcb.SetType(mcb_next.GetType()); - } else { - mcb_segment+=mcb.GetSize()+1; - mcb.SetPt(mcb_segment); - } - } -} - -void DOS_FreeProcessMemory(Bit16u pspseg) { - Bit16u mcb_segment=dos.firstMCB; - DOS_MCB mcb(mcb_segment); - while (true) { - if (mcb.GetPSPSeg()==pspseg) { - mcb.SetPSPSeg(MCB_FREE); - } - if (mcb.GetType()==0x5a) { - /* check if currently last block reaches up to the PCJr graphics memory */ - if ((machine==MCH_PCJR) && (mcb_segment+mcb.GetSize()==0x17fe) && - (real_readb(0x17ff,0)==0x4d) && (real_readw(0x17ff,1)==8)) { - /* re-enable the memory past segment 0x2000 */ - mcb.SetType(0x4d); - } else break; - } - mcb_segment+=mcb.GetSize()+1; - mcb.SetPt(mcb_segment); - } - - Bit16u umb_start=dos_infoblock.GetStartOfUMBChain(); - if (umb_start==UMB_START_SEG) { - DOS_MCB umb_mcb(umb_start); - while (true) { - if (umb_mcb.GetPSPSeg()==pspseg) { - umb_mcb.SetPSPSeg(MCB_FREE); - } - if (umb_mcb.GetType()!=0x4d) break; - umb_start+=umb_mcb.GetSize()+1; - umb_mcb.SetPt(umb_start); - } - } else if (umb_start!=0xffff) LOG(LOG_DOSMISC,LOG_ERROR)("Corrupt UMB chain: %x",umb_start); - - DOS_CompressMemory(); -} - -Bit16u DOS_GetMemAllocStrategy() { - return memAllocStrategy; -} - -bool DOS_SetMemAllocStrategy(Bit16u strat) { - if ((strat&0x3f)<3) { - memAllocStrategy = strat; - return true; - } - /* otherwise an invalid allocation strategy was specified */ - return false; -} - -bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { - DOS_CompressMemory(); - Bit16u bigsize=0; - Bit16u mem_strat=memAllocStrategy; - Bit16u mcb_segment=dos.firstMCB; - - Bit16u umb_start=dos_infoblock.GetStartOfUMBChain(); - if (umb_start==UMB_START_SEG) { - /* start with UMBs if requested (bits 7 or 6 set) */ - if (mem_strat&0xc0) mcb_segment=umb_start; - } else if (umb_start!=0xffff) LOG(LOG_DOSMISC,LOG_ERROR)("Corrupt UMB chain: %x",umb_start); - - DOS_MCB mcb(0); - DOS_MCB mcb_next(0); - DOS_MCB psp_mcb(dos.psp()-1); - char psp_name[9]; - psp_mcb.GetFileName(psp_name); - Bit16u found_seg=0,found_seg_size=0; - for (;;) { - mcb.SetPt(mcb_segment); - if (mcb.GetPSPSeg()==0) { - /* Check for enough free memory in current block */ - Bit16u block_size=mcb.GetSize(); - if (block_size<(*blocks)) { - if (bigsizetotal, - in the second case resize block to maximum */ - - if ((mcb_next.GetPSPSeg()==MCB_FREE) && (mcb.GetType()!=0x5a)) { - /* adjust type of joined MCB */ - mcb.SetType(mcb_next.GetType()); - } - mcb.SetSize(total); - mcb.SetPSPSeg(dos.psp()); - if (*blocks==total) return true; /* block fit exactly */ - - *blocks=total; /* return maximum */ - DOS_SetError(DOSERR_INSUFFICIENT_MEMORY); - return false; -} - - -bool DOS_FreeMemory(Bit16u segment) { -//TODO Check if allowed to free this segment - if (segment < DOS_MEM_START+1) { - LOG(LOG_DOSMISC,LOG_ERROR)("Program tried to free %X ---ERROR",segment); - DOS_SetError(DOSERR_MB_ADDRESS_INVALID); - return false; - } - - DOS_MCB mcb(segment-1); - if ((mcb.GetType()!=0x4d) && (mcb.GetType()!=0x5a)) { - DOS_SetError(DOSERR_MB_ADDRESS_INVALID); - return false; - } - mcb.SetPSPSeg(MCB_FREE); -// DOS_CompressMemory(); - return true; -} - - -void DOS_BuildUMBChain(bool umb_active,bool ems_active) { - if (umb_active && (machine!=MCH_TANDY)) { - Bit16u first_umb_seg = 0xd000; - Bit16u first_umb_size = 0x2000; - if(ems_active || (machine == MCH_PCJR)) first_umb_size = 0x1000; - - dos_infoblock.SetStartOfUMBChain(UMB_START_SEG); - dos_infoblock.SetUMBChainState(0); // UMBs not linked yet - - DOS_MCB umb_mcb(first_umb_seg); - umb_mcb.SetPSPSeg(0); // currently free - umb_mcb.SetSize(first_umb_size-1); - umb_mcb.SetType(0x5a); - - /* Scan MCB-chain for last block */ - Bit16u mcb_segment=dos.firstMCB; - DOS_MCB mcb(mcb_segment); - while (mcb.GetType()!=0x5a) { - mcb_segment+=mcb.GetSize()+1; - mcb.SetPt(mcb_segment); - } - - /* A system MCB has to cover the space between the - regular MCB-chain and the UMBs */ - Bit16u cover_mcb=(Bit16u)(mcb_segment+mcb.GetSize()+1); - mcb.SetPt(cover_mcb); - mcb.SetType(0x4d); - mcb.SetPSPSeg(0x0008); - mcb.SetSize(first_umb_seg-cover_mcb-1); - mcb.SetFileName("SC "); - - } else { - dos_infoblock.SetStartOfUMBChain(0xffff); - dos_infoblock.SetUMBChainState(0); - } -} - -bool DOS_LinkUMBsToMemChain(Bit16u linkstate) { - /* Get start of UMB-chain */ - Bit16u umb_start=dos_infoblock.GetStartOfUMBChain(); - if (umb_start!=UMB_START_SEG) { - if (umb_start!=0xffff) LOG(LOG_DOSMISC,LOG_ERROR)("Corrupt UMB chain: %x",umb_start); - return true; - } - - if ((linkstate&1)==(dos_infoblock.GetUMBChainState()&1)) return true; - - /* Scan MCB-chain for last block before UMB-chain */ - Bit16u mcb_segment=dos.firstMCB; - Bit16u prev_mcb_segment=dos.firstMCB; - DOS_MCB mcb(mcb_segment); - while ((mcb_segment!=umb_start) && (mcb.GetType()!=0x5a)) { - prev_mcb_segment=mcb_segment; - mcb_segment+=mcb.GetSize()+1; - mcb.SetPt(mcb_segment); - } - DOS_MCB prev_mcb(prev_mcb_segment); - - switch (linkstate) { - case 0x0000: // unlink - if ((prev_mcb.GetType()==0x4d) && (mcb_segment==umb_start)) { - prev_mcb.SetType(0x5a); - } - dos_infoblock.SetUMBChainState(0); - break; - case 0x0001: // link - if (mcb.GetType()==0x5a) { - mcb.SetType(0x4d); - dos_infoblock.SetUMBChainState(1); - } - break; - default: - LOG_MSG("Invalid link state %x when reconfiguring MCB chain",linkstate); - return false; - } - - return true; -} - - -static Bitu DOS_default_handler(void) { - LOG(LOG_CPU,LOG_ERROR)("DOS rerouted Interrupt Called %X",lastint); - return CBRET_NONE; -} - -static CALLBACK_HandlerObject callbackhandler; -void DOS_SetupMemory(void) { - /* Let dos claim a few bios interrupts. Makes DOSBox more compatible with - * buggy games, which compare against the interrupt table. (probably a - * broken linked list implementation) */ - callbackhandler.Allocate(&DOS_default_handler,"DOS default int"); - Bitu ihseg = 0x70; - Bitu ihofs = 0x08; - real_writeb(ihseg,ihofs+0x00,(Bit8u)0xFE); //GRP 4 - real_writeb(ihseg,ihofs+0x01,(Bit8u)0x38); //Extra Callback instruction - real_writew(ihseg,ihofs+0x02,callbackhandler.Get_callback()); //The immediate word - real_writeb(ihseg,ihofs+0x04,(Bit8u)0xCF); //An IRET Instruction - RealSetVec(0x01,RealMake(ihseg,ihofs)); //BioMenace (offset!=4) - RealSetVec(0x02,RealMake(ihseg,ihofs)); //BioMenace (segment<0x8000) - RealSetVec(0x03,RealMake(ihseg,ihofs)); //Alien Incident (offset!=0) - RealSetVec(0x04,RealMake(ihseg,ihofs)); //Shadow President (lower byte of segment!=0) -// RealSetVec(0x0f,RealMake(ihseg,ihofs)); //Always a tricky one (soundblaster irq) - - // Create a dummy device MCB with PSPSeg=0x0008 - DOS_MCB mcb_devicedummy((Bit16u)DOS_MEM_START); - mcb_devicedummy.SetPSPSeg(MCB_DOS); // Devices - mcb_devicedummy.SetSize(1); - mcb_devicedummy.SetType(0x4d); // More blocks will follow -// mcb_devicedummy.SetFileName("SD "); - - Bit16u mcb_sizes=2; - // Create a small empty MCB (result from a growing environment block) - DOS_MCB tempmcb((Bit16u)DOS_MEM_START+mcb_sizes); - tempmcb.SetPSPSeg(MCB_FREE); - tempmcb.SetSize(4); - mcb_sizes+=5; - tempmcb.SetType(0x4d); - - // Lock the previous empty MCB - DOS_MCB tempmcb2((Bit16u)DOS_MEM_START+mcb_sizes); - tempmcb2.SetPSPSeg(0x40); // can be removed by loadfix - tempmcb2.SetSize(16); - mcb_sizes+=17; - tempmcb2.SetType(0x4d); - - DOS_MCB mcb((Bit16u)DOS_MEM_START+mcb_sizes); - mcb.SetPSPSeg(MCB_FREE); //Free - mcb.SetType(0x5a); //Last Block - if (machine==MCH_TANDY) { - /* memory up to 608k available, the rest (to 640k) is used by - the tandy graphics system's variable mapping of 0xb800 */ - mcb.SetSize(0x97FE - DOS_MEM_START - mcb_sizes); - } else if (machine==MCH_PCJR) { - /* memory from 128k to 640k is available */ - mcb_devicedummy.SetPt((Bit16u)0x2000); - mcb_devicedummy.SetPSPSeg(MCB_FREE); - mcb_devicedummy.SetSize(0x9FFE - 0x2000); - mcb_devicedummy.SetType(0x5a); - - /* exclude PCJr graphics region */ - mcb_devicedummy.SetPt((Bit16u)0x17ff); - mcb_devicedummy.SetPSPSeg(MCB_DOS); - mcb_devicedummy.SetSize(0x800); - mcb_devicedummy.SetType(0x4d); - - /* memory below 96k */ - mcb.SetSize(0x1800 - DOS_MEM_START - (2+mcb_sizes)); - mcb.SetType(0x4d); - } else { - /* complete memory up to 640k available */ - mcb.SetSize(0x9FFE - DOS_MEM_START - mcb_sizes); - } - - dos.firstMCB=DOS_MEM_START; - dos_infoblock.SetFirstMCB(DOS_MEM_START); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "mem.h" +#include "dos_inc.h" + + +#define MEM_START 0x60 //First Segment that DOS can use +//#define MEM_START 4000 //First Segment that DOS can use + + +static void DOS_CompressMemory(void) { + MCB * pmcb;MCB * pmcbnext; + Bit16u mcb_segment; + mcb_segment=dos.firstMCB; + pmcb=(MCB *)real_off(mcb_segment,0); + while (pmcb->type!=0x5a) { + pmcbnext=pmcbnext=(MCB *)real_off(mcb_segment+pmcb->size+1,0); + if ((pmcb->psp_segment==0) && (pmcbnext->psp_segment==0)) { + pmcb->size+=pmcbnext->size+1; + pmcb->type=pmcbnext->type; + } else { + mcb_segment+=pmcb->size+1; + pmcb=(MCB *)real_off(mcb_segment,0); + } + } +} + +void DOS_FreeProcessMemory(Bit16u pspseg) { + MCB * pmcb; + Bit16u mcb_segment=dos.firstMCB; + pmcb=(MCB *)real_off(mcb_segment,0); + while (true) { + if (pmcb->psp_segment==pspseg) { + pmcb->psp_segment=MCB_FREE; + } + mcb_segment+=pmcb->size+1; + if (pmcb->type==0x5a) break; + pmcb=(MCB *)real_off(mcb_segment,0); + } + DOS_CompressMemory(); +}; + + +bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { + MCB * pmcb;MCB * pmcbnext; + Bit16u bigsize=0;Bit16u mcb_segment; + bool stop=false;mcb_segment=dos.firstMCB; + DOS_CompressMemory(); + while(!stop) { + pmcb=(MCB *)real_off(mcb_segment,0); + if (pmcb->psp_segment==0) { + /* Check for enough free memory in current block */ + if (pmcb->size<(*blocks)) { + if (bigsizesize) { + bigsize=pmcb->size; + } + + } else if (pmcb->size==*blocks) { + pmcb->psp_segment=dos.psp; + *segment=mcb_segment+1; + return true; + } else { + /* If so allocate it */ + pmcbnext=(MCB *)real_off(mcb_segment+*blocks+1,0); + pmcbnext->psp_segment=MCB_FREE; + pmcbnext->type=pmcb->type; + pmcbnext->size=pmcb->size-*blocks-1; + pmcb->size=*blocks; + pmcb->type=0x4D; + pmcb->psp_segment=dos.psp; + //TODO Filename + *segment=mcb_segment+1; + return true; + } + } + /* Onward to the next MCB if there is one */ + if (pmcb->type==0x5a) { + *blocks=bigsize; + DOS_SetError(DOSERR_INSUFFICIENT_MEMORY); + return false; + } + mcb_segment+=pmcb->size+1; + } + return false; +}; + + +bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) { + DOS_CompressMemory(); + MCB * pmcb,* pmcbnext,* pmcbnew; + pmcb=(MCB *)real_off(segment-1,0); + pmcbnext=(MCB *)real_off(segment+pmcb->size,0); + Bit16u total=pmcb->size; + if (pmcb->type!=0x5a) { + if (pmcbnext->psp_segment==MCB_FREE) { + total+=pmcbnext->size+1; + } + }; + if (*blockstype!=0x5a) { + pmcb->type=pmcbnext->type; + } + pmcb->size=*blocks; + pmcbnew=(MCB *)real_off(segment+*blocks,0); + pmcbnew->size=total-*blocks-1; + pmcbnew->type=pmcb->type; + pmcbnew->psp_segment=MCB_FREE; + pmcb->type=0x4D; + return true; + } + if (*blocks==total) { + if (pmcb->type!=0x5a) { + pmcb->type=pmcbnext->type; + } + pmcb->size=*blocks; + return true; + } + *blocks=total; + DOS_SetError(DOSERR_INSUFFICIENT_MEMORY); + return false; +}; + + +bool DOS_FreeMemory(Bit16u segment) { +//TODO Check if allowed to free this segment + MCB * pmcb; + pmcb=(MCB *)real_off(segment-1,0); + pmcb->psp_segment=MCB_FREE; + DOS_CompressMemory(); + return true; +} + + + + +void DOS_SetupMemory(void) { +//TODO Maybe allocate some memory for dos transfer buffers +//Although i could use bios regions for that for max free low memory + MCB * mcb=(MCB *) real_off(MEM_START,0); + mcb->psp_segment=MCB_FREE; //Free + mcb->size=0x9FFE - MEM_START; + mcb->type=0x5a; //Last Block + dos.firstMCB=MEM_START; +} + diff --git a/src/dos/dos_misc.cpp b/src/dos/dos_misc.cpp index 45bb7f8..cce5ada 100644 --- a/src/dos/dos_misc.cpp +++ b/src/dos/dos_misc.cpp @@ -1,216 +1,69 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos_misc.cpp,v 1.22 2009/04/28 18:47:04 c2woody Exp $ */ - -#include "dosbox.h" -#include "callback.h" -#include "mem.h" -#include "regs.h" -#include "dos_inc.h" -#include - - -static Bitu call_int2f,call_int2a; - -static std::list Multiplex; -typedef std::list::iterator Multiplex_it; - -void DOS_AddMultiplexHandler(MultiplexHandler * handler) { - Multiplex.push_front(handler); -} - -void DOS_DelMultiplexHandler(MultiplexHandler * handler) { - for(Multiplex_it it =Multiplex.begin();it != Multiplex.end();it++) { - if(*it == handler) { - Multiplex.erase(it); - return; - } - } -} - -static Bitu INT2F_Handler(void) { - for(Multiplex_it it = Multiplex.begin();it != Multiplex.end();it++) - if( (*it)() ) return CBRET_NONE; - - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Multiplex Unhandled call %4X",reg_ax); - return CBRET_NONE; -} - - -static Bitu INT2A_Handler(void) { - return CBRET_NONE; -} - -static bool DOS_MultiplexFunctions(void) { - switch (reg_ax) { - case 0x1216: /* GET ADDRESS OF SYSTEM FILE TABLE ENTRY */ - // reg_bx is a system file table entry, should coincide with - // the file handle so just use that - LOG(LOG_DOSMISC,LOG_ERROR)("Some BAD filetable call used bx=%X",reg_bx); - if(reg_bx <= DOS_FILES) CALLBACK_SCF(false); - else CALLBACK_SCF(true); - if (reg_bx<16) { - RealPt sftrealpt=mem_readd(Real2Phys(dos_infoblock.GetPointer())+4); - PhysPt sftptr=Real2Phys(sftrealpt); - Bitu sftofs=0x06+reg_bx*0x3b; - - if (Files[reg_bx]) mem_writeb(sftptr+sftofs,Files[reg_bx]->refCtr); - else mem_writeb(sftptr+sftofs,0); - - if (!Files[reg_bx]) return true; - - Bit32u handle=RealHandle(reg_bx); - if (handle>=DOS_FILES) { - mem_writew(sftptr+sftofs+0x02,0x02); // file open mode - mem_writeb(sftptr+sftofs+0x04,0x00); // file attribute - mem_writew(sftptr+sftofs+0x05,Files[reg_bx]->GetInformation()); // device info word - mem_writed(sftptr+sftofs+0x07,0); // device driver header - mem_writew(sftptr+sftofs+0x0d,0); // packed time - mem_writew(sftptr+sftofs+0x0f,0); // packed date - mem_writew(sftptr+sftofs+0x11,0); // size - mem_writew(sftptr+sftofs+0x15,0); // current position - } else { - Bit8u drive=Files[reg_bx]->GetDrive(); - - mem_writew(sftptr+sftofs+0x02,(Bit16u)(Files[reg_bx]->flags&3)); // file open mode - mem_writeb(sftptr+sftofs+0x04,(Bit8u)(Files[reg_bx]->attr)); // file attribute - mem_writew(sftptr+sftofs+0x05,0x40|drive); // device info word - mem_writed(sftptr+sftofs+0x07,RealMake(dos.tables.dpb,drive)); // dpb of the drive - mem_writew(sftptr+sftofs+0x0d,Files[reg_bx]->time); // packed file time - mem_writew(sftptr+sftofs+0x0f,Files[reg_bx]->date); // packed file date - Bit32u curpos=0; - Files[reg_bx]->Seek(&curpos,DOS_SEEK_CUR); - Bit32u endpos=0; - Files[reg_bx]->Seek(&endpos,DOS_SEEK_END); - mem_writed(sftptr+sftofs+0x11,endpos); // size - mem_writed(sftptr+sftofs+0x15,curpos); // current position - Files[reg_bx]->Seek(&curpos,DOS_SEEK_SET); - } - - // fill in filename in fcb style - // (space-padded name (8 chars)+space-padded extension (3 chars)) - const char* filename=(const char*)Files[reg_bx]->GetName(); - if (strrchr(filename,'\\')) filename=strrchr(filename,'\\')+1; - if (strrchr(filename,'/')) filename=strrchr(filename,'/')+1; - if (!filename) return true; - const char* dotpos=strrchr(filename,'.'); - if (dotpos) { - dotpos++; - size_t nlen=strlen(filename); - size_t extlen=strlen(dotpos); - Bits nmelen=(Bits)nlen-(Bits)extlen; - if (nmelen<1) return true; - nlen-=(extlen+1); - - if (nlen>8) nlen=8; - size_t i; - - for (i=0; i3) extlen=3; - for (i=0; i8) nlen=8; - for (i=0; inext=first_multiplex; + new_multiplex->handler=handler; + first_multiplex=new_multiplex; +} + +static Bitu INT2F_Handler(void) { + MultiplexBlock * loop_multiplex=first_multiplex; + while (loop_multiplex) { + if ((*loop_multiplex->handler)()) return CBRET_NONE; + loop_multiplex=loop_multiplex->next; + } + LOG_WARN("DOS:Multiplex Unhandled call %4X",reg_ax); + return CBRET_NONE; +}; + + +static Bitu INT2A_Handler(void) { + + return CBRET_NONE; +}; + + +void DOS_SetupMisc(void) { + /* Setup the dos multiplex interrupt */ + first_multiplex=0; + call_int2f=CALLBACK_Allocate(); + CALLBACK_Setup(call_int2f,&INT2F_Handler,CB_IRET); + RealSetVec(0x2f,CALLBACK_RealPointer(call_int2f)); + /* Setup the dos network interrupt */ + call_int2a=CALLBACK_Allocate(); + CALLBACK_Setup(call_int2a,&INT2A_Handler,CB_IRET); + RealSetVec(0x2A<<2,CALLBACK_RealPointer(call_int2a)); +}; + diff --git a/src/dos/dos_mscdex.cpp b/src/dos/dos_mscdex.cpp deleted file mode 100644 index ecb7373..0000000 --- a/src/dos/dos_mscdex.cpp +++ /dev/null @@ -1,1289 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos_mscdex.cpp,v 1.59 2009/04/16 12:28:30 qbix79 Exp $ */ - -#include -#include -#include "regs.h" -#include "callback.h" -#include "dos_system.h" -#include "dos_inc.h" -#include "setup.h" -#include "support.h" -#include "bios_disk.h" -#include "cpu.h" - -#include "cdrom.h" - -#define MSCDEX_LOG LOG(LOG_MISC,LOG_ERROR) -//#define MSCDEX_LOG - -#define MSCDEX_VERSION_HIGH 2 -#define MSCDEX_VERSION_LOW 23 -#define MSCDEX_MAX_DRIVES 8 - -// Error Codes -#define MSCDEX_ERROR_BAD_FORMAT 11 -#define MSCDEX_ERROR_UNKNOWN_DRIVE 15 -#define MSCDEX_ERROR_DRIVE_NOT_READY 21 - -// Request Status -#define REQUEST_STATUS_DONE 0x0100 -#define REQUEST_STATUS_ERROR 0x8000 - -// Use cdrom Interface -int useCdromInterface = CDROM_USE_SDL; -int forceCD = -1; - -static Bitu MSCDEX_Strategy_Handler(void); -static Bitu MSCDEX_Interrupt_Handler(void); - -class DOS_DeviceHeader:public MemStruct { -public: - DOS_DeviceHeader(PhysPt ptr) { pt = ptr; }; - - void SetNextDeviceHeader (RealPt ptr) { sSave(sDeviceHeader,nextDeviceHeader,ptr); }; - RealPt GetNextDeviceHeader (void) { return sGet(sDeviceHeader,nextDeviceHeader); }; - void SetAttribute (Bit16u atr) { sSave(sDeviceHeader,devAttributes,atr); }; - void SetDriveLetter (Bit8u letter) { sSave(sDeviceHeader,driveLetter,letter); }; - void SetNumSubUnits (Bit8u num) { sSave(sDeviceHeader,numSubUnits,num); }; - Bit8u GetNumSubUnits (void) { return sGet(sDeviceHeader,numSubUnits); }; - void SetName (char const* _name) { MEM_BlockWrite(pt+offsetof(sDeviceHeader,name),_name,8); }; - void SetInterrupt (Bit16u ofs) { sSave(sDeviceHeader,interrupt,ofs); }; - void SetStrategy (Bit16u ofs) { sSave(sDeviceHeader,strategy,ofs); }; - -public: - #ifdef _MSC_VER - #pragma pack(1) - #endif - struct sDeviceHeader{ - RealPt nextDeviceHeader; - Bit16u devAttributes; - Bit16u strategy; - Bit16u interrupt; - Bit8u name[8]; - Bit16u wReserved; - Bit8u driveLetter; - Bit8u numSubUnits; - } GCC_ATTRIBUTE(packed) TDeviceHeader; - #ifdef _MSC_VER - #pragma pack() - #endif -}; - -class CMscdex { -public: - CMscdex (void); - ~CMscdex (void); - - Bit16u GetVersion (void) { return (MSCDEX_VERSION_HIGH<<8)+MSCDEX_VERSION_LOW; }; - Bit16u GetNumDrives (void) { return numDrives; }; - Bit16u GetFirstDrive (void) { return dinfo[0].drive; }; - Bit8u GetSubUnit (Bit16u _drive); - bool GetUPC (Bit8u subUnit, Bit8u& attr, char* upc); - - void InitNewMedia (Bit8u subUnit); - bool PlayAudioSector (Bit8u subUnit, Bit32u start, Bit32u length); - bool PlayAudioMSF (Bit8u subUnit, Bit32u start, Bit32u length); - bool StopAudio (Bit8u subUnit); - bool GetAudioStatus (Bit8u subUnit, bool& playing, bool& pause, TMSF& start, TMSF& end); - - bool GetSubChannelData (Bit8u subUnit, Bit8u& attr, Bit8u& track, Bit8u &index, TMSF& rel, TMSF& abs); - - int RemoveDrive (Bit16u _drive); - int AddDrive (Bit16u _drive, char* physicalPath, Bit8u& subUnit); - bool HasDrive (Bit16u drive); - void ReplaceDrive (CDROM_Interface* newCdrom, Bit8u subUnit); - void GetDrives (PhysPt data); - void GetDriverInfo (PhysPt data); - bool GetVolumeName (Bit8u subUnit, char* name); - bool GetCopyrightName (Bit16u drive, PhysPt data); - bool GetAbstractName (Bit16u drive, PhysPt data); - bool GetDocumentationName(Bit16u drive, PhysPt data); - bool GetDirectoryEntry (Bit16u drive, bool copyFlag, PhysPt pathname, PhysPt buffer, Bit16u& error); - bool ReadVTOC (Bit16u drive, Bit16u volume, PhysPt data, Bit16u& error); - bool ReadSectors (Bit16u drive, Bit32u sector, Bit16u num, PhysPt data); - bool ReadSectors (Bit8u subUnit, bool raw, Bit32u sector, Bit16u num, PhysPt data); - bool ReadSectorsMSF (Bit8u subUnit, bool raw, Bit32u sector, Bit16u num, PhysPt data); - bool SendDriverRequest (Bit16u drive, PhysPt data); - bool IsValidDrive (Bit16u drive); - bool GetCDInfo (Bit8u subUnit, Bit8u& tr1, Bit8u& tr2, TMSF& leadOut); - Bit32u GetVolumeSize (Bit8u subUnit); - bool GetTrackInfo (Bit8u subUnit, Bit8u track, Bit8u& attr, TMSF& start); - Bit16u GetStatusWord (Bit8u subUnit,Bit16u status); - bool GetCurrentPos (Bit8u subUnit, TMSF& pos); - Bit32u GetDeviceStatus (Bit8u subUnit); - bool GetMediaStatus (Bit8u subUnit, Bit8u& status); - bool LoadUnloadMedia (Bit8u subUnit, bool unload); - bool ResumeAudio (Bit8u subUnit); - bool GetMediaStatus (Bit8u subUnit, bool& media, bool& changed, bool& trayOpen); - -private: - - PhysPt GetDefaultBuffer (void); - PhysPt GetTempBuffer (void); - - Bit16u numDrives; - - typedef struct SDriveInfo { - Bit8u drive; // drive letter in dosbox - Bit8u physDrive; // drive letter in system - bool audioPlay; // audio playing active - bool audioPaused; // audio playing paused - Bit32u audioStart; // StartLoc for resume - Bit32u audioEnd; // EndLoc for resume - bool locked; // drive locked ? - bool lastResult; // last operation success ? - Bit32u volumeSize; // for media change - } TDriveInfo; - - Bit16u defaultBufSeg; - TDriveInfo dinfo[MSCDEX_MAX_DRIVES]; - CDROM_Interface* cdrom[MSCDEX_MAX_DRIVES]; - -public: - Bit16u rootDriverHeaderSeg; -}; - -CMscdex::CMscdex(void) { - numDrives = 0; - rootDriverHeaderSeg = 0; - defaultBufSeg = 0; - - memset(dinfo,0,sizeof(dinfo)); - for (Bit32u i=0; i=MSCDEX_MAX_DRIVES) return 4; - if (GetNumDrives()) { - // Error check, driveletter have to be in a row - if (dinfo[0].drive-1!=_drive && dinfo[numDrives-1].drive+1!=_drive) - return 1; - } - // Set return type to ok - int result = 0; - // Get Mounttype and init needed cdrom interface - switch (CDROM_GetMountType(physicalPath,forceCD)) { - case 0x00: { - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting physical cdrom: %s" ,physicalPath); -#if defined (WIN32) - // Check OS - OSVERSIONINFO osi; - osi.dwOSVersionInfoSize = sizeof(osi); - GetVersionEx(&osi); - if ((osi.dwPlatformId==VER_PLATFORM_WIN32_NT) && (osi.dwMajorVersion>4)) { - // only WIN NT/200/XP - if (useCdromInterface==CDROM_USE_IOCTL_DIO) { - cdrom[numDrives] = new CDROM_Interface_Ioctl(CDROM_Interface_Ioctl::CDIOCTL_CDA_DIO); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: IOCTL Interface."); - break; - } - if (useCdromInterface==CDROM_USE_IOCTL_DX) { - cdrom[numDrives] = new CDROM_Interface_Ioctl(CDROM_Interface_Ioctl::CDIOCTL_CDA_DX); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: IOCTL Interface (digital audio extraction)."); - break; - } - if (useCdromInterface==CDROM_USE_IOCTL_MCI) { - cdrom[numDrives] = new CDROM_Interface_Ioctl(CDROM_Interface_Ioctl::CDIOCTL_CDA_MCI); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: IOCTL Interface (media control interface)."); - break; - } - } - if (useCdromInterface==CDROM_USE_ASPI) { - // all Wins - ASPI - cdrom[numDrives] = new CDROM_Interface_Aspi(); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: ASPI Interface."); - break; - } -#endif -#if defined (LINUX) || defined(OS2) - // Always use IOCTL in Linux or OS/2 - cdrom[numDrives] = new CDROM_Interface_Ioctl(); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: IOCTL Interface."); -#else - // Default case windows and other oses - cdrom[numDrives] = new CDROM_Interface_SDL(); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: SDL Interface."); -#endif - } break; - case 0x01: // iso cdrom interface - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting iso file as cdrom: %s", physicalPath); - cdrom[numDrives] = new CDROM_Interface_Image((Bit8u)numDrives); - break; - case 0x02: // fake cdrom interface (directories) - cdrom[numDrives] = new CDROM_Interface_Fake; - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting directory as cdrom: %s",physicalPath); - LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: You wont have full MSCDEX support !"); - result = 5; - break; - default : // weird result - return 6; - }; - - if (!cdrom[numDrives]->SetDevice(physicalPath,forceCD)) { -// delete cdrom[numDrives] ; mount seems to delete it - return 3; - } - - - if (rootDriverHeaderSeg==0) { - - Bit16u driverSize = sizeof(DOS_DeviceHeader::sDeviceHeader) + 10; // 10 = Bytes for 3 callbacks - - // Create Device Header - Bit16u seg = DOS_GetMemory(driverSize/16+((driverSize%16)>0)); - DOS_DeviceHeader devHeader(PhysMake(seg,0)); - devHeader.SetNextDeviceHeader (0xFFFFFFFF); - devHeader.SetAttribute(0xc800); - devHeader.SetDriveLetter (_drive+1); - devHeader.SetNumSubUnits (1); - devHeader.SetName ("MSCD001 "); - - //Link it in the device chain - Bit32u start = dos_infoblock.GetDeviceChain(); - Bit16u segm = (Bit16u)(start>>16); - Bit16u offm = (Bit16u)(start&0xFFFF); - while(start != 0xFFFFFFFF) { - segm = (Bit16u)(start>>16); - offm = (Bit16u)(start&0xFFFF); - start = real_readd(segm,offm); - } - real_writed(segm,offm,seg<<16); - - // Create Callback Strategy - Bit16u off = sizeof(DOS_DeviceHeader::sDeviceHeader); - Bitu call_strategy=CALLBACK_Allocate(); - CallBack_Handlers[call_strategy]=MSCDEX_Strategy_Handler; - real_writeb(seg,off+0,(Bit8u)0xFE); //GRP 4 - real_writeb(seg,off+1,(Bit8u)0x38); //Extra Callback instruction - real_writew(seg,off+2,call_strategy); //The immediate word - real_writeb(seg,off+4,(Bit8u)0xCB); //A RETF Instruction - devHeader.SetStrategy(off); - - // Create Callback Interrupt - off += 5; - Bitu call_interrupt=CALLBACK_Allocate(); - CallBack_Handlers[call_interrupt]=MSCDEX_Interrupt_Handler; - real_writeb(seg,off+0,(Bit8u)0xFE); //GRP 4 - real_writeb(seg,off+1,(Bit8u)0x38); //Extra Callback instruction - real_writew(seg,off+2,call_interrupt); //The immediate word - real_writeb(seg,off+4,(Bit8u)0xCB); //A RETF Instruction - devHeader.SetInterrupt(off); - - rootDriverHeaderSeg = seg; - - } else if (GetNumDrives() == 0) { - DOS_DeviceHeader devHeader(PhysMake(rootDriverHeaderSeg,0)); - Bit16u off = sizeof(DOS_DeviceHeader::sDeviceHeader); - devHeader.SetDriveLetter(_drive+1); - devHeader.SetStrategy(off); - devHeader.SetInterrupt(off+5); - } - - subUnit = (Bit8u)numDrives; - // Set drive - DOS_DeviceHeader devHeader(PhysMake(rootDriverHeaderSeg,0)); - devHeader.SetNumSubUnits(devHeader.GetNumSubUnits()+1); - - if (dinfo[0].drive-1==_drive) { - CDROM_Interface *_cdrom = cdrom[numDrives]; - for (Bit16u i=GetNumDrives(); i>0; i--) { - dinfo[i] = dinfo[i-1]; - cdrom[i] = cdrom[i-1]; - } - cdrom[0] = _cdrom; - dinfo[0].drive = (Bit8u)_drive; - dinfo[0].physDrive = toupper(physicalPath[0]); - } else { - dinfo[numDrives].drive = (Bit8u)_drive; - dinfo[numDrives].physDrive = toupper(physicalPath[0]); - } - numDrives++; - // stop audio - StopAudio(subUnit); - return result; -} - -bool CMscdex::HasDrive(Bit16u drive) { - return (GetSubUnit(drive) != 0xff); -} - -void CMscdex::ReplaceDrive(CDROM_Interface* newCdrom, Bit8u subUnit) { - delete cdrom[subUnit]; - cdrom[subUnit] = newCdrom; - StopAudio(subUnit); -} - -PhysPt CMscdex::GetDefaultBuffer(void) { - if (defaultBufSeg==0) { - Bit16u size = (2352*2+15)/16; - defaultBufSeg = DOS_GetMemory(size); - }; - return PhysMake(defaultBufSeg,2352); -} - -PhysPt CMscdex::GetTempBuffer(void) { - if (defaultBufSeg==0) { - Bit16u size = (2352*2+15)/16; - defaultBufSeg = DOS_GetMemory(size); - }; - return PhysMake(defaultBufSeg,0); -} - -void CMscdex::GetDriverInfo (PhysPt data) { - for (Bit16u i=0; i=numDrives) return false; - int tr1i,tr2i; - // Assume Media change - cdrom[subUnit]->InitNewMedia(); - dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioTracks(tr1i,tr2i,leadOut); - if (!dinfo[subUnit].lastResult) { - tr1 = tr2 = 0; - memset(&leadOut,0,sizeof(leadOut)); - } else { - tr1 = (Bit8u) tr1i; - tr2 = (Bit8u) tr2i; - } - return dinfo[subUnit].lastResult; -} - -bool CMscdex::GetTrackInfo(Bit8u subUnit, Bit8u track, Bit8u& attr, TMSF& start) -{ - if (subUnit>=numDrives) return false; - dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioTrackInfo(track,start,attr); - if (!dinfo[subUnit].lastResult) { - attr = 0; - memset(&start,0,sizeof(start)); - }; - return dinfo[subUnit].lastResult; -} - -bool CMscdex::PlayAudioSector(Bit8u subUnit, Bit32u sector, Bit32u length) -{ - if (subUnit>=numDrives) return false; - // If value from last stop is used, this is meant as a resume - // better start using resume command - if (dinfo[subUnit].audioPaused && (sector==dinfo[subUnit].audioStart)) { - dinfo[subUnit].lastResult = cdrom[subUnit]->PauseAudio(true); - } else - dinfo[subUnit].lastResult = cdrom[subUnit]->PlayAudioSector(sector,length); - - if (dinfo[subUnit].lastResult) { - dinfo[subUnit].audioPlay = true; - dinfo[subUnit].audioPaused = false; - dinfo[subUnit].audioStart = sector; - dinfo[subUnit].audioEnd = length; - }; - return dinfo[subUnit].lastResult; -} - -bool CMscdex::PlayAudioMSF(Bit8u subUnit, Bit32u start, Bit32u length) -{ - if (subUnit>=numDrives) return false; - Bit8u min = (Bit8u)(start>>16) & 0xFF; - Bit8u sec = (Bit8u)(start>> 8) & 0xFF; - Bit8u fr = (Bit8u)(start>> 0) & 0xFF; - Bit32u sector = min*60*75+sec*75+fr - 150; - return dinfo[subUnit].lastResult = PlayAudioSector(subUnit,sector,length); -} - -bool CMscdex::GetSubChannelData(Bit8u subUnit, Bit8u& attr, Bit8u& track, Bit8u &index, TMSF& rel, TMSF& abs) -{ - if (subUnit>=numDrives) return false; - dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioSub(attr,track,index,rel,abs); - if (!dinfo[subUnit].lastResult) { - attr = track = index = 0; - memset(&rel,0,sizeof(rel)); - memset(&abs,0,sizeof(abs)); - }; - return dinfo[subUnit].lastResult; -} - -bool CMscdex::GetAudioStatus(Bit8u subUnit, bool& playing, bool& pause, TMSF& start, TMSF& end) -{ - if (subUnit>=numDrives) return false; - dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioStatus(playing,pause); - if (dinfo[subUnit].lastResult) { - // Start - Bit32u addr = dinfo[subUnit].audioStart + 150; - start.fr = (Bit8u)(addr%75); addr/=75; - start.sec = (Bit8u)(addr%60); - start.min = (Bit8u)(addr/60); - // End - addr = dinfo[subUnit].audioEnd + 150; - end.fr = (Bit8u)(addr%75); addr/=75; - end.sec = (Bit8u)(addr%60); - end.min = (Bit8u)(addr/60); - } else { - playing = false; - pause = false; - memset(&start,0,sizeof(start)); - memset(&end,0,sizeof(end)); - }; - - return dinfo[subUnit].lastResult; -} - -bool CMscdex::StopAudio(Bit8u subUnit) -{ - if (subUnit>=numDrives) return false; - if (dinfo[subUnit].audioPlay) dinfo[subUnit].lastResult = cdrom[subUnit]->PauseAudio(false); - else dinfo[subUnit].lastResult = cdrom[subUnit]->StopAudio(); - - if (dinfo[subUnit].lastResult) { - if (dinfo[subUnit].audioPlay) { - TMSF pos; - GetCurrentPos(subUnit,pos); - dinfo[subUnit].audioStart = pos.min*60*75+pos.sec*75+pos.fr - 150; - dinfo[subUnit].audioPaused = true; - } else { - dinfo[subUnit].audioPaused = false; - dinfo[subUnit].audioStart = 0; - dinfo[subUnit].audioEnd = 0; - }; - dinfo[subUnit].audioPlay = false; - }; - return dinfo[subUnit].lastResult; -} - -bool CMscdex::ResumeAudio(Bit8u subUnit) -{ - if (subUnit>=numDrives) return false; - return dinfo[subUnit].lastResult = PlayAudioSector(subUnit,dinfo[subUnit].audioStart,dinfo[subUnit].audioEnd); -} - -Bit32u CMscdex::GetVolumeSize(Bit8u subUnit) -{ - if (subUnit>=numDrives) return false; - Bit8u tr1,tr2; - TMSF leadOut; - dinfo[subUnit].lastResult = GetCDInfo(subUnit,tr1,tr2,leadOut); - if (dinfo[subUnit].lastResult) return (leadOut.min*60*75)+(leadOut.sec*75)+leadOut.fr; - return 0; -} - -bool CMscdex::ReadVTOC(Bit16u drive, Bit16u volume, PhysPt data, Bit16u& error) -{ - if (!ReadSectors(GetSubUnit(drive),false,16+volume,1,data)) { - error=MSCDEX_ERROR_DRIVE_NOT_READY; - return false; - } - char id[5]; - MEM_BlockRead(data + 1, id, 5); - if (strncmp("CD001",id, 5)!=0) { - error = MSCDEX_ERROR_BAD_FORMAT; - return false; - } - Bit8u type = mem_readb(data); - error = (type == 1) ? 1 : (type == 0xFF) ? 0xFF : 0; - return true; -} - -bool CMscdex::GetVolumeName(Bit8u subUnit, char* data) { - if (subUnit>=numDrives) return false; - Bit16u drive = dinfo[subUnit].drive; - - Bit16u error; - bool success = false; - PhysPt ptoc = GetTempBuffer(); - success = ReadVTOC(drive,0x00,ptoc,error); - if (success) { - MEM_StrCopy(ptoc+40,data,31); - data[31] = 0; - rtrim(data); - }; - - return success; -} - -bool CMscdex::GetCopyrightName(Bit16u drive, PhysPt data) { - Bit16u error; - bool success = false; - PhysPt ptoc = GetTempBuffer(); - success = ReadVTOC(drive,0x00,ptoc,error); - if (success) { - MEM_BlockCopy(data,ptoc+702,37); - mem_writeb(data+37,0); - }; - return success; -} - -bool CMscdex::GetAbstractName(Bit16u drive, PhysPt data) { - Bit16u error; - bool success = false; - PhysPt ptoc = GetTempBuffer(); - success = ReadVTOC(drive,0x00,ptoc,error); - if (success) { - MEM_BlockCopy(data,ptoc+739,37); - mem_writeb(data+37,0); - }; - return success; -} - -bool CMscdex::GetDocumentationName(Bit16u drive, PhysPt data) { - Bit16u error; - bool success = false; - PhysPt ptoc = GetTempBuffer(); - success = ReadVTOC(drive,0x00,ptoc,error); - if (success) { - MEM_BlockCopy(data,ptoc+776,37); - mem_writeb(data+37,0); - }; - return success; -} - -bool CMscdex::GetUPC(Bit8u subUnit, Bit8u& attr, char* upc) -{ - if (subUnit>=numDrives) return false; - return dinfo[subUnit].lastResult = cdrom[subUnit]->GetUPC(attr,&upc[0]); -} - -bool CMscdex::ReadSectors(Bit8u subUnit, bool raw, Bit32u sector, Bit16u num, PhysPt data) { - if (subUnit>=numDrives) return false; - if ((4*num*2048+5) < CPU_Cycles) CPU_Cycles -= 4*num*2048; - else CPU_Cycles = 5; - dinfo[subUnit].lastResult = cdrom[subUnit]->ReadSectors(data,raw,sector,num); - return dinfo[subUnit].lastResult; -} - -bool CMscdex::ReadSectorsMSF(Bit8u subUnit, bool raw, Bit32u start, Bit16u num, PhysPt data) { - if (subUnit>=numDrives) return false; - Bit8u min = (Bit8u)(start>>16) & 0xFF; - Bit8u sec = (Bit8u)(start>> 8) & 0xFF; - Bit8u fr = (Bit8u)(start>> 0) & 0xFF; - Bit32u sector = min*60*75+sec*75+fr - 150; - return ReadSectors(subUnit,raw,sector,num,data); -} - -// Called from INT 2F -bool CMscdex::ReadSectors(Bit16u drive, Bit32u sector, Bit16u num, PhysPt data) { - return ReadSectors(GetSubUnit(drive),false,sector,num,data); -} - -bool CMscdex::GetDirectoryEntry(Bit16u drive, bool copyFlag, PhysPt pathname, PhysPt buffer, Bit16u& error) -{ - char volumeID[6] = {0}; - char searchName[256]; - char entryName[256]; - bool foundComplete = false; - bool foundName; - char* useName = 0; - Bitu entryLength,nameLength; - // clear error - error = 0; - MEM_StrCopy(pathname+1,searchName,mem_readb(pathname)); - upcase(searchName); - char* searchPos = searchName; - - //strip of tailing . (XCOM APOCALYPSE) - size_t searchlen = strlen(searchName); - if (searchlen > 1 && strcmp(searchName,"..")) - if (searchName[searchlen-1] =='.') searchName[searchlen-1] = 0; - - //LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Get DirEntry : Find : %s",searchName); - // read vtoc - PhysPt defBuffer = GetDefaultBuffer(); - if (!ReadSectors(GetSubUnit(drive),false,16,1,defBuffer)) return false; - // TODO: has to be iso 9960 - MEM_StrCopy(defBuffer+1,volumeID,5); volumeID[5] = 0; - bool iso = (strcmp("CD001",volumeID)==0); - if (!iso) E_Exit("MSCDEX: GetDirEntry: Not an ISO 9960 CD."); - // get directory position - Bitu dirEntrySector = mem_readd(defBuffer+156+2); - Bits dirSize = mem_readd(defBuffer+156+10); - Bitu index; - while (dirSize>0) { - index = 0; - if (!ReadSectors(GetSubUnit(drive),false,dirEntrySector,1,defBuffer)) return false; - // Get string part - foundName = false; - if (searchPos) { - useName = searchPos; - searchPos = strchr(searchPos,'\\'); - } - - if (searchPos) { *searchPos = 0; searchPos++; } - else foundComplete = true; - - do { - entryLength = mem_readb(defBuffer+index); - if (entryLength==0) break; - nameLength = mem_readb(defBuffer+index+32); - MEM_StrCopy(defBuffer+index+33,entryName,nameLength); - if (strcmp(entryName,useName)==0) { - //LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Get DirEntry : Found : %s",useName); - foundName = true; - break; - } - /* Xcom Apocalipse searches for MUSIC. and expects to find MUSIC;1 - * All Files on the CDROM are of the kind blah;1 - */ - char* longername = strchr(entryName,';'); - if(longername) { - *longername = 0; - if (strcmp(entryName,useName)==0) { - //LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Get DirEntry : Found : %s",useName); - foundName = true; - break; - } - } - index += entryLength; - } while (index+33<=2048); - - if (foundName) { - if (foundComplete) { - if (copyFlag) { - LOG(LOG_MISC,LOG_WARN)("MSCDEX: GetDirEntry: Copyflag structure not entirely accurate maybe"); - Bit8u readBuf[256]; - Bit8u writeBuf[256]; - if (entryLength > 256) - return false; - MEM_BlockRead( defBuffer+index, readBuf, entryLength ); - writeBuf[0] = readBuf[1]; // 00h BYTE length of XAR in Logical Block Numbers - memcpy( &writeBuf[1], &readBuf[0x2], 4); // 01h DWORD Logical Block Number of file start - writeBuf[5] = 0;writeBuf[6] = 8; // 05h WORD size of disk in logical blocks - memcpy( &writeBuf[7], &readBuf[0xa], 4); // 07h DWORD file length in bytes - memcpy( &writeBuf[0xb], &readBuf[0x12], 7); // 0bh DWORD date and time - writeBuf[0x12] = readBuf[0x19]; // 12h BYTE bit flags - writeBuf[0x13] = readBuf[0x1a]; // 13h BYTE interleave size - writeBuf[0x14] = readBuf[0x1b]; // 14h BYTE interleave skip factor - memcpy( &writeBuf[0x15], &readBuf[0x1c], 2); // 15h WORD volume set sequence number - writeBuf[0x17] = readBuf[0x20]; - memcpy( &writeBuf[0x18], &readBuf[21], readBuf[0x20] <= 38 ? readBuf[0x20] : 38 ); - MEM_BlockWrite( buffer, writeBuf, 0x18 + 40 ); - } else { - // Direct copy - MEM_BlockCopy(buffer,defBuffer+index,entryLength); - } - error = iso ? 1:0; - return true; - } - // change directory - dirEntrySector = mem_readd(defBuffer+index+2); - dirSize = mem_readd(defBuffer+index+10); - } else { - // continue search in next sector - dirSize -= 2048; - dirEntrySector++; - } - }; - error = 2; // file not found - return false; // not found -} - -bool CMscdex::GetCurrentPos(Bit8u subUnit, TMSF& pos) -{ - if (subUnit>=numDrives) return false; - TMSF rel; - Bit8u attr,track,index; - dinfo[subUnit].lastResult = GetSubChannelData(subUnit, attr, track, index, rel, pos); - if (!dinfo[subUnit].lastResult) memset(&pos,0,sizeof(pos)); - return dinfo[subUnit].lastResult; -} - -bool CMscdex::GetMediaStatus(Bit8u subUnit, bool& media, bool& changed, bool& trayOpen) -{ - if (subUnit>=numDrives) return false; - dinfo[subUnit].lastResult = cdrom[subUnit]->GetMediaTrayStatus(media,changed,trayOpen); - return dinfo[subUnit].lastResult; -} - -Bit32u CMscdex::GetDeviceStatus(Bit8u subUnit) -{ - if (subUnit>=numDrives) return false; - bool media,changed,trayOpen; - - dinfo[subUnit].lastResult = GetMediaStatus(subUnit,media,changed,trayOpen); - Bit32u status = (trayOpen << 0) | // Drive is open ? - (dinfo[subUnit].locked << 1) | // Drive is locked ? - (1<<2) | // raw + cooked sectors - (1<<4) | // Can read sudio - (1<<9) | // Red book & HSG - ((!media) << 11); // Drive is empty ? - return status; -} - -bool CMscdex::GetMediaStatus(Bit8u subUnit, Bit8u& status) -{ - if (subUnit>=numDrives) return false; -/* bool media,changed,open,result; - result = GetMediaStatus(subUnit,media,changed,open); - status = changed ? 0xFF : 0x01; - return result; */ - status = getSwapRequest() ? 0xFF : 0x01; - return true; -} - -bool CMscdex::LoadUnloadMedia(Bit8u subUnit, bool unload) -{ - if (subUnit>=numDrives) return false; - dinfo[subUnit].lastResult = cdrom[subUnit]->LoadUnloadMedia(unload); - return dinfo[subUnit].lastResult; -} - -bool CMscdex::SendDriverRequest(Bit16u drive, PhysPt data) -{ - Bit8u subUnit = GetSubUnit(drive); - if (subUnit>=numDrives) return false; - // Get SubUnit - mem_writeb(data+1,subUnit); - // Call Strategy / Interrupt - MSCDEX_Strategy_Handler(); - MSCDEX_Interrupt_Handler(); - return true; -} - -Bit16u CMscdex::GetStatusWord(Bit8u subUnit,Bit16u status) -{ - if (subUnit>=numDrives) return REQUEST_STATUS_ERROR | 0x02; // error : Drive not ready - - if (dinfo[subUnit].lastResult) status |= REQUEST_STATUS_DONE; // ok - else status |= REQUEST_STATUS_ERROR; - - if (dinfo[subUnit].audioPlay) { - // Check if audio is still playing.... - TMSF start,end; - bool playing,pause; - if (GetAudioStatus(subUnit,playing,pause,start,end)) { - dinfo[subUnit].audioPlay = playing; - } else - dinfo[subUnit].audioPlay = false; - - status |= (dinfo[subUnit].audioPlay<<9); - } - dinfo[subUnit].lastResult = true; - return status; -} - -void CMscdex::InitNewMedia(Bit8u subUnit) { - if (subUnitInitNewMedia(); - } -} - -static CMscdex* mscdex = 0; -static PhysPt curReqheaderPtr = 0; - -static Bit16u MSCDEX_IOCTL_Input(PhysPt buffer,Bit8u drive_unit) { - Bitu ioctl_fct = mem_readb(buffer); - MSCDEX_LOG("MSCDEX: IOCTL INPUT Subfunction %02X",ioctl_fct); - switch (ioctl_fct) { - case 0x00 : /* Get Device Header address */ - mem_writed(buffer+1,RealMake(mscdex->rootDriverHeaderSeg,0)); - break; - case 0x01 :{/* Get current position */ - TMSF pos; - mscdex->GetCurrentPos(drive_unit,pos); - Bit8u addr_mode = mem_readb(buffer+1); - if (addr_mode==0) { // HSG - Bit32u frames=MSF_TO_FRAMES(pos.min, pos.sec, pos.fr); - if (frames<150) MSCDEX_LOG("MSCDEX: Get position: invalid position %d:%d:%d", pos.min, pos.sec, pos.fr); - else frames-=150; - mem_writed(buffer+2,frames); - } else if (addr_mode==1) { // Red book - mem_writeb(buffer+2,pos.fr); - mem_writeb(buffer+3,pos.sec); - mem_writeb(buffer+4,pos.min); - mem_writeb(buffer+5,0x00); - } else { - MSCDEX_LOG("MSCDEX: Get position: invalid address mode %x",addr_mode); - return 0x03; // invalid function - } - }break; - case 0x06 : /* Get Device status */ - mem_writed(buffer+1,mscdex->GetDeviceStatus(drive_unit)); - break; - case 0x07 : /* Get sector size */ - if (mem_readb(buffer+1)==0) mem_writed(buffer+2,2048); - else if (mem_readb(buffer+1)==1) mem_writed(buffer+2,2352); - else return 0x03; // invalid function - break; - case 0x08 : /* Get size of current volume */ - mem_writed(buffer+1,mscdex->GetVolumeSize(drive_unit)); - break; - case 0x09 : /* Media change ? */ - Bit8u status; - if (!mscdex->GetMediaStatus(drive_unit,status)) { - status = 0; // state unknown - } - mem_writeb(buffer+1,status); - break; - case 0x0A : /* Get Audio Disk info */ - Bit8u tr1,tr2; TMSF leadOut; - if (!mscdex->GetCDInfo(drive_unit,tr1,tr2,leadOut)) return 0x05; - mem_writeb(buffer+1,tr1); - mem_writeb(buffer+2,tr2); - mem_writeb(buffer+3,leadOut.fr); - mem_writeb(buffer+4,leadOut.sec); - mem_writeb(buffer+5,leadOut.min); - mem_writeb(buffer+6,0x00); - break; - case 0x0B :{/* Audio Track Info */ - Bit8u attr; TMSF start; - Bit8u track = mem_readb(buffer+1); - mscdex->GetTrackInfo(drive_unit,track,attr,start); - mem_writeb(buffer+2,start.fr); - mem_writeb(buffer+3,start.sec); - mem_writeb(buffer+4,start.min); - mem_writeb(buffer+5,0x00); - mem_writeb(buffer+6,attr); - break; }; - case 0x0C :{/* Get Audio Sub Channel data */ - Bit8u attr,track,index; - TMSF abs,rel; - mscdex->GetSubChannelData(drive_unit,attr,track,index,rel,abs); - mem_writeb(buffer+1,attr); - mem_writeb(buffer+2,track); - mem_writeb(buffer+3,index); - mem_writeb(buffer+4,rel.min); - mem_writeb(buffer+5,rel.sec); - mem_writeb(buffer+6,rel.fr); - mem_writeb(buffer+7,0x00); - mem_writeb(buffer+8,abs.min); - mem_writeb(buffer+9,abs.sec); - mem_writeb(buffer+10,abs.fr); - break; - }; - case 0x0E :{ /* Get UPC */ - Bit8u attr; char upc[8]; - mscdex->GetUPC(drive_unit,attr,&upc[0]); - mem_writeb(buffer+1,attr); - for (int i=0; i<7; i++) mem_writeb(buffer+2+i,upc[i]); - mem_writeb(buffer+9,0x00); - break; - }; - case 0x0F :{ /* Get Audio Status */ - bool playing,pause; - TMSF resStart,resEnd; - mscdex->GetAudioStatus(drive_unit,playing,pause,resStart,resEnd); - mem_writeb(buffer+1,pause); - mem_writeb(buffer+3,resStart.min); - mem_writeb(buffer+4,resStart.sec); - mem_writeb(buffer+5,resStart.fr); - mem_writeb(buffer+6,0x00); - mem_writeb(buffer+7,resEnd.min); - mem_writeb(buffer+8,resEnd.sec); - mem_writeb(buffer+9,resEnd.fr); - mem_writeb(buffer+10,0x00); - break; - }; - default : LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Unsupported IOCTL INPUT Subfunction %02X",ioctl_fct); - return 0x03; // invalid function - } - return 0x00; // success -} - -static Bit16u MSCDEX_IOCTL_Optput(PhysPt buffer,Bit8u drive_unit) { - Bitu ioctl_fct = mem_readb(buffer); -// MSCDEX_LOG("MSCDEX: IOCTL OUTPUT Subfunction %02X",ioctl_fct); - switch (ioctl_fct) { - case 0x00 : // Unload /eject media - if (!mscdex->LoadUnloadMedia(drive_unit,true)) return 0x02; - break; - case 0x03: //Audio Channel control - MSCDEX_LOG("MSCDEX: Audio Channel Control used. Not handled. Faking succes!"); - case 0x01 : // (un)Lock door - // do nothing -> report as success - break; - case 0x02 : // Reset Drive - LOG(LOG_MISC,LOG_WARN)("cdromDrive reset"); - if (!mscdex->StopAudio(drive_unit)) return 0x02; - break; - case 0x05 : // load media - if (!mscdex->LoadUnloadMedia(drive_unit,false)) return 0x02; - default : LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Unsupported IOCTL OUTPUT Subfunction %02X",ioctl_fct); - return 0x03; // invalid function - } - return 0x00; // success -} - -static Bitu MSCDEX_Strategy_Handler(void) { - curReqheaderPtr = PhysMake(SegValue(es),reg_bx); -// MSCDEX_LOG("MSCDEX: Device Strategy Routine called, request header at %x",curReqheaderPtr); - return CBRET_NONE; -} - -static Bitu MSCDEX_Interrupt_Handler(void) { - if (curReqheaderPtr==0) { - MSCDEX_LOG("MSCDEX: invalid call to interrupt handler"); - return CBRET_NONE; - } - Bit8u subUnit = mem_readb(curReqheaderPtr+1); - Bit8u funcNr = mem_readb(curReqheaderPtr+2); - Bit16u errcode = 0; - PhysPt buffer = 0; - - MSCDEX_LOG("MSCDEX: Driver Function %02X",funcNr); - - if ((funcNr==0x03) || (funcNr==0x0c) || (funcNr==0x80) || (funcNr==0x82)) { - buffer = PhysMake(mem_readw(curReqheaderPtr+0x10),mem_readw(curReqheaderPtr+0x0E)); - } - - switch (funcNr) { - case 0x03 : { /* IOCTL INPUT */ - Bit16u error=MSCDEX_IOCTL_Input(buffer,subUnit); - if (error) errcode = error; - break; - }; - case 0x0C : { /* IOCTL OUTPUT */ - Bit16u error=MSCDEX_IOCTL_Optput(buffer,subUnit); - if (error) errcode = error; - break; - }; - case 0x0D : // device open - case 0x0E : // device close - dont care :) - break; - case 0x80 : // Read long - case 0x82 : { // Read long prefetch -> both the same here :) - Bit32u start = mem_readd(curReqheaderPtr+0x14); - Bit16u len = mem_readw(curReqheaderPtr+0x12); - bool raw = (mem_readb(curReqheaderPtr+0x18)==1); - if (mem_readb(curReqheaderPtr+0x0D)==0x00) // HSG - mscdex->ReadSectors(subUnit,raw,start,len,buffer); - else - mscdex->ReadSectorsMSF(subUnit,raw,start,len,buffer); - break; - }; - case 0x83 : // Seek - dont care :) - break; - case 0x84 : { /* Play Audio Sectors */ - Bit32u start = mem_readd(curReqheaderPtr+0x0E); - Bit32u len = mem_readd(curReqheaderPtr+0x12); - if (mem_readb(curReqheaderPtr+0x0D)==0x00) // HSG - mscdex->PlayAudioSector(subUnit,start,len); - else // RED BOOK - mscdex->PlayAudioMSF(subUnit,start,len); - break; - }; - case 0x85 : /* Stop Audio */ - mscdex->StopAudio(subUnit); - break; - case 0x88 : /* Resume Audio */ - mscdex->ResumeAudio(subUnit); - break; - default : LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Unsupported Driver Request %02X",funcNr); - break; - - }; - - // Set Statusword - mem_writew(curReqheaderPtr+3,mscdex->GetStatusWord(subUnit,errcode)); - MSCDEX_LOG("MSCDEX: Status : %04X",mem_readw(curReqheaderPtr+3)); - return CBRET_NONE; -} - -static bool MSCDEX_Handler(void) { - if(reg_ah == 0x11) { - if(reg_al == 0x00) { - PhysPt check = PhysMake(SegValue(ss),reg_sp); - if(mem_readw(check+6) == 0xDADA) { - //MSCDEX sets word on stack to ADAD if it DADA on entry. - mem_writew(check+6,0xADAD); - } - reg_al = 0xff; - return true; - } else { - LOG(LOG_MISC,LOG_ERROR)("NETWORK REDIRECTOR USED!!!"); - reg_ax = 0x49;//NETWERK SOFTWARE NOT INSTALLED - CALLBACK_SCF(true); - return true; - } - } - - if (reg_ah!=0x15) return false; // not handled here, continue chain - - PhysPt data = PhysMake(SegValue(es),reg_bx); - MSCDEX_LOG("MSCDEX: INT 2F %04X BX= %04X CX=%04X",reg_ax,reg_bx,reg_cx); - switch (reg_ax) { - - case 0x1500: /* Install check */ - reg_bx = mscdex->GetNumDrives(); - if (reg_bx>0) reg_cx = mscdex->GetFirstDrive(); - reg_al = 0xff; - return true; - case 0x1501: /* Get cdrom driver info */ - mscdex->GetDriverInfo(data); - return true; - case 0x1502: /* Get Copyright filename */ - if (mscdex->GetCopyrightName(reg_cx,data)) { - CALLBACK_SCF(false); - } else { - reg_al = MSCDEX_ERROR_UNKNOWN_DRIVE; - CALLBACK_SCF(true); - }; - return true; - case 0x1503: /* Get Abstract filename */ - if (mscdex->GetAbstractName(reg_cx,data)) { - CALLBACK_SCF(false); - } else { - reg_al = MSCDEX_ERROR_UNKNOWN_DRIVE; - CALLBACK_SCF(true); - }; - return true; - case 0x1504: /* Get Documentation filename */ - if (mscdex->GetDocumentationName(reg_cx,data)) { - CALLBACK_SCF(false); - } else { - reg_al = MSCDEX_ERROR_UNKNOWN_DRIVE; - CALLBACK_SCF(true); - }; - return true; - case 0x1505: { // read vtoc - Bit16u error = 0; - if (mscdex->ReadVTOC(reg_cx,reg_dx,data,error)) { - CALLBACK_SCF(false); - } else { - reg_ax = error; - CALLBACK_SCF(true); - }; - }; - return true; - case 0x1508: { // read sectors - Bit32u sector = (reg_si<<16)+reg_di; - if (mscdex->ReadSectors(reg_cx,sector,reg_dx,data)) { - CALLBACK_SCF(false); - } else { - reg_al = MSCDEX_ERROR_UNKNOWN_DRIVE; - CALLBACK_SCF(true); - }; - return true; - }; - case 0x1509: // write sectors - not supported - reg_al = MSCDEX_ERROR_DRIVE_NOT_READY; - CALLBACK_SCF(true); - return true; - case 0x150B: /* Valid CDROM drive ? */ - reg_ax = mscdex->IsValidDrive(reg_cx); - reg_bx = 0xADAD; - return true; - case 0x150C: /* Get MSCDEX Version */ - reg_bx = mscdex->GetVersion(); - return true; - case 0x150D: /* Get drives */ - mscdex->GetDrives(data); - return true; - case 0x150F: { // Get directory entry - Bit16u error; - bool success = mscdex->GetDirectoryEntry(reg_cl,reg_ch&1,data,PhysMake(reg_si,reg_di),error); - reg_ax = error; - CALLBACK_SCF(!success); - }; return true; - case 0x1510: /* Device driver request */ - if (mscdex->SendDriverRequest(reg_cx,data)) { - CALLBACK_SCF(false); - } else { - reg_ax = 0x0f; // invalid drive - CALLBACK_SCF(true); - } - return true; - }; - LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Unknwon call : %04X",reg_ax); - return true; -} - -class device_MSCDEX : public DOS_Device { -public: - device_MSCDEX() { SetName("MSCD001"); } - bool Read (Bit8u * /*data*/,Bit16u * /*size*/) { return false;} - bool Write(Bit8u * /*data*/,Bit16u * /*size*/) { - LOG(LOG_ALL,LOG_NORMAL)("Write to mscdex device"); - return false; - } - bool Seek(Bit32u * /*pos*/,Bit32u /*type*/){return false;} - bool Close(){return false;} - Bit16u GetInformation(void){return 0xc880;} - bool ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode); - bool WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode); -private: -// Bit8u cache; -}; - -bool device_MSCDEX::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { - if (MSCDEX_IOCTL_Input(bufptr,0)==0) { - *retcode=size; - return true; - } - return false; -} - -bool device_MSCDEX::WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { - if (MSCDEX_IOCTL_Optput(bufptr,0)==0) { - *retcode=size; - return true; - } - return false; -} - -int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit) -{ - int result = mscdex->AddDrive(driveLetter-'A',(char*)physicalPath,subUnit); - return result; -} - -int MSCDEX_RemoveDrive(char driveLetter) -{ - if(!mscdex) return 0; - return mscdex->RemoveDrive(driveLetter-'A'); -} - -bool MSCDEX_HasDrive(char driveLetter) -{ - return mscdex->HasDrive(driveLetter-'A'); -} - -void MSCDEX_ReplaceDrive(CDROM_Interface* cdrom, Bit8u subUnit) -{ - mscdex->ReplaceDrive(cdrom, subUnit); -} - -bool MSCDEX_GetVolumeName(Bit8u subUnit, char* name) -{ - return mscdex->GetVolumeName(subUnit,name); -} - -bool MSCDEX_HasMediaChanged(Bit8u subUnit) -{ - static TMSF leadOut[MSCDEX_MAX_DRIVES]; - - TMSF leadnew; - Bit8u tr1,tr2; - if (mscdex->GetCDInfo(subUnit,tr1,tr2,leadnew)) { - bool changed = (leadOut[subUnit].min!=leadnew.min) || (leadOut[subUnit].sec!=leadnew.sec) || (leadOut[subUnit].fr!=leadnew.fr); - if (changed) { - leadOut[subUnit].min = leadnew.min; - leadOut[subUnit].sec = leadnew.sec; - leadOut[subUnit].fr = leadnew.fr; - mscdex->InitNewMedia(subUnit); - } - return changed; - }; - if (subUnitAddDestroyFunction(&MSCDEX_ShutDown); - /* Register the mscdex device */ - DOS_Device * newdev = new device_MSCDEX(); - DOS_AddDevice(newdev); - curReqheaderPtr = 0; - /* Add Multiplexer */ - DOS_AddMultiplexHandler(MSCDEX_Handler); - /* Create MSCDEX */ - mscdex = new CMscdex; -} diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index a2d0ae7..f1e3c94 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -1,1544 +1,210 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos_programs.cpp,v 1.93 2009/04/16 12:28:30 qbix79 Exp $ */ - -#include "dosbox.h" -#include -#include -#include -#include -#include -#include "programs.h" -#include "support.h" -#include "drives.h" -#include "cross.h" -#include "regs.h" -#include "callback.h" -#include "cdrom.h" -#include "dos_system.h" -#include "dos_inc.h" -#include "bios.h" -#include "setup.h" -#include "control.h" - - -#if defined(OS2) -#define INCL DOSFILEMGR -#define INCL_DOSERRORS -#include "os2.h" -#endif - -#if C_DEBUG -Bitu DEBUG_EnableDebugger(void); -#endif - -void MSCDEX_SetCDInterface(int intNr, int forceCD); - - -class MOUNT : public Program { -public: - void Run(void) - { - DOS_Drive * newdrive;char drive; - std::string label; - std::string umount; - - //Hack To allow long commandlines - ChangeToLongCmd(); - /* Parse the command line */ - /* if the command line is empty show current mounts */ - if (!cmd->GetCount()) { - WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_1")); - for (int d=0;dGetInfo()); - } - } - return; - } - - /* In secure mode don't allow people to change mount points. - * Neither mount nor unmount */ - if(control->SecureMode()) { - WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); - return; - } - - /* Check for unmounting */ - if (cmd->FindString("-u",umount,false)) { - umount[0] = toupper(umount[0]); - int i_drive = umount[0]-'A'; - if(i_drive < DOS_DRIVES && i_drive >= 0 && Drives[i_drive]) { - switch (DriveManager::UnmountDrive(i_drive)) { - case 0: - Drives[i_drive] = 0; - if(i_drive == DOS_GetDefaultDrive()) - DOS_SetDrive(toupper('Z') - 'A'); - WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_SUCCES"),umount[0]); - break; - case 1: - WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_NO_VIRTUAL")); - break; - case 2: - WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); - break; - } - } else { - WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_NOT_MOUNTED"),umount[0]); - } - return; - } - - // Show list of cdroms - if (cmd->FindExist("-cd",false)) { - int num = SDL_CDNumDrives(); - WriteOut(MSG_Get("PROGRAM_MOUNT_CDROMS_FOUND"),num); - for (int i=0; iFindString("-t",type,true); - bool iscdrom = (type =="cdrom"); //Used for mscdex bug cdrom label name emulation - if (type=="floppy" || type=="dir" || type=="cdrom") { - Bit16u sizes[4]; - Bit8u mediaid; - std::string str_size; - if (type=="floppy") { - str_size="512,1,2880,2880";/* All space free */ - mediaid=0xF0; /* Floppy 1.44 media */ - } else if (type=="dir") { - // 512*127*16383==~1GB total size - // 512*127*4031==~250MB total free size - str_size="512,127,16383,4031"; - mediaid=0xF8; /* Hard Disk */ - } else if (type=="cdrom") { - str_size="2048,1,65535,0"; - mediaid=0xF8; /* Hard Disk */ - } else { - WriteOut(MSG_Get("PROGAM_MOUNT_ILL_TYPE"),type.c_str()); - return; - } - /* Parse the free space in mb's (kb's for floppies) */ - std::string mb_size; - if(cmd->FindString("-freesize",mb_size,true)) { - char teststr[1024]; - Bit16u sizemb = static_cast(atoi(mb_size.c_str())); - if (type=="floppy") { - sprintf(teststr,"512,1,2880,%d",sizemb*1024/(512*1)); - } else { - sprintf(teststr,"512,127,16513,%d",sizemb*1024*1024/(512*127)); - } - str_size=teststr; - } - - cmd->FindString("-size",str_size,true); - char number[20];const char * scan=str_size.c_str(); - Bitu index=0;Bitu count=0; - /* Parse the str_size string */ - while (*scan) { - if (*scan==',') { - number[index]=0;sizes[count++]=atoi(number); - index=0; - } else number[index++]=*scan; - scan++; - } - number[index]=0;sizes[count++]=atoi(number); - - // get the drive letter - cmd->FindCommand(1,temp_line); - if ((temp_line.size() > 2) || ((temp_line.size()>1) && (temp_line[1]!=':'))) goto showusage; - drive=toupper(temp_line[0]); - if (!isalpha(drive)) goto showusage; - - if (!cmd->FindCommand(2,temp_line)) goto showusage; - if (!temp_line.size()) goto showusage; - struct stat test; - //Win32 : strip tailing backslashes - //os2: some special drive check - //rest: substiture ~ for home - bool failed = false; -#if defined (WIN32) || defined(OS2) - /* Removing trailing backslash if not root dir so stat will succeed */ - if(temp_line.size() > 3 && temp_line[temp_line.size()-1]=='\\') temp_line.erase(temp_line.size()-1,1); - if (stat(temp_line.c_str(),&test)) { -#endif -#if defined(WIN32) -// Nothing to do here. -#elif defined (OS2) - if (temp_line.size() <= 2) // Seems to be a drive. - { - failed = true; - HFILE cdrom_fd = 0; - ULONG ulAction = 0; - - APIRET rc = DosOpen((unsigned char*)temp_line.c_str(), &cdrom_fd, &ulAction, 0L, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS, - OPEN_FLAGS_DASD | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, 0L); - DosClose(cdrom_fd); - if (rc != NO_ERROR && rc != ERROR_NOT_READY) - { - failed = true; - } else { - failed = false; - } - } - } - if (failed) { -#else - if (stat(temp_line.c_str(),&test)) { - failed = true; - Cross::ResolveHomedir(temp_line); - //Try again after resolving ~ - if(!stat(temp_line.c_str(),&test)) failed = false; - } - if(failed) { -#endif - WriteOut(MSG_Get("PROGRAM_MOUNT_ERROR_1"),temp_line.c_str()); - return; - } - /* Not a switch so a normal directory/file */ - if (!(test.st_mode & S_IFDIR)) { -#ifdef OS2 - HFILE cdrom_fd = 0; - ULONG ulAction = 0; - - APIRET rc = DosOpen((unsigned char*)temp_line.c_str(), &cdrom_fd, &ulAction, 0L, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS, - OPEN_FLAGS_DASD | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, 0L); - DosClose(cdrom_fd); - if (rc != NO_ERROR && rc != ERROR_NOT_READY) { - WriteOut(MSG_Get("PROGRAM_MOUNT_ERROR_2"),temp_line.c_str()); - return; - } -#else - WriteOut(MSG_Get("PROGRAM_MOUNT_ERROR_2"),temp_line.c_str()); - return; -#endif - } - - if (temp_line[temp_line.size()-1]!=CROSS_FILESPLIT) temp_line+=CROSS_FILESPLIT; - Bit8u bit8size=(Bit8u) sizes[1]; - if (type=="cdrom") { - int num = -1; - cmd->FindInt("-usecd",num,true); - int error; - if (cmd->FindExist("-aspi",false)) { - MSCDEX_SetCDInterface(CDROM_USE_ASPI, num); - } else if (cmd->FindExist("-ioctl_dio",false)) { - MSCDEX_SetCDInterface(CDROM_USE_IOCTL_DIO, num); - } else if (cmd->FindExist("-ioctl_dx",false)) { - MSCDEX_SetCDInterface(CDROM_USE_IOCTL_DX, num); -#if defined (WIN32) - } else if (cmd->FindExist("-ioctl_mci",false)) { - MSCDEX_SetCDInterface(CDROM_USE_IOCTL_MCI, num); -#endif - } else if (cmd->FindExist("-noioctl",false)) { - MSCDEX_SetCDInterface(CDROM_USE_SDL, num); - } else { -#if defined (WIN32) - // Check OS - OSVERSIONINFO osi; - osi.dwOSVersionInfoSize = sizeof(osi); - GetVersionEx(&osi); - if ((osi.dwPlatformId==VER_PLATFORM_WIN32_NT) && (osi.dwMajorVersion>5)) { - // Vista/above - MSCDEX_SetCDInterface(CDROM_USE_IOCTL_DX, num); - } else { - MSCDEX_SetCDInterface(CDROM_USE_IOCTL_DIO, num); - } -#else - MSCDEX_SetCDInterface(CDROM_USE_IOCTL_DIO, num); -#endif - } - newdrive = new cdromDrive(drive,temp_line.c_str(),sizes[0],bit8size,sizes[2],0,mediaid,error); - // Check Mscdex, if it worked out... - switch (error) { - case 0 : WriteOut(MSG_Get("MSCDEX_SUCCESS")); break; - case 1 : WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); break; - case 2 : WriteOut(MSG_Get("MSCDEX_ERROR_NOT_SUPPORTED")); break; - case 3 : WriteOut(MSG_Get("MSCDEX_ERROR_PATH")); break; - case 4 : WriteOut(MSG_Get("MSCDEX_TOO_MANY_DRIVES")); break; - case 5 : WriteOut(MSG_Get("MSCDEX_LIMITED_SUPPORT")); break; - default : WriteOut(MSG_Get("MSCDEX_UNKNOWN_ERROR")); break; - }; - if (error && error!=5) { - delete newdrive; - return; - } - } else { - /* Give a warning when mount c:\ or the / */ -#if defined (WIN32) || defined(OS2) - if( (temp_line == "c:\\") || (temp_line == "C:\\") || - (temp_line == "c:/") || (temp_line == "C:/") ) - WriteOut(MSG_Get("PROGRAM_MOUNT_WARNING_WIN")); -#else - if(temp_line == "/") WriteOut(MSG_Get("PROGRAM_MOUNT_WARNING_OTHER")); -#endif - newdrive=new localDrive(temp_line.c_str(),sizes[0],bit8size,sizes[2],sizes[3],mediaid); - } - } else { - WriteOut(MSG_Get("PROGRAM_MOUNT_ILL_TYPE"),type.c_str()); - return; - } - if (Drives[drive-'A']) { - WriteOut(MSG_Get("PROGRAM_MOUNT_ALREADY_MOUNTED"),drive,Drives[drive-'A']->GetInfo()); - if (newdrive) delete newdrive; - return; - } - if (!newdrive) E_Exit("DOS:Can't create drive"); - Drives[drive-'A']=newdrive; - /* Set the correct media byte in the table */ - mem_writeb(Real2Phys(dos.tables.mediaid)+(drive-'A')*2,newdrive->GetMediaByte()); - WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"),drive,newdrive->GetInfo()); - /* check if volume label is given and don't allow it to updated in the future */ - if (cmd->FindString("-label",label,true)) newdrive->dirCache.SetLabel(label.c_str(),iscdrom,false); - /* For hard drives set the label to DRIVELETTER_Drive. - * For floppy drives set the label to DRIVELETTER_Floppy. - * This way every drive except cdroms should get a label.*/ - else if(type == "dir") { - label = drive; label += "_DRIVE"; - newdrive->dirCache.SetLabel(label.c_str(),iscdrom,true); - } else if(type == "floppy") { - label = drive; label += "_FLOPPY"; - newdrive->dirCache.SetLabel(label.c_str(),iscdrom,true); - } - return; -showusage: - WriteOut(MSG_Get("PROGRAM_MOUNT_USAGE")); - return; - } -}; - -static void MOUNT_ProgramStart(Program * * make) { - *make=new MOUNT; -} - -class MEM : public Program { -public: - void Run(void) { - /* Show conventional Memory */ - WriteOut("\n"); - - Bit16u umb_start=dos_infoblock.GetStartOfUMBChain(); - Bit8u umb_flag=dos_infoblock.GetUMBChainState(); - Bit8u old_memstrat=DOS_GetMemAllocStrategy()&0xff; - if (umb_start!=0xffff) { - if ((umb_flag&1)==1) DOS_LinkUMBsToMemChain(0); - DOS_SetMemAllocStrategy(0); - } - - Bit16u seg,blocks;blocks=0xffff; - DOS_AllocateMemory(&seg,&blocks); - if ((machine==MCH_PCJR) && (real_readb(0x2000,0)==0x5a) && (real_readw(0x2000,1)==0) && (real_readw(0x2000,3)==0x7ffe)) { - WriteOut(MSG_Get("PROGRAM_MEM_CONVEN"),0x7ffe*16/1024); - } else WriteOut(MSG_Get("PROGRAM_MEM_CONVEN"),blocks*16/1024); - - if (umb_start!=0xffff) { - DOS_LinkUMBsToMemChain(1); - DOS_SetMemAllocStrategy(0x40); // search in UMBs only - - Bit16u largest_block=0,total_blocks=0,block_count=0; - for (;; block_count++) { - blocks=0xffff; - DOS_AllocateMemory(&seg,&blocks); - if (blocks==0) break; - total_blocks+=blocks; - if (blocks>largest_block) largest_block=blocks; - DOS_AllocateMemory(&seg,&blocks); - } - - Bit8u current_umb_flag=dos_infoblock.GetUMBChainState(); - if ((current_umb_flag&1)!=(umb_flag&1)) DOS_LinkUMBsToMemChain(umb_flag); - DOS_SetMemAllocStrategy(old_memstrat); // restore strategy - - if (block_count>0) WriteOut(MSG_Get("PROGRAM_MEM_UPPER"),total_blocks*16/1024,block_count,largest_block*16/1024); - } - - /* Test for and show free XMS */ - reg_ax=0x4300;CALLBACK_RunRealInt(0x2f); - if (reg_al==0x80) { - reg_ax=0x4310;CALLBACK_RunRealInt(0x2f); - Bit16u xms_seg=SegValue(es);Bit16u xms_off=reg_bx; - reg_ah=8; - CALLBACK_RunRealFar(xms_seg,xms_off); - if (!reg_bl) { - WriteOut(MSG_Get("PROGRAM_MEM_EXTEND"),reg_dx); - } - } - /* Test for and show free EMS */ - Bit16u handle; - char emm[9] = { 'E','M','M','X','X','X','X','0',0 }; - if (DOS_OpenFile(emm,0,&handle)) { - DOS_CloseFile(handle); - reg_ah=0x42; - CALLBACK_RunRealInt(0x67); - WriteOut(MSG_Get("PROGRAM_MEM_EXPAND"),reg_bx*16); - } - } -}; - - -static void MEM_ProgramStart(Program * * make) { - *make=new MEM; -} - -extern Bit32u floppytype; - - -class BOOT : public Program { -private: - - FILE *getFSFile_mounted(char const* filename, Bit32u *ksize, Bit32u *bsize, Bit8u *error) { - //if return NULL then put in error the errormessage code if an error was requested - bool tryload = (*error)?true:false; - *error = 0; - Bit8u drive; - FILE *tmpfile; - char fullname[DOS_PATHLENGTH]; - - localDrive* ldp=0; - if (!DOS_MakeName(const_cast(filename),fullname,&drive)) return NULL; - - try { - ldp=dynamic_cast(Drives[drive]); - if(!ldp) return NULL; - - tmpfile = ldp->GetSystemFilePtr(fullname, "rb"); - if(tmpfile == NULL) { - if (!tryload) *error=1; - return NULL; - } - - // get file size - fseek(tmpfile,0L, SEEK_END); - *ksize = (ftell(tmpfile) / 1024); - *bsize = ftell(tmpfile); - fclose(tmpfile); - - tmpfile = ldp->GetSystemFilePtr(fullname, "rb+"); - if(tmpfile == NULL) { -// if (!tryload) *error=2; -// return NULL; - WriteOut(MSG_Get("PROGRAM_BOOT_WRITE_PROTECTED")); - tmpfile = ldp->GetSystemFilePtr(fullname, "rb"); - if(tmpfile == NULL) { - if (!tryload) *error=1; - return NULL; - } - } - - return tmpfile; - } - catch(...) { - return NULL; - } - } - - FILE *getFSFile(char const * filename, Bit32u *ksize, Bit32u *bsize,bool tryload=false) { - Bit8u error = tryload?1:0; - FILE* tmpfile = getFSFile_mounted(filename,ksize,bsize,&error); - if(tmpfile) return tmpfile; - //File not found on mounted filesystem. Try regular filesystem - std::string filename_s(filename); - Cross::ResolveHomedir(filename_s); - tmpfile = fopen(filename_s.c_str(),"rb+"); - if(!tmpfile) { - if( (tmpfile = fopen(filename_s.c_str(),"rb")) ) { - //File exists; So can't be opened in correct mode => error 2 -// fclose(tmpfile); -// if(tryload) error = 2; - WriteOut(MSG_Get("PROGRAM_BOOT_WRITE_PROTECTED")); - fseek(tmpfile,0L, SEEK_END); - *ksize = (ftell(tmpfile) / 1024); - *bsize = ftell(tmpfile); - return tmpfile; - } - // Give the delayed errormessages from the mounted variant (or from above) - if(error == 1) WriteOut(MSG_Get("PROGRAM_BOOT_NOT_EXIST")); - if(error == 2) WriteOut(MSG_Get("PROGRAM_BOOT_NOT_OPEN")); - return NULL; - } - fseek(tmpfile,0L, SEEK_END); - *ksize = (ftell(tmpfile) / 1024); - *bsize = ftell(tmpfile); - return tmpfile; - } - - void printError(void) { - WriteOut(MSG_Get("PROGRAM_BOOT_PRINT_ERROR")); - } - - void disable_umb_ems_xms(void) { - Section* dos_sec = control->GetSection("dos"); - dos_sec->ExecuteDestroy(false); - char test[20]; - strcpy(test,"umb=false"); - dos_sec->HandleInputline(test); - strcpy(test,"xms=false"); - dos_sec->HandleInputline(test); - strcpy(test,"ems=false"); - dos_sec->HandleInputline(test); - dos_sec->ExecuteInit(false); - } - -public: - - void Run(void) { - //Hack To allow long commandlines - ChangeToLongCmd(); - /* In secure mode don't allow people to boot stuff. - * They might try to corrupt the data on it */ - if(control->SecureMode()) { - WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); - return; - } - - FILE *usefile_1=NULL; - FILE *usefile_2=NULL; - Bitu i=0; - Bit32u floppysize; - Bit32u rombytesize_1=0; - Bit32u rombytesize_2=0; - Bit8u drive = 'A'; - std::string cart_cmd=""; - - if(!cmd->GetCount()) { - printError(); - return; - } - while(iGetCount()) { - if(cmd->FindCommand(i+1, temp_line)) { - if((temp_line == "-l") || (temp_line == "-L")) { - /* Specifying drive... next argument then is the drive */ - i++; - if(cmd->FindCommand(i+1, temp_line)) { - drive=toupper(temp_line[0]); - if ((drive != 'A') && (drive != 'C') && (drive != 'D')) { - printError(); - return; - } - - } else { - printError(); - return; - } - i++; - continue; - } - - if((temp_line == "-e") || (temp_line == "-E")) { - /* Command mode for PCJr cartridges */ - i++; - if(cmd->FindCommand(i + 1, temp_line)) { - for(size_t ct = 0;ct < temp_line.size();ct++) temp_line[ct] = toupper(temp_line[ct]); - cart_cmd = temp_line; - } else { - printError(); - return; - } - i++; - continue; - } - - WriteOut(MSG_Get("PROGRAM_BOOT_IMAGE_OPEN"), temp_line.c_str()); - Bit32u rombytesize; - FILE *usefile = getFSFile(temp_line.c_str(), &floppysize, &rombytesize); - if(usefile != NULL) { - if(diskSwap[i] != NULL) delete diskSwap[i]; - diskSwap[i] = new imageDisk(usefile, (Bit8u *)temp_line.c_str(), floppysize, false); - if (usefile_1==NULL) { - usefile_1=usefile; - rombytesize_1=rombytesize; - } else { - usefile_2=usefile; - rombytesize_2=rombytesize; - } - } else { - WriteOut(MSG_Get("PROGRAM_BOOT_IMAGE_NOT_OPEN"), temp_line.c_str()); - return; - } - - } - i++; - } - - swapPosition = 0; - - swapInDisks(); - - if(imageDiskList[drive-65]==NULL) { - WriteOut(MSG_Get("PROGRAM_BOOT_UNABLE"), drive); - return; - } - - bootSector bootarea; - imageDiskList[drive-65]->Read_Sector(0,0,1,(Bit8u *)&bootarea); - if ((bootarea.rawdata[0]==0x50) && (bootarea.rawdata[1]==0x43) && (bootarea.rawdata[2]==0x6a) && (bootarea.rawdata[3]==0x72)) { - if (machine!=MCH_PCJR) WriteOut(MSG_Get("PROGRAM_BOOT_CART_WO_PCJR")); - else { - Bit8u rombuf[65536]; - Bits cfound_at=-1; - if (cart_cmd!="") { - /* read cartridge data into buffer */ - fseek(usefile_1,0x200L, SEEK_SET); - fread(rombuf, 1, rombytesize_1-0x200, usefile_1); - - char cmdlist[1024]; - cmdlist[0]=0; - Bitu ct=6; - Bits clen=rombuf[ct]; - char buf[257]; - if (cart_cmd=="?") { - while (clen!=0) { - strncpy(buf,(char*)&rombuf[ct+1],clen); - buf[clen]=0; - upcase(buf); - strcat(cmdlist," "); - strcat(cmdlist,buf); - ct+=1+clen+3; - if (ct>sizeof(cmdlist)) break; - clen=rombuf[ct]; - } - if (ct>6) { - WriteOut(MSG_Get("PROGRAM_BOOT_CART_LIST_CMDS"),cmdlist); - } else { - WriteOut(MSG_Get("PROGRAM_BOOT_CART_NO_CMDS")); - } - for(Bitu dct=0;dctsizeof(cmdlist)) break; - clen=rombuf[ct]; - } - if (cfound_at<=0) { - if (ct>6) { - WriteOut(MSG_Get("PROGRAM_BOOT_CART_LIST_CMDS"),cmdlist); - } else { - WriteOut(MSG_Get("PROGRAM_BOOT_CART_NO_CMDS")); - } - for(Bitu dct=0;dct0) { - /* run cartridge setup */ - SegSet16(ds,dos.psp()); - SegSet16(es,dos.psp()); - CALLBACK_RunRealFar(romseg,cfound_at); - } - } - } - } else { - disable_umb_ems_xms(); - void RemoveEMSPageFrame(void); - RemoveEMSPageFrame(); - WriteOut(MSG_Get("PROGRAM_BOOT_BOOT"), drive); - for(i=0;i<512;i++) real_writeb(0, 0x7c00 + i, bootarea.rawdata[i]); - - /* revector some dos-allocated interrupts */ - real_writed(0,0x01*4,0xf000ff53); - real_writed(0,0x03*4,0xf000ff53); - - SegSet16(cs, 0); - reg_ip = 0x7c00; - SegSet16(ds, 0); - SegSet16(es, 0); - /* set up stack at a safe place */ - SegSet16(ss, 0x7000); - reg_esp = 0x400; - reg_esi = 0; - reg_ecx = 1; - reg_ebp = 0; - reg_eax = 0; - reg_edx = 0; //Head 0 drive 0 - reg_ebx= 0x7c00; //Real code probably uses bx to load the image - } - } -}; - -static void BOOT_ProgramStart(Program * * make) { - *make=new BOOT; -} - - -#if C_DEBUG -class LDGFXROM : public Program { -public: - void Run(void) { - if (!(cmd->FindCommand(1, temp_line))) return; - - Bit8u drive; - char fullname[DOS_PATHLENGTH]; - - localDrive* ldp=0; - if (!DOS_MakeName((char *)temp_line.c_str(),fullname,&drive)) return; - - try { - ldp=dynamic_cast(Drives[drive]); - if(!ldp) return; - - FILE *tmpfile = ldp->GetSystemFilePtr(fullname, "rb"); - if(tmpfile == NULL) { - LOG_MSG("BIOS file not accessible."); - return; - } - fseek(tmpfile, 0L, SEEK_END); - if (ftell(tmpfile)>0x10000) { - LOG_MSG("BIOS file too large."); - return; - } - fseek(tmpfile, 0L, SEEK_SET); - - PhysPt rom_base=PhysMake(0xc000,0); - - Bit8u vga_buffer[0x10000]; - Bitu data_written=0; - Bitu data_read=fread(vga_buffer, 1, 0x10000, tmpfile); - for (Bitu ct=0; ctFindCommand(commandNr,temp_line)) { - if (temp_line[0]=='-') { - char ch = temp_line[1]; - if ((*upcase(&ch)=='D') || (*upcase(&ch)=='F')) { - // Deallocate all - DOS_FreeProcessMemory(0x40); - WriteOut(MSG_Get("PROGRAM_LOADFIX_DEALLOCALL"),kb); - return; - } else { - // Set mem amount to allocate - kb = atoi(temp_line.c_str()+1); - if (kb==0) kb=64; - commandNr++; - } - } - } - // Allocate Memory - Bit16u segment; - Bit16u blocks = kb*1024/16; - if (DOS_AllocateMemory(&segment,&blocks)) { - DOS_MCB mcb((Bit16u)(segment-1)); - mcb.SetPSPSeg(0x40); // use fake segment - WriteOut(MSG_Get("PROGRAM_LOADFIX_ALLOC"),kb); - // Prepare commandline... - if (cmd->FindCommand(commandNr++,temp_line)) { - // get Filename - char filename[128]; - safe_strncpy(filename,temp_line.c_str(),128); - // Setup commandline - bool ok; - char args[256]; - args[0] = 0; - do { - ok = cmd->FindCommand(commandNr++,temp_line); - if(sizeof(args)-strlen(args)-1 < temp_line.length()+1) - break; - strcat(args,temp_line.c_str()); - strcat(args," "); - } while (ok); - // Use shell to start program - DOS_Shell shell; - shell.Execute(filename,args); - DOS_FreeMemory(segment); - WriteOut(MSG_Get("PROGRAM_LOADFIX_DEALLOC"),kb); - } - } else { - WriteOut(MSG_Get("PROGRAM_LOADFIX_ERROR"),kb); - } -} - -static void LOADFIX_ProgramStart(Program * * make) { - *make=new LOADFIX; -} - -// RESCAN - -class RESCAN : public Program { -public: - void Run(void); -}; - -void RESCAN::Run(void) -{ - // Get current drive - Bit8u drive = DOS_GetDefaultDrive(); - if (Drives[drive]) { - Drives[drive]->EmptyCache(); - WriteOut(MSG_Get("PROGRAM_RESCAN_SUCCESS")); - } -} - -static void RESCAN_ProgramStart(Program * * make) { - *make=new RESCAN; -} - -class INTRO : public Program { -public: - void DisplayMount(void) { - /* Basic mounting has a version for each operating system. - * This is done this way so both messages appear in the language file*/ - WriteOut(MSG_Get("PROGRAM_INTRO_MOUNT_START")); -#if (WIN32) - WriteOut(MSG_Get("PROGRAM_INTRO_MOUNT_WINDOWS")); -#else - WriteOut(MSG_Get("PROGRAM_INTRO_MOUNT_OTHER")); -#endif - WriteOut(MSG_Get("PROGRAM_INTRO_MOUNT_END")); - } - - void Run(void) { - /* Only run if called from the first shell (Xcom TFTD runs any intro file in the path) */ - if(DOS_PSP(dos.psp()).GetParent() != DOS_PSP(DOS_PSP(dos.psp()).GetParent()).GetParent()) return; - if(cmd->FindExist("cdrom",false)) { - WriteOut(MSG_Get("PROGRAM_INTRO_CDROM")); - return; - } - if(cmd->FindExist("mount",false)) { - WriteOut("\033[2J");//Clear screen before printing - DisplayMount(); - return; - } - if(cmd->FindExist("special",false)) { - WriteOut(MSG_Get("PROGRAM_INTRO_SPECIAL")); - return; - } - /* Default action is to show all pages */ - WriteOut(MSG_Get("PROGRAM_INTRO")); - Bit8u c;Bit16u n=1; - DOS_ReadFile (STDIN,&c,&n); - DisplayMount(); - DOS_ReadFile (STDIN,&c,&n); - WriteOut(MSG_Get("PROGRAM_INTRO_CDROM")); - DOS_ReadFile (STDIN,&c,&n); - WriteOut(MSG_Get("PROGRAM_INTRO_SPECIAL")); - } -}; - -static void INTRO_ProgramStart(Program * * make) { - *make=new INTRO; -} - -class IMGMOUNT : public Program { -public: - void Run(void) { - //Hack To allow long commandlines - ChangeToLongCmd(); - /* In secure mode don't allow people to change imgmount points. - * Neither mount nor unmount */ - if(control->SecureMode()) { - WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); - return; - } - DOS_Drive * newdrive = NULL; - imageDisk * newImage = NULL; - Bit32u imagesize; - char drive; - std::string label; - std::vector paths; - std::string umount; - /* Check for unmounting */ - if (cmd->FindString("-u",umount,false)) { - umount[0] = toupper(umount[0]); - int i_drive = umount[0]-'A'; - if (i_drive < DOS_DRIVES && i_drive >= 0 && Drives[i_drive]) { - switch (DriveManager::UnmountDrive(i_drive)) { - case 0: - Drives[i_drive] = 0; - if (i_drive == DOS_GetDefaultDrive()) - DOS_SetDrive(toupper('Z') - 'A'); - WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_SUCCES"),umount[0]); - break; - case 1: - WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_NO_VIRTUAL")); - break; - case 2: - WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); - break; - } - } else { - WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_NOT_MOUNTED"),umount[0]); - } - return; - } - - - std::string type="hdd"; - std::string fstype="fat"; - cmd->FindString("-t",type,true); - cmd->FindString("-fs",fstype,true); - if(type == "cdrom") type = "iso"; //Tiny hack for people who like to type -t cdrom - Bit8u mediaid; - if (type=="floppy" || type=="hdd" || type=="iso") { - Bit16u sizes[4]; - bool imgsizedetect=false; - - std::string str_size; - mediaid=0xF8; - - if (type=="floppy") { - mediaid=0xF0; - } else if (type=="iso") { - str_size="650,127,16513,1700"; - mediaid=0xF8; - fstype = "iso"; - } - cmd->FindString("-size",str_size,true); - if ((type=="hdd") && (str_size.size()==0)) { - imgsizedetect=true; - } else { - char number[20]; - const char * scan=str_size.c_str(); - Bitu index=0;Bitu count=0; - - while (*scan) { - if (*scan==',') { - number[index]=0;sizes[count++]=atoi(number); - index=0; - } else number[index++]=*scan; - scan++; - } - number[index]=0;sizes[count++]=atoi(number); - } - - if(fstype=="fat" || fstype=="iso") { - // get the drive letter - if (!cmd->FindCommand(1,temp_line) || (temp_line.size() > 2) || ((temp_line.size()>1) && (temp_line[1]!=':'))) { - WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_DRIVE")); - return; - } - drive=toupper(temp_line[0]); - if (!isalpha(drive)) { - WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_DRIVE")); - return; - } - } else if (fstype=="none") { - cmd->FindCommand(1,temp_line); - if ((temp_line.size() > 1) || (!isdigit(temp_line[0]))) { - WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY2")); - return; - } - drive=temp_line[0]; - if ((drive<'0') || (drive>3+'0')) { - WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY2")); - return; - } - } else { - WriteOut_NoParsing(MSG_Get("PROGRAM_IMGMOUNT_FORMAT_UNSUPPORTED")); - return; - } - - // find all file parameters, assuming that all option parameters have been removed - while(cmd->FindCommand((unsigned int)(paths.size() + 2), temp_line) && temp_line.size()) { - - struct stat test; - if (stat(temp_line.c_str(),&test)) { - //See if it works if the ~ are written out - std::string homedir(temp_line); - Cross::ResolveHomedir(homedir); - if(!stat(homedir.c_str(),&test)) { - temp_line = homedir; - } else { - // convert dosbox filename to system filename - char fullname[CROSS_LEN]; - char tmp[CROSS_LEN]; - safe_strncpy(tmp, temp_line.c_str(), CROSS_LEN); - - Bit8u dummy; - if (!DOS_MakeName(tmp, fullname, &dummy) || strncmp(Drives[dummy]->GetInfo(),"local directory",15)) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_NON_LOCAL_DRIVE")); - return; - } - - localDrive *ldp = dynamic_cast(Drives[dummy]); - if (ldp==NULL) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FILE_NOT_FOUND")); - return; - } - ldp->GetSystemFilename(tmp, fullname); - temp_line = tmp; - - if (stat(temp_line.c_str(),&test)) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FILE_NOT_FOUND")); - return; - } - - if ((test.st_mode & S_IFDIR)) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT")); - return; - } - } - } - paths.push_back(temp_line); - } - if (paths.size() == 0) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_FILE")); - return; - } - if (paths.size() == 1) - temp_line = paths[0]; - if (paths.size() > 1 && fstype != "iso") { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MULTIPLE_NON_CUEISO_FILES")); - return; - } - - if(fstype=="fat") { - if (imgsizedetect) { - FILE * diskfile = fopen(temp_line.c_str(), "rb+"); - if(!diskfile) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE")); - return; - } - fseek(diskfile, 0L, SEEK_END); - Bit32u fcsize = (Bit32u)(ftell(diskfile) / 512L); - Bit8u buf[512]; - fseek(diskfile, 0L, SEEK_SET); - if (fread(buf,sizeof(Bit8u),512,diskfile)<512) { - fclose(diskfile); - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE")); - return; - } - fclose(diskfile); - if ((buf[510]!=0x55) || (buf[511]!=0xaa)) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_GEOMETRY")); - return; - } - Bitu sectors=(Bitu)(fcsize/(16*63)); - if (sectors*16*63!=fcsize) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_GEOMETRY")); - return; - } - sizes[0]=512; sizes[1]=63; sizes[2]=16; sizes[3]=sectors; - LOG_MSG("autosized image file: %d:%d:%d:%d",sizes[0],sizes[1],sizes[2],sizes[3]); - } - - newdrive=new fatDrive(temp_line.c_str(),sizes[0],sizes[1],sizes[2],sizes[3],0); - if(!(dynamic_cast(newdrive))->created_succesfully) { - delete newdrive; - newdrive = 0; - } - } else if (fstype=="iso") { - } else { - FILE *newDisk = fopen(temp_line.c_str(), "rb+"); - fseek(newDisk,0L, SEEK_END); - imagesize = (ftell(newDisk) / 1024); - - newImage = new imageDisk(newDisk, (Bit8u *)temp_line.c_str(), imagesize, (imagesize > 2880)); - if(imagesize>2880) newImage->Set_Geometry(sizes[2],sizes[3],sizes[1],sizes[0]); - } - } else { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_TYPE_UNSUPPORTED"),type.c_str()); - return; - } - - if(fstype=="fat") { - if (Drives[drive-'A']) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_ALREADY_MOUNTED")); - if (newdrive) delete newdrive; - return; - } - if (!newdrive) {WriteOut(MSG_Get("PROGRAM_IMGMOUNT_CANT_CREATE"));return;} - Drives[drive-'A']=newdrive; - // Set the correct media byte in the table - mem_writeb(Real2Phys(dos.tables.mediaid)+(drive-'A')*2,mediaid); - WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"),drive,temp_line.c_str()); - if(((fatDrive *)newdrive)->loadedDisk->hardDrive) { - if(imageDiskList[2] == NULL) { - imageDiskList[2] = ((fatDrive *)newdrive)->loadedDisk; - updateDPT(); - return; - } - if(imageDiskList[3] == NULL) { - imageDiskList[3] = ((fatDrive *)newdrive)->loadedDisk; - updateDPT(); - return; - } - } - if(!((fatDrive *)newdrive)->loadedDisk->hardDrive) { - imageDiskList[0] = ((fatDrive *)newdrive)->loadedDisk; - } - } else if (fstype=="iso") { - if (Drives[drive-'A']) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_ALREADY_MOUNTED")); - return; - } - MSCDEX_SetCDInterface(CDROM_USE_SDL, -1); - // create new drives for all images - std::vector isoDisks; - std::vector::size_type i; - std::vector::size_type ct; - for (i = 0; i < paths.size(); i++) { - int error = -1; - DOS_Drive* newDrive = new isoDrive(drive, paths[i].c_str(), mediaid, error); - isoDisks.push_back(newDrive); - switch (error) { - case 0 : break; - case 1 : WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); break; - case 2 : WriteOut(MSG_Get("MSCDEX_ERROR_NOT_SUPPORTED")); break; - case 3 : WriteOut(MSG_Get("MSCDEX_ERROR_PATH")); break; - case 4 : WriteOut(MSG_Get("MSCDEX_TOO_MANY_DRIVES")); break; - case 5 : WriteOut(MSG_Get("MSCDEX_LIMITED_SUPPORT")); break; - case 6 : WriteOut(MSG_Get("MSCDEX_INVALID_FILEFORMAT")); break; - default : WriteOut(MSG_Get("MSCDEX_UNKNOWN_ERROR")); break; - } - // error: clean up and leave - if (error) { - for(ct = 0; ct < isoDisks.size(); ct++) { - delete isoDisks[ct]; - } - return; - } - } - // Update DriveManager - for(ct = 0; ct < isoDisks.size(); ct++) { - DriveManager::AppendDisk(drive - 'A', isoDisks[ct]); - } - DriveManager::InitializeDrive(drive - 'A'); - - // Set the correct media byte in the table - mem_writeb(Real2Phys(dos.tables.mediaid) + (drive - 'A') * 2, mediaid); - - // Print status message (success) - WriteOut(MSG_Get("MSCDEX_SUCCESS")); - std::string tmp(paths[0]); - for (i = 1; i < paths.size(); i++) { - tmp += "; " + paths[i]; - } - WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"), drive, tmp.c_str()); - - } else if (fstype=="none") { - if(imageDiskList[drive-'0'] != NULL) delete imageDiskList[drive-'0']; - imageDiskList[drive-'0'] = newImage; - updateDPT(); - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT_NUMBER"),drive-'0',temp_line.c_str()); - } - - // check if volume label is given. becareful for cdrom - //if (cmd->FindString("-label",label,true)) newdrive->dirCache.SetLabel(label.c_str()); - return; - } -}; - -void IMGMOUNT_ProgramStart(Program * * make) { - *make=new IMGMOUNT; -} - - -Bitu DOS_SwitchKeyboardLayout(const char* new_layout); -Bitu DOS_LoadKeyboardLayout(const char * layoutname, Bit32s codepage, const char * codepagefile); -const char* DOS_GetLoadedLayout(void); - -class KEYB : public Program { -public: - void Run(void); -}; - -void KEYB::Run(void) { - if (cmd->FindCommand(1,temp_line)) { - if (cmd->FindString("?",temp_line,false)) { - WriteOut(MSG_Get("PROGRAM_KEYB_SHOWHELP")); - } else { - /* first parameter is layout ID */ - Bitu keyb_error=0; - std::string cp_string; - if (cmd->FindCommand(2,cp_string)) { - /* second parameter is codepage number */ - Bit32s par_cp=atoi(cp_string.c_str()); - char cp_file_name[256]; - if (cmd->FindCommand(3,cp_string)) { - /* third parameter is codepage file */ - strcpy(cp_file_name, cp_string.c_str()); - } else { - /* no codepage file specified, use automatic selection */ - strcpy(cp_file_name, "auto"); - } - - keyb_error=DOS_LoadKeyboardLayout(temp_line.c_str(), par_cp, cp_file_name); - } else keyb_error=DOS_SwitchKeyboardLayout(temp_line.c_str()); - switch (keyb_error) { - case KEYB_NOERROR: - WriteOut(MSG_Get("PROGRAM_KEYB_NOERROR"),temp_line.c_str(),dos.loaded_codepage); - break; - case KEYB_FILENOTFOUND: - WriteOut(MSG_Get("PROGRAM_KEYB_FILENOTFOUND"),temp_line.c_str()); - WriteOut(MSG_Get("PROGRAM_KEYB_SHOWHELP")); - break; - case KEYB_INVALIDFILE: - WriteOut(MSG_Get("PROGRAM_KEYB_INVALIDFILE"),temp_line.c_str()); - break; - case KEYB_LAYOUTNOTFOUND: - WriteOut(MSG_Get("PROGRAM_KEYB_LAYOUTNOTFOUND"),temp_line.c_str(),dos.loaded_codepage); - break; - case KEYB_INVALIDCPFILE: - WriteOut(MSG_Get("PROGRAM_KEYB_INVCPFILE"),temp_line.c_str()); - WriteOut(MSG_Get("PROGRAM_KEYB_SHOWHELP")); - break; - default: - LOG(LOG_DOSMISC,LOG_ERROR)("KEYB:Invalid returncode %x",keyb_error); - break; - } - } - } else { - /* no parameter in the command line, just output codepage info and possibly loaded layout ID */ - const char* layout_name = DOS_GetLoadedLayout(); - if (layout_name==NULL) { - WriteOut(MSG_Get("PROGRAM_KEYB_INFO"),dos.loaded_codepage); - } else { - WriteOut(MSG_Get("PROGRAM_KEYB_INFO_LAYOUT"),dos.loaded_codepage,layout_name); - } - } -} - -static void KEYB_ProgramStart(Program * * make) { - *make=new KEYB; -} - - -void DOS_SetupPrograms(void) { - /*Add Messages */ - - MSG_Add("PROGRAM_MOUNT_CDROMS_FOUND","CDROMs found: %d\n"); - MSG_Add("PROGRAM_MOUNT_STATUS_2","Drive %c is mounted as %s\n"); - MSG_Add("PROGRAM_MOUNT_STATUS_1","Current mounted drives are:\n"); - MSG_Add("PROGRAM_MOUNT_ERROR_1","Directory %s doesn't exist.\n"); - MSG_Add("PROGRAM_MOUNT_ERROR_2","%s isn't a directory\n"); - MSG_Add("PROGRAM_MOUNT_ILL_TYPE","Illegal type %s\n"); - MSG_Add("PROGRAM_MOUNT_ALREADY_MOUNTED","Drive %c already mounted with %s\n"); - MSG_Add("PROGRAM_MOUNT_USAGE","Usage \033[34;1mMOUNT Drive-Letter Local-Directory\033[0m\nSo a MOUNT c c:\\windows mounts windows directory as the c: drive in DOSBox\n"); - MSG_Add("PROGRAM_MOUNT_UMOUNT_NOT_MOUNTED","Drive %c isn't mounted.\n"); - MSG_Add("PROGRAM_MOUNT_UMOUNT_SUCCES","Drive %c has succesfully been removed.\n"); - MSG_Add("PROGRAM_MOUNT_UMOUNT_NO_VIRTUAL","Virtual Drives can not be unMOUNTed.\n"); - MSG_Add("PROGRAM_MOUNT_WARNING_WIN","\033[31;1mMounting c:\\ is NOT recommended. Please mount a (sub)directory next time.\033[0m\n"); - MSG_Add("PROGRAM_MOUNT_WARNING_OTHER","\033[31;1mMounting / is NOT recommended. Please mount a (sub)directory next time.\033[0m\n"); - - MSG_Add("PROGRAM_MEM_CONVEN","%10d Kb free conventional memory\n"); - MSG_Add("PROGRAM_MEM_EXTEND","%10d Kb free extended memory\n"); - MSG_Add("PROGRAM_MEM_EXPAND","%10d Kb free expanded memory\n"); - MSG_Add("PROGRAM_MEM_UPPER","%10d Kb free upper memory in %d blocks (largest UMB %d Kb)\n"); - - MSG_Add("PROGRAM_LOADFIX_ALLOC","%d kb allocated.\n"); - MSG_Add("PROGRAM_LOADFIX_DEALLOC","%d kb freed.\n"); - MSG_Add("PROGRAM_LOADFIX_DEALLOCALL","Used memory freed.\n"); - MSG_Add("PROGRAM_LOADFIX_ERROR","Memory allocation error.\n"); - - MSG_Add("MSCDEX_SUCCESS","MSCDEX installed.\n"); - MSG_Add("MSCDEX_ERROR_MULTIPLE_CDROMS","MSCDEX: Failure: Drive-letters of multiple CDRom-drives have to be continuous.\n"); - MSG_Add("MSCDEX_ERROR_NOT_SUPPORTED","MSCDEX: Failure: Not yet supported.\n"); - MSG_Add("MSCDEX_ERROR_PATH","MSCDEX: Failure: Path not valid.\n"); - MSG_Add("MSCDEX_TOO_MANY_DRIVES","MSCDEX: Failure: Too many CDRom-drives (max: 5). MSCDEX Installation failed.\n"); - MSG_Add("MSCDEX_LIMITED_SUPPORT","MSCDEX: Mounted subdirectory: limited support.\n"); - MSG_Add("MSCDEX_INVALID_FILEFORMAT","MSCDEX: Failure: File is either no iso/cue image or contains errors.\n"); - MSG_Add("MSCDEX_UNKNOWN_ERROR","MSCDEX: Failure: Unknown error.\n"); - - MSG_Add("PROGRAM_RESCAN_SUCCESS","Drive cache cleared.\n"); - - MSG_Add("PROGRAM_INTRO", - "\033[2J\033[32;1mWelcome to DOSBox\033[0m, an x86 emulator with sound and graphics.\n" - "DOSBox creates a shell for you which looks like old plain DOS.\n" - "\n" - "For information about basic mount type \033[34;1mintro mount\033[0m\n" - "For information about CD-ROM support type \033[34;1mintro cdrom\033[0m\n" - "For information about special keys type \033[34;1mintro special\033[0m\n" - "For more information about DOSBox, go to \033[34;1mhttp://dosbox.sourceforge.net/wiki\033[0m\n" - "\n" - "\033[31;1mDOSBox will stop/exit without a warning if an error occured!\033[0m\n" - "\n" - "\n" - ); - MSG_Add("PROGRAM_INTRO_MOUNT_START", - "\033[32;1mHere are some commands to get you started:\033[0m\n" - "Before you can use the files located on your own filesystem,\n" - "You have to mount the directory containing the files.\n" - "\n" - ); - MSG_Add("PROGRAM_INTRO_MOUNT_WINDOWS", - "\033[44;1m\xC9\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBB\n" - "\xBA \033[32mmount c c:\\dosprog\\\033[37m will create a C drive with c:\\dosprog as contents. \xBA\n" - "\xBA \xBA\n" - "\xBA \033[32mc:\\dosprog\\\033[37m is an example. Replace it with your own games directory. \033[37m \xBA\n" - "\xC8\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBC\033[0m\n" - ); - MSG_Add("PROGRAM_INTRO_MOUNT_OTHER", - "\033[44;1m\xC9\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBB\n" - "\xBA \033[32mmount c ~/dosprog\033[37m will create a C drive with ~/dosprog as contents. \xBA\n" - "\xBA \xBA\n" - "\xBA \033[32m~/dosprog\033[37m is an example. Replace it with your own games directory. \033[37m \xBA\n" - "\xC8\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBC\033[0m\n" - ); - MSG_Add("PROGRAM_INTRO_MOUNT_END", - "When the mount has succesfully completed you can type \033[34;1mc:\033[0m to go to your freshly\n" - "mounted C-drive. Typing \033[34;1mdir\033[0m there will show its contents." - " \033[34;1mcd\033[0m will allow you to\n" - "enter a directory (recognised by the \033[33;1m[]\033[0m in a directory listing).\n" - "You can run programs/files which end with \033[31m.exe .bat\033[0m and \033[31m.com\033[0m.\n" - ); - MSG_Add("PROGRAM_INTRO_CDROM", - "\033[2J\033[32;1mHow to mount a Real/Virtual CD-ROM Drive in DOSBox:\033[0m\n" - "DOSBox provides CD-ROM emulation on several levels.\n" - "\n" - "The \033[33mbasic\033[0m level works on all CD-ROM drives and normal directories.\n" - "It installs MSCDEX and marks the files read-only.\n" - "Usually this is enough for most games:\n" - "\033[34;1mmount d \033[0;31mD:\\\033[34;1m -t cdrom\033[0m or \033[34;1mmount d C:\\example -t cdrom\033[0m\n" - "If it doesn't work you might have to tell DOSBox the label of the CD-ROM:\n" - "\033[34;1mmount d C:\\example -t cdrom -label CDLABEL\033[0m\n" - "\n" - "The \033[33mnext\033[0m level adds some low-level support.\n" - "Therefore only works on CD-ROM drives:\n" - "\033[34;1mmount d \033[0;31mD:\\\033[34;1m -t cdrom -usecd \033[33m0\033[0m\n" - "\n" - "The \033[33mlast\033[0m level of support depends on your Operating System:\n" - "For \033[1mWindows 2000\033[0m, \033[1mWindows XP\033[0m and \033[1mLinux\033[0m:\n" - "\033[34;1mmount d \033[0;31mD:\\\033[34;1m -t cdrom -usecd \033[33m0 \033[34m-ioctl\033[0m\n" - "For \033[1mWindows 9x\033[0m with a ASPI layer installed:\n" - "\033[34;1mmount d \033[0;31mD:\\\033[34;1m -t cdrom -usecd \033[33m0 \033[34m-aspi\033[0m\n" - "\n" - "Replace \033[0;31mD:\\\033[0m with the location of your CD-ROM.\n" - "Replace the \033[33;1m0\033[0m in \033[34;1m-usecd \033[33m0\033[0m with the number reported for your CD-ROM if you type:\n" - "\033[34;1mmount -cd\033[0m\n" - ); - MSG_Add("PROGRAM_INTRO_SPECIAL", - "\033[2J\033[32;1mSpecial keys:\033[0m\n" - "These are the default keybindings.\n" - "They can be changed in the \033[33mkeymapper\033[0m.\n" - "\n" - "\033[33;1mALT-ENTER\033[0m : Go full screen and back.\n" - "\033[33;1mALT-PAUSE\033[0m : Pause DOSBox.\n" - "\033[33;1mCTRL-F1\033[0m : Start the \033[33mkeymapper\033[0m.\n" - "\033[33;1mCTRL-F4\033[0m : Update directory cache for all drives! Swap mounted disk-image.\n" - "\033[33;1mCTRL-ALT-F5\033[0m : Start/Stop creating a movie of the screen.\n" - "\033[33;1mCTRL-F5\033[0m : Save a screenshot.\n" - "\033[33;1mCTRL-F6\033[0m : Start/Stop recording sound output to a wave file.\n" - "\033[33;1mCTRL-ALT-F7\033[0m : Start/Stop recording of OPL commands.\n" - "\033[33;1mCTRL-ALT-F8\033[0m : Start/Stop the recording of raw MIDI commands.\n" - "\033[33;1mCTRL-F7\033[0m : Decrease frameskip.\n" - "\033[33;1mCTRL-F8\033[0m : Increase frameskip.\n" - "\033[33;1mCTRL-F9\033[0m : Kill DOSBox.\n" - "\033[33;1mCTRL-F10\033[0m : Capture/Release the mouse.\n" - "\033[33;1mCTRL-F11\033[0m : Slow down emulation (Decrease DOSBox Cycles).\n" - "\033[33;1mCTRL-F12\033[0m : Speed up emulation (Increase DOSBox Cycles).\n" - "\033[33;1mALT-F12\033[0m : Unlock speed (turbo button).\n" - ); - MSG_Add("PROGRAM_BOOT_NOT_EXIST","Bootdisk file does not exist. Failing.\n"); - MSG_Add("PROGRAM_BOOT_NOT_OPEN","Cannot open bootdisk file. Failing.\n"); - MSG_Add("PROGRAM_BOOT_WRITE_PROTECTED","Image file is read-only! Might create problems.\n"); - MSG_Add("PROGRAM_BOOT_PRINT_ERROR","This command boots DOSBox from either a floppy or hard disk image.\n\n" - "For this command, one can specify a succession of floppy disks swappable\n" - "by pressing Ctrl-F4, and -l specifies the mounted drive to boot from. If\n" - "no drive letter is specified, this defaults to booting from the A drive.\n" - "The only bootable drive letters are A, C, and D. For booting from a hard\n" - "drive (C or D), the image should have already been mounted using the\n" - "\033[34;1mIMGMOUNT\033[0m command.\n\n" - "The syntax of this command is:\n\n" - "\033[34;1mBOOT [diskimg1.img diskimg2.img] [-l driveletter]\033[0m\n" - ); - MSG_Add("PROGRAM_BOOT_UNABLE","Unable to boot off of drive %c"); - MSG_Add("PROGRAM_BOOT_IMAGE_OPEN","Opening image file: %s\n"); - MSG_Add("PROGRAM_BOOT_IMAGE_NOT_OPEN","Cannot open %s"); - MSG_Add("PROGRAM_BOOT_BOOT","Booting from drive %c...\n"); - MSG_Add("PROGRAM_BOOT_CART_WO_PCJR","PCjr cartridge found, but machine is not PCjr"); - MSG_Add("PROGRAM_BOOT_CART_LIST_CMDS","Available PCjr cartridge commandos:%s"); - MSG_Add("PROGRAM_BOOT_CART_NO_CMDS","No PCjr cartridge commandos found"); - - MSG_Add("PROGRAM_IMGMOUNT_SPECIFY_DRIVE","Must specify drive letter to mount image at.\n"); - MSG_Add("PROGRAM_IMGMOUNT_SPECIFY2","Must specify drive number (0 or 3) to mount image at (0,1=fda,fdb;2,3=hda,hdb).\n"); - MSG_Add("PROGRAM_IMGMOUNT_SPECIFY_GEOMETRY", - "For \033[33mCD-ROM\033[0m images: \033[34;1mIMGMOUNT drive-letter location-of-image -t iso\033[0m\n" - "\n" - "For \033[33mhardrive\033[0m images: Must specify drive geometry for hard drives:\n" - "bytes_per_sector, sectors_per_cylinder, heads_per_cylinder, cylinder_count.\n" - "\033[34;1mIMGMOUNT drive-letter location-of-image -size bps,spc,hpc,cyl\033[0m\n"); - MSG_Add("PROGRAM_IMGMOUNT_INVALID_IMAGE","Could not load image file.\n" - "Check that the path is correct and the image is accessible.\n"); - MSG_Add("PROGRAM_IMGMOUNT_INVALID_GEOMETRY","Could not extract drive geometry from image.\n" - "Use parameter -size bps,spc,hpc,cyl to specify the geometry.\n"); - MSG_Add("PROGRAM_IMGMOUNT_TYPE_UNSUPPORTED","Type \"%s\" is unsupported. Specify \"hdd\" or \"floppy\" or\"iso\".\n"); - MSG_Add("PROGRAM_IMGMOUNT_FORMAT_UNSUPPORTED","Format \"%s\" is unsupported. Specify \"fat\" or \"iso\" or \"none\".\n"); - MSG_Add("PROGRAM_IMGMOUNT_SPECIFY_FILE","Must specify file-image to mount.\n"); - MSG_Add("PROGRAM_IMGMOUNT_FILE_NOT_FOUND","Image file not found.\n"); - MSG_Add("PROGRAM_IMGMOUNT_MOUNT","To mount directories, use the \033[34;1mMOUNT\033[0m command, not the \033[34;1mIMGMOUNT\033[0m command.\n"); - MSG_Add("PROGRAM_IMGMOUNT_ALREADY_MOUNTED","Drive already mounted at that letter.\n"); - MSG_Add("PROGRAM_IMGMOUNT_CANT_CREATE","Can't create drive from file.\n"); - MSG_Add("PROGRAM_IMGMOUNT_MOUNT_NUMBER","Drive number %d mounted as %s\n"); - MSG_Add("PROGRAM_IMGMOUNT_NON_LOCAL_DRIVE", "The image must be on a host or local drive.\n"); - MSG_Add("PROGRAM_IMGMOUNT_MULTIPLE_NON_CUEISO_FILES", "Using multiple files is only supported for cue/iso images.\n"); - - MSG_Add("PROGRAM_KEYB_INFO","Codepage %i has been loaded\n"); - MSG_Add("PROGRAM_KEYB_INFO_LAYOUT","Codepage %i has been loaded for layout %s\n"); - MSG_Add("PROGRAM_KEYB_SHOWHELP", - "\033[32;1mKEYB\033[0m [keyboard layout ID[ codepage number[ codepage file]]]\n\n" - "Some examples:\n" - " \033[32;1mKEYB\033[0m: Display currently loaded codepage.\n" - " \033[32;1mKEYB\033[0m sp: Load the spanish (SP) layout, use an appropriate codepage.\n" - " \033[32;1mKEYB\033[0m sp 850: Load the spanish (SP) layout, use codepage 850.\n" - " \033[32;1mKEYB\033[0m sp 850 mycp.cpi: Same as above, but use file mycp.cpi.\n"); - MSG_Add("PROGRAM_KEYB_NOERROR","Keyboard layout %s loaded for codepage %i\n"); - MSG_Add("PROGRAM_KEYB_FILENOTFOUND","Keyboard file %s not found\n\n"); - MSG_Add("PROGRAM_KEYB_INVALIDFILE","Keyboard file %s invalid\n"); - MSG_Add("PROGRAM_KEYB_LAYOUTNOTFOUND","No layout in %s for codepage %i\n"); - MSG_Add("PROGRAM_KEYB_INVCPFILE","None or invalid codepage file for layout %s\n\n"); - - /*regular setup*/ - PROGRAMS_MakeFile("MOUNT.COM",MOUNT_ProgramStart); - PROGRAMS_MakeFile("MEM.COM",MEM_ProgramStart); - PROGRAMS_MakeFile("LOADFIX.COM",LOADFIX_ProgramStart); - PROGRAMS_MakeFile("RESCAN.COM",RESCAN_ProgramStart); - PROGRAMS_MakeFile("INTRO.COM",INTRO_ProgramStart); - PROGRAMS_MakeFile("BOOT.COM",BOOT_ProgramStart); -#if C_DEBUG - PROGRAMS_MakeFile("LDGFXROM.COM", LDGFXROM_ProgramStart); -#endif - PROGRAMS_MakeFile("IMGMOUNT.COM", IMGMOUNT_ProgramStart); - PROGRAMS_MakeFile("KEYB.COM", KEYB_ProgramStart); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include "programs.h" +#include "support.h" +#include "drives.h" +#include "cross.h" + + +class MOUNT : public Program { +public: + MOUNT(PROGRAM_Info * program_info); + void Run(void); +}; + + +MOUNT::MOUNT(PROGRAM_Info * info):Program(info) { + +} + + +void MOUNT::Run(void) { +/* Parse the command line */ + /* if the command line is empty show current mounts */ + + if (!*prog_info->cmd_line) { + WriteOut("Current mounted drives are\n"); + for (int d=0;dGetInfo()); + } + } + return; + } + + char drive; + drive=toupper(*prog_info->cmd_line); + char * dir=strchr(prog_info->cmd_line,' '); + if (dir) { + if (!*dir) dir=0; + else dir=trim(dir); + }; + + if (!isalpha(drive) || !dir) { + WriteOut("Usage MOUNT Drive-Letter Local-Directory\nSo a MOUNT c c:\\windows mounts windows directory as the c: drive in DOSBox\n"); + return; + }; + struct stat test; + if (stat(dir,&test)) { + WriteOut("Directory %s Doesn't exist",dir); + return; + } + /* Not a switch so a normal directory/file */ + if (!(test.st_mode & S_IFDIR)) { + WriteOut("%s isn't a directory",dir); + return; + } + if (Drives[drive-'A']) { + WriteOut("Drive %c already mounted with %s\n",drive,Drives[drive-'A']->GetInfo()); + return; + } + char fulldir[DOS_PATHLENGTH]; + strcpy(fulldir,dir); + static char theend[2]={CROSS_FILESPLIT,0}; + char * last=strrchr(fulldir,CROSS_FILESPLIT); + if (!last || *(++last)) strcat(fulldir,theend); + Drives[drive-'A']=new localDrive(fulldir); + WriteOut("Mounting drive %c as %s\n",drive,fulldir); +} + +static void MOUNT_ProgramStart(PROGRAM_Info * info) { + MOUNT * tempmount=new MOUNT(info); + tempmount->Run(); + delete tempmount; +} + + +class MEM : public Program { +public: + MEM(PROGRAM_Info * program_info); + void Run(void); +}; + + +MEM::MEM(PROGRAM_Info * info):Program(info) { + +} + + +void MEM::Run(void) { + +} + +static void MEM_ProgramStart(PROGRAM_Info * info) { + MEM mem(info); + mem.Run(); + +} + + +#if !defined (WIN32) /* Unix */ +class UPCASE : public Program { +public: + UPCASE(PROGRAM_Info * program_info); + void Run(void); + void upcasedir(char * directory); +}; + + +UPCASE::UPCASE(PROGRAM_Info * info):Program(info) { + +} + + +void UPCASE::upcasedir(char * directory) { + DIR * sdir; + char fullname[512]; + char newname[512]; + struct dirent *tempdata; + struct stat finfo; + + if(!(sdir=opendir(directory))) { + WriteOut("Failed to open directory %s\n",directory); + return; + } + WriteOut("Scanning directory %s\n",fullname); + while (tempdata=readdir(sdir)) { + if (strcmp(tempdata->d_name,".")==0) continue; + if (strcmp(tempdata->d_name,"..")==0) continue; + strcpy(fullname,directory); + strcat(fullname,"/"); + strcat(fullname,tempdata->d_name); + strcpy(newname,directory); + strcat(newname,"/"); + upcase(tempdata->d_name); + strcat(newname,tempdata->d_name); + WriteOut("Renaming %s to %s\n",fullname,newname); + rename(fullname,newname); + stat(fullname,&finfo); + if(S_ISDIR(finfo.st_mode)) { + upcasedir(fullname); + } + } + closedir(sdir); +} + + +void UPCASE::Run(void) { + /* First check if the directory exists */ + struct stat info; + WriteOut("UPCASE 0.1 Directory case convertor.\n"); + if (!strlen(prog_info->cmd_line)) { + WriteOut("Usage UPCASE [local directory]\n"); + WriteOut("This tool will convert all files and subdirectories in a directory.\n"); + WriteOut("Be VERY sure this directory contains only dos related material.\n"); + WriteOut("Otherwise you might horribly screw up your filesystem.\n"); + return; + } + if (stat(prog_info->cmd_line,&info)) { + WriteOut("%s doesn't exist\n",prog_info->cmd_line); + return; + } + if(!S_ISDIR(info.st_mode)) { + WriteOut("%s isn't a directory\n",prog_info->cmd_line); + return; + } + WriteOut("Converting the wrong directories can be very harmfull, please be carefull.\n"); + WriteOut("Are you really really sure you want to convert %s to upcase?Y/N\n",prog_info->cmd_line); + Bit8u key;Bit16u n=1; + DOS_ReadFile(STDIN,&key,&n); + if (toupper(key)=='Y') { + upcasedir(prog_info->cmd_line); + } else { + WriteOut("Okay better not do it.\n"); + } +} + +static void UPCASE_ProgramStart(PROGRAM_Info * info) { + UPCASE * tempUPCASE=new UPCASE(info); + tempUPCASE->Run(); + delete tempUPCASE; +} + +#endif + +void DOS_SetupPrograms(void) { + PROGRAMS_MakeFile("MOUNT.COM",MOUNT_ProgramStart); +// PROGRAMS_MakeFile("MEM.COM",MEM_ProgramStart); /*next release */ +#if !defined (WIN32) /* Unix */ + PROGRAMS_MakeFile("UPCASE.COM",UPCASE_ProgramStart); +#endif +} diff --git a/src/dos/dos_tables.cpp b/src/dos/dos_tables.cpp index a5d9b29..a2b2fce 100644 --- a/src/dos/dos_tables.cpp +++ b/src/dos/dos_tables.cpp @@ -1,171 +1,54 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dos_tables.cpp,v 1.30 2008/08/06 18:32:34 c2woody Exp $ */ - -#include "dosbox.h" -#include "mem.h" -#include "dos_inc.h" -#include "callback.h" - -#ifdef _MSC_VER -#pragma pack(1) -#endif -struct DOS_TableCase { - Bit16u size; - Bit8u chars[256]; -} -GCC_ATTRIBUTE (packed); -#ifdef _MSC_VER -#pragma pack () -#endif - -RealPt DOS_TableUpCase; -RealPt DOS_TableLowCase; - -static Bitu call_casemap; - -static Bit16u dos_memseg=DOS_PRIVATE_SEGMENT; - -Bit16u DOS_GetMemory(Bit16u pages) { - if ((Bitu)pages+(Bitu)dos_memseg>=DOS_PRIVATE_SEGMENT_END) { - E_Exit("DOS:Not enough memory for internal tables"); - } - Bit16u page=dos_memseg; - dos_memseg+=pages; - return page; -} - -static Bitu DOS_CaseMapFunc(void) { - //LOG(LOG_DOSMISC,LOG_ERROR)("Case map routine called : %c",reg_al); - return CBRET_NONE; -} - -static Bit8u country_info[0x22] = { -/* Date format */ 0x00, 0x00, -/* Currencystring */ 0x24, 0x00, 0x00, 0x00, 0x00, -/* Thousands sep */ 0x2c, 0x00, -/* Decimal sep */ 0x2e, 0x00, -/* Date sep */ 0x2d, 0x00, -/* time sep */ 0x3a, 0x00, -/* currency form */ 0x00, -/* digits after dec */ 0x02, -/* Time format */ 0x00, -/* Casemap */ 0x00, 0x00, 0x00, 0x00, -/* Data sep */ 0x2c, 0x00, -/* Reservered 5 */ 0x00, 0x00, 0x00, 0x00, 0x00, -/* Reservered 5 */ 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -void DOS_SetupTables(void) { - Bit16u seg;Bitu i; - dos.tables.mediaid=RealMake(DOS_GetMemory(4),0); - dos.tables.tempdta=RealMake(DOS_GetMemory(4),0); - dos.tables.tempdta_fcbdelete=RealMake(DOS_GetMemory(4),0); - for (i=0;i20 detection routine */ - /* Possibly obselete when SFT is properly handled */ - real_writed(DOS_CONSTRING_SEG,0x0a,0x204e4f43); - real_writed(DOS_CONSTRING_SEG,0x1a,0x204e4f43); - real_writed(DOS_CONSTRING_SEG,0x2a,0x204e4f43); - - /* create a CON device driver */ - seg=DOS_CONDRV_SEG; - real_writed(seg,0x00,0xffffffff); // next ptr - real_writew(seg,0x04,0x8013); // attributes - real_writed(seg,0x06,0xffffffff); // strategy routine - real_writed(seg,0x0a,0x204e4f43); // driver name - real_writed(seg,0x0e,0x20202020); // driver name - dos_infoblock.SetDeviceChainStart(RealMake(seg,0)); - - /* Create a fake Current Directory Structure */ - seg=DOS_CDS_SEG; - real_writed(seg,0x00,0x005c3a43); - dos_infoblock.SetCurDirStruct(RealMake(seg,0)); - - - - /* Allocate DCBS DOUBLE BYTE CHARACTER SET LEAD-BYTE TABLE */ - dos.tables.dbcs=RealMake(DOS_GetMemory(12),0); - mem_writed(Real2Phys(dos.tables.dbcs),0); //empty table - /* FILENAME CHARACTER TABLE */ - dos.tables.filenamechar=RealMake(DOS_GetMemory(2),0); - mem_writew(Real2Phys(dos.tables.filenamechar)+0x00,0x16); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x02,0x01); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x03,0x00); // allowed chars from - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x04,0xff); // ...to - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x05,0x00); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x06,0x00); // excluded chars from - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x07,0x20); // ...to - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x08,0x02); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x09,0x0e); // number of illegal separators - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x0a,0x2e); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x0b,0x22); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x0c,0x2f); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x0d,0x5c); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x0e,0x5b); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x0f,0x5d); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x10,0x3a); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x11,0x7c); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x12,0x3c); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x13,0x3e); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x14,0x2b); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x15,0x3d); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x16,0x3b); - mem_writeb(Real2Phys(dos.tables.filenamechar)+0x17,0x2c); - /* COLLATING SEQUENCE TABLE */ - dos.tables.collatingseq=RealMake(DOS_GetMemory(17),0); - mem_writew(Real2Phys(dos.tables.collatingseq),0x100); - for (i=0; i<256; i++) mem_writeb(Real2Phys(dos.tables.collatingseq)+i+2,i); - - /* Create a fake FCB SFT */ - seg=DOS_GetMemory(4); - real_writed(seg,0,0xffffffff); //Last File Table - real_writew(seg,4,100); //File Table supports 100 files - dos_infoblock.SetFCBTable(RealMake(seg,0)); - - /* Create a fake DPB */ - dos.tables.dpb=DOS_GetMemory(2); - for(Bitu d=0;d<26;d++) real_writeb(dos.tables.dpb,d,d); - - /* Create a fake disk buffer head */ - seg=DOS_GetMemory(6); - for (Bitu ct=0; ct<0x20; ct++) real_writeb(seg,ct,0); - real_writew(seg,0x00,0xffff); // forward ptr - real_writew(seg,0x02,0xffff); // backward ptr - real_writeb(seg,0x04,0xff); // not in use - real_writeb(seg,0x0a,0x01); // number of FATs - real_writed(seg,0x0d,0xffffffff); // pointer to DPB - dos_infoblock.SetDiskBufferHeadPt(RealMake(seg,0)); - - /* Set buffers to a nice value */ - dos_infoblock.SetBuffers(50,50); - - /* case map routine INT 0x21 0x38 */ - call_casemap = CALLBACK_Allocate(); - CALLBACK_Setup(call_casemap,DOS_CaseMapFunc,CB_RETF,"DOS CaseMap"); - /* Add it to country structure */ - host_writed(country_info + 0x12, CALLBACK_RealPointer(call_casemap)); - dos.tables.country=country_info; -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "mem.h" +#include "dos_inc.h" + +#pragma pack(1) + +struct DOS_TableCase { + Bit16u size; + Bit8u chars[256]; +}; +#pragma pack() + + +RealPt DOS_TableUpCase; +RealPt DOS_TableLowCase; + +static Bit16u dos_memseg=0xd000; +Bit16u DOS_GetMemory(Bit16u pages) { + if (pages+dos_memseg>=0xe000) { + E_Exit("DOS:Not enough memory for internal tables"); + } + Bit16u page=dos_memseg; + dos_memseg+=pages; + return page; +} + + +void DOS_SetupTables(void) { + dos.tables.indosflag=RealMake(DOS_GetMemory(1),0); + mem_writeb(Real2Phys(dos.tables.indosflag),0); +}; + + + + + diff --git a/src/dos/drive_cache.cpp b/src/dos/drive_cache.cpp deleted file mode 100644 index 2facf3f..0000000 --- a/src/dos/drive_cache.cpp +++ /dev/null @@ -1,764 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: drive_cache.cpp,v 1.59 2009/04/16 12:28:30 qbix79 Exp $ */ - -#include "drives.h" -#include "dos_inc.h" -#include "support.h" -#include "cross.h" - -// STL stuff -#include -#include -#include - -#if defined (WIN32) /* Win 32 */ -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from -#include -#endif - -#if defined (OS2) -#define INCL_DOSERRORS -#define INCL_DOSFILEMGR -#include -#endif - -int fileInfoCounter = 0; - -bool SortByName(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) { - return strcmp(a->shortname,b->shortname)<0; -} - -bool SortByNameRev(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) { - return strcmp(a->shortname,b->shortname)>0; -} - -bool SortByDirName(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) { - // Directories first... - if (a->isDir!=b->isDir) return (a->isDir>b->isDir); - return strcmp(a->shortname,b->shortname)<0; -} - -bool SortByDirNameRev(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) { - // Directories first... - if (a->isDir!=b->isDir) return (a->isDir>b->isDir); - return strcmp(a->shortname,b->shortname)>0; -} - -DOS_Drive_Cache::DOS_Drive_Cache(void) { - dirBase = new CFileInfo; - save_dir = 0; - srchNr = 0; - label[0] = 0; - nextFreeFindFirst = 0; - for (Bit32u i=0; iupdatelabel) return; - this->updatelabel = allowupdate; - Set_Label(vname,label,cdrom); - LOG(LOG_DOSMISC,LOG_NORMAL)("DIRCACHE: Set volume label to %s",label); -} - -Bit16u DOS_Drive_Cache::GetFreeID(CFileInfo* dir) { - for (Bit16u i=0; i 26) { // drive letter was lowercase - drivenumber = drive[0] - 'a' + 1; - } - APIRET rc = DosQueryFSInfo(drivenumber, FSIL_VOLSER, &fsinfo, sizeof(FSINFO)); - if (rc == NO_ERROR) { -#endif - /* Set label and allow being updated */ - SetLabel(labellocal,cdrom,true); - } -#endif -} - -void DOS_Drive_Cache::ExpandName(char* path) { - strcpy(path,GetExpandName(path)); -} - -char* DOS_Drive_Cache::GetExpandName(const char* path) { - static char work [CROSS_LEN] = { 0 }; - char dir [CROSS_LEN]; - - work[0] = 0; - strcpy (dir,path); - - const char* pos = strrchr(path,CROSS_FILESPLIT); - - if (pos) dir[pos-path+1] = 0; - CFileInfo* dirInfo = FindDirInfo(dir, work); - - if (pos) { - // Last Entry = File - strcpy(dir,pos+1); - GetLongName(dirInfo, dir); - strcat(work,dir); - } - - if (*work) { - size_t len = strlen(work); -#if defined (WIN32) - if((work[len-1] == CROSS_FILESPLIT ) && (len >= 2) && (work[len-2] != ':')) { -#else - if((len > 1) && (work[len-1] == CROSS_FILESPLIT )) { -#endif - work[len-1] = 0; // Remove trailing slashes except when in root - } - } - return work; -} - -void DOS_Drive_Cache::AddEntry(const char* path, bool checkExists) { - // Get Last part... - char file [CROSS_LEN]; - char expand [CROSS_LEN]; - - CFileInfo* dir = FindDirInfo(path,expand); - const char* pos = strrchr(path,CROSS_FILESPLIT); - - if (pos) { - strcpy(file,pos+1); - // Check if file already exists, then don't add new entry... - if (checkExists) { - if (GetLongName(dir,file)>=0) return; - } - - CreateEntry(dir,file,false); - - Bits index = GetLongName(dir,file); - if (index>=0) { - Bit32u i; - // Check if there are any open search dir that are affected by this... - if (dir) for (i=0; inextEntry)) - dirSearch[i]->nextEntry++; - } - } - // LOG_DEBUG("DIR: Added Entry %s",path); - } else { -// LOG_DEBUG("DIR: Error: Failed to add %s",path); - } -} - -void DOS_Drive_Cache::DeleteEntry(const char* path, bool ignoreLastDir) { - CacheOut(path,ignoreLastDir); - if (dirSearch[srchNr] && (dirSearch[srchNr]->nextEntry>0)) dirSearch[srchNr]->nextEntry--; - - if (!ignoreLastDir) { - // Check if there are any open search dir that are affected by this... - Bit32u i; - char expand [CROSS_LEN]; - CFileInfo* dir = FindDirInfo(path,expand); - if (dir) for (i=0; inextEntry>0)) - dirSearch[i]->nextEntry--; - } - } -} - -void DOS_Drive_Cache::CacheOut(const char* path, bool ignoreLastDir) { - char expand[CROSS_LEN] = { 0 }; - CFileInfo* dir; - - if (ignoreLastDir) { - char tmp[CROSS_LEN] = { 0 }; - Bit32s len=0; - const char* pos = strrchr(path,CROSS_FILESPLIT); - if (pos) len = (Bit32s)(pos - path); - if (len>0) { - safe_strncpy(tmp,path,len+1); - } else { - strcpy(tmp,path); - } - dir = FindDirInfo(tmp,expand); - } else { - dir = FindDirInfo(path,expand); - } - -// LOG_DEBUG("DIR: Caching out %s : dir %s",expand,dir->orgname); - // delete file objects... - for(Bit32u i=0; ifileList.size(); i++) { - if (dirSearch[srchNr]==dir->fileList[i]) dirSearch[srchNr] = 0; - delete dir->fileList[i]; dir->fileList[i] = 0; - } - // clear lists - dir->fileList.clear(); - dir->longNameList.clear(); - save_dir = 0; -} - -bool DOS_Drive_Cache::IsCachedIn(CFileInfo* curDir) { - return (curDir->fileList.size()>0); -} - - -bool DOS_Drive_Cache::GetShortName(const char* fullname, char* shortname) { - // Get Dir Info - char expand[CROSS_LEN] = {0}; - CFileInfo* curDir = FindDirInfo(fullname,expand); - - std::vector::size_type filelist_size = curDir->longNameList.size(); - if (GCC_UNLIKELY(filelist_size<=0)) return false; - - Bits low = 0; - Bits high = (Bits)(filelist_size-1); - Bits mid, res; - - while (low<=high) { - mid = (low+high)/2; - res = strcmp(fullname,curDir->longNameList[mid]->orgname); - if (res>0) low = mid+1; else - if (res<0) high = mid-1; - else { - strcpy(shortname,curDir->longNameList[mid]->shortname); - return true; - }; - } - return false; -} - -int DOS_Drive_Cache::CompareShortname(const char* compareName, const char* shortName) { - char const* cpos = strchr(shortName,'~'); - if (cpos) { -/* the following code is replaced as it's not safe when char* is 64 bits */ -/* Bits compareCount1 = (int)cpos - (int)shortName; - char* endPos = strchr(cpos,'.'); - Bitu numberSize = endPos ? int(endPos)-int(cpos) : strlen(cpos); - - char* lpos = strchr(compareName,'.'); - Bits compareCount2 = lpos ? int(lpos)-int(compareName) : strlen(compareName); - if (compareCount2>8) compareCount2 = 8; - - compareCount2 -= numberSize; - if (compareCount2>compareCount1) compareCount1 = compareCount2; -*/ - size_t compareCount1 = strcspn(shortName,"~"); - size_t numberSize = strcspn(cpos,"."); - size_t compareCount2 = strcspn(compareName,"."); - if(compareCount2 > 8) compareCount2 = 8; - /* We want - * compareCount2 -= numberSize; - * if (compareCount2>compareCount1) compareCount1 = compareCount2; - * but to prevent negative numbers: - */ - if(compareCount2 > compareCount1 + numberSize) - compareCount1 = compareCount2 - numberSize; - return strncmp(compareName,shortName,compareCount1); - } - return strcmp(compareName,shortName); -} - -Bitu DOS_Drive_Cache::CreateShortNameID(CFileInfo* curDir, const char* name) { - std::vector::size_type filelist_size = curDir->longNameList.size(); - if (GCC_UNLIKELY(filelist_size<=0)) return 1; // shortener IDs start with 1 - - Bitu foundNr = 0; - Bits low = 0; - Bits high = (Bits)(filelist_size-1); - Bits mid, res; - - while (low<=high) { - mid = (low+high)/2; - res = CompareShortname(name,curDir->longNameList[mid]->shortname); - - if (res>0) low = mid+1; else - if (res<0) high = mid-1; - else { - // any more same x chars in next entries ? - do { - foundNr = curDir->longNameList[mid]->shortNr; - mid++; - } while((Bitu)midlongNameList.size() && (CompareShortname(name,curDir->longNameList[mid]->shortname)==0)); - break; - }; - } - return foundNr+1; -} - -bool DOS_Drive_Cache::RemoveTrailingDot(char* shortname) { -// remove trailing '.' if no extension is available (Linux compatibility) - size_t len = strlen(shortname); - if (len && (shortname[len-1]=='.')) { - if (len==1) return false; - if ((len==2) && (shortname[0]=='.')) return false; - shortname[len-1] = 0; - return true; - } - return false; -} - -Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) { - std::vector::size_type filelist_size = curDir->fileList.size(); - if (GCC_UNLIKELY(filelist_size<=0)) return -1; - - // Remove dot, if no extension... - RemoveTrailingDot(shortName); - // Search long name and return array number of element - Bits low = 0; - Bits high = (Bits)(filelist_size-1); - Bits mid,res; - while (low<=high) { - mid = (low+high)/2; - res = strcmp(shortName,curDir->fileList[mid]->shortname); - if (res>0) low = mid+1; else - if (res<0) high = mid-1; else - { // Found - strcpy(shortName,curDir->fileList[mid]->orgname); - return mid; - }; - } - // not available - return -1; -} - -bool DOS_Drive_Cache::RemoveSpaces(char* str) { -// Removes all spaces - char* curpos = str; - char* chkpos = str; - while (*chkpos!=0) { - if (*chkpos==' ') chkpos++; else *curpos++ = *chkpos++; - } - *curpos = 0; - return (curpos!=chkpos); -} - -void DOS_Drive_Cache::CreateShortName(CFileInfo* curDir, CFileInfo* info) { - Bits len = 0; - bool createShort = false; - - char tmpNameBuffer[CROSS_LEN]; - - char* tmpName = tmpNameBuffer; - - // Remove Spaces - strcpy(tmpName,info->orgname); - upcase(tmpName); - createShort = RemoveSpaces(tmpName); - - // Get Length of filename - char* pos = strchr(tmpName,'.'); - if (pos) { - // ignore preceding '.' if extension is longer than "3" - if (strlen(pos)>4) { - while (*tmpName=='.') tmpName++; - createShort = true; - } - pos = strchr(tmpName,'.'); - if (pos) len = (Bits)(pos - tmpName); - else len = (Bits)strlen(tmpName); - } else { - len = (Bits)strlen(tmpName); - } - - // Should shortname version be created ? - createShort = createShort || (len>8); - if (!createShort) { - char buffer[CROSS_LEN]; - strcpy(buffer,tmpName); - createShort = (GetLongName(curDir,buffer)>=0); - } - - if (createShort) { - // Create number - char buffer[8]; - info->shortNr = CreateShortNameID(curDir,tmpName); - sprintf(buffer,"%d",info->shortNr); - // Copy first letters - Bits tocopy = 0; - size_t buflen = strlen(buffer); - if (len+buflen+1>8) tocopy = (Bits)(8 - buflen - 1); - else tocopy = len; - safe_strncpy(info->shortname,tmpName,tocopy+1); - // Copy number - strcat(info->shortname,"~"); - strcat(info->shortname,buffer); - // Add (and cut) Extension, if available - if (pos) { - // Step to last extension... - pos = strrchr(tmpName, '.'); - // add extension - strncat(info->shortname,pos,4); - info->shortname[DOS_NAMELENGTH] = 0; - } - - // keep list sorted for CreateShortNameID to work correctly - if (curDir->longNameList.size()>0) { - if (!(strcmp(info->shortname,curDir->longNameList.back()->shortname)<0)) { - // append at end of list - curDir->longNameList.push_back(info); - } else { - // look for position where to insert this element - bool found=false; - std::vector::iterator it; - for (it=curDir->longNameList.begin(); it!=curDir->longNameList.end(); ++it) { - if (strcmp(info->shortname,(*it)->shortname)<0) { - found = true; - break; - } - } - // Put it in longname list... - if (found) curDir->longNameList.insert(it,info); - else curDir->longNameList.push_back(info); - } - } else { - // empty file list, append - curDir->longNameList.push_back(info); - } - } else { - strcpy(info->shortname,tmpName); - } - RemoveTrailingDot(info->shortname); -} - -DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* expandedPath) { - // statics - static char split[2] = { CROSS_FILESPLIT,0 }; - - char dir [CROSS_LEN]; - char work [CROSS_LEN]; - const char* start = path; - const char* pos; - CFileInfo* curDir = dirBase; - Bit16u id; - - if (save_dir && (strcmp(path,save_path)==0)) { - strcpy(expandedPath,save_expanded); - return save_dir; - }; - -// LOG_DEBUG("DIR: Find %s",path); - - // Remove base dir path - start += strlen(basePath); - strcpy(expandedPath,basePath); - - // hehe, baseDir should be cached in... - if (!IsCachedIn(curDir)) { - strcpy(work,basePath); - if (OpenDir(curDir,work,id)) { - char buffer[CROSS_LEN]; - char* result = 0; - strcpy(buffer,dirPath); - ReadDir(id,result); - strcpy(dirPath,buffer); - free[id] = true; - }; - }; - - do { -// bool errorcheck = false; - pos = strchr(start,CROSS_FILESPLIT); - if (pos) { safe_strncpy(dir,start,pos-start+1); /*errorcheck = true;*/ } - else { strcpy(dir,start); }; - - // Path found - Bits nextDir = GetLongName(curDir,dir); - strcat(expandedPath,dir); - - // Error check -/* if ((errorcheck) && (nextDir<0)) { - LOG_DEBUG("DIR: Error: %s not found.",expandedPath); - }; -*/ - // Follow Directory - if ((nextDir>=0) && curDir->fileList[nextDir]->isDir) { - curDir = curDir->fileList[nextDir]; - strcpy (curDir->orgname,dir); - if (!IsCachedIn(curDir)) { - if (OpenDir(curDir,expandedPath,id)) { - char buffer[CROSS_LEN]; - char* result = 0; - strcpy(buffer,dirPath); - ReadDir(id,result); - strcpy(dirPath,buffer); - free[id] = true; - }; - } - }; - if (pos) { - strcat(expandedPath,split); - start = pos+1; - } - } while (pos); - - // Save last result for faster access next time - strcpy(save_path,path); - strcpy(save_expanded,expandedPath); - save_dir = curDir; - - return curDir; -} - -bool DOS_Drive_Cache::OpenDir(const char* path, Bit16u& id) { - char expand[CROSS_LEN] = {0}; - CFileInfo* dir = FindDirInfo(path,expand); - if (OpenDir(dir,expand,id)) { - dirSearch[id]->nextEntry = 0; - return true; - } - return false; -} - -bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, const char* expand, Bit16u& id) { - id = GetFreeID(dir); - dirSearch[id] = dir; - char expandcopy [CROSS_LEN]; - strcpy(expandcopy,expand); - // Add "/" - char end[2]={CROSS_FILESPLIT,0}; - if (expandcopy[strlen(expandcopy)-1]!=CROSS_FILESPLIT) strcat(expandcopy,end); - // open dir - if (dirSearch[id]) { - // open dir - dir_information* dirp = open_directory(expandcopy); - if (dirp) { - // Reset it.. - close_directory(dirp); - strcpy(dirPath,expandcopy); - free[id] = false; - return true; - } - }; - return false; -} - -void DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name, bool is_directory) { - CFileInfo* info = new CFileInfo; - strcpy(info->orgname, name); - info->shortNr = 0; - info->isDir = is_directory; - - // Check for long filenames... - CreateShortName(dir, info); - - bool found = false; - - // keep list sorted (so GetLongName works correctly, used by CreateShortName in this routine) - if (dir->fileList.size()>0) { - if (!(strcmp(info->shortname,dir->fileList.back()->shortname)<0)) { - // append at end of list - dir->fileList.push_back(info); - } else { - // look for position where to insert this element - std::vector::iterator it; - for (it=dir->fileList.begin(); it!=dir->fileList.end(); ++it) { - if (strcmp(info->shortname,(*it)->shortname)<0) { - found = true; - break; - } - } - // Put file in lists - if (found) dir->fileList.insert(it,info); - else dir->fileList.push_back(info); - } - } else { - // empty file list, append - dir->fileList.push_back(info); - } -} - -void DOS_Drive_Cache::CopyEntry(CFileInfo* dir, CFileInfo* from) { - CFileInfo* info = new CFileInfo; - // just copy things into new fileinfo - strcpy(info->orgname, from->orgname); - strcpy(info->shortname, from->shortname); - info->shortNr = from->shortNr; - info->isDir = from->isDir; - - dir->fileList.push_back(info); -} - -bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) { - // shouldnt happen... - if (id>MAX_OPENDIRS) return false; - - if (!IsCachedIn(dirSearch[id])) { - // Try to open directory - dir_information* dirp = open_directory(dirPath); - if (!dirp) { - free[id] = true; - return false; - } - // Read complete directory - char dir_name[CROSS_LEN]; - bool is_directory; - if (read_directory_first(dirp, dir_name, is_directory)) { - CreateEntry(dirSearch[id], dir_name, is_directory); - while (read_directory_next(dirp, dir_name, is_directory)) { - CreateEntry(dirSearch[id], dir_name, is_directory); - } - } - - // close dir - close_directory(dirp); - - // Info -/* if (!dirp) { - LOG_DEBUG("DIR: Error Caching in %s",dirPath); - return false; - } else { - char buffer[128]; - sprintf(buffer,"DIR: Caching in %s (%d Files)",dirPath,dirSearch[srchNr]->fileList.size()); - LOG_DEBUG(buffer); - };*/ - }; - if (SetResult(dirSearch[id], result, dirSearch[id]->nextEntry)) return true; - free[id] = true; - return false; -} - -bool DOS_Drive_Cache::SetResult(CFileInfo* dir, char* &result, Bitu entryNr) -{ - static char res[CROSS_LEN] = { 0 }; - - result = res; - if (entryNr>=dir->fileList.size()) return false; - CFileInfo* info = dir->fileList[entryNr]; - // copy filename, short version - strcpy(res,info->shortname); - // Set to next Entry - dir->nextEntry = entryNr+1; - return true; -} - -// FindFirst / FindNext -bool DOS_Drive_Cache::FindFirst(char* path, Bitu& id) { - Bit16u dirID; - Bitu dirFindFirstID = this->nextFreeFindFirst; - - // Cache directory in - if (!OpenDir(path,dirID)) return false; - - this->nextFreeFindFirst++; //increase it for the next search - - if (dirFindFirstID == MAX_OPENDIRS) { - // no free slot found... - LOG(LOG_MISC,LOG_ERROR)("DIRCACHE: FindFirst/Next: All slots full. Resetting"); - // Clear the internal list then. - dirFindFirstID = 0; - this->nextFreeFindFirst = 1; //the next free one after this search - for(Bitu n=0; n nextEntry = 0; - - // Copy entries to use with FindNext - for (Bitu i=0; ifileList.size(); i++) { - CopyEntry(dirFindFirst[dirFindFirstID],dirSearch[dirID]->fileList[i]); - } - // Now re-sort the fileList accordingly to output - switch (sortDirType) { - case ALPHABETICAL : break; -// case ALPHABETICAL : std::sort(dirFindFirst[dirFindFirstID]->fileList.begin(), dirFindFirst[dirFindFirstID]->fileList.end(), SortByName); break; - case DIRALPHABETICAL : std::sort(dirFindFirst[dirFindFirstID]->fileList.begin(), dirFindFirst[dirFindFirstID]->fileList.end(), SortByDirName); break; - case ALPHABETICALREV : std::sort(dirFindFirst[dirFindFirstID]->fileList.begin(), dirFindFirst[dirFindFirstID]->fileList.end(), SortByNameRev); break; - case DIRALPHABETICALREV : std::sort(dirFindFirst[dirFindFirstID]->fileList.begin(), dirFindFirst[dirFindFirstID]->fileList.end(), SortByDirNameRev); break; - case NOSORT : break; - } - -// LOG(LOG_MISC,LOG_ERROR)("DIRCACHE: FindFirst : %s (ID:%02X)",path,dirFindFirstID); - id = dirFindFirstID; - return true; -} - -bool DOS_Drive_Cache::FindNext(Bitu id, char* &result) { - // out of range ? - if ((id>=MAX_OPENDIRS) || !dirFindFirst[id]) { - LOG(LOG_MISC,LOG_ERROR)("DIRCACHE: FindFirst/Next failure : ID out of range: %04X",id); - return false; - } - if (!SetResult(dirFindFirst[id], result, dirFindFirst[id]->nextEntry)) { - // free slot - delete dirFindFirst[id]; dirFindFirst[id] = 0; - return false; - } - return true; -} diff --git a/src/dos/drive_fat.cpp b/src/dos/drive_fat.cpp deleted file mode 100644 index ac114b9..0000000 --- a/src/dos/drive_fat.cpp +++ /dev/null @@ -1,1260 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: drive_fat.cpp,v 1.26 2008/08/06 18:32:34 c2woody Exp $ */ - -#include -#include -#include -#include -#include "dosbox.h" -#include "dos_inc.h" -#include "drives.h" -#include "support.h" -#include "cross.h" -#include "bios.h" - -#define IMGTYPE_FLOPPY 0 -#define IMGTYPE_ISO 1 -#define IMGTYPE_HDD 2 - -#define FAT12 0 -#define FAT16 1 -#define FAT32 2 - -Bit8u fatSectBuffer[1024]; -Bit32u curFatSect; - -class fatFile : public DOS_File { -public: - fatFile(const char* name, Bit32u startCluster, Bit32u fileLen, fatDrive *useDrive); - bool Read(Bit8u * data,Bit16u * size); - bool Write(Bit8u * data,Bit16u * size); - bool Seek(Bit32u * pos,Bit32u type); - bool Close(); - Bit16u GetInformation(void); - bool UpdateDateTimeFromHost(void); -public: - Bit32u firstCluster; - Bit32u seekpos; - Bit32u filelength; - Bit32u currentSector; - Bit32u curSectOff; - Bit8u sectorBuffer[512]; - /* Record of where in the directory structure this file is located */ - Bit32u dirCluster; - Bit32u dirIndex; - - bool loadedSector; - fatDrive *myDrive; -private: - enum { NONE,READ,WRITE } last_action; - Bit16u info; -}; - - -/* IN - char * filename: Name in regular filename format, e.g. bob.txt */ -/* OUT - char * filearray: Name in DOS directory format, eleven char, e.g. bob txt */ -static void convToDirFile(char *filename, char *filearray) { - Bit32u charidx = 0; - Bit32u flen,i; - flen = (Bit32u)strlen(filename); - memset(filearray, 32, 11); - for(i=0;i= 11) break; - if(filename[i] != '.') { - filearray[charidx] = filename[i]; - charidx++; - } else { - charidx = 8; - } - } -} - -fatFile::fatFile(const char* /*name*/, Bit32u startCluster, Bit32u fileLen, fatDrive *useDrive) { - Bit32u seekto = 0; - firstCluster = startCluster; - myDrive = useDrive; - filelength = fileLen; - open = true; - loadedSector = false; - curSectOff = 0; - seekpos = 0; - memset(§orBuffer[0], 0, sizeof(sectorBuffer)); - - if(filelength > 0) { - Seek(&seekto, DOS_SEEK_SET); - myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); - loadedSector = true; - } -} - -bool fatFile::Read(Bit8u * data, Bit16u *size) { - Bit16u sizedec, sizecount; - if(seekpos >= filelength) { - *size = 0; - return true; - } - - if (!loadedSector) { - currentSector = myDrive->getAbsoluteSectFromBytePos(firstCluster, seekpos); - if(currentSector == 0) { - /* EOC reached before EOF */ - *size = 0; - loadedSector = false; - return true; - } - curSectOff = 0; - myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); - loadedSector = true; - } - - sizedec = *size; - sizecount = 0; - while(sizedec != 0) { - if(seekpos >= filelength) { - *size = sizecount; - return true; - } - data[sizecount++] = sectorBuffer[curSectOff++]; - seekpos++; - if(curSectOff >= myDrive->getSectorSize()) { - currentSector = myDrive->getAbsoluteSectFromBytePos(firstCluster, seekpos); - if(currentSector == 0) { - /* EOC reached before EOF */ - //LOG_MSG("EOC reached before EOF, seekpos %d, filelen %d", seekpos, filelength); - *size = sizecount; - loadedSector = false; - return true; - } - curSectOff = 0; - myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); - loadedSector = true; - //LOG_MSG("Reading absolute sector at %d for seekpos %d", currentSector, seekpos); - } - --sizedec; - } - *size =sizecount; - return true; -} - -bool fatFile::Write(Bit8u * data, Bit16u *size) { - /* TODO: Check for read-only bit */ - - direntry tmpentry; - Bit16u sizedec, sizecount; - sizedec = *size; - sizecount = 0; - - while(sizedec != 0) { - /* Increase filesize if necessary */ - if(seekpos >= filelength) { - if(filelength == 0) { - firstCluster = myDrive->getFirstFreeClust(); - myDrive->allocateCluster(firstCluster, 0); - currentSector = myDrive->getAbsoluteSectFromBytePos(firstCluster, seekpos); - myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); - loadedSector = true; - } - filelength = seekpos+1; - if (!loadedSector) { - currentSector = myDrive->getAbsoluteSectFromBytePos(firstCluster, seekpos); - if(currentSector == 0) { - /* EOC reached before EOF - try to increase file allocation */ - myDrive->appendCluster(firstCluster); - /* Try getting sector again */ - currentSector = myDrive->getAbsoluteSectFromBytePos(firstCluster, seekpos); - if(currentSector == 0) { - /* No can do. lets give up and go home. We must be out of room */ - goto finalizeWrite; - } - } - curSectOff = 0; - myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); - - loadedSector = true; - } - } - sectorBuffer[curSectOff++] = data[sizecount++]; - seekpos++; - if(curSectOff >= myDrive->getSectorSize()) { - if(loadedSector) myDrive->loadedDisk->Write_AbsoluteSector(currentSector, sectorBuffer); - - currentSector = myDrive->getAbsoluteSectFromBytePos(firstCluster, seekpos); - if(currentSector == 0) { - /* EOC reached before EOF - try to increase file allocation */ - myDrive->appendCluster(firstCluster); - /* Try getting sector again */ - currentSector = myDrive->getAbsoluteSectFromBytePos(firstCluster, seekpos); - if(currentSector == 0) { - /* No can do. lets give up and go home. We must be out of room */ - loadedSector = false; - goto finalizeWrite; - } - } - curSectOff = 0; - myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); - - loadedSector = true; - } - --sizedec; - } - if(curSectOff>0 && loadedSector) myDrive->loadedDisk->Write_AbsoluteSector(currentSector, sectorBuffer); - -finalizeWrite: - myDrive->directoryBrowse(dirCluster, &tmpentry, dirIndex); - tmpentry.entrysize = filelength; - tmpentry.loFirstClust = (Bit16u)firstCluster; - myDrive->directoryChange(dirCluster, &tmpentry, dirIndex); - - *size =sizecount; - return true; -} - -bool fatFile::Seek(Bit32u *pos, Bit32u type) { - Bit32s seekto=0; - - switch(type) { - case DOS_SEEK_SET: - seekto = (Bit32s)*pos; - break; - case DOS_SEEK_CUR: - /* Is this relative seek signed? */ - seekto = (Bit32s)*pos + (Bit32s)seekpos; - break; - case DOS_SEEK_END: - seekto = (Bit32s)filelength + (Bit32s)*pos; - break; - } -// LOG_MSG("Seek to %d with type %d (absolute value %d)", *pos, type, seekto); - - if((Bit32u)seekto > filelength) seekto = (Bit32s)filelength; - if(seekto<0) seekto = 0; - seekpos = (Bit32u)seekto; - currentSector = myDrive->getAbsoluteSectFromBytePos(firstCluster, seekpos); - if (currentSector == 0) { - /* not within file size, thus no sector is available */ - loadedSector = false; - } else { - curSectOff = seekpos % myDrive->getSectorSize(); - myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); - } - *pos = seekpos; - return true; -} - -bool fatFile::Close() { - /* Flush buffer */ - if (loadedSector) myDrive->loadedDisk->Write_AbsoluteSector(currentSector, sectorBuffer); - - return false; -} - -Bit16u fatFile::GetInformation(void) { - return 0; -} - -bool fatFile::UpdateDateTimeFromHost(void) { - return true; -} - -Bit32u fatDrive::getClustFirstSect(Bit32u clustNum) { - return ((clustNum - 2) * bootbuffer.sectorspercluster) + firstDataSector; -} - -Bit32u fatDrive::getClusterValue(Bit32u clustNum) { - Bit32u fatoffset=0; - Bit32u fatsectnum; - Bit32u fatentoff; - Bit32u clustValue=0; - - switch(fattype) { - case FAT12: - fatoffset = clustNum + (clustNum / 2); - break; - case FAT16: - fatoffset = clustNum * 2; - break; - case FAT32: - fatoffset = clustNum * 4; - break; - } - fatsectnum = bootbuffer.reservedsectors + (fatoffset / bootbuffer.bytespersector) + partSectOff; - fatentoff = fatoffset % bootbuffer.bytespersector; - - if(curFatSect != fatsectnum) { - /* Load two sectors at once for FAT12 */ - loadedDisk->Read_AbsoluteSector(fatsectnum, &fatSectBuffer[0]); - if (fattype==FAT12) - loadedDisk->Read_AbsoluteSector(fatsectnum+1, &fatSectBuffer[512]); - curFatSect = fatsectnum; - } - - switch(fattype) { - case FAT12: - clustValue = *((Bit16u *)&fatSectBuffer[fatentoff]); - if(clustNum & 0x1) { - clustValue >>= 4; - } else { - clustValue &= 0xfff; - } - break; - case FAT16: - clustValue = *((Bit16u *)&fatSectBuffer[fatentoff]); - break; - case FAT32: - clustValue = *((Bit32u *)&fatSectBuffer[fatentoff]); - break; - } - - return clustValue; -} - -void fatDrive::setClusterValue(Bit32u clustNum, Bit32u clustValue) { - Bit32u fatoffset=0; - Bit32u fatsectnum; - Bit32u fatentoff; - - switch(fattype) { - case FAT12: - fatoffset = clustNum + (clustNum / 2); - break; - case FAT16: - fatoffset = clustNum * 2; - break; - case FAT32: - fatoffset = clustNum * 4; - break; - } - fatsectnum = bootbuffer.reservedsectors + (fatoffset / bootbuffer.bytespersector) + partSectOff; - fatentoff = fatoffset % bootbuffer.bytespersector; - - if(curFatSect != fatsectnum) { - /* Load two sectors at once for FAT12 */ - loadedDisk->Read_AbsoluteSector(fatsectnum, &fatSectBuffer[0]); - if (fattype==FAT12) - loadedDisk->Read_AbsoluteSector(fatsectnum+1, &fatSectBuffer[512]); - curFatSect = fatsectnum; - } - - switch(fattype) { - case FAT12: { - Bit16u tmpValue = *((Bit16u *)&fatSectBuffer[fatentoff]); - if(clustNum & 0x1) { - clustValue &= 0xfff; - clustValue <<= 4; - tmpValue &= 0xf; - tmpValue |= (Bit16u)clustValue; - - } else { - clustValue &= 0xfff; - tmpValue &= 0xf000; - tmpValue |= (Bit16u)clustValue; - } - *((Bit16u *)&fatSectBuffer[fatentoff]) = tmpValue; - break; - } - case FAT16: - *((Bit16u *)&fatSectBuffer[fatentoff]) = (Bit16u)clustValue; - break; - case FAT32: - *((Bit32u *)&fatSectBuffer[fatentoff]) = clustValue; - break; - } - for(int fc=0;fcWrite_AbsoluteSector(fatsectnum + (fc * bootbuffer.sectorsperfat), &fatSectBuffer[0]); - if (fattype==FAT12) { - if (fatentoff>=511) - loadedDisk->Write_AbsoluteSector(fatsectnum+1+(fc * bootbuffer.sectorsperfat), &fatSectBuffer[512]); - } - } -} - -bool fatDrive::getEntryName(char *fullname, char *entname) { - char dirtoken[DOS_PATHLENGTH]; - - char * findDir; - char * findFile; - strcpy(dirtoken,fullname); - - //LOG_MSG("Testing for filename %s", fullname); - findDir = strtok(dirtoken,"\\"); - if (findDir==NULL) { - return true; // root always exists - } - findFile = findDir; - while(findDir != NULL) { - findFile = findDir; - findDir = strtok(NULL,"\\"); - } - strcpy(entname, findFile); - return true; -} - -bool fatDrive::getFileDirEntry(char const * const filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry) { - size_t len = strlen(filename); - char dirtoken[DOS_PATHLENGTH]; - Bit32u currentClust = 0; - - direntry foundEntry; - char * findDir; - char * findFile; - strcpy(dirtoken,filename); - findFile=dirtoken; - - /* Skip if testing in root directory */ - if ((len>0) && (filename[len-1]!='\\')) { - //LOG_MSG("Testing for filename %s", filename); - findDir = strtok(dirtoken,"\\"); - findFile = findDir; - while(findDir != NULL) { - imgDTA->SetupSearch(0,DOS_ATTR_DIRECTORY,findDir); - imgDTA->SetDirID(0); - - findFile = findDir; - if(!FindNextInternal(currentClust, *imgDTA, &foundEntry)) break; - else { - //Found something. See if it's a directory (findfirst always finds regular files) - char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size;Bit8u find_attr; - imgDTA->GetResult(find_name,find_size,find_date,find_time,find_attr); - if(!(find_attr & DOS_ATTR_DIRECTORY)) break; - } - - currentClust = foundEntry.loFirstClust; - findDir = strtok(NULL,"\\"); - } - } else { - /* Set to root directory */ - } - - /* Search found directory for our file */ - imgDTA->SetupSearch(0,0x7,findFile); - imgDTA->SetDirID(0); - if(!FindNextInternal(currentClust, *imgDTA, &foundEntry)) return false; - - memcpy(useEntry, &foundEntry, sizeof(direntry)); - *dirClust = (Bit32u)currentClust; - *subEntry = ((Bit32u)imgDTA->GetDirID()-1); - return true; -} - -bool fatDrive::getDirClustNum(char *dir, Bit32u *clustNum, bool parDir) { - Bit32u len = (Bit32u)strlen(dir); - char dirtoken[DOS_PATHLENGTH]; - Bit32u currentClust = 0; - direntry foundEntry; - char * findDir; - strcpy(dirtoken,dir); - - /* Skip if testing for root directory */ - if ((len>0) && (dir[len-1]!='\\')) { - //LOG_MSG("Testing for dir %s", dir); - findDir = strtok(dirtoken,"\\"); - while(findDir != NULL) { - imgDTA->SetupSearch(0,DOS_ATTR_DIRECTORY,findDir); - imgDTA->SetDirID(0); - findDir = strtok(NULL,"\\"); - if(parDir && (findDir == NULL)) break; - - char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size;Bit8u find_attr; - if(!FindNextInternal(currentClust, *imgDTA, &foundEntry)) { - return false; - } else { - imgDTA->GetResult(find_name,find_size,find_date,find_time,find_attr); - if(!(find_attr &DOS_ATTR_DIRECTORY)) return false; - } - currentClust = foundEntry.loFirstClust; - - } - *clustNum = currentClust; - } else { - /* Set to root directory */ - *clustNum = 0; - } - return true; -} - -Bit32u fatDrive::getSectorSize(void) { - return bootbuffer.bytespersector; -} - -Bit32u fatDrive::getAbsoluteSectFromBytePos(Bit32u startClustNum, Bit32u bytePos) { - return getAbsoluteSectFromChain(startClustNum, bytePos / bootbuffer.bytespersector); -} - -Bit32u fatDrive::getAbsoluteSectFromChain(Bit32u startClustNum, Bit32u logicalSector) { - Bit32s skipClust = logicalSector / bootbuffer.sectorspercluster; - Bit32u sectClust = logicalSector % bootbuffer.sectorspercluster; - - Bit32u currentClust = startClustNum; - Bit32u testvalue; - - while(skipClust!=0) { - bool isEOF = false; - testvalue = getClusterValue(currentClust); - switch(fattype) { - case FAT12: - if(testvalue >= 0xff8) isEOF = true; - break; - case FAT16: - if(testvalue >= 0xfff8) isEOF = true; - break; - case FAT32: - if(testvalue >= 0xfffffff8) isEOF = true; - break; - } - if((isEOF) && (skipClust>=1)) { - //LOG_MSG("End of cluster chain reached before end of logical sector seek!"); - return 0; - } - currentClust = testvalue; - --skipClust; - } - - return (getClustFirstSect(currentClust) + sectClust); -} - -void fatDrive::deleteClustChain(Bit32u startCluster) { - Bit32u testvalue; - Bit32u currentClust = startCluster; - bool isEOF = false; - while(!isEOF) { - testvalue = getClusterValue(currentClust); - if(testvalue == 0) { - /* What the crap? Cluster is already empty - BAIL! */ - break; - } - /* Mark cluster as empty */ - setClusterValue(currentClust, 0); - switch(fattype) { - case FAT12: - if(testvalue >= 0xff8) isEOF = true; - break; - case FAT16: - if(testvalue >= 0xfff8) isEOF = true; - break; - case FAT32: - if(testvalue >= 0xfffffff8) isEOF = true; - break; - } - if(isEOF) break; - currentClust = testvalue; - } -} - -Bit32u fatDrive::appendCluster(Bit32u startCluster) { - Bit32u testvalue; - Bit32u currentClust = startCluster; - bool isEOF = false; - - while(!isEOF) { - testvalue = getClusterValue(currentClust); - switch(fattype) { - case FAT12: - if(testvalue >= 0xff8) isEOF = true; - break; - case FAT16: - if(testvalue >= 0xfff8) isEOF = true; - break; - case FAT32: - if(testvalue >= 0xfffffff8) isEOF = true; - break; - } - if(isEOF) break; - currentClust = testvalue; - } - - Bit32u newClust = getFirstFreeClust(); - /* Drive is full */ - if(newClust == 0) return 0; - - if(!allocateCluster(newClust, currentClust)) return 0; - - zeroOutCluster(newClust); - - return newClust; -} - -bool fatDrive::allocateCluster(Bit32u useCluster, Bit32u prevCluster) { - - /* Can't allocate cluster #0 */ - if(useCluster == 0) return false; - - if(prevCluster != 0) { - /* Refuse to allocate cluster if previous cluster value is zero (unallocated) */ - if(!getClusterValue(prevCluster)) return false; - - /* Point cluster to new cluster in chain */ - setClusterValue(prevCluster, useCluster); - //LOG_MSG("Chaining cluser %d to %d", prevCluster, useCluster); - } - - switch(fattype) { - case FAT12: - setClusterValue(useCluster, 0xfff); - break; - case FAT16: - setClusterValue(useCluster, 0xffff); - break; - case FAT32: - setClusterValue(useCluster, 0xffffffff); - break; - } - return true; -} - -fatDrive::fatDrive(const char *sysFilename, Bit32u bytesector, Bit32u cylsector, Bit32u headscyl, Bit32u cylinders, Bit32u startSector) { - created_succesfully = true; - FILE *diskfile; - Bit32u filesize; - struct partTable mbrData; - - if(imgDTASeg == 0) { - imgDTASeg = DOS_GetMemory(2); - imgDTAPtr = RealMake(imgDTASeg, 0); - imgDTA = new DOS_DTA(imgDTAPtr); - } - - diskfile = fopen(sysFilename, "rb+"); - if(!diskfile) {created_succesfully = false;return;} - fseek(diskfile, 0L, SEEK_END); - filesize = (Bit32u)ftell(diskfile) / 1024L; - - /* Load disk image */ - loadedDisk = new imageDisk(diskfile, (Bit8u *)sysFilename, filesize, (filesize > 2880)); - if(!loadedDisk) { - created_succesfully = false; - return; - } - - if(filesize > 2880) { - /* Set user specified harddrive parameters */ - loadedDisk->Set_Geometry(headscyl, cylinders,cylsector, bytesector); - - loadedDisk->Read_Sector(0,0,1,&mbrData); - - if(mbrData.magic1!= 0x55 || mbrData.magic2!= 0xaa) LOG_MSG("Possibly invalid partition table in disk image."); - - startSector = 63; - int m; - for(m=0;m<4;m++) { - /* Pick the first available partition */ - if(mbrData.pentry[m].partSize != 0x00) { - LOG_MSG("Using partition %d on drive; skipping %d sectors", m, mbrData.pentry[m].absSectStart); - startSector = mbrData.pentry[m].absSectStart; - break; - } - } - - if(m==4) LOG_MSG("No good partiton found in image."); - - partSectOff = startSector; - } else { - /* Floppy disks don't have partitions */ - partSectOff = 0; - } - - loadedDisk->Read_AbsoluteSector(0+partSectOff,&bootbuffer); - if ((bootbuffer.magic1 != 0x55) || (bootbuffer.magic2 != 0xaa)) { - /* Not a FAT filesystem */ - LOG_MSG("Loaded image has no valid magicnumbers at the end!"); - } - - if(!bootbuffer.sectorsperfat) { - /* FAT32 not implemented yet */ - created_succesfully = false; - return; - } - - - /* Determine FAT format, 12, 16 or 32 */ - - /* Get size of root dir in sectors */ - /* TODO: Get 32-bit total sector count if needed */ - Bit32u RootDirSectors = ((bootbuffer.rootdirentries * 32) + (bootbuffer.bytespersector - 1)) / bootbuffer.bytespersector; - Bit32u DataSectors; - if(bootbuffer.totalsectorcount != 0) { - DataSectors = bootbuffer.totalsectorcount - (bootbuffer.reservedsectors + (bootbuffer.fatcopies * bootbuffer.sectorsperfat) + RootDirSectors); - } else { - DataSectors = bootbuffer.totalsecdword - (bootbuffer.reservedsectors + (bootbuffer.fatcopies * bootbuffer.sectorsperfat) + RootDirSectors); - - } - CountOfClusters = DataSectors / bootbuffer.sectorspercluster; - - firstDataSector = (bootbuffer.reservedsectors + (bootbuffer.fatcopies * bootbuffer.sectorsperfat) + RootDirSectors) + partSectOff; - firstRootDirSect = bootbuffer.reservedsectors + (bootbuffer.fatcopies * bootbuffer.sectorsperfat) + partSectOff; - - if(CountOfClusters < 4085) { - /* Volume is FAT12 */ - LOG_MSG("Mounted FAT volume is FAT12 with %d clusters", CountOfClusters); - fattype = FAT12; - } else if (CountOfClusters < 65525) { - LOG_MSG("Mounted FAT volume is FAT16 with %d clusters", CountOfClusters); - fattype = FAT16; - } else { - LOG_MSG("Mounted FAT volume is FAT32 with %d clusters", CountOfClusters); - fattype = FAT32; - } - - /* There is no cluster 0, this means we are in the root directory */ - cwdDirCluster = 0; - - memset(fatSectBuffer,0,1024); - curFatSect = 0xffffffff; -} - -bool fatDrive::AllocationInfo(Bit16u *_bytes_sector, Bit8u *_sectors_cluster, Bit16u *_total_clusters, Bit16u *_free_clusters) { - Bit32u hs, cy, sect,sectsize; - Bit32u countFree = 0; - Bit32u i; - - loadedDisk->Get_Geometry(&hs, &cy, §, §size); - *_bytes_sector = (Bit16u)sectsize; - *_sectors_cluster = bootbuffer.sectorspercluster; - if (CountOfClusters<65536) *_total_clusters = (Bit16u)CountOfClusters; - else { - // maybe some special handling needed for fat32 - *_total_clusters = 65535; - } - for(i=0;iGetBiosType(); } - -bool fatDrive::FileCreate(DOS_File **file, char *name, Bit16u attributes) { - direntry fileEntry; - Bit32u dirClust, subEntry; - char dirName[DOS_NAMELENGTH_ASCII]; - char pathName[11]; - - Bitu save_errorcode=dos.errorcode; - - /* Check if file already exists */ - if(getFileDirEntry(name, &fileEntry, &dirClust, &subEntry)) { - /* Truncate file */ - fileEntry.entrysize=0; - directoryChange(dirClust, &fileEntry, subEntry); - } else { - /* Can we even get the name of the file itself? */ - if(!getEntryName(name, &dirName[0])) return false; - convToDirFile(&dirName[0], &pathName[0]); - - /* Can we find the base directory? */ - if(!getDirClustNum(name, &dirClust, true)) return false; - memset(&fileEntry, 0, sizeof(direntry)); - memcpy(&fileEntry.entryname, &pathName[0], 11); - fileEntry.attrib = (Bit8u)(attributes & 0xff); - addDirectoryEntry(dirClust, fileEntry); - - /* Check if file exists now */ - if(!getFileDirEntry(name, &fileEntry, &dirClust, &subEntry)) return false; - } - - /* Empty file created, now lets open it */ - /* TODO: check for read-only flag and requested write access */ - *file = new fatFile(name, fileEntry.loFirstClust, fileEntry.entrysize, this); - ((fatFile *)(*file))->dirCluster = dirClust; - ((fatFile *)(*file))->dirIndex = subEntry; - /* Maybe modTime and date should be used ? (crt matches findnext) */ - ((fatFile *)(*file))->time = fileEntry.crtTime; - ((fatFile *)(*file))->date = fileEntry.crtDate; - - dos.errorcode=save_errorcode; - return true; -} - -bool fatDrive::FileExists(const char *name) { - direntry fileEntry; - Bit32u dummy1, dummy2; - if(!getFileDirEntry(name, &fileEntry, &dummy1, &dummy2)) return false; - return true; -} - -bool fatDrive::FileOpen(DOS_File **file, char *name, Bit32u /*flags*/) { - direntry fileEntry; - Bit32u dirClust, subEntry; - if(!getFileDirEntry(name, &fileEntry, &dirClust, &subEntry)) return false; - /* TODO: check for read-only flag and requested write access */ - *file = new fatFile(name, fileEntry.loFirstClust, fileEntry.entrysize, this); - ((fatFile *)(*file))->dirCluster = dirClust; - ((fatFile *)(*file))->dirIndex = subEntry; - /* Maybe modTime and date should be used ? (crt matches findnext) */ - ((fatFile *)(*file))->time = fileEntry.crtTime; - ((fatFile *)(*file))->date = fileEntry.crtDate; - return true; -} - -bool fatDrive::FileStat(const char * /*name*/, FileStat_Block *const /*stat_block*/) { - /* TODO: Stub */ - return false; -} - -bool fatDrive::FileUnlink(char * name) { - direntry fileEntry; - Bit32u dirClust, subEntry; - - if(!getFileDirEntry(name, &fileEntry, &dirClust, &subEntry)) return false; - - fileEntry.entryname[0] = 0xe5; - directoryChange(dirClust, &fileEntry, subEntry); - - if(fileEntry.loFirstClust != 0) deleteClustChain(fileEntry.loFirstClust); - - return true; -} - -bool fatDrive::FindFirst(char *_dir, DOS_DTA &dta,bool /*fcb_findfirst*/) { - direntry dummyClust; - Bit8u attr;char pattern[DOS_NAMELENGTH_ASCII]; - dta.GetSearchParams(attr,pattern); - if(attr==DOS_ATTR_VOLUME) { - if (strcmp(GetLabel(), "") == 0 ) { - DOS_SetError(DOSERR_NO_MORE_FILES); - return false; - } - dta.SetResult(GetLabel(),0,0,0,DOS_ATTR_VOLUME); - return true; - } - if(attr & DOS_ATTR_VOLUME) //check for root dir or fcb_findfirst - LOG(LOG_DOSMISC,LOG_WARN)("findfirst for volumelabel used on fatDrive. Unhandled!!!!!"); - if(!getDirClustNum(_dir, &cwdDirCluster, false)) { - DOS_SetError(DOSERR_PATH_NOT_FOUND); - return false; - } - dta.SetDirID(0); - dta.SetDirIDCluster((Bit16u)(cwdDirCluster&0xffff)); - return FindNextInternal(cwdDirCluster, dta, &dummyClust); -} - -char* removeTrailingSpaces(char* str) { - char* end = str + strlen(str); - while((*--end == ' ') && (end > str)) {}; - *++end = '\0'; - return str; -} - -char* removeLeadingSpaces(char* str) { - size_t len = strlen(str); - size_t pos = strspn(str," "); - memmove(str,str + pos,len - pos + 1); - return str; -} - -char* trimString(char* str) { - return removeTrailingSpaces(removeLeadingSpaces(str)); -} - -bool fatDrive::FindNextInternal(Bit32u dirClustNumber, DOS_DTA &dta, direntry *foundEntry) { - direntry sectbuf[16]; /* 16 directory entries per sector */ - Bit32u logentsector; /* Logical entry sector */ - Bit32u entryoffset; /* Index offset within sector */ - Bit32u tmpsector; - Bit8u attrs; - Bit16u dirPos; - char srch_pattern[DOS_NAMELENGTH_ASCII]; - char find_name[DOS_NAMELENGTH_ASCII]; - char extension[4]; - - dta.GetSearchParams(attrs, srch_pattern); - dirPos = dta.GetDirID(); - -nextfile: - logentsector = dirPos / 16; - entryoffset = dirPos % 16; - - if(dirClustNumber==0) { - loadedDisk->Read_AbsoluteSector(firstRootDirSect+logentsector,sectbuf); - } else { - tmpsector = getAbsoluteSectFromChain(dirClustNumber, logentsector); - /* A zero sector number can't happen */ - if(tmpsector == 0) { - DOS_SetError(DOSERR_NO_MORE_FILES); - return false; - } - loadedDisk->Read_AbsoluteSector(tmpsector,sectbuf); - } - dirPos++; - dta.SetDirID(dirPos); - - /* Deleted file entry */ - if (sectbuf[entryoffset].entryname[0] == 0xe5) goto nextfile; - - /* End of directory list */ - if (sectbuf[entryoffset].entryname[0] == 0x00) { - DOS_SetError(DOSERR_NO_MORE_FILES); - return false; - } - - memset(find_name,0,DOS_NAMELENGTH_ASCII); - memset(extension,0,4); - memcpy(find_name,§buf[entryoffset].entryname[0],8); - memcpy(extension,§buf[entryoffset].entryname[8],3); - trimString(&find_name[0]); - trimString(&extension[0]); - if(!(sectbuf[entryoffset].attrib & DOS_ATTR_DIRECTORY) || extension[0]!=0) { - strcat(find_name, "."); - strcat(find_name, extension); - } - - /* Ignore files with volume label. FindFirst should search for those. (return the first one found) */ - if(sectbuf[entryoffset].attrib & 0x8) goto nextfile; - - /* Always find ARCHIVES even if bit is not set Perhaps test is not the best test */ - if(~attrs & sectbuf[entryoffset].attrib & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM) ) goto nextfile; - if(!WildFileCmp(find_name,srch_pattern)) goto nextfile; - - dta.SetResult(find_name, sectbuf[entryoffset].entrysize, sectbuf[entryoffset].crtDate, sectbuf[entryoffset].crtTime, sectbuf[entryoffset].attrib); - memcpy(foundEntry, §buf[entryoffset], sizeof(direntry)); - - return true; -} - -bool fatDrive::FindNext(DOS_DTA &dta) { - direntry dummyClust; - - return FindNextInternal(dta.GetDirIDCluster(), dta, &dummyClust); -} - -bool fatDrive::GetFileAttr(char *name, Bit16u *attr) { - direntry fileEntry; - Bit32u dirClust, subEntry; - if(!getFileDirEntry(name, &fileEntry, &dirClust, &subEntry)) { - char dirName[DOS_NAMELENGTH_ASCII]; - char pathName[11]; - - /* Can we even get the name of the directory itself? */ - if(!getEntryName(name, &dirName[0])) return false; - convToDirFile(&dirName[0], &pathName[0]); - - /* Get parent directory starting cluster */ - if(!getDirClustNum(name, &dirClust, true)) return false; - - /* Find directory entry in parent directory */ - Bit32s fileidx = 2; - if (dirClust==0) fileidx = 0; // root directory - while(directoryBrowse(dirClust, &fileEntry, fileidx)) { - if(memcmp(&fileEntry.entryname, &pathName[0], 11) == 0) { - *attr=fileEntry.attrib; - return true; - } - fileidx++; - } - return false; - } else *attr=fileEntry.attrib; - return true; -} - -bool fatDrive::directoryBrowse(Bit32u dirClustNumber, direntry *useEntry, Bit32s entNum) { - direntry sectbuf[16]; /* 16 directory entries per sector */ - Bit32u logentsector; /* Logical entry sector */ - Bit32u entryoffset = 0; /* Index offset within sector */ - Bit32u tmpsector; - Bit16u dirPos = 0; - - while(entNum>=0) { - - logentsector = dirPos / 16; - entryoffset = dirPos % 16; - - if(dirClustNumber==0) { - if(dirPos >= bootbuffer.rootdirentries) return false; - tmpsector = firstRootDirSect+logentsector; - loadedDisk->Read_AbsoluteSector(tmpsector,sectbuf); - } else { - tmpsector = getAbsoluteSectFromChain(dirClustNumber, logentsector); - /* A zero sector number can't happen */ - if(tmpsector == 0) return false; - loadedDisk->Read_AbsoluteSector(tmpsector,sectbuf); - } - dirPos++; - - - /* End of directory list */ - if (sectbuf[entryoffset].entryname[0] == 0x00) return false; - --entNum; - } - - memcpy(useEntry, §buf[entryoffset],sizeof(direntry)); - return true; -} - -bool fatDrive::directoryChange(Bit32u dirClustNumber, direntry *useEntry, Bit32s entNum) { - direntry sectbuf[16]; /* 16 directory entries per sector */ - Bit32u logentsector; /* Logical entry sector */ - Bit32u entryoffset = 0; /* Index offset within sector */ - Bit32u tmpsector = 0; - Bit16u dirPos = 0; - - while(entNum>=0) { - - logentsector = dirPos / 16; - entryoffset = dirPos % 16; - - if(dirClustNumber==0) { - if(dirPos >= bootbuffer.rootdirentries) return false; - tmpsector = firstRootDirSect+logentsector; - loadedDisk->Read_AbsoluteSector(tmpsector,sectbuf); - } else { - tmpsector = getAbsoluteSectFromChain(dirClustNumber, logentsector); - /* A zero sector number can't happen */ - if(tmpsector == 0) return false; - loadedDisk->Read_AbsoluteSector(tmpsector,sectbuf); - } - dirPos++; - - - /* End of directory list */ - if (sectbuf[entryoffset].entryname[0] == 0x00) return false; - --entNum; - } - if(tmpsector != 0) { - memcpy(§buf[entryoffset], useEntry, sizeof(direntry)); - loadedDisk->Write_AbsoluteSector(tmpsector, sectbuf); - return true; - } else { - return false; - } -} - -bool fatDrive::addDirectoryEntry(Bit32u dirClustNumber, direntry useEntry) { - direntry sectbuf[16]; /* 16 directory entries per sector */ - Bit32u logentsector; /* Logical entry sector */ - Bit32u entryoffset; /* Index offset within sector */ - Bit32u tmpsector; - Bit16u dirPos = 0; - - for(;;) { - - logentsector = dirPos / 16; - entryoffset = dirPos % 16; - - if(dirClustNumber==0) { - if(dirPos >= bootbuffer.rootdirentries) return false; - tmpsector = firstRootDirSect+logentsector; - loadedDisk->Read_AbsoluteSector(tmpsector,sectbuf); - } else { - tmpsector = getAbsoluteSectFromChain(dirClustNumber, logentsector); - /* A zero sector number can't happen - we need to allocate more room for this directory*/ - if(tmpsector == 0) { - Bit32u newClust; - newClust = appendCluster(dirClustNumber); - if(newClust == 0) return false; - /* Try again to get tmpsector */ - tmpsector = getAbsoluteSectFromChain(dirClustNumber, logentsector); - if(tmpsector == 0) return false; /* Give up if still can't get more room for directory */ - } - loadedDisk->Read_AbsoluteSector(tmpsector,sectbuf); - } - dirPos++; - - /* Deleted file entry or end of directory list */ - if ((sectbuf[entryoffset].entryname[0] == 0xe5) || (sectbuf[entryoffset].entryname[0] == 0x00)) { - sectbuf[entryoffset] = useEntry; - loadedDisk->Write_AbsoluteSector(tmpsector,sectbuf); - break; - } - } - - return true; -} - -void fatDrive::zeroOutCluster(Bit32u clustNumber) { - Bit8u secBuffer[512]; - - memset(&secBuffer[0], 0, 512); - - int i; - for(i=0;iWrite_AbsoluteSector(getAbsoluteSectFromChain(clustNumber,i), &secBuffer[0]); - } -} - -bool fatDrive::MakeDir(char *dir) { - Bit32u dummyClust, dirClust; - direntry tmpentry; - char dirName[DOS_NAMELENGTH_ASCII]; - char pathName[11]; - - /* Can we even get the name of the directory itself? */ - if(!getEntryName(dir, &dirName[0])) return false; - convToDirFile(&dirName[0], &pathName[0]); - - /* Fail to make directory if already exists */ - if(getDirClustNum(dir, &dummyClust, false)) return false; - - dummyClust = getFirstFreeClust(); - /* No more space */ - if(dummyClust == 0) return false; - - if(!allocateCluster(dummyClust, 0)) return false; - - zeroOutCluster(dummyClust); - - /* Can we find the base directory? */ - if(!getDirClustNum(dir, &dirClust, true)) return false; - - /* Add the new directory to the base directory */ - memset(&tmpentry,0, sizeof(direntry)); - memcpy(&tmpentry.entryname, &pathName[0], 11); - tmpentry.loFirstClust = (Bit16u)(dummyClust & 0xffff); - tmpentry.hiFirstClust = (Bit16u)(dummyClust >> 16); - tmpentry.attrib = DOS_ATTR_DIRECTORY; - addDirectoryEntry(dirClust, tmpentry); - - /* Add the [.] and [..] entries to our new directory*/ - /* [.] entry */ - memset(&tmpentry,0, sizeof(direntry)); - memcpy(&tmpentry.entryname, ". ", 11); - tmpentry.loFirstClust = (Bit16u)(dummyClust & 0xffff); - tmpentry.hiFirstClust = (Bit16u)(dummyClust >> 16); - tmpentry.attrib = DOS_ATTR_DIRECTORY; - addDirectoryEntry(dummyClust, tmpentry); - - /* [..] entry */ - memset(&tmpentry,0, sizeof(direntry)); - memcpy(&tmpentry.entryname, ".. ", 11); - tmpentry.loFirstClust = (Bit16u)(dirClust & 0xffff); - tmpentry.hiFirstClust = (Bit16u)(dirClust >> 16); - tmpentry.attrib = DOS_ATTR_DIRECTORY; - addDirectoryEntry(dummyClust, tmpentry); - - return true; -} - -bool fatDrive::RemoveDir(char *dir) { - Bit32u dummyClust, dirClust; - direntry tmpentry; - char dirName[DOS_NAMELENGTH_ASCII]; - char pathName[11]; - - /* Can we even get the name of the directory itself? */ - if(!getEntryName(dir, &dirName[0])) return false; - convToDirFile(&dirName[0], &pathName[0]); - - /* Get directory starting cluster */ - if(!getDirClustNum(dir, &dummyClust, false)) return false; - - /* Can't remove root directory */ - if(dummyClust == 0) return false; - - /* Get parent directory starting cluster */ - if(!getDirClustNum(dir, &dirClust, true)) return false; - - /* Check to make sure directory is empty */ - Bit32u filecount = 0; - /* Set to 2 to skip first 2 entries, [.] and [..] */ - Bit32s fileidx = 2; - while(directoryBrowse(dummyClust, &tmpentry, fileidx)) { - /* Check for non-deleted files */ - if(tmpentry.entryname[0] != 0xe5) filecount++; - fileidx++; - } - - /* Return if directory is not empty */ - if(filecount > 0) return false; - - /* Find directory entry in parent directory */ - if (dirClust==0) fileidx = 0; // root directory - else fileidx = 2; - bool found = false; - while(directoryBrowse(dirClust, &tmpentry, fileidx)) { - if(memcmp(&tmpentry.entryname, &pathName[0], 11) == 0) { - found = true; - tmpentry.entryname[0] = 0xe5; - directoryChange(dirClust, &tmpentry, fileidx); - deleteClustChain(dummyClust); - - break; - } - fileidx++; - } - - if(!found) return false; - - return true; -} - -bool fatDrive::Rename(char * oldname, char * newname) { - direntry fileEntry1; - Bit32u dirClust1, subEntry1; - if(!getFileDirEntry(oldname, &fileEntry1, &dirClust1, &subEntry1)) return false; - /* File to be renamed really exists */ - - direntry fileEntry2; - Bit32u dirClust2, subEntry2; - - /* Check if file already exists */ - if(!getFileDirEntry(newname, &fileEntry2, &dirClust2, &subEntry2)) { - /* Target doesn't exist, can rename */ - - char dirName2[DOS_NAMELENGTH_ASCII]; - char pathName2[11]; - /* Can we even get the name of the file itself? */ - if(!getEntryName(newname, &dirName2[0])) return false; - convToDirFile(&dirName2[0], &pathName2[0]); - - /* Can we find the base directory? */ - if(!getDirClustNum(newname, &dirClust2, true)) return false; - memcpy(&fileEntry2, &fileEntry1, sizeof(direntry)); - memcpy(&fileEntry2.entryname, &pathName2[0], 11); - addDirectoryEntry(dirClust2, fileEntry2); - - /* Check if file exists now */ - if(!getFileDirEntry(newname, &fileEntry2, &dirClust2, &subEntry2)) return false; - - /* Remove old entry */ - fileEntry1.entryname[0] = 0xe5; - directoryChange(dirClust1, &fileEntry1, subEntry1); - - return true; - } - - /* Target already exists, fail */ - return false; -} - -bool fatDrive::TestDir(char *dir) { - Bit32u dummyClust; - return getDirClustNum(dir, &dummyClust, false); -} - diff --git a/src/dos/drive_iso.cpp b/src/dos/drive_iso.cpp deleted file mode 100644 index 63b49fd..0000000 --- a/src/dos/drive_iso.cpp +++ /dev/null @@ -1,576 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: drive_iso.cpp,v 1.24 2008/09/07 10:55:14 c2woody Exp $ */ - -#include -#include -#include "cdrom.h" -#include "dosbox.h" -#include "dos_system.h" -#include "support.h" -#include "drives.h" - -using namespace std; - -class isoFile : public DOS_File { -public: - isoFile(isoDrive *drive, const char *name, FileStat_Block *stat, Bit32u offset); - bool Read(Bit8u *data, Bit16u *size); - bool Write(Bit8u *data, Bit16u *size); - bool Seek(Bit32u *pos, Bit32u type); - bool Close(); - Bit16u GetInformation(void); -private: - isoDrive *drive; - Bit8u buffer[ISO_FRAMESIZE]; - int cachedSector; - Bit32u fileBegin; - Bit32u filePos; - Bit32u fileEnd; - Bit16u info; -}; - -isoFile::isoFile(isoDrive *drive, const char *name, FileStat_Block *stat, Bit32u offset) -{ - this->drive = drive; - time = stat->time; - date = stat->date; - attr = stat->attr; - fileBegin = offset; - filePos = fileBegin; - fileEnd = fileBegin + stat->size; - cachedSector = -1; - open = true; - this->name = NULL; - SetName(name); -} - -bool isoFile::Read(Bit8u *data, Bit16u *size) -{ - if (filePos + *size > fileEnd) - *size = (Bit16u)(fileEnd - filePos); - - Bit16u nowSize = 0; - int sector = filePos / ISO_FRAMESIZE; - Bit16u sectorPos = (Bit16u)(filePos % ISO_FRAMESIZE); - - if (sector != cachedSector) { - if (drive->readSector(buffer, sector)) cachedSector = sector; - else { *size = 0; cachedSector = -1; } - } - while (nowSize < *size) { - Bit16u remSector = ISO_FRAMESIZE - sectorPos; - Bit16u remSize = *size - nowSize; - if(remSector < remSize) { - memcpy(&data[nowSize], &buffer[sectorPos], remSector); - nowSize += remSector; - sectorPos = 0; - sector++; - cachedSector++; - if (!drive->readSector(buffer, sector)) { - *size = nowSize; - cachedSector = -1; - } - } else { - memcpy(&data[nowSize], &buffer[sectorPos], remSize); - nowSize += remSize; - } - - } - - *size = nowSize; - filePos += *size; - return true; -} - -bool isoFile::Write(Bit8u *data, Bit16u *size) -{ - return false; -} - -bool isoFile::Seek(Bit32u *pos, Bit32u type) -{ - switch (type) { - case DOS_SEEK_SET: - filePos = fileBegin + *pos; - break; - case DOS_SEEK_CUR: - filePos += *pos; - break; - case DOS_SEEK_END: - filePos = fileEnd + *pos; - break; - default: - return false; - } - if (filePos > fileEnd || filePos < fileBegin) - filePos = fileEnd; - - *pos = filePos - fileBegin; - return true; -} - -bool isoFile::Close() -{ - if (refCtr == 1) open = false; - return true; -} - -Bit16u isoFile::GetInformation(void) -{ - return 0x40; // read-only drive -} - -int MSCDEX_RemoveDrive(char driveLetter); -int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit); -void MSCDEX_ReplaceDrive(CDROM_Interface* cdrom, Bit8u subUnit); -bool MSCDEX_HasDrive(char driveLetter); -bool MSCDEX_GetVolumeName(Bit8u subUnit, char* name); - -isoDrive::isoDrive(char driveLetter, const char *fileName, Bit8u mediaid, int &error) -{ - nextFreeDirIterator = 0; - memset(dirIterators, 0, sizeof(dirIterators)); - memset(sectorHashEntries, 0, sizeof(sectorHashEntries)); - memset(&rootEntry, 0, sizeof(isoDirEntry)); - - safe_strncpy(this->fileName, fileName, CROSS_LEN); - error = UpdateMscdex(driveLetter, fileName, subUnit); - - if (!error) { - if (loadImage()) { - strcpy(info, "isoDrive "); - strcat(info, fileName); - this->driveLetter = driveLetter; - this->mediaid = mediaid; - char buffer[32] = { 0 }; - if (!MSCDEX_GetVolumeName(subUnit, buffer)) strcpy(buffer, ""); - Set_Label(buffer,discLabel,true); - - } else if (CDROM_Interface_Image::images[subUnit]->HasDataTrack() == false) { //Audio only cdrom - strcpy(info, "isoDrive "); - strcat(info, fileName); - this->driveLetter = driveLetter; - this->mediaid = mediaid; - char buffer[32] = { 0 }; - strcpy(buffer, "Audio_CD"); - Set_Label(buffer,discLabel,true); - } else error = 6; //Corrupt image - } -} - -isoDrive::~isoDrive() { } - -int isoDrive::UpdateMscdex(char driveLetter, const char* path, Bit8u& subUnit) { - if (MSCDEX_HasDrive(driveLetter)) { - CDROM_Interface_Image* oldCdrom = CDROM_Interface_Image::images[subUnit]; - CDROM_Interface* cdrom = new CDROM_Interface_Image(subUnit); - char pathCopy[CROSS_LEN]; - safe_strncpy(pathCopy, path, CROSS_LEN); - if (!cdrom->SetDevice(pathCopy, 0)) { - CDROM_Interface_Image::images[subUnit] = oldCdrom; - delete cdrom; - return 3; - } - MSCDEX_ReplaceDrive(cdrom, subUnit); - return 0; - } else { - return MSCDEX_AddDrive(driveLetter, path, subUnit); - } -} - -void isoDrive::Activate(void) { - UpdateMscdex(driveLetter, fileName, subUnit); -} - -bool isoDrive::FileOpen(DOS_File **file, char *name, Bit32u flags) -{ - if (flags == OPEN_WRITE) { - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; - } - - isoDirEntry de; - bool success = lookup(&de, name) && !IS_DIR(de.fileFlags); - - if (success) { - FileStat_Block file_stat; - file_stat.size = DATA_LENGTH(de); - file_stat.attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY; - file_stat.date = DOS_PackDate(1900 + de.dateYear, de.dateMonth, de.dateDay); - file_stat.time = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec); - *file = new isoFile(this, name, &file_stat, EXTENT_LOCATION(de) * ISO_FRAMESIZE); - (*file)->flags = flags; - } - return success; -} - -bool isoDrive::FileCreate(DOS_File **file, char *name, Bit16u attributes) -{ - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool isoDrive::FileUnlink(char *name) -{ - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool isoDrive::RemoveDir(char *dir) -{ - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool isoDrive::MakeDir(char *dir) -{ - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool isoDrive::TestDir(char *dir) -{ - isoDirEntry de; - return (lookup(&de, dir) && IS_DIR(de.fileFlags)); -} - -bool isoDrive::FindFirst(char *dir, DOS_DTA &dta, bool fcb_findfirst) -{ - isoDirEntry de; - if (!lookup(&de, dir)) { - DOS_SetError(DOSERR_PATH_NOT_FOUND); - return false; - } - - // get a directory iterator and save its id in the dta - dta.SetDirID((Bit16u)GetDirIterator(&de)); - - Bit8u attr; - char pattern[ISO_MAXPATHNAME]; - dta.GetSearchParams(attr, pattern); - - if (attr == DOS_ATTR_VOLUME) { - if (strlen(discLabel) != 0) { - dta.SetResult(discLabel, 0, 0, 0, DOS_ATTR_VOLUME); - return true; - } else { - DOS_SetError(DOSERR_NO_MORE_FILES); - return false; - } - } else if ((attr & DOS_ATTR_VOLUME) && (*dir == 0) && !fcb_findfirst) { - if (WildFileCmp(discLabel,pattern)) { - // Get Volume Label (DOS_ATTR_VOLUME) and only in basedir and if it matches the searchstring - dta.SetResult(discLabel, 0, 0, 0, DOS_ATTR_VOLUME); - return true; - } - } - - return FindNext(dta); -} - -bool isoDrive::FindNext(DOS_DTA &dta) -{ - Bit8u attr; - char pattern[DOS_NAMELENGTH_ASCII]; - dta.GetSearchParams(attr, pattern); - - int dirIterator = dta.GetDirID(); - - isoDirEntry de; - while (GetNextDirEntry(dirIterator, &de)) { - Bit8u findAttr = 0; - if (IS_DIR(de.fileFlags)) findAttr |= DOS_ATTR_DIRECTORY; - else findAttr |= DOS_ATTR_ARCHIVE; - if (IS_HIDDEN(de.fileFlags)) findAttr |= DOS_ATTR_HIDDEN; - - if (WildFileCmp((char*)de.ident, pattern) - && !(~attr & findAttr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM))) { - - /* file is okay, setup everything to be copied in DTA Block */ - char findName[DOS_NAMELENGTH_ASCII]; - findName[0] = 0; - if(strlen((char*)de.ident) < DOS_NAMELENGTH_ASCII) { - strcpy(findName, (char*)de.ident); - upcase(findName); - } - Bit32u findSize = DATA_LENGTH(de); - Bit16u findDate = DOS_PackDate(1900 + de.dateYear, de.dateMonth, de.dateDay); - Bit16u findTime = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec); - dta.SetResult(findName, findSize, findDate, findTime, findAttr); - return true; - } - } - // after searching the directory, free the iterator - FreeDirIterator(dirIterator); - - DOS_SetError(DOSERR_NO_MORE_FILES); - return false; -} - -bool isoDrive::Rename(char *oldname, char *newname) -{ - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool isoDrive::GetFileAttr(char *name, Bit16u *attr) -{ - *attr = 0; - isoDirEntry de; - bool success = lookup(&de, name); - if (success) { - *attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY; - if (IS_HIDDEN(de.fileFlags)) *attr |= DOS_ATTR_HIDDEN; - if (IS_DIR(de.fileFlags)) *attr |= DOS_ATTR_DIRECTORY; - } - return success; -} - -bool isoDrive::AllocationInfo(Bit16u *bytes_sector, Bit8u *sectors_cluster, Bit16u *total_clusters, Bit16u *free_clusters) -{ - *bytes_sector = 2048; - *sectors_cluster = 1; // cluster size for cdroms ? - *total_clusters = 60000; - *free_clusters = 0; - return true; -} - -bool isoDrive::FileExists(const char *name) -{ - isoDirEntry de; - return (lookup(&de, name) && !IS_DIR(de.fileFlags)); -} - -bool isoDrive::FileStat(const char *name, FileStat_Block *const stat_block) -{ - isoDirEntry de; - bool success = lookup(&de, name); - - if (success) { - stat_block->date = DOS_PackDate(1900 + de.dateYear, de.dateMonth, de.dateDay); - stat_block->time = DOS_PackTime(de.timeHour, de.timeMin, de.timeSec); - stat_block->size = DATA_LENGTH(de); - stat_block->attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY; - if (IS_DIR(de.fileFlags)) stat_block->attr |= DOS_ATTR_DIRECTORY; - } - - return success; -} - -Bit8u isoDrive::GetMediaByte(void) -{ - return mediaid; -} - -bool isoDrive::isRemote(void) -{ - return true; -} - -bool isoDrive::isRemovable(void) -{ - return true; -} - -Bits isoDrive::UnMount(void) { - if(MSCDEX_RemoveDrive(driveLetter)) { - delete this; - return 0; - } - return 2; -} - -int isoDrive::GetDirIterator(const isoDirEntry* de) -{ - int dirIterator = nextFreeDirIterator; - - // get start and end sector of the directory entry (pad end sector if necessary) - dirIterators[dirIterator].currentSector = EXTENT_LOCATION(*de); - dirIterators[dirIterator].endSector = - EXTENT_LOCATION(*de) + DATA_LENGTH(*de) / ISO_FRAMESIZE - 1; - if (DATA_LENGTH(*de) % ISO_FRAMESIZE != 0) - dirIterators[dirIterator].endSector++; - - // reset position and mark as valid - dirIterators[dirIterator].pos = 0; - dirIterators[dirIterator].valid = true; - - // advance to next directory iterator (wrap around if necessary) - nextFreeDirIterator = (nextFreeDirIterator + 1) % MAX_OPENDIRS; - - return dirIterator; -} - -bool isoDrive::GetNextDirEntry(const int dirIteratorHandle, isoDirEntry* de) -{ - bool result = false; - Bit8u* buffer = NULL; - DirIterator& dirIterator = dirIterators[dirIteratorHandle]; - - // check if the directory entry is valid - if (dirIterator.valid && ReadCachedSector(&buffer, dirIterator.currentSector)) { - // check if the next sector has to be read - if ((dirIterator.pos >= ISO_FRAMESIZE) - || (buffer[dirIterator.pos] == 0) - || (dirIterator.pos + buffer[dirIterator.pos] > ISO_FRAMESIZE)) { - - // check if there is another sector available - if (dirIterator.currentSector < dirIterator.endSector) { - dirIterator.pos = 0; - dirIterator.currentSector++; - if (!ReadCachedSector(&buffer, dirIterator.currentSector)) { - return false; - } - } else { - return false; - } - } - // read sector and advance sector pointer - int length = readDirEntry(de, &buffer[dirIterator.pos]); - result = length >= 0; - dirIterator.pos += length; - } - return result; -} - -void isoDrive::FreeDirIterator(const int dirIterator) -{ - dirIterators[dirIterator].valid = false; - - // if this was the last aquired iterator decrement nextFreeIterator - if ((dirIterator + 1) % MAX_OPENDIRS == nextFreeDirIterator) { - nextFreeDirIterator--; - } -} - -bool isoDrive::ReadCachedSector(Bit8u** buffer, const Bit32u sector) -{ - // get hash table entry - int pos = sector % ISO_MAX_HASH_TABLE_SIZE; - SectorHashEntry& he = sectorHashEntries[pos]; - - // check if the entry is valid and contains the correct sector - if (!he.valid || he.sector != sector) { - if (!CDROM_Interface_Image::images[subUnit]->ReadSector(he.data, false, sector)) { - return false; - } - he.valid = true; - he.sector = sector; - } - - *buffer = he.data; - return true; -} - -inline bool isoDrive :: readSector(Bit8u *buffer, Bit32u sector) -{ - return CDROM_Interface_Image::images[subUnit]->ReadSector(buffer, false, sector); -} - -int isoDrive :: readDirEntry(isoDirEntry *de, Bit8u *data) -{ - // copy data into isoDirEntry struct, data[0] = length of DirEntry -// if (data[0] > sizeof(isoDirEntry)) return -1;//check disabled as isoDirentry is currently 258 bytes large. So it always fits - memcpy(de, data, data[0]);//Perharps care about a zero at the end. - - // xa not supported - if (de->extAttrLength != 0) return -1; - // interleaved mode not supported - if (de->fileUnitSize != 0 || de->interleaveGapSize != 0) return -1; - - // modify file identifier for use with dosbox - if ((de->length < 33 + de->fileIdentLength)) return -1; - if (IS_DIR(de->fileFlags)) { - if (de->fileIdentLength == 1 && de->ident[0] == 0) strcpy((char*)de->ident, "."); - else if (de->fileIdentLength == 1 && de->ident[0] == 1) strcpy((char*)de->ident, ".."); - else { - if (de->fileIdentLength > 200) return -1; - de->ident[de->fileIdentLength] = 0; - } - } else { - if (de->fileIdentLength > 200) return -1; - de->ident[de->fileIdentLength] = 0; - // remove any file version identifiers as there are some cdroms that don't have them - strreplace((char*)de->ident, ';', 0); - // if file has no extension remove the trailing dot - size_t tmp = strlen((char*)de->ident); - if (tmp > 0) { - if (de->ident[tmp - 1] == '.') de->ident[tmp - 1] = 0; - } - } - const char* dotpos = strchr((char*)de->ident, '.'); - if (dotpos!=NULL) { - if (dotpos-(char*)de->ident>8) { - strcpy((char*)(&de->ident[8]),dotpos); - } - } - if (strlen((char*)de->ident)>12) de->ident[12]=0; - return de->length; -} - -bool isoDrive :: loadImage() -{ - isoPVD pvd; - dataCD = false; - readSector((Bit8u*)(&pvd), ISO_FIRST_VD); - if (pvd.type != 1 || strncmp((char*)pvd.standardIdent, "CD001", 5) || pvd.version != 1) return false; - if (readDirEntry(&this->rootEntry, pvd.rootEntry)>0) { - dataCD = true; - return true; - } - return false; -} - -bool isoDrive :: lookup(isoDirEntry *de, const char *path) -{ - if (!dataCD) return false; - *de = this->rootEntry; - if (!strcmp(path, "")) return true; - - char isoPath[ISO_MAXPATHNAME]; - safe_strncpy(isoPath, path, ISO_MAXPATHNAME); - strreplace(isoPath, '\\', '/'); - - // iterate over all path elements (name), and search each of them in the current de - for(char* name = strtok(isoPath, "/"); NULL != name; name = strtok(NULL, "/")) { - - bool found = false; - // current entry must be a directory, abort otherwise - if (IS_DIR(de->fileFlags)) { - - // remove the trailing dot if present - size_t nameLength = strlen(name); - if (nameLength > 0) { - if (name[nameLength - 1] == '.') name[nameLength - 1] = 0; - } - - // look for the current path element - int dirIterator = GetDirIterator(de); - while (!found && GetNextDirEntry(dirIterator, de)) { - if (0 == strncasecmp((char*) de->ident, name, ISO_MAX_FILENAME_LENGTH)) { - found = true; - } - } - FreeDirIterator(dirIterator); - } - if (!found) return false; - } - return true; -} diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index 9fb09f3..9b7cf0a 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -1,650 +1,277 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: drive_local.cpp,v 1.79 2009/04/26 18:24:36 qbix79 Exp $ */ - -#include -#include -#include -#include -#include - -#include "dosbox.h" -#include "dos_inc.h" -#include "drives.h" -#include "support.h" -#include "cross.h" -#include "inout.h" - -class localFile : public DOS_File { -public: - localFile(const char* name, FILE * handle); - bool Read(Bit8u * data,Bit16u * size); - bool Write(Bit8u * data,Bit16u * size); - bool Seek(Bit32u * pos,Bit32u type); - bool Close(); - Bit16u GetInformation(void); - bool UpdateDateTimeFromHost(void); - void FlagReadOnlyMedium(void); -private: - FILE * fhandle; - bool read_only_medium; - enum { NONE,READ,WRITE } last_action; -}; - - -bool localDrive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) { -//TODO Maybe care for attributes but not likely - char newname[CROSS_LEN]; - strcpy(newname,basedir); - strcat(newname,name); - CROSS_FILENAME(newname); - char* temp_name = dirCache.GetExpandName(newname); //Can only be used in till a new drive_cache action is preformed */ - /* Test if file exists (so we need to truncate it). don't add to dirCache then */ - bool existing_file=false; - - FILE * test=fopen(temp_name,"rb+"); - if(test) { - fclose(test); - existing_file=true; - - } - - FILE * hand=fopen(temp_name,"wb+"); - if (!hand){ - LOG_MSG("Warning: file creation failed: %s",newname); - return false; - } - - if(!existing_file) dirCache.AddEntry(newname, true); - /* Make the 16 bit device information */ - *file=new localFile(name,hand); - - return true; -} - -bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { - const char* type; - switch (flags &3) { - case OPEN_READ:type="rb"; break; - case OPEN_WRITE:type="rb+"; break; - case OPEN_READWRITE:type="rb+"; break; - default: -//TODO FIX IT - type="rb+"; -// return false; - - }; - char newname[CROSS_LEN]; - strcpy(newname,basedir); - strcat(newname,name); - CROSS_FILENAME(newname); - dirCache.ExpandName(newname); - - FILE * hand=fopen(newname,type); -// Bit32u err=errno; - if (!hand) { - if((flags&3) != OPEN_READ) { - FILE * hmm=fopen(newname,"rb"); - if (hmm) { - fclose(hmm); - LOG_MSG("Warning: file %s exists and failed to open in write mode.\nPlease Remove write-protection",newname); - } - } - return false; - } - - *file=new localFile(name,hand); - (*file)->flags=flags; //for the inheritance flag and maybe check for others. -// (*file)->SetFileName(newname); - return true; -} - -FILE * localDrive::GetSystemFilePtr(char const * const name, char const * const type) { - - char newname[CROSS_LEN]; - strcpy(newname,basedir); - strcat(newname,name); - CROSS_FILENAME(newname); - dirCache.ExpandName(newname); - - return fopen(newname,type); -} - -bool localDrive::GetSystemFilename(char *sysName, char const * const dosName) { - - strcpy(sysName, basedir); - strcat(sysName, dosName); - CROSS_FILENAME(sysName); - dirCache.ExpandName(sysName); - return true; -} - -bool localDrive::FileUnlink(char * name) { - - char newname[CROSS_LEN]; - strcpy(newname,basedir); - strcat(newname,name); - CROSS_FILENAME(newname); - char *fullname = dirCache.GetExpandName(newname); - if (unlink(fullname)) { - //Unlink failed for some reason try finding it. - struct stat buffer; - if(stat(fullname,&buffer)) return false; // File not found. - - FILE* file_writable = fopen(fullname,"rb+"); - if(!file_writable) return false; //No acces ? ERROR MESSAGE NOT SET. FIXME ? - fclose(file_writable); - - //File exists and can technically be deleted, nevertheless it failed. - //This means that the file is probably open by some process. - //See if We have it open. - bool found_file = false; - for(Bitu i = 0;i < DOS_FILES;i++){ - if(Files[i] && Files[i]->IsName(name)) { - Bitu max = DOS_FILES; - while(Files[i]->IsOpen() && max--) { - Files[i]->Close(); - if (Files[i]->RemoveRef()<=0) break; - } - found_file=true; - } - } - if(!found_file) return false; - if (!unlink(fullname)) { - dirCache.DeleteEntry(newname); - return true; - } - return false; - } else { - dirCache.DeleteEntry(newname); - return true; - } - return false; -} - -bool localDrive::FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst) { - - char tempDir[CROSS_LEN]; - strcpy(tempDir,basedir); - strcat(tempDir,_dir); - CROSS_FILENAME(tempDir); - - if (allocation.mediaid==0xF0 ) { - EmptyCache(); //rescan floppie-content on each findfirst - } - - char end[2]={CROSS_FILESPLIT,0}; - if (tempDir[strlen(tempDir)-1]!=CROSS_FILESPLIT) strcat(tempDir,end); - - Bitu id; - if (!dirCache.FindFirst(tempDir,id)) - { - DOS_SetError(DOSERR_PATH_NOT_FOUND); - return false; - } - strcpy(srchInfo[id].srch_dir,tempDir); - dta.SetDirID(id); - - Bit8u sAttr; - dta.GetSearchParams(sAttr,tempDir); - - if (this->isRemote() && this->isRemovable()) { - // cdroms behave a bit different than regular drives - if (sAttr == DOS_ATTR_VOLUME) { - dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); - return true; - } - } else { - if (sAttr == DOS_ATTR_VOLUME) { - if ( strcmp(dirCache.GetLabel(), "") == 0 ) { -// LOG(LOG_DOSMISC,LOG_ERROR)("DRIVELABEL REQUESTED: none present, returned NOLABEL"); -// dta.SetResult("NO_LABEL",0,0,0,DOS_ATTR_VOLUME); -// return true; - DOS_SetError(DOSERR_NO_MORE_FILES); - return false; - } - dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); - return true; - } else if ((sAttr & DOS_ATTR_VOLUME) && (*_dir == 0) && !fcb_findfirst) { - //should check for a valid leading directory instead of 0 - //exists==true if the volume label matches the searchmask and the path is valid - if (WildFileCmp(dirCache.GetLabel(),tempDir)) { - dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); - return true; - } - } - } - return FindNext(dta); -} - -bool localDrive::FindNext(DOS_DTA & dta) { - - char * dir_ent; - struct stat stat_block; - char full_name[CROSS_LEN]; - char dir_entcopy[CROSS_LEN]; - - Bit8u srch_attr;char srch_pattern[DOS_NAMELENGTH_ASCII]; - Bit8u find_attr; - - dta.GetSearchParams(srch_attr,srch_pattern); - Bitu id = dta.GetDirID(); - -again: - if (!dirCache.FindNext(id,dir_ent)) { - DOS_SetError(DOSERR_NO_MORE_FILES); - return false; - } - if(!WildFileCmp(dir_ent,srch_pattern)) goto again; - - strcpy(full_name,srchInfo[id].srch_dir); - strcat(full_name,dir_ent); - - //GetExpandName might indirectly destroy dir_ent (by caching in a new directory - //and due to its design dir_ent might be lost.) - //Copying dir_ent first - strcpy(dir_entcopy,dir_ent); - if (stat(dirCache.GetExpandName(full_name),&stat_block)!=0) { - goto again;//No symlinks and such - } - - if(stat_block.st_mode & S_IFDIR) find_attr=DOS_ATTR_DIRECTORY; - else find_attr=DOS_ATTR_ARCHIVE; - if (~srch_attr & find_attr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM)) goto again; - - /*file is okay, setup everything to be copied in DTA Block */ - char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size; - - if(strlen(dir_entcopy)tm_year+1900,time->tm_mon+1,time->tm_mday); - find_time=DOS_PackTime(time->tm_hour,time->tm_min,time->tm_sec); - } else { - find_time=6; - find_date=4; - } - dta.SetResult(find_name,find_size,find_date,find_time,find_attr); - return true; -} - -bool localDrive::GetFileAttr(char * name,Bit16u * attr) { - char newname[CROSS_LEN]; - strcpy(newname,basedir); - strcat(newname,name); - CROSS_FILENAME(newname); - dirCache.ExpandName(newname); - - struct stat status; - if (stat(newname,&status)==0) { - *attr=DOS_ATTR_ARCHIVE; - if(status.st_mode & S_IFDIR) *attr|=DOS_ATTR_DIRECTORY; - return true; - } - *attr=0; - return false; -} - -bool localDrive::MakeDir(char * dir) { - char newdir[CROSS_LEN]; - strcpy(newdir,basedir); - strcat(newdir,dir); - CROSS_FILENAME(newdir); -#if defined (WIN32) /* MS Visual C++ */ - int temp=mkdir(dirCache.GetExpandName(newdir)); -#else - int temp=mkdir(dirCache.GetExpandName(newdir),0700); -#endif - if (temp==0) dirCache.CacheOut(newdir,true); - - return (temp==0);// || ((temp!=0) && (errno==EEXIST)); -} - -bool localDrive::RemoveDir(char * dir) { - char newdir[CROSS_LEN]; - strcpy(newdir,basedir); - strcat(newdir,dir); - CROSS_FILENAME(newdir); - int temp=rmdir(dirCache.GetExpandName(newdir)); - if (temp==0) dirCache.DeleteEntry(newdir,true); - return (temp==0); -} - -bool localDrive::TestDir(char * dir) { - char newdir[CROSS_LEN]; - strcpy(newdir,basedir); - strcat(newdir,dir); - CROSS_FILENAME(newdir); - dirCache.ExpandName(newdir); - // Skip directory test, if "\" - size_t len = strlen(newdir); - if (len && (newdir[len-1]!='\\')) { - // It has to be a directory ! - struct stat test; - if (stat(newdir,&test)) return false; - if ((test.st_mode & S_IFDIR)==0) return false; - }; - int temp=access(newdir,F_OK); - return (temp==0); -} - -bool localDrive::Rename(char * oldname,char * newname) { - char newold[CROSS_LEN]; - strcpy(newold,basedir); - strcat(newold,oldname); - CROSS_FILENAME(newold); - dirCache.ExpandName(newold); - - char newnew[CROSS_LEN]; - strcpy(newnew,basedir); - strcat(newnew,newname); - CROSS_FILENAME(newnew); - int temp=rename(newold,dirCache.GetExpandName(newnew)); - if (temp==0) dirCache.CacheOut(newnew); - return (temp==0); - -} - -bool localDrive::AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters) { - /* Always report 100 mb free should be enough */ - /* Total size is always 1 gb */ - *_bytes_sector=allocation.bytes_sector; - *_sectors_cluster=allocation.sectors_cluster; - *_total_clusters=allocation.total_clusters; - *_free_clusters=allocation.free_clusters; - return true; -} - -bool localDrive::FileExists(const char* name) { - char newname[CROSS_LEN]; - strcpy(newname,basedir); - strcat(newname,name); - CROSS_FILENAME(newname); - dirCache.ExpandName(newname); - FILE* Temp=fopen(newname,"rb"); - if(Temp==NULL) return false; - fclose(Temp); - return true; -} - -bool localDrive::FileStat(const char* name, FileStat_Block * const stat_block) { - char newname[CROSS_LEN]; - strcpy(newname,basedir); - strcat(newname,name); - CROSS_FILENAME(newname); - dirCache.ExpandName(newname); - struct stat temp_stat; - if(stat(newname,&temp_stat)!=0) return false; - /* Convert the stat to a FileStat */ - struct tm *time; - if((time=localtime(&temp_stat.st_mtime))!=0) { - stat_block->time=DOS_PackTime(time->tm_hour,time->tm_min,time->tm_sec); - stat_block->date=DOS_PackDate(time->tm_year+1900,time->tm_mon+1,time->tm_mday); - } else { - - } - stat_block->size=(Bit32u)temp_stat.st_size; - return true; -} - - -Bit8u localDrive::GetMediaByte(void) { - return allocation.mediaid; -} - -bool localDrive::isRemote(void) { - return false; -} - -bool localDrive::isRemovable(void) { - return false; -} - -Bits localDrive::UnMount(void) { - delete this; - return 0; -} - -localDrive::localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid) { - strcpy(basedir,startdir); - sprintf(info,"local directory %s",startdir); - allocation.bytes_sector=_bytes_sector; - allocation.sectors_cluster=_sectors_cluster; - allocation.total_clusters=_total_clusters; - allocation.free_clusters=_free_clusters; - allocation.mediaid=_mediaid; - - dirCache.SetBaseDir(basedir); -} - - -//TODO Maybe use fflush, but that seemed to fuck up in visual c -bool localFile::Read(Bit8u * data,Bit16u * size) { - if (last_action==WRITE) fseek(fhandle,ftell(fhandle),SEEK_SET); - last_action=READ; - *size=(Bit16u)fread(data,1,*size,fhandle); - /* Fake harddrive motion. Inspector Gadget with soundblaster compatible */ - /* Same for Igor */ - /* hardrive motion => unmask irq 2. Only do it when it's masked as unmasking is realitively heavy to emulate */ - Bit8u mask = IO_Read(0x21); - if(mask & 0x4 ) IO_Write(0x21,mask&0xfb); - return true; -} - -bool localFile::Write(Bit8u * data,Bit16u * size) { - if (last_action==READ) fseek(fhandle,ftell(fhandle),SEEK_SET); - last_action=WRITE; - if(*size==0){ - return (!ftruncate(fileno(fhandle),ftell(fhandle))); - } - else - { - *size=(Bit16u)fwrite(data,1,*size,fhandle); - return true; - } -} - -bool localFile::Seek(Bit32u * pos,Bit32u type) { - int seektype; - switch (type) { - case DOS_SEEK_SET:seektype=SEEK_SET;break; - case DOS_SEEK_CUR:seektype=SEEK_CUR;break; - case DOS_SEEK_END:seektype=SEEK_END;break; - default: - //TODO Give some doserrorcode; - return false;//ERROR - } - int ret=fseek(fhandle,*reinterpret_cast(pos),seektype); - if (ret!=0) { - // Out of file range, pretend everythings ok - // and move file pointer top end of file... ?! (Black Thorne) - fseek(fhandle,0,SEEK_END); - }; -#if 0 - fpos_t temppos; - fgetpos(fhandle,&temppos); - Bit32u * fake_pos=(Bit32u*)&temppos; - *pos=*fake_pos; -#endif - *pos=(Bit32u)ftell(fhandle); - last_action=NONE; - return true; -} - -bool localFile::Close() { - // only close if one reference left - if (refCtr==1) { - if(fhandle) fclose(fhandle); - fhandle = 0; - open = false; - }; - return true; -} - -Bit16u localFile::GetInformation(void) { - return read_only_medium?0x40:0; -} - - -localFile::localFile(const char* _name, FILE * handle) { - fhandle=handle; - struct stat temp_stat; - fstat(fileno(handle),&temp_stat); - struct tm * ltime; - if((ltime=localtime(&temp_stat.st_mtime))!=0) { - time=DOS_PackTime(ltime->tm_hour,ltime->tm_min,ltime->tm_sec); - date=DOS_PackDate(ltime->tm_year+1900,ltime->tm_mon+1,ltime->tm_mday); - } else { - time=1;date=1; - } - attr=DOS_ATTR_ARCHIVE; - last_action=NONE; - read_only_medium=false; - - open=true; - name=0; - SetName(_name); -} - -void localFile::FlagReadOnlyMedium(void) { - read_only_medium = true; -} - -bool localFile::UpdateDateTimeFromHost(void) { - if(!open) return false; - struct stat temp_stat; - fstat(fileno(fhandle),&temp_stat); - struct tm * ltime; - if((ltime=localtime(&temp_stat.st_mtime))!=0) { - time=DOS_PackTime(ltime->tm_hour,ltime->tm_min,ltime->tm_sec); - date=DOS_PackDate(ltime->tm_year+1900,ltime->tm_mon+1,ltime->tm_mday); - } else { - time=1;date=1; - } - return true; -} - - -// ******************************************** -// CDROM DRIVE -// ******************************************** - -int MSCDEX_RemoveDrive(char driveLetter); -int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit); -bool MSCDEX_HasMediaChanged(Bit8u subUnit); -bool MSCDEX_GetVolumeName(Bit8u subUnit, char* name); - - -cdromDrive::cdromDrive(const char driveLetter, const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid, int& error) - :localDrive(startdir,_bytes_sector,_sectors_cluster,_total_clusters,_free_clusters,_mediaid) { - // Init mscdex - error = MSCDEX_AddDrive(driveLetter,startdir,subUnit); - strcpy(info, "CDRom "); - strcat(info, startdir); - this->driveLetter = driveLetter; - // Get Volume Label - char name[32]; - if (MSCDEX_GetVolumeName(subUnit,name)) dirCache.SetLabel(name,true,true); -} - -bool cdromDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { - if ((flags&3)==OPEN_READWRITE) { - flags &= ~OPEN_READWRITE; - } else if ((flags&3)==OPEN_WRITE) { - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; - } - bool retcode = localDrive::FileOpen(file,name,flags); - if(retcode) (dynamic_cast(*file))->FlagReadOnlyMedium(); - return retcode; -} - -bool cdromDrive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) { - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool cdromDrive::FileUnlink(char * name) { - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool cdromDrive::RemoveDir(char * dir) { - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool cdromDrive::MakeDir(char * dir) { - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool cdromDrive::Rename(char * oldname,char * newname) { - DOS_SetError(DOSERR_ACCESS_DENIED); - return false; -} - -bool cdromDrive::GetFileAttr(char * name,Bit16u * attr) { - bool result = localDrive::GetFileAttr(name,attr); - if (result) *attr |= DOS_ATTR_READ_ONLY; - return result; -} - -bool cdromDrive::FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst) { - // If media has changed, reInit drivecache. - if (MSCDEX_HasMediaChanged(subUnit)) { - dirCache.EmptyCache(); - // Get Volume Label - char name[32]; - if (MSCDEX_GetVolumeName(subUnit,name)) dirCache.SetLabel(name,true,true); - } - return localDrive::FindFirst(_dir,dta); -} - -void cdromDrive::SetDir(const char* path) { - // If media has changed, reInit drivecache. - if (MSCDEX_HasMediaChanged(subUnit)) { - dirCache.EmptyCache(); - // Get Volume Label - char name[32]; - if (MSCDEX_GetVolumeName(subUnit,name)) dirCache.SetLabel(name,true,true); - } - localDrive::SetDir(path); -} - -bool cdromDrive::isRemote(void) { - return true; -} - -bool cdromDrive::isRemovable(void) { - return true; -} - -Bits cdromDrive::UnMount(void) { - if(MSCDEX_RemoveDrive(driveLetter)) { - delete this; - return 0; - } - return 2; -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include "dosbox.h" +#include "dos_system.h" +#include "drives.h" +#include "support.h" +#include "cross.h" + + +class localFile : public DOS_File { +public: + localFile(FILE * handle,Bit16u devinfo); + bool Read(Bit8u * data,Bit16u * size); + bool Write(Bit8u * data,Bit16u * size); + bool Seek(Bit32u * pos,Bit32u type); + bool Close(); + Bit16u GetInformation(void); +private: + FILE * fhandle; + Bit16u info; +}; + + +bool localDrive:: FileCreate(DOS_File * * file,char * name,Bit16u attributes) { +//TODO Maybe care for attributes but not likely + char newname[512]; + strcpy(newname,basedir); + strcat(newname,name); + CROSS_FILENAME(newname); + FILE * hand=fopen(newname,"wb+"); + if (!hand) return false; + /* Make the 16 bit device information */ + *file=new localFile(hand,0x202); + return true; +}; + +bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { + char * type; + switch (flags) { + case OPEN_READ:type="rb";break; + case OPEN_WRITE:type="rb+";break; + case OPEN_READWRITE:type="rb+";break; + default: +//TODO FIX IT + type="rb+"; +// return false; + + }; + char newname[512]; + strcpy(newname,basedir); + strcat(newname,name); + CROSS_FILENAME(newname); + FILE * hand=fopen(newname,type); + Bit32u err=errno; + if (!hand) return false; + *file=new localFile(hand,0x202); + return true; +}; + +bool localDrive::FileUnlink(char * name) { + char newname[512]; + strcpy(newname,basedir); + strcat(newname,name); + CROSS_FILENAME(newname); + if (!unlink(newname)) return true; + return false; +}; + + +bool localDrive::FindFirst(char * search,DTA_FindBlock * dta) { + //TODO Find some way for lowcase and highcase drives oneday + char name[512]; + strcpy(name,basedir); + strcat(name,search); + CROSS_FILENAME(name); + char * last=strrchr(name, CROSS_FILESPLIT); + *last=0; + last++; + /* Check the wildcard string for an extension */ + strcpy(wild_name,last); + wild_ext=strrchr(wild_name,'.'); + if (wild_ext) { + *wild_ext++=0; + } + strcpy(directory,name); +/* make sure / is last sign */ + if (pdir) closedir(pdir); + if(directory[(strlen(directory)-1)]!=CROSS_FILESPLIT) strcat(directory, "/"); + if((pdir=opendir(directory))==NULL) return false; + return FindNext(dta); +} + +bool localDrive::FindNext(DTA_FindBlock * dta) { + Bit8u tempattr=0; + struct dirent *tempdata; + struct stat stat_block; + char werkbuffer[512]; + + if(pdir==NULL){ + return false; + }; + start: + if((tempdata=readdir(pdir))==NULL) { + closedir(pdir); + pdir=NULL; + return false; + } + strcpy(werkbuffer,tempdata->d_name); + if (wild_ext) { + char * ext=strrchr(werkbuffer,'.'); + if (!ext) ext="*"; + else *ext++=0; + if(!wildcmp(wild_ext,ext)) goto start; + } + if(!wildcmp(wild_name,werkbuffer)) goto start; + werkbuffer[0]='\0'; + strcpy(werkbuffer,directory); + strcat(werkbuffer,tempdata->d_name); + if(stat(werkbuffer,&stat_block)!=0){ + /*nu is er iets fout!*/ exit(1); + } + if(S_ISDIR(stat_block.st_mode)) tempattr=DOS_ATTR_DIRECTORY; + else tempattr=DOS_ATTR_ARCHIVE; + if(!(dta->sattr & tempattr)) goto start; + /*file is oke so filldtablok */ + if(strlen(tempdata->d_name)<=DOS_NAMELENGTH) strcpy(dta->name,upcase(tempdata->d_name)); + dta->attr=tempattr; + dta->size=(Bit32u) stat_block.st_size; + struct tm *time; + time=localtime(&stat_block.st_mtime); + + dta->time=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */ + dta->date=((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday); + return true; +} + +bool localDrive::GetFileAttr(char * name,Bit16u * attr) { + char newname[512]; + strcpy(newname,basedir); + strcat(newname,name); + CROSS_FILENAME(newname); + FILE * hand=fopen(newname,"rb"); + if (hand) { + fclose(hand); + *attr=DOS_ATTR_ARCHIVE; + return true; + } + *attr=0; + return false; +}; + +bool localDrive::MakeDir(char * dir) { + char newdir[512]; + strcpy(newdir,basedir); + strcat(newdir,dir); + CROSS_FILENAME(newdir); +#if defined (WIN32) /* MS Visual C++ */ + int temp=mkdir(newdir); +#else + int temp=mkdir(newdir,0); +#endif + return (temp==0); +} + +bool localDrive::RemoveDir(char * dir) { + char newdir[512]; + strcpy(newdir,basedir); + strcat(newdir,dir); + int temp=rmdir(newdir); + return (temp==0); +} + +bool localDrive::TestDir(char * dir) { + char newdir[512]; + strcpy(newdir,basedir); + strcat(newdir,dir); + int temp=access(newdir,F_OK); + return (temp==0); +} + +bool localDrive::Rename(char * oldname,char * newname) { + char newold[512]; + strcpy(newold,basedir); + strcat(newold,oldname); + CROSS_FILENAME(newold); + char newnew[512]; + strcpy(newnew,basedir); + strcat(newnew,newnew); + CROSS_FILENAME(newname); + int temp=rename(newold,newnew); + return (temp==0); + +}; + +bool localDrive::FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) { + /* Always report 100 mb free should be enough */ + /* Total size is always 1 gb */ + *bytes=512; + *sectors=127; + *clusters=16513; + *free=1700; + return true; +}; + + +localDrive::localDrive(char * startdir) { + strcpy(basedir,startdir); + sprintf(info,"local directory %s",startdir); + pdir=NULL; +} + + +bool localFile::Read(Bit8u * data,Bit16u * size) { + *size=fread(data,1,*size,fhandle); + return true; +}; + +bool localFile::Write(Bit8u * data,Bit16u * size) { + *size=fwrite(data,1,*size,fhandle); + return true; +} + +bool localFile::Seek(Bit32u * pos,Bit32u type) { + int seektype; + switch (type) { + case DOS_SEEK_SET:seektype=SEEK_SET;break; + case DOS_SEEK_CUR:seektype=SEEK_CUR;break; + case DOS_SEEK_END:seektype=SEEK_END;break; + default: + //TODO Give some doserrorcode; + return false;//ERROR + } + fpos_t temppos; + int ret=fseek(fhandle,*pos,seektype); + fgetpos(fhandle,&temppos); +//TODO Hope we don't encouter files with 64 bits size + Bit32u * fake_pos=(Bit32u*)&temppos; + *pos=*fake_pos; + + return true; +} + +bool localFile::Close() { + fclose(fhandle); + return true; +} + +Bit16u localFile::GetInformation(void) { + return info; +} + +localFile::localFile(FILE * handle,Bit16u devinfo) { + fhandle=handle; + info=devinfo; +} + diff --git a/src/dos/drive_virtual.cpp b/src/dos/drive_virtual.cpp index 8090cf1..b8140e1 100644 --- a/src/dos/drive_virtual.cpp +++ b/src/dos/drive_virtual.cpp @@ -1,275 +1,205 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include "dosbox.h" -#include "dos_inc.h" -#include "drives.h" -#include "support.h" -#include "cross.h" - -struct VFILE_Block { - const char * name; - Bit8u * data; - Bit32u size; - Bit16u date; - Bit16u time; - VFILE_Block * next; -}; - - -static VFILE_Block * first_file; - -void VFILE_Register(const char * name,Bit8u * data,Bit32u size) { - VFILE_Block * new_file=new VFILE_Block; - new_file->name=name; - new_file->data=data; - new_file->size=size; - new_file->date=DOS_PackDate(2002,10,1); - new_file->time=DOS_PackTime(12,34,56); - new_file->next=first_file; - first_file=new_file; -} - -void VFILE_Remove(const char *name) { - VFILE_Block * chan=first_file; - VFILE_Block * * where=&first_file; - while (chan) { - if (strcmp(name,chan->name) == 0) { - *where = chan->next; - if(chan == first_file) first_file = chan->next; - delete chan; - return; - } - where=&chan->next; - chan=chan->next; - } -} - -class Virtual_File : public DOS_File { -public: - Virtual_File(Bit8u * in_data,Bit32u in_size); - bool Read(Bit8u * data,Bit16u * size); - bool Write(Bit8u * data,Bit16u * size); - bool Seek(Bit32u * pos,Bit32u type); - bool Close(); - Bit16u GetInformation(void); -private: - Bit32u file_size; - Bit32u file_pos; - Bit8u * file_data; -}; - - -Virtual_File::Virtual_File(Bit8u * in_data,Bit32u in_size) { - file_size=in_size; - file_data=in_data; - file_pos=0; - date=DOS_PackDate(2002,10,1); - time=DOS_PackTime(12,34,56); - open=true; -} - -bool Virtual_File::Read(Bit8u * data,Bit16u * size) { - Bit32u left=file_size-file_pos; - if (left<=*size) { - memcpy(data,&file_data[file_pos],left); - *size=(Bit16u)left; - } else { - memcpy(data,&file_data[file_pos],*size); - } - file_pos+=*size; - return true; -} - -bool Virtual_File::Write(Bit8u * data,Bit16u * size){ -/* Not really writeable */ - return false; -} - -bool Virtual_File::Seek(Bit32u * new_pos,Bit32u type){ - switch (type) { - case DOS_SEEK_SET: - if (*new_pos<=file_size) file_pos=*new_pos; - else return false; - break; - case DOS_SEEK_CUR: - if ((*new_pos+file_pos)<=file_size) file_pos=*new_pos+file_pos; - else return false; - break; - case DOS_SEEK_END: - if (*new_pos<=file_size) file_pos=file_size-*new_pos; - else return false; - break; - } - *new_pos=file_pos; - return true; -} - -bool Virtual_File::Close(){ - return true; -} - - -Bit16u Virtual_File::GetInformation(void) { - return 0x40; // read-only drive -} - - -Virtual_Drive::Virtual_Drive() { - strcpy(info,"Internal Virtual Drive"); - search_file=0; -} - - -bool Virtual_Drive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { -/* Scan through the internal list of files */ - VFILE_Block * cur_file=first_file; - while (cur_file) { - if (strcasecmp(name,cur_file->name)==0) { - /* We have a match */ - *file=new Virtual_File(cur_file->data,cur_file->size); - (*file)->flags=flags; - return true; - } - cur_file=cur_file->next; - } - return false; -} - -bool Virtual_Drive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) { - return false; -} - -bool Virtual_Drive::FileUnlink(char * name) { - return false; -} - -bool Virtual_Drive::RemoveDir(char * dir) { - return false; -} - -bool Virtual_Drive::MakeDir(char * dir) { - return false; -} - -bool Virtual_Drive::TestDir(char * dir) { - if (!dir[0]) return true; //only valid dir is the empty dir - return false; -} - -bool Virtual_Drive::FileStat(const char* name, FileStat_Block * const stat_block){ - VFILE_Block * cur_file=first_file; - while (cur_file) { - if (strcasecmp(name,cur_file->name)==0) { - stat_block->attr=DOS_ATTR_ARCHIVE; - stat_block->size=cur_file->size; - stat_block->date=DOS_PackDate(2002,10,1); - stat_block->time=DOS_PackTime(12,34,56); - return true; - } - cur_file=cur_file->next; - } - return false; -} - -bool Virtual_Drive::FileExists(const char* name){ - VFILE_Block * cur_file=first_file; - while (cur_file) { - if (strcasecmp(name,cur_file->name)==0) return true; - cur_file=cur_file->next; - } - return false; -} - -bool Virtual_Drive::FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst) { - search_file=first_file; - Bit8u attr;char pattern[DOS_NAMELENGTH_ASCII]; - dta.GetSearchParams(attr,pattern); - if (attr == DOS_ATTR_VOLUME) { - dta.SetResult("DOSBOX",0,0,0,DOS_ATTR_VOLUME); - return true; - } else if ((attr & DOS_ATTR_VOLUME) && !fcb_findfirst) { - if (WildFileCmp("DOSBOX",pattern)) { - dta.SetResult("DOSBOX",0,0,0,DOS_ATTR_VOLUME); - return true; - } - } - return FindNext(dta); -} - -bool Virtual_Drive::FindNext(DOS_DTA & dta) { - Bit8u attr;char pattern[DOS_NAMELENGTH_ASCII]; - dta.GetSearchParams(attr,pattern); - while (search_file) { - if (WildFileCmp(search_file->name,pattern)) { - dta.SetResult(search_file->name,search_file->size,search_file->date,search_file->time,DOS_ATTR_ARCHIVE); - search_file=search_file->next; - return true; - } - search_file=search_file->next; - } - DOS_SetError(DOSERR_NO_MORE_FILES); - return false; -} - -bool Virtual_Drive::GetFileAttr(char * name,Bit16u * attr) { - VFILE_Block * cur_file=first_file; - while (cur_file) { - if (strcasecmp(name,cur_file->name)==0) { - *attr = DOS_ATTR_ARCHIVE; //Maybe readonly ? - return true; - } - cur_file=cur_file->next; - } - return false; -} - -bool Virtual_Drive::Rename(char * oldname,char * newname) { - return false; -} - -bool Virtual_Drive::AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters) { - /* Always report 100 mb free should be enough */ - /* Total size is always 1 gb */ - *_bytes_sector=512; - *_sectors_cluster=127; - *_total_clusters=16513; - *_free_clusters=00; - return true; -} - -Bit8u Virtual_Drive::GetMediaByte(void) { - return 0xF8; -} - -bool Virtual_Drive::isRemote(void) { - return false; -} - -bool Virtual_Drive::isRemovable(void) { - return false; -} - -Bits Virtual_Drive::UnMount(void) { - return 1; -} - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include "dosbox.h" +#include "dos_system.h" +#include "drives.h" +#include "support.h" + +struct VFILE_Block { + char * name; + Bit8u * data; + Bit32u size; + VFILE_Block * next; +}; + + +static VFILE_Block * first_file; + +void VFILE_Register(char * name,Bit8u * data,Bit32u size) { + VFILE_Block * new_file=new VFILE_Block; + new_file->name=name; + new_file->data=data; + new_file->size=size; + new_file->next=first_file; + first_file=new_file; +} + + +class Virtual_File : public DOS_File { +public: + Virtual_File(Bit8u * in_data,Bit32u in_size); + bool Read(Bit8u * data,Bit16u * size); + bool Write(Bit8u * data,Bit16u * size); + bool Seek(Bit32u * pos,Bit32u type); + bool Close(); + Bit16u GetInformation(void); +private: + Bit32u file_size; + Bit32u file_pos; + Bit8u * file_data; +}; + + +Virtual_File::Virtual_File(Bit8u * in_data,Bit32u in_size) { + file_size=in_size; + file_data=in_data; + file_pos=0; +} + +bool Virtual_File::Read(Bit8u * data,Bit16u * size) { + Bit32u left=file_size-file_pos; + if (left<=*size) { + memcpy(data,&file_data[file_pos],left); + *size=(Bit16u)left; + } else { + memcpy(data,&file_data[file_pos],*size); + } + file_pos+=*size; + return true; +}; + +bool Virtual_File::Write(Bit8u * data,Bit16u * size){ +/* Not really writeable */ + return false; +}; + +bool Virtual_File::Seek(Bit32u * new_pos,Bit32u type){ + switch (type) { + case DOS_SEEK_SET: + if (*new_pos<=file_size) file_pos=*new_pos; + else return false; + break; + case DOS_SEEK_CUR: + if ((*new_pos+file_pos)<=file_size) file_pos=*new_pos+file_pos; + else return false; + break; + case DOS_SEEK_END: + if (*new_pos<=file_size) file_pos=file_size-*new_pos; + else return false; + break; + } + *new_pos=file_pos; + return true; +}; + +bool Virtual_File::Close(){ + return true; +}; + + +Bit16u Virtual_File::GetInformation(void) { + return 0; +} + + +Virtual_Drive::Virtual_Drive() { + strcpy(info,"Internal Virtual Drive"); + search_file=0; +} + + +bool Virtual_Drive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { +/* Scan through the internal list of files */ + VFILE_Block * cur_file=first_file; + while (cur_file) { + if (strcasecmp(name,cur_file->name)==0) { + /* We have a match */ + *file=new Virtual_File(cur_file->data,cur_file->size); + return true; + } + cur_file=cur_file->next; + } + return false; +} + +bool Virtual_Drive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) { + return false; +} + +bool Virtual_Drive::FileUnlink(char * name) { + return false; +} + +bool Virtual_Drive::RemoveDir(char * dir) { + return false; +} + +bool Virtual_Drive::MakeDir(char * dir) { + return false; +} + +bool Virtual_Drive::TestDir(char * dir) { + return false; +} + +static void FillDTABlock(DTA_FindBlock * dta,VFILE_Block * fill_file) { + strcpy(dta->name,fill_file->name); + dta->size=fill_file->size; + dta->attr=DOS_ATTR_ARCHIVE; + dta->time=2; + dta->date=6; +} + +bool Virtual_Drive::FindFirst(char * search,DTA_FindBlock * dta) { + search_file=first_file; + strcpy(search_string,search); + while (search_file) { + if (wildcmp(search_string,search_file->name)) { + FillDTABlock(dta,search_file); + search_file=search_file->next; + return true; + } + search_file=search_file->next; + } + return false; +} + +bool Virtual_Drive::FindNext(DTA_FindBlock * dta) { + while (search_file) { + if (wildcmp(search_string,search_file->name)) { + FillDTABlock(dta,search_file); + search_file=search_file->next; + return true; + } + search_file=search_file->next; + } + return false; +} + +bool Virtual_Drive::GetFileAttr(char * name,Bit16u * attr) { + return false; +} + +bool Virtual_Drive::Rename(char * oldname,char * newname) { + return false; +} + +bool Virtual_Drive::FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) { + /* Always report 100 mb free should be enough */ + /* Total size is always 1 gb */ + *bytes=512; + *sectors=127; + *clusters=16513; + *free=00; + return true; +} + diff --git a/src/dos/drives.cpp b/src/dos/drives.cpp index 55b5673..2a71172 100644 --- a/src/dos/drives.cpp +++ b/src/dos/drives.cpp @@ -1,229 +1,31 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: drives.cpp,v 1.14 2008/09/07 10:55:14 c2woody Exp $ */ - -#include "dosbox.h" -#include "dos_system.h" -#include "drives.h" -#include "mapper.h" -#include "support.h" - -bool WildFileCmp(const char * file, const char * wild) -{ - char file_name[9]; - char file_ext[4]; - char wild_name[9]; - char wild_ext[4]; - const char * find_ext; - Bitu r; - - strcpy(file_name," "); - strcpy(file_ext," "); - strcpy(wild_name," "); - strcpy(wild_ext," "); - - find_ext=strrchr(file,'.'); - if (find_ext) { - Bitu size=(Bitu)(find_ext-file); - if (size>8) size=8; - memcpy(file_name,file,size); - find_ext++; - memcpy(file_ext,find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext)); - } else { - memcpy(file_name,file,(strlen(file) > 8) ? 8 : strlen(file)); - } - upcase(file_name);upcase(file_ext); - find_ext=strrchr(wild,'.'); - if (find_ext) { - Bitu size=(Bitu)(find_ext-wild); - if (size>8) size=8; - memcpy(wild_name,wild,size); - find_ext++; - memcpy(wild_ext,find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext)); - } else { - memcpy(wild_name,wild,(strlen(wild) > 8) ? 8 : strlen(wild)); - } - upcase(wild_name);upcase(wild_ext); - /* Names are right do some checking */ - r=0; - while (r<8) { - if (wild_name[r]=='*') goto checkext; - if (wild_name[r]!='?' && wild_name[r]!=file_name[r]) return false; - r++; - } -checkext: - r=0; - while (r<3) { - if (wild_ext[r]=='*') return true; - if (wild_ext[r]!='?' && wild_ext[r]!=file_ext[r]) return false; - r++; - } - return true; -} - -void Set_Label(char const * const input, char * const output, bool cdrom) { - Bitu togo = 8; - Bitu vnamePos = 0; - Bitu labelPos = 0; - bool point = false; - - //spacepadding the filenamepart to include spaces after the terminating zero is more closely to the specs. (not doing this now) - // HELLO\0' '' ' - - while (togo > 0) { - if (input[vnamePos]==0) break; - if (!point && (input[vnamePos]=='.')) { togo=4; point=true; } - - //another mscdex quirk. Label is not always uppercase. (Daggerfall) - output[labelPos] = (cdrom?input[vnamePos]:toupper(input[vnamePos])); - - labelPos++; vnamePos++; - togo--; - if ((togo==0) && !point) { - if (input[vnamePos]=='.') vnamePos++; - output[labelPos]='.'; labelPos++; point=true; togo=3; - } - }; - output[labelPos]=0; - - //Remove trailing dot. except when on cdrom and filename is exactly 8 (9 including the dot) letters. MSCDEX feature/bug (fifa96 cdrom detection) - if((labelPos > 0) && (output[labelPos-1] == '.') && !(cdrom && labelPos ==9)) - output[labelPos-1] = 0; -} - - - -DOS_Drive::DOS_Drive() { - curdir[0]=0; - info[0]=0; -} - -char * DOS_Drive::GetInfo(void) { - return info; -} - -// static members variables -int DriveManager::currentDrive; -DriveManager::DriveInfo DriveManager::driveInfos[26]; - -void DriveManager::AppendDisk(int drive, DOS_Drive* disk) { - driveInfos[drive].disks.push_back(disk); -} - -void DriveManager::InitializeDrive(int drive) { - currentDrive = drive; - DriveInfo& driveInfo = driveInfos[currentDrive]; - if (driveInfo.disks.size() > 0) { - driveInfo.currentDisk = 0; - DOS_Drive* disk = driveInfo.disks[driveInfo.currentDisk]; - Drives[currentDrive] = disk; - disk->Activate(); - } -} - -/* -void DriveManager::CycleDrive(bool pressed) { - if (!pressed) return; - - // do one round through all drives or stop at the next drive with multiple disks - int oldDrive = currentDrive; - do { - currentDrive = (currentDrive + 1) % DOS_DRIVES; - int numDisks = driveInfos[currentDrive].disks.size(); - if (numDisks > 1) break; - } while (currentDrive != oldDrive); -} - -void DriveManager::CycleDisk(bool pressed) { - if (!pressed) return; - - int numDisks = driveInfos[currentDrive].disks.size(); - if (numDisks > 1) { - // cycle disk - int currentDisk = driveInfos[currentDrive].currentDisk; - DOS_Drive* oldDisk = driveInfos[currentDrive].disks[currentDisk]; - currentDisk = (currentDisk + 1) % numDisks; - DOS_Drive* newDisk = driveInfos[currentDrive].disks[currentDisk]; - driveInfos[currentDrive].currentDisk = currentDisk; - - // copy working directory, acquire system resources and finally switch to next drive - strcpy(newDisk->curdir, oldDisk->curdir); - newDisk->Activate(); - Drives[currentDrive] = newDisk; - } -} -*/ - -void DriveManager::CycleAllDisks(void) { - for (int idrive=0; idrive 1) { - // cycle disk - int currentDisk = driveInfos[idrive].currentDisk; - DOS_Drive* oldDisk = driveInfos[idrive].disks[currentDisk]; - currentDisk = (currentDisk + 1) % numDisks; - DOS_Drive* newDisk = driveInfos[idrive].disks[currentDisk]; - driveInfos[idrive].currentDisk = currentDisk; - - // copy working directory, acquire system resources and finally switch to next drive - strcpy(newDisk->curdir, oldDisk->curdir); - newDisk->Activate(); - Drives[idrive] = newDisk; - LOG_MSG("Drive %c: disk %d of %d now active", 'A'+idrive, currentDisk+1, numDisks); - } - } -} - -int DriveManager::UnmountDrive(int drive) { - int result = 0; - // unmanaged drive - if (driveInfos[drive].disks.size() == 0) { - result = Drives[drive]->UnMount(); - } else { - // managed drive - int currentDisk = driveInfos[drive].currentDisk; - result = driveInfos[drive].disks[currentDisk]->UnMount(); - // only delete on success, current disk set to NULL because of UnMount - if (result == 0) { - driveInfos[drive].disks[currentDisk] = NULL; - for (int i = 0; i < (int)driveInfos[drive].disks.size(); i++) { - delete driveInfos[drive].disks[i]; - } - driveInfos[drive].disks.clear(); - } - } - - return result; -} - -void DriveManager::Init(Section* /* sec */) { - - // setup driveInfos structure - currentDrive = 0; - for(int i = 0; i < DOS_DRIVES; i++) { - driveInfos[i].currentDisk = 0; - } - -// MAPPER_AddHandler(&CycleDisk, MK_f3, MMOD1, "cycledisk", "Cycle Disk"); -// MAPPER_AddHandler(&CycleDrive, MK_f3, MMOD2, "cycledrive", "Cycle Drv"); -} - -void DRIVES_Init(Section* sec) { - DriveManager::Init(sec); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "dos_system.h" +#include "drives.h" + + +DOS_Drive::DOS_Drive() { + curdir[0]=0; + info[0]=0; +} + +char * DOS_Drive::GetInfo(void) { + return info; +} diff --git a/src/dos/drives.h b/src/dos/drives.h index 2148646..a2dcf75 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -1,399 +1,71 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: drives.h,v 1.40 2009/02/01 14:24:36 qbix79 Exp $ */ - -#ifndef _DRIVES_H__ -#define _DRIVES_H__ - -#include -#include -#include "dos_system.h" -#include "shell.h" /* for DOS_Shell */ -#include "bios_disk.h" /* for fatDrive */ - -bool WildFileCmp(const char * file, const char * wild); -void Set_Label(char const * const input, char * const output, bool cdrom); - -class DriveManager { -public: - static void AppendDisk(int drive, DOS_Drive* disk); - static void InitializeDrive(int drive); - static int UnmountDrive(int drive); -// static void CycleDrive(bool pressed); -// static void CycleDisk(bool pressed); - static void CycleAllDisks(void); - static void Init(Section* sec); - -private: - static struct DriveInfo { - std::vector disks; - Bit32u currentDisk; - } driveInfos[DOS_DRIVES]; - - static int currentDrive; -}; - -class localDrive : public DOS_Drive { -public: - localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid); - virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags); - virtual FILE *GetSystemFilePtr(char const * const name, char const * const type); - virtual bool GetSystemFilename(char* sysName, char const * const dosName); - virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); - virtual bool FileUnlink(char * name); - virtual bool RemoveDir(char * dir); - virtual bool MakeDir(char * dir); - virtual bool TestDir(char * dir); - virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false); - virtual bool FindNext(DOS_DTA & dta); - virtual bool GetFileAttr(char * name,Bit16u * attr); - virtual bool Rename(char * oldname,char * newname); - virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters); - virtual bool FileExists(const char* name); - virtual bool FileStat(const char* name, FileStat_Block * const stat_block); - virtual Bit8u GetMediaByte(void); - virtual bool isRemote(void); - virtual bool isRemovable(void); - virtual Bits UnMount(void); -private: - char basedir[CROSS_LEN]; - friend void DOS_Shell::CMD_SUBST(char* args); - struct { - char srch_dir[CROSS_LEN]; - } srchInfo[MAX_OPENDIRS]; - - struct { - Bit16u bytes_sector; - Bit8u sectors_cluster; - Bit16u total_clusters; - Bit16u free_clusters; - Bit8u mediaid; - } allocation; -}; - -#ifdef _MSC_VER -#pragma pack (1) -#endif -struct bootstrap { - Bit8u nearjmp[3]; - Bit8u oemname[8]; - Bit16u bytespersector; - Bit8u sectorspercluster; - Bit16u reservedsectors; - Bit8u fatcopies; - Bit16u rootdirentries; - Bit16u totalsectorcount; - Bit8u mediadescriptor; - Bit16u sectorsperfat; - Bit16u sectorspertrack; - Bit16u headcount; - /* 32-bit FAT extensions */ - Bit32u hiddensectorcount; - Bit32u totalsecdword; - Bit8u bootcode[474]; - Bit8u magic1; /* 0x55 */ - Bit8u magic2; /* 0xaa */ -} GCC_ATTRIBUTE(packed); - -struct direntry { - Bit8u entryname[11]; - Bit8u attrib; - Bit8u NTRes; - Bit8u milliSecondStamp; - Bit16u crtTime; - Bit16u crtDate; - Bit16u accessDate; - Bit16u hiFirstClust; - Bit16u modTime; - Bit16u modDate; - Bit16u loFirstClust; - Bit32u entrysize; -} GCC_ATTRIBUTE(packed); - -struct partTable { - Bit8u booter[446]; - struct { - Bit8u bootflag; - Bit8u beginchs[3]; - Bit8u parttype; - Bit8u endchs[3]; - Bit32u absSectStart; - Bit32u partSize; - } pentry[4]; - Bit8u magic1; /* 0x55 */ - Bit8u magic2; /* 0xaa */ -} GCC_ATTRIBUTE(packed); - -#ifdef _MSC_VER -#pragma pack () -#endif - -class fatDrive : public DOS_Drive { -public: - fatDrive(const char * sysFilename, Bit32u bytesector, Bit32u cylsector, Bit32u headscyl, Bit32u cylinders, Bit32u startSector); - virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags); - virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); - virtual bool FileUnlink(char * name); - virtual bool RemoveDir(char * dir); - virtual bool MakeDir(char * dir); - virtual bool TestDir(char * dir); - virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false); - virtual bool FindNext(DOS_DTA & dta); - virtual bool GetFileAttr(char * name,Bit16u * attr); - virtual bool Rename(char * oldname,char * newname); - virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters); - virtual bool FileExists(const char* name); - virtual bool FileStat(const char* name, FileStat_Block * const stat_block); - virtual Bit8u GetMediaByte(void); - virtual bool isRemote(void); - virtual bool isRemovable(void); - virtual Bits UnMount(void); -public: - Bit32u getAbsoluteSectFromBytePos(Bit32u startClustNum, Bit32u bytePos); - Bit32u getSectorSize(void); - Bit32u getAbsoluteSectFromChain(Bit32u startClustNum, Bit32u logicalSector); - bool allocateCluster(Bit32u useCluster, Bit32u prevCluster); - Bit32u appendCluster(Bit32u startCluster); - void deleteClustChain(Bit32u startCluster); - Bit32u getFirstFreeClust(void); - bool directoryBrowse(Bit32u dirClustNumber, direntry *useEntry, Bit32s entNum); - bool directoryChange(Bit32u dirClustNumber, direntry *useEntry, Bit32s entNum); - imageDisk *loadedDisk; - bool created_succesfully; -private: - Bit32u getClusterValue(Bit32u clustNum); - void setClusterValue(Bit32u clustNum, Bit32u clustValue); - Bit32u getClustFirstSect(Bit32u clustNum); - bool FindNextInternal(Bit32u dirClustNumber, DOS_DTA & dta, direntry *foundEntry); - bool getDirClustNum(char * dir, Bit32u * clustNum, bool parDir); - bool getFileDirEntry(char const * const filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry); - bool addDirectoryEntry(Bit32u dirClustNumber, direntry useEntry); - void zeroOutCluster(Bit32u clustNumber); - bool getEntryName(char *fullname, char *entname); - friend void DOS_Shell::CMD_SUBST(char* args); - struct { - char srch_dir[CROSS_LEN]; - } srchInfo[MAX_OPENDIRS]; - - struct { - Bit16u bytes_sector; - Bit8u sectors_cluster; - Bit16u total_clusters; - Bit16u free_clusters; - Bit8u mediaid; - } allocation; - - bootstrap bootbuffer; - Bit8u fattype; - Bit32u CountOfClusters; - Bit32u partSectOff; - Bit32u firstDataSector; - Bit32u firstRootDirSect; - - Bit32u cwdDirCluster; - Bit32u dirPosition; /* Position in directory search */ -}; - - -class cdromDrive : public localDrive -{ -public: - cdromDrive(const char driveLetter, const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid, int& error); - virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags); - virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); - virtual bool FileUnlink(char * name); - virtual bool RemoveDir(char * dir); - virtual bool MakeDir(char * dir); - virtual bool Rename(char * oldname,char * newname); - virtual bool GetFileAttr(char * name,Bit16u * attr); - virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false); - virtual void SetDir(const char* path); - virtual bool isRemote(void); - virtual bool isRemovable(void); - virtual Bits UnMount(void); -private: - Bit8u subUnit; - char driveLetter; -}; - -#ifdef _MSC_VER -#pragma pack (1) -#endif -struct isoPVD { - Bit8u type; - Bit8u standardIdent[5]; - Bit8u version; - Bit8u unused1; - Bit8u systemIdent[32]; - Bit8u volumeIdent[32]; - Bit8u unused2[8]; - Bit32u volumeSpaceSizeL; - Bit32u volumeSpaceSizeM; - Bit8u unused3[32]; - Bit16u volumeSetSizeL; - Bit16u volumeSetSizeM; - Bit16u volumeSeqNumberL; - Bit16u volumeSeqNumberM; - Bit16u logicBlockSizeL; - Bit16u logicBlockSizeM; - Bit32u pathTableSizeL; - Bit32u pathTableSizeM; - Bit32u locationPathTableL; - Bit32u locationOptPathTableL; - Bit32u locationPathTableM; - Bit32u locationOptPathTableM; - Bit8u rootEntry[34]; - Bit32u unused4[1858]; -} GCC_ATTRIBUTE(packed); - -struct isoDirEntry { - Bit8u length; - Bit8u extAttrLength; - Bit32u extentLocationL; - Bit32u extentLocationM; - Bit32u dataLengthL; - Bit32u dataLengthM; - Bit8u dateYear; - Bit8u dateMonth; - Bit8u dateDay; - Bit8u timeHour; - Bit8u timeMin; - Bit8u timeSec; - Bit8u timeZone; - Bit8u fileFlags; - Bit8u fileUnitSize; - Bit8u interleaveGapSize; - Bit16u VolumeSeqNumberL; - Bit16u VolumeSeqNumberM; - Bit8u fileIdentLength; - Bit8u ident[222]; -} GCC_ATTRIBUTE(packed); - -#ifdef _MSC_VER -#pragma pack () -#endif - -#if defined (WORDS_BIGENDIAN) -#define EXTENT_LOCATION(de) ((de).extentLocationM) -#define DATA_LENGTH(de) ((de).dataLengthM) -#else -#define EXTENT_LOCATION(de) ((de).extentLocationL) -#define DATA_LENGTH(de) ((de).dataLengthL) -#endif - -#define ISO_FRAMESIZE 2048 -#define ISO_DIRECTORY 2 -#define ISO_HIDDEN 1 -#define ISO_MAX_FILENAME_LENGTH 37 -#define ISO_MAXPATHNAME 256 -#define ISO_FIRST_VD 16 -#define IS_DIR(fileFlags) (fileFlags & ISO_DIRECTORY) -#define IS_HIDDEN(fileFlags) (fileFlags & ISO_HIDDEN) -#define ISO_MAX_HASH_TABLE_SIZE 100 - -class isoDrive : public DOS_Drive { -public: - isoDrive(char driveLetter, const char* device_name, Bit8u mediaid, int &error); - ~isoDrive(); - virtual bool FileOpen(DOS_File **file, char *name, Bit32u flags); - virtual bool FileCreate(DOS_File **file, char *name, Bit16u attributes); - virtual bool FileUnlink(char *name); - virtual bool RemoveDir(char *dir); - virtual bool MakeDir(char *dir); - virtual bool TestDir(char *dir); - virtual bool FindFirst(char *_dir, DOS_DTA &dta, bool fcb_findfirst); - virtual bool FindNext(DOS_DTA &dta); - virtual bool GetFileAttr(char *name, Bit16u *attr); - virtual bool Rename(char * oldname,char * newname); - virtual bool AllocationInfo(Bit16u *bytes_sector, Bit8u *sectors_cluster, Bit16u *total_clusters, Bit16u *free_clusters); - virtual bool FileExists(const char *name); - virtual bool FileStat(const char *name, FileStat_Block *const stat_block); - virtual Bit8u GetMediaByte(void); - virtual void EmptyCache(void){} - virtual bool isRemote(void); - virtual bool isRemovable(void); - virtual Bits UnMount(void); - bool readSector(Bit8u *buffer, Bit32u sector); - virtual char const* GetLabel(void) {return discLabel;}; - virtual void Activate(void); -private: - int readDirEntry(isoDirEntry *de, Bit8u *data); - bool loadImage(); - bool lookupSingle(isoDirEntry *de, const char *name, Bit32u sectorStart, Bit32u length); - bool lookup(isoDirEntry *de, const char *path); - int UpdateMscdex(char driveLetter, const char* physicalPath, Bit8u& subUnit); - int GetDirIterator(const isoDirEntry* de); - bool GetNextDirEntry(const int dirIterator, isoDirEntry* de); - void FreeDirIterator(const int dirIterator); - bool ReadCachedSector(Bit8u** buffer, const Bit32u sector); - - struct DirIterator { - bool valid; - Bit32u currentSector; - Bit32u endSector; - Bit32u pos; - } dirIterators[MAX_OPENDIRS]; - - int nextFreeDirIterator; - - struct SectorHashEntry { - bool valid; - Bit32u sector; - Bit8u data[ISO_FRAMESIZE]; - } sectorHashEntries[ISO_MAX_HASH_TABLE_SIZE]; - - bool dataCD; - isoDirEntry rootEntry; - Bit8u mediaid; - char fileName[CROSS_LEN]; - Bit8u subUnit; - char driveLetter; - char discLabel[32]; -}; - -struct VFILE_Block; - -class Virtual_Drive: public DOS_Drive { -public: - Virtual_Drive(); - bool FileOpen(DOS_File * * file,char * name,Bit32u flags); - bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); - bool FileUnlink(char * name); - bool RemoveDir(char * dir); - bool MakeDir(char * dir); - bool TestDir(char * dir); - bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst); - bool FindNext(DOS_DTA & dta); - bool GetFileAttr(char * name,Bit16u * attr); - bool Rename(char * oldname,char * newname); - bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters); - bool FileExists(const char* name); - bool FileStat(const char* name, FileStat_Block* const stat_block); - Bit8u GetMediaByte(void); - void EmptyCache(void){} - bool isRemote(void); - virtual bool isRemovable(void); - virtual Bits UnMount(void); -private: - VFILE_Block * search_file; -}; - - - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DRIVES_H__ +#define _DRIVES_H__ + +#include +#include + + +class localDrive : public DOS_Drive { +public: + localDrive(char * startdir); + bool FileOpen(DOS_File * * file,char * name,Bit32u flags); + bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); + bool FileUnlink(char * name); + bool RemoveDir(char * dir); + bool MakeDir(char * dir); + bool TestDir(char * dir); + bool FindFirst(char * search,DTA_FindBlock * dta); + bool FindNext(DTA_FindBlock * dta); + bool GetFileAttr(char * name,Bit16u * attr); + bool Rename(char * oldname,char * newname); + bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free); +private: + bool FillDTABlock(DTA_FindBlock * dta); + char basedir[512]; + char directory[512]; + char wild_name[15]; + char * wild_ext; + DIR *pdir; +}; + +struct VFILE_Block; + + +class Virtual_Drive: public DOS_Drive { +public: + Virtual_Drive(); + bool FileOpen(DOS_File * * file,char * name,Bit32u flags); + bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); + bool FileUnlink(char * name); + bool RemoveDir(char * dir); + bool MakeDir(char * dir); + bool TestDir(char * dir); + bool FindFirst(char * search,DTA_FindBlock * dta); + bool FindNext(DTA_FindBlock * dta); + bool GetFileAttr(char * name,Bit16u * attr); + bool Rename(char * oldname,char * newname); + bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free); +private: + VFILE_Block * search_file; + char search_string[255]; +}; + +#endif diff --git a/src/dos/scsidefs.h b/src/dos/scsidefs.h deleted file mode 100644 index 74aa6e7..0000000 --- a/src/dos/scsidefs.h +++ /dev/null @@ -1,288 +0,0 @@ -/* Got it from Bochs */ - -///////////////////////////////////////////////////////////////////////// -// $Id: scsidefs.h,v 1.3 2005/07/21 12:49:52 qbix79 Exp $ -///////////////////////////////////////////////////////////////////////// -// -// -// iodev/scsidefs.h -// $Id: scsidefs.h,v 1.3 2005/07/21 12:49:52 qbix79 Exp $ -// -// This file was copied from ... ? -// - -//*************************************************************************** -// -// Name: SCSIDEFS.H -// -// Description: SCSI definitions ('C' Language) -// -//*************************************************************************** - -//*************************************************************************** -// %%% TARGET STATUS VALUES %%% -//*************************************************************************** -#define STATUS_GOOD 0x00 // Status Good -#define STATUS_CHKCOND 0x02 // Check Condition -#define STATUS_CONDMET 0x04 // Condition Met -#define STATUS_BUSY 0x08 // Busy -#define STATUS_INTERM 0x10 // Intermediate -#define STATUS_INTCDMET 0x14 // Intermediate-condition met -#define STATUS_RESCONF 0x18 // Reservation conflict -#define STATUS_COMTERM 0x22 // Command Terminated -#define STATUS_QFULL 0x28 // Queue full - -//*************************************************************************** -// %%% SCSI MISCELLANEOUS EQUATES %%% -//*************************************************************************** -#define MAXLUN 7 // Maximum Logical Unit Id -#define MAXTARG 7 // Maximum Target Id -#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs -#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's - -//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ -// -// %%% SCSI COMMAND OPCODES %%% -// -///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ - -//*************************************************************************** -// %%% Commands for all Device Types %%% -//*************************************************************************** -#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) -#define SCSI_COMPARE 0x39 // Compare (O) -#define SCSI_COPY 0x18 // Copy (O) -#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) -#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) -#define SCSI_LOG_SELECT 0x4C // Log Select (O) -#define SCSI_LOG_SENSE 0x4D // Log Sense (O) -#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) -#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) -#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) -#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) -#define SCSI_READ_BUFF 0x3C // Read Buffer (O) -#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) -#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) -#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) -#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) - -//*************************************************************************** -// %%% Commands Unique to Direct Access Devices %%% -//*************************************************************************** -#define SCSI_COMPARE 0x39 // Compare (O) -#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) -#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) -#define SCSI_PREFETCH 0x34 // Prefetch (O) -#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) -#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) -#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) -#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) -#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) -#define SCSI_READ_LONG 0x3E // Read Long (O) -#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) -#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) -#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) -#define SCSI_REZERO 0x01 // Rezero Unit (O) -#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) -#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) -#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) -#define SCSI_SEEK6 0x0B // Seek 6-Byte (O) -#define SCSI_SEEK10 0x2B // Seek 10-Byte (O) -#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) -#define SCSI_SET_LIMIT 0x33 // Set Limits (O) -#define SCSI_START_STP 0x1B // Start/Stop Unit (O) -#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) -#define SCSI_VERIFY 0x2F // Verify (O) -#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) -#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) -#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) -#define SCSI_WRITE_LONG 0x3F // Write Long (O) -#define SCSI_WRITE_SAME 0x41 // Write Same (O) - -//*************************************************************************** -// %%% Commands Unique to Sequential Access Devices %%% -//*************************************************************************** -#define SCSI_ERASE 0x19 // Erase (MANDATORY) -#define SCSI_LOAD_UN 0x1B // Load/Unload (O) -#define SCSI_LOCATE 0x2B // Locate (O) -#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) -#define SCSI_READ_POS 0x34 // Read Position (O) -#define SCSI_READ_REV 0x0F // Read Reverse (O) -#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) -#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) -#define SCSI_REWIND 0x01 // Rewind (MANDATORY) -#define SCSI_SPACE 0x11 // Space (MANDATORY) -#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) -#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) - -//*************************************************************************** -// %%% Commands Unique to Printer Devices %%% -//*************************************************************************** -#define SCSI_PRINT 0x0A // Print (MANDATORY) -#define SCSI_SLEW_PNT 0x0B // Slew and Print (O) -#define SCSI_STOP_PNT 0x1B // Stop Print (O) -#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) - -//*************************************************************************** -// %%% Commands Unique to Processor Devices %%% -//*************************************************************************** -#define SCSI_RECEIVE 0x08 // Receive (O) -#define SCSI_SEND 0x0A // Send (O) - -//*************************************************************************** -// %%% Commands Unique to Write-Once Devices %%% -//*************************************************************************** -#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) -#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) -#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) -#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) -#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) -#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) -#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) -#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) -#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) -#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) -#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) -#define SCSI_WRITE12 0xAA // Write 12-Byte (O) -#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) -#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) - -//*************************************************************************** -// %%% Commands Unique to CD-ROM Devices %%% -//*************************************************************************** -#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) -#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) -#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) -#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) -#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) -#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) -#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) -#define SCSI_READHEADER 0x44 // Read Header (O) -#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) -#define SCSI_READ_TOC 0x43 // Read TOC (O) - -//*************************************************************************** -// %%% Commands Unique to Scanner Devices %%% -//*************************************************************************** -#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) -#define SCSI_GETWINDOW 0x25 // Get Window (O) -#define SCSI_OBJECTPOS 0x31 // Object Postion (O) -#define SCSI_SCAN 0x1B // Scan (O) -#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) - -//*************************************************************************** -// %%% Commands Unique to Optical Memory Devices %%% -//*************************************************************************** -#define SCSI_UpdateBlk 0x3D // Update Block (O) - -//*************************************************************************** -// %%% Commands Unique to Medium Changer Devices %%% -//*************************************************************************** -#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) -#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) -#define SCSI_POSTOELEM 0x2B // Position to Element (O) -#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) -#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) - -//*************************************************************************** -// %%% Commands Unique to Communication Devices %%% -//*************************************************************************** -#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) -#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) -#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) -#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) -#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) -#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) - -//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ -// -// %%% END OF SCSI COMMAND OPCODES %%% -// -///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ - -//*************************************************************************** -// %%% Request Sense Data Format %%% -//*************************************************************************** -typedef struct { - - BYTE ErrorCode; // Error Code (70H or 71H) - BYTE SegmentNum; // Number of current segment descriptor - BYTE SenseKey; // Sense Key(See bit definitions too) - BYTE InfoByte0; // Information MSB - BYTE InfoByte1; // Information MID - BYTE InfoByte2; // Information MID - BYTE InfoByte3; // Information LSB - BYTE AddSenLen; // Additional Sense Length - BYTE ComSpecInf0; // Command Specific Information MSB - BYTE ComSpecInf1; // Command Specific Information MID - BYTE ComSpecInf2; // Command Specific Information MID - BYTE ComSpecInf3; // Command Specific Information LSB - BYTE AddSenseCode; // Additional Sense Code - BYTE AddSenQual; // Additional Sense Code Qualifier - BYTE FieldRepUCode; // Field Replaceable Unit Code - BYTE SenKeySpec15; // Sense Key Specific 15th byte - BYTE SenKeySpec16; // Sense Key Specific 16th byte - BYTE SenKeySpec17; // Sense Key Specific 17th byte - BYTE AddSenseBytes; // Additional Sense Bytes - -} SENSE_DATA_FMT; - -//*************************************************************************** -// %%% REQUEST SENSE ERROR CODE %%% -//*************************************************************************** -#define SERROR_CURRENT 0x70 // Current Errors -#define SERROR_DEFERED 0x71 // Deferred Errors - -//*************************************************************************** -// %%% REQUEST SENSE BIT DEFINITIONS %%% -//*************************************************************************** -#define SENSE_VALID 0x80 // Byte 0 Bit 7 -#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 -#define SENSE_EOM 0x40 // Byte 2 Bit 6 -#define SENSE_ILI 0x20 // Byte 2 Bit 5 - -//*************************************************************************** -// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% -//*************************************************************************** -#define KEY_NOSENSE 0x00 // No Sense -#define KEY_RECERROR 0x01 // Recovered Error -#define KEY_NOTREADY 0x02 // Not Ready -#define KEY_MEDIUMERR 0x03 // Medium Error -#define KEY_HARDERROR 0x04 // Hardware Error -#define KEY_ILLGLREQ 0x05 // Illegal Request -#define KEY_UNITATT 0x06 // Unit Attention -#define KEY_DATAPROT 0x07 // Data Protect -#define KEY_BLANKCHK 0x08 // Blank Check -#define KEY_VENDSPEC 0x09 // Vendor Specific -#define KEY_COPYABORT 0x0A // Copy Abort -#define KEY_EQUAL 0x0C // Equal (Search) -#define KEY_VOLOVRFLW 0x0D // Volume Overflow -#define KEY_MISCOMP 0x0E // Miscompare (Search) -#define KEY_RESERVED 0x0F // Reserved - -//*************************************************************************** -// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% -//*************************************************************************** -#define DTYPE_DASD 0x00 // Disk Device -#define DTYPE_SEQD 0x01 // Tape Device -#define DTYPE_PRNT 0x02 // Printer -#define DTYPE_PROC 0x03 // Processor -#define DTYPE_WORM 0x04 // Write-once read-multiple -#define DTYPE_CROM 0x05 // CD-ROM device -#define DTYPE_CDROM 0x05 // CD-ROM device -#define DTYPE_SCAN 0x06 // Scanner device -#define DTYPE_OPTI 0x07 // Optical memory device -#define DTYPE_JUKE 0x08 // Medium Changer device -#define DTYPE_COMM 0x09 // Communications device -#define DTYPE_RESL 0x0A // Reserved (low) -#define DTYPE_RESH 0x1E // Reserved (high) -#define DTYPE_UNKNOWN 0x1F // Unknown or no device type - -//*************************************************************************** -// %%% ANSI APPROVED VERSION DEFINITIONS %%% -//*************************************************************************** -#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand -#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) -#define ANSI_SCSI2 0x2 // Device complies to SCSI-2 -#define ANSI_RESLO 0x3 // Reserved (low) -#define ANSI_RESHI 0x7 // Reserved (high) diff --git a/src/dos/wnaspi32.h b/src/dos/wnaspi32.h deleted file mode 100644 index 98ac7c3..0000000 --- a/src/dos/wnaspi32.h +++ /dev/null @@ -1,354 +0,0 @@ -/****************************************************************************** -** -** Module Name: wnaspi32.h -** -** Description: Header file for ASPI for Win32. This header includes -** macro and type declarations, and can be included without -** modification when using Borland C++ or Microsoft Visual -** C++ with 32-bit compilation. If you are using a different -** compiler then you MUST ensure that structures are packed -** onto byte alignments, and that C++ name mangling is turned -** off. -** -** Notes: This file created using 4 spaces per tab. -** -******************************************************************************/ - -#ifndef __WNASPI32_H__ -#define __WNASPI32_H__ - -/* -** Make sure structures are packed and undecorated. -*/ - -#ifdef __BORLANDC__ -#pragma option -a1 -#endif //__BORLANDC__ - -#ifdef _MSC_VER -#pragma pack(1) -#endif //__MSC_VER - -#ifdef __cplusplus -extern "C" { -#endif //__cplusplus - -//***************************************************************************** -// %%% SCSI MISCELLANEOUS EQUATES %%% -//***************************************************************************** - -#define SENSE_LEN 14 // Default sense buffer length -#define SRB_DIR_SCSI 0x00 // Direction determined by SCSI -#define SRB_POSTING 0x01 // Enable ASPI posting -#define SRB_ENABLE_RESIDUAL_COUNT 0x04 // Enable residual byte count reporting -#define SRB_DIR_IN 0x08 // Transfer from SCSI target to host -#define SRB_DIR_OUT 0x10 // Transfer from host to SCSI target -#define SRB_EVENT_NOTIFY 0x40 // Enable ASPI event notification - -#define RESIDUAL_COUNT_SUPPORTED 0x02 // Extended buffer flag -#define MAX_SRB_TIMEOUT 108000lu // 30 hour maximum timeout in s -#define DEFAULT_SRB_TIMEOUT 108000lu // Max timeout by default - - -//***************************************************************************** -// %%% ASPI Command Definitions %%% -//***************************************************************************** - -#define SC_HA_INQUIRY 0x00 // Host adapter inquiry -#define SC_GET_DEV_TYPE 0x01 // Get device type -#define SC_EXEC_SCSI_CMD 0x02 // Execute SCSI command -#define SC_ABORT_SRB 0x03 // Abort an SRB -#define SC_RESET_DEV 0x04 // SCSI bus device reset -#define SC_SET_HA_PARMS 0x05 // Set HA parameters -#define SC_GET_DISK_INFO 0x06 // Get Disk information -#define SC_RESCAN_SCSI_BUS 0x07 // ReBuild SCSI device map -#define SC_GETSET_TIMEOUTS 0x08 // Get/Set target timeouts - -//***************************************************************************** -// %%% SRB Status %%% -//***************************************************************************** - -#define SS_PENDING 0x00 // SRB being processed -#define SS_COMP 0x01 // SRB completed without error -#define SS_ABORTED 0x02 // SRB aborted -#define SS_ABORT_FAIL 0x03 // Unable to abort SRB -#define SS_ERR 0x04 // SRB completed with error - -#define SS_INVALID_CMD 0x80 // Invalid ASPI command -#define SS_INVALID_HA 0x81 // Invalid host adapter number -#define SS_NO_DEVICE 0x82 // SCSI device not installed - -#define SS_INVALID_SRB 0xE0 // Invalid parameter set in SRB -#define SS_OLD_MANAGER 0xE1 // ASPI manager doesn't support Windows -#define SS_BUFFER_ALIGN 0xE1 // Buffer not aligned (replaces OLD_MANAGER in Win32) -#define SS_ILLEGAL_MODE 0xE2 // Unsupported Windows mode -#define SS_NO_ASPI 0xE3 // No ASPI managers resident -#define SS_FAILED_INIT 0xE4 // ASPI for windows failed init -#define SS_ASPI_IS_BUSY 0xE5 // No resources available to execute cmd -#define SS_BUFFER_TO_BIG 0xE6 // Buffer size to big to handle! -#define SS_MISMATCHED_COMPONENTS 0xE7 // The DLLs/EXEs of ASPI don't version check -#define SS_NO_ADAPTERS 0xE8 // No host adapters to manage -#define SS_INSUFFICIENT_RESOURCES 0xE9 // Couldn't allocate resources needed to init -#define SS_ASPI_IS_SHUTDOWN 0xEA // Call came to ASPI after PROCESS_DETACH -#define SS_BAD_INSTALL 0xEB // The DLL or other components are installed wrong - -//***************************************************************************** -// %%% Host Adapter Status %%% -//***************************************************************************** - -#define HASTAT_OK 0x00 // Host adapter did not detect an // error -#define HASTAT_SEL_TO 0x11 // Selection Timeout -#define HASTAT_DO_DU 0x12 // Data overrun data underrun -#define HASTAT_BUS_FREE 0x13 // Unexpected bus free -#define HASTAT_PHASE_ERR 0x14 // Target bus phase sequence // failure -#define HASTAT_TIMEOUT 0x09 // Timed out while SRB was waiting to beprocessed. -#define HASTAT_COMMAND_TIMEOUT 0x0B // Adapter timed out processing SRB. -#define HASTAT_MESSAGE_REJECT 0x0D // While processing SRB, the // adapter received a MESSAGE -#define HASTAT_BUS_RESET 0x0E // A bus reset was detected. -#define HASTAT_PARITY_ERROR 0x0F // A parity error was detected. -#define HASTAT_REQUEST_SENSE_FAILED 0x10 // The adapter failed in issuing - -//***************************************************************************** -// %%% SRB - HOST ADAPTER INQUIRY - SC_HA_INQUIRY (0) %%% -//***************************************************************************** - -typedef struct // Offset -{ // HX/DEC - BYTE SRB_Cmd; // 00/000 ASPI command code = SC_HA_INQUIRY - BYTE SRB_Status; // 01/001 ASPI command status byte - BYTE SRB_HaId; // 02/002 ASPI host adapter number - BYTE SRB_Flags; // 03/003 ASPI request flags - DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 - BYTE HA_Count; // 08/008 Number of host adapters present - BYTE HA_SCSI_ID; // 09/009 SCSI ID of host adapter - BYTE HA_ManagerId[16]; // 0A/010 String describing the manager - BYTE HA_Identifier[16]; // 1A/026 String describing the host adapter - BYTE HA_Unique[16]; // 2A/042 Host Adapter Unique parameters - WORD HA_Rsvd1; // 3A/058 Reserved, MUST = 0 -} -SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry; - -//***************************************************************************** -// %%% SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE (1) %%% -//***************************************************************************** - -typedef struct // Offset -{ // HX/DEC - BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GET_DEV_TYPE - BYTE SRB_Status; // 01/001 ASPI command status byte - BYTE SRB_HaId; // 02/002 ASPI host adapter number - BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 - DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 - BYTE SRB_Target; // 08/008 Target's SCSI ID - BYTE SRB_Lun; // 09/009 Target's LUN number - BYTE SRB_DeviceType; // 0A/010 Target's peripheral device type - BYTE SRB_Rsvd1; // 0B/011 Reserved, MUST = 0 -} -SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock; - -//***************************************************************************** -// %%% SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD (2) %%% -//***************************************************************************** - -typedef struct // Offset -{ // HX/DEC - BYTE SRB_Cmd; // 00/000 ASPI command code = SC_EXEC_SCSI_CMD - BYTE SRB_Status; // 01/001 ASPI command status byte - BYTE SRB_HaId; // 02/002 ASPI host adapter number - BYTE SRB_Flags; // 03/003 ASPI request flags - DWORD SRB_Hdr_Rsvd; // 04/004 Reserved - BYTE SRB_Target; // 08/008 Target's SCSI ID - BYTE SRB_Lun; // 09/009 Target's LUN number - WORD SRB_Rsvd1; // 0A/010 Reserved for Alignment - DWORD SRB_BufLen; // 0C/012 Data Allocation Length - BYTE FAR *SRB_BufPointer; // 10/016 Data Buffer Pointer - BYTE SRB_SenseLen; // 14/020 Sense Allocation Length - BYTE SRB_CDBLen; // 15/021 CDB Length - BYTE SRB_HaStat; // 16/022 Host Adapter Status - BYTE SRB_TargStat; // 17/023 Target Status - VOID FAR *SRB_PostProc; // 18/024 Post routine - BYTE SRB_Rsvd2[20]; // 1C/028 Reserved, MUST = 0 - BYTE CDBByte[16]; // 30/048 SCSI CDB - BYTE SenseArea[SENSE_LEN+2]; // 50/064 Request Sense buffer -} -SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd; - -//***************************************************************************** -// %%% SRB - ABORT AN SRB - SC_ABORT_SRB (3) %%% -//***************************************************************************** - -typedef struct // Offset -{ // HX/DEC - BYTE SRB_Cmd; // 00/000 ASPI command code = SC_ABORT_SRB - BYTE SRB_Status; // 01/001 ASPI command status byte - BYTE SRB_HaId; // 02/002 ASPI host adapter number - BYTE SRB_Flags; // 03/003 Reserved - DWORD SRB_Hdr_Rsvd; // 04/004 Reserved - VOID FAR *SRB_ToAbort; // 08/008 Pointer to SRB to abort -} -SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort; - -//***************************************************************************** -// %%% SRB - BUS DEVICE RESET - SC_RESET_DEV (4) %%% -//***************************************************************************** - -typedef struct // Offset -{ // HX/DEC - BYTE SRB_Cmd; // 00/000 ASPI command code = SC_RESET_DEV - BYTE SRB_Status; // 01/001 ASPI command status byte - BYTE SRB_HaId; // 02/002 ASPI host adapter number - BYTE SRB_Flags; // 03/003 ASPI request flags - DWORD SRB_Hdr_Rsvd; // 04/004 Reserved - BYTE SRB_Target; // 08/008 Target's SCSI ID - BYTE SRB_Lun; // 09/009 Target's LUN number - BYTE SRB_Rsvd1[12]; // 0A/010 Reserved for Alignment - BYTE SRB_HaStat; // 16/022 Host Adapter Status - BYTE SRB_TargStat; // 17/023 Target Status - VOID FAR *SRB_PostProc; // 18/024 Post routine - BYTE SRB_Rsvd2[36]; // 1C/028 Reserved, MUST = 0 -} -SRB_BusDeviceReset, *PSRB_BusDeviceReset, FAR *LPSRB_BusDeviceReset; - -//***************************************************************************** -// %%% SRB - GET DISK INFORMATION - SC_GET_DISK_INFO %%% -//***************************************************************************** - -typedef struct // Offset -{ // HX/DEC - BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GET_DISK_INFO - BYTE SRB_Status; // 01/001 ASPI command status byte - BYTE SRB_HaId; // 02/002 ASPI host adapter number - BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 - DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 - BYTE SRB_Target; // 08/008 Target's SCSI ID - BYTE SRB_Lun; // 09/009 Target's LUN number - BYTE SRB_DriveFlags; // 0A/010 Driver flags - BYTE SRB_Int13HDriveInfo; // 0B/011 Host Adapter Status - BYTE SRB_Heads; // 0C/012 Preferred number of heads translation - BYTE SRB_Sectors; // 0D/013 Preferred number of sectors translation - BYTE SRB_Rsvd1[10]; // 0E/014 Reserved, MUST = 0 -} -SRB_GetDiskInfo, *PSRB_GetDiskInfo, FAR *LPSRB_GetDiskInfo; - -//***************************************************************************** -// %%% SRB - RESCAN SCSI BUS(ES) ON SCSIPORT %%% -//***************************************************************************** - -typedef struct // Offset -{ // HX/DEC - BYTE SRB_Cmd; // 00/000 ASPI command code = SC_RESCAN_SCSI_BUS - BYTE SRB_Status; // 01/001 ASPI command status byte - BYTE SRB_HaId; // 02/002 ASPI host adapter number - BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 - DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 -} -SRB_RescanPort, *PSRB_RescanPort, FAR *LPSRB_RescanPort; - -//***************************************************************************** -// %%% SRB - GET/SET TARGET TIMEOUTS %%% -//***************************************************************************** - -typedef struct // Offset -{ // HX/DEC - BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GETSET_TIMEOUTS - BYTE SRB_Status; // 01/001 ASPI command status byte - BYTE SRB_HaId; // 02/002 ASPI host adapter number - BYTE SRB_Flags; // 03/003 ASPI request flags - DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 - BYTE SRB_Target; // 08/008 Target's SCSI ID - BYTE SRB_Lun; // 09/009 Target's LUN number - DWORD SRB_Timeout; // 0A/010 Timeout in half seconds -} -SRB_GetSetTimeouts, *PSRB_GetSetTimeouts, FAR *LPSRB_GetSetTimeouts; - -//***************************************************************************** -// %%% ASPIBUFF - Structure For Controllng I/O Buffers %%% -//***************************************************************************** - -typedef struct tag_ASPI32BUFF // Offset -{ // HX/DEC - PBYTE AB_BufPointer; // 00/000 Pointer to the ASPI allocated buffer - DWORD AB_BufLen; // 04/004 Length in bytes of the buffer - DWORD AB_ZeroFill; // 08/008 Flag set to 1 if buffer should be zeroed - DWORD AB_Reserved; // 0C/012 Reserved -} -ASPI32BUFF, *PASPI32BUFF, FAR *LPASPI32BUFF; - -//***************************************************************************** -// %%% TOC structures %%% -//***************************************************************************** - -typedef struct -{ - unsigned char reserved1; - unsigned char cAdrCtrl; - unsigned char cTrackNum; - unsigned char reserved2; - unsigned long lAddr; -} TOC_TRACK; - -typedef struct -{ - unsigned short usTocDataLen; - unsigned char cFirstTrack; - unsigned char cLastTrack; - TOC_TRACK tracks[100]; -} TOC, *PTOC, FAR *LPTOC; - -//***************************************************************************** -// %%% PROTOTYPES - User Callable ASPI for Win32 Functions %%% -//***************************************************************************** - -typedef struct -{ - BYTE SRB_Cmd; - BYTE SRB_Status; - BYTE SRB_HaId; - BYTE SRB_Flags; - DWORD SRB_Hdr_Rsvd; -} SRB, *PSRB, FAR *LPSRB; - - -#if defined(__BORLANDC__) - -DWORD _import GetASPI32SupportInfo( void ); -DWORD _import SendASPI32Command( LPSRB ); -BOOL _import GetASPI32Buffer( PASPI32BUFF ); -BOOL _import FreeASPI32Buffer( PASPI32BUFF ); -BOOL _import TranslateASPI32Address( PDWORD, PDWORD ); - -#elif defined(_MSC_VER) - -__declspec(dllimport) DWORD GetASPI32SupportInfo( void ); -__declspec(dllimport) DWORD SendASPI32Command( LPSRB ); -__declspec(dllimport) BOOL GetASPI32Buffer( PASPI32BUFF ); -__declspec(dllimport) BOOL FreeASPI32Buffer( PASPI32BUFF ); -__declspec(dllimport) BOOL TranslateASPI32Address( PDWORD, PDWORD ); - -#else - -extern DWORD GetASPI32SupportInfo( void ); -extern DWORD GetASPI32Command( LPSRB ); -extern BOOL GetASPI32Buffer( PASPI32BUFF ); -extern BOOL FreeASPI32Buffer( PASPI32BUFF ); -extern BOOL TranslateASPI32Address( PDWORD, PDWORD ); - -#endif - -/* -** Restore compiler default packing and close off the C declarations. -*/ - -#ifdef __BORLANDC__ -#pragma option -a. -#endif //__BORLANDC__ - -#ifdef _MSC_VER -#pragma pack() -#endif //_MSC_VER - -#ifdef __cplusplus -} -#endif //__cplusplus - -#endif //__WNASPI32_H__ diff --git a/src/dosbox.cpp b/src/dosbox.cpp index fe19fe5..4fdfe00 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -1,678 +1,297 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dosbox.cpp,v 1.148 2009/04/26 15:37:04 c2woody Exp $ */ - -#include -#include -#include -#include -#include -#include "dosbox.h" -#include "debug.h" -#include "cpu.h" -#include "video.h" -#include "pic.h" -#include "cpu.h" -#include "callback.h" -#include "inout.h" -#include "mixer.h" -#include "timer.h" -#include "dos_inc.h" -#include "setup.h" -#include "control.h" -#include "cross.h" -#include "programs.h" -#include "support.h" -#include "mapper.h" -#include "ints/int10.h" -#include "render.h" - -Config * control; -MachineType machine; -SVGACards svgaCard; - -/* The whole load of startups for all the subfunctions */ -void MSG_Init(Section_prop *); -void LOG_StartUp(void); -void MEM_Init(Section *); -void PAGING_Init(Section *); -void IO_Init(Section * ); -void CALLBACK_Init(Section*); -void PROGRAMS_Init(Section*); -//void CREDITS_Init(Section*); -void RENDER_Init(Section*); -void VGA_Init(Section*); - -void DOS_Init(Section*); - - -void CPU_Init(Section*); - -#if C_FPU -void FPU_Init(Section*); -#endif - -void DMA_Init(Section*); - -void MIXER_Init(Section*); -void MIDI_Init(Section*); -void HARDWARE_Init(Section*); - - -void KEYBOARD_Init(Section*); //TODO This should setup INT 16 too but ok ;) -void JOYSTICK_Init(Section*); -void MOUSE_Init(Section*); -void SBLASTER_Init(Section*); -void GUS_Init(Section*); -void MPU401_Init(Section*); -void PCSPEAKER_Init(Section*); -void TANDYSOUND_Init(Section*); -void DISNEY_Init(Section*); -void SERIAL_Init(Section*); - - -#if C_IPX -void IPX_Init(Section*); -#endif - -void SID_Init(Section* sec); - -void PIC_Init(Section*); -void TIMER_Init(Section*); -void BIOS_Init(Section*); -void DEBUG_Init(Section*); -void CMOS_Init(Section*); - -void MSCDEX_Init(Section*); -void DRIVES_Init(Section*); -void CDROM_Image_Init(Section*); - -/* Dos Internal mostly */ -void EMS_Init(Section*); -void XMS_Init(Section*); - -void DOS_KeyboardLayout_Init(Section*); - -void AUTOEXEC_Init(Section*); -void SHELL_Init(void); - -void INT10_Init(Section*); - -static LoopHandler * loop; - -bool SDLNetInited; - -static Bit32u ticksRemain; -static Bit32u ticksLast; -static Bit32u ticksAdded; -Bit32s ticksDone; -Bit32u ticksScheduled; -bool ticksLocked; - -static Bitu Normal_Loop(void) { - Bits ret; - while (1) { - if (PIC_RunQueue()) { - ret=(*cpudecoder)(); - if (ret<0) return 1; - if (ret>0) { - Bitu blah=(*CallBack_Handlers[ret])(); - if (blah) return blah; - } -#if C_DEBUG - if (DEBUG_ExitLoop()) return 0; -#endif - } else { - GFX_Events(); - if (ticksRemain>0) { - TIMER_AddTick(); - ticksRemain--; - } else goto increaseticks; - } - } -increaseticks: - if (GCC_UNLIKELY(ticksLocked)) { - ticksRemain=5; - /* Reset any auto cycle guessing for this frame */ - ticksLast = GetTicks(); - ticksAdded = 0; - ticksDone = 0; - ticksScheduled = 0; - } else { - Bit32u ticksNew; - ticksNew=GetTicks(); - ticksScheduled += ticksAdded; - if (ticksNew > ticksLast) { - ticksRemain = ticksNew-ticksLast; - ticksLast = ticksNew; - ticksDone += ticksRemain; - if ( ticksRemain > 20 ) { - ticksRemain = 20; - } - ticksAdded = ticksRemain; - if (CPU_CycleAutoAdjust && !CPU_SkipCycleAutoAdjust) { - if (ticksScheduled >= 250 || ticksDone >= 250 || (ticksAdded > 15 && ticksScheduled >= 5) ) { - /* ratio we are aiming for is around 90% usage*/ - Bit32s ratio = (ticksScheduled * (CPU_CyclePercUsed*90*1024/100/100)) / ticksDone; - Bit32s new_cmax = CPU_CycleMax; - Bit64s cproc = (Bit64s)CPU_CycleMax * (Bit64s)ticksScheduled; - if (cproc > 0) { - /* ignore the cycles added due to the io delay code in order - to have smoother auto cycle adjustments */ - double ratioremoved = (double) CPU_IODelayRemoved / (double) cproc; - if (ratioremoved < 1.0) { - ratio = (Bit32s)((double)ratio * (1 - ratioremoved)); - Bit64s cmax_scaled = (Bit64s)CPU_CycleMax * (Bit64s)ratio; - if (ratio <= 1024) - new_cmax = (Bit32s)(cmax_scaled / (Bit64s)1024); - else - new_cmax = (Bit32s)(1 + (CPU_CycleMax >> 1) + cmax_scaled / (Bit64s)2048); - } - } - - if (new_cmax10) { - /* ratios below 12% along with a large time since the last update - has taken place are most likely caused by heavy load through a - different application, the cycles adjusting is skipped as well */ - if ((ratio>120) || (ticksDone<700)) { - CPU_CycleMax = new_cmax; - if (CPU_CycleLimit > 0) { - if (CPU_CycleMax>CPU_CycleLimit) CPU_CycleMax = CPU_CycleLimit; - } - } - } - CPU_IODelayRemoved = 0; - ticksDone = 0; - ticksScheduled = 0; - } else if (ticksAdded > 15) { - /* ticksAdded > 15 but ticksScheduled < 5, lower the cycles - but do not reset the scheduled/done ticks to take them into - account during the next auto cycle adjustment */ - CPU_CycleMax /= 3; - if (CPU_CycleMax < CPU_CYCLES_LOWER_LIMIT) - CPU_CycleMax = CPU_CYCLES_LOWER_LIMIT; - } - } - } else { - ticksAdded = 0; - SDL_Delay(1); - ticksDone -= GetTicks() - ticksNew; - if (ticksDone < 0) - ticksDone = 0; - } - } - return 0; -} - -void DOSBOX_SetLoop(LoopHandler * handler) { - loop=handler; -} - -void DOSBOX_SetNormalLoop() { - loop=Normal_Loop; -} - -void DOSBOX_RunMachine(void){ - Bitu ret; - do { - ret=(*loop)(); - } while (!ret); -} - -static void DOSBOX_UnlockSpeed( bool pressed ) { - static bool autoadjust = false; - if (pressed) { - ticksLocked = true; - if (CPU_CycleAutoAdjust) { - autoadjust = true; - CPU_CycleAutoAdjust = false; - CPU_CycleMax /= 3; - if (CPU_CycleMax<1000) CPU_CycleMax=1000; - } - } else { - ticksLocked = false; - if (autoadjust) { - autoadjust = false; - CPU_CycleAutoAdjust = true; - } - } -} - -static void DOSBOX_RealInit(Section * sec) { - Section_prop * section=static_cast(sec); - /* Initialize some dosbox internals */ - - ticksRemain=0; - ticksLast=GetTicks(); - ticksLocked = false; - DOSBOX_SetLoop(&Normal_Loop); - MSG_Init(section); - - MAPPER_AddHandler(DOSBOX_UnlockSpeed, MK_f12, MMOD2,"speedlock","Speedlock"); - std::string cmd_machine; - if (control->cmdline->FindString("-machine",cmd_machine,true)){ - //update value in config (else no matching against suggested values - section->HandleInputline(std::string("machine=") + cmd_machine); - } - - std::string mtype(section->Get_string("machine")); - svgaCard = SVGA_None; - machine = MCH_VGA; - int10.vesa_nolfb = false; - int10.vesa_oldvbe = false; - if (mtype == "cga") { machine = MCH_CGA; } - else if (mtype == "tandy") { machine = MCH_TANDY; } - else if (mtype == "pcjr") { machine = MCH_PCJR; } - else if (mtype == "hercules") { machine = MCH_HERC; } - else if (mtype == "ega") { machine = MCH_EGA; } -// else if (mtype == "vga") { svgaCard = SVGA_S3Trio; } - else if (mtype == "svga_s3") { svgaCard = SVGA_S3Trio; } - else if (mtype == "vesa_nolfb") { svgaCard = SVGA_S3Trio; int10.vesa_nolfb = true;} - else if (mtype == "vesa_oldvbe") { svgaCard = SVGA_S3Trio; int10.vesa_oldvbe = true;} - else if (mtype == "svga_et4000") { svgaCard = SVGA_TsengET4K; } - else if (mtype == "svga_et3000") { svgaCard = SVGA_TsengET3K; } -// else if (mtype == "vga_pvga1a") { svgaCard = SVGA_ParadisePVGA1A; } - else if (mtype == "svga_paradise") { svgaCard = SVGA_ParadisePVGA1A; } - else if (mtype == "vgaonly") { svgaCard = SVGA_None; } - else E_Exit("DOSBOX:Unknown machine type %s",mtype.c_str()); -} - - -void DOSBOX_Init(void) { - Section_prop * secprop; - Section_line * secline; - Prop_int* Pint; - Prop_hex* Phex; - Prop_string* Pstring; - Prop_bool* Pbool; - Prop_multival* Pmulti; - Prop_multival_remain* Pmulti_remain; - - SDLNetInited = false; - - // Some frequently used option sets - const char *rates[] = { "22050", "44100", "48000", "32000", "16000", "11025", "8000", "49716", 0 }; - const char *oplrates[] = { "22050", "49716", "44100", "48000", "32000", "16000", "11025", "8000", 0 }; - const char *ios[] = { "220", "240", "260", "280", "2a0", "2c0", "2e0", "300", 0 }; - const char *irqssb[] = { "7", "5", "3", "9", "10", "11", "12", 0 }; - const char *dmassb[] = { "1", "5", "0", "3", "6", "7", 0 }; - const char *iosgus[] = { "240", "220", "260", "280", "2a0", "2c0", "2e0", "300", 0 }; - const char *irqsgus[] = { "5", "3", "7", "9", "10", "11", "12", 0 }; - const char *dmasgus[] = { "3", "0", "1", "5", "6", "7", 0 }; - - - /* Setup all the different modules making up DOSBox */ - const char* machines[] = { - "hercules", "cga", "tandy", "pcjr", "ega", - "vgaonly", "svga_s3", "svga_et3000", "svga_et4000", - "svga_paradise", "vesa_nolfb", "vesa_oldvbe", 0 }; - secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit); - Pstring = secprop->Add_path("language",Property::Changeable::Always,""); - Pstring->Set_help("Select another language file."); - - Pstring = secprop->Add_string("machine",Property::Changeable::OnlyAtStart,"svga_s3"); - Pstring->Set_values(machines); - Pstring->Set_help("The type of machine tries to emulate."); - - Pstring = secprop->Add_path("captures",Property::Changeable::Always,"capture"); - Pstring->Set_help("Directory where things like wave, midi, screenshot get captured."); - -#if C_DEBUG - LOG_StartUp(); -#endif - - secprop->AddInitFunction(&IO_Init);//done - secprop->AddInitFunction(&PAGING_Init);//done - secprop->AddInitFunction(&MEM_Init);//done - secprop->AddInitFunction(&HARDWARE_Init);//done - Pint = secprop->Add_int("memsize", Property::Changeable::WhenIdle,16); - Pint->SetMinMax(1,63); - Pint->Set_help( - "Amount of memory DOSBox has in megabytes.\n" - " This value is best left at its default to avoid problems with some games,\n" - " though few games might require a higher value.\n" - " There is generally no speed advantage when raising this value."); - secprop->AddInitFunction(&CALLBACK_Init); - secprop->AddInitFunction(&PIC_Init);//done - secprop->AddInitFunction(&PROGRAMS_Init); - secprop->AddInitFunction(&TIMER_Init);//done - secprop->AddInitFunction(&CMOS_Init);//done - - secprop=control->AddSection_prop("render",&RENDER_Init,true); - Pint = secprop->Add_int("frameskip",Property::Changeable::Always,0); - Pint->SetMinMax(0,10); - Pint->Set_help("How many frames DOSBox skips before drawing one."); - - Pbool = secprop->Add_bool("aspect",Property::Changeable::Always,false); - Pbool->Set_help("Do aspect correction, if your output method doesn't support scaling this can slow things down!."); - - Pmulti = secprop->Add_multi("scaler",Property::Changeable::Always," "); - Pmulti->SetValue("normal2x"); - Pmulti->Set_help("Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended,the scaler will be used even if the result might not be desired."); - Pstring = Pmulti->GetSection()->Add_string("type",Property::Changeable::Always,"normal2x"); - - const char *scalers[] = { - "none", "normal2x", "normal3x", -#if RENDER_USE_ADVANCED_SCALERS>2 - "advmame2x", "advmame3x", "advinterp2x", "advinterp3x", "hq2x", "hq3x", "2xsai", "super2xsai", "supereagle", -#endif -#if RENDER_USE_ADVANCED_SCALERS>0 - "tv2x", "tv3x", "rgb2x", "rgb3x", "scan2x", "scan3x", -#endif - 0 }; - Pstring->Set_values(scalers); - - const char* force[] = { "", "forced", 0 }; - Pstring = Pmulti->GetSection()->Add_string("force",Property::Changeable::Always,""); - Pstring->Set_values(force); - - secprop=control->AddSection_prop("cpu",&CPU_Init,true);//done - const char* cores[] = { "auto", -#if (C_DYNAMIC_X86) || (C_DYNREC) - "dynamic", -#endif - "normal", "simple",0 }; - Pstring = secprop->Add_string("core",Property::Changeable::WhenIdle,"auto"); - Pstring->Set_values(cores); - Pstring->Set_help("CPU Core used in emulation. auto will switch to dynamic if available and appropriate."); - - const char* cputype_values[] = { "auto", "386", "386_slow", "486_slow", "pentium_slow", "386_prefetch", 0}; - Pstring = secprop->Add_string("cputype",Property::Changeable::Always,"auto"); - Pstring->Set_values(cputype_values); - Pstring->Set_help("CPU Type used in emulation. auto is the fastest choice."); - - - Pmulti_remain = secprop->Add_multiremain("cycles",Property::Changeable::Always," "); - Pmulti_remain->Set_help( - "Amount of instructions DOSBox tries to emulate each millisecond. Setting this value too high results in sound dropouts and lags. Cycles can be set in 3 ways:\n" - " 'auto' tries to guess what a game needs.\n" - " It usually works, but can fail for certain games.\n" - " 'fixed #number' will set a fixed amount of cycles. This is what you usually need if 'auto' fails.\n" - " (Example: fixed 4000)\n" - " 'max' will allocate as much cycles as your computer is able to handle\n"); - - const char* cyclest[] = { "auto","fixed","max","%u",0 }; - Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::Always,"auto"); - Pmulti_remain->SetValue("auto"); - Pstring->Set_values(cyclest); - - Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::Always,""); - - Pint = secprop->Add_int("cycleup",Property::Changeable::Always,500); - Pint->SetMinMax(1,1000000); - Pint->Set_help("Amount of cycles to increase/decrease with keycombo."); - - Pint = secprop->Add_int("cycledown",Property::Changeable::Always,20); - Pint->SetMinMax(1,1000000); - Pint->Set_help("Setting it lower than 100 will be a percentage."); - -#if C_FPU - secprop->AddInitFunction(&FPU_Init); -#endif - secprop->AddInitFunction(&DMA_Init);//done - secprop->AddInitFunction(&VGA_Init); - secprop->AddInitFunction(&KEYBOARD_Init); - - secprop=control->AddSection_prop("mixer",&MIXER_Init); - Pbool = secprop->Add_bool("nosound",Property::Changeable::OnlyAtStart,false); - Pbool->Set_help("Enable silent mode, sound is still emulated though."); - - Pint = secprop->Add_int("rate",Property::Changeable::OnlyAtStart,22050); - Pint->Set_values(rates); - Pint->Set_help("Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality."); - - const char *blocksizes[] = { - "2048", "4096", "8192", "1024", "512", "256", 0}; - Pint = secprop->Add_int("blocksize",Property::Changeable::OnlyAtStart,2048); - Pint->Set_values(blocksizes); - Pint->Set_help("Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged."); - - Pint = secprop->Add_int("prebuffer",Property::Changeable::OnlyAtStart,10); - Pint->SetMinMax(0,100); - Pint->Set_help("How many milliseconds of data to keep on top of the blocksize."); - - secprop=control->AddSection_prop("midi",&MIDI_Init,true);//done - secprop->AddInitFunction(&MPU401_Init,true);//done - - const char* mputypes[] = { "intelligent", "uart", "none",0}; - // FIXME: add some way to offer the actually available choices. - const char *devices[] = { "default", "win32", "alsa", "oss", "coreaudio", "coremidi","none", 0}; - Pstring = secprop->Add_string("mpu401",Property::Changeable::WhenIdle,"intelligent"); - Pstring->Set_values(mputypes); - Pstring->Set_help("Type of MPU-401 to emulate."); - - Pstring = secprop->Add_string("mididevice",Property::Changeable::WhenIdle,"default"); - Pstring->Set_values(devices); - Pstring->Set_help("Device that will receive the MIDI data from MPU-401."); - - Pstring = secprop->Add_string("midiconfig",Property::Changeable::WhenIdle,""); - Pstring->Set_help("Special configuration options for the device driver. This is usually the id of the device you want to use. See README for details."); - -#if C_DEBUG - secprop=control->AddSection_prop("debug",&DEBUG_Init); -#endif - - secprop=control->AddSection_prop("sblaster",&SBLASTER_Init,true);//done - - const char* sbtypes[] = { "sb1", "sb2", "sbpro1", "sbpro2", "sb16", "none", 0 }; - Pstring = secprop->Add_string("sbtype",Property::Changeable::WhenIdle,"sb16"); - Pstring->Set_values(sbtypes); - Pstring->Set_help("Type of sblaster to emulate."); - - Phex = secprop->Add_hex("sbbase",Property::Changeable::WhenIdle,0x220); - Phex->Set_values(ios); - Phex->Set_help("The IO address of the soundblaster."); - - Pint = secprop->Add_int("irq",Property::Changeable::WhenIdle,7); - Pint->Set_values(irqssb); - Pint->Set_help("The IRQ number of the soundblaster."); - - Pint = secprop->Add_int("dma",Property::Changeable::WhenIdle,1); - Pint->Set_values(dmassb); - Pint->Set_help("The DMA number of the soundblaster."); - - Pint = secprop->Add_int("hdma",Property::Changeable::WhenIdle,5); - Pint->Set_values(dmassb); - Pint->Set_help("The High DMA number of the soundblaster."); - - Pbool = secprop->Add_bool("sbmixer",Property::Changeable::WhenIdle,true); - Pbool->Set_help("Allow the soundblaster mixer to modify the DOSBox mixer."); - - const char* oplmodes[]={ "auto", "cms", "opl2", "dualopl2", "opl3", "none", 0}; - Pstring = secprop->Add_string("oplmode",Property::Changeable::WhenIdle,"auto"); - Pstring->Set_values(oplmodes); - Pstring->Set_help("Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'."); - - const char* oplemus[]={ "default", "compat", "fast", "old", 0}; - Pstring = secprop->Add_string("oplemu",Property::Changeable::WhenIdle,"default"); - Pstring->Set_values(oplemus); - Pstring->Set_help("Provider for the OPL emulation. compat or old might provide better quality (see oplrate as well)."); - - Pint = secprop->Add_int("oplrate",Property::Changeable::WhenIdle,22050); - Pint->Set_values(oplrates); - Pint->Set_help("Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly)."); - - - secprop=control->AddSection_prop("gus",&GUS_Init,true); //done - Pbool = secprop->Add_bool("gus",Property::Changeable::WhenIdle,false); - Pbool->Set_help("Enable the Gravis Ultrasound emulation."); - - Pint = secprop->Add_int("gusrate",Property::Changeable::WhenIdle,22050); - Pint->Set_values(rates); - Pint->Set_help("Sample rate of Ultrasound emulation."); - - Phex = secprop->Add_hex("gusbase",Property::Changeable::WhenIdle,0x240); - Phex->Set_values(iosgus); - Phex->Set_help("The IO base address of the Gravis Ultrasound."); - - Pint = secprop->Add_int("gusirq",Property::Changeable::WhenIdle,5); - Pint->Set_values(irqsgus); - Pint->Set_help("The IRQ number of the Gravis Ultrasound."); - - Pint = secprop->Add_int("gusdma",Property::Changeable::WhenIdle,3); - Pint->Set_values(dmasgus); - Pint->Set_help("The DMA channel of the Gravis Ultrasound."); - - Pstring = secprop->Add_string("ultradir",Property::Changeable::WhenIdle,"C:\\ULTRASND"); - Pstring->Set_help( - "Path to Ultrasound directory. In this directory\n" - "there should be a MIDI directory that contains\n" - "the patch files for GUS playback. Patch sets used\n" - "with Timidity should work fine."); - - secprop = control->AddSection_prop("speaker",&PCSPEAKER_Init,true);//done - Pbool = secprop->Add_bool("pcspeaker",Property::Changeable::WhenIdle,true); - Pbool->Set_help("Enable PC-Speaker emulation."); - - Pint = secprop->Add_int("pcrate",Property::Changeable::WhenIdle,22050); - Pint->Set_values(rates); - Pint->Set_help("Sample rate of the PC-Speaker sound generation."); - - secprop->AddInitFunction(&TANDYSOUND_Init,true);//done - const char* tandys[] = { "auto", "on", "off", 0}; - Pstring = secprop->Add_string("tandy",Property::Changeable::WhenIdle,"auto"); - Pstring->Set_values(tandys); - Pstring->Set_help("Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'."); - - Pint = secprop->Add_int("tandyrate",Property::Changeable::WhenIdle,22050); - Pint->Set_values(rates); - Pint->Set_help("Sample rate of the Tandy 3-Voice generation."); - - secprop->AddInitFunction(&DISNEY_Init,true);//done - - Pbool = secprop->Add_bool("disney",Property::Changeable::WhenIdle,true); - Pbool->Set_help("Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible)."); - - secprop=control->AddSection_prop("joystick",&BIOS_Init,false);//done - secprop->AddInitFunction(&INT10_Init); - secprop->AddInitFunction(&MOUSE_Init); //Must be after int10 as it uses CurMode - secprop->AddInitFunction(&JOYSTICK_Init); - const char* joytypes[] = { "auto", "2axis", "4axis", "4axis_2", "fcs", "ch", "none",0}; - Pstring = secprop->Add_string("joysticktype",Property::Changeable::WhenIdle,"auto"); - Pstring->Set_values(joytypes); - Pstring->Set_help( - "Type of joystick to emulate: auto (default), none,\n" - "2axis (supports two joysticks),\n" - "4axis (supports one joystick, first joystick used),\n" - "4axis_2 (supports one joystick, second joystick used),\n" - "fcs (Thrustmaster), ch (CH Flightstick).\n" - "none disables joystick emulation.\n" - "auto chooses emulation depending on real joystick(s)."); - - Pbool = secprop->Add_bool("timed",Property::Changeable::WhenIdle,true); - Pbool->Set_help("enable timed intervals for axis. (false is old style behaviour)."); - - Pbool = secprop->Add_bool("autofire",Property::Changeable::WhenIdle,false); - Pbool->Set_help("continuously fires as long as you keep the button pressed."); - - Pbool = secprop->Add_bool("swap34",Property::Changeable::WhenIdle,false); - Pbool->Set_help("swap the 3rd and the 4th axis. can be useful for certain joysticks."); - - Pbool = secprop->Add_bool("buttonwrap",Property::Changeable::WhenIdle,true); - Pbool->Set_help("enable button wrapping at the number of emulated buttons."); - - secprop=control->AddSection_prop("serial",&SERIAL_Init,true); - const char* serials[] = { "dummy", "disabled", "modem", "nullmodem", - "directserial",0 }; - - Pmulti_remain = secprop->Add_multiremain("serial1",Property::Changeable::WhenIdle," "); - Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::WhenIdle,"dummy"); - Pmulti_remain->SetValue("dummy"); - Pstring->Set_values(serials); - Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::WhenIdle,""); - Pmulti_remain->Set_help( - "set type of device connected to com port.\n" - "Can be disabled, dummy, modem, nullmodem, directserial.\n" - "Additional parameters must be in the same line in the form of\n" - "parameter:value. Parameter for all types is irq.\n" - "for directserial: realport (required), rxdelay (optional).\n" - " (realport:COM1 realport:ttyS0).\n" - "for modem: listenport (optional).\n" - "for nullmodem: server, rxdelay, txdelay, telnet, usedtr,\n" - " transparent, port, inhsocket (all optional).\n" - "Example: serial1=modem listenport:5000"); - - Pmulti_remain = secprop->Add_multiremain("serial2",Property::Changeable::WhenIdle," "); - Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::WhenIdle,"dummy"); - Pmulti_remain->SetValue("dummy"); - Pstring->Set_values(serials); - Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::WhenIdle,""); - Pmulti_remain->Set_help("see serial1"); - - Pmulti_remain = secprop->Add_multiremain("serial3",Property::Changeable::WhenIdle," "); - Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::WhenIdle,"disabled"); - Pmulti_remain->SetValue("disabled"); - Pstring->Set_values(serials); - Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::WhenIdle,""); - Pmulti_remain->Set_help("see serial1"); - - Pmulti_remain = secprop->Add_multiremain("serial4",Property::Changeable::WhenIdle," "); - Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::WhenIdle,"disabled"); - Pmulti_remain->SetValue("disabled"); - Pstring->Set_values(serials); - Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::WhenIdle,""); - Pmulti_remain->Set_help("see serial1"); - - - /* All the DOS Related stuff, which will eventually start up in the shell */ - secprop=control->AddSection_prop("dos",&DOS_Init,false);//done - secprop->AddInitFunction(&XMS_Init,true);//done - Pbool = secprop->Add_bool("xms",Property::Changeable::WhenIdle,true); - Pbool->Set_help("Enable XMS support."); - - secprop->AddInitFunction(&EMS_Init,true);//done - Pbool = secprop->Add_bool("ems",Property::Changeable::WhenIdle,true); - Pbool->Set_help("Enable EMS support."); - - Pbool = secprop->Add_bool("umb",Property::Changeable::WhenIdle,true); - Pbool->Set_help("Enable UMB support."); - - secprop->AddInitFunction(&DOS_KeyboardLayout_Init,true); - Pstring = secprop->Add_string("keyboardlayout",Property::Changeable::WhenIdle, "auto"); - Pstring->Set_help("Language code of the keyboard layout (or none)."); - - // Mscdex - secprop->AddInitFunction(&MSCDEX_Init); - secprop->AddInitFunction(&DRIVES_Init); - secprop->AddInitFunction(&CDROM_Image_Init); -#if C_IPX - secprop=control->AddSection_prop("ipx",&IPX_Init,true); - Pbool = secprop->Add_bool("ipx",Property::Changeable::WhenIdle, false); - Pbool->Set_help("Enable ipx over UDP/IP emulation."); -#endif -// secprop->AddInitFunction(&CREDITS_Init); - - //TODO ? - secline=control->AddSection_line("autoexec",&AUTOEXEC_Init); - MSG_Add("AUTOEXEC_CONFIGFILE_HELP", - "Lines in this section will be run at startup.\n" - ); - MSG_Add("CONFIGFILE_INTRO", - "# This is the configurationfile for DOSBox %s.\n" - "# Lines starting with a # are commentlines.\n" - "# They are used to (briefly) document the effect of each option.\n"); - MSG_Add("CONFIG_SUGGESTED_VALUES", "Possible values"); - - control->SetStartUp(&SHELL_Init); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include "dosbox.h" +#include "debug.h" +#include "cpu.h" +#include "video.h" +#include "pic.h" +#include "cpu.h" +#include "callback.h" +#include "inout.h" +#include "mixer.h" +#include "timer.h" +#include "dos_inc.h" +#include "setup.h" +#include "cross.h" +#include "programs.h" + +char dosbox_basedir[CROSS_LEN]; + + +#if 0 + +int main(int argc, char* argv[]) { + + + + /* Strip out the dosbox startup directory */ + + + + /* Handle the command line for new stuff to add to autoexec.bat */ + int argl=1; + if (argc>1) { + if (*argv[1]!='-') { + struct stat test; + if (stat(argv[1],&test)) { + E_Exit("%s Doesn't exist",argv[1]); + } + /* Not a switch so a normal directory/file */ + if (test.st_mode & S_IFDIR) { + SHELL_AddAutoexec("MOUNT C %s",argv[1]); + SHELL_AddAutoexec("C:"); + } else { + char * name=strrchr(argv[1],CROSS_FILESPLIT); + if (!name) E_Exit("This is weird %s",argv[1]); + *name++=0; + if (access(argv[1],F_OK)) E_Exit("Illegal Directory %s",argv[1]); + SHELL_AddAutoexec("MOUNT C %s",argv[1]); + SHELL_AddAutoexec("C:"); + SHELL_AddAutoexec(name); + } + argl++; + } + } + bool sw_c=false; + while (arglLastTicks) { + Bit32u ticks=new_ticks-LastTicks; + if (ticks>20) ticks=20; + LastTicks=new_ticks; + TIMER_AddTicks(ticks); + } + TIMER_CheckPIT(); + GFX_Events(); + PIC_runIRQs(); + return (*cpudecoder)(cpu_cycles); +}; + + +static Bitu Speed_Loop(void) { + Bit32u new_ticks; + new_ticks=GetTicks(); + Bitu ret=0; + Bitu cycles=1; + if (new_ticks>LastTicks) { + Bit32u ticks=new_ticks-LastTicks; + if (ticks>20) ticks=20; +// if (ticks>3) LOG_DEBUG("Ticks %d",ticks); + LastTicks=new_ticks; + TIMER_AddTicks(ticks); + cycles+=cpu_cycles*ticks; + } + TIMER_CheckPIT(); + GFX_Events(); + PIC_runIRQs(); + return (*cpudecoder)(cycles); +} + +void DOSBOX_SetLoop(LoopHandler * handler) { + loop=handler; +} + + +void DOSBOX_RunMachine(void){ + Bitu ret; + do { + ret=(*loop)(); + } while (!ret); +} + + + +static void InitSystems(void) { + MSG_Init(); + MEM_Init(); + IO_Init(); + CALLBACK_Init(); + PROGRAMS_Init(); + HARDWARE_Init(); + TIMER_Init(); + CPU_Init(); + FPU_Init(); + MIXER_Init(); +#ifdef C_DEBUG + DEBUG_Init(); +#endif + //Start up individual hardware + DMA_Init(); + PIC_Init(); + VGA_Init(); + KEYBOARD_Init(); + MOUSE_Init(); + JOYSTICK_Init(); + SBLASTER_Init(); + TANDY_Init(); + PCSPEAKER_Init(); + ADLIB_Init(); + CMS_Init(); + + PLUGIN_Init(); +/* Most of teh interrupt handlers */ + BIOS_Init(); + DOS_Init(); + EMS_Init(); //Needs dos first + XMS_Init(); //Needs dos first + +/* Setup the normal system loop */ + LastTicks=GetTicks(); + DOSBOX_SetLoop(&Normal_Loop); +// DOSBOX_SetLoop(&Speed_Loop); +} + + +void DOSBOX_Init(int argc, char* argv[]) { +/* Find the base directory */ + strcpy(dosbox_basedir,argv[0]); + char * last=strrchr(dosbox_basedir,CROSS_FILESPLIT); //if windowsversion fails: + if (!last) E_Exit("Can't find basedir"); + *++last=0; + /* Parse the command line with a setup function */ + int argl=1; + if (argc>1) { + if (*argv[1]!='-') { + struct stat test; + if (stat(argv[1],&test)) { + E_Exit("%s Doesn't exist",argv[1]); + } + /* Not a switch so a normal directory/file */ + if (test.st_mode & S_IFDIR) { + SHELL_AddAutoexec("MOUNT C %s",argv[1]); + SHELL_AddAutoexec("C:"); + } else { + char * name=strrchr(argv[1],CROSS_FILESPLIT); + if (!name) E_Exit("This is weird %s",argv[1]); + *name++=0; + if (access(argv[1],F_OK)) E_Exit("Illegal Directory %s",argv[1]); + SHELL_AddAutoexec("MOUNT C %s",argv[1]); + SHELL_AddAutoexec("C:"); + SHELL_AddAutoexec(name); + } + argl++; + } + } + bool sw_c=false; + while (argl -#include -#include "cross.h" -#include "mem.h" -#include "fpu.h" -#include "cpu.h" - -FPU_rec fpu; - -void FPU_FLDCW(PhysPt addr){ - Bit16u temp = mem_readw(addr); - FPU_SetCW(temp); -} - -Bit16u FPU_GetTag(void){ - Bit16u tag=0; - for(Bitu i=0;i<8;i++) - tag |= ( (fpu.tags[i]&3) <<(2*i)); - return tag; -} - -#if C_FPU_X86 -#include "fpu_instructions_x86.h" -#else -#include "fpu_instructions.h" -#endif - -/* WATCHIT : ALWAYS UPDATE REGISTERS BEFORE AND AFTER USING THEM - STATUS WORD => FPU_SET_TOP(TOP) BEFORE a read - TOP=FPU_GET_TOP() after a write; - */ - -static void EATREE(Bitu _rm){ - Bitu group=(_rm >> 3) & 7; - switch(group){ - case 0x00: /* FADD */ - FPU_FADD_EA(TOP); - break; - case 0x01: /* FMUL */ - FPU_FMUL_EA(TOP); - break; - case 0x02: /* FCOM */ - FPU_FCOM_EA(TOP); - break; - case 0x03: /* FCOMP */ - FPU_FCOM_EA(TOP); - FPU_FPOP(); - break; - case 0x04: /* FSUB */ - FPU_FSUB_EA(TOP); - break; - case 0x05: /* FSUBR */ - FPU_FSUBR_EA(TOP); - break; - case 0x06: /* FDIV */ - FPU_FDIV_EA(TOP); - break; - case 0x07: /* FDIVR */ - FPU_FDIVR_EA(TOP); - break; - default: - break; - } -} - -void FPU_ESC0_EA(Bitu rm,PhysPt addr) { - /* REGULAR TREE WITH 32 BITS REALS */ - FPU_FLD_F32_EA(addr); - EATREE(rm); -} - -void FPU_ESC0_Normal(Bitu rm) { - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch (group){ - case 0x00: /* FADD ST,STi */ - FPU_FADD(TOP,STV(sub)); - break; - case 0x01: /* FMUL ST,STi */ - FPU_FMUL(TOP,STV(sub)); - break; - case 0x02: /* FCOM STi */ - FPU_FCOM(TOP,STV(sub)); - break; - case 0x03: /* FCOMP STi */ - FPU_FCOM(TOP,STV(sub)); - FPU_FPOP(); - break; - case 0x04: /* FSUB ST,STi */ - FPU_FSUB(TOP,STV(sub)); - break; - case 0x05: /* FSUBR ST,STi */ - FPU_FSUBR(TOP,STV(sub)); - break; - case 0x06: /* FDIV ST,STi */ - FPU_FDIV(TOP,STV(sub)); - break; - case 0x07: /* FDIVR ST,STi */ - FPU_FDIVR(TOP,STV(sub)); - break; - default: - break; - } -} - -void FPU_ESC1_EA(Bitu rm,PhysPt addr) { -// floats - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch(group){ - case 0x00: /* FLD float*/ - FPU_PREP_PUSH(); - FPU_FLD_F32(addr,TOP); - break; - case 0x01: /* UNKNOWN */ - LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FST float*/ - FPU_FST_F32(addr); - break; - case 0x03: /* FSTP float*/ - FPU_FST_F32(addr); - FPU_FPOP(); - break; - case 0x04: /* FLDENV */ - FPU_FLDENV(addr); - break; - case 0x05: /* FLDCW */ - FPU_FLDCW(addr); - break; - case 0x06: /* FSTENV */ - FPU_FSTENV(addr); - break; - case 0x07: /* FNSTCW*/ - mem_writew(addr,fpu.cw); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub); - break; - } -} - -void FPU_ESC1_Normal(Bitu rm) { - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch (group){ - case 0x00: /* FLD STi */ - { - Bitu reg_from=STV(sub); - FPU_PREP_PUSH(); - FPU_FST(reg_from, TOP); - break; - } - case 0x01: /* FXCH STi */ - FPU_FXCH(TOP,STV(sub)); - break; - case 0x02: /* FNOP */ - FPU_FNOP(); - break; - case 0x03: /* FSTP STi */ - FPU_FST(TOP,STV(sub)); - FPU_FPOP(); - break; - case 0x04: - switch(sub){ - case 0x00: /* FCHS */ - FPU_FCHS(); - break; - case 0x01: /* FABS */ - FPU_FABS(); - break; - case 0x02: /* UNKNOWN */ - case 0x03: /* ILLEGAL */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - case 0x04: /* FTST */ - FPU_FTST(); - break; - case 0x05: /* FXAM */ - FPU_FXAM(); - break; - case 0x06: /* FTSTP (cyrix)*/ - case 0x07: /* UNKNOWN */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - } - break; - case 0x05: - switch(sub){ - case 0x00: /* FLD1 */ - FPU_FLD1(); - break; - case 0x01: /* FLDL2T */ - FPU_FLDL2T(); - break; - case 0x02: /* FLDL2E */ - FPU_FLDL2E(); - break; - case 0x03: /* FLDPI */ - FPU_FLDPI(); - break; - case 0x04: /* FLDLG2 */ - FPU_FLDLG2(); - break; - case 0x05: /* FLDLN2 */ - FPU_FLDLN2(); - break; - case 0x06: /* FLDZ*/ - FPU_FLDZ(); - break; - case 0x07: /* ILLEGAL */ - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - } - break; - case 0x06: - switch(sub){ - case 0x00: /* F2XM1 */ - FPU_F2XM1(); - break; - case 0x01: /* FYL2X */ - FPU_FYL2X(); - break; - case 0x02: /* FPTAN */ - FPU_FPTAN(); - break; - case 0x03: /* FPATAN */ - FPU_FPATAN(); - break; - case 0x04: /* FXTRACT */ - FPU_FXTRACT(); - break; - case 0x05: /* FPREM1 */ - FPU_FPREM1(); - break; - case 0x06: /* FDECSTP */ - TOP = (TOP - 1) & 7; - break; - case 0x07: /* FINCSTP */ - TOP = (TOP + 1) & 7; - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - } - break; - case 0x07: - switch(sub){ - case 0x00: /* FPREM */ - FPU_FPREM(); - break; - case 0x01: /* FYL2XP1 */ - FPU_FYL2XP1(); - break; - case 0x02: /* FSQRT */ - FPU_FSQRT(); - break; - case 0x03: /* FSINCOS */ - FPU_FSINCOS(); - break; - case 0x04: /* FRNDINT */ - FPU_FRNDINT(); - break; - case 0x05: /* FSCALE */ - FPU_FSCALE(); - break; - case 0x06: /* FSIN */ - FPU_FSIN(); - break; - case 0x07: /* FCOS */ - FPU_FCOS(); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); - } -} - - -void FPU_ESC2_EA(Bitu rm,PhysPt addr) { - /* 32 bits integer operants */ - FPU_FLD_I32_EA(addr); - EATREE(rm); -} - -void FPU_ESC2_Normal(Bitu rm) { - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch(group){ - case 0x05: - switch(sub){ - case 0x01: /* FUCOMPP */ - FPU_FUCOM(TOP,STV(1)); - FPU_FPOP(); - FPU_FPOP(); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub); - break; - } -} - - -void FPU_ESC3_EA(Bitu rm,PhysPt addr) { - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch(group){ - case 0x00: /* FILD */ - FPU_PREP_PUSH(); - FPU_FLD_I32(addr,TOP); - break; - case 0x01: /* FISTTP */ - LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FIST */ - FPU_FST_I32(addr); - break; - case 0x03: /* FISTP */ - FPU_FST_I32(addr); - FPU_FPOP(); - break; - case 0x05: /* FLD 80 Bits Real */ - FPU_PREP_PUSH(); - FPU_FLD_F80(addr); - break; - case 0x07: /* FSTP 80 Bits Real */ - FPU_FST_F80(addr); - FPU_FPOP(); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub); - } -} - -void FPU_ESC3_Normal(Bitu rm) { - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch (group) { - case 0x04: - switch (sub) { - case 0x00: //FNENI - case 0x01: //FNDIS - LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion :%d",sub); - break; - case 0x02: //FNCLEX FCLEX - FPU_FCLEX(); - break; - case 0x03: //FNINIT FINIT - FPU_FINIT(); - break; - case 0x04: //FNSETPM - case 0x05: //FRSTPM -// LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); - FPU_FNOP(); - break; - default: - E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",group,sub); - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",group,sub); - break; - } - return; -} - - -void FPU_ESC4_EA(Bitu rm,PhysPt addr) { - /* REGULAR TREE WITH 64 BITS REALS */ - FPU_FLD_F64_EA(addr); - EATREE(rm); -} - -void FPU_ESC4_Normal(Bitu rm) { - /* LOOKS LIKE number 6 without popping */ - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch(group){ - case 0x00: /* FADD STi,ST*/ - FPU_FADD(STV(sub),TOP); - break; - case 0x01: /* FMUL STi,ST*/ - FPU_FMUL(STV(sub),TOP); - break; - case 0x02: /* FCOM*/ - FPU_FCOM(TOP,STV(sub)); - break; - case 0x03: /* FCOMP*/ - FPU_FCOM(TOP,STV(sub)); - FPU_FPOP(); - break; - case 0x04: /* FSUBR STi,ST*/ - FPU_FSUBR(STV(sub),TOP); - break; - case 0x05: /* FSUB STi,ST*/ - FPU_FSUB(STV(sub),TOP); - break; - case 0x06: /* FDIVR STi,ST*/ - FPU_FDIVR(STV(sub),TOP); - break; - case 0x07: /* FDIV STi,ST*/ - FPU_FDIV(STV(sub),TOP); - break; - default: - break; - } -} - -void FPU_ESC5_EA(Bitu rm,PhysPt addr) { - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch(group){ - case 0x00: /* FLD double real*/ - FPU_PREP_PUSH(); - FPU_FLD_F64(addr,TOP); - break; - case 0x01: /* FISTTP longint*/ - LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FST double real*/ - FPU_FST_F64(addr); - break; - case 0x03: /* FSTP double real*/ - FPU_FST_F64(addr); - FPU_FPOP(); - break; - case 0x04: /* FRSTOR */ - FPU_FRSTOR(addr); - break; - case 0x06: /* FSAVE */ - FPU_FSAVE(addr); - break; - case 0x07: /*FNSTSW NG DISAGREES ON THIS*/ - FPU_SET_TOP(TOP); - mem_writew(addr,fpu.sw); - //seems to break all dos4gw games :) - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub); - } -} - -void FPU_ESC5_Normal(Bitu rm) { - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch(group){ - case 0x00: /* FFREE STi */ - fpu.tags[STV(sub)]=TAG_Empty; - break; - case 0x01: /* FXCH STi*/ - FPU_FXCH(TOP,STV(sub)); - break; - case 0x02: /* FST STi */ - FPU_FST(TOP,STV(sub)); - break; - case 0x03: /* FSTP STi*/ - FPU_FST(TOP,STV(sub)); - FPU_FPOP(); - break; - case 0x04: /* FUCOM STi */ - FPU_FUCOM(TOP,STV(sub)); - break; - case 0x05: /*FUCOMP STi */ - FPU_FUCOM(TOP,STV(sub)); - FPU_FPOP(); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",group,sub); - break; - } -} - -void FPU_ESC6_EA(Bitu rm,PhysPt addr) { - /* 16 bit (word integer) operants */ - FPU_FLD_I16_EA(addr); - EATREE(rm); -} - -void FPU_ESC6_Normal(Bitu rm) { - /* all P variants working only on registers */ - /* get top before switch and pop afterwards */ - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch(group){ - case 0x00: /*FADDP STi,ST*/ - FPU_FADD(STV(sub),TOP); - break; - case 0x01: /* FMULP STi,ST*/ - FPU_FMUL(STV(sub),TOP); - break; - case 0x02: /* FCOMP5*/ - FPU_FCOM(TOP,STV(sub)); - break; /* TODO IS THIS ALLRIGHT ????????? */ - case 0x03: /*FCOMPP*/ - if(sub != 1) { - LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",group,sub); - return; - } - FPU_FCOM(TOP,STV(1)); - FPU_FPOP(); /* extra pop at the bottom*/ - break; - case 0x04: /* FSUBRP STi,ST*/ - FPU_FSUBR(STV(sub),TOP); - break; - case 0x05: /* FSUBP STi,ST*/ - FPU_FSUB(STV(sub),TOP); - break; - case 0x06: /* FDIVRP STi,ST*/ - FPU_FDIVR(STV(sub),TOP); - break; - case 0x07: /* FDIVP STi,ST*/ - FPU_FDIV(STV(sub),TOP); - break; - default: - break; - } - FPU_FPOP(); -} - - -void FPU_ESC7_EA(Bitu rm,PhysPt addr) { - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch(group){ - case 0x00: /* FILD Bit16s */ - FPU_PREP_PUSH(); - FPU_FLD_I16(addr,TOP); - break; - case 0x01: - LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub); - break; - case 0x02: /* FIST Bit16s */ - FPU_FST_I16(addr); - break; - case 0x03: /* FISTP Bit16s */ - FPU_FST_I16(addr); - FPU_FPOP(); - break; - case 0x04: /* FBLD packed BCD */ - FPU_PREP_PUSH(); - FPU_FBLD(addr,TOP); - break; - case 0x05: /* FILD Bit64s */ - FPU_PREP_PUSH(); - FPU_FLD_I64(addr,TOP); - break; - case 0x06: /* FBSTP packed BCD */ - FPU_FBST(addr); - FPU_FPOP(); - break; - case 0x07: /* FISTP Bit64s */ - FPU_FST_I64(addr); - FPU_FPOP(); - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub); - break; - } -} - -void FPU_ESC7_Normal(Bitu rm) { - Bitu group=(rm >> 3) & 7; - Bitu sub=(rm & 7); - switch (group){ - case 0x01: /* FXCH STi*/ - FPU_FXCH(TOP,STV(sub)); - break; - case 0x02: /* FSTP STi*/ - case 0x03: /* FSTP STi*/ - FPU_FST(TOP,STV(sub)); - FPU_FPOP(); - break; - case 0x04: - switch(sub){ - case 0x00: /* FNSTSW AX*/ - FPU_SET_TOP(TOP); - reg_ax = fpu.sw; - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub); - break; - } - break; - default: - LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub); - break; - } -} - - -void FPU_Init(Section*) { - FPU_FINIT(); -} - -#endif +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include "mem.h" +#include "dosbox.h" + +typedef PhysOff EAPoint; + +#define LoadMb(off) mem_readb(off) +#define LoadMw(off) mem_readw(off) +#define LoadMd(off) mem_readd(off) + +#define LoadMbs(off) (Bit8s)(LoadMb(off)) +#define LoadMws(off) (Bit16s)(LoadMw(off)) +#define LoadMds(off) (Bit32s)(LoadMd(off)) + +#define SaveMb(off,val) mem_writeb(off,val) +#define SaveMw(off,val) mem_writew(off,val) +#define SaveMd(off,val) mem_writed(off,val) + +typedef long double FPUREG; + + +#include "fpu_load.h" + + + + + +void FPU_ESC0_EA(Bitu rm,PhysOff addr) { + + +} + +void FPU_ESC0_Normal(Bitu rm) { + + +} + + + + +void FPU_Init(void) { + +} \ No newline at end of file diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h deleted file mode 100644 index a913380..0000000 --- a/src/fpu/fpu_instructions.h +++ /dev/null @@ -1,596 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: fpu_instructions.h,v 1.32 2009/04/25 06:59:54 qbix79 Exp $ */ - - -static void FPU_FINIT(void) { - FPU_SetCW(0x37F); - fpu.sw = 0; - TOP=FPU_GET_TOP(); - fpu.tags[0] = TAG_Empty; - fpu.tags[1] = TAG_Empty; - fpu.tags[2] = TAG_Empty; - fpu.tags[3] = TAG_Empty; - fpu.tags[4] = TAG_Empty; - fpu.tags[5] = TAG_Empty; - fpu.tags[6] = TAG_Empty; - fpu.tags[7] = TAG_Empty; - fpu.tags[8] = TAG_Valid; // is only used by us -} - -static void FPU_FCLEX(void){ - fpu.sw &= 0x7f00; //should clear exceptions -} - -static void FPU_FNOP(void){ - return; -} - -static void FPU_PUSH(double in){ - TOP = (TOP - 1) &7; - //actually check if empty - fpu.tags[TOP] = TAG_Valid; - fpu.regs[TOP].d = in; -// LOG(LOG_FPU,LOG_ERROR)("Pushed at %d %g to the stack",newtop,in); - return; -} - -static void FPU_PREP_PUSH(void){ - TOP = (TOP - 1) &7; - fpu.tags[TOP] = TAG_Valid; -} - -static void FPU_FPOP(void){ - fpu.tags[TOP]=TAG_Empty; - //maybe set zero in it as well - TOP = ((TOP+1)&7); -// LOG(LOG_FPU,LOG_ERROR)("popped from %d %g off the stack",top,fpu.regs[top].d); - return; -} - -static double FROUND(double in){ - switch(fpu.round){ - case ROUND_Nearest: - if (in-floor(in)>0.5) return (floor(in)+1); - else if (in-floor(in)<0.5) return (floor(in)); - else return (((static_cast(floor(in)))&1)!=0)?(floor(in)+1):(floor(in)); - break; - case ROUND_Down: - return (floor(in)); - break; - case ROUND_Up: - return (ceil(in)); - break; - case ROUND_Chop: - return in; //the cast afterwards will do it right maybe cast here - break; - default: - return in; - break; - } -} - -#define BIAS80 16383 -#define BIAS64 1023 - -static Real64 FPU_FLD80(PhysPt addr) { - struct { - Bit16s begin; - FPU_Reg eind; - } test; - test.eind.l.lower = mem_readd(addr); - test.eind.l.upper = mem_readd(addr+4); - test.begin = mem_readw(addr+8); - - Bit64s exp64 = (((test.begin&0x7fff) - BIAS80)); - Bit64s blah = ((exp64 >0)?exp64:-exp64)&0x3ff; - Bit64s exp64final = ((exp64 >0)?blah:-blah) +BIAS64; - - Bit64s mant64 = (test.eind.ll >> 11) & LONGTYPE(0xfffffffffffff); - Bit64s sign = (test.begin&0x8000)?1:0; - FPU_Reg result; - result.ll = (sign <<63)|(exp64final << 52)| mant64; - return result.d; - - //mant64= test.mant80/2***64 * 2 **53 -} - -static void FPU_ST80(PhysPt addr,Bitu reg) { - struct { - Bit16s begin; - FPU_Reg eind; - } test; - Bit64s sign80 = (fpu.regs[reg].ll&LONGTYPE(0x8000000000000000))?1:0; - Bit64s exp80 = fpu.regs[reg].ll&LONGTYPE(0x7ff0000000000000); - Bit64s exp80final = (exp80>>52) - BIAS64 + BIAS80; - Bit64s mant80 = fpu.regs[reg].ll&LONGTYPE(0x000fffffffffffff); - Bit64s mant80final = (mant80 << 11); - // Elvira wants the 8 and tcalc doesn't - if(fpu.regs[reg].d != 0) mant80final |= LONGTYPE(0x8000000000000000); - test.begin= (static_cast(sign80)<<15)| static_cast(exp80final); - test.eind.ll = mant80final; - mem_writed(addr,test.eind.l.lower); - mem_writed(addr+4,test.eind.l.upper); - mem_writew(addr+8,test.begin); -} - - -static void FPU_FLD_F32(PhysPt addr,Bitu store_to) { - union { - float f; - Bit32u l; - } blah; - blah.l = mem_readd(addr); - fpu.regs[store_to].d = static_cast(blah.f); -} - -static void FPU_FLD_F64(PhysPt addr,Bitu store_to) { - fpu.regs[store_to].l.lower = mem_readd(addr); - fpu.regs[store_to].l.upper = mem_readd(addr+4); -} - -static void FPU_FLD_F80(PhysPt addr) { - fpu.regs[TOP].d = FPU_FLD80(addr); -} - -static void FPU_FLD_I16(PhysPt addr,Bitu store_to) { - Bit16s blah = mem_readw(addr); - fpu.regs[store_to].d = static_cast(blah); -} - -static void FPU_FLD_I32(PhysPt addr,Bitu store_to) { - Bit32s blah = mem_readd(addr); - fpu.regs[store_to].d = static_cast(blah); -} - -static void FPU_FLD_I64(PhysPt addr,Bitu store_to) { - FPU_Reg blah; - blah.l.lower = mem_readd(addr); - blah.l.upper = mem_readd(addr+4); - fpu.regs[store_to].d = static_cast(blah.ll); -} - -static void FPU_FBLD(PhysPt addr,Bitu store_to) { - Bit64u val = 0; - Bitu in = 0; - Bit64u base = 1; - for(Bitu i = 0;i < 9;i++){ - in = mem_readb(addr + i); - val += ( (in&0xf) * base); //in&0xf shouldn't be higher then 9 - base *= 10; - val += ((( in>>4)&0xf) * base); - base *= 10; - } - - //last number, only now convert to float in order to get - //the best signification - Real64 temp = static_cast(val); - in = mem_readb(addr + 9); - temp += ( (in&0xf) * base ); - if(in&0x80) temp *= -1.0; - fpu.regs[store_to].d = temp; -} - - -static INLINE void FPU_FLD_F32_EA(PhysPt addr) { - FPU_FLD_F32(addr,8); -} -static INLINE void FPU_FLD_F64_EA(PhysPt addr) { - FPU_FLD_F64(addr,8); -} -static INLINE void FPU_FLD_I32_EA(PhysPt addr) { - FPU_FLD_I32(addr,8); -} -static INLINE void FPU_FLD_I16_EA(PhysPt addr) { - FPU_FLD_I16(addr,8); -} - - -static void FPU_FST_F32(PhysPt addr) { - union { - float f; - Bit32u l; - } blah; - //should depend on rounding method - blah.f = static_cast(fpu.regs[TOP].d); - mem_writed(addr,blah.l); -} - -static void FPU_FST_F64(PhysPt addr) { - mem_writed(addr,fpu.regs[TOP].l.lower); - mem_writed(addr+4,fpu.regs[TOP].l.upper); -} - -static void FPU_FST_F80(PhysPt addr) { - FPU_ST80(addr,TOP); -} - -static void FPU_FST_I16(PhysPt addr) { - mem_writew(addr,static_cast(FROUND(fpu.regs[TOP].d))); -} - -static void FPU_FST_I32(PhysPt addr) { - mem_writed(addr,static_cast(FROUND(fpu.regs[TOP].d))); -} - -static void FPU_FST_I64(PhysPt addr) { - FPU_Reg blah; - blah.ll = static_cast(FROUND(fpu.regs[TOP].d)); - mem_writed(addr,blah.l.lower); - mem_writed(addr+4,blah.l.upper); -} - -static void FPU_FBST(PhysPt addr) { - FPU_Reg val = fpu.regs[TOP]; - bool sign = false; - if(val.d<0.0){ //sign - sign=true; - val.d=-val.d; - } - //numbers from back to front - Real64 temp=val.d; - Bitu p; - for(Bitu i=0;i<9;i++){ - val.d=temp; - temp = static_cast(static_cast(floor(val.d/10.0))); - p = static_cast(val.d - 10.0*temp); - val.d=temp; - temp = static_cast(static_cast(floor(val.d/10.0))); - p |= (static_cast(val.d - 10.0*temp)<<4); - - mem_writeb(addr+i,p); - } - val.d=temp; - temp = static_cast(static_cast(floor(val.d/10.0))); - p = static_cast(val.d - 10.0*temp); - if(sign) - p|=0x80; - mem_writeb(addr+9,p); -} - -static void FPU_FADD(Bitu op1, Bitu op2){ - fpu.regs[op1].d+=fpu.regs[op2].d; - //flags and such :) - return; -} - -static void FPU_FSIN(void){ - fpu.regs[TOP].d = sin(fpu.regs[TOP].d); - FPU_SET_C2(0); - //flags and such :) - return; -} - -static void FPU_FSINCOS(void){ - Real64 temp = fpu.regs[TOP].d; - fpu.regs[TOP].d = sin(temp); - FPU_PUSH(cos(temp)); - FPU_SET_C2(0); - //flags and such :) - return; -} - -static void FPU_FCOS(void){ - fpu.regs[TOP].d = cos(fpu.regs[TOP].d); - FPU_SET_C2(0); - //flags and such :) - return; -} - -static void FPU_FSQRT(void){ - fpu.regs[TOP].d = sqrt(fpu.regs[TOP].d); - //flags and such :) - return; -} -static void FPU_FPATAN(void){ - fpu.regs[STV(1)].d = atan2(fpu.regs[STV(1)].d,fpu.regs[TOP].d); - FPU_FPOP(); - //flags and such :) - return; -} -static void FPU_FPTAN(void){ - fpu.regs[TOP].d = tan(fpu.regs[TOP].d); - FPU_PUSH(1.0); - FPU_SET_C2(0); - //flags and such :) - return; -} -static void FPU_FDIV(Bitu st, Bitu other){ - fpu.regs[st].d= fpu.regs[st].d/fpu.regs[other].d; - //flags and such :) - return; -} - -static void FPU_FDIVR(Bitu st, Bitu other){ - fpu.regs[st].d= fpu.regs[other].d/fpu.regs[st].d; - // flags and such :) - return; -} - -static void FPU_FMUL(Bitu st, Bitu other){ - fpu.regs[st].d*=fpu.regs[other].d; - //flags and such :) - return; -} - -static void FPU_FSUB(Bitu st, Bitu other){ - fpu.regs[st].d = fpu.regs[st].d - fpu.regs[other].d; - //flags and such :) - return; -} - -static void FPU_FSUBR(Bitu st, Bitu other){ - fpu.regs[st].d= fpu.regs[other].d - fpu.regs[st].d; - //flags and such :) - return; -} - -static void FPU_FXCH(Bitu st, Bitu other){ - FPU_Tag tag = fpu.tags[other]; - FPU_Reg reg = fpu.regs[other]; - fpu.tags[other] = fpu.tags[st]; - fpu.regs[other] = fpu.regs[st]; - fpu.tags[st] = tag; - fpu.regs[st] = reg; -} - -static void FPU_FST(Bitu st, Bitu other){ - fpu.tags[other] = fpu.tags[st]; - fpu.regs[other] = fpu.regs[st]; -} - - -static void FPU_FCOM(Bitu st, Bitu other){ - if(((fpu.tags[st] != TAG_Valid) && (fpu.tags[st] != TAG_Zero)) || - ((fpu.tags[other] != TAG_Valid) && (fpu.tags[other] != TAG_Zero))){ - FPU_SET_C3(1);FPU_SET_C2(1);FPU_SET_C0(1);return; - } - if(fpu.regs[st].d == fpu.regs[other].d){ - FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0);return; - } - if(fpu.regs[st].d < fpu.regs[other].d){ - FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C0(1);return; - } - // st > other - FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C0(0);return; -} - -static void FPU_FUCOM(Bitu st, Bitu other){ - //does atm the same as fcom - FPU_FCOM(st,other); -} - -static void FPU_FRNDINT(void){ - Bit64s temp= static_cast(FROUND(fpu.regs[TOP].d)); - fpu.regs[TOP].d=static_cast(temp); -} - -static void FPU_FPREM(void){ - Real64 valtop = fpu.regs[TOP].d; - Real64 valdiv = fpu.regs[STV(1)].d; - Bit64s ressaved = static_cast( (valtop/valdiv) ); -// Some backups -// Real64 res=valtop - ressaved*valdiv; -// res= fmod(valtop,valdiv); - fpu.regs[TOP].d = valtop - ressaved*valdiv; - FPU_SET_C0(static_cast(ressaved&4)); - FPU_SET_C3(static_cast(ressaved&2)); - FPU_SET_C1(static_cast(ressaved&1)); - FPU_SET_C2(0); -} - -static void FPU_FPREM1(void){ - Real64 valtop = fpu.regs[TOP].d; - Real64 valdiv = fpu.regs[STV(1)].d; - double quot = valtop/valdiv; - double quotf = floor(quot); - Bit64s ressaved; - if (quot-quotf>0.5) ressaved = static_cast(quotf+1); - else if (quot-quotf<0.5) ressaved = static_cast(quotf); - else ressaved = static_cast((((static_cast(quotf))&1)!=0)?(quotf+1):(quotf)); - fpu.regs[TOP].d = valtop - ressaved*valdiv; - FPU_SET_C0(static_cast(ressaved&4)); - FPU_SET_C3(static_cast(ressaved&2)); - FPU_SET_C1(static_cast(ressaved&1)); - FPU_SET_C2(0); -} - -static void FPU_FXAM(void){ - if(fpu.regs[TOP].ll & LONGTYPE(0x8000000000000000)) //sign - { - FPU_SET_C1(1); - } - else - { - FPU_SET_C1(0); - } - if(fpu.tags[TOP] == TAG_Empty) - { - FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(1); - return; - } - if(fpu.regs[TOP].d == 0.0) //zero or normalized number. - { - FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0); - } - else - { - FPU_SET_C3(0);FPU_SET_C2(1);FPU_SET_C0(0); - } -} - - -static void FPU_F2XM1(void){ - fpu.regs[TOP].d = pow(2.0,fpu.regs[TOP].d) - 1; - return; -} - -static void FPU_FYL2X(void){ - fpu.regs[STV(1)].d*=log(fpu.regs[TOP].d)/log(static_cast(2.0)); - FPU_FPOP(); - return; -} - -static void FPU_FYL2XP1(void){ - fpu.regs[STV(1)].d*=log(fpu.regs[TOP].d+1.0)/log(static_cast(2.0)); - FPU_FPOP(); - return; -} - -static void FPU_FSCALE(void){ - fpu.regs[TOP].d *= pow(2.0,static_cast(static_cast(fpu.regs[STV(1)].d))); - return; //2^x where x is chopped. -} - -static void FPU_FSTENV(PhysPt addr){ - FPU_SET_TOP(TOP); - if(!cpu.code.big) { - mem_writew(addr+0,static_cast(fpu.cw)); - mem_writew(addr+2,static_cast(fpu.sw)); - mem_writew(addr+4,static_cast(FPU_GetTag())); - } else { - mem_writed(addr+0,static_cast(fpu.cw)); - mem_writed(addr+4,static_cast(fpu.sw)); - mem_writed(addr+8,static_cast(FPU_GetTag())); - } -} - -static void FPU_FLDENV(PhysPt addr){ - Bit16u tag; - Bit32u tagbig; - Bitu cw; - if(!cpu.code.big) { - cw = mem_readw(addr+0); - fpu.sw = mem_readw(addr+2); - tag = mem_readw(addr+4); - } else { - cw = mem_readd(addr+0); - fpu.sw = (Bit16u)mem_readd(addr+4); - tagbig = mem_readd(addr+8); - tag = static_cast(tagbig); - } - FPU_SetTag(tag); - FPU_SetCW(cw); - TOP = FPU_GET_TOP(); -} - -static void FPU_FSAVE(PhysPt addr){ - FPU_FSTENV(addr); - Bitu start = (cpu.code.big?28:14); - for(Bitu i = 0;i < 8;i++){ - FPU_ST80(addr+start,STV(i)); - start += 10; - } - FPU_FINIT(); -} - -static void FPU_FRSTOR(PhysPt addr){ - FPU_FLDENV(addr); - Bitu start = (cpu.code.big?28:14); - for(Bitu i = 0;i < 8;i++){ - fpu.regs[STV(i)].d = FPU_FLD80(addr+start); - start += 10; - } -} - -static void FPU_FXTRACT(void) { - // function stores real bias in st and - // pushes the significant number onto the stack - // if double ever uses a different base please correct this function - - FPU_Reg test = fpu.regs[TOP]; - Bit64s exp80 = test.ll&LONGTYPE(0x7ff0000000000000); - Bit64s exp80final = (exp80>>52) - BIAS64; - Real64 mant = test.d / (pow(2.0,static_cast(exp80final))); - fpu.regs[TOP].d = static_cast(exp80final); - FPU_PUSH(mant); -} - -static void FPU_FCHS(void){ - fpu.regs[TOP].d = -1.0*(fpu.regs[TOP].d); -} - -static void FPU_FABS(void){ - fpu.regs[TOP].d = fabs(fpu.regs[TOP].d); -} - -static void FPU_FTST(void){ - fpu.regs[8].d = 0.0; - FPU_FCOM(TOP,8); -} - -static void FPU_FLD1(void){ - FPU_PREP_PUSH(); - fpu.regs[TOP].d = 1.0; -} - -static void FPU_FLDL2T(void){ - FPU_PREP_PUSH(); - fpu.regs[TOP].d = L2T; -} - -static void FPU_FLDL2E(void){ - FPU_PREP_PUSH(); - fpu.regs[TOP].d = L2E; -} - -static void FPU_FLDPI(void){ - FPU_PREP_PUSH(); - fpu.regs[TOP].d = PI; -} - -static void FPU_FLDLG2(void){ - FPU_PREP_PUSH(); - fpu.regs[TOP].d = LG2; -} - -static void FPU_FLDLN2(void){ - FPU_PREP_PUSH(); - fpu.regs[TOP].d = LN2; -} - -static void FPU_FLDZ(void){ - FPU_PREP_PUSH(); - fpu.regs[TOP].d = 0.0; - fpu.tags[TOP] = TAG_Zero; -} - - -static INLINE void FPU_FADD_EA(Bitu op1){ - FPU_FADD(op1,8); -} -static INLINE void FPU_FMUL_EA(Bitu op1){ - FPU_FMUL(op1,8); -} -static INLINE void FPU_FSUB_EA(Bitu op1){ - FPU_FSUB(op1,8); -} -static INLINE void FPU_FSUBR_EA(Bitu op1){ - FPU_FSUBR(op1,8); -} -static INLINE void FPU_FDIV_EA(Bitu op1){ - FPU_FDIV(op1,8); -} -static INLINE void FPU_FDIVR_EA(Bitu op1){ - FPU_FDIVR(op1,8); -} -static INLINE void FPU_FCOM_EA(Bitu op1){ - FPU_FCOM(op1,8); -} - diff --git a/src/fpu/fpu_instructions_x86.h b/src/fpu/fpu_instructions_x86.h deleted file mode 100644 index 52ce31e..0000000 --- a/src/fpu/fpu_instructions_x86.h +++ /dev/null @@ -1,1489 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: fpu_instructions_x86.h,v 1.6 2008/01/06 16:45:42 c2woody Exp $ */ - - -// #define WEAK_EXCEPTIONS - - -#if defined (_MSC_VER) - -#ifdef WEAK_EXCEPTIONS -#define clx -#else -#define clx fclex -#endif - -#ifdef WEAK_EXCEPTIONS -#define FPUD_LOAD(op,szI,szA) \ - __asm { \ - __asm mov ebx, store_to \ - __asm shl ebx, 4 \ - __asm op szI PTR fpu.p_regs[128].m1 \ - __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ - } -#else -#define FPUD_LOAD(op,szI,szA) \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, 8 \ - __asm shl eax, 4 \ - __asm mov ebx, store_to \ - __asm shl ebx, 4 \ - __asm fclex \ - __asm op szI PTR fpu.p_regs[eax].m1 \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ - } \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); -#endif - -#ifdef WEAK_EXCEPTIONS -#define FPUD_LOAD_EA(op,szI,szA) \ - __asm { \ - __asm op szI PTR fpu.p_regs[128].m1 \ - } -#else -#define FPUD_LOAD_EA(op,szI,szA) \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, 8 \ - __asm shl eax, 4 \ - __asm fclex \ - __asm op szI PTR fpu.p_regs[eax].m1 \ - __asm fnstsw new_sw \ - } \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); -#endif - -#ifdef WEAK_EXCEPTIONS -#define FPUD_STORE(op,szI,szA) \ - Bit16u save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm mov eax, TOP \ - __asm fldcw fpu.cw_mask_all \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm op szI PTR fpu.p_regs[128].m1 \ - __asm fldcw save_cw \ - } -#else -#define FPUD_STORE(op,szI,szA) \ - Bit16u new_sw,save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm fldcw fpu.cw_mask_all \ - __asm mov eax, TOP \ - __asm shl eax, 4 \ - __asm mov ebx, 8 \ - __asm shl ebx, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm clx \ - __asm op szI PTR fpu.p_regs[ebx].m1 \ - __asm fnstsw new_sw \ - __asm fldcw save_cw \ - } \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); -#endif - -// handles fsin,fcos,f2xm1,fchs,fabs -#define FPUD_TRIG(op) \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, TOP \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm clx \ - __asm op \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - } \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); - -// handles fsincos -#define FPUD_SINCOS() \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, TOP \ - __asm mov ebx, eax \ - __asm dec ebx \ - __asm and ebx, 7 \ - __asm shl eax, 4 \ - __asm shl ebx, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm clx \ - __asm fsincos \ - __asm fnstsw new_sw \ - __asm mov cx, new_sw \ - __asm and ch, 0x04 \ - __asm jnz argument_too_large1 \ - __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm jmp end_sincos \ - __asm argument_too_large1: \ - __asm fstp st(0) \ - __asm end_sincos: \ - } \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ - if ((new_sw&0x0400)==0) FPU_PREP_PUSH(); - -// handles fptan -#define FPUD_PTAN() \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, TOP \ - __asm mov ebx, eax \ - __asm dec ebx \ - __asm and ebx, 7 \ - __asm shl eax, 4 \ - __asm shl ebx, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm clx \ - __asm fptan \ - __asm fnstsw new_sw \ - __asm mov cx, new_sw \ - __asm and ch, 0x04 \ - __asm jnz argument_too_large2 \ - __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm jmp end_ptan \ - __asm argument_too_large2: \ - __asm fstp st(0) \ - __asm end_ptan: \ - } \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ - if ((new_sw&0x0400)==0) FPU_PREP_PUSH(); - -// handles fxtract -#ifdef WEAK_EXCEPTIONS -#define FPUD_XTRACT \ - __asm { \ - __asm mov eax, TOP \ - __asm mov ebx, eax \ - __asm dec ebx \ - __asm and ebx, 7 \ - __asm shl eax, 4 \ - __asm shl ebx, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fxtract \ - __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - } \ - FPU_PREP_PUSH(); -#else -#define FPUD_XTRACT \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, TOP \ - __asm mov ebx, eax \ - __asm dec ebx \ - __asm and ebx, 7 \ - __asm shl eax, 4 \ - __asm shl ebx, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fclex \ - __asm fxtract \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - } \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \ - FPU_PREP_PUSH(); -#endif - -// handles fadd,fmul,fsub,fsubr -#ifdef WEAK_EXCEPTIONS -#define FPUD_ARITH1(op) \ - Bit16u save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm mov eax, op1 \ - __asm shl eax, 4 \ - __asm fldcw fpu.cw_mask_all \ - __asm mov ebx, op2 \ - __asm shl ebx, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm op st(1), st(0) \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fldcw save_cw \ - } -#else -#define FPUD_ARITH1(op) \ - Bit16u new_sw,save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm fldcw fpu.cw_mask_all \ - __asm mov eax, op1 \ - __asm shl eax, 4 \ - __asm mov ebx, op2 \ - __asm shl ebx, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm clx \ - __asm op st(1), st(0) \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fldcw save_cw \ - } \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); -#endif - -// handles fadd,fmul,fsub,fsubr -#ifdef WEAK_EXCEPTIONS -#define FPUD_ARITH1_EA(op) \ - Bit16u save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm mov eax, op1 \ - __asm fldcw fpu.cw_mask_all \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fxch \ - __asm op st(1), st(0) \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fldcw save_cw \ - } -#else -#define FPUD_ARITH1_EA(op) \ - Bit16u new_sw,save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm fldcw fpu.cw_mask_all \ - __asm mov eax, op1 \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fxch \ - __asm clx \ - __asm op st(1), st(0) \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fldcw save_cw \ - } \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); -#endif - -// handles fsqrt,frndint -#ifdef WEAK_EXCEPTIONS -#define FPUD_ARITH2(op) \ - Bit16u save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm mov eax, TOP \ - __asm fldcw fpu.cw_mask_all \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm op \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fldcw save_cw \ - } -#else -#define FPUD_ARITH2(op) \ - Bit16u new_sw,save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm fldcw fpu.cw_mask_all \ - __asm mov eax, TOP \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm clx \ - __asm op \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fldcw save_cw \ - } \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); -#endif - -// handles fdiv,fdivr -#ifdef WEAK_EXCEPTIONS -#define FPUD_ARITH3(op) \ - Bit16u save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm mov eax, op1 \ - __asm shl eax, 4 \ - __asm fldcw fpu.cw_mask_all \ - __asm mov ebx, op2 \ - __asm shl ebx, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm op st(1), st(0) \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fldcw save_cw \ - } -#else -#define FPUD_ARITH3(op) \ - Bit16u new_sw,save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm fldcw fpu.cw_mask_all \ - __asm mov eax, op1 \ - __asm shl eax, 4 \ - __asm mov ebx, op2 \ - __asm shl ebx, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fclex \ - __asm op st(1), st(0) \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fldcw save_cw \ - } \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); -#endif - -// handles fdiv,fdivr -#ifdef WEAK_EXCEPTIONS -#define FPUD_ARITH3_EA(op) \ - Bit16u save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm mov eax, op1 \ - __asm fldcw fpu.cw_mask_all \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fxch \ - __asm op st(1), st(0) \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fldcw save_cw \ - } -#else -#define FPUD_ARITH3_EA(op) \ - Bit16u new_sw,save_cw; \ - __asm { \ - __asm fnstcw save_cw \ - __asm mov eax, op1 \ - __asm fldcw fpu.cw_mask_all \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fxch \ - __asm fclex \ - __asm op st(1), st(0) \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fldcw save_cw \ - } \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); -#endif - -// handles fprem,fprem1,fscale -#define FPUD_REMINDER(op) \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, TOP \ - __asm mov ebx, eax \ - __asm inc ebx \ - __asm and ebx, 7 \ - __asm shl ebx, 4 \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fclex \ - __asm op \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fstp st(0) \ - } \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); - -// handles fcom,fucom -#define FPUD_COMPARE(op) \ - Bit16u new_sw; \ - __asm { \ - __asm mov ebx, op2 \ - __asm mov eax, op1 \ - __asm shl ebx, 4 \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm clx \ - __asm op \ - __asm fnstsw new_sw \ - } \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); - -#define FPUD_COMPARE_EA(op) \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, op1 \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm clx \ - __asm op \ - __asm fnstsw new_sw \ - } \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); - -// handles fxam,ftst -#define FPUD_EXAMINE(op) \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, TOP \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm clx \ - __asm op \ - __asm fnstsw new_sw \ - __asm fstp st(0) \ - } \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); - -// handles fpatan,fyl2xp1 -#ifdef WEAK_EXCEPTIONS -#define FPUD_WITH_POP(op) \ - __asm { \ - __asm mov eax, TOP \ - __asm mov ebx, eax \ - __asm inc ebx \ - __asm and ebx, 7 \ - __asm shl ebx, 4 \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm op \ - __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ - } \ - FPU_FPOP(); -#else -#define FPUD_WITH_POP(op) \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, TOP \ - __asm mov ebx, eax \ - __asm inc ebx \ - __asm and ebx, 7 \ - __asm shl ebx, 4 \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fclex \ - __asm op \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ - } \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \ - FPU_FPOP(); -#endif - -// handles fyl2x -#ifdef WEAK_EXCEPTIONS -#define FPUD_FYL2X(op) \ - __asm { \ - __asm mov eax, TOP \ - __asm mov ebx, eax \ - __asm inc ebx \ - __asm and ebx, 7 \ - __asm shl ebx, 4 \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm op \ - __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ - } \ - FPU_FPOP(); -#else -#define FPUD_FYL2X(op) \ - Bit16u new_sw; \ - __asm { \ - __asm mov eax, TOP \ - __asm mov ebx, eax \ - __asm inc ebx \ - __asm and ebx, 7 \ - __asm shl ebx, 4 \ - __asm shl eax, 4 \ - __asm fld TBYTE PTR fpu.p_regs[ebx].m1 \ - __asm fld TBYTE PTR fpu.p_regs[eax].m1 \ - __asm fclex \ - __asm op \ - __asm fnstsw new_sw \ - __asm fstp TBYTE PTR fpu.p_regs[ebx].m1 \ - } \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \ - FPU_FPOP(); -#endif - -// load math constants -#define FPUD_LOAD_CONST(op) \ - FPU_PREP_PUSH(); \ - __asm { \ - __asm mov eax, TOP \ - __asm shl eax, 4 \ - __asm clx \ - __asm op \ - __asm fstp TBYTE PTR fpu.p_regs[eax].m1 \ - } \ - -#else - -#ifdef WEAK_EXCEPTIONS -#define clx -#else -#define clx "fclex" -#endif - -#ifdef WEAK_EXCEPTIONS -#define FPUD_LOAD(op,szI,szA) \ - __asm__ volatile ( \ - "movl $128, %%eax \n" \ - "shl $4, %0 \n" \ - #op #szA " (%1, %%eax) \n" \ - "fstpt (%1, %0) " \ - : \ - : "r" (store_to), "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); -#else -#define FPUD_LOAD(op,szI,szA) \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "movl $8, %%eax \n" \ - "shl $4, %%eax \n" \ - "shl $4, %1 \n" \ - "fclex \n" \ - #op #szA " (%2, %%eax) \n" \ - "fnstsw %0 \n" \ - "fstpt (%2, %1) " \ - : "=m" (new_sw) \ - : "r" (store_to), "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); -#endif - -#ifdef WEAK_EXCEPTIONS -#define FPUD_LOAD_EA(op,szI,szA) \ - __asm__ volatile ( \ - "movl $128, %%eax \n" \ - #op #szA " (%0, %%eax) \n" \ - : \ - : "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); -#else -#define FPUD_LOAD_EA(op,szI,szA) \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "movl $8, %%eax \n" \ - "shl $4, %%eax \n" \ - "fclex \n" \ - #op #szA " (%1, %%eax) \n" \ - "fnstsw %0 \n" \ - : "=m" (new_sw) \ - : "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); -#endif - -#ifdef WEAK_EXCEPTIONS -#define FPUD_STORE(op,szI,szA) \ - Bit16u save_cw; \ - __asm__ volatile ( \ - "fnstcw %0 \n" \ - "shll $4, %1 \n" \ - "fldcw %3 \n" \ - "movl $128, %%eax \n" \ - "fldt (%2, %1) \n" \ - #op #szA " (%2, %%eax) \n" \ - "fldcw %0 " \ - : "=m" (save_cw) \ - : "r" (TOP), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "eax", "memory" \ - ); -#else -#define FPUD_STORE(op,szI,szA) \ - Bit16u new_sw,save_cw; \ - __asm__ volatile ( \ - "fnstcw %1 \n" \ - "fldcw %4 \n" \ - "shll $4, %2 \n" \ - "movl $8, %%eax \n" \ - "shl $4, %%eax \n" \ - "fldt (%3, %2) \n" \ - clx" \n" \ - #op #szA " (%3, %%eax) \n" \ - "fnstsw %0 \n" \ - "fldcw %1 " \ - : "=m" (new_sw), "=m" (save_cw) \ - : "r" (TOP), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "eax", "memory" \ - ); \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); -#endif - -// handles fsin,fcos,f2xm1,fchs,fabs -#define FPUD_TRIG(op) \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "shll $4, %1 \n" \ - "fldt (%2, %1) \n" \ - clx" \n" \ - #op" \n" \ - "fnstsw %0 \n" \ - "fstpt (%2, %1) " \ - : "=m" (new_sw) \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "memory" \ - ); \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); - -// handles fsincos -#define FPUD_SINCOS() \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "movl %1, %%eax \n" \ - "shll $4, %1 \n" \ - "decl %%eax \n" \ - "andl $7, %%eax \n" \ - "shll $4, %%eax \n" \ - "fldt (%2, %1) \n" \ - clx" \n" \ - "fsincos \n" \ - "fnstsw %0 \n" \ - "fstpt (%2, %%eax) \n" \ - "movw %0, %%ax \n" \ - "sahf \n" \ - "jp argument_too_large1 \n" \ - "fstpt (%2, %1) \n" \ - "argument_too_large1: " \ - : "=m" (new_sw) \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "eax", "cc", "memory" \ - ); \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ - if ((new_sw&0x0400)==0) FPU_PREP_PUSH(); - -// handles fptan -#define FPUD_PTAN() \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "movl %1, %%eax \n" \ - "shll $4, %1 \n" \ - "decl %%eax \n" \ - "andl $7, %%eax \n" \ - "shll $4, %%eax \n" \ - "fldt (%2, %1) \n" \ - clx" \n" \ - "fptan \n" \ - "fnstsw %0 \n" \ - "fstpt (%2, %%eax) \n" \ - "movw %0, %%ax \n" \ - "sahf \n" \ - "jp argument_too_large2 \n" \ - "fstpt (%2, %1) \n" \ - "argument_too_large2: " \ - : "=m" (new_sw) \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "eax", "cc", "memory" \ - ); \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); \ - if ((new_sw&0x0400)==0) FPU_PREP_PUSH(); - -// handles fxtract -#ifdef WEAK_EXCEPTIONS -#define FPUD_XTRACT \ - __asm__ volatile ( \ - "movl %0, %%eax \n" \ - "shll $4, %0 \n" \ - "decl %%eax \n" \ - "andl $7, %%eax \n" \ - "shll $4, %%eax \n" \ - "fldt (%1, %0) \n" \ - "fxtract \n" \ - "fstpt (%1, %%eax) \n" \ - "fstpt (%1, %0) " \ - : \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); \ - FPU_PREP_PUSH(); -#else -#define FPUD_XTRACT \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "movl %1, %%eax \n" \ - "shll $4, %1 \n" \ - "decl %%eax \n" \ - "andl $7, %%eax \n" \ - "shll $4, %%eax \n" \ - "fldt (%2, %1) \n" \ - "fclex \n" \ - "fxtract \n" \ - "fnstsw %0 \n" \ - "fstpt (%2, %%eax) \n" \ - "fstpt (%2, %1) " \ - : "=m" (new_sw) \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \ - FPU_PREP_PUSH(); -#endif - -// handles fadd,fmul,fsub,fsubr -#ifdef WEAK_EXCEPTIONS -#define FPUD_ARITH1(op) \ - Bit16u save_cw; \ - __asm__ volatile ( \ - "fnstcw %0 \n" \ - "fldcw %4 \n" \ - "shll $4, %2 \n" \ - "shll $4, %1 \n" \ - "fldt (%3, %2) \n" \ - "fldt (%3, %1) \n" \ - #op" \n" \ - "fstpt (%3, %1) \n" \ - "fldcw %0 " \ - : "=m" (save_cw) \ - : "r" (op1), "r" (op2), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "memory" \ - ); -#else -#define FPUD_ARITH1(op) \ - Bit16u new_sw,save_cw; \ - __asm__ volatile ( \ - "fnstcw %1 \n" \ - "fldcw %5 \n" \ - "shll $4, %3 \n" \ - "shll $4, %2 \n" \ - "fldt (%4, %3) \n" \ - "fldt (%4, %2) \n" \ - clx" \n" \ - #op" \n" \ - "fnstsw %0 \n" \ - "fstpt (%4, %2) \n" \ - "fldcw %1 " \ - : "=m" (new_sw), "=m" (save_cw) \ - : "r" (op1), "r" (op2), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "memory" \ - ); \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); -#endif - -// handles fadd,fmul,fsub,fsubr -#ifdef WEAK_EXCEPTIONS -#define FPUD_ARITH1_EA(op) \ - Bit16u save_cw; \ - __asm__ volatile ( \ - "fnstcw %0 \n" \ - "fldcw %3 \n" \ - "shll $4, %1 \n" \ - "fldt (%2, %1) \n" \ - #op" \n" \ - "fstpt (%2, %1) \n" \ - "fldcw %0 " \ - : "=m" (save_cw) \ - : "r" (op1), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "memory" \ - ); -#else -#define FPUD_ARITH1_EA(op) \ - Bit16u new_sw,save_cw; \ - __asm__ volatile ( \ - "fnstcw %1 \n" \ - "fldcw %4 \n" \ - "shll $4, %2 \n" \ - "fldt (%3, %2) \n" \ - clx" \n" \ - #op" \n" \ - "fnstsw %0 \n" \ - "fstpt (%3, %2) \n" \ - "fldcw %1 " \ - : "=m" (new_sw), "=m" (save_cw) \ - : "r" (op1), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "memory" \ - ); \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); -#endif - -// handles fsqrt,frndint -#ifdef WEAK_EXCEPTIONS -#define FPUD_ARITH2(op) \ - Bit16u save_cw; \ - __asm__ volatile ( \ - "fnstcw %0 \n" \ - "fldcw %3 \n" \ - "shll $4, %1 \n" \ - "fldt (%2, %1) \n" \ - #op" \n" \ - "fstpt (%2, %1) \n" \ - "fldcw %0 " \ - : "=m" (save_cw) \ - : "r" (TOP), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "memory" \ - ); -#else -#define FPUD_ARITH2(op) \ - Bit16u new_sw,save_cw; \ - __asm__ volatile ( \ - "fnstcw %1 \n" \ - "fldcw %4 \n" \ - "shll $4, %2 \n" \ - "fldt (%3, %2) \n" \ - clx" \n" \ - #op" \n" \ - "fnstsw %0 \n" \ - "fstpt (%3, %2) \n" \ - "fldcw %1 " \ - : "=m" (new_sw), "=m" (save_cw) \ - : "r" (TOP), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "memory" \ - ); \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); -#endif - -// handles fdiv,fdivr -#ifdef WEAK_EXCEPTIONS -#define FPUD_ARITH3(op) \ - Bit16u save_cw; \ - __asm__ volatile ( \ - "fnstcw %0 \n" \ - "fldcw %4 \n" \ - "shll $4, %2 \n" \ - "shll $4, %1 \n" \ - "fldt (%3, %2) \n" \ - "fldt (%3, %1) \n" \ - #op" \n" \ - "fstpt (%3, %1) \n" \ - "fldcw %0 " \ - : "=m" (save_cw) \ - : "r" (op1), "r" (op2), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "memory" \ - ); -#else -#define FPUD_ARITH3(op) \ - Bit16u new_sw,save_cw; \ - __asm__ volatile ( \ - "fnstcw %1 \n" \ - "fldcw %5 \n" \ - "shll $4, %3 \n" \ - "shll $4, %2 \n" \ - "fldt (%4, %3) \n" \ - "fldt (%4, %2) \n" \ - "fclex \n" \ - #op" \n" \ - "fnstsw %0 \n" \ - "fstpt (%4, %2) \n" \ - "fldcw %1 " \ - : "=m" (new_sw), "=m" (save_cw) \ - : "r" (op1), "r" (op2), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "memory" \ - ); \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); -#endif - -// handles fdiv,fdivr -#ifdef WEAK_EXCEPTIONS -#define FPUD_ARITH3_EA(op) \ - Bit16u save_cw; \ - __asm__ volatile ( \ - "fnstcw %0 \n" \ - "fldcw %3 \n" \ - "shll $4, %1 \n" \ - "fldt (%2, %1) \n" \ - #op" \n" \ - "fstpt (%2, %1) \n" \ - "fldcw %0 " \ - : "=m" (save_cw) \ - : "r" (op1), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "memory" \ - ); -#else -#define FPUD_ARITH3_EA(op) \ - Bit16u new_sw,save_cw; \ - __asm__ volatile ( \ - "fnstcw %1 \n" \ - "fldcw %4 \n" \ - "shll $4, %2 \n" \ - "fldt (%3, %2) \n" \ - "fclex \n" \ - #op" \n" \ - "fnstsw %0 \n" \ - "fstpt (%3, %2) \n" \ - "fldcw %1 " \ - : "=m" (new_sw), "=m" (save_cw) \ - : "r" (op1), "r" (fpu.p_regs), "m" (fpu.cw_mask_all) \ - : "memory" \ - ); \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); -#endif - -// handles fprem,fprem1,fscale -#define FPUD_REMINDER(op) \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "movl %1, %%eax \n" \ - "incl %%eax \n" \ - "andl $7, %%eax \n" \ - "shll $4, %%eax \n" \ - "shll $4, %1 \n" \ - "fldt (%2, %%eax) \n" \ - "fldt (%2, %1) \n" \ - "fclex \n" \ - #op" \n" \ - "fnstsw %0 \n" \ - "fstpt (%2, %1) \n" \ - "fstp %%st(0) " \ - : "=m" (new_sw) \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); - -// handles fcom,fucom -#define FPUD_COMPARE(op) \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "shll $4, %2 \n" \ - "shll $4, %1 \n" \ - "fldt (%3, %2) \n" \ - "fldt (%3, %1) \n" \ - clx" \n" \ - #op" \n" \ - "fnstsw %0 " \ - : "=m" (new_sw) \ - : "r" (op1), "r" (op2), "r" (fpu.p_regs) \ - : "memory" \ - ); \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); - -// handles fcom,fucom -#define FPUD_COMPARE_EA(op) \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "shll $4, %1 \n" \ - "fldt (%2, %1) \n" \ - clx" \n" \ - #op" \n" \ - "fnstsw %0 " \ - : "=m" (new_sw) \ - : "r" (op1), "r" (fpu.p_regs) \ - : "memory" \ - ); \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); - -// handles fxam,ftst -#define FPUD_EXAMINE(op) \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "shll $4, %1 \n" \ - "fldt (%2, %1) \n" \ - clx" \n" \ - #op" \n" \ - "fnstsw %0 \n" \ - "fstp %%st(0) " \ - : "=m" (new_sw) \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "memory" \ - ); \ - fpu.sw=(new_sw&exc_mask)|(fpu.sw&0x80ff); - -// handles fpatan,fyl2xp1 -#ifdef WEAK_EXCEPTIONS -#define FPUD_WITH_POP(op) \ - __asm__ volatile ( \ - "movl %0, %%eax \n" \ - "incl %%eax \n" \ - "andl $7, %%eax \n" \ - "shll $4, %%eax \n" \ - "shll $4, %0 \n" \ - "fldt (%1, %%eax) \n" \ - "fldt (%1, %0) \n" \ - #op" \n" \ - "fstpt (%1, %%eax) \n" \ - : \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); \ - FPU_FPOP(); -#else -#define FPUD_WITH_POP(op) \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "movl %1, %%eax \n" \ - "incl %%eax \n" \ - "andl $7, %%eax \n" \ - "shll $4, %%eax \n" \ - "shll $4, %1 \n" \ - "fldt (%2, %%eax) \n" \ - "fldt (%2, %1) \n" \ - "fclex \n" \ - #op" \n" \ - "fnstsw %0 \n" \ - "fstpt (%2, %%eax) \n" \ - : "=m" (new_sw) \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \ - FPU_FPOP(); -#endif - -// handles fyl2x -#ifdef WEAK_EXCEPTIONS -#define FPUD_FYL2X(op) \ - __asm__ volatile ( \ - "movl %0, %%eax \n" \ - "incl %%eax \n" \ - "andl $7, %%eax \n" \ - "shll $4, %%eax \n" \ - "shll $4, %0 \n" \ - "fldt (%1, %%eax) \n" \ - "fldt (%1, %0) \n" \ - #op" \n" \ - "fstpt (%1, %%eax) \n" \ - : \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); \ - FPU_FPOP(); -#else -#define FPUD_FYL2X(op) \ - Bit16u new_sw; \ - __asm__ volatile ( \ - "movl %1, %%eax \n" \ - "incl %%eax \n" \ - "andl $7, %%eax \n" \ - "shll $4, %%eax \n" \ - "shll $4, %1 \n" \ - "fldt (%2, %%eax) \n" \ - "fldt (%2, %1) \n" \ - "fclex \n" \ - #op" \n" \ - "fnstsw %0 \n" \ - "fstpt (%2, %%eax) \n" \ - : "=m" (new_sw) \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "eax", "memory" \ - ); \ - fpu.sw=(new_sw&0xffbf)|(fpu.sw&0x80ff); \ - FPU_FPOP(); -#endif - -// load math constants -#define FPUD_LOAD_CONST(op) \ - FPU_PREP_PUSH(); \ - __asm__ volatile ( \ - "shll $4, %0 \n" \ - clx" \n" \ - #op" \n" \ - "fstpt (%1, %0) \n" \ - : \ - : "r" (TOP), "r" (fpu.p_regs) \ - : "memory" \ - ); - -#endif - -#ifdef WEAK_EXCEPTIONS -const Bit16u exc_mask=0x7f00; -#else -const Bit16u exc_mask=0xffbf; -#endif - -static void FPU_FINIT(void) { - FPU_SetCW(0x37F); - fpu.sw=0; - TOP=FPU_GET_TOP(); - fpu.tags[0]=TAG_Empty; - fpu.tags[1]=TAG_Empty; - fpu.tags[2]=TAG_Empty; - fpu.tags[3]=TAG_Empty; - fpu.tags[4]=TAG_Empty; - fpu.tags[5]=TAG_Empty; - fpu.tags[6]=TAG_Empty; - fpu.tags[7]=TAG_Empty; - fpu.tags[8]=TAG_Valid; // is only used by us -} - -static void FPU_FCLEX(void){ - fpu.sw&=0x7f00; //should clear exceptions -} - -static void FPU_FNOP(void){ -} - -static void FPU_PREP_PUSH(void){ - TOP = (TOP - 1) &7; - fpu.tags[TOP]=TAG_Valid; -} - -static void FPU_FPOP(void){ - fpu.tags[TOP]=TAG_Empty; - TOP = ((TOP+1)&7); -} - -static void FPU_FLD_F32(PhysPt addr,Bitu store_to) { - fpu.p_regs[8].m1 = mem_readd(addr); - FPUD_LOAD(fld,DWORD,s) -} - -static void FPU_FLD_F32_EA(PhysPt addr) { - fpu.p_regs[8].m1 = mem_readd(addr); - FPUD_LOAD_EA(fld,DWORD,s) -} - -static void FPU_FLD_F64(PhysPt addr,Bitu store_to) { - fpu.p_regs[8].m1 = mem_readd(addr); - fpu.p_regs[8].m2 = mem_readd(addr+4); - FPUD_LOAD(fld,QWORD,l) -} - -static void FPU_FLD_F64_EA(PhysPt addr) { - fpu.p_regs[8].m1 = mem_readd(addr); - fpu.p_regs[8].m2 = mem_readd(addr+4); - FPUD_LOAD_EA(fld,QWORD,l) -} - -static void FPU_FLD_F80(PhysPt addr) { - fpu.p_regs[TOP].m1 = mem_readd(addr); - fpu.p_regs[TOP].m2 = mem_readd(addr+4); - fpu.p_regs[TOP].m3 = mem_readw(addr+8); - FPU_SET_C1(0); -} - -static void FPU_FLD_I16(PhysPt addr,Bitu store_to) { - fpu.p_regs[8].m1 = (Bit32u)mem_readw(addr); - FPUD_LOAD(fild,WORD,) -} - -static void FPU_FLD_I16_EA(PhysPt addr) { - fpu.p_regs[8].m1 = (Bit32u)mem_readw(addr); - FPUD_LOAD_EA(fild,WORD,) -} - -static void FPU_FLD_I32(PhysPt addr,Bitu store_to) { - fpu.p_regs[8].m1 = mem_readd(addr); - FPUD_LOAD(fild,DWORD,l) -} - -static void FPU_FLD_I32_EA(PhysPt addr) { - fpu.p_regs[8].m1 = mem_readd(addr); - FPUD_LOAD_EA(fild,DWORD,l) -} - -static void FPU_FLD_I64(PhysPt addr,Bitu store_to) { - fpu.p_regs[8].m1 = mem_readd(addr); - fpu.p_regs[8].m2 = mem_readd(addr+4); - FPUD_LOAD(fild,QWORD,q) -} - -static void FPU_FBLD(PhysPt addr,Bitu store_to) { - fpu.p_regs[8].m1 = mem_readd(addr); - fpu.p_regs[8].m2 = mem_readd(addr+4); - fpu.p_regs[8].m3 = mem_readw(addr+8); - FPUD_LOAD(fbld,TBYTE,) -} - -static void FPU_FST_F32(PhysPt addr) { - FPUD_STORE(fstp,DWORD,s) - mem_writed(addr,fpu.p_regs[8].m1); -} - -static void FPU_FST_F64(PhysPt addr) { - FPUD_STORE(fstp,QWORD,l) - mem_writed(addr,fpu.p_regs[8].m1); - mem_writed(addr+4,fpu.p_regs[8].m2); -} - -static void FPU_FST_F80(PhysPt addr) { - mem_writed(addr,fpu.p_regs[TOP].m1); - mem_writed(addr+4,fpu.p_regs[TOP].m2); - mem_writew(addr+8,fpu.p_regs[TOP].m3); - FPU_SET_C1(0); -} - -static void FPU_FST_I16(PhysPt addr) { - FPUD_STORE(fistp,WORD,) - mem_writew(addr,(Bit16u)fpu.p_regs[8].m1); -} - -static void FPU_FST_I32(PhysPt addr) { - FPUD_STORE(fistp,DWORD,l) - mem_writed(addr,fpu.p_regs[8].m1); -} - -static void FPU_FST_I64(PhysPt addr) { - FPUD_STORE(fistp,QWORD,q) - mem_writed(addr,fpu.p_regs[8].m1); - mem_writed(addr+4,fpu.p_regs[8].m2); -} - -static void FPU_FBST(PhysPt addr) { - FPUD_STORE(fbstp,TBYTE,) - mem_writed(addr,fpu.p_regs[8].m1); - mem_writed(addr+4,fpu.p_regs[8].m2); - mem_writew(addr+8,fpu.p_regs[8].m3); -} - - -static void FPU_FSIN(void){ - FPUD_TRIG(fsin) -} - -static void FPU_FSINCOS(void){ - FPUD_SINCOS() -} - -static void FPU_FCOS(void){ - FPUD_TRIG(fcos) -} - -static void FPU_FSQRT(void){ - FPUD_ARITH2(fsqrt) -} - -static void FPU_FPATAN(void){ - FPUD_WITH_POP(fpatan) -} - -static void FPU_FPTAN(void){ - FPUD_PTAN() -} - - -static void FPU_FADD(Bitu op1, Bitu op2){ - FPUD_ARITH1(faddp) -} - -static void FPU_FADD_EA(Bitu op1){ - FPUD_ARITH1_EA(faddp) -} - -static void FPU_FDIV(Bitu op1, Bitu op2){ - FPUD_ARITH3(fdivp) -} - -static void FPU_FDIV_EA(Bitu op1){ - FPUD_ARITH3_EA(fdivp) -} - -static void FPU_FDIVR(Bitu op1, Bitu op2){ - FPUD_ARITH3(fdivrp) -} - -static void FPU_FDIVR_EA(Bitu op1){ - FPUD_ARITH3_EA(fdivrp) -} - -static void FPU_FMUL(Bitu op1, Bitu op2){ - FPUD_ARITH1(fmulp) -} - -static void FPU_FMUL_EA(Bitu op1){ - FPUD_ARITH1_EA(fmulp) -} - -static void FPU_FSUB(Bitu op1, Bitu op2){ - FPUD_ARITH1(fsubp) -} - -static void FPU_FSUB_EA(Bitu op1){ - FPUD_ARITH1_EA(fsubp) -} - -static void FPU_FSUBR(Bitu op1, Bitu op2){ - FPUD_ARITH1(fsubrp) -} - -static void FPU_FSUBR_EA(Bitu op1){ - FPUD_ARITH1_EA(fsubrp) -} - -static void FPU_FXCH(Bitu stv, Bitu other){ - FPU_Tag tag = fpu.tags[other]; - fpu.tags[other] = fpu.tags[stv]; - fpu.tags[stv] = tag; - - Bit32u m1s = fpu.p_regs[other].m1; - Bit32u m2s = fpu.p_regs[other].m2; - Bit16u m3s = fpu.p_regs[other].m3; - fpu.p_regs[other].m1 = fpu.p_regs[stv].m1; - fpu.p_regs[other].m2 = fpu.p_regs[stv].m2; - fpu.p_regs[other].m3 = fpu.p_regs[stv].m3; - fpu.p_regs[stv].m1 = m1s; - fpu.p_regs[stv].m2 = m2s; - fpu.p_regs[stv].m3 = m3s; - - FPU_SET_C1(0); -} - -static void FPU_FST(Bitu stv, Bitu other){ - fpu.tags[other] = fpu.tags[stv]; - - fpu.p_regs[other].m1 = fpu.p_regs[stv].m1; - fpu.p_regs[other].m2 = fpu.p_regs[stv].m2; - fpu.p_regs[other].m3 = fpu.p_regs[stv].m3; - - FPU_SET_C1(0); -} - - -static void FPU_FCOM(Bitu op1, Bitu op2){ - FPUD_COMPARE(fcompp) -} - -static void FPU_FCOM_EA(Bitu op1){ - FPUD_COMPARE_EA(fcompp) -} - -static void FPU_FUCOM(Bitu op1, Bitu op2){ - FPUD_COMPARE(fucompp) -} - -static void FPU_FRNDINT(void){ - FPUD_ARITH2(frndint) -} - -static void FPU_FPREM(void){ - FPUD_REMINDER(fprem) -} - -static void FPU_FPREM1(void){ - FPUD_REMINDER(fprem1) -} - -static void FPU_FXAM(void){ - FPUD_EXAMINE(fxam) - // handle empty registers (C1 set to sign in any way!) - if(fpu.tags[TOP] == TAG_Empty) { - FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(1); - return; - } -} - -static void FPU_F2XM1(void){ - FPUD_TRIG(f2xm1) -} - -static void FPU_FYL2X(void){ - FPUD_FYL2X(fyl2x) -} - -static void FPU_FYL2XP1(void){ - FPUD_WITH_POP(fyl2xp1) -} - -static void FPU_FSCALE(void){ - FPUD_REMINDER(fscale) -} - - -static void FPU_FSTENV(PhysPt addr){ - FPU_SET_TOP(TOP); - if(!cpu.code.big) { - mem_writew(addr+0,static_cast(fpu.cw)); - mem_writew(addr+2,static_cast(fpu.sw)); - mem_writew(addr+4,static_cast(FPU_GetTag())); - } else { - mem_writed(addr+0,static_cast(fpu.cw)); - mem_writed(addr+4,static_cast(fpu.sw)); - mem_writed(addr+8,static_cast(FPU_GetTag())); - } -} - -static void FPU_FLDENV(PhysPt addr){ - Bit16u tag; - Bit32u tagbig; - Bitu cw; - if(!cpu.code.big) { - cw = mem_readw(addr+0); - fpu.sw = mem_readw(addr+2); - tag = mem_readw(addr+4); - } else { - cw = mem_readd(addr+0); - fpu.sw = (Bit16u)mem_readd(addr+4); - tagbig = mem_readd(addr+8); - tag = static_cast(tagbig); - } - FPU_SetTag(tag); - FPU_SetCW(cw); - TOP=FPU_GET_TOP(); -} - -static void FPU_FSAVE(PhysPt addr){ - FPU_FSTENV(addr); - Bitu start=(cpu.code.big?28:14); - for(Bitu i=0;i<8;i++){ - mem_writed(addr+start,fpu.p_regs[STV(i)].m1); - mem_writed(addr+start+4,fpu.p_regs[STV(i)].m2); - mem_writew(addr+start+8,fpu.p_regs[STV(i)].m3); - start+=10; - } - FPU_FINIT(); -} - -static void FPU_FRSTOR(PhysPt addr){ - FPU_FLDENV(addr); - Bitu start=(cpu.code.big?28:14); - for(Bitu i=0;i<8;i++){ - fpu.p_regs[STV(i)].m1 = mem_readd(addr+start); - fpu.p_regs[STV(i)].m2 = mem_readd(addr+start+4); - fpu.p_regs[STV(i)].m3 = mem_readw(addr+start+8); - start+=10; - } -} - - -static void FPU_FXTRACT(void) { - FPUD_XTRACT -} - -static void FPU_FCHS(void){ - FPUD_TRIG(fchs) -} - -static void FPU_FABS(void){ - FPUD_TRIG(fabs) -} - -static void FPU_FTST(void){ - FPUD_EXAMINE(ftst) -} - -static void FPU_FLD1(void){ - FPUD_LOAD_CONST(fld1) -} - -static void FPU_FLDL2T(void){ - FPUD_LOAD_CONST(fldl2t) -} - -static void FPU_FLDL2E(void){ - FPUD_LOAD_CONST(fldl2e) -} - -static void FPU_FLDPI(void){ - FPUD_LOAD_CONST(fldpi) -} - -static void FPU_FLDLG2(void){ - FPUD_LOAD_CONST(fldlg2) -} - -static void FPU_FLDLN2(void){ - FPUD_LOAD_CONST(fldln2) -} - -static void FPU_FLDZ(void){ - FPUD_LOAD_CONST(fldz) - fpu.tags[TOP]=TAG_Zero; -} diff --git a/src/fpu/fpu_load.h b/src/fpu/fpu_load.h new file mode 100644 index 0000000..b7f6ee0 --- /dev/null +++ b/src/fpu/fpu_load.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +INLINE FPUREG Load_Short(EAPoint addr) { + return (Bit16s)mem_readw(addr); +} \ No newline at end of file diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 7ee6a55..00fc576 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -1,11 +1,5 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include - -noinst_LIBRARIES = libgui.a -libgui_a_SOURCES = sdlmain.cpp sdl_mapper.cpp dosbox_logo.h \ - render.cpp render_scalers.cpp render_scalers.h \ - render_templates.h render_loops.h render_simple.h \ - render_templates_sai.h render_templates_hq.h \ - render_templates_hq2x.h render_templates_hq3x.h \ - midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h midi_alsa.h \ - midi_coremidi.h sdl_gui.cpp - +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libgui.a +libgui_a_SOURCES = sdlmain.cpp render.cpp + diff --git a/src/gui/Makefile.in b/src/gui/Makefile.in new file mode 100644 index 0000000..edb51fc --- /dev/null +++ b/src/gui/Makefile.in @@ -0,0 +1,303 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libgui.a +libgui_a_SOURCES = sdlmain.cpp render.cpp +subdir = src/gui +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libgui_a_AR = $(AR) cru +libgui_a_LIBADD = +am_libgui_a_OBJECTS = sdlmain.$(OBJEXT) render.$(OBJEXT) +libgui_a_OBJECTS = $(am_libgui_a_OBJECTS) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/render.Po ./$(DEPDIR)/sdlmain.Po +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +CXXFLAGS = @CXXFLAGS@ +DIST_SOURCES = $(libgui_a_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libgui_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/gui/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +AR = ar + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libgui.a: $(libgui_a_OBJECTS) $(libgui_a_DEPENDENCIES) + -rm -f libgui.a + $(libgui_a_AR) libgui.a $(libgui_a_OBJECTS) $(libgui_a_LIBADD) + $(RANLIB) libgui.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/render.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdlmain.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `cygpath -w $<` +CXXDEPMODE = @CXXDEPMODE@ +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic tags uninstall uninstall-am \ + uninstall-info-am + +# 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/gui/dosbox_logo.h b/src/gui/dosbox_logo.h deleted file mode 100644 index 61895b3..0000000 --- a/src/gui/dosbox_logo.h +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dosbox_logo.h,v 1.4 2007/01/08 19:45:39 qbix79 Exp $ */ - -/* DOSBox icon designed by Ido Beeri */ - -/* Select only one logo at the time */ -#define LOGO_1 1 -//#define LOGO_2 1 -#ifdef LOGO_1 - 65, 44, 25,0, 65, 44, 25,0, 93, 58, 30,0, 93, 58, 30,0 -, 92, 57, 30,0, 92, 57, 30,0, 98, 59, 28,0, 98, 59, 28,0 -, 97, 58, 29,0, 97, 58, 29,0, 97, 60, 30,0, 97, 60, 30,0 -, 97, 60, 30,0, 97, 60, 30,0, 96, 59, 29,0, 96, 59, 29,0 -, 91, 55, 26,0, 91, 55, 26,0, 96, 60, 29,0, 96, 60, 29,0 -, 93, 58, 28,0, 93, 58, 28,0, 93, 57, 27,0, 93, 57, 27,0 -, 93, 56, 27,0, 93, 56, 27,0, 85, 52, 25,0, 85, 52, 25,0 -, 89, 53, 24,0, 89, 53, 24,0, 63, 39, 22,0, 63, 39, 22,0 -, 65, 44, 25,0, 65, 44, 25,0, 93, 58, 30,0, 93, 58, 30,0 -, 92, 57, 30,0, 92, 57, 30,0, 98, 59, 28,0, 98, 59, 28,0 -, 97, 58, 29,0, 97, 58, 29,0, 97, 60, 30,0, 97, 60, 30,0 -, 97, 60, 30,0, 97, 60, 30,0, 96, 59, 29,0, 96, 59, 29,0 -, 91, 55, 26,0, 91, 55, 26,0, 96, 60, 29,0, 96, 60, 29,0 -, 93, 58, 28,0, 93, 58, 28,0, 93, 57, 27,0, 93, 57, 27,0 -, 93, 56, 27,0, 93, 56, 27,0, 85, 52, 25,0, 85, 52, 25,0 -, 89, 53, 24,0, 89, 53, 24,0, 63, 39, 22,0, 63, 39, 22,0 -, 81, 50, 26,0, 81, 50, 26,0,145, 89, 46,0,145, 89, 46,0 -,145, 76, 29,0,145, 76, 29,0,134, 72, 26,0,134, 72, 26,0 -,136, 76, 30,0,136, 76, 30,0,148, 85, 36,0,148, 85, 36,0 -,137, 77, 31,0,137, 77, 31,0,134, 72, 27,0,134, 72, 27,0 -,117, 64, 26,0,117, 64, 26,0,141, 80, 32,0,141, 80, 32,0 -,141, 81, 34,0,141, 81, 34,0,123, 70, 27,0,123, 70, 27,0 -,123, 68, 27,0,123, 68, 27,0,130, 72, 27,0,130, 72, 27,0 -,135, 80, 37,0,135, 80, 37,0, 85, 50, 24,0, 85, 50, 24,0 -, 81, 50, 26,0, 81, 50, 26,0,145, 89, 46,0,145, 89, 46,0 -,145, 76, 29,0,145, 76, 29,0,134, 72, 26,0,134, 72, 26,0 -,136, 76, 30,0,136, 76, 30,0,148, 85, 36,0,148, 85, 36,0 -,137, 77, 31,0,137, 77, 31,0,134, 72, 27,0,134, 72, 27,0 -,117, 64, 26,0,117, 64, 26,0,141, 80, 32,0,141, 80, 32,0 -,141, 81, 34,0,141, 81, 34,0,123, 70, 27,0,123, 70, 27,0 -,123, 68, 27,0,123, 68, 27,0,130, 72, 27,0,130, 72, 27,0 -,135, 80, 37,0,135, 80, 37,0, 85, 50, 24,0, 85, 50, 24,0 -, 80, 48, 24,0, 80, 48, 24,0,146, 76, 29,0,146, 76, 29,0 -,255,227, 30,0,255,227, 30,0,255,237, 75,0,255,237, 75,0 -,125, 98, 52,0,125, 98, 52,0,145,120, 69,0,145,120, 69,0 -,133,105, 55,0,133,105, 55,0,255,231, 48,0,255,231, 48,0 -,255,237, 75,0,255,237, 75,0,127,100, 53,0,127,100, 53,0 -,143,117, 67,0,143,117, 67,0,132,105, 55,0,132,105, 55,0 -,255,232, 54,0,255,232, 54,0,255,236, 76,0,255,236, 76,0 -, 85, 44, 15,0, 85, 44, 15,0, 83, 47, 20,0, 83, 47, 20,0 -, 80, 48, 24,0, 80, 48, 24,0,146, 76, 29,0,146, 76, 29,0 -,255,227, 30,0,255,227, 30,0,255,237, 75,0,255,237, 75,0 -,125, 98, 52,0,125, 98, 52,0,145,120, 69,0,145,120, 69,0 -,133,105, 55,0,133,105, 55,0,255,231, 48,0,255,231, 48,0 -,255,237, 75,0,255,237, 75,0,127,100, 53,0,127,100, 53,0 -,143,117, 67,0,143,117, 67,0,132,105, 55,0,132,105, 55,0 -,255,232, 54,0,255,232, 54,0,255,236, 76,0,255,236, 76,0 -, 85, 44, 15,0, 85, 44, 15,0, 83, 47, 20,0, 83, 47, 20,0 -, 79, 48, 23,0, 79, 48, 23,0,149, 72, 24,0,149, 72, 24,0 -,255,227, 31,0,255,227, 31,0, 82, 56, 21,0, 82, 56, 21,0 -,255,236, 76,0,255,236, 76,0, 97, 72, 30,0, 97, 72, 30,0 -,255,231, 48,0,255,231, 48,0, 16, 12, 5,0, 16, 12, 5,0 -,102, 75, 32,0,102, 75, 32,0,255,237, 75,0,255,237, 75,0 -,107, 80, 36,0,107, 80, 36,0,255,221, 2,0,255,221, 2,0 -, 65, 45, 19,0, 65, 45, 19,0, 48, 38, 19,0, 48, 38, 19,0 -, 66, 32, 6,0, 66, 32, 6,0, 80, 43, 14,0, 80, 43, 14,0 -, 79, 48, 23,0, 79, 48, 23,0,149, 72, 24,0,149, 72, 24,0 -,255,227, 31,0,255,227, 31,0, 82, 56, 21,0, 82, 56, 21,0 -,255,236, 76,0,255,236, 76,0, 97, 72, 30,0, 97, 72, 30,0 -,255,231, 48,0,255,231, 48,0, 16, 12, 5,0, 16, 12, 5,0 -,102, 75, 32,0,102, 75, 32,0,255,237, 75,0,255,237, 75,0 -,107, 80, 36,0,107, 80, 36,0,255,221, 2,0,255,221, 2,0 -, 65, 45, 19,0, 65, 45, 19,0, 48, 38, 19,0, 48, 38, 19,0 -, 66, 32, 6,0, 66, 32, 6,0, 80, 43, 14,0, 80, 43, 14,0 -, 85, 52, 25,0, 85, 52, 25,0,149, 70, 21,0,149, 70, 21,0 -,255,229, 37,0,255,229, 37,0, 16, 12, 3,0, 16, 12, 3,0 -,255,236, 76,0,255,236, 76,0, 62, 48, 12,0, 62, 48, 12,0 -,255,236, 76,0,255,236, 76,0, 27, 21, 8,0, 27, 21, 8,0 -,107, 84, 34,0,107, 84, 34,0,255,237, 75,0,255,237, 75,0 -, 11, 8, 3,0, 11, 8, 3,0,106, 84, 35,0,106, 84, 35,0 -,255,237, 74,0,255,237, 74,0, 98, 75, 35,0, 98, 75, 35,0 -,105, 50, 7,0,105, 50, 7,0, 83, 46, 15,0, 83, 46, 15,0 -, 85, 52, 25,0, 85, 52, 25,0,149, 70, 21,0,149, 70, 21,0 -,255,229, 37,0,255,229, 37,0, 16, 12, 3,0, 16, 12, 3,0 -,255,236, 76,0,255,236, 76,0, 62, 48, 12,0, 62, 48, 12,0 -,255,236, 76,0,255,236, 76,0, 27, 21, 8,0, 27, 21, 8,0 -,107, 84, 34,0,107, 84, 34,0,255,237, 75,0,255,237, 75,0 -, 11, 8, 3,0, 11, 8, 3,0,106, 84, 35,0,106, 84, 35,0 -,255,237, 74,0,255,237, 74,0, 98, 75, 35,0, 98, 75, 35,0 -,105, 50, 7,0,105, 50, 7,0, 83, 46, 15,0, 83, 46, 15,0 -, 81, 49, 23,0, 81, 49, 23,0,142, 67, 20,0,142, 67, 20,0 -,255,230, 45,0,255,230, 45,0, 2, 1, 0,0, 2, 1, 0,0 -,255,236, 76,0,255,236, 76,0, 75, 58, 13,0, 75, 58, 13,0 -,255,236, 76,0,255,236, 76,0, 80, 62, 19,0, 80, 62, 19,0 -, 81, 64, 21,0, 81, 64, 21,0,255,236, 76,0,255,236, 76,0 -, 2, 2, 1,0, 2, 2, 1,0,111, 86, 36,0,111, 86, 36,0 -, 88, 63, 23,0, 88, 63, 23,0,255,236, 76,0,255,236, 76,0 -, 66, 31, 4,0, 66, 31, 4,0, 87, 46, 15,0, 87, 46, 15,0 -, 81, 49, 23,0, 81, 49, 23,0,142, 67, 20,0,142, 67, 20,0 -,255,230, 45,0,255,230, 45,0, 2, 1, 0,0, 2, 1, 0,0 -,255,236, 76,0,255,236, 76,0, 75, 58, 13,0, 75, 58, 13,0 -,255,236, 76,0,255,236, 76,0, 80, 62, 19,0, 80, 62, 19,0 -, 81, 64, 21,0, 81, 64, 21,0,255,236, 76,0,255,236, 76,0 -, 2, 2, 1,0, 2, 2, 1,0,111, 86, 36,0,111, 86, 36,0 -, 88, 63, 23,0, 88, 63, 23,0,255,236, 76,0,255,236, 76,0 -, 66, 31, 4,0, 66, 31, 4,0, 87, 46, 15,0, 87, 46, 15,0 -, 78, 46, 21,0, 78, 46, 21,0,150, 76, 25,0,150, 76, 25,0 -,255,237, 75,0,255,237, 75,0,255,236, 76,0,255,236, 76,0 -, 57, 44, 14,0, 57, 44, 14,0,111, 87, 27,0,111, 87, 27,0 -,104, 80, 30,0,104, 80, 30,0,255,236, 76,0,255,236, 76,0 -,255,236, 76,0,255,236, 76,0, 47, 37, 16,0, 47, 37, 16,0 -,116, 91, 38,0,116, 91, 38,0,255,237, 75,0,255,237, 75,0 -,255,236, 76,0,255,236, 76,0, 38, 30, 13,0, 38, 30, 13,0 -, 56, 26, 4,0, 56, 26, 4,0, 82, 43, 14,0, 82, 43, 14,0 -, 78, 46, 21,0, 78, 46, 21,0,150, 76, 25,0,150, 76, 25,0 -,255,237, 75,0,255,237, 75,0,255,236, 76,0,255,236, 76,0 -, 57, 44, 14,0, 57, 44, 14,0,111, 87, 27,0,111, 87, 27,0 -,104, 80, 30,0,104, 80, 30,0,255,236, 76,0,255,236, 76,0 -,255,236, 76,0,255,236, 76,0, 47, 37, 16,0, 47, 37, 16,0 -,116, 91, 38,0,116, 91, 38,0,255,237, 75,0,255,237, 75,0 -,255,236, 76,0,255,236, 76,0, 38, 30, 13,0, 38, 30, 13,0 -, 56, 26, 4,0, 56, 26, 4,0, 82, 43, 14,0, 82, 43, 14,0 -, 82, 50, 25,0, 82, 50, 25,0,159, 84, 31,0,159, 84, 31,0 -,125,101, 52,0,125,101, 52,0, 57, 46, 20,0, 57, 46, 20,0 -, 66, 51, 23,0, 66, 51, 23,0,140,115, 53,0,140,115, 53,0 -,134,109, 51,0,134,109, 51,0,118, 94, 41,0,118, 94, 41,0 -, 47, 38, 16,0, 47, 38, 16,0, 63, 50, 23,0, 63, 50, 23,0 -,129,105, 46,0,129,105, 46,0,114, 92, 41,0,114, 92, 41,0 -, 71, 57, 25,0, 71, 57, 25,0, 68, 52, 26,0, 68, 52, 26,0 -,111, 51, 7,0,111, 51, 7,0, 84, 47, 17,0, 84, 47, 17,0 -, 82, 50, 25,0, 82, 50, 25,0,159, 84, 31,0,159, 84, 31,0 -,125,101, 52,0,125,101, 52,0, 57, 46, 20,0, 57, 46, 20,0 -, 66, 51, 23,0, 66, 51, 23,0,140,115, 53,0,140,115, 53,0 -,134,109, 51,0,134,109, 51,0,118, 94, 41,0,118, 94, 41,0 -, 47, 38, 16,0, 47, 38, 16,0, 63, 50, 23,0, 63, 50, 23,0 -,129,105, 46,0,129,105, 46,0,114, 92, 41,0,114, 92, 41,0 -, 71, 57, 25,0, 71, 57, 25,0, 68, 52, 26,0, 68, 52, 26,0 -,111, 51, 7,0,111, 51, 7,0, 84, 47, 17,0, 84, 47, 17,0 -, 81, 50, 24,0, 81, 50, 24,0,164, 89, 35,0,164, 89, 35,0 -,130,104, 57,0,130,104, 57,0,121, 97, 46,0,121, 97, 46,0 -,131,109, 52,0,131,109, 52,0,139,116, 57,0,139,116, 57,0 -,137,114, 58,0,137,114, 58,0,123, 98, 47,0,123, 98, 47,0 -,125,101, 49,0,125,101, 49,0,139,115, 59,0,139,115, 59,0 -,141,118, 62,0,141,118, 62,0,137,110, 58,0,137,110, 58,0 -,130,106, 52,0,130,106, 52,0,131,108, 55,0,131,108, 55,0 -,113, 54, 9,0,113, 54, 9,0, 85, 48, 18,0, 85, 48, 18,0 -, 81, 50, 24,0, 81, 50, 24,0,164, 89, 35,0,164, 89, 35,0 -,130,104, 57,0,130,104, 57,0,121, 97, 46,0,121, 97, 46,0 -,131,109, 52,0,131,109, 52,0,139,116, 57,0,139,116, 57,0 -,137,114, 58,0,137,114, 58,0,123, 98, 47,0,123, 98, 47,0 -,125,101, 49,0,125,101, 49,0,139,115, 59,0,139,115, 59,0 -,141,118, 62,0,141,118, 62,0,137,110, 58,0,137,110, 58,0 -,130,106, 52,0,130,106, 52,0,131,108, 55,0,131,108, 55,0 -,113, 54, 9,0,113, 54, 9,0, 85, 48, 18,0, 85, 48, 18,0 -, 76, 45, 21,0, 76, 45, 21,0,150, 75, 26,0,150, 75, 26,0 -,255,228, 34,0,255,228, 34,0,255,237, 75,0,255,237, 75,0 -,118, 90, 42,0,118, 90, 42,0,138,111, 58,0,138,111, 58,0 -,120, 93, 46,0,120, 93, 46,0,255,231, 48,0,255,231, 48,0 -,255,237, 75,0,255,237, 75,0,118, 92, 43,0,118, 92, 43,0 -,118, 91, 42,0,118, 91, 42,0,255,233, 60,0,255,233, 60,0 -,100, 73, 31,0,100, 73, 31,0,255,236, 76,0,255,236, 76,0 -,102, 51, 9,0,102, 51, 9,0, 82, 43, 14,0, 82, 43, 14,0 -, 76, 45, 21,0, 76, 45, 21,0,150, 75, 26,0,150, 75, 26,0 -,255,228, 34,0,255,228, 34,0,255,237, 75,0,255,237, 75,0 -,118, 90, 42,0,118, 90, 42,0,138,111, 58,0,138,111, 58,0 -,120, 93, 46,0,120, 93, 46,0,255,231, 48,0,255,231, 48,0 -,255,237, 75,0,255,237, 75,0,118, 92, 43,0,118, 92, 43,0 -,118, 91, 42,0,118, 91, 42,0,255,233, 60,0,255,233, 60,0 -,100, 73, 31,0,100, 73, 31,0,255,236, 76,0,255,236, 76,0 -,102, 51, 9,0,102, 51, 9,0, 82, 43, 14,0, 82, 43, 14,0 -, 78, 47, 22,0, 78, 47, 22,0,142, 67, 20,0,142, 67, 20,0 -,255,226, 24,0,255,226, 24,0, 82, 56, 20,0, 82, 56, 20,0 -,255,236, 76,0,255,236, 76,0,106, 80, 33,0,106, 80, 33,0 -,255,220, 0,0,255,220, 0,0, 15, 11, 4,0, 15, 11, 4,0 -, 99, 72, 30,0, 99, 72, 30,0,255,237, 74,0,255,237, 74,0 -, 93, 70, 27,0, 93, 70, 27,0,247,212, 0,0,247,212, 0,0 -, 66, 50, 15,0, 66, 50, 15,0,255,236, 76,0,255,236, 76,0 -, 66, 30, 1,0, 66, 30, 1,0, 77, 40, 11,0, 77, 40, 11,0 -, 78, 47, 22,0, 78, 47, 22,0,142, 67, 20,0,142, 67, 20,0 -,255,226, 24,0,255,226, 24,0, 82, 56, 20,0, 82, 56, 20,0 -,255,236, 76,0,255,236, 76,0,106, 80, 33,0,106, 80, 33,0 -,255,220, 0,0,255,220, 0,0, 15, 11, 4,0, 15, 11, 4,0 -, 99, 72, 30,0, 99, 72, 30,0,255,237, 74,0,255,237, 74,0 -, 93, 70, 27,0, 93, 70, 27,0,247,212, 0,0,247,212, 0,0 -, 66, 50, 15,0, 66, 50, 15,0,255,236, 76,0,255,236, 76,0 -, 66, 30, 1,0, 66, 30, 1,0, 77, 40, 11,0, 77, 40, 11,0 -, 86, 52, 25,0, 86, 52, 25,0,136, 64, 18,0,136, 64, 18,0 -,255,230, 45,0,255,230, 45,0,255,236, 76,0,255,236, 76,0 -, 42, 33, 8,0, 42, 33, 8,0, 82, 64, 20,0, 82, 64, 20,0 -,255,237, 74,0,255,237, 74,0, 28, 22, 8,0, 28, 22, 8,0 -,109, 84, 35,0,109, 84, 35,0,255,225, 26,0,255,225, 26,0 -, 35, 26, 9,0, 35, 26, 9,0, 82, 64, 22,0, 82, 64, 22,0 -,255,237, 74,0,255,237, 74,0, 49, 39, 13,0, 49, 39, 13,0 -, 67, 30, 0,0, 67, 30, 0,0, 80, 40, 8,0, 80, 40, 8,0 -, 86, 52, 25,0, 86, 52, 25,0,136, 64, 18,0,136, 64, 18,0 -,255,230, 45,0,255,230, 45,0,255,236, 76,0,255,236, 76,0 -, 42, 33, 8,0, 42, 33, 8,0, 82, 64, 20,0, 82, 64, 20,0 -,255,237, 74,0,255,237, 74,0, 28, 22, 8,0, 28, 22, 8,0 -,109, 84, 35,0,109, 84, 35,0,255,225, 26,0,255,225, 26,0 -, 35, 26, 9,0, 35, 26, 9,0, 82, 64, 22,0, 82, 64, 22,0 -,255,237, 74,0,255,237, 74,0, 49, 39, 13,0, 49, 39, 13,0 -, 67, 30, 0,0, 67, 30, 0,0, 80, 40, 8,0, 80, 40, 8,0 -, 74, 43, 19,0, 74, 43, 19,0,140, 63, 17,0,140, 63, 17,0 -,255,237, 74,0,255,237, 74,0, 14, 11, 3,0, 14, 11, 3,0 -,255,236, 76,0,255,236, 76,0, 82, 63, 15,0, 82, 63, 15,0 -,255,237, 75,0,255,237, 75,0, 80, 63, 19,0, 80, 63, 19,0 -, 86, 67, 22,0, 86, 67, 22,0,255,237, 75,0,255,237, 75,0 -, 67, 52, 16,0, 67, 52, 16,0,255,237, 74,0,255,237, 74,0 -, 43, 34, 8,0, 43, 34, 8,0,255,236, 76,0,255,236, 76,0 -, 66, 29, 0,0, 66, 29, 0,0, 71, 34, 4,0, 71, 34, 4,0 -, 74, 43, 19,0, 74, 43, 19,0,140, 63, 17,0,140, 63, 17,0 -,255,237, 74,0,255,237, 74,0, 14, 11, 3,0, 14, 11, 3,0 -,255,236, 76,0,255,236, 76,0, 82, 63, 15,0, 82, 63, 15,0 -,255,237, 75,0,255,237, 75,0, 80, 63, 19,0, 80, 63, 19,0 -, 86, 67, 22,0, 86, 67, 22,0,255,237, 75,0,255,237, 75,0 -, 67, 52, 16,0, 67, 52, 16,0,255,237, 74,0,255,237, 74,0 -, 43, 34, 8,0, 43, 34, 8,0,255,236, 76,0,255,236, 76,0 -, 66, 29, 0,0, 66, 29, 0,0, 71, 34, 4,0, 71, 34, 4,0 -, 77, 45, 20,0, 77, 45, 20,0,145, 71, 22,0,145, 71, 22,0 -,255,237, 75,0,255,237, 75,0,255,236, 76,0,255,236, 76,0 -, 47, 37, 11,0, 47, 37, 11,0,108, 84, 26,0,108, 84, 26,0 -, 95, 76, 27,0, 95, 76, 27,0,255,236, 76,0,255,236, 76,0 -,255,236, 76,0,255,236, 76,0, 71, 55, 20,0, 71, 55, 20,0 -, 98, 77, 26,0, 98, 77, 26,0,255,236, 76,0,255,236, 76,0 -, 78, 62, 19,0, 78, 62, 19,0,255,236, 76,0,255,236, 76,0 -, 32, 14, 0,0, 32, 14, 0,0, 75, 37, 5,0, 75, 37, 5,0 -, 77, 45, 20,0, 77, 45, 20,0,145, 71, 22,0,145, 71, 22,0 -,255,237, 75,0,255,237, 75,0,255,236, 76,0,255,236, 76,0 -, 47, 37, 11,0, 47, 37, 11,0,108, 84, 26,0,108, 84, 26,0 -, 95, 76, 27,0, 95, 76, 27,0,255,236, 76,0,255,236, 76,0 -,255,236, 76,0,255,236, 76,0, 71, 55, 20,0, 71, 55, 20,0 -, 98, 77, 26,0, 98, 77, 26,0,255,236, 76,0,255,236, 76,0 -, 78, 62, 19,0, 78, 62, 19,0,255,236, 76,0,255,236, 76,0 -, 32, 14, 0,0, 32, 14, 0,0, 75, 37, 5,0, 75, 37, 5,0 -, 79, 46, 24,0, 79, 46, 24,0,132, 76, 31,0,132, 76, 31,0 -,124, 59, 13,0,124, 59, 13,0, 96, 43, 0,0, 96, 43, 0,0 -, 52, 23, 0,0, 52, 23, 0,0,123, 55, 0,0,123, 55, 0,0 -,136, 59, 1,0,136, 59, 1,0,124, 54, 2,0,124, 54, 2,0 -, 96, 43, 0,0, 96, 43, 0,0, 95, 42, 0,0, 95, 42, 0,0 -,124, 57, 0,0,124, 57, 0,0,121, 55, 0,0,121, 55, 0,0 -, 93, 41, 0,0, 93, 41, 0,0, 98, 43, 0,0, 98, 43, 0,0 -, 57, 28, 5,0, 57, 28, 5,0, 79, 43, 12,0, 79, 43, 12,0 -, 79, 46, 24,0, 79, 46, 24,0,132, 76, 31,0,132, 76, 31,0 -,124, 59, 13,0,124, 59, 13,0, 96, 43, 0,0, 96, 43, 0,0 -, 52, 23, 0,0, 52, 23, 0,0,123, 55, 0,0,123, 55, 0,0 -,136, 59, 1,0,136, 59, 1,0,124, 54, 2,0,124, 54, 2,0 -, 96, 43, 0,0, 96, 43, 0,0, 95, 42, 0,0, 95, 42, 0,0 -,124, 57, 0,0,124, 57, 0,0,121, 55, 0,0,121, 55, 0,0 -, 93, 41, 0,0, 93, 41, 0,0, 98, 43, 0,0, 98, 43, 0,0 -, 57, 28, 5,0, 57, 28, 5,0, 79, 43, 12,0, 79, 43, 12,0 -, 66, 43, 24,0, 66, 43, 24,0, 78, 46, 20,0, 78, 46, 20,0 -, 69, 38, 13,0, 69, 38, 13,0, 70, 36, 8,0, 70, 36, 8,0 -, 70, 35, 7,0, 70, 35, 7,0, 69, 35, 7,0, 69, 35, 7,0 -, 71, 39, 10,0, 71, 39, 10,0, 71, 36, 9,0, 71, 36, 9,0 -, 71, 36, 9,0, 71, 36, 9,0, 72, 36, 9,0, 72, 36, 9,0 -, 68, 36, 7,0, 68, 36, 7,0, 67, 33, 7,0, 67, 33, 7,0 -, 67, 33, 6,0, 67, 33, 6,0, 64, 33, 7,0, 64, 33, 7,0 -, 74, 38, 12,0, 74, 38, 12,0, 61, 35, 14,0, 61, 35, 14,0 -, 66, 43, 24,0, 66, 43, 24,0, 78, 46, 20,0, 78, 46, 20,0 -, 69, 38, 13,0, 69, 38, 13,0, 70, 36, 8,0, 70, 36, 8,0 -, 70, 35, 7,0, 70, 35, 7,0, 69, 35, 7,0, 69, 35, 7,0 -, 71, 39, 10,0, 71, 39, 10,0, 71, 36, 9,0, 71, 36, 9,0 -, 71, 36, 9,0, 71, 36, 9,0, 72, 36, 9,0, 72, 36, 9,0 -, 68, 36, 7,0, 68, 36, 7,0, 67, 33, 7,0, 67, 33, 7,0 -, 67, 33, 6,0, 67, 33, 6,0, 64, 33, 7,0, 64, 33, 7,0 -, 74, 38, 12,0, 74, 38, 12,0, 61, 35, 14,0, 61, 35, 14,0 -#endif -#ifdef LOGO_2 - 61, 39, 23,0, 91, 57, 30,0, 85, 53, 28,0, 82, 51, 26,0 -, 83, 52, 28,0, 91, 57, 30,0, 91, 57, 30,0, 91, 57, 30,0 -, 88, 55, 29,0, 91, 57, 30,0, 91, 57, 30,0, 91, 57, 30,0 -, 91, 57, 30,0, 91, 57, 30,0, 91, 57, 30,0, 88, 55, 29,0 -, 80, 50, 25,0, 85, 53, 28,0, 91, 57, 30,0, 91, 57, 30,0 -, 85, 53, 28,0, 88, 55, 29,0, 88, 55, 29,0, 85, 53, 28,0 -, 85, 53, 28,0, 85, 53, 28,0, 82, 51, 26,0, 78, 48, 25,0 -, 78, 48, 25,0, 82, 51, 26,0, 88, 55, 29,0, 61, 39, 23,0 -, 91, 57, 30,0,140, 89, 49,0,166,101, 49,0,161, 97, 49,0 -,157, 96, 49,0,165, 99, 50,0,165, 99, 50,0,161, 99, 50,0 -,170,104, 52,0,170,104, 52,0,170,104, 52,0,157, 96, 49,0 -,161, 97, 49,0,162, 99, 50,0,161, 97, 49,0,148, 89, 46,0 -,156, 95, 48,0,153, 93, 47,0,156, 95, 48,0,156, 95, 47,0 -,166,101, 49,0,166,101, 49,0,159, 98, 50,0,157, 96, 49,0 -,160, 96, 49,0,166,101, 49,0,150, 92, 47,0,148, 89, 46,0 -,148, 89, 46,0,160, 96, 49,0,156, 99, 53,0, 91, 57, 30,0 -, 75, 46, 24,0,150, 92, 47,0,151, 99, 53,0,172,106, 53,0 -,162, 99, 50,0,162, 99, 50,0,159, 98, 50,0,147, 91, 46,0 -,148, 89, 46,0,146, 89, 47,0,150, 92, 47,0,147, 91, 46,0 -,140, 84, 42,0,153, 91, 44,0,153, 91, 44,0,145, 86, 41,0 -,145, 86, 41,0,145, 86, 41,0,150, 92, 47,0,157, 96, 49,0 -,150, 92, 47,0,143, 87, 44,0,144, 89, 45,0,136, 84, 42,0 -,148, 89, 46,0,148, 89, 46,0,156, 95, 48,0,150, 92, 47,0 -,159, 98, 50,0,145, 93, 52,0,170,104, 52,0, 80, 50, 25,0 -, 71, 45, 23,0,140, 84, 42,0,172,106, 53,0,137, 87, 53,0 -,132, 92, 57,0,132, 92, 57,0,140, 97, 61,0,141,101, 64,0 -,141,101, 64,0,141,101, 64,0,140, 97, 61,0,141,101, 64,0 -,132, 88, 51,0,231,192, 61,0,245,209, 66,0,245,209, 66,0 -,245,209, 66,0,246,210, 68,0,243,209, 68,0,136, 97, 62,0 -,141,101, 64,0,136, 97, 62,0,136, 97, 62,0,136, 97, 62,0 -,136, 97, 62,0,132, 92, 57,0,122, 85, 52,0,125, 88, 54,0 -,122, 85, 52,0,168,102, 50,0,161, 97, 49,0, 78, 48, 25,0 -, 75, 46, 24,0,150, 92, 47,0,165, 99, 50,0,122, 85, 52,0 -,132,112, 74,0,130,111, 74,0,130,111, 74,0,154,135, 91,0 -,167,148,101,0,167,148,101,0,168,149,102,0,166,147, 99,0 -,147,124, 78,0,132,107, 61,0,224,185, 54,0,242,206, 67,0 -,156,136, 86,0,151,129, 80,0,242,208, 64,0,244,207, 66,0 -,164,145, 99,0,165,146, 99,0,165,146, 99,0,167,148,101,0 -,154,135, 91,0,132,112, 74,0,131,113, 76,0,134,115, 78,0 -,113, 84, 53,0,156, 95, 48,0,171,103, 50,0, 80, 50, 25,0 -, 72, 44, 22,0,163,102, 51,0,168,102, 50,0,125, 88, 54,0 -,128,110, 73,0,131,113, 76,0,131,113, 76,0,128,110, 73,0 -,148,130, 87,0,164,145, 99,0,167,148,101,0,166,147, 98,0 -,162,143, 92,0,132,107, 61,0,220,180, 55,0,247,212, 70,0 -,155,135, 82,0,152,130, 81,0,243,209, 65,0,246,212, 67,0 -,163,144, 96,0,168,149,102,0,168,149,102,0,150,132, 89,0 -,127,109, 71,0,130,111, 74,0,132,112, 74,0,129,112, 75,0 -,113, 84, 53,0,156, 95, 48,0,178,109, 54,0, 75, 46, 24,0 -, 75, 46, 24,0,150, 92, 47,0,172,106, 53,0,140, 97, 61,0 -,128,111, 74,0,129,112, 75,0,133,113, 75,0,133,113, 75,0 -,132,112, 74,0,150,132, 89,0,166,147, 98,0,163,144, 96,0 -,158,138, 88,0,132,107, 61,0,217,177, 51,0,243,207, 69,0 -,243,207, 69,0,231,192, 61,0,240,205, 65,0,159,140, 90,0 -,163,144, 96,0,167,148,101,0,150,132, 89,0,130,111, 74,0 -,133,114, 76,0,133,113, 75,0,130,111, 74,0,129,112, 75,0 -,123, 93, 58,0,154, 94, 48,0,165, 99, 50,0, 78, 48, 25,0 -, 78, 48, 25,0,144, 88, 45,0,174,108, 52,0,142,101, 62,0 -,161,141, 95,0,128,111, 74,0,130,111, 74,0,133,113, 75,0 -,133,113, 75,0,128,110, 73,0,150,132, 89,0,165,146, 98,0 -,161,142, 93,0,135,112, 64,0,223,183, 55,0,247,212, 70,0 -,155,135, 82,0,144,122, 72,0,240,205, 65,0,245,209, 66,0 -,163,143, 95,0,148,130, 87,0,127,109, 71,0,133,113, 75,0 -,133,113, 75,0,130,111, 74,0,129,112, 75,0,164,145, 99,0 -,126, 96, 62,0,154, 94, 48,0,161, 97, 49,0, 83, 52, 28,0 -, 80, 50, 25,0,147, 91, 46,0,178,109, 54,0,148,103, 65,0 -,166,147,100,0,161,142, 95,0,128,111, 74,0,128,109, 72,0 -,132,112, 74,0,132,112, 74,0,130,110, 73,0,147,128, 85,0 -,153,132, 84,0,137,114, 66,0,224,185, 54,0,245,209, 66,0 -,155,135, 82,0,149,129, 75,0,235,199, 63,0,245,209, 66,0 -,148,130, 87,0,130,111, 74,0,132,112, 74,0,130,111, 74,0 -,128,110, 73,0,128,111, 74,0,161,142, 95,0,168,149,102,0 -,127, 97, 63,0,153, 93, 47,0,162, 99, 50,0, 83, 52, 28,0 -, 82, 51, 26,0,148, 89, 46,0,178,109, 54,0,151,106, 65,0 -,166,147,100,0,167,148,101,0,160,143, 95,0,129,112, 75,0 -,129,112, 75,0,135,115, 77,0,135,115, 77,0,130,109, 69,0 -,129,106, 61,0,210,166, 47,0,210,169, 51,0,231,192, 61,0 -,234,197, 61,0,224,185, 56,0,225,189, 55,0,141,120, 75,0 -,130,111, 74,0,134,116, 78,0,133,114, 76,0,128,110, 73,0 -,132,114, 76,0,163,144, 98,0,168,149,102,0,167,148,101,0 -,127, 97, 63,0,153, 93, 47,0,163,102, 51,0, 84, 52, 27,0 -, 75, 46, 24,0,150, 92, 47,0,170,104, 52,0,147,105, 69,0 -,170,151,105,0,170,151,105,0,166,147,100,0,164,145, 99,0 -,134,116, 78,0,133,114, 76,0,133,114, 76,0,131,110, 71,0 -,116, 94, 54,0,116, 94, 54,0,137,114, 66,0,144,122, 72,0 -,146,125, 75,0,148,127, 78,0,137,117, 73,0,130,110, 73,0 -,134,116, 78,0,134,116, 78,0,133,113, 75,0,134,116, 78,0 -,164,145, 99,0,168,149,102,0,170,151,105,0,167,148,101,0 -,126, 96, 62,0,150, 92, 47,0,172,106, 53,0, 85, 53, 28,0 -, 75, 46, 24,0,147, 91, 46,0,166,101, 49,0,151,106, 65,0 -,165,146, 98,0,165,146, 98,0,165,146, 99,0,165,146, 99,0 -,160,143, 95,0,134,116, 78,0,130,110, 73,0,132,112, 74,0 -,130,109, 69,0,117, 98, 59,0,137,117, 73,0,158,138, 88,0 -,156,136, 86,0,137,117, 73,0,125,105, 65,0,133,114, 76,0 -,135,115, 77,0,130,111, 74,0,134,116, 78,0,164,145, 99,0 -,166,147, 99,0,167,148,101,0,166,147,100,0,166,147,100,0 -,134, 97, 62,0,150, 92, 47,0,162, 99, 50,0, 84, 52, 27,0 -, 75, 46, 24,0,146, 89, 43,0,162, 95, 42,0,234,197, 61,0 -,248,214, 73,0,248,214, 73,0,248,211, 69,0,246,210, 68,0 -,159,140, 93,0,163,144, 96,0,131,113, 76,0,126,107, 69,0 -,125,105, 65,0,125,105, 65,0,247,212, 70,0,248,211, 69,0 -,246,210, 68,0,248,211, 69,0,245,211, 67,0,132,112, 74,0 -,132,112, 74,0,134,116, 78,0,161,141, 95,0,162,142, 94,0 -,247,212, 70,0,247,212, 70,0,248,211, 69,0,247,212, 70,0 -,123, 93, 58,0,148, 89, 46,0,157, 96, 49,0, 84, 52, 27,0 -, 72, 44, 22,0,145, 86, 41,0,158, 87, 33,0,110, 68, 32,0 -,224,185, 56,0,243,209, 68,0,158,138, 88,0,240,205, 65,0 -,244,208, 66,0,167,148,101,0,165,146, 99,0,134,116, 76,0 -,114, 93, 56,0,231,192, 61,0,244,208, 66,0,122,100, 60,0 -,112, 90, 51,0,109, 87, 49,0,241,207, 67,0,244,208, 66,0 -,134,116, 78,0,162,142, 94,0,148,127, 78,0,225,187, 56,0 -,243,209, 65,0,152,130, 81,0,156,136, 86,0,240,205, 65,0 -,245,209, 66,0,153, 93, 47,0,159, 98, 50,0, 80, 50, 25,0 -, 75, 46, 24,0,142, 84, 38,0,157, 88, 35,0,117, 67, 29,0 -,214,174, 48,0,241,206, 62,0,153,133, 80,0,141,118, 71,0 -,239,202, 64,0,243,208, 67,0,166,147, 99,0,163,143, 95,0 -,109, 87, 49,0,221,179, 53,0,241,206, 62,0,124,103, 62,0 -,121, 99, 57,0, 97, 75, 39,0,223,183, 53,0,241,206, 62,0 -,159,140, 93,0,157,139, 89,0,135,112, 64,0,202,161, 42,0 -,232,194, 57,0,241,206, 62,0,153,133, 80,0,159,139, 90,0 -,123, 93, 58,0,127, 79, 39,0,172,106, 53,0, 80, 50, 25,0 -, 78, 48, 25,0,142, 84, 38,0,166, 93, 38,0,117, 67, 29,0 -,221,183, 53,0,245,209, 66,0,149,129, 75,0,140,117, 70,0 -,231,192, 61,0,246,212, 67,0,164,145, 96,0,161,141, 92,0 -,129,106, 61,0,222,184, 56,0,247,212, 70,0,125,105, 65,0 -,124,103, 62,0,100, 77, 41,0,221,183, 53,0,245,211, 67,0 -,161,141, 92,0,155,136, 86,0,134,109, 62,0,123, 98, 52,0 -,217,177, 51,0,240,205, 65,0,245,209, 66,0,157,139, 89,0 -,123, 93, 58,0,137, 83, 40,0,157, 96, 49,0, 84, 52, 27,0 -, 78, 48, 25,0,132, 79, 38,0,166, 93, 38,0,117, 67, 29,0 -,224,185, 54,0,241,206, 62,0,149,129, 75,0,144,122, 72,0 -,232,194, 57,0,241,206, 62,0,155,136, 86,0,156,136, 86,0 -,104, 82, 43,0,214,174, 48,0,241,206, 65,0,130,109, 69,0 -,125,105, 65,0,104, 82, 43,0,224,185, 54,0,241,206, 65,0 -,163,144, 96,0,164,145, 96,0,152,130, 81,0,144,121, 71,0 -,144,121, 71,0,141,121, 70,0,238,201, 61,0,241,206, 62,0 -,241,206, 62,0,137, 83, 40,0,157, 96, 49,0, 85, 53, 28,0 -, 75, 46, 24,0,132, 79, 38,0,160, 87, 33,0,117, 67, 29,0 -,228,191, 59,0,246,209, 65,0,153,133, 80,0,246,210, 68,0 -,244,208, 66,0,157,139, 89,0,158,138, 88,0,125,107, 68,0 -, 97, 75, 39,0,210,166, 47,0,246,209, 65,0,122,100, 60,0 -,122,100, 60,0,112, 90, 51,0,235,199, 63,0,247,212, 70,0 -,134,116, 76,0,164,145, 96,0,152,130, 81,0,231,192, 61,0 -,248,211, 69,0,149,129, 75,0,144,121, 71,0,243,205, 64,0 -,246,210, 68,0,140, 84, 42,0,165, 99, 50,0, 84, 52, 27,0 -, 69, 43, 22,0,145, 86, 41,0,150, 82, 30,0,210,169, 51,0 -,212,172, 53,0,226,190, 63,0,229,191, 61,0,227,189, 57,0 -,155,136, 86,0,161,141, 92,0,131,113, 76,0,125,105, 65,0 -,109, 87, 49,0,100, 77, 41,0,220,180, 55,0,238,201, 61,0 -,239,202, 64,0,225,187, 56,0,227,189, 57,0,125,105, 65,0 -,127,109, 71,0,131,114, 73,0,147,124, 78,0,137,114, 66,0 -,223,183, 55,0,228,191, 59,0,223,183, 55,0,225,187, 56,0 -,113, 84, 53,0,161, 97, 49,0,154, 94, 48,0, 80, 50, 25,0 -, 72, 44, 22,0,145, 86, 41,0,150, 82, 30,0,120, 73, 33,0 -,134,109, 62,0,137,114, 66,0,141,118, 71,0,152,130, 81,0 -,159,139, 90,0,134,116, 78,0,132,112, 76,0,132,112, 74,0 -,125,105, 65,0,107, 86, 49,0,122,100, 60,0,144,122, 72,0 -,141,120, 75,0,123,102, 59,0,117, 98, 59,0,131,110, 71,0 -,132,112, 74,0,126,107, 69,0,125,105, 65,0,134,113, 66,0 -,134,113, 66,0,137,114, 66,0,141,118, 71,0,151,129, 80,0 -,122, 85, 52,0,143, 87, 44,0,162, 99, 50,0, 80, 50, 25,0 -, 71, 45, 23,0,140, 84, 42,0,162, 95, 42,0,144, 98, 56,0 -,161,141, 92,0,163,143, 95,0,164,145, 96,0,163,144, 96,0 -,134,115, 78,0,132,112, 74,0,133,113, 75,0,133,113, 75,0 -,126,107, 69,0,141,120, 75,0,159,139, 90,0,158,138, 88,0 -,161,141, 92,0,156,136, 88,0,143,124, 80,0,131,110, 71,0 -,133,114, 76,0,132,112, 74,0,127,109, 71,0,125,107, 68,0 -,152,133, 84,0,155,136, 86,0,159,139, 90,0,159,140, 93,0 -,134, 97, 62,0,148, 89, 46,0,162, 99, 50,0, 78, 48, 25,0 -, 75, 46, 24,0,134, 83, 41,0,171,103, 50,0,142,101, 62,0 -,164,145, 96,0,167,148,101,0,163,144, 98,0,132,114, 76,0 -,130,111, 74,0,135,115, 77,0,137,116, 77,0,132,112, 74,0 -,137,116, 77,0,243,208, 67,0,243,209, 65,0,162,142, 94,0 -,162,143, 92,0,155,136, 86,0,244,208, 66,0,245,209, 66,0 -,129,112, 75,0,133,114, 76,0,133,113, 75,0,125,107, 68,0 -,127,109, 71,0,157,137, 89,0,161,141, 92,0,167,148,101,0 -,128, 97, 65,0,148, 89, 46,0,159, 98, 50,0, 80, 50, 25,0 -, 81, 51, 29,0,136, 84, 42,0,157, 96, 49,0,148,103, 65,0 -,167,148,101,0,164,145, 99,0,131,113, 76,0,132,112, 74,0 -,132,112, 74,0,133,113, 75,0,128,110, 73,0,145,125, 81,0 -,139,116, 69,0,221,179, 53,0,248,214, 73,0,164,145, 96,0 -,163,143, 95,0,157,137, 89,0,247,212, 70,0,247,212, 70,0 -,147,128, 85,0,130,111, 74,0,133,113, 75,0,132,112, 74,0 -,130,111, 74,0,128,111, 74,0,159,140, 93,0,163,144, 96,0 -,126, 96, 62,0,136, 84, 42,0,161, 97, 49,0, 80, 50, 25,0 -, 80, 50, 25,0,144, 88, 45,0,168,102, 50,0,151,106, 65,0 -,163,144, 98,0,128,111, 74,0,128,110, 73,0,130,111, 74,0 -,130,110, 73,0,127,109, 71,0,148,130, 87,0,163,144, 96,0 -,140,117, 70,0,129,106, 61,0,224,185, 54,0,245,209, 66,0 -,156,136, 86,0,242,208, 64,0,244,208, 66,0,163,143, 95,0 -,165,146, 99,0,150,132, 89,0,128,109, 72,0,132,112, 74,0 -,130,111, 74,0,130,111, 74,0,128,110, 73,0,159,140, 93,0 -,123, 93, 58,0,150, 92, 47,0,156, 95, 48,0, 82, 51, 26,0 -, 75, 46, 24,0,140, 84, 42,0,171,103, 50,0,142,101, 62,0 -,129,112, 75,0,130,111, 74,0,130,111, 74,0,130,111, 74,0 -,128,109, 72,0,147,128, 85,0,161,142, 95,0,159,139, 90,0 -,155,136, 86,0,135,112, 64,0,134,109, 62,0,233,196, 58,0 -,244,208, 66,0,244,208, 66,0,160,139, 90,0,164,145, 96,0 -,166,147,100,0,167,148,101,0,150,132, 89,0,131,113, 76,0 -,134,115, 78,0,134,115, 78,0,132,112, 76,0,131,113, 76,0 -,123, 93, 58,0,146, 89, 47,0,153, 93, 47,0, 80, 50, 25,0 -, 71, 45, 23,0,138, 85, 44,0,168,102, 50,0,122, 85, 52,0 -,128,110, 73,0,130,111, 74,0,128,110, 73,0,128,110, 73,0 -,150,132, 89,0,164,146, 97,0,164,146, 97,0,161,142, 93,0 -,157,139, 89,0,146,125, 75,0,137,114, 66,0,227,189, 57,0 -,235,199, 63,0,245,211, 67,0,160,140, 90,0,165,146, 99,0 -,168,149,102,0,167,148,101,0,165,146, 99,0,150,132, 89,0 -,128,110, 73,0,130,111, 74,0,130,111, 74,0,128,110, 73,0 -,103, 81, 51,0,147, 91, 46,0,156, 95, 48,0, 75, 46, 24,0 -, 69, 43, 22,0,150, 92, 47,0,166,101, 49,0,125, 88, 54,0 -,131,113, 76,0,130,111, 74,0,128,109, 72,0,148,130, 87,0 -,163,144, 96,0,166,147,100,0,166,147, 98,0,161,141, 92,0 -,153,132, 84,0,146,125, 75,0,238,201, 61,0,233,196, 58,0 -,134,109, 62,0,225,187, 56,0,241,206, 62,0,163,143, 95,0 -,163,143, 95,0,165,146, 99,0,166,147,100,0,166,147,100,0 -,154,137, 93,0,130,111, 74,0,130,111, 74,0,130,111, 74,0 -,113, 84, 53,0,153, 93, 47,0,172,106, 53,0, 72, 44, 22,0 -, 71, 45, 23,0,143, 87, 44,0,168,102, 50,0,122, 85, 52,0 -,129,112, 75,0,130,111, 74,0,150,132, 89,0,163,144, 96,0 -,163,144, 96,0,161,142, 95,0,159,140, 93,0,157,137, 89,0 -,141,121, 70,0,225,189, 55,0,246,209, 65,0,149,129, 75,0 -,135,112, 64,0,129,104, 58,0,238,201, 61,0,248,211, 69,0 -,163,144, 96,0,166,147,100,0,168,149,102,0,170,151,105,0 -,167,148,101,0,150,132, 89,0,128,111, 74,0,132,112, 74,0 -,113, 84, 53,0,156, 95, 48,0,168,102, 50,0, 78, 48, 25,0 -, 71, 45, 23,0,138, 85, 44,0,168,102, 50,0,134, 86, 50,0 -,132, 92, 57,0,151,106, 65,0,156,110, 68,0,156,110, 68,0 -,149,107, 67,0,151,106, 65,0,150,104, 59,0,150,104, 59,0 -,127, 79, 39,0,209,167, 48,0,234,197, 61,0,150,104, 59,0 -,151, 99, 53,0,120, 73, 33,0,212,170, 48,0,241,206, 65,0 -,149,107, 67,0,151,106, 65,0,149,107, 67,0,149,107, 67,0 -,156,110, 68,0,151,106, 65,0,147,105, 64,0,132, 92, 57,0 -,122, 85, 52,0,170,104, 52,0,162, 99, 50,0, 78, 48, 25,0 -, 75, 46, 24,0,144, 89, 45,0,145, 93, 52,0,159, 98, 50,0 -,154, 94, 48,0,162, 99, 50,0,153, 93, 47,0,144, 88, 45,0 -,144, 89, 45,0,144, 88, 45,0,148, 89, 46,0,152, 89, 41,0 -,131, 71, 25,0,131, 71, 25,0,146, 83, 34,0,152, 89, 41,0 -,134, 76, 33,0,131, 71, 25,0,131, 71, 25,0,134, 76, 33,0 -,156, 95, 48,0,150, 92, 47,0,156, 95, 48,0,156, 95, 48,0 -,144, 88, 45,0,143, 87, 44,0,150, 92, 47,0,147, 91, 46,0 -,155, 96, 51,0,146, 91, 48,0,170,104, 52,0, 82, 51, 26,0 -, 91, 57, 30,0,117, 75, 42,0,138, 85, 44,0,132, 79, 38,0 -,122, 76, 39,0,124, 77, 40,0,120, 74, 37,0,117, 73, 38,0 -,127, 79, 39,0,124, 77, 40,0,132, 79, 38,0,141, 83, 40,0 -,125, 74, 34,0,119, 70, 32,0,120, 73, 33,0,120, 74, 37,0 -,118, 71, 34,0,119, 70, 32,0,119, 70, 32,0,120, 73, 33,0 -,127, 79, 39,0,127, 79, 39,0,124, 77, 40,0,127, 79, 39,0 -,122, 76, 39,0,122, 76, 39,0,117, 73, 38,0,117, 73, 38,0 -,124, 77, 40,0,138, 85, 44,0,140, 89, 49,0, 91, 57, 30,0 -, 61, 39, 23,0, 88, 55, 29,0, 75, 46, 24,0, 69, 43, 22,0 -, 69, 43, 22,0, 72, 44, 22,0, 71, 45, 23,0, 71, 45, 23,0 -, 71, 45, 23,0, 71, 45, 23,0, 75, 46, 24,0, 72, 44, 22,0 -, 72, 44, 22,0, 75, 46, 24,0, 72, 44, 22,0, 69, 43, 22,0 -, 69, 43, 22,0, 72, 44, 22,0, 75, 46, 24,0, 72, 44, 22,0 -, 69, 43, 22,0, 75, 46, 24,0, 69, 43, 22,0, 69, 43, 22,0 -, 71, 45, 23,0, 69, 43, 22,0, 69, 43, 22,0, 69, 43, 22,0 -, 69, 43, 22,0, 75, 46, 24,0, 88, 55, 29,0, 61, 39, 23,0 -#endif diff --git a/src/gui/midi.cpp b/src/gui/midi.cpp deleted file mode 100644 index d6f30f3..0000000 --- a/src/gui/midi.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include - -#include "dosbox.h" -#include "cross.h" -#include "support.h" -#include "setup.h" -#include "mapper.h" -#include "pic.h" -#include "hardware.h" - -#define SYSEX_SIZE 1024 -#define RAWBUF 1024 - -Bit8u MIDI_evt_len[256] = { - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x00 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x10 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x20 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x30 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x40 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x50 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x60 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x70 - - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0x80 - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0x90 - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xa0 - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xb0 - - 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, // 0xc0 - 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, // 0xd0 - - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xe0 - - 0,2,3,2, 0,0,1,0, 1,0,1,1, 1,0,1,0 // 0xf0 -}; - -class MidiHandler; - -MidiHandler * handler_list=0; - -class MidiHandler { -public: - MidiHandler() { - next=handler_list; - handler_list=this; - }; - virtual bool Open(const char * /*conf*/) { return true; }; - virtual void Close(void) {}; - virtual void PlayMsg(Bit8u * /*msg*/) {}; - virtual void PlaySysex(Bit8u * /*sysex*/,Bitu /*len*/) {}; - virtual const char * GetName(void) { return "none"; }; - virtual ~MidiHandler() { }; - MidiHandler * next; -}; - -MidiHandler Midi_none; - -/* Include different midi drivers, lowest ones get checked first for default */ - -#if defined(MACOSX) - -#include "midi_coremidi.h" -#include "midi_coreaudio.h" - -#elif defined (WIN32) - -#include "midi_win32.h" - -#else - -#include "midi_oss.h" - -#endif - -#if defined (HAVE_ALSA) - -#include "midi_alsa.h" - -#endif - -static struct { - Bitu status; - Bitu cmd_len; - Bitu cmd_pos; - Bit8u cmd_buf[8]; - Bit8u rt_buf[8]; - struct { - Bit8u buf[SYSEX_SIZE]; - Bitu used; - } sysex; - bool available; - MidiHandler * handler; -} midi; - -void MIDI_RawOutByte(Bit8u data) { - /* Test for a realtime MIDI message */ - if (data>=0xf8) { - midi.rt_buf[0]=data; - midi.handler->PlayMsg(midi.rt_buf); - return; - } - /* Test for a active sysex tranfer */ - if (midi.status==0xf0) { - if (!(data&0x80)) { - if (midi.sysex.used<(SYSEX_SIZE-1)) midi.sysex.buf[midi.sysex.used++]=data; - return; - } else { - midi.sysex.buf[midi.sysex.used++]=0xf7; - midi.handler->PlaySysex(midi.sysex.buf,midi.sysex.used); - LOG(LOG_ALL,LOG_NORMAL)("Sysex message size %d",midi.sysex.used); - if (CaptureState & CAPTURE_MIDI) { - CAPTURE_AddMidi( true, midi.sysex.used-1, &midi.sysex.buf[1]); - } - } - } - if (data&0x80) { - midi.status=data; - midi.cmd_pos=0; - midi.cmd_len=MIDI_evt_len[data]; - if (midi.status==0xf0) { - midi.sysex.buf[0]=0xf0; - midi.sysex.used=1; - } - } - if (midi.cmd_len) { - midi.cmd_buf[midi.cmd_pos++]=data; - if (midi.cmd_pos >= midi.cmd_len) { - if (CaptureState & CAPTURE_MIDI) { - CAPTURE_AddMidi(false, midi.cmd_len, midi.cmd_buf); - } - midi.handler->PlayMsg(midi.cmd_buf); - midi.cmd_pos=1; //Use Running status - } - } -} - -bool MIDI_Available(void) { - return midi.available; -} - -class MIDI:public Module_base{ -public: - MIDI(Section* configuration):Module_base(configuration){ - Section_prop * section=static_cast(configuration); - const char * dev=section->Get_string("mididevice"); - const char * conf=section->Get_string("midiconfig"); - /* If device = "default" go for first handler that works */ - MidiHandler * handler; -// MAPPER_AddHandler(MIDI_SaveRawEvent,MK_f8,MMOD1|MMOD2,"caprawmidi","Cap MIDI"); - midi.status=0x00; - midi.cmd_pos=0; - midi.cmd_len=0; - if (!strcasecmp(dev,"default")) goto getdefault; - handler=handler_list; - while (handler) { - if (!strcasecmp(dev,handler->GetName())) { - if (!handler->Open(conf)) { - LOG_MSG("MIDI:Can't open device:%s with config:%s.",dev,conf); - goto getdefault; - } - midi.handler=handler; - midi.available=true; - LOG_MSG("MIDI:Opened device:%s",handler->GetName()); - return; - } - handler=handler->next; - } - LOG_MSG("MIDI:Can't find device:%s, finding default handler.",dev); -getdefault: - handler=handler_list; - while (handler) { - if (handler->Open(conf)) { - midi.available=true; - midi.handler=handler; - LOG_MSG("MIDI:Opened device:%s",handler->GetName()); - return; - } - handler=handler->next; - } - /* This shouldn't be possible */ - } - ~MIDI(){ - if(midi.available) midi.handler->Close(); - midi.available = false; - midi.handler = 0; - } -}; - - -static MIDI* test; -void MIDI_Destroy(Section* /*sec*/){ - delete test; -} -void MIDI_Init(Section * sec) { - test = new MIDI(sec); - sec->AddDestroyFunction(&MIDI_Destroy,true); -} diff --git a/src/gui/midi_alsa.h b/src/gui/midi_alsa.h deleted file mode 100644 index 689a32b..0000000 --- a/src/gui/midi_alsa.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: midi_alsa.h,v 1.20 2009/04/27 17:33:12 qbix79 Exp $ */ - -#define ALSA_PCM_OLD_HW_PARAMS_API -#define ALSA_PCM_OLD_SW_PARAMS_API -#include -#include -#include -#include -#define ADDR_DELIM ".:" - -#if ((SND_LIB_MINOR >= 6) && (SND_LIB_MAJOR == 0)) || (SND_LIB_MAJOR >= 1) -#define snd_seq_flush_output(x) snd_seq_drain_output(x) -#define snd_seq_set_client_group(x,name) /*nop */ -#define my_snd_seq_open(seqp) snd_seq_open(seqp, "hw", SND_SEQ_OPEN_OUTPUT, 0) -#else -/* SND_SEQ_OPEN_OUT causes oops on early version of ALSA */ -#define my_snd_seq_open(seqp) snd_seq_open(seqp, SND_SEQ_OPEN) -#endif - -class MidiHandler_alsa : public MidiHandler { -private: - snd_seq_event_t ev; - snd_seq_t *seq_handle; - int seq_client, seq_port; - int my_client, my_port; - void send_event(int do_flush) { - snd_seq_ev_set_direct(&ev); - snd_seq_ev_set_source(&ev, my_port); - snd_seq_ev_set_dest(&ev, seq_client, seq_port); - - snd_seq_event_output(seq_handle, &ev); - if (do_flush) - snd_seq_flush_output(seq_handle); - } - - bool parse_addr(const char *arg, int *client, int *port) { - std::string in(arg); - if(in.empty()) return false; - - if(in[0] == 's' || in[0] == 'S') { - *client = SND_SEQ_ADDRESS_SUBSCRIBERS; - *port = 0; - return true; - } - - if(in.find_first_of(ADDR_DELIM) == std::string::npos) return false; - std::istringstream inp(in); - int val1, val2; char c; - if(!(inp >> val1)) return false; - if(!(inp >> c )) return false; - if(!(inp >> val2)) return false; - *client = val1; *port = val2; - return true; - } -public: - MidiHandler_alsa() : MidiHandler() {}; - const char* GetName(void) { return "alsa"; } - void PlaySysex(Bit8u * sysex,Bitu len) { - snd_seq_ev_set_sysex(&ev, len, sysex); - send_event(1); - } - - void PlayMsg(Bit8u * msg) { - ev.type = SND_SEQ_EVENT_OSS; - - ev.data.raw32.d[0] = msg[0]; - ev.data.raw32.d[1] = msg[1]; - ev.data.raw32.d[2] = msg[2]; - - unsigned char chanID = msg[0] & 0x0F; - switch (msg[0] & 0xF0) { - case 0x80: - snd_seq_ev_set_noteoff(&ev, chanID, msg[1], msg[2]); - send_event(1); - break; - case 0x90: - snd_seq_ev_set_noteon(&ev, chanID, msg[1], msg[2]); - send_event(1); - break; - case 0xB0: - snd_seq_ev_set_controller(&ev, chanID, msg[1], msg[2]); - send_event(1); - break; - case 0xC0: - snd_seq_ev_set_pgmchange(&ev, chanID, msg[1]); - send_event(0); - break; - case 0xD0: - snd_seq_ev_set_chanpress(&ev, chanID, msg[1]); - send_event(0); - break; - case 0xE0:{ - long theBend = ((long)msg[1] + (long)(msg[2] << 7)) - 0x2000; - snd_seq_ev_set_pitchbend(&ev, chanID, theBend); - send_event(1); - } - break; - default: - LOG(LOG_MISC,LOG_WARN)("ALSA:Unknown Command: %08lx", (long)msg); - send_event(1); - break; - } - } - - void Close(void) { - if (seq_handle) - snd_seq_close(seq_handle); - } - - bool Open(const char * conf) { - char var[10]; - unsigned int caps; - bool defaultport = true; //try 17:0. Seems to be default nowadays - - // try to use port specified in config file - if (conf && conf[0]) { - safe_strncpy(var, conf, 10); - if (!parse_addr(var, &seq_client, &seq_port)) { - LOG_MSG("ALSA:Invalid alsa port %s", var); - return false; - } - defaultport = false; - } - // default port if none specified - else if (!parse_addr("65:0", &seq_client, &seq_port)) { - LOG_MSG("ALSA:Invalid alsa port 65:0"); - return false; - } - - if (my_snd_seq_open(&seq_handle)) { - LOG_MSG("ALSA:Can't open sequencer"); - return false; - } - - my_client = snd_seq_client_id(seq_handle); - snd_seq_set_client_name(seq_handle, "DOSBOX"); - snd_seq_set_client_group(seq_handle, "input"); - - caps = SND_SEQ_PORT_CAP_READ; - if (seq_client == SND_SEQ_ADDRESS_SUBSCRIBERS) - caps = ~SND_SEQ_PORT_CAP_SUBS_READ; - my_port = - snd_seq_create_simple_port(seq_handle, "DOSBOX", caps, - SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); - if (my_port < 0) { - snd_seq_close(seq_handle); - LOG_MSG("ALSA:Can't create ALSA port"); - return false; - } - - if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) { - /* subscribe to MIDI port */ - if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) { - if (defaultport) { //if port "65:0" (default) try "17:0" as well - seq_client = 17; seq_port = 0; //Update reported values - if(snd_seq_connect_to(seq_handle,my_port,seq_client,seq_port) < 0) { //Try 128:0 Timidity port as well -// seq_client = 128; seq_port = 0; //Update reported values -// if(snd_seq_connect_to(seq_handle,my_port,seq_client,seq_port) < 0) { - snd_seq_close(seq_handle); - LOG_MSG("ALSA:Can't subscribe to MIDI port (65:0) nor (17:0)"); - return false; -// } - } - } else { - snd_seq_close(seq_handle); - LOG_MSG("ALSA:Can't subscribe to MIDI port (%d:%d)", seq_client, seq_port); - return false; - } - } - } - - LOG_MSG("ALSA:Client initialised [%d:%d]", seq_client, seq_port); - return true; - } - -}; - -MidiHandler_alsa Midi_alsa; diff --git a/src/gui/midi_coreaudio.h b/src/gui/midi_coreaudio.h deleted file mode 100644 index d8b2bfa..0000000 --- a/src/gui/midi_coreaudio.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include - -// A macro to simplify error handling a bit. -#define RequireNoErr(error) \ -do { \ - err = error; \ - if (err != noErr) \ - goto bail; \ -} while (false) - -class MidiHandler_coreaudio : public MidiHandler { -private: - AUGraph m_auGraph; - AudioUnit m_synth; -public: - MidiHandler_coreaudio() : m_auGraph(0), m_synth(0) {} - const char * GetName(void) { return "coreaudio"; } - bool Open(const char * conf) { - OSStatus err = 0; - - if (m_auGraph) - return false; - - // Open the Music Device. - RequireNoErr(NewAUGraph(&m_auGraph)); - - AUNode outputNode, synthNode; - ComponentDescription desc; - - // The default output device - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_DefaultOutput; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - RequireNoErr(AUGraphNewNode(m_auGraph, &desc, 0, NULL, &outputNode)); - - // The built-in default (softsynth) music device - desc.componentType = kAudioUnitType_MusicDevice; - desc.componentSubType = kAudioUnitSubType_DLSSynth; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - RequireNoErr(AUGraphNewNode(m_auGraph, &desc, 0, NULL, &synthNode)); - - // Connect the softsynth to the default output - RequireNoErr(AUGraphConnectNodeInput(m_auGraph, synthNode, 0, outputNode, 0)); - - // Open and initialize the whole graph - RequireNoErr(AUGraphOpen(m_auGraph)); - RequireNoErr(AUGraphInitialize(m_auGraph)); - - // Get the music device from the graph. - RequireNoErr(AUGraphGetNodeInfo(m_auGraph, synthNode, NULL, NULL, NULL, &m_synth)); - - // Finally: Start the graph! - RequireNoErr(AUGraphStart(m_auGraph)); - - return true; - - bail: - if (m_auGraph) { - AUGraphStop(m_auGraph); - DisposeAUGraph(m_auGraph); - m_auGraph = 0; - } - return false; - } - - void Close(void) { - if (m_auGraph) { - AUGraphStop(m_auGraph); - DisposeAUGraph(m_auGraph); - m_auGraph = 0; - } - } - - void PlayMsg(Bit8u * msg) { - MusicDeviceMIDIEvent(m_synth, msg[0], msg[1], msg[2], 0); - } - - void PlaySysex(Bit8u * sysex, Bitu len) { - MusicDeviceSysEx(m_synth, sysex, len); - } -}; - -#undef RequireNoErr - -MidiHandler_coreaudio Midi_coreaudio; diff --git a/src/gui/midi_coremidi.h b/src/gui/midi_coremidi.h deleted file mode 100644 index 8e50147..0000000 --- a/src/gui/midi_coremidi.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include - -class MidiHandler_coremidi : public MidiHandler { -private: - MIDIPortRef m_port; - MIDIClientRef m_client; - MIDIEndpointRef m_endpoint; - MIDIPacket* m_pCurPacket; -public: - MidiHandler_coremidi() {m_pCurPacket = 0;} - const char * GetName(void) { return "coremidi"; } - bool Open(const char * conf) { - - // Get the MIDIEndPoint - m_endpoint = 0; - OSStatus result; - Bitu numDests = MIDIGetNumberOfDestinations(); - Bitu destId = 0; - if(conf && conf[0]) destId = atoi(conf); - if (destId < numDests) - { - m_endpoint = MIDIGetDestination(destId); - } - - // Create a MIDI client and port - MIDIClientCreate(CFSTR("MyClient"), 0, 0, &m_client); - - if (!m_client) - { - LOG_MSG("MIDI:coremidi: No client created."); - return false; - } - - MIDIOutputPortCreate(m_client, CFSTR("MyOutPort"), &m_port); - - if (!m_port) - { - LOG_MSG("MIDI:coremidi: No port created."); - return false; - } - - - return true; - } - - void Close(void) { - // Dispose the port - MIDIPortDispose(m_port); - - // Dispose the client - MIDIClientDispose(m_client); - - // Dispose the endpoint - MIDIEndpointDispose(m_endpoint); - } - - void PlayMsg(Bit8u * msg) { - // Acquire a MIDIPacketList - Byte packetBuf[128]; - MIDIPacketList *packetList = (MIDIPacketList *)packetBuf; - m_pCurPacket = MIDIPacketListInit(packetList); - - // Determine the length of msg - Bitu len=MIDI_evt_len[*msg]; - - // Add msg to the MIDIPacketList - MIDIPacketListAdd(packetList, (ByteCount)sizeof(packetBuf), m_pCurPacket, (MIDITimeStamp)0, len, msg); - - // Send the MIDIPacketList - MIDISend(m_port,m_endpoint,packetList); - } - - void PlaySysex(Bit8u * sysex, Bitu len) { - // Acquire a MIDIPacketList - Byte packetBuf[SYSEX_SIZE*4]; - Bitu pos=0; - MIDIPacketList *packetList = (MIDIPacketList *)packetBuf; - m_pCurPacket = MIDIPacketListInit(packetList); - - // Add msg to the MIDIPacketList - MIDIPacketListAdd(packetList, (ByteCount)sizeof(packetBuf), m_pCurPacket, (MIDITimeStamp)0, len, sysex); - - // Send the MIDIPacketList - MIDISend(m_port,m_endpoint,packetList); - } -}; - -MidiHandler_coremidi Midi_coremidi; - diff --git a/src/gui/midi_oss.h b/src/gui/midi_oss.h deleted file mode 100644 index 2469990..0000000 --- a/src/gui/midi_oss.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#define SEQ_MIDIPUTC 5 - -class MidiHandler_oss: public MidiHandler { -private: - int device; - Bit8u device_num; - bool isOpen; -public: - MidiHandler_oss() : MidiHandler(),isOpen(false) {}; - const char * GetName(void) { return "oss";}; - bool Open(const char * conf) { - char devname[512]; - if (conf && conf[0]) safe_strncpy(devname,conf,512); - else strcpy(devname,"/dev/sequencer"); - char * devfind=(strrchr(devname,',')); - if (devfind) { - *devfind++=0; - device_num=atoi(devfind); - } else device_num=0; - if (isOpen) return false; - device=open(devname, O_WRONLY, 0); - if (device<0) return false; - return true; - }; - void Close(void) { - if (!isOpen) return; - if (device>0) close(device); - }; - void PlayMsg(Bit8u * msg) { - Bit8u buf[128];Bitu pos=0; - Bitu len=MIDI_evt_len[*msg]; - for (;len>0;len--) { - buf[pos++] = SEQ_MIDIPUTC; - buf[pos++] = *msg; - buf[pos++] = device_num; - buf[pos++] = 0; - msg++; - } - write(device,buf,pos); - }; - void PlaySysex(Bit8u * sysex,Bitu len) { - Bit8u buf[SYSEX_SIZE*4];Bitu pos=0; - for (;len>0;len--) { - buf[pos++] = SEQ_MIDIPUTC; - buf[pos++] = *sysex++; - buf[pos++] = device_num; - buf[pos++] = 0; - } - write(device,buf,pos); - } -}; - -MidiHandler_oss Midi_oss; - - - - diff --git a/src/gui/midi_win32.h b/src/gui/midi_win32.h deleted file mode 100644 index cfa7e28..0000000 --- a/src/gui/midi_win32.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: midi_win32.h,v 1.15 2008/08/06 18:32:34 c2woody Exp $ */ - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#include -#include - -class MidiHandler_win32: public MidiHandler { -private: - HMIDIOUT m_out; - MIDIHDR m_hdr; - HANDLE m_event; - bool isOpen; -public: - MidiHandler_win32() : MidiHandler(),isOpen(false) {}; - const char * GetName(void) { return "win32";}; - bool Open(const char * conf) { - if (isOpen) return false; - m_event = CreateEvent (NULL, true, true, NULL); - MMRESULT res = MMSYSERR_NOERROR; - if(conf && *conf) { - std::string strconf(conf); - std::istringstream configmidi(strconf); - unsigned int nummer = midiOutGetNumDevs(); - configmidi >> nummer; - if(nummer < midiOutGetNumDevs()){ - MIDIOUTCAPS mididev; - midiOutGetDevCaps(nummer, &mididev, sizeof(MIDIOUTCAPS)); - LOG_MSG("MIDI:win32 selected %s",mididev.szPname); - res = midiOutOpen(&m_out, nummer, (DWORD)m_event, 0, CALLBACK_EVENT); - } - } else { - res = midiOutOpen(&m_out, MIDI_MAPPER, (DWORD)m_event, 0, CALLBACK_EVENT); - } - if (res != MMSYSERR_NOERROR) return false; - isOpen=true; - return true; - }; - - void Close(void) { - if (!isOpen) return; - isOpen=false; - midiOutClose(m_out); - CloseHandle (m_event); - }; - void PlayMsg(Bit8u * msg) { - midiOutShortMsg(m_out, *(Bit32u*)msg); - }; - void PlaySysex(Bit8u * sysex,Bitu len) { - if (WaitForSingleObject (m_event, 2000) == WAIT_TIMEOUT) { - LOG(LOG_MISC,LOG_ERROR)("Can't send midi message"); - return; - } - midiOutUnprepareHeader (m_out, &m_hdr, sizeof (m_hdr)); - - m_hdr.lpData = (char *) sysex; - m_hdr.dwBufferLength = len ; - m_hdr.dwBytesRecorded = len ; - m_hdr.dwUser = 0; - - MMRESULT result = midiOutPrepareHeader (m_out, &m_hdr, sizeof (m_hdr)); - if (result != MMSYSERR_NOERROR) return; - ResetEvent (m_event); - result = midiOutLongMsg (m_out,&m_hdr,sizeof(m_hdr)); - if (result != MMSYSERR_NOERROR) { - SetEvent (m_event); - return; - } - } -}; - -MidiHandler_win32 Midi_win32; - - diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 6ba9921..b6867b0 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -1,634 +1,160 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: render.cpp,v 1.60 2009/04/26 19:14:50 harekiet Exp $ */ - -#include -#include -#include - -#include "dosbox.h" -#include "video.h" -#include "render.h" -#include "setup.h" -#include "control.h" -#include "mapper.h" -#include "cross.h" -#include "hardware.h" -#include "support.h" - -#include "render_scalers.h" - -Render_t render; -ScalerLineHandler_t RENDER_DrawLine; - -static void RENDER_CallBack( GFX_CallBackFunctions_t function ); - -static void Check_Palette(void) { - /* Clean up any previous changed palette data */ - if (render.pal.changed) { - memset(render.pal.modified, 0, sizeof(render.pal.modified)); - render.pal.changed = false; - } - if (render.pal.first>render.pal.last) - return; - Bitu i; - switch (render.scale.outMode) { - case scalerMode8: - GFX_SetPalette(render.pal.first,render.pal.last-render.pal.first+1,(GFX_PalEntry *)&render.pal.rgb[render.pal.first]); - break; - case scalerMode15: - case scalerMode16: - for (i=render.pal.first;i<=render.pal.last;i++) { - Bit8u r=render.pal.rgb[i].red; - Bit8u g=render.pal.rgb[i].green; - Bit8u b=render.pal.rgb[i].blue; - Bit16u newPal = GFX_GetRGB(r,g,b); - if (newPal != render.pal.lut.b16[i]) { - render.pal.changed = true; - render.pal.modified[i] = 1; - render.pal.lut.b16[i] = newPal; - } - } - break; - case scalerMode32: - default: - for (i=render.pal.first;i<=render.pal.last;i++) { - Bit8u r=render.pal.rgb[i].red; - Bit8u g=render.pal.rgb[i].green; - Bit8u b=render.pal.rgb[i].blue; - Bit32u newPal = GFX_GetRGB(r,g,b); - if (newPal != render.pal.lut.b32[i]) { - render.pal.changed = true; - render.pal.modified[i] = 1; - render.pal.lut.b32[i] = newPal; - } - } - break; - } - /* Setup pal index to startup values */ - render.pal.first=256; - render.pal.last=0; -} - -void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) { - render.pal.rgb[entry].red=red; - render.pal.rgb[entry].green=green; - render.pal.rgb[entry].blue=blue; - if (render.pal.first>entry) render.pal.first=entry; - if (render.pal.last0;) { - if (GCC_UNLIKELY(src[0] != cache[0])) { - if (!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch )) { - RENDER_DrawLine = RENDER_EmptyLineHandler; - return; - } - render.scale.outWrite += render.scale.outPitch * Scaler_ChangedLines[0]; - RENDER_DrawLine = render.scale.lineHandler; - RENDER_DrawLine( s ); - return; - } - x--; src++; cache++; - } - } - render.scale.cacheRead += render.scale.cachePitch; - Scaler_ChangedLines[0] += Scaler_Aspect[ render.scale.inLine ]; - render.scale.inLine++; - render.scale.outLine++; -} - -static void RENDER_FinishLineHandler(const void * s) { - if (s) { - const Bitu *src = (Bitu*)s; - Bitu *cache = (Bitu*)(render.scale.cacheRead); - for (Bits x=render.src.start;x>0;) { - cache[0] = src[0]; - x--; src++; cache++; - } - } - render.scale.cacheRead += render.scale.cachePitch; -} - - -static void RENDER_ClearCacheHandler(const void * src) { - Bitu x, width; - Bit32u *srcLine, *cacheLine; - srcLine = (Bit32u *)src; - cacheLine = (Bit32u *)render.scale.cacheRead; - width = render.scale.cachePitch / 4; - for (x=0;x= miny) { - Bitu templines = (Bitu)lines; - lines -= templines; - linesadded += templines; - Scaler_Aspect[i] = templines; - } else { - Scaler_Aspect[i] = 0; - } - } - return linesadded; -} - - -static void RENDER_Reset( void ) { - Bitu width=render.src.width; - Bitu height=render.src.height; - bool dblw=render.src.dblw; - bool dblh=render.src.dblh; - - double gfx_scalew; - double gfx_scaleh; - - Bitu gfx_flags, xscale, yscale; - ScalerSimpleBlock_t *simpleBlock = &ScaleNormal1x; - ScalerComplexBlock_t *complexBlock = 0; - if (render.aspect) { - if (render.src.ratio>1.0) { - gfx_scalew = 1; - gfx_scaleh = render.src.ratio; - } else { - gfx_scalew = (1/render.src.ratio); - gfx_scaleh = 1; - } - } else { - gfx_scalew = 1; - gfx_scaleh = 1; - } - if ((dblh && dblw) || (render.scale.forced && !dblh && !dblw)) { - /* Initialize always working defaults */ - if (render.scale.size == 2) - simpleBlock = &ScaleNormal2x; - else if (render.scale.size == 3) - simpleBlock = &ScaleNormal3x; - else - simpleBlock = &ScaleNormal1x; - /* Maybe override them */ -#if RENDER_USE_ADVANCED_SCALERS>0 - switch (render.scale.op) { -#if RENDER_USE_ADVANCED_SCALERS>2 - case scalerOpAdvInterp: - if (render.scale.size == 2) - complexBlock = &ScaleAdvInterp2x; - else if (render.scale.size == 3) - complexBlock = &ScaleAdvInterp3x; - break; - case scalerOpAdvMame: - if (render.scale.size == 2) - complexBlock = &ScaleAdvMame2x; - else if (render.scale.size == 3) - complexBlock = &ScaleAdvMame3x; - break; - case scalerOpHQ: - if (render.scale.size == 2) - complexBlock = &ScaleHQ2x; - else if (render.scale.size == 3) - complexBlock = &ScaleHQ3x; - break; - case scalerOpSuperSaI: - if (render.scale.size == 2) - complexBlock = &ScaleSuper2xSaI; - break; - case scalerOpSuperEagle: - if (render.scale.size == 2) - complexBlock = &ScaleSuperEagle; - break; - case scalerOpSaI: - if (render.scale.size == 2) - complexBlock = &Scale2xSaI; - break; -#endif - case scalerOpTV: - if (render.scale.size == 2) - simpleBlock = &ScaleTV2x; - else if (render.scale.size == 3) - simpleBlock = &ScaleTV3x; - break; - case scalerOpRGB: - if (render.scale.size == 2) - simpleBlock = &ScaleRGB2x; - else if (render.scale.size == 3) - simpleBlock = &ScaleRGB3x; - break; - case scalerOpScan: - if (render.scale.size == 2) - simpleBlock = &ScaleScan2x; - else if (render.scale.size == 3) - simpleBlock = &ScaleScan3x; - break; - default: - break; - } -#endif - } else if (dblw) { - simpleBlock = &ScaleNormalDw; - } else if (dblh) { - simpleBlock = &ScaleNormalDh; - } else { -forcenormal: - complexBlock = 0; - simpleBlock = &ScaleNormal1x; - } - if (complexBlock) { -#if RENDER_USE_ADVANCED_SCALERS>1 - if ((width >= SCALER_COMPLEXWIDTH - 16) || height >= SCALER_COMPLEXHEIGHT - 16) { - LOG_MSG("Scaler can't handle this resolution, going back to normal"); - goto forcenormal; - } -#else - goto forcenormal; -#endif - gfx_flags = complexBlock->gfxFlags; - xscale = complexBlock->xscale; - yscale = complexBlock->yscale; -// LOG_MSG("Scaler:%s",complexBlock->name); - } else { - gfx_flags = simpleBlock->gfxFlags; - xscale = simpleBlock->xscale; - yscale = simpleBlock->yscale; -// LOG_MSG("Scaler:%s",simpleBlock->name); - } - switch (render.src.bpp) { - case 8: - render.src.start = ( render.src.width * 1) / sizeof(Bitu); - if (gfx_flags & GFX_CAN_8) - gfx_flags |= GFX_LOVE_8; - else - gfx_flags |= GFX_LOVE_32; - break; - case 15: - render.src.start = ( render.src.width * 2) / sizeof(Bitu); - gfx_flags |= GFX_LOVE_15; - gfx_flags = (gfx_flags & ~GFX_CAN_8) | GFX_RGBONLY; - break; - case 16: - render.src.start = ( render.src.width * 2) / sizeof(Bitu); - gfx_flags |= GFX_LOVE_16; - gfx_flags = (gfx_flags & ~GFX_CAN_8) | GFX_RGBONLY; - break; - case 32: - render.src.start = ( render.src.width * 4) / sizeof(Bitu); - gfx_flags |= GFX_LOVE_32; - gfx_flags = (gfx_flags & ~GFX_CAN_8) | GFX_RGBONLY; - break; - } - gfx_flags=GFX_GetBestMode(gfx_flags); - if (!gfx_flags) { - if (!complexBlock && simpleBlock == &ScaleNormal1x) - E_Exit("Failed to create a rendering output"); - else - goto forcenormal; - } - width *= xscale; - Bitu skip = complexBlock ? 1 : 0; - if (gfx_flags & GFX_SCALING) { - height = MakeAspectTable(skip, render.src.height, yscale, yscale ); - } else { - if ((gfx_flags & GFX_CAN_RANDOM) && gfx_scaleh > 1) { - gfx_scaleh *= yscale; - height = MakeAspectTable( skip, render.src.height, gfx_scaleh, yscale ); - } else { - gfx_flags &= ~GFX_CAN_RANDOM; //Hardware surface when possible - height = MakeAspectTable( skip, render.src.height, yscale, yscale); - } - } -/* Setup the scaler variables */ - gfx_flags=GFX_SetSize(width,height,gfx_flags,gfx_scalew,gfx_scaleh,&RENDER_CallBack); - if (gfx_flags & GFX_CAN_8) - render.scale.outMode = scalerMode8; - else if (gfx_flags & GFX_CAN_15) - render.scale.outMode = scalerMode15; - else if (gfx_flags & GFX_CAN_16) - render.scale.outMode = scalerMode16; - else if (gfx_flags & GFX_CAN_32) - render.scale.outMode = scalerMode32; - else - E_Exit("Failed to create a rendering output"); - ScalerLineBlock_t *lineBlock; - if (gfx_flags & GFX_HARDWARE) { -#if RENDER_USE_ADVANCED_SCALERS>1 - if (complexBlock) { - lineBlock = &ScalerCache; - render.scale.complexHandler = complexBlock->Linear[ render.scale.outMode ]; - } else -#endif - { - render.scale.complexHandler = 0; - lineBlock = &simpleBlock->Linear; - } - } else { -#if RENDER_USE_ADVANCED_SCALERS>1 - if (complexBlock) { - lineBlock = &ScalerCache; - render.scale.complexHandler = complexBlock->Random[ render.scale.outMode ]; - } else -#endif - { - render.scale.complexHandler = 0; - lineBlock = &simpleBlock->Random; - } - } - switch (render.src.bpp) { - case 8: - render.scale.lineHandler = (*lineBlock)[0][render.scale.outMode]; - render.scale.linePalHandler = (*lineBlock)[4][render.scale.outMode]; - render.scale.inMode = scalerMode8; - render.scale.cachePitch = render.src.width * 1; - break; - case 15: - render.scale.lineHandler = (*lineBlock)[1][render.scale.outMode]; - render.scale.linePalHandler = 0; - render.scale.inMode = scalerMode15; - render.scale.cachePitch = render.src.width * 2; - break; - case 16: - render.scale.lineHandler = (*lineBlock)[2][render.scale.outMode]; - render.scale.linePalHandler = 0; - render.scale.inMode = scalerMode16; - render.scale.cachePitch = render.src.width * 2; - break; - case 32: - render.scale.lineHandler = (*lineBlock)[3][render.scale.outMode]; - render.scale.linePalHandler = 0; - render.scale.inMode = scalerMode32; - render.scale.cachePitch = render.src.width * 4; - break; - default: - E_Exit("RENDER:Wrong source bpp %d", render.src.bpp ); - } - render.scale.blocks = render.src.width / SCALER_BLOCKSIZE; - render.scale.lastBlock = render.src.width % SCALER_BLOCKSIZE; - render.scale.inHeight = render.src.height; - /* Reset the palette change detection to it's initial value */ - render.pal.first= 0; - render.pal.last = 255; - render.pal.changed = false; - memset(render.pal.modified, 0, sizeof(render.pal.modified)); - //Finish this frame using a copy only handler - RENDER_DrawLine = RENDER_FinishLineHandler; - render.scale.outWrite = 0; - /* Signal the next frame to first reinit the cache */ - render.scale.clearCache = true; - render.active=true; -} - -static void RENDER_CallBack( GFX_CallBackFunctions_t function ) { - if (function == GFX_CallBackStop) { - RENDER_Halt( ); - return; - } else if (function == GFX_CallBackRedraw) { - render.scale.clearCache = true; - return; - } else if ( function == GFX_CallBackReset) { - GFX_EndUpdate( 0 ); - RENDER_Reset(); - } else { - E_Exit("Unhandled GFX_CallBackReset %d", function ); - } -} - -void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double ratio,bool dblw,bool dblh) { - RENDER_Halt( ); - if (!width || !height || width > SCALER_MAXWIDTH || height > SCALER_MAXHEIGHT) { - return; - } - if ( ratio > 1 ) { - double target = height * ratio + 0.1; - ratio = target / height; - } else { - //This would alter the width of the screen, we don't care about rounding errors here - } - render.src.width=width; - render.src.height=height; - render.src.bpp=bpp; - render.src.dblw=dblw; - render.src.dblh=dblh; - render.src.fps=fps; - render.src.ratio=ratio; - RENDER_Reset( ); -} - -extern void GFX_SetTitle(Bit32s cycles, Bits frameskip,bool paused); -static void IncreaseFrameSkip(bool pressed) { - if (!pressed) - return; - if (render.frameskip.max<10) render.frameskip.max++; - LOG_MSG("Frame Skip at %d",render.frameskip.max); - GFX_SetTitle(-1,render.frameskip.max,false); -} - -static void DecreaseFrameSkip(bool pressed) { - if (!pressed) - return; - if (render.frameskip.max>0) render.frameskip.max--; - LOG_MSG("Frame Skip at %d",render.frameskip.max); - GFX_SetTitle(-1,render.frameskip.max,false); -} -/* Disabled as I don't want to waste a keybind for that. Might be used in the future (Qbix) -static void ChangeScaler(bool pressed) { - if (!pressed) - return; - render.scale.op = (scalerOperation)((int)render.scale.op+1); - if((render.scale.op) >= scalerLast || render.scale.size == 1) { - render.scale.op = (scalerOperation)0; - if(++render.scale.size > 3) - render.scale.size = 1; - } - RENDER_CallBack( GFX_CallBackReset ); -} */ - -void RENDER_Init(Section * sec) { - Section_prop * section=static_cast(sec); - - //For restarting the renderer. - static bool running = false; - bool aspect = render.aspect; - Bitu scalersize = render.scale.size; - bool scalerforced = render.scale.forced; - scalerOperation_t scaleOp = render.scale.op; - - render.pal.first=256; - render.pal.last=0; - render.aspect=section->Get_bool("aspect"); - render.frameskip.max=section->Get_int("frameskip"); - render.frameskip.count=0; - std::string cline; - std::string scaler; - //Check for commandline paramters and parse them through the configclass so they get checked against allowed values - if (control->cmdline->FindString("-scaler",cline,false)) { - section->HandleInputline(std::string("scaler=") + cline); - } else if (control->cmdline->FindString("-forcescaler",cline,false)) { - section->HandleInputline(std::string("scaler=") + cline + " forced"); - } - - Prop_multival* prop = section->Get_multival("scaler"); - scaler = prop->GetSection()->Get_string("type"); - std::string f = prop->GetSection()->Get_string("force"); - render.scale.forced = false; - if(f == "forced") render.scale.forced = true; - - if (scaler == "none") { render.scale.op = scalerOpNormal;render.scale.size = 1; } - else if (scaler == "normal2x") { render.scale.op = scalerOpNormal;render.scale.size = 2; } - else if (scaler == "normal3x") { render.scale.op = scalerOpNormal;render.scale.size = 3; } -#if RENDER_USE_ADVANCED_SCALERS>2 - else if (scaler == "advmame2x") { render.scale.op = scalerOpAdvMame;render.scale.size = 2; } - else if (scaler == "advmame3x") { render.scale.op = scalerOpAdvMame;render.scale.size = 3; } - else if (scaler == "advinterp2x") { render.scale.op = scalerOpAdvInterp;render.scale.size = 2; } - else if (scaler == "advinterp3x") { render.scale.op = scalerOpAdvInterp;render.scale.size = 3; } - else if (scaler == "hq2x") { render.scale.op = scalerOpHQ;render.scale.size = 2; } - else if (scaler == "hq3x") { render.scale.op = scalerOpHQ;render.scale.size = 3; } - else if (scaler == "2xsai") { render.scale.op = scalerOpSaI;render.scale.size = 2; } - else if (scaler == "super2xsai") { render.scale.op = scalerOpSuperSaI;render.scale.size = 2; } - else if (scaler == "supereagle") { render.scale.op = scalerOpSuperEagle;render.scale.size = 2; } -#endif -#if RENDER_USE_ADVANCED_SCALERS>0 - else if (scaler == "tv2x") { render.scale.op = scalerOpTV;render.scale.size = 2; } - else if (scaler == "tv3x") { render.scale.op = scalerOpTV;render.scale.size = 3; } - else if (scaler == "rgb2x"){ render.scale.op = scalerOpRGB;render.scale.size = 2; } - else if (scaler == "rgb3x"){ render.scale.op = scalerOpRGB;render.scale.size = 3; } - else if (scaler == "scan2x"){ render.scale.op = scalerOpScan;render.scale.size = 2; } - else if (scaler == "scan3x"){ render.scale.op = scalerOpScan;render.scale.size = 3; } -#endif - - //If something changed that needs a ReInit - // Only ReInit when there is a src.bpp (fixes crashes on startup and directly changing the scaler without a screen specified yet) - if(running && render.src.bpp && ((render.aspect != aspect) || (render.scale.op != scaleOp) || - (render.scale.size != scalersize) || (render.scale.forced != scalerforced) || - render.scale.forced)) - RENDER_CallBack( GFX_CallBackReset ); - - if(!running) render.updating=true; - running = true; - - MAPPER_AddHandler(DecreaseFrameSkip,MK_f7,MMOD1,"decfskip","Dec Fskip"); - MAPPER_AddHandler(IncreaseFrameSkip,MK_f8,MMOD1,"incfskip","Inc Fskip"); - GFX_SetTitle(-1,render.frameskip.max,false); -} - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "video.h" +#include "render.h" + + + +#define MAX_RES 2048 + +struct PalData { + struct { + Bit8u red; + Bit8u green; + Bit8u blue; + Bit8u unused; + } rgb[256]; + Bitu first; + Bitu last; +}; + + +static struct { + struct { + Bitu width; + Bitu height; + Bitu bpp; + Bitu pitch; + float ratio; + } src; + Bitu flags; + RENDER_Handler * handler; + Bitu stretch_x[MAX_RES]; + Bitu stretch_y[MAX_RES]; + PalData pal; + bool remake; + bool enlarge; +} render; + +/* This could go kinda bad with multiple threads */ +static void Check_Palette(void) { + if (render.pal.first>render.pal.last) return; + + GFX_SetPalette(render.pal.first,render.pal.last-render.pal.first+1,(GFX_PalEntry *)&render.pal.rgb[render.pal.first]); + render.pal.first=256; + render.pal.last=0; +} + +static void MakeTables(void) { + //The stretching tables + Bitu i;Bit32u c,a; + c=0;a=(render.src.width<<16)/gfx_info.width; + for (i=0;i> 16; + c=(c&0xffff)+a; + } + c=0;a=(render.src.height<<16)/gfx_info.height; + for (i=0;i> 16)*render.src.pitch; + c=(c&0xffff)+a; + } +} + +static void Draw_8_Normal(Bit8u * src_data,Bit8u * dst_data) { + for (Bitu y=0;yentry) render.pal.first=entry; + if (render.pal.last 1) - PTYPE * line1; -#endif -#if (SCALERHEIGHT > 2) - PTYPE * line2; -#endif - /* Clear this block being dirty marker */ - const Bitu changeType = changed[b]; - changed[b] = 0; - switch (changeType) { - case 0: - line0 += SCALERWIDTH * SCALER_BLOCKSIZE; - fc += SCALER_BLOCKSIZE; - continue; - case SCALE_LEFT: -#if (SCALERHEIGHT > 1) - line1 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch); -#endif -#if (SCALERHEIGHT > 2) - line2 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch * 2); -#endif - SCALERFUNC; - line0 += SCALERWIDTH * SCALER_BLOCKSIZE; - fc += SCALER_BLOCKSIZE; - break; - case SCALE_LEFT | SCALE_RIGHT: -#if (SCALERHEIGHT > 1) - line1 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch); -#endif -#if (SCALERHEIGHT > 2) - line2 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch * 2); -#endif - SCALERFUNC; - case SCALE_RIGHT: -#if (SCALERHEIGHT > 1) - line1 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch); -#endif -#if (SCALERHEIGHT > 2) - line2 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch * 2); -#endif - line0 += SCALERWIDTH * (SCALER_BLOCKSIZE -1); -#if (SCALERHEIGHT > 1) - line1 += SCALERWIDTH * (SCALER_BLOCKSIZE -1); -#endif -#if (SCALERHEIGHT > 2) - line2 += SCALERWIDTH * (SCALER_BLOCKSIZE -1); -#endif - fc += SCALER_BLOCKSIZE -1; - SCALERFUNC; - line0 += SCALERWIDTH; - fc++; - break; - default: -#if defined(SCALERLINEAR) -#if (SCALERHEIGHT > 1) - line1 = WC[0]; -#endif -#if (SCALERHEIGHT > 2) - line2 = WC[1]; -#endif -#else -#if (SCALERHEIGHT > 1) - line1 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch); -#endif -#if (SCALERHEIGHT > 2) - line2 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch * 2); -#endif -#endif //defined(SCALERLINEAR) - for (Bitu i = 0; i 1) - line1 += SCALERWIDTH; -#endif -#if (SCALERHEIGHT > 2) - line2 += SCALERWIDTH; -#endif - fc++; - } -#if defined(SCALERLINEAR) -#if (SCALERHEIGHT > 1) - BituMove((Bit8u*)(&line0[-SCALER_BLOCKSIZE*SCALERWIDTH])+render.scale.outPitch ,WC[0], SCALER_BLOCKSIZE *SCALERWIDTH*PSIZE); -#endif -#if (SCALERHEIGHT > 2) - BituMove((Bit8u*)(&line0[-SCALER_BLOCKSIZE*SCALERWIDTH])+render.scale.outPitch*2,WC[1], SCALER_BLOCKSIZE *SCALERWIDTH*PSIZE); -#endif -#endif //defined(SCALERLINEAR) - break; - } - } -#if defined(SCALERLINEAR) - Bitu scaleLines = SCALERHEIGHT; -#else - Bitu scaleLines = Scaler_Aspect[ render.scale.outLine ]; - if ( ((Bits)(scaleLines - SCALERHEIGHT)) > 0 ) { - BituMove( render.scale.outWrite + render.scale.outPitch * SCALERHEIGHT, - render.scale.outWrite + render.scale.outPitch * (SCALERHEIGHT-1), - render.src.width * SCALERWIDTH * PSIZE); - } -#endif - ScalerAddLines( 1, scaleLines ); - if (++render.scale.outLine == render.scale.inHeight) - goto lastagain; -} - -#if !defined(SCALERLINEAR) -#define SCALERLINEAR 1 -#include "render_loops.h" -#undef SCALERLINEAR -#endif diff --git a/src/gui/render_scalers.cpp b/src/gui/render_scalers.cpp deleted file mode 100644 index 78880d0..0000000 --- a/src/gui/render_scalers.cpp +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -//TODO: -//Maybe just do the cache checking back into the simple scalers so they can -//just handle it all in one go, but this seems to work well enough for now - -#include "dosbox.h" -#include "render.h" -#include - -Bit8u Scaler_Aspect[SCALER_MAXHEIGHT]; -Bit16u Scaler_ChangedLines[SCALER_MAXHEIGHT]; -Bitu Scaler_ChangedLineIndex; - -static union { - Bit32u b32 [4][SCALER_MAXWIDTH*3]; - Bit16u b16 [4][SCALER_MAXWIDTH*3]; - Bit8u b8 [4][SCALER_MAXWIDTH*3]; -} scalerWriteCache; -//scalerFrameCache_t scalerFrameCache; -scalerSourceCache_t scalerSourceCache; -#if RENDER_USE_ADVANCED_SCALERS>1 -scalerChangeCache_t scalerChangeCache; -#endif - -#define _conc2(A,B) A ## B -#define _conc3(A,B,C) A ## B ## C -#define _conc4(A,B,C,D) A ## B ## C ## D -#define _conc5(A,B,C,D,E) A ## B ## C ## D ## E -#define _conc7(A,B,C,D,E,F,G) A ## B ## C ## D ## E ## F ## G - -#define conc2(A,B) _conc2(A,B) -#define conc3(A,B,C) _conc3(A,B,C) -#define conc4(A,B,C,D) _conc4(A,B,C,D) -#define conc2d(A,B) _conc3(A,_,B) -#define conc3d(A,B,C) _conc5(A,_,B,_,C) -#define conc4d(A,B,C,D) _conc7(A,_,B,_,C,_,D) - -static INLINE void BituMove( void *_dst, const void * _src, Bitu size) { - Bitu * dst=(Bitu *)(_dst); - const Bitu * src=(Bitu *)(_src); - size/=sizeof(Bitu); - for (Bitu x=0; x1 -ScalerLineBlock_t ScalerCache = { -{ Cache_8_8, Cache_8_15 , Cache_8_16 , Cache_8_32 }, -{ 0, Cache_15_15, Cache_15_16, Cache_15_32}, -{ 0, Cache_16_15, Cache_16_16, Cache_16_32}, -{ 0, Cache_32_15, Cache_32_16, Cache_32_32}, -{ Cache_8_8, Cache_9_15 , Cache_9_16 , Cache_9_32 } -}; -#endif - -ScalerSimpleBlock_t ScaleNormal1x = { - "Normal", - GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 1,1,{ -{ Normal1x_8_8_L, Normal1x_8_15_L , Normal1x_8_16_L , Normal1x_8_32_L }, -{ 0, Normal1x_15_15_L, Normal1x_15_16_L, Normal1x_15_32_L}, -{ 0, Normal1x_16_15_L, Normal1x_16_16_L, Normal1x_16_32_L}, -{ 0, Normal1x_32_15_L, Normal1x_32_16_L, Normal1x_32_32_L}, -{ Normal1x_8_8_L, Normal1x_9_15_L , Normal1x_9_16_L , Normal1x_9_32_L } -},{ -{ Normal1x_8_8_R, Normal1x_8_15_R , Normal1x_8_16_R , Normal1x_8_32_R }, -{ 0, Normal1x_15_15_R, Normal1x_15_16_R, Normal1x_15_32_R}, -{ 0, Normal1x_16_15_R, Normal1x_16_16_R, Normal1x_16_32_R}, -{ 0, Normal1x_32_15_R, Normal1x_32_16_R, Normal1x_32_32_R}, -{ Normal1x_8_8_R, Normal1x_9_15_R , Normal1x_9_16_R , Normal1x_9_32_R } -}}; - -ScalerSimpleBlock_t ScaleNormalDw = { - "Normal", - GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 2,1,{ -{ NormalDw_8_8_L, NormalDw_8_15_L , NormalDw_8_16_L , NormalDw_8_32_L }, -{ 0, NormalDw_15_15_L, NormalDw_15_16_L, NormalDw_15_32_L}, -{ 0, NormalDw_16_15_L, NormalDw_16_16_L, NormalDw_16_32_L}, -{ 0, NormalDw_32_15_L, NormalDw_32_16_L, NormalDw_32_32_L}, -{ NormalDw_8_8_L, NormalDw_9_15_L , NormalDw_9_16_L , NormalDw_9_32_L } -},{ -{ NormalDw_8_8_R, NormalDw_8_15_R , NormalDw_8_16_R , NormalDw_8_32_R }, -{ 0, NormalDw_15_15_R, NormalDw_15_16_R, NormalDw_15_32_R}, -{ 0, NormalDw_16_15_R, NormalDw_16_16_R, NormalDw_16_32_R}, -{ 0, NormalDw_32_15_R, NormalDw_32_16_R, NormalDw_32_32_R}, -{ NormalDw_8_8_R, NormalDw_9_15_R , NormalDw_9_16_R , NormalDw_9_32_R } -}}; - -ScalerSimpleBlock_t ScaleNormalDh = { - "Normal", - GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 1,2,{ -{ NormalDh_8_8_L, NormalDh_8_15_L , NormalDh_8_16_L , NormalDh_8_32_L }, -{ 0, NormalDh_15_15_L, NormalDh_15_16_L, NormalDh_15_32_L}, -{ 0, NormalDh_16_15_L, NormalDh_16_16_L, NormalDh_16_32_L}, -{ 0, NormalDh_32_15_L, NormalDh_32_16_L, NormalDh_32_32_L}, -{ NormalDh_8_8_L, NormalDh_9_15_L , NormalDh_9_16_L , NormalDh_9_32_L } -},{ -{ NormalDh_8_8_R, NormalDh_8_15_R , NormalDh_8_16_R , NormalDh_8_32_R }, -{ 0, NormalDh_15_15_R, NormalDh_15_16_R, NormalDh_15_32_R}, -{ 0, NormalDh_16_15_R, NormalDh_16_16_R, NormalDh_16_32_R}, -{ 0, NormalDh_32_15_R, NormalDh_32_16_R, NormalDh_32_32_R}, -{ NormalDh_8_8_R, NormalDh_9_15_R , NormalDh_9_16_R , NormalDh_9_32_R } -}}; - -ScalerSimpleBlock_t ScaleNormal2x = { - "Normal2x", - GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 2,2,{ -{ Normal2x_8_8_L, Normal2x_8_15_L, Normal2x_8_16_L, Normal2x_8_32_L }, -{ 0, Normal2x_15_15_L, Normal2x_15_16_L, Normal2x_15_32_L}, -{ 0, Normal2x_16_15_L, Normal2x_16_16_L, Normal2x_16_32_L}, -{ 0, Normal2x_32_15_L, Normal2x_32_16_L, Normal2x_32_32_L}, -{ Normal2x_8_8_L, Normal2x_9_15_L , Normal2x_9_16_L, Normal2x_9_32_L } -},{ -{ Normal2x_8_8_R, Normal2x_8_15_R , Normal2x_8_16_R, Normal2x_8_32_R }, -{ 0, Normal2x_15_15_R, Normal2x_15_16_R, Normal2x_15_32_R}, -{ 0, Normal2x_16_15_R, Normal2x_16_16_R, Normal2x_16_32_R}, -{ 0, Normal2x_32_15_R, Normal2x_32_16_R, Normal2x_32_32_R}, -{ Normal2x_8_8_R, Normal2x_9_15_R , Normal2x_9_16_R, Normal2x_9_32_R }, -}}; - -ScalerSimpleBlock_t ScaleNormal3x = { - "Normal3x", - GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 3,3,{ -{ Normal3x_8_8_L, Normal3x_8_15_L , Normal3x_8_16_L , Normal3x_8_32_L }, -{ 0, Normal3x_15_15_L, Normal3x_15_16_L, Normal3x_15_32_L}, -{ 0, Normal3x_16_15_L, Normal3x_16_16_L, Normal3x_16_32_L}, -{ 0, Normal3x_32_15_L, Normal3x_32_16_L, Normal3x_32_32_L}, -{ Normal3x_8_8_L, Normal3x_9_15_L , Normal3x_9_16_L , Normal3x_9_32_L } -},{ -{ Normal3x_8_8_R, Normal3x_8_15_R , Normal3x_8_16_R , Normal3x_8_32_R }, -{ 0, Normal3x_15_15_R, Normal3x_15_16_R, Normal3x_15_32_R}, -{ 0, Normal3x_16_15_R, Normal3x_16_16_R, Normal3x_16_32_R}, -{ 0, Normal3x_32_15_R, Normal3x_32_16_R, Normal3x_32_32_R}, -{ Normal3x_8_8_R, Normal3x_9_15_R , Normal3x_9_16_R , Normal3x_9_32_R } -}}; - -#if RENDER_USE_ADVANCED_SCALERS>0 -ScalerSimpleBlock_t ScaleTV2x = { - "TV2x", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2,{ -{ 0, TV2x_8_15_L , TV2x_8_16_L , TV2x_8_32_L }, -{ 0, TV2x_15_15_L, TV2x_15_16_L, TV2x_15_32_L}, -{ 0, TV2x_16_15_L, TV2x_16_16_L, TV2x_16_32_L}, -{ 0, TV2x_32_15_L, TV2x_32_16_L, TV2x_32_32_L}, -{ 0, TV2x_9_15_L , TV2x_9_16_L , TV2x_9_32_L } -},{ -{ 0, TV2x_8_15_R , TV2x_8_16_R , TV2x_8_32_R }, -{ 0, TV2x_15_15_R, TV2x_15_16_R, TV2x_15_32_R}, -{ 0, TV2x_16_15_R, TV2x_16_16_R, TV2x_16_32_R}, -{ 0, TV2x_32_15_R, TV2x_32_16_R, TV2x_32_32_R}, -{ 0, TV2x_9_15_R , TV2x_9_16_R , TV2x_9_32_R } -}}; - -ScalerSimpleBlock_t ScaleTV3x = { - "TV3x", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 3,3,{ -{ 0, TV3x_8_15_L , TV3x_8_16_L , TV3x_8_32_L }, -{ 0, TV3x_15_15_L, TV3x_15_16_L, TV3x_15_32_L}, -{ 0, TV3x_16_15_L, TV3x_16_16_L, TV3x_16_32_L}, -{ 0, TV3x_32_15_L, TV3x_32_16_L, TV3x_32_32_L}, -{ 0, TV3x_9_15_L , TV3x_9_16_L , TV3x_9_32_L } -},{ -{ 0, TV3x_8_15_R , TV3x_8_16_R , TV3x_8_32_R }, -{ 0, TV3x_15_15_R, TV3x_15_16_R, TV3x_15_32_R}, -{ 0, TV3x_16_15_R, TV3x_16_16_R, TV3x_16_32_R}, -{ 0, TV3x_32_15_R, TV3x_32_16_R, TV3x_32_32_R}, -{ 0, TV3x_9_15_R , TV3x_9_16_R , TV3x_9_32_R } -}}; - -ScalerSimpleBlock_t ScaleScan2x = { - "Scan2x", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2,{ -{ 0, Scan2x_8_15_L , Scan2x_8_16_L , Scan2x_8_32_L }, -{ 0, Scan2x_15_15_L, Scan2x_15_16_L, Scan2x_15_32_L}, -{ 0, Scan2x_16_15_L, Scan2x_16_16_L, Scan2x_16_32_L}, -{ 0, Scan2x_32_15_L, Scan2x_32_16_L, Scan2x_32_32_L}, -{ 0, Scan2x_9_15_L , Scan2x_9_16_L , Scan2x_9_32_L } -},{ -{ 0, Scan2x_8_15_R , Scan2x_8_16_R , Scan2x_8_32_R }, -{ 0, Scan2x_15_15_R, Scan2x_15_16_R, Scan2x_15_32_R}, -{ 0, Scan2x_16_15_R, Scan2x_16_16_R, Scan2x_16_32_R}, -{ 0, Scan2x_32_15_R, Scan2x_32_16_R, Scan2x_32_32_R}, -{ 0, Scan2x_9_15_R , Scan2x_9_16_R , Scan2x_9_32_R } -}}; - -ScalerSimpleBlock_t ScaleScan3x = { - "Scan3x", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 3,3,{ -{ 0, Scan3x_8_15_L , Scan3x_8_16_L , Scan3x_8_32_L }, -{ 0, Scan3x_15_15_L, Scan3x_15_16_L, Scan3x_15_32_L}, -{ 0, Scan3x_16_15_L, Scan3x_16_16_L, Scan3x_16_32_L}, -{ 0, Scan3x_32_15_L, Scan3x_32_16_L, Scan3x_32_32_L}, -{ 0, Scan3x_9_15_L , Scan3x_9_16_L , Scan3x_9_32_L }, -},{ -{ 0, Scan3x_8_15_R , Scan3x_8_16_R , Scan3x_8_32_R }, -{ 0, Scan3x_15_15_R, Scan3x_15_16_R, Scan3x_15_32_R}, -{ 0, Scan3x_16_15_R, Scan3x_16_16_R, Scan3x_16_32_R}, -{ 0, Scan3x_32_15_R, Scan3x_32_16_R, Scan3x_32_32_R}, -{ 0, Scan3x_9_15_R , Scan3x_9_16_R , Scan3x_9_32_R } -}}; - -ScalerSimpleBlock_t ScaleRGB2x = { - "RGB2x", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2,{ -{ 0, RGB2x_8_15_L , RGB2x_8_16_L , RGB2x_8_32_L }, -{ 0, RGB2x_15_15_L, RGB2x_15_16_L, RGB2x_15_32_L}, -{ 0, RGB2x_16_15_L, RGB2x_16_16_L, RGB2x_16_32_L}, -{ 0, RGB2x_32_15_L, RGB2x_32_16_L, RGB2x_32_32_L}, -{ 0, RGB2x_9_15_L , RGB2x_9_16_L , RGB2x_9_32_L } -},{ -{ 0, RGB2x_8_15_R , RGB2x_8_16_R , RGB2x_8_32_R }, -{ 0, RGB2x_15_15_R, RGB2x_15_16_R, RGB2x_15_32_R}, -{ 0, RGB2x_16_15_R, RGB2x_16_16_R, RGB2x_16_32_R}, -{ 0, RGB2x_32_15_R, RGB2x_32_16_R, RGB2x_32_32_R}, -{ 0, RGB2x_9_15_R , RGB2x_9_16_R , RGB2x_9_32_R } -}}; - -ScalerSimpleBlock_t ScaleRGB3x = { - "RGB3x", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 3,3,{ -{ 0, RGB3x_8_15_L , RGB3x_8_16_L , RGB3x_8_32_L }, -{ 0, RGB3x_15_15_L, RGB3x_15_16_L, RGB3x_15_32_L}, -{ 0, RGB3x_16_15_L, RGB3x_16_16_L, RGB3x_16_32_L}, -{ 0, RGB3x_32_15_L, RGB3x_32_16_L, RGB3x_32_32_L}, -{ 0, RGB3x_9_15_L , RGB3x_9_16_L , RGB3x_9_32_L } -},{ -{ 0, RGB3x_8_15_R , RGB3x_8_16_R , RGB3x_8_32_R }, -{ 0, RGB3x_15_15_R, RGB3x_15_16_R, RGB3x_15_32_R}, -{ 0, RGB3x_16_15_R, RGB3x_16_16_R, RGB3x_16_32_R}, -{ 0, RGB3x_32_15_R, RGB3x_32_16_R, RGB3x_32_32_R}, -{ 0, RGB3x_9_15_R , RGB3x_9_16_R , RGB3x_9_32_R } -}}; -#endif - - -/* Complex scalers */ - -#if RENDER_USE_ADVANCED_SCALERS>2 -ScalerComplexBlock_t ScaleAdvMame2x ={ - "AdvMame2x", - GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 2,2, -{ AdvMame2x_8_L,AdvMame2x_16_L,AdvMame2x_16_L,AdvMame2x_32_L}, -{ AdvMame2x_8_R,AdvMame2x_16_R,AdvMame2x_16_R,AdvMame2x_32_R} -}; - -ScalerComplexBlock_t ScaleAdvMame3x = { - "AdvMame3x", - GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 3,3, -{ AdvMame3x_8_L,AdvMame3x_16_L,AdvMame3x_16_L,AdvMame3x_32_L}, -{ AdvMame3x_8_R,AdvMame3x_16_R,AdvMame3x_16_R,AdvMame3x_32_R} -}; - -/* These need specific 15bpp versions */ -ScalerComplexBlock_t ScaleHQ2x ={ - "HQ2x", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2, -{ 0,HQ2x_16_L,HQ2x_16_L,HQ2x_32_L}, -{ 0,HQ2x_16_R,HQ2x_16_R,HQ2x_32_R} -}; - -ScalerComplexBlock_t ScaleHQ3x ={ - "HQ3x", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 3,3, -{ 0,HQ3x_16_L,HQ3x_16_L,HQ3x_32_L}, -{ 0,HQ3x_16_R,HQ3x_16_R,HQ3x_32_R} -}; - -ScalerComplexBlock_t ScaleSuper2xSaI ={ - "Super2xSaI", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2, -{ 0,Super2xSaI_16_L,Super2xSaI_16_L,Super2xSaI_32_L}, -{ 0,Super2xSaI_16_R,Super2xSaI_16_R,Super2xSaI_32_R} -}; - -ScalerComplexBlock_t Scale2xSaI ={ - "2xSaI", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2, -{ 0,_2xSaI_16_L,_2xSaI_16_L,_2xSaI_32_L}, -{ 0,_2xSaI_16_R,_2xSaI_16_R,_2xSaI_32_R} -}; - -ScalerComplexBlock_t ScaleSuperEagle ={ - "SuperEagle", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2, -{ 0,SuperEagle_16_L,SuperEagle_16_L,SuperEagle_32_L}, -{ 0,SuperEagle_16_R,SuperEagle_16_R,SuperEagle_32_R} -}; - -ScalerComplexBlock_t ScaleAdvInterp2x = { - "AdvInterp2x", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2, -{ 0,AdvInterp2x_15_L,AdvInterp2x_16_L,AdvInterp2x_32_L}, -{ 0,AdvInterp2x_15_R,AdvInterp2x_16_R,AdvInterp2x_32_R} -}; - -ScalerComplexBlock_t ScaleAdvInterp3x = { - "AdvInterp3x", - GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 3,3, -{ 0,AdvInterp3x_15_L,AdvInterp3x_16_L,AdvInterp3x_32_L}, -{ 0,AdvInterp3x_15_R,AdvInterp3x_16_R,AdvInterp3x_32_R} -}; - -#endif diff --git a/src/gui/render_scalers.h b/src/gui/render_scalers.h deleted file mode 100644 index e9d38f0..0000000 --- a/src/gui/render_scalers.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _RENDER_SCALERS_H -#define _RENDER_SCALERS_H - -//#include "render.h" -#include "video.h" -#if RENDER_USE_ADVANCED_SCALERS>0 -#define SCALER_MAXWIDTH 1280 -#define SCALER_MAXHEIGHT 1024 -#else -// reduced to save some memory -#define SCALER_MAXWIDTH 800 -#define SCALER_MAXHEIGHT 600 -#endif - -#if RENDER_USE_ADVANCED_SCALERS>1 -#define SCALER_COMPLEXWIDTH 800 -#define SCALER_COMPLEXHEIGHT 600 -#endif - -#define SCALER_BLOCKSIZE 16 - -typedef enum { - scalerMode8, scalerMode15, scalerMode16, scalerMode32 -} scalerMode_t; - -typedef enum scalerOperation { - scalerOpNormal, -#if RENDER_USE_ADVANCED_SCALERS>2 - scalerOpAdvMame, - scalerOpAdvInterp, - scalerOpHQ, - scalerOpSaI, - scalerOpSuperSaI, - scalerOpSuperEagle, -#endif -#if RENDER_USE_ADVANCED_SCALERS>0 - scalerOpTV, - scalerOpRGB, - scalerOpScan, -#endif - scalerLast -} scalerOperation_t; - -typedef void (*ScalerLineHandler_t)(const void *src); -typedef void (*ScalerComplexHandler_t)(void); - -extern Bit8u Scaler_Aspect[]; -extern Bit8u diff_table[]; -extern Bitu Scaler_ChangedLineIndex; -extern Bit16u Scaler_ChangedLines[]; -#if RENDER_USE_ADVANCED_SCALERS>1 -/* Not entirely happy about those +2's since they make a non power of 2, with muls instead of shift */ -typedef Bit8u scalerChangeCache_t [SCALER_COMPLEXHEIGHT][SCALER_COMPLEXWIDTH / SCALER_BLOCKSIZE] ; -typedef union { - Bit32u b32 [SCALER_COMPLEXHEIGHT] [SCALER_COMPLEXWIDTH]; - Bit16u b16 [SCALER_COMPLEXHEIGHT] [SCALER_COMPLEXWIDTH]; - Bit8u b8 [SCALER_COMPLEXHEIGHT] [SCALER_COMPLEXWIDTH]; -} scalerFrameCache_t; -#endif -typedef union { - Bit32u b32 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH]; - Bit16u b16 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH]; - Bit8u b8 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH]; -} scalerSourceCache_t; -extern scalerSourceCache_t scalerSourceCache; -#if RENDER_USE_ADVANCED_SCALERS>1 -extern scalerChangeCache_t scalerChangeCache; -#endif -typedef ScalerLineHandler_t ScalerLineBlock_t[5][4]; - -typedef struct { - const char *name; - Bitu gfxFlags; - Bitu xscale,yscale; - ScalerComplexHandler_t Linear[4]; - ScalerComplexHandler_t Random[4]; -} ScalerComplexBlock_t; - -typedef struct { - const char *name; - Bitu gfxFlags; - Bitu xscale,yscale; - ScalerLineBlock_t Linear; - ScalerLineBlock_t Random; -} ScalerSimpleBlock_t; - - -#define SCALE_LEFT 0x1 -#define SCALE_RIGHT 0x2 -#define SCALE_FULL 0x4 - -/* Simple scalers */ -extern ScalerSimpleBlock_t ScaleNormal1x; -extern ScalerSimpleBlock_t ScaleNormalDw; -extern ScalerSimpleBlock_t ScaleNormalDh; -extern ScalerSimpleBlock_t ScaleNormal2x; -extern ScalerSimpleBlock_t ScaleNormal3x; -#if RENDER_USE_ADVANCED_SCALERS>0 -extern ScalerSimpleBlock_t ScaleTV2x; -extern ScalerSimpleBlock_t ScaleTV3x; -extern ScalerSimpleBlock_t ScaleRGB2x; -extern ScalerSimpleBlock_t ScaleRGB3x; -extern ScalerSimpleBlock_t ScaleScan2x; -extern ScalerSimpleBlock_t ScaleScan3x; -#endif -/* Complex scalers */ -#if RENDER_USE_ADVANCED_SCALERS>2 -extern ScalerComplexBlock_t ScaleHQ2x; -extern ScalerComplexBlock_t ScaleHQ3x; -extern ScalerComplexBlock_t Scale2xSaI; -extern ScalerComplexBlock_t ScaleSuper2xSaI; -extern ScalerComplexBlock_t ScaleSuperEagle; -extern ScalerComplexBlock_t ScaleAdvMame2x; -extern ScalerComplexBlock_t ScaleAdvMame3x; -extern ScalerComplexBlock_t ScaleAdvInterp2x; -extern ScalerComplexBlock_t ScaleAdvInterp3x; -#endif -#if RENDER_USE_ADVANCED_SCALERS>1 -extern ScalerLineBlock_t ScalerCache; -#endif -#endif diff --git a/src/gui/render_simple.h b/src/gui/render_simple.h deleted file mode 100644 index 965d669..0000000 --- a/src/gui/render_simple.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: render_simple.h,v 1.6 2008/09/07 10:55:15 c2woody Exp $ */ - -#if defined (SCALERLINEAR) -static void conc4d(SCALERNAME,SBPP,DBPP,L)(const void *s) { -#else -static void conc4d(SCALERNAME,SBPP,DBPP,R)(const void *s) { -#endif -#ifdef RENDER_NULL_INPUT - if (!s) { - render.scale.cacheRead += render.scale.cachePitch; -#if defined(SCALERLINEAR) - Bitu skipLines = SCALERHEIGHT; -#else - Bitu skipLines = Scaler_Aspect[ render.scale.outLine++ ]; -#endif - ScalerAddLines( 0, skipLines ); - return; - } -#endif - /* Clear the complete line marker */ - Bitu hadChange = 0; - const SRCTYPE *src = (SRCTYPE*)s; - SRCTYPE *cache = (SRCTYPE*)(render.scale.cacheRead); - render.scale.cacheRead += render.scale.cachePitch; - PTYPE * line0=(PTYPE *)(render.scale.outWrite); -#if (SBPP == 9) - for (Bits x=render.src.width;x>0;) { - if (*(Bit32u const*)src == *(Bit32u*)cache && !( - render.pal.modified[src[0]] | - render.pal.modified[src[1]] | - render.pal.modified[src[2]] | - render.pal.modified[src[3]] )) { - x-=4; - src+=4; - cache+=4; - line0+=4*SCALERWIDTH; -#else - for (Bits x=render.src.width;x>0;) { - if (*(Bitu const*)src == *(Bitu*)cache) { - x-=(sizeof(Bitu)/sizeof(SRCTYPE)); - src+=(sizeof(Bitu)/sizeof(SRCTYPE)); - cache+=(sizeof(Bitu)/sizeof(SRCTYPE)); - line0+=(sizeof(Bitu)/sizeof(SRCTYPE))*SCALERWIDTH; -#endif - } else { -#if defined(SCALERLINEAR) -#if (SCALERHEIGHT > 1) - PTYPE *line1 = WC[0]; -#endif -#if (SCALERHEIGHT > 2) - PTYPE *line2 = WC[1]; -#endif -#else -#if (SCALERHEIGHT > 1) - PTYPE *line1 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch); -#endif -#if (SCALERHEIGHT > 2) - PTYPE *line2 = (PTYPE *)(((Bit8u*)line0)+ render.scale.outPitch * 2); -#endif -#endif //defined(SCALERLINEAR) - hadChange = 1; - for (Bitu i = x > 32 ? 32 : x;i>0;i--,x--) { - const SRCTYPE S = *src; - *cache = S; - src++;cache++; - const PTYPE P = PMAKE(S); - SCALERFUNC; - line0 += SCALERWIDTH; -#if (SCALERHEIGHT > 1) - line1 += SCALERWIDTH; -#endif -#if (SCALERHEIGHT > 2) - line2 += SCALERWIDTH; -#endif - } -#if defined(SCALERLINEAR) -#if (SCALERHEIGHT > 1) - Bitu copyLen = (Bitu)((Bit8u*)line1 - (Bit8u*)WC[0]); - BituMove(((Bit8u*)line0)-copyLen+render.scale.outPitch ,WC[0], copyLen ); -#endif -#if (SCALERHEIGHT > 2) - BituMove(((Bit8u*)line0)-copyLen+render.scale.outPitch*2,WC[1], copyLen ); -#endif -#endif //defined(SCALERLINEAR) - } - } -#if defined(SCALERLINEAR) - Bitu scaleLines = SCALERHEIGHT; -#else - Bitu scaleLines = Scaler_Aspect[ render.scale.outLine++ ]; - if ( scaleLines - SCALERHEIGHT && hadChange ) { - BituMove( render.scale.outWrite + render.scale.outPitch * SCALERHEIGHT, - render.scale.outWrite + render.scale.outPitch * (SCALERHEIGHT-1), - render.src.width * SCALERWIDTH * PSIZE); - } -#endif - ScalerAddLines( hadChange, scaleLines ); -} - -#if !defined(SCALERLINEAR) -#define SCALERLINEAR 1 -#include "render_simple.h" -#undef SCALERLINEAR -#endif diff --git a/src/gui/render_templates.h b/src/gui/render_templates.h deleted file mode 100644 index 4475b41..0000000 --- a/src/gui/render_templates.h +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#if DBPP == 8 -#define PSIZE 1 -#define PTYPE Bit8u -#define WC scalerWriteCache.b8 -//#define FC scalerFrameCache.b8 -#define FC (*(scalerFrameCache_t*)(&scalerSourceCache.b32[400][0])).b8 -#define redMask 0 -#define greenMask 0 -#define blueMask 0 -#define redBits 0 -#define greenBits 0 -#define blueBits 0 -#define redShift 0 -#define greenShift 0 -#define blueShift 0 -#elif DBPP == 15 || DBPP == 16 -#define PSIZE 2 -#define PTYPE Bit16u -#define WC scalerWriteCache.b16 -//#define FC scalerFrameCache.b16 -#define FC (*(scalerFrameCache_t*)(&scalerSourceCache.b32[400][0])).b16 -#if DBPP == 15 -#define redMask 0x7C00 -#define greenMask 0x03E0 -#define blueMask 0x001F -#define redBits 5 -#define greenBits 5 -#define blueBits 5 -#define redShift 10 -#define greenShift 5 -#define blueShift 0 -#elif DBPP == 16 -#define redMask 0xF800 -#define greenMask 0x07E0 -#define blueMask 0x001F -#define redBits 5 -#define greenBits 6 -#define blueBits 5 -#define redShift 11 -#define greenShift 5 -#define blueShift 0 -#endif -#elif DBPP == 32 -#define PSIZE 4 -#define PTYPE Bit32u -#define WC scalerWriteCache.b32 -//#define FC scalerFrameCache.b32 -#define FC (*(scalerFrameCache_t*)(&scalerSourceCache.b32[400][0])).b32 -#define redMask 0xff0000 -#define greenMask 0x00ff00 -#define blueMask 0x0000ff -#define redBits 8 -#define greenBits 8 -#define blueBits 8 -#define redShift 16 -#define greenShift 8 -#define blueShift 0 -#endif - -#define redblueMask (redMask | blueMask) - - -#if SBPP == 8 || SBPP == 9 -#define SC scalerSourceCache.b8 -#if DBPP == 8 -#define PMAKE(_VAL) (_VAL) -#elif DBPP == 15 -#define PMAKE(_VAL) render.pal.lut.b16[_VAL] -#elif DBPP == 16 -#define PMAKE(_VAL) render.pal.lut.b16[_VAL] -#elif DBPP == 32 -#define PMAKE(_VAL) render.pal.lut.b32[_VAL] -#endif -#define SRCTYPE Bit8u -#endif - -#if SBPP == 15 -#define SC scalerSourceCache.b16 -#if DBPP == 15 -#define PMAKE(_VAL) (_VAL) -#elif DBPP == 16 -#define PMAKE(_VAL) (((_VAL) & 31) | ((_VAL) & ~31) << 1) -#elif DBPP == 32 -#define PMAKE(_VAL) (((_VAL&(31<<10))<<9)|((_VAL&(31<<5))<<6)|((_VAL&31)<<3)) -#endif -#define SRCTYPE Bit16u -#endif - -#if SBPP == 16 -#define SC scalerSourceCache.b16 -#if DBPP == 15 -#define PMAKE(_VAL) (((_VAL&~31)>>1)|(_VAL&31)) -#elif DBPP == 16 -#define PMAKE(_VAL) (_VAL) -#elif DBPP == 32 -#define PMAKE(_VAL) (((_VAL&(31<<11))<<8)|((_VAL&(63<<5))<<5)|((_VAL&31)<<3)) -#endif -#define SRCTYPE Bit16u -#endif - -#if SBPP == 32 -#define SC scalerSourceCache.b32 -#if DBPP == 15 -#define PMAKE(_VAL) (PTYPE)(((_VAL&(31<<19))>>9)|((_VAL&(31<<11))>>6)|((_VAL&(31<<3))>>3)) -#elif DBPP == 16 -#define PMAKE(_VAL) (PTYPE)(((_VAL&(31<<19))>>8)|((_VAL&(63<<10))>>4)|((_VAL&(31<<3))>>3)) -#elif DBPP == 32 -#define PMAKE(_VAL) (_VAL) -#endif -#define SRCTYPE Bit32u -#endif - -// C0 C1 C2 D3 -// C3 C4 C5 D4 -// C6 C7 C8 D5 -// D0 D1 D2 D6 - -#define C0 fc[-1 - SCALER_COMPLEXWIDTH] -#define C1 fc[+0 - SCALER_COMPLEXWIDTH] -#define C2 fc[+1 - SCALER_COMPLEXWIDTH] -#define C3 fc[-1 ] -#define C4 fc[+0 ] -#define C5 fc[+1 ] -#define C6 fc[-1 + SCALER_COMPLEXWIDTH] -#define C7 fc[+0 + SCALER_COMPLEXWIDTH] -#define C8 fc[+1 + SCALER_COMPLEXWIDTH] - -#define D0 fc[-1 + 2*SCALER_COMPLEXWIDTH] -#define D1 fc[+0 + 2*SCALER_COMPLEXWIDTH] -#define D2 fc[+1 + 2*SCALER_COMPLEXWIDTH] -#define D3 fc[+2 - SCALER_COMPLEXWIDTH] -#define D4 fc[+2] -#define D5 fc[+2 + SCALER_COMPLEXWIDTH] -#define D6 fc[+2 + 2*SCALER_COMPLEXWIDTH] - - -#if RENDER_USE_ADVANCED_SCALERS>1 -static void conc3d(Cache,SBPP,DBPP) (const void * s) { -#ifdef RENDER_NULL_INPUT - if (!s) { - render.scale.cacheRead += render.scale.cachePitch; - render.scale.inLine++; - render.scale.complexHandler(); - return; - } -#endif - const SRCTYPE * src = (SRCTYPE*)s; - PTYPE *fc= &FC[render.scale.inLine+1][1]; - SRCTYPE *sc = (SRCTYPE*)(render.scale.cacheRead); - render.scale.cacheRead += render.scale.cachePitch; - Bitu b; - bool hadChange = false; - /* This should also copy the surrounding pixels but it looks nice enough without */ - for (b=0;b 8) - -#if RENDER_USE_ADVANCED_SCALERS>0 - -#define SCALERNAME TV2x -#define SCALERWIDTH 2 -#define SCALERHEIGHT 2 -#define SCALERFUNC \ -{ \ - Bitu halfpixel=(((P & redblueMask) * 5) >> 3) & redblueMask; \ - halfpixel|=(((P & greenMask) * 5) >> 3) & greenMask; \ - line0[0]=P; \ - line0[1]=P; \ - line1[0]=halfpixel; \ - line1[1]=halfpixel; \ -} -#include "render_simple.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#define SCALERNAME TV3x -#define SCALERWIDTH 3 -#define SCALERHEIGHT 3 -#define SCALERFUNC \ -{ \ - Bitu halfpixel=(((P & redblueMask) * 5) >> 3) & redblueMask; \ - halfpixel|=(((P & greenMask) * 5) >> 3) & greenMask; \ - line0[0]=P; \ - line0[1]=P; \ - line0[2]=P; \ - line1[0]=halfpixel; \ - line1[1]=halfpixel; \ - line1[2]=halfpixel; \ - halfpixel=(((P & redblueMask) * 5) >> 4) & redblueMask; \ - halfpixel|=(((P & greenMask) * 5) >> 4) & greenMask; \ - line2[0]=halfpixel; \ - line2[1]=halfpixel; \ - line2[2]=halfpixel; \ -} -#include "render_simple.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#define SCALERNAME RGB2x -#define SCALERWIDTH 2 -#define SCALERHEIGHT 2 -#define SCALERFUNC \ - line0[0]=P & redMask; \ - line0[1]=P & greenMask; \ - line1[0]=P & blueMask; \ - line1[1]=P; -#include "render_simple.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#define SCALERNAME RGB3x -#define SCALERWIDTH 3 -#define SCALERHEIGHT 3 -#define SCALERFUNC \ - line0[0]=P; \ - line0[1]=P & greenMask; \ - line0[2]=P & blueMask; \ - line1[0]=P & blueMask; \ - line1[1]=P; \ - line1[2]=P & redMask; \ - line2[0]=P & redMask; \ - line2[1]=P & greenMask; \ - line2[2]=P; -#include "render_simple.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#define SCALERNAME Scan2x -#define SCALERWIDTH 2 -#define SCALERHEIGHT 2 -#define SCALERFUNC \ - line0[0]=P; \ - line0[1]=P; \ - line1[0]=0; \ - line1[1]=0; -#include "render_simple.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#define SCALERNAME Scan3x -#define SCALERWIDTH 3 -#define SCALERHEIGHT 3 -#define SCALERFUNC \ - line0[0]=P; \ - line0[1]=P; \ - line0[2]=P; \ - line1[0]=0; \ - line1[1]=0; \ - line1[2]=0; \ - line2[0]=0; \ - line2[1]=0; \ - line2[2]=0; -#include "render_simple.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#endif //#if RENDER_USE_ADVANCED_SCALERS>0 - -#endif //#if (DBPP > 8) - -/* Complex scalers */ - -#if RENDER_USE_ADVANCED_SCALERS>2 - -#if (SBPP == DBPP) - - -#if (DBPP > 8) - -#include "render_templates_hq.h" - -#define SCALERNAME HQ2x -#define SCALERWIDTH 2 -#define SCALERHEIGHT 2 -#include "render_templates_hq2x.h" -#define SCALERFUNC conc2d(Hq2x,SBPP)(line0, line1, fc) -#include "render_loops.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#define SCALERNAME HQ3x -#define SCALERWIDTH 3 -#define SCALERHEIGHT 3 -#include "render_templates_hq3x.h" -#define SCALERFUNC conc2d(Hq3x,SBPP)(line0, line1, line2, fc) -#include "render_loops.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#include "render_templates_sai.h" - -#define SCALERNAME Super2xSaI -#define SCALERWIDTH 2 -#define SCALERHEIGHT 2 -#define SCALERFUNC conc2d(Super2xSaI,SBPP)(line0, line1, fc) -#include "render_loops.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#define SCALERNAME SuperEagle -#define SCALERWIDTH 2 -#define SCALERHEIGHT 2 -#define SCALERFUNC conc2d(SuperEagle,SBPP)(line0, line1, fc) -#include "render_loops.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#define SCALERNAME _2xSaI -#define SCALERWIDTH 2 -#define SCALERHEIGHT 2 -#define SCALERFUNC conc2d(_2xSaI,SBPP)(line0, line1, fc) -#include "render_loops.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#define SCALERNAME AdvInterp2x -#define SCALERWIDTH 2 -#define SCALERHEIGHT 2 -#define SCALERFUNC \ - if (C1 != C7 && C3 != C5) { \ - line0[0] = C3 == C1 ? interp_w2(C3,C4,5U,3U) : C4; \ - line0[1] = C1 == C5 ? interp_w2(C5,C4,5U,3U) : C4; \ - line1[0] = C3 == C7 ? interp_w2(C3,C4,5U,3U) : C4; \ - line1[1] = C7 == C5 ? interp_w2(C5,C4,5U,3U) : C4; \ - } else { \ - line0[0] = line0[1] = C4; \ - line1[0] = line1[1] = C4; \ - } -#include "render_loops.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -//TODO, come up with something better for this one -#define SCALERNAME AdvInterp3x -#define SCALERWIDTH 3 -#define SCALERHEIGHT 3 -#define SCALERFUNC \ - if ((C1 != C7) && (C3 != C5)) { \ - line0[0] = C3 == C1 ? interp_w2(C3,C4,5U,3U) : C4; \ - line0[1] = (C3 == C1 && C4 != C2) || (C5 == C1 && C4 != C0) ? C1 : C4; \ - line0[2] = C5 == C1 ? interp_w2(C5,C4,5U,3U) : C4; \ - line1[0] = (C3 == C1 && C4 != C6) || (C3 == C7 && C4 != C0) ? C3 : C4; \ - line1[1] = C4; \ - line1[2] = (C5 == C1 && C4 != C8) || (C5 == C7 && C4 != C2) ? C5 : C4; \ - line2[0] = C3 == C7 ? interp_w2(C3,C4,5U,3U) : C4; \ - line2[1] = (C3 == C7 && C4 != C8) || (C5 == C7 && C4 != C6) ? C7 : C4; \ - line2[2] = C5 == C7 ? interp_w2(C5,C4,5U,3U) : C4; \ - } else { \ - line0[0] = line0[1] = line0[2] = C4; \ - line1[0] = line1[1] = line1[2] = C4; \ - line2[0] = line2[1] = line2[2] = C4; \ - } -#include "render_loops.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#endif // #if (DBPP > 8) - -#define SCALERNAME AdvMame2x -#define SCALERWIDTH 2 -#define SCALERHEIGHT 2 -#define SCALERFUNC \ - if (C1 != C7 && C3 != C5) { \ - line0[0] = C3 == C1 ? C3 : C4; \ - line0[1] = C1 == C5 ? C5 : C4; \ - line1[0] = C3 == C7 ? C3 : C4; \ - line1[1] = C7 == C5 ? C5 : C4; \ - } else { \ - line0[0] = line0[1] = C4; \ - line1[0] = line1[1] = C4; \ - } -#include "render_loops.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - -#define SCALERNAME AdvMame3x -#define SCALERWIDTH 3 -#define SCALERHEIGHT 3 -#define SCALERFUNC \ - if ((C1 != C7) && (C3 != C5)) { \ - line0[0] = C3 == C1 ? C3 : C4; \ - line0[1] = (C3 == C1 && C4 != C2) || (C5 == C1 && C4 != C0) ? C1 : C4; \ - line0[2] = C5 == C1 ? C5 : C4; \ - line1[0] = (C3 == C1 && C4 != C6) || (C3 == C7 && C4 != C0) ? C3 : C4; \ - line1[1] = C4; \ - line1[2] = (C5 == C1 && C4 != C8) || (C5 == C7 && C4 != C2) ? C5 : C4; \ - line2[0] = C3 == C7 ? C3 : C4; \ - line2[1] = (C3 == C7 && C4 != C8) || (C5 == C7 && C4 != C6) ? C7 : C4; \ - line2[2] = C5 == C7 ? C5 : C4; \ - } else { \ - line0[0] = line0[1] = line0[2] = C4; \ - line1[0] = line1[1] = line1[2] = C4; \ - line2[0] = line2[1] = line2[2] = C4; \ - } - -#include "render_loops.h" -#undef SCALERNAME -#undef SCALERWIDTH -#undef SCALERHEIGHT -#undef SCALERFUNC - - -#endif // (SBPP == DBPP) && !defined (CACHEWITHPAL) - -#endif // #if RENDER_USE_ADVANCED_SCALERS>2 - -#undef PSIZE -#undef PTYPE -#undef PMAKE -#undef WC -#undef LC -#undef FC -#undef SC -#undef redMask -#undef greenMask -#undef blueMask -#undef redblueMask -#undef redBits -#undef greenBits -#undef blueBits -#undef redShift -#undef greenShift -#undef blueShift -#undef SRCTYPE diff --git a/src/gui/render_templates_hq.h b/src/gui/render_templates_hq.h deleted file mode 100644 index 14f1422..0000000 --- a/src/gui/render_templates_hq.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * The HQ3x high quality 3x graphics filter. - * Original author Maxim Stepin (see http://www.hiend3d.com/hq3x.html). - * Adapted for DOSBox from ScummVM and HiEnd3D code by Kronuz. - */ - -#include - -#ifndef RENDER_TEMPLATES_HQNX_TABLE_H -#define RENDER_TEMPLATES_HQNX_TABLE_H - -static Bit32u *_RGBtoYUV = 0; -static inline bool diffYUV(Bit32u yuv1, Bit32u yuv2) -{ - static const Bit32u Ymask = 0x00FF0000; - static const Bit32u Umask = 0x0000FF00; - static const Bit32u Vmask = 0x000000FF; - static const Bit32u trY = 0x00300000; - static const Bit32u trU = 0x00000700; - static const Bit32u trV = 0x00000006; - - Bit32u diff; - Bit32u mask; - - diff = ((yuv1 & Ymask) - (yuv2 & Ymask)); - mask = diff >> 31; // -1 if value < 0, 0 otherwise - diff = (diff ^ mask) - mask; //-1: ~value + 1; 0: value - if (diff > trY) return true; - - diff = ((yuv1 & Umask) - (yuv2 & Umask)); - mask = diff >> 31; // -1 if value < 0, 0 otherwise - diff = (diff ^ mask) - mask; //-1: ~value + 1; 0: value - if (diff > trU) return true; - - diff = ((yuv1 & Vmask) - (yuv2 & Vmask)); - mask = diff >> 31; // -1 if value < 0, 0 otherwise - diff = (diff ^ mask) - mask; //-1: ~value + 1; 0: value - if (diff > trV) return true; - - return false; -} - -#endif - -static inline void conc2d(InitLUTs,SBPP)(void) -{ - int r, g, b; - int Y, u, v; - - _RGBtoYUV = (Bit32u *)malloc(65536 * sizeof(Bit32u)); - - for (int color = 0; color < 65536; ++color) { -#if SBPP == 32 - r = ((color & 0xF800) >> 11) << (8 - 5); - g = ((color & 0x07E0) >> 5) << (8 - 6); - b = ((color & 0x001F) >> 0) << (8 - 5); -#else - r = ((color & redMask) >> redShift) << (8 - redBits); - g = ((color & greenMask) >> greenShift) << (8 - greenBits); - b = ((color & blueMask) >> blueShift) << (8 - blueBits); -#endif - Y = (r + g + b) >> 2; - u = 128 + ((r - b) >> 2); - v = 128 + ((-r + 2 * g - b) >> 3); - _RGBtoYUV[color] = (Y << 16) | (u << 8) | v; - } -} diff --git a/src/gui/render_templates_hq2x.h b/src/gui/render_templates_hq2x.h deleted file mode 100644 index cf4573d..0000000 --- a/src/gui/render_templates_hq2x.h +++ /dev/null @@ -1,1896 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * The HQ2x high quality 2x graphics filter. - * Original author Maxim Stepin (see http://www.hiend3d.com/hq2x.html). - * Adapted for DOSBox from ScummVM and HiEnd3D code by Kronuz. - */ - -#ifndef RENDER_TEMPLATES_HQ2X_TABLE_H -#define RENDER_TEMPLATES_HQ2X_TABLE_H - -#define PIXEL00_0 line0[0] = C4; -#define PIXEL00_10 line0[0] = interp_w2(C4,C0,3U,1U); -#define PIXEL00_11 line0[0] = interp_w2(C4,C3,3U,1U); -#define PIXEL00_12 line0[0] = interp_w2(C4,C1,3U,1U); -#define PIXEL00_20 line0[0] = interp_w3(C4,C3,C1,2U,1U,1U); -#define PIXEL00_21 line0[0] = interp_w3(C4,C0,C1,2U,1U,1U); -#define PIXEL00_22 line0[0] = interp_w3(C4,C0,C3,2U,1U,1U); -#define PIXEL00_60 line0[0] = interp_w3(C4,C1,C3,5U,2U,1U); -#define PIXEL00_61 line0[0] = interp_w3(C4,C3,C1,5U,2U,1U); -#define PIXEL00_70 line0[0] = interp_w3(C4,C3,C1,6U,1U,1U); -#define PIXEL00_90 line0[0] = interp_w3(C4,C3,C1,2U,3U,3U); -#define PIXEL00_100 line0[0] = interp_w3(C4,C3,C1,14U,1U,1U); - -#define PIXEL01_0 line0[1] = C4; -#define PIXEL01_10 line0[1] = interp_w2(C4,C2,3U,1U); -#define PIXEL01_11 line0[1] = interp_w2(C4,C1,3U,1U); -#define PIXEL01_12 line0[1] = interp_w2(C4,C5,3U,1U); -#define PIXEL01_20 line0[1] = interp_w3(C4,C1,C5,2U,1U,1U); -#define PIXEL01_21 line0[1] = interp_w3(C4,C2,C5,2U,1U,1U); -#define PIXEL01_22 line0[1] = interp_w3(C4,C2,C1,2U,1U,1U); -#define PIXEL01_60 line0[1] = interp_w3(C4,C5,C1,5U,2U,1U); -#define PIXEL01_61 line0[1] = interp_w3(C4,C1,C5,5U,2U,1U); -#define PIXEL01_70 line0[1] = interp_w3(C4,C1,C5,6U,1U,1U); -#define PIXEL01_90 line0[1] = interp_w3(C4,C1,C5,2U,3U,3U); -#define PIXEL01_100 line0[1] = interp_w3(C4,C1,C5,14U,1U,1U); - -#define PIXEL10_0 line1[0] = C4; -#define PIXEL10_10 line1[0] = interp_w2(C4,C6,3U,1U); -#define PIXEL10_11 line1[0] = interp_w2(C4,C7,3U,1U); -#define PIXEL10_12 line1[0] = interp_w2(C4,C3,3U,1U); -#define PIXEL10_20 line1[0] = interp_w3(C4,C7,C3,2U,1U,1U); -#define PIXEL10_21 line1[0] = interp_w3(C4,C6,C3,2U,1U,1U); -#define PIXEL10_22 line1[0] = interp_w3(C4,C6,C7,2U,1U,1U); -#define PIXEL10_60 line1[0] = interp_w3(C4,C3,C7,5U,2U,1U); -#define PIXEL10_61 line1[0] = interp_w3(C4,C7,C3,5U,2U,1U); -#define PIXEL10_70 line1[0] = interp_w3(C4,C7,C3,6U,1U,1U); -#define PIXEL10_90 line1[0] = interp_w3(C4,C7,C3,2U,3U,3U); -#define PIXEL10_100 line1[0] = interp_w3(C4,C7,C3,14U,1U,1U); - -#define PIXEL11_0 line1[1] = C4; -#define PIXEL11_10 line1[1] = interp_w2(C4,C8,3U,1U); -#define PIXEL11_11 line1[1] = interp_w2(C4,C5,3U,1U); -#define PIXEL11_12 line1[1] = interp_w2(C4,C7,3U,1U); -#define PIXEL11_20 line1[1] = interp_w3(C4,C5,C7,2U,1U,1U); -#define PIXEL11_21 line1[1] = interp_w3(C4,C8,C7,2U,1U,1U); -#define PIXEL11_22 line1[1] = interp_w3(C4,C8,C5,2U,1U,1U); -#define PIXEL11_60 line1[1] = interp_w3(C4,C7,C5,5U,2U,1U); -#define PIXEL11_61 line1[1] = interp_w3(C4,C5,C7,5U,2U,1U); -#define PIXEL11_70 line1[1] = interp_w3(C4,C5,C7,6U,1U,1U); -#define PIXEL11_90 line1[1] = interp_w3(C4,C5,C7,2U,3U,3U); -#define PIXEL11_100 line1[1] = interp_w3(C4,C5,C7,14U,1U,1U); - -#endif - -#if SBPP == 32 -#define RGBtoYUV(c) _RGBtoYUV[((c & 0xf80000) >> 8) | ((c & 0x00fc00) >> 5) | ((c & 0x0000f8) >> 3)] -#else -#define RGBtoYUV(c) _RGBtoYUV[c] -#endif - -inline void conc2d(Hq2x,SBPP)(PTYPE * line0, PTYPE * line1, const PTYPE * fc) -{ - if (_RGBtoYUV == 0) conc2d(InitLUTs,SBPP)(); - - Bit32u pattern = 0; - const Bit32u YUV4 = RGBtoYUV(C4); - if (C4 != C0 && diffYUV(YUV4, RGBtoYUV(C0))) pattern |= 0x0001; - if (C4 != C1 && diffYUV(YUV4, RGBtoYUV(C1))) pattern |= 0x0002; - if (C4 != C2 && diffYUV(YUV4, RGBtoYUV(C2))) pattern |= 0x0004; - if (C4 != C3 && diffYUV(YUV4, RGBtoYUV(C3))) pattern |= 0x0008; - if (C4 != C5 && diffYUV(YUV4, RGBtoYUV(C5))) pattern |= 0x0010; - if (C4 != C6 && diffYUV(YUV4, RGBtoYUV(C6))) pattern |= 0x0020; - if (C4 != C7 && diffYUV(YUV4, RGBtoYUV(C7))) pattern |= 0x0040; - if (C4 != C8 && diffYUV(YUV4, RGBtoYUV(C8))) pattern |= 0x0080; - - switch (pattern) { - case 0: - case 1: - case 4: - case 32: - case 128: - case 5: - case 132: - case 160: - case 33: - case 129: - case 36: - case 133: - case 164: - case 161: - case 37: - case 165: - PIXEL00_20 - PIXEL01_20 - PIXEL10_20 - PIXEL11_20 - break; - case 2: - case 34: - case 130: - case 162: - PIXEL00_22 - PIXEL01_21 - PIXEL10_20 - PIXEL11_20 - break; - case 16: - case 17: - case 48: - case 49: - PIXEL00_20 - PIXEL01_22 - PIXEL10_20 - PIXEL11_21 - break; - case 64: - case 65: - case 68: - case 69: - PIXEL00_20 - PIXEL01_20 - PIXEL10_21 - PIXEL11_22 - break; - case 8: - case 12: - case 136: - case 140: - PIXEL00_21 - PIXEL01_20 - PIXEL10_22 - PIXEL11_20 - break; - case 3: - case 35: - case 131: - case 163: - PIXEL00_11 - PIXEL01_21 - PIXEL10_20 - PIXEL11_20 - break; - case 6: - case 38: - case 134: - case 166: - PIXEL00_22 - PIXEL01_12 - PIXEL10_20 - PIXEL11_20 - break; - case 20: - case 21: - case 52: - case 53: - PIXEL00_20 - PIXEL01_11 - PIXEL10_20 - PIXEL11_21 - break; - case 144: - case 145: - case 176: - case 177: - PIXEL00_20 - PIXEL01_22 - PIXEL10_20 - PIXEL11_12 - break; - case 192: - case 193: - case 196: - case 197: - PIXEL00_20 - PIXEL01_20 - PIXEL10_21 - PIXEL11_11 - break; - case 96: - case 97: - case 100: - case 101: - PIXEL00_20 - PIXEL01_20 - PIXEL10_12 - PIXEL11_22 - break; - case 40: - case 44: - case 168: - case 172: - PIXEL00_21 - PIXEL01_20 - PIXEL10_11 - PIXEL11_20 - break; - case 9: - case 13: - case 137: - case 141: - PIXEL00_12 - PIXEL01_20 - PIXEL10_22 - PIXEL11_20 - break; - case 18: - case 50: - PIXEL00_22 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_20 - } - PIXEL10_20 - PIXEL11_21 - break; - case 80: - case 81: - PIXEL00_20 - PIXEL01_22 - PIXEL10_21 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_20 - } - break; - case 72: - case 76: - PIXEL00_21 - PIXEL01_20 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_20 - } - PIXEL11_22 - break; - case 10: - case 138: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_22 - PIXEL11_20 - break; - case 66: - PIXEL00_22 - PIXEL01_21 - PIXEL10_21 - PIXEL11_22 - break; - case 24: - PIXEL00_21 - PIXEL01_22 - PIXEL10_22 - PIXEL11_21 - break; - case 7: - case 39: - case 135: - PIXEL00_11 - PIXEL01_12 - PIXEL10_20 - PIXEL11_20 - break; - case 148: - case 149: - case 180: - PIXEL00_20 - PIXEL01_11 - PIXEL10_20 - PIXEL11_12 - break; - case 224: - case 228: - case 225: - PIXEL00_20 - PIXEL01_20 - PIXEL10_12 - PIXEL11_11 - break; - case 41: - case 169: - case 45: - PIXEL00_12 - PIXEL01_20 - PIXEL10_11 - PIXEL11_20 - break; - case 22: - case 54: - PIXEL00_22 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_20 - PIXEL11_21 - break; - case 208: - case 209: - PIXEL00_20 - PIXEL01_22 - PIXEL10_21 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 104: - case 108: - PIXEL00_21 - PIXEL01_20 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_22 - break; - case 11: - case 139: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_22 - PIXEL11_20 - break; - case 19: - case 51: - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL00_11 - PIXEL01_10 - } else { - PIXEL00_60 - PIXEL01_90 - } - PIXEL10_20 - PIXEL11_21 - break; - case 146: - case 178: - PIXEL00_22 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - PIXEL11_12 - } else { - PIXEL01_90 - PIXEL11_61 - } - PIXEL10_20 - break; - case 84: - case 85: - PIXEL00_20 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL01_11 - PIXEL11_10 - } else { - PIXEL01_60 - PIXEL11_90 - } - PIXEL10_21 - break; - case 112: - case 113: - PIXEL00_20 - PIXEL01_22 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL10_12 - PIXEL11_10 - } else { - PIXEL10_61 - PIXEL11_90 - } - break; - case 200: - case 204: - PIXEL00_21 - PIXEL01_20 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - PIXEL11_11 - } else { - PIXEL10_90 - PIXEL11_60 - } - break; - case 73: - case 77: - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL00_12 - PIXEL10_10 - } else { - PIXEL00_61 - PIXEL10_90 - } - PIXEL01_20 - PIXEL11_22 - break; - case 42: - case 170: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - PIXEL10_11 - } else { - PIXEL00_90 - PIXEL10_60 - } - PIXEL01_21 - PIXEL11_20 - break; - case 14: - case 142: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - PIXEL01_12 - } else { - PIXEL00_90 - PIXEL01_61 - } - PIXEL10_22 - PIXEL11_20 - break; - case 67: - PIXEL00_11 - PIXEL01_21 - PIXEL10_21 - PIXEL11_22 - break; - case 70: - PIXEL00_22 - PIXEL01_12 - PIXEL10_21 - PIXEL11_22 - break; - case 28: - PIXEL00_21 - PIXEL01_11 - PIXEL10_22 - PIXEL11_21 - break; - case 152: - PIXEL00_21 - PIXEL01_22 - PIXEL10_22 - PIXEL11_12 - break; - case 194: - PIXEL00_22 - PIXEL01_21 - PIXEL10_21 - PIXEL11_11 - break; - case 98: - PIXEL00_22 - PIXEL01_21 - PIXEL10_12 - PIXEL11_22 - break; - case 56: - PIXEL00_21 - PIXEL01_22 - PIXEL10_11 - PIXEL11_21 - break; - case 25: - PIXEL00_12 - PIXEL01_22 - PIXEL10_22 - PIXEL11_21 - break; - case 26: - case 31: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_22 - PIXEL11_21 - break; - case 82: - case 214: - PIXEL00_22 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_21 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 88: - case 248: - PIXEL00_21 - PIXEL01_22 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 74: - case 107: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_21 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_22 - break; - case 27: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_10 - PIXEL10_22 - PIXEL11_21 - break; - case 86: - PIXEL00_22 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_21 - PIXEL11_10 - break; - case 216: - PIXEL00_21 - PIXEL01_22 - PIXEL10_10 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 106: - PIXEL00_10 - PIXEL01_21 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_22 - break; - case 30: - PIXEL00_10 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_22 - PIXEL11_21 - break; - case 210: - PIXEL00_22 - PIXEL01_10 - PIXEL10_21 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 120: - PIXEL00_21 - PIXEL01_22 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_10 - break; - case 75: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_10 - PIXEL11_22 - break; - case 29: - PIXEL00_12 - PIXEL01_11 - PIXEL10_22 - PIXEL11_21 - break; - case 198: - PIXEL00_22 - PIXEL01_12 - PIXEL10_21 - PIXEL11_11 - break; - case 184: - PIXEL00_21 - PIXEL01_22 - PIXEL10_11 - PIXEL11_12 - break; - case 99: - PIXEL00_11 - PIXEL01_21 - PIXEL10_12 - PIXEL11_22 - break; - case 57: - PIXEL00_12 - PIXEL01_22 - PIXEL10_11 - PIXEL11_21 - break; - case 71: - PIXEL00_11 - PIXEL01_12 - PIXEL10_21 - PIXEL11_22 - break; - case 156: - PIXEL00_21 - PIXEL01_11 - PIXEL10_22 - PIXEL11_12 - break; - case 226: - PIXEL00_22 - PIXEL01_21 - PIXEL10_12 - PIXEL11_11 - break; - case 60: - PIXEL00_21 - PIXEL01_11 - PIXEL10_11 - PIXEL11_21 - break; - case 195: - PIXEL00_11 - PIXEL01_21 - PIXEL10_21 - PIXEL11_11 - break; - case 102: - PIXEL00_22 - PIXEL01_12 - PIXEL10_12 - PIXEL11_22 - break; - case 153: - PIXEL00_12 - PIXEL01_22 - PIXEL10_22 - PIXEL11_12 - break; - case 58: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - PIXEL10_11 - PIXEL11_21 - break; - case 83: - PIXEL00_11 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - PIXEL10_21 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 92: - PIXEL00_21 - PIXEL01_11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 202: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - PIXEL01_21 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - PIXEL11_11 - break; - case 78: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - PIXEL01_12 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - PIXEL11_22 - break; - case 154: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - PIXEL10_22 - PIXEL11_12 - break; - case 114: - PIXEL00_22 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - PIXEL10_12 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 89: - PIXEL00_12 - PIXEL01_22 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 90: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 55: - case 23: - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL00_11 - PIXEL01_0 - } else { - PIXEL00_60 - PIXEL01_90 - } - PIXEL10_20 - PIXEL11_21 - break; - case 182: - case 150: - PIXEL00_22 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - PIXEL11_12 - } else { - PIXEL01_90 - PIXEL11_61 - } - PIXEL10_20 - break; - case 213: - case 212: - PIXEL00_20 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL01_11 - PIXEL11_0 - } else { - PIXEL01_60 - PIXEL11_90 - } - PIXEL10_21 - break; - case 241: - case 240: - PIXEL00_20 - PIXEL01_22 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL10_12 - PIXEL11_0 - } else { - PIXEL10_61 - PIXEL11_90 - } - break; - case 236: - case 232: - PIXEL00_21 - PIXEL01_20 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - PIXEL11_11 - } else { - PIXEL10_90 - PIXEL11_60 - } - break; - case 109: - case 105: - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL00_12 - PIXEL10_0 - } else { - PIXEL00_61 - PIXEL10_90 - } - PIXEL01_20 - PIXEL11_22 - break; - case 171: - case 43: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - PIXEL10_11 - } else { - PIXEL00_90 - PIXEL10_60 - } - PIXEL01_21 - PIXEL11_20 - break; - case 143: - case 15: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - PIXEL01_12 - } else { - PIXEL00_90 - PIXEL01_61 - } - PIXEL10_22 - PIXEL11_20 - break; - case 124: - PIXEL00_21 - PIXEL01_11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_10 - break; - case 203: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_10 - PIXEL11_11 - break; - case 62: - PIXEL00_10 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_11 - PIXEL11_21 - break; - case 211: - PIXEL00_11 - PIXEL01_10 - PIXEL10_21 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 118: - PIXEL00_22 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_12 - PIXEL11_10 - break; - case 217: - PIXEL00_12 - PIXEL01_22 - PIXEL10_10 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 110: - PIXEL00_10 - PIXEL01_12 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_22 - break; - case 155: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_10 - PIXEL10_22 - PIXEL11_12 - break; - case 188: - PIXEL00_21 - PIXEL01_11 - PIXEL10_11 - PIXEL11_12 - break; - case 185: - PIXEL00_12 - PIXEL01_22 - PIXEL10_11 - PIXEL11_12 - break; - case 61: - PIXEL00_12 - PIXEL01_11 - PIXEL10_11 - PIXEL11_21 - break; - case 157: - PIXEL00_12 - PIXEL01_11 - PIXEL10_22 - PIXEL11_12 - break; - case 103: - PIXEL00_11 - PIXEL01_12 - PIXEL10_12 - PIXEL11_22 - break; - case 227: - PIXEL00_11 - PIXEL01_21 - PIXEL10_12 - PIXEL11_11 - break; - case 230: - PIXEL00_22 - PIXEL01_12 - PIXEL10_12 - PIXEL11_11 - break; - case 199: - PIXEL00_11 - PIXEL01_12 - PIXEL10_21 - PIXEL11_11 - break; - case 220: - PIXEL00_21 - PIXEL01_11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 158: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_22 - PIXEL11_12 - break; - case 234: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - PIXEL01_21 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_11 - break; - case 242: - PIXEL00_22 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - PIXEL10_12 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 59: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - PIXEL10_11 - PIXEL11_21 - break; - case 121: - PIXEL00_12 - PIXEL01_22 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 87: - PIXEL00_11 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_21 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 79: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_12 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - PIXEL11_22 - break; - case 122: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 94: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 218: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 91: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 229: - PIXEL00_20 - PIXEL01_20 - PIXEL10_12 - PIXEL11_11 - break; - case 167: - PIXEL00_11 - PIXEL01_12 - PIXEL10_20 - PIXEL11_20 - break; - case 173: - PIXEL00_12 - PIXEL01_20 - PIXEL10_11 - PIXEL11_20 - break; - case 181: - PIXEL00_20 - PIXEL01_11 - PIXEL10_20 - PIXEL11_12 - break; - case 186: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - PIXEL10_11 - PIXEL11_12 - break; - case 115: - PIXEL00_11 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - PIXEL10_12 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 93: - PIXEL00_12 - PIXEL01_11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 206: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - PIXEL01_12 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - PIXEL11_11 - break; - case 205: - case 201: - PIXEL00_12 - PIXEL01_20 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_10 - } else { - PIXEL10_70 - } - PIXEL11_11 - break; - case 174: - case 46: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_10 - } else { - PIXEL00_70 - } - PIXEL01_12 - PIXEL10_11 - PIXEL11_20 - break; - case 179: - case 147: - PIXEL00_11 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_10 - } else { - PIXEL01_70 - } - PIXEL10_20 - PIXEL11_12 - break; - case 117: - case 116: - PIXEL00_20 - PIXEL01_11 - PIXEL10_12 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_10 - } else { - PIXEL11_70 - } - break; - case 189: - PIXEL00_12 - PIXEL01_11 - PIXEL10_11 - PIXEL11_12 - break; - case 231: - PIXEL00_11 - PIXEL01_12 - PIXEL10_12 - PIXEL11_11 - break; - case 126: - PIXEL00_10 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_10 - break; - case 219: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_10 - PIXEL10_10 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 125: - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL00_12 - PIXEL10_0 - } else { - PIXEL00_61 - PIXEL10_90 - } - PIXEL01_11 - PIXEL11_10 - break; - case 221: - PIXEL00_12 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL01_11 - PIXEL11_0 - } else { - PIXEL01_60 - PIXEL11_90 - } - PIXEL10_10 - break; - case 207: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - PIXEL01_12 - } else { - PIXEL00_90 - PIXEL01_61 - } - PIXEL10_10 - PIXEL11_11 - break; - case 238: - PIXEL00_10 - PIXEL01_12 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - PIXEL11_11 - } else { - PIXEL10_90 - PIXEL11_60 - } - break; - case 190: - PIXEL00_10 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - PIXEL11_12 - } else { - PIXEL01_90 - PIXEL11_61 - } - PIXEL10_11 - break; - case 187: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - PIXEL10_11 - } else { - PIXEL00_90 - PIXEL10_60 - } - PIXEL01_10 - PIXEL11_12 - break; - case 243: - PIXEL00_11 - PIXEL01_10 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL10_12 - PIXEL11_0 - } else { - PIXEL10_61 - PIXEL11_90 - } - break; - case 119: - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL00_11 - PIXEL01_0 - } else { - PIXEL00_60 - PIXEL01_90 - } - PIXEL10_12 - PIXEL11_10 - break; - case 237: - case 233: - PIXEL00_12 - PIXEL01_20 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_100 - } - PIXEL11_11 - break; - case 175: - case 47: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_100 - } - PIXEL01_12 - PIXEL10_11 - PIXEL11_20 - break; - case 183: - case 151: - PIXEL00_11 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_100 - } - PIXEL10_20 - PIXEL11_12 - break; - case 245: - case 244: - PIXEL00_20 - PIXEL01_11 - PIXEL10_12 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_100 - } - break; - case 250: - PIXEL00_10 - PIXEL01_10 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 123: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_10 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_10 - break; - case 95: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_10 - PIXEL11_10 - break; - case 222: - PIXEL00_10 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_10 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 252: - PIXEL00_21 - PIXEL01_11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_100 - } - break; - case 249: - PIXEL00_12 - PIXEL01_22 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_100 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 235: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_21 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_100 - } - PIXEL11_11 - break; - case 111: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_100 - } - PIXEL01_12 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_22 - break; - case 63: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_100 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_11 - PIXEL11_21 - break; - case 159: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_100 - } - PIXEL10_22 - PIXEL11_12 - break; - case 215: - PIXEL00_11 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_100 - } - PIXEL10_21 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 246: - PIXEL00_22 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - PIXEL10_12 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_100 - } - break; - case 254: - PIXEL00_10 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_100 - } - break; - case 253: - PIXEL00_12 - PIXEL01_11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_100 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_100 - } - break; - case 251: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - PIXEL01_10 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_100 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 239: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_100 - } - PIXEL01_12 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_100 - } - PIXEL11_11 - break; - case 127: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_100 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_20 - } - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_20 - } - PIXEL11_10 - break; - case 191: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_100 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_100 - } - PIXEL10_11 - PIXEL11_12 - break; - case 223: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_20 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_100 - } - PIXEL10_10 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_20 - } - break; - case 247: - PIXEL00_11 - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_100 - } - PIXEL10_12 - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_100 - } - break; - case 255: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_0 - } else { - PIXEL00_100 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_0 - } else { - PIXEL01_100 - } - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_0 - } else { - PIXEL10_100 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL11_0 - } else { - PIXEL11_100 - } - break; - } -} - -#undef RGBtoYUV diff --git a/src/gui/render_templates_hq3x.h b/src/gui/render_templates_hq3x.h deleted file mode 100644 index 86f6271..0000000 --- a/src/gui/render_templates_hq3x.h +++ /dev/null @@ -1,2872 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * The HQ3x high quality 3x graphics filter. - * Original author Maxim Stepin (see http://www.hiend3d.com/hq3x.html). - * Adapted for DOSBox from ScummVM and HiEnd3D code by Kronuz. - */ - -#ifndef RENDER_TEMPLATES_HQ3X_TABLE_H -#define RENDER_TEMPLATES_HQ3X_TABLE_H - -#define PIXEL00_1M line0[0] = interp_w2(C4,C0,3U,1U); -#define PIXEL00_1U line0[0] = interp_w2(C4,C1,3U,1U); -#define PIXEL00_1L line0[0] = interp_w2(C4,C3,3U,1U); -#define PIXEL00_2 line0[0] = interp_w3(C4,C3,C1,2U,1U,1U); -#define PIXEL00_4 line0[0] = interp_w3(C4,C3,C1,2U,7U,7U); -#define PIXEL00_5 line0[0] = interp_w2(C3,C1,1U,1U); -#define PIXEL00_C line0[0] = C4; - -#define PIXEL01_1 line0[1] = interp_w2(C4,C1,3U,1U); -#define PIXEL01_3 line0[1] = interp_w2(C4,C1,7U,1U); -#define PIXEL01_6 line0[1] = interp_w2(C1,C4,3U,1U); -#define PIXEL01_C line0[1] = C4; - -#define PIXEL02_1M line0[2] = interp_w2(C4,C2,3U,1U); -#define PIXEL02_1U line0[2] = interp_w2(C4,C1,3U,1U); -#define PIXEL02_1R line0[2] = interp_w2(C4,C5,3U,1U); -#define PIXEL02_2 line0[2] = interp_w3(C4,C1,C5,2U,1U,1U); -#define PIXEL02_4 line0[2] = interp_w3(C4,C1,C5,2U,7U,7U); -#define PIXEL02_5 line0[2] = interp_w2(C1,C5,1U,1U); -#define PIXEL02_C line0[2] = C4; - -#define PIXEL10_1 line1[0] = interp_w2(C4,C3,3U,1U); -#define PIXEL10_3 line1[0] = interp_w2(C4,C3,7U,1U); -#define PIXEL10_6 line1[0] = interp_w2(C3,C4,3U,1U); -#define PIXEL10_C line1[0] = C4; - -#define PIXEL11 line1[1] = C4; - -#define PIXEL12_1 line1[2] = interp_w2(C4,C5,3U,1U); -#define PIXEL12_3 line1[2] = interp_w2(C4,C5,7U,1U); -#define PIXEL12_6 line1[2] = interp_w2(C5,C4,3U,1U); -#define PIXEL12_C line1[2] = C4; - -#define PIXEL20_1M line2[0] = interp_w2(C4,C6,3U,1U); -#define PIXEL20_1D line2[0] = interp_w2(C4,C7,3U,1U); -#define PIXEL20_1L line2[0] = interp_w2(C4,C3,3U,1U); -#define PIXEL20_2 line2[0] = interp_w3(C4,C7,C3,2U,1U,1U); -#define PIXEL20_4 line2[0] = interp_w3(C4,C7,C3,2U,7U,7U); -#define PIXEL20_5 line2[0] = interp_w2(C7,C3,1U,1U); -#define PIXEL20_C line2[0] = C4; - -#define PIXEL21_1 line2[1] = interp_w2(C4,C7,3U,1U); -#define PIXEL21_3 line2[1] = interp_w2(C4,C7,7U,1U); -#define PIXEL21_6 line2[1] = interp_w2(C7,C4,3U,1U); -#define PIXEL21_C line2[1] = C4; - -#define PIXEL22_1M line2[2] = interp_w2(C4,C8,3U,1U); -#define PIXEL22_1D line2[2] = interp_w2(C4,C7,3U,1U); -#define PIXEL22_1R line2[2] = interp_w2(C4,C5,3U,1U); -#define PIXEL22_2 line2[2] = interp_w3(C4,C5,C7,2U,1U,1U); -#define PIXEL22_4 line2[2] = interp_w3(C4,C5,C7,2U,7U,7U); -#define PIXEL22_5 line2[2] = interp_w2(C5,C7,1U,1U); -#define PIXEL22_C line2[2] = C4; - -#endif - -#if SBPP == 32 -#define RGBtoYUV(c) _RGBtoYUV[((c & 0xf80000) >> 8) | ((c & 0x00fc00) >> 5) | ((c & 0x0000f8) >> 3)] -#else -#define RGBtoYUV(c) _RGBtoYUV[c] -#endif - -inline void conc2d(Hq3x,SBPP)(PTYPE * line0, PTYPE * line1, PTYPE * line2, const PTYPE * fc) -{ - if (_RGBtoYUV == 0) conc2d(InitLUTs,SBPP)(); - - Bit32u pattern = 0; - const Bit32u YUV4 = RGBtoYUV(C4); - - if (C4 != C0 && diffYUV(YUV4, RGBtoYUV(C0))) pattern |= 0x0001; - if (C4 != C1 && diffYUV(YUV4, RGBtoYUV(C1))) pattern |= 0x0002; - if (C4 != C2 && diffYUV(YUV4, RGBtoYUV(C2))) pattern |= 0x0004; - if (C4 != C3 && diffYUV(YUV4, RGBtoYUV(C3))) pattern |= 0x0008; - if (C4 != C5 && diffYUV(YUV4, RGBtoYUV(C5))) pattern |= 0x0010; - if (C4 != C6 && diffYUV(YUV4, RGBtoYUV(C6))) pattern |= 0x0020; - if (C4 != C7 && diffYUV(YUV4, RGBtoYUV(C7))) pattern |= 0x0040; - if (C4 != C8 && diffYUV(YUV4, RGBtoYUV(C8))) pattern |= 0x0080; - - switch (pattern) { - case 0: - case 1: - case 4: - case 32: - case 128: - case 5: - case 132: - case 160: - case 33: - case 129: - case 36: - case 133: - case 164: - case 161: - case 37: - case 165: - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - case 2: - case 34: - case 130: - case 162: - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - case 16: - case 17: - case 48: - case 49: - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - case 64: - case 65: - case 68: - case 69: - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - case 8: - case 12: - case 136: - case 140: - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - case 3: - case 35: - case 131: - case 163: - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - case 6: - case 38: - case 134: - case 166: - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - case 20: - case 21: - case 52: - case 53: - PIXEL00_2 - PIXEL01_1 - PIXEL02_1U - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - case 144: - case 145: - case 176: - case 177: - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1D - break; - case 192: - case 193: - case 196: - case 197: - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - case 96: - case 97: - case 100: - case 101: - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - case 40: - case 44: - case 168: - case 172: - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1D - PIXEL21_1 - PIXEL22_2 - break; - case 9: - case 13: - case 137: - case 141: - PIXEL00_1U - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - case 18: - case 50: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_1M - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - case 80: - case 81: - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_1M - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - case 72: - case 76: - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_1M - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 10: - case 138: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - case 66: - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - case 24: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - case 7: - case 39: - case 135: - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - case 148: - case 149: - case 180: - PIXEL00_2 - PIXEL01_1 - PIXEL02_1U - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1D - break; - case 224: - case 228: - case 225: - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - case 41: - case 169: - case 45: - PIXEL00_1U - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1D - PIXEL21_1 - PIXEL22_2 - break; - case 22: - case 54: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - case 208: - case 209: - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - case 104: - case 108: - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 11: - case 139: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - case 19: - case 51: - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL12_C - } else { - PIXEL00_2 - PIXEL01_6 - PIXEL02_5 - PIXEL12_1 - } - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - case 146: - case 178: - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_1M - PIXEL12_C - PIXEL22_1D - } else { - PIXEL01_1 - PIXEL02_5 - PIXEL12_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - break; - case 84: - case 85: - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL02_1U - PIXEL12_C - PIXEL21_C - PIXEL22_1M - } else { - PIXEL02_2 - PIXEL12_6 - PIXEL21_1 - PIXEL22_5 - } - PIXEL00_2 - PIXEL01_1 - PIXEL10_1 - PIXEL11 - PIXEL20_1M - break; - case 112: - case 113: - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - } else { - PIXEL12_1 - PIXEL20_2 - PIXEL21_6 - PIXEL22_5 - } - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - break; - case 200: - case 204: - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - } else { - PIXEL10_1 - PIXEL20_5 - PIXEL21_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - break; - case 73: - case 77: - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL00_1U - PIXEL10_C - PIXEL20_1M - PIXEL21_C - } else { - PIXEL00_2 - PIXEL10_6 - PIXEL20_5 - PIXEL21_1 - } - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - PIXEL22_1M - break; - case 42: - case 170: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - PIXEL01_C - PIXEL10_C - PIXEL20_1D - } else { - PIXEL00_5 - PIXEL01_1 - PIXEL10_6 - PIXEL20_2 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL21_1 - PIXEL22_2 - break; - case 14: - case 142: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_C - } else { - PIXEL00_5 - PIXEL01_6 - PIXEL02_2 - PIXEL10_1 - } - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - case 67: - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - case 70: - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - case 28: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - case 152: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - case 194: - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - case 98: - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - case 56: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - case 25: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - case 26: - case 31: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL10_3 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_C - PIXEL12_C - } else { - PIXEL02_4 - PIXEL12_3 - } - PIXEL11 - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - case 82: - case 214: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - } else { - PIXEL01_3 - PIXEL02_4 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL21_C - PIXEL22_C - } else { - PIXEL21_3 - PIXEL22_4 - } - break; - case 88: - case 248: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - } else { - PIXEL10_3 - PIXEL20_4 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL22_4 - } - break; - case 74: - case 107: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - } else { - PIXEL00_4 - PIXEL01_3 - } - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_C - PIXEL21_C - } else { - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 27: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - case 86: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_1 - PIXEL11 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - case 216: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - case 106: - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 30: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_C - PIXEL11 - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - case 210: - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - case 120: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 75: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - case 29: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1M - break; - case 198: - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - case 184: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - case 99: - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - case 57: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - case 71: - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - case 156: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - case 226: - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - case 60: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - case 195: - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - case 102: - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - case 153: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - case 58: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - case 83: - PIXEL00_1L - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 92: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 202: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - case 78: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1M - break; - case 154: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - case 114: - PIXEL00_1M - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 89: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 90: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 55: - case 23: - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL00_1L - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL00_2 - PIXEL01_6 - PIXEL02_5 - PIXEL12_1 - } - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - PIXEL22_1M - break; - case 182: - case 150: - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - PIXEL22_1D - } else { - PIXEL01_1 - PIXEL02_5 - PIXEL12_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL10_1 - PIXEL11 - PIXEL20_2 - PIXEL21_1 - break; - case 213: - case 212: - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL02_1U - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL02_2 - PIXEL12_6 - PIXEL21_1 - PIXEL22_5 - } - PIXEL00_2 - PIXEL01_1 - PIXEL10_1 - PIXEL11 - PIXEL20_1M - break; - case 241: - case 240: - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL20_1L - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_1 - PIXEL20_2 - PIXEL21_6 - PIXEL22_5 - } - PIXEL00_2 - PIXEL01_1 - PIXEL02_1M - PIXEL10_1 - PIXEL11 - break; - case 236: - case 232: - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - PIXEL22_1R - } else { - PIXEL10_1 - PIXEL20_5 - PIXEL21_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - break; - case 109: - case 105: - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL00_1U - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL00_2 - PIXEL10_6 - PIXEL20_5 - PIXEL21_1 - } - PIXEL01_1 - PIXEL02_2 - PIXEL11 - PIXEL12_1 - PIXEL22_1M - break; - case 171: - case 43: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - PIXEL20_1D - } else { - PIXEL00_5 - PIXEL01_1 - PIXEL10_6 - PIXEL20_2 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL21_1 - PIXEL22_2 - break; - case 143: - case 15: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL02_1R - PIXEL10_C - } else { - PIXEL00_5 - PIXEL01_6 - PIXEL02_2 - PIXEL10_1 - } - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_1 - PIXEL22_2 - break; - case 124: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 203: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - case 62: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_C - PIXEL11 - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - case 211: - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - case 118: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_1 - PIXEL11 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - case 217: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - case 110: - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 155: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - case 188: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - case 185: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - case 61: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - case 157: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - case 103: - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - case 227: - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - case 230: - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - case 199: - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - case 220: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - case 158: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_C - PIXEL11 - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - case 234: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1M - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1R - break; - case 242: - PIXEL00_1M - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL20_1L - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - case 59: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - case 121: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 87: - PIXEL00_1L - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_1 - PIXEL11 - PIXEL20_1M - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 79: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1R - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1M - break; - case 122: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 94: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_C - PIXEL11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 218: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - case 91: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 229: - PIXEL00_2 - PIXEL01_1 - PIXEL02_2 - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - case 167: - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_2 - PIXEL21_1 - PIXEL22_2 - break; - case 173: - PIXEL00_1U - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1D - PIXEL21_1 - PIXEL22_2 - break; - case 181: - PIXEL00_2 - PIXEL01_1 - PIXEL02_1U - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1D - break; - case 186: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - case 115: - PIXEL00_1L - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 93: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 206: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - case 205: - case 201: - PIXEL00_1U - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_1M - } else { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - case 174: - case 46: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_1M - } else { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1D - PIXEL21_1 - PIXEL22_2 - break; - case 179: - case 147: - PIXEL00_1L - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_1M - } else { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1D - break; - case 117: - case 116: - PIXEL00_2 - PIXEL01_1 - PIXEL02_1U - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_1M - } else { - PIXEL22_2 - } - break; - case 189: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - case 231: - PIXEL00_1L - PIXEL01_C - PIXEL02_1R - PIXEL10_1 - PIXEL11 - PIXEL12_1 - PIXEL20_1L - PIXEL21_C - PIXEL22_1R - break; - case 126: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_4 - PIXEL12_3 - } - PIXEL11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 219: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL01_3 - PIXEL10_3 - } - PIXEL02_1M - PIXEL11 - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_4 - } - break; - case 125: - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL00_1U - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL00_2 - PIXEL10_6 - PIXEL20_5 - PIXEL21_1 - } - PIXEL01_1 - PIXEL02_1U - PIXEL11 - PIXEL12_C - PIXEL22_1M - break; - case 221: - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL02_1U - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL02_2 - PIXEL12_6 - PIXEL21_1 - PIXEL22_5 - } - PIXEL00_1U - PIXEL01_1 - PIXEL10_C - PIXEL11 - PIXEL20_1M - break; - case 207: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL02_1R - PIXEL10_C - } else { - PIXEL00_5 - PIXEL01_6 - PIXEL02_2 - PIXEL10_1 - } - PIXEL11 - PIXEL12_1 - PIXEL20_1M - PIXEL21_C - PIXEL22_1R - break; - case 238: - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - PIXEL22_1R - } else { - PIXEL10_1 - PIXEL20_5 - PIXEL21_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL01_C - PIXEL02_1R - PIXEL11 - PIXEL12_1 - break; - case 190: - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - PIXEL22_1D - } else { - PIXEL01_1 - PIXEL02_5 - PIXEL12_6 - PIXEL22_2 - } - PIXEL00_1M - PIXEL10_C - PIXEL11 - PIXEL20_1D - PIXEL21_1 - break; - case 187: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - PIXEL20_1D - } else { - PIXEL00_5 - PIXEL01_1 - PIXEL10_6 - PIXEL20_2 - } - PIXEL02_1M - PIXEL11 - PIXEL12_C - PIXEL21_1 - PIXEL22_1D - break; - case 243: - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL20_1L - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_1 - PIXEL20_2 - PIXEL21_6 - PIXEL22_5 - } - PIXEL00_1L - PIXEL01_C - PIXEL02_1M - PIXEL10_1 - PIXEL11 - break; - case 119: - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL00_1L - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL00_2 - PIXEL01_6 - PIXEL02_5 - PIXEL12_1 - } - PIXEL10_1 - PIXEL11 - PIXEL20_1L - PIXEL21_C - PIXEL22_1M - break; - case 237: - case 233: - PIXEL00_1U - PIXEL01_1 - PIXEL02_2 - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_C - } else { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - case 175: - case 47: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - } else { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - PIXEL20_1D - PIXEL21_1 - PIXEL22_2 - break; - case 183: - case 151: - PIXEL00_1L - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_C - } else { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_2 - PIXEL21_1 - PIXEL22_1D - break; - case 245: - case 244: - PIXEL00_2 - PIXEL01_1 - PIXEL02_1U - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_C - } else { - PIXEL22_2 - } - break; - case 250: - PIXEL00_1M - PIXEL01_C - PIXEL02_1M - PIXEL11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - } else { - PIXEL10_3 - PIXEL20_4 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL22_4 - } - break; - case 123: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - } else { - PIXEL00_4 - PIXEL01_3 - } - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_C - PIXEL21_C - } else { - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 95: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL10_3 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_C - PIXEL12_C - } else { - PIXEL02_4 - PIXEL12_3 - } - PIXEL11 - PIXEL20_1M - PIXEL21_C - PIXEL22_1M - break; - case 222: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - } else { - PIXEL01_3 - PIXEL02_4 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL21_C - PIXEL22_C - } else { - PIXEL21_3 - PIXEL22_4 - } - break; - case 252: - PIXEL00_1M - PIXEL01_1 - PIXEL02_1U - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - } else { - PIXEL10_3 - PIXEL20_4 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_C - } else { - PIXEL22_2 - } - break; - case 249: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1M - PIXEL10_C - PIXEL11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_C - } else { - PIXEL20_2 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL22_4 - } - break; - case 235: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - } else { - PIXEL00_4 - PIXEL01_3 - } - PIXEL02_1M - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_C - } else { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - case 111: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - } else { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_C - PIXEL21_C - } else { - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 63: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - } else { - PIXEL00_2 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_C - PIXEL12_C - } else { - PIXEL02_4 - PIXEL12_3 - } - PIXEL10_C - PIXEL11 - PIXEL20_1D - PIXEL21_1 - PIXEL22_1M - break; - case 159: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL10_3 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_C - } else { - PIXEL02_2 - } - PIXEL11 - PIXEL12_C - PIXEL20_1M - PIXEL21_1 - PIXEL22_1D - break; - case 215: - PIXEL00_1L - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_C - } else { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL21_C - PIXEL22_C - } else { - PIXEL21_3 - PIXEL22_4 - } - break; - case 246: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - } else { - PIXEL01_3 - PIXEL02_4 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_C - } else { - PIXEL22_2 - } - break; - case 254: - PIXEL00_1M - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - } else { - PIXEL01_3 - PIXEL02_4 - } - PIXEL11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - } else { - PIXEL10_3 - PIXEL20_4 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL21_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL21_3 - PIXEL22_2 - } - break; - case 253: - PIXEL00_1U - PIXEL01_1 - PIXEL02_1U - PIXEL10_C - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_C - } else { - PIXEL20_2 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_C - } else { - PIXEL22_2 - } - break; - case 251: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - } else { - PIXEL00_4 - PIXEL01_3 - } - PIXEL02_1M - PIXEL11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL10_C - PIXEL20_C - PIXEL21_C - } else { - PIXEL10_3 - PIXEL20_2 - PIXEL21_3 - } - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL12_C - PIXEL22_C - } else { - PIXEL12_3 - PIXEL22_4 - } - break; - case 239: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - } else { - PIXEL00_2 - } - PIXEL01_C - PIXEL02_1R - PIXEL10_C - PIXEL11 - PIXEL12_1 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_C - } else { - PIXEL20_2 - } - PIXEL21_C - PIXEL22_1R - break; - case 127: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL01_C - PIXEL10_C - } else { - PIXEL00_2 - PIXEL01_3 - PIXEL10_3 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_C - PIXEL12_C - } else { - PIXEL02_4 - PIXEL12_3 - } - PIXEL11 - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_C - PIXEL21_C - } else { - PIXEL20_4 - PIXEL21_3 - } - PIXEL22_1M - break; - case 191: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - } else { - PIXEL00_2 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_C - } else { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - PIXEL20_1D - PIXEL21_1 - PIXEL22_1D - break; - case 223: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - PIXEL10_C - } else { - PIXEL00_4 - PIXEL10_3 - } - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL01_C - PIXEL02_C - PIXEL12_C - } else { - PIXEL01_3 - PIXEL02_2 - PIXEL12_3 - } - PIXEL11 - PIXEL20_1M - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL21_C - PIXEL22_C - } else { - PIXEL21_3 - PIXEL22_4 - } - break; - case 247: - PIXEL00_1L - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_C - } else { - PIXEL02_2 - } - PIXEL10_1 - PIXEL11 - PIXEL12_C - PIXEL20_1L - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_C - } else { - PIXEL22_2 - } - break; - case 255: - if (diffYUV(RGBtoYUV(C3), RGBtoYUV(C1))) { - PIXEL00_C - } else { - PIXEL00_2 - } - PIXEL01_C - if (diffYUV(RGBtoYUV(C1), RGBtoYUV(C5))) { - PIXEL02_C - } else { - PIXEL02_2 - } - PIXEL10_C - PIXEL11 - PIXEL12_C - if (diffYUV(RGBtoYUV(C7), RGBtoYUV(C3))) { - PIXEL20_C - } else { - PIXEL20_2 - } - PIXEL21_C - if (diffYUV(RGBtoYUV(C5), RGBtoYUV(C7))) { - PIXEL22_C - } else { - PIXEL22_2 - } - break; - } -} - -#undef RGBtoYUV diff --git a/src/gui/render_templates_sai.h b/src/gui/render_templates_sai.h deleted file mode 100644 index 36d339c..0000000 --- a/src/gui/render_templates_sai.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -static inline int conc2d(GetResult,SBPP)(PTYPE A, PTYPE B, PTYPE C, PTYPE D) { - const bool ac = (A==C); - const bool bc = (B==C); - const int x1 = ac; - const int y1 = (bc & !ac); - const bool ad = (A==D); - const bool bd = (B==D); - const int x2 = ad; - const int y2 = (bd & !ad); - const int x = x1+x2; - const int y = y1+y2; - static const int rmap[3][3] = { - {0, 0, -1}, - {0, 0, -1}, - {1, 1, 0} - }; - return rmap[y][x]; -} - -inline void conc2d(Super2xSaI,SBPP)(PTYPE * line0, PTYPE * line1, const PTYPE * fc) -{ - //-------------------------------------- - if (C7 == C5 && C4 != C8) { - line1[1] = line0[1] = C7; - } else if (C4 == C8 && C7 != C5) { - line1[1] = line0[1] = C4; - } else if (C4 == C8 && C7 == C5) { - register int r = 0; - r += conc2d(GetResult,SBPP)(C5,C4,C6,D1); - r += conc2d(GetResult,SBPP)(C5,C4,C3,C1); - r += conc2d(GetResult,SBPP)(C5,C4,D2,D5); - r += conc2d(GetResult,SBPP)(C5,C4,C2,D4); - - if (r > 0) - line1[1] = line0[1] = C5; - else if (r < 0) - line1[1] = line0[1] = C4; - else { - line1[1] = line0[1] = interp_w2(C4,C5,1U,1U); - } - } else { - if (C5 == C8 && C8 == D1 && C7 != D2 && C8 != D0) - line1[1] = interp_w2(C8,C7,3U,1U); - else if (C4 == C7 && C7 == D2 && D1 != C8 && C7 != D6) - line1[1] = interp_w2(C7,C8,3U,1U); - else - line1[1] = interp_w2(C7,C8,1U,1U); - - if (C5 == C8 && C5 == C1 && C4 != C2 && C5 != C0) - line0[1] = interp_w2(C5,C4,3U,1U); - else if (C4 == C7 && C4 == C2 && C1 != C5 && C4 != D3) - line0[1] = interp_w2(C4,C5,3U,1U); - else - line0[1] = interp_w2(C4,C5,1U,1U); - } - - if (C4 == C8 && C7 != C5 && C3 == C4 && C4 != D2) - line1[0] = interp_w2(C7,C4,1U,1U); - else if (C4 == C6 && C5 == C4 && C3 != C7 && C4 != D0) - line1[0] = interp_w2(C7,C4,1U,1U); - else - line1[0] = C7; - - if (C7 == C5 && C4 != C8 && C6 == C7 && C7 != C2) - line0[0] = interp_w2(C7,C4,1U,1U); - else if (C3 == C7 && C8 == C7 && C6 != C4 && C7 != C0) - line0[0] = interp_w2(C7,C4,1U,1U); - else - line0[0] = C4; -} - -inline void conc2d(SuperEagle,SBPP)(PTYPE * line0, PTYPE * line1, const PTYPE * fc) -{ - // -------------------------------------- - if (C4 != C8) { - if (C7 == C5) { - line0[1] = line1[0] = C7; - if ((C6 == C7) || (C5 == C2)) { - line0[0] = interp_w2(C7,C4,3U,1U); - } else { - line0[0] = interp_w2(C4,C5,1U,1U); - } - - if ((C5 == D4) || (C7 == D1)) { - line1[1] = interp_w2(C7,C8,3U,1U); - } else { - line1[1] = interp_w2(C7,C8,1U,1U); - } - } else { - line1[1] = interp_w3(C8,C7,C5,6U,1U,1U); - line0[0] = interp_w3(C4,C7,C5,6U,1U,1U); - - line1[0] = interp_w3(C7,C4,C8,6U,1U,1U); - line0[1] = interp_w3(C5,C4,C8,6U,1U,1U); - } - } else { - if (C7 != C5) { - line1[1] = line0[0] = C4; - - if ((C1 == C4) || (C8 == D5)) { - line0[1] = interp_w2(C4,C5,3U,1U); - } else { - line0[1] = interp_w2(C4,C5,1U,1U); - } - - if ((C8 == D2) || (C3 == C4)) { - line1[0] = interp_w2(C4,C7,3U,1U); - } else { - line1[0] = interp_w2(C7,C8,1U,1U); - } - } else { - register int r = 0; - r += conc2d(GetResult,SBPP)(C5,C4,C6,D1); - r += conc2d(GetResult,SBPP)(C5,C4,C3,C1); - r += conc2d(GetResult,SBPP)(C5,C4,D2,D5); - r += conc2d(GetResult,SBPP)(C5,C4,C2,D4); - - if (r > 0) { - line0[1] = line1[0] = C7; - line0[0] = line1[1] = interp_w2(C4,C5,1U,1U); - } else if (r < 0) { - line1[1] = line0[0] = C4; - line0[1] = line1[0] = interp_w2(C4,C5,1U,1U); - } else { - line1[1] = line0[0] = C4; - line0[1] = line1[0] = C7; - } - } - } -} - -inline void conc2d(_2xSaI,SBPP)(PTYPE * line0, PTYPE * line1, const PTYPE * fc) -{ - if ((C4 == C8) && (C5 != C7)) { - if (((C4 == C1) && (C5 == D5)) || - ((C4 == C7) && (C4 == C2) && (C5 != C1) && (C5 == D3))) { - line0[1] = C4; - } else { - line0[1] = interp_w2(C4,C5,1U,1U); - } - - if (((C4 == C3) && (C7 == D2)) || - ((C4 == C5) && (C4 == C6) && (C3 != C7) && (C7 == D0))) { - line1[0] = C4; - } else { - line1[0] = interp_w2(C4,C7,1U,1U); - } - line1[1] = C4; - } else if ((C5 == C7) && (C4 != C8)) { - if (((C5 == C2) && (C4 == C6)) || - ((C5 == C1) && (C5 == C8) && (C4 != C2) && (C4 == C0))) { - line0[1] = C5; - } else { - line0[1] = interp_w2(C4,C5,1U,1U); - } - - if (((C7 == C6) && (C4 == C2)) || - ((C7 == C3) && (C7 == C8) && (C4 != C6) && (C4 == C0))) { - line1[0] = C7; - } else { - line1[0] = interp_w2(C4,C7,1U,1U); - } - line1[1] = C5; - } else if ((C4 == C8) && (C5 == C7)) { - if (C4 == C5) { - line0[1] = C4; - line1[0] = C4; - line1[1] = C4; - } else { - register int r = 0; - r += conc2d(GetResult,SBPP)(C4,C5,C3,C1); - r -= conc2d(GetResult,SBPP)(C5,C4,D4,C2); - r -= conc2d(GetResult,SBPP)(C5,C4,C6,D1); - r += conc2d(GetResult,SBPP)(C4,C5,D5,D2); - - if (r > 0) - line1[1] = C4; - else if (r < 0) - line1[1] = C5; - else { - line1[1] = interp_w4(C4,C5,C7,C8,1U,1U,1U,1U); - } - - line1[0] = interp_w2(C4,C7,1U,1U); - line0[1] = interp_w2(C4,C5,1U,1U); - } - } else { - line1[1] = interp_w4(C4,C5,C7,C8,1U,1U,1U,1U); - - if ((C4 == C7) && (C4 == C2) - && (C5 != C1) && (C5 == D3)) { - line0[1] = C4; - } else if ((C5 == C1) && (C5 == C8) - && (C4 != C2) && (C4 == C0)) { - line0[1] = C5; - } else { - line0[1] = interp_w2(C4,C5,1U,1U); - } - - if ((C4 == C5) && (C4 == C6) - && (C3 != C7) && (C7 == D0)) { - line1[0] = C4; - } else if ((C7 == C3) && (C7 == C8) - && (C4 != C6) && (C4 == C0)) { - line1[0] = C7; - } else { - line1[0] = interp_w2(C4,C7,1U,1U); - } - } - line0[0] = C4; -} diff --git a/src/gui/sdl_gui.cpp b/src/gui/sdl_gui.cpp deleted file mode 100644 index bc8ea97..0000000 --- a/src/gui/sdl_gui.cpp +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: sdl_gui.cpp,v 1.11 2009/02/25 19:58:11 c2woody Exp $ */ - -#if 0 -#include "SDL.h" -#include "../libs/gui_tk/gui_tk.h" - -#include "dosbox.h" -#include "keyboard.h" -#include "video.h" -#include "render.h" -#include "mapper.h" -#include "setup.h" -#include "control.h" -#include "shell.h" - -#include -#include -#include -#include -#include -#include - -extern Bit8u int10_font_14[256 * 14]; -extern Program * first_shell; -extern void MSG_Write(const char *); -extern void GFX_SetTitle(Bit32s cycles, Bits frameskip, bool paused); - -static int cursor, saved_bpp; -static int old_unicode; -static bool mousetoggle, running, shell_idle; - -static SDL_Surface *screenshot, *background; - -/* Prepare screen for UI */ -void UI_Init(void) { - GUI::Font::addFont("default",new GUI::BitmapFont(int10_font_14,14,10)); -} - -static void getPixel(Bits x, Bits y, int &r, int &g, int &b, int shift) -{ - if (x >= (Bits)render.src.width) x = (Bits)render.src.width-1; - if (y >= (Bits)render.src.height) x = (Bits)render.src.height-1; - if (x < 0) x = 0; - if (y < 0) y = 0; - - Bit8u* src = (Bit8u *)&scalerSourceCache; - Bit32u pixel; - switch (render.scale.inMode) { - case scalerMode8: - pixel = *(x+(Bit8u*)(src+y*render.scale.cachePitch)); - r += render.pal.rgb[pixel].red >> shift; - g += render.pal.rgb[pixel].green >> shift; - b += render.pal.rgb[pixel].blue >> shift; - break; - case scalerMode15: - pixel = *(x+(Bit16u*)(src+y*render.scale.cachePitch)); - r += (pixel >> (7+shift)) & (0xf8 >> shift); - g += (pixel >> (2+shift)) & (0xf8 >> shift); - b += (pixel << (3-shift)) & (0xf8 >> shift); - break; - case scalerMode16: - pixel = *(x+(Bit16u*)(src+y*render.scale.cachePitch)); - r += (pixel >> (8+shift)) & (0xf8 >> shift); - g += (pixel >> (3+shift)) & (0xfc >> shift); - b += (pixel << (3-shift)) & (0xf8 >> shift); - break; - case scalerMode32: - pixel = *(x+(Bit32u*)(src+y*render.scale.cachePitch)); - r += (pixel >> (16+shift)) & (0xff >> shift); - g += (pixel >> (8+shift)) & (0xff >> shift); - b += (pixel >> shift) & (0xff >> shift); - break; - } -} - -static GUI::ScreenSDL *UI_Startup(GUI::ScreenSDL *screen) { - GFX_EndUpdate(0); - GFX_SetTitle(-1,-1,true); - if(!screen) { //Coming from DOSBox. Clean up the keyboard buffer. - KEYBOARD_ClrBuffer();//Clear buffer - } - GFX_LosingFocus();//Release any keys pressed (buffer gets filled again). (could be in above if, but clearing the mapper input when exiting the mapper is sensible as well - SDL_Delay(500); - - // Comparable to the code of intro.com, but not the same! (the code of intro.com is called from within a com file) - shell_idle = first_shell && (DOS_PSP(dos.psp()).GetSegment() == DOS_PSP(dos.psp()).GetParent()); - - int w, h; - bool fs; - GFX_GetSize(w, h, fs); - if (w < 512) w = 640; - if (h < 350) h = 400; - - old_unicode = SDL_EnableUNICODE(1); - SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL); - screenshot = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, GUI::Color::RedMask, GUI::Color::GreenMask, GUI::Color::BlueMask, 0); - - // create screenshot for fade effect - int rs = screenshot->format->Rshift, gs = screenshot->format->Gshift, bs = screenshot->format->Bshift, am = GUI::Color::AlphaMask; - for (int y = 0; y < h; y++) { - Bit32u *bg = (Bit32u*)(y*screenshot->pitch + (char*)screenshot->pixels); - for (int x = 0; x < w; x++) { - int r = 0, g = 0, b = 0; - getPixel(x *(int)render.src.width/w, y *(int)render.src.height/h, r, g, b, 0); - bg[x] = r << rs | g << gs | b << bs; - } - } - - background = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, GUI::Color::RedMask, GUI::Color::GreenMask, GUI::Color::BlueMask, GUI::Color::AlphaMask); - // use a blurred and sepia-toned screenshot as menu background - for (int y = 0; y < h; y++) { - Bit32u *bg = (Bit32u*)(y*background->pitch + (char*)background->pixels); - for (int x = 0; x < w; x++) { - int r = 0, g = 0, b = 0; - getPixel(x *(int)render.src.width/w, y *(int)render.src.height/h, r, g, b, 3); - getPixel((x-1)*(int)render.src.width/w, y *(int)render.src.height/h, r, g, b, 3); - getPixel(x *(int)render.src.width/w, (y-1)*(int)render.src.height/h, r, g, b, 3); - getPixel((x-1)*(int)render.src.width/w, (y-1)*(int)render.src.height/h, r, g, b, 3); - getPixel((x+1)*(int)render.src.width/w, y *(int)render.src.height/h, r, g, b, 3); - getPixel(x *(int)render.src.width/w, (y+1)*(int)render.src.height/h, r, g, b, 3); - getPixel((x+1)*(int)render.src.width/w, (y+1)*(int)render.src.height/h, r, g, b, 3); - getPixel((x-1)*(int)render.src.width/w, (y+1)*(int)render.src.height/h, r, g, b, 3); - int r1 = (int)((r * 393 + g * 769 + b * 189) / 1351); - int g1 = (int)((r * 349 + g * 686 + b * 168) / 1203); - int b1 = (int)((r * 272 + g * 534 + b * 131) / 2140); - bg[x] = r1 << rs | g1 << gs | b1 << bs | am; - } - } - - cursor = SDL_ShowCursor(SDL_QUERY); - SDL_ShowCursor(SDL_ENABLE); - - mousetoggle = mouselocked; - if (mouselocked) GFX_CaptureMouse(); - - SDL_Surface* sdlscreen = SDL_SetVideoMode(w, h, 32, SDL_SWSURFACE|(fs?SDL_FULLSCREEN:0)); - if (sdlscreen == NULL) E_Exit("Could not initialize video mode %ix%ix32 for UI: %s", w, h, SDL_GetError()); - - // fade out - SDL_Event event; - for (int i = 0xff; i > 0; i -= 0x11) { - SDL_SetAlpha(screenshot, SDL_SRCALPHA, i); - SDL_BlitSurface(background, NULL, sdlscreen, NULL); - SDL_BlitSurface(screenshot, NULL, sdlscreen, NULL); - SDL_UpdateRect(sdlscreen, 0, 0, 0, 0); - while (SDL_PollEvent(&event)) {}; - SDL_Delay(40); - } - - SDL_BlitSurface(background, NULL, sdlscreen, NULL); - SDL_UpdateRect(sdlscreen, 0, 0, 0, 0); - - if (screen) screen->setSurface(sdlscreen); - else screen = new GUI::ScreenSDL(sdlscreen); - - saved_bpp = render.src.bpp; - render.src.bpp = 0; - running = true; - return screen; -} - -/* Restore screen */ -static void UI_Shutdown(GUI::ScreenSDL *screen) { - SDL_Surface *sdlscreen = screen->getSurface(); - render.src.bpp = saved_bpp; - - // fade in - SDL_Event event; - for (int i = 0x00; i < 0xff; i += 0x11) { - SDL_SetAlpha(screenshot, SDL_SRCALPHA, i); - SDL_BlitSurface(background, NULL, sdlscreen, NULL); - SDL_BlitSurface(screenshot, NULL, sdlscreen, NULL); - SDL_UpdateRect(sdlscreen, 0, 0, 0, 0); - while (SDL_PollEvent(&event)) {}; - SDL_Delay(40); - } - - // clean up - if (mousetoggle) GFX_CaptureMouse(); - SDL_ShowCursor(cursor); - SDL_FreeSurface(background); - SDL_FreeSurface(screenshot); - SDL_FreeSurface(sdlscreen); - screen->setSurface(NULL); - GFX_ResetScreen(); - SDL_EnableUNICODE(old_unicode); - SDL_EnableKeyRepeat(0,0); - GFX_SetTitle(-1,-1,false); -} - -/* helper class for command execution */ -class VirtualBatch : public BatchFile { -protected: - std::istringstream lines; -public: - VirtualBatch(DOS_Shell *host, const std::string& cmds) : BatchFile(host, "CON", ""), lines(cmds) { - } - bool ReadLine(char *line) { - std::string l; - if (!std::getline(lines,l)) { - delete this; - return false; - } - strcpy(line,l.c_str()); - return true; - } -}; - -static void UI_RunCommands(GUI::ScreenSDL *s, const std::string &cmds) { - DOS_Shell temp; - temp.call = true; - UI_Shutdown(s); - temp.bf = new VirtualBatch(&temp, cmds); - temp.RunInternal(); - temp.ShowPrompt(); - UI_Startup(s); -} - - -/* stringification and conversion from the c++ FAQ */ -class BadConversion : public std::runtime_error { -public: BadConversion(const std::string& s) : std::runtime_error(s) { } -}; - -template inline std::string stringify(const T& x, std::ios_base& ( *pf )(std::ios_base&) = NULL) { - std::ostringstream o; - if (pf) o << pf; - if (!(o << x)) throw BadConversion(std::string("stringify(") + typeid(x).name() + ")"); - return o.str(); -} - -template inline void convert(const std::string& s, T& x, bool failIfLeftoverChars = true, std::ios_base& ( *pf )(std::ios_base&) = NULL) { - std::istringstream i(s); - if (pf) i >> pf; - char c; - if (!(i >> x) || (failIfLeftoverChars && i.get(c))) throw BadConversion(s); -} - -/*****************************************************************************************************************************************/ -/* UI classes */ - -class PropertyEditor : public GUI::Window, public GUI::ActionEventSource_Callback { -protected: - Section_prop * section; - Property *prop; -public: - PropertyEditor(Window *parent, int x, int y, Section_prop *section, Property *prop) : - Window(parent, x, y, 240, 30), section(section), prop(prop) { } - - virtual bool prepare(std::string &buffer) = 0; - - void actionExecuted(GUI::ActionEventSource *b, const GUI::String &arg) { - std::string line; - if (prepare(line)) { - if (first_shell) section->ExecuteDestroy(false); - prop->SetValue(GUI::String(line)); - if (first_shell) section->ExecuteInit(false); - } - } -}; - -class PropertyEditorBool : public PropertyEditor { - GUI::Checkbox *input; -public: - PropertyEditorBool(Window *parent, int x, int y, Section_prop *section, Property *prop) : - PropertyEditor(parent, x, y, section, prop) { - input = new GUI::Checkbox(this, 0, 3, prop->propname.c_str()); - input->setChecked(static_cast(prop->GetValue())); - } - - bool prepare(std::string &buffer) { - if (input->isChecked() == static_cast(prop->GetValue())) return false; - buffer.append(input->isChecked()?"true":"false"); - return true; - } -}; - -class PropertyEditorString : public PropertyEditor { -protected: - GUI::Input *input; -public: - PropertyEditorString(Window *parent, int x, int y, Section_prop *section, Property *prop) : - PropertyEditor(parent, x, y, section, prop) { - new GUI::Label(this, 0, 5, prop->propname); - input = new GUI::Input(this, 130, 0, 110); - std::string temps = prop->GetValue().ToString(); - input->setText(stringify(temps)); - } - - bool prepare(std::string &buffer) { - std::string temps = prop->GetValue().ToString(); - if (input->getText() == GUI::String(temps)) return false; - buffer.append(static_cast(input->getText())); - return true; - } -}; - -class PropertyEditorFloat : public PropertyEditor { -protected: - GUI::Input *input; -public: - PropertyEditorFloat(Window *parent, int x, int y, Section_prop *section, Property *prop) : - PropertyEditor(parent, x, y, section, prop) { - new GUI::Label(this, 0, 5, prop->propname); - input = new GUI::Input(this, 130, 0, 50); - input->setText(stringify((double)prop->GetValue())); - } - - bool prepare(std::string &buffer) { - double val; - convert(input->getText(), val, false); - if (val == (double)prop->GetValue()) return false; - buffer.append(stringify(val)); - return true; - } -}; - -class PropertyEditorHex : public PropertyEditor { -protected: - GUI::Input *input; -public: - PropertyEditorHex(Window *parent, int x, int y, Section_prop *section, Property *prop) : - PropertyEditor(parent, x, y, section, prop) { - new GUI::Label(this, 0, 5, prop->propname); - input = new GUI::Input(this, 130, 0, 50); - std::string temps = prop->GetValue().ToString(); - input->setText(temps.c_str()); - } - - bool prepare(std::string &buffer) { - int val; - convert(input->getText(), val, false, std::hex); - if ((Hex)val == prop->GetValue()) return false; - buffer.append(stringify(val, std::hex)); - return true; - } -}; - -class PropertyEditorInt : public PropertyEditor { -protected: - GUI::Input *input; -public: - PropertyEditorInt(Window *parent, int x, int y, Section_prop *section, Property *prop) : - PropertyEditor(parent, x, y, section, prop) { - new GUI::Label(this, 0, 5, prop->propname); - input = new GUI::Input(this, 130, 0, 50); - //Maybe use ToString() of Value - input->setText(stringify(static_cast(prop->GetValue()))); - } - - bool prepare(std::string &buffer) { - int val; - convert(input->getText(), val, false); - if (val == static_cast(prop->GetValue())) return false; - buffer.append(stringify(val)); - return true; - } -}; - -class HelpWindow : public GUI::MessageBox { -public: - HelpWindow(GUI::Screen *parent, int x, int y, Section *section) : - MessageBox(parent, x, y, 580, "", "") { - std::string title(section->GetName()); - title.at(0) = std::toupper(title.at(0)); - setTitle("Help for "+title); - std::string name = section->GetName(); - std::transform(name.begin(), name.end(), name.begin(), (int(*)(int))std::toupper); - name += "_CONFIGFILE_HELP"; - setText(MSG_Get(name.c_str())); - } -}; - -class SectionEditor : public GUI::ToplevelWindow { - Section_prop * section; -public: - SectionEditor(GUI::Screen *parent, int x, int y, Section_prop *section) : - ToplevelWindow(parent, x, y, 510, 300, ""), section(section) { - std::string title(section->GetName()); - title[0] = std::toupper(title[0]); - setTitle("Configuration for "+title); - new GUI::Label(this, 5, 10, "Settings:"); - GUI::Button *b = new GUI::Button(this, 120, 220, "Cancel", 70); - b->addActionHandler(this); - b = new GUI::Button(this, 200, 220, "Help", 70); - b->addActionHandler(this); - b = new GUI::Button(this, 280, 220, "OK", 70); - - int i = 0; - Property *prop; - while ((prop = section->Get_prop(i))) { - Prop_bool *pbool = dynamic_cast(prop); - Prop_int *pint = dynamic_cast(prop); - Prop_double *pdouble = dynamic_cast(prop); - Prop_hex *phex = dynamic_cast(prop); - Prop_string *pstring = dynamic_cast(prop); - - PropertyEditor *p; - if (pbool) p = new PropertyEditorBool(this, 5+250*(i/6), 40+(i%6)*30, section, prop); - else if (phex) p = new PropertyEditorHex(this, 5+250*(i/6), 40+(i%6)*30, section, prop); - else if (pint) p = new PropertyEditorInt(this, 5+250*(i/6), 40+(i%6)*30, section, prop); - else if (pdouble) p = new PropertyEditorFloat(this, 5+250*(i/6), 40+(i%6)*30, section, prop); - else if (pstring) p = new PropertyEditorString(this, 5+250*(i/6), 40+(i%6)*30, section, prop); - else { i++; continue; } - b->addActionHandler(p); - i++; - } - b->addActionHandler(this); - } - - void actionExecuted(GUI::ActionEventSource *b, const GUI::String &arg) { - if (arg == "OK" || arg == "Cancel") close(); - else if (arg == "Help") new HelpWindow(static_cast(parent), getX()-10, getY()-10, section); - else ToplevelWindow::actionExecuted(b, arg); - } -}; - -class AutoexecEditor : public GUI::ToplevelWindow { - Section_line * section; - GUI::Input *content; -public: - AutoexecEditor(GUI::Screen *parent, int x, int y, Section_line *section) : - ToplevelWindow(parent, x, y, 450, 300, ""), section(section) { - std::string title(section->GetName()); - title[0] = std::toupper(title[0]); - setTitle("Edit "+title); - new GUI::Label(this, 5, 10, "Content:"); - content = new GUI::Input(this, 5, 30, 420, 185); - content->setText(section->data); - if (first_shell) (new GUI::Button(this, 5, 220, "Append History"))->addActionHandler(this); - if (shell_idle) (new GUI::Button(this, 180, 220, "Execute Now"))->addActionHandler(this); - (new GUI::Button(this, 290, 220, "Cancel", 70))->addActionHandler(this); - (new GUI::Button(this, 360, 220, "OK", 70))->addActionHandler(this); - } - - void actionExecuted(GUI::ActionEventSource *b, const GUI::String &arg) { - if (arg == "OK") section->data = *(std::string*)content->getText(); - if (arg == "OK" || arg == "Cancel") close(); - else if (arg == "Append Shell Commands") { - DOS_Shell *s = static_cast(first_shell); - std::list::reverse_iterator i = s->l_history.rbegin(); - std::string lines = *(std::string*)content->getText(); - while (i != s->l_history.rend()) { - lines += "\n"; - lines += *i; - ++i; - } - content->setText(lines); - } else if (arg == "Execute Now") { - UI_RunCommands(dynamic_cast(getScreen()), content->getText()); - } else ToplevelWindow::actionExecuted(b, arg); - } -}; - -class SaveDialog : public GUI::ToplevelWindow { -protected: - GUI::Input *name; -public: - SaveDialog(GUI::Screen *parent, int x, int y, const char *title) : - ToplevelWindow(parent, x, y, 400, 150, title) { - new GUI::Label(this, 5, 10, "Enter filename for configuration file:"); - name = new GUI::Input(this, 5, 30, 350); - name->setText("dosbox.conf"); - (new GUI::Button(this, 120, 70, "Cancel", 70))->addActionHandler(this); - (new GUI::Button(this, 210, 70, "OK", 70))->addActionHandler(this); - } - - void actionExecuted(GUI::ActionEventSource *b, const GUI::String &arg) { - if (arg == "OK") control->PrintConfig(name->getText()); - close(); - } -}; - -class SaveLangDialog : public GUI::ToplevelWindow { -protected: - GUI::Input *name; -public: - SaveLangDialog(GUI::Screen *parent, int x, int y, const char *title) : - ToplevelWindow(parent, x, y, 400, 150, title) { - new GUI::Label(this, 5, 10, "Enter filename for language file:"); - name = new GUI::Input(this, 5, 30, 350); - name->setText("messages.txt"); - (new GUI::Button(this, 120, 70, "Cancel", 70))->addActionHandler(this); - (new GUI::Button(this, 210, 70, "OK", 70))->addActionHandler(this); - } - - void actionExecuted(GUI::ActionEventSource *b, const GUI::String &arg) { - if (arg == "OK") MSG_Write(name->getText()); - close(); - } -}; - -class ConfigurationWindow : public GUI::ToplevelWindow { -public: - ConfigurationWindow(GUI::Screen *parent, GUI::Size x, GUI::Size y, GUI::String title) : - GUI::ToplevelWindow(parent, x, y, 470, 290, title) { - - (new GUI::Button(this, 180, 215, "Close", 70))->addActionHandler(this); - - GUI::Menubar *bar = new GUI::Menubar(this, 0, 0, getWidth()); - bar->addMenu("Configuration"); - bar->addItem(0,"Save..."); - bar->addItem(0,"Save Language File..."); - bar->addItem(0,""); - bar->addItem(0,"Close"); - bar->addMenu("Settings"); - bar->addMenu("Help"); - bar->addItem(2,"Introduction"); - bar->addItem(2,"Getting Started"); - bar->addItem(2,"CD-ROM Support"); - bar->addItem(2,"Special Keys"); - bar->addItem(2,""); - bar->addItem(2,"About"); - bar->addActionHandler(this); - - new GUI::Label(this, 10, 30, "Choose a settings group to configure:"); - - Section *sec; - int i = 0; - while ((sec = control->GetSection(i))) { - std::string name = sec->GetName(); - name[0] = std::toupper(name[0]); - GUI::Button *b = new GUI::Button(this, 12+(i/5)*160, 50+(i%5)*30, name, 100); - b->addActionHandler(this); - bar->addItem(1, name); - i++; - } - - if (first_shell) { - (new GUI::Button(this, 12+(i/5)*160, 50+(i%5)*30, "Keyboard", 100))->addActionHandler(this); - bar->addItem(1, ""); - bar->addItem(1, "Keyboard"); - } - } - - ~ConfigurationWindow() { running = false; } - - void actionExecuted(GUI::ActionEventSource *b, const GUI::String &arg) { - GUI::String sname = arg; - sname.at(0) = std::tolower(sname.at(0)); - Section *sec; - if (arg == "Close" || arg == "Cancel") { - running = false; - } else if (arg == "Keyboard") { - UI_Shutdown(dynamic_cast(getScreen())); - MAPPER_Run(false); - UI_Startup(dynamic_cast(getScreen())); - } else if (sname == "autoexec") { - Section_line *section = static_cast(control->GetSection((const char *)sname)); - new AutoexecEditor(getScreen(), 50, 30, section); - } else if ((sec = control->GetSection((const char *)sname))) { - Section_prop *section = static_cast(sec); - new SectionEditor(getScreen(), 50, 30, section); - } else if (arg == "About") { - new GUI::MessageBox(getScreen(), 200, 150, 280, "About DOSBox", "\nDOSBox 0.72\nAn emulator for old DOS Games\n\nCopyright 2002-2009\nThe DOSBox Team"); - } else if (arg == "Introduction") { - new GUI::MessageBox(getScreen(), 20, 50, 600, "Introduction", MSG_Get("PROGRAM_INTRO")); - } else if (arg == "Getting Started") { - std::string msg = MSG_Get("PROGRAM_INTRO_MOUNT_START"); -#ifdef WIN32 - msg += MSG_Get("PROGRAM_INTRO_MOUNT_WINDOWS"); -#else - msg += MSG_Get("PROGRAM_INTRO_MOUNT_OTHER"); -#endif - msg += MSG_Get("PROGRAM_INTRO_MOUNT_END"); - - new GUI::MessageBox(getScreen(), 20, 50, 600, std::string("Introduction"), msg); - } else if (arg == "CD-ROM Support") { - new GUI::MessageBox(getScreen(), 20, 50, 600, "Introduction", MSG_Get("PROGRAM_INTRO_CDROM")); - } else if (arg == "Special Keys") { - new GUI::MessageBox(getScreen(), 20, 50, 600, "Introduction", MSG_Get("PROGRAM_INTRO_SPECIAL")); - } else if (arg == "Save...") { - new SaveDialog(getScreen(), 90, 100, "Save Configuration..."); - } else if (arg == "Save Language File...") { - new SaveLangDialog(getScreen(), 90, 100, "Save Language File..."); - } else { - return ToplevelWindow::actionExecuted(b, arg); - } - } -}; - -/*********************************************************************************************************************/ -/* UI control functions */ - -static void UI_Execute(GUI::ScreenSDL *screen) { - SDL_Surface *sdlscreen = screen->getSurface(); - new ConfigurationWindow(screen, 30, 30, "DOSBox Configuration"); - - // event loop - SDL_Event event; - while (running) { - while (SDL_PollEvent(&event)) { - if (!screen->event(event)) { - if (event.type == SDL_QUIT) running = false; - } - } - //Selecting keyboard will create a new surface. - sdlscreen = screen->getSurface(); - SDL_BlitSurface(background, NULL, sdlscreen, NULL); - screen->update(4); - SDL_UpdateRect(sdlscreen, 0, 0, 0, 0); - - SDL_Delay(40); - } -} - -void UI_Run(bool pressed) { - if (pressed) return; - GUI::ScreenSDL *screen = UI_Startup(NULL); - UI_Execute(screen); - UI_Shutdown(screen); - delete screen; -} -#endif diff --git a/src/gui/sdl_mapper.cpp b/src/gui/sdl_mapper.cpp deleted file mode 100644 index bd83118..0000000 --- a/src/gui/sdl_mapper.cpp +++ /dev/null @@ -1,2469 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: sdl_mapper.cpp,v 1.58 2009/04/25 06:59:54 qbix79 Exp $ */ - -#include -#include -#include -#include -#include -#include -#include - - -#include "SDL.h" -#include "SDL_thread.h" - -#include "dosbox.h" -#include "video.h" -#include "keyboard.h" -#include "joystick.h" -#include "support.h" -#include "mapper.h" -#include "setup.h" - -enum { - CLR_BLACK=0, - CLR_WHITE=1, - CLR_RED=2, - CLR_BLUE=3, - CLR_GREEN=4 -}; - -enum BB_Types { - BB_Next,BB_Add,BB_Del, - BB_Save,BB_Exit -}; - -enum BC_Types { - BC_Mod1,BC_Mod2,BC_Mod3, - BC_Hold -}; - -#define BMOD_Mod1 0x0001 -#define BMOD_Mod2 0x0002 -#define BMOD_Mod3 0x0004 - -#define BFLG_Hold 0x0001 -#define BFLG_Repeat 0x0004 - - -#define MAXSTICKS 8 -#define MAXACTIVE 16 -#define MAXBUTTON 32 -#define MAXBUTTON_CAP 16 - -class CEvent; -class CHandlerEvent; -class CButton; -class CBind; -class CBindGroup; - -static void SetActiveEvent(CEvent * event); -static void SetActiveBind(CBind * _bind); -extern Bit8u int10_font_14[256 * 14]; - -static std::vector events; -static std::vector buttons; -static std::vector bindgroups; -static std::vector handlergroup; -typedef std::list CBindList; -typedef std::list::iterator CEventList_it; -typedef std::list::iterator CBindList_it; -typedef std::vector::iterator CButton_it; -typedef std::vector::iterator CEventVector_it; -typedef std::vector::iterator CHandlerEventVector_it; -typedef std::vector::iterator CBindGroup_it; - -static CBindList holdlist; - - -class CEvent { -public: - CEvent(char const * const _entry) { - safe_strncpy(entry,_entry,16); - events.push_back(this); - bindlist.clear(); - activity=0; - current_value=0; - } - void AddBind(CBind * bind); - virtual ~CEvent() {} - virtual void Active(bool yesno)=0; - virtual void ActivateEvent(bool ev_trigger,bool skip_action)=0; - virtual void DeActivateEvent(bool ev_trigger)=0; - void DeActivateAll(void); - void SetValue(Bits value){ - current_value=value; - } - Bits GetValue(void) { - return current_value; - } - char * GetName(void) { return entry; } - virtual bool IsTrigger(void)=0; - CBindList bindlist; -protected: - Bitu activity; - char entry[16]; - Bits current_value; -}; - -/* class for events which can be ON/OFF only: key presses, joystick buttons, joystick hat */ -class CTriggeredEvent : public CEvent { -public: - CTriggeredEvent(char const * const _entry) : CEvent(_entry) {} - virtual bool IsTrigger(void) { - return true; - } - void ActivateEvent(bool ev_trigger,bool skip_action) { - if (current_value>25000) { - /* value exceeds boundary, trigger event if not active */ - if (!activity && !skip_action) Active(true); - if (activity<32767) activity++; - } else { - if (activity>0) { - /* untrigger event if it is fully inactive */ - DeActivateEvent(ev_trigger); - activity=0; - } - } - } - void DeActivateEvent(bool /*ev_trigger*/) { - activity--; - if (!activity) Active(false); - } -}; - -/* class for events which have a non-boolean state: joystick axis movement */ -class CContinuousEvent : public CEvent { -public: - CContinuousEvent(char const * const _entry) : CEvent(_entry) {} - virtual bool IsTrigger(void) { - return false; - } - void ActivateEvent(bool ev_trigger,bool skip_action) { - if (ev_trigger) { - activity++; - if (!skip_action) Active(true); - } else { - /* test if no trigger-activity is present, this cares especially - about activity of the opposite-direction joystick axis for example */ - if (!GetActivityCount()) Active(true); - } - } - void DeActivateEvent(bool ev_trigger) { - if (ev_trigger) { - if (activity>0) activity--; - if (activity==0) { - /* test if still some trigger-activity is present, - adjust the state in this case accordingly */ - if (GetActivityCount()) RepostActivity(); - else Active(false); - } - } else { - if (!GetActivityCount()) Active(false); - } - } - virtual Bitu GetActivityCount(void) { - return activity; - } - virtual void RepostActivity(void) {} -}; - -class CBind { -public: - virtual ~CBind () { - list->remove(this); -// event->bindlist.remove(this); - } - CBind(CBindList * _list) { - list=_list; - _list->push_back(this); - mods=flags=0; - event=0; - active=holding=false; - } - void AddFlags(char * buf) { - if (mods & BMOD_Mod1) strcat(buf," mod1"); - if (mods & BMOD_Mod2) strcat(buf," mod2"); - if (mods & BMOD_Mod3) strcat(buf," mod3"); - if (flags & BFLG_Hold) strcat(buf," hold"); - } - void SetFlags(char * buf) { - char * word; - while (*(word=StripWord(buf))) { - if (!strcasecmp(word,"mod1")) mods|=BMOD_Mod1; - if (!strcasecmp(word,"mod2")) mods|=BMOD_Mod2; - if (!strcasecmp(word,"mod3")) mods|=BMOD_Mod3; - if (!strcasecmp(word,"hold")) flags|=BFLG_Hold; - } - } - void ActivateBind(Bits _value,bool ev_trigger,bool skip_action=false) { - if (event->IsTrigger()) { - /* use value-boundary for on/off events */ - if (_value>25000) { - event->SetValue(_value); - if (active) return; - event->ActivateEvent(ev_trigger,skip_action); - active=true; - } else { - if (active) { - event->DeActivateEvent(ev_trigger); - active=false; - } - } - } else { - /* store value for possible later use in the activated event */ - event->SetValue(_value); - event->ActivateEvent(ev_trigger,false); - } - } - void DeActivateBind(bool ev_trigger) { - if (event->IsTrigger()) { - if (!active) return; - active=false; - if (flags & BFLG_Hold) { - if (!holding) { - holdlist.push_back(this); - holding=true; - return; - } else { - holdlist.remove(this); - holding=false; - } - } - event->DeActivateEvent(ev_trigger); - } else { - /* store value for possible later use in the activated event */ - event->SetValue(0); - event->DeActivateEvent(ev_trigger); - } - } - virtual void ConfigName(char * buf)=0; - virtual void BindName(char * buf)=0; - - Bitu mods,flags; - Bit16s value; - CEvent * event; - CBindList * list; - bool active,holding; -}; - - -void CEvent::AddBind(CBind * bind) { - bindlist.push_front(bind); - bind->event=this; -} -void CEvent::DeActivateAll(void) { - for (CBindList_it bit=bindlist.begin();bit!=bindlist.end();bit++) { - (*bit)->DeActivateBind(true); - } -} - - - -class CBindGroup { -public: - CBindGroup() { - bindgroups.push_back(this); - } - void ActivateBindList(CBindList * list,Bits value,bool ev_trigger); - void DeactivateBindList(CBindList * list,bool ev_trigger); - virtual CBind * CreateConfigBind(char *&buf)=0; - virtual CBind * CreateEventBind(SDL_Event * event)=0; - - virtual bool CheckEvent(SDL_Event * event)=0; - virtual const char * ConfigStart(void)=0; - virtual const char * BindStart(void)=0; - virtual ~CBindGroup (void) { } - -protected: - -}; - - -#define MAX_SDLKEYS 323 - -static bool usescancodes; -static Bit8u scancode_map[MAX_SDLKEYS]; - -#define Z SDLK_UNKNOWN - -#if defined (MACOSX) -static SDLKey sdlkey_map[]={ - /* Main block printables */ - /*00-05*/ SDLK_a, SDLK_s, SDLK_d, SDLK_f, SDLK_h, SDLK_g, - /*06-0B*/ SDLK_z, SDLK_x, SDLK_c, SDLK_v, SDLK_WORLD_0, SDLK_b, - /*0C-11*/ SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_y, SDLK_t, - /*12-17*/ SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_6, SDLK_5, - /*18-1D*/ SDLK_EQUALS, SDLK_9, SDLK_7, SDLK_MINUS, SDLK_8, SDLK_0, - /*1E-21*/ SDLK_RIGHTBRACKET, SDLK_o, SDLK_u, SDLK_LEFTBRACKET, - /*22-23*/ SDLK_i, SDLK_p, - /*24-29*/ SDLK_RETURN, SDLK_l, SDLK_j, SDLK_QUOTE, SDLK_k, SDLK_SEMICOLON, - /*2A-29*/ SDLK_BACKSLASH, SDLK_COMMA, SDLK_SLASH, SDLK_n, SDLK_m, - /*2F-2F*/ SDLK_PERIOD, - - /* Spaces, controls, modifiers (dosbox uses LMETA only for - * hotkeys, it's not really mapped to an emulated key) */ - /*30-33*/ SDLK_TAB, SDLK_SPACE, SDLK_BACKQUOTE, SDLK_BACKSPACE, - /*34-37*/ Z, SDLK_ESCAPE, Z, SDLK_LMETA, - /*38-3B*/ SDLK_LSHIFT, SDLK_CAPSLOCK, SDLK_LALT, SDLK_LCTRL, - - /*3C-40*/ Z, Z, Z, Z, Z, - - /* Keypad (KP_EQUALS not supported, NUMLOCK used on what is CLEAR - * in Mac OS X) */ - /*41-46*/ SDLK_KP_PERIOD, Z, SDLK_KP_MULTIPLY, Z, SDLK_KP_PLUS, Z, - /*47-4A*/ SDLK_NUMLOCK /*==SDLK_CLEAR*/, Z, Z, Z, - /*4B-4D*/ SDLK_KP_DIVIDE, SDLK_KP_ENTER, Z, - /*4E-51*/ SDLK_KP_MINUS, Z, Z, SDLK_KP_EQUALS, - /*52-57*/ SDLK_KP0, SDLK_KP1, SDLK_KP2, SDLK_KP3, SDLK_KP4, SDLK_KP5, - /*58-5C*/ SDLK_KP6, SDLK_KP7, Z, SDLK_KP8, SDLK_KP9, - - /*5D-5F*/ Z, Z, Z, - - /* Function keys and cursor blocks (F13 not supported, F14 => - * PRINT[SCREEN], F15 => SCROLLOCK, F16 => PAUSE, HELP => INSERT) */ - /*60-64*/ SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F3, SDLK_F8, - /*65-6A*/ SDLK_F9, Z, SDLK_F11, Z, SDLK_F13, SDLK_PAUSE /*==SDLK_F16*/, - /*6B-70*/ SDLK_PRINT /*==SDLK_F14*/, Z, SDLK_F10, Z, SDLK_F12, Z, - /*71-72*/ SDLK_SCROLLOCK /*==SDLK_F15*/, SDLK_INSERT /*==SDLK_HELP*/, - /*73-77*/ SDLK_HOME, SDLK_PAGEUP, SDLK_DELETE, SDLK_F4, SDLK_END, - /*78-7C*/ SDLK_F2, SDLK_PAGEDOWN, SDLK_F1, SDLK_LEFT, SDLK_RIGHT, - /*7D-7E*/ SDLK_DOWN, SDLK_UP, - - /*7F-7F*/ Z, - - /* 4 extra keys that don't really exist, but are needed for - * round-trip mapping (dosbox uses RMETA only for hotkeys, it's - * not really mapped to an emulated key) */ - SDLK_RMETA, SDLK_RSHIFT, SDLK_RALT, SDLK_RCTRL, -}; -#define MAX_SCANCODES (0x80+4) -/* Make sure that the table above has the expected size. This - expression will raise a compiler error if the condition is false. */ -typedef char assert_right_size [MAX_SCANCODES == (sizeof(sdlkey_map)/sizeof(sdlkey_map[0])) ? 1 : -1]; - -#else // !MACOSX - -#define MAX_SCANCODES 212 -static SDLKey sdlkey_map[MAX_SCANCODES]={SDLK_UNKNOWN,SDLK_ESCAPE, - SDLK_1,SDLK_2,SDLK_3,SDLK_4,SDLK_5,SDLK_6,SDLK_7,SDLK_8,SDLK_9,SDLK_0, - /* 0x0c: */ - SDLK_MINUS,SDLK_EQUALS,SDLK_BACKSPACE,SDLK_TAB, - SDLK_q,SDLK_w,SDLK_e,SDLK_r,SDLK_t,SDLK_y,SDLK_u,SDLK_i,SDLK_o,SDLK_p, - SDLK_LEFTBRACKET,SDLK_RIGHTBRACKET,SDLK_RETURN,SDLK_LCTRL, - SDLK_a,SDLK_s,SDLK_d,SDLK_f,SDLK_g,SDLK_h,SDLK_j,SDLK_k,SDLK_l, - SDLK_SEMICOLON,SDLK_QUOTE,SDLK_BACKQUOTE,SDLK_LSHIFT,SDLK_BACKSLASH, - SDLK_z,SDLK_x,SDLK_c,SDLK_v,SDLK_b,SDLK_n,SDLK_m, - /* 0x33: */ - SDLK_COMMA,SDLK_PERIOD,SDLK_SLASH,SDLK_RSHIFT,SDLK_KP_MULTIPLY, - SDLK_LALT,SDLK_SPACE,SDLK_CAPSLOCK, - SDLK_F1,SDLK_F2,SDLK_F3,SDLK_F4,SDLK_F5,SDLK_F6,SDLK_F7,SDLK_F8,SDLK_F9,SDLK_F10, - /* 0x45: */ - SDLK_NUMLOCK,SDLK_SCROLLOCK, - SDLK_KP7,SDLK_KP8,SDLK_KP9,SDLK_KP_MINUS,SDLK_KP4,SDLK_KP5,SDLK_KP6,SDLK_KP_PLUS, - SDLK_KP1,SDLK_KP2,SDLK_KP3,SDLK_KP0,SDLK_KP_PERIOD, - SDLK_UNKNOWN,SDLK_UNKNOWN, - SDLK_LESS,SDLK_F11,SDLK_F12, - Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, - Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, - Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z, - /* 0xb7: */ - Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z - /* 0xd4: ... */ -}; -#endif - -#undef Z - - -SDLKey MapSDLCode(Bitu skey) { - if (usescancodes) { - if (skey SDLK_WORLD_95) -#endif - ) { - /* try to retrieve key from symbolic key as scancode is zero */ - if (keysym.symtype!=SDL_KEYDOWN) return 0; - return CreateKeyBind((SDLKey)GetKeyCode(event->key.keysym)); - }; - bool CheckEvent(SDL_Event * event) { - if (event->type!=SDL_KEYDOWN && event->type!=SDL_KEYUP) return false; - Bitu key=GetKeyCode(event->key.keysym); -// LOG_MSG("key type %i is %x [%x %x]",event->type,key,event->key.keysym.sym,event->key.keysym.scancode); - assert(Bitu(event->key.keysym.sym)type==SDL_KEYDOWN) ActivateBindList(&lists[key],0x7fff,true); - else DeactivateBindList(&lists[key],true); - return 0; - } - CBind * CreateKeyBind(SDLKey _key) { - if (!usescancodes) assert((Bitu)_keyConfigStart(),axis,positive ? 1 : 0); - } - void BindName(char * buf) { - sprintf(buf,"%s Axis %d%s",group->BindStart(),axis,positive ? "+" : "-"); - } -protected: - CBindGroup * group; - Bitu axis; - bool positive; -}; - -class CJButtonBind : public CBind { -public: - CJButtonBind(CBindList * _list,CBindGroup * _group,Bitu _button) : CBind(_list) { - group = _group; - button=_button; - } - void ConfigName(char * buf) { - sprintf(buf,"%s button %d",group->ConfigStart(),button); - } - void BindName(char * buf) { - sprintf(buf,"%s Button %d",group->BindStart(),button); - } -protected: - CBindGroup * group; - Bitu button; -}; - -class CJHatBind : public CBind { -public: - CJHatBind(CBindList * _list,CBindGroup * _group,Bitu _hat,Bit8u _dir) : CBind(_list) { - group = _group; - hat = _hat; - dir = _dir; - /* allow only one hat position */ - if (dir&SDL_HAT_UP) dir=SDL_HAT_UP; - else if (dir&SDL_HAT_RIGHT) dir=SDL_HAT_RIGHT; - else if (dir&SDL_HAT_DOWN) dir=SDL_HAT_DOWN; - else if (dir&SDL_HAT_LEFT) dir=SDL_HAT_LEFT; - else E_Exit("MAPPER:JOYSTICK:Invalid hat position"); - } - void ConfigName(char * buf) { - sprintf(buf,"%s hat %d %d",group->ConfigStart(),hat,dir); - } - void BindName(char * buf) { - sprintf(buf,"%s Hat %d %s",group->BindStart(),hat,(dir==SDL_HAT_UP)?"up": - ((dir==SDL_HAT_RIGHT)?"right": - ((dir==SDL_HAT_DOWN)?"down":"left"))); - } -protected: - CBindGroup * group; - Bitu hat; - Bit8u dir; -}; - -bool autofire = false; - -class CStickBindGroup : public CBindGroup { -public: - CStickBindGroup(Bitu _stick,Bitu _emustick,bool _dummy=false) : CBindGroup (){ - stick=_stick; // the number of the physical device (SDL numbering|) - emustick=_emustick; // the number of the emulated device - sprintf(configname,"stick_%d",emustick); - - sdl_joystick=NULL; - axes=0; buttons=0; hats=0; - button_wrap=0; - button_cap=0; axes_cap=0; hats_cap=0; - emulated_buttons=0; emulated_axes=0; emulated_hats=0; - - is_dummy=_dummy; - if (_dummy) return; - - // initialize binding lists and position data - pos_axis_lists=new CBindList[4]; - neg_axis_lists=new CBindList[4]; - button_lists=new CBindList[MAXBUTTON]; - hat_lists=new CBindList[4]; - Bitu i; - for (i=0; iMAXBUTTON_CAP) button_cap = MAXBUTTON_CAP; - } - if (button_wrap > MAXBUTTON) button_wrap = MAXBUTTON; - axes_cap=emulated_axes; - if (axes_cap>axes) axes_cap=axes; - hats_cap=emulated_hats; - if (hats_cap>hats) hats_cap=hats; - LOG_MSG("Using joystick %s with %d axes, %d buttons and %d hat(s)",SDL_JoystickName(stick),axes,buttons,hats); - } - ~CStickBindGroup() { - SDL_JoystickClose(sdl_joystick); - delete[] pos_axis_lists; - delete[] neg_axis_lists; - delete[] button_lists; - delete[] hat_lists; - } - - CBind * CreateConfigBind(char *& buf) { - if (strncasecmp(configname,buf,strlen(configname))) return 0; - StripWord(buf);char * type=StripWord(buf); - CBind * bind=0; - if (!strcasecmp(type,"axis")) { - Bitu ax=ConvDecWord(StripWord(buf)); - bool pos=ConvDecWord(StripWord(buf)) > 0; - bind=CreateAxisBind(ax,pos); - } else if (!strcasecmp(type,"button")) { - Bitu but=ConvDecWord(StripWord(buf)); - bind=CreateButtonBind(but); - } else if (!strcasecmp(type,"hat")) { - Bitu hat=ConvDecWord(StripWord(buf)); - Bit8u dir=(Bit8u)ConvDecWord(StripWord(buf)); - bind=CreateHatBind(hat,dir); - } - return bind; - } - CBind * CreateEventBind(SDL_Event * event) { - if (event->type==SDL_JOYAXISMOTION) { - if (event->jaxis.which!=stick) return 0; -#if defined (REDUCE_JOYSTICK_POLLING) - if (event->jaxis.axis>=emulated_axes) return 0; -#endif - if (abs(event->jaxis.value)<25000) return 0; - return CreateAxisBind(event->jaxis.axis,event->jaxis.value>0); - } else if (event->type==SDL_JOYBUTTONDOWN) { - if (event->button.which!=stick) return 0; -#if defined (REDUCE_JOYSTICK_POLLING) - return CreateButtonBind(event->jbutton.button%button_wrap); -#else - return CreateButtonBind(event->jbutton.button); -#endif - } else if (event->type==SDL_JOYHATMOTION) { - if (event->jhat.which!=stick) return 0; - if (event->jhat.value==0) return 0; - if (event->jhat.value>(SDL_HAT_UP|SDL_HAT_RIGHT|SDL_HAT_DOWN|SDL_HAT_LEFT)) return 0; - return CreateHatBind(event->jhat.hat,event->jhat.value); - } else return 0; - } - - virtual bool CheckEvent(SDL_Event * event) { - SDL_JoyAxisEvent * jaxis = NULL; - SDL_JoyButtonEvent * jbutton = NULL; - Bitu but = 0; - - switch(event->type) { - case SDL_JOYAXISMOTION: - jaxis = &event->jaxis; - if(jaxis->which == stick) { - if(jaxis->axis == 0) - JOYSTICK_Move_X(emustick,(float)(jaxis->value/32768.0)); - else if(jaxis->axis == 1) - JOYSTICK_Move_Y(emustick,(float)(jaxis->value/32768.0)); - } - break; - case SDL_JOYBUTTONDOWN: - case SDL_JOYBUTTONUP: - jbutton = &event->jbutton; - bool state; - state=jbutton->type==SDL_JOYBUTTONDOWN; - but = jbutton->button % emulated_buttons; - if (jbutton->which == stick) { - JOYSTICK_Button(emustick,but,state); - } - break; - } - return false; - } - - virtual void UpdateJoystick() { - if (is_dummy) return; - /* query SDL joystick and activate bindings */ - ActivateJoystickBoundEvents(); - - bool button_pressed[MAXBUTTON]; - Bitu i; - for (i=0; i1) { - if (old_neg_axis_state[i]) { - DeactivateBindList(&neg_axis_lists[i],false); - old_neg_axis_state[i] = false; - } - ActivateBindList(&pos_axis_lists[i],caxis_pos,false); - old_pos_axis_state[i] = true; - } else if (caxis_pos<-1) { - if (old_pos_axis_state[i]) { - DeactivateBindList(&pos_axis_lists[i],false); - old_pos_axis_state[i] = false; - } - if (caxis_pos!=-32768) caxis_pos=(Sint16)abs(caxis_pos); - else caxis_pos=32767; - ActivateBindList(&neg_axis_lists[i],caxis_pos,false); - old_neg_axis_state[i] = true; - } else { - /* center */ - if (old_pos_axis_state[i]) { - DeactivateBindList(&pos_axis_lists[i],false); - old_pos_axis_state[i] = false; - } - if (old_neg_axis_state[i]) { - DeactivateBindList(&neg_axis_lists[i],false); - old_neg_axis_state[i] = false; - } - } - } - - for (i=0; iaxes) axes_cap=axes; - hats_cap=emulated_hats; - if (hats_cap>hats) hats_cap=hats; - - JOYSTICK_Enable(1,true); - } - - bool CheckEvent(SDL_Event * event) { - SDL_JoyAxisEvent * jaxis = NULL; - SDL_JoyButtonEvent * jbutton = NULL; - Bitu but = 0; - - switch(event->type) { - case SDL_JOYAXISMOTION: - jaxis = &event->jaxis; - if(jaxis->which == stick && jaxis->axis < 4) { - if(jaxis->axis & 1) - JOYSTICK_Move_Y(jaxis->axis>>1 & 1,(float)(jaxis->value/32768.0)); - else - JOYSTICK_Move_X(jaxis->axis>>1 & 1,(float)(jaxis->value/32768.0)); - } - break; - case SDL_JOYBUTTONDOWN: - case SDL_JOYBUTTONUP: - jbutton = &event->jbutton; - bool state; - state=jbutton->type==SDL_JOYBUTTONDOWN; - but = jbutton->button % emulated_buttons; - if (jbutton->which == stick) { - JOYSTICK_Button((but >> 1),(but & 1),state); - } - break; - } - return false; - } - - virtual void UpdateJoystick() { - /* query SDL joystick and activate bindings */ - ActivateJoystickBoundEvents(); - - bool button_pressed[MAXBUTTON]; - Bitu i; - for (i=0; i>1,i&1,(++button_autofire[i])&1); - else - JOYSTICK_Button(i>>1,i&1,button_pressed[i]); - } - - JOYSTICK_Move_X(0,((float)virtual_joysticks[0].axis_pos[0])/32768.0f); - JOYSTICK_Move_Y(0,((float)virtual_joysticks[0].axis_pos[1])/32768.0f); - JOYSTICK_Move_X(1,((float)virtual_joysticks[0].axis_pos[2])/32768.0f); - JOYSTICK_Move_Y(1,((float)virtual_joysticks[0].axis_pos[3])/32768.0f); - } -}; - -class CFCSBindGroup : public CStickBindGroup { -public: - CFCSBindGroup(Bitu _stick,Bitu _emustick) : CStickBindGroup (_stick,_emustick){ - emulated_axes=4; - emulated_buttons=4; - old_hat_position=0; - emulated_hats=1; - if (button_wrapping_enabled) button_wrap=emulated_buttons; - - axes_cap=emulated_axes; - if (axes_cap>axes) axes_cap=axes; - hats_cap=emulated_hats; - if (hats_cap>hats) hats_cap=hats; - - JOYSTICK_Enable(1,true); - JOYSTICK_Move_Y(1,1.0); - } - - bool CheckEvent(SDL_Event * event) { - SDL_JoyAxisEvent * jaxis = NULL; - SDL_JoyButtonEvent * jbutton = NULL; - SDL_JoyHatEvent * jhat = NULL; - Bitu but = 0; - - switch(event->type) { - case SDL_JOYAXISMOTION: - jaxis = &event->jaxis; - if(jaxis->which == stick) { - if(jaxis->axis == 0) - JOYSTICK_Move_X(0,(float)(jaxis->value/32768.0)); - else if(jaxis->axis == 1) - JOYSTICK_Move_Y(0,(float)(jaxis->value/32768.0)); - else if(jaxis->axis == 2) - JOYSTICK_Move_X(1,(float)(jaxis->value/32768.0)); - } - break; - case SDL_JOYHATMOTION: - jhat = &event->jhat; - if(jhat->which == stick) DecodeHatPosition(jhat->value); - break; - case SDL_JOYBUTTONDOWN: - case SDL_JOYBUTTONUP: - jbutton = &event->jbutton; - bool state; - state=jbutton->type==SDL_JOYBUTTONDOWN; - but = jbutton->button % emulated_buttons; - if (jbutton->which == stick) { - JOYSTICK_Button((but >> 1),(but & 1),state); - } - break; - } - return false; - } - - virtual void UpdateJoystick() { - /* query SDL joystick and activate bindings */ - ActivateJoystickBoundEvents(); - - bool button_pressed[MAXBUTTON]; - Bitu i; - for (i=0; i>1,i&1,(++button_autofire[i])&1); - else - JOYSTICK_Button(i>>1,i&1,button_pressed[i]); - } - - JOYSTICK_Move_X(0,((float)virtual_joysticks[0].axis_pos[0])/32768.0f); - JOYSTICK_Move_Y(0,((float)virtual_joysticks[0].axis_pos[1])/32768.0f); - JOYSTICK_Move_X(1,((float)virtual_joysticks[0].axis_pos[2])/32768.0f); - - Uint8 hat_pos=0; - if (virtual_joysticks[0].hat_pressed[0]) hat_pos|=SDL_HAT_UP; - else if (virtual_joysticks[0].hat_pressed[2]) hat_pos|=SDL_HAT_DOWN; - if (virtual_joysticks[0].hat_pressed[3]) hat_pos|=SDL_HAT_LEFT; - else if (virtual_joysticks[0].hat_pressed[1]) hat_pos|=SDL_HAT_RIGHT; - - if (hat_pos!=old_hat_position) { - DecodeHatPosition(hat_pos); - old_hat_position=hat_pos; - } - } - -private: - Uint8 old_hat_position; - - void DecodeHatPosition(Uint8 hat_pos) { - switch(hat_pos) { - case SDL_HAT_CENTERED: - JOYSTICK_Move_Y(1,1.0); - break; - case SDL_HAT_UP: - JOYSTICK_Move_Y(1,-1.0); - break; - case SDL_HAT_RIGHT: - JOYSTICK_Move_Y(1,-0.5); - break; - case SDL_HAT_DOWN: - JOYSTICK_Move_Y(1,0.0); - break; - case SDL_HAT_LEFT: - JOYSTICK_Move_Y(1,0.5); - break; - case SDL_HAT_LEFTUP: - if(JOYSTICK_GetMove_Y(1) < 0) - JOYSTICK_Move_Y(1,0.5); - else - JOYSTICK_Move_Y(1,-1.0); - break; - case SDL_HAT_RIGHTUP: - if(JOYSTICK_GetMove_Y(1) < -0.7) - JOYSTICK_Move_Y(1,-0.5); - else - JOYSTICK_Move_Y(1,-1.0); - break; - case SDL_HAT_RIGHTDOWN: - if(JOYSTICK_GetMove_Y(1) < -0.2) - JOYSTICK_Move_Y(1,0.0); - else - JOYSTICK_Move_Y(1,-0.5); - break; - case SDL_HAT_LEFTDOWN: - if(JOYSTICK_GetMove_Y(1) > 0.2) - JOYSTICK_Move_Y(1,0.0); - else - JOYSTICK_Move_Y(1,0.5); - break; - } - } -}; - -class CCHBindGroup : public CStickBindGroup { -public: - CCHBindGroup(Bitu _stick,Bitu _emustick) : CStickBindGroup (_stick,_emustick){ - emulated_axes=4; - emulated_buttons=6; - emulated_hats=1; - if (button_wrapping_enabled) button_wrap=emulated_buttons; - - axes_cap=emulated_axes; - if (axes_cap>axes) axes_cap=axes; - hats_cap=emulated_hats; - if (hats_cap>hats) hats_cap=hats; - - JOYSTICK_Enable(1,true); - button_state=0; - } - - bool CheckEvent(SDL_Event * event) { - SDL_JoyAxisEvent * jaxis = NULL; - SDL_JoyButtonEvent * jbutton = NULL; - SDL_JoyHatEvent * jhat = NULL; - Bitu but = 0; - static unsigned const button_magic[6]={0x02,0x04,0x10,0x100,0x20,0x200}; - static unsigned const hat_magic[2][5]={{0x8888,0x8000,0x800,0x80,0x08}, - {0x5440,0x4000,0x400,0x40,0x1000}}; - switch(event->type) { - case SDL_JOYAXISMOTION: - jaxis = &event->jaxis; - if(jaxis->which == stick && jaxis->axis < 4) { - if(jaxis->axis & 1) - JOYSTICK_Move_Y(jaxis->axis>>1 & 1,(float)(jaxis->value/32768.0)); - else - JOYSTICK_Move_X(jaxis->axis>>1 & 1,(float)(jaxis->value/32768.0)); - } - break; - case SDL_JOYHATMOTION: - jhat = &event->jhat; - if(jhat->which == stick && jhat->hat < 2) { - if(jhat->value == SDL_HAT_CENTERED) - button_state&=~hat_magic[jhat->hat][0]; - if(jhat->value & SDL_HAT_UP) - button_state|=hat_magic[jhat->hat][1]; - if(jhat->value & SDL_HAT_RIGHT) - button_state|=hat_magic[jhat->hat][2]; - if(jhat->value & SDL_HAT_DOWN) - button_state|=hat_magic[jhat->hat][3]; - if(jhat->value & SDL_HAT_LEFT) - button_state|=hat_magic[jhat->hat][4]; - } - break; - case SDL_JOYBUTTONDOWN: - jbutton = &event->jbutton; - but = jbutton->button % emulated_buttons; - if (jbutton->which == stick) - button_state|=button_magic[but]; - break; - case SDL_JOYBUTTONUP: - jbutton = &event->jbutton; - but = jbutton->button % emulated_buttons; - if (jbutton->which == stick) - button_state&=~button_magic[but]; - break; - } - - unsigned i; - Bit16u j; - j=button_state; - for(i=0;i<16;i++) if (j & 1) break; else j>>=1; - JOYSTICK_Button(0,0,i&1); - JOYSTICK_Button(0,1,(i>>1)&1); - JOYSTICK_Button(1,0,(i>>2)&1); - JOYSTICK_Button(1,1,(i>>3)&1); - return false; - } - - void UpdateJoystick() { - static unsigned const button_priority[6]={7,11,13,14,5,6}; - static unsigned const hat_priority[2][4]={{0,1,2,3},{8,9,10,12}}; - - /* query SDL joystick and activate bindings */ - ActivateJoystickBoundEvents(); - - JOYSTICK_Move_X(0,((float)virtual_joysticks[0].axis_pos[0])/32768.0f); - JOYSTICK_Move_Y(0,((float)virtual_joysticks[0].axis_pos[1])/32768.0f); - JOYSTICK_Move_X(1,((float)virtual_joysticks[0].axis_pos[2])/32768.0f); - JOYSTICK_Move_Y(1,((float)virtual_joysticks[0].axis_pos[3])/32768.0f); - - Bitu bt_state=15; - - Bitu i; - for (i=0; i<(hats<2?hats:2); i++) { - Uint8 hat_pos=0; - if (virtual_joysticks[0].hat_pressed[(i<<2)+0]) hat_pos|=SDL_HAT_UP; - else if (virtual_joysticks[0].hat_pressed[(i<<2)+2]) hat_pos|=SDL_HAT_DOWN; - if (virtual_joysticks[0].hat_pressed[(i<<2)+3]) hat_pos|=SDL_HAT_LEFT; - else if (virtual_joysticks[0].hat_pressed[(i<<2)+1]) hat_pos|=SDL_HAT_RIGHT; - - if (hat_pos & SDL_HAT_UP) - if (bt_state>hat_priority[i][0]) bt_state=hat_priority[i][0]; - if (hat_pos & SDL_HAT_DOWN) - if (bt_state>hat_priority[i][1]) bt_state=hat_priority[i][1]; - if (hat_pos & SDL_HAT_RIGHT) - if (bt_state>hat_priority[i][2]) bt_state=hat_priority[i][2]; - if (hat_pos & SDL_HAT_LEFT) - if (bt_state>hat_priority[i][3]) bt_state=hat_priority[i][3]; - } - - bool button_pressed[MAXBUTTON]; - for (i=0; ibutton_priority[i])) - bt_state=button_priority[i]; - } - - if (bt_state>15) bt_state=15; - JOYSTICK_Button(0,0,(bt_state&8)==0); - JOYSTICK_Button(0,1,(bt_state&4)==0); - JOYSTICK_Button(1,0,(bt_state&2)==0); - JOYSTICK_Button(1,1,(bt_state&1)==0); - } - -protected: - Bit16u button_state; -}; - -static struct CMapper { - SDL_Surface * surface; - SDL_Surface * draw_surface; - bool exit; - CEvent * aevent; //Active Event - CBind * abind; //Active Bind - CBindList_it abindit; //Location of active bind in list - bool redraw; - bool addbind; - Bitu mods; - struct { - Bitu num_groups,num; - CStickBindGroup * stick[MAXSTICKS]; - } sticks; - std::string filename; -} mapper; - -void CBindGroup::ActivateBindList(CBindList * list,Bits value,bool ev_trigger) { - Bitu validmod=0; - CBindList_it it; - for (it=list->begin();it!=list->end();it++) { - if (((*it)->mods & mapper.mods) == (*it)->mods) { - if (validmod<(*it)->mods) validmod=(*it)->mods; - } - } - for (it=list->begin();it!=list->end();it++) { - /*BUG:CRASH if keymapper key is removed*/ - if (validmod==(*it)->mods) (*it)->ActivateBind(value,ev_trigger); - } -} - -void CBindGroup::DeactivateBindList(CBindList * list,bool ev_trigger) { - CBindList_it it; - for (it=list->begin();it!=list->end();it++) { - (*it)->DeActivateBind(ev_trigger); - } -} - -static void DrawText(Bitu x,Bitu y,const char * text,Bit8u color) { - Bit8u * draw=((Bit8u *)mapper.surface->pixels)+(y*mapper.surface->pitch)+x; - while (*text) { - Bit8u * font=&int10_font_14[(*text)*14]; - Bitu i,j;Bit8u * draw_line=draw; - for (i=0;i<14;i++) { - Bit8u map=*font++; - for (j=0;j<8;j++) { - if (map & 0x80) *(draw_line+j)=color; - else *(draw_line+j)=CLR_BLACK; - map<<=1; - } - draw_line+=mapper.surface->pitch; - } - text++;draw+=8; - } -} - -class CButton { -public: - virtual ~CButton(){}; - CButton(Bitu _x,Bitu _y,Bitu _dx,Bitu _dy) { - x=_x;y=_y;dx=_dx;dy=_dy; - buttons.push_back(this); - color=CLR_WHITE; - enabled=true; - } - virtual void Draw(void) { - if (!enabled) return; - Bit8u * point=((Bit8u *)mapper.surface->pixels)+(y*mapper.surface->pitch)+x; - for (Bitu lines=0;linespitch; - } - } - virtual bool OnTop(Bitu _x,Bitu _y) { - return ( enabled && (_x>=x) && (_x=y) && (_ySetColor(CLR_WHITE); - this->SetColor(CLR_GREEN); - SetActiveEvent(event); - last_clicked=this; - } -protected: - CEvent * event; -}; - -class CCaptionButton : public CButton { -public: - CCaptionButton(Bitu _x,Bitu _y,Bitu _dx,Bitu _dy) : CButton(_x,_y,_dx,_dy){ - caption[0]=0; - } - void Change(const char * format,...) GCC_ATTRIBUTE(__format__(__printf__,2,3)); - - void Draw(void) { - if (!enabled) return; - DrawText(x+2,y+2,caption,color); - } -protected: - char caption[128]; -}; - -void CCaptionButton::Change(const char * format,...) { - va_list msg; - va_start(msg,format); - vsprintf(caption,format,msg); - va_end(msg); - mapper.redraw=true; -} - -static void change_action_text(const char* text,Bit8u col); - -static void MAPPER_SaveBinds(void); -class CBindButton : public CTextButton { -public: - CBindButton(Bitu _x,Bitu _y,Bitu _dx,Bitu _dy,const char * _text,BB_Types _type) - : CTextButton(_x,_y,_dx,_dy,_text) { - type=_type; - } - void Click(void) { - switch (type) { - case BB_Add: - mapper.addbind=true; - SetActiveBind(0); - change_action_text("Press a key/joystick button or move the joystick.",CLR_RED); - break; - case BB_Del: - if (mapper.abindit!=mapper.aevent->bindlist.end()) { - delete (*mapper.abindit); - mapper.abindit=mapper.aevent->bindlist.erase(mapper.abindit); - if (mapper.abindit==mapper.aevent->bindlist.end()) - mapper.abindit=mapper.aevent->bindlist.begin(); - } - if (mapper.abindit!=mapper.aevent->bindlist.end()) SetActiveBind(*(mapper.abindit)); - else SetActiveBind(0); - break; - case BB_Next: - if (mapper.abindit!=mapper.aevent->bindlist.end()) - mapper.abindit++; - if (mapper.abindit==mapper.aevent->bindlist.end()) - mapper.abindit=mapper.aevent->bindlist.begin(); - SetActiveBind(*(mapper.abindit)); - break; - case BB_Save: - MAPPER_SaveBinds(); - break; - case BB_Exit: - mapper.exit=true; - break; - } - } -protected: - BB_Types type; -}; - -class CCheckButton : public CTextButton { -public: - CCheckButton(Bitu _x,Bitu _y,Bitu _dx,Bitu _dy,const char * _text,BC_Types _type) - : CTextButton(_x,_y,_dx,_dy,_text) { - type=_type; - } - void Draw(void) { - if (!enabled) return; - bool checked=false; - switch (type) { - case BC_Mod1: - checked=(mapper.abind->mods&BMOD_Mod1)>0; - break; - case BC_Mod2: - checked=(mapper.abind->mods&BMOD_Mod2)>0; - break; - case BC_Mod3: - checked=(mapper.abind->mods&BMOD_Mod3)>0; - break; - case BC_Hold: - checked=(mapper.abind->flags&BFLG_Hold)>0; - break; - } - if (checked) { - Bit8u * point=((Bit8u *)mapper.surface->pixels)+((y+2)*mapper.surface->pitch)+x+dx-dy+2; - for (Bitu lines=0;lines<(dy-4);lines++) { - memset(point,color,dy-4); - point+=mapper.surface->pitch; - } - } - CTextButton::Draw(); - } - void Click(void) { - switch (type) { - case BC_Mod1: - mapper.abind->mods^=BMOD_Mod1; - break; - case BC_Mod2: - mapper.abind->mods^=BMOD_Mod2; - break; - case BC_Mod3: - mapper.abind->mods^=BMOD_Mod3; - break; - case BC_Hold: - mapper.abind->flags^=BFLG_Hold; - break; - } - mapper.redraw=true; - } -protected: - BC_Types type; -}; - -class CKeyEvent : public CTriggeredEvent { -public: - CKeyEvent(char const * const _entry,KBD_KEYS _key) : CTriggeredEvent(_entry) { - key=_key; - } - void Active(bool yesno) { - KEYBOARD_AddKey(key,yesno); - }; - KBD_KEYS key; -}; - -class CJAxisEvent : public CContinuousEvent { -public: - CJAxisEvent(char const * const _entry,Bitu _stick,Bitu _axis,bool _positive,CJAxisEvent * _opposite_axis) : CContinuousEvent(_entry) { - stick=_stick; - axis=_axis; - positive=_positive; - opposite_axis=_opposite_axis; - if (_opposite_axis) { - _opposite_axis->SetOppositeAxis(this); - } - } - void Active(bool /*moved*/) { - virtual_joysticks[stick].axis_pos[axis]=(Bit16s)(GetValue()*(positive?1:-1)); - } - virtual Bitu GetActivityCount(void) { - return activity|opposite_axis->activity; - } - virtual void RepostActivity(void) { - /* caring for joystick movement into the opposite direction */ - opposite_axis->Active(true); - } -protected: - void SetOppositeAxis(CJAxisEvent * _opposite_axis) { - opposite_axis=_opposite_axis; - } - Bitu stick,axis; - bool positive; - CJAxisEvent * opposite_axis; -}; - -class CJButtonEvent : public CTriggeredEvent { -public: - CJButtonEvent(char const * const _entry,Bitu _stick,Bitu _button) : CTriggeredEvent(_entry) { - stick=_stick; - button=_button; - } - void Active(bool pressed) { - virtual_joysticks[stick].button_pressed[button]=pressed; - } -protected: - Bitu stick,button; -}; - -class CJHatEvent : public CTriggeredEvent { -public: - CJHatEvent(char const * const _entry,Bitu _stick,Bitu _hat,Bitu _dir) : CTriggeredEvent(_entry) { - stick=_stick; - hat=_hat; - dir=_dir; - } - void Active(bool pressed) { - virtual_joysticks[stick].hat_pressed[(hat<<2)+dir]=pressed; - } -protected: - Bitu stick,hat,dir; -}; - - -class CModEvent : public CTriggeredEvent { -public: - CModEvent(char const * const _entry,Bitu _wmod) : CTriggeredEvent(_entry) { - wmod=_wmod; - } - void Active(bool yesno) { - if (yesno) mapper.mods|=(1 << (wmod-1)); - else mapper.mods&=~(1 << (wmod-1)); - }; -protected: - Bitu wmod; -}; - -class CHandlerEvent : public CTriggeredEvent { -public: - CHandlerEvent(char const * const _entry,MAPPER_Handler * _handler,MapKeys _key,Bitu _mod,char const * const _buttonname) : CTriggeredEvent(_entry) { - handler=_handler; - defmod=_mod; - defkey=_key; - buttonname=_buttonname; - handlergroup.push_back(this); - } - void Active(bool yesno) { - (*handler)(yesno); - }; - const char * ButtonName(void) { - return buttonname; - } - void MakeDefaultBind(char * buf) { - Bitu key=0; - switch (defkey) { - case MK_f1:case MK_f2:case MK_f3:case MK_f4: - case MK_f5:case MK_f6:case MK_f7:case MK_f8: - case MK_f9:case MK_f10:case MK_f11:case MK_f12: - key=SDLK_F1+(defkey-MK_f1); - break; - case MK_return: - key=SDLK_RETURN; - break; - case MK_kpminus: - key=SDLK_KP_MINUS; - break; - case MK_scrolllock: - key=SDLK_SCROLLOCK; - break; - case MK_pause: - key=SDLK_PAUSE; - break; - case MK_printscreen: - key=SDLK_PRINT; - break; - } - sprintf(buf,"%s \"key %d%s%s%s\"", - entry, - key, - defmod & 1 ? " mod1" : "", - defmod & 2 ? " mod2" : "", - defmod & 4 ? " mod3" : "" - ); - } -protected: - MapKeys defkey; - Bitu defmod; - MAPPER_Handler * handler; -public: - const char * buttonname; -}; - - -static struct { - CCaptionButton * event_title; - CCaptionButton * bind_title; - CCaptionButton * selected; - CCaptionButton * action; - CBindButton * save; - CBindButton * exit; - CBindButton * add; - CBindButton * del; - CBindButton * next; - CCheckButton * mod1,* mod2,* mod3,* hold; -} bind_but; - - -static void change_action_text(const char* text,Bit8u col) { - bind_but.action->Change(text,""); - bind_but.action->SetColor(col); -} - - -static void SetActiveBind(CBind * _bind) { - mapper.abind=_bind; - if (_bind) { - bind_but.bind_title->Enable(true); - char buf[256];_bind->BindName(buf); - bind_but.bind_title->Change("BIND:%s",buf); - bind_but.del->Enable(true); - bind_but.next->Enable(true); - bind_but.mod1->Enable(true); - bind_but.mod2->Enable(true); - bind_but.mod3->Enable(true); - bind_but.hold->Enable(true); - } else { - bind_but.bind_title->Enable(false); - bind_but.del->Enable(false); - bind_but.next->Enable(false); - bind_but.mod1->Enable(false); - bind_but.mod2->Enable(false); - bind_but.mod3->Enable(false); - bind_but.hold->Enable(false); - } -} - -static void SetActiveEvent(CEvent * event) { - mapper.aevent=event; - mapper.redraw=true; - mapper.addbind=false; - bind_but.event_title->Change("EVENT:%s",event ? event->GetName(): "none"); - if (!event) { - change_action_text("Select an event to change.",CLR_WHITE); - bind_but.add->Enable(false); - SetActiveBind(0); - } else { - change_action_text("Select a different event or hit the Add/Del/Next buttons.",CLR_WHITE); - mapper.abindit=event->bindlist.begin(); - if (mapper.abindit!=event->bindlist.end()) { - SetActiveBind(*(mapper.abindit)); - } else SetActiveBind(0); - bind_but.add->Enable(true); - } -} - -static void DrawButtons(void) { - SDL_FillRect(mapper.surface,0,0); - SDL_LockSurface(mapper.surface); - for (CButton_it but_it = buttons.begin();but_it!=buttons.end();but_it++) { - (*but_it)->Draw(); - } - SDL_UnlockSurface(mapper.surface); - SDL_Flip(mapper.surface); -} - -static CKeyEvent * AddKeyButtonEvent(Bitu x,Bitu y,Bitu dx,Bitu dy,char const * const title,char const * const entry,KBD_KEYS key) { - char buf[64]; - strcpy(buf,"key_"); - strcat(buf,entry); - CKeyEvent * event=new CKeyEvent(buf,key); - new CEventButton(x,y,dx,dy,title,event); - return event; -} - -static CJAxisEvent * AddJAxisButton(Bitu x,Bitu y,Bitu dx,Bitu dy,char const * const title,Bitu stick,Bitu axis,bool positive,CJAxisEvent * opposite_axis) { - char buf[64]; - sprintf(buf,"jaxis_%d_%d%s",stick,axis,positive ? "+" : "-"); - CJAxisEvent * event=new CJAxisEvent(buf,stick,axis,positive,opposite_axis); - new CEventButton(x,y,dx,dy,title,event); - return event; -} -static CJAxisEvent * AddJAxisButton_hidden(Bitu stick,Bitu axis,bool positive,CJAxisEvent * opposite_axis) { - char buf[64]; - sprintf(buf,"jaxis_%d_%d%s",stick,axis,positive ? "+" : "-"); - return new CJAxisEvent(buf,stick,axis,positive,opposite_axis); -} - -static void AddJButtonButton(Bitu x,Bitu y,Bitu dx,Bitu dy,char const * const title,Bitu stick,Bitu button) { - char buf[64]; - sprintf(buf,"jbutton_%d_%d",stick,button); - CJButtonEvent * event=new CJButtonEvent(buf,stick,button); - new CEventButton(x,y,dx,dy,title,event); -} -static void AddJButtonButton_hidden(Bitu stick,Bitu button) { - char buf[64]; - sprintf(buf,"jbutton_%d_%d",stick,button); - new CJButtonEvent(buf,stick,button); -} - -static void AddJHatButton(Bitu x,Bitu y,Bitu dx,Bitu dy,char const * const title,Bitu _stick,Bitu _hat,Bitu _dir) { - char buf[64]; - sprintf(buf,"jhat_%d_%d_%d",_stick,_hat,_dir); - CJHatEvent * event=new CJHatEvent(buf,_stick,_hat,_dir); - new CEventButton(x,y,dx,dy,title,event); -} - -static void AddModButton(Bitu x,Bitu y,Bitu dx,Bitu dy,char const * const title,Bitu _mod) { - char buf[64]; - sprintf(buf,"mod_%d",_mod); - CModEvent * event=new CModEvent(buf,_mod); - new CEventButton(x,y,dx,dy,title,event); -} - -struct KeyBlock { - const char * title; - const char * entry; - KBD_KEYS key; -}; -static KeyBlock combo_f[12]={ - {"F1","f1",KBD_f1}, {"F2","f2",KBD_f2}, {"F3","f3",KBD_f3}, - {"F4","f4",KBD_f4}, {"F5","f5",KBD_f5}, {"F6","f6",KBD_f6}, - {"F7","f7",KBD_f7}, {"F8","f8",KBD_f8}, {"F9","f9",KBD_f9}, - {"F10","f10",KBD_f10}, {"F11","f11",KBD_f11}, {"F12","f12",KBD_f12}, -}; - -static KeyBlock combo_1[14]={ - {"`~","grave",KBD_grave}, {"1!","1",KBD_1}, {"2@","2",KBD_2}, - {"3#","3",KBD_3}, {"4$","4",KBD_4}, {"5%","5",KBD_5}, - {"6^","6",KBD_6}, {"7&","7",KBD_7}, {"8*","8",KBD_8}, - {"9(","9",KBD_9}, {"0)","0",KBD_0}, {"-_","minus",KBD_minus}, - {"=+","equals",KBD_equals}, {"\x1B","bspace",KBD_backspace}, -}; - -static KeyBlock combo_2[12]={ - {"q","q",KBD_q}, {"w","w",KBD_w}, {"e","e",KBD_e}, - {"r","r",KBD_r}, {"t","t",KBD_t}, {"y","y",KBD_y}, - {"u","u",KBD_u}, {"i","i",KBD_i}, {"o","o",KBD_o}, - {"p","p",KBD_p}, {"[","lbracket",KBD_leftbracket}, - {"]","rbracket",KBD_rightbracket}, -}; - -static KeyBlock combo_3[12]={ - {"a","a",KBD_a}, {"s","s",KBD_s}, {"d","d",KBD_d}, - {"f","f",KBD_f}, {"g","g",KBD_g}, {"h","h",KBD_h}, - {"j","j",KBD_j}, {"k","k",KBD_k}, {"l","l",KBD_l}, - {";","semicolon",KBD_semicolon}, {"'","quote",KBD_quote}, - {"\\","backslash",KBD_backslash}, -}; - -static KeyBlock combo_4[11]={ - {"<","lessthan",KBD_extra_lt_gt}, - {"z","z",KBD_z}, {"x","x",KBD_x}, {"c","c",KBD_c}, - {"v","v",KBD_v}, {"b","b",KBD_b}, {"n","n",KBD_n}, - {"m","m",KBD_m}, {",","comma",KBD_comma}, - {".","period",KBD_period}, {"/","slash",KBD_slash}, -}; - -static CKeyEvent * caps_lock_event=NULL; -static CKeyEvent * num_lock_event=NULL; - -static void CreateLayout(void) { - Bitu i; - /* Create the buttons for the Keyboard */ -#define BW 28 -#define BH 20 -#define DX 5 -#define PX(_X_) ((_X_)*BW + DX) -#define PY(_Y_) (30+(_Y_)*BH) - AddKeyButtonEvent(PX(0),PY(0),BW,BH,"ESC","esc",KBD_esc); - for (i=0;i<12;i++) AddKeyButtonEvent(PX(2+i),PY(0),BW,BH,combo_f[i].title,combo_f[i].entry,combo_f[i].key); - for (i=0;i<14;i++) AddKeyButtonEvent(PX( i),PY(1),BW,BH,combo_1[i].title,combo_1[i].entry,combo_1[i].key); - - AddKeyButtonEvent(PX(0),PY(2),BW*2,BH,"TAB","tab",KBD_tab); - for (i=0;i<12;i++) AddKeyButtonEvent(PX(2+i),PY(2),BW,BH,combo_2[i].title,combo_2[i].entry,combo_2[i].key); - - AddKeyButtonEvent(PX(14),PY(2),BW*2,BH*2,"ENTER","enter",KBD_enter); - - caps_lock_event=AddKeyButtonEvent(PX(0),PY(3),BW*2,BH,"CLCK","capslock",KBD_capslock); - for (i=0;i<12;i++) AddKeyButtonEvent(PX(2+i),PY(3),BW,BH,combo_3[i].title,combo_3[i].entry,combo_3[i].key); - - AddKeyButtonEvent(PX(0),PY(4),BW*2,BH,"SHIFT","lshift",KBD_leftshift); - for (i=0;i<11;i++) AddKeyButtonEvent(PX(2+i),PY(4),BW,BH,combo_4[i].title,combo_4[i].entry,combo_4[i].key); - AddKeyButtonEvent(PX(13),PY(4),BW*3,BH,"SHIFT","rshift",KBD_rightshift); - - /* Last Row */ - AddKeyButtonEvent(PX(0) ,PY(5),BW*2,BH,"CTRL","lctrl",KBD_leftctrl); - AddKeyButtonEvent(PX(3) ,PY(5),BW*2,BH,"ALT","lalt",KBD_leftalt); - AddKeyButtonEvent(PX(5) ,PY(5),BW*6,BH,"SPACE","space",KBD_space); - AddKeyButtonEvent(PX(11),PY(5),BW*2,BH,"ALT","ralt",KBD_rightalt); - AddKeyButtonEvent(PX(14),PY(5),BW*2,BH,"CTRL","rctrl",KBD_rightctrl); - - /* Arrow Keys */ - AddKeyButtonEvent(PX(0),PY(7),BW,BH,"PRT","printscreen",KBD_printscreen); - AddKeyButtonEvent(PX(1),PY(7),BW,BH,"SCL","scrolllock",KBD_scrolllock); - AddKeyButtonEvent(PX(2),PY(7),BW,BH,"PAU","pause",KBD_pause); - AddKeyButtonEvent(PX(0),PY(8),BW,BH,"INS","insert",KBD_insert); - AddKeyButtonEvent(PX(1),PY(8),BW,BH,"HOM","home",KBD_home); - AddKeyButtonEvent(PX(2),PY(8),BW,BH,"PUP","pageup",KBD_pageup); - AddKeyButtonEvent(PX(0),PY(9),BW,BH,"DEL","delete",KBD_delete); - AddKeyButtonEvent(PX(1),PY(9),BW,BH,"END","end",KBD_end); - AddKeyButtonEvent(PX(2),PY(9),BW,BH,"PDN","pagedown",KBD_pagedown); - AddKeyButtonEvent(PX(1),PY(10),BW,BH,"\x18","up",KBD_up); - AddKeyButtonEvent(PX(0),PY(11),BW,BH,"\x1B","left",KBD_left); - AddKeyButtonEvent(PX(1),PY(11),BW,BH,"\x19","down",KBD_down); - AddKeyButtonEvent(PX(2),PY(11),BW,BH,"\x1A","right",KBD_right); - - /* Numeric KeyPad */ - num_lock_event=AddKeyButtonEvent(PX(4),PY(7),BW,BH,"NUM","numlock",KBD_numlock); - AddKeyButtonEvent(PX(5),PY(7),BW,BH,"/","kp_divide",KBD_kpdivide); - AddKeyButtonEvent(PX(6),PY(7),BW,BH,"*","kp_multiply",KBD_kpmultiply); - AddKeyButtonEvent(PX(7),PY(7),BW,BH,"-","kp_minus",KBD_kpminus); - AddKeyButtonEvent(PX(4),PY(8),BW,BH,"7","kp_7",KBD_kp7); - AddKeyButtonEvent(PX(5),PY(8),BW,BH,"8","kp_8",KBD_kp8); - AddKeyButtonEvent(PX(6),PY(8),BW,BH,"9","kp_9",KBD_kp9); - AddKeyButtonEvent(PX(7),PY(8),BW,BH*2,"+","kp_plus",KBD_kpplus); - AddKeyButtonEvent(PX(4),PY(9),BW,BH,"4","kp_4",KBD_kp4); - AddKeyButtonEvent(PX(5),PY(9),BW,BH,"5","kp_5",KBD_kp5); - AddKeyButtonEvent(PX(6),PY(9),BW,BH,"6","kp_6",KBD_kp6); - AddKeyButtonEvent(PX(4),PY(10),BW,BH,"1","kp_1",KBD_kp1); - AddKeyButtonEvent(PX(5),PY(10),BW,BH,"2","kp_2",KBD_kp2); - AddKeyButtonEvent(PX(6),PY(10),BW,BH,"3","kp_3",KBD_kp3); - AddKeyButtonEvent(PX(7),PY(10),BW,BH*2,"ENT","kp_enter",KBD_kpenter); - AddKeyButtonEvent(PX(4),PY(11),BW*2,BH,"0","kp_0",KBD_kp0); - AddKeyButtonEvent(PX(6),PY(11),BW,BH,".","kp_period",KBD_kpperiod); - - /* Joystick Buttons/Texts */ - /* Buttons 1+2 of 1st Joystick */ - AddJButtonButton(PX(18),PY(0),BW,BH,"1" ,0,0); - AddJButtonButton(PX(20),PY(0),BW,BH,"2" ,0,1); - /* Axes 1+2 (X+Y) of 1st Joystick */ - CJAxisEvent * cjaxis=AddJAxisButton(PX(19),PY(0),BW,BH,"Y-",0,1,false,NULL); - AddJAxisButton (PX(19),PY(1),BW,BH,"Y+",0,1,true,cjaxis); - cjaxis=AddJAxisButton (PX(18),PY(1),BW,BH,"X-",0,0,false,NULL); - AddJAxisButton (PX(20),PY(1),BW,BH,"X+",0,0,true,cjaxis); - - if (joytype==JOY_2AXIS) { - /* Buttons 1+2 of 2nd Joystick */ - AddJButtonButton(PX(18),PY(3),BW,BH,"1" ,1,0); - AddJButtonButton(PX(20),PY(3),BW,BH,"2" ,1,1); - /* Buttons 3+4 of 1st Joystick, not accessible */ - AddJButtonButton_hidden(0,2); - AddJButtonButton_hidden(0,3); - - /* Axes 1+2 (X+Y) of 2nd Joystick */ - cjaxis= AddJAxisButton(PX(18),PY(4),BW,BH,"X-",1,0,false,NULL); - AddJAxisButton(PX(20),PY(4),BW,BH,"X+",1,0,true,cjaxis); - cjaxis= AddJAxisButton(PX(19),PY(3),BW,BH,"Y-",1,1,false,NULL); - AddJAxisButton(PX(19),PY(4),BW,BH,"Y+",1,1,true,cjaxis); - /* Axes 3+4 (X+Y) of 1st Joystick, not accessible */ - cjaxis= AddJAxisButton_hidden(0,2,false,NULL); - AddJAxisButton_hidden(0,2,true,cjaxis); - cjaxis= AddJAxisButton_hidden(0,3,false,NULL); - AddJAxisButton_hidden(0,3,true,cjaxis); - } else { - /* Buttons 3+4 of 1st Joystick */ - AddJButtonButton(PX(18),PY(3),BW,BH,"3" ,0,2); - AddJButtonButton(PX(20),PY(3),BW,BH,"4" ,0,3); - /* Buttons 1+2 of 2nd Joystick, not accessible */ - AddJButtonButton_hidden(1,0); - AddJButtonButton_hidden(1,1); - - /* Axes 3+4 (X+Y) of 1st Joystick */ - cjaxis= AddJAxisButton(PX(18),PY(4),BW,BH,"X-",0,2,false,NULL); - AddJAxisButton(PX(20),PY(4),BW,BH,"X+",0,2,true,cjaxis); - cjaxis= AddJAxisButton(PX(19),PY(3),BW,BH,"Y-",0,3,false,NULL); - AddJAxisButton(PX(19),PY(4),BW,BH,"Y+",0,3,true,cjaxis); - /* Axes 1+2 (X+Y) of 2nd Joystick , not accessible*/ - cjaxis= AddJAxisButton_hidden(1,0,false,NULL); - AddJAxisButton_hidden(1,0,true,cjaxis); - cjaxis= AddJAxisButton_hidden(1,1,false,NULL); - AddJAxisButton_hidden(1,1,true,cjaxis); - } - - if (joytype==JOY_CH) { - /* Buttons 5+6 of 1st Joystick */ - AddJButtonButton(PX(18),PY(6),BW,BH,"5" ,0,4); - AddJButtonButton(PX(20),PY(6),BW,BH,"6" ,0,5); - } else { - /* Buttons 5+6 of 1st Joystick, not accessible */ - AddJButtonButton_hidden(0,4); - AddJButtonButton_hidden(0,5); - } - - /* Hat directions up, left, down, right */ - AddJHatButton(PX(19),PY(6),BW,BH,"UP",0,0,0); - AddJHatButton(PX(18),PY(7),BW,BH,"LFT",0,0,3); - AddJHatButton(PX(19),PY(7),BW,BH,"DWN",0,0,2); - AddJHatButton(PX(20),PY(7),BW,BH,"RGT",0,0,1); - - /* The modifier buttons */ - AddModButton(PX(0),PY(13),50,20,"Mod1",1); - AddModButton(PX(2),PY(13),50,20,"Mod2",2); - AddModButton(PX(4),PY(13),50,20,"Mod3",3); - /* Create Handler buttons */ - Bitu xpos=3;Bitu ypos=10; - for (CHandlerEventVector_it hit=handlergroup.begin();hit!=handlergroup.end();hit++) { - new CEventButton(PX(xpos*3),PY(ypos),BW*3,BH,(*hit)->ButtonName(),(*hit)); - xpos++; - if (xpos>6) { - xpos=3;ypos++; - } - } - /* Create some text buttons */ - new CTextButton(PX(6),0,124,20,"Keyboard Layout"); - new CTextButton(PX(17),0,124,20,"Joystick Layout"); - - bind_but.action=new CCaptionButton(180,330,0,0); - - bind_but.event_title=new CCaptionButton(0,350,0,0); - bind_but.bind_title=new CCaptionButton(0,365,0,0); - - /* Create binding support buttons */ - - bind_but.mod1=new CCheckButton(20,410,60,20, "mod1",BC_Mod1); - bind_but.mod2=new CCheckButton(20,432,60,20, "mod2",BC_Mod2); - bind_but.mod3=new CCheckButton(20,454,60,20, "mod3",BC_Mod3); - bind_but.hold=new CCheckButton(100,410,60,20,"hold",BC_Hold); - - bind_but.next=new CBindButton(250,400,50,20,"Next",BB_Next); - - bind_but.add=new CBindButton(250,380,50,20,"Add",BB_Add); - bind_but.del=new CBindButton(300,380,50,20,"Del",BB_Del); - - bind_but.save=new CBindButton(400,450,50,20,"Save",BB_Save); - bind_but.exit=new CBindButton(450,450,50,20,"Exit",BB_Exit); - - bind_but.bind_title->Change("Bind Title"); -} - -static SDL_Color map_pal[5]={ - {0x00,0x00,0x00,0x00}, //0=black - {0xff,0xff,0xff,0x00}, //1=white - {0xff,0x00,0x00,0x00}, //2=red - {0x10,0x30,0xff,0x00}, //3=blue - {0x00,0xff,0x20,0x00} //4=green -}; - -static void CreateStringBind(char * line) { - line=trim(line); - char * eventname=StripWord(line); - CEvent * event; - for (CEventVector_it ev_it=events.begin();ev_it!=events.end();ev_it++) { - if (!strcasecmp((*ev_it)->GetName(),eventname)) { - event=*ev_it; - goto foundevent; - } - } - LOG_MSG("Can't find matching event for %s",eventname); - return ; -foundevent: - CBind * bind; - for (char * bindline=StripWord(line);*bindline;bindline=StripWord(line)) { - for (CBindGroup_it it=bindgroups.begin();it!=bindgroups.end();it++) { - bind=(*it)->CreateConfigBind(bindline); - if (bind) { - event->AddBind(bind); - bind->SetFlags(bindline); - break; - } - } - } -} - -static struct { - const char * eventend; - Bitu key; -} DefaultKeys[]={ - {"f1",SDLK_F1}, {"f2",SDLK_F2}, {"f3",SDLK_F3}, {"f4",SDLK_F4}, - {"f5",SDLK_F5}, {"f6",SDLK_F6}, {"f7",SDLK_F7}, {"f8",SDLK_F8}, - {"f9",SDLK_F9}, {"f10",SDLK_F10}, {"f11",SDLK_F11}, {"f12",SDLK_F12}, - - {"1",SDLK_1}, {"2",SDLK_2}, {"3",SDLK_3}, {"4",SDLK_4}, - {"5",SDLK_5}, {"6",SDLK_6}, {"7",SDLK_7}, {"8",SDLK_8}, - {"9",SDLK_9}, {"0",SDLK_0}, - - {"a",SDLK_a}, {"b",SDLK_b}, {"c",SDLK_c}, {"d",SDLK_d}, - {"e",SDLK_e}, {"f",SDLK_f}, {"g",SDLK_g}, {"h",SDLK_h}, - {"i",SDLK_i}, {"j",SDLK_j}, {"k",SDLK_k}, {"l",SDLK_l}, - {"m",SDLK_m}, {"n",SDLK_n}, {"o",SDLK_o}, {"p",SDLK_p}, - {"q",SDLK_q}, {"r",SDLK_r}, {"s",SDLK_s}, {"t",SDLK_t}, - {"u",SDLK_u}, {"v",SDLK_v}, {"w",SDLK_w}, {"x",SDLK_x}, - {"y",SDLK_y}, {"z",SDLK_z}, {"space",SDLK_SPACE}, - {"esc",SDLK_ESCAPE}, {"equals",SDLK_EQUALS}, {"grave",SDLK_BACKQUOTE}, - {"tab",SDLK_TAB}, {"enter",SDLK_RETURN}, {"bspace",SDLK_BACKSPACE}, - {"lbracket",SDLK_LEFTBRACKET}, {"rbracket",SDLK_RIGHTBRACKET}, - {"minus",SDLK_MINUS}, {"capslock",SDLK_CAPSLOCK}, {"semicolon",SDLK_SEMICOLON}, - {"quote", SDLK_QUOTE}, {"backslash",SDLK_BACKSLASH}, {"lshift",SDLK_LSHIFT}, - {"rshift",SDLK_RSHIFT}, {"lalt",SDLK_LALT}, {"ralt",SDLK_RALT}, - {"lctrl",SDLK_LCTRL}, {"rctrl",SDLK_RCTRL}, {"comma",SDLK_COMMA}, - {"period",SDLK_PERIOD}, {"slash",SDLK_SLASH}, {"printscreen",SDLK_PRINT}, - {"scrolllock",SDLK_SCROLLOCK}, {"pause",SDLK_PAUSE}, {"pagedown",SDLK_PAGEDOWN}, - {"pageup",SDLK_PAGEUP}, {"insert",SDLK_INSERT}, {"home",SDLK_HOME}, - {"delete",SDLK_DELETE}, {"end",SDLK_END}, {"up",SDLK_UP}, - {"left",SDLK_LEFT}, {"down",SDLK_DOWN}, {"right",SDLK_RIGHT}, - {"kp_0",SDLK_KP0}, {"kp_1",SDLK_KP1}, {"kp_2",SDLK_KP2}, {"kp_3",SDLK_KP3}, - {"kp_4",SDLK_KP4}, {"kp_5",SDLK_KP5}, {"kp_6",SDLK_KP6}, {"kp_7",SDLK_KP7}, - {"kp_8",SDLK_KP8}, {"kp_9",SDLK_KP9}, {"numlock",SDLK_NUMLOCK}, - {"kp_divide",SDLK_KP_DIVIDE}, {"kp_multiply",SDLK_KP_MULTIPLY}, - {"kp_minus",SDLK_KP_MINUS}, {"kp_plus",SDLK_KP_PLUS}, - {"kp_period",SDLK_KP_PERIOD}, {"kp_enter",SDLK_KP_ENTER}, - -#if defined (MACOSX) - /* Intl Mac keyboards in US layout actually put U+00A7 SECTION SIGN here */ - {"lessthan",SDLK_WORLD_0}, -#else - {"lessthan",SDLK_LESS}, -#endif - - {0,0} -}; - -static void CreateDefaultBinds(void) { - char buffer[512]; - Bitu i=0; - while (DefaultKeys[i].eventend) { - sprintf(buffer,"key_%s \"key %d\"",DefaultKeys[i].eventend,DefaultKeys[i].key); - CreateStringBind(buffer); - i++; - } - sprintf(buffer,"mod_1 \"key %d\"",SDLK_RCTRL);CreateStringBind(buffer); - sprintf(buffer,"mod_1 \"key %d\"",SDLK_LCTRL);CreateStringBind(buffer); - sprintf(buffer,"mod_2 \"key %d\"",SDLK_RALT);CreateStringBind(buffer); - sprintf(buffer,"mod_2 \"key %d\"",SDLK_LALT);CreateStringBind(buffer); - for (CHandlerEventVector_it hit=handlergroup.begin();hit!=handlergroup.end();hit++) { - (*hit)->MakeDefaultBind(buffer); - CreateStringBind(buffer); - } - - /* joystick1, buttons 1-6 */ - sprintf(buffer,"jbutton_0_0 \"stick_0 button 0\" ");CreateStringBind(buffer); - sprintf(buffer,"jbutton_0_1 \"stick_0 button 1\" ");CreateStringBind(buffer); - sprintf(buffer,"jbutton_0_2 \"stick_0 button 2\" ");CreateStringBind(buffer); - sprintf(buffer,"jbutton_0_3 \"stick_0 button 3\" ");CreateStringBind(buffer); - sprintf(buffer,"jbutton_0_4 \"stick_0 button 4\" ");CreateStringBind(buffer); - sprintf(buffer,"jbutton_0_5 \"stick_0 button 5\" ");CreateStringBind(buffer); - /* joystick2, buttons 1-2 */ - sprintf(buffer,"jbutton_1_0 \"stick_1 button 0\" ");CreateStringBind(buffer); - sprintf(buffer,"jbutton_1_1 \"stick_1 button 1\" ");CreateStringBind(buffer); - - /* joystick1, axes 1-4 */ - sprintf(buffer,"jaxis_0_0- \"stick_0 axis 0 0\" ");CreateStringBind(buffer); - sprintf(buffer,"jaxis_0_0+ \"stick_0 axis 0 1\" ");CreateStringBind(buffer); - sprintf(buffer,"jaxis_0_1- \"stick_0 axis 1 0\" ");CreateStringBind(buffer); - sprintf(buffer,"jaxis_0_1+ \"stick_0 axis 1 1\" ");CreateStringBind(buffer); - sprintf(buffer,"jaxis_0_2- \"stick_0 axis 2 0\" ");CreateStringBind(buffer); - sprintf(buffer,"jaxis_0_2+ \"stick_0 axis 2 1\" ");CreateStringBind(buffer); - sprintf(buffer,"jaxis_0_3- \"stick_0 axis 3 0\" ");CreateStringBind(buffer); - sprintf(buffer,"jaxis_0_3+ \"stick_0 axis 3 1\" ");CreateStringBind(buffer); - /* joystick2, axes 1-2 */ - sprintf(buffer,"jaxis_1_0- \"stick_1 axis 0 0\" ");CreateStringBind(buffer); - sprintf(buffer,"jaxis_1_0+ \"stick_1 axis 0 1\" ");CreateStringBind(buffer); - sprintf(buffer,"jaxis_1_1- \"stick_1 axis 1 0\" ");CreateStringBind(buffer); - sprintf(buffer,"jaxis_1_1+ \"stick_1 axis 1 1\" ");CreateStringBind(buffer); - - /* joystick1, hat */ - sprintf(buffer,"jhat_0_0_0 \"stick_0 hat 0 1\" ");CreateStringBind(buffer); - sprintf(buffer,"jhat_0_0_1 \"stick_0 hat 0 2\" ");CreateStringBind(buffer); - sprintf(buffer,"jhat_0_0_2 \"stick_0 hat 0 4\" ");CreateStringBind(buffer); - sprintf(buffer,"jhat_0_0_3 \"stick_0 hat 0 8\" ");CreateStringBind(buffer); -} - -void MAPPER_AddHandler(MAPPER_Handler * handler,MapKeys key,Bitu mods,char const * const eventname,char const * const buttonname) { - //Check if it allready exists=> if so return. - for(CHandlerEventVector_it it=handlergroup.begin();it!=handlergroup.end();it++) - if(strcmp((*it)->buttonname,buttonname) == 0) return; - - char tempname[17]; - strcpy(tempname,"hand_"); - strcat(tempname,eventname); - new CHandlerEvent(tempname,handler,key,mods,buttonname); - return ; -} - -static void MAPPER_SaveBinds(void) { - FILE * savefile=fopen(mapper.filename.c_str(),"wb+"); - if (!savefile) { - LOG_MSG("Can't open %s for saving the mappings",mapper.filename.c_str()); - return; - } - char buf[128]; - for (CEventVector_it event_it=events.begin();event_it!=events.end();event_it++) { - CEvent * event=*(event_it); - fprintf(savefile,"%s ",event->GetName()); - for (CBindList_it bind_it=event->bindlist.begin();bind_it!=event->bindlist.end();bind_it++) { - CBind * bind=*(bind_it); - bind->ConfigName(buf); - bind->AddFlags(buf); - fprintf(savefile,"\"%s\" ",buf); - } - fprintf(savefile,"\n"); - } - fclose(savefile); - change_action_text("Mapper file saved.",CLR_WHITE); -} - -static bool MAPPER_LoadBinds(void) { - FILE * loadfile=fopen(mapper.filename.c_str(),"rb"); - if (!loadfile) return false; - char linein[512]; - while (fgets(linein,512,loadfile)) { - CreateStringBind(linein); - } - fclose(loadfile); - LOG_MSG("MAPPER: Loading mapper settings from %s", mapper.filename.c_str()); - return true; -} - -void MAPPER_CheckEvent(SDL_Event * event) { - for (CBindGroup_it it=bindgroups.begin();it!=bindgroups.end();it++) { - if ((*it)->CheckEvent(event)) return; - } -} - -void BIND_MappingEvents(void) { - SDL_Event event; - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_MOUSEBUTTONDOWN: - /* Check the press */ - for (CButton_it but_it = buttons.begin();but_it!=buttons.end();but_it++) { - if ((*but_it)->OnTop(event.button.x,event.button.y)) { - (*but_it)->Click(); - } - } - break; - case SDL_QUIT: - mapper.exit=true; - break; - default: - if (mapper.addbind) for (CBindGroup_it it=bindgroups.begin();it!=bindgroups.end();it++) { - CBind * newbind=(*it)->CreateEventBind(&event); - if (!newbind) continue; - mapper.aevent->AddBind(newbind); - SetActiveEvent(mapper.aevent); - mapper.addbind=false; - break; - } - } - } -} - -static void InitializeJoysticks(void) { - mapper.sticks.num=0; - mapper.sticks.num_groups=0; - if (joytype != JOY_NONE) { - mapper.sticks.num=SDL_NumJoysticks(); - if (joytype==JOY_AUTO) { - // try to figure out what joystick type to select - // depending on the number of physically attached joysticks - if (mapper.sticks.num>1) { - // more than one joystick present; if all are acceptable use 2axis - // to allow emulation of two joysticks - bool first_usable=false; - SDL_Joystick* tmp_stick1=SDL_JoystickOpen(0); - if (tmp_stick1) { - if ((SDL_JoystickNumAxes(tmp_stick1)>1) || (SDL_JoystickNumButtons(tmp_stick1)>0)) { - first_usable=true; - } - SDL_JoystickClose(tmp_stick1); - } - bool second_usable=false; - SDL_Joystick* tmp_stick2=SDL_JoystickOpen(1); - if (tmp_stick2) { - if ((SDL_JoystickNumAxes(tmp_stick2)>1) || (SDL_JoystickNumButtons(tmp_stick2)>0)) { - second_usable=true; - } - SDL_JoystickClose(tmp_stick2); - } - // choose joystick type now that we know which physical joysticks are usable - if (first_usable) { - if (second_usable) { - joytype=JOY_2AXIS; - LOG_MSG("Two or more joysticks reported, initializing with 2axis"); - } else { - joytype=JOY_4AXIS; - LOG_MSG("One joystick reported, initializing with 4axis"); - } - } else if (second_usable) { - joytype=JOY_4AXIS_2; - LOG_MSG("One joystick reported, initializing with 4axis_2"); - } - } else if (mapper.sticks.num) { - // one joystick present; if it is acceptable use 4axis - joytype=JOY_NONE; - SDL_Joystick* tmp_stick1=SDL_JoystickOpen(0); - if (tmp_stick1) { - if ((SDL_JoystickNumAxes(tmp_stick1)>0) || (SDL_JoystickNumButtons(tmp_stick1)>0)) { - joytype=JOY_4AXIS; - LOG_MSG("One joystick reported, initializing with 4axis"); - } - } - } else { - joytype=JOY_NONE; - } - } - } -} - -static void CreateBindGroups(void) { - bindgroups.clear(); - new CKeyBindGroup(SDLK_LAST); - if (joytype != JOY_NONE) { -#if defined (REDUCE_JOYSTICK_POLLING) - // direct access to the SDL joystick, thus removed from the event handling - if (mapper.sticks.num) SDL_JoystickEventState(SDL_DISABLE); -#else - // enable joystick event handling - if (mapper.sticks.num) SDL_JoystickEventState(SDL_ENABLE); - else return; -#endif - Bit8u joyno=0; - switch (joytype) { - case JOY_NONE: - break; - case JOY_4AXIS: - mapper.sticks.stick[mapper.sticks.num_groups++]=new C4AxisBindGroup(joyno,joyno); - new CStickBindGroup(joyno+1U,joyno+1U,true); - break; - case JOY_4AXIS_2: - mapper.sticks.stick[mapper.sticks.num_groups++]=new C4AxisBindGroup(joyno+1U,joyno); - new CStickBindGroup(joyno,joyno+1U,true); - break; - case JOY_FCS: - mapper.sticks.stick[mapper.sticks.num_groups++]=new CFCSBindGroup(joyno,joyno); - new CStickBindGroup(joyno+1U,joyno+1U,true); - break; - case JOY_CH: - mapper.sticks.stick[mapper.sticks.num_groups++]=new CCHBindGroup(joyno,joyno); - new CStickBindGroup(joyno+1U,joyno+1U,true); - break; - case JOY_2AXIS: - default: - mapper.sticks.stick[mapper.sticks.num_groups++]=new CStickBindGroup(joyno,joyno); - if((joyno+1U) < mapper.sticks.num) { - mapper.sticks.stick[mapper.sticks.num_groups++]=new CStickBindGroup(joyno+1U,joyno+1U); - } else { - new CStickBindGroup(joyno+1U,joyno+1U,true); - } - break; - } - } -} - -#if defined (REDUCE_JOYSTICK_POLLING) -void MAPPER_UpdateJoysticks(void) { - for (Bitu i=0; iUpdateJoystick(); - } -} -#endif - -void MAPPER_LosingFocus(void) { - for (CEventVector_it evit=events.begin();evit!=events.end();evit++) { - if(*evit != caps_lock_event && *evit != num_lock_event) - (*evit)->DeActivateAll(); - } -} - -void MAPPER_Run(bool pressed) { - if (pressed) - return; - KEYBOARD_ClrBuffer(); //Clear buffer - GFX_LosingFocus(); //Release any keys pressed (buffer gets filled again). - - int cursor = SDL_ShowCursor(SDL_QUERY); - SDL_ShowCursor(SDL_ENABLE); - bool mousetoggle=false; - if(mouselocked) { - mousetoggle=true; - GFX_CaptureMouse(); - } - - /* Be sure that there is no update in progress */ - GFX_EndUpdate( 0 ); - mapper.surface=SDL_SetVideoMode(640,480,8,0); - if (mapper.surface == NULL) E_Exit("Could not initialize video mode for mapper: %s",SDL_GetError()); - - /* Set some palette entries */ - SDL_SetPalette(mapper.surface, SDL_LOGPAL|SDL_PHYSPAL, map_pal, 0, 5); - if (last_clicked) { - last_clicked->SetColor(CLR_WHITE); - last_clicked=NULL; - } - /* Go in the event loop */ - mapper.exit=false; - mapper.redraw=true; - SetActiveEvent(0); -#if defined (REDUCE_JOYSTICK_POLLING) - SDL_JoystickEventState(SDL_ENABLE); -#endif - while (!mapper.exit) { - if (mapper.redraw) { - mapper.redraw=false; - DrawButtons(); - } - BIND_MappingEvents(); - SDL_Delay(1); - } -#if defined (REDUCE_JOYSTICK_POLLING) - SDL_JoystickEventState(SDL_DISABLE); -#endif - if(mousetoggle) GFX_CaptureMouse(); - SDL_ShowCursor(cursor); - GFX_ResetScreen(); -} - -void MAPPER_Init(void) { - InitializeJoysticks(); - CreateLayout(); - CreateBindGroups(); - if (!MAPPER_LoadBinds()) CreateDefaultBinds(); - if (SDL_GetModState()&KMOD_CAPS) { - for (CBindList_it bit=caps_lock_event->bindlist.begin();bit!=caps_lock_event->bindlist.end();bit++) { - (*bit)->ActivateBind(32767,true,true); - } - } - if (SDL_GetModState()&KMOD_NUM) { - for (CBindList_it bit=num_lock_event->bindlist.begin();bit!=num_lock_event->bindlist.end();bit++) { - (*bit)->ActivateBind(32767,true,true); - } - } -} -//Somehow including them at the top conflicts with something in setup.h -#ifdef LINUX -#include "SDL_syswm.h" -#include -#endif -void MAPPER_StartUp(Section * sec) { - Section_prop * section=static_cast(sec); - mapper.sticks.num=0; - mapper.sticks.num_groups=0; - Bitu i; - for (i=0; i<16; i++) { - virtual_joysticks[0].button_pressed[i]=false; - virtual_joysticks[1].button_pressed[i]=false; - virtual_joysticks[0].hat_pressed[i]=false; - virtual_joysticks[1].hat_pressed[i]=false; - } - for (i=0; i<8; i++) { - virtual_joysticks[0].axis_pos[i]=0; - virtual_joysticks[0].axis_pos[i]=0; - } - - usescancodes = false; - - if (section->Get_bool("usescancodes")) { - usescancodes=true; - - /* Note: table has to be tested/updated for various OSs */ -#if defined (MACOSX) - /* nothing */ -#elif defined(OS2) - sdlkey_map[0x61]=SDLK_UP; - sdlkey_map[0x66]=SDLK_DOWN; - sdlkey_map[0x63]=SDLK_LEFT; - sdlkey_map[0x64]=SDLK_RIGHT; - sdlkey_map[0x60]=SDLK_HOME; - sdlkey_map[0x65]=SDLK_END; - sdlkey_map[0x62]=SDLK_PAGEUP; - sdlkey_map[0x67]=SDLK_PAGEDOWN; - sdlkey_map[0x68]=SDLK_INSERT; - sdlkey_map[0x69]=SDLK_DELETE; - sdlkey_map[0x5C]=SDLK_KP_DIVIDE; - sdlkey_map[0x5A]=SDLK_KP_ENTER; - sdlkey_map[0x5B]=SDLK_RCTRL; - sdlkey_map[0x5F]=SDLK_PAUSE; -// sdlkey_map[0x00]=SDLK_PRINT; - sdlkey_map[0x5E]=SDLK_RALT; - sdlkey_map[0x40]=SDLK_KP5; - sdlkey_map[0x41]=SDLK_KP6; -#elif !defined (WIN32) /* => Linux & BSDs */ - bool evdev_input = false; -#ifdef LINUX - SDL_SysWMinfo info; - SDL_VERSION(&info.version); - if (SDL_GetWMInfo(&info)) { - XkbDescPtr desc = NULL; - if((desc = XkbGetMap(info.info.x11.display,XkbAllComponentsMask,XkbUseCoreKbd))) { - if(XkbGetNames(info.info.x11.display,XkbAllNamesMask,desc) == 0) { - const char* keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes); -// const char* geom = XGetAtomName(info.info.x11.display, desc->names->geometry); - if(keycodes) { - LOG(LOG_MISC,LOG_NORMAL)("keyboard type %s",keycodes); - if (strncmp(keycodes,"evdev",5) == 0) evdev_input = true; - } - XkbFreeNames(desc,XkbAllNamesMask,True); - } - XkbFreeClientMap(desc,0,True); - } - } -#endif - if (evdev_input) { - sdlkey_map[0x67]=SDLK_UP; - sdlkey_map[0x6c]=SDLK_DOWN; - sdlkey_map[0x69]=SDLK_LEFT; - sdlkey_map[0x6a]=SDLK_RIGHT; - sdlkey_map[0x66]=SDLK_HOME; - sdlkey_map[0x6b]=SDLK_END; - sdlkey_map[0x68]=SDLK_PAGEUP; - sdlkey_map[0x6d]=SDLK_PAGEDOWN; - sdlkey_map[0x6e]=SDLK_INSERT; - sdlkey_map[0x6f]=SDLK_DELETE; - sdlkey_map[0x62]=SDLK_KP_DIVIDE; - sdlkey_map[0x60]=SDLK_KP_ENTER; - sdlkey_map[0x61]=SDLK_RCTRL; - sdlkey_map[0x77]=SDLK_PAUSE; - sdlkey_map[0x63]=SDLK_PRINT; - sdlkey_map[0x64]=SDLK_RALT; - } else { - sdlkey_map[0x5a]=SDLK_UP; - sdlkey_map[0x60]=SDLK_DOWN; - sdlkey_map[0x5c]=SDLK_LEFT; - sdlkey_map[0x5e]=SDLK_RIGHT; - sdlkey_map[0x59]=SDLK_HOME; - sdlkey_map[0x5f]=SDLK_END; - sdlkey_map[0x5b]=SDLK_PAGEUP; - sdlkey_map[0x61]=SDLK_PAGEDOWN; - sdlkey_map[0x62]=SDLK_INSERT; - sdlkey_map[0x63]=SDLK_DELETE; - sdlkey_map[0x68]=SDLK_KP_DIVIDE; - sdlkey_map[0x64]=SDLK_KP_ENTER; - sdlkey_map[0x65]=SDLK_RCTRL; - sdlkey_map[0x66]=SDLK_PAUSE; - sdlkey_map[0x67]=SDLK_PRINT; - sdlkey_map[0x69]=SDLK_RALT; - } -#else - sdlkey_map[0xc8]=SDLK_UP; - sdlkey_map[0xd0]=SDLK_DOWN; - sdlkey_map[0xcb]=SDLK_LEFT; - sdlkey_map[0xcd]=SDLK_RIGHT; - sdlkey_map[0xc7]=SDLK_HOME; - sdlkey_map[0xcf]=SDLK_END; - sdlkey_map[0xc9]=SDLK_PAGEUP; - sdlkey_map[0xd1]=SDLK_PAGEDOWN; - sdlkey_map[0xd2]=SDLK_INSERT; - sdlkey_map[0xd3]=SDLK_DELETE; - sdlkey_map[0xb5]=SDLK_KP_DIVIDE; - sdlkey_map[0x9c]=SDLK_KP_ENTER; - sdlkey_map[0x9d]=SDLK_RCTRL; - sdlkey_map[0xc5]=SDLK_PAUSE; - sdlkey_map[0xb7]=SDLK_PRINT; - sdlkey_map[0xb8]=SDLK_RALT; -#endif - - Bitu i; - for (i=0; iGet_path("mapperfile"); - mapper.filename = pp->realpath; - MAPPER_AddHandler(&MAPPER_Run,MK_f1,MMOD1,"mapper","Mapper"); -} - diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 5d1bdc7..08e40d3 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -1,1672 +1,513 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: sdlmain.cpp,v 1.150 2009/02/25 19:58:11 c2woody Exp $ */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include -#include -#include -#include -#include -#include -#ifdef WIN32 -#include -#include -#endif - -#include "SDL.h" - -#include "dosbox.h" -#include "video.h" -#include "mouse.h" -#include "pic.h" -#include "timer.h" -#include "setup.h" -#include "support.h" -#include "debug.h" -#include "mapper.h" -#include "vga.h" -#include "keyboard.h" -#include "cpu.h" -#include "cross.h" -#include "control.h" - -//#define DISABLE_JOYSTICK - -#if C_OPENGL -#include "SDL_opengl.h" - -#ifndef APIENTRY -#define APIENTRY -#endif -#ifndef APIENTRYP -#define APIENTRYP APIENTRY * -#endif - -#ifdef __WIN32__ -#define NVIDIA_PixelDataRange 1 - -#ifndef WGL_NV_allocate_memory -#define WGL_NV_allocate_memory 1 -typedef void * (APIENTRY * PFNWGLALLOCATEMEMORYNVPROC) (int size, float readfreq, float writefreq, float priority); -typedef void (APIENTRY * PFNWGLFREEMEMORYNVPROC) (void *pointer); -#endif - -PFNWGLALLOCATEMEMORYNVPROC db_glAllocateMemoryNV = NULL; -PFNWGLFREEMEMORYNVPROC db_glFreeMemoryNV = NULL; - -#else - -#endif - -#if defined(NVIDIA_PixelDataRange) - -#ifndef GL_NV_pixel_data_range -#define GL_NV_pixel_data_range 1 -#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 -typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer); -typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); -#endif - -PFNGLPIXELDATARANGENVPROC glPixelDataRangeNV = NULL; - -#endif - -#endif //C_OPENGL - -#if !(ENVIRON_INCLUDED) -extern char** environ; -#endif - -#ifdef WIN32 -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#if (HAVE_DDRAW_H) -#include -struct private_hwdata { - LPDIRECTDRAWSURFACE3 dd_surface; - LPDIRECTDRAWSURFACE3 dd_writebuf; -}; -#endif - -#define STDOUT_FILE TEXT("stdout.txt") -#define STDERR_FILE TEXT("stderr.txt") -#define DEFAULT_CONFIG_FILE "/dosbox.conf" -#elif defined(MACOSX) -#define DEFAULT_CONFIG_FILE "/Library/Preferences/DOSBox Preferences" -#else /*linux freebsd*/ -#define DEFAULT_CONFIG_FILE "/.dosboxrc" -#endif - -#if C_SET_PRIORITY -#include -#define PRIO_TOTAL (PRIO_MAX-PRIO_MIN) -#endif - -#ifdef OS2 -#define INCL_DOS -#define INCL_WIN -#include -#endif - -enum SCREEN_TYPES { - SCREEN_SURFACE, - SCREEN_SURFACE_DDRAW, - SCREEN_OVERLAY, - SCREEN_OPENGL -}; - -enum PRIORITY_LEVELS { - PRIORITY_LEVEL_PAUSE, - PRIORITY_LEVEL_LOWEST, - PRIORITY_LEVEL_LOWER, - PRIORITY_LEVEL_NORMAL, - PRIORITY_LEVEL_HIGHER, - PRIORITY_LEVEL_HIGHEST -}; - - -struct SDL_Block { - bool active; //If this isn't set don't draw - bool updating; - struct { - Bit32u width; - Bit32u height; - Bit32u bpp; - Bitu flags; - double scalex,scaley; - GFX_CallBack_t callback; - } draw; - bool wait_on_error; - struct { - struct { - Bit16u width, height; - bool fixed; - } full; - struct { - Bit16u width, height; - } window; - Bit8u bpp; - bool fullscreen; - bool doublebuf; - SCREEN_TYPES type; - SCREEN_TYPES want_type; - } desktop; -#if C_OPENGL - struct { - Bitu pitch; - void * framebuf; - GLuint texture; - GLuint displaylist; - GLint max_texsize; - bool bilinear; - bool packed_pixel; - bool paletted_texture; -#if defined(NVIDIA_PixelDataRange) - bool pixel_data_range; -#endif - } opengl; -#endif - struct { - SDL_Surface * surface; -#if (HAVE_DDRAW_H) && defined(WIN32) - RECT rect; -#endif - } blit; - struct { - PRIORITY_LEVELS focus; - PRIORITY_LEVELS nofocus; - } priority; - SDL_Rect clip; - SDL_Surface * surface; - SDL_Overlay * overlay; - SDL_cond *cond; - struct { - bool autolock; - bool autoenable; - bool requestlock; - bool locked; - Bitu sensitivity; - } mouse; - SDL_Rect updateRects[1024]; - Bitu num_joysticks; -#if defined (WIN32) - bool using_windib; -#endif - // state of alt-keys for certain special handlings - Bit8u laltstate; - Bit8u raltstate; -}; - -static SDL_Block sdl; - -extern const char* RunningProgram; -extern bool CPU_CycleAutoAdjust; -//Globals for keyboard initialisation -bool startup_state_numlock=false; -bool startup_state_capslock=false; -void GFX_SetTitle(Bit32s cycles,Bits frameskip,bool paused){ - char title[200]={0}; - static Bit32s internal_cycles=0; - static Bits internal_frameskip=0; - if(cycles != -1) internal_cycles = cycles; - if(frameskip != -1) internal_frameskip = frameskip; - if(CPU_CycleAutoAdjust) { - if (internal_cycles>=100) - sprintf(title,"DOSBox %s, Cpu Cycles: max, Frameskip %2d, Program: %8s",VERSION,internal_frameskip,RunningProgram); - else - sprintf(title,"DOSBox %s, Cpu Cycles: [%3d%%], Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram); - } else { - sprintf(title,"DOSBox %s, Cpu Cycles: %8d, Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram); - } - - if(paused) strcat(title," PAUSED"); - SDL_WM_SetCaption(title,VERSION); -} - -static void PauseDOSBox(bool pressed) { - if (!pressed) - return; - GFX_SetTitle(-1,-1,true); - bool paused = true; - KEYBOARD_ClrBuffer(); - SDL_Delay(500); - SDL_Event event; - while (SDL_PollEvent(&event)) { - // flush event queue. - } - - while (paused) { - SDL_WaitEvent(&event); // since we're not polling, cpu usage drops to 0. - switch (event.type) { - - case SDL_QUIT: throw(0); break; - case SDL_KEYDOWN: // Must use Pause/Break Key to resume. - case SDL_KEYUP: - if(event.key.keysym.sym==SDLK_PAUSE) { - - paused=false; - GFX_SetTitle(-1,-1,false); - break; - } - } - } -} - -#if defined (WIN32) -bool GFX_SDLUsingWinDIB(void) { - return sdl.using_windib; -} -#endif - -/* Reset the screen with current values in the sdl structure */ -Bitu GFX_GetBestMode(Bitu flags) { - Bitu testbpp,gotbpp; - switch (sdl.desktop.want_type) { - case SCREEN_SURFACE: -check_surface: - /* Check if we can satisfy the depth it loves */ - if (flags & GFX_LOVE_8) testbpp=8; - else if (flags & GFX_LOVE_15) testbpp=15; - else if (flags & GFX_LOVE_16) testbpp=16; - else if (flags & GFX_LOVE_32) testbpp=32; - else testbpp=0; -#if (HAVE_DDRAW_H) && defined(WIN32) -check_gotbpp: -#endif - if (sdl.desktop.fullscreen) gotbpp=SDL_VideoModeOK(640,480,testbpp,SDL_FULLSCREEN|SDL_HWSURFACE|SDL_HWPALETTE); - else gotbpp=sdl.desktop.bpp; - /* If we can't get our favorite mode check for another working one */ - switch (gotbpp) { - case 8: - if (flags & GFX_CAN_8) flags&=~(GFX_CAN_15|GFX_CAN_16|GFX_CAN_32); - break; - case 15: - if (flags & GFX_CAN_15) flags&=~(GFX_CAN_8|GFX_CAN_16|GFX_CAN_32); - break; - case 16: - if (flags & GFX_CAN_16) flags&=~(GFX_CAN_8|GFX_CAN_15|GFX_CAN_32); - break; - case 24: - case 32: - if (flags & GFX_CAN_32) flags&=~(GFX_CAN_8|GFX_CAN_15|GFX_CAN_16); - break; - } - flags |= GFX_CAN_RANDOM; - break; -#if (HAVE_DDRAW_H) && defined(WIN32) - case SCREEN_SURFACE_DDRAW: - if (!(flags&(GFX_CAN_15|GFX_CAN_16|GFX_CAN_32))) goto check_surface; - if (flags & GFX_LOVE_15) testbpp=15; - else if (flags & GFX_LOVE_16) testbpp=16; - else if (flags & GFX_LOVE_32) testbpp=32; - else testbpp=0; - flags|=GFX_SCALING; - goto check_gotbpp; -#endif - case SCREEN_OVERLAY: - if (flags & GFX_RGBONLY || !(flags&GFX_CAN_32)) goto check_surface; - flags|=GFX_SCALING; - flags&=~(GFX_CAN_8|GFX_CAN_15|GFX_CAN_16); - break; -#if C_OPENGL - case SCREEN_OPENGL: - if (flags & GFX_RGBONLY || !(flags&GFX_CAN_32)) goto check_surface; - flags|=GFX_SCALING; - flags&=~(GFX_CAN_8|GFX_CAN_15|GFX_CAN_16); - break; -#endif - default: - goto check_surface; - break; - } - return flags; -} - - -void GFX_ResetScreen(void) { - GFX_Stop(); - if (sdl.draw.callback) - (sdl.draw.callback)( GFX_CallBackReset ); - GFX_Start(); - CPU_Reset_AutoAdjust(); -} - -static int int_log2 (int val) { - int log = 0; - while ((val >>= 1) != 0) - log++; - return log; -} - - -static SDL_Surface * GFX_SetupSurfaceScaled(Bit32u sdl_flags, Bit32u bpp) { - Bit16u fixedWidth; - Bit16u fixedHeight; - - if (sdl.desktop.fullscreen) { - fixedWidth = sdl.desktop.full.fixed ? sdl.desktop.full.width : 0; - fixedHeight = sdl.desktop.full.fixed ? sdl.desktop.full.height : 0; - sdl_flags |= SDL_FULLSCREEN|SDL_HWSURFACE; - } else { - fixedWidth = sdl.desktop.window.width; - fixedHeight = sdl.desktop.window.height; - sdl_flags |= SDL_HWSURFACE; - } - if (fixedWidth && fixedHeight) { - double ratio_w=(double)fixedWidth/(sdl.draw.width*sdl.draw.scalex); - double ratio_h=(double)fixedHeight/(sdl.draw.height*sdl.draw.scaley); - if ( ratio_w < ratio_h) { - sdl.clip.w=fixedWidth; - sdl.clip.h=(Bit16u)(sdl.draw.height*sdl.draw.scaley*ratio_w); - } else { - sdl.clip.w=(Bit16u)(sdl.draw.width*sdl.draw.scalex*ratio_h); - sdl.clip.h=(Bit16u)fixedHeight; - } - if (sdl.desktop.fullscreen) - sdl.surface = SDL_SetVideoMode(fixedWidth,fixedHeight,bpp,sdl_flags); - else - sdl.surface = SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,sdl_flags); - if (sdl.surface && sdl.surface->flags & SDL_FULLSCREEN) { - sdl.clip.x=(Sint16)((sdl.surface->w-sdl.clip.w)/2); - sdl.clip.y=(Sint16)((sdl.surface->h-sdl.clip.h)/2); - } else { - sdl.clip.x = 0; - sdl.clip.y = 0; - } - return sdl.surface; - } else { - sdl.clip.x=0;sdl.clip.y=0; - sdl.clip.w=(Bit16u)(sdl.draw.width*sdl.draw.scalex); - sdl.clip.h=(Bit16u)(sdl.draw.height*sdl.draw.scaley); - sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,sdl_flags); - return sdl.surface; - } -} - -Bitu GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_CallBack_t callback) { - if (sdl.updating) - GFX_EndUpdate( 0 ); - - sdl.draw.width=width; - sdl.draw.height=height; - sdl.draw.callback=callback; - sdl.draw.scalex=scalex; - sdl.draw.scaley=scaley; - - Bitu bpp=0; - Bitu retFlags = 0; - - if (sdl.blit.surface) { - SDL_FreeSurface(sdl.blit.surface); - sdl.blit.surface=0; - } - switch (sdl.desktop.want_type) { - case SCREEN_SURFACE: -dosurface: - if (flags & GFX_CAN_8) bpp=8; - if (flags & GFX_CAN_15) bpp=15; - if (flags & GFX_CAN_16) bpp=16; - if (flags & GFX_CAN_32) bpp=32; - sdl.desktop.type=SCREEN_SURFACE; - sdl.clip.w=width; - sdl.clip.h=height; - if (sdl.desktop.fullscreen) { - if (sdl.desktop.full.fixed) { - sdl.clip.x=(Sint16)((sdl.desktop.full.width-width)/2); - sdl.clip.y=(Sint16)((sdl.desktop.full.height-height)/2); - sdl.surface=SDL_SetVideoMode(sdl.desktop.full.width,sdl.desktop.full.height,bpp, - SDL_FULLSCREEN | ((flags & GFX_CAN_RANDOM) ? SDL_SWSURFACE : SDL_HWSURFACE) | - (sdl.desktop.doublebuf ? SDL_DOUBLEBUF|SDL_ASYNCBLIT : 0) | SDL_HWPALETTE); - if (sdl.surface == NULL) E_Exit("Could not set fullscreen video mode %ix%i-%i: %s",sdl.desktop.full.width,sdl.desktop.full.height,bpp,SDL_GetError()); - } else { - sdl.clip.x=0;sdl.clip.y=0; - sdl.surface=SDL_SetVideoMode(width,height,bpp, - SDL_FULLSCREEN | ((flags & GFX_CAN_RANDOM) ? SDL_SWSURFACE : SDL_HWSURFACE) | - (sdl.desktop.doublebuf ? SDL_DOUBLEBUF|SDL_ASYNCBLIT : 0)|SDL_HWPALETTE); - if (sdl.surface == NULL) - E_Exit("Could not set fullscreen video mode %ix%i-%i: %s",width,height,bpp,SDL_GetError()); - } - } else { - sdl.clip.x=0;sdl.clip.y=0; - sdl.surface=SDL_SetVideoMode(width,height,bpp,(flags & GFX_CAN_RANDOM) ? SDL_SWSURFACE : SDL_HWSURFACE); -#ifdef WIN32 - if (sdl.surface == NULL) { - SDL_QuitSubSystem(SDL_INIT_VIDEO); - if (!sdl.using_windib) { - LOG_MSG("Failed to create hardware surface.\nRestarting video subsystem with windib enabled."); - putenv("SDL_VIDEODRIVER=windib"); - sdl.using_windib=true; - } else { - LOG_MSG("Failed to create hardware surface.\nRestarting video subsystem with directx enabled."); - putenv("SDL_VIDEODRIVER=directx"); - sdl.using_windib=false; - } - SDL_InitSubSystem(SDL_INIT_VIDEO); - sdl.surface = SDL_SetVideoMode(width,height,bpp,SDL_HWSURFACE); - } -#endif - if (sdl.surface == NULL) - E_Exit("Could not set windowed video mode %ix%i-%i: %s",width,height,bpp,SDL_GetError()); - } - if (sdl.surface) { - switch (sdl.surface->format->BitsPerPixel) { - case 8: - retFlags = GFX_CAN_8; - break; - case 15: - retFlags = GFX_CAN_15; - break; - case 16: - retFlags = GFX_CAN_16; - break; - case 32: - retFlags = GFX_CAN_32; - break; - } - if (retFlags && (sdl.surface->flags & SDL_HWSURFACE)) - retFlags |= GFX_HARDWARE; - if (retFlags && (sdl.surface->flags & SDL_DOUBLEBUF)) { - sdl.blit.surface=SDL_CreateRGBSurface(SDL_HWSURFACE, - sdl.draw.width, sdl.draw.height, - sdl.surface->format->BitsPerPixel, - sdl.surface->format->Rmask, - sdl.surface->format->Gmask, - sdl.surface->format->Bmask, - 0); - /* If this one fails be ready for some flickering... */ - } - } - break; -#if (HAVE_DDRAW_H) && defined(WIN32) - case SCREEN_SURFACE_DDRAW: - if (flags & GFX_CAN_15) bpp=15; - if (flags & GFX_CAN_16) bpp=16; - if (flags & GFX_CAN_32) bpp=32; - if (!GFX_SetupSurfaceScaled((sdl.desktop.doublebuf && sdl.desktop.fullscreen) ? SDL_DOUBLEBUF : 0,bpp)) goto dosurface; - sdl.blit.rect.top=sdl.clip.y; - sdl.blit.rect.left=sdl.clip.x; - sdl.blit.rect.right=sdl.clip.x+sdl.clip.w; - sdl.blit.rect.bottom=sdl.clip.y+sdl.clip.h; - sdl.blit.surface=SDL_CreateRGBSurface(SDL_HWSURFACE,sdl.draw.width,sdl.draw.height, - sdl.surface->format->BitsPerPixel, - sdl.surface->format->Rmask, - sdl.surface->format->Gmask, - sdl.surface->format->Bmask, - 0); - if (!sdl.blit.surface || (!sdl.blit.surface->flags&SDL_HWSURFACE)) { - if (sdl.blit.surface) { - SDL_FreeSurface(sdl.blit.surface); - sdl.blit.surface=0; - } - LOG_MSG("Failed to create ddraw surface, back to normal surface."); - goto dosurface; - } - switch (sdl.surface->format->BitsPerPixel) { - case 15: - retFlags = GFX_CAN_15 | GFX_SCALING | GFX_HARDWARE; - break; - case 16: - retFlags = GFX_CAN_16 | GFX_SCALING | GFX_HARDWARE; - break; - case 32: - retFlags = GFX_CAN_32 | GFX_SCALING | GFX_HARDWARE; - break; - } - sdl.desktop.type=SCREEN_SURFACE_DDRAW; - break; -#endif - case SCREEN_OVERLAY: - if (sdl.overlay) { - SDL_FreeYUVOverlay(sdl.overlay); - sdl.overlay=0; - } - if (!(flags&GFX_CAN_32) || (flags & GFX_RGBONLY)) goto dosurface; - if (!GFX_SetupSurfaceScaled(0,0)) goto dosurface; - sdl.overlay=SDL_CreateYUVOverlay(width*2,height,SDL_UYVY_OVERLAY,sdl.surface); - if (!sdl.overlay) { - LOG_MSG("SDL:Failed to create overlay, switching back to surface"); - goto dosurface; - } - sdl.desktop.type=SCREEN_OVERLAY; - retFlags = GFX_CAN_32 | GFX_SCALING | GFX_HARDWARE; - break; -#if C_OPENGL - case SCREEN_OPENGL: - { - if (sdl.opengl.framebuf) { -#if defined(NVIDIA_PixelDataRange) - if (sdl.opengl.pixel_data_range) db_glFreeMemoryNV(sdl.opengl.framebuf); - else -#endif - free(sdl.opengl.framebuf); - } - sdl.opengl.framebuf=0; - if (!(flags&GFX_CAN_32) || (flags & GFX_RGBONLY)) goto dosurface; - int texsize=2 << int_log2(width > height ? width : height); - if (texsize>sdl.opengl.max_texsize) { - LOG_MSG("SDL:OPENGL:No support for texturesize of %d, falling back to surface",texsize); - goto dosurface; - } - SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); -#if defined (WIN32) && SDL_VERSION_ATLEAST(1, 2, 11) - SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 0 ); -#endif - GFX_SetupSurfaceScaled(SDL_OPENGL,0); - if (!sdl.surface || sdl.surface->format->BitsPerPixel<15) { - LOG_MSG("SDL:OPENGL:Can't open drawing surface, are you running in 16bpp(or higher) mode?"); - goto dosurface; - } - /* Create the texture and display list */ -#if defined(NVIDIA_PixelDataRange) - if (sdl.opengl.pixel_data_range) { - sdl.opengl.framebuf=db_glAllocateMemoryNV(width*height*4,0.0,1.0,1.0); - glPixelDataRangeNV(GL_WRITE_PIXEL_DATA_RANGE_NV,width*height*4,sdl.opengl.framebuf); - glEnableClientState(GL_WRITE_PIXEL_DATA_RANGE_NV); - } else { -#else - { -#endif - sdl.opengl.framebuf=malloc(width*height*4); //32 bit color - } - sdl.opengl.pitch=width*4; - glViewport(sdl.clip.x,sdl.clip.y,sdl.clip.w,sdl.clip.h); - glMatrixMode (GL_PROJECTION); - glDeleteTextures(1,&sdl.opengl.texture); - glGenTextures(1,&sdl.opengl.texture); - glBindTexture(GL_TEXTURE_2D,sdl.opengl.texture); - // No borders - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - if (sdl.opengl.bilinear) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texsize, texsize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 0); - - glClearColor (0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - SDL_GL_SwapBuffers(); - glClear(GL_COLOR_BUFFER_BIT); - glShadeModel (GL_FLAT); - glDisable (GL_DEPTH_TEST); - glDisable (GL_LIGHTING); - glDisable(GL_CULL_FACE); - glEnable(GL_TEXTURE_2D); - glMatrixMode (GL_MODELVIEW); - glLoadIdentity (); - - GLfloat tex_width=((GLfloat)(width)/(GLfloat)texsize); - GLfloat tex_height=((GLfloat)(height)/(GLfloat)texsize); - - if (glIsList(sdl.opengl.displaylist)) glDeleteLists(sdl.opengl.displaylist, 1); - sdl.opengl.displaylist = glGenLists(1); - glNewList(sdl.opengl.displaylist, GL_COMPILE); - glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture); - glBegin(GL_QUADS); - // lower left - glTexCoord2f(0,tex_height); glVertex2f(-1.0f,-1.0f); - // lower right - glTexCoord2f(tex_width,tex_height); glVertex2f(1.0f, -1.0f); - // upper right - glTexCoord2f(tex_width,0); glVertex2f(1.0f, 1.0f); - // upper left - glTexCoord2f(0,0); glVertex2f(-1.0f, 1.0f); - glEnd(); - glEndList(); - sdl.desktop.type=SCREEN_OPENGL; - retFlags = GFX_CAN_32 | GFX_SCALING; -#if defined(NVIDIA_PixelDataRange) - if (sdl.opengl.pixel_data_range) - retFlags |= GFX_HARDWARE; -#endif - break; - }//OPENGL -#endif //C_OPENGL - default: - goto dosurface; - break; - }//CASE - if (retFlags) - GFX_Start(); - if (!sdl.mouse.autoenable) SDL_ShowCursor(sdl.mouse.autolock?SDL_DISABLE:SDL_ENABLE); - return retFlags; -} - -void GFX_CaptureMouse(void) { - sdl.mouse.locked=!sdl.mouse.locked; - if (sdl.mouse.locked) { - SDL_WM_GrabInput(SDL_GRAB_ON); - SDL_ShowCursor(SDL_DISABLE); - } else { - SDL_WM_GrabInput(SDL_GRAB_OFF); - if (sdl.mouse.autoenable || !sdl.mouse.autolock) SDL_ShowCursor(SDL_ENABLE); - } - mouselocked=sdl.mouse.locked; -} - -bool mouselocked; //Global variable for mapper -static void CaptureMouse(bool pressed) { - if (!pressed) - return; - GFX_CaptureMouse(); -} - -void GFX_SwitchFullScreen(void) { - sdl.desktop.fullscreen=!sdl.desktop.fullscreen; - if (sdl.desktop.fullscreen) { - if (!sdl.mouse.locked) GFX_CaptureMouse(); - } else { - if (sdl.mouse.locked) GFX_CaptureMouse(); - } - GFX_ResetScreen(); -} - -static void SwitchFullScreen(bool pressed) { - if (!pressed) - return; - GFX_SwitchFullScreen(); -} - - -bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch) { - if (!sdl.active || sdl.updating) - return false; - switch (sdl.desktop.type) { - case SCREEN_SURFACE: - if (sdl.blit.surface) { - if (SDL_MUSTLOCK(sdl.blit.surface) && SDL_LockSurface(sdl.blit.surface)) - return false; - pixels=(Bit8u *)sdl.blit.surface->pixels; - pitch=sdl.blit.surface->pitch; - } else { - if (SDL_MUSTLOCK(sdl.surface) && SDL_LockSurface(sdl.surface)) - return false; - pixels=(Bit8u *)sdl.surface->pixels; - pixels+=sdl.clip.y*sdl.surface->pitch; - pixels+=sdl.clip.x*sdl.surface->format->BytesPerPixel; - pitch=sdl.surface->pitch; - } - sdl.updating=true; - return true; -#if (HAVE_DDRAW_H) && defined(WIN32) - case SCREEN_SURFACE_DDRAW: - if (SDL_LockSurface(sdl.blit.surface)) { -// LOG_MSG("SDL Lock failed"); - return false; - } - pixels=(Bit8u *)sdl.blit.surface->pixels; - pitch=sdl.blit.surface->pitch; - sdl.updating=true; - return true; -#endif - case SCREEN_OVERLAY: - SDL_LockYUVOverlay(sdl.overlay); - pixels=(Bit8u *)*(sdl.overlay->pixels); - pitch=*(sdl.overlay->pitches); - sdl.updating=true; - return true; -#if C_OPENGL - case SCREEN_OPENGL: - pixels=(Bit8u *)sdl.opengl.framebuf; - pitch=sdl.opengl.pitch; - sdl.updating=true; - return true; -#endif - default: - break; - } - return false; -} - - -void GFX_EndUpdate( const Bit16u *changedLines ) { -#if (HAVE_DDRAW_H) && defined(WIN32) - int ret; -#endif - if (!sdl.updating) - return; - sdl.updating=false; - switch (sdl.desktop.type) { - case SCREEN_SURFACE: - if (SDL_MUSTLOCK(sdl.surface)) { - if (sdl.blit.surface) { - SDL_UnlockSurface(sdl.blit.surface); - int Blit = SDL_BlitSurface( sdl.blit.surface, 0, sdl.surface, &sdl.clip ); - LOG(LOG_MISC,LOG_WARN)("BlitSurface returned %d",Blit); - } else { - SDL_UnlockSurface(sdl.surface); - } - SDL_Flip(sdl.surface); - } else if (changedLines) { - Bitu y = 0, index = 0, rectCount = 0; - while (y < sdl.draw.height) { - if (!(index & 1)) { - y += changedLines[index]; - } else { - SDL_Rect *rect = &sdl.updateRects[rectCount++]; - rect->x = sdl.clip.x; - rect->y = sdl.clip.y + y; - rect->w = (Bit16u)sdl.draw.width; - rect->h = changedLines[index]; -#if 0 - if (rect->h + rect->y > sdl.surface->h) { - LOG_MSG("WTF %d + %d >%d",rect->h,rect->y,sdl.surface->h); - } -#endif - y += changedLines[index]; - } - index++; - } - if (rectCount) - SDL_UpdateRects( sdl.surface, rectCount, sdl.updateRects ); - } - break; -#if (HAVE_DDRAW_H) && defined(WIN32) - case SCREEN_SURFACE_DDRAW: - SDL_UnlockSurface(sdl.blit.surface); - ret=IDirectDrawSurface3_Blt( - sdl.surface->hwdata->dd_writebuf,&sdl.blit.rect, - sdl.blit.surface->hwdata->dd_surface,0, - DDBLT_WAIT, NULL); - switch (ret) { - case DD_OK: - break; - case DDERR_SURFACELOST: - IDirectDrawSurface3_Restore(sdl.blit.surface->hwdata->dd_surface); - IDirectDrawSurface3_Restore(sdl.surface->hwdata->dd_surface); - break; - default: - LOG_MSG("DDRAW:Failed to blit, error %X",ret); - } - SDL_Flip(sdl.surface); - break; -#endif - case SCREEN_OVERLAY: - SDL_UnlockYUVOverlay(sdl.overlay); - SDL_DisplayYUVOverlay(sdl.overlay,&sdl.clip); - break; -#if C_OPENGL - case SCREEN_OPENGL: -#if defined(NVIDIA_PixelDataRange) - if (sdl.opengl.pixel_data_range) { - glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, - sdl.draw.width, sdl.draw.height, GL_BGRA_EXT, - GL_UNSIGNED_INT_8_8_8_8_REV, sdl.opengl.framebuf); - glCallList(sdl.opengl.displaylist); - SDL_GL_SwapBuffers(); - } else -#endif - if (changedLines) { - Bitu y = 0, index = 0; - glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture); - while (y < sdl.draw.height) { - if (!(index & 1)) { - y += changedLines[index]; - } else { - Bit8u *pixels = (Bit8u *)sdl.opengl.framebuf + y * sdl.opengl.pitch; - Bitu height = changedLines[index]; - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, - sdl.draw.width, height, GL_BGRA_EXT, - GL_UNSIGNED_INT_8_8_8_8_REV, pixels ); - y += height; - } - index++; - } - glCallList(sdl.opengl.displaylist); - SDL_GL_SwapBuffers(); - } - break; -#endif - default: - break; - } -} - - -void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { - /* I should probably not change the GFX_PalEntry :) */ - if (sdl.surface->flags & SDL_HWPALETTE) { - if (!SDL_SetPalette(sdl.surface,SDL_PHYSPAL,(SDL_Color *)entries,start,count)) { - E_Exit("SDL:Can't set palette"); - } - } else { - if (!SDL_SetPalette(sdl.surface,SDL_LOGPAL,(SDL_Color *)entries,start,count)) { - E_Exit("SDL:Can't set palette"); - } - } -} - -Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue) { - switch (sdl.desktop.type) { - case SCREEN_SURFACE: - case SCREEN_SURFACE_DDRAW: - return SDL_MapRGB(sdl.surface->format,red,green,blue); - case SCREEN_OVERLAY: - { - Bit8u y = ( 9797*(red) + 19237*(green) + 3734*(blue) ) >> 15; - Bit8u u = (18492*((blue)-(y)) >> 15) + 128; - Bit8u v = (23372*((red)-(y)) >> 15) + 128; -#ifdef WORDS_BIGENDIAN - return (y << 0) | (v << 8) | (y << 16) | (u << 24); -#else - return (u << 0) | (y << 8) | (v << 16) | (y << 24); -#endif - } - case SCREEN_OPENGL: -// return ((red << 0) | (green << 8) | (blue << 16)) | (255 << 24); - //USE BGRA - return ((blue << 0) | (green << 8) | (red << 16)) | (255 << 24); - } - return 0; -} - -void GFX_Stop() { - if (sdl.updating) - GFX_EndUpdate( 0 ); - sdl.active=false; -} - -void GFX_Start() { - sdl.active=true; -} - -static void GUI_ShutDown(Section * /*sec*/) { - GFX_Stop(); - if (sdl.draw.callback) (sdl.draw.callback)( GFX_CallBackStop ); - if (sdl.mouse.locked) GFX_CaptureMouse(); - if (sdl.desktop.fullscreen) GFX_SwitchFullScreen(); -} - -static void KillSwitch(bool pressed) { - if (!pressed) - return; - throw 1; -} - -static void SetPriority(PRIORITY_LEVELS level) { - -#if C_SET_PRIORITY -// Do nothing if priorties are not the same and not root, else the highest -// priority can not be set as users can only lower priority (not restore it) - - if((sdl.priority.focus != sdl.priority.nofocus ) && - (getuid()!=0) ) return; - -#endif - switch (level) { -#ifdef WIN32 - case PRIORITY_LEVEL_PAUSE: // if DOSBox is paused, assume idle priority - case PRIORITY_LEVEL_LOWEST: - SetPriorityClass(GetCurrentProcess(),IDLE_PRIORITY_CLASS); - break; - case PRIORITY_LEVEL_LOWER: - SetPriorityClass(GetCurrentProcess(),BELOW_NORMAL_PRIORITY_CLASS); - break; - case PRIORITY_LEVEL_NORMAL: - SetPriorityClass(GetCurrentProcess(),NORMAL_PRIORITY_CLASS); - break; - case PRIORITY_LEVEL_HIGHER: - SetPriorityClass(GetCurrentProcess(),ABOVE_NORMAL_PRIORITY_CLASS); - break; - case PRIORITY_LEVEL_HIGHEST: - SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); - break; -#elif C_SET_PRIORITY -/* Linux use group as dosbox has mulitple threads under linux */ - case PRIORITY_LEVEL_PAUSE: // if DOSBox is paused, assume idle priority - case PRIORITY_LEVEL_LOWEST: - setpriority (PRIO_PGRP, 0,PRIO_MAX); - break; - case PRIORITY_LEVEL_LOWER: - setpriority (PRIO_PGRP, 0,PRIO_MAX-(PRIO_TOTAL/3)); - break; - case PRIORITY_LEVEL_NORMAL: - setpriority (PRIO_PGRP, 0,PRIO_MAX-(PRIO_TOTAL/2)); - break; - case PRIORITY_LEVEL_HIGHER: - setpriority (PRIO_PGRP, 0,PRIO_MAX-((3*PRIO_TOTAL)/5) ); - break; - case PRIORITY_LEVEL_HIGHEST: - setpriority (PRIO_PGRP, 0,PRIO_MAX-((3*PRIO_TOTAL)/4) ); - break; -#endif - default: - break; - } -} - -static unsigned char logo[32*32*4]= { -#include "dosbox_logo.h" -}; - -//extern void UI_Run(bool); -static void GUI_StartUp(Section * sec) { - sec->AddDestroyFunction(&GUI_ShutDown); - Section_prop * section=static_cast(sec); - sdl.active=false; - sdl.updating=false; - -#if !defined(MACOSX) - /* Set Icon (must be done before any sdl_setvideomode call) */ - /* But don't set it on OS X, as we use a nicer external icon there. */ -#if WORDS_BIGENDIAN - SDL_Surface* logos= SDL_CreateRGBSurfaceFrom((void*)logo,32,32,32,128,0xff000000,0x00ff0000,0x0000ff00,0); -#else - SDL_Surface* logos= SDL_CreateRGBSurfaceFrom((void*)logo,32,32,32,128,0x000000ff,0x0000ff00,0x00ff0000,0); -#endif - SDL_WM_SetIcon(logos,NULL); -#endif - - sdl.desktop.fullscreen=section->Get_bool("fullscreen"); - sdl.wait_on_error=section->Get_bool("waitonerror"); - - Prop_multival* p=section->Get_multival("priority"); - std::string focus = p->GetSection()->Get_string("active"); - std::string notfocus = p->GetSection()->Get_string("inactive"); - - if (focus == "lowest") { sdl.priority.focus = PRIORITY_LEVEL_LOWEST; } - else if (focus == "lower") { sdl.priority.focus = PRIORITY_LEVEL_LOWER; } - else if (focus == "normal") { sdl.priority.focus = PRIORITY_LEVEL_NORMAL; } - else if (focus == "higher") { sdl.priority.focus = PRIORITY_LEVEL_HIGHER; } - else if (focus == "highest") { sdl.priority.focus = PRIORITY_LEVEL_HIGHEST; } - - if (notfocus == "lowest") { sdl.priority.nofocus=PRIORITY_LEVEL_LOWEST; } - else if (notfocus == "lower") { sdl.priority.nofocus=PRIORITY_LEVEL_LOWER; } - else if (notfocus == "normal") { sdl.priority.nofocus=PRIORITY_LEVEL_NORMAL; } - else if (notfocus == "higher") { sdl.priority.nofocus=PRIORITY_LEVEL_HIGHER; } - else if (notfocus == "highest") { sdl.priority.nofocus=PRIORITY_LEVEL_HIGHEST; } - else if (notfocus == "pause") { - /* we only check for pause here, because it makes no sense - * for DOSBox to be paused while it has focus - */ - sdl.priority.nofocus=PRIORITY_LEVEL_PAUSE; - } - - SetPriority(sdl.priority.focus); //Assume focus on startup - sdl.mouse.locked=false; - mouselocked=false; //Global for mapper - sdl.mouse.requestlock=false; - sdl.desktop.full.fixed=false; - const char* fullresolution=section->Get_string("fullresolution"); - sdl.desktop.full.width = 0; - sdl.desktop.full.height = 0; - if(fullresolution && *fullresolution) { - char res[100]; - strncpy( res, fullresolution, sizeof( res )); - fullresolution = lowcase (res);//so x and X are allowed - if(strcmp(fullresolution,"original")) { - sdl.desktop.full.fixed = true; - char* height = const_cast(strchr(fullresolution,'x')); - if(height && * height) { - *height = 0; - sdl.desktop.full.height = (Bit16u)atoi(height+1); - sdl.desktop.full.width = (Bit16u)atoi(res); - } - } - } - - sdl.desktop.window.width = 0; - sdl.desktop.window.height = 0; - const char* windowresolution=section->Get_string("windowresolution"); - if(windowresolution && *windowresolution) { - char res[100]; - strncpy( res,windowresolution, sizeof( res )); - windowresolution = lowcase (res);//so x and X are allowed - if(strcmp(windowresolution,"original")) { - char* height = const_cast(strchr(windowresolution,'x')); - if(height && *height) { - *height = 0; - sdl.desktop.window.height = (Bit16u)atoi(height+1); - sdl.desktop.window.width = (Bit16u)atoi(res); - } - } - } - sdl.desktop.doublebuf=section->Get_bool("fulldouble"); - if (!sdl.desktop.full.width) { -#ifdef WIN32 - sdl.desktop.full.width=(Bit16u)GetSystemMetrics(SM_CXSCREEN); -#else - sdl.desktop.full.width=1024; -#endif - } - if (!sdl.desktop.full.height) { -#ifdef WIN32 - sdl.desktop.full.height=(Bit16u)GetSystemMetrics(SM_CYSCREEN); -#else - sdl.desktop.full.height=768; -#endif - } - sdl.mouse.autoenable=section->Get_bool("autolock"); - if (!sdl.mouse.autoenable) SDL_ShowCursor(SDL_DISABLE); - sdl.mouse.autolock=false; - sdl.mouse.sensitivity=section->Get_int("sensitivity"); - std::string output=section->Get_string("output"); - - /* Setup Mouse correctly if fullscreen */ - if(sdl.desktop.fullscreen) GFX_CaptureMouse(); - - if (output == "surface") { - sdl.desktop.want_type=SCREEN_SURFACE; -#if (HAVE_DDRAW_H) && defined(WIN32) - } else if (output == "ddraw") { - sdl.desktop.want_type=SCREEN_SURFACE_DDRAW; -#endif - } else if (output == "overlay") { - sdl.desktop.want_type=SCREEN_OVERLAY; -#if C_OPENGL - } else if (output == "opengl") { - sdl.desktop.want_type=SCREEN_OPENGL; - sdl.opengl.bilinear=true; - } else if (output == "openglnb") { - sdl.desktop.want_type=SCREEN_OPENGL; - sdl.opengl.bilinear=false; -#endif - } else { - LOG_MSG("SDL:Unsupported output device %s, switching back to surface",output.c_str()); - sdl.desktop.want_type=SCREEN_SURFACE;//SHOULDN'T BE POSSIBLE anymore - } - - sdl.overlay=0; -#if C_OPENGL - if(sdl.desktop.want_type==SCREEN_OPENGL){ /* OPENGL is requested */ - sdl.surface=SDL_SetVideoMode(640,400,0,SDL_OPENGL); - if (sdl.surface == NULL) { - LOG_MSG("Could not initialize OpenGL, switching back to surface"); - sdl.desktop.want_type=SCREEN_SURFACE; - } else { - sdl.opengl.framebuf=0; - sdl.opengl.texture=0; - sdl.opengl.displaylist=0; - glGetIntegerv (GL_MAX_TEXTURE_SIZE, &sdl.opengl.max_texsize); -#if defined(__WIN32__) && defined(NVIDIA_PixelDataRange) - glPixelDataRangeNV = (PFNGLPIXELDATARANGENVPROC) wglGetProcAddress("glPixelDataRangeNV"); - db_glAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC) wglGetProcAddress("wglAllocateMemoryNV"); - db_glFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC) wglGetProcAddress("wglFreeMemoryNV"); -#endif - const char * gl_ext = (const char *)glGetString (GL_EXTENSIONS); - if(gl_ext && *gl_ext){ - sdl.opengl.packed_pixel=(strstr(gl_ext,"EXT_packed_pixels") > 0); - sdl.opengl.paletted_texture=(strstr(gl_ext,"EXT_paletted_texture") > 0); -#if defined(NVIDIA_PixelDataRange) - sdl.opengl.pixel_data_range=(strstr(gl_ext,"GL_NV_pixel_data_range") >0 ) && - glPixelDataRangeNV && db_glAllocateMemoryNV && db_glFreeMemoryNV; - sdl.opengl.pixel_data_range = 0; -#endif - } else { - sdl.opengl.packed_pixel=sdl.opengl.paletted_texture=false; - } - } - } /* OPENGL is requested end */ - -#endif //OPENGL - /* Initialize screen for first time */ - sdl.surface=SDL_SetVideoMode(640,400,0,0); - if (sdl.surface == NULL) E_Exit("Could not initialize video: %s",SDL_GetError()); - sdl.desktop.bpp=sdl.surface->format->BitsPerPixel; - if (sdl.desktop.bpp==24) { - LOG_MSG("SDL:You are running in 24 bpp mode, this will slow down things!"); - } - GFX_Stop(); -/* Get some Event handlers */ - MAPPER_AddHandler(KillSwitch,MK_f9,MMOD1,"shutdown","ShutDown"); - MAPPER_AddHandler(CaptureMouse,MK_f10,MMOD1,"capmouse","Cap Mouse"); - MAPPER_AddHandler(SwitchFullScreen,MK_return,MMOD2,"fullscr","Fullscreen"); -#if C_DEBUG - /* Pause binds with activate-debugger */ -#else - MAPPER_AddHandler(&PauseDOSBox, MK_pause, MMOD2, "pause", "Pause"); -#endif - /* Get Keyboard state of numlock and capslock */ - SDLMod keystate = SDL_GetModState(); - if(keystate&KMOD_NUM) startup_state_numlock = true; - if(keystate&KMOD_CAPS) startup_state_capslock = true; -} - -void Mouse_AutoLock(bool enable) { - sdl.mouse.autolock=enable; - if (sdl.mouse.autoenable) sdl.mouse.requestlock=enable; - else { - SDL_ShowCursor(enable?SDL_DISABLE:SDL_ENABLE); - sdl.mouse.requestlock=false; - } -} - -static void HandleMouseMotion(SDL_MouseMotionEvent * motion) { - if (sdl.mouse.locked || !sdl.mouse.autoenable) - Mouse_CursorMoved((float)motion->xrel*sdl.mouse.sensitivity/100.0f, - (float)motion->yrel*sdl.mouse.sensitivity/100.0f, - (float)(motion->x-sdl.clip.x)/(sdl.clip.w-1)*sdl.mouse.sensitivity/100.0f, - (float)(motion->y-sdl.clip.y)/(sdl.clip.h-1)*sdl.mouse.sensitivity/100.0f, - sdl.mouse.locked); -} - -static void HandleMouseButton(SDL_MouseButtonEvent * button) { - switch (button->state) { - case SDL_PRESSED: - if (sdl.mouse.requestlock && !sdl.mouse.locked) { - GFX_CaptureMouse(); - // Dont pass klick to mouse handler - break; - } - if (!sdl.mouse.autoenable && sdl.mouse.autolock && button->button == SDL_BUTTON_MIDDLE) { - GFX_CaptureMouse(); - break; - } - switch (button->button) { - case SDL_BUTTON_LEFT: - Mouse_ButtonPressed(0); - break; - case SDL_BUTTON_RIGHT: - Mouse_ButtonPressed(1); - break; - case SDL_BUTTON_MIDDLE: - Mouse_ButtonPressed(2); - break; - } - break; - case SDL_RELEASED: - switch (button->button) { - case SDL_BUTTON_LEFT: - Mouse_ButtonReleased(0); - break; - case SDL_BUTTON_RIGHT: - Mouse_ButtonReleased(1); - break; - case SDL_BUTTON_MIDDLE: - Mouse_ButtonReleased(2); - break; - } - break; - } -} - -void GFX_LosingFocus(void) { - sdl.laltstate=SDL_KEYUP; - sdl.raltstate=SDL_KEYUP; - MAPPER_LosingFocus(); -} - -void GFX_Events() { - SDL_Event event; -#if defined (REDUCE_JOYSTICK_POLLING) - static int poll_delay=0; - int time=GetTicks(); - if (time-poll_delay>20) { - poll_delay=time; - if (sdl.num_joysticks>0) SDL_JoystickUpdate(); - MAPPER_UpdateJoysticks(); - } -#endif - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_ACTIVEEVENT: - if (event.active.state & SDL_APPINPUTFOCUS) { - if (event.active.gain) { - if (sdl.desktop.fullscreen && !sdl.mouse.locked) - GFX_CaptureMouse(); - SetPriority(sdl.priority.focus); - CPU_Disable_SkipAutoAdjust(); - } else { - if (sdl.mouse.locked) { -#ifdef WIN32 - if (sdl.desktop.fullscreen) { - VGA_KillDrawing(); - sdl.desktop.fullscreen=false; - GFX_ResetScreen(); - } -#endif - GFX_CaptureMouse(); - } - SetPriority(sdl.priority.nofocus); - GFX_LosingFocus(); - CPU_Enable_SkipAutoAdjust(); - } - } - - /* Non-focus priority is set to pause; check to see if we've lost window or input focus - * i.e. has the window been minimised or made inactive? - */ - if (sdl.priority.nofocus == PRIORITY_LEVEL_PAUSE) { - if ((event.active.state & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) && (!event.active.gain)) { - /* Window has lost focus, pause the emulator. - * This is similar to what PauseDOSBox() does, but the exit criteria is different. - * Instead of waiting for the user to hit Alt-Break, we wait for the window to - * regain window or input focus. - */ - bool paused = true; - SDL_Event ev; - - GFX_SetTitle(-1,-1,true); - KEYBOARD_ClrBuffer(); -// SDL_Delay(500); -// while (SDL_PollEvent(&ev)) { - // flush event queue. -// } - - while (paused) { - // WaitEvent waits for an event rather than polling, so CPU usage drops to zero - SDL_WaitEvent(&ev); - - switch (ev.type) { - case SDL_QUIT: throw(0); break; // a bit redundant at linux at least as the active events gets before the quit event. - case SDL_ACTIVEEVENT: // wait until we get window focus back - if (ev.active.state & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) { - // We've got focus back, so unpause and break out of the loop - if (ev.active.gain) { - paused = false; - GFX_SetTitle(-1,-1,false); - } - - /* Now poke a "release ALT" command into the keyboard buffer - * we have to do this, otherwise ALT will 'stick' and cause - * problems with the app running in the DOSBox. - */ - KEYBOARD_AddKey(KBD_leftalt, false); - KEYBOARD_AddKey(KBD_rightalt, false); - } - break; - } - } - } - } - break; - case SDL_MOUSEMOTION: - HandleMouseMotion(&event.motion); - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - HandleMouseButton(&event.button); - break; - case SDL_VIDEORESIZE: -// HandleVideoResize(&event.resize); - break; - case SDL_QUIT: - throw(0); - break; - case SDL_VIDEOEXPOSE: - if (sdl.draw.callback) sdl.draw.callback( GFX_CallBackRedraw ); - break; -#ifdef WIN32 - case SDL_KEYDOWN: - case SDL_KEYUP: - // ignore event alt+tab - if (event.key.keysym.sym==SDLK_LALT) sdl.laltstate = event.key.type; - if (event.key.keysym.sym==SDLK_RALT) sdl.raltstate = event.key.type; - if (((event.key.keysym.sym==SDLK_TAB)) && - ((sdl.laltstate==SDL_KEYDOWN) || (sdl.raltstate==SDL_KEYDOWN))) break; -#endif - default: - void MAPPER_CheckEvent(SDL_Event * event); - MAPPER_CheckEvent(&event); - } - } -} - -#if defined (WIN32) -static BOOL WINAPI ConsoleEventHandler(DWORD event) { - switch (event) { - case CTRL_SHUTDOWN_EVENT: - case CTRL_LOGOFF_EVENT: - case CTRL_CLOSE_EVENT: - case CTRL_BREAK_EVENT: - raise(SIGTERM); - return TRUE; - case CTRL_C_EVENT: - default: //pass to the next handler - return FALSE; - } -} -#endif - - -/* static variable to show wether there is not a valid stdout. - * Fixes some bugs when -noconsole is used in a read only directory */ -static bool no_stdout = false; - -void GFX_ShowMsg(char const* format,...) { - char buf[512]; - va_list msg; - va_start(msg,format); - vsprintf(buf,format,msg); - strcat(buf,"\n"); - va_end(msg); - if(!no_stdout) printf("%s",buf); //Else buf is parsed again. -} - - -void Config_Add_SDL() { - Section_prop * sdl_sec=control->AddSection_prop("sdl",&GUI_StartUp); - sdl_sec->AddInitFunction(&MAPPER_StartUp); - Prop_bool* Pbool; - Prop_string* Pstring; - Prop_int* Pint; - Prop_multival* Pmulti; - - Pbool = sdl_sec->Add_bool("fullscreen",Property::Changeable::Always,false); - Pbool->Set_help("Start dosbox directly in fullscreen."); - - Pbool = sdl_sec->Add_bool("fulldouble",Property::Changeable::Always,false); - Pbool->Set_help("Use double buffering in fullscreen."); - - Pstring = sdl_sec->Add_string("fullresolution",Property::Changeable::Always,"original"); - Pstring->Set_help("What resolution to use for fullscreen: original or fixed size (e.g. 1024x768)."); - - Pstring = sdl_sec->Add_string("windowresolution",Property::Changeable::Always,"original"); - Pstring->Set_help("Scale the window to this size IF the output device supports hardware scaling."); - - const char* outputs[] = { - "surface", "overlay", -#if C_OPENGL - "opengl", "openglnb", -#endif -#if (HAVE_DDRAW_H) && defined(WIN32) - "ddraw", -#endif - 0 }; - Pstring = sdl_sec->Add_string("output",Property::Changeable::Always,"surface"); - Pstring->Set_help("What video system to use for output."); - Pstring->Set_values(outputs); - - Pbool = sdl_sec->Add_bool("autolock",Property::Changeable::Always,true); - Pbool->Set_help("Mouse will automatically lock, if you click on the screen."); - - Pint = sdl_sec->Add_int("sensitivity",Property::Changeable::Always,100); - Pint->SetMinMax(1,1000); - Pint->Set_help("Mouse sensitivity."); - - Pbool = sdl_sec->Add_bool("waitonerror",Property::Changeable::Always, true); - Pbool->Set_help("Wait before closing the console if dosbox has an error."); - - Pmulti = sdl_sec->Add_multi("priority", Property::Changeable::Always, ","); - Pmulti->SetValue("higher,normal"); - Pmulti->Set_help("Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. (pause is only valid for the second entry)"); - - const char* actt[] = { "lowest", "lower", "normal", "higher", "highest", "pause", 0}; - Pstring = Pmulti->GetSection()->Add_string("active",Property::Changeable::Always,"higher"); - Pstring->Set_values(actt); - - const char* inactt[] = { "lowest", "lower", "normal", "higher", "highest", "pause", 0}; - Pstring = Pmulti->GetSection()->Add_string("inactive",Property::Changeable::Always,"normal"); - Pstring->Set_values(inactt); - - Pstring = sdl_sec->Add_path("mapperfile",Property::Changeable::Always,"mapper.txt"); - Pstring->Set_help("File used to load/save the key/event mappings from."); - - Pbool = sdl_sec->Add_bool("usescancodes",Property::Changeable::Always,true); - Pbool->Set_help("Avoid usage of symkeys, might not work on all operating systems."); -} - -static void launcheditor(std::string const& edit) { - std::string path,file; - Cross::CreatePlatformConfigDir(path); - Cross::GetPlatformConfigName(file); - path += file; - FILE* f = fopen(path.c_str(),"r"); - if(!f && !control->PrintConfig(path.c_str())) { - printf("tried creating %s. but failed.\n",path.c_str()); - exit(1); - } - if(f) fclose(f); - if(edit.empty()) { - printf("no editor specified.\n"); - exit(1); - } - - execlp(edit.c_str(),edit.c_str(),path.c_str(),(char*) 0); - //if you get here the launching failed! - printf("can't find editor %s\n",edit.c_str()); - exit(1); -} - -static void printconfiglocation() { - std::string path,file; - Cross::CreatePlatformConfigDir(path); - Cross::GetPlatformConfigName(file); - path += file; - FILE* f = fopen(path.c_str(),"r"); - if(!f && !control->PrintConfig(path.c_str())) { - printf("tried creating %s. but failed",path.c_str()); - exit(1); - } - if(f) fclose(f); - printf("%s\n",path.c_str()); - exit(0); -} - - -//extern void UI_Init(void); -int main(int argc, char* argv[]) { - try { - CommandLine com_line(argc,argv); - Config myconf(&com_line); - control=&myconf; - /* Init the configuration system and add default values */ - Config_Add_SDL(); - DOSBOX_Init(); - - std::string editor; - if(control->cmdline->FindString("-editconf",editor,true)) launcheditor(editor); - - /* Can't disable the console with debugger enabled */ -#if defined(WIN32) && !(C_DEBUG) - if (control->cmdline->FindExist("-noconsole")) { - FreeConsole(); - /* Redirect standard input and standard output */ - if(freopen(STDOUT_FILE, "w", stdout) == NULL) - no_stdout = true; // No stdout so don't write messages - freopen(STDERR_FILE, "w", stderr); - setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* Line buffered */ - setbuf(stderr, NULL); /* No buffering */ - } else { - if (AllocConsole()) { - fclose(stdin); - fclose(stdout); - fclose(stderr); - freopen("CONIN$","r",stdin); - freopen("CONOUT$","w",stdout); - freopen("CONOUT$","w",stderr); - } - SetConsoleTitle("DOSBox Status Window"); - } -#endif //defined(WIN32) && !(C_DEBUG) - if (control->cmdline->FindExist("-version") || - control->cmdline->FindExist("--version") ) { - printf("\nDOSBox version %s, copyright 2002-2009 DOSBox Team.\n\n",VERSION); - printf("DOSBox is written by the DOSBox Team (See AUTHORS file))\n"); - printf("DOSBox comes with ABSOLUTELY NO WARRANTY. This is free software,\n"); - printf("and you are welcome to redistribute it under certain conditions;\n"); - printf("please read the COPYING file thoroughly before doing so.\n\n"); - return 0; - } - if(control->cmdline->FindExist("-printconf")) printconfiglocation(); - -#if C_DEBUG - DEBUG_SetupConsole(); -#endif - -#if defined(WIN32) - SetConsoleCtrlHandler((PHANDLER_ROUTINE) ConsoleEventHandler,TRUE); -#endif - -#ifdef OS2 - PPIB pib; - PTIB tib; - DosGetInfoBlocks(&tib, &pib); - if (pib->pib_ultype == 2) pib->pib_ultype = 3; - setbuf(stdout, NULL); - setbuf(stderr, NULL); -#endif - - /* Display Welcometext in the console */ - LOG_MSG("DOSBox version %s",VERSION); - LOG_MSG("Copyright 2002-2009 DOSBox Team, published under GNU GPL."); - LOG_MSG("---"); - - /* Init SDL */ - putenv(const_cast("SDL_DISABLE_LOCK_KEYS=1")); //Workaround debian/ubuntu fixes for SDL. - if ( SDL_Init( SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_CDROM - |SDL_INIT_NOPARACHUTE - ) < 0 ) E_Exit("Can't init SDL %s",SDL_GetError()); - -#ifndef DISABLE_JOYSTICK - //Initialise Joystick seperately. This way we can warn when it fails instead - //of exiting the application - if( SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0 ) LOG_MSG("Failed to init joystick support"); -#endif - - sdl.laltstate = SDL_KEYUP; - sdl.raltstate = SDL_KEYUP; - -#if defined (WIN32) -#if SDL_VERSION_ATLEAST(1, 2, 10) - sdl.using_windib=true; -#else - sdl.using_windib=false; -#endif - char sdl_drv_name[128]; - if (getenv("SDL_VIDEODRIVER")==NULL) { - if (SDL_VideoDriverName(sdl_drv_name,128)!=NULL) { - sdl.using_windib=false; - if (strcmp(sdl_drv_name,"directx")!=0) { - SDL_QuitSubSystem(SDL_INIT_VIDEO); - putenv("SDL_VIDEODRIVER=directx"); - if (SDL_InitSubSystem(SDL_INIT_VIDEO)<0) { - putenv("SDL_VIDEODRIVER=windib"); - if (SDL_InitSubSystem(SDL_INIT_VIDEO)<0) E_Exit("Can't init SDL Video %s",SDL_GetError()); - sdl.using_windib=true; - } - } - } - } else { - char* sdl_videodrv = getenv("SDL_VIDEODRIVER"); - if (strcmp(sdl_videodrv,"directx")==0) sdl.using_windib = false; - else if (strcmp(sdl_videodrv,"windib")==0) sdl.using_windib = true; - } - if (SDL_VideoDriverName(sdl_drv_name,128)!=NULL) { - if (strcmp(sdl_drv_name,"windib")==0) LOG_MSG("SDL_Init: Starting up with SDL windib video driver.\n Try to update your video card and directx drivers!"); - } -#endif - sdl.num_joysticks=SDL_NumJoysticks(); - - /* Parse configuration files */ - std::string config_file,config_path; - bool parsed_anyconfigfile = false; - //First Parse -conf switches - while(control->cmdline->FindString("-conf",config_file,true)) - if (control->ParseConfigFile(config_file.c_str())) parsed_anyconfigfile = true; - - //if none found => parse localdir conf - config_file = "dosbox.conf"; - if (!parsed_anyconfigfile && control->ParseConfigFile(config_file.c_str())) parsed_anyconfigfile = true; - - //if none found => parse userlevel conf - if(!parsed_anyconfigfile) { - config_file.clear(); - Cross::GetPlatformConfigDir(config_path); - Cross::GetPlatformConfigName(config_file); - config_path += config_file; - if(control->ParseConfigFile(config_path.c_str())) parsed_anyconfigfile = true; - } - - if(!parsed_anyconfigfile) { - //Try to create the userlevel configfile. - config_file.clear(); - Cross::CreatePlatformConfigDir(config_path); - Cross::GetPlatformConfigName(config_file); - config_path += config_file; - if(control->PrintConfig(config_path.c_str())) { - LOG_MSG("CONFIG: Generating default configuration.\nWriting it to %s",config_path.c_str()); - //Load them as well. Makes relative paths much easier - control->ParseConfigFile(config_path.c_str()); - } else { - LOG_MSG("CONFIG: Using default settings. Create a configfile to change them"); - } - } - - -#if (ENVIRON_LINKED) - control->ParseEnv(environ); -#endif -// UI_Init(); -// if (control->cmdline->FindExist("-startui")) UI_Run(false); - /* Init all the sections */ - control->Init(); - /* Some extra SDL Functions */ - Section_prop * sdl_sec=static_cast(control->GetSection("sdl")); - - if (control->cmdline->FindExist("-fullscreen") || sdl_sec->Get_bool("fullscreen")) { - if(!sdl.desktop.fullscreen) { //only switch if not allready in fullscreen - GFX_SwitchFullScreen(); - } - } - - /* Init the keyMapper */ - MAPPER_Init(); - if (control->cmdline->FindExist("-startmapper")) MAPPER_Run(false); - /* Start up main machine */ - control->StartUp(); - /* Shutdown everything */ - } catch (char * error) { - GFX_ShowMsg("Exit to error: %s",error); - fflush(NULL); - if(sdl.wait_on_error) { - //TODO Maybe look for some way to show message in linux? -#if (C_DEBUG) - GFX_ShowMsg("Press enter to continue"); - fflush(NULL); - fgetc(stdin); -#elif defined(WIN32) - Sleep(5000); -#endif - } - - } - catch (int){ - ;//nothing pressed killswitch - } - catch(...){ - //Force visible mouse to end user. Somehow this sometimes doesn't happen - SDL_WM_GrabInput(SDL_GRAB_OFF); - SDL_ShowCursor(SDL_ENABLE); - throw;//dunno what happened. rethrow for sdl to catch - } - //Force visible mouse to end user. Somehow this sometimes doesn't happen - SDL_WM_GrabInput(SDL_GRAB_OFF); - SDL_ShowCursor(SDL_ENABLE); - - SDL_Quit();//Let's hope sdl will quit as well when it catches an exception - return 0; -}; - -void GFX_GetSize(int &width, int &height, bool &fullscreen) { - width = sdl.draw.width; - height = sdl.draw.height; - fullscreen = sdl.desktop.fullscreen; -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include "dosbox.h" +#include "video.h" +#include "keyboard.h" +#include "mouse.h" +#include "joystick.h" +#include "pic.h" +#include "timer.h" + + +//#define DISABLE_JOYSTICK + + +struct SDL_Block { + bool active; //If this isn't set don't draw + Bitu width; + Bitu height; + Bitu bpp; + GFX_DrawHandler * draw; + GFX_ResizeHandler * resize; + bool mouse_grabbed; + bool full_screen; + SDL_Thread * thread; + SDL_mutex * mutex; + SDL_Surface * surface; + SDL_Joystick * joy; + SDL_Color pal[256]; +}; + +static SDL_Block sdl; + +GFX_Info gfx_info; + +static void RestorePalette(void) { + if (sdl.bpp!=8) return; +/* Use some other way of doing this */ + if (sdl.full_screen) { + if (!SDL_SetPalette(sdl.surface,SDL_PHYSPAL,sdl.pal,0,256)) { + E_Exit("SDL:Can't set palette"); + } + } else { + if (!SDL_SetPalette(sdl.surface,SDL_LOGPAL,sdl.pal,0,256)) { + E_Exit("SDL:Can't set palette"); + } + } + return; +} +/* Reset the screen with current values in the sdl structure */ +static void ResetScreen(void) { + if (sdl.full_screen) { + /* First get the original resolution */ + sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,sdl.bpp,SDL_HWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN|SDL_DOUBLEBUF); + } else { + sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,sdl.bpp,SDL_SWSURFACE|SDL_RESIZABLE); + } + if (sdl.surface==0) { + E_Exit("SDL:Would be nice if I could get a surface."); + } + SDL_WM_SetCaption(VERSION,VERSION); +/* also fill up gfx_info structure */ + gfx_info.width=sdl.width; + gfx_info.height=sdl.height; + gfx_info.bpp=sdl.bpp; + gfx_info.pitch=sdl.surface->pitch; + RestorePalette(); +} + + +void GFX_Resize(Bitu width,Bitu height,Bitu bpp,GFX_ResizeHandler * resize) { + GFX_Stop(); + sdl.width=width; + sdl.height=height; + sdl.bpp=bpp; + sdl.resize=resize; + ResetScreen(); + GFX_Start(); +} + +static void CaptureMouse() { + sdl.mouse_grabbed=!sdl.mouse_grabbed; + if (sdl.mouse_grabbed) { + SDL_WM_GrabInput(SDL_GRAB_ON); + SDL_ShowCursor(SDL_DISABLE); + } else { + SDL_WM_GrabInput(SDL_GRAB_OFF); + SDL_ShowCursor(SDL_ENABLE); + } +} + +static void SwitchFullScreen(void) { + GFX_Stop(); + sdl.full_screen=!sdl.full_screen; + if (sdl.full_screen) { + if (sdl.resize) { + sdl.width=0;sdl.height=0; + (*sdl.resize)(&sdl.width,&sdl.height); + } + } + ResetScreen(); + GFX_Start(); +} + +static void GFX_Redraw() { +#ifdef C_THREADED + if (SDL_mutexP(sdl.mutex)) { + E_Exit("Can't Lock Mutex"); + }; +#endif + if (sdl.active) { + SDL_LockSurface(sdl.surface ); + if (sdl.surface->pixels && sdl.draw) (*sdl.draw)((Bit8u *)sdl.surface->pixels); + SDL_UnlockSurface(sdl.surface ); + if (sdl.full_screen) SDL_Flip(sdl.surface); + else SDL_UpdateRect(sdl.surface,0,0,0,0); + }; +#ifdef C_THREADED + if (SDL_mutexV(sdl.mutex)) { + E_Exit("Can't Release Mutex"); + } +#endif +} + +static int SDLGFX_Thread(void * data) { + do { + GFX_Redraw(); + SDL_Delay(1000/70); + } while (true); + return 1; +} + +void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { +/* I should probably not change the GFX_PalEntry :) */ +#ifdef C_THREADED + if (SDL_mutexP(sdl.mutex)) { + E_Exit("SDL:Can't Lock Mutex"); + }; +#endif + if (sdl.full_screen) { + if (!SDL_SetPalette(sdl.surface,SDL_PHYSPAL,(SDL_Color *)entries,start,count)) { + E_Exit("SDL:Can't set palette"); + } + } else { + if (!SDL_SetPalette(sdl.surface,SDL_LOGPAL,(SDL_Color *)entries,start,count)) { + E_Exit("SDL:Can't set palette"); + } + } + /* Copy palette entries into some internal back up table */ +#ifdef C_THREADED + if (SDL_mutexV(sdl.mutex)) { + E_Exit("SDL:Can't Release Mutex"); + } +#endif + memcpy(&sdl.pal[start],entries,count*sizeof(SDL_Color)); +} + +void GFX_SetDrawHandler(GFX_DrawHandler * handler) { + sdl.draw=handler; +} + +void GFX_Stop() { +#ifdef C_THREADED + SDL_mutexP(sdl.mutex); +#endif + sdl.active=false; +#ifdef C_THREADED + SDL_mutexV(sdl.mutex); +#endif +} + + +void GFX_Start() { + sdl.active=true; +} + + +void GFX_StartUp() { + sdl.active=false; + sdl.full_screen=false; + sdl.draw=0; +#ifdef C_THREADED + sdl.mutex=SDL_CreateMutex(); + sdl.thread = SDL_CreateThread(&SDLGFX_Thread,0); +#else + TIMER_RegisterMicroHandler(GFX_Redraw,1000000/70); +#endif + GFX_Resize(640,400,8,0); + SDL_EnableKeyRepeat(250,30); + +/* Get some Keybinds */ + KEYBOARD_AddEvent(KBD_f9,CTRL_PRESSED,SwitchFullScreen); + KEYBOARD_AddEvent(KBD_f10,CTRL_PRESSED,CaptureMouse); + KEYBOARD_AddEvent(KBD_enter,ALT_PRESSED,SwitchFullScreen); +} + +void GFX_ShutDown() { + if (sdl.full_screen) SwitchFullScreen(); + if (sdl.mouse_grabbed) CaptureMouse(); + GFX_Stop(); +} + + +static void HandleKey(SDL_KeyboardEvent * key) { + Bit32u code; + switch (key->keysym.sym) { + case SDLK_1:code=KBD_1;break; + case SDLK_2:code=KBD_2;break; + case SDLK_3:code=KBD_3;break; + case SDLK_4:code=KBD_4;break; + case SDLK_5:code=KBD_5;break; + case SDLK_6:code=KBD_6;break; + case SDLK_7:code=KBD_7;break; + case SDLK_8:code=KBD_8;break; + case SDLK_9:code=KBD_9;break; + case SDLK_0:code=KBD_0;break; + + case SDLK_q:code=KBD_q;break; + case SDLK_w:code=KBD_w;break; + case SDLK_e:code=KBD_e;break; + case SDLK_r:code=KBD_r;break; + case SDLK_t:code=KBD_t;break; + case SDLK_y:code=KBD_y;break; + case SDLK_u:code=KBD_u;break; + case SDLK_i:code=KBD_i;break; + case SDLK_o:code=KBD_o;break; + case SDLK_p:code=KBD_p;break; + + case SDLK_a:code=KBD_a;break; + case SDLK_s:code=KBD_s;break; + case SDLK_d:code=KBD_d;break; + case SDLK_f:code=KBD_f;break; + case SDLK_g:code=KBD_g;break; + case SDLK_h:code=KBD_h;break; + case SDLK_j:code=KBD_j;break; + case SDLK_k:code=KBD_k;break; + case SDLK_l:code=KBD_l;break; + + case SDLK_z:code=KBD_z;break; + case SDLK_x:code=KBD_x;break; + case SDLK_c:code=KBD_c;break; + case SDLK_v:code=KBD_v;break; + case SDLK_b:code=KBD_b;break; + case SDLK_n:code=KBD_n;break; + case SDLK_m:code=KBD_m;break; + + + case SDLK_F1:code=KBD_f1;break; + case SDLK_F2:code=KBD_f2;break; + case SDLK_F3:code=KBD_f3;break; + case SDLK_F4:code=KBD_f4;break; + case SDLK_F5:code=KBD_f5;break; + case SDLK_F6:code=KBD_f6;break; + case SDLK_F7:code=KBD_f7;break; + case SDLK_F8:code=KBD_f8;break; + case SDLK_F9:code=KBD_f9;break; + case SDLK_F10:code=KBD_f10;break; + case SDLK_F11:code=KBD_f11;break; + case SDLK_F12:code=KBD_f12;break; + +// KBD_esc,KBD_tab,KBD_backspace,KBD_enter,KBD_space, + + case SDLK_ESCAPE:code=KBD_esc;break; + case SDLK_TAB:code=KBD_tab;break; + case SDLK_BACKSPACE:code=KBD_backspace;break; + case SDLK_RETURN:code=KBD_enter;break; + case SDLK_SPACE:code=KBD_space;break; + + case SDLK_LALT:code=KBD_leftalt;break; + case SDLK_RALT:code=KBD_rightalt;break; + case SDLK_LCTRL:code=KBD_leftctrl;break; + case SDLK_RCTRL:code=KBD_rightctrl;break; + case SDLK_LSHIFT:code=KBD_leftshift;break; + case SDLK_RSHIFT:code=KBD_rightshift;break; + + case SDLK_CAPSLOCK:code=KBD_capslock;break; + case SDLK_SCROLLOCK:code=KBD_scrolllock;break; + case SDLK_NUMLOCK:code=KBD_numlock;break; + + case SDLK_BACKQUOTE:code=KBD_grave;break; + case SDLK_MINUS:code=KBD_minus;break; + case SDLK_EQUALS:code=KBD_equals;break; + case SDLK_BACKSLASH:code=KBD_backslash;break; + case SDLK_LEFTBRACKET:code=KBD_leftbracket;break; + case SDLK_RIGHTBRACKET:code=KBD_rightbracket;break; + + case SDLK_SEMICOLON:code=KBD_semicolon;break; + case SDLK_QUOTE:code=KBD_quote;break; + case SDLK_PERIOD:code=KBD_period;break; + case SDLK_COMMA:code=KBD_comma;break; + case SDLK_SLASH:code=KBD_slash;break; + + case SDLK_INSERT:code=KBD_insert;break; + case SDLK_HOME:code=KBD_home;break; + case SDLK_PAGEUP:code=KBD_pageup;break; + case SDLK_DELETE:code=KBD_delete;break; + case SDLK_END:code=KBD_end;break; + case SDLK_PAGEDOWN:code=KBD_pagedown;break; + case SDLK_LEFT:code=KBD_left;break; + case SDLK_UP:code=KBD_up;break; + case SDLK_DOWN:code=KBD_down;break; + case SDLK_RIGHT:code=KBD_right;break; + + case SDLK_KP1:code=KBD_kp1;break; + case SDLK_KP2:code=KBD_kp2;break; + case SDLK_KP3:code=KBD_kp3;break; + case SDLK_KP4:code=KBD_kp4;break; + case SDLK_KP5:code=KBD_kp5;break; + case SDLK_KP6:code=KBD_kp6;break; + case SDLK_KP7:code=KBD_kp7;break; + case SDLK_KP8:code=KBD_kp8;break; + case SDLK_KP9:code=KBD_kp9;break; + case SDLK_KP0:code=KBD_kp0;break; + + case SDLK_KP_DIVIDE:code=KBD_kpslash;break; + case SDLK_KP_MULTIPLY:code=KBD_kpmultiply;break; + case SDLK_KP_MINUS:code=KBD_kpminus;break; + case SDLK_KP_PLUS:code=KBD_kpplus;break; + case SDLK_KP_ENTER:code=KBD_kpenter;break; + case SDLK_KP_PERIOD:code=KBD_kpperiod;break; + +// case SDLK_:code=key_;break; + /* Special Keys */ + default: +//TODO maybe give warning for keypress unknown + return; + } + KEYBOARD_AddKey(code,(key->state==SDL_PRESSED)); +} + +static void HandleMouseMotion(SDL_MouseMotionEvent * motion) { + if (!sdl.mouse_grabbed) { + Mouse_CursorSet((float)motion->x/(float)sdl.width,(float)motion->y/(float)sdl.height); + } else { + Mouse_CursorMoved((float)motion->xrel/(float)sdl.width,(float)motion->yrel/(float)sdl.height); + } +} + +static void HandleMouseButton(SDL_MouseButtonEvent * button) { + switch (button->state) { + case SDL_PRESSED: + switch (button->button) { + case SDL_BUTTON_LEFT: + Mouse_ButtonPressed(0); + break; + case SDL_BUTTON_RIGHT: + Mouse_ButtonPressed(1); + break; + case SDL_BUTTON_MIDDLE: + Mouse_ButtonPressed(2); + break; + } + break; + case SDL_RELEASED: + switch (button->button) { + case SDL_BUTTON_LEFT: + Mouse_ButtonReleased(0); + break; + case SDL_BUTTON_RIGHT: + Mouse_ButtonReleased(1); + break; + case SDL_BUTTON_MIDDLE: + Mouse_ButtonReleased(2); + break; + } + break; + } +} + +static void HandleJoystickAxis(SDL_JoyAxisEvent * jaxis) { + switch (jaxis->axis) { + case 0: + JOYSTICK_Move_X(0,(float)(jaxis->value/32768.0)); + break; + case 1: + JOYSTICK_Move_Y(0,(float)(jaxis->value/32768.0)); + break; + } +} + +static void HandleJoystickButton(SDL_JoyButtonEvent * jbutton) { + bool state; + state=jbutton->type==SDL_JOYBUTTONDOWN; + if (jbutton->button<2) { + JOYSTICK_Button(0,jbutton->button,state); + } +} + + +static void HandleVideoResize(SDL_ResizeEvent * resize) { + Bitu width,height; + width=resize->w; + height=resize->h; + if (sdl.resize) { + GFX_Stop(); + (*sdl.resize)(&width,&height); + sdl.width=width; + sdl.height=height; + ResetScreen(); + GFX_Start(); + } +} + +void GFX_Events() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_KEYDOWN: + case SDL_KEYUP: + HandleKey(&event.key); + break; + case SDL_MOUSEMOTION: + HandleMouseMotion(&event.motion); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + HandleMouseButton(&event.button); + break; + case SDL_JOYAXISMOTION: + HandleJoystickAxis(&event.jaxis); + break; + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: + HandleJoystickButton(&event.jbutton); + break; + case SDL_VIDEORESIZE: + HandleVideoResize(&event.resize); + break; + case SDL_QUIT: + E_Exit("Closed the SDL Window"); + break; + } + } +} +#if 0 + +void E_Exit(char * format,...) { + char buf[1024]; + + va_list msg; + strcpy(buf,"EXIT:"); + va_start(msg,format); + vsprintf(buf+strlen(buf),format,msg); + va_end(msg); + waddstr(dbg.win_out,buf); + wprintw(dbg.win_out," %d\n",cycle_count); + wrefresh(dbg.win_out); + throw ((Bitu)1); +} + +#endif + + +void GFX_ShowMsg(char * msg) { + char buf[1024]; + strcpy(buf,msg); + strcat(buf,"\n"); + printf(buf); +}; + +int main(int argc, char* argv[]) { + try { + if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER +#ifndef DISABLE_JOYSTICK + |SDL_INIT_JOYSTICK + +#endif + ) < 0 ) { + E_Exit("Can't init SDL"); + } + GFX_StartUp(); +/* Init all the dosbox subsystems */ + DOSBOX_Init(argc,argv); +/* Start the systems that SDL should provide */ +#ifndef DISABLE_JOYSTICK + if (SDL_NumJoysticks()>0) { + SDL_JoystickEventState(SDL_ENABLE); + sdl.joy=SDL_JoystickOpen(0); + LOG_MSG("Using joystick %s with %d axes and %d buttons",SDL_JoystickName(0),SDL_JoystickNumAxes(sdl.joy),SDL_JoystickNumButtons(sdl.joy)); + JOYSTICK_Enable(0,true); +#endif + } +/* Start dosbox up */ + DOSBOX_StartUp(); + } + catch (Bitu e) { + LOG_MSG("Exit to error %d",e); + } + GFX_Stop(); + + + + return 0; +}; \ No newline at end of file diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am index 42bb606..8f6507d 100644 --- a/src/hardware/Makefile.am +++ b/src/hardware/Makefile.am @@ -1,15 +1,11 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include - -SUBDIRS = serialport - -EXTRA_DIST = opl.cpp opl.h fmopl.c fmopl.h ymf262.h ymf262.c adlib.h dbopl.h - -noinst_LIBRARIES = libhardware.a - -libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler.cpp joystick.cpp keyboard.cpp \ - memory.cpp mixer.cpp pcspeaker.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \ - vga.cpp vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp vga_other.cpp \ - vga_memory.cpp vga_misc.cpp vga_seq.cpp vga_xga.cpp vga_s3.cpp vga_tseng.cpp vga_paradise.cpp \ - cmos.cpp disney.cpp gus.cpp mpu401.cpp ipx.cpp ipxserver.cpp dbopl.cpp - - +AM_CPPFLAGS = -I$(top_srcdir)/include + +EXTRA_DIST = fmopl.c fmopl.h + +noinst_LIBRARIES = libhardware.a + +libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler.cpp joystick.cpp keyboard.cpp \ + memory.cpp mixer.cpp pcspeaker.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \ + vga.cpp vga.h vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_fonts.cpp vga_gfx.cpp \ + vga_memory.cpp vga_misc.cpp vga_seq.cpp font-switch.h ega-switch.h + diff --git a/src/hardware/Makefile.in b/src/hardware/Makefile.in new file mode 100644 index 0000000..3ef7bf2 --- /dev/null +++ b/src/hardware/Makefile.in @@ -0,0 +1,356 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +AM_CPPFLAGS = -I$(top_srcdir)/include + +EXTRA_DIST = fmopl.c fmopl.h + +noinst_LIBRARIES = libhardware.a + +libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler.cpp joystick.cpp keyboard.cpp \ + memory.cpp mixer.cpp pcspeaker.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \ + vga.cpp vga.h vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_fonts.cpp vga_gfx.cpp \ + vga_memory.cpp vga_misc.cpp vga_seq.cpp font-switch.h ega-switch.h + +subdir = src/hardware +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libhardware_a_AR = $(AR) cru +libhardware_a_LIBADD = +am_libhardware_a_OBJECTS = adlib.$(OBJEXT) dma.$(OBJEXT) \ + gameblaster.$(OBJEXT) hardware.$(OBJEXT) iohandler.$(OBJEXT) \ + joystick.$(OBJEXT) keyboard.$(OBJEXT) memory.$(OBJEXT) \ + mixer.$(OBJEXT) pcspeaker.$(OBJEXT) pic.$(OBJEXT) \ + sblaster.$(OBJEXT) tandy_sound.$(OBJEXT) timer.$(OBJEXT) \ + vga.$(OBJEXT) vga_attr.$(OBJEXT) vga_crtc.$(OBJEXT) \ + vga_dac.$(OBJEXT) vga_draw.$(OBJEXT) vga_fonts.$(OBJEXT) \ + vga_gfx.$(OBJEXT) vga_memory.$(OBJEXT) vga_misc.$(OBJEXT) \ + vga_seq.$(OBJEXT) +libhardware_a_OBJECTS = $(am_libhardware_a_OBJECTS) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/adlib.Po ./$(DEPDIR)/dma.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/gameblaster.Po ./$(DEPDIR)/hardware.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/iohandler.Po ./$(DEPDIR)/joystick.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/keyboard.Po ./$(DEPDIR)/memory.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mixer.Po ./$(DEPDIR)/pcspeaker.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pic.Po ./$(DEPDIR)/sblaster.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/tandy_sound.Po ./$(DEPDIR)/timer.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/vga.Po ./$(DEPDIR)/vga_attr.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/vga_crtc.Po ./$(DEPDIR)/vga_dac.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/vga_draw.Po ./$(DEPDIR)/vga_fonts.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/vga_gfx.Po ./$(DEPDIR)/vga_memory.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/vga_misc.Po ./$(DEPDIR)/vga_seq.Po +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +CXXFLAGS = @CXXFLAGS@ +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libhardware_a_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libhardware_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/hardware/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +AR = ar + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libhardware.a: $(libhardware_a_OBJECTS) $(libhardware_a_DEPENDENCIES) + -rm -f libhardware.a + $(libhardware_a_AR) libhardware.a $(libhardware_a_OBJECTS) $(libhardware_a_LIBADD) + $(RANLIB) libhardware.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adlib.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gameblaster.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hardware.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iohandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/joystick.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyboard.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcspeaker.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pic.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sblaster.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tandy_sound.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_attr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_crtc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_dac.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_draw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_fonts.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_gfx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_memory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_misc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_seq.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `cygpath -w $<` +CXXDEPMODE = @CXXDEPMODE@ +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic tags uninstall uninstall-am \ + uninstall-info-am + +# 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/hardware/adlib.cpp b/src/hardware/adlib.cpp index 3411411..171772d 100644 --- a/src/hardware/adlib.cpp +++ b/src/hardware/adlib.cpp @@ -1,804 +1,224 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: adlib.cpp,v 1.38 2009/04/28 21:48:24 harekiet Exp $ */ - -#include -#include -#include -#include -#include "adlib.h" - -#include "setup.h" -#include "mapper.h" -#include "mem.h" -#include "dbopl.h" - -/* - Thanks to vdmsound for nice simple way to implement this -*/ - -#ifdef _MSC_VER - /* Disable recurring warnings */ -# pragma warning ( disable : 4018 ) -# pragma warning ( disable : 4244 ) -#endif - - -#define logerror - - -struct __MALLOCPTR { - void* m_ptr; - - __MALLOCPTR(void) : m_ptr(NULL) { } - __MALLOCPTR(void* src) : m_ptr(src) { } - void* operator=(void* rhs) { return (m_ptr = rhs); } - operator int*() const { return (int*)m_ptr; } - operator int**() const { return (int**)m_ptr; } - operator char*() const { return (char*)m_ptr; } -}; - - -namespace OPL2 { - #include "opl.cpp" - - struct Handler : public Adlib::Handler { - virtual void WriteReg( Bit32u reg, Bit8u val ) { - adlib_write(reg,val); - } - virtual Bit32u WriteAddr( Bit32u port, Bit8u val ) { - return val; - } - - virtual void Generate( MixerChannel* chan, Bitu samples ) { - Bit16s buf[1024]; - while( samples > 0 ) { - Bitu todo = samples > 1024 ? 1024 : samples; - samples -= todo; - adlib_getsample(buf, todo); - chan->AddSamples_m16( todo, buf ); - } - } - virtual void Init( Bitu rate ) { - adlib_init(rate); - } - ~Handler() { - } - }; -} - -namespace OPL3 { - #define OPLTYPE_IS_OPL3 - #include "opl.cpp" - - struct Handler : public Adlib::Handler { - virtual void WriteReg( Bit32u reg, Bit8u val ) { - adlib_write(reg,val); - } - virtual Bit32u WriteAddr( Bit32u port, Bit8u val ) { - adlib_write_index(port, val); - return index; - } - virtual void Generate( MixerChannel* chan, Bitu samples ) { - Bit16s buf[1024*2]; - while( samples > 0 ) { - Bitu todo = samples > 1024 ? 1024 : samples; - samples -= todo; - adlib_getsample(buf, todo); - chan->AddSamples_s16( todo, buf ); - } - } - virtual void Init( Bitu rate ) { - adlib_init(rate); - } - ~Handler() { - } - }; -} - - -namespace old_OPL2 { - #define OPL2_INTERNAL_FREQ 3579545 // The OPL2 operates at ~3.6MHz - #define HAS_YM3812 1 - #include "fmopl.c" - - struct Handler : public Adlib::Handler { - virtual void WriteReg( Bit32u reg, Bit8u val ) { - OPLWriteReg( OPL_YM3812[ 0 ], reg, val ); - } - virtual Bit32u WriteAddr( Bit32u port, Bit8u val ) { - OPL_YM3812[ 0 ]->address = val; - return val; - } - - virtual void Generate( MixerChannel* chan, Bitu samples ) { - Bit16s buf[1024]; - while( samples > 0 ) { - Bitu todo = samples > 1024 ? 1024 : samples; - samples -= todo; - YM3812UpdateOne( 0, buf, todo ); - chan->AddSamples_m16( todo, buf ); - } - } - virtual void Init( Bitu rate ) { - if ( YM3812Init( 1, OPL2_INTERNAL_FREQ, rate )) { - E_Exit("Can't create OPL2 Emulator"); - }; - } - ~Handler() { - YM3812Shutdown(); - } - }; -} -#undef OSD_CPU_H -#undef TL_TAB_LEN - -namespace old_OPL3 { - #define OPL3_INTERNAL_FREQ 14318180 // The OPL3 operates at ~14.3MHz - #define HAS_YMF262 1 - #include "ymf262.c" - - struct Handler : public Adlib::Handler { - virtual void WriteReg( Bit32u reg, Bit8u val ) { - OPL3WriteReg( YMF262[0], reg, val ); - } - virtual Bit32u WriteAddr( Bit32u port, Bit8u val ) { - OPL3Write( YMF262[0], port, val ); - return YMF262[0]->address; - } - virtual void Generate( MixerChannel* chan, Bitu samples ) { - Bit16s buf[2][1024]; - while( samples > 0 ) { - Bitu todo = samples > 1024 ? 1024 : samples; - samples -= todo; - YMF262UpdateOne( 0, buf[0], todo ); - chan->AddSamples_s16( todo, buf[0] ); - } - } - virtual void Init( Bitu rate ) { - if ( YMF262Init( 1, OPL3_INTERNAL_FREQ, rate )) { - E_Exit("Can't create OPL3 Emulator"); - }; - } - ~Handler() { - YMF262Shutdown(); - } - }; -} - - - -#define RAW_SIZE 1024 - - -/* - Main Adlib implementation - -*/ - -namespace Adlib { - - -/* Raw DRO capture stuff */ - -#ifdef _MSC_VER -#pragma pack (1) -#endif - -#define HW_OPL2 0 -#define HW_DUALOPL2 1 -#define HW_OPL3 2 - -struct RawHeader { - Bit8u id[8]; /* 0x00, "DBRAWOPL" */ - Bit16u versionHigh; /* 0x08, size of the data following the m */ - Bit16u versionLow; /* 0x0a, size of the data following the m */ - Bit32u commands; /* 0x0c, Bit32u amount of command/data pairs */ - Bit32u milliseconds; /* 0x10, Bit32u Total milliseconds of data in this chunk */ - Bit8u hardware; /* 0x14, Bit8u Hardware Type 0=opl2,1=dual-opl2,2=opl3 */ - Bit8u format; /* 0x15, Bit8u Format 0=cmd/data interleaved, 1 maybe all cdms, followed by all data */ - Bit8u compression; /* 0x16, Bit8u Compression Type, 0 = No Compression */ - Bit8u delay256; /* 0x17, Bit8u Delay 1-256 msec command */ - Bit8u delayShift8; /* 0x18, Bit8u (delay + 1)*256 */ - Bit8u conversionTableSize; /* 0x191, Bit8u Raw Conversion Table size */ -} GCC_ATTRIBUTE(packed); -#ifdef _MSC_VER -#pragma pack() -#endif -/* - The Raw Tables is < 128 and is used to convert raw commands into a full register index - When the high bit of a raw command is set it indicates the cmd/data pair is to be sent to the 2nd port - After the conversion table the raw data follows immediatly till the end of the chunk -*/ - -//Table to map the opl register to one <127 for dro saving -class Capture { - //127 entries to go from raw data to registers - Bit8u ToReg[127]; - //How many entries in the ToPort are used - Bit8u RawUsed; - //256 entries to go from port index to raw data - Bit8u ToRaw[256]; - Bit8u delay256; - Bit8u delayShift8; - RawHeader header; - - FILE* handle; //File used for writing - Bit32u startTicks; //Start used to check total raw length on end - Bit32u lastTicks; //Last ticks when last last cmd was added - Bit8u buf[1024]; //16 added for delay commands and what not - Bit32u bufUsed; - Bit8u cmd[2]; //Last cmd's sent to either ports - bool doneOpl3; - bool doneDualOpl2; - - RegisterCache* cache; - - void MakeEntry( Bit8u reg, Bit8u& raw ) { - ToReg[ raw ] = reg; - ToRaw[ reg ] = raw; - raw++; - } - void MakeTables( void ) { - Bit8u index = 0; - memset( ToReg, 0xff, sizeof ( ToReg ) ); - memset( ToRaw, 0xff, sizeof ( ToRaw ) ); - //Select the entries that are valid and the index is the mapping to the index entry - MakeEntry( 0x01, index ); //0x01: Waveform select - MakeEntry( 0x04, index ); //104: Four-Operator Enable - MakeEntry( 0x05, index ); //105: OPL3 Mode Enable - MakeEntry( 0x08, index ); //08: CSW / NOTE-SEL - MakeEntry( 0xbd, index ); //BD: Tremolo Depth / Vibrato Depth / Percussion Mode / BD/SD/TT/CY/HH On - //Add the 32 byte range that hold the 18 operators - for ( int i = 0 ; i < 24; i++ ) { - if ( (i & 7) < 6 ) { - MakeEntry(0x20 + i, index ); //20-35: Tremolo / Vibrato / Sustain / KSR / Frequency Multiplication Facto - MakeEntry(0x40 + i, index ); //40-55: Key Scale Level / Output Level - MakeEntry(0x60 + i, index ); //60-75: Attack Rate / Decay Rate - MakeEntry(0x80 + i, index ); //80-95: Sustain Level / Release Rate - MakeEntry(0xe0 + i, index ); //E0-F5: Waveform Select - } - } - //Add the 9 byte range that hold the 9 channels - for ( int i = 0 ; i < 9; i++ ) { - MakeEntry(0xa0 + i, index ); //A0-A8: Frequency Number - MakeEntry(0xb0 + i, index ); //B0-B8: Key On / Block Number / F-Number(hi bits) - MakeEntry(0xc0 + i, index ); //C0-C8: FeedBack Modulation Factor / Synthesis Type - } - //Store the amount of bytes the table contains - RawUsed = index; -// assert( RawUsed <= 127 ); - delay256 = RawUsed; - delayShift8 = RawUsed+1; - } - - void ClearBuf( void ) { - fwrite( buf, 1, bufUsed, handle ); - header.commands += bufUsed / 2; - bufUsed = 0; - } - void AddBuf( Bit8u raw, Bit8u val ) { - buf[bufUsed++] = raw; - buf[bufUsed++] = val; - if ( bufUsed >= sizeof( buf ) ) { - ClearBuf(); - } - } - void AddWrite( Bit32u regFull, Bit8u val ) { - Bit8u regMask = regFull & 0xff; - /* - Do some special checks if we're doing opl3 or dualopl2 commands - Although you could pretty much just stick to always doing opl3 on the player side - */ - //Enabling opl3 4op modes will make us go into opl3 mode - if ( header.hardware != HW_OPL3 && regFull == 0x104 && val && (*cache)[0x105] ) { - header.hardware = HW_OPL3; - } - //Writing a keyon to a 2nd address enables dual opl2 otherwise - //Maybe also check for rhythm - if ( header.hardware == HW_OPL2 && regFull >= 0x1b0 && regFull <=0x1b8 && val ) { - header.hardware = HW_DUALOPL2; - } - Bit8u raw = ToRaw[ regMask ]; - if ( raw == 0xff ) - return; - if ( regFull & 0x100 ) - raw |= 128; - AddBuf( raw, val ); - } - void WriteCache( void ) { - Bitu i, val; - /* Check the registers to add */ - for (i=0;i<256;i++) { - //Skip the note on entries - if (i>=0xb0 && i<=0xb8) - continue; - val = (*cache)[ i ]; - if (val) { - AddWrite( i, val ); - } - val = (*cache)[ 0x100 + i ]; - if (val) { - AddWrite( 0x100 + i, val ); - } - } - } - void InitHeader( void ) { - memset( &header, 0, sizeof( header ) ); - memcpy( header.id, "DBRAWOPL", 8 ); - header.versionLow = 0; - header.versionHigh = 2; - header.delay256 = delay256; - header.delayShift8 = delayShift8; - header.conversionTableSize = RawUsed; - } - void CloseFile( void ) { - if ( handle ) { - ClearBuf(); - /* Endianize the header and write it to beginning of the file */ - var_write( &header.versionHigh, header.versionHigh ); - var_write( &header.versionLow, header.versionLow ); - var_write( &header.commands, header.commands ); - var_write( &header.milliseconds, header.milliseconds ); - fseek( handle, 0, SEEK_SET ); - fwrite( &header, 1, sizeof( header ), handle ); - fclose( handle ); - handle = 0; - } - } -public: - bool DoWrite( Bit32u regFull, Bit8u val ) { - Bit8u regMask = regFull & 0xff; - //Check the raw index for this register if we actually have to save it - if ( handle ) { - /* - Check if we actually care for this to be logged, else just ignore it - */ - Bit8u raw = ToRaw[ regMask ]; - if ( raw == 0xff ) { - return true; - } - /* Check if this command will not just replace the same value - in a reg that doesn't do anything with it - */ - if ( (*cache)[ regFull ] == val ) - return true; - /* Check how much time has passed */ - Bitu passed = PIC_Ticks - lastTicks; - lastTicks = PIC_Ticks; - header.milliseconds += passed; - - //if ( passed > 0 ) LOG_MSG( "Delay %d", passed ) ; - - // If we passed more than 30 seconds since the last command, we'll restart the the capture - if ( passed > 30000 ) { - CloseFile(); - goto skipWrite; - } - while (passed > 0) { - if (passed < 257) { //1-256 millisecond delay - AddBuf( delay256, passed - 1 ); - passed = 0; - } else { - Bitu shift = (passed >> 8); - passed -= shift << 8; - AddBuf( delayShift8, shift - 1 ); - } - } - AddWrite( regFull, val ); - return true; - } -skipWrite: - //Not yet capturing to a file here - //Check for commands that would start capturing, if it's not one of them return - if ( !( - //note on in any channel - ( regMask>=0xb0 && regMask<=0xb8 && (val&0x020) ) || - //Percussion mode enabled and a note on in any percussion instrument - ( regMask == 0xbd && ( (val&0x3f) > 0x20 ) ) - )) { - return true; - } - handle = OpenCaptureFile("Raw Opl",".dro"); - if (!handle) - return false; - InitHeader(); - //Prepare space at start of the file for the header - fwrite( &header, 1, sizeof(header), handle ); - /* write the Raw To Reg table */ - fwrite( &ToReg, 1, RawUsed, handle ); - /* Write the cache of last commands */ - WriteCache( ); - /* Write the command that triggered this */ - AddWrite( regFull, val ); - //Init the timing information for the next commands - lastTicks = PIC_Ticks; - startTicks = PIC_Ticks; - return true; - } - Capture( RegisterCache* _cache ) { - cache = _cache; - handle = 0; - bufUsed = 0; - MakeTables(); - } - ~Capture() { - CloseFile(); - } - -}; - -/* -Chip -*/ - -bool Chip::Write( Bit32u reg, Bit8u val ) { - switch ( reg ) { - case 0x02: - timer[0].counter = val; - return true; - case 0x03: - timer[1].counter = val; - return true; - case 0x04: - double time; - time = PIC_FullIndex(); - if ( val & 0x80 ) { - timer[0].Reset( time ); - timer[1].Reset( time ); - } else { - timer[0].Update( time ); - timer[1].Update( time ); - if ( val & 0x1 ) { - timer[0].Start( time, 80 ); - } else { - timer[0].Stop( ); - } - timer[0].masked = (val & 0x40) > 0; - if ( timer[0].masked ) - timer[0].overflow = false; - if ( val & 0x2 ) { - timer[1].Start( time, 320 ); - } else { - timer[1].Stop( ); - } - timer[1].masked = (val & 0x20) > 0; - if ( timer[1].masked ) - timer[1].overflow = false; - - } - return true; - } - return false; -} - - -Bit8u Chip::Read( ) { - double time( PIC_FullIndex() ); - timer[0].Update( time ); - timer[1].Update( time ); - Bit8u ret = 0; - //Overflow won't be set if a channel is masked - if ( timer[0].overflow ) { - ret |= 0x40; - ret |= 0x80; - } - if ( timer[1].overflow ) { - ret |= 0x20; - ret |= 0x80; - } - return ret; - -} - -void Module::CacheWrite( Bit32u reg, Bit8u val ) { - //capturing? - if ( capture ) { - capture->DoWrite( reg, val ); - } - //Store it into the cache - cache[ reg ] = val; -} - -void Module::DualWrite( Bit8u index, Bit8u reg, Bit8u val ) { - //Make sure you don't use opl3 features - //Don't allow write to disable opl3 - if ( reg == 5 ) { - return; - } - //Only allow 4 waveforms - if ( reg >= 0xE0 ) { - val &= 3; - } - //Write to the timer? - if ( chip[index].Write( reg, val ) ) - return; - //Enabling panning - if ( reg >= 0xc0 && reg <0xc8 ) { - val &= 7; - val |= index ? 0xA0 : 0x50; - } - Bit32u fullReg = reg + (index ? 0x100 : 0); - handler->WriteReg( fullReg, val ); - CacheWrite( fullReg, val ); -} - - -void Module::PortWrite( Bitu port, Bitu val, Bitu iolen ) { - //Keep track of last write time - lastUsed = PIC_Ticks; - //Maybe only enable with a keyon? - if ( !mixerChan->enabled ) { - mixerChan->Enable(true); - } - if ( port&1 ) { - switch ( mode ) { - case MODE_OPL2: - case MODE_OPL3: - if ( !chip[0].Write( reg.normal, val ) ) { - handler->WriteReg( reg.normal, val ); - CacheWrite( reg.normal, val ); - } - break; - case MODE_DUALOPL2: - //Not a 0x??8 port, then write to a specific port - if ( !(port & 0x8) ) { - Bit8u index = ( port & 2 ) >> 1; - DualWrite( index, reg.dual[index], val ); - } else { - //Write to both ports - DualWrite( 0, reg.dual[0], val ); - DualWrite( 1, reg.dual[1], val ); - } - break; - } - } else { - //Ask the handler to write the address - //Make sure to clip them in the right range - switch ( mode ) { - case MODE_OPL2: - reg.normal = handler->WriteAddr( port, val ) & 0xff; - break; - case MODE_OPL3: - reg.normal = handler->WriteAddr( port, val ) & 0x1ff; - break; - case MODE_DUALOPL2: - //Not a 0x?88 port, when write to a specific side - if ( !(port & 0x8) ) { - Bit8u index = ( port & 2 ) >> 1; - reg.dual[index] = val & 0xff; - } else { - reg.dual[0] = val & 0xff; - reg.dual[1] = val & 0xff; - } - break; - } - } -} - - -Bitu Module::PortRead( Bitu port, Bitu iolen ) { - switch ( mode ) { - case MODE_OPL2: - //We allocated 4 ports, so just return -1 for the higher ones - if ( !(port & 3 ) ) { - //Make sure the low bits are 6 on opl2 - return chip[0].Read() | 0x6; - } else { - return 0xff; - } - case MODE_OPL3: - //We allocated 4 ports, so just return -1 for the higher ones - if ( !(port & 3 ) ) { - return chip[0].Read(); - } else { - return 0xff; - } - case MODE_DUALOPL2: - //Only return for the lower ports - if ( port & 1 ) { - return 0xff; - } - //Make sure the low bits are 6 on opl2 - return chip[ (port >> 1) & 1].Read() | 0x6; - } - return 0; -} - - -void Module::Init( Mode m ) { - mode = m; - switch ( mode ) { - case MODE_OPL3: - case MODE_OPL2: - break; - case MODE_DUALOPL2: - //Setup opl3 mode in the hander - handler->WriteReg( 0x105, 1 ); - //Also set it up in the cache so the capturing will start opl3 - CacheWrite( 0x105, 1 ); - break; - } -} - -}; //namespace - - - -static Adlib::Module* module = 0; - -static void OPL_CallBack(Bitu len) { - module->handler->Generate( module->mixerChan, len ); - //Disable the sound generation after 30 seconds of silence - if ((PIC_Ticks - module->lastUsed) > 30000) { - module->mixerChan->Enable(false); - } -} - -static Bitu OPL_Read(Bitu port,Bitu iolen) { - return module->PortRead( port, iolen ); -} - -void OPL_Write(Bitu port,Bitu val,Bitu iolen) { - module->PortWrite( port, val, iolen ); -} - -/* - Save the current state of the operators as instruments in an reality adlib tracker file -*/ -static void SaveRad() { - char b[16 * 1024]; - int w = 0; - - FILE* handle = OpenCaptureFile("RAD Capture",".rad"); - if ( !handle ) - return; - //Header - fwrite( "RAD by REALiTY!!", 1, 16, handle ); - b[w++] = 0x10; //version - b[w++] = 0x06; //default speed and no description - //Write 18 instuments for all operators in the cache - for ( int i = 0; i < 18; i++ ) { - Bit8u* set = module->cache + ( i / 9 ) * 256; - Bitu offset = ((i % 9) / 3) * 8 + (i % 3); - Bit8u* base = set + offset; - b[w++] = 1 + i; //instrument number - b[w++] = base[0x23]; - b[w++] = base[0x20]; - b[w++] = base[0x43]; - b[w++] = base[0x40]; - b[w++] = base[0x63]; - b[w++] = base[0x60]; - b[w++] = base[0x83]; - b[w++] = base[0x80]; - b[w++] = set[0xc0 + (i % 9)]; - b[w++] = base[0xe3]; - b[w++] = base[0xe0]; - } - b[w++] = 0; //instrument 0, no more instruments following - b[w++] = 1; //1 pattern following - //Zero out the remaing part of the file a bit to make rad happy - for ( int i = 0; i < 64; i++ ) { - b[w++] = 0; - } - fwrite( b, 1, w, handle ); - fclose( handle ); -}; - - -static void OPL_SaveRawEvent(bool pressed) { - if (!pressed) - return; -// SaveRad();return; - /* Check for previously opened wave file */ - if ( module->capture ) { - delete module->capture; - module->capture = 0; - LOG_MSG("Stopped Raw OPL capturing."); - } else { - LOG_MSG("Preparing to capture Raw OPL, will start with first note played."); - module->capture = new Adlib::Capture( &module->cache ); - } -} - -namespace Adlib { - -Module::Module( Section* configuration ) : Module_base(configuration) { - reg.dual[0] = 0; - reg.dual[1] = 0; - reg.normal = 0; - handler = 0; - capture = 0; - - Section_prop * section=static_cast(configuration); - Bitu base = section->Get_hex("sbbase"); - Bitu rate = section->Get_int("oplrate"); - std::string oplemu( section->Get_string( "oplemu" ) ); - - mixerChan = mixerObject.Install(OPL_CallBack,rate,"FM"); - mixerChan->SetScale( 2.0 ); - if (oplemu == "old") { - if ( oplmode == OPL_opl2 ) { - handler = new old_OPL2::Handler(); - } else { - handler = new old_OPL3::Handler(); - } - } else if (oplemu == "fast") { - handler = new DBOPL::Handler(); - } else if (oplemu == "compat") { - if ( oplmode == OPL_opl2 ) { - handler = new OPL2::Handler(); - } else { - handler = new OPL3::Handler(); - } - } else { - handler = new DBOPL::Handler(); - } - handler->Init( rate ); - Bit8u portRange = 4; //opl2 will set this to 2 - switch ( oplmode ) { - case OPL_opl2: - portRange = 2; - Init( Adlib::MODE_OPL2 ); - break; - case OPL_dualopl2: - Init( Adlib::MODE_DUALOPL2 ); - break; - case OPL_opl3: - Init( Adlib::MODE_OPL3 ); - break; - } - //0x388 range - WriteHandler[0].Install(0x388,OPL_Write,IO_MB, portRange ); - ReadHandler[0].Install(0x388,OPL_Read,IO_MB, portRange - 1 ); - //0x220 range - WriteHandler[1].Install(base,OPL_Write,IO_MB, portRange ); - ReadHandler[1].Install(base,OPL_Read,IO_MB, portRange - 1 ); - //0x228 range - WriteHandler[2].Install(base+8,OPL_Write,IO_MB,2); - ReadHandler[2].Install(base+8,OPL_Read,IO_MB,1); - - MAPPER_AddHandler(OPL_SaveRawEvent,MK_f7,MMOD1|MMOD2,"caprawopl","Cap OPL"); -} - -Module::~Module() { - if ( capture ) { - delete capture; - } - if ( handler ) { - delete handler; - } -} - -//Initialize static members -OPL_Mode Module::oplmode=OPL_none; - -}; //Adlib Namespace - - -void OPL_Init(Section* sec,OPL_Mode oplmode) { - Adlib::Module::oplmode = oplmode; - module = new Adlib::Module( sec ); -} - -void OPL_ShutDown(Section* sec){ - delete module; - module = 0; - -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include "dosbox.h" +#include "inout.h" +#include "mixer.h" +#include "timer.h" +#include "hardware.h" + +/* + Thanks to vdmsound for nice simple way to implement this +*/ + +namespace MAME { + /* Defines */ +# define logerror(x) + /* Disable recurring warnings */ +#pragma warning ( disable : 4018 ) +#pragma warning ( disable : 4244 ) + + /* Bring in Tatsuyuki Satoh's OPL emulation */ +#define HAS_YM3812 1 +#include "fmopl.c" +} + +struct OPLTimer_t { + bool isEnabled; + bool isMasked; + bool isOverflowed; + Bit32u count; + Bit32u base; +}; + +static OPLTimer_t timer1,timer2; +static MAME::FM_OPL * myopl; +static Bit8u regsel; +#define OPL_INTERNAL_FREQ 3600000 // The OPL operates at 3.6MHz +static MIXER_Channel * adlib_chan; + +static void ADLIB_CallBack(Bit8u *stream, Bit32u len) { + /* Check for size to update and check for 1 ms updates to the opl registers */ + /* Calculate teh machine ms we are at now */ + + /* update 1 ms of data */ + MAME::YM3812UpdateOne(myopl,(MAME::INT16 *)stream,len); +} + +static Bit8u read_p388(Bit32u port) { + Bit8u ret=0; + Bit32u new_ticks=GetTicks(); + if (timer1.isEnabled) { + if ((new_ticks-timer1.base)>timer1.count) { + timer1.isOverflowed=true; + timer1.base=new_ticks; + } + if (timer1.isOverflowed || !timer1.isMasked) { + ret|=0xc0; + } + } + if (timer2.isEnabled) { + if ((new_ticks-timer2.base)>timer2.count) { + timer2.isOverflowed=true; + timer2.base=new_ticks; + } + if (timer2.isOverflowed || !timer2.isMasked) { + ret|=0xA0; + } + } + return ret; +} + +static void write_p388(Bit32u port,Bit8u val) { + regsel=val; +} + +static void write_p389(Bit32u port,Bit8u val) { + switch (regsel) { + case 0x02: /* Timer 1 */ + timer1.count=(val*80/1000); + return; + case 0x03: /* Timer 2 */ + timer2.count=(val*320/1000); + return; + case 0x04: /* IRQ clear / mask and Timer enable */ + if (val&0x80) { + timer1.isOverflowed=false; + timer2.isOverflowed=false; + return; + } + if (val&0x40) { + timer1.isMasked=true; + } else { + timer1.isMasked=false; + timer1.isEnabled=((val&1)>0); + timer1.base=GetTicks(); + } + if (val&0x20) { + timer2.isMasked=true; + } else { + timer2.isMasked=false; + timer2.isEnabled=((val&2)>0); + timer2.base=GetTicks(); + } + return; + default: /* Normal OPL call queue it */ + MAME::OPLWriteReg(myopl,regsel,val); + } + +} + +static HWBlock hw_adlib; +static bool adlib_enabled; + +static void ADLIB_Enable(bool enable) { + if (enable) { + adlib_enabled=true; + MIXER_Enable(adlib_chan,true); + IO_RegisterWriteHandler(0x388,write_p388,"ADLIB Register select"); + IO_RegisterWriteHandler(0x389,write_p389,"ADLIB Data Write"); + IO_RegisterReadHandler(0x388,read_p388,"ADLIB Status"); + + IO_RegisterWriteHandler(0x220,write_p388,"ADLIB Register select"); + IO_RegisterWriteHandler(0x221,write_p389,"ADLIB Data Write"); + IO_RegisterReadHandler(0x220,read_p388,"ADLIB Status"); + } else { + adlib_enabled=false; + MIXER_Enable(adlib_chan,false); + IO_FreeWriteHandler(0x220); + IO_FreeWriteHandler(0x221); + IO_FreeReadHandler(0x220); + IO_FreeWriteHandler(0x388); + IO_FreeWriteHandler(0x389); + IO_FreeReadHandler(0x388); + } +} + + +static void ADLIB_InputHandler(char * line) { + bool s_off=ScanCMDBool(line,"OFF"); + bool s_on=ScanCMDBool(line,"ON"); + char * rem=ScanCMDRemain(line); + if (rem) { + sprintf(line,"Illegal Switch"); + return; + } + if (s_on && s_off) { + sprintf(line,"Can't use /ON and /OFF at the same time"); + return; + } + if (s_on) { + ADLIB_Enable(true); + sprintf(line,"Adlib has been enabled"); + return; + } + if (s_off) { + ADLIB_Enable(false); + sprintf(line,"Adlib has been disabled"); + return; + } + return; +} + +static void ADLIB_OutputHandler (char * towrite) { + if(adlib_enabled) { + sprintf(towrite,"IO %X",0x388); + } else { + sprintf(towrite,"Disabled"); + } +}; + + + + + + + +void ADLIB_Init(void) { + + timer1.isMasked=true; + timer1.base=0; + timer1.count=0; + timer1.isEnabled=false; + timer1.isOverflowed=false; + + timer2.isMasked=true; + timer2.base=0; + timer2.count=0; + timer2.isEnabled=false; + timer2.isOverflowed=false; + + #define ADLIB_FREQ 22050 + myopl=MAME::OPLCreate(0,OPL_INTERNAL_FREQ,ADLIB_FREQ); + + adlib_chan=MIXER_AddChannel(ADLIB_CallBack,ADLIB_FREQ,"ADLIB"); + MIXER_SetMode(adlib_chan,MIXER_16MONO); + + hw_adlib.dev_name="ADLIB"; + hw_adlib.full_name="Adlib FM Synthesizer"; + hw_adlib.next=0; + hw_adlib.help="/ON Enables Adlib\n/OFF Disables Adlib\n"; + hw_adlib.get_input=ADLIB_InputHandler; + hw_adlib.show_status=ADLIB_OutputHandler; + HW_Register(&hw_adlib); + ADLIB_Enable(true); +}; + diff --git a/src/hardware/adlib.h b/src/hardware/adlib.h deleted file mode 100644 index 7a595e9..0000000 --- a/src/hardware/adlib.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: adlib.h,v 1.5 2009/04/28 21:45:43 c2woody Exp $ */ - -#ifndef DOSBOX_ADLIB_H -#define DOSBOX_ADLIB_H - -#include "dosbox.h" -#include "mixer.h" -#include "inout.h" -#include "setup.h" -#include "pic.h" -#include "hardware.h" - - -namespace Adlib { - -struct Timer { - double start; - double delay; - bool enabled, overflow, masked; - Bit8u counter; - Timer() { - masked = false; - overflow = false; - enabled = false; - counter = 0; - delay = 0; - } - //Call update before making any further changes - void Update( double time ) { - if ( !enabled || !delay ) - return; - double deltaStart = time - start; - //Only set the overflow flag when not masked - if ( deltaStart >= 0 && !masked ) { - overflow = 1; - } - } - //On a reset make sure the start is in sync with the next cycle - void Reset(const double& time ) { - overflow = false; - if ( !delay || !enabled ) - return; - double delta = (time - start); - double rem = fmod( delta, delay ); - double next = delay - rem; - start = time + next; - } - void Stop( ) { - enabled = false; - } - void Start( const double& time, Bits scale ) { - //Don't enable again - if ( enabled ) { - return; - } - enabled = true; - delay = 0.001 * (256 - counter ) * scale; - start = time + delay; - } - -}; - -struct Chip { - //Last selected register - Timer timer[2]; - //Check for it being a write to the timer - bool Write( Bit32u addr, Bit8u val ); - //Read the current timer state, will use current double - Bit8u Read( ); -}; - -//The type of handler this is -typedef enum { - MODE_OPL2, - MODE_DUALOPL2, - MODE_OPL3 -} Mode; - -class Handler { -public: - //Write an address to a chip, returns the address the chip sets - virtual Bit32u WriteAddr( Bit32u port, Bit8u val ) = 0; - //Write to a specific register in the chip - virtual void WriteReg( Bit32u addr, Bit8u val ) = 0; - //Generate a certain amount of samples - virtual void Generate( MixerChannel* chan, Bitu samples ) = 0; - //Initialize at a specific sample rate and mode - virtual void Init( Bitu rate ) = 0; - virtual ~Handler() { - } -}; - -//The cache for 2 chips or an opl3 -typedef Bit8u RegisterCache[512]; - -//Internal class used for dro capturing -class Capture; - -class Module: public Module_base { - IO_ReadHandleObject ReadHandler[3]; - IO_WriteHandleObject WriteHandler[3]; - MixerObject mixerObject; - - //Mode we're running in - Mode mode; - //Last selected address in the chip for the different modes - union { - Bit32u normal; - Bit8u dual[2]; - } reg; - void CacheWrite( Bit32u reg, Bit8u val ); - void DualWrite( Bit8u index, Bit8u reg, Bit8u val ); -public: - static OPL_Mode oplmode; - MixerChannel* mixerChan; - Bit32u lastUsed; //Ticks when adlib was last used to turn of mixing after a few second - - Handler* handler; //Handler that will generate the sound - RegisterCache cache; - Capture* capture; - Chip chip[2]; - - //Handle port writes - void PortWrite( Bitu port, Bitu val, Bitu iolen ); - Bitu PortRead( Bitu port, Bitu iolen ); - void Init( Mode m ); - - Module( Section* configuration); - ~Module(); -}; - - -} //Adlib namespace - -#endif diff --git a/src/hardware/cmos.cpp b/src/hardware/cmos.cpp deleted file mode 100644 index 6be919a..0000000 --- a/src/hardware/cmos.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: cmos.cpp,v 1.27 2009/04/26 18:26:10 qbix79 Exp $ */ - -#include - -#include "dosbox.h" -#include "timer.h" -#include "pic.h" -#include "inout.h" -#include "mem.h" -#include "bios_disk.h" -#include "setup.h" - -static struct { - Bit8u regs[0x40]; - bool nmi; - bool bcd; - Bit8u reg; - struct { - bool enabled; - Bit8u div; - float delay; - bool acknowledged; - } timer; - struct { - double timer; - double ended; - double alarm; - } last; - bool update_ended; -} cmos; - -static void cmos_timerevent(Bitu val) { - if (cmos.timer.acknowledged) { - cmos.timer.acknowledged=false; - PIC_ActivateIRQ(8); - } - if (cmos.timer.enabled) { - PIC_AddEvent(cmos_timerevent,cmos.timer.delay); - cmos.regs[0xc] = 0xC0;//Contraption Zack (music) - } -} - -static void cmos_checktimer(void) { - PIC_RemoveEvents(cmos_timerevent); - if (cmos.timer.div<=2) cmos.timer.div+=7; - cmos.timer.delay=(1000.0f/(32768.0f / (1 << (cmos.timer.div - 1)))); - if (!cmos.timer.div || !cmos.timer.enabled) return; - LOG(LOG_PIT,LOG_NORMAL)("RTC Timer at %.2f hz",1000.0/cmos.timer.delay); - PIC_AddEvent(cmos_timerevent,cmos.timer.delay); -// PIC_AddEvent(cmos_timerevent,(double)cmos.timer.delay-fmod(PIC_FullIndex(),(double)cmos.timer.delay)); //Should be more like a real pc. Check -// status reg A reading with this (and with other delays actually) -} - -void cmos_selreg(Bitu port,Bitu val,Bitu iolen) { - cmos.reg=val & 0x3f; - cmos.nmi=(val & 0x80)>0; -} - -static void cmos_writereg(Bitu port,Bitu val,Bitu iolen) { - switch (cmos.reg) { - case 0x00: /* Seconds */ - case 0x02: /* Minutes */ - case 0x04: /* Hours */ - case 0x06: /* Day of week */ - case 0x07: /* Date of month */ - case 0x08: /* Month */ - case 0x09: /* Year */ - case 0x32: /* Century */ - /* Ignore writes to change alarm */ - break; - case 0x01: /* Seconds Alarm */ - case 0x03: /* Minutes Alarm */ - case 0x05: /* Hours Alarm */ - LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Trying to set alarm"); - cmos.regs[cmos.reg]=val; - break; - case 0x0a: /* Status reg A */ - cmos.regs[cmos.reg]=val & 0x7f; - if ((val & 0x70)!=0x20) LOG(LOG_BIOS,LOG_ERROR)("CMOS Illegal 22 stage divider value"); - cmos.timer.div=(val & 0xf); - cmos_checktimer(); - break; - case 0x0b: /* Status reg B */ - cmos.bcd=!(val & 0x4); - cmos.regs[cmos.reg]=val & 0x7f; - cmos.timer.enabled=(val & 0x40)>0; - if (val&0x10) LOG(LOG_BIOS,LOG_ERROR)("CMOS:Updated ended interrupt not supported yet"); - cmos_checktimer(); - break; - case 0x0d:/* Status reg D */ - cmos.regs[cmos.reg]=val & 0x80; /*Bit 7=1:RTC Pown on*/ - break; - case 0x0f: /* Shutdown status byte */ - cmos.regs[cmos.reg]=val & 0x7f; - break; - default: - cmos.regs[cmos.reg]=val & 0x7f; - LOG(LOG_BIOS,LOG_ERROR)("CMOS:WRite to unhandled register %x",cmos.reg); - } -} - - -#define MAKE_RETURN(_VAL) (cmos.bcd ? ((((_VAL) / 10) << 4) | ((_VAL) % 10)) : (_VAL)); - -static Bitu cmos_readreg(Bitu port,Bitu iolen) { - if (cmos.reg>0x3f) { - LOG(LOG_BIOS,LOG_ERROR)("CMOS:Read from illegal register %x",cmos.reg); - return 0xff; - } - Bitu drive_a, drive_b; - Bit8u hdparm; - time_t curtime; - struct tm *loctime; - /* Get the current time. */ - curtime = time (NULL); - - /* Convert it to local time representation. */ - loctime = localtime (&curtime); - - switch (cmos.reg) { - case 0x00: /* Seconds */ - return MAKE_RETURN(loctime->tm_sec); - case 0x02: /* Minutes */ - return MAKE_RETURN(loctime->tm_min); - case 0x04: /* Hours */ - return MAKE_RETURN(loctime->tm_hour); - case 0x06: /* Day of week */ - return MAKE_RETURN(loctime->tm_wday + 1); - case 0x07: /* Date of month */ - return MAKE_RETURN(loctime->tm_mday); - case 0x08: /* Month */ - return MAKE_RETURN(loctime->tm_mon + 1); - case 0x09: /* Year */ - return MAKE_RETURN(loctime->tm_year % 100); - case 0x32: /* Century */ - return MAKE_RETURN(loctime->tm_year / 100 + 19); - case 0x01: /* Seconds Alarm */ - case 0x03: /* Minutes Alarm */ - case 0x05: /* Hours Alarm */ - return cmos.regs[cmos.reg]; - case 0x0a: /* Status register A */ - if (PIC_TickIndex()<0.002) { - return (cmos.regs[0x0a]&0x7f) | 0x80; - } else { - return (cmos.regs[0x0a]&0x7f); - } - case 0x0c: /* Status register C */ - cmos.timer.acknowledged=true; - if (cmos.timer.enabled) { - /* In periodic interrupt mode only care for those flags */ - Bit8u val=cmos.regs[0xc]; - cmos.regs[0xc]=0; - return val; - } else { - /* Give correct values at certain times */ - Bit8u val=0; - double index=PIC_FullIndex(); - if (index>=(cmos.last.timer+cmos.timer.delay)) { - cmos.last.timer=index; - val|=0x40; - } - if (index>=(cmos.last.ended+1000)) { - cmos.last.ended=index; - val|=0x10; - } - return val; - } - case 0x10: /* Floppy size */ - drive_a = 0; - drive_b = 0; - if(imageDiskList[0] != NULL) drive_a = imageDiskList[0]->GetBiosType(); - if(imageDiskList[1] != NULL) drive_b = imageDiskList[1]->GetBiosType(); - return ((drive_a << 4) | (drive_b)); - /* First harddrive info */ - case 0x12: - hdparm = 0; - if(imageDiskList[2] != NULL) hdparm |= 0xf; - if(imageDiskList[3] != NULL) hdparm |= 0xf0; - return hdparm; - case 0x19: - if(imageDiskList[2] != NULL) return 47; /* User defined type */ - return 0; - case 0x1b: - if(imageDiskList[2] != NULL) return (imageDiskList[2]->cylinders & 0xff); - return 0; - case 0x1c: - if(imageDiskList[2] != NULL) return ((imageDiskList[2]->cylinders & 0xff00)>>8); - return 0; - case 0x1d: - if(imageDiskList[2] != NULL) return (imageDiskList[2]->heads); - return 0; - case 0x1e: - if(imageDiskList[2] != NULL) return 0xff; - return 0; - case 0x1f: - if(imageDiskList[2] != NULL) return 0xff; - return 0; - case 0x20: - if(imageDiskList[2] != NULL) return (0xc0 | (((imageDiskList[2]->heads) > 8) << 3)); - return 0; - case 0x21: - if(imageDiskList[2] != NULL) return (imageDiskList[2]->cylinders & 0xff); - return 0; - case 0x22: - if(imageDiskList[2] != NULL) return ((imageDiskList[2]->cylinders & 0xff00)>>8); - return 0; - case 0x23: - if(imageDiskList[2] != NULL) return (imageDiskList[2]->sectors); - return 0; - /* Second harddrive info */ - case 0x1a: - if(imageDiskList[3] != NULL) return 47; /* User defined type */ - return 0; - case 0x24: - if(imageDiskList[3] != NULL) return (imageDiskList[3]->cylinders & 0xff); - return 0; - case 0x25: - if(imageDiskList[3] != NULL) return ((imageDiskList[3]->cylinders & 0xff00)>>8); - return 0; - case 0x26: - if(imageDiskList[3] != NULL) return (imageDiskList[3]->heads); - return 0; - case 0x27: - if(imageDiskList[3] != NULL) return 0xff; - return 0; - case 0x28: - if(imageDiskList[3] != NULL) return 0xff; - return 0; - case 0x29: - if(imageDiskList[3] != NULL) return (0xc0 | (((imageDiskList[3]->heads) > 8) << 3)); - return 0; - case 0x2a: - if(imageDiskList[3] != NULL) return (imageDiskList[3]->cylinders & 0xff); - return 0; - case 0x2b: - if(imageDiskList[3] != NULL) return ((imageDiskList[3]->cylinders & 0xff00)>>8); - return 0; - case 0x2c: - if(imageDiskList[3] != NULL) return (imageDiskList[3]->sectors); - return 0; - case 0x39: - return 0; - case 0x3a: - return 0; - - - case 0x0b: /* Status register B */ - case 0x0d: /* Status register D */ - case 0x0f: /* Shutdown status byte */ - case 0x14: /* Equipment */ - case 0x15: /* Base Memory KB Low Byte */ - case 0x16: /* Base Memory KB High Byte */ - case 0x17: /* Extended memory in KB Low Byte */ - case 0x18: /* Extended memory in KB High Byte */ - case 0x30: /* Extended memory in KB Low Byte */ - case 0x31: /* Extended memory in KB High Byte */ -// LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Read from reg %X : %04X",cmos.reg,cmos.regs[cmos.reg]); - return cmos.regs[cmos.reg]; - default: - LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Read from reg %X",cmos.reg); - return cmos.regs[cmos.reg]; - } -} - -void CMOS_SetRegister(Bitu regNr, Bit8u val) { - cmos.regs[regNr] = val; -} - - -class CMOS:public Module_base{ -private: - IO_ReadHandleObject ReadHandler[2]; - IO_WriteHandleObject WriteHandler[2]; -public: - CMOS(Section* configuration):Module_base(configuration){ - WriteHandler[0].Install(0x70,cmos_selreg,IO_MB); - WriteHandler[1].Install(0x71,cmos_writereg,IO_MB); - ReadHandler[0].Install(0x71,cmos_readreg,IO_MB); - cmos.timer.enabled=false; - cmos.timer.acknowledged=true; - cmos.reg=0xa; - cmos_writereg(0x71,0x26,1); - cmos.reg=0xb; - cmos_writereg(0x71,0x2,1); //Struct tm *loctime is of 24 hour format, - cmos.reg=0xd; - cmos_writereg(0x71,0x80,1); /* RTC power on */ - // Equipment is updated from bios.cpp and bios_disk.cpp - /* Fill in base memory size, it is 640K always */ - cmos.regs[0x15]=(Bit8u)0x80; - cmos.regs[0x16]=(Bit8u)0x02; - /* Fill in extended memory size */ - Bitu exsize=(MEM_TotalPages()*4)-1024; - cmos.regs[0x17]=(Bit8u)exsize; - cmos.regs[0x18]=(Bit8u)(exsize >> 8); - cmos.regs[0x30]=(Bit8u)exsize; - cmos.regs[0x31]=(Bit8u)(exsize >> 8); - } -}; - -static CMOS* test; - -void CMOS_Destroy(Section* sec){ - delete test; -} - -void CMOS_Init(Section* sec) { - test = new CMOS(sec); - sec->AddDestroyFunction(&CMOS_Destroy,true); -} diff --git a/src/hardware/dbopl.cpp b/src/hardware/dbopl.cpp deleted file mode 100644 index 7c65e04..0000000 --- a/src/hardware/dbopl.cpp +++ /dev/null @@ -1,1474 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - DOSBox implementation of a combined Yamaha YMF262 and Yamaha YM3812 emulator. - Enabling the opl3 bit will switch the emulator to stereo opl3 output instead of regular mono opl2 - Except for the table generation it's all integer math - Can choose different types of generators, using muls and bigger tables, try different ones for slower platforms - The generation was based on the MAME implementation but tried to have it use less memory and be faster in general - MAME uses much bigger envelope tables and this will be the biggest cause of it sounding different at times - - //TODO Don't delay first operator 1 sample in opl3 mode - //TODO Maybe not use class method pointers but a regular function pointers with operator as first parameter - //TODO Fix panning for the Percussion channels, would any opl3 player use it and actually really change it though? - //TODO don't use variables in work structure for tremolo and vibrato but give the variables as parameters to GetSample - //TODO Since the vibrato takes 1024 samples it's easier to run the emulator in same vibrato chunks, vibrato would be costfree - - //DUNNO Keyon in 4op, switch to 2op without keyoff. -*/ - - -#include -#include -#include -#include "dosbox.h" -#include "dbopl.h" - - -#ifndef PI -#define PI 3.14159265358979323846 -#endif - -namespace DBOPL { - -#define MAX_SAMPLES 256 -#define OPLRATE ((double)(14318180.0 / 288.0)) - -//Only need 4 valid bits at the top for vibrato -#define VIBRATO_SH ( 32 - 4 ) -//Need 6 bits of accuracy -#define TREMOLO_SH ( 32 - 6 ) -#define TREMOLO_TABLE 52 - -//Wave bits available in the top of the 32bit range -//Original adlib uses 10.10, we use 12.20 -//Have to keep some bits in the top to allow for freqmul 0.5 -#define WAVE_BITS 12 -#define WAVE_SH ( 32 - WAVE_BITS ) -#define WAVE_MASK ( ( 1 << WAVE_SH ) - 1 ) - -//Maximum amount of attenuation bits -//Envelope goes to 511, 9 bits -#if (DBOPL_WAVE == WAVE_TABLEMUL ) -//Uses the value directly -#define ENV_BITS ( 9 ) -#else -//Add 3 bits here for more accuracy and would have to be shifted up either way -#define ENV_BITS ( 9 ) -#endif -//Limits of the envelope with those bits and when the envelope goes silent -#define ENV_MIN 0 -#define ENV_EXTRA ( ENV_BITS - 9 ) -#define ENV_MAX ( 511 << ENV_EXTRA ) -#define ENV_LIMIT ( ( 12 * 256) >> ( 3 - ENV_EXTRA ) ) -#define ENV_SILENT( _X_ ) ( (_X_) >= ENV_LIMIT ) - -//Attack/decay/release rate counter shift -#define RATE_SH 24 -#define RATE_MASK ( ( 1 << RATE_SH ) - 1 ) -//Has to fit within 16bit lookuptable -#define MUL_SH 16 - -//Check some ranges -#if ENV_EXTRA > 3 -#error Too many envelope bits -#endif - - -//How much to substract from the base value for the final attenuation -static const Bit8u KslCreateTable[16] = { - //0 will always be be lower than 7 * 8 - 64, 32, 24, 19, - 16, 12, 11, 10, - 8, 6, 5, 4, - 3, 2, 1, 0, -}; - -#define M(_X_) ((Bit8u)( (_X_) * 2)) -static const Bit8u FreqCreateTable[16] = { - M(0.5), M(1 ), M(2 ), M(3 ), M(4 ), M(5 ), M(6 ), M(7 ), - M(8 ), M(9 ), M(10), M(10), M(12), M(12), M(15), M(15) -}; -#undef M - -//We're not including the highest attack rate, that gets a special value -static const Bit8u AttackSamplesTable[13] = { - 69, 55, 46, 40, - 35, 29, 23, 20, - 19, 15, 11, 10, - 9 -}; -//On a real opl these values take 8 samples to reach and are based upon larger tables -static const Bit8u EnvelopeIncreaseTable[13] = { - 4, 5, 6, 7, - 8, 10, 12, 14, - 16, 20, 24, 28, - 32, -}; - -#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG ) -static Bit16u ExpTable[ 256 ]; -#endif - -#if ( DBOPL_WAVE == WAVE_HANDLER ) -//PI table used by WAVEHANDLER -static Bit16u SinTable[ 512 ]; -#endif - -#if ( DBOPL_WAVE > WAVE_HANDLER ) -//Layout of the waveform table in 512 entry intervals -//With overlapping waves we reduce the table to half it's size - -// | |//\\|____|WAV7|//__|/\ |____|/\/\| -// |\\//| | |WAV7| | \/| | | -// |06 |0126|17 |7 |3 |4 |4 5 |5 | - -//6 is just 0 shifted and masked - -static Bit16s WaveTable[ 8 * 512 ]; -//Distance into WaveTable the wave starts -static const Bit16u WaveBaseTable[8] = { - 0x000, 0x200, 0x200, 0x800, - 0xa00, 0xc00, 0x100, 0x400, - -}; -//Mask the counter with this -static const Bit16u WaveMaskTable[8] = { - 1023, 1023, 511, 511, - 1023, 1023, 512, 1023, -}; - -//Where to start the counter on at keyon -static const Bit16u WaveStartTable[8] = { - 512, 0, 0, 0, - 0, 512, 512, 256, -}; -#endif - -#if ( DBOPL_WAVE == WAVE_TABLEMUL ) -static Bit16u MulTable[ 384 ]; -#endif - -static Bit8u KslTable[ 8 * 16 ]; -static Bit8u TremoloTable[ TREMOLO_TABLE ]; -//Start of a channel behind the chip struct start -static Bit16u ChanOffsetTable[32]; -//Start of an operator behind the chip struct start -static Bit16u OpOffsetTable[64]; - -//The lower bits are the shift of the operator vibrato value -//The highest bit is right shifted to generate -1 or 0 for negation -//So taking the highest input value of 7 this gives 3, 7, 3, 0, -3, -7, -3, 0 -static const Bit8s VibratoTable[ 8 ] = { - 1 - 0x00, 0 - 0x00, 1 - 0x00, 30 - 0x00, - 1 - 0x80, 0 - 0x80, 1 - 0x80, 30 - 0x80 -}; - -//Shift strength for the ksl value determined by ksl strength -static const Bit8u KslShiftTable[4] = { - 31,1,2,0 -}; - -//Generate a table index and table shift value using input value from a selected rate -static void EnvelopeSelect( Bit8u val, Bit8u& index, Bit8u& shift ) { - if ( val < 13 * 4 ) { //Rate 0 - 12 - shift = 12 - ( val >> 2 ); - index = val & 3; - } else if ( val < 15 * 4 ) { //rate 13 - 14 - shift = 0; - index = val - 12 * 4; - } else { //rate 15 and up - shift = 0; - index = 12; - } -} - -#if ( DBOPL_WAVE == WAVE_HANDLER ) -/* - Generate the different waveforms out of the sine/exponetial table using handlers -*/ -static inline Bits MakeVolume( Bitu wave, Bitu volume ) { - Bitu total = wave + volume; - Bitu index = total & 0xff; - Bitu sig = ExpTable[ index ]; - Bitu exp = total >> 8; -#if 0 - //Check if we overflow the 31 shift limit - if ( exp >= 32 ) { - LOG_MSG( "WTF %d %d", total, exp ); - } -#endif - return (sig >> exp); -}; - -static Bits DB_FASTCALL WaveForm0( Bitu i, Bitu volume ) { - Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0 - Bitu wave = SinTable[i & 511]; - return (MakeVolume( wave, volume ) ^ neg) - neg; -} -static Bits DB_FASTCALL WaveForm1( Bitu i, Bitu volume ) { - Bit32u wave = SinTable[i & 511]; - wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 ); - return MakeVolume( wave, volume ); -} -static Bits DB_FASTCALL WaveForm2( Bitu i, Bitu volume ) { - Bitu wave = SinTable[i & 511]; - return MakeVolume( wave, volume ); -} -static Bits DB_FASTCALL WaveForm3( Bitu i, Bitu volume ) { - Bitu wave = SinTable[i & 255]; - wave |= ( ( (i ^ 256 ) & 256) - 1) >> ( 32 - 12 ); - return MakeVolume( wave, volume ); -} -static Bits DB_FASTCALL WaveForm4( Bitu i, Bitu volume ) { - //Twice as fast - i <<= 1; - Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0 - Bitu wave = SinTable[i & 511]; - wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 ); - return (MakeVolume( wave, volume ) ^ neg) - neg; -} -static Bits DB_FASTCALL WaveForm5( Bitu i, Bitu volume ) { - //Twice as fast - i <<= 1; - Bitu wave = SinTable[i & 511]; - wave |= ( ( (i ^ 512 ) & 512) - 1) >> ( 32 - 12 ); - return MakeVolume( wave, volume ); -} -static Bits DB_FASTCALL WaveForm6( Bitu i, Bitu volume ) { - Bits neg = 0 - (( i >> 9) & 1);//Create ~0 or 0 - return (MakeVolume( 0, volume ) ^ neg) - neg; -} -static Bits DB_FASTCALL WaveForm7( Bitu i, Bitu volume ) { - //Negative is reversed here - Bits neg = (( i >> 9) & 1) - 1; - Bitu wave = (i << 3); - //When negative the volume also runs backwards - wave = ((wave ^ neg) - neg) & 4095; - return (MakeVolume( wave, volume ) ^ neg) - neg; -} - -static const WaveHandler WaveHandlerTable[8] = { - WaveForm0, WaveForm1, WaveForm2, WaveForm3, - WaveForm4, WaveForm5, WaveForm6, WaveForm7 -}; - -#endif - -//Structto hold the data everything well yeh works with -static struct { - Bitu samples; - Bits vibrato; - Bits tremolo; - inline void SetVibrato( Bit8s vib ) { - vibrato = vib; - vibrato &= ~0x80; - } - Bit32s output[MAX_SAMPLES * 2]; - //Could intermix the vib/trem table for slightly better cache hits - Bit8s vibTable[MAX_SAMPLES]; - Bit8s tremTable[MAX_SAMPLES]; -} Work; - -/* - Operator -*/ - -//We zero out when rate == 0 -inline void Operator::UpdateAttack( const Chip* chip ) { - Bit8u rate = reg60 >> 4; - if ( rate ) { - Bit8u val = (rate << 2) + ksr; - attackAdd = chip->attackRates[ val ]; - rateZero &= ~(1 << ATTACK); - } else { - attackAdd = 0; - rateZero |= (1 << ATTACK); - } -} -inline void Operator::UpdateDecay( const Chip* chip ) { - Bit8u rate = reg60 & 0xf; - if ( rate ) { - Bit8u val = (rate << 2) + ksr; - decayAdd = chip->linearRates[ val ]; - rateZero &= ~(1 << DECAY); - } else { - decayAdd = 0; - rateZero |= (1 << DECAY); - } -} -inline void Operator::UpdateRelease( const Chip* chip ) { - Bit8u rate = reg80 & 0xf; - if ( rate ) { - Bit8u val = (rate << 2) + ksr; - releaseAdd = chip->linearRates[ val ]; - rateZero &= ~(1 << RELEASE); - if ( !(reg20 & MASK_SUSTAIN ) ) { - rateZero &= ~( 1 << SUSTAIN ); - } - } else { - rateZero |= (1 << RELEASE); - releaseAdd = 0; - if ( !(reg20 & MASK_SUSTAIN ) ) { - rateZero |= ( 1 << SUSTAIN ); - } - } -} - -inline void Operator::UpdateAttenuation( ) { - Bit8u kslBase = (Bit8u)((chanData >> SHIFT_KSLBASE) & 0xff); - Bit32u tl = reg40 & 0x3f; - Bit8u kslShift = KslShiftTable[ reg40 >> 6 ]; - //Make sure the attenuation goes to the right bits - totalLevel = tl << ( ENV_BITS - 7 ); //Total level goes 2 bits below max - totalLevel += ( kslBase << ENV_EXTRA ) >> kslShift; -} - -void Operator::UpdateFrequency( ) { - Bit32u freq = chanData & (( 1 << 10 ) - 1); - Bit32u block = (chanData >> 10) & 0xff; - - waveAdd = (freq << block) * freqMul; - if ( reg20 & MASK_VIBRATO ) { - vibStrength = (Bit8u)(freq >> 7); - vibrato = ( vibStrength << block ) * freqMul; - } else { - vibStrength = 0; - vibrato = 0; - } -} - -void Operator::UpdateRates( const Chip* chip ) { - //Mame seems to reverse this where enabling ksr actually lowers - //the rate, but pdf manuals says otherwise? - Bit8u newKsr = (Bit8u)((chanData >> SHIFT_KEYCODE) & 0xff); - if ( !( reg20 & MASK_KSR ) ) { - newKsr >>= 2; - } - if ( ksr == newKsr ) - return; - ksr = newKsr; - UpdateAttack( chip ); - UpdateDecay( chip ); - UpdateRelease( chip ); -} - -INLINE Bit32s Operator::RateForward( Bit32u add ) { - rateIndex += add; - Bit32s ret = rateIndex >> RATE_SH; - rateIndex = rateIndex & RATE_MASK; - return ret; -} - -template< Operator::State yes> -Bits Operator::TemplateVolume( ) { - Bit32s vol = activeLevel; - Bit32s change; - switch ( yes ) { - case OFF: - return ENV_MAX; - case ATTACK: - change = RateForward( attackAdd ); - if ( !change ) - return vol; - vol += ( (~vol) * change ) >> 3; - if ( vol < ENV_MIN ) { - activeLevel = ENV_MIN; - rateIndex = 0; - SetState( DECAY ); - return ENV_MIN; - } - break; - case DECAY: - vol += RateForward( decayAdd ); - if ( vol >= sustainLevel ) { - //Check if we didn't overshoot max attenuation, then just go off - if ( vol >= ENV_MAX ) { - activeLevel = ENV_MAX; - SetState( OFF ); - return ENV_MAX; - } - //Continue as sustain - rateIndex = 0; - SetState( SUSTAIN ); - } - break; - case SUSTAIN: - if ( reg20 & MASK_SUSTAIN ) { - return vol; - } - //In sustain phase, but not sustaining, do regular release - case RELEASE: - vol += RateForward( releaseAdd );; - if ( vol >= ENV_MAX ) { - activeLevel = ENV_MAX; - SetState( OFF ); - return ENV_MAX; - } - break; - } - activeLevel = vol; - return vol; -} - -static const VolumeHandler VolumeHandlerTable[5] = { - &Operator::TemplateVolume< Operator::OFF >, - &Operator::TemplateVolume< Operator::RELEASE >, - &Operator::TemplateVolume< Operator::SUSTAIN >, - &Operator::TemplateVolume< Operator::DECAY >, - &Operator::TemplateVolume< Operator::ATTACK > -}; - -INLINE Bitu Operator::ForwardVolume() { - return totalLevel + (this->*volHandler)() -#if defined ( DBOPL_TREMOLO ) - + (Work.tremolo & tremoloMask) -#endif - ; -} - - -INLINE Bitu Operator::ForwardWave() { -#if defined ( DBOPL_VIBRATO ) - if ( vibStrength >> (Bit8u)(Work.vibrato) ) { - Bit32s add = vibrato >> (Bit8u)(Work.vibrato); - //Sign extend over the shift value - Bit32s neg = Work.vibrato >> 16; - //Negate the add with -1 or 0 - add = ( add ^ neg ) - neg; - waveIndex += add + waveAdd; - return waveIndex >> WAVE_SH; - } -#endif - waveIndex += waveAdd; - return waveIndex >> WAVE_SH; -} - - -void Operator::Write20( const Chip* chip, Bit8u val ) { - Bit8u change = (reg20 ^ val ); - if ( !change ) - return; - reg20 = val; - //Shift the tremolo bit over the entire register, saved a branch, YES! - tremoloMask = (Bit8s)(val) >> 7; - tremoloMask &= ~(( 1 << ENV_EXTRA ) -1); - //Update specific features based on changes - if ( change & MASK_KSR ) { - UpdateRates( chip ); - } - //With sustain enable the volume doesn't change - if ( reg20 & MASK_SUSTAIN || ( !releaseAdd ) ) { - rateZero |= ( 1 << SUSTAIN ); - } else { - rateZero &= ~( 1 << SUSTAIN ); - } - //Frequency multiplier or vibrato changed - if ( change & (0xf | MASK_VIBRATO) ) { - freqMul = chip->freqMul[ val & 0xf ]; - UpdateFrequency(); - } -} - -void Operator::Write40( const Chip* chip, Bit8u val ) { - if (!(reg40 ^ val )) - return; - reg40 = val; - UpdateAttenuation( ); -} - -void Operator::Write60( const Chip* chip, Bit8u val ) { - Bit8u change = reg60 ^ val; - reg60 = val; - if ( change & 0x0f ) { - UpdateDecay( chip ); - } - if ( change & 0xf0 ) { - UpdateAttack( chip ); - } -} - -void Operator::Write80( const Chip* chip, Bit8u val ) { - Bit8u change = (reg80 ^ val ); - if ( !change ) - return; - reg80 = val; - Bit8u sustain = val >> 4; - //Turn 0xf into 0x1f - sustain |= ( sustain + 1) & 0x10; - sustainLevel = sustain << ( ENV_BITS - 5 ); - if ( change & 0x0f ) { - UpdateRelease( chip ); - } -} - -void Operator::WriteE0( const Chip* chip, Bit8u val ) { - if ( !(regE0 ^ val) ) - return; - //in opl3 mode you can always selet 7 waveforms regardless of waveformselect - Bit8u waveForm = val & ( ( 0x3 & chip->waveFormMask ) | (0x7 & chip->opl3Active ) ); - regE0 = val; -#if ( DBOPL_WAVE == WAVE_HANDLER ) - waveHandler = WaveHandlerTable[ waveForm ]; -#else - waveBase = WaveTable + WaveBaseTable[ waveForm ]; - waveStart = WaveStartTable[ waveForm ] << WAVE_SH; - waveMask = WaveMaskTable[ waveForm ]; -#endif -} - -INLINE void Operator::SetState( Bit8u s ) { - state = s; - volHandler = VolumeHandlerTable[ s ]; -} - -INLINE bool Operator::Silent() const { - if ( !ENV_SILENT( totalLevel + activeLevel ) ) - return false; - if ( !(rateZero & ( 1 << state ) ) ) - return false; - return true; -}; - -void Operator::KeyOn( Bit8u mask ) { - if ( !keyOn ) { - //Restart the frequency generator -#if ( DBOPL_WAVE > WAVE_HANDLER ) - waveIndex = waveStart; -#else - waveIndex = 0; -#endif - rateIndex = 0; - SetState( ATTACK ); - } - keyOn |= mask; -} - -void Operator::KeyOff( Bit8u mask ) { - keyOn &= ~mask; - if ( !keyOn ) { - if ( state != OFF ) { - SetState( RELEASE ); - } - } -} - -INLINE Bits Operator::GetWave( Bitu index, Bitu vol ) { -#if ( DBOPL_WAVE == WAVE_HANDLER ) - return waveHandler( index, vol << ( 3 - ENV_EXTRA ) ); -#elif ( DBOPL_WAVE == WAVE_TABLEMUL ) - return (waveBase[ index & waveMask ] * MulTable[ vol >> ENV_EXTRA ]) >> MUL_SH; -#elif ( DBOPL_WAVE == WAVE_TABLELOG ) - Bit32s wave = waveBase[ index & waveMask ]; - Bit32u total = ( wave & 0x7fff ) + vol << ( 3 - ENV_EXTRA ); - Bit32s sig = ExpTable[ total & 0xff ]; - Bit32u exp = total >> 8; - Bit32s neg = wave >> 16; - return ((sig ^ neg) - neg) >> exp; -#else -#error "No valid wave routine" -#endif -} - -Bits INLINE Operator::GetSample( Bits modulation ) { - Bitu vol = ForwardVolume(); - if ( ENV_SILENT( vol ) ) { - //Simply forward the wave - waveIndex += waveAdd; - return 0; - } else { - Bitu index = ForwardWave(); - index += modulation; - return GetWave( index, vol ); - } -} - -Operator::Operator() { - chanData = 0; - freqMul = 0; - waveIndex = 0; - waveAdd = 0; - keyOn = 0; - ksr = 0; - reg20 = 0; - reg40 = 0; - reg60 = 0; - reg80 = 0; - regE0 = 0; - SetState( OFF ); - rateZero = (1 << OFF); - sustainLevel = ENV_MAX; - activeLevel = ENV_MAX; - totalLevel = ENV_MAX; -} - -/* - Channel -*/ - -Channel::Channel() { - old[0] = old[1] = 0; - chanData = 0; - regB0 = 0; - regC0 = 0; - maskLeft = -1; - maskRight = -1; - feedback = 31; - fourMask = 0; - synthHandler = &Channel::BlockTemplate< sm2FM >; -}; - -void Channel::SetChanData( const Chip* chip, Bit32u data ) { - Bit32u change = chanData ^ data; - chanData = data; - Op( 0 )->chanData = data; - Op( 1 )->chanData = data; - //Since a frequency update triggered this, always update frequency - Op( 0 )->UpdateFrequency(); - Op( 1 )->UpdateFrequency(); - if ( change & ( 0xff << SHIFT_KSLBASE ) ) { - Op( 0 )->UpdateAttenuation(); - Op( 1 )->UpdateAttenuation(); - } - if ( change & ( 0xff << SHIFT_KEYCODE ) ) { - Op( 0 )->UpdateRates( chip ); - Op( 1 )->UpdateRates( chip ); - } -} - -void Channel::UpdateFrequency( const Chip* chip, Bit8u fourOp ) { - //Extrace the frequency bits - Bit32u data = chanData & 0xffff; - Bit32u kslBase = KslTable[ data >> 6 ]; - Bit32u keyCode = ( data & 0x1c00) >> 9; - if ( chip->reg08 & 0x40 ) { - keyCode |= ( data & 0x100)>>8; /* notesel == 1 */ - } else { - keyCode |= ( data & 0x200)>>9; /* notesel == 0 */ - } - //Add the keycode and ksl into the highest bits of chanData - data |= (keyCode << SHIFT_KEYCODE) | ( kslBase << SHIFT_KSLBASE ); - ( this + 0 )->SetChanData( chip, data ); - if ( fourOp & 0x3f ) { - ( this + 1 )->SetChanData( chip, data ); - } -} - -void Channel::WriteA0( const Chip* chip, Bit8u val ) { - Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask; - //Don't handle writes to silent fourop channels - if ( fourOp > 0x80 ) - return; - Bit32u change = (chanData ^ val ) & 0xff; - if ( change ) { - chanData ^= change; - UpdateFrequency( chip, fourOp ); - } -} - -void Channel::WriteB0( const Chip* chip, Bit8u val ) { - Bit8u fourOp = chip->reg104 & chip->opl3Active & fourMask; - //Don't handle writes to silent fourop channels - if ( fourOp > 0x80 ) - return; - Bitu change = (chanData ^ ( val << 8 ) ) & 0x1f00; - if ( change ) { - chanData ^= change; - UpdateFrequency( chip, fourOp ); - } - //Check for a change in the keyon/off state - if ( !(( val ^ regB0) & 0x20)) - return; - regB0 = val; - if ( val & 0x20 ) { - Op(0)->KeyOn( 0x1 ); - Op(1)->KeyOn( 0x1 ); - if ( fourOp & 0x3f ) { - ( this + 1 )->Op(0)->KeyOn( 1 ); - ( this + 1 )->Op(1)->KeyOn( 1 ); - } - } else { - Op(0)->KeyOff( 0x1 ); - Op(1)->KeyOff( 0x1 ); - if ( fourOp & 0x3f ) { - ( this + 1 )->Op(0)->KeyOff( 1 ); - ( this + 1 )->Op(1)->KeyOff( 1 ); - } - } -} - -void Channel::WriteC0( const Chip* chip, Bit8u val ) { - Bit8u change = val ^ regC0; - if ( !change ) - return; - regC0 = val; - feedback = ( val >> 1 ) & 7; - if ( feedback ) { - //We shift the input to the right 10 bit wave index value - feedback = 9 - feedback; - } else { - feedback = 31; - } - //Select the new synth mode - if ( chip->opl3Active ) { - //4-op mode enabled for this channel - if ( (chip->reg104 & fourMask) & 0x3f ) { - Channel* chan0, *chan1; - //Check if it's the 2nd channel in a 4-op - if ( !(fourMask & 0x80 ) ) { - chan0 = this; - chan1 = this + 1; - } else { - chan0 = this - 1; - chan1 = this; - } - - Bit8u synth = ( (chan0->regC0 & 1) << 0 )| (( chan1->regC0 & 1) << 1 ); - switch ( synth ) { - case 0: - chan0->synthHandler = &Channel::BlockTemplate< sm3FMFM >; - break; - case 1: - chan0->synthHandler = &Channel::BlockTemplate< sm3AMFM >; - break; - case 2: - chan0->synthHandler = &Channel::BlockTemplate< sm3FMAM >; - break; - case 3: - chan0->synthHandler = &Channel::BlockTemplate< sm3AMAM >; - break; - } - //Disable updating percussion channels - } else if ((fourMask & 0x40) && ( chip->regBD & 0x20) ) { - - //Regular dual op, am or fm - } else if ( val & 1 ) { - synthHandler = &Channel::BlockTemplate< sm3AM >; - } else { - synthHandler = &Channel::BlockTemplate< sm3FM >; - } - maskLeft = ( val & 0x10 ) ? -1 : 0; - maskRight = ( val & 0x20 ) ? -1 : 0; - //opl2 active - } else { - //Disable updating percussion channels - if ( (fourMask & 0x40) && ( chip->regBD & 0x20 ) ) { - - //Regular dual op, am or fm - } else if ( val & 1 ) { - synthHandler = &Channel::BlockTemplate< sm2AM >; - } else { - synthHandler = &Channel::BlockTemplate< sm2FM >; - } - } -} - -void Channel::ResetC0( const Chip* chip ) { - Bit8u val = regC0; - regC0 ^= 0xff; - WriteC0( chip, val ); -}; - -template< bool opl3Mode> -void Channel::GeneratePercussion( Bit32s* output ) { - Channel* chan = this; - - //BassDrum - Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback; - old[0] = old[1]; - old[1] = Op(0)->GetSample( mod ); - - //When bassdrum is in AM mode first operator is ignoed - if ( chan->regC0 & 1 ) { - mod = 0; - } else { - mod = old[0]; - } - Bit32s sample = Op(1)->GetSample( mod ); - - Operator* op2 = ( this + 1 )->Op(0); - Operator* op4 = ( this + 2 )->Op(0); - - //Precalculate stuff used by other oupts - Bit32u noiseBit = rand() & 0x2; - Bit32u c2 = op2->ForwardWave(); - //(bit 7 ^ bit 2) | bit 3 -> combined in bit 1 - Bit32u phaseBit = ( (c2 >> 6) ^ ( c2 >> 1 ) ) | ( c2 >> 2 ); - Bit32u c4 = op4->ForwardWave(); - //bit 5 ^ bit 3 to bit 1 - Bit32u gateBit = ( c4 >> 4 ) ^ ( c4 >> 3 ); - phaseBit = (phaseBit | gateBit) & 0x2; - - //Hi-Hat - Bit32u hhVol = op2->ForwardVolume(); - if ( !ENV_SILENT( hhVol ) ) { - /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */ - /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */ - Bit32u hhIndex = ( phaseBit << 8 ) | ( 0xd0 >> ( phaseBit ^ noiseBit ) ); - sample += op2->GetWave( hhIndex, hhVol ); - } - //Snare Drum - Operator* op3 = ( this + 1 )->Op(1); - Bit32u sdVol = op3->ForwardVolume(); - if ( !ENV_SILENT( sdVol ) ) { - Bit32u sdBits = 0x100 + (c2 & 0x100); - Bit32u sdIndex = sdBits ^ ( noiseBit << 7 ); - sample += op3->GetWave( sdIndex, sdVol ); - } - //Tom-tom - sample += op4->GetSample( 0 ); - //Top-Cymbal - Operator* op5 = ( this + 2 )->Op(1); - Bit32u tcVol = op5->ForwardVolume(); - if ( !ENV_SILENT( tcVol ) ) { - Bit32u tcIndex = (1 + phaseBit) << 8; - sample += op5->GetWave( tcIndex, tcVol ); - } - sample <<= 1; - if ( opl3Mode ) { - output[0] += sample; - output[1] += sample; - } else { - output[0] += sample; - } -} - -template -Channel* Channel::BlockTemplate( ) { - switch( mode ) { - case sm2AM: - case sm3AM: - if ( Op(0)->Silent() && Op(1)->Silent() ) { - old[0] = old[1] = 0; - return (this + 1); - } - break; - case sm2FM: - case sm3FM: - if ( Op(1)->Silent() ) { - old[0] = old[1] = 0; - return (this + 1); - } - break; - case sm3FMFM: - if ( Op(3)->Silent() ) { - old[0] = old[1] = 0; - return (this + 2); - } - break; - case sm3AMFM: - if ( Op(0)->Silent() && Op(3)->Silent() ) { - old[0] = old[1] = 0; - return (this + 2); - } - break; - case sm3FMAM: - if ( Op(1)->Silent() && Op(3)->Silent() ) { - old[0] = old[1] = 0; - return (this + 2); - } - break; - case sm3AMAM: - if ( Op(0)->Silent() && Op(2)->Silent() && Op(3)->Silent() ) { - old[0] = old[1] = 0; - return (this + 2); - } - break; - } - for ( Bitu i = 0; i < Work.samples; i++ ) { - Work.vibrato = Work.vibTable[i]; - Work.tremolo = Work.tremTable[i]; - - //Early out for percussion handlers - if ( mode == sm2Percussion ) { - GeneratePercussion( Work.output + i ); - continue; //Prevent some unitialized value bitching - } else if ( mode == sm3Percussion ) { - GeneratePercussion( Work.output + i * 2 ); - continue; //Prevent some unitialized value bitching - } - - //Do unsigned shift so we can shift out all bits but still stay in 10 bit range otherwise - Bit32s mod = (Bit32u)((old[0] + old[1])) >> feedback; - old[0] = old[1]; - old[1] = Op(0)->GetSample( mod ); - Bit32s sample; - Bit32s out0 = old[0]; - if ( mode == sm2AM || mode == sm3AM ) { - sample = out0 + Op(1)->GetSample( 0 ); - } else if ( mode == sm2FM || mode == sm3FM ) { - sample = Op(1)->GetSample( out0 ); - } else if ( mode == sm3FMFM ) { - Bits next = Op(1)->GetSample( out0 ); - next = Op(2)->GetSample( next ); - sample = Op(3)->GetSample( next ); - } else if ( mode == sm3AMFM ) { - sample = out0; - Bits next = Op(1)->GetSample( 0 ); - next = Op(2)->GetSample( next ); - sample += Op(3)->GetSample( next ); - } else if ( mode == sm3FMAM ) { - sample = Op(1)->GetSample( out0 ); - Bits next = Op(2)->GetSample( 0 ); - sample += Op(3)->GetSample( next ); - } else if ( mode == sm3AMAM ) { - sample = out0; - Bits next = Op(1)->GetSample( 0 ); - sample += Op(2)->GetSample( next ); - sample += Op(3)->GetSample( 0 ); - } - switch( mode ) { - case sm2AM: - case sm2FM: - Work.output[ i ] += sample; - break; - case sm3AM: - case sm3FM: - case sm3FMFM: - case sm3AMFM: - case sm3FMAM: - case sm3AMAM: - Work.output[ i * 2 + 0 ] += sample & maskLeft; - Work.output[ i * 2 + 1 ] += sample & maskRight; - break; - } - } - switch( mode ) { - case sm2AM: - case sm2FM: - case sm3AM: - case sm3FM: - return ( this + 1 ); - case sm3FMFM: - case sm3AMFM: - case sm3FMAM: - case sm3AMAM: - return( this + 2 ); - case sm2Percussion: - case sm3Percussion: - return( this + 3 ); - } - return 0; -} - -/* - Chip -*/ - -Chip::Chip() { - reg08 = 0; - reg04 = 0; - regBD = 0; - reg104 = 0; - opl3Active = 0; -} - - -Bit8u Chip::ForwardTremolo( ) { - tremoloCounter += tremoloAdd; - if ( tremoloCounter >= (TREMOLO_TABLE << TREMOLO_SH) ) { - tremoloCounter -= TREMOLO_TABLE << TREMOLO_SH; - } - Bitu index = tremoloCounter >> TREMOLO_SH; - return TremoloTable[ index ] >> tremoloShift; -} - -Bit8s Chip::ForwardVibrato( ) { - vibratoCounter += vibratoAdd; - Bitu index = vibratoCounter >> VIBRATO_SH; - //Vibrato shift, basically makes the shift greater reducing the actual final value - return VibratoTable[index & 7] + vibratoShift; -} - -void Chip::WriteBD( Bit8u val ) { - Bit8u change = regBD ^ val; - if ( !change ) - return; - regBD = val; - //TODO could do this with shift and xor? - vibratoShift = (val & 0x40) ? 0x00 : 0x01; - tremoloShift = (val & 0x80) ? 0x00 : 0x02; - if ( val & 0x20 ) { - //Drum was just enabled, make sure channel 6 has the right synth - if ( change & 0x20 ) { - if ( opl3Active ) { - chan[6].synthHandler = &Channel::BlockTemplate< sm3Percussion >; - } else { - chan[6].synthHandler = &Channel::BlockTemplate< sm2Percussion >; - } - } - //Bass Drum - if ( val & 0x10 ) { - chan[6].op[0].KeyOn( 0x2 ); - chan[6].op[1].KeyOn( 0x2 ); - } else { - chan[6].op[0].KeyOff( 0x2 ); - chan[6].op[1].KeyOff( 0x2 ); - } - //Hi-Hat - if ( val & 0x1 ) { - chan[7].op[0].KeyOn( 0x2 ); - } else { - chan[7].op[0].KeyOff( 0x2 ); - } - //Snare - if ( val & 0x8 ) { - chan[7].op[1].KeyOn( 0x2 ); - } else { - chan[7].op[1].KeyOff( 0x2 ); - } - //Tom-Tom - if ( val & 0x4 ) { - chan[8].op[0].KeyOn( 0x2 ); - } else { - chan[8].op[0].KeyOff( 0x2 ); - } - //Top Cymbal - if ( val & 0x2 ) { - chan[8].op[1].KeyOn( 0x2 ); - } else { - chan[8].op[1].KeyOff( 0x2 ); - } - //Toggle keyoffs when we turn off the percussion - } else if ( change & 0x20 ) { - //Trigger a reset to setup the original synth handler - chan[6].ResetC0( this ); - chan[6].op[0].KeyOff( 0x2 ); - chan[6].op[1].KeyOff( 0x2 ); - chan[7].op[0].KeyOff( 0x2 ); - chan[7].op[1].KeyOff( 0x2 ); - chan[8].op[0].KeyOff( 0x2 ); - chan[8].op[1].KeyOff( 0x2 ); - } -} - - -#define REGOP( _FUNC_ ) \ - index = ( ( reg >> 3) & 0x20 ) | ( reg & 0x1f ); \ - if ( OpOffsetTable[ index ] ) { \ - Operator* regOp = (Operator*)( ((char *)this ) + OpOffsetTable[ index ] ); \ - regOp->_FUNC_( this, val ); \ - } - -#define REGCHAN( _FUNC_ ) \ - index = ( ( reg >> 4) & 0x10 ) | ( reg & 0xf ); \ - if ( ChanOffsetTable[ index ] ) { \ - Channel* regChan = (Channel*)( ((char *)this ) + ChanOffsetTable[ index ] ); \ - regChan->_FUNC_( this, val ); \ - } - -void Chip::WriteReg( Bit32u reg, Bit8u val ) { - Bitu index; - switch ( (reg & 0xf0) >> 4 ) { - case 0x00 >> 4: - if ( reg == 0x01 ) { - waveFormMask = ( val & 0x20 ) ? 0x7 : 0x0; - } else if ( reg == 0x104 ) { - //Only detect changes in lowest 6 bits - if ( !((reg104 ^ val) & 0x3f) ) - return; - //Always keep the highest bit enabled, for checking > 0x80 - reg104 = 0x80 | ( val & 0x3f ); - } else if ( reg == 0x105 ) { - //MAME says the real opl3 doesn't reset anything on opl3 disable/enable till the next write in another register - if ( !((opl3Active ^ val) & 1 ) ) - return; - opl3Active = ( val & 1 ) ? 0xff : 0; - //Update the 0xc0 register for all channels to signal the switch to mono/stereo handlers - for ( int i = 0; i < 18;i++ ) { - chan[i].ResetC0( this ); - } - } else if ( reg == 0x08 ) { - reg08 = val; - } - case 0x10 >> 4: - break; - case 0x20 >> 4: - case 0x30 >> 4: - REGOP( Write20 ); - break; - case 0x40 >> 4: - case 0x50 >> 4: - REGOP( Write40 ); - break; - case 0x60 >> 4: - case 0x70 >> 4: - REGOP( Write60 ); - break; - case 0x80 >> 4: - case 0x90 >> 4: - REGOP( Write80 ); - break; - case 0xa0 >> 4: - REGCHAN( WriteA0 ); - break; - case 0xb0 >> 4: - if ( reg == 0xbd ) { - WriteBD( val ); - } else { - REGCHAN( WriteB0 ); - } - break; - case 0xc0 >> 4: - REGCHAN( WriteC0 ); - case 0xd0 >> 4: - break; - case 0xe0 >> 4: - case 0xf0 >> 4: - REGOP( WriteE0 ); - break; - } -} - - -Bit32u Chip::WriteAddr( Bit32u port, Bit8u val ) { - switch ( port & 3 ) { - case 0: - return val; - case 2: - if ( opl3Active || (val == 0x05) ) - return 0x100 | val; - else - return val; - } - return 0; -} - -void Chip::GenerateBlock2( Bitu samples ) { - Work.samples = samples; - for ( Bitu i = 0; i < Work.samples; i++ ) { - Work.vibTable[i] = ForwardVibrato(); - Work.tremTable[i] = ForwardTremolo(); - Work.output[i] = 0; - } - int count = 0; - for( Channel* ch = chan; ch < chan + 9; ) { - count++; - ch = (ch->*(ch->synthHandler))(); - } -} - -void Chip::GenerateBlock3( Bitu samples ) { - Work.samples = samples; - for ( Bitu i = 0; i < Work.samples; i++ ) { - Work.vibTable[i] = ForwardVibrato(); - Work.tremTable[i] = ForwardTremolo(); - Work.output[i*2 + 0] = 0; - Work.output[i*2 + 1] = 0; - } - int count = 0; - for( Channel* ch = chan; ch < chan + 18; ) { - count++; - ch = (ch->*(ch->synthHandler))(); - } -} - -void Chip::Setup( Bit32u rate ) { - //Vibrato forwards every 1024 samples - vibratoAdd = (Bit32u)((double)rate * (double)( 1 << (VIBRATO_SH - 10) ) / OPLRATE); - vibratoCounter = 0; - //tremolo forwards every 64 samples - //We use a 52 entry table, real is 210, so repeat each sample an extra 4 times - tremoloAdd = (Bit32u)((double)rate * (double)( 1 << (TREMOLO_SH - 6 - 2) ) / OPLRATE); - tremoloCounter = 0; - //10 bits of frequency counter - //With higher octave this gets shifted up - //-1 since the freqCreateTable = *2 - double scale = (OPLRATE * (double)( 1 << ( WAVE_SH - 10 - 1))) / rate; - for ( int i = 0; i < 16; i++ ) { - //Use rounding with 0.5 - freqMul[i] = (Bit32u)( 0.5 + scale * FreqCreateTable[ i ] ); - } - - scale = OPLRATE / rate; - //-3 since the real envelope takes 8 steps to reach the single value we supply - for ( Bit8u i = 0; i < 76; i++ ) { - Bit8u index, shift; - EnvelopeSelect( i, index, shift ); - linearRates[i] = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH + ENV_EXTRA - shift - 3 ))); - } - //Generate the best matching attack rate - for ( Bit8u i = 0; i < 62; i++ ) { - Bit8u index, shift; - EnvelopeSelect( i, index, shift ); - //Original amount of samples the attack would take - Bit32s original = (Bit32u)( (AttackSamplesTable[ index ] << shift) / scale); - - Bit32s guessAdd = (Bit32u)( scale * (EnvelopeIncreaseTable[ index ] << ( RATE_SH - shift - 3 ))); - Bit32s bestAdd; - Bit32u bestDiff = 1 << 30; - for( Bit32u passes = 0; passes < 16; passes ++ ) { - Bit32s volume = ENV_MAX; - Bit32s samples = 0; - Bit32u count = 0; - while ( volume > 0 && samples < original * 2 ) { - count += guessAdd; - Bit32s change = count >> RATE_SH; - count &= RATE_MASK; - if ( change ) { - volume += ( ~volume * change ) >> 3; - } - samples++; - - } - Bit32s diff = original - samples; - Bit32u lDiff = labs( diff ); - //Init last on first pass - if ( lDiff < bestDiff ) { - bestDiff = lDiff; - bestAdd = guessAdd; - if ( !bestDiff ) - break; - } - //Below our target - if ( diff < 0 ) { - //Better than the last time - Bit32s mul = ((original - diff) << 12) / original; - guessAdd = ((guessAdd * mul) >> 12); - guessAdd++; - } else if ( diff > 0 ) { - Bit32s mul = ((original - diff) << 12) / original; - guessAdd = (guessAdd * mul) >> 12; - guessAdd--; - } - } - attackRates[i] = bestAdd; - } - for ( Bit8u i = 62; i < 76; i++ ) { - //This should provide instant volume maximizing - attackRates[i] = 8 << RATE_SH; - } - //Setup the channels with the correct four op flags - //Channels are accessed through a table so they appear linear here - chan[ 0].fourMask = 0x00 | ( 1 << 0 ); - chan[ 1].fourMask = 0x80 | ( 1 << 0 ); - chan[ 2].fourMask = 0x00 | ( 1 << 1 ); - chan[ 3].fourMask = 0x80 | ( 1 << 1 ); - chan[ 4].fourMask = 0x00 | ( 1 << 2 ); - chan[ 5].fourMask = 0x80 | ( 1 << 2 ); - - chan[ 9].fourMask = 0x00 | ( 1 << 3 ); - chan[10].fourMask = 0x80 | ( 1 << 3 ); - chan[11].fourMask = 0x00 | ( 1 << 4 ); - chan[12].fourMask = 0x80 | ( 1 << 4 ); - chan[13].fourMask = 0x00 | ( 1 << 5 ); - chan[14].fourMask = 0x80 | ( 1 << 5 ); - - //mark the percussion channels - chan[ 6].fourMask = 0x40; - chan[ 7].fourMask = 0x40; - chan[ 8].fourMask = 0x40; - - //Clear Everything in opl3 mode - WriteReg( 0x105, 0x1 ); - for ( int i = 0; i < 512; i++ ) { - if ( i == 0x105 ) - continue; - WriteReg( i, 0xff ); - WriteReg( i, 0x0 ); - } - WriteReg( 0x105, 0x0 ); - //Clear everything in opl2 mode - for ( int i = 0; i < 255; i++ ) { - WriteReg( i, 0xff ); - WriteReg( i, 0x0 ); - } -} - -static bool doneTables = false; -void InitTables( void ) { - if ( doneTables ) - return; - doneTables = true; -#if ( DBOPL_WAVE == WAVE_HANDLER ) || ( DBOPL_WAVE == WAVE_TABLELOG ) - //Exponential volume table, same as the real adlib - for ( int i = 0; i < 256; i++ ) { - //Save them in reverse - ExpTable[i] = (int)( 0.5 + ( pow(2.0, ( 255 - i) * ( 1.0 /256 ) )-1) * 1024 ); - ExpTable[i] += 1024; //or remove the -1 oh well :) - //Preshift to the left once so the final volume can shift to the right - ExpTable[i] *= 2; - } -#endif -#if ( DBOPL_WAVE == WAVE_HANDLER ) - //Add 0.5 for the trunc rounding of the integer cast - //Do a PI sinetable instead of the original 0.5 PI - for ( int i = 0; i < 512; i++ ) { - SinTable[i] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 ); - } -#endif -#if ( DBOPL_WAVE == WAVE_TABLEMUL ) - //Multiplication based tables - for ( int i = 0; i < 384; i++ ) { - int s = i * 8; - //TODO maybe keep some of the precision errors of the original table? - double val = ( 0.5 + ( pow(2, -1 + ( 255 - s) * ( 1.0 /256 ) )) * ( 1 << MUL_SH )); - MulTable[i] = (Bit16u)(val); - } - - //Sine Wave Base - for ( int i = 0; i < 512; i++ ) { - WaveTable[ 0x0200 + i ] = (Bit16s)(sin( (i + 0.5) * (PI / 512.0) ) * 4084); - WaveTable[ 0x0000 + i ] = -WaveTable[ 0x200 + i ]; - } - //Exponential wave - for ( int i = 0; i < 256; i++ ) { - WaveTable[ 0x700 + i ] = (Bit16s)( 0.5 + ( pow(2, -1 + ( 255 - i * 8) * ( 1.0 /256 ) ) ) * 4085 ); - WaveTable[ 0x6ff - i ] = -WaveTable[ 0x700 + i ]; - } -#endif -#if ( DBOPL_WAVE == WAVE_TABLELOG ) - //Sine Wave Base - for ( int i = 0; i < 512; i++ ) { - WaveTable[ 0x0200 + i ] = (Bit16s)( 0.5 - log10( sin( (i + 0.5) * (PI / 512.0) ) ) / log10(2.0)*256 ); - WaveTable[ 0x0000 + i ] = ((Bit16s)0x8000) | WaveTable[ 0x200 + i]; - } - //Exponential wave - for ( int i = 0; i < 256; i++ ) { - WaveTable[ 0x700 + i ] = i * 8; - WaveTable[ 0x6ff - i ] = ((Bit16s)0x8000) | i * 8; - } -#endif - - // | |//\\|____|WAV7|//__|/\ |____|/\/\| - // |\\//| | |WAV7| | \/| | | - // |06 |0126|27 |7 |3 |4 |4 5 |5 | - -#if (( DBOPL_WAVE == WAVE_TABLELOG ) || ( DBOPL_WAVE == WAVE_TABLEMUL )) - for ( int i = 0; i < 256; i++ ) { - //Fill silence gaps - WaveTable[ 0x400 + i ] = WaveTable[0]; - WaveTable[ 0x500 + i ] = WaveTable[0]; - WaveTable[ 0x900 + i ] = WaveTable[0]; - WaveTable[ 0xc00 + i ] = WaveTable[0]; - WaveTable[ 0xd00 + i ] = WaveTable[0]; - //Replicate sines in other pieces - WaveTable[ 0x800 + i ] = WaveTable[ 0x200 + i ]; - //double speed sines - WaveTable[ 0xa00 + i ] = WaveTable[ 0x200 + i * 2 ]; - WaveTable[ 0xb00 + i ] = WaveTable[ 0x000 + i * 2 ]; - WaveTable[ 0xe00 + i ] = WaveTable[ 0x200 + i * 2 ]; - WaveTable[ 0xf00 + i ] = WaveTable[ 0x200 + i * 2 ]; - } -#endif - - //Create the ksl table - for ( int oct = 0; oct < 8; oct++ ) { - int base = oct * 8; - for ( int i = 0; i < 16; i++ ) { - int val = base - KslCreateTable[i]; - if ( val < 0 ) - val = 0; - //*4 for the final range to match attenuation range - KslTable[ oct * 16 + i ] = val * 4; - } - } - //Create the Tremolo table, just increase and decrease a triangle wave - for ( Bit8u i = 0; i < TREMOLO_TABLE / 2; i++ ) { - Bit8u val = i << ENV_EXTRA; - TremoloTable[i] = val; - TremoloTable[TREMOLO_TABLE - 1 - i] = val; - } - //Create a table with offsets of the channels from the start of the chip - DBOPL::Chip* chip = 0; - for ( Bitu i = 0; i < 32; i++ ) { - Bitu index = i & 0xf; - if ( index >= 9 ) { - ChanOffsetTable[i] = 0; - continue; - } - //Make sure the four op channels follow eachother - if ( index < 6 ) { - index = (index % 3) * 2 + ( index / 3 ); - } - //Add back the bits for highest ones - if ( i >= 16 ) - index += 9; - Bitu blah = reinterpret_cast( &(chip->chan[ index ]) ); - ChanOffsetTable[i] = blah; - } - //Same for operators - for ( Bitu i = 0; i < 64; i++ ) { - if ( i % 8 >= 6 || ( (i / 8) % 4 == 3 ) ) { - OpOffsetTable[i] = 0; - continue; - } - Bitu chNum = (i / 8) * 3 + (i % 8) % 3; - //Make sure we use 16 and up for the 2nd range to match the chanoffset gap - if ( chNum >= 12 ) - chNum += 16 - 12; - Bitu opNum = ( i % 8 ) / 3; - DBOPL::Channel* chan = 0; - Bitu blah = reinterpret_cast( &(chan->op[opNum]) ); - OpOffsetTable[i] = ChanOffsetTable[ chNum ] + blah; - } -#if 0 - //Stupid checks if table's are correct - for ( Bitu i = 0; i < 18; i++ ) { - Bit32u find = (Bit16u)( &(chip->chan[ i ]) ); - for ( Bitu c = 0; c < 32; c++ ) { - if ( ChanOffsetTable[c] == find ) { - find = 0; - break; - } - } - if ( find ) { - find = find; - } - } - for ( Bitu i = 0; i < 36; i++ ) { - Bit32u find = (Bit16u)( &(chip->chan[ i / 2 ].op[i % 2]) ); - for ( Bitu c = 0; c < 64; c++ ) { - if ( OpOffsetTable[c] == find ) { - find = 0; - break; - } - } - if ( find ) { - find = find; - } - } -#endif -} - -Bit32u Handler::WriteAddr( Bit32u port, Bit8u val ) { - return chip.WriteAddr( port, val ); - -} -void Handler::WriteReg( Bit32u addr, Bit8u val ) { - chip.WriteReg( addr, val ); -} - -void Handler::Generate( MixerChannel* chan, Bitu samples ) { - if ( !chip.opl3Active ) { - chip.GenerateBlock2( samples ); - chan->AddSamples_m32( samples, Work.output ); - } else { - chip.GenerateBlock3( samples ); - chan->AddSamples_s32( samples, Work.output ); - } -} - -void Handler::Init( Bitu rate ) { - InitTables(); - chip.Setup( rate ); -} - - -}; //Namespace DBOPL diff --git a/src/hardware/dbopl.h b/src/hardware/dbopl.h deleted file mode 100644 index cf19f5b..0000000 --- a/src/hardware/dbopl.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "adlib.h" -#include "dosbox.h" - -//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume -#define WAVE_HANDLER 10 -//Use a logarithmic wavetable with an exponential table for volume -#define WAVE_TABLELOG 11 -//Use a linear wavetable with a multiply table for volume -#define WAVE_TABLEMUL 12 - -//Select the type of wave generator routine -#define DBOPL_WAVE WAVE_TABLEMUL -//Enable vibrato in the output -#define DBOPL_VIBRATO -//Enable tremolo in the output -#define DBOPL_TREMOLO - -namespace DBOPL { - -struct Chip; -struct Operator; -struct Channel; - -#if (DBOPL_WAVE == WAVE_HANDLER) -typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume ); -#endif - -typedef Bits ( DBOPL::Operator::*VolumeHandler) ( ); -typedef Channel* ( DBOPL::Channel::*SynthHandler) ( ); - -//Different synth modes that can generate blocks of data -typedef enum { - smNone, - sm2AM, - sm2FM, - sm2Percussion, - sm3AM, - sm3FM, - sm3FMFM, - sm3AMFM, - sm3FMAM, - sm3AMAM, - sm3Percussion, -} SynthMode; - -//Shifts for the values contained in chandata variable -enum { - SHIFT_KSLBASE = 16, - SHIFT_KEYCODE = 24, -}; - -struct Operator { -public: - //Masks for operator 20 values - enum { - MASK_KSR = 0x10, - MASK_SUSTAIN = 0x20, - MASK_VIBRATO = 0x40, - MASK_TREMOLO = 0x80, - }; - - typedef enum { - OFF, - RELEASE, - SUSTAIN, - DECAY, - ATTACK, - } State; - - VolumeHandler volHandler; - -#if (DBOPL_WAVE == WAVE_HANDLER) - WaveHandler waveHandler; //Routine that generate a wave -#else - Bit16s* waveBase; - Bit32u waveMask; - Bit32u waveStart; -#endif - Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index - Bit32u waveAdd; - - Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this - Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove? - Bit32u vibrato; //Scaled up vibrato strength - Bit32s sustainLevel; //When stopping at sustain level stop here - Bit32s totalLevel; //totalLeve is added to every generated volume - Bit32s activeLevel; //The currently active volume - - Bit32u attackAdd; //Timers for the different states of the envelope - Bit32u decayAdd; - Bit32u releaseAdd; - Bit32u rateIndex; //Current position of the evenlope - - Bit8u rateZero; //Bits for the different states of the envelope having no changes - Bit8u keyOn; //Bitmask of different values that can generate keyon - //Registers, also used to check for changes - Bit8u reg20, reg40, reg60, reg80, regE0; - //Active part of the envelope we're in - Bit8u state; - //0xff when tremolo is enabled - Bit8u tremoloMask; - //Strength of the vibrato - Bit8u vibStrength; - //Keep track of the calculated KSR so we can check for changes - Bit8u ksr; -private: - void SetState( Bit8u s ); - void UpdateAttack( const Chip* chip ); - void UpdateRelease( const Chip* chip ); - void UpdateDecay( const Chip* chip ); -public: - void UpdateAttenuation(); - void UpdateRates( const Chip* chip ); - void UpdateFrequency( ); - - void Write20( const Chip* chip, Bit8u val ); - void Write40( const Chip* chip, Bit8u val ); - void Write60( const Chip* chip, Bit8u val ); - void Write80( const Chip* chip, Bit8u val ); - void WriteE0( const Chip* chip, Bit8u val ); - - bool Silent() const; - void KeyOn( Bit8u mask); - void KeyOff( Bit8u mask); - - template< State state> - Bits TemplateVolume( ); - - Bit32s RateForward( Bit32u add ); - Bitu ForwardWave(); - Bitu ForwardVolume(); - - Bits GetSample( Bits modulation ); - Bits GetWave( Bitu index, Bitu vol ); -public: - Operator(); -}; - -struct Channel { - Operator op[2]; - inline Operator* Op( Bitu index ) { - return &( ( this + (index >> 1) )->op[ index & 1 ]); - } - SynthHandler synthHandler; - Bit32u chanData; //Frequency/octave and derived values - Bit32s old[2]; //Old data for feedback - - Bit8u feedback; //Feedback shift - Bit8u regB0; //Register values to check for changes - Bit8u regC0; - //This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel - Bit8u fourMask; - Bit8s maskLeft; //Sign extended values for both channel's panning - Bit8s maskRight; - - //Forward the channel data to the operators of the channel - void SetChanData( const Chip* chip, Bit32u data ); - //Change in the chandata, check for new values and if we have to forward to operators - void UpdateFrequency( const Chip* chip, Bit8u fourOp ); - void WriteA0( const Chip* chip, Bit8u val ); - void WriteB0( const Chip* chip, Bit8u val ); - void WriteC0( const Chip* chip, Bit8u val ); - void ResetC0( const Chip* chip ); - - //call this for the first channel - template< bool opl3Mode > - void GeneratePercussion( Bit32s* output ); - - //Generate blocks of data in specific modes - template - Channel* BlockTemplate( ); - Channel(); -}; - -struct Chip { - //This is used as the base counter for vibrato and tremolo - Bit32u tremoloCounter; - Bit32u tremoloAdd; - Bit32u vibratoCounter; - Bit32u vibratoAdd; - - //Frequency scales for the different multiplications - Bit32u freqMul[16]; - //Rates for decay and release for rate of this chip - Bit32u linearRates[76]; - //Best match attack rates for the rate of this chip - Bit32u attackRates[76]; - - //18 channels with 2 operators each - Channel chan[18]; - - Bit8u reg104; - Bit8u reg08; - Bit8u reg04; - Bit8u regBD; - Bit8u vibratoShift; - Bit8u tremoloShift; - //Mask for allowed wave forms - Bit8u waveFormMask; - //0 or -1 when enabled - Bit8s opl3Active; - - Bit8u ForwardTremolo(); - Bit8s ForwardVibrato(); - - void WriteBD( Bit8u val ); - void WriteReg(Bit32u reg, Bit8u val ); - - Bit32u WriteAddr( Bit32u port, Bit8u val ); - - void GenerateBlock2( Bitu samples ); - void GenerateBlock3( Bitu samples ); - - void Generate( Bit32u samples ); - void Setup( Bit32u r ); - - Chip(); -}; - -struct Handler : public Adlib::Handler { - DBOPL::Chip chip; - virtual Bit32u WriteAddr( Bit32u port, Bit8u val ); - virtual void WriteReg( Bit32u addr, Bit8u val ); - virtual void Generate( MixerChannel* chan, Bitu samples ); - virtual void Init( Bitu rate ); -}; - - -}; //Namespace diff --git a/src/hardware/disney.cpp b/src/hardware/disney.cpp deleted file mode 100644 index fa45813..0000000 --- a/src/hardware/disney.cpp +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: disney.cpp,v 1.16 2008/07/14 19:39:10 qbix79 Exp $ */ - -#include -#include "dosbox.h" -#include "inout.h" -#include "mixer.h" -#include "pic.h" -#include "setup.h" - -#define DISNEY_BASE 0x0378 - -#define DISNEY_SIZE 128 - -typedef struct _dac_channel { - Bit8u buffer[DISNEY_SIZE]; // data buffer - Bitu used; // current data buffer level - double speedcheck_sum; - double speedcheck_last; - bool speedcheck_failed; - bool speedcheck_init; -} dac_channel; - -static struct { - // parallel port stuff - Bit8u data; - Bit8u status; - Bit8u control; - // the D/A channels - dac_channel da[2]; - - Bitu last_used; - MixerObject * mo; - MixerChannel * chan; - bool stereo; - // which channel do we use for mono output? - // and the channel used for stereo - dac_channel* leader; - - Bitu state; - Bitu interface_det; -} disney; - -#define DS_IDLE 0 -#define DS_RUNNING 1 -#define DS_FINISH 2 -#define DS_ANALYZING 3 - -static void DISNEY_CallBack(Bitu len); - -static void DISNEY_disable(Bitu) { - if(disney.mo) { - disney.chan->AddSilence(); - disney.chan->Enable(false); - delete disney.mo; - } - disney.interface_det = 0; - disney.leader = 0; - disney.last_used = 0; - disney.mo = 0; - disney.state = DS_IDLE; - disney.interface_det = 0; -} - -static void DISNEY_enable(Bitu freq) { - if(freq < 500 || freq > 100000) { - // try again.. - disney.state = DS_IDLE; - return; - } else { -#if 0 - if(disney.stereo) LOG(LOG_MISC,LOG_NORMAL)("disney enable %d Hz, stereo",freq); - else LOG(LOG_MISC,LOG_NORMAL)("disney enable %d Hz, mono",freq); -#endif - disney.mo = new MixerObject(); - disney.chan=disney.mo->Install(&DISNEY_CallBack,freq,"DISNEY"); - disney.chan->Enable(true); - disney.state = DS_RUNNING; - } -} - -static void DISNEY_analyze(Bitu channel){ - switch(disney.state) { - case DS_RUNNING: // should not get here - break; - case DS_IDLE: - // initialize channel data - for(int i = 0; i < 2; i++) { - disney.da[i].used = 0; - disney.da[i].speedcheck_sum = 0; - disney.da[i].speedcheck_failed = false; - disney.da[i].speedcheck_init = false; - } - disney.da[channel].speedcheck_last = PIC_FullIndex(); - disney.da[channel].speedcheck_init = true; - - disney.state = DS_ANALYZING; - break; - - case DS_FINISH: - { - // detect stereo: if we have about the same data amount in both channels - Bits st_diff = disney.da[0].used - disney.da[1].used; - - // find leader channel (the one with higher rate) [this good for the stereo case?] - if(disney.da[0].used > disney.da[1].used) { - //disney.monochannel=0; - disney.leader = &disney.da[0]; - } else { - //disney.monochannel=1; - disney.leader = &disney.da[1]; - } - - if((st_diff < 5) && (st_diff > -5)) disney.stereo = true; - else disney.stereo = false; - - // calculate rate for both channels - Bitu ch_speed[2]; - - for(Bitu i = 0; i < 2; i++) { - ch_speed[i] = (Bitu)(1.0/((disney.da[i].speedcheck_sum/1000.0) / - (float)(((float)disney.da[i].used)-1.0))); // -1.75 - } - - // choose the larger value - DISNEY_enable(ch_speed[0] > ch_speed[1]? - ch_speed[0]:ch_speed[1]); // TODO - break; - } - case DS_ANALYZING: - { - double current = PIC_FullIndex(); - dac_channel* cch = &disney.da[channel]; - - if(!cch->speedcheck_init) { - cch->speedcheck_init = true; - cch->speedcheck_last = current; - break; - } - cch->speedcheck_sum += current - cch->speedcheck_last; - //LOG_MSG("t=%f",current - cch->speedcheck_last); - - // sanity checks (printer...) - if((current - cch-> speedcheck_last) < 0.01 || - (current - cch-> speedcheck_last) > 2) - cch->speedcheck_failed = true; - - // if both are failed we are back at start - if(disney.da[0].speedcheck_failed && disney.da[1].speedcheck_failed) { - disney.state=DS_IDLE; - break; - } - - cch->speedcheck_last = current; - - // analyze finish condition - if(disney.da[0].used > 30 || disney.da[1].used > 30) - disney.state = DS_FINISH; - break; - } - } -} - -static void disney_write(Bitu port,Bitu val,Bitu iolen) { - //LOG_MSG("write disney time %f addr%x val %x",PIC_FullIndex(),port,val); - disney.last_used=PIC_Ticks; - switch (port-DISNEY_BASE) { - case 0: /* Data Port */ - { - disney.data=val; - // if data is written here too often without using the stereo - // mechanism we use the simple DAC machanism. - if(disney.state != DS_RUNNING) { - disney.interface_det++; - if(disney.interface_det > 5) - DISNEY_analyze(0); - } - if(disney.interface_det > 5) { - if(disney.da[0].used < DISNEY_SIZE) { - disney.da[0].buffer[disney.da[0].used] = disney.data; - disney.da[0].used++; - } //else LOG_MSG("disney overflow 0"); - - } - break; - } - case 1: /* Status Port */ - LOG(LOG_MISC,LOG_NORMAL)("DISNEY:Status write %x",val); - break; - case 2: /* Control Port */ - if((disney.control & 0x2) && !(val & 0x2)) { - if(disney.state != DS_RUNNING) { - disney.interface_det = 0; - DISNEY_analyze(1); - } - - // stereo channel latch - if(disney.da[1].used < DISNEY_SIZE) { - disney.da[1].buffer[disney.da[1].used] = disney.data; - disney.da[1].used++; - } //else LOG_MSG("disney overflow 1"); - } - - if((disney.control & 0x1) && !(val & 0x1)) { - if(disney.state != DS_RUNNING) { - disney.interface_det = 0; - DISNEY_analyze(0); - } - // stereo channel latch - if(disney.da[0].used < DISNEY_SIZE) { - disney.da[0].buffer[disney.da[0].used] = disney.data; - disney.da[0].used++; - } //else LOG_MSG("disney overflow 0"); - } - -// LOG_WARN("DISNEY:Control write %x",val); - if (val&0x10) LOG(LOG_MISC,LOG_ERROR)("DISNEY:Parallel IRQ Enabled"); - disney.control=val; - break; - } -} - -static Bitu disney_read(Bitu port,Bitu iolen) { - switch (port-DISNEY_BASE) { - case 0: /* Data Port */ -// LOG(LOG_MISC,LOG_NORMAL)("DISNEY:Read from data port"); - return disney.data; - break; - case 1: /* Status Port */ -// LOG(LOG_MISC,"DISNEY:Read from status port %X",disney.status); - if (disney.leader && disney.leader->used >= 16) return 0x40; - /* Stereo-on-1 and (or) New-Stereo DACs present */ - if(!(disney.data&0x80)) return 0xc4; - else return 0x0; - break; - case 2: /* Control Port */ - LOG(LOG_MISC,LOG_NORMAL)("DISNEY:Read from control port"); - return disney.control; - break; - } - return 0xff; -} - -static void DISNEY_PlayStereo(Bitu len, Bit8u* l, Bit8u* r) { - static Bit8u stereodata[DISNEY_SIZE*2]; - for(Bitu i = 0; i < len; i++) { - stereodata[i*2] = l[i]; - stereodata[i*2+1] = r[i]; - } - disney.chan->AddSamples_s8(len,stereodata); -} - -static void DISNEY_CallBack(Bitu len) { - if (!len) return; - - // get the smaller used - Bitu real_used; - if(disney.stereo) { - real_used = disney.da[0].used; - if(disney.da[1].used < real_used) real_used = disney.da[1].used; - } else - real_used = disney.leader->used; - - if (real_used >= len) { // enough data for now - if(disney.stereo) DISNEY_PlayStereo(len, disney.da[0].buffer, disney.da[1].buffer); - else disney.chan->AddSamples_m8(len,disney.leader->buffer); - - // put the rest back to start - for(int i = 0; i < 2; i++) { - // TODO for mono only one - memmove(disney.da[i].buffer,&disney.da[i].buffer[len],DISNEY_SIZE/*real_used*/-len); - disney.da[i].used -= len; - } - // TODO: len > DISNEY - } else { // not enough data - if(disney.stereo) { - Bit8u gapfiller0 = 128; - Bit8u gapfiller1 = 128; - if(real_used) { - gapfiller0 = disney.da[0].buffer[real_used-1]; - gapfiller1 = disney.da[1].buffer[real_used-1]; - }; - - memset(disney.da[0].buffer+real_used, - gapfiller0,len-real_used); - memset(disney.da[1].buffer+real_used, - gapfiller1,len-real_used); - - DISNEY_PlayStereo(len, disney.da[0].buffer, disney.da[1].buffer); - len -= real_used; - - } else { // mono - Bit8u gapfiller = 128; //Keep the middle - if(real_used) { - // fix for some stupid game; it outputs 0 at the end of the stream - // causing a click. So if we have at least two bytes availible in the - // buffer and the last one is a 0 then ignore that. - if(disney.leader->buffer[real_used-1]==0) - real_used--; - } - // do it this way because AddSilence sounds like a gnawing mouse - if(real_used) - gapfiller = disney.leader->buffer[real_used-1]; - //LOG_MSG("gapfiller %x, fill len %d, realused %d",gapfiller,len-real_used,real_used); - memset(disney.leader->buffer+real_used, gapfiller, len-real_used); - disney.chan->AddSamples_m8(len, disney.leader->buffer); - } - disney.da[0].used =0; - disney.da[1].used =0; - - //LOG_MSG("disney underflow %d",len - real_used); - } - if (disney.last_used+100(configuration); - if(!section->Get_bool("disney")) return; - - WriteHandler.Install(DISNEY_BASE,disney_write,IO_MB,3); - ReadHandler.Install(DISNEY_BASE,disney_read,IO_MB,3); - - disney.status=0x84; - disney.control=0; - disney.last_used=0; - - disney.mo=0; - DISNEY_disable(0); - } - ~DISNEY(){ - DISNEY_disable(0); - } -}; - -static DISNEY* test; - -static void DISNEY_ShutDown(Section* sec){ - delete test; -} - -void DISNEY_Init(Section* sec) { - test = new DISNEY(sec); - sec->AddDestroyFunction(&DISNEY_ShutDown,true); -} diff --git a/src/hardware/dma.cpp b/src/hardware/dma.cpp index 2b60b50..62e9a6c 100644 --- a/src/hardware/dma.cpp +++ b/src/hardware/dma.cpp @@ -1,381 +1,225 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: dma.cpp,v 1.39 2008/09/13 20:04:28 c2woody Exp $ */ - -#include -#include "dosbox.h" -#include "mem.h" -#include "inout.h" -#include "dma.h" -#include "pic.h" -#include "paging.h" -#include "setup.h" - -DmaController *DmaControllers[2]; - -#define EMM_PAGEFRAME4K ((0xE000*16)/4096) -Bit32u ems_board_mapping[LINK_START]; - -static void UpdateEMSMapping(void) { - /* if EMS is not present, this will result in a 1:1 mapping */ - Bitu i; - for (i=0;i<0x10;i++) { - ems_board_mapping[EMM_PAGEFRAME4K+i]=paging.firstmb[EMM_PAGEFRAME4K+i]; - } -} - -/* read a block from physical memory */ -static void DMA_BlockRead(PhysPt pt,void * data,Bitu size) { - Bit8u * write=(Bit8u *) data; - for ( ; size ; size--, pt++) { - Bitu page = pt >> 12; - /* care for EMS pageframe etc. */ - if (page < EMM_PAGEFRAME4K) page = paging.firstmb[page]; - else if (page < EMM_PAGEFRAME4K+0x10) page = ems_board_mapping[page]; - else if (page < LINK_START) page = paging.firstmb[page]; - *write++=phys_readb(page*4096 + (pt & 4095)); - } -} - -/* write a block into physical memory */ -static void DMA_BlockWrite(PhysPt pt,void * data,Bitu size) { - Bit8u * read=(Bit8u *) data; - for ( ; size ; size--, pt++) { - Bitu page = pt >> 12; - /* care for EMS pageframe etc. */ - if (page < EMM_PAGEFRAME4K) page = paging.firstmb[page]; - else if (page < EMM_PAGEFRAME4K+0x10) page = ems_board_mapping[page]; - else if (page < LINK_START) page = paging.firstmb[page]; - phys_writeb(page*4096 + (pt & 4095), *read++); - } -} - -DmaChannel * GetDMAChannel(Bit8u chan) { - if (chan<4) { - /* channel on first DMA controller */ - if (DmaControllers[0]) return DmaControllers[0]->GetChannel(chan); - } else if (chan<8) { - /* channel on second DMA controller */ - if (DmaControllers[1]) return DmaControllers[1]->GetChannel(chan-4); - } - return NULL; -} - -/* remove the second DMA controller (ports are removed automatically) */ -void CloseSecondDMAController(void) { - if (DmaControllers[1]) { - delete DmaControllers[1]; - DmaControllers[1]=NULL; - } -} - -/* check availability of second DMA controller, needed for SB16 */ -bool SecondDMAControllerAvailable(void) { - if (DmaControllers[1]) return true; - else return false; -} - -static void DMA_Write_Port(Bitu port,Bitu val,Bitu iolen) { - if (port<0x10) { - /* write to the first DMA controller (channels 0-3) */ - DmaControllers[0]->WriteControllerReg(port,val,1); - } else if (port>=0xc0 && port <=0xdf) { - /* write to the second DMA controller (channels 4-7) */ - DmaControllers[1]->WriteControllerReg((port-0xc0) >> 1,val,1); - } else { - UpdateEMSMapping(); - switch (port) { - /* write DMA page register */ - case 0x81:GetDMAChannel(2)->SetPage(val);break; - case 0x82:GetDMAChannel(3)->SetPage(val);break; - case 0x83:GetDMAChannel(1)->SetPage(val);break; - case 0x89:GetDMAChannel(6)->SetPage(val);break; - case 0x8a:GetDMAChannel(7)->SetPage(val);break; - case 0x8b:GetDMAChannel(5)->SetPage(val);break; - } - } -} - -static Bitu DMA_Read_Port(Bitu port,Bitu iolen) { - if (port<0x10) { - /* read from the first DMA controller (channels 0-3) */ - return DmaControllers[0]->ReadControllerReg(port,iolen); - } else if (port>=0xc0 && port <=0xdf) { - /* read from the second DMA controller (channels 4-7) */ - return DmaControllers[1]->ReadControllerReg((port-0xc0) >> 1,iolen); - } else switch (port) { - /* read DMA page register */ - case 0x81:return GetDMAChannel(2)->pagenum; - case 0x82:return GetDMAChannel(3)->pagenum; - case 0x83:return GetDMAChannel(1)->pagenum; - case 0x89:return GetDMAChannel(6)->pagenum; - case 0x8a:return GetDMAChannel(7)->pagenum; - case 0x8b:return GetDMAChannel(5)->pagenum; - } - return 0; -} - -void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu len) { - DmaChannel * chan;Bitu i; - switch (reg) { - /* set base address of DMA transfer (1st byte low part, 2nd byte high part) */ - case 0x0:case 0x2:case 0x4:case 0x6: - UpdateEMSMapping(); - chan=GetChannel(reg >> 1); - flipflop=!flipflop; - if (flipflop) { - chan->baseaddr=(chan->baseaddr&0xff00)|val; - chan->curraddr=(chan->curraddr&0xff00)|val; - } else { - chan->baseaddr=(chan->baseaddr&0x00ff)|(val << 8); - chan->curraddr=(chan->curraddr&0x00ff)|(val << 8); - } - break; - /* set DMA transfer count (1st byte low part, 2nd byte high part) */ - case 0x1:case 0x3:case 0x5:case 0x7: - UpdateEMSMapping(); - chan=GetChannel(reg >> 1); - flipflop=!flipflop; - if (flipflop) { - chan->basecnt=(chan->basecnt&0xff00)|val; - chan->currcnt=(chan->currcnt&0xff00)|val; - } else { - chan->basecnt=(chan->basecnt&0x00ff)|(val << 8); - chan->currcnt=(chan->currcnt&0x00ff)|(val << 8); - } - break; - case 0x8: /* Comand reg not used */ - break; - case 0x9: /* Request registers, memory to memory */ - //TODO Warning? - break; - case 0xa: /* Mask Register */ - if ((val & 0x4)==0) UpdateEMSMapping(); - chan=GetChannel(val & 3); - chan->SetMask((val & 0x4)>0); - break; - case 0xb: /* Mode Register */ - UpdateEMSMapping(); - chan=GetChannel(val & 3); - chan->autoinit=(val & 0x10) > 0; - chan->increment=(val & 0x20) > 0; - //TODO Maybe other bits? - break; - case 0xc: /* Clear Flip/Flip */ - flipflop=false; - break; - case 0xd: /* Master Clear/Reset */ - for (i=0;i<4;i++) { - chan=GetChannel(i); - chan->SetMask(true); - chan->tcount=false; - } - flipflop=false; - break; - case 0xe: /* Clear Mask register */ - UpdateEMSMapping(); - for (i=0;i<4;i++) { - chan=GetChannel(i); - chan->SetMask(false); - } - break; - case 0xf: /* Multiple Mask register */ - UpdateEMSMapping(); - for (i=0;i<4;i++) { - chan=GetChannel(i); - chan->SetMask(val & 1); - val>>=1; - } - break; - } -} - -Bitu DmaController::ReadControllerReg(Bitu reg,Bitu len) { - DmaChannel * chan;Bitu i,ret; - switch (reg) { - /* read base address of DMA transfer (1st byte low part, 2nd byte high part) */ - case 0x0:case 0x2:case 0x4:case 0x6: - chan=GetChannel(reg >> 1); - flipflop=!flipflop; - if (flipflop) { - return chan->curraddr & 0xff; - } else { - return (chan->curraddr >> 8) & 0xff; - } - /* read DMA transfer count (1st byte low part, 2nd byte high part) */ - case 0x1:case 0x3:case 0x5:case 0x7: - chan=GetChannel(reg >> 1); - flipflop=!flipflop; - if (flipflop) { - return chan->currcnt & 0xff; - } else { - return (chan->currcnt >> 8) & 0xff; - } - case 0x8: /* Status Register */ - ret=0; - for (i=0;i<4;i++) { - chan=GetChannel(i); - if (chan->tcount) ret|=1 << i; - chan->tcount=false; -// if (chan->callback) ret|=1 << (i+4); - if (chan->request) ret|=1 << (4+i); - } - return ret; - default: - LOG(LOG_DMACONTROL,LOG_NORMAL)("Trying to read undefined DMA port %x",reg); - break; - } - return 0xffffffff; -} - -DmaChannel::DmaChannel(Bit8u num, bool dma16) { - masked = true; - callback = NULL; - if(num == 4) return; - channum = num; - DMA16 = dma16 ? 0x1 : 0x0; - pagenum = 0; - pagebase = 0; - baseaddr = 0; - curraddr = 0; - basecnt = 0; - currcnt = 0; - increment = true; - autoinit = false; - tcount = false; - request = false; -} - -Bitu DmaChannel::Read(Bitu want, Bit8u * buffer) { - Bitu done=0; -again: - Bitu left=(currcnt+1); - if (wantDMA_WriteHandler[i].Install(i,DMA_Write_Port,mask); - DmaControllers[0]->DMA_ReadHandler[i].Install(i,DMA_Read_Port,mask); - if (IS_EGAVGA_ARCH) { - /* install handler for second DMA controller ports */ - DmaControllers[1]->DMA_WriteHandler[i].Install(0xc0+i*2,DMA_Write_Port,mask); - DmaControllers[1]->DMA_ReadHandler[i].Install(0xc0+i*2,DMA_Read_Port,mask); - } - } - /* install handlers for ports 0x81-0x83 (on the first DMA controller) */ - DmaControllers[0]->DMA_WriteHandler[0x10].Install(0x81,DMA_Write_Port,IO_MB,3); - DmaControllers[0]->DMA_ReadHandler[0x10].Install(0x81,DMA_Read_Port,IO_MB,3); - - if (IS_EGAVGA_ARCH) { - /* install handlers for ports 0x81-0x83 (on the second DMA controller) */ - DmaControllers[1]->DMA_WriteHandler[0x10].Install(0x89,DMA_Write_Port,IO_MB,3); - DmaControllers[1]->DMA_ReadHandler[0x10].Install(0x89,DMA_Read_Port,IO_MB,3); - } - } - ~DMA(){ - if (DmaControllers[0]) { - delete DmaControllers[0]; - DmaControllers[0]=NULL; - } - if (DmaControllers[1]) { - delete DmaControllers[1]; - DmaControllers[1]=NULL; - } - } -}; - -static DMA* test; - -void DMA_Destroy(Section* sec){ - delete test; -} -void DMA_Init(Section* sec) { - test = new DMA(sec); - sec->AddDestroyFunction(&DMA_Destroy); - Bitu i; - for (i=0;i +#include "dosbox.h" +#include "mem.h" +#include "inout.h" +#include "dma.h" + +#ifdef DEBUG_DMA +#define DMA_DEBUG LOG_DEBUG +#else +#define DMA_DEBUG +#endif + +#define DMA_MODE_DEMAND 0 +#define DMA_MODE_SINGLE 1 +#define DMA_MODE_BLOCK 2 +#define DMA_MODE_CASCADE 3 + +struct DMA_CHANNEL { + struct { + Bit8u mode_type; + Bit8u address_decrement; + Bit8u autoinit_enable; + Bit8u transfer_type; + } mode; + Bit16u base_address; + Bit16u base_count; + Bit16u current_address; + Bit32u current_count; + Bit8u page; + bool masked; + HostOff host_address; + bool addr_changed; +}; + + +struct DMA_CONTROLLER { + bool flipflop; + Bit8u status_reg; + Bit8u command_reg; + DMA_CHANNEL chan[4]; +}; + +static DMA_CONTROLLER dma[2]; + + +static void write_dma(Bit32u port,Bit8u val) { + /* only use first dma for now */ + DMA_CONTROLLER * cont=&dma[0]; + DMA_CHANNEL * chan=&cont->chan[port>>1]; + switch (port) { + case 0x00:case 0x02:case 0x04:case 0x06: + if (cont->flipflop) { + chan->base_address=val; + } else { + chan->base_address|=(val<<8); + } + cont->flipflop=!cont->flipflop; + chan->addr_changed=true; + break; + case 0x01:case 0x03:case 0x05:case 0x07: + if (cont->flipflop) { + chan->base_count=val; + } else { + chan->base_count|=(val<<8); + } + cont->flipflop=!cont->flipflop; + chan->addr_changed=true; + break; + case 0x08: /* Command Register */ + if (val != 4) LOG_WARN("DMA1:Illegal command %2X",val); + cont->command_reg=val; + break; + case 0x09: /* Request Register */ + if (val&4) { + /* Set Request bit */ + } else { + Bitu channel = val & 0x03; + cont->status_reg &= ~(1 << (channel+4)); + } + break; + case 0x0a: /* single mask bit register */ + chan->masked=(val & 4)>0; + break; + case 0x0b: /* mode register */ + chan->mode.mode_type = (val >> 6) & 0x03; + chan->mode.address_decrement = (val >> 5) & 0x01; + chan->mode.autoinit_enable = (val >> 4) & 0x01; + chan->mode.transfer_type = (val >> 2) & 0x03; + if (chan->mode.address_decrement) { + LOG_WARN("DMA:Address Decrease not supported yet"); + } + + break; + case 0x0c: /* Clear Flip/Flip */ + cont->flipflop=true; + break; + }; +}; + + +static Bit8u channelindex[7] = {2, 3, 1, 0, 0, 0, 0}; +void write_dma_page(Bit32u port,Bit8u val) { + + switch (port) { + case 0x81: /* dma0 page register, channel 2 */ + case 0x82: /* dma0 page register, channel 3 */ + case 0x83: /* dma0 page register, channel 1 */ + case 0x87: /* dma0 page register, channel 0 */ + Bitu channel = channelindex[port - 0x81]; + dma[0].chan[channel].page=val; + dma[0].chan[channel].addr_changed=true; + break; + } +} + +void DMA_8_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) { + DMA_CHANNEL * chan=&dma[0].chan[dmachan]; + +/* DMA always does autoinit should work under normal situations */ + if (chan->addr_changed) { + /* Calculate the new starting position for dma read*/ + chan->addr_changed=false; + chan->host_address=memory+(chan->page << 16)+chan->base_address; + + chan->current_count=chan->base_count+1; + chan->current_address=chan->base_address; + DMA_DEBUG("DMA:Transfer from %d size %d",(chan->page << 16)+chan->base_address,chan->current_count); + } + if (!count) return; + if (chan->current_count>=count) { + memcpy(buffer,chan->host_address,count); + chan->host_address+=count; + chan->current_address+=count; + chan->current_count-=count; + return; + } else { + /* Copy remaining piece of first buffer */ + memcpy(buffer,chan->host_address,chan->current_count); + buffer+=chan->current_count; + count-=(Bit16u)chan->current_count; + /* Autoinit reset the dma channel */ + chan->host_address=memory+(chan->page << 16)+chan->base_address; + chan->current_count=chan->base_count+1; + chan->current_address=chan->base_address; + /* Copy the rest of the buffer */ + memcpy(buffer,chan->host_address,count); + chan->host_address+=count; + chan->current_address+=count; + chan->current_count-=count; + return; + } +}; + +void DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) { + if (dma[0].chan[dmachan].addr_changed) { + /* Calculate the new starting position for dma read*/ + dma[0].chan[dmachan].addr_changed=false; + dma[0].chan[dmachan].host_address=memory+(dma[0].chan[dmachan].page << 16)+dma[0].chan[dmachan].base_address; + dma[0].chan[dmachan].current_count=dma[0].chan[dmachan].base_count; + dma[0].chan[dmachan].current_count=dma[0].chan[dmachan].current_count; + } + if (dma[0].chan[dmachan].current_count>=count) { + memcpy(dma[0].chan[dmachan].host_address,buffer,count); + dma[0].chan[dmachan].host_address+=count; + dma[0].chan[dmachan].current_address+=count; + dma[0].chan[dmachan].current_count-=count; + return; + } else { + + } + return; +}; + + + + +void DMA_16_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) { + +} + +void DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) { + +} + + + + +void DMA_Init(void) { + for (Bit32u i=0;i<0x10;i++) { + IO_RegisterWriteHandler(i,write_dma,"DMA1"); + } + IO_RegisterWriteHandler(0x81,write_dma_page,"DMA Pages"); + IO_RegisterWriteHandler(0x82,write_dma_page,"DMA Pages"); + IO_RegisterWriteHandler(0x83,write_dma_page,"DMA Pages"); + IO_RegisterWriteHandler(0x87,write_dma_page,"DMA Pages"); +} diff --git a/src/hardware/ega-switch.h b/src/hardware/ega-switch.h new file mode 100644 index 0000000..b4dff45 --- /dev/null +++ b/src/hardware/ega-switch.h @@ -0,0 +1,9730 @@ +switch (bit_mask) { + case 0: + break; + case 1: + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 2: + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 3: + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 4: + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 5: + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 6: + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 7: + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 8: + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 9: + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 10: + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 11: + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 12: + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 13: + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 14: + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 15: + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 16: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + break; + case 17: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 18: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 19: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 20: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 21: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 22: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 23: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 24: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 25: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 26: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 27: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 28: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 29: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 30: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 31: + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 32: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + break; + case 33: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 34: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 35: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 36: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 37: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 38: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 39: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 40: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 41: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 42: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 43: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 44: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 45: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 46: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 47: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 48: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + break; + case 49: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 50: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 51: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 52: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 53: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 54: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 55: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 56: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 57: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 58: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 59: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 60: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 61: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 62: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 63: + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 64: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + break; + case 65: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 66: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 67: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 68: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 69: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 70: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 71: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 72: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 73: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 74: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 75: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 76: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 77: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 78: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 79: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 80: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + break; + case 81: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 82: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 83: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 84: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 85: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 86: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 87: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 88: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 89: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 90: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 91: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 92: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 93: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 94: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 95: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 96: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + break; + case 97: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 98: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 99: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 100: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 101: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 102: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 103: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 104: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 105: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 106: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 107: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 108: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 109: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 110: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 111: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 112: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + break; + case 113: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 114: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 115: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 116: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 117: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 118: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 119: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 120: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 121: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 122: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 123: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 124: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 125: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 126: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 127: + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 128: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + break; + case 129: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 130: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 131: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 132: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 133: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 134: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 135: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 136: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 137: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 138: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 139: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 140: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 141: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 142: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 143: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 144: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + break; + case 145: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 146: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 147: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 148: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 149: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 150: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 151: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 152: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 153: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 154: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 155: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 156: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 157: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 158: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 159: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 160: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + break; + case 161: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 162: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 163: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 164: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 165: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 166: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 167: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 168: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 169: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 170: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 171: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 172: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 173: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 174: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 175: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 176: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + break; + case 177: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 178: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 179: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 180: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 181: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 182: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 183: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 184: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 185: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 186: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 187: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 188: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 189: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 190: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 191: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 192: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + break; + case 193: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 194: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 195: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 196: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 197: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 198: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 199: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 200: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 201: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 202: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 203: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 204: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 205: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 206: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 207: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 208: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + break; + case 209: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 210: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 211: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 212: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 213: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 214: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 215: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 216: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 217: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 218: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 219: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 220: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 221: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 222: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 223: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 224: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + break; + case 225: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 226: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 227: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 228: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 229: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 230: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 231: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 232: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 233: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 234: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 235: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 236: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 237: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 238: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 239: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 240: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + break; + case 241: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 242: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 243: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 244: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 245: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 246: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 247: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 248: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + break; + case 249: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 250: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 251: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 252: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + break; + case 253: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; + case 254: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + break; + case 255: + { + Bit8u color=0; + if (pixels.b[0] & 128) color|=1; + if (pixels.b[1] & 128) color|=2; + if (pixels.b[2] & 128) color|=4; + if (pixels.b[3] & 128) color|=8; + *(write_pixels+0)=color; + *(write_pixels+0+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 64) color|=1; + if (pixels.b[1] & 64) color|=2; + if (pixels.b[2] & 64) color|=4; + if (pixels.b[3] & 64) color|=8; + *(write_pixels+1)=color; + *(write_pixels+1+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 32) color|=1; + if (pixels.b[1] & 32) color|=2; + if (pixels.b[2] & 32) color|=4; + if (pixels.b[3] & 32) color|=8; + *(write_pixels+2)=color; + *(write_pixels+2+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 16) color|=1; + if (pixels.b[1] & 16) color|=2; + if (pixels.b[2] & 16) color|=4; + if (pixels.b[3] & 16) color|=8; + *(write_pixels+3)=color; + *(write_pixels+3+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 8) color|=1; + if (pixels.b[1] & 8) color|=2; + if (pixels.b[2] & 8) color|=4; + if (pixels.b[3] & 8) color|=8; + *(write_pixels+4)=color; + *(write_pixels+4+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 4) color|=1; + if (pixels.b[1] & 4) color|=2; + if (pixels.b[2] & 4) color|=4; + if (pixels.b[3] & 4) color|=8; + *(write_pixels+5)=color; + *(write_pixels+5+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 2) color|=1; + if (pixels.b[1] & 2) color|=2; + if (pixels.b[2] & 2) color|=4; + if (pixels.b[3] & 2) color|=8; + *(write_pixels+6)=color; + *(write_pixels+6+512*1024)=color; + } + { + Bit8u color=0; + if (pixels.b[0] & 1) color|=1; + if (pixels.b[1] & 1) color|=2; + if (pixels.b[2] & 1) color|=4; + if (pixels.b[3] & 1) color|=8; + *(write_pixels+7)=color; + *(write_pixels+7+512*1024)=color; + } + break; +} diff --git a/src/hardware/fmopl.c b/src/hardware/fmopl.c index 9587519..2f73d7d 100644 --- a/src/hardware/fmopl.c +++ b/src/hardware/fmopl.c @@ -1,2524 +1,1878 @@ -/* -** -** File: fmopl.c - software implementation of FM sound generator -** types OPL and OPL2 -** -** Copyright (C) 2002,2003 Jarek Burczynski (bujar at mame dot net) -** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmulator development -** -** Version 0.70 -** - -Revision History: - -14-06-2003 Jarek Burczynski: - - implemented all of the status register flags in Y8950 emulation - - renamed Y8950SetDeltaTMemory() parameters from _rom_ to _mem_ since - they can be either RAM or ROM - -08-10-2002 Jarek Burczynski (thanks to Dox for the YM3526 chip) - - corrected YM3526Read() to always set bit 2 and bit 1 - to HIGH state - identical to YM3812Read (verified on real YM3526) - -04-28-2002 Jarek Burczynski: - - binary exact Envelope Generator (verified on real YM3812); - compared to YM2151: the EG clock is equal to internal_clock, - rates are 2 times slower and volume resolution is one bit less - - modified interface functions (they no longer return pointer - - that's internal to the emulator now): - - new wrapper functions for OPLCreate: YM3526Init(), YM3812Init() and Y8950Init() - - corrected 'off by one' error in feedback calculations (when feedback is off) - - enabled waveform usage (credit goes to Vlad Romascanu and zazzal22) - - speeded up noise generator calculations (Nicola Salmoria) - -03-24-2002 Jarek Burczynski (thanks to Dox for the YM3812 chip) - Complete rewrite (all verified on real YM3812): - - corrected sin_tab and tl_tab data - - corrected operator output calculations - - corrected waveform_select_enable register; - simply: ignore all writes to waveform_select register when - waveform_select_enable == 0 and do not change the waveform previously selected. - - corrected KSR handling - - corrected Envelope Generator: attack shape, Sustain mode and - Percussive/Non-percussive modes handling - - Envelope Generator rates are two times slower now - - LFO amplitude (tremolo) and phase modulation (vibrato) - - rhythm sounds phase generation - - white noise generator (big thanks to Olivier Galibert for mentioning Berlekamp-Massey algorithm) - - corrected key on/off handling (the 'key' signal is ORed from three sources: FM, rhythm and CSM) - - funky details (like ignoring output of operator 1 in BD rhythm sound when connect == 1) - -12-28-2001 Acho A. Tang - - reflected Delta-T EOS status on Y8950 status port. - - fixed subscription range of attack/decay tables - - - To do: - add delay before key off in CSM mode (see CSMKeyControll) - verify volume of the FM part on the Y8950 -*/ - -#include -#include -#include - -//#include "driver.h" /* use M.A.M.E. */ -#include "fmopl.h" - -#ifndef PI -#define PI 3.14159265358979323846 -#endif - - - -/* output final shift */ -#if (OPL_SAMPLE_BITS==16) - #define FINAL_SH (0) - #define MAXOUT (+32767) - #define MINOUT (-32768) -#else - #define FINAL_SH (8) - #define MAXOUT (+127) - #define MINOUT (-128) -#endif - - -#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ -#define EG_SH 16 /* 16.16 fixed point (EG timing) */ -#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */ -#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */ - -#define FREQ_MASK ((1<=0) - { - if (value < 0x0200) - return (value & ~0); - if (value < 0x0400) - return (value & ~1); - if (value < 0x0800) - return (value & ~3); - if (value < 0x1000) - return (value & ~7); - if (value < 0x2000) - return (value & ~15); - if (value < 0x4000) - return (value & ~31); - return (value & ~63); - } - /*else value < 0*/ - if (value > -0x0200) - return (~abs(value) & ~0); - if (value > -0x0400) - return (~abs(value) & ~1); - if (value > -0x0800) - return (~abs(value) & ~3); - if (value > -0x1000) - return (~abs(value) & ~7); - if (value > -0x2000) - return (~abs(value) & ~15); - if (value > -0x4000) - return (~abs(value) & ~31); - return (~abs(value) & ~63); -} - - -static FILE *sample[1]; - #if 1 /*save to MONO file */ - #define SAVE_ALL_CHANNELS \ - { signed int pom = acc_calc(lt); \ - fputc((unsigned short)pom&0xff,sample[0]); \ - fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ - } - #else /*save to STEREO file */ - #define SAVE_ALL_CHANNELS \ - { signed int pom = lt; \ - fputc((unsigned short)pom&0xff,sample[0]); \ - fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ - pom = rt; \ - fputc((unsigned short)pom&0xff,sample[0]); \ - fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ - } - #endif -#endif - -/* #define LOG_CYM_FILE */ -#ifdef LOG_CYM_FILE - FILE * cymfile = NULL; -#endif - - - -#define OPL_TYPE_WAVESEL 0x01 /* waveform select */ -#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */ -#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */ -#define OPL_TYPE_IO 0x08 /* I/O port */ - -/* ---------- Generic interface section ---------- */ -#define OPL_TYPE_YM3526 (0) -#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL) -#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO) - - - -typedef struct{ - UINT32 ar; /* attack rate: AR<<2 */ - UINT32 dr; /* decay rate: DR<<2 */ - UINT32 rr; /* release rate:RR<<2 */ - UINT8 KSR; /* key scale rate */ - UINT8 ksl; /* keyscale level */ - UINT8 ksr; /* key scale rate: kcode>>KSR */ - UINT8 mul; /* multiple: mul_tab[ML] */ - - /* Phase Generator */ - UINT32 Cnt; /* frequency counter */ - UINT32 Incr; /* frequency counter step */ - UINT8 FB; /* feedback shift value */ - INT32 *connect1; /* slot1 output pointer */ - INT32 op1_out[2]; /* slot1 output for feedback */ - UINT8 CON; /* connection (algorithm) type */ - - /* Envelope Generator */ - UINT8 eg_type; /* percussive/non-percussive mode */ - UINT8 state; /* phase type */ - UINT32 TL; /* total level: TL << 2 */ - INT32 TLL; /* adjusted now TL */ - INT32 volume; /* envelope counter */ - UINT32 sl; /* sustain level: sl_tab[SL] */ - UINT8 eg_sh_ar; /* (attack state) */ - UINT8 eg_sel_ar; /* (attack state) */ - UINT8 eg_sh_dr; /* (decay state) */ - UINT8 eg_sel_dr; /* (decay state) */ - UINT8 eg_sh_rr; /* (release state) */ - UINT8 eg_sel_rr; /* (release state) */ - UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */ - - /* LFO */ - UINT32 AMmask; /* LFO Amplitude Modulation enable mask */ - UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/ - - /* waveform select */ - unsigned int wavetable; -} OPL_SLOT; - -typedef struct{ - OPL_SLOT SLOT[2]; - /* phase generator state */ - UINT32 block_fnum; /* block+fnum */ - UINT32 fc; /* Freq. Increment base */ - UINT32 ksl_base; /* KeyScaleLevel Base step */ - UINT8 kcode; /* key code (for key scaling) */ -} OPL_CH; - -/* OPL state */ -typedef struct fm_opl_f { - /* FM channel slots */ - OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels*/ - - UINT32 eg_cnt; /* global envelope generator counter */ - UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */ - UINT32 eg_timer_add; /* step of eg_timer */ - UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */ - - UINT8 rhythm; /* Rhythm mode */ - - UINT32 fn_tab[1024]; /* fnumber->increment counter */ - - /* LFO */ - UINT8 lfo_am_depth; - UINT8 lfo_pm_depth_range; - UINT32 lfo_am_cnt; - UINT32 lfo_am_inc; - UINT32 lfo_pm_cnt; - UINT32 lfo_pm_inc; - - UINT32 noise_rng; /* 23 bit noise shift register */ - UINT32 noise_p; /* current noise 'phase' */ - UINT32 noise_f; /* current noise period */ - - UINT8 wavesel; /* waveform select enable flag */ - - int T[2]; /* timer counters */ - int TC[2]; - UINT8 st[2]; /* timer enable */ - -#if BUILD_Y8950 - /* Delta-T ADPCM unit (Y8950) */ - - YM_DELTAT *deltat; - - /* Keyboard and I/O ports interface */ - UINT8 portDirection; - UINT8 portLatch; - OPL_PORTHANDLER_R porthandler_r; - OPL_PORTHANDLER_W porthandler_w; - int port_param; - OPL_PORTHANDLER_R keyboardhandler_r; - OPL_PORTHANDLER_W keyboardhandler_w; - int keyboard_param; -#endif - - /* external event callback handlers */ - OPL_TIMERHANDLER TimerHandler; /* TIMER handler */ - int TimerParam; /* TIMER parameter */ - OPL_IRQHANDLER IRQHandler; /* IRQ handler */ - int IRQParam; /* IRQ parameter */ - OPL_UPDATEHANDLER UpdateHandler;/* stream update handler */ - int UpdateParam; /* stream update parameter */ - - UINT8 type; /* chip type */ - UINT8 address; /* address register */ - UINT8 status; /* status flag */ - UINT8 statusmask; /* status mask */ - UINT8 mode; /* Reg.08 : CSM,notesel,etc. */ - - int clock; /* master clock (Hz) */ - int rate; /* sampling rate (Hz) */ - double freqbase; /* frequency base */ - double TimerBase; /* Timer base time (==sampling time)*/ -} FM_OPL; - - - -/* mapping of register number (offset) to slot number used by the emulator */ -static const int slot_array[32]= -{ - 0, 2, 4, 1, 3, 5,-1,-1, - 6, 8,10, 7, 9,11,-1,-1, - 12,14,16,13,15,17,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1 -}; - -/* key scale level */ -/* table is 3dB/octave , DV converts this into 6dB/octave */ -/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */ -#define SC(x) ((UINT32)((x)/(0.1875/2.0))) -static const UINT32 ksl_tab[8*16]= -{ - /* OCT 0 */ - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - /* OCT 1 */ - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(0.750), SC(1.125), SC(1.500), - SC(1.875), SC(2.250), SC(2.625), SC(3.000), - /* OCT 2 */ - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(1.125), SC(1.875), SC(2.625), - SC(3.000), SC(3.750), SC(4.125), SC(4.500), - SC(4.875), SC(5.250), SC(5.625), SC(6.000), - /* OCT 3 */ - SC(0.000), SC(0.000), SC(0.000), SC(1.875), - SC(3.000), SC(4.125), SC(4.875), SC(5.625), - SC(6.000), SC(6.750), SC(7.125), SC(7.500), - SC(7.875), SC(8.250), SC(8.625), SC(9.000), - /* OCT 4 */ - SC(0.000), SC(0.000), SC(3.000), SC(4.875), - SC(6.000), SC(7.125), SC(7.875), SC(8.625), - SC(9.000), SC(9.750),SC(10.125),SC(10.500), - SC(10.875),SC(11.250),SC(11.625),SC(12.000), - /* OCT 5 */ - SC(0.000), SC(3.000), SC(6.000), SC(7.875), - SC(9.000),SC(10.125),SC(10.875),SC(11.625), - SC(12.000),SC(12.750),SC(13.125),SC(13.500), - SC(13.875),SC(14.250),SC(14.625),SC(15.000), - /* OCT 6 */ - SC(0.000), SC(6.000), SC(9.000),SC(10.875), - SC(12.000),SC(13.125),SC(13.875),SC(14.625), - SC(15.000),SC(15.750),SC(16.125),SC(16.500), - SC(16.875),SC(17.250),SC(17.625),SC(18.000), - /* OCT 7 */ - SC(0.000), SC(9.000),SC(12.000),SC(13.875), - SC(15.000),SC(16.125),SC(16.875),SC(17.625), - SC(18.000),SC(18.750),SC(19.125),SC(19.500), - SC(19.875),SC(20.250),SC(20.625),SC(21.000) -}; -#undef SC - -/* key scale level lookup */ -static const INT32 ksl_level[4]= -{ - 31,1,2,0 -}; - -/* sustain level table (3dB per step) */ -/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ -#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) ) -static const UINT32 sl_tab[16]={ - SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7), - SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31) -}; -#undef SC - - -#define RATE_STEPS (8) -static const unsigned char eg_inc[15*RATE_STEPS]={ - -/*cycle:0 1 2 3 4 5 6 7*/ - -/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */ -/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */ -/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */ -/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */ - -/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */ -/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */ -/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */ -/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */ - -/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */ -/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */ -/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */ -/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */ - -/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */ -/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */ -/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */ -}; - - -#define O(a) (a*RATE_STEPS) - -/*note that there is no O(13) in this table - it's directly in the code */ -static const unsigned char eg_rate_select[16+64+16]={ /* Envelope Generator rates (16 + 64 rates + 16 RKS) */ -/* 16 infinite time rates */ -O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14), -O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14), - -/* rates 00-12 */ -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), - -/* rate 13 */ -O( 4),O( 5),O( 6),O( 7), - -/* rate 14 */ -O( 8),O( 9),O(10),O(11), - -/* rate 15 */ -O(12),O(12),O(12),O(12), - -/* 16 dummy rates (same as 15 3) */ -O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12), -O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12), - -}; -#undef O - -/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */ -/*shift 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 */ -/*mask 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0 */ - -#define O(a) (a*1) -static const unsigned char eg_rate_shift[16+64+16]={ /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */ -/* 16 infinite time rates */ -O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), -O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), - -/* rates 00-12 */ -O(12),O(12),O(12),O(12), -O(11),O(11),O(11),O(11), -O(10),O(10),O(10),O(10), -O( 9),O( 9),O( 9),O( 9), -O( 8),O( 8),O( 8),O( 8), -O( 7),O( 7),O( 7),O( 7), -O( 6),O( 6),O( 6),O( 6), -O( 5),O( 5),O( 5),O( 5), -O( 4),O( 4),O( 4),O( 4), -O( 3),O( 3),O( 3),O( 3), -O( 2),O( 2),O( 2),O( 2), -O( 1),O( 1),O( 1),O( 1), -O( 0),O( 0),O( 0),O( 0), - -/* rate 13 */ -O( 0),O( 0),O( 0),O( 0), - -/* rate 14 */ -O( 0),O( 0),O( 0),O( 0), - -/* rate 15 */ -O( 0),O( 0),O( 0),O( 0), - -/* 16 dummy rates (same as 15 3) */ -O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), -O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), - -}; -#undef O - - -/* multiple table */ -#define SC(x) ((UINT32)((x)*2)) -static const UINT8 mul_tab[16]= { -/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ - SC(0.50), SC(1.00), SC(2.00), SC(3.00), SC(4.00), SC(5.00), SC(6.00), SC(7.00), - SC(8.00), SC(9.00),SC(10.00),SC(10.00),SC(12.00),SC(12.00),SC(15.00),SC(15.00) -}; -#undef SC - -/* TL_TAB_LEN is calculated as: -* 12 - sinus amplitude bits (Y axis) -* 2 - sinus sign bit (Y axis) -* TL_RES_LEN - sinus resolution (X axis) -*/ -#define TL_TAB_LEN (12*2*TL_RES_LEN) -static signed int tl_tab[TL_TAB_LEN]; - -#define ENV_QUIET (TL_TAB_LEN>>4) - -/* sin waveform table in 'decibel' scale */ -/* four waveforms on OPL2 type chips */ -static unsigned int sin_tab[SIN_LEN * 4]; - - -/* LFO Amplitude Modulation table (verified on real YM3812) - 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples - - Length: 210 elements. - - Each of the elements has to be repeated - exactly 64 times (on 64 consecutive samples). - The whole table takes: 64 * 210 = 13440 samples. - - When AM = 1 data is used directly - When AM = 0 data is divided by 4 before being used (loosing precision is important) -*/ - -#define LFO_AM_TAB_ELEMENTS 210 - -static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = { -0,0,0,0,0,0,0, -1,1,1,1, -2,2,2,2, -3,3,3,3, -4,4,4,4, -5,5,5,5, -6,6,6,6, -7,7,7,7, -8,8,8,8, -9,9,9,9, -10,10,10,10, -11,11,11,11, -12,12,12,12, -13,13,13,13, -14,14,14,14, -15,15,15,15, -16,16,16,16, -17,17,17,17, -18,18,18,18, -19,19,19,19, -20,20,20,20, -21,21,21,21, -22,22,22,22, -23,23,23,23, -24,24,24,24, -25,25,25,25, -26,26,26, -25,25,25,25, -24,24,24,24, -23,23,23,23, -22,22,22,22, -21,21,21,21, -20,20,20,20, -19,19,19,19, -18,18,18,18, -17,17,17,17, -16,16,16,16, -15,15,15,15, -14,14,14,14, -13,13,13,13, -12,12,12,12, -11,11,11,11, -10,10,10,10, -9,9,9,9, -8,8,8,8, -7,7,7,7, -6,6,6,6, -5,5,5,5, -4,4,4,4, -3,3,3,3, -2,2,2,2, -1,1,1,1 -}; - -/* LFO Phase Modulation table (verified on real YM3812) */ -static const INT8 lfo_pm_table[8*8*2] = { - -/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */ -0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/ -0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */ -0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/ -1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */ -1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/ -2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */ -1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/ -3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */ -2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/ -4, 2, 0,-2,-4,-2, 0, 2, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */ -2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/ -5, 2, 0,-2,-5,-2, 0, 2, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */ -3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/ -6, 3, 0,-3,-6,-3, 0, 3, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */ -3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/ -7, 3, 0,-3,-7,-3, 0, 3 /*LFO PM depth = 1*/ -}; - - -/* lock level of common table */ -static int num_lock = 0; - - -static void *cur_chip = NULL; /* current chip pointer */ -static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2; - -static signed int phase_modulation; /* phase modulation input (SLOT 2) */ -static signed int output[1]; - -#if BUILD_Y8950 -static INT32 output_deltat[4]; /* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */ -#endif - -static UINT32 LFO_AM; -static INT32 LFO_PM; - - - -INLINE int limit( int val, int max, int min ) { - if ( val > max ) - val = max; - else if ( val < min ) - val = min; - - return val; -} - - -/* status set and IRQ handling */ -INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag) -{ - /* set status flag */ - OPL->status |= flag; - if(!(OPL->status & 0x80)) - { - if(OPL->status & OPL->statusmask) - { /* IRQ on */ - OPL->status |= 0x80; - /* callback user interrupt handler (IRQ is OFF to ON) */ - if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1); - } - } -} - -/* status reset and IRQ handling */ -INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag) -{ - /* reset status flag */ - OPL->status &=~flag; - if((OPL->status & 0x80)) - { - if (!(OPL->status & OPL->statusmask) ) - { - OPL->status &= 0x7f; - /* callback user interrupt handler (IRQ is ON to OFF) */ - if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0); - } - } -} - -/* IRQ mask set */ -INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag) -{ - OPL->statusmask = flag; - /* IRQ handling check */ - OPL_STATUS_SET(OPL,0); - OPL_STATUS_RESET(OPL,0); -} - - -/* advance LFO to next sample */ -INLINE void advance_lfo(FM_OPL *OPL) -{ - UINT8 tmp; - - /* LFO */ - OPL->lfo_am_cnt += OPL->lfo_am_inc; - if (OPL->lfo_am_cnt >= (LFO_AM_TAB_ELEMENTS<lfo_am_cnt -= (LFO_AM_TAB_ELEMENTS<lfo_am_cnt >> LFO_SH ]; - - if (OPL->lfo_am_depth) - LFO_AM = tmp; - else - LFO_AM = tmp>>2; - - OPL->lfo_pm_cnt += OPL->lfo_pm_inc; - LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range; -} - -/* advance to next sample */ -INLINE void advance(FM_OPL *OPL) -{ - OPL_CH *CH; - OPL_SLOT *op; - int i; - - OPL->eg_timer += OPL->eg_timer_add; - - while (OPL->eg_timer >= OPL->eg_timer_overflow) - { - OPL->eg_timer -= OPL->eg_timer_overflow; - - OPL->eg_cnt++; - - for (i=0; i<9*2; i++) - { - CH = &OPL->P_CH[i/2]; - op = &CH->SLOT[i&1]; - - /* Envelope Generator */ - switch(op->state) - { - case EG_ATT: /* attack phase */ - if ( !(OPL->eg_cnt & ((1<eg_sh_ar)-1) ) ) - { - op->volume += (~op->volume * - (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)]) - ) >>3; - - if (op->volume <= MIN_ATT_INDEX) - { - op->volume = MIN_ATT_INDEX; - op->state = EG_DEC; - } - - } - break; - - case EG_DEC: /* decay phase */ - if ( !(OPL->eg_cnt & ((1<eg_sh_dr)-1) ) ) - { - op->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)]; - - if ( op->volume >= op->sl ) - op->state = EG_SUS; - - } - break; - - case EG_SUS: /* sustain phase */ - - /* this is important behaviour: - one can change percusive/non-percussive modes on the fly and - the chip will remain in sustain phase - verified on real YM3812 */ - - if(op->eg_type) /* non-percussive mode */ - { - /* do nothing */ - } - else /* percussive mode */ - { - /* during sustain phase chip adds Release Rate (in percussive mode) */ - if ( !(OPL->eg_cnt & ((1<eg_sh_rr)-1) ) ) - { - op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)]; - - if ( op->volume >= MAX_ATT_INDEX ) - op->volume = MAX_ATT_INDEX; - } - /* else do nothing in sustain phase */ - } - break; - - case EG_REL: /* release phase */ - if ( !(OPL->eg_cnt & ((1<eg_sh_rr)-1) ) ) - { - op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)]; - - if ( op->volume >= MAX_ATT_INDEX ) - { - op->volume = MAX_ATT_INDEX; - op->state = EG_OFF; - } - - } - break; - - default: - break; - } - } - } - - for (i=0; i<9*2; i++) - { - CH = &OPL->P_CH[i/2]; - op = &CH->SLOT[i&1]; - - /* Phase Generator */ - if(op->vib) - { - UINT8 block; - unsigned int block_fnum = CH->block_fnum; - - unsigned int fnum_lfo = (block_fnum&0x0380) >> 7; - - signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + 16*fnum_lfo ]; - - if (lfo_fn_table_index_offset) /* LFO phase modulation active */ - { - block_fnum += lfo_fn_table_index_offset; - block = (block_fnum&0x1c00) >> 10; - op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul; - } - else /* LFO phase modulation = zero */ - { - op->Cnt += op->Incr; - } - } - else /* LFO phase modulation disabled for this operator */ - { - op->Cnt += op->Incr; - } - } - - /* The Noise Generator of the YM3812 is 23-bit shift register. - * Period is equal to 2^23-2 samples. - * Register works at sampling frequency of the chip, so output - * can change on every sample. - * - * Output of the register and input to the bit 22 is: - * bit0 XOR bit14 XOR bit15 XOR bit22 - * - * Simply use bit 22 as the noise output. - */ - - OPL->noise_p += OPL->noise_f; - i = OPL->noise_p >> FREQ_SH; /* number of events (shifts of the shift register) */ - OPL->noise_p &= FREQ_MASK; - while (i) - { - /* - UINT32 j; - j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1; - OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1); - */ - - /* - Instead of doing all the logic operations above, we - use a trick here (and use bit 0 as the noise output). - The difference is only that the noise bit changes one - step ahead. This doesn't matter since we don't know - what is real state of the noise_rng after the reset. - */ - - if (OPL->noise_rng & 1) OPL->noise_rng ^= 0x800302; - OPL->noise_rng >>= 1; - - i--; - } -} - - -INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) -{ - UINT32 p; - - p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ]; - - if (p >= TL_TAB_LEN) - return 0; - return tl_tab[p]; -} - -INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) -{ - UINT32 p; - - p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK) ]; - - if (p >= TL_TAB_LEN) - return 0; - return tl_tab[p]; -} - - -#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask)) - -/* calculate output */ -INLINE void OPL_CALC_CH( OPL_CH *CH ) -{ - OPL_SLOT *SLOT; - unsigned int env; - signed int out; - - phase_modulation = 0; - - /* SLOT 1 */ - SLOT = &CH->SLOT[SLOT1]; - env = volume_calc(SLOT); - out = SLOT->op1_out[0] + SLOT->op1_out[1]; - SLOT->op1_out[0] = SLOT->op1_out[1]; - *SLOT->connect1 += SLOT->op1_out[0]; - SLOT->op1_out[1] = 0; - if( env < ENV_QUIET ) - { - if (!SLOT->FB) - out = 0; - SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB), SLOT->wavetable ); - } - - /* SLOT 2 */ - SLOT++; - env = volume_calc(SLOT); - if( env < ENV_QUIET ) - output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable); -} - -/* - operators used in the rhythm sounds generation process: - - Envelope Generator: - -channel operator register number Bass High Snare Tom Top -/ slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal - 6 / 0 12 50 70 90 f0 + - 6 / 1 15 53 73 93 f3 + - 7 / 0 13 51 71 91 f1 + - 7 / 1 16 54 74 94 f4 + - 8 / 0 14 52 72 92 f2 + - 8 / 1 17 55 75 95 f5 + - - Phase Generator: - -channel operator register number Bass High Snare Tom Top -/ slot number MULTIPLE Drum Hat Drum Tom Cymbal - 6 / 0 12 30 + - 6 / 1 15 33 + - 7 / 0 13 31 + + + - 7 / 1 16 34 ----- n o t u s e d ----- - 8 / 0 14 32 + - 8 / 1 17 35 + + - -channel operator register number Bass High Snare Tom Top -number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal - 6 12,15 B6 A6 + - - 7 13,16 B7 A7 + + + - - 8 14,17 B8 A8 + + + - -*/ - -/* calculate rhythm */ - -INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise ) -{ - OPL_SLOT *SLOT; - signed int out; - unsigned int env; - - - /* Bass Drum (verified on real YM3812): - - depends on the channel 6 'connect' register: - when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out) - when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored - - output sample always is multiplied by 2 - */ - - phase_modulation = 0; - /* SLOT 1 */ - SLOT = &CH[6].SLOT[SLOT1]; - env = volume_calc(SLOT); - - out = SLOT->op1_out[0] + SLOT->op1_out[1]; - SLOT->op1_out[0] = SLOT->op1_out[1]; - - if (!SLOT->CON) - phase_modulation = SLOT->op1_out[0]; - /* else ignore output of operator 1 */ - - SLOT->op1_out[1] = 0; - if( env < ENV_QUIET ) - { - if (!SLOT->FB) - out = 0; - SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB), SLOT->wavetable ); - } - - /* SLOT 2 */ - SLOT++; - env = volume_calc(SLOT); - if( env < ENV_QUIET ) - output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable) * 2; - - - /* Phase generation is based on: */ - /* HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */ - /* SD (16) channel 7->slot 1 */ - /* TOM (14) channel 8->slot 1 */ - /* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */ - - /* Envelope generation based on: */ - /* HH channel 7->slot1 */ - /* SD channel 7->slot2 */ - /* TOM channel 8->slot1 */ - /* TOP channel 8->slot2 */ - - - /* The following formulas can be well optimized. - I leave them in direct form for now (in case I've missed something). - */ - - /* High Hat (verified on real YM3812) */ - env = volume_calc(SLOT7_1); - if( env < ENV_QUIET ) - { - - /* high hat phase generation: - phase = d0 or 234 (based on frequency only) - phase = 34 or 2d0 (based on noise) - */ - - /* base frequency derived from operator 1 in channel 7 */ - unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1; - unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1; - unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1; - - unsigned char res1 = (bit2 ^ bit7) | bit3; - - /* when res1 = 0 phase = 0x000 | 0xd0; */ - /* when res1 = 1 phase = 0x200 | (0xd0>>2); */ - UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0; - - /* enable gate based on frequency of operator 2 in channel 8 */ - unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1; - unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1; - - unsigned char res2 = (bit3e ^ bit5e); - - /* when res2 = 0 pass the phase from calculation above (res1); */ - /* when res2 = 1 phase = 0x200 | (0xd0>>2); */ - if (res2) - phase = (0x200|(0xd0>>2)); - - - /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */ - /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */ - if (phase&0x200) - { - if (noise) - phase = 0x200|0xd0; - } - else - /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */ - /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */ - { - if (noise) - phase = 0xd0>>2; - } - - output[0] += op_calc(phase<wavetable) * 2; - } - - /* Snare Drum (verified on real YM3812) */ - env = volume_calc(SLOT7_2); - if( env < ENV_QUIET ) - { - /* base frequency derived from operator 1 in channel 7 */ - unsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1; - - /* when bit8 = 0 phase = 0x100; */ - /* when bit8 = 1 phase = 0x200; */ - UINT32 phase = bit8 ? 0x200 : 0x100; - - /* Noise bit XOR'es phase by 0x100 */ - /* when noisebit = 0 pass the phase from calculation above */ - /* when noisebit = 1 phase ^= 0x100; */ - /* in other words: phase ^= (noisebit<<8); */ - if (noise) - phase ^= 0x100; - - output[0] += op_calc(phase<wavetable) * 2; - } - - /* Tom Tom (verified on real YM3812) */ - env = volume_calc(SLOT8_1); - if( env < ENV_QUIET ) - output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2; - - /* Top Cymbal (verified on real YM3812) */ - env = volume_calc(SLOT8_2); - if( env < ENV_QUIET ) - { - /* base frequency derived from operator 1 in channel 7 */ - unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1; - unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1; - unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1; - - unsigned char res1 = (bit2 ^ bit7) | bit3; - - /* when res1 = 0 phase = 0x000 | 0x100; */ - /* when res1 = 1 phase = 0x200 | 0x100; */ - UINT32 phase = res1 ? 0x300 : 0x100; - - /* enable gate based on frequency of operator 2 in channel 8 */ - unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1; - unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1; - - unsigned char res2 = (bit3e ^ bit5e); - /* when res2 = 0 pass the phase from calculation above (res1); */ - /* when res2 = 1 phase = 0x200 | 0x100; */ - if (res2) - phase = 0x300; - - output[0] += op_calc(phase<wavetable) * 2; - } - -} - - -/* generic table initialize */ -static int init_tables(void) -{ - signed int i,x; - signed int n; - double o,m; - - - for (x=0; x>= 4; /* 12 bits here */ - if (n&1) /* round to nearest */ - n = (n>>1)+1; - else - n = n>>1; - /* 11 bits here (rounded) */ - n <<= 1; /* 12 bits here (as in real chip) */ - tl_tab[ x*2 + 0 ] = n; - tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ]; - - for (i=1; i<12; i++) - { - tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i; - tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ]; - } - #if 0 - logerror("tl %04i", x*2); - for (i=0; i<12; i++) - logerror(", [%02i] %5i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] ); - logerror("\n"); - #endif - } - /*logerror("FMOPL.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/ - - - for (i=0; i0.0) - o = 8*log(1.0/m)/log(2.0); /* convert to 'decibels' */ - else - o = 8*log(-1.0/m)/log(2.0); /* convert to 'decibels' */ - - o = o / (ENV_STEP/4); - - n = (int)(2.0*o); - if (n&1) /* round to nearest */ - n = (n>>1)+1; - else - n = n>>1; - - sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); - - /*logerror("FMOPL.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/ - } - - for (i=0; i>1) ]; - - /* waveform 3: _ _ _ _ */ - /* / |_/ |_/ |_/ |_*/ - /* abs(output only first quarter of the sinus waveform) */ - - if (i & (1<<(SIN_BITS-2)) ) - sin_tab[3*SIN_LEN+i] = TL_TAB_LEN; - else - sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)]; - - /*logerror("FMOPL.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] ); - logerror("FMOPL.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] ); - logerror("FMOPL.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );*/ - } - /*logerror("FMOPL.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/ - - -#ifdef SAVE_SAMPLE - sample[0]=fopen("sampsum.pcm","wb"); -#endif - - return 1; -} - -static void OPLCloseTable( void ) -{ -#ifdef SAVE_SAMPLE - fclose(sample[0]); -#endif -} - - - -static void OPL_initalize(FM_OPL *OPL) -{ - int i; - - /* frequency base */ - OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate : 0; -#if 0 - OPL->rate = (double)OPL->clock / 72.0; - OPL->freqbase = 1.0; -#endif - - /*logerror("freqbase=%f\n", OPL->freqbase);*/ - - /* Timer base time */ - OPL->TimerBase = 1.0 / ((double)OPL->clock / 72.0 ); - - /* make fnumber -> increment counter table */ - for( i=0 ; i < 1024 ; i++ ) - { - /* opn phase increment counter = 20bit */ - OPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */ -#if 0 - logerror("FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\n", - i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 ); -#endif - } - -#if 0 - for( i=0 ; i < 16 ; i++ ) - { - logerror("FMOPL.C: sl_tab[%i] = %08x\n", - i, sl_tab[i] ); - } - for( i=0 ; i < 8 ; i++ ) - { - int j; - logerror("FMOPL.C: ksl_tab[oct=%2i] =",i); - for (j=0; j<16; j++) - { - logerror("%08x ", ksl_tab[i*16+j] ); - } - logerror("\n"); - } -#endif - - - /* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */ - /* One entry from LFO_AM_TABLE lasts for 64 samples */ - OPL->lfo_am_inc = (UINT32)((1.0 / 64.0 ) * (1<freqbase); - - /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */ - OPL->lfo_pm_inc = (UINT32)((1.0 / 1024.0) * (1<freqbase); - - /*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/ - - /* Noise generator: a step takes 1 sample */ - OPL->noise_f = (UINT32)((1.0 / 1.0) * (1<freqbase); - - OPL->eg_timer_add = (UINT32)((1<freqbase); - OPL->eg_timer_overflow = ( 1 ) * (1<eg_timer_add, OPL->eg_timer_overflow);*/ - -} - -INLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set) -{ - if( !SLOT->key ) - { - /* restart Phase Generator */ - SLOT->Cnt = 0; - /* phase -> Attack */ - SLOT->state = EG_ATT; - } - SLOT->key |= key_set; -} - -INLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr) -{ - if( SLOT->key ) - { - SLOT->key &= key_clr; - - if( !SLOT->key ) - { - /* phase -> Release */ - if (SLOT->state>EG_REL) - SLOT->state = EG_REL; - } - } -} - -/* update phase increment counter of operator (also update the EG rates if necessary) */ -INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT) -{ - int ksr; - - /* (frequency) phase increment counter */ - SLOT->Incr = CH->fc * SLOT->mul; - ksr = CH->kcode >> SLOT->KSR; - - if( SLOT->ksr != ksr ) - { - SLOT->ksr = ksr; - - /* calculate envelope generator rates */ - if ((SLOT->ar + SLOT->ksr) < 16+62) - { - SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; - SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; - } - else - { - SLOT->eg_sh_ar = 0; - SLOT->eg_sel_ar = 13*RATE_STEPS; - } - SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; - SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; - SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; - SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; - } -} - -/* set multi,am,vib,EG-TYP,KSR,mul */ -INLINE void set_mul(FM_OPL *OPL,int slot,int v) -{ - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - - SLOT->mul = mul_tab[v&0x0f]; - SLOT->KSR = (v&0x10) ? 0 : 2; - SLOT->eg_type = (v&0x20); - SLOT->vib = (v&0x40); - SLOT->AMmask = (v&0x80) ? ~0 : 0; - CALC_FCSLOT(CH,SLOT); -} - -/* set ksl & tl */ -INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v) -{ - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - - SLOT->ksl = ksl_level[(v>>6)&3]; /* 0 / 3.0 / 1.5 / 6.0 dB/OCT */ - SLOT->TL = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */ - - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); -} - -/* set attack rate & decay rate */ -INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v) -{ - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - - SLOT->ar = (v>>4) ? 16 + ((v>>4) <<2) : 0; - - if ((SLOT->ar + SLOT->ksr) < 16+62) - { - SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; - SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; - } - else - { - SLOT->eg_sh_ar = 0; - SLOT->eg_sel_ar = 13*RATE_STEPS; - } - - SLOT->dr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; - SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; - SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; -} - -/* set sustain level & release rate */ -INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v) -{ - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - - SLOT->sl = sl_tab[ v>>4 ]; - - SLOT->rr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; - SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; - SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; -} - - -/* write a value v to register r on OPL chip */ -static void OPLWriteReg(FM_OPL *OPL, int r, int v) -{ - OPL_CH *CH; - int slot; - int block_fnum; - - - /* adjust bus to 8 bits */ - r &= 0xff; - v &= 0xff; - -#ifdef LOG_CYM_FILE - if ((cymfile) && (r!=0) ) - { - fputc( (unsigned char)r, cymfile ); - fputc( (unsigned char)v, cymfile ); - } -#endif - - - switch(r&0xe0) - { - case 0x00: /* 00-1f:control */ - switch(r&0x1f) - { - case 0x01: /* waveform select enable */ - if(OPL->type&OPL_TYPE_WAVESEL) - { - OPL->wavesel = v&0x20; - /* do not change the waveform previously selected */ - } - break; - case 0x02: /* Timer 1 */ - OPL->T[0] = (256-v)*4; - break; - case 0x03: /* Timer 2 */ - OPL->T[1] = (256-v)*16; - break; - case 0x04: /* IRQ clear / mask and Timer enable */ - if(v&0x80) - { /* IRQ flag clear */ - OPL_STATUS_RESET(OPL,0x7f); - } - else - { /* set IRQ mask ,timer enable*/ - OPL->st[0] = v&1; - OPL->st[1] = (v>>1)&1; - - /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */ - OPL_STATUS_RESET(OPL, v & 0x78 ); - OPL_STATUSMASK_SET(OPL, (~v) & 0x78 ); - - /* timer 1 */ - if(OPL->st[0]) - { - OPL->TC[0]=OPL->T[0]*20; - double interval = (double)OPL->T[0]*OPL->TimerBase; - if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval); - } - /* timer 2 */ - if(OPL->st[1]) - { - OPL->TC[1]=OPL->T[1]*20; - double interval =(double)OPL->T[1]*OPL->TimerBase; - if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval); - } - } - break; -#if BUILD_Y8950 - case 0x06: /* Key Board OUT */ - if(OPL->type&OPL_TYPE_KEYBOARD) - { - if(OPL->keyboardhandler_w) - OPL->keyboardhandler_w(OPL->keyboard_param,v); - else - logerror("Y8950: write unmapped KEYBOARD port\n"); - } - break; - case 0x07: /* DELTA-T control 1 : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */ - if(OPL->type&OPL_TYPE_ADPCM) - YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); - break; -#endif - case 0x08: /* MODE,DELTA-T control 2 : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */ - OPL->mode = v; -#if BUILD_Y8950 - if(OPL->type&OPL_TYPE_ADPCM) - YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v&0x0f); /* mask 4 LSBs in register 08 for DELTA-T unit */ -#endif - break; - -#if BUILD_Y8950 - case 0x09: /* START ADD */ - case 0x0a: - case 0x0b: /* STOP ADD */ - case 0x0c: - case 0x0d: /* PRESCALE */ - case 0x0e: - case 0x0f: /* ADPCM data write */ - case 0x10: /* DELTA-N */ - case 0x11: /* DELTA-N */ - case 0x12: /* ADPCM volume */ - if(OPL->type&OPL_TYPE_ADPCM) - YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); - break; - - case 0x15: /* DAC data high 8 bits (F7,F6...F2) */ - case 0x16: /* DAC data low 2 bits (F1, F0 in bits 7,6) */ - case 0x17: /* DAC data shift (S2,S1,S0 in bits 2,1,0) */ - logerror("FMOPL.C: DAC data register written, but not implemented reg=%02x val=%02x\n",r,v); - break; - - case 0x18: /* I/O CTRL (Direction) */ - if(OPL->type&OPL_TYPE_IO) - OPL->portDirection = v&0x0f; - break; - case 0x19: /* I/O DATA */ - if(OPL->type&OPL_TYPE_IO) - { - OPL->portLatch = v; - if(OPL->porthandler_w) - OPL->porthandler_w(OPL->port_param,v&OPL->portDirection); - } - break; -#endif - default: - logerror("FMOPL.C: write to unknown register: %02x\n",r); - break; - } - break; - case 0x20: /* am ON, vib ON, ksr, eg_type, mul */ - slot = slot_array[r&0x1f]; - if(slot < 0) return; - set_mul(OPL,slot,v); - break; - case 0x40: - slot = slot_array[r&0x1f]; - if(slot < 0) return; - set_ksl_tl(OPL,slot,v); - break; - case 0x60: - slot = slot_array[r&0x1f]; - if(slot < 0) return; - set_ar_dr(OPL,slot,v); - break; - case 0x80: - slot = slot_array[r&0x1f]; - if(slot < 0) return; - set_sl_rr(OPL,slot,v); - break; - case 0xa0: - if (r == 0xbd) /* am depth, vibrato depth, r,bd,sd,tom,tc,hh */ - { - OPL->lfo_am_depth = v & 0x80; - OPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0; - - OPL->rhythm = v&0x3f; - - if(OPL->rhythm&0x20) - { - /* BD key on/off */ - if(v&0x10) - { - FM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2); - FM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2); - } - else - { - FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2); - FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2); - } - /* HH key on/off */ - if(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2); - else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2); - /* SD key on/off */ - if(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2); - else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2); - /* TOM key on/off */ - if(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2); - else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2); - /* TOP-CY key on/off */ - if(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2); - else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2); - } - else - { - /* BD key off */ - FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2); - FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2); - /* HH key off */ - FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2); - /* SD key off */ - FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2); - /* TOM key off */ - FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2); - /* TOP-CY off */ - FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2); - } - return; - } - /* keyon,block,fnum */ - if( (r&0x0f) > 8) return; - CH = &OPL->P_CH[r&0x0f]; - if(!(r&0x10)) - { /* a0-a8 */ - block_fnum = (CH->block_fnum&0x1f00) | v; - } - else - { /* b0-b8 */ - block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff); - - if(v&0x20) - { - FM_KEYON (&CH->SLOT[SLOT1], 1); - FM_KEYON (&CH->SLOT[SLOT2], 1); - } - else - { - FM_KEYOFF(&CH->SLOT[SLOT1],~1); - FM_KEYOFF(&CH->SLOT[SLOT2],~1); - } - } - /* update */ - if(CH->block_fnum != block_fnum) - { - UINT8 block = block_fnum >> 10; - - CH->block_fnum = block_fnum; - - CH->ksl_base = ksl_tab[block_fnum>>6]; - CH->fc = OPL->fn_tab[block_fnum&0x03ff] >> (7-block); - - /* BLK 2,1,0 bits -> bits 3,2,1 of kcode */ - CH->kcode = (CH->block_fnum&0x1c00)>>9; - - /* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */ - /* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum */ - /* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */ - if (OPL->mode&0x40) - CH->kcode |= (CH->block_fnum&0x100)>>8; /* notesel == 1 */ - else - CH->kcode |= (CH->block_fnum&0x200)>>9; /* notesel == 0 */ - - /* refresh Total Level in both SLOTs of this channel */ - CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl); - CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl); - - /* refresh frequency counter in both SLOTs of this channel */ - CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); - CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); - } - break; - case 0xc0: - /* FB,C */ - if( (r&0x0f) > 8) return; - CH = &OPL->P_CH[r&0x0f]; - CH->SLOT[SLOT1].FB = (v>>1)&7 ? ((v>>1)&7) + 7 : 0; - CH->SLOT[SLOT1].CON = v&1; - CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &output[0] : &phase_modulation; - break; - case 0xe0: /* waveform select */ - /* simply ignore write to the waveform select register if selecting not enabled in test register */ - if(OPL->wavesel) - { - slot = slot_array[r&0x1f]; - if(slot < 0) return; - CH = &OPL->P_CH[slot/2]; - - CH->SLOT[slot&1].wavetable = (v&0x03)*SIN_LEN; - } - break; - } -} - -#ifdef LOG_CYM_FILE -static void cymfile_callback (int n) -{ - if (cymfile) - { - fputc( (unsigned char)0, cymfile ); - } -} -#endif - -/* lock/unlock for common table */ -static int OPL_LockTable(void) -{ - num_lock++; - if(num_lock>1) return 0; - - /* first time */ - - cur_chip = NULL; - /* allocate total level table (128kb space) */ - if( !init_tables() ) - { - num_lock--; - return -1; - } - -#ifdef LOG_CYM_FILE - cymfile = fopen("3812_.cym","wb"); - if (cymfile) - timer_pulse ( TIME_IN_HZ(110), 0, cymfile_callback); /*110 Hz pulse timer*/ - else - logerror("Could not create file 3812_.cym\n"); -#endif - - return 0; -} - -static void OPL_UnLockTable(void) -{ - if(num_lock) num_lock--; - if(num_lock) return; - - /* last time */ - - cur_chip = NULL; - OPLCloseTable(); - -#ifdef LOG_CYM_FILE - fclose (cymfile); - cymfile = NULL; -#endif - -} - -static void OPLResetChip(FM_OPL *OPL) -{ - int c,s; - int i; - - OPL->eg_timer = 0; - OPL->eg_cnt = 0; - - OPL->noise_rng = 1; /* noise shift register */ - OPL->mode = 0; /* normal mode */ - OPL_STATUS_RESET(OPL,0x7f); - - /* reset with register write */ - OPLWriteReg(OPL,0x01,0); /* wavesel disable */ - OPLWriteReg(OPL,0x02,0); /* Timer1 */ - OPLWriteReg(OPL,0x03,0); /* Timer2 */ - OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */ - for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0); - - /* reset operator parameters */ - for( c = 0 ; c < 9 ; c++ ) - { - OPL_CH *CH = &OPL->P_CH[c]; - for(s = 0 ; s < 2 ; s++ ) - { - /* wave table */ - CH->SLOT[s].wavetable = 0; - CH->SLOT[s].state = EG_OFF; - CH->SLOT[s].volume = MAX_ATT_INDEX; - } - } -#if BUILD_Y8950 - if(OPL->type&OPL_TYPE_ADPCM) - { - YM_DELTAT *DELTAT = OPL->deltat; - - DELTAT->freqbase = OPL->freqbase; - DELTAT->output_pointer = &output_deltat[0]; - DELTAT->portshift = 5; - DELTAT->output_range = 1<<23; - YM_DELTAT_ADPCM_Reset(DELTAT,0); - } -#endif -} - -/* Create one of virtual YM3812/YM3526/Y8950 */ -/* 'clock' is chip clock in Hz */ -/* 'rate' is sampling rate */ -static FM_OPL *OPLCreate(int type, int clock, int rate) -{ - char *ptr; - FM_OPL *OPL; - int state_size; - - if (OPL_LockTable() ==-1) return NULL; - - /* calculate OPL state size */ - state_size = sizeof(FM_OPL); - -#if BUILD_Y8950 - if (type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT); -#endif - - /* allocate memory block */ - ptr = (char *)malloc(state_size); - - if (ptr==NULL) - return NULL; - - /* clear */ - memset(ptr,0,state_size); - - OPL = (FM_OPL *)ptr; - - ptr += sizeof(FM_OPL); - -#if BUILD_Y8950 - if (type&OPL_TYPE_ADPCM) - { - OPL->deltat = (YM_DELTAT *)ptr; - } - ptr += sizeof(YM_DELTAT); -#endif - - OPL->type = type; - OPL->clock = clock; - OPL->rate = rate; - - /* init global tables */ - OPL_initalize(OPL); - - return OPL; -} - -/* Destroy one of virtual YM3812 */ -static void OPLDestroy(FM_OPL *OPL) -{ - OPL_UnLockTable(); - free(OPL); -} - -/* Optional handlers */ - -static void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset) -{ - OPL->TimerHandler = TimerHandler; - OPL->TimerParam = channelOffset; -} -static void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param) -{ - OPL->IRQHandler = IRQHandler; - OPL->IRQParam = param; -} -static void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param) -{ - OPL->UpdateHandler = UpdateHandler; - OPL->UpdateParam = param; -} - -static int OPLWrite(FM_OPL *OPL,int a,int v) -{ - if( !(a&1) ) - { /* address port */ - OPL->address = v & 0xff; - } - else - { /* data port */ - if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); - OPLWriteReg(OPL,OPL->address,v); - } - return OPL->status>>7; -} - -static unsigned char OPLRead(FM_OPL *OPL,int a) -{ - if( !(a&1) ) - { - /* status port */ - - #if BUILD_Y8950 - - if(OPL->type&OPL_TYPE_ADPCM) /* Y8950 */ - { - return (OPL->status & (OPL->statusmask|0x80)) | (OPL->deltat->PCM_BSY&1); - } - - #endif - if (OPL->st[0]) { - /* Timer A */ - if (OPL->TC[0]) OPL->TC[0]--; - else { - OPL->TC[0]=OPL->T[0]*20; - OPL_STATUS_SET(OPL,0x40); - } - } - if (OPL->st[1]) { - /* Timer B */ - if (OPL->TC[1]) OPL->TC[1]--; - else { - OPL->TC[1]=OPL->T[1]*20; - OPL_STATUS_SET(OPL,0x20); - } - } - return OPL->status & (OPL->statusmask|0x80); - } - -#if BUILD_Y8950 - /* data port */ - switch(OPL->address) - { - case 0x05: /* KeyBoard IN */ - if(OPL->type&OPL_TYPE_KEYBOARD) - { - if(OPL->keyboardhandler_r) - return OPL->keyboardhandler_r(OPL->keyboard_param); - else - logerror("Y8950: read unmapped KEYBOARD port\n"); - } - return 0; - - case 0x0f: /* ADPCM-DATA */ - if(OPL->type&OPL_TYPE_ADPCM) - { - UINT8 val; - - val = YM_DELTAT_ADPCM_Read(OPL->deltat); - /*logerror("Y8950: read ADPCM value read=%02x\n",val);*/ - return val; - } - return 0; - - case 0x19: /* I/O DATA */ - if(OPL->type&OPL_TYPE_IO) - { - if(OPL->porthandler_r) - return OPL->porthandler_r(OPL->port_param); - else - logerror("Y8950:read unmapped I/O port\n"); - } - return 0; - case 0x1a: /* PCM-DATA */ - if(OPL->type&OPL_TYPE_ADPCM) - { - logerror("Y8950 A/D convertion is accessed but not implemented !\n"); - return 0x80; /* 2's complement PCM data - result from A/D convertion */ - } - return 0; - } -#endif - - return 0xff; -} - -/* CSM Key Controll */ -INLINE void CSMKeyControll(OPL_CH *CH) -{ - FM_KEYON (&CH->SLOT[SLOT1], 4); - FM_KEYON (&CH->SLOT[SLOT2], 4); - - /* The key off should happen exactly one sample later - not implemented correctly yet */ - - FM_KEYOFF(&CH->SLOT[SLOT1], ~4); - FM_KEYOFF(&CH->SLOT[SLOT2], ~4); -} - - -static int OPLTimerOver(FM_OPL *OPL,int c) -{ - if( c ) - { /* Timer B */ - OPL_STATUS_SET(OPL,0x20); - } - else - { /* Timer A */ - OPL_STATUS_SET(OPL,0x40); - /* CSM mode key,TL controll */ - if( OPL->mode & 0x80 ) - { /* CSM mode total level latch and auto key on */ - int ch; - if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); - for(ch=0; ch<9; ch++) - CSMKeyControll( &OPL->P_CH[ch] ); - } - } - /* reload timer */ -// if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase); - return OPL->status>>7; -} - - -#define MAX_OPL_CHIPS 2 - - -#if (BUILD_YM3812) - -static FM_OPL *OPL_YM3812[MAX_OPL_CHIPS]; /* array of pointers to the YM3812's */ -static int YM3812NumChips = 0; /* number of chips */ - -int YM3812Init(int num, int clock, int rate) -{ - int i; - - if (YM3812NumChips) - return -1; /* duplicate init. */ - - YM3812NumChips = num; - - for (i = 0;i < YM3812NumChips; i++) - { - /* emulator create */ - OPL_YM3812[i] = OPLCreate(OPL_TYPE_YM3812,clock,rate); - if(OPL_YM3812[i] == NULL) - { - /* it's really bad - we run out of memeory */ - YM3812NumChips = 0; - return -1; - } - /* reset */ - YM3812ResetChip(i); - } - - return 0; -} - -void YM3812Shutdown(void) -{ - int i; - - for (i = 0;i < YM3812NumChips; i++) - { - /* emulator shutdown */ - OPLDestroy(OPL_YM3812[i]); - OPL_YM3812[i] = NULL; - } - YM3812NumChips = 0; -} -void YM3812ResetChip(int which) -{ - OPLResetChip(OPL_YM3812[which]); -} - -int YM3812Write(int which, int a, int v) -{ - return OPLWrite(OPL_YM3812[which], a, v); -} - -unsigned char YM3812Read(int which, int a) -{ - /* YM3812 always returns bit2 and bit1 in HIGH state */ - return OPLRead(OPL_YM3812[which], a) | 0x06 ; -} -int YM3812TimerOver(int which, int c) -{ - return OPLTimerOver(OPL_YM3812[which], c); -} - -void YM3812SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset) -{ - OPLSetTimerHandler(OPL_YM3812[which], TimerHandler, channelOffset); -} -void YM3812SetIRQHandler(int which,OPL_IRQHANDLER IRQHandler,int param) -{ - OPLSetIRQHandler(OPL_YM3812[which], IRQHandler, param); -} -void YM3812SetUpdateHandler(int which,OPL_UPDATEHANDLER UpdateHandler,int param) -{ - OPLSetUpdateHandler(OPL_YM3812[which], UpdateHandler, param); -} - - -/* -** Generate samples for one of the YM3812's -** -** 'which' is the virtual YM3812 number -** '*buffer' is the output buffer pointer -** 'length' is the number of samples that should be generated -*/ -void YM3812UpdateOne(int which, INT16 *buffer, int length) -{ - FM_OPL *OPL = OPL_YM3812[which]; - UINT8 rhythm = OPL->rhythm&0x20; - OPLSAMPLE *buf = buffer; - int i; - - if( (void *)OPL != cur_chip ){ - cur_chip = (void *)OPL; - /* rhythm slots */ - SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1]; - SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2]; - SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1]; - SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2]; - } - for( i=0; i < length ; i++ ) - { - int lt; - - output[0] = 0; - - advance_lfo(OPL); - - /* FM part */ - OPL_CALC_CH(&OPL->P_CH[0]); - OPL_CALC_CH(&OPL->P_CH[1]); - OPL_CALC_CH(&OPL->P_CH[2]); - OPL_CALC_CH(&OPL->P_CH[3]); - OPL_CALC_CH(&OPL->P_CH[4]); - OPL_CALC_CH(&OPL->P_CH[5]); - - if(!rhythm) - { - OPL_CALC_CH(&OPL->P_CH[6]); - OPL_CALC_CH(&OPL->P_CH[7]); - OPL_CALC_CH(&OPL->P_CH[8]); - } - else /* Rhythm part */ - { - OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 ); - } - - lt = output[0]; - - lt >>= FINAL_SH; - - /* limit check */ - lt = limit( lt , MAXOUT, MINOUT ); - - #ifdef SAVE_SAMPLE - if (which==0) - { - SAVE_ALL_CHANNELS - } - #endif - - /* store to sound buffer */ - buf[i] = lt; - - advance(OPL); - } - -} -#endif /* BUILD_YM3812 */ - - - -#if (BUILD_YM3526) - -static FM_OPL *OPL_YM3526[MAX_OPL_CHIPS]; /* array of pointers to the YM3526's */ -static int YM3526NumChips = 0; /* number of chips */ - -int YM3526Init(int num, int clock, int rate) -{ - int i; - - if (YM3526NumChips) - return -1; /* duplicate init. */ - - YM3526NumChips = num; - - for (i = 0;i < YM3526NumChips; i++) - { - /* emulator create */ - OPL_YM3526[i] = OPLCreate(OPL_TYPE_YM3526,clock,rate); - if(OPL_YM3526[i] == NULL) - { - /* it's really bad - we run out of memeory */ - YM3526NumChips = 0; - return -1; - } - /* reset */ - YM3526ResetChip(i); - } - - return 0; -} - -void YM3526Shutdown(void) -{ - int i; - - for (i = 0;i < YM3526NumChips; i++) - { - /* emulator shutdown */ - OPLDestroy(OPL_YM3526[i]); - OPL_YM3526[i] = NULL; - } - YM3526NumChips = 0; -} -void YM3526ResetChip(int which) -{ - OPLResetChip(OPL_YM3526[which]); -} - -int YM3526Write(int which, int a, int v) -{ - return OPLWrite(OPL_YM3526[which], a, v); -} - -unsigned char YM3526Read(int which, int a) -{ - /* YM3526 always returns bit2 and bit1 in HIGH state */ - return OPLRead(OPL_YM3526[which], a) | 0x06 ; -} -int YM3526TimerOver(int which, int c) -{ - return OPLTimerOver(OPL_YM3526[which], c); -} - -void YM3526SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset) -{ - OPLSetTimerHandler(OPL_YM3526[which], TimerHandler, channelOffset); -} -void YM3526SetIRQHandler(int which,OPL_IRQHANDLER IRQHandler,int param) -{ - OPLSetIRQHandler(OPL_YM3526[which], IRQHandler, param); -} -void YM3526SetUpdateHandler(int which,OPL_UPDATEHANDLER UpdateHandler,int param) -{ - OPLSetUpdateHandler(OPL_YM3526[which], UpdateHandler, param); -} - - -/* -** Generate samples for one of the YM3526's -** -** 'which' is the virtual YM3526 number -** '*buffer' is the output buffer pointer -** 'length' is the number of samples that should be generated -*/ -void YM3526UpdateOne(int which, INT16 *buffer, int length) -{ - FM_OPL *OPL = OPL_YM3526[which]; - UINT8 rhythm = OPL->rhythm&0x20; - OPLSAMPLE *buf = buffer; - int i; - - if( (void *)OPL != cur_chip ){ - cur_chip = (void *)OPL; - /* rhythm slots */ - SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1]; - SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2]; - SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1]; - SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2]; - } - for( i=0; i < length ; i++ ) - { - int lt; - - output[0] = 0; - - advance_lfo(OPL); - - /* FM part */ - OPL_CALC_CH(&OPL->P_CH[0]); - OPL_CALC_CH(&OPL->P_CH[1]); - OPL_CALC_CH(&OPL->P_CH[2]); - OPL_CALC_CH(&OPL->P_CH[3]); - OPL_CALC_CH(&OPL->P_CH[4]); - OPL_CALC_CH(&OPL->P_CH[5]); - - if(!rhythm) - { - OPL_CALC_CH(&OPL->P_CH[6]); - OPL_CALC_CH(&OPL->P_CH[7]); - OPL_CALC_CH(&OPL->P_CH[8]); - } - else /* Rhythm part */ - { - OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 ); - } - - lt = output[0]; - - lt >>= FINAL_SH; - - /* limit check */ - lt = limit( lt , MAXOUT, MINOUT ); - - #ifdef SAVE_SAMPLE - if (which==0) - { - SAVE_ALL_CHANNELS - } - #endif - - /* store to sound buffer */ - buf[i] = lt; - - advance(OPL); - } - -} -#endif /* BUILD_YM3526 */ - - - - -#if BUILD_Y8950 - -static FM_OPL *OPL_Y8950[MAX_OPL_CHIPS]; /* array of pointers to the Y8950's */ -static int Y8950NumChips = 0; /* number of chips */ - -static void Y8950_deltat_status_set(UINT8 which, UINT8 changebits) -{ - OPL_STATUS_SET(OPL_Y8950[which], changebits); -} -static void Y8950_deltat_status_reset(UINT8 which, UINT8 changebits) -{ - OPL_STATUS_RESET(OPL_Y8950[which], changebits); -} - -int Y8950Init(int num, int clock, int rate) -{ - int i; - - if (Y8950NumChips) - return -1; /* duplicate init. */ - - Y8950NumChips = num; - - for (i = 0;i < Y8950NumChips; i++) - { - /* emulator create */ - OPL_Y8950[i] = OPLCreate(OPL_TYPE_Y8950,clock,rate); - if(OPL_Y8950[i] == NULL) - { - /* it's really bad - we run out of memeory */ - Y8950NumChips = 0; - return -1; - } - OPL_Y8950[i]->deltat->status_set_handler = Y8950_deltat_status_set; - OPL_Y8950[i]->deltat->status_reset_handler = Y8950_deltat_status_reset; - OPL_Y8950[i]->deltat->status_change_which_chip = i; - OPL_Y8950[i]->deltat->status_change_EOS_bit = 0x10; /* status flag: set bit4 on End Of Sample */ - OPL_Y8950[i]->deltat->status_change_BRDY_bit = 0x08; /* status flag: set bit3 on BRDY (End Of: ADPCM analysis/synthesis, memory reading/writing) */ - /* reset */ - Y8950ResetChip(i); - } - - return 0; -} - -void Y8950Shutdown(void) -{ - int i; - - for (i = 0;i < Y8950NumChips; i++) - { - /* emulator shutdown */ - OPLDestroy(OPL_Y8950[i]); - OPL_Y8950[i] = NULL; - } - Y8950NumChips = 0; -} -void Y8950ResetChip(int which) -{ - OPLResetChip(OPL_Y8950[which]); -} - -int Y8950Write(int which, int a, int v) -{ - return OPLWrite(OPL_Y8950[which], a, v); -} - -unsigned char Y8950Read(int which, int a) -{ - return OPLRead(OPL_Y8950[which], a); -} -int Y8950TimerOver(int which, int c) -{ - return OPLTimerOver(OPL_Y8950[which], c); -} - -void Y8950SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset) -{ - OPLSetTimerHandler(OPL_Y8950[which], TimerHandler, channelOffset); -} -void Y8950SetIRQHandler(int which,OPL_IRQHANDLER IRQHandler,int param) -{ - OPLSetIRQHandler(OPL_Y8950[which], IRQHandler, param); -} -void Y8950SetUpdateHandler(int which,OPL_UPDATEHANDLER UpdateHandler,int param) -{ - OPLSetUpdateHandler(OPL_Y8950[which], UpdateHandler, param); -} - -void Y8950SetDeltaTMemory(int which, void * deltat_mem_ptr, int deltat_mem_size ) -{ - FM_OPL *OPL = OPL_Y8950[which]; - OPL->deltat->memory = (UINT8 *)(deltat_mem_ptr); - OPL->deltat->memory_size = deltat_mem_size; -} - -/* -** Generate samples for one of the Y8950's -** -** 'which' is the virtual Y8950 number -** '*buffer' is the output buffer pointer -** 'length' is the number of samples that should be generated -*/ -void Y8950UpdateOne(int which, INT16 *buffer, int length) -{ - int i; - FM_OPL *OPL = OPL_Y8950[which]; - UINT8 rhythm = OPL->rhythm&0x20; - YM_DELTAT *DELTAT = OPL->deltat; - OPLSAMPLE *buf = buffer; - - if( (void *)OPL != cur_chip ){ - cur_chip = (void *)OPL; - /* rhythm slots */ - SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1]; - SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2]; - SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1]; - SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2]; - - } - for( i=0; i < length ; i++ ) - { - int lt; - - output[0] = 0; - output_deltat[0] = 0; - - advance_lfo(OPL); - - /* deltaT ADPCM */ - if( DELTAT->portstate&0x80 ) - YM_DELTAT_ADPCM_CALC(DELTAT); - - /* FM part */ - OPL_CALC_CH(&OPL->P_CH[0]); - OPL_CALC_CH(&OPL->P_CH[1]); - OPL_CALC_CH(&OPL->P_CH[2]); - OPL_CALC_CH(&OPL->P_CH[3]); - OPL_CALC_CH(&OPL->P_CH[4]); - OPL_CALC_CH(&OPL->P_CH[5]); - - if(!rhythm) - { - OPL_CALC_CH(&OPL->P_CH[6]); - OPL_CALC_CH(&OPL->P_CH[7]); - OPL_CALC_CH(&OPL->P_CH[8]); - } - else /* Rhythm part */ - { - OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 ); - } - - lt = output[0] + (output_deltat[0]>>11); - - lt >>= FINAL_SH; - - /* limit check */ - lt = limit( lt , MAXOUT, MINOUT ); - - #ifdef SAVE_SAMPLE - if (which==0) - { - SAVE_ALL_CHANNELS - } - #endif - - /* store to sound buffer */ - buf[i] = lt; - - advance(OPL); - } - -} - -void Y8950SetPortHandler(int which,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param) -{ - FM_OPL *OPL = OPL_Y8950[which]; - OPL->porthandler_w = PortHandler_w; - OPL->porthandler_r = PortHandler_r; - OPL->port_param = param; -} - -void Y8950SetKeyboardHandler(int which,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param) -{ - FM_OPL *OPL = OPL_Y8950[which]; - OPL->keyboardhandler_w = KeyboardHandler_w; - OPL->keyboardhandler_r = KeyboardHandler_r; - OPL->keyboard_param = param; -} - -#endif - +/* +** +** File: fmopl.c - software implementation of FM sound generator +** types OPL and OPL2 +** +** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmulator development +** (c) 2002 Jarek Burczynski +** +** Version 0.58 +** + +Revision History: + +03-24-2002 Jarek Burczynski (thanks to Dox for the YM3812 chip) + + Complete rewrite (all verified on real YM3812): + + - corrected sin_tab and tl_tab data + - corrected operator output calculations + - corrected waveform_select_enable register; + simply: ignore all writes to waveform_select register when + waveform_select_enable == 0 and do not change the waveform previously selected. + - corrected KSR handling + - corrected Envelope Generator: attack shape, Sustain mode and + Percussive/Non-percussive modes handling + - Envelope Generator rates are two times slower now + - LFO amplitude (tremolo) and phase modulation (vibrato) + - rhythm sounds phase generation + - white noise generator (big thanks to Olivier Galibert for mentioning Berlekamp-Massey algorithm) + - corrected key on/off handling (the 'key' signal is ORed from three sources: FM, rhythm and CSM) + - funky details (like ignoring output of operator 1 in BD rhythm sound when connect == 1) + +12-28-2001 Acho A. Tang + - reflected Delta-T EOS status on Y8950 status port. + - fixed subscription range of attack/decay tables + + + + To do: + add delay before key off in CSM mode (see CSMKeyControll) + verify volume of the FM part on the Y8950 +*/ + +#include +#include +#include +#include +#include +//#include "driver.h" /* use M.A.M.E. */ +#include "fmopl.h" + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + + + + + +/* output final shift */ +#if (OPL_SAMPLE_BITS==16) + #define FINAL_SH (0) + #define MAXOUT (+32767) + #define MINOUT (-32768) +#else + #define FINAL_SH (8) + #define MAXOUT (+127) + #define MINOUT (-128) +#endif + + +#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ +#define ENV_SH 16 /* 16.16 fixed point (envelope calculations) */ +#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */ +#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */ + +#define FREQ_MASK ((1<>8)&0xff,sample[0]); \ + } + #else /*save to STEREO file */ + #define SAVE_ALL_CHANNELS \ + { signed int pom = lt; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + pom = rt; \ + fputc((unsigned short)pom&0xff,sample[0]); \ + fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ + } + #endif +#endif + +/* #define LOG_CYM_FILE */ +#ifdef LOG_CYM_FILE + FILE * cymfile = NULL; +#endif + + + +/* mapping of register number (offset) to slot number used by the emulator */ +static const int slot_array[32]= +{ + 0, 2, 4, 1, 3, 5,-1,-1, + 6, 8,10, 7, 9,11,-1,-1, + 12,14,16,13,15,17,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1 +}; + +/* key scale level */ +/* table is 3dB/octave , DV converts this into 6dB/octave */ +/* 0.09375 is bit 0 weight expressed in the 'decibel' scale */ +#define DV (0.09375/2.0) +static const UINT32 ksl_tab[8*16]= +{ + /* OCT 0 */ + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + /* OCT 1 */ + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV, + 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV, + /* OCT 2 */ + 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV, + 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV, + 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV, + /* OCT 3 */ + 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV, + 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV, + 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV, + 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV, + /* OCT 4 */ + 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV, + 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV, + 9.000/DV, 9.750/DV,10.125/DV,10.500/DV, + 10.875/DV,11.250/DV,11.625/DV,12.000/DV, + /* OCT 5 */ + 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV, + 9.000/DV,10.125/DV,10.875/DV,11.625/DV, + 12.000/DV,12.750/DV,13.125/DV,13.500/DV, + 13.875/DV,14.250/DV,14.625/DV,15.000/DV, + /* OCT 6 */ + 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV, + 12.000/DV,13.125/DV,13.875/DV,14.625/DV, + 15.000/DV,15.750/DV,16.125/DV,16.500/DV, + 16.875/DV,17.250/DV,17.625/DV,18.000/DV, + /* OCT 7 */ + 0.000/DV, 9.000/DV,12.000/DV,13.875/DV, + 15.000/DV,16.125/DV,16.875/DV,17.625/DV, + 18.000/DV,18.750/DV,19.125/DV,19.500/DV, + 19.875/DV,20.250/DV,20.625/DV,21.000/DV +}; +#undef DV + +/* sustain lebel table (3dB per step) */ +/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ +#define SC(db) (UINT32) ( db * (4.0/ENV_STEP) * (1<>3) + +/* sin waveform table in 'decibel' scale */ +/* four waveforms on OPL2 type chips */ +static unsigned int sin_tab[SIN_LEN * 4]; + + +/* LFO Amplitude Modulation table (verified on real YM3812) + + Length: 210 elements. + + Each of the elements has to be repeated + exactly 64 times (on 64 consecutive samples). + The whole table takes: 64 * 210 = 13440 samples. + + When AM = 1 data is multiplied by 2 + When AM = 0 data is divided by 4 and then multiplied by 2 (loosing precision is important) +*/ + +#define LFO_AM_TAB_ELEMENTS 210 + +static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = { +0,0,0,0,0,0,0, +1,1,1,1, +2,2,2,2, +3,3,3,3, +4,4,4,4, +5,5,5,5, +6,6,6,6, +7,7,7,7, +8,8,8,8, +9,9,9,9, +10,10,10,10, +11,11,11,11, +12,12,12,12, +13,13,13,13, +14,14,14,14, +15,15,15,15, +16,16,16,16, +17,17,17,17, +18,18,18,18, +19,19,19,19, +20,20,20,20, +21,21,21,21, +22,22,22,22, +23,23,23,23, +24,24,24,24, +25,25,25,25, +26,26,26, +25,25,25,25, +24,24,24,24, +23,23,23,23, +22,22,22,22, +21,21,21,21, +20,20,20,20, +19,19,19,19, +18,18,18,18, +17,17,17,17, +16,16,16,16, +15,15,15,15, +14,14,14,14, +13,13,13,13, +12,12,12,12, +11,11,11,11, +10,10,10,10, +9,9,9,9, +8,8,8,8, +7,7,7,7, +6,6,6,6, +5,5,5,5, +4,4,4,4, +3,3,3,3, +2,2,2,2, +1,1,1,1 +}; + +/* LFO Phase Modulation table (verified on real YM3812) */ +static const INT8 lfo_pm_table[8*8*2] = { + +/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */ +0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/ +0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */ +0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/ +1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */ +1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/ +2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */ +1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/ +3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */ +2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/ +4, 2, 0,-2,-4,-2, 0, 2, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */ +2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/ +5, 2, 0,-2,-5,-2, 0, 2, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */ +3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/ +6, 3, 0,-3,-6,-3, 0, 3, /*LFO PM depth = 1*/ + +/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */ +3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/ +7, 3, 0,-3,-7,-3, 0, 3 /*LFO PM depth = 1*/ +}; + + +/* lock level of common table */ +static int num_lock = 0; + +/* work table */ +static void *cur_chip = NULL; /* current chip point */ +OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2; + +static signed int phase_modulation; /* phase modulation input (SLOT 2) */ +static signed int output[1]; + +#if BUILD_Y8950 +static INT32 output_deltat[4]; /* for Y8950 DELTA-T */ +#endif + +static UINT32 LFO_AM; +static INT32 LFO_PM; + + + +/* log output level */ +#define LOG_ERR 3 /* ERROR */ +#define LOG_WAR 2 /* WARNING */ +#define LOG_INF 1 /* INFORMATION */ + +#define LOG_LEVEL LOG_INF + +#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x + + + +INLINE int limit( int val, int max, int min ) { + if ( val > max ) + val = max; + else if ( val < min ) + val = min; + + return val; +} + + + +/* status set and IRQ handling */ +INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag) +{ + /* set status flag */ + OPL->status |= flag; + if(!(OPL->status & 0x80)) + { + if(OPL->status & OPL->statusmask) + { /* IRQ on */ + OPL->status |= 0x80; + /* callback user interrupt handler (IRQ is OFF to ON) */ + if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1); + } + } +} + +/* status reset and IRQ handling */ +INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag) +{ + /* reset status flag */ + OPL->status &=~flag; + if((OPL->status & 0x80)) + { + if (!(OPL->status & OPL->statusmask) ) + { + OPL->status &= 0x7f; + /* callback user interrupt handler (IRQ is ON to OFF) */ + if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0); + } + } +} + +/* IRQ mask set */ +INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag) +{ + OPL->statusmask = flag; + /* IRQ handling check */ + OPL_STATUS_SET(OPL,0); + OPL_STATUS_RESET(OPL,0); +} + + +/* advance LFO to next sample */ +INLINE void advance_lfo(FM_OPL *OPL) +{ + UINT8 tmp; + + /* LFO */ + OPL->lfo_am_cnt += OPL->lfo_am_inc; + if (OPL->lfo_am_cnt >= (LFO_AM_TAB_ELEMENTS<lfo_am_cnt -= (LFO_AM_TAB_ELEMENTS<lfo_am_cnt >> LFO_SH ]; + + if (OPL->lfo_am_depth) + LFO_AM = (tmp) * 2; + else + LFO_AM = (tmp>>2) * 2; + + OPL->lfo_pm_cnt += OPL->lfo_pm_inc; + LFO_PM = ( (OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range; +} + +/* advance to next sample */ +INLINE void advance(FM_OPL *OPL) +{ + OPL_CH *CH; + OPL_SLOT *SLOT; + int i; + + + for (i=0; i<9*2; i++) + { + CH = &OPL->P_CH[i/2]; + SLOT = &CH->SLOT[i&1]; + + /* Envelope Generator */ + switch(SLOT->state) + { + case EG_ATT: /* attack phase */ + { + INT32 step = SLOT->volume; + + SLOT->volume -= SLOT->delta_ar; + step = (step>>ENV_SH) - (((UINT32)SLOT->volume)>>ENV_SH); /* number of levels passed since last time */ + if (step > 0) + { + INT32 tmp_volume = SLOT->volume + (step<>4) & ~ENV_MASK); + if (tmp_volume <= MIN_ATT_INDEX) + break; + step--; + }while(step); + SLOT->volume = tmp_volume; + } + + if (SLOT->volume <= MIN_ATT_INDEX) + { + if (SLOT->volume < 0) + SLOT->volume = 0; /* this is not quite correct (checked) */ + + SLOT->state = EG_DEC; + } + } + break; + + case EG_DEC: /* decay phase */ + + if ( (SLOT->volume += SLOT->delta_dr) >= SLOT->sl ) + { + SLOT->volume = SLOT->sl; /* this is not quite correct (checked) */ + SLOT->state = EG_SUS; + } + break; + + case EG_SUS: /* sustain phase */ + + /* this is important behaviour: + one can change percusive/non-percussive modes on the fly and + the chip will remain in sustain phase - verified on real YM3812 */ + + if(SLOT->eg_type) /* non-percussive mode */ + { + /* do nothing */ + } + else /* percussive mode */ + { + /* during sustain phase chip adds Release Rate (in percussive mode) */ + + if ( (SLOT->volume += SLOT->delta_rr) > MAX_ATT_INDEX ) + { + SLOT->volume = MAX_ATT_INDEX; + } + /* else do nothing in sustain phase */ + } + break; + + case EG_REL: /* release phase */ + if ( (SLOT->volume += SLOT->delta_rr) > MAX_ATT_INDEX ) + { + SLOT->volume = MAX_ATT_INDEX; + SLOT->state = EG_OFF; + } + break; + + default: + break; + } + + /* Phase Generator */ + if(SLOT->vib) + { + UINT8 block; + unsigned int block_fnum = CH->block_fnum; + + unsigned int fnum_lfo = (block_fnum&0x0380) >> 7; + + signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + 16*fnum_lfo ]; + + if (lfo_fn_table_index_offset) /* LFO phase modulation active */ + { + block_fnum += lfo_fn_table_index_offset; + block = (block_fnum&0x1c00) >> 10; + SLOT->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * SLOT->mul;//ok + } + else /* LFO phase modulation = zero */ + { + SLOT->Cnt += SLOT->Incr; + } + } + else /* LFO phase modulation disabled for this operator */ + { + SLOT->Cnt += SLOT->Incr; + } + } + + /* The Noise Generator of the YM3812 is 23-bit shift register. + * Period is equal to 2^23-2 samples. + * Register works at sampling frequency of the chip, so output + * can change on every sample. + * + * Output of the register and input to the bit 22 is: + * bit0 XOR bit14 XOR bit15 XOR bit22 + * + * Simply use bit 22 as the noise output. + */ + + OPL->noise_p += OPL->noise_f; + i = OPL->noise_p >> FREQ_SH; /* number of events (shifts of the shift register) */ + OPL->noise_p &= FREQ_MASK; + while (i) + { + UINT32 j; + j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1; + OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1); + i--; + } +} + + +INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm) +{ + UINT32 p; + + p = (env<<3) + sin_tab[ ( ((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK ]; + + if (p >= TL_TAB_LEN) + return 0; + return tl_tab[p]; +} + +INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm) +{ + UINT32 p; + INT32 i; + + i = (phase & ~FREQ_MASK) + pm; + +/*logerror("i=%08x (i>>16)&511=%8i phase=%i [pm=%08x] ",i, (i>>16)&511, phase>>FREQ_SH, pm);*/ + + p = (env<<3) + sin_tab[ (i>>FREQ_SH) & SIN_MASK]; + +/*logerror("(p&255=%i p>>8=%i) out= %i\n", p&255,p>>8, tl_tab[p&255]>>(p>>8) );*/ + + if (p >= TL_TAB_LEN) + return 0; + return tl_tab[p]; +} + + +#define volume_calc(OP) ((OP)->TLL + (((UINT32)(OP)->volume)>>ENV_SH) + (LFO_AM & (OP)->AMmask)) + +/* calculate output */ +INLINE void OPL_CALC_CH( OPL_CH *CH ) +{ + OPL_SLOT *SLOT; + unsigned int env; + signed int out; + + phase_modulation = 0; + + /* SLOT 1 */ + SLOT = &CH->SLOT[SLOT1]; + env = volume_calc(SLOT); + out = CH->op1_out[0] + CH->op1_out[1]; + CH->op1_out[0] = CH->op1_out[1]; + *CH->connect1 += CH->op1_out[0]; + CH->op1_out[1] = 0; + if( env < ENV_QUIET ) + CH->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB) ); + + /* SLOT 2 */ + SLOT++; + env = volume_calc(SLOT); + if( env < ENV_QUIET ) + output[0] += op_calc(SLOT->Cnt, env, phase_modulation); +} + +/* + operators used in the rhythm sounds generation process: + + Envelope Generator: + +channel operator register number Bass High Snare Tom Top +/ slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal + 6 / 0 12 50 70 90 f0 + + 6 / 1 15 53 73 93 f3 + + 7 / 0 13 51 71 91 f1 + + 7 / 1 16 54 74 94 f4 + + 8 / 0 14 52 72 92 f2 + + 8 / 1 17 55 75 95 f5 + + + Phase Generator: + +channel operator register number Bass High Snare Tom Top +/ slot number MULTIPLE Drum Hat Drum Tom Cymbal + 6 / 0 12 30 + + 6 / 1 15 33 + + 7 / 0 13 31 + + + + 7 / 1 16 34 ----- n o t u s e d ----- + 8 / 0 14 32 + + 8 / 1 17 35 + + + +channel operator register number Bass High Snare Tom Top +number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal + 6 12,15 B6 A6 + + + 7 13,16 B7 A7 + + + + + 8 14,17 B8 A8 + + + + +*/ + +/* calculate rhythm */ + +INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise ) +{ + OPL_SLOT *SLOT; + signed int out; + unsigned int env; + + + /* Bass Drum (verified on real YM3812): + - depends on the channel 6 'connect' register: + when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out) + when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored + - output sample always is multiplied by 2 + */ + + phase_modulation = 0; + /* SLOT 1 */ + SLOT = &CH[6].SLOT[SLOT1]; + env = volume_calc(SLOT); + { + out = CH[6].op1_out[0] + CH[6].op1_out[1]; + CH[6].op1_out[0] = CH[6].op1_out[1]; + + if (!CH[6].CON) + phase_modulation = CH[6].op1_out[0]; + //else ignore output of operator 1 + + CH[6].op1_out[1] = 0; + if( env < ENV_QUIET ) + CH[6].op1_out[1] = op_calc1(SLOT->Cnt, env, (out<Cnt, env, phase_modulation) * 2; + + + /* Phase generation is based on: */ + // HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) + // SD (16) channel 7->slot 1 + // TOM (14) channel 8->slot 1 + // TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) + + /* Envelope generation based on: */ + // HH channel 7->slot1 + // SD channel 7->slot2 + // TOM channel 8->slot1 + // TOP channel 8->slot2 + + + /* The following formulas can be well optimized. + I leave them in direct form for now (in case I've missed something). + */ + + /* High Hat (verified on real YM3812) */ + env = volume_calc(SLOT7_1); + if( env < ENV_QUIET ) + { + + /* high hat phase generation: + phase = d0 or 234 (based on frequency only) + phase = 34 or 2d0 (based on noise) + */ + + /* base frequency derived from operator 1 in channel 7 */ + unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1; + unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1; + unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1; + + unsigned char res1 = (bit2 ^ bit7) | bit3; + + /* when res1 = 0 phase = 0x000 | 0xd0; */ + /* when res1 = 1 phase = 0x200 | (0xd0>>2); */ + UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0; + + /* enable gate based on frequency of operator 2 in channel 8 */ + unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1; + unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1; + + unsigned char res2 = (bit3e ^ bit5e); + + /* when res2 = 0 pass the phase from calculation above (res1); */ + /* when res2 = 1 phase = 0x200 | (0xd0>>2); */ + if (res2) + phase = (0x200|(0xd0>>2)); + + + /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */ + /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */ + if (phase&0x200) + { + if (noise) + phase = 0x200|0xd0; + } + else + /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */ + /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */ + { + if (noise) + phase = 0xd0>>2; + } + + output[0] += op_calc(phase<Cnt>>FREQ_SH)>>8)&1; + + /* when bit8 = 0 phase = 0x100; */ + /* when bit8 = 1 phase = 0x200; */ + UINT32 phase = bit8 ? 0x200 : 0x100; + + /* Noise bit XOR'es phase by 0x100 */ + /* when noisebit = 0 pass the phase from calculation above */ + /* when noisebit = 1 phase ^= 0x100; */ + /* in other words: phase ^= (noisebit<<8); */ + if (noise) + phase ^= 0x100; + + output[0] += op_calc(phase<Cnt, env, 0) * 2; + + /* Top Cymbal (verified on real YM3812) */ + env = volume_calc(SLOT8_2); + if( env < ENV_QUIET ) + { + /* base frequency derived from operator 1 in channel 7 */ + unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1; + unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1; + unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1; + + unsigned char res1 = (bit2 ^ bit7) | bit3; + + /* when res1 = 0 phase = 0x000 | 0x100; */ + /* when res1 = 1 phase = 0x200 | 0x100; */ + UINT32 phase = res1 ? 0x300 : 0x100; + + /* enable gate based on frequency of operator 2 in channel 8 */ + unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1; + unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1; + + unsigned char res2 = (bit3e ^ bit5e); + /* when res2 = 0 pass the phase from calculation above (res1); */ + /* when res2 = 1 phase = 0x200 | 0x100; */ + if (res2) + phase = 0x300; + + output[0] += op_calc(phase<eg_tab[i] = 0; + + for (i = 4;i < 64;i++) + { + rate = OPL->freqbase; /* frequency rate */ + if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */ + rate *= 1 << (i>>2); /* b2-5 : shift bit */ + rate /= /*576*/ 8 * 1024.0; + rate *= (double)(1<eg_tab[16+i] = rate; +#if 0 + logerror("FMOPL.C: Rate %2i %1i Decay [real %11.4f ms][emul %11.4f ms][d=%08x]\n",i>>2, i&3, + ( ((double)(ENV_LEN<rate), + ( ((double)(ENV_LEN<eg_tab[16+i]) * (1000.0 / (double)OPL->rate), OPL->eg_tab[16+i] ); +#endif + } + + for (i = 0; i < 16; i++) + { + OPL->eg_tab[16+64+i] = OPL->eg_tab[16+63]; + } + +#if 0 + for (i = 4; i < 64 ; i++) /* test */ + { + UINT32 vol = 0; + UINT32 vol_step = OPL->eg_tab[16+i]; + int j=0, change_no=0; + int lastchange=-1; + + logerror("FMOPL.C - EG TEST: Rate %2i %1i [d=%08x]\n",i>>2, i&3, vol_step ); + logerror(" -> changes every samples: "); + + while (change_no<16) + { + UINT32 tmp_vol = vol>>ENV_SH; + vol += vol_step; + if (tmp_vol!=(vol>>ENV_SH)) + { + //display the distance (in number of samples) since last level change + logerror("%i ",j-lastchange); + lastchange = j; + change_no++; + } + j++; + } + logerror("\n"); + } +#endif +} + +/* generic table initialize */ +static int init_tables(void) +{ + signed int i,x; + signed int n; + double o,m; + + + for (x=0; x>= 4; /* 12 bits here */ + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + /* 11 bits here (rounded) */ + n <<= 1; /* 12 bits here (as in real chip) */ + tl_tab[ x*2 + 0 ] = n; + tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ]; + + for (i=1; i<12; i++) + { + tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i; + tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ]; + } + #if 0 + logerror("tl %04i", x); + for (i=0; i<12; i++) + logerror(", [%02i] %4i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] ); + logerror("\n"); + #endif + } + /*logerror("FMOPL.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/ + + + for (i=0; i0.0) + o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */ + else + o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */ + + o = o / (ENV_STEP/4); + + n = (int)(2.0*o); + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + + sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); + + /*logerror("FMOPL.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/ + } + + for (i=0; i>1) ]; + + /* waveform 3: /- /- /- /- */ + /* abs(output only first quarter of the sinus waveform) */ + if (i & (1<<(SIN_BITS-2)) ) + sin_tab[3*SIN_LEN+i] = TL_TAB_LEN; + else + sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)]; + + /*logerror("FMOPL.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] ); + logerror("FMOPL.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] ); + logerror("FMOPL.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );*/ + } + /*logerror("FMOPL.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/ + + +#ifdef SAVE_SAMPLE + sample[0]=fopen("sampsum.pcm","wb"); +#endif + + return 1; +} + +static void OPLCloseTable( void ) +{ +#ifdef SAVE_SAMPLE + fclose(sample[0]); +#endif +} + + + +static void OPL_initalize(FM_OPL *OPL) +{ + int i; + + /* frequency base */ +#if 1 + OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate : 0; +#else + OPL->rate = (double)OPL->clock / 72.0; + OPL->freqbase = 1.0; +#endif + + /* Timer base time */ + OPL->TimerBase = 1.0 / ((double)OPL->clock / 72.0 ); + + /* make time tables */ + init_timetables( OPL ); + + /* make fnumber -> increment counter table */ + for( i=0 ; i < 1024 ; i++ ) + { + /* opn phase increment counter = 20bit */ + OPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */ +#if 0 + logerror("FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\n", + i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 ); +#endif + } + +#if 0 + for( i=0 ; i < 16 ; i++ ) + { + logerror("FMOPL.C: sl_tab[%i] = %08x\n", + i, sl_tab[i] ); + } + for( i=0 ; i < 8 ; i++ ) + { + int j; + logerror("FMOPL.C: ksl_tab[oct=%2i] =",i); + for (j=0; j<16; j++) + { + logerror("%08x ", ksl_tab[i*16+j] ); + } + logerror("\n"); + } +#endif + + + /* Amplitude modulation: 26 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */ + /* In our LFO_AM_TABLE one entry lasts for 64 samples */ + OPL->lfo_am_inc = (1.0 / 64.0 ) * (1<freqbase; + + /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */ + OPL->lfo_pm_inc = (1.0 / 1024.0) * (1<freqbase; + + /*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/ + + /* Noise generator: a step takes 1 sample */ + OPL->noise_f = (1.0 / 1.0) * (1<freqbase; +} + +INLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set) +{ + if( !SLOT->key ) + { + /* restart Phase Generator */ + SLOT->Cnt = 0; + /* phase -> Attack */ + SLOT->state = EG_ATT; + } + SLOT->key |= key_set; +} + +INLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr) +{ + if( SLOT->key ) + { + SLOT->key &= key_clr; + + if( !SLOT->key ) + { + /* phase -> Release */ + if (SLOT->state>EG_REL) + SLOT->state = EG_REL; + } + } +} + +/* update phase increment counter of operator (also update the EG rates if necessary) */ +INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT) +{ + int ksr; + + /* (frequency) phase increment counter */ + SLOT->Incr = CH->fc * SLOT->mul; + ksr = CH->kcode >> SLOT->KSR; + + if( SLOT->ksr != ksr ) + { + SLOT->ksr = ksr; + + /* calculate envelope generator rates */ + if ((SLOT->ARval + SLOT->ksr) < 16+60) + SLOT->delta_ar = SLOT->AR[ SLOT->ksr ]; + else + SLOT->delta_ar = MAX_ATT_INDEX+1; + SLOT->delta_dr = SLOT->DR[ SLOT->ksr ]; + SLOT->delta_rr = SLOT->RR[ SLOT->ksr ]; + } +} + +/* set multi,am,vib,EG-TYP,KSR,mul */ +INLINE void set_mul(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + + SLOT->mul = mul_tab[v&0x0f]; + SLOT->KSR = (v&0x10) ? 0 : 2; + SLOT->eg_type = (v&0x20); + SLOT->vib = (v&0x40); + SLOT->AMmask = (v&0x80) ? ~0 : 0; + CALC_FCSLOT(CH,SLOT); +} + +/* set ksl & tl */ +INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + int ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */ + + SLOT->ksl = ksl ? 3-ksl : 31; + SLOT->TL = (v&0x3f)<<(ENV_BITS-7); /* 7 bits TL (bit 6 = always 0) */ + + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); +} + +/* set attack rate & decay rate */ +INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + int DRval = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; + + SLOT->ARval = (v>>4) ? 16 + ((v>>4) <<2) : 0; + SLOT->AR = &OPL->eg_tab[ SLOT->ARval ]; + + if ((SLOT->ARval + SLOT->ksr) < 16+60) + SLOT->delta_ar = SLOT->AR[ SLOT->ksr ]; + else + SLOT->delta_ar = MAX_ATT_INDEX+1; + SLOT->DR = &OPL->eg_tab[DRval]; + SLOT->delta_dr = SLOT->DR[ SLOT->ksr ]; +} + +/* set sustain level & release rate */ +INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + int RRval = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; + + SLOT->sl = sl_tab[ v>>4 ]; + + SLOT->RR = &OPL->eg_tab[RRval]; + SLOT->delta_rr = SLOT->RR[ SLOT->ksr ]; +} + + +/* write a value v to register r on OPL chip */ +static void OPLWriteReg(FM_OPL *OPL, int r, int v) +{ + OPL_CH *CH; + int slot; + int block_fnum; + + + /* adjust bus to 8 bits */ + r &= 0xff; + v &= 0xff; + +#ifdef LOG_CYM_FILE + if ((cymfile) && (r!=0) ) + { + fputc( (unsigned char)r, cymfile ); + fputc( (unsigned char)v, cymfile ); + } +#endif + + + switch(r&0xe0) + { + case 0x00: /* 00-1f:control */ + switch(r&0x1f) + { + case 0x01: /* waveform select enable */ + if(OPL->type&OPL_TYPE_WAVESEL) + { + OPL->wavesel = v&0x20; + /* do not change the waveform previously selected */ + } + break; + case 0x02: /* Timer 1 */ + OPL->T[0] = (256-v)*4; + break; + case 0x03: /* Timer 2 */ + OPL->T[1] = (256-v)*16; + break; + case 0x04: /* IRQ clear / mask and Timer enable */ + if(v&0x80) + { /* IRQ flag clear */ + OPL_STATUS_RESET(OPL,0x7f); + } + else + { /* set IRQ mask ,timer enable*/ + UINT8 st1 = v&1; + UINT8 st2 = (v>>1)&1; + /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */ + OPL_STATUS_RESET(OPL,v&0x78); + OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01); + /* timer 2 */ + if(OPL->st[1] != st2) + { + double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0; + OPL->st[1] = st2; + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval); + } + /* timer 1 */ + if(OPL->st[0] != st1) + { + double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0; + OPL->st[0] = st1; + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval); + } + } + break; +#if BUILD_Y8950 + case 0x06: /* Key Board OUT */ + if(OPL->type&OPL_TYPE_KEYBOARD) + { + if(OPL->keyboardhandler_w) + OPL->keyboardhandler_w(OPL->keyboard_param,v); + else + LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n")); + } + break; + case 0x07: /* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */ + if(OPL->type&OPL_TYPE_ADPCM) + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); + break; + case 0x08: /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */ + OPL->mode = v; + v&=0x1f; /* for DELTA-T unit */ + case 0x09: /* START ADD */ + case 0x0a: + case 0x0b: /* STOP ADD */ + case 0x0c: + case 0x0d: /* PRESCALE */ + case 0x0e: + case 0x0f: /* ADPCM data */ + case 0x10: /* DELTA-N */ + case 0x11: /* DELTA-N */ + case 0x12: /* EG-CTRL */ + if(OPL->type&OPL_TYPE_ADPCM) + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); + break; +#if 0 + case 0x15: /* DAC data */ + case 0x16: + case 0x17: /* SHIFT */ + break; + case 0x18: /* I/O CTRL (Direction) */ + if(OPL->type&OPL_TYPE_IO) + OPL->portDirection = v&0x0f; + break; + case 0x19: /* I/O DATA */ + if(OPL->type&OPL_TYPE_IO) + { + OPL->portLatch = v; + if(OPL->porthandler_w) + OPL->porthandler_w(OPL->port_param,v&OPL->portDirection); + } + break; + case 0x1a: /* PCM data */ + break; +#endif +#endif + } + break; + case 0x20: /* am ON, vib ON, ksr, eg_type, mul */ + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_mul(OPL,slot,v); + break; + case 0x40: + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_ksl_tl(OPL,slot,v); + break; + case 0x60: + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_ar_dr(OPL,slot,v); + break; + case 0x80: + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_sl_rr(OPL,slot,v); + break; + case 0xa0: + if (r == 0xbd) /* am depth, vibrato depth, r,bd,sd,tom,tc,hh */ + { + OPL->lfo_am_depth = v & 0x80; + OPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0; + + OPL->rhythm = v&0x3f; + + if(OPL->rhythm&0x20) + { + /* BD key on/off */ + if(v&0x10) + { + FM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2); + FM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2); + } + else + { + FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2); + FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2); + } + /* HH key on/off */ + if(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2); + else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2); + /* SD key on/off */ + if(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2); + else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2); + /* TOM key on/off */ + if(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2); + else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2); + /* TOP-CY key on/off */ + if(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2); + else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2); + } + else + { + /* BD key off */ + FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2); + FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2); + /* HH key off */ + FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2); + /* SD key off */ + FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2); + /* TOM key off */ + FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2); + /* TOP-CY off */ + FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2); + } + return; + } + /* keyon,block,fnum */ + if( (r&0x0f) > 8) return; + CH = &OPL->P_CH[r&0x0f]; + if(!(r&0x10)) + { /* a0-a8 */ + block_fnum = (CH->block_fnum&0x1f00) | v; + } + else + { /* b0-b8 */ + block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff); + + if(v&0x20) + { + FM_KEYON (&CH->SLOT[SLOT1], 1); + FM_KEYON (&CH->SLOT[SLOT2], 1); + } + else + { + FM_KEYOFF(&CH->SLOT[SLOT1],~1); + FM_KEYOFF(&CH->SLOT[SLOT2],~1); + } + } + /* update */ + if(CH->block_fnum != block_fnum) + { + UINT8 block = block_fnum >> 10; + + CH->block_fnum = block_fnum; + + CH->ksl_base = ksl_tab[block_fnum>>6]; + CH->fc = OPL->fn_tab[block_fnum&0x03ff] >> (7-block); + + /* BLK 2,1,0 bits -> bits 3,2,1 of kcode */ + CH->kcode = (CH->block_fnum&0x1c00)>>9; + + /* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */ + /* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum */ + /* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */ + if (OPL->mode&0x40) + CH->kcode |= (CH->block_fnum&0x100)>>8; /* notesel == 1 */ + else + CH->kcode |= (CH->block_fnum&0x200)>>9; /* notesel == 0 */ + + /* refresh Total Level in both SLOTs of this channel */ + CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl); + CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl); + + /* refresh frequency counter in both SLOTs of this channel */ + CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); + CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); + } + break; + case 0xc0: + /* FB,C */ + if( (r&0x0f) > 8) return; + CH = &OPL->P_CH[r&0x0f]; + CH->FB = (v>>1)&7 ? ((v>>1)&7) + 7 : 0; + CH->CON = v&1; + CH->connect1 = CH->CON ? &output[0] : &phase_modulation; + break; + case 0xe0: /* waveform select */ + /* simply ignore write to the waveform select register if selecting not enabled in test register */ + if(OPL->wavesel) + { + slot = slot_array[r&0x1f]; + if(slot == -1) return; + CH = &OPL->P_CH[slot/2]; + + CH->SLOT[slot&1].wavetable = &sin_tab[(v&0x03)*SIN_LEN]; + } + break; + } +} + +#ifdef LOG_CYM_FILE +static void cymfile_callback (int n) +{ + if (cymfile) + { + fputc( (unsigned char)0, cymfile ); + } +} +#endif + +/* lock/unlock for common table */ +static int OPL_LockTable(void) +{ + num_lock++; + if(num_lock>1) return 0; + + /* first time */ + + cur_chip = NULL; + /* allocate total level table (128kb space) */ + if( !init_tables() ) + { + num_lock--; + return -1; + } + +#ifdef LOG_CYM_FILE + cymfile = fopen("3812_.cym","wb"); + if (cymfile) + timer_pulse ( TIME_IN_HZ(110), 0, cymfile_callback); /*110 Hz pulse timer*/ + else + logerror("Could not create file 3812_.cym\n"); +#endif + + return 0; +} + +static void OPL_UnLockTable(void) +{ + if(num_lock) num_lock--; + if(num_lock) return; + + /* last time */ + + cur_chip = NULL; + OPLCloseTable(); + +#ifdef LOG_CYM_FILE + fclose (cymfile); + cymfile = NULL; +#endif + +} + +#if (BUILD_YM3812 || BUILD_YM3526) +/*******************************************************************************/ +/* YM3812 local section */ +/*******************************************************************************/ + +/* Generate samples for one of the YM3812's +* +* '*OPL' is pointer to the virtual YM3812 +* '*buffer' is pointer to the sample buffer +* 'length' is the number of samples that should be generated +*/ +void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length) +{ + int i; + OPLSAMPLE *buf = buffer; + UINT8 rhythm = OPL->rhythm&0x20; + + if( (void *)OPL != cur_chip ){ + cur_chip = (void *)OPL; + /* rhythm slots */ + SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1]; + SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2]; + SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1]; + SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2]; + } + for( i=0; i < length ; i++ ) + { + int lt; + + output[0] = 0; + + advance_lfo(OPL); + + /* FM part */ + OPL_CALC_CH(&OPL->P_CH[0]); + OPL_CALC_CH(&OPL->P_CH[1]); + OPL_CALC_CH(&OPL->P_CH[2]); + OPL_CALC_CH(&OPL->P_CH[3]); + OPL_CALC_CH(&OPL->P_CH[4]); + OPL_CALC_CH(&OPL->P_CH[5]); + + if(!rhythm) + { + OPL_CALC_CH(&OPL->P_CH[6]); + OPL_CALC_CH(&OPL->P_CH[7]); + OPL_CALC_CH(&OPL->P_CH[8]); + } + else /* Rhythm part */ + { + OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>22)&1 ); + } + + lt = output[0]; + + lt >>= FINAL_SH; + + /* limit check */ + lt = limit( lt , MAXOUT, MINOUT ); + + #ifdef SAVE_SAMPLE + SAVE_ALL_CHANNELS + #endif + + /* store to sound buffer */ + buf[i] = lt; + + advance(OPL); + + } + +} +#endif /* (BUILD_YM3812 || BUILD_YM3526) */ + +#if BUILD_Y8950 + +void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length) +{ + int i; + OPLSAMPLE *buf = buffer; + UINT8 rhythm = OPL->rhythm&0x20; + YM_DELTAT *DELTAT = OPL->deltat; + + /* setup DELTA-T unit */ + YM_DELTAT_DECODE_PRESET(DELTAT); + + if( (void *)OPL != cur_chip ){ + cur_chip = (void *)OPL; + /* rhythm slots */ + SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1]; + SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2]; + SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1]; + SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2]; + + } + for( i=0; i < length ; i++ ) + { + int lt; + + output[0] = 0; + output_deltat[0] = 0; + + advance_lfo(OPL); + + /* deltaT ADPCM */ + if( DELTAT->portstate ) + YM_DELTAT_ADPCM_CALC(DELTAT); + + /* FM part */ + OPL_CALC_CH(&OPL->P_CH[0]); + OPL_CALC_CH(&OPL->P_CH[1]); + OPL_CALC_CH(&OPL->P_CH[2]); + OPL_CALC_CH(&OPL->P_CH[3]); + OPL_CALC_CH(&OPL->P_CH[4]); + OPL_CALC_CH(&OPL->P_CH[5]); + + if(!rhythm) + { + OPL_CALC_CH(&OPL->P_CH[6]); + OPL_CALC_CH(&OPL->P_CH[7]); + OPL_CALC_CH(&OPL->P_CH[8]); + } + else /* Rhythm part */ + { + OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>22)&1 ); + } + + lt = output[0] + (output_deltat[0]>>11); + + lt >>= FINAL_SH; + + /* limit check */ + lt = limit( lt , MAXOUT, MINOUT ); + + #ifdef SAVE_SAMPLE + SAVE_ALL_CHANNELS + #endif + + /* store to sound buffer */ + buf[i] = lt; + + advance(OPL); + } + + /* deltaT START flag */ + if( !DELTAT->portstate ) + OPL->status &= 0xfe; + + if( DELTAT->eos ) //AT: set bit 4 of OPL status register on EOS + { + DELTAT->eos = 0; + OPL->status |= 0x10; + } +} +#endif + + +void OPLResetChip(FM_OPL *OPL) +{ + int c,s; + int i; + + OPL->noise_rng = 1; /* noise shift register */ + OPL->mode = 0; /* normal mode */ + OPL_STATUS_RESET(OPL,0x7f); + + /* reset with register write */ + OPLWriteReg(OPL,0x01,0); /* wavesel disable */ + OPLWriteReg(OPL,0x02,0); /* Timer1 */ + OPLWriteReg(OPL,0x03,0); /* Timer2 */ + OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */ + for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0); + + /* reset operator parameters */ + for( c = 0 ; c < 9 ; c++ ) + { + OPL_CH *CH = &OPL->P_CH[c]; + for(s = 0 ; s < 2 ; s++ ) + { + /* wave table */ + CH->SLOT[s].wavetable = &sin_tab[0]; + CH->SLOT[s].state = EG_OFF; + CH->SLOT[s].volume = MAX_ATT_INDEX; + } + } +#if BUILD_Y8950 + if(OPL->type&OPL_TYPE_ADPCM) + { + YM_DELTAT *DELTAT = OPL->deltat; + + DELTAT->freqbase = OPL->freqbase; + DELTAT->output_pointer = &output_deltat[0]; + DELTAT->portshift = 5; + DELTAT->output_range = 1<<23; + YM_DELTAT_ADPCM_Reset(DELTAT,0); + } +#endif +} + +/* Create one of virtual YM3812 */ +/* 'clock' is chip clock in Hz */ +/* 'rate' is sampling rate */ +FM_OPL *OPLCreate(int type, int clock, int rate) +{ + union { + char *ptr; + void *ptr_void; + }; + FM_OPL *OPL; + int state_size; + + if (OPL_LockTable() ==-1) return NULL; + + /* calculate OPL state size */ + state_size = sizeof(FM_OPL); + +#if BUILD_Y8950 + if (type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT); +#endif + + /* allocate memory block */ + ptr_void = malloc(state_size); + + if (ptr==NULL) + return NULL; + + /* clear */ + memset(ptr,0,state_size); + + OPL = (FM_OPL *)ptr; + + ptr += sizeof(FM_OPL); + +#if BUILD_Y8950 + if (type&OPL_TYPE_ADPCM) + OPL->deltat = (YM_DELTAT *)ptr; + ptr += sizeof(YM_DELTAT); +#endif + + OPL->type = type; + OPL->clock = clock; + OPL->rate = rate; + + /* init global tables */ + OPL_initalize(OPL); + + /* reset chip */ + OPLResetChip(OPL); + return OPL; +} + +/* Destroy one of virtual YM3812 */ +void OPLDestroy(FM_OPL *OPL) +{ + OPL_UnLockTable(); + free(OPL); +} + +/* Option handlers */ + +void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset) +{ + OPL->TimerHandler = TimerHandler; + OPL->TimerParam = channelOffset; +} +void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param) +{ + OPL->IRQHandler = IRQHandler; + OPL->IRQParam = param; +} +void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param) +{ + OPL->UpdateHandler = UpdateHandler; + OPL->UpdateParam = param; +} + +#if BUILD_Y8950 +void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param) +{ + OPL->porthandler_w = PortHandler_w; + OPL->porthandler_r = PortHandler_r; + OPL->port_param = param; +} + +void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param) +{ + OPL->keyboardhandler_w = KeyboardHandler_w; + OPL->keyboardhandler_r = KeyboardHandler_r; + OPL->keyboard_param = param; +} +#endif + +/* YM3812 I/O interface */ +int OPLWrite(FM_OPL *OPL,int a,int v) +{ + if( !(a&1) ) + { /* address port */ + OPL->address = v & 0xff; + } + else + { /* data port */ + if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); + OPLWriteReg(OPL,OPL->address,v); + } + return OPL->status>>7; +} + +unsigned char OPLRead(FM_OPL *OPL,int a) +{ + if( !(a&1) ) + { + /* YM3812 returns 0x06 (bit2 and bit1 are HIGH) */ + + /* status port */ + return OPL->status & (OPL->statusmask|0x80); + } + +#if BUILD_Y8950 + /* data port */ + switch(OPL->address) + { + case 0x05: /* KeyBoard IN */ + if(OPL->type&OPL_TYPE_KEYBOARD) + { + if(OPL->keyboardhandler_r) + return OPL->keyboardhandler_r(OPL->keyboard_param); + else + LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n")); + } + return 0; +#if 0 + case 0x0f: /* ADPCM-DATA */ + return 0; +#endif + case 0x19: /* I/O DATA */ + if(OPL->type&OPL_TYPE_IO) + { + if(OPL->porthandler_r) + return OPL->porthandler_r(OPL->port_param); + else + LOG(LOG_WAR,("OPL:read unmapped I/O port\n")); + } + return 0; + case 0x1a: /* PCM-DATA */ + return 0; + } +#endif + + return 0xff; +} + +/* CSM Key Controll */ +INLINE void CSMKeyControll(OPL_CH *CH) +{ + FM_KEYON (&CH->SLOT[SLOT1], 4); + FM_KEYON (&CH->SLOT[SLOT2], 4); + + /* The key off should happen exactly one sample later - not implemented correctly yet */ + + FM_KEYOFF(&CH->SLOT[SLOT1], ~4); + FM_KEYOFF(&CH->SLOT[SLOT2], ~4); +} + + +int OPLTimerOver(FM_OPL *OPL,int c) +{ + if( c ) + { /* Timer B */ + OPL_STATUS_SET(OPL,0x20); + } + else + { /* Timer A */ + OPL_STATUS_SET(OPL,0x40); + /* CSM mode key,TL controll */ + if( OPL->mode & 0x80 ) + { /* CSM mode total level latch and auto key on */ + int ch; + if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); + for(ch=0; ch<9; ch++) + CSMKeyControll( &OPL->P_CH[ch] ); + } + } + /* reload timer */ + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase); + return OPL->status>>7; +} diff --git a/src/hardware/fmopl.h b/src/hardware/fmopl.h index 5a4c02d..46c5c15 100644 --- a/src/hardware/fmopl.h +++ b/src/hardware/fmopl.h @@ -1,111 +1,191 @@ -#ifndef __FMOPL_H_ -#define __FMOPL_H_ - -/* --- select emulation chips --- */ -#define BUILD_YM3812 (HAS_YM3812) -#define BUILD_YM3526 (HAS_YM3526) -#define BUILD_Y8950 (HAS_Y8950) - -/* select output bits size of output : 8 or 16 */ -#define OPL_SAMPLE_BITS 16 - -/* compiler dependence */ -#ifndef OSD_CPU_H -#define OSD_CPU_H -typedef unsigned char UINT8; /* unsigned 8bit */ -typedef unsigned short UINT16; /* unsigned 16bit */ -typedef unsigned int UINT32; /* unsigned 32bit */ -typedef signed char INT8; /* signed 8bit */ -typedef signed short INT16; /* signed 16bit */ -typedef signed int INT32; /* signed 32bit */ -#endif - -#if (OPL_SAMPLE_BITS==16) -typedef INT16 OPLSAMPLE; -#endif -#if (OPL_SAMPLE_BITS==8) -typedef INT8 OPLSAMPLE; -#endif - - -typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec); -typedef void (*OPL_IRQHANDLER)(int param,int irq); -typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us); -typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data); -typedef unsigned char (*OPL_PORTHANDLER_R)(int param); - - -#if BUILD_YM3812 - -int YM3812Init(int num, int clock, int rate); -void YM3812Shutdown(void); -void YM3812ResetChip(int which); -int YM3812Write(int which, int a, int v); -unsigned char YM3812Read(int which, int a); -int YM3812TimerOver(int which, int c); -void YM3812UpdateOne(int which, INT16 *buffer, int length); - -void YM3812SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset); -void YM3812SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param); -void YM3812SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param); - -#endif - - -#if BUILD_YM3526 - -/* -** Initialize YM3526 emulator(s). -** -** 'num' is the number of virtual YM3526's to allocate -** 'clock' is the chip clock in Hz -** 'rate' is sampling rate -*/ -int YM3526Init(int num, int clock, int rate); -/* shutdown the YM3526 emulators*/ -void YM3526Shutdown(void); -void YM3526ResetChip(int which); -int YM3526Write(int which, int a, int v); -unsigned char YM3526Read(int which, int a); -int YM3526TimerOver(int which, int c); -/* -** Generate samples for one of the YM3526's -** -** 'which' is the virtual YM3526 number -** '*buffer' is the output buffer pointer -** 'length' is the number of samples that should be generated -*/ -void YM3526UpdateOne(int which, INT16 *buffer, int length); - -void YM3526SetTimerHandler(int which, OPL_TIMERHANDLER TimerHandler, int channelOffset); -void YM3526SetIRQHandler(int which, OPL_IRQHANDLER IRQHandler, int param); -void YM3526SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int param); - -#endif - - -#if BUILD_Y8950 - -#include "ymdeltat.h" - -/* Y8950 port handlers */ -void Y8950SetPortHandler(int which, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, int param); -void Y8950SetKeyboardHandler(int which, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, int param); -void Y8950SetDeltaTMemory(int which, void * deltat_mem_ptr, int deltat_mem_size ); - -int Y8950Init (int num, int clock, int rate); -void Y8950Shutdown (void); -void Y8950ResetChip (int which); -int Y8950Write (int which, int a, int v); -unsigned char Y8950Read (int which, int a); -int Y8950TimerOver (int which, int c); -void Y8950UpdateOne (int which, INT16 *buffer, int length); - -void Y8950SetTimerHandler (int which, OPL_TIMERHANDLER TimerHandler, int channelOffset); -void Y8950SetIRQHandler (int which, OPL_IRQHANDLER IRQHandler, int param); -void Y8950SetUpdateHandler (int which, OPL_UPDATEHANDLER UpdateHandler, int param); - -#endif - - -#endif +#ifndef __FMOPL_H_ +#define __FMOPL_H_ + +/* --- select emulation chips --- */ +#define BUILD_YM3812 (HAS_YM3812) +#define BUILD_YM3526 (HAS_YM3526) +#define BUILD_Y8950 (HAS_Y8950) + +/* --- system optimize --- */ +/* select bit size of output : 8 or 16 */ +#define OPL_SAMPLE_BITS 16 + +/* compiler dependence */ +#ifndef OSD_CPU_H +#define OSD_CPU_H +typedef unsigned char UINT8; /* unsigned 8bit */ +typedef unsigned short UINT16; /* unsigned 16bit */ +typedef unsigned int UINT32; /* unsigned 32bit */ +typedef signed char INT8; /* signed 8bit */ +typedef signed short INT16; /* signed 16bit */ +typedef signed int INT32; /* signed 32bit */ +#endif + +#if (OPL_SAMPLE_BITS==16) +typedef INT16 OPLSAMPLE; +#endif +#if (OPL_SAMPLE_BITS==8) +typedef unsigned char OPLSAMPLE; +#endif + + +#if BUILD_Y8950 +#include "ymdeltat.h" +#endif + +typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec); +typedef void (*OPL_IRQHANDLER)(int param,int irq); +typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us); +typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data); +typedef unsigned char (*OPL_PORTHANDLER_R)(int param); + +/* !!!!! here is private section , do not access there member direct !!!!! */ + +#define OPL_TYPE_WAVESEL 0x01 /* waveform select */ +#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */ +#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */ +#define OPL_TYPE_IO 0x08 /* I/O port */ + +/* Saving is necessary for member of the 'R' mark for suspend/resume */ +/* ---------- OPL slot ---------- */ +typedef struct fm_opl_slot { + const UINT32 *AR; /* attack rate tab :&eg_table[AR<<2]*/ + const UINT32 *DR; /* decay rate tab :&eg_table[DR<<2]*/ + const UINT32 *RR; /* release rate tab:&eg_table[RR<<2]*/ + UINT8 KSR; /* key scale rate */ + UINT8 ARval; /* current AR */ + UINT8 ksl; /* keyscale level */ + UINT8 ksr; /* key scale rate :kcode>>KSR */ + UINT8 mul; /* multiple :ML_TABLE[ML] */ + + /* Phase Generator */ + UINT32 Cnt; /* frequency count */ + UINT32 Incr; /* frequency step */ + + /* Envelope Generator */ + UINT8 eg_type; /* percussive/non-percussive mode */ + UINT8 state; /* phase type */ + UINT32 TL; /* total level :TL << 3 */ + INT32 TLL; /* adjusted now TL */ + INT32 volume; /* envelope counter */ + UINT32 sl; /* sustain level :SL_TABLE[SL] */ + UINT32 delta_ar; /* envelope step for Attack */ + UINT32 delta_dr; /* envelope step for Decay */ + UINT32 delta_rr; /* envelope step for Release */ + + UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */ + + /* LFO */ + UINT32 AMmask; /* LFO Amplitude Modulation enable mask */ + UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/ + + /* waveform select */ + unsigned int *wavetable; +}OPL_SLOT; + +/* ---------- OPL one of channel ---------- */ +typedef struct fm_opl_channel { + OPL_SLOT SLOT[2]; + UINT8 FB; /* feedback shift value */ + INT32 *connect1; /* slot1 output pointer */ + INT32 op1_out[2]; /* slot1 output for feedback */ + + /* phase generator state */ + UINT32 block_fnum; /* block+fnum */ + UINT32 fc; /* Freq. Increment base */ + UINT32 ksl_base; /* KeyScaleLevel Base step */ + UINT8 kcode; /* key code (for key scaling) */ + + UINT8 CON; /* connection (algorithm) type */ +} OPL_CH; + +/* OPL state */ +typedef struct fm_opl_f { + /* FM channel slots */ + OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels */ + + UINT8 rhythm; /* Rhythm mode */ + + UINT32 eg_tab[16+64+16]; /* EG rate table: 16 (dummy) + 64 rates + 16 RKS */ + UINT32 fn_tab[1024]; /* fnumber -> increment counter */ + + /* LFO */ + UINT8 lfo_am_depth; + UINT8 lfo_pm_depth_range; + UINT32 lfo_am_cnt; + UINT32 lfo_am_inc; + UINT32 lfo_pm_cnt; + UINT32 lfo_pm_inc; + + UINT32 noise_rng; /* 23 bit noise shift register */ + UINT32 noise_p; /* current noise 'phase' */ + UINT32 noise_f; /* current noise period */ + + UINT8 wavesel; /* waveform select enable flag */ + + int T[2]; /* timer counters */ + UINT8 st[2]; /* timer enable */ + +#if BUILD_Y8950 + /* Delta-T ADPCM unit (Y8950) */ + + YM_DELTAT *deltat; + + /* Keyboard / I/O interface unit*/ + UINT8 portDirection; + UINT8 portLatch; + OPL_PORTHANDLER_R porthandler_r; + OPL_PORTHANDLER_W porthandler_w; + int port_param; + OPL_PORTHANDLER_R keyboardhandler_r; + OPL_PORTHANDLER_W keyboardhandler_w; + int keyboard_param; +#endif + + /* external event callback handlers */ + OPL_TIMERHANDLER TimerHandler; /* TIMER handler */ + int TimerParam; /* TIMER parameter */ + OPL_IRQHANDLER IRQHandler; /* IRQ handler */ + int IRQParam; /* IRQ parameter */ + OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */ + int UpdateParam; /* stream update parameter */ + + UINT8 type; /* chip type */ + UINT8 address; /* address register */ + UINT8 status; /* status flag */ + UINT8 statusmask; /* status mask */ + UINT8 mode; /* Reg.08 : CSM,notesel,etc. */ + + int clock; /* master clock (Hz) */ + int rate; /* sampling rate (Hz) */ + double freqbase; /* frequency base */ + double TimerBase; /* Timer base time (==sampling time)*/ +} FM_OPL; + + +/* ---------- Generic interface section ---------- */ +#define OPL_TYPE_YM3526 (0) +#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL) +#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO) + +FM_OPL *OPLCreate(int type, int clock, int rate); +void OPLDestroy(FM_OPL *OPL); +void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset); +void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param); +void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param); +/* Y8950 port handlers */ +void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param); +void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param); + +void OPLResetChip(FM_OPL *OPL); +int OPLWrite(FM_OPL *OPL,int a,int v); +unsigned char OPLRead(FM_OPL *OPL,int a); +int OPLTimerOver(FM_OPL *OPL,int c); + + +/* YM3626/YM3812 local section */ +void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length); + +void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length); + +#endif diff --git a/src/hardware/font-switch.h b/src/hardware/font-switch.h new file mode 100644 index 0000000..80a3adf --- /dev/null +++ b/src/hardware/font-switch.h @@ -0,0 +1,2562 @@ +switch (bit_mask) { + case 0: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 1: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 2: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 3: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 4: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 5: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 6: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 7: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 8: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 9: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 10: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 11: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 12: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 13: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 14: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 15: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 16: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 17: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 18: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 19: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 20: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 21: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 22: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 23: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 24: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 25: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 26: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 27: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 28: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 29: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 30: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 31: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 32: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 33: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 34: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 35: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 36: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 37: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 38: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 39: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 40: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 41: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 42: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 43: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 44: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 45: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 46: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 47: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 48: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 49: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 50: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 51: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 52: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 53: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 54: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 55: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 56: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 57: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 58: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 59: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 60: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 61: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 62: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 63: + *(draw+0)=bg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 64: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 65: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 66: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 67: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 68: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 69: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 70: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 71: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 72: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 73: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 74: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 75: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 76: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 77: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 78: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 79: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 80: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 81: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 82: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 83: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 84: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 85: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 86: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 87: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 88: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 89: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 90: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 91: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 92: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 93: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 94: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 95: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 96: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 97: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 98: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 99: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 100: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 101: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 102: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 103: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 104: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 105: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 106: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 107: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 108: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 109: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 110: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 111: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 112: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 113: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 114: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 115: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 116: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 117: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 118: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 119: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 120: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 121: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 122: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 123: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 124: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 125: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 126: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 127: + *(draw+0)=bg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 128: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 129: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 130: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 131: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 132: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 133: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 134: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 135: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 136: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 137: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 138: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 139: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 140: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 141: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 142: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 143: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 144: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 145: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 146: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 147: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 148: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 149: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 150: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 151: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 152: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 153: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 154: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 155: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 156: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 157: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 158: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 159: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 160: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 161: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 162: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 163: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 164: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 165: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 166: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 167: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 168: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 169: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 170: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 171: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 172: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 173: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 174: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 175: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 176: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 177: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 178: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 179: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 180: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 181: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 182: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 183: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 184: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 185: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 186: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 187: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 188: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 189: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 190: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 191: + *(draw+0)=fg; + *(draw+1)=bg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 192: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 193: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 194: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 195: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 196: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 197: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 198: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 199: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 200: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 201: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 202: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 203: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 204: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 205: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 206: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 207: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 208: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 209: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 210: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 211: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 212: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 213: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 214: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 215: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 216: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 217: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 218: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 219: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 220: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 221: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 222: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 223: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=bg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 224: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 225: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 226: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 227: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 228: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 229: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 230: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 231: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 232: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 233: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 234: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 235: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 236: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 237: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 238: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 239: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=bg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 240: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 241: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 242: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 243: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 244: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 245: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 246: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 247: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=bg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 248: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 249: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 250: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 251: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=bg; + *(draw+6)=fg; + *(draw+7)=fg; + break; + case 252: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=bg; + break; + case 253: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=bg; + *(draw+7)=fg; + break; + case 254: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=bg; + break; + case 255: + *(draw+0)=fg; + *(draw+1)=fg; + *(draw+2)=fg; + *(draw+3)=fg; + *(draw+4)=fg; + *(draw+5)=fg; + *(draw+6)=fg; + *(draw+7)=fg; + break; +} diff --git a/src/hardware/gameblaster.cpp b/src/hardware/gameblaster.cpp index 1a892b3..bcddec0 100644 --- a/src/hardware/gameblaster.cpp +++ b/src/hardware/gameblaster.cpp @@ -1,461 +1,256 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "dosbox.h" -#include "inout.h" -#include "mixer.h" -#include "mem.h" -#include "hardware.h" -#include "setup.h" -#include "pic.h" -#include -#include - - -#define LEFT 0x00 -#define RIGHT 0x01 -#define CMS_BUFFER_SIZE 128 -#define CMS_RATE 22050 - - -typedef Bit8u UINT8; -typedef Bit16s INT16; - -/* this structure defines a channel */ -struct saa1099_channel -{ - int frequency; /* frequency (0x00..0xff) */ - int freq_enable; /* frequency enable */ - int noise_enable; /* noise enable */ - int octave; /* octave (0x00..0x07) */ - int amplitude[2]; /* amplitude (0x00..0x0f) */ - int envelope[2]; /* envelope (0x00..0x0f or 0x10 == off) */ - - /* vars to simulate the square wave */ - double counter; - double freq; - int level; -}; - -/* this structure defines a noise channel */ -struct saa1099_noise -{ - /* vars to simulate the noise generator output */ - double counter; - double freq; - int level; /* noise polynomal shifter */ -}; - -/* this structure defines a SAA1099 chip */ -struct SAA1099 -{ - int stream; /* our stream */ - int noise_params[2]; /* noise generators parameters */ - int env_enable[2]; /* envelope generators enable */ - int env_reverse_right[2]; /* envelope reversed for right channel */ - int env_mode[2]; /* envelope generators mode */ - int env_bits[2]; /* non zero = 3 bits resolution */ - int env_clock[2]; /* envelope clock mode (non-zero external) */ - int env_step[2]; /* current envelope step */ - int all_ch_enable; /* all channels enable */ - int sync_state; /* sync all channels */ - int selected_reg; /* selected register */ - struct saa1099_channel channels[6]; /* channels */ - struct saa1099_noise noise[2]; /* noise generators */ -}; - -static UINT8 envelope[8][64] = { - /* zero amplitude */ - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - /* maximum amplitude */ - {15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, - 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, }, - /* single decay */ - {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - /* repetitive decay */ - {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, - 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, - 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, - 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, - /* single triangular */ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, - 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - /* repetitive triangular */ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, - 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, - 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, - /* single attack */ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - /* repetitive attack */ - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 } -}; - - -static int amplitude_lookup[16] = { - 0*32767/16, 1*32767/16, 2*32767/16, 3*32767/16, - 4*32767/16, 5*32767/16, 6*32767/16, 7*32767/16, - 8*32767/16, 9*32767/16, 10*32767/16, 11*32767/16, - 12*32767/16, 13*32767/16, 14*32767/16, 15*32767/16 -}; - -/* global parameters */ -static double sample_rate; -static SAA1099 saa1099[2]; -static MixerChannel * cms_chan; -static Bit16s cms_buffer[2][2][CMS_BUFFER_SIZE]; -static Bit16s * cms_buf_point[4] = { - cms_buffer[0][0],cms_buffer[0][1],cms_buffer[1][0],cms_buffer[1][1] }; - -static Bitu last_command; - - -static void saa1099_envelope(int chip, int ch) -{ - struct SAA1099 *saa = &saa1099[chip]; - if (saa->env_enable[ch]) - { - int step, mode, mask; - mode = saa->env_mode[ch]; - /* step from 0..63 and then loop in steps 32..63 */ - step = saa->env_step[ch] = - ((saa->env_step[ch] + 1) & 0x3f) | (saa->env_step[ch] & 0x20); - - mask = 15; - if (saa->env_bits[ch]) - mask &= ~1; /* 3 bit resolution, mask LSB */ - - saa->channels[ch*3+0].envelope[ LEFT] = - saa->channels[ch*3+1].envelope[ LEFT] = - saa->channels[ch*3+2].envelope[ LEFT] = envelope[mode][step] & mask; - if (saa->env_reverse_right[ch] & 0x01) - { - saa->channels[ch*3+0].envelope[RIGHT] = - saa->channels[ch*3+1].envelope[RIGHT] = - saa->channels[ch*3+2].envelope[RIGHT] = (15 - envelope[mode][step]) & mask; - } - else - { - saa->channels[ch*3+0].envelope[RIGHT] = - saa->channels[ch*3+1].envelope[RIGHT] = - saa->channels[ch*3+2].envelope[RIGHT] = envelope[mode][step] & mask; - } - } - else - { - /* envelope mode off, set all envelope factors to 16 */ - saa->channels[ch*3+0].envelope[ LEFT] = - saa->channels[ch*3+1].envelope[ LEFT] = - saa->channels[ch*3+2].envelope[ LEFT] = - saa->channels[ch*3+0].envelope[RIGHT] = - saa->channels[ch*3+1].envelope[RIGHT] = - saa->channels[ch*3+2].envelope[RIGHT] = 16; - } -} - - -static void saa1099_update(int chip, INT16 **buffer, int length) -{ - struct SAA1099 *saa = &saa1099[chip]; - int j, ch; - - /* if the channels are disabled we're done */ - if (!saa->all_ch_enable) - { - /* init output data */ - memset(buffer[LEFT],0,length*sizeof(INT16)); - memset(buffer[RIGHT],0,length*sizeof(INT16)); - return; - } - - for (ch = 0; ch < 2; ch++) - { - switch (saa->noise_params[ch]) - { - case 0: saa->noise[ch].freq = 31250.0 * 2; break; - case 1: saa->noise[ch].freq = 15625.0 * 2; break; - case 2: saa->noise[ch].freq = 7812.5 * 2; break; - case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break; - } - } - - /* fill all data needed */ - for( j = 0; j < length; j++ ) - { - int output_l = 0, output_r = 0; - - /* for each channel */ - for (ch = 0; ch < 6; ch++) - { - if (saa->channels[ch].freq == 0.0) - saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / - (511.0 - (double)saa->channels[ch].frequency); - - /* check the actual position in the square wave */ - saa->channels[ch].counter -= saa->channels[ch].freq; - while (saa->channels[ch].counter < 0) - { - /* calculate new frequency now after the half wave is updated */ - saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / - (511.0 - (double)saa->channels[ch].frequency); - - saa->channels[ch].counter += sample_rate; - saa->channels[ch].level ^= 1; - - /* eventually clock the envelope counters */ - if (ch == 1 && saa->env_clock[0] == 0) - saa1099_envelope(chip, 0); - if (ch == 4 && saa->env_clock[1] == 0) - saa1099_envelope(chip, 1); - } - - /* if the noise is enabled */ - if (saa->channels[ch].noise_enable) - { - /* if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) */ - if (saa->noise[ch/3].level & 1) - { - /* subtract to avoid overflows, also use only half amplitude */ - output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16 / 2; - output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16 / 2; - } - } - - /* if the square wave is enabled */ - if (saa->channels[ch].freq_enable) - { - /* if the channel level is high */ - if (saa->channels[ch].level & 1) - { - output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16; - output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16; - } - } - } - - for (ch = 0; ch < 2; ch++) - { - /* check the actual position in noise generator */ - saa->noise[ch].counter -= saa->noise[ch].freq; - while (saa->noise[ch].counter < 0) - { - saa->noise[ch].counter += sample_rate; - if( ((saa->noise[ch].level & 0x4000) == 0) == ((saa->noise[ch].level & 0x0040) == 0) ) - saa->noise[ch].level = (saa->noise[ch].level << 1) | 1; - else - saa->noise[ch].level <<= 1; - } - } - /* write sound data to the buffer */ - buffer[LEFT][j] = output_l / 6; - buffer[RIGHT][j] = output_r / 6; - } -} - -static void saa1099_write_port_w( int chip, int offset, int data ) -{ - struct SAA1099 *saa = &saa1099[chip]; - int reg = saa->selected_reg; - int ch; - - switch (reg) - { - /* channel i amplitude */ - case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: - ch = reg & 7; - saa->channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f]; - saa->channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f]; - break; - /* channel i frequency */ - case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: - ch = reg & 7; - saa->channels[ch].frequency = data & 0xff; - break; - /* channel i octave */ - case 0x10: case 0x11: case 0x12: - ch = (reg - 0x10) << 1; - saa->channels[ch + 0].octave = data & 0x07; - saa->channels[ch + 1].octave = (data >> 4) & 0x07; - break; - /* channel i frequency enable */ - case 0x14: - saa->channels[0].freq_enable = data & 0x01; - saa->channels[1].freq_enable = data & 0x02; - saa->channels[2].freq_enable = data & 0x04; - saa->channels[3].freq_enable = data & 0x08; - saa->channels[4].freq_enable = data & 0x10; - saa->channels[5].freq_enable = data & 0x20; - break; - /* channel i noise enable */ - case 0x15: - saa->channels[0].noise_enable = data & 0x01; - saa->channels[1].noise_enable = data & 0x02; - saa->channels[2].noise_enable = data & 0x04; - saa->channels[3].noise_enable = data & 0x08; - saa->channels[4].noise_enable = data & 0x10; - saa->channels[5].noise_enable = data & 0x20; - break; - /* noise generators parameters */ - case 0x16: - saa->noise_params[0] = data & 0x03; - saa->noise_params[1] = (data >> 4) & 0x03; - break; - /* envelope generators parameters */ - case 0x18: case 0x19: - ch = reg - 0x18; - saa->env_reverse_right[ch] = data & 0x01; - saa->env_mode[ch] = (data >> 1) & 0x07; - saa->env_bits[ch] = data & 0x10; - saa->env_clock[ch] = data & 0x20; - saa->env_enable[ch] = data & 0x80; - /* reset the envelope */ - saa->env_step[ch] = 0; - break; - /* channels enable & reset generators */ - case 0x1c: - saa->all_ch_enable = data & 0x01; - saa->sync_state = data & 0x02; - if (data & 0x02) - { - int i; -// logerror("%04x: (SAA1099 #%d) -reg 0x1c- Chip reset\n",activecpu_get_pc(), chip); - /* Synch & Reset generators */ - for (i = 0; i < 6; i++) - { - saa->channels[i].level = 0; - saa->channels[i].counter = 0.0; - } - } - break; - default: /* Error! */ -// logerror("%04x: (SAA1099 #%d) Unknown operation (reg:%02x, data:%02x)\n",activecpu_get_pc(), chip, reg, data); - LOG(LOG_MISC,LOG_ERROR)("CMS Unkown write to reg %x with %x",reg, data); - } -} - - -static void write_cms(Bitu port,Bitu val,Bitu iolen) { - if (last_command + 1000 < PIC_Ticks) if(cms_chan) cms_chan->Enable(true); - last_command = PIC_Ticks; - switch (port) { - case 0x0220: - saa1099_write_port_w(0,1,val); - break; - case 0x221: - saa1099[0].selected_reg = val & 0x1f; - if (saa1099[0].selected_reg == 0x18 || saa1099[0].selected_reg == 0x19) { - /* clock the envelope channels */ - if (saa1099[0].env_clock[0]) saa1099_envelope(0,0); - if (saa1099[0].env_clock[1]) saa1099_envelope(0,1); - } - break; - case 0x0222: - saa1099_write_port_w(1,1,val); - break; - case 0x223: - saa1099[1].selected_reg = val & 0x1f; - if (saa1099[1].selected_reg == 0x18 || saa1099[1].selected_reg == 0x19) { - /* clock the envelope channels */ - if (saa1099[1].env_clock[0]) saa1099_envelope(1,0); - if (saa1099[1].env_clock[1]) saa1099_envelope(1,1); - } - break; - } -} - - static void CMS_CallBack(Bitu len) { - if (len > CMS_BUFFER_SIZE) return; - - saa1099_update(0, &cms_buf_point[0], (int)len); - saa1099_update(1, &cms_buf_point[2], (int)len); - - Bit16s * stream=(Bit16s *) MixTemp; - /* Mix chip outputs */ - for (Bitu l=0;lMAX_AUDIO) *stream=MAX_AUDIO; - else if (leftMAX_AUDIO) *stream=MAX_AUDIO; - else if (rightAddSamples_s16(len,(Bit16s *)MixTemp); - if (last_command + 10000 < PIC_Ticks) if(cms_chan) cms_chan->Enable(false); -} - - -class CMS:public Module_base { -private: - IO_WriteHandleObject WriteHandler; - MixerObject MixerChan; - -public: - CMS(Section* configuration):Module_base(configuration) { - Section_prop * section = static_cast(configuration); - Bitu sample_rate_temp = section->Get_int("oplrate"); - sample_rate = static_cast(sample_rate_temp); - Bitu base = section->Get_hex("sbbase"); - WriteHandler.Install(base,write_cms,IO_MB,4); - - /* Register the Mixer CallBack */ - cms_chan = MixerChan.Install(CMS_CallBack,sample_rate_temp,"CMS"); - - last_command = PIC_Ticks; - - for (int s=0;s<2;s++) { - struct SAA1099 *saa = &saa1099[s]; - memset(saa, 0, sizeof(struct SAA1099)); - } - } - ~CMS() { - cms_chan = 0; - } -}; - - -static CMS* test; - -void CMS_Init(Section* sec) { - test = new CMS(sec); -} -void CMS_ShutDown(Section* sec) { - delete test; -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "dosbox.h" +#include "inout.h" +#include "mixer.h" +#include "mem.h" +#include "hardware.h" + +#define CMS_RATE 22050 +#define CMS_VOLUME 6000 + + +#define FREQ_SHIFT 16 + +#define SIN_ENT 1024 +#define SIN_MAX (SIN_ENT << FREQ_SHIFT) + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + + + +struct CMS { + struct { + Bit32u freq_pos; + Bit32u freq_add; + Bit16s * vol_left; + Bit16s * vol_right; + Bit8u octave; + Bit8u freq; + } chan[6]; + struct { + Bit32u freq_pos; + Bit32u freq_add; + Bit32u random_val; + } noise[2]; + + Bit8u voice_enabled; + Bit8u noise_enabled; + Bit8u reg; +}; + +static Bit32u freq_table[256][8]; +static Bit32u noise_freq[3]; +static Bit16s vol_table[16]; +static Bit16s sin_table[16][SIN_ENT]; + +static MIXER_Channel * cms_chan; +static CMS cms_block[2]; + +static void write_cms(Bit32u port,Bit8u val) { + Bit32u sel=(port>>1)&1; + CMS * cms=&cms_block[sel]; + switch (port & 1) { + case 1: /* Register Select */ + cms->reg=val; + break; + case 0: /* Write Register */ + switch (cms->reg) { + case 0x00: case 0x01: case 0x02: /* Volume Select */ + case 0x03: case 0x04: case 0x05: + cms->chan[cms->reg].vol_left=sin_table[val & 0xf]; + cms->chan[cms->reg].vol_right=sin_table[(val>>4) & 0xf]; + break; + case 0x08: case 0x09: case 0x0a: /* Frequency Select */ + case 0x0b: case 0x0c: case 0x0d: + { + Bit8u chan=cms->reg-0x08; + cms->chan[chan].freq=val; + /* Get a new entry in the freq table */ + cms->chan[chan].freq_add=freq_table[cms->chan[chan].freq][cms->chan[chan].octave]; + break; + } + case 0x10: case 0x11: case 0x12: /* Octave Select */ + { + Bit8u chan=(cms->reg-0x10)*2; + cms->chan[chan].octave=val&7; + cms->chan[chan].freq_add=freq_table[cms->chan[chan].freq][cms->chan[chan].octave]; + chan++; + cms->chan[chan].octave=(val>>4)&7; + cms->chan[chan].freq_add=freq_table[cms->chan[chan].freq][cms->chan[chan].octave]; + } + break; + case 0x14: /* Frequency enable */ + cms->voice_enabled=val; + //TODO Check for enabling of speaker maybe + break; + case 0x15: /* Noise Enable */ + cms->noise_enabled=val; + //TODO Check for enabling of speaker maybe + break; + case 0x16: /* Noise generator setup */ + cms->noise[0].freq_add=noise_freq[val & 3]; + cms->noise[1].freq_add=noise_freq[(val>>4) & 3]; + break; + default: + LOG_ERROR("CMS %d:Illegal register %X2 Selected for write",sel,cms->reg); + break; + }; + break; + } + +}; + +static void CMS_CallBack(Bit8u * stream,Bit32u len) { + /* Generate the CMS wave */ + /* Generate 12 channels of sound data this could be nice */ + for (Bit32u l=0;lnoise_enabled & use_voice) { + + } else if (cms->voice_enabled & use_voice) { + int pos=cms->chan[chan].freq_pos>>FREQ_SHIFT; + left+=cms->chan[chan].vol_left[pos]; + right+=cms->chan[chan].vol_right[pos]; + cms->chan[chan].freq_pos+=cms->chan[chan].freq_add; + if (cms->chan[chan].freq_pos>=SIN_MAX) + cms->chan[chan].freq_pos-=SIN_MAX; + } + use_voice<<=1; + } + } + if (left>MAX_AUDIO) *(Bit16s *)stream=MAX_AUDIO; + else if (leftMAX_AUDIO) *(Bit16s *)stream=MAX_AUDIO; + else if (right=0;i--) { + sin_table[i][s]=(Bit16s)out; +// out /= (float)1.258925412; /* = 10 ^ (2/20) = 2dB */ + out /= 1.1; + } + } + + +} + diff --git a/src/hardware/gus.cpp b/src/hardware/gus.cpp deleted file mode 100644 index fd3be81..0000000 --- a/src/hardware/gus.cpp +++ /dev/null @@ -1,888 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: gus.cpp,v 1.36 2009/04/27 17:11:26 qbix79 Exp $ */ - -#include -#include -#include -#include "dosbox.h" -#include "inout.h" -#include "mixer.h" -#include "dma.h" -#include "pic.h" -#include "setup.h" -#include "shell.h" -#include "math.h" -#include "regs.h" -using namespace std; - -//Extra bits of precision over normal gus -#define WAVE_BITS 2 -#define WAVE_FRACT (9+WAVE_BITS) -#define WAVE_FRACT_MASK ((1 << WAVE_FRACT)-1) -#define WAVE_MSWMASK ((1 << (16+WAVE_BITS))-1) -#define WAVE_LSWMASK (0xffffffff ^ WAVE_MSWMASK) - -//Amount of precision the volume has -#define RAMP_FRACT (10) -#define RAMP_FRACT_MASK ((1 << RAMP_FRACT)-1) - -#define GUS_BASE myGUS.portbase -#define GUS_RATE myGUS.rate -#define LOG_GUS 0 - -Bit8u adlib_commandreg; -static MixerChannel * gus_chan; -static Bit8u irqtable[8] = { 0, 2, 5, 3, 7, 11, 12, 15 }; -static Bit8u dmatable[8] = { 0, 1, 3, 5, 6, 7, 0, 0 }; -static Bit8u GUSRam[1024*1024]; // 1024K of GUS Ram -static Bit32s AutoAmp = 512; -static Bit16u vol16bit[4096]; -static Bit32u pantable[16]; - -class GUSChannels; -static void CheckVoiceIrq(void); - -struct GFGus { - Bit8u gRegSelect; - Bit16u gRegData; - Bit32u gDramAddr; - Bit16u gCurChannel; - - Bit8u DMAControl; - Bit16u dmaAddr; - Bit8u TimerControl; - Bit8u SampControl; - Bit8u mixControl; - Bit8u ActiveChannels; - Bit32u basefreq; - - struct GusTimer { - Bit8u value; - bool reached; - bool raiseirq; - bool masked; - bool running; - float delay; - } timers[2]; - Bit32u rate; - Bitu portbase; - Bit8u dma1; - Bit8u dma2; - - Bit8u irq1; - Bit8u irq2; - - bool irqenabled; - bool ChangeIRQDMA; - // IRQ status register values - Bit8u IRQStatus; - Bit32u ActiveMask; - Bit8u IRQChan; - Bit32u RampIRQ; - Bit32u WaveIRQ; -} myGUS; - -Bitu DEBUG_EnableDebugger(void); - -static void GUS_DMA_Callback(DmaChannel * chan,DMAEvent event); - -// Returns a single 16-bit sample from the Gravis's RAM -static INLINE Bit32s GetSample(Bit32u Delta, Bit32u CurAddr, bool eightbit) { - Bit32u useAddr; - Bit32u holdAddr; - useAddr = CurAddr >> WAVE_FRACT; - if (eightbit) { - if (Delta >= (1 << WAVE_FRACT)) { - Bit32s tmpsmall = (Bit8s)GUSRam[useAddr]; - return tmpsmall << 8; - } else { - // Interpolate - Bit32s w1 = ((Bit8s)GUSRam[useAddr+0]) << 8; - Bit32s w2 = ((Bit8s)GUSRam[useAddr+1]) << 8; - Bit32s diff = w2 - w1; - return (w1+((diff*(Bit32s)(CurAddr&WAVE_FRACT_MASK ))>>WAVE_FRACT)); - } - } else { - // Formula used to convert addresses for use with 16-bit samples - holdAddr = useAddr & 0xc0000L; - useAddr = useAddr & 0x1ffffL; - useAddr = useAddr << 1; - useAddr = (holdAddr | useAddr); - - if(Delta >= (1 << WAVE_FRACT)) { - return (GUSRam[useAddr+0] | (((Bit8s)GUSRam[useAddr+1]) << 8)); - } else { - // Interpolate - Bit32s w1 = (GUSRam[useAddr+0] | (((Bit8s)GUSRam[useAddr+1]) << 8)); - Bit32s w2 = (GUSRam[useAddr+2] | (((Bit8s)GUSRam[useAddr+3]) << 8)); - Bit32s diff = w2 - w1; - return (w1+((diff*(Bit32s)(CurAddr&WAVE_FRACT_MASK ))>>WAVE_FRACT)); - } - } -} - -class GUSChannels { -public: - Bit32u WaveStart; - Bit32u WaveEnd; - Bit32u WaveAddr; - Bit32u WaveAdd; - Bit8u WaveCtrl; - Bit16u WaveFreq; - - Bit32u RampStart; - Bit32u RampEnd; - Bit32u RampVol; - Bit32u RampAdd; - Bit32u RampAddReal; - - Bit8u RampRate; - Bit8u RampCtrl; - - Bit8u PanPot; - Bit8u channum; - Bit32u irqmask; - Bit32u PanLeft; - Bit32u PanRight; - Bit32s VolLeft; - Bit32s VolRight; - - GUSChannels(Bit8u num) { - channum = num; - irqmask = 1 << num; - WaveStart = 0; - WaveEnd = 0; - WaveAddr = 0; - WaveAdd = 0; - WaveFreq = 0; - WaveCtrl = 3; - RampRate = 0; - RampStart = 0; - RampEnd = 0; - RampCtrl = 3; - RampAdd = 0; - RampVol = 0; - VolLeft = 0; - VolRight = 0; - PanLeft = 0; - PanRight = 0; - PanPot = 0x7; - }; - void WriteWaveFreq(Bit16u val) { - WaveFreq = val; - double frameadd = double(val >> 1)/512.0; //Samples / original gus frame - double realadd = (frameadd*(double)myGUS.basefreq/(double)GUS_RATE) * (double)(1 << WAVE_FRACT); - WaveAdd = (Bit32u)realadd; - } - void WriteWaveCtrl(Bit8u val) { - Bit32u oldirq=myGUS.WaveIRQ; - WaveCtrl = val & 0x7f; - if ((val & 0xa0)==0xa0) myGUS.WaveIRQ|=irqmask; - else myGUS.WaveIRQ&=~irqmask; - if (oldirq != myGUS.WaveIRQ) - CheckVoiceIrq(); - } - INLINE Bit8u ReadWaveCtrl(void) { - Bit8u ret=WaveCtrl; - if (myGUS.WaveIRQ & irqmask) ret|=0x80; - return ret; - } - void UpdateWaveRamp(void) { - WriteWaveFreq(WaveFreq); - WriteRampRate(RampRate); - } - void WritePanPot(Bit8u val) { - PanPot = val; - PanLeft = pantable[0x0f-(val & 0xf)]; - PanRight = pantable[(val & 0xf)]; - UpdateVolumes(); - } - Bit8u ReadPanPot(void) { - return PanPot; - } - void WriteRampCtrl(Bit8u val) { - Bit32u old=myGUS.RampIRQ; - RampCtrl = val & 0x7f; - if ((val & 0xa0)==0xa0) myGUS.RampIRQ|=irqmask; - else myGUS.RampIRQ&=~irqmask; - if (old != myGUS.RampIRQ) CheckVoiceIrq(); - } - INLINE Bit8u ReadRampCtrl(void) { - Bit8u ret=RampCtrl; - if (myGUS.RampIRQ & irqmask) ret|=0x80; - return ret; - } - void WriteRampRate(Bit8u val) { - RampRate = val; - double frameadd = (double)(RampRate & 63)/(double)(1 << (3*(val >> 6))); - double realadd = (frameadd*(double)myGUS.basefreq/(double)GUS_RATE) * (double)(1 << RAMP_FRACT); - RampAdd = (Bit32u)realadd; - } - INLINE void WaveUpdate(void) { - if (WaveCtrl & 0x3) return; - Bit32s WaveLeft; - if (WaveCtrl & 0x40) { - WaveAddr-=WaveAdd; - WaveLeft=WaveStart-WaveAddr; - } else { - WaveAddr+=WaveAdd; - WaveLeft=WaveAddr-WaveEnd; - } - if (WaveLeft<0) return; - /* Generate an IRQ if needed */ - if (WaveCtrl & 0x20) { - myGUS.WaveIRQ|=irqmask; - } - /* Check for not being in PCM operation */ - if (RampCtrl & 0x04) return; - /* Check for looping */ - if (WaveCtrl & 0x08) { - /* Bi-directional looping */ - if (WaveCtrl & 0x10) WaveCtrl^=0x40; - WaveAddr = (WaveCtrl & 0x40) ? (WaveEnd-WaveLeft) : (WaveStart+WaveLeft); - } else { - WaveCtrl|=1; //Stop the channel - WaveAddr = (WaveCtrl & 0x40) ? WaveStart : WaveEnd; - } - } - INLINE void UpdateVolumes(void) { - Bit32s templeft=RampVol - PanLeft; - templeft&=~(templeft >> 31); - Bit32s tempright=RampVol - PanRight; - tempright&=~(tempright >> 31); - VolLeft=vol16bit[templeft >> RAMP_FRACT]; - VolRight=vol16bit[tempright >> RAMP_FRACT]; - } - INLINE void RampUpdate(void) { - /* Check if ramping enabled */ - if (RampCtrl & 0x3) return; - Bit32s RampLeft; - if (RampCtrl & 0x40) { - RampVol-=RampAdd; - RampLeft=RampStart-RampVol; - } else { - RampVol+=RampAdd; - RampLeft=RampVol-RampEnd; - } - if (RampLeft<0) { - UpdateVolumes(); - return; - } - /* Generate an IRQ if needed */ - if (RampCtrl & 0x20) { - myGUS.RampIRQ|=irqmask; - } - /* Check for looping */ - if (RampCtrl & 0x08) { - /* Bi-directional looping */ - if (RampCtrl & 0x10) RampCtrl^=0x40; - RampVol = (RampCtrl & 0x40) ? (RampEnd-RampLeft) : (RampStart+RampLeft); - } else { - RampCtrl|=1; //Stop the channel - RampVol = (RampCtrl & 0x40) ? RampStart : RampEnd; - } - UpdateVolumes(); - } - void generateSamples(Bit32s * stream,Bit32u len) { - int i; - Bit32s tmpsamp; - bool eightbit; - if (RampCtrl & WaveCtrl & 3) return; - eightbit = ((WaveCtrl & 0x4) == 0); - - for(i=0;i<(int)len;i++) { - // Get sample - tmpsamp = GetSample(WaveAdd, WaveAddr, eightbit); - // Output stereo sample - stream[i<<1]+= tmpsamp * VolLeft; - stream[(i<<1)+1]+= tmpsamp * VolRight; - WaveUpdate(); - RampUpdate(); - } - } -}; - -static GUSChannels *guschan[32]; -static GUSChannels *curchan; - -static void GUSReset(void) { - if((myGUS.gRegData & 0x1) == 0x1) { - // Reset - adlib_commandreg = 85; - myGUS.IRQStatus = 0; - myGUS.timers[0].raiseirq = false; - myGUS.timers[1].raiseirq = false; - myGUS.timers[0].reached = false; - myGUS.timers[1].reached = false; - myGUS.timers[0].running = false; - myGUS.timers[1].running = false; - - myGUS.timers[0].value = 0xff; - myGUS.timers[1].value = 0xff; - myGUS.timers[0].delay = 0.080f; - myGUS.timers[1].delay = 0.320f; - myGUS.ChangeIRQDMA = false; - // Stop all channels - int i; - for(i=0;i<32;i++) { - guschan[i]->RampVol=0; - guschan[i]->WriteWaveCtrl(0x1); - guschan[i]->WriteRampCtrl(0x1); - guschan[i]->WritePanPot(0x7); - } - myGUS.IRQChan = 0; - } - if ((myGUS.gRegData & 0x4) != 0) { - myGUS.irqenabled = true; - } else { - myGUS.irqenabled = false; - } -} - -static INLINE void GUS_CheckIRQ(void) { - if (myGUS.IRQStatus && (myGUS.mixControl & 0x08)) - PIC_ActivateIRQ(myGUS.irq1); - -} - -static void CheckVoiceIrq(void) { - myGUS.IRQStatus&=0x9f; - Bitu totalmask=(myGUS.RampIRQ|myGUS.WaveIRQ) & myGUS.ActiveMask; - if (!totalmask) return; - if (myGUS.RampIRQ) myGUS.IRQStatus|=0x40; - if (myGUS.WaveIRQ) myGUS.IRQStatus|=0x20; - GUS_CheckIRQ(); - for (;;) { - Bit32u check=(1 << myGUS.IRQChan); - if (totalmask & check) return; - myGUS.IRQChan++; - if (myGUS.IRQChan>=myGUS.ActiveChannels) myGUS.IRQChan=0; - } -} - -static Bit16u ExecuteReadRegister(void) { - Bit8u tmpreg; -// LOG_MSG("Read global reg %x",myGUS.gRegSelect); - switch (myGUS.gRegSelect) { - case 0x41: // Dma control register - read acknowledges DMA IRQ - tmpreg = myGUS.DMAControl & 0xbf; - tmpreg |= (myGUS.IRQStatus & 0x80) >> 1; - myGUS.IRQStatus&=0x7f; - return (Bit16u)(tmpreg << 8); - case 0x42: // Dma address register - return myGUS.dmaAddr; - case 0x45: // Timer control register. Identical in operation to Adlib's timer - return (Bit16u)(myGUS.TimerControl << 8); - break; - case 0x49: // Dma sample register - tmpreg = myGUS.DMAControl & 0xbf; - tmpreg |= (myGUS.IRQStatus & 0x80) >> 1; - return (Bit16u)(tmpreg << 8); - case 0x80: // Channel voice control read register - if (curchan) return curchan->ReadWaveCtrl() << 8; - else return 0x0300; - - case 0x82: // Channel MSB start address register - if (curchan) return (Bit16u)(curchan->WaveStart >> (WAVE_BITS+16)); - else return 0x0000; - case 0x83: // Channel LSW start address register - if (curchan) return (Bit16u)(curchan->WaveStart >> WAVE_BITS); - else return 0x0000; - - case 0x89: // Channel volume register - if (curchan) return (Bit16u)((curchan->RampVol >> RAMP_FRACT) << 4); - else return 0x0000; - case 0x8a: // Channel MSB current address register - if (curchan) return (Bit16u)(curchan->WaveAddr >> (WAVE_BITS+16)); - else return 0x0000; - case 0x8b: // Channel LSW current address register - if (curchan) return (Bit16u)(curchan->WaveAddr >> WAVE_BITS); - else return 0x0000; - - case 0x8d: // Channel volume control register - if (curchan) return curchan->ReadRampCtrl() << 8; - else return 0x0300; - case 0x8f: // General channel IRQ status register - tmpreg=myGUS.IRQChan|0x20; - Bit32u mask; - mask=1 << myGUS.IRQChan; - if (!(myGUS.RampIRQ & mask)) tmpreg|=0x40; - if (!(myGUS.WaveIRQ & mask)) tmpreg|=0x80; - myGUS.RampIRQ&=~mask; - myGUS.WaveIRQ&=~mask; - CheckVoiceIrq(); - return (Bit16u)(tmpreg << 8); - default: -#if LOG_GUS - LOG_MSG("Read Register num 0x%x", myGUS.gRegSelect); -#endif - return myGUS.gRegData; - } -} - -static void GUS_TimerEvent(Bitu val) { - if (!myGUS.timers[val].masked) myGUS.timers[val].reached=true; - if (myGUS.timers[val].raiseirq) { - myGUS.IRQStatus|=0x4 << val; - GUS_CheckIRQ(); - } - if (myGUS.timers[val].running) - PIC_AddEvent(GUS_TimerEvent,myGUS.timers[val].delay,val); -} - - -static void ExecuteGlobRegister(void) { - int i; -// if (myGUS.gRegSelect|1!=0x44) LOG_MSG("write global register %x with %x", myGUS.gRegSelect, myGUS.gRegData); - switch(myGUS.gRegSelect) { - case 0x0: // Channel voice control register - if(curchan) curchan->WriteWaveCtrl((Bit16u)myGUS.gRegData>>8); - break; - case 0x1: // Channel frequency control register - if(curchan) curchan->WriteWaveFreq(myGUS.gRegData); - break; - case 0x2: // Channel MSW start address register - if (curchan) { - Bit32u tmpaddr = (Bit32u)(myGUS.gRegData & 0x1fff) << (16+WAVE_BITS); - curchan->WaveStart = (curchan->WaveStart & WAVE_MSWMASK) | tmpaddr; - } - break; - case 0x3: // Channel LSW start address register - if(curchan != NULL) { - Bit32u tmpaddr = (Bit32u)(myGUS.gRegData) << WAVE_BITS; - curchan->WaveStart = (curchan->WaveStart & WAVE_LSWMASK) | tmpaddr; - } - break; - case 0x4: // Channel MSW end address register - if(curchan != NULL) { - Bit32u tmpaddr = (Bit32u)(myGUS.gRegData & 0x1fff) << (16+WAVE_BITS); - curchan->WaveEnd = (curchan->WaveEnd & WAVE_MSWMASK) | tmpaddr; - } - break; - case 0x5: // Channel MSW end address register - if(curchan != NULL) { - Bit32u tmpaddr = (Bit32u)(myGUS.gRegData) << WAVE_BITS; - curchan->WaveEnd = (curchan->WaveEnd & WAVE_LSWMASK) | tmpaddr; - } - break; - case 0x6: // Channel volume ramp rate register - if(curchan != NULL) { - Bit8u tmpdata = (Bit16u)myGUS.gRegData>>8; - curchan->WriteRampRate(tmpdata); - } - break; - case 0x7: // Channel volume ramp start register EEEEMMMM - if(curchan != NULL) { - Bit8u tmpdata = (Bit16u)myGUS.gRegData >> 8; - curchan->RampStart = tmpdata << (4+RAMP_FRACT); - } - break; - case 0x8: // Channel volume ramp end register EEEEMMMM - if(curchan != NULL) { - Bit8u tmpdata = (Bit16u)myGUS.gRegData >> 8; - curchan->RampEnd = tmpdata << (4+RAMP_FRACT); - } - break; - case 0x9: // Channel current volume register - if(curchan != NULL) { - Bit16u tmpdata = (Bit16u)myGUS.gRegData >> 4; - curchan->RampVol = tmpdata << RAMP_FRACT; - curchan->UpdateVolumes(); - } - break; - case 0xA: // Channel MSW current address register - if(curchan != NULL) { - Bit32u tmpaddr = (Bit32u)(myGUS.gRegData & 0x1fff) << (16+WAVE_BITS); - curchan->WaveAddr = (curchan->WaveAddr & WAVE_MSWMASK) | tmpaddr; - } - break; - case 0xB: // Channel LSW current address register - if(curchan != NULL) { - Bit32u tmpaddr = (Bit32u)(myGUS.gRegData) << (WAVE_BITS); - curchan->WaveAddr = (curchan->WaveAddr & WAVE_LSWMASK) | tmpaddr; - } - break; - case 0xC: // Channel pan pot register - if(curchan) curchan->WritePanPot((Bit16u)myGUS.gRegData>>8); - break; - case 0xD: // Channel volume control register - if(curchan) curchan->WriteRampCtrl((Bit16u)myGUS.gRegData>>8); - break; - case 0xE: // Set active channel register - myGUS.gRegSelect = myGUS.gRegData>>8; //JAZZ Jackrabbit seems to assume this? - myGUS.ActiveChannels = 1+((myGUS.gRegData>>8) & 63); - if(myGUS.ActiveChannels < 14) myGUS.ActiveChannels = 14; - if(myGUS.ActiveChannels > 32) myGUS.ActiveChannels = 32; - myGUS.ActiveMask=0xffffffffU >> (32-myGUS.ActiveChannels); - gus_chan->Enable(true); - myGUS.basefreq = (Bit32u)((float)1000000/(1.619695497*(float)(myGUS.ActiveChannels))); -#if LOG_GUS - LOG_MSG("GUS set to %d channels", myGUS.ActiveChannels); -#endif - for (i=0;iUpdateWaveRamp(); - break; - case 0x10: // Undocumented register used in Fast Tracker 2 - break; - case 0x41: // Dma control register - myGUS.DMAControl = (Bit8u)(myGUS.gRegData>>8); - GetDMAChannel(myGUS.dma1)->Register_Callback( - (myGUS.DMAControl & 0x1) ? GUS_DMA_Callback : 0); - break; - case 0x42: // Gravis DRAM DMA address register - myGUS.dmaAddr = myGUS.gRegData; - break; - case 0x43: // MSB Peek/poke DRAM position - myGUS.gDramAddr = (0xff0000 & myGUS.gDramAddr) | ((Bit32u)myGUS.gRegData); - break; - case 0x44: // LSW Peek/poke DRAM position - myGUS.gDramAddr = (0xffff & myGUS.gDramAddr) | ((Bit32u)myGUS.gRegData>>8) << 16; - break; - case 0x45: // Timer control register. Identical in operation to Adlib's timer - myGUS.TimerControl = (Bit8u)(myGUS.gRegData>>8); - myGUS.timers[0].raiseirq=(myGUS.TimerControl & 0x04)>0; - if (!myGUS.timers[0].raiseirq) myGUS.IRQStatus&=~0x04; - myGUS.timers[1].raiseirq=(myGUS.TimerControl & 0x08)>0; - if (!myGUS.timers[1].raiseirq) myGUS.IRQStatus&=~0x08; - break; - case 0x46: // Timer 1 control - myGUS.timers[0].value = (Bit8u)(myGUS.gRegData>>8); - myGUS.timers[0].delay = (0x100 - myGUS.timers[0].value) * 0.080f; - break; - case 0x47: // Timer 2 control - myGUS.timers[1].value = (Bit8u)(myGUS.gRegData>>8); - myGUS.timers[1].delay = (0x100 - myGUS.timers[1].value) * 0.320f; - break; - case 0x49: // DMA sampling control register - myGUS.SampControl = (Bit8u)(myGUS.gRegData>>8); - GetDMAChannel(myGUS.dma1)->Register_Callback( - (myGUS.SampControl & 0x1) ? GUS_DMA_Callback : 0); - break; - case 0x4c: // GUS reset register - GUSReset(); - break; - default: -#if LOG_GUS - LOG_MSG("Unimplemented global register %x -- %x", myGUS.gRegSelect, myGUS.gRegData); -#endif - break; - } - return; -} - - -static Bitu read_gus(Bitu port,Bitu iolen) { -// LOG_MSG("read from gus port %x",port); - switch(port - GUS_BASE) { - case 0x206: - return myGUS.IRQStatus; - case 0x208: - Bit8u tmptime; - tmptime = 0; - if (myGUS.timers[0].reached) tmptime |= (1 << 6); - if (myGUS.timers[1].reached) tmptime |= (1 << 5); - if (tmptime & 0x60) tmptime |= (1 << 7); - if (myGUS.IRQStatus & 0x04) tmptime|=(1 << 2); - if (myGUS.IRQStatus & 0x08) tmptime|=(1 << 1); - return tmptime; - case 0x20a: - return adlib_commandreg; - case 0x302: - return (Bit8u)myGUS.gCurChannel; - case 0x303: - return myGUS.gRegSelect; - case 0x304: - if (iolen==2) return ExecuteReadRegister() & 0xffff; - else return ExecuteReadRegister() & 0xff; - case 0x305: - return ExecuteReadRegister() >> 8; - case 0x307: - if(myGUS.gDramAddr < sizeof(GUSRam)) { - return GUSRam[myGUS.gDramAddr]; - } else { - return 0; - } - default: -#if LOG_GUS - LOG_MSG("Read GUS at port 0x%x", port); -#endif - break; - } - - return 0xff; -} - - -static void write_gus(Bitu port,Bitu val,Bitu iolen) { -// LOG_MSG("Write gus port %x val %x",port,val); - switch(port - GUS_BASE) { - case 0x200: - myGUS.mixControl = val; - myGUS.ChangeIRQDMA = true; - return; - case 0x208: - adlib_commandreg = val; - break; - case 0x209: -//TODO adlib_commandreg should be 4 for this to work else it should just latch the value - if (val & 0x80) { - myGUS.timers[0].reached=false; - myGUS.timers[1].reached=false; - return; - } - myGUS.timers[0].masked=(val & 0x40)>0; - myGUS.timers[1].masked=(val & 0x20)>0; - if (val & 0x1) { - if (!myGUS.timers[0].running) { - PIC_AddEvent(GUS_TimerEvent,myGUS.timers[0].delay,0); - myGUS.timers[0].running=true; - } - } else myGUS.timers[0].running=false; - if (val & 0x2) { - if (!myGUS.timers[1].running) { - PIC_AddEvent(GUS_TimerEvent,myGUS.timers[1].delay,1); - myGUS.timers[1].running=true; - } - } else myGUS.timers[1].running=false; - break; -//TODO Check if 0x20a register is also available on the gus like on the interwave - case 0x20b: - if (!myGUS.ChangeIRQDMA) break; - myGUS.ChangeIRQDMA=false; - if (myGUS.mixControl & 0x40) { - // IRQ configuration, only use low bits for irq 1 - if (irqtable[val & 0x7]) myGUS.irq1=irqtable[val & 0x7]; -#if LOG_GUS - LOG_MSG("Assigned GUS to IRQ %d", myGUS.irq1); -#endif - } else { - // DMA configuration, only use low bits for dma 1 - if (dmatable[val & 0x7]) myGUS.dma1=dmatable[val & 0x7]; -#if LOG_GUS - LOG_MSG("Assigned GUS to DMA %d", myGUS.dma1); -#endif - } - break; - case 0x302: - myGUS.gCurChannel = val & 31 ; - curchan = guschan[myGUS.gCurChannel]; - break; - case 0x303: - myGUS.gRegSelect = val; - myGUS.gRegData = 0; - break; - case 0x304: - if (iolen==2) { - myGUS.gRegData=val; - ExecuteGlobRegister(); - } else myGUS.gRegData = val; - break; - case 0x305: - myGUS.gRegData = (0x00ff & myGUS.gRegData) | val << 8; - ExecuteGlobRegister(); - break; - case 0x307: - if(myGUS.gDramAddr < sizeof(GUSRam)) GUSRam[myGUS.gDramAddr] = val; - break; - default: -#if LOG_GUS - LOG_MSG("Write GUS at port 0x%x with %x", port, val); -#endif - break; - } -} - -static void GUS_DMA_Callback(DmaChannel * chan,DMAEvent event) { - if (event!=DMA_UNMASKED) return; - Bitu dmaaddr = myGUS.dmaAddr << 4; - if((myGUS.DMAControl & 0x2) == 0) { - Bitu read=chan->Read(chan->currcnt+1,&GUSRam[dmaaddr]); - //Check for 16 or 8bit channel - read*=(chan->DMA16+1); - if((myGUS.DMAControl & 0x80) != 0) { - //Invert the MSB to convert twos compliment form - Bitu i; - if((myGUS.DMAControl & 0x40) == 0) { - // 8-bit data - for(i=dmaaddr;i<(dmaaddr+read);i++) GUSRam[i] ^= 0x80; - } else { - // 16-bit data - for(i=dmaaddr+1;i<(dmaaddr+read);i+=2) GUSRam[i] ^= 0x80; - } - } - } else { - //Read data out of UltraSound - chan->Write(chan->currcnt+1,&GUSRam[dmaaddr]); - } - /* Raise the TC irq if needed */ - if((myGUS.DMAControl & 0x20) != 0) { - myGUS.IRQStatus |= 0x80; - GUS_CheckIRQ(); - } - chan->Register_Callback(0); -} - -static void GUS_CallBack(Bitu len) { - memset(&MixTemp,0,len*8); - Bitu i; - Bit16s * buf16 = (Bit16s *)MixTemp; - Bit32s * buf32 = (Bit32s *)MixTemp; - for(i=0;igenerateSamples(buf32,len); - for(i=0;i> 13)*AutoAmp)>>9; - if (sample>32767) { - sample=32767; - AutoAmp--; - } else if (sample<-32768) { - sample=-32768; - AutoAmp--; - } - buf16[i] = (Bit16s)(sample); - } - gus_chan->AddSamples_s16(len,buf16); - CheckVoiceIrq(); -} - -// Generate logarithmic to linear volume conversion tables -static void MakeTables(void) { - int i; - double out = (double)(1 << 13); - for (i=4095;i>=0;i--) { - vol16bit[i]=(Bit16s)out; - out/=1.002709201; /* 0.0235 dB Steps */ - } - pantable[0]=0; - for (i=1;i<16;i++) { - pantable[i]=(Bit32u)(-128.0*(log((double)i/15.0)/log(2.0))*(double)(1 << RAMP_FRACT)); - } -} - -class GUS:public Module_base{ -private: - IO_ReadHandleObject ReadHandler[8]; - IO_WriteHandleObject WriteHandler[9]; - AutoexecObject autoexecline[2]; - MixerObject MixerChan; -public: - GUS(Section* configuration):Module_base(configuration){ - if(!IS_EGAVGA_ARCH) return; - Section_prop * section=static_cast(configuration); - if(!section->Get_bool("gus")) return; - - memset(&myGUS,0,sizeof(myGUS)); - memset(GUSRam,0,1024*1024); - - myGUS.rate=section->Get_int("gusrate"); - - myGUS.portbase = section->Get_hex("gusbase") - 0x200; - int dma_val = section->Get_int("gusdma"); - if ((dma_val<0) || (dma_val>255)) dma_val = 3; // sensible default - int irq_val = section->Get_int("gusirq"); - if ((irq_val<0) || (irq_val>255)) irq_val = 5; // sensible default - myGUS.dma1 = (Bit8u)dma_val; - myGUS.dma2 = (Bit8u)dma_val; - myGUS.irq1 = (Bit8u)irq_val; - myGUS.irq2 = (Bit8u)irq_val; - - // We'll leave the MIDI interface to the MPU-401 - // Ditto for the Joystick - // GF1 Synthesizer - ReadHandler[0].Install(0x302 + GUS_BASE,read_gus,IO_MB); - WriteHandler[0].Install(0x302 + GUS_BASE,write_gus,IO_MB); - - WriteHandler[1].Install(0x303 + GUS_BASE,write_gus,IO_MB); - ReadHandler[1].Install(0x303 + GUS_BASE,read_gus,IO_MB); - - WriteHandler[2].Install(0x304 + GUS_BASE,write_gus,IO_MB|IO_MW); - ReadHandler[2].Install(0x304 + GUS_BASE,read_gus,IO_MB|IO_MW); - - WriteHandler[3].Install(0x305 + GUS_BASE,write_gus,IO_MB); - ReadHandler[3].Install(0x305 + GUS_BASE,read_gus,IO_MB); - - ReadHandler[4].Install(0x206 + GUS_BASE,read_gus,IO_MB); - - WriteHandler[4].Install(0x208 + GUS_BASE,write_gus,IO_MB); - ReadHandler[5].Install(0x208 + GUS_BASE,read_gus,IO_MB); - - WriteHandler[5].Install(0x209 + GUS_BASE,write_gus,IO_MB); - - WriteHandler[6].Install(0x307 + GUS_BASE,write_gus,IO_MB); - ReadHandler[6].Install(0x307 + GUS_BASE,read_gus,IO_MB); - - // Board Only - - WriteHandler[7].Install(0x200 + GUS_BASE,write_gus,IO_MB); - ReadHandler[7].Install(0x20A + GUS_BASE,read_gus,IO_MB); - WriteHandler[8].Install(0x20B + GUS_BASE,write_gus,IO_MB); - - // DmaChannels[myGUS.dma1]->Register_TC_Callback(GUS_DMA_TC_Callback); - - MakeTables(); - - for (Bit8u chan_ct=0; chan_ct<32; chan_ct++) { - guschan[chan_ct] = new GUSChannels(chan_ct); - } - // Register the Mixer CallBack - gus_chan=MixerChan.Install(GUS_CallBack,GUS_RATE,"GUS"); - myGUS.gRegData=0x1; - GUSReset(); - myGUS.gRegData=0x0; - int portat = 0x200+GUS_BASE; - - // ULTRASND=Port,DMA1,DMA2,IRQ1,IRQ2 - // [GUS port], [GUS DMA (recording)], [GUS DMA (playback)], [GUS IRQ (playback)], [GUS IRQ (MIDI)] - ostringstream temp; - temp << "SET ULTRASND=" << hex << setw(3) << portat << "," - << dec << (Bitu)myGUS.dma1 << "," << (Bitu)myGUS.dma2 << "," - << (Bitu)myGUS.irq1 << "," << (Bitu)myGUS.irq2 << ends; - // Create autoexec.bat lines - autoexecline[0].Install(temp.str()); - autoexecline[1].Install(std::string("SET ULTRADIR=") + section->Get_string("ultradir")); - } - - - ~GUS() { - if(!IS_EGAVGA_ARCH) return; - Section_prop * section=static_cast(m_configuration); - if(!section->Get_bool("gus")) return; - - myGUS.gRegData=0x1; - GUSReset(); - myGUS.gRegData=0x0; - - for(Bitu i=0;i<32;i++) { - delete guschan[i]; - } - - memset(&myGUS,0,sizeof(myGUS)); - memset(GUSRam,0,1024*1024); - } -}; - -static GUS* test; - -void GUS_ShutDown(Section* /*sec*/) { - delete test; -} - -void GUS_Init(Section* sec) { - test = new GUS(sec); - sec->AddDestroyFunction(&GUS_ShutDown,true); -} diff --git a/src/hardware/hardware.cpp b/src/hardware/hardware.cpp index e4f79ee..79ccf08 100644 --- a/src/hardware/hardware.cpp +++ b/src/hardware/hardware.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2009 The DOSBox Team + * Copyright (C) 2002 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -9,752 +9,109 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: hardware.cpp,v 1.22 2009/04/26 18:24:36 qbix79 Exp $ */ +/* + This could do with a serious revision :) +*/ #include -#include -#include #include "dosbox.h" +#include "programs.h" #include "hardware.h" -#include "setup.h" -#include "support.h" -#include "mem.h" -#include "mapper.h" -#include "pic.h" -#include "render.h" -#include "cross.h" -#if (C_SSHOT) -#include -#include "../libs/zmbv/zmbv.cpp" -#endif +static HWBlock * firsthw=0; -static std::string capturedir; -extern const char* RunningProgram; -Bitu CaptureState; -#define WAVE_BUF 16*1024 -#define MIDI_BUF 4*1024 -#define AVI_HEADER_SIZE 500 +class HWSET : public Program { +public: + HWSET(PROGRAM_Info * program_info); + void Run(void); -static struct { - struct { - FILE * handle; - Bit16s buf[WAVE_BUF][2]; - Bitu used; - Bit32u length; - Bit32u freq; - } wave; - struct { - FILE * handle; - Bit8u buffer[MIDI_BUF]; - Bitu used,done; - Bit32u last; - } midi; - struct { - Bitu rowlen; - } image; -#if (C_SSHOT) - struct { - FILE *handle; - Bitu frames; - Bit16s audiobuf[WAVE_BUF][2]; - Bitu audioused; - Bitu audiorate; - Bitu audiowritten; - VideoCodec *codec; - Bitu width, height, bpp; - Bitu written; - float fps; - int bufSize; - void *buf; - Bit8u *index; - Bitu indexsize, indexused; - } video; -#endif -} capture; +}; -FILE * OpenCaptureFile(const char * type,const char * ext) { - if(capturedir.empty()) { - LOG_MSG("Please specify a capture directory"); - return 0; - } - Bitu last=0; - char file_start[16]; - dir_information * dir; - /* Find a filename to open */ - dir = open_directory(capturedir.c_str()); - if (!dir) { - //Try creating it first - Cross::CreateDir(capturedir); - dir=open_directory(capturedir.c_str()); - if(!dir) { - - LOG_MSG("Can't open dir %s for capturing %s",capturedir.c_str(),type); - return 0; - } - } - strcpy(file_start,RunningProgram); - lowcase(file_start); - strcat(file_start,"_"); - bool is_directory; - char tempname[CROSS_LEN]; - bool testRead = read_directory_first(dir, tempname, is_directory ); - for ( ; testRead; testRead = read_directory_next(dir, tempname, is_directory) ) { - char * test=strstr(tempname,ext); - if (!test || strlen(test)!=strlen(ext)) - continue; - *test=0; - if (strncasecmp(tempname,file_start,strlen(file_start))!=0) continue; - Bitu num=atoi(&tempname[strlen(file_start)]); - if (num>=last) last=num+1; - } - close_directory( dir ); - char file_name[CROSS_LEN]; - sprintf(file_name,"%s%c%s%03d%s",capturedir.c_str(),CROSS_FILESPLIT,file_start,last,ext); - /* Open the actual file */ - FILE * handle=fopen(file_name,"wb"); - if (handle) { - LOG_MSG("Capturing %s to %s",type,file_name); - } else { - LOG_MSG("Failed to open %s for capturing %s",file_name,type); - } - return handle; +HWSET::HWSET(PROGRAM_Info * info):Program(info) { + } -#if (C_SSHOT) -static void CAPTURE_AddAviChunk(const char * tag, Bit32u size, void * data, Bit32u flags) { - Bit8u chunk[8];Bit8u *index;Bit32u pos, writesize; - - chunk[0] = tag[0];chunk[1] = tag[1];chunk[2] = tag[2];chunk[3] = tag[3]; - host_writed(&chunk[4], size); - /* Write the actual data */ - fwrite(chunk,1,8,capture.video.handle); - writesize = (size+1)&~1; - fwrite(data,1,writesize,capture.video.handle); - pos = capture.video.written + 4; - capture.video.written += writesize + 8; - if (capture.video.indexused + 16 >= capture.video.indexsize ) { - capture.video.index = (Bit8u*)realloc( capture.video.index, capture.video.indexsize + 16 * 4096); - if (!capture.video.index) - E_Exit("Ran out of memory during AVI capturing"); - capture.video.indexsize += 16*4096; - } - index = capture.video.index+capture.video.indexused; - capture.video.indexused += 16; - index[0] = tag[0]; - index[1] = tag[1]; - index[2] = tag[2]; - index[3] = tag[3]; - host_writed(index+4, flags); - host_writed(index+8, pos); - host_writed(index+12, size); +void HW_Register(HWBlock * block) { + block->next=firsthw; + firsthw=block; } -#endif -#if (C_SSHOT) -static void CAPTURE_VideoEvent(bool pressed) { - if (!pressed) - return; - if (CaptureState & CAPTURE_VIDEO) { - /* Close the video */ - CaptureState &= ~CAPTURE_VIDEO; - LOG_MSG("Stopped capturing video."); - Bit8u avi_header[AVI_HEADER_SIZE]; - Bitu main_list; - Bitu header_pos=0; -#define AVIOUT4(_S_) memcpy(&avi_header[header_pos],_S_,4);header_pos+=4; -#define AVIOUTw(_S_) host_writew(&avi_header[header_pos], _S_);header_pos+=2; -#define AVIOUTd(_S_) host_writed(&avi_header[header_pos], _S_);header_pos+=4; - /* Try and write an avi header */ - AVIOUT4("RIFF"); // Riff header - AVIOUTd(AVI_HEADER_SIZE + capture.video.written - 8 + capture.video.indexused); - AVIOUT4("AVI "); - AVIOUT4("LIST"); // List header - main_list = header_pos; - AVIOUTd(0); // TODO size of list - AVIOUT4("hdrl"); +void HWSET::Run(void) { + /* Hopefull enough space */ + char buf[1024]; - AVIOUT4("avih"); - AVIOUTd(56); /* # of bytes to follow */ - AVIOUTd((Bit32u)(1000000 / capture.video.fps)); /* Microseconds per frame */ - AVIOUTd(0); - AVIOUTd(0); /* PaddingGranularity (whatever that might be) */ - AVIOUTd(0x110); /* Flags,0x10 has index, 0x100 interleaved */ - AVIOUTd(capture.video.frames); /* TotalFrames */ - AVIOUTd(0); /* InitialFrames */ - AVIOUTd(2); /* Stream count */ - AVIOUTd(0); /* SuggestedBufferSize */ - AVIOUTd(capture.video.width); /* Width */ - AVIOUTd(capture.video.height); /* Height */ - AVIOUTd(0); /* TimeScale: Unit used to measure time */ - AVIOUTd(0); /* DataRate: Data rate of playback */ - AVIOUTd(0); /* StartTime: Starting time of AVI data */ - AVIOUTd(0); /* DataLength: Size of AVI data chunk */ - - /* Video stream list */ - AVIOUT4("LIST"); - AVIOUTd(4 + 8 + 56 + 8 + 40); /* Size of the list */ - AVIOUT4("strl"); - /* video stream header */ - AVIOUT4("strh"); - AVIOUTd(56); /* # of bytes to follow */ - AVIOUT4("vids"); /* Type */ - AVIOUT4(CODEC_4CC); /* Handler */ - AVIOUTd(0); /* Flags */ - AVIOUTd(0); /* Reserved, MS says: wPriority, wLanguage */ - AVIOUTd(0); /* InitialFrames */ - AVIOUTd(1000000); /* Scale */ - AVIOUTd((Bit32u)(1000000 * capture.video.fps)); /* Rate: Rate/Scale == samples/second */ - AVIOUTd(0); /* Start */ - AVIOUTd(capture.video.frames); /* Length */ - AVIOUTd(0); /* SuggestedBufferSize */ - AVIOUTd(~0); /* Quality */ - AVIOUTd(0); /* SampleSize */ - AVIOUTd(0); /* Frame */ - AVIOUTd(0); /* Frame */ - /* The video stream format */ - AVIOUT4("strf"); - AVIOUTd(40); /* # of bytes to follow */ - AVIOUTd(40); /* Size */ - AVIOUTd(capture.video.width); /* Width */ - AVIOUTd(capture.video.height); /* Height */ -// OUTSHRT(1); OUTSHRT(24); /* Planes, Count */ - AVIOUTd(0); - AVIOUT4(CODEC_4CC); /* Compression */ - AVIOUTd(capture.video.width * capture.video.height*4); /* SizeImage (in bytes?) */ - AVIOUTd(0); /* XPelsPerMeter */ - AVIOUTd(0); /* YPelsPerMeter */ - AVIOUTd(0); /* ClrUsed: Number of colors used */ - AVIOUTd(0); /* ClrImportant: Number of colors important */ - - /* Audio stream list */ - AVIOUT4("LIST"); - AVIOUTd(4 + 8 + 56 + 8 + 16); /* Length of list in bytes */ - AVIOUT4("strl"); - /* The audio stream header */ - AVIOUT4("strh"); - AVIOUTd(56); /* # of bytes to follow */ - AVIOUT4("auds"); - AVIOUTd(0); /* Format (Optionally) */ - AVIOUTd(0); /* Flags */ - AVIOUTd(0); /* Reserved, MS says: wPriority, wLanguage */ - AVIOUTd(0); /* InitialFrames */ - AVIOUTd(4); /* Scale */ - AVIOUTd(capture.video.audiorate*4); /* Rate, actual rate is scale/rate */ - AVIOUTd(0); /* Start */ - if (!capture.video.audiorate) - capture.video.audiorate = 1; - AVIOUTd(capture.video.audiowritten/4); /* Length */ - AVIOUTd(0); /* SuggestedBufferSize */ - AVIOUTd(~0); /* Quality */ - AVIOUTd(4); /* SampleSize */ - AVIOUTd(0); /* Frame */ - AVIOUTd(0); /* Frame */ - /* The audio stream format */ - AVIOUT4("strf"); - AVIOUTd(16); /* # of bytes to follow */ - AVIOUTw(1); /* Format, WAVE_ZMBV_FORMAT_PCM */ - AVIOUTw(2); /* Number of channels */ - AVIOUTd(capture.video.audiorate); /* SamplesPerSec */ - AVIOUTd(capture.video.audiorate*4); /* AvgBytesPerSec*/ - AVIOUTw(4); /* BlockAlign */ - AVIOUTw(16); /* BitsPerSample */ - int nmain = header_pos - main_list - 4; - /* Finish stream list, i.e. put number of bytes in the list to proper pos */ - - int njunk = AVI_HEADER_SIZE - 8 - 12 - header_pos; - AVIOUT4("JUNK"); - AVIOUTd(njunk); - /* Fix the size of the main list */ - header_pos = main_list; - AVIOUTd(nmain); - header_pos = AVI_HEADER_SIZE - 12; - AVIOUT4("LIST"); - AVIOUTd(capture.video.written+4); /* Length of list in bytes */ - AVIOUT4("movi"); - /* First add the index table to the end */ - memcpy(capture.video.index, "idx1", 4); - host_writed( capture.video.index+4, capture.video.indexused - 8 ); - fwrite( capture.video.index, 1, capture.video.indexused, capture.video.handle); - fseek(capture.video.handle, 0, SEEK_SET); - fwrite(&avi_header, 1, AVI_HEADER_SIZE, capture.video.handle); - fclose( capture.video.handle ); - free( capture.video.index ); - free( capture.video.buf ); - delete capture.video.codec; - capture.video.handle = 0; - } else { - CaptureState |= CAPTURE_VIDEO; - } -} -#endif - -void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags, float fps, Bit8u * data, Bit8u * pal) { -#if (C_SSHOT) - Bitu i; - Bit8u doubleRow[SCALER_MAXWIDTH*4]; - Bitu countWidth = width; - - if (flags & CAPTURE_FLAG_DBLH) - height *= 2; - if (flags & CAPTURE_FLAG_DBLW) - width *= 2; - - if (height > SCALER_MAXHEIGHT) - return; - if (width > SCALER_MAXWIDTH) - return; - - if (CaptureState & CAPTURE_IMAGE) { - png_structp png_ptr; - png_infop info_ptr; - png_color palette[256]; - - CaptureState &= ~CAPTURE_IMAGE; - /* Open the actual file */ - FILE * fp=OpenCaptureFile("Screenshot",".png"); - if (!fp) goto skip_shot; - /* First try to alloacte the png structures */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL); - if (!png_ptr) goto skip_shot; - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_write_struct(&png_ptr,(png_infopp)NULL); - goto skip_shot; - } - - /* Finalize the initing of png library */ - png_init_io(png_ptr, fp); - png_set_compression_level(png_ptr,Z_BEST_COMPRESSION); - - /* set other zlib parameters */ - png_set_compression_mem_level(png_ptr, 8); - png_set_compression_strategy(png_ptr,Z_DEFAULT_STRATEGY); - png_set_compression_window_bits(png_ptr, 15); - png_set_compression_method(png_ptr, 8); - png_set_compression_buffer_size(png_ptr, 8192); - - if (bpp==8) { - png_set_IHDR(png_ptr, info_ptr, width, height, - 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - for (i=0;i<256;i++) { - palette[i].red=pal[i*4+0]; - palette[i].green=pal[i*4+1]; - palette[i].blue=pal[i*4+2]; - } - png_set_PLTE(png_ptr, info_ptr, palette,256); - } else { - png_set_bgr( png_ptr ); - png_set_IHDR(png_ptr, info_ptr, width, height, - 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - } - png_write_info(png_ptr, info_ptr); - for (i=0;i> 1)*pitch); - else - srcLine=(data+(i >> 0)*pitch); - rowPointer=srcLine; - switch (bpp) { - case 8: - if (flags & CAPTURE_FLAG_DBLW) { - for (Bitu x=0;x> 2; - doubleRow[x*6+1] = doubleRow[x*6+4] = ((pixel& 0x03e0) * 0x21) >> 7; - doubleRow[x*6+2] = doubleRow[x*6+5] = ((pixel& 0x7c00) * 0x21) >> 12; - } - } else { - for (Bitu x=0;x> 2; - doubleRow[x*3+1] = ((pixel& 0x03e0) * 0x21) >> 7; - doubleRow[x*3+2] = ((pixel& 0x7c00) * 0x21) >> 12; - } - } - rowPointer = doubleRow; - break; - case 16: - if (flags & CAPTURE_FLAG_DBLW) { - for (Bitu x=0;x> 2; - doubleRow[x*6+1] = doubleRow[x*6+4] = ((pixel& 0x07e0) * 0x41) >> 9; - doubleRow[x*6+2] = doubleRow[x*6+5] = ((pixel& 0xf800) * 0x21) >> 13; - } - } else { - for (Bitu x=0;x> 2; - doubleRow[x*3+1] = ((pixel& 0x07e0) * 0x41) >> 9; - doubleRow[x*3+2] = ((pixel& 0xf800) * 0x21) >> 13; - } - } - rowPointer = doubleRow; - break; - case 32: - if (flags & CAPTURE_FLAG_DBLW) { - for (Bitu x=0;xSetupCompress( width, height)) - goto skip_video; - capture.video.bufSize = capture.video.codec->NeededSize(width, height, format); - capture.video.buf = malloc( capture.video.bufSize ); - if (!capture.video.buf) - goto skip_video; - capture.video.index = (Bit8u*)malloc( 16*4096 ); - if (!capture.video.buf) - goto skip_video; - capture.video.indexsize = 16*4096; - capture.video.indexused = 8; - - capture.video.width = width; - capture.video.height = height; - capture.video.bpp = bpp; - capture.video.fps = fps; - for (i=0;iPrepareCompressFrame( codecFlags, format, (char *)pal, capture.video.buf, capture.video.bufSize)) - goto skip_video; - - for (i=0;i> 1; - if (flags & CAPTURE_FLAG_DBLH) - srcLine=(data+(i >> 1)*pitch); - else - srcLine=(data+(i >> 0)*pitch); - switch ( bpp) { - case 8: - for (x=0;xcmd_line) { + /* No command line given give overview of hardware */ + loopblock=firsthw; + WriteOut("ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿"); + WriteOut("³Device ³Full Name ³Status ³"); + WriteOut("ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´"); + while (loopblock) { + if (loopblock->show_status) { + loopblock->show_status(buf); } else { - if (flags & CAPTURE_FLAG_DBLH) - rowPointer=(data+(i >> 1)*pitch); - else - rowPointer=(data+(i >> 0)*pitch); + strcpy(buf,"No Status Handler"); } - capture.video.codec->CompressLines( 1, &rowPointer ); + WriteOut("³%-8s³%-25s³%-43s³",loopblock->dev_name,loopblock->full_name,buf); + loopblock=loopblock->next; } - int written = capture.video.codec->FinishCompressFrame(); - if (written < 0) - goto skip_video; - CAPTURE_AddAviChunk( "00dc", written, capture.video.buf, codecFlags & 1 ? 0x10 : 0x0); - capture.video.frames++; -// LOG_MSG("Frame %d video %d audio %d",capture.video.frames, written, capture.video.audioused *4 ); - if ( capture.video.audioused ) { - CAPTURE_AddAviChunk( "01wb", capture.video.audioused * 4, capture.video.audiobuf, 0); - capture.video.audiowritten = capture.video.audioused*4; - capture.video.audioused = 0; - } - - /* Everything went okay, set flag again for next frame */ - CaptureState |= CAPTURE_VIDEO; + WriteOut("ÀÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ"); + WriteOut("If you want to setup specific hardware use \"HWSET Device\" for information.\n"); + return; + } + /* Command line given */ + if (strcmp(prog_info->cmd_line,"/?")==0) { + WriteOut("Hardware setup tool for DOSBox.\n"); + WriteOut("This program can be used to change the settings of internal hardware.\n\n" + "HWSET [device] [switches]\n\n" + "Using an empty command line gives you a list of hardware.\n" + "You can get list of switches for a device with HWSET device.\n" + ); + return; + } + char * rest=strchr(prog_info->cmd_line,' '); + if (rest) *rest++=0; + loopblock=firsthw; + while (loopblock) { + if (strcasecmp(loopblock->dev_name,prog_info->cmd_line)==0) goto founddev; + loopblock=loopblock->next; + } + WriteOut("Device %s not found\n",prog_info->cmd_line); + return; +founddev: +/* Check for rest of line */ + if (rest) { + strcpy(buf,rest); + loopblock->get_input(buf); + WriteOut(buf); + + } else { + WriteOut("Command overview for %s\n%s",loopblock->full_name,loopblock->help); } -skip_video: -#endif return; } - -#if (C_SSHOT) -static void CAPTURE_ScreenShotEvent(bool pressed) { - if (!pressed) - return; - CaptureState |= CAPTURE_IMAGE; +static void HWSET_ProgramStart(PROGRAM_Info * info) { + HWSET * tempHWSET=new HWSET(info); + tempHWSET->Run(); + delete tempHWSET; } -#endif -/* WAV capturing */ -static Bit8u wavheader[]={ - 'R','I','F','F', 0x0,0x0,0x0,0x0, /* Bit32u Riff Chunk ID / Bit32u riff size */ - 'W','A','V','E', 'f','m','t',' ', /* Bit32u Riff Format / Bit32u fmt chunk id */ - 0x10,0x0,0x0,0x0, 0x1,0x0,0x2,0x0, /* Bit32u fmt size / Bit16u encoding/ Bit16u channels */ - 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, /* Bit32u freq / Bit32u byterate */ - 0x4,0x0,0x10,0x0, 'd','a','t','a', /* Bit16u byte-block / Bit16u bits / Bit16u data chunk id */ - 0x0,0x0,0x0,0x0, /* Bit32u data size */ + +void HARDWARE_Init(void) { + PROGRAMS_MakeFile("HWSET.COM",HWSET_ProgramStart); + }; -void CAPTURE_AddWave(Bit32u freq, Bit32u len, Bit16s * data) { -#if (C_SSHOT) - if (CaptureState & CAPTURE_VIDEO) { - Bitu left = WAVE_BUF - capture.video.audioused; - if (left > len) - left = len; - memcpy( &capture.video.audiobuf[capture.video.audioused], data, left*4); - capture.video.audioused += left; - capture.video.audiorate = freq; - } -#endif - if (CaptureState & CAPTURE_WAVE) { - if (!capture.wave.handle) { - capture.wave.handle=OpenCaptureFile("Wave Output",".wav"); - if (!capture.wave.handle) { - CaptureState &= ~CAPTURE_WAVE; - return; - } - capture.wave.length = 0; - capture.wave.used = 0; - capture.wave.freq = freq; - fwrite(wavheader,1,sizeof(wavheader),capture.wave.handle); - } - Bit16s * read = data; - while (len > 0 ) { - Bitu left = WAVE_BUF - capture.wave.used; - if (!left) { - fwrite(capture.wave.buf,1,4*WAVE_BUF,capture.wave.handle); - capture.wave.length += 4*WAVE_BUF; - capture.wave.used = 0; - left = WAVE_BUF; - } - if (left > len) - left = len; - memcpy( &capture.wave.buf[capture.wave.used], read, left*4); - capture.wave.used += left; - read += left*2; - len -= left; - } - } -} -static void CAPTURE_WaveEvent(bool pressed) { - if (!pressed) - return; - /* Check for previously opened wave file */ - if (capture.wave.handle) { - LOG_MSG("Stopped capturing wave output."); - /* Write last piece of audio in buffer */ - fwrite(capture.wave.buf,1,capture.wave.used*4,capture.wave.handle); - capture.wave.length+=capture.wave.used*4; - /* Fill in the header with useful information */ - host_writed(&wavheader[0x04],capture.wave.length+sizeof(wavheader)-8); - host_writed(&wavheader[0x18],capture.wave.freq); - host_writed(&wavheader[0x1C],capture.wave.freq*4); - host_writed(&wavheader[0x28],capture.wave.length); - - fseek(capture.wave.handle,0,0); - fwrite(wavheader,1,sizeof(wavheader),capture.wave.handle); - fclose(capture.wave.handle); - capture.wave.handle=0; - CaptureState |= CAPTURE_WAVE; - } - CaptureState ^= CAPTURE_WAVE; -} - -/* MIDI capturing */ - -static Bit8u midi_header[]={ - 'M','T','h','d', /* Bit32u, Header Chunk */ - 0x0,0x0,0x0,0x6, /* Bit32u, Chunk Length */ - 0x0,0x0, /* Bit16u, Format, 0=single track */ - 0x0,0x1, /* Bit16u, Track Count, 1 track */ - 0x01,0xf4, /* Bit16u, Timing, 2 beats/second with 500 frames */ - 'M','T','r','k', /* Bit32u, Track Chunk */ - 0x0,0x0,0x0,0x0, /* Bit32u, Chunk Length */ - //Track data -}; - - -static void RawMidiAdd(Bit8u data) { - capture.midi.buffer[capture.midi.used++]=data; - if (capture.midi.used >= MIDI_BUF ) { - capture.midi.done += capture.midi.used; - fwrite(capture.midi.buffer,1,MIDI_BUF,capture.midi.handle); - capture.midi.used = 0; - } -} - -static void RawMidiAddNumber(Bit32u val) { - if (val & 0xfe00000) RawMidiAdd((Bit8u)(0x80|((val >> 21) & 0x7f))); - if (val & 0xfffc000) RawMidiAdd((Bit8u)(0x80|((val >> 14) & 0x7f))); - if (val & 0xfffff80) RawMidiAdd((Bit8u)(0x80|((val >> 7) & 0x7f))); - RawMidiAdd((Bit8u)(val & 0x7f)); -} - -void CAPTURE_AddMidi(bool sysex, Bitu len, Bit8u * data) { - if (!capture.midi.handle) { - capture.midi.handle=OpenCaptureFile("Raw Midi",".mid"); - if (!capture.midi.handle) { - return; - } - fwrite(midi_header,1,sizeof(midi_header),capture.midi.handle); - capture.midi.last=PIC_Ticks; - } - Bit32u delta=PIC_Ticks-capture.midi.last; - capture.midi.last=PIC_Ticks; - RawMidiAddNumber(delta); - if (sysex) { - RawMidiAdd( 0xf0 ); - RawMidiAddNumber( len ); - } - for (Bitu i=0;i> 24); - size[1]=(Bit8u)(capture.midi.done >> 16); - size[2]=(Bit8u)(capture.midi.done >> 8); - size[3]=(Bit8u)(capture.midi.done >> 0); - fwrite(&size,1,4,capture.midi.handle); - fclose(capture.midi.handle); - capture.midi.handle=0; - CaptureState &= ~CAPTURE_MIDI; - return; - } - CaptureState ^= CAPTURE_MIDI; - if (CaptureState & CAPTURE_MIDI) { - LOG_MSG("Preparing for raw midi capture, will start with first data."); - capture.midi.used=0; - capture.midi.done=0; - capture.midi.handle=0; - } else { - LOG_MSG("Stopped capturing raw midi before any data arrived."); - } -} - -class HARDWARE:public Module_base{ -public: - HARDWARE(Section* configuration):Module_base(configuration){ - Section_prop * section = static_cast(configuration); - Prop_path* proppath= section->Get_path("captures"); - capturedir = proppath->realpath; - CaptureState = 0; - MAPPER_AddHandler(CAPTURE_WaveEvent,MK_f6,MMOD1,"recwave","Rec Wave"); - MAPPER_AddHandler(CAPTURE_MidiEvent,MK_f8,MMOD1|MMOD2,"caprawmidi","Cap MIDI"); -#if (C_SSHOT) - MAPPER_AddHandler(CAPTURE_ScreenShotEvent,MK_f5,MMOD1,"scrshot","Screenshot"); - MAPPER_AddHandler(CAPTURE_VideoEvent,MK_f5,MMOD1|MMOD2,"video","Video"); -#endif - } - ~HARDWARE(){ - if (capture.wave.handle) CAPTURE_WaveEvent(true); - if (capture.midi.handle) CAPTURE_MidiEvent(true); - } -}; - -static HARDWARE* test; - -void HARDWARE_Destroy(Section * sec) { - delete test; -} - -void HARDWARE_Init(Section * sec) { - test = new HARDWARE(sec); - sec->AddDestroyFunction(&HARDWARE_Destroy,true); -} diff --git a/src/hardware/iohandler.cpp b/src/hardware/iohandler.cpp index 7fae817..242f6f0 100644 --- a/src/hardware/iohandler.cpp +++ b/src/hardware/iohandler.cpp @@ -1,439 +1,91 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: iohandler.cpp,v 1.29 2009/04/11 08:02:23 qbix79 Exp $ */ - -#include -#include "dosbox.h" -#include "inout.h" -#include "setup.h" -#include "cpu.h" -#include "../src/cpu/lazyflags.h" -#include "callback.h" - -IO_WriteHandler * io_writehandlers[3][IO_MAX]; -IO_ReadHandler * io_readhandlers[3][IO_MAX]; - -static Bitu IO_ReadBlocked(Bitu /*port*/,Bitu /*iolen*/) { - return ~0; -} - -static void IO_WriteBlocked(Bitu /*port*/,Bitu /*val*/,Bitu /*iolen*/) { -} - -static Bitu IO_ReadDefault(Bitu port,Bitu iolen) { - switch (iolen) { - case 1: - LOG(LOG_IO,LOG_WARN)("Read from port %04X",port); - io_readhandlers[0][port]=IO_ReadBlocked; - return 0xff; - case 2: - return - (io_readhandlers[0][port+0](port+0,1) << 0) | - (io_readhandlers[0][port+1](port+1,1) << 8); - case 4: - return - (io_readhandlers[1][port+0](port+0,2) << 0) | - (io_readhandlers[1][port+2](port+2,2) << 16); - } - return 0; -} - -void IO_WriteDefault(Bitu port,Bitu val,Bitu iolen) { - switch (iolen) { - case 1: - LOG(LOG_IO,LOG_WARN)("Writing %02X to port %04X",val,port); - io_writehandlers[0][port]=IO_WriteBlocked; - break; - case 2: - io_writehandlers[0][port+0](port+0,(val >> 0) & 0xff,1); - io_writehandlers[0][port+1](port+1,(val >> 8) & 0xff,1); - break; - case 4: - io_writehandlers[1][port+0](port+0,(val >> 0 ) & 0xffff,2); - io_writehandlers[1][port+2](port+2,(val >> 16) & 0xffff,2); - break; - } -} - -void IO_RegisterReadHandler(Bitu port,IO_ReadHandler * handler,Bitu mask,Bitu range) { - while (range--) { - if (mask&IO_MB) io_readhandlers[0][port]=handler; - if (mask&IO_MW) io_readhandlers[1][port]=handler; - if (mask&IO_MD) io_readhandlers[2][port]=handler; - port++; - } -} - -void IO_RegisterWriteHandler(Bitu port,IO_WriteHandler * handler,Bitu mask,Bitu range) { - while (range--) { - if (mask&IO_MB) io_writehandlers[0][port]=handler; - if (mask&IO_MW) io_writehandlers[1][port]=handler; - if (mask&IO_MD) io_writehandlers[2][port]=handler; - port++; - } -} - -void IO_FreeReadHandler(Bitu port,Bitu mask,Bitu range) { - while (range--) { - if (mask&IO_MB) io_readhandlers[0][port]=IO_ReadDefault; - if (mask&IO_MW) io_readhandlers[1][port]=IO_ReadDefault; - if (mask&IO_MD) io_readhandlers[2][port]=IO_ReadDefault; - port++; - } -} - -void IO_FreeWriteHandler(Bitu port,Bitu mask,Bitu range) { - while (range--) { - if (mask&IO_MB) io_writehandlers[0][port]=IO_WriteDefault; - if (mask&IO_MW) io_writehandlers[1][port]=IO_WriteDefault; - if (mask&IO_MD) io_writehandlers[2][port]=IO_WriteDefault; - port++; - } -} - -void IO_ReadHandleObject::Install(Bitu port,IO_ReadHandler * handler,Bitu mask,Bitu range) { - if(!installed) { - installed=true; - m_port=port; - m_mask=mask; - m_range=range; - IO_RegisterReadHandler(port,handler,mask,range); - } else E_Exit("IO_readHandler allready installed port %x",port); -} - -IO_ReadHandleObject::~IO_ReadHandleObject(){ - if(!installed) return; - IO_FreeReadHandler(m_port,m_mask,m_range); -} - -void IO_WriteHandleObject::Install(Bitu port,IO_WriteHandler * handler,Bitu mask,Bitu range) { - if(!installed) { - installed=true; - m_port=port; - m_mask=mask; - m_range=range; - IO_RegisterWriteHandler(port,handler,mask,range); - } else E_Exit("IO_writeHandler allready installed port %x",port); -} - -IO_WriteHandleObject::~IO_WriteHandleObject(){ - if(!installed) return; - IO_FreeWriteHandler(m_port,m_mask,m_range); - //LOG_MSG("FreeWritehandler called with port %X",m_port); -} - -struct IOF_Entry { - Bitu cs; - Bitu eip; -}; - -#define IOF_QUEUESIZE 16 -static struct { - Bitu used; - IOF_Entry entries[IOF_QUEUESIZE]; -} iof_queue; - -static Bits IOFaultCore(void) { - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=1; - Bits ret=CPU_Core_Full_Run(); - CPU_CycleLeft+=CPU_Cycles; - if (ret<0) E_Exit("Got a dosbox close machine in IO-fault core?"); - if (ret) - return ret; - if (!iof_queue.used) E_Exit("IO-faul Core without IO-faul"); - IOF_Entry * entry=&iof_queue.entries[iof_queue.used-1]; - if (entry->cs == SegValue(cs) && entry->eip==reg_eip) - return -1; - return 0; -} - - -/* Some code to make io operations take some virtual time. Helps certain - * games with their timing of certain operations - */ - - -#define IODELAY_READ_MICROS 1.0 -#define IODELAY_WRITE_MICROS 0.75 - -inline void IO_USEC_read_delay_old() { - if(CPU_CycleMax > static_cast((IODELAY_READ_MICROS*1000.0))) { - // this could be calculated whenever CPU_CycleMax changes - Bits delaycyc = static_cast((CPU_CycleMax/1000)*IODELAY_READ_MICROS); - if(CPU_Cycles > delaycyc) CPU_Cycles -= delaycyc; - else CPU_Cycles = 0; - } -} - -inline void IO_USEC_write_delay_old() { - if(CPU_CycleMax > static_cast((IODELAY_WRITE_MICROS*1000.0))) { - // this could be calculated whenever CPU_CycleMax changes - Bits delaycyc = static_cast((CPU_CycleMax/1000)*IODELAY_WRITE_MICROS); - if(CPU_Cycles > delaycyc) CPU_Cycles -= delaycyc; - else CPU_Cycles = 0; - } -} - - -#define IODELAY_READ_MICROSk (Bit32u)(1024/1.0) -#define IODELAY_WRITE_MICROSk (Bit32u)(1024/0.75) - -inline void IO_USEC_read_delay() { - Bits delaycyc = CPU_CycleMax/IODELAY_READ_MICROSk; - if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc = 0; //Else port acces will set cycles to 0. which might trigger problem with games which read 16 bit values - CPU_Cycles -= delaycyc; - CPU_IODelayRemoved += delaycyc; -} - -inline void IO_USEC_write_delay() { - Bits delaycyc = CPU_CycleMax/IODELAY_WRITE_MICROSk; - if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc=0; - CPU_Cycles -= delaycyc; - CPU_IODelayRemoved += delaycyc; -} - - -void IO_WriteB(Bitu port,Bitu val) { - if (GCC_UNLIKELY(GETFLAG(VM) && (CPU_IO_Exception(port,1)))) { - LazyFlags old_lflags; - memcpy(&old_lflags,&lflags,sizeof(LazyFlags)); - CPU_Decoder * old_cpudecoder; - old_cpudecoder=cpudecoder; - cpudecoder=&IOFaultCore; - IOF_Entry * entry=&iof_queue.entries[iof_queue.used++]; - entry->cs=SegValue(cs); - entry->eip=reg_eip; - CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip); - Bit8u old_al = reg_al; - Bit16u old_dx = reg_dx; - reg_al = val; - reg_dx = port; - RealPt icb = CALLBACK_RealPointer(call_priv_io); - SegSet16(cs,RealSeg(icb)); - reg_eip = RealOff(icb)+0x08; - CPU_Exception(cpu.exception.which,cpu.exception.error); - - DOSBOX_RunMachine(); - iof_queue.used--; - - reg_al = old_al; - reg_dx = old_dx; - memcpy(&lflags,&old_lflags,sizeof(LazyFlags)); - cpudecoder=old_cpudecoder; - } - else { - IO_USEC_write_delay(); - io_writehandlers[0][port](port,val,1); - } -} - -void IO_WriteW(Bitu port,Bitu val) { - if (GCC_UNLIKELY(GETFLAG(VM) && (CPU_IO_Exception(port,2)))) { - LazyFlags old_lflags; - memcpy(&old_lflags,&lflags,sizeof(LazyFlags)); - CPU_Decoder * old_cpudecoder; - old_cpudecoder=cpudecoder; - cpudecoder=&IOFaultCore; - IOF_Entry * entry=&iof_queue.entries[iof_queue.used++]; - entry->cs=SegValue(cs); - entry->eip=reg_eip; - CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip); - Bit16u old_ax = reg_ax; - Bit16u old_dx = reg_dx; - reg_al = val; - reg_dx = port; - RealPt icb = CALLBACK_RealPointer(call_priv_io); - SegSet16(cs,RealSeg(icb)); - reg_eip = RealOff(icb)+0x0a; - CPU_Exception(cpu.exception.which,cpu.exception.error); - - DOSBOX_RunMachine(); - iof_queue.used--; - - reg_ax = old_ax; - reg_dx = old_dx; - memcpy(&lflags,&old_lflags,sizeof(LazyFlags)); - cpudecoder=old_cpudecoder; - } - else { - IO_USEC_write_delay(); - io_writehandlers[1][port](port,val,2); - } -} - -void IO_WriteD(Bitu port,Bitu val) { - if (GCC_UNLIKELY(GETFLAG(VM) && (CPU_IO_Exception(port,4)))) { - LazyFlags old_lflags; - memcpy(&old_lflags,&lflags,sizeof(LazyFlags)); - CPU_Decoder * old_cpudecoder; - old_cpudecoder=cpudecoder; - cpudecoder=&IOFaultCore; - IOF_Entry * entry=&iof_queue.entries[iof_queue.used++]; - entry->cs=SegValue(cs); - entry->eip=reg_eip; - CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip); - Bit32u old_eax = reg_eax; - Bit16u old_dx = reg_dx; - reg_al = val; - reg_dx = port; - RealPt icb = CALLBACK_RealPointer(call_priv_io); - SegSet16(cs,RealSeg(icb)); - reg_eip = RealOff(icb)+0x0c; - CPU_Exception(cpu.exception.which,cpu.exception.error); - - DOSBOX_RunMachine(); - iof_queue.used--; - - reg_eax = old_eax; - reg_dx = old_dx; - memcpy(&lflags,&old_lflags,sizeof(LazyFlags)); - cpudecoder=old_cpudecoder; - } - else io_writehandlers[2][port](port,val,4); -} - -Bitu IO_ReadB(Bitu port) { - if (GCC_UNLIKELY(GETFLAG(VM) && (CPU_IO_Exception(port,1)))) { - LazyFlags old_lflags; - memcpy(&old_lflags,&lflags,sizeof(LazyFlags)); - CPU_Decoder * old_cpudecoder; - old_cpudecoder=cpudecoder; - cpudecoder=&IOFaultCore; - IOF_Entry * entry=&iof_queue.entries[iof_queue.used++]; - entry->cs=SegValue(cs); - entry->eip=reg_eip; - CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip); - Bit16u old_dx = reg_dx; - reg_dx = port; - RealPt icb = CALLBACK_RealPointer(call_priv_io); - SegSet16(cs,RealSeg(icb)); - reg_eip = RealOff(icb)+0x00; - CPU_Exception(cpu.exception.which,cpu.exception.error); - - DOSBOX_RunMachine(); - iof_queue.used--; - - Bitu retval = reg_al; - - reg_dx = old_dx; - memcpy(&lflags,&old_lflags,sizeof(LazyFlags)); - cpudecoder=old_cpudecoder; - return retval; - } - else { - IO_USEC_read_delay(); - return io_readhandlers[0][port](port,1); - } -} - -Bitu IO_ReadW(Bitu port) { - if (GCC_UNLIKELY(GETFLAG(VM) && (CPU_IO_Exception(port,2)))) { - LazyFlags old_lflags; - memcpy(&old_lflags,&lflags,sizeof(LazyFlags)); - CPU_Decoder * old_cpudecoder; - old_cpudecoder=cpudecoder; - cpudecoder=&IOFaultCore; - IOF_Entry * entry=&iof_queue.entries[iof_queue.used++]; - entry->cs=SegValue(cs); - entry->eip=reg_eip; - CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip); - Bit16u old_dx = reg_dx; - reg_dx = port; - RealPt icb = CALLBACK_RealPointer(call_priv_io); - SegSet16(cs,RealSeg(icb)); - reg_eip = RealOff(icb)+0x02; - CPU_Exception(cpu.exception.which,cpu.exception.error); - - DOSBOX_RunMachine(); - iof_queue.used--; - - Bitu retval = reg_ax; - - reg_dx = old_dx; - memcpy(&lflags,&old_lflags,sizeof(LazyFlags)); - cpudecoder=old_cpudecoder; - return retval; - } - else { - IO_USEC_read_delay(); - return io_readhandlers[1][port](port,2); - } -} - -Bitu IO_ReadD(Bitu port) { - if (GCC_UNLIKELY(GETFLAG(VM) && (CPU_IO_Exception(port,4)))) { - LazyFlags old_lflags; - memcpy(&old_lflags,&lflags,sizeof(LazyFlags)); - CPU_Decoder * old_cpudecoder; - old_cpudecoder=cpudecoder; - cpudecoder=&IOFaultCore; - IOF_Entry * entry=&iof_queue.entries[iof_queue.used++]; - entry->cs=SegValue(cs); - entry->eip=reg_eip; - CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip); - Bit16u old_dx = reg_dx; - reg_dx = port; - RealPt icb = CALLBACK_RealPointer(call_priv_io); - SegSet16(cs,RealSeg(icb)); - reg_eip = RealOff(icb)+0x04; - CPU_Exception(cpu.exception.which,cpu.exception.error); - - DOSBOX_RunMachine(); - iof_queue.used--; - - Bitu retval = reg_eax; - - reg_dx = old_dx; - memcpy(&lflags,&old_lflags,sizeof(LazyFlags)); - cpudecoder=old_cpudecoder; - return retval; - } - else return io_readhandlers[2][port](port,4); -} - -class IO :public Module_base { -public: - IO(Section* configuration):Module_base(configuration){ - iof_queue.used=0; - IO_FreeReadHandler(0,IO_MA,IO_MAX); - IO_FreeWriteHandler(0,IO_MA,IO_MAX); - } - ~IO() - { - //Same as the constructor ? - } -}; - -static IO* test; - -void IO_Destroy(Section*) { - delete test; -} - -void IO_Init(Section * sect) { - test = new IO(sect); - sect->AddDestroyFunction(&IO_Destroy); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "inout.h" + +IO_ReadBlock IO_ReadTable[IO_MAX]; +IO_WriteBlock IO_WriteTable[IO_MAX]; + +void IO_Write(Bitu num,Bit8u val) { + if (num -#include -#include -#include "cross.h" -#include "support.h" -#include "cpu.h" -#include "regs.h" -#include "inout.h" -#include "setup.h" -#include "debug.h" -#include "callback.h" -#include "dos_system.h" -#include "mem.h" -#include "ipx.h" -#include "ipxserver.h" -#include "timer.h" -#include "SDL_net.h" -#include "programs.h" -#include "pic.h" - -#define SOCKTABLESIZE 150 // DOS IPX driver was limited to 150 open sockets - -struct ipxnetaddr { - Uint8 netnum[4]; // Both are big endian - Uint8 netnode[6]; -} localIpxAddr; - -Bit32u udpPort; -bool isIpxServer; -bool isIpxConnected; -IPaddress ipxServConnIp; // IPAddress for client connection to server -UDPsocket ipxClientSocket; -int UDPChannel; // Channel used by UDP connection -Bit8u recvBuffer[IPXBUFFERSIZE]; // Incoming packet buffer - -static RealPt ipx_callback; - -SDLNet_SocketSet clientSocketSet; - -packetBuffer incomingPacket; - -static Bit16u socketCount; -static Bit16u opensockets[SOCKTABLESIZE]; - -static Bit16u swapByte(Bit16u sockNum) { - return (((sockNum>> 8)) | (sockNum << 8)); -} - -void UnpackIP(PackedIP ipPack, IPaddress * ipAddr) { - ipAddr->host = ipPack.host; - ipAddr->port = ipPack.port; -} - -void PackIP(IPaddress ipAddr, PackedIP *ipPack) { - ipPack->host = ipAddr.host; - ipPack->port = ipAddr.port; -} - -ECBClass *ECBList; // Linked list of ECB's -ECBClass* ESRList; // ECBs waiting to be ESR notified - -#ifdef IPX_DEBUGMSG -Bitu ECBSerialNumber = 0; -Bitu ECBAmount = 0; -#endif - - -ECBClass::ECBClass(Bit16u segment, Bit16u offset) { - ECBAddr = RealMake(segment, offset); - databuffer = 0; - -#ifdef IPX_DEBUGMSG - SerialNumber = ECBSerialNumber; - ECBSerialNumber++; - ECBAmount++; - - LOG_IPX("ECB: SN%7d created. Number of ECBs: %3d, ESR %4x:%4x, ECB %4x:%4x", - SerialNumber,ECBAmount, - real_readw(RealSeg(ECBAddr), - RealOff(ECBAddr)+6), - real_readw(RealSeg(ECBAddr), - RealOff(ECBAddr)+4),segment,offset); -#endif - isInESRList = false; - prevECB = NULL; - nextECB = NULL; - - if (ECBList == NULL) - ECBList = this; - else { - // Transverse the list until we hit the end - ECBClass *useECB = ECBList; - - while(useECB->nextECB != NULL) - useECB = useECB->nextECB; - - useECB->nextECB = this; - this->prevECB = useECB; - } - - iuflag = getInUseFlag(); - mysocket = getSocket(); -} -void ECBClass::writeDataBuffer(Bit8u* buffer, Bit16u length) { - if(databuffer!=0) delete [] databuffer; - databuffer = new Bit8u[length]; - memcpy(databuffer,buffer,length); - buflen=length; - -} -bool ECBClass::writeData() { - Bitu length=buflen; - Bit8u* buffer = databuffer; - fragmentDescriptor tmpFrag; - setInUseFlag(USEFLAG_AVAILABLE); - Bitu fragCount = getFragCount(); - Bitu bufoffset = 0; - for(Bitu i = 0;i < fragCount;i++) { - getFragDesc(i,&tmpFrag); - for(Bitu t = 0;t < tmpFrag.size;t++) { - real_writeb(tmpFrag.segment, tmpFrag.offset + t, buffer[bufoffset]); - bufoffset++; - if(bufoffset >= length) { - setCompletionFlag(COMP_SUCCESS); - setImmAddress(&buffer[22]); // Write in source node - return true; - } - } - } - if(bufoffset < length) { - setCompletionFlag(COMP_MALFORMED); - return false; - } - return false; -} - -Bit16u ECBClass::getSocket(void) { - return swapByte(real_readw(RealSeg(ECBAddr), RealOff(ECBAddr) + 0xa)); -} - -Bit8u ECBClass::getInUseFlag(void) { - return real_readb(RealSeg(ECBAddr), RealOff(ECBAddr) + 0x8); -} - -void ECBClass::setInUseFlag(Bit8u flagval) { - iuflag = flagval; - real_writeb(RealSeg(ECBAddr), RealOff(ECBAddr) + 0x8, flagval); -} - -void ECBClass::setCompletionFlag(Bit8u flagval) { - real_writeb(RealSeg(ECBAddr), RealOff(ECBAddr) + 0x9, flagval); -} - -Bit16u ECBClass::getFragCount(void) { - return real_readw(RealSeg(ECBAddr), RealOff(ECBAddr) + 34); -} - -void ECBClass::getFragDesc(Bit16u descNum, fragmentDescriptor *fragDesc) { - Bit16u memoff = RealOff(ECBAddr) + 30 + ((descNum+1) * 6); - fragDesc->offset = real_readw(RealSeg(ECBAddr), memoff); - memoff += 2; - fragDesc->segment = real_readw(RealSeg(ECBAddr), memoff); - memoff += 2; - fragDesc->size = real_readw(RealSeg(ECBAddr), memoff); -} - -RealPt ECBClass::getESRAddr(void) { - return RealMake(real_readw(RealSeg(ECBAddr), - RealOff(ECBAddr)+6), - real_readw(RealSeg(ECBAddr), - RealOff(ECBAddr)+4)); -} - -void ECBClass::NotifyESR(void) { - Bit32u ESRval = real_readd(RealSeg(ECBAddr), RealOff(ECBAddr)+4); - if(ESRval || databuffer) { // databuffer: write data at realmode/v86 time - // LOG_IPX("ECB: SN%7d to be notified.", SerialNumber); - // take the ECB out of the current list - if(prevECB == NULL) { // was the first in the list - ECBList = nextECB; - if(ECBList != NULL) ECBList->prevECB = NULL; - } else { // not the first - prevECB->nextECB = nextECB; - if(nextECB != NULL) nextECB->prevECB = prevECB; - } - - nextECB = NULL; - // put it to the notification queue - if(ESRList==NULL) { - ESRList = this; - prevECB = NULL; - } else {// put to end of ESR list - ECBClass* useECB = ESRList; - - while(useECB->nextECB != NULL) - useECB = useECB->nextECB; - - useECB->nextECB = this; - prevECB = useECB; - } - isInESRList = true; - PIC_ActivateIRQ(11); - } - // this one does not want to be notified, delete it right away - else delete this; -} - -void ECBClass::setImmAddress(Bit8u *immAddr) { - for(Bitu i=0;i<6;i++) - real_writeb(RealSeg(ECBAddr), RealOff(ECBAddr)+28+i, immAddr[i]); -} - -void ECBClass::getImmAddress(Bit8u* immAddr) { - for(Bitu i=0;i<6;i++) - immAddr[i] = real_readb(RealSeg(ECBAddr), RealOff(ECBAddr)+28+i); -} - -ECBClass::~ECBClass() { -#ifdef IPX_DEBUGMSG - ECBAmount--; - LOG_IPX("ECB: SN%7d destroyed. Remaining ECBs: %3d", SerialNumber,ECBAmount); -#endif - - if(isInESRList) { - // in ESR list, always the first element is deleted. - ESRList=nextECB; - } else { - if(prevECB == NULL) { // was the first in the list - ECBList = nextECB; - if(ECBList != NULL) ECBList->prevECB = NULL; - } else { // not the first - prevECB->nextECB = nextECB; - if(nextECB != NULL) nextECB->prevECB = prevECB; - } - } - if(databuffer!=0) delete [] databuffer; -} - - - -static bool sockInUse(Bit16u sockNum) { - for(Bitu i=0;i= SOCKTABLESIZE) { - reg_al = 0xfe; // Socket table full - return; - } - - if(sockNum == 0x0000) { - // Dynamic socket allocation - sockAlloc = 0x4002; - while(sockInUse(sockAlloc) && (sockAlloc < 0x7fff)) sockAlloc++; - if(sockAlloc > 0x7fff) { - // I have no idea how this could happen if the IPX driver - // is limited to 150 open sockets at a time - LOG_MSG("IPX: Out of dynamic sockets"); - } - sockNum = sockAlloc; - } else { - if(sockInUse(sockNum)) { - reg_al = 0xff; // Socket already open - return; - } - } - - opensockets[socketCount] = sockNum; - socketCount++; - - reg_al = 0x00; // Success - reg_dx = swapByte(sockNum); // Convert back to big-endian -} - -static void CloseSocket(void) { - Bit16u sockNum, i; - ECBClass* tmpECB = ECBList; - ECBClass* tmp2ECB = ECBList; - - sockNum = swapByte(reg_dx); - if(!sockInUse(sockNum)) return; - - for(i=0;inextECB; - if(tmpECB->getSocket()==sockNum) { - tmpECB->setCompletionFlag(COMP_CANCELLED); - tmpECB->setInUseFlag(USEFLAG_AVAILABLE); - delete tmpECB; - } - tmpECB = tmp2ECB; - } -} - -//static RealPt IPXVERpointer; - -static bool IPX_Multiplex(void) { - if(reg_ax != 0x7a00) return false; - reg_al = 0xff; - SegSet16(es,RealSeg(ipx_callback)); - reg_di = RealOff(ipx_callback); - - //reg_bx = RealOff(IPXVERpointer); - //reg_cx = RealSeg(ipx_callback); - return true; -} - -static void IPX_AES_EventHandler(Bitu param) -{ - ECBClass* tmpECB = ECBList; - ECBClass* tmp2ECB; - while(tmpECB!=0) { - tmp2ECB = tmpECB->nextECB; - if(tmpECB->iuflag==USEFLAG_AESCOUNT && param==(Bitu)tmpECB->ECBAddr) { - tmpECB->setCompletionFlag(COMP_SUCCESS); - tmpECB->setInUseFlag(USEFLAG_AVAILABLE); - tmpECB->NotifyESR(); - // LOG_IPX("AES Notification: ECB S/N %d",tmpECB->SerialNumber); - return; - } - tmpECB = tmp2ECB; - } - LOG_MSG("!!!! Rouge AES !!!!" ); -} - -static void sendPacket(ECBClass* sendecb); - -static void handleIpxRequest(void) { - ECBClass *tmpECB; - - switch (reg_bx) { - case 0x0000: // Open socket - OpenSocket(); - LOG_IPX("IPX: Open socket %4x", swapByte(reg_dx)); - break; - case 0x0001: // Close socket - LOG_IPX("IPX: Close socket %4x", swapByte(reg_dx)); - CloseSocket(); - break; - case 0x0002: // get local target - // es:si - // Currently no support for multiple networks - - for(Bitu i = 0; i < 6; i++) - real_writeb(SegValue(es),reg_di+i,real_readb(SegValue(es),reg_si+i+4)); - - reg_cx=1; // time ticks expected - reg_al=0x00; //success - break; - - case 0x0003: // Send packet - tmpECB = new ECBClass(SegValue(es),reg_si); - if(!incomingPacket.connected) { - tmpECB->setInUseFlag(USEFLAG_AVAILABLE); - tmpECB->setCompletionFlag(COMP_UNDELIVERABLE); - delete tmpECB; // not notify? - reg_al = 0xff; // Failure - } else { - tmpECB->setInUseFlag(USEFLAG_SENDING); - //LOG_IPX("IPX: Sending packet on %4x", tmpECB->getSocket()); - reg_al = 0x00; // Success - sendPacket(tmpECB); - } - - break; - case 0x0004: // Listen for packet - tmpECB = new ECBClass(SegValue(es),reg_si); - // LOG_IPX("ECB: SN%7d RECEIVE.", tmpECB->SerialNumber); - if(!sockInUse(tmpECB->getSocket())) { // Socket is not open - reg_al = 0xff; - tmpECB->setInUseFlag(USEFLAG_AVAILABLE); - tmpECB->setCompletionFlag(COMP_HARDWAREERROR); - delete tmpECB; - } else { - reg_al = 0x00; // Success - tmpECB->setInUseFlag(USEFLAG_LISTENING); - /*LOG_IPX("IPX: Listen for packet on 0x%4x - ESR address %4x:%4x", - tmpECB->getSocket(), - RealSeg(tmpECB->getESRAddr()), - RealOff(tmpECB->getESRAddr()));*/ - } - break; - - case 0x0005: // SCHEDULE IPX EVENT - case 0x0007: // SCHEDULE SPECIAL IPX EVENT - { - tmpECB = new ECBClass(SegValue(es),reg_si); - // LOG_IPX("ECB: SN%7d AES. T=%fms.", tmpECB->SerialNumber, - // (1000.0f/(1193182.0f/65536.0f))*(float)reg_ax); - PIC_AddEvent(IPX_AES_EventHandler, - (1000.0f/(1193182.0f/65536.0f))*(float)reg_ax,(Bitu)tmpECB->ECBAddr); - tmpECB->setInUseFlag(USEFLAG_AESCOUNT); - break; - } - case 0x0006: // cancel operation - { - RealPt ecbaddress = RealMake(SegValue(es),reg_si); - ECBClass* tmpECB= ECBList; - ECBClass* tmp2ECB; - while(tmpECB) { - tmp2ECB=tmpECB->nextECB; - if(tmpECB->ECBAddr == ecbaddress) { - if(tmpECB->getInUseFlag()==USEFLAG_AESCOUNT) - PIC_RemoveSpecificEvents(IPX_AES_EventHandler,(Bitu)ecbaddress); - tmpECB->setInUseFlag(USEFLAG_AVAILABLE); - tmpECB->setCompletionFlag(COMP_CANCELLED); - delete tmpECB; - reg_al=0; // Success - LOG_IPX("IPX: ECB canceled."); - return; - } - tmpECB=tmp2ECB; - } - reg_al=0xff; // Fail - break; - } - case 0x0008: // Get interval marker - reg_ax = mem_readw(0x46c); // BIOS_TIMER - break; - case 0x0009: // Get internetwork address - { - LOG_IPX("IPX: Get internetwork address %2x:%2x:%2x:%2x:%2x:%2x", - localIpxAddr.netnode[5], localIpxAddr.netnode[4], - localIpxAddr.netnode[3], localIpxAddr.netnode[2], - localIpxAddr.netnode[1], localIpxAddr.netnode[0]); - - Bit8u * addrptr = (Bit8u *)&localIpxAddr; - for(Bit16u i=0;i<10;i++) - real_writeb(SegValue(es),reg_si+i,addrptr[i]); - break; - } - case 0x000a: // Relinquish control - break; // Idle thingy - - case 0x000b: // Disconnect from Target - break; // We don't even connect - - case 0x000d: // get packet size - reg_cx=0; // retry count - reg_ax=1024; // real implementation returns 1024 - break; - - case 0x0010: // SPX install check - reg_al=0; // SPX not installed - break; - - case 0x001a: // get driver maximum packet size - reg_cx=0; // retry count - reg_ax=IPXBUFFERSIZE; // max packet size: something near the - // ethernet packet size - break; - - default: - LOG_MSG("Unhandled IPX function: %4x", reg_bx); - break; - } -} - -// Entrypoint handler -Bitu IPX_Handler(void) { - handleIpxRequest(); - return CBRET_NONE; -} - -// INT 7A handler -Bitu IPX_IntHandler(void) { - handleIpxRequest(); - return CBRET_NONE; -} - -static void pingAck(IPaddress retAddr) { - IPXHeader regHeader; - UDPpacket regPacket; - Bits result; - - SDLNet_Write16(0xffff, regHeader.checkSum); - SDLNet_Write16(sizeof(regHeader), regHeader.length); - - SDLNet_Write32(0, regHeader.dest.network); - PackIP(retAddr, ®Header.dest.addr.byIP); - SDLNet_Write16(0x2, regHeader.dest.socket); - - SDLNet_Write32(0, regHeader.src.network); - memcpy(regHeader.src.addr.byNode.node, localIpxAddr.netnode, sizeof(regHeader.src.addr.byNode.node)); - SDLNet_Write16(0x2, regHeader.src.socket); - regHeader.transControl = 0; - regHeader.pType = 0x0; - - regPacket.data = (Uint8 *)®Header; - regPacket.len = sizeof(regHeader); - regPacket.maxlen = sizeof(regHeader); - regPacket.channel = UDPChannel; - - result = SDLNet_UDP_Send(ipxClientSocket, regPacket.channel, ®Packet); -} - -static void pingSend(void) { - IPXHeader regHeader; - UDPpacket regPacket; - Bits result; - - SDLNet_Write16(0xffff, regHeader.checkSum); - SDLNet_Write16(sizeof(regHeader), regHeader.length); - - SDLNet_Write32(0, regHeader.dest.network); - regHeader.dest.addr.byIP.host = 0xffffffff; - regHeader.dest.addr.byIP.port = 0xffff; - SDLNet_Write16(0x2, regHeader.dest.socket); - - SDLNet_Write32(0, regHeader.src.network); - memcpy(regHeader.src.addr.byNode.node, localIpxAddr.netnode, sizeof(regHeader.src.addr.byNode.node)); - SDLNet_Write16(0x2, regHeader.src.socket); - regHeader.transControl = 0; - regHeader.pType = 0x0; - - regPacket.data = (Uint8 *)®Header; - regPacket.len = sizeof(regHeader); - regPacket.maxlen = sizeof(regHeader); - regPacket.channel = UDPChannel; - - result = SDLNet_UDP_Send(ipxClientSocket, regPacket.channel, ®Packet); - if(!result) { - LOG_MSG("IPX: SDLNet_UDP_Send: %s\n", SDLNet_GetError()); - } -} - -static void receivePacket(Bit8u *buffer, Bit16s bufSize) { - ECBClass *useECB; - ECBClass *nextECB; - Bit16u *bufword = (Bit16u *)buffer; - Bit16u useSocket = swapByte(bufword[8]); - IPXHeader * tmpHeader; - tmpHeader = (IPXHeader *)buffer; - - // Check to see if ping packet - if(useSocket == 0x2) { - // Is this a broadcast? - if((tmpHeader->dest.addr.byIP.host == 0xffffffff) && - (tmpHeader->dest.addr.byIP.port == 0xffff)) { - // Yes. We should return the ping back to the sender - IPaddress tmpAddr; - UnpackIP(tmpHeader->src.addr.byIP, &tmpAddr); - pingAck(tmpAddr); - return; - } - } - - useECB = ECBList; - while(useECB != NULL) - { - nextECB = useECB->nextECB; - if(useECB->iuflag == USEFLAG_LISTENING && useECB->mysocket == useSocket) { - useECB->writeDataBuffer(buffer, bufSize); - useECB->NotifyESR(); - return; - } - useECB = nextECB; - } - LOG_IPX("IPX: RX Packet loss!"); -} - -static void IPX_ClientLoop(void) { - int numrecv; - UDPpacket inPacket; - inPacket.data = (Uint8 *)recvBuffer; - inPacket.maxlen = IPXBUFFERSIZE; - inPacket.channel = UDPChannel; - - // Its amazing how much simpler UDP is than TCP - numrecv = SDLNet_UDP_Recv(ipxClientSocket, &inPacket); - if(numrecv) receivePacket(inPacket.data, inPacket.len); -} - - -void DisconnectFromServer(bool unexpected) { - if(unexpected) LOG_MSG("IPX: Server disconnected unexpectedly"); - if(incomingPacket.connected) { - incomingPacket.connected = false; - TIMER_DelTickHandler(&IPX_ClientLoop); - SDLNet_UDP_Close(ipxClientSocket); - } -} - -static void sendPacket(ECBClass* sendecb) { - Bit8u outbuffer[IPXBUFFERSIZE]; - fragmentDescriptor tmpFrag; - Bit16u i, fragCount,t; - Bit16s packetsize; - Bit16u *wordptr; - Bits result; - UDPpacket outPacket; - - sendecb->setInUseFlag(USEFLAG_AVAILABLE); - packetsize = 0; - fragCount = sendecb->getFragCount(); - for(i=0;igetFragDesc(i,&tmpFrag); - if(i==0) { - // Fragment containing IPX header - // Must put source address into header - Bit8u * addrptr; - - // source netnum - addrptr = (Bit8u *)&localIpxAddr.netnum; - for(Bit16u m=0;m<4;m++) { - real_writeb(tmpFrag.segment,tmpFrag.offset+m+18,addrptr[m]); - } - // source node number - addrptr = (Bit8u *)&localIpxAddr.netnode; - for(Bit16u m=0;m<6;m++) { - real_writeb(tmpFrag.segment,tmpFrag.offset+m+22,addrptr[m]); - } - // Source socket - real_writew(tmpFrag.segment,tmpFrag.offset+28, swapByte(sendecb->getSocket())); - - // blank checksum - real_writew(tmpFrag.segment,tmpFrag.offset, 0xffff); - } - - for(t=0;t=IPXBUFFERSIZE) { - LOG_MSG("IPX: Packet size to be sent greater than %d bytes.", IPXBUFFERSIZE); - sendecb->setCompletionFlag(COMP_UNDELIVERABLE); - sendecb->NotifyESR(); - return; - } - } - } - - // Add length and source socket to IPX header - wordptr = (Bit16u *)&outbuffer[0]; - // Blank CRC - //wordptr[0] = 0xffff; - // Length - wordptr[1] = swapByte(packetsize); - // Source socket - //wordptr[14] = swapByte(sendecb->getSocket()); - - sendecb->getFragDesc(0,&tmpFrag); - real_writew(tmpFrag.segment,tmpFrag.offset+2, swapByte(packetsize)); - - - Bit8u immedAddr[6]; - sendecb->getImmAddress(immedAddr); - // filter out broadcasts and local loopbacks - // Real implementation uses the ImmedAddr to check wether this is a broadcast - - bool islocalbroadcast=true; - bool isloopback=true; - - Bit8u * addrptr; - - addrptr = (Bit8u *)&localIpxAddr.netnum; - for(Bitu m=0;m<4;m++) { - if(addrptr[m]!=outbuffer[m+0x6])isloopback=false; - } - addrptr = (Bit8u *)&localIpxAddr.netnode; - for(Bitu m=0;m<6;m++) { - if(addrptr[m]!=outbuffer[m+0xa])isloopback=false; - if(immedAddr[m]!=0xff) islocalbroadcast=false; - } - LOG_IPX("SEND crc:%2x",packetCRC(&outbuffer[0], packetsize)); - if(!isloopback) { - outPacket.channel = UDPChannel; - outPacket.data = (Uint8 *)&outbuffer[0]; - outPacket.len = packetsize; - outPacket.maxlen = packetsize; - // Since we're using a channel, we won't send the IP address again - result = SDLNet_UDP_Send(ipxClientSocket, UDPChannel, &outPacket); - - if(result == 0) { - LOG_MSG("IPX: Could not send packet: %s", SDLNet_GetError()); - sendecb->setCompletionFlag(COMP_HARDWAREERROR); - sendecb->NotifyESR(); - DisconnectFromServer(true); - return; - } else { - sendecb->setCompletionFlag(COMP_SUCCESS); - LOG_IPX("Packet sent: size: %d",packetsize); - } - } - else sendecb->setCompletionFlag(COMP_SUCCESS); - - if(isloopback||islocalbroadcast) { - // Send packet back to ourselves. - receivePacket(&outbuffer[0],packetsize); - LOG_IPX("Packet back: loopback:%d, broadcast:%d",isloopback,islocalbroadcast); - } - sendecb->NotifyESR(); -} - -static bool pingCheck(IPXHeader * outHeader) { - char buffer[1024]; - Bits result; - UDPpacket regPacket; - IPXHeader *regHeader; - regPacket.data = (Uint8 *)buffer; - regPacket.maxlen = sizeof(buffer); - regPacket.channel = UDPChannel; - regHeader = (IPXHeader *)buffer; - - result = SDLNet_UDP_Recv(ipxClientSocket, ®Packet); - if (result != 0) { - memcpy(outHeader, regHeader, sizeof(IPXHeader)); - return true; - } - return false; -} - -bool ConnectToServer(char const *strAddr) { - int numsent; - UDPpacket regPacket; - IPXHeader regHeader; - if(!SDLNet_ResolveHost(&ipxServConnIp, strAddr, (Bit16u)udpPort)) { - - // Generate the MAC address. This is made by zeroing out the first two - // octets and then using the actual IP address for the last 4 octets. - // This idea is from the IPX over IP implementation as specified in RFC 1234: - // http://www.faqs.org/rfcs/rfc1234.html - - // Select an anonymous UDP port - ipxClientSocket = SDLNet_UDP_Open(0); - if(ipxClientSocket) { - // Bind UDP port to address to channel - UDPChannel = SDLNet_UDP_Bind(ipxClientSocket,-1,&ipxServConnIp); - //ipxClientSocket = SDLNet_TCP_Open(&ipxServConnIp); - SDLNet_Write16(0xffff, regHeader.checkSum); - SDLNet_Write16(sizeof(regHeader), regHeader.length); - - // Echo packet with zeroed dest and src is a server registration packet - SDLNet_Write32(0, regHeader.dest.network); - regHeader.dest.addr.byIP.host = 0x0; - regHeader.dest.addr.byIP.port = 0x0; - SDLNet_Write16(0x2, regHeader.dest.socket); - - SDLNet_Write32(0, regHeader.src.network); - regHeader.src.addr.byIP.host = 0x0; - regHeader.src.addr.byIP.port = 0x0; - SDLNet_Write16(0x2, regHeader.src.socket); - regHeader.transControl = 0; - - regPacket.data = (Uint8 *)®Header; - regPacket.len = sizeof(regHeader); - regPacket.maxlen = sizeof(regHeader); - regPacket.channel = UDPChannel; - // Send registration string to server. If server doesn't get - // this, client will not be registered - numsent = SDLNet_UDP_Send(ipxClientSocket, regPacket.channel, ®Packet); - - if(!numsent) { - LOG_MSG("IPX: Unable to connect to server: %s", SDLNet_GetError()); - SDLNet_UDP_Close(ipxClientSocket); - return false; - } else { - // Wait for return packet from server. - // This will contain our IPX address and port num - Bits result; - Bit32u ticks, elapsed; - ticks = GetTicks(); - - while(true) { - elapsed = GetTicks() - ticks; - if(elapsed > 5000) { - LOG_MSG("Timeout connecting to server at %s", strAddr); - SDLNet_UDP_Close(ipxClientSocket); - - return false; - } - CALLBACK_Idle(); - result = SDLNet_UDP_Recv(ipxClientSocket, ®Packet); - if (result != 0) { - memcpy(localIpxAddr.netnode, regHeader.dest.addr.byNode.node, sizeof(localIpxAddr.netnode)); - memcpy(localIpxAddr.netnum, regHeader.dest.network, sizeof(localIpxAddr.netnum)); - break; - } - - } - - LOG_MSG("IPX: Connected to server. IPX address is %d:%d:%d:%d:%d:%d", CONVIPX(localIpxAddr.netnode)); - - incomingPacket.connected = true; - TIMER_AddTickHandler(&IPX_ClientLoop); - return true; - } - } else { - LOG_MSG("IPX: Unable to open socket"); - } - } else { - LOG_MSG("IPX: Unable resolve connection to server"); - } - return false; -} - -void IPX_NetworkInit() { - - localIpxAddr.netnum[0] = 0x0; - localIpxAddr.netnum[1] = 0x0; - localIpxAddr.netnum[2] = 0x0; - localIpxAddr.netnum[3] = 0x1; - localIpxAddr.netnode[0] = 0x00; - localIpxAddr.netnode[1] = 0x00; - localIpxAddr.netnode[2] = 0x00; - localIpxAddr.netnode[3] = 0x00; - localIpxAddr.netnode[4] = 0x00; - localIpxAddr.netnode[5] = 0x00; - - socketCount = 0; - return; -} - -class IPXNET : public Program { -public: - void HelpCommand(const char *helpStr) { - // Help on connect command - if(strcasecmp("connect", helpStr) == 0) { - WriteOut("IPXNET CONNECT opens a connection to an IPX tunneling server running on another\n"); - WriteOut("DosBox session. The \"address\" parameter specifies the IP address or host name\n"); - WriteOut("of the server computer. One can also specify the UDP port to use. By default\n"); - WriteOut("IPXNET uses port 213, the assigned IANA port for IPX tunneling, for its\nconnection.\n\n"); - WriteOut("The syntax for IPXNET CONNECT is:\n\n"); - WriteOut("IPXNET CONNECT address \n\n"); - return; - } - // Help on the disconnect command - if(strcasecmp("disconnect", helpStr) == 0) { - WriteOut("IPXNET DISCONNECT closes the connection to the IPX tunneling server.\n\n"); - WriteOut("The syntax for IPXNET DISCONNECT is:\n\n"); - WriteOut("IPXNET DISCONNECT\n\n"); - return; - } - // Help on the startserver command - if(strcasecmp("startserver", helpStr) == 0) { - WriteOut("IPXNET STARTSERVER starts and IPX tunneling server on this DosBox session. By\n"); - WriteOut("default, the server will accept connections on UDP port 213, though this can be\n"); - WriteOut("changed. Once the server is started, DosBox will automatically start a client\n"); - WriteOut("connection to the IPX tunneling server.\n\n"); - WriteOut("The syntax for IPXNET STARTSERVER is:\n\n"); - WriteOut("IPXNET STARTSERVER \n\n"); - return; - } - // Help on the stop server command - if(strcasecmp("stopserver", helpStr) == 0) { - WriteOut("IPXNET STOPSERVER stops the IPX tunneling server running on this DosBox\nsession."); - WriteOut(" Care should be taken to ensure that all other connections have\nterminated "); - WriteOut("as well sinnce stoping the server may cause lockups on other\nmachines still using "); - WriteOut("the IPX tunneling server.\n\n"); - WriteOut("The syntax for IPXNET STOPSERVER is:\n\n"); - WriteOut("IPXNET STOPSERVER\n\n"); - return; - } - // Help on the ping command - if(strcasecmp("ping", helpStr) == 0) { - WriteOut("IPXNET PING broadcasts a ping request through the IPX tunneled network. In \n"); - WriteOut("response, all other connected computers will respond to the ping and report\n"); - WriteOut("the time it took to receive and send the ping message.\n\n"); - WriteOut("The syntax for IPXNET PING is:\n\n"); - WriteOut("IPXNET PING\n\n"); - return; - } - // Help on the status command - if(strcasecmp("status", helpStr) == 0) { - WriteOut("IPXNET STATUS reports the current state of this DosBox's sessions IPX tunneling\n"); - WriteOut("network. For a list of the computers connected to the network use the IPXNET \n"); - WriteOut("PING command.\n\n"); - WriteOut("The syntax for IPXNET STATUS is:\n\n"); - WriteOut("IPXNET STATUS\n\n"); - return; - } - } - - void Run(void) - { - WriteOut("IPX Tunneling utility for DosBox\n\n"); - if(!cmd->GetCount()) { - WriteOut("The syntax of this command is:\n\n"); - WriteOut("IPXNET [ CONNECT | DISCONNECT | STARTSERVER | STOPSERVER | PING | HELP |\n STATUS ]\n\n"); - return; - } - - if(cmd->FindCommand(1, temp_line)) { - if(strcasecmp("help", temp_line.c_str()) == 0) { - if(!cmd->FindCommand(2, temp_line)) { - WriteOut("The following are valid IPXNET commands:\n\n"); - WriteOut("IPXNET CONNECT IPXNET DISCONNECT IPXNET STARTSERVER\n"); - WriteOut("IPXNET STOPSERVER IPXNET PING IPXNET STATUS\n\n"); - WriteOut("To get help on a specific command, type:\n\n"); - WriteOut("IPXNET HELP command\n\n"); - - } else { - HelpCommand(temp_line.c_str()); - return; - } - return; - } - if(strcasecmp("startserver", temp_line.c_str()) == 0) { - if(!isIpxServer) { - if(incomingPacket.connected) { - WriteOut("IPX Tunneling Client alreadu connected to another server. Disconnect first.\n"); - return; - } - bool startsuccess; - if(!cmd->FindCommand(2, temp_line)) { - udpPort = 213; - } else { - udpPort = strtol(temp_line.c_str(), NULL, 10); - } - startsuccess = IPX_StartServer((Bit16u)udpPort); - if(startsuccess) { - WriteOut("IPX Tunneling Server started\n"); - isIpxServer = true; - ConnectToServer("localhost"); - } else { - WriteOut("IPX Tunneling Server failed to start\n"); - } - } else { - WriteOut("IPX Tunneling Server already started\n"); - } - return; - } - if(strcasecmp("stopserver", temp_line.c_str()) == 0) { - if(!isIpxServer) { - WriteOut("IPX Tunneling Server not running in this DosBox session.\n"); - } else { - isIpxServer = false; - DisconnectFromServer(false); - IPX_StopServer(); - WriteOut("IPX Tunneling Server stopped."); - } - return; - } - if(strcasecmp("connect", temp_line.c_str()) == 0) { - char strHost[1024]; - if(incomingPacket.connected) { - WriteOut("IPX Tunneling Client already connected.\n"); - return; - } - if(!cmd->FindCommand(2, temp_line)) { - WriteOut("IPX Server address not specified.\n"); - return; - } - strcpy(strHost, temp_line.c_str()); - - if(!cmd->FindCommand(3, temp_line)) { - udpPort = 213; - } else { - udpPort = strtol(temp_line.c_str(), NULL, 10); - } - - if(ConnectToServer(strHost)) { - WriteOut("IPX Tunneling Client connected to server at %s.\n", strHost); - } else { - WriteOut("IPX Tunneling Client failed to connect to server at %s.\n", strHost); - } - return; - } - - if(strcasecmp("disconnect", temp_line.c_str()) == 0) { - if(!incomingPacket.connected) { - WriteOut("IPX Tunneling Client not connected.\n"); - return; - } - // TODO: Send a packet to the server notifying of disconnect - WriteOut("IPX Tunneling Client disconnected from server.\n"); - DisconnectFromServer(false); - return; - } - - if(strcasecmp("status", temp_line.c_str()) == 0) { - WriteOut("IPX Tunneling Status:\n\n"); - WriteOut("Server status: "); - if(isIpxServer) WriteOut("ACTIVE\n"); else WriteOut("INACTIVE\n"); - WriteOut("Client status: "); - if(incomingPacket.connected) { - WriteOut("CONNECTED -- Server at %d.%d.%d.%d port %d\n", CONVIP(ipxServConnIp.host), udpPort); - } else { - WriteOut("DISCONNECTED\n"); - } - if(isIpxServer) { - WriteOut("List of active connections:\n\n"); - int i; - IPaddress *ptrAddr; - for(i=0;ihost), SDLNet_Read16(&ptrAddr->port)); - } - } - WriteOut("\n"); - } - return; - } - - if(strcasecmp("ping", temp_line.c_str()) == 0) { - Bit32u ticks; - IPXHeader pingHead; - - if(!incomingPacket.connected) { - WriteOut("IPX Tunneling Client not connected.\n"); - return; - } - TIMER_DelTickHandler(&IPX_ClientLoop); - WriteOut("Sending broadcast ping:\n\n"); - pingSend(); - ticks = GetTicks(); - while((GetTicks() - ticks) < 1500) { - CALLBACK_Idle(); - if(pingCheck(&pingHead)) { - WriteOut("Response from %d.%d.%d.%d, port %d time=%dms\n", CONVIP(pingHead.src.addr.byIP.host), SDLNet_Read16(&pingHead.src.addr.byIP.port), GetTicks() - ticks); - } - } - TIMER_AddTickHandler(&IPX_ClientLoop); - return; - } - } - } -}; - -static void IPXNET_ProgramStart(Program * * make) { - *make=new IPXNET; -} - -Bitu IPX_ESRHandler(void) { - LOG_IPX("ESR: >>>>>>>>>>>>>>>" ); - while(ESRList!=NULL) { - // LOG_IPX("ECB: SN%7d notified.", ESRList->SerialNumber); - if(ESRList->databuffer) ESRList->writeData(); - if(ESRList->getESRAddr()) { - // setup registers - SegSet16(es, RealSeg(ESRList->ECBAddr)); - reg_si = RealOff(ESRList->ECBAddr); - reg_al = 0xff; - CALLBACK_RunRealFar(RealSeg(ESRList->getESRAddr()), - RealOff(ESRList->getESRAddr())); - } - delete ESRList; - } // while - - IO_WriteB(0xa0,0x63); //EOI11 - IO_WriteB(0x20,0x62); //EOI2 - LOG_IPX("ESR: <<<<<<<<<<<<<<<"); - return CBRET_NONE; -} - -void VFILE_Remove(const char *name); - -class IPX: public Module_base { -private: - CALLBACK_HandlerObject callback_ipx; - CALLBACK_HandlerObject callback_esr; - CALLBACK_HandlerObject callback_ipxint; - RealPt old_73_vector; - static Bit16u dospage; -public: - IPX(Section* configuration):Module_base(configuration) { - Section_prop * section = static_cast(configuration); - if(!section->Get_bool("ipx")) return; - if(!SDLNetInited) { - if(SDLNet_Init() == -1){ - LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError()); - return; - } - SDLNetInited = true; - } - - ECBList = NULL; - ESRList = NULL; - isIpxServer = false; - isIpxConnected = false; - IPX_NetworkInit(); - - DOS_AddMultiplexHandler(IPX_Multiplex); - - callback_ipx.Install(&IPX_Handler,CB_RETF,"IPX Handler"); - ipx_callback = callback_ipx.Get_RealPointer(); - - callback_ipxint.Install(&IPX_IntHandler,CB_IRET,"IPX (int 7a)"); - callback_ipxint.Set_RealVec(0x7a); - - callback_esr.Allocate(&IPX_ESRHandler,"IPX_ESR"); - Bit16u call_ipxesr1 = callback_esr.Get_callback(); - - if(!dospage) dospage = DOS_GetMemory(2); // can not be freed yet - - PhysPt phyDospage = PhysMake(dospage,0); - - LOG_IPX("ESR callback address: %x, HandlerID %d", phyDospage,call_ipxesr1); - - //save registers - phys_writeb(phyDospage+0,(Bit8u)0xFA); // CLI - phys_writeb(phyDospage+1,(Bit8u)0x60); // PUSHA - phys_writeb(phyDospage+2,(Bit8u)0x1E); // PUSH DS - phys_writeb(phyDospage+3,(Bit8u)0x06); // PUSH ES - phys_writew(phyDospage+4,(Bit16u)0xA00F); // PUSH FS - phys_writew(phyDospage+6,(Bit16u)0xA80F); // PUSH GS - - // callback - phys_writeb(phyDospage+8,(Bit8u)0xFE); // GRP 4 - phys_writeb(phyDospage+9,(Bit8u)0x38); // Extra Callback instruction - phys_writew(phyDospage+10,call_ipxesr1); // Callback identifier - - // register recreation - phys_writew(phyDospage+12,(Bit16u)0xA90F); // POP GS - phys_writew(phyDospage+14,(Bit16u)0xA10F); // POP FS - phys_writeb(phyDospage+16,(Bit8u)0x07); // POP ES - phys_writeb(phyDospage+17,(Bit8u)0x1F); // POP DS - phys_writeb(phyDospage+18,(Bit8u)0x61); // POPA - phys_writeb(phyDospage+19,(Bit8u)0xCF); // IRET: restores flags, CS, IP - - // IPX version 2.12 - //phys_writeb(phyDospage+27,(Bit8u)0x2); - //phys_writeb(phyDospage+28,(Bit8u)0x12); - //IPXVERpointer = RealMake(dospage,27); - - RealPt ESRRoutineBase = RealMake(dospage, 0); - - // Interrupt enabling - RealSetVec(0x73,ESRRoutineBase,old_73_vector); // IRQ11 - IO_WriteB(0xa1,IO_ReadB(0xa1)&(~8)); // enable IRQ11 - - PROGRAMS_MakeFile("IPXNET.COM",IPXNET_ProgramStart); - } - - ~IPX() { - Section_prop * section = static_cast(m_configuration); - PIC_RemoveEvents(IPX_AES_EventHandler); - if(!section->Get_bool("ipx")) return; - - if(isIpxServer) { - isIpxServer = false; - IPX_StopServer(); - } - DisconnectFromServer(false); - - DOS_DelMultiplexHandler(IPX_Multiplex); - RealSetVec(0x73,old_73_vector); - IO_WriteB(0xa1,IO_ReadB(0xa1)|8); // disable IRQ11 - - PhysPt phyDospage = PhysMake(dospage,0); - for(Bitu i = 0;i < 32;i++) - phys_writeb(phyDospage+i,(Bit8u)0x00); - - VFILE_Remove("IPXNET.COM"); - } -}; - -static IPX* test; - -void IPX_ShutDown(Section* sec) { - delete test; -} - -void IPX_Init(Section* sec) { - test = new IPX(sec); - sec->AddDestroyFunction(&IPX_ShutDown,true); -} - -//Initialize static members; -Bit16u IPX::dospage = 0; - -#endif diff --git a/src/hardware/ipxserver.cpp b/src/hardware/ipxserver.cpp deleted file mode 100644 index befe97b..0000000 --- a/src/hardware/ipxserver.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: ipxserver.cpp,v 1.9 2007/01/08 19:45:40 qbix79 Exp $ */ - -#include "dosbox.h" - -#if C_IPX - -#include "dosbox.h" -#include "ipxserver.h" -#include "timer.h" -#include -#include -#include "ipx.h" - -IPaddress ipxServerIp; // IPAddress for server's listening port -UDPsocket ipxServerSocket; // Listening server socket - -packetBuffer connBuffer[SOCKETTABLESIZE]; - -Bit8u inBuffer[IPXBUFFERSIZE]; -IPaddress ipconn[SOCKETTABLESIZE]; // Active TCP/IP connection -UDPsocket tcpconn[SOCKETTABLESIZE]; // Active TCP/IP connections -SDLNet_SocketSet serverSocketSet; -TIMER_TickHandler* serverTimer; - -Bit8u packetCRC(Bit8u *buffer, Bit16u bufSize) { - Bit8u tmpCRC = 0; - Bit16u i; - for(i=0;isrc.addr.byIP.host; - desthost = tmpHeader->dest.addr.byIP.host; - - srcport = tmpHeader->src.addr.byIP.port; - destport = tmpHeader->dest.addr.byIP.port; - - - if(desthost == 0xffffffff) { - // Broadcast - for(i=0;i= SOCKETTABLESIZE) return false; - *ptrAddr = &ipconn[tableNum]; - return connBuffer[tableNum].connected; -} - -static void ackClient(IPaddress clientAddr) { - IPXHeader regHeader; - UDPpacket regPacket; - Bits result; - - SDLNet_Write16(0xffff, regHeader.checkSum); - SDLNet_Write16(sizeof(regHeader), regHeader.length); - - SDLNet_Write32(0, regHeader.dest.network); - PackIP(clientAddr, ®Header.dest.addr.byIP); - SDLNet_Write16(0x2, regHeader.dest.socket); - - SDLNet_Write32(1, regHeader.src.network); - PackIP(ipxServerIp, ®Header.src.addr.byIP); - SDLNet_Write16(0x2, regHeader.src.socket); - regHeader.transControl = 0; - - regPacket.data = (Uint8 *)®Header; - regPacket.len = sizeof(regHeader); - regPacket.maxlen = sizeof(regHeader); - regPacket.address = clientAddr; - // Send registration string to client. If client doesn't get this, client will not be registered - result = SDLNet_UDP_Send(ipxServerSocket,-1,®Packet); - -} - -static void IPX_ServerLoop() { - UDPpacket inPacket; - IPaddress tmpAddr; - - //char regString[] = "IPX Register\0"; - - Bit16u i; - Bit32u host; - Bits result; - - inPacket.channel = -1; - inPacket.data = &inBuffer[0]; - inPacket.maxlen = IPXBUFFERSIZE; - - - result = SDLNet_UDP_Recv(ipxServerSocket, &inPacket); - if (result != 0) { - // Check to see if incoming packet is a registration packet - // For this, I just spoofed the echo protocol packet designation 0x02 - IPXHeader *tmpHeader; - tmpHeader = (IPXHeader *)&inBuffer[0]; - - // Check to see if echo packet - if(SDLNet_Read16(tmpHeader->dest.socket) == 0x2) { - // Null destination node means its a server registration packet - if(tmpHeader->dest.addr.byIP.host == 0x0) { - UnpackIP(tmpHeader->src.addr.byIP, &tmpAddr); - for(i=0;i -#include "dosbox.h" -#include "inout.h" -#include "setup.h" -#include "joystick.h" -#include "pic.h" -#include "support.h" - -#define RANGE 64 -#define TIMEOUT 10 - -#define OHMS 120000/2 -#define JOY_S_CONSTANT 0.0000242 -#define S_PER_OHM 0.000000011 - -struct JoyStick { - bool enabled; - float xpos,ypos; - double xtick,ytick; - Bitu xcount,ycount; - bool button[2]; -}; - -JoystickType joytype; -static JoyStick stick[2]; - -static Bit32u last_write = 0; -static bool write_active = false; -static bool swap34 = false; -bool button_wrapping_enabled = true; - -extern bool autofire; //sdl_mapper.cpp - -static Bitu read_p201(Bitu port,Bitu iolen) { - /* Reset Joystick to 0 after TIMEOUT ms */ - if(write_active && ((PIC_Ticks - last_write) > TIMEOUT)) { - write_active = false; - stick[0].xcount = 0; - stick[1].xcount = 0; - stick[0].ycount = 0; - stick[1].ycount = 0; -// LOG_MSG("reset by time %d %d",PIC_Ticks,last_write); - } - - /** Format of the byte to be returned: - ** | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - ** +-------------------------------+ - ** | | | | | | | | - ** Joystick B, Button 2 ---+ | | | | | | +--- Joystick A, X Axis - ** Joystick B, Button 1 -------+ | | | | +------- Joystick A, Y Axis - ** Joystick A, Button 2 -----------+ | | +----------- Joystick B, X Axis - ** Joystick A, Button 1 ---------------+ +--------------- Joystick B, Y Axis - **/ - Bit8u ret=0xff; - if (stick[0].enabled) { - if (stick[0].xcount) stick[0].xcount--; else ret&=~1; - if (stick[0].ycount) stick[0].ycount--; else ret&=~2; - if (stick[0].button[0]) ret&=~16; - if (stick[0].button[1]) ret&=~32; - } - if (stick[1].enabled) { - if (stick[1].xcount) stick[1].xcount--; else ret&=~4; - if (stick[1].ycount) stick[1].ycount--; else ret&=~8; - if (stick[1].button[0]) ret&=~64; - if (stick[1].button[1]) ret&=~128; - } - return ret; -} - -static Bitu read_p201_timed(Bitu port,Bitu iolen) { - Bit8u ret=0xff; - double currentTick = PIC_FullIndex(); - if( stick[0].enabled ){ - if( stick[0].xtick < currentTick ) ret &=~1; - if( stick[0].ytick < currentTick ) ret &=~2; - } - if( stick[1].enabled ){ - if( stick[1].xtick < currentTick ) ret &=~4; - if( stick[1].ytick < currentTick ) ret &=~8; - } - - if (stick[0].enabled) { - if (stick[0].button[0]) ret&=~16; - if (stick[0].button[1]) ret&=~32; - } - if (stick[1].enabled) { - if (stick[1].button[0]) ret&=~64; - if (stick[1].button[1]) ret&=~128; - } - return ret; -} - -static void write_p201(Bitu port,Bitu val,Bitu iolen) { - /* Store writetime index */ - write_active = true; - last_write = PIC_Ticks; - if (stick[0].enabled) { - stick[0].xcount=(Bitu)((stick[0].xpos*RANGE)+RANGE); - stick[0].ycount=(Bitu)((stick[0].ypos*RANGE)+RANGE); - } - if (stick[1].enabled) { - stick[1].xcount=(Bitu)(((swap34? stick[1].ypos : stick[1].xpos)*RANGE)+RANGE); - stick[1].ycount=(Bitu)(((swap34? stick[1].xpos : stick[1].ypos)*RANGE)+RANGE); - } - -} -static void write_p201_timed(Bitu port,Bitu val,Bitu iolen) { - // Store writetime index - // Axes take time = 24.2 microseconds + ( 0.011 microsecons/ohm * resistance ) - // to reset to 0 - // Precalculate the time at which each axis hits 0 here - double currentTick = PIC_FullIndex(); - if (stick[0].enabled) { - stick[0].xtick = currentTick + 1000.0*( JOY_S_CONSTANT + S_PER_OHM * - (double)(((stick[0].xpos+1.0)* OHMS)) ); - stick[0].ytick = currentTick + 1000.0*( JOY_S_CONSTANT + S_PER_OHM * - (double)(((stick[0].ypos+1.0)* OHMS)) ); - } - if (stick[1].enabled) { - stick[1].xtick = currentTick + 1000.0*( JOY_S_CONSTANT + S_PER_OHM * - (double)((swap34? stick[1].ypos : stick[1].xpos)+1.0) * OHMS); - stick[1].ytick = currentTick + 1000.0*( JOY_S_CONSTANT + S_PER_OHM * - (double)((swap34? stick[1].xpos : stick[1].ypos)+1.0) * OHMS); - } -} - -void JOYSTICK_Enable(Bitu which,bool enabled) { - if (which<2) stick[which].enabled=enabled; -} - -void JOYSTICK_Button(Bitu which,Bitu num,bool pressed) { - if ((which<2) && (num<2)) stick[which].button[num]=pressed; -} - -void JOYSTICK_Move_X(Bitu which,float x) { - if (which<2) { - stick[which].xpos=x; - } -} - -void JOYSTICK_Move_Y(Bitu which,float y) { - if (which<2) { - stick[which].ypos=y; - } -} - -bool JOYSTICK_IsEnabled(Bitu which) { - if (which<2) return stick[which].enabled; - return false; -} - -bool JOYSTICK_GetButton(Bitu which, Bitu num) { - if ((which<2) && (num<2)) return stick[which].button[num]; - return false; -} - -float JOYSTICK_GetMove_X(Bitu which) { - if (which<2) return stick[which].xpos; - return 0.0f; -} - -float JOYSTICK_GetMove_Y(Bitu which) { - if (which<2) return stick[which].ypos; - return 0.0f; -} - -class JOYSTICK:public Module_base{ -private: - IO_ReadHandleObject ReadHandler; - IO_WriteHandleObject WriteHandler; -public: - JOYSTICK(Section* configuration):Module_base(configuration){ - Section_prop * section=static_cast(configuration); - const char * type=section->Get_string("joysticktype"); - if (!strcasecmp(type,"none")) joytype = JOY_NONE; - else if (!strcasecmp(type,"false")) joytype = JOY_NONE; - else if (!strcasecmp(type,"auto")) joytype = JOY_AUTO; - else if (!strcasecmp(type,"2axis")) joytype = JOY_2AXIS; - else if (!strcasecmp(type,"4axis")) joytype = JOY_4AXIS; - else if (!strcasecmp(type,"4axis_2")) joytype = JOY_4AXIS_2; - else if (!strcasecmp(type,"fcs")) joytype = JOY_FCS; - else if (!strcasecmp(type,"ch")) joytype = JOY_CH; - else joytype = JOY_AUTO; - - bool timed = section->Get_bool("timed"); - if(timed) { - ReadHandler.Install(0x201,read_p201_timed,IO_MB); - WriteHandler.Install(0x201,write_p201_timed,IO_MB); - } else { - ReadHandler.Install(0x201,read_p201,IO_MB); - WriteHandler.Install(0x201,write_p201,IO_MB); - } - autofire = section->Get_bool("autofire"); - swap34 = section->Get_bool("swap34"); - button_wrapping_enabled = section->Get_bool("buttonwrap"); - stick[0].enabled = false; - stick[1].enabled = false; - stick[0].xtick = stick[0].ytick = stick[1].xtick = - stick[1].ytick = PIC_FullIndex(); - } -}; -static JOYSTICK* test; - -void JOYSTICK_Destroy(Section* sec) { - delete test; -} - -void JOYSTICK_Init(Section* sec) { - test = new JOYSTICK(sec); - sec->AddDestroyFunction(&JOYSTICK_Destroy,true); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "inout.h" + +#define RANGE 64 + +struct JoyStick { + bool enabled; + float xpos,ypos; + Bitu xcount,ycount; + bool button[2]; +}; + + +static JoyStick stick[2]; + + +static Bit8u read_p201(Bit32u port) { + /** Format of the byte to be returned: + ** | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + ** +-------------------------------+ + ** | | | | | | | | + ** Joystick B, Button 2 ---+ | | | | | | +--- Joystick A, X Axis + ** Joystick B, Button 1 -------+ | | | | +------- Joystick A, Y Axis + ** Joystick A, Button 2 -----------+ | | +----------- Joystick B, X Axis + ** Joystick A, Button 1 ---------------+ +--------------- Joystick B, Y Axis + **/ + Bit8u ret=0xff; + if (stick[0].enabled) { + if (stick[0].xcount) stick[0].xcount--; else ret&=~1; + if (stick[0].ycount) stick[0].ycount--; else ret&=~2; + if (stick[0].button[0]) ret&=16; + if (stick[0].button[1]) ret&=32; + } + if (stick[1].enabled) { + if (stick[1].xcount) stick[0].xcount--; else ret&=~4; + if (stick[1].ycount) stick[0].ycount--; else ret&=~8; + if (stick[1].button[0]) ret&=64; + if (stick[1].button[1]) ret&=128; + } + return ret; +} + +static void write_p201(Bit32u port,Bit8u val) { + if (stick[0].enabled) { + stick[0].xcount=(Bitu)(stick[0].xpos*RANGE+RANGE*2); + stick[0].ycount=(Bitu)(stick[0].ypos*RANGE+RANGE*2); + } + if (stick[1].enabled) { + stick[1].xcount=(Bitu)(stick[1].xpos*RANGE+RANGE*2); + stick[1].ycount=(Bitu)(stick[1].ypos*RANGE+RANGE*2); + } + +} + +void JOYSTICK_Enable(Bitu which,bool enabled) { + if (which<2) stick[which].enabled=enabled; +} + +void JOYSTICK_Button(Bitu which,Bitu num,bool pressed) { + if ((which<2) && (num<2)) stick[which].button[num]=pressed; +} + +void JOYSTICK_Move_X(Bitu which,float x) { + if (which<2) { + stick[which].xpos=x; + } +} + +void JOYSTICK_Move_Y(Bitu which,float y) { + if (which<2) { + stick[which].ypos=y; + } +} + + +void JOYSTICK_Init(void) { + IO_RegisterReadHandler(0x201,read_p201,"JOYSTICK"); + IO_RegisterWriteHandler(0x201,write_p201,"JOYSTICK"); + stick[0].enabled=false; + stick[1].enabled=false; +} + + diff --git a/src/hardware/keyboard.cpp b/src/hardware/keyboard.cpp index 5646468..f29cc65 100644 --- a/src/hardware/keyboard.cpp +++ b/src/hardware/keyboard.cpp @@ -1,389 +1,260 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: keyboard.cpp,v 1.40 2007/11/18 17:09:15 qbix79 Exp $ */ - -#include "dosbox.h" -#include "keyboard.h" -#include "inout.h" -#include "pic.h" -#include "mem.h" -#include "mixer.h" -#include "timer.h" - -#define KEYBUFSIZE 32 -#define KEYDELAY 0.300f //Considering 20-30 khz serial clock and 11 bits/char - -enum KeyCommands { - CMD_NONE, - CMD_SETLEDS, - CMD_SETTYPERATE, - CMD_SETOUTPORT -}; - -static struct { - Bit8u buffer[KEYBUFSIZE]; - Bitu used; - Bitu pos; - struct { - KBD_KEYS key; - Bitu wait; - Bitu pause,rate; - } repeat; - KeyCommands command; - Bit8u p60data; - bool p60changed; - bool active; - bool scanning; - bool scheduled; -} keyb; - -static void KEYBOARD_SetPort60(Bit8u val) { - keyb.p60changed=true; - keyb.p60data=val; - if (machine==MCH_PCJR) PIC_ActivateIRQ(6); - else PIC_ActivateIRQ(1); -} - -static void KEYBOARD_TransferBuffer(Bitu val) { - keyb.scheduled=false; - if (!keyb.used) { - LOG(LOG_KEYBOARD,LOG_NORMAL)("Transfer started with empty buffer"); - return; - } - KEYBOARD_SetPort60(keyb.buffer[keyb.pos]); - if (++keyb.pos>=KEYBUFSIZE) keyb.pos-=KEYBUFSIZE; - keyb.used--; -} - - -void KEYBOARD_ClrBuffer(void) { - keyb.used=0; - keyb.pos=0; - PIC_RemoveEvents(KEYBOARD_TransferBuffer); - keyb.scheduled=false; -} - -static void KEYBOARD_AddBuffer(Bit8u data) { - if (keyb.used>=KEYBUFSIZE) { - LOG(LOG_KEYBOARD,LOG_NORMAL)("Buffer full, dropping code"); - return; - } - Bitu start=keyb.pos+keyb.used; - if (start>=KEYBUFSIZE) start-=KEYBUFSIZE; - keyb.buffer[start]=data; - keyb.used++; - /* Start up an event to start the first IRQ */ - if (!keyb.scheduled && !keyb.p60changed) { - keyb.scheduled=true; - PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY); - } -} - - -static Bitu read_p60(Bitu port,Bitu iolen) { - keyb.p60changed=false; - if (!keyb.scheduled && keyb.used) { - keyb.scheduled=true; - PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY); - } - return keyb.p60data; -} - -static void write_p60(Bitu port,Bitu val,Bitu iolen) { - switch (keyb.command) { - case CMD_NONE: /* None */ - /* No active command this would normally get sent to the keyboard then */ - KEYBOARD_ClrBuffer(); - switch (val) { - case 0xed: /* Set Leds */ - keyb.command=CMD_SETLEDS; - KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ - break; - case 0xee: /* Echo */ - KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ - break; - case 0xf2: /* Identify keyboard */ - /* AT's just send acknowledge */ - KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ - break; - case 0xf3: /* Typematic rate programming */ - keyb.command=CMD_SETTYPERATE; - KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ - break; - case 0xf4: /* Enable keyboard,clear buffer, start scanning */ - LOG(LOG_KEYBOARD,LOG_NORMAL)("Clear buffer,enable Scaning"); - KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ - keyb.scanning=true; - break; - case 0xf5: /* Reset keyboard and disable scanning */ - LOG(LOG_KEYBOARD,LOG_NORMAL)("Reset, disable scanning"); - keyb.scanning=false; - KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ - break; - case 0xf6: /* Reset keyboard and enable scanning */ - LOG(LOG_KEYBOARD,LOG_NORMAL)("Reset, enable scanning"); - KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ - keyb.scanning=false; - break; - default: - /* Just always acknowledge strange commands */ - LOG(LOG_KEYBOARD,LOG_ERROR)("60:Unhandled command %X",val); - KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ - } - return; - case CMD_SETOUTPORT: - MEM_A20_Enable((val & 2)>0); - keyb.command = CMD_NONE; - break; - case CMD_SETTYPERATE: - { - static const int delay[] = { 250, 500, 750, 1000 }; - static const int repeat[] = - { 33,37,42,46,50,54,58,63,67,75,83,92,100, - 109,118,125,133,149,167,182,200,217,233, - 250,270,303,333,370,400,435,476,500 }; - keyb.repeat.pause = delay[(val>>5)&3]; - keyb.repeat.rate = repeat[val&0x1f]; - keyb.command=CMD_NONE; - } - /* Fallthrough! as setleds does what we want */ - case CMD_SETLEDS: - keyb.command=CMD_NONE; - KEYBOARD_ClrBuffer(); - KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ - break; - } -} - -static Bit8u port_61_data = 0; -static Bitu read_p61(Bitu port,Bitu iolen) { - port_61_data^=0x20; - port_61_data^=0x10; - return port_61_data; -} - -extern void TIMER_SetGate2(bool); -static void write_p61(Bitu port,Bitu val,Bitu iolen) { - if ((port_61_data ^ val) & 3) { - if((port_61_data ^ val) & 1) TIMER_SetGate2(val&0x1); - PCSPEAKER_SetType(val & 3); - } - port_61_data = val; -} - -static void write_p64(Bitu port,Bitu val,Bitu iolen) { - switch (val) { - case 0xae: /* Activate keyboard */ - keyb.active=true; - if (keyb.used && !keyb.scheduled && !keyb.p60changed) { - keyb.scheduled=true; - PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY); - } - LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated"); - break; - case 0xad: /* Deactivate keyboard */ - keyb.active=false; - LOG(LOG_KEYBOARD,LOG_NORMAL)("De-Activated"); - break; - case 0xd0: /* Outport on buffer */ - KEYBOARD_SetPort60(MEM_A20_Enabled() ? 0x02 : 0); - break; - case 0xd1: /* Write to outport */ - keyb.command=CMD_SETOUTPORT; - break; - default: - LOG(LOG_KEYBOARD,LOG_ERROR)("Port 64 write with val %d",val); - break; - } -} - -static Bitu read_p64(Bitu port,Bitu iolen) { - Bit8u status= 0x1c | (keyb.p60changed? 0x1 : 0x0); - return status; -} - -void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed) { - Bit8u ret=0;bool extend=false; - switch (keytype) { - case KBD_esc:ret=1;break; - case KBD_1:ret=2;break; - case KBD_2:ret=3;break; - case KBD_3:ret=4;break; - case KBD_4:ret=5;break; - case KBD_5:ret=6;break; - case KBD_6:ret=7;break; - case KBD_7:ret=8;break; - case KBD_8:ret=9;break; - case KBD_9:ret=10;break; - case KBD_0:ret=11;break; - - case KBD_minus:ret=12;break; - case KBD_equals:ret=13;break; - case KBD_backspace:ret=14;break; - case KBD_tab:ret=15;break; - - case KBD_q:ret=16;break; - case KBD_w:ret=17;break; - case KBD_e:ret=18;break; - case KBD_r:ret=19;break; - case KBD_t:ret=20;break; - case KBD_y:ret=21;break; - case KBD_u:ret=22;break; - case KBD_i:ret=23;break; - case KBD_o:ret=24;break; - case KBD_p:ret=25;break; - - case KBD_leftbracket:ret=26;break; - case KBD_rightbracket:ret=27;break; - case KBD_enter:ret=28;break; - case KBD_leftctrl:ret=29;break; - - case KBD_a:ret=30;break; - case KBD_s:ret=31;break; - case KBD_d:ret=32;break; - case KBD_f:ret=33;break; - case KBD_g:ret=34;break; - case KBD_h:ret=35;break; - case KBD_j:ret=36;break; - case KBD_k:ret=37;break; - case KBD_l:ret=38;break; - - case KBD_semicolon:ret=39;break; - case KBD_quote:ret=40;break; - case KBD_grave:ret=41;break; - case KBD_leftshift:ret=42;break; - case KBD_backslash:ret=43;break; - case KBD_z:ret=44;break; - case KBD_x:ret=45;break; - case KBD_c:ret=46;break; - case KBD_v:ret=47;break; - case KBD_b:ret=48;break; - case KBD_n:ret=49;break; - case KBD_m:ret=50;break; - - case KBD_comma:ret=51;break; - case KBD_period:ret=52;break; - case KBD_slash:ret=53;break; - case KBD_rightshift:ret=54;break; - case KBD_kpmultiply:ret=55;break; - case KBD_leftalt:ret=56;break; - case KBD_space:ret=57;break; - case KBD_capslock:ret=58;break; - - case KBD_f1:ret=59;break; - case KBD_f2:ret=60;break; - case KBD_f3:ret=61;break; - case KBD_f4:ret=62;break; - case KBD_f5:ret=63;break; - case KBD_f6:ret=64;break; - case KBD_f7:ret=65;break; - case KBD_f8:ret=66;break; - case KBD_f9:ret=67;break; - case KBD_f10:ret=68;break; - - case KBD_numlock:ret=69;break; - case KBD_scrolllock:ret=70;break; - - case KBD_kp7:ret=71;break; - case KBD_kp8:ret=72;break; - case KBD_kp9:ret=73;break; - case KBD_kpminus:ret=74;break; - case KBD_kp4:ret=75;break; - case KBD_kp5:ret=76;break; - case KBD_kp6:ret=77;break; - case KBD_kpplus:ret=78;break; - case KBD_kp1:ret=79;break; - case KBD_kp2:ret=80;break; - case KBD_kp3:ret=81;break; - case KBD_kp0:ret=82;break; - case KBD_kpperiod:ret=83;break; - - case KBD_extra_lt_gt:ret=86;break; - case KBD_f11:ret=87;break; - case KBD_f12:ret=88;break; - - //The Extended keys - - case KBD_kpenter:extend=true;ret=28;break; - case KBD_rightctrl:extend=true;ret=29;break; - case KBD_kpdivide:extend=true;ret=53;break; - case KBD_rightalt:extend=true;ret=56;break; - case KBD_home:extend=true;ret=71;break; - case KBD_up:extend=true;ret=72;break; - case KBD_pageup:extend=true;ret=73;break; - case KBD_left:extend=true;ret=75;break; - case KBD_right:extend=true;ret=77;break; - case KBD_end:extend=true;ret=79;break; - case KBD_down:extend=true;ret=80;break; - case KBD_pagedown:extend=true;ret=81;break; - case KBD_insert:extend=true;ret=82;break; - case KBD_delete:extend=true;ret=83;break; - case KBD_pause: - KEYBOARD_AddBuffer(0xe1); - KEYBOARD_AddBuffer(29|(pressed?0:0x80)); - KEYBOARD_AddBuffer(69|(pressed?0:0x80)); - return; - case KBD_printscreen: - /* Not handled yet. But usuable in mapper for special events */ - return; - default: - E_Exit("Unsupported key press"); - break; - } - /* Add the actual key in the keyboard queue */ - if (pressed) { - if (keyb.repeat.key==keytype) keyb.repeat.wait=keyb.repeat.rate; - else keyb.repeat.wait=keyb.repeat.pause; - keyb.repeat.key=keytype; - } else { - keyb.repeat.key=KBD_NONE; - keyb.repeat.wait=0; - ret+=128; - } - if (extend) KEYBOARD_AddBuffer(0xe0); - KEYBOARD_AddBuffer(ret); -} - -static void KEYBOARD_TickHandler(void) { - if (keyb.repeat.wait) { - keyb.repeat.wait--; - if (!keyb.repeat.wait) KEYBOARD_AddKey(keyb.repeat.key,true); - } -} - -void KEYBOARD_Init(Section* sec) { - IO_RegisterWriteHandler(0x60,write_p60,IO_MB); - IO_RegisterReadHandler(0x60,read_p60,IO_MB); - IO_RegisterWriteHandler(0x61,write_p61,IO_MB); - IO_RegisterReadHandler(0x61,read_p61,IO_MB); - IO_RegisterWriteHandler(0x64,write_p64,IO_MB); - IO_RegisterReadHandler(0x64,read_p64,IO_MB); - TIMER_AddTickHandler(&KEYBOARD_TickHandler); - write_p61(0,0,0); - /* Init the keyb struct */ - keyb.active=true; - keyb.scanning=true; - keyb.command=CMD_NONE; - keyb.p60changed=false; - keyb.repeat.key=KBD_NONE; - keyb.repeat.pause=500; - keyb.repeat.rate=33; - keyb.repeat.wait=0; - KEYBOARD_ClrBuffer(); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "dosbox.h" +#include "keyboard.h" +#include "inout.h" +#include "pic.h" +#include "mixer.h" + + +#define KEYBUFSIZE 32 + + +struct KeyEvent { + Bitu type; + Bitu state; + KEYBOARD_EventHandler * handler; + KeyEvent * next; +}; + +static Bitu shift_state=0; +static Bit8u cur_scancode; +static Bit8u kbuf[KEYBUFSIZE]; +static Bitu kbuf_pos; +static Bitu kbuf_used; +static Bit8u port_61_data; +//TODO Are these initialized at 0 at startup? Hope so :) +static KeyEvent * event_handlers[KBD_LAST]; + + +static Bit8u read_p60(Bit32u port) { + if (kbuf_used>0) { + cur_scancode=kbuf[kbuf_pos]; + }; + return cur_scancode; +} + +static void write_p60(Bit32u port,Bit8u val) { +//TODO Work this out ;) + LOG_DEBUG("Port 60 write with val %d",val); +} + +static Bit8u read_p61(Bit32u port) { + return port_61_data; +}; + +static void write_p61(Bit32u port,Bit8u val) { +//TODO Enable spreaker through here :) + if ((val&128)) { /* Keyboard acknowledge */ + kbuf_used--; + kbuf_pos++; + if (kbuf_pos>=KEYBUFSIZE) kbuf_pos=0; + if (kbuf_used>0) PIC_ActivateIRQ(1); + } + port_61_data=val; + if ((val & 3)==3) { + PCSPEAKER_Enable(true); + } else { + PCSPEAKER_Enable(false); + } +} + + + +void KEYBOARD_AddCode(Bit8u code) { + //Now Raise the keyboard IRQ + //If the buffer is full just drop the scancode :) + if (kbuf_used=KEYBUFSIZE) start-=KEYBUFSIZE; + kbuf[start]=code; + } + PIC_ActivateIRQ(1); +} + + +void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler) { + KeyEvent * newevent=new KeyEvent; +/* Add the event in the correct key structure */ + if (keytype>=KBD_LAST) { + LOG_ERROR("KEYBOARD:Illegal key %d for handler",keytype); + } + newevent->next=event_handlers[keytype]; + event_handlers[keytype]=newevent; + newevent->type=keytype; + newevent->state=state; + newevent->handler=handler; + + +}; + +void KEYBOARD_AddKey(Bitu keytype,bool pressed) { + bool extend=false; + Bit8u ret=0; + switch (keytype) { + case KBD_esc:ret=1;break; + case KBD_1:ret=2;break; + case KBD_2:ret=3;break; + case KBD_3:ret=4;break; + case KBD_4:ret=5;break; + case KBD_5:ret=6;break; + case KBD_6:ret=7;break; + case KBD_7:ret=8;break; + case KBD_8:ret=9;break; + case KBD_9:ret=10;break; + case KBD_0:ret=11;break; + + case KBD_minus:ret=12;break; + case KBD_equals:ret=13;break; + case KBD_backspace:ret=14;break; + case KBD_tab:ret=15;break; + + case KBD_q:ret=16;break; + case KBD_w:ret=17;break; + case KBD_e:ret=18;break; + case KBD_r:ret=19;break; + case KBD_t:ret=20;break; + case KBD_y:ret=21;break; + case KBD_u:ret=22;break; + case KBD_i:ret=23;break; + case KBD_o:ret=24;break; + case KBD_p:ret=25;break; + + case KBD_leftbracket:ret=26;break; + case KBD_rightbracket:ret=27;break; + case KBD_enter:ret=28;break; + case KBD_leftctrl:ret=29; + shift_state=(shift_state&~CTRL_PRESSED)|(pressed ? CTRL_PRESSED:0); + break; + + case KBD_a:ret=30;break; + case KBD_s:ret=31;break; + case KBD_d:ret=32;break; + case KBD_f:ret=33;break; + case KBD_g:ret=34;break; + case KBD_h:ret=35;break; + case KBD_j:ret=36;break; + case KBD_k:ret=37;break; + case KBD_l:ret=38;break; + + case KBD_semicolon:ret=39;break; + case KBD_quote:ret=40;break; + case KBD_grave:ret=41;break; + case KBD_leftshift:ret=42; + shift_state=(shift_state&~SHIFT_PRESSED)|(pressed ? SHIFT_PRESSED:0); + break; + case KBD_backslash:ret=43;break; + case KBD_z:ret=44;break; + case KBD_x:ret=45;break; + case KBD_c:ret=46;break; + case KBD_v:ret=47;break; + case KBD_b:ret=48;break; + case KBD_n:ret=49;break; + case KBD_m:ret=50;break; + + case KBD_comma:ret=51;break; + case KBD_period:ret=52;break; + case KBD_slash:ret=53;break; + case KBD_rightshift:ret=54;break; + case KBD_kpmultiply:ret=55;break; + case KBD_leftalt:ret=56; + shift_state=(shift_state&~ALT_PRESSED)|(pressed ? ALT_PRESSED:0); + break; + case KBD_space:ret=57;break; + case KBD_capslock:ret=58;break; + + case KBD_f1:ret=59;break; + case KBD_f2:ret=60;break; + case KBD_f3:ret=61;break; + case KBD_f4:ret=62;break; + case KBD_f5:ret=63;break; + case KBD_f6:ret=64;break; + case KBD_f7:ret=65;break; + case KBD_f8:ret=66;break; + case KBD_f9:ret=67;break; + case KBD_f10:ret=68;break; + + case KBD_numlock:ret=69;break; + case KBD_scrolllock:ret=70;break; + + case KBD_kp7:ret=71;break; + case KBD_kp8:ret=72;break; + case KBD_kp9:ret=73;break; + case KBD_kpminus:ret=74;break; + case KBD_kp4:ret=75;break; + case KBD_kp5:ret=76;break; + case KBD_kp6:ret=77;break; + case KBD_kpplus:ret=78;break; + case KBD_kp1:ret=79;break; + case KBD_kp2:ret=80;break; + case KBD_kp3:ret=81;break; + case KBD_kp0:ret=82;break; + case KBD_kpperiod:ret=83;break; + + case KBD_f11:ret=87;break; + case KBD_f12:ret=88;break; + + //The Extended keys + + case KBD_kpenter:extend=true;ret=28;break; + case KBD_rightctrl:extend=true;ret=29;break; + case KBD_kpslash:extend=true;ret=53;break; + case KBD_rightalt:extend=true;ret=56;break; + case KBD_home:extend=true;ret=71;break; + case KBD_up:extend=true;ret=72;break; + case KBD_pageup:extend=true;ret=73;break; + case KBD_left:extend=true;ret=75;break; + case KBD_right:extend=true;ret=77;break; + case KBD_end:extend=true;ret=79;break; + case KBD_down:extend=true;ret=80;break; + case KBD_pagedown:extend=true;ret=81;break; + case KBD_insert:extend=true;ret=82;break; + case KBD_delete:extend=true;ret=83;break; + default: + E_Exit("Unsopperted key press"); + break; + }; + /* check for active key events */ + KeyEvent * checkevent=event_handlers[keytype]; + while (checkevent) { + if ((shift_state & checkevent->state)==checkevent->state) { + if (checkevent->type==keytype && pressed) { + (*checkevent->handler)(); + return; + } + if (checkevent->type==keytype) return; + } + checkevent=checkevent->next; + } + if (extend) KEYBOARD_AddCode(224); + if (!pressed) ret+=128; + KEYBOARD_AddCode(ret); +}; + +void KEYBOARD_Init(void) { + kbuf_used=0;kbuf_pos=0; + IO_RegisterWriteHandler(0x60,write_p60,"Keyboard"); + IO_RegisterReadHandler(0x60,read_p60,"Keyboard"); + IO_RegisterWriteHandler(0x61,write_p61,"Keyboard"); + IO_RegisterReadHandler(0x61,read_p61,"Keyboard"); + port_61_data=1; /* Speaker control through PIT and speaker disabled */ +// memset(&event_handlers,0,sizeof(event_handlers)); +}; diff --git a/src/hardware/memory.cpp b/src/hardware/memory.cpp index 09d43fd..d2fd529 100644 --- a/src/hardware/memory.cpp +++ b/src/hardware/memory.cpp @@ -1,613 +1,299 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: memory.cpp,v 1.55 2008/10/27 11:02:41 c2woody Exp $ */ - -#include "dosbox.h" -#include "mem.h" -#include "inout.h" -#include "setup.h" -#include "paging.h" -#include "regs.h" - -#include - -#define PAGES_IN_BLOCK ((1024*1024)/MEM_PAGE_SIZE) -#define SAFE_MEMORY 32 -#define MAX_MEMORY 64 -#define MAX_PAGE_ENTRIES (MAX_MEMORY*1024*1024/4096) -#define LFB_PAGES 512 -#define MAX_LINKS ((MAX_MEMORY*1024/4)+4096) //Hopefully enough - -struct LinkBlock { - Bitu used; - Bit32u pages[MAX_LINKS]; -}; - -static struct MemoryBlock { - Bitu pages; - PageHandler * * phandlers; - MemHandle * mhandles; - LinkBlock links; - struct { - Bitu start_page; - Bitu end_page; - Bitu pages; - PageHandler *handler; - PageHandler *mmiohandler; - } lfb; - struct { - bool enabled; - Bit8u controlport; - } a20; -} memory; - -HostPt MemBase; - -class IllegalPageHandler : public PageHandler { -public: - IllegalPageHandler() { - flags=PFLAG_INIT|PFLAG_NOCODE; - } - Bitu readb(PhysPt addr) { -#if C_DEBUG - LOG_MSG("Illegal read from %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip); -#else - static Bits lcount=0; - if (lcount<1000) { - lcount++; - LOG_MSG("Illegal read from %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip); - } -#endif - return 0; - } - void writeb(PhysPt addr,Bitu val) { -#if C_DEBUG - LOG_MSG("Illegal write to %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip); -#else - static Bits lcount=0; - if (lcount<1000) { - lcount++; - LOG_MSG("Illegal write to %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip); - } -#endif - } -}; - -class RAMPageHandler : public PageHandler { -public: - RAMPageHandler() { - flags=PFLAG_READABLE|PFLAG_WRITEABLE; - } - HostPt GetHostReadPt(Bitu phys_page) { - return MemBase+phys_page*MEM_PAGESIZE; - } - HostPt GetHostWritePt(Bitu phys_page) { - return MemBase+phys_page*MEM_PAGESIZE; - } -}; - -class ROMPageHandler : public RAMPageHandler { -public: - ROMPageHandler() { - flags=PFLAG_READABLE|PFLAG_HASROM; - } - void writeb(PhysPt addr,Bitu val){ - LOG(LOG_CPU,LOG_ERROR)("Write %x to rom at %x",val,addr); - } - void writew(PhysPt addr,Bitu val){ - LOG(LOG_CPU,LOG_ERROR)("Write %x to rom at %x",val,addr); - } - void writed(PhysPt addr,Bitu val){ - LOG(LOG_CPU,LOG_ERROR)("Write %x to rom at %x",val,addr); - } -}; - - - -static IllegalPageHandler illegal_page_handler; -static RAMPageHandler ram_page_handler; -static ROMPageHandler rom_page_handler; - -void MEM_SetLFB(Bitu page, Bitu pages, PageHandler *handler, PageHandler *mmiohandler) { - memory.lfb.handler=handler; - memory.lfb.mmiohandler=mmiohandler; - memory.lfb.start_page=page; - memory.lfb.end_page=page+pages; - memory.lfb.pages=pages; - PAGING_ClearTLB(); -} - -PageHandler * MEM_GetPageHandler(Bitu phys_page) { - if (phys_page=memory.lfb.start_page) && (phys_page=memory.lfb.start_page+0x01000000/4096) && - (phys_page0;pages--) { - memory.phandlers[phys_page]=handler; - phys_page++; - } -} - -void MEM_ResetPageHandler(Bitu phys_page, Bitu pages) { - for (;pages>0;pages--) { - memory.phandlers[phys_page]=&ram_page_handler; - phys_page++; - } -} - -Bitu mem_strlen(PhysPt pt) { - Bitu x=0; - while (x<1024) { - if (!mem_readb_inline(pt+x)) return x; - x++; - } - return 0; //Hope this doesn't happen -} - -void mem_strcpy(PhysPt dest,PhysPt src) { - Bit8u r; - while ( (r = mem_readb(src++)) ) mem_writeb_inline(dest++,r); - mem_writeb_inline(dest,0); -} - -void mem_memcpy(PhysPt dest,PhysPt src,Bitu size) { - while (size--) mem_writeb_inline(dest++,mem_readb_inline(src++)); -} - -void MEM_BlockRead(PhysPt pt,void * data,Bitu size) { - Bit8u * write=reinterpret_cast(data); - while (size--) { - *write++=mem_readb_inline(pt++); - } -} - -void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size) { - Bit8u const * read = reinterpret_cast(data); - while (size--) { - mem_writeb_inline(pt++,*read++); - } -} - -void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size) { - mem_memcpy(dest,src,size); -} - -void MEM_StrCopy(PhysPt pt,char * data,Bitu size) { - while (size--) { - Bit8u r=mem_readb_inline(pt++); - if (!r) break; - *data++=r; - } - *data=0; -} - -Bitu MEM_TotalPages(void) { - return memory.pages; -} - -Bitu MEM_FreeLargest(void) { - Bitu size=0;Bitu largest=0; - Bitu index=XMS_START; - while (indexlargest) largest=size; - size=0; - } - index++; - } - if (size>largest) largest=size; - return largest; -} - -Bitu MEM_FreeTotal(void) { - Bitu free=0; - Bitu index=XMS_START; - while (index0) { - pages++; - handle=memory.mhandles[handle]; - } - return pages; -} - -//TODO Maybe some protection for this whole allocation scheme - -INLINE Bitu BestMatch(Bitu size) { - Bitu index=XMS_START; - Bitu first=0; - Bitu best=0xfffffff; - Bitu best_first=0; - while (indexsize) { - if (pages=size) && (index-first0) { - MemHandle next=memory.mhandles[handle]; - memory.mhandles[handle]=0; - handle=next; - } -} - -bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence) { - if (handle<=0) { - if (!pages) return true; - handle=MEM_AllocatePages(pages,sequence); - return (handle>0); - } - if (!pages) { - MEM_ReleasePages(handle); - handle=-1; - return true; - } - MemHandle index=handle; - MemHandle last;Bitu old_pages=0; - while (index>0) { - old_pages++; - last=index; - index=memory.mhandles[index]; - } - if (old_pages == pages) return true; - if (old_pages > pages) { - /* Decrease size */ - pages--;index=handle;old_pages--; - while (pages) { - index=memory.mhandles[index]; - pages--;old_pages--; - } - MemHandle next=memory.mhandles[index]; - memory.mhandles[index]=-1; - index=next; - while (old_pages) { - next=memory.mhandles[index]; - memory.mhandles[index]=0; - index=next; - old_pages--; - } - return true; - } else { - /* Increase size, check for enough free space */ - Bitu need=pages-old_pages; - if (sequence) { - index=last+1; - Bitu free=0; - while ((index<(MemHandle)memory.pages) && !memory.mhandles[index]) { - index++;free++; - } - if (free>=need) { - /* Enough space allocate more pages */ - index=last; - while (need) { - memory.mhandles[index]=index+1; - need--;index++; - } - memory.mhandles[index]=-1; - return true; - } else { - /* Not Enough space allocate new block and copy */ - MemHandle newhandle=MEM_AllocatePages(pages,true); - if (!newhandle) return false; - MEM_BlockCopy(newhandle*4096,handle*4096,old_pages*4096); - MEM_ReleasePages(handle); - handle=newhandle; - return true; - } - } else { - MemHandle rem=MEM_AllocatePages(need,false); - if (!rem) return false; - memory.mhandles[last]=rem; - return true; - } - } - return 0; -} - -MemHandle MEM_NextHandle(MemHandle handle) { - return memory.mhandles[handle]; -} - -MemHandle MEM_NextHandleAt(MemHandle handle,Bitu where) { - while (where) { - where--; - handle=memory.mhandles[handle]; - } - return handle; -} - - -/* - A20 line handling, - Basically maps the 4 pages at the 1mb to 0mb in the default page directory -*/ -bool MEM_A20_Enabled(void) { - return memory.a20.enabled; -} - -void MEM_A20_Enable(bool enabled) { - Bitu phys_base=enabled ? (1024/4) : 0; - for (Bitu i=0;i<16;i++) PAGING_MapPage((1024/4)+i,phys_base+i); - memory.a20.enabled=enabled; -} - - -/* Memory access functions */ -Bit16u mem_unalignedreadw(PhysPt address) { - return mem_readb_inline(address) | - mem_readb_inline(address+1) << 8; -} - -Bit32u mem_unalignedreadd(PhysPt address) { - return mem_readb_inline(address) | - (mem_readb_inline(address+1) << 8) | - (mem_readb_inline(address+2) << 16) | - (mem_readb_inline(address+3) << 24); -} - - -void mem_unalignedwritew(PhysPt address,Bit16u val) { - mem_writeb_inline(address,(Bit8u)val);val>>=8; - mem_writeb_inline(address+1,(Bit8u)val); -} - -void mem_unalignedwrited(PhysPt address,Bit32u val) { - mem_writeb_inline(address,(Bit8u)val);val>>=8; - mem_writeb_inline(address+1,(Bit8u)val);val>>=8; - mem_writeb_inline(address+2,(Bit8u)val);val>>=8; - mem_writeb_inline(address+3,(Bit8u)val); -} - - -bool mem_unalignedreadw_checked(PhysPt address, Bit16u * val) { - Bit8u rval1,rval2; - if (mem_readb_checked(address+0, &rval1)) return true; - if (mem_readb_checked(address+1, &rval2)) return true; - *val=(Bit16u)(((Bit8u)rval1) | (((Bit8u)rval2) << 8)); - return false; -} - -bool mem_unalignedreadd_checked(PhysPt address, Bit32u * val) { - Bit8u rval1,rval2,rval3,rval4; - if (mem_readb_checked(address+0, &rval1)) return true; - if (mem_readb_checked(address+1, &rval2)) return true; - if (mem_readb_checked(address+2, &rval3)) return true; - if (mem_readb_checked(address+3, &rval4)) return true; - *val=(Bit32u)(((Bit8u)rval1) | (((Bit8u)rval2) << 8) | (((Bit8u)rval3) << 16) | (((Bit8u)rval4) << 24)); - return false; -} - -bool mem_unalignedwritew_checked(PhysPt address,Bit16u val) { - if (mem_writeb_checked(address,(Bit8u)(val & 0xff))) return true;val>>=8; - if (mem_writeb_checked(address+1,(Bit8u)(val & 0xff))) return true; - return false; -} - -bool mem_unalignedwrited_checked(PhysPt address,Bit32u val) { - if (mem_writeb_checked(address,(Bit8u)(val & 0xff))) return true;val>>=8; - if (mem_writeb_checked(address+1,(Bit8u)(val & 0xff))) return true;val>>=8; - if (mem_writeb_checked(address+2,(Bit8u)(val & 0xff))) return true;val>>=8; - if (mem_writeb_checked(address+3,(Bit8u)(val & 0xff))) return true; - return false; -} - -Bit8u mem_readb(PhysPt address) { - return mem_readb_inline(address); -} - -Bit16u mem_readw(PhysPt address) { - return mem_readw_inline(address); -} - -Bit32u mem_readd(PhysPt address) { - return mem_readd_inline(address); -} - -void mem_writeb(PhysPt address,Bit8u val) { - mem_writeb_inline(address,val); -} - -void mem_writew(PhysPt address,Bit16u val) { - mem_writew_inline(address,val); -} - -void mem_writed(PhysPt address,Bit32u val) { - mem_writed_inline(address,val); -} - -static void write_p92(Bitu port,Bitu val,Bitu iolen) { - // Bit 0 = system reset (switch back to real mode) - if (val&1) E_Exit("XMS: CPU reset via port 0x92 not supported."); - memory.a20.controlport = val & ~2; - MEM_A20_Enable((val & 2)>0); -} - -static Bitu read_p92(Bitu port,Bitu iolen) { - return memory.a20.controlport | (memory.a20.enabled ? 0x02 : 0); -} - -void RemoveEMSPageFrame(void) { - /* Setup rom at 0xe0000-0xf0000 */ - for (Bitu ct=0xe0;ct<0xf0;ct++) { - memory.phandlers[ct] = &rom_page_handler; - } -} - -void PreparePCJRCartRom(void) { - /* Setup rom at 0xd0000-0xe0000 */ - for (Bitu ct=0xd0;ct<0xe0;ct++) { - memory.phandlers[ct] = &rom_page_handler; - } -} - -HostPt GetMemBase(void) { return MemBase; } - -class MEMORY:public Module_base{ -private: - IO_ReadHandleObject ReadHandler; - IO_WriteHandleObject WriteHandler; -public: - MEMORY(Section* configuration):Module_base(configuration){ - Bitu i; - Section_prop * section=static_cast(configuration); - - /* Setup the Physical Page Links */ - Bitu memsize=section->Get_int("memsize"); - - if (memsize < 1) memsize = 1; - /* max 63 to solve problems with certain xms handlers */ - if (memsize > MAX_MEMORY-1) { - LOG_MSG("Maximum memory size is %d MB",MAX_MEMORY - 1); - memsize = MAX_MEMORY-1; - } - if (memsize > SAFE_MEMORY-1) { - LOG_MSG("Memory sizes above %d MB are NOT recommended.",SAFE_MEMORY - 1); - LOG_MSG("Stick with the default values unless you are absolutely certain."); - } - MemBase = new Bit8u[memsize*1024*1024]; - if (!MemBase) E_Exit("Can't allocate main memory of %d MB",memsize); - /* Clear the memory, as new doesn't always give zeroed memory - * (Visual C debug mode). We want zeroed memory though. */ - memset((void*)MemBase,0,memsize*1024*1024); - memory.pages = (memsize*1024*1024)/4096; - /* Allocate the data for the different page information blocks */ - memory.phandlers=new PageHandler * [memory.pages]; - memory.mhandles=new MemHandle [memory.pages]; - for (i = 0;i < memory.pages;i++) { - memory.phandlers[i] = &ram_page_handler; - memory.mhandles[i] = 0; //Set to 0 for memory allocation - } - /* Setup rom at 0xc0000-0xc8000 */ - for (i=0xc0;i<0xc8;i++) { - memory.phandlers[i] = &rom_page_handler; - } - /* Setup rom at 0xf0000-0x100000 */ - for (i=0xf0;i<0x100;i++) { - memory.phandlers[i] = &rom_page_handler; - } - if (machine==MCH_PCJR) { - /* Setup cartridge rom at 0xe0000-0xf0000 */ - for (i=0xe0;i<0xf0;i++) { - memory.phandlers[i] = &rom_page_handler; - } - } - /* Reset some links */ - memory.links.used = 0; - // A20 Line - PS/2 system control port A - WriteHandler.Install(0x92,write_p92,IO_MB); - ReadHandler.Install(0x92,read_p92,IO_MB); - MEM_A20_Enable(false); - } - ~MEMORY(){ - delete [] MemBase; - delete [] memory.phandlers; - delete [] memory.mhandles; - } -}; - - -static MEMORY* test; - -static void MEM_ShutDown(Section * sec) { - delete test; -} - -void MEM_Init(Section * sec) { - /* shutdown function */ - test = new MEMORY(sec); - sec->AddDestroyFunction(&MEM_ShutDown); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include +#include +#include "dosbox.h" +#include "mem.h" + +#define MEM_MAXSIZE 16 /* The Size of memory used to get size of page table */ +#define memsize 8 /* 8 mb of memory */ +#define EMM_HANDLECOUNT 250 + +EMM_Handle EMM_Handles[EMM_HANDLECOUNT]; +PageEntry * PageEntries[MEM_MAXSIZE*1024*16]; /* Number of pages */ +Bit8u * memory=0; + +bool MEMORY_TestSpecial(PhysOff off) { + return (PageEntries[off >> 12]>0); +} + +void MEMORY_SetupHandler(Bit32u page,Bit32u pages,PageEntry * entry) { + for (Bit32u i=page;i>2);c++) { + writed(idata,mem_readd(off)); + idata+=4;off+=4; + } + for (c=1;c<=(size&3);c++) { + writeb(idata,mem_readb(off)); + idata+=1;off+=1; + } +} + +void MEM_BlockWrite(PhysOff off,void * data,Bitu size) { + Bitu c; + Bit8u * idata=(Bit8u *)data; + for (c=1;c<=(size>>2);c++) { + mem_writed(off,readd(idata)); + idata+=4;off+=4; + } + for (c=1;c<=(size&3);c++) { + mem_writeb(off,readb(idata)); + idata+=1;off+=1; + } +} + +void MEM_BlockCopy(PhysOff dest,PhysOff src,Bitu size) { + Bitu c; + for (c=1;c<=(size>>2);c++) { + mem_writed(dest,mem_readd(src)); + dest+=4;src+=4; + } + for (c=1;c<=(size&3);c++) { + mem_writeb(dest,mem_readb(src)); + dest+=1;src+=1; + } + + +}; + +void MEM_StrCopy(PhysOff off,char * data,Bitu size) { + Bit8u c; + while ((c=mem_readb(off)) && size) { + *data=c; + off++;data++;size--; + } + *data='\0'; +} + + + + +/* TODO Maybe check for page boundaries but that would be wasting lot's of time */ +void mem_writeb(PhysOff off,Bit8u val) { + PageEntry * entry=PageEntries[off >> 12]; + if (!entry) { writeb(memory+off,val);return; } + switch (entry->type) { + case MEMORY_RELOCATE: + writeb(entry->relocate+(off-entry->base),val); + break; + case MEMORY_HANDLER: + entry->handler.write(off-entry->base,val); + break; + default: + E_Exit("Write to Illegal Memory Address %4x",off); + } +} + +void mem_writew(PhysOff off,Bit16u val) { + PageEntry * entry=PageEntries[off >> 12]; + if (!entry) { writew(memory+off,val);return; } + switch (entry->type) { + case MEMORY_RELOCATE: + writew(entry->relocate+(off-entry->base),val); + break; + case MEMORY_HANDLER: + entry->handler.write(off-entry->base,(val & 0xFF)); + entry->handler.write(off-entry->base+1,(val >> 8)); + break; + default: + E_Exit("Write to Illegal Memory Address %4x",off); + } +} + +void mem_writed(PhysOff off,Bit32u val) { + PageEntry * entry=PageEntries[off >> 12]; + if (!entry) { writed(memory+off,val);return; } + switch (entry->type) { + case MEMORY_RELOCATE: + writed(entry->relocate+(off-entry->base),val); + break; + case MEMORY_HANDLER: + entry->handler.write(off-entry->base, (Bit8u)(val & 0xFF)); + entry->handler.write(off-entry->base+1,(Bit8u)(val >> 8) & 0xFF); + entry->handler.write(off-entry->base+2,(Bit8u)(val >> 16) & 0xFF); + entry->handler.write(off-entry->base+3,(Bit8u)(val >> 24) & 0xFF); + break; + default: + E_Exit("Write to Illegal Memory Address %4x",off); + } +} + +Bit8u mem_readb(PhysOff off) { + PageEntry * entry=PageEntries[off >> 12]; + if (!entry) { return readb(memory+off);} + switch (entry->type) { + case MEMORY_RELOCATE: + return readb(entry->relocate+(off-entry->base)); + case MEMORY_HANDLER: + return entry->handler.read(off-entry->base); + break; + default: + E_Exit("Read from Illegal Memory Address %4x",off); + } + return 0; /* Keep compiler happy */ +} + +Bit16u mem_readw(PhysOff off) { + PageEntry * entry=PageEntries[off >> 12]; + if (!entry) { return readw(memory+off);} + switch (entry->type) { + case MEMORY_RELOCATE: + return readw(entry->relocate+(off-entry->base)); + case MEMORY_HANDLER: + return entry->handler.read(off-entry->base) | + (entry->handler.read(off-entry->base+1) << 8); + break; + default: + E_Exit("Read from Illegal Memory Address %4x",off); + } + return 0; /* Keep compiler happy */ +} + +Bit32u mem_readd(PhysOff off) { + PageEntry * entry=PageEntries[off >> 12]; + if (!entry) { return readd(memory+off);} + switch (entry->type) { + case MEMORY_RELOCATE: + return readd(entry->relocate+(off-entry->base)); + case MEMORY_HANDLER: + return entry->handler.read(off-entry->base) | + (entry->handler.read(off-entry->base+1) << 8) | + (entry->handler.read(off-entry->base+2) << 16)| + (entry->handler.read(off-entry->base+3) << 24); + break; + default: + E_Exit("Read from Illegal Memory Address %4x",off); + } + return 0; /* Keep compiler happy */ +} + +/* The EMM Allocation Part */ + +/* If this returns 0 we got and error since 0 is always taken */ +static Bit16u EMM_GetFreeHandle(void) { + Bit16u i=0; + while (i*maxblock) *maxblock=EMM_Handles[index].size; + *total+=EMM_Handles[index].size; + } + if (EMM_Handles[index].next) index=EMM_Handles[index].next; + else break; + } +} + +void EMM_Allocate(Bit16u size,Bit16u * handle) { + Bit16u index=0;*handle=0; + while (EMM_Handles[index].active) { + if (EMM_Handles[index].free) { + /* Use entire block */ + if(EMM_Handles[index].size==size) { + EMM_Handles[index].free=false; + *handle=index; + break; + } + /* Split up block */ + if(EMM_Handles[index].size>size) { + Bit16u newindex=EMM_GetFreeHandle(); + EMM_Handles[newindex].active=true; + EMM_Handles[newindex].phys_base=EMM_Handles[newindex].phys_base+size*4096; + EMM_Handles[newindex].size=EMM_Handles[index].size-size; + EMM_Handles[newindex].free=true; + EMM_Handles[newindex].next=EMM_Handles[index].next; + EMM_Handles[index].next=newindex; + EMM_Handles[index].free=false; + EMM_Handles[index].size=size; + *handle=index; + break; + } + } + if (EMM_Handles[index].next) index=EMM_Handles[index].next; + else break; + } +} + +void EMM_Free(Bit16u handle) { + if (!EMM_Handles[handle].active) E_Exit("EMM:Tried to free illegal handle"); + EMM_Handles[handle].free=true; + //TODO join memory blocks +} + + +PageEntry HMA_PageEntry; + +void MEM_Init(void) { + memset((void *)&PageEntries,0,sizeof(PageEntries)); + memory=(Bit8u *)malloc(memsize*1024*1024); + if (!memory) { + E_Exit("Can't allocate memory for memory"); + } + /* Setup the HMA to wrap */ + HMA_PageEntry.type=MEMORY_RELOCATE;; + HMA_PageEntry.base=1024*1024; + HMA_PageEntry.relocate=memory; + Bitu i; + for (i=0;i<16;i++) { + PageEntries[i+256]=&HMA_PageEntry; + } + /* Setup the EMM Structures */ + for (i=0;i1) { + EMM_Handles[1].size=(memsize-1)*256-16; + } else { + EMM_Handles[0].size=0;; + } + EMM_Handles[1].active=true; + EMM_Handles[1].free=true; + EMM_Handles[1].phys_base=0x110000; +}; + + diff --git a/src/hardware/mixer.cpp b/src/hardware/mixer.cpp index 9693a30..8144e39 100644 --- a/src/hardware/mixer.cpp +++ b/src/hardware/mixer.cpp @@ -1,671 +1,254 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: mixer.cpp,v 1.53 2009/04/28 21:48:24 harekiet Exp $ */ - -/* - Remove the sdl code from here and have it handeld in the sdlmain. - That should call the mixer start from there or something. -*/ - -#include -#include -#include - -#if defined (WIN32) -//Midi listing -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#endif - -#include "SDL.h" -#include "mem.h" -#include "pic.h" -#include "dosbox.h" -#include "mixer.h" -#include "timer.h" -#include "setup.h" -#include "cross.h" -#include "support.h" -#include "mapper.h" -#include "hardware.h" -#include "programs.h" - -#define MIXER_SSIZE 4 -#define MIXER_SHIFT 14 -#define MIXER_REMAIN ((1< MIN_AUDIO) - return SAMP; - else return MIN_AUDIO; - } else return MAX_AUDIO; -} - -static struct { - Bit32s work[MIXER_BUFSIZE][2]; - Bitu pos,done; - Bitu needed, min_needed, max_needed; - Bit32u tick_add,tick_remain; - float mastervol[2]; - MixerChannel * channels; - bool nosound; - Bit32u freq; - Bit32u blocksize; -} mixer; - -Bit8u MixTemp[MIXER_BUFSIZE]; - -MixerChannel * MIXER_AddChannel(MIXER_Handler handler,Bitu freq,const char * name) { - MixerChannel * chan=new MixerChannel(); - chan->scale = 1.0; - chan->handler=handler; - chan->name=name; - chan->SetFreq(freq); - chan->next=mixer.channels; - chan->SetVolume(1,1); - chan->enabled=false; - mixer.channels=chan; - return chan; -} - -MixerChannel * MIXER_FindChannel(const char * name) { - MixerChannel * chan=mixer.channels; - while (chan) { - if (!strcasecmp(chan->name,name)) break; - chan=chan->next; - } - return chan; -} - -void MIXER_DelChannel(MixerChannel* delchan) { - MixerChannel * chan=mixer.channels; - MixerChannel * * where=&mixer.channels; - while (chan) { - if (chan==delchan) { - *where=chan->next; - delete delchan; - return; - } - where=&chan->next; - chan=chan->next; - } -} - -void MixerChannel::UpdateVolume(void) { - volmul[0]=(Bits)((1 << MIXER_VOLSHIFT)*scale*volmain[0]*mixer.mastervol[0]); - volmul[1]=(Bits)((1 << MIXER_VOLSHIFT)*scale*volmain[1]*mixer.mastervol[1]); -} - -void MixerChannel::SetVolume(float _left,float _right) { - volmain[0]=_left; - volmain[1]=_right; - UpdateVolume(); -} - -void MixerChannel::SetScale( float f ) { - scale = f; - UpdateVolume(); -} - -void MixerChannel::Enable(bool _yesno) { - if (_yesno==enabled) return; - enabled=_yesno; - if (enabled) { - freq_index=MIXER_REMAIN; - SDL_LockAudio(); - if (donedone) { - Bitu todo=needed-done; - todo*=freq_add; - if (todo & MIXER_REMAIN) { - todo=(todo >> MIXER_SHIFT) + 1; - } else { - todo=(todo >> MIXER_SHIFT); - } - handler(todo); - } -} - -void MixerChannel::AddSilence(void) { - if (done -inline void MixerChannel::AddSamples(Bitu len, const Type* data) { - Bits diff[2]; - Bitu mixpos=mixer.pos+done; - freq_index&=MIXER_REMAIN; - Bitu pos=0;Bitu new_pos; - - goto thestart; - for (;;) { - new_pos=freq_index >> MIXER_SHIFT; - if (pos=len) return; - if ( sizeof( Type) == 1) { - if (!signeddata) { - if (stereo) { - diff[0]=(((Bit8s)(data[pos*2+0] ^ 0x80)) << 8)-last[0]; - diff[1]=(((Bit8s)(data[pos*2+1] ^ 0x80)) << 8)-last[1]; - } else { - diff[0]=(((Bit8s)(data[pos] ^ 0x80)) << 8)-last[0]; - } - } else { - if (stereo) { - diff[0]=(data[pos*2+0] << 8)-last[0]; - diff[1]=(data[pos*2+1] << 8)-last[1]; - } else { - diff[0]=(data[pos] << 8)-last[0]; - } - } - //16bit and 32bit both contain 16bit data internally - } else { - if (signeddata) { - if (stereo) { - if (nativeorder) { - diff[0]=data[pos*2+0]-last[0]; - diff[1]=data[pos*2+1]-last[1]; - } else { - if ( sizeof( Type) == 2) { - diff[0]=(Bit16s)host_readw((HostPt)&data[pos*2+0])-last[0]; - diff[1]=(Bit16s)host_readw((HostPt)&data[pos*2+1])-last[1]; - } else { - diff[0]=(Bit32s)host_readd((HostPt)&data[pos*2+0])-last[0]; - diff[1]=(Bit32s)host_readd((HostPt)&data[pos*2+1])-last[1]; - } - } - } else { - if (nativeorder) { - diff[0]=data[pos]-last[0]; - } else { - if ( sizeof( Type) == 2) { - diff[0]=(Bit16s)host_readw((HostPt)&data[pos])-last[0]; - } else { - diff[0]=(Bit32s)host_readd((HostPt)&data[pos])-last[0]; - } - } - } - } else { - if (stereo) { - if (nativeorder) { - diff[0]=(Bits)data[pos*2+0]-32768-last[0]; - diff[1]=(Bits)data[pos*2+1]-32768-last[1]; - } else { - if ( sizeof( Type) == 2) { - diff[0]=(Bits)host_readw((HostPt)&data[pos*2+0])-32768-last[0]; - diff[1]=(Bits)host_readw((HostPt)&data[pos*2+1])-32768-last[1]; - } else { - diff[0]=(Bits)host_readd((HostPt)&data[pos*2+0])-32768-last[0]; - diff[1]=(Bits)host_readd((HostPt)&data[pos*2+1])-32768-last[1]; - } - } - } else { - if (nativeorder) { - diff[0]=(Bits)data[pos]-32768-last[0]; - } else { - if ( sizeof( Type) == 2) { - diff[0]=(Bits)host_readw((HostPt)&data[pos])-32768-last[0]; - } else { - diff[0]=(Bits)host_readd((HostPt)&data[pos])-32768-last[0]; - } - } - } - } - } - } - Bits diff_mul=freq_index & MIXER_REMAIN; - freq_index+=freq_add; - mixpos&=MIXER_BUFMASK; - Bits sample=last[0]+((diff[0]*diff_mul) >> MIXER_SHIFT); - mixer.work[mixpos][0]+=sample*volmul[0]; - if (stereo) sample=last[1]+((diff[1]*diff_mul) >> MIXER_SHIFT); - mixer.work[mixpos][1]+=sample*volmul[1]; - mixpos++;done++; - } -} - -void MixerChannel::AddStretched(Bitu len,Bit16s * data) { - if (done>=needed) { - LOG_MSG("Can't add, buffer full"); - return; - } - Bitu outlen=needed-done;Bits diff; - freq_index=0; - Bitu temp_add=(len << MIXER_SHIFT)/outlen; - Bitu mixpos=mixer.pos+done;done=needed; - Bitu pos=0; - diff=data[0]-last[0]; - while (outlen--) { - Bitu new_pos=freq_index >> MIXER_SHIFT; - if (pos> MIXER_SHIFT); - mixer.work[mixpos][0]+=sample*volmul[0]; - mixer.work[mixpos][1]+=sample*volmul[1]; - mixpos++; - } -} - -void MixerChannel::AddSamples_m8(Bitu len, const Bit8u * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_s8(Bitu len,const Bit8u * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_m8s(Bitu len,const Bit8s * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_s8s(Bitu len,const Bit8s * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_m16(Bitu len,const Bit16s * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_s16(Bitu len,const Bit16s * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_m16u(Bitu len,const Bit16u * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_s16u(Bitu len,const Bit16u * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_m32(Bitu len,const Bit32s * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_s32(Bitu len,const Bit32s * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_m16_nonnative(Bitu len,const Bit16s * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_s16_nonnative(Bitu len,const Bit16s * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_m16u_nonnative(Bitu len,const Bit16u * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_s16u_nonnative(Bitu len,const Bit16u * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_m32_nonnative(Bitu len,const Bit32s * data) { - AddSamples(len,data); -} -void MixerChannel::AddSamples_s32_nonnative(Bitu len,const Bit32s * data) { - AddSamples(len,data); -} - -void MixerChannel::FillUp(void) { - SDL_LockAudio(); - if (!enabled || doneMix(needed); - chan=chan->next; - } - if (CaptureState & (CAPTURE_WAVE|CAPTURE_VIDEO)) { - Bit16s convert[1024][2]; - Bitu added=needed-mixer.done; - if (added>1024) - added=1024; - Bitu readpos=(mixer.pos+mixer.done)&MIXER_BUFMASK; - for (Bitu i=0;i> MIXER_VOLSHIFT; - convert[i][0]=MIXER_CLIP(sample); - sample=mixer.work[readpos][1] >> MIXER_VOLSHIFT; - convert[i][1]=MIXER_CLIP(sample); - readpos=(readpos+1)&MIXER_BUFMASK; - } - CAPTURE_AddWave( mixer.freq, added, (Bit16s*)convert ); - } - //Reset the the tick_add for constant speed - if( Mixer_irq_important() ) - mixer.tick_add = ((mixer.freq) << MIXER_SHIFT)/1000; - mixer.done = needed; -} - -static void MIXER_Mix(void) { - SDL_LockAudio(); - MIXER_MixData(mixer.needed); - mixer.tick_remain+=mixer.tick_add; - mixer.needed+=(mixer.tick_remain>>MIXER_SHIFT); - mixer.tick_remain&=MIXER_REMAIN; - SDL_UnlockAudio(); -} - -static void MIXER_Mix_NoSound(void) { - MIXER_MixData(mixer.needed); - /* Clear piece we've just generated */ - for (Bitu i=0;inext) { - if (chan->done>mixer.needed) chan->done-=mixer.needed; - else chan->done=0; - } - /* Set values for next tick */ - mixer.tick_remain+=mixer.tick_add; - mixer.needed=mixer.tick_remain>>MIXER_SHIFT; - mixer.tick_remain&=MIXER_REMAIN; - mixer.done=0; -} - -static void MIXER_CallBack(void * userdata, Uint8 *stream, int len) { - Bitu need=(Bitu)len/MIXER_SSIZE; - Bit16s * output=(Bit16s *)stream; - Bitu reduce; - Bitu pos, index, index_add; - Bits sample; - /* Enough room in the buffer ? */ - if (mixer.done < need) { -// LOG_MSG("Full underrun need %d, have %d, min %d", need, mixer.done, mixer.min_needed); - if((need - mixer.done) > (need >>7) ) //Max 1 procent stretch. - return; - reduce = mixer.done; - index_add = (reduce << MIXER_SHIFT) / need; - mixer.tick_add = ((mixer.freq+mixer.min_needed) << MIXER_SHIFT)/1000; - } else if (mixer.done < mixer.max_needed) { - Bitu left = mixer.done - need; - if (left < mixer.min_needed) { - if( !Mixer_irq_important() ) { - Bitu needed = mixer.needed - need; - Bitu diff = (mixer.min_needed>needed?mixer.min_needed:needed) - left; - mixer.tick_add = ((mixer.freq+(diff*3)) << MIXER_SHIFT)/1000; - left = 0; //No stretching as we compensate with the tick_add value - } else { - left = (mixer.min_needed - left); - left = 1 + (2*left) / mixer.min_needed; //left=1,2,3 - } -// LOG_MSG("needed underrun need %d, have %d, min %d, left %d", need, mixer.done, mixer.min_needed, left); - reduce = need - left; - index_add = (reduce << MIXER_SHIFT) / need; - } else { - reduce = need; - index_add = (1 << MIXER_SHIFT); -// LOG_MSG("regular run need %d, have %d, min %d, left %d", need, mixer.done, mixer.min_needed, left); - - /* Mixer tick value being updated: - * 3 cases: - * 1) A lot too high. >division by 5. but maxed by 2* min to prevent too fast drops. - * 2) A little too high > division by 8 - * 3) A little to nothing above the min_needed buffer > go to default value - */ - Bitu diff = left - mixer.min_needed; - if(diff > (mixer.min_needed<<1)) diff = mixer.min_needed<<1; - if(diff > (mixer.min_needed>>1)) - mixer.tick_add = ((mixer.freq-(diff/5)) << MIXER_SHIFT)/1000; - else if (diff > (mixer.min_needed>>4)) - mixer.tick_add = ((mixer.freq-(diff>>3)) << MIXER_SHIFT)/1000; - else - mixer.tick_add = (mixer.freq<< MIXER_SHIFT)/1000; - } - } else { - /* There is way too much data in the buffer */ -// LOG_MSG("overflow run need %d, have %d, min %d", need, mixer.done, mixer.min_needed); - if (mixer.done > MIXER_BUFSIZE) - index_add = MIXER_BUFSIZE - 2*mixer.min_needed; - else - index_add = mixer.done - 2*mixer.min_needed; - index_add = (index_add << MIXER_SHIFT) / need; - reduce = mixer.done - 2* mixer.min_needed; - mixer.tick_add = ((mixer.freq-(mixer.min_needed/5)) << MIXER_SHIFT)/1000; - } - /* Reduce done count in all channels */ - for (MixerChannel * chan=mixer.channels;chan;chan=chan->next) { - if (chan->done>reduce) chan->done-=reduce; - else chan->done=0; - } - - // Reset mixer.tick_add when irqs are important - if( Mixer_irq_important() ) - mixer.tick_add=(mixer.freq<< MIXER_SHIFT)/1000; - - mixer.done -= reduce; - mixer.needed -= reduce; - pos = mixer.pos; - mixer.pos = (mixer.pos + reduce) & MIXER_BUFMASK; - index = 0; - if(need != reduce) { - while (need--) { - Bitu i = (pos + (index >> MIXER_SHIFT )) & MIXER_BUFMASK; - index += index_add; - sample=mixer.work[i][0]>>MIXER_VOLSHIFT; - *output++=MIXER_CLIP(sample); - sample=mixer.work[i][1]>>MIXER_VOLSHIFT; - *output++=MIXER_CLIP(sample); - } - /* Clean the used buffer */ - while (reduce--) { - pos &= MIXER_BUFMASK; - mixer.work[pos][0]=0; - mixer.work[pos][1]=0; - pos++; - } - } else { - while (reduce--) { - pos &= MIXER_BUFMASK; - sample=mixer.work[pos][0]>>MIXER_VOLSHIFT; - *output++=MIXER_CLIP(sample); - sample=mixer.work[pos][1]>>MIXER_VOLSHIFT; - *output++=MIXER_CLIP(sample); - mixer.work[pos][0]=0; - mixer.work[pos][1]=0; - pos++; - } - } -} - -static void MIXER_Stop(Section* sec) { -} - -class MIXER : public Program { -public: - void MakeVolume(char * scan,float & vol0,float & vol1) { - Bitu w=0; - bool db=(toupper(*scan)=='D'); - if (db) scan++; - while (*scan) { - if (*scan==':') { - ++scan;w=1; - } - char * before=scan; - float val=(float)strtod(scan,&scan); - if (before==scan) { - ++scan;continue; - } - if (!db) val/=100; - else val=powf(10.0f,(float)val/20.0f); - if (val<0) val=1.0f; - if (!w) { - vol0=val; - } else { - vol1=val; - } - } - if (!w) vol1=vol0; - } - - void Run(void) { - if(cmd->FindExist("/LISTMIDI")) { - ListMidi(); - return; - } - if (cmd->FindString("MASTER",temp_line,false)) { - MakeVolume((char *)temp_line.c_str(),mixer.mastervol[0],mixer.mastervol[1]); - } - MixerChannel * chan=mixer.channels; - while (chan) { - if (cmd->FindString(chan->name,temp_line,false)) { - MakeVolume((char *)temp_line.c_str(),chan->volmain[0],chan->volmain[1]); - } - chan->UpdateVolume(); - chan=chan->next; - } - if (cmd->FindExist("/NOSHOW")) return; - chan=mixer.channels; - WriteOut("Channel Main Main(dB)\n"); - ShowVolume("MASTER",mixer.mastervol[0],mixer.mastervol[1]); - for (chan=mixer.channels;chan;chan=chan->next) - ShowVolume(chan->name,chan->volmain[0],chan->volmain[1]); - } -private: - void ShowVolume(const char * name,float vol0,float vol1) { - WriteOut("%-8s %3.0f:%-3.0f %+3.2f:%-+3.2f \n",name, - vol0*100,vol1*100, - 20*log(vol0)/log(10.0f),20*log(vol1)/log(10.0f) - ); - } - - void ListMidi(){ -#if defined (WIN32) - unsigned int total = midiOutGetNumDevs(); - for(unsigned int i=0;i 31) E_Exit("Too long mixer channel name"); - safe_strncpy(m_name,name,32); - installed = true; - return MIXER_AddChannel(handler,freq,name); - } else { - E_Exit("allready added mixer channel."); - return 0; //Compiler happy - } -} - -MixerObject::~MixerObject(){ - if(!installed) return; - MIXER_DelChannel(MIXER_FindChannel(m_name)); -} - - -void MIXER_Init(Section* sec) { - sec->AddDestroyFunction(&MIXER_Stop); - - Section_prop * section=static_cast(sec); - /* Read out config section */ - mixer.freq=section->Get_int("rate"); - mixer.nosound=section->Get_bool("nosound"); - mixer.blocksize=section->Get_int("blocksize"); - - /* Initialize the internal stuff */ - mixer.channels=0; - mixer.pos=0; - mixer.done=0; - memset(mixer.work,0,sizeof(mixer.work)); - mixer.mastervol[0]=1.0f; - mixer.mastervol[1]=1.0f; - - /* Start the Mixer using SDL Sound at 22 khz */ - SDL_AudioSpec spec; - SDL_AudioSpec obtained; - - spec.freq=mixer.freq; - spec.format=AUDIO_S16SYS; - spec.channels=2; - spec.callback=MIXER_CallBack; - spec.userdata=NULL; - spec.samples=(Uint16)mixer.blocksize; - - mixer.tick_remain=0; - if (mixer.nosound) { - LOG_MSG("MIXER:No Sound Mode Selected."); - mixer.tick_add=((mixer.freq) << MIXER_SHIFT)/1000; - TIMER_AddTickHandler(MIXER_Mix_NoSound); - } else if (SDL_OpenAudio(&spec, &obtained) <0 ) { - mixer.nosound = true; - LOG_MSG("MIXER:Can't open audio: %s , running in nosound mode.",SDL_GetError()); - mixer.tick_add=((mixer.freq) << MIXER_SHIFT)/1000; - TIMER_AddTickHandler(MIXER_Mix_NoSound); - } else { - mixer.freq=obtained.freq; - mixer.blocksize=obtained.samples; - mixer.tick_add=(mixer.freq << MIXER_SHIFT)/1000; - TIMER_AddTickHandler(MIXER_Mix); - SDL_PauseAudio(0); - } - mixer.min_needed=section->Get_int("prebuffer"); - if (mixer.min_needed>100) mixer.min_needed=100; - mixer.min_needed=(mixer.freq*mixer.min_needed)/1000; - mixer.max_needed=mixer.blocksize * 2 + 2*mixer.min_needed; - mixer.needed=mixer.min_needed+1; - PROGRAMS_MakeFile("MIXER.COM",MIXER_ProgramStart); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Remove the sdl code from here and have it handeld in the sdlmain. + That should call the mixer start from there or something. +*/ + +#include +#include +#include "dosbox.h" +#include "mixer.h" +#include "timer.h" + +#define MIXER_MAXCHAN 8 +#define MIXER_BLOCKSIZE 1024 +#define MIXER_BUFSIZE MIXER_BLOCKSIZE*8 +#define MIXER_SSIZE 4 +#define MIXER_SHIFT 16 +#define MIXER_REMAIN ((1<playing=false; + chan->volume=255; + chan->mode=MIXER_16STEREO; + chan->handler=handler; + chan->name=name; + chan->sample_add=(freq<next=first_channel; + first_channel=chan; + return chan; +}; + +void MIXER_SetFreq(MIXER_Channel * chan,Bit32u freq) { + if (chan) { + chan->freq=freq; + /* Calculate the new addition value */ + chan->sample_add=(freq<mode=mode; +}; + +void MIXER_SetVolume(MIXER_Channel * chan,Bit8u vol) { + if (chan) chan->volume=vol; +} + +void MIXER_Enable(MIXER_Channel * chan,bool enable) { + if (chan) chan->playing=enable; +} + + + +/* Mix a certain amount of new samples */ +static void MIXER_MixData(Bit32u samples) { +/* This Should mix the channels */ + if (!samples) return; + if (samples>MIXER_BUFSIZE) samples=MIXER_BUFSIZE; + /* 16-bit stereo is 4 bytes per sample */ + memset((void *)&mix_buftemp,0,samples*MIXER_SSIZE); + MIXER_Channel * chan=first_channel; + while (chan) { + if (chan->playing) { + Bit32u chan_samples=samples*chan->sample_add; + Bit32u real_samples=chan_samples>>MIXER_SHIFT; + if (chan_samples & MIXER_REMAIN) real_samples++; + (chan->handler)((Bit8u*)&temp_m8,real_samples); + switch (chan->mode) { + case MIXER_8MONO: + /* Mix a 8 bit mono stream into the final 16 bit stereo output stream */ + { + /* Mix the data with output buffer */ + Bit32s newsample;Bit32u sample_read=0;Bit32u sample_add=chan->sample_add; + for (Bit32u mix=0;mix> MIXER_SHIFT; + sample_read+=sample_add; + newsample=mix_buftemp[mix][0]+((Bit8s)(temp_m8[pos][0]^0x80) << 8); + if (newsample>MAX_AUDIO) mix_buftemp[mix][0]=MAX_AUDIO; + else if (newsampleMAX_AUDIO) mix_buftemp[mix][1]=MAX_AUDIO; + else if (newsamplesample_add; + for (Bit32u mix=0;mix> MIXER_SHIFT; + sample_read+=sample_add; + newsample=mix_buftemp[mix][0]+temp_m16[pos][0]; + if (newsample>MAX_AUDIO) mix_buftemp[mix][0]=MAX_AUDIO; + else if (newsampleMAX_AUDIO) mix_buftemp[mix][1]=MAX_AUDIO; + else if (newsamplesample_add; + for (Bit32u mix=0;mix> MIXER_SHIFT; + sample_read+=sample_add; + newsample=mix_buftemp[mix][0]+temp_s16[pos][0]; + if (newsample>MAX_AUDIO) mix_buftemp[mix][0]=MAX_AUDIO; + else if (newsampleMAX_AUDIO) mix_buftemp[mix][1]=MAX_AUDIO; + else if (newsamplemode); + } + } + chan=chan->next; + } + Bit32u buf_remain=MIXER_BUFSIZE-mix_writepos; + /* Fill the samples size buffer with 0's */ + if (buf_remain>samples) { + memcpy(&mix_bufout[mix_writepos][0],&mix_buftemp[0][0],samples*MIXER_SSIZE); + mix_writepos+=samples; + } else { + memcpy(&mix_bufout[mix_writepos][0],&mix_buftemp[0][0],buf_remain*MIXER_SSIZE); + memcpy(&mix_bufout[0][0],&mix_buftemp[buf_remain][0],(samples-buf_remain)*MIXER_SSIZE); + mix_writepos=(mix_writepos+samples)-MIXER_BUFSIZE; + } + + +} + +void MIXER_Mix(Bitu ticks) { +/* Check for 1 ms of sound to mix */ + Bitu count=(ticks*mix_add)+mix_remain; + mix_remain=count&((1<<10)-1); + count>>=10; + Bit32u size=MIXER_BUFSIZE+mix_writepos-mix_readpos; + if (size>=MIXER_BUFSIZE) size-=MIXER_BUFSIZE; + if (size>MIXER_BLOCKSIZE+2048) return; + MIXER_MixData(count); + +} + +static Bit32u last_pos; +static void MIXER_CallBack(void * userdata, Uint8 *stream, int len) { + /* Copy data from buf_out to the stream */ + + Bit32u remain=MIXER_BUFSIZE-mix_readpos; + if (remain>=len/MIXER_SSIZE) { + memcpy((void *)stream,(void *)&mix_bufout[mix_readpos][0],len); + } else { + memcpy((void *)stream,(void *)&mix_bufout[mix_readpos][0],remain*MIXER_SSIZE); + stream+=remain*MIXER_SSIZE; + memcpy((void *)stream,(void *)&mix_bufout[0][0],(len)-remain*MIXER_SSIZE); + } + mix_readpos+=(len/MIXER_SSIZE); + if (mix_readpos>=MIXER_BUFSIZE) mix_readpos-=MIXER_BUFSIZE; +} + + + +void MIXER_Init(void) { + /* Initialize the internal stuff */ + first_channel=0; + mix_ticks=GetTicks(); + mix_bufextra=0; + mix_writepos=0; + mix_readpos=0; + + /* Start the Mixer using SDL Sound at 22 khz */ + SDL_AudioSpec spec; + SDL_AudioSpec obtained; + mix_add=((MIXER_FREQ) << 10)/1000; + mix_remain=0; + spec.freq=MIXER_FREQ; + spec.format=AUDIO_S16SYS; + spec.channels=2; + spec.callback=MIXER_CallBack; + spec.userdata=NULL; + spec.samples=MIXER_BLOCKSIZE; + + TIMER_RegisterTickHandler(MIXER_Mix); + + if ( SDL_OpenAudio(&spec, &obtained) < 0 ) { + LOG_MSG("No sound output device found, starting in no sound mode"); + } else { + MIXER_MixData(MIXER_BLOCKSIZE/MIXER_SSIZE); + SDL_PauseAudio(0); + } +} diff --git a/src/hardware/mpu401.cpp b/src/hardware/mpu401.cpp deleted file mode 100644 index ebd94c7..0000000 --- a/src/hardware/mpu401.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: mpu401.cpp,v 1.28 2008/11/10 15:29:38 qbix79 Exp $ */ - -#include -#include "dosbox.h" -#include "inout.h" -#include "pic.h" -#include "setup.h" -#include "cpu.h" -#include "support.h" - -void MIDI_RawOutByte(Bit8u data); -bool MIDI_Available(void); - -static void MPU401_Event(Bitu); -static void MPU401_Reset(void); -static void MPU401_EOIHandler(void); - -#define MPU401_VERSION 0x15 -#define MPU401_REVISION 0x01 -#define MPU401_QUEUE 32 -#define MPU401_TIMECONSTANT (60000000/1000.0f) - -enum MpuMode { M_UART,M_INTELLIGENT }; -enum MpuDataType {T_OVERFLOW,T_MARK,T_MIDI_SYS,T_MIDI_NORM,T_COMMAND}; - -static void MPU401_WriteData(Bitu port,Bitu val,Bitu iolen); - -/* Messages sent to MPU-401 from host */ -#define MSG_EOX 0xf7 -#define MSG_OVERFLOW 0xf8 -#define MSG_MARK 0xfc - -/* Messages sent to host from MPU-401 */ -#define MSG_MPU_OVERFLOW 0xf8 -#define MSG_MPU_COMMAND_REQ 0xf9 -#define MSG_MPU_END 0xfc -#define MSG_MPU_CLOCK 0xfd -#define MSG_MPU_ACK 0xfe - -static struct { - bool intelligent; - MpuMode mode; - Bitu irq; - Bit8u queue[MPU401_QUEUE]; - Bitu queue_pos,queue_used; - struct track { - Bits counter; - Bit8u value[8],sys_val; - Bit8u vlength,length; - MpuDataType type; - } playbuf[8],condbuf; - struct { - bool conductor,cond_req,cond_set, block_ack; - bool playing,reset; - bool wsd,wsm,wsd_start; - bool run_irq,irq_pending; - bool send_now; - Bits data_onoff; - Bitu command_byte; - Bit8u tmask,cmask,amask; - Bit16u midi_mask; - Bit16u req_mask; - Bit8u channel,old_chan; - } state; - struct { - Bit8u timebase,old_timebase; - Bit8u tempo,old_tempo; - Bit8u tempo_rel,old_tempo_rel; - Bit8u tempo_grad; - Bit8u cth_rate,cth_counter; - bool clock_to_host,cth_active; - } clock; -} mpu; - - -static void QueueByte(Bit8u data) { - if (mpu.state.block_ack) {mpu.state.block_ack=false;return;} - if (mpu.queue_used==0 && mpu.intelligent) { - mpu.state.irq_pending=true; - PIC_ActivateIRQ(mpu.irq); - } - if (mpu.queue_used=MPU401_QUEUE) mpu.queue_pos-=MPU401_QUEUE; - if (pos>=MPU401_QUEUE) pos-=MPU401_QUEUE; - mpu.queue_used++; - mpu.queue[pos]=data; - } else LOG(LOG_MISC,LOG_NORMAL)("MPU401:Data queue full"); -} - -static void ClrQueue(void) { - mpu.queue_used=0; - mpu.queue_pos=0; -} - -static Bitu MPU401_ReadStatus(Bitu port,Bitu iolen) { - Bit8u ret=0x3f; /* Bits 6 and 7 clear */ - if (!mpu.queue_used) ret|=0x80; - return ret; -} - -static void MPU401_WriteCommand(Bitu port,Bitu val,Bitu iolen) { - mpu.state.reset=0; - if (val<=0x2f) { - switch (val&3) { /* MIDI stop, start, continue */ - case 1: {MIDI_RawOutByte(0xfc);break;} - case 2: {MIDI_RawOutByte(0xfa);break;} - case 3: {MIDI_RawOutByte(0xfb);break;} - } - if (val&0x20) LOG(LOG_MISC,LOG_ERROR)("MPU-401:Unhandled Recording Command %x",val); - switch (val&0xc) { - case 0x4: /* Stop */ - PIC_RemoveEvents(MPU401_Event); - mpu.state.playing=false; - for (Bitu i=0xb0;i<0xbf;i++) { /* All notes off */ - MIDI_RawOutByte(i); - MIDI_RawOutByte(0x7b); - MIDI_RawOutByte(0); - } - break; - case 0x8: /* Play */ - LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Intelligent mode playback started"); - mpu.state.playing=true; - PIC_RemoveEvents(MPU401_Event); - PIC_AddEvent(MPU401_Event,MPU401_TIMECONSTANT/(mpu.clock.tempo*mpu.clock.timebase)); - ClrQueue(); - break; - } - } - else if (val>=0xa0 && val<=0xa7) { /* Request play counter */ - if (mpu.state.cmask&(1<<(val&7))) QueueByte(mpu.playbuf[val&7].counter); - } - else if (val>=0xd0 && val<=0xd7) { /* Send data */ - mpu.state.old_chan=mpu.state.channel; - mpu.state.channel=val&7; - mpu.state.wsd=true; - mpu.state.wsm=false; - mpu.state.wsd_start=true; - } - else - switch (val) { - case 0xdf: /* Send system message */ - mpu.state.wsd=false; - mpu.state.wsm=true; - mpu.state.wsd_start=true; - break; - case 0x8e: /* Conductor */ - mpu.state.cond_set=false; - break; - case 0x8f: - mpu.state.cond_set=true; - break; - case 0x94: /* Clock to host */ - mpu.clock.clock_to_host=false; - break; - case 0x95: - mpu.clock.clock_to_host=true; - break; - case 0xc2: /* Internal timebase */ - mpu.clock.timebase=48; - break; - case 0xc3: - mpu.clock.timebase=72; - break; - case 0xc4: - mpu.clock.timebase=96; - break; - case 0xc5: - mpu.clock.timebase=120; - break; - case 0xc6: - mpu.clock.timebase=144; - break; - case 0xc7: - mpu.clock.timebase=168; - break; - case 0xc8: - mpu.clock.timebase=192; - break; - /* Commands with data byte */ - case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6: - case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef: - mpu.state.command_byte=val; - break; - /* Commands 0xa# returning data */ - case 0xab: /* Request and clear recording counter */ - QueueByte(MSG_MPU_ACK); - QueueByte(0); - return; - case 0xac: /* Request version */ - QueueByte(MSG_MPU_ACK); - QueueByte(MPU401_VERSION); - return; - case 0xad: /* Request revision */ - QueueByte(MSG_MPU_ACK); - QueueByte(MPU401_REVISION); - return; - case 0xaf: /* Request tempo */ - QueueByte(MSG_MPU_ACK); - QueueByte(mpu.clock.tempo); - return; - case 0xb1: /* Reset relative tempo */ - mpu.clock.tempo_rel=40; - break; - case 0xb9: /* Clear play map */ - case 0xb8: /* Clear play counters */ - for (Bitu i=0xb0;i<0xbf;i++) { /* All notes off */ - MIDI_RawOutByte(i); - MIDI_RawOutByte(0x7b); - MIDI_RawOutByte(0); - } - for (Bitu i=0;i<8;i++) { - mpu.playbuf[i].counter=0; - mpu.playbuf[i].type=T_OVERFLOW; - } - mpu.condbuf.counter=0; - mpu.condbuf.type=T_OVERFLOW; - if (!(mpu.state.conductor=mpu.state.cond_set)) mpu.state.cond_req=0; - mpu.state.amask=mpu.state.tmask; - mpu.state.req_mask=0; - mpu.state.irq_pending=true; - break; - case 0xff: /* Reset MPU-401 */ - LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Reset %X",val); - mpu.state.reset=1; - if (CPU_Cycles > 5) { //It came from the desert wants a fast irq - CPU_CycleLeft += CPU_Cycles; - CPU_Cycles = 5; - } - MPU401_Reset(); - break; - case 0x3f: /* UART mode */ - LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Set UART mode %X",val); - mpu.mode=M_UART; - break; - default:; - //LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Unhandled command %X",val); - } - QueueByte(MSG_MPU_ACK); -} - -static Bitu MPU401_ReadData(Bitu port,Bitu iolen) { - Bit8u ret=MSG_MPU_ACK; - if (mpu.queue_used) { - if (mpu.queue_pos>=MPU401_QUEUE) mpu.queue_pos-=MPU401_QUEUE; - ret=mpu.queue[mpu.queue_pos]; - mpu.queue_pos++;mpu.queue_used--; - } - if (!mpu.intelligent) return ret; - - if (mpu.queue_used == 0) PIC_DeActivateIRQ(mpu.irq); - - if (ret>=0xf0 && ret<=0xf7) { /* MIDI data request */ - mpu.state.channel=ret&7; - mpu.state.data_onoff=0; - mpu.state.cond_req=false; - } - if (ret==MSG_MPU_COMMAND_REQ) { - mpu.state.data_onoff=0; - mpu.state.cond_req=true; - if (mpu.condbuf.type!=T_OVERFLOW) { - mpu.state.block_ack=true; - MPU401_WriteCommand(0x331,mpu.condbuf.value[0],1); - if (mpu.state.command_byte) MPU401_WriteData(0x330,mpu.condbuf.value[1],1); - } - mpu.condbuf.type=T_OVERFLOW; - } - if (ret==MSG_MPU_END || ret==MSG_MPU_CLOCK || ret==MSG_MPU_ACK) { - mpu.state.data_onoff=-1; - MPU401_EOIHandler(); - } - return ret; -} - -static void MPU401_WriteData(Bitu port,Bitu val,Bitu iolen) { - if (mpu.mode==M_UART) {MIDI_RawOutByte(val);return;} - switch (mpu.state.command_byte) { /* 0xe# command data */ - case 0x00: - break; - case 0xe0: /* Set tempo */ - mpu.state.command_byte=0; - mpu.clock.tempo=val; - return; - case 0xe1: /* Set relative tempo */ - mpu.state.command_byte=0; - if (val!=0x40) //default value - LOG(LOG_MISC,LOG_ERROR)("MPU-401:Relative tempo change not implemented"); - return; - case 0xe7: /* Set internal clock to host interval */ - mpu.state.command_byte=0; - mpu.clock.cth_rate=val>>2; - return; - case 0xec: /* Set active track mask */ - mpu.state.command_byte=0; - mpu.state.tmask=val; - return; - case 0xed: /* Set play counter mask */ - mpu.state.command_byte=0; - mpu.state.cmask=val; - return; - case 0xee: /* Set 1-8 MIDI channel mask */ - mpu.state.command_byte=0; - mpu.state.midi_mask&=0xff00; - mpu.state.midi_mask|=val; - return; - case 0xef: /* Set 9-16 MIDI channel mask */ - mpu.state.command_byte=0; - mpu.state.midi_mask&=0x00ff; - mpu.state.midi_mask|=((Bit16u)val)<<8; - return; - //case 0xe2: /* Set graduation for relative tempo */ - //case 0xe4: /* Set metronome */ - //case 0xe6: /* Set metronome measure length */ - default: - mpu.state.command_byte=0; - return; - } - static Bitu length,cnt,posd; - if (mpu.state.wsd) { /* Directly send MIDI message */ - if (mpu.state.wsd_start) { - mpu.state.wsd_start=0; - cnt=0; - switch (val&0xf0) { - case 0xc0:case 0xd0: - mpu.playbuf[mpu.state.channel].value[0]=val; - length=2; - break; - case 0x80:case 0x90:case 0xa0:case 0xb0:case 0xe0: - mpu.playbuf[mpu.state.channel].value[0]=val; - length=3; - break; - case 0xf0: - LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal WSD byte"); - mpu.state.wsd=0; - mpu.state.channel=mpu.state.old_chan; - return; - default: /* MIDI with running status */ - cnt++; - MIDI_RawOutByte(mpu.playbuf[mpu.state.channel].value[0]); - } - } - if (cnt0xf7) { - mpu.playbuf[mpu.state.channel].type=T_MARK; - mpu.playbuf[mpu.state.channel].sys_val=val; - length=1; - } else { - LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal message"); - mpu.playbuf[mpu.state.channel].type=T_MIDI_SYS; - mpu.playbuf[mpu.state.channel].sys_val=val; - length=1; - } - break; - case 0xc0: case 0xd0: /* MIDI Message */ - mpu.playbuf[mpu.state.channel].type=T_MIDI_NORM; - length=mpu.playbuf[mpu.state.channel].length=2; - break; - case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xe0: - mpu.playbuf[mpu.state.channel].type=T_MIDI_NORM; - length=mpu.playbuf[mpu.state.channel].length=3; - break; - default: /* MIDI data with running status */ - posd++; - mpu.playbuf[mpu.state.channel].vlength++; - mpu.playbuf[mpu.state.channel].type=T_MIDI_NORM; - length=mpu.playbuf[mpu.state.channel].length; - break; - } - } - if (!(posd==1 && val>=0xf0)) mpu.playbuf[mpu.state.channel].value[posd-1]=val; - if (posd==length) MPU401_EOIHandler(); - } -} - -static void MPU401_IntelligentOut(Bit8u chan) { - Bitu val; - switch (mpu.playbuf[chan].type) { - case T_OVERFLOW: - break; - case T_MARK: - val=mpu.playbuf[chan].sys_val; - if (val==0xfc) { - MIDI_RawOutByte(val); - mpu.state.amask&=~(1<= mpu.clock.cth_rate) { - mpu.clock.cth_counter=0; - mpu.state.req_mask|=(1<<13); - } - } - if (!mpu.state.irq_pending && mpu.state.req_mask) MPU401_EOIHandler(); -next_event: - PIC_RemoveEvents(MPU401_Event); - Bitu new_time; - if ((new_time=mpu.clock.tempo*mpu.clock.timebase)==0) return; - PIC_AddEvent(MPU401_Event,MPU401_TIMECONSTANT/new_time); -} - -static void MPU401_EOIHandler(void) { - if (mpu.state.send_now) { - mpu.state.send_now=false; - if (mpu.state.cond_req) UpdateConductor(); - else UpdateTrack(mpu.state.channel); - } - mpu.state.irq_pending=false; - if (!mpu.state.playing || !mpu.state.req_mask) return; - Bitu i=0; - do { - if (mpu.state.req_mask&(1<(configuration); - const char* s_mpu = section->Get_string("mpu401"); - if(strcasecmp(s_mpu,"none") == 0) return; - if(strcasecmp(s_mpu,"off") == 0) return; - if(strcasecmp(s_mpu,"false") == 0) return; - if (!MIDI_Available()) return; - /*Enabled and there is a Midi */ - installed = true; - - WriteHandler[0].Install(0x330,&MPU401_WriteData,IO_MB); - WriteHandler[1].Install(0x331,&MPU401_WriteCommand,IO_MB); - ReadHandler[0].Install(0x330,&MPU401_ReadData,IO_MB); - ReadHandler[1].Install(0x331,&MPU401_ReadStatus,IO_MB); - - mpu.queue_used=0; - mpu.queue_pos=0; - mpu.mode=M_UART; - mpu.irq=9; /* Princess Maker 2 wants it on irq 9 */ - - mpu.intelligent = true; //Default is on - if(strcasecmp(s_mpu,"uart") == 0) mpu.intelligent = false; - if (!mpu.intelligent) return; - /*Set IRQ and unmask it(for timequest/princess maker 2) */ - PIC_SetIRQMask(mpu.irq,false); - MPU401_Reset(); - } - ~MPU401(){ - if(!installed) return; - Section_prop * section=static_cast(m_configuration); - if(strcasecmp(section->Get_string("mpu401"),"intelligent")) return; - PIC_SetIRQMask(mpu.irq,true); - } -}; - -static MPU401* test; - -void MPU401_Destroy(Section* sec){ - delete test; -} - -void MPU401_Init(Section* sec) { - test = new MPU401(sec); - sec->AddDestroyFunction(&MPU401_Destroy,true); -} diff --git a/src/hardware/opl.cpp b/src/hardware/opl.cpp deleted file mode 100644 index da78414..0000000 --- a/src/hardware/opl.cpp +++ /dev/null @@ -1,1452 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * OPL2/OPL3 emulation library - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -/* - * Originally based on ADLIBEMU.C, an AdLib/OPL2 emulation library by Ken Silverman - * Copyright (C) 1998-2001 Ken Silverman - * Ken Silverman's official web site: "http://www.advsys.net/ken" - */ - - -#include -#include -#include "dosbox.h" -#include "opl.h" - - -static fltype recipsamp; // inverse of sampling rate -static Bit16s wavtable[WAVEPREC*3]; // wave form table - -// vibrato/tremolo tables -static Bit32s vib_table[VIBTAB_SIZE]; -static Bit32s trem_table[TREMTAB_SIZE*2]; - -static Bit32s vibval_const[BLOCKBUF_SIZE]; -static Bit32s tremval_const[BLOCKBUF_SIZE]; - -// vibrato value tables (used per-operator) -static Bit32s vibval_var1[BLOCKBUF_SIZE]; -static Bit32s vibval_var2[BLOCKBUF_SIZE]; -static Bit32s vibval_var3[BLOCKBUF_SIZE]; -static Bit32s vibval_var4[BLOCKBUF_SIZE]; - -// vibrato/trmolo value table pointers -static Bit32s *vibval1, *vibval2, *vibval3, *vibval4; -static Bit32s *tremval1, *tremval2, *tremval3, *tremval4; - - -// key scale level lookup table -static const fltype kslmul[4] = { - 0.0, 0.5, 0.25, 1.0 // -> 0, 3, 1.5, 6 dB/oct -}; - -// frequency multiplicator lookup table -static const fltype frqmul_tab[16] = { - 0.5,1,2,3,4,5,6,7,8,9,10,10,12,12,15,15 -}; -// calculated frequency multiplication values (depend on sampling rate) -static float frqmul[16]; - -// key scale levels -static Bit8u kslev[8][16]; - -// map a channel number to the register offset of the modulator (=register base) -static const Bit8u modulatorbase[9] = { - 0,1,2, - 8,9,10, - 16,17,18 -}; - -// map a register base to a modulator operator number or operator number -#if defined(OPLTYPE_IS_OPL3) -static const Bit8u regbase2modop[44] = { - 0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8, // first set - 18,19,20,18,19,20,0,0,21,22,23,21,22,23,0,0,24,25,26,24,25,26 // second set -}; -static const Bit8u regbase2op[44] = { - 0,1,2,9,10,11,0,0,3,4,5,12,13,14,0,0,6,7,8,15,16,17, // first set - 18,19,20,27,28,29,0,0,21,22,23,30,31,32,0,0,24,25,26,33,34,35 // second set -}; -#else -static const Bit8u regbase2modop[22] = { - 0,1,2,0,1,2,0,0,3,4,5,3,4,5,0,0,6,7,8,6,7,8 -}; -static const Bit8u regbase2op[22] = { - 0,1,2,9,10,11,0,0,3,4,5,12,13,14,0,0,6,7,8,15,16,17 -}; -#endif - - -// start of the waveform -static Bit32u waveform[8] = { - WAVEPREC, - WAVEPREC>>1, - WAVEPREC, - (WAVEPREC*3)>>2, - 0, - 0, - (WAVEPREC*5)>>2, - WAVEPREC<<1 -}; - -// length of the waveform as mask -static Bit32u wavemask[8] = { - WAVEPREC-1, - WAVEPREC-1, - (WAVEPREC>>1)-1, - (WAVEPREC>>1)-1, - WAVEPREC-1, - ((WAVEPREC*3)>>2)-1, - WAVEPREC>>1, - WAVEPREC-1 -}; - -// where the first entry resides -static Bit32u wavestart[8] = { - 0, - WAVEPREC>>1, - 0, - WAVEPREC>>2, - 0, - 0, - 0, - WAVEPREC>>3 -}; - -// envelope generator function constants -static fltype attackconst[4] = {1/2.82624,1/2.25280,1/1.88416,1/1.59744}; -static fltype decrelconst[4] = {1/39.28064,1/31.41608,1/26.17344,1/22.44608}; - - -void operator_advance(op_type* op_pt, Bit32s vib) { - op_pt->wfpos = op_pt->tcount; // waveform position - - // advance waveform time - op_pt->tcount += op_pt->tinc; - op_pt->tcount += (Bit32s)(op_pt->tinc)*vib/FIXEDPT; - - op_pt->generator_pos += generator_add; -} - -void operator_advance_drums(op_type* op_pt1, Bit32s vib1, op_type* op_pt2, Bit32s vib2, op_type* op_pt3, Bit32s vib3) { - Bit32u c1 = op_pt1->tcount/FIXEDPT; - Bit32u c3 = op_pt3->tcount/FIXEDPT; - Bit32u phasebit = (((c1 & 0x88) ^ ((c1<<5) & 0x80)) | ((c3 ^ (c3<<2)) & 0x20)) ? 0x02 : 0x00; - - Bit32u noisebit = rand()&1; - - Bit32u snare_phase_bit = (((Bitu)((op_pt1->tcount/FIXEDPT) / 0x100))&1); - - //Hihat - Bit32u inttm = (phasebit<<8) | (0x34<<(phasebit ^ (noisebit<<1))); - op_pt1->wfpos = inttm*FIXEDPT; // waveform position - // advance waveform time - op_pt1->tcount += op_pt1->tinc; - op_pt1->tcount += (Bit32s)(op_pt1->tinc)*vib1/FIXEDPT; - op_pt1->generator_pos += generator_add; - - //Snare - inttm = ((1+snare_phase_bit) ^ noisebit)<<8; - op_pt2->wfpos = inttm*FIXEDPT; // waveform position - // advance waveform time - op_pt2->tcount += op_pt2->tinc; - op_pt2->tcount += (Bit32s)(op_pt2->tinc)*vib2/FIXEDPT; - op_pt2->generator_pos += generator_add; - - //Cymbal - inttm = (1+phasebit)<<8; - op_pt3->wfpos = inttm*FIXEDPT; // waveform position - // advance waveform time - op_pt3->tcount += op_pt3->tinc; - op_pt3->tcount += (Bit32s)(op_pt3->tinc)*vib3/FIXEDPT; - op_pt3->generator_pos += generator_add; -} - - -// output level is sustained, mode changes only when operator is turned off (->release) -// or when the keep-sustained bit is turned off (->sustain_nokeep) -void operator_output(op_type* op_pt, Bit32s modulator, Bit32s trem) { - if (op_pt->op_state != OF_TYPE_OFF) { - op_pt->lastcval = op_pt->cval; - Bit32u i = (Bit32u)((op_pt->wfpos+modulator)/FIXEDPT); - - // wform: -16384 to 16383 (0x4000) - // trem : 32768 to 65535 (0x10000) - // step_amp: 0.0 to 1.0 - // vol : 1/2^14 to 1/2^29 (/0x4000; /1../0x8000) - - op_pt->cval = (Bit32s)(op_pt->step_amp*op_pt->vol*op_pt->cur_wform[i&op_pt->cur_wmask]*trem/16.0); - } -} - - -// no action, operator is off -void operator_off(op_type* /*op_pt*/) { -} - -// output level is sustained, mode changes only when operator is turned off (->release) -// or when the keep-sustained bit is turned off (->sustain_nokeep) -void operator_sustain(op_type* op_pt) { - Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT; // number of (standardized) samples - for (Bit32u ct=0; ctcur_env_step++; - } - op_pt->generator_pos -= num_steps_add*FIXEDPT; -} - -// operator in release mode, if output level reaches zero the operator is turned off -void operator_release(op_type* op_pt) { - // ??? boundary? - if (op_pt->amp > 0.00000001) { - // release phase - op_pt->amp *= op_pt->releasemul; - } - - Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT; // number of (standardized) samples - for (Bit32u ct=0; ctcur_env_step++; // sample counter - if ((op_pt->cur_env_step & op_pt->env_step_r)==0) { - if (op_pt->amp <= 0.00000001) { - // release phase finished, turn off this operator - op_pt->amp = 0.0; - if (op_pt->op_state == OF_TYPE_REL) { - op_pt->op_state = OF_TYPE_OFF; - } - } - op_pt->step_amp = op_pt->amp; - } - } - op_pt->generator_pos -= num_steps_add*FIXEDPT; -} - -// operator in decay mode, if sustain level is reached the output level is either -// kept (sustain level keep enabled) or the operator is switched into release mode -void operator_decay(op_type* op_pt) { - if (op_pt->amp > op_pt->sustain_level) { - // decay phase - op_pt->amp *= op_pt->decaymul; - } - - Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT; // number of (standardized) samples - for (Bit32u ct=0; ctcur_env_step++; - if ((op_pt->cur_env_step & op_pt->env_step_d)==0) { - if (op_pt->amp <= op_pt->sustain_level) { - // decay phase finished, sustain level reached - if (op_pt->sus_keep) { - // keep sustain level (until turned off) - op_pt->op_state = OF_TYPE_SUS; - op_pt->amp = op_pt->sustain_level; - } else { - // next: release phase - op_pt->op_state = OF_TYPE_SUS_NOKEEP; - } - } - op_pt->step_amp = op_pt->amp; - } - } - op_pt->generator_pos -= num_steps_add*FIXEDPT; -} - -// operator in attack mode, if full output level is reached, -// the operator is switched into decay mode -void operator_attack(op_type* op_pt) { - op_pt->amp = ((op_pt->a3*op_pt->amp + op_pt->a2)*op_pt->amp + op_pt->a1)*op_pt->amp + op_pt->a0; - - Bit32u num_steps_add = op_pt->generator_pos/FIXEDPT; // number of (standardized) samples - for (Bit32u ct=0; ctcur_env_step++; // next sample - if ((op_pt->cur_env_step & op_pt->env_step_a)==0) { // check if next step already reached - if (op_pt->amp > 1.0) { - // attack phase finished, next: decay - op_pt->op_state = OF_TYPE_DEC; - op_pt->amp = 1.0; - op_pt->step_amp = 1.0; - } - op_pt->step_skip_pos <<= 1; - if (op_pt->step_skip_pos==0) op_pt->step_skip_pos = 1; - if (op_pt->step_skip_pos & op_pt->env_step_skip_a) { // check if required to skip next step - op_pt->step_amp = op_pt->amp; - } - } - } - op_pt->generator_pos -= num_steps_add*FIXEDPT; -} - - -typedef void (*optype_fptr)(op_type*); - -optype_fptr opfuncs[6] = { - operator_attack, - operator_decay, - operator_release, - operator_sustain, // sustain phase (keeping level) - operator_release, // sustain_nokeep phase (release-style) - operator_off -}; - -void change_attackrate(Bitu regbase, op_type* op_pt) { - Bits attackrate = adlibreg[ARC_ATTR_DECR+regbase]>>4; - if (attackrate) { - fltype f = (fltype)(pow(FL2,(fltype)attackrate+(op_pt->toff>>2)-1)*attackconst[op_pt->toff&3]*recipsamp); - // attack rate coefficients - op_pt->a0 = (fltype)(0.0377*f); - op_pt->a1 = (fltype)(10.73*f+1); - op_pt->a2 = (fltype)(-17.57*f); - op_pt->a3 = (fltype)(7.42*f); - - Bits step_skip = attackrate*4 + op_pt->toff; - Bits steps = step_skip >> 2; - op_pt->env_step_a = (1<<(steps<=12?12-steps:0))-1; - - Bits step_num = (step_skip<=48)?(4-(step_skip&3)):0; - static Bit8u step_skip_mask[5] = {0xff, 0xfe, 0xee, 0xba, 0xaa}; - op_pt->env_step_skip_a = step_skip_mask[step_num]; - -#if defined(OPLTYPE_IS_OPL3) - if (step_skip>=60) { -#else - if (step_skip>=62) { -#endif - op_pt->a0 = (fltype)(2.0); // something that triggers an immediate transition to amp:=1.0 - op_pt->a1 = (fltype)(0.0); - op_pt->a2 = (fltype)(0.0); - op_pt->a3 = (fltype)(0.0); - } - } else { - // attack disabled - op_pt->a0 = 0.0; - op_pt->a1 = 1.0; - op_pt->a2 = 0.0; - op_pt->a3 = 0.0; - op_pt->env_step_a = 0; - op_pt->env_step_skip_a = 0; - } -} - -void change_decayrate(Bitu regbase, op_type* op_pt) { - Bits decayrate = adlibreg[ARC_ATTR_DECR+regbase]&15; - // decaymul should be 1.0 when decayrate==0 - if (decayrate) { - fltype f = (fltype)(-7.4493*decrelconst[op_pt->toff&3]*recipsamp); - op_pt->decaymul = (fltype)(pow(FL2,f*pow(FL2,(fltype)(decayrate+(op_pt->toff>>2))))); - Bits steps = (decayrate*4 + op_pt->toff) >> 2; - op_pt->env_step_d = (1<<(steps<=12?12-steps:0))-1; - } else { - op_pt->decaymul = 1.0; - op_pt->env_step_d = 0; - } -} - -void change_releaserate(Bitu regbase, op_type* op_pt) { - Bits releaserate = adlibreg[ARC_SUSL_RELR+regbase]&15; - // releasemul should be 1.0 when releaserate==0 - if (releaserate) { - fltype f = (fltype)(-7.4493*decrelconst[op_pt->toff&3]*recipsamp); - op_pt->releasemul = (fltype)(pow(FL2,f*pow(FL2,(fltype)(releaserate+(op_pt->toff>>2))))); - Bits steps = (releaserate*4 + op_pt->toff) >> 2; - op_pt->env_step_r = (1<<(steps<=12?12-steps:0))-1; - } else { - op_pt->releasemul = 1.0; - op_pt->env_step_r = 0; - } -} - -void change_sustainlevel(Bitu regbase, op_type* op_pt) { - Bits sustainlevel = adlibreg[ARC_SUSL_RELR+regbase]>>4; - // sustainlevel should be 0.0 when sustainlevel==15 (max) - if (sustainlevel<15) { - op_pt->sustain_level = (fltype)(pow(FL2,(fltype)sustainlevel * (-FL05))); - } else { - op_pt->sustain_level = 0.0; - } -} - -void change_waveform(Bitu regbase, op_type* op_pt) { -#if defined(OPLTYPE_IS_OPL3) - if (regbase>=ARC_SECONDSET) regbase -= (ARC_SECONDSET-22); // second set starts at 22 -#endif - // waveform selection - op_pt->cur_wmask = wavemask[wave_sel[regbase]]; - op_pt->cur_wform = &wavtable[waveform[wave_sel[regbase]]]; - // (might need to be adapted to waveform type here...) -} - -void change_keepsustain(Bitu regbase, op_type* op_pt) { - op_pt->sus_keep = (adlibreg[ARC_TVS_KSR_MUL+regbase]&0x20)>0; - if (op_pt->op_state==OF_TYPE_SUS) { - if (!op_pt->sus_keep) op_pt->op_state = OF_TYPE_SUS_NOKEEP; - } else if (op_pt->op_state==OF_TYPE_SUS_NOKEEP) { - if (op_pt->sus_keep) op_pt->op_state = OF_TYPE_SUS; - } -} - -// enable/disable vibrato/tremolo LFO effects -void change_vibrato(Bitu regbase, op_type* op_pt) { - op_pt->vibrato = (adlibreg[ARC_TVS_KSR_MUL+regbase]&0x40)!=0; - op_pt->tremolo = (adlibreg[ARC_TVS_KSR_MUL+regbase]&0x80)!=0; -} - -// change amount of self-feedback -void change_feedback(Bitu chanbase, op_type* op_pt) { - Bits feedback = adlibreg[ARC_FEEDBACK+chanbase]&14; - if (feedback) op_pt->mfbi = (Bit32s)(pow(FL2,(fltype)((feedback>>1)+8))); - else op_pt->mfbi = 0; -} - -void change_frequency(Bitu chanbase, Bitu regbase, op_type* op_pt) { - // frequency - Bit32u frn = ((((Bit32u)adlibreg[ARC_KON_BNUM+chanbase])&3)<<8) + (Bit32u)adlibreg[ARC_FREQ_NUM+chanbase]; - // block number/octave - Bit32u oct = ((((Bit32u)adlibreg[ARC_KON_BNUM+chanbase])>>2)&7); - op_pt->freq_high = (Bit32s)((frn>>7)&7); - - // keysplit - Bit32u note_sel = (adlibreg[8]>>6)&1; - op_pt->toff = ((frn>>9)&(note_sel^1)) | ((frn>>8)¬e_sel); - op_pt->toff += (oct<<1); - - // envelope scaling (KSR) - if (!(adlibreg[ARC_TVS_KSR_MUL+regbase]&0x10)) op_pt->toff >>= 2; - - // 20+a0+b0: - op_pt->tinc = (Bit32u)((((fltype)(frn<>6]*kslev[oct][frn>>6]); - op_pt->vol = (fltype)(pow(FL2,(fltype)(vol_in * -0.125 - 14))); - - // operator frequency changed, care about features that depend on it - change_attackrate(regbase,op_pt); - change_decayrate(regbase,op_pt); - change_releaserate(regbase,op_pt); -} - -void enable_operator(Bitu regbase, op_type* op_pt, Bit32u act_type) { - // check if this is really an off-on transition - if (op_pt->act_state == OP_ACT_OFF) { - Bits wselbase = regbase; - if (wselbase>=ARC_SECONDSET) wselbase -= (ARC_SECONDSET-22); // second set starts at 22 - - op_pt->tcount = wavestart[wave_sel[wselbase]]*FIXEDPT; - - // start with attack mode - op_pt->op_state = OF_TYPE_ATT; - op_pt->act_state |= act_type; - } -} - -void disable_operator(op_type* op_pt, Bit32u act_type) { - // check if this is really an on-off transition - if (op_pt->act_state != OP_ACT_OFF) { - op_pt->act_state &= (~act_type); - if (op_pt->act_state == OP_ACT_OFF) { - if (op_pt->op_state != OF_TYPE_OFF) op_pt->op_state = OF_TYPE_REL; - } - } -} - -void adlib_init(Bit32u samplerate) { - Bits i, j, oct; - - int_samplerate = samplerate; - - generator_add = (Bit32u)(INTFREQU*FIXEDPT/int_samplerate); - - - memset((void *)adlibreg,0,sizeof(adlibreg)); - memset((void *)op,0,sizeof(op_type)*MAXOPERATORS); - memset((void *)wave_sel,0,sizeof(wave_sel)); - - for (i=0;i=0;i--) { - frqmul[i] = (fltype)(frqmul_tab[i]*INTFREQU/(fltype)WAVEPREC*(fltype)FIXEDPT*recipsamp); - } - - status = 0; - index = 0; - - - // create vibrato table - vib_table[0] = 8; - vib_table[1] = 4; - vib_table[2] = 0; - vib_table[3] = -4; - for (i=4; i(VIBTAB_SIZE*FIXEDPT_LFO/8192*INTFREQU/int_samplerate); - vibtab_pos = 0; - - for (i=0; i -0.5/6 to 0) - for (i=14; i<41; i++) trem_table_int[i] = -i+14; // downwards (26 to 0 -> 0 to -1/6) - for (i=41; i<53; i++) trem_table_int[i] = i-40-26; // upwards (1 to 12 -> -1/6 to -0.5/6) - - for (i=0; i>1);i++) { - wavtable[(i<<1) +WAVEPREC] = (Bit16s)(16384*sin((fltype)((i<<1) )*PI*2/WAVEPREC)); - wavtable[(i<<1)+1+WAVEPREC] = (Bit16s)(16384*sin((fltype)((i<<1)+1)*PI*2/WAVEPREC)); - wavtable[i] = wavtable[(i<<1) +WAVEPREC]; - // table to be verified, alternative: (zero-less) -/* wavtable[(i<<1) +WAVEPREC] = (Bit16s)(16384*sin((fltype)(((i*2+1)<<1)-1)*PI/WAVEPREC)); - wavtable[(i<<1)+1+WAVEPREC] = (Bit16s)(16384*sin((fltype)(((i*2+1)<<1) )*PI/WAVEPREC)); - wavtable[i] = wavtable[(i<<1)-1+WAVEPREC]; */ - } - for (i=0;i<(WAVEPREC>>3);i++) { - wavtable[i+(WAVEPREC<<1)] = wavtable[i+(WAVEPREC>>3)]-16384; - wavtable[i+((WAVEPREC*17)>>3)] = wavtable[i+(WAVEPREC>>2)]+16384; - } - - // key scale level table verified ([table in book]*8/3) - kslev[7][0] = 0; kslev[7][1] = 24; kslev[7][2] = 32; kslev[7][3] = 37; - kslev[7][4] = 40; kslev[7][5] = 43; kslev[7][6] = 45; kslev[7][7] = 47; - kslev[7][8] = 48; - for (i=9;i<16;i++) kslev[7][i] = (Bit8u)(i+41); - for (j=6;j>=0;j--) { - for (i=0;i<16;i++) { - oct = (Bits)kslev[j+1][i]-8; - if (oct < 0) oct = 0; - kslev[j][i] = (Bit8u)oct; - } - } - } - -} - - - -void adlib_write(Bitu idx, Bit8u val) { - Bit32u second_set = idx&0x100; - Bit8u old_val = adlibreg[idx]; - adlibreg[idx] = val; - - switch (idx&0xf0) { - case ARC_CONTROL: - // here we check for the second set registers, too: - switch (idx) { - case 0x02: // timer1 counter - case 0x03: // timer2 counter - break; - case 0x04: - // IRQ reset, timer mask/start - if (val&0x80) { - // clear IRQ bits in status register - status &= ~0x60; - } else { - status = 0; - } - break; -#if defined(OPLTYPE_IS_OPL3) - case 0x04|ARC_SECONDSET: - // 4op enable/disable switches for each possible channel - op[0].is_4op = (val&1)>0; - op[3].is_4op_attached = op[0].is_4op; - op[1].is_4op = (val&2)>0; - op[4].is_4op_attached = op[1].is_4op; - op[2].is_4op = (val&4)>0; - op[5].is_4op_attached = op[2].is_4op; - op[18].is_4op = (val&8)>0; - op[21].is_4op_attached = op[18].is_4op; - op[19].is_4op = (val&16)>0; - op[22].is_4op_attached = op[19].is_4op; - op[20].is_4op = (val&32)>0; - op[23].is_4op_attached = op[20].is_4op; - break; - case 0x05|ARC_SECONDSET: - break; -#endif - case 0x08: - // CSW, note select - break; - default: - break; - } - break; - case ARC_TVS_KSR_MUL: - case ARC_TVS_KSR_MUL+0x10: { - // tremolo/vibrato/sustain keeping enabled; key scale rate; frequency multiplication - int num = idx&7; - Bitu base = (idx-ARC_TVS_KSR_MUL)&0xff; - if ((num<6) && (base<22)) { - Bitu modop = regbase2modop[second_set?(base+22):base]; - Bitu regbase = base+second_set; - Bitu chanbase = second_set?(modop-18+ARC_SECONDSET):modop; - - // change tremolo/vibrato and sustain keeping of this operator - op_type* op_ptr = &op[modop+((num<3) ? 0 : 9)]; - change_keepsustain(regbase,op_ptr); - change_vibrato(regbase,op_ptr); - - // change frequency calculations of this operator as - // key scale rate and frequency multiplicator can be changed -#if defined(OPLTYPE_IS_OPL3) - if ((adlibreg[0x105]&1) && (op[modop].is_4op_attached)) { - // operator uses frequency of channel - change_frequency(chanbase-3,regbase,op_ptr); - } else { - change_frequency(chanbase,regbase,op_ptr); - } -#else - change_frequency(chanbase,base,op_ptr); -#endif - } - } - break; - case ARC_KSL_OUTLEV: - case ARC_KSL_OUTLEV+0x10: { - // key scale level; output rate - int num = idx&7; - Bitu base = (idx-ARC_KSL_OUTLEV)&0xff; - if ((num<6) && (base<22)) { - Bitu modop = regbase2modop[second_set?(base+22):base]; - Bitu chanbase = second_set?(modop-18+ARC_SECONDSET):modop; - - // change frequency calculations of this operator as - // key scale level and output rate can be changed - op_type* op_ptr = &op[modop+((num<3) ? 0 : 9)]; -#if defined(OPLTYPE_IS_OPL3) - Bitu regbase = base+second_set; - if ((adlibreg[0x105]&1) && (op[modop].is_4op_attached)) { - // operator uses frequency of channel - change_frequency(chanbase-3,regbase,op_ptr); - } else { - change_frequency(chanbase,regbase,op_ptr); - } -#else - change_frequency(chanbase,base,op_ptr); -#endif - } - } - break; - case ARC_ATTR_DECR: - case ARC_ATTR_DECR+0x10: { - // attack/decay rates - int num = idx&7; - Bitu base = (idx-ARC_ATTR_DECR)&0xff; - if ((num<6) && (base<22)) { - Bitu regbase = base+second_set; - - // change attack rate and decay rate of this operator - op_type* op_ptr = &op[regbase2op[second_set?(base+22):base]]; - change_attackrate(regbase,op_ptr); - change_decayrate(regbase,op_ptr); - } - } - break; - case ARC_SUSL_RELR: - case ARC_SUSL_RELR+0x10: { - // sustain level; release rate - int num = idx&7; - Bitu base = (idx-ARC_SUSL_RELR)&0xff; - if ((num<6) && (base<22)) { - Bitu regbase = base+second_set; - - // change sustain level and release rate of this operator - op_type* op_ptr = &op[regbase2op[second_set?(base+22):base]]; - change_releaserate(regbase,op_ptr); - change_sustainlevel(regbase,op_ptr); - } - } - break; - case ARC_FREQ_NUM: { - // 0xa0-0xa8 low8 frequency - Bitu base = (idx-ARC_FREQ_NUM)&0xff; - if (base<9) { - Bits opbase = second_set?(base+18):base; -#if defined(OPLTYPE_IS_OPL3) - if ((adlibreg[0x105]&1) && op[opbase].is_4op_attached) break; -#endif - // regbase of modulator: - Bits modbase = modulatorbase[base]+second_set; - - Bitu chanbase = base+second_set; - - change_frequency(chanbase,modbase,&op[opbase]); - change_frequency(chanbase,modbase+3,&op[opbase+9]); -#if defined(OPLTYPE_IS_OPL3) - // for 4op channels all four operators are modified to the frequency of the channel - if ((adlibreg[0x105]&1) && op[second_set?(base+18):base].is_4op) { - change_frequency(chanbase,modbase+8,&op[opbase+3]); - change_frequency(chanbase,modbase+3+8,&op[opbase+3+9]); - } -#endif - } - } - break; - case ARC_KON_BNUM: { - if (idx == ARC_PERC_MODE) { -#if defined(OPLTYPE_IS_OPL3) - if (second_set) return; -#endif - - if ((val&0x30) == 0x30) { // BassDrum active - enable_operator(16,&op[6],OP_ACT_PERC); - change_frequency(6,16,&op[6]); - enable_operator(16+3,&op[6+9],OP_ACT_PERC); - change_frequency(6,16+3,&op[6+9]); - } else { - disable_operator(&op[6],OP_ACT_PERC); - disable_operator(&op[6+9],OP_ACT_PERC); - } - if ((val&0x28) == 0x28) { // Snare active - enable_operator(17+3,&op[16],OP_ACT_PERC); - change_frequency(7,17+3,&op[16]); - } else { - disable_operator(&op[16],OP_ACT_PERC); - } - if ((val&0x24) == 0x24) { // TomTom active - enable_operator(18,&op[8],OP_ACT_PERC); - change_frequency(8,18,&op[8]); - } else { - disable_operator(&op[8],OP_ACT_PERC); - } - if ((val&0x22) == 0x22) { // Cymbal active - enable_operator(18+3,&op[8+9],OP_ACT_PERC); - change_frequency(8,18+3,&op[8+9]); - } else { - disable_operator(&op[8+9],OP_ACT_PERC); - } - if ((val&0x21) == 0x21) { // Hihat active - enable_operator(17,&op[7],OP_ACT_PERC); - change_frequency(7,17,&op[7]); - } else { - disable_operator(&op[7],OP_ACT_PERC); - } - - break; - } - // regular 0xb0-0xb8 - Bitu base = (idx-ARC_KON_BNUM)&0xff; - if (base<9) { - Bits opbase = second_set?(base+18):base; -#if defined(OPLTYPE_IS_OPL3) - if ((adlibreg[0x105]&1) && op[opbase].is_4op_attached) break; -#endif - // regbase of modulator: - Bits modbase = modulatorbase[base]+second_set; - - if (val&32) { - // operator switched on - enable_operator(modbase,&op[opbase],OP_ACT_NORMAL); // modulator (if 2op) - enable_operator(modbase+3,&op[opbase+9],OP_ACT_NORMAL); // carrier (if 2op) -#if defined(OPLTYPE_IS_OPL3) - // for 4op channels all four operators are switched on - if ((adlibreg[0x105]&1) && op[opbase].is_4op) { - // turn on chan+3 operators as well - enable_operator(modbase+8,&op[opbase+3],OP_ACT_NORMAL); - enable_operator(modbase+3+8,&op[opbase+3+9],OP_ACT_NORMAL); - } -#endif - } else { - // operator switched off - disable_operator(&op[opbase],OP_ACT_NORMAL); - disable_operator(&op[opbase+9],OP_ACT_NORMAL); -#if defined(OPLTYPE_IS_OPL3) - // for 4op channels all four operators are switched off - if ((adlibreg[0x105]&1) && op[opbase].is_4op) { - // turn off chan+3 operators as well - disable_operator(&op[opbase+3],OP_ACT_NORMAL); - disable_operator(&op[opbase+3+9],OP_ACT_NORMAL); - } -#endif - } - - Bitu chanbase = base+second_set; - - // change frequency calculations of modulator and carrier (2op) as - // the frequency of the channel has changed - change_frequency(chanbase,modbase,&op[opbase]); - change_frequency(chanbase,modbase+3,&op[opbase+9]); -#if defined(OPLTYPE_IS_OPL3) - // for 4op channels all four operators are modified to the frequency of the channel - if ((adlibreg[0x105]&1) && op[second_set?(base+18):base].is_4op) { - // change frequency calculations of chan+3 operators as well - change_frequency(chanbase,modbase+8,&op[opbase+3]); - change_frequency(chanbase,modbase+3+8,&op[opbase+3+9]); - } -#endif - } - } - break; - case ARC_FEEDBACK: { - // 0xc0-0xc8 feedback/modulation type (AM/FM) - Bitu base = (idx-ARC_FEEDBACK)&0xff; - if (base<9) { - Bits opbase = second_set?(base+18):base; - Bitu chanbase = base+second_set; - change_feedback(chanbase,&op[opbase]); -#if defined(OPLTYPE_IS_OPL3) - // OPL3 panning - op[opbase].left_pan = ((val&0x10)>>4); - op[opbase].right_pan = ((val&0x20)>>5); -#endif - } - } - break; - case ARC_WAVE_SEL: - case ARC_WAVE_SEL+0x10: { - int num = idx&7; - Bitu base = (idx-ARC_WAVE_SEL)&0xff; - if ((num<6) && (base<22)) { -#if defined(OPLTYPE_IS_OPL3) - Bits wselbase = second_set?(base+22):base; // for easier mapping onto wave_sel[] - // change waveform - if (adlibreg[0x105]&1) wave_sel[wselbase] = val&7; // opl3 mode enabled, all waveforms accessible - else wave_sel[wselbase] = val&3; - op_type* op_ptr = &op[regbase2modop[wselbase]+((num<3) ? 0 : 9)]; - change_waveform(wselbase,op_ptr); -#else - if (adlibreg[0x01]&0x20) { - // wave selection enabled, change waveform - wave_sel[base] = val&3; - op_type* op_ptr = &op[regbase2modop[base]+((num<3) ? 0 : 9)]; - change_waveform(base,op_ptr); - } -#endif - } - } - break; - default: - break; - } -} - - -Bitu adlib_reg_read(Bitu port) { -#if defined(OPLTYPE_IS_OPL3) - // opl3-detection routines require ret&6 to be zero - if ((port&1)==0) { - return status; - } - return 0x00; -#else - // opl2-detection routines require ret&6 to be 6 - if ((port&1)==0) { - return status|6; - } - return 0xff; -#endif -} - -void adlib_write_index(Bitu port, Bit8u val) { - index = val; -#if defined(OPLTYPE_IS_OPL3) - if ((port&3)!=0) { - // possibly second set - if (((adlibreg[0x105]&1)!=0) || (index==5)) index |= ARC_SECONDSET; - } -#endif -} - -static void INLINE clipit16(Bit32s ival, Bit16s* outval) { - if (ival<32768) { - if (ival>-32769) { - *outval=(Bit16s)ival; - } else { - *outval = -32768; - } - } else { - *outval = 32767; - } -} - - - -// be careful with this -// uses cptr and chanval, outputs into outbufl(/outbufr) -// for opl3 check if opl3-mode is enabled (which uses stereo panning) -#undef CHANVAL_OUT -#if defined(OPLTYPE_IS_OPL3) -#define CHANVAL_OUT \ - if (adlibreg[0x105]&1) { \ - outbufl[i] += chanval*cptr[0].left_pan; \ - outbufr[i] += chanval*cptr[0].right_pan; \ - } else { \ - outbufl[i] += chanval; \ - } -#else -#define CHANVAL_OUT \ - outbufl[i] += chanval; -#endif - -void adlib_getsample(Bit16s* sndptr, Bits numsamples) { - Bits i, endsamples; - op_type* cptr; - - Bit32s outbufl[BLOCKBUF_SIZE]; -#if defined(OPLTYPE_IS_OPL3) - // second output buffer (right channel for opl3 stereo) - Bit32s outbufr[BLOCKBUF_SIZE]; -#endif - - // vibrato/tremolo lookup tables (global, to possibly be used by all operators) - Bit32s vib_lut[BLOCKBUF_SIZE]; - Bit32s trem_lut[BLOCKBUF_SIZE]; - - Bits samples_to_process = numsamples; - - for (Bits cursmp=0; cursmpBLOCKBUF_SIZE) endsamples = BLOCKBUF_SIZE; - - memset((void*)&outbufl,0,endsamples*sizeof(Bit32s)); -#if defined(OPLTYPE_IS_OPL3) - // clear second output buffer (opl3 stereo) - if (adlibreg[0x105]&1) memset((void*)&outbufr,0,endsamples*sizeof(Bit32s)); -#endif - - // calculate vibrato/tremolo lookup tables - Bit32s vib_tshift = ((adlibreg[ARC_PERC_MODE]&0x40)==0) ? 1 : 0; // 14cents/7cents switching - for (i=0;i=VIBTAB_SIZE) vibtab_pos-=VIBTAB_SIZE*FIXEDPT_LFO; - vib_lut[i] = vib_table[vibtab_pos/FIXEDPT_LFO]>>vib_tshift; // 14cents (14/100 of a semitone) or 7cents - - // cycle through tremolo table - tremtab_pos += tremtab_add; - if (tremtab_pos/FIXEDPT_LFO>=TREMTAB_SIZE) tremtab_pos-=TREMTAB_SIZE*FIXEDPT_LFO; - if (adlibreg[ARC_PERC_MODE]&0x80) trem_lut[i] = trem_table[tremtab_pos/FIXEDPT_LFO]; - else trem_lut[i] = trem_table[TREMTAB_SIZE+tremtab_pos/FIXEDPT_LFO]; - } - - if (adlibreg[ARC_PERC_MODE]&0x20) { - //BassDrum - cptr = &op[6]; - if (adlibreg[ARC_FEEDBACK+6]&1) { - // additive synthesis - if (cptr[9].op_state != OF_TYPE_OFF) { - if (cptr[9].vibrato) { - vibval1 = vibval_var1; - for (i=0;i=0; cur_ch--) { - // skip drum/percussion operators - if ((adlibreg[ARC_PERC_MODE]&0x20) && (cur_ch >= 6) && (cur_ch < 9)) continue; - - Bitu k = cur_ch; -#if defined(OPLTYPE_IS_OPL3) - if (cur_ch < 9) { - cptr = &op[cur_ch]; - } else { - cptr = &op[cur_ch+9]; // second set is operator18-operator35 - k += (-9+256); // second set uses registers 0x100 onwards - } - // check if this operator is part of a 4-op - if ((adlibreg[0x105]&1) && cptr->is_4op_attached) continue; -#else - cptr = &op[cur_ch]; -#endif - - // check for FM/AM - if (adlibreg[ARC_FEEDBACK+k]&1) { -#if defined(OPLTYPE_IS_OPL3) - if ((adlibreg[0x105]&1) && cptr->is_4op) { - if (adlibreg[ARC_FEEDBACK+k+3]&1) { - // AM-AM-style synthesis (op1[fb] + (op2 * op3) + op4) - if (cptr[0].op_state != OF_TYPE_OFF) { - if (cptr[0].vibrato) { - vibval1 = vibval_var1; - for (i=0;iis_4op) { - if (adlibreg[ARC_FEEDBACK+k+3]&1) { - // FM-AM-style synthesis ((op1[fb] * op2) + (op3 * op4)) - if ((cptr[0].op_state != OF_TYPE_OFF) || (cptr[9].op_state != OF_TYPE_OFF)) { - if ((cptr[0].vibrato) && (cptr[0].op_state != OF_TYPE_OFF)) { - vibval1 = vibval_var1; - for (i=0;i -typedef uintptr_t Bitu; -typedef intptr_t Bits; -typedef uint32_t Bit32u; -typedef int32_t Bit32s; -typedef uint16_t Bit16u; -typedef int16_t Bit16s; -typedef uint8_t Bit8u; -typedef int8_t Bit8s; -*/ - -#undef NUM_CHANNELS -#if defined(OPLTYPE_IS_OPL3) -#define NUM_CHANNELS 18 -#else -#define NUM_CHANNELS 9 -#endif - -#define MAXOPERATORS (NUM_CHANNELS*2) - - -#define FL05 ((fltype)0.5) -#define FL2 ((fltype)2.0) -#define PI ((fltype)3.1415926535897932384626433832795) - - -#define FIXEDPT 0x10000 // fixed-point calculations using 16+16 -#define FIXEDPT_LFO 0x1000000 // fixed-point calculations using 8+24 - -#define WAVEPREC 1024 // waveform precision (10 bits) - -#define INTFREQU ((fltype)(14318180.0 / 288.0)) // clocking of the chip - - -#define OF_TYPE_ATT 0 -#define OF_TYPE_DEC 1 -#define OF_TYPE_REL 2 -#define OF_TYPE_SUS 3 -#define OF_TYPE_SUS_NOKEEP 4 -#define OF_TYPE_OFF 5 - -#define ARC_CONTROL 0x00 -#define ARC_TVS_KSR_MUL 0x20 -#define ARC_KSL_OUTLEV 0x40 -#define ARC_ATTR_DECR 0x60 -#define ARC_SUSL_RELR 0x80 -#define ARC_FREQ_NUM 0xa0 -#define ARC_KON_BNUM 0xb0 -#define ARC_PERC_MODE 0xbd -#define ARC_FEEDBACK 0xc0 -#define ARC_WAVE_SEL 0xe0 - -#define ARC_SECONDSET 0x100 // second operator set for OPL3 - - -#define OP_ACT_OFF 0x00 -#define OP_ACT_NORMAL 0x01 // regular channel activated (bitmasked) -#define OP_ACT_PERC 0x02 // percussion channel activated (bitmasked) - -#define BLOCKBUF_SIZE 512 - - -// vibrato constants -#define VIBTAB_SIZE 8 -#define VIBFAC 70/50000 // no braces, integer mul/div - -// tremolo constants and table -#define TREMTAB_SIZE 53 -#define TREM_FREQ ((fltype)(3.7)) // tremolo at 3.7hz - - -/* operator struct definition - For OPL2 all 9 channels consist of two operators each, carrier and modulator. - Channel x has operators x as modulator and operators (9+x) as carrier. - For OPL3 all 18 channels consist either of two operators (2op mode) or four - operators (4op mode) which is determined through register4 of the second - adlib register set. - Only the channels 0,1,2 (first set) and 9,10,11 (second set) can act as - 4op channels. The two additional operators for a channel y come from the - 2op channel y+3 so the operatorss y, (9+y), y+3, (9+y)+3 make up a 4op - channel. -*/ -typedef struct operator_struct { - Bit32s cval, lastcval; // current output/last output (used for feedback) - Bit32u tcount, wfpos, tinc; // time (position in waveform) and time increment - fltype amp, step_amp; // and amplification (envelope) - fltype vol; // volume - fltype sustain_level; // sustain level - Bit32s mfbi; // feedback amount - fltype a0, a1, a2, a3; // attack rate function coefficients - fltype decaymul, releasemul; // decay/release rate functions - Bit32u op_state; // current state of operator (attack/decay/sustain/release/off) - Bit32u toff; - Bit32s freq_high; // highest three bits of the frequency, used for vibrato calculations - Bit16s* cur_wform; // start of selected waveform - Bit32u cur_wmask; // mask for selected waveform - Bit32u act_state; // activity state (regular, percussion) - bool sus_keep; // keep sustain level when decay finished - bool vibrato,tremolo; // vibrato/tremolo enable bits - - // variables used to provide non-continuous envelopes - Bit32u generator_pos; // for non-standard sample rates we need to determine how many samples have passed - Bits cur_env_step; // current (standardized) sample position - Bits env_step_a,env_step_d,env_step_r; // number of std samples of one step (for attack/decay/release mode) - Bit8u step_skip_pos; // position of 8-cyclic step skipping (always 2^x to check against mask) - Bits env_step_skip_a; // bitmask that determines if a step is skipped (respective bit is zero then) - -#if defined(OPLTYPE_IS_OPL3) - bool is_4op,is_4op_attached; // base of a 4op channel/part of a 4op channel - Bit32s left_pan,right_pan; // opl3 stereo panning amount -#endif -} op_type; - -// per-chip variables -Bitu chip_num; -op_type op[MAXOPERATORS]; - -Bits int_samplerate; - -Bit8u status; -Bit32u index; -#if defined(OPLTYPE_IS_OPL3) -Bit8u adlibreg[512]; // adlib register set (including second set) -Bit8u wave_sel[44]; // waveform selection -#else -Bit8u adlibreg[256]; // adlib register set -Bit8u wave_sel[22]; // waveform selection -#endif - - -// vibrato/tremolo increment/counter -Bit32u vibtab_pos; -Bit32u vibtab_add; -Bit32u tremtab_pos; -Bit32u tremtab_add; - - -// enable an operator -void enable_operator(Bitu regbase, op_type* op_pt); - -// functions to change parameters of an operator -void change_frequency(Bitu chanbase, Bitu regbase, op_type* op_pt); - -void change_attackrate(Bitu regbase, op_type* op_pt); -void change_decayrate(Bitu regbase, op_type* op_pt); -void change_releaserate(Bitu regbase, op_type* op_pt); -void change_sustainlevel(Bitu regbase, op_type* op_pt); -void change_waveform(Bitu regbase, op_type* op_pt); -void change_keepsustain(Bitu regbase, op_type* op_pt); -void change_vibrato(Bitu regbase, op_type* op_pt); -void change_feedback(Bitu chanbase, op_type* op_pt); - -// general functions -void adlib_init(Bit32u samplerate); -void adlib_write(Bitu idx, Bit8u val); -void adlib_getsample(Bit16s* sndptr, Bits numsamples); - -Bitu adlib_reg_read(Bitu port); -void adlib_write_index(Bitu port, Bit8u val); - -static Bit32u generator_add; // should be a chip parameter diff --git a/src/hardware/pcspeaker.cpp b/src/hardware/pcspeaker.cpp index f756ad7..c8aabb1 100644 --- a/src/hardware/pcspeaker.cpp +++ b/src/hardware/pcspeaker.cpp @@ -1,354 +1,88 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - /* $Id: pcspeaker.cpp,v 1.24 2007/07/15 16:36:27 c2woody Exp $ */ - -#include -#include "dosbox.h" -#include "mixer.h" -#include "timer.h" -#include "setup.h" -#include "pic.h" - - -#ifndef PI -#define PI 3.14159265358979323846 -#endif - -#define SPKR_ENTRIES 1024 -#define SPKR_VOLUME 5000 -//#define SPKR_SHIFT 8 -#define SPKR_SPEED (float)((SPKR_VOLUME*2)/0.070f) - -enum SPKR_MODES { - SPKR_OFF,SPKR_ON,SPKR_PIT_OFF,SPKR_PIT_ON -}; - -struct DelayEntry { - float index; - float vol; -}; - -static struct { - MixerChannel * chan; - SPKR_MODES mode; - Bitu pit_mode; - Bitu rate; - - float pit_last; - float pit_new_max,pit_new_half; - float pit_max,pit_half; - float pit_index; - float volwant,volcur; - Bitu last_ticks; - float last_index; - Bitu min_tr; - DelayEntry entries[SPKR_ENTRIES]; - Bitu used; -} spkr; - -static void AddDelayEntry(float index,float vol) { - if (spkr.used==SPKR_ENTRIES) { - return; - } - spkr.entries[spkr.used].index=index; - spkr.entries[spkr.used].vol=vol; - spkr.used++; -} - - -static void ForwardPIT(float newindex) { - float passed=(newindex-spkr.last_index); - float delay_base=spkr.last_index; - spkr.last_index=newindex; - switch (spkr.pit_mode) { - case 0: - return; - case 1: - return; - case 2: - while (passed>0) { - /* passed the initial low cycle? */ - if (spkr.pit_index>=spkr.pit_half) { - /* Start a new low cycle */ - if ((spkr.pit_index+passed)>=spkr.pit_max) { - float delay=spkr.pit_max-spkr.pit_index; - delay_base+=delay;passed-=delay; - spkr.pit_last=-SPKR_VOLUME; - if (spkr.mode==SPKR_PIT_ON) AddDelayEntry(delay_base,spkr.pit_last); - spkr.pit_index=0; - } else { - spkr.pit_index+=passed; - return; - } - } else { - if ((spkr.pit_index+passed)>=spkr.pit_half) { - float delay=spkr.pit_half-spkr.pit_index; - delay_base+=delay;passed-=delay; - spkr.pit_last=SPKR_VOLUME; - if (spkr.mode==SPKR_PIT_ON) AddDelayEntry(delay_base,spkr.pit_last); - spkr.pit_index=spkr.pit_half; - } else { - spkr.pit_index+=passed; - return; - } - } - } - break; - //END CASE 2 - case 3: - while (passed>0) { - /* Determine where in the wave we're located */ - if (spkr.pit_index>=spkr.pit_half) { - if ((spkr.pit_index+passed)>=spkr.pit_max) { - float delay=spkr.pit_max-spkr.pit_index; - delay_base+=delay;passed-=delay; - spkr.pit_last=SPKR_VOLUME; - if (spkr.mode==SPKR_PIT_ON) AddDelayEntry(delay_base,spkr.pit_last); - spkr.pit_index=0; - /* Load the new count */ - spkr.pit_half=spkr.pit_new_half; - spkr.pit_max=spkr.pit_new_max; - } else { - spkr.pit_index+=passed; - return; - } - } else { - if ((spkr.pit_index+passed)>=spkr.pit_half) { - float delay=spkr.pit_half-spkr.pit_index; - delay_base+=delay;passed-=delay; - spkr.pit_last=-SPKR_VOLUME; - if (spkr.mode==SPKR_PIT_ON) AddDelayEntry(delay_base,spkr.pit_last); - spkr.pit_index=spkr.pit_half; - /* Load the new count */ - spkr.pit_half=spkr.pit_new_half; - spkr.pit_max=spkr.pit_new_max; - } else { - spkr.pit_index+=passed; - return; - } - } - } - break; - //END CASE 3 - case 4: - if (spkr.pit_index=spkr.pit_max) { - float delay=spkr.pit_max-spkr.pit_index; - delay_base+=delay;passed-=delay; - spkr.pit_last=-SPKR_VOLUME; - if (spkr.mode==SPKR_PIT_ON) AddDelayEntry(delay_base,spkr.pit_last); //No new events unless reprogrammed - spkr.pit_index=spkr.pit_max; - } else spkr.pit_index+=passed; - } - break; - //END CASE 4 - } -} - -void PCSPEAKER_SetCounter(Bitu cntr,Bitu mode) { - if (!spkr.last_ticks) { - if(spkr.chan) spkr.chan->Enable(true); - spkr.last_index=0; - } - spkr.last_ticks=PIC_Ticks; - float newindex=PIC_TickIndex(); - ForwardPIT(newindex); - switch (mode) { - case 0: /* Mode 0 one shot, used with realsound */ - if (spkr.mode!=SPKR_PIT_ON) return; - if (cntr>80) { - cntr=80; - } - spkr.pit_last=((float)cntr-40)*(SPKR_VOLUME/40.0f); - AddDelayEntry(newindex,spkr.pit_last); - spkr.pit_index=0; - break; - case 1: - if (spkr.mode!=SPKR_PIT_ON) return; - spkr.pit_last=SPKR_VOLUME; - AddDelayEntry(newindex,spkr.pit_last); - break; - case 2: /* Single cycle low, rest low high generator */ - spkr.pit_index=0; - spkr.pit_last=-SPKR_VOLUME; - AddDelayEntry(newindex,spkr.pit_last); - spkr.pit_half=(1000.0f/PIT_TICK_RATE)*1; - spkr.pit_max=(1000.0f/PIT_TICK_RATE)*cntr; - break; - case 3: /* Square wave generator */ - if (cntrEnable(true); - spkr.last_index=0; - } - spkr.last_ticks=PIC_Ticks; - float newindex=PIC_TickIndex(); - ForwardPIT(newindex); - switch (mode) { - case 0: - spkr.mode=SPKR_OFF; - AddDelayEntry(newindex,-SPKR_VOLUME); - break; - case 1: - spkr.mode=SPKR_PIT_OFF; - AddDelayEntry(newindex,-SPKR_VOLUME); - break; - case 2: - spkr.mode=SPKR_ON; - AddDelayEntry(newindex,SPKR_VOLUME); - break; - case 3: - if (spkr.mode!=SPKR_PIT_ON) { - AddDelayEntry(newindex,spkr.pit_last); - } - spkr.mode=SPKR_PIT_ON; - break; - }; -} - -static void PCSPEAKER_CallBack(Bitu len) { - Bit16s * stream=(Bit16s*)MixTemp; - ForwardPIT(1); - spkr.last_index=0; - Bitu count=len; - Bitu pos=0; - float sample_base=0; - float sample_add=(1.0001f)/len; - while (count--) { - float index=sample_base; - sample_base+=sample_add; - float end=sample_base; - double value=0; - while(indexAddSamples_m16(len,(Bit16s*)MixTemp); - - //Turn off speaker after 10 seconds of idle or one second idle when in off mode - Bitu test_ticks = PIC_Ticks; - if ((spkr.last_ticks+10000)Enable(false); - } - if((spkr.mode == SPKR_OFF) && ((spkr.last_ticks+1000) Enable(false); - } -} -class PCSPEAKER:public Module_base { -private: - MixerObject MixerChan; -public: - PCSPEAKER(Section* configuration):Module_base(configuration){ - spkr.chan=0; - Section_prop * section=static_cast(configuration); - if(!section->Get_bool("pcspeaker")) return; - spkr.mode=SPKR_OFF; - spkr.last_ticks=0; - spkr.last_index=0; - spkr.rate=section->Get_int("pcrate"); - spkr.pit_max=(1000.0f/PIT_TICK_RATE)*65535; - spkr.pit_half=spkr.pit_max/2; - spkr.pit_new_max=spkr.pit_max; - spkr.pit_new_half=spkr.pit_half; - spkr.pit_index=0; - spkr.min_tr=(PIT_TICK_RATE+spkr.rate/2-1)/(spkr.rate/2); - spkr.used=0; - /* Register the sound channel */ - spkr.chan=MixerChan.Install(&PCSPEAKER_CallBack,spkr.rate,"SPKR"); - } - ~PCSPEAKER(){ - Section_prop * section=static_cast(m_configuration); - if(!section->Get_bool("pcspeaker")) return; - } -}; -static PCSPEAKER* test; - -void PCSPEAKER_ShutDown(Section* sec){ - delete test; -} - -void PCSPEAKER_Init(Section* sec) { - test = new PCSPEAKER(sec); - sec->AddDestroyFunction(&PCSPEAKER_ShutDown,true); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include + + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +#define SPKR_RATE 22050 +#define SPKR_VOLUME 5000 + +#define FREQ_SHIFT 16 +#define FREQ_MAX (2 << FREQ_SHIFT) +#define FREQ_HALF (FREQ_MAX >> 1) + + + +struct Speaker { + Bit32u freq_add; + Bit32u freq_pos; + Bit16s volume; + MIXER_Channel * chan; + bool enabled; +}; + + +static Speaker spkr; + + +void PCSPEAKER_SetFreq(Bit32u freq) { + spkr.freq_add=(Bit32u)(FREQ_MAX/((float)SPKR_RATE/(float)freq)); + spkr.freq_pos=0; +} + +void PCSPEAKER_Enable(bool enable) { + spkr.enabled=enable; + MIXER_Enable(spkr.chan,enable); +} + +static void PCSPEAKER_CallBack(Bit8u * stream,Bit32u len) { + /* Generate the speaker wave, TODO Improve :) */ + for (Bit32u c=0;c=FREQ_MAX) spkr.freq_pos-=FREQ_MAX; + if (spkr.freq_pos>=FREQ_HALF) { + *(Bit16s*)(stream)=spkr.volume; + } else { + *(Bit16s*)(stream)=-spkr.volume; + } +/* + if (spkr.freq_pos>=FREQ_HALF) { + spkr.freq_pos-=FREQ_HALF; + spkr.volume=-spkr.volume; + }; + *(Bit16s*)(stream)=spkr.volume; +*/ + stream+=2; + } + +} + +void PCSPEAKER_Init(void) { + spkr.chan=MIXER_AddChannel(&PCSPEAKER_CallBack,SPKR_RATE,"PC-SPEAKER"); + MIXER_Enable(spkr.chan,false); + MIXER_SetMode(spkr.chan,MIXER_16MONO); + spkr.volume=SPKR_VOLUME; + spkr.enabled=false; +} diff --git a/src/hardware/pic.cpp b/src/hardware/pic.cpp index d090a8e..b21bd49 100644 --- a/src/hardware/pic.cpp +++ b/src/hardware/pic.cpp @@ -1,603 +1,369 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: pic.cpp,v 1.43 2008/01/07 22:29:37 c2woody Exp $ */ - -#include - -#include "dosbox.h" -#include "inout.h" -#include "cpu.h" -#include "callback.h" -#include "pic.h" -#include "timer.h" -#include "setup.h" - -#define PIC_QUEUESIZE 512 - -struct IRQ_Block { - bool masked; - bool active; - bool inservice; - Bitu vector; -}; - -struct PIC_Controller { - Bitu icw_words; - Bitu icw_index; - Bitu masked; - - bool special; - bool auto_eoi; - bool rotate_on_auto_eoi; - bool single; - bool request_issr; - Bit8u vector_base; -}; - -Bitu PIC_Ticks=0; -Bitu PIC_IRQCheck; -Bitu PIC_IRQOnSecondPicActive; -Bitu PIC_IRQActive; - - -static IRQ_Block irqs[16]; -static PIC_Controller pics[2]; -static bool PIC_Special_Mode = false; //Saves one compare in the pic_run_irqloop -struct PICEntry { - float index; - Bitu value; - PIC_EventHandler pic_event; - PICEntry * next; -}; - -static struct { - PICEntry entries[PIC_QUEUESIZE]; - PICEntry * free_entry; - PICEntry * next_entry; -} pic_queue; - -static void write_command(Bitu port,Bitu val,Bitu iolen) { - PIC_Controller * pic=&pics[port==0x20 ? 0 : 1]; - Bitu irq_base=port==0x20 ? 0 : 8; - Bitu i; - static Bit16u IRQ_priority_table[16] = - { 0,1,2,8,9,10,11,12,13,14,15,3,4,5,6,7 }; - if (GCC_UNLIKELY(val&0x10)) { // ICW1 issued - if (val&0x04) E_Exit("PIC: 4 byte interval not handled"); - if (val&0x08) E_Exit("PIC: level triggered mode not handled"); - if (val&0xe0) E_Exit("PIC: 8080/8085 mode not handled"); - pic->single=(val&0x02)==0x02; - pic->icw_index=1; // next is ICW2 - pic->icw_words=2 + (val&0x01); // =3 if ICW4 needed - } else if (GCC_UNLIKELY(val&0x08)) { // OCW3 issued - if (val&0x04) E_Exit("PIC: poll command not handled"); - if (val&0x02) { // function select - if (val&0x01) pic->request_issr=true; /* select read interrupt in-service register */ - else pic->request_issr=false; /* select read interrupt request register */ - } - if (val&0x40) { // special mask select - if (val&0x20) pic->special=true; - else pic->special=false; - if(pic[0].special || pics[1].special) - PIC_Special_Mode = true; else - PIC_Special_Mode = false; - if (PIC_IRQCheck) { //Recheck irqs - CPU_CycleLeft += CPU_Cycles; - CPU_Cycles = 0; - } - LOG(LOG_PIC,LOG_NORMAL)("port %X : special mask %s",port,(pic->special)?"ON":"OFF"); - } - } else { // OCW2 issued - if (val&0x20) { // EOI commands - if (GCC_UNLIKELY(val&0x80)) E_Exit("rotate mode not supported"); - if (val&0x40) { // specific EOI - if (PIC_IRQActive==(irq_base+val-0x60U)) { - irqs[PIC_IRQActive].inservice=false; - PIC_IRQActive=PIC_NOIRQ; - for (i=0; i<=15; i++) { - if (irqs[IRQ_priority_table[i]].inservice) { - PIC_IRQActive=IRQ_priority_table[i]; - break; - } - } - } -// if (val&0x80); // perform rotation - } else { // nonspecific EOI - if (PIC_IRQActive<(irq_base+8)) { - irqs[PIC_IRQActive].inservice=false; - PIC_IRQActive=PIC_NOIRQ; - for (i=0; i<=15; i++){ - if(irqs[IRQ_priority_table[i]].inservice) { - PIC_IRQActive=IRQ_priority_table[i]; - break; - } - } - } -// if (val&0x80); // perform rotation - } - } else { - if ((val&0x40)==0) { // rotate in auto EOI mode - if (val&0x80) pic->rotate_on_auto_eoi=true; - else pic->rotate_on_auto_eoi=false; - } else if (val&0x80) { - LOG(LOG_PIC,LOG_NORMAL)("set priority command not handled"); - } // else NOP command - } - } // end OCW2 -} - -static void write_data(Bitu port,Bitu val,Bitu iolen) { - PIC_Controller * pic=&pics[port==0x21 ? 0 : 1]; - Bitu irq_base=(port==0x21) ? 0 : 8; - Bitu i; - bool old_irq2_mask = irqs[2].masked; - switch(pic->icw_index) { - case 0: /* mask register */ - LOG(LOG_PIC,LOG_NORMAL)("%d mask %X",port==0x21 ? 0 : 1,val); - for (i=0;i<=7;i++) { - irqs[i+irq_base].masked=(val&(1<0; - if(port==0x21) { - if (irqs[i+irq_base].active && !irqs[i+irq_base].masked) PIC_IRQCheck|=(1 << (i+irq_base)); - else PIC_IRQCheck&=~(1 << (i+irq_base)); - } else { - if (irqs[i+irq_base].active && !irqs[i+irq_base].masked && !irqs[2].masked) PIC_IRQCheck|=(1 << (i+irq_base)); - else PIC_IRQCheck&=~(1 << (i+irq_base)); - } - } - if (machine==MCH_PCJR) { - /* irq6 cannot be disabled as it serves as pseudo-NMI */ - irqs[6].masked=false; - } - if(irqs[2].masked != old_irq2_mask) { - /* Irq 2 mask has changed recheck second pic */ - for(i=8;i<=15;i++) { - if (irqs[i].active && !irqs[i].masked && !irqs[2].masked) PIC_IRQCheck|=(1 << (i)); - else PIC_IRQCheck&=~(1 << (i)); - } - } - if (PIC_IRQCheck) { - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=0; - } - break; - case 1: /* icw2 */ - LOG(LOG_PIC,LOG_NORMAL)("%d:Base vector %X",port==0x21 ? 0 : 1,val); - for (i=0;i<=7;i++) { - irqs[i+irq_base].vector=(val&0xf8)+i; - }; - if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0; - else if(pic->single) pic->icw_index=3; /* skip ICW3 in single mode */ - break; - case 2: /* icw 3 */ - LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 3 %X",port==0x21 ? 0 : 1,val); - if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0; - break; - case 3: /* icw 4 */ - /* - 0 1 8086/8080 0 mcs-8085 mode - 1 1 Auto EOI 0 Normal EOI - 2-3 0x Non buffer Mode - 10 Buffer Mode Slave - 11 Buffer mode Master - 4 Special/Not Special nested mode - */ - pic->auto_eoi=(val & 0x2)>0; - - LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 4 %X",port==0x21 ? 0 : 1,val); - - if ((val&0x01)==0) E_Exit("PIC:ICW4: %x, 8085 mode not handled",val); - if ((val&0x10)!=0) LOG_MSG("PIC:ICW4: %x, special fully-nested mode not handled",val); - - if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0; - break; - default: - LOG(LOG_PIC,LOG_NORMAL)("ICW HUH? %X",val); - break; - } -} - - -static Bitu read_command(Bitu port,Bitu iolen) { - PIC_Controller * pic=&pics[port==0x20 ? 0 : 1]; - Bitu irq_base=(port==0x20) ? 0 : 8; - Bitu i;Bit8u ret=0;Bit8u b=1; - if (pic->request_issr) { - for (i=irq_base;i 7 && irqs[2].masked) return false; - irqs[i].active = false; - PIC_IRQCheck&= ~(1 << i); - PIC_IRQOnSecondPicActive&= ~(1 << i); - CPU_HW_Interrupt(irqs[i].vector); - Bitu pic=(i&8)>>3; - if (!pics[pic].auto_eoi) { //irq 0-7 => pic 0 else pic 1 - PIC_IRQActive = i; - irqs[i].inservice = true; - } else if (pics[pic].rotate_on_auto_eoi) { - E_Exit("rotate on auto EOI not handled"); - } - return true; -} - -void PIC_runIRQs(void) { - if (!GETFLAG(IF)) return; - if (!PIC_IRQCheck) return; - if (cpudecoder==CPU_Core_Normal_Trap_Run) return; - - static Bitu IRQ_priority_order[16] = - { 0,1,2,8,9,10,11,12,13,14,15,3,4,5,6,7 }; - static Bit16u IRQ_priority_lookup[17] = - { 0,1,2,11,12,13,14,15,3,4,5,6,7,8,9,10,16 }; - Bit16u activeIRQ = PIC_IRQActive; - if (activeIRQ == PIC_NOIRQ) activeIRQ = 16; - /* Get the priority of the active irq */ - Bit16u Priority_Active_IRQ = IRQ_priority_lookup[activeIRQ]; - - Bitu i,j; - /* j is the priority (walker) - * i is the irq at the current priority */ - - /* If one of the pics is in special mode use a check that cares for that. */ - if(!PIC_Special_Mode) { - for (j = 0; j < Priority_Active_IRQ; j++) { - i = IRQ_priority_order[j]; - if (!irqs[i].masked && irqs[i].active) { - if(PIC_startIRQ(i)) return; - } - } - } else { /* Special mode variant */ - for (j = 0; j<= 15; j++) { - i = IRQ_priority_order[j]; - if ( (j < Priority_Active_IRQ) || (pics[ ((i&8)>>3) ].special) ) { - if (!irqs[i].masked && irqs[i].active) { - /* the irq line is active. it's not masked and - * the irq is allowed priority wise. So let's start it */ - /* If started succesfully return, else go for the next */ - if(PIC_startIRQ(i)) return; - } - } - } - } -} - -void PIC_SetIRQMask(Bitu irq, bool masked) { - if(irqs[irq].masked == masked) return; /* Do nothing if mask doesn't change */ - bool old_irq2_mask = irqs[2].masked; - irqs[irq].masked=masked; - if(irq < 8) { - if (irqs[irq].active && !irqs[irq].masked) { - PIC_IRQCheck|=(1 << (irq)); - } else { - PIC_IRQCheck&=~(1 << (irq)); - } - } else { - if (irqs[irq].active && !irqs[irq].masked && !irqs[2].masked) { - PIC_IRQCheck|=(1 << (irq)); - } else { - PIC_IRQCheck&=~(1 << (irq)); - } - } - if(irqs[2].masked != old_irq2_mask) { - /* Irq 2 mask has changed recheck second pic */ - for(Bitu i=8;i<=15;i++) { - if (irqs[i].active && !irqs[i].masked && !irqs[2].masked) PIC_IRQCheck|=(1 << (i)); - else PIC_IRQCheck&=~(1 << (i)); - } - } - if (PIC_IRQCheck) { - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=0; - } -} - -static void AddEntry(PICEntry * entry) { - PICEntry * find_entry=pic_queue.next_entry; - if (!find_entry) { - entry->next=0; - pic_queue.next_entry=entry; - } else if (find_entry->index>entry->index) { - pic_queue.next_entry=entry; - entry->next=find_entry; - } else while (find_entry) { - if (find_entry->next) { - /* See if the next index comes later than this one */ - if (find_entry->next->index > entry->index) { - entry->next=find_entry->next; - find_entry->next=entry; - break; - } else { - find_entry=find_entry->next; - } - } else { - entry->next=find_entry->next; - find_entry->next=entry; - break; - } - } - Bits cycles=PIC_MakeCycles(pic_queue.next_entry->index-PIC_TickIndex()); - if (cyclesindex=delay+PIC_TickIndex(); - entry->pic_event=handler; - entry->value=val; - pic_queue.free_entry=pic_queue.free_entry->next; - AddEntry(entry); -} - -void PIC_RemoveSpecificEvents(PIC_EventHandler handler, Bitu val) { - PICEntry * entry=pic_queue.next_entry; - PICEntry * prev_entry; - prev_entry = 0; - while (entry) { - if ((entry->pic_event == handler) && (entry->value == val)) { - if (prev_entry) { - prev_entry->next=entry->next; - entry->next=pic_queue.free_entry; - pic_queue.free_entry=entry; - entry=prev_entry->next; - continue; - } else { - pic_queue.next_entry=entry->next; - entry->next=pic_queue.free_entry; - pic_queue.free_entry=entry; - entry=pic_queue.next_entry; - continue; - } - } - prev_entry=entry; - entry=entry->next; - } -} - -void PIC_RemoveEvents(PIC_EventHandler handler) { - PICEntry * entry=pic_queue.next_entry; - PICEntry * prev_entry; - prev_entry=0; - while (entry) { - if (entry->pic_event==handler) { - if (prev_entry) { - prev_entry->next=entry->next; - entry->next=pic_queue.free_entry; - pic_queue.free_entry=entry; - entry=prev_entry->next; - continue; - } else { - pic_queue.next_entry=entry->next; - entry->next=pic_queue.free_entry; - pic_queue.free_entry=entry; - entry=pic_queue.next_entry; - continue; - } - } - prev_entry=entry; - entry=entry->next; - } -} - - -bool PIC_RunQueue(void) { - /* Check to see if a new milisecond needs to be started */ - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=0; - if (CPU_CycleLeft<=0) { - return false; - } - /* Check the queue for an entry */ - Bits index_nd=PIC_TickIndexND(); - while (pic_queue.next_entry && (pic_queue.next_entry->index*CPU_CycleMax<=index_nd)) { - PICEntry * entry=pic_queue.next_entry; - pic_queue.next_entry=entry->next; - (entry->pic_event)(entry->value); - /* Put the entry in the free list */ - entry->next=pic_queue.free_entry; - pic_queue.free_entry=entry; - } - /* Check when to set the new cycle end */ - if (pic_queue.next_entry) { - Bits cycles=(Bits)(pic_queue.next_entry->index*CPU_CycleMax-index_nd); - if (!cycles) cycles=1; - if (cycleshandler==handler) { - *tick_where=ticker->next; - delete ticker; - return; - } - tick_where=&ticker->next; - ticker=ticker->next; - } -} - -void TIMER_AddTickHandler(TIMER_TickHandler handler) { - TickerBlock * newticker=new TickerBlock; - newticker->next=firstticker; - newticker->handler=handler; - firstticker=newticker; -} - -void TIMER_AddTick(void) { - /* Setup new amount of cycles for PIC */ - CPU_CycleLeft=CPU_CycleMax; - CPU_Cycles=0; - PIC_Ticks++; - /* Go through the list of scheduled events and lower their index with 1000 */ - PICEntry * entry=pic_queue.next_entry; - while (entry) { - if (entry->index>=1) entry->index-=1; - else entry->index=0; - entry=entry->next; - } - /* Call our list of ticker handlers */ - TickerBlock * ticker=firstticker; - while (ticker) { - TickerBlock * nextticker=ticker->next; - ticker->handler(); - ticker=nextticker; - } -} - - -class PIC:public Module_base{ -private: - IO_ReadHandleObject ReadHandler[4]; - IO_WriteHandleObject WriteHandler[4]; -public: - PIC(Section* configuration):Module_base(configuration){ - /* Setup pic0 and pic1 with initial values like DOS has normally */ - PIC_IRQCheck=0; - PIC_IRQActive=PIC_NOIRQ; - PIC_Ticks=0; - Bitu i; - for (i=0;i<2;i++) { - pics[i].masked=0xff; - pics[i].auto_eoi=false; - pics[i].rotate_on_auto_eoi=false; - pics[i].request_issr=false; - pics[i].special=false; - pics[i].single=false; - pics[i].icw_index=0; - pics[i].icw_words=0; - } - for (i=0;i<=7;i++) { - irqs[i].active=false; - irqs[i].masked=true; - irqs[i].inservice=false; - irqs[i+8].active=false; - irqs[i+8].masked=true; - irqs[i+8].inservice=false; - irqs[i].vector=0x8+i; - irqs[i+8].vector=0x70+i; - } - irqs[0].masked=false; /* Enable system timer */ - irqs[1].masked=false; /* Enable Keyboard IRQ */ - irqs[2].masked=false; /* Enable second pic */ - irqs[8].masked=false; /* Enable RTC IRQ */ - if (machine==MCH_PCJR) { - /* Enable IRQ6 (replacement for the NMI for PCJr) */ - irqs[6].masked=false; - } - ReadHandler[0].Install(0x20,read_command,IO_MB); - ReadHandler[1].Install(0x21,read_data,IO_MB); - WriteHandler[0].Install(0x20,write_command,IO_MB); - WriteHandler[1].Install(0x21,write_data,IO_MB); - ReadHandler[2].Install(0xa0,read_command,IO_MB); - ReadHandler[3].Install(0xa1,read_data,IO_MB); - WriteHandler[2].Install(0xa0,write_command,IO_MB); - WriteHandler[3].Install(0xa1,write_data,IO_MB); - /* Initialize the pic queue */ - for (i=0;iAddDestroyFunction(&PIC_Destroy); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include "dosbox.h" +#include "inout.h" +#include "cpu.h" +#include "pic.h" + +struct IRQ_Block { + bool masked; + bool active; + bool inservice; + Bit8u vector; + char * name; + PIC_EOIHandler * handler; +}; + +Bit32u PIC_IRQCheck; + +static IRQ_Block irqs[16]; +static Bit8u pic0_icws=0; +static Bit8u pic1_icws=0; +static Bit8u pic0_icw_state=0; +static Bit8u pic1_icw_state=0; +static bool pic0_request_iisr=0; +static bool pic1_request_iisr=0; +//TODO Special mask mode in ocw3 +//TODO maybe check for illegal modes that don't work on pc too and exit the emu + +//Pic 0 command port +static void write_p20(Bit32u port,Bit8u val) { + Bit32u i; + switch (val) { + case 0x0A: /* select read interrupt request register */ + pic0_request_iisr=false; + break; + case 0x0B: /* select read interrupt in-service register */ + pic0_request_iisr=true; + break; + case 0x10: /* ICW1 */ + pic0_icws=2; + pic0_icw_state=1; + + break; + case 0x11: /* ICW1 + need for ICW4 */ + pic0_icws=3; + pic0_icw_state=1; + break; + case 0x20: /* end of interrupt command */ + /* clear highest current in service bit */ + for (i=0;i<=7;i++) { + if (irqs[i].inservice) { + irqs[i].inservice=false; + if (irqs[i].handler!=0) irqs[i].handler(); + break; + }; + }; + break; + case 0x60: /* specific EOI 0 */ + case 0x61: /* specific EOI 1 */ + case 0x62: /* specific EOI 2 */ + case 0x63: /* specific EOI 3 */ + case 0x64: /* specific EOI 4 */ + case 0x65: /* specific EOI 5 */ + case 0x66: /* specific EOI 6 */ + case 0x67: /* specific EOI 7 */ + if (irqs[val-0x60].inservice) { + irqs[val-0x60].inservice=false; + if (irqs[val-0x60].handler!=0) irqs[val-0x60].handler(); + }; + break; + // IRQ lowest priority commands + case 0xC0: // 0 7 6 5 4 3 2 1 + case 0xC1: // 1 0 7 6 5 4 3 2 + case 0xC2: // 2 1 0 7 6 5 4 3 + case 0xC3: // 3 2 1 0 7 6 5 4 + case 0xC4: // 4 3 2 1 0 7 6 5 + case 0xC5: // 5 4 3 2 1 0 7 6 + case 0xC6: // 6 5 4 3 2 1 0 7 + case 0xC7: // 7 6 5 4 3 2 1 0 + // ignore for now TODO + break; + default: + E_Exit("PIC0:Unhandled command %02X",val); + } +} + +//Pic 0 Interrupt mask +static void write_p21(Bit32u port,Bit8u val) { + Bit8u i; + switch(pic0_icw_state) { + case 0: /* mask register */ + for (i=0;i<=7;i++) { + irqs[i].masked=(val&(1<0; + if (irqs[i].active && !irqs[i].masked) PIC_IRQCheck|=(1 << 1); + else PIC_IRQCheck&=~(1 << i); + }; + break; + case 1: /* icw2 */ + for (i=0;i<=7;i++) { + irqs[i].vector=(val&0xf8)+i; + }; + default: /* icw2, 3, and 4*/ + if(pic0_icw_state++ >= pic0_icws) pic0_icw_state=0; + } + +} + +static Bit8u read_p20(Bit32u port) { + Bit8u ret=0; + Bit32u i; + Bit8u b=1; + if (pic0_request_iisr) { + for (i=0;i<=7;i++) { + if (irqs[i].inservice) ret|=b; + b <<= 1; + } + } else { + for (i=0;i<=7;i++) { + if (irqs[i].active) ret|=b; + b <<= 1; + } + }; + return ret; +} + +static Bit8u read_p21(Bit32u port) { + Bit8u ret=0; + Bit32u i; + Bit8u b=1; + for (i=0;i<=7;i++) { + if (irqs[i].masked) ret|=b; + b <<= 1; + } + return ret; +} + +static void write_pa0(Bit32u port,Bit8u val) { + Bit32u i; + switch (val) { + case 0x0A: /* select read interrupt request register */ + pic1_request_iisr=false; + break; + case 0x0B: /* select read interrupt in-service register */ + pic1_request_iisr=true; + break; + case 0x10: /* ICW1 */ + /* Clear everything set full mask and clear all inservice */ + for (i=0;i<=7;i++) { + irqs[i].masked=true; + irqs[i].active=false; + irqs[i].inservice=false; + } + pic1_icws=2; + pic1_icw_state=1; + break; + case 0x11: /* ICW1 + need for ICW4 */ + pic1_icws=3; + pic1_icw_state=1; + break; + case 0x20: /* end of interrupt command */ + /* clear highest current in service bit */ + for (i=8;i<=15;i++) { + if (irqs[i].inservice) { + irqs[i].inservice=false; + if (irqs[i].handler!=0) irqs[i].handler(); + break; + }; + }; + break; + case 0x60: /* specific EOI 0 */ + case 0x61: /* specific EOI 1 */ + case 0x62: /* specific EOI 2 */ + case 0x63: /* specific EOI 3 */ + case 0x64: /* specific EOI 4 */ + case 0x65: /* specific EOI 5 */ + case 0x66: /* specific EOI 6 */ + case 0x67: /* specific EOI 7 */ + if (irqs[val-0x60+8].inservice) { + irqs[val-0x60+8].inservice=false; + if (irqs[val-0x60+8].handler!=0) irqs[val-0x60+8].handler(); + }; + break; + // IRQ lowest priority commands + case 0xC0: // 0 7 6 5 4 3 2 1 + case 0xC1: // 1 0 7 6 5 4 3 2 + case 0xC2: // 2 1 0 7 6 5 4 3 + case 0xC3: // 3 2 1 0 7 6 5 4 + case 0xC4: // 4 3 2 1 0 7 6 5 + case 0xC5: // 5 4 3 2 1 0 7 6 + case 0xC6: // 6 5 4 3 2 1 0 7 + case 0xC7: // 7 6 5 4 3 2 1 0 + //TODO Maybe does it even matter? + break; + default: + E_Exit("Unhandled command %04X sent to port A0",val); + } +} + + +static void write_pa1(Bit32u port,Bit8u val) { + Bit8u i; + switch(pic1_icw_state) { + case 0: /* mask register */ + for (i=0;i<=7;i++) { + irqs[i+8].masked=(val&1 <0; + }; + break; + case 1: /* icw2 */ + for (i=0;i<=7;i++) { + irqs[i+8].vector=(val&0xf8)+i; + }; + default: /* icw2, 3, and 4*/ + if(pic1_icw_state++ >= pic1_icws) pic1_icw_state=0; + } +} + +static Bit8u read_pa0(Bit32u port) { + Bit8u ret=0; + Bit32u i; + Bit8u b=1; + if (pic1_request_iisr) { + for (i=0;i<=7;i++) { + if (irqs[i+8].inservice) ret|=b; + b <<= 1; + } + } else { + for (i=0;i<=7;i++) { + if (irqs[i+8].active) ret|=b; + b <<= 1; + } + }; + return ret; +} + + +static Bit8u read_pa1(Bit32u port) { + Bit8u ret=0; + Bit32u i; + Bit8u b=1; + for (i=0;i<=7;i++) { + if (irqs[i+8].masked) ret|=b; + b <<= 1; + } + return ret; +} + +void PIC_RegisterIRQ(Bit32u irq,PIC_EOIHandler handler,char * name) { + if (irq>15) E_Exit("PIC:Illegal IRQ"); + irqs[irq].name=name; + irqs[irq].handler=handler; +} + +void PIC_FreeIRQ(Bit32u irq) { + if (irq>15) E_Exit("PIC:Illegal IRQ"); + irqs[irq].name=0; + irqs[irq].handler=0; + irqs[irq].active=0; + irqs[irq].inservice=0; + PIC_IRQCheck&=~(1 << irq); +} + +void PIC_ActivateIRQ(Bit32u irq) { + if (irq<16) { + irqs[irq].active=true; + if (!irqs[irq].masked) { + PIC_IRQCheck|=(1 << irq); + } + } +} + +void PIC_DeActivateIRQ(Bit32u irq) { + if (irq<16) { + irqs[irq].active=false; + PIC_IRQCheck&=~(1 << irq); + } +} + +bool PIC_IRQActive(Bit32u irq) { + if (irq<16) { + return irqs[irq].active; + } + return true; +} + + +#define PIC_MAXQUEUE 16 +static PIC_Function * pic_queue[PIC_MAXQUEUE]; +static Bit32u pic_queuesize; + +void PIC_QueueFunction(PIC_Function * function) { + if (pic_queuesize0;) { + (*pic_queue[--pic_queuesize])(); + } +}; + + +void PIC_Init(void) { + /* Setup pic0 and pic1 with initial values like DOS has normally */ + PIC_IRQCheck=0; + Bit8u i; + for (i=0;i<=7;i++) { + irqs[i].active=false; + irqs[i].masked=true; + irqs[i].inservice=false; + irqs[i+8].active=false; + irqs[i+8].masked=true; + irqs[i+8].inservice=false; + irqs[i].vector=0x8+i; + irqs[i+8].vector=0x70+i; + }; + irqs[0].masked=false; /* Enable system timer */ + irqs[1].masked=false; /* Enable Keyboard IRQ */ + irqs[2].masked=false; /* Enable 2nd PIC Although i can't care if this is masked */ + irqs[12].masked=false; + IO_RegisterReadHandler(0x20,read_p20,"Master PIC Command"); + IO_RegisterReadHandler(0x21,read_p21,"Master PIC Data"); + IO_RegisterWriteHandler(0x20,write_p20,"Master PIC Command"); + IO_RegisterWriteHandler(0x21,write_p21,"Master PIC Data"); + IO_RegisterReadHandler(0xa0,read_pa0,"Slave PIC Command"); + IO_RegisterReadHandler(0xa1,read_pa1,"Slave PIC Data"); + IO_RegisterWriteHandler(0xa0,write_pa0,"Slave PIC Command"); + IO_RegisterWriteHandler(0xa1,write_pa1,"Slave PIC Data"); +}; + + diff --git a/src/hardware/sblaster.cpp b/src/hardware/sblaster.cpp index 8bfb4b4..5b1c0f2 100644 --- a/src/hardware/sblaster.cpp +++ b/src/hardware/sblaster.cpp @@ -1,1569 +1,613 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: sblaster.cpp,v 1.73 2009/04/25 07:02:28 qbix79 Exp $ */ - -#include -#include -#include -#include -#include "dosbox.h" -#include "inout.h" -#include "mixer.h" -#include "dma.h" -#include "pic.h" -#include "hardware.h" -#include "setup.h" -#include "support.h" -#include "shell.h" -using namespace std; - -void MIDI_RawOutByte(Bit8u data); -bool MIDI_Available(void); - -#define SB_PIC_EVENTS 0 - -#define DSP_MAJOR 3 -#define DSP_MINOR 1 - -#define MIXER_INDEX 0x04 -#define MIXER_DATA 0x05 - -#define DSP_RESET 0x06 -#define DSP_READ_DATA 0x0A -#define DSP_WRITE_DATA 0x0C -#define DSP_WRITE_STATUS 0x0C -#define DSP_READ_STATUS 0x0E -#define DSP_ACK_16BIT 0x0f - -#define DSP_NO_COMMAND 0 - -#define DMA_BUFSIZE 1024 -#define DSP_BUFSIZE 64 -#define DSP_DACSIZE 512 - -//Should be enough for sound generated in millisecond blocks -#define SB_BUF_SIZE 8096 -#define SB_SH 14 -#define SB_SH_MASK ((1 << SB_SH)-1) - -enum {DSP_S_RESET,DSP_S_NORMAL,DSP_S_HIGHSPEED}; -enum SB_TYPES {SBT_NONE=0,SBT_1=1,SBT_PRO1=2,SBT_2=3,SBT_PRO2=4,SBT_16=6}; -enum SB_IRQS {SB_IRQ_8,SB_IRQ_16,SB_IRQ_MPU}; - -enum DSP_MODES { - MODE_NONE, - MODE_DAC, - MODE_DMA, - MODE_DMA_PAUSE, - MODE_DMA_MASKED - -}; - -enum DMA_MODES { - DSP_DMA_NONE, - DSP_DMA_2,DSP_DMA_3,DSP_DMA_4,DSP_DMA_8, - DSP_DMA_16,DSP_DMA_16_ALIASED -}; - -enum { - PLAY_MONO,PLAY_STEREO -}; - -struct SB_INFO { - Bitu freq; - struct { - bool stereo,sign,autoinit; - DMA_MODES mode; - Bitu rate,mul; - Bitu total,left,min; - Bit64u start; - union { - Bit8u b8[DMA_BUFSIZE]; - Bit16s b16[DMA_BUFSIZE]; - } buf; - Bitu bits; - DmaChannel * chan; - Bitu remain_size; - } dma; - bool speaker; - bool midi; - Bit8u time_constant; - DSP_MODES mode; - SB_TYPES type; - struct { - bool pending_8bit; - bool pending_16bit; - } irq; - struct { - Bit8u state; - Bit8u cmd; - Bit8u cmd_len; - Bit8u cmd_in_pos; - Bit8u cmd_in[DSP_BUFSIZE]; - struct { - Bit8u data[DSP_BUFSIZE]; - Bitu pos,used; - } in,out; - Bit8u test_register; - Bitu write_busy; - } dsp; - struct { - Bit16s data[DSP_DACSIZE+1]; - Bitu used; - Bit16s last; - } dac; - struct { - Bit8u index; - Bit8u dac[2],fm[2],cda[2],master[2],lin[2]; - Bit8u mic; - bool stereo; - bool enabled; - bool filtered; - Bit8u unhandled[0x48]; - } mixer; - struct { - Bit8u reference; - Bits stepsize; - bool haveref; - } adpcm; - struct { - Bitu base; - Bitu irq; - Bitu dma8,dma16; - } hw; - struct { - Bits value; - Bitu count; - } e2; - MixerChannel * chan; -}; - - - -static SB_INFO sb; - -static char const * const copyright_string="COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; - -// number of bytes in input for commands (sb/sbpro) -static Bit8u DSP_cmd_len_sb[256] = { - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x00 -// 1,0,0,0, 2,0,2,2, 0,0,0,0, 0,0,0,0, // 0x10 - 1,0,0,0, 2,2,2,2, 0,0,0,0, 0,0,0,0, // 0x10 Wari hack - 0,0,0,0, 2,0,0,0, 0,0,0,0, 0,0,0,0, // 0x20 - 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, // 0x30 - - 1,2,2,0, 0,0,0,0, 2,0,0,0, 0,0,0,0, // 0x40 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x50 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x60 - 0,0,0,0, 2,2,2,2, 0,0,0,0, 0,0,0,0, // 0x70 - - 2,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x80 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x90 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xa0 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xb0 - - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xc0 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xd0 - 1,0,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, // 0xe0 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 // 0xf0 -}; - -// number of bytes in input for commands (sb16) -static Bit8u DSP_cmd_len_sb16[256] = { - 0,0,0,0, 1,2,0,0, 1,0,0,0, 0,0,2,1, // 0x00 -// 1,0,0,0, 2,0,2,2, 0,0,0,0, 0,0,0,0, // 0x10 - 1,0,0,0, 2,2,2,2, 0,0,0,0, 0,0,0,0, // 0x10 Wari hack - 0,0,0,0, 2,0,0,0, 0,0,0,0, 0,0,0,0, // 0x20 - 0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0, // 0x30 - - 1,2,2,0, 0,0,0,0, 2,0,0,0, 0,0,0,0, // 0x40 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x50 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x60 - 0,0,0,0, 2,2,2,2, 0,0,0,0, 0,0,0,0, // 0x70 - - 2,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x80 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x90 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xa0 - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xb0 - - 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xc0 - 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xd0 - 1,0,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, // 0xe0 - 0,0,0,0, 0,0,0,0, 0,1,0,0, 0,0,0,0 // 0xf0 -}; - -static Bit8u ASP_regs[256]; -static bool ASP_init_in_progress = false; - -static int E2_incr_table[4][9] = { - { 0x01, -0x02, -0x04, 0x08, -0x10, 0x20, 0x40, -0x80, -106 }, - { -0x01, 0x02, -0x04, 0x08, 0x10, -0x20, 0x40, -0x80, 165 }, - { -0x01, 0x02, 0x04, -0x08, 0x10, -0x20, -0x40, 0x80, -151 }, - { 0x01, -0x02, 0x04, -0x08, -0x10, 0x20, -0x40, 0x80, 90 } -}; - -#ifndef max -#define max(a,b) ((a)>(b)?(a):(b)) -#endif -#ifndef min -#define min(a,b) ((a)<(b)?(a):(b)) -#endif - -static void DSP_ChangeMode(DSP_MODES mode); -static void CheckDMAEnd(); -static void END_DMA_Event(Bitu); -static void DMA_Silent_Event(Bitu val); -static void GenerateDMASound(Bitu size); - -static void DSP_SetSpeaker(bool how) { - if (sb.speaker==how) return; - sb.speaker=how; - if (sb.type==SBT_16) return; - sb.chan->Enable(how); - if (sb.speaker) { - PIC_RemoveEvents(DMA_Silent_Event); - CheckDMAEnd(); - } else { - - } -} - -static INLINE void SB_RaiseIRQ(SB_IRQS type) { - LOG(LOG_SB,LOG_NORMAL)("Raising IRQ"); - PIC_ActivateIRQ(sb.hw.irq); - switch (type) { - case SB_IRQ_8: - sb.irq.pending_8bit=true; - break; - case SB_IRQ_16: - sb.irq.pending_16bit=true; - break; - default: - break; - } -} - -static INLINE void DSP_FlushData(void) { - sb.dsp.out.used=0; - sb.dsp.out.pos=0; -} - -static void DSP_DMA_CallBack(DmaChannel * chan, DMAEvent event) { - if (event==DMA_REACHED_TC) return; - else if (event==DMA_MASKED) { - if (sb.mode==MODE_DMA) { - GenerateDMASound(sb.dma.min); - sb.mode=MODE_DMA_MASKED; -// DSP_ChangeMode(MODE_DMA_MASKED); - LOG(LOG_SB,LOG_NORMAL)("DMA masked,stopping output, left %d",chan->currcnt); - } - } else if (event==DMA_UNMASKED) { - if (sb.mode==MODE_DMA_MASKED && sb.dma.mode!=DSP_DMA_NONE) { - DSP_ChangeMode(MODE_DMA); -// sb.mode=MODE_DMA; - CheckDMAEnd(); - LOG(LOG_SB,LOG_NORMAL)("DMA unmasked,starting output, auto %d block %d",chan->autoinit,chan->basecnt); - } - } -} - -#define MIN_ADAPTIVE_STEP_SIZE 0 -#define MAX_ADAPTIVE_STEP_SIZE 32767 -#define DC_OFFSET_FADE 254 - -static INLINE Bit8u decode_ADPCM_4_sample(Bit8u sample,Bit8u & reference,Bits& scale) { - static const Bit8s scaleMap[64] = { - 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, - 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, - 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, - 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60 - }; - static const Bit8u adjustMap[64] = { - 0, 0, 0, 0, 0, 16, 16, 16, - 0, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 16, 16, 16, - 240, 0, 0, 0, 0, 0, 0, 0, - 240, 0, 0, 0, 0, 0, 0, 0 - }; - - Bits samp = sample + scale; - - if ((samp < 0) || (samp > 63)) { - LOG(LOG_SB,LOG_ERROR)("Bad ADPCM-4 sample"); - if(samp < 0 ) samp = 0; - if(samp > 63) samp = 63; - } - - Bits ref = reference + scaleMap[samp]; - if (ref > 0xff) reference = 0xff; - else if (ref < 0x00) reference = 0x00; - else reference = ref; - scale = (scale + adjustMap[samp]) & 0xff; - - return reference; -} - -static INLINE Bit8u decode_ADPCM_2_sample(Bit8u sample,Bit8u & reference,Bits& scale) { - static const Bit8s scaleMap[24] = { - 0, 1, 0, -1, 1, 3, -1, -3, - 2, 6, -2, -6, 4, 12, -4, -12, - 8, 24, -8, -24, 6, 48, -16, -48 - }; - static const Bit8u adjustMap[24] = { - 0, 4, 0, 4, - 252, 4, 252, 4, 252, 4, 252, 4, - 252, 4, 252, 4, 252, 4, 252, 4, - 252, 0, 252, 0 - }; - - Bits samp = sample + scale; - if ((samp < 0) || (samp > 23)) { - LOG(LOG_SB,LOG_ERROR)("Bad ADPCM-2 sample"); - if(samp < 0 ) samp = 0; - if(samp > 23) samp = 23; - } - - Bits ref = reference + scaleMap[samp]; - if (ref > 0xff) reference = 0xff; - else if (ref < 0x00) reference = 0x00; - else reference = ref; - scale = (scale + adjustMap[samp]) & 0xff; - - return reference; -} - -INLINE Bit8u decode_ADPCM_3_sample(Bit8u sample,Bit8u & reference,Bits& scale) { - static const Bit8s scaleMap[40] = { - 0, 1, 2, 3, 0, -1, -2, -3, - 1, 3, 5, 7, -1, -3, -5, -7, - 2, 6, 10, 14, -2, -6, -10, -14, - 4, 12, 20, 28, -4, -12, -20, -28, - 5, 15, 25, 35, -5, -15, -25, -35 - }; - static const Bit8u adjustMap[40] = { - 0, 0, 0, 8, 0, 0, 0, 8, - 248, 0, 0, 8, 248, 0, 0, 8, - 248, 0, 0, 8, 248, 0, 0, 8, - 248, 0, 0, 8, 248, 0, 0, 8, - 248, 0, 0, 0, 248, 0, 0, 0 - }; - - Bits samp = sample + scale; - if ((samp < 0) || (samp > 39)) { - LOG(LOG_SB,LOG_ERROR)("Bad ADPCM-3 sample"); - if(samp < 0 ) samp = 0; - if(samp > 39) samp = 39; - } - - Bits ref = reference + scaleMap[samp]; - if (ref > 0xff) reference = 0xff; - else if (ref < 0x00) reference = 0x00; - else reference = ref; - scale = (scale + adjustMap[samp]) & 0xff; - - return reference; -} - -static void GenerateDMASound(Bitu size) { - Bitu read=0;Bitu done=0;Bitu i=0; - - if(sb.dma.autoinit) { - if (sb.dma.left <= size) size = sb.dma.left; - } else if (sb.dma.left <= sb.dma.min) size = sb.dma.left; - - switch (sb.dma.mode) { - case DSP_DMA_2: - read=sb.dma.chan->Read(size,sb.dma.buf.b8); - if (read && sb.adpcm.haveref) { - sb.adpcm.haveref=false; - sb.adpcm.reference=sb.dma.buf.b8[0]; - sb.adpcm.stepsize=MIN_ADAPTIVE_STEP_SIZE; - i++; - } - for (;i> 6) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize); - MixTemp[done++]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >> 4) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize); - MixTemp[done++]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >> 2) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize); - MixTemp[done++]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >> 0) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize); - } - sb.chan->AddSamples_m8(done,MixTemp); - break; - case DSP_DMA_3: - read=sb.dma.chan->Read(size,sb.dma.buf.b8); - if (read && sb.adpcm.haveref) { - sb.adpcm.haveref=false; - sb.adpcm.reference=sb.dma.buf.b8[0]; - sb.adpcm.stepsize=MIN_ADAPTIVE_STEP_SIZE; - i++; - } - for (;i> 5) & 0x7,sb.adpcm.reference,sb.adpcm.stepsize); - MixTemp[done++]=decode_ADPCM_3_sample((sb.dma.buf.b8[i] >> 2) & 0x7,sb.adpcm.reference,sb.adpcm.stepsize); - MixTemp[done++]=decode_ADPCM_3_sample((sb.dma.buf.b8[i] & 0x3) << 1,sb.adpcm.reference,sb.adpcm.stepsize); - } - sb.chan->AddSamples_m8(done,MixTemp); - break; - case DSP_DMA_4: - read=sb.dma.chan->Read(size,sb.dma.buf.b8); - if (read && sb.adpcm.haveref) { - sb.adpcm.haveref=false; - sb.adpcm.reference=sb.dma.buf.b8[0]; - sb.adpcm.stepsize=MIN_ADAPTIVE_STEP_SIZE; - i++; - } - for (;i> 4,sb.adpcm.reference,sb.adpcm.stepsize); - MixTemp[done++]=decode_ADPCM_4_sample(sb.dma.buf.b8[i]& 0xf,sb.adpcm.reference,sb.adpcm.stepsize); - } - sb.chan->AddSamples_m8(done,MixTemp); - break; - case DSP_DMA_8: - if (sb.dma.stereo) { - read=sb.dma.chan->Read(size,&sb.dma.buf.b8[sb.dma.remain_size]); - Bitu total=read+sb.dma.remain_size; - if (!sb.dma.sign) sb.chan->AddSamples_s8(total>>1,sb.dma.buf.b8); - else sb.chan->AddSamples_s8s(total>>1,(Bit8s*)sb.dma.buf.b8); - if (total&1) { - sb.dma.remain_size=1; - sb.dma.buf.b8[0]=sb.dma.buf.b8[total-1]; - } else sb.dma.remain_size=0; - } else { - read=sb.dma.chan->Read(size,sb.dma.buf.b8); - if (!sb.dma.sign) sb.chan->AddSamples_m8(read,sb.dma.buf.b8); - else sb.chan->AddSamples_m8s(read,(Bit8s *)sb.dma.buf.b8); - } - break; - case DSP_DMA_16: - case DSP_DMA_16_ALIASED: - if (sb.dma.stereo) { - /* In DSP_DMA_16_ALIASED mode temporarily divide by 2 to get number of 16-bit - samples, because 8-bit DMA Read returns byte size, while in DSP_DMA_16 mode - 16-bit DMA Read returns word size */ - read=sb.dma.chan->Read(size,(Bit8u *)&sb.dma.buf.b16[sb.dma.remain_size]) - >> (sb.dma.mode==DSP_DMA_16_ALIASED ? 1:0); - Bitu total=read+sb.dma.remain_size; -#if defined(WORDS_BIGENDIAN) - if (sb.dma.sign) sb.chan->AddSamples_s16_nonnative(total>>1,sb.dma.buf.b16); - else sb.chan->AddSamples_s16u_nonnative(total>>1,(Bit16u *)sb.dma.buf.b16); -#else - if (sb.dma.sign) sb.chan->AddSamples_s16(total>>1,sb.dma.buf.b16); - else sb.chan->AddSamples_s16u(total>>1,(Bit16u *)sb.dma.buf.b16); -#endif - if (total&1) { - sb.dma.remain_size=1; - sb.dma.buf.b16[0]=sb.dma.buf.b16[total-1]; - } else sb.dma.remain_size=0; - } else { - read=sb.dma.chan->Read(size,(Bit8u *)sb.dma.buf.b16) - >> (sb.dma.mode==DSP_DMA_16_ALIASED ? 1:0); -#if defined(WORDS_BIGENDIAN) - if (sb.dma.sign) sb.chan->AddSamples_m16_nonnative(read,sb.dma.buf.b16); - else sb.chan->AddSamples_m16u_nonnative(read,(Bit16u *)sb.dma.buf.b16); -#else - if (sb.dma.sign) sb.chan->AddSamples_m16(read,sb.dma.buf.b16); - else sb.chan->AddSamples_m16u(read,(Bit16u *)sb.dma.buf.b16); -#endif - } - //restore buffer length value to byte size in aliased mode - if (sb.dma.mode==DSP_DMA_16_ALIASED) read=read<<1; - break; - default: - LOG_MSG("Unhandled dma mode %d",sb.dma.mode); - sb.mode=MODE_NONE; - return; - } - sb.dma.left-=read; - if (!sb.dma.left) { - PIC_RemoveEvents(END_DMA_Event); - if (!sb.dma.autoinit) { - LOG(LOG_SB,LOG_NORMAL)("Single cycle transfer ended"); - sb.mode=MODE_NONE; - sb.dma.mode=DSP_DMA_NONE; - } else { - sb.dma.left=sb.dma.total; - if (!sb.dma.left) { - LOG(LOG_SB,LOG_NORMAL)("Auto-init transfer with 0 size"); - sb.mode=MODE_NONE; - } - } - if (sb.dma.mode >= DSP_DMA_16) SB_RaiseIRQ(SB_IRQ_16); - else SB_RaiseIRQ(SB_IRQ_8); - } -} - -/* old version... -static void GenerateDACSound(Bitu len) { - if (!sb.dac.used) { - sb.mode=MODE_NONE; - return; - } - Bitu dac_add=(sb.dac.used<<16)/len; - Bitu dac_pos=0; - Bit16s * out=(Bit16s *)MixTemp; - for (Bitu i=len;i;i--) { - *out++=sb.dac.data[0+(dac_pos>>16)]; - dac_pos+=dac_add; - } - sb.dac.used=0; - sb.chan->AddSamples_m16(len,(Bit16s *)MixTemp); -} -*/ - -static void DMA_Silent_Event(Bitu val) { - if (sb.dma.leftRead(val,sb.dma.buf.b8); - sb.dma.left-=read; - if (!sb.dma.left) { - if (sb.dma.mode >= DSP_DMA_16) SB_RaiseIRQ(SB_IRQ_16); - else SB_RaiseIRQ(SB_IRQ_8); - if (sb.dma.autoinit) sb.dma.left=sb.dma.total; - else { - sb.mode=MODE_NONE; - sb.dma.mode=DSP_DMA_NONE; - } - } - if (sb.dma.left) { - Bitu bigger=(sb.dma.left > sb.dma.min) ? sb.dma.min : sb.dma.left; - float delay=(bigger*1000.0f)/sb.dma.rate; - PIC_AddEvent(DMA_Silent_Event,delay,bigger); - } - -} - -static void END_DMA_Event(Bitu val) { - GenerateDMASound(val); -} - -static void CheckDMAEnd(void) { - if (!sb.dma.left) return; - if (!sb.speaker && sb.type!=SBT_16) { - Bitu bigger=(sb.dma.left > sb.dma.min) ? sb.dma.min : sb.dma.left; - float delay=(bigger*1000.0f)/sb.dma.rate; - PIC_AddEvent(DMA_Silent_Event,delay,bigger); - LOG(LOG_SB,LOG_NORMAL)("Silent DMA Transfer scheduling IRQ in %.3f milliseconds",delay); - } else if (sb.dma.leftFillUp(); - sb.mode=mode; -} - -static void DSP_RaiseIRQEvent(Bitu val) { - SB_RaiseIRQ(SB_IRQ_8); -} - -static void DSP_DoDMATransfer(DMA_MODES mode,Bitu freq,bool stereo) { - char const * type; - sb.mode=MODE_DMA_MASKED; - sb.chan->FillUp(); - sb.dma.left=sb.dma.total; - sb.dma.mode=mode; - sb.dma.stereo=stereo; - sb.irq.pending_8bit=false; - sb.irq.pending_16bit=false; - switch (mode) { - case DSP_DMA_2: - type="2-bits ADPCM"; - sb.dma.mul=(1 << SB_SH)/4; - break; - case DSP_DMA_3: - type="3-bits ADPCM"; - sb.dma.mul=(1 << SB_SH)/3; - break; - case DSP_DMA_4: - type="4-bits ADPCM"; - sb.dma.mul=(1 << SB_SH)/2; - break; - case DSP_DMA_8: - type="8-bits PCM"; - sb.dma.mul=(1 << SB_SH); - break; - case DSP_DMA_16_ALIASED: - type="16-bits(aliased) PCM"; - sb.dma.mul=(1 << SB_SH)*2; - break; - case DSP_DMA_16: - type="16-bits PCM"; - sb.dma.mul=(1 << SB_SH); - break; - default: - LOG(LOG_SB,LOG_ERROR)("DSP:Illegal transfer mode %d",mode); - return; - } - if (sb.dma.stereo) sb.dma.mul*=2; - sb.dma.rate=(sb.freq*sb.dma.mul) >> SB_SH; - sb.dma.min=(sb.dma.rate*3)/1000; - sb.chan->SetFreq(freq); - sb.dma.mode=mode; - PIC_RemoveEvents(END_DMA_Event); - sb.dma.chan->Register_Callback(DSP_DMA_CallBack); -#if (C_DEBUG) - LOG(LOG_SB,LOG_NORMAL)("DMA Transfer:%s %s %s freq %d rate %d size %d", - type, - sb.dma.stereo ? "Stereo" : "Mono", - sb.dma.autoinit ? "Auto-Init" : "Single-Cycle", - freq,sb.dma.rate,sb.dma.total - ); -#endif -} - -static void DSP_PrepareDMA_Old(DMA_MODES mode,bool autoinit,bool sign) { - sb.dma.autoinit=autoinit; - sb.dma.sign=sign; - if (!autoinit) sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); - sb.dma.chan=GetDMAChannel(sb.hw.dma8); - DSP_DoDMATransfer(mode,sb.freq / (sb.mixer.stereo ? 2 : 1),sb.mixer.stereo); -} - -static void DSP_PrepareDMA_New(DMA_MODES mode,Bitu length,bool autoinit,bool stereo) { - Bitu freq=sb.freq; - //equal length if data format and dma channel are both 16-bit or 8-bit - sb.dma.total=length; - sb.dma.autoinit=autoinit; - if (mode==DSP_DMA_16) { - if (sb.hw.dma16!=0xff) { - sb.dma.chan=GetDMAChannel(sb.hw.dma16); - if (sb.dma.chan==NULL) { - sb.dma.chan=GetDMAChannel(sb.hw.dma8); - mode=DSP_DMA_16_ALIASED; - sb.dma.total<<=1; - } - } else { - sb.dma.chan=GetDMAChannel(sb.hw.dma8); - mode=DSP_DMA_16_ALIASED; - //UNDOCUMENTED: - //In aliased mode sample length is written to DSP as number of - //16-bit samples so we need double 8-bit DMA buffer length - sb.dma.total<<=1; - } - } else sb.dma.chan=GetDMAChannel(sb.hw.dma8); - DSP_DoDMATransfer(mode,freq,stereo); -} - - -static void DSP_AddData(Bit8u val) { - if (sb.dsp.out.used=DSP_BUFSIZE) start-=DSP_BUFSIZE; - sb.dsp.out.data[start]=val; - sb.dsp.out.used++; - } else { - LOG(LOG_SB,LOG_ERROR)("DSP:Data Output buffer full"); - } -} - - -static void DSP_Reset(void) { - LOG(LOG_SB,LOG_ERROR)("DSP:Reset"); - PIC_DeActivateIRQ(sb.hw.irq); - DSP_ChangeMode(MODE_NONE); - sb.dsp.cmd_len=0; - sb.dsp.in.pos=0; - sb.dsp.write_busy=0; - sb.dma.left=0; - sb.dma.total=0; - sb.dma.stereo=false; - sb.dma.sign=false; - sb.dma.autoinit=false; - sb.dma.mode=DSP_DMA_NONE; - sb.dma.remain_size=0; - if (sb.dma.chan) sb.dma.chan->Clear_Request(); - sb.freq=22050; - sb.time_constant=45; - sb.dac.used=0; - sb.dac.last=0; - sb.e2.value=0xaa; - sb.e2.count=0; - sb.irq.pending_8bit=false; - sb.irq.pending_16bit=false; - sb.chan->SetFreq(22050); -// DSP_SetSpeaker(false); - PIC_RemoveEvents(END_DMA_Event); -} - - -static void DSP_DoReset(Bit8u val) { - if ((val&1)!=0) { -//TODO Get out of highspeed mode - DSP_Reset(); - sb.dsp.state=DSP_S_RESET; - } else { - DSP_FlushData(); - DSP_AddData(0xaa); - sb.dsp.state=DSP_S_NORMAL; - } -} - -static void DSP_E2_DMA_CallBack(DmaChannel * chan, DMAEvent event) { - if (event==DMA_UNMASKED) { - Bit8u val=sb.e2.value; - DmaChannel * chan=GetDMAChannel(sb.hw.dma8); - chan->Register_Callback(0); - chan->Write(1,&val); - } -} - -static void DSP_ADC_CallBack(DmaChannel * chan, DMAEvent event) { - if (event!=DMA_UNMASKED) return; - Bit8u val=128; - DmaChannel * ch=GetDMAChannel(sb.hw.dma8); - while (sb.dma.left--) { - ch->Write(1,&val); - } - SB_RaiseIRQ(SB_IRQ_8); - ch->Register_Callback(0); -} - -Bitu DEBUG_EnableDebugger(void); - -#define DSP_SB16_ONLY if (sb.type != SBT_16) { LOG(LOG_SB,LOG_ERROR)("DSP:Command %2X requires SB16",sb.dsp.cmd); break; } -#define DSP_SB2_ABOVE if (sb.type <= SBT_1) { LOG(LOG_SB,LOG_ERROR)("DSP:Command %2X requires SB2 or above",sb.dsp.cmd); break; } - -static void DSP_DoCommand(void) { -// LOG_MSG("DSP Command %X",sb.dsp.cmd); - switch (sb.dsp.cmd) { - case 0x04: - if (sb.type == SBT_16) { - /* SB16 ASP set mode register */ - if ((sb.dsp.in.data[0]&0xf1)==0xf1) ASP_init_in_progress=true; - else ASP_init_in_progress=false; - LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X (set mode register to %X)",sb.dsp.cmd,sb.dsp.in.data[0]); - } else { - /* DSP Status SB 2.0/pro version. NOT SB16. */ - DSP_FlushData(); - if (sb.type == SBT_2) DSP_AddData(0x88); - else if ((sb.type == SBT_PRO1) || (sb.type == SBT_PRO2)) DSP_AddData(0x7b); - else DSP_AddData(0xff); //Everything enabled - } - break; - case 0x05: /* SB16 ASP set codec parameter */ - LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X (set codec parameter)",sb.dsp.cmd); - break; - case 0x08: /* SB16 ASP get version */ - LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X sub %X",sb.dsp.cmd,sb.dsp.in.data[0]); - if (sb.type == SBT_16) { - switch (sb.dsp.in.data[0]) { - case 0x03: - DSP_AddData(0x18); // version ID (??) - break; - default: - LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X sub %X",sb.dsp.cmd,sb.dsp.in.data[0]); - break; - } - } else { - LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X sub %X",sb.dsp.cmd,sb.dsp.in.data[0]); - } - break; - case 0x0e: /* SB16 ASP set register */ - if (sb.type == SBT_16) { -// LOG(LOG_SB,LOG_NORMAL)("SB16 ASP set register %X := %X",sb.dsp.in.data[0],sb.dsp.in.data[1]); - ASP_regs[sb.dsp.in.data[0]] = sb.dsp.in.data[1]; - } else { - LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X (set register)",sb.dsp.cmd); - } - break; - case 0x0f: /* SB16 ASP get register */ - if (sb.type == SBT_16) { - if ((ASP_init_in_progress) && (sb.dsp.in.data[0]==0x83)) { - ASP_regs[0x83] = ~ASP_regs[0x83]; - } -// LOG(LOG_SB,LOG_NORMAL)("SB16 ASP get register %X == %X",sb.dsp.in.data[0],ASP_regs[sb.dsp.in.data[0]]); - DSP_AddData(ASP_regs[sb.dsp.in.data[0]]); - } else { - LOG(LOG_SB,LOG_NORMAL)("DSP Unhandled SB16ASP command %X (get register)",sb.dsp.cmd); - } - break; - case 0x10: /* Direct DAC */ - DSP_ChangeMode(MODE_DAC); - if (sb.dac.usedRegister_Callback(DSP_ADC_CallBack); - break; - case 0x14: /* Singe Cycle 8-Bit DMA DAC */ - case 0x15: /* Wari hack. Waru uses this one instead of 0x14, but some weird stuff going on there anyway */ - case 0x91: /* Singe Cycle 8-Bit DMA High speed DAC */ - /* Note: 0x91 is documented only for DSP ver.2.x and 3.x, not 4.x */ - DSP_PrepareDMA_Old(DSP_DMA_8,false,false); - break; - case 0x90: /* Auto Init 8-bit DMA High Speed */ - case 0x1c: /* Auto Init 8-bit DMA */ - DSP_SB2_ABOVE; /* Note: 0x90 is documented only for DSP ver.2.x and 3.x, not 4.x */ - DSP_PrepareDMA_Old(DSP_DMA_8,true,false); - break; - case 0x38: /* Write to SB MIDI Output */ - if (sb.midi == true) MIDI_RawOutByte(sb.dsp.in.data[0]); - break; - case 0x40: /* Set Timeconstant */ - sb.freq=(1000000 / (256 - sb.dsp.in.data[0])); - /* Nasty kind of hack to allow runtime changing of frequency */ - if (sb.dma.mode != DSP_DMA_NONE && sb.dma.autoinit) { - DSP_PrepareDMA_Old(sb.dma.mode,sb.dma.autoinit,sb.dma.sign); - } - break; - case 0x41: /* Set Output Samplerate */ - case 0x42: /* Set Input Samplerate */ - DSP_SB16_ONLY; - sb.freq=(sb.dsp.in.data[0] << 8) | sb.dsp.in.data[1]; - break; - case 0x48: /* Set DMA Block Size */ - DSP_SB2_ABOVE; - //TODO Maybe check limit for new irq? - sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); - break; - case 0x75: /* 075h : Single Cycle 4-bit ADPCM Reference */ - sb.adpcm.haveref=true; - case 0x74: /* 074h : Single Cycle 4-bit ADPCM */ - DSP_PrepareDMA_Old(DSP_DMA_4,false,false); - break; - case 0x77: /* 077h : Single Cycle 3-bit(2.6bit) ADPCM Reference*/ - sb.adpcm.haveref=true; - case 0x76: /* 074h : Single Cycle 3-bit(2.6bit) ADPCM */ - DSP_PrepareDMA_Old(DSP_DMA_3,false,false); - break; - case 0x17: /* 017h : Single Cycle 2-bit ADPCM Reference*/ - sb.adpcm.haveref=true; - case 0x16: /* 074h : Single Cycle 2-bit ADPCM */ - DSP_PrepareDMA_Old(DSP_DMA_2,false,false); - break; - case 0x80: /* Silence DAC */ - PIC_AddEvent(&DSP_RaiseIRQEvent, - (1000.0f*(1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8))/sb.freq)); - 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: - DSP_SB16_ONLY; - /* Generic 8/16 bit DMA */ -// DSP_SetSpeaker(true); //SB16 always has speaker enabled - sb.dma.sign=(sb.dsp.in.data[0] & 0x10) > 0; - DSP_PrepareDMA_New((sb.dsp.cmd & 0x10) ? DSP_DMA_16 : DSP_DMA_8, - 1+sb.dsp.in.data[1]+(sb.dsp.in.data[2] << 8), - (sb.dsp.cmd & 0x4)>0, - (sb.dsp.in.data[0] & 0x20) > 0 - ); - break; - case 0xd5: /* Halt 16-bit DMA */ - DSP_SB16_ONLY; - case 0xd0: /* Halt 8-bit DMA */ -// DSP_ChangeMode(MODE_NONE); -// Games sometimes already program a new dma before stopping, gives noise - sb.mode=MODE_DMA_PAUSE; - PIC_RemoveEvents(END_DMA_Event); - break; - case 0xd1: /* Enable Speaker */ - DSP_SetSpeaker(true); - break; - case 0xd3: /* Disable Speaker */ - DSP_SetSpeaker(false); - break; - case 0xd8: /* Speaker status */ - DSP_SB2_ABOVE; - DSP_FlushData(); - if (sb.speaker) DSP_AddData(0xff); - else DSP_AddData(0x00); - break; - case 0xd6: /* Continue DMA 16-bit */ - DSP_SB16_ONLY; - case 0xd4: /* Continue DMA 8-bit*/ - if (sb.mode==MODE_DMA_PAUSE) { - sb.mode=MODE_DMA_MASKED; - sb.dma.chan->Register_Callback(DSP_DMA_CallBack); - } - break; - case 0xd9: /* Exit Autoinitialize 16-bit */ - DSP_SB16_ONLY; - case 0xda: /* Exit Autoinitialize 8-bit */ - DSP_SB2_ABOVE; - /* Set mode to single transfer so it ends with current block */ - sb.dma.autoinit=false; //Should stop itself - break; - case 0xe0: /* DSP Identification - SB2.0+ */ - DSP_FlushData(); - DSP_AddData(~sb.dsp.in.data[0]); - break; - case 0xe1: /* Get DSP Version */ - DSP_FlushData(); - switch (sb.type) { - case SBT_1: - DSP_AddData(0x1);DSP_AddData(0x1);break; - case SBT_2: - DSP_AddData(0x2);DSP_AddData(0x1);break; - case SBT_PRO1: - DSP_AddData(0x3);DSP_AddData(0x0);break; - case SBT_PRO2: - DSP_AddData(0x3);DSP_AddData(0x2);break; - case SBT_16: - DSP_AddData(0x4);DSP_AddData(0x5);break; - default: - break; - } - break; - case 0xe2: /* Weird DMA identification write routine */ - { - LOG(LOG_SB,LOG_NORMAL)("DSP Function 0xe2"); - for (Bitu i = 0; i < 8; i++) - if ((sb.dsp.in.data[0] >> i) & 0x01) sb.e2.value += E2_incr_table[sb.e2.count % 4][i]; - sb.e2.value += E2_incr_table[sb.e2.count % 4][8]; - sb.e2.count++; - GetDMAChannel(sb.hw.dma8)->Register_Callback(DSP_E2_DMA_CallBack); - } - break; - case 0xe3: /* DSP Copyright */ - { - DSP_FlushData(); - for (size_t i=0;i<=strlen(copyright_string);i++) { - DSP_AddData(copyright_string[i]); - } - } - break; - case 0xe4: /* Write Test Register */ - sb.dsp.test_register=sb.dsp.in.data[0]; - break; - case 0xe8: /* Read Test Register */ - DSP_FlushData(); - DSP_AddData(sb.dsp.test_register);; - break; - case 0xf2: /* Trigger 8bit IRQ */ - SB_RaiseIRQ(SB_IRQ_8); - break; - case 0xf8: /* Undocumented, pre-SB16 only */ - DSP_FlushData(); - DSP_AddData(0); - break; - case 0x30: case 0x31: - LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented MIDI I/O command %2X",sb.dsp.cmd); - break; - case 0x34: case 0x35: case 0x36: case 0x37: - DSP_SB2_ABOVE; - LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented MIDI UART command %2X",sb.dsp.cmd); - break; - case 0x7d: case 0x7f: case 0x1f: - DSP_SB2_ABOVE; - LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented auto-init DMA ADPCM command %2X",sb.dsp.cmd); - break; - case 0x20: - case 0x2c: - case 0x98: case 0x99: /* Documented only for DSP 2.x and 3.x */ - case 0xa0: case 0xa8: /* Documented only for DSP 3.x */ - LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented input command %2X",sb.dsp.cmd); - break; - case 0xf9: /* SB16 ASP ??? */ - if (sb.type == SBT_16) { - LOG(LOG_SB,LOG_NORMAL)("SB16 ASP unknown function %x",sb.dsp.in.data[0]); - // just feed it what it expects - switch (sb.dsp.in.data[0]) { - case 0x0b: - DSP_AddData(0x00); - break; - case 0x0e: - DSP_AddData(0xff); - break; - case 0x0f: - DSP_AddData(0x07); - break; - case 0x23: - DSP_AddData(0x00); - break; - case 0x24: - DSP_AddData(0x00); - break; - case 0x2b: - DSP_AddData(0x00); - break; - case 0x2c: - DSP_AddData(0x00); - break; - case 0x2d: - DSP_AddData(0x00); - break; - case 0x37: - DSP_AddData(0x38); - break; - default: - DSP_AddData(0x00); - break; - } - } else { - LOG(LOG_SB,LOG_NORMAL)("SB16 ASP unknown function %X",sb.dsp.cmd); - } - break; - default: - LOG(LOG_SB,LOG_ERROR)("DSP:Unhandled (undocumented) command %2X",sb.dsp.cmd); - break; - } - sb.dsp.cmd=DSP_NO_COMMAND; - sb.dsp.cmd_len=0; - sb.dsp.in.pos=0; -} - -static void DSP_DoWrite(Bit8u val) { - switch (sb.dsp.cmd) { - case DSP_NO_COMMAND: - sb.dsp.cmd=val; - if (sb.type == SBT_16) sb.dsp.cmd_len=DSP_cmd_len_sb16[val]; - else sb.dsp.cmd_len=DSP_cmd_len_sb[val]; - sb.dsp.in.pos=0; - if (!sb.dsp.cmd_len) DSP_DoCommand(); - break; - default: - sb.dsp.in.data[sb.dsp.in.pos]=val; - sb.dsp.in.pos++; - if (sb.dsp.in.pos>=sb.dsp.cmd_len) DSP_DoCommand(); - } -} - -static Bit8u DSP_ReadData(void) { -/* Static so it repeats the last value on succesive reads (JANGLE DEMO) */ - static Bit8u data = 0; - if (sb.dsp.out.used) { - data=sb.dsp.out.data[sb.dsp.out.pos]; - sb.dsp.out.pos++; - if (sb.dsp.out.pos>=DSP_BUFSIZE) sb.dsp.out.pos-=DSP_BUFSIZE; - sb.dsp.out.used--; - } - return data; -} - -//The soundblaster manual says 2.0 Db steps but we'll go for a bit less -#define CALCVOL(_VAL) (float)pow(10.0f,((float)(31-_VAL)*-1.3f)/20) -static void CTMIXER_UpdateVolumes(void) { - if (!sb.mixer.enabled) return; - MixerChannel * chan; - //adjust to get linear master volume slider in trackers - chan=MIXER_FindChannel("SB"); - if (chan) chan->SetVolume(float(sb.mixer.master[0])/31.0f*CALCVOL(sb.mixer.dac[0]), - float(sb.mixer.master[1])/31.0f*CALCVOL(sb.mixer.dac[1])); - chan=MIXER_FindChannel("FM"); - if (chan) chan->SetVolume(float(sb.mixer.master[0])/31.0f*CALCVOL(sb.mixer.fm[0]), - float(sb.mixer.master[1])/31.0f*CALCVOL(sb.mixer.fm[1])); -} - -static void CTMIXER_Reset(void) { - sb.mixer.fm[0]= - sb.mixer.fm[1]= - sb.mixer.dac[0]= - sb.mixer.dac[1]=31; - sb.mixer.master[0]= - sb.mixer.master[1]=31; - CTMIXER_UpdateVolumes(); -} - -#define SETPROVOL(_WHICH_,_VAL_) \ - _WHICH_[0]= ((((_VAL_) & 0xf0) >> 3)|(sb.type==SBT_16 ? 1:3)); \ - _WHICH_[1]= ((((_VAL_) & 0x0f) << 1)|(sb.type==SBT_16 ? 1:3)); \ - -#define MAKEPROVOL(_WHICH_) \ - ((((_WHICH_[0] & 0x1e) << 3) | ((_WHICH_[1] & 0x1e) >> 1)) & (sb.type==SBT_16 ? 0xff:0xee)) - -static void DSP_ChangeStereo(bool stereo) { - if (!sb.dma.stereo && stereo) { - sb.chan->SetFreq(sb.freq/2); - sb.dma.mul*=2; - sb.dma.rate=(sb.freq*sb.dma.mul) >> SB_SH; - sb.dma.min=(sb.dma.rate*3)/1000; - } else if (sb.dma.stereo && !stereo) { - sb.chan->SetFreq(sb.freq); - sb.dma.mul/=2; - sb.dma.rate=(sb.freq*sb.dma.mul) >> SB_SH; - sb.dma.min=(sb.dma.rate*3)/1000; - } - sb.dma.stereo=stereo; -} - -static void CTMIXER_Write(Bit8u val) { - switch (sb.mixer.index) { - case 0x00: /* Reset */ - CTMIXER_Reset(); - LOG(LOG_SB,LOG_WARN)("Mixer reset value %x",val); - break; - case 0x02: /* Master Volume (SB2 Only) */ - SETPROVOL(sb.mixer.master,(val&0xf)|(val<<4)); - CTMIXER_UpdateVolumes(); - break; - case 0x04: /* DAC Volume (SBPRO) */ - SETPROVOL(sb.mixer.dac,val); - CTMIXER_UpdateVolumes(); - break; - case 0x06: /* FM output selection, Somewhat obsolete with dual OPL SBpro + FM volume (SB2 Only) */ - //volume controls both channels - SETPROVOL(sb.mixer.fm,(val&0xf)|(val<<4)); - CTMIXER_UpdateVolumes(); - if(val&0x60) LOG(LOG_SB,LOG_WARN)("Turned FM one channel off. not implemented %X",val); - //TODO Change FM Mode if only 1 fm channel is selected - break; - case 0x08: /* CDA Volume (SB2 Only) */ - SETPROVOL(sb.mixer.cda,(val&0xf)|(val<<4)); - break; - case 0x0a: /* Mic Level (SBPRO) or DAC Volume (SB2): 2-bit, 3-bit on SB16 */ - if (sb.type==SBT_2) sb.mixer.dac[0]=sb.mixer.dac[1]=((val & 0x6) << 2)|3; - else sb.mixer.mic=((val & 0x7) << 2)|(sb.type==SBT_16?1:3); - break; - case 0x0e: /* Output/Stereo Select */ - sb.mixer.stereo=(val & 0x2) > 0; - sb.mixer.filtered=(val & 0x20) > 0; - DSP_ChangeStereo(sb.mixer.stereo); - LOG(LOG_SB,LOG_WARN)("Mixer set to %s",sb.dma.stereo ? "STEREO" : "MONO"); - break; - case 0x22: /* Master Volume (SBPRO) */ - SETPROVOL(sb.mixer.master,val); - CTMIXER_UpdateVolumes(); - break; - case 0x26: /* FM Volume (SBPRO) */ - SETPROVOL(sb.mixer.fm,val); - CTMIXER_UpdateVolumes(); - break; - case 0x28: /* CD Audio Volume (SBPRO) */ - SETPROVOL(sb.mixer.cda,val); - break; - case 0x2e: /* Line-in Volume (SBPRO) */ - SETPROVOL(sb.mixer.lin,val); - break; - //case 0x20: /* Master Volume Left (SBPRO) ? */ - case 0x30: /* Master Volume Left (SB16) */ - if (sb.type==SBT_16) { - sb.mixer.master[0]=val>>3; - CTMIXER_UpdateVolumes(); - } - break; - //case 0x21: /* Master Volume Right (SBPRO) ? */ - case 0x31: /* Master Volume Right (SB16) */ - if (sb.type==SBT_16) { - sb.mixer.master[1]=val>>3; - CTMIXER_UpdateVolumes(); - } - break; - case 0x32: /* DAC Volume Left (SB16) */ - if (sb.type==SBT_16) { - sb.mixer.dac[0]=val>>3; - CTMIXER_UpdateVolumes(); - } - break; - case 0x33: /* DAC Volume Right (SB16) */ - if (sb.type==SBT_16) { - sb.mixer.dac[1]=val>>3; - CTMIXER_UpdateVolumes(); - } - break; - case 0x34: /* FM Volume Left (SB16) */ - if (sb.type==SBT_16) { - sb.mixer.fm[0]=val>>3; - CTMIXER_UpdateVolumes(); - } - break; - case 0x35: /* FM Volume Right (SB16) */ - if (sb.type==SBT_16) { - sb.mixer.fm[1]=val>>3; - CTMIXER_UpdateVolumes(); - } - break; - case 0x36: /* CD Volume Left (SB16) */ - if (sb.type==SBT_16) sb.mixer.cda[0]=val>>3; - break; - case 0x37: /* CD Volume Right (SB16) */ - if (sb.type==SBT_16) sb.mixer.cda[1]=val>>3; - break; - case 0x38: /* Line-in Volume Left (SB16) */ - if (sb.type==SBT_16) sb.mixer.lin[0]=val>>3; - break; - case 0x39: /* Line-in Volume Right (SB16) */ - if (sb.type==SBT_16) sb.mixer.lin[1]=val>>3; - break; - case 0x3a: - if (sb.type==SBT_16) sb.mixer.mic=val>>3; - break; - case 0x80: /* IRQ Select */ - sb.hw.irq=0xff; - if (val & 0x1) sb.hw.irq=2; - else if (val & 0x2) sb.hw.irq=5; - else if (val & 0x4) sb.hw.irq=7; - else if (val & 0x8) sb.hw.irq=10; - break; - case 0x81: /* DMA Select */ - sb.hw.dma8=0xff; - sb.hw.dma16=0xff; - if (val & 0x1) sb.hw.dma8=0; - else if (val & 0x2) sb.hw.dma8=1; - else if (val & 0x8) sb.hw.dma8=3; - if (val & 0x20) sb.hw.dma16=5; - else if (val & 0x40) sb.hw.dma16=6; - else if (val & 0x80) sb.hw.dma16=7; - LOG(LOG_SB,LOG_NORMAL)("Mixer select dma8:%x dma16:%x",sb.hw.dma8,sb.hw.dma16); - break; - default: - - if( ((sb.type == SBT_PRO1 || sb.type == SBT_PRO2) && sb.mixer.index==0x0c) || /* Input control on SBPro */ - (sb.type == SBT_16 && sb.mixer.index >= 0x3b && sb.mixer.index <= 0x47)) /* New SB16 registers */ - sb.mixer.unhandled[sb.mixer.index] = val; - LOG(LOG_SB,LOG_WARN)("MIXER:Write %X to unhandled index %X",val,sb.mixer.index); - } -} - -static Bit8u CTMIXER_Read(void) { - Bit8u ret; -// if ( sb.mixer.index< 0x80) LOG_MSG("Read mixer %x",sb.mixer.index); - switch (sb.mixer.index) { - case 0x00: /* RESET */ - return 0x00; - case 0x02: /* Master Volume (SB2 Only) */ - return ((sb.mixer.master[1]>>1) & 0xe); - case 0x22: /* Master Volume (SBPRO) */ - return MAKEPROVOL(sb.mixer.master); - case 0x04: /* DAC Volume (SBPRO) */ - return MAKEPROVOL(sb.mixer.dac); - case 0x06: /* FM Volume (SB2 Only) + FM output selection */ - return ((sb.mixer.fm[1]>>1) & 0xe); - case 0x08: /* CD Volume (SB2 Only) */ - return ((sb.mixer.cda[1]>>1) & 0xe); - case 0x0a: /* Mic Level (SBPRO) or Voice (SB2 Only) */ - if (sb.type==SBT_2) return (sb.mixer.dac[0]>>2); - else return ((sb.mixer.mic >> 2) & (sb.type==SBT_16 ? 7:6)); - case 0x0e: /* Output/Stereo Select */ - return 0x11|(sb.mixer.stereo ? 0x02 : 0x00)|(sb.mixer.filtered ? 0x20 : 0x00); - case 0x26: /* FM Volume (SBPRO) */ - return MAKEPROVOL(sb.mixer.fm); - case 0x28: /* CD Audio Volume (SBPRO) */ - return MAKEPROVOL(sb.mixer.cda); - case 0x2e: /* Line-IN Volume (SBPRO) */ - return MAKEPROVOL(sb.mixer.lin); - case 0x30: /* Master Volume Left (SB16) */ - if (sb.type==SBT_16) return sb.mixer.master[0]<<3; - ret=0xa; - break; - case 0x31: /* Master Volume Right (S16) */ - if (sb.type==SBT_16) return sb.mixer.master[1]<<3; - ret=0xa; - break; - case 0x32: /* DAC Volume Left (SB16) */ - if (sb.type==SBT_16) return sb.mixer.dac[0]<<3; - ret=0xa; - break; - case 0x33: /* DAC Volume Right (SB16) */ - if (sb.type==SBT_16) return sb.mixer.dac[1]<<3; - ret=0xa; - break; - case 0x34: /* FM Volume Left (SB16) */ - if (sb.type==SBT_16) return sb.mixer.fm[0]<<3; - ret=0xa; - break; - case 0x35: /* FM Volume Right (SB16) */ - if (sb.type==SBT_16) return sb.mixer.fm[1]<<3; - ret=0xa; - break; - case 0x36: /* CD Volume Left (SB16) */ - if (sb.type==SBT_16) return sb.mixer.cda[0]<<3; - ret=0xa; - break; - case 0x37: /* CD Volume Right (SB16) */ - if (sb.type==SBT_16) return sb.mixer.cda[1]<<3; - ret=0xa; - break; - case 0x38: /* Line-in Volume Left (SB16) */ - if (sb.type==SBT_16) return sb.mixer.lin[0]<<3; - ret=0xa; - break; - case 0x39: /* Line-in Volume Right (SB16) */ - if (sb.type==SBT_16) return sb.mixer.lin[1]<<3; - ret=0xa; - break; - case 0x3a: /* Mic Volume (SB16) */ - if (sb.type==SBT_16) return sb.mixer.mic<<3; - ret=0xa; - break; - case 0x80: /* IRQ Select */ - switch (sb.hw.irq) { - case 2: return 0x1; - case 5: return 0x2; - case 7: return 0x4; - case 10: return 0x8; - } - case 0x81: /* DMA Select */ - ret=0; - switch (sb.hw.dma8) { - case 0:ret|=0x1;break; - case 1:ret|=0x2;break; - case 3:ret|=0x8;break; - } - switch (sb.hw.dma16) { - case 5:ret|=0x20;break; - case 6:ret|=0x40;break; - case 7:ret|=0x80;break; - } - return ret; - case 0x82: /* IRQ Status */ - return (sb.irq.pending_8bit ? 0x1 : 0) | - (sb.irq.pending_16bit ? 0x2 : 0); - default: - if ( ((sb.type == SBT_PRO1 || sb.type == SBT_PRO2) && sb.mixer.index==0x0c) || /* Input control on SBPro */ - (sb.type == SBT_16 && sb.mixer.index >= 0x3b && sb.mixer.index <= 0x47)) /* New SB16 registers */ - ret = sb.mixer.unhandled[sb.mixer.index]; - else - ret=0xa; - LOG(LOG_SB,LOG_WARN)("MIXER:Read from unhandled index %X",sb.mixer.index); - } - return ret; -} - - -static Bitu read_sb(Bitu port,Bitu iolen) { - switch (port-sb.hw.base) { - case MIXER_INDEX: - return sb.mixer.index; - case MIXER_DATA: - return CTMIXER_Read(); - case DSP_READ_DATA: - return DSP_ReadData(); - case DSP_READ_STATUS: - //TODO See for high speed dma :) - sb.irq.pending_8bit=false; - if (sb.dsp.out.used) return 0xff; - else return 0x7f; - case DSP_ACK_16BIT: - sb.irq.pending_16bit=false; - break; - case DSP_WRITE_STATUS: - switch (sb.dsp.state) { - case DSP_S_NORMAL: - sb.dsp.write_busy++; - if (sb.dsp.write_busy & 8) return 0xff; - return 0x7f; - case DSP_S_RESET: - return 0xff; - } - return 0xff; - case DSP_RESET: - return 0xff; - default: - LOG(LOG_SB,LOG_NORMAL)("Unhandled read from SB Port %4X",port); - break; - } - return 0xff; -} - -static void write_sb(Bitu port,Bitu val,Bitu iolen) { - switch (port-sb.hw.base) { - case DSP_RESET: - DSP_DoReset(val); - break; - case DSP_WRITE_DATA: - DSP_DoWrite(val); - break; - case MIXER_INDEX: - sb.mixer.index=val; - break; - case MIXER_DATA: - CTMIXER_Write(val); - break; - default: - LOG(LOG_SB,LOG_NORMAL)("Unhandled write to SB Port %4X",port); - break; - } -} - -static void adlib_gusforward(Bitu port,Bitu val,Bitu iolen) { - adlib_commandreg=val; -} - -static void SBLASTER_CallBack(Bitu len) { - switch (sb.mode) { - case MODE_NONE: - case MODE_DMA_PAUSE: - case MODE_DMA_MASKED: - sb.chan->AddSilence(); - break; - case MODE_DAC: -// GenerateDACSound(len); -// break; - if (!sb.dac.used) { - sb.mode=MODE_NONE; - return; - } - sb.chan->AddStretched(sb.dac.used,sb.dac.data); - sb.dac.used=0; - break; - case MODE_DMA: - len*=sb.dma.mul; - if (len&SB_SH_MASK) len+=1 << SB_SH; - len>>=SB_SH; - if (len>sb.dma.left) len=sb.dma.left; - GenerateDMASound(len); - break; - } -} -class SBLASTER: public Module_base { -private: - /* Data */ - IO_ReadHandleObject ReadHandler[0x10]; - IO_WriteHandleObject WriteHandler[0x10]; - AutoexecObject autoexecline; - MixerObject MixerChan; - - /* Support Functions */ - void Find_Type_And_Opl(Section_prop* config,SB_TYPES& type, OPL_Mode& opl_mode){ - const char * sbtype=config->Get_string("sbtype"); - if (!strcasecmp(sbtype,"sb1")) type=SBT_1; - else if (!strcasecmp(sbtype,"sb2")) type=SBT_2; - else if (!strcasecmp(sbtype,"sbpro1")) type=SBT_PRO1; - else if (!strcasecmp(sbtype,"sbpro2")) type=SBT_PRO2; - else if (!strcasecmp(sbtype,"sb16")) type=SBT_16; - else if (!strcasecmp(sbtype,"none")) type=SBT_NONE; - else type=SBT_16; - - if (type==SBT_16) { - if ((!IS_EGAVGA_ARCH) || !SecondDMAControllerAvailable()) type=SBT_PRO2; - } - - /* OPL/CMS Init */ - const char * omode=config->Get_string("oplmode"); - if (!strcasecmp(omode,"none")) opl_mode=OPL_none; - else if (!strcasecmp(omode,"cms")) opl_mode=OPL_cms; - else if (!strcasecmp(omode,"opl2")) opl_mode=OPL_opl2; - else if (!strcasecmp(omode,"dualopl2")) opl_mode=OPL_dualopl2; - else if (!strcasecmp(omode,"opl3")) opl_mode=OPL_opl3; - /* Else assume auto */ - else { - switch (type) { - case SBT_NONE:opl_mode=OPL_none;break; - case SBT_1:opl_mode=OPL_opl2;break; - case SBT_2:opl_mode=OPL_opl2;break; - case SBT_PRO1:opl_mode=OPL_dualopl2;break; - case SBT_PRO2: - case SBT_16: - opl_mode=OPL_opl3;break; - } - } - } -public: - SBLASTER(Section* configuration):Module_base(configuration) { - Bitu i; - Section_prop * section=static_cast(configuration); - sb.hw.base=section->Get_hex("sbbase"); - sb.hw.irq=section->Get_int("irq"); - sb.hw.dma8=section->Get_int("dma"); - sb.hw.dma16=section->Get_int("hdma"); - sb.mixer.enabled=section->Get_bool("sbmixer"); - sb.mixer.stereo=false; - OPL_Mode opl_mode = OPL_none; - Find_Type_And_Opl(section,sb.type,opl_mode); - - switch (opl_mode) { - case OPL_none: - WriteHandler[0].Install(0x388,adlib_gusforward,IO_MB); - break; - case OPL_cms: - WriteHandler[0].Install(0x388,adlib_gusforward,IO_MB); - CMS_Init(section); - break; - case OPL_opl2: - CMS_Init(section); - case OPL_dualopl2: - case OPL_opl3: - OPL_Init(section,opl_mode); - break; - } - if (sb.type==SBT_NONE) return; - sb.chan=MixerChan.Install(&SBLASTER_CallBack,22050,"SB"); - sb.dsp.state=DSP_S_NORMAL; - sb.dma.chan=NULL; - - for (i=4;i<=0xf;i++) { - if (i==8 || i==9) continue; - //Disable mixer ports for lower soundblaster - if ((sb.type==SBT_1 || sb.type==SBT_2) && (i==4 || i==5)) continue; - ReadHandler[i].Install(sb.hw.base+i,read_sb,IO_MB); - WriteHandler[i].Install(sb.hw.base+i,write_sb,IO_MB); - } - for (i=0;i<256;i++) ASP_regs[i] = 0; - ASP_regs[5] = 0x01; - ASP_regs[9] = 0xf8; - DSP_Reset(); - CTMIXER_Reset(); - // The documentation does not specify if SB gets initialized with the speaker enabled - // or disabled. Real SBPro2 has it disabled. - sb.speaker=false; - // On SB16 the speaker flag does not affect actual speaker state. - if (sb.type == SBT_16) sb.chan->Enable(true); - else sb.chan->Enable(false); - - // Create set blaster line - ostringstream temp; - temp << "SET BLASTER=A" << setw(3)<< hex << sb.hw.base - << " I" << dec << sb.hw.irq << " D"<< sb.hw.dma8; - if (sb.type==SBT_16) temp << " H" << sb.hw.dma16; - temp << " T" << static_cast(sb.type) << ends; - - autoexecline.Install(temp.str()); - - /* Soundblaster midi interface */ - if (!MIDI_Available()) sb.midi = false; - else sb.midi = true; - } - - ~SBLASTER() { - Section_prop * section=static_cast(m_configuration); - OPL_Mode opl_mode = OPL_none; - Find_Type_And_Opl(section,sb.type,opl_mode); - - switch (opl_mode) { - case OPL_none: - - break; - case OPL_cms: - - CMS_ShutDown(m_configuration); - break; - case OPL_opl2: - CMS_ShutDown(m_configuration); - case OPL_dualopl2: - case OPL_opl3: - OPL_ShutDown(m_configuration); - break; - } - - if (sb.type==SBT_NONE) return; - DSP_Reset();//Stop everything - } -}; //End of SBLASTER class - - -static SBLASTER* test; -void SBLASTER_ShutDown(Section* sec) { - delete test; -} - -void SBLASTER_Init(Section* sec) { - test = new SBLASTER(sec); - sec->AddDestroyFunction(&SBLASTER_ShutDown,true); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "dosbox.h" +#include "inout.h" +#include "mixer.h" +#include "dma.h" +#include "pic.h" +#include "hardware.h" + +#define SB_BASE 0x220 +#define SB_IRQ 5 +#define SB_DMA 1 + +#define DSP_RESET 0x06 +#define DSP_READ_DATA 0x0A +#define DSP_WRITE_DATA 0x0C +#define DSP_WRITE_STATUS 0x0C +#define DSP_READ_STATUS 0x0E + +#define DSP_NO_COMMAND 0 + +#define DSP_MAJOR 2 +#define DSP_MINOR 0 + +#define DSP_BUFSIZE 64 +#define DSP_DACSIZE 4096 + +enum {DSP_S_RESET,DSP_S_NORMAL,DSP_S_HIGHSPEED}; +enum { + MODE_NONE,MODE_DAC, + MODE_PCM_8S,MODE_PCM_8A, + MODE_ADPCM_4S +}; + +#ifdef DEBUG_SBLASTER +#define SB_DEBUG LOG_DEBUG +#else +#define SB_DEBUG +#endif + + +struct SB_INFO { + Bit16u freq; + Bitu samples_total; + Bitu samples_left; + bool speaker; + Bit8u time_constant; + bool use_time_constant; + + Bit8u output_mode; + /* DSP Stuff */ + Bit8u mode; + Bit8u state; + Bit8u cmd; + Bit8u cmd_len; + Bit8u cmd_in_pos; + Bit8u cmd_in[DSP_BUFSIZE]; + Bit8u data_out[DSP_BUFSIZE]; + Bit8u data_out_pos; + Bit8u data_out_used; + Bit8u dac_data[DSP_DACSIZE]; + Bit32u dac_used; + Bit8u test_register; +/*ADPCM Part */ + Bits adpcm_reference; + Bits adpcm_scale; + Bits adpcm_remain; +/* Hardware setup part */ + Bit32u base; + Bit8u irq; + Bit8u dma; + bool enabled; + HWBlock hwblock; + MIXER_Channel * chan; +}; + +static SB_INFO sb; +static Bit8u e2_value; +static Bit8u e2_count; + +static char * copyright_string="COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; + +static Bit8u DSP_cmd_len[256] = { + 0,0,0,0, 0,2,0,0, 0,0,0,0, 0,0,0,0, // 0x00 + 1,0,0,0, 2,0,2,2, 0,0,0,0, 0,0,0,0, // 0x10 + 0,0,0,0, 2,0,0,0, 0,0,0,0, 0,0,0,0, // 0x20 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x30 + + 1,2,2,0, 0,0,0,0, 2,0,0,0, 0,0,0,0, // 0x40 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x50 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x60 + 0,0,0,0, 2,2,2,2, 0,0,0,0, 0,0,0,0, // 0x70 + + 2,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x80 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x90 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xa0 + 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xb0 + + 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xc0 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0xd0 + 1,0,1,0, 1,0,0,0, 0,0,0,0, 0,0,0,0, // 0xe0 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 // 0xf0 +}; + +static int E2_incr_table[4][9] = { + { 0x01, -0x02, -0x04, 0x08, -0x10, 0x20, 0x40, -0x80, -106 }, + { -0x01, 0x02, -0x04, 0x08, 0x10, -0x20, 0x40, -0x80, 165 }, + { -0x01, 0x02, 0x04, -0x08, 0x10, -0x20, -0x40, 0x80, -151 }, + { 0x01, -0x02, 0x04, -0x08, -0x10, 0x20, -0x40, 0x80, 90 } +}; + +#ifndef max +#define max(a,b) ((a)>(b)?(a):(b)) +#endif +#ifndef min +#define min(a,b) ((a)<(b)?(a):(b)) +#endif + +static void DSP_SetSpeaker(bool how) { +/* This should just set the mixer value */ + MIXER_Enable(sb.chan,how); + sb.speaker=how; +} + +static void DSP_HaltDMA(void) { + +} + +static INLINE void DSP_FlushData(void) { + sb.data_out_used=0; + sb.data_out_pos=0; +} + +static void DSP_SetSampleRate(Bit32u rate) { +/* This directly changes the mixer */ + + +} +static void DSP_StopDMA(void) { + sb.mode=MODE_NONE; +// MIXER_SetMode(sb.chan,MIXER_8MONO); +// MIXER_SetFreq(sb.chan,22050); +} + +static void DSP_StartDMATranfser(Bit8u mode) { + sb.samples_left=sb.samples_total; + if (sb.use_time_constant) { + sb.freq=(1000000 / (256 - sb.time_constant)); + }; + switch (mode) { + case MODE_PCM_8S: + MIXER_SetFreq(sb.chan,sb.freq); + SB_DEBUG("DSP:PCM 8 bit single cycle rate %d size %d",sb.freq,sb.samples_total); + break; + case MODE_PCM_8A: + MIXER_SetFreq(sb.chan,sb.freq); + SB_DEBUG("DSP:PCM 8 bit auto init rate %d size %d",sb.freq,sb.samples_total); + + break; + case MODE_ADPCM_4S: + MIXER_SetFreq(sb.chan,sb.freq*2); + SB_DEBUG("DSP:ADPCM 4 bit single cycle rate %d size %X",sb.freq,sb.samples_total); + break; + + default: + LOG_ERROR("DSP:Illegal transfer mode %d",mode); + return; + } + /* Hack to enable dma transfer when game has speaker disabled */ + DSP_SetSpeaker(true); + sb.mode=mode; +} + +static void DSP_AddData(Bit8u val) { + if (sb.data_out_used=DSP_BUFSIZE) start-=DSP_BUFSIZE; + sb.data_out[start]=val; + sb.data_out_used++; + } else { + LOG_ERROR("SB:DSP:Data Output buffer full this is weird"); + } +} + +static void DSP_Reset(void) { + sb.mode=MODE_NONE; + sb.cmd_len=0; + sb.cmd_in_pos=0; + sb.use_time_constant=false; + sb.dac_used=0; + e2_value=0xaa; + e2_count=0; + DSP_HaltDMA(); + MIXER_SetFreq(sb.chan,22050); + MIXER_SetMode(sb.chan,MIXER_8MONO); + DSP_SetSpeaker(false); +} +static void DSP_DoReset(Bit8u val) { + if (val&1!=0) { +//TODO Get out of highspeed mode + DSP_Reset(); + sb.state=DSP_S_RESET; + } else { + DSP_FlushData(); + DSP_AddData(0xaa); + sb.state=DSP_S_NORMAL; + } +}; + +static bool dac_warn=false; +static void DSP_DoCommand(void) { + switch (sb.cmd) { + case 0x10: /* Direct DAC */ + sb.mode=MODE_DAC; + if (sb.dac_used> i) & 0x01) m_E2Value += E2_incr_table[m_E2Count % 4][i]; + + m_E2Value += E2_incr_table[m_E2Count % 4][8]; + m_E2Count++; +*/ +//TODO Ofcourse :) + } + + break; + case 0xe3: /* DSP Copyright */ + { + DSP_FlushData(); + for (Bit32u i=0;i<=strlen(copyright_string);i++) { + DSP_AddData(copyright_string[i]); + } + } + break; + case 0xe4: /* Write Test Register */ + sb.test_register=sb.cmd_in[0]; + break; + case 0xe8: /* Read Test Register */ + DSP_FlushData(); + DSP_AddData(sb.test_register);; + break; + + case 0xf2: /* Trigger 8bit IRQ */ + DSP_FlushData(); + DSP_AddData(0xaa); + PIC_ActivateIRQ(sb.irq); + break; + default: + LOG_WARN("SB:DSP:Unhandled command %2X",sb.cmd); + } + sb.cmd=DSP_NO_COMMAND; + sb.cmd_len=0; + sb.cmd_in_pos=0; +} + + + +static void DSP_DoWrite(Bit8u val) { + switch (sb.cmd) { + case DSP_NO_COMMAND: + sb.cmd=val; + sb.cmd_len=DSP_cmd_len[val]; + sb.cmd_in_pos=0; + if (!sb.cmd_len) DSP_DoCommand(); + break; + default: + sb.cmd_in[sb.cmd_in_pos]=val; + sb.cmd_in_pos++; + if (sb.cmd_in_pos>=sb.cmd_len) DSP_DoCommand(); + } +} + +static Bit8u DSP_ReadData(void) { + Bit8u data=0; + if (sb.data_out_used) { + data=sb.data_out[sb.data_out_pos]; + sb.data_out_pos++; + if (sb.data_out_pos>=DSP_BUFSIZE) sb.data_out_pos-=DSP_BUFSIZE; + sb.data_out_used--; + } + return data; +} + +static Bit8u read_sb(Bit32u port) { + switch (port-sb.base) { + case DSP_READ_DATA: + return DSP_ReadData(); + case DSP_READ_STATUS: + //TODO Acknowledge 8bit irq + //TODO See for high speed dma :) + if (sb.data_out_used) return 0xff; + else return 0x7f; + case DSP_WRITE_STATUS: + switch (sb.state) { + case DSP_S_NORMAL: + return 0x7f; + case DSP_S_RESET: + return 0xff; + } + return 0xff; +/* For now loop FM Stuff to 0x388 */ + case 0x00: case 0x02: case 0x08: + return IO_Read(0x388); + case DSP_RESET: + return 0xff; + default: + LOG_WARN("SB:Unhandled read from SB Port %4X",port); + break; + } + return 0xff; +} + +static void write_sb(Bit32u port,Bit8u val) { + switch (port-sb.base) { + case DSP_RESET: + DSP_DoReset(val); + break; + case DSP_WRITE_DATA: + DSP_DoWrite(val); + break; +/* For now loop FM Stuff to 0x388 */ + case 0x00: case 0x02: case 0x08: + IO_Write(0x388,val); + break; + case 0x01: case 0x03: case 0x09: + IO_Write(0x389,val); + break; + + default: + LOG_WARN("SB:Unhandled write to SB Port %4X",port); + break; + } +} + + +INLINE Bit8u decode_ADPCM_4_sample( + Bit8u sample, + Bits& reference, + Bits& scale) +{ + static int scaleMap[8] = { -2, -1, 0, 0, 1, 1, 1, 1 }; + + if (sample & 0x08) { + reference = max(0x00, reference - ((sample & 0x07) << scale)); + } else { + reference = min(0xff, reference + ((sample & 0x07) << scale)); + } + + scale = max(2, min(6, scaleMap[sample & 0x07])); + + return (Bit8u)reference; +} + +static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) { + unsigned char tmpbuf[65536]; + if (!len) return; + switch (sb.mode) { + case MODE_NONE: + /* If there isn't a mode it's 8 bit mono mode speaker should be disabled normally */ + memset(stream,0x80,len); + break; + case MODE_DAC: + /* Stretch the inputted dac data over len samples */ + { + Bit32u dac_add=(sb.dac_used<<16)/len; + Bit32u dac_pos=0; + while (len-->0) { + *(stream++)=sb.dac_data[dac_pos>>16]; + dac_pos+=dac_add; + } + } + sb.dac_used=0; + sb.mode=MODE_NONE; + break; + case MODE_PCM_8A: + DMA_8_Read(sb.dma,stream,(Bit16u)len); + if (sb.samples_left>len) { + sb.samples_left-=len; + } else { + if (len>(sb.samples_total+sb.samples_left)) sb.samples_left=sb.samples_total; + else sb.samples_left=sb.samples_total+sb.samples_left-len; + PIC_ActivateIRQ(sb.irq); + } + break; + case MODE_PCM_8S: + if (sb.samples_left>=len) { + DMA_8_Read(sb.dma,stream,(Bit16u)len); + sb.samples_left-=len; + } else if (sb.samples_left && (sb.samples_left=0) { + *stream++=decode_ADPCM_4_sample((Bit8u)sb.adpcm_remain,sb.adpcm_reference,sb.adpcm_scale); + len--; + } + Bitu dma_size=len/2+(len&1); //Amount of bytes that need to be transferred + Bit8u * decode_pos=tmpbuf; + if (sb.adpcm_reference < 0) { + dma_size++; + } + /* Read from the DMA Channel */ + if (sb.samples_left>=dma_size) { + DMA_8_Read(sb.dma,decode_pos,(Bit16u)dma_size); + sb.samples_left-=dma_size; + } else if (sb.samples_left0;i--) { + *stream++=decode_ADPCM_4_sample(*decode_pos >> 4,sb.adpcm_reference,sb.adpcm_scale); + *stream++=decode_ADPCM_4_sample(*decode_pos++ ,sb.adpcm_reference,sb.adpcm_scale); + } + if (len & 1) { + *stream++=decode_ADPCM_4_sample(*decode_pos >> 4,sb.adpcm_reference,sb.adpcm_scale); + sb.adpcm_remain=*decode_pos & 0xf; + } else { + sb.adpcm_remain=-1; + } + } + } +} + + + +static bool SB_enabled; + +static void SB_Enable(bool enable) { + Bitu i; + if (enable) { + sb.enabled=true; + for (i=sb.base+4;i - -/* This is a serial passthrough class. Its amazingly simple to */ -/* write now that the serial ports themselves were abstracted out */ - -CDirectSerial::CDirectSerial (Bitu id, CommandLine *cmd) - : CSerial(id, cmd) { - InstallationSuccessful = false; - - - rx_retry = 0; - rx_retry_max = 0; - - std::string tmpstring; - - if (!cmd->FindStringBegin("realport:", tmpstring, false)) - { - return; - } -#if SERIAL_DEBUG - if (dbg_modemcontrol) - { - fprintf(debugfp, "%12.3f Port type directserial realport %s\r\n", PIC_FullIndex(), tmpstring.c_str()); - } -#endif - - - // rxdelay: How many milliseconds to wait before causing an - // overflow when the application is unresponsive. - if(getBituSubstring("rxdelay:", &rx_retry_max, cmd)) { - if(!(rx_retry_max<=10000)) { - rx_retry_max=0; - } - } - - const char* tmpchar=tmpstring.c_str(); - - LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpstring.c_str()); - - ULONG ulAction = 0; - APIRET rc = DosOpen((unsigned char*)tmpstring.c_str(), &hCom, &ulAction, 0L, FILE_NORMAL, FILE_OPEN, - OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | OPEN_FLAGS_SEQUENTIAL, 0L); - if (rc != NO_ERROR) - { - LOG_MSG ("Serial%d: Serial port \"%s\" could not be opened.", COMNUMBER, tmpstring.c_str()); - if (rc == 2) { - LOG_MSG ("The specified port does not exist."); - } else if (rc == 99) { - LOG_MSG ("The specified port is already in use."); - } else { - LOG_MSG ("OS/2 error %d occurred.", rc); - } - - hCom = 0; - return; - } - - DCBINFO dcb; - ULONG ulParmLen = sizeof(DCBINFO); - rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO, 0, 0, 0, &dcb, ulParmLen, &ulParmLen); - if ( rc != NO_ERROR) - { - LOG_MSG("GetCommState failed with error %d.\n", rc); - DosClose(hCom); - hCom = 0; - return; - } - - dcb.usWriteTimeout = 0; - dcb.usReadTimeout = 0; //65535; - dcb.fbCtlHndShake = dcb.fbFlowReplace = 0; - dcb.fbTimeout = 6; - rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcb, ulParmLen, &ulParmLen, 0, 0, 0); - if ( rc != NO_ERROR) - { - LOG_MSG("SetDCBInfo failed with error %d.\n", rc); - DosClose(hCom); - hCom = 0; - return; - } - - - struct { - ULONG baud; - BYTE fraction; - } setbaud; - setbaud.baud = 9600; - setbaud.fraction = 0; - ulParmLen = sizeof(setbaud); - rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_EXTSETBAUDRATE, &setbaud, ulParmLen, &ulParmLen, 0, 0, 0); - if (rc != NO_ERROR) - { - LOG_MSG("ExtSetBaudrate failed with error %d.\n", rc); - DosClose (hCom); - hCom = 0; - return; -} - - struct { - UCHAR data; - UCHAR parity; - UCHAR stop; - } paramline; - - // byte length - paramline.data = 8; - paramline.parity = 0; - paramline.stop = 0; - ulParmLen = sizeof(paramline); - rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETLINECTRL, ¶mline, ulParmLen, &ulParmLen, 0, 0, 0); - if ( rc != NO_ERROR) - { - LOG_MSG ("SetLineCtrl failed with error %d.\n", rc); - } - - CSerial::Init_Registers(); - InstallationSuccessful = true; - receiveblock = false; - - // Clears comm errors - USHORT errors = 0; - ulParmLen = sizeof(errors); - DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMERROR, 0, 0, 0, &errors, ulParmLen, &ulParmLen); - setEvent(SERIAL_POLLING_EVENT, 1); - } - -CDirectSerial::~CDirectSerial () { - if (hCom != 0) - DosClose (hCom); -} - - - -/*****************************************************************************/ -/* updatePortConfig is called when emulated app changes the serial port **/ -/* parameters baudrate, stopbits, number of databits, parity. **/ -/*****************************************************************************/ -void CDirectSerial::updatePortConfig (Bit16u divider, Bit8u lcr) { - Bit8u parity = 0; - Bit8u bytelength = 0; - struct { - ULONG baud; - BYTE fraction; - } setbaud; - - // baud - if (divider <= 0x1) - setbaud.baud = 115200; - else if (divider <= 0x2) - setbaud.baud = 57600; - else if (divider <= 0x3) - setbaud.baud = 38400; - else if (divider <= 0x6) - setbaud.baud = 19200; - else if (divider <= 0xc) - setbaud.baud = 9600; - else if (divider <= 0x18) - setbaud.baud = 4800; - else if (divider <= 0x30) - setbaud.baud = 2400; - else if (divider <= 0x60) - setbaud.baud = 1200; - else if (divider <= 0xc0) - setbaud.baud = 600; - else if (divider <= 0x180) - setbaud.baud = 300; - else if (divider <= 0x417) - setbaud.baud = 110; - - // I read that windows can handle nonstandard baudrates: - else - setbaud.baud = 115200 / divider; - - - setbaud.fraction = 0; - ULONG ulParmLen = sizeof(setbaud); - APIRET rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_EXTSETBAUDRATE, &setbaud, ulParmLen, &ulParmLen, 0, 0, 0); - if (rc != NO_ERROR) - { - LOG_MSG("Serial%d: Desired serial mode not supported (Baud: %d, %d, Error: %d)", - COMNUMBER, setbaud.baud, divider, rc); - } - - - struct { - UCHAR data; - UCHAR parity; - UCHAR stop; - } paramline; - - // byte length - bytelength = lcr & 0x3; - bytelength += 5; - paramline.data = bytelength; - - // parity - parity = lcr & 0x38; - parity = parity >> 3; - switch (parity) { - case 0x1: - paramline.parity = 1; - break; - case 0x3: - paramline.parity = 2; - break; - case 0x5: - paramline.parity = 3; - break; - case 0x7: - paramline.parity = 4; - break; - default: - paramline.parity = 0; - break; - } - - // stopbits - if (lcr & 0x4) { - if (bytelength == 5) - paramline.stop = 1; - else - paramline.stop = 2; - } else { - paramline.stop = 0; - } - - -#ifdef SERIAL_DEBUG - LOG_MSG("_____________________________________________________"); - LOG_MSG("Serial%d, new baud rate: %d", COMNUMBER, setbaud.baud); - LOG_MSG("Serial%d: new bytelen: %d", COMNUMBER, paramline.data); - LOG_MSG("Serial%d: new parity: %d", COMNUMBER, paramline.parity); - LOG_MSG("Serial%d: new stopbits: %d", COMNUMBER, paramline.stop); -#endif - - ulParmLen = sizeof(paramline); - rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETLINECTRL, ¶mline, ulParmLen, &ulParmLen, 0, 0, 0); - if ( rc != NO_ERROR) - { -#ifdef SERIAL_DEBUG - if (dbg_modemcontrol) - { - fprintf(debugfp, "%12.3f serial mode not supported: rate=%d, LCR=%x.\r\n", PIC_FullIndex(), setbaud.baud, lcr); - } -#endif - LOG_MSG("Serial%d: Desired serial mode not supported (%d,%d,%d,%d)", - COMNUMBER, setbaud.baud, paramline.data, paramline.parity, lcr); - } - - -} - -void CDirectSerial::updateMSR () { - Bit8u newmsr = 0; - UCHAR dptr = 0; - ULONG ulParmLen = sizeof(dptr); - - APIRET rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETMODEMINPUT, 0, 0, 0, &dptr, ulParmLen, &ulParmLen); - if (rc != NO_ERROR) { - LOG_MSG ("Serial port at %x: GetModemInput failed with %d !", idnumber, dptr); - } - setCTS( (dptr & 16) != 0); - setDSR( (dptr & 32) != 0); - setRI( (dptr & 64) != 0); - setCD( (dptr & 128) != 0); -} - -void CDirectSerial::transmitByte (Bit8u val, bool first) { - ULONG bytesWritten = 0; - APIRET rc = DosWrite (hCom, &val, 1, &bytesWritten); - if (rc == NO_ERROR && bytesWritten > 0) { - //LOG_MSG("UART 0x%x: TX 0x%x", base,val); - } else { - LOG_MSG ("Serial%d: NO BYTE WRITTEN!", idnumber); - } - if (first) - { - setEvent(SERIAL_THR_EVENT, bytetime / 8); - } else { - setEvent(SERIAL_TX_EVENT, bytetime); - } -} - -/*****************************************************************************/ -/* setBreak(val) switches break on or off **/ -/*****************************************************************************/ - -void CDirectSerial::setBreak (bool value) { - USHORT error; - ULONG ulParmLen = sizeof(error); - if (value) - DosDevIOCtl (hCom, IOCTL_ASYNC, ASYNC_SETBREAKON, 0,0,0, &error, ulParmLen, &ulParmLen); - else - DosDevIOCtl (hCom, IOCTL_ASYNC, ASYNC_SETBREAKOFF, 0,0,0, &error, ulParmLen, &ulParmLen); -} - -/*****************************************************************************/ -/* updateModemControlLines(mcr) sets DTR and RTS. **/ -/*****************************************************************************/ -void CDirectSerial::setRTSDTR(bool rts, bool dtr) -{ - bool change = false; - DCBINFO dcb; - ULONG ulParmLen = sizeof(dcb); - - DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO, 0, 0, 0, &dcb, ulParmLen, &ulParmLen); - - /*** DTR ***/ - if (dtr) { // DTR on - if (dcb.fbCtlHndShake && 3 == 0) { // DTR disabled - dcb.fbCtlHndShake |= 1; - change = true; - } - } else { - if (dcb.fbCtlHndShake && 3 == 1) { // DTR enabled - dcb.fbCtlHndShake &= ~3; - change = true; - } - } - /*** RTS ***/ - if (rts) { // RTS on - if (dcb.fbFlowReplace && 192 == 0) { //RTS disabled - dcb.fbFlowReplace |= 64; - change = true; - } - } else { - if (dcb.fbFlowReplace && 192 == 1) { // RTS enabled - dcb.fbFlowReplace &= ~192; - change = true; - } - } - if (change) - DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcb, ulParmLen, &ulParmLen, 0, 0, 0); -} - -void CDirectSerial::setRTS(bool val) -{ - bool change = false; - DCBINFO dcb; - ULONG ulParmLen = sizeof(dcb); - - DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO, 0, 0, 0, &dcb, ulParmLen, &ulParmLen); - - /*** RTS ***/ - if (val) { // RTS on - if (dcb.fbFlowReplace && 192 == 0) { //RTS disabled - dcb.fbFlowReplace |= 64; - change = true; - } - } else { - if (dcb.fbFlowReplace && 192 == 1) { // RTS enabled - dcb.fbFlowReplace &= ~192; - change = true; - } - } - if (change) - DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcb, ulParmLen, &ulParmLen, 0, 0, 0); - } - -void CDirectSerial::setDTR(bool val) -{ - bool change = false; - DCBINFO dcb; - ULONG ulParmLen = sizeof(dcb); - - DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO, 0, 0, 0, &dcb, ulParmLen, &ulParmLen); - - /*** DTR ***/ - if (val) { // DTR on - if (dcb.fbCtlHndShake && 3 == 0) { // DTR disabled - dcb.fbCtlHndShake |= 1; - change = true; - } - } else { - if (dcb.fbCtlHndShake && 3 == 1) { // DTR enabled - dcb.fbCtlHndShake &= ~3; - change = true; - } - } - if (change) - DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO, &dcb, ulParmLen, &ulParmLen, 0, 0, 0); - } - - -void CDirectSerial::handleUpperEvent(Bit16u type) - { - switch(type) { - case SERIAL_POLLING_EVENT: { - ULONG dwRead = 0; - ULONG errors = 0; - Bit8u chRead = 0; - - setEvent(SERIAL_POLLING_EVENT, 1); - if(!receiveblock) { - if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )) - { - rx_retry=0; - if (DosRead (hCom, &chRead, 1, &dwRead) == NO_ERROR) { - if (dwRead) { - receiveByte (chRead); - setEvent(40, bytetime-0.03f); // receive timing - receiveblock=true; - } - } - } else rx_retry++; - } - // check for errors - CheckErrors(); - // update Modem input line states - updateMSR (); - break; - } - case 40: { - // receive time is up - ULONG dwRead = 0; - Bit8u chRead = 0; - receiveblock=false; - // check if there is something to receive - if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )) - { - rx_retry=0; - if (DosRead (hCom, &chRead, 1, &dwRead) == NO_ERROR) { - if (dwRead) { - receiveByte (chRead); - setEvent(40, bytetime-0.03f); // receive timing - receiveblock=true; - } - } - } else rx_retry++; - break; - } - case SERIAL_TX_EVENT: { - ULONG dwRead = 0; - Bit8u chRead = 0; - if(!receiveblock) { - if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )) - { - rx_retry=0; - if (DosRead (hCom, &chRead, 1, &dwRead) == NO_ERROR) { - if (dwRead) { - receiveByte (chRead); - setEvent(40, bytetime-0.03f); // receive timing - receiveblock=true; - } - } - } else rx_retry++; - } - ByteTransmitted(); - break; - } - case SERIAL_THR_EVENT: { - ByteTransmitting(); - setEvent(SERIAL_TX_EVENT,bytetime+0.03f); - break; - } - } - -} - -void CDirectSerial::CheckErrors() { - - USHORT errors = 0, event = 0; - ULONG ulParmLen = sizeof(errors); - DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMEVENT, 0, 0, 0, &event, ulParmLen, &ulParmLen); - if (event & (64 + 128) ) { // Break (Bit 6) or Frame or Parity (Bit 7) error - Bit8u errreg = 0; - if (event & 64) errreg |= LSR_RX_BREAK_MASK; - if (event & 128) { - DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMERROR, 0, 0, 0, &errors, ulParmLen, &ulParmLen); - if (errors & 8) errreg |= LSR_FRAMING_ERROR_MASK; - if (errors & 4) errreg |= LSR_PARITY_ERROR_MASK; - } - receiveError (errreg); - } -} - -#endif -#endif diff --git a/src/hardware/serialport/directserial_os2.h b/src/hardware/serialport/directserial_os2.h deleted file mode 100644 index a27438f..0000000 --- a/src/hardware/serialport/directserial_os2.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: directserial_os2.h,v 1.4 2007/02/22 08:41:16 qbix79 Exp $ */ - -// include guard -#ifndef DOSBOX_DIRECTSERIAL_OS2_H -#define DOSBOX_DIRECTSERIAL_OS2_H - -#include "dosbox.h" - -#if C_DIRECTSERIAL -#if defined(OS2) -#define DIRECTSERIAL_AVAILIBLE -#include "serialport.h" -#define INCL_DOSFILEMGR -#define INCL_DOSERRORS -#define INCL_DOSDEVICES -#define INCL_DOSDEVIOCTL -#define INCL_DOSPROCESS -#include - -class CDirectSerial : public CSerial { -public: - HFILE hCom; - BOOL fSuccess; - - CDirectSerial(Bitu id, CommandLine* cmd); - ~CDirectSerial(); - - - //Bitu lastChance; // If there is no space for new - // received data, it gets a little chance - //Bit8u ChanceChar; - - //bool CanRecv(void); - //bool CanSend(void); - - - //void RXBufferEmpty(); - bool receiveblock; - Bitu rx_retry; - Bitu rx_retry_max; - - void CheckErrors(); - - void updatePortConfig(Bit16u divider, Bit8u lcr); - void updateMSR(); - void transmitByte(Bit8u val, bool first); - void setBreak(bool value); - - void setRTSDTR(bool rts, bool dtr); - void setRTS(bool val); - void setDTR(bool val); - void handleUpperEvent(Bit16u type); - - - //void updateModemControlLines(/*Bit8u mcr*/); - //void Timer2(void); - - -}; -#endif // IFDEF - -#endif // C_DIRECTSERIAL -#endif // include guard - diff --git a/src/hardware/serialport/directserial_posix.cpp b/src/hardware/serialport/directserial_posix.cpp deleted file mode 100644 index a5e4a51..0000000 --- a/src/hardware/serialport/directserial_posix.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: directserial_posix.cpp,v 1.3 2009/01/26 20:15:58 qbix79 Exp $ */ - -#include "dosbox.h" - -#if C_DIRECTSERIAL - -// Posix version -#if defined (LINUX) || defined (MACOSX) || defined (BSD) - -#include "serialport.h" -#include "directserial_posix.h" -#include "pic.h" - -#include -#include -#include - -#include -#include - -/* This is a serial passthrough class. Its amazingly simple to */ -/* write now that the serial ports themselves were abstracted out */ - -CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd) - :CSerial (id, cmd) { - InstallationSuccessful = false; - - rx_retry = 0; - rx_retry_max = 0; - - std::string prefix="/dev/"; - std::string tmpstring; - if(!cmd->FindStringBegin("realport:",tmpstring,false)) return; - -#if SERIAL_DEBUG - if(dbg_modemcontrol) - fprintf(debugfp,"%12.3f Port type directserial realport %s\r\n", - PIC_FullIndex(),tmpstring.c_str()); -#endif - - prefix.append(tmpstring); - - // rxdelay: How many milliseconds to wait before causing an - // overflow when the application is unresponsive. - if(getBituSubstring("rxdelay:", &rx_retry_max, cmd)) { - if(!(rx_retry_max<=10000)) rx_retry_max=0; - } - - const char* tmpchar=prefix.c_str(); - - LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpchar); - - fileHandle = open (tmpchar, O_RDWR | O_NOCTTY | O_NONBLOCK); - - if (fileHandle < 0) { - LOG_MSG ("Serial%d: Serial Port \"%s\" could not be opened.", - COMNUMBER, tmpchar); - if (errno == 2) { - LOG_MSG ("The specified port does not exist."); - } else if (errno == EBUSY) { - LOG_MSG ("The specified port is already in use."); - } else { - LOG_MSG ("Errno %d occurred.", errno); - } - return; - } - - int result = tcgetattr(fileHandle, &termInfo); - - - if (result==-1) { - // Handle the error. - LOG_MSG ("tcgetattr failed with error %d.\n", errno); - return; - } - - // save it here to restore in destructor - tcgetattr(fileHandle,&backup); - - // initialize the port - termInfo.c_cflag = CS8 | CREAD | CLOCAL; // noparity, 1 stopbit - termInfo.c_iflag = PARMRK | INPCK; - termInfo.c_oflag = 0; - termInfo.c_lflag = 0; - - cfsetospeed (&termInfo, B9600); - cfsetispeed (&termInfo, B9600); - - termInfo.c_cc[VMIN] = 0; - termInfo.c_cc[VTIME] = 0; - - tcflush (fileHandle, TCIFLUSH); - tcsetattr (fileHandle, TCSANOW, &termInfo); - - //initialise base class - CSerial::Init_Registers(); - InstallationSuccessful = true; - receiveblock=false; - - setEvent(SERIAL_POLLING_EVENT, 1); // millisecond tick -} - -CDirectSerial::~CDirectSerial () { - if (fileHandle >= 0) - { - tcsetattr(fileHandle, TCSANOW, &backup); - close(fileHandle); - } - // We do not use own events so we don't have to clear them. -} - -void CDirectSerial::handleUpperEvent(Bit16u type) { - - switch(type) { - case SERIAL_POLLING_EVENT: { - setEvent(SERIAL_POLLING_EVENT, 1); - if(!receiveblock) { - if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )) - { - ReadCharacter(); - } else rx_retry++; - } - // check for errors - CheckErrors(); - // update Modem input line states - updateMSR (); - break; - } - case 40: { - // receive time is up - receiveblock=false; - // check if there is something to receive - if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )) - { - ReadCharacter(); - } else rx_retry++; - break; - } - case SERIAL_TX_EVENT: { - if(!receiveblock) { - if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )) - { - ReadCharacter(); - } else rx_retry++; - } - ByteTransmitted(); - break; - } - case SERIAL_THR_EVENT: { - ByteTransmitting(); - setEvent(SERIAL_TX_EVENT,bytetime+0.03f); - break; - } - } -} - -void CDirectSerial::ReadCharacter() -{ - Bit8u chRead = 0; - int dwRead = 0; - rx_retry=0; - - dwRead=read(fileHandle,&chRead,1); - if (dwRead==1) { - if(chRead==0xff) // error escape - { - dwRead=read(fileHandle,&chRead,1); - if(chRead==0x00) // an error - { - dwRead=read(fileHandle,&chRead,1); - if(chRead==0x0)receiveError(LSR_RX_BREAK_MASK); - else receiveError(LSR_PARITY_ERROR_MASK); - } - } - receiveByte (chRead); - setEvent(40, bytetime-0.03f); // receive timing - receiveblock=true; - } -} - -void CDirectSerial::CheckErrors() { - -} - -/*****************************************************************************/ -/* updatePortConfig is called when emulated app changes the serial port **/ -/* parameters baudrate, stopbits, number of databits, parity. **/ -/*****************************************************************************/ -void CDirectSerial::updatePortConfig (Bit16u divider, Bit8u lcr) { - Bit8u parity = 0; - Bit8u bytelength = 0; - int baudrate=0; - - // baud - termInfo.c_cflag = CREAD | CLOCAL; - - if (divider == 0x1) baudrate = B115200; - else if (divider == 0x2) baudrate = B57600; - else if (divider == 0x3) baudrate = B38400; - else if (divider == 0x6) baudrate = B19200; - else if (divider == 0xc) baudrate = B9600; - else if (divider == 0x18) baudrate = B4800; - else if (divider == 0x30) baudrate = B2400; - else if (divider == 0x60) baudrate = B1200; - else if (divider == 0xc0) baudrate = B600; - else if (divider == 0x180) baudrate = B300; - else if (divider == 0x417) baudrate = B110; - - // Don't think termios supports nonstandard baudrates - else baudrate = B9600; - - // byte length - bytelength = lcr & 0x3; - bytelength += 5; - - switch (bytelength) { - case 5: - termInfo.c_cflag |= CS5; - break; - - case 6: - termInfo.c_cflag |= CS6; - break; - - case 7: - termInfo.c_cflag |= CS7; - break; - - case 8: - default: - termInfo.c_cflag |= CS8; - break; - } - - // parity - parity = lcr & 0x38; - parity >>= 3; - switch (parity) { - case 0x1: - termInfo.c_cflag |= PARODD; - termInfo.c_cflag |= PARENB; - break; - case 0x3: - termInfo.c_cflag |= PARENB; - break; - case 0x5: - -// "works on many systems" -#define CMSPAR 010000000000 - - termInfo.c_cflag |= PARODD; - termInfo.c_cflag |= PARENB; - termInfo.c_cflag |= CMSPAR; - //LOG_MSG("Serial%d: Mark parity not supported.", COMNUMBER); - break; - case 0x7: - termInfo.c_cflag |= PARENB; - termInfo.c_cflag |= CMSPAR; - //LOG_MSG("Serial%d: Space parity not supported.", COMNUMBER); - break; - default: // no parity - break; - } - - // stopbits - if (lcr & 0x4) termInfo.c_cflag |= CSTOPB; - - cfsetospeed (&termInfo, baudrate); - cfsetispeed (&termInfo, baudrate); - - int retval = tcsetattr(fileHandle, TCSANOW, &termInfo); - - if(retval==-1) - LOG_MSG ("Serial%d: Desired serial mode not supported", COMNUMBER); - -} - -void CDirectSerial::updateMSR () { - long flags = 0; - ioctl (fileHandle, TIOCMGET, &flags); - - if (flags & TIOCM_CTS) setCTS(true); - else setCTS(false); - - if (flags & TIOCM_DSR) setDSR(true); - else setDSR(false); - - if (flags & TIOCM_RI) setRI(true); - else setRI(false); - - if (flags & TIOCM_CD) setCD(true); - else setCD(false); -} - -void CDirectSerial::transmitByte (Bit8u val, bool first) { - if((LCR&LCR_BREAK_MASK) == 0) { - - int bytesWritten = write(fileHandle, &val, 1); - if (bytesWritten != 1) - LOG_MSG ("Serial%d: COM port error: write failed!", idnumber); - } - if(first) setEvent(SERIAL_THR_EVENT, bytetime/8); - else setEvent(SERIAL_TX_EVENT, bytetime); -} - -/*****************************************************************************/ -/* setBreak(val) switches break on or off **/ -/*****************************************************************************/ -void CDirectSerial::setBreak (bool value) { - if (value) ioctl (fileHandle, TIOCSBRK); - else ioctl (fileHandle, TIOCCBRK); -} - -/*****************************************************************************/ -/* updateModemControlLines(mcr) sets DTR and RTS. **/ -/*****************************************************************************/ -void CDirectSerial::setRTSDTR(bool rts, bool dtr) { - - long setflags = 0; - long clearflags = 0; - - if(rts) setflags |= TIOCM_RTS; - else clearflags |= TIOCM_RTS; - - if(dtr) setflags |= TIOCM_DTR; - else clearflags |= TIOCM_DTR; - - if(setflags) ioctl (fileHandle, TIOCMBIS, &setflags); - if(clearflags) ioctl (fileHandle, TIOCMBIC, &clearflags); -} -void CDirectSerial::setRTS(bool val) { - long flag = TIOCM_RTS; - if(val) ioctl(fileHandle, TIOCMBIS, &flag); - else ioctl(fileHandle, TIOCMBIC, &flag); -} -void CDirectSerial::setDTR(bool val) { - long flag = TIOCM_DTR; - if(val) ioctl(fileHandle, TIOCMBIS, &flag); - else ioctl(fileHandle, TIOCMBIC, &flag); -} - -#endif -#endif diff --git a/src/hardware/serialport/directserial_posix.h b/src/hardware/serialport/directserial_posix.h deleted file mode 100644 index 5ba38b5..0000000 --- a/src/hardware/serialport/directserial_posix.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: directserial_posix.h,v 1.3 2009/01/26 20:15:58 qbix79 Exp $ */ - -// include guard -#ifndef DOSBOX_DIRECTSERIAL_POSIX_H -#define DOSBOX_DIRECTSERIAL_POSIX_H - -#include "dosbox.h" - -#if C_DIRECTSERIAL -#if defined (LINUX) || defined (MACOSX) || defined (BSD) - - - -#define DIRECTSERIAL_AVAILIBLE -#include "serialport.h" -#include -#include - -class CDirectSerial : public CSerial { -public: - termios termInfo; - termios backup; - int fileHandle; - - CDirectSerial(Bitu id, CommandLine* cmd); - ~CDirectSerial(); - bool receiveblock; // It's not a block of data it rather blocks - - Bitu rx_retry; // counter of retries - - Bitu rx_retry_max; // how many POLL_EVENTS to wait before causing - // a overrun error. - - void ReadCharacter(); - void CheckErrors(); - - void updatePortConfig(Bit16u divider, Bit8u lcr); - void updateMSR(); - void transmitByte(Bit8u val, bool first); - void setBreak(bool value); - - void setRTSDTR(bool rts, bool dtr); - void setRTS(bool val); - void setDTR(bool val); - void handleUpperEvent(Bit16u type); - -}; - -#endif // WIN32 -#endif // C_DIRECTSERIAL -#endif // include guard diff --git a/src/hardware/serialport/directserial_win32.cpp b/src/hardware/serialport/directserial_win32.cpp deleted file mode 100644 index c8124d8..0000000 --- a/src/hardware/serialport/directserial_win32.cpp +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: directserial_win32.cpp,v 1.7 2008/08/06 18:33:30 c2woody Exp $ */ - -#include "dosbox.h" - -#if C_DIRECTSERIAL - -/* Windows version */ -#if defined (WIN32) - -#include "serialport.h" -#include "directserial_win32.h" -#include "misc_util.h" -#include "pic.h" - -// Win32 related headers -#include - -/* This is a serial passthrough class. Its amazingly simple to */ -/* write now that the serial ports themselves were abstracted out */ - -CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd) - :CSerial (id, cmd) { - InstallationSuccessful = false; - hCom = INVALID_HANDLE_VALUE; // else destructor may close an invalid handle - rx_retry = 0; - rx_retry_max = 0; - - // open the port in NT object space (recommended by Microsoft) - // allows the user to open COM10+ and custom port names. - std::string prefix="\\\\.\\"; - std::string tmpstring; - if(!cmd->FindStringBegin("realport:",tmpstring,false)) return; - -#if SERIAL_DEBUG - if(dbg_modemcontrol) - fprintf(debugfp,"%12.3f Port type directserial realport %s\r\n", - PIC_FullIndex(),tmpstring.c_str()); -#endif - - prefix.append(tmpstring); - - // rxdelay: How many milliseconds to wait before causing an - // overflow when the application is unresponsive. - if(getBituSubstring("rxdelay:", &rx_retry_max, cmd)) { - if(!(rx_retry_max<=10000)) { - rx_retry_max=0; - } - } - - const char* tmpchar=prefix.c_str(); - - LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpstring.c_str()); - hCom = CreateFile (tmpchar, - GENERIC_READ | GENERIC_WRITE, 0, - // must be opened with exclusive-access - NULL, // no security attributes - OPEN_EXISTING, // must use OPEN_EXISTING - 0, // non overlapped I/O - NULL // hTemplate must be NULL for comm devices - ); - - if (hCom == INVALID_HANDLE_VALUE) { - int error = GetLastError (); - LOG_MSG ("Serial%d: Serial Port \"%s\" could not be opened.", - COMNUMBER, tmpstring.c_str()); - if (error == 2) { - LOG_MSG ("The specified port does not exist."); - } else if (error == 5) { - LOG_MSG ("The specified port is already in use."); - } else { - LOG_MSG ("Windows error %d occurred.", error); - } - return; - } - - dcb.DCBlength=sizeof(dcb); - fSuccess = GetCommState (hCom, &dcb); - - if (!fSuccess) { - // Handle the error. - LOG_MSG ("GetCommState failed with error %d.\n", (int)GetLastError ()); - hCom = INVALID_HANDLE_VALUE; - return; - } - - // initialize the port - dcb.BaudRate=CBR_9600; - dcb.fBinary=true; - dcb.fParity=true; - dcb.fOutxCtsFlow=false; - dcb.fOutxDsrFlow=false; - dcb.fDtrControl=DTR_CONTROL_DISABLE; - dcb.fDsrSensitivity=false; - - dcb.fOutX=false; - dcb.fInX=false; - dcb.fErrorChar=0; - dcb.fNull=false; - dcb.fRtsControl=RTS_CONTROL_DISABLE; - dcb.fAbortOnError=false; - - dcb.ByteSize=8; - dcb.Parity=NOPARITY; - dcb.StopBits=ONESTOPBIT; - - fSuccess = SetCommState (hCom, &dcb); - - if (!fSuccess) { - // Handle the error. - LOG_MSG ("SetCommState failed with error %d.\n", (int)GetLastError ()); - hCom = INVALID_HANDLE_VALUE; - return; - } - - // Configure timeouts to effectively use polling - COMMTIMEOUTS ct; - ct.ReadIntervalTimeout = MAXDWORD; - ct.ReadTotalTimeoutConstant = 0; - ct.ReadTotalTimeoutMultiplier = 0; - ct.WriteTotalTimeoutConstant = 0; - ct.WriteTotalTimeoutMultiplier = 0; - SetCommTimeouts (hCom, &ct); - - CSerial::Init_Registers(); - InstallationSuccessful = true; - receiveblock=false; - - ClearCommBreak (hCom); - setEvent(SERIAL_POLLING_EVENT, 1); // millisecond tick -} - -CDirectSerial::~CDirectSerial () { - if (hCom != INVALID_HANDLE_VALUE) CloseHandle (hCom); - // We do not use own events so we don't have to clear them. -} - -void CDirectSerial::handleUpperEvent(Bit16u type) { - - switch(type) { - case SERIAL_POLLING_EVENT: { - DWORD dwRead = 0; - Bit8u chRead = 0; - - setEvent(SERIAL_POLLING_EVENT, 1); - if(!receiveblock) { - if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )) - { - rx_retry=0; - if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) { - if (dwRead) { - receiveByte (chRead); - setEvent(40, bytetime-0.03f); // receive timing - receiveblock=true; - } - } - } else rx_retry++; - } - // check for errors - CheckErrors(); - // update Modem input line states - updateMSR (); - break; - } - case 40: { - // receive time is up - DWORD dwRead = 0; - Bit8u chRead = 0; - receiveblock=false; - // check if there is something to receive - if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )) - { - rx_retry=0; - if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) { - if (dwRead) { - receiveByte (chRead); - setEvent(40, bytetime-0.03f); // receive timing - receiveblock=true; - } - } - } else rx_retry++; - break; - } - case SERIAL_TX_EVENT: { - DWORD dwRead = 0; - Bit8u chRead = 0; - if(!receiveblock) { - if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max )) - { - rx_retry=0; - if (ReadFile (hCom, &chRead, 1, &dwRead, NULL)) { - if (dwRead) { - receiveByte (chRead); - setEvent(40, bytetime-0.03f); // receive timing - receiveblock=true; - } - } - } else rx_retry++; - } - ByteTransmitted(); - break; - } - case SERIAL_THR_EVENT: { - ByteTransmitting(); - setEvent(SERIAL_TX_EVENT,bytetime+0.03f); - break; - } - } -} - -void CDirectSerial::CheckErrors() { - - DWORD errors=0; - // check for errors - if (ClearCommError (hCom, &errors, NULL)) - if (errors & (CE_BREAK | CE_FRAME | CE_RXPARITY)) { - Bit8u errreg = 0; - if (errors & CE_BREAK) errreg |= LSR_RX_BREAK_MASK; - if (errors & CE_FRAME) errreg |= LSR_FRAMING_ERROR_MASK; - if (errors & CE_RXPARITY) errreg |= LSR_PARITY_ERROR_MASK; - receiveError (errreg); - } -} - -/*****************************************************************************/ -/* updatePortConfig is called when emulated app changes the serial port **/ -/* parameters baudrate, stopbits, number of databits, parity. **/ -/*****************************************************************************/ -void CDirectSerial::updatePortConfig (Bit16u divider, Bit8u lcr) { - Bit8u parity = 0; - Bit8u bytelength = 0; - - // baud - if (divider == 0x1) - dcb.BaudRate = CBR_115200; - else if (divider == 0x2) - dcb.BaudRate = CBR_57600; - else if (divider == 0x3) - dcb.BaudRate = CBR_38400; - else if (divider == 0x6) - dcb.BaudRate = CBR_19200; - else if (divider == 0xc) - dcb.BaudRate = CBR_9600; - else if (divider == 0x18) - dcb.BaudRate = CBR_4800; - else if (divider == 0x30) - dcb.BaudRate = CBR_2400; - else if (divider == 0x60) - dcb.BaudRate = CBR_1200; - else if (divider == 0xc0) - dcb.BaudRate = CBR_600; - else if (divider == 0x180) - dcb.BaudRate = CBR_300; - else if (divider == 0x417) - dcb.BaudRate = CBR_110; - - // I read that windows can handle nonstandard baudrates: - else - dcb.BaudRate = 115200 / divider; - - // byte length - bytelength = lcr & 0x3; - bytelength += 5; - dcb.ByteSize = bytelength; - - // parity - parity = lcr & 0x38; - parity = parity >> 3; - switch (parity) { - case 0x1: - dcb.Parity = ODDPARITY; - break; - case 0x3: - dcb.Parity = EVENPARITY; - break; - case 0x5: - dcb.Parity = MARKPARITY; - break; - case 0x7: - dcb.Parity = SPACEPARITY; - break; - default: - dcb.Parity = NOPARITY; - break; - } - - // stopbits - if (lcr & 0x4) { - if (bytelength == 5) - dcb.StopBits = ONE5STOPBITS; - else - dcb.StopBits = TWOSTOPBITS; - } else { - dcb.StopBits = ONESTOPBIT; - } - -#ifdef SERIALPORT_DEBUGMSG - LOG_MSG ("__________________________"); - LOG_MSG ("Serial%d: new baud rate: %d", COMNUMBER, dcb.BaudRate); - LOG_MSG ("Serial%d: new bytelen: %d", COMNUMBER, dcb.ByteSize); - LOG_MSG ("Serial%d: new parity: %d", COMNUMBER, dcb.Parity); - LOG_MSG ("Serial%d: new stopbits: %d", COMNUMBER, dcb.StopBits); -#endif - - if (!SetCommState (hCom, &dcb)) { - -#if SERIAL_DEBUG - if(dbg_modemcontrol) - fprintf(debugfp,"%12.3f serial mode not supported: rate=%d,LCR=%x.\r\n", - PIC_FullIndex(),dcb.BaudRate,lcr); -#endif - - LOG_MSG ("Serial%d: Desired serial mode not supported (%d,%d,%d,%d", - (Bit32u)dcb.BaudRate,(Bit32u)dcb.ByteSize, - (Bit32u)dcb.Parity,(Bit32u)dcb.StopBits, COMNUMBER); - } -} - -void CDirectSerial::updateMSR () { - DWORD dptr = 0; - - if (!GetCommModemStatus (hCom, &dptr)) { -#ifdef SERIALPORT_DEBUGMSG -// LOG_MSG ("Serial port at %x: GetCommModemStatus failed!", base); -#endif - //return; - } - setCTS((dptr & MS_CTS_ON)!=0); - setDSR((dptr & MS_DSR_ON)!=0); - setRI ((dptr & MS_RING_ON)!=0); - setCD((dptr & MS_RLSD_ON)!=0); -} - -void CDirectSerial::transmitByte (Bit8u val, bool first) { - // mean bug: with break = 1, WriteFile will never return. - if((LCR&LCR_BREAK_MASK) == 0) { - DWORD bytesWritten = 0; - WriteFile (hCom, &val, 1, &bytesWritten, NULL); - if (bytesWritten != 1) - LOG_MSG ("Serial%d: COM port error: write failed!", idnumber); - } - if(first) setEvent(SERIAL_THR_EVENT, bytetime/8); - else setEvent(SERIAL_TX_EVENT, bytetime); -} - -/*****************************************************************************/ -/* setBreak(val) switches break on or off **/ -/*****************************************************************************/ -void CDirectSerial::setBreak (bool value) { - if (value) SetCommBreak (hCom); - else ClearCommBreak (hCom); -} - -/*****************************************************************************/ -/* updateModemControlLines(mcr) sets DTR and RTS. **/ -/*****************************************************************************/ -void CDirectSerial::setRTSDTR(bool rts, bool dtr) { - if(rts) dcb.fRtsControl = RTS_CONTROL_ENABLE; - else dcb.fRtsControl = RTS_CONTROL_DISABLE; - if(dtr) dcb.fDtrControl = DTR_CONTROL_ENABLE; - else dcb.fDtrControl = DTR_CONTROL_DISABLE; - SetCommState (hCom, &dcb); - -} -void CDirectSerial::setRTS(bool val) { - if(val) dcb.fRtsControl = RTS_CONTROL_ENABLE; - else dcb.fRtsControl = RTS_CONTROL_DISABLE; - SetCommState (hCom, &dcb); -} -void CDirectSerial::setDTR(bool val) { - if(val) dcb.fDtrControl = DTR_CONTROL_ENABLE; - else dcb.fDtrControl = DTR_CONTROL_DISABLE; - SetCommState (hCom, &dcb); -} - -#endif -#endif diff --git a/src/hardware/serialport/directserial_win32.h b/src/hardware/serialport/directserial_win32.h deleted file mode 100644 index 651a02c..0000000 --- a/src/hardware/serialport/directserial_win32.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: directserial_win32.h,v 1.5 2007/05/23 08:05:22 qbix79 Exp $ */ - -// include guard -#ifndef DOSBOX_DIRECTSERIAL_WIN32_H -#define DOSBOX_DIRECTSERIAL_WIN32_H - -#include "dosbox.h" - -#if C_DIRECTSERIAL -#ifdef WIN32 - - - -#define DIRECTSERIAL_AVAILIBLE -#include "serialport.h" -#include //To prevent compilation problems with windows.h including winsock.h -#include - -class CDirectSerial : public CSerial { -public: - HANDLE hCom; - DCB dcb; - BOOL fSuccess; - - CDirectSerial(Bitu id, CommandLine* cmd/*const char* configstring*/); - ~CDirectSerial(); - bool receiveblock; // It's not a block of data it rather blocks - - Bitu rx_retry; // counter of retries - - Bitu rx_retry_max; // how many POLL_EVENTS to wait before causing - // a overrun error. - - - void CheckErrors(); - - void updatePortConfig(Bit16u divider, Bit8u lcr); - void updateMSR(); - void transmitByte(Bit8u val, bool first); - void setBreak(bool value); - - void setRTSDTR(bool rts, bool dtr); - void setRTS(bool val); - void setDTR(bool val); - void handleUpperEvent(Bit16u type); - -}; - -#endif // WIN32 -#endif // C_DIRECTSERIAL -#endif // include guard diff --git a/src/hardware/serialport/misc_util.cpp b/src/hardware/serialport/misc_util.cpp deleted file mode 100644 index bd0e36c..0000000 --- a/src/hardware/serialport/misc_util.cpp +++ /dev/null @@ -1,304 +0,0 @@ -#include "config.h" - -#if C_MODEM - -/*****************************************************************************/ -// C++ SDLnet wrapper - -#include "misc_util.h" - -struct _TCPsocketX { - int ready; -#ifdef NATIVESOCKETS - SOCKET channel; -#endif - IPaddress remoteAddress; - IPaddress localAddress; - int sflag; -}; - -Bit32u Netwrapper_GetCapabilities() -{ - Bit32u retval=0; - retval = CAPWORD; - return retval; -} - -#ifdef NATIVESOCKETS -TCPClientSocket::TCPClientSocket(int platformsocket) { - sendbuffer=0; - nativetcpstruct = new Bit8u[sizeof(struct _TCPsocketX)]; - - mysock = (TCPsocket)nativetcpstruct; - isopen = false; - if(!SDLNetInited) { - if(SDLNet_Init()==-1) { - LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError()); - return; - } - SDLNetInited = true; - } - // fill the SDL socket manually - ((struct _TCPsocketX*)nativetcpstruct)->ready=0; - ((struct _TCPsocketX*)nativetcpstruct)->sflag=0; - ((struct _TCPsocketX*)nativetcpstruct)->channel=(SOCKET) platformsocket; - sockaddr_in sa; - socklen_t sz; - sz=sizeof(sa); - if(getpeername(platformsocket, (sockaddr *)(&sa), &sz)==0) { - ((struct _TCPsocketX*)nativetcpstruct)-> - remoteAddress.host=/*ntohl(*/sa.sin_addr.s_addr;//); - ((struct _TCPsocketX*)nativetcpstruct)-> - remoteAddress.port=/*ntohs(*/sa.sin_port;//); - } - else { - mysock=0; - return; - } - sz=sizeof(sa); - if(getsockname(platformsocket, (sockaddr *)(&sa), &sz)==0) { - ((struct _TCPsocketX*)nativetcpstruct)-> - localAddress.host=/*ntohl(*/sa.sin_addr.s_addr;//); - ((struct _TCPsocketX*)nativetcpstruct)-> - localAddress.port=/*ntohs(*/sa.sin_port;//); - } - else { - mysock=0; - return; - } - if(mysock!=0) { - listensocketset = SDLNet_AllocSocketSet(1); - if(!listensocketset) return; - SDLNet_TCP_AddSocket(listensocketset, mysock); - isopen=true; - return; - } - mysock=0; - return; -} -#endif // NATIVESOCKETS - -TCPClientSocket::TCPClientSocket(TCPsocket source) { -#ifdef NATIVESOCKETS - nativetcpstruct=0; -#endif - sendbuffer=0; - isopen = false; - if(!SDLNetInited) { - if(SDLNet_Init()==-1) { - LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError()); - return; - } - SDLNetInited = true; - } - - mysock=0; - listensocketset=0; - if(source!=0) { - mysock = source; - listensocketset = SDLNet_AllocSocketSet(1); - if(!listensocketset) return; - SDLNet_TCP_AddSocket(listensocketset, source); - - isopen=true; - } -} -TCPClientSocket::TCPClientSocket(const char* destination, Bit16u port) { -#ifdef NATIVESOCKETS - nativetcpstruct=0; -#endif - sendbuffer=0; - isopen = false; - if(!SDLNetInited) { - if(SDLNet_Init()==-1) { - LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError()); - return; - } - SDLNetInited = true; - } - mysock=0; - listensocketset=0; - - IPaddress openip; - //Ancient versions of SDL_net had this as char*. People still appear to be using this one. - if (!SDLNet_ResolveHost(&openip,const_cast(destination),port)) { - listensocketset = SDLNet_AllocSocketSet(1); - if(!listensocketset) return; - mysock = SDLNet_TCP_Open(&openip); - if(!mysock) return; - SDLNet_TCP_AddSocket(listensocketset, mysock); - isopen=true; - } -} - -TCPClientSocket::~TCPClientSocket() { - - if(sendbuffer) delete [] sendbuffer; -#ifdef NATIVESOCKETS - if(nativetcpstruct) delete [] nativetcpstruct; - else -#endif - if(mysock) { - if(listensocketset) SDLNet_TCP_DelSocket(listensocketset,mysock); - SDLNet_TCP_Close(mysock); - } - - if(listensocketset) SDLNet_FreeSocketSet(listensocketset); -} -bool TCPClientSocket::GetRemoteAddressString(Bit8u* buffer) { - IPaddress* remote_ip; - Bit8u b1, b2, b3, b4; - remote_ip=SDLNet_TCP_GetPeerAddress(mysock); - if(!remote_ip) return false; - b4=remote_ip->host>>24; - b3=(remote_ip->host>>16)&0xff; - b2=(remote_ip->host>>8)&0xff; - b1=remote_ip->host&0xff; - sprintf((char*)buffer,"%u.%u.%u.%u",b1,b2,b3,b4); - return true; -} - -bool TCPClientSocket::ReceiveArray(Bit8u* data, Bitu* size) { - if(SDLNet_CheckSockets(listensocketset,0)) - { - Bitu retval = SDLNet_TCP_Recv(mysock, data, *size); - if(retval<1) { - isopen=false; - *size=0; - return false; - } else { - *size=retval; - return true; - } - } - else { - *size=0; - return true; - } -} - - -Bits TCPClientSocket::GetcharNonBlock() { -// return: -// -1: no data -// -2: socket closed -// 0..255: data - if(SDLNet_CheckSockets(listensocketset,0)) - { - Bitu retval =0; - if(SDLNet_TCP_Recv(mysock, &retval, 1)!=1) { - isopen=false; - return -2; - } else return retval; - } - else return -1; -} -bool TCPClientSocket::Putchar(Bit8u data) { - if(SDLNet_TCP_Send(mysock, &data, 1)!=1) { - isopen=false; - return false; - } - return true; -} - -bool TCPClientSocket::SendArray(Bit8u* data, Bitu bufsize) { - if(SDLNet_TCP_Send(mysock, data, bufsize)!=bufsize) { - isopen=false; - return false; - } - return true; -} - -bool TCPClientSocket::SendByteBuffered(Bit8u data) { - - if(sendbufferindex==(sendbuffersize-1)) { - // buffer is full, get rid of it - sendbuffer[sendbufferindex]=data; - sendbufferindex=0; - - if(SDLNet_TCP_Send(mysock, sendbuffer, sendbuffersize)!=sendbuffersize) { - isopen=false; - return false; - } - } else { - sendbuffer[sendbufferindex]=data; - sendbufferindex++; - } - return true; -} -/* -bool TCPClientSocket::SendArrayBuffered(Bit8u* data, Bitu bufsize) { - - Bitu bytes - while( - - // first case, buffer already full - if(sendbufferindex==(sendbuffersize-1)) { - // buffer is full, get rid of it - sendbuffer[sendbufferindex]=data; - sendbufferindex=0; - - if(SDLNet_TCP_Send(mysock, sendbuffer, sendbuffersize)!=sendbuffersize) { - isopen=false; - return false; - } - } -} -*/ -void TCPClientSocket::FlushBuffer() { - if(sendbufferindex) { - if(SDLNet_TCP_Send(mysock, sendbuffer, - sendbufferindex)!=sendbufferindex) { - isopen=false; - return; - } - sendbufferindex=0; - } -} - -void TCPClientSocket::SetSendBufferSize(Bitu bufsize) { - if(sendbuffer) delete [] sendbuffer; - sendbuffer = new Bit8u[bufsize]; - sendbuffersize=bufsize; - sendbufferindex=0; -} - - -TCPServerSocket::TCPServerSocket(Bit16u port) -{ - isopen = false; - mysock = 0; - if(!SDLNetInited) { - if(SDLNet_Init()==-1) { - LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError()); - return; - } - SDLNetInited = true; - } - if (port) { - IPaddress listen_ip; - SDLNet_ResolveHost(&listen_ip, NULL, port); - mysock=SDLNet_TCP_Open(&listen_ip); - if(!mysock) return; - } - else return; - isopen = true; -} - -TCPServerSocket::~TCPServerSocket() { - if(mysock) SDLNet_TCP_Close(mysock); -} - -TCPClientSocket* TCPServerSocket::Accept() { - - TCPsocket new_tcpsock; - - new_tcpsock=SDLNet_TCP_Accept(mysock); - if(!new_tcpsock) { - //printf("SDLNet_TCP_Accept: %s\n", SDLNet_GetError()); - return 0; - } - - return new TCPClientSocket(new_tcpsock); -} -#endif // #if C_MODEM diff --git a/src/hardware/serialport/misc_util.h b/src/hardware/serialport/misc_util.h deleted file mode 100644 index 80f40b4..0000000 --- a/src/hardware/serialport/misc_util.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef SDLNETWRAPPER_H -#define SDLNETWRAPPER_H - -#ifndef DOSBOX_DOSBOX_H -#include "dosbox.h" -#endif - -#if C_MODEM - -# ifndef DOSBOX_SUPPORT_H -#include "support.h" -#endif - -// Netwrapper Capabilities -#define NETWRAPPER_TCP 1 -#define NETWRAPPER_TCP_NATIVESOCKET 2 - -#if defined WIN32 - #define NATIVESOCKETS - #include - #include //for socklen_t - //typedef int socklen_t; - -//Tests for BSD/OS2/LINUX -#elif defined HAVE_STDLIB_H && defined HAVE_SYS_TYPES_H && defined HAVE_SYS_SOCKET_H && defined HAVE_NETINET_IN_H - #define NATIVESOCKETS - #define SOCKET int - #include //darwin - #include //darwin - #include - #include - #include - //socklen_t should be handled by configure -#endif - -#ifdef NATIVESOCKETS - #define CAPWORD (NETWRAPPER_TCP|NETWRAPPER_TCP_NATIVESOCKET) -#else - #define CAPWORD NETWRAPPER_TCP -#endif - -#include "SDL_net.h" - - - -Bit32u Netwrapper_GetCapabilities(); - - -class TCPClientSocket { - public: - TCPClientSocket(TCPsocket source); - TCPClientSocket(const char* destination, Bit16u port); -#ifdef NATIVESOCKETS - Bit8u* nativetcpstruct; - TCPClientSocket(int platformsocket); -#endif - ~TCPClientSocket(); - - // return: - // -1: no data - // -2: socket closed - // >0: data char - Bits GetcharNonBlock(); - - - bool Putchar(Bit8u data); - bool SendArray(Bit8u* data, Bitu bufsize); - bool ReceiveArray(Bit8u* data, Bitu* size); - bool isopen; - - bool GetRemoteAddressString(Bit8u* buffer); - - void FlushBuffer(); - void SetSendBufferSize(Bitu bufsize); - - // buffered send functions - bool SendByteBuffered(Bit8u data); - bool SendArrayBuffered(Bit8u* data, Bitu bufsize); - - private: - TCPsocket mysock; - SDLNet_SocketSet listensocketset; - - // Items for send buffering - Bitu sendbuffersize; - Bitu sendbufferindex; - - Bit8u* sendbuffer; -}; - -class TCPServerSocket { - public: - bool isopen; - TCPsocket mysock; - TCPServerSocket(Bit16u port); - ~TCPServerSocket(); - TCPClientSocket* Accept(); -}; - - -#endif //C_MODEM - -#endif //# SDLNETWRAPPER_H diff --git a/src/hardware/serialport/nullmodem.cpp b/src/hardware/serialport/nullmodem.cpp deleted file mode 100644 index 8a809c2..0000000 --- a/src/hardware/serialport/nullmodem.cpp +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: nullmodem.cpp,v 1.6 2009/02/01 14:24:37 qbix79 Exp $ */ - -#include "dosbox.h" - -#if C_MODEM - -#include "control.h" -#include "serialport.h" -#include "nullmodem.h" - -CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) { - Bitu temptcpport=23; - memset(&telClient, 0, sizeof(telClient)); - InstallationSuccessful = false; - serversocket = 0; - clientsocket = 0; - serverport = 0; - clientport = 0; - - rx_retry = 0; - rx_retry_max = 100; - - tx_gather = 12; - - dtrrespect=false; - tx_block=false; - receiveblock=false; - transparent=false; - telnet=false; - - Bitu bool_temp=0; - - // usedtr: The nullmodem will - // 1) when it is client connect to the server not immediately but - // as soon as a modem-aware application is started (DTR is switched on). - // 2) only transfer data when DTR is on. - if(getBituSubstring("usedtr:", &bool_temp, cmd)) { - if(bool_temp==1) { - dtrrespect=true; - transparent=true; - } - } - // transparent: don't add additional handshake control. - if(getBituSubstring("transparent:", &bool_temp, cmd)) { - if(bool_temp==1) transparent=true; - else transparent=false; - } - // telnet: interpret telnet commands. - if(getBituSubstring("telnet:", &bool_temp, cmd)) { - if(bool_temp==1) { - transparent=true; - telnet=true; - } - } - // rxdelay: How many milliseconds to wait before causing an - // overflow when the application is unresponsive. - if(getBituSubstring("rxdelay:", &rx_retry_max, cmd)) { - if(!(rx_retry_max<=10000)) { - rx_retry_max=50; - } - } - // txdelay: How many milliseconds to wait before sending data. - // This reduces network overhead quite a lot. - if(getBituSubstring("txdelay:", &tx_gather, cmd)) { - if(!(tx_gather<=500)) { - tx_gather=12; - } - } - // port is for both server and client - if(getBituSubstring("port:", &temptcpport, cmd)) { - if(!(temptcpport>0&&temptcpport<65536)) { - temptcpport=23; - } - } - // socket inheritance - if(getBituSubstring("inhsocket:", &bool_temp, cmd)) { -#ifdef NATIVESOCKETS - if(Netwrapper_GetCapabilities()&NETWRAPPER_TCP_NATIVESOCKET) { - if(bool_temp==1) { - int sock; - if (control->cmdline->FindInt("-socket",sock,true)) { - dtrrespect=false; - transparent=true; - // custom connect - Bit8u peernamebuf[16]; - LOG_MSG("inheritance port: %d",sock); - clientsocket = new TCPClientSocket(sock); - if(!clientsocket->isopen) { - LOG_MSG("Serial%d: Connection failed.",COMNUMBER); - delete clientsocket; - clientsocket=0; - return; - } - clientsocket->SetSendBufferSize(256); - clientsocket->GetRemoteAddressString(peernamebuf); - // transmit the line status - if(!transparent) setRTSDTR(getRTS(), getDTR()); - - LOG_MSG("Serial%d: Connected to %s",COMNUMBER,peernamebuf); - setEvent(SERIAL_POLLING_EVENT, 1); - - CSerial::Init_Registers (); - InstallationSuccessful = true; - - setCTS(true); - setDSR(true); - setRI (false); - setCD (true); - return; - } else { - LOG_MSG("Serial%d: -socket start parameter missing.",COMNUMBER); - return; - } - } - } else { -#endif - LOG_MSG("Serial%d: socket inheritance not supported on this platform.", - COMNUMBER); - return; - } - } - std::string tmpstring; - if(cmd->FindStringBegin("server:",tmpstring,false)) { - // we are a client - const char* hostnamechar=tmpstring.c_str(); - size_t hostlen=strlen(hostnamechar)+1; - if(hostlen>sizeof(hostnamebuffer)) { - hostlen=sizeof(hostnamebuffer); - hostnamebuffer[sizeof(hostnamebuffer)-1]=0; - } - memcpy(hostnamebuffer,hostnamechar,hostlen); - clientport=(Bit16u)temptcpport; - if(dtrrespect) { - // we connect as soon as DTR is switched on - setEvent(SERIAL_NULLMODEM_DTR_EVENT, 50); - LOG_MSG("Serial%d: Waiting for DTR...",COMNUMBER); - } else ClientConnect(); - } else { - // we are a server - serverport = (Bit16u)temptcpport; - serversocket = new TCPServerSocket(serverport); - if(!serversocket->isopen) return; - LOG_MSG("Serial%d: Nullmodem server waiting for connection on port %d...", - COMNUMBER,serverport); - setEvent(SERIAL_SERVER_POLLING_EVENT, 50); - } - - // .... - - CSerial::Init_Registers (); - InstallationSuccessful = true; - - setCTS(dtrrespect||transparent); - setDSR(dtrrespect||transparent); - setRI (false); - setCD (dtrrespect); -} - -CNullModem::~CNullModem () { - if(serversocket) delete serversocket; - if(clientsocket) delete clientsocket; - // remove events - for(Bit16u i = SERIAL_BASE_EVENT_COUNT+1; - i <= SERIAL_NULLMODEM_EVENT_COUNT; i++) { - removeEvent(i); - } -} - -void CNullModem::WriteChar(Bit8u data) { - - if(clientsocket)clientsocket->SendByteBuffered(data); - if(!tx_block) { - //LOG_MSG("setevreduct"); - setEvent(SERIAL_TX_REDUCTION, (float)tx_gather); - tx_block=true; - } -} - -Bits CNullModem::readChar() { - - Bits rxchar = clientsocket->GetcharNonBlock(); - if(telnet && rxchar>=0) return TelnetEmulation((Bit8u)rxchar); - else if(rxchar==0xff && !transparent) {// escape char - // get the next char - Bits rxchar = clientsocket->GetcharNonBlock(); - if(rxchar==0xff) return rxchar; // 0xff 0xff -> 0xff was meant - rxchar&0x1? setCTS(true) : setCTS(false); - rxchar&0x2? setDSR(true) : setDSR(false); - if(rxchar&0x4) receiveError(0x10); - return -1; // no "payload" received - } else return rxchar; -} - -void CNullModem::ClientConnect(){ - Bit8u peernamebuf[16]; - clientsocket = new TCPClientSocket((char*)hostnamebuffer, - (Bit16u)clientport); - if(!clientsocket->isopen) { - LOG_MSG("Serial%d: Connection failed.",idnumber+1); - delete clientsocket; - clientsocket=0; - return; - } - clientsocket->SetSendBufferSize(256); - clientsocket->GetRemoteAddressString(peernamebuf); - // transmit the line status - if(!transparent) setRTSDTR(getRTS(), getDTR()); - - LOG_MSG("Serial%d: Connected to %s",idnumber+1,peernamebuf); - setEvent(SERIAL_POLLING_EVENT, 1); -} - -void CNullModem::Disconnect() { - // it was disconnected; free the socket and restart the server socket - LOG_MSG("Serial%d: Disconnected.",idnumber+1); - delete clientsocket; - clientsocket=0; - setDSR(false); - setCTS(false); - if(serverport) { - serversocket = new TCPServerSocket(serverport); - if(serversocket->isopen) - setEvent(SERIAL_SERVER_POLLING_EVENT, 50); - else delete serversocket; - } -} - -void CNullModem::handleUpperEvent(Bit16u type) { - - switch(type) { - case SERIAL_POLLING_EVENT: { - // periodically check if new data arrived, disconnect - // if required. Add it back. - if(!receiveblock && clientsocket) { - if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ) - &&(!dtrrespect | (dtrrespect&& getDTR()) )) { - rx_retry=0; - Bits rxchar = readChar(); - if(rxchar>=0) { - receiveblock=true; - setEvent(SERIAL_RX_EVENT, bytetime-0.01f); - receiveByte((Bit8u)rxchar); - } - else if(rxchar==-2) Disconnect(); - else setEvent(SERIAL_POLLING_EVENT, 1); - } else { - rx_retry++; - setEvent(SERIAL_POLLING_EVENT, 1); - } - } - break; - } - case SERIAL_RX_EVENT: { - // receive time is up, try to receive another byte. - receiveblock=false; - - if((!(LSR&LSR_RX_DATA_READY_MASK) || rx_retry>=rx_retry_max) - &&(!dtrrespect | (dtrrespect&& getDTR()) ) - ) { - rx_retry=0; - Bits rxchar = readChar(); - if(rxchar>=0) { - receiveblock=true; - setEvent(SERIAL_RX_EVENT, bytetime-0.01f); - receiveByte((Bit8u)rxchar); - } - else if(rxchar==-2) Disconnect(); - else setEvent(SERIAL_POLLING_EVENT, 1); - } else { - setEvent(SERIAL_POLLING_EVENT, 1); - rx_retry++; - } - break; - } - case SERIAL_TX_EVENT: { - ByteTransmitted(); - break; - } - case SERIAL_THR_EVENT: { - ByteTransmitting(); - // actually send it - setEvent(SERIAL_TX_EVENT,bytetime+0.01f); - break; - } - case SERIAL_SERVER_POLLING_EVENT: { - // As long as nothing is connected to out server poll the - // connection. - clientsocket=serversocket->Accept(); - if(clientsocket) { - Bit8u peeripbuf[16]; - clientsocket->GetRemoteAddressString(peeripbuf); - LOG_MSG("Serial%d: A client (%s) has connected.",idnumber+1,peeripbuf); - // new socket found... - clientsocket->SetSendBufferSize(256); - setEvent(SERIAL_POLLING_EVENT, 1); - - // we don't accept further connections - delete serversocket; - serversocket=0; - - // transmit the line status - setRTSDTR(getRTS(), getDTR()); - } else { - // continue looking - setEvent(SERIAL_SERVER_POLLING_EVENT, 50); - } - break; - } - case SERIAL_TX_REDUCTION: { - // Flush the data in the transmitting buffer. - if(clientsocket) clientsocket->FlushBuffer(); - tx_block=false; - break; - } - case SERIAL_NULLMODEM_DTR_EVENT: { - if(getDTR()) ClientConnect(); - else setEvent(SERIAL_NULLMODEM_DTR_EVENT,50); - break; - } - } -} - -/*****************************************************************************/ -/* updatePortConfig is called when emulated app changes the serial port **/ -/* parameters baudrate, stopbits, number of databits, parity. **/ -/*****************************************************************************/ -void CNullModem::updatePortConfig (Bit16u /*divider*/, Bit8u /*lcr*/) { - -} - -void CNullModem::updateMSR () { - -} - -void CNullModem::transmitByte (Bit8u val, bool first) { - - // transmit it later in THR_Event - if(first) { - setEvent(SERIAL_THR_EVENT, bytetime/8); - } else { - //if(clientsocket) clientsocket->Putchar(val); - setEvent(SERIAL_TX_EVENT, bytetime); - } - // disable 0xff escaping when transparent mode is enabled - if (!transparent && (val==0xff)) WriteChar(0xff); - - WriteChar(val); -} - -Bits CNullModem::TelnetEmulation(Bit8u data) { - Bit8u response[3]; - if(telClient.inIAC) { - if(telClient.recCommand) { - if((data != 0) && (data != 1) && (data != 3)) { - LOG_MSG("Serial%d: Unrecognized telnet option %d",COMNUMBER, data); - if(telClient.command>250) { - /* Reject anything we don't recognize */ - response[0]=0xff; - response[1]=252; - response[2]=data; /* We won't do crap! */ - if(clientsocket) clientsocket->SendArray(response, 3); - } - } - switch(telClient.command) { - case 251: /* Will */ - if(data == 0) telClient.binary[TEL_SERVER] = true; - if(data == 1) telClient.echo[TEL_SERVER] = true; - if(data == 3) telClient.supressGA[TEL_SERVER] = true; - break; - case 252: /* Won't */ - if(data == 0) telClient.binary[TEL_SERVER] = false; - if(data == 1) telClient.echo[TEL_SERVER] = false; - if(data == 3) telClient.supressGA[TEL_SERVER] = false; - break; - case 253: /* Do */ - if(data == 0) { - telClient.binary[TEL_CLIENT] = true; - response[0]=0xff; - response[1]=251; - response[2]=0; /* Will do binary transfer */ - if(clientsocket) clientsocket->SendArray(response, 3); - } - if(data == 1) { - telClient.echo[TEL_CLIENT] = false; - response[0]=0xff; - response[1]=252; - response[2]=1; /* Won't echo (too lazy) */ - if(clientsocket) clientsocket->SendArray(response, 3); - } - if(data == 3) { - telClient.supressGA[TEL_CLIENT] = true; - response[0]=0xff; - response[1]=251; - response[2]=3; /* Will Suppress GA */ - if(clientsocket) clientsocket->SendArray(response, 3); - } - break; - case 254: /* Don't */ - if(data == 0) { - telClient.binary[TEL_CLIENT] = false; - response[0]=0xff; - response[1]=252; - response[2]=0; /* Won't do binary transfer */ - if(clientsocket) clientsocket->SendArray(response, 3); - } - if(data == 1) { - telClient.echo[TEL_CLIENT] = false; - response[0]=0xff; - response[1]=252; - response[2]=1; /* Won't echo (fine by me) */ - if(clientsocket) clientsocket->SendArray(response, 3); - } - if(data == 3) { - telClient.supressGA[TEL_CLIENT] = true; - response[0]=0xff; - response[1]=251; - response[2]=3; /* Will Suppress GA (too lazy) */ - if(clientsocket) clientsocket->SendArray(response, 3); - } - break; - default: - LOG_MSG("MODEM: Telnet client sent IAC %d", telClient.command); - break; - } - telClient.inIAC = false; - telClient.recCommand = false; - return -1; //continue; - } else { - if(data==249) { - /* Go Ahead received */ - telClient.inIAC = false; - return -1; //continue; - } - telClient.command = data; - telClient.recCommand = true; - - if((telClient.binary[TEL_SERVER]) && (data == 0xff)) { - /* Binary data with value of 255 */ - telClient.inIAC = false; - telClient.recCommand = false; - return 0xff; - } - } - } else { - if(data == 0xff) { - telClient.inIAC = true; - return -1; - } - return data; - } - return -1; // ??? -} - - -/*****************************************************************************/ -/* setBreak(val) switches break on or off **/ -/*****************************************************************************/ - -void CNullModem::setBreak (bool /*value*/) { - CNullModem::setRTSDTR(getRTS(), getDTR()); -} - -/*****************************************************************************/ -/* updateModemControlLines(mcr) sets DTR and RTS. **/ -/*****************************************************************************/ -void CNullModem::setRTSDTR(bool xrts, bool xdtr) { - if(!transparent) { - Bit8u control[2]; - control[0]=0xff; - control[1]=0x0; - if(xrts) control[1]|=1; - if(xdtr) control[1]|=2; - if(LCR&LCR_BREAK_MASK) control[1]|=4; - if(clientsocket) clientsocket->SendArray(control, 2); - } -} -void CNullModem::setRTS(bool val) { - setRTSDTR(val, getDTR()); -} -void CNullModem::setDTR(bool val) { - setRTSDTR(getRTS(), val); -} -#endif diff --git a/src/hardware/serialport/nullmodem.h b/src/hardware/serialport/nullmodem.h deleted file mode 100644 index 9f860b0..0000000 --- a/src/hardware/serialport/nullmodem.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: nullmodem.h,v 1.2 2007/02/22 08:41:16 qbix79 Exp $ */ - -// include guard -#ifndef DOSBOX_NULLMODEM_WIN32_H -#define DOSBOX_NULLMODEM_WIN32_H - -#include "dosbox.h" - -#if C_MODEM - -#include "misc_util.h" -#include "serialport.h" - -#define SERIAL_SERVER_POLLING_EVENT SERIAL_BASE_EVENT_COUNT+1 -#define SERIAL_TX_REDUCTION SERIAL_BASE_EVENT_COUNT+2 -#define SERIAL_NULLMODEM_DTR_EVENT SERIAL_BASE_EVENT_COUNT+3 -#define SERIAL_NULLMODEM_EVENT_COUNT SERIAL_BASE_EVENT_COUNT+3 - -class CNullModem : public CSerial { -public: - TCPServerSocket* serversocket; - TCPClientSocket* clientsocket; - - CNullModem(Bitu id, CommandLine* cmd); - ~CNullModem(); - bool receiveblock; // It's not a block of data it rather blocks - Bit16u serverport; // we are a server if this is nonzero - Bit16u clientport; - - Bit8u hostnamebuffer[128]; // the name passed to us by the user - - void updatePortConfig(Bit16u divider, Bit8u lcr); - void updateMSR(); - void transmitByte(Bit8u val, bool first); - void setBreak(bool value); - - void setRTSDTR(bool rts, bool dtr); - void setRTS(bool val); - void setDTR(bool val); - void handleUpperEvent(Bit16u type); - - void ClientConnect(); - void Disconnect(); - Bits readChar(); - void WriteChar(Bit8u data); - - bool tx_block; // true while the SERIAL_TX_REDUCTION event - // is pending - - Bitu rx_retry; // counter of retries - - Bitu rx_retry_max; // how many POLL_EVENTS to wait before causing - // a overrun error. - - Bitu tx_gather; // how long to gather tx data before - // sending all of them [milliseconds] - - - bool dtrrespect; // dtr behavior - only send data to the serial - // port when DTR is on - - bool transparent; // if true, don't send 0xff 0xXX to toggle - // DSR/CTS. - - bool telnet; // Do Telnet parsing. - - // Telnet's brain -#define TEL_CLIENT 0 -#define TEL_SERVER 1 - - Bits TelnetEmulation(Bit8u data); - - // Telnet's memory - struct { - bool binary[2]; - bool echo[2]; - bool supressGA[2]; - bool timingMark[2]; - - bool inIAC; - bool recCommand; - Bit8u command; - } telClient; -}; - -#endif // C_MODEM -#endif // include guard diff --git a/src/hardware/serialport/serialdummy.cpp b/src/hardware/serialport/serialdummy.cpp deleted file mode 100644 index de1df0d..0000000 --- a/src/hardware/serialport/serialdummy.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: serialdummy.cpp,v 1.4 2007/01/13 08:35:49 qbix79 Exp $ */ - -#include "dosbox.h" - -#include "setup.h" -#include "serialdummy.h" -#include "serialport.h" - -CSerialDummy::CSerialDummy(Bitu id, CommandLine* cmd):CSerial(id, cmd) { - CSerial::Init_Registers(); - setRI(false); - setDSR(false); - setCD(false); - setCTS(false); - InstallationSuccessful=true; -} - -CSerialDummy::~CSerialDummy() { - // clear events - removeEvent(SERIAL_TX_EVENT); -} - -void CSerialDummy::handleUpperEvent(Bit16u type) { - if(type==SERIAL_TX_EVENT) { - //LOG_MSG("SERIAL_TX_EVENT"); -#ifdef CHECKIT_TESTPLUG - receiveByte(loopbackdata); -#endif - ByteTransmitted(); // tx timeout - } - else if(type==SERIAL_THR_EVENT){ - //LOG_MSG("SERIAL_THR_EVENT"); - ByteTransmitting(); - setEvent(SERIAL_TX_EVENT,bytetime); - } - -} - -/*****************************************************************************/ -/* updatePortConfig is called when emulated app changes the serial port **/ -/* parameters baudrate, stopbits, number of databits, parity. **/ -/*****************************************************************************/ -void CSerialDummy::updatePortConfig(Bit16u divider, Bit8u lcr) { - //LOG_MSG("Serial port at 0x%x: Port params changed: %d Baud", base,dcb.BaudRate); -} - -void CSerialDummy::updateMSR() { -} -void CSerialDummy::transmitByte(Bit8u val, bool first) { - - if(first) setEvent(SERIAL_THR_EVENT, bytetime/10); - else setEvent(SERIAL_TX_EVENT, bytetime); - -#ifdef CHECKIT_TESTPLUG - loopbackdata=val; -#endif -} - -/*****************************************************************************/ -/* setBreak(val) switches break on or off **/ -/*****************************************************************************/ - -void CSerialDummy::setBreak(bool value) { - //LOG_MSG("UART 0x%x: Break toggeled: %d", base, value); -} - -/*****************************************************************************/ -/* setRTSDTR sets the modem control lines **/ -/*****************************************************************************/ -void CSerialDummy::setRTSDTR(bool rts, bool dtr) { - setRTS(rts); - setDTR(dtr); -} -void CSerialDummy::setRTS(bool val) { -#ifdef CHECKIT_TESTPLUG - setCTS(val); -#endif -} -void CSerialDummy::setDTR(bool val) { -#ifdef CHECKIT_TESTPLUG - setDSR(val); - setRI(val); - setCD(val); -#endif -} diff --git a/src/hardware/serialport/serialdummy.h b/src/hardware/serialport/serialdummy.h deleted file mode 100644 index 2616320..0000000 --- a/src/hardware/serialport/serialdummy.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: serialdummy.h,v 1.4 2007/01/13 08:35:49 qbix79 Exp $ */ - -#ifndef INCLUDEGUARD_SERIALDUMMY_H -#define INCLUDEGUARD_SERIALDUMMY_H - -#include "serialport.h" - -//#define CHECKIT_TESTPLUG - -class CSerialDummy : public CSerial { -public: - CSerialDummy(Bitu id, CommandLine* cmd); - ~CSerialDummy(); - - void setRTSDTR(bool rts, bool dtr); - void setRTS(bool val); - void setDTR(bool val); - - void updatePortConfig(Bit16u, Bit8u lcr); - void updateMSR(); - void transmitByte(Bit8u val, bool first); - void setBreak(bool value); - void handleUpperEvent(Bit16u type); - -#ifdef CHECKIT_TESTPLUG - Bit8u loopbackdata; -#endif - -}; - -#endif // INCLUDEGUARD diff --git a/src/hardware/serialport/serialport.cpp b/src/hardware/serialport/serialport.cpp deleted file mode 100644 index 5bf578d..0000000 --- a/src/hardware/serialport/serialport.cpp +++ /dev/null @@ -1,1242 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: serialport.cpp,v 1.11 2009/04/11 08:02:23 qbix79 Exp $ */ - -#include -#include - -#include "dosbox.h" - -#include "inout.h" -#include "pic.h" -#include "setup.h" -#include "bios.h" // SetComPorts(..) -#include "callback.h" // CALLBACK_Idle - -#include "serialport.h" -#include "directserial_win32.h" -#include "directserial_posix.h" -#include "directserial_os2.h" -#include "serialdummy.h" -#include "softmodem.h" -#include "nullmodem.h" - -#include "cpu.h" - - -bool device_COM::Read(Bit8u * data,Bit16u * size) { - // DTR + RTS on - sclass->Write_MCR(0x03); - for (Bit16u i=0; i<*size; i++) - { - Bit8u status; - if(!(sclass->Getchar(&data[i],&status,true,1000))) { - *size=i; - return true; - } - } - return true; -} - - -bool device_COM::Write(Bit8u * data,Bit16u * size) { - // DTR + RTS on - sclass->Write_MCR(0x03); - for (Bit16u i=0; i<*size; i++) - { - if(!(sclass->Putchar(data[i],true,true,1000))) { - *size=i; - sclass->Write_MCR(0x01); - return false; - } - } - // RTS off - sclass->Write_MCR(0x01); - return true; -} - -bool device_COM::Seek(Bit32u * pos,Bit32u type) { - *pos = 0; - return true; -} - -bool device_COM::Close() { - return false; -} - -Bit16u device_COM::GetInformation(void) { - return 0x80A0; -} - -device_COM::device_COM(class CSerial* sc) { - sclass = sc; - SetName(serial_comname[sclass->idnumber]); -} - -device_COM::~device_COM() { -} - - - -// COM1 - COM4 objects -CSerial* serialports[4] ={0,0,0,0}; - -static Bitu SERIAL_Read (Bitu port, Bitu iolen) { - for(Bitu i = 0; i < 4; i++) { - if(serial_baseaddr[i]==(port&0xfff8) && (serialports[i]!=0)) { - Bitu retval=0xff; - switch (port & 0x7) { - case RHR_OFFSET: - retval = serialports[i]->Read_RHR(); - break; - case IER_OFFSET: - retval = serialports[i]->Read_IER(); - break; - case ISR_OFFSET: - retval = serialports[i]->Read_ISR(); - break; - case LCR_OFFSET: - retval = serialports[i]->Read_LCR(); - break; - case MCR_OFFSET: - retval = serialports[i]->Read_MCR(); - break; - case LSR_OFFSET: - retval = serialports[i]->Read_LSR(); - break; - case MSR_OFFSET: - retval = serialports[i]->Read_MSR(); - break; - case SPR_OFFSET: - retval = serialports[i]->Read_SPR(); - break; - } - -#if SERIAL_DEBUG - const char* const dbgtext[]= - {"RHR","IER","ISR","LCR","MCR","LSR","MSR","SPR"}; - if(serialports[i]->dbg_register) - fprintf(serialports[i]->debugfp,"%12.3f read 0x%x from %s.\r\n", - PIC_FullIndex(),retval,dbgtext[port&0x7]); -#endif - - return retval; - } - } - return 0xff; -} -static void SERIAL_Write (Bitu port, Bitu val, Bitu) { - - for(Bitu i = 0; i < 4; i++) { - if(serial_baseaddr[i]==(port&0xfff8) && serialports[i]) { - -#if SERIAL_DEBUG - const char* const dbgtext[]={"THR","IER","FCR","LCR","MCR","!LSR","MSR","SPR"}; - if(serialports[i]->dbg_register) - fprintf(serialports[i]->debugfp,"%12.3f write 0x%x to %s.\r\n", - PIC_FullIndex(),val,dbgtext[port&0x7]); -#endif - - switch (port & 0x7) { - case THR_OFFSET: - serialports[i]->Write_THR (val); - return; - case IER_OFFSET: - serialports[i]->Write_IER (val); - return; - case FCR_OFFSET: - serialports[i]->Write_FCR (val); - return; - case LCR_OFFSET: - serialports[i]->Write_LCR (val); - return; - case MCR_OFFSET: - serialports[i]->Write_MCR (val); - return; - case MSR_OFFSET: - serialports[i]->Write_MSR (val); - return; - case SPR_OFFSET: - serialports[i]->Write_SPR (val); - return; - default: - serialports[i]->Write_reserved (val, port & 0x7); - } - } - } -} - -void CSerial::changeLineProperties() { - // update the event wait time - - float bitlen = (1000.0f/115200.0f)*(float)baud_divider; - bytetime=bitlen*(float)(1+5+1); // startbit + minimum length + stopbit - bytetime+= bitlen*(float)(LCR&0x3); // databits - if(LCR&0x4) bytetime+=bitlen; // stopbit - updatePortConfig (baud_divider, LCR); -} - -static void Serial_EventHandler(Bitu val) { - Bitu serclassid=val&0x3; - if(serialports[serclassid]!=0) - serialports[serclassid]->handleEvent(val>>2); -} - -void CSerial::setEvent(Bit16u type, float duration) { - PIC_AddEvent(Serial_EventHandler,duration,(type<<2)|idnumber); -} - -void CSerial::removeEvent(Bit16u type) { - // TODO - PIC_RemoveSpecificEvents(Serial_EventHandler,(type<<2)|idnumber); -} - -void CSerial::handleEvent(Bit16u type) { - switch(type) { - case SERIAL_TX_LOOPBACK_EVENT: { - -#if SERIAL_DEBUG - if(dbg_serialtraffic) - fprintf(debugfp,loopback_data<0x10? "%12.3f tx 0x%02x (%u) (loopback)\r\n": - "%12.3f tx 0x%02x (%c) (loopback)\r\n", - PIC_FullIndex(),loopback_data, - loopback_data); -#endif - - receiveByte (loopback_data); - ByteTransmitted (); - break; - } - case SERIAL_THR_LOOPBACK_EVENT: { - ByteTransmitting(); - loopback_data=THR; - setEvent(SERIAL_TX_LOOPBACK_EVENT,bytetime); - break; - } - case SERIAL_ERRMSG_EVENT: { - LOG_MSG("Serial%d: Errors occured: "\ - "Framing %d, Parity %d, Overrun %d (IF0:%d), Break %d", COMNUMBER, - framingErrors, parityErrors, overrunErrors, overrunIF0, breakErrors); - errormsg_pending=false; - framingErrors=0; - parityErrors=0; - overrunErrors=0; - overrunIF0=0; - breakErrors=0; - break; - } - default: handleUpperEvent(type); - } -} - -/*****************************************************************************/ -/* Interrupt control routines **/ -/*****************************************************************************/ -void CSerial::rise (Bit8u priority) { -#if SERIAL_DEBUG - if(dbg_interrupt) - { - if(priority&TX_PRIORITY && !(waiting_interrupts&TX_PRIORITY)) - fprintf(debugfp,"%12.3f tx interrupt on.\r\n",PIC_FullIndex()); - - if(priority&RX_PRIORITY && !(waiting_interrupts&RX_PRIORITY)) - fprintf(debugfp,"%12.3f rx interrupt on.\r\n",PIC_FullIndex()); - - if(priority&MSR_PRIORITY && !(waiting_interrupts&MSR_PRIORITY)) - fprintf(debugfp,"%12.3f msr interrupt on.\r\n",PIC_FullIndex()); - - if(priority&ERROR_PRIORITY && !(waiting_interrupts&ERROR_PRIORITY)) - fprintf(debugfp,"%12.3f error interrupt on.\r\n",PIC_FullIndex()); - } -#endif - - waiting_interrupts |= priority; - ComputeInterrupts(); -} - -// clears the pending interrupt, triggers other waiting interrupt -void CSerial::clear (Bit8u priority) { - -#if SERIAL_DEBUG - if(dbg_interrupt) - { - if(priority&TX_PRIORITY && (waiting_interrupts&TX_PRIORITY)) - fprintf(debugfp,"%12.3f tx interrupt off.\r\n",PIC_FullIndex()); - - if(priority&RX_PRIORITY && (waiting_interrupts&RX_PRIORITY)) - fprintf(debugfp,"%12.3f rx interrupt off.\r\n",PIC_FullIndex()); - - if(priority&MSR_PRIORITY && (waiting_interrupts&MSR_PRIORITY)) - fprintf(debugfp,"%12.3f msr interrupt off.\r\n",PIC_FullIndex()); - - if(priority&ERROR_PRIORITY && (waiting_interrupts&ERROR_PRIORITY)) - fprintf(debugfp,"%12.3f error interrupt off.\r\n",PIC_FullIndex()); - } -#endif - - - waiting_interrupts &= (~priority); - ComputeInterrupts(); -} - -void CSerial::ComputeInterrupts () { - - Bitu val = IER & waiting_interrupts; - - if (val & ERROR_PRIORITY) ISR = ISR_ERROR_VAL; - else if (val & RX_PRIORITY) ISR = ISR_RX_VAL; - else if (val & TX_PRIORITY) ISR = ISR_TX_VAL; - else if (val & MSR_PRIORITY) ISR = ISR_MSR_VAL; - else ISR = ISR_CLEAR_VAL; - - if(val && !irq_active) { - irq_active=true; - PIC_ActivateIRQ(irq); - -#if SERIAL_DEBUG - if(dbg_interrupt) - fprintf(debugfp,"%12.3f IRQ%d on.\r\n",PIC_FullIndex(),irq); -#endif - } - - if(!val && irq_active) { - irq_active=false; - PIC_DeActivateIRQ(irq); - -#if SERIAL_DEBUG - if(dbg_interrupt) - fprintf(debugfp,"%12.3f IRQ%d off.\r\n",PIC_FullIndex(),irq); -#endif - } -} - -/*****************************************************************************/ -/* Can a byte be received? **/ -/*****************************************************************************/ -bool CSerial::CanReceiveByte() { - return (LSR & LSR_RX_DATA_READY_MASK) == 0; -} - -/*****************************************************************************/ -/* A byte was received **/ -/*****************************************************************************/ -void CSerial::receiveByte (Bit8u data) { - -#if SERIAL_DEBUG - if(dbg_serialtraffic) - fprintf(debugfp,loopback_data<0x10? "%12.3f rx 0x%02x (%u)\r\n": - "%12.3f rx 0x%02x (%c)\r\n", - PIC_FullIndex(), data, data); -#endif - - if (LSR & LSR_RX_DATA_READY_MASK) { // Overrun error ;o - if(!errormsg_pending) { - errormsg_pending=true; - setEvent(SERIAL_ERRMSG_EVENT,1000); - } - overrunErrors++; - Bitu iflag= GETFLAG(IF); - if(!iflag)overrunIF0++; - -#if SERIAL_DEBUG - if(dbg_serialtraffic) - fprintf(debugfp, "%12.3f rx overrun (IF=%d)\r\n", - PIC_FullIndex(), iflag); -#endif - - LSR |= LSR_OVERRUN_ERROR_MASK; - rise (ERROR_PRIORITY); - } else { - RHR = data; - LSR |= LSR_RX_DATA_READY_MASK; - rise (RX_PRIORITY); - } -} - -/*****************************************************************************/ -/* A line error was received **/ -/*****************************************************************************/ -void CSerial::receiveError (Bit8u errorword) { - - if(!errormsg_pending) { - errormsg_pending=true; - setEvent(SERIAL_ERRMSG_EVENT,1000); - } - if(errorword&LSR_PARITY_ERROR_MASK) { - parityErrors++; - -#if SERIAL_DEBUG - if(dbg_serialtraffic) - fprintf(debugfp, "%12.3f parity error\r\n", - PIC_FullIndex()); -#endif - - } - if(errorword&LSR_FRAMING_ERROR_MASK) { - framingErrors++; - -#if SERIAL_DEBUG - if(dbg_serialtraffic) - fprintf(debugfp, "%12.3f framing error\r\n", - PIC_FullIndex()); -#endif - - } - if(errorword&LSR_RX_BREAK_MASK) { - breakErrors++; - -#if SERIAL_DEBUG - if(dbg_serialtraffic) - fprintf(debugfp, "%12.3f break received\r\n", - PIC_FullIndex()); -#endif - - } - LSR |= errorword; - - rise (ERROR_PRIORITY); -} - -/*****************************************************************************/ -/* ByteTransmitting: Byte has made it from THR to TX. **/ -/*****************************************************************************/ -void CSerial::ByteTransmitting() { - switch(LSR&(LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK)) - { - case LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK: - // bad case there must have been one - case LSR_TX_HOLDING_EMPTY_MASK: - case LSR_TX_EMPTY_MASK: // holding full but workreg empty impossible - LOG_MSG("Internal error in serial port(1)(0x%x).",LSR); - break; - case 0: // THR is empty now. - LSR |= LSR_TX_HOLDING_EMPTY_MASK; - - // trigger interrupt - rise (TX_PRIORITY); - break; - } -} - - -/*****************************************************************************/ -/* ByteTransmitted: When a byte was sent, notify here. **/ -/*****************************************************************************/ -void CSerial::ByteTransmitted () { - switch(LSR&(LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK)) - { - case LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK: - // bad case there must have been one - case LSR_TX_EMPTY_MASK: // holding full but workreg empty impossible - LOG_MSG("Internal error in serial port(2)."); - break; - - case LSR_TX_HOLDING_EMPTY_MASK: // now both are empty - LSR |= LSR_TX_EMPTY_MASK; - break; - - case 0: // now one is empty, send the other one - LSR |= LSR_TX_HOLDING_EMPTY_MASK; - if (loopback) { - loopback_data=THR; - setEvent(SERIAL_TX_LOOPBACK_EVENT, bytetime); - } - else { - - #if SERIAL_DEBUG - if(dbg_serialtraffic) - fprintf(debugfp,THR<0x10? "%12.3f tx 0x%02x (%u) (from THR)\r\n": - "%12.3f tx 0x%02x (%c) (from THR)\r\n", - PIC_FullIndex(),THR, - THR); - #endif - - transmitByte(THR,false); - } - // It's ok here. - rise (TX_PRIORITY); - break; - } -} - -/*****************************************************************************/ -/* Transmit Holding Register, also LSB of Divisor Latch (r/w) **/ -/*****************************************************************************/ -void CSerial::Write_THR (Bit8u data) { - // 0-7 transmit data - - if ((LCR & LCR_DIVISOR_Enable_MASK)) { - // write to DLL - baud_divider&=0xFF00; - baud_divider |= data; - changeLineProperties(); - } else { - // write to THR - clear (TX_PRIORITY); - - switch(LSR&(LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK)) - { - case 0: // both full - overflow -#if SERIAL_DEBUG - if(dbg_serialtraffic) fprintf(debugfp, "%12.3f tx overflow\r\n", - PIC_FullIndex()); -#endif - // overwrite THR - THR = data; - break; - - case LSR_TX_EMPTY_MASK: // holding full but workreg empty impossible - LOG_MSG("Internal error in serial port(3)."); - break; - - case LSR_TX_HOLDING_EMPTY_MASK: // now both are full - LSR &= (~LSR_TX_HOLDING_EMPTY_MASK); - THR = data; - break; - - case LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK: - // both are full until the first delay has passed - THR=data; - LSR &= (~LSR_TX_EMPTY_MASK); - LSR &= (~LSR_TX_HOLDING_EMPTY_MASK); - if(loopback) setEvent(SERIAL_THR_LOOPBACK_EVENT, bytetime/10); - else { - -#if SERIAL_DEBUG - if(dbg_serialtraffic) - fprintf(debugfp,data<0x10? "%12.3f tx 0x%02x (%u)\r\n": - "%12.3f tx 0x%02x (%c)\r\n", - PIC_FullIndex(),data, - data); -#endif - - transmitByte (data,true); - } - - // triggered - // when holding gets empty - // rise (TX_PRIORITY); - break; - } - } -} - - -/*****************************************************************************/ -/* Receive Holding Register, also LSB of Divisor Latch (r/w) **/ -/*****************************************************************************/ -Bitu CSerial::Read_RHR () { - // 0-7 received data - if ((LCR & LCR_DIVISOR_Enable_MASK)) return baud_divider&0xff; - else { - clear (RX_PRIORITY); - LSR &= (~LSR_RX_DATA_READY_MASK); - return RHR; - } -} - -/*****************************************************************************/ -/* Interrupt Enable Register, also MSB of Divisor Latch (r/w) **/ -/*****************************************************************************/ -// Modified by: -// - writing to it. -Bitu CSerial::Read_IER () { - // 0 receive holding register (byte received) - // 1 transmit holding register (byte sent) - // 2 receive line status (overrun, parity error, frame error, break) - // 3 modem status - // 4-7 0 - - if (LCR & LCR_DIVISOR_Enable_MASK) return baud_divider>>8; - else return IER; -} - -void CSerial::Write_IER (Bit8u data) { - if ((LCR & LCR_DIVISOR_Enable_MASK)) { // write to DLM - baud_divider&=0xff; - baud_divider |= ((Bit16u)data)<<8; - changeLineProperties(); - } else { - - IER = data&0xF; - if ((LSR & LSR_TX_HOLDING_EMPTY_MASK) && (IER&TX_PRIORITY)) - waiting_interrupts |= TX_PRIORITY; - - ComputeInterrupts(); - } -} - -/*****************************************************************************/ -/* Interrupt Status Register (r) **/ -/*****************************************************************************/ -// modified by: -// - incoming interrupts -// - loopback mode -Bitu CSerial::Read_ISR () { - // 0 0:interrupt pending 1: no interrupt - // 1-3 identification - // 011 LSR - // 010 RXRDY - // 001 TXRDY - // 000 MSR - // 4-7 0 - - if(IER&Modem_Status_INT_Enable_MASK) updateMSR(); - Bit8u retval = ISR; - - // clear changes ISR!! mean.. - if(ISR==ISR_TX_VAL) clear (TX_PRIORITY); - return retval; -} - -void CSerial::Write_FCR (Bit8u data) { - if((!fifo_warn) && (data&0x1)) { - fifo_warn=true; - LOG_MSG("Serial%d: Warning: Tried to activate FIFO.",COMNUMBER); - } -} - -/*****************************************************************************/ -/* Line Control Register (r/w) **/ -/*****************************************************************************/ -// signal decoder configuration: -// - parity, stopbits, word length -// - send break -// - switch between RHR/THR and baud rate registers -// Modified by: -// - writing to it. -Bitu CSerial::Read_LCR () { - // 0-1 word length - // 2 stop bits - // 3 parity enable - // 4-5 parity type - // 6 set break - // 7 divisor latch enable - return LCR; -} - -void CSerial::Write_LCR (Bit8u data) { - Bit8u lcr_old = LCR; - LCR = data; - if (((data ^ lcr_old) & LCR_PORTCONFIG_MASK) != 0) { - changeLineProperties(); - } - if (((data ^ lcr_old) & LCR_BREAK_MASK) != 0) { - if(!loopback) setBreak ((LCR & LCR_BREAK_MASK)!=0); - else { - // TODO: set loopback break event to reveiveError after - } -#if SERIAL_DEBUG - if(dbg_serialtraffic) - fprintf(debugfp,((LCR & LCR_BREAK_MASK)!=0)? - "%12.3f break on.\r\n": - "%12.3f break off.\r\n", PIC_FullIndex()); -#endif - } -} - -/*****************************************************************************/ -/* Modem Control Register (r/w) **/ -/*****************************************************************************/ -// Set levels of RTS and DTR, as well as loopback-mode. -// Modified by: -// - writing to it. -Bitu CSerial::Read_MCR () { - // 0 -DTR - // 1 -RTS - // 2 -OP1 - // 3 -OP2 - // 4 loopback enable - // 5-7 0 - Bit8u retval=0; - if(dtr) retval|=MCR_DTR_MASK; - if(rts) retval|=MCR_RTS_MASK; - if(op1) retval|=MCR_OP1_MASK; - if(op2) retval|=MCR_OP2_MASK; - if(loopback) retval|=MCR_LOOPBACK_Enable_MASK; - return retval; -} - -void CSerial::Write_MCR (Bit8u data) { - // WARNING: At the time setRTSDTR is called rts and dsr members are still wrong. - - bool temp_dtr = data & MCR_DTR_MASK? true:false; - bool temp_rts = data & MCR_RTS_MASK? true:false; - bool temp_op1 = data & MCR_OP1_MASK? true:false; - bool temp_op2 = data & MCR_OP2_MASK? true:false; - bool temp_loopback = data & MCR_LOOPBACK_Enable_MASK? true:false; - if(loopback!=temp_loopback) { - if(temp_loopback) setRTSDTR(false,false); - else setRTSDTR(temp_rts,temp_dtr); - } - - if (temp_loopback) { // is on: - // DTR->DSR - // RTS->CTS - // OP1->RI - // OP2->CD - if(temp_dtr!=dtr && !d_dsr) { - d_dsr=true; - rise (MSR_PRIORITY); - } - if(temp_rts!=rts && !d_cts) { - d_cts=true; - rise (MSR_PRIORITY); - } - if(temp_op1!=op1 && !d_ri) { - // interrupt only at trailing edge - if(!temp_op1) { - d_ri=true; - rise (MSR_PRIORITY); - } - } - if(temp_op2!=op2 && !d_cd) { - d_cd=true; - rise (MSR_PRIORITY); - } - } else { - // loopback is off - if(temp_rts!=rts) { - // RTS difference - if(temp_dtr!=dtr) { - // both difference - -#if SERIAL_DEBUG - if(dbg_modemcontrol) - { - fprintf(debugfp,temp_rts?"%12.3f RTS on.\r\n": - "%12.3f RTS off.\r\n", PIC_FullIndex()); - fprintf(debugfp,temp_dtr?"%12.3f DTR on.\r\n": - "%12.3f DTR off.\r\n", PIC_FullIndex()); - } -#endif - setRTSDTR(temp_rts, temp_dtr); - } else { - // only RTS - -#if SERIAL_DEBUG - if(dbg_modemcontrol) - fprintf(debugfp,temp_rts?"%12.3f RTS on.\r\n":"%12.3f RTS off.\r\n", PIC_FullIndex()); -#endif - - setRTS(temp_rts); - } - } else if(temp_dtr!=dtr) { - // only DTR -#if SERIAL_DEBUG - if(dbg_modemcontrol) - fprintf(debugfp,temp_dtr?"%12.3f DTR on.\r\n":"%12.3f DTR off.\r\n", PIC_FullIndex()); -#endif - setDTR(temp_dtr); - } - } - dtr=temp_dtr; - rts=temp_rts; - op1=temp_op1; - op2=temp_op2; - loopback=temp_loopback; -} - -/*****************************************************************************/ -/* Line Status Register (r) **/ -/*****************************************************************************/ -// errors, tx registers status, rx register status -// modified by: -// - event from real serial port -// - loopback -Bitu CSerial::Read_LSR () { - Bitu retval = LSR; - LSR &= (~LSR_ERROR_MASK); // clear error bits on read - clear (ERROR_PRIORITY); - return retval; -} - -void CSerial::Write_MSR (Bit8u val) { - d_cts = (val&MSR_dCTS_MASK)?true:false; - d_dsr = (val&MSR_dDSR_MASK)?true:false; - d_cd = (val&MSR_dCD_MASK)?true:false; - d_ri = (val&MSR_dRI_MASK)?true:false; -} - -/*****************************************************************************/ -/* Modem Status Register (r) **/ -/*****************************************************************************/ -// Contains status of the control input lines (CD, RI, DSR, CTS) and -// their "deltas": if level changed since last read delta = 1. -// modified by: -// - real values -// - write operation to MCR in loopback mode -Bitu CSerial::Read_MSR () { - Bit8u retval=0; - - if (loopback) { - - if (rts) retval |= MSR_CTS_MASK; - if (dtr) retval |= MSR_DSR_MASK; - if (op1) retval |= MSR_RI_MASK; - if (op2) retval |= MSR_CD_MASK; - - } else { - - updateMSR(); - if (cd) retval |= MSR_CD_MASK; - if (ri) retval |= MSR_RI_MASK; - if (dsr) retval |= MSR_DSR_MASK; - if (cts) retval |= MSR_CTS_MASK; - - } - // new delta flags - if(d_cd) retval|=MSR_dCD_MASK; - if(d_ri) retval|=MSR_dRI_MASK; - if(d_cts) retval|=MSR_dCTS_MASK; - if(d_dsr) retval|=MSR_dDSR_MASK; - - d_cd = false; - d_ri = false; - d_cts = false; - d_dsr = false; - - clear (MSR_PRIORITY); - return retval; -} - -/*****************************************************************************/ -/* Scratchpad Register (r/w) **/ -/*****************************************************************************/ -// Just a memory register. Not much to do here. -Bitu CSerial::Read_SPR () { - return SPR; -} - -void CSerial::Write_SPR (Bit8u data) { - SPR = data; -} - -/*****************************************************************************/ -/* Write_reserved **/ -/*****************************************************************************/ -void CSerial::Write_reserved (Bit8u data, Bit8u address) { - /*LOG_UART("Serial%d: Write to reserved register, value 0x%x, register %x", - COMNUMBER, data, address);*/ -} - -/*****************************************************************************/ -/* MCR Access: returns cirquit state as boolean. **/ -/*****************************************************************************/ -bool CSerial::getDTR () { - if(loopback) return false; - else return dtr; -} - -bool CSerial::getRTS () { - if(loopback) return false; - else return rts; -} - -/*****************************************************************************/ -/* MSR Access **/ -/*****************************************************************************/ -bool CSerial::getRI () { - return ri; -} - -bool CSerial::getCD () { - return cd; -} - -bool CSerial::getDSR () { - return dsr; -} - -bool CSerial::getCTS () { - return cts; -} - -void CSerial::setRI (bool value) { - if (value != ri) { - -#if SERIAL_DEBUG - if(dbg_modemcontrol) - fprintf(debugfp,value?"%12.3f RI on.\r\n":"%12.3f RI off.\r\n", PIC_FullIndex()); -#endif - // don't change delta when in loopback mode - ri=value; - if(!loopback) { - if(value==false) d_ri=true; - rise (MSR_PRIORITY); - } - } - //else no change -} -void CSerial::setDSR (bool value) { - if (value != dsr) { -#if SERIAL_DEBUG - if(dbg_modemcontrol) - fprintf(debugfp,value?"%12.3f DSR on.\r\n":"%12.3f DSR off.\r\n", PIC_FullIndex()); -#endif - // don't change delta when in loopback mode - dsr=value; - if(!loopback) { - d_dsr=true; - rise (MSR_PRIORITY); - } - } - //else no change -} -void CSerial::setCD (bool value) { - if (value != cd) { -#if SERIAL_DEBUG - if(dbg_modemcontrol) - fprintf(debugfp,value?"%12.3f CD on.\r\n":"%12.3f CD off.\r\n", PIC_FullIndex()); -#endif - // don't change delta when in loopback mode - cd=value; - if(!loopback) { - d_cd=true; - rise (MSR_PRIORITY); - } - } - //else no change -} -void CSerial::setCTS (bool value) { - if (value != cts) { -#if SERIAL_DEBUG - if(dbg_modemcontrol) - fprintf(debugfp,value?"%12.3f CTS on.\r\n":"%12.3f CTS off.\r\n", PIC_FullIndex()); -#endif - // don't change delta when in loopback mode - cts=value; - if(!loopback) { - d_cts=true; - rise (MSR_PRIORITY); - } - } - //else no change -} - -/*****************************************************************************/ -/* Initialisation **/ -/*****************************************************************************/ -void CSerial::Init_Registers () { - // The "power on" settings - irq_active=false; - waiting_interrupts = 0x0; - - Bit32u initbps = 9600; - Bit8u bytesize = 8; - char parity = 'N'; - - Bit8u lcrresult = 0; - Bit16u baudresult = 0; - - RHR = 0; - THR = 0; - IER = 0; - ISR = 0x1; - LCR = 0; - //MCR = 0xff; - loopback = true; - dtr=true; - rts=true; - op1=true; - op2=true; - - - LSR = 0x60; - d_cts = true; - d_dsr = true; - d_ri = true; - d_cd = true; - cts = true; - dsr = true; - ri = true; - cd = true; - - SPR = 0xFF; - - baud_divider=0x0; - - // make lcr: byte size, parity, stopbits, baudrate - - if (bytesize == 5) - lcrresult |= LCR_DATABITS_5; - else if (bytesize == 6) - lcrresult |= LCR_DATABITS_6; - else if (bytesize == 7) - lcrresult |= LCR_DATABITS_7; - else - lcrresult |= LCR_DATABITS_8; - - switch(parity) - { - case 'N': - case 'n': - lcrresult |= LCR_PARITY_NONE; - break; - case 'O': - case 'o': - lcrresult |= LCR_PARITY_ODD; - break; - case 'E': - case 'e': - lcrresult |= LCR_PARITY_EVEN; - break; - case 'M': - case 'm': - lcrresult |= LCR_PARITY_MARK; - break; - case 'S': - case 's': - lcrresult |= LCR_PARITY_SPACE; - break; - } - - // baudrate - if (initbps > 0) - baudresult = (Bit16u) (115200 / initbps); - else - baudresult = 12; // = 9600 baud - - Write_MCR (0); - Write_LCR (LCR_DIVISOR_Enable_MASK); - Write_THR ((Bit8u) baudresult & 0xff); - Write_IER ((Bit8u) (baudresult >> 8)); - Write_LCR (lcrresult); - updateMSR(); - Read_MSR(); -} - -CSerial::CSerial(Bitu id, CommandLine* cmd) { - -#if SERIAL_DEBUG - dbg_serialtraffic = cmd->FindExist("dbgtr", false); - dbg_modemcontrol = cmd->FindExist("dbgmd", false); - dbg_register = cmd->FindExist("dbgreg", false); - dbg_interrupt = cmd->FindExist("dbgirq", false); - dbg_aux = cmd->FindExist("dbgaux", false); - - - if(dbg_serialtraffic|dbg_modemcontrol|dbg_register|dbg_interrupt|dbg_aux) - debugfp=OpenCaptureFile("serlog",".serlog.txt"); - else debugfp=0; - -#endif - - - - idnumber=id; - mydosdevice=new device_COM(this); - DOS_AddDevice(mydosdevice); - Bit16u base = serial_baseaddr[id]; - fifo_warn=false; - - errormsg_pending=false; - framingErrors=0; - parityErrors=0; - overrunErrors=0; - overrunIF0=0; - breakErrors=0; - - // find the IRQ - irq = serial_defaultirq[id]; - getBituSubstring("irq:",&irq, cmd); - if (irq < 2 || irq > 15) irq = serial_defaultirq[id]; - - - for (Bitu i = 0; i <= 7; i++) { - WriteHandler[i].Install (i + base, SERIAL_Write, IO_MB); - ReadHandler[i].Install (i + base, SERIAL_Read, IO_MB); - } - -#if SERIAL_DEBUG - if(debugfp) fprintf(debugfp,"COM%d: BASE %3x, IRQ %d\r\n\r\n", - COMNUMBER,base,irq); -#endif -} - -bool CSerial::getBituSubstring(const char* name,Bitu* data, CommandLine* cmd) { - std::string tmpstring; - if(!(cmd->FindStringBegin(name,tmpstring,false))) return false; - const char* tmpchar=tmpstring.c_str(); - if(sscanf(tmpchar,"%u",data)!=1) return false; - return true; -} - -CSerial::~CSerial(void) { - DOS_DelDevice(mydosdevice); - for(Bitu i = 0; i <= SERIAL_BASE_EVENT_COUNT; i++) - removeEvent(i); -} -bool CSerial::Getchar(Bit8u* data, Bit8u* lsr, bool wait_dsr, Bitu timeout) { - - double starttime=PIC_FullIndex(); - // wait for it to become empty - // wait for DSR on - if(wait_dsr) { - while((!(Read_MSR()&0x20))&&(starttime>PIC_FullIndex()-timeout)) - CALLBACK_Idle(); - if(!(starttime>PIC_FullIndex()-timeout)) { - #if SERIAL_DEBUG -if(dbg_aux) - fprintf(debugfp,"%12.3f Getchar status timeout: MSR 0x%x\r\n", PIC_FullIndex(),Read_MSR()); -#endif - return false; - } - } - // wait for a byte to arrive - while((!((*lsr=Read_LSR())&0x1))&&(starttime>PIC_FullIndex()-timeout)) - CALLBACK_Idle(); - - if(!(starttime>PIC_FullIndex()-timeout)) { - #if SERIAL_DEBUG -if(dbg_aux) - fprintf(debugfp,"%12.3f Getchar data timeout: MSR 0x%x\r\n", PIC_FullIndex(),Read_MSR()); -#endif - return false; - } - - - *data=Read_RHR(); - -#if SERIAL_DEBUG - if(dbg_aux) - fprintf(debugfp,"%12.3f API read success: 0x%x\r\n", PIC_FullIndex(),*data); -#endif - - return true; -} - - -bool CSerial::Putchar(Bit8u data, bool wait_dsr, bool wait_cts, Bitu timeout) { - - double starttime=PIC_FullIndex(); - //Bit16u starttime= - // wait for it to become empty - while(!(LSR&0x20)) { - CALLBACK_Idle(); - } - // wait for DSR+CTS on - if(wait_dsr||wait_cts) { - if(wait_dsr||wait_cts) { - while(((Read_MSR()&0x30)!=0x30)&&(starttime>PIC_FullIndex()-timeout)) - CALLBACK_Idle(); - } else if(wait_dsr) { - while(!(Read_MSR()&0x20)&&(starttime>PIC_FullIndex()-timeout)) - CALLBACK_Idle(); - } else if(wait_cts) { - while(!(Read_MSR()&0x10)&&(starttime>PIC_FullIndex()-timeout)) - CALLBACK_Idle(); - - } - if(!(starttime>PIC_FullIndex()-timeout)) { -#if SERIAL_DEBUG - if(dbg_aux) - fprintf(debugfp,"%12.3f Putchar timeout: MSR 0x%x\r\n", - PIC_FullIndex(),Read_MSR()); -#endif - return false; - } - } - Write_THR(data); - -#if SERIAL_DEBUG - if(dbg_aux) - fprintf(debugfp,"%12.3f API write success: 0x%x\r\n", PIC_FullIndex(),data); -#endif - - return true; -} - -class SERIALPORTS:public Module_base { -public: - SERIALPORTS (Section * configuration):Module_base (configuration) { - Bit16u biosParameter[4] = { 0, 0, 0, 0 }; - Section_prop *section = static_cast (configuration); - - char s_property[] = "serialx"; - for(Bitu i = 0; i < 4; i++) { - // get the configuration property - s_property[6] = '1' + i; - Prop_multival* p = section->Get_multival(s_property); - std::string type = p->GetSection()->Get_string("type"); - CommandLine cmd(0,p->GetSection()->Get_string("parameters")); - - // detect the type - if (type=="dummy") { - serialports[i] = new CSerialDummy (i, &cmd); - } -#ifdef DIRECTSERIAL_AVAILIBLE - else if (type=="directserial") { - serialports[i] = new CDirectSerial (i, &cmd); - if (!serialports[i]->InstallationSuccessful) { - // serial port name was wrong or already in use - delete serialports[i]; - serialports[i] = NULL; - } - } -#endif -#if C_MODEM - else if(type=="modem") { - serialports[i] = new CSerialModem (i, &cmd); - if (!serialports[i]->InstallationSuccessful) { - delete serialports[i]; - serialports[i] = NULL; - } - } - else if(type=="nullmodem") { - serialports[i] = new CNullModem (i, &cmd); - if (!serialports[i]->InstallationSuccessful) { - delete serialports[i]; - serialports[i] = NULL; - } - } -#endif - else if(type=="disabled") { - serialports[i] = NULL; - } else { - serialports[i] = NULL; - LOG_MSG("Invalid type for serial%d",i+1); - } - if(serialports[i]) biosParameter[i] = serial_baseaddr[i]; - } // for 1-4 - BIOS_SetComPorts (biosParameter); - } - - ~SERIALPORTS () { - for (Bitu i = 0; i < 4; i++) - if (serialports[i]) { - delete serialports[i]; - serialports[i] = 0; - } - } -}; - -static SERIALPORTS *testSerialPortsBaseclass; - -void SERIAL_Destroy (Section * sec) { - delete testSerialPortsBaseclass; - testSerialPortsBaseclass = NULL; -} - -void SERIAL_Init (Section * sec) { - // should never happen - if (testSerialPortsBaseclass) delete testSerialPortsBaseclass; - testSerialPortsBaseclass = new SERIALPORTS (sec); - sec->AddDestroyFunction (&SERIAL_Destroy, true); -} diff --git a/src/hardware/serialport/softmodem.cpp b/src/hardware/serialport/softmodem.cpp deleted file mode 100644 index e349e87..0000000 --- a/src/hardware/serialport/softmodem.cpp +++ /dev/null @@ -1,803 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: softmodem.cpp,v 1.10 2009/01/14 22:24:39 qbix79 Exp $ */ - -#include "dosbox.h" - -#if C_MODEM - -#include -#include -#include - -#include "support.h" -#include "serialport.h" -#include "softmodem.h" -#include "misc_util.h" - -//#include "mixer.h" - - -CSerialModem::CSerialModem(Bitu id, CommandLine* cmd):CSerial(id, cmd) { - InstallationSuccessful=false; - connected=false; - - rqueue=new CFifo(MODEM_BUFFER_QUEUE_SIZE); - tqueue=new CFifo(MODEM_BUFFER_QUEUE_SIZE); - - // Default to direct null modem connection. Telnet mode interprets IAC codes - telnetmode = false; - - // Initialize the sockets and setup the listening port - listenport = 23; - waitingclientsocket=0; - clientsocket = 0; - serversocket = 0; - getBituSubstring("listenport:", &listenport, cmd); - - // TODO: Fix dialtones if requested - //mhd.chan=MIXER_AddChannel((MIXER_MixHandler)this->MODEM_CallBack,8000,"MODEM"); - //MIXER_Enable(mhd.chan,false); - //MIXER_SetMode(mhd.chan,MIXER_16MONO); - - CSerial::Init_Registers(); - Reset(); // reset calls EnterIdleState - - setEvent(SERIAL_POLLING_EVENT,1); - InstallationSuccessful=true; -} - -CSerialModem::~CSerialModem() { - if(serversocket) delete serversocket; - if(clientsocket) delete clientsocket; - if(waitingclientsocket) delete waitingclientsocket; - - delete rqueue; - delete tqueue; - - // remove events - for(Bitu i = SERIAL_BASE_EVENT_COUNT+1; i <= SERIAL_MODEM_EVENT_COUNT; i++) - removeEvent(i); -} - -void CSerialModem::handleUpperEvent(Bit16u type) { - switch(type) - { - case SERIAL_RX_EVENT: - { - break; - } - case MODEM_TX_EVENT: - { - if(tqueue->left()) { - tqueue->addb(waiting_tx_character); - if(tqueue->left() < 2) { - CSerial::setCTS(false); - } - } else { - static Bits lcount=0; - if (lcount<1000) { - lcount++; - LOG_MSG("MODEM: TX Buffer overflow!"); - } - } - ByteTransmitted(); - - break; - } - case SERIAL_POLLING_EVENT: - { - Timer2(); - setEvent(SERIAL_POLLING_EVENT,1); - break; - } - - case MODEM_RING_EVENT: - { - break; - } - } -} - -void CSerialModem::SendLine(const char *line) { - rqueue->addb(0xd); - rqueue->addb(0xa); - rqueue->adds((Bit8u *)line,strlen(line)); - rqueue->addb(0xd); - rqueue->addb(0xa); -} - -// only for numbers < 1000... -void CSerialModem::SendNumber(Bitu val) { - rqueue->addb(0xd); - rqueue->addb(0xa); - - rqueue->addb(val/100+'0'); - val = val%100; - rqueue->addb(val/10+'0'); - val = val%10; - rqueue->addb(val+'0'); - - rqueue->addb(0xd); - rqueue->addb(0xa); -} - -void CSerialModem::SendRes(ResTypes response) { - char const * string;Bitu code; - switch (response) - { - case ResNONE: return; - case ResOK: string="OK"; code=0; break; - case ResERROR: string="ERROR"; code=4; break; - case ResRING: string="RING"; code=2; break; - case ResNODIALTONE: string="NO DIALTONE"; code=6; break; - case ResNOCARRIER: string="NO CARRIER" ;code=3; break; - case ResCONNECT: string="CONNECT 57600"; code=1; break; - } - - if(doresponse!=1) { - if(doresponse==2 && (response==ResRING || - response == ResCONNECT || response==ResNOCARRIER)) return; - if(numericresponse) SendNumber(code); - else SendLine(string); - - //if(CSerial::CanReceiveByte()) // very fast response - // if(rqueue->inuse() && CSerial::getRTS()) - // { Bit8u rbyte =rqueue->getb(); - // CSerial::receiveByte(rbyte); - // LOG_MSG("Modem: sending byte %2x back to UART2",rbyte); - // } - - LOG_MSG("Modem response: %s", string); - } -} - -bool CSerialModem::Dial(char * host) { - - // Scan host for port - Bit16u port; - char * hasport=strrchr(host,':'); - if (hasport) { - *hasport++=0; - port=(Bit16u)atoi(hasport); - } - else port=MODEM_DEFAULT_PORT; - // Resolve host we're gonna dial - LOG_MSG("Connecting to host %s port %d",host,port); - clientsocket = new TCPClientSocket(host, port); - if(!clientsocket->isopen) { - delete clientsocket; - clientsocket=0; - LOG_MSG("Failed to connect."); - SendRes(ResNOCARRIER); - EnterIdleState(); - return false; - } else { - EnterConnectedState(); - return true; - } -} - -void CSerialModem::AcceptIncomingCall(void) { - if(waitingclientsocket) { - clientsocket=waitingclientsocket; - waitingclientsocket=0; - EnterConnectedState(); - } else { - EnterIdleState(); - } -} - -Bitu CSerialModem::ScanNumber(char * & scan) { - Bitu ret=0; - while (char c=*scan) { - if (c>='0' && c<='9') { - ret*=10; - ret+=c-'0'; - scan++; - } else break; - } - return ret; -} - -void CSerialModem::Reset(){ - EnterIdleState(); - cmdpos = 0; - cmdbuf[0]=0; - oldDTRstate = getDTR(); - flowcontrol = 0; - plusinc = 0; - if(clientsocket) { - delete clientsocket; - clientsocket=0; - } - memset(®,0,sizeof(reg)); - reg[MREG_AUTOANSWER_COUNT]=0; // no autoanswer - reg[MREG_RING_COUNT] = 1; - reg[MREG_ESCAPE_CHAR]='+'; - reg[MREG_CR_CHAR]='\r'; - reg[MREG_LF_CHAR]='\n'; - reg[MREG_BACKSPACE_CHAR]='\b'; - - cmdpause = 0; - echo = true; - doresponse = 0; - numericresponse = false; - - /* Default to direct null modem connection. Telnet mode interprets IAC codes */ - telnetmode = false; -} - -void CSerialModem::EnterIdleState(void){ - connected=false; - ringing=false; - - if(clientsocket) { - delete clientsocket; - clientsocket=0; - } - - if(waitingclientsocket) { // clear current incoming socket - delete waitingclientsocket; - waitingclientsocket=0; - } - // get rid of everything - if(serversocket) { - while(waitingclientsocket=serversocket->Accept()) - delete waitingclientsocket; - } else if (listenport) { - - serversocket=new TCPServerSocket(listenport); - if(!serversocket->isopen) { - LOG_MSG("Serial%d: Modem could not open TCP port %d.",COMNUMBER,listenport); - delete serversocket; - serversocket=0; - } else LOG_MSG("Serial%d: Modem listening on port %d...",COMNUMBER,listenport); - } - waitingclientsocket=0; - - commandmode = true; - CSerial::setCD(false); - CSerial::setRI(false); - CSerial::setDSR(true); - CSerial::setCTS(true); - tqueue->clear(); -} - -void CSerialModem::EnterConnectedState(void) { - if(serversocket) { - // we don't accept further calls - delete serversocket; - serversocket=0; - } - SendRes(ResCONNECT); - commandmode = false; - memset(&telClient, 0, sizeof(telClient)); - connected = true; - ringing = false; - CSerial::setCD(true); - CSerial::setRI(false); -} - -void CSerialModem::DoCommand() { - cmdbuf[cmdpos] = 0; - cmdpos = 0; //Reset for next command - upcase(cmdbuf); - LOG_MSG("Command sent to modem: ->%s<-\n", cmdbuf); - /* Check for empty line, stops dialing and autoanswer */ - if (!cmdbuf[0]) { - reg[0]=0; // autoanswer off - return; - // } - //else { - //MIXER_Enable(mhd.chan,false); - // dialing = false; - // SendRes(ResNOCARRIER); - // goto ret_none; - // } - } - /* AT command set interpretation */ - - if ((cmdbuf[0] != 'A') || (cmdbuf[1] != 'T')) { - SendRes(ResERROR); - return; - } - - if (strstr(cmdbuf,"NET0")) { - telnetmode = false; - SendRes(ResOK); - return; - } - else if (strstr(cmdbuf,"NET1")) { - telnetmode = true; - SendRes(ResOK); - return; - } - - char * scanbuf; - scanbuf=&cmdbuf[2]; - char chr; - Bitu num; - while (chr=*scanbuf++) { - switch (chr) { - case 'D': // Dial - { - char * foundstr=&scanbuf[0]; - if (*foundstr=='T' || *foundstr=='P') foundstr++; - // Small protection against empty line and long string - if ((!foundstr[0]) || (strlen(foundstr)>100)) { - SendRes(ResERROR); - return; - } - char* helper; - // scan for and remove spaces; weird bug: with leading spaces in the string, - // SDLNet_ResolveHost will return no error but not work anyway (win) - while(foundstr[0]==' ') foundstr++; - helper=foundstr; - helper+=strlen(foundstr); - while(helper[0]==' ') { - helper[0]=0; - helper--; - } - if (strlen(foundstr) >= 12) { - // Check if supplied parameter only consists of digits - bool isNum = true; - for (Bitu i=0; i '9') - isNum = false; - if (isNum) { - // Parameter is a number with at least 12 digits => this cannot - // be a valid IP/name - // Transform by adding dots - char buffer[128]; - Bitu j = 0; - for (Bitu i=0; i12) - buffer[j++] = ':'; - } - buffer[j] = 0; - foundstr = buffer; - } - } - Dial(foundstr); - return; - } - case 'I': //Some strings about firmware - switch (num=ScanNumber(scanbuf)) { - case 3:SendLine("DosBox Emulated Modem Firmware V1.00");break; - case 4:SendLine("Modem compiled for DosBox version " VERSION);break; - };break; - case 'E': //Echo on/off - switch (num=ScanNumber(scanbuf)) { - case 0:echo = false;break; - case 1:echo = true;break; - };break; - case 'V': - switch (num=ScanNumber(scanbuf)) { - case 0:numericresponse = true;break; - case 1:numericresponse = false;break; - };break; - case 'H': //Hang up - switch (num=ScanNumber(scanbuf)) { - case 0: - if (connected) { - SendRes(ResNOCARRIER); - EnterIdleState(); - return; - } - //Else return ok - };break; - case 'O': //Return to data mode - switch (num=ScanNumber(scanbuf)) - { - case 0: - if (clientsocket) { - commandmode = false; - return; - } else { - SendRes(ResERROR); - return; - } - };break; - case 'T': //Tone Dial - case 'P': //Pulse Dial - break; - case 'M': //Monitor - case 'L': //Volume - ScanNumber(scanbuf); - break; - case 'A': //Answer call - if (waitingclientsocket) { - AcceptIncomingCall(); - } else { - SendRes(ResERROR); - return; - } - return; - case 'Z': //Reset and load profiles - { - // scan the number away, if any - ScanNumber(scanbuf); - if (clientsocket/*socket*/) SendRes(ResNOCARRIER); - Reset(); - break; - } - case ' ': //Space just skip - break; - case 'Q': // Response options - { // 0 = all on, 1 = all off, - // 2 = no ring and no connect/carrier in answermode - Bitu val = ScanNumber(scanbuf); - if(!(val>2)) { - doresponse=val; - break; - } else { - SendRes(ResERROR); - return; - } - } - case 'S': //Registers - { - Bitu index=ScanNumber(scanbuf); - if(index>=SREGS) { - SendRes(ResERROR); - return; //goto ret_none; - } - - while(scanbuf[0]==' ') scanbuf++; // skip spaces - - if(scanbuf[0]=='=') { // set register - scanbuf++; - while(scanbuf[0]==' ') scanbuf++; // skip spaces - Bitu val = ScanNumber(scanbuf); - reg[index]=val; - break; - } - else if(scanbuf[0]=='?') { // get register - SendNumber(reg[index]); - scanbuf++; - break; - } - //else LOG_MSG("print reg %d with %d",index,reg[index]); - } - break; - case '&': - { - if(scanbuf[0]!=0) { - char ch = scanbuf[0]; - scanbuf++; - switch(ch) { - case 'K': - { - Bitu val = ScanNumber(scanbuf); - if(val<5) flowcontrol=val; - else { - SendRes(ResERROR); - return; - } - break; - } - default: - { - scanbuf++; - LOG_MSG("Modem: Unhandled command: &%c%d",ch,ScanNumber(scanbuf)); - break; - } - } - } else { - SendRes(ResERROR); - return; - } - } - break; - - default: - LOG_MSG("Modem: Unhandled command: %c%d",chr,ScanNumber(scanbuf)); - } - } - - SendRes(ResOK); - return; - } - -void CSerialModem::TelnetEmulation(Bit8u * data, Bitu size) { - Bitu i; - Bit8u c; - for(i=0;i250) { - /* Reject anything we don't recognize */ - tqueue->addb(0xff); - tqueue->addb(252); - tqueue->addb(c); /* We won't do crap! */ - } - } - switch(telClient.command) { - case 251: /* Will */ - if(c == 0) telClient.binary[TEL_SERVER] = true; - if(c == 1) telClient.echo[TEL_SERVER] = true; - if(c == 3) telClient.supressGA[TEL_SERVER] = true; - break; - case 252: /* Won't */ - if(c == 0) telClient.binary[TEL_SERVER] = false; - if(c == 1) telClient.echo[TEL_SERVER] = false; - if(c == 3) telClient.supressGA[TEL_SERVER] = false; - break; - case 253: /* Do */ - if(c == 0) { - telClient.binary[TEL_CLIENT] = true; - tqueue->addb(0xff); - tqueue->addb(251); - tqueue->addb(0); /* Will do binary transfer */ - } - if(c == 1) { - telClient.echo[TEL_CLIENT] = false; - tqueue->addb(0xff); - tqueue->addb(252); - tqueue->addb(1); /* Won't echo (too lazy) */ - } - if(c == 3) { - telClient.supressGA[TEL_CLIENT] = true; - tqueue->addb(0xff); - tqueue->addb(251); - tqueue->addb(3); /* Will Suppress GA */ - } - break; - case 254: /* Don't */ - if(c == 0) { - telClient.binary[TEL_CLIENT] = false; - tqueue->addb(0xff); - tqueue->addb(252); - tqueue->addb(0); /* Won't do binary transfer */ - } - if(c == 1) { - telClient.echo[TEL_CLIENT] = false; - tqueue->addb(0xff); - tqueue->addb(252); - tqueue->addb(1); /* Won't echo (fine by me) */ - } - if(c == 3) { - telClient.supressGA[TEL_CLIENT] = true; - tqueue->addb(0xff); - tqueue->addb(251); - tqueue->addb(3); /* Will Suppress GA (too lazy) */ - } - break; - default: - LOG_MSG("MODEM: Telnet client sent IAC %d", telClient.command); - break; - } - telClient.inIAC = false; - telClient.recCommand = false; - continue; - } else { - if(c==249) { - /* Go Ahead received */ - telClient.inIAC = false; - continue; - } - telClient.command = c; - telClient.recCommand = true; - - if((telClient.binary[TEL_SERVER]) && (c == 0xff)) { - /* Binary data with value of 255 */ - telClient.inIAC = false; - telClient.recCommand = false; - rqueue->addb(0xff); - continue; - } - } - } else { - if(c == 0xff) { - telClient.inIAC = true; - continue; - } - rqueue->addb(c); - } - } -} - -void CSerialModem::Timer2(void) { - - unsigned long args = 1; - bool sendbyte = true; - Bitu usesize; - Bit8u txval; - Bitu txbuffersize =0; - - // check for bytes to be sent to port - if(CSerial::CanReceiveByte()) - if(rqueue->inuse() && (CSerial::getRTS()||(flowcontrol!=3))) { - Bit8u rbyte = rqueue->getb(); - //LOG_MSG("Modem: sending byte %2x back to UART3",rbyte); - CSerial::receiveByte(rbyte); - } - // Check for eventual break command - if (!commandmode) cmdpause++; - // Handle incoming data from serial port, read as much as available - CSerial::setCTS(true); // buffer will get 'emptier', new data can be received - while (tqueue->inuse()) { - txval = tqueue->getb(); - if (commandmode) { - if (echo) { - rqueue->addb(txval); - //LOG_MSG("Echo back to queue: %x",txval); - } - if (txval==0xa) continue; //Real modem doesn't seem to skip this? - else if (txval==0x8 && (cmdpos > 0)) --cmdpos; // backspace - else if (txval==0xd) DoCommand(); // return - else if (txval != '+') { - if(cmdpos<99) { - cmdbuf[cmdpos] = txval; - cmdpos++; - } - } - } - else {// + character - // 1000 ticks have passed, can check for pause command - if (cmdpause > 1000) { - if(txval ==reg[MREG_ESCAPE_CHAR]) // + - { - plusinc++; - if(plusinc>=3) { - LOG_MSG("Modem: Entering command mode(escape sequence)"); - commandmode = true; - SendRes(ResOK); - plusinc = 0; - } - sendbyte=false; - } else { - plusinc=0; - } - // If not a special pause command, should go for bigger blocks to send - } - tmpbuf[txbuffersize] = txval; - txbuffersize++; - } - } // while loop - - if (clientsocket && sendbyte && txbuffersize) { - // down here it saves a lot of network traffic - clientsocket->SendArray(tmpbuf,txbuffersize); - //TODO error testing - } - // Handle incoming to the serial port - if(!commandmode && clientsocket && rqueue->left()) { - usesize = rqueue->left(); - if (usesize>16) usesize=16; - if(!clientsocket->ReceiveArray(tmpbuf, &usesize)) { - SendRes(ResNOCARRIER); - EnterIdleState(); - } else if(usesize) { - // LOG_MSG("rcv:%d", result); - // Filter telnet commands - if(telnetmode) TelnetEmulation(tmpbuf, usesize); - else rqueue->adds(tmpbuf,usesize); - cmdpause = 0; - } - } - // Check for incoming calls - if (!connected && !waitingclientsocket && serversocket) { - waitingclientsocket=serversocket->Accept(); - if(waitingclientsocket) { - if(!CSerial::getDTR()) { - // accept no calls with DTR off; TODO: AT &Dn - EnterIdleState(); - } else { - ringing=true; - SendRes(ResRING); - CSerial::setRI(!CSerial::getRI()); - //MIXER_Enable(mhd.chan,true); - ringtimer = 3000; - reg[1] = 0; //Reset ring counter reg - } - } - } - if (ringing) { - if (ringtimer <= 0) { - reg[1]++; - if ((reg[0]>0) && (reg[0]>=reg[1])) { - AcceptIncomingCall(); - return; - } - SendRes(ResRING); - CSerial::setRI(!CSerial::getRI()); - - //MIXER_Enable(mhd.chan,true); - ringtimer = 3000; - } - --ringtimer; - } -} - - -//TODO -void CSerialModem::RXBufferEmpty() { - // see if rqueue has some more bytes - if(rqueue->inuse() && (CSerial::getRTS()||(flowcontrol!=3))){ - Bit8u rbyte = rqueue->getb(); - //LOG_MSG("Modem: sending byte %2x back to UART1",rbyte); - CSerial::receiveByte(rbyte); - } -} - -void CSerialModem::transmitByte(Bit8u val, bool first) { - waiting_tx_character=val; - setEvent(MODEM_TX_EVENT, bytetime); // TX event - if(first) ByteTransmitting(); - //LOG_MSG("MODEM: Byte %x to be transmitted",val); -} - -void CSerialModem::updatePortConfig(Bit16u, Bit8u lcr) { -// nothing to do here right? -} - -void CSerialModem::updateMSR() { - // think it is not needed -} - -void CSerialModem::setBreak(bool) { - // TODO: handle this -} - -void CSerialModem::setRTSDTR(bool rts, bool dtr) { - setDTR(dtr); -} -void CSerialModem::setRTS(bool val) { - -} -void CSerialModem::setDTR(bool val) { - if(!val && connected) { - // If DTR goes low, hang up. - SendRes(ResNOCARRIER); - EnterIdleState(); - LOG_MSG("Modem: Hang up due to dropped DTR."); - } -} -/* -void CSerialModem::updateModemControlLines() { - //bool txrdy=tqueue->left(); - //if(CSerial::getRTS() && txrdy) CSerial::setCTS(true); - //else CSerial::setCTS(tqueue->left()); - - // If DTR goes low, hang up. - if(connected) - if(oldDTRstate) - if(!getDTR()) { - SendRes(ResNOCARRIER); - EnterIdleState(); - LOG_MSG("Modem: Hang up due to dropped DTR."); - } - - oldDTRstate = getDTR(); -} -*/ - -#endif - diff --git a/src/hardware/serialport/softmodem.h b/src/hardware/serialport/softmodem.h deleted file mode 100644 index 3bac11b..0000000 --- a/src/hardware/serialport/softmodem.h +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: softmodem.h,v 1.9 2009/04/11 08:02:23 qbix79 Exp $ */ - -#ifndef DOSBOX_SERIALMODEM_H -#define DOSBOX_SERIALMODEM_H - -#include "dosbox.h" -#if C_MODEM -#include "serialport.h" - -#include "misc_util.h" - -#define MODEMSPD 57600 -#define SREGS 100 - -//If it's too high you overflow terminal clients buffers i think -#define MODEM_BUFFER_QUEUE_SIZE 1024 - -#define MODEM_DEFAULT_PORT 23 - -#define MODEM_TX_EVENT SERIAL_BASE_EVENT_COUNT + 1 -#define MODEM_RX_POLLING SERIAL_BASE_EVENT_COUNT + 2 -#define MODEM_RING_EVENT SERIAL_BASE_EVENT_COUNT + 3 -#define SERIAL_MODEM_EVENT_COUNT SERIAL_BASE_EVENT_COUNT+3 - - -enum ResTypes { - ResNONE, - ResOK,ResERROR, - ResCONNECT,ResRING, - ResBUSY,ResNODIALTONE,ResNOCARRIER -}; - -#define TEL_CLIENT 0 -#define TEL_SERVER 1 - -class CFifo { -public: - CFifo(Bitu _size) { - size=_size; - pos=used=0; - data=new Bit8u[size]; - } - ~CFifo() { - delete[] data; - } - INLINE Bitu left(void) { - return size-used; - } - INLINE Bitu inuse(void) { - return used; - } - void clear(void) { - used=pos=0; - } - - void addb(Bit8u _val) { - if(used>=size) { - static Bits lcount=0; - if (lcount<1000) { - lcount++; - LOG_MSG("MODEM: FIFO Overflow! (addb)"); - } - return; - } - //assert(used=size) where-=size; - data[where]=_val; - //LOG_MSG("+%x",_val); - used++; - } - void adds(Bit8u * _str,Bitu _len) { - if((used+_len)>size) { - static Bits lcount=0; - if (lcount<1000) { - lcount++; - LOG_MSG("MODEM: FIFO Overflow! (adds len %d)",_len); - } - return; - } - - //assert((used+_len)<=size); - Bitu where=pos+used; - used+=_len; - while (_len--) { - if (where>=size) where-=size; - //LOG_MSG("+%x",*_str); - data[where++]=*_str++; - } - } - Bit8u getb(void) { - if (!used) { - static Bits lcount=0; - if (lcount<1000) { - lcount++; - LOG_MSG("MODEM: FIFO UNDERFLOW! (getb)"); - } - return data[pos]; - } - Bitu where=pos; - if (++pos>=size) pos-=size; - used--; - //LOG_MSG("-%x",data[where]); - return data[where]; - } - void gets(Bit8u * _str,Bitu _len) { - if (!used) { - static Bits lcount=0; - if (lcount<1000) { - lcount++; - LOG_MSG("MODEM: FIFO UNDERFLOW! (gets len %d)",_len); - } - return; - } - //assert(used>=_len); - used-=_len; - while (_len--) { - //LOG_MSG("-%x",data[pos]); - *_str++=data[pos]; - if (++pos>=size) pos-=size; - } - } -private: - Bit8u * data; - Bitu size,pos,used; -}; -#define MREG_AUTOANSWER_COUNT 0 -#define MREG_RING_COUNT 1 -#define MREG_ESCAPE_CHAR 2 -#define MREG_CR_CHAR 3 -#define MREG_LF_CHAR 4 -#define MREG_BACKSPACE_CHAR 5 - - -class CSerialModem : public CSerial { -public: - - CFifo *rqueue; - CFifo *tqueue; - - CSerialModem(Bitu id, CommandLine* cmd); - ~CSerialModem(); - - void Reset(); - - void SendLine(const char *line); - void SendRes(ResTypes response); - void SendNumber(Bitu val); - - void EnterIdleState(); - void EnterConnectedState(); - - void openConnection(void); - bool Dial(char * host); - void AcceptIncomingCall(void); - Bitu ScanNumber(char * & scan); - - void DoCommand(); - - void MC_Changed(Bitu new_mc); - - void TelnetEmulation(Bit8u * data, Bitu size); - - //TODO - void Timer2(void); - void handleUpperEvent(Bit16u type); - - void RXBufferEmpty(); - - void transmitByte(Bit8u val, bool first); - void updatePortConfig(Bit16u divider, Bit8u lcr); - void updateMSR(); - - void setBreak(bool); - - void setRTSDTR(bool rts, bool dtr); - void setRTS(bool val); - void setDTR(bool val); - -protected: - char cmdbuf[255]; - bool commandmode; // true: interpret input as commands - bool echo; // local echo on or off - - bool oldDTRstate; - bool ringing; - //bool response; - bool numericresponse; // true: send control response as number. - // false: send text (i.e. NO DIALTONE) - bool telnetmode; // true: process IAC commands. - - bool connected; - Bitu doresponse; - - Bit8u waiting_tx_character; - - Bitu cmdpause; - Bits ringtimer; - Bits ringcount; - Bitu plusinc; - Bitu cmdpos; - Bitu flowcontrol; - - Bit8u tmpbuf[MODEM_BUFFER_QUEUE_SIZE]; - - Bitu listenport; - Bit8u reg[SREGS]; - - - TCPServerSocket* serversocket; - TCPClientSocket* clientsocket; - TCPClientSocket* waitingclientsocket; - - struct { - bool binary[2]; - bool echo[2]; - bool supressGA[2]; - bool timingMark[2]; - - bool inIAC; - bool recCommand; - Bit8u command; - } telClient; - struct { - bool active; - double f1, f2; - Bitu len,pos; - char str[256]; - } dial; -}; -#endif -#endif diff --git a/src/hardware/tandy_sound.cpp b/src/hardware/tandy_sound.cpp index 8fd27da..357a338 100644 --- a/src/hardware/tandy_sound.cpp +++ b/src/hardware/tandy_sound.cpp @@ -1,381 +1,143 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - Based of sn76496.c of the M.A.M.E. project -*/ - -#include "dosbox.h" -#include "inout.h" -#include "mixer.h" -#include "mem.h" -#include "setup.h" -#include "pic.h" -#include "dma.h" -#include -#include - -#define DAC_CLOCK 3570000 -#define MAX_OUTPUT 0x7fff -#define STEP 0x10000 - -/* Formulas for noise generator */ -/* bit0 = output */ - -/* noise feedback for white noise mode (verified on real SN76489 by John Kortink) */ -#define FB_WNOISE 0x14002 /* (16bits) bit16 = bit0(out) ^ bit2 ^ bit15 */ - -/* noise feedback for periodic noise mode */ -//#define FB_PNOISE 0x10000 /* 16bit rorate */ -#define FB_PNOISE 0x08000 /* JH 981127 - fixes Do Run Run */ - -/* -0x08000 is definitely wrong. The Master System conversion of Marble Madness -uses periodic noise as a baseline. With a 15-bit rotate, the bassline is -out of tune. -The 16-bit rotate has been confirmed against a real PAL Sega Master System 2. -Hope that helps the System E stuff, more news on the PSG as and when! -*/ - -/* noise generator start preset (for periodic noise) */ -#define NG_PRESET 0x0f35 - - -struct SN76496 -{ - int SampleRate; - unsigned int UpdateStep; - int VolTable[16]; /* volume table */ - int Register[8]; /* registers */ - int LastRegister; /* last register written */ - int Volume[4]; /* volume of voice 0-2 and noise */ - unsigned int RNG; /* noise generator */ - int NoiseFB; /* noise feedback mask */ - int Period[4]; - int Count[4]; - int Output[4]; -}; - -static struct SN76496 sn; -static struct { - MixerChannel * chan; - bool enabled; - Bitu last_write; - struct { - bool playing; - Bitu rate; - } dac; -} tandy; - - -static void SN76496Write(Bitu port,Bitu data,Bitu iolen) { - struct SN76496 *R = &sn; - - tandy.last_write=PIC_Ticks; - if (!tandy.enabled) { - tandy.chan->Enable(true); - tandy.enabled=true; - } - - /* update the output buffer before changing the registers */ - - if (data & 0x80) - { - int r = (data & 0x70) >> 4; - int c = r/2; - - R->LastRegister = r; - R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f); - switch (r) - { - case 0: /* tone 0 : frequency */ - case 2: /* tone 1 : frequency */ - case 4: /* tone 2 : frequency */ - R->Period[c] = R->UpdateStep * R->Register[r]; - if (R->Period[c] == 0) R->Period[c] = 0x3fe; - if (r == 4) - { - /* update noise shift frequency */ - if ((R->Register[6] & 0x03) == 0x03) - R->Period[3] = 2 * R->Period[2]; - } - break; - case 1: /* tone 0 : volume */ - case 3: /* tone 1 : volume */ - case 5: /* tone 2 : volume */ - case 7: /* noise : volume */ - R->Volume[c] = R->VolTable[data & 0x0f]; - break; - case 6: /* noise : frequency, mode */ - { - int n = R->Register[6]; - R->NoiseFB = (n & 4) ? FB_WNOISE : FB_PNOISE; - n &= 3; - /* N/512,N/1024,N/2048,Tone #3 output */ - R->Period[3] = (n == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5+n)); - - /* reset noise shifter */ -// R->RNG = NG_PRESET; -// R->Output[3] = R->RNG & 1; - } - break; - } - } - else - { - int r = R->LastRegister; - int c = r/2; - - switch (r) - { - case 0: /* tone 0 : frequency */ - case 2: /* tone 1 : frequency */ - case 4: /* tone 2 : frequency */ - R->Register[r] = (R->Register[r] & 0x0f) | ((data & 0x3f) << 4); - R->Period[c] = R->UpdateStep * R->Register[r]; - if (R->Period[c] == 0) R->Period[c] = 0x3fe; - if (r == 4) - { - /* update noise shift frequency */ - if ((R->Register[6] & 0x03) == 0x03) - R->Period[3] = 2 * R->Period[2]; - } - break; - } - } -} - -static void SN76496Update(Bitu length) -{ - if ((tandy.last_write+5000)Enable(false); - } - int i; - struct SN76496 *R = &sn; - Bit16s * buffer=(Bit16s *)MixTemp; - - /* If the volume is 0, increase the counter */ - for (i = 0;i < 4;i++) - { - if (R->Volume[i] == 0) - { - /* note that I do count += length, NOT count = length + 1. You might think */ - /* it's the same since the volume is 0, but doing the latter could cause */ - /* interferencies when the program is rapidly modulating the volume. */ - if (R->Count[i] <= (int)length*STEP) R->Count[i] += length*STEP; - } - } - - Bitu count=length; - while (count) - { - int vol[4]; - unsigned int out; - int left; - - - /* vol[] keeps track of how long each square wave stays */ - /* in the 1 position during the sample period. */ - vol[0] = vol[1] = vol[2] = vol[3] = 0; - - for (i = 0;i < 3;i++) - { - if (R->Output[i]) vol[i] += R->Count[i]; - R->Count[i] -= STEP; - /* Period[i] is the half period of the square wave. Here, in each */ - /* loop I add Period[i] twice, so that at the end of the loop the */ - /* square wave is in the same status (0 or 1) it was at the start. */ - /* vol[i] is also incremented by Period[i], since the wave has been 1 */ - /* exactly half of the time, regardless of the initial position. */ - /* If we exit the loop in the middle, Output[i] has to be inverted */ - /* and vol[i] incremented only if the exit status of the square */ - /* wave is 1. */ - while (R->Count[i] <= 0) - { - R->Count[i] += R->Period[i]; - if (R->Count[i] > 0) - { - R->Output[i] ^= 1; - if (R->Output[i]) vol[i] += R->Period[i]; - break; - } - R->Count[i] += R->Period[i]; - vol[i] += R->Period[i]; - } - if (R->Output[i]) vol[i] -= R->Count[i]; - } - - left = STEP; - do - { - int nextevent; - - - if (R->Count[3] < left) nextevent = R->Count[3]; - else nextevent = left; - - if (R->Output[3]) vol[3] += R->Count[3]; - R->Count[3] -= nextevent; - if (R->Count[3] <= 0) - { - if (R->RNG & 1) R->RNG ^= R->NoiseFB; - R->RNG >>= 1; - R->Output[3] = R->RNG & 1; - R->Count[3] += R->Period[3]; - if (R->Output[3]) vol[3] += R->Period[3]; - } - if (R->Output[3]) vol[3] -= R->Count[3]; - - left -= nextevent; - } while (left > 0); - - out = vol[0] * R->Volume[0] + vol[1] * R->Volume[1] + - vol[2] * R->Volume[2] + vol[3] * R->Volume[3]; - - if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP; - - *(buffer++) = out / STEP; - - count--; - } - tandy.chan->AddSamples_m16(length,(Bit16s *)MixTemp); -} - - - -static void SN76496_set_clock(int clock) -{ - struct SN76496 *R = &sn; - - - /* the base clock for the tone generators is the chip clock divided by 16; */ - /* for the noise generator, it is clock / 256. */ - /* Here we calculate the number of steps which happen during one sample */ - /* at the given sample rate. No. of events = sample rate / (clock/16). */ - /* STEP is a multiplier used to turn the fraction into a fixed point */ - /* number. */ - R->UpdateStep = (unsigned int)(((double)STEP * R->SampleRate * 16) / clock); -} - - -static void TandyDACWrite(Bitu port,Bitu data,Bitu iolen) { - LOG_MSG("Write tandy dac %X val %X",port,data); - - -} - - -static void SN76496_set_gain(int gain) -{ - struct SN76496 *R = &sn; - int i; - double out; - - - gain &= 0xff; - - /* increase max output basing on gain (0.2 dB per step) */ - out = MAX_OUTPUT / 3; - while (gain-- > 0) - out *= 1.023292992; /* = (10 ^ (0.2/20)) */ - - /* build volume table (2dB per step) */ - for (i = 0;i < 15;i++) - { - /* limit volume to avoid clipping */ - if (out > MAX_OUTPUT / 3) R->VolTable[i] = MAX_OUTPUT / 3; - else R->VolTable[i] = (int)out; - - out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */ - } - R->VolTable[15] = 0; -} - - -class TANDYSOUND: public Module_base { -private: - IO_WriteHandleObject WriteHandler[3]; - MixerObject MixerChan; -public: - TANDYSOUND(Section* configuration):Module_base(configuration){ - Section_prop * section=static_cast(configuration); - - real_writeb(0x40,0xd4,0x00); - if (IS_TANDY_ARCH) { - /* enable tandy sound if tandy=true/auto */ - if ((strcmp(section->Get_string("tandy"),"true")!=0) && - (strcmp(section->Get_string("tandy"),"on")!=0) && - (strcmp(section->Get_string("tandy"),"auto")!=0)) return; - } else { - /* only enable tandy sound if tandy=true */ - if ((strcmp(section->Get_string("tandy"),"true")!=0) && - (strcmp(section->Get_string("tandy"),"on")!=0)) return; - - /* ports from second DMA controller conflict with tandy ports */ - CloseSecondDMAController(); - - WriteHandler[2].Install(0x1e0,SN76496Write,IO_MB,2); - } - - WriteHandler[0].Install(0xc0,SN76496Write,IO_MB,2); - WriteHandler[1].Install(0xc4,TandyDACWrite,IO_MB,4); - - - Bit32u sample_rate = section->Get_int("tandyrate"); - tandy.chan=MixerChan.Install(&SN76496Update,sample_rate,"TANDY"); - - tandy.enabled=false; - real_writeb(0x40,0xd4,0xff); /* tandy DAC initialization value */ - - Bitu i; - struct SN76496 *R = &sn; - R->SampleRate = sample_rate; - SN76496_set_clock(3579545); - for (i = 0;i < 4;i++) R->Volume[i] = 0; - R->LastRegister = 0; - for (i = 0;i < 8;i+=2) - { - R->Register[i] = 0; - R->Register[i + 1] = 0x0f; /* volume = 0 */ - } - - for (i = 0;i < 4;i++) - { - R->Output[i] = 0; - R->Period[i] = R->Count[i] = R->UpdateStep; - } - R->RNG = NG_PRESET; - R->Output[3] = R->RNG & 1; - SN76496_set_gain(0x1); - } - ~TANDYSOUND(){ } -}; - - - -static TANDYSOUND* test; - -void TANDYSOUND_ShutDown(Section* sec) { - delete test; -} - -void TANDYSOUND_Init(Section* sec) { - test = new TANDYSOUND(sec); - sec->AddDestroyFunction(&TANDYSOUND_ShutDown,true); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Probably just use the mame code for the same chip sometime +*/ + +#include +#include "dosbox.h" +#include "inout.h" +#include "mixer.h" +#include "mem.h" + +#define TANDY_DIV 111860 +#define TANDY_RATE 22050 +#define BIT_SHIFT 16 +#define TANDY_VOLUME 10000 +static MIXER_Channel * tandy_chan; +struct TandyChannel { + Bit32u div; + Bit32u freq_add; + Bit32u freq_pos; +}; + + +struct TandyBlock { + TandyChannel chan[3]; + + Bit32s volume[4]; + Bit8u reg; +}; + +static TandyBlock tandy; + + +#define REG_CHAN0DIV 0 /* 0 0 0 */ +#define REG_CHAN0ATT 1 /* 0 0 1 */ +#define REG_CHAN1DIV 2 /* 0 1 0 */ +#define REG_CHAN1ATT 3 /* 0 1 1 */ +#define REG_CHAN2DIV 4 /* 1 0 0 */ +#define REG_CHAN2ATT 5 /* 1 0 1 */ + +#define REG_NOISEATT 7 /* 1 1 1 */ + +//TODO a db volume table :) +static Bit32s vol_table[16]; + + +static void write_pc0(Bit32u port,Bit8u val) { + /* Test for a command byte */ + if (val & 0x80) { + tandy.reg=(val>>4) & 7; + switch (tandy.reg) { + case REG_CHAN0DIV: + case REG_CHAN1DIV: + case REG_CHAN2DIV: + tandy.chan[tandy.reg>>1].div=val&15; + break; + case REG_CHAN0ATT: + case REG_CHAN1ATT: + case REG_CHAN2ATT: + case REG_NOISEATT: + tandy.volume[tandy.reg>>1]=vol_table[val&15]; + if (tandy.volume[0] || tandy.volume[1] || tandy.volume[2] || tandy.volume[3]) { + MIXER_Enable(tandy_chan,true); + } else { + MIXER_Enable(tandy_chan,false); + } + break; + default: +// LOG_WARN("TANDY:Illegal register %d selected",tandy.reg); + break; + } + } else { +/* Dual byte command */ + switch (tandy.reg) { +#define MAKE_ADD(DIV)(Bit32u)((2 << BIT_SHIFT)/((float)TANDY_RATE/((float)TANDY_DIV/(float)DIV))); + case REG_CHAN0DIV: + case REG_CHAN1DIV: + case REG_CHAN2DIV: + tandy.chan[tandy.reg>>1].div|=(val & 63)<<4; + tandy.chan[tandy.reg>>1].freq_add=MAKE_ADD(tandy.chan[tandy.reg>>1].div); +// tandy.chan[tandy.reg>>1].freq_pos=0; + break; + default: + LOG_WARN("TANDY:Illegal dual byte reg %d",tandy.reg); + }; + } + +} + +static void TANDYSOUND_CallBack(Bit8u * stream,Bit32u len) { + for (Bit32u i=0;i=(2 << BIT_SHIFT)) tandy.chan[c].freq_pos-=(2 << BIT_SHIFT); + } + } + /* Generate the noise channel */ + + if (sample>MAX_AUDIO) *(Bit16s *)stream=MAX_AUDIO; + else if (sample -#include "dosbox.h" -#include "inout.h" -#include "pic.h" -#include "mem.h" -#include "mixer.h" -#include "timer.h" -#include "setup.h" - -static INLINE void BIN2BCD(Bit16u& val) { - Bit16u temp=val%10 + (((val/10)%10)<<4)+ (((val/100)%10)<<8) + (((val/1000)%10)<<12); - val=temp; -} - -static INLINE void BCD2BIN(Bit16u& val) { - Bit16u temp= (val&0x0f) +((val>>4)&0x0f) *10 +((val>>8)&0x0f) *100 +((val>>12)&0x0f) *1000; - val=temp; -} - -struct PIT_Block { - Bitu cntr; - float delay; - double start; - - Bit16u read_latch; - Bit16u write_latch; - - Bit8u mode; - Bit8u latch_mode; - Bit8u read_state; - Bit8u write_state; - - bool bcd; - bool go_read_latch; - bool new_mode; - bool counterstatus_set; - bool counting; - bool update_count; -}; - -static PIT_Block pit[3]; -static bool gate2; - -static Bit8u latched_timerstatus; -// the timer status can not be overwritten until it is read or the timer was -// reprogrammed. -static bool latched_timerstatus_locked; - -static void PIT0_Event(Bitu /*val*/) { - PIC_ActivateIRQ(0); - if (pit[0].mode != 0) { - pit[0].start += pit[0].delay; - - if (GCC_UNLIKELY(pit[0].update_count)) { - pit[0].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[0].cntr)); - pit[0].update_count=false; - } - - double error = pit[0].start - PIC_FullIndex(); - PIC_AddEvent(PIT0_Event,(float)(pit[0].delay + error)); - } -} - -static bool counter_output(Bitu counter) { - PIT_Block * p=&pit[counter]; - double index=PIC_FullIndex()-p->start; - switch (p->mode) { - case 0: - if (p->new_mode) return false; - if (index>p->delay) return true; - else return false; - break; - case 2: - if (p->new_mode) return true; - index=fmod(index,(double)p->delay); - return index>0; - case 3: - if (p->new_mode) return true; - index=fmod(index,(double)p->delay); - return index*2delay; - case 4: - //Only low on terminal count - // if(fmod(index,(double)p->delay) == 0) return false; //Maybe take one rate tick in consideration - //Easiest solution is to report always high (Space marines uses this mode) - return true; - default: - LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading output",p->mode); - return true; - } -} -static void status_latch(Bitu counter) { - // the timer status can not be overwritten until it is read or the timer was - // reprogrammed. - if(!latched_timerstatus_locked) { - PIT_Block * p=&pit[counter]; - latched_timerstatus=0; - // Timer Status Word - // 0: BCD - // 1-3: Timer mode - // 4-5: read/load mode - // 6: "NULL" - this is 0 if "the counter value is in the counter" ;) - // should rarely be 1 (i.e. on exotic modes) - // 7: OUT - the logic level on the Timer output pin - if(p->bcd)latched_timerstatus|=0x1; - latched_timerstatus|=((p->mode&7)<<1); - if((p->read_state==0)||(p->read_state==3)) latched_timerstatus|=0x30; - else if(p->read_state==1) latched_timerstatus|=0x10; - else if(p->read_state==2) latched_timerstatus|=0x20; - if(counter_output(counter)) latched_timerstatus|=0x80; - if(p->new_mode) latched_timerstatus|=0x40; - // The first thing that is being read from this counter now is the - // counter status. - p->counterstatus_set=true; - latched_timerstatus_locked=true; - } -} -static void counter_latch(Bitu counter) { - /* Fill the read_latch of the selected counter with current count */ - PIT_Block * p=&pit[counter]; - p->go_read_latch=false; - - //If gate2 is disabled don't update the read_latch - if(counter == 2 && !gate2 && p->mode !=1) return; - - double index=PIC_FullIndex()-p->start; - switch (p->mode) { - case 4: /* Software Triggered Strobe */ - case 0: /* Interrupt on Terminal Count */ - /* Counter keeps on counting after passing terminal count */ - if (index>p->delay) { - index-=p->delay; - if(p->bcd) { - index = fmod(index,(1000.0/PIT_TICK_RATE)*10000.0); - p->read_latch = (Bit16u)(9999-index*(PIT_TICK_RATE/1000.0)); - } else { - index = fmod(index,(1000.0/PIT_TICK_RATE)*(double)0x10000); - p->read_latch = (Bit16u)(0xffff-index*(PIT_TICK_RATE/1000.0)); - } - } else { - p->read_latch=(Bit16u)(p->cntr-index*(PIT_TICK_RATE/1000.0)); - } - break; - case 1: // countdown - if(p->counting) { - if (index>p->delay) { // has timed out - p->read_latch = 0xffff; //unconfirmed - } else { - p->read_latch=(Bit16u)(p->cntr-index*(PIT_TICK_RATE/1000.0)); - } - } - break; - case 2: /* Rate Generator */ - index=fmod(index,(double)p->delay); - p->read_latch=(Bit16u)(p->cntr - (index/p->delay)*p->cntr); - break; - case 3: /* Square Wave Rate Generator */ - index=fmod(index,(double)p->delay); - index*=2; - if (index>p->delay) index-=p->delay; - p->read_latch=(Bit16u)(p->cntr - (index/p->delay)*p->cntr); - // In mode 3 it never returns odd numbers LSB (if odd number is written 1 will be - // subtracted on first clock and then always 2) - // fixes "Corncob 3D" - p->read_latch&=0xfffe; - break; - default: - LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading counter %d",p->mode,counter); - p->read_latch=0xffff; - break; - } -} - - -static void write_latch(Bitu port,Bitu val,Bitu /*iolen*/) { -//LOG(LOG_PIT,LOG_ERROR)("port %X write:%X state:%X",port,val,pit[port-0x40].write_state); - Bitu counter=port-0x40; - PIT_Block * p=&pit[counter]; - if(p->bcd == true) BIN2BCD(p->write_latch); - - switch (p->write_state) { - case 0: - p->write_latch = p->write_latch | ((val & 0xff) << 8); - p->write_state = 3; - break; - case 3: - p->write_latch = val & 0xff; - p->write_state = 0; - break; - case 1: - p->write_latch = val & 0xff; - break; - case 2: - p->write_latch = (val & 0xff) << 8; - break; - } - if (p->bcd==true) BCD2BIN(p->write_latch); - if (p->write_state != 0) { - if (p->write_latch == 0) { - if (p->bcd == false) p->cntr = 0x10000; - else p->cntr=9999; - } else p->cntr = p->write_latch; - - if ((!p->new_mode) && (p->mode == 2) && (counter == 0)) { - // In mode 2 writing another value has no direct effect on the count - // until the old one has run out. This might apply to other modes too. - // This is not fixed for PIT2 yet!! - p->update_count=true; - return; - } - p->start=PIC_FullIndex(); - p->delay=(1000.0f/((float)PIT_TICK_RATE/(float)p->cntr)); - - switch (counter) { - case 0x00: /* Timer hooked to IRQ 0 */ - if (p->new_mode || p->mode == 0 ) { - if(p->mode==0) PIC_RemoveEvents(PIT0_Event); // DoWhackaDo demo - PIC_AddEvent(PIT0_Event,p->delay); - } else LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer set without new control word"); - LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer at %.4f Hz mode %d",1000.0/p->delay,p->mode); - break; - case 0x02: /* Timer hooked to PC-Speaker */ -// LOG(LOG_PIT,"PIT 2 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode); - PCSPEAKER_SetCounter(p->cntr,p->mode); - break; - default: - LOG(LOG_PIT,LOG_ERROR)("PIT:Illegal timer selected for writing"); - } - p->new_mode=false; - } -} - -static Bitu read_latch(Bitu port,Bitu /*iolen*/) { -//LOG(LOG_PIT,LOG_ERROR)("port read %X",port); - Bit32u counter=port-0x40; - Bit8u ret=0; - if(GCC_UNLIKELY(pit[counter].counterstatus_set)){ - pit[counter].counterstatus_set = false; - latched_timerstatus_locked = false; - ret = latched_timerstatus; - } else { - if (pit[counter].go_read_latch == true) - counter_latch(counter); - - if( pit[counter].bcd == true) BIN2BCD(pit[counter].read_latch); - - switch (pit[counter].read_state) { - case 0: /* read MSB & return to state 3 */ - ret=(pit[counter].read_latch >> 8) & 0xff; - pit[counter].read_state = 3; - pit[counter].go_read_latch = true; - break; - case 3: /* read LSB followed by MSB */ - ret = pit[counter].read_latch & 0xff; - - if (pit[counter].mode & 0x80) pit[counter].mode &= 7; - else pit[counter].read_state = 0; - break; - case 1: /* read LSB */ - ret = pit[counter].read_latch & 0xff; - pit[counter].go_read_latch = true; - break; - case 2: /* read MSB */ - ret = (pit[counter].read_latch >> 8) & 0xff; - pit[counter].go_read_latch = true; - break; - default: - E_Exit("Timer.cpp: error in readlatch"); - break; - } - if( pit[counter].bcd == true) BCD2BIN(pit[counter].read_latch); - } - return ret; -} - -static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) { -//LOG(LOG_PIT,LOG_ERROR)("port 43 %X",val); - Bitu latch=(val >> 6) & 0x03; - switch (latch) { - case 0: - case 1: - case 2: - if ((val & 0x30) == 0) { - /* Counter latch command */ - counter_latch(latch); - } else { - pit[latch].bcd = (val&1)>0; - if (val & 1) { - if(pit[latch].cntr>=9999) pit[latch].cntr=9999; - } - - // Timer is being reprogrammed, unlock the status - if(pit[latch].counterstatus_set) { - pit[latch].counterstatus_set=false; - latched_timerstatus_locked=false; - } - pit[latch].update_count = false; - pit[latch].counting = false; - pit[latch].read_state = (val >> 4) & 0x03; - pit[latch].write_state = (val >> 4) & 0x03; - Bit8u mode = (val >> 1) & 0x07; - if (mode > 5) - mode -= 4; //6,7 become 2 and 3 - - /* Don't set it directly so counter_output uses the old mode */ - /* That's theory. It breaks panic. So set it here again */ - if(!pit[latch].mode) pit[latch].mode = mode; - - /* If the line goes from low to up => generate irq. - * ( BUT needs to stay up until acknowlegded by the cpu!!! therefore: ) - * If the line goes to low => disable irq. - * Mode 0 starts with a low line. (so always disable irq) - * Mode 2,3 start with a high line. - * counter_output tells if the current counter is high or low - * So actually a mode 2 timer enables and disables irq al the time. (not handled) */ - - if (latch == 0) { - PIC_RemoveEvents(PIT0_Event); - if (!counter_output(0) && mode) { - PIC_ActivateIRQ(0); - //Don't raise instantaniously. (Origamo) - if(CPU_Cycles < 25) CPU_Cycles = 25; - } - if(!mode) - PIC_DeActivateIRQ(0); - } - pit[latch].new_mode = true; - pit[latch].mode = mode; //Set the correct mode (here) - } - break; - case 3: - if ((val & 0x20)==0) { /* Latch multiple pit counters */ - if (val & 0x02) counter_latch(0); - if (val & 0x04) counter_latch(1); - if (val & 0x08) counter_latch(2); - } - // status and values can be latched simultaneously - if ((val & 0x10)==0) { /* Latch status words */ - // but only 1 status can be latched simultaneously - if (val & 0x02) status_latch(0); - else if (val & 0x04) status_latch(1); - else if (val & 0x08) status_latch(2); - } - break; - } -} - -void TIMER_SetGate2(bool in) { - //No changes if gate doesn't change - if(gate2 == in) return; - Bit8u & mode=pit[2].mode; - switch(mode) { - case 0: - if(in) pit[2].start = PIC_FullIndex(); - else { - //Fill readlatch and store it. - counter_latch(2); - pit[2].cntr = pit[2].read_latch; - } - break; - case 1: - // gate 1 on: reload counter; off: nothing - if(in) { - pit[2].counting = true; - pit[2].start = PIC_FullIndex(); - } - break; - case 2: - case 3: - //If gate is enabled restart counting. If disable store the current read_latch - if(in) pit[2].start = PIC_FullIndex(); - else counter_latch(2); - break; - case 4: - case 5: - LOG(LOG_MISC,LOG_WARN)("unsupported gate 2 mode %x",mode); - break; - } - gate2 = in; //Set it here so the counter_latch above works -} - -class TIMER:public Module_base{ -private: - IO_ReadHandleObject ReadHandler[4]; - IO_WriteHandleObject WriteHandler[4]; -public: - TIMER(Section* configuration):Module_base(configuration){ - WriteHandler[0].Install(0x40,write_latch,IO_MB); - // WriteHandler[1].Install(0x41,write_latch,IO_MB); - WriteHandler[2].Install(0x42,write_latch,IO_MB); - WriteHandler[3].Install(0x43,write_p43,IO_MB); - ReadHandler[0].Install(0x40,read_latch,IO_MB); - ReadHandler[1].Install(0x41,read_latch,IO_MB); - ReadHandler[2].Install(0x42,read_latch,IO_MB); - /* Setup Timer 0 */ - pit[0].cntr=0x10000; - pit[0].write_state = 3; - pit[0].read_state = 3; - pit[0].read_latch=0; - pit[0].write_latch=0; - pit[0].mode=3; - pit[0].bcd = false; - pit[0].go_read_latch = true; - pit[0].counterstatus_set = false; - pit[0].update_count = false; - - pit[1].bcd = false; - pit[1].write_state = 1; - pit[1].read_state = 1; - pit[1].go_read_latch = true; - pit[1].cntr = 18; - pit[1].mode = 2; - pit[1].write_state = 3; - pit[1].counterstatus_set = false; - - pit[2].read_latch=1320; /* MadTv1 */ - pit[2].write_state = 3; /* Chuck Yeager */ - pit[2].read_state = 3; - pit[2].mode=3; - pit[2].bcd=false; - pit[2].cntr=1320; - pit[2].go_read_latch=true; - pit[2].counterstatus_set = false; - pit[2].counting = false; - - pit[0].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[0].cntr)); - pit[1].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[1].cntr)); - pit[2].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[2].cntr)); - - latched_timerstatus_locked=false; - gate2 = false; - PIC_AddEvent(PIT0_Event,pit[0].delay); - } - ~TIMER(){ - PIC_RemoveEvents(PIT0_Event); - } -}; -static TIMER* test; - -void TIMER_Destroy(Section*){ - delete test; -} -void TIMER_Init(Section* sec) { - test = new TIMER(sec); - sec->AddDestroyFunction(&TIMER_Destroy); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + + + +#include +#include "dosbox.h" +#include "inout.h" +#include "pic.h" +#include "bios.h" +#include "mem.h" +#include "dosbox.h" +#include "mixer.h" +#include "timer.h" + + + +struct PIT_Block { + Bit8u mode; /* Current Counter Mode */ + Bit32s cntr; + Bit8u latch_mode; + Bit8u read_state; + Bit16s read_latch; + Bit8u write_state; + Bit16u write_latch; + Bit32u last_ticks; +}; + + +static PIT_Block pit[3]; +static Bit32u pit_ticks; /* The amount of pit ticks one host tick is bit shifted */ +static Bit32u timer_ticks; /* The amount of pit ticks bitshifted one timer cycle needs */ +static Bit32u timer_buildup; /* The amount of pit ticks waiting */ +#define PIT_TICK_RATE 1193182 +#define PIT_SHIFT 9 +#define MAX_PASSED ((PIT_TICK_RATE/4) << PIT_SHIFT) /* Alow 1/4 second of timer build up */ + + +static void counter_latch(Bitu counter) { + /* Fill the read_latch of the selected counter with current count */ + PIT_Block * p=&pit[counter]; +//TODO Perhaps make it a bit64u for accuracy :) + Bit32u ticks=(((LastTicks - p->last_ticks) * pit_ticks) >> PIT_SHIFT) % p->cntr ; + switch (p->mode) { + case 2: + case 3: + p->read_latch=(Bit16u)ticks; + break; + default: + LOG_ERROR("PIT:Illegal Mode %d for reading counter %d",p->mode,counter); + p->read_latch=(Bit16u)ticks; + break; + } +} + + + +static void write_latch(Bit32u port,Bit8u val) { + Bit32u counter=port-0x40; + PIT_Block * p=&pit[counter]; + switch (p->write_state) { + case 0: + p->write_latch = p->write_latch | ((val & 0xff) << 8); + p->write_state = 3; + break; + case 3: + p->write_latch = val & 0xff; + p->write_state = 0; + break; + case 1: + p->write_latch = val & 0xff; + break; + case 2: + p->write_latch = (val & 0xff) << 8; + break; + } + if (p->write_state != 0) { + if (p->write_latch == 0) p->cntr = 0x10000; + else p->cntr = p->write_latch; + p->last_ticks=LastTicks; + switch (counter) { + case 0x00: /* Timer hooked to IRQ 0 */ + PIC_DeActivateIRQ(0); + timer_ticks=p->cntr << PIT_SHIFT; + timer_buildup=0; + LOG_DEBUG("PIT 0 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode); + break; + case 0x02: /* Timer hooked to PC-Speaker */ + PCSPEAKER_SetFreq(PIT_TICK_RATE/p->cntr); + break; + default: + LOG_ERROR("PIT:Illegal timer selected for writing"); + } + + } +} + +static Bit8u read_latch(Bit32u port) { + Bit32u counter=port-0x40; + if (pit[counter].read_latch == -1) + counter_latch(counter); + Bit8u ret; + switch (pit[counter].read_state) { + case 0: /* read MSB & return to state 3 */ + ret=(pit[counter].read_latch >> 8) & 0xff; + pit[counter].read_state = 3; + pit[counter].read_latch = -1; + break; + case 3: /* read LSB followed by MSB */ + ret = (pit[counter].read_latch & 0xff); + if (pit[counter].mode & 0x80) pit[counter].mode &= 7; /* moved here */ + else + pit[counter].read_state = 0; + break; + case 1: /* read MSB */ + ret = (pit[counter].read_latch >> 8) & 0xff; + pit[counter].read_latch = -1; + break; + case 2: /* read LSB */ + ret = (pit[counter].read_latch & 0xff); + pit[counter].read_latch = -1; + break; + default: + ret=0; + E_Exit("Timer.cpp: error in readlatch"); + break; + } + return ret; +} + + + + + +static void write_p43(Bit32u port,Bit8u val) { + if (val & 1) { + E_Exit("PIT:BCD Counter not supported"); + } + Bitu latch=(val >> 6) & 0x03; + switch (latch) { + case 0: + case 1: + case 2: + if ((val & 0x30) == 0) { + /* Counter latch command */ + counter_latch(latch); + } else { + pit[latch].read_state = (val >> 4) & 0x03; + pit[latch].write_state = (val >> 4) & 0x03; + pit[latch].mode = (val >> 1) & 0x07; + } + break; + case 3: + E_Exit("Special PIT Latch Read out thing"); + } + +} + +/* The TIMER Part */ + +enum { T_TICK,T_MICRO,T_DELAY}; + +struct Timer { + Bitu type; + union { + struct { + TIMER_TickHandler handler; + } tick; + struct{ + Bitu count; + Bitu total; + TIMER_MicroHandler handler; + } micro; + struct { + Bitu end; + TIMER_DelayHandler handler; + } delay; + }; +}; + +static Timer * first_timer=0; +static std::list Timers; + +TIMER_Block * TIMER_RegisterTickHandler(TIMER_TickHandler handler) { + Timer * new_timer=new(Timer); + new_timer->type=T_TICK; + new_timer->tick.handler=handler; + Timers.push_front(new_timer); + return (TIMER_Block *)new_timer; +} + +TIMER_Block * TIMER_RegisterMicroHandler(TIMER_MicroHandler handler,Bitu micro) { + Timer * new_timer=new(Timer); + new_timer->type=T_MICRO; + new_timer->micro.handler=handler; + new_timer->micro.total=micro; + new_timer->micro.count=0; + Timers.push_front(new_timer); + return (TIMER_Block *)new_timer; +} + +TIMER_Block * TIMER_RegisterDelayHandler(TIMER_DelayHandler handler,Bitu delay) { +//Todo maybe check for a too long delay + Timer * new_timer=new(Timer); + new_timer->type=T_DELAY; + new_timer->delay.handler=handler; + new_timer->delay.end=LastTicks+delay; + Timers.push_front(new_timer); + return (TIMER_Block *)new_timer; + +} +void TIMER_SetNewMicro(TIMER_Block * block,Bitu micro) { + Timer * timer=(Timer *)block; + if (timer->type!=T_MICRO) E_Exit("TIMER:Illegal handler type"); + timer->micro.count=0; + timer->micro.total=micro; +} + +void TIMER_AddTicks(Bit32u ticks) { +/* This will run through registered handlers and handle the PIT ticks */ + timer_buildup+=ticks*pit_ticks; + if (timer_buildup>MAX_PASSED) timer_buildup=MAX_PASSED; + Bitu add_micro=ticks*1000; + std::list::iterator i; + for(i=Timers.begin(); i != Timers.end(); ++i) { + Timer * timer=(*i); + switch (timer->type) { + case T_TICK: + timer->tick.handler(ticks); + break; + case T_MICRO: + timer->micro.count+=add_micro; + if (timer->micro.count>=timer->micro.total) { + timer->micro.count-=timer->micro.total; + timer->micro.handler(); + } + break; + case T_DELAY: + /* Also unregister the timer handler from the list */ + if (LastTicks>timer->delay.end) { + std::list::iterator remove; + timer->delay.handler(); + remove=i++; + Timers.erase(remove); + } + break; + default: + E_Exit("TIMER:Illegal handler type"); + }; + + }; +} + + +void TIMER_CheckPIT(void) { + if (timer_buildup>timer_ticks) { + timer_buildup-=timer_ticks; + PIC_ActivateIRQ(0); + return; + } +} + + +void TIMER_Init(void) { + IO_RegisterWriteHandler(0x40,write_latch,"PIT Timer 0"); + IO_RegisterWriteHandler(0x42,write_latch,"PIT Timer 2"); + IO_RegisterWriteHandler(0x43,write_p43,"PIT Mode Control"); + IO_RegisterReadHandler(0x40,read_latch,"PIT Timer 0"); +// IO_RegisterReadHandler(0x41,read_p41,"PIT Timer 1"); + IO_RegisterReadHandler(0x42,read_latch,"PIT Timer 2"); + /* Setup Timer 0 */ + pit[0].cntr=0x10000; + pit[0].write_state = 3; + pit[0].read_state = 3; + pit[0].read_latch=-1; + pit[0].write_latch=0; + pit[0].mode=3; + timer_ticks=pit[0].cntr << PIT_SHIFT; + timer_buildup=0; +// first_timer=0; + pit_ticks=(PIT_TICK_RATE << PIT_SHIFT)/1000; + PIC_RegisterIRQ(0,&TIMER_CheckPIT,"PIT 0 Timer"); +} + diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index 41f5730..1d866fc 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -1,258 +1,165 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga.cpp,v 1.35 2008/08/06 18:32:35 c2woody Exp $ */ - -#include "dosbox.h" -//#include "setup.h" -#include "video.h" -#include "pic.h" -#include "vga.h" - -#include - -VGA_Type vga; -SVGA_Driver svga; - -Bit32u CGA_2_Table[16]; -Bit32u CGA_4_Table[256]; -Bit32u CGA_4_HiRes_Table[256]; -Bit32u CGA_16_Table[256]; -Bit32u TXT_Font_Table[16]; -Bit32u TXT_FG_Table[16]; -Bit32u TXT_BG_Table[16]; -Bit32u ExpandTable[256]; -Bit32u Expand16Table[4][16]; -Bit32u FillTable[16]; -Bit32u ColorTable[16]; - - - -void VGA_SetMode(VGAModes mode) { - if (vga.mode == mode) return; - vga.mode=mode; - VGA_SetupHandlers(); - VGA_StartResize(); -} - -void VGA_DetermineMode(void) { - if (svga.determine_mode) { - svga.determine_mode(); - return; - } - /* Test for VGA output active or direct color modes */ - switch (vga.s3.misc_control_2 >> 4) { - case 0: - if (vga.attr.mode_control & 1) { // graphics mode - if (IS_VGA_ARCH && (vga.gfx.mode & 0x40)) { - // access above 256k? - if (vga.s3.reg_31 & 0x8) VGA_SetMode(M_LIN8); - else VGA_SetMode(M_VGA); - } - else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4); - else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2); - else { - // access above 256k? - if (vga.s3.reg_31 & 0x8) VGA_SetMode(M_LIN4); - else VGA_SetMode(M_EGA); - } - } else { - VGA_SetMode(M_TEXT); - } - break; - case 1:VGA_SetMode(M_LIN8);break; - case 3:VGA_SetMode(M_LIN15);break; - case 5:VGA_SetMode(M_LIN16);break; - case 13:VGA_SetMode(M_LIN32);break; - } -} - -void VGA_StartResize(Bitu delay /*=50*/) { - if (!vga.draw.resizing) { - vga.draw.resizing=true; - /* Start a resize after delay (default 50 ms) */ - PIC_AddEvent(VGA_SetupDrawing,(float)delay); - } -} - -void VGA_SetClock(Bitu which,Bitu target) { - if (svga.set_clock) { - svga.set_clock(which, target); - return; - } - struct{ - Bitu n,m; - Bits err; - } best; - best.err=target; - best.m=1; - best.n=1; - Bitu n,r; - Bits m; - - for (r = 0; r <= 3; r++) { - Bitu f_vco = target * (1 << r); - if (MIN_VCO <= f_vco && f_vco < MAX_VCO) break; - } - for (n=1;n<=31;n++) { - m=(target * (n + 2) * (1 << r) + (S3_CLOCK_REF/2)) / S3_CLOCK_REF - 2; - if (0 <= m && m <= 127) { - Bitu temp_target = S3_CLOCK(m,n,r); - Bits err = target - temp_target; - if (err < 0) err = -err; - if (err < best.err) { - best.err = err; - best.m = m; - best.n = n; - } - } - } - /* Program the s3 clock chip */ - vga.s3.clk[which].m=best.m; - vga.s3.clk[which].r=r; - vga.s3.clk[which].n=best.n; - VGA_StartResize(); -} - -void VGA_SetCGA2Table(Bit8u val0,Bit8u val1) { - Bit8u total[2]={ val0,val1}; - for (Bitu i=0;i<16;i++) { - CGA_2_Table[i]= -#ifdef WORDS_BIGENDIAN - (total[(i >> 0) & 1] << 0 ) | (total[(i >> 1) & 1] << 8 ) | - (total[(i >> 2) & 1] << 16 ) | (total[(i >> 3) & 1] << 24 ); -#else - (total[(i >> 3) & 1] << 0 ) | (total[(i >> 2) & 1] << 8 ) | - (total[(i >> 1) & 1] << 16 ) | (total[(i >> 0) & 1] << 24 ); -#endif - } -} - -void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3) { - Bit8u total[4]={ val0,val1,val2,val3}; - for (Bitu i=0;i<256;i++) { - CGA_4_Table[i]= -#ifdef WORDS_BIGENDIAN - (total[(i >> 0) & 3] << 0 ) | (total[(i >> 2) & 3] << 8 ) | - (total[(i >> 4) & 3] << 16 ) | (total[(i >> 6) & 3] << 24 ); -#else - (total[(i >> 6) & 3] << 0 ) | (total[(i >> 4) & 3] << 8 ) | - (total[(i >> 2) & 3] << 16 ) | (total[(i >> 0) & 3] << 24 ); -#endif - CGA_4_HiRes_Table[i]= -#ifdef WORDS_BIGENDIAN - (total[((i >> 0) & 1) | ((i >> 3) & 2)] << 0 ) | (total[((i >> 1) & 1) | ((i >> 4) & 2)] << 8 ) | - (total[((i >> 2) & 1) | ((i >> 5) & 2)] << 16 ) | (total[((i >> 3) & 1) | ((i >> 6) & 2)] << 24 ); -#else - (total[((i >> 3) & 1) | ((i >> 6) & 2)] << 0 ) | (total[((i >> 2) & 1) | ((i >> 5) & 2)] << 8 ) | - (total[((i >> 1) & 1) | ((i >> 4) & 2)] << 16 ) | (total[((i >> 0) & 1) | ((i >> 3) & 2)] << 24 ); -#endif - } -} - -void VGA_Init(Section* sec) { -// Section_prop * section=static_cast(sec); -// vga.screenflip = section->Get_int("screenflip"); - vga.screenflip = 0; - vga.draw.resizing=false; - vga.mode=M_ERROR; //For first init - SVGA_Setup_Driver(); - VGA_SetupMemory(sec); - VGA_SetupMisc(); - VGA_SetupDAC(); - VGA_SetupGFX(); - VGA_SetupSEQ(); - VGA_SetupAttr(); - VGA_SetupOther(); - VGA_SetupXGA(); - VGA_SetClock(0,CLK_25); - VGA_SetClock(1,CLK_28); -/* Generate tables */ - VGA_SetCGA2Table(0,1); - VGA_SetCGA4Table(0,1,2,3); - Bitu i,j; - for (i=0;i<256;i++) { - ExpandTable[i]=i | (i << 8)| (i <<16) | (i << 24); - } - for (i=0;i<16;i++) { - TXT_FG_Table[i]=i | (i << 8)| (i <<16) | (i << 24); - TXT_BG_Table[i]=i | (i << 8)| (i <<16) | (i << 24); -#ifdef WORDS_BIGENDIAN - FillTable[i]= - ((i & 1) ? 0xff000000 : 0) | - ((i & 2) ? 0x00ff0000 : 0) | - ((i & 4) ? 0x0000ff00 : 0) | - ((i & 8) ? 0x000000ff : 0) ; - TXT_Font_Table[i]= - ((i & 1) ? 0x000000ff : 0) | - ((i & 2) ? 0x0000ff00 : 0) | - ((i & 4) ? 0x00ff0000 : 0) | - ((i & 8) ? 0xff000000 : 0) ; -#else - FillTable[i]= - ((i & 1) ? 0x000000ff : 0) | - ((i & 2) ? 0x0000ff00 : 0) | - ((i & 4) ? 0x00ff0000 : 0) | - ((i & 8) ? 0xff000000 : 0) ; - TXT_Font_Table[i]= - ((i & 1) ? 0xff000000 : 0) | - ((i & 2) ? 0x00ff0000 : 0) | - ((i & 4) ? 0x0000ff00 : 0) | - ((i & 8) ? 0x000000ff : 0) ; -#endif - } - for (j=0;j<4;j++) { - for (i=0;i<16;i++) { -#ifdef WORDS_BIGENDIAN - Expand16Table[j][i] = - ((i & 1) ? 1 << j : 0) | - ((i & 2) ? 1 << (8 + j) : 0) | - ((i & 4) ? 1 << (16 + j) : 0) | - ((i & 8) ? 1 << (24 + j) : 0); -#else - Expand16Table[j][i] = - ((i & 1) ? 1 << (24 + j) : 0) | - ((i & 2) ? 1 << (16 + j) : 0) | - ((i & 4) ? 1 << (8 + j) : 0) | - ((i & 8) ? 1 << j : 0); -#endif - } - } -} - -void SVGA_Setup_Driver(void) { - memset(&svga, 0, sizeof(SVGA_Driver)); - - switch(svgaCard) { - case SVGA_S3Trio: - SVGA_Setup_S3Trio(); - break; - case SVGA_TsengET4K: - SVGA_Setup_TsengET4K(); - break; - case SVGA_TsengET3K: - SVGA_Setup_TsengET3K(); - break; - case SVGA_ParadisePVGA1A: - SVGA_Setup_ParadisePVGA1A(); - break; - default: - vga.vmemsize = vga.vmemwrap = 256*1024; - break; - } -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "dosbox.h" +#include "video.h" +#include "pic.h" +#include "render.h" +#include "timer.h" +#include "vga.h" + +VGA_Type vga; +Bit32u CGAWriteTable[256]; +Bit32u ExpandTable[256]; + +Bit32u FillTable[16]={ + 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, + 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, + 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, + 0xffff0000,0xffff00ff,0xffffff00,0xffffffff +}; + +static PageEntry VGA_PageEntry; + +void VGA_Render_GFX_4(Bit8u * * data); +void VGA_Render_GFX_16(Bit8u * * data); +void VGA_Render_GFX_256C(Bit8u * * data); +void VGA_Render_GFX_256U(Bit8u * * data); +void VGA_Render_TEXT_16(Bit8u * * data); + +void VGA_FindSettings(void) { + /* Sets up the correct memory handler from the vga.mode setting */ + MEMORY_ResetHandler(0xA0000/4096,128*1024/4096); + VGA_PageEntry.type=MEMORY_HANDLER; + /* Detect the kind of video mode this is */ + if (vga.config.gfxmode) { + if (vga.config.vga_enabled) { + if (vga.config.chained) { + /* 256 color chained vga */ + vga.mode=GFX_256C; + //Doesn't need a memory handler + } else { + /* 256 color unchained vga */ + vga.mode=GFX_256U; + VGA_PageEntry.base=0xA0000; + VGA_PageEntry.handler.read=VGA_NormalReadHandler; + VGA_PageEntry.handler.write=VGA_GFX_256U_WriteHandler; + MEMORY_SetupHandler(0xA0000/4096,16,&VGA_PageEntry); + } + } else if (vga.config.cga_enabled) { + /* 4 color cga */ + //TODO Detect hercules modes, probably set them up in bios too + vga.mode=GFX_4; +// VGA_PageEntry.base=0xB8000; +// VGA_PageEntry.handler.read=VGA_GFX_4_ReadHandler; +// VGA_PageEntry.handler.write=VGA_GFX_4_WriteHandler; +// MEMORY_SetupHandler(0xB8000/4096,8,&VGA_PageEntry); + } else { + /* 16 color ega */ + vga.mode=GFX_16; + VGA_PageEntry.base=0xA0000; + VGA_PageEntry.handler.read=VGA_NormalReadHandler; + VGA_PageEntry.handler.write=VGA_GFX_16_WriteHandler; + MEMORY_SetupHandler(0xA0000/4096,16,&VGA_PageEntry); + } + } else { + vga.mode=TEXT_16; + } + VGA_StartResize(); +} + +static void VGA_DoResize(void) { + vga.draw.resizing=false; + Bitu width,height,pitch; + RENDER_Handler * renderer; + + height=vga.config.vdisplayend+1; + if (vga.config.vline_height>0) { + height/=(vga.config.vline_height+1); + } + if (vga.config.vline_double) height>>=1; + width=vga.config.hdisplayend; + switch (vga.mode) { + case GFX_256C: + renderer=&VGA_Render_GFX_256C; + width<<=2; + pitch=vga.config.scan_len*8; + break; + case GFX_256U: + width<<=2; + pitch=vga.config.scan_len*8; + renderer=&VGA_Render_GFX_256U; + break; + case GFX_16: + width<<=3; + pitch=vga.config.scan_len*16; + renderer=&VGA_Render_GFX_16; + break; + case GFX_4: + width<<=3; + height<<=1; + pitch=width; + renderer=&VGA_Render_GFX_4; + break; + case TEXT_16: + /* probably a 16-color text mode, got to detect mono mode somehow */ + width<<=3; /* 8 bit wide text font */ + height<<=4; /* 16 bit font height */ + if (width>640) width=640; + if (height>480) height=480; + pitch=width; + renderer=&VGA_Render_TEXT_16; + }; + + vga.draw.width=width; + vga.draw.height=height; + RENDER_SetSize(width,height,8,pitch,((float)width/(float)height),0,renderer); + +}; + +void VGA_StartResize(void) { + if (!vga.draw.resizing) { + vga.draw.resizing=true; + /* Start a resize after 50 ms */ + TIMER_RegisterDelayHandler(VGA_DoResize,50); + } +} + + + + +void VGA_Init() { + vga.draw.resizing=false; + VGA_SetupMemory(); + VGA_SetupMisc(); + VGA_SetupDAC(); + VGA_SetupCRTC(); + VGA_SetupGFX(); + VGA_SetupSEQ(); + VGA_SetupAttr(); +/* Generate tables */ + Bit32u i; + for (i=0;i<256;i++) { + ExpandTable[i]=i | (i << 8)| (i <<16) | (i << 24); + CGAWriteTable[i]=((i>>6)&3) | (((i>>4)&3) << 8)| (((i>>2)&3) <<16) | (((i>>0)&3) << 24); + } +} + diff --git a/src/hardware/vga.h b/src/hardware/vga.h new file mode 100644 index 0000000..bd2985a --- /dev/null +++ b/src/hardware/vga.h @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef VGA_H_ +#define VGA_H_ + +#include + +enum { TEXT, GRAPH }; +enum { GFX_256C,GFX_256U,GFX_16,GFX_4,GFX_2, TEXT_16 }; + +typedef struct { + + bool attrindex; +} VGA_Internal; + +typedef struct { + +/* Video drawing */ + Bit16u display_start; + Bit16u real_start; + bool retrace; /* A retrace has started */ + Bitu scan_len; + +/* Screen resolution and memory mode */ + Bitu vdisplayend; + Bitu hdisplayend; + + bool chained; /* Enable or Disabled Chain 4 Mode */ + bool gfxmode; /* Yes or No Easy no */ + bool blinking; /* Attribute bit 7 is blinking */ + + bool vga_enabled; + bool cga_enabled; + + bool vline_double; + Bit8u vline_height; + + /* Pixel Scrolling */ + Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */ + Bit8u hlines_skip; + Bit8u bytes_skip; + +/* Specific stuff memory write/read handling */ + Bit8u read_mode; + Bit8u write_mode; + Bit8u read_map_select; + Bit8u color_dont_care; + Bit8u color_compare; + Bit8u data_rotate; + Bit8u raster_op; + Bit8u enable_set_reset; + Bit8u set_reset; + + Bit32u full_bit_mask; + Bit32u full_map_mask; + +} VGA_Config; + +typedef struct { + bool resizing; + Bitu width; + Bitu height; + Bit8u font_height; + Bit8u cursor_enable; + Bit8u cursor_row; + Bit8u cursor_col; + Bit8u cursor_count; +} VGA_Draw; + + +typedef struct { + Bit8u index; + + Bit8u reset; + Bit8u clocking_mode; + Bit8u map_mask; + Bit8u character_map_select; + Bit8u memory_mode; +} VGA_Seq; + + +typedef struct { + Bit8u palette[16]; + Bit8u mode_control; + Bit8u horizontal_pel_panning; + Bit8u overscan_color; + Bit8u color_plane_enable; + Bit8u color_select; + Bit8u index; +} VGA_Attr; + + +typedef struct { + Bit8u horizontal_total; + Bit8u horizontal_display_end; + Bit8u start_horizontal_blanking; + Bit8u end_horizontal_blanking; + Bit8u start_horizontal_retrace; + Bit8u end_horizontal_retrace; + Bit8u vertical_total; + Bit8u overflow; + Bit8u preset_row_scan; + Bit8u maximum_scan_line; + Bit8u cursor_start; + Bit8u cursor_end; + Bit8u start_address_high; + Bit8u start_address_low; + Bit8u cursor_location_high; + Bit8u cursor_location_low; + Bit8u vertical_retrace_start; + Bit8u vertical_retrace_end; + Bit8u vertical_display_end; + Bit8u offset; + Bit8u underline_location; + Bit8u start_vertical_blank; + Bit8u end_vertical_blank; + Bit8u mode_control; + Bit8u line_compare; + + Bit8u index; +} VGA_Crtc; + +typedef struct { + Bit8u index; + Bit8u set_reset; + Bit8u enable_set_reset; + Bit8u color_compare; + Bit8u data_rotate; + Bit8u read_map_select; + Bit8u mode; + Bit8u miscellaneous; + Bit8u color_dont_care; + Bit8u bit_mask; +} VGA_Gfx; + +struct RGBEntry { + Bit8u red; + Bit8u green; + Bit8u blue; + Bit8u attr_entry; +}; + +typedef struct { + Bit8u bits; /* DAC bits, usually 6 or 8 */ + Bit8u pel_mask; + Bit8u pel_index; + Bit8u state; + Bit8u index; + Bitu first_changed; + RGBEntry rgb[0x100]; +} VGA_Dac; + +union VGA_Latch { + Bit32u d; + Bit8u b[4]; +}; + +union VGA_Memory { + Bit8u linear[64*1024*4]; + Bit8u paged[64*1024][4]; + VGA_Latch latched[64*1024]; +}; + + + +typedef struct { + Bitu mode; /* The mode the vga system is in */ + VGA_Draw draw; + VGA_Config config; + VGA_Internal internal; +/* Internal module groups */ + VGA_Seq seq; + VGA_Attr attr; + VGA_Crtc crtc; + VGA_Gfx gfx; + VGA_Dac dac; + VGA_Latch latch; + VGA_Memory mem; +//Special little hack to let the memory run over into the buffer + Bit8u buffer[1024*1024]; +} VGA_Type; + + + + + +/* Functions for different resolutions */ +//void VGA_FindSize(void); +void VGA_FindSettings(void); +void VGA_StartResize(void); + +/* The Different Drawing functions */ +void VGA_DrawTEXT(Bit8u * bitdata,Bitu next_line); +void VGA_DrawGFX256_Fast(Bit8u * bitdata,Bitu next_line); +void VGA_DrawGFX256_Full(Bit8u * bitdata,Bitu next_line); +void VGA_DrawGFX16_Full(Bit8u * bitdata,Bitu next_line); +void VGA_DrawGFX4_Full(Bit8u * bitdata,Bitu next_line); +/* The Different Memory Read/Write Handlers */ +Bit8u VGA_NormalReadHandler(Bit32u start); +void VGA_NormalWriteHandler(Bit32u start,Bit8u val); + +void VGA_GFX_256U_WriteHandler(Bit32u start,Bit8u val); +void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val); +void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val); + +Bit8u VGA_ChainedReadHandler(Bit32u start); +void VGA_ChainedWriteHandler(Bit32u start,Bit8u val); + +Bit8u VGA_GFX_4_ReadHandler(Bit32u start); + + + +/* Some support functions */ +void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal); + + +/* The VGA Subfunction startups */ +void VGA_SetupAttr(void); +void VGA_SetupMemory(void); +void VGA_SetupDAC(void); +void VGA_SetupCRTC(void); +void VGA_SetupMisc(void); +void VGA_SetupGFX(void); +void VGA_SetupSEQ(void); + +/* Some Support Functions */ +void VGA_DACSetEntirePalette(void); + +extern VGA_Type vga; +extern Bit8u vga_rom_8[256 * 8]; +extern Bit8u vga_rom_14[256 * 14]; +extern Bit8u vga_rom_16[256 * 16]; +//extern Bit8u vga_buffer[1024*1024]; +extern Bit32u ExpandTable[256]; +extern Bit32u FillTable[16]; +extern Bit32u CGAWriteTable[256]; + +#endif + diff --git a/src/hardware/vga_attr.cpp b/src/hardware/vga_attr.cpp index e5e4022..4b0473f 100644 --- a/src/hardware/vga_attr.cpp +++ b/src/hardware/vga_attr.cpp @@ -1,226 +1,165 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_attr.cpp,v 1.29 2008/10/05 14:44:52 qbix79 Exp $ */ - -#include "dosbox.h" -#include "inout.h" -#include "vga.h" - -#define attr(blah) vga.attr.blah - -void VGA_ATTR_SetPalette(Bit8u index,Bit8u val) { - vga.attr.palette[index] = val; - if (vga.attr.mode_control & 0x80) val = (val&0xf) | (vga.attr.color_select << 4); - val &= 63; - val |= (vga.attr.color_select & 0xc) << 4; - if (GCC_UNLIKELY(machine==MCH_EGA)) { - if ((vga.crtc.vertical_total | ((vga.crtc.overflow & 1) << 8)) == 260) { - // check for intensity bit - if (val&0x10) val|=0x38; - else { - val&=0x7; - // check for special brown - if (val==6) val=0x14; - } - } - } - VGA_DAC_CombineColor(index,val); -} - -Bitu read_p3c0(Bitu port,Bitu iolen) { -//Wcharts - return 0x0; -} - -void write_p3c0(Bitu port,Bitu val,Bitu iolen) { - if (!vga.internal.attrindex) { - attr(index)=val & 0x1F; - vga.internal.attrindex=true; - attr(enabled)=val & 0x20; - /* - 0-4 Address of data register to write to port 3C0h or read from port 3C1h - 5 If set screen output is enabled and the palette can not be modified, - if clear screen output is disabled and the palette can be modified. - */ - return; - } else { - vga.internal.attrindex=false; - switch (attr(index)) { - /* Palette */ - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - if (!attr(enabled)) VGA_ATTR_SetPalette(attr(index),val); - /* - 0-5 Index into the 256 color DAC table. May be modified by 3C0h index - 10h and 14h. - */ - break; - case 0x10: /* Mode Control Register */ - if (!IS_VGA_ARCH) val&=0x1f; // not really correct, but should do it - if ((attr(mode_control) ^ val) & 0x80) { - attr(mode_control)^=0x80; - for (Bitu i=0;i<0x10;i++) { - VGA_ATTR_SetPalette(i,vga.attr.palette[i]); - } - } - if ((attr(mode_control) ^ val) & 0x08) { - VGA_SetBlinking(val & 0x8); - } - if ((attr(mode_control) ^ val) & 0x04) { - attr(mode_control)=val; - VGA_DetermineMode(); - if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) VGA_StartResize(); - } else { - attr(mode_control)=val; - VGA_DetermineMode(); - } - - /* - 0 Graphics mode if set, Alphanumeric mode else. - 1 Monochrome mode if set, color mode else. - 2 9-bit wide characters if set. - The 9th bit of characters C0h-DFh will be the same as - the 8th bit. Otherwise it will be the background color. - 3 If set Attribute bit 7 is blinking, else high intensity. - 5 If set the PEL panning register (3C0h index 13h) is temporarily set - to 0 from when the line compare causes a wrap around until the next - vertical retrace when the register is automatically reloaded with - the old value, else the PEL panning register ignores line compares. - 6 If set pixels are 8 bits wide. Used in 256 color modes. - 7 If set bit 4-5 of the index into the DAC table are taken from port - 3C0h index 14h bit 0-1, else the bits in the palette register are - used. - */ - break; - case 0x11: /* Overscan Color Register */ - attr(overscan_color)=val; - /* 0-5 Color of screen border. Color is defined as in the palette registers. */ - break; - case 0x12: /* Color Plane Enable Register */ - /* Why disable colour planes? */ - attr(color_plane_enable)=val; - /* - 0 Bit plane 0 is enabled if set. - 1 Bit plane 1 is enabled if set. - 2 Bit plane 2 is enabled if set. - 3 Bit plane 3 is enabled if set. - 4-5 Video Status MUX. Diagnostics use only. - Two attribute bits appear on bits 4 and 5 of the Input Status - Register 1 (3dAh). 0: Bit 2/0, 1: Bit 5/4, 2: bit 3/1, 3: bit 7/6 - */ - break; - case 0x13: /* Horizontal PEL Panning Register */ - attr(horizontal_pel_panning)=val & 0xF; - switch (vga.mode) { - case M_TEXT: - if ((val==0x7) && (svgaCard==SVGA_None)) vga.config.pel_panning=7; - if (val>0x7) vga.config.pel_panning=0; - else vga.config.pel_panning=val+1; - break; - case M_VGA: - case M_LIN8: - vga.config.pel_panning=(val & 0x7)/2; - break; - case M_LIN16: - default: - vga.config.pel_panning=(val & 0x7); - } - /* - 0-3 Indicates number of pixels to shift the display left - Value 9bit textmode 256color mode Other modes - 0 1 0 0 - 1 2 n/a 1 - 2 3 1 2 - 3 4 n/a 3 - 4 5 2 4 - 5 6 n/a 5 - 6 7 3 6 - 7 8 n/a 7 - 8 0 n/a n/a - */ - break; - case 0x14: /* Color Select Register */ - if (!IS_VGA_ARCH) { - attr(color_select)=0; - break; - } - if (attr(color_select) ^ val) { - attr(color_select)=val; - for (Bitu i=0;i<0x10;i++) { - VGA_ATTR_SetPalette(i,vga.attr.palette[i]); - } - } - /* - 0-1 If 3C0h index 10h bit 7 is set these 2 bits are used as bits 4-5 of - the index into the DAC table. - 2-3 These 2 bits are used as bit 6-7 of the index into the DAC table - except in 256 color mode. - Note: this register does not affect 256 color modes. - */ - break; - default: - if (svga.write_p3c0) { - svga.write_p3c0(attr(index), val, iolen); - break; - } - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:Write to unkown Index %2X",attr(index)); - break; - } - } -} - -Bitu read_p3c1(Bitu port,Bitu iolen) { -// vga.internal.attrindex=false; - switch (attr(index)) { - /* Palette */ - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - return attr(palette[attr(index)]); - case 0x10: /* Mode Control Register */ - return attr(mode_control); - case 0x11: /* Overscan Color Register */ - return attr(overscan_color); - case 0x12: /* Color Plane Enable Register */ - return attr(color_plane_enable); - case 0x13: /* Horizontal PEL Panning Register */ - return attr(horizontal_pel_panning); - case 0x14: /* Color Select Register */ - return attr(color_select); - default: - if (svga.read_p3c1) - return svga.read_p3c1(attr(index), iolen); - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:Read from unkown Index %2X",attr(index)); - } - return 0; -} - - -void VGA_SetupAttr(void) { - if (IS_EGAVGA_ARCH) { - IO_RegisterWriteHandler(0x3c0,write_p3c0,IO_MB); - if (IS_VGA_ARCH) { - IO_RegisterReadHandler(0x3c0,read_p3c0,IO_MB); - IO_RegisterReadHandler(0x3c1,read_p3c1,IO_MB); - } - } -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "inout.h" +#include "vga.h" + +#define attr(blah) vga.attr.blah + +void write_p3c0(Bit32u port,Bit8u val) { + if (!vga.internal.attrindex) { + attr(index)=val & 0x1F; + vga.internal.attrindex=true; + /* + 0-4 Address of data register to write to port 3C0h or read from port 3C1h + If set screen output is enabled and the palette can not be modified, + if clear screen output is disabled and the palette can be modified. + */ + return; + } else { + vga.internal.attrindex=false; + switch (attr(index)) { + /* Palette */ + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + attr(palette[attr(index)])=val; + VGA_DAC_CombineColor(attr(index),val); + /* + 0-5 Index into the 256 color DAC table. May be modified by 3C0h index + 10h and 14h. + */ + break; + case 0x10: /* Mode Control Register */ + attr(mode_control)=val; + vga.config.gfxmode=val&1; + vga.config.vga_enabled=(val & 64)>0; + VGA_FindSettings(); + //TODO Monochrome mode + //TODO 9 bit characters + //TODO line wrapping split screen shit see bit 5 + //TODO index 14h weirdo dac switch bits + /* + 0 Graphics mode if set, Alphanumeric mode else. + 1 Monochrome mode if set, color mode else. + 2 9-bit wide characters if set. + The 9th bit of characters C0h-DFh will be the same as + the 8th bit. Otherwise it will be the background color. + 3 If set Attribute bit 7 is blinking, else high intensity. + 5 If set the PEL panning register (3C0h index 13h) is temporarily set + to 0 from when the line compare causes a wrap around until the next + vertical retrace when the register is automatically reloaded with + the old value, else the PEL panning register ignores line compares. + 6 If set pixels are 8 bits wide. Used in 256 color modes. + 7 If set bit 4-5 of the index into the DAC table are taken from port + 3C0h index 14h bit 0-1, else the bits in the palette register are + used. + */ + if (val&128) { + E_Exit("VGA:Special 16 colour DAC Shift"); + } + break; + case 0x11: /* Overscan Color Register */ + attr(overscan_color)=val; + /* 0-5 Color of screen border. Color is defined as in the palette registers. */ + break; + case 0x12: /* Color Plane Enable Register */ + /* Why disable colour planes? */ + attr(color_plane_enable)=val; + /* + 0 Bit plane 0 is enabled if set. + 1 Bit plane 1 is enabled if set. + 2 Bit plane 2 is enabled if set. + 3 Bit plane 3 is enabled if set. + 4-5 Video Status MUX. Diagnostics use only. + Two attribute bits appear on bits 4 and 5 of the Input Status + Register 1 (3dAh). 0: Bit 2/0, 1: Bit 5/4, 2: bit 3/1, 3: bit 7/6 + */ + break; + case 0x13: /* Horizontal PEL Panning Register */ + attr(horizontal_pel_panning)=val & 0xF; + vga.config.pel_panning=val & 0xF; + /* + 0-3 Indicates number of pixels to shift the display left + Value 9bit textmode 256color mode Other modes + 0 1 0 0 + 1 2 n/a 1 + 2 3 1 2 + 3 4 n/a 3 + 4 5 2 4 + 5 6 n/a 5 + 6 7 3 6 + 7 8 n/a 7 + 8 0 n/a n/a + */ + break; + case 0x14: /* Color Select Register */ + attr(color_select)=val; + /* + 0-1 If 3C0h index 10h bit 7 is set these 2 bits are used as bits 4-5 of + the index into the DAC table. + 2-3 These 2 bits are used as bit 6-7 of the index into the DAC table + except in 256 color mode. + Note: this register does not affect 256 color modes. + */ + if (val) LOG_DEBUG("VGA:ATTR:DAC index set to %d",val); + break; + default: + LOG_ERROR("VGA:ATTR:Write to unkown Index %2X",attr(index)); + break; + } + } +} + +Bit8u read_p3c1(Bit32u port) { + switch (attr(index)) { + /* Palette */ + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + return attr(palette[attr(index)]); + case 0x10: /* Mode Control Register */ + return attr(mode_control); + case 0x11: /* Overscan Color Register */ + return attr(overscan_color); + case 0x12: /* Color Plane Enable Register */ + return attr(color_plane_enable); + case 0x13: /* Horizontal PEL Panning Register */ + return attr(horizontal_pel_panning); + case 0x14: /* Color Select Register */ + return attr(color_select); + default: + LOG_ERROR("VGA:ATTR:Read from unkown Index %2X",attr(index)); + } + return 0; +}; + + + + + + +void VGA_SetupAttr(void) { + IO_RegisterWriteHandler(0x3c0,write_p3c0,"VGA Attribute controller"); + IO_RegisterReadHandler(0x3c1,read_p3c1,"VGA Attribute Read"); +} + + diff --git a/src/hardware/vga_crtc.cpp b/src/hardware/vga_crtc.cpp index e361490..99f1ac1 100644 --- a/src/hardware/vga_crtc.cpp +++ b/src/hardware/vga_crtc.cpp @@ -1,432 +1,332 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_crtc.cpp,v 1.34 2009/03/18 18:08:16 c2woody Exp $ */ - -#include -#include "dosbox.h" -#include "inout.h" -#include "vga.h" -#include "debug.h" -#include "cpu.h" -#include "video.h" -#include "pic.h" - -#define crtc(blah) vga.crtc.blah - - -void VGA_MapMMIO(void); -void VGA_UnmapMMIO(void); - -void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen); -Bitu DEBUG_EnableDebugger(void); - -void vga_write_p3d4(Bitu port,Bitu val,Bitu iolen) { - crtc(index)=val; -} - -Bitu vga_read_p3d4(Bitu port,Bitu iolen) { - return crtc(index); -} - -void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen) { -// if (crtc(index)>0x18) LOG_MSG("VGA CRCT write %X to reg %X",val,crtc(index)); - switch(crtc(index)) { - case 0x00: /* Horizontal Total Register */ - if (crtc(read_only)) break; - crtc(horizontal_total)=val; - /* 0-7 Horizontal Total Character Clocks-5 */ - break; - case 0x01: /* Horizontal Display End Register */ - if (crtc(read_only)) break; - if (val != crtc(horizontal_display_end)) { - crtc(horizontal_display_end)=val; - VGA_StartResize(); - } - /* 0-7 Number of Character Clocks Displayed -1 */ - break; - case 0x02: /* Start Horizontal Blanking Register */ - if (crtc(read_only)) break; - crtc(start_horizontal_blanking)=val; - /* 0-7 The count at which Horizontal Blanking starts */ - break; - case 0x03: /* End Horizontal Blanking Register */ - if (crtc(read_only)) break; - crtc(end_horizontal_blanking)=val; - /* - 0-4 Horizontal Blanking ends when the last 6 bits of the character - counter equals this field. Bit 5 is at 3d4h index 5 bit 7. - 5-6 Number of character clocks to delay start of display after Horizontal - Total has been reached. - 7 Access to Vertical Retrace registers if set. If clear reads to 3d4h - index 10h and 11h access the Lightpen read back registers ?? - */ - break; - case 0x04: /* Start Horizontal Retrace Register */ - if (crtc(read_only)) break; - crtc(start_horizontal_retrace)=val; - /* 0-7 Horizontal Retrace starts when the Character Counter reaches this value. */ - break; - case 0x05: /* End Horizontal Retrace Register */ - if (crtc(read_only)) break; - crtc(end_horizontal_retrace)=val; - /* - 0-4 Horizontal Retrace ends when the last 5 bits of the character counter - equals this value. - 5-6 Number of character clocks to delay start of display after Horizontal - Retrace. - 7 bit 5 of the End Horizontal Blanking count (See 3d4h index 3 bit 0-4) - */ - break; - case 0x06: /* Vertical Total Register */ - if (crtc(read_only)) break; - if (val != crtc(vertical_total)) { - crtc(vertical_total)=val; - VGA_StartResize(); - } - /* 0-7 Lower 8 bits of the Vertical Total. Bit 8 is found in 3d4h index 7 - bit 0. Bit 9 is found in 3d4h index 7 bit 5. - Note: For the VGA this value is the number of scan lines in the display -2. - */ - break; - case 0x07: /* Overflow Register */ - //Line compare bit ignores read only */ - vga.config.line_compare=(vga.config.line_compare & 0x6ff) | (val & 0x10) << 4; - if (crtc(read_only)) break; - if ((vga.crtc.overflow ^ val) & 0xd6) { - crtc(overflow)=val; - VGA_StartResize(); - } else crtc(overflow)=val; - /* - 0 Bit 8 of Vertical Total (3d4h index 6) - 1 Bit 8 of Vertical Display End (3d4h index 12h) - 2 Bit 8 of Vertical Retrace Start (3d4h index 10h) - 3 Bit 8 of Start Vertical Blanking (3d4h index 15h) - 4 Bit 8 of Line Compare Register (3d4h index 18h) - 5 Bit 9 of Vertical Total (3d4h index 6) - 6 Bit 9 of Vertical Display End (3d4h index 12h) - 7 Bit 9 of Vertical Retrace Start (3d4h index 10h) - */ - break; - case 0x08: /* Preset Row Scan Register */ - crtc(preset_row_scan)=val; - vga.config.hlines_skip=val&31; - if (IS_VGA_ARCH) vga.config.bytes_skip=(val>>5)&3; - else vga.config.bytes_skip=0; -// LOG_DEBUG("Skip lines %d bytes %d",vga.config.hlines_skip,vga.config.bytes_skip); - /* - 0-4 Number of lines we have scrolled down in the first character row. - Provides Smooth Vertical Scrolling.b - 5-6 Number of bytes to skip at the start of scanline. Provides Smooth - Horizontal Scrolling together with the Horizontal Panning Register - (3C0h index 13h). - */ - break; - case 0x09: /* Maximum Scan Line Register */ - if (IS_VGA_ARCH) - vga.config.line_compare=(vga.config.line_compare & 0x5ff)|(val&0x40)<<3; - - if (IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA)) { - // in vgaonly mode we take special care of line repeats (excluding CGA modes) - if ((vga.crtc.maximum_scan_line ^ val) & 0x20) { - crtc(maximum_scan_line)=val; - VGA_StartResize(); - } else { - crtc(maximum_scan_line)=val; - } - vga.draw.address_line_total = (val &0x1F) + 1; - if (val&0x80) vga.draw.address_line_total*=2; - } else { - if ((vga.crtc.maximum_scan_line ^ val) & 0xbf) { - crtc(maximum_scan_line)=val; - VGA_StartResize(); - } else { - crtc(maximum_scan_line)=val; - } - } - /* - 0-4 Number of scan lines in a character row -1. In graphics modes this is - the number of times (-1) the line is displayed before passing on to - the next line (0: normal, 1: double, 2: triple...). - This is independent of bit 7, except in CGA modes which seems to - require this field to be 1 and bit 7 to be set to work. - 5 Bit 9 of Start Vertical Blanking - 6 Bit 9 of Line Compare Register - 7 Doubles each scan line if set. I.e. displays 200 lines on a 400 display. - */ - break; - case 0x0A: /* Cursor Start Register */ - crtc(cursor_start)=val; - vga.draw.cursor.sline=val&0x1f; - if (IS_VGA_ARCH) vga.draw.cursor.enabled=!(val&0x20); - else vga.draw.cursor.enabled=true; - /* - 0-4 First scanline of cursor within character. - 5 Turns Cursor off if set - */ - break; - case 0x0B: /* Cursor End Register */ - crtc(cursor_end)=val; - vga.draw.cursor.eline=val&0x1f; - vga.draw.cursor.delay=(val>>5)&0x3; - - /* - 0-4 Last scanline of cursor within character - 5-6 Delay of cursor data in character clocks. - */ - break; - case 0x0C: /* Start Address High Register */ - crtc(start_address_high)=val; - vga.config.display_start=(vga.config.display_start & 0xFF00FF)| (val << 8); - /* 0-7 Upper 8 bits of the start address of the display buffer */ - break; - case 0x0D: /* Start Address Low Register */ - crtc(start_address_low)=val; - vga.config.display_start=(vga.config.display_start & 0xFFFF00)| val; - /* 0-7 Lower 8 bits of the start address of the display buffer */ - break; - case 0x0E: /*Cursor Location High Register */ - crtc(cursor_location_high)=val; - vga.config.cursor_start&=0xff00ff; - vga.config.cursor_start|=val << 8; - /* 0-7 Upper 8 bits of the address of the cursor */ - break; - case 0x0F: /* Cursor Location Low Register */ -//TODO update cursor on screen - crtc(cursor_location_low)=val; - vga.config.cursor_start&=0xffff00; - vga.config.cursor_start|=val; - /* 0-7 Lower 8 bits of the address of the cursor */ - break; - case 0x10: /* Vertical Retrace Start Register */ - crtc(vertical_retrace_start)=val; - /* - 0-7 Lower 8 bits of Vertical Retrace Start. Vertical Retrace starts when - the line counter reaches this value. Bit 8 is found in 3d4h index 7 - bit 2. Bit 9 is found in 3d4h index 7 bit 7. - */ - break; - case 0x11: /* Vertical Retrace End Register */ - crtc(vertical_retrace_end)=val; - - if (IS_EGAVGA_ARCH && !(val & 0x10)) { - vga.draw.vret_triggered=false; - if (GCC_UNLIKELY(machine==MCH_EGA)) PIC_DeActivateIRQ(9); - } - if (IS_VGA_ARCH) crtc(read_only)=(val & 128)>0; - else crtc(read_only)=false; - /* - 0-3 Vertical Retrace ends when the last 4 bits of the line counter equals - this value. - 4 if clear Clears pending Vertical Interrupts. - 5 Vertical Interrupts (IRQ 2) disabled if set. Can usually be left - disabled, but some systems (including PS/2) require it to be enabled. - 6 If set selects 5 refresh cycles per scanline rather than 3. - 7 Disables writing to registers 0-7 if set 3d4h index 7 bit 4 is not - affected by this bit. - */ - break; - case 0x12: /* Vertical Display End Register */ - if (val!=crtc(vertical_display_end)) { - if (abs((Bits)val-(Bits)crtc(vertical_display_end))<3) { - // delay small vde changes a bit to avoid screen resizing - // if they are reverted in a short timeframe - PIC_RemoveEvents(VGA_SetupDrawing); - vga.draw.resizing=false; - crtc(vertical_display_end)=val; - VGA_StartResize(150); - } else { - crtc(vertical_display_end)=val; - VGA_StartResize(); - } - } - /* - 0-7 Lower 8 bits of Vertical Display End. The display ends when the line - counter reaches this value. Bit 8 is found in 3d4h index 7 bit 1. - Bit 9 is found in 3d4h index 7 bit 6. - */ - break; - case 0x13: /* Offset register */ - crtc(offset)=val; - vga.config.scan_len&=0x300; - vga.config.scan_len|=val; - VGA_CheckScanLength(); - /* - 0-7 Number of bytes in a scanline / K. Where K is 2 for byte mode, 4 for - word mode and 8 for Double Word mode. - */ - break; - case 0x14: /* Underline Location Register */ - crtc(underline_location)=val; - if (IS_VGA_ARCH) { - //Byte,word,dword mode - if ( crtc(underline_location) & 0x20 ) - vga.config.addr_shift = 2; - else if ( crtc( mode_control) & 0x40 ) - vga.config.addr_shift = 0; - else - vga.config.addr_shift = 1; - } else { - vga.config.addr_shift = 1; - } - /* - 0-4 Position of underline within Character cell. - 5 If set memory address is only changed every fourth character clock. - 6 Double Word mode addressing if set - */ - break; - case 0x15: /* Start Vertical Blank Register */ - if (val!=crtc(start_vertical_blanking)) { - crtc(start_vertical_blanking)=val; - VGA_StartResize(); - } - /* - 0-7 Lower 8 bits of Vertical Blank Start. Vertical blanking starts when - the line counter reaches this value. Bit 8 is found in 3d4h index 7 - bit 3. - */ - break; - case 0x16: /* End Vertical Blank Register */ - crtc(end_vertical_blanking)=val; - /* - 0-6 Vertical blanking stops when the lower 7 bits of the line counter - equals this field. Some SVGA chips uses all 8 bits! - */ - break; - case 0x17: /* Mode Control Register */ - crtc(mode_control)=val; - vga.tandy.line_mask = (~val) & 3; - //Byte,word,dword mode - if ( crtc(underline_location) & 0x20 ) - vga.config.addr_shift = 2; - else if ( crtc( mode_control) & 0x40 ) - vga.config.addr_shift = 0; - else - vga.config.addr_shift = 1; - - if ( vga.tandy.line_mask ) { - vga.tandy.line_shift = 13; - vga.tandy.addr_mask = (1 << 13) - 1; - } else { - vga.tandy.addr_mask = ~0; - vga.tandy.line_shift = 0; - } - //Should we really need to do a determinemode here? -// VGA_DetermineMode(); - /* - 0 If clear use CGA compatible memory addressing system - by substituting character row scan counter bit 0 for address bit 13, - thus creating 2 banks for even and odd scan lines. - 1 If clear use Hercules compatible memory addressing system by - substituting character row scan counter bit 1 for address bit 14, - thus creating 4 banks. - 2 If set increase scan line counter only every second line. - 3 If set increase memory address counter only every other character clock. - 5 When in Word Mode bit 15 is rotated to bit 0 if this bit is set else - bit 13 is rotated into bit 0. - 6 If clear system is in word mode. Addresses are rotated 1 position up - bringing either bit 13 or 15 into bit 0. - 7 Clearing this bit will reset the display system until the bit is set again. - */ - break; - case 0x18: /* Line Compare Register */ - crtc(line_compare)=val; - vga.config.line_compare=(vga.config.line_compare & 0x700) | val; - /* - 0-7 Lower 8 bits of the Line Compare. When the Line counter reaches this - value, the display address wraps to 0. Provides Split Screen - facilities. Bit 8 is found in 3d4h index 7 bit 4. - Bit 9 is found in 3d4h index 9 bit 6. - */ - break; - default: - if (svga.write_p3d5) { - svga.write_p3d5(crtc(index), val, iolen); - } else { - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:Write to unknown index %X",crtc(index)); - } - break; - } -} - -Bitu vga_read_p3d5(Bitu port,Bitu iolen) { -// LOG_MSG("VGA CRCT read from reg %X",crtc(index)); - switch(crtc(index)) { - case 0x00: /* Horizontal Total Register */ - return crtc(horizontal_total); - case 0x01: /* Horizontal Display End Register */ - return crtc(horizontal_display_end); - case 0x02: /* Start Horizontal Blanking Register */ - return crtc(start_horizontal_blanking); - case 0x03: /* End Horizontal Blanking Register */ - return crtc(end_horizontal_blanking); - case 0x04: /* Start Horizontal Retrace Register */ - return crtc(start_horizontal_retrace); - case 0x05: /* End Horizontal Retrace Register */ - return crtc(end_horizontal_retrace); - case 0x06: /* Vertical Total Register */ - return crtc(vertical_total); - case 0x07: /* Overflow Register */ - return crtc(overflow); - case 0x08: /* Preset Row Scan Register */ - return crtc(preset_row_scan); - case 0x09: /* Maximum Scan Line Register */ - return crtc(maximum_scan_line); - case 0x0A: /* Cursor Start Register */ - return crtc(cursor_start); - case 0x0B: /* Cursor End Register */ - return crtc(cursor_end); - case 0x0C: /* Start Address High Register */ - return crtc(start_address_high); - case 0x0D: /* Start Address Low Register */ - return crtc(start_address_low); - case 0x0E: /*Cursor Location High Register */ - return crtc(cursor_location_high); - case 0x0F: /* Cursor Location Low Register */ - return crtc(cursor_location_low); - case 0x10: /* Vertical Retrace Start Register */ - return crtc(vertical_retrace_start); - case 0x11: /* Vertical Retrace End Register */ - return crtc(vertical_retrace_end); - case 0x12: /* Vertical Display End Register */ - return crtc(vertical_display_end); - case 0x13: /* Offset register */ - return crtc(offset); - case 0x14: /* Underline Location Register */ - return crtc(underline_location); - case 0x15: /* Start Vertical Blank Register */ - return crtc(start_vertical_blanking); - case 0x16: /* End Vertical Blank Register */ - return crtc(end_vertical_blanking); - case 0x17: /* Mode Control Register */ - return crtc(mode_control); - case 0x18: /* Line Compare Register */ - return crtc(line_compare); - default: - if (svga.read_p3d5) { - return svga.read_p3d5(crtc(index), iolen); - } else { - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:Read from unknown index %X",crtc(index)); - return 0x0; - } - } -} - - - - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "inout.h" +#include "vga.h" + + + +#define crtc(blah) vga.crtc.blah + +void write_p3d4(Bit32u port,Bit8u val) { + crtc(index)=val; +} + +void write_p3d5(Bit32u port,Bit8u val) { + switch(crtc(index)) { + case 0x00: /* Horizontal Total Register */ + crtc(horizontal_total)=val; + /* 0-7 Horizontal Total Character Clocks-5 */ + break; + case 0x01: /* Horizontal Display End Register */ + crtc(horizontal_display_end)=val; + vga.config.hdisplayend=val+1; + VGA_FindSettings(); + /* 0-7 Number of Character Clocks Displayed -1 */ + break; + case 0x02: /* Start Horizontal Blanking Register */ + crtc(start_horizontal_blanking)=val; + /* 0-7 The count at which Horizontal Blanking starts */ + break; + case 0x03: /* End Horizontal Blanking Register */ + crtc(end_horizontal_blanking)=val; + /* + 0-4 Horizontal Blanking ends when the last 6 bits of the character + counter equals this field. Bit 5 is at 3d4h index 5 bit 7. + 5-6 Number of character clocks to delay start of display after Horizontal + Total has been reached. + 7 Access to Vertical Retrace registers if set. If clear reads to 3d4h + index 10h and 11h access the Lightpen read back registers ?? + */ + break; + case 0x04: /* Start Horizontal Retrace Register */ + crtc(start_horizontal_retrace)=val; + /* 0-7 Horizontal Retrace starts when the Character Counter reaches this value. */ + break; + case 0x05: /* End Horizontal Retrace Register */ + crtc(end_horizontal_retrace)=val; + /* + 0-4 Horizontal Retrace ends when the last 5 bits of the character counter + equals this value. + 5-6 Number of character clocks to delay start of display after Horizontal + Retrace. + 7 bit 5 of the End Horizontal Blanking count (See 3d4h index 3 bit 0-4) + */ + break; + case 0x06: /* Vertical Total Register */ + crtc(vertical_total)=val; + /* 0-7 Lower 8 bits of the Vertical Total. Bit 8 is found in 3d4h index 7 + bit 0. Bit 9 is found in 3d4h index 7 bit 5. + Note: For the VGA this value is the number of scan lines in the display -2. + */ + break; + case 0x07: /* Overflow Register */ + crtc(overflow)=val; + vga.config.vdisplayend=(vga.config.vdisplayend&0xFF)|((val&2)<<7)|((val&64)<<2); + VGA_FindSettings(); + /* + 0 Bit 8 of Vertical Total (3d4h index 6) + 1 Bit 8 of Vertical Display End (3d4h index 12h) + 2 Bit 8 of Vertical Retrace Start (3d4h index 10h) + 3 Bit 8 of Start Vertical Blanking (3d4h index 15h) + 4 Bit 8 of Line Compare Register (3d4h index 18h) + 5 Bit 9 of Vertical Total (3d4h index 6) + 6 Bit 9 of Vertical Display End (3d4h index 12h) + 7 Bit 9 of Vertical Retrace Start (3d4h index 10h) + */ + break; + case 0x08: /* Preset Row Scan Register */ + crtc(preset_row_scan)=val; + vga.config.hlines_skip=val&31; + vga.config.bytes_skip=(val>>5)&3; +// LOG_DEBUG("Skip lines %d bytes %d",vga.config.hlines_skip,vga.config.bytes_skip); + /* + 0-4 Number of lines we have scrolled down in the first character row. + Provides Smooth Vertical Scrolling.b + 5-6 Number of bytes to skip at the start of scanline. Provides Smooth + Horizontal Scrolling together with the Horizontal Panning Register + (3C0h index 13h). + */ + break; + case 0x09: /* Maximum Scan Line Register */ + crtc(maximum_scan_line)=val; + vga.config.vline_double=(val & 128)>1; + vga.config.vline_height=(val & 0xf); + VGA_FindSettings(); + /* + 0-4 Number of scan lines in a character row -1. In graphics modes this is + the number of times (-1) the line is displayed before passing on to + the next line (0: normal, 1: double, 2: triple...). + This is independent of bit 7, except in CGA modes which seems to + require this field to be 1 and bit 7 to be set to work. + 5 Bit 9 of Start Vertical Blanking + 6 Bit 9 of Line Compare Register + 7 Doubles each scan line if set. I.e. displays 200 lines on a 400 display. + */ + break; + case 0x0A: /* Cursor Start Register */ + crtc(cursor_start)=val; + /* + 0-4 First scanline of cursor within character. + 5 Turns Cursor off if set + */ + break; + case 0x0B: /* Cursor End Register */ + crtc(cursor_end)=val; + /* + 0-4 Last scanline of cursor within character + 5-6 Delay of cursor data in character clocks. + */ + break; + case 0x0C: /* Start Address High Register */ + crtc(start_address_high)=val; + vga.config.display_start=(vga.config.display_start & 0x00FF)| (val << 8); + /* 0-7 Upper 8 bits of the start address of the display buffer */ + break; + case 0x0D: /* Start Address Low Register */ + crtc(start_address_low)=val; + vga.config.display_start=(vga.config.display_start & 0xFF00)| val; + /* 0-7 Lower 8 bits of the start address of the display buffer */ + break; + case 0x0E: /*Cursor Location High Register */ + crtc(cursor_location_high)=val; + if (vga.config.scan_len<2) break; + vga.draw.cursor_row=(crtc(cursor_location_high)<<8|crtc(cursor_location_low))/(vga.config.scan_len*2); + vga.draw.cursor_col=(crtc(cursor_location_high)<<8|crtc(cursor_location_low))%(vga.config.scan_len*2); + /* 0-7 Upper 8 bits of the address of the cursor */ + break; + case 0x0F: /* Cursor Location Low Register */ +//TODO update cursor on screen + crtc(cursor_location_low)=val; + if (vga.config.scan_len<2) break; + vga.draw.cursor_row=(crtc(cursor_location_high)<<8|crtc(cursor_location_low))/(vga.config.scan_len*2); + vga.draw.cursor_col=(crtc(cursor_location_high)<<8|crtc(cursor_location_low))%(vga.config.scan_len*2); + /* 0-7 Lower 8 bits of the address of the cursor */ + break; + case 0x10: /* Vertical Retrace Start Register */ + crtc(vertical_retrace_start)=val; + /* + 0-7 Lower 8 bits of Vertical Retrace Start. Vertical Retrace starts when + the line counter reaches this value. Bit 8 is found in 3d4h index 7 + bit 2. Bit 9 is found in 3d4h index 7 bit 7. + */ + break; + case 0x11: /* Vertical Retrace End Register */ + crtc(vertical_retrace_end)=val; + /* + 0-3 Vertical Retrace ends when the last 4 bits of the line counter equals + this value. + 4 if clear Clears pending Vertical Interrupts. + 5 Vertical Interrupts (IRQ 2) disabled if set. Can usually be left + disabled, but some systems (including PS/2) require it to be enabled. + 6 If set selects 5 refresh cycles per scanline rather than 3. + 7 Disables writing to registers 0-7 if set 3d4h index 7 bit 4 is not + affected by this bit. + */ + break; + case 0x12: /* Vertical Display End Register */ + crtc(vertical_display_end)=val; + vga.config.vdisplayend=(vga.config.vdisplayend & 0x300)|val; + VGA_FindSettings(); + /* + 0-7 Lower 8 bits of Vertical Display End. The display ends when the line + counter reaches this value. Bit 8 is found in 3d4h index 7 bit 1. + Bit 9 is found in 3d4h index 7 bit 6. + */ + break; + case 0x13: /* Offset register */ + crtc(offset)=val; + vga.config.scan_len=val; + VGA_FindSettings(); + /* + 0-7 Number of bytes in a scanline / K. Where K is 2 for byte mode, 4 for + word mode and 8 for Double Word mode. + */ + break; + case 0x14: /* Underline Location Register */ + crtc(underline_location)=val; + /* + 0-4 Position of underline within Character cell. + 5 If set memory address is only changed every fourth character clock. + 6 Double Word mode addressing if set + */ + break; + case 0x15: /* Start Vertical Blank Register */ + crtc(start_vertical_blank)=val; + /* + 0-7 Lower 8 bits of Vertical Blank Start. Vertical blanking starts when + the line counter reaches this value. Bit 8 is found in 3d4h index 7 + bit 3. + */ + break; + case 0x16: /* End Vertical Blank Register */ + crtc(end_vertical_blank)=val; + /* + 0-6 Vertical blanking stops when the lower 7 bits of the line counter + equals this field. Some SVGA chips uses all 8 bits! + */ + break; + case 0x17: /* Mode Control Register */ + crtc(mode_control)=val; + vga.config.cga_enabled=!((val&1)>0); + VGA_FindSettings(); + /* + 0 If clear use CGA compatible memory addressing system + by substituting character row scan counter bit 0 for address bit 13, + thus creating 2 banks for even and odd scan lines. + 1 If clear use Hercules compatible memory addressing system by + substituting character row scan counter bit 1 for address bit 14, + thus creating 4 banks. + 2 If set increase scan line counter only every second line. + 3 If set increase memory address counter only every other character clock. + 5 When in Word Mode bit 15 is rotated to bit 0 if this bit is set else + bit 13 is rotated into bit 0. + 6 If clear system is in word mode. Addresses are rotated 1 position up + bringing either bit 13 or 15 into bit 0. + 7 Clearing this bit will reset the display system until the bit is set again. + */ + break; + case 0x18: /* Line Compare Register */ + crtc(line_compare)=val; + /* + 0-7 Lower 8 bits of the Line Compare. When the Line counter reaches this + value, the display address wraps to 0. Provides Split Screen + facilities. Bit 8 is found in 3d4h index 7 bit 4. + Bit 9 is found in 3d4h index 9 bit 6. + */ + + break; + default: + LOG_ERROR("VGA:CRTC:Write to unknown index %2X",val,crtc(index)); + } +} + +Bit8u read_p3d5(Bit32u port) { + switch(crtc(index)) { + case 0x00: /* Horizontal Total Register */ + return crtc(horizontal_total); + case 0x01: /* Horizontal Display End Register */ + return crtc(horizontal_display_end); + case 0x02: /* Start Horizontal Blanking Register */ + return crtc(start_horizontal_blanking); + case 0x03: /* End Horizontal Blanking Register */ + return crtc(end_horizontal_blanking); + case 0x04: /* Start Horizontal Retrace Register */ + return crtc(start_horizontal_retrace); + case 0x05: /* End Horizontal Retrace Register */ + return crtc(end_horizontal_retrace); + case 0x06: /* Vertical Total Register */ + return crtc(vertical_total); + case 0x07: /* Overflow Register */ + return crtc(overflow); + case 0x08: /* Preset Row Scan Register */ + return crtc(preset_row_scan); + case 0x09: /* Maximum Scan Line Register */ + return crtc(maximum_scan_line); + case 0x0A: /* Cursor Start Register */ + return crtc(cursor_start); + case 0x0B: /* Cursor End Register */ + return crtc(cursor_end); + case 0x0C: /* Start Address High Register */ + return crtc(start_address_high); + case 0x0D: /* Start Address Low Register */ + return crtc(start_address_low); + case 0x0E: /*Cursor Location High Register */ + return crtc(cursor_location_high); + case 0x0F: /* Cursor Location Low Register */ + return crtc(cursor_location_low); + case 0x10: /* Vertical Retrace Start Register */ + return crtc(vertical_retrace_start); + case 0x11: /* Vertical Retrace End Register */ + return crtc(vertical_retrace_end); + case 0x12: /* Vertical Display End Register */ + return crtc(vertical_display_end); + case 0x13: /* Offset register */ + return crtc(offset); + case 0x14: /* Underline Location Register */ + return crtc(underline_location); + case 0x15: /* Start Vertical Blank Register */ + return crtc(start_vertical_blank); + case 0x16: /* End Vertical Blank Register */ + return crtc(end_vertical_blank); + case 0x17: /* Mode Control Register */ + return crtc(mode_control); + case 0x18: /* Line Compare Register */ + return crtc(line_compare); + default: + LOG_ERROR("VGA:CRTC:Read from unknown index %X",crtc(index)); + } + return 0; +} + + + +void VGA_SetupCRTC(void) { + IO_RegisterWriteHandler(0x3d4,write_p3d4,"VGA:CRTC Index Select"); + IO_RegisterWriteHandler(0x3d5,write_p3d5,"VGA:CRTC Data Register"); + IO_RegisterReadHandler(0x3d5,read_p3d5,"VGA:CRTC Data Register"); + +// IO_RegisterWriteHandler(0x3b4,write_p3d4,"VGA:CRTC Index Select"); +// IO_RegisterWriteHandler(0x3b5,write_p3d5,"VGA:CRTC Data Register"); +// IO_RegisterReadHandler(0x3b5,read_p3d5,"VGA:CRTC Data Register"); + + + +} + diff --git a/src/hardware/vga_dac.cpp b/src/hardware/vga_dac.cpp index 49cd2a6..b161c86 100644 --- a/src/hardware/vga_dac.cpp +++ b/src/hardware/vga_dac.cpp @@ -1,243 +1,160 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "dosbox.h" -#include "inout.h" -#include "render.h" -#include "vga.h" - -/* -3C6h (R/W): PEL Mask -bit 0-7 This register is anded with the palette index sent for each dot. - Should be set to FFh. - -3C7h (R): DAC State Register -bit 0-1 0 indicates the DAC is in Write Mode and 3 indicates Read mode. - -3C7h (W): PEL Address Read Mode -bit 0-7 The PEL data register (0..255) to be read from 3C9h. -Note: After reading the 3 bytes at 3C9h this register will increment, - pointing to the next data register. - -3C8h (R/W): PEL Address Write Mode -bit 0-7 The PEL data register (0..255) to be written to 3C9h. -Note: After writing the 3 bytes at 3C9h this register will increment, pointing - to the next data register. - -3C9h (R/W): PEL Data Register -bit 0-5 Color value -Note: Each read or write of this register will cycle through first the - registers for Red, Blue and Green, then increment the appropriate - address register, thus the entire palette can be loaded by writing 0 to - the PEL Address Write Mode register 3C8h and then writing all 768 bytes - of the palette to this register. -*/ - -enum {DAC_READ,DAC_WRITE}; - -static INLINE void VGA_DAC_UpdateColor( Bitu index ) { - Bitu maskIndex = index & vga.dac.pel_mask; - vga.dac.xlat16[index] = ((vga.dac.rgb[maskIndex].blue>>1)&0x1f) | - (((vga.dac.rgb[maskIndex].green)&0x3f)<<5)| - (((vga.dac.rgb[maskIndex].red>>1)&0x1f) << 11); - RENDER_SetPal( index, - vga.dac.rgb[maskIndex].red << 2, - vga.dac.rgb[maskIndex].green << 2, - vga.dac.rgb[maskIndex].blue << 2 - ); -} - -static void write_p3c6(Bitu port,Bitu val,Bitu iolen) { - if ( vga.dac.pel_mask != val ) { - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:DCA:Pel Mask set to %X", val); - vga.dac.pel_mask = val; - for ( Bitu i = 0;i<256;i++) - VGA_DAC_UpdateColor( i ); - } -} - - -static Bitu read_p3c6(Bitu port,Bitu iolen) { - return vga.dac.pel_mask; -} - - -static void write_p3c7(Bitu port,Bitu val,Bitu iolen) { - vga.dac.read_index=val; - vga.dac.pel_index=0; - vga.dac.state=DAC_READ; - vga.dac.write_index= val + 1; -} - -static Bitu read_p3c7(Bitu port,Bitu iolen) { - if (vga.dac.state==DAC_READ) return 0x3; - else return 0x0; -} - -static void write_p3c8(Bitu port,Bitu val,Bitu iolen) { - vga.dac.write_index=val; - vga.dac.pel_index=0; - vga.dac.state=DAC_WRITE; -} - -static Bitu read_p3c8(Bitu port, Bitu iolen){ - return vga.dac.write_index; -} - -static void write_p3c9(Bitu port,Bitu val,Bitu iolen) { - val&=0x3f; - switch (vga.dac.pel_index) { - case 0: - vga.dac.rgb[vga.dac.write_index].red=val; - vga.dac.pel_index=1; - break; - case 1: - vga.dac.rgb[vga.dac.write_index].green=val; - vga.dac.pel_index=2; - break; - case 2: - vga.dac.rgb[vga.dac.write_index].blue=val; - switch (vga.mode) { - case M_VGA: - case M_LIN8: - VGA_DAC_UpdateColor( vga.dac.write_index ); - if ( GCC_UNLIKELY( vga.dac.pel_mask != 0xff)) { - Bitu index = vga.dac.write_index; - if ( (index & vga.dac.pel_mask) == index ) { - for ( Bitu i = index+1;i<256;i++) - if ( (i & vga.dac.pel_mask) == index ) - VGA_DAC_UpdateColor( i ); - } - } - break; - default: - /* Check for attributes and DAC entry link */ - for (Bitu i=0;i<16;i++) { - if (vga.dac.combine[i]==vga.dac.write_index) { - vga.dac.xlat16[i] = ( - (vga.dac.rgb[vga.dac.write_index].blue>>1)&0x1f) | - (((vga.dac.rgb[vga.dac.write_index].green)&0x3f)<<5)| - (((vga.dac.rgb[vga.dac.write_index].red>>1)&0x1f) << 11); - RENDER_SetPal(i, - vga.dac.rgb[vga.dac.write_index].red << 2, - vga.dac.rgb[vga.dac.write_index].green << 2, - vga.dac.rgb[vga.dac.write_index].blue << 2); - } - } - } - vga.dac.write_index++; -// vga.dac.read_index = vga.dac.write_index - 1;//disabled as it breaks Wari - vga.dac.pel_index=0; - break; - default: - LOG(LOG_VGAGFX,LOG_NORMAL)("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day - break; - }; -} - -static Bitu read_p3c9(Bitu port,Bitu iolen) { - Bit8u ret; - switch (vga.dac.pel_index) { - case 0: - ret=vga.dac.rgb[vga.dac.read_index].red; - vga.dac.pel_index=1; - break; - case 1: - ret=vga.dac.rgb[vga.dac.read_index].green; - vga.dac.pel_index=2; - break; - case 2: - ret=vga.dac.rgb[vga.dac.read_index].blue; - vga.dac.read_index++; - vga.dac.pel_index=0; -// vga.dac.write_index=vga.dac.read_index+1;//disabled as it breaks wari - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day - ret=0; - break; - } - return ret; -} - -void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal) { - /* Check if this is a new color */ - vga.dac.combine[attr]=pal; - switch (vga.mode) { - case M_LIN8: - break; - case M_VGA: - // used by copper demo; almost no video card seems to suport it - if(!IS_VGA_ARCH || (svgaCard!=SVGA_None)) break; - - default: - vga.dac.xlat16[attr] = ((vga.dac.rgb[pal].blue>>1)&0x1f) | - (((vga.dac.rgb[pal].green)&0x3f)<<5)| - (((vga.dac.rgb[pal].red>>1)&0x1f) << 11); - RENDER_SetPal(attr, - vga.dac.rgb[pal].red << 2, - vga.dac.rgb[pal].green << 2, - vga.dac.rgb[pal].blue << 2 - ); - } -} - -void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue) { - //Should only be called in machine != vga - vga.dac.rgb[entry].red=red; - vga.dac.rgb[entry].green=green; - vga.dac.rgb[entry].blue=blue; - for (Bitu i=0;i<16;i++) - if (vga.dac.combine[i]==entry) - RENDER_SetPal(i,red << 2,green << 2,blue << 2); -} - -void VGA_SetupDAC(void) { - vga.dac.first_changed=256; - vga.dac.bits=6; - vga.dac.pel_mask=0xff; - vga.dac.pel_index=0; - vga.dac.state=DAC_READ; - vga.dac.read_index=0; - vga.dac.write_index=0; - if (IS_VGA_ARCH) { - /* Setup the DAC IO port Handlers */ - IO_RegisterWriteHandler(0x3c6,write_p3c6,IO_MB); - IO_RegisterReadHandler(0x3c6,read_p3c6,IO_MB); - IO_RegisterWriteHandler(0x3c7,write_p3c7,IO_MB); - IO_RegisterReadHandler(0x3c7,read_p3c7,IO_MB); - IO_RegisterWriteHandler(0x3c8,write_p3c8,IO_MB); - IO_RegisterReadHandler(0x3c8,read_p3c8,IO_MB); - IO_RegisterWriteHandler(0x3c9,write_p3c9,IO_MB); - IO_RegisterReadHandler(0x3c9,read_p3c9,IO_MB); - } else if (machine==MCH_EGA) { - for (Bitu i=0;i<64;i++) { - if ((i&4)>0) vga.dac.rgb[i].red=0x2a; - else vga.dac.rgb[i].red=0; - if ((i&32)>0) vga.dac.rgb[i].red+=0x15; - - if ((i&2)>0) vga.dac.rgb[i].green=0x2a; - else vga.dac.rgb[i].green=0; - if ((i&16)>0) vga.dac.rgb[i].green+=0x15; - - if ((i&1)>0) vga.dac.rgb[i].blue=0x2a; - else vga.dac.rgb[i].blue=0; - if ((i&8)>0) vga.dac.rgb[i].blue+=0x15; - } - } -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "inout.h" +#include "render.h" +#include "vga.h" + +/* +//TODO PEL Mask Maybe +//TODO Find some way to get palette lookups in groups +3C6h (R/W): PEL Mask +bit 0-7 This register is anded with the palette index sent for each dot. + Should be set to FFh. + +3C7h (R): DAC State Register +bit 0-1 0 indicates the DAC is in Write Mode and 3 indicates Read mode. + +3C7h (W): PEL Address Read Mode +bit 0-7 The PEL data register (0..255) to be read from 3C9h. +Note: After reading the 3 bytes at 3C9h this register will increment, + pointing to the next data register. + +3C8h (R/W): PEL Address Write Mode +bit 0-7 The PEL data register (0..255) to be written to 3C9h. +Note: After writing the 3 bytes at 3C9h this register will increment, pointing + to the next data register. + +3C9h (R/W): PEL Data Register +bit 0-5 Color value +Note: Each read or write of this register will cycle through first the + registers for Red, Blue and Green, then increment the appropriate + address register, thus the entire palette can be loaded by writing 0 to + the PEL Address Write Mode register 3C8h and then writing all 768 bytes + of the palette to this register. +*/ + +enum {DAC_READ,DAC_WRITE}; + + +static void write_p3c6(Bit32u port,Bit8u val) { + if (val!=0xff) LOG_ERROR("VGA:Pel Mask not 0xff"); +} + + +static void write_p3c7(Bit32u port,Bit8u val) { + vga.dac.index=val; + vga.dac.pel_index=0; + vga.dac.state=DAC_READ; +} + +static void write_p3c8(Bit32u port,Bit8u val) { + vga.dac.index=val; + vga.dac.pel_index=0; + vga.dac.state=DAC_WRITE; +} + +static void write_p3c9(Bit32u port,Bit8u val) { + switch (vga.dac.pel_index) { + case 0: + vga.dac.rgb[vga.dac.index].red=val; + vga.dac.pel_index=1; + break; + case 1: + vga.dac.rgb[vga.dac.index].green=val; + vga.dac.pel_index=2; + break; + case 2: + vga.dac.rgb[vga.dac.index].blue=val; + switch (vga.mode) { + case GFX_256C: + case GFX_256U: + RENDER_SetPal(vga.dac.index, + vga.dac.rgb[vga.dac.index].red << 2, + vga.dac.rgb[vga.dac.index].green << 2, + vga.dac.rgb[vga.dac.index].blue << 2 + ); + break; + default: + /* Check for attributes and DAC entry link */ + if (vga.dac.rgb[vga.dac.index].attr_entry>15) return; + if (vga.attr.palette[vga.dac.rgb[vga.dac.index].attr_entry]==vga.dac.index) { + RENDER_SetPal(vga.dac.rgb[vga.dac.index].attr_entry, + vga.dac.rgb[vga.dac.index].red << 2, + vga.dac.rgb[vga.dac.index].green << 2, + vga.dac.rgb[vga.dac.index].blue << 2 + ); + } + } + vga.dac.index++; + vga.dac.pel_index=0; + break; + default: + LOG_ERROR("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day + }; +} + +static Bit8u read_p3c9(Bit32u port) { + Bit8u ret; + switch (vga.dac.pel_index) { + case 0: + ret=vga.dac.rgb[vga.dac.index].red; + vga.dac.pel_index=1; + break; + case 1: + ret=vga.dac.rgb[vga.dac.index].green; + vga.dac.pel_index=2; + break; + case 2: + ret=vga.dac.rgb[vga.dac.index].blue; + vga.dac.index++; + vga.dac.pel_index=0; + break; + default: + LOG_ERROR("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day + } + return ret; +} + +void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal) { + /* Check if this is a new color */ + vga.dac.rgb[pal].attr_entry=attr; + RENDER_SetPal(attr, + vga.dac.rgb[pal].red << 2, + vga.dac.rgb[pal].green << 2, + vga.dac.rgb[pal].blue << 2 + ); +} + +void VGA_SetupDAC(void) { + vga.dac.first_changed=256; + vga.dac.bits=6; + vga.dac.pel_mask=0xff; + vga.dac.pel_index=0; + vga.dac.state=DAC_READ; + + /* Setup the DAC IO port Handlers */ + IO_RegisterWriteHandler(0x3c6,write_p3c6,"PEL Mask"); + IO_RegisterWriteHandler(0x3c7,write_p3c7,"PEL Read Mode"); + IO_RegisterWriteHandler(0x3c8,write_p3c8,"PEL Write Mode"); + IO_RegisterWriteHandler(0x3c9,write_p3c9,"PEL Data"); + IO_RegisterReadHandler(0x3c9,read_p3c9,"PEL Data"); +}; + + diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 08bf834..c8f859f 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -1,1376 +1,165 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_draw.cpp,v 1.107 2009/04/11 08:02:23 qbix79 Exp $ */ - -#include -#include -#include "dosbox.h" -#include "video.h" -#include "render.h" -#include "../gui/render_scalers.h" -#include "vga.h" -#include "pic.h" - -#define VGA_PARTS 4 - -typedef Bit8u * (* VGA_Line_Handler)(Bitu vidstart, Bitu line); - -static VGA_Line_Handler VGA_DrawLine; -static Bit8u TempLine[SCALER_MAXWIDTH * 4]; - -static Bit8u * VGA_Draw_1BPP_Line(Bitu vidstart, Bitu line) { - const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); - Bit32u *draw = (Bit32u *)TempLine; - for (Bitu x=vga.draw.blocks;x>0;x--, vidstart++) { - Bitu val = base[(vidstart & (8 * 1024 -1))]; - *draw++=CGA_2_Table[val >> 4]; - *draw++=CGA_2_Table[val & 0xf]; - } - return TempLine; -} - -static Bit8u * VGA_Draw_2BPP_Line(Bitu vidstart, Bitu line) { - const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); - Bit32u * draw=(Bit32u *)TempLine; - for (Bitu x=0;x>4)|(val2&0xf0)]; - *draw++=CGA_4_HiRes_Table[(val1&0x0f)|((val2&0x0f)<<4)]; - } - return TempLine; -} - -static Bitu temp[643]={0}; - -static Bit8u * VGA_Draw_CGA16_Line(Bitu vidstart, Bitu line) { - const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); - const Bit8u *reader = base + vidstart; - Bit32u * draw=(Bit32u *)TempLine; - //Generate a temporary bitline to calculate the avarage - //over bit-2 bit-1 bit bit+1. - //Combine this number with the current colour to get - //an unigue index in the pallete. Or it with bit 7 as they are stored - //in the upperpart to keep them from interfering the regular cga stuff - - for(Bitu x = 0; x < 640; x++) - temp[x+2] = (( reader[(x>>3)] >> (7-(x&7)) )&1) << 4; - //shift 4 as that is for the index. - Bitu i = 0,temp1,temp2,temp3,temp4; - for (Bitu x=0;x>= 4; - - temp1 = temp[i] + temp[i+1] + temp[i+2] + temp[i+3]; i++; - temp2 = temp[i] + temp[i+1] + temp[i+2] + temp[i+3]; i++; - temp3 = temp[i] + temp[i+1] + temp[i+2] + temp[i+3]; i++; - temp4 = temp[i] + temp[i+1] + temp[i+2] + temp[i+3]; i++; - - *draw++ = 0x80808080|(temp1|val1) | - ((temp2|val1) << 8) | - ((temp3|val1) <<16) | - ((temp4|val1) <<24); - temp1 = temp[i] + temp[i+1] + temp[i+2] + temp[i+3]; i++; - temp2 = temp[i] + temp[i+1] + temp[i+2] + temp[i+3]; i++; - temp3 = temp[i] + temp[i+1] + temp[i+2] + temp[i+3]; i++; - temp4 = temp[i] + temp[i+1] + temp[i+2] + temp[i+3]; i++; - *draw++ = 0x80808080|(temp1|val2) | - ((temp2|val2) << 8) | - ((temp3|val2) <<16) | - ((temp4|val2) <<24); - } - return TempLine; -} - -static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart, Bitu line) { - const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); - Bit32u * draw=(Bit32u *)TempLine; - for (Bitu x=0;x> 4 | - (val2 & 0x0f) << 24 | - (val2 & 0xf0) << 12; - } - return TempLine; -} - -static Bit8u * VGA_Draw_4BPP_Line_Double(Bitu vidstart, Bitu line) { - const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); - Bit32u * draw=(Bit32u *)TempLine; - for (Bitu x=0;x> 4 | - (val & 0xf0) << 4 | - (val & 0x0f) << 16 | - (val & 0x0f) << 24; - } - return TempLine; -} - -#ifdef VGA_KEEP_CHANGES -static Bit8u * VGA_Draw_Changes_Line(Bitu vidstart, Bitu line) { - Bitu checkMask = vga.changes.checkMask; - Bit8u *map = vga.changes.map; - Bitu start = (vidstart >> VGA_CHANGE_SHIFT); - Bitu end = ((vidstart + vga.draw.line_length ) >> VGA_CHANGE_SHIFT); - for (; start <= end;start++) { - if ( map[start] & checkMask ) { - Bitu offset = vidstart & vga.draw.linear_mask; - if(vga.draw.linear_mask-offset < vga.draw.line_length) - memcpy(vga.draw.linear_base+vga.draw.linear_mask+1, vga.draw.linear_base, vga.draw.line_length); - Bit8u *ret = &vga.draw.linear_base[ offset ]; -#if !defined(C_UNALIGNED_MEMORY) - if (GCC_UNLIKELY( ((Bitu)ret) & (sizeof(Bitu)-1)) ) { - memcpy( TempLine, ret, vga.draw.line_length ); - return TempLine; - } -#endif - return ret; - } - } -// memset( TempLine, 0x30, vga.changes.lineWidth ); -// return TempLine; - return 0; -} - -#endif - -static Bit8u * VGA_Draw_Linear_Line(Bitu vidstart, Bitu /*line*/) { -// There is guaranteed extra memory past the wrap boundary. So, instead of using temporary -// storage just copy appropriate chunk from the beginning to the wrap boundary when needed. - Bitu offset = vidstart & vga.draw.linear_mask; - if (vga.draw.linear_mask-offset < vga.draw.line_length) - memcpy(vga.draw.linear_base+vga.draw.linear_mask+1, vga.draw.linear_base, vga.draw.line_length); - Bit8u *ret = &vga.draw.linear_base[ offset ]; -#if !defined(C_UNALIGNED_MEMORY) - if (GCC_UNLIKELY( ((Bitu)ret) & (sizeof(Bitu)-1)) ) { - memcpy( TempLine, ret, vga.draw.line_length ); - return TempLine; - } -#endif - return ret; -} - -static Bit8u * VGA_Draw_Xlat16_Linear_Line(Bitu vidstart, Bitu /*line*/) { - Bit8u *ret = &vga.draw.linear_base[ vidstart & vga.draw.linear_mask ]; - Bit16u* temps = (Bit16u*) TempLine; - for(Bitu i = 0; i < vga.draw.line_length; i++) { - temps[i]=vga.dac.xlat16[ret[i]]; - } - return TempLine; - /* -#if !defined(C_UNALIGNED_MEMORY) - if (GCC_UNLIKELY( ((Bitu)ret) & (sizeof(Bitu)-1)) ) { - memcpy( TempLine, ret, vga.draw.line_length ); - return TempLine; - } -#endif - return ret;*/ -} - -//Test version, might as well keep it -/* static Bit8u * VGA_Draw_Chain_Line(Bitu vidstart, Bitu line) { - Bitu i = 0; - for ( i = 0; i < vga.draw.width;i++ ) { - Bitu addr = vidstart + i; - TempLine[i] = vga.mem.linear[((addr&~3)<<2)+(addr&3)]; - } - return TempLine; -} */ - -static Bit8u * VGA_Draw_VGA_Line_HWMouse( Bitu vidstart, Bitu /*line*/) { - if (!svga.hardware_cursor_active || !svga.hardware_cursor_active()) - // HW Mouse not enabled, use the tried and true call - return &vga.mem.linear[vidstart]; - - Bitu lineat = (vidstart-(vga.config.real_start<<2)) / vga.draw.width; - if ((vga.s3.hgc.posx >= vga.draw.width) || - (lineat < vga.s3.hgc.originy) || - (lineat > (vga.s3.hgc.originy + (63U-vga.s3.hgc.posy))) ) { - // the mouse cursor *pattern* is not on this line - return &vga.mem.linear[ vidstart ]; - } else { - // Draw mouse cursor: cursor is a 64x64 pattern which is shifted (inside the - // 64x64 mouse cursor space) to the right by posx pixels and up by posy pixels. - // This is used when the mouse cursor partially leaves the screen. - // It is arranged as bitmap of 16bits of bitA followed by 16bits of bitB, each - // AB bits corresponding to a cursor pixel. The whole map is 8kB in size. - memcpy(TempLine, &vga.mem.linear[ vidstart ], vga.draw.width); - // the index of the bit inside the cursor bitmap we start at: - Bitu sourceStartBit = ((lineat - vga.s3.hgc.originy) + vga.s3.hgc.posy)*64 + vga.s3.hgc.posx; - // convert to video memory addr and bit index - // start adjusted to the pattern structure (thus shift address by 2 instead of 3) - // Need to get rid of the third bit, so "/8 *2" becomes ">> 2 & ~1" - Bitu cursorMemStart = ((sourceStartBit >> 2)& ~1) + (((Bit32u)vga.s3.hgc.startaddr) << 10); - Bitu cursorStartBit = sourceStartBit & 0x7; - // stay at the right position in the pattern - if (cursorMemStart & 0x2) cursorMemStart--; - Bitu cursorMemEnd = cursorMemStart + ((64-vga.s3.hgc.posx) >> 2); - Bit8u* xat = &TempLine[vga.s3.hgc.originx]; // mouse data start pos. in scanline - for (Bitu m = cursorMemStart; m < cursorMemEnd; (m&1)?(m+=3):m++) { - // for each byte of cursor data - Bit8u bitsA = vga.mem.linear[m]; - Bit8u bitsB = vga.mem.linear[m+2]; - for (Bit8u bit=(0x80 >> cursorStartBit); bit != 0; bit >>= 1) { - // for each bit - cursorStartBit=0; // only the first byte has some bits cut off - if (bitsA&bit) { - if (bitsB&bit) *xat ^= 0xFF; // Invert screen data - //else Transparent - } else if (bitsB&bit) { - *xat = vga.s3.hgc.forestack[0]; // foreground color - } else { - *xat = vga.s3.hgc.backstack[0]; - } - xat++; - } - } - return TempLine; - } -} - -static Bit8u * VGA_Draw_LIN16_Line_HWMouse(Bitu vidstart, Bitu /*line*/) { - if (!svga.hardware_cursor_active || !svga.hardware_cursor_active()) - return &vga.mem.linear[vidstart]; - - Bitu lineat = ((vidstart-(vga.config.real_start<<2)) >> 1) / vga.draw.width; - if ((vga.s3.hgc.posx >= vga.draw.width) || - (lineat < vga.s3.hgc.originy) || - (lineat > (vga.s3.hgc.originy + (63U-vga.s3.hgc.posy))) ) { - return &vga.mem.linear[vidstart]; - } else { - memcpy(TempLine, &vga.mem.linear[ vidstart ], vga.draw.width*2); - Bitu sourceStartBit = ((lineat - vga.s3.hgc.originy) + vga.s3.hgc.posy)*64 + vga.s3.hgc.posx; - Bitu cursorMemStart = ((sourceStartBit >> 2)& ~1) + (((Bit32u)vga.s3.hgc.startaddr) << 10); - Bitu cursorStartBit = sourceStartBit & 0x7; - if (cursorMemStart & 0x2) cursorMemStart--; - Bitu cursorMemEnd = cursorMemStart + ((64-vga.s3.hgc.posx) >> 2); - Bit16u* xat = &((Bit16u*)TempLine)[vga.s3.hgc.originx]; - for (Bitu m = cursorMemStart; m < cursorMemEnd; (m&1)?(m+=3):m++) { - // for each byte of cursor data - Bit8u bitsA = vga.mem.linear[m]; - Bit8u bitsB = vga.mem.linear[m+2]; - for (Bit8u bit=(0x80 >> cursorStartBit); bit != 0; bit >>= 1) { - // for each bit - cursorStartBit=0; - if (bitsA&bit) { - // byte order doesn't matter here as all bits get flipped - if (bitsB&bit) *xat ^= ~0U; - //else Transparent - } else if (bitsB&bit) { - // Source as well as destination are Bit8u arrays, - // so this should work out endian-wise? - *xat = *(Bit16u*)vga.s3.hgc.forestack; - } else { - *xat = *(Bit16u*)vga.s3.hgc.backstack; - } - xat++; - } - } - return TempLine; - } -} - -static Bit8u * VGA_Draw_LIN32_Line_HWMouse(Bitu vidstart, Bitu /*line*/) { - if (!svga.hardware_cursor_active || !svga.hardware_cursor_active()) - return &vga.mem.linear[vidstart]; - - Bitu lineat = ((vidstart-(vga.config.real_start<<2)) >> 2) / vga.draw.width; - if ((vga.s3.hgc.posx >= vga.draw.width) || - (lineat < vga.s3.hgc.originy) || - (lineat > (vga.s3.hgc.originy + (63U-vga.s3.hgc.posy))) ) { - return &vga.mem.linear[ vidstart ]; - } else { - memcpy(TempLine, &vga.mem.linear[ vidstart ], vga.draw.width*4); - Bitu sourceStartBit = ((lineat - vga.s3.hgc.originy) + vga.s3.hgc.posy)*64 + vga.s3.hgc.posx; - Bitu cursorMemStart = ((sourceStartBit >> 2)& ~1) + (((Bit32u)vga.s3.hgc.startaddr) << 10); - Bitu cursorStartBit = sourceStartBit & 0x7; - if (cursorMemStart & 0x2) cursorMemStart--; - Bitu cursorMemEnd = cursorMemStart + ((64-vga.s3.hgc.posx) >> 2); - Bit32u* xat = &((Bit32u*)TempLine)[vga.s3.hgc.originx]; - for (Bitu m = cursorMemStart; m < cursorMemEnd; (m&1)?(m+=3):m++) { - // for each byte of cursor data - Bit8u bitsA = vga.mem.linear[m]; - Bit8u bitsB = vga.mem.linear[m+2]; - for (Bit8u bit=(0x80 >> cursorStartBit); bit != 0; bit >>= 1) { // for each bit - cursorStartBit=0; - if (bitsA&bit) { - if (bitsB&bit) *xat ^= ~0U; - //else Transparent - } else if (bitsB&bit) { - *xat = *(Bit32u*)vga.s3.hgc.forestack; - } else { - *xat = *(Bit32u*)vga.s3.hgc.backstack; - } - xat++; - } - } - return TempLine; - } -} - -static Bit32u FontMask[2]={0xffffffff,0x0}; -static Bit8u * VGA_TEXT_Draw_Line(Bitu vidstart, Bitu line) { - Bits font_addr; - Bit32u * draw=(Bit32u *)TempLine; - const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; - for (Bitu cx=0;cx> 3)&1][chr*32+line]; - Bit32u mask1=TXT_Font_Table[font>>4] & FontMask[col >> 7]; - Bit32u mask2=TXT_Font_Table[font&0xf] & FontMask[col >> 7]; - Bit32u fg=TXT_FG_Table[col&0xf]; - Bit32u bg=TXT_BG_Table[col>>4]; - *draw++=(fg&mask1) | (bg&~mask1); - *draw++=(fg&mask2) | (bg&~mask2); - } - if (!vga.draw.cursor.enabled || !(vga.draw.cursor.count&0x8)) goto skip_cursor; - font_addr = (vga.draw.cursor.address-vidstart) >> 1; - if (font_addr>=0 && font_addr<(Bits)vga.draw.blocks) { - if (linevga.draw.cursor.eline) goto skip_cursor; - draw=(Bit32u *)&TempLine[font_addr*8]; - Bit32u att=TXT_FG_Table[vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf]; - *draw++=att;*draw++=att; - } -skip_cursor: - return TempLine; -} - -static Bit8u * VGA_TEXT_Herc_Draw_Line(Bitu vidstart, Bitu line) { - Bits font_addr; - Bit32u * draw=(Bit32u *)TempLine; - const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; - - for (Bitu cx=0;cx> 7]; - else { - Bitu font=vga.draw.font_tables[0][chr*32+line]; - mask1=TXT_Font_Table[font>>4] & FontMask[attrib >> 7]; // blinking - mask2=TXT_Font_Table[font&0xf] & FontMask[attrib >> 7]; - } - *draw++=(fg&mask1) | (bg&~mask1); - *draw++=(fg&mask2) | (bg&~mask2); - } - } - if (!vga.draw.cursor.enabled || !(vga.draw.cursor.count&0x8)) goto skip_cursor; - font_addr = (vga.draw.cursor.address-vidstart) >> 1; - if (font_addr>=0 && font_addr<(Bits)vga.draw.blocks) { - if (linevga.draw.cursor.eline) goto skip_cursor; - draw=(Bit32u *)&TempLine[font_addr*8]; - Bit32u att=TXT_FG_Table[vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf]; - *draw++=att;*draw++=att; - } -skip_cursor: - return TempLine; -} - -static Bit8u * VGA_TEXT_Xlat16_Draw_Line(Bitu vidstart, Bitu line) { - Bits font_addr; - Bit16u * draw=(Bit16u *)TempLine; - const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; - for (Bitu cx=0;cx> 3)&1][chr*32+line]; - Bit32u mask1=TXT_Font_Table[font>>4] & FontMask[col >> 7]; - Bit32u mask2=TXT_Font_Table[font&0xf] & FontMask[col >> 7]; - Bit32u fg=TXT_FG_Table[col&0xf]; - Bit32u bg=TXT_BG_Table[col>>4]; - - mask1=(fg&mask1) | (bg&~mask1); - mask2=(fg&mask2) | (bg&~mask2); - - for(int i = 0; i < 4; i++) { - *draw++ = vga.dac.xlat16[(mask1>>8*i)&0xff]; - } - for(int i = 0; i < 4; i++) { - *draw++ = vga.dac.xlat16[(mask2>>8*i)&0xff]; - } - } - if (!vga.draw.cursor.enabled || !(vga.draw.cursor.count&0x8)) goto skip_cursor; - font_addr = (vga.draw.cursor.address-vidstart) >> 1; - if (font_addr>=0 && font_addr<(Bits)vga.draw.blocks) { - if (linevga.draw.cursor.eline) goto skip_cursor; - draw=(Bit16u *)&TempLine[font_addr*16]; - Bit8u att=(Bit8u)(TXT_FG_Table[vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf]&0xff); - for(int i = 0; i < 8; i++) { - *draw++ = vga.dac.xlat16[att]; - } - } -skip_cursor: - return TempLine; -} - -/* -static Bit8u * VGA_TEXT_Draw_Line_9(Bitu vidstart, Bitu line) { - Bits font_addr; - Bit8u * draw=(Bit8u *)TempLine; - bool underline=(Bitu)(vga.crtc.underline_location&0x1f)==line; - Bit8u pel_pan=(Bit8u)vga.draw.panning; - if ((vga.attr.mode_control&0x20) && (vga.draw.lines_done>=vga.draw.split_line)) pel_pan=0; - const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; - Bit8u chr=vidmem[0]; - Bit8u col=vidmem[1]; - Bit8u font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<>4]&0xff); - Bitu draw_blocks=vga.draw.blocks; - draw_blocks++; - for (Bitu cx=1;cx>(8-pel_pan); - else font|=vga.draw.font_tables[(col >> 3)&1][chr*32+line]>>(8-pel_pan); - fg=col&0xf; - bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff); - } else { - chr=vidmem[(cx-1)*2]; - col=vidmem[(cx-1)*2+1]; - if (underline && ((col&0x07) == 0x01)) font=0xff; - else font=vga.draw.font_tables[(col >> 3)&1][chr*32+line]; - fg=col&0xf; - bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff); - } - if (FontMask[col>>7]==0) font=0; - *draw++=(font&0x80)?fg:bg; *draw++=(font&0x40)?fg:bg; - *draw++=(font&0x20)?fg:bg; *draw++=(font&0x10)?fg:bg; - *draw++=(font&0x08)?fg:bg; *draw++=(font&0x04)?fg:bg; - *draw++=(font&0x02)?fg:bg; - Bit8u last=(font&0x01)?fg:bg; - *draw++=last; - *draw++=((vga.attr.mode_control&0x04) && ((chr<0xc0) || (chr>0xdf))) ? bg : last; - if (pel_pan) { - if (underline && ((col&0x07) == 0x01)) font=0xff; - else font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<> 1; - if (font_addr>=0 && font_addr<(Bits)vga.draw.blocks) { - if (linevga.draw.cursor.eline) goto skip_cursor; - draw=&TempLine[font_addr*9]; - Bit8u fg=vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf; - *draw++=fg; *draw++=fg; *draw++=fg; *draw++=fg; - *draw++=fg; *draw++=fg; *draw++=fg; *draw++=fg; - } -skip_cursor: - return TempLine; -} -*/ - -static Bit8u * VGA_TEXT_Xlat16_Draw_Line_9(Bitu vidstart, Bitu line) { - Bits font_addr; - Bit16u * draw=(Bit16u *)TempLine; - bool underline=(Bitu)(vga.crtc.underline_location&0x1f)==line; - Bit8u pel_pan=(Bit8u)vga.draw.panning; - if ((vga.attr.mode_control&0x20) && (vga.draw.lines_done>=vga.draw.split_line)) pel_pan=0; - const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; - Bit8u chr=vidmem[0]; - Bit8u col=vidmem[1]; - Bit8u font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<>4]&0xff); - Bitu draw_blocks=vga.draw.blocks; - draw_blocks++; - for (Bitu cx=1;cx>(8-pel_pan); - else font|=vga.draw.font_tables[(col >> 3)&1][chr*32+line]>>(8-pel_pan); - fg=col&0xf; - bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff); - } else { - chr=vidmem[(cx-1)*2]; - col=vidmem[(cx-1)*2+1]; - if (underline && ((col&0x07) == 0x01)) font=0xff; - else font=vga.draw.font_tables[(col >> 3)&1][chr*32+line]; - fg=col&0xf; - bg=(Bit8u)(TXT_BG_Table[col>>4]&0xff); - } - if (FontMask[col>>7]==0) font=0; - Bit8u mask=0x80; - for (int i = 0; i < 7; i++) { - *draw++=vga.dac.xlat16[font&mask?fg:bg]; - mask>>=1; - } - Bit16u lastval=vga.dac.xlat16[font&mask?fg:bg]; - *draw++=lastval; - *draw++=(((vga.attr.mode_control&0x04) && ((chr<0xc0) || (chr>0xdf))) && - !(underline && ((col&0x07) == 0x01))) ? - (vga.dac.xlat16[bg]) : lastval; - if (pel_pan) { - if (underline && ((col&0x07) == 0x01)) font=0xff; - else font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<> 1; - if (font_addr>=0 && font_addr<(Bits)vga.draw.blocks) { - if (linevga.draw.cursor.eline) goto skip_cursor; - draw=(Bit16u*)&TempLine[font_addr*18]; - Bit8u fg=vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf; - for(int i = 0; i < 8; i++) { - *draw++ = vga.dac.xlat16[fg]; - } - //if(underline && ((col&0x07) == 0x01)) - // *draw = vga.dac.xlat16[fg]; - } -skip_cursor: - return TempLine; -} - -#ifdef VGA_KEEP_CHANGES -static INLINE void VGA_ChangesEnd(void ) { - if ( vga.changes.active ) { -// vga.changes.active = false; - Bitu end = vga.draw.address >> VGA_CHANGE_SHIFT; - Bitu total = 4 + end - vga.changes.start; - Bit32u clearMask = vga.changes.clearMask; - total >>= 2; - Bit32u *clear = (Bit32u *)&vga.changes.map[ vga.changes.start & ~3 ]; - while ( total-- ) { - clear[0] &= clearMask; - clear++; - } - } -} -#endif - - -static void VGA_ProcessSplit() { - // On the EGA the address is always reset to 0. - if ((vga.attr.mode_control&0x20) || (machine==MCH_EGA)) { - vga.draw.address=0; - } else { - // In text mode only the characters are shifted by panning, not the address; - // this is done in the text line draw function. - vga.draw.address = vga.draw.byte_panning_shift*vga.draw.bytes_skip; - if (!(vga.mode==M_TEXT)) vga.draw.address += vga.draw.panning; - } - vga.draw.address_line=0; -} - -static void VGA_DrawSingleLine(Bitu /*blah*/) { - if(vga.attr.enabled || (!(vga.mode==M_VGA || vga.mode==M_EGA))) { - Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line ); - RENDER_DrawLine(data); - } else { - // else draw overscan color line - // TODO: black line should be good enough for now - // (DoWhackaDo) - memset(TempLine, 0, sizeof(TempLine)); - RENDER_DrawLine(TempLine); - } - - vga.draw.address_line++; - if (vga.draw.address_line>=vga.draw.address_line_total) { - vga.draw.address_line=0; - vga.draw.address+=vga.draw.address_add; - } - vga.draw.lines_done++; - if (vga.draw.split_line==vga.draw.lines_done) VGA_ProcessSplit(); - if (vga.draw.lines_done < vga.draw.lines_total) { - PIC_AddEvent(VGA_DrawSingleLine,(float)vga.draw.delay.htotal); - } else RENDER_EndUpdate(); -} - -static void VGA_DrawPart(Bitu lines) { - while (lines--) { - Bit8u * data=VGA_DrawLine( vga.draw.address, vga.draw.address_line ); - RENDER_DrawLine(data); - vga.draw.address_line++; - if (vga.draw.address_line>=vga.draw.address_line_total) { - vga.draw.address_line=0; - vga.draw.address+=vga.draw.address_add; - } - vga.draw.lines_done++; - if (vga.draw.split_line==vga.draw.lines_done) { -#ifdef VGA_KEEP_CHANGES - VGA_ChangesEnd( ); -#endif - VGA_ProcessSplit(); -#ifdef VGA_KEEP_CHANGES - vga.changes.start = vga.draw.address >> VGA_CHANGE_SHIFT; -#endif - } - } - if (--vga.draw.parts_left) { - PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts, - (vga.draw.parts_left!=1) ? vga.draw.parts_lines : (vga.draw.lines_total - vga.draw.lines_done)); - } else { -#ifdef VGA_KEEP_CHANGES - VGA_ChangesEnd(); -#endif - RENDER_EndUpdate(); - } -} - -void VGA_SetBlinking(Bitu enabled) { - Bitu b; - LOG(LOG_VGA,LOG_NORMAL)("Blinking %d",enabled); - if (enabled) { - b=0;vga.draw.blinking=1; //used to -1 but blinking is unsigned - vga.attr.mode_control|=0x08; - vga.tandy.mode_control|=0x20; - } else { - b=8;vga.draw.blinking=0; - vga.attr.mode_control&=~0x08; - vga.tandy.mode_control&=~0x20; - } - for (Bitu i=0;i<8;i++) TXT_BG_Table[i+8]=(b+i) | ((b+i) << 8)| ((b+i) <<16) | ((b+i) << 24); -} - -#ifdef VGA_KEEP_CHANGES -static void INLINE VGA_ChangesStart( void ) { - vga.changes.start = vga.draw.address >> VGA_CHANGE_SHIFT; - vga.changes.last = vga.changes.start; - if ( vga.changes.lastAddress != vga.draw.address ) { -// LOG_MSG("Address"); - VGA_DrawLine = VGA_Draw_Linear_Line; - vga.changes.lastAddress = vga.draw.address; - } else if ( render.fullFrame ) { -// LOG_MSG("Full Frame"); - VGA_DrawLine = VGA_Draw_Linear_Line; - } else { -// LOG_MSG("Changes"); - VGA_DrawLine = VGA_Draw_Changes_Line; - } - vga.changes.active = true; - vga.changes.checkMask = vga.changes.writeMask; - vga.changes.clearMask = ~( 0x01010101 << (vga.changes.frame & 7)); - vga.changes.frame++; - vga.changes.writeMask = 1 << (vga.changes.frame & 7); -} -#endif - -static void VGA_VertInterrupt(Bitu /*val*/) { - if ((!vga.draw.vret_triggered) && ((vga.crtc.vertical_retrace_end&0x30)==0x10)) { - vga.draw.vret_triggered=true; - if (GCC_UNLIKELY(machine==MCH_EGA)) PIC_ActivateIRQ(9); - } -} - -static void VGA_DisplayStartLatch(Bitu /*val*/) { - vga.config.real_start=vga.config.display_start & (vga.vmemwrap-1); - vga.draw.bytes_skip = vga.config.bytes_skip; -} - -static void VGA_PanningLatch(Bitu /*val*/) { - vga.draw.panning = vga.config.pel_panning; -} - -static void VGA_VerticalTimer(Bitu /*val*/) { - double error = vga.draw.delay.framestart; - vga.draw.delay.framestart = PIC_FullIndex(); - error = vga.draw.delay.framestart - error - vga.draw.delay.vtotal; - PIC_AddEvent( VGA_VerticalTimer, (float)vga.draw.delay.vtotal ); - //PIC_AddEvent( VGA_VerticalDisplayEnd, (float)vga.draw.delay.vrstart ); - double flip_offset = vga.screenflip/1000.0 + vga.draw.delay.vrstart; - if(flip_offset > vga.draw.delay.vtotal) { - VGA_DisplayStartLatch(0); - } else PIC_AddEvent( VGA_DisplayStartLatch,(float)flip_offset); - PIC_AddEvent(VGA_PanningLatch,(float)vga.draw.delay.vrend); - - // EGA: 82c435 datasheet: interrupt happens at display end - // VGA: checked with scope - // add a little amount of time to make sure the last drawpart has already fired - if (IS_EGAVGA_ARCH) PIC_AddEvent(VGA_VertInterrupt,(float)(vga.draw.delay.vdend + 0.005)); - - if ( GCC_UNLIKELY( vga.draw.parts_left)) { - if (!IS_VGA_ARCH || (svgaCard!=SVGA_None)) { - LOG(LOG_VGAMISC,LOG_NORMAL)( "Parts left: %d", vga.draw.parts_left ); - PIC_RemoveEvents( &VGA_DrawPart ); - RENDER_EndUpdate(); - vga.draw.parts_left = 0; - } - } - //Check if we can actually render, else skip the rest - if (!RENDER_StartUpdate()) - return; - if ( GCC_UNLIKELY( vga.draw.lines_done < vga.draw.lines_total)) { - if (IS_VGA_ARCH && (svgaCard==SVGA_None)) { - while(vga.draw.lines_done < vga.draw.lines_total) - VGA_DrawSingleLine(0); - PIC_RemoveEvents(VGA_DrawSingleLine); - } - } - //TODO Maybe check for an active frame on parts_left and clear that first? - vga.draw.parts_left = vga.draw.parts_total; - vga.draw.lines_done = 0; - vga.draw.address_line = vga.config.hlines_skip; - if (IS_EGAVGA_ARCH) { - vga.draw.split_line = (Bitu)((vga.config.line_compare+1)/vga.draw.lines_scaled); - if ((svgaCard==SVGA_S3Trio) && (vga.config.line_compare==0)) vga.draw.split_line=0; - } else { - vga.draw.split_line = 0x10000; // don't care - } - vga.draw.address = vga.config.real_start; - vga.draw.byte_panning_shift = 0; - // go figure... - if (machine==MCH_EGA) vga.draw.split_line*=2; -// if (machine==MCH_EGA) vga.draw.split_line = ((((vga.config.line_compare&0x5ff)+1)*2-1)/vga.draw.lines_scaled); -#ifdef VGA_KEEP_CHANGES - bool startaddr_changed=false; -#endif - switch (vga.mode) { - case M_EGA: - case M_LIN4: - vga.draw.byte_panning_shift = 8; - vga.draw.address += vga.draw.bytes_skip; - vga.draw.address *= vga.draw.byte_panning_shift; - vga.draw.address += vga.draw.panning; -#ifdef VGA_KEEP_CHANGES - startaddr_changed=true; -#endif - break; - case M_VGA: - if(vga.config.compatible_chain4 && (vga.crtc.underline_location & 0x40)) { - vga.draw.linear_base = vga.fastmem; - vga.draw.linear_mask = 0xffff; - } else { - vga.draw.linear_base = vga.mem.linear; - vga.draw.linear_mask = vga.vmemwrap - 1; - } - case M_LIN8: - case M_LIN15: - case M_LIN16: - case M_LIN32: - vga.draw.byte_panning_shift = 4; - vga.draw.address += vga.draw.bytes_skip; - vga.draw.address *= vga.draw.byte_panning_shift; - vga.draw.address += vga.draw.panning; -#ifdef VGA_KEEP_CHANGES - startaddr_changed=true; -#endif - break; - case M_TEXT: - if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) vga.draw.byte_panning_shift = 2; - else vga.draw.byte_panning_shift = 0; - if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) vga.draw.address = vga.config.real_start * 2; - else vga.draw.address = vga.config.display_start * 2; - vga.draw.address += vga.draw.bytes_skip*vga.draw.byte_panning_shift; - case M_TANDY_TEXT: - case M_HERC_TEXT: - vga.draw.cursor.address=vga.config.cursor_start*2; - vga.draw.cursor.count++; - /* check for blinking and blinking change delay */ - FontMask[1]=(vga.draw.blinking & (vga.draw.cursor.count >> 4)) ? - 0 : 0xffffffff; - break; - case M_HERC_GFX: - break; - case M_CGA4:case M_CGA2: - vga.draw.address=(vga.draw.address*2)&0x1fff; - break; - case M_CGA16: - case M_TANDY2:case M_TANDY4:case M_TANDY16: - vga.draw.address *= 2; - break; - default: - break; - } - if (GCC_UNLIKELY(vga.draw.split_line==0)) VGA_ProcessSplit(); -#ifdef VGA_KEEP_CHANGES - if (startaddr_changed) VGA_ChangesStart(); -#endif - - if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) PIC_AddEvent(VGA_DrawSingleLine,(float)(vga.draw.delay.htotal/4.0)); - else PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts,vga.draw.parts_lines); - //VGA_DrawPart( vga.draw.parts_lines ); - //PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts,vga.draw.parts_lines); - //PIC_AddEvent(VGA_DrawPart,(float)(vga.draw.delay.parts/2),vga.draw.parts_lines); //Else tearline in Tyrian and second reality -} - -void VGA_CheckScanLength(void) { - switch (vga.mode) { - case M_EGA: - case M_LIN4: - vga.draw.address_add=vga.config.scan_len*16; - break; - case M_VGA: - case M_LIN8: - case M_LIN15: - case M_LIN16: - case M_LIN32: - vga.draw.address_add=vga.config.scan_len*8; - break; - case M_TEXT: - vga.draw.address_add=vga.config.scan_len*4; - break; - case M_CGA2: - case M_CGA4: - case M_CGA16: - vga.draw.address_add=80; - return; - case M_TANDY2: - vga.draw.address_add=vga.draw.blocks/4; - break; - case M_TANDY4: - vga.draw.address_add=vga.draw.blocks; - break; - case M_TANDY16: - vga.draw.address_add=vga.draw.blocks; - break; - case M_TANDY_TEXT: - vga.draw.address_add=vga.draw.blocks*2; - break; - case M_HERC_TEXT: - vga.draw.address_add=vga.draw.blocks*2; - break; - case M_HERC_GFX: - vga.draw.address_add=vga.draw.blocks; - break; - default: - vga.draw.address_add=vga.draw.blocks*8; - break; - } -} - -void VGA_ActivateHardwareCursor(void) { - bool hwcursor_active=false; - if (svga.hardware_cursor_active) { - if (svga.hardware_cursor_active()) hwcursor_active=true; - } - if (hwcursor_active) { - switch(vga.mode) { - case M_LIN32: - VGA_DrawLine=VGA_Draw_LIN32_Line_HWMouse; - break; - case M_LIN15: - case M_LIN16: - VGA_DrawLine=VGA_Draw_LIN16_Line_HWMouse; - break; - default: - VGA_DrawLine=VGA_Draw_VGA_Line_HWMouse; - } - } else { - VGA_DrawLine=VGA_Draw_Linear_Line; - } -} - -void VGA_SetupDrawing(Bitu /*val*/) { - if (vga.mode==M_ERROR) { - PIC_RemoveEvents(VGA_VerticalTimer); - PIC_RemoveEvents(VGA_PanningLatch); - PIC_RemoveEvents(VGA_DisplayStartLatch); - return; - } - /* Calculate the FPS for this screen */ - float fps; Bitu clock; - Bitu htotal, hdend, hbstart, hbend, hrstart, hrend; - Bitu vtotal, vdend, vbstart, vbend, vrstart, vrend; - if (IS_EGAVGA_ARCH) { - htotal = vga.crtc.horizontal_total; - hdend = vga.crtc.horizontal_display_end; - hbend = vga.crtc.end_horizontal_blanking&0x1F; - hbstart = vga.crtc.start_horizontal_blanking; - hrstart = vga.crtc.start_horizontal_retrace; - - vtotal= vga.crtc.vertical_total | ((vga.crtc.overflow & 1) << 8); - vdend = vga.crtc.vertical_display_end | ((vga.crtc.overflow & 2)<<7); - vbstart = vga.crtc.start_vertical_blanking | ((vga.crtc.overflow & 0x08) << 5); - vrstart = vga.crtc.vertical_retrace_start + ((vga.crtc.overflow & 0x04) << 6); - - if (IS_VGA_ARCH) { - // additional bits only present on vga cards - htotal |= (vga.s3.ex_hor_overflow & 0x1) << 8; - htotal += 3; - hdend |= (vga.s3.ex_hor_overflow & 0x2) << 7; - hbend |= (vga.crtc.end_horizontal_retrace&0x80) >> 2; - hbstart |= (vga.s3.ex_hor_overflow & 0x4) << 6; - hrstart |= (vga.s3.ex_hor_overflow & 0x10) << 4; - - vtotal |= (vga.crtc.overflow & 0x20) << 4; - vtotal |= (vga.s3.ex_ver_overflow & 0x1) << 10; - vdend |= (vga.crtc.overflow & 0x40) << 3; - vdend |= (vga.s3.ex_ver_overflow & 0x2) << 9; - vbstart |= (vga.crtc.maximum_scan_line & 0x20) << 4; - vbstart |= (vga.s3.ex_ver_overflow & 0x4) << 8; - vrstart |= ((vga.crtc.overflow & 0x80) << 2); - vrstart |= (vga.s3.ex_ver_overflow & 0x10) << 6; - vbend = vga.crtc.end_vertical_blanking & 0x3f; - } else { - vbend = vga.crtc.end_vertical_blanking & 0xf; - } - htotal += 2; - vtotal += 2; - hdend += 1; - vdend += 1; - - hbend = hbstart + ((hbend - hbstart) & 0x3F); - hrend = vga.crtc.end_horizontal_retrace & 0x1f; - hrend = (hrend - hrstart) & 0x1f; - - if ( !hrend ) hrend = hrstart + 0x1f + 1; - else hrend = hrstart + hrend; - - vrend = vga.crtc.vertical_retrace_end & 0xF; - vrend = ( vrend - vrstart)&0xF; - - if ( !vrend) vrend = vrstart + 0xf + 1; - else vrend = vrstart + vrend; - - vbend = (vbend - vbstart) & 0x3f; - if ( !vbend) vbend = vbstart + 0x3f + 1; - else vbend = vbstart + vbend; - - if (svga.get_clock) { - clock = svga.get_clock(); - } else { - switch ((vga.misc_output >> 2) & 3) { - case 0: - clock = (machine==MCH_EGA) ? 14318180 : 25175000; - break; - case 1: - default: - clock = (machine==MCH_EGA) ? 16257000 : 28322000; - break; - } - } - - /* Check for 8 for 9 character clock mode */ - if (vga.seq.clocking_mode & 1 ) clock/=8; else clock/=9; - /* Check for pixel doubling, master clock/2 */ - if (vga.seq.clocking_mode & 0x8) { - htotal*=2; - } - vga.draw.address_line_total=(vga.crtc.maximum_scan_line&0x1f)+1; - if(IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA)) { - // vgaonly; can't use with CGA because these use address_line for their - // own purposes. - // Set the low resolution modes to have as many lines as are scanned - - // Quite a few demos change the max_scanline register at display time - // to get SFX: Majic12 show, Magic circle, Copper, GBU, Party91 - if( vga.crtc.maximum_scan_line&0x80) vga.draw.address_line_total*=2; - vga.draw.double_scan=false; - } - else if (IS_VGA_ARCH) vga.draw.double_scan=(vga.crtc.maximum_scan_line&0x80)>0; - else vga.draw.double_scan=(vtotal==262); - } else { - htotal = vga.other.htotal + 1; - hdend = vga.other.hdend; - hbstart = hdend; - hbend = htotal; - hrstart = vga.other.hsyncp; - hrend = hrstart + (vga.other.syncw & 0xf) ; - - vga.draw.address_line_total = vga.other.max_scanline + 1; - vtotal = vga.draw.address_line_total * (vga.other.vtotal+1)+vga.other.vadjust; - vdend = vga.draw.address_line_total * vga.other.vdend; - vrstart = vga.draw.address_line_total * vga.other.vsyncp; - vrend = (vga.other.syncw >> 4); - if (!vrend) - vrend = vrstart + 0xf + 1; - else - vrend = vrstart + vrend; - vbstart = vdend; - vbend = vtotal; - vga.draw.double_scan=false; - switch (machine) { - case MCH_CGA: - case TANDY_ARCH_CASE: - clock=((vga.tandy.mode_control & 1) ? 14318180 : (14318180/2))/8; - break; - case MCH_HERC: - if (vga.herc.mode_control & 0x2) clock=16000000/16; - else clock=16000000/8; - break; - default: - clock = 14318180; - break; - } - } -#if C_DEBUG - LOG(LOG_VGA,LOG_NORMAL)("h total %d end %d blank (%d/%d) retrace (%d/%d)", - htotal, hdend, hbstart, hbend, hrstart, hrend ); - LOG(LOG_VGA,LOG_NORMAL)("v total %d end %d blank (%d/%d) retrace (%d/%d)", - vtotal, vdend, vbstart, vbend, vrstart, vrend ); -#endif - if (!htotal) return; - if (!vtotal) return; - - fps=(float)clock/(vtotal*htotal); - // The time a complete video frame takes - vga.draw.delay.vtotal = (1000.0 * (double)(vtotal*htotal)) / (double)clock; - // Horizontal total (that's how long a line takes with whistles and bells) - vga.draw.delay.htotal = htotal*1000.0/clock; //in milliseconds - // Start and End of horizontal blanking - vga.draw.delay.hblkstart = hbstart*1000.0/clock; //in milliseconds - vga.draw.delay.hblkend = hbend*1000.0/clock; - vga.draw.delay.hrstart = 0; - - // Start and End of vertical blanking - vga.draw.delay.vblkstart = vbstart * vga.draw.delay.htotal; - vga.draw.delay.vblkend = vbend * vga.draw.delay.htotal; - // Start and End of vertical retrace pulse - vga.draw.delay.vrstart = vrstart * vga.draw.delay.htotal; - vga.draw.delay.vrend = vrend * vga.draw.delay.htotal; - // Display end - vga.draw.delay.vdend = vdend * vga.draw.delay.htotal; - -#if C_DEBUG - LOG(LOG_VGA,LOG_NORMAL)("h total %2.5f (%3.2fkHz) blank(%02.5f/%02.5f) retrace(%02.5f/%02.5f)", - vga.draw.delay.htotal,(1.0/vga.draw.delay.htotal), - vga.draw.delay.hblkstart,vga.draw.delay.hblkend, - vga.draw.delay.hrstart,vga.draw.delay.hrend); - LOG(LOG_VGA,LOG_NORMAL)("v total %2.5f (%3.2fHz) blank(%02.5f/%02.5f) retrace(%02.5f/%02.5f)", - vga.draw.delay.vtotal,(1000.0/vga.draw.delay.vtotal), - vga.draw.delay.vblkstart,vga.draw.delay.vblkend, - vga.draw.delay.vrstart,vga.draw.delay.vrend); -#endif - - vga.draw.parts_total=VGA_PARTS; - /* - 6 Horizontal Sync Polarity. Negative if set - 7 Vertical Sync Polarity. Negative if set - Bit 6-7 indicates the number of lines on the display: - 1: 400, 2: 350, 3: 480 - */ - //Try to determine the pixel size, aspect correct is based around square pixels - - //Base pixel width around 100 clocks horizontal - //For 9 pixel text modes this should be changed, but we don't support that anyway :) - //Seems regular vga only listens to the 9 char pixel mode with character mode enabled - double pwidth = (machine==MCH_EGA) ? (114.0 / htotal) : (100.0 / htotal); - //Base pixel height around vertical totals of modes that have 100 clocks horizontal - //Different sync values gives different scaling of the whole vertical range - //VGA monitor just seems to thighten or widen the whole vertical range - double pheight; - double target_total = (machine==MCH_EGA) ? 262.0 : 449.0; - Bitu sync = vga.misc_output >> 6; - switch ( sync ) { - case 0: // This is not defined in vga specs, - // Kiet, seems to be slightly less than 350 on my monitor - //340 line mode, filled with 449 total - pheight = (480.0 / 340.0) * ( target_total / vtotal ); - break; - case 1: //400 line mode, filled with 449 total - pheight = (480.0 / 400.0) * ( target_total / vtotal ); - break; - case 2: //350 line mode, filled with 449 total - //This mode seems to get regular 640x400 timing and goes for a loong retrace - //Depends on the monitor to stretch the screen - pheight = (480.0 / 350.0) * ( target_total / vtotal ); - break; - case 3: //480 line mode, filled with 525 total - default: - pheight = (480.0 / 480.0) * ( 525.0 / vtotal ); - break; - } - - double aspect_ratio = pheight / pwidth; - - vga.draw.delay.parts = vga.draw.delay.vdend/vga.draw.parts_total; - vga.draw.resizing=false; - vga.draw.vret_triggered=false; - - //Check to prevent useless black areas - if (hbstart>=1; - else if(svgaCard == SVGA_S3Trio && !(vga.s3.reg_3a&0x10)) { - doublewidth=true; - width >>=1; - } - // fall-through - case M_LIN32: - width<<=3; - if (vga.crtc.mode_control & 0x8) - doublewidth = true; - /* Use HW mouse cursor drawer if enabled */ - VGA_ActivateHardwareCursor(); - break; - case M_LIN15: - case M_LIN16: - // 15/16 bpp modes double the horizontal values - width<<=2; - if ((vga.crtc.mode_control & 0x8) || (svgaCard == SVGA_S3Trio && (vga.s3.pll.cmd & 0x10))) - doublewidth = true; - /* Use HW mouse cursor drawer if enabled */ - VGA_ActivateHardwareCursor(); - break; - case M_LIN4: - doublewidth=(vga.seq.clocking_mode & 0x8) > 0; - vga.draw.blocks = width; - width<<=3; - VGA_DrawLine=VGA_Draw_Linear_Line; - vga.draw.linear_base = vga.fastmem; - vga.draw.linear_mask = (vga.vmemwrap<<1) - 1; - break; - case M_EGA: - doublewidth=(vga.seq.clocking_mode & 0x8) > 0; - vga.draw.blocks = width; - width<<=3; - if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) { - bpp=16; - VGA_DrawLine = VGA_Draw_Xlat16_Linear_Line; - } else VGA_DrawLine=VGA_Draw_Linear_Line; - - vga.draw.linear_base = vga.fastmem; - vga.draw.linear_mask = (vga.vmemwrap<<1) - 1; - break; - case M_CGA16: - doubleheight=true; - vga.draw.blocks=width*2; - width<<=4; - VGA_DrawLine=VGA_Draw_CGA16_Line; - break; - case M_CGA4: - doublewidth=true; - vga.draw.blocks=width*2; - width<<=3; - VGA_DrawLine=VGA_Draw_2BPP_Line; - break; - case M_CGA2: - doubleheight=true; - vga.draw.blocks=2*width; - width<<=3; - VGA_DrawLine=VGA_Draw_1BPP_Line; - break; - case M_TEXT: - aspect_ratio=1.0; - vga.draw.blocks=width; - doublewidth=(vga.seq.clocking_mode & 0x8) > 0; - if ((IS_VGA_ARCH) && (svgaCard==SVGA_None) && !(vga.seq.clocking_mode&0x01)) { - width*=9; /* 9 bit wide text font */ - VGA_DrawLine=VGA_TEXT_Xlat16_Draw_Line_9; - bpp=16; -// VGA_DrawLine=VGA_TEXT_Draw_Line_9; - } else { - width<<=3; /* 8 bit wide text font */ - if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) { - VGA_DrawLine=VGA_TEXT_Xlat16_Draw_Line; - bpp=16; - } else VGA_DrawLine=VGA_TEXT_Draw_Line; - } - break; - case M_HERC_GFX: - aspect_ratio=1.5; - vga.draw.blocks=width*2; - width*=16; - VGA_DrawLine=VGA_Draw_1BPP_Line; - break; - case M_TANDY2: - aspect_ratio=1.2; - doubleheight=true; - if (machine==MCH_PCJR) doublewidth=(vga.tandy.gfx_control & 0x8)==0x00; - else doublewidth=(vga.tandy.mode_control & 0x10)==0; - vga.draw.blocks=width * (doublewidth ? 4:8); - width=vga.draw.blocks*2; - VGA_DrawLine=VGA_Draw_1BPP_Line; - break; - case M_TANDY4: - aspect_ratio=1.2; - doubleheight=true; - if (machine==MCH_TANDY) doublewidth=(vga.tandy.mode_control & 0x10)==0; - else doublewidth=(vga.tandy.mode_control & 0x01)==0x00; - vga.draw.blocks=width * 2; - width=vga.draw.blocks*4; - if ((machine==MCH_TANDY && (vga.tandy.gfx_control & 0x8)) || - (machine==MCH_PCJR && (vga.tandy.mode_control==0x0b))) - VGA_DrawLine=VGA_Draw_2BPPHiRes_Line; - else VGA_DrawLine=VGA_Draw_2BPP_Line; - break; - case M_TANDY16: - aspect_ratio=1.2; - doubleheight=true; - vga.draw.blocks=width*2; - if (vga.tandy.mode_control & 0x1) { - if (( machine==MCH_TANDY ) && ( vga.tandy.mode_control & 0x10 )) { - doublewidth = false; - vga.draw.blocks*=2; - width=vga.draw.blocks*2; - } else { - doublewidth = true; - width=vga.draw.blocks*2; - } - VGA_DrawLine=VGA_Draw_4BPP_Line; - } else { - doublewidth=true; - width=vga.draw.blocks*4; - VGA_DrawLine=VGA_Draw_4BPP_Line_Double; - } - break; - case M_TANDY_TEXT: - doublewidth=(vga.tandy.mode_control & 0x1)==0; - aspect_ratio=1; - doubleheight=true; - vga.draw.blocks=width; - width<<=3; - VGA_DrawLine=VGA_TEXT_Draw_Line; - break; - case M_HERC_TEXT: - aspect_ratio=1; - vga.draw.blocks=width; - width<<=3; - VGA_DrawLine=VGA_TEXT_Herc_Draw_Line; - break; - default: - LOG(LOG_VGA,LOG_ERROR)("Unhandled VGA mode %d while checking for resolution",vga.mode); - break; - } - VGA_CheckScanLength(); - if (vga.draw.double_scan) { - if (IS_VGA_ARCH) height/=2; - doubleheight=true; - } - - if(!(IS_VGA_ARCH && (svgaCard==SVGA_None) && (vga.mode==M_EGA || vga.mode==M_VGA))) { - //Only check for extra double height in vga modes - //(line multiplying by address_line_total) - if (!doubleheight && (vga.mode 640x480 modes have 4:3 aspect ratio - */ - if ( width >= 640 && height >= 480 ) { - aspect_ratio = ((float)width / (float)height) * ( 3.0 / 4.0); - } -// LOG_MSG("ht %d vt %d ratio %f", htotal, vtotal, aspect_ratio ); - - if (( width != vga.draw.width) || (height != vga.draw.height) || - (aspect_ratio != vga.draw.aspect_ratio) || - (vga.mode != vga.lastmode)) { - vga.lastmode = vga.mode; - PIC_RemoveEvents(VGA_VerticalTimer); - PIC_RemoveEvents(VGA_PanningLatch); - PIC_RemoveEvents(VGA_DisplayStartLatch); - PIC_RemoveEvents(VGA_DrawPart); - PIC_RemoveEvents(VGA_DrawSingleLine); - vga.draw.width = width; - vga.draw.height = height; - vga.draw.doublewidth = doublewidth; - vga.draw.doubleheight = doubleheight; - vga.draw.aspect_ratio = aspect_ratio; - if (doubleheight) vga.draw.lines_scaled=2; - else vga.draw.lines_scaled=1; -#if C_DEBUG - LOG(LOG_VGA,LOG_NORMAL)("Width %d, Height %d, fps %f",width,height,fps); - LOG(LOG_VGA,LOG_NORMAL)("%s width, %s height aspect %f", - doublewidth ? "double":"normal",doubleheight ? "double":"normal",aspect_ratio); -#endif - RENDER_SetSize(width,height,bpp,fps,aspect_ratio,doublewidth,doubleheight); - vga.draw.delay.framestart = PIC_FullIndex(); - PIC_AddEvent( VGA_VerticalTimer , (float)vga.draw.delay.vtotal ); - vga.draw.lines_done = 0; - } -} - -void VGA_KillDrawing(void) { - PIC_RemoveEvents(VGA_DrawPart); - PIC_RemoveEvents(VGA_DrawSingleLine); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "dosbox.h" +#include "video.h" +#include "vga.h" + + +/* This Should draw a complete 16 colour screen */ + +void VGA_Render_GFX_4(Bit8u * * data) { + *data=vga.buffer; + VGA_DrawGFX4_Full(vga.buffer,vga.draw.width); + vga.config.retrace=true; +} + +void VGA_Render_GFX_16(Bit8u * * data) { + *data=&vga.buffer[vga.config.display_start*8+vga.config.pel_panning]; + vga.config.retrace=true; +} + +void VGA_Render_GFX_256U(Bit8u * * data) { + *data=&vga.mem.linear[vga.config.display_start*4+vga.config.pel_panning]; + vga.config.retrace=true; +} + +void VGA_Render_GFX_256C(Bit8u * * data) { + *data=memory+0xa0000; + vga.config.retrace=true; +} + +void VGA_Render_TEXT_16(Bit8u * * data) { + *data=vga.buffer; + VGA_DrawTEXT(vga.buffer,vga.draw.width); + vga.config.retrace=true; +} + + + + +void VGA_DrawGFX4_Full(Bit8u * bitdata,Bitu next_line) { + //TODO use vga memory handler + Bit8u * reader=real_host(0xB800,0); + Bit8u * draw; + for (Bitu y=0;y>2;x++) { + Bit8u val=*(tempread++); +/* + *(draw+0)=(val>>6)&3; + *(draw+1)=(val>>4)&3; + *(draw+2)=(val>>2)&3; + *(draw+3)=(val)&3; + draw+=4; +*/ + *(Bit32u *)draw=CGAWriteTable[val]; + draw+=4; + } + //TODO use scanline length and dword mode crap + bitdata+=next_line; + }; + vga.config.retrace=true; +} + +void VGA_DrawGFX16_Full(Bit8u * bitdata,Bitu next_line) { + Bit8u * reader=&vga.buffer[vga.config.display_start*8+vga.config.pel_panning]; + for (Bitu y=0;y>2;x++) { + for (Bit32u dx=0;dx<4;dx++) { + (*bitdata++)=vga.mem.paged[xreader][dx]; + } + xreader++; + } + //TODO use scanline length and dword mode crap + yreader+=vga.config.scan_len*2; + bitdata+=next_line; + }; + vga.config.retrace=true; +}; + +void VGA_DrawGFX256_Fast(Bit8u * bitdata,Bitu next_line) { + /* For now just copy 64 kb of memory with pitch support */ + Bit8u * reader=memory+0xa0000; + for (Bitu y=0;y> 4); + Bit8u * draw=draw_char; + for (Bitu y=0;y<16;y++) { + Bit8u bit_mask=*findex++; + #include "font-switch.h" + draw+=+next_line; + }; + draw_char+=8; + }; + draw_start+=16*next_line; + }; + vga.config.retrace=true; + + /* Draw a cursor */ + if ((vga.draw.cursor_col*8)>=vga.draw.width) return; + if ((vga.draw.cursor_row*16)>=vga.draw.height) return; + Bit8u * cursor_draw=bitdata+(vga.draw.cursor_row*16+15)*vga.draw.width+vga.draw.cursor_col*8; + if (vga.draw.cursor_count>8) { + for (Bit8u loop=0;loop<8;loop++) *cursor_draw++=15; + } + vga.draw.cursor_count++; + if (vga.draw.cursor_count>16) vga.draw.cursor_count=0; +}; + diff --git a/src/hardware/vga_fonts.cpp b/src/hardware/vga_fonts.cpp new file mode 100644 index 0000000..bba9b32 --- /dev/null +++ b/src/hardware/vga_fonts.cpp @@ -0,0 +1,1254 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Bitmap fonts for the VGA emulation; taken from + * ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip + * + * See copyleft_vgafonts.txt for the copyright notice. + */ +#include "dosbox.h" +#include "mem.h" +#include "vga.h" + +Bit8u vga_rom_08[256 * 8] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, + 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, + 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, + 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, + 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, + 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, + 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, + 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, + 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, + 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, + 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, + 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, + 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, + 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, + 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, + 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, + 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, + 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, + 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, + 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, + 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00, + 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, + 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, + 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, + 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, + 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, + 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, + 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, + 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, + 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, + 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, + 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, + 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, + 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, + 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, + 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, + 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, + 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, + 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, + 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, + 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, + 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, + 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, + 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, + 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, + 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, + 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, + 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, + 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, + 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, + 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, + 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, + 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, + 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, + 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, + 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, + 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, + 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, + 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, + 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, + 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, + 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, + 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, + 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, + 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, + 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, + 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, + 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, + 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, + 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, + 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, + 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, + 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, + 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, + 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, + 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, + 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, + 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, + 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, + 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, + 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, + 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, + 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, + 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, + 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, + 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, + 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, + 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, + 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, + 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, + 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, + 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, + 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00, + 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00, + 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, + 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, + 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f, + 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, + 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, + 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00, + 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0, + 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, + 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, + 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00, + 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0, + 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00, + 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc, + 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00, + 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, + 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0, + 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00, + 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, + 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, + 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00, + 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, + 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, + 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, + 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, + 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, + 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +Bit8u vga_rom_14[256 * 14] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, + 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, + 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, + 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, + 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, + 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, + 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, + 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x70, 0xf0, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, + 0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, + 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xf8, + 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, + 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x7c, + 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, + 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, + 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, + 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, + 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, + 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, + 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x66, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, + 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, + 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, + 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, + 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, + 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, + 0x3c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, + 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x60, + 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x0c, + 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, + 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0c, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, + 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, + 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, + 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, + 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, + 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, + 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, + 0xc0, 0xde, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, + 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x6c, + 0x78, 0x6c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xe6, + 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, + 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, + 0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, + 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, + 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, + 0xd6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, + 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, + 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, + 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x3c, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, + 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, + 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, + 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, + 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, + 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, + 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, + 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, + 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, + 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, + 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, + 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, + 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, + 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, + 0xc6, 0x70, 0x1c, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, + 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, + 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, + 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, + 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, + 0x70, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, + 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, + 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc2, + 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, 0x00, + 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0x76, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, + 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, + 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, + 0x76, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, + 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, + 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcc, 0xcc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, + 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, + 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x10, + 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, + 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, + 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, + 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, + 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, + 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0xcc, + 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, + 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, 0x00, 0xc6, + 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, + 0x38, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x00, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, + 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, + 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, + 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xc6, 0x00, + 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, + 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, + 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x76, 0xdc, + 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, + 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, + 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, + 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, + 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x66, + 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x3c, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, + 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x55, 0xaa, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, + 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, + 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, + 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, + 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, + 0xc0, 0xc0, 0x40, 0x00, 0x00, 0x00, 0xfe, 0xc6, + 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, + 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, + 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, + 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, + 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, + 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, + 0x60, 0x60, 0x7c, 0x60, 0x60, 0x30, 0x1c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, + 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, + 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, + 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, + 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +Bit8u vga_rom_16[256 * 16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, + 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, + 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, + 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, + 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, + 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, + 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, + 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, + 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, + 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, + 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, + 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, + 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, + 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, + 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, + 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, + 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, + 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, + 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, + 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, + 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, + 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, + 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, + 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, + 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, + 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, + 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, + 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, + 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, + 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, + 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, + 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, + 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, + 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, + 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, + 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, + 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, + 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, + 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, + 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, + 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, + 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, + 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, + 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, + 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, + 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, + 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, + 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, + 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, + 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, + 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, + 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, + 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, + 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, + 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, + 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, + 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, + 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, + 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, + 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, + 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 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, 0xff, 0x00, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, + 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, + 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, + 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, + 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, + 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, + 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, + 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, + 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, + 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, + 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, + 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, + 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, + 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, + 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, + 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, + 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, + 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, + 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, + 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, + 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, + 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, + 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, + 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, + 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, + 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, + 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, + 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, + 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, + 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, + 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, + 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, + 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, + 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, + 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, + 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, + 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, + 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, + 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, + 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, + 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, + 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, + 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, + 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, + 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, + 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, + 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, + 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, + 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, + 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, + 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, + 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, + 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, + 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + diff --git a/src/hardware/vga_gfx.cpp b/src/hardware/vga_gfx.cpp index 6b90a90..ddbb133 100644 --- a/src/hardware/vga_gfx.cpp +++ b/src/hardware/vga_gfx.cpp @@ -1,236 +1,221 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_gfx.cpp,v 1.18 2008/01/09 20:34:51 c2woody Exp $ */ - -#include "dosbox.h" -#include "inout.h" -#include "vga.h" - -#define gfx(blah) vga.gfx.blah -static bool index9warned=false; - -static void write_p3ce(Bitu port,Bitu val,Bitu iolen) { - gfx(index)=val & 0x0f; -} - -static Bitu read_p3ce(Bitu port,Bitu iolen) { - return gfx(index); -} - -static void write_p3cf(Bitu port,Bitu val,Bitu iolen) { - switch (gfx(index)) { - case 0: /* Set/Reset Register */ - gfx(set_reset)=val & 0x0f; - vga.config.full_set_reset=FillTable[val & 0x0f]; - vga.config.full_enable_and_set_reset=vga.config.full_set_reset & - vga.config.full_enable_set_reset; - /* - 0 If in Write Mode 0 and bit 0 of 3CEh index 1 is set a write to - display memory will set all the bits in plane 0 of the byte to this - bit, if the corresponding bit is set in the Map Mask Register (3CEh - index 8). - 1 Same for plane 1 and bit 1 of 3CEh index 1. - 2 Same for plane 2 and bit 2 of 3CEh index 1. - 3 Same for plane 3 and bit 3 of 3CEh index 1. - */ -// LOG_DEBUG("Set Reset = %2X",val); - break; - case 1: /* Enable Set/Reset Register */ - gfx(enable_set_reset)=val & 0x0f; - vga.config.full_enable_set_reset=FillTable[val & 0x0f]; - vga.config.full_not_enable_set_reset=~vga.config.full_enable_set_reset; - vga.config.full_enable_and_set_reset=vga.config.full_set_reset & - vga.config.full_enable_set_reset; -// if (gfx(enable_set_reset)) vga.config.mh_mask|=MH_SETRESET else vga.config.mh_mask&=~MH_SETRESET; - break; - case 2: /* Color Compare Register */ - gfx(color_compare)=val & 0x0f; - /* - 0-3 In Read Mode 1 each pixel at the address of the byte read is compared - to this color and the corresponding bit in the output set to 1 if - they match, 0 if not. The Color Don't Care Register (3CEh index 7) - can exclude bitplanes from the comparison. - */ - vga.config.color_compare=val & 0xf; -// LOG_DEBUG("Color Compare = %2X",val); - break; - case 3: /* Data Rotate */ - gfx(data_rotate)=val; - vga.config.data_rotate=val & 7; -// if (val) vga.config.mh_mask|=MH_ROTATEOP else vga.config.mh_mask&=~MH_ROTATEOP; - vga.config.raster_op=(val>>3) & 3; - /* - 0-2 Number of positions to rotate data right before it is written to - display memory. Only active in Write Mode 0. - 3-4 In Write Mode 2 this field controls the relation between the data - written from the CPU, the data latched from the previous read and the - data written to display memory: - 0: CPU Data is written unmodified - 1: CPU data is ANDed with the latched data - 2: CPU data is ORed with the latch data. - 3: CPU data is XORed with the latched data. - */ - break; - case 4: /* Read Map Select Register */ - /* 0-1 number of the plane Read Mode 0 will read from */ - gfx(read_map_select)=val & 0x03; - vga.config.read_map_select=val & 0x03; -// LOG_DEBUG("Read Map %2X",val); - break; - case 5: /* Mode Register */ - if ((gfx(mode) ^ val) & 0xf0) { - gfx(mode)=val; - VGA_DetermineMode(); - } else gfx(mode)=val; - vga.config.write_mode=val & 3; - vga.config.read_mode=(val >> 3) & 1; -// LOG_DEBUG("Write Mode %d Read Mode %d val %d",vga.config.write_mode,vga.config.read_mode,val); - /* - 0-1 Write Mode: Controls how data from the CPU is transformed before - being written to display memory: - 0: Mode 0 works as a Read-Modify-Write operation. - First a read access loads the data latches of the VGA with the - value in video memory at the addressed location. Then a write - access will provide the destination address and the CPU data - byte. The data written is modified by the function code in the - Data Rotate register (3CEh index 3) as a function of the CPU - data and the latches, then data is rotated as specified by the - same register. - 1: Mode 1 is used for video to video transfers. - A read access will load the data latches with the contents of - the addressed byte of video memory. A write access will write - the contents of the latches to the addressed byte. Thus a single - MOVSB instruction can copy all pixels in the source address byte - to the destination address. - 2: Mode 2 writes a color to all pixels in the addressed byte of - video memory. Bit 0 of the CPU data is written to plane 0 et - cetera. Individual bits can be enabled or disabled through the - Bit Mask register (3CEh index 8). - 3: Mode 3 can be used to fill an area with a color and pattern. The - CPU data is rotated according to 3CEh index 3 bits 0-2 and anded - with the Bit Mask Register (3CEh index 8). For each bit in the - result the corresponding pixel is set to the color in the - Set/Reset Register (3CEh index 0 bits 0-3) if the bit is set and - to the contents of the processor latch if the bit is clear. - 3 Read Mode - 0: Data is read from one of 4 bit planes depending on the Read Map - Select Register (3CEh index 4). - 1: Data returned is a comparison between the 8 pixels occupying the - read byte and the color in the Color Compare Register (3CEh - index 2). A bit is set if the color of the corresponding pixel - matches the register. - 4 Enables Odd/Even mode if set (See 3C4h index 4 bit 2). - 5 Enables CGA style 4 color pixels using even/odd bit pairs if set. - 6 Enables 256 color mode if set. - */ - break; - case 6: /* Miscellaneous Register */ - if ((gfx(miscellaneous) ^ val) & 0x0c) { - gfx(miscellaneous)=val; - VGA_DetermineMode(); - } else gfx(miscellaneous)=val; - VGA_SetupHandlers(); - /* - 0 Indicates Graphics Mode if set, Alphanumeric mode else. - 1 Enables Odd/Even mode if set. - 2-3 Memory Mapping: - 0: use A000h-BFFFh - 1: use A000h-AFFFh VGA Graphics modes - 2: use B000h-B7FFh Monochrome modes - 3: use B800h-BFFFh CGA modes - */ - break; - case 7: /* Color Don't Care Register */ - gfx(color_dont_care)=val & 0x0f; - /* - 0 Ignore bit plane 0 in Read mode 1 if clear. - 1 Ignore bit plane 1 in Read mode 1 if clear. - 2 Ignore bit plane 2 in Read mode 1 if clear. - 3 Ignore bit plane 3 in Read mode 1 if clear. - */ - vga.config.color_dont_care=val & 0xf; -// LOG_DEBUG("Color don't care = %2X",val); - break; - case 8: /* Bit Mask Register */ - gfx(bit_mask)=val; - vga.config.full_bit_mask=ExpandTable[val]; -// LOG_DEBUG("Bit mask %2X",val); - /* - 0-7 Each bit if set enables writing to the corresponding bit of a byte in - display memory. - */ - break; - default: - if (svga.write_p3cf) { - svga.write_p3cf(gfx(index), val, iolen); - break; - } - if (gfx(index) == 9 && !index9warned) { - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:3CF:Write %2X to illegal index 9",val); - index9warned=true; - break; - } - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:3CF:Write %2X to illegal index %2X",val,gfx(index)); - break; - } -} - -static Bitu read_p3cf(Bitu port,Bitu iolen) { - switch (gfx(index)) { - case 0: /* Set/Reset Register */ - return gfx(set_reset); - case 1: /* Enable Set/Reset Register */ - return gfx(enable_set_reset); - case 2: /* Color Compare Register */ - return gfx(color_compare); - case 3: /* Data Rotate */ - return gfx(data_rotate); - case 4: /* Read Map Select Register */ - return gfx(read_map_select); - case 5: /* Mode Register */ - return gfx(mode); - case 6: /* Miscellaneous Register */ - return gfx(miscellaneous); - case 7: /* Color Don't Care Register */ - return gfx(color_dont_care); - case 8: /* Bit Mask Register */ - return gfx(bit_mask); - default: - if (svga.read_p3cf) - return svga.read_p3cf(gfx(index), iolen); - LOG(LOG_VGAMISC,LOG_NORMAL)("Reading from illegal index %2X in port %4X",static_cast(gfx(index)),port); - break; - } - return 0; /* Compiler happy */ -} - - - -void VGA_SetupGFX(void) { - if (IS_EGAVGA_ARCH) { - IO_RegisterWriteHandler(0x3ce,write_p3ce,IO_MB); - IO_RegisterWriteHandler(0x3cf,write_p3cf,IO_MB); - if (IS_VGA_ARCH) { - IO_RegisterReadHandler(0x3ce,read_p3ce,IO_MB); - IO_RegisterReadHandler(0x3cf,read_p3cf,IO_MB); - } - } -} - - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "inout.h" +#include "vga.h" + + +#define gfx(blah) vga.gfx.blah +static bool index9warned=false; + +void write_p3ce(Bit32u port,Bit8u val) { + gfx(index)=val & 0x0f; +} + +Bit8u read_p3ce(Bit32u port) { + return gfx(index); +} + +void write_p3cf(Bit32u port,Bit8u val) { + switch (gfx(index)) { + case 0: /* Set/Reset Register */ + gfx(set_reset)=val & 0x0f; + vga.config.set_reset=val & 0x0f; + /* + 0 If in Write Mode 0 and bit 0 of 3CEh index 1 is set a write to + display memory will set all the bits in plane 0 of the byte to this + bit, if the corresponding bit is set in the Map Mask Register (3CEh + index 8). + 1 Same for plane 1 and bit 1 of 3CEh index 1. + 2 Same for plane 2 and bit 2 of 3CEh index 1. + 3 Same for plane 3 and bit 3 of 3CEh index 1. + */ +// LOG_DEBUG("Set Reset = %2X",val); + break; + case 1: /* Enable Set/Reset Register */ + gfx(enable_set_reset)=val & 0x0f; + vga.config.enable_set_reset=val & 0x0f; + /* + 0 If set enables Set/reset of plane 0 in Write Mode 0. + 1 Same for plane 1. + 2 Same for plane 2. + 3 Same for plane 3. + */ +// LOG_DEBUG("Enable Set Reset = %2X",val); + break; + case 2: /* Color Compare Register */ + gfx(color_compare)=val & 0x0f; + /* + 0-3 In Read Mode 1 each pixel at the address of the byte read is compared + to this color and the corresponding bit in the output set to 1 if + they match, 0 if not. The Color Don't Care Register (3CEh index 7) + can exclude bitplanes from the comparison. + */ + vga.config.color_compare=val & 0xf; +// LOG_DEBUG("Color Compare = %2X",val); + break; + case 3: /* Data Rotate */ + gfx(data_rotate)=val; + vga.config.data_rotate=val & 7; + vga.config.raster_op=(val>>3) & 3; + /* + 0-2 Number of positions to rotate data right before it is written to + display memory. Only active in Write Mode 0. + 3-4 In Write Mode 2 this field controls the relation between the data + written from the CPU, the data latched from the previous read and the + data written to display memory: + 0: CPU Data is written unmodified + 1: CPU data is ANDed with the latched data + 2: CPU data is ORed with the latch data. + 3: CPU data is XORed with the latched data. + */ +// if (vga.config.data_rotate || vga.config.raster_op ) LOG_DEBUG("Data Rotate = %2X Raster op %2X",val & 7,(val>>3) & 3 ); + break; + case 4: /* Read Map Select Register */ + /* 0-1 number of the plane Read Mode 0 will read from */ + gfx(read_map_select)=val & 0x03; + vga.config.read_map_select=val & 0x03; +// LOG_DEBUG("Read Map %2X",val); + break; + case 5: /* Mode Register */ /* Important one very */ + gfx(mode)=val; + vga.config.write_mode=val & 3; + vga.config.read_mode=(val >> 3) & 1; +// LOG_DEBUG("Write Mode %d Read Mode %d val %d",vga.config.write_mode,vga.config.read_mode,val); + /* + 0-1 Write Mode: Controls how data from the CPU is transformed before + being written to display memory: + 0: Mode 0 works as a Read-Modify-Write operation. + First a read access loads the data latches of the VGA with the + value in video memory at the addressed location. Then a write + access will provide the destination address and the CPU data + byte. The data written is modified by the function code in the + Data Rotate register (3CEh index 3) as a function of the CPU + data and the latches, then data is rotated as specified by the + same register. + 1: Mode 1 is used for video to video transfers. + A read access will load the data latches with the contents of + the addressed byte of video memory. A write access will write + the contents of the latches to the addressed byte. Thus a single + MOVSB instruction can copy all pixels in the source address byte + to the destination address. + 2: Mode 2 writes a color to all pixels in the addressed byte of + video memory. Bit 0 of the CPU data is written to plane 0 et + cetera. Individual bits can be enabled or disabled through the + Bit Mask register (3CEh index 8). + 3: Mode 3 can be used to fill an area with a color and pattern. The + CPU data is rotated according to 3CEh index 3 bits 0-2 and anded + with the Bit Mask Register (3CEh index 8). For each bit in the + result the corresponding pixel is set to the color in the + Set/Reset Register (3CEh index 0 bits 0-3) if the bit is set and + to the contents of the processor latch if the bit is clear. + 3 Read Mode + 0: Data is read from one of 4 bit planes depending on the Read Map + Select Register (3CEh index 4). + 1: Data returned is a comparison between the 8 pixels occupying the + read byte and the color in the Color Compare Register (3CEh + index 2). A bit is set if the color of the corresponding pixel + matches the register. + 4 Enables Odd/Even mode if set (See 3C4h index 4 bit 2). + 5 Enables CGA style 4 color pixels using even/odd bit pairs if set. + 6 Enables 256 color mode if set. + + */ + break; + case 6: /* Miscellaneous Register */ + gfx(miscellaneous)=val; + /* + 0 Indicates Graphics Mode if set, Alphanumeric mode else. + 1 Enables Odd/Even mode if set. + 2-3 Memory Mapping: + 0: use A000h-BFFFh + 1: use A000h-AFFFh VGA Graphics modes + 2: use B000h-B7FFh Monochrome modes + 3: use B800h-BFFFh CGA modes + */ + break; + case 7: /* Color Don't Care Register */ + gfx(color_dont_care)=val & 0x0f; + /* + 0 Ignore bit plane 0 in Read mode 1 if clear. + 1 Ignore bit plane 1 in Read mode 1 if clear. + 2 Ignore bit plane 2 in Read mode 1 if clear. + 3 Ignore bit plane 3 in Read mode 1 if clear. + */ + vga.config.color_dont_care=val & 0xf; +// LOG_DEBUG("Color don't care = %2X",val); + break; + case 8: /* Bit Mask Register */ + gfx(bit_mask)=val; + vga.config.full_bit_mask=ExpandTable[val]; +// LOG_DEBUG("Bit mask %2X",val); + /* + 0-7 Each bit if set enables writing to the corresponding bit of a byte in + display memory. + */ + break; + case 9: /* Unknown */ + /* Crystal Dreams seems to like to write tothis register very weird */ + if (!index9warned) { + LOG_WARN("VGA:3CF:Write %2X to illegal index 9",val); + index9warned=true; + } + break; + default: + LOG_WARN("VGA:3CF:Write %2X to illegal index %2X",val,gfx(index)); + break; + } +} + +Bit8u read_p3cf(Bit32u port) { +switch (gfx(index)) { + case 0: /* Set/Reset Register */ + return gfx(set_reset); + case 1: /* Enable Set/Reset Register */ + return gfx(enable_set_reset); + case 2: /* Color Compare Register */ + return gfx(color_compare); + case 3: /* Data Rotate */ + return gfx(data_rotate); + case 4: /* Read Map Select Register */ + return gfx(read_map_select); + case 5: /* Mode Register */ + return gfx(mode); + case 6: /* Miscellaneous Register */ + return gfx(miscellaneous); + case 7: /* Color Don't Care Register */ + return gfx(color_dont_care); + case 8: /* Bit Mask Register */ + return gfx(bit_mask); + default: + LOG_WARN("Reading from illegal index %2X in port %4X",gfx(index),port); + } + return 0; /* Compiler happy */ +} + + + +void VGA_SetupGFX(void) { + IO_RegisterWriteHandler(0x3ce,write_p3ce,"VGA Graphics Index"); + IO_RegisterWriteHandler(0x3cf,write_p3cf,"VGA Graphics Data"); + IO_RegisterReadHandler(0x3ce,read_p3ce,"Vga Graphics Index"); + IO_RegisterReadHandler(0x3cf,read_p3cf,"Vga Graphics Data"); +} + + diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 5fd22a1..ffd2f0a 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -1,948 +1,214 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_memory.cpp,v 1.52 2009/03/22 21:04:41 c2woody Exp $ */ - -#include -#include -#include "dosbox.h" -#include "mem.h" -#include "vga.h" -#include "paging.h" -#include "pic.h" -#include "inout.h" -#include "setup.h" - - -#ifndef C_VGARAM_CHECKED -#define C_VGARAM_CHECKED 1 -#endif - -#if C_VGARAM_CHECKED -// Checked linear offset -#define CHECKED(v) ((v)&(vga.vmemwrap-1)) -// Checked planar offset (latched access) -#define CHECKED2(v) ((v)&((vga.vmemwrap>>2)-1)) -#else -#define CHECKED(v) (v) -#define CHECKED2(v) (v) -#endif - -#define CHECKED3(v) ((v)&(vga.vmemwrap-1)) -#define CHECKED4(v) ((v)&((vga.vmemwrap>>2)-1)) - - -#ifdef VGA_KEEP_CHANGES -#define MEM_CHANGED( _MEM ) vga.changes.map[ (_MEM) >> VGA_CHANGE_SHIFT ] |= vga.changes.writeMask; -//#define MEM_CHANGED( _MEM ) vga.changes.map[ (_MEM) >> VGA_CHANGE_SHIFT ] = 1; -#else -#define MEM_CHANGED( _MEM ) -#endif - -#define TANDY_VIDBASE(_X_) &MemBase[ 0x80000 + (_X_)] - -template -static INLINE void hostWrite(HostPt off, Bitu val) { - if ( sizeof( Size ) == 1) - host_writeb( off, (Bit8u)val ); - else if ( sizeof( Size ) == 2) - host_writew( off, (Bit16u)val ); - else if ( sizeof( Size ) == 4) - host_writed( off, (Bit32u)val ); -} - -template -static INLINE Bitu hostRead(HostPt off ) { - if ( sizeof( Size ) == 1) - return host_readb( off ); - else if ( sizeof( Size ) == 2) - return host_readw( off ); - else if ( sizeof( Size ) == 4) - return host_readd( off ); - return 0; -} - - -void VGA_MapMMIO(void); -//Nice one from DosEmu -INLINE static Bit32u RasterOp(Bit32u input,Bit32u mask) { - switch (vga.config.raster_op) { - case 0x00: /* None */ - return (input & mask) | (vga.latch.d & ~mask); - case 0x01: /* AND */ - return (input | ~mask) & vga.latch.d; - case 0x02: /* OR */ - return (input & mask) | vga.latch.d; - case 0x03: /* XOR */ - return (input & mask) ^ vga.latch.d; - }; - return 0; -} - -INLINE static Bit32u ModeOperation(Bit8u val) { - Bit32u full; - switch (vga.config.write_mode) { - case 0x00: - // Write Mode 0: In this mode, the host data is first rotated as per the Rotate Count field, then the Enable Set/Reset mechanism selects data from this or the Set/Reset field. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. - val=((val >> vga.config.data_rotate) | (val << (8-vga.config.data_rotate))); - full=ExpandTable[val]; - full=(full & vga.config.full_not_enable_set_reset) | vga.config.full_enable_and_set_reset; - full=RasterOp(full,vga.config.full_bit_mask); - break; - case 0x01: - // Write Mode 1: In this mode, data is transferred directly from the 32 bit latch register to display memory, affected only by the Memory Plane Write Enable field. The host data is not used in this mode. - full=vga.latch.d; - break; - case 0x02: - //Write Mode 2: In this mode, the bits 3-0 of the host data are replicated across all 8 bits of their respective planes. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. - full=RasterOp(FillTable[val&0xF],vga.config.full_bit_mask); - break; - case 0x03: - // Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. - full=RasterOp(vga.config.full_set_reset,ExpandTable[val] & vga.config.full_bit_mask); - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:Unsupported write mode %d",vga.config.write_mode); - full=0; - break; - } - return full; -} - -/* Gonna assume that whoever maps vga memory, maps it on 32/64kb boundary */ - -#define VGA_PAGES (128/4) -#define VGA_PAGE_A0 (0xA0000/4096) -#define VGA_PAGE_B0 (0xB0000/4096) -#define VGA_PAGE_B8 (0xB8000/4096) - -static struct { - Bitu base, mask; -} vgapages; - -class VGA_UnchainedRead_Handler : public PageHandler { -public: - Bitu readHandler(PhysPt start) { - vga.latch.d=((Bit32u*)vga.mem.linear)[start]; - switch (vga.config.read_mode) { - case 0: - return (vga.latch.b[vga.config.read_map_select]); - case 1: - VGA_Latch templatch; - templatch.d=(vga.latch.d & FillTable[vga.config.color_dont_care]) ^ FillTable[vga.config.color_compare & vga.config.color_dont_care]; - return (Bit8u)~(templatch.b[0] | templatch.b[1] | templatch.b[2] | templatch.b[3]); - } - return 0; - } -public: - Bitu readb(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED2(addr); - return readHandler(addr); - } - Bitu readw(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED2(addr); - return - (readHandler(addr+0) << 0) | - (readHandler(addr+1) << 8); - } - Bitu readd(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED2(addr); - return - (readHandler(addr+0) << 0) | - (readHandler(addr+1) << 8) | - (readHandler(addr+2) << 16) | - (readHandler(addr+3) << 24); - } -}; - -class VGA_ChainedEGA_Handler : public PageHandler { -public: - Bitu readHandler(PhysPt addr) { - return vga.mem.linear[addr]; - } - void writeHandler(PhysPt start, Bit8u val) { - ModeOperation(val); - /* Update video memory and the pixel buffer */ - VGA_Latch pixels; - vga.mem.linear[start] = val; - start >>= 2; - pixels.d=((Bit32u*)vga.mem.linear)[start]; - - Bit8u * write_pixels=&vga.fastmem[start<<3]; - - Bit32u colors0_3, colors4_7; - VGA_Latch temp;temp.d=(pixels.d>>4) & 0x0f0f0f0f; - colors0_3 = - Expand16Table[0][temp.b[0]] | - Expand16Table[1][temp.b[1]] | - Expand16Table[2][temp.b[2]] | - Expand16Table[3][temp.b[3]]; - *(Bit32u *)write_pixels=colors0_3; - temp.d=pixels.d & 0x0f0f0f0f; - colors4_7 = - Expand16Table[0][temp.b[0]] | - Expand16Table[1][temp.b[1]] | - Expand16Table[2][temp.b[2]] | - Expand16Table[3][temp.b[3]]; - *(Bit32u *)(write_pixels+4)=colors4_7; - } -public: - VGA_ChainedEGA_Handler() { - flags=PFLAG_NOCODE; - } - void writeb(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED(addr); - MEM_CHANGED( addr << 3); - writeHandler(addr+0,(Bit8u)(val >> 0)); - } - void writew(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED(addr); - MEM_CHANGED( addr << 3); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - } - void writed(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED(addr); - MEM_CHANGED( addr << 3); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - writeHandler(addr+2,(Bit8u)(val >> 16)); - writeHandler(addr+3,(Bit8u)(val >> 24)); - } - Bitu readb(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED(addr); - return readHandler(addr); - } - Bitu readw(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED(addr); - return - (readHandler(addr+0) << 0) | - (readHandler(addr+1) << 8); - } - Bitu readd(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED(addr); - return - (readHandler(addr+0) << 0) | - (readHandler(addr+1) << 8) | - (readHandler(addr+2) << 16) | - (readHandler(addr+3) << 24); - } -}; - -class VGA_UnchainedEGA_Handler : public VGA_UnchainedRead_Handler { -public: - template< bool wrapping> - void writeHandler(PhysPt start, Bit8u val) { - Bit32u data=ModeOperation(val); - /* Update video memory and the pixel buffer */ - VGA_Latch pixels; - pixels.d=((Bit32u*)vga.mem.linear)[start]; - pixels.d&=vga.config.full_not_map_mask; - pixels.d|=(data & vga.config.full_map_mask); - ((Bit32u*)vga.mem.linear)[start]=pixels.d; - Bit8u * write_pixels=&vga.fastmem[start<<3]; - - Bit32u colors0_3, colors4_7; - VGA_Latch temp;temp.d=(pixels.d>>4) & 0x0f0f0f0f; - colors0_3 = - Expand16Table[0][temp.b[0]] | - Expand16Table[1][temp.b[1]] | - Expand16Table[2][temp.b[2]] | - Expand16Table[3][temp.b[3]]; - *(Bit32u *)write_pixels=colors0_3; - temp.d=pixels.d & 0x0f0f0f0f; - colors4_7 = - Expand16Table[0][temp.b[0]] | - Expand16Table[1][temp.b[1]] | - Expand16Table[2][temp.b[2]] | - Expand16Table[3][temp.b[3]]; - *(Bit32u *)(write_pixels+4)=colors4_7; - } -public: - VGA_UnchainedEGA_Handler() { - flags=PFLAG_NOCODE; - } - void writeb(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED2(addr); - MEM_CHANGED( addr << 3); - writeHandler(addr+0,(Bit8u)(val >> 0)); - } - void writew(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED2(addr); - MEM_CHANGED( addr << 3); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - } - void writed(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED2(addr); - MEM_CHANGED( addr << 3); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - writeHandler(addr+2,(Bit8u)(val >> 16)); - writeHandler(addr+3,(Bit8u)(val >> 24)); - } -}; - -//Slighly unusual version, will directly write 8,16,32 bits values -class VGA_ChainedVGA_Handler : public PageHandler { -public: - VGA_ChainedVGA_Handler() { - flags=PFLAG_NOCODE; - } - template - static INLINE Bitu readHandler(PhysPt addr ) { - return hostRead( &vga.mem.linear[((addr&~3)<<2)+(addr&3)] ); - } - template - static INLINE void writeCache(PhysPt addr, Bitu val) { - hostWrite( &vga.fastmem[addr], val ); - if (GCC_UNLIKELY(addr < 320)) { - // And replicate the first line - hostWrite( &vga.fastmem[addr+64*1024], val ); - } - } - template - static INLINE void writeHandler(PhysPt addr, Bitu val) { - // No need to check for compatible chains here, this one is only enabled if that bit is set - hostWrite( &vga.mem.linear[((addr&~3)<<2)+(addr&3)], val ); - } - Bitu readb(PhysPt addr ) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED(addr); - return readHandler( addr ); - } - Bitu readw(PhysPt addr ) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED(addr); - if (GCC_UNLIKELY(addr & 1)) - return - (readHandler( addr+0 ) << 0 ) | - (readHandler( addr+1 ) << 8 ); - else - return readHandler( addr ); - } - Bitu readd(PhysPt addr ) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED(addr); - if (GCC_UNLIKELY(addr & 3)) - return - (readHandler( addr+0 ) << 0 ) | - (readHandler( addr+1 ) << 8 ) | - (readHandler( addr+2 ) << 16 ) | - (readHandler( addr+3 ) << 24 ); - else - return readHandler( addr ); - } - void writeb(PhysPt addr, Bitu val ) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED(addr); - MEM_CHANGED( addr ); - writeHandler( addr, val ); - writeCache( addr, val ); - } - void writew(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED(addr); - MEM_CHANGED( addr ); -// MEM_CHANGED( addr + 1); - if (GCC_UNLIKELY(addr & 1)) { - writeHandler( addr+0, val >> 0 ); - writeHandler( addr+1, val >> 8 ); - } else { - writeHandler( addr, val ); - } - writeCache( addr, val ); - } - void writed(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED(addr); - MEM_CHANGED( addr ); -// MEM_CHANGED( addr + 3); - if (GCC_UNLIKELY(addr & 3)) { - writeHandler( addr+0, val >> 0 ); - writeHandler( addr+1, val >> 8 ); - writeHandler( addr+2, val >> 16 ); - writeHandler( addr+3, val >> 24 ); - } else { - writeHandler( addr, val ); - } - writeCache( addr, val ); - } -}; - -class VGA_UnchainedVGA_Handler : public VGA_UnchainedRead_Handler { -public: - void writeHandler( PhysPt addr, Bit8u val ) { - Bit32u data=ModeOperation(val); - VGA_Latch pixels; - pixels.d=((Bit32u*)vga.mem.linear)[addr]; - pixels.d&=vga.config.full_not_map_mask; - pixels.d|=(data & vga.config.full_map_mask); - ((Bit32u*)vga.mem.linear)[addr]=pixels.d; -// if(vga.config.compatible_chain4) -// ((Bit32u*)vga.mem.linear)[CHECKED2(addr+64*1024)]=pixels.d; - } -public: - VGA_UnchainedVGA_Handler() { - flags=PFLAG_NOCODE; - } - void writeb(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED2(addr); - MEM_CHANGED( addr << 2 ); - writeHandler(addr+0,(Bit8u)(val >> 0)); - } - void writew(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED2(addr); - MEM_CHANGED( addr << 2); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - } - void writed(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED2(addr); - MEM_CHANGED( addr << 2); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - writeHandler(addr+2,(Bit8u)(val >> 16)); - writeHandler(addr+3,(Bit8u)(val >> 24)); - } -}; - -class VGA_TEXT_PageHandler : public PageHandler { -public: - VGA_TEXT_PageHandler() { - flags=PFLAG_NOCODE; - } - Bitu readb(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - return vga.draw.font[addr]; - } - void writeb(PhysPt addr,Bitu val){ - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - if (vga.seq.map_mask & 0x4) { - vga.draw.font[addr]=(Bit8u)val; - } - } -}; - -class VGA_Map_Handler : public PageHandler { -public: - VGA_Map_Handler() { - flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE; - } - HostPt GetHostReadPt(Bitu phys_page) { - phys_page-=vgapages.base; - return &vga.mem.linear[CHECKED3(vga.svga.bank_read_full+phys_page*4096)]; - } - HostPt GetHostWritePt(Bitu phys_page) { - phys_page-=vgapages.base; - return &vga.mem.linear[CHECKED3(vga.svga.bank_write_full+phys_page*4096)]; - } -}; - -class VGA_Changes_Handler : public PageHandler { -public: - VGA_Changes_Handler() { - flags=PFLAG_NOCODE; - } - Bitu readb(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED(addr); - return hostRead( &vga.mem.linear[addr] ); - } - Bitu readw(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED(addr); - return hostRead( &vga.mem.linear[addr] ); - } - Bitu readd(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_read_full; - addr = CHECKED(addr); - return hostRead( &vga.mem.linear[addr] ); - } - void writeb(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED(addr); - MEM_CHANGED( addr ); - hostWrite( &vga.mem.linear[addr], val ); - } - void writew(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED(addr); - MEM_CHANGED( addr ); - hostWrite( &vga.mem.linear[addr], val ); - } - void writed(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) & vgapages.mask; - addr += vga.svga.bank_write_full; - addr = CHECKED(addr); - MEM_CHANGED( addr ); - hostWrite( &vga.mem.linear[addr], val ); - } -}; - -class VGA_LIN4_Handler : public VGA_UnchainedEGA_Handler { -public: - VGA_LIN4_Handler() { - flags=PFLAG_NOCODE; - } - void writeb(PhysPt addr,Bitu val) { - addr = vga.svga.bank_write_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr = CHECKED4(addr); - MEM_CHANGED( addr << 3 ); - writeHandler(addr+0,(Bit8u)(val >> 0)); - } - void writew(PhysPt addr,Bitu val) { - addr = vga.svga.bank_write_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr = CHECKED4(addr); - MEM_CHANGED( addr << 3 ); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - } - void writed(PhysPt addr,Bitu val) { - addr = vga.svga.bank_write_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr = CHECKED4(addr); - MEM_CHANGED( addr << 3 ); - writeHandler(addr+0,(Bit8u)(val >> 0)); - writeHandler(addr+1,(Bit8u)(val >> 8)); - writeHandler(addr+2,(Bit8u)(val >> 16)); - writeHandler(addr+3,(Bit8u)(val >> 24)); - } - Bitu readb(PhysPt addr) { - addr = vga.svga.bank_read_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr = CHECKED4(addr); - return readHandler(addr); - } - Bitu readw(PhysPt addr) { - addr = vga.svga.bank_read_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr = CHECKED4(addr); - return - (readHandler(addr+0) << 0) | - (readHandler(addr+1) << 8); - } - Bitu readd(PhysPt addr) { - addr = vga.svga.bank_read_full + (PAGING_GetPhysicalAddress(addr) & 0xffff); - addr = CHECKED4(addr); - return - (readHandler(addr+0) << 0) | - (readHandler(addr+1) << 8) | - (readHandler(addr+2) << 16) | - (readHandler(addr+3) << 24); - } -}; - - -class VGA_LFBChanges_Handler : public PageHandler { -public: - VGA_LFBChanges_Handler() { - flags=PFLAG_NOCODE; - } - Bitu readb(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - addr = CHECKED(addr); - return hostRead( &vga.mem.linear[addr] ); - } - Bitu readw(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - addr = CHECKED(addr); - return hostRead( &vga.mem.linear[addr] ); - } - Bitu readd(PhysPt addr) { - addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - addr = CHECKED(addr); - return hostRead( &vga.mem.linear[addr] ); - } - void writeb(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - addr = CHECKED(addr); - hostWrite( &vga.mem.linear[addr], val ); - MEM_CHANGED( addr ); - } - void writew(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - addr = CHECKED(addr); - hostWrite( &vga.mem.linear[addr], val ); - MEM_CHANGED( addr ); - } - void writed(PhysPt addr,Bitu val) { - addr = PAGING_GetPhysicalAddress(addr) - vga.lfb.addr; - addr = CHECKED(addr); - hostWrite( &vga.mem.linear[addr], val ); - MEM_CHANGED( addr ); - } -}; - -class VGA_LFB_Handler : public PageHandler { -public: - VGA_LFB_Handler() { - flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE; - } - HostPt GetHostReadPt( Bitu phys_page ) { - phys_page -= vga.lfb.page; - return &vga.mem.linear[CHECKED3(phys_page * 4096)]; - } - HostPt GetHostWritePt( Bitu phys_page ) { - return GetHostReadPt( phys_page ); - } -}; - -extern void XGA_Write(Bitu port, Bitu val, Bitu len); -extern Bitu XGA_Read(Bitu port, Bitu len); - -class VGA_MMIO_Handler : public PageHandler { -public: - VGA_MMIO_Handler() { - flags=PFLAG_NOCODE; - } - void writeb(PhysPt addr,Bitu val) { - Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - XGA_Write(port, val, 1); - } - void writew(PhysPt addr,Bitu val) { - Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - XGA_Write(port, val, 2); - } - void writed(PhysPt addr,Bitu val) { - Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - XGA_Write(port, val, 4); - } - - Bitu readb(PhysPt addr) { - Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - return XGA_Read(port, 1); - } - Bitu readw(PhysPt addr) { - Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - return XGA_Read(port, 2); - } - Bitu readd(PhysPt addr) { - Bitu port = PAGING_GetPhysicalAddress(addr) & 0xffff; - return XGA_Read(port, 4); - } -}; - -class VGA_TANDY_PageHandler : public PageHandler { -public: - VGA_TANDY_PageHandler() { - flags=PFLAG_READABLE|PFLAG_WRITEABLE; -// |PFLAG_NOCODE; - } - HostPt GetHostReadPt(Bitu phys_page) { - if (vga.tandy.mem_bank & 1) - phys_page&=0x03; - else - phys_page&=0x07; - return vga.tandy.mem_base + (phys_page * 4096); - } - HostPt GetHostWritePt(Bitu phys_page) { - return GetHostReadPt( phys_page ); - } -}; - - -class VGA_PCJR_Handler : public PageHandler { -public: - VGA_PCJR_Handler() { - flags=PFLAG_READABLE|PFLAG_WRITEABLE; - } - HostPt GetHostReadPt(Bitu phys_page) { - phys_page-=0xb8; - //test for a unaliged bank, then replicate 2x16kb - if (vga.tandy.mem_bank & 1) - phys_page&=0x03; - return vga.tandy.mem_base + (phys_page * 4096); - } - HostPt GetHostWritePt(Bitu phys_page) { - return GetHostReadPt( phys_page ); - } -}; - -class VGA_Empty_Handler : public PageHandler { -public: - VGA_Empty_Handler() { - flags=PFLAG_NOCODE; - } - Bitu readb(PhysPt /*addr*/) { -// LOG(LOG_VGA, LOG_NORMAL ) ( "Read from empty memory space at %x", addr ); - return 0xff; - } - void writeb(PhysPt /*addr*/,Bitu /*val*/) { -// LOG(LOG_VGA, LOG_NORMAL ) ( "Write %x to empty memory space at %x", val, addr ); - } -}; - -static struct vg { - VGA_Map_Handler map; - VGA_Changes_Handler changes; - VGA_TEXT_PageHandler text; - VGA_TANDY_PageHandler tandy; - VGA_ChainedEGA_Handler cega; - VGA_ChainedVGA_Handler cvga; - VGA_UnchainedEGA_Handler uega; - VGA_UnchainedVGA_Handler uvga; - VGA_PCJR_Handler pcjr; - VGA_LIN4_Handler lin4; - VGA_LFB_Handler lfb; - VGA_LFBChanges_Handler lfbchanges; - VGA_MMIO_Handler mmio; - VGA_Empty_Handler empty; -} vgaph; - -void VGA_ChangedBank(void) { -#ifndef VGA_LFB_MAPPED - //If the mode is accurate than the correct mapper must have been installed already - if ( vga.mode >= M_LIN4 && vga.mode <= M_LIN32 ) { - return; - } -#endif - VGA_SetupHandlers(); -} - -void VGA_SetupHandlers(void) { - vga.svga.bank_read_full = vga.svga.bank_read*vga.svga.bank_size; - vga.svga.bank_write_full = vga.svga.bank_write*vga.svga.bank_size; - - PageHandler *newHandler; - switch (machine) { - case MCH_CGA: - case MCH_PCJR: - MEM_SetPageHandler( VGA_PAGE_B8, 8, &vgaph.pcjr ); - goto range_done; - case MCH_HERC: - vgapages.base=VGA_PAGE_B0; - if (vga.herc.enable_bits & 0x2) { - vgapages.mask=0xffff; - MEM_SetPageHandler(VGA_PAGE_B0,16,&vgaph.map); - } else { - vgapages.mask=0x7fff; - /* With hercules in 32kb mode it leaves a memory hole on 0xb800 */ - MEM_SetPageHandler(VGA_PAGE_B0,8,&vgaph.map); - MEM_SetPageHandler(VGA_PAGE_B8,8,&vgaph.empty); - } - goto range_done; - case MCH_TANDY: - /* Always map 0xa000 - 0xbfff, might overwrite 0xb800 */ - vgapages.base=VGA_PAGE_A0; - vgapages.mask=0x1ffff; - MEM_SetPageHandler(VGA_PAGE_A0, 32, &vgaph.map ); - if ( vga.tandy.extended_ram & 1 ) { - //You seem to be able to also map different 64kb banks, but have to figure that out - //This seems to work so far though - vga.tandy.draw_base = vga.mem.linear; - vga.tandy.mem_base = vga.mem.linear; - } else { - vga.tandy.draw_base = TANDY_VIDBASE( vga.tandy.draw_bank * 16 * 1024); - vga.tandy.mem_base = TANDY_VIDBASE( vga.tandy.mem_bank * 16 * 1024); - MEM_SetPageHandler( 0xb8, 8, &vgaph.tandy ); - } - goto range_done; -// MEM_SetPageHandler(vga.tandy.mem_bank<<2,vga.tandy.is_32k_mode ? 0x08 : 0x04,range_handler); - case EGAVGA_ARCH_CASE: - break; - default: - LOG_MSG("Illegal machine type %d", machine ); - return; - } - - /* This should be vga only */ - switch (vga.mode) { - case M_ERROR: - default: - return; - case M_LIN4: - newHandler = &vgaph.lin4; - break; - case M_LIN15: - case M_LIN16: - case M_LIN32: -#ifdef VGA_LFB_MAPPED - newHandler = &vgaph.map; -#else - newHandler = &vgaph.changes; -#endif - break; - case M_LIN8: - case M_VGA: - if (vga.config.chained) { - if(vga.config.compatible_chain4) - newHandler = &vgaph.cvga; - else -#ifdef VGA_LFB_MAPPED - newHandler = &vgaph.map; -#else - newHandler = &vgaph.changes; -#endif - } else { - newHandler = &vgaph.uvga; - } - break; - case M_EGA: - if (vga.config.chained) - newHandler = &vgaph.cega; - else - newHandler = &vgaph.uega; - break; - case M_TEXT: - /* Check if we're not in odd/even mode */ - if (vga.gfx.miscellaneous & 0x2) newHandler = &vgaph.map; - else newHandler = &vgaph.text; - break; - case M_CGA4: - case M_CGA2: - newHandler = &vgaph.map; - break; - } - switch ((vga.gfx.miscellaneous >> 2) & 3) { - case 0: - vgapages.base = VGA_PAGE_A0; - switch (svgaCard) { - case SVGA_TsengET3K: - case SVGA_TsengET4K: - vgapages.mask = 0xffff; - break; - case SVGA_S3Trio: - default: - vgapages.mask = 0x1ffff; - break; - } - MEM_SetPageHandler(VGA_PAGE_A0, 32, newHandler ); - break; - case 1: - vgapages.base = VGA_PAGE_A0; - vgapages.mask = 0xffff; - MEM_SetPageHandler( VGA_PAGE_A0, 16, newHandler ); - MEM_ResetPageHandler( VGA_PAGE_B0, 16); - break; - case 2: - vgapages.base = VGA_PAGE_B0; - vgapages.mask = 0x7fff; - MEM_SetPageHandler( VGA_PAGE_B0, 8, newHandler ); - MEM_ResetPageHandler( VGA_PAGE_A0, 16 ); - MEM_ResetPageHandler( VGA_PAGE_B8, 8 ); - break; - case 3: - vgapages.base = VGA_PAGE_B8; - vgapages.mask = 0x7fff; - MEM_SetPageHandler( VGA_PAGE_B8, 8, newHandler ); - MEM_ResetPageHandler( VGA_PAGE_A0, 16 ); - MEM_ResetPageHandler( VGA_PAGE_B0, 8 ); - break; - } - if(svgaCard == SVGA_S3Trio && (vga.s3.ext_mem_ctrl & 0x10)) - MEM_SetPageHandler(VGA_PAGE_A0, 16, &vgaph.mmio); -range_done: - PAGING_ClearTLB(); -} - -void VGA_StartUpdateLFB(void) { - vga.lfb.page = vga.s3.la_window << 4; - vga.lfb.addr = vga.s3.la_window << 16; -#ifdef VGA_LFB_MAPPED - vga.lfb.handler = &vgaph.lfb; -#else - vga.lfb.handler = &vgaph.lfbchanges; -#endif - MEM_SetLFB(vga.s3.la_window << 4 ,vga.vmemsize/4096, vga.lfb.handler, &vgaph.mmio); -} - -static void VGA_Memory_ShutDown(Section * /*sec*/) { - delete[] vga.mem.linear_orgptr; - delete[] vga.fastmem_orgptr; -#ifdef VGA_KEEP_CHANGES - delete[] vga.changes.map; -#endif -} - -void VGA_SetupMemory(Section* sec) { - vga.svga.bank_read = vga.svga.bank_write = 0; - vga.svga.bank_read_full = vga.svga.bank_write_full = 0; - - Bit32u vga_allocsize=vga.vmemsize; - // Keep lower limit at 512k - if (vga_allocsize<512*1024) vga_allocsize=512*1024; - // We reserve extra 2K for one scan line - vga_allocsize+=2048; - vga.mem.linear_orgptr = new Bit8u[vga_allocsize+16]; - vga.mem.linear=(Bit8u*)(((Bitu)vga.mem.linear_orgptr + 16-1) & ~(16-1)); - memset(vga.mem.linear,0,vga_allocsize); - - vga.fastmem_orgptr = new Bit8u[(vga.vmemsize<<1)+4096+16]; - vga.fastmem=(Bit8u*)(((Bitu)vga.fastmem_orgptr + 16-1) & ~(16-1)); - - // In most cases these values stay the same. Assumptions: vmemwrap is power of 2, - // vmemwrap <= vmemsize, fastmem implicitly has mem wrap twice as big - vga.vmemwrap = vga.vmemsize; - -#ifdef VGA_KEEP_CHANGES - memset( &vga.changes, 0, sizeof( vga.changes )); - int changesMapSize = (vga.vmemsize >> VGA_CHANGE_SHIFT) + 32; - vga.changes.map = new Bit8u[changesMapSize]; - memset(vga.changes.map, 0, changesMapSize); -#endif - vga.svga.bank_read = vga.svga.bank_write = 0; - vga.svga.bank_read_full = vga.svga.bank_write_full = 0; - vga.svga.bank_size = 0x10000; /* most common bank size is 64K */ - - sec->AddDestroyFunction(&VGA_Memory_ShutDown); - - if (machine==MCH_PCJR) { - /* PCJr does not have dedicated graphics memory but uses - conventional memory below 128k */ - //TODO map? - } -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + + + +#include +#include +#include "dosbox.h" +#include "mem.h" +#include "vga.h" + + +Bit8u VGA_ChainedReadHandler(Bit32u start) { + return vga.mem.linear[start]; +} + +void VGA_ChainedWriteHandler(Bit32u start,Bit8u val) { + vga.mem.linear[start]=val; +}; + + +Bit8u VGA_NormalReadHandler(Bit32u start) { + vga.latch.d=vga.mem.latched[start].d; + switch (vga.config.read_mode) { + case 0: + return(vga.latch.b[vga.config.read_map_select]); + case 1: + VGA_Latch templatch; + templatch.d=(vga.latch.d & FillTable[vga.config.color_dont_care]) ^ FillTable[vga.config.color_compare & vga.config.color_dont_care]; + return ~(templatch.b[0] | templatch.b[1] | templatch.b[2] | templatch.b[3]); + } + return 0; +} + +//Nice one from DosEmu +INLINE Bit32u RasterOp(Bit32u input,Bit32u mask) { + switch (vga.config.raster_op) { + case 0x00: /* None */ + return (input & mask) | (vga.latch.d & ~mask); + case 0x01: /* AND */ + return (input | ~mask) & vga.latch.d; + case 0x02: /* OR */ + return (input & mask) | vga.latch.d; + case 0x03: /* XOR */ + return (input & mask) ^ vga.latch.d; + }; + return 0; +} + +Bit8u VGA_GFX_4_ReadHandler(Bit32u start) { + return vga.mem.linear[start]; +} + +void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val) { + vga.mem.linear[start]=val; + Bitu line=start / 320; + Bitu x=start % 320; + Bit8u * draw=&vga.buffer[start<<2]; + /* TODO Could also use a Bit32u lookup table for this */ + *(draw+0)=(val>>6)&3; + *(draw+1)=(val>>4)&3; + *(draw+2)=(val>>2)&3; + *(draw+3)=(val)&3; +} + +void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val) { + VGA_Latch new_latch; + Bitu bit_mask; + switch (vga.config.write_mode) { + case 0x00: + // Write Mode 0: In this mode, the host data is first rotated as per the Rotate Count field, then the Enable Set/Reset mechanism selects data from this or the Set/Reset field. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. +// val=(val >> vga.config.data_rotate) | (val << (8-vga.config.data_rotate)); + //Todo could also include the rotation in the table :) + new_latch.d=ExpandTable[val]; + { + Bit32u resetmask=FillTable[vga.config.enable_set_reset]; + new_latch.d=(new_latch.d & ~resetmask) | ( FillTable[vga.config.set_reset] & resetmask); + }; + new_latch.d=RasterOp(new_latch.d,vga.config.full_bit_mask); + bit_mask=vga.gfx.bit_mask; + break; + case 0x01: + // Write Mode 1: In this mode, data is transferred directly from the 32 bit latch register to display memory, affected only by the Memory Plane Write Enable field. The host data is not used in this mode. + new_latch.d=vga.latch.d; + bit_mask=0xff; + break; + case 0x02: + //Write Mode 2: In this mode, the bits 3-0 of the host data are replicated across all 8 bits of their respective planes. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. + new_latch.d=RasterOp(FillTable[val&0xF],vga.config.full_bit_mask); + bit_mask=vga.gfx.bit_mask; + break; + case 0x03: + // Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. + new_latch.d=ExpandTable[val]; + new_latch.d&=vga.config.full_bit_mask; //Dunno would anyone use this seems a bit pointless + bit_mask=new_latch.b[0]; + new_latch.d=RasterOp(FillTable[vga.config.set_reset],new_latch.d); + break; + default: + LOG_ERROR("VGA:Unsupported write mode %d",vga.config.write_mode); + } + /* Update video memory and the pixel buffer */ + VGA_Latch pixels; + pixels.d=vga.mem.latched[start].d; + pixels.d&=~vga.config.full_map_mask; + pixels.d|=(new_latch.d & vga.config.full_map_mask); + vga.mem.latched[start].d=pixels.d; + Bit8u * write_pixels=&vga.buffer[start<<3]; +#if 1 + Bit8u sel=128; + do { + if (bit_mask & sel) { + Bitu color; + color=0; + if (pixels.b[0] & sel) color|=1; + if (pixels.b[1] & sel) color|=2; + if (pixels.b[2] & sel) color|=4; + if (pixels.b[3] & sel) color|=8; + *write_pixels=color; + *(write_pixels+512*1024)=color; + + } + write_pixels++; + sel>>=1; + } while (sel); +#else +#include "ega-switch.h" +#endif + +} + + + + +void VGA_GFX_256U_WriteHandler(Bit32u start,Bit8u val) { + VGA_Latch new_latch; + switch (vga.config.write_mode) { + case 0x00: + /* This should be no problem with big or little endian */ + // Write Mode 0: In this mode, the host data is first rotated as per the Rotate Count field, then the Enable Set/Reset mechanism selects data from this or the Set/Reset field. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. +// val=(val >> vga.config.data_rotate) | (val << (8-vga.config.data_rotate)); + //Todo could also include the rotation in the table :) + new_latch.d=ExpandTable[val]; + { + Bit32u resetmask=FillTable[vga.config.enable_set_reset]; + new_latch.d=(new_latch.d & ~resetmask) | ( FillTable[vga.config.set_reset] & resetmask); + }; + new_latch.d=RasterOp(new_latch.d,vga.config.full_bit_mask); + break; + case 0x01: + // Write Mode 1: In this mode, data is transferred directly from the 32 bit latch register to display memory, affected only by the Memory Plane Write Enable field. The host data is not used in this mode. + new_latch.d=vga.latch.d; + break; + case 0x02: + //TODO this mode also has Raster op + //Write Mode 2: In this mode, the bits 3-0 of the host data are replicated across all 8 bits of their respective planes. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. + new_latch.d=RasterOp(FillTable[val&0xF],vga.config.full_bit_mask); + break; + case 0x03: + // Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. + new_latch.d=ExpandTable[val]; + new_latch.d&=vga.config.full_bit_mask; //Dunno would anyone use this seems a bit pointless + new_latch.d=RasterOp(FillTable[vga.config.set_reset],new_latch.d); + break; + default: + E_Exit("VGA:Unsupported write mode %d",vga.config.write_mode); + } + VGA_Latch pixels; + pixels.d=vga.mem.latched[start].d; + pixels.d&=~vga.config.full_map_mask; + pixels.d|=(new_latch.d & vga.config.full_map_mask); + vga.mem.latched[start].d=pixels.d; + vga.mem.latched[start+64*1024].d=pixels.d; + +}; + + + + + + + + + + + + + + + + +void VGA_SetupMemory() { + memset((void *)&vga.mem,0,256*1024); + /* Alocate Video Memory */ + /* Not needed for VGA memory it gets allocated together with emulator maybe + later for VESA memory */ + +} diff --git a/src/hardware/vga_misc.cpp b/src/hardware/vga_misc.cpp index 3a802f2..c1d6f19 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_misc.cpp @@ -1,155 +1,70 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_misc.cpp,v 1.39 2009/01/25 12:00:49 c2woody Exp $ */ - -#include "dosbox.h" -#include "inout.h" -#include "pic.h" -#include "vga.h" -#include - - -void vga_write_p3d4(Bitu port,Bitu val,Bitu iolen); -Bitu vga_read_p3d4(Bitu port,Bitu iolen); -void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen); -Bitu vga_read_p3d5(Bitu port,Bitu iolen); - -Bitu vga_read_p3da(Bitu port,Bitu iolen) { - Bit8u retval=0; - double timeInFrame = PIC_FullIndex()-vga.draw.delay.framestart; - - vga.internal.attrindex=false; - vga.tandy.pcjr_flipflop=false; - - // 3DAh (R): Status Register - // bit 0 Horizontal or Vertical blanking - // 3 Vertical sync - - if (timeInFrame >= vga.draw.delay.vrstart && - timeInFrame <= vga.draw.delay.vrend) - retval |= 8; - if (timeInFrame >= vga.draw.delay.vdend) { - retval |= 1; - } else { - double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal); - if (timeInLine >= vga.draw.delay.hblkstart && - timeInLine <= vga.draw.delay.hblkend) { - retval |= 1; - } - } - return retval; -} - -static void write_p3c2(Bitu port,Bitu val,Bitu iolen) { - vga.misc_output=val; - if (val & 0x1) { - IO_RegisterWriteHandler(0x3d4,vga_write_p3d4,IO_MB); - IO_RegisterReadHandler(0x3d4,vga_read_p3d4,IO_MB); - IO_RegisterReadHandler(0x3da,vga_read_p3da,IO_MB); - - IO_RegisterWriteHandler(0x3d5,vga_write_p3d5,IO_MB); - IO_RegisterReadHandler(0x3d5,vga_read_p3d5,IO_MB); - - IO_FreeWriteHandler(0x3b4,IO_MB); - IO_FreeReadHandler(0x3b4,IO_MB); - IO_FreeWriteHandler(0x3b5,IO_MB); - IO_FreeReadHandler(0x3b5,IO_MB); - IO_FreeReadHandler(0x3ba,IO_MB); - } else { - IO_RegisterWriteHandler(0x3b4,vga_write_p3d4,IO_MB); - IO_RegisterReadHandler(0x3b4,vga_read_p3d4,IO_MB); - IO_RegisterReadHandler(0x3ba,vga_read_p3da,IO_MB); - - IO_RegisterWriteHandler(0x3b5,vga_write_p3d5,IO_MB); - IO_RegisterReadHandler(0x3b5,vga_read_p3d5,IO_MB); - - - IO_FreeWriteHandler(0x3d4,IO_MB); - IO_FreeReadHandler(0x3d4,IO_MB); - IO_FreeWriteHandler(0x3d5,IO_MB); - IO_FreeReadHandler(0x3d5,IO_MB); - IO_FreeReadHandler(0x3da,IO_MB); - } - /* - 0 If set Color Emulation. Base Address=3Dxh else Mono Emulation. Base Address=3Bxh. - 2-3 Clock Select. 0: 25MHz, 1: 28MHz - 5 When in Odd/Even modes Select High 64k bank if set - 6 Horizontal Sync Polarity. Negative if set - 7 Vertical Sync Polarity. Negative if set - Bit 6-7 indicates the number of lines on the display: - 1: 400, 2: 350, 3: 480 - Note: Set to all zero on a hardware reset. - Note: This register can be read from port 3CCh. - */ -} - - -static Bitu read_p3cc(Bitu port,Bitu iolen) { - return vga.misc_output; -} - -// VGA feature control register -static Bitu read_p3ca(Bitu port,Bitu iolen) { - return 0; -} - -static Bitu read_p3c8(Bitu port,Bitu iolen) { - return 0x10; -} - -static Bitu read_p3c2(Bitu port,Bitu iolen) { - Bit8u retval=0; - - if (machine==MCH_EGA) retval = 0x0F; - else if (IS_VGA_ARCH) retval = 0x60; - if ((machine==MCH_VGA) || (((vga.misc_output>>2)&3)==0) || (((vga.misc_output>>2)&3)==3)) { - retval |= 0x10; - } - - if (vga.draw.vret_triggered) retval |= 0x80; - return retval; - /* - 0-3 0xF on EGA, 0x0 on VGA - 4 Status of the switch selected by the Miscellaneous Output - Register 3C2h bit 2-3. Switch high if set. - (apparently always 1 on VGA) - 5 (EGA) Pin 19 of the Feature Connector (FEAT0) is high if set - 6 (EGA) Pin 17 of the Feature Connector (FEAT1) is high if set - (default differs by card, ET4000 sets them both) - 7 If set IRQ 2 has happened due to Vertical Retrace. - Should be cleared by IRQ 2 interrupt routine by clearing port 3d4h - index 11h bit 4. - */ -} - -void VGA_SetupMisc(void) { - if (IS_EGAVGA_ARCH) { - vga.draw.vret_triggered=false; - IO_RegisterReadHandler(0x3c2,read_p3c2,IO_MB); - IO_RegisterWriteHandler(0x3c2,write_p3c2,IO_MB); - if (IS_VGA_ARCH) { - IO_RegisterReadHandler(0x3ca,read_p3ca,IO_MB); - IO_RegisterReadHandler(0x3cc,read_p3cc,IO_MB); - } else { - IO_RegisterReadHandler(0x3c8,read_p3c8,IO_MB); - } - } else if (machine==MCH_CGA || IS_TANDY_ARCH) { - IO_RegisterReadHandler(0x3da,vga_read_p3da,IO_MB); - } -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "inout.h" +#include "timer.h" +#include "vga.h" + +static Bit8u flip=0; +static Bit32u keep_vretrace; +static bool keeping=false; +static Bit8u p3c2data; + +static Bit8u read_p3da(Bit32u port) { + vga.internal.attrindex=false; + if (vga.config.retrace) { + vga.config.retrace=false; + vga.config.real_start=vga.config.display_start; + keep_vretrace=LastTicks+1; + keeping=true; + flip=0; + return 9; + } + if (keeping) { + if (LastTicks>(keep_vretrace)) keeping=false; + return 9; + } else { + flip++; + if (flip>10) flip=0; + if (flip>5) return 1; + return 0; + } +}; + + +static void write_p3d8(Bit32u port,Bit8u val) { + return; +} + +static void write_p3c2(Bit32u port,Bit8u val) { + p3c2data=val; +} +static Bit8u read_p3c2(Bit32u port) { + return p3c2data; +} + + +void VGA_SetupMisc(void) { + IO_RegisterReadHandler(0x3da,read_p3da,"VGA Input Status 1"); +// IO_RegisterWriteHandler(0x3d8,write_p3d8,"VGA Mode Control"); + IO_RegisterWriteHandler(0x3c2,write_p3c2,"VGA Misc Output"); + IO_RegisterReadHandler(0x3c2,read_p3c2,"VGA Misc Output"); +} + + diff --git a/src/hardware/vga_other.cpp b/src/hardware/vga_other.cpp deleted file mode 100644 index df85d12..0000000 --- a/src/hardware/vga_other.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_other.cpp,v 1.25 2009/01/25 12:00:51 c2woody Exp $ */ - -#include -#include -#include "dosbox.h" -#include "inout.h" -#include "vga.h" -#include "mem.h" -#include "pic.h" -#include "render.h" -#include "mapper.h" - -static void write_crtc_index_other(Bitu port,Bitu val,Bitu iolen) { - vga.other.index=val; -} - -static Bitu read_crtc_index_other(Bitu port,Bitu iolen) { - return vga.other.index; -} - -static void write_crtc_data_other(Bitu port,Bitu val,Bitu iolen) { - switch (vga.other.index) { - case 0x00: //Horizontal total - if (vga.other.htotal ^ val) VGA_StartResize(); - vga.other.htotal=val; - break; - case 0x01: //Horizontal displayed chars - if (vga.other.hdend ^ val) VGA_StartResize(); - vga.other.hdend=val; - break; - case 0x02: //Horizontal sync position - vga.other.hsyncp=val; - break; - case 0x03: //Horizontal and vertical sync width - vga.other.syncw=val; - break; - case 0x04: //Vertical total - if (vga.other.vtotal ^ val) VGA_StartResize(); - vga.other.vtotal=val; - break; - case 0x05: //Vertical display adjust - if (vga.other.vadjust ^ val) VGA_StartResize(); - vga.other.vadjust=val; - break; - case 0x06: //Vertical rows - if (vga.other.vdend ^ val) VGA_StartResize(); - vga.other.vdend=val; - break; - case 0x07: //Vertical sync position - vga.other.vsyncp=val; - break; - case 0x09: //Max scanline - if (vga.other.max_scanline ^ val) VGA_StartResize(); - vga.other.max_scanline=val; - break; - case 0x0A: /* Cursor Start Register */ - vga.other.cursor_start = val & 0x3f; - vga.draw.cursor.sline = val&0x1f; - vga.draw.cursor.enabled = ((val & 0x60) != 0x20); - break; - case 0x0B: /* Cursor End Register */ - vga.other.cursor_end = val&0x1f; - vga.draw.cursor.eline = val&0x1f; - break; - case 0x0C: /* Start Address High Register */ - vga.config.display_start=(vga.config.display_start & 0x00FF) | (val << 8); - break; - case 0x0D: /* Start Address Low Register */ - vga.config.display_start=(vga.config.display_start & 0xFF00) | val; - break; - case 0x0E: /*Cursor Location High Register */ - vga.config.cursor_start&=0x00ff; - vga.config.cursor_start|=val << 8; - break; - case 0x0F: /* Cursor Location Low Register */ - vga.config.cursor_start&=0xff00; - vga.config.cursor_start|=val; - break; - case 0x10: /* Light Pen High */ - vga.other.lpen_high = val & 0x1f; //only 6 bits - break; - case 0x11: /* Light Pen Low */ - vga.other.lpen_low = val; - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("MC6845:Write %X to illegal index %x",val,vga.other.index); - } -} -static Bitu read_crtc_data_other(Bitu port,Bitu iolen) { - switch (vga.other.index) { - case 0x00: //Horizontal total - return vga.other.htotal; - case 0x01: //Horizontal displayed chars - return vga.other.hdend; - case 0x02: //Horizontal sync position - return vga.other.hsyncp; - case 0x03: //Horizontal and vertical sync width - return vga.other.syncw; - case 0x04: //Vertical total - return vga.other.vtotal; - case 0x05: //Vertical display adjust - return vga.other.vadjust; - case 0x06: //Vertical rows - return vga.other.vdend; - case 0x07: //Vertical sync position - return vga.other.vsyncp; - case 0x09: //Max scanline - return vga.other.max_scanline; - case 0x0A: /* Cursor Start Register */ - return vga.other.cursor_start; - case 0x0B: /* Cursor End Register */ - return vga.other.cursor_end; - case 0x0C: /* Start Address High Register */ - return vga.config.display_start >> 8; - case 0x0D: /* Start Address Low Register */ - return vga.config.display_start; - case 0x0E: /*Cursor Location High Register */ - return vga.config.cursor_start>>8; - case 0x0F: /* Cursor Location Low Register */ - return vga.config.cursor_start; - case 0x10: /* Light Pen High */ - return vga.other.lpen_high; - case 0x11: /* Light Pen Low */ - return vga.other.lpen_low; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("MC6845:Read from illegal index %x",vga.other.index); - } - return ~0; -} - -static double hue_offset = 0.0; -static Bit8u cga16_val = 0; -static void update_cga16_color(void); - -static void cga16_color_select(Bit8u val) { - cga16_val = val; - update_cga16_color(); -} - -static void update_cga16_color(void) { -// Algorithm provided by NewRisingSun -// His/Her algorithm is more complex and gives better results than the one below -// However that algorithm doesn't fit in our vga pallette. -// Therefore a simple variant is used, but the colours are bit lighter. - -// It uses an avarage over the bits to give smooth transitions from colour to colour -// This is represented by the j variable. The i variable gives the 16 colours -// The draw handler calculates the needed avarage and combines this with the colour -// to match an entry that is generated here. - - int baseR=0, baseG=0, baseB=0; - double sinhue,coshue,hue,basehue = 50.0; - double I,Q,Y,pixelI,pixelQ,R,G,B; - Bitu colorBit1,colorBit2,colorBit3,colorBit4,index; - - if (cga16_val & 0x01) baseB += 0xa8; - if (cga16_val & 0x02) baseG += 0xa8; - if (cga16_val & 0x04) baseR += 0xa8; - if (cga16_val & 0x08) { baseR += 0x57; baseG += 0x57; baseB += 0x57; } - if (cga16_val & 0x20) basehue = 35.0; - - hue = (basehue + hue_offset)*0.017453239; - sinhue = sin(hue); - coshue = cos(hue); - - for(Bitu i = 0; i < 16;i++) { - for(Bitu j = 0;j < 5;j++) { - index = 0x80|(j << 4)|i; //use upperpart of vga pallette - colorBit4 = (i&1)>>0; - colorBit3 = (i&2)>>1; - colorBit2 = (i&4)>>2; - colorBit1 = (i&8)>>3; - - //calculate lookup table - I = 0; Q = 0; - I += (double) colorBit1; - Q += (double) colorBit2; - I -= (double) colorBit3; - Q -= (double) colorBit4; - Y = (double) j / 4.0; //calculated avarage is over 4 bits - - pixelI = I * 1.0 / 3.0; //I* tvSaturnation / 3.0 - pixelQ = Q * 1.0 / 3.0; //Q* tvSaturnation / 3.0 - I = pixelI*coshue + pixelQ*sinhue; - Q = pixelQ*coshue - pixelI*sinhue; - - R = Y + 0.956*I + 0.621*Q; if (R < 0.0) R = 0.0; if (R > 1.0) R = 1.0; - G = Y - 0.272*I - 0.647*Q; if (G < 0.0) G = 0.0; if (G > 1.0) G = 1.0; - B = Y - 1.105*I + 1.702*Q; if (B < 0.0) B = 0.0; if (B > 1.0) B = 1.0; - - RENDER_SetPal(index,static_cast(R*baseR),static_cast(G*baseG),static_cast(B*baseB)); - } - } -} - -static void IncreaseHue(bool pressed) { - if (!pressed) - return; - hue_offset += 5.0; - update_cga16_color(); - LOG_MSG("Hue at %f",hue_offset); -} - -static void DecreaseHue(bool pressed) { - if (!pressed) - return; - hue_offset -= 5.0; - update_cga16_color(); - LOG_MSG("Hue at %f",hue_offset); -} - -static void write_color_select(Bit8u val) { - vga.tandy.color_select=val; - switch (vga.mode) { - case M_TANDY2: - VGA_SetCGA2Table(0,val & 0xf); - break; - case M_TANDY4: - { - if ((machine==MCH_TANDY && (vga.tandy.gfx_control & 0x8)) || - (machine==MCH_PCJR && (vga.tandy.mode_control==0x0b))) { - VGA_SetCGA4Table(0,1,2,3); - return; - } - Bit8u base=(val & 0x10) ? 0x08 : 0; - /* Check for BW Mode */ - if (vga.tandy.mode_control & 0x4) { - VGA_SetCGA4Table(val & 0xf,3+base,4+base,7+base); - } else { - if (val & 0x20) VGA_SetCGA4Table(val & 0xf,3+base,5+base,7+base); - else VGA_SetCGA4Table(val & 0xf,2+base,4+base,6+base); - } - } - break; - case M_CGA16: - cga16_color_select(val); - break; - case M_TEXT: - case M_TANDY16: - break; - } -} - -static void TANDY_FindMode(void) { - if (vga.tandy.mode_control & 0x2) { - if (vga.tandy.gfx_control & 0x10) - VGA_SetMode(M_TANDY16); - else if (vga.tandy.gfx_control & 0x08) - VGA_SetMode(M_TANDY4); - else if (vga.tandy.mode_control & 0x10) - VGA_SetMode(M_TANDY2); - else - VGA_SetMode(M_TANDY4); - write_color_select(vga.tandy.color_select); - } else { - VGA_SetMode(M_TANDY_TEXT); - } -} - -static void PCJr_FindMode(void) { - if (vga.tandy.mode_control & 0x2) { - if (vga.tandy.mode_control & 0x10) { - /* bit4 of mode control 1 signals 16 colour graphics mode */ - VGA_SetMode(M_TANDY16); - } else if (vga.tandy.gfx_control & 0x08) { - /* bit3 of mode control 2 signals 2 colour graphics mode */ - VGA_SetMode(M_TANDY2); - } else { - /* otherwise some 4-colour graphics mode */ - VGA_SetMode(M_TANDY4); - } - write_color_select(vga.tandy.color_select); - } else { - VGA_SetMode(M_TANDY_TEXT); - } -} - -static void TandyCheckLineMask(void ) { - if ( vga.tandy.extended_ram & 1 ) { - vga.tandy.line_mask = 0; - } else if ( vga.tandy.mode_control & 0x2) { - vga.tandy.line_mask |= 1; - } - if ( vga.tandy.line_mask ) { - vga.tandy.line_shift = 13; - vga.tandy.addr_mask = (1 << 13) - 1; - } else { - vga.tandy.addr_mask = ~0; - vga.tandy.line_shift = 0; - } -} - -static void write_tandy_reg(Bit8u val) { - switch (vga.tandy.reg_index) { - case 0x0: - if (machine==MCH_PCJR) { - vga.tandy.mode_control=val; - VGA_SetBlinking(val & 0x20); - PCJr_FindMode(); - } else { - LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index); - } - break; - case 0x2: /* Border color */ - vga.tandy.border_color=val; - break; - case 0x3: /* More control */ - vga.tandy.gfx_control=val; - if (machine==MCH_TANDY) TANDY_FindMode(); - else PCJr_FindMode(); - break; - case 0x5: /* Extended ram page register */ - // Bit 0 enables extended ram - // Bit 7 Switches clock, 0 -> cga 28.6 , 1 -> mono 32.5 - vga.tandy.extended_ram = val; - //This is a bit of a hack to enable mapping video memory differently for highres mode - TandyCheckLineMask(); - VGA_SetupHandlers(); - break; - case 0x8: /* Monitor mode seletion */ - //Bit 1 select mode e, for 640x200x16, some double clocking thing? - //Bit 4 select 350 line mode for hercules emulation - LOG(LOG_VGAMISC,LOG_NORMAL)("Write %2X to tandy monitor mode",val ); - break; - /* palette colors */ - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x14: case 0x15: case 0x16: case 0x17: - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x1c: case 0x1d: case 0x1e: case 0x1f: - VGA_ATTR_SetPalette(vga.tandy.reg_index-0x10,val & 0xf); - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index); - } -} - -static void write_cga(Bitu port,Bitu val,Bitu iolen) { - switch (port) { - case 0x3d8: - vga.tandy.mode_control=val; - if (vga.tandy.mode_control & 0x2) { - if (vga.tandy.mode_control & 0x10) { - if (!(val & 0x4) && machine==MCH_CGA) { - VGA_SetMode(M_CGA16); //Video burst 16 160x200 color mode - } else { - VGA_SetMode(M_TANDY2); - } - } else VGA_SetMode(M_TANDY4); - write_color_select(vga.tandy.color_select); - } else { - VGA_SetMode(M_TANDY_TEXT); - } - VGA_SetBlinking(val & 0x20); - break; - case 0x3d9: - write_color_select(val); - break; - } -} - -static void write_tandy(Bitu port,Bitu val,Bitu iolen) { - switch (port) { - case 0x3d8: - vga.tandy.mode_control=val; - TandyCheckLineMask(); - VGA_SetBlinking(val & 0x20); - TANDY_FindMode(); - break; - case 0x3d9: - write_color_select(val); - break; - case 0x3da: - vga.tandy.reg_index=val; - break; -// case 0x3db: //Clear lightpen latch - break; -// case 0x3dc: //Preset lightpen latch - break; -// case 0x3dd: //Extended ram page address register: - break; - case 0x3de: - write_tandy_reg(val); - break; - case 0x3df: - vga.tandy.line_mask = val >> 6; - vga.tandy.draw_bank = val & ((vga.tandy.line_mask&2) ? 0x6 : 0x7); - vga.tandy.mem_bank = (val >> 3) & ((vga.tandy.line_mask&2) ? 0x6 : 0x7); - TandyCheckLineMask(); - VGA_SetupHandlers(); - break; - } -} - -static void write_pcjr(Bitu port,Bitu val,Bitu iolen) { - switch (port) { - case 0x3d9: - write_color_select(val); - break; - case 0x3da: - if (vga.tandy.pcjr_flipflop) write_tandy_reg(val); - else vga.tandy.reg_index=val; - vga.tandy.pcjr_flipflop=!vga.tandy.pcjr_flipflop; - break; - case 0x3df: - vga.tandy.line_mask = val >> 6; - vga.tandy.draw_bank = val & ((vga.tandy.line_mask&2) ? 0x6 : 0x7); - vga.tandy.mem_bank = (val >> 3) & ((vga.tandy.line_mask&2) ? 0x6 : 0x7); - vga.tandy.draw_base = &MemBase[vga.tandy.draw_bank * 16 * 1024]; - vga.tandy.mem_base = &MemBase[vga.tandy.mem_bank * 16 * 1024]; - TandyCheckLineMask(); - VGA_SetupHandlers(); - break; - } -} - -static void write_hercules(Bitu port,Bitu val,Bitu iolen) { - switch (port) { - case 0x3b8: { - // the protected bits can always be cleared but only be set if the - // protection bits are set - if (vga.herc.mode_control&0x2) { - // already set - if (!(val&0x2)) { - vga.herc.mode_control &= ~0x2; - VGA_SetMode(M_HERC_TEXT); - } - } else { - // not set, can only set if protection bit is set - if ((val & 0x2) && (vga.herc.enable_bits & 0x1)) { - vga.herc.mode_control |= 0x2; - VGA_SetMode(M_HERC_GFX); - } - } - if (vga.herc.mode_control&0x80) { - if (!(val&0x80)) { - vga.herc.mode_control &= ~0x80; - vga.tandy.draw_base = &vga.mem.linear[0]; - } - } else { - if ((val & 0x80) && (vga.herc.enable_bits & 0x2)) { - vga.herc.mode_control |= 0x80; - vga.tandy.draw_base = &vga.mem.linear[32*1024]; - } - } - vga.draw.blinking = (val&0x20)!=0; - vga.herc.mode_control &= 0x82; - vga.herc.mode_control |= val & ~0x82; - break; - } - case 0x3bf: - vga.herc.enable_bits=val; - break; - } -} - -/* static Bitu read_hercules(Bitu port,Bitu iolen) { - LOG_MSG("read from Herc port %x",port); - return 0; -} */ - -Bitu read_herc_status(Bitu port,Bitu iolen) { - // 3BAh (R): Status Register - // bit 0 Horizontal sync - // 1 Light pen status (only some cards) - // 3 Video signal - // 4-6 000: Hercules - // 001: Hercules Plus - // 101: Hercules InColor - // 111: Unknown clone - // 7 Vertical sync inverted - - double timeInFrame = PIC_FullIndex()-vga.draw.delay.framestart; - Bit8u retval=0x72; // Hercules ident; from a working card (Winbond W86855AF) - // Another known working card has 0x76 ("KeysoGood", full-length) - if (timeInFrame < vga.draw.delay.vrstart || - timeInFrame > vga.draw.delay.vrend) retval |= 0x80; - - double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal); - if (timeInLine >= vga.draw.delay.hrstart && - timeInLine <= vga.draw.delay.hrend) retval |= 0x1; - - // 688 Attack sub checks bit 3 - as a workaround have the bit enabled - // if no sync active (corresponds to a completely white screen) - if ((retval&0x81)==0x80) retval |= 0x8; - return retval; -} - - -void VGA_SetupOther(void) { - Bitu i; - memset( &vga.tandy, 0, sizeof( vga.tandy )); - //Initialize values common for most machines, can be overwritten - vga.tandy.draw_base = vga.mem.linear; - vga.tandy.mem_base = vga.mem.linear; - vga.tandy.addr_mask = 8*1024 - 1; - vga.tandy.line_mask = 3; - vga.tandy.line_shift = 13; - - if (machine==MCH_CGA || IS_TANDY_ARCH) { - extern Bit8u int10_font_08[256 * 8]; - for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_08[i*8],8); - vga.draw.font_tables[0]=vga.draw.font_tables[1]=vga.draw.font; - } - if (machine==MCH_HERC) { - extern Bit8u int10_font_14[256 * 14]; - for (i=0;i<256;i++) memcpy(&vga.draw.font[i*32],&int10_font_14[i*14],14); - vga.draw.font_tables[0]=vga.draw.font_tables[1]=vga.draw.font; - } - if (machine==MCH_CGA) { - IO_RegisterWriteHandler(0x3d8,write_cga,IO_MB); - IO_RegisterWriteHandler(0x3d9,write_cga,IO_MB); - MAPPER_AddHandler(IncreaseHue,MK_f11,MMOD2,"inchue","Inc Hue"); - MAPPER_AddHandler(DecreaseHue,MK_f11,0,"dechue","Dec Hue"); - } - if (machine==MCH_TANDY) { - write_tandy( 0x3df, 0x0, 0 ); - IO_RegisterWriteHandler(0x3d8,write_tandy,IO_MB); - IO_RegisterWriteHandler(0x3d9,write_tandy,IO_MB); - IO_RegisterWriteHandler(0x3de,write_tandy,IO_MB); - IO_RegisterWriteHandler(0x3df,write_tandy,IO_MB); - IO_RegisterWriteHandler(0x3da,write_tandy,IO_MB); - } - if (machine==MCH_PCJR) { - //write_pcjr will setup base address - write_pcjr( 0x3df, 0x7 | (0x7 << 3), 0 ); - IO_RegisterWriteHandler(0x3d9,write_pcjr,IO_MB); - IO_RegisterWriteHandler(0x3da,write_pcjr,IO_MB); - IO_RegisterWriteHandler(0x3df,write_pcjr,IO_MB); - } - if (machine==MCH_HERC) { - Bitu base=0x3b0; - for (Bitu i = 0; i < 4; i++) { - // The registers are repeated as the address is not decoded properly; - // The official ports are 3b4, 3b5 - IO_RegisterWriteHandler(base+i*2,write_crtc_index_other,IO_MB); - IO_RegisterWriteHandler(base+i*2+1,write_crtc_data_other,IO_MB); - IO_RegisterReadHandler(base+i*2,read_crtc_index_other,IO_MB); - IO_RegisterReadHandler(base+i*2+1,read_crtc_data_other,IO_MB); - } - vga.herc.enable_bits=0; - vga.herc.mode_control=0xa; // first mode written will be text mode - vga.crtc.underline_location = 13; - IO_RegisterWriteHandler(0x3b8,write_hercules,IO_MB); - IO_RegisterWriteHandler(0x3bf,write_hercules,IO_MB); - IO_RegisterReadHandler(0x3ba,read_herc_status,IO_MB); - } - if (machine==MCH_CGA) { - Bitu base=0x3d0; - for (Bitu port_ct=0; port_ct<4; port_ct++) { - IO_RegisterWriteHandler(base+port_ct*2,write_crtc_index_other,IO_MB); - IO_RegisterWriteHandler(base+port_ct*2+1,write_crtc_data_other,IO_MB); - IO_RegisterReadHandler(base+port_ct*2,read_crtc_index_other,IO_MB); - IO_RegisterReadHandler(base+port_ct*2+1,read_crtc_data_other,IO_MB); - } - } - if (IS_TANDY_ARCH) { - Bitu base=0x3d4; - IO_RegisterWriteHandler(base,write_crtc_index_other,IO_MB); - IO_RegisterWriteHandler(base+1,write_crtc_data_other,IO_MB); - IO_RegisterReadHandler(base,read_crtc_index_other,IO_MB); - IO_RegisterReadHandler(base+1,read_crtc_data_other,IO_MB); - } - -} - diff --git a/src/hardware/vga_paradise.cpp b/src/hardware/vga_paradise.cpp deleted file mode 100644 index 9db1950..0000000 --- a/src/hardware/vga_paradise.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_paradise.cpp,v 1.3 2008/08/06 18:32:35 c2woody Exp $ */ - -#include "dosbox.h" -#include "setup.h" -#include "vga.h" -#include "inout.h" -#include "mem.h" - -typedef struct { - Bitu PR0A; - Bitu PR0B; - Bitu PR1; - Bitu PR2; - Bitu PR3; - Bitu PR4; - Bitu PR5; - - inline bool locked() { return (PR5&7)!=5; } - - Bitu clockFreq[4]; - Bitu biosMode; -} SVGA_PVGA1A_DATA; - -static SVGA_PVGA1A_DATA pvga1a = { 0,0, 0,0,0,0,0, {0,0,0,0}, 0 }; - - -static void bank_setup_pvga1a() { -// Note: There is some inconsistency in available documentation. Most sources tell that PVGA1A used -// only 7 bits of bank index (VGADOC and Ferraro agree on that) but also point that there are -// implementations with 1M of RAM which is simply not possible with 7-bit banks. This implementation -// assumes that the eighth bit was actually wired and could be used. This does not conflict with -// anything and actually works in WHATVGA just fine. - if (pvga1a.PR1 & 0x08) { - // TODO: Dual bank function is not supported yet - // TODO: Requirements are not compatible with vga_memory implementation. - } else { - // Single bank config is straightforward - vga.svga.bank_read = vga.svga.bank_write = pvga1a.PR0A; - vga.svga.bank_size = 4*1024; - VGA_SetupHandlers(); - } -} - -void write_p3cf_pvga1a(Bitu reg,Bitu val,Bitu iolen) { - if (pvga1a.locked() && reg >= 0x09 && reg <= 0x0e) - return; - - switch (reg) { - case 0x09: - // Bank A, 4K granularity, not using bit 7 - // Maps to A800h-AFFFh if PR1 bit 3 set and 64k config B000h-BFFFh if 128k config. A000h-AFFFh otherwise. - pvga1a.PR0A = val; - bank_setup_pvga1a(); - break; - case 0x0a: - // Bank B, 4K granularity, not using bit 7 - // Maps to A000h-A7FFh if PR1 bit 3 set and 64k config, A000h-AFFFh if 128k - pvga1a.PR0B = val; - bank_setup_pvga1a(); - break; - case 0x0b: - // Memory size. We only allow to mess with bit 3 here (enable bank B) - this may break some detection schemes - pvga1a.PR1 = (pvga1a.PR1 & ~0x08) | (val & 0x08); - bank_setup_pvga1a(); - break; - case 0x0c: - // Video configuration - // TODO: Figure out if there is anything worth implementing here. - pvga1a.PR2 = val; - break; - case 0x0d: - // CRT control. Bits 3-4 contain bits 16-17 of CRT start. - // TODO: Implement bit 2 (CRT address doubling - this mechanism is present in other chipsets as well, - // but not implemented in DosBox core) - pvga1a.PR3 = val; - vga.config.display_start = (vga.config.display_start & 0xffff) | ((val & 0x18)<<13); - vga.config.cursor_start = (vga.config.cursor_start & 0xffff) | ((val & 0x18)<<13); - break; - case 0x0e: - // Video control - // TODO: Figure out if there is anything worth implementing here. - pvga1a.PR4 = val; - break; - case 0x0f: - // Enable extended registers - pvga1a.PR5 = val; - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:GFX:PVGA1A:Write to illegal index %2X", reg); - break; - } -} - -Bitu read_p3cf_pvga1a(Bitu reg,Bitu iolen) { - if (pvga1a.locked() && reg >= 0x09 && reg <= 0x0e) - return 0x0; - - switch (reg) { - case 0x09: - return pvga1a.PR0A; - case 0x0a: - return pvga1a.PR0B; - case 0x0b: - return pvga1a.PR1; - case 0x0c: - return pvga1a.PR2; - case 0x0d: - return pvga1a.PR3; - case 0x0e: - return pvga1a.PR4; - case 0x0f: - return pvga1a.PR5; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:GFX:PVGA1A:Read from illegal index %2X", reg); - break; - } - - return 0x0; -} - -void FinishSetMode_PVGA1A(Bitu /*crtc_base*/, VGA_ModeExtraData* modeData) { - pvga1a.biosMode = modeData->modeNo; - -// Reset to single bank and set it to 0. May need to unlock first (DPaint locks on exit) - IO_Write(0x3ce, 0x0f); - Bitu oldlock = IO_Read(0x3cf); - IO_Write(0x3cf, 0x05); - IO_Write(0x3ce, 0x09); - IO_Write(0x3cf, 0x00); - IO_Write(0x3ce, 0x0a); - IO_Write(0x3cf, 0x00); - IO_Write(0x3ce, 0x0b); - Bit8u val = IO_Read(0x3cf); - IO_Write(0x3cf, val & ~0x08); - IO_Write(0x3ce, 0x0c); - IO_Write(0x3cf, 0x00); - IO_Write(0x3ce, 0x0d); - IO_Write(0x3cf, 0x00); - IO_Write(0x3ce, 0x0e); - IO_Write(0x3cf, 0x00); - IO_Write(0x3ce, 0x0f); - IO_Write(0x3cf, oldlock); - - if (svga.determine_mode) - svga.determine_mode(); - - if(vga.mode != M_VGA) { - vga.config.compatible_chain4 = false; - vga.vmemwrap = vga.vmemsize; - } else { - vga.config.compatible_chain4 = true; - vga.vmemwrap = 256*1024; - } - - VGA_SetupHandlers(); -} - -void DetermineMode_PVGA1A() { - // Close replica from the base implementation. It will stay here - // until I figure a way to either distinguish M_VGA and M_LIN8 or - // merge them. - if (vga.attr.mode_control & 1) { - if (vga.gfx.mode & 0x40) VGA_SetMode((pvga1a.biosMode<=0x13)?M_VGA:M_LIN8); - else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4); - else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2); - else VGA_SetMode((pvga1a.biosMode<=0x13)?M_EGA:M_LIN4); - } else { - VGA_SetMode(M_TEXT); - } -} - -void SetClock_PVGA1A(Bitu which,Bitu target) { - if (which < 4) { - pvga1a.clockFreq[which]=1000*target; - VGA_StartResize(); - } -} - -Bitu GetClock_PVGA1A() { - return pvga1a.clockFreq[(vga.misc_output >> 2) & 3]; -} - -bool AcceptsMode_PVGA1A(Bitu mode) { - return VideoModeMemSize(mode) < vga.vmemsize; -} - -void SVGA_Setup_ParadisePVGA1A(void) { - svga.write_p3cf = &write_p3cf_pvga1a; - svga.read_p3cf = &read_p3cf_pvga1a; - - svga.set_video_mode = &FinishSetMode_PVGA1A; - svga.determine_mode = &DetermineMode_PVGA1A; - svga.set_clock = &SetClock_PVGA1A; - svga.get_clock = &GetClock_PVGA1A; - svga.accepts_mode = &AcceptsMode_PVGA1A; - - VGA_SetClock(0,CLK_25); - VGA_SetClock(1,CLK_28); - VGA_SetClock(2,32400); // could not find documentation - VGA_SetClock(3,35900); - - // Adjust memory, default to 512K - if (vga.vmemsize == 0) - vga.vmemsize = 512*1024; - - if (vga.vmemsize < 512*1024) { - vga.vmemsize = 256*1024; - pvga1a.PR1 = 1<<6; - } else if (vga.vmemsize > 512*1024) { - vga.vmemsize = 1024*1024; - pvga1a.PR1 = 3<<6; - } else { - pvga1a.PR1 = 2<<6; - } - - // Paradise ROM signature - PhysPt rom_base=PhysMake(0xc000,0); - phys_writeb(rom_base+0x007d,'V'); - phys_writeb(rom_base+0x007e,'G'); - phys_writeb(rom_base+0x007f,'A'); - phys_writeb(rom_base+0x0080,'='); - - IO_Write(0x3cf, 0x05); // Enable! -} diff --git a/src/hardware/vga_s3.cpp b/src/hardware/vga_s3.cpp deleted file mode 100644 index 7556d0d..0000000 --- a/src/hardware/vga_s3.cpp +++ /dev/null @@ -1,566 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_s3.cpp,v 1.18 2009/03/15 11:28:35 c2woody Exp $ */ - -#include "dosbox.h" -#include "inout.h" -#include "vga.h" -#include "mem.h" - -void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { - switch (reg) { - case 0x31: /* CR31 Memory Configuration */ -//TODO Base address - vga.s3.reg_31 = val; - vga.config.compatible_chain4 = !(val&0x08); - if (vga.config.compatible_chain4) vga.vmemwrap = 256*1024; - else vga.vmemwrap = vga.vmemsize; - vga.config.display_start = (vga.config.display_start&~0x30000)|((val&0x30)<<12); - VGA_DetermineMode(); - VGA_SetupHandlers(); - break; - /* - 0 Enable Base Address Offset (CPUA BASE). Enables bank operation if - set, disables if clear. - 1 Two Page Screen Image. If set enables 2048 pixel wide screen setup - 2 VGA 16bit Memory Bus Width. Set for 16bit, clear for 8bit - 3 Use Enhanced Mode Memory Mapping (ENH MAP). Set to enable access to - video memory above 256k. - 4-5 Bit 16-17 of the Display Start Address. For the 801/5,928 see index - 51h, for the 864/964 see index 69h. - 6 High Speed Text Display Font Fetch Mode. If set enables Page Mode - for Alpha Mode Font Access. - 7 (not 864/964) Extended BIOS ROM Space Mapped out. If clear the area - C6800h-C7FFFh is mapped out, if set it is accessible. - */ - case 0x35: /* CR35 CRT Register Lock */ - if (vga.s3.reg_lock1 != 0x48) return; //Needed for uvconfig detection - vga.s3.reg_35=val & 0xf0; - if ((vga.svga.bank_read & 0xf) ^ (val & 0xf)) { - vga.svga.bank_read&=0xf0; - vga.svga.bank_read|=val & 0xf; - vga.svga.bank_write = vga.svga.bank_read; - VGA_SetupHandlers(); - } - break; - /* - 0-3 CPU Base Address. 64k bank number. For the 801/5 and 928 see 3d4h - index 51h bits 2-3. For the 864/964 see index 6Ah. - 4 Lock Vertical Timing Registers (LOCK VTMG). Locks 3d4h index 6, 7 - (bits 0,2,3,5,7), 9 bit 5, 10h, 11h bits 0-3, 15h, 16h if set - 5 Lock Horizontal Timing Registers (LOCK HTMG). Locks 3d4h index - 0,1,2,3,4,5,17h bit 2 if set - 6 (911/924) Lock VSync Polarity. - 7 (911/924) Lock HSync Polarity. - */ - case 0x38: /* CR38 Register Lock 1 */ - vga.s3.reg_lock1=val; - break; - case 0x39: /* CR39 Register Lock 2 */ - vga.s3.reg_lock2=val; - break; - case 0x3a: - vga.s3.reg_3a = val; - break; - case 0x40: /* CR40 System Config */ - vga.s3.reg_40 = val; - break; - case 0x41: /* CR41 BIOS flags */ - vga.s3.reg_41 = val; - break; - case 0x43: /* CR43 Extended Mode */ - vga.s3.reg_43=val & ~0x4; - if (((val & 0x4) ^ (vga.config.scan_len >> 6)) & 0x4) { - vga.config.scan_len&=0x2ff; - vga.config.scan_len|=(val & 0x4) << 6; - VGA_CheckScanLength(); - } - break; - /* - 2 Logical Screen Width bit 8. Bit 8 of the Display Offset Register/ - (3d4h index 13h). (801/5,928) Only active if 3d4h index 51h bits 4-5 - are 0 - */ - case 0x45: /* Hardware cursor mode */ - vga.s3.hgc.curmode = val; - // Activate hardware cursor code if needed - VGA_ActivateHardwareCursor(); - break; - case 0x46: - vga.s3.hgc.originx = (vga.s3.hgc.originx & 0x00ff) | (val << 8); - break; - case 0x47: /* HGC orgX */ - vga.s3.hgc.originx = (vga.s3.hgc.originx & 0xff00) | val; - break; - case 0x48: - vga.s3.hgc.originy = (vga.s3.hgc.originy & 0x00ff) | (val << 8); - break; - case 0x49: /* HGC orgY */ - vga.s3.hgc.originy = (vga.s3.hgc.originy & 0xff00) | val; - break; - case 0x4A: /* HGC foreground stack */ - if (vga.s3.hgc.fstackpos > 2) vga.s3.hgc.fstackpos = 0; - vga.s3.hgc.forestack[vga.s3.hgc.fstackpos] = val; - vga.s3.hgc.fstackpos++; - break; - case 0x4B: /* HGC background stack */ - if (vga.s3.hgc.bstackpos > 2) vga.s3.hgc.bstackpos = 0; - vga.s3.hgc.backstack[vga.s3.hgc.bstackpos] = val; - vga.s3.hgc.bstackpos++; - break; - case 0x4c: /* HGC start address high byte*/ - vga.s3.hgc.startaddr &=0xff; - vga.s3.hgc.startaddr |= ((val & 0xf) << 8); - if ((((Bitu)vga.s3.hgc.startaddr)<<10)+((64*64*2)/8) > vga.vmemsize) { - vga.s3.hgc.startaddr &= 0xff; // put it back to some sane area; - // if read back of this address is ever implemented this needs to change - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:CRTC: HGC pattern address beyond video memory" ); - } - break; - case 0x4d: /* HGC start address low byte*/ - vga.s3.hgc.startaddr &=0xff00; - vga.s3.hgc.startaddr |= (val & 0xff); - break; - case 0x4e: /* HGC pattern start X */ - vga.s3.hgc.posx = val & 0x3f; // bits 0-5 - break; - case 0x4f: /* HGC pattern start Y */ - vga.s3.hgc.posy = val & 0x3f; // bits 0-5 - break; - case 0x50: // Extended System Control 1 - vga.s3.reg_50 = val; - switch (val & S3_XGA_CMASK) { - case S3_XGA_32BPP: vga.s3.xga_color_mode = M_LIN32; break; - case S3_XGA_16BPP: vga.s3.xga_color_mode = M_LIN16; break; - case S3_XGA_8BPP: vga.s3.xga_color_mode = M_LIN8; break; - } - switch (val & S3_XGA_WMASK) { - case S3_XGA_1024: vga.s3.xga_screen_width = 1024; break; - case S3_XGA_1152: vga.s3.xga_screen_width = 1152; break; - case S3_XGA_640: vga.s3.xga_screen_width = 640; break; - case S3_XGA_800: vga.s3.xga_screen_width = 800; break; - case S3_XGA_1280: vga.s3.xga_screen_width = 1280; break; - default: vga.s3.xga_screen_width = 1024; break; - } - break; - case 0x51: /* Extended System Control 2 */ - vga.s3.reg_51=val & 0xc0; //Only store bits 6,7 - vga.config.display_start&=0xF3FFFF; - vga.config.display_start|=(val & 3) << 18; - if ((vga.svga.bank_read&0x30) ^ ((val&0xc)<<2)) { - vga.svga.bank_read&=0xcf; - vga.svga.bank_read|=(val&0xc)<<2; - vga.svga.bank_write = vga.svga.bank_read; - VGA_SetupHandlers(); - } - if (((val & 0x30) ^ (vga.config.scan_len >> 4)) & 0x30) { - vga.config.scan_len&=0xff; - vga.config.scan_len|=(val & 0x30) << 4; - VGA_CheckScanLength(); - } - break; - /* - 0 (80x) Display Start Address bit 18 - 0-1 (928 +) Display Start Address bit 18-19 - Bits 16-17 are in index 31h bits 4-5, Bits 0-15 are in 3d4h index - 0Ch,0Dh. For the 864/964 see 3d4h index 69h - 2 (80x) CPU BASE. CPU Base Address Bit 18. - 2-3 (928 +) Old CPU Base Address Bits 19-18. - 64K Bank register bits 4-5. Bits 0-3 are in 3d4h index 35h. - For the 864/964 see 3d4h index 6Ah - 4-5 Logical Screen Width Bit [8-9]. Bits 8-9 of the CRTC Offset register - (3d4h index 13h). If this field is 0, 3d4h index 43h bit 2 is active - 6 (928,964) DIS SPXF. Disable Split Transfers if set. Spilt Transfers - allows transferring one half of the VRAM shift register data while - the other half is being output. For the 964 Split Transfers - must be enabled in enhanced modes (4AE8h bit 0 set). Guess: They - probably can't time the VRAM load cycle closely enough while the - graphics engine is running. - 7 (not 864/964) Enable EPROM Write. If set enables flash memory write - control to the BIOS ROM address - */ - case 0x52: // Extended System Control 1 - vga.s3.reg_52 = val; - break; - case 0x53: - // Map or unmap MMIO - // bit 4 = MMIO at A0000 - // bit 3 = MMIO at LFB + 16M (should be fine if its always enabled for now) - if(vga.s3.ext_mem_ctrl!=val) { - vga.s3.ext_mem_ctrl = val; - VGA_SetupHandlers(); - } - break; - case 0x55: /* Extended Video DAC Control */ - vga.s3.reg_55=val; - break; - /* - 0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the - RAMDAC, allowing access to all 8 or 16 registers on advanced RAMDACs. - If this field is 0, 3d4h index 43h bit 1 is active. - 2 Enable General Input Port Read. If set DAC reads are disabled and the - STRD strobe for reading the General Input Port is enabled for reading - while DACRD is active, if clear DAC reads are enabled. - 3 (928) Enable External SID Operation if set. If set video data is - passed directly from the VRAMs to the DAC rather than through the - VGA chip - 4 Hardware Cursor MS/X11 Mode. If set the Hardware Cursor is in X11 - mode, if clear in MS-Windows mode - 5 (80x,928) Hardware Cursor External Operation Mode. If set the two - bits of cursor data ,is output on the HC[0-1] pins for the video DAC - The SENS pin becomes HC1 and the MID2 pin becomes HC0. - 6 ?? - 7 (80x,928) Disable PA Output. If set PA[0-7] and VCLK are tristated. - (864/964) TOFF VCLK. Tri-State Off VCLK Output. VCLK output tri - -stated if set - */ - case 0x58: /* Linear Address Window Control */ - vga.s3.reg_58=val; - break; - /* - 0-1 Linear Address Window Size. Must be less than or equal to video - memory size. 0: 64K, 1: 1MB, 2: 2MB, 3: 4MB (928)/8Mb (864/964) - 2 (not 864/964) Enable Read Ahead Cache if set - 3 (80x,928) ISA Latch Address. If set latches address during every ISA - cycle, unlatches during every ISA cycle if clear. - (864/964) LAT DEL. Address Latch Delay Control (VL-Bus only). If set - address latching occours in the T1 cycle, if clear in the T2 cycle - (I.e. one clock cycle delayed). - 4 ENB LA. Enable Linear Addressing if set. - 5 (not 864/964) Limit Entry Depth for Write-Post. If set limits Write - -Post Entry Depth to avoid ISA bus timeout due to wait cycle limit. - 6 (928,964) Serial Access Mode (SAM) 256 Words Control. If set SAM - control is 256 words, if clear 512 words. - 7 (928) RAS 6-MCLK. If set the random read/write cycle time is 6MCLKs, - if clear 7MCLKs - */ - case 0x59: /* Linear Address Window Position High */ - if ((vga.s3.la_window&0xff00) ^ (val << 8)) { - vga.s3.la_window=(vga.s3.la_window&0x00ff) | (val << 8); - VGA_StartUpdateLFB(); - } - break; - case 0x5a: /* Linear Address Window Position Low */ - if ((vga.s3.la_window&0x00ff) ^ val) { - vga.s3.la_window=(vga.s3.la_window&0xff00) | val; - VGA_StartUpdateLFB(); - } - break; - case 0x5D: /* Extended Horizontal Overflow */ - if ((val ^ vga.s3.ex_hor_overflow) & 3) { - vga.s3.ex_hor_overflow=val; - VGA_StartResize(); - } else vga.s3.ex_hor_overflow=val; - break; - /* - 0 Horizontal Total bit 8. Bit 8 of the Horizontal Total register (3d4h - index 0) - 1 Horizontal Display End bit 8. Bit 8 of the Horizontal Display End - register (3d4h index 1) - 2 Start Horizontal Blank bit 8. Bit 8 of the Horizontal Start Blanking - register (3d4h index 2). - 3 (864,964) EHB+64. End Horizontal Blank +64. If set the /BLANK pulse - is extended by 64 DCLKs. Note: Is this bit 6 of 3d4h index 3 or - does it really extend by 64 ? - 4 Start Horizontal Sync Position bit 8. Bit 8 of the Horizontal Start - Retrace register (3d4h index 4). - 5 (864,964) EHS+32. End Horizontal Sync +32. If set the HSYNC pulse - is extended by 32 DCLKs. Note: Is this bit 5 of 3d4h index 5 or - does it really extend by 32 ? - 6 (928,964) Data Transfer Position bit 8. Bit 8 of the Data Transfer - Position register (3d4h index 3Bh) - 7 (928,964) Bus-Grant Terminate Position bit 8. Bit 8 of the Bus Grant - Termination register (3d4h index 5Fh). - */ - case 0x5e: /* Extended Vertical Overflow */ - vga.config.line_compare=(vga.config.line_compare & 0x3ff) | (val & 0x40) << 4; - if ((val ^ vga.s3.ex_ver_overflow) & 0x3) { - vga.s3.ex_ver_overflow=val; - VGA_StartResize(); - } else vga.s3.ex_ver_overflow=val; - break; - /* - 0 Vertical Total bit 10. Bit 10 of the Vertical Total register (3d4h - index 6). Bits 8 and 9 are in 3d4h index 7 bit 0 and 5. - 1 Vertical Display End bit 10. Bit 10 of the Vertical Display End - register (3d4h index 12h). Bits 8 and 9 are in 3d4h index 7 bit 1 - and 6 - 2 Start Vertical Blank bit 10. Bit 10 of the Vertical Start Blanking - register (3d4h index 15h). Bit 8 is in 3d4h index 7 bit 3 and bit 9 - in 3d4h index 9 bit 5 - 4 Vertical Retrace Start bit 10. Bit 10 of the Vertical Start Retrace - register (3d4h index 10h). Bits 8 and 9 are in 3d4h index 7 bit 2 - and 7. - 6 Line Compare Position bit 10. Bit 10 of the Line Compare register - (3d4h index 18h). Bit 8 is in 3d4h index 7 bit 4 and bit 9 in 3d4h - index 9 bit 6. - */ - case 0x67: /* Extended Miscellaneous Control 2 */ - /* - 0 VCLK PHS. VCLK Phase With Respect to DCLK. If clear VLKC is inverted - DCLK, if set VCLK = DCLK. - 2-3 (Trio64V+) streams mode - 00 disable Streams Processor - 01 overlay secondary stream on VGA-mode background - 10 reserved - 11 full Streams Processor operation - 4-7 Pixel format. - 0 Mode 0: 8bit (1 pixel/VCLK) - 1 Mode 8: 8bit (2 pixels/VCLK) - 3 Mode 9: 15bit (1 pixel/VCLK) - 5 Mode 10: 16bit (1 pixel/VCLK) - 7 Mode 11: 24/32bit (2 VCLKs/pixel) - 13 (732/764) 32bit (1 pixel/VCLK) - */ - vga.s3.misc_control_2=val; - VGA_DetermineMode(); - break; - case 0x69: /* Extended System Control 3 */ - if (((vga.config.display_start & 0x1f0000)>>16) ^ (val & 0x1f)) { - vga.config.display_start&=0xffff; - vga.config.display_start|=(val & 0x1f) << 16; - } - break; - case 0x6a: /* Extended System Control 4 */ - vga.svga.bank_read=val & 0x7f; - vga.svga.bank_write = vga.svga.bank_read; - VGA_SetupHandlers(); - break; - case 0x6b: // BIOS scratchpad: LFB adress - vga.s3.reg_6b=(Bit8u)val; - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:CRTC:Write to illegal index %2X", reg ); - break; - } -} - -Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { - switch (reg) { - case 0x24: /* attribute controller index (read only) */ - case 0x26: - return (vga.attr.enabled?0x20:0x00) | (vga.attr.index&0x1f); - case 0x2d: /* Extended Chip ID (high byte of PCI device ID) */ - return 0x88; - case 0x2e: /* New Chip ID (low byte of PCI device ID) */ - return 0x11; // Trio64 - case 0x2f: /* Revision */ - return 0x00; // Trio64 (exact value?) -// return 0x44; // Trio64 V+ - case 0x30: /* CR30 Chip ID/REV register */ - return 0xe1; // Trio+ dual byte - case 0x31: /* CR31 Memory Configuration */ -//TODO mix in bits from baseaddress; - return vga.s3.reg_31; - case 0x35: /* CR35 CRT Register Lock */ - return vga.s3.reg_35|(vga.svga.bank_read & 0xf); - case 0x36: /* CR36 Reset State Read 1 */ - return vga.s3.reg_36; - case 0x37: /* Reset state read 2 */ - return 0x2b; - case 0x38: /* CR38 Register Lock 1 */ - return vga.s3.reg_lock1; - case 0x39: /* CR39 Register Lock 2 */ - return vga.s3.reg_lock2; - case 0x3a: - return vga.s3.reg_3a; - case 0x40: /* CR40 system config */ - return vga.s3.reg_40; - case 0x41: /* CR40 system config */ - return vga.s3.reg_41; - case 0x42: // not interlaced - return 0x0d; - case 0x43: /* CR43 Extended Mode */ - return vga.s3.reg_43|((vga.config.scan_len>>6)&0x4); - case 0x45: /* Hardware cursor mode */ - vga.s3.hgc.bstackpos = 0; - vga.s3.hgc.fstackpos = 0; - return vga.s3.hgc.curmode|0xa0; - case 0x46: - return vga.s3.hgc.originx>>8; - case 0x47: /* HGC orgX */ - return vga.s3.hgc.originx&0xff; - case 0x48: - return vga.s3.hgc.originy>>8; - case 0x49: /* HGC orgY */ - return vga.s3.hgc.originy&0xff; - case 0x4A: /* HGC foreground stack */ - return vga.s3.hgc.forestack[vga.s3.hgc.fstackpos]; - case 0x4B: /* HGC background stack */ - return vga.s3.hgc.backstack[vga.s3.hgc.bstackpos]; - case 0x50: // CR50 Extended System Control 1 - return vga.s3.reg_50; - case 0x51: /* Extended System Control 2 */ - return ((vga.config.display_start >> 16) & 3 ) | - ((vga.svga.bank_read & 0x30) >> 2) | - ((vga.config.scan_len & 0x300) >> 4) | - vga.s3.reg_51; - case 0x52: // CR52 Extended BIOS flags 1 - return vga.s3.reg_52; - case 0x53: - return vga.s3.ext_mem_ctrl; - case 0x55: /* Extended Video DAC Control */ - return vga.s3.reg_55; - case 0x58: /* Linear Address Window Control */ - return vga.s3.reg_58; - case 0x59: /* Linear Address Window Position High */ - return (vga.s3.la_window >> 8); - case 0x5a: /* Linear Address Window Position Low */ - return (vga.s3.la_window & 0xff); - case 0x5D: /* Extended Horizontal Overflow */ - return vga.s3.ex_hor_overflow; - case 0x5e: /* Extended Vertical Overflow */ - return vga.s3.ex_ver_overflow; - case 0x67: /* Extended Miscellaneous Control 2 */ - return vga.s3.misc_control_2; - case 0x69: /* Extended System Control 3 */ - return (Bit8u)((vga.config.display_start & 0x1f0000)>>16); - case 0x6a: /* Extended System Control 4 */ - return (Bit8u)(vga.svga.bank_read & 0x7f); - case 0x6b: // BIOS scatchpad: LFB address - return vga.s3.reg_6b; - default: - return 0x00; - } -} - -void SVGA_S3_WriteSEQ(Bitu reg,Bitu val,Bitu iolen) { - if (reg>0x8 && vga.s3.pll.lock!=0x6) return; - switch (reg) { - case 0x08: - vga.s3.pll.lock=val; - break; - case 0x10: /* Memory PLL Data Low */ - vga.s3.mclk.n=val & 0x1f; - vga.s3.mclk.r=val >> 5; - break; - case 0x11: /* Memory PLL Data High */ - vga.s3.mclk.m=val & 0x7f; - break; - case 0x12: /* Video PLL Data Low */ - vga.s3.clk[3].n=val & 0x1f; - vga.s3.clk[3].r=val >> 5; - break; - case 0x13: /* Video PLL Data High */ - vga.s3.clk[3].m=val & 0x7f; - break; - case 0x15: - vga.s3.pll.cmd=val; - VGA_StartResize(); - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:SEQ:Write to illegal index %2X", reg ); - break; - } -} - -Bitu SVGA_S3_ReadSEQ(Bitu reg,Bitu iolen) { - /* S3 specific group */ - if (reg>0x8 && vga.s3.pll.lock!=0x6) { - if (reg<0x1b) return 0; - else return reg; - } - switch (reg) { - case 0x08: /* PLL Unlock */ - return vga.s3.pll.lock; - case 0x10: /* Memory PLL Data Low */ - return vga.s3.mclk.n || (vga.s3.mclk.r << 5); - case 0x11: /* Memory PLL Data High */ - return vga.s3.mclk.m; - case 0x12: /* Video PLL Data Low */ - return vga.s3.clk[3].n || (vga.s3.clk[3].r << 5); - case 0x13: /* Video Data High */ - return vga.s3.clk[3].m; - case 0x15: - return vga.s3.pll.cmd; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:SEQ:Read from illegal index %2X", reg); - return 0; - } -} - -Bitu SVGA_S3_GetClock(void) { - Bitu clock = (vga.misc_output >> 2) & 3; - if (clock == 0) - clock = 25175000; - else if (clock == 1) - clock = 28322000; - else - clock=1000*S3_CLOCK(vga.s3.clk[clock].m,vga.s3.clk[clock].n,vga.s3.clk[clock].r); - /* Check for dual transfer, master clock/2 */ - if (vga.s3.pll.cmd & 0x10) clock/=2; - return clock; -} - -bool SVGA_S3_HWCursorActive(void) { - return (vga.s3.hgc.curmode & 0x1) != 0; -} - -bool SVGA_S3_AcceptsMode(Bitu mode) { - return VideoModeMemSize(mode) < vga.vmemsize; -} - -void SVGA_Setup_S3Trio(void) { - svga.write_p3d5 = &SVGA_S3_WriteCRTC; - svga.read_p3d5 = &SVGA_S3_ReadCRTC; - svga.write_p3c5 = &SVGA_S3_WriteSEQ; - svga.read_p3c5 = &SVGA_S3_ReadSEQ; - svga.write_p3c0 = 0; /* no S3-specific functionality */ - svga.read_p3c1 = 0; /* no S3-specific functionality */ - - svga.set_video_mode = 0; /* implemented in core */ - svga.determine_mode = 0; /* implemented in core */ - svga.set_clock = 0; /* implemented in core */ - svga.get_clock = &SVGA_S3_GetClock; - svga.hardware_cursor_active = &SVGA_S3_HWCursorActive; - svga.accepts_mode = &SVGA_S3_AcceptsMode; - - if (vga.vmemsize == 0) - vga.vmemsize = 2*1024*1024; // the most common S3 configuration - - // Set CRTC 36 to specify amount of VRAM and PCI - if (vga.vmemsize < 1024*1024) { - vga.vmemsize = 512*1024; - vga.s3.reg_36 = 0xfa; // less than 1mb fast page mode - } else if (vga.vmemsize < 2048*1024) { - vga.vmemsize = 1024*1024; - vga.s3.reg_36 = 0xda; // 1mb fast page mode - } else if (vga.vmemsize < 3072*1024) { - vga.vmemsize = 2048*1024; - vga.s3.reg_36 = 0x9a; // 2mb fast page mode - } else if (vga.vmemsize < 4096*1024) { - vga.vmemsize = 3072*1024; - vga.s3.reg_36 = 0x5a; // 3mb fast page mode - } else { // Trio64 supported only up to 4M - vga.vmemsize = 4096*1024; - vga.s3.reg_36 = 0x1a; // 4mb fast page mode - } - - // S3 ROM signature - PhysPt rom_base=PhysMake(0xc000,0); - phys_writeb(rom_base+0x003f,'S'); - phys_writeb(rom_base+0x0040,'3'); - phys_writeb(rom_base+0x0041,' '); - phys_writeb(rom_base+0x0042,'8'); - phys_writeb(rom_base+0x0043,'6'); - phys_writeb(rom_base+0x0044,'C'); - phys_writeb(rom_base+0x0045,'7'); - phys_writeb(rom_base+0x0046,'6'); - phys_writeb(rom_base+0x0047,'4'); -} diff --git a/src/hardware/vga_seq.cpp b/src/hardware/vga_seq.cpp index 8bbe31c..ce5e0cf 100644 --- a/src/hardware/vga_seq.cpp +++ b/src/hardware/vga_seq.cpp @@ -1,159 +1,125 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_seq.cpp,v 1.23 2009/04/11 08:02:23 qbix79 Exp $ */ - -#include "dosbox.h" -#include "inout.h" -#include "vga.h" - -#define seq(blah) vga.seq.blah - -Bitu read_p3c4(Bitu /*port*/,Bitu /*iolen*/) { - return seq(index); -} - -void write_p3c4(Bitu /*port*/,Bitu val,Bitu /*iolen*/) { - seq(index)=val; -} - -void write_p3c5(Bitu /*port*/,Bitu val,Bitu iolen) { -// LOG_MSG("SEQ WRITE reg %X val %X",seq(index),val); - switch(seq(index)) { - case 0: /* Reset */ - seq(reset)=val; - break; - case 1: /* Clocking Mode */ - if (val!=seq(clocking_mode)) { - // don't resize if only the screen off bit was changed - if ((val&(~0x20))!=(seq(clocking_mode)&(~0x20))) { - seq(clocking_mode)=val; - VGA_StartResize(); - } else { - seq(clocking_mode)=val; - } - } - /* TODO Figure this out :) - 0 If set character clocks are 8 dots wide, else 9. - 2 If set loads video serializers every other character - clock cycle, else every one. - 3 If set the Dot Clock is Master Clock/2, else same as Master Clock - (See 3C2h bit 2-3). (Doubles pixels). Note: on some SVGA chipsets - this bit also affects the Sequencer mode. - 4 If set loads video serializers every fourth character clock cycle, - else every one. - 5 if set turns off screen and gives all memory cycles to the CPU - interface. - */ - break; - case 2: /* Map Mask */ - seq(map_mask)=val & 15; - vga.config.full_map_mask=FillTable[val & 15]; - vga.config.full_not_map_mask=~vga.config.full_map_mask; - /* - 0 Enable writes to plane 0 if set - 1 Enable writes to plane 1 if set - 2 Enable writes to plane 2 if set - 3 Enable writes to plane 3 if set - */ - break; - case 3: /* Character Map Select */ - { - seq(character_map_select)=val; - Bit8u font1=(val & 0x3) << 1; - if (IS_VGA_ARCH) font1|=(val & 0x10) >> 4; - vga.draw.font_tables[0]=&vga.draw.font[font1*8*1024]; - Bit8u font2=((val & 0xc) >> 1); - if (IS_VGA_ARCH) font2|=(val & 0x20) >> 5; - vga.draw.font_tables[1]=&vga.draw.font[font2*8*1024]; - } - /* - 0,1,4 Selects VGA Character Map (0..7) if bit 3 of the character - attribute is clear. - 2,3,5 Selects VGA Character Map (0..7) if bit 3 of the character - attribute is set. - Note: Character Maps are placed as follows: - Map 0 at 0k, 1 at 16k, 2 at 32k, 3: 48k, 4: 8k, 5: 24k, 6: 40k, 7: 56k - */ - break; - case 4: /* Memory Mode */ - /* - 0 Set if in an alphanumeric mode, clear in graphics modes. - 1 Set if more than 64kbytes on the adapter. - 2 Enables Odd/Even addressing mode if set. Odd/Even mode places all odd - bytes in plane 1&3, and all even bytes in plane 0&2. - 3 If set address bit 0-1 selects video memory planes (256 color mode), - rather than the Map Mask and Read Map Select Registers. - */ - seq(memory_mode)=val; - if (IS_VGA_ARCH) { - /* Changing this means changing the VGA Memory Read/Write Handler */ - if (val&0x08) vga.config.chained=true; - else vga.config.chained=false; - VGA_SetupHandlers(); - } - break; - default: - if (svga.write_p3c5) { - svga.write_p3c5(seq(index), val, iolen); - } else { - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:Write to illegal index %2X",seq(index)); - } - break; - } -} - - -Bitu read_p3c5(Bitu /*port*/,Bitu iolen) { -// LOG_MSG("VGA:SEQ:Read from index %2X",seq(index)); - switch(seq(index)) { - case 0: /* Reset */ - return seq(reset); - break; - case 1: /* Clocking Mode */ - return seq(clocking_mode); - break; - case 2: /* Map Mask */ - return seq(map_mask); - break; - case 3: /* Character Map Select */ - return seq(character_map_select); - break; - case 4: /* Memory Mode */ - return seq(memory_mode); - break; - default: - if (svga.read_p3c5) - return svga.read_p3c5(seq(index), iolen); - break; - } - return 0; -} - - -void VGA_SetupSEQ(void) { - if (IS_EGAVGA_ARCH) { - IO_RegisterWriteHandler(0x3c4,write_p3c4,IO_MB); - IO_RegisterWriteHandler(0x3c5,write_p3c5,IO_MB); - if (IS_VGA_ARCH) { - IO_RegisterReadHandler(0x3c4,read_p3c4,IO_MB); - IO_RegisterReadHandler(0x3c5,read_p3c5,IO_MB); - } - } -} - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "inout.h" +#include "vga.h" + +#define seq(blah) vga.seq.blah + +Bit8u read_p3c4(Bit32u port) { + return seq(index); +} + +void write_p3c4(Bit32u port,Bit8u val) { + seq(index)=val; +}; + +void write_p3c5(Bit32u port,Bit8u val) { + switch(seq(index)) { + case 0: /* Reset */ + seq(reset)=val; + break; + case 1: /* Clocking Mode */ + seq(clocking_mode)=val; + /* TODO Figure this out :) + 0 If set character clocks are 8 dots wide, else 9. + 2 If set loads video serializers every other character + clock cycle, else every one. + 3 If set the Dot Clock is Master Clock/2, else same as Master Clock + (See 3C2h bit 2-3). (Doubles pixels). Note: on some SVGA chipsets + this bit also affects the Sequencer mode. + 4 If set loads video serializers every fourth character clock cycle, + else every one. + 5 if set turns off screen and gives all memory cycles to the CPU + interface. + */ + break; + case 2: /* Map Mask */ + seq(map_mask)=val & 15; + vga.config.full_map_mask=FillTable[val & 15]; + /* + 0 Enable writes to plane 0 if set + 1 Enable writes to plane 1 if set + 2 Enable writes to plane 2 if set + 3 Enable writes to plane 3 if set + */ + break; + case 3: /* Character Map Select */ + seq(character_map_select)=val; + /* + 0,1,4 Selects VGA Character Map (0..7) if bit 3 of the character + attribute is clear. + 2,3,5 Selects VGA Character Map (0..7) if bit 3 of the character + attribute is set. + Note: Character Maps are placed as follows: + Map 0 at 0k, 1 at 16k, 2 at 32k, 3: 48k, 4: 8k, 5: 24k, 6: 40k, 7: 56k + */ + break; + case 4: /* Memory Mode */ + /* + 0 Set if in an alphanumeric mode, clear in graphics modes. + 1 Set if more than 64kbytes on the adapter. + 2 Enables Odd/Even addressing mode if set. Odd/Even mode places all odd + bytes in plane 1&3, and all even bytes in plane 0&2. + 3 If set address bit 0-1 selects video memory planes (256 color mode), + rather than the Map Mask and Read Map Select Registers. + */ + seq(memory_mode)=val; + /* Changing this means changing the VGA Memory Read/Write Handler */ + if (val&0x08) vga.config.chained=true; + else vga.config.chained=false; + VGA_FindSettings(); + break; + default: + LOG_ERROR("VGA:SEQ:Write to illegal index %2X",seq(index)); + }; +}; + + +Bit8u read_p3c5(Bit32u port) { + switch(seq(index)) { + case 0: /* Reset */ + return seq(reset); + break; + case 1: /* Clocking Mode */ + return seq(clocking_mode); + break; + case 2: /* Map Mask */ + return seq(map_mask); + break; + case 3: /* Character Map Select */ + return seq(character_map_select); + break; + case 4: /* Memory Mode */ + return seq(memory_mode); + default: + LOG_ERROR("VGA:SEQ:Read from illegal index %2X",seq(index)); + }; + return 0; +}; + + +void VGA_SetupSEQ(void) { + IO_RegisterWriteHandler(0x3c4,write_p3c4,"VGA:Sequencer Index"); + IO_RegisterWriteHandler(0x3c5,write_p3c5,"VGA:Sequencer Data"); + IO_RegisterReadHandler(0x3c4,read_p3c4,"VGA:Sequencer Index"); + IO_RegisterReadHandler(0x3c5,read_p3c5,"VGA:Sequencer Data"); + +} + diff --git a/src/hardware/vga_tseng.cpp b/src/hardware/vga_tseng.cpp deleted file mode 100644 index b51b4ff..0000000 --- a/src/hardware/vga_tseng.cpp +++ /dev/null @@ -1,804 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_tseng.cpp,v 1.4 2008/08/06 18:32:35 c2woody Exp $ */ - - -#include "dosbox.h" -#include "setup.h" -#include "vga.h" -#include "inout.h" -#include "mem.h" -#include -// Tseng ET4K data -typedef struct { - Bit8u extensionsEnabled; - -// Stored exact values of some registers. Documentation only specifies some bits but hardware checks may -// expect other bits to be preserved. - Bitu store_3d4_31; - Bitu store_3d4_32; - Bitu store_3d4_33; - Bitu store_3d4_34; - Bitu store_3d4_35; - Bitu store_3d4_36; - Bitu store_3d4_37; - Bitu store_3d4_3f; - - Bitu store_3c0_16; - Bitu store_3c0_17; - - Bitu store_3c4_06; - Bitu store_3c4_07; - - Bitu clockFreq[16]; - Bitu biosMode; -} SVGA_ET4K_DATA; - -static SVGA_ET4K_DATA et4k = { 1,0,0,0,0,0,0,0,0, 0,0, 0,0, - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0 }; - -#define STORE_ET4K(port, index) \ - case 0x##index: \ - et4k.store_##port##_##index = val; \ - break; - -#define RESTORE_ET4K(port, index) \ - case 0x##index: \ - return et4k.store_##port##_##index; - -// Tseng ET4K implementation -void write_p3d5_et4k(Bitu reg,Bitu val,Bitu iolen) { - if(!et4k.extensionsEnabled && reg!=0x33) - return; - - switch(reg) { - /* - 3d4h index 31h (R/W): General Purpose - bit 0-3 Scratch pad - 6-7 Clock Select bits 3-4. Bits 0-1 are in 3C2h/3CCh bits 2-3. - */ - STORE_ET4K(3d4, 31); - - // 3d4h index 32h - RAS/CAS Configuration (R/W) - // No effect on emulation. Should not be written by software. - STORE_ET4K(3d4, 32); - - case 0x33: - // 3d4 index 33h (R/W): Extended start Address - // 0-1 Display Start Address bits 16-17 - // 2-3 Cursor start address bits 16-17 - // Used by standard Tseng ID scheme - et4k.store_3d4_33 = val; - vga.config.display_start = (vga.config.display_start & 0xffff) | ((val & 0x03)<<16); - vga.config.cursor_start = (vga.config.cursor_start & 0xffff) | ((val & 0x0c)<<14); - break; - - /* - 3d4h index 34h (R/W): 6845 Compatibility Control Register - bit 0 Enable CS0 (alternate clock timing) - 1 Clock Select bit 2. Bits 0-1 in 3C2h bits 2-3, bits 3-4 are in 3d4h - index 31h bits 6-7 - 2 Tristate ET4000 bus and color outputs if set - 3 Video Subsystem Enable Register at 46E8h if set, at 3C3h if clear. - 4 Enable Translation ROM for reading CRTC and MISCOUT if set - 5 Enable Translation ROM for writing CRTC and MISCOUT if set - 6 Enable double scan in AT&T compatibility mode if set - 7 Enable 6845 compatibility if set - */ - // TODO: Bit 6 may have effect on emulation - STORE_ET4K(3d4, 34); - - case 0x35: - /* - 3d4h index 35h (R/W): Overflow High - bit 0 Vertical Blank Start Bit 10 (3d4h index 15h). - 1 Vertical Total Bit 10 (3d4h index 6). - 2 Vertical Display End Bit 10 (3d4h index 12h). - 3 Vertical Sync Start Bit 10 (3d4h index 10h). - 4 Line Compare Bit 10 (3d4h index 18h). - 5 Gen-Lock Enabled if set (External sync) - 6 (4000) Read/Modify/Write Enabled if set. Currently not implemented. - 7 Vertical interlace if set. The Vertical timing registers are - programmed as if the mode was non-interlaced!! - */ - et4k.store_3d4_35 = val; - vga.config.line_compare = (vga.config.line_compare & 0x3ff) | ((val&0x10)<<6); - // Abusing s3 ex_ver_overflow field. This is to be cleaned up later. - { - Bit8u s3val = - ((val & 0x01) << 2) | // vbstart - ((val & 0x02) >> 1) | // vtotal - ((val & 0x04) >> 1) | // vdispend - ((val & 0x08) << 1) | // vsyncstart (?) - ((val & 0x10) << 2); // linecomp - if ((s3val ^ vga.s3.ex_ver_overflow) & 0x3) { - vga.s3.ex_ver_overflow=s3val; - VGA_StartResize(); - } else vga.s3.ex_ver_overflow=s3val; - } - break; - - // 3d4h index 36h - Video System Configuration 1 (R/W) - // VGADOC provides a lot of info on this register, Ferraro has significantly less detail. - // This is unlikely to be used by any games. Bit 4 switches chipset into linear mode - - // that may be useful in some cases if there is any software actually using it. - // TODO (not near future): support linear addressing - STORE_ET4K(3d4, 36); - - // 3d4h index 37 - Video System Configuration 2 (R/W) - // Bits 0,1, and 3 provides information about memory size: - // 0-1 Bus width (1: 8 bit, 2: 16 bit, 3: 32 bit) - // 3 Size of RAM chips (0: 64Kx, 1: 256Kx) - // Other bits have no effect on emulation. - case 0x37: - if (val != et4k.store_3d4_37) { - et4k.store_3d4_37 = val; - vga.vmemwrap = ((64*1024)<<((val&8)>>2))<<((val&3)-1); - VGA_SetupHandlers(); - } - break; - - case 0x3f: - /* - 3d4h index 3Fh (R/W): - bit 0 Bit 8 of the Horizontal Total (3d4h index 0) - 2 Bit 8 of the Horizontal Blank Start (3d4h index 3) - 4 Bit 8 of the Horizontal Retrace Start (3d4h index 4) - 7 Bit 8 of the CRTC offset register (3d4h index 13h). - */ - // The only unimplemented one is bit 7 - et4k.store_3d4_3f = val; - // Abusing s3 ex_hor_overflow field which very similar. This is - // to be cleaned up later - if ((val ^ vga.s3.ex_hor_overflow) & 3) { - vga.s3.ex_hor_overflow=(val&0x15); - VGA_StartResize(); - } else vga.s3.ex_hor_overflow=(val&0x15); - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:ET4K:Write to illegal index %2X", reg); - break; - } -} - -Bitu read_p3d5_et4k(Bitu reg,Bitu iolen) { - if (!et4k.extensionsEnabled && reg!=0x33) - return 0x0; - switch(reg) { - RESTORE_ET4K(3d4, 31); - RESTORE_ET4K(3d4, 32); - RESTORE_ET4K(3d4, 33); - RESTORE_ET4K(3d4, 34); - RESTORE_ET4K(3d4, 35); - RESTORE_ET4K(3d4, 36); - RESTORE_ET4K(3d4, 37); - RESTORE_ET4K(3d4, 3f); - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:ET4K:Read from illegal index %2X", reg); - break; - } - return 0x0; -} - -void write_p3c5_et4k(Bitu reg,Bitu val,Bitu iolen) { - switch(reg) { - /* - 3C4h index 6 (R/W): TS State Control - bit 1-2 Font Width Select in dots/character - If 3C4h index 4 bit 0 clear: - 0: 9 dots, 1: 10 dots, 2: 12 dots, 3: 6 dots - If 3C4h index 5 bit 0 set: - 0: 8 dots, 1: 11 dots, 2: 7 dots, 3: 16 dots - Only valid if 3d4h index 34h bit 3 set. - */ - // TODO: Figure out if this has any practical use - STORE_ET4K(3c4, 06); - // 3C4h index 7 (R/W): TS Auxiliary Mode - // Unlikely to be used by games (things like ROM enable/disable and emulation of VGA vs EGA) - STORE_ET4K(3c4, 07); - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:ET4K:Write to illegal index %2X", reg); - break; - } -} - -Bitu read_p3c5_et4k(Bitu reg,Bitu iolen) { - switch(reg) { - RESTORE_ET4K(3c4, 06); - RESTORE_ET4K(3c4, 07); - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:ET4K:Read from illegal index %2X", reg); - break; - } - return 0x0; -} - -/* -3CDh (R/W): Segment Select -bit 0-3 64k Write bank number (0..15) - 4-7 64k Read bank number (0..15) -*/ -void write_p3cd_et4k(Bitu port,Bitu val,Bitu iolen) { - vga.svga.bank_write = val & 0x0f; - vga.svga.bank_read = (val>>4) & 0x0f; - VGA_SetupHandlers(); -} - -Bitu read_p3cd_et4k(Bitu port,Bitu iolen) { - return (vga.svga.bank_read<<4)|vga.svga.bank_write; -} - -void write_p3c0_et4k(Bitu reg,Bitu val,Bitu iolen) { - switch(reg) { - // 3c0 index 16h: ATC Miscellaneous - // VGADOC provides a lot of information, Ferarro documents only two bits - // and even those incompletely. The register is used as part of identification - // scheme. - // Unlikely to be used by any games but double timing may be useful. - // TODO: Figure out if this has any practical use - STORE_ET4K(3c0, 16); - /* - 3C0h index 17h (R/W): Miscellaneous 1 - bit 7 If set protects the internal palette ram and redefines the attribute - bits as follows: - Monochrome: - bit 0-2 Select font 0-7 - 3 If set selects blinking - 4 If set selects underline - 5 If set prevents the character from being displayed - 6 If set displays the character at half intensity - 7 If set selects reverse video - Color: - bit 0-1 Selects font 0-3 - 2 Foreground Blue - 3 Foreground Green - 4 Foreground Red - 5 Background Blue - 6 Background Green - 7 Background Red - */ - // TODO: Figure out if this has any practical use - STORE_ET4K(3c0, 17); - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:ET4K:Write to illegal index %2X", reg); - break; - } -} - -Bitu read_p3c1_et4k(Bitu reg,Bitu iolen) { - switch(reg) { - RESTORE_ET4K(3c0, 16); - RESTORE_ET4K(3c0, 17); - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:ET4K:Read from illegal index %2X", reg); - break; - } - return 0x0; -} - -/* -These ports are used but have little if any effect on emulation: - 3BFh (R/W): Hercules Compatibility Mode - 3CBh (R/W): PEL Address/Data Wd - 3CEh index 0Dh (R/W): Microsequencer Mode - 3CEh index 0Eh (R/W): Microsequencer Reset - 3d8h (R/W): Display Mode Control - 3DEh (W); AT&T Mode Control Register -*/ - -static Bitu get_clock_index_et4k() { - // Ignoring bit 4, using "only" 16 frequencies. Looks like most implementations had only that - return ((vga.misc_output>>2)&3) | ((et4k.store_3d4_34<<1)&4) | ((et4k.store_3d4_31>>3)&8); -} - -static void set_clock_index_et4k(Bitu index) { - // Shortwiring register reads/writes for simplicity - IO_Write(0x3c2, (vga.misc_output&~0x0c)|((index&3)<<2)); - et4k.store_3d4_34 = (et4k.store_3d4_34&~0x02)|((index&4)>>1); - et4k.store_3d4_31 = (et4k.store_3d4_31&~0xc0)|((index&8)<<3); // (index&0x18) if 32 clock frequencies are to be supported -} - -void FinishSetMode_ET4K(Bitu crtc_base, VGA_ModeExtraData* modeData) { - et4k.biosMode = modeData->modeNo; - - IO_Write(0x3cd, 0x00); // both banks to 0 - - // Reinterpret hor_overflow. Curiously, three bits out of four are - // in the same places. Input has hdispend (not supported), output - // has CRTC offset (also not supported) - Bit8u et4k_hor_overflow = - (modeData->hor_overflow & 0x01) | - (modeData->hor_overflow & 0x04) | - (modeData->hor_overflow & 0x10); - IO_Write(crtc_base,0x3f);IO_Write(crtc_base+1,et4k_hor_overflow); - - // Reinterpret ver_overflow - Bit8u et4k_ver_overflow = - ((modeData->ver_overflow & 0x01) << 1) | // vtotal10 - ((modeData->ver_overflow & 0x02) << 1) | // vdispend10 - ((modeData->ver_overflow & 0x04) >> 2) | // vbstart10 - ((modeData->ver_overflow & 0x10) >> 1) | // vretrace10 (tseng has vsync start?) - ((modeData->ver_overflow & 0x40) >> 2); // line_compare - IO_Write(crtc_base,0x35);IO_Write(crtc_base+1,et4k_ver_overflow); - - // Clear remaining ext CRTC registers - IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,0); - IO_Write(crtc_base,0x32);IO_Write(crtc_base+1,0); - IO_Write(crtc_base,0x33);IO_Write(crtc_base+1,0); - IO_Write(crtc_base,0x34);IO_Write(crtc_base+1,0); - IO_Write(crtc_base,0x36);IO_Write(crtc_base+1,0); - IO_Write(crtc_base,0x37);IO_Write(crtc_base+1,0x0c|(vga.vmemsize==1024*1024?3:vga.vmemsize==512*1024?2:1)); - // Clear ext SEQ - IO_Write(0x3c4,0x06);IO_Write(0x3c5,0); - IO_Write(0x3c4,0x07);IO_Write(0x3c5,0); - // Clear ext ATTR - IO_Write(0x3c0,0x16);IO_Write(0x3c0,0); - IO_Write(0x3c0,0x17);IO_Write(0x3c0,0); - - // Select SVGA clock to get close to 60Hz (not particularly clean implementation) - if (modeData->modeNo > 0x13) { - Bitu target = modeData->vtotal*8*modeData->htotal*60; - Bitu best = 1; - Bits dist = 100000000; - for (Bitu i=0; i<16; i++) { - if (abs(target-et4k.clockFreq[i]) < dist) { - best = i; - dist = abs(target-et4k.clockFreq[i]); - } - } - set_clock_index_et4k(best); - } - - if(svga.determine_mode) - svga.determine_mode(); - - // Verified (on real hardware and in a few games): Tseng ET4000 used chain4 implementation - // different from standard VGA. It was also not limited to 64K in regular mode 13h. - vga.config.compatible_chain4 = false; - vga.vmemwrap = vga.vmemsize; - - VGA_SetupHandlers(); -} - -void DetermineMode_ET4K() { - // Close replica from the base implementation. It will stay here - // until I figure a way to either distinguish M_VGA and M_LIN8 or - // merge them. - if (vga.attr.mode_control & 1) { - if (vga.gfx.mode & 0x40) VGA_SetMode((et4k.biosMode<=0x13)?M_VGA:M_LIN8); // Ugly... - else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4); - else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2); - else VGA_SetMode((et4k.biosMode<=0x13)?M_EGA:M_LIN4); - } else { - VGA_SetMode(M_TEXT); - } -} - -void SetClock_ET4K(Bitu which,Bitu target) { - et4k.clockFreq[which]=1000*target; - VGA_StartResize(); -} - -Bitu GetClock_ET4K() { - return et4k.clockFreq[get_clock_index_et4k()]; -} - -bool AcceptsMode_ET4K(Bitu mode) { - return VideoModeMemSize(mode) < vga.vmemsize; -// return mode != 0x3d; -} - -void SVGA_Setup_TsengET4K(void) { - svga.write_p3d5 = &write_p3d5_et4k; - svga.read_p3d5 = &read_p3d5_et4k; - svga.write_p3c5 = &write_p3c5_et4k; - svga.read_p3c5 = &read_p3c5_et4k; - svga.write_p3c0 = &write_p3c0_et4k; - svga.read_p3c1 = &read_p3c1_et4k; - - svga.set_video_mode = &FinishSetMode_ET4K; - svga.determine_mode = &DetermineMode_ET4K; - svga.set_clock = &SetClock_ET4K; - svga.get_clock = &GetClock_ET4K; - svga.accepts_mode = &AcceptsMode_ET4K; - - // From the depths of X86Config, probably inexact - VGA_SetClock(0,CLK_25); - VGA_SetClock(1,CLK_28); - VGA_SetClock(2,32400); - VGA_SetClock(3,35900); - VGA_SetClock(4,39900); - VGA_SetClock(5,44700); - VGA_SetClock(6,31400); - VGA_SetClock(7,37500); - VGA_SetClock(8,50000); - VGA_SetClock(9,56500); - VGA_SetClock(10,64900); - VGA_SetClock(11,71900); - VGA_SetClock(12,79900); - VGA_SetClock(13,89600); - VGA_SetClock(14,62800); - VGA_SetClock(15,74800); - - IO_RegisterReadHandler(0x3cd,read_p3cd_et4k,IO_MB); - IO_RegisterWriteHandler(0x3cd,write_p3cd_et4k,IO_MB); - - // Default to 1M of VRAM - if (vga.vmemsize == 0) - vga.vmemsize = 1024*1024; - - if (vga.vmemsize < 512*1024) - vga.vmemsize = 256*1024; - else if (vga.vmemsize < 1024*1024) - vga.vmemsize = 512*1024; - else - vga.vmemsize = 1024*1024; - - // Tseng ROM signature - PhysPt rom_base=PhysMake(0xc000,0); - phys_writeb(rom_base+0x0075,' '); - phys_writeb(rom_base+0x0076,'T'); - phys_writeb(rom_base+0x0077,'s'); - phys_writeb(rom_base+0x0078,'e'); - phys_writeb(rom_base+0x0079,'n'); - phys_writeb(rom_base+0x007a,'g'); - phys_writeb(rom_base+0x007b,' '); -} - - -// Tseng ET3K implementation -typedef struct { -// Stored exact values of some registers. Documentation only specifies some bits but hardware checks may -// expect other bits to be preserved. - Bitu store_3d4_1b; - Bitu store_3d4_1c; - Bitu store_3d4_1d; - Bitu store_3d4_1e; - Bitu store_3d4_1f; - Bitu store_3d4_20; - Bitu store_3d4_21; - Bitu store_3d4_23; // note that 22 is missing - Bitu store_3d4_24; - Bitu store_3d4_25; - - Bitu store_3c0_16; - Bitu store_3c0_17; - - Bitu store_3c4_06; - Bitu store_3c4_07; - - Bitu clockFreq[8]; - Bitu biosMode; -} SVGA_ET3K_DATA; - -static SVGA_ET3K_DATA et3k = { 0,0,0,0,0,0,0,0,0,0, 0,0, 0,0, {0,0,0,0,0,0,0,0}, 0 }; - -#define STORE_ET3K(port, index) \ - case 0x##index: \ - et3k.store_##port##_##index = val; \ - break; - -#define RESTORE_ET3K(port, index) \ - case 0x##index: \ - return et3k.store_##port##_##index; - - -void write_p3d5_et3k(Bitu reg,Bitu val,Bitu iolen) { - switch(reg) { - // 3d4 index 1bh-21h: Hardware zoom control registers - // I am not sure if there was a piece of software that used these. - // Not implemented and will probably stay this way. - STORE_ET3K(3d4, 1b); - STORE_ET3K(3d4, 1c); - STORE_ET3K(3d4, 1d); - STORE_ET3K(3d4, 1e); - STORE_ET3K(3d4, 1f); - STORE_ET3K(3d4, 20); - STORE_ET3K(3d4, 21); - - case 0x23: - /* - 3d4h index 23h (R/W): Extended start ET3000 - bit 0 Cursor start address bit 16 - 1 Display start address bit 16 - 2 Zoom start address bit 16 - 7 If set memory address 8 is output on the MBSL pin (allowing access to - 1MB), if clear the blanking signal is output. - */ - // Only bits 1 and 2 are supported. Bit 2 is related to hardware zoom, bit 7 is too obscure to be useful - et3k.store_3d4_23 = val; - vga.config.display_start = (vga.config.display_start & 0xffff) | ((val & 0x02)<<15); - vga.config.cursor_start = (vga.config.cursor_start & 0xffff) | ((val & 0x01)<<16); - break; - - - /* - 3d4h index 24h (R/W): Compatibility Control - bit 0 Enable Clock Translate if set - 1 Clock Select bit 2. Bits 0-1 are in 3C2h/3CCh. - 2 Enable tri-state for all output pins if set - 3 Enable input A8 of 1MB DRAMs from the INTL output if set - 4 Reserved - 5 Enable external ROM CRTC translation if set - 6 Enable Double Scan and Underline Attribute if set - 7 Enable 6845 compatibility if set. - */ - // TODO: Some of these may be worth implementing. - STORE_ET3K(3d4, 24); - - - case 0x25: - /* - 3d4h index 25h (R/W): Overflow High - bit 0 Vertical Blank Start bit 10 - 1 Vertical Total Start bit 10 - 2 Vertical Display End bit 10 - 3 Vertical Sync Start bit 10 - 4 Line Compare bit 10 - 5-6 Reserved - 7 Vertical Interlace if set - */ - et3k.store_3d4_25 = val; - vga.config.line_compare = (vga.config.line_compare & 0x3ff) | ((val&0x10)<<6); - // Abusing s3 ex_ver_overflow field. This is to be cleaned up later. - { - Bit8u s3val = - ((val & 0x01) << 2) | // vbstart - ((val & 0x02) >> 1) | // vtotal - ((val & 0x04) >> 1) | // vdispend - ((val & 0x08) << 1) | // vsyncstart (?) - ((val & 0x10) << 2); // linecomp - if ((s3val ^ vga.s3.ex_ver_overflow) & 0x3) { - vga.s3.ex_ver_overflow=s3val; - VGA_StartResize(); - } else vga.s3.ex_ver_overflow=s3val; - } - break; - - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:ET3K:Write to illegal index %2X", reg); - break; - } -} - -Bitu read_p3d5_et3k(Bitu reg,Bitu iolen) { - switch(reg) { - RESTORE_ET3K(3d4, 1b); - RESTORE_ET3K(3d4, 1c); - RESTORE_ET3K(3d4, 1d); - RESTORE_ET3K(3d4, 1e); - RESTORE_ET3K(3d4, 1f); - RESTORE_ET3K(3d4, 20); - RESTORE_ET3K(3d4, 21); - RESTORE_ET3K(3d4, 23); - RESTORE_ET3K(3d4, 24); - RESTORE_ET3K(3d4, 25); - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:ET3K:Read from illegal index %2X", reg); - break; - } - return 0x0; -} - -void write_p3c5_et3k(Bitu reg,Bitu val,Bitu iolen) { - switch(reg) { - // Both registers deal mostly with hardware zoom which is not implemented. Other bits - // seem to be useless for emulation with the exception of index 7 bit 4 (font select) - STORE_ET3K(3c4, 06); - STORE_ET3K(3c4, 07); - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:ET3K:Write to illegal index %2X", reg); - break; - } -} - -Bitu read_p3c5_et3k(Bitu reg,Bitu iolen) { - switch(reg) { - RESTORE_ET3K(3c4, 06); - RESTORE_ET3K(3c4, 07); - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:ET3K:Read from illegal index %2X", reg); - break; - } - return 0x0; -} - -/* -3CDh (R/W): Segment Select -bit 0-2 64k Write bank number - 3-5 64k Read bank number - 6-7 Segment Configuration. - 0 128K segments - 1 64K segments - 2 1M linear memory -NOTES: 1M linear memory is not supported -*/ -void write_p3cd_et3k(Bitu port,Bitu val,Bitu iolen) { - vga.svga.bank_write = val & 0x07; - vga.svga.bank_read = (val>>3) & 0x07; - vga.svga.bank_size = (val&0x40)?64*1024:128*1024; - VGA_SetupHandlers(); -} - -Bitu read_p3cd_et3k(Bitu port,Bitu iolen) { - return (vga.svga.bank_read<<3)|vga.svga.bank_write|((vga.svga.bank_size==128*1024)?0:0x40); -} - -void write_p3c0_et3k(Bitu reg,Bitu val,Bitu iolen) { -// See ET4K notes. - switch(reg) { - STORE_ET3K(3c0, 16); - STORE_ET3K(3c0, 17); - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:ET3K:Write to illegal index %2X", reg); - break; - } -} - -Bitu read_p3c1_et3k(Bitu reg,Bitu iolen) { - switch(reg) { - RESTORE_ET3K(3c0, 16); - RESTORE_ET3K(3c0, 17); - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:ET3K:Read from illegal index %2X", reg); - break; - } - return 0x0; -} - -/* -These ports are used but have little if any effect on emulation: - 3B8h (W): Display Mode Control Register - 3BFh (R/W): Hercules Compatibility Mode - 3CBh (R/W): PEL Address/Data Wd - 3CEh index 0Dh (R/W): Microsequencer Mode - 3CEh index 0Eh (R/W): Microsequencer Reset - 3d8h (R/W): Display Mode Control - 3D9h (W): Color Select Register - 3dAh (W): Feature Control Register - 3DEh (W); AT&T Mode Control Register -*/ - -static Bitu get_clock_index_et3k() { - return ((vga.misc_output>>2)&3) | ((et3k.store_3d4_24<<1)&4); -} - -static void set_clock_index_et3k(Bitu index) { - // Shortwiring register reads/writes for simplicity - IO_Write(0x3c2, (vga.misc_output&~0x0c)|((index&3)<<2)); - et3k.store_3d4_24 = (et3k.store_3d4_24&~0x02)|((index&4)>>1); -} - -void FinishSetMode_ET3K(Bitu crtc_base, VGA_ModeExtraData* modeData) { - et3k.biosMode = modeData->modeNo; - - IO_Write(0x3cd, 0x40); // both banks to 0, 64K bank size - - // Tseng ET3K does not have horizontal overflow bits - // Reinterpret ver_overflow - Bit8u et4k_ver_overflow = - ((modeData->ver_overflow & 0x01) << 1) | // vtotal10 - ((modeData->ver_overflow & 0x02) << 1) | // vdispend10 - ((modeData->ver_overflow & 0x04) >> 2) | // vbstart10 - ((modeData->ver_overflow & 0x10) >> 1) | // vretrace10 (tseng has vsync start?) - ((modeData->ver_overflow & 0x40) >> 2); // line_compare - IO_Write(crtc_base,0x25);IO_Write(crtc_base+1,et4k_ver_overflow); - - // Clear remaining ext CRTC registers - for (Bitu i=0x16; i<=0x21; i++) - IO_Write(crtc_base,i);IO_Write(crtc_base+1,0); - IO_Write(crtc_base,0x23);IO_Write(crtc_base+1,0); - IO_Write(crtc_base,0x24);IO_Write(crtc_base+1,0); - // Clear ext SEQ - IO_Write(0x3c4,0x06);IO_Write(0x3c5,0); - IO_Write(0x3c4,0x07);IO_Write(0x3c5,0x40); // 0 in this register breaks WHATVGA - // Clear ext ATTR - IO_Write(0x3c0,0x16);IO_Write(0x3c0,0); - IO_Write(0x3c0,0x17);IO_Write(0x3c0,0); - - // Select SVGA clock to get close to 60Hz (not particularly clean implementation) - if (modeData->modeNo > 0x13) { - Bitu target = modeData->vtotal*8*modeData->htotal*60; - Bitu best = 1; - Bits dist = 100000000; - for (Bitu i=0; i<8; i++) { - if (abs(target-et3k.clockFreq[i]) < dist) { - best = i; - dist = abs(target-et3k.clockFreq[i]); - } - } - set_clock_index_et3k(best); - } - - if (svga.determine_mode) - svga.determine_mode(); - - // Verified on functioning (at last!) hardware: Tseng ET3000 is the same as ET4000 when - // it comes to chain4 architecture - vga.config.compatible_chain4 = false; - vga.vmemwrap = vga.vmemsize; - - VGA_SetupHandlers(); -} - -void DetermineMode_ET3K() { - // Close replica from the base implementation. It will stay here - // until I figure a way to either distinguish M_VGA and M_LIN8 or - // merge them. - if (vga.attr.mode_control & 1) { - if (vga.gfx.mode & 0x40) VGA_SetMode((et3k.biosMode<=0x13)?M_VGA:M_LIN8); // Ugly... - else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4); - else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2); - else VGA_SetMode((et3k.biosMode<=0x13)?M_EGA:M_LIN4); - } else { - VGA_SetMode(M_TEXT); - } -} - -void SetClock_ET3K(Bitu which,Bitu target) { - et3k.clockFreq[which]=1000*target; - VGA_StartResize(); -} - -Bitu GetClock_ET3K() { - return et3k.clockFreq[get_clock_index_et3k()]; -} - -bool AcceptsMode_ET3K(Bitu mode) { - return mode <= 0x37 && mode != 0x2f && VideoModeMemSize(mode) < vga.vmemsize; -} - -void SVGA_Setup_TsengET3K(void) { - svga.write_p3d5 = &write_p3d5_et3k; - svga.read_p3d5 = &read_p3d5_et3k; - svga.write_p3c5 = &write_p3c5_et3k; - svga.read_p3c5 = &read_p3c5_et3k; - svga.write_p3c0 = &write_p3c0_et3k; - svga.read_p3c1 = &read_p3c1_et3k; - - svga.set_video_mode = &FinishSetMode_ET3K; - svga.determine_mode = &DetermineMode_ET3K; - svga.set_clock = &SetClock_ET3K; - svga.get_clock = &GetClock_ET3K; - svga.accepts_mode = &AcceptsMode_ET3K; - - VGA_SetClock(0,CLK_25); - VGA_SetClock(1,CLK_28); - VGA_SetClock(2,32400); - VGA_SetClock(3,35900); - VGA_SetClock(4,39900); - VGA_SetClock(5,44700); - VGA_SetClock(6,31400); - VGA_SetClock(7,37500); - - IO_RegisterReadHandler(0x3cd,read_p3cd_et3k,IO_MB); - IO_RegisterWriteHandler(0x3cd,write_p3cd_et3k,IO_MB); - - vga.vmemsize = 512*1024; // Cannot figure how this was supposed to work on the real card - - // Tseng ROM signature - PhysPt rom_base=PhysMake(0xc000,0); - phys_writeb(rom_base+0x0075,' '); - phys_writeb(rom_base+0x0076,'T'); - phys_writeb(rom_base+0x0077,'s'); - phys_writeb(rom_base+0x0078,'e'); - phys_writeb(rom_base+0x0079,'n'); - phys_writeb(rom_base+0x007a,'g'); - phys_writeb(rom_base+0x007b,' '); -} diff --git a/src/hardware/vga_xga.cpp b/src/hardware/vga_xga.cpp deleted file mode 100644 index 41f9615..0000000 --- a/src/hardware/vga_xga.cpp +++ /dev/null @@ -1,1320 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: vga_xga.cpp,v 1.16 2008/08/21 09:10:31 c2woody Exp $ */ - -#include -#include "dosbox.h" -#include "inout.h" -#include "vga.h" -#include -#include -#include "callback.h" -#include "cpu.h" // for 0x3da delay - -#define XGA_SCREEN_WIDTH vga.s3.xga_screen_width -#define XGA_COLOR_MODE vga.s3.xga_color_mode - -#define XGA_SHOW_COMMAND_TRACE 0 - -struct XGAStatus { - struct scissorreg { - Bit16u x1, y1, x2, y2; - } scissors; - - Bit32u readmask; - Bit32u writemask; - - Bit32u forecolor; - Bit32u backcolor; - - Bitu curcommand; - - Bit16u foremix; - Bit16u backmix; - - Bit16u curx, cury; - Bit16u destx, desty; - - Bit16u ErrTerm; - Bit16u MIPcount; - Bit16u MAPcount; - - Bit16u pix_cntl; - Bit16u control1; - Bit16u control2; - Bit16u read_sel; - - struct XGA_WaitCmd { - bool newline; - bool wait; - Bit16u cmd; - Bit16u curx, cury; - Bit16u x1, y1, x2, y2, sizex, sizey; - Bit32u data; /* transient data passed by multiple calls */ - Bitu datasize; - Bitu buswidth; - } waitcmd; - -} xga; - -void XGA_Write_Multifunc(Bitu val, Bitu len) { - Bitu regselect = val >> 12; - Bitu dataval = val & 0xfff; - switch(regselect) { - case 0: // minor axis pixel count - xga.MIPcount = dataval; - break; - case 1: // top scissors - xga.scissors.y1 = dataval; - break; - case 2: // left - xga.scissors.x1 = dataval; - break; - case 3: // bottom - xga.scissors.y2 = dataval; - break; - case 4: // right - xga.scissors.x2 = dataval; - break; - case 0xa: // data manip control - xga.pix_cntl = dataval; - break; - case 0xd: // misc 2 - xga.control2 = dataval; - break; - case 0xe: - xga.control1 = dataval; - break; - case 0xf: - xga.read_sel = dataval; - break; - default: - LOG_MSG("XGA: Unhandled multifunction command %x", regselect); - break; - } -} - -Bitu XGA_Read_Multifunc() { - switch(xga.read_sel++) { - case 0: return xga.MIPcount; - case 1: return xga.scissors.y1; - case 2: return xga.scissors.x1; - case 3: return xga.scissors.y2; - case 4: return xga.scissors.x2; - case 5: return xga.pix_cntl; - case 6: return xga.control1; - case 7: return 0; // TODO - case 8: return 0; // TODO - case 9: return 0; // TODO - case 10: return xga.control2; - default: return 0; - } -} - - -void XGA_DrawPoint(Bitu x, Bitu y, Bitu c) { - if(!(xga.curcommand & 0x1)) return; - if(!(xga.curcommand & 0x10)) return; - - if(x < xga.scissors.x1) return; - if(x > xga.scissors.x2) return; - if(y < xga.scissors.y1) return; - if(y > xga.scissors.y2) return; - - Bit32u memaddr = (y * XGA_SCREEN_WIDTH) + x; - /* Need to zero out all unused bits in modes that have any (15-bit or "32"-bit -- the last - one is actually 24-bit. Without this step there may be some graphics corruption (mainly, - during windows dragging. */ - switch(XGA_COLOR_MODE) { - case M_LIN8: - if (GCC_UNLIKELY(memaddr >= vga.vmemsize)) break; - vga.mem.linear[memaddr] = c; - break; - case M_LIN15: - if (GCC_UNLIKELY(memaddr*2 >= vga.vmemsize)) break; - ((Bit16u*)(vga.mem.linear))[memaddr] = (Bit16u)(c&0x7fff); - break; - case M_LIN16: - if (GCC_UNLIKELY(memaddr*2 >= vga.vmemsize)) break; - ((Bit16u*)(vga.mem.linear))[memaddr] = (Bit16u)(c&0xffff); - break; - case M_LIN32: - if (GCC_UNLIKELY(memaddr*4 >= vga.vmemsize)) break; - ((Bit32u*)(vga.mem.linear))[memaddr] = c; - break; - default: - break; - } - -} - -Bitu XGA_GetPoint(Bitu x, Bitu y) { - Bit32u memaddr = (y * XGA_SCREEN_WIDTH) + x; - - switch(XGA_COLOR_MODE) { - case M_LIN8: - if (GCC_UNLIKELY(memaddr >= vga.vmemsize)) break; - return vga.mem.linear[memaddr]; - case M_LIN15: - case M_LIN16: - if (GCC_UNLIKELY(memaddr*2 >= vga.vmemsize)) break; - return ((Bit16u*)(vga.mem.linear))[memaddr]; - case M_LIN32: - if (GCC_UNLIKELY(memaddr*4 >= vga.vmemsize)) break; - return ((Bit32u*)(vga.mem.linear))[memaddr]; - default: - break; - } - return 0; -} - - -Bitu XGA_GetMixResult(Bitu mixmode, Bitu srcval, Bitu dstdata) { - Bitu destval = 0; - switch(mixmode & 0xf) { - case 0x00: /* not DST */ - destval = ~dstdata; - break; - case 0x01: /* 0 (false) */ - destval = 0; - break; - case 0x02: /* 1 (true) */ - destval = 0xffffffff; - break; - case 0x03: /* 2 DST */ - destval = dstdata; - break; - case 0x04: /* not SRC */ - destval = ~srcval; - break; - case 0x05: /* SRC xor DST */ - destval = srcval ^ dstdata; - break; - case 0x06: /* not (SRC xor DST) */ - destval = ~(srcval ^ dstdata); - break; - case 0x07: /* SRC */ - destval = srcval; - break; - case 0x08: /* not (SRC and DST) */ - destval = ~(srcval & dstdata); - break; - case 0x09: /* (not SRC) or DST */ - destval = (~srcval) | dstdata; - break; - case 0x0a: /* SRC or (not DST) */ - destval = srcval | (~dstdata); - break; - case 0x0b: /* SRC or DST */ - destval = srcval | dstdata; - break; - case 0x0c: /* SRC and DST */ - destval = srcval & dstdata; - break; - case 0x0d: /* SRC and (not DST) */ - destval = srcval & (~dstdata); - break; - case 0x0e: /* (not SRC) and DST */ - destval = (~srcval) & dstdata; - break; - case 0x0f: /* not (SRC or DST) */ - destval = ~(srcval | dstdata); - break; - default: - LOG_MSG("XGA: GetMixResult: Unknown mix. Shouldn't be able to get here!"); - break; - } - return destval; -} - -void XGA_DrawLineVector(Bitu val) { - Bits xat, yat; - Bitu srcval; - Bitu destval; - Bitu dstdata; - Bits i; - - Bits dx, sx, sy; - - dx = xga.MAPcount; - xat = xga.curx; - yat = xga.cury; - - switch((val >> 5) & 0x7) { - case 0x00: /* 0 degrees */ - sx = 1; - sy = 0; - break; - case 0x01: /* 45 degrees */ - sx = 1; - sy = -1; - break; - case 0x02: /* 90 degrees */ - sx = 0; - sy = -1; - break; - case 0x03: /* 135 degrees */ - sx = -1; - sy = -1; - break; - case 0x04: /* 180 degrees */ - sx = -1; - sy = 0; - break; - case 0x05: /* 225 degrees */ - sx = -1; - sy = 1; - break; - case 0x06: /* 270 degrees */ - sx = 0; - sy = 1; - break; - case 0x07: /* 315 degrees */ - sx = 1; - sy = 1; - break; - default: // Should never get here - sx = 0; - sy = 0; - break; - } - - for (i=0;i<=dx;i++) { - Bitu mixmode = (xga.pix_cntl >> 6) & 0x3; - switch (mixmode) { - case 0x00: /* FOREMIX always used */ - mixmode = xga.foremix; - switch((mixmode >> 5) & 0x03) { - case 0x00: /* Src is background color */ - srcval = xga.backcolor; - break; - case 0x01: /* Src is foreground color */ - srcval = xga.forecolor; - break; - case 0x02: /* Src is pixel data from PIX_TRANS register */ - //srcval = tmpval; - //LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register"); - break; - case 0x03: /* Src is bitmap data */ - LOG_MSG("XGA: DrawRect: Wants data from srcdata"); - //srcval = srcdata; - break; - default: - LOG_MSG("XGA: DrawRect: Shouldn't be able to get here!"); - break; - } - dstdata = XGA_GetPoint(xat,yat); - - destval = XGA_GetMixResult(mixmode, srcval, dstdata); - - XGA_DrawPoint(xat,yat, destval); - break; - default: - LOG_MSG("XGA: DrawLine: Needs mixmode %x", mixmode); - break; - } - xat += sx; - yat += sy; - } - - xga.curx = xat-1; - xga.cury = yat; -} - -void XGA_DrawLineBresenham(Bitu val) { - Bits xat, yat; - Bitu srcval; - Bitu destval; - Bitu dstdata; - Bits i; - Bits tmpswap; - bool steep; - -#define SWAP(a,b) tmpswap = a; a = b; b = tmpswap; - - Bits dx, sx, dy, sy, e, dmajor, dminor,destxtmp; - - // Probably a lot easier way to do this, but this works. - - dminor = (Bits)((Bit16s)xga.desty); - if(xga.desty&0x2000) dminor |= 0xffffe000; - dminor >>= 1; - - destxtmp=(Bits)((Bit16s)xga.destx); - if(xga.destx&0x2000) destxtmp |= 0xffffe000; - - - dmajor = -(destxtmp - (dminor << 1)) >> 1; - - dx = dmajor; - if((val >> 5) & 0x1) { - sx = 1; - } else { - sx = -1; - } - dy = dminor; - if((val >> 7) & 0x1) { - sy = 1; - } else { - sy = -1; - } - e = (Bits)((Bit16s)xga.ErrTerm); - if(xga.ErrTerm&0x2000) e |= 0xffffe000; - xat = xga.curx; - yat = xga.cury; - - if((val >> 6) & 0x1) { - steep = false; - SWAP(xat, yat); - SWAP(sx, sy); - } else { - steep = true; - } - - //LOG_MSG("XGA: Bresenham: ASC %d, LPDSC %d, sx %d, sy %d, err %d, steep %d, length %d, dmajor %d, dminor %d, xstart %d, ystart %d", dx, dy, sx, sy, e, steep, xga.MAPcount, dmajor, dminor,xat,yat); - - for (i=0;i<=xga.MAPcount;i++) { - Bitu mixmode = (xga.pix_cntl >> 6) & 0x3; - switch (mixmode) { - case 0x00: /* FOREMIX always used */ - mixmode = xga.foremix; - switch((mixmode >> 5) & 0x03) { - case 0x00: /* Src is background color */ - srcval = xga.backcolor; - break; - case 0x01: /* Src is foreground color */ - srcval = xga.forecolor; - break; - case 0x02: /* Src is pixel data from PIX_TRANS register */ - //srcval = tmpval; - LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register"); - break; - case 0x03: /* Src is bitmap data */ - LOG_MSG("XGA: DrawRect: Wants data from srcdata"); - //srcval = srcdata; - break; - default: - LOG_MSG("XGA: DrawRect: Shouldn't be able to get here!"); - break; - } - - if(steep) { - dstdata = XGA_GetPoint(xat,yat); - } else { - dstdata = XGA_GetPoint(yat,xat); - } - - destval = XGA_GetMixResult(mixmode, srcval, dstdata); - - if(steep) { - XGA_DrawPoint(xat,yat, destval); - } else { - XGA_DrawPoint(yat,xat, destval); - } - - break; - default: - LOG_MSG("XGA: DrawLine: Needs mixmode %x", mixmode); - break; - } - while (e > 0) { - yat += sy; - e -= (dx << 1); - } - xat += sx; - e += (dy << 1); - } - - if(steep) { - xga.curx = xat; - xga.cury = yat; - } else { - xga.curx = yat; - xga.cury = xat; - } - // } - //} - -} - -void XGA_DrawRectangle(Bitu val) { - Bit32u xat, yat; - Bitu srcval; - Bitu destval; - Bitu dstdata; - - Bits srcx, srcy, dx, dy; - - dx = -1; - dy = -1; - - if(((val >> 5) & 0x01) != 0) dx = 1; - if(((val >> 7) & 0x01) != 0) dy = 1; - - srcy = xga.cury; - - for(yat=0;yat<=xga.MIPcount;yat++) { - srcx = xga.curx; - for(xat=0;xat<=xga.MAPcount;xat++) { - Bitu mixmode = (xga.pix_cntl >> 6) & 0x3; - switch (mixmode) { - case 0x00: /* FOREMIX always used */ - mixmode = xga.foremix; - switch((mixmode >> 5) & 0x03) { - case 0x00: /* Src is background color */ - srcval = xga.backcolor; - break; - case 0x01: /* Src is foreground color */ - srcval = xga.forecolor; - break; - case 0x02: /* Src is pixel data from PIX_TRANS register */ - //srcval = tmpval; - LOG_MSG("XGA: DrawRect: Wants data from PIX_TRANS register"); - break; - case 0x03: /* Src is bitmap data */ - LOG_MSG("XGA: DrawRect: Wants data from srcdata"); - //srcval = srcdata; - break; - default: - LOG_MSG("XGA: DrawRect: Shouldn't be able to get here!"); - break; - } - dstdata = XGA_GetPoint(srcx,srcy); - - destval = XGA_GetMixResult(mixmode, srcval, dstdata); - - XGA_DrawPoint(srcx,srcy, destval); - break; - default: - LOG_MSG("XGA: DrawRect: Needs mixmode %x", mixmode); - break; - } - srcx += dx; - } - srcy += dy; - } - xga.curx = srcx; - xga.cury = srcy; - - //LOG_MSG("XGA: Draw rect (%d, %d)-(%d, %d), %d", x1, y1, x2, y2, xga.forecolor); -} - -bool XGA_CheckX(void) { - bool newline = false; - if(!xga.waitcmd.newline) { - - if((xga.waitcmd.curx<2048) && xga.waitcmd.curx > (xga.waitcmd.x2)) { - xga.waitcmd.curx = xga.waitcmd.x1; - xga.waitcmd.cury++; - xga.waitcmd.cury&=0x0fff; - newline = true; - xga.waitcmd.newline = true; - if((xga.waitcmd.cury<2048)&&(xga.waitcmd.cury > xga.waitcmd.y2)) - xga.waitcmd.wait = false; - } else if(xga.waitcmd.curx>=2048) { - Bit16u realx = 4096-xga.waitcmd.curx; - if(xga.waitcmd.x2>2047) { // x end is negative too - Bit16u realxend=4096-xga.waitcmd.x2; - if(realx==realxend) { - xga.waitcmd.curx = xga.waitcmd.x1; - xga.waitcmd.cury++; - xga.waitcmd.cury&=0x0fff; - newline = true; - xga.waitcmd.newline = true; - if((xga.waitcmd.cury<2048)&&(xga.waitcmd.cury > xga.waitcmd.y2)) - xga.waitcmd.wait = false; - } - } else { // else overlapping - if(realx==xga.waitcmd.x2) { - xga.waitcmd.curx = xga.waitcmd.x1; - xga.waitcmd.cury++; - xga.waitcmd.cury&=0x0fff; - newline = true; - xga.waitcmd.newline = true; - if((xga.waitcmd.cury<2048)&&(xga.waitcmd.cury > xga.waitcmd.y2)) - xga.waitcmd.wait = false; - } - } - } - } else { - xga.waitcmd.newline = false; - } - return newline; -} - -void XGA_DrawWaitSub(Bitu mixmode, Bitu srcval) { - Bitu destval; - Bitu dstdata; - dstdata = XGA_GetPoint(xga.waitcmd.curx, xga.waitcmd.cury); - destval = XGA_GetMixResult(mixmode, srcval, dstdata); - //LOG_MSG("XGA: DrawPattern: Mixmode: %x srcval: %x", mixmode, srcval); - - XGA_DrawPoint(xga.waitcmd.curx, xga.waitcmd.cury, destval); - xga.waitcmd.curx++; - xga.waitcmd.curx&=0x0fff; - XGA_CheckX(); -} - -void XGA_DrawWait(Bitu val, Bitu len) { - if(!xga.waitcmd.wait) return; - Bitu mixmode = (xga.pix_cntl >> 6) & 0x3; - Bitu srcval; - switch(xga.waitcmd.cmd) { - case 2: /* Rectangle */ - switch(mixmode) { - case 0x00: /* FOREMIX always used */ - mixmode = xga.foremix; - -/* switch((mixmode >> 5) & 0x03) { - case 0x00: // Src is background color - srcval = xga.backcolor; - break; - case 0x01: // Src is foreground color - srcval = xga.forecolor; - break; - case 0x02: // Src is pixel data from PIX_TRANS register -*/ - if(((mixmode >> 5) & 0x03) != 0x2) { - // those cases don't seem to occur - LOG_MSG("XGA: unsupported drawwait operation"); - break; - } - switch(xga.waitcmd.buswidth) { - case M_LIN8: // 8 bit - XGA_DrawWaitSub(mixmode, val); - break; - case 0x20 | M_LIN8: // 16 bit - for(Bitu i = 0; i < len; i++) { - XGA_DrawWaitSub(mixmode, (val>>(8*i))&0xff); - if(xga.waitcmd.newline) break; - } - break; - case 0x40 | M_LIN8: // 32 bit - for(int i = 0; i < 4; i++) - XGA_DrawWaitSub(mixmode, (val>>(8*i))&0xff); - break; - case (0x20 | M_LIN32): - if(len!=4) { // Win 3.11 864 'hack?' - if(xga.waitcmd.datasize == 0) { - // set it up to wait for the next word - xga.waitcmd.data = val; - xga.waitcmd.datasize = 2; - return; - } else { - srcval = (val<<16)|xga.waitcmd.data; - xga.waitcmd.data = 0; - xga.waitcmd.datasize = 0; - XGA_DrawWaitSub(mixmode, srcval); - } - break; - } // fall-through - case 0x40 | M_LIN32: // 32 bit - XGA_DrawWaitSub(mixmode, val); - break; - case 0x20 | M_LIN15: // 16 bit - case 0x20 | M_LIN16: // 16 bit - XGA_DrawWaitSub(mixmode, val); - break; - case 0x40 | M_LIN15: // 32 bit - case 0x40 | M_LIN16: // 32 bit - XGA_DrawWaitSub(mixmode, val&0xffff); - if(!xga.waitcmd.newline) - XGA_DrawWaitSub(mixmode, val>>16); - break; - default: - // Let's hope they never show up ;) - LOG_MSG("XGA: unsupported bpp / datawidth combination %x", - xga.waitcmd.buswidth); - break; - }; - break; - - case 0x02: // Data from PIX_TRANS selects the mix - Bitu chunksize; - Bitu chunks; - switch(xga.waitcmd.buswidth&0x60) { - case 0x0: - chunksize=8; - chunks=1; - break; - case 0x20: // 16 bit - chunksize=16; - if(len==4) chunks=2; - else chunks = 1; - break; - case 0x40: // 32 bit - chunksize=16; - if(len==4) chunks=2; - else chunks = 1; - break; - case 0x60: // undocumented guess (but works) - chunksize=8; - chunks=4; - break; - } - - for(Bitu k = 0; k < chunks; k++) { // chunks counter - xga.waitcmd.newline = false; - for(Bitu n = 0; n < chunksize; n++) { // pixels - Bitu mixmode; - - // This formula can rule the world ;) - Bitu mask = 1 << ((((n&0xF8)+(8-(n&0x7)))-1)+chunksize*k); - if(val&mask) mixmode = xga.foremix; - else mixmode = xga.backmix; - - switch((mixmode >> 5) & 0x03) { - case 0x00: // Src is background color - srcval = xga.backcolor; - break; - case 0x01: // Src is foreground color - srcval = xga.forecolor; - break; - default: - LOG_MSG("XGA: DrawBlitWait: Unsupported src %x", - (mixmode >> 5) & 0x03); - srcval=0; - break; - } - XGA_DrawWaitSub(mixmode, srcval); - - if((xga.waitcmd.cury<2048) && - (xga.waitcmd.cury >= xga.waitcmd.y2)) { - xga.waitcmd.wait = false; - k=1000; // no more chunks - break; - } - // next chunk goes to next line - if(xga.waitcmd.newline) break; - } // pixels loop - } // chunks loop - break; - - default: - LOG_MSG("XGA: DrawBlitWait: Unhandled mixmode: %d", mixmode); - break; - } // switch mixmode - break; - default: - LOG_MSG("XGA: Unhandled draw command %x", xga.waitcmd.cmd); - break; - } -} - -void XGA_BlitRect(Bitu val) { - Bit32u xat, yat; - Bitu srcdata; - Bitu dstdata; - - Bitu srcval; - Bitu destval; - - Bits srcx, srcy, tarx, tary, dx, dy; - - dx = -1; - dy = -1; - - if(((val >> 5) & 0x01) != 0) dx = 1; - if(((val >> 7) & 0x01) != 0) dy = 1; - - srcx = xga.curx; - srcy = xga.cury; - tarx = xga.destx; - tary = xga.desty; - - Bitu mixselect = (xga.pix_cntl >> 6) & 0x3; - Bitu mixmode = 0x67; /* Source is bitmap data, mix mode is src */ - switch(mixselect) { - case 0x00: /* Foreground mix is always used */ - mixmode = xga.foremix; - break; - case 0x02: /* CPU Data determines mix used */ - LOG_MSG("XGA: DrawPattern: Mixselect data from PIX_TRANS register"); - break; - case 0x03: /* Video memory determines mix */ - //LOG_MSG("XGA: Srcdata: %x, Forecolor %x, Backcolor %x, Foremix: %x Backmix: %x", srcdata, xga.forecolor, xga.backcolor, xga.foremix, xga.backmix); - break; - default: - LOG_MSG("XGA: BlitRect: Unknown mix select register"); - break; - } - - - /* Copy source to video ram */ - for(yat=0;yat<=xga.MIPcount ;yat++) { - srcx = xga.curx; - tarx = xga.destx; - - for(xat=0;xat<=xga.MAPcount;xat++) { - srcdata = XGA_GetPoint(srcx, srcy); - dstdata = XGA_GetPoint(tarx, tary); - - if(mixselect == 0x3) { - if(srcdata == xga.forecolor) { - mixmode = xga.foremix; - } else { - if(srcdata == xga.backcolor) { - mixmode = xga.backmix; - } else { - /* Best guess otherwise */ - mixmode = 0x67; /* Source is bitmap data, mix mode is src */ - } - } - } - - switch((mixmode >> 5) & 0x03) { - case 0x00: /* Src is background color */ - srcval = xga.backcolor; - break; - case 0x01: /* Src is foreground color */ - srcval = xga.forecolor; - break; - case 0x02: /* Src is pixel data from PIX_TRANS register */ - LOG_MSG("XGA: DrawPattern: Wants data from PIX_TRANS register"); - break; - case 0x03: /* Src is bitmap data */ - srcval = srcdata; - break; - default: - LOG_MSG("XGA: DrawPattern: Shouldn't be able to get here!"); - srcval = 0; - break; - } - - destval = XGA_GetMixResult(mixmode, srcval, dstdata); - //LOG_MSG("XGA: DrawPattern: Mixmode: %x Mixselect: %x", mixmode, mixselect); - - XGA_DrawPoint(tarx, tary, destval); - - srcx += dx; - tarx += dx; - } - srcy += dy; - tary += dy; - } -} - -void XGA_DrawPattern(Bitu val) { - Bitu srcdata; - Bitu dstdata; - - Bitu srcval; - Bitu destval; - - Bits xat, yat, srcx, srcy, tarx, tary, dx, dy; - - dx = -1; - dy = -1; - - if(((val >> 5) & 0x01) != 0) dx = 1; - if(((val >> 7) & 0x01) != 0) dy = 1; - - srcx = xga.curx; - srcy = xga.cury; - - tary = xga.desty; - - Bitu mixselect = (xga.pix_cntl >> 6) & 0x3; - Bitu mixmode = 0x67; /* Source is bitmap data, mix mode is src */ - switch(mixselect) { - case 0x00: /* Foreground mix is always used */ - mixmode = xga.foremix; - break; - case 0x02: /* CPU Data determines mix used */ - LOG_MSG("XGA: DrawPattern: Mixselect data from PIX_TRANS register"); - break; - case 0x03: /* Video memory determines mix */ - //LOG_MSG("XGA: Pixctl: %x, Srcdata: %x, Forecolor %x, Backcolor %x, Foremix: %x Backmix: %x",xga.pix_cntl, srcdata, xga.forecolor, xga.backcolor, xga.foremix, xga.backmix); - break; - default: - LOG_MSG("XGA: DrawPattern: Unknown mix select register"); - break; - } - - for(yat=0;yat<=xga.MIPcount;yat++) { - tarx = xga.destx; - for(xat=0;xat<=xga.MAPcount;xat++) { - - srcdata = XGA_GetPoint(srcx + (tarx & 0x7), srcy + (tary & 0x7)); - //LOG_MSG("patternpoint (%3d/%3d)v%x",srcx + (tarx & 0x7), srcy + (tary & 0x7),srcdata); - dstdata = XGA_GetPoint(tarx, tary); - - - if(mixselect == 0x3) { - // TODO lots of guessing here but best results this way - /*if(srcdata == xga.forecolor)*/ mixmode = xga.foremix; - // else - if(srcdata == xga.backcolor || srcdata == 0) - mixmode = xga.backmix; - } - - switch((mixmode >> 5) & 0x03) { - case 0x00: /* Src is background color */ - srcval = xga.backcolor; - break; - case 0x01: /* Src is foreground color */ - srcval = xga.forecolor; - break; - case 0x02: /* Src is pixel data from PIX_TRANS register */ - LOG_MSG("XGA: DrawPattern: Wants data from PIX_TRANS register"); - break; - case 0x03: /* Src is bitmap data */ - srcval = srcdata; - break; - default: - LOG_MSG("XGA: DrawPattern: Shouldn't be able to get here!"); - srcval = 0; - break; - } - - destval = XGA_GetMixResult(mixmode, srcval, dstdata); - - XGA_DrawPoint(tarx, tary, destval); - - tarx += dx; - } - tary += dy; - } -} - -void XGA_DrawCmd(Bitu val, Bitu len) { - Bit16u cmd; - cmd = val >> 13; -#if XGA_SHOW_COMMAND_TRACE == 1 - //LOG_MSG("XGA: Draw command %x", cmd); -#endif - xga.curcommand = val; - switch(cmd) { - case 1: /* Draw line */ - if((val & 0x100) == 0) { - if((val & 0x8) == 0) { -#if XGA_SHOW_COMMAND_TRACE == 1 - LOG_MSG("XGA: Drawing Bresenham line"); -#endif - XGA_DrawLineBresenham(val); - } else { -#if XGA_SHOW_COMMAND_TRACE == 1 - LOG_MSG("XGA: Drawing vector line"); -#endif - XGA_DrawLineVector(val); - } - } else { - LOG_MSG("XGA: Wants line drawn from PIX_TRANS register!"); - } - break; - case 2: /* Rectangle fill */ - if((val & 0x100) == 0) { - xga.waitcmd.wait = false; -#if XGA_SHOW_COMMAND_TRACE == 1 - LOG_MSG("XGA: Draw immediate rect: xy(%3d/%3d), len(%3d/%3d)", - xga.curx,xga.cury,xga.MAPcount,xga.MIPcount); -#endif - XGA_DrawRectangle(val); - - } else { - - xga.waitcmd.newline = true; - xga.waitcmd.wait = true; - xga.waitcmd.curx = xga.curx; - xga.waitcmd.cury = xga.cury; - xga.waitcmd.x1 = xga.curx; - xga.waitcmd.y1 = xga.cury; - xga.waitcmd.x2 = (Bit16u)((xga.curx + xga.MAPcount)&0x0fff); - xga.waitcmd.y2 = (Bit16u)((xga.cury + xga.MIPcount + 1)&0x0fff); - xga.waitcmd.sizex = xga.MAPcount; - xga.waitcmd.sizey = xga.MIPcount + 1; - xga.waitcmd.cmd = 2; - xga.waitcmd.buswidth = vga.mode | ((val&0x600) >> 4); - xga.waitcmd.data = 0; - xga.waitcmd.datasize = 0; - -#if XGA_SHOW_COMMAND_TRACE == 1 - LOG_MSG("XGA: Draw wait rect, w/h(%3d/%3d), x/y1(%3d/%3d), x/y2(%3d/%3d), %4x", - xga.MAPcount+1, xga.MIPcount+1,xga.curx,xga.cury, - (xga.curx + xga.MAPcount)&0x0fff, - (xga.cury + xga.MIPcount + 1)&0x0fff,val&0xffff); -#endif - - } - break; - case 6: /* BitBLT */ -#if XGA_SHOW_COMMAND_TRACE == 1 - LOG_MSG("XGA: Blit Rect"); -#endif - XGA_BlitRect(val); - break; - case 7: /* Pattern fill */ -#if XGA_SHOW_COMMAND_TRACE == 1 - LOG_MSG("XGA: Pattern fill: src(%3d/%3d), dest(%3d/%3d), fill(%3d/%3d)", - xga.curx,xga.cury,xga.destx,xga.desty,xga.MAPcount,xga.MIPcount); -#endif - XGA_DrawPattern(val); - break; - default: - LOG_MSG("XGA: Unhandled draw command %x", cmd); - break; - } -} - -void XGA_SetDualReg(Bit32u& reg, Bitu val) { - switch(XGA_COLOR_MODE) { - case M_LIN8: - reg = (Bit8u)(val&0xff); break; - case M_LIN15: - case M_LIN16: - reg = (Bit16u)(val&0xffff); break; - case M_LIN32: - if (xga.control1 & 0x200) - reg = val; - else if (xga.control1 & 0x10) - reg = (reg&0x0000ffff)|(val<<16); - else - reg = (reg&0xffff0000)|(val&0x0000ffff); - xga.control1 ^= 0x10; - break; - } -} - -Bitu XGA_GetDualReg(Bit32u reg) { - switch(XGA_COLOR_MODE) { - case M_LIN8: - return (Bit8u)(reg&0xff); - case M_LIN15: case M_LIN16: - return (Bit16u)(reg&0xffff); - case M_LIN32: - if (xga.control1 & 0x200) return reg; - xga.control1 ^= 0x10; - if (xga.control1 & 0x10) return reg&0x0000ffff; - else return reg>>16; - } - return 0; -} - -extern Bitu vga_read_p3da(Bitu port,Bitu iolen); - -extern void vga_write_p3d4(Bitu port,Bitu val,Bitu iolen); -extern Bitu vga_read_p3d4(Bitu port,Bitu iolen); - -extern void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen); -extern Bitu vga_read_p3d5(Bitu port,Bitu iolen); - -void XGA_Write(Bitu port, Bitu val, Bitu len) { -// LOG_MSG("XGA: Write to port %x, val %8x, len %x", port,val, len); - - switch(port) { - case 0x8100:// drawing control: row (low word), column (high word) - // "CUR_X" and "CUR_Y" (see PORT 82E8h,PORT 86E8h) - xga.cury = val & 0x0fff; - if(len==4) xga.curx = (val>>16)&0x0fff; - break; - case 0x8102: - xga.curx = val& 0x0fff; - break; - - case 0x8108:// DWORD drawing control: destination Y and axial step - // constant (low word), destination X and axial step - // constant (high word) (see PORT 8AE8h,PORT 8EE8h) - xga.desty = val&0x3FFF; - if(len==4) xga.destx = (val>>16)&0x3fff; - break; - case 0x810a: - xga.destx = val&0x3fff; - break; - case 0x8110: // WORD error term (see PORT 92E8h) - xga.ErrTerm = val&0x3FFF; - break; - - case 0x8120: // packed MMIO: DWORD background color (see PORT A2E8h) - xga.backcolor = val; - break; - case 0x8124: // packed MMIO: DWORD foreground color (see PORT A6E8h) - xga.forecolor = val; - break; - case 0x8128: // DWORD write mask (see PORT AAE8h) - xga.writemask = val; - break; - case 0x812C: // DWORD read mask (see PORT AEE8h) - xga.readmask = val; - break; - case 0x8134: // packed MMIO: DWORD background mix (low word) and - // foreground mix (high word) (see PORT B6E8h,PORT BAE8h) - xga.backmix = val&0xFFFF; - if(len==4) xga.foremix = (val>>16); - break; - case 0x8136: - xga.foremix = val; - break; - case 0x8138:// DWORD top scissors (low word) and left scissors (high - // word) (see PORT BEE8h,#P1047) - xga.scissors.y1=val&0x0fff; - if(len==4) xga.scissors.x1 = (val>>16)&0x0fff; - break; - case 0x813a: - xga.scissors.x1 = val&0x0fff; - break; - case 0x813C:// DWORD bottom scissors (low word) and right scissors - // (high word) (see PORT BEE8h,#P1047) - xga.scissors.y2=val&0x0fff; - if(len==4) xga.scissors.x2 = (val>>16)&0x0fff; - break; - case 0x813e: - xga.scissors.x2 = val&0x0fff; - break; - - case 0x8140:// DWORD data manipulation control (low word) and - // miscellaneous 2 (high word) (see PORT BEE8h,#P1047) - xga.pix_cntl=val&0xFFFF; - if(len==4) xga.control2=(val>>16)&0x0fff; - break; - case 0x8144:// DWORD miscellaneous (low word) and read register select - // (high word)(see PORT BEE8h,#P1047) - xga.control1=val&0xffff; - if(len==4)xga.read_sel=(val>>16)&0x7; - break; - case 0x8148:// DWORD minor axis pixel count (low word) and major axis - // pixel count (high word) (see PORT BEE8h,#P1047,PORT 96E8h) - xga.MIPcount = val&0x0fff; - if(len==4) xga.MAPcount = (val>>16)&0x0fff; - break; - case 0x814a: - xga.MAPcount = val&0x0fff; - break; - case 0x92e8: - xga.ErrTerm = val&0x3FFF; - break; - case 0x96e8: - xga.MAPcount = val&0x0fff; - break; - case 0x9ae8: - case 0x8118: // Trio64V+ packed MMIO - XGA_DrawCmd(val, len); - break; - case 0xa2e8: - XGA_SetDualReg(xga.backcolor, val); - break; - case 0xa6e8: - XGA_SetDualReg(xga.forecolor, val); - break; - case 0xaae8: - XGA_SetDualReg(xga.writemask, val); - break; - case 0xaee8: - XGA_SetDualReg(xga.readmask, val); - break; - case 0x82e8: - xga.cury = val&0x0fff; - break; - case 0x86e8: - xga.curx = val&0x0fff; - break; - case 0x8ae8: - xga.desty = val&0x3fff; - break; - case 0x8ee8: - xga.destx = val&0x3fff; - break; - case 0xb2e8: - LOG_MSG("COLOR_CMP not implemented"); - break; - case 0xb6e8: - xga.backmix = val; - break; - case 0xbae8: - xga.foremix = val; - break; - case 0xbee8: - XGA_Write_Multifunc(val, len); - break; - case 0xe2e8: - xga.waitcmd.newline = false; - XGA_DrawWait(val, len); - break; - case 0x83d4: - if(len==1) vga_write_p3d4(0,val,1); - else if(len==2) { - vga_write_p3d4(0,val&0xff,1); - vga_write_p3d5(0,val>>8,1); - } - else E_Exit("unimplemented XGA MMIO"); - break; - case 0x83d5: - if(len==1) vga_write_p3d5(0,val,1); - else E_Exit("unimplemented XGA MMIO"); - break; - default: - if(port <= 0x4000) { - //LOG_MSG("XGA: Wrote to port %4x with %08x, len %x", port, val, len); - xga.waitcmd.newline = false; - XGA_DrawWait(val, len); - - } - else LOG_MSG("XGA: Wrote to port %x with %x, len %x", port, val, len); - break; - } -} - -Bitu XGA_Read(Bitu port, Bitu len) { - switch(port) { - case 0x8118: - case 0x9ae8: - return 0x400; // nothing busy - break; - case 0x81ec: // S3 video data processor - return 0x00007000; - break; - case 0x83da: - { - Bits delaycyc = CPU_CycleMax/5000; - if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc = 0; - CPU_Cycles -= delaycyc; - CPU_IODelayRemoved += delaycyc; - return vga_read_p3da(0,0); - break; - } - case 0x83d4: - if(len==1) return vga_read_p3d4(0,0); - else E_Exit("unimplemented XGA MMIO"); - break; - case 0x83d5: - if(len==1) return vga_read_p3d5(0,0); - else E_Exit("unimplemented XGA MMIO"); - break; - case 0x9ae9: - if(xga.waitcmd.wait) return 0x4; - else return 0x0; - case 0xbee8: - return XGA_Read_Multifunc(); - case 0xa2e8: - return XGA_GetDualReg(xga.backcolor); - break; - case 0xa6e8: - return XGA_GetDualReg(xga.forecolor); - break; - case 0xaae8: - return XGA_GetDualReg(xga.writemask); - break; - case 0xaee8: - return XGA_GetDualReg(xga.readmask); - break; - default: - //LOG_MSG("XGA: Read from port %x, len %x", port, len); - break; - } - return 0xffffffff; -} - -void VGA_SetupXGA(void) { - if (!IS_VGA_ARCH) return; - - memset(&xga, 0, sizeof(XGAStatus)); - - xga.scissors.y1 = 0; - xga.scissors.x1 = 0; - xga.scissors.y2 = 0xFFF; - xga.scissors.x2 = 0xFFF; - - IO_RegisterWriteHandler(0x42e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x42e8,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0x46e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0x4ae8,&XGA_Write,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0x82e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x82e8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0x82e9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x82e9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0x86e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x86e8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0x86e9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x86e9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0x8ae8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x8ae8,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0x8ee8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x8ee8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0x8ee9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x8ee9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0x92e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x92e8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0x92e9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x92e9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0x96e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x96e8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0x96e9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x96e9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0x9ae8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x9ae8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0x9ae9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x9ae9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0x9ee8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x9ee8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0x9ee9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0x9ee9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xa2e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xa2e8,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xa6e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xa6e8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0xa6e9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xa6e9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xaae8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xaae8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0xaae9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xaae9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xaee8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xaee8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0xaee9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xaee9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xb2e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xb2e8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0xb2e9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xb2e9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xb6e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xb6e8,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xbee8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xbee8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0xbee9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xbee9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xbae8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xbae8,&XGA_Read,IO_MB | IO_MW | IO_MD); - IO_RegisterWriteHandler(0xbae9,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xbae9,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xe2e8,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xe2e8,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xe2e0,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xe2e0,&XGA_Read,IO_MB | IO_MW | IO_MD); - - IO_RegisterWriteHandler(0xe2ea,&XGA_Write,IO_MB | IO_MW | IO_MD); - IO_RegisterReadHandler(0xe2ea,&XGA_Read,IO_MB | IO_MW | IO_MD); -} diff --git a/src/hardware/ymf262.c b/src/hardware/ymf262.c deleted file mode 100644 index cbe8ad4..0000000 --- a/src/hardware/ymf262.c +++ /dev/null @@ -1,2746 +0,0 @@ -/* -** -** File: ymf262.c - software implementation of YMF262 -** FM sound generator type OPL3 -** -** Copyright (C) 2003 Jarek Burczynski -** -** Version 0.2 -** - -Revision History: - -03-03-2003: initial release - - thanks to Olivier Galibert and Chris Hardy for YMF262 and YAC512 chips - - thanks to Stiletto for the datasheets - - - -differences between OPL2 and OPL3 not documented in Yamaha datahasheets: -- sinus table is a little different: the negative part is off by one... - -- in order to enable selection of four different waveforms on OPL2 - one must set bit 5 in register 0x01(test). - on OPL3 this bit is ignored and 4-waveform select works *always*. - (Don't confuse this with OPL3's 8-waveform select.) - -- Envelope Generator: all 15 x rates take zero time on OPL3 - (on OPL2 15 0 and 15 1 rates take some time while 15 2 and 15 3 rates - take zero time) - -- channel calculations: output of operator 1 is in perfect sync with - output of operator 2 on OPL3; on OPL and OPL2 output of operator 1 - is always delayed by one sample compared to output of operator 2 - - -differences between OPL2 and OPL3 shown in datasheets: -- YMF262 does not support CSM mode - - -*/ - -#include -#include -#include - -//#include "driver.h" /* use M.A.M.E. */ -#include "ymf262.h" - -#ifndef PI -#define PI 3.14159265358979323846 -#endif - - - -/* output final shift */ -#if (OPL3_SAMPLE_BITS==16) - #define FINAL_SH (0) - #define MAXOUT (+32767) - #define MINOUT (-32768) -#else - #define FINAL_SH (8) - #define MAXOUT (+127) - #define MINOUT (-128) -#endif - - -#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ -#define EG_SH 16 /* 16.16 fixed point (EG timing) */ -#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */ -#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */ - -#define FREQ_MASK ((1<>8)&0xff,sample[0]); \ - } - #else /*save to STEREO file */ - #define SAVE_ALL_CHANNELS \ - { signed int pom = a; \ - fputc((unsigned short)pom&0xff,sample[0]); \ - fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ - pom = b; \ - fputc((unsigned short)pom&0xff,sample[0]); \ - fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ - } - #endif -#endif - -/*#define LOG_CYM_FILE*/ -#ifdef LOG_CYM_FILE - FILE * cymfile = NULL; -#endif - - - - - -#define OPL3_TYPE_YMF262 (0) /* 36 operators, 8 waveforms */ - - -typedef struct{ - UINT32 ar; /* attack rate: AR<<2 */ - UINT32 dr; /* decay rate: DR<<2 */ - UINT32 rr; /* release rate:RR<<2 */ - UINT8 KSR; /* key scale rate */ - UINT8 ksl; /* keyscale level */ - UINT8 ksr; /* key scale rate: kcode>>KSR */ - UINT8 mul; /* multiple: mul_tab[ML] */ - - /* Phase Generator */ - UINT32 Cnt; /* frequency counter */ - UINT32 Incr; /* frequency counter step */ - UINT8 FB; /* feedback shift value */ - INT32 *connect; /* slot output pointer */ - INT32 op1_out[2]; /* slot1 output for feedback */ - UINT8 CON; /* connection (algorithm) type */ - - /* Envelope Generator */ - UINT8 eg_type; /* percussive/non-percussive mode */ - UINT8 state; /* phase type */ - UINT32 TL; /* total level: TL << 2 */ - INT32 TLL; /* adjusted now TL */ - INT32 volume; /* envelope counter */ - UINT32 sl; /* sustain level: sl_tab[SL] */ - - UINT32 eg_m_ar; /* (attack state) */ - UINT8 eg_sh_ar; /* (attack state) */ - UINT8 eg_sel_ar; /* (attack state) */ - UINT32 eg_m_dr; /* (decay state) */ - UINT8 eg_sh_dr; /* (decay state) */ - UINT8 eg_sel_dr; /* (decay state) */ - UINT32 eg_m_rr; /* (release state) */ - UINT8 eg_sh_rr; /* (release state) */ - UINT8 eg_sel_rr; /* (release state) */ - - UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */ - - /* LFO */ - UINT32 AMmask; /* LFO Amplitude Modulation enable mask */ - UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/ - - /* waveform select */ - UINT8 waveform_number; - unsigned int wavetable; - -//unsigned char reserved[128-84];//speedup: pump up the struct size to power of 2 -unsigned char reserved[128-100];//speedup: pump up the struct size to power of 2 - -} OPL3_SLOT; - -typedef struct{ - OPL3_SLOT SLOT[2]; - - UINT32 block_fnum; /* block+fnum */ - UINT32 fc; /* Freq. Increment base */ - UINT32 ksl_base; /* KeyScaleLevel Base step */ - UINT8 kcode; /* key code (for key scaling) */ - - /* - there are 12 2-operator channels which can be combined in pairs - to form six 4-operator channel, they are: - 0 and 3, - 1 and 4, - 2 and 5, - 9 and 12, - 10 and 13, - 11 and 14 - */ - UINT8 extended; /* set to 1 if this channel forms up a 4op channel with another channel(only used by first of pair of channels, ie 0,1,2 and 9,10,11) */ - -unsigned char reserved[512-272];//speedup:pump up the struct size to power of 2 - -} OPL3_CH; - -/* OPL3 state */ -typedef struct { - OPL3_CH P_CH[18]; /* OPL3 chips have 18 channels */ - - UINT32 pan[18*2]; /* channels output multiplier; 2 per channel */ - - UINT32 eg_cnt; /* global envelope generator counter */ - UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/288 (288=8*36) */ - UINT32 eg_timer_add; /* step of eg_timer */ - UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */ - - UINT32 fn_tab[1024]; /* fnumber->increment counter */ - - /* LFO */ - UINT8 lfo_am_depth; - UINT8 lfo_pm_depth_range; - UINT32 lfo_am_cnt; - UINT32 lfo_am_inc; - UINT32 lfo_pm_cnt; - UINT32 lfo_pm_inc; - - UINT32 noise_rng; /* 23 bit noise shift register */ - UINT32 noise_p; /* current noise 'phase' */ - UINT32 noise_f; /* current noise period */ - - UINT8 OPL3_mode; /* OPL3 extension enable flag */ - - UINT8 rhythm; /* Rhythm mode */ - - int T[2]; /* timer counters */ - int TC[2]; - UINT8 st[2]; /* timer enable */ - - UINT32 address; /* address register */ - UINT8 status; /* status flag */ - UINT8 statusmask; /* status mask */ - - UINT8 nts; /* NTS (note select) */ - - /* external event callback handlers */ - OPL3_TIMERHANDLER TimerHandler;/* TIMER handler */ - int TimerParam; /* TIMER parameter */ - OPL3_IRQHANDLER IRQHandler; /* IRQ handler */ - int IRQParam; /* IRQ parameter */ - OPL3_UPDATEHANDLER UpdateHandler;/* stream update handler */ - int UpdateParam; /* stream update parameter */ - - UINT8 type; /* chip type */ - int clock; /* master clock (Hz) */ - int rate; /* sampling rate (Hz) */ - double freqbase; /* frequency base */ - double TimerBase; /* Timer base time (==sampling time)*/ -} OPL3; - - - -/* mapping of register number (offset) to slot number used by the emulator */ -static const int slot_array[32]= -{ - 0, 2, 4, 1, 3, 5,-1,-1, - 6, 8,10, 7, 9,11,-1,-1, - 12,14,16,13,15,17,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1 -}; - -/* key scale level */ -/* table is 3dB/octave , DV converts this into 6dB/octave */ -/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */ -#define SC(x) ((UINT32)((x)/(0.1875/2.0))) -static const UINT32 ksl_tab[8*16]= -{ - /* OCT 0 */ - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - /* OCT 1 */ - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(0.750), SC(1.125), SC(1.500), - SC(1.875), SC(2.250), SC(2.625), SC(3.000), - /* OCT 2 */ - SC(0.000), SC(0.000), SC(0.000), SC(0.000), - SC(0.000), SC(1.125), SC(1.875), SC(2.625), - SC(3.000), SC(3.750), SC(4.125), SC(4.500), - SC(4.875), SC(5.250), SC(5.625), SC(6.000), - /* OCT 3 */ - SC(0.000), SC(0.000), SC(0.000), SC(1.875), - SC(3.000), SC(4.125), SC(4.875), SC(5.625), - SC(6.000), SC(6.750), SC(7.125), SC(7.500), - SC(7.875), SC(8.250), SC(8.625), SC(9.000), - /* OCT 4 */ - SC(0.000), SC(0.000), SC(3.000), SC(4.875), - SC(6.000), SC(7.125), SC(7.875), SC(8.625), - SC(9.000), SC(9.750),SC(10.125),SC(10.500), - SC(10.875),SC(11.250),SC(11.625),SC(12.000), - /* OCT 5 */ - SC(0.000), SC(3.000), SC(6.000), SC(7.875), - SC(9.000),SC(10.125),SC(10.875),SC(11.625), - SC(12.000),SC(12.750),SC(13.125),SC(13.500), - SC(13.875),SC(14.250),SC(14.625),SC(15.000), - /* OCT 6 */ - SC(0.000), SC(6.000), SC(9.000),SC(10.875), - SC(12.000),SC(13.125),SC(13.875),SC(14.625), - SC(15.000),SC(15.750),SC(16.125),SC(16.500), - SC(16.875),SC(17.250),SC(17.625),SC(18.000), - /* OCT 7 */ - SC(0.000), SC(9.000),SC(12.000),SC(13.875), - SC(15.000),SC(16.125),SC(16.875),SC(17.625), - SC(18.000),SC(18.750),SC(19.125),SC(19.500), - SC(19.875),SC(20.250),SC(20.625),SC(21.000) -}; -#undef SC - -/* key scale level lookup */ -static const INT32 ksl_level[4]= -{ - 31,1,2,0 -}; - -/* sustain level table (3dB per step) */ -/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ -#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) ) -static const UINT32 sl_tab[16]={ - SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7), - SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31) -}; -#undef SC - - -#define RATE_STEPS (8) -static const unsigned char eg_inc[15*RATE_STEPS]={ - -/*cycle:0 1 2 3 4 5 6 7*/ - -/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */ -/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */ -/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */ -/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */ - -/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */ -/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */ -/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */ -/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */ - -/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */ -/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */ -/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */ -/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */ - -/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 for decay */ -/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 for attack (zero time) */ -/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */ -}; - - -#define O(a) (a*RATE_STEPS) - -/* note that there is no O(13) in this table - it's directly in the code */ -static const unsigned char eg_rate_select[16+64+16]={ /* Envelope Generator rates (16 + 64 rates + 16 RKS) */ -/* 16 infinite time rates */ -O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14), -O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14), - -/* rates 00-12 */ -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), -O( 0),O( 1),O( 2),O( 3), - -/* rate 13 */ -O( 4),O( 5),O( 6),O( 7), - -/* rate 14 */ -O( 8),O( 9),O(10),O(11), - -/* rate 15 */ -O(12),O(12),O(12),O(12), - -/* 16 dummy rates (same as 15 3) */ -O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12), -O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12), - -}; -#undef O - -/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */ -/*shift 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 */ -/*mask 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0 */ - -#define O(a) (a*1) -static const unsigned char eg_rate_shift[16+64+16]={ /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */ -/* 16 infinite time rates */ -O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), -O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), - -/* rates 00-12 */ -O(12),O(12),O(12),O(12), -O(11),O(11),O(11),O(11), -O(10),O(10),O(10),O(10), -O( 9),O( 9),O( 9),O( 9), -O( 8),O( 8),O( 8),O( 8), -O( 7),O( 7),O( 7),O( 7), -O( 6),O( 6),O( 6),O( 6), -O( 5),O( 5),O( 5),O( 5), -O( 4),O( 4),O( 4),O( 4), -O( 3),O( 3),O( 3),O( 3), -O( 2),O( 2),O( 2),O( 2), -O( 1),O( 1),O( 1),O( 1), -O( 0),O( 0),O( 0),O( 0), - -/* rate 13 */ -O( 0),O( 0),O( 0),O( 0), - -/* rate 14 */ -O( 0),O( 0),O( 0),O( 0), - -/* rate 15 */ -O( 0),O( 0),O( 0),O( 0), - -/* 16 dummy rates (same as 15 3) */ -O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), -O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), - -}; -#undef O - - -/* multiple table */ -#define SC(x) ((UINT32)((x)*2)) -static const UINT8 mul_tab[16]= { -/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ - SC(0.50), SC(1.00), SC(2.00), SC(3.00), SC(4.00), SC(5.00), SC(6.00), SC(7.00), - SC(8.00), SC(9.00),SC(10.00),SC(10.00),SC(12.00),SC(12.00),SC(15.00),SC(15.00) -}; -#undef SC - -/* TL_TAB_LEN is calculated as: - -* (12+1)=13 - sinus amplitude bits (Y axis) -* additional 1: to compensate for calculations of negative part of waveform -* (if we don't add it then the greatest possible _negative_ value would be -2 -* and we really need -1 for waveform #7) -* 2 - sinus sign bit (Y axis) -* TL_RES_LEN - sinus resolution (X axis) -*/ -#define TL_TAB_LEN (13*2*TL_RES_LEN) -static signed int tl_tab[TL_TAB_LEN]; - -#define ENV_QUIET (TL_TAB_LEN>>4) - -/* sin waveform table in 'decibel' scale */ -/* there are eight waveforms on OPL3 chips */ -static unsigned int sin_tab[SIN_LEN * 8]; - - -/* LFO Amplitude Modulation table (verified on real YM3812) - 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples - - Length: 210 elements. - - Each of the elements has to be repeated - exactly 64 times (on 64 consecutive samples). - The whole table takes: 64 * 210 = 13440 samples. - - When AM = 1 data is used directly - When AM = 0 data is divided by 4 before being used (loosing precision is important) -*/ - -#define LFO_AM_TAB_ELEMENTS 210 - -static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = { -0,0,0,0,0,0,0, -1,1,1,1, -2,2,2,2, -3,3,3,3, -4,4,4,4, -5,5,5,5, -6,6,6,6, -7,7,7,7, -8,8,8,8, -9,9,9,9, -10,10,10,10, -11,11,11,11, -12,12,12,12, -13,13,13,13, -14,14,14,14, -15,15,15,15, -16,16,16,16, -17,17,17,17, -18,18,18,18, -19,19,19,19, -20,20,20,20, -21,21,21,21, -22,22,22,22, -23,23,23,23, -24,24,24,24, -25,25,25,25, -26,26,26, -25,25,25,25, -24,24,24,24, -23,23,23,23, -22,22,22,22, -21,21,21,21, -20,20,20,20, -19,19,19,19, -18,18,18,18, -17,17,17,17, -16,16,16,16, -15,15,15,15, -14,14,14,14, -13,13,13,13, -12,12,12,12, -11,11,11,11, -10,10,10,10, -9,9,9,9, -8,8,8,8, -7,7,7,7, -6,6,6,6, -5,5,5,5, -4,4,4,4, -3,3,3,3, -2,2,2,2, -1,1,1,1 -}; - -/* LFO Phase Modulation table (verified on real YM3812) */ -static const INT8 lfo_pm_table[8*8*2] = { - -/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */ -0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/ -0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */ -0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/ -1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */ -1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/ -2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */ -1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/ -3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */ -2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/ -4, 2, 0,-2,-4,-2, 0, 2, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */ -2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/ -5, 2, 0,-2,-5,-2, 0, 2, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */ -3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/ -6, 3, 0,-3,-6,-3, 0, 3, /*LFO PM depth = 1*/ - -/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */ -3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/ -7, 3, 0,-3,-7,-3, 0, 3 /*LFO PM depth = 1*/ -}; - - -/* lock level of common table */ -static int num_lock = 0; - -/* work table */ -static void *cur_chip = NULL; /* current chip point */ -static OPL3_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2; - -static signed int phase_modulation; /* phase modulation input (SLOT 2) */ -static signed int phase_modulation2; /* phase modulation input (SLOT 3 in 4 operator channels) */ -static signed int chanout[18]; /* 18 channels */ - - -static UINT32 LFO_AM; -static INT32 LFO_PM; - - - -INLINE int limit( int val, int max, int min ) { - if ( val > max ) - val = max; - else if ( val < min ) - val = min; - - return val; -} - - -/* status set and IRQ handling */ -INLINE void OPL3_STATUS_SET(OPL3 *chip,int flag) -{ - /* set status flag masking out disabled IRQs */ - chip->status |= (flag & chip->statusmask); - if(!(chip->status & 0x80)) - { - if(chip->status & 0x7f) - { /* IRQ on */ - chip->status |= 0x80; - /* callback user interrupt handler (IRQ is OFF to ON) */ - if(chip->IRQHandler) (chip->IRQHandler)(chip->IRQParam,1); - } - } -} - -/* status reset and IRQ handling */ -INLINE void OPL3_STATUS_RESET(OPL3 *chip,int flag) -{ - /* reset status flag */ - chip->status &= ~flag; - if(chip->status & 0x80) - { - if (!(chip->status & 0x7f)) - { - chip->status &= 0x7f; - /* callback user interrupt handler (IRQ is ON to OFF) */ - if(chip->IRQHandler) (chip->IRQHandler)(chip->IRQParam,0); - } - } -} - -/* IRQ mask set */ -INLINE void OPL3_STATUSMASK_SET(OPL3 *chip,int flag) -{ - chip->statusmask = flag; - /* IRQ handling check */ - OPL3_STATUS_SET(chip,0); - OPL3_STATUS_RESET(chip,0); -} - - -/* advance LFO to next sample */ -INLINE void advance_lfo(OPL3 *chip) -{ - UINT8 tmp; - - /* LFO */ - chip->lfo_am_cnt += chip->lfo_am_inc; - if (chip->lfo_am_cnt >= (LFO_AM_TAB_ELEMENTS<lfo_am_cnt -= (LFO_AM_TAB_ELEMENTS<lfo_am_cnt >> LFO_SH ]; - - if (chip->lfo_am_depth) - LFO_AM = tmp; - else - LFO_AM = tmp>>2; - - chip->lfo_pm_cnt += chip->lfo_pm_inc; - LFO_PM = ((chip->lfo_pm_cnt>>LFO_SH) & 7) | chip->lfo_pm_depth_range; -} - -/* advance to next sample */ -INLINE void advance(OPL3 *chip) -{ - OPL3_CH *CH; - OPL3_SLOT *op; - int i; - -//profiler_mark(PROFILER_USER3); - chip->eg_timer += chip->eg_timer_add; - - while (chip->eg_timer >= chip->eg_timer_overflow) - { - chip->eg_timer -= chip->eg_timer_overflow; - - chip->eg_cnt++; - - for (i=0; i<9*2*2; i++) - { - CH = &chip->P_CH[i/2]; - op = &CH->SLOT[i&1]; -#if 1 - /* Envelope Generator */ - switch(op->state) - { - case EG_ATT: /* attack phase */ -// if ( !(chip->eg_cnt & ((1<eg_sh_ar)-1) ) ) - if ( !(chip->eg_cnt & op->eg_m_ar) ) - { - op->volume += (~op->volume * - (eg_inc[op->eg_sel_ar + ((chip->eg_cnt>>op->eg_sh_ar)&7)]) - ) >>3; - - if (op->volume <= MIN_ATT_INDEX) - { - op->volume = MIN_ATT_INDEX; - op->state = EG_DEC; - } - - } - break; - - case EG_DEC: /* decay phase */ -// if ( !(chip->eg_cnt & ((1<eg_sh_dr)-1) ) ) - if ( !(chip->eg_cnt & op->eg_m_dr) ) - { - op->volume += eg_inc[op->eg_sel_dr + ((chip->eg_cnt>>op->eg_sh_dr)&7)]; - - if ( op->volume >= op->sl ) - op->state = EG_SUS; - - } - break; - - case EG_SUS: /* sustain phase */ - - /* this is important behaviour: - one can change percusive/non-percussive modes on the fly and - the chip will remain in sustain phase - verified on real YM3812 */ - - if(op->eg_type) /* non-percussive mode */ - { - /* do nothing */ - } - else /* percussive mode */ - { - /* during sustain phase chip adds Release Rate (in percussive mode) */ -// if ( !(chip->eg_cnt & ((1<eg_sh_rr)-1) ) ) - if ( !(chip->eg_cnt & op->eg_m_rr) ) - { - op->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)]; - - if ( op->volume >= MAX_ATT_INDEX ) - op->volume = MAX_ATT_INDEX; - } - /* else do nothing in sustain phase */ - } - break; - - case EG_REL: /* release phase */ -// if ( !(chip->eg_cnt & ((1<eg_sh_rr)-1) ) ) - if ( !(chip->eg_cnt & op->eg_m_rr) ) - { - op->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)]; - - if ( op->volume >= MAX_ATT_INDEX ) - { - op->volume = MAX_ATT_INDEX; - op->state = EG_OFF; - } - - } - break; - - default: - break; - } -#endif - } - } -//profiler_mark(PROFILER_END); - -//profiler_mark(PROFILER_USER4); - for (i=0; i<9*2*2; i++) - { - CH = &chip->P_CH[i/2]; - op = &CH->SLOT[i&1]; - - /* Phase Generator */ - if(op->vib) - { - UINT8 block; - unsigned int block_fnum = CH->block_fnum; - - unsigned int fnum_lfo = (block_fnum&0x0380) >> 7; - - signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + 16*fnum_lfo ]; - - if (lfo_fn_table_index_offset) /* LFO phase modulation active */ - { - block_fnum += lfo_fn_table_index_offset; - block = (block_fnum&0x1c00) >> 10; - op->Cnt += (chip->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul; - } - else /* LFO phase modulation = zero */ - { - op->Cnt += op->Incr; - } - } - else /* LFO phase modulation disabled for this operator */ - { - op->Cnt += op->Incr; - } - } -//profiler_mark(PROFILER_END); - - /* The Noise Generator of the YM3812 is 23-bit shift register. - * Period is equal to 2^23-2 samples. - * Register works at sampling frequency of the chip, so output - * can change on every sample. - * - * Output of the register and input to the bit 22 is: - * bit0 XOR bit14 XOR bit15 XOR bit22 - * - * Simply use bit 22 as the noise output. - */ - - chip->noise_p += chip->noise_f; - i = chip->noise_p >> FREQ_SH; /* number of events (shifts of the shift register) */ - chip->noise_p &= FREQ_MASK; - while (i) - { - /* - UINT32 j; - j = ( (chip->noise_rng) ^ (chip->noise_rng>>14) ^ (chip->noise_rng>>15) ^ (chip->noise_rng>>22) ) & 1; - chip->noise_rng = (j<<22) | (chip->noise_rng>>1); - */ - - /* - Instead of doing all the logic operations above, we - use a trick here (and use bit 0 as the noise output). - The difference is only that the noise bit changes one - step ahead. This doesn't matter since we don't know - what is real state of the noise_rng after the reset. - */ - - if (chip->noise_rng & 1) chip->noise_rng ^= 0x800302; - chip->noise_rng >>= 1; - - i--; - } -} - - -INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) -{ - UINT32 p; - - p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ]; - - if (p >= TL_TAB_LEN) - return 0; - return tl_tab[p]; -} - -INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) -{ - UINT32 p; - - p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm))>>FREQ_SH) & SIN_MASK)]; - - if (p >= TL_TAB_LEN) - return 0; - return tl_tab[p]; -} - - -#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask)) - -/* calculate output of a standard 2 operator channel - (or 1st part of a 4-op channel) */ -INLINE void chan_calc( OPL3_CH *CH ) -{ - OPL3_SLOT *SLOT; - unsigned int env; - signed int out; - - phase_modulation = 0; - phase_modulation2= 0; - - /* SLOT 1 */ - SLOT = &CH->SLOT[SLOT1]; - env = volume_calc(SLOT); - out = SLOT->op1_out[0] + SLOT->op1_out[1]; - SLOT->op1_out[0] = SLOT->op1_out[1]; - SLOT->op1_out[1] = 0; - if( env < ENV_QUIET ) - { - if (!SLOT->FB) - out = 0; - SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB), SLOT->wavetable ); - } - *SLOT->connect += SLOT->op1_out[1]; -//logerror("out0=%5i vol0=%4i ", SLOT->op1_out[1], env ); - - /* SLOT 2 */ - SLOT++; - env = volume_calc(SLOT); - if( env < ENV_QUIET ) - *SLOT->connect += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable); - -//logerror("out1=%5i vol1=%4i\n", op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable), env ); - -} - -/* calculate output of a 2nd part of 4-op channel */ -INLINE void chan_calc_ext( OPL3_CH *CH ) -{ - OPL3_SLOT *SLOT; - unsigned int env; - - phase_modulation = 0; - - /* SLOT 1 */ - SLOT = &CH->SLOT[SLOT1]; - env = volume_calc(SLOT); - if( env < ENV_QUIET ) - *SLOT->connect += op_calc(SLOT->Cnt, env, phase_modulation2, SLOT->wavetable ); - - /* SLOT 2 */ - SLOT++; - env = volume_calc(SLOT); - if( env < ENV_QUIET ) - *SLOT->connect += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable); - -} - -/* - operators used in the rhythm sounds generation process: - - Envelope Generator: - -channel operator register number Bass High Snare Tom Top -/ slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal - 6 / 0 12 50 70 90 f0 + - 6 / 1 15 53 73 93 f3 + - 7 / 0 13 51 71 91 f1 + - 7 / 1 16 54 74 94 f4 + - 8 / 0 14 52 72 92 f2 + - 8 / 1 17 55 75 95 f5 + - - Phase Generator: - -channel operator register number Bass High Snare Tom Top -/ slot number MULTIPLE Drum Hat Drum Tom Cymbal - 6 / 0 12 30 + - 6 / 1 15 33 + - 7 / 0 13 31 + + + - 7 / 1 16 34 ----- n o t u s e d ----- - 8 / 0 14 32 + - 8 / 1 17 35 + + - -channel operator register number Bass High Snare Tom Top -number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal - 6 12,15 B6 A6 + - - 7 13,16 B7 A7 + + + - - 8 14,17 B8 A8 + + + - -*/ - -/* calculate rhythm */ - -INLINE void chan_calc_rhythm( OPL3_CH *CH, unsigned int noise ) -{ - OPL3_SLOT *SLOT; - signed int out; - unsigned int env; - - - /* Bass Drum (verified on real YM3812): - - depends on the channel 6 'connect' register: - when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out) - when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored - - output sample always is multiplied by 2 - */ - - phase_modulation = 0; - - /* SLOT 1 */ - SLOT = &CH[6].SLOT[SLOT1]; - env = volume_calc(SLOT); - - out = SLOT->op1_out[0] + SLOT->op1_out[1]; - SLOT->op1_out[0] = SLOT->op1_out[1]; - - if (!SLOT->CON) - phase_modulation = SLOT->op1_out[0]; - //else ignore output of operator 1 - - SLOT->op1_out[1] = 0; - if( env < ENV_QUIET ) - { - if (!SLOT->FB) - out = 0; - SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB), SLOT->wavetable ); - } - - /* SLOT 2 */ - SLOT++; - env = volume_calc(SLOT); - if( env < ENV_QUIET ) - chanout[6] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable) * 2; - - - /* Phase generation is based on: */ - // HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) - // SD (16) channel 7->slot 1 - // TOM (14) channel 8->slot 1 - // TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) - - /* Envelope generation based on: */ - // HH channel 7->slot1 - // SD channel 7->slot2 - // TOM channel 8->slot1 - // TOP channel 8->slot2 - - - /* The following formulas can be well optimized. - I leave them in direct form for now (in case I've missed something). - */ - - /* High Hat (verified on real YM3812) */ - env = volume_calc(SLOT7_1); - if( env < ENV_QUIET ) - { - - /* high hat phase generation: - phase = d0 or 234 (based on frequency only) - phase = 34 or 2d0 (based on noise) - */ - - /* base frequency derived from operator 1 in channel 7 */ - unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1; - unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1; - unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1; - - unsigned char res1 = (bit2 ^ bit7) | bit3; - - /* when res1 = 0 phase = 0x000 | 0xd0; */ - /* when res1 = 1 phase = 0x200 | (0xd0>>2); */ - UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0; - - /* enable gate based on frequency of operator 2 in channel 8 */ - unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1; - unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1; - - unsigned char res2 = (bit3e ^ bit5e); - - /* when res2 = 0 pass the phase from calculation above (res1); */ - /* when res2 = 1 phase = 0x200 | (0xd0>>2); */ - if (res2) - phase = (0x200|(0xd0>>2)); - - - /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */ - /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */ - if (phase&0x200) - { - if (noise) - phase = 0x200|0xd0; - } - else - /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */ - /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */ - { - if (noise) - phase = 0xd0>>2; - } - - chanout[7] += op_calc(phase<wavetable) * 2; - } - - /* Snare Drum (verified on real YM3812) */ - env = volume_calc(SLOT7_2); - if( env < ENV_QUIET ) - { - /* base frequency derived from operator 1 in channel 7 */ - unsigned char bit8 = ((SLOT7_1->Cnt>>FREQ_SH)>>8)&1; - - /* when bit8 = 0 phase = 0x100; */ - /* when bit8 = 1 phase = 0x200; */ - UINT32 phase = bit8 ? 0x200 : 0x100; - - /* Noise bit XOR'es phase by 0x100 */ - /* when noisebit = 0 pass the phase from calculation above */ - /* when noisebit = 1 phase ^= 0x100; */ - /* in other words: phase ^= (noisebit<<8); */ - if (noise) - phase ^= 0x100; - - chanout[7] += op_calc(phase<wavetable) * 2; - } - - /* Tom Tom (verified on real YM3812) */ - env = volume_calc(SLOT8_1); - if( env < ENV_QUIET ) - chanout[8] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2; - - /* Top Cymbal (verified on real YM3812) */ - env = volume_calc(SLOT8_2); - if( env < ENV_QUIET ) - { - /* base frequency derived from operator 1 in channel 7 */ - unsigned char bit7 = ((SLOT7_1->Cnt>>FREQ_SH)>>7)&1; - unsigned char bit3 = ((SLOT7_1->Cnt>>FREQ_SH)>>3)&1; - unsigned char bit2 = ((SLOT7_1->Cnt>>FREQ_SH)>>2)&1; - - unsigned char res1 = (bit2 ^ bit7) | bit3; - - /* when res1 = 0 phase = 0x000 | 0x100; */ - /* when res1 = 1 phase = 0x200 | 0x100; */ - UINT32 phase = res1 ? 0x300 : 0x100; - - /* enable gate based on frequency of operator 2 in channel 8 */ - unsigned char bit5e= ((SLOT8_2->Cnt>>FREQ_SH)>>5)&1; - unsigned char bit3e= ((SLOT8_2->Cnt>>FREQ_SH)>>3)&1; - - unsigned char res2 = (bit3e ^ bit5e); - /* when res2 = 0 pass the phase from calculation above (res1); */ - /* when res2 = 1 phase = 0x200 | 0x100; */ - if (res2) - phase = 0x300; - - chanout[8] += op_calc(phase<wavetable) * 2; - } - -} - - -/* generic table initialize */ -static int init_tables(void) -{ - signed int i,x; - signed int n; - double o,m; - - - for (x=0; x>= 4; /* 12 bits here */ - if (n&1) /* round to nearest */ - n = (n>>1)+1; - else - n = n>>1; - /* 11 bits here (rounded) */ - n <<= 1; /* 12 bits here (as in real chip) */ - tl_tab[ x*2 + 0 ] = n; - tl_tab[ x*2 + 1 ] = ~tl_tab[ x*2 + 0 ]; /* this *is* different from OPL2 (verified on real YMF262) */ - - for (i=1; i<13; i++) - { - tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i; - tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = ~tl_tab[ x*2+0 + i*2*TL_RES_LEN ]; /* this *is* different from OPL2 (verified on real YMF262) */ - } - #if 0 - logerror("tl %04i", x*2); - for (i=0; i<13; i++) - logerror(", [%02i] %5i", i*2, tl_tab[ x*2 +0 + i*2*TL_RES_LEN ] ); /* positive */ - logerror("\n"); - - logerror("tl %04i", x*2); - for (i=0; i<13; i++) - logerror(", [%02i] %5i", i*2, tl_tab[ x*2 +1 + i*2*TL_RES_LEN ] ); /* negative */ - logerror("\n"); - #endif - } - - for (i=0; i0.0) - o = 8*log(1.0/m)/log(2.0); /* convert to 'decibels' */ - else - o = 8*log(-1.0/m)/log(2.0); /* convert to 'decibels' */ - - o = o / (ENV_STEP/4); - - n = (int)(2.0*o); - if (n&1) /* round to nearest */ - n = (n>>1)+1; - else - n = n>>1; - - sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 ); - - /*logerror("YMF262.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/ - } - - for (i=0; i>1) ]; - - /* waveform 3: _ _ _ _ */ - /* / |_/ |_/ |_/ |_*/ - /* abs(output only first quarter of the sinus waveform) */ - - if (i & (1<<(SIN_BITS-2)) ) - sin_tab[3*SIN_LEN+i] = TL_TAB_LEN; - else - sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)]; - - /* waveform 4: */ - /* /\ ____/\ ____*/ - /* \/ \/ */ - /* output whole sinus waveform in half the cycle(step=2) and output 0 on the other half of cycle */ - - if (i & (1<<(SIN_BITS-1)) ) - sin_tab[4*SIN_LEN+i] = TL_TAB_LEN; - else - sin_tab[4*SIN_LEN+i] = sin_tab[i*2]; - - /* waveform 5: */ - /* /\/\____/\/\____*/ - /* */ - /* output abs(whole sinus) waveform in half the cycle(step=2) and output 0 on the other half of cycle */ - - if (i & (1<<(SIN_BITS-1)) ) - sin_tab[5*SIN_LEN+i] = TL_TAB_LEN; - else - sin_tab[5*SIN_LEN+i] = sin_tab[(i*2) & (SIN_MASK>>1) ]; - - /* waveform 6: ____ ____ */ - /* */ - /* ____ ____*/ - /* output maximum in half the cycle and output minimum on the other half of cycle */ - - if (i & (1<<(SIN_BITS-1)) ) - sin_tab[6*SIN_LEN+i] = 1; /* negative */ - else - sin_tab[6*SIN_LEN+i] = 0; /* positive */ - - /* waveform 7: */ - /* |\____ |\____ */ - /* \| \|*/ - /* output sawtooth waveform */ - - if (i & (1<<(SIN_BITS-1)) ) - x = ((SIN_LEN-1)-i)*16 + 1; /* negative: from 8177 to 1 */ - else - x = i*16; /*positive: from 0 to 8176 */ - - if (x > TL_TAB_LEN) - x = TL_TAB_LEN; /* clip to the allowed range */ - - sin_tab[7*SIN_LEN+i] = x; - - //logerror("YMF262.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] ); - //logerror("YMF262.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] ); - //logerror("YMF262.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] ); - //logerror("YMF262.C: sin4[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[4*SIN_LEN+i], tl_tab[sin_tab[4*SIN_LEN+i]] ); - //logerror("YMF262.C: sin5[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[5*SIN_LEN+i], tl_tab[sin_tab[5*SIN_LEN+i]] ); - //logerror("YMF262.C: sin6[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[6*SIN_LEN+i], tl_tab[sin_tab[6*SIN_LEN+i]] ); - //logerror("YMF262.C: sin7[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[7*SIN_LEN+i], tl_tab[sin_tab[7*SIN_LEN+i]] ); - } - /*logerror("YMF262.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/ - -#ifdef SAVE_SAMPLE - sample[0]=fopen("sampsum.pcm","wb"); -#endif - - return 1; -} - -static void OPLCloseTable( void ) -{ -#ifdef SAVE_SAMPLE - fclose(sample[0]); -#endif -} - - - -static void OPL3_initalize(OPL3 *chip) -{ - int i; - - /* frequency base */ - chip->freqbase = (chip->rate) ? ((double)chip->clock / (8.0*36)) / chip->rate : 0; -#if 0 - chip->rate = (double)chip->clock / (8.0*36); - chip->freqbase = 1.0; -#endif - - /* logerror("YMF262: freqbase=%f\n", chip->freqbase); */ - - /* Timer base time */ - chip->TimerBase = 1.0 / ((double)chip->clock / (8.0*36) ); - - /* make fnumber -> increment counter table */ - for( i=0 ; i < 1024 ; i++ ) - { - /* opn phase increment counter = 20bit */ - chip->fn_tab[i] = (UINT32)( (double)i * 64 * chip->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */ -#if 0 - logerror("YMF262.C: fn_tab[%4i] = %08x (dec=%8i)\n", - i, chip->fn_tab[i]>>6, chip->fn_tab[i]>>6 ); -#endif - } - -#if 0 - for( i=0 ; i < 16 ; i++ ) - { - logerror("YMF262.C: sl_tab[%i] = %08x\n", - i, sl_tab[i] ); - } - for( i=0 ; i < 8 ; i++ ) - { - int j; - logerror("YMF262.C: ksl_tab[oct=%2i] =",i); - for (j=0; j<16; j++) - { - logerror("%08x ", ksl_tab[i*16+j] ); - } - logerror("\n"); - } -#endif - - - /* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */ - /* One entry from LFO_AM_TABLE lasts for 64 samples */ - chip->lfo_am_inc = (UINT32)((1.0 / 64.0 ) * (1<freqbase); - - /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */ - chip->lfo_pm_inc = (UINT32)((1.0 / 1024.0) * (1<freqbase); - - /*logerror ("chip->lfo_am_inc = %8x ; chip->lfo_pm_inc = %8x\n", chip->lfo_am_inc, chip->lfo_pm_inc);*/ - - /* Noise generator: a step takes 1 sample */ - chip->noise_f = (UINT32)((1.0 / 1.0) * (1<freqbase); - - chip->eg_timer_add = (UINT32)((1<freqbase); - chip->eg_timer_overflow = ( 1 ) * (1<eg_timer_add, chip->eg_timer_overflow);*/ - -} - -INLINE void FM_KEYON(OPL3_SLOT *SLOT, UINT32 key_set) -{ - if( !SLOT->key ) - { - /* restart Phase Generator */ - SLOT->Cnt = 0; - /* phase -> Attack */ - SLOT->state = EG_ATT; - } - SLOT->key |= key_set; -} - -INLINE void FM_KEYOFF(OPL3_SLOT *SLOT, UINT32 key_clr) -{ - if( SLOT->key ) - { - SLOT->key &= key_clr; - - if( !SLOT->key ) - { - /* phase -> Release */ - if (SLOT->state>EG_REL) - SLOT->state = EG_REL; - } - } -} - -/* update phase increment counter of operator (also update the EG rates if necessary) */ -INLINE void CALC_FCSLOT(OPL3_CH *CH,OPL3_SLOT *SLOT) -{ - int ksr; - - /* (frequency) phase increment counter */ - SLOT->Incr = CH->fc * SLOT->mul; - ksr = CH->kcode >> SLOT->KSR; - - if( SLOT->ksr != ksr ) - { - SLOT->ksr = ksr; - - /* calculate envelope generator rates */ - if ((SLOT->ar + SLOT->ksr) < 16+60) - { - SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; - SLOT->eg_m_ar = (1<eg_sh_ar)-1; - SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; - } - else - { - SLOT->eg_sh_ar = 0; - SLOT->eg_m_ar = (1<eg_sh_ar)-1; - SLOT->eg_sel_ar = 13*RATE_STEPS; - } - SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; - SLOT->eg_m_dr = (1<eg_sh_dr)-1; - SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; - SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; - SLOT->eg_m_rr = (1<eg_sh_rr)-1; - SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; - } -} - -/* set multi,am,vib,EG-TYP,KSR,mul */ -INLINE void set_mul(OPL3 *chip,int slot,int v) -{ - OPL3_CH *CH = &chip->P_CH[slot/2]; - OPL3_SLOT *SLOT = &CH->SLOT[slot&1]; - - SLOT->mul = mul_tab[v&0x0f]; - SLOT->KSR = (v&0x10) ? 0 : 2; - SLOT->eg_type = (v&0x20); - SLOT->vib = (v&0x40); - SLOT->AMmask = (v&0x80) ? ~0 : 0; - - if (chip->OPL3_mode & 1) - { - int chan_no = slot/2; - - /* in OPL3 mode */ - //DO THIS: - //if this is one of the slots of 1st channel forming up a 4-op channel - //do normal operation - //else normal 2 operator function - //OR THIS: - //if this is one of the slots of 2nd channel forming up a 4-op channel - //update it using channel data of 1st channel of a pair - //else normal 2 operator function - switch(chan_no) - { - case 0: case 1: case 2: - case 9: case 10: case 11: - if (CH->extended) - { - /* normal */ - CALC_FCSLOT(CH,SLOT); - } - else - { - /* normal */ - CALC_FCSLOT(CH,SLOT); - } - break; - case 3: case 4: case 5: - case 12: case 13: case 14: - if ((CH-3)->extended) - { - /* update this SLOT using frequency data for 1st channel of a pair */ - CALC_FCSLOT(CH-3,SLOT); - } - else - { - /* normal */ - CALC_FCSLOT(CH,SLOT); - } - break; - default: - /* normal */ - CALC_FCSLOT(CH,SLOT); - break; - } - } - else - { - /* in OPL2 mode */ - CALC_FCSLOT(CH,SLOT); - } -} - -/* set ksl & tl */ -INLINE void set_ksl_tl(OPL3 *chip,int slot,int v) -{ - OPL3_CH *CH = &chip->P_CH[slot/2]; - OPL3_SLOT *SLOT = &CH->SLOT[slot&1]; - - SLOT->ksl = ksl_level[(v>>6)&3]; /* 0 / 3.0 / 1.5 / 6.0 dB/OCT */ - SLOT->TL = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */ - - if (chip->OPL3_mode & 1) - { - int chan_no = slot/2; - - /* in OPL3 mode */ - //DO THIS: - //if this is one of the slots of 1st channel forming up a 4-op channel - //do normal operation - //else normal 2 operator function - //OR THIS: - //if this is one of the slots of 2nd channel forming up a 4-op channel - //update it using channel data of 1st channel of a pair - //else normal 2 operator function - switch(chan_no) - { - case 0: case 1: case 2: - case 9: case 10: case 11: - if (CH->extended) - { - /* normal */ - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); - } - else - { - /* normal */ - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); - } - break; - case 3: case 4: case 5: - case 12: case 13: case 14: - if ((CH-3)->extended) - { - /* update this SLOT using frequency data for 1st channel of a pair */ - SLOT->TLL = SLOT->TL + ((CH-3)->ksl_base>>SLOT->ksl); - } - else - { - /* normal */ - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); - } - break; - default: - /* normal */ - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); - break; - } - } - else - { - /* in OPL2 mode */ - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); - } - -} - -/* set attack rate & decay rate */ -INLINE void set_ar_dr(OPL3 *chip,int slot,int v) -{ - OPL3_CH *CH = &chip->P_CH[slot/2]; - OPL3_SLOT *SLOT = &CH->SLOT[slot&1]; - - SLOT->ar = (v>>4) ? 16 + ((v>>4) <<2) : 0; - - if ((SLOT->ar + SLOT->ksr) < 16+60) /* verified on real YMF262 - all 15 x rates take "zero" time */ - { - SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; - SLOT->eg_m_ar = (1<eg_sh_ar)-1; - SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; - } - else - { - SLOT->eg_sh_ar = 0; - SLOT->eg_m_ar = (1<eg_sh_ar)-1; - SLOT->eg_sel_ar = 13*RATE_STEPS; - } - - SLOT->dr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; - SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ]; - SLOT->eg_m_dr = (1<eg_sh_dr)-1; - SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ]; -} - -/* set sustain level & release rate */ -INLINE void set_sl_rr(OPL3 *chip,int slot,int v) -{ - OPL3_CH *CH = &chip->P_CH[slot/2]; - OPL3_SLOT *SLOT = &CH->SLOT[slot&1]; - - SLOT->sl = sl_tab[ v>>4 ]; - - SLOT->rr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0; - SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ]; - SLOT->eg_m_rr = (1<eg_sh_rr)-1; - SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ]; -} - - -static void update_channels(OPL3 *chip, OPL3_CH *CH) -{ - /* update channel passed as a parameter and a channel at CH+=3; */ - if (CH->extended) - { /* we've just switched to combined 4 operator mode */ - - } - else - { /* we've just switched to normal 2 operator mode */ - - } - -} - -/* write a value v to register r on OPL chip */ -static void OPL3WriteReg(OPL3 *chip, int r, int v) -{ - OPL3_CH *CH; - unsigned int ch_offset = 0; - int slot; - int block_fnum; - - - -#ifdef LOG_CYM_FILE - if ((cymfile) && ((r&255)!=0) && (r!=255) ) - { - if (r>0xff) - fputc( (unsigned char)0xff, cymfile );/*mark writes to second register set*/ - - fputc( (unsigned char)r&0xff, cymfile ); - fputc( (unsigned char)v, cymfile ); - } -#endif - - if(r&0x100) - { - switch(r) - { - case 0x101: /* test register */ - return; - break; - case 0x104: /* 6 channels enable */ - { - UINT8 prev; - - CH = &chip->P_CH[0]; /* channel 0 */ - prev = CH->extended; - CH->extended = (v>>0) & 1; - if(prev != CH->extended) - update_channels(chip, CH); - CH++; /* channel 1 */ - prev = CH->extended; - CH->extended = (v>>1) & 1; - if(prev != CH->extended) - update_channels(chip, CH); - CH++; /* channel 2 */ - prev = CH->extended; - CH->extended = (v>>2) & 1; - if(prev != CH->extended) - update_channels(chip, CH); - - - CH = &chip->P_CH[9]; /* channel 9 */ - prev = CH->extended; - CH->extended = (v>>3) & 1; - if(prev != CH->extended) - update_channels(chip, CH); - CH++; /* channel 10 */ - prev = CH->extended; - CH->extended = (v>>4) & 1; - if(prev != CH->extended) - update_channels(chip, CH); - CH++; /* channel 11 */ - prev = CH->extended; - CH->extended = (v>>5) & 1; - if(prev != CH->extended) - update_channels(chip, CH); - - } - return; - break; - case 0x105: /* OPL3 extensions enable register */ - - chip->OPL3_mode = v&0x01; /* OPL3 mode when bit0=1 otherwise it is OPL2 mode */ - - /* following behaviour was tested on real YMF262, - switching OPL3/OPL2 modes on the fly: - - does not change the waveform previously selected (unless when ....) - - does not update CH.A, CH.B, CH.C and CH.D output selectors (registers c0-c8) (unless when ....) - - does not disable channels 9-17 on OPL3->OPL2 switch - - does not switch 4 operator channels back to 2 operator channels - */ - - return; - break; - - default: - if (r < 0x120) - logerror("YMF262: write to unknown register (set#2): %03x value=%02x\n",r,v); - break; - } - - ch_offset = 9; /* register page #2 starts from channel 9 (counting from 0) */ - } - - /* adjust bus to 8 bits */ - r &= 0xff; - v &= 0xff; - - - switch(r&0xe0) - { - case 0x00: /* 00-1f:control */ - switch(r&0x1f) - { - case 0x01: /* test register */ - break; - case 0x02: /* Timer 1 */ - chip->T[0] = (256-v)*4; - break; - case 0x03: /* Timer 2 */ - chip->T[1] = (256-v)*16; - break; - case 0x04: /* IRQ clear / mask and Timer enable */ - if(v&0x80) - { /* IRQ flags clear */ - OPL3_STATUS_RESET(chip,0x60); - } - else - { /* set IRQ mask ,timer enable */ - chip->st[0] = v & 1; - chip->st[1] = (v>>1) & 1; - - /* IRQRST,T1MSK,t2MSK,x,x,x,ST2,ST1 */ - OPL3_STATUS_RESET(chip, v & 0x60); - OPL3_STATUSMASK_SET(chip, (~v) & 0x60 ); - - /* timer 1 */ - if(chip->st[0]) - { - chip->TC[0]=chip->T[0]*20; - double interval = (double)chip->T[0]*chip->TimerBase; - if (chip->TimerHandler) (chip->TimerHandler)(chip->TimerParam+0,interval); - } - /* timer 2 */ - if(chip->st[1]) - { - chip->TC[1]=chip->T[1]*20; - double interval =(double)chip->T[1]*chip->TimerBase; - if (chip->TimerHandler) (chip->TimerHandler)(chip->TimerParam+1,interval); - } - } - break; - case 0x08: /* x,NTS,x,x, x,x,x,x */ - chip->nts = v; - break; - - default: - logerror("YMF262: write to unknown register: %02x value=%02x\n",r,v); - break; - } - break; - case 0x20: /* am ON, vib ON, ksr, eg_type, mul */ - slot = slot_array[r&0x1f]; - if(slot < 0) return; - set_mul(chip, slot + ch_offset*2, v); - break; - case 0x40: - slot = slot_array[r&0x1f]; - if(slot < 0) return; - set_ksl_tl(chip, slot + ch_offset*2, v); - break; - case 0x60: - slot = slot_array[r&0x1f]; - if(slot < 0) return; - set_ar_dr(chip, slot + ch_offset*2, v); - break; - case 0x80: - slot = slot_array[r&0x1f]; - if(slot < 0) return; - set_sl_rr(chip, slot + ch_offset*2, v); - break; - case 0xa0: - if (r == 0xbd) /* am depth, vibrato depth, r,bd,sd,tom,tc,hh */ - { - if (ch_offset != 0) /* 0xbd register is present in set #1 only */ - return; - - chip->lfo_am_depth = v & 0x80; - chip->lfo_pm_depth_range = (v&0x40) ? 8 : 0; - - chip->rhythm = v&0x3f; - - if(chip->rhythm&0x20) - { - /* BD key on/off */ - if(v&0x10) - { - FM_KEYON (&chip->P_CH[6].SLOT[SLOT1], 2); - FM_KEYON (&chip->P_CH[6].SLOT[SLOT2], 2); - } - else - { - FM_KEYOFF(&chip->P_CH[6].SLOT[SLOT1],~2); - FM_KEYOFF(&chip->P_CH[6].SLOT[SLOT2],~2); - } - /* HH key on/off */ - if(v&0x01) FM_KEYON (&chip->P_CH[7].SLOT[SLOT1], 2); - else FM_KEYOFF(&chip->P_CH[7].SLOT[SLOT1],~2); - /* SD key on/off */ - if(v&0x08) FM_KEYON (&chip->P_CH[7].SLOT[SLOT2], 2); - else FM_KEYOFF(&chip->P_CH[7].SLOT[SLOT2],~2); - /* TOM key on/off */ - if(v&0x04) FM_KEYON (&chip->P_CH[8].SLOT[SLOT1], 2); - else FM_KEYOFF(&chip->P_CH[8].SLOT[SLOT1],~2); - /* TOP-CY key on/off */ - if(v&0x02) FM_KEYON (&chip->P_CH[8].SLOT[SLOT2], 2); - else FM_KEYOFF(&chip->P_CH[8].SLOT[SLOT2],~2); - } - else - { - /* BD key off */ - FM_KEYOFF(&chip->P_CH[6].SLOT[SLOT1],~2); - FM_KEYOFF(&chip->P_CH[6].SLOT[SLOT2],~2); - /* HH key off */ - FM_KEYOFF(&chip->P_CH[7].SLOT[SLOT1],~2); - /* SD key off */ - FM_KEYOFF(&chip->P_CH[7].SLOT[SLOT2],~2); - /* TOM key off */ - FM_KEYOFF(&chip->P_CH[8].SLOT[SLOT1],~2); - /* TOP-CY off */ - FM_KEYOFF(&chip->P_CH[8].SLOT[SLOT2],~2); - } - return; - } - - /* keyon,block,fnum */ - if( (r&0x0f) > 8) return; - CH = &chip->P_CH[(r&0x0f) + ch_offset]; - - if(!(r&0x10)) - { /* a0-a8 */ - block_fnum = (CH->block_fnum&0x1f00) | v; - } - else - { /* b0-b8 */ - block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff); - - if (chip->OPL3_mode & 1) - { - int chan_no = (r&0x0f) + ch_offset; - - /* in OPL3 mode */ - //DO THIS: - //if this is 1st channel forming up a 4-op channel - //ALSO keyon/off slots of 2nd channel forming up 4-op channel - //else normal 2 operator function keyon/off - //OR THIS: - //if this is 2nd channel forming up 4-op channel just do nothing - //else normal 2 operator function keyon/off - switch(chan_no) - { - case 0: case 1: case 2: - case 9: case 10: case 11: - if (CH->extended) - { - //if this is 1st channel forming up a 4-op channel - //ALSO keyon/off slots of 2nd channel forming up 4-op channel - if(v&0x20) - { - FM_KEYON (&CH->SLOT[SLOT1], 1); - FM_KEYON (&CH->SLOT[SLOT2], 1); - FM_KEYON (&(CH+3)->SLOT[SLOT1], 1); - FM_KEYON (&(CH+3)->SLOT[SLOT2], 1); - } - else - { - FM_KEYOFF(&CH->SLOT[SLOT1],~1); - FM_KEYOFF(&CH->SLOT[SLOT2],~1); - FM_KEYOFF(&(CH+3)->SLOT[SLOT1],~1); - FM_KEYOFF(&(CH+3)->SLOT[SLOT2],~1); - } - } - else - { - //else normal 2 operator function keyon/off - if(v&0x20) - { - FM_KEYON (&CH->SLOT[SLOT1], 1); - FM_KEYON (&CH->SLOT[SLOT2], 1); - } - else - { - FM_KEYOFF(&CH->SLOT[SLOT1],~1); - FM_KEYOFF(&CH->SLOT[SLOT2],~1); - } - } - break; - - case 3: case 4: case 5: - case 12: case 13: case 14: - if ((CH-3)->extended) - { - //if this is 2nd channel forming up 4-op channel just do nothing - } - else - { - //else normal 2 operator function keyon/off - if(v&0x20) - { - FM_KEYON (&CH->SLOT[SLOT1], 1); - FM_KEYON (&CH->SLOT[SLOT2], 1); - } - else - { - FM_KEYOFF(&CH->SLOT[SLOT1],~1); - FM_KEYOFF(&CH->SLOT[SLOT2],~1); - } - } - break; - - default: - if(v&0x20) - { - FM_KEYON (&CH->SLOT[SLOT1], 1); - FM_KEYON (&CH->SLOT[SLOT2], 1); - } - else - { - FM_KEYOFF(&CH->SLOT[SLOT1],~1); - FM_KEYOFF(&CH->SLOT[SLOT2],~1); - } - break; - } - } - else - { - if(v&0x20) - { - FM_KEYON (&CH->SLOT[SLOT1], 1); - FM_KEYON (&CH->SLOT[SLOT2], 1); - } - else - { - FM_KEYOFF(&CH->SLOT[SLOT1],~1); - FM_KEYOFF(&CH->SLOT[SLOT2],~1); - } - } - } - /* update */ - if(CH->block_fnum != block_fnum) - { - UINT8 block = block_fnum >> 10; - - CH->block_fnum = block_fnum; - - CH->ksl_base = ksl_tab[block_fnum>>6]; - CH->fc = chip->fn_tab[block_fnum&0x03ff] >> (7-block); - - /* BLK 2,1,0 bits -> bits 3,2,1 of kcode */ - CH->kcode = (CH->block_fnum&0x1c00)>>9; - - /* the info below is actually opposite to what is stated in the Manuals (verifed on real YMF262) */ - /* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum */ - /* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */ - if (chip->nts&0x40) - CH->kcode |= (CH->block_fnum&0x100)>>8; /* notesel == 1 */ - else - CH->kcode |= (CH->block_fnum&0x200)>>9; /* notesel == 0 */ - - if (chip->OPL3_mode & 1) - { - int chan_no = (r&0x0f) + ch_offset; - /* in OPL3 mode */ - //DO THIS: - //if this is 1st channel forming up a 4-op channel - //ALSO update slots of 2nd channel forming up 4-op channel - //else normal 2 operator function keyon/off - //OR THIS: - //if this is 2nd channel forming up 4-op channel just do nothing - //else normal 2 operator function keyon/off - switch(chan_no) - { - case 0: case 1: case 2: - case 9: case 10: case 11: - if (CH->extended) - { - //if this is 1st channel forming up a 4-op channel - //ALSO update slots of 2nd channel forming up 4-op channel - - /* refresh Total Level in FOUR SLOTs of this channel and channel+3 using data from THIS channel */ - CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl); - CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl); - (CH+3)->SLOT[SLOT1].TLL = (CH+3)->SLOT[SLOT1].TL + (CH->ksl_base>>(CH+3)->SLOT[SLOT1].ksl); - (CH+3)->SLOT[SLOT2].TLL = (CH+3)->SLOT[SLOT2].TL + (CH->ksl_base>>(CH+3)->SLOT[SLOT2].ksl); - - /* refresh frequency counter in FOUR SLOTs of this channel and channel+3 using data from THIS channel */ - CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); - CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); - CALC_FCSLOT(CH,&(CH+3)->SLOT[SLOT1]); - CALC_FCSLOT(CH,&(CH+3)->SLOT[SLOT2]); - } - else - { - //else normal 2 operator function - /* refresh Total Level in both SLOTs of this channel */ - CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl); - CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl); - - /* refresh frequency counter in both SLOTs of this channel */ - CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); - CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); - } - break; - - case 3: case 4: case 5: - case 12: case 13: case 14: - if ((CH-3)->extended) - { - //if this is 2nd channel forming up 4-op channel just do nothing - } - else - { - //else normal 2 operator function - /* refresh Total Level in both SLOTs of this channel */ - CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl); - CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl); - - /* refresh frequency counter in both SLOTs of this channel */ - CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); - CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); - } - break; - - default: - /* refresh Total Level in both SLOTs of this channel */ - CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl); - CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl); - - /* refresh frequency counter in both SLOTs of this channel */ - CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); - CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); - break; - } - } - else - { - /* in OPL2 mode */ - - /* refresh Total Level in both SLOTs of this channel */ - CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl); - CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl); - - /* refresh frequency counter in both SLOTs of this channel */ - CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); - CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); - } - } - break; - - case 0xc0: - /* CH.D, CH.C, CH.B, CH.A, FB(3bits), C */ - if( (r&0xf) > 8) return; - - CH = &chip->P_CH[(r&0xf) + ch_offset]; - - if( chip->OPL3_mode & 1 ) - { - int base = ((r&0xf) + ch_offset) * 2; - - /* OPL3 mode */ - chip->pan[ base ] = (v & 0x10) ? 1 : 0; /* ch.A */ - chip->pan[ base +1 ] = (v & 0x20) ? 1 : 0; /* ch.B */ - } - else - { - int base = ((r&0xf) + ch_offset) * 2; - - /* OPL2 mode - always enabled */ - chip->pan[ base ] = 1; /* ch.A */ - chip->pan[ base +1 ] = 1; /* ch.B */ - } - - CH->SLOT[SLOT1].FB = (v>>1)&7 ? ((v>>1)&7) + 7 : 0; - CH->SLOT[SLOT1].CON = v&1; - - if( chip->OPL3_mode & 1 ) - { - int chan_no = (r&0x0f) + ch_offset; - - switch(chan_no) - { - case 0: case 1: case 2: - case 9: case 10: case 11: - if (CH->extended) - { - UINT8 conn = (CH->SLOT[SLOT1].CON<<1) | ((CH+3)->SLOT[SLOT1].CON<<0); - switch(conn) - { - case 0: - /* 1 -> 2 -> 3 -> 4 - out */ - - CH->SLOT[SLOT1].connect = &phase_modulation; - CH->SLOT[SLOT2].connect = &phase_modulation2; - (CH+3)->SLOT[SLOT1].connect = &phase_modulation; - (CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ]; - break; - case 1: - /* 1 -> 2 -\ - 3 -> 4 -+- out */ - - CH->SLOT[SLOT1].connect = &phase_modulation; - CH->SLOT[SLOT2].connect = &chanout[ chan_no ]; - (CH+3)->SLOT[SLOT1].connect = &phase_modulation; - (CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ]; - break; - case 2: - /* 1 -----------\ - 2 -> 3 -> 4 -+- out */ - - CH->SLOT[SLOT1].connect = &chanout[ chan_no ]; - CH->SLOT[SLOT2].connect = &phase_modulation2; - (CH+3)->SLOT[SLOT1].connect = &phase_modulation; - (CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ]; - break; - case 3: - /* 1 ------\ - 2 -> 3 -+- out - 4 ------/ */ - CH->SLOT[SLOT1].connect = &chanout[ chan_no ]; - CH->SLOT[SLOT2].connect = &phase_modulation2; - (CH+3)->SLOT[SLOT1].connect = &chanout[ chan_no + 3 ]; - (CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ]; - break; - } - } - else - { - /* 2 operators mode */ - CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation; - CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset]; - } - break; - - case 3: case 4: case 5: - case 12: case 13: case 14: - if ((CH-3)->extended) - { - UINT8 conn = ((CH-3)->SLOT[SLOT1].CON<<1) | (CH->SLOT[SLOT1].CON<<0); - switch(conn) - { - case 0: - /* 1 -> 2 -> 3 -> 4 - out */ - - (CH-3)->SLOT[SLOT1].connect = &phase_modulation; - (CH-3)->SLOT[SLOT2].connect = &phase_modulation2; - CH->SLOT[SLOT1].connect = &phase_modulation; - CH->SLOT[SLOT2].connect = &chanout[ chan_no ]; - break; - case 1: - /* 1 -> 2 -\ - 3 -> 4 -+- out */ - - (CH-3)->SLOT[SLOT1].connect = &phase_modulation; - (CH-3)->SLOT[SLOT2].connect = &chanout[ chan_no - 3 ]; - CH->SLOT[SLOT1].connect = &phase_modulation; - CH->SLOT[SLOT2].connect = &chanout[ chan_no ]; - break; - case 2: - /* 1 -----------\ - 2 -> 3 -> 4 -+- out */ - - (CH-3)->SLOT[SLOT1].connect = &chanout[ chan_no - 3 ]; - (CH-3)->SLOT[SLOT2].connect = &phase_modulation2; - CH->SLOT[SLOT1].connect = &phase_modulation; - CH->SLOT[SLOT2].connect = &chanout[ chan_no ]; - break; - case 3: - /* 1 ------\ - 2 -> 3 -+- out - 4 ------/ */ - (CH-3)->SLOT[SLOT1].connect = &chanout[ chan_no - 3 ]; - (CH-3)->SLOT[SLOT2].connect = &phase_modulation2; - CH->SLOT[SLOT1].connect = &chanout[ chan_no ]; - CH->SLOT[SLOT2].connect = &chanout[ chan_no ]; - break; - } - } - else - { - /* 2 operators mode */ - CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation; - CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset]; - } - break; - - default: - /* 2 operators mode */ - CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation; - CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset]; - break; - } - } - else - { - /* OPL2 mode - always 2 operators mode */ - CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation; - CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset]; - } - break; - - case 0xe0: /* waveform select */ - slot = slot_array[r&0x1f]; - if(slot < 0) return; - - slot += ch_offset*2; - - CH = &chip->P_CH[slot/2]; - - - /* store 3-bit value written regardless of current OPL2 or OPL3 mode... (verified on real YMF262) */ - v &= 7; - CH->SLOT[slot&1].waveform_number = v; - - /* ... but select only waveforms 0-3 in OPL2 mode */ - if( !(chip->OPL3_mode & 1) ) - { - v &= 3; /* we're in OPL2 mode */ - } - CH->SLOT[slot&1].wavetable = v * SIN_LEN; - break; - } -} - -#ifdef LOG_CYM_FILE -static void cymfile_callback (int n) -{ - if (cymfile) - { - fputc( (unsigned char)0, cymfile ); - } -} -#endif - -/* lock/unlock for common table */ -static int OPL3_LockTable(void) -{ - num_lock++; - if(num_lock>1) return 0; - - /* first time */ - - cur_chip = NULL; - - if( !init_tables() ) - { - num_lock--; - return -1; - } - -#ifdef LOG_CYM_FILE - cymfile = fopen("ymf262_.cym","wb"); - if (cymfile) - timer_pulse ( TIME_IN_HZ(110), 0, cymfile_callback); /*110 Hz pulse timer*/ - else - logerror("Could not create ymf262_.cym file\n"); -#endif - - return 0; -} - -static void OPL3_UnLockTable(void) -{ - if(num_lock) num_lock--; - if(num_lock) return; - - /* last time */ - - cur_chip = NULL; - OPLCloseTable(); - -#ifdef LOG_CYM_FILE - fclose (cymfile); - cymfile = NULL; -#endif - -} - -static void OPL3ResetChip(OPL3 *chip) -{ - int c,s; - - chip->eg_timer = 0; - chip->eg_cnt = 0; - - chip->noise_rng = 1; /* noise shift register */ - chip->nts = 0; /* note split */ - OPL3_STATUS_RESET(chip,0x60); - - /* reset with register write */ - OPL3WriteReg(chip,0x01,0); /* test register */ - OPL3WriteReg(chip,0x02,0); /* Timer1 */ - OPL3WriteReg(chip,0x03,0); /* Timer2 */ - OPL3WriteReg(chip,0x04,0); /* IRQ mask clear */ - - -//FIX IT registers 101, 104 and 105 - - -//FIX IT (dont change CH.D, CH.C, CH.B and CH.A in C0-C8 registers) - for(c = 0xff ; c >= 0x20 ; c-- ) - OPL3WriteReg(chip,c,0); -//FIX IT (dont change CH.D, CH.C, CH.B and CH.A in C0-C8 registers) - for(c = 0x1ff ; c >= 0x120 ; c-- ) - OPL3WriteReg(chip,c,0); - - - - /* reset operator parameters */ - for( c = 0 ; c < 9*2 ; c++ ) - { - OPL3_CH *CH = &chip->P_CH[c]; - for(s = 0 ; s < 2 ; s++ ) - { - CH->SLOT[s].state = EG_OFF; - CH->SLOT[s].volume = MAX_ATT_INDEX; - } - } -} - -/* Create one of virtual YMF262 */ -/* 'clock' is chip clock in Hz */ -/* 'rate' is sampling rate */ -static OPL3 *OPL3Create(int type, int clock, int rate) -{ - OPL3 *chip; - - if (OPL3_LockTable() ==-1) return NULL; - - /* allocate memory block */ - chip = (OPL3 *)malloc(sizeof(OPL3)); - - if (chip==NULL) - return NULL; - - /* clear */ - memset(chip, 0, sizeof(OPL3)); - - chip->type = type; - chip->clock = clock; - chip->rate = rate; - - /* init global tables */ - OPL3_initalize(chip); - - /* reset chip */ - OPL3ResetChip(chip); - return chip; -} - -/* Destroy one of virtual YMF262 */ -static void OPL3Destroy(OPL3 *chip) -{ - OPL3_UnLockTable(); - free(chip); -} - - -/* Optional handlers */ - -static void OPL3SetTimerHandler(OPL3 *chip,OPL3_TIMERHANDLER TimerHandler,int channelOffset) -{ - chip->TimerHandler = TimerHandler; - chip->TimerParam = channelOffset; -} -static void OPL3SetIRQHandler(OPL3 *chip,OPL3_IRQHANDLER IRQHandler,int param) -{ - chip->IRQHandler = IRQHandler; - chip->IRQParam = param; -} -static void OPL3SetUpdateHandler(OPL3 *chip,OPL3_UPDATEHANDLER UpdateHandler,int param) -{ - chip->UpdateHandler = UpdateHandler; - chip->UpdateParam = param; -} - -/* YMF262 I/O interface */ -static int OPL3Write(OPL3 *chip, int a, int v) -{ - /* data bus is 8 bits */ - v &= 0xff; - - switch(a&3) - { - case 0: /* address port 0 (register set #1) */ - chip->address = v; - break; - - case 1: /* data port - ignore A1 */ - case 3: /* data port - ignore A1 */ - if(chip->UpdateHandler) chip->UpdateHandler(chip->UpdateParam,0); - OPL3WriteReg(chip,chip->address,v); - break; - - case 2: /* address port 1 (register set #2) */ - - /* verified on real YMF262: - in OPL3 mode: - address line A1 is stored during *address* write and ignored during *data* write. - - in OPL2 mode: - register set#2 writes go to register set#1 (ignoring A1) - verified on registers from set#2: 0x01, 0x04, 0x20-0xef - The only exception is register 0x05. - */ - if( chip->OPL3_mode & 1 ) - { - /* OPL3 mode */ - chip->address = v | 0x100; - } - else - { - /* in OPL2 mode the only accessible in set #2 is register 0x05 */ - if( v==5 ) - chip->address = v | 0x100; - else - chip->address = v; /* verified range: 0x01, 0x04, 0x20-0xef(set #2 becomes set #1 in opl2 mode) */ - } - break; - } - - return chip->status>>7; -} - -static unsigned char OPL3Read(OPL3 *chip,int a) -{ - if( a==0 ) - { - if (chip->st[0]) { - /* Timer A */ - if (chip->TC[0]) chip->TC[0]--; - else { - chip->TC[0]=chip->T[0]*20; - OPL3_STATUS_SET(chip,0x40); - } - } - if (chip->st[1]) { - /* Timer B */ - if (chip->TC[1]) chip->TC[1]--; - else { - chip->TC[1]=chip->T[1]*20; - OPL3_STATUS_SET(chip,0x20); - } - } - return chip->status; - } - - return 0x00; /* verified on real YMF262 */ -} - - - -static int OPL3TimerOver(OPL3 *chip,int c) -{ - if( c ) - { /* Timer B */ - OPL3_STATUS_SET(chip,0x20); - } - else - { /* Timer A */ - OPL3_STATUS_SET(chip,0x40); - } - /* reload timer */ -// if (chip->TimerHandler) (chip->TimerHandler)(chip->TimerParam+c,(double)chip->T[c]*chip->TimerBase); - return chip->status>>7; -} - - - - -#if (BUILD_YMF262) - -#define MAX_OPL3_CHIPS 2 - -static OPL3 *YMF262[MAX_OPL3_CHIPS]; /* array of pointers to the YMF262's */ -static int YMF262NumChips = 0; /* number of chips */ - -int YMF262Init(int num, int clock, int rate) -{ - int i; - - if (YMF262NumChips) - return -1; /* duplicate init. */ - - YMF262NumChips = num; - - for (i = 0;i < YMF262NumChips; i++) - { - /* emulator create */ - YMF262[i] = OPL3Create(OPL3_TYPE_YMF262,clock,rate); - if(YMF262[i] == NULL) - { - /* it's really bad - we run out of memeory */ - YMF262NumChips = 0; - return -1; - } - } - - return 0; -} - -void YMF262Shutdown(void) -{ - int i; - - for (i = 0;i < YMF262NumChips; i++) - { - /* emulator shutdown */ - OPL3Destroy(YMF262[i]); - YMF262[i] = NULL; - } - YMF262NumChips = 0; -} -void YMF262ResetChip(int which) -{ - OPL3ResetChip(YMF262[which]); -} - -int YMF262Write(int which, int a, int v) -{ - return OPL3Write(YMF262[which], a, v); -} - -unsigned char YMF262Read(int which, int a) -{ - /* Note on status register: */ - - /* YM3526(OPL) and YM3812(OPL2) return bit2 and bit1 in HIGH state */ - - /* YMF262(OPL3) always returns bit2 and bit1 in LOW state */ - /* which can be used to identify the chip */ - - /* YMF278(OPL4) returns bit2 in LOW and bit1 in HIGH state ??? info from manual - not verified */ - - return OPL3Read(YMF262[which], a); -} -int YMF262TimerOver(int which, int c) -{ - return OPL3TimerOver(YMF262[which], c); -} - -void YMF262SetTimerHandler(int which, OPL3_TIMERHANDLER TimerHandler, int channelOffset) -{ - OPL3SetTimerHandler(YMF262[which], TimerHandler, channelOffset); -} -void YMF262SetIRQHandler(int which,OPL3_IRQHANDLER IRQHandler,int param) -{ - OPL3SetIRQHandler(YMF262[which], IRQHandler, param); -} -void YMF262SetUpdateHandler(int which,OPL3_UPDATEHANDLER UpdateHandler,int param) -{ - OPL3SetUpdateHandler(YMF262[which], UpdateHandler, param); -} - - -/* -** Generate samples for one of the YMF262's -** -** 'which' is the virtual YMF262 number -** '**buffers' is table of 4 pointers to the buffers: CH.A, CH.B, CH.C and CH.D -** 'length' is the number of samples that should be generated -*/ -#if 0 -void YMF262UpdateOne(int which, INT16 **buffers, int length) -#else -void YMF262UpdateOne(int which, INT16 *buffer, int length) -#endif -{ - OPL3 *chip = YMF262[which]; - UINT8 rhythm = chip->rhythm&0x20; -#if 0 - OPL3SAMPLE *ch_a = buffers[0]; - OPL3SAMPLE *ch_b = buffers[1]; -#endif - int i; - - if( (void *)chip != cur_chip ){ - cur_chip = (void *)chip; - /* rhythm slots */ - SLOT7_1 = &chip->P_CH[7].SLOT[SLOT1]; - SLOT7_2 = &chip->P_CH[7].SLOT[SLOT2]; - SLOT8_1 = &chip->P_CH[8].SLOT[SLOT1]; - SLOT8_2 = &chip->P_CH[8].SLOT[SLOT2]; - } - for( i=0; i < length ; i++ ) - { - int a,b; - - - advance_lfo(chip); - - /* clear channel outputs */ - memset(chanout, 0, sizeof(signed int) * 18); - -//profiler_mark(PROFILER_USER1); - - /* register set #1 */ - chan_calc(&chip->P_CH[0]); /* extended 4op ch#0 part 1 or 2op ch#0 */ - if (chip->P_CH[0].extended) - chan_calc_ext(&chip->P_CH[3]); /* extended 4op ch#0 part 2 */ - else - chan_calc(&chip->P_CH[3]); /* standard 2op ch#3 */ - - - chan_calc(&chip->P_CH[1]); /* extended 4op ch#1 part 1 or 2op ch#1 */ - if (chip->P_CH[1].extended) - chan_calc_ext(&chip->P_CH[4]); /* extended 4op ch#1 part 2 */ - else - chan_calc(&chip->P_CH[4]); /* standard 2op ch#4 */ - - - chan_calc(&chip->P_CH[2]); /* extended 4op ch#2 part 1 or 2op ch#2 */ - if (chip->P_CH[2].extended) - chan_calc_ext(&chip->P_CH[5]); /* extended 4op ch#2 part 2 */ - else - chan_calc(&chip->P_CH[5]); /* standard 2op ch#5 */ - - - if(!rhythm) - { - chan_calc(&chip->P_CH[6]); - chan_calc(&chip->P_CH[7]); - chan_calc(&chip->P_CH[8]); - } - else /* Rhythm part */ - { - chan_calc_rhythm(&chip->P_CH[0], (chip->noise_rng>>0)&1 ); - } - - /* register set #2 */ - chan_calc(&chip->P_CH[ 9]); - if (chip->P_CH[9].extended) - chan_calc_ext(&chip->P_CH[12]); - else - chan_calc(&chip->P_CH[12]); - - - chan_calc(&chip->P_CH[10]); - if (chip->P_CH[10].extended) - chan_calc_ext(&chip->P_CH[13]); - else - chan_calc(&chip->P_CH[13]); - - - chan_calc(&chip->P_CH[11]); - if (chip->P_CH[11].extended) - chan_calc_ext(&chip->P_CH[14]); - else - chan_calc(&chip->P_CH[14]); - - - /* channels 15,16,17 are fixed 2-operator channels only */ - chan_calc(&chip->P_CH[15]); - chan_calc(&chip->P_CH[16]); - chan_calc(&chip->P_CH[17]); - -//profiler_mark(PROFILER_END); - - - -//profiler_mark(PROFILER_USER2); - /* accumulator register set #1 */ - a = chanout[0] * chip->pan[0]; - b = chanout[0] * chip->pan[1]; - - a += chanout[1] * chip->pan[2]; - b += chanout[1] * chip->pan[3]; - a += chanout[2] * chip->pan[4]; - b += chanout[2] * chip->pan[5]; - - a += chanout[3] * chip->pan[6]; - b += chanout[3] * chip->pan[7]; - a += chanout[4] * chip->pan[8]; - b += chanout[4] * chip->pan[9]; - a += chanout[5] * chip->pan[10]; - b += chanout[5] * chip->pan[11]; - - a += chanout[6] * chip->pan[12]; - b += chanout[6] * chip->pan[13]; - a += chanout[7] * chip->pan[14]; - b += chanout[7] * chip->pan[15]; - a += chanout[8] * chip->pan[16]; - b += chanout[8] * chip->pan[17]; - - /* accumulator register set #2 */ - a += chanout[9] * chip->pan[18]; - b += chanout[9] * chip->pan[19]; - a += chanout[10] * chip->pan[20]; - b += chanout[10] * chip->pan[21]; - a += chanout[11] * chip->pan[22]; - b += chanout[11] * chip->pan[23]; - - a += chanout[12] * chip->pan[24]; - b += chanout[12] * chip->pan[25]; - a += chanout[13] * chip->pan[26]; - b += chanout[13] * chip->pan[27]; - a += chanout[14] * chip->pan[28]; - b += chanout[14] * chip->pan[29]; - - a += chanout[15] * chip->pan[30]; - b += chanout[15] * chip->pan[31]; - a += chanout[16] * chip->pan[32]; - b += chanout[16] * chip->pan[33]; - a += chanout[17] * chip->pan[34]; - b += chanout[17] * chip->pan[35]; - - a >>= FINAL_SH; - b >>= FINAL_SH; - - /* limit check */ - a = limit( a , MAXOUT, MINOUT ); - b = limit( b , MAXOUT, MINOUT ); - - #ifdef SAVE_SAMPLE - if (which==0) - { - SAVE_ALL_CHANNELS - } - #endif - - /* store to sound buffer */ - *buffer++=(INT16)a; - *buffer++=(INT16)b; -#if 0 - ch_a[i] = a; - ch_b[i] = b; -#endif -//profiler_mark(PROFILER_END); - - advance(chip); - } - -} -#endif /* BUILD_YMF262 */ diff --git a/src/hardware/ymf262.h b/src/hardware/ymf262.h deleted file mode 100644 index 376bc62..0000000 --- a/src/hardware/ymf262.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef YMF262_H -#define YMF262_H - - -#define BUILD_YMF262 (HAS_YMF262) - - -/* select number of output bits: 8 or 16 */ -#define OPL3_SAMPLE_BITS 16 - -/* compiler dependence */ -#ifndef OSD_CPU_H -#define OSD_CPU_H -typedef unsigned char UINT8; /* unsigned 8bit */ -typedef unsigned short UINT16; /* unsigned 16bit */ -typedef unsigned int UINT32; /* unsigned 32bit */ -typedef signed char INT8; /* signed 8bit */ -typedef signed short INT16; /* signed 16bit */ -typedef signed int INT32; /* signed 32bit */ -#endif - -#if (OPL3_SAMPLE_BITS==16) -typedef INT16 OPL3SAMPLE; -#endif -#if (OPL3_SAMPLE_BITS==8) -typedef INT8 OPL3SAMPLE; -#endif - - -typedef void (*OPL3_TIMERHANDLER)(int channel,double interval_Sec); -typedef void (*OPL3_IRQHANDLER)(int param,int irq); -typedef void (*OPL3_UPDATEHANDLER)(int param,int min_interval_us); - - - -#if BUILD_YMF262 - -int YMF262Init(int num, int clock, int rate); -void YMF262Shutdown(void); -void YMF262ResetChip(int which); -int YMF262Write(int which, int a, int v); -unsigned char YMF262Read(int which, int a); -int YMF262TimerOver(int which, int c); -void YMF262UpdateOne(int which, INT16 **buffers, int length); - -void YMF262SetTimerHandler(int which, OPL3_TIMERHANDLER TimerHandler, int channelOffset); -void YMF262SetIRQHandler(int which, OPL3_IRQHANDLER IRQHandler, int param); -void YMF262SetUpdateHandler(int which, OPL3_UPDATEHANDLER UpdateHandler, int param); - -#endif - - -#endif /* YMF262_H */ diff --git a/src/ints/Makefile.am b/src/ints/Makefile.am index bf3d769..f5a095e 100644 --- a/src/ints/Makefile.am +++ b/src/ints/Makefile.am @@ -1,7 +1,6 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include - -noinst_LIBRARIES = libints.a -libints_a_SOURCES = mouse.cpp xms.cpp xms.h ems.cpp \ - int10.cpp int10.h int10_char.cpp int10_memory.cpp int10_misc.cpp int10_modes.cpp \ - int10_vesa.cpp int10_pal.cpp int10_put_pixel.cpp int10_video_state.cpp int10_vptable.cpp \ - bios.cpp bios_disk.cpp bios_keyboard.cpp +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libints.a +libints_a_SOURCES = mouse.cpp xms.cpp ems.cpp \ + int10.cpp int10.h int10_char.cpp int10_memory.cpp int10_misc.cpp int10_modes.cpp int10_pal.cpp int10_put_pixel.cpp \ + bios.cpp bios_disk.cpp bios_keyboard.cpp diff --git a/src/ints/Makefile.in b/src/ints/Makefile.in new file mode 100644 index 0000000..228ddbd --- /dev/null +++ b/src/ints/Makefile.in @@ -0,0 +1,333 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libints.a +libints_a_SOURCES = mouse.cpp xms.cpp ems.cpp \ + int10.cpp int10.h int10_char.cpp int10_memory.cpp int10_misc.cpp int10_modes.cpp int10_pal.cpp int10_put_pixel.cpp \ + bios.cpp bios_disk.cpp bios_keyboard.cpp + +subdir = src/ints +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libints_a_AR = $(AR) cru +libints_a_LIBADD = +am_libints_a_OBJECTS = mouse.$(OBJEXT) xms.$(OBJEXT) ems.$(OBJEXT) \ + int10.$(OBJEXT) int10_char.$(OBJEXT) int10_memory.$(OBJEXT) \ + int10_misc.$(OBJEXT) int10_modes.$(OBJEXT) int10_pal.$(OBJEXT) \ + int10_put_pixel.$(OBJEXT) bios.$(OBJEXT) bios_disk.$(OBJEXT) \ + bios_keyboard.$(OBJEXT) +libints_a_OBJECTS = $(am_libints_a_OBJECTS) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/bios.Po ./$(DEPDIR)/bios_disk.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/bios_keyboard.Po ./$(DEPDIR)/ems.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/int10.Po ./$(DEPDIR)/int10_char.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/int10_memory.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/int10_misc.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/int10_modes.Po ./$(DEPDIR)/int10_pal.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/int10_put_pixel.Po ./$(DEPDIR)/mouse.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/xms.Po +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +CXXFLAGS = @CXXFLAGS@ +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libints_a_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libints_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/ints/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +AR = ar + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libints.a: $(libints_a_OBJECTS) $(libints_a_DEPENDENCIES) + -rm -f libints.a + $(libints_a_AR) libints.a $(libints_a_OBJECTS) $(libints_a_LIBADD) + $(RANLIB) libints.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bios.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bios_disk.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bios_keyboard.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ems.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_char.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_memory.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_misc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_modes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_pal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_put_pixel.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mouse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xms.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `cygpath -w $<` +CXXDEPMODE = @CXXDEPMODE@ +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic tags uninstall uninstall-am \ + uninstall-info-am + +# 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/ints/bios.cpp b/src/ints/bios.cpp index 87bbc82..963fbb0 100644 --- a/src/ints/bios.cpp +++ b/src/ints/bios.cpp @@ -1,1068 +1,235 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: bios.cpp,v 1.73 2009/01/21 21:50:23 qbix79 Exp $ */ - -#include "dosbox.h" -#include "mem.h" -#include "bios.h" -#include "regs.h" -#include "cpu.h" -#include "callback.h" -#include "inout.h" -#include "pic.h" -#include "joystick.h" -#include "mouse.h" -#include "setup.h" -#include "serialport.h" - - -/* if mem_systems 0 then size_extended is reported as the real size else - * zero is reported. ems and xms can increase or decrease the other_memsystems - * counter using the BIOS_ZeroExtendedSize call */ -static Bit16u size_extended; -static Bits other_memsystems=0; -void CMOS_SetRegister(Bitu regNr, Bit8u val); //For setting equipment word - -static Bitu INT70_Handler(void) { - /* Acknowledge irq with cmos */ - IO_Write(0x70,0xc); - IO_Read(0x71); - if (mem_readb(BIOS_WAIT_FLAG_ACTIVE)) { - Bit32u count=mem_readd(BIOS_WAIT_FLAG_COUNT); - if (count>997) { - mem_writed(BIOS_WAIT_FLAG_COUNT,count-997); - } else { - mem_writed(BIOS_WAIT_FLAG_COUNT,0); - PhysPt where=Real2Phys(mem_readd(BIOS_WAIT_FLAG_POINTER)); - mem_writeb(where,mem_readb(where)|0x80); - mem_writeb(BIOS_WAIT_FLAG_ACTIVE,0); - mem_writed(BIOS_WAIT_FLAG_POINTER,RealMake(0,BIOS_WAIT_FLAG_TEMP)); - IO_Write(0x70,0xb); - IO_Write(0x71,IO_Read(0x71)&~0x40); - } - } - /* Signal EOI to both pics */ - IO_Write(0xa0,0x20); - IO_Write(0x20,0x20); - return 0; -} - -CALLBACK_HandlerObject* tandy_DAC_callback[2]; -static struct { - Bit16u port; - Bit8u irq; - Bit8u dma; -} tandy_sb; - -static bool Tandy_ProbeSBPort(Bit16u sbport) { - IO_Write(sbport+0x6,1); - IO_Write(sbport+0x6,0); - while (!(IO_Read(sbport+0xe)&0x80)) ; - if (IO_Read(sbport+0xa)==0xaa) return true; - else return false; -} - -static bool Tandy_InitializeSB() { - /* see if soundblaster module available and at what port */ - if (Tandy_ProbeSBPort(0x220)) tandy_sb.port=0x220; - else if (Tandy_ProbeSBPort(0x230)) tandy_sb.port=0x230; - else if (Tandy_ProbeSBPort(0x210)) tandy_sb.port=0x210; - else if (Tandy_ProbeSBPort(0x240)) tandy_sb.port=0x240; - else if (Tandy_ProbeSBPort(0x250)) tandy_sb.port=0x250; - else if (Tandy_ProbeSBPort(0x260)) tandy_sb.port=0x260; - else { - /* no soundblaster accessible, disable Tandy DAC */ - tandy_sb.port=0; - return false; - } - - /* try to detect IRQ setting */ - IO_Write(tandy_sb.port+0x4,0x80); - Bit8u rval=IO_Read(tandy_sb.port+0x5); - if (rval && (rval!=0xff)) { - if (rval&1) tandy_sb.irq=0x02; - else if (rval&2) tandy_sb.irq=0x05; - else if (rval&4) tandy_sb.irq=0x07; - else tandy_sb.irq=0x10; - } else tandy_sb.irq=0x07; /* assume irq=7 for older soundblaster settings */ - - /* try to detect DMA setting */ - IO_Write(tandy_sb.port+0x4,0x81); - rval=IO_Read(tandy_sb.port+0x5); - if (rval && (rval!=0xff)) { - if (rval&1) tandy_sb.dma=0x00; - else if (rval&2) tandy_sb.dma=0x01; - else tandy_sb.dma=0x03; - } else tandy_sb.dma=0x01; /* assume dma=1 for older soundblaster settings */ - - return true; -} - -/* check if Tandy DAC is still playing */ -static bool Tandy_TransferInProgress(void) { - if (real_readw(0x40,0xd0)) return true; /* not yet done */ - if (real_readb(0x40,0xd4)==0xff) return false; /* still in init-state */ - - IO_Write(0x0c,0x00); - Bit16u datalen=IO_ReadB(tandy_sb.dma*2+1); - datalen|=(IO_ReadB(tandy_sb.dma*2+1)<<8); - if (datalen==0xffff) return false; /* no DMA transfer */ - else if ((datalen<0x10) && (real_readb(0x40,0xd4)==0x0f) && (real_readw(0x40,0xd2)==0x1c)) { - /* stop already requested */ - return false; - } - return true; -} - -static void Tandy_SetupTransfer(PhysPt bufpt,bool isplayback) { - Bitu length=real_readw(0x40,0xd0); - if (length==0) return; /* nothing to do... */ - - if (tandy_sb.port==0) return; - - /* revector IRQ-handler if necessary */ - RealPt current_irq=RealGetVec(tandy_sb.irq+8); - if (current_irq!=tandy_DAC_callback[0]->Get_RealPointer()) { - real_writed(0x40,0xd6,current_irq); - RealSetVec(tandy_sb.irq+8,tandy_DAC_callback[0]->Get_RealPointer()); - } - - IO_Write(tandy_sb.port+0xc,0xd0); /* stop DMA transfer */ - IO_Write(0x21,IO_Read(0x21)&(~(1<>16)&0xff); - IO_Write(tandy_sb.dma*2,(Bit8u)(bufpt&0xff)); - IO_Write(tandy_sb.dma*2,(Bit8u)((bufpt>>8)&0xff)); - switch (tandy_sb.dma) { - case 0: IO_Write(0x87,bufpage); break; - case 1: IO_Write(0x83,bufpage); break; - case 2: IO_Write(0x81,bufpage); break; - case 3: IO_Write(0x82,bufpage); break; - } - real_writeb(0x40,0xd4,bufpage); - - /* calculate transfer size (respects segment boundaries) */ - Bit32u tlength=length; - if (tlength+(bufpt&0xffff)>0x10000) tlength=0x10000-(bufpt&0xffff); - real_writew(0x40,0xd0,(Bit16u)(length-tlength)); /* remaining buffer length */ - tlength--; - - /* set transfer size */ - IO_Write(tandy_sb.dma*2+1,(Bit8u)(tlength&0xff)); - IO_Write(tandy_sb.dma*2+1,(Bit8u)((tlength>>8)&0xff)); - IO_Write(0x0a,tandy_sb.dma); /* enable DMA channel */ - - Bitu delay=real_readw(0x40,0xd2)&0xfff; - /* set frequency */ - IO_Write(tandy_sb.port+0xc,0x40); - IO_Write(tandy_sb.port+0xc,256-delay*100/358); - /* set playback type to 8bit */ - if (isplayback) IO_Write(tandy_sb.port+0xc,0x14); - else IO_Write(tandy_sb.port+0xc,0x24); - /* set transfer size */ - IO_Write(tandy_sb.port+0xc,(Bit8u)(tlength&0xff)); - IO_Write(tandy_sb.port+0xc,(Bit8u)((tlength>>8)&0xff)); - - if (!isplayback) { - /* mark transfer as recording operation */ - real_writew(0x40,0xd2,delay|0x1000); - } -} - -static Bitu IRQ_TandyDAC(void) { - if (real_readw(0x40,0xd0)) { /* play/record next buffer */ - /* acknowledge IRQ */ - IO_Write(0x20,0x20); - IO_Read(tandy_sb.port+0xe); - - /* buffer starts at the next page */ - Bit8u npage=real_readb(0x40,0xd4)+1; - real_writeb(0x40,0xd4,npage); - - Bitu rb=real_readb(0x40,0xd3); - if (rb&0x10) { - /* start recording */ - real_writeb(0x40,0xd3,rb&0xef); - Tandy_SetupTransfer(npage<<16,false); - } else { - /* start playback */ - Tandy_SetupTransfer(npage<<16,true); - } - } else { /* playing/recording is finished */ - RealSetVec(tandy_sb.irq+8,real_readd(0x40,0xd6)); - - /* turn off speaker and acknowledge soundblaster IRQ */ - IO_Write(tandy_sb.port+0xc,0xd3); - IO_Read(tandy_sb.port+0xe); - - /* issue BIOS tandy sound device busy callout */ - SegSet16(cs, RealSeg(tandy_DAC_callback[1]->Get_RealPointer())); - reg_ip = RealOff(tandy_DAC_callback[1]->Get_RealPointer()); - } - return CBRET_NONE; -} - -static void TandyDAC_Handler(Bit8u tfunction) { - if (!tandy_sb.port) return; - switch (tfunction) { - case 0x81: /* Tandy sound system check */ - reg_ax=0xc4; - CALLBACK_SCF(Tandy_TransferInProgress()); - break; - case 0x82: /* Tandy sound system start recording */ - case 0x83: /* Tandy sound system start playback */ - if (Tandy_TransferInProgress()) { - /* cannot play yet as the last transfer isn't finished yet */ - reg_ah=0x00; - CALLBACK_SCF(true); - break; - } - /* store buffer length */ - real_writew(0x40,0xd0,reg_cx); - /* store delay and volume */ - real_writew(0x40,0xd2,(reg_dx&0xfff)|((reg_al&7)<<13)); - Tandy_SetupTransfer(PhysMake(SegValue(es),reg_bx),reg_ah==0x83); - reg_ah=0x00; - CALLBACK_SCF(false); - break; - case 0x84: /* Tandy sound system stop playing */ - reg_ah=0x00; - - /* setup for a small buffer with silence */ - real_writew(0x40,0xd0,0x0a); - real_writew(0x40,0xd2,0x1c); - Tandy_SetupTransfer(PhysMake(0xf000,0xa084),true); - CALLBACK_SCF(false); - break; - case 0x85: /* Tandy sound system reset */ - reg_ah=0x00; - CALLBACK_SCF(false); - break; - } -} - -static Bitu INT1A_Handler(void) { - switch (reg_ah) { - case 0x00: /* Get System time */ - { - Bit32u ticks=mem_readd(BIOS_TIMER); - reg_al=0; /* Midnight never passes :) */ - reg_cx=(Bit16u)(ticks >> 16); - reg_dx=(Bit16u)(ticks & 0xffff); - break; - } - case 0x01: /* Set System time */ - mem_writed(BIOS_TIMER,(reg_cx<<16)|reg_dx); - break; - case 0x02: /* GET REAL-TIME CLOCK TIME (AT,XT286,PS) */ - IO_Write(0x70,0x04); //Hours - reg_ch=IO_Read(0x71); - IO_Write(0x70,0x02); //Minutes - reg_cl=IO_Read(0x71); - IO_Write(0x70,0x00); //Seconds - reg_dh=IO_Read(0x71); - reg_dl=0; //Daylight saving disabled - CALLBACK_SCF(false); - break; - case 0x04: /* GET REAL-TIME ClOCK DATE (AT,XT286,PS) */ - IO_Write(0x70,0x32); //Centuries - reg_ch=IO_Read(0x71); - IO_Write(0x70,0x09); //Years - reg_cl=IO_Read(0x71); - IO_Write(0x70,0x08); //Months - reg_dh=IO_Read(0x71); - IO_Write(0x70,0x07); //Days - reg_dl=IO_Read(0x71); - CALLBACK_SCF(false); - break; - case 0x80: /* Pcjr Setup Sound Multiplexer */ - LOG(LOG_BIOS,LOG_ERROR)("INT1A:80:Setup tandy sound multiplexer to %d",reg_al); - break; - case 0x81: /* Tandy sound system check */ - case 0x82: /* Tandy sound system start recording */ - case 0x83: /* Tandy sound system start playback */ - case 0x84: /* Tandy sound system stop playing */ - case 0x85: /* Tandy sound system reset */ - TandyDAC_Handler(reg_ah); - break; - case 0xb1: /* PCI Bios Calls */ - LOG(LOG_BIOS,LOG_ERROR)("INT1A:PCI bios call %2X",reg_al); - CALLBACK_SCF(true); - break; - default: - LOG(LOG_BIOS,LOG_ERROR)("INT1A:Undefined call %2X",reg_ah); - } - return CBRET_NONE; -} - -static Bitu INT11_Handler(void) { - reg_ax=mem_readw(BIOS_CONFIGURATION); - return CBRET_NONE; -} -/* - * Define the following define to 1 if you want dosbox to check - * the system time every 5 seconds and adjust 1/2 a second to sync them. - */ -#ifndef DOSBOX_CLOCKSYNC -#define DOSBOX_CLOCKSYNC 0 -#endif -static Bitu INT8_Handler(void) { - /* Increase the bios tick counter */ - Bit32u value = mem_readd(BIOS_TIMER) + 1; -#if DOSBOX_CLOCKSYNC - static bool check = false; - if((value %50)==0) { - if(((value %100)==0) && check) { - check = false; - time_t curtime;struct tm *loctime; - curtime = time (NULL);loctime = localtime (&curtime); - Bit32u ticksnu = (Bit32u)((loctime->tm_hour*3600+loctime->tm_min*60+loctime->tm_sec)*(float)PIT_TICK_RATE/65536.0); - Bit32s bios = value;Bit32s tn = ticksnu; - Bit32s diff = tn - bios; - if(diff>0) { - if(diff < 18) { diff = 0; } else diff = 9; - } else { - if(diff > -18) { diff = 0; } else diff = -9; - } - - value += diff; - } else if((value%100)==50) check = true; - } -#endif - mem_writed(BIOS_TIMER,value); - - /* decrease floppy motor timer */ - Bit8u val = mem_readb(BIOS_DISK_MOTOR_TIMEOUT); - if (val) mem_writeb(BIOS_DISK_MOTOR_TIMEOUT,val-1); - /* and running drive */ - mem_writeb(BIOS_DRIVE_RUNNING,mem_readb(BIOS_DRIVE_RUNNING) & 0xF0); - return CBRET_NONE; -} -#undef DOSBOX_CLOCKSYNC - -static Bitu INT1C_Handler(void) { - return CBRET_NONE; -} - -static Bitu INT12_Handler(void) { - reg_ax=mem_readw(BIOS_MEMORY_SIZE); - return CBRET_NONE; -} - -static Bitu INT17_Handler(void) { - LOG(LOG_BIOS,LOG_NORMAL)("INT17:Function %X",reg_ah); - switch(reg_ah) { - case 0x00: /* PRINTER: Write Character */ - reg_ah=1; /* Report a timeout */ - break; - case 0x01: /* PRINTER: Initialize port */ - break; - case 0x02: /* PRINTER: Get Status */ - reg_ah=0; - break; - case 0x20: /* Some sort of printerdriver install check*/ - break; - default: - E_Exit("Unhandled INT 17 call %2X",reg_ah); - }; - return CBRET_NONE; -} - -static Bitu INT14_Handler(void) -{ - if(reg_ah > 0x3 || reg_dx > 0x3) { // 0-3 serial port functions - // and no more than 4 serial ports - LOG_MSG("BIOS INT14: Unhandled call AH=%2X DX=%4x",reg_ah,reg_dx); - return CBRET_NONE; - } - - Bit16u port = real_readw(0x40,reg_dx*2); // DX is always port number - if(port==0) { - LOG(LOG_BIOS,LOG_NORMAL)("BIOS INT14: port %d does not exist.",reg_dx); - return CBRET_NONE; - } - switch (reg_ah) - { - case 0x00: /* Init port */ - // Parameters: - // AL: port parameters - // Return: - // AH: line status - // AL: modem status - { - // set baud rate - Bitu baudrate = 9600; - Bit16u baudresult; - Bitu rawbaud=reg_al>>5; - - if(rawbaud==0){ baudrate=110;} - else if (rawbaud==1){ baudrate=150;} - else if (rawbaud==2){ baudrate=300;} - else if (rawbaud==3){ baudrate=600;} - else if (rawbaud==4){ baudrate=1200;} - else if (rawbaud==5){ baudrate=2400;} - else if (rawbaud==6){ baudrate=4800;} - else if (rawbaud==7){ baudrate=9600;} - - baudresult = (Bit16u)(115200 / baudrate); - - IO_WriteB(port+3, 0x80); // enable divider access - IO_WriteB(port,(Bit8u)baudresult&0xff); - IO_WriteB(port+1,(Bit8u)(baudresult>>8)); - - // set line parameters, disable divider access - IO_WriteB(port+3, reg_al&0x1F);//LCR - - // disable interrupts - IO_WriteB(port+1, 0); - IO_ReadB(port+2); - - // get result - reg_ah=IO_ReadB(port+5); - reg_al=IO_ReadB(port+6); - CALLBACK_SCF(false); - } - break; - case 0x01: /* Write character */ - // Parameters: - // AL: character - // Return: - // AH: line status - // AL: modem status - { - if(serialports[reg_dx]) { - bool timeout; - // switch modem lines on - IO_WriteB(port+4,0x3); - timeout = !serialports[reg_dx]->Putchar(reg_al,true,true, - mem_readb(BIOS_COM1_TIMEOUT+reg_dx)*1000); - // get result - reg_ah=IO_ReadB(port+5); - if(timeout) reg_ah |= 0x80; - } - CALLBACK_SCF(false); - } - break; - - case 0x02: /* Read character */ - { - if(serialports[reg_dx]) { - bool timeout; - Bit8u buffer; - // switch modem lines on - IO_WriteB(port+4,0x3); - // wait for something - timeout = !serialports[reg_dx]->Getchar(&buffer,®_ah,true, - mem_readb(BIOS_COM1_TIMEOUT+reg_dx)*1000); - - // RTS off - IO_WriteB(port+4,0x1); - // get result - reg_ah=IO_ReadB(port+5); - if(timeout) reg_ah |= 0x80; - else reg_al=buffer; - } - CALLBACK_SCF(false); - break; - } - case 0x03: // get status - { - reg_ah=IO_ReadB(port+5); - reg_al=IO_ReadB(port+6); - CALLBACK_SCF(false); - } - break; - } - return CBRET_NONE; -} - -static Bitu INT15_Handler(void) { - static Bitu biosConfigSeg=0; - switch (reg_ah) { - case 0x06: - LOG(LOG_BIOS,LOG_NORMAL)("INT15 Unkown Function 6"); - break; - case 0xC0: /* Get Configuration*/ - { - if (biosConfigSeg==0) biosConfigSeg = DOS_GetMemory(1); //We have 16 bytes - PhysPt data = PhysMake(biosConfigSeg,0); - mem_writew(data,8); // 8 Bytes following - if (IS_TANDY_ARCH) { - if (machine==MCH_TANDY) { - // Model ID (Tandy) - mem_writeb(data+2,0xFF); - } else { - // Model ID (PCJR) - mem_writeb(data+2,0xFD); - } - mem_writeb(data+3,0x0A); // Submodel ID - mem_writeb(data+4,0x10); // Bios Revision - /* Tandy doesn't have a 2nd PIC, left as is for now */ - mem_writeb(data+5,(1<<6)|(1<<5)|(1<<4)); // Feature Byte 1 - } else { - mem_writeb(data+2,0xFC); // Model ID (PC) - mem_writeb(data+3,0x00); // Submodel ID - mem_writeb(data+4,0x01); // Bios Revision - mem_writeb(data+5,(1<<6)|(1<<5)|(1<<4)); // Feature Byte 1 - } - mem_writeb(data+6,(1<<6)); // Feature Byte 2 - mem_writeb(data+7,0); // Feature Byte 3 - mem_writeb(data+8,0); // Feature Byte 4 - mem_writeb(data+9,0); // Feature Byte 5 - CPU_SetSegGeneral(es,biosConfigSeg); - reg_bx = 0; - reg_ah = 0; - CALLBACK_SCF(false); - }; break; - case 0x4f: /* BIOS - Keyboard intercept */ - /* Carry should be set but let's just set it just in case */ - CALLBACK_SCF(true); - break; - case 0x83: /* BIOS - SET EVENT WAIT INTERVAL */ - { - if(reg_al == 0x01) { /* Cancel it */ - mem_writeb(BIOS_WAIT_FLAG_ACTIVE,0); - IO_Write(0x70,0xb); - IO_Write(0x71,IO_Read(0x71)&~0x40); - CALLBACK_SCF(false); - break; - } - if (mem_readb(BIOS_WAIT_FLAG_ACTIVE)) { - reg_ah=0x80; - CALLBACK_SCF(true); - break; - } - Bit32u count=(reg_cx<<16)|reg_dx; - mem_writed(BIOS_WAIT_FLAG_POINTER,RealMake(SegValue(es),reg_bx)); - mem_writed(BIOS_WAIT_FLAG_COUNT,count); - mem_writeb(BIOS_WAIT_FLAG_ACTIVE,1); - /* Reprogram RTC to start */ - IO_Write(0x70,0xb); - IO_Write(0x71,IO_Read(0x71)|0x40); - CALLBACK_SCF(false); - } - break; - case 0x84: /* BIOS - JOYSTICK SUPPORT (XT after 11/8/82,AT,XT286,PS) */ - if (reg_dx == 0x0000) { - // Get Joystick button status - if (JOYSTICK_IsEnabled(0) || JOYSTICK_IsEnabled(1)) { - reg_al = IO_ReadB(0x201)&0xf0; - CALLBACK_SCF(false); - } else { - // dos values - reg_ax = 0x00f0; reg_dx = 0x0201; - CALLBACK_SCF(true); - } - } else if (reg_dx == 0x0001) { - if (JOYSTICK_IsEnabled(0)) { - reg_ax = (Bit16u)(JOYSTICK_GetMove_X(0)*127+128); - reg_bx = (Bit16u)(JOYSTICK_GetMove_Y(0)*127+128); - if(JOYSTICK_IsEnabled(1)) { - reg_cx = (Bit16u)(JOYSTICK_GetMove_X(1)*127+128); - reg_dx = (Bit16u)(JOYSTICK_GetMove_Y(1)*127+128); - } - else { - reg_cx = reg_dx = 0; - } - CALLBACK_SCF(false); - } else if (JOYSTICK_IsEnabled(1)) { - reg_ax = reg_bx = 0; - reg_cx = (Bit16u)(JOYSTICK_GetMove_X(1)*127+128); - reg_dx = (Bit16u)(JOYSTICK_GetMove_Y(1)*127+128); - CALLBACK_SCF(false); - } else { - reg_ax = reg_bx = reg_cx = reg_dx = 0; - CALLBACK_SCF(true); - } - } else { - LOG(LOG_BIOS,LOG_ERROR)("INT15:84:Unknown Bios Joystick functionality."); - } - break; - case 0x86: /* BIOS - WAIT (AT,PS) */ - { - if (mem_readb(BIOS_WAIT_FLAG_ACTIVE)) { - reg_ah=0x83; - CALLBACK_SCF(true); - break; - } - Bit32u count=(reg_cx<<16)|reg_dx; - mem_writed(BIOS_WAIT_FLAG_POINTER,RealMake(0,BIOS_WAIT_FLAG_TEMP)); - mem_writed(BIOS_WAIT_FLAG_COUNT,count); - mem_writeb(BIOS_WAIT_FLAG_ACTIVE,1); - /* Reprogram RTC to start */ - IO_Write(0x70,0xb); - IO_Write(0x71,IO_Read(0x71)|0x40); - while (mem_readd(BIOS_WAIT_FLAG_COUNT)) { - CALLBACK_Idle(); - } - CALLBACK_SCF(false); - } - case 0x87: /* Copy extended memory */ - { - bool enabled = MEM_A20_Enabled(); - MEM_A20_Enable(true); - Bitu bytes = reg_cx * 2; - PhysPt data = SegPhys(es)+reg_si; - PhysPt source = (mem_readd(data+0x12) & 0x00FFFFFF) + (mem_readb(data+0x16)<<24); - PhysPt dest = (mem_readd(data+0x1A) & 0x00FFFFFF) + (mem_readb(data+0x1E)<<24); - MEM_BlockCopy(dest,source,bytes); - reg_ax = 0x00; - MEM_A20_Enable(enabled); - CALLBACK_SCF(false); - break; - } - case 0x88: /* SYSTEM - GET EXTENDED MEMORY SIZE (286+) */ - reg_ax=other_memsystems?0:size_extended; - LOG(LOG_BIOS,LOG_NORMAL)("INT15:Function 0x88 Remaining %04X kb",reg_ax); - CALLBACK_SCF(false); - break; - case 0x89: /* SYSTEM - SWITCH TO PROTECTED MODE */ - { - IO_Write(0x20,0x10);IO_Write(0x21,reg_bh);IO_Write(0x21,0); - IO_Write(0xA0,0x10);IO_Write(0xA1,reg_bl);IO_Write(0xA1,0); - MEM_A20_Enable(true); - PhysPt table=SegPhys(es)+reg_si; - CPU_LGDT(mem_readw(table+0x8),mem_readd(table+0x8+0x2) & 0xFFFFFF); - CPU_LIDT(mem_readw(table+0x10),mem_readd(table+0x10+0x2) & 0xFFFFFF); - CPU_SET_CRX(0,CPU_GET_CRX(0)|1); - CPU_SetSegGeneral(ds,0x18); - CPU_SetSegGeneral(es,0x20); - CPU_SetSegGeneral(ss,0x28); - reg_sp+=6; //Clear stack of interrupt frame - CPU_SetFlags(0,FMASK_ALL); - reg_ax=0; - CPU_JMP(false,0x30,reg_cx,0); - } - break; - case 0x90: /* OS HOOK - DEVICE BUSY */ - CALLBACK_SCF(false); - reg_ah=0; - break; - case 0x91: /* OS HOOK - DEVICE POST */ - CALLBACK_SCF(false); - reg_ah=0; - break; - case 0xc2: /* BIOS PS2 Pointing Device Support */ - switch (reg_al) { - case 0x00: // enable/disable - if (reg_bh==0) { // disable - Mouse_SetPS2State(false); - reg_ah=0; - CALLBACK_SCF(false); - } else if (reg_bh==0x01) { //enable - if (!Mouse_SetPS2State(true)) { - reg_ah=5; - CALLBACK_SCF(true); - break; - } - reg_ah=0; - CALLBACK_SCF(false); - } else { - CALLBACK_SCF(true); - reg_ah=1; - } - break; - case 0x01: // reset - reg_bx=0x00aa; // mouse - // fall through - case 0x05: // initialize - Mouse_SetPS2State(false); - CALLBACK_SCF(false); - reg_ah=0; - break; - case 0x02: // set sampling rate - case 0x03: // set resolution - CALLBACK_SCF(false); - reg_ah=0; - break; - case 0x04: // get type - reg_bh=0; // ID - CALLBACK_SCF(false); - reg_ah=0; - break; - case 0x06: // extended commands - if ((reg_bh==0x01) || (reg_bh==0x02)) { - CALLBACK_SCF(false); - reg_ah=0; - } else { - CALLBACK_SCF(true); - reg_ah=1; - } - break; - case 0x07: // set callback - Mouse_ChangePS2Callback(SegValue(es),reg_bx); - CALLBACK_SCF(false); - reg_ah=0; - break; - default: - CALLBACK_SCF(true); - reg_ah=1; - break; - } - break; - case 0xc3: /* set carry flag so BorlandRTM doesn't assume a VECTRA/PS2 */ - reg_ah=0x86; - CALLBACK_SCF(true); - break; - case 0xc4: /* BIOS POS Programm option Select */ - LOG(LOG_BIOS,LOG_NORMAL)("INT15:Function %X called, bios mouse not supported",reg_ah); - CALLBACK_SCF(true); - break; - default: - LOG(LOG_BIOS,LOG_ERROR)("INT15:Unknown call %4X",reg_ax); - reg_ah=0x86; - CALLBACK_SCF(true); - if ((IS_EGAVGA_ARCH) || (machine==MCH_CGA)) { - /* relict from comparisons, as int15 exits with a retf2 instead of an iret */ - CALLBACK_SZF(false); - } - } - return CBRET_NONE; -} - -static Bitu Reboot_Handler(void) { - // switch to text mode, notify user (let's hope INT10 still works) - const char* const text = "\n\n Reboot requested, quitting now."; - reg_ax = 0; - CALLBACK_RunRealInt(0x10); - reg_ah = 0xe; - reg_bx = 0; - for(Bitu i = 0; i < strlen(text);i++) { - reg_al = text[i]; - CALLBACK_RunRealInt(0x10); - } - LOG_MSG(text); - double start = PIC_FullIndex(); - while((PIC_FullIndex()-start)<3000) CALLBACK_Idle(); - throw 1; - return CBRET_NONE; -} - -void BIOS_ZeroExtendedSize(bool in) { - if(in) other_memsystems++; - else other_memsystems--; - if(other_memsystems < 0) other_memsystems=0; -} - -#define RAM_REFRESH_DELAY 16.7f - -static void RAMRefresh_Event(Bitu val) { - PIC_ActivateIRQ(5); - PIC_AddEvent(RAMRefresh_Event,RAM_REFRESH_DELAY); -} - -void BIOS_SetupKeyboard(void); -void BIOS_SetupDisks(void); - -class BIOS:public Module_base{ -private: - CALLBACK_HandlerObject callback[11]; -public: - BIOS(Section* configuration):Module_base(configuration){ - /* tandy DAC can be requested in tandy_sound.cpp by initializing this field */ - bool use_tandyDAC=(real_readb(0x40,0xd4)==0xff); - - /* Clear the Bios Data Area (0x400-0x5ff, 0x600- is accounted to DOS) */ - for (Bit16u i=0;i<0x200;i++) real_writeb(0x40,i,0); - - /* Setup all the interrupt handlers the bios controls */ - /* INT 8 Clock IRQ Handler */ - callback[0].Install(INT8_Handler,CB_IRQ0,"Int 8 Clock"); - callback[0].Set_RealVec(0x8); - // pseudocode for CB_IRQ0: - // callback INT8_Handler - // push ax,dx,ds - // int 0x1c - // cli - // pop ds,dx - // mov al, 0x20 - // out 0x20, al - // pop ax - // iret - - mem_writed(BIOS_TIMER,0); //Calculate the correct time - - /* INT 11 Get equipment list */ - callback[1].Install(&INT11_Handler,CB_IRET,"Int 11 Equipment"); - callback[1].Set_RealVec(0x11); - - /* INT 12 Memory Size default at 640 kb */ - callback[2].Install(&INT12_Handler,CB_IRET,"Int 12 Memory"); - callback[2].Set_RealVec(0x12); - if (IS_TANDY_ARCH) { - /* reduce reported memory size for the Tandy (32k graphics memory - at the end of the conventional 640k) */ - if (machine==MCH_TANDY) mem_writew(BIOS_MEMORY_SIZE,608); - else mem_writew(BIOS_MEMORY_SIZE,640); - mem_writew(BIOS_TRUE_MEMORY_SIZE,640); - } else mem_writew(BIOS_MEMORY_SIZE,640); - - /* INT 13 Bios Disk Support */ - BIOS_SetupDisks(); - - /* INT 14 Serial Ports */ - callback[3].Install(&INT14_Handler,CB_IRET_STI,"Int 14 COM-port"); - callback[3].Set_RealVec(0x14); - - /* INT 15 Misc Calls */ - callback[4].Install(&INT15_Handler,CB_IRET,"Int 15 Bios"); - callback[4].Set_RealVec(0x15); - - /* INT 16 Keyboard handled in another file */ - BIOS_SetupKeyboard(); - - /* INT 17 Printer Routines */ - callback[5].Install(&INT17_Handler,CB_IRET_STI,"Int 17 Printer"); - callback[5].Set_RealVec(0x17); - - /* INT 1A TIME and some other functions */ - callback[6].Install(&INT1A_Handler,CB_IRET_STI,"Int 1a Time"); - callback[6].Set_RealVec(0x1A); - - /* INT 1C System Timer tick called from INT 8 */ - callback[7].Install(&INT1C_Handler,CB_IRET,"Int 1c Timer"); - callback[7].Set_RealVec(0x1C); - - /* IRQ 8 RTC Handler */ - callback[8].Install(&INT70_Handler,CB_IRET,"Int 70 RTC"); - callback[8].Set_RealVec(0x70); - - /* Irq 9 rerouted to irq 2 */ - callback[9].Install(NULL,CB_IRQ9,"irq 9 bios"); - callback[9].Set_RealVec(0x71); - - /* Reboot */ - callback[10].Install(&Reboot_Handler,CB_IRET,"reboot"); - callback[10].Set_RealVec(0x18); - RealPt rptr = callback[10].Get_RealPointer(); - RealSetVec(0x19,rptr); - // set system BIOS entry point too - phys_writeb(0xFFFF0,0xEA); // FARJMP - phys_writew(0xFFFF1,RealOff(rptr)); // offset - phys_writew(0xFFFF3,RealSeg(rptr)); // segment - - /* Irq 2 */ - RealPt irq2pt=RealMake(0xf000,0xff55); /* Ghost busters 2 mt32 mode */ - Bitu call_irq2=CALLBACK_Allocate(); - CALLBACK_Setup(call_irq2,NULL,CB_IRET_EOI_PIC1,Real2Phys(irq2pt),"irq 2 bios"); - RealSetVec(0x0a,irq2pt); - - /* Some hardcoded vectors */ - phys_writeb(0xfff53,0xcf); /* bios default interrupt vector location */ - phys_writeb(0xfe987,0xea); /* original IRQ1 location (Defender booter) */ - phys_writed(0xfe988,RealGetVec(0x09)); - phys_writew(Real2Phys(RealGetVec(0x12))+0x12,0x20); //Hack for Jurresic - - if (machine==MCH_TANDY) phys_writeb(0xffffe,0xff) ; /* Tandy model */ - else if (machine==MCH_PCJR) phys_writeb(0xffffe,0xfd); /* PCJr model */ - else phys_writeb(0xffffe,0xfc); /* PC */ - - // System BIOS identification - const char* const b_type = - "IBM COMPATIBLE 486 BIOS COPYRIGHT The DOSBox Team."; - for(Bitu i = 0; i < strlen(b_type); i++) phys_writeb(0xfe00e + i,b_type[i]); - - // System BIOS version - const char* const b_vers = - "DOSBox FakeBIOS v1.0"; - for(Bitu i = 0; i < strlen(b_vers); i++) phys_writeb(0xfe061+i,b_vers[i]); - - // write system BIOS date - const char* const b_date = "01/01/92"; - for(Bitu i = 0; i < strlen(b_date); i++) phys_writeb(0xffff5+i,b_date[i]); - phys_writeb(0xfffff,0x55); // signature - - if (use_tandyDAC) { - /* tandy DAC sound requested, see if soundblaster device is available */ - if (Tandy_InitializeSB()) { - real_writew(0x40,0xd0,0x0000); - real_writew(0x40,0xd2,0x0000); - real_writeb(0x40,0xd4,0xff); /* tandy DAC init value */ - real_writed(0x40,0xd6,0x00000000); - /* install the DAC callback handler */ - tandy_DAC_callback[0]=new CALLBACK_HandlerObject(); - tandy_DAC_callback[1]=new CALLBACK_HandlerObject(); - tandy_DAC_callback[0]->Install(&IRQ_TandyDAC,CB_IRET,"Tandy DAC IRQ"); - tandy_DAC_callback[1]->Install(NULL,CB_TDE_IRET,"Tandy DAC end transfer"); - // pseudocode for CB_TDE_IRET: - // push ax - // mov ax, 0x91fb - // int 15 - // cli - // mov al, 0x20 - // out 0x20, al - // pop ax - // iret - - RealPt current_irq=RealGetVec(tandy_sb.irq+8); - real_writed(0x40,0xd6,current_irq); - for (Bitu i=0; i<0x10; i++) phys_writeb(PhysMake(0xf000,0xa084+i),0x80); - } else real_writeb(0x40,0xd4,0x00); - } - - /* Setup some stuff in 0x40 bios segment */ - - // port timeouts - // always 1 second even if the port does not exist - mem_writeb(BIOS_LPT1_TIMEOUT,1); - mem_writeb(BIOS_LPT2_TIMEOUT,1); - mem_writeb(BIOS_LPT3_TIMEOUT,1); - mem_writeb(BIOS_COM1_TIMEOUT,1); - mem_writeb(BIOS_COM2_TIMEOUT,1); - mem_writeb(BIOS_COM3_TIMEOUT,1); - mem_writeb(BIOS_COM4_TIMEOUT,1); - - /* detect parallel ports */ - Bitu ppindex=0; // number of lpt ports - if ((IO_Read(0x378)!=0xff)|(IO_Read(0x379)!=0xff)) { - // this is our LPT1 - mem_writew(BIOS_ADDRESS_LPT1,0x378); - ppindex++; - if((IO_Read(0x278)!=0xff)|(IO_Read(0x279)!=0xff)) { - // this is our LPT2 - mem_writew(BIOS_ADDRESS_LPT2,0x278); - ppindex++; - if((IO_Read(0x3bc)!=0xff)|(IO_Read(0x3be)!=0xff)) { - // this is our LPT3 - mem_writew(BIOS_ADDRESS_LPT3,0x3bc); - ppindex++; - } - } else if((IO_Read(0x3bc)!=0xff)|(IO_Read(0x3be)!=0xff)) { - // this is our LPT2 - mem_writew(BIOS_ADDRESS_LPT2,0x3bc); - ppindex++; - } - } else if((IO_Read(0x3bc)!=0xff)|(IO_Read(0x3be)!=0xff)) { - // this is our LPT1 - mem_writew(BIOS_ADDRESS_LPT1,0x3bc); - ppindex++; - if((IO_Read(0x278)!=0xff)|(IO_Read(0x279)!=0xff)) { - // this is our LPT2 - mem_writew(BIOS_ADDRESS_LPT2,0x278); - ppindex++; - } - } else if((IO_Read(0x278)!=0xff)|(IO_Read(0x279)!=0xff)) { - // this is our LPT1 - mem_writew(BIOS_ADDRESS_LPT1,0x278); - ppindex++; - } - - /* Setup equipment list */ - // look http://www.bioscentral.com/misc/bda.htm - - //Bitu config=0x4400; //1 Floppy, 2 serial and 1 parrallel - Bitu config = 0x0; - - // set number of parallel ports - // if(ppindex == 0) config |= 0x8000; // looks like 0 ports are not specified - //else if(ppindex == 1) config |= 0x0000; - if(ppindex == 2) config |= 0x4000; - else config |= 0xc000; // 3 ports -#if (C_FPU) - //FPU - config|=0x2; -#endif - switch (machine) { - case MCH_HERC: - //Startup monochrome - config|=0x30; - break; - case EGAVGA_ARCH_CASE: - case MCH_CGA: - case TANDY_ARCH_CASE: - //Startup 80x25 color - config|=0x20; - break; - default: - //EGA VGA - config|=0; - break; - } - // PS2 mouse - config |= 0x04; - // Gameport - config |= 0x1000; - mem_writew(BIOS_CONFIGURATION,config); - CMOS_SetRegister(0x14,config); //Should be updated on changes - /* Setup extended memory size */ - IO_Write(0x70,0x30); - size_extended=IO_Read(0x71); - IO_Write(0x70,0x31); - size_extended|=(IO_Read(0x71) << 8); - - if (machine==MCH_PCJR) PIC_AddEvent(RAMRefresh_Event,RAM_REFRESH_DELAY); - } - ~BIOS(){ - /* abort DAC playing */ - if (tandy_sb.port) { - IO_Write(tandy_sb.port+0xc,0xd3); - IO_Write(tandy_sb.port+0xc,0xd0); - } - real_writeb(0x40,0xd4,0x00); - if (tandy_DAC_callback[0]) { - Bit32u orig_vector=real_readd(0x40,0xd6); - if (orig_vector==tandy_DAC_callback[0]->Get_RealPointer()) { - /* set IRQ vector to old value */ - RealSetVec(tandy_sb.irq+8,real_readd(0x40,0xd6)); - real_writed(0x40,0xd6,0x00000000); - } - delete tandy_DAC_callback[0]; - delete tandy_DAC_callback[1]; - tandy_DAC_callback[0]=NULL; - tandy_DAC_callback[1]=NULL; - } - } -}; - -// set com port data in bios data area -// parameter: array of 4 com port base addresses, 0 = none -void BIOS_SetComPorts(Bit16u baseaddr[]) { - Bit16u portcount=0; - Bit16u equipmentword; - for(Bitu i = 0; i < 4; i++) { - if(baseaddr[i]!=0) portcount++; - if(i==0) mem_writew(BIOS_BASE_ADDRESS_COM1,baseaddr[i]); - else if(i==1) mem_writew(BIOS_BASE_ADDRESS_COM2,baseaddr[i]); - else if(i==2) mem_writew(BIOS_BASE_ADDRESS_COM3,baseaddr[i]); - else mem_writew(BIOS_BASE_ADDRESS_COM4,baseaddr[i]); - } - // set equipment word - equipmentword = mem_readw(BIOS_CONFIGURATION); - equipmentword &= (~0x0E00); - equipmentword |= (portcount << 9); - mem_writew(BIOS_CONFIGURATION,equipmentword); - CMOS_SetRegister(0x14,(Bit8u)(equipmentword&0xff)); //Should be updated on changes -} - - -static BIOS* test; - -void BIOS_Destroy(Section* sec){ - delete test; -} - -void BIOS_Init(Section* sec) { - test = new BIOS(sec); - sec->AddDestroyFunction(&BIOS_Destroy,false); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include "dosbox.h" +#include "bios.h" +#include "regs.h" +#include "callback.h" +#include "inout.h" +#include "mem.h" + + +static Bitu call_int1a,call_int11,call_int8,call_int17,call_int12,call_int15,call_int1c; + +static Bitu INT1A_Handler(void) { + switch (reg_ah) { + case 0x00: /* Get System time */ + { + Bit32u ticks=mem_readd(BIOS_TIMER); + reg_al=0; /* Midnight never passes :) */ + reg_cx=(Bit16u)(ticks >> 16); + reg_dx=(Bit16u)(ticks & 0xffff); + break; + } + case 0x01: /* Set System time */ + mem_writed(BIOS_TIMER,(reg_cx<<16)|reg_dx); + break; + case 0x02: /* GET REAL-TIME CLOCK TIME (AT,XT286,PS) */ + reg_dx=reg_cx=0; + CALLBACK_SCF(false); + LOG_WARN("INT1A:02:Faked RTC get time call"); + break; + case 0x04: /* GET REAL-TIME ClOCK DATA (AT,XT286,PS) */ + reg_dx=reg_cx=0; + CALLBACK_SCF(false); + LOG_WARN("INT1A:04:Faked RTC get date call"); + break; + case 0x80: /* Pcjr Setup Sound Multiplexer */ + LOG_WARN("INT1A:80:Setup tandy sound multiplexer to %d",reg_al); + break; + case 0x81: /* Tandy sound system checks */ + LOG_WARN("INT1A:81:Tandy DAC Check failing"); + break; +/* + INT 1A - Tandy 2500, Tandy 1000L series - DIGITAL SOUND - INSTALLATION CHECK + AX = 8100h + Return: AL > 80h if supported + AX = 00C4h if supported (1000SL/TL) + CF set if sound chip is busy + CF clear if sound chip is free + Note: the value of CF is not definitive; call this function until CF is + clear on return, then call AH=84h"Tandy" +*/ + default: + LOG_WARN("INT1A:Undefined call %2X",reg_ah); + } + return CBRET_NONE; +} + +static Bitu INT11_Handler(void) { + /* + AX = BIOS equipment list word + bits + 0 floppy disk(s) installed (see bits 6-7) + 1 80x87 coprocessor installed + 2,3 number of 16K banks of RAM on motherboard (PC only) + number of 64K banks of RAM on motherboard (XT only) + 2 pointing device installed (PS) + 3 unused (PS) + 4-5 initial video mode + 00 EGA, VGA, or PGA + 01 40x25 color + 10 80x25 color + 11 80x25 monochrome + 6-7 number of floppies installed less 1 (if bit 0 set) + 8 DMA support installed (PCjr, some Tandy 1000s, 1400LT) + 9-11 number of serial ports installed + 12 game port installed + 13 serial printer attached (PCjr) + internal modem installed (PC/Convertible) + 14-15 number of parallel ports installed + */ + reg_eax=0x104D; + return CBRET_NONE; +} + +static Bitu INT8_Handler(void) { + /* Increase the bios tick counter */ + mem_writed(BIOS_TIMER,mem_readd(BIOS_TIMER)+1); + CALLBACK_RunRealInt(0x1c); + IO_Write(0x20,0x20); + return CBRET_NONE; +}; + +static Bitu INT1C_Handler(void) { + return CBRET_NONE; +}; + +static Bitu INT12_Handler(void) { + reg_ax=mem_readw(BIOS_MEMORY_SIZE); + return CBRET_NONE; +}; + +static Bitu INT17_Handler(void) { + LOG_ERROR("INT17:Not supported call for bios printer support"); + switch(reg_ah) { + case 0x00: /* PRINTER: Write Character */ + reg_ah=1; /* Report a timeout */ + break; + case 0x01: /* PRINTER: Initialize port */ + break; + case 0x02: /* PRINTER: Get Status */ + reg_ah=0; + break; + default: + E_Exit("Unhandled INT 17 call %2X",reg_ah); + }; + return CBRET_NONE; +}; + +static Bitu INT15_Handler(void) { + switch (reg_ah) { + case 0x06: + LOG_WARN("Calling unkown int15 function 6"); + break; + case 0xC0: /* Get Configuration*/ + LOG_WARN("Request BIOS Configuration INT 15 C0"); + CALLBACK_SCF(true); + break; + case 0x84: /* BIOS - JOYSTICK SUPPORT (XT after 11/8/82,AT,XT286,PS) */ + //Does anyone even use this? + LOG_WARN("INT15:84:Bios Joystick functionality not done"); + reg_ax=reg_bx=reg_cx=reg_dx=0; + break; + case 0x86: /* BIOS - WAIT (AT,PS) */ + { + //TODO Perhaps really wait :) + Bit32u micro=(reg_cx<<16)|reg_dx; + CALLBACK_SCF(false); + } + case 0x88: /* SYSTEM - GET EXTENDED MEMORY SIZE (286+) */ + reg_ax=0; + CALLBACK_SCF(false); + break; + case 0x90: /* OS HOOK - DEVICE BUSY */ + CALLBACK_SCF(true); + reg_ah=0; + break; + case 0xc2: /* BIOS PS2 Pointing Device Support */ + /* + Damn programs should use the mouse drivers + So let's fail these calls + */ + CALLBACK_SCF(true); + break; + case 0xc4: /* BIOS POS Programma option Select */ + LOG_WARN("INT15:C4:Call for POS Function %2x",reg_al); + CALLBACK_SCF(true); + break; + default: + LOG_WARN("INT15:Unknown call %2X",reg_ah); + } + return CBRET_NONE; +}; + +static void INT15_StartUp(void) { +/* TODO Start the time correctly */ +}; + + +void BIOS_SetupKeyboard(void); +void BIOS_SetupDisks(void); + +void BIOS_Init(void) { + /* Clear the Bios Data Area */ + for (Bit16u i=0;i<1024;i++) real_writeb(0x40,i,0); + /* Setup all the interrupt handlers the bios controls */ + /* INT 8 Clock IRQ Handler */ + //TODO Maybe give this a special callback that will also call int 8 instead of starting + //a new system + call_int8=CALLBACK_Allocate(); + CALLBACK_Setup(call_int8,&INT8_Handler,CB_IRET); + mem_writed(BIOS_TIMER,0); //Calculate the correct time + RealSetVec(0x8,CALLBACK_RealPointer(call_int8)); + /* INT10 Video Bios */ + INT10_StartUp(); + /* INT 11 Get equipment list */ + call_int11=CALLBACK_Allocate(); + CALLBACK_Setup(call_int11,&INT11_Handler,CB_IRET); + RealSetVec(0x11,CALLBACK_RealPointer(call_int11)); + /* INT 12 Memory Size default at 640 kb */ + call_int12=CALLBACK_Allocate(); + CALLBACK_Setup(call_int12,&INT12_Handler,CB_IRET); + RealSetVec(0x12,CALLBACK_RealPointer(call_int12)); + mem_writew(BIOS_MEMORY_SIZE,640); + /* INT 13 Bios Disk Support */ + BIOS_SetupDisks(); + /* INT 15 Misc Calls */ + call_int15=CALLBACK_Allocate(); + CALLBACK_Setup(call_int15,&INT15_Handler,CB_IRET); + RealSetVec(0x15,CALLBACK_RealPointer(call_int15)); + /* INT 16 Keyboard handled in another file */ + BIOS_SetupKeyboard(); + /* INT 16 Printer Routines */ + call_int17=CALLBACK_Allocate(); + CALLBACK_Setup(call_int17,&INT17_Handler,CB_IRET); + RealSetVec(0x17,CALLBACK_RealPointer(call_int17)); + /* INT 1A TIME and some other functions */ + call_int1a=CALLBACK_Allocate(); + CALLBACK_Setup(call_int1a,&INT1A_Handler,CB_IRET); + RealSetVec(0x1A,CALLBACK_RealPointer(call_int1a)); + /* INT 1C System Timer tick called from INT 8 */ + call_int1c=CALLBACK_Allocate(); + CALLBACK_Setup(call_int1c,&INT1C_Handler,CB_IRET); + RealSetVec(0x1C,CALLBACK_RealPointer(call_int1c)); + +} + + + + diff --git a/src/ints/bios_disk.cpp b/src/ints/bios_disk.cpp index 4bc34e3..3813c5b 100644 --- a/src/ints/bios_disk.cpp +++ b/src/ints/bios_disk.cpp @@ -1,523 +1,95 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: bios_disk.cpp,v 1.37 2007/07/14 16:42:38 c2woody Exp $ */ - -#include "dosbox.h" -#include "callback.h" -#include "bios.h" -#include "regs.h" -#include "mem.h" -#include "dos_inc.h" /* for Drives[] */ -#include "../dos/drives.h" -#include "mapper.h" - -#define MAX_DISK_IMAGES 4 - -diskGeo DiskGeometryList[] = { - { 160, 8, 1, 40, 0}, - { 180, 9, 1, 40, 0}, - { 200, 10, 1, 40, 0}, - { 320, 8, 2, 40, 1}, - { 360, 9, 2, 40, 1}, - { 400, 10, 2, 40, 1}, - { 720, 9, 2, 80, 3}, - {1200, 15, 2, 80, 2}, - {1440, 18, 2, 80, 4}, - {2880, 36, 2, 80, 6}, - {0, 0, 0, 0, 0} -}; - -Bitu call_int13; -Bitu diskparm0, diskparm1; -static Bit8u last_status; -static Bit8u last_drive; -Bit16u imgDTASeg; -RealPt imgDTAPtr; -DOS_DTA *imgDTA; -bool killRead; -static bool swapping_requested; - -void CMOS_SetRegister(Bitu regNr, Bit8u val); //For setting equipment word - -/* 2 floppys and 2 harddrives, max */ -imageDisk *imageDiskList[MAX_DISK_IMAGES]; -imageDisk *diskSwap[MAX_SWAPPABLE_DISKS]; -Bits swapPosition; - -void updateDPT(void) { - Bit32u tmpheads, tmpcyl, tmpsect, tmpsize; - if(imageDiskList[2] != NULL) { - PhysPt dp0physaddr=CALLBACK_PhysPointer(diskparm0); - imageDiskList[2]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize); - phys_writew(dp0physaddr,(Bit16u)tmpcyl); - phys_writeb(dp0physaddr+0x2,(Bit8u)tmpheads); - phys_writew(dp0physaddr+0x3,0); - phys_writew(dp0physaddr+0x5,(Bit16u)-1); - phys_writeb(dp0physaddr+0x7,0); - phys_writeb(dp0physaddr+0x8,(0xc0 | (((imageDiskList[2]->heads) > 8) << 3))); - phys_writeb(dp0physaddr+0x9,0); - phys_writeb(dp0physaddr+0xa,0); - phys_writeb(dp0physaddr+0xb,0); - phys_writew(dp0physaddr+0xc,(Bit16u)tmpcyl); - phys_writeb(dp0physaddr+0xe,(Bit8u)tmpsect); - } - if(imageDiskList[3] != NULL) { - PhysPt dp1physaddr=CALLBACK_PhysPointer(diskparm1); - imageDiskList[3]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize); - phys_writew(dp1physaddr,(Bit16u)tmpcyl); - phys_writeb(dp1physaddr+0x2,(Bit8u)tmpheads); - phys_writeb(dp1physaddr+0xe,(Bit8u)tmpsect); - } -} - -void swapInDisks(void) { - bool allNull = true; - Bits diskcount = 0; - Bits swapPos = swapPosition; - int i; - - /* Check to make sure there's atleast one setup image */ - for(i=0;idiskname); - imageDiskList[diskcount] = diskSwap[swapPos]; - diskcount++; - } - swapPos++; - if(swapPos>=MAX_SWAPPABLE_DISKS) swapPos=0; - } -} - -bool getSwapRequest(void) { - bool sreq=swapping_requested; - swapping_requested = false; - return sreq; -} - -void swapInNextDisk(bool pressed) { - if (!pressed) - return; - /* Hack/feature: rescan all disks as well */ - DriveManager::CycleAllDisks(); - for(Bitu i=0;iEmptyCache(); - } - swapPosition++; - if(diskSwap[swapPosition] == NULL) swapPosition = 0; - swapInDisks(); - swapping_requested = true; -} - - -Bit8u imageDisk::Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data) { - Bit32u sectnum; - - sectnum = ( (cylinder * heads + head) * sectors ) + sector - 1L; - - return Read_AbsoluteSector(sectnum, data); -} - -Bit8u imageDisk::Read_AbsoluteSector(Bit32u sectnum, void * data) { - Bit32u bytenum; - - bytenum = sectnum * sector_size; - - fseek(diskimg,bytenum,SEEK_SET); - fread(data, 1, sector_size, diskimg); - - return 0x00; -} - -Bit8u imageDisk::Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data) { - Bit32u sectnum; - - sectnum = ( (cylinder * heads + head) * sectors ) + sector - 1L; - - return Write_AbsoluteSector(sectnum, data); - -} - - -Bit8u imageDisk::Write_AbsoluteSector(Bit32u sectnum, void *data) { - Bit32u bytenum; - - bytenum = sectnum * sector_size; - - //LOG_MSG("Writing sectors to %ld at bytenum %d", sectnum, bytenum); - - fseek(diskimg,bytenum,SEEK_SET); - size_t ret=fwrite(data, sector_size, 1, diskimg); - - return ((ret>0)?0x00:0x05); - -} - -imageDisk::imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk) { - heads = 0; - cylinders = 0; - sectors = 0; - sector_size = 512; - diskimg = imgFile; - - memset(diskname,0,512); - if(strlen((const char *)imgName) > 511) { - memcpy(diskname, imgName, 511); - } else { - strcpy((char *)diskname, (const char *)imgName); - } - - active = false; - hardDrive = isHardDisk; - if(!isHardDisk) { - Bitu i=0; - bool founddisk = false; - while (DiskGeometryList[i].ksize!=0x0) { - if ((DiskGeometryList[i].ksize==imgSizeK) || - (DiskGeometryList[i].ksize+1==imgSizeK)) { - if (DiskGeometryList[i].ksize!=imgSizeK) - LOG_MSG("ImageLoader: image file with additional data, might not load!"); - founddisk = true; - active = true; - floppytype = i; - heads = DiskGeometryList[i].headscyl; - cylinders = DiskGeometryList[i].cylcount; - sectors = DiskGeometryList[i].secttrack; - break; - } - i++; - } - if(!founddisk) { - active = false; - } else { - Bit16u equipment=mem_readw(BIOS_CONFIGURATION); - if(equipment&1) { - Bitu numofdisks = (equipment>>6)&3; - numofdisks++; - if(numofdisks > 1) numofdisks=1;//max 2 floppies at the moment - equipment&=~0x00C0; - equipment|=(numofdisks<<6); - } else equipment|=1; - mem_writew(BIOS_CONFIGURATION,equipment); - CMOS_SetRegister(0x14, (Bit8u)(equipment&0xff)); - } - } -} - -void imageDisk::Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize) { - heads = setHeads; - cylinders = setCyl; - sectors = setSect; - sector_size = setSectSize; - active = true; -} - -void imageDisk::Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit32u *getSectSize) { - *getHeads = heads; - *getCyl = cylinders; - *getSect = sectors; - *getSectSize = sector_size; -} - -Bit8u imageDisk::GetBiosType(void) { - if(!hardDrive) { - return (Bit8u)DiskGeometryList[floppytype].biosval; - } else return 0; -} - -Bit32u imageDisk::getSectSize(void) { - return sector_size; -} - -static Bitu GetDosDriveNumber(Bitu biosNum) { - switch(biosNum) { - case 0x0: - return 0x0; - case 0x1: - return 0x1; - case 0x80: - return 0x2; - case 0x81: - return 0x3; - case 0x82: - return 0x4; - case 0x83: - return 0x5; - default: - return 0x7f; - } -} - -static bool driveInactive(Bitu driveNum) { - if(driveNum>=(2 + MAX_HDD_IMAGES)) { - LOG(LOG_BIOS,LOG_ERROR)("Disk %d non-existant", driveNum); - last_status = 0x01; - CALLBACK_SCF(true); - return true; - } - if(imageDiskList[driveNum] == NULL) { - LOG(LOG_BIOS,LOG_ERROR)("Disk %d not active", driveNum); - last_status = 0x01; - CALLBACK_SCF(true); - return true; - } - if(!imageDiskList[driveNum]->active) { - LOG(LOG_BIOS,LOG_ERROR)("Disk %d not active", driveNum); - last_status = 0x01; - CALLBACK_SCF(true); - return true; - } - return false; -} - - -static Bitu INT13_DiskHandler(void) { - Bit16u segat, bufptr; - Bit8u sectbuf[512]; - Bitu drivenum; - Bitu i,t; - last_drive = reg_dl; - drivenum = GetDosDriveNumber(reg_dl); - bool any_images = false; - for(i = 0;i < MAX_DISK_IMAGES;i++) { - if(imageDiskList[i]) any_images=true; - } - - //drivenum = 0; - //LOG_MSG("INT13: Function %x called on drive %x (dos drive %d)", reg_ah, reg_dl, drivenum); - switch(reg_ah) { - case 0x0: /* Reset disk */ - { - /* if there aren't any diskimages (so only localdrives and virtual drives) - * always succeed on reset disk. If there are diskimages then and only then - * do real checks - */ - if (any_images && driveInactive(drivenum)) { - /* driveInactive sets carry flag if the specified drive is not available */ - if ((machine==MCH_CGA) || (machine==MCH_PCJR)) { - /* those bioses call floppy drive reset for invalid drive values */ - if (((imageDiskList[0]) && (imageDiskList[0]->active)) || ((imageDiskList[1]) && (imageDiskList[1]->active))) { - last_status = 0x00; - CALLBACK_SCF(false); - } - } - return CBRET_NONE; - } - last_status = 0x00; - CALLBACK_SCF(false); - } - break; - case 0x1: /* Get status of last operation */ - - if(last_status != 0x00) { - reg_ah = last_status; - CALLBACK_SCF(true); - } else { - reg_ah = 0x00; - CALLBACK_SCF(false); - } - break; - case 0x2: /* Read sectors */ - if (reg_al==0) { - reg_ah = 0x01; - CALLBACK_SCF(true); - return CBRET_NONE; - } - if(!any_images && (reg_dh == 0)) { // Inherit the Earth cdrom (uses it as disk test) - reg_ah = 0; - CALLBACK_SCF(false); - return CBRET_NONE; - } - if(driveInactive(drivenum)) { - reg_ah = 0xff; - CALLBACK_SCF(true); - return CBRET_NONE; - } - - segat = SegValue(es); - bufptr = reg_bx; - for(i=0;iRead_Sector((Bit32u)reg_dh, (Bit32u)(reg_ch | ((reg_cl & 0xc0)<< 2)), (Bit32u)((reg_cl & 63)+i), sectbuf); - if((last_status != 0x00) || (killRead)) { - LOG_MSG("Error in disk read"); - killRead = false; - reg_ah = 0x04; - CALLBACK_SCF(true); - return CBRET_NONE; - } - for(t=0;t<512;t++) { - real_writeb(segat,bufptr,sectbuf[t]); - bufptr++; - } - } - reg_ah = 0x00; - CALLBACK_SCF(false); - break; - case 0x3: /* Write sectors */ - - if(driveInactive(drivenum)) { - reg_ah = 0xff; - CALLBACK_SCF(true); - return CBRET_NONE; - } - - - bufptr = reg_bx; - for(i=0;igetSectSize();t++) { - sectbuf[t] = real_readb(SegValue(es),bufptr); - bufptr++; - } - - last_status = imageDiskList[drivenum]->Write_Sector((Bit32u)reg_dh, (Bit32u)(reg_ch | ((reg_cl & 0xc0) << 2)), (Bit32u)((reg_cl & 63) + i), §buf[0]); - if(last_status != 0x00) { - CALLBACK_SCF(true); - return CBRET_NONE; - } - } - reg_ah = 0x00; - CALLBACK_SCF(false); - break; - case 0x04: /* Verify sectors */ - if (reg_al==0) { - reg_ah = 0x01; - CALLBACK_SCF(true); - return CBRET_NONE; - } - if(driveInactive(drivenum)) return CBRET_NONE; - - /* TODO: Finish coding this section */ - /* - segat = SegValue(es); - bufptr = reg_bx; - for(i=0;iRead_Sector((Bit32u)reg_dh, (Bit32u)(reg_ch | ((reg_cl & 0xc0)<< 2)), (Bit32u)((reg_cl & 63)+i), sectbuf); - if(last_status != 0x00) { - LOG_MSG("Error in disk read"); - CALLBACK_SCF(true); - return CBRET_NONE; - } - for(t=0;t<512;t++) { - real_writeb(segat,bufptr,sectbuf[t]); - bufptr++; - } - }*/ - reg_ah = 0x00; - //Qbix: The following codes don't match my specs. al should be number of sector verified - //reg_al = 0x10; /* CRC verify failed */ - //reg_al = 0x00; /* CRC verify succeeded */ - CALLBACK_SCF(false); - - break; - case 0x08: /* Get drive parameters */ - if(driveInactive(drivenum)) { - last_status = 0x07; - reg_ah = last_status; - CALLBACK_SCF(true); - return CBRET_NONE; - } - reg_ax = 0x00; - reg_bl = imageDiskList[drivenum]->GetBiosType(); - Bit32u tmpheads, tmpcyl, tmpsect, tmpsize; - imageDiskList[drivenum]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize); - if (tmpcyl==0) LOG(LOG_BIOS,LOG_ERROR)("INT13 DrivParm: cylinder count zero!"); - else tmpcyl--; // cylinder count -> max cylinder - if (tmpheads==0) LOG(LOG_BIOS,LOG_ERROR)("INT13 DrivParm: head count zero!"); - else tmpheads--; // head count -> max head - reg_ch = (Bit8u)(tmpcyl & 0xff); - reg_cl = (Bit8u)(((tmpcyl >> 2) & 0xc0) | (tmpsect & 0x3f)); - reg_dh = (Bit8u)tmpheads; - last_status = 0x00; - if (reg_dl&0x80) { // harddisks - reg_dl = 0; - if(imageDiskList[2] != NULL) reg_dl++; - if(imageDiskList[3] != NULL) reg_dl++; - } else { // floppy disks - reg_dl = 0; - if(imageDiskList[0] != NULL) reg_dl++; - if(imageDiskList[1] != NULL) reg_dl++; - } - CALLBACK_SCF(false); - break; - case 0x11: /* Recalibrate drive */ - reg_ah = 0x00; - CALLBACK_SCF(false); - break; - case 0x17: /* Set disk type for format */ - /* Pirates! needs this to load */ - killRead = true; - reg_ah = 0x00; - CALLBACK_SCF(false); - break; - default: - LOG(LOG_BIOS,LOG_ERROR)("INT13: Function %x called on drive %x (dos drive %d)", reg_ah, reg_dl, drivenum); - reg_ah=0xff; - CALLBACK_SCF(true); - } - return CBRET_NONE; -} - - -void BIOS_SetupDisks(void) { -/* TODO Start the time correctly */ - call_int13=CALLBACK_Allocate(); - CALLBACK_Setup(call_int13,&INT13_DiskHandler,CB_IRET,"Int 13 Bios disk"); - RealSetVec(0x13,CALLBACK_RealPointer(call_int13)); - int i; - for(i=0;i<4;i++) { - imageDiskList[i] = NULL; - } - - for(i=0;iRead_Sector(®_al,reg_dh,reg_ch,(reg_cl & 0x3f)-1,real_off(Segs[es].value,reg_bx)); + CALLBACK_SCF(false); + break; + case 0x03: /* Write Sectors from Memory */ + last_status=reg_ah=disk->Write_Sector(®_al,reg_dh,reg_ch,(reg_cl & 0x3f)-1,real_off(Segs[es].value,reg_bx)); + CALLBACK_SCF(false); + break; + default: + LOG_DEBUG("INT13:Illegal call %2X",reg_ah); + reg_ah=0xff; + CALLBACK_SCF(true); + } + return CBRET_NONE; +}; + + +static Bitu INT13_SmallHandler(void) { + switch (reg_ah) { + case 0x02: /* Read Disk Sectors */ + LOG_DEBUG("INT13:02:Read Disk Sectors not supported failing"); + reg_ah=0xff; + CALLBACK_SCF(true); + break; + case 0x08: /* Get Drive Parameters */ + LOG_DEBUG("INT13:08:Get Drive parameters not supported failing"); + reg_ah=0xff; + CALLBACK_SCF(true); + break; + case 0xff: + default: + LOG_WARN("Illegal int 13h call %2X Fail it",reg_ah); + reg_ah=0xff; + CALLBACK_SCF(true); + } + return CBRET_NONE; +} + +void BIOS_SetupDisks(void) { +/* TODO Start the time correctly */ + call_int13=CALLBACK_Allocate(); +#ifdef C_IMAGE + Floppys[0]=new imageDisk("c:\\test.img"); + for (Bit32u i=0;i */ - { 0x352f, 0x353f, none, 0x35f0 }, /* /? */ - { none, none, none, none }, /* R Shift */ - { 0x372a, 0x372a, 0x9600, 0x37f0 }, /* * */ - { none, none, none, none }, /* L Alt */ - { 0x3920, 0x3920, 0x3920, 0x3920 }, /* space */ - { none, none, none, none }, /* caps lock */ - { 0x3b00, 0x5400, 0x5e00, 0x6800 }, /* F1 */ - { 0x3c00, 0x5500, 0x5f00, 0x6900 }, /* F2 */ - { 0x3d00, 0x5600, 0x6000, 0x6a00 }, /* F3 */ - { 0x3e00, 0x5700, 0x6100, 0x6b00 }, /* F4 */ - { 0x3f00, 0x5800, 0x6200, 0x6c00 }, /* F5 */ - { 0x4000, 0x5900, 0x6300, 0x6d00 }, /* F6 */ - { 0x4100, 0x5a00, 0x6400, 0x6e00 }, /* F7 */ - { 0x4200, 0x5b00, 0x6500, 0x6f00 }, /* F8 */ - { 0x4300, 0x5c00, 0x6600, 0x7000 }, /* F9 */ - { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* F10 */ - { none, none, none, none }, /* Num Lock */ - { none, none, none, none }, /* Scroll Lock */ - { 0x4700, 0x4737, 0x7700, 0x0007 }, /* 7 Home */ - { 0x4800, 0x4838, 0x8d00, 0x0008 }, /* 8 UP */ - { 0x4900, 0x4939, 0x8400, 0x0009 }, /* 9 PgUp */ - { 0x4a2d, 0x4a2d, 0x8e00, 0x4af0 }, /* - */ - { 0x4b00, 0x4b34, 0x7300, 0x0004 }, /* 4 Left */ - { 0x4cf0, 0x4c35, 0x8f00, 0x0005 }, /* 5 */ - { 0x4d00, 0x4d36, 0x7400, 0x0006 }, /* 6 Right */ - { 0x4e2b, 0x4e2b, 0x9000, 0x4ef0 }, /* + */ - { 0x4f00, 0x4f31, 0x7500, 0x0001 }, /* 1 End */ - { 0x5000, 0x5032, 0x9100, 0x0002 }, /* 2 Down */ - { 0x5100, 0x5133, 0x7600, 0x0003 }, /* 3 PgDn */ - { 0x5200, 0x5230, 0x9200, 0x0000 }, /* 0 Ins */ - { 0x5300, 0x532e, 0x9300, none }, /* Del */ - { none, none, none, none }, - { none, none, none, none }, - { 0x565c, 0x567c, none, none }, /* (102-key) */ - { 0x8500, 0x8700, 0x8900, 0x8b00 }, /* F11 */ - { 0x8600, 0x8800, 0x8a00, 0x8c00 } /* F12 */ - }; - -bool BIOS_AddKeyToBuffer(Bit16u code) { - if (mem_readb(BIOS_KEYBOARD_FLAGS2)&8) return true; - Bit16u start,end,head,tail,ttail; - if (machine==MCH_PCJR) { - /* should be done for cga and others as well, to be tested */ - start=0x1e; - end=0x3e; - } else { - start=mem_readw(BIOS_KEYBOARD_BUFFER_START); - end =mem_readw(BIOS_KEYBOARD_BUFFER_END); - } - head =mem_readw(BIOS_KEYBOARD_BUFFER_HEAD); - tail =mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); - ttail=tail+2; - if (ttail>=end) { - ttail=start; - } - /* Check for buffer Full */ - //TODO Maybe beeeeeeep or something although that should happend when internal buffer is full - if (ttail==head) return false; - real_writew(0x40,tail,code); - mem_writew(BIOS_KEYBOARD_BUFFER_TAIL,ttail); - return true; -} - -static void add_key(Bit16u code) { - if (code!=0) BIOS_AddKeyToBuffer(code); -} - -static bool get_key(Bit16u &code) { - Bit16u start,end,head,tail,thead; - if (machine==MCH_PCJR) { - /* should be done for cga and others as well, to be tested */ - start=0x1e; - end=0x3e; - } else { - start=mem_readw(BIOS_KEYBOARD_BUFFER_START); - end =mem_readw(BIOS_KEYBOARD_BUFFER_END); - } - head =mem_readw(BIOS_KEYBOARD_BUFFER_HEAD); - tail =mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); - - if (head==tail) return false; - thead=head+2; - if (thead>=end) thead=start; - mem_writew(BIOS_KEYBOARD_BUFFER_HEAD,thead); - code = real_readw(0x40,head); - return true; -} - -static bool check_key(Bit16u &code) { - Bit16u head,tail; - head =mem_readw(BIOS_KEYBOARD_BUFFER_HEAD); - tail =mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); - if (head==tail) return false; - code = real_readw(0x40,head); - return true; -} - - /* Flag Byte 1 - bit 7 =1 INSert active - bit 6 =1 Caps Lock active - bit 5 =1 Num Lock active - bit 4 =1 Scroll Lock active - bit 3 =1 either Alt pressed - bit 2 =1 either Ctrl pressed - bit 1 =1 Left Shift pressed - bit 0 =1 Right Shift pressed - */ - /* Flag Byte 2 - bit 7 =1 INSert pressed - bit 6 =1 Caps Lock pressed - bit 5 =1 Num Lock pressed - bit 4 =1 Scroll Lock pressed - bit 3 =1 Pause state active - bit 2 =1 Sys Req pressed - bit 1 =1 Left Alt pressed - bit 0 =1 Left Ctrl pressed - */ - /* - Keyboard status byte 3 - bit 7 =1 read-ID in progress - bit 6 =1 last code read was first of two ID codes - bit 5 =1 force Num Lock if read-ID and enhanced keyboard - bit 4 =1 enhanced keyboard installed - bit 3 =1 Right Alt pressed - bit 2 =1 Right Ctrl pressed - bit 1 =1 last code read was E0h - bit 0 =1 last code read was E1h - */ - - -/* the scancode is in reg_al */ -static Bitu IRQ1_Handler(void) { -/* handling of the locks key is difficult as sdl only gives - * states for numlock capslock. - */ - Bitu scancode=reg_al; /* Read the code */ - - Bit8u flags1,flags2,flags3,leds; - flags1=mem_readb(BIOS_KEYBOARD_FLAGS1); - flags2=mem_readb(BIOS_KEYBOARD_FLAGS2); - flags3=mem_readb(BIOS_KEYBOARD_FLAGS3); - leds =mem_readb(BIOS_KEYBOARD_LEDS); -#ifdef CAN_USE_LOCK - /* No hack anymore! */ -#else - flags2&=~(0x40+0x20);//remove numlock/capslock pressed (hack for sdl only reporting states) -#endif - if (DOS_LayoutKey(scancode,flags1,flags2,flags3)) return CBRET_NONE; - switch (scancode) { - /* First the hard ones */ - case 0xfa: /* ack. Do nothing for now */ - break; - case 0xe1: /* Extended key special. Only pause uses this */ - flags3 |=0x01; - break; - case 0xe0: /* Extended key */ - flags3 |=0x02; - break; - case 0x1d: /* Ctrl Pressed */ - if (!(flags3 &0x01)) { - flags1 |=0x04; - if (flags3 &0x02) flags3 |=0x04; - else flags2 |=0x01; - } /* else it's part of the pause scancodes */ - break; - case 0x9d: /* Ctrl Released */ - if (!(flags3 &0x01)) { - if (flags3 &0x02) flags3 &=~0x04; - else flags2 &=~0x01; - if( !( (flags3 &0x04) || (flags2 &0x01) ) ) flags1 &=~0x04; - } - break; - case 0x2a: /* Left Shift Pressed */ - flags1 |=0x02; - break; - case 0xaa: /* Left Shift Released */ - flags1 &=~0x02; - break; - case 0x36: /* Right Shift Pressed */ - flags1 |=0x01; - break; - case 0xb6: /* Right Shift Released */ - flags1 &=~0x01; - break; - case 0x38: /* Alt Pressed */ - flags1 |=0x08; - if (flags3 &0x02) flags3 |=0x08; - else flags2 |=0x02; - break; - case 0xb8: /* Alt Released */ - if (flags3 &0x02) flags3 &= ~0x08; - else flags2 &= ~0x02; - if( !( (flags3 &0x08) || (flags2 &0x02) ) ) { /* Both alt released */ - flags1 &= ~0x08; - Bit16u token =mem_readb(BIOS_KEYBOARD_TOKEN); - if(token != 0){ - add_key(token); - mem_writeb(BIOS_KEYBOARD_TOKEN,0); - } - } - break; - -#ifdef CAN_USE_LOCK - case 0x3a:flags2 |=0x40;break;//CAPSLOCK - case 0xba:flags1 ^=0x40;flags2 &=~0x40;leds ^=0x04;break; -#else - case 0x3a:flags2 |=0x40;flags1 |=0x40;leds |=0x04;break; //SDL gives only the state instead of the toggle /* Caps Lock */ - case 0xba:flags1 &=~0x40;leds &=~0x04;break; -#endif - case 0x45: - if (flags3 &0x01) { - /* last scancode of pause received; first remove 0xe1-prefix */ - flags3 &=~0x01; - mem_writeb(BIOS_KEYBOARD_FLAGS3,flags3); - if (flags2&1) { - /* ctrl-pause (break), special handling needed: - add zero to the keyboard buffer, call int 0x1b which - sets ctrl-c flag which calls int 0x23 in certain dos - input/output functions; not handled */ - } else if ((flags2&8)==0) { - /* normal pause key, enter loop */ - mem_writeb(BIOS_KEYBOARD_FLAGS2,flags2|8); - IO_Write(0x20,0x20); - while (mem_readb(BIOS_KEYBOARD_FLAGS2)&8) CALLBACK_Idle(); // pause loop - reg_ip+=5; // skip out 20,20 - return CBRET_NONE; - } - } else { - /* Num Lock */ -#ifdef CAN_USE_LOCK - flags2 |=0x20; -#else - flags2 |=0x20; - flags1 |=0x20; - leds |=0x02; -#endif - } - break; - case 0xc5: - if (flags3 &0x01) { - /* pause released */ - flags3 &=~0x01; - } else { -#ifdef CAN_USE_LOCK - flags1^=0x20; - leds^=0x02; - flags2&=~0x20; -#else - /* Num Lock released */ - flags1 &=~0x20; - leds &=~0x02; -#endif - } - break; - case 0x46:flags2 |=0x10;break; /* Scroll Lock SDL Seems to do this one fine (so break and make codes) */ - case 0xc6:flags1 ^=0x10;flags2 &=~0x10;leds ^=0x01;break; -// case 0x52:flags2|=128;break;//See numpad /* Insert */ - case 0xd2: - if(flags3&0x02) { /* Maybe honour the insert on keypad as well */ - flags1^=0x80; - flags2&=~0x80; - break; - } else { - goto irq1_end;/*Normal release*/ - } - case 0x47: /* Numpad */ - case 0x48: - case 0x49: - case 0x4b: - case 0x4c: - case 0x4d: - case 0x4f: - case 0x50: - case 0x51: - case 0x52: - case 0x53: /* del . Not entirely correct, but works fine */ - if(flags3 &0x02) { /*extend key. e.g key above arrows or arrows*/ - if(scancode == 0x52) flags2 |=0x80; /* press insert */ - if(flags1 &0x08) { - add_key(scan_to_scanascii[scancode].normal+0x5000); - } else if (flags1 &0x04) { - add_key((scan_to_scanascii[scancode].control&0xff00)|0xe0); - } else if( ((flags1 &0x3) != 0) || ((flags1 &0x20) != 0) ) { - add_key((scan_to_scanascii[scancode].shift&0xff00)|0xe0); - } else add_key((scan_to_scanascii[scancode].normal&0xff00)|0xe0); - break; - } - if(flags1 &0x08) { - Bit8u token = mem_readb(BIOS_KEYBOARD_TOKEN); - token= token*10 + scan_to_scanascii[scancode].alt; - mem_writeb(BIOS_KEYBOARD_TOKEN,token); - } else if (flags1 &0x04) { - add_key(scan_to_scanascii[scancode].control); - } else if( ((flags1 &0x3) != 0) || ((flags1 &0x20) != 0) ) { - add_key(scan_to_scanascii[scancode].shift); - } else add_key(scan_to_scanascii[scancode].normal); - break; - - default: /* Normal Key */ - Bit16u asciiscan; - /* Now Handle the releasing of keys and see if they match up for a code */ - /* Handle the actual scancode */ - if (scancode & 0x80) goto irq1_end; - if (scancode > MAX_SCAN_CODE) goto irq1_end; - if (flags1 & 0x08) { /* Alt is being pressed */ - asciiscan=scan_to_scanascii[scancode].alt; -#if 0 /* old unicode support disabled*/ - } else if (ascii) { - asciiscan=(scancode << 8) | ascii; -#endif - } else if (flags1 & 0x04) { /* Ctrl is being pressed */ - asciiscan=scan_to_scanascii[scancode].control; - } else if (flags1 & 0x03) { /* Either shift is being pressed */ - asciiscan=scan_to_scanascii[scancode].shift; - } else { - asciiscan=scan_to_scanascii[scancode].normal; - } - /* cancel shift is letter and capslock active */ - if(flags1&64) { - if(flags1&3) { - /*cancel shift */ - if(((asciiscan&0x00ff) >0x40) && ((asciiscan&0x00ff) <0x5b)) - asciiscan=scan_to_scanascii[scancode].normal; - } else { - /* add shift */ - if(((asciiscan&0x00ff) >0x60) && ((asciiscan&0x00ff) <0x7b)) - asciiscan=scan_to_scanascii[scancode].shift; - } - } - if (flags3 &0x02) { - /* extended key (numblock), return and slash need special handling */ - if (scancode==0x1c) { /* return */ - if (flags1 &0x08) asciiscan=0xa600; - else asciiscan=(asciiscan&0xff)|0xe000; - } else if (scancode==0x35) { /* slash */ - if (flags1 &0x08) asciiscan=0xa400; - else if (flags1 &0x04) asciiscan=0x9500; - else asciiscan=0xe02f; - } - } - add_key(asciiscan); - break; - }; -irq1_end: - if(scancode !=0xe0) flags3 &=~0x02; //Reset 0xE0 Flag - mem_writeb(BIOS_KEYBOARD_FLAGS1,flags1); - if ((scancode&0x80)==0) flags2&=0xf7; - mem_writeb(BIOS_KEYBOARD_FLAGS2,flags2); - mem_writeb(BIOS_KEYBOARD_FLAGS3,flags3); - mem_writeb(BIOS_KEYBOARD_LEDS,leds); -/* IO_Write(0x20,0x20); moved out of handler to be virtualizable */ -#if 0 -/* Signal the keyboard for next code */ -/* In dosbox port 60 reads do this as well */ - Bit8u old61=IO_Read(0x61); - IO_Write(0x61,old61 | 128); - IO_Write(0x64,0xae); -#endif - return CBRET_NONE; -} - - -/* check whether key combination is enhanced or not, - translate key if necessary */ -static bool IsEnhancedKey(Bit16u &key) { - /* test for special keys (return and slash on numblock) */ - if ((key>>8)==0xe0) { - if (((key&0xff)==0x0a) || ((key&0xff)==0x0d)) { - /* key is return on the numblock */ - key=(key&0xff)|0x1c00; - } else { - /* key is slash on the numblock */ - key=(key&0xff)|0x3500; - } - /* both keys are not considered enhanced keys */ - return false; - } else if (((key>>8)>0x84) || (((key&0xff)==0xf0) && (key>>8))) { - /* key is enhanced key (either scancode part>0x84 or - specially-marked keyboard combination, low part==0xf0) */ - return true; - } - /* convert key if necessary (extended keys) */ - if ((key>>8) && ((key&0xff)==0xe0)) { - key&=0xff00; - } - return false; -} - -static Bitu INT16_Handler(void) { - Bit16u temp=0; - switch (reg_ah) { - case 0x00: /* GET KEYSTROKE */ - if ((get_key(temp)) && (!IsEnhancedKey(temp))) { - /* normal key found, return translated key in ax */ - reg_ax=temp; - } else { - /* enter small idle loop to allow for irqs to happen */ - reg_ip+=1; - } - break; - case 0x10: /* GET KEYSTROKE (enhanced keyboards only) */ - if (get_key(temp)) { - if (((temp&0xff)==0xf0) && (temp>>8)) { - /* special enhanced key, clear low part before returning key */ - temp&=0xff00; - } - reg_ax=temp; - } else { - /* enter small idle loop to allow for irqs to happen */ - reg_ip+=1; - } - break; - case 0x01: /* CHECK FOR KEYSTROKE */ - // enable interrupt-flag after IRET of this int16 - mem_writew(SegPhys(ss)+reg_sp+4,(mem_readw(SegPhys(ss)+reg_sp+4) | FLAG_IF)); - for (;;) { - if (check_key(temp)) { - if (!IsEnhancedKey(temp)) { - /* normal key, return translated key in ax */ - CALLBACK_SZF(false); - reg_ax=temp; - break; - } else { - /* remove enhanced key from buffer and ignore it */ - get_key(temp); - } - } else { - /* no key available */ - CALLBACK_SZF(true); - break; - } -// CALLBACK_Idle(); - } - break; - case 0x11: /* CHECK FOR KEYSTROKE (enhanced keyboards only) */ - if (!check_key(temp)) { - CALLBACK_SZF(true); - } else { - CALLBACK_SZF(false); - if (((temp&0xff)==0xf0) && (temp>>8)) { - /* special enhanced key, clear low part before returning key */ - temp&=0xff00; - } - reg_ax=temp; - } - break; - case 0x02: /* GET SHIFT FlAGS */ - reg_al=mem_readb(BIOS_KEYBOARD_FLAGS1); - break; - case 0x03: /* SET TYPEMATIC RATE AND DELAY */ - if (reg_al == 0x00) { // set default delay and rate - IO_Write(0x60,0xf3); - IO_Write(0x60,0x20); // 500 msec delay, 30 cps - } else if (reg_al == 0x05) { // set repeat rate and delay - IO_Write(0x60,0xf3); - IO_Write(0x60,(reg_bh&3)<<5|(reg_bl&0x1f)); - } else { - LOG(LOG_BIOS,LOG_ERROR)("INT16:Unhandled Typematic Rate Call %2X BX=%X",reg_al,reg_bx); - } - break; - case 0x05: /* STORE KEYSTROKE IN KEYBOARD BUFFER */ - if (BIOS_AddKeyToBuffer(reg_cx)) reg_al=0; - else reg_al=1; - break; - case 0x12: /* GET EXTENDED SHIFT STATES */ - reg_al=mem_readb(BIOS_KEYBOARD_FLAGS1); - reg_ah=mem_readb(BIOS_KEYBOARD_FLAGS2); - break; - case 0x55: - /* Weird call used by some dos apps */ - LOG(LOG_BIOS,LOG_NORMAL)("INT16:55:Word TSR compatible call"); - break; - default: - LOG(LOG_BIOS,LOG_ERROR)("INT16:Unhandled call %02X",reg_ah); - break; - - }; - - return CBRET_NONE; -} - -//Keyboard initialisation. src/gui/sdlmain.cpp -extern bool startup_state_numlock; -extern bool startup_state_capslock; - -static void InitBiosSegment(void) { - /* Setup the variables for keyboard in the bios data segment */ - mem_writew(BIOS_KEYBOARD_BUFFER_START,0x1e); - mem_writew(BIOS_KEYBOARD_BUFFER_END,0x3e); - mem_writew(BIOS_KEYBOARD_BUFFER_HEAD,0x1e); - mem_writew(BIOS_KEYBOARD_BUFFER_TAIL,0x1e); - Bit8u flag1 = 0; - Bit8u leds = 16; /* Ack recieved */ - if(startup_state_capslock) { flag1|=0x40; leds|=0x04;} - if(startup_state_numlock){ flag1|=0x20; leds|=0x02;} - mem_writeb(BIOS_KEYBOARD_FLAGS1,flag1); - mem_writeb(BIOS_KEYBOARD_FLAGS2,0); - mem_writeb(BIOS_KEYBOARD_FLAGS3,16); /* Enhanced keyboard installed */ - mem_writeb(BIOS_KEYBOARD_TOKEN,0); - mem_writeb(BIOS_KEYBOARD_LEDS,leds); -} - -void BIOS_SetupKeyboard(void) { - /* Init the variables */ - InitBiosSegment(); - - /* Allocate/setup a callback for int 0x16 and for standard IRQ 1 handler */ - call_int16=CALLBACK_Allocate(); - CALLBACK_Setup(call_int16,&INT16_Handler,CB_INT16,"keyboard"); - RealSetVec(0x16,CALLBACK_RealPointer(call_int16)); - - call_irq1=CALLBACK_Allocate(); - CALLBACK_Setup(call_irq1,&IRQ1_Handler,CB_IRQ1,"keyboard irq"); - RealSetVec(0x9,CALLBACK_RealPointer(call_irq1)); - // pseudocode for CB_IRQ1: - // push ax - // in al, 0x60 - // mov ah, 0x4f - // stc - // int 15 - // jc skip - // callback IRQ1_Handler - // label skip: - // cli - // mov al, 0x20 - // out 0x20, al - // pop ax - // iret - - if (machine==MCH_PCJR) { - call_irq6=CALLBACK_Allocate(); - CALLBACK_Setup(call_irq6,NULL,CB_IRQ6_PCJR,"PCJr kb irq"); - RealSetVec(0x0e,CALLBACK_RealPointer(call_irq6)); - // pseudocode for CB_IRQ6_PCJR: - // push ax - // in al, 0x60 - // cmp al, 0xe0 - // je skip - // int 0x09 - // label skip: - // cli - // mov al, 0x20 - // out 0x20, al - // pop ax - // iret - } -} - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "callback.h" +#include "mem.h" +#include "bios.h" +#include "keyboard.h" +#include "regs.h" +#include "inout.h" + + +static Bitu call_int16,call_irq1; + + +/* Nice table from BOCHS i should feel bad for ripping this */ +#define none 0 +#define MAX_SCAN_CODE 0x53 +static struct { + Bit16u normal; + Bit16u shift; + Bit16u control; + Bit16u alt; + } scan_to_scanascii[MAX_SCAN_CODE + 1] = { + { none, none, none, none }, + { 0x011b, 0x011b, 0x011b, 0x0100 }, /* escape */ + { 0x0231, 0x0221, none, 0x7800 }, /* 1! */ + { 0x0332, 0x0340, 0x0300, 0x7900 }, /* 2@ */ + { 0x0433, 0x0423, none, 0x7a00 }, /* 3# */ + { 0x0534, 0x0524, none, 0x7b00 }, /* 4$ */ + { 0x0635, 0x0625, none, 0x7c00 }, /* 5% */ + { 0x0736, 0x075e, 0x071e, 0x7d00 }, /* 6^ */ + { 0x0837, 0x0826, none, 0x7e00 }, /* 7& */ + { 0x0938, 0x092a, none, 0x7f00 }, /* 8* */ + { 0x0a39, 0x0a28, none, 0x8000 }, /* 9( */ + { 0x0b30, 0x0b29, none, 0x8100 }, /* 0) */ + { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* -_ */ + { 0x0d3d, 0x0d2b, none, 0x8300 }, /* =+ */ + { 0x0e08, 0x0e08, 0x0e7f, none }, /* backspace */ + { 0x0f09, 0x0f00, none, none }, /* tab */ + { 0x1071, 0x1051, 0x1011, 0x1000 }, /* Q */ + { 0x1177, 0x1157, 0x1117, 0x1100 }, /* W */ + { 0x1265, 0x1245, 0x1205, 0x1200 }, /* E */ + { 0x1372, 0x1352, 0x1312, 0x1300 }, /* R */ + { 0x1474, 0x1454, 0x1414, 0x1400 }, /* T */ + { 0x1579, 0x1559, 0x1519, 0x1500 }, /* Y */ + { 0x1675, 0x1655, 0x1615, 0x1600 }, /* U */ + { 0x1769, 0x1749, 0x1709, 0x1700 }, /* I */ + { 0x186f, 0x184f, 0x180f, 0x1800 }, /* O */ + { 0x1970, 0x1950, 0x1910, 0x1900 }, /* P */ + { 0x1a5b, 0x1a7b, 0x1a1b, none }, /* [{ */ + { 0x1b5d, 0x1b7d, 0x1b1d, none }, /* ]} */ + { 0x1c0d, 0x1c0d, 0x1c0a, none }, /* Enter */ + { none, none, none, none }, /* L Ctrl */ + { 0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* A */ + { 0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* S */ + { 0x2064, 0x2044, 0x2004, 0x2000 }, /* D */ + { 0x2166, 0x2146, 0x2106, 0x2100 }, /* F */ + { 0x2267, 0x2247, 0x2207, 0x2200 }, /* G */ + { 0x2368, 0x2348, 0x2308, 0x2300 }, /* H */ + { 0x246a, 0x244a, 0x240a, 0x2400 }, /* J */ + { 0x256b, 0x254b, 0x250b, 0x2500 }, /* K */ + { 0x266c, 0x264c, 0x260c, 0x2600 }, /* L */ + { 0x273b, 0x273a, none, none }, /* ;: */ + { 0x2827, 0x2822, none, none }, /* '" */ + { 0x2960, 0x297e, none, none }, /* `~ */ + { none, none, none, none }, /* L shift */ + { 0x2b5c, 0x2b7c, 0x2b1c, none }, /* |\ */ + { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* Z */ + { 0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* X */ + { 0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* C */ + { 0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* V */ + { 0x3062, 0x3042, 0x3002, 0x3000 }, /* B */ + { 0x316e, 0x314e, 0x310e, 0x3100 }, /* N */ + { 0x326d, 0x324d, 0x320d, 0x3200 }, /* M */ + { 0x332c, 0x333c, none, none }, /* ,< */ + { 0x342e, 0x343e, none, none }, /* .> */ + { 0x352f, 0x353f, none, none }, /* /? */ + { none, none, none, none }, /* R Shift */ + { 0x372a, 0x372a, none, none }, /* * */ + { none, none, none, none }, /* L Alt */ + { 0x3920, 0x3920, 0x3920, 0x3920 }, /* space */ + { none, none, none, none }, /* caps lock */ + { 0x3b00, 0x5400, 0x5e00, 0x6800 }, /* F1 */ + { 0x3c00, 0x5500, 0x5f00, 0x6900 }, /* F2 */ + { 0x3d00, 0x5600, 0x6000, 0x6a00 }, /* F3 */ + { 0x3e00, 0x5700, 0x6100, 0x6b00 }, /* F4 */ + { 0x3f00, 0x5800, 0x6200, 0x6c00 }, /* F5 */ + { 0x4000, 0x5900, 0x6300, 0x6d00 }, /* F6 */ + { 0x4100, 0x5a00, 0x6400, 0x6e00 }, /* F7 */ + { 0x4200, 0x5b00, 0x6500, 0x6f00 }, /* F8 */ + { 0x4300, 0x5c00, 0x6600, 0x7000 }, /* F9 */ + { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* F10 */ + { none, none, none, none }, /* Num Lock */ + { none, none, none, none }, /* Scroll Lock */ + { 0x4700, 0x4737, 0x7700, none }, /* 7 Home */ + { 0x4800, 0x4838, none, none }, /* 8 UP */ + { 0x4900, 0x4939, 0x8400, none }, /* 9 PgUp */ + { 0x4a2d, 0x4a2d, none, none }, /* - */ + { 0x4b00, 0x4b34, 0x7300, none }, /* 4 Left */ + { 0x4c00, 0x4c35, none, none }, /* 5 */ + { 0x4d00, 0x4d36, 0x7400, none }, /* 6 Right */ + { 0x4e2b, 0x4e2b, none, none }, /* + */ + { 0x4f00, 0x4f31, 0x7500, none }, /* 1 End */ + { 0x5000, 0x5032, none, none }, /* 2 Down */ + { 0x5100, 0x5133, 0x7600, none }, /* 3 PgDn */ + { 0x5200, 0x5230, none, none }, /* 0 Ins */ + { 0x5300, 0x532e, none, none } /* Del */ + }; + +/* +Old Stuff not needed after i ripped Bochs :) +static Bit8u KeyNoShift[128]={ + 27,'1','2','3', '4','5','6','7', '8','9','0','-', '=',8,9,'q', + 'w','e','r','t', 'y','u','i','o', 'p','[',']',13, 255,'a','s','d', + 'f','g','h','j', 'k','l',';','\'', '`',255,'\\','z', 'x','c','v','b', + 'n','m',',','.', '/',255,'*',255, ' ',255,0,0, 0,0,0,0, + 0,0,0,0, 255,255,0,0, 0,'-',0,255, 0,'+',0,0, + 0,0,0,0, 0 +}; + +static Bit8u KeyShift[128]={ + 27,'!','@','#', '$','%','^','&', '*','(',')','_', '+',8,9,'Q', + 'W','E','R','T', 'Y','U','I','O', 'P','{','}',13, 255,'A','S','D', + 'F','G','H','J', 'K','L',':','"', '~',255,'|','Z', 'X','C','V','B', + 'N','M','<','>', '?',255,'*',255, ' ',255,0,0, 0,0,0,0, + 0,0,0,0, 255,255,0,0, 0,'-',0,255, 0,'+',0,0, + 0,0,0,0, 0 +}; +*/ + +static void add_key(Bit16u code) { + Bit16u start,end,head,tail,ttail; + start=mem_readw(BIOS_KEYBOARD_BUFFER_START); + end =mem_readw(BIOS_KEYBOARD_BUFFER_END); + head =mem_readw(BIOS_KEYBOARD_BUFFER_HEAD); + tail =mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); + ttail=tail+2; + if (ttail>=end) ttail=start; + /* Check for buffer Full */ + //TODO Maybe beeeeeeep or something although that should happend when internal buffer is full + if (ttail==head) return; + real_writew(0x40,tail,code); + mem_writew(BIOS_KEYBOARD_BUFFER_TAIL,ttail); +} + +static Bit16u get_key(void) { + Bit16u start,end,head,tail,thead; + start=mem_readw(BIOS_KEYBOARD_BUFFER_START); + end =mem_readw(BIOS_KEYBOARD_BUFFER_END); + head =mem_readw(BIOS_KEYBOARD_BUFFER_HEAD); + tail =mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); + + if (head==tail) return 0; + thead=head+2; + if (thead>=end) thead=start; + mem_writew(BIOS_KEYBOARD_BUFFER_HEAD,thead); + return real_readw(0x40,head); +} + +static Bit16u check_key(void) { + Bit16u head,tail; + head =mem_readw(BIOS_KEYBOARD_BUFFER_HEAD); + tail =mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); + if (head==tail) return 0; + return real_readw(0x40,head); +} + + + /* Flag Byte 1 + bit 7 =1 INSert active + bit 6 =1 Caps Lock active + bit 5 =1 Num Lock active + bit 4 =1 Scroll Lock active + bit 3 =1 either Alt pressed + bit 2 =1 either Ctrl pressed + bit 1 =1 Left Shift pressed + bit 0 =1 Right Shift pressed + */ + /* Flag Byte 2 + bit 7 =1 INSert pressed + bit 6 =1 Caps Lock pressed + bit 5 =1 Num Lock pressed + bit 4 =1 Scroll Lock pressed + bit 3 =1 Pause state active + bit 2 =1 Sys Req pressed + bit 1 =1 Left Alt pressed + bit 0 =1 Left Ctrl pressed + */ + /* + Keyboard status byte 3 + bit 7 =1 read-ID in progress + bit 6 =1 last code read was first of two ID codes + bit 5 =1 force Num Lock if read-ID and enhanced keyboard + bit 4 =1 enhanced keyboard installed + bit 3 =1 Right Alt pressed + bit 2 =1 Right Ctrl pressed + bit 1 =1 last code read was E0h + bit 0 =1 last code read was E1h + */ + + +static Bitu IRQ1_Handler(void) { + //TODO CAPSLOCK NUMLOCK SCROLLLOCK maybe :) + Bit8u code=IO_Read(0x60); + //TODO maybe implement the int 0x15 ah=4f scancode lookup hook +/* Changed it so the flag handling takes place in here too */ + Bit8u flags1=mem_readb(BIOS_KEYBOARD_FLAGS1); + Bit8u flags2=mem_readb(BIOS_KEYBOARD_FLAGS2); + Bit8u flags3=mem_readb(BIOS_KEYBOARD_FLAGS3); + switch (code) { + /* First the hard ones */ + case 0xe0: + //TODO Think of something else maybe + flags3|=2; + break; + case 29: /* Ctrl Pressed */ + flags1|=4; + if (flags3 & 2) flags3|=4; + else flags2|=1; + break; + case 157: /* Ctrl Released */ + flags1&=~4; + if (flags3 & 2) flags3&=~4; + else flags2&=~1; + break; + case 42: /* Left Shift Pressed */ + flags1|=2; + break; + case 170: /* Left Shift Released */ + flags1&=~2; + break; + case 54: /* Right Shift Pressed */ + flags1|=1; + break; + case 182: /* Right Shift Released */ + flags1&=~1; + break; + case 56: /* Alt Pressed */ + flags1|=8; + if (flags3 & 2) flags3|=8; + else flags2|=2; + break; + case 184: /* Alt Released */ + flags1&=~8; + if (flags3 & 2) flags3&=~8; + else flags2&=~2; + break; + +#if 0 + case 58:p_capslock=true;break; /* Caps Lock */ + case 186:p_capslock=false;break; + case 69:p_numlock=true;break; /* Num Lock */ + case 197:p_numlock=false;break; + case 70:p_scrolllock=true;break; /* Scroll Lock */ + case 198:p_scrolllock=false;break; + case 82:p_insert=true;break; /* Insert */ + case 210:p_insert=false;a_insert=!a_insert;break; +#endif + default: /* Normal Key */ + Bit16u asciiscan; + /* Now Handle the releasing of keys and see if they match up for a code */ + flags3&=~2; //Reset 0xE0 Flag + /* Handle the actual scancode */ + if (code & 0x80) goto irq1_end; + if (code > MAX_SCAN_CODE) goto irq1_end; + if (flags1 & 8) { /* Alt is being pressed */ + asciiscan=scan_to_scanascii[code].alt; + } else if (flags1 & 4) { /* Ctrl is being pressed */ + asciiscan=scan_to_scanascii[code].control; + } else if (flags1 & 3) { /* Either shift is being pressed */ +//TODO Maybe check for Capslock sometime in some bored way + asciiscan=scan_to_scanascii[code].shift; + } else { + asciiscan=scan_to_scanascii[code].normal; + } + add_key(asciiscan); + }; +irq1_end: + mem_writeb(BIOS_KEYBOARD_FLAGS1,flags1); + mem_writeb(BIOS_KEYBOARD_FLAGS2,flags2); + mem_writeb(BIOS_KEYBOARD_FLAGS3,flags3); + IO_Write(0x20,0x20); + /* Signal the keyboard for next code */ + Bit8u old61=IO_Read(0x61); + IO_Write(0x61,old61 | 128); + IO_Write(0x61,old61 & 127); + return CBRET_NONE; +} + +static Bitu INT16_Handler(void) { + Bit16u temp; + switch (reg_ah) { + case 0x00: /* GET KEYSTROKE */ + case 0x10: + { +//TODO find a more elegant way to do this + do { + temp=get_key(); + if (temp==0) { flags.intf=true;CALLBACK_Idle();}; + } while (temp==0); + reg_ax=temp; + break; + } + case 0x01: /* CHECK FOR KEYSTROKE */ + case 0x11: + temp=check_key(); + if (temp==0) { + CALLBACK_SZF(true); + } else { + CALLBACK_SZF(false); + reg_ax=temp; + } + break; + case 0x02: /* GET SHIFT FlAGS */ + reg_al=mem_readb(BIOS_KEYBOARD_FLAGS1); + break; + case 0x03: /* SET TYPEMATIC RATE AND DELAY */ +//Have to implement this trhough SDL + LOG_DEBUG("INT16:Unhandled Typematic Rate Call %2X",reg_al); + break; + case 0x05: /* STORE KEYSTROKE IN KEYBOARD BUFFER */ +//TODO make add_key bool :) + add_key(reg_ax); + reg_al=0; + break; + case 0x12: /* GET EXTENDED SHIFT STATES */ + reg_al=mem_readb(BIOS_KEYBOARD_FLAGS1); + reg_ah=mem_readb(BIOS_KEYBOARD_FLAGS2); + break; + case 0x55: + /* Weird call used by some dos apps */ + LOG_DEBUG("INT16:55:Word TSR compatible call"); + break; + default: + E_Exit("INT16:Unhandled call %02X",reg_ah); + break; + + }; + + return CBRET_NONE; +} + +static void InitBiosSegment(void) { + /* Setup the variables for keyboard in the bios data segment */ + mem_writew(BIOS_KEYBOARD_BUFFER_START,0x1e); + mem_writew(BIOS_KEYBOARD_BUFFER_END,0x3e); + mem_writew(BIOS_KEYBOARD_BUFFER_HEAD,0x1e); + mem_writew(BIOS_KEYBOARD_BUFFER_TAIL,0x1e); + mem_writeb(BIOS_KEYBOARD_FLAGS1,0); + mem_writeb(BIOS_KEYBOARD_FLAGS2,0); + mem_writeb(BIOS_KEYBOARD_FLAGS3,16); /* Enhanced keyboard installed */ +} + +void BIOS_SetupKeyboard(void) { + /* Init the variables */ + InitBiosSegment(); + /* Allocate a callback for int 0x16 and for standard IRQ 1 handler */ + call_int16=CALLBACK_Allocate(); + call_irq1=CALLBACK_Allocate(); + CALLBACK_Setup(call_int16,&INT16_Handler,CB_IRET); + RealSetVec(0x16,CALLBACK_RealPointer(call_int16)); + CALLBACK_Setup(call_irq1,&IRQ1_Handler,CB_IRET); + RealSetVec(0x9,CALLBACK_RealPointer(call_irq1)); +} + diff --git a/src/ints/ems.cpp b/src/ints/ems.cpp index 345b278..d10839c 100644 --- a/src/ints/ems.cpp +++ b/src/ints/ems.cpp @@ -1,1383 +1,165 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: ems.cpp,v 1.60 2008/11/27 18:57:45 c2woody Exp $ */ - -#include -#include -#include "dosbox.h" -#include "callback.h" -#include "mem.h" -#include "paging.h" -#include "bios.h" -#include "keyboard.h" -#include "regs.h" -#include "inout.h" -#include "dos_inc.h" -#include "setup.h" -#include "support.h" -#include "cpu.h" - -#define EMM_PAGEFRAME 0xE000 -#define EMM_PAGEFRAME4K ((EMM_PAGEFRAME*16)/4096) -#define EMM_MAX_HANDLES 200 /* 255 Max */ -#define EMM_PAGE_SIZE (16*1024U) -#define EMM_MAX_PAGES (32 * 1024 / 16 ) -#define EMM_MAX_PHYS 4 /* 4 16kb pages in pageframe */ - -#define EMM_VERSION 0x40 -#define GEMMIS_VERSION 0x0001 // Version 1.0 - -#define NULL_HANDLE 0xffff -#define NULL_PAGE 0xffff - -#define ENABLE_VCPI 1 -#define ENABLE_V86_STARTUP 0 - - -/* EMM errors */ -#define EMM_NO_ERROR 0x00 -#define EMM_SOFT_MAL 0x80 -#define EMM_HARD_MAL 0x81 -#define EMM_INVALID_HANDLE 0x83 -#define EMM_FUNC_NOSUP 0x84 -#define EMM_OUT_OF_HANDLES 0x85 -#define EMM_SAVEMAP_ERROR 0x86 -#define EMM_OUT_OF_PHYS 0x87 -#define EMM_OUT_OF_LOG 0x88 -#define EMM_ZERO_PAGES 0x89 -#define EMM_LOG_OUT_RANGE 0x8a -#define EMM_ILL_PHYS 0x8b -#define EMM_PAGE_MAP_SAVED 0x8d -#define EMM_NO_SAVED_PAGE_MAP 0x8e -#define EMM_INVALID_SUB 0x8f -#define EMM_FEAT_NOSUP 0x91 -#define EMM_MOVE_OVLAP 0x92 -#define EMM_MOVE_OVLAPI 0x97 -#define EMM_NOT_FOUND 0xa0 - -static Bit16u GEMMIS_seg; - -class device_EMM : public DOS_Device { -public: - device_EMM() { - SetName("EMMXXXX0"); - GEMMIS_seg=0; - } - bool Read(Bit8u * data,Bit16u * size) { return false;} - bool Write(Bit8u * data,Bit16u * size){ - LOG(LOG_IOCTL,LOG_NORMAL)("EMS:Write to device"); - return false; - } - bool Seek(Bit32u * pos,Bit32u type){return false;} - bool Close(){return false;} - Bit16u GetInformation(void){return 0xc080;} - bool ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode); - bool WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode){return true;} -private: - Bit8u cache; -}; - -bool device_EMM::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { - Bitu subfct=mem_readb(bufptr); - switch (subfct) { - case 0x00: - if (size!=6) return false; - mem_writew(bufptr+0x00,0x0023); // ID - mem_writed(bufptr+0x02,0); // private API entry point - *retcode=6; - return true; - case 0x01: { - if (size!=6) return false; - if (GEMMIS_seg==0) GEMMIS_seg=DOS_GetMemory(0x20); - PhysPt GEMMIS_addr=PhysMake(GEMMIS_seg,0); - - mem_writew(GEMMIS_addr+0x00,0x0004); // flags - mem_writew(GEMMIS_addr+0x02,0x019d); // size of this structure - mem_writew(GEMMIS_addr+0x04,GEMMIS_VERSION); // version 1.0 (provide ems information only) - mem_writed(GEMMIS_addr+0x06,0); // reserved - - /* build non-EMS frames (0-0xe000) */ - for (Bitu frct=0; frct>4); // version 4.0 - mem_writew(bufptr+0x01,EMM_VERSION&0x0f); - *retcode=2; - return true; - } - return false; -} - -struct EMM_Mapping { - Bit16u handle; - Bit16u page; -}; - -struct EMM_Handle { - Bit16u pages; - MemHandle mem; - char name[8]; - bool saved_page_map; - EMM_Mapping page_map[EMM_MAX_PHYS]; -}; - -static EMM_Handle emm_handles[EMM_MAX_HANDLES]; -static EMM_Mapping emm_mappings[EMM_MAX_PHYS]; -static EMM_Mapping emm_segmentmappings[0x40]; - -static struct { - bool enabled; - Bit16u ems_handle; - Bitu pm_interface; - MemHandle private_area; - Bit8u pic1_remapping,pic2_remapping; -} vcpi ; - -struct MoveRegion { - Bit32u bytes; - Bit8u src_type; - Bit16u src_handle; - Bit16u src_offset; - Bit16u src_page_seg; - Bit8u dest_type; - Bit16u dest_handle; - Bit16u dest_offset; - Bit16u dest_page_seg; -}; - -static Bit16u EMM_GetFreePages(void) { - Bitu count=MEM_FreeTotal()/4; - if (count>0x7fff) count=0x7fff; - return (Bit16u)count; -} - -static bool INLINE ValidHandle(Bit16u handle) { - if (handle>=EMM_MAX_HANDLES) return false; - if (emm_handles[handle].pages==NULL_HANDLE) return false; - return true; -} - -static Bit8u EMM_AllocateMemory(Bit16u pages,Bit16u & dhandle,bool can_allocate_zpages) { - /* Check for 0 page allocation */ - if (!pages) { - if (!can_allocate_zpages) return EMM_ZERO_PAGES; - } - /* Check for enough free pages */ - if ((MEM_FreeTotal()/ 4) < pages) { return EMM_OUT_OF_LOG;} - Bit16u handle = 1; - /* Check for a free handle */ - while (emm_handles[handle].pages != NULL_HANDLE) { - if (++handle >= EMM_MAX_HANDLES) {return EMM_OUT_OF_HANDLES;} - } - MemHandle mem = MEM_AllocatePages(pages*4,false); - if (!mem) E_Exit("EMS:Memory allocation failure"); - emm_handles[handle].pages = pages; - emm_handles[handle].mem = mem; - /* Change handle only if there is no error. */ - dhandle = handle; - return EMM_NO_ERROR; -} - -static Bit8u EMM_AllocateSystemHandle(Bit16u pages) { - /* Check for enough free pages */ - if ((MEM_FreeTotal()/ 4) < pages) { return EMM_OUT_OF_LOG;} - Bit16u handle = 0; // emm system handle (reserved for OS usage) - /* Release memory if already allocated */ - if (emm_handles[handle].pages != NULL_HANDLE) { - MEM_ReleasePages(emm_handles[handle].mem); - } - MemHandle mem = MEM_AllocatePages(pages*4,false); - if (!mem) E_Exit("EMS:System handle memory allocation failure"); - emm_handles[handle].pages = pages; - emm_handles[handle].mem = mem; - return EMM_NO_ERROR; -} - -static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) { - /* Check for valid handle */ - if (!ValidHandle(handle)) return EMM_INVALID_HANDLE; - /* Check for enough pages */ - if (!MEM_ReAllocatePages(emm_handles[handle].mem,pages*4,false)) return EMM_OUT_OF_LOG; - /* Update size */ - emm_handles[handle].pages=pages; - return EMM_NO_ERROR; -} - -static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) { -// LOG_MSG("EMS MapPage handle %d phys %d log %d",handle,phys_page,log_page); - /* Check for too high physical page */ - if (phys_page>=EMM_MAX_PHYS) return EMM_ILL_PHYS; - - /* unmapping doesn't need valid handle (as handle isn't used) */ - if (log_page==NULL_PAGE) { - /* Unmapping */ - emm_mappings[phys_page].handle=NULL_HANDLE; - emm_mappings[phys_page].page=NULL_PAGE; - for (Bitu i=0;i<4;i++) - PAGING_MapPage(EMM_PAGEFRAME4K+phys_page*4+i,EMM_PAGEFRAME4K+phys_page*4+i); - PAGING_ClearTLB(); - return EMM_NO_ERROR; - } - /* Check for valid handle */ - if (!ValidHandle(handle)) return EMM_INVALID_HANDLE; - - if (log_page=0xa000) && (segment<0xb000)) || ((segment>=EMM_PAGEFRAME-0x1000) && (segment=0) && (tphysPage>10].handle=NULL_HANDLE; - emm_segmentmappings[segment>>10].page=NULL_PAGE; - } - for (Bitu i=0;i<4;i++) - PAGING_MapPage(segment*16/4096+i,segment*16/4096+i); - PAGING_ClearTLB(); - return EMM_NO_ERROR; - } - /* Check for valid handle */ - if (!ValidHandle(handle)) return EMM_INVALID_HANDLE; - - if (log_page=0) && (tphysPage>10].handle=handle; - emm_segmentmappings[segment>>10].page=log_page; - } - - MemHandle memh=MEM_NextHandleAt(emm_handles[handle].mem,log_page*4);; - for (Bitu i=0;i<4;i++) { - PAGING_MapPage(segment*16/4096+i,memh); - memh=MEM_NextHandle(memh); - } - PAGING_ClearTLB(); - return EMM_NO_ERROR; - } else { - /* Illegal logical page it is */ - return EMM_LOG_OUT_RANGE; - } - } - - return EMM_ILL_PHYS; -} - -static Bit8u EMM_ReleaseMemory(Bit16u handle) { - /* Check for valid handle */ - if (!ValidHandle(handle)) return EMM_INVALID_HANDLE; - // should check for saved_page_map flag here, returning an error if it's true - // as apps are required to restore the pagemap beforehand; to be checked - MEM_ReleasePages(emm_handles[handle].mem); - /* Reset handle */ - emm_handles[handle].mem=0; - if (handle==0) { - emm_handles[handle].pages=0; // OS handle is NEVER deallocated - } else { - emm_handles[handle].pages=NULL_HANDLE; - } - emm_handles[handle].saved_page_map=false; - memset(&emm_handles[handle].name,0,8); - return EMM_NO_ERROR; -} - -static Bit8u EMM_SavePageMap(Bit16u handle) { - /* Check for valid handle */ - if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) { - if (handle!=0) return EMM_INVALID_HANDLE; - } - /* Check for previous save */ - if (emm_handles[handle].saved_page_map) return EMM_PAGE_MAP_SAVED; - /* Copy the mappings over */ - for (Bitu i=0;i=EMM_PAGEFRAME/0x400) && (i<(EMM_PAGEFRAME/0x400)+EMM_MAX_PHYS)) continue; - result=EMM_MapSegment(i<<10,emm_segmentmappings[i].handle,emm_segmentmappings[i].page); - } - for (Bitu i=0;i=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) { - if (handle!=0) return EMM_INVALID_HANDLE; - } - /* Check for previous save */ - if (!emm_handles[handle].saved_page_map) return EMM_NO_SAVED_PAGE_MAP; - /* Restore the mappings */ - emm_handles[handle].saved_page_map=false; - for (Bitu i=0;i0;count--) { - Bit16u segment=mem_readw(list);list+=2; - if ((segment>=EMM_PAGEFRAME) && (segment>4); - mem_writew(data,segment);data+=2; - MEM_BlockWrite(data,&emm_mappings[page],sizeof(EMM_Mapping)); - data+=sizeof(EMM_Mapping); - } else if (((segment>=EMM_PAGEFRAME-0x1000) && (segment=0xa000) && (segment<0xb000))) { - mem_writew(data,segment);data+=2; - MEM_BlockWrite(data,&emm_segmentmappings[segment>>10],sizeof(EMM_Mapping)); - data+=sizeof(EMM_Mapping); - } else { - return EMM_ILL_PHYS; - } - } - break; - case 0x01: /* Restore Partial Page Map */ - data = SegPhys(ds)+reg_si; - count= mem_readw(data);data+=2; - for (;count>0;count--) { - Bit16u segment=mem_readw(data);data+=2; - if ((segment>=EMM_PAGEFRAME) && (segment>4); - MEM_BlockRead(data,&emm_mappings[page],sizeof(EMM_Mapping)); - } else if (((segment>=EMM_PAGEFRAME-0x1000) && (segment=0xa000) && (segment<0xb000))) { - MEM_BlockRead(data,&emm_segmentmappings[segment>>10],sizeof(EMM_Mapping)); - } else { - return EMM_ILL_PHYS; - } - data+=sizeof(EMM_Mapping); - } - return EMM_RestoreMappingTable(); - break; - case 0x02: /* Get Partial Page Map Array Size */ - reg_al=(Bit8u)(2+reg_bx*(2+sizeof(EMM_Mapping))); - break; - default: - LOG(LOG_MISC,LOG_ERROR)("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); - return EMM_FUNC_NOSUP; - } - return EMM_NO_ERROR; -} - -static Bit8u HandleNameSearch(void) { - char name[9]; - Bit16u handle=0;PhysPt data; - switch (reg_al) { - case 0x00: /* Get all handle names */ - reg_al=0;data=SegPhys(es)+reg_di; - for (handle=0;handle=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE; - MEM_BlockWrite(SegPhys(es)+reg_di,emm_handles[handle].name,8); - break; - case 0x01: /* Set Handle Name */ - if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE; - MEM_BlockRead(SegPhys(es)+reg_di,emm_handles[handle].name,8); - break; - default: - LOG(LOG_MISC,LOG_ERROR)("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); - return EMM_INVALID_SUB; - } - return EMM_NO_ERROR; - -} - - -static void LoadMoveRegion(PhysPt data,MoveRegion & region) { - region.bytes=mem_readd(data+0x0); - - region.src_type=mem_readb(data+0x4); - region.src_handle=mem_readw(data+0x5); - region.src_offset=mem_readw(data+0x7); - region.src_page_seg=mem_readw(data+0x9); - - region.dest_type=mem_readb(data+0xb); - region.dest_handle=mem_readw(data+0xc); - region.dest_offset=mem_readw(data+0xe); - region.dest_page_seg=mem_readw(data+0x10); -} - -static Bit8u MemoryRegion(void) { - MoveRegion region; - Bit8u buf_src[MEM_PAGE_SIZE]; - Bit8u buf_dest[MEM_PAGE_SIZE]; - if (reg_al>1) { - LOG(LOG_MISC,LOG_ERROR)("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); - return EMM_FUNC_NOSUP; - } - LoadMoveRegion(SegPhys(ds)+reg_si,region); - /* Parse the region for information */ - PhysPt src_mem = 0,dest_mem = 0; - MemHandle src_handle = 0,dest_handle = 0; - Bitu src_off = 0,dest_off = 0 ;Bitu src_remain = 0,dest_remain = 0; - if (!region.src_type) { - src_mem=region.src_page_seg*16+region.src_offset; - } else { - if (!ValidHandle(region.src_handle)) return EMM_INVALID_HANDLE; - if ((emm_handles[region.src_handle].pages*EMM_PAGE_SIZE) < ((region.src_page_seg*EMM_PAGE_SIZE)+region.src_offset+region.bytes)) return EMM_LOG_OUT_RANGE; - src_handle=emm_handles[region.src_handle].mem; - Bitu pages=region.src_page_seg*4+(region.src_offset/MEM_PAGE_SIZE); - for (;pages>0;pages--) src_handle=MEM_NextHandle(src_handle); - src_off=region.src_offset&(MEM_PAGE_SIZE-1); - src_remain=MEM_PAGE_SIZE-src_off; - } - if (!region.dest_type) { - dest_mem=region.dest_page_seg*16+region.dest_offset; - } else { - if (!ValidHandle(region.dest_handle)) return EMM_INVALID_HANDLE; - if (emm_handles[region.dest_handle].pages*EMM_PAGE_SIZE < (region.dest_page_seg*EMM_PAGE_SIZE)+region.dest_offset+region.bytes) return EMM_LOG_OUT_RANGE; - dest_handle=emm_handles[region.dest_handle].mem; - Bitu pages=region.dest_page_seg*4+(region.dest_offset/MEM_PAGE_SIZE); - for (;pages>0;pages--) dest_handle=MEM_NextHandle(dest_handle); - dest_off=region.dest_offset&(MEM_PAGE_SIZE-1); - dest_remain=MEM_PAGE_SIZE-dest_off; - } - Bitu toread; - while (region.bytes>0) { - if (region.bytes>MEM_PAGE_SIZE) toread=MEM_PAGE_SIZE; - else toread=region.bytes; - /* Read from the source */ - if (!region.src_type) { - MEM_BlockRead(src_mem,buf_src,toread); - } else { - if (toread>6)+(ct*0x10); - real_writew(SegValue(es),entry_addr+0x00+0x01,(memh+0)*0x10); // mapping of 1/4 of page - real_writew(SegValue(es),entry_addr+0x04+0x01,(memh+1)*0x10); // mapping of 2/4 of page - real_writew(SegValue(es),entry_addr+0x08+0x01,(memh+2)*0x10); // mapping of 3/4 of page - real_writew(SegValue(es),entry_addr+0x0c+0x01,(memh+3)*0x10); // mapping of 4/4 of page - } - } - reg_di+=0x400; // advance pointer by 0x100*4 - - /* Set up three descriptor table entries */ - Bit32u cbseg_low=(CALLBACK_GetBase()&0xffff)<<16; - Bit32u cbseg_high=(CALLBACK_GetBase()&0x1f0000)>>16; - /* Descriptor 1 (code segment, callback segment) */ - real_writed(SegValue(ds),reg_si+0x00,0x0000ffff|cbseg_low); - real_writed(SegValue(ds),reg_si+0x04,0x00009a00|cbseg_high); - /* Descriptor 2 (data segment, full access) */ - real_writed(SegValue(ds),reg_si+0x08,0x0000ffff); - real_writed(SegValue(ds),reg_si+0x0c,0x00009200); - /* Descriptor 3 (full access) */ - real_writed(SegValue(ds),reg_si+0x10,0x0000ffff); - real_writed(SegValue(ds),reg_si+0x14,0x00009200); - - reg_ebx=(vcpi.pm_interface&0xffff); - reg_ah=EMM_NO_ERROR; - break; - } - case 0x02: /* VCPI Maximum Physical Address */ - reg_edx=((MEM_TotalPages()*MEM_PAGESIZE)-1)&0xfffff000; - reg_ah=EMM_NO_ERROR; - break; - case 0x03: /* VCPI Get Number of Free Pages */ - reg_edx=MEM_FreeTotal(); - reg_ah=EMM_NO_ERROR; - break; - case 0x04: { /* VCPI Allocate one Page */ - MemHandle mem = MEM_AllocatePages(1,false); - if (mem) { - reg_edx=mem<<12; - reg_ah=EMM_NO_ERROR; - } else { - reg_ah=EMM_OUT_OF_LOG; - } - break; - } - case 0x05: /* VCPI Free Page */ - MEM_ReleasePages(reg_edx>>12); - reg_ah=EMM_NO_ERROR; - break; - case 0x06: { /* VCPI Get Physical Address of Page in 1st MB */ - if (((reg_cx<<8)>=EMM_PAGEFRAME) && ((reg_cx<<8)>12); - reg_ah=EMM_NO_ERROR; - break; - case 0xDE0C: { /* VCPI Switch from Protected Mode to V86 */ - reg_flags&=(~FLAG_IF); - - /* Flags need to be filled in, VM=true, IOPL=3 */ - mem_writed(SegPhys(ss) + (reg_esp & cpu.stack.mask)+0x10, 0x23002); - - /* Disable Paging */ - CPU_SET_CRX(0, CPU_GET_CRX(0)&0x7ffffff7); - CPU_SET_CRX(3, 0); - - PhysPt tbaddr=vcpi.private_area+0x0000+(0x10&0xfff8)+5; - Bit8u tb=mem_readb(tbaddr); - mem_writeb(tbaddr, tb&0xfd); - - /* Load descriptor table registers */ - CPU_LGDT(0xff, vcpi.private_area+0x0000); - CPU_LIDT(0x7ff, vcpi.private_area+0x2000); - if (CPU_LLDT(0x08)) LOG_MSG("VCPI:Could not load LDT"); - if (CPU_LTR(0x10)) LOG_MSG("VCPI:Could not load TR"); - - reg_flags&=(~FLAG_NT); - reg_esp+=8; // skip interrupt return information -// MEM_A20_Enable(false); - - /* Switch to v86-task */ - CPU_IRET(true,0); - } - break; - default: - LOG(LOG_MISC,LOG_WARN)("Unhandled VCPI-function %x in protected mode",reg_al); - break; - } - return CBRET_NONE; -} - -static Bitu V86_Monitor() { - /* Calculate which interrupt did occur */ - Bitu int_num=(mem_readw(SegPhys(ss)+(reg_esp & cpu.stack.mask))-0x2803); - - /* See if Exception 0x0d and not Interrupt 0x0d */ - if ((int_num==(0x0d*4)) && ((reg_sp&0xffff)!=0x1fda)) { - /* Protection violation during V86-execution, - needs intervention by monitor (depends on faulting opcode) */ - - reg_esp+=6; // skip ip of CALL and error code of EXCEPTION 0x0d - - /* Get adress of faulting instruction */ - Bit16u v86_cs=mem_readw(SegPhys(ss)+((reg_esp+4) & cpu.stack.mask)); - Bit16u v86_ip=mem_readw(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask)); - Bit8u v86_opcode=mem_readb((v86_cs<<4)+v86_ip); -// LOG_MSG("v86 monitor caught protection violation at %x:%x, opcode=%x",v86_cs,v86_ip,v86_opcode); - switch (v86_opcode) { - case 0x0f: // double byte opcode - v86_opcode=mem_readb((v86_cs<<4)+v86_ip+1); - switch (v86_opcode) { - case 0x20: { // mov reg,CRx - Bitu rm_val=mem_readb((v86_cs<<4)+v86_ip+2); - Bitu which=(rm_val >> 3) & 7; - if ((rm_val<0xc0) || (rm_val>=0xe8)) - E_Exit("Invalid opcode 0x0f 0x20 %x caused a protection fault!",static_cast(rm_val)); - Bit32u crx=CPU_GET_CRX(which); - switch (rm_val&7) { - case 0: reg_eax=crx; break; - case 1: reg_ecx=crx; break; - case 2: reg_edx=crx; break; - case 3: reg_ebx=crx; break; - case 4: reg_esp=crx; break; - case 5: reg_ebp=crx; break; - case 6: reg_esi=crx; break; - case 7: reg_edi=crx; break; - } - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+3); - } - break; - case 0x22: { // mov CRx,reg - Bitu rm_val=mem_readb((v86_cs<<4)+v86_ip+2); - Bitu which=(rm_val >> 3) & 7; - if ((rm_val<0xc0) || (rm_val>=0xe8)) - E_Exit("Invalid opcode 0x0f 0x22 %x caused a protection fault!",static_cast(rm_val)); - Bit32u crx=0; - switch (rm_val&7) { - case 0: crx=reg_eax; break; - case 1: crx=reg_ecx; break; - case 2: crx=reg_edx; break; - case 3: crx=reg_ebx; break; - case 4: crx=reg_esp; break; - case 5: crx=reg_ebp; break; - case 6: crx=reg_esi; break; - case 7: crx=reg_edi; break; - } - if (which==0) crx|=1; // protection bit always on - CPU_SET_CRX(which,crx); - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+3); - } - break; - default: - E_Exit("Unhandled opcode 0x0f %x caused a protection fault!",v86_opcode); - } - break; - case 0xe4: // IN AL,Ib - reg_al=IO_ReadB(mem_readb((v86_cs<<4)+v86_ip+1)); - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+2); - break; - case 0xe5: // IN AX,Ib - reg_ax=IO_ReadW(mem_readb((v86_cs<<4)+v86_ip+1)); - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+2); - break; - case 0xe6: // OUT Ib,AL - IO_WriteB(mem_readb((v86_cs<<4)+v86_ip+1),reg_al); - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+2); - break; - case 0xe7: // OUT Ib,AX - IO_WriteW(mem_readb((v86_cs<<4)+v86_ip+1),reg_ax); - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+2); - break; - case 0xec: // IN AL,DX - reg_al=IO_ReadB(reg_dx); - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+1); - break; - case 0xed: // IN AX,DX - reg_ax=IO_ReadW(reg_dx); - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+1); - break; - case 0xee: // OUT DX,AL - IO_WriteB(reg_dx,reg_al); - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+1); - break; - case 0xef: // OUT DX,AX - IO_WriteW(reg_dx,reg_ax); - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+1); - break; - case 0xf0: // LOCK prefix - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+1); - break; - case 0xf4: // HLT - reg_flags|=FLAG_IF; - CPU_HLT(reg_eip); - mem_writew(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask),v86_ip+1); - break; - default: - E_Exit("Unhandled opcode %x caused a protection fault!",v86_opcode); - } - return CBRET_NONE; - } - - /* Get address to interrupt handler */ - Bit16u vint_vector_seg=mem_readw(SegValue(ds)+int_num+2); - Bit16u vint_vector_ofs=mem_readw(int_num); - if (reg_sp!=0x1fda) reg_esp+=(2+3*4); // Interrupt from within protected mode - else reg_esp+=2; - - /* Read entries that were pushed onto the stack by the interrupt */ - Bit16u return_ip=mem_readw(SegPhys(ss)+(reg_esp & cpu.stack.mask)); - Bit16u return_cs=mem_readw(SegPhys(ss)+((reg_esp+4) & cpu.stack.mask)); - Bit32u return_eflags=mem_readd(SegPhys(ss)+((reg_esp+8) & cpu.stack.mask)); - - /* Modify stack to call v86-interrupt handler */ - mem_writed(SegPhys(ss)+(reg_esp & cpu.stack.mask),vint_vector_ofs); - mem_writed(SegPhys(ss)+((reg_esp+4) & cpu.stack.mask),vint_vector_seg); - mem_writed(SegPhys(ss)+((reg_esp+8) & cpu.stack.mask),return_eflags&(~(FLAG_IF|FLAG_TF))); - - /* Adjust SP of v86-stack */ - Bit16u v86_ss=mem_readw(SegPhys(ss)+((reg_esp+0x10) & cpu.stack.mask)); - Bit16u v86_sp=mem_readw(SegPhys(ss)+((reg_esp+0x0c) & cpu.stack.mask))-6; - mem_writew(SegPhys(ss)+((reg_esp+0x0c) & cpu.stack.mask),v86_sp); - - /* Return to original code after v86-interrupt handler */ - mem_writew((v86_ss<<4)+v86_sp+0,return_ip); - mem_writew((v86_ss<<4)+v86_sp+2,return_cs); - mem_writew((v86_ss<<4)+v86_sp+4,(Bit16u)(return_eflags&0xffff)); - return CBRET_NONE; -} - -static void SetupVCPI() { - vcpi.enabled=true; - - vcpi.pic1_remapping=0x08; // master PIC base - vcpi.pic2_remapping=0x70; // slave PIC base - - /* Allocate one EMS-page for private VCPI-data in memory beyond 1MB */ - EMM_AllocateMemory(1,vcpi.ems_handle,false); - vcpi.private_area=emm_handles[vcpi.ems_handle].mem<<12; - - /* GDT */ - mem_writed(vcpi.private_area+0x0000,0x00000000); // descriptor 0 - mem_writed(vcpi.private_area+0x0004,0x00000000); // descriptor 0 - - Bit32u ldt_address=(vcpi.private_area+0x1000); - Bit16u ldt_limit=0xff; - Bit32u ldt_desc_part=((ldt_address&0xffff)<<16)|ldt_limit; - mem_writed(vcpi.private_area+0x0008,ldt_desc_part); // descriptor 1 (LDT) - ldt_desc_part=((ldt_address&0xff0000)>>16)|(ldt_address&0xff000000)|0x8200; - mem_writed(vcpi.private_area+0x000c,ldt_desc_part); // descriptor 1 - - Bit32u tss_address=(vcpi.private_area+0x3000); - Bit32u tss_desc_part=((tss_address&0xffff)<<16)|(0x0068+0x200); - mem_writed(vcpi.private_area+0x0010,tss_desc_part); // descriptor 2 (TSS) - tss_desc_part=((tss_address&0xff0000)>>16)|(tss_address&0xff000000)|0x8900; - mem_writed(vcpi.private_area+0x0014,tss_desc_part); // descriptor 2 - - /* LDT */ - mem_writed(vcpi.private_area+0x1000,0x00000000); // descriptor 0 - mem_writed(vcpi.private_area+0x1004,0x00000000); // descriptor 0 - Bit32u cs_desc_part=((vcpi.private_area&0xffff)<<16)|0xffff; - mem_writed(vcpi.private_area+0x1008,cs_desc_part); // descriptor 1 (code) - cs_desc_part=((vcpi.private_area&0xff0000)>>16)|(vcpi.private_area&0xff000000)|0x9a00; - mem_writed(vcpi.private_area+0x100c,cs_desc_part); // descriptor 1 - Bit32u ds_desc_part=((vcpi.private_area&0xffff)<<16)|0xffff; - mem_writed(vcpi.private_area+0x1010,ds_desc_part); // descriptor 2 (data) - ds_desc_part=((vcpi.private_area&0xff0000)>>16)|(vcpi.private_area&0xff000000)|0x9200; - mem_writed(vcpi.private_area+0x1014,ds_desc_part); // descriptor 2 - - /* IDT setup */ - for (Bit16u int_ct=0; int_ct<0x100; int_ct++) { - /* build a CALL NEAR V86MON, the value of IP pushed by the - CALL is used to identify the interrupt number */ - mem_writeb(vcpi.private_area+0x2800+int_ct*4+0,0xe8); // call - mem_writew(vcpi.private_area+0x2800+int_ct*4+1,0x05fd-(int_ct*4)); - mem_writeb(vcpi.private_area+0x2800+int_ct*4+3,0xcf); // iret (dummy) - - /* put a Gate-Descriptor into the IDT */ - mem_writed(vcpi.private_area+0x2000+int_ct*8+0,0x000c0000|(0x2800+int_ct*4)); - mem_writed(vcpi.private_area+0x2000+int_ct*8+4,0x0000ee00); - } - - /* TSS */ - for (Bitu tse_ct=0; tse_ct<0x68+0x200; tse_ct++) { - /* clear the TSS as most entries are not used here */ - mem_writeb(vcpi.private_area+0x3000,0); - } - /* Set up the ring0-stack */ - mem_writed(vcpi.private_area+0x3004,0x00002000); // esp - mem_writed(vcpi.private_area+0x3008,0x00000014); // ss - - mem_writed(vcpi.private_area+0x3066,0x0068); // io-map base (map follows, all zero) -} - -static Bitu INT4B_Handler() { - switch (reg_ah) { - case 0x81: - CALLBACK_SCF(true); - reg_ax=0x1; - break; - default: - LOG(LOG_MISC,LOG_WARN)("Unhandled interrupt 4B function %x",reg_ah); - break; - } - return CBRET_NONE; -} - - -class EMS: public Module_base { -private: - /* location in protected unfreeable memory where the ems name and callback are - * stored 32 bytes.*/ - static Bit16u emsnameseg; - RealPt old4b_pointer,old67_pointer; - CALLBACK_HandlerObject call_vdma,int67,call_vcpi,call_v86mon; - -public: - EMS(Section* configuration):Module_base(configuration){ - - /* Virtual DMA interrupt callback */ - call_vdma.Install(&INT4B_Handler,CB_IRET,"Int 4b vdma"); - call_vdma.Set_RealVec(0x4b); - - vcpi.enabled=false; - GEMMIS_seg=0; - - Section_prop * section=static_cast(configuration); - if (!section->Get_bool("ems")) return; - if (machine==MCH_PCJR) { - LOG_MSG("EMS disabled for PCJr machine"); - return; - } - BIOS_ZeroExtendedSize(true); - int67.Install(&INT67_Handler,CB_IRET,"Int 67 ems"); - Bit16u call_int67=int67.Get_callback(); - - /* Register the ems device */ - //TODO MAYBE put it in the class. - DOS_Device * newdev = new device_EMM(); - DOS_AddDevice(newdev); - - /* Add a little hack so it appears that there is an actual ems device installed */ - char const* emsname="EMMXXXX0"; - if(!emsnameseg) emsnameseg=DOS_GetMemory(2); //We have 32 bytes - MEM_BlockWrite(PhysMake(emsnameseg,0xa),emsname,(Bitu)(strlen(emsname)+1)); - - /* Copy the callback piece into the beginning, and set the interrupt vector to it*/ - char buf[16]; - MEM_BlockRead(CALLBACK_PhysPointer(call_int67),buf,0xa); - MEM_BlockWrite(PhysMake(emsnameseg,0),buf,0xa); - RealSetVec(0x67,RealMake(emsnameseg,0),old67_pointer); - - /* Clear handle and page tables */ - Bitu i; - for (i=0;i(m_configuration); - if (!section->Get_bool("ems")) return; - /* Undo Biosclearing */ - BIOS_ZeroExtendedSize(false); - - /* Remove ems device */ - device_EMM newdev; - DOS_DelDevice(&newdev); - GEMMIS_seg=0; - - /* Remove the emsname and callback hack */ - char buf[32]= { 0 }; - MEM_BlockWrite(PhysMake(emsnameseg,0),buf,32); - RealSetVec(0x67,old67_pointer); - /* Clear handle and page tables */ - //TODO - - if (!ENABLE_VCPI) return; - - /* Free private data area in expanded memory */ - EMM_ReleaseMemory(vcpi.ems_handle); - - if (cpu.pmode && GETFLAG(VM)) { - /* Switch back to real mode if in v86-mode */ - CPU_SET_CRX(0, 0); - CPU_SET_CRX(3, 0); - reg_flags&=(~(FLAG_IOPL|FLAG_VM)); - CPU_LIDT(0x3ff, 0); - cpu.cpl=0; - } - } -}; - -static EMS* test; - -void EMS_ShutDown(Section* sec) { - delete test; -} - -void EMS_Init(Section* sec) { - test = new EMS(sec); - sec->AddDestroyFunction(&EMS_ShutDown,true); -} - -//Initialize static members -Bit16u EMS::emsnameseg = 0; +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include +#include "dosbox.h" +#include "callback.h" +#include "mem.h" +#include "bios.h" +#include "keyboard.h" +#include "regs.h" +#include "inout.h" +#include "dos_inc.h" + + +#define PAGEFRAME_SEG 0xe000 + +class device_EMS : public DOS_Device { +public: + device_EMS(); + bool Read(Bit8u * data,Bit16u * size); + bool Write(Bit8u * data,Bit16u * size); + bool Seek(Bit32u * pos,Bit32u type); + bool Close(); + Bit16u GetInformation(void); +private: + Bit8u cache; +}; + +bool device_EMS::Read(Bit8u * data,Bit16u * size) { + return false; +} + +bool device_EMS::Write(Bit8u * data,Bit16u * size) { + return false; +} + +bool device_EMS::Seek(Bit32u * pos,Bit32u type) { + return false; +} + +bool device_EMS::Close() { + return false; +} + +Bit16u device_EMS::GetInformation(void) { + return 0x8093; +}; + +device_EMS::device_EMS() { + name="EMMXXXX0"; +} + + +PageEntry ems_entries[4]; + +Bitu call_int67; +static Bitu INT67_Handler(void) { + switch (reg_ah) { + case 0x40: /* Get Status */ + reg_ah=0; //Status ok :) + break; + case 0x41: /* Get PageFrame Segment */ + reg_bx=PAGEFRAME_SEG; + reg_ah=0; + break; + case 0x42: /* Get number of pages */ + { +//HEHE Hope this works not exactly like the specs but who cares + Bit16u maxfree,total; + EMM_GetFree(&maxfree,&total); + reg_dx=maxfree>>2; + reg_bx=total>>2; + reg_ah=0; + }; + break; + case 0x43: /* Get Handle and Allocate Pages */ + { + if (!reg_bx) { reg_ah=0x89;break; } + Bit16u handle; + EMM_Allocate(reg_bx*4,&handle); + if (handle) { + reg_ah=0; + reg_dx=handle; + } else { reg_ah=0x88; } + break; + } + case 0x44: /* Map Memory */ + { + if (reg_al>3) { reg_ah=0x8b;break; } + HostOff pagestart=memory+EMM_Handles[reg_dx].phys_base+reg_bx*16*1024; + ems_entries[reg_al].relocate=pagestart; + reg_ah=0; + break; + } + case 0x45: /* Release handle and free pages */ + EMM_Free(reg_dx); + reg_ah=0; + break; + case 0x46: /* Get EMM Version */ + reg_ah=0; + reg_al=0x32; //Only 3.2 support for now + break; + case 0x47: /* Save Mapping Context */ + LOG_ERROR("EMS:47:Save Mapping Context not supported"); + reg_ah=0x8c; + break; + case 0xDE: /* VCPI Functions */ + LOG_ERROR("VCPI Functions not supported"); + reg_ah=0x8c; + break; + default: + LOG_ERROR("EMS:Call %2X not supported",reg_ah); + reg_ah=0x8c; + break; + } + return CBRET_NONE; +} + + + +void EMS_Init(void) { + call_int67=CALLBACK_Allocate(); + CALLBACK_Setup(call_int67,&INT67_Handler,CB_IRET); +/* Register the ems device */ + DOS_Device * newdev = new device_EMS(); + DOS_AddDevice(newdev); +/* Setup the page handlers for the page frame */ + for (Bitu i=0;i<4;i++) { + ems_entries[i].base=(PAGEFRAME_SEG<<4)+i*16*1024; + ems_entries[i].type=MEMORY_RELOCATE; + ems_entries[i].relocate=memory+(PAGEFRAME_SEG<<4)+i*16*1024; +/* Place the page handlers in the ems page fram piece of the memory handler*/ + MEMORY_SetupHandler(((PAGEFRAME_SEG<<4)+i*16*1024)>>12,4,&ems_entries[i]); + } + + +/* Add a little hack so it appears that there is an actual ems device installed */ + char * emsname="EMMXXXX0"; + Bit16u seg=DOS_GetMemory(2); //We have 32 bytes + MEM_BlockWrite(real_phys(seg,0xa),emsname,strlen(emsname)+1); +/* Copy the callback piece into the beginning */ + char buf[16]; + MEM_BlockRead(real_phys(CB_SEG,call_int67<<4),buf,0xa); + MEM_BlockWrite(real_phys(seg,0),buf,0xa); + + RealSetVec(0x67,RealMake(seg,0)); + +} + diff --git a/src/ints/int10.cpp b/src/ints/int10.cpp index 5d41df7..b08c0b1 100644 --- a/src/ints/int10.cpp +++ b/src/ints/int10.cpp @@ -1,723 +1,278 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: int10.cpp,v 1.55 2009/04/11 07:58:39 qbix79 Exp $ */ - -#include "dosbox.h" -#include "mem.h" -#include "callback.h" -#include "regs.h" -#include "inout.h" -#include "int10.h" -#include "setup.h" - -Int10Data int10; -static Bitu call_10; -static bool warned_ff=false; - -static Bitu INT10_Handler(void) { -#if 0 - switch (reg_ah) { - case 0x02: - case 0x03: - case 0x09: - case 0xc: - case 0xd: - case 0x0e: - case 0x10: - case 0x4f: - - break; - default: - LOG(LOG_INT10,LOG_NORMAL)("Function AX:%04X , BX %04X DX %04X",reg_ax,reg_bx,reg_dx); - break; - } -#endif - - switch (reg_ah) { - case 0x00: /* Set VideoMode */ - INT10_SetVideoMode(reg_al); - break; - case 0x01: /* Set TextMode Cursor Shape */ - INT10_SetCursorShape(reg_ch,reg_cl); - break; - case 0x02: /* Set Cursor Pos */ - INT10_SetCursorPos(reg_dh,reg_dl,reg_bh); - break; - case 0x03: /* get Cursor Pos and Cursor Shape*/ -// reg_ah=0; - reg_dl=CURSOR_POS_COL(reg_bh); - reg_dh=CURSOR_POS_ROW(reg_bh); - reg_cx=real_readw(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE); - break; - case 0x04: /* read light pen pos YEAH RIGHT */ - /* Light pen is not supported */ - reg_ax=0; - break; - case 0x05: /* Set Active Page */ - if ((reg_al & 0x80) && IS_TANDY_ARCH) { - Bit8u crtcpu=real_readb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE); - switch (reg_al) { - case 0x80: - reg_bh=crtcpu & 7; - reg_bl=(crtcpu >> 3) & 0x7; - break; - case 0x81: - crtcpu=(crtcpu & 0xc7) | ((reg_bl & 7) << 3); - break; - case 0x82: - crtcpu=(crtcpu & 0xf8) | (reg_bh & 7); - break; - case 0x83: - crtcpu=(crtcpu & 0xc0) | (reg_bh & 7) | ((reg_bl & 7) << 3); - break; - } - if (machine==MCH_PCJR) { - /* always return graphics mapping, even for invalid values of AL */ - reg_bh=crtcpu & 7; - reg_bl=(crtcpu >> 3) & 0x7; - } - IO_WriteB(0x3df,crtcpu); - real_writeb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE,crtcpu); - } - else INT10_SetActivePage(reg_al); - break; - case 0x06: /* Scroll Up */ - INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,-reg_al,reg_bh,0xFF); - break; - case 0x07: /* Scroll Down */ - INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF); - break; - case 0x08: /* Read character & attribute at cursor */ - INT10_ReadCharAttr(®_ax,reg_bh); - break; - case 0x09: /* Write Character & Attribute at cursor CX times */ - INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,true); - break; - case 0x0A: /* Write Character at cursor CX times */ - INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,false); - break; - case 0x0B: /* Set Background/Border Colour & Set Palette*/ - switch (reg_bh) { - case 0x00: //Background/Border color - INT10_SetBackgroundBorder(reg_bl); - break; - case 0x01: //Set color Select - default: - INT10_SetColorSelect(reg_bl); - break; - } - break; - case 0x0C: /* Write Graphics Pixel */ - INT10_PutPixel(reg_cx,reg_dx,reg_bh,reg_al); - break; - case 0x0D: /* Read Graphics Pixel */ - INT10_GetPixel(reg_cx,reg_dx,reg_bh,®_al); - break; - case 0x0E: /* Teletype OutPut */ - INT10_TeletypeOutput(reg_al,reg_bl); - break; - case 0x0F: /* Get videomode */ - reg_bh=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); - reg_al=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)|(real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)&0x80); - reg_ah=(Bit8u)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); - break; - case 0x10: /* Palette functions */ - if ((machine==MCH_CGA) || ((!IS_VGA_ARCH) && (reg_al>0x02))) break; - //TODO: subfunction 0x03 for ega - switch (reg_al) { - case 0x00: /* SET SINGLE PALETTE REGISTER */ - INT10_SetSinglePaletteRegister(reg_bl,reg_bh); - break; - case 0x01: /* SET BORDER (OVERSCAN) COLOR*/ - INT10_SetOverscanBorderColor(reg_bh); - break; - case 0x02: /* SET ALL PALETTE REGISTERS */ - INT10_SetAllPaletteRegisters(SegPhys(es)+reg_dx); - break; - case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */ - INT10_ToggleBlinkingBit(reg_bl); - break; - case 0x07: /* GET SINGLE PALETTE REGISTER */ - INT10_GetSinglePaletteRegister(reg_bl,®_bh); - break; - case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER */ - INT10_GetOverscanBorderColor(®_bh); - break; - case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER */ - INT10_GetAllPaletteRegisters(SegPhys(es)+reg_dx); - break; - case 0x10: /* SET INDIVIDUAL DAC REGISTER */ - INT10_SetSingleDacRegister(reg_bl,reg_dh,reg_ch,reg_cl); - break; - case 0x12: /* SET BLOCK OF DAC REGISTERS */ - INT10_SetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx); - break; - case 0x13: /* SELECT VIDEO DAC COLOR PAGE */ - INT10_SelectDACPage(reg_bl,reg_bh); - break; - case 0x15: /* GET INDIVIDUAL DAC REGISTER */ - INT10_GetSingleDacRegister(reg_bl,®_dh,®_ch,®_cl); - break; - case 0x17: /* GET BLOCK OF DAC REGISTER */ - INT10_GetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx); - break; - case 0x18: /* undocumented - SET PEL MASK */ - INT10_SetPelMask(reg_bl); - break; - case 0x19: /* undocumented - GET PEL MASK */ - INT10_GetPelMask(reg_bl); - reg_bh=0; // bx for get mask - break; - case 0x1A: /* GET VIDEO DAC COLOR PAGE */ - INT10_GetDACPage(®_bl,®_bh); - break; - case 0x1B: /* PERFORM GRAY-SCALE SUMMING */ - INT10_PerformGrayScaleSumming(reg_bx,reg_cx); - break; - case 0xF0: /* ET4000: SET HiColor GRAPHICS MODE */ - case 0xF1: /* ET4000: GET DAC TYPE */ - case 0xF2: /* ET4000: CHECK/SET HiColor MODE */ - default: - LOG(LOG_INT10,LOG_ERROR)("Function 10:Unhandled EGA/VGA Palette Function %2X",reg_al); - break; - } - break; - case 0x11: /* Character generator functions */ - if (!IS_EGAVGA_ARCH) - break; - switch (reg_al) { -/* Textmode calls */ - case 0x00: /* Load user font */ - case 0x10: - INT10_LoadFont(SegPhys(es)+reg_bp,reg_al==0x10,reg_cx,reg_dx,reg_bl,reg_bh); - break; - case 0x01: /* Load 8x14 font */ - case 0x11: - INT10_LoadFont(Real2Phys(int10.rom.font_14),reg_al==0x11,256,0,0,14); - break; - case 0x02: /* Load 8x8 font */ - case 0x12: - INT10_LoadFont(Real2Phys(int10.rom.font_8_first),reg_al==0x12,256,0,0,8); - break; - case 0x03: /* Set Block Specifier */ - IO_Write(0x3c4,0x3);IO_Write(0x3c5,reg_bl); - break; - case 0x04: /* Load 8x16 font */ - case 0x14: - if (!IS_VGA_ARCH) break; - INT10_LoadFont(Real2Phys(int10.rom.font_16),reg_al==0x14,256,0,0,16); - break; -/* Graphics mode calls */ - case 0x20: /* Set User 8x8 Graphics characters */ - RealSetVec(0x1f,RealMake(SegValue(es),reg_bp)); - break; - case 0x21: /* Set user graphics characters */ - RealSetVec(0x43,RealMake(SegValue(es),reg_bp)); - real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,reg_cx); - goto graphics_chars; - case 0x22: /* Rom 8x14 set */ - RealSetVec(0x43,int10.rom.font_14); - real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,14); - goto graphics_chars; - case 0x23: /* Rom 8x8 double dot set */ - RealSetVec(0x43,int10.rom.font_8_first); - real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,8); - goto graphics_chars; - case 0x24: /* Rom 8x16 set */ - if (!IS_VGA_ARCH) break; - RealSetVec(0x43,int10.rom.font_16); - real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,16); - goto graphics_chars; -graphics_chars: - switch (reg_bl) { - case 0x00:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,reg_dl-1);break; - case 0x01:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,13);break; - case 0x03:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,42);break; - case 0x02: - default:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,24);break; - } - break; -/* General */ - case 0x30:/* Get Font Information */ - switch (reg_bh) { - case 0x00: /* interupt 0x1f vector */ - { - RealPt int_1f=RealGetVec(0x1f); - SegSet16(es,RealSeg(int_1f)); - reg_bp=RealOff(int_1f); - } - break; - case 0x01: /* interupt 0x43 vector */ - { - RealPt int_43=RealGetVec(0x43); - SegSet16(es,RealSeg(int_43)); - reg_bp=RealOff(int_43); - } - break; - case 0x02: /* font 8x14 */ - SegSet16(es,RealSeg(int10.rom.font_14)); - reg_bp=RealOff(int10.rom.font_14); - break; - case 0x03: /* font 8x8 first 128 */ - SegSet16(es,RealSeg(int10.rom.font_8_first)); - reg_bp=RealOff(int10.rom.font_8_first); - break; - case 0x04: /* font 8x8 second 128 */ - SegSet16(es,RealSeg(int10.rom.font_8_second)); - reg_bp=RealOff(int10.rom.font_8_second); - break; - case 0x05: /* alpha alternate 9x14 */ - if (!IS_VGA_ARCH) break; - SegSet16(es,RealSeg(int10.rom.font_14_alternate)); - reg_bp=RealOff(int10.rom.font_14_alternate); - break; - case 0x06: /* font 8x16 */ - if (!IS_VGA_ARCH) break; - SegSet16(es,RealSeg(int10.rom.font_16)); - reg_bp=RealOff(int10.rom.font_16); - break; - case 0x07: /* alpha alternate 9x16 */ - if (!IS_VGA_ARCH) break; - SegSet16(es,RealSeg(int10.rom.font_16_alternate)); - reg_bp=RealOff(int10.rom.font_16_alternate); - break; - default: - LOG(LOG_INT10,LOG_ERROR)("Function 11:30 Request for font %2X",reg_bh); - break; - } - if ((reg_bh<=7) || (svgaCard==SVGA_TsengET4K)) { - if (machine==MCH_EGA) { - reg_cx=0x0e; - reg_dl=0x18; - } else { - reg_cx=real_readw(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); - reg_dl=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS); - } - } - break; - default: - LOG(LOG_INT10,LOG_ERROR)("Function 11:Unsupported character generator call %2X",reg_al); - break; - } - break; - case 0x12: /* alternate function select */ - if (!IS_EGAVGA_ARCH) - break; - switch (reg_bl) { - case 0x10: /* Get EGA Information */ - reg_bh=(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)==0x3B4); - reg_bl=3; //256 kb - reg_cl=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES) & 0x0F; - reg_ch=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES) >> 4; - break; - case 0x20: /* Set alternate printscreen */ - break; - case 0x30: /* Select vertical resolution */ - if (!IS_VGA_ARCH) break; - LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl); - if (reg_al>2) reg_al=0; //invalid subfunction - else reg_al=0x12; //fake a success call - break; - case 0x31: /* Palette loading on modeset */ - { - if (!IS_VGA_ARCH) break; - if (svgaCard==SVGA_TsengET4K) reg_al&=1; - if (reg_al>1) { - reg_al=0; //invalid subfunction - break; - } - Bit8u temp = real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL) & 0xf7; - if (reg_al&1) temp|=8; // enable if al=0 - real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,temp); - reg_al=0x12; - break; - } - case 0x32: /* Video adressing */ - if (!IS_VGA_ARCH) break; - LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl); - if (svgaCard==SVGA_TsengET4K) reg_al&=1; - if (reg_al>1) reg_al=0; //invalid subfunction - else reg_al=0x12; //fake a success call - break; - case 0x33: /* SWITCH GRAY-SCALE SUMMING */ - { - if (!IS_VGA_ARCH) break; - if (svgaCard==SVGA_TsengET4K) reg_al&=1; - if (reg_al>1) { - reg_al=0; - break; - } - Bit8u temp = real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL) & 0xfd; - if (!(reg_al&1)) temp|=2; // enable if al=0 - real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,temp); - reg_al=0x12; - break; - } - case 0x34: /* ALTERNATE FUNCTION SELECT (VGA) - CURSOR EMULATION */ - { - // bit 0: 0=enable, 1=disable - if (!IS_VGA_ARCH) break; - if (svgaCard==SVGA_TsengET4K) reg_al&=1; - if (reg_al>1) { - reg_al=0; - break; - } - Bit8u temp = real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & 0xfe; - real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,temp|reg_al); - reg_al=0x12; - break; - } - case 0x35: - if (!IS_VGA_ARCH) break; - LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl); - reg_al=0x12; - break; - case 0x36: /* VGA Refresh control */ - if (!IS_VGA_ARCH) break; - if ((svgaCard==SVGA_S3Trio) && (reg_al>1)) { - reg_al=0; - break; - } - /* - Call disables/enables the vga from outputting video, - don't support it, but fake a success return - */ - reg_al=0x12; - break; - default: - LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl); - if (machine!=MCH_EGA) reg_al=0; - break; - } - break; - case 0x13: /* Write String */ - INT10_WriteString(reg_dh,reg_dl,reg_al,reg_bl,SegPhys(es)+reg_bp,reg_cx,reg_bh); - break; - case 0x1A: /* Display Combination */ - if (!IS_VGA_ARCH) break; - if (reg_al==0) { // get dcc - // walk the tables... - RealPt vsavept=real_readd(BIOSMEM_SEG,BIOSMEM_VS_POINTER); - RealPt svstable=real_readd(RealSeg(vsavept),RealOff(vsavept)+0x10); - if (svstable) { - RealPt dcctable=real_readd(RealSeg(svstable),RealOff(svstable)+0x02); - Bit8u entries=real_readb(RealSeg(dcctable),RealOff(dcctable)+0x00); - Bit8u idx=real_readb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX); - // check if index within range - if (idx>8; - else reg_bx=dccentry; - } else reg_bx=0xffff; - } else reg_bx=0xffff; - reg_ax=0x1A; // high part destroyed or zeroed depending on BIOS - } else if (reg_al==1) { // set dcc - Bit8u newidx=0xff; - // walk the tables... - RealPt vsavept=real_readd(BIOSMEM_SEG,BIOSMEM_VS_POINTER); - RealPt svstable=real_readd(RealSeg(vsavept),RealOff(vsavept)+0x10); - if (svstable) { - RealPt dcctable=real_readd(RealSeg(svstable),RealOff(svstable)+0x02); - Bit8u entries=real_readb(RealSeg(dcctable),RealOff(dcctable)+0x00); - if (entries) { - Bitu ct; - Bit16u swpidx=reg_bh|(reg_bl<<8); - // search the ddc index in the dcc table - for (ct=0; ct +#include "dosbox.h" +#include "bios.h" +#include "mem.h" +#include "callback.h" +#include "regs.h" +#include "video.h" +#include "inout.h" +#include "int10.h" + +#define TEXT_SEG 0xb800 + +static Bitu call_10; +static bool warned_ff=false; + + +static Bitu INT10_Handler(void) { + switch (reg_ah) { + case 0x00: /* Set VideoMode */ + INT10_SetVideoMode(reg_al); + break; + case 0x01: /* Set TextMode Cursor Shape */ + LOG_WARN("INT10:01:Set textmode cursor shape not supported"); + break; + case 0x02: /* Set Cursor Pos */ + //TODO Check some shit but not really usefull + INT10_SetCursorPos(reg_dh,reg_dl,reg_bh); + break; + case 0x03: /* get Cursor Pos and Cursor Shape*/ + //TODO the Cursor Shape Stuff + reg_dl=CURSOR_POS_COL(reg_bh); + reg_dh=CURSOR_POS_ROW(reg_bh); + break; + case 0x04: /* read light pen pos YEAH RIGHT */ + LOG_WARN("INT10:04:Ligthpen not supported"); + break; + case 0x05: /* Set Active Page */ + INT10_SetActivePage(reg_al); + break; + case 0x06: /* Scroll Up */ +//TODO Graphics mode scroll + INT10_ScrollUpWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF); + break; + case 0x07: /* Scroll Down */ + INT10_ScrollDownWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF); + break; + case 0x08: /* Read character & attribute at cursor */ +//TODO Check for GRAPH and then just return + INT10_ReadCharAttr(®_ax,reg_bh); + break; + case 0x09: /* Write Character & Attribute at cursor CX times */ + INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,true); + break; + case 0x0A: /* Write Character at cursor CX times */ + INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,false); + break; + case 0x0B: /* Set Background/Border Colour & Set Palette*/ + break; + E_Exit("Unsupported int 10 call %02X" ,reg_ah); + break; + case 0x0C: /* Write Graphics Pixel */ + INT10_PutPixel(reg_cx,reg_dx,reg_bh,reg_al); + break; + case 0x0D: /* Read Graphics Pixel */ + INT10_GetPixel(reg_cx,reg_dx,reg_bh,®_al); + break; + case 0x0E: /* Teletype OutPut */ + //TODO FIX + INT10_TeletypeOutput(reg_al,reg_bl,false,0); +// INT10_TeletypeOutput(reg_al,reg_bl,false,reg_bh); + break; + case 0x0F: /* Get videomode */ + reg_bh=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + reg_al=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); + reg_ah=(Bit8u)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); + break; + case 0x10: /* EGA/VGA Palette functions */ + switch (reg_al) { + case 0x00: /* SET SINGLE PALETTE REGISTER */ + INT10_SetSinglePaletteRegister(reg_bl,reg_bh); + break; + case 0x01: /* SET BORDER (OVERSCAN) COLOR*/ + INT10_SetOverscanBorderColor(reg_bh); + break; + case 0x02: /* SET ALL PALETTE REGISTERS */ + INT10_SetAllPaletteRegisters(real_phys(Segs[es].value,reg_dx)); + break; + case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */ + INT10_ToggleBlinkingBit(reg_bl); + break; + case 0x07: /* GET SINGLE PALETTE REGISTER */ + INT10_GetSinglePaletteRegister(reg_bl,®_bh); + break; + case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER */ + INT10_GetOverscanBorderColor(®_bh); + break; + case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER */ + INT10_GetAllPaletteRegisters(real_phys(Segs[es].value,reg_dx)); + break; + case 0x10: /* SET INDIVIDUAL DAC REGISTER */ + INT10_SetSingleDacRegister(reg_bl,reg_dh,reg_ch,reg_cl); + break; + case 0x12: /* SET BLOCK OF DAC REGISTERS */ + INT10_SetDACBlock(reg_bx,reg_cx,real_phys(Segs[es].value,reg_dx)); + break; + case 0x15: /* GET INDIVIDUAL DAC REGISTER */ + INT10_GetSingleDacRegister(reg_bl,®_dh,®_ch,®_cl); + break; + case 0x17: /* GET BLOCK OF DAC REGISTER */ + INT10_GetDACBlock(reg_bx,reg_cx,real_phys(Segs[es].value,reg_dx)); + break; + default: + LOG_WARN("INT10:10:Unhandled EGA/VGA Palette Function %2X",reg_al); + } + break; + case 0x11: /* Character generator functions */ + switch (reg_al) { + case 0x30:/* Get Font Information */ + switch (reg_bh) { + case 0x00: /* interupt 0x1f vector */ + { + RealPt int_1f=RealGetVec(0x1f); + SetSegment_16(es,RealSeg(int_1f)); + reg_bp=RealOff(int_1f); + reg_cx=8; + } + break; + case 0x01: /* interupt 0x43 vector */ + { + RealPt int_43=RealGetVec(0x43); + SetSegment_16(es,RealSeg(int_43)); + reg_bp=RealOff(int_43); + reg_cx=8; + } + break; + case 0x02: /* font 8x14 */ + SetSegment_16(es,RealSeg(int10_romarea.font_14)); + reg_bp=RealOff(int10_romarea.font_14); + reg_cx=14; + break; + case 0x03: /* font 8x8 first 128 */ + SetSegment_16(es,RealSeg(int10_romarea.font_8_first)); + reg_bp=RealOff(int10_romarea.font_8_first); + reg_cx=8; + break; + case 0x04: /* font 8x8 second 128 */ + SetSegment_16(es,RealSeg(int10_romarea.font_8_second)); + reg_bp=RealOff(int10_romarea.font_8_second); + reg_cx=8; + break; + case 0x06: /* font 8x16 */ + SetSegment_16(es,RealSeg(int10_romarea.font_16)); + reg_bp=RealOff(int10_romarea.font_16); + reg_cx=16; + break; + default: + reg_cx=16; + LOG_DEBUG("INT10:11:30 Request for font %2X",reg_bh); + } + reg_dl=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS); + break; + default: + LOG_WARN("INT10:11:Unsupported character generator call %2X",reg_al); + } + break; + case 0x12: /* alternate function select */ + switch (reg_bl) { + case 0x10: /* Get EGA Information */ + { + reg_bh=(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)==0x3B4); + reg_bl=3; //256 kb + reg_cx=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES) & 0x0F; + break; + } + default: + LOG_WARN("Alternate functions select %2X not handled",reg_bl); + } + break; + case 0x13: /* Write String */ + INT10_WriteString(reg_dh,reg_dl,reg_al,reg_bl,real_phys(Segs[es].value,reg_bp),reg_cx,reg_bh); + break; + case 0x1A: /* Display Combination */ + if (reg_al==0) { + reg_bx=real_readb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX); + reg_al=0x1A; + break; + } + if (reg_al==1) { + real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,reg_bl); + reg_al=0x1A; + break; + } + LOG_DEBUG("INT10:1A:Display Combination call %2X",reg_al); + break; + case 0x1B: /* functionality State Information */ + switch (reg_bx) { + case 0x0000: + INT10_GetFuncStateInformation(Segs[es].value,reg_di); + reg_al=0x1B; + break; + default: + LOG_WARN("INT10:1B:Unhandled call BX %2X",reg_bx); + } + break; + case 0xff: + if (!warned_ff) LOG_WARN("INT10:FF:Weird NC call"); + warned_ff=true; + break; + default: + LOG_WARN("Unhandled INT 10 call %2X",reg_ah); + }; + return CBRET_NONE; +} + +static void INT10_Seg40Init(void) { + //This should fill the ega vga structures + // init detected hardware BIOS Area + real_writew(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE,real_readw(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE)&0xFFCF); + // Just for the first int10 find its children + // the default char height + real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,16); + // Clear the screen + real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,0x60); + // Set the basic screen we have + real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9); + // Set the basic modeset options + real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,0x51); + // Set the default MSR + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x09); + + INT10_SetVideoMode(3); +} + + +static void INT10_InitVGA(void) { +/* switch to color mode and enable CPU access 480 lines */ + + IO_Write(0x3c2,0xc3); + + /* More than 64k */ + IO_Write(0x3c4,0x04); + IO_Write(0x3c5,0x02); +}; + +void INT10_StartUp(void) { + + INT10_InitVGA(); + /* Setup the INT 10 vector */ + call_10=CALLBACK_Allocate(); + //TODO ERRORS ERRORS ERRORS + if (call_10==-1) E_Exit("Error can't allocate Video Int 10 CallBack\n"); + CALLBACK_Setup(call_10,&INT10_Handler,CB_IRET); + RealSetVec(0x10,CALLBACK_RealPointer(call_10)); + //Init the 0x40 segment and init the datastructures in the the video rom area + INT10_SetupRomMemory(); + INT10_Seg40Init(); +}; + + diff --git a/src/ints/int10.h b/src/ints/int10.h index e3d5a7b..f7af321 100644 --- a/src/ints/int10.h +++ b/src/ints/int10.h @@ -1,233 +1,205 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: int10.h,v 1.38 2009/04/25 16:25:03 harekiet Exp $ */ - -#include "vga.h" - -#define S3_LFB_BASE 0xC0000000 - -#define BIOSMEM_SEG 0x40 - -#define BIOSMEM_INITIAL_MODE 0x10 -#define BIOSMEM_CURRENT_MODE 0x49 -#define BIOSMEM_NB_COLS 0x4A -#define BIOSMEM_PAGE_SIZE 0x4C -#define BIOSMEM_CURRENT_START 0x4E -#define BIOSMEM_CURSOR_POS 0x50 -#define BIOSMEM_CURSOR_TYPE 0x60 -#define BIOSMEM_CURRENT_PAGE 0x62 -#define BIOSMEM_CRTC_ADDRESS 0x63 -#define BIOSMEM_CURRENT_MSR 0x65 -#define BIOSMEM_CURRENT_PAL 0x66 -#define BIOSMEM_NB_ROWS 0x84 -#define BIOSMEM_CHAR_HEIGHT 0x85 -#define BIOSMEM_VIDEO_CTL 0x87 -#define BIOSMEM_SWITCHES 0x88 -#define BIOSMEM_MODESET_CTL 0x89 -#define BIOSMEM_DCC_INDEX 0x8A -#define BIOSMEM_CRTCPU_PAGE 0x8A -#define BIOSMEM_VS_POINTER 0xA8 - - -/* - * - * VGA registers - * - */ -#define VGAREG_ACTL_ADDRESS 0x3c0 -#define VGAREG_ACTL_WRITE_DATA 0x3c0 -#define VGAREG_ACTL_READ_DATA 0x3c1 - -#define VGAREG_INPUT_STATUS 0x3c2 -#define VGAREG_WRITE_MISC_OUTPUT 0x3c2 -#define VGAREG_VIDEO_ENABLE 0x3c3 -#define VGAREG_SEQU_ADDRESS 0x3c4 -#define VGAREG_SEQU_DATA 0x3c5 - -#define VGAREG_PEL_MASK 0x3c6 -#define VGAREG_DAC_STATE 0x3c7 -#define VGAREG_DAC_READ_ADDRESS 0x3c7 -#define VGAREG_DAC_WRITE_ADDRESS 0x3c8 -#define VGAREG_DAC_DATA 0x3c9 - -#define VGAREG_READ_FEATURE_CTL 0x3ca -#define VGAREG_READ_MISC_OUTPUT 0x3cc - -#define VGAREG_GRDC_ADDRESS 0x3ce -#define VGAREG_GRDC_DATA 0x3cf - -#define VGAREG_MDA_CRTC_ADDRESS 0x3b4 -#define VGAREG_MDA_CRTC_DATA 0x3b5 -#define VGAREG_VGA_CRTC_ADDRESS 0x3d4 -#define VGAREG_VGA_CRTC_DATA 0x3d5 - -#define VGAREG_MDA_WRITE_FEATURE_CTL 0x3ba -#define VGAREG_VGA_WRITE_FEATURE_CTL 0x3da -#define VGAREG_ACTL_RESET 0x3da -#define VGAREG_TDY_RESET 0x3da -#define VGAREG_TDY_ADDRESS 0x3da -#define VGAREG_TDY_DATA 0x3de -#define VGAREG_PCJR_DATA 0x3da - -#define VGAREG_MDA_MODECTL 0x3b8 -#define VGAREG_CGA_MODECTL 0x3d8 -#define VGAREG_CGA_PALETTE 0x3d9 - -/* Video memory */ -#define VGAMEM_GRAPH 0xA000 -#define VGAMEM_CTEXT 0xB800 -#define VGAMEM_MTEXT 0xB000 - -#define BIOS_NCOLS Bit16u ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); -#define BIOS_NROWS Bit16u nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; - -extern Bit8u int10_font_08[256 * 8]; -extern Bit8u int10_font_14[256 * 14]; -extern Bit8u int10_font_16[256 * 16]; - -struct VideoModeBlock { - Bitu mode; - VGAModes type; - Bitu swidth, sheight; - Bitu twidth, theight; - Bitu cwidth, cheight; - Bitu ptotal,pstart,plength; - - Bitu htotal,vtotal; - Bitu hdispend,vdispend; - Bitu special; - -}; -extern VideoModeBlock ModeList_VGA[]; -extern VideoModeBlock * CurMode; - -typedef struct { - struct { - RealPt font_8_first; - RealPt font_8_second; - RealPt font_14; - RealPt font_16; - RealPt font_14_alternate; - RealPt font_16_alternate; - RealPt static_state; - RealPt video_save_pointers; - RealPt video_parameter_table; - RealPt video_save_pointer_table; - RealPt video_dcc_table; - RealPt oemstring; - RealPt vesa_modes; - RealPt pmode_interface; - Bit16u pmode_interface_size; - Bit16u pmode_interface_start; - Bit16u pmode_interface_window; - Bit16u pmode_interface_palette; - Bitu used; - } rom; - Bitu vesa_setmode; - bool vesa_nolfb; - bool vesa_oldvbe; -} Int10Data; - -extern Int10Data int10; - -static Bit8u CURSOR_POS_COL(Bit8u page) { - return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2); -} - -static Bit8u CURSOR_POS_ROW(Bit8u page) { - return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2+1); -} - -bool INT10_SetVideoMode(Bitu mode); - -void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page); - -void INT10_SetActivePage(Bit8u page); -void INT10_GetFuncStateInformation(PhysPt save); - -void INT10_SetCursorShape(Bit8u first,Bit8u last); -void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page); -void INT10_TeletypeOutput(Bit8u chr,Bit8u attr); -void INT10_TeletypeOutputAttr(Bit8u chr,Bit8u attr,bool useattr); -void INT10_ReadCharAttr(Bit16u * result,Bit8u page); -void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr); -void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page); - -/* Graphics Stuff */ -void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color); -void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color); - -/* Font Stuff */ -void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu height); - -/* Palette Group */ -void INT10_SetBackgroundBorder(Bit8u val); -void INT10_SetColorSelect(Bit8u val); -void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val); -void INT10_SetOverscanBorderColor(Bit8u val); -void INT10_SetAllPaletteRegisters(PhysPt data); -void INT10_ToggleBlinkingBit(Bit8u state); -void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val); -void INT10_GetOverscanBorderColor(Bit8u * val); -void INT10_GetAllPaletteRegisters(PhysPt data); -void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue); -void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue); -void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data); -void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data); -void INT10_SelectDACPage(Bit8u function,Bit8u mode); -void INT10_GetDACPage(Bit8u* mode,Bit8u* page); -void INT10_SetPelMask(Bit8u mask); -void INT10_GetPelMask(Bit8u & mask); -void INT10_PerformGrayScaleSumming(Bit16u start_reg,Bit16u count); - - -/* Vesa Group */ -Bit8u VESA_GetSVGAInformation(Bit16u seg,Bit16u off); -Bit8u VESA_GetSVGAModeInformation(Bit16u mode,Bit16u seg,Bit16u off); -Bit8u VESA_SetSVGAMode(Bit16u mode); -Bit8u VESA_GetSVGAMode(Bit16u & mode); -Bit8u VESA_SetCPUWindow(Bit8u window,Bit8u address); -Bit8u VESA_GetCPUWindow(Bit8u window,Bit16u & address); -Bit8u VESA_ScanLineLength(Bit8u subcall, Bit16u val, Bit16u & bytes,Bit16u & pixels,Bit16u & lines); -Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y); -Bit8u VESA_GetDisplayStart(Bit16u & x,Bit16u & y); -Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count); -Bit8u VESA_GetPalette(PhysPt data,Bitu index,Bitu count); - -/* Sub Groups */ -void INT10_SetupRomMemory(void); -void INT10_SetupRomMemoryChecksum(void); -void INT10_SetupVESA(void); - -/* EGA RIL */ -RealPt INT10_EGA_RIL_GetVersionPt(void); -void INT10_EGA_RIL_ReadRegister(Bit8u & bl, Bit16u dx); -void INT10_EGA_RIL_WriteRegister(Bit8u & bl, Bit8u bh, Bit16u dx); -void INT10_EGA_RIL_ReadRegisterRange(Bit8u ch, Bit8u cl, Bit16u dx, PhysPt dst); -void INT10_EGA_RIL_WriteRegisterRange(Bit8u ch, Bit8u cl, Bit16u dx, PhysPt dst); -void INT10_EGA_RIL_ReadRegisterSet(Bit16u cx, PhysPt tbl); -void INT10_EGA_RIL_WriteRegisterSet(Bit16u cx, PhysPt tbl); - -/* Video State */ -Bitu INT10_VideoState_GetSize(Bitu state); -bool INT10_VideoState_Save(Bitu state,RealPt buffer); -bool INT10_VideoState_Restore(Bitu state,RealPt buffer); - -/* Video Parameter Tables */ -Bitu INT10_SetupVideoParameterTable(PhysPt basepos); +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define BIOSMEM_SEG 0x40 + +#define BIOSMEM_INITIAL_MODE 0x10 +#define BIOSMEM_CURRENT_MODE 0x49 +#define BIOSMEM_NB_COLS 0x4A +#define BIOSMEM_PAGE_SIZE 0x4C +#define BIOSMEM_CURRENT_START 0x4E +#define BIOSMEM_CURSOR_POS 0x50 +#define BIOSMEM_CURSOR_TYPE 0x60 +#define BIOSMEM_CURRENT_PAGE 0x62 +#define BIOSMEM_CRTC_ADDRESS 0x63 +#define BIOSMEM_CURRENT_MSR 0x65 +#define BIOSMEM_CURRENT_PAL 0x66 +#define BIOSMEM_NB_ROWS 0x84 +#define BIOSMEM_CHAR_HEIGHT 0x85 +#define BIOSMEM_VIDEO_CTL 0x87 +#define BIOSMEM_SWITCHES 0x88 +#define BIOSMEM_MODESET_CTL 0x89 +#define BIOSMEM_DCC_INDEX 0x8A +#define BIOSMEM_VS_POINTER 0xA8 + + +/* + * + * VGA registers + * + */ +#define VGAREG_ACTL_ADDRESS 0x3c0 +#define VGAREG_ACTL_WRITE_DATA 0x3c0 +#define VGAREG_ACTL_READ_DATA 0x3c1 + +#define VGAREG_INPUT_STATUS 0x3c2 +#define VGAREG_WRITE_MISC_OUTPUT 0x3c2 +#define VGAREG_VIDEO_ENABLE 0x3c3 +#define VGAREG_SEQU_ADDRESS 0x3c4 +#define VGAREG_SEQU_DATA 0x3c5 + +#define VGAREG_PEL_MASK 0x3c6 +#define VGAREG_DAC_STATE 0x3c7 +#define VGAREG_DAC_READ_ADDRESS 0x3c7 +#define VGAREG_DAC_WRITE_ADDRESS 0x3c8 +#define VGAREG_DAC_DATA 0x3c9 + +#define VGAREG_READ_FEATURE_CTL 0x3ca +#define VGAREG_READ_MISC_OUTPUT 0x3cc + +#define VGAREG_GRDC_ADDRESS 0x3ce +#define VGAREG_GRDC_DATA 0x3cf + +#define VGAREG_MDA_CRTC_ADDRESS 0x3b4 +#define VGAREG_MDA_CRTC_DATA 0x3b5 +#define VGAREG_VGA_CRTC_ADDRESS 0x3d4 +#define VGAREG_VGA_CRTC_DATA 0x3d5 + +#define VGAREG_MDA_WRITE_FEATURE_CTL 0x3ba +#define VGAREG_VGA_WRITE_FEATURE_CTL 0x3da +#define VGAREG_ACTL_RESET 0x3da + +#define VGAREG_MDA_MODECTL 0x3b8 +#define VGAREG_CGA_MODECTL 0x3d8 +#define VGAREG_CGA_PALETTE 0x3d9 + +/* Video memory */ +#define VGAMEM_GRAPH 0xA000 +#define VGAMEM_CTEXT 0xB800 +#define VGAMEM_MTEXT 0xB000 + + + +/* + * + * Tables of default values for each mode + * + */ +#define MODE_MAX 0x13 +#define TEXT 0x00 +#define GRAPH 0x01 + +#define CTEXT 0x00 +#define MTEXT 0x01 +#define CGA 0x02 +#define PLANAR1 0x03 +#define PLANAR2 0x04 +#define PLANAR4 0x05 +#define LINEAR8 0x06 + +// for SVGA +#define LINEAR15 0x07 +#define LINEAR16 0x08 +#define LINEAR24 0x09 +#define LINEAR32 0x0 + + +#define SCREEN_SIZE(x,y) (((x*y*2)|0x00ff)+1) +#define SCREEN_MEM_START(x,y,p) ((((x*y*2)|0x00ff)+1)*p) +#define SCREEN_IO_START(x,y,p) ((((x*y)|0x00ff)+1)*p) + + +extern Bit8u int10_font_08[256 * 8]; +extern Bit8u int10_font_14[256 * 14]; +extern Bit8u int10_font_16[256 * 16]; + + + +typedef struct +{Bit8u svgamode; + Bit16u vesamode; + Bit8u type; /* TEXT, GRAPH */ + Bit8u memmodel; /* CTEXT,MTEXT,CGA,PL1,PL2,PL4,P8,P15,P16,P24,P32 */ + Bit8u nbpages; + Bit8u pixbits; + Bit16u swidth, sheight; + Bit16u twidth, theight; + Bit16u cwidth, cheight; + Bit16u sstart; + Bit16u slength; + Bit8u miscreg; + Bit8u pelmask; + Bit8u crtcmodel; + Bit8u actlmodel; + Bit8u grdcmodel; + Bit8u sequmodel; + Bit8u dacmodel; /* 0 1 2 3 */ +} VGAMODES; + +extern VGAMODES vga_modes[MODE_MAX+1]; + + +typedef struct { + RealPt font_8_first; + RealPt font_8_second; + RealPt font_14; + RealPt font_16; + RealPt static_state; +} VGAROMAREA; +extern VGAROMAREA int10_romarea; + +#define BIOS_NCOLS Bit16u ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); +#define BIOS_NROWS Bit16u nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; + +inline Bit8u CURSOR_POS_COL(Bit8u page) { + return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2); +} + +inline Bit8u CURSOR_POS_ROW(Bit8u page) { + return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2+1); +} + + +void INT10_SetVideoMode(Bit8u mode); + +void INT10_ScrollUpWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8u nlines,Bit8u attr,Bit8u page); +void INT10_ScrollDownWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8u nlines,Bit8u attr,Bit8u page); + + +void INT10_SetActivePage(Bit8u page); +void INT10_GetFuncStateInformation(Bit16u seg,Bit16u off); + + +void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page); +void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page); +void INT10_ReadCharAttr(Bit16u * result,Bit8u page); +void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr); +void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysOff string,Bit16u count,Bit8u page); + +/* Graphics Stuff */ +void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color); +void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color); +VGAMODES * GetCurrentMode(void); + +/* Palette Group */ +void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val); +void INT10_SetOverscanBorderColor(Bit8u val); +void INT10_SetAllPaletteRegisters(PhysOff data); +void INT10_ToggleBlinkingBit(Bit8u state); +void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val); +void INT10_GetOverscanBorderColor(Bit8u * val); +void INT10_GetAllPaletteRegisters(PhysOff data); +void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue); +void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue); +void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysOff data); +void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysOff data); + + +/* Sup Groups */ +void INT10_SetupRomMemory(void); + diff --git a/src/ints/int10_char.cpp b/src/ints/int10_char.cpp index 58e69f8..6c90fcb 100644 --- a/src/ints/int10_char.cpp +++ b/src/ints/int10_char.cpp @@ -1,628 +1,394 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: int10_char.cpp,v 1.57 2009/04/25 16:25:03 harekiet Exp $ */ - -/* Character displaying moving functions */ - -#include "dosbox.h" -#include "bios.h" -#include "mem.h" -#include "inout.h" -#include "int10.h" - -static void CGA2_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) { - Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); - PhysPt dest=base+((CurMode->twidth*rnew)*(cheight/2)+cleft); - PhysPt src=base+((CurMode->twidth*rold)*(cheight/2)+cleft); - Bitu copy=(cright-cleft); - Bitu nextline=CurMode->twidth; - for (Bitu i=0;itwidth*rnew)*(cheight/2)+cleft)*2; - PhysPt src=base+((CurMode->twidth*rold)*(cheight/2)+cleft)*2; - Bitu copy=(cright-cleft)*2;Bitu nextline=CurMode->twidth*2; - for (Bitu i=0;itwidth*rnew)*(cheight/4)+cleft)*4; - PhysPt src=base+((CurMode->twidth*rold)*(cheight/4)+cleft)*4; - Bitu copy=(cright-cleft)*4;Bitu nextline=CurMode->twidth*4; - for (Bitu i=0;itwidth*rnew)*cheight+cleft; - src=base+(CurMode->twidth*rold)*cheight+cleft; - Bitu nextline=CurMode->twidth; - /* Setup registers correctly */ - IO_Write(0x3ce,5);IO_Write(0x3cf,1); /* Memory transfer mode */ - IO_Write(0x3c4,2);IO_Write(0x3c5,0xf); /* Enable all Write planes */ - /* Do some copying */ - Bitu rowsize=(cright-cleft); - copy=cheight; - for (;copy>0;copy--) { - for (Bitu x=0;xtwidth*rnew)*cheight+cleft); - src=base+8*((CurMode->twidth*rold)*cheight+cleft); - Bitu nextline=8*CurMode->twidth; - Bitu rowsize=8*(cright-cleft); - copy=cheight; - for (;copy>0;copy--) { - for (Bitu x=0;xtwidth+cleft)*2; - dest=base+(rnew*CurMode->twidth+cleft)*2; - MEM_BlockCopy(dest,src,(cright-cleft)*2); -} - -static void CGA2_FillRow(Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) { - Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); - PhysPt dest=base+((CurMode->twidth*row)*(cheight/2)+cleft); - Bitu copy=(cright-cleft); - Bitu nextline=CurMode->twidth; - attr=(attr & 0x3) | ((attr & 0x3) << 2) | ((attr & 0x3) << 4) | ((attr & 0x3) << 6); - for (Bitu i=0;itwidth*row)*(cheight/2)+cleft)*2; - Bitu copy=(cright-cleft)*2;Bitu nextline=CurMode->twidth*2; - attr=(attr & 0x3) | ((attr & 0x3) << 2) | ((attr & 0x3) << 4) | ((attr & 0x3) << 6); - for (Bitu i=0;itwidth*row)*(cheight/4)+cleft)*4; - Bitu copy=(cright-cleft)*4;Bitu nextline=CurMode->twidth*4; - attr=(attr & 0xf) | (attr & 0xf) << 4; - for (Bitu i=0;itwidth*row)*cheight+cleft; - Bitu nextline=CurMode->twidth; - Bitu copy = cheight;Bitu rowsize=(cright-cleft); - for (;copy>0;copy--) { - for (Bitu x=0;xtwidth*row)*cheight+cleft); - Bitu nextline=8*CurMode->twidth; - Bitu copy = cheight;Bitu rowsize=8*(cright-cleft); - for (;copy>0;copy--) { - for (Bitu x=0;xtwidth+cleft)*2; - Bit16u fill=(attr<<8)+' '; - for (Bit8u x=0;x<(cright-cleft);x++) { - mem_writew(dest,fill); - dest+=2; - } -} - - -void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page) { -/* Do some range checking */ - if (CurMode->type!=M_TEXT) page=0xff; - BIOS_NCOLS;BIOS_NROWS; - if(rul>rlr) return; - if(cul>clr) return; - if(rlr>=nrows) rlr=(Bit8u)nrows-1; - if(clr>=ncols) clr=(Bit8u)ncols-1; - clr++; - - /* Get the correct page */ - if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); - PhysPt base=CurMode->pstart+page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); - - /* See how much lines need to be copied */ - Bit8u start,end;Bits next; - /* Copy some lines */ - if (nlines>0) { - start=rlr-nlines+1; - end=rul; - next=-1; - } else if (nlines<0) { - start=rul-nlines-1; - end=rlr; - next=1; - } else { - nlines=rlr-rul+1; - goto filling; - } - while (start!=end) { - start+=next; - switch (CurMode->type) { - case M_TEXT: - TEXT_CopyRow(cul,clr,start,start+nlines,base);break; - case M_CGA2: - CGA2_CopyRow(cul,clr,start,start+nlines,base);break; - case M_CGA4: - CGA4_CopyRow(cul,clr,start,start+nlines,base);break; - case M_TANDY16: - TANDY16_CopyRow(cul,clr,start,start+nlines,base);break; - case M_EGA: - EGA16_CopyRow(cul,clr,start,start+nlines,base);break; - case M_VGA: - VGA_CopyRow(cul,clr,start,start+nlines,base);break; - default: - LOG(LOG_INT10,LOG_ERROR)("Unhandled mode %d for scroll",CurMode->type); - } - } - /* Fill some lines */ -filling: - if (nlines>0) { - start=rul; - } else { - nlines=-nlines; - start=rlr-nlines+1; - } - for (;nlines>0;nlines--) { - switch (CurMode->type) { - case M_TEXT: - TEXT_FillRow(cul,clr,start,base,attr);break; - case M_CGA2: - CGA2_FillRow(cul,clr,start,base,attr);break; - case M_CGA4: - CGA4_FillRow(cul,clr,start,base,attr);break; - case M_TANDY16: - TANDY16_FillRow(cul,clr,start,base,attr);break; - case M_EGA: - EGA16_FillRow(cul,clr,start,base,attr);break; - case M_VGA: - VGA_FillRow(cul,clr,start,base,attr);break; - default: - LOG(LOG_INT10,LOG_ERROR)("Unhandled mode %d for scroll",CurMode->type); - } - start++; - } -} - -void INT10_SetActivePage(Bit8u page) { - Bit16u mem_address; - - if (page>7) LOG(LOG_INT10,LOG_ERROR)("INT10_SetActivePage page %d",page); - mem_address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); - /* Write the new page start */ - real_writew(BIOSMEM_SEG,BIOSMEM_CURRENT_START,mem_address); - if (IS_EGAVGA_ARCH && CurMode->mode<0x8) mem_address>>=1; - /* Write the new start address in vgahardware */ - Bit16u base=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); - IO_Write(base,0x0c); - IO_Write(base+1,(Bit8u)(mem_address>>8)); - IO_Write(base,0x0d); - IO_Write(base+1,(Bit8u)mem_address); - - // And change the BIOS page - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page); - Bit8u cur_row=CURSOR_POS_ROW(page); - Bit8u cur_col=CURSOR_POS_COL(page); - // Display the cursor, now the page is active - INT10_SetCursorPos(cur_row,cur_col,page); -} - -void INT10_SetCursorShape(Bit8u first,Bit8u last) { - real_writew(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,last|(first<<8)); - if (machine==MCH_CGA) goto dowrite; - if (IS_TANDY_ARCH) goto dowrite; - /* Skip CGA cursor emulation if EGA/VGA system is active */ - if (!(real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & 0x8)) { - /* Check for CGA type 01, invisible */ - if ((first & 0x60) == 0x20) { - first=0x1e; - last=0x00; - goto dowrite; - } - /* Check if we need to convert CGA Bios cursor values */ - if (!(real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & 0x1)) { // set by int10 fun12 sub34 -// if (CurMode->mode>0x3) goto dowrite; //Only mode 0-3 are text modes on cga - if ((first & 0xe0) || (last & 0xe0)) goto dowrite; - Bit8u cheight=real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)-1; - /* Creative routine i based of the original ibmvga bios */ - - if (last=cheight) || !(last==(cheight-1)) || !(first==cheight) ) { - if (last<=3) goto dowrite; - if (first+22) { - first=(cheight+1)/2; - last=cheight; - } else { - last=cheight; - } - } else { - first=(first-last)+cheight; - last=cheight; - - if (cheight>0xc) { // vgatest sets 15 15 2x where only one should be decremented to 14 14 - first--; // implementing int10 fun12 sub34 fixed this. - last--; - } - } - } - - } - } -dowrite: - Bit16u base=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); - IO_Write(base,0xa);IO_Write(base+1,first); - IO_Write(base,0xb);IO_Write(base+1,last); -} - -void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page) { - Bit16u address; - - if (page>7) LOG(LOG_INT10,LOG_ERROR)("INT10_SetCursorPos page %d",page); - // Bios cursor pos - real_writeb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2,col); - real_writeb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2+1,row); - // Set the hardware cursor - Bit8u current=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); - if(page==current) { - // Get the dimensions - BIOS_NCOLS; - // Calculate the address knowing nbcols nbrows and page num - // NOTE: BIOSMEM_CURRENT_START counts in colour/flag pairs - address=(ncols*row)+col+real_readw(BIOSMEM_SEG,BIOSMEM_CURRENT_START)/2; - // CRTC regs 0x0e and 0x0f - Bit16u base=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); - IO_Write(base,0x0e); - IO_Write(base+1,(Bit8u)(address>>8)); - IO_Write(base,0x0f); - IO_Write(base+1,(Bit8u)address); - } -} - -void ReadCharAttr(Bit16u col,Bit16u row,Bit8u page,Bit16u * result) { - /* Externally used by the mouse routine */ - PhysPt fontdata; - Bitu x,y; - Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); - bool split_chr = false; - switch (CurMode->type) { - case M_TEXT: - { - // Compute the address - Bit16u address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); - address+=(row*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)+col)*2; - // read the char - PhysPt where = CurMode->pstart+address; - *result=mem_readw(where); - } - return; - case M_CGA4: - case M_CGA2: - case M_TANDY16: - split_chr = true; - /* Fallthrough */ - default: /* EGA/VGA don't have a split font-table */ - for(Bit16u chr=0;chr <= 255 ;chr++) { - if (!split_chr || (chr<128)) fontdata = Real2Phys(RealGetVec(0x43))+chr*cheight; - else fontdata = Real2Phys(RealGetVec(0x1F))+(chr-128)*cheight; - - x=8*col; - y=cheight*row; - bool error=false; - for (Bit8u h=0;h>=1; - } - y++; - if(bitline != vidline){ - /* It's not character 'chr', move on to the next */ - error = true; - break; - } - } - if(!error){ - /* We found it */ - *result = chr; - return; - } - } - LOG(LOG_INT10,LOG_ERROR)("ReadChar didn't find character"); - *result = 0; - break; - } -} -void INT10_ReadCharAttr(Bit16u * result,Bit8u page) { - if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); - Bit8u cur_row=CURSOR_POS_ROW(page); - Bit8u cur_col=CURSOR_POS_COL(page); - ReadCharAttr(cur_col,cur_row,page,result); -} -void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool useattr) { - /* Externally used by the mouse routine */ - RealPt fontdata; - Bitu x,y; - Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); - switch (CurMode->type) { - case M_TEXT: - { - // Compute the address - Bit16u address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); - address+=(row*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)+col)*2; - // Write the char - PhysPt where = CurMode->pstart+address; - mem_writeb(where,chr); - if (useattr) { - mem_writeb(where+1,attr); - } - } - return; - case M_CGA4: - case M_CGA2: - case M_TANDY16: - if (chr<128) - fontdata=RealGetVec(0x43); - else { - chr-=128; - fontdata=RealGetVec(0x1f); - } - fontdata=RealMake(RealSeg(fontdata), RealOff(fontdata) + chr*cheight); - break; - default: - fontdata=RealGetVec(0x43); - fontdata=RealMake(RealSeg(fontdata), RealOff(fontdata) + chr*cheight); - break; - } - - if(GCC_UNLIKELY(!useattr)) { //Set attribute(color) to a sensible value - static bool warned_use = false; - if(GCC_UNLIKELY(!warned_use)){ - LOG(LOG_INT10,LOG_ERROR)("writechar used without attribute in non-textmode %c %X",chr,chr); - warned_use = true; - } - switch(CurMode->type) { - case M_CGA4: - attr = 0x3; - break; - case M_CGA2: - attr = 0x1; - break; - case M_TANDY16: - case M_EGA: - default: - attr = 0xf; - break; - } - } - - //Some weird behavior of mode 6 (and 11) - if ((CurMode->mode == 0x6)/* || (CurMode->mode==0x11)*/) attr = (attr&0x80)|1; - //(same fix for 11 fixes vgatest2, but it's not entirely correct according to wd) - - x=8*col; - y=cheight*row;Bit8u xor_mask=(CurMode->type == M_VGA) ? 0x0 : 0x80; - //TODO Check for out of bounds - if (CurMode->type==M_EGA) { - /* enable all planes for EGA modes (Ultima 1 colour bug) */ - /* might be put into INT10_PutPixel but different vga bios - implementations have different opinions about this */ - IO_Write(0x3c4,0x2);IO_Write(0x3c5,0xf); - } - for (Bit8u h=0;h>=1; - } - y++; - } -} - -void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) { - if (CurMode->type!=M_TEXT) { - showattr=true; //Use attr in graphics mode always - switch (machine) { - case EGAVGA_ARCH_CASE: - page%=CurMode->ptotal; - break; - case MCH_CGA: - case MCH_PCJR: - page=0; - break; - } - } - - Bit8u cur_row=CURSOR_POS_ROW(page); - Bit8u cur_col=CURSOR_POS_COL(page); - BIOS_NCOLS; - while (count>0) { - WriteChar(cur_col,cur_row,page,chr,attr,showattr); - count--; - cur_col++; - if(cur_col==ncols) { - cur_col=0; - cur_row++; - } - } -} - -static void INT10_TeletypeOutputAttr(Bit8u chr,Bit8u attr,bool useattr,Bit8u page) { - BIOS_NCOLS;BIOS_NROWS; - Bit8u cur_row=CURSOR_POS_ROW(page); - Bit8u cur_col=CURSOR_POS_COL(page); - switch (chr) { - case 7: - //TODO BEEP - break; - case 8: - if(cur_col>0) cur_col--; - break; - case '\r': - cur_col=0; - break; - case '\n': -// cur_col=0; //Seems to break an old chess game - cur_row++; - break; - case '\t': - do { - INT10_TeletypeOutputAttr(' ',attr,useattr,page); - cur_row=CURSOR_POS_ROW(page); - cur_col=CURSOR_POS_COL(page); - } while(cur_col%8); - break; - default: - /* Draw the actual Character */ - WriteChar(cur_col,cur_row,page,chr,attr,useattr); - cur_col++; - } - if(cur_col==ncols) { - cur_col=0; - cur_row++; - } - // Do we need to scroll ? - if(cur_row==nrows) { - //Fill with black on non-text modes and with 0x7 on textmode - Bit8u fill = (CurMode->type == M_TEXT)?0x7:0; - INT10_ScrollWindow(0,0,nrows-1,ncols-1,-1,fill,page); - cur_row--; - } - // Set the cursor for the page - INT10_SetCursorPos(cur_row,cur_col,page); -} - -void INT10_TeletypeOutputAttr(Bit8u chr,Bit8u attr,bool useattr) { - INT10_TeletypeOutputAttr(chr,attr,useattr,real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); -} - -void INT10_TeletypeOutput(Bit8u chr,Bit8u attr) { - INT10_TeletypeOutputAttr(chr,attr,CurMode->type!=M_TEXT); -} - -void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page) { - Bit8u cur_row=CURSOR_POS_ROW(page); - Bit8u cur_col=CURSOR_POS_COL(page); - - // if row=0xff special case : use current cursor position - if (row==0xff) { - row=cur_row; - col=cur_col; - } - INT10_SetCursorPos(row,col,page); - while (count>0) { - Bit8u chr=mem_readb(string); - string++; - if (flag&2) { - attr=mem_readb(string); - string++; - }; - INT10_TeletypeOutputAttr(chr,attr,true,page); - count--; - } - if (!(flag&1)) { - INT10_SetCursorPos(cur_row,cur_col,page); - } -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +/* Character displaying moving functions */ + +#include "dosbox.h" +#include "bios.h" +#include "mem.h" +#include "inout.h" +#include "int10.h" + + +void INT10_ScrollDownWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8u nlines,Bit8u attr,Bit8u page) { + +// Bit8u mode; + Bit16u fill=( (attr << 8) | ' '); + BIOS_NCOLS;BIOS_NROWS; + + if(rul>rlr) return; + if(cul>clr) return; + if(rlr>=nrows) rlr=(Bit8u)nrows-1; + if(clr>=ncols) clr=(Bit8u)ncols-1; + + // Get the current page + if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + + /* Get this from active video mode */ + Bit16u textseg=0xb800; + PhysOff start=real_phys(textseg,ncols*nrows*2*page); + + Bit32u dcol=clr-cul+1; + Bit32u drow=rlr-rul+1; + + Bit32u tocopy; + PhysOff dest=start+((rlr*ncols)+cul)*2; + PhysOff src = 0;/* for gcc */ + if (nlines==0) { + nlines=(Bit8u)nrows; + } + if (nlines>=drow) { + tocopy=0; + } else { + tocopy=drow-nlines; + src=start+(((rul+tocopy-1)*ncols)+cul)*2; + } + + for (Bit32u y=0;ynrows) rlr=(Bit8u)nrows; + if(clr>ncols) clr=(Bit8u)ncols; + + if(rul>rlr) return; + if(cul>clr) return; + + VGAMODES * curmode=GetCurrentMode(); + switch (curmode->memmodel) { + case CGA: + { + if (nlines==0) { + /* Clear Screen that we can */ + PhysOff dest=real_phys(0xb800,0); + for (Bit32u tel=0;tel<0x4000;tel++) { + mem_writew(dest,0x0000); + dest+=2; + } + return; + } + LOG_WARN("INT10:Scroll in CGA Mode"); + } + case MTEXT: + case CTEXT: + break; + default: + LOG_ERROR("INT10:Scroll on non supported graphics mode"); + } + + // Get the current page + if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + + /* Get this from active video mode */ + Bit16u textseg=0xb800; + PhysOff start=real_phys(textseg,ncols*nrows*2*page); + + Bit32u dcol=clr-cul+1; + Bit32u drow=rlr-rul+1; + + Bit32u tocopy; + PhysOff dest=start+((rul*ncols)+cul)*2; + PhysOff src; + if (nlines==0) { + nlines=(Bit8u)nrows; + } + + if (nlines>=drow) { + tocopy=0; + } else { + tocopy=drow-nlines; + src=start+(((rul+nlines)*ncols)+cul)*2; + } + for (Bit32u y=0;y7) return; + switch (curmode->memmodel) { + case MTEXT: + case CTEXT:{ + BIOS_NCOLS;BIOS_NROWS; + cur_col=CURSOR_POS_COL(page); + cur_row=CURSOR_POS_ROW(page); + vid_address=SCREEN_IO_START(ncols,nrows,page); + mem_address=SCREEN_MEM_START(ncols,nrows,page); + break; + } + case CGA:{ + vid_address=0; + mem_address=0; + break; + } + case PLANAR4:{ + mem_address=0; + vid_address=((((curmode->sheight*curmode->swidth)>>3)|0xff)+1)*page; + + break; + } + default: + vid_address=0; + mem_address=0; + break; + } + // Calculate the address knowing nbcols nbrows and page num + real_writew(BIOSMEM_SEG,BIOSMEM_CURRENT_START,mem_address); + + // CRTC regs 0x0c and 0x0d + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0c); + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(vid_address&0xff00)>>8); + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0d); + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,vid_address&0x00ff); + + // And change the BIOS page + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page); + + // Display the cursor, now the page is active + INT10_SetCursorPos(cur_row,cur_col,page); +} + + +void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page) { + Bit16u address; + + if(page>7) return; + // Bios cursor pos + real_writeb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2,col); + real_writeb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2+1,row); + // Set the hardware cursor + Bit8u current=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + if(page==current) { + // Get the dimensions + BIOS_NCOLS;BIOS_NROWS; + // Calculate the address knowing nbcols nbrows and page num + address=SCREEN_IO_START(ncols,nrows,page)+col+row*ncols; + // CRTC regs 0x0e and 0x0f + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0e); + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(address&0xff00)>>8); + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0f); + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,address&0x00ff); + } +} + + +void INT10_ReadCharAttr(Bit16u * result,Bit8u page) { + + if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + BIOS_NCOLS;BIOS_NROWS; + Bit8u cur_row=CURSOR_POS_ROW(page); + Bit8u cur_col=CURSOR_POS_COL(page); + + Bit16u address=SCREEN_MEM_START(ncols,nrows,page)+(cur_col+cur_row*ncols)*2; + *result=real_readw(0xb800,address); +} + + + +INLINE static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool useattr) { + VGAMODES * curmode=GetCurrentMode(); + switch (curmode->type) { + case TEXT: + { + // Compute the address + Bit16u address=SCREEN_MEM_START(curmode->twidth,curmode->theight,page)+(col+row*curmode->twidth)*2; + // Write the char + real_writeb(0xb800,address,chr); + if (useattr) { + real_writeb(0xb800,address+1,attr); + } + } + break; + case GRAPH: + { + /* Split this up for certain graphics modes, since in PLANAR4 especially this is sooo slow */ + /* Amount of lines */ + Bit8u * fontdata; + Bit16u x,y; + switch (curmode->cheight) { + case 8: +// fontdata=&int10_font_08[chr*8]; + fontdata=Real2Host(RealGetVec(0x43))+chr*8; + break; + case 14: + fontdata=&int10_font_14[chr*14]; + break; + case 16: + fontdata=&int10_font_16[chr*16]; + break; + default: + LOG_ERROR("INT10:Teletype Illegal Font Height"); + return; + } + x=8*col; + y=curmode->cheight*row; + //TODO Check for out of bounds + for (Bit8u h=0;hcheight;h++) { + Bit8u bitsel=128; + Bit8u bitline=*fontdata++; + Bit16u tx=x; + while (bitsel) { + if (bitline&bitsel) INT10_PutPixel(tx,y,page,attr); + else INT10_PutPixel(tx,y,page,0); + tx++; + bitsel>>=1; + } + y++; + } + } + break; + } +} + + + + +void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) { + if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + Bit8u cur_row=CURSOR_POS_ROW(page); + Bit8u cur_col=CURSOR_POS_COL(page); + while (count>0) { + WriteChar(cur_col,cur_row,page,chr,attr,showattr); + count--; + } +} + + +void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page) { + if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + BIOS_NCOLS;BIOS_NROWS; + Bit8u cur_row=CURSOR_POS_ROW(page); + Bit8u cur_col=CURSOR_POS_COL(page); + + switch (chr) { + case 7: + //TODO BEEP + break; + case 8: + if(cur_col>0) cur_col--; + break; + case '\r': + cur_col=0; + break; + case '\n': + cur_col=0; + cur_row++; + break; + case '\t': + do { + INT10_TeletypeOutput(' ',attr,showattr,page); + cur_row=CURSOR_POS_ROW(page); + cur_col=CURSOR_POS_COL(page); + } while(cur_col%8==0); + break; + default: + /* Draw the actual Character */ + WriteChar(cur_col,cur_row,page,chr,attr,showattr); + cur_col++; + } + if(cur_col==ncols) { + cur_col=0; + cur_row++; + } + // Do we need to scroll ? + if(cur_row==nrows) { + INT10_ScrollUpWindow(0,0,nrows-1,ncols-1,1,0x07,page); + cur_row--; + } + // Set the cursor for the page + INT10_SetCursorPos(cur_row,cur_col,page); +} + +void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysOff string,Bit16u count,Bit8u page) { + + if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); + BIOS_NCOLS;BIOS_NROWS; + Bit8u cur_row=CURSOR_POS_ROW(page); + Bit8u cur_col=CURSOR_POS_COL(page); + + // if row=0xff special case : use current cursor position + if (row==0xff) { + row=cur_row; + col=cur_col; + } + + INT10_SetCursorPos(row,col,page); + while (count>0) { + Bit8u chr=mem_readb(string); + string++; + if (flag&2) { + attr=mem_readb(string); + string++; + } + INT10_TeletypeOutput(chr,attr,true,page); + count--; + } + if (flag & 1) { + INT10_SetCursorPos(cur_row,cur_col,page); + } +} + diff --git a/src/ints/int10_memory.cpp b/src/ints/int10_memory.cpp index f3dab5e..252dfd3 100644 --- a/src/ints/int10_memory.cpp +++ b/src/ints/int10_memory.cpp @@ -1,1448 +1,1302 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: int10_memory.cpp,v 1.27 2008/08/09 15:37:15 c2woody Exp $ */ - -#include "dosbox.h" -#include "mem.h" -#include "inout.h" -#include "int10.h" - - -static Bit8u static_functionality[0x10]= -{ - /* 0 */ 0xff, // All modes supported #1 - /* 1 */ 0xff, // All modes supported #2 - /* 2 */ 0x0f, // All modes supported #3 - /* 3 */ 0x00, 0x00, 0x00, 0x00, // reserved - /* 7 */ 0x07, // 200, 350, 400 scan lines - /* 8 */ 0x04, // total number of character blocks available in text modes - /* 9 */ 0x02, // maximum number of active character blocks in text modes - /* a */ 0xff, // Misc Flags Everthing supported - /* b */ 0x0e, // Support for Display combination, intensity/blinking and video state saving/restoring - /* c */ 0x00, // reserved - /* d */ 0x00, // reserved - /* e */ 0x00, // Change to add new functions - /* f */ 0x00 // reserved -}; - -static Bit16u map_offset[8]={ - 0x0000,0x4000,0x8000,0xc000, - 0x2000,0x6000,0xa000,0xe000 -}; - -void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu height) { - PhysPt ftwhere=PhysMake(0xa000,map_offset[map & 0x7]+offset*32); - IO_Write(0x3c4,0x2);IO_Write(0x3c5,0x4); //Enable plane 2 - IO_Write(0x3ce,0x6);Bitu old_6=IO_Read(0x3cf); - IO_Write(0x3cf,0x0); //Disable odd/even and a0000 adressing - for (Bitu i=0;isheight/height)-1); - real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,height); - //TODO Reprogram cursor size? - } -} - - -void INT10_SetupRomMemory(void) { -/* This should fill up certain structures inside the Video Bios Rom Area */ - PhysPt rom_base=PhysMake(0xc000,0); - Bitu i; - int10.rom.used=3; - if (IS_EGAVGA_ARCH) { - // set up the start of the ROM - phys_writew(rom_base+0,0xaa55); - phys_writeb(rom_base+2,0x40); // Size of ROM: 64 512-blocks = 32KB - if (IS_VGA_ARCH) { - phys_writeb(rom_base+0x1e,0x49); // IBM string - phys_writeb(rom_base+0x1f,0x42); - phys_writeb(rom_base+0x20,0x4d); - phys_writeb(rom_base+0x21,0x00); - } - int10.rom.used=0x100; - } - int10.rom.font_8_first=RealMake(0xC000,int10.rom.used); - for (i=0;i<128*8;i++) { - phys_writeb(rom_base+int10.rom.used++,int10_font_08[i]); - } - int10.rom.font_8_second=RealMake(0xC000,int10.rom.used); - for (i=0;i<128*8;i++) { - phys_writeb(rom_base+int10.rom.used++,int10_font_08[i+128*8]); - } - int10.rom.font_14=RealMake(0xC000,int10.rom.used); - for (i=0;i<256*14;i++) { - phys_writeb(rom_base+int10.rom.used++,int10_font_14[i]); - } - int10.rom.font_16=RealMake(0xC000,int10.rom.used); - for (i=0;i<256*16;i++) { - phys_writeb(rom_base+int10.rom.used++,int10_font_16[i]); - } - int10.rom.static_state=RealMake(0xC000,int10.rom.used); - for (i=0;i<0x10;i++) { - phys_writeb(rom_base+int10.rom.used++,static_functionality[i]); - } - for (i=0;i<128*8;i++) { - phys_writeb(PhysMake(0xf000,0xfa6e)+i,int10_font_08[i]); - } - RealSetVec(0x1F,int10.rom.font_8_second); - int10.rom.font_14_alternate=RealMake(0xC000,int10.rom.used); - int10.rom.font_16_alternate=RealMake(0xC000,int10.rom.used); - phys_writeb(rom_base+int10.rom.used++,0x00); // end of table (empty) - - if (IS_EGAVGA_ARCH) { - int10.rom.video_parameter_table=RealMake(0xC000,int10.rom.used); - int10.rom.used+=INT10_SetupVideoParameterTable(rom_base+int10.rom.used); - - if (IS_VGA_ARCH) { - int10.rom.video_dcc_table=RealMake(0xC000,int10.rom.used); - phys_writeb(rom_base+int10.rom.used++,0x10); // number of entries - phys_writeb(rom_base+int10.rom.used++,1); // version number - phys_writeb(rom_base+int10.rom.used++,8); // maximal display code - phys_writeb(rom_base+int10.rom.used++,0); // reserved - // display combination codes - phys_writew(rom_base+int10.rom.used,0x0000); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0100); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0200); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0102); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0400); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0104); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0500); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0502); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0600); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0601); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0605); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0800); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0801); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0700); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0702); int10.rom.used+=2; - phys_writew(rom_base+int10.rom.used,0x0706); int10.rom.used+=2; - - int10.rom.video_save_pointer_table=RealMake(0xC000,int10.rom.used); - phys_writew(rom_base+int10.rom.used,0x1a); // length of table - int10.rom.used+=2; - phys_writed(rom_base+int10.rom.used,int10.rom.video_dcc_table); - int10.rom.used+=4; - phys_writed(rom_base+int10.rom.used,0); // alphanumeric charset override - int10.rom.used+=4; - phys_writed(rom_base+int10.rom.used,0); // user palette table - int10.rom.used+=4; - phys_writed(rom_base+int10.rom.used,0); int10.rom.used+=4; - phys_writed(rom_base+int10.rom.used,0); int10.rom.used+=4; - phys_writed(rom_base+int10.rom.used,0); int10.rom.used+=4; - } - - int10.rom.video_save_pointers=RealMake(0xC000,int10.rom.used); - phys_writed(rom_base+int10.rom.used,int10.rom.video_parameter_table); - int10.rom.used+=4; - phys_writed(rom_base+int10.rom.used,0); // dynamic save area pointer - int10.rom.used+=4; - phys_writed(rom_base+int10.rom.used,0); // alphanumeric character set override - int10.rom.used+=4; - phys_writed(rom_base+int10.rom.used,0); // graphics character set override - int10.rom.used+=4; - if (IS_VGA_ARCH) { - phys_writed(rom_base+int10.rom.used,int10.rom.video_save_pointer_table); - } else { - phys_writed(rom_base+int10.rom.used,0); // secondary save pointer table - } - int10.rom.used+=4; - phys_writed(rom_base+int10.rom.used,0); int10.rom.used+=4; - phys_writed(rom_base+int10.rom.used,0); int10.rom.used+=4; - } - - if (IS_TANDY_ARCH) { - RealSetVec(0x44,int10.rom.font_8_first); - } -} - -void INT10_ReloadRomFonts(void) { - // 16x8 font - PhysPt font16pt=Real2Phys(int10.rom.font_16); - for (Bitu i=0;i<256*16;i++) { - phys_writeb(font16pt+i,int10_font_16[i]); - } - // 14x8 font - PhysPt font14pt=Real2Phys(int10.rom.font_14); - for (Bitu i=0;i<256*14;i++) { - phys_writeb(font14pt+i,int10_font_14[i]); - } - // 8x8 fonts - PhysPt font8pt=Real2Phys(int10.rom.font_8_first); - for (Bitu i=0;i<128*8;i++) { - phys_writeb(font8pt+i,int10_font_08[i]); - } - font8pt=Real2Phys(int10.rom.font_8_second); - for (Bitu i=0;i<128*8;i++) { - phys_writeb(font8pt+i,int10_font_08[i+128*8]); - } -} - -void INT10_SetupRomMemoryChecksum(void) { - if (IS_EGAVGA_ARCH) { //EGA/VGA. Just to be safe - /* Sum of all bytes in rom module 256 should be 0 */ - Bit8u sum = 0; - PhysPt rom_base = PhysMake(0xc000,0); - Bitu last_rombyte = 32*1024 - 1; //32 KB romsize - for (Bitu i = 0;i < last_rombyte;i++) - sum += phys_readb(rom_base + i); //OVERFLOW IS OKAY - sum = 256 - sum; - phys_writeb(rom_base + last_rombyte,sum); - } -} - - -Bit8u int10_font_08[256 * 8] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, - 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, - 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, - 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, - 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, - 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, - 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, - 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, - 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, - 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, - 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, - 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, - 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, - 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, - 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, - 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, - 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, - 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, - 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, - 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, - 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, - 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, - 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, - 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, - 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, - 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, - 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00, - 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, - 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, - 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, - 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, - 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, - 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, - 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, - 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, - 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, - 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, - 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, - 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, - 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, - 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, - 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, - 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, - 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, - 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, - 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, - 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, - 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, - 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, - 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, - 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, - 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, - 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, - 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, - 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, - 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, - 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, - 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, - 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, - 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, - 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, - 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, - 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, - 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, - 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, - 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, - 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, - 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, - 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, - 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, - 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, - 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, - 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, - 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, - 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, - 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, - 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, - 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, - 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, - 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, - 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, - 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, - 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, - 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, - 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, - 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, - 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, - 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, - 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, - 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, - 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, - 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, - 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, - 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, - 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, - 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, - 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, - 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, - 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, - 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, - 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, - 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, - 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, - 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, - 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, - 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, - 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, - 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, - 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, - 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, - 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00, - 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00, - 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, - 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, - 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, - 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f, - 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03, - 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, - 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, - 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, - 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, - 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, - 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, - 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, - 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, - 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, - 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, - 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, - 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, - 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00, - 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0, - 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, - 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, - 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00, - 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0, - 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00, - 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc, - 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00, - 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00, - 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, - 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0, - 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00, - 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, - 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, - 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00, - 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, - 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, - 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, - 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, - 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, - 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, - 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, - 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -Bit8u int10_font_14[256 * 14] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, - 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, - 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, - 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, - 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, - 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, - 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, - 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x70, 0xf0, - 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, - 0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, - 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xf8, - 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, - 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x7c, - 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, - 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, - 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, - 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, - 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, - 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, - 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, - 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x66, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, - 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, - 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, - 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, - 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, - 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, - 0x3c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, - 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xc6, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x60, - 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x0c, - 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, - 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0c, - 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, - 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, - 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, - 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, - 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, - 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, - 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, - 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, - 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, - 0xc0, 0xde, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, - 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x6c, - 0x78, 0x6c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, - 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xe6, - 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, - 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, - 0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, - 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, - 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, - 0xd6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, - 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, - 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, - 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x3c, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, - 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, - 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, - 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, - 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, - 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, - 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, - 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, - 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, - 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, - 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, - 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, - 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, - 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, - 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, - 0xc6, 0x70, 0x1c, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, - 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, - 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, - 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, - 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, - 0x70, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, - 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, - 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, - 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc2, - 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, 0x00, - 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0x76, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, - 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, - 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x60, - 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, - 0x76, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, - 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, - 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xcc, 0xcc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, - 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, - 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x60, - 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x10, - 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, - 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, - 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, - 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, - 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, - 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0xcc, - 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, - 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, 0x00, 0xc6, - 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, - 0x38, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x00, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, - 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, - 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, - 0x18, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, - 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xc6, 0x00, - 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, - 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, - 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x76, 0xdc, - 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, - 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, - 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, - 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, - 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x66, - 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x3c, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, - 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x55, 0xaa, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, - 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, - 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, - 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, - 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, - 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, - 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, - 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, - 0xc0, 0xc0, 0x40, 0x00, 0x00, 0x00, 0xfe, 0xc6, - 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, - 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, - 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, - 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, - 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, - 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, - 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, - 0x60, 0x60, 0x7c, 0x60, 0x60, 0x30, 0x1c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, - 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, - 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, - 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, - 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, - 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, - 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -Bit8u int10_font_16[256 * 16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, - 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, - 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, - 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, - 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, - 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, - 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, - 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, - 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, - 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, - 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, - 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, - 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, - 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, - 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, - 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, - 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, - 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, - 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, - 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, - 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, - 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, - 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, - 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, - 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, - 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, - 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, - 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, - 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, - 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, - 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, - 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, - 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, - 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, - 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, - 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, - 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, - 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, - 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, - 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, - 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, - 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, - 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, - 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, - 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, - 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, - 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, - 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, - 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, - 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, - 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, - 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, - 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, - 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, - 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, - 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, - 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, - 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, - 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, - 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, - 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, - 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 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, 0xff, 0x00, 0x00, - 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, - 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, - 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, - 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, - 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, - 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, - 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, - 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, - 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, - 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, - 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, - 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, - 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, - 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, - 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, - 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, - 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, - 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, - 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, - 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, - 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, - 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, - 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, - 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, - 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, - 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, - 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, - 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, - 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, - 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, - 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, - 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, - 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, - 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00, - 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, - 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, - 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, - 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, - 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, - 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, - 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, - 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, - 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, - 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, - 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, - 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, - 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, - 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, - 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, - 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, - 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, - 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, - 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, - 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, - 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, - 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, - 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, - 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, - 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "mem.h" +#include "inout.h" +#include "int10.h" + + +VGAROMAREA int10_romarea; +static Bit8u static_functionality[0x10]= +{ + /* 0 */ 0xff, // All modes supported #1 + /* 1 */ 0xff, // All modes supported #2 + /* 2 */ 0x0f, // All modes supported #3 + /* 3 */ 0x00, 0x00, 0x00, 0x00, // reserved + /* 7 */ 0x07, // 200, 350, 400 scan lines + /* 8 */ 0x04, // total number of character blocks available in text modes + /* 9 */ 0x02, // maximum number of active character blocks in text modes + /* a */ 0xff, // Misc Flags Everthing supported + /* b */ 0x0c, // Support for Display combination and intensity/blinking + /* c */ 0x00, // reserved + /* d */ 0x00, // reserved + /* e */ 0x00, // Change to add new functions + /* f */ 0x00 // reserved +}; + + + +void INT10_SetupRomMemory(void) { +/* This should fill up certain structures inside the Video Bios Rom Area */ + Bit32u i; + + Bit16u segoff=0; + int10_romarea.font_8_first=RealMake(0xC000,segoff); + for (i=0;i<128*8;i++) { + real_writeb(0xC000,segoff++,int10_font_08[i]); + } + int10_romarea.font_8_second=RealMake(0xC000,segoff); + for (i=0;i<128*8;i++) { + real_writeb(0xC000,segoff++,int10_font_08[i+128*8]); + } + int10_romarea.font_14=RealMake(0xC000,segoff); + for (i=0;i<256*14;i++) { + real_writeb(0xC000,segoff++,int10_font_14[i]); + } + int10_romarea.font_16=RealMake(0xC000,segoff); + for (i=0;i<256*16;i++) { + real_writeb(0xC000,segoff++,int10_font_16[i]); + } + int10_romarea.static_state=RealMake(0xC000,segoff); + for (i=0;i<0x10;i++) { + real_writeb(0xC000,segoff++,static_functionality[i]); + } + +}; + + + + +Bit8u int10_font_08[256 * 8] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, + 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, + 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, + 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, + 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, + 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, + 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, + 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, + 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, + 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, + 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, + 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, + 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, + 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, + 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, + 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, + 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, + 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, + 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, + 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, + 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00, + 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, + 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, + 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, + 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, + 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, + 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, + 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, + 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, + 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, + 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, + 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, + 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, + 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, + 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, + 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, + 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, + 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, + 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, + 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, + 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, + 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, + 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, + 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, + 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, + 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, + 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, + 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, + 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, + 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, + 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, + 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, + 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, + 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, + 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, + 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, + 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, + 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, + 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, + 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, + 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, + 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, + 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, + 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, + 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, + 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, + 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, + 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, + 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, + 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, + 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, + 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, + 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, + 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, + 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, + 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, + 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, + 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, + 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, + 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, + 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, + 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, + 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, + 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, + 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, + 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, + 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, + 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, + 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, + 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, + 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, + 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, + 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, + 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, + 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00, + 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00, + 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, + 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, + 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f, + 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, + 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, + 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00, + 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0, + 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, + 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, + 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00, + 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0, + 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00, + 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc, + 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00, + 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, + 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0, + 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00, + 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, + 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, + 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00, + 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, + 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, + 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, + 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, + 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, + 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +Bit8u int10_font_14[256 * 14] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, + 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, + 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, + 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, + 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, + 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, + 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, + 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x70, 0xf0, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, + 0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, + 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xf8, + 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, + 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x7c, + 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, + 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, + 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, + 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, + 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, + 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, + 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x66, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, + 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, + 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, + 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, + 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, + 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, + 0x3c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, + 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x60, + 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x0c, + 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, + 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0c, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, + 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, + 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, + 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, + 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, + 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, + 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, + 0xc0, 0xde, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, + 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x6c, + 0x78, 0x6c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xe6, + 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, + 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, + 0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, + 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, + 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, + 0xd6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, + 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, + 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, + 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x3c, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, + 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, + 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, + 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, + 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, + 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, + 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, + 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, + 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, + 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, + 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, + 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, + 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, + 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, + 0xc6, 0x70, 0x1c, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, + 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, + 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, + 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, + 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, + 0x70, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, + 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, + 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc2, + 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, 0x00, + 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0x76, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, + 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, + 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, + 0x76, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, + 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, + 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcc, 0xcc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, + 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, + 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x10, + 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, + 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, + 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, + 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, + 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, + 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0xcc, + 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, + 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, 0x00, 0xc6, + 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, + 0x38, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x00, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, + 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, + 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, + 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xc6, 0x00, + 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, + 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, + 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, + 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x76, 0xdc, + 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, + 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, + 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, + 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, + 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, + 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x66, + 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x3c, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, + 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x55, 0xaa, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, + 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, + 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, + 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, + 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, + 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, + 0xc0, 0xc0, 0x40, 0x00, 0x00, 0x00, 0xfe, 0xc6, + 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, + 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, + 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, + 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, + 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, + 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, + 0x60, 0x60, 0x7c, 0x60, 0x60, 0x30, 0x1c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, + 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, + 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, + 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, + 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +Bit8u int10_font_16[256 * 16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, + 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, + 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, + 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, + 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, + 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, + 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, + 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, + 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, + 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, + 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, + 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, + 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, + 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, + 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, + 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, + 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, + 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, + 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, + 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, + 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, + 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, + 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, + 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, + 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, + 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, + 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, + 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, + 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, + 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, + 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, + 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, + 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, + 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, + 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, + 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, + 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, + 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, + 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, + 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, + 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, + 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, + 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, + 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, + 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, + 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, + 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, + 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, + 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, + 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, + 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, + 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, + 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, + 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, + 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, + 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, + 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, + 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, + 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, + 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, + 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, + 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 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, 0xff, 0x00, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, + 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, + 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, + 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, + 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, + 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, + 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, + 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, + 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, + 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, + 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, + 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, + 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, + 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, + 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, + 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, + 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, + 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, + 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, + 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, + 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, + 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, + 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, + 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, + 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, + 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, + 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, + 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, + 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, + 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, + 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, + 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, + 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, + 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, + 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, + 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, + 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, + 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, + 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, + 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, + 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, + 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, + 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, + 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, + 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, + 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, + 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, + 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, + 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, + 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, + 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, + 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, + 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, + 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, + 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, + 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, + 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, + 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + + diff --git a/src/ints/int10_misc.cpp b/src/ints/int10_misc.cpp index 298b6bb..c2f256d 100644 --- a/src/ints/int10_misc.cpp +++ b/src/ints/int10_misc.cpp @@ -1,312 +1,135 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: int10_misc.cpp,v 1.20 2009/04/11 07:58:39 qbix79 Exp $ */ - -#include "dosbox.h" -#include "mem.h" -#include "inout.h" -#include "int10.h" - - - -#pragma pack(1) -struct Dynamic_Functionality { - RealPt static_table; /* 00h DWORD address of static functionality table */ - Bit8u cur_mode; /* 04h BYTE video mode in effect */ - Bit16u num_cols; /* 05h WORD number of columns */ - Bit16u regen_size; /* 07h WORD length of regen buffer in bytes */ - Bit16u regen_start; /* 09h WORD starting address of regen buffer*/ - Bit16u cursor_pos[8]; /* 0Bh WORD cursor position for page 0-7 */ - Bit16u cursor_type; /* 1Bh WORD cursor type */ - Bit8u active_page; /* 1Dh BYTE active display page */ - Bit16u crtc_address; /* 1Eh WORD CRTC port address */ - Bit8u reg_3x8; /* 20h BYTE current setting of register (3?8) */ - Bit8u reg_3x9; /* 21h BYTE current setting of register (3?9) */ - Bit8u num_rows; /* 22h BYTE number of rows */ - Bit16u bytes_per_char; /* 23h WORD bytes/character */ - Bit8u dcc; /* 25h BYTE display combination code of active display */ - Bit8u dcc_alternate; /* 26h BYTE DCC of alternate display */ - Bit16u num_colors; /* 27h WORD number of colors supported in current mode */ - Bit8u num_pages; /* 29h BYTE number of pages supported in current mode */ - Bit8u num_scanlines; /* 2Ah BYTE number of scan lines active mode (0,1,2,3) = (200,350,400,480) */ - Bit8u pri_char_block; /* 2Bh BYTE primary character block */ - Bit8u sec_char_block; /* 2Ch BYTE secondary character block */ - Bit8u misc_flags; /* 2Dh BYTE miscellaneous flags - bit 0 all modes on all displays on - 1 grey summing on - 2 monochrome display attached - 3 default palette loading disabled - 4 cursor emulation enabled - 5 0 = intensity; 1 = blinking - 6 PS/2 P70 plasma display (without 9-dot wide font) active - 7 reserved - */ - Bit8u reserved1[3]; /* 2Eh 3 BYTEs reserved (00h) */ - Bit8u vid_mem; /* 31h BYTE video memory available 00h = 64K, 01h = 128K, 02h = 192K, 03h = 256K */ - Bit8u savep_state_flag; /* 32h BYTE save pointer state flags - bit 0 512 character set active - 1 dynamic save area present - 2 alpha font override active - 3 graphics font override active - 4 palette override active - 5 DCC override active - 6 reserved - 7 reserved - */ - Bit8u reserved2[13]; /* 33h 13 BYTEs reserved (00h) */ -} GCC_ATTRIBUTE(packed); -#pragma pack() - -void INT10_GetFuncStateInformation(PhysPt save) { - /* set static state pointer */ - mem_writed(save,int10.rom.static_state); - /* Copy BIOS Segment areas */ - Bit16u i; - - /* First area in Bios Seg */ - for (i=0;i<0x1e;i++) { - mem_writeb(save+0x4+i,real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE+i)); - } - /* Second area */ - mem_writeb(save+0x22,real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1); - for (i=1;i<3;i++) { - mem_writeb(save+0x22+i,real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS+i)); - } - /* Zero out rest of block */ - for (i=0x25;i<0x40;i++) mem_writeb(save+i,0); - /* DCC */ -// mem_writeb(save+0x25,real_readb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX)); - Bit8u dccode = 0x00; - RealPt vsavept=real_readd(BIOSMEM_SEG,BIOSMEM_VS_POINTER); - RealPt svstable=real_readd(RealSeg(vsavept),RealOff(vsavept)+0x10); - if (svstable) { - RealPt dcctable=real_readd(RealSeg(svstable),RealOff(svstable)+0x02); - Bit8u entries=real_readb(RealSeg(dcctable),RealOff(dcctable)+0x00); - Bit8u idx=real_readb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX); - // check if index within range - if (idx>8)&0xff); - else dccode=(Bit8u)(dccentry&0xff); - } - } - mem_writeb(save+0x25,dccode); - - Bit16u col_count=0; - switch (CurMode->type) { - case M_TEXT: - if (CurMode->mode==0x7) col_count=1; else col_count=16;break; - case M_CGA2: - col_count=2;break; - case M_CGA4: - col_count=4;break; - case M_EGA: - if (CurMode->mode==0x11 || CurMode->mode==0x0f) - col_count=2; - else - col_count=16; - break; - case M_VGA: - col_count=256;break; - default: - LOG(LOG_INT10,LOG_ERROR)("Get Func State illegal mode type %d",CurMode->type); - } - /* Colour count */ - mem_writew(save+0x27,col_count); - /* Page count */ - mem_writeb(save+0x29,CurMode->ptotal); - /* scan lines */ - switch (CurMode->sheight) { - case 200: - mem_writeb(save+0x2a,0);break; - case 350: - mem_writeb(save+0x2a,1);break; - case 400: - mem_writeb(save+0x2a,2);break; - case 480: - mem_writeb(save+0x2a,3);break; - }; - /* misc flags */ - if (CurMode->type==M_TEXT) mem_writeb(save+0x2d,0x21); - else mem_writeb(save+0x2d,0x01); - /* Video Memory available */ - mem_writeb(save+0x31,3); -} - -RealPt INT10_EGA_RIL_GetVersionPt(void) { - /* points to a graphics ROM location at the moment - as checks test for bx!=0 only */ - return RealMake(0xc000,0x30); -} - -static void EGA_RIL(Bit16u dx, Bitu& port, Bitu& regs) { - port = 0; - regs = 0; //if nul is returned it's a single register port - switch(dx) { - case 0x00: /* CRT Controller (25 reg) 3B4h mono modes, 3D4h color modes */ - port = real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); - regs = 25; - break; - case 0x08: /* Sequencer (5 registers) 3C4h */ - port = 0x3C4; - regs = 5; - break; - case 0x10: /* Graphics Controller (9 registers) 3CEh */ - port = 0x3CE; - regs = 9; - break; - case 0x18: /* Attribute Controller (20 registers) 3C0h */ - port = 0x3c0; - regs = 20; - break; - case 0x20: /* Miscellaneous Output register 3C2h */ - port = 0x3C2; - break; - case 0x28: /* Feature Control register (3BAh mono modes, 3DAh color modes) */ - port = real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6; - break; - case 0x30: /* Graphics 1 Position register 3CCh */ - port = 0x3CC; - break; - case 0x38: /* Graphics 2 Position register 3CAh */ - port = 0x3CA; - break; - default: - LOG(LOG_INT10,LOG_ERROR)("unknown RIL port selection %X",dx); - break; - } -} - -void INT10_EGA_RIL_ReadRegister(Bit8u & bl, Bit16u dx) { - Bitu port = 0; - Bitu regs = 0; - EGA_RIL(dx,port,regs); - if(regs == 0) { - if(port) bl = IO_Read(port); - } else { - if(port == 0x3c0) IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6); - IO_Write(port,bl); - bl = IO_Read(port+1); - if(port == 0x3c0) IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6); - LOG(LOG_INT10,LOG_NORMAL)("EGA RIL read used with multi-reg"); - } -} - -void INT10_EGA_RIL_WriteRegister(Bit8u & bl, Bit8u bh, Bit16u dx) { - Bitu port = 0; - Bitu regs = 0; - EGA_RIL(dx,port,regs); - if(regs == 0) { - if(port) IO_Write(port,bl); - } else { - if(port == 0x3c0) { - IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6); - IO_Write(port,bl); - IO_Write(port,bh); - } else { - IO_Write(port,bl); - IO_Write(port+1,bh); - } - bl = bh;//Not sure - LOG(LOG_INT10,LOG_NORMAL)("EGA RIL write used with multi-reg"); - } -} - -void INT10_EGA_RIL_ReadRegisterRange(Bit8u ch, Bit8u cl, Bit16u dx, PhysPt dst) { - Bitu port = 0; - Bitu regs = 0; - EGA_RIL(dx,port,regs); - if(regs == 0) { - LOG(LOG_INT10,LOG_ERROR)("EGA RIL range read with port %x called",port); - } else { - if(chregs) cl=(Bit8u)(regs-ch); - for (Bitu i=0; iregs) cl=(Bit8u)(regs-ch); - if(port == 0x3c0) { - IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6); - for (Bitu i=0; imemmodel) { + case CTEXT: + col_count=2;break; + case MTEXT: + col_count=16;break; + case CGA: + col_count=4;break; + case PLANAR1: + col_count=2;break; + case PLANAR2: + col_count=4;break; + case PLANAR4: + col_count=16;break; + case LINEAR8: + col_count=256;break; + } + /* Colour count */ + mem_writew(save+0x27,col_count); + /* Page count */ + mem_writeb(save+0x29,curmode->nbpages); + /* scan lines */ + switch (curmode->sheight) { + case 200: + mem_writeb(save+0x2a,0);break; + case 350: + mem_writeb(save+0x2a,1);break; + case 400: + mem_writeb(save+0x2a,2);break; + case 480: + mem_writeb(save+0x2a,3);break; + }; + //TODO Maybe misc flags + /* Video Memory available */ + mem_writeb(save+0x31,3); +} + diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index 0ae364a..d2acd81 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.cpp @@ -1,1359 +1,403 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: int10_modes.cpp,v 1.85 2009/01/25 12:00:52 c2woody Exp $ */ - -#include - -#include "dosbox.h" -#include "mem.h" -#include "inout.h" -#include "int10.h" -#include "mouse.h" -#include "vga.h" - -#define _EGA_HALF_CLOCK 0x0001 -#define _EGA_LINE_DOUBLE 0x0002 -#define _VGA_PIXEL_DOUBLE 0x0004 - -#define SEQ_REGS 0x05 -#define GFX_REGS 0x09 -#define ATT_REGS 0x15 - -VideoModeBlock ModeList_VGA[]={ -/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */ -{ 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, -{ 0x001 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, -{ 0x002 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, -{ 0x003 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, -{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x007 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, - -{ 0x00D ,M_EGA ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE }, -{ 0x00E ,M_EGA ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE }, -{ 0x00F ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },/*was EGA_2*/ -{ 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 }, -{ 0x011 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },/*was EGA_2 */ -{ 0x012 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 }, -{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,0 }, - -{ 0x054 ,M_TEXT ,1056,688, 132,43, 8, 16, 1 ,0xB8000 ,0x4000, 192, 800, 132,688, 0 }, -{ 0x055 ,M_TEXT ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 192, 449, 132,400, 0 }, - -/* Alias of mode 102 */ -{ 0x06A ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0 }, - -/* Follow vesa 1.2 for first 0x20 */ -{ 0x100 ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 }, -{ 0x101 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 }, -{ 0x102 ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 }, -{ 0x103 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 }, -{ 0x104 ,M_LIN4 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 }, -{ 0x105 ,M_LIN8 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 }, -{ 0x106 ,M_LIN4 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 }, -{ 0x107 ,M_LIN8 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 }, - -{ 0x10D ,M_LIN15 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x10E ,M_LIN16 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x10F ,M_LIN32 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x110 ,M_LIN15 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0 }, -{ 0x111 ,M_LIN16 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0 }, -{ 0x112 ,M_LIN32 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 }, -{ 0x113 ,M_LIN15 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0 }, -{ 0x114 ,M_LIN16 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0 }, -{ 0x115 ,M_LIN32 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 }, - -{ 0x116 ,M_LIN15 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0 }, -{ 0x117 ,M_LIN16 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0 }, -{ 0x118 ,M_LIN32 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 }, -/* those should be interlaced but ok */ -//{ 0x119 ,M_LIN15 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0 }, -//{ 0x11A ,M_LIN16 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0 }, - -{ 0x150 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x152 ,M_LIN8 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE }, -{ 0x153 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE }, - -{ 0x160 ,M_LIN15 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x161 ,M_LIN15 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 , _VGA_PIXEL_DOUBLE }, -{ 0x162 ,M_LIN15 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE }, -{ 0x165 ,M_LIN15 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0 }, - -{ 0x170 ,M_LIN16 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x171 ,M_LIN16 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 , _VGA_PIXEL_DOUBLE }, -{ 0x172 ,M_LIN16 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE }, -{ 0x175 ,M_LIN16 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0 }, - -{ 0x190 ,M_LIN32 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE }, -{ 0x191 ,M_LIN32 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,449 ,40 ,400 , _VGA_PIXEL_DOUBLE }, -{ 0x192 ,M_LIN32 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 , _VGA_PIXEL_DOUBLE }, - -/* S3 specific modes */ -{ 0x207 ,M_LIN8 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,182 ,948 ,144,864 ,0 }, -{ 0x209 ,M_LIN15 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,364 ,948 ,288,864 ,0 }, -{ 0x20A ,M_LIN16 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,364 ,948 ,288,864 ,0 }, -//{ 0x20B ,M_LIN32 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,182 ,948 ,144,864 ,0 }, -{ 0x213 ,M_LIN32 ,640 ,400,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 }, - -/* Some custom modes */ -//{ 0x220 ,M_LIN32 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 }, -// A nice 16:9 mode -{ 0x222 ,M_LIN8 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,0 }, -{ 0x223 ,M_LIN15 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,212 ,480 ,0 }, -{ 0x224 ,M_LIN16 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,212 ,480 ,0 }, -{ 0x225 ,M_LIN32 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,0 }, - -{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, -}; - -VideoModeBlock ModeList_VGA_Tseng[]={ -/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */ -{ 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, -{ 0x001 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, -{ 0x002 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, -{ 0x003 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, -{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x007 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, - -{ 0x00D ,M_EGA ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE }, -{ 0x00E ,M_EGA ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE }, -{ 0x00F ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },/*was EGA_2*/ -{ 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 }, -{ 0x011 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },/*was EGA_2 */ -{ 0x012 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 }, -{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,0 }, - -{ 0x018 ,M_TEXT ,1056 ,688, 132,44, 8, 8, 1 ,0xB0000 ,0x4000, 192, 800, 132, 704, 0 }, -{ 0x019 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1 ,0xB0000 ,0x2000, 192, 449, 132, 400, 0 }, -{ 0x01A ,M_TEXT ,1056 ,400, 132,28, 8, 16,1 ,0xB0000 ,0x2000, 192, 449, 132, 448, 0 }, -{ 0x022 ,M_TEXT ,1056 ,688, 132,44, 8, 8, 1 ,0xB8000 ,0x4000, 192, 800, 132, 704, 0 }, -{ 0x023 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1 ,0xB8000 ,0x2000, 192, 449, 132, 400, 0 }, -{ 0x024 ,M_TEXT ,1056 ,400, 132,28, 8, 16,1 ,0xB8000 ,0x2000, 192, 449, 132, 448, 0 }, -{ 0x025 ,M_LIN4 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 , 0 }, -{ 0x029 ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 }, -{ 0x02D ,M_LIN8 ,640 ,350 ,80 ,21 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,350 , 0 }, -{ 0x02E ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , 0 }, -{ 0x02F ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , 0 },/* ET4000 only */ -{ 0x030 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 , 0 }, -{ 0x036 ,M_LIN4 ,960 , 720,120,45 ,8 ,16 ,1 ,0xA0000 ,0xA000, 120 ,800 ,120,720 , 0 },/* STB only */ -{ 0x037 ,M_LIN4 ,1024, 768,128,48 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,800 ,128,768 , 0 }, -{ 0x038 ,M_LIN8 ,1024 ,768,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,800 ,128,768 , 0 },/* ET4000 only */ -{ 0x03D ,M_LIN4 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0xA000, 160 ,1152,160,1024, 0 },/* newer ET4000 */ -{ 0x03E ,M_LIN4 ,1280, 960,160,60 ,8 ,16 ,1 ,0xA0000 ,0xA000, 160 ,1024,160,960 , 0 },/* Definicon only */ -{ 0x06A ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 },/* newer ET4000 */ - -{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, -}; - -VideoModeBlock ModeList_VGA_Paradise[]={ -/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */ -{ 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, -{ 0x001 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, -{ 0x002 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, -{ 0x003 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, -{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x007 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, - -{ 0x00D ,M_EGA ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE }, -{ 0x00E ,M_EGA ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE }, -{ 0x00F ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },/*was EGA_2*/ -{ 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 }, -{ 0x011 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },/*was EGA_2 */ -{ 0x012 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 }, -{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,0 }, - -{ 0x054 ,M_TEXT ,1056 ,688, 132,43, 8, 9, 1, 0xB0000, 0x4000, 192, 720, 132,688, 0 }, -{ 0x055 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1, 0xB0000, 0x2000, 192, 449, 132,400, 0 }, -{ 0x056 ,M_TEXT ,1056 ,688, 132,43, 8, 9, 1, 0xB0000, 0x4000, 192, 720, 132,688, 0 }, -{ 0x057 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1, 0xB0000, 0x2000, 192, 449, 132,400, 0 }, -{ 0x058 ,M_LIN4 ,800 , 600, 100,37, 8, 16,1, 0xA0000, 0xA000, 128 ,663 ,100,600, 0 }, -{ 0x05D ,M_LIN4 ,1024, 768, 128,48 ,8, 16,1, 0xA0000, 0x10000,128 ,800 ,128,768 ,0 }, // documented only on C00 upwards -{ 0x05E ,M_LIN8 ,640 , 400, 80 ,25, 8, 16,1, 0xA0000, 0x10000,100 ,449 ,80 ,400, 0 }, -{ 0x05F ,M_LIN8 ,640 , 480, 80 ,30, 8, 16,1, 0xA0000, 0x10000,100 ,525 ,80 ,480, 0 }, - -{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, -}; - - -VideoModeBlock ModeList_EGA[]={ -/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */ -{ 0x000 ,M_TEXT ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50 ,366 ,40 ,350 ,_EGA_HALF_CLOCK }, -{ 0x001 ,M_TEXT ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50 ,366 ,40 ,350 ,_EGA_HALF_CLOCK }, -{ 0x002 ,M_TEXT ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,96 ,366 ,80 ,350 ,0 }, -{ 0x003 ,M_TEXT ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,96 ,366 ,80 ,350 ,0 }, -{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,60 ,262 ,40 ,200 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,60 ,262 ,40 ,200 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, -{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,120 ,262 ,80 ,200 ,_EGA_LINE_DOUBLE}, -{ 0x007 ,M_TEXT ,720 ,350 ,80 ,25 ,9 ,14 ,8 ,0xB0000 ,0x1000 ,120 ,440 ,80 ,350 ,0 }, - -{ 0x00D ,M_EGA ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,60 ,262 ,40 ,200 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE }, -{ 0x00E ,M_EGA ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,120 ,262 ,80 ,200 ,_EGA_LINE_DOUBLE }, -{ 0x00F ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,96 ,366 ,80 ,350 ,0 },/*was EGA_2*/ -{ 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,96 ,366 ,80 ,350 ,0 }, - -{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, -}; - -VideoModeBlock ModeList_OTHER[]={ -/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde ,special flags */ -{ 0x000 ,M_TEXT ,320 ,400 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x0800 ,56 ,31 ,40 ,25 ,0 }, -{ 0x001 ,M_TEXT ,320 ,400 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x0800 ,56 ,31 ,40 ,25 ,0 }, -{ 0x002 ,M_TEXT ,640 ,400 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x1000 ,113 ,31 ,80 ,25 ,0 }, -{ 0x003 ,M_TEXT ,640 ,400 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x1000 ,113 ,31 ,80 ,25 ,0 }, -{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,56 ,127 ,40 ,100 ,0 }, -{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,56 ,127 ,40 ,100 ,0 }, -{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,56 ,127 ,40 ,100 ,0 }, -{ 0x008 ,M_TANDY16,160 ,200 ,20 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,56 ,127 ,40 ,100 ,0 }, -{ 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 }, -{ 0x00A ,M_CGA4 ,640 ,200 ,80 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 }, -{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, -}; - -VideoModeBlock Hercules_Mode= -{ 0x007 ,M_TEXT ,640 ,400 ,80 ,25 ,8 ,14 ,4 ,0xB0000 ,0x1000 ,97 ,25 ,80 ,25 ,0 }; - -static Bit8u text_palette[64][3]= -{ - {0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x2a,0x00},{0x2a,0x2a,0x2a}, - {0x00,0x00,0x15},{0x00,0x00,0x3f},{0x00,0x2a,0x15},{0x00,0x2a,0x3f},{0x2a,0x00,0x15},{0x2a,0x00,0x3f},{0x2a,0x2a,0x15},{0x2a,0x2a,0x3f}, - {0x00,0x15,0x00},{0x00,0x15,0x2a},{0x00,0x3f,0x00},{0x00,0x3f,0x2a},{0x2a,0x15,0x00},{0x2a,0x15,0x2a},{0x2a,0x3f,0x00},{0x2a,0x3f,0x2a}, - {0x00,0x15,0x15},{0x00,0x15,0x3f},{0x00,0x3f,0x15},{0x00,0x3f,0x3f},{0x2a,0x15,0x15},{0x2a,0x15,0x3f},{0x2a,0x3f,0x15},{0x2a,0x3f,0x3f}, - {0x15,0x00,0x00},{0x15,0x00,0x2a},{0x15,0x2a,0x00},{0x15,0x2a,0x2a},{0x3f,0x00,0x00},{0x3f,0x00,0x2a},{0x3f,0x2a,0x00},{0x3f,0x2a,0x2a}, - {0x15,0x00,0x15},{0x15,0x00,0x3f},{0x15,0x2a,0x15},{0x15,0x2a,0x3f},{0x3f,0x00,0x15},{0x3f,0x00,0x3f},{0x3f,0x2a,0x15},{0x3f,0x2a,0x3f}, - {0x15,0x15,0x00},{0x15,0x15,0x2a},{0x15,0x3f,0x00},{0x15,0x3f,0x2a},{0x3f,0x15,0x00},{0x3f,0x15,0x2a},{0x3f,0x3f,0x00},{0x3f,0x3f,0x2a}, - {0x15,0x15,0x15},{0x15,0x15,0x3f},{0x15,0x3f,0x15},{0x15,0x3f,0x3f},{0x3f,0x15,0x15},{0x3f,0x15,0x3f},{0x3f,0x3f,0x15},{0x3f,0x3f,0x3f} -}; - -static Bit8u mtext_palette[64][3]= -{ - {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00}, - {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a}, - {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00}, - {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f}, - {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00}, - {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a}, - {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00}, - {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f} -}; - -static Bit8u mtext_s3_palette[64][3]= -{ - {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00}, - {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a}, - {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a}, - {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f}, - {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00}, - {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a}, - {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a}, - {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f} -}; - -static Bit8u ega_palette[64][3]= -{ - {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, - {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, - {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}, - {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}, - {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, - {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, - {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}, - {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f} -}; - -static Bit8u cga_palette[16][3]= -{ - {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, - {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}, -}; - -static Bit8u cga_palette_2[64][3]= -{ - {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, - {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, - {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}, - {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}, - {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, - {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, - {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}, - {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}, -}; - -static Bit8u vga_palette[256][3]= -{ - {0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x15,0x00},{0x2a,0x2a,0x2a}, - {0x15,0x15,0x15},{0x15,0x15,0x3f},{0x15,0x3f,0x15},{0x15,0x3f,0x3f},{0x3f,0x15,0x15},{0x3f,0x15,0x3f},{0x3f,0x3f,0x15},{0x3f,0x3f,0x3f}, - {0x00,0x00,0x00},{0x05,0x05,0x05},{0x08,0x08,0x08},{0x0b,0x0b,0x0b},{0x0e,0x0e,0x0e},{0x11,0x11,0x11},{0x14,0x14,0x14},{0x18,0x18,0x18}, - {0x1c,0x1c,0x1c},{0x20,0x20,0x20},{0x24,0x24,0x24},{0x28,0x28,0x28},{0x2d,0x2d,0x2d},{0x32,0x32,0x32},{0x38,0x38,0x38},{0x3f,0x3f,0x3f}, - {0x00,0x00,0x3f},{0x10,0x00,0x3f},{0x1f,0x00,0x3f},{0x2f,0x00,0x3f},{0x3f,0x00,0x3f},{0x3f,0x00,0x2f},{0x3f,0x00,0x1f},{0x3f,0x00,0x10}, - {0x3f,0x00,0x00},{0x3f,0x10,0x00},{0x3f,0x1f,0x00},{0x3f,0x2f,0x00},{0x3f,0x3f,0x00},{0x2f,0x3f,0x00},{0x1f,0x3f,0x00},{0x10,0x3f,0x00}, - {0x00,0x3f,0x00},{0x00,0x3f,0x10},{0x00,0x3f,0x1f},{0x00,0x3f,0x2f},{0x00,0x3f,0x3f},{0x00,0x2f,0x3f},{0x00,0x1f,0x3f},{0x00,0x10,0x3f}, - {0x1f,0x1f,0x3f},{0x27,0x1f,0x3f},{0x2f,0x1f,0x3f},{0x37,0x1f,0x3f},{0x3f,0x1f,0x3f},{0x3f,0x1f,0x37},{0x3f,0x1f,0x2f},{0x3f,0x1f,0x27}, - - {0x3f,0x1f,0x1f},{0x3f,0x27,0x1f},{0x3f,0x2f,0x1f},{0x3f,0x37,0x1f},{0x3f,0x3f,0x1f},{0x37,0x3f,0x1f},{0x2f,0x3f,0x1f},{0x27,0x3f,0x1f}, - {0x1f,0x3f,0x1f},{0x1f,0x3f,0x27},{0x1f,0x3f,0x2f},{0x1f,0x3f,0x37},{0x1f,0x3f,0x3f},{0x1f,0x37,0x3f},{0x1f,0x2f,0x3f},{0x1f,0x27,0x3f}, - {0x2d,0x2d,0x3f},{0x31,0x2d,0x3f},{0x36,0x2d,0x3f},{0x3a,0x2d,0x3f},{0x3f,0x2d,0x3f},{0x3f,0x2d,0x3a},{0x3f,0x2d,0x36},{0x3f,0x2d,0x31}, - {0x3f,0x2d,0x2d},{0x3f,0x31,0x2d},{0x3f,0x36,0x2d},{0x3f,0x3a,0x2d},{0x3f,0x3f,0x2d},{0x3a,0x3f,0x2d},{0x36,0x3f,0x2d},{0x31,0x3f,0x2d}, - {0x2d,0x3f,0x2d},{0x2d,0x3f,0x31},{0x2d,0x3f,0x36},{0x2d,0x3f,0x3a},{0x2d,0x3f,0x3f},{0x2d,0x3a,0x3f},{0x2d,0x36,0x3f},{0x2d,0x31,0x3f}, - {0x00,0x00,0x1c},{0x07,0x00,0x1c},{0x0e,0x00,0x1c},{0x15,0x00,0x1c},{0x1c,0x00,0x1c},{0x1c,0x00,0x15},{0x1c,0x00,0x0e},{0x1c,0x00,0x07}, - {0x1c,0x00,0x00},{0x1c,0x07,0x00},{0x1c,0x0e,0x00},{0x1c,0x15,0x00},{0x1c,0x1c,0x00},{0x15,0x1c,0x00},{0x0e,0x1c,0x00},{0x07,0x1c,0x00}, - {0x00,0x1c,0x00},{0x00,0x1c,0x07},{0x00,0x1c,0x0e},{0x00,0x1c,0x15},{0x00,0x1c,0x1c},{0x00,0x15,0x1c},{0x00,0x0e,0x1c},{0x00,0x07,0x1c}, - - {0x0e,0x0e,0x1c},{0x11,0x0e,0x1c},{0x15,0x0e,0x1c},{0x18,0x0e,0x1c},{0x1c,0x0e,0x1c},{0x1c,0x0e,0x18},{0x1c,0x0e,0x15},{0x1c,0x0e,0x11}, - {0x1c,0x0e,0x0e},{0x1c,0x11,0x0e},{0x1c,0x15,0x0e},{0x1c,0x18,0x0e},{0x1c,0x1c,0x0e},{0x18,0x1c,0x0e},{0x15,0x1c,0x0e},{0x11,0x1c,0x0e}, - {0x0e,0x1c,0x0e},{0x0e,0x1c,0x11},{0x0e,0x1c,0x15},{0x0e,0x1c,0x18},{0x0e,0x1c,0x1c},{0x0e,0x18,0x1c},{0x0e,0x15,0x1c},{0x0e,0x11,0x1c}, - {0x14,0x14,0x1c},{0x16,0x14,0x1c},{0x18,0x14,0x1c},{0x1a,0x14,0x1c},{0x1c,0x14,0x1c},{0x1c,0x14,0x1a},{0x1c,0x14,0x18},{0x1c,0x14,0x16}, - {0x1c,0x14,0x14},{0x1c,0x16,0x14},{0x1c,0x18,0x14},{0x1c,0x1a,0x14},{0x1c,0x1c,0x14},{0x1a,0x1c,0x14},{0x18,0x1c,0x14},{0x16,0x1c,0x14}, - {0x14,0x1c,0x14},{0x14,0x1c,0x16},{0x14,0x1c,0x18},{0x14,0x1c,0x1a},{0x14,0x1c,0x1c},{0x14,0x1a,0x1c},{0x14,0x18,0x1c},{0x14,0x16,0x1c}, - {0x00,0x00,0x10},{0x04,0x00,0x10},{0x08,0x00,0x10},{0x0c,0x00,0x10},{0x10,0x00,0x10},{0x10,0x00,0x0c},{0x10,0x00,0x08},{0x10,0x00,0x04}, - {0x10,0x00,0x00},{0x10,0x04,0x00},{0x10,0x08,0x00},{0x10,0x0c,0x00},{0x10,0x10,0x00},{0x0c,0x10,0x00},{0x08,0x10,0x00},{0x04,0x10,0x00}, - - {0x00,0x10,0x00},{0x00,0x10,0x04},{0x00,0x10,0x08},{0x00,0x10,0x0c},{0x00,0x10,0x10},{0x00,0x0c,0x10},{0x00,0x08,0x10},{0x00,0x04,0x10}, - {0x08,0x08,0x10},{0x0a,0x08,0x10},{0x0c,0x08,0x10},{0x0e,0x08,0x10},{0x10,0x08,0x10},{0x10,0x08,0x0e},{0x10,0x08,0x0c},{0x10,0x08,0x0a}, - {0x10,0x08,0x08},{0x10,0x0a,0x08},{0x10,0x0c,0x08},{0x10,0x0e,0x08},{0x10,0x10,0x08},{0x0e,0x10,0x08},{0x0c,0x10,0x08},{0x0a,0x10,0x08}, - {0x08,0x10,0x08},{0x08,0x10,0x0a},{0x08,0x10,0x0c},{0x08,0x10,0x0e},{0x08,0x10,0x10},{0x08,0x0e,0x10},{0x08,0x0c,0x10},{0x08,0x0a,0x10}, - {0x0b,0x0b,0x10},{0x0c,0x0b,0x10},{0x0d,0x0b,0x10},{0x0f,0x0b,0x10},{0x10,0x0b,0x10},{0x10,0x0b,0x0f},{0x10,0x0b,0x0d},{0x10,0x0b,0x0c}, - {0x10,0x0b,0x0b},{0x10,0x0c,0x0b},{0x10,0x0d,0x0b},{0x10,0x0f,0x0b},{0x10,0x10,0x0b},{0x0f,0x10,0x0b},{0x0d,0x10,0x0b},{0x0c,0x10,0x0b}, - {0x0b,0x10,0x0b},{0x0b,0x10,0x0c},{0x0b,0x10,0x0d},{0x0b,0x10,0x0f},{0x0b,0x10,0x10},{0x0b,0x0f,0x10},{0x0b,0x0d,0x10},{0x0b,0x0c,0x10}, - {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00} -}; -VideoModeBlock * CurMode; - -static bool SetCurMode(VideoModeBlock modeblock[],Bitu mode) { - Bitu i=0; - while (modeblock[i].mode!=0xffff) { - if (modeblock[i].mode!=mode) i++; - else { - if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) { - CurMode=&modeblock[i]; - return true; - } - return false; - } - } - return false; -} - - -static void FinishSetMode(bool clearmem) { - Bitu i; - /* Clear video memory if needs be */ - if (clearmem) { - switch (CurMode->type) { - case M_CGA4: - case M_CGA2: - case M_TANDY16: - for (i=0;i<16*1024;i++) { - real_writew( 0xb800,i*2,0x0000); - } - break; - case M_TEXT: { - Bit16u seg = (CurMode->mode==7)?0xb000:0xb800; - for (i=0;i<16*1024;i++) real_writew(seg,i*2,0x0720); - break; - } - case M_EGA: - case M_VGA: - case M_LIN8: - case M_LIN4: - case M_LIN15: - case M_LIN16: - case M_LIN32: - /* Hack we just acess the memory directly */ - memset(vga.mem.linear,0,vga.vmemsize); - memset(vga.fastmem, 0, vga.vmemsize<<1); - } - } - /* Setup the BIOS */ - if (CurMode->mode<128) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,CurMode->mode); - else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,CurMode->mode-0x98); //Looks like the s3 bios - real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,CurMode->twidth); - real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,CurMode->plength); - real_writew(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,((CurMode->mode==7 )|| (CurMode->mode==0x0f)) ? 0x3b4 : 0x3d4); - real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,CurMode->theight-1); - real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,CurMode->cheight); - real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem?0:0x80))); - real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09); - real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f); - - // this is an index into the dcc table: - if (IS_VGA_ARCH) real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x0b); - real_writed(BIOSMEM_SEG,BIOSMEM_VS_POINTER,int10.rom.video_save_pointers); - - // Set cursor shape - if(CurMode->type==M_TEXT) { - INT10_SetCursorShape(0x06,07); - } - // Set cursor pos for page 0..7 - for(i=0;i<8;i++) INT10_SetCursorPos(0,0,(Bit8u)i); - // Set active page 0 - INT10_SetActivePage(0); - /* Set some interrupt vectors */ - switch (CurMode->cheight) { - case 8:RealSetVec(0x43,int10.rom.font_8_first);break; - case 14:RealSetVec(0x43,int10.rom.font_14);break; - case 16:RealSetVec(0x43,int10.rom.font_16);break; - } - /* Tell mouse resolution change */ - Mouse_NewVideoMode(); -} - -bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) { - Bitu i; - switch (machine) { - case MCH_CGA: - if (mode>6) return false; - case TANDY_ARCH_CASE: - if (mode>0xa) return false; - if (!SetCurMode(ModeList_OTHER,mode)) { - LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode); - return false; - } - break; - case MCH_HERC: - CurMode=&Hercules_Mode; - break; - } - LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode); - - /* Setup the VGA to the correct mode */ -// VGA_SetMode(CurMode->type); - /* Setup the CRTC */ - Bitu crtc_base=machine==MCH_HERC ? 0x3b4 : 0x3d4; - //Horizontal total - IO_WriteW(crtc_base,0x00 | (CurMode->htotal) << 8); - //Horizontal displayed - IO_WriteW(crtc_base,0x01 | (CurMode->hdispend) << 8); - //Horizontal sync position - IO_WriteW(crtc_base,0x02 | (CurMode->hdispend+1) << 8); - //Horizontal sync width, seems to be fixed to 0xa, for cga at least, hercules has 0xf - IO_WriteW(crtc_base,0x03 | (0xa) << 8); - ////Vertical total - IO_WriteW(crtc_base,0x04 | (CurMode->vtotal) << 8); - //Vertical total adjust, 6 for cga,hercules,tandy - IO_WriteW(crtc_base,0x05 | (6) << 8); - //Vertical displayed - IO_WriteW(crtc_base,0x06 | (CurMode->vdispend) << 8); - //Vertical sync position - IO_WriteW(crtc_base,0x07 | (CurMode->vdispend+1) << 8); - //Maximum scanline - Bit8u scanline,crtpage; - scanline=8; - switch(CurMode->type) { - case M_TEXT: - if (machine==MCH_HERC) scanline=14; - else scanline=8; - break; - case M_CGA2: - scanline=2; - break; - case M_CGA4: - if (CurMode->mode!=0xa) scanline=2; - else scanline=4; - break; - case M_TANDY16: - if (CurMode->mode!=0x9) scanline=2; - else scanline=4; - break; - } - IO_WriteW(crtc_base,0x09 | (scanline-1) << 8); - //Setup the CGA palette using VGA DAC palette - for (i=0;i<16;i++) VGA_DAC_SetEntry(i,cga_palette[i][0],cga_palette[i][1],cga_palette[i][2]); - //Setup the tandy palette - for (i=0;i<16;i++) VGA_DAC_CombineColor(i,i); - //Setup the special registers for each machine type - Bit8u mode_control_list[0xa+1]={ - 0x2c,0x28,0x2d,0x29, //0-3 - 0x2a,0x2e,0x16,0x29, //4-7 - 0x2a,0x2b,0x3b //8-a - }; - Bit8u mode_control_list_pcjr[0xa+1]={ - 0x0c,0x08,0x0d,0x09, //0-3 - 0x0a,0x0e,0x0e,0x09, //4-7 - 0x1a,0x1b,0x0b //8-a - }; - Bit8u mode_control,color_select; - switch (machine) { - case MCH_HERC: - IO_WriteB(0x3b8,0x28); // TEXT mode and blinking characters - - VGA_DAC_CombineColor(0,0); - VGA_DAC_CombineColor(1,7); - - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x29); // attribute controls blinking - break; - case MCH_CGA: - mode_control=mode_control_list[CurMode->mode]; - if (CurMode->mode == 0x6) color_select=0x3f; - else color_select=0x30; - IO_WriteB(0x3d8,mode_control); - IO_WriteB(0x3d9,color_select); - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control); - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select); - break; - case MCH_TANDY: - /* Init some registers */ - IO_WriteB(0x3da,0x1);IO_WriteB(0x3de,0xf); //Palette mask always 0xf - IO_WriteB(0x3da,0x2);IO_WriteB(0x3de,0x0); //black border - IO_WriteB(0x3da,0x3); //Tandy color overrides? - switch (CurMode->mode) { - case 0x8: - IO_WriteB(0x3de,0x14);break; - case 0x9: - IO_WriteB(0x3de,0x14);break; - case 0xa: - IO_WriteB(0x3de,0x0c);break; - default: - IO_WriteB(0x3de,0x0);break; - } - //Clear extended mapping - IO_WriteB(0x3da,0x5); - IO_WriteB(0x3de,0x0); - //Clear monitor mode - IO_WriteB(0x3da,0x8); - IO_WriteB(0x3de,0x0); - crtpage=(CurMode->mode>=0x9) ? 0xf6 : 0x3f; - IO_WriteB(0x3df,crtpage); - real_writeb(BIOSMEM_SEG,BIOSMEM_CRTCPU_PAGE,crtpage); - mode_control=mode_control_list[CurMode->mode]; - if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f; - else color_select=0x30; - IO_WriteB(0x3d8,mode_control); - IO_WriteB(0x3d9,color_select); - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control); - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select); - break; - case MCH_PCJR: - /* Init some registers */ - IO_ReadB(0x3da); - IO_WriteB(0x3da,0x1);IO_WriteB(0x3da,0xf); //Palette mask always 0xf - IO_WriteB(0x3da,0x2);IO_WriteB(0x3da,0x0); //black border - IO_WriteB(0x3da,0x3); - if (CurMode->mode<=0x04) IO_WriteB(0x3da,0x02); - else if (CurMode->mode==0x06) IO_WriteB(0x3da,0x08); - else IO_WriteB(0x3da,0x00); - - /* set CRT/Processor page register */ - if (CurMode->mode<0x04) crtpage=0x3f; - else if (CurMode->mode>=0x09) crtpage=0xf6; - else crtpage=0x7f; - IO_WriteB(0x3df,crtpage); - real_writeb(BIOSMEM_SEG,BIOSMEM_CRTCPU_PAGE,crtpage); - - mode_control=mode_control_list_pcjr[CurMode->mode]; - IO_WriteB(0x3da,0x0);IO_WriteB(0x3da,mode_control); - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control); - - if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f; - else color_select=0x30; - IO_WriteB(0x3d9,color_select); - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select); - break; - } - FinishSetMode(clearmem); - return true; -} - - -bool INT10_SetVideoMode(Bitu mode) { - bool clearmem=true;Bitu i; - if (mode>=0x100) { - if ((mode & 0x4000) && int10.vesa_nolfb) return false; - if (mode & 0x8000) clearmem=false; - mode&=0xfff; - } - if ((mode<0x100) && (mode & 0x80)) { - clearmem=false; - mode-=0x80; - } - int10.vesa_setmode=0xffff; - LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode); - if (!IS_EGAVGA_ARCH) return INT10_SetVideoMode_OTHER(mode,clearmem); - Bit8u modeset_ctl,video_ctl,vga_switches; - - if (IS_VGA_ARCH) { - if (svga.accepts_mode) { - if (!svga.accepts_mode(mode)) return false; - } - - switch(svgaCard) { - case SVGA_TsengET4K: - case SVGA_TsengET3K: - if (!SetCurMode(ModeList_VGA_Tseng,mode)){ - LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode); - return false; - } - break; - case SVGA_ParadisePVGA1A: - if (!SetCurMode(ModeList_VGA_Paradise,mode)){ - LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode); - return false; - } - break; - default: - if (!SetCurMode(ModeList_VGA,mode)){ - LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode); - return false; - } - } - } else { - if (!SetCurMode(ModeList_EGA,mode)){ - LOG(LOG_INT10,LOG_ERROR)("EGA:Trying to set illegal mode %X",mode); - return false; - } - } - - /* First read mode setup settings from bios area */ - video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL); - vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES); - modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); - - /* Setup the VGA to the correct mode */ - - Bit16u crtc_base; - bool mono_mode=(mode == 7) || (mode==0xf); - if (mono_mode) crtc_base=0x3b4; - else crtc_base=0x3d4; - - if (IS_VGA_ARCH && (svgaCard == SVGA_S3Trio)) { - // Disable MMIO here so we can read / write memory - IO_Write(crtc_base,0x53); - IO_Write(crtc_base+1,0x0); - } - - /* Setup MISC Output Register */ - Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1); - - switch (CurMode->vdispend) { - case 400: - misc_output|=0x60; - if (CurMode->type==M_TEXT) // && (CurMode->pstart==0xB8000)) - misc_output|=0x4; - break; - case 480: - misc_output|=0xe0; - break; - case 350: - misc_output|=0xa0; - break; - default: - misc_output|=0x60; - } - IO_Write(0x3c2,misc_output); //Setup for 3b4 or 3d4 - - /* Program Sequencer */ - Bit8u seq_data[SEQ_REGS]; - memset(seq_data,0,SEQ_REGS); - if (CurMode->cwidth==8) seq_data[1]|=1; //8 dot fonts by default - if (CurMode->special & _EGA_HALF_CLOCK) seq_data[1]|=0x08; //Check for half clock - if ((machine==MCH_EGA) && (CurMode->special & _EGA_HALF_CLOCK)) seq_data[1]|=0x02; - seq_data[4]|=0x02; //More than 64kb - switch (CurMode->type) { - case M_TEXT: - seq_data[2]|=0x3; //Enable plane 0 and 1 - seq_data[4]|=0x01; //Alpanumeric - if (IS_VGA_ARCH) seq_data[4]|=0x04; //odd/even enabled - break; - case M_CGA2: - seq_data[2]|=0xf; //Enable plane 0 - if (machine==MCH_EGA) seq_data[4]|=0x04; //odd/even enabled - break; - case M_CGA4: - if (machine==MCH_EGA) seq_data[2]|=0x03; //Enable plane 0 and 1 - break; - case M_LIN4: - case M_EGA: - seq_data[2]|=0xf; //Enable all planes for writing - if (machine==MCH_EGA) seq_data[4]|=0x04; //odd/even enabled - break; - case M_LIN8: //Seems to have the same reg layout from testing - case M_LIN15: - case M_LIN16: - case M_LIN32: - case M_VGA: - seq_data[2]|=0xf; //Enable all planes for writing - seq_data[4]|=0xc; //Graphics - odd/even - Chained - break; - } - for (i=0;ihtotal-5); - hor_overflow|=((CurMode->htotal-5) & 0x100) >> 8; - /* Horizontal Display End */ - IO_Write(crtc_base,0x01);IO_Write(crtc_base+1,CurMode->hdispend-1); - hor_overflow|=((CurMode->hdispend-1) & 0x100) >> 7; - /* Start horizontal Blanking */ - IO_Write(crtc_base,0x02);IO_Write(crtc_base+1,CurMode->hdispend); - hor_overflow|=((CurMode->hdispend) & 0x100) >> 6; - /* End horizontal Blanking */ - Bitu blank_end=(CurMode->htotal-2) & 0x7f; - IO_Write(crtc_base,0x03);IO_Write(crtc_base+1,0x80|(blank_end & 0x1f)); - - /* Start Horizontal Retrace */ - Bitu ret_start; - if ((CurMode->special & _EGA_HALF_CLOCK) && (CurMode->type!=M_CGA2)) ret_start = (CurMode->hdispend+3); - else if (CurMode->type==M_TEXT) ret_start = (CurMode->hdispend+5); - else ret_start = (CurMode->hdispend+4); - IO_Write(crtc_base,0x04);IO_Write(crtc_base+1,ret_start); - hor_overflow|=(ret_start & 0x100) >> 4; - - /* End Horizontal Retrace */ - Bitu ret_end; - if (CurMode->special & _EGA_HALF_CLOCK) { - if (CurMode->type==M_CGA2) ret_end=0; // mode 6 - else if (CurMode->special & _EGA_LINE_DOUBLE) ret_end = (CurMode->htotal-18) & 0x1f; - else ret_end = ((CurMode->htotal-18) & 0x1f) | 0x20; // mode 0&1 have 1 char sync delay - } else if (CurMode->type==M_TEXT) ret_end = (CurMode->htotal-3) & 0x1f; - else ret_end = (CurMode->htotal-4) & 0x1f; - - IO_Write(crtc_base,0x05);IO_Write(crtc_base+1,ret_end | (blank_end & 0x20) << 2); - - /* Vertical Total */ - IO_Write(crtc_base,0x06);IO_Write(crtc_base+1,(CurMode->vtotal-2)); - overflow|=((CurMode->vtotal-2) & 0x100) >> 8; - overflow|=((CurMode->vtotal-2) & 0x200) >> 4; - ver_overflow|=((CurMode->vtotal-2) & 0x400) >> 10; - - Bitu vretrace; - if (IS_VGA_ARCH) { - switch (CurMode->vdispend) { - case 400: vretrace=CurMode->vdispend+12; - break; - case 480: vretrace=CurMode->vdispend+10; - break; - case 350: vretrace=CurMode->vdispend+37; - break; - default: vretrace=CurMode->vdispend+12; - } - } else { - switch (CurMode->vdispend) { - case 350: vretrace=CurMode->vdispend; - break; - default: vretrace=CurMode->vdispend+24; - } - } - - /* Vertical Retrace Start */ - IO_Write(crtc_base,0x10);IO_Write(crtc_base+1,vretrace); - overflow|=(vretrace & 0x100) >> 6; - overflow|=(vretrace & 0x200) >> 2; - ver_overflow|=(vretrace & 0x400) >> 6; - - /* Vertical Retrace End */ - IO_Write(crtc_base,0x11);IO_Write(crtc_base+1,(vretrace+2) & 0xF); - - /* Vertical Display End */ - IO_Write(crtc_base,0x12);IO_Write(crtc_base+1,(CurMode->vdispend-1)); - overflow|=((CurMode->vdispend-1) & 0x100) >> 7; - overflow|=((CurMode->vdispend-1) & 0x200) >> 3; - ver_overflow|=((CurMode->vdispend-1) & 0x400) >> 9; - - Bitu vblank_trim; - if (IS_VGA_ARCH) { - switch (CurMode->vdispend) { - case 400: vblank_trim=6; - break; - case 480: vblank_trim=7; - break; - case 350: vblank_trim=5; - break; - default: vblank_trim=8; - } - } else { - switch (CurMode->vdispend) { - case 350: vblank_trim=0; - break; - default: vblank_trim=23; - } - } - - /* Vertical Blank Start */ - IO_Write(crtc_base,0x15);IO_Write(crtc_base+1,(CurMode->vdispend+vblank_trim)); - overflow|=((CurMode->vdispend+vblank_trim) & 0x100) >> 5; - max_scanline|=((CurMode->vdispend+vblank_trim) & 0x200) >> 4; - ver_overflow|=((CurMode->vdispend+vblank_trim) & 0x400) >> 8; - - /* Vertical Blank End */ - IO_Write(crtc_base,0x16);IO_Write(crtc_base+1,(CurMode->vtotal-vblank_trim-2)); - - /* Line Compare */ - Bitu line_compare=(CurMode->vtotal < 1024) ? 1023 : 2047; - IO_Write(crtc_base,0x18);IO_Write(crtc_base+1,line_compare&0xff); - overflow|=(line_compare & 0x100) >> 4; - max_scanline|=(line_compare & 0x200) >> 3; - ver_overflow|=(line_compare & 0x400) >> 4; - Bit8u underline=0; - /* Maximum scanline / Underline Location */ - if (CurMode->special & _EGA_LINE_DOUBLE) { - if (machine!=MCH_EGA) max_scanline|=0x80; - } - switch (CurMode->type) { - case M_TEXT: - max_scanline|=CurMode->cheight-1; - underline=mono_mode ? 0x0f : 0x1f; // mode 7 uses a diff underline position - break; - case M_VGA: - underline=0x40; - max_scanline|=1; //Vga doesn't use double line but this - break; - case M_LIN8: - case M_LIN15: - case M_LIN16: - case M_LIN32: - underline=0x60; //Seems to enable the every 4th clock on my s3 - break; - case M_CGA2: - case M_CGA4: - max_scanline|=1; - break; - } - if (CurMode->vdispend==350) underline=0x0f; - - IO_Write(crtc_base,0x09);IO_Write(crtc_base+1,max_scanline); - IO_Write(crtc_base,0x14);IO_Write(crtc_base+1,underline); - - /* OverFlow */ - IO_Write(crtc_base,0x07);IO_Write(crtc_base+1,overflow); - - if (svgaCard == SVGA_S3Trio) { - /* Extended Horizontal Overflow */ - IO_Write(crtc_base,0x5d);IO_Write(crtc_base+1,hor_overflow); - /* Extended Vertical Overflow */ - IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1,ver_overflow); - } - - /* Offset Register */ - Bitu offset; - switch (CurMode->type) { - case M_LIN8: - offset = CurMode->swidth/8; - break; - case M_LIN15: - case M_LIN16: - offset = 2 * CurMode->swidth/8; - break; - case M_LIN32: - offset = 4 * CurMode->swidth/8; - break; - default: - offset = CurMode->hdispend/2; - } - IO_Write(crtc_base,0x13); - IO_Write(crtc_base + 1,offset & 0xff); - - if (svgaCard == SVGA_S3Trio) { - /* Extended System Control 2 Register */ - /* This register actually has more bits but only use the extended offset ones */ - IO_Write(crtc_base,0x51); - IO_Write(crtc_base + 1,(offset & 0x300) >> 4); - /* Clear remaining bits of the display start */ - IO_Write(crtc_base,0x69); - IO_Write(crtc_base + 1,0); - /* Extended Vertical Overflow */ - IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1,ver_overflow); - } - - /* Mode Control */ - Bit8u mode_control=0; - - switch (CurMode->type) { - case M_CGA2: - mode_control=0xc2; // 0x06 sets address wrap. - break; - case M_CGA4: - mode_control=0xa2; - break; - case M_LIN4: - case M_EGA: - if (CurMode->mode==0x11) // 0x11 also sets address wrap. thought maybe all 2 color modes did but 0x0f doesn't. - mode_control=0xc3; // so.. 0x11 or 0x0f a one off? - else { - if (machine==MCH_EGA) { - if (CurMode->special & _EGA_LINE_DOUBLE) mode_control=0xc3; - else mode_control=0x8b; - } else { - mode_control=0xe3; - } - } - break; - case M_TEXT: - case M_VGA: - case M_LIN8: - case M_LIN15: - case M_LIN16: - case M_LIN32: - mode_control=0xa3; - if (CurMode->special & _VGA_PIXEL_DOUBLE) - mode_control |= 0x08; - break; - } - - IO_Write(crtc_base,0x17);IO_Write(crtc_base+1,mode_control); - /* Renable write protection */ - IO_Write(crtc_base,0x11); - IO_Write(crtc_base+1,IO_Read(crtc_base+1)|0x80); - - if (svgaCard == SVGA_S3Trio) { - /* Setup the correct clock */ - if (CurMode->mode>=0x100) { - misc_output|=0xef; //Select clock 3 - Bitu clock=CurMode->vtotal*8*CurMode->htotal*70; - VGA_SetClock(3,clock/1000); - } - Bit8u misc_control_2; - /* Setup Pixel format */ - switch (CurMode->type) { - case M_LIN8: - misc_control_2=0x00; - break; - case M_LIN15: - misc_control_2=0x30; - break; - case M_LIN16: - misc_control_2=0x50; - break; - case M_LIN32: - misc_control_2=0xd0; - break; - default: - misc_control_2=0x0; - break; - } - IO_WriteB(crtc_base,0x67);IO_WriteB(crtc_base+1,misc_control_2); - } - - /* Write Misc Output */ - IO_Write(0x3c2,misc_output); - /* Program Graphics controller */ - Bit8u gfx_data[GFX_REGS]; - memset(gfx_data,0,GFX_REGS); - gfx_data[0x7]=0xf; /* Color don't care */ - gfx_data[0x8]=0xff; /* BitMask */ - switch (CurMode->type) { - case M_TEXT: - gfx_data[0x5]|=0x10; //Odd-Even Mode - gfx_data[0x6]|=mono_mode ? 0x0a : 0x0e; //Either b800 or b000 - break; - case M_LIN8: - case M_LIN15: - case M_LIN16: - case M_LIN32: - case M_VGA: - gfx_data[0x5]|=0x40; //256 color mode - gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff - break; - case M_LIN4: - case M_EGA: - gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff - break; - case M_CGA4: - gfx_data[0x5]|=0x20; //CGA mode - gfx_data[0x6]|=0x0f; //graphics mode at at 0xb800=0xbfff - if (machine==MCH_EGA) gfx_data[0x5]|=0x10; - break; - case M_CGA2: - if (machine==MCH_EGA) { - gfx_data[0x6]|=0x0d; //graphics mode at at 0xb800=0xbfff - } else { - gfx_data[0x6]|=0x0f; //graphics mode at at 0xb800=0xbfff - } - break; - } - for (i=0;itype) { - case M_EGA: - case M_LIN4: - att_data[0x10]=0x01; //Color Graphics - switch (CurMode->mode) { - case 0x0f: - att_data[0x10]|=0x0a; //Monochrome - att_data[0x01]=0x08; - att_data[0x04]=0x18; - att_data[0x05]=0x18; - att_data[0x09]=0x08; - att_data[0x0d]=0x18; - break; - case 0x11: - for (i=1;i<16;i++) att_data[i]=0x3f; - break; - case 0x10: - case 0x12: - goto att_text16; - default: - if ( CurMode->type == M_LIN4 ) - goto att_text16; - for (i=0;i<8;i++) { - att_data[i]=i; - att_data[i+8]=i+0x10; - } - break; - } - break; - case M_TANDY16: - att_data[0x10]=0x01; //Color Graphics - for (i=0;i<16;i++) att_data[i]=i; - break; - case M_TEXT: - if (machine==MCH_EGA) { - att_data[0x13]=0x00; - att_data[0x10]=0x08; //8 Bit characters - } else { - att_data[0x13]=0x08; //Pel panning on 8, although we don't have 9 dot text mode - att_data[0x10]=0x0C; //Color Text with blinking - } - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30); -att_text16: - if (CurMode->mode==7) { - att_data[0]=0x00; - att_data[8]=0x10; - for (i=1; i<8; i++) { - att_data[i]=0x08; - att_data[i+8]=0x18; - } - } else { - for (i=0;i<8;i++) { - att_data[i]=i; - att_data[i+8]=i+0x38; - } - if (IS_VGA_ARCH) att_data[0x06]=0x14; //Odd Color 6 yellow/brown. - } - break; - case M_CGA2: - att_data[0x10]=0x01; //Color Graphics - att_data[0]=0x0; - for (i=1;i<0x10;i++) att_data[i]=0x17; - att_data[0x12]=0x1; //Only enable 1 plane - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x3f); - break; - case M_CGA4: - att_data[0x10]=0x01; //Color Graphics - att_data[0]=0x0; - att_data[1]=0x13; - att_data[2]=0x15; - att_data[3]=0x17; - att_data[4]=0x02; - att_data[5]=0x04; - att_data[6]=0x06; - att_data[7]=0x07; - for (i=0x8;i<0x10;i++) - att_data[i] = i + 0x8; - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30); - break; - case M_VGA: - case M_LIN8: - case M_LIN15: - case M_LIN16: - case M_LIN32: - for (i=0;i<16;i++) att_data[i]=i; - att_data[0x10]=0x41; //Color Graphics 8-bit - break; - } - IO_Read(mono_mode ? 0x3ba : 0x3da); - if ((modeset_ctl & 8)==0) { - for (i=0;itype) { - case M_EGA: - if (CurMode->mode>0xf) { - goto dac_text16; - } else if (CurMode->mode==0xf) { - for (i=0;i<64;i++) { - IO_Write(0x3c9,mtext_s3_palette[i][0]); - IO_Write(0x3c9,mtext_s3_palette[i][1]); - IO_Write(0x3c9,mtext_s3_palette[i][2]); - } - } else { - for (i=0;i<64;i++) { - IO_Write(0x3c9,ega_palette[i][0]); - IO_Write(0x3c9,ega_palette[i][1]); - IO_Write(0x3c9,ega_palette[i][2]); - } - } - break; - case M_CGA2: - case M_CGA4: - case M_TANDY16: - for (i=0;i<64;i++) { - IO_Write(0x3c9,cga_palette_2[i][0]); - IO_Write(0x3c9,cga_palette_2[i][1]); - IO_Write(0x3c9,cga_palette_2[i][2]); - } - break; - case M_TEXT: - if (CurMode->mode==7) { - if ((IS_VGA_ARCH) && (svgaCard == SVGA_S3Trio)) { - for (i=0;i<64;i++) { - IO_Write(0x3c9,mtext_s3_palette[i][0]); - IO_Write(0x3c9,mtext_s3_palette[i][1]); - IO_Write(0x3c9,mtext_s3_palette[i][2]); - } - } else { - for (i=0;i<64;i++) { - IO_Write(0x3c9,mtext_palette[i][0]); - IO_Write(0x3c9,mtext_palette[i][1]); - IO_Write(0x3c9,mtext_palette[i][2]); - } - } - break; - } //FALLTHROUGH!!!! - case M_LIN4: //Added for CAD Software -dac_text16: - for (i=0;i<64;i++) { - IO_Write(0x3c9,text_palette[i][0]); - IO_Write(0x3c9,text_palette[i][1]); - IO_Write(0x3c9,text_palette[i][2]); - } - break; - case M_VGA: - case M_LIN8: - case M_LIN15: - case M_LIN16: - case M_LIN32: - for (i=0;i<256;i++) { - IO_Write(0x3c9,vga_palette[i][0]); - IO_Write(0x3c9,vga_palette[i][1]); - IO_Write(0x3c9,vga_palette[i][2]); - } - break; - } - if (IS_VGA_ARCH) { - /* check if gray scale summing is enabled */ - if (real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL) & 2) { - INT10_PerformGrayScaleSumming(0,256); - } - } - } else { - for (i=0x10;itype) { - case M_CGA2: - feature=(feature&~0x30)|0x20; - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x1e); - break; - case M_CGA4: - feature=(feature&~0x30)|0x20; - if (CurMode->mode==4) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2a); - else if (CurMode->mode==5) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2e); - else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2); - break; - case M_TANDY16: - feature=(feature&~0x30)|0x20; - break; - case M_TEXT: - feature=(feature&~0x30)|0x20; - switch (CurMode->mode) { - case 0:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2c);break; - case 1:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x28);break; - case 2:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2d);break; - case 3: - case 7:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x29);break; - } - break; - case M_LIN4: - case M_EGA: - case M_VGA: - feature=(feature&~0x30); - break; - } - // disabled, has to be set in bios.cpp exclusively -// real_writeb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE,feature); - - if (svgaCard == SVGA_S3Trio) { - /* Setup the CPU Window */ - IO_Write(crtc_base,0x6a); - IO_Write(crtc_base+1,0); - /* Setup the linear frame buffer */ - IO_Write(crtc_base,0x59); - IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 24)); - IO_Write(crtc_base,0x5a); - IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 16)); - IO_Write(crtc_base,0x6b); // BIOS scratchpad - IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 24)); - - /* Setup some remaining S3 registers */ - IO_Write(crtc_base,0x41); // BIOS scratchpad - IO_Write(crtc_base+1,0x88); - IO_Write(crtc_base,0x52); // extended BIOS scratchpad - IO_Write(crtc_base+1,0x80); - - IO_Write(0x3c4,0x15); - IO_Write(0x3c5,0x03); - - // Accellerator setup - Bitu reg_50=S3_XGA_8BPP; - switch (CurMode->type) { - case M_LIN15: - case M_LIN16: reg_50|=S3_XGA_16BPP; break; - case M_LIN32: reg_50|=S3_XGA_32BPP; break; - default: break; - } - switch(CurMode->swidth) { - case 640: reg_50|=S3_XGA_640; break; - case 800: reg_50|=S3_XGA_800; break; - case 1024: reg_50|=S3_XGA_1024; break; - case 1152: reg_50|=S3_XGA_1152; break; - case 1280: reg_50|=S3_XGA_1280; break; - default: break; - } - IO_WriteB(crtc_base,0x50); IO_WriteB(crtc_base+1,reg_50); - - Bitu reg_31, reg_3a; - switch (CurMode->type) { - case M_LIN15: - case M_LIN16: - case M_LIN32: - reg_3a=0x15; - break; - case M_LIN8: - // S3VBE20 does it this way. The other double pixel bit does not - // seem to have an effect on the Trio64. - if(CurMode->special&_VGA_PIXEL_DOUBLE) reg_3a=0x5; - else reg_3a=0x15; - break; - default: - reg_3a=5; - break; - }; - - switch (CurMode->type) { - case M_LIN4: // <- Theres a discrepance with real hardware on this - case M_LIN8: - case M_LIN15: - case M_LIN16: - case M_LIN32: - reg_31 = 9; - break; - default: - reg_31 = 5; - break; - } - IO_Write(crtc_base,0x3a);IO_Write(crtc_base+1,reg_3a); - IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,reg_31); //Enable banked memory and 256k+ access - IO_Write(crtc_base,0x58);IO_Write(crtc_base+1,0x3); //Enable 8 mb of linear addressing - - IO_Write(crtc_base,0x38);IO_Write(crtc_base+1,0x48); //Register lock 1 - IO_Write(crtc_base,0x39);IO_Write(crtc_base+1,0xa5); //Register lock 2 - } else if (svga.set_video_mode) { - VGA_ModeExtraData modeData; - modeData.ver_overflow = ver_overflow; - modeData.hor_overflow = hor_overflow; - modeData.offset = offset; - modeData.modeNo = CurMode->mode; - modeData.htotal = CurMode->htotal; - modeData.vtotal = CurMode->vtotal; - svga.set_video_mode(crtc_base, &modeData); - } - - FinishSetMode(clearmem); - /* Load text mode font */ - if (CurMode->type==M_TEXT) { - if (IS_VGA_ARCH) INT10_LoadFont(Real2Phys(int10.rom.font_16),true,256,0,0,16); - else INT10_LoadFont(Real2Phys(int10.rom.font_14),true,256,0,0,14); - } - return true; -} - -Bitu VideoModeMemSize(Bitu mode) { - if (!IS_VGA_ARCH) - return 0; - - VideoModeBlock* modelist = NULL; - - switch (svgaCard) { - case SVGA_TsengET4K: - case SVGA_TsengET3K: - modelist = ModeList_VGA_Tseng; - break; - case SVGA_ParadisePVGA1A: - modelist = ModeList_VGA_Paradise; - break; - default: - modelist = ModeList_VGA; - break; - } - - VideoModeBlock* vmodeBlock = NULL; - Bitu i=0; - while (modelist[i].mode!=0xffff) { - if (modelist[i].mode==mode) { - vmodeBlock = &modelist[i]; - break; - } - i++; - } - if (!vmodeBlock) - return 0; - - switch(vmodeBlock->type) { - case M_LIN4: - return vmodeBlock->swidth*vmodeBlock->sheight/2; - case M_LIN8: - return vmodeBlock->swidth*vmodeBlock->sheight; - case M_LIN15: case M_LIN16: - return vmodeBlock->swidth*vmodeBlock->sheight*2; - case M_LIN32: - return vmodeBlock->swidth*vmodeBlock->sheight*4; - case M_TEXT: - return vmodeBlock->twidth*vmodeBlock->theight*2; - } - // Return 0 for all other types, those always fit in memory - return 0; -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "mem.h" +#include "inout.h" +#include "int10.h" + +//TODO Maybe also add PCJR Video Modes could be nice :) +//TODO include some credits to bochs/plex86 bios i used for info/tables + +VGAMODES vga_modes[MODE_MAX+1]= +{//mode vesa class model pg bits sw sh tw th cw ch sstart slength misc pelm crtc actl gdc sequ dac + {0x00, 0xFFFF, TEXT, CTEXT, 8, 4, 360, 400, 40, 25, 9, 16, 0xB800, 0x0800, 0x67, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x01, 0xFFFF, TEXT, CTEXT, 8, 4, 360, 400, 40, 25, 9, 16, 0xB800, 0x0800, 0x67, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x02, 0xFFFF, TEXT, CTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB800, 0x1000, 0x67, 0xFF, 0x01, 0x00, 0x00, 0x01, 0x02}, + {0x03, 0xFFFF, TEXT, CTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB800, 0x1000, 0x67, 0xFF, 0x01, 0x00, 0x00, 0x01, 0x02}, + {0x04, 0xFFFF, GRAPH, CGA, 4, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01}, + {0x05, 0xFFFF, GRAPH, CGA, 1, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01}, + {0x06, 0xFFFF, GRAPH, CGA, 1, 1, 640, 200, 80, 25, 8, 8, 0xB800, 0x1000, 0x63, 0xFF, 0x03, 0x02, 0x02, 0x03, 0x01}, + {0x07, 0xFFFF, TEXT, MTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB000, 0x1000, 0x66, 0xFF, 0x04, 0x03, 0x03, 0x01, 0x00}, + {0x0D, 0xFFFF, GRAPH, PLANAR4, 8, 4, 320, 200, 40, 25, 8, 8, 0xA000, 0x0000, 0x63, 0xFF, 0x05, 0x04, 0x04, 0x04, 0x01}, + {0x0E, 0xFFFF, GRAPH, PLANAR4, 4, 4, 640, 200, 80, 25, 8, 8, 0xA000, 0x0000, 0x63, 0xFF, 0x06, 0x04, 0x04, 0x05, 0x01}, + {0x0F, 0xFFFF, GRAPH, PLANAR2, 2, 2, 640, 350, 80, 25, 8, 14, 0xA000, 0x0000, 0xa2, 0xFF, 0x07, 0x05, 0x04, 0x05, 0x00}, + {0x10, 0xFFFF, GRAPH, PLANAR4, 2, 4, 640, 350, 80, 25, 8, 14, 0xA000, 0x0000, 0xa3, 0xFF, 0x07, 0x06, 0x04, 0x05, 0x02}, + {0x11, 0xFFFF, GRAPH, PLANAR1, 1, 1, 640, 480, 80, 30, 8, 16, 0xA000, 0x0000, 0xe3, 0xFF, 0x08, 0x07, 0x04, 0x05, 0x02}, + {0x12, 0xFFFF, GRAPH, PLANAR4, 1, 4, 640, 480, 80, 30, 8, 16, 0xA000, 0x0000, 0xe3, 0xFF, 0x08, 0x06, 0x04, 0x05, 0x02}, + {0x13, 0xFFFF, GRAPH, LINEAR8, 1, 8, 320, 200, 40, 25, 8, 8, 0xA000, 0x0000, 0x63, 0xFF, 0x09, 0x08, 0x05, 0x06, 0x03} +}; + +/* CRTC */ +#define CRTC_MAX_REG 0x18 +#define CRTC_MAX_MODEL 0x09 +static Bit8u crtc_access[CRTC_MAX_REG+1]= +{ /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 */ + 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 +}; +static Bit8u crtc_regs[CRTC_MAX_MODEL+1][CRTC_MAX_REG+1]= +{/* Model 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 */ + /* 00 */ 0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,0xff, + /* 01 */ 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff, + /* 02 */ 0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,0xff, + /* 03 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,0xff, + /* 04 */ 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,0xff, + /* 05 */ 0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,0xff, + /* 06 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,0xff, + /* 07 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x85,0x5d,0x28,0x0f,0x63,0xba,0xe3,0xff, + /* 08 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0xea,0x8c,0xdf,0x28,0x00,0xe7,0x04,0xe3,0xff, + /* 09 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,0xff +}; + +/* Attribute Controler 0x3c0 */ +#define ACTL_MAX_REG 0x14 +#define ACTL_MAX_MODEL 0x08 + +static Bit8u actl_access[ACTL_MAX_REG+1]= +{/* 00 01 02 03 04 05 06 07 08 09 0A 0B OC OD OE OF 10 11 12 13 14 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +static Bit8u actl_regs[ACTL_MAX_MODEL+1][ACTL_MAX_REG+1]= +{/* Model 00 01 02 03 04 05 06 07 08 09 0A 0B OC OD OE OF 10 11 12 13 14 */ + /* 00 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x0c,0x00,0x0f,0x08,0x00, + /* 01 */ 0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x01,0x00,0x03,0x00,0x00, + /* 02 */ 0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x01,0x00,0x01,0x00,0x00, + /* 03 */ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x0e,0x00,0x0f,0x08,0x00, + /* 04 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x01,0x00,0x0f,0x00,0x00, + /* 05 */ 0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x0b,0x00,0x05,0x00,0x00, + /* 06 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x01,0x00,0x0f,0x00,0x00, + /* 07 */ 0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x01,0x00,0x01,0x00,0x00, + /* 08 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x41,0x00,0x0f,0x00,0x00 +}; + +/* Sequencer 0x3c4 */ +#define SEQU_MAX_REG 0x04 +#define SEQU_MAX_MODEL 0x06 + +static Bit8u sequ_access[SEQU_MAX_REG+1]= +{ /* 00 01 02 03 04 */ + 0x00,0x00,0x00,0x00,0x00 +}; + +static Bit8u sequ_regs[SEQU_MAX_MODEL+1][SEQU_MAX_REG+1]= +{/* Model 00 01 02 03 04 */ + /* 00 */ 0x03,0x08,0x03,0x00,0x02, + /* 01 */ 0x03,0x00,0x03,0x00,0x02, + /* 02 */ 0x03,0x09,0x03,0x00,0x02, + /* 03 */ 0x03,0x01,0x01,0x00,0x06, + /* 04 */ 0x03,0x09,0x0f,0x00,0x06, + /* 05 */ 0x03,0x01,0x0f,0x00,0x06, + /* 06 */ 0x03,0x01,0x0f,0x00,0x0e +}; + +/* Graphic ctl 0x3ce */ +#define GRDC_MAX_REG 0x08 +#define GRDC_MAX_MODEL 0x05 + +static Bit8u grdc_access[GRDC_MAX_REG+1]= +{ /* 00 01 02 03 04 05 06 07 08 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +static Bit8u grdc_regs[GRDC_MAX_MODEL+1][GRDC_MAX_REG+1]= +{/* Model 00 01 02 03 04 05 06 07 08 */ + /* 00 */ 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x0f,0xff, + /* 01 */ 0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x0f,0xff, + /* 02 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x0f,0xff, + /* 03 */ 0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x0f,0xff, + /* 04 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,0xff, + /* 05 */ 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,0xff +}; + +/* Default Palette */ +#define DAC_MAX_MODEL 3 + +static Bit8u dac_regs[DAC_MAX_MODEL+1]= +{0x3f,0x3f,0x3f,0xff}; + +/* Mono */ +static Bit8u palette0[63+1][3]= +{ + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, + 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, + 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f +}; + +static Bit8u palette1[63+1][3]= +{ + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f +}; + +static Bit8u palette2[63+1][3]= +{ + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a, + 0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f, 0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f, + 0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a, 0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a, + 0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f, 0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f, + 0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a, 0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a, + 0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f, 0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f, + 0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a, 0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f +}; + +static Bit8u palette3[256][3]= +{ + 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, + 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, + 0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b, 0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18, + 0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28, 0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f, + 0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f, 0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10, + 0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00, 0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00, + 0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f, 0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f, + 0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f, 0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27, + + 0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f, 0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f, + 0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37, 0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f, + 0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f, 0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31, + 0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d, 0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d, + 0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a, 0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f, + 0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c, 0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07, + 0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00, 0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00, + 0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15, 0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c, + + 0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c, 0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11, + 0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e, 0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e, + 0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18, 0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c, + 0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c, 0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16, + 0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14, 0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14, + 0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a, 0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c, + 0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10, 0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04, + 0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00, 0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00, + + 0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c, 0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10, + 0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10, 0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a, + 0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08, 0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08, + 0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e, 0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10, + 0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10, 0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c, + 0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b, 0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b, + 0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f, 0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00 +}; + +static Bit8u static_functionality[0x10]= +{ + /* 0 */ 0xff, // All modes supported #1 + /* 1 */ 0xff, // All modes supported #2 + /* 2 */ 0x0f, // All modes supported #3 + /* 3 */ 0x00, 0x00, 0x00, 0x00, // reserved + /* 7 */ 0x07, // 200, 350, 400 scan lines + /* 8 */ 0xFF, // FIXME i don't know what this is + /* 9 */ 0xFF, // FIXME i don't know what this is + /* a */ 0xe3, // Change to add new functions + /* b */ 0x0c, // Change to add new functions + /* c */ 0x00, // reserved + /* d */ 0x00, // reserved + /* e */ 0x00, // Change to add new functions + /* f */ 0x00 // reserved +}; + +static Bit8u FindVideoMode(Bit8u mode) { + Bit8u line=0xff; + for(Bit8u i=0;i<=MODE_MAX;i++) { + if(vga_modes[i].svgamode==mode) { + line=i; + break; + } + } + return line; + +} + +VGAMODES * GetCurrentMode(void) { + Bit8u ret=FindVideoMode(real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)&127); + if (ret==0xff) return 0; + return &vga_modes[ret]; +} + + +void INT10_SetVideoMode(Bit8u mode) { + + bool clearmem=(mode & 128)==0; + Bit8u *palette; + Bit16u i,twidth,theight,cheight; + Bit8u modeset_ctl,video_ctl,vga_switches; + Bit16u crtc_addr; + Bit8u line; + + mode&=mode & 127; + line=FindVideoMode(mode); + if (line==0xff) { + LOG_ERROR("INT10:Trying to set non supported video mode %X",mode); + return; + } + + twidth=vga_modes[line].twidth; + theight=vga_modes[line].theight; + cheight=vga_modes[line].cheight; + + // Read the bios vga control + video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL); + + // Read the bios vga switches + vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES); + + // Read the bios mode set control + modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); + + + if((modeset_ctl&0x08)==0) { + // Set the PEL mask + IO_Write(VGAREG_PEL_MASK,vga_modes[line].pelmask); + // Set the whole dac always, from 0 + IO_Write(VGAREG_DAC_WRITE_ADDRESS,0x00); + // From which palette + switch(vga_modes[line].dacmodel) { + case 0: + palette=(Bit8u*)&palette0; + break; + case 1: + palette=(Bit8u*)&palette1; + break; + case 2: + palette=(Bit8u*)&palette2; + break; + case 3: + palette=(Bit8u*)&palette3; + break; + default: + palette=(Bit8u*)&palette0;/*for gcc*/ + E_Exit("INT10: palette error in setvidmode"); + break; + } + // Set the actual palette + for (i=0;i<256;i++) { + if (i<=dac_regs[vga_modes[line].dacmodel]) { + IO_Write(VGAREG_DAC_DATA,palette[(i*3)+0]); + IO_Write(VGAREG_DAC_DATA,palette[(i*3)+1]); + IO_Write(VGAREG_DAC_DATA,palette[(i*3)+2]); + } else { + IO_Write(VGAREG_DAC_DATA,0); + IO_Write(VGAREG_DAC_DATA,0); + IO_Write(VGAREG_DAC_DATA,0); + } + } + } + + /* Reset Attribute ctl into address mode just to be safe */ + + IO_Read(VGAREG_ACTL_RESET); + // Set Attribute Ctl + for(i=0;i<=ACTL_MAX_REG;i++) { + IO_Write(VGAREG_ACTL_ADDRESS,(Bit8u)i); + IO_Write(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]); + } + // Set Sequencer Ctl + for(i=0;i<=SEQU_MAX_REG;i++) { + IO_Write(VGAREG_SEQU_ADDRESS,(Bit8u)i); + IO_Write(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]); + } + + // Set Grafx Ctl + for(i=0;i<=GRDC_MAX_REG;i++) { + IO_Write(VGAREG_GRDC_ADDRESS,(Bit8u)i); + IO_Write(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]); + } + + // Set CRTC address VGA or MDA + crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS; + // Set CRTC regs + for(i=0;i<=CRTC_MAX_REG;i++) { + IO_Write(crtc_addr,(Bit8u)i); + IO_Write(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]); + } + + // Set the misc register + IO_Write(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg); + + // Enable video + IO_Write(VGAREG_ACTL_ADDRESS,0x20); + IO_Read(VGAREG_ACTL_RESET); + Bit32u tel; + if(clearmem) { + if(vga_modes[line].type==TEXT) { + PhysOff dest=real_phys(vga_modes[line].sstart,0); + for (tel=0;tel<0x4000;tel++) { + mem_writew(dest,0x0720); + dest+=2; + } + } else { + PhysOff dest=real_phys(0xb800,0); + for (tel=0;tel<0x4000;tel++) { + mem_writew(dest,0x0000); + dest+=2; + } + dest=real_phys(0xa000,0); + for (tel=0;tel<0x8000;tel++) { + mem_writew(dest,0x0000); + dest+=2; + } + // FIXME should handle gfx mode + } + } + // Set the BIOS mem + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode|((!clearmem) << 7)); + real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth); + real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength); + real_writew(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr); + real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1); + real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight); + real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem << 7))); + real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9); + real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f); + + // FIXME We nearly have the good tables. to be reworked + real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now + real_writew(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00); + real_writew(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00); + + // FIXME + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but... + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but... + + // Set cursor shape + if(vga_modes[line].type==TEXT) { +//TODO cursor shape biosfn_set_cursor_shape(0x06,0x07); + } + // Set cursor pos for page 0..7 + for(i=0;i<8;i++) INT10_SetCursorPos(0,0,(Bit8u)i); + // Set active page 0 + INT10_SetActivePage(0); + /* Set some interrupt vectors */ + //TODO set 0x43 to the correct font height font + RealSetVec(0x43,int10_romarea.font_8_first); + RealSetVec(0x1F,int10_romarea.font_8_second); + +}; diff --git a/src/ints/int10_pal.cpp b/src/ints/int10_pal.cpp index 65774e1..fee1de1 100644 --- a/src/ints/int10_pal.cpp +++ b/src/ints/int10_pal.cpp @@ -1,284 +1,126 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "dosbox.h" -#include "mem.h" -#include "inout.h" -#include "int10.h" - -#define ACTL_MAX_REG 0x14 - -static INLINE void ResetACTL(void) { - IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6); -} - -static INLINE void WriteTandyACTL(Bit8u creg,Bit8u val) { - IO_Write(VGAREG_TDY_ADDRESS,creg); - if (machine==MCH_TANDY) IO_Write(VGAREG_TDY_DATA,val); - else IO_Write(VGAREG_PCJR_DATA,val); -} - -void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val) { - switch (machine) { - case TANDY_ARCH_CASE: - IO_Read(VGAREG_TDY_RESET); - WriteTandyACTL(reg+0x10,val); - break; - case EGAVGA_ARCH_CASE: - if (!IS_VGA_ARCH) reg&=0x1f; - if(reg<=ACTL_MAX_REG) { - ResetACTL(); - IO_Write(VGAREG_ACTL_ADDRESS,reg); - IO_Write(VGAREG_ACTL_WRITE_DATA,val); - } - IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette - break; - } -} - - -void INT10_SetOverscanBorderColor(Bit8u val) { - switch (machine) { - case TANDY_ARCH_CASE: - IO_Read(VGAREG_TDY_RESET); - WriteTandyACTL(0x02,val); - break; - case EGAVGA_ARCH_CASE: - ResetACTL(); - IO_Write(VGAREG_ACTL_ADDRESS,0x11); - IO_Write(VGAREG_ACTL_WRITE_DATA,val); - IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette - break; - } -} - -void INT10_SetAllPaletteRegisters(PhysPt data) { - switch (machine) { - case TANDY_ARCH_CASE: - IO_Read(VGAREG_TDY_RESET); - // First the colors - for(Bit8u i=0;i<0x10;i++) { - WriteTandyACTL(i+0x10,mem_readb(data)); - data++; - } - // Then the border - WriteTandyACTL(0x02,mem_readb(data)); - break; - case EGAVGA_ARCH_CASE: - ResetACTL(); - // First the colors - for(Bit8u i=0;i<0x10;i++) { - IO_Write(VGAREG_ACTL_ADDRESS,i); - IO_Write(VGAREG_ACTL_WRITE_DATA,mem_readb(data)); - data++; - } - // Then the border - IO_Write(VGAREG_ACTL_ADDRESS,0x11); - IO_Write(VGAREG_ACTL_WRITE_DATA,mem_readb(data)); - IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette - break; - } -} - -void INT10_ToggleBlinkingBit(Bit8u state) { - Bit8u value; -// state&=0x01; - if ((state>1) && (svgaCard==SVGA_S3Trio)) return; - ResetACTL(); - - IO_Write(VGAREG_ACTL_ADDRESS,0x10); - value=IO_Read(VGAREG_ACTL_READ_DATA); - if (state<=1) { - value&=0xf7; - value|=state<<3; - } - - ResetACTL(); - IO_Write(VGAREG_ACTL_ADDRESS,0x10); - IO_Write(VGAREG_ACTL_WRITE_DATA,value); - IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette - - if (state<=1) { - Bit8u msrval=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR)&0xdf; - if (state) msrval|=0x20; - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,msrval); - } -} - -void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val) { - if(reg<=ACTL_MAX_REG) { - ResetACTL(); - IO_Write(VGAREG_ACTL_ADDRESS,reg+32); - *val=IO_Read(VGAREG_ACTL_READ_DATA); - IO_Write(VGAREG_ACTL_WRITE_DATA,*val); - } -} - -void INT10_GetOverscanBorderColor(Bit8u * val) { - ResetACTL(); - IO_Write(VGAREG_ACTL_ADDRESS,0x11+32); - *val=IO_Read(VGAREG_ACTL_READ_DATA); - IO_Write(VGAREG_ACTL_WRITE_DATA,*val); -} - -void INT10_GetAllPaletteRegisters(PhysPt data) { - ResetACTL(); - // First the colors - for(Bit8u i=0;i<0x10;i++) { - IO_Write(VGAREG_ACTL_ADDRESS,i); - mem_writeb(data,IO_Read(VGAREG_ACTL_READ_DATA)); - ResetACTL(); - data++; - } - // Then the border - IO_Write(VGAREG_ACTL_ADDRESS,0x11+32); - mem_writeb(data,IO_Read(VGAREG_ACTL_READ_DATA)); - ResetACTL(); -} - -void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue) { - IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index); - IO_Write(VGAREG_DAC_DATA,red); - IO_Write(VGAREG_DAC_DATA,green); - IO_Write(VGAREG_DAC_DATA,blue); -} - -void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue) { - IO_Write(VGAREG_DAC_READ_ADDRESS,index); - *red=IO_Read(VGAREG_DAC_DATA); - *green=IO_Read(VGAREG_DAC_DATA); - *blue=IO_Read(VGAREG_DAC_DATA); -} - -void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data) { - IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index); - for (;count>0;count--) { - IO_Write(VGAREG_DAC_DATA,mem_readb(data++)); - IO_Write(VGAREG_DAC_DATA,mem_readb(data++)); - IO_Write(VGAREG_DAC_DATA,mem_readb(data++)); - } -} - -void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data) { - IO_Write(VGAREG_DAC_READ_ADDRESS,(Bit8u)index); - for (;count>0;count--) { - mem_writeb(data++,IO_Read(VGAREG_DAC_DATA)); - mem_writeb(data++,IO_Read(VGAREG_DAC_DATA)); - mem_writeb(data++,IO_Read(VGAREG_DAC_DATA)); - } -} - -void INT10_SelectDACPage(Bit8u function,Bit8u mode) { - ResetACTL(); - IO_Write(VGAREG_ACTL_ADDRESS,0x10); - Bit8u old10=IO_Read(VGAREG_ACTL_READ_DATA); - if (!function) { //Select paging mode - if (mode) old10|=0x80; - else old10&=0x7f; - //IO_Write(VGAREG_ACTL_ADDRESS,0x10); - IO_Write(VGAREG_ACTL_WRITE_DATA,old10); - } else { //Select page - IO_Write(VGAREG_ACTL_WRITE_DATA,old10); - if (!(old10 & 0x80)) mode<<=2; - mode&=0xf; - IO_Write(VGAREG_ACTL_ADDRESS,0x14); - IO_Write(VGAREG_ACTL_WRITE_DATA,mode); - } - IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette -} - -void INT10_GetDACPage(Bit8u* mode,Bit8u* page) { - ResetACTL(); - IO_Write(VGAREG_ACTL_ADDRESS,0x10); - Bit8u reg10=IO_Read(VGAREG_ACTL_READ_DATA); - IO_Write(VGAREG_ACTL_WRITE_DATA,reg10); - *mode=(reg10&0x80)?0x01:0x00; - IO_Write(VGAREG_ACTL_ADDRESS,0x14); - *page=IO_Read(VGAREG_ACTL_READ_DATA); - IO_Write(VGAREG_ACTL_WRITE_DATA,*page); - if(*mode) { - *page&=0xf; - } else { - *page&=0xc; - *page>>=2; - } -} - -void INT10_SetPelMask(Bit8u mask) { - IO_Write(VGAREG_PEL_MASK,mask); -} - -void INT10_GetPelMask(Bit8u & mask) { - mask=IO_Read(VGAREG_PEL_MASK); -} - -void INT10_SetBackgroundBorder(Bit8u val) { - Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL); - temp=(temp & 0xe0) | (val & 0x1f); - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp); - if (machine == MCH_CGA || IS_TANDY_ARCH) - IO_Write(0x3d9,temp); - else if (IS_EGAVGA_ARCH) { - val = ((val << 1) & 0x10) | (val & 0x7); - /* Aways set the overscan color */ - INT10_SetSinglePaletteRegister( 0x11, val ); - /* Don't set any extra colors when in text mode */ - if (CurMode->mode <= 3) - return; - INT10_SetSinglePaletteRegister( 0, val ); - val = (temp & 0x10) | 2 | ((temp & 0x20) >> 5); - INT10_SetSinglePaletteRegister( 1, val ); - val+=2; - INT10_SetSinglePaletteRegister( 2, val ); - val+=2; - INT10_SetSinglePaletteRegister( 3, val ); - } -} - -void INT10_SetColorSelect(Bit8u val) { - Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL); - temp=(temp & 0xdf) | ((val & 1) ? 0x20 : 0x0); - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp); - if (machine == MCH_CGA || IS_TANDY_ARCH) - IO_Write(0x3d9,temp); - else if (IS_EGAVGA_ARCH) { - if (CurMode->mode <= 3) //Maybe even skip the total function! - return; - val = (temp & 0x10) | 2 | val; - INT10_SetSinglePaletteRegister( 1, val ); - val+=2; - INT10_SetSinglePaletteRegister( 2, val ); - val+=2; - INT10_SetSinglePaletteRegister( 3, val ); - } -} - -void INT10_PerformGrayScaleSumming(Bit16u start_reg,Bit16u count) { - if (count>0x100) count=0x100; - for (Bitu ct=0; ct> 8; - Bit8u ic=(i>0x3f) ? 0x3f : ((Bit8u)(i & 0xff)); - INT10_SetSingleDacRegister(start_reg+ct,ic,ic,ic); - } -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "mem.h" +#include "inout.h" +#include "int10.h" + +#define ACTL_MAX_REG 0x14 + +void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val) { + if(reg<=ACTL_MAX_REG) { + IO_Read(VGAREG_ACTL_RESET); + IO_Write(VGAREG_ACTL_ADDRESS,reg); + IO_Write(VGAREG_ACTL_WRITE_DATA,val); + } +} + + +void INT10_SetOverscanBorderColor(Bit8u val) { + IO_Read(VGAREG_ACTL_RESET); + IO_Write(VGAREG_ACTL_ADDRESS,0x11); + IO_Write(VGAREG_ACTL_WRITE_DATA,val); +} + +void INT10_SetAllPaletteRegisters(PhysOff data) { + IO_Read(VGAREG_ACTL_RESET); + // First the colors + for(Bit8u i=0;i<0x10;i++) { + IO_Write(VGAREG_ACTL_ADDRESS,i); + IO_Write(VGAREG_ACTL_WRITE_DATA,mem_readb(data)); + data++; + } + // Then the border + IO_Write(VGAREG_ACTL_ADDRESS,0x11); + IO_Write(VGAREG_ACTL_WRITE_DATA,mem_readb(data)); +} + +void INT10_ToggleBlinkingBit(Bit8u state) { + Bit8u value; + state&=0x01; + IO_Read(VGAREG_ACTL_RESET); + + IO_Write(VGAREG_ACTL_ADDRESS,0x10); + value=IO_Read(VGAREG_ACTL_READ_DATA); + value&=0xf7; + value|=state<<3; + + IO_Read(VGAREG_ACTL_RESET); + IO_Write(VGAREG_ACTL_ADDRESS,0x10); + IO_Write(VGAREG_ACTL_WRITE_DATA,value); +} + +void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val) { + if(reg<=ACTL_MAX_REG) { + IO_Read(VGAREG_ACTL_RESET); + IO_Write(VGAREG_ACTL_ADDRESS,reg); + *val=IO_Read(VGAREG_ACTL_READ_DATA); + } +} + +void INT10_GetOverscanBorderColor(Bit8u * val) { + IO_Read(VGAREG_ACTL_RESET); + IO_Write(VGAREG_ACTL_ADDRESS,0x11); + *val=IO_Read(VGAREG_ACTL_READ_DATA); +} + +void INT10_GetAllPaletteRegisters(PhysOff data) { + IO_Read(VGAREG_ACTL_RESET); + // First the colors + for(Bit8u i=0;i<0x10;i++) { + IO_Write(VGAREG_ACTL_ADDRESS,i); + mem_writeb(data,IO_Read(VGAREG_ACTL_READ_DATA)); + data++; + } + // Then the border + IO_Write(VGAREG_ACTL_ADDRESS,0x11); + mem_writeb(data,IO_Read(VGAREG_ACTL_READ_DATA)); +} + +void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue) { + IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index); + IO_Write(VGAREG_DAC_DATA,red); + IO_Write(VGAREG_DAC_DATA,green); + IO_Write(VGAREG_DAC_DATA,blue); +} + +void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue) { + IO_Write(VGAREG_DAC_READ_ADDRESS,index); + *red=IO_Read(VGAREG_DAC_DATA); + *green=IO_Read(VGAREG_DAC_DATA); + *blue=IO_Read(VGAREG_DAC_DATA); +} + +void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysOff data) { + IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index); + for (;count>0;count--) { + IO_Write(VGAREG_DAC_DATA,mem_readb(data++)); + IO_Write(VGAREG_DAC_DATA,mem_readb(data++)); + IO_Write(VGAREG_DAC_DATA,mem_readb(data++)); + } +} + +void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysOff data) { + IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index); + for (;count>0;count--) { + mem_writeb(data++,IO_Read(VGAREG_DAC_DATA)); + mem_writeb(data++,IO_Read(VGAREG_DAC_DATA)); + mem_writeb(data++,IO_Read(VGAREG_DAC_DATA)); + } +}; diff --git a/src/ints/int10_put_pixel.cpp b/src/ints/int10_put_pixel.cpp index 2f3428e..5d6ce9f 100644 --- a/src/ints/int10_put_pixel.cpp +++ b/src/ints/int10_put_pixel.cpp @@ -1,200 +1,91 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: int10_put_pixel.cpp,v 1.22 2008/08/06 18:32:35 c2woody Exp $ */ - -#include "dosbox.h" -#include "mem.h" -#include "inout.h" -#include "int10.h" - -static Bit8u cga_masks[4]={0x3f,0xcf,0xf3,0xfc}; -static Bit8u cga_masks2[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; - -void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { - static bool putpixelwarned = false; - - switch (CurMode->type) { - case M_CGA4: - { - if (real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)<=5) { - Bit16u off=(y>>1)*80+(x>>2); - if (y&1) off+=8*1024; - - Bit8u old=real_readb(0xb800,off); - if (color & 0x80) { - color&=3; - old^=color << (2*(3-(x&3))); - } else { - old=(old&cga_masks[x&3])|((color&3) << (2*(3-(x&3)))); - } - real_writeb(0xb800,off,old); - } else { - Bit16u off=(y>>2)*160+((x>>2)&(~1)); - off+=(8*1024) * (y & 3); - - Bit16u old=real_readw(0xb800,off); - if (color & 0x80) { - old^=(color&1) << (7-(x&7)); - old^=((color&2)>>1) << ((7-(x&7))+8); - } else { - old=(old&(~(0x101<<(7-(x&7))))) | ((color&1) << (7-(x&7))) | (((color&2)>>1) << ((7-(x&7))+8)); - } - real_writew(0xb800,off,old); - } - } - break; - case M_CGA2: - { - Bit16u off=(y>>1)*80+(x>>3); - if (y&1) off+=8*1024; - Bit8u old=real_readb(0xb800,off); - if (color & 0x80) { - color&=1; - old^=color << ((7-(x&7))); - } else { - old=(old&cga_masks2[x&7])|((color&1) << ((7-(x&7)))); - } - real_writeb(0xb800,off,old); - } - break; - case M_TANDY16: - { - IO_Write(0x3d4,0x09); - Bit8u scanlines_m1=IO_Read(0x3d5); - Bit16u off=(y>>((scanlines_m1==1)?1:2))*(CurMode->swidth>>1)+(x>>1); - off+=(8*1024) * (y & scanlines_m1); - Bit8u old=real_readb(0xb800,off); - Bit8u p[2]; - p[1] = (old >> 4) & 0xf; - p[0] = old & 0xf; - Bitu ind = 1-(x & 0x1); - - if (color & 0x80) { - p[ind]^=(color & 0x7f); - } else { - p[ind]=color; - } - old = (p[1] << 4) | p[0]; - real_writeb(0xb800,off,old); - } - break; - case M_EGA: - { - /* Set the correct bitmask for the pixel position */ - IO_Write(0x3ce,0x8);Bit8u mask=128>>(x&7);IO_Write(0x3cf,mask); - /* Set the color to set/reset register */ - IO_Write(0x3ce,0x0);IO_Write(0x3cf,color); - /* Enable all the set/resets */ - IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf); - /* test for xorring */ - if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x18); } - //Perhaps also set mode 1 - /* Calculate where the pixel is in video memory */ - if (CurMode->plength!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)) - LOG(LOG_INT10,LOG_ERROR)("PutPixel_EGA_p: %x!=%x",CurMode->plength,real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); - if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8) - LOG(LOG_INT10,LOG_ERROR)("PutPixel_EGA_w: %x!=%x",CurMode->swidth,real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8); - PhysPt off=0xa0000+real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page+ - ((y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8+x)>>3); - /* Bitmask and set/reset should do the rest */ - mem_readb(off); - mem_writeb(off,0xff); - /* Restore bitmask */ - IO_Write(0x3ce,0x8);IO_Write(0x3cf,0xff); - IO_Write(0x3ce,0x1);IO_Write(0x3cf,0); - /* Restore write operating if changed */ - if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x0); } - break; - } - - case M_VGA: - mem_writeb(PhysMake(0xa000,y*320+x),color); - break; - case M_LIN8: { - if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8) - LOG(LOG_INT10,LOG_ERROR)("PutPixel_VGA_w: %x!=%x",CurMode->swidth,real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8); - PhysPt off=S3_LFB_BASE+y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8+x; - mem_writeb(off,color); - break; - } - default: - if(GCC_UNLIKELY(!putpixelwarned)) { - putpixelwarned = true; - LOG(LOG_INT10,LOG_ERROR)("PutPixel unhandled mode type %d",CurMode->type); - } - break; - } -} - -void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) { - switch (CurMode->type) { - case M_CGA4: - { - Bit16u off=(y>>1)*80+(x>>2); - if (y&1) off+=8*1024; - Bit8u val=real_readb(0xb800,off); - *color=(val>>(((3-(x&3)))*2)) & 3 ; - } - break; - case M_CGA2: - { - Bit16u off=(y>>1)*80+(x>>3); - if (y&1) off+=8*1024; - Bit8u val=real_readb(0xb800,off); - *color=(val>>(((7-(x&7))))) & 1 ; - } - break; - case M_EGA: - { - /* Calculate where the pixel is in video memory */ - if (CurMode->plength!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)) - LOG(LOG_INT10,LOG_ERROR)("GetPixel_EGA_p: %x!=%x",CurMode->plength,real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); - if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8) - LOG(LOG_INT10,LOG_ERROR)("GetPixel_EGA_w: %x!=%x",CurMode->swidth,real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8); - PhysPt off=0xa0000+real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page+ - ((y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8+x)>>3); - Bitu shift=7-(x & 7); - /* Set the read map */ - *color=0; - IO_Write(0x3ce,0x4);IO_Write(0x3cf,0); - *color|=((mem_readb(off)>>shift) & 1) << 0; - IO_Write(0x3ce,0x4);IO_Write(0x3cf,1); - *color|=((mem_readb(off)>>shift) & 1) << 1; - IO_Write(0x3ce,0x4);IO_Write(0x3cf,2); - *color|=((mem_readb(off)>>shift) & 1) << 2; - IO_Write(0x3ce,0x4);IO_Write(0x3cf,3); - *color|=((mem_readb(off)>>shift) & 1) << 3; - break; - } - case M_VGA: - *color=mem_readb(PhysMake(0xa000,320*y+x)); - break; - case M_LIN8: { - if (CurMode->swidth!=(Bitu)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8) - LOG(LOG_INT10,LOG_ERROR)("GetPixel_VGA_w: %x!=%x",CurMode->swidth,real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8); - PhysPt off=S3_LFB_BASE+y*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8+x; - *color = mem_readb(off); - break; - } - default: - LOG(LOG_INT10,LOG_ERROR)("GetPixel unhandled mode type %d",CurMode->type); - break; - } -} - +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "dosbox.h" +#include "mem.h" +#include "inout.h" +#include "int10.h" + +union VGA_Memory { + Bit8u linear[64*1024*4]; + Bit8u paged[64*1024][4]; +}; +extern VGA_Memory vga_mem; + +static Bit8u cga_masks[4]={~192,~48,~12,~3}; + +void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { + + VGAMODES * curmode=GetCurrentMode(); + + switch (curmode->memmodel) { + case CGA: + { + Bit16u off=(y>>1)*80+(x>>2); + if (y&1) off+=8*1024; + Bit8u old=real_readb(0xb800,off); + old=old&cga_masks[x&3]|((color&3) << (2*(3-(x&3)))); + real_writeb(0xb800,off,old); + } + break; + case PLANAR4: + { + /* Set the correct bitmask for the pixel position */ + IO_Write(0x3ce,0x8);Bit8u mask=128>>(x&7);IO_Write(0x3cf,mask); + /* Set the color to set/reset register */ + IO_Write(0x3ce,0x0);IO_Write(0x3cf,color); + /* Enable all the set/resets */ + IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf); + //Perhaps also set mode 1 + /* Calculate where the pixel is in video memory */ + Bit16u base_address=((((curmode->sheight*curmode->swidth)>>3)|0xff)+1)*page; + PhysOff off=0xa0000+base_address+((y*curmode->swidth+x)>>3); + /* Bitmask and set/reset should do the rest */ + mem_readb(off); + mem_writeb(off,0xff); + break; + } + case CTEXT: + case MTEXT: + case PLANAR1: + case PLANAR2: + case LINEAR8: + default: + LOG_WARN("INT10:PutPixel Unhanled memory model"); + break; + } +} + +void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) { + + VGAMODES * curmode=GetCurrentMode(); + switch (curmode->memmodel) { + case CGA: + { + Bit16u off=(y>>1)*80+(x>>2); + if (y&1) off+=8*1024; + Bit8u val=real_readb(0xb800,off); + *color=val<<((x&3)*2); + } + break; + default: + LOG_WARN("INT10:GetPixel Unhanled memory model"); + break; + } +} + diff --git a/src/ints/int10_vesa.cpp b/src/ints/int10_vesa.cpp deleted file mode 100644 index 6e30d9c..0000000 --- a/src/ints/int10_vesa.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: int10_vesa.cpp,v 1.38 2009/04/11 07:58:39 qbix79 Exp $ */ - -#include -#include - -#include "dosbox.h" -#include "callback.h" -#include "regs.h" -#include "mem.h" -#include "inout.h" -#include "int10.h" -#include "dos_inc.h" - -static struct { - Bitu setwindow; - Bitu pmStart; - Bitu pmWindow; - Bitu pmPalette; -} callback; - -static char string_oem[]="S3 Incorporated. Trio64"; -static char string_vendorname[]="DOSBox Development Team"; -static char string_productname[]="DOSBox - The DOS Emulator"; -static char string_productrev[]="DOSBox "VERSION; - -#ifdef _MSC_VER -#pragma pack (1) -#endif -struct MODE_INFO{ - Bit16u ModeAttributes; - Bit8u WinAAttributes; - Bit8u WinBAttributes; - Bit16u WinGranularity; - Bit16u WinSize; - Bit16u WinASegment; - Bit16u WinBSegment; - Bit32u WinFuncPtr; - Bit16u BytesPerScanLine; - Bit16u XResolution; - Bit16u YResolution; - Bit8u XCharSize; - Bit8u YCharSize; - Bit8u NumberOfPlanes; - Bit8u BitsPerPixel; - Bit8u NumberOfBanks; - Bit8u MemoryModel; - Bit8u BankSize; - Bit8u NumberOfImagePages; - Bit8u Reserved_page; - Bit8u RedMaskSize; - Bit8u RedMaskPos; - Bit8u GreenMaskSize; - Bit8u GreenMaskPos; - Bit8u BlueMaskSize; - Bit8u BlueMaskPos; - Bit8u ReservedMaskSize; - Bit8u ReservedMaskPos; - Bit8u DirectColorModeInfo; - Bit32u PhysBasePtr; - Bit32u OffScreenMemOffset; - Bit16u OffScreenMemSize; - Bit8u Reserved[206]; -} GCC_ATTRIBUTE(packed); -#ifdef _MSC_VER -#pragma pack() -#endif - - - -Bit8u VESA_GetSVGAInformation(Bit16u seg,Bit16u off) { - /* Fill 256 byte buffer with VESA information */ - PhysPt buffer=PhysMake(seg,off); - Bitu i; - bool vbe2=false;Bit16u vbe2_pos=256+off; - Bitu id=mem_readd(buffer); - if (((id==0x56424532)||(id==0x32454256)) && (!int10.vesa_oldvbe)) vbe2=true; - if (vbe2) { - for (i=0;i<0x200;i++) mem_writeb(buffer+i,0); - } else { - for (i=0;i<0x100;i++) mem_writeb(buffer+i,0); - } - /* Fill common data */ - MEM_BlockWrite(buffer,(void *)"VESA",4); //Identification - if (!int10.vesa_oldvbe) mem_writew(buffer+0x04,0x200); //Vesa version 2.0 - else mem_writew(buffer+0x04,0x102); //Vesa version 1.2 - if (vbe2) { - mem_writed(buffer+0x06,RealMake(seg,vbe2_pos)); - for (i=0;i=0x120)) return 0x01; - VideoModeBlock * mblock=&ModeList_VGA[i]; - switch (mblock->type) { - case M_LIN4: - pageSize = mblock->sheight * mblock->swidth/2; - pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.BytesPerScanLine,mblock->swidth/8); - var_write(&minfo.NumberOfPlanes,0x4); - var_write(&minfo.BitsPerPixel,4); - var_write(&minfo.MemoryModel,3); //ega planar mode - modeAttributes = 0x1b; // Color, graphics, no linear buffer - break; - case M_LIN8: - pageSize = mblock->sheight * mblock->swidth; - pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.BytesPerScanLine,mblock->swidth); - var_write(&minfo.NumberOfPlanes,0x1); - var_write(&minfo.BitsPerPixel,8); - var_write(&minfo.MemoryModel,4); //packed pixel - modeAttributes = 0x1b; // Color, graphics - if (!int10.vesa_nolfb) modeAttributes |= 0x80; // linear framebuffer - break; - case M_LIN15: - pageSize = mblock->sheight * mblock->swidth*2; - pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.BytesPerScanLine,mblock->swidth*2); - var_write(&minfo.NumberOfPlanes,0x1); - var_write(&minfo.BitsPerPixel,15); - var_write(&minfo.MemoryModel,6); //HiColour - var_write(&minfo.RedMaskSize,5); - var_write(&minfo.RedMaskPos,10); - var_write(&minfo.GreenMaskSize,5); - var_write(&minfo.GreenMaskPos,5); - var_write(&minfo.BlueMaskSize,5); - var_write(&minfo.BlueMaskPos,0); - var_write(&minfo.ReservedMaskSize,0x01); - var_write(&minfo.ReservedMaskPos,0x0f); - modeAttributes = 0x1b; // Color, graphics - if (!int10.vesa_nolfb) modeAttributes |= 0x80; // linear framebuffer - break; - case M_LIN16: - pageSize = mblock->sheight * mblock->swidth*2; - pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.BytesPerScanLine,mblock->swidth*2); - var_write(&minfo.NumberOfPlanes,0x1); - var_write(&minfo.BitsPerPixel,16); - var_write(&minfo.MemoryModel,6); //HiColour - var_write(&minfo.RedMaskSize,5); - var_write(&minfo.RedMaskPos,11); - var_write(&minfo.GreenMaskSize,6); - var_write(&minfo.GreenMaskPos,5); - var_write(&minfo.BlueMaskSize,5); - var_write(&minfo.BlueMaskPos,0); - modeAttributes = 0x1b; // Color, graphics - if (!int10.vesa_nolfb) modeAttributes |= 0x80; // linear framebuffer - break; - case M_LIN32: - pageSize = mblock->sheight * mblock->swidth*4; - pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.BytesPerScanLine,mblock->swidth*4); - var_write(&minfo.NumberOfPlanes,0x1); - var_write(&minfo.BitsPerPixel,32); - var_write(&minfo.MemoryModel,6); //HiColour - var_write(&minfo.RedMaskSize,8); - var_write(&minfo.RedMaskPos,0x10); - var_write(&minfo.GreenMaskSize,0x8); - var_write(&minfo.GreenMaskPos,0x8); - var_write(&minfo.BlueMaskSize,0x8); - var_write(&minfo.BlueMaskPos,0x0); - var_write(&minfo.ReservedMaskSize,0x8); - var_write(&minfo.ReservedMaskPos,0x18); - modeAttributes = 0x1b; // Color, graphics - if (!int10.vesa_nolfb) modeAttributes |= 0x80; // linear framebuffer - break; -/* case M_TEXT: - pageSize = mblock->sheight/8 * mblock->swidth*2/8; - pageSize = (pageSize | 15) & ~ 15; - var_write(&minfo.BytesPerScanLine,mblock->swidth*2/8); - var_write(&minfo.NumberOfPlanes,0x4); - var_write(&minfo.BitsPerPixel,4); - var_write(&minfo.MemoryModel,0); //Text - modeAttributes = 0x0f; //Color, text, bios output - break; */ - default: - return 0x1; - } - var_write(&minfo.WinAAttributes,0x7); // Exists/readable/writable - - if(pageSize > vga.vmemsize) { - // Mode not supported by current hardware configuration - var_write(&minfo.ModeAttributes, modeAttributes & ~0x1); - var_write(&minfo.NumberOfImagePages,0); - } else { - var_write(&minfo.ModeAttributes, modeAttributes); - Bitu pages = (vga.vmemsize / pageSize)-1; - var_write(&minfo.NumberOfImagePages,pages); - } - - if (mblock->type==M_TEXT) { - var_write(&minfo.WinGranularity,32); - var_write(&minfo.WinSize,32); - var_write(&minfo.WinASegment,0xb800); - var_write(&minfo.XResolution,mblock->swidth/8); - var_write(&minfo.YResolution,mblock->sheight/8); - } else { - var_write(&minfo.WinGranularity,64); - var_write(&minfo.WinSize,64); - var_write(&minfo.WinASegment,0xa000); - var_write(&minfo.XResolution,mblock->swidth); - var_write(&minfo.YResolution,mblock->sheight); - } - var_write(&minfo.WinFuncPtr,CALLBACK_RealPointer(callback.setwindow)); - var_write(&minfo.NumberOfBanks,0x1); - var_write(&minfo.Reserved_page,0x1); - var_write(&minfo.XCharSize,mblock->cwidth); - var_write(&minfo.YCharSize,mblock->cheight); - if (!int10.vesa_nolfb) var_write(&minfo.PhysBasePtr,S3_LFB_BASE); - - MEM_BlockWrite(buf,&minfo,sizeof(MODE_INFO)); - return 0x00; -} - - -Bit8u VESA_SetSVGAMode(Bit16u mode) { - if (INT10_SetVideoMode(mode)) { - int10.vesa_setmode=mode&0x7fff; - return 0x00; - } - return 0x01; -} - -Bit8u VESA_GetSVGAMode(Bit16u & mode) { - if (int10.vesa_setmode!=0xffff) mode=int10.vesa_setmode; - else mode=(Bit16u)(CurMode->mode); - return 0x00; -} - -Bit8u VESA_SetCPUWindow(Bit8u window,Bit8u address) { - if (window) return 0x1; - if (((Bit32u)(address)*64*1024255) return 0x1; - if (index+count>256) return 0x1; - IO_Write(0x3c8,index); - while (count) { - b = mem_readb(data++); - g = mem_readb(data++); - r = mem_readb(data++); - data++; - IO_Write(0x3c9,r); - IO_Write(0x3c9,g); - IO_Write(0x3c9,b); - count--; - } - return 0x00; -} - - -Bit8u VESA_GetPalette(PhysPt data,Bitu index,Bitu count) { - Bit8u r,g,b; - if (index>255) return 0x1; - if (index+count>256) return 0x1; - IO_Write(0x3c7,index); - while (count) { - r = IO_Read(0x3c9); - g = IO_Read(0x3c9); - b = IO_Read(0x3c9); - mem_writeb(data++,b); - mem_writeb(data++,g); - mem_writeb(data++,r); - data++; - count--; - } - return 0x00; -} - - -Bit8u VESA_ScanLineLength(Bit8u subcall,Bit16u val, Bit16u & bytes,Bit16u & pixels,Bit16u & lines) { - Bit8u bpp; - switch (CurMode->type) { - case M_LIN4: - bpp = 1; - break; - case M_LIN8: - bpp=1; - break; - case M_LIN15: - case M_LIN16: - bpp=2; - break; - case M_LIN32: - bpp=4; - break; - default: - return 0x1; - } - switch (subcall) { - case 0x00: /* Set in pixels */ - if(CurMode->type==M_LIN4) vga.config.scan_len=val/2; - else vga.config.scan_len = (val * bpp); - break; - case 0x02: /* Set in bytes */ - if(CurMode->type==M_LIN4) vga.config.scan_len = val*4; - else vga.config.scan_len = val; - break; - case 0x03: /* Get maximum */ - bytes=0x400*4; - pixels=bytes/bpp; - lines = (Bit16u)(vga.vmemsize / bytes); - return 0x00; - case 0x01: /* Get lengths */ - break; - default: - return 0x1; //Illegal call - } - if (subcall!=0x01) { - /* Write the scan line to video card the simple way */ - if (vga.config.scan_len & 7) - vga.config.scan_len += 8; - vga.config.scan_len /= 8; - } - if(CurMode->type==M_LIN4) { - pixels=(vga.config.scan_len*16)/bpp; - bytes=vga.config.scan_len*2; - lines = (Bit16u)(vga.vmemsize /( bytes*4)); - } - else { - pixels=(vga.config.scan_len*8)/bpp; - bytes=vga.config.scan_len*8; - lines = (Bit16u)(vga.vmemsize / bytes); - } - VGA_StartResize(); - return 0x0; -} - -Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y) { - //TODO Maybe do things differently with lowres double line modes? - Bitu start; - switch (CurMode->type) { - case M_LIN4: - start=vga.config.scan_len*16*y+x; - vga.config.display_start=start/8; - IO_Read(0x3da); - IO_Write(0x3c0,0x13+32); - IO_Write(0x3c0,start % 8); - break; - case M_LIN8: - start=vga.config.scan_len*8*y+x; - vga.config.display_start=start/4; - IO_Read(0x3da); - IO_Write(0x3c0,0x13+32); - IO_Write(0x3c0,(start % 4)*2); - break; - case M_LIN16: - case M_LIN15: - start=vga.config.scan_len*8*y+x*2; - vga.config.display_start=start/4; - break; - case M_LIN32: - start=vga.config.scan_len*8*y+x*4; - vga.config.display_start=start/4; - break; - default: - return 0x1; - } - return 0x00; -} - -Bit8u VESA_GetDisplayStart(Bit16u & x,Bit16u & y) { - Bitu times=(vga.config.display_start*4)/(vga.config.scan_len*8); - Bitu rem=(vga.config.display_start*4) % (vga.config.scan_len*8); - Bitu pan=vga.config.pel_panning; - switch (CurMode->type) { - case M_LIN8: - y=times; - x=rem+pan; - break; - default: - return 0x1; - } - return 0x00; -} - -static Bitu VESA_SetWindow(void) { - if (reg_bh) reg_ah=VESA_GetCPUWindow(reg_bl,reg_dx); - else reg_ah=VESA_SetCPUWindow(reg_bl,(Bit8u)reg_dx); - reg_al=0x4f; - return 0; -} - -static Bitu VESA_PMSetWindow(void) { - VESA_SetCPUWindow(0,(Bit8u)reg_dx); - return 0; -} -static Bitu VESA_PMSetPalette(void) { - VESA_SetPalette(SegPhys(es) + reg_edi, reg_dx, reg_cx ); - return 0; -} -static Bitu VESA_PMSetStart(void) { - Bit32u start = (reg_dx << 16) | reg_cx; - vga.config.display_start = start; - return 0; -} - - - - -void INT10_SetupVESA(void) { - /* Put the mode list somewhere in memory */ - Bitu i; - i=0; - int10.rom.vesa_modes=RealMake(0xc000,int10.rom.used); -//TODO Maybe add normal vga modes too, but only seems to complicate things - while (ModeList_VGA[i].mode!=0xffff) { - bool canuse_mode=false; - if (!svga.accepts_mode) canuse_mode=true; - else { - if (svga.accepts_mode(ModeList_VGA[i].mode)) canuse_mode=true; - } - if (ModeList_VGA[i].mode>=0x100 && canuse_mode) { - if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) { - phys_writew(PhysMake(0xc000,int10.rom.used),ModeList_VGA[i].mode); - int10.rom.used+=2; - } - } - i++; - } - phys_writew(PhysMake(0xc000,int10.rom.used),0xffff); - int10.rom.used+=2; - int10.rom.oemstring=RealMake(0xc000,int10.rom.used); - Bitu len=(Bitu)(strlen(string_oem)+1); - for (i=0;i64k graphics memory) - 0x50, 0x18, 0x0e, 0x00, 0x80, // bios data - 0x01, 0x0f, 0x00, 0x02, // sequencer registers - 0xa2, // misc output registers - 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, // crtc registers 0-7 - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3, 0xff, // crtc registers 16-24 - 0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, // attr registers 0-7 - 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, // attr registers 8-15 - 0x0b, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 10 (>64k graphics memory) - 0x50, 0x18, 0x0e, 0x00, 0x80, // bios data - 0x01, 0x0f, 0x00, 0x02, // sequencer registers - 0xa3, // misc output registers - 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, // crtc registers 0-7 - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, // attr registers 0-7 - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, // attr registers 8-15 - 0x01, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 0 (350 lines) - 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, -// video parameter table for mode 1 (350 lines) - 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, -// video parameter table for mode 2 (350 lines) - 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, -// video parameter table for mode 3 (350 lines) - 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, -// video parameter table for mode e - 0x28, 0x18, 0x10, 0x00, 0x08, // bios data - 0x08, 0x0f, 0x00, 0x07, // sequencer registers - 0x67, // misc output registers - 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f, // crtc registers 0-7 - 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, // attr registers 0-7 - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, // attr registers 8-15 - 0x0c, 0x00, 0x0f, 0x08, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode f - 0x50, 0x18, 0x10, 0x00, 0x10, // bios data - 0x00, 0x0f, 0x00, 0x07, // sequencer registers - 0x67, // misc output registers - 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, // crtc registers 0-7 - 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, // attr registers 0-7 - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, // attr registers 8-15 - 0x0c, 0x00, 0x0f, 0x08, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 10 - 0x50, 0x18, 0x10, 0x00, 0x10, // bios data - 0x00, 0x0f, 0x00, 0x07, // sequencer registers - 0x66, // misc output registers - 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, // crtc registers 0-7 - 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, // attr registers 0-7 - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, // attr registers 8-15 - 0x0c, 0x00, 0x0f, 0x08, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 11 - 0x50, 0x1d, 0x10, 0x00, 0xa0, // bios data - 0x01, 0x0f, 0x00, 0x02, // sequencer registers - 0xe3, // misc output registers - 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, // crtc registers 0-7 - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xc3, 0xff, // crtc registers 16-24 - 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, // attr registers 0-7 - 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, // attr registers 8-15 - 0x01, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 12 - 0x50, 0x1d, 0x10, 0x00, 0xa0, // bios data - 0x01, 0x0f, 0x00, 0x02, // sequencer registers - 0xe3, // misc output registers - 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, // crtc registers 0-7 - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, // attr registers 0-7 - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, // attr registers 8-15 - 0x01, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 13 - 0x28, 0x18, 0x08, 0x00, 0x20, // bios data - 0x01, 0x0f, 0x00, 0x0e, // sequencer registers - 0x63, // misc output registers - 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, // crtc registers 0-7 - 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // attr registers 0-7 - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, // attr registers 8-15 - 0x41, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff // graphics registers 0-8 -}; - -static Bit8u video_parameter_table_ega[0x40*0x17]={ -// video parameter table for mode 0 (cga emulation) - 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, -// video parameter table for mode 1 (cga emulation) - 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, -// video parameter table for mode 2 (cga emulation) - 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, -// video parameter table for mode 3 (cga emulation) - 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, -// video parameter table for mode 4 - 0x28, 0x18, 0x08, 0x00, 0x40, // bios data - 0x09, 0x03, 0x00, 0x02, // sequencer registers - 0x63, // misc output registers - 0x37, 0x27, 0x28, 0x9a, 0x2b, 0x8a, 0x04, 0x11, // crtc registers 0-7 - 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0xd4, 0x86, 0xc7, 0x14, 0x00, 0xd0, 0xfc, 0xb2, 0xff, // crtc registers 16-24 - 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, // attr registers 0-7 - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // attr registers 8-15 - 0x01, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 5 - 0x28, 0x18, 0x08, 0x00, 0x40, // bios data - 0x09, 0x03, 0x00, 0x02, // sequencer registers - 0x63, // misc output registers - 0x37, 0x27, 0x28, 0x9a, 0x2b, 0x8a, 0x04, 0x11, // crtc registers 0-7 - 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0xd4, 0x86, 0xc7, 0x14, 0x00, 0xd0, 0xfc, 0xb2, 0xff, // crtc registers 16-24 - 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, // attr registers 0-7 - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // attr registers 8-15 - 0x01, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 6 - 0x50, 0x18, 0x08, 0x00, 0x40, // bios data - 0x01, 0x0f, 0x00, 0x06, // sequencer registers - 0x63, // misc output registers - 0x73, 0x4f, 0x50, 0x96, 0x54, 0x94, 0x04, 0x11, // crtc registers 0-7 - 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0xd4, 0x86, 0xc7, 0x28, 0x00, 0xd0, 0xfc, 0xd2, 0xff, // crtc registers 16-24 - 0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, // attr registers 0-7 - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, // attr registers 8-15 - 0x01, 0x00, 0x01, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 7 - 0x50, 0x18, 0x0e, 0x00, 0x10, // bios data - 0x00, 0x0f, 0x00, 0x03, // sequencer registers - 0xa2, // misc output registers - 0x73, 0x4f, 0x50, 0x96, 0x55, 0x95, 0xb6, 0x1f, // crtc registers 0-7 - 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xb1, 0xb3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // attr registers 0-7 - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // attr registers 8-15 - 0x08, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 8 - 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, -// video parameter table for mode 9 - 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, -// video parameter table for mode a - 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, -// video parameter table for mode b - 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, -// video parameter table for mode c - 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, -// video parameter table for mode d - 0x28, 0x18, 0x08, 0x00, 0x20, // bios data - 0x09, 0x0f, 0x00, 0x06, // sequencer registers - 0x63, // misc output registers - 0x37, 0x27, 0x28, 0x9a, 0x2b, 0x8a, 0x04, 0x11, // crtc registers 0-7 - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0xd4, 0x86, 0xc7, 0x14, 0x00, 0xd0, 0xfc, 0xd3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // attr registers 0-7 - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // attr registers 8-15 - 0x01, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode e - 0x50, 0x18, 0x08, 0x00, 0x40, // bios data - 0x01, 0x0f, 0x00, 0x06, // sequencer registers - 0x63, // misc output registers - 0x73, 0x4f, 0x50, 0x96, 0x54, 0x94, 0x04, 0x11, // crtc registers 0-7 - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0xd4, 0x86, 0xc7, 0x28, 0x00, 0xd0, 0xfc, 0xd3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // attr registers 0-7 - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // attr registers 8-15 - 0x01, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode f (64k graphics memory) - 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, -// video parameter table for mode 10 (64k graphics memory) - 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, -// video parameter table for mode f (>64k graphics memory) - 0x50, 0x18, 0x0e, 0x00, 0x80, // bios data - 0x01, 0x0f, 0x00, 0x06, // sequencer registers - 0xa2, // misc output registers - 0x73, 0x4f, 0x50, 0x96, 0x54, 0x94, 0xb6, 0x1f, // crtc registers 0-7 - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x83, 0x85, 0x5d, 0x14, 0x0f, 0x63, 0xb1, 0x9b, 0xff, // crtc registers 16-24 - 0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, // attr registers 0-7 - 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, // attr registers 8-15 - 0x0b, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 10 (>64k graphics memory) - 0x50, 0x18, 0x0e, 0x00, 0x80, // bios data - 0x01, 0x0f, 0x00, 0x06, // sequencer registers - 0xa3, // misc output registers - 0x5b, 0x4f, 0x50, 0x9e, 0x54, 0x1c, 0x4e, 0x1f, // crtc registers 0-7 - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x83, 0x85, 0x5d, 0x14, 0x0f, 0x63, 0x49, 0x9b, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // attr registers 0-7 - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // attr registers 8-15 - 0x01, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 0 (350 lines) - 0x28, 0x18, 0x0e, 0x00, 0x08, // bios data - 0x09, 0x0f, 0x00, 0x03, // sequencer registers - 0xa3, // misc output registers - 0x37, 0x27, 0x28, 0x9a, 0x2b, 0xaa, 0x04, 0x1f, // crtc registers 0-7 - 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x83, 0x85, 0x5d, 0x14, 0x0f, 0x63, 0xff, 0xb3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // attr registers 0-7 - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // attr registers 8-15 - 0x08, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 1 (350 lines) - 0x28, 0x18, 0x0e, 0x00, 0x08, // bios data - 0x09, 0x0f, 0x00, 0x03, // sequencer registers - 0xa3, // misc output registers - 0x37, 0x27, 0x28, 0x9a, 0x2b, 0xaa, 0x04, 0x1f, // crtc registers 0-7 - 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x83, 0x85, 0x5d, 0x14, 0x0f, 0x63, 0xff, 0xb3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // attr registers 0-7 - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // attr registers 8-15 - 0x08, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 2 (350 lines) - 0x50, 0x18, 0x0e, 0x00, 0x10, // bios data - 0x01, 0x0f, 0x00, 0x03, // sequencer registers - 0xa3, // misc output registers - 0x73, 0x4f, 0x50, 0x96, 0x55, 0x95, 0xb6, 0x1f, // crtc registers 0-7 - 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xb1, 0xb3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // attr registers 0-7 - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // attr registers 8-15 - 0x08, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff, // graphics registers 0-8 -// video parameter table for mode 3 (350 lines) - 0x50, 0x18, 0x0e, 0x00, 0x10, // bios data - 0x01, 0x0f, 0x00, 0x03, // sequencer registers - 0xa3, // misc output registers - 0x73, 0x4f, 0x50, 0x96, 0x55, 0x95, 0xb6, 0x1f, // crtc registers 0-7 - 0x00, 0x4d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, // crtc registers 8-15 - 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xb1, 0xb3, 0xff, // crtc registers 16-24 - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // attr registers 0-7 - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // attr registers 8-15 - 0x08, 0x00, 0x0f, 0x00, // attr registers 16-19 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff // graphics registers 0-8 -}; - - -Bitu INT10_SetupVideoParameterTable(PhysPt basepos) { - if (IS_VGA_ARCH) { - for (Bitu i=0;i<0x40*0x1d;i++) { - phys_writeb(basepos+i,video_parameter_table_vga[i]); - } - return 0x40*0x1d; - } else { - for (Bitu i=0;i<0x40*0x17;i++) { - phys_writeb(basepos+i,video_parameter_table_ega[i]); - } - return 0x40*0x17; - } -} - -#if 0 -void INT10_GenerateVideoParameterTable(void) { - if (!IS_VGA_ARCH) E_Exit("Be sure that all graphics registers are readable!"); - Bitu i; - for (i=0; i<4; i++) { - LOG_MSG("// video parameter table for mode %x (cga emulation)",i); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - } - for (i=4; i<0x0f; i++) { - Bitu ct; - LOG_MSG("// video parameter table for mode %x",i); - if ((i>=8) && (i<0x0d)) { - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - } else { - INT10_SetVideoMode(i); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // bios data",real_readb(0x40,0x4a),real_readb(0x40,0x84),real_readb(0x40,0x85),real_readb(0x40,0x4c),real_readb(0x40,0x4d)); - Bitu seq_regs[4]; - for (ct=0; ct<4; ct++) { - IO_WriteB(0x3c4,ct+1); - seq_regs[ct]=IO_ReadB(0x3c5); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, // sequencer registers",seq_regs[0],seq_regs[1],seq_regs[2],seq_regs[3]); - LOG_MSG(" 0x%02x, // misc output registers",IO_ReadB(0x3cc)); - Bitu crtc_regs[0x19]; - Bit16u crt_addr=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); - for (ct=0; ct<0x19; ct++) { - IO_WriteB(crt_addr,ct); - crtc_regs[ct]=IO_ReadB(crt_addr+1); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 0-7", - crtc_regs[0x00],crtc_regs[0x01],crtc_regs[0x02],crtc_regs[0x03], - crtc_regs[0x04],crtc_regs[0x05],crtc_regs[0x06],crtc_regs[0x07]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 8-15", - crtc_regs[0x08],crtc_regs[0x09],crtc_regs[0x0a],crtc_regs[0x0b], - crtc_regs[0x0c],crtc_regs[0x0d],crtc_regs[0x0e],crtc_regs[0x0f]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 16-24", - crtc_regs[0x10],crtc_regs[0x11],crtc_regs[0x12],crtc_regs[0x13], - crtc_regs[0x14],crtc_regs[0x15],crtc_regs[0x16],crtc_regs[0x17],crtc_regs[0x18]); - Bitu attr_regs[0x14]; - for (ct=0; ct<0x14; ct++) { - IO_ReadB(crt_addr+6); - IO_WriteB(0x3c0,ct); - attr_regs[ct]=IO_ReadB(0x3c1); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 0-7", - attr_regs[0x00],attr_regs[0x01],attr_regs[0x02],attr_regs[0x03], - attr_regs[0x04],attr_regs[0x05],attr_regs[0x06],attr_regs[0x07]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 8-15", - attr_regs[0x08],attr_regs[0x09],attr_regs[0x0a],attr_regs[0x0b], - attr_regs[0x0c],attr_regs[0x0d],attr_regs[0x0e],attr_regs[0x0f]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 16-19", - attr_regs[0x10],attr_regs[0x11],attr_regs[0x12],attr_regs[0x13]); - Bitu gfx_regs[9]; - for (ct=0; ct<0x09; ct++) { - IO_WriteB(0x3ce,ct); - gfx_regs[ct]=IO_ReadB(0x3cf); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // graphics registers 0-8", - gfx_regs[0x00],gfx_regs[0x01],gfx_regs[0x02],gfx_regs[0x03], - gfx_regs[0x04],gfx_regs[0x05],gfx_regs[0x06],gfx_regs[0x07],gfx_regs[0x08]); - } - } - for (i=0x0f; i<0x11; i++) { - LOG_MSG("// video parameter table for mode %x (64k graphics memory)",i); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - } - for (i=0x0f; i<0x11; i++) { - Bitu ct; - INT10_SetVideoMode(i); - LOG_MSG("// video parameter table for mode %x (>64k graphics memory)",i); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // bios data",real_readb(0x40,0x4a),real_readb(0x40,0x84),real_readb(0x40,0x85),real_readb(0x40,0x4c),real_readb(0x40,0x4d)); - Bitu seq_regs[4]; - for (ct=0; ct<4; ct++) { - IO_WriteB(0x3c4,ct+1); - seq_regs[ct]=IO_ReadB(0x3c5); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, // sequencer registers",seq_regs[0],seq_regs[1],seq_regs[2],seq_regs[3]); - LOG_MSG(" 0x%02x, // misc output registers",IO_ReadB(0x3cc)); - Bitu crtc_regs[0x19]; - Bit16u crt_addr=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); - for (ct=0; ct<0x19; ct++) { - IO_WriteB(crt_addr,ct); - crtc_regs[ct]=IO_ReadB(crt_addr+1); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 0-7", - crtc_regs[0x00],crtc_regs[0x01],crtc_regs[0x02],crtc_regs[0x03], - crtc_regs[0x04],crtc_regs[0x05],crtc_regs[0x06],crtc_regs[0x07]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 8-15", - crtc_regs[0x08],crtc_regs[0x09],crtc_regs[0x0a],crtc_regs[0x0b], - crtc_regs[0x0c],crtc_regs[0x0d],crtc_regs[0x0e],crtc_regs[0x0f]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 16-24", - crtc_regs[0x10],crtc_regs[0x11],crtc_regs[0x12],crtc_regs[0x13], - crtc_regs[0x14],crtc_regs[0x15],crtc_regs[0x16],crtc_regs[0x17],crtc_regs[0x18]); - Bitu attr_regs[0x14]; - for (ct=0; ct<0x14; ct++) { - IO_ReadB(crt_addr+6); - IO_WriteB(0x3c0,ct); - attr_regs[ct]=IO_ReadB(0x3c1); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 0-7", - attr_regs[0x00],attr_regs[0x01],attr_regs[0x02],attr_regs[0x03], - attr_regs[0x04],attr_regs[0x05],attr_regs[0x06],attr_regs[0x07]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 8-15", - attr_regs[0x08],attr_regs[0x09],attr_regs[0x0a],attr_regs[0x0b], - attr_regs[0x0c],attr_regs[0x0d],attr_regs[0x0e],attr_regs[0x0f]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 16-19", - attr_regs[0x10],attr_regs[0x11],attr_regs[0x12],attr_regs[0x13]); - Bitu gfx_regs[9]; - for (ct=0; ct<0x09; ct++) { - IO_WriteB(0x3ce,ct); - gfx_regs[ct]=IO_ReadB(0x3cf); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // graphics registers 0-8", - gfx_regs[0x00],gfx_regs[0x01],gfx_regs[0x02],gfx_regs[0x03], - gfx_regs[0x04],gfx_regs[0x05],gfx_regs[0x06],gfx_regs[0x07],gfx_regs[0x08]); - } - for (i=0; i<4; i++) { - if (IS_VGA_ARCH) { - LOG_MSG("// video parameter table for mode %x (350 lines)",i); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - LOG_MSG(" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,"); - } else { - Bitu ct; - INT10_SetVideoMode(i); - LOG_MSG("// video parameter table for mode %x (350 lines)",i); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // bios data",real_readb(0x40,0x4a),real_readb(0x40,0x84),real_readb(0x40,0x85),real_readb(0x40,0x4c),real_readb(0x40,0x4d)); - Bitu seq_regs[4]; - for (ct=0; ct<4; ct++) { - IO_WriteB(0x3c4,ct+1); - seq_regs[ct]=IO_ReadB(0x3c5); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, // sequencer registers",seq_regs[0],seq_regs[1],seq_regs[2],seq_regs[3]); - LOG_MSG(" 0x%02x, // misc output registers",IO_ReadB(0x3cc)); - Bitu crtc_regs[0x19]; - Bit16u crt_addr=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); - for (ct=0; ct<0x19; ct++) { - IO_WriteB(crt_addr,ct); - crtc_regs[ct]=IO_ReadB(crt_addr+1); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 0-7", - crtc_regs[0x00],crtc_regs[0x01],crtc_regs[0x02],crtc_regs[0x03], - crtc_regs[0x04],crtc_regs[0x05],crtc_regs[0x06],crtc_regs[0x07]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 8-15", - crtc_regs[0x08],crtc_regs[0x09],crtc_regs[0x0a],crtc_regs[0x0b], - crtc_regs[0x0c],crtc_regs[0x0d],crtc_regs[0x0e],crtc_regs[0x0f]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 16-24", - crtc_regs[0x10],crtc_regs[0x11],crtc_regs[0x12],crtc_regs[0x13], - crtc_regs[0x14],crtc_regs[0x15],crtc_regs[0x16],crtc_regs[0x17],crtc_regs[0x18]); - Bitu attr_regs[0x14]; - for (ct=0; ct<0x14; ct++) { - IO_ReadB(crt_addr+6); - IO_WriteB(0x3c0,ct); - attr_regs[ct]=IO_ReadB(0x3c1); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 0-7", - attr_regs[0x00],attr_regs[0x01],attr_regs[0x02],attr_regs[0x03], - attr_regs[0x04],attr_regs[0x05],attr_regs[0x06],attr_regs[0x07]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 8-15", - attr_regs[0x08],attr_regs[0x09],attr_regs[0x0a],attr_regs[0x0b], - attr_regs[0x0c],attr_regs[0x0d],attr_regs[0x0e],attr_regs[0x0f]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 16-19", - attr_regs[0x10],attr_regs[0x11],attr_regs[0x12],attr_regs[0x13]); - Bitu gfx_regs[9]; - for (ct=0; ct<0x09; ct++) { - IO_WriteB(0x3ce,ct); - gfx_regs[ct]=IO_ReadB(0x3cf); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // graphics registers 0-8", - gfx_regs[0x00],gfx_regs[0x01],gfx_regs[0x02],gfx_regs[0x03], - gfx_regs[0x04],gfx_regs[0x05],gfx_regs[0x06],gfx_regs[0x07],gfx_regs[0x08]); - } - } - if (IS_VGA_ARCH) { - for (i=0x0e; i<0x14; i++) { - Bitu ct=i; - if (i==0x0e) ct=1; - if (i==0x0f) ct=3; - if (i==0x010) ct=7; - INT10_SetVideoMode(ct); - LOG_MSG("// video parameter table for mode %x",i); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // bios data",real_readb(0x40,0x4a),real_readb(0x40,0x84),real_readb(0x40,0x85),real_readb(0x40,0x4c),real_readb(0x40,0x4d)); - Bitu seq_regs[4]; - for (ct=0; ct<4; ct++) { - IO_WriteB(0x3c4,ct+1); - seq_regs[ct]=IO_ReadB(0x3c5); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, // sequencer registers",seq_regs[0],seq_regs[1],seq_regs[2],seq_regs[3]); - LOG_MSG(" 0x%02x, // misc output registers",IO_ReadB(0x3cc)); - Bitu crtc_regs[0x19]; - Bit16u crt_addr=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); - for (ct=0; ct<0x19; ct++) { - IO_WriteB(crt_addr,ct); - crtc_regs[ct]=IO_ReadB(crt_addr+1); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 0-7", - crtc_regs[0x00],crtc_regs[0x01],crtc_regs[0x02],crtc_regs[0x03], - crtc_regs[0x04],crtc_regs[0x05],crtc_regs[0x06],crtc_regs[0x07]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 8-15", - crtc_regs[0x08],crtc_regs[0x09],crtc_regs[0x0a],crtc_regs[0x0b], - crtc_regs[0x0c],crtc_regs[0x0d],crtc_regs[0x0e],crtc_regs[0x0f]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // crtc registers 16-24", - crtc_regs[0x10],crtc_regs[0x11],crtc_regs[0x12],crtc_regs[0x13], - crtc_regs[0x14],crtc_regs[0x15],crtc_regs[0x16],crtc_regs[0x17],crtc_regs[0x18]); - Bitu attr_regs[0x14]; - for (ct=0; ct<0x14; ct++) { - IO_ReadB(crt_addr+6); - IO_WriteB(0x3c0,ct); - attr_regs[ct]=IO_ReadB(0x3c1); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 0-7", - attr_regs[0x00],attr_regs[0x01],attr_regs[0x02],attr_regs[0x03], - attr_regs[0x04],attr_regs[0x05],attr_regs[0x06],attr_regs[0x07]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 8-15", - attr_regs[0x08],attr_regs[0x09],attr_regs[0x0a],attr_regs[0x0b], - attr_regs[0x0c],attr_regs[0x0d],attr_regs[0x0e],attr_regs[0x0f]); - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, // attr registers 16-19", - attr_regs[0x10],attr_regs[0x11],attr_regs[0x12],attr_regs[0x13]); - Bitu gfx_regs[9]; - for (ct=0; ct<0x09; ct++) { - IO_WriteB(0x3ce,ct); - gfx_regs[ct]=IO_ReadB(0x3cf); - } - LOG_MSG(" 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, // graphics registers 0-8", - gfx_regs[0x00],gfx_regs[0x01],gfx_regs[0x02],gfx_regs[0x03], - gfx_regs[0x04],gfx_regs[0x05],gfx_regs[0x06],gfx_regs[0x07],gfx_regs[0x08]); - } - } - INT10_SetVideoMode(3); - E_Exit("done!"); -} -#endif diff --git a/src/ints/mouse.cpp b/src/ints/mouse.cpp index e07104f..baab599 100644 --- a/src/ints/mouse.cpp +++ b/src/ints/mouse.cpp @@ -1,1077 +1,294 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: mouse.cpp,v 1.79 2009/04/16 12:11:45 qbix79 Exp $ */ - -#include -#include - - -#include "dosbox.h" -#include "callback.h" -#include "mem.h" -#include "regs.h" -#include "cpu.h" -#include "mouse.h" -#include "pic.h" -#include "inout.h" -#include "int10.h" -#include "bios.h" -#include "dos_inc.h" - -static Bitu call_int33,call_int74,int74_ret_callback,call_mouse_bd; -static Bit16u ps2cbseg,ps2cbofs; -static bool useps2callback,ps2callbackinit; -static Bitu call_ps2; -static RealPt ps2_callback; -static Bit16s oldmouseX, oldmouseY; -// forward -void WriteMouseIntVector(void); - -struct button_event { - Bit8u type; - Bit8u buttons; -}; - -#define QUEUE_SIZE 32 -#define MOUSE_BUTTONS 3 -#define MOUSE_IRQ 12 -#define POS_X (Bit16s)(mouse.x) -#define POS_Y (Bit16s)(mouse.y) - -#define CURSORX 16 -#define CURSORY 16 -#define HIGHESTBIT (1<<(CURSORX-1)) - -static Bit16u defaultTextAndMask = 0x77FF; -static Bit16u defaultTextXorMask = 0x7700; - -static Bit16u defaultScreenMask[CURSORY] = { - 0x3FFF, 0x1FFF, 0x0FFF, 0x07FF, - 0x03FF, 0x01FF, 0x00FF, 0x007F, - 0x003F, 0x001F, 0x01FF, 0x00FF, - 0x30FF, 0xF87F, 0xF87F, 0xFCFF -}; - -static Bit16u defaultCursorMask[CURSORY] = { - 0x0000, 0x4000, 0x6000, 0x7000, - 0x7800, 0x7C00, 0x7E00, 0x7F00, - 0x7F80, 0x7C00, 0x6C00, 0x4600, - 0x0600, 0x0300, 0x0300, 0x0000 -}; - -static Bit16u userdefScreenMask[CURSORY]; -static Bit16u userdefCursorMask[CURSORY]; - -static struct { - Bit8u buttons; - Bit16u times_pressed[MOUSE_BUTTONS]; - Bit16u times_released[MOUSE_BUTTONS]; - Bit16u last_released_x[MOUSE_BUTTONS]; - Bit16u last_released_y[MOUSE_BUTTONS]; - Bit16u last_pressed_x[MOUSE_BUTTONS]; - Bit16u last_pressed_y[MOUSE_BUTTONS]; - Bit16u hidden; - float add_x,add_y; - Bit16s min_x,max_x,min_y,max_y; - float mickey_x,mickey_y; - float x,y; - button_event event_queue[QUEUE_SIZE]; - Bit8u events;//Increase if QUEUE_SIZE >255 (currently 32) - Bit16u sub_seg,sub_ofs; - Bit16u sub_mask; - - bool background; - Bit16s backposx, backposy; - Bit8u backData[CURSORX*CURSORY]; - Bit16u* screenMask; - Bit16u* cursorMask; - Bit16s clipx,clipy; - Bit16s hotx,hoty; - Bit16u textAndMask, textXorMask; - - float mickeysPerPixel_x; - float mickeysPerPixel_y; - float pixelPerMickey_x; - float pixelPerMickey_y; - Bit16u senv_x_val; - Bit16u senv_y_val; - Bit16u dspeed_val; - float senv_x; - float senv_y; - Bit16u updateRegion_x[2]; - Bit16u updateRegion_y[2]; - Bit16u doubleSpeedThreshold; - Bit16u language; - Bit16u cursorType; - Bit16u oldhidden; - Bit8u page; - bool enabled; - bool inhibit_draw; - bool timer_in_progress; - bool in_UIR; - Bit8u mode; -} mouse; - -bool Mouse_SetPS2State(bool use) { - if (use && (!ps2callbackinit)) { - useps2callback = false; - PIC_SetIRQMask(MOUSE_IRQ,true); - return false; - } - useps2callback = use; - Mouse_AutoLock(useps2callback); - PIC_SetIRQMask(MOUSE_IRQ,!useps2callback); - return true; -} - -void Mouse_ChangePS2Callback(Bit16u pseg, Bit16u pofs) { - if ((pseg==0) && (pofs==0)) { - ps2callbackinit = false; - Mouse_AutoLock(false); - } else { - ps2callbackinit = true; - ps2cbseg = pseg; - ps2cbofs = pofs; - } - Mouse_AutoLock(ps2callbackinit); -} - -void DoPS2Callback(Bit16u data, Bit16s mouseX, Bit16s mouseY) { - if (useps2callback) { - Bit16u mdat = (data & 0x03) | 0x08; - Bit16s xdiff = mouseX-oldmouseX; - Bit16s ydiff = oldmouseY-mouseY; - oldmouseX = mouseX; - oldmouseY = mouseY; - if ((xdiff>0xff) || (xdiff<-0xff)) mdat |= 0x40; // x overflow - if ((ydiff>0xff) || (ydiff<-0xff)) mdat |= 0x80; // y overflow - xdiff %= 256; - ydiff %= 256; - if (xdiff<0) { - xdiff = (0x100+xdiff); - mdat |= 0x10; - } - if (ydiff<0) { - ydiff = (0x100+ydiff); - mdat |= 0x20; - } - CPU_Push16((Bit16u)mdat); - CPU_Push16((Bit16u)(xdiff % 256)); - CPU_Push16((Bit16u)(ydiff % 256)); - CPU_Push16((Bit16u)0); - CPU_Push16(RealSeg(ps2_callback)); - CPU_Push16(RealOff(ps2_callback)); - SegSet16(cs, ps2cbseg); - reg_ip = ps2cbofs; - } -} - -Bitu PS2_Handler(void) { - CPU_Pop16();CPU_Pop16();CPU_Pop16();CPU_Pop16();// remove the 4 words - return CBRET_NONE; -} - - -#define X_MICKEY 8 -#define Y_MICKEY 8 - -#define MOUSE_HAS_MOVED 1 -#define MOUSE_LEFT_PRESSED 2 -#define MOUSE_LEFT_RELEASED 4 -#define MOUSE_RIGHT_PRESSED 8 -#define MOUSE_RIGHT_RELEASED 16 -#define MOUSE_MIDDLE_PRESSED 32 -#define MOUSE_MIDDLE_RELEASED 64 -#define MOUSE_DELAY 5.0 - -void MOUSE_Limit_Events(Bitu /*val*/) { - mouse.timer_in_progress = false; - if (mouse.events) { - mouse.timer_in_progress = true; - PIC_AddEvent(MOUSE_Limit_Events,MOUSE_DELAY); - PIC_ActivateIRQ(MOUSE_IRQ); - } -} - -INLINE void Mouse_AddEvent(Bit8u type) { - if (mouse.events0) { - /* Skip duplicate events */ - if (type==MOUSE_HAS_MOVED) return; - /* Always put the newest element in the front as that the events are - * handled backwards (prevents doubleclicks while moving) - */ - for(Bitu i = mouse.events ; i ; i--) - mouse.event_queue[i] = mouse.event_queue[i-1]; - } - mouse.event_queue[0].type=type; - mouse.event_queue[0].buttons=mouse.buttons; - mouse.events++; - } - if (!mouse.timer_in_progress) { - mouse.timer_in_progress = true; - PIC_AddEvent(MOUSE_Limit_Events,MOUSE_DELAY); - PIC_ActivateIRQ(MOUSE_IRQ); - } -} - -// *************************************************************************** -// Mouse cursor - text mode -// *************************************************************************** -/* Write and read directly to the screen. Do no use int_setcursorpos (LOTUS123) */ -extern void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool useattr); -extern void ReadCharAttr(Bit16u col,Bit16u row,Bit8u page,Bit16u * result); - -void RestoreCursorBackgroundText() { - if (mouse.hidden || mouse.inhibit_draw) return; - - if (mouse.background) { - WriteChar(mouse.backposx,mouse.backposy,real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE),mouse.backData[0],mouse.backData[1],true); - mouse.background = false; - } -} - -void DrawCursorText() { - // Restore Background - RestoreCursorBackgroundText(); - - - // Save Background - mouse.backposx = POS_X>>3; - mouse.backposy = POS_Y>>3; - - //use current page (CV program) - Bit8u page = real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); - Bit16u result; - - ReadCharAttr(mouse.backposx,mouse.backposy,page,&result); - mouse.backData[0] = (Bit8u)(result & 0xFF); - mouse.backData[1] = (Bit8u)(result>>8); - mouse.background = true; - // Write Cursor - result = (result & mouse.textAndMask) ^ mouse.textXorMask; - WriteChar(mouse.backposx,mouse.backposy,page,(Bit8u)(result&0xFF),(Bit8u)(result>>8),true); -} - -// *************************************************************************** -// Mouse cursor - graphic mode -// *************************************************************************** - -static Bit8u gfxReg3CE[9]; -static Bit8u index3C4,gfxReg3C5; -void SaveVgaRegisters() { - if (IS_VGA_ARCH) { - for (Bit8u i=0; i<9; i++) { - IO_Write (0x3CE,i); - gfxReg3CE[i] = IO_Read(0x3CF); - } - /* Setup some default values in GFX regs that should work */ - IO_Write(0x3CE,3); IO_Write(0x3Cf,0); //disable rotate and operation - IO_Write(0x3CE,5); IO_Write(0x3Cf,gfxReg3CE[5]&0xf0); //Force read/write mode 0 - - //Set Map to all planes. Celtic Tales - index3C4 = IO_Read(0x3c4); IO_Write(0x3C4,2); - gfxReg3C5 = IO_Read(0x3C5); IO_Write(0x3C5,0xF); - } else if (machine==MCH_EGA) { - //Set Map to all planes. - IO_Write(0x3C4,2); - IO_Write(0x3C5,0xF); - } -} - -void RestoreVgaRegisters() { - if (IS_VGA_ARCH) { - for (Bit8u i=0; i<9; i++) { - IO_Write(0x3CE,i); - IO_Write(0x3CF,gfxReg3CE[i]); - } - - IO_Write(0x3C4,2); - IO_Write(0x3C5,gfxReg3C5); - IO_Write(0x3C4,index3C4); - } -} - -void ClipCursorArea(Bit16s& x1, Bit16s& x2, Bit16s& y1, Bit16s& y2, - Bit16u& addx1, Bit16u& addx2, Bit16u& addy) { - addx1 = addx2 = addy = 0; - // Clip up - if (y1<0) { - addy += (-y1); - y1 = 0; - } - // Clip down - if (y2>mouse.clipy) { - y2 = mouse.clipy; - }; - // Clip left - if (x1<0) { - addx1 += (-x1); - x1 = 0; - }; - // Clip right - if (x2>mouse.clipx) { - addx2 = x2 - mouse.clipx; - x2 = mouse.clipx; - }; -} - -void RestoreCursorBackground() { - if (mouse.hidden || mouse.inhibit_draw) return; - - SaveVgaRegisters(); - if (mouse.background) { - // Restore background - Bit16s x,y; - Bit16u addx1,addx2,addy; - Bit16u dataPos = 0; - Bit16s x1 = mouse.backposx; - Bit16s y1 = mouse.backposy; - Bit16s x2 = x1 + CURSORX - 1; - Bit16s y2 = y1 + CURSORY - 1; - - ClipCursorArea(x1, x2, y1, y2, addx1, addx2, addy); - - dataPos = addy * CURSORX; - for (y=y1; y<=y2; y++) { - dataPos += addx1; - for (x=x1; x<=x2; x++) { - INT10_PutPixel(x,y,mouse.page,mouse.backData[dataPos++]); - }; - dataPos += addx2; - }; - mouse.background = false; - }; - RestoreVgaRegisters(); -} - -void DrawCursor() { - if (mouse.hidden || mouse.inhibit_draw) return; - // In Textmode ? - if (CurMode->type==M_TEXT) { - DrawCursorText(); - return; - } - - // Check video page. Seems to be ignored for text mode. - // hence the text mode handled above this - if (real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)!=mouse.page) return; -// Check if cursor in update region -/* if ((POS_X >= mouse.updateRegion_x[0]) && (POS_X <= mouse.updateRegion_x[1]) && - (POS_Y >= mouse.updateRegion_y[0]) && (POS_Y <= mouse.updateRegion_y[1])) { - if (CurMode->type==M_TEXT16) - RestoreCursorBackgroundText(); - else - RestoreCursorBackground(); - mouse.shown--; - return; - } - */ /*Not sure yet what to do update region should be set to ??? */ - - // Get Clipping ranges - - - mouse.clipx = (Bit16s)((Bits)CurMode->swidth-1); /* Get from bios ? */ - mouse.clipy = (Bit16s)((Bits)CurMode->sheight-1); - - /* might be vidmode == 0x13?2:1 */ - Bit16s xratio = 640; - if (CurMode->swidth>0) xratio/=CurMode->swidth; - if (xratio==0) xratio = 1; - - RestoreCursorBackground(); - - SaveVgaRegisters(); - - // Save Background - Bit16s x,y; - Bit16u addx1,addx2,addy; - Bit16u dataPos = 0; - Bit16s x1 = POS_X / xratio - mouse.hotx; - Bit16s y1 = POS_Y - mouse.hoty; - Bit16s x2 = x1 + CURSORX - 1; - Bit16s y2 = y1 + CURSORY - 1; - - ClipCursorArea(x1,x2,y1,y2, addx1, addx2, addy); - - dataPos = addy * CURSORX; - for (y=y1; y<=y2; y++) { - dataPos += addx1; - for (x=x1; x<=x2; x++) { - INT10_GetPixel(x,y,mouse.page,&mouse.backData[dataPos++]); - }; - dataPos += addx2; - }; - mouse.background= true; - mouse.backposx = POS_X / xratio - mouse.hotx; - mouse.backposy = POS_Y - mouse.hoty; - - // Draw Mousecursor - dataPos = addy * CURSORX; - for (y=y1; y<=y2; y++) { - Bit16u scMask = mouse.screenMask[addy+y-y1]; - Bit16u cuMask = mouse.cursorMask[addy+y-y1]; - if (addx1>0) { scMask<<=addx1; cuMask<<=addx1; dataPos += addx1; }; - for (x=x1; x<=x2; x++) { - Bit8u pixel = 0; - // ScreenMask - if (scMask & HIGHESTBIT) pixel = mouse.backData[dataPos]; - scMask<<=1; - // CursorMask - if (cuMask & HIGHESTBIT) pixel = pixel ^ 0x0F; - cuMask<<=1; - // Set Pixel - INT10_PutPixel(x,y,mouse.page,pixel); - dataPos++; - }; - dataPos += addx2; - }; - RestoreVgaRegisters(); -} - -void Mouse_CursorMoved(float xrel,float yrel,float x,float y,bool emulate) { - float dx = xrel * mouse.pixelPerMickey_x; - float dy = yrel * mouse.pixelPerMickey_y; - - if((fabs(xrel) > 1.0) || (mouse.senv_x < 1.0)) dx *= mouse.senv_x; - if((fabs(yrel) > 1.0) || (mouse.senv_y < 1.0)) dy *= mouse.senv_y; - if (useps2callback) dy *= 2; - - mouse.mickey_x += dx; - mouse.mickey_y += dy; - if (emulate) { - mouse.x += dx; - mouse.y += dy; - } else { - if (CurMode->type == M_TEXT) { - mouse.x = x*CurMode->swidth; - mouse.y = y*CurMode->sheight * 8 / CurMode->cheight; - } else if ((mouse.max_x < 2048) || (mouse.max_y < 2048) || (mouse.max_x != mouse.max_y)) { - if ((mouse.max_x > 0) && (mouse.max_y > 0)) { - mouse.x = x*mouse.max_x; - mouse.y = y*mouse.max_y; - } else { - mouse.x += xrel; - mouse.y += yrel; - } - } else { // Games faking relative movement through absolute coordinates. Quite surprising that this actually works.. - mouse.x += xrel; - mouse.y += yrel; - } - } - - /* ignore constraints if using PS2 mouse callback in the bios */ - - if (!useps2callback) { - if (mouse.x > mouse.max_x) mouse.x = mouse.max_x; - if (mouse.x < mouse.min_x) mouse.x = mouse.min_x; - if (mouse.y > mouse.max_y) mouse.y = mouse.max_y; - if (mouse.y < mouse.min_y) mouse.y = mouse.min_y; - } - Mouse_AddEvent(MOUSE_HAS_MOVED); - DrawCursor(); -} - -void Mouse_CursorSet(float x,float y) { - mouse.x=x; - mouse.y=y; - DrawCursor(); -} - -void Mouse_ButtonPressed(Bit8u button) { - switch (button) { - case 0: - mouse.buttons|=1; - Mouse_AddEvent(MOUSE_LEFT_PRESSED); - break; - case 1: - mouse.buttons|=2; - Mouse_AddEvent(MOUSE_RIGHT_PRESSED); - break; - case 2: - mouse.buttons|=4; - Mouse_AddEvent(MOUSE_MIDDLE_PRESSED); - break; - } - mouse.times_pressed[button]++; - mouse.last_pressed_x[button]=POS_X; - mouse.last_pressed_y[button]=POS_Y; -} - -void Mouse_ButtonReleased(Bit8u button) { - switch (button) { - case 0: - mouse.buttons&=~1; - Mouse_AddEvent(MOUSE_LEFT_RELEASED); - break; - case 1: - mouse.buttons&=~2; - Mouse_AddEvent(MOUSE_RIGHT_RELEASED); - break; - case 2: - mouse.buttons&=~4; - Mouse_AddEvent(MOUSE_MIDDLE_RELEASED); - break; - } - mouse.times_released[button]++; - mouse.last_released_x[button]=POS_X; - mouse.last_released_y[button]=POS_Y; -} - -static void Mouse_SetMickeyPixelRate(Bit16s px, Bit16s py){ - if ((px!=0) && (py!=0)) { - mouse.mickeysPerPixel_x = (float)px/X_MICKEY; - mouse.mickeysPerPixel_y = (float)py/Y_MICKEY; - mouse.pixelPerMickey_x = X_MICKEY/(float)px; - mouse.pixelPerMickey_y = Y_MICKEY/(float)py; - } -} - -static void Mouse_SetSensitivity(Bit16u px, Bit16u py, Bit16u dspeed){ - if(px>100) px=100; - if(py>100) py=100; - if(dspeed>100) dspeed=100; - // save values - mouse.senv_x_val=px; - mouse.senv_y_val=py; - mouse.dspeed_val=dspeed; - if ((px!=0) && (py!=0)) { - px--; //Inspired by cutemouse - py--; //Although their cursor update routine is far more complex then ours - mouse.senv_x=(static_cast(px)*px)/3600.0f +1.0f/3.0f; - mouse.senv_y=(static_cast(py)*py)/3600.0f +1.0f/3.0f; - } -} - - -static void Mouse_ResetHardware(void){ - PIC_SetIRQMask(MOUSE_IRQ,false); -} - -//Does way to much. Many things should be moved to mouse reset one day -void Mouse_NewVideoMode(void) { - mouse.inhibit_draw=false; - /* Get the correct resolution from the current video mode */ - Bit8u mode=mem_readb(BIOS_VIDEO_MODE); - if(mode == mouse.mode) {LOG(LOG_MOUSE,LOG_NORMAL)("New video is the same as the old"); /*return;*/} - switch (mode) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: { - Bitu rows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS); - if ((rows==0) || (rows>250)) rows=25-1; - mouse.max_y=8*(rows+1)-1; - break; - } - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0a: - case 0x0d: - case 0x0e: - case 0x13: - mouse.max_y=199; - break; - case 0x0f: - case 0x10: - mouse.max_y=349; - break; - case 0x11: - case 0x12: - mouse.max_y=479; - break; - default: - LOG(LOG_MOUSE,LOG_ERROR)("Unhandled videomode %X on reset",mode); - mouse.inhibit_draw=true; - return; - } - mouse.mode = mode; - mouse.hidden = 1; - mouse.max_x = 639; - mouse.min_x = 0; - mouse.min_y = 0; - - mouse.events = 0; - mouse.timer_in_progress = false; - PIC_RemoveEvents(MOUSE_Limit_Events); - - mouse.hotx = 0; - mouse.hoty = 0; - mouse.background = false; - mouse.screenMask = defaultScreenMask; - mouse.cursorMask = defaultCursorMask; - mouse.textAndMask= defaultTextAndMask; - mouse.textXorMask= defaultTextXorMask; - mouse.language = 0; - mouse.page = 0; - mouse.doubleSpeedThreshold = 64; - mouse.updateRegion_x[0] = 1; - mouse.updateRegion_y[0] = 1; - mouse.updateRegion_x[1] = 1; - mouse.updateRegion_y[1] = 1; - mouse.cursorType = 0; - mouse.enabled=true; - mouse.oldhidden=1; - - oldmouseX = static_cast(mouse.x); - oldmouseY = static_cast(mouse.y); - - -} - -//Much too empty, Mouse_NewVideoMode contains stuff that should be in here -static void Mouse_Reset(void) { - /* Remove drawn mouse Legends of Valor */ - if (CurMode->type!=M_TEXT) RestoreCursorBackground(); - else RestoreCursorBackgroundText(); - mouse.hidden = 1; - - Mouse_NewVideoMode(); - Mouse_SetMickeyPixelRate(8,16); - - mouse.mickey_x = 0; - mouse.mickey_y = 0; - - // Dont set max coordinates here. it is done by SetResolution! - mouse.x = static_cast((mouse.max_x + 1)/ 2); - mouse.y = static_cast((mouse.max_y + 1)/ 2); - mouse.sub_mask = 0; - mouse.in_UIR = false; -} - -static Bitu INT33_Handler(void) { -// LOG(LOG_MOUSE,LOG_NORMAL)("MOUSE: %04X %X %X %d %d",reg_ax,reg_bx,reg_cx,POS_X,POS_Y); - switch (reg_ax) { - case 0x00: /* Reset Driver and Read Status */ - Mouse_ResetHardware(); /* fallthrough */ - case 0x21: /* Software Reset */ - reg_ax=0xffff; - reg_bx=MOUSE_BUTTONS; - Mouse_Reset(); - Mouse_AutoLock(true); - break; - case 0x01: /* Show Mouse */ - if(mouse.hidden) mouse.hidden--; - Mouse_AutoLock(true); - DrawCursor(); - break; - case 0x02: /* Hide Mouse */ - { - if (CurMode->type!=M_TEXT) RestoreCursorBackground(); - else RestoreCursorBackgroundText(); - mouse.hidden++; - } - break; - case 0x03: /* Return position and Button Status */ - reg_bx=mouse.buttons; - reg_cx=POS_X; - reg_dx=POS_Y; - break; - case 0x04: /* Position Mouse */ - /* If position isn't different from current position - * don't change it then. (as position is rounded so numbers get - * lost when the rounded number is set) (arena/simulation Wolf) */ - if ((Bit16s)reg_cx >= mouse.max_x) mouse.x = static_cast(mouse.max_x); - else if (mouse.min_x >= (Bit16s)reg_cx) mouse.x = static_cast(mouse.min_x); - else if ((Bit16s)reg_cx != POS_X) mouse.x = static_cast(reg_cx); - - if ((Bit16s)reg_dx >= mouse.max_y) mouse.y = static_cast(mouse.max_y); - else if (mouse.min_y >= (Bit16s)reg_dx) mouse.y = static_cast(mouse.min_y); - else if ((Bit16s)reg_dx != POS_Y) mouse.y = static_cast(reg_dx); - DrawCursor(); - break; - case 0x05: /* Return Button Press Data */ - { - Bit16u but=reg_bx; - reg_ax=mouse.buttons; - if (but>=MOUSE_BUTTONS) but = MOUSE_BUTTONS - 1; - reg_cx=mouse.last_pressed_x[but]; - reg_dx=mouse.last_pressed_y[but]; - reg_bx=mouse.times_pressed[but]; - mouse.times_pressed[but]=0; - break; - } - case 0x06: /* Return Button Release Data */ - { - Bit16u but=reg_bx; - reg_ax=mouse.buttons; - if (but>=MOUSE_BUTTONS) but = MOUSE_BUTTONS - 1; - reg_cx=mouse.last_released_x[but]; - reg_dx=mouse.last_released_y[but]; - reg_bx=mouse.times_released[but]; - mouse.times_released[but]=0; - break; - } - case 0x07: /* Define horizontal cursor range */ - { //lemmings set 1-640 and wants that. iron seeds set 0-640 but doesn't like 640 - //Iron seed works if newvideo mode with mode 13 sets 0-639 - //Larry 6 actually wants newvideo mode with mode 13 to set it to 0-319 - Bit16s max,min; - if ((Bit16s)reg_cx<(Bit16s)reg_dx) { min=(Bit16s)reg_cx;max=(Bit16s)reg_dx;} - else { min=(Bit16s)reg_dx;max=(Bit16s)reg_cx;} - mouse.min_x=min; - mouse.max_x=max; - /* Battlechess wants this */ - if(mouse.x > mouse.max_x) mouse.x = mouse.max_x; - if(mouse.x < mouse.min_x) mouse.x = mouse.min_x; - /* Or alternatively this: - mouse.x = (mouse.max_x - mouse.min_x + 1)/2;*/ - LOG(LOG_MOUSE,LOG_NORMAL)("Define Hortizontal range min:%d max:%d",min,max); - } - break; - case 0x08: /* Define vertical cursor range */ - { // not sure what to take instead of the CurMode (see case 0x07 as well) - // especially the cases where sheight= 400 and we set it with the mouse_reset to 200 - //disabled it at the moment. Seems to break syndicate who want 400 in mode 13 - Bit16s max,min; - if ((Bit16s)reg_cx<(Bit16s)reg_dx) { min=(Bit16s)reg_cx;max=(Bit16s)reg_dx;} - else { min=(Bit16s)reg_dx;max=(Bit16s)reg_cx;} - mouse.min_y=min; - mouse.max_y=max; - /* Battlechess wants this */ - if(mouse.y > mouse.max_y) mouse.y = mouse.max_y; - if(mouse.y < mouse.min_y) mouse.y = mouse.min_y; - /* Or alternatively this: - mouse.y = (mouse.max_y - mouse.min_y + 1)/2;*/ - LOG(LOG_MOUSE,LOG_NORMAL)("Define Vertical range min:%d max:%d",min,max); - } - break; - case 0x09: /* Define GFX Cursor */ - { - PhysPt src = SegPhys(es)+reg_dx; - MEM_BlockRead(src ,userdefScreenMask,CURSORY*2); - MEM_BlockRead(src+CURSORY*2,userdefCursorMask,CURSORY*2); - mouse.screenMask = userdefScreenMask; - mouse.cursorMask = userdefCursorMask; - mouse.hotx = reg_bx; - mouse.hoty = reg_cx; - mouse.cursorType = 2; - DrawCursor(); - } - break; - case 0x0a: /* Define Text Cursor */ - mouse.cursorType = reg_bx; - mouse.textAndMask = reg_cx; - mouse.textXorMask = reg_dx; - break; - case 0x0b: /* Read Motion Data */ - reg_cx=(Bit16s)(mouse.mickey_x*mouse.mickeysPerPixel_x); - reg_dx=(Bit16s)(mouse.mickey_y*mouse.mickeysPerPixel_y); - mouse.mickey_x=0; - mouse.mickey_y=0; - break; - case 0x0c: /* Define interrupt subroutine parameters */ - mouse.sub_mask=reg_cx; - mouse.sub_seg=SegValue(es); - mouse.sub_ofs=reg_dx; - Mouse_AutoLock(true); //Some games don't seem to reset the mouse before using - break; - case 0x0f: /* Define mickey/pixel rate */ - Mouse_SetMickeyPixelRate(reg_cx,reg_dx); - break; - case 0x10: /* Define screen region for updating */ - mouse.updateRegion_x[0]=reg_cx; - mouse.updateRegion_y[0]=reg_dx; - mouse.updateRegion_x[1]=reg_si; - mouse.updateRegion_y[1]=reg_di; - break; - case 0x11: /* Get number of buttons */ - reg_ax=0xffff; - reg_bx=MOUSE_BUTTONS; - break; - case 0x13: /* Set double-speed threshold */ - mouse.doubleSpeedThreshold=(reg_bx ? reg_bx : 64); - break; - case 0x14: /* Exchange event-handler */ - { - Bit16u oldSeg = mouse.sub_seg; - Bit16u oldOfs = mouse.sub_ofs; - Bit16u oldMask= mouse.sub_mask; - // Set new values - mouse.sub_mask= reg_cx; - mouse.sub_seg = SegValue(es); - mouse.sub_ofs = reg_dx; - // Return old values - reg_cx = oldMask; - reg_dx = oldOfs; - SegSet16(es,oldSeg); - } - break; - case 0x15: /* Get Driver storage space requirements */ - reg_bx = sizeof(mouse); - break; - case 0x16: /* Save driver state */ - { - LOG(LOG_MOUSE,LOG_WARN)("Saving driver state..."); - PhysPt dest = SegPhys(es)+reg_dx; - MEM_BlockWrite(dest, &mouse, sizeof(mouse)); - } - break; - case 0x17: /* load driver state */ - { - LOG(LOG_MOUSE,LOG_WARN)("Loading driver state..."); - PhysPt src = SegPhys(es)+reg_dx; - MEM_BlockRead(src, &mouse, sizeof(mouse)); - } - break; - case 0x1a: /* Set mouse sensitivity */ - // ToDo : double mouse speed value - Mouse_SetSensitivity(reg_bx,reg_cx,reg_dx); - - LOG(LOG_MOUSE,LOG_WARN)("Set sensitivity used with %d %d (%d)",reg_bx,reg_cx,reg_dx); - break; - case 0x1b: /* Get mouse sensitivity */ - reg_bx = mouse.senv_x_val; - reg_cx = mouse.senv_y_val; - reg_dx = mouse.dspeed_val; - - LOG(LOG_MOUSE,LOG_WARN)("Get sensitivity %d %d",reg_bx,reg_cx); - break; - case 0x1c: /* Set interrupt rate */ - /* Can't really set a rate this is host determined */ - break; - case 0x1d: /* Set display page number */ - mouse.page=reg_bl; - break; - case 0x1e: /* Get display page number */ - reg_bx=mouse.page; - break; - case 0x1f: /* Disable Mousedriver */ - /* ES:BX old mouse driver Zero at the moment TODO */ - reg_bx=0; - SegSet16(es,0); - mouse.enabled=false; /* Just for reporting not doing a thing with it */ - mouse.oldhidden=mouse.hidden; - mouse.hidden=1; - break; - case 0x20: /* Enable Mousedriver */ - mouse.enabled=true; - mouse.hidden=mouse.oldhidden; - break; - case 0x22: /* Set language for messages */ - /* - * Values for mouse driver language: - * - * 00h English - * 01h French - * 02h Dutch - * 03h German - * 04h Swedish - * 05h Finnish - * 06h Spanish - * 07h Portugese - * 08h Italian - * - */ - mouse.language=reg_bx; - break; - case 0x23: /* Get language for messages */ - reg_bx=mouse.language; - break; - case 0x24: /* Get Software version and mouse type */ - reg_bx=0x805; //Version 8.05 woohoo - reg_ch=0x04; /* PS/2 type */ - reg_cl=0; /* PS/2 (unused) */ - break; - case 0x26: /* Get Maximum virtual coordinates */ - reg_bx=(mouse.enabled ? 0x0000 : 0xffff); - reg_cx=(Bit16u)mouse.max_x; - reg_dx=(Bit16u)mouse.max_y; - break; - default: - LOG(LOG_MOUSE,LOG_ERROR)("Mouse Function %04X not implemented!",reg_ax); - break; - } - return CBRET_NONE; -} - -static Bitu MOUSE_BD_Handler(void) { - // the stack contains offsets to register values - Bit16u raxpt=real_readw(SegValue(ss),reg_sp+0x0a); - Bit16u rbxpt=real_readw(SegValue(ss),reg_sp+0x08); - Bit16u rcxpt=real_readw(SegValue(ss),reg_sp+0x06); - Bit16u rdxpt=real_readw(SegValue(ss),reg_sp+0x04); - - // read out the actual values, registers ARE overwritten - Bit16u rax=real_readw(SegValue(ds),raxpt); - reg_ax=rax; - reg_bx=real_readw(SegValue(ds),rbxpt); - reg_cx=real_readw(SegValue(ds),rcxpt); - reg_dx=real_readw(SegValue(ds),rdxpt); -// LOG_MSG("MOUSE BD: %04X %X %X %X %d %d",reg_ax,reg_bx,reg_cx,reg_dx,POS_X,POS_Y); - - // some functions are treated in a special way (additional registers) - switch (rax) { - case 0x09: /* Define GFX Cursor */ - case 0x16: /* Save driver state */ - case 0x17: /* load driver state */ - SegSet16(es,SegValue(ds)); - break; - case 0x0c: /* Define interrupt subroutine parameters */ - case 0x14: /* Exchange event-handler */ - if (reg_bx!=0) SegSet16(es,reg_bx); - else SegSet16(es,SegValue(ds)); - break; - case 0x10: /* Define screen region for updating */ - reg_cx=real_readw(SegValue(ds),rdxpt); - reg_dx=real_readw(SegValue(ds),rdxpt+2); - reg_si=real_readw(SegValue(ds),rdxpt+4); - reg_di=real_readw(SegValue(ds),rdxpt+6); - break; - default: - break; - } - - INT33_Handler(); - - // save back the registers, too - real_writew(SegValue(ds),raxpt,reg_ax); - real_writew(SegValue(ds),rbxpt,reg_bx); - real_writew(SegValue(ds),rcxpt,reg_cx); - real_writew(SegValue(ds),rdxpt,reg_dx); - switch (rax) { - case 0x1f: /* Disable Mousedriver */ - real_writew(SegValue(ds),rbxpt,SegValue(es)); - break; - case 0x14: /* Exchange event-handler */ - real_writew(SegValue(ds),rcxpt,SegValue(es)); - break; - default: - break; - } - - reg_ax=rax; - return CBRET_NONE; -} - -static Bitu INT74_Handler(void) { - if (mouse.events>0) { - mouse.events--; - /* Check for an active Interrupt Handler that will get called */ - if (mouse.sub_mask & mouse.event_queue[mouse.events].type) { - reg_ax=mouse.event_queue[mouse.events].type; - reg_bx=mouse.event_queue[mouse.events].buttons; - reg_cx=POS_X; - reg_dx=POS_Y; - reg_si=(Bit16s)(mouse.mickey_x*mouse.mickeysPerPixel_x); - reg_di=(Bit16s)(mouse.mickey_y*mouse.mickeysPerPixel_y); - CPU_Push16(RealSeg(CALLBACK_RealPointer(int74_ret_callback))); - CPU_Push16(RealOff(CALLBACK_RealPointer(int74_ret_callback))); - SegSet16(cs, mouse.sub_seg); - reg_ip = mouse.sub_ofs; - if(mouse.in_UIR) LOG(LOG_MOUSE,LOG_ERROR)("Already in UIR!"); - mouse.in_UIR = true; - } else if (useps2callback) { - CPU_Push16(RealSeg(CALLBACK_RealPointer(int74_ret_callback))); - CPU_Push16(RealOff(CALLBACK_RealPointer(int74_ret_callback))); - DoPS2Callback(mouse.event_queue[mouse.events].buttons, POS_X, POS_Y); - } else { - SegSet16(cs, RealSeg(CALLBACK_RealPointer(int74_ret_callback))); - reg_ip = RealOff(CALLBACK_RealPointer(int74_ret_callback)); - } - } else { - SegSet16(cs, RealSeg(CALLBACK_RealPointer(int74_ret_callback))); - reg_ip = RealOff(CALLBACK_RealPointer(int74_ret_callback)); - } - return CBRET_NONE; -} - -Bitu MOUSE_UserInt_CB_Handler(void) { - mouse.in_UIR = false; - if (mouse.events) { - if (!mouse.timer_in_progress) { - mouse.timer_in_progress = true; - PIC_AddEvent(MOUSE_Limit_Events,MOUSE_DELAY); - } - } - return CBRET_NONE; -} - -void MOUSE_Init(Section* /*sec*/) { - // Callback for mouse interrupt 0x33 - call_int33=CALLBACK_Allocate(); -// RealPt i33loc=RealMake(CB_SEG+1,(call_int33*CB_SIZE)-0x10); - RealPt i33loc=RealMake(DOS_GetMemory(0x1)-1,0x10); - CALLBACK_Setup(call_int33,&INT33_Handler,CB_MOUSE,Real2Phys(i33loc),"Mouse"); - // Wasteland needs low(seg(int33))!=0 and low(ofs(int33))!=0 - real_writed(0,0x33<<2,i33loc); - - call_mouse_bd=CALLBACK_Allocate(); - CALLBACK_Setup(call_mouse_bd,&MOUSE_BD_Handler,CB_RETF8, - PhysMake(RealSeg(i33loc),RealOff(i33loc)+2),"MouseBD"); - // pseudocode for CB_MOUSE (including the special backdoor entry point): - // jump near i33hd - // callback MOUSE_BD_Handler - // retf 8 - // label i33hd: - // callback INT33_Handler - // iret - - - // Callback for ps2 irq - call_int74=CALLBACK_Allocate(); - CALLBACK_Setup(call_int74,&INT74_Handler,CB_IRQ12,"int 74"); - // pseudocode for CB_IRQ12: - // push ds - // push es - // pushad - // sti - // callback INT74_Handler - // doesn't return here, but rather to CB_IRQ12_RET - // (ps2 callback/user callback inbetween if requested) - - int74_ret_callback=CALLBACK_Allocate(); - CALLBACK_Setup(int74_ret_callback,&MOUSE_UserInt_CB_Handler,CB_IRQ12_RET,"int 74 ret"); - // pseudocode for CB_IRQ12_RET: - // callback MOUSE_UserInt_CB_Handler - // cli - // mov al, 0x20 - // out 0xa0, al - // out 0x20, al - // popad - // pop es - // pop ds - // iret - - Bit8u hwvec=(MOUSE_IRQ>7)?(0x70+MOUSE_IRQ-8):(0x8+MOUSE_IRQ); - RealSetVec(hwvec,CALLBACK_RealPointer(call_int74)); - - // Callback for ps2 user callback handling - useps2callback = false; ps2callbackinit = false; - call_ps2=CALLBACK_Allocate(); - CALLBACK_Setup(call_ps2,&PS2_Handler,CB_RETF,"ps2 bios callback"); - ps2_callback=CALLBACK_RealPointer(call_ps2); - - memset(&mouse,0,sizeof(mouse)); - mouse.hidden = 1; //Hide mouse on startup - mouse.timer_in_progress = false; - mouse.mode = 0xFF; //Non existing mode - - mouse.sub_mask=0; - mouse.sub_seg=0x6362; // magic value - mouse.sub_ofs=0; - - Mouse_ResetHardware(); - Mouse_Reset(); - Mouse_SetSensitivity(50,50,50); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include +#include "dosbox.h" +#include "callback.h" +#include "mem.h" +#include "regs.h" +#include "mouse.h" +#include "pic.h" +#include "inout.h" + + +static Bitu call_int33,call_int74; + +struct button_event { + Bit16u type; + Bit16u buttons; +}; + +#define QUEUE_SIZE 32 +//TODO Maybe use :) +#define MOUSE_IRQ 12 +#define POS_X (Bit16s)(mouse.x*mouse.range_x) +#define POS_Y (Bit16s)(mouse.y*mouse.range_y) + + +static struct { + Bit16u buttons; + Bit16u times_pressed[3]; + Bit16u times_released[3]; + Bit16u last_released_x[3]; + Bit16u last_released_y[3]; + Bit16u last_pressed_x[3]; + Bit16u last_pressed_y[3]; + Bit16s shown; + float add_x,add_y; + Bit16u min_x,max_x,min_y,max_y; + float range_x,range_y; + float mickey_x,mickey_y; + float x,y; + button_event event_queue[QUEUE_SIZE]; + Bit32u events; + Bit16u sub_seg,sub_ofs; + Bit16u sub_mask; +} mouse; + +#define X_MICKEY 500 +#define Y_MICKEY 500 + +#define MOUSE_MOVED 1 +#define MOUSE_LEFT_PRESSED 2 +#define MOUSE_LEFT_RELEASED 4 +#define MOUSE_RIGHT_PRESSED 8 +#define MOUSE_RIGHT_RELEASED 16 +#define MOUSE_MIDDLE_PRESSED 32 +#define MOUSE_MIDDLE_RELEASED 64 + +inline void Mouse_AddEvent(Bit16u type) { + if (mouse.events1) mouse.x=1; + if (mouse.x<0) mouse.x=0; + mouse.y+=y; + if (mouse.y>1) mouse.y=1; + if (mouse.y<0) mouse.y=0; + Mouse_AddEvent(MOUSE_MOVED); +} + +void Mouse_CursorSet(float x,float y) { + + mouse.x=x; + mouse.y=y; +} + +void Mouse_ButtonPressed(Bit8u button) { + switch (button) { + case 0: + mouse.buttons|=1; + Mouse_AddEvent(MOUSE_LEFT_PRESSED); + break; + case 1: + mouse.buttons|=2; + Mouse_AddEvent(MOUSE_RIGHT_PRESSED); + break; + case 2: + mouse.buttons|=4; + Mouse_AddEvent(MOUSE_MIDDLE_PRESSED); + break; + } + mouse.times_pressed[button]++; + mouse.last_pressed_x[button]=POS_X; + mouse.last_pressed_y[button]=POS_Y; +} + +void Mouse_ButtonReleased(Bit8u button) { + switch (button) { + case 0: + mouse.buttons&=~1; + Mouse_AddEvent(MOUSE_LEFT_RELEASED); + break; + case 1: + mouse.buttons&=~2; + Mouse_AddEvent(MOUSE_RIGHT_RELEASED); + break; + case 2: + mouse.buttons&=~4; + Mouse_AddEvent(MOUSE_MIDDLE_RELEASED); + break; + } + mouse.times_released[button]++; + mouse.last_released_x[button]=POS_X; + mouse.last_released_y[button]=POS_Y; +} + + +static void mouse_reset(void) { + real_writed(0,(0x33<<2),CALLBACK_RealPointer(call_int33)); + real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74)); + mouse.shown=-1; + mouse.min_x=0; + mouse.max_x=639; + mouse.min_y=0; + mouse.max_y=199; + mouse.range_x=639; + mouse.range_y=199; + mouse.x=320; + mouse.y=100; + mouse.events=0; + mouse.mickey_x=0; + mouse.mickey_y=0; + mouse.sub_mask=0; + mouse.sub_seg=0; + mouse.sub_ofs=0; +}; + + +static Bitu INT33_Handler(void) { + switch (reg_ax) { + case 0x00: /* Reset Driver and Read Status */ + reg_ax=0xffff; + reg_bx=0; + mouse_reset(); + break; + case 0x01: /* Show Mouse */ + mouse.shown++; + if (mouse.shown>0) mouse.shown=0; + break; + case 0x02: /* Hide Mouse */ + mouse.shown--; + break; + case 0x03: /* Return position and Button Status */ + reg_bx=mouse.buttons; + reg_cx=POS_X; + reg_dx=POS_Y; + break; + case 0x04: /* Position Mouse */ + mouse.x=((float)reg_cx)/mouse.range_x; + mouse.y=((float)reg_dx)/mouse.range_y; + break; + case 0x05: /* Return Button Press Data */ + { + Bit16u but=reg_bx; + reg_ax=mouse.buttons; + reg_cx=mouse.last_pressed_x[but]; + mouse.last_pressed_x[but]=0; + reg_dx=mouse.last_pressed_y[but]; + mouse.last_pressed_y[but]=0; + reg_bx=mouse.times_pressed[but]; + mouse.times_pressed[but]=0; + break; + } + case 0x07: /* Define horizontal cursor range */ + mouse.min_x=reg_cx; + mouse.max_x=reg_dx; + mouse.range_x=mouse.max_x-mouse.min_x; +//TODO Check for range start 0 + break; + case 0x08: /* Define vertical cursor range */ + mouse.min_y=reg_cx; + mouse.max_y=reg_dx; + mouse.range_y=mouse.max_y-mouse.min_y; + break; + case 0x09: /* Define GFX Cursor */ + LOG_WARN("MOUSE:Define gfx cursor not supported"); + break; + case 0x0a: /* Define Text Cursor */ + /* Don't see much need for supporting this */ + break; + case 0x0c: /* Define interrupt subroutine parameters */ + mouse.sub_mask=reg_cx; + mouse.sub_seg=Segs[es].value; + mouse.sub_ofs=reg_dx; + break; + case 0x0f: /* Define mickey/pixel rate */ + //TODO Maybe dunno for sure might be possible */ + break; + case 0x0B: /* Read Motion Data */ + reg_cx=(Bit16s)(mouse.mickey_x*X_MICKEY); + reg_dx=(Bit16s)(mouse.mickey_y*Y_MICKEY); + mouse.mickey_x=0; + mouse.mickey_y=0; + break; + case 0x1c: /* Set interrupt rate */ + /* Can't really set a rate this is host determined */ + break; + case 0x21: /* Software Reset */ + //TODO reset internal mouse software variables likes mickeys + reg_ax=0xffff; + reg_bx=2; + break; + case 0x24: /* Get Software version and mouse type */ + reg_bx=0x805; //Version 8.05 woohoo + reg_ch=0xff; /* Unkown type */ + reg_cl=0; /* Hmm ps2 irq dunno */ + break; + default: + LOG_ERROR("Mouse Function %2X",reg_ax); + }; + return CBRET_NONE; +}; + +static Bitu INT74_Handler(void) { + if (mouse.events>0) { + mouse.events--; + /* Check for an active Interrupt Handler that will get called */ + if (mouse.sub_mask & mouse.event_queue[mouse.events].type) { + /* Save lot's of registers */ + Bit16u oldax,oldbx,oldcx,olddx,oldsi,olddi; + oldax=reg_ax;oldbx=reg_bx;oldcx=reg_cx;olddx=reg_dx;oldsi=reg_si;olddi=reg_di; + reg_ax=mouse.event_queue[mouse.events].type; + reg_bx=mouse.event_queue[mouse.events].buttons; + reg_cx=POS_X; + reg_dx=POS_Y; + reg_si=(Bit16s)(mouse.mickey_x*X_MICKEY); + reg_di=(Bit16s)(mouse.mickey_y*Y_MICKEY); + if (mouse.event_queue[mouse.events].type==MOUSE_MOVED) { + mouse.mickey_x=0; + mouse.mickey_y=0; + } + CALLBACK_RunRealFar(mouse.sub_seg,mouse.sub_ofs); + reg_ax=oldax;reg_bx=oldbx;reg_cx=oldcx;reg_dx=olddx;reg_si=oldsi;reg_di=olddi; + } + } + IO_Write(0xa0,0x20); + /* Check for more Events if so reactivate IRQ */ + + if (mouse.events) { + PIC_ActivateIRQ(12); + } + + return CBRET_NONE; +}; + + +void MOUSE_Init(void) { + call_int33=CALLBACK_Allocate(); + CALLBACK_Setup(call_int33,&INT33_Handler,CB_IRET); + real_writed(0,(0x33<<2),CALLBACK_RealPointer(call_int33)); + + call_int74=CALLBACK_Allocate(); + CALLBACK_Setup(call_int74,&INT74_Handler,CB_IRET); + real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74)); + + memset((void *)&mouse,0,sizeof(mouse)); + mouse_reset(); +}; + diff --git a/src/ints/xms.cpp b/src/ints/xms.cpp index bc6702d..d5f2c77 100644 --- a/src/ints/xms.cpp +++ b/src/ints/xms.cpp @@ -1,482 +1,185 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: xms.cpp,v 1.54 2009/02/01 14:24:38 qbix79 Exp $ */ - -#include -#include -#include "dosbox.h" -#include "callback.h" -#include "mem.h" -#include "regs.h" -#include "dos_inc.h" -#include "setup.h" -#include "inout.h" -#include "xms.h" -#include "bios.h" - -#define XMS_HANDLES 50 /* 50 XMS Memory Blocks */ -#define XMS_VERSION 0x0300 /* version 3.00 */ -#define XMS_DRIVER_VERSION 0x0301 /* my driver version 3.01 */ - -#define XMS_GET_VERSION 0x00 -#define XMS_ALLOCATE_HIGH_MEMORY 0x01 -#define XMS_FREE_HIGH_MEMORY 0x02 -#define XMS_GLOBAL_ENABLE_A20 0x03 -#define XMS_GLOBAL_DISABLE_A20 0x04 -#define XMS_LOCAL_ENABLE_A20 0x05 -#define XMS_LOCAL_DISABLE_A20 0x06 -#define XMS_QUERY_A20 0x07 -#define XMS_QUERY_FREE_EXTENDED_MEMORY 0x08 -#define XMS_ALLOCATE_EXTENDED_MEMORY 0x09 -#define XMS_FREE_EXTENDED_MEMORY 0x0a -#define XMS_MOVE_EXTENDED_MEMORY_BLOCK 0x0b -#define XMS_LOCK_EXTENDED_MEMORY_BLOCK 0x0c -#define XMS_UNLOCK_EXTENDED_MEMORY_BLOCK 0x0d -#define XMS_GET_EMB_HANDLE_INFORMATION 0x0e -#define XMS_RESIZE_EXTENDED_MEMORY_BLOCK 0x0f -#define XMS_ALLOCATE_UMB 0x10 -#define XMS_DEALLOCATE_UMB 0x11 -#define XMS_QUERY_ANY_FREE_MEMORY 0x88 -#define XMS_ALLOCATE_ANY_MEMORY 0x89 -#define XMS_GET_EMB_HANDLE_INFORMATION_EXT 0x8e -#define XMS_RESIZE_ANY_EXTENDED_MEMORY_BLOCK 0x8f - -#define XMS_FUNCTION_NOT_IMPLEMENTED 0x80 -#define HIGH_MEMORY_NOT_EXIST 0x90 -#define HIGH_MEMORY_IN_USE 0x91 -#define HIGH_MEMORY_NOT_ALLOCATED 0x93 -#define XMS_OUT_OF_SPACE 0xa0 -#define XMS_OUT_OF_HANDLES 0xa1 -#define XMS_INVALID_HANDLE 0xa2 -#define XMS_INVALID_SOURCE_HANDLE 0xa3 -#define XMS_INVALID_SOURCE_OFFSET 0xa4 -#define XMS_INVALID_DEST_HANDLE 0xa5 -#define XMS_INVALID_DEST_OFFSET 0xa6 -#define XMS_INVALID_LENGTH 0xa7 -#define XMS_BLOCK_NOT_LOCKED 0xaa -#define XMS_BLOCK_LOCKED 0xab -#define UMB_ONLY_SMALLER_BLOCK 0xb0 -#define UMB_NO_BLOCKS_AVAILABLE 0xb1 - -struct XMS_Block { - Bitu size; - MemHandle mem; - Bit8u locked; - bool free; -}; - -#ifdef _MSC_VER -#pragma pack (1) -#endif -struct XMS_MemMove{ - Bit32u length; - Bit16u src_handle; - union { - RealPt realpt; - Bit32u offset; - } src; - Bit16u dest_handle; - union { - RealPt realpt; - Bit32u offset; - } dest; - -} GCC_ATTRIBUTE(packed); -#ifdef _MSC_VER -#pragma pack () -#endif - - -Bitu XMS_EnableA20(bool enable) { - Bit8u val = IO_Read (0x92); - if (enable) IO_Write(0x92,val | 2); - else IO_Write(0x92,val & ~2); - return 0; -} - -Bitu XMS_GetEnabledA20(void) { - return (IO_Read(0x92)&2)>0; -} - -static RealPt xms_callback; -static bool umb_available; - -static XMS_Block xms_handles[XMS_HANDLES]; - -static INLINE bool InvalidHandle(Bitu handle) { - return (!handle || (handle>=XMS_HANDLES) || xms_handles[handle].free); -} - -Bitu XMS_QueryFreeMemory(Bit16u& largestFree, Bit16u& totalFree) { - /* Scan the tree for free memory and find largest free block */ - totalFree=(Bit16u)(MEM_FreeTotal()*4); - largestFree=(Bit16u)(MEM_FreeLargest()*4); - if (!totalFree) return XMS_OUT_OF_SPACE; - return 0; -} - -Bitu XMS_AllocateMemory(Bitu size, Bit16u& handle) { // size = kb - /* Find free handle */ - Bit16u index=1; - while (!xms_handles[index].free) { - if (++index>=XMS_HANDLES) return XMS_OUT_OF_HANDLES; - } - MemHandle mem; - if (size!=0) { - Bitu pages=(size/4) + ((size & 3) ? 1 : 0); - mem=MEM_AllocatePages(pages,true); - if (!mem) return XMS_OUT_OF_SPACE; - } else { - mem=MEM_GetNextFreePage(); - if (mem==0) LOG(LOG_MISC,LOG_ERROR)("XMS:Allocate zero pages with no memory left"); - } - xms_handles[index].free=false; - xms_handles[index].mem=mem; - xms_handles[index].locked=0; - xms_handles[index].size=size; - handle=index; - return 0; -} - -Bitu XMS_FreeMemory(Bitu handle) { - if (InvalidHandle(handle)) return XMS_INVALID_HANDLE; - MEM_ReleasePages(xms_handles[handle].mem); - xms_handles[handle].mem=-1; - xms_handles[handle].size=0; - xms_handles[handle].free=true; - return 0; -} - -Bitu XMS_MoveMemory(PhysPt bpt) { - /* Read the block with mem_read's */ - Bitu length=mem_readd(bpt+offsetof(XMS_MemMove,length)); - Bitu src_handle=mem_readw(bpt+offsetof(XMS_MemMove,src_handle)); - union { - RealPt realpt; - Bit32u offset; - } src,dest; - src.offset=mem_readd(bpt+offsetof(XMS_MemMove,src.offset)); - Bitu dest_handle=mem_readw(bpt+offsetof(XMS_MemMove,dest_handle)); - dest.offset=mem_readd(bpt+offsetof(XMS_MemMove,dest.offset)); - PhysPt srcpt,destpt; - if (src_handle) { - if (InvalidHandle(src_handle)) { - return XMS_INVALID_SOURCE_HANDLE; - } - if (src.offset>=(xms_handles[src_handle].size*1024U)) { - return XMS_INVALID_SOURCE_OFFSET; - } - if (length>xms_handles[src_handle].size*1024U-src.offset) { - return XMS_INVALID_LENGTH; - } - srcpt=(xms_handles[src_handle].mem*4096)+src.offset; - } else { - srcpt=Real2Phys(src.realpt); - } - if (dest_handle) { - if (InvalidHandle(dest_handle)) { - return XMS_INVALID_DEST_HANDLE; - } - if (dest.offset>=(xms_handles[dest_handle].size*1024U)) { - return XMS_INVALID_DEST_OFFSET; - } - if (length>xms_handles[dest_handle].size*1024U-dest.offset) { - return XMS_INVALID_LENGTH; - } - destpt=(xms_handles[dest_handle].mem*4096)+dest.offset; - } else { - destpt=Real2Phys(dest.realpt); - } -// LOG_MSG("XMS move src %X dest %X length %X",srcpt,destpt,length); - mem_memcpy(destpt,srcpt,length); - return 0; -} - -Bitu XMS_LockMemory(Bitu handle, Bit32u& address) { - if (InvalidHandle(handle)) return XMS_INVALID_HANDLE; - if (xms_handles[handle].locked<255) xms_handles[handle].locked++; - address = xms_handles[handle].mem*4096; - return 0; -} - -Bitu XMS_UnlockMemory(Bitu handle) { - if (InvalidHandle(handle)) return XMS_INVALID_HANDLE; - if (xms_handles[handle].locked) { - xms_handles[handle].locked--; - return 0; - } - return XMS_BLOCK_NOT_LOCKED; -} - -Bitu XMS_GetHandleInformation(Bitu handle, Bit8u& lockCount, Bit8u& numFree, Bit16u& size) { - if (InvalidHandle(handle)) return XMS_INVALID_HANDLE; - lockCount = xms_handles[handle].locked; - /* Find available blocks */ - numFree=0; - for (Bitu i=1;i0) return XMS_BLOCK_LOCKED; - Bitu pages=newSize/4 + ((newSize & 3) ? 1 : 0); - if (MEM_ReAllocatePages(xms_handles[handle].mem,pages,true)) { - xms_handles[handle].size = newSize; - return 0; - } else return XMS_OUT_OF_SPACE; -} - -static bool multiplex_xms(void) { - switch (reg_ax) { - case 0x4300: /* XMS installed check */ - reg_al=0x80; - return true; - case 0x4310: /* XMS handler seg:offset */ - SegSet16(es,RealSeg(xms_callback)); - reg_bx=RealOff(xms_callback); - return true; - } - return false; - -} - -INLINE void SET_RESULT(Bitu res,bool touch_bl_on_succes=true) { - if(touch_bl_on_succes || res) reg_bl = (Bit8u)res; - reg_ax = (res==0); -} - -Bitu XMS_Handler(void) { -// LOG(LOG_MISC,LOG_ERROR)("XMS: CALL %02X",reg_ah); - switch (reg_ah) { - case XMS_GET_VERSION: /* 00 */ - reg_ax=XMS_VERSION; - reg_bx=XMS_DRIVER_VERSION; - reg_dx=0; /* No we don't have HMA */ - break; - case XMS_ALLOCATE_HIGH_MEMORY: /* 01 */ - reg_ax=0; - reg_bl=HIGH_MEMORY_NOT_EXIST; - break; - case XMS_FREE_HIGH_MEMORY: /* 02 */ - reg_ax=0; - reg_bl=HIGH_MEMORY_NOT_EXIST; - break; - - case XMS_GLOBAL_ENABLE_A20: /* 03 */ - case XMS_LOCAL_ENABLE_A20: /* 05 */ - SET_RESULT(XMS_EnableA20(true)); - break; - case XMS_GLOBAL_DISABLE_A20: /* 04 */ - case XMS_LOCAL_DISABLE_A20: /* 06 */ - SET_RESULT(XMS_EnableA20(false)); - break; - case XMS_QUERY_A20: /* 07 */ - reg_ax = XMS_GetEnabledA20(); - reg_bl = 0; - break; - case XMS_QUERY_FREE_EXTENDED_MEMORY: /* 08 */ - reg_bl = XMS_QueryFreeMemory(reg_ax,reg_dx); - break; - case XMS_ALLOCATE_ANY_MEMORY: /* 89 */ - reg_edx &= 0xffff; - // fall through - case XMS_ALLOCATE_EXTENDED_MEMORY: /* 09 */ - { - Bit16u handle = 0; - SET_RESULT(XMS_AllocateMemory(reg_dx,handle)); - reg_dx = handle; - }; break; - case XMS_FREE_EXTENDED_MEMORY: /* 0a */ - SET_RESULT(XMS_FreeMemory(reg_dx)); - break; - case XMS_MOVE_EXTENDED_MEMORY_BLOCK: /* 0b */ - SET_RESULT(XMS_MoveMemory(SegPhys(ds)+reg_si),false); - break; - case XMS_LOCK_EXTENDED_MEMORY_BLOCK: { /* 0c */ - Bit32u address; - Bitu res = XMS_LockMemory(reg_dx, address); - if(res) reg_bl = (Bit8u)res; - reg_ax = (res==0); - if (res==0) { // success - reg_bx=(Bit16u)(address & 0xFFFF); - reg_dx=(Bit16u)(address >> 16); - }; - }; break; - case XMS_UNLOCK_EXTENDED_MEMORY_BLOCK: /* 0d */ - SET_RESULT(XMS_UnlockMemory(reg_dx)); - break; - case XMS_GET_EMB_HANDLE_INFORMATION: /* 0e */ - SET_RESULT(XMS_GetHandleInformation(reg_dx,reg_bh,reg_bl,reg_dx),false); - break; - case XMS_RESIZE_ANY_EXTENDED_MEMORY_BLOCK: /* 0x8f */ - if(reg_ebx > reg_bx) LOG_MSG("64MB memory limit!"); - //fall through - case XMS_RESIZE_EXTENDED_MEMORY_BLOCK: /* 0f */ - SET_RESULT(XMS_ResizeMemory(reg_dx, reg_bx)); - break; - case XMS_ALLOCATE_UMB: { /* 10 */ - if (!umb_available) { - reg_ax=0; - reg_bl=XMS_FUNCTION_NOT_IMPLEMENTED; - break; - } - Bit16u umb_start=dos_infoblock.GetStartOfUMBChain(); - if (umb_start==0xffff) { - reg_ax=0; - reg_bl=UMB_NO_BLOCKS_AVAILABLE; - reg_dx=0; // no upper memory available - break; - } - /* Save status and linkage of upper UMB chain and link upper - memory to the regular MCB chain */ - Bit8u umb_flag=dos_infoblock.GetUMBChainState(); - if ((umb_flag&1)==0) DOS_LinkUMBsToMemChain(1); - Bit8u old_memstrat=DOS_GetMemAllocStrategy()&0xff; - DOS_SetMemAllocStrategy(0x40); // search in UMBs only - - Bit16u size=reg_dx;Bit16u seg; - if (DOS_AllocateMemory(&seg,&size)) { - reg_ax=1; - reg_bx=seg; - } else { - reg_ax=0; - if (size==0) reg_bl=UMB_NO_BLOCKS_AVAILABLE; - else reg_bl=UMB_ONLY_SMALLER_BLOCK; - reg_dx=size; // size of largest available UMB - } - - /* Restore status and linkage of upper UMB chain */ - Bit8u current_umb_flag=dos_infoblock.GetUMBChainState(); - if ((current_umb_flag&1)!=(umb_flag&1)) DOS_LinkUMBsToMemChain(umb_flag); - DOS_SetMemAllocStrategy(old_memstrat); - } - break; - case XMS_DEALLOCATE_UMB: /* 11 */ - if (!umb_available) { - reg_ax=0; - reg_bl=XMS_FUNCTION_NOT_IMPLEMENTED; - break; - } - if (dos_infoblock.GetStartOfUMBChain()!=0xffff) { - if (DOS_FreeMemory(reg_dx)) { - reg_ax=0x0001; - break; - } - } - reg_ax=0x0000; - reg_bl=UMB_NO_BLOCKS_AVAILABLE; - break; - case XMS_QUERY_ANY_FREE_MEMORY: /* 88 */ - reg_bl = XMS_QueryFreeMemory(reg_ax,reg_dx); - reg_eax &= 0xffff; - reg_edx &= 0xffff; - reg_ecx = (MEM_TotalPages()*MEM_PAGESIZE)-1; // highest known physical memory address - break; - case XMS_GET_EMB_HANDLE_INFORMATION_EXT: { /* 8e */ - Bit8u free_handles; - Bitu result = XMS_GetHandleInformation(reg_dx,reg_bh,free_handles,reg_dx); - if (result != 0) reg_bl = result; - else { - reg_edx &= 0xffff; - reg_cx = free_handles; - } - reg_ax = (result==0); - } break; - default: - LOG(LOG_MISC,LOG_ERROR)("XMS: unknown function %02X",reg_ah); - reg_ax=0; - reg_bl=XMS_FUNCTION_NOT_IMPLEMENTED; - } -// LOG(LOG_MISC,LOG_ERROR)("XMS: CALL Result: %02X",reg_bl); - return CBRET_NONE; -} - -class XMS: public Module_base { -private: - CALLBACK_HandlerObject callbackhandler; -public: - XMS(Section* configuration):Module_base(configuration){ - Section_prop * section=static_cast(configuration); - umb_available=false; - if (!section->Get_bool("xms")) return; - Bitu i; - BIOS_ZeroExtendedSize(true); - DOS_AddMultiplexHandler(multiplex_xms); - - /* place hookable callback in writable memory area */ - xms_callback=RealMake(DOS_GetMemory(0x1)-1,0x10); - callbackhandler.Install(&XMS_Handler,CB_HOOKABLE,Real2Phys(xms_callback),"XMS Handler"); - // pseudocode for CB_HOOKABLE: - // jump near skip - // nop,nop,nop - // label skip: - // callback XMS_Handler - // retf - - for (i=0;iGet_bool("umb"); - DOS_BuildUMBChain(section->Get_bool("umb"),section->Get_bool("ems")); - } - - ~XMS(){ - Section_prop * section = static_cast(m_configuration); - /* Remove upper memory information */ - dos_infoblock.SetStartOfUMBChain(0xffff); - if (umb_available) { - dos_infoblock.SetUMBChainState(0); - umb_available=false; - } - - if (!section->Get_bool("xms")) return; - /* Undo biosclearing */ - BIOS_ZeroExtendedSize(false); - - /* Remove Multiplex */ - DOS_DelMultiplexHandler(multiplex_xms); - - /* Free used memory while skipping the 0 handle */ - for (Bitu i = 1;iAddDestroyFunction(&XMS_ShutDown,true); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "dosbox.h" +#include "callback.h" +#include "mem.h" +#include "regs.h" +#include "dos_system.h" + + +#define XMS_VERSION 0x0300 /* version 3.00 */ +#define XMS_DRIVER_VERSION 0x0301 /* my driver version 3.01 */ + +#define XMS_GET_VERSION 0x00 +#define XMS_ALLOCATE_HIGH_MEMORY 0x01 +#define XMS_FREE_HIGH_MEMORY 0x02 +#define XMS_GLOBAL_ENABLE_A20 0x03 +#define XMS_GLOBAL_DISABLE_A20 0x04 +#define XMS_LOCAL_ENABLE_A20 0x05 +#define XMS_LOCAL_DISABLE_A20 0x06 +#define XMS_QUERY_A20 0x07 +#define XMS_QUERY_FREE_EXTENDED_MEMORY 0x08 +#define XMS_ALLOCATE_EXTENDED_MEMORY 0x09 +#define XMS_FREE_EXTENDED_MEMORY 0x0a +#define XMS_MOVE_EXTENDED_MEMORY_BLOCK 0x0b +#define XMS_LOCK_EXTENDED_MEMORY_BLOCK 0x0c +#define XMS_UNLOCK_EXTENDED_MEMORY_BLOCK 0x0d +#define XMS_GET_EMB_HANDLE_INFORMATION 0x0e +#define XMS_RESIZE_EXTENDED_MEMORY_BLOCK 0x0f +#define XMS_ALLOCATE_UMB 0x10 +#define XMS_DEALLOCATE_UMB 0x11 + +#define HIGH_MEMORY_IN_USE 0x92 +#define HIGH_MEMORY_NOT_ALLOCATED 0x93 +#define XMS_OUT_OF_SPACE 0xa0 +#define XMS_INVALID_HANDLE 0xa2 + + +static Bit16u call_xms; +static RealPt xms_callback; + + +static bool multiplex_xms(void) { + switch (reg_ax) { + case 0x4300: /* XMS installed check */ + reg_al=0x80; + return true; + case 0x4310: /* XMS handler seg:offset */ + SetSegment_16(es,RealSeg(xms_callback)); + reg_bx=RealOff(xms_callback); + return true; + } + return false; + +}; + +#if defined (_MSC_VER) +#pragma pack(1) +#endif +struct XMS_MemMove{ + Bit32u length; + Bit16u src_handle; + RealPt src_offset; + Bit16u dest_handle; + RealPt dest_offset; +} +#if defined (_MSC_VER) +; +#pragma pack() +#else +__attribute__ ((packed)); +#endif + +static void XMS_MoveBlock(PhysOff block,Bit8u * result) { + XMS_MemMove moveblock; +//TODO Will not work on other endian, probably base it on a class would be nice + MEM_BlockRead(block,(Bit8u *)&moveblock,sizeof(XMS_MemMove)); + HostOff src; + PhysOff dest; + if (moveblock.src_handle) { + src=memory+EMM_Handles[moveblock.src_handle].phys_base+moveblock.src_offset; + } else { + src=Real2Host(moveblock.src_offset); + } + if (moveblock.dest_handle) { + dest=EMM_Handles[moveblock.dest_handle].phys_base+moveblock.dest_offset; + } else { + dest=Real2Phys(moveblock.dest_offset); + } + //memcpy((void *)dest,(void *)src,moveblock.length); + MEM_BlockWrite(dest,src,moveblock.length); + *result=0; +}; + + +Bitu XMS_Handler(void) { + switch (reg_ah) { + case XMS_GET_VERSION: /* 00 */ + reg_ax=XMS_VERSION; + reg_bx=XMS_DRIVER_VERSION; + reg_dx=0; //TODO HMA Maybe + break; + case XMS_ALLOCATE_HIGH_MEMORY: /* 01 */ + case XMS_FREE_HIGH_MEMORY: /* 02 */ + case XMS_GLOBAL_ENABLE_A20: /* 03 */ + case XMS_GLOBAL_DISABLE_A20: /* 04 */ + case XMS_LOCAL_ENABLE_A20: /* 05 */ + case XMS_LOCAL_DISABLE_A20: /* 06 */ + case XMS_QUERY_A20: /* 07 */ + LOG_WARN("XMS:Unhandled call %2X",reg_ah);break; + case XMS_QUERY_FREE_EXTENDED_MEMORY: /* 08 */ + EMM_GetFree(®_ax,®_dx); + reg_ax<<=2;reg_dx<<=2; + reg_bl=0; + break; + case XMS_ALLOCATE_EXTENDED_MEMORY: /* 09 */ + EMM_Allocate(PAGES(reg_dx*1024),®_dx); + if (reg_dx) reg_ax=1; + else { reg_ax=0;reg_bl=0xb0; } + break; + case XMS_FREE_EXTENDED_MEMORY: /* 0a */ + EMM_Free(reg_dx); + reg_ax=1; + break; + + case XMS_MOVE_EXTENDED_MEMORY_BLOCK: /* 0b */ + XMS_MoveBlock(real_phys(Segs[ds].value,reg_si),®_bl); + if (reg_bl) reg_ax=0; + else reg_ax=1; + break; + case XMS_LOCK_EXTENDED_MEMORY_BLOCK: /* 0c */ + if ((!EMM_Handles[reg_dx].active) || (EMM_Handles[reg_dx].free)) { + reg_ax=0; + reg_bl=0xa2; /* Invalid block */ + break; + } + reg_ax=1; + reg_bx=(Bit16u)((EMM_Handles[reg_dx].phys_base) & 0xffff); + reg_dx=(Bit16u)((EMM_Handles[reg_dx].phys_base >> 16) & 0xffff); + break; + case XMS_UNLOCK_EXTENDED_MEMORY_BLOCK: /* 0d */ + reg_ax=1; + break; + case XMS_GET_EMB_HANDLE_INFORMATION: /* 0e */ + LOG_WARN("XMS:Unhandled call %2X",reg_ah);break; + case XMS_RESIZE_EXTENDED_MEMORY_BLOCK: /* 0f */ + LOG_WARN("XMS:Unhandled call %2X",reg_ah);break; + case XMS_ALLOCATE_UMB: /* 10 */ + reg_ax=0; + reg_bl=0xb1; //No UMB Available + reg_dx=0; + break; + case XMS_DEALLOCATE_UMB: /* 11 */ + default: + LOG_WARN("XMS:Unhandled call %2X",reg_ah);break; + + } + return CBRET_NONE; +} + + + +void XMS_Init(void) { + DOS_AddMultiplexHandler(multiplex_xms); + call_xms=CALLBACK_Allocate(); + CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF); + xms_callback=CALLBACK_RealPointer(call_xms); +} + diff --git a/src/libs/Makefile.am b/src/libs/Makefile.am deleted file mode 100644 index 1c2cc86..0000000 --- a/src/libs/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include - -SUBDIRS = zmbv gui_tk diff --git a/src/libs/gui_tk/Doxyfile b/src/libs/gui_tk/Doxyfile deleted file mode 100644 index fc7686f..0000000 --- a/src/libs/gui_tk/Doxyfile +++ /dev/null @@ -1,238 +0,0 @@ -# Doxyfile 1.5.2 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = gui::tk -PROJECT_NUMBER = "Version 1.0" -OUTPUT_DIRECTORY = -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = . -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = YES -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -BUILTIN_STL_SUPPORT = YES -CPP_CLI_SUPPORT = NO -DISTRIBUTE_GROUP_DOC = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = NO -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = YES -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = NO -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = . -INPUT_ENCODING = UTF-8 -FILE_PATTERNS = gui_tk.h \ - gui_tk.cpp -RECURSIVE = NO -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = YES -REFERENCES_RELATION = YES -REFERENCES_LINK_SOURCE = YES -USE_HTAGS = NO -VERBATIM_HEADERS = YES -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = NO -COLS_IN_ALPHA_INDEX = 5 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = NO -USE_PDFLATEX = NO -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = TESTING SDL_MAJOR_VERSION -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = DOSBox.tag -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES -MSCGEN_PATH = -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = YES -TEMPLATE_RELATIONS = YES -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = YES -CALLER_GRAPH = YES -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = YES -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -DOT_GRAPH_MAX_NODES = 50 -DOT_TRANSPARENT = YES -DOT_MULTI_TARGETS = YES -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/src/libs/gui_tk/Makefile.am b/src/libs/gui_tk/Makefile.am deleted file mode 100644 index e281609..0000000 --- a/src/libs/gui_tk/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include - -noinst_LIBRARIES = libgui_tk.a -libgui_tk_a_SOURCES = gui_tk.cpp gui_tk.h diff --git a/src/libs/gui_tk/gui_tk.cpp b/src/libs/gui_tk/gui_tk.cpp deleted file mode 100644 index 2a75074..0000000 --- a/src/libs/gui_tk/gui_tk.cpp +++ /dev/null @@ -1,1707 +0,0 @@ -#if 0 -/* - * gui_tk - framework-agnostic GUI toolkit - * Copyright (C) 2005-2007 Jörg Walter - * - * gui_tk is free software; you can 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. - * - * gui_tk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU 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 - */ - -/* TODO: - - make menu a bufferedwindow with shadow -*/ -/* $Id: gui_tk.cpp,v 1.5 2009/02/01 16:06:26 qbix79 Exp $ */ - -/** \file - * \brief Implementation file for gui_tk. - * - * It contains implementations for all non-inlined class methods. - * - * Also contained is a small test program that demonstrates all features of - * gui_tk. It is enabled by defining the preprocessor macro TESTING. - */ - -#include -#include "gui_tk.h" - -namespace GUI { - -namespace Color { - -RGB Background3D = 0xffc0c0c0; - -RGB Light3D = 0xfffcfcfc; - -RGB Shadow3D = 0xff808080; - -RGB Border = 0xff000000; - -RGB Text = 0xff000000; - -RGB Background = 0xffc0c0c0; - -RGB SelectionBackground = 0xff000080; - -RGB SelectionForeground = 0xffffffff; - -RGB EditableBackground = 0xffffffff; - -RGB Titlebar = 0xff000080; - -RGB TitlebarText = 0xffffffff; - -} - -void Drawable::drawText(const String& text, bool interpret, Size start, Size len) { - if (interpret) { - if (len > text.size()-start) len = (Size)(text.size()-start); - len += start; - - Size wordstart = start; - int width = 0; - - while (start < len) { - switch (font->toSpecial(text[start])) { - case Font::CR: - if (wordstart != start) { - drawText(text,false,wordstart,start-wordstart); - wordstart = start; - width = 0; - } - wordstart++; - gotoXY(0,y); - break; - case Font::LF: - if (wordstart != start) { - drawText(text,false,wordstart,start-wordstart); - wordstart = start; - width = 0; - } - wordstart++; - gotoXY(0,y+font->getHeight()); - break; - case Font::BS: - if (wordstart != start) { - drawText(text,false,wordstart,start-wordstart); - wordstart = start; - width = 0; - } - wordstart++; - gotoXY(imax(0,x-font->getWidth()),y); - break; - case Font::Tab: - if (wordstart != start) { - drawText(text,false,wordstart,start-wordstart); - wordstart = start; - width = 0; - } - wordstart++; - gotoXY((((int)(x/font->getWidth()/8))+1)*8*font->getWidth(),y); - break; - case Font::Space: - if (wordstart != start) { - drawText(text,false,wordstart,start-wordstart); - wordstart = start; - width = 0; - } - wordstart++; - font->drawString(this,text,start,1); - break; - case Font::ESC: // ignore ANSI sequences except for colors - if (wordstart != start) { - drawText(text,false,wordstart,start-wordstart); - wordstart = start; - width = 0; - } - wordstart++; - do { - int seqstart = start+1; - Char c; - do { - start++; - wordstart++; - c = font->toSpecial(text[start]); - } while (start < len && ((c >= '0' && c <= '9') || c == ';' || c == '[')); - if (c == 'm' && start < len) { - if (font->toSpecial(text[seqstart++]) != '[') break; - c = font->toSpecial(text[seqstart++]); - while (c != 'm') { - int param = 0; - if (c == ';') c = '0'; - while (c != 'm' && c != ';') { - param = param * 10 + c-'0'; - c = font->toSpecial(text[seqstart++]); - } - const RGB bright = 0x00808080; - const RGB intensity = (color&bright?~0:~bright); - switch (param) { - case 0: setColor(Color::Black); break; - case 1: setColor(color | 0x00808080); break; - case 30: setColor((Color::Black|bright) & intensity); break; - case 31: setColor(Color::Red & intensity); break; - case 32: setColor(Color::Green & intensity); break; - case 33: setColor(Color::Yellow & intensity); break; - case 34: setColor(Color::Blue & intensity); break; - case 35: setColor(Color::Magenta & intensity); break; - case 36: setColor(Color::Cyan & intensity); break; - case 37: setColor(Color::White & intensity); break; - default: break; - } - } - } - } while (0); - default: - width += font->getWidth(text[start]); - if (x > 0 && x+width > cw) gotoXY(0,y+font->getHeight()); - } - start++; - } - if (wordstart != start) drawText(text,false,wordstart,start-wordstart); - return; - } - - font->drawString(this,text,start,len); -} - -bool ToplevelWindow::mouseDown(int x, int y, MouseButton button) { - if (button == Left && x > 32 && x < width-6 && y > 4 && y < 31) { - dragx = x; - dragy = y; - mouseChild = NULL; - systemMenu->setVisible(false); - return true; - } else if (button == Left && x < 32 && x > 6 && y > 4 && y < 31) { - mouseChild = NULL; - raise(); - systemMenu->setVisible(!systemMenu->isVisible()); - return true; - } - systemMenu->setVisible(false); - BorderedWindow::mouseDown(x,y,button); - return true; -} - -Drawable::Drawable(int w, int h, RGB clear) : - buffer(new RGB[w*h]), - width(w), height(h), - owner(true), - color(Color::Black), - font(NULL), - lineWidth(1), - tx(0), ty(0), - cx(0), cy(0), - cw(w), ch(h), - x(0), y(0) -{ - this->clear(clear); -} - -Drawable::Drawable(Drawable &src, RGB clear) : - buffer(new RGB[src.cw*src.ch]), - width(src.cw), height(src.ch), - owner(true), - color(src.color), - font(src.font), - lineWidth(src.lineWidth), - tx(0), ty(0), - cx(0), cy(0), - cw(src.cw), ch(src.ch), - x(src.x), y(src.y) -{ - if (clear != 0) { - this->clear(clear); - } else { - for (int h = 0; h < src.ch; h++) { - memcpy(buffer+src.cw*h,src.buffer+src.width*(h+src.ty)+src.tx,4*src.cw); - } - } -} - -Drawable::Drawable(Drawable &src, int x, int y, int w, int h) : - buffer(src.buffer), - width(src.width), height(src.height), - owner(false), - color(src.color), - font(src.font), - lineWidth(src.lineWidth), - tx(src.tx+x), ty(src.ty+y), - cx(imax(imax(-x,src.cx-x),0)), cy(imax(imax(-y,src.cy-y),0)), - cw(imax(0,imin(src.cw-x,w))), ch(imax(0,imin(src.ch-y,h))), - x(imax(0,imin(src.tx-tx,cw))), y(imax(0,imin(src.ty-ty,cw))) -{ -} - -Drawable::~Drawable() -{ - if (owner) delete[] buffer; -} - -void Drawable::clear(RGB clear) -{ - for (int y = cy; y < ch; y++) { - for (int x = cx; x < cw; x++) { - buffer[(y+ty)*width+x+tx] = clear; - } - } -} - -void Drawable::drawLine(int x2, int y2) -{ - int x0 = x2, x1 = x, y0 = y2, y1 = y; - int dx = x2-x1, dy = y2-y1; - drawPixel(); - - if (abs(dx) > abs(dy)) { - if (x1 > x2) { - x = x2; x2 = x1; x1 = x; - y = y2; y2 = y1; y1 = y; - } - for (x = x1; x <= x2; x++) { - y = y1+(x-x1)*dy/dx-lineWidth/2; - for (int i = 0; i < lineWidth; i++, y++) { - drawPixel(); - } - } - } else if (y1 != y2) { - if (y1 > y2) { - x = x2; x2 = x1; x1 = x; - y = y2; y2 = y1; y1 = y; - } - for (y = y1; y <= y2; y ++) { - x = x1+(y-y1)*dx/dy-lineWidth/2; - for (int i = 0; i < lineWidth; i++, x++) { - drawPixel(); - } - } - } - - drawPixel(x0,y0); -} - -void Drawable::drawCircle(int d) { - int xo = 0, yo = d/2, rest = (d+1)/2-yo, x0 = x, y0 = y, rsq = d*d/4, lwo = lineWidth/2; - - while (xo <= yo) { - while (xo*xo+(2*yo-1)*(2*yo-1)/4 > rsq) yo--; - for (int i = 0, yow = yo+lwo; i < lineWidth; i++, yow--) { - drawPixel(x0+xo,y0-yow-rest); - drawPixel(x0+yow,y0-xo-rest); - drawPixel(x0+yow,y0+xo); - drawPixel(x0+xo,y0+yow); - - drawPixel(x0-xo-rest,y0-yow-rest); - drawPixel(x0-yow-rest,y0-xo-rest); - drawPixel(x0-yow-rest,y0+xo); - drawPixel(x0-xo-rest,y0+yow); - } - - xo++; - } - gotoXY(x0,y0); -} - -void Drawable::drawRect(int w, int h) -{ - gotoXY(x-lineWidth/2,y); - drawLine(x+w+lineWidth-1,y); - gotoXY(x-(lineWidth-1)/2,y); - drawLine(x,y+h); - gotoXY(x+(lineWidth-1)/2,y); - drawLine(x-w-lineWidth+1,y); - gotoXY(x+lineWidth/2,y); - drawLine(x,y-h); -} - -void Drawable::fill() -{ - int x0 = x, xmin; - RGB color = getPixel(); - - if (color == this->color) return; - - for (x--; x >= 0 && getPixel() == color; x--) drawPixel(); - xmin = ++x; - for (x = x0; x < cw && getPixel() == color; x++) drawPixel(); - y++; - for (x--; x >= xmin; x--) { - if (getPixel() == color) fill(); - y -= 2; - if (getPixel() == color) fill(); - y += 2; - } - y--; - x = x0; -} - -void Drawable::fillCircle(int d) -{ - int xo = 0, yo = d/2, rest = (d+1)/2-yo, x0 = x, y0 = y, rsq = d*d/4; - - while (xo <= yo) { - while (xo*xo+(2*yo-1)*(2*yo-1)/4 > rsq) yo--; - x = x0+xo; - for (y = y0-yo-rest; y <= y0+yo; y++) drawPixel(); - x = x0-xo-rest; - for (y = y0-yo-rest; y <= y0+yo; y++) drawPixel(); - - y = y0-xo-rest; - for (x = x0-yo-rest; x <= x0+yo; x++) drawPixel(); - y = y0+xo; - for (x = x0-yo-rest; x <= x0+yo; x++) drawPixel(); - - xo++; - } - gotoXY(x0,y0); -} - -void Drawable::fillRect(int w, int h) -{ - int x0 = x, y0 = y, w0 = w; - for (; h > 0; h--, y++) { - for (x = x0, w = w0; w > 0; w--, x++) { - drawPixel(); - } - } - gotoXY(x0,y0); -} - -void Drawable::drawDrawable(Drawable &d, unsigned char alpha) -{ - int scw = d.cw, sch = d.ch, w, h; - RGB *src, *dest; - - for (h = imax(d.cy,-ty-y); h < sch && y+h < ch; h++) { - src = d.buffer+d.width*(h+d.ty)+d.tx; - dest = buffer+width*(y+ty+h)+tx+x; - for (w = imax(d.cx,-tx-x); w < scw && x+w < cw; w++) { - RGB srcb = src[w], destb = dest[w]; - unsigned int sop = Color::A(srcb)*((unsigned int)alpha)/255; - unsigned int rop = Color::A(destb) + sop - Color::A(destb)*sop/255; - if (rop == 0) { - dest[w] = Color::Transparent; - } else { - unsigned int dop = Color::A(destb)*(255-sop)/255; - unsigned int magval = ((destb&Color::MagentaMask)*dop+(srcb&Color::MagentaMask)*sop); - dest[w] = (((magval&0xffff)/rop)&Color::BlueMask) | - (((magval&0xffff0000)/rop)&Color::RedMask) | - ((((destb&Color::GreenMask)*dop+(srcb&Color::GreenMask)*sop)/rop)&Color::GreenMask) | - (rop<toSpecial(c)) { - case Font::CR: gotoXY(0,y); return; - case Font::LF: gotoXY(0,y+font->getHeight()); return; - case Font::BS: gotoXY(imax(0,x-font->getWidth()),y); return; - case Font::Tab: gotoXY((((int)(x/font->getWidth()/8))+1)*8*font->getWidth(),y); return; - default: break; - } - if (font->getWidth(c)+x > cw) gotoXY(0,y+font->getHeight()); - } - font->drawChar(this,c); -} - -#define move(x) (ptr += ((x)+bit)/8-(((x)+bit)<0), bit = ((x)+bit+(((x)+bit)<0?8:0))%8) -void BitmapFont::drawChar(Drawable *d, const Char c) const { - const unsigned char *ptr = bitmap; - int bit = 0; - - if (c > last) return; - - if (char_position != NULL) { - ptr = char_position[c]; - bit = 0; - } else { - move(character_step*((int)c)); - } - - int rs = row_step; - int w = (widths != NULL?widths[c]:width); - int h = (ascents != NULL?ascents[c]:height); - Drawable out(*d,d->getX(),d->getY()-ascent,w,h); - - if (rs == 0) rs = isign(col_step)*w; - if (rs < 0) move(-rs*(h-1)); - if (col_step < 0) move(abs(rs)-1); - - for (int row = height-h; row < height; row++, move(rs-w*col_step)) { - for (int col = 0; col < w; col++, move(col_step)) { - if (!background_set ^ !(*ptr&(1<gotoXY(d->getX()+w,d->getY()); -} -#undef move - -std::map Font::registry; - -void Timer::check(unsigned int ticks) -{ - if (timers.empty()) return; - - if (Timer::ticks > (Timer::ticks+ticks)) { - ticks -= -1-Timer::ticks; - check(-1-Timer::ticks); - } - - std::multimap::iterator old, i = timers.lower_bound(Timer::ticks+1); - Timer::ticks += ticks; - - while (i != timers.end() && (*i).first <= Timer::ticks) { - Timer_Callback *c = (*i).second; - unsigned int time = (*i).first; - old = i; - ++i; - timers.erase(old); - unsigned int next = c->timerExpired(time); - if (next) add(c, time+next-Timer::ticks); - } -} - -void Timer::remove(const Timer_Callback *const timer) -{ - if (timers.empty()) return; - - std::multimap::iterator old, i = timers.begin(); - - while (i != timers.end()) { - old = i; - ++i; - if ((*old).second == timer) timers.erase(old); - } -} - -unsigned int Timer::next() -{ - if (timers.empty()) return 0; - - std::multimap::iterator i = timers.upper_bound(ticks); - - if (i == timers.end()) return 0; - return (*i).first-Timer::ticks; -} - -std::multimap Timer::timers; -unsigned int Timer::ticks = 0; - -BitmapFont::BitmapFont(const unsigned char *data, int height, int ascent, bool owner, - int width, bool background_set, - int col_step, int row_step, int character_step, Char last, - const int *widths, const int *ascents, const unsigned char *const* char_position, - const Font::SpecialChar *special) : - bitmap(data), - width(width), height(height), ascent(ascent), widths(widths), ascents(ascents), - background_set(background_set), col_step(col_step), row_step(row_step), - character_step(character_step?character_step:abs((row_step?row_step:width*col_step)*height)), - char_position(char_position), special(special), owner(owner), last(last) -{ -} - -BitmapFont::~BitmapFont() { - if (owner) { - if (bitmap != NULL) delete bitmap; - if (ascents != NULL) delete ascents; - if (widths != NULL) delete widths; - if (special != NULL) delete special; - } -} - -Window::Window(Window *parent, int x, int y, int w, int h) : - width(w), height(h), - x(x), y(y), - dirty(true), - visible(true), - parent(parent), - mouseChild(NULL) -{ - parent->addChild(this); -} - -Window::Window() : - width(0), height(0), - x(0), y(0), - dirty(false), - visible(true), - parent(NULL), - mouseChild(NULL) -{ -} - - -Window::~Window() -{ - while (!children.empty()) delete children.front(); - if (parent) parent->removeChild(this); - if (parent && parent->mouseChild == this) parent->mouseChild = NULL; -} - -void Window::addChild(Window *child) -{ - children.push_back(child); - setDirty(); -} - -void Window::removeChild(Window *child) -{ - children.remove(child); - setDirty(); -} - -void Window::move(int x, int y) -{ - this->x = x; - this->y = y; - std::list::iterator i = movehandlers.begin(); - bool end = (i == movehandlers.end()); - while (!end) { - Window_Callback *c = *i; - ++i; - end = (i == movehandlers.end()); - c->windowMoved(this,x,y); - } - parent->setDirty(); -} - -void Window::resize(int w, int h) -{ - this->width = w; - this->height = h; - setDirty(); -} - -void Window::paintAll(Drawable &d) const -{ - paint(d); - std::list::const_iterator i = children.begin(); - while (i != children.end()) { - Window *child = *i; - ++i; - if (child->visible) { - Drawable *cd = new Drawable(d,child->x,child->y,child->width,child->height); - child->paintAll(*cd); - delete cd; - } - } -} - -bool Window::keyDown(const Key &key) -{ - if (children.empty()) return false; - if ((*children.rbegin())->keyDown(key)) return true; - if (key.ctrl || key.alt || key.windows || key.special != Key::Tab) return false; - - if (key.shift) { - std::list::reverse_iterator i = children.rbegin(), e = children.rend(); - ++i; - while (i != e && !(*i)->raise()) ++i; - return i != e; - } else { - std::list::iterator i = children.begin(), e = children.end(); - while (i != e && !(*i)->raise()) ++i; - return (i != e); - } -} - -bool Window::keyUp(const Key &key) -{ - if (children.empty()) return false; - return (*children.rbegin())->keyUp(key); -} - -bool Window::mouseMoved(int x, int y) -{ - std::list::reverse_iterator i = children.rbegin(); - bool end = (i == children.rend()); - while (!end) { - Window *w = *i; - i++; - end = (i == children.rend()); - if (w->visible && x >= w->x && x <= w->x+w->width - && y >= w->y && y <= w->y+w->height - && w->mouseMoved(x-w->x, y-w->y)) return true; - } - return false; -} - -bool Window::mouseDragged(int x, int y, MouseButton button) -{ - if (mouseChild == NULL) return false; - return mouseChild->mouseDragged(x-mouseChild->x, y-mouseChild->y, button); -} - -bool Window::mouseDown(int x, int y, MouseButton button) -{ - Window *last = NULL; - std::list::reverse_iterator i = children.rbegin(); - bool end = (i == children.rend()); - while (!end) { - Window *w = *i; - i++; - end = (i == children.rend()); - if (w->visible && x >= w->x && x <= w->x+w->width - && y >= w->y && y <= w->y+w->height - && (mouseChild = last = w) - && w->mouseDown(x-w->x, y-w->y, button) - && w->raise()) { - return true; - } - } - mouseChild = NULL; - if (last != NULL) last->raise(); - return false; -} - -bool Window::mouseUp(int x, int y, MouseButton button) -{ - if (mouseChild == NULL) return false; - return mouseChild->mouseUp(x-mouseChild->x, y-mouseChild->y, button); -} - -bool Window::mouseClicked(int x, int y, MouseButton button) -{ - if (mouseChild == NULL) return false; - return mouseChild->mouseClicked(x-mouseChild->x, y-mouseChild->y, button); -} - -bool Window::mouseDoubleClicked(int x, int y, MouseButton button) -{ - if (mouseChild == NULL) return false; - return mouseChild->mouseDoubleClicked(x-mouseChild->x, y-mouseChild->y, button); -} - -bool BorderedWindow::mouseDown(int x, int y, MouseButton button) -{ - mouseChild = NULL; - if (x > width-border_right || y > width-border_bottom) return false; - x -= border_left; y -= border_top; - if (x < 0 || y < 0) return false; - return Window::mouseDown(x,y,button); -} - -bool BorderedWindow::mouseMoved(int x, int y) -{ - if (x > width-border_right || y > width-border_bottom) return false; - x -= border_left; y -= border_top; - if (x < 0 || y < 0) return false; - return Window::mouseMoved(x,y); -} - -bool BorderedWindow::mouseDragged(int x, int y, MouseButton button) -{ - if (x > width-border_right || y > width-border_bottom) return false; - x -= border_left; y -= border_top; - if (x < 0 || y < 0) return false; - return Window::mouseDragged(x,y,button); -} - -void ToplevelWindow::paint(Drawable &d) const -{ - int mask = (systemMenu->isVisible()?Color::RedMask|Color::GreenMask|Color::BlueMask:0); - d.clear(Color::Background); - - d.setColor(Color::Border); - d.drawLine(0,height-1,width-1,height-1); - d.drawLine(width-1,0,width-1,height-1); - - d.setColor(Color::Shadow3D); - d.drawLine(0,0,width-2,0); - d.drawLine(0,0,0,height-2); - d.drawLine(0,height-2,width-2,height-2); - d.drawLine(width-2,0,width-2,height-2); - - d.drawLine(5,4,width-7,4); - d.drawLine(5,4,5,30); - - d.setColor(Color::Light3D); - d.drawLine(1,1,width-3,1); - d.drawLine(1,1,1,height-3); - - d.drawLine(5,31,width-6,31); - d.drawLine(width-6,5,width-6,31); - - d.setColor(Color::Background3D^mask); - d.fillRect(6,5,26,26); - d.setColor(Color::Grey50^mask); - d.fillRect(9,17,20,4); - d.setColor(Color::Black^mask); - d.fillRect(8,16,20,4); - d.setColor(Color::White^mask); - d.fillRect(9,17,18,2); - - d.setColor(Color::Border); - d.drawLine(32,5,32,30); - - d.setColor(Color::Titlebar); - d.fillRect(33,5,width-39,26); - - const Font *font = Font::getFont("title"); - d.setColor(Color::TitlebarText); - d.setFont(font); - d.drawText(31+(width-39-font->getWidth(title))/2,5+(26-font->getHeight())/2+font->getAscent(),title,false,0); -} - -void Input::paint(Drawable &d) const -{ - d.clear(Color::EditableBackground); - - d.setColor(Color::Shadow3D); - d.drawLine(0,0,width-2,0); - d.drawLine(0,0,0,height-2); - - d.setColor(Color::Background3D); - d.drawLine(1,height-2,width-2,height-2); - d.drawLine(width-2,1,width-2,height-2); - - d.setColor(Color::Text); - d.drawLine(1,1,width-3,1); - d.drawLine(1,1,1,height-3); - - const Font *f = Font::getFont("input"); - d.setFont(f); - - Drawable d1(d,3,4,width-6,height-8); - Drawable dr(d1,(multi?0:-offset),(multi?-offset:0),width-6+(multi?0:offset),height-8+(multi?offset:0)); - - const Size start = imin(start_sel, end_sel), end = imax(start_sel, end_sel); - dr.drawText(0,f->getAscent()+1,text,multi,0,start); - - int sx = dr.getX(), sy = dr.getY(); - dr.drawText(text, multi, start, end-start); - int ex = dr.getX(), ey = dr.getY(); - - if (sx != ex || sy != ey) { - dr.setColor(Color::SelectionBackground); - if (sy == ey) dr.fillRect(sx,sy-f->getAscent(),ex-sx,f->getHeight()+1); - else { - dr.fillRect(sx, sy-f->getAscent(), width-sx+offset, f->getHeight() ); - dr.fillRect(0, sy-f->getAscent()+f->getHeight(), width+offset, ey-sy-f->getHeight()); - dr.fillRect(0, ey-f->getAscent(), ex, f->getHeight() ); - } - dr.setColor(Color::SelectionForeground); - dr.drawText(sx, sy, text, multi, start, end-start); - } - - dr.setColor(Color::Text); - - dr.drawText(text, multi, end); - - if (blink && hasFocus()) { - if (insert) dr.drawLine(posx,posy,posx,posy+f->getHeight()+1); - else dr.fillRect(posx,posy,f->getWidth(text[pos]),f->getHeight()+1); - } -} - -Size Input::findPos(int x, int y) { - const Font *f = Font::getFont("input"); - if (multi) y += offset; - else x += offset; - y = (y-4) / f->getHeight(); - int line = 0; - Size pos = 0; - while (line < y && pos < text.size()) if (f->toSpecial(text[pos++]) == Font::LF) line++; - Drawable d(width-6,1); - d.setFont(f); - while (pos <= text.size() && d.getY() == 0 && x > d.getX()) { - d.drawText(String(text), multi, pos, 1); - pos++; - } - if (pos > 0) pos--; - return pos; -} - -bool Input::mouseDown(int x, int y, MouseButton button) -{ - if (button == Left || (button == Middle && start_sel == end_sel)) { - end_sel = start_sel = pos = findPos(x,y); - blink = true; - checkOffset(); - } - if (button == Middle) keyDown(Key(0,Key::Insert,true,false,false,false)); - return true; -} - -bool Input::mouseDragged(int x, int y, MouseButton button) -{ - if (button == Left) { - end_sel = pos = findPos(x,y); - blink = true; - checkOffset(); - } - return true; -} - -bool Input::keyDown(const Key &key) -{ - const Font *f = Font::getFont("input"); - switch (key.special) { - case Key::None: - if (key.ctrl) { - switch (key.character) { - case 1: - case 'a': - case 'A': - if (key.shift) { - start_sel = end_sel = pos; - } else { - start_sel = 0; - pos = end_sel = (Size)text.size(); - } - break; - case 24: - case 'x': - case 'X': - cutSelection(); - break; - case 3: - case 'c': - case 'C': - copySelection(); - break; - case 22: - case 'v': - case 'V': - pasteSelection(); - break; - default: printf("Ctrl-0x%x\n",key.character); break; - } - break; - } - if (start_sel != end_sel) clearSelection(); - if (insert || pos >= text.size() ) text.insert(text.begin()+pos++,key.character); - else text[pos++] = key.character; - break; - case Key::Left: - if (pos > 0) pos--; - break; - case Key::Right: - if (pos < text.size()) pos++; - break; - case Key::Down: - if (multi) pos = findPos(posx+3, posy-offset+f->getHeight()+4); - break; - case Key::Up: - if (multi) pos = findPos(posx+3, posy-offset-f->getHeight()+4); - break; - case Key::Home: - if (multi) { - while (pos > 0 && f->toSpecial(text[pos-1]) != Font::LF) pos--; - } else pos = 0; - break; - case Key::End: - if (multi) { - while (pos < text.size() && f->toSpecial(text[pos]) != Font::LF) pos++; - } else pos = (Size)text.size(); - break; - case Key::Backspace: - if (!key.shift && start_sel != end_sel) clearSelection(); - else if (pos > 0) text.erase(text.begin()+ --pos); - break; - case Key::Delete: - if (key.shift) cutSelection(); - else if (start_sel != end_sel) clearSelection(); - else if (pos < text.size()) text.erase(text.begin()+pos); - break; - case Key::Insert: - if (key.ctrl) copySelection(); - else if (key.shift) pasteSelection(); - else insert = !insert; - break; - case Key::Enter: - if (multi) { - if (start_sel != end_sel) clearSelection(); - if (insert || pos >= text.size() ) text.insert(text.begin()+pos++,f->fromSpecial(Font::LF)); - else text[pos++] = f->fromSpecial(Font::LF); - } else executeAction(text); - break; - case Key::Tab: - if (multi) { - if (start_sel != end_sel) clearSelection(); - if (insert || pos >= text.size() ) text.insert(text.begin()+pos++,f->fromSpecial(Font::Tab)); - else text[pos++] = f->fromSpecial(Font::Tab); - } else return false; - break; - default: - return false; - } - if (!key.ctrl) { - if (!key.shift || key.special == Key::None) start_sel = end_sel = pos; - else end_sel = pos; - } - checkOffset(); - blink = true; - return true; -} - -void BorderedWindow::paintAll(Drawable &d) const -{ - this->paint(d); - Drawable dchild(d,border_left,border_top,width-border_left-border_right,height-border_top-border_bottom); - for (std::list::const_iterator i = children.begin(); i != children.end(); ++i) { - Window *child = *i; - if (child->isVisible()) { - Drawable cd(dchild,child->getX(),child->getY(),child->getWidth(),child->getHeight()); - child->paintAll(cd); - } - } -} - -void Button::paint(Drawable &d) const -{ - int offset = -1; - - if (hasFocus()) { - offset = 0; - d.setColor(Color::Border); - d.drawLine(0,0,width,0); - d.drawLine(0,0,0,height); - - d.drawLine(0,height-1,width,height-1); - d.drawLine(width-1,0,width-1,height); - } - - d.setColor(Color::Background3D); - d.fillRect(2,2,width-4,height-4); - - if (pressed) { - d.setColor(Color::Shadow3D); - - d.drawLine(1+offset,1+offset,width-2-offset,1+offset); - d.drawLine(1+offset,1+offset,1+offset,height-2-offset); - } else { - d.setColor(Color::Background3D); - - d.drawLine(1+offset,1+offset,width-3-offset,1+offset); - d.drawLine(1+offset,1+offset,1+offset,height-3-offset); - - d.setColor(Color::Light3D); - - d.drawLine(2+offset,2+offset,width-4-offset,2+offset); - d.drawLine(2+offset,2+offset,2+offset,height-4-offset); - - d.setColor(Color::Shadow3D); - - d.drawLine(2+offset,height-3-offset,width-2-offset,height-3-offset); - d.drawLine(width-3-offset,2+offset,width-3-offset,height-2-offset); - - d.setColor(Color::Border); - - d.drawLine(width-2-offset,1+offset,width-2-offset,height-2-offset); - d.drawLine(1+offset,height-2-offset,width-2-offset,height-2-offset); - } -} - -bool Checkbox::keyDown(const Key &key) -{ - switch (key.special) { - case Key::None: - if (key.character != ' ') return false; - case Key::Enter: - break; - default: return false; - } - mouseDown(0,0,Left); - return true; -} - -bool Checkbox::keyUp(const Key &key) -{ - if (key.ctrl || key.alt || key.windows || (key.character != ' ' && key.special != Key::Enter)) return false; - mouseUp(0,0,Left); - mouseClicked(0,0,Left); - return true; -} - -void Checkbox::paint(Drawable &d) const -{ - d.setColor(Color::Background3D); - d.fillRect(2,(height/2)-7,14,14); - - d.setColor(Color::Shadow3D); - d.drawLine(2,(height/2)-7,13,(height/2)-7); - d.drawLine(2,(height/2)-7,2,(height/2)+5); - - d.setColor(Color::Light3D); - d.drawLine(2,(height/2)+5,14,(height/2)+5); - d.drawLine(14,(height/2)-7,14,(height/2)+5); - - d.setColor(Color::EditableBackground); - d.fillRect(4,(height/2)-5,9,9); - - d.setColor(Color::Border); - d.drawLine(3,(height/2)-6,12,(height/2)-6); - d.drawLine(3,(height/2)-6,3,(height/2)+4); - - if (checked) { - d.setColor(Color::Text); - d.drawLine(5,(height/2)-2,7,(height/2) ); - d.drawLine(11,(height/2)-4); - d.drawLine(5,(height/2)-1,7,(height/2)+1); - d.drawLine(11,(height/2)-3); - d.drawLine(5,(height/2) ,7,(height/2)+2); - d.drawLine(11,(height/2)-2); - } -} - -Radiobox::Radiobox(Frame *parent, int x, int y, int w, int h) : BorderedWindow(static_cast(parent),x,y,w,h,16,0,0,0), ActionEventSource("GUI::Radiobox"), checked(0) -{ - addActionHandler(parent); -} - -bool Radiobox::keyDown(const Key &key) -{ - switch (key.special) { - case Key::None: - if (key.character != ' ') return false; - case Key::Enter: - break; - default: return false; - } - mouseDown(0,0,Left); - return true; -} - -bool Radiobox::keyUp(const Key &key) -{ - if (key.ctrl || key.alt || key.windows || (key.character != ' ' && key.special != Key::Enter)) return false; - mouseUp(0,0,Left); - mouseClicked(0,0,Left); - return true; -} - -void Radiobox::paint(Drawable &d) const -{ - d.setColor(Color::Light3D); - d.drawLine(6,(height/2)+6,9,(height/2)+6); - d.drawLine(4,(height/2)+5,11,(height/2)+5); - d.drawLine(13,(height/2)-1,13,(height/2)+2); - d.drawLine(12,(height/2)-2,12,(height/2)+4); - - d.setColor(Color::Background3D); - d.drawLine(6,(height/2)+5,9,(height/2)+5); - d.drawLine(4,(height/2)+4,11,(height/2)+4); - d.drawLine(12,(height/2)-1,12,(height/2)+2); - d.drawLine(11,(height/2)-2,11,(height/2)+4); - - d.setColor(Color::Shadow3D); - d.drawLine(6,(height/2)-5,9,(height/2)-5); - d.drawLine(4,(height/2)-4,11,(height/2)-4); - d.drawLine(2,(height/2)-1,2,(height/2)+2); - d.drawLine(3,(height/2)-3,3,(height/2)+4); - - d.setColor(Color::Border); - d.drawLine(6,(height/2)-4,9,(height/2)-4); - d.drawLine(4,(height/2)-3,11,(height/2)-3); - d.drawLine(3,(height/2)-1,3,(height/2)+2); - d.drawLine(4,(height/2)-3,4,(height/2)+3); - - d.setColor(Color::EditableBackground); - d.fillRect(5,(height/2)-2,6,6); - d.fillRect(4,(height/2)-1,8,4); - d.fillRect(6,(height/2)-3,4,8); - - if (checked) { - d.setColor(Color::Text); - d.fillRect(6,(height/2),4,2); - d.fillRect(7,(height/2)-1,2,4); - } -} - -void Menu::paint(Drawable &d) const -{ - d.clear(Color::Background3D); - - d.setColor(Color::Border); - d.drawLine(0,height-1,width-1,height-1); - d.drawLine(width-1,0,width-1,height-1); - - d.setColor(Color::Shadow3D); - d.drawLine(0,0,width-2,0); - d.drawLine(0,0,0,height-2); - d.drawLine(0,height-2,width-2,height-2); - d.drawLine(width-2,0,width-2,height-2); - - d.setColor(Color::Light3D); - d.drawLine(1,1,width-3,1); - d.drawLine(1,1,1,height-3); - - d.setFont(Font::getFont("menu")); - const int asc = Font::getFont("menu")->getAscent()+1; - const int height = Font::getFont("menu")->getHeight()+2; - int y = asc+3; - int index = 0; - for (std::vector::const_iterator i = items.begin(); i != items.end(); ++i) { - if ((*i).empty()) { - d.setColor(Color::Shadow3D); - d.drawLine(4,y-asc+6,width-5,y-asc+6); - d.setColor(Color::Light3D); - d.drawLine(4,y-asc+7,width-5,y-asc+7); - y += 12; - } else { - if (index == selected && hasFocus()) { - d.setColor(Color::SelectionBackground); - d.fillRect(3,y-asc,width-6,height); - d.setColor(Color::SelectionForeground); - } else { - d.setColor(Color::Text); - } - d.drawText(20,y,(*i),false,0); - y += height; - } - index++; - } -} - -void Menubar::paint(Drawable &d) const -{ - const Font *f = Font::getFont("menu"); - - d.setColor(Color::Light3D); - d.drawLine(0,height-1,width-1,height-1); - d.setColor(Color::Shadow3D); - d.drawLine(0,height-2,width-1,height-2); - - d.gotoXY(7,f->getAscent()+2); - - int index = 0; - for (std::vector::const_iterator i = menus.begin(); i != menus.end(); ++i, ++index) { - if (index == selected && (*i)->isVisible()) { - int w = f->getWidth((*i)->getName()); - d.setColor(Color::SelectionBackground); - d.fillRect(d.getX()-7,0,w+14,height-2); - d.setColor(Color::SelectionForeground); - d.gotoXY(d.getX()+7,f->getAscent()+2); - } else { - d.setColor(Color::Text); - } - d.drawText((*i)->getName(),false); - d.gotoXY(d.getX()+14,f->getAscent()+2); - } -} - -bool Button::keyDown(const Key &key) -{ - switch (key.special) { - case Key::None: - if (key.character != ' ') return false; - case Key::Enter: - break; - default: return false; - } - mouseDown(0,0,Left); - return true; -} - -bool Button::keyUp(const Key &key) -{ - if (key.ctrl || key.alt || key.windows || (key.character != ' ' && key.special != Key::Enter)) return false; - mouseUp(0,0,Left); - mouseClicked(0,0,Left); - return true; -} - -void Frame::paint(Drawable &d) const { - const Font *f = Font::getFont("default"); - const int top = (label.empty()?1:f->getAscent()/2+1); - - d.setColor(Color::Shadow3D); - d.drawLine(1,height-2,1,top); - d.drawLine(8,top); - d.drawLine((label.empty()?8:f->getWidth(label)+14),top,width-2,top); - d.drawLine(2,height-3,width-3,height-3); - d.drawLine(width-3,top+1); - - d.setColor(Color::Light3D); - d.drawLine(2,height-3,2,top+1); - d.drawLine(8,top+1); - d.drawLine((label.empty()?8:f->getWidth(label)+14),top+1,width-3,top+1); - d.drawLine(2,height-2,width-2,height-2); - d.drawLine(width-2,top+1); - - d.setColor(Color::Text); - d.drawText(11,f->getAscent()+1,label,false,0); -} - -Screen *Window::getScreen() { return (parent == NULL?dynamic_cast(this):parent->getScreen()); } - -Screen::Screen(unsigned int width, unsigned int height) : - Window(), - buffer(new Drawable(width, height)) -{ - this->width = width; - this->height = height; -} - -Screen::Screen(Drawable *d) : - Window(), - buffer(d) -{ - this->width = d->getClipWidth(); - this->height = d->getClipHeight(); -} - -Screen::~Screen() -{ -} - -void Screen::paint(Drawable &d) const -{ - d.clear(Color::Transparent); -} - -unsigned int Screen::update(void *surface, unsigned int ticks) -{ - Timer::check(ticks); - - paintAll(*buffer); - RGB *buf = buffer->buffer; - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++, buf++) { - RGB sval = surfaceToRGB(surface); - RGB bval = *buf; - int a = Color::A(bval); - bval = ((((sval&Color::MagentaMask)*a+(bval&Color::MagentaMask)*(256-a))>>8)&Color::MagentaMask) - | ((((sval&Color::GreenMask)*a+(bval&Color::GreenMask)*(256-a))>>8)&Color::GreenMask); - rgbToSurface(bval, &surface); - } - } - - return Timer::next(); -} - -void Screen::move(int x, int y) -{ -} - -void Screen::resize(int w, int h) -{ -} - -#ifdef TESTING -static void test(Drawable &d) { - const int width = d.getClipWidth(); - const int height = d.getClipHeight(); - - d.clear(Color::rgba(0,0,255,128)); - - d.setColor(Color::Black); - for (int x = 0; x < width; x += 10) d.drawLine(x,0,x,height); - for (int y = 0; y < height; y += 10) d.drawLine(0,y,width,y); - - d.setColor(Color::Red); - for (int x = 10; x <= 130 ; x += 10) { - d.drawLine(x,10,70,70); - d.drawLine(x,130); - } - for (int y = 10; y <= 130 ; y += 10) { - d.drawLine(10,y,70,70); - d.drawLine(130,y); - } - - d.setColor(Color::Yellow); - d.fillRect(150,10,30,30); - d.setColor(Color::Blue); - d.drawRect(30,30); - - d.drawRect(150,60,30,30); - d.setColor(Color::Yellow); - d.fillRect(30,30); - - for (int x = 0; x <= 100 ; x += 10) { - d.setColor(Color::rgba(0xff,0x00,0xff,(255*x/100)&255)); - d.fillRect(200+2*x,0,20,20); - } - - d.setColor(Color::Yellow); - d.fillCircle(210,60,40); - d.setColor(Color::Blue); - d.drawCircle(40); - - d.drawCircle(210,110,40); - d.setColor(Color::Yellow); - d.fillCircle(40); - - d.setColor(Color::rgba(0,0,255,128)); - d.fillRect(251,41,9,59); - d.fillRect(251,41,59,9); - d.fillRect(301,41,9,59); - d.fillRect(291,91,19,9); - d.fillRect(291,51,9,49); - d.fillRect(261,51,39,9); - d.fillRect(261,51,9,49); - d.fillRect(261,91,29,9); - d.fillRect(281,61,9,39); - d.fillRect(271,61,19,9); - d.fillRect(271,61,9,29); - d.fillRect(241,41,9,59); - d.fillRect(241,41,19,9); - d.fillRect(241,91,19,9); - d.setColor(Color::rgba(255,0,0,128)); - d.fill(255,64); - - d.setColor(Color::Green); - Drawable(d,500,355,30,30).fillCircle(65); - - for (int i = 0; i <= 100; i += 10) { - Drawable(d,25,155+i*3,420,30).drawDrawable(0,0,d,255*i/100); - } - - d.setColor(Color::White); - d.setFont(Font::getFont("VGA14")); - d.drawText(270,110,"GUI:: Test Program\n"); - d.drawText("Still testing\tTable\n"); - d.drawText("More of...\tTable\n"); - d.drawText("Overwrite\rXXXXXXXXX\n"); - d.drawText("Fake int'l chars: O\b/e\b\"\n"); - d.drawText("Real ones: \211\222\234\345\246\321"); -} -#else -static void test(Drawable &d) { (void)d; } -#endif - - -void ScreenRGB32le::paint(Drawable &d) const -{ - parent->paint(d); - test(d); -} - -static MouseButton SDL_to_GUI(const int button) -{ - switch (button) { - case SDL_BUTTON_LEFT: return GUI::Left; - case SDL_BUTTON_RIGHT: return GUI::Right; - case SDL_BUTTON_MIDDLE: return GUI::Middle; - case SDL_BUTTON_WHEELUP: return GUI::WheelUp; - case SDL_BUTTON_WHEELDOWN: return GUI::WheelDown; - default: return GUI::NoButton; - } -} - -static const Key SDL_to_GUI(const SDL_keysym &key) -{ - GUI::Key::Special ksym = GUI::Key::None; - switch (key.sym) { - case SDLK_ESCAPE: ksym = GUI::Key::Escape; break; - case SDLK_BACKSPACE: ksym = GUI::Key::Backspace; break; - case SDLK_TAB: ksym = GUI::Key::Tab; break; - case SDLK_LEFT: ksym = GUI::Key::Left; break; - case SDLK_RIGHT: ksym = GUI::Key::Right; break; - case SDLK_UP: ksym = GUI::Key::Up; break; - case SDLK_DOWN: ksym = GUI::Key::Down; break; - case SDLK_HOME: ksym = GUI::Key::Home; break; - case SDLK_END: ksym = GUI::Key::End; break; - case SDLK_DELETE: ksym = GUI::Key::Delete; break; - case SDLK_INSERT: ksym = GUI::Key::Insert; break; - case SDLK_RETURN: ksym = GUI::Key::Enter; break; - case SDLK_MENU: ksym = GUI::Key::Menu; break; - case SDLK_PAGEUP: ksym = GUI::Key::PageUp; break; - case SDLK_PAGEDOWN: ksym = GUI::Key::PageDown; break; - case SDLK_PRINT: ksym = GUI::Key::Print; break; - case SDLK_PAUSE: ksym = GUI::Key::Pause; break; - case SDLK_BREAK: ksym = GUI::Key::Break; break; - case SDLK_CAPSLOCK: ksym = GUI::Key::CapsLock; break; - case SDLK_NUMLOCK: ksym = GUI::Key::NumLock; break; - case SDLK_SCROLLOCK: ksym = GUI::Key::ScrollLock; break; - case SDLK_F1:case SDLK_F2:case SDLK_F3:case SDLK_F4:case SDLK_F5:case SDLK_F6: - case SDLK_F7:case SDLK_F8:case SDLK_F9:case SDLK_F10:case SDLK_F11:case SDLK_F12: - ksym = (GUI::Key::Special)(GUI::Key::F1 + key.sym-SDLK_F1); - default: break; - } - return Key(key.unicode, ksym, - (key.mod&KMOD_SHIFT)>0, - (key.mod&KMOD_CTRL)>0, - (key.mod&KMOD_ALT)>0, - (key.mod&KMOD_META)>0); -} - -/** \brief Internal class that handles different screen bit depths and layouts the SDL way */ -class SDL_Drawable : public Drawable { -protected: - SDL_Surface *const surface; - -public: - SDL_Drawable(int width, int height, RGB clear = Color::Transparent) : Drawable(width, height, clear), surface(SDL_CreateRGBSurfaceFrom(buffer, width, height, 32, width*4, Color::RedMask, Color::GreenMask, Color::BlueMask, Color::AlphaMask)) { - surface->flags |= SDL_SRCALPHA; - } - - ~SDL_Drawable() { - SDL_FreeSurface(surface); - } - - void update(SDL_Surface *dest) const { - SDL_BlitSurface(surface, NULL, dest, NULL); - } -}; - -ScreenSDL::ScreenSDL(SDL_Surface *surface) : Screen(new SDL_Drawable(surface->w, surface->h)), surface(surface), downx(0), downy(0), lastclick(0) {} - -Ticks ScreenSDL::update(Ticks ticks) -{ - Timer::check(ticks); - - paintAll(*buffer); - static_cast(buffer)->update(surface); - - return Timer::next(); -} - -void ScreenSDL::paint(Drawable &d) const { - d.clear(Color::Transparent); - test(d); -} - -bool ScreenSDL::event(const SDL_Event &event) { - bool rc; - - switch (event.type) { - case SDL_KEYUP: { - const Key &key = SDL_to_GUI(event.key.keysym); - if (key.special == GUI::Key::None && key.character == 0) break; - if (key.special == GUI::Key::CapsLock || key.special == GUI::Key::NumLock) keyDown(key); - return keyUp(key); - } - case SDL_KEYDOWN: { - const Key &key = SDL_to_GUI(event.key.keysym); - if (key.special == GUI::Key::None && key.character == 0) break; - rc = keyDown(key); - if (key.special == GUI::Key::CapsLock || key.special == GUI::Key::NumLock) keyUp(key); - return rc; - } - case SDL_MOUSEMOTION: - if (event.motion.state) { - if (abs(event.motion.x-downx) <= 10 && abs(event.motion.y-downy) <= 10) - break; - downx = -11; downy = -11; - if (event.motion.state&SDL_BUTTON(1)) - return mouseDragged(event.motion.x, event.motion.y, GUI::Left); - else if (event.motion.state&SDL_BUTTON(2)) - return mouseDragged(event.motion.x, event.motion.y, GUI::Middle); - else if (event.motion.state&SDL_BUTTON(3)) - return mouseDragged(event.motion.x, event.motion.y, GUI::Right); - break; - } - - return mouseMoved(event.motion.x, event.motion.y); - - case SDL_MOUSEBUTTONDOWN: - rc = mouseDown(event.button.x, event.button.y, SDL_to_GUI(event.button.button)); - if (abs(event.button.x-downx) > 10 || abs(event.button.y-downy) > 10) lastclick = 0; - downx = event.button.x; downy = event.button.y; - return rc; - - case SDL_MOUSEBUTTONUP: - rc = mouseUp(event.button.x, event.button.y, SDL_to_GUI(event.button.button)); - if (abs(event.button.x-downx) < 10 && abs(event.button.y-downy) < 10) { - if (lastclick == 0 || (GUI::Timer::now()-lastclick) > 20) { - lastclick = GUI::Timer::now(); - rc |= mouseClicked(downx, downy, SDL_to_GUI(event.button.button)); - } else if (lastclick != 0) { - rc |= mouseDoubleClicked(downx, downy, SDL_to_GUI(event.button.button)); - lastclick = 0; - } else { - lastclick = 0; - } - } else { - lastclick = 0; - } - return rc; - } - - return false; -} - -} - - - -#ifdef TESTING -#include - -/** \brief A test program that serves as an example for all GUI elements. - * - * Note that you need SDL installed and a file "testfont.h" for this - * to compile, which must contain a bitmap font declared as - * - * \code - * static const unsigned char testfont[256 * 14] = { ... }; - * \endcode - * - * (256 chars, 8x14 fixed-width font, for example the IBM PC VGA 14-line font, - * you can get it from DOSBox) - * - * To compile it, use a command line like this: - * - * \code - * g++ -DTESTING `sdl-config --cflags` `sdl-config --libs` gui_tk.cpp -o testgui_tk - * \endcode - * - */ - -int main(int argc, char *argv[]) -{ - printf("GUI:: test program\n"); - - SDL_Surface *screen; - - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); - exit(1); - } - - atexit(SDL_Quit); - - screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE); - if (screen == NULL) { - fprintf(stderr, "Couldn't set 640x480x32 video mode: %s\n", SDL_GetError()); - exit(1); - } - printf("GUI:: color depth %i\n",screen->format->BitsPerPixel); - - SDL_EnableUNICODE(true); - SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL); - - #include "testfont.h" - GUI::Font::addFont("default",new GUI::BitmapFont(testfont,14,10)); - - GUI::ScreenSDL guiscreen(screen); - GUI::ToplevelWindow *frame = new GUI::ToplevelWindow(&guiscreen,205,100,380,250,"GUI::Frame"); - static struct delwin : public GUI::ActionEventSource_Callback { - void actionExecuted(GUI::ActionEventSource *b, const GUI::String &arg) { - dynamic_cast(dynamic_cast(b)->getParent())->close(); - } - } dw; - struct newwin : public GUI::ActionEventSource_Callback { - GUI::Screen *screen; - int n; - void actionExecuted(GUI::ActionEventSource *b, const GUI::String &arg) { - char title[256]; - sprintf(title,"Window %i",++n); - GUI::ToplevelWindow *w = new GUI::ToplevelWindow(screen,405,100,120,150,title); - GUI::Button *close = new GUI::Button(w,5,5,"Close"); - close->addActionHandler(&dw); - } - } nw; - nw.screen = &guiscreen; - nw.n = 0; - struct quit : public GUI::ActionEventSource_Callback { - GUI::ToplevelWindow *frame; - void actionExecuted(GUI::ActionEventSource *b, const GUI::String &arg) { - if (arg == "Quit" && b->getName() != "GUI::Input") exit(0); - frame->setTitle(arg); - } - } ex; - ex.frame = frame; - - GUI::Button *b = new GUI::Button(frame,8,20,"Open a new Window"); - b->addActionHandler(&nw); - (new GUI::Button(frame,200,20,"1"))->addActionHandler(&ex); - (new GUI::Button(frame,235,20,"2"))->addActionHandler(&ex); - b = new GUI::Button(frame,270,20,"Quit"); - b->addActionHandler(&ex); - (new GUI::Input(frame,16,55,150))->addActionHandler(&ex); - - printf("Title: %s\n",(const char*)frame->getTitle()); - - struct movewin : public GUI::Timer_Callback, public GUI::ToplevelWindow_Callback { - public: - GUI::ToplevelWindow *frame; - GUI::Checkbox *cb1, *cb2; - int x, y; - virtual unsigned int timerExpired(unsigned int t) { - if (cb2->isChecked()) frame->move(frame->getX()+x,frame->getY()+y); - if (frame->getX() <= -frame->getWidth()) x = 1; - if (frame->getX() >= 640) x = -1; - if (frame->getY() <= -frame->getHeight()) y = 1; - if (frame->getY() >= 480) y = -1; - return 10; - } - virtual bool windowClosing(GUI::ToplevelWindow *win) { - if (!cb1->isChecked()) return false; - return true; - } - virtual void windowClosed(GUI::ToplevelWindow *win) { - GUI::Timer::remove(this); - } - } mw; - mw.frame = frame; - mw.x = -1; - mw.y = 1; - GUI::Frame *box = new GUI::Frame(frame,16,80,300,50); - mw.cb1 = new GUI::Checkbox(box,0,0,"Allow to close this window"); - mw.cb2 = new GUI::Checkbox(box,0,20,"Move this window"); - box = new GUI::Frame(frame,16,130,300,80,"Radio Buttons"); - (new GUI::Radiobox(box,0,0,"Normal"))->setChecked(true); - new GUI::Radiobox(box,0,20,"Dynamic"); - new GUI::Radiobox(box,0,40,"Simple"); - box->addActionHandler(&ex); - GUI::Timer::add(&mw,10); - frame->addWindowHandler(&mw); - GUI::Menubar *bar = new GUI::Menubar(frame,0,0,frame->getWidth()); - bar->addMenu("File"); - bar->addItem(0,"New..."); - bar->addItem(0,"Open..."); - bar->addItem(0,""); - bar->addItem(0,"Save"); - bar->addItem(0,"Save as..."); - bar->addItem(0,""); - bar->addItem(0,"Close"); - bar->addItem(0,"Quit"); - bar->addMenu("Edit"); - bar->addItem(1,"Undo"); - bar->addItem(1,"Redo"); - bar->addItem(1,""); - bar->addItem(1,"Cut"); - bar->addItem(1,"Copy"); - bar->addItem(1,"Paste"); - bar->addItem(1,""); - bar->addItem(1,"Select all"); - bar->addItem(1,"Select none"); - bar->addMenu("View"); - bar->addItem(2,"Zoom..."); - bar->addItem(2,"Zoom in"); - bar->addItem(2,"Zoom out"); - bar->addMenu("?"); - bar->addItem(3,"Manual"); - bar->addItem(3,"Search..."); - bar->addItem(3,""); - bar->addItem(3,"About"); - bar->addActionHandler(&ex); - - SDL_Event event; - while (1) { - while (SDL_PollEvent(&event)) { - if (!guiscreen.event(event)) { - if (event.type == SDL_QUIT) exit(0); - } - } - - if (SDL_MUSTLOCK(screen)) SDL_LockSurface(screen); - memset(screen->pixels,0xff,4*640*15); - memset(((char *)screen->pixels)+4*640*15,0x00,4*640*450); - memset(((char *)screen->pixels)+4*640*465,0xff,4*640*15); - if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); - guiscreen.update(4); - SDL_UpdateRect(screen, 0, 0, screen->w, screen->h); - - SDL_Delay(40); - } -} -#endif - -#endif \ No newline at end of file diff --git a/src/libs/gui_tk/gui_tk.h b/src/libs/gui_tk/gui_tk.h deleted file mode 100644 index 16674f6..0000000 --- a/src/libs/gui_tk/gui_tk.h +++ /dev/null @@ -1,2225 +0,0 @@ -/** \mainpage gui::tk - framework-agnostic C++ GUI toolkit - * - * \section i Introduction - * - * gui::tk is a simple one-file C++ GUI toolkit for use with arbitrary - * memory framebuffers. - * - * \section f Features - * - * \li small source and binary code size - * \li reasonable performance and memory usage - * \li comfortable usage - * \li suitable for embedded usage: integer math only - * \li extensibility via OO - * \li non-intrusive: can be integrated with any event mechanism of your liking - * \li no dependencies apart from standards-conformant ANSI C++ (including a little STL) - * \li support for different encodings, single- and multibyte - * \li flexible font support - * - * \section o Overview - * - * The toolkit draws on a surface you provide, using any size or pixel format. - * Create a GUI::Screen with the buffer to draw on, then pass that object - * (or a GUI::Window created from it) to all other widgets' constructors. - * - * It doesn't provide an own event loop. Instead, it relies on you passing events - * and updating the screen regularly. This way, it can easily be integrated with - * any event loop available (SDL, Qt, glib, X11, Win32, selfmade, ...) - * - * Many functions and concepts were taken from other well-known toolkits, so if you - * know Qt, Java or wxWindows, you may encounter (intentional) similarities. However, - * simplicity of code has been given priority over maximum optimization and pixel-exact - * replication of their appearance. - * - * A note about font support and encodings: All text-related functions use templates to - * support any encoding. Fonts define the charset. - * - * \section g Getting Started - * - * gui::tk contains an SDL adapter, so if your program is already using SDL, - * things are really easy. The rough sequence to get up and running is: - * - * \code - * // setup a suitable video mode with SDL - * SDL_surface *screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE); - * - * // add a default font, you will most probably need it - * GUI::Font::addFont("default",new GUI::BitmapFont(testfont,14,10)); - * - * // create the root-level screen object, the parent of all top-level windows - * GUI::ScreenSDL guiscreen(screen); - * - * // create any amount of toplevel windows you like - * GUI::ToplevelWindow *frame = new GUI::ToplevelWindow(&guiscreen, 205, 100, 380, 250, "gui::tk example"); - * - * // add some GUI elements to the toplevel window - * GUI::Button *b = new GUI::Button(frame,8,20,"Quit"); - * - * // Define and add an event handler - * struct quit : public GUI::ActionEventSource_Callback { - * void actionExecuted(GUI::ActionEventSource *b, const GUI::String &arg) { - * exit(0); - * } - * } ex; - * b->addActionHandler(&ex); - * - * // Enter an event loop, calling update() regularly. - * SDL_Event event; - * while (1) { - * while (SDL_PollEvent(&event)) { - * if (!guiscreen.event(event)) { // gui::tk didn't handle that event - * if (event.type == SDL_QUIT) exit(0); - * } - * } - * - * guiscreen.update(4); // 4 ticks = 40ms - * SDL_UpdateRect(screen, 0, 0, screen->w, screen->h); - * - * SDL_Delay(40); // wait 40ms - * } - * \endcode - * - * Look at gui_tk.h for more detailed documentation and reference of all classes. - * - * A test program that shows off the capabilities of gui::tk is available as part of gui_tk.cpp. - * - * \section l License - * - * Copyright (C) 2005-2007 Jörg Walter - * - * gui::tk is free software; you can 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. - * - * gui::tk is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU 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 - */ - -/* $Id: gui_tk.h,v 1.5 2008/09/07 10:55:15 c2woody Exp $ */ - -#ifndef GUI__TOOLKIT_H -#define GUI__TOOLKIT_H - -#define imin(x,y) (xy?x:y) -#define isign(x) (((x)<0?-1:1)) - -/** \file - * \brief Header file for gui::tk. - * - * All you need to do is to include "gui_tk.h". If you want SDL support, then include \c SDL.h first. - */ - -#ifdef _MSC_VER -typedef signed __int8 int8_t; -typedef signed __int16 int16_t; -typedef signed __int32 int32_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -#else -#include -#endif - -#include -#include -#include -#include -#include -#include - -/// This namespace contains all GUI toolkit classes, types and functions. -namespace GUI { - -/// ARGB 24-bit color value: (a<<24)|(r<<16)|(g<<8)|(b) -typedef uint32_t RGB; - -/// Collection of all color-related constants and functions. -namespace Color { -/// A fully transparent pixel. -const RGB Transparent = 0x00ffffff; - -/// A fully opaque black pixel. -const RGB Black = 0xff000000; - -/// A fully opaque white pixel. -const RGB White = 0xffffffff; - -/// Alpha mask. -const RGB AlphaMask = 0xff000000; - -/// Offset of alpha value. -const int AlphaShift = 24; - -/// Red mask. -const RGB RedMask = 0x00ff0000; - -/// Full-intensity red. -const RGB Red = Black|RedMask; - -/// Offset of red value. -const int RedShift = 16; - -/// Green mask. -const RGB GreenMask = 0x0000ff00; - -/// Full-intensity green. -const RGB Green = Black|GreenMask; - -/// Offset of green value. -const int GreenShift = 8; - -/// Blue mask. -const RGB BlueMask = 0x000000ff; - -/// Full-intensity blue. -const RGB Blue = Black|BlueMask; - -/// Offset of blue value. -const int BlueShift = 0; - -/// Full-intensity Magenta. -const RGB Magenta = Red|Blue; - -/// Magenta mask. -const RGB MagentaMask = RedMask|BlueMask; - -/// Full-intensity Cyan. -const RGB Cyan = Green|Blue; - -/// Cyan mask. -const RGB CyanMask = GreenMask|BlueMask; - -/// Full-intensity Yellow. -const RGB Yellow = Red|Green; - -/// Yellow mask. -const RGB YellowMask = RedMask|GreenMask; - -/// 50% grey -const RGB Grey50 = 0xff808080; - -/// Background color for 3D effects. May be customized. -extern RGB Background3D; - -/// Light highlight color for 3D effects. May be customized. -extern RGB Light3D; - -/// Dark highlight color (shadow) for 3D effects. May be customized. -extern RGB Shadow3D; - -/// Generic border color for highlights or similar. May be customized. -extern RGB Border; - -/// Foreground color for regular content (mainly text). May be customized. -extern RGB Text; - -/// Background color for inactive areas. May be customized. -extern RGB Background; - -/// Background color for selected areas. May be customized. -extern RGB SelectionBackground; - -/// Foreground color for selected areas. May be customized. -extern RGB SelectionForeground; - -/// Background color for inputs / application area. May be customized. -extern RGB EditableBackground; - -/// Title bar color for windows. May be customized. -extern RGB Titlebar; - -/// Title bar text color for windows. May be customized. -extern RGB TitlebarText; - -/// Convert separate r, g, b and a values (each 0-255) to an RGB value. -static inline RGB rgba(int r, int g, int b, int a=0) { - return (((r&255)<>Color::RedShift); } -/// Get green value (0-255) from an RGB value. -static inline int G(RGB val) { return ((val&Color::GreenMask)>>Color::GreenShift); } -/// Get blue value (0-255) from an RGB value. -static inline int B(RGB val) { return ((val&Color::BlueMask)>>Color::BlueShift); } -/// Get alpha value (0-255) from an RGB value. -static inline int A(RGB val) { return ((val&Color::AlphaMask)>>Color::AlphaShift); } - -} - -/// Identifies a mouse button. -enum MouseButton { NoButton, Left, Right, Middle, WheelUp, WheelDown, WheelLeft, WheelRight }; - -/// A type which holds size values that can be very large. -typedef unsigned int Size; - -/// A type which holds a single character. Large enough for Unicode. -typedef uint32_t Char; - -/// A type which holds a number of timer ticks. -typedef unsigned int Ticks; - -/// Identifies a keyboard key. -class Key { -public: - /// Translated character value. - /** No encoding is implied. The Font that is used to display this character - * determines the appearance. */ - Char character; - /// Special keyboard keys. - /** It is modeled after PC keyboards. When you feed keyboard events to a GUI::Screen, - * try to map native keys to this set. Some special keys have a character value. Set - * to \c None if the key has no special meaning. */ - enum Special { - None, - F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, - Up, Down, Left, Right, Backspace, Tab, Backtab, Enter, Escape, - Home, End, PageUp, PageDown, Insert, Delete, Menu, - Print, Pause, Break, CapsLock, NumLock, ScrollLock, - Alt, Ctrl, Shift, Windows - } special; - /// Set if the Shift key is currently down. - bool shift; - /// Set if the Ctrl key is currently down. - bool ctrl; - /// Set if the Alt (PC) or Meta (classic Unix) key is currently down. - bool alt; - /// Set if the "Windows"/Meta (PC) or Super (classic Unix) key is currently down. - /** Do not depend too heavily on this, as many keyboards and systems do not have such a key. */ - bool windows; - - /// Constructor. - Key(int character, Special special, bool shift, bool ctrl, bool alt, bool windows) : - character(character), special(special), - shift(shift), ctrl(ctrl), alt(alt), windows(windows) {} -}; - -class Drawable; -class String; - -/** \brief Converts between strings of various types and String objects. - * - * It is used to deal with string encoding. It is intended to be used with template - * specializations. Having such a specialization means you can feed the corresponding type to - * all functions that expect a string -- without any conversion. You can add specializations - * yourself in your program's code to deal with unsupported types. - * - * As an example, see the std::string version. - * - * Encodings, as opposed to character sets, define how bytes map to character values. - * ASCII, for example, has an \em encoding where each byte is one character, while the - * ASCII \em character \em set says that values 0-127 are valid and 65 is the upper case - * letter 'A'. UTF-8 has 1-6 bytes per character, and the character set is unicode. - * - * GUI::Font deals with the character set, and this class encapsulates encodings. - * - */ -template class NativeString { -protected: - friend class String; - - /// Converts a native string into a String object - static void getString(String &dest, const STR &src) { STR::_this_string_type_is_not_supported_(); } - - /** \brief Converts a string object to native representation. - * - * If some characters cannot be converted, they should silently be skipped. Apart from that, - * \c nativeString(stringNative(String(),X)) should be value-equal to \c X. - */ - static STR& getNative(const String &src) { STR::_this_string_type_is_not_supported_();return*new STR(); } -}; - -template class NativeString { -protected: - friend class String; - static void getString(String &dest, const STR *src); - static STR* getNative(const String &src); -}; - -template class NativeString : public NativeString {}; -template class NativeString : public NativeString {}; -template class NativeString : public NativeString {}; - -/// 'less-than' comparison between pointer addresses -struct ltvoid { bool operator()(const void* s1, const void* s2) const { return s1 < s2; } }; - -/** \brief Simple STL-based string class. - * - * This is intended as internal helper class to allow gui::tk to work with any kind of - * string objects. While you can use this in normal application code, you should better - * use the string class of your application framework (like Qt). If you don't have any, - * use std::string. - * - * It supports arbitrary characters, no character set is implied. Conversion from/to usual - * string types like \c char* is automatic but not thread-safe for non-class types. - */ -class String : public std::vector { -protected: - template friend class NativeString; - /// Simple pointer encapsulation class for memory management. - class Native { public: virtual ~Native() {}; }; - /// Simple pointer encapsulation class for memory management. - template class NativeArray: public Native { - STR *data; - public: - NativeArray(STR *data) : data(data) {} - virtual ~NativeArray() { delete[] data; } - }; - template class NativeObject: public Native { - STR *data; - public: - NativeObject(STR *data) : data(data) {} - virtual ~NativeObject() { delete data; } - }; - -private: - /// Semi-static memory management for pointer string types. - mutable std::map strings; - -protected: - /// Manage a native string's memory. - void addNative(Native *dest) const { - const class std::type_info &type = typeid(dest); - if (strings[&type] != NULL) delete strings[&type]; - strings[&type] = dest; - } - -public: - /// Allocate a new String initialized from native string. - template String(const STR& src) { NativeString::getString(*this, src); } - - /// Taken from STL. - template String(InputIterator a, InputIterator b) : std::vector(a,b) {} - - /// Copy-constructor - String(const String &src) : std::vector(src), strings() {}; - - /// Allocate a new String. - String() { } - - /// Deallocate a String. - ~String() { - for (std::map::iterator i = strings.begin(); i != strings.end(); ++i) - delete (*i).second; - }; - - /// Convert to native representation. - /** For pointer types like \c char*, the returned pointer is usually only valid as long as - * this object exists, or until it is modified and cast to the same type again. */ - template operator T() const { return NativeString::getNative(*this); } - - /// Compare with native representation. - template bool operator==(const T &src) const { return *this == String(src); } - /// Compare with other Strings. - bool operator==(const String &src) const { return *(std::vector*)this == src; } - - /// Compare with native representation. - template bool operator!=(const T &src) const { return *this != String(src); } - /// Compare with other Strings. - bool operator!=(const String &src) const { return *(std::vector*)this != src; } -}; - -template void NativeString::getString(String &dest, const STR* src) { - Size strlen = 0; - while (src[strlen]) strlen++; - dest.resize(strlen); - for (strlen = 0; src[strlen]; strlen++) dest[strlen] = (sizeof(STR)==1?(unsigned char)src[strlen]:sizeof(STR)==2?(unsigned short)src[strlen]:src[strlen]); -} - -template STR* NativeString::getNative(const String &src) { - Size strlen = (Size)src.size(); - STR* dest = new STR[strlen+1]; - dest[strlen] = 0; - for (; strlen > 0; strlen--) dest[strlen-1] = src[strlen-1]; - src.addNative(new String::NativeArray(dest)); - return dest; -} - -template <> class NativeString { -protected: - friend class String; - static void getString(String &dest, const std::string *src) { - Size strlen = (Size)src->length(); - dest.resize(strlen); - for (Size i = 0; i< strlen; i++) dest[i] = (*src)[i]; - } - static std::string* getNative(const String &src) { - Size strlen = (Size)src.size(); - std::string* dest = new std::string(); - for (Size i = 0; i < strlen; i++) dest->append(1,src[i]); - src.addNative(new String::NativeObject(dest)); - return dest; - } -}; - -template <> class NativeString : public NativeString {}; - -template <> class NativeString { -protected: - friend class String; - static void getString(String &dest, const std::string &src) { - Size strlen = (Size)src.length(); - dest.resize(strlen); - for (Size i = 0; i< strlen; i++) dest[i] = src[i]; - } - static std::string& getNative(const String &src) { - Size strlen = (Size)src.size(); - std::string* dest = new std::string(); - for (Size i = 0; i < strlen; i++) dest->append(1,src[i]); - src.addNative(new String::NativeObject(dest)); - return *dest; - } -}; - -template <> class NativeString : public NativeString {}; - -class ToplevelWindow; -class Menu; -class TransientWindow; -class Screen; -class Window; - -/// Callback for window events. -struct Window_Callback { -public: - /// Called whenever this window changes position. - virtual void windowMoved(Window *win, int x, int y) = 0; - virtual ~Window_Callback() {} -}; - - -/** \brief A Window is a rectangular sub-area of another window. - * - * Windows are arranged hierarchically. A Window cannot leave its parent's - * area. They may contain their own buffer or share it with their parent. - * - * Usually, every GUI element is a subclass of Window. Note that this is - * \em not a GUI window with decorations like border and title bar. See ToplevelWindow - * for that. - */ -class Window { -protected: - friend class ToplevelWindow; - friend class TransientWindow; - friend class Menu; - - /// Width of the window. - int width; - /// Height of the window. - int height; - /// X position relative to parent. - int x; - /// Y position relative to parent. - int y; - - /// \c true if anything changed in this window or one of it's children - bool dirty; - - /// \c true if this window should be visible on screen. - bool visible; - - /// Parent window. - Window *const parent; - - /// Child window of last button-down event - /** It receives all drag/up/click/doubleclick events until an up event is received */ - Window *mouseChild; - - /// Child windows. - /** Z ordering is done in list order. The first element is the lowermost - * window. This window's content is below all children. */ - std::list children; - - /// List of registered event handlers. - std::list movehandlers; - - /// Register child window. - virtual void addChild(Window *child); - - /// Remove child window. - virtual void removeChild(Window *child); - - /// Mark this window and all parents as dirty. - void setDirty() { if (dirty) return; dirty = true; if (parent != NULL) parent->setDirty(); }; - - /// Replace clipboard content. - virtual void setClipboard(const String &s) { parent->setClipboard(s); }; - - /// Get clipboard content. - virtual const String& getClipboard() { return parent->getClipboard(); }; - - /// Default constructor. Only used in class Screen. Do not use. - Window(); - - /// Called whenever the focus changes. - virtual void focusChanged(bool gained) { - if (children.size() > 0) children.back()->focusChanged(gained); - } - -public: - - /// Add an event handler. - void addWindowHandler(Window_Callback *handler) { movehandlers.push_back(handler); } - - /// Remove an event handler. - void removeWindowHandler(Window_Callback *handler) { movehandlers.remove(handler); } - - /// Create a subwindow of the given parent window. - Window(Window *parent, int x, int y, int w, int h); - - /// Destructor. - virtual ~Window(); - - /// Resize this window to the given dimensions. - /** If that would move part of the window outside of this window's area, - * the outside area will silently be clipped while drawing. */ - virtual void resize(int w, int h); - /// Return this window's width - virtual int getWidth() const { return width; } - /// Return this window's height - virtual int getHeight() const { return height; } - - /// Move this window to the given position relative to the parent window's origin. - /** If that would move part of the window outside of this window's area, - * the outside area will silently be clipped while drawing. */ - virtual void move(int x, int y); - /// Return this window's X position relative to the parent's top left corner - virtual int getX() const { return x; } - /// Return this window's Y position relative to the parent's top left corner - virtual int getY() const { return y; } - /// Return this window's contents' X position relative to the screen's top left corner - virtual int getScreenX() const { return (parent == NULL?0:parent->getScreenX()+x); } - /// Return this window's contents' Y position relative to the screen's top left corner - virtual int getScreenY() const { return (parent == NULL?0:parent->getScreenY()+y); } - - /// Draw this window's content including all children. - virtual void paintAll(Drawable &d) const; - - /// Draw this window's content. - virtual void paint(Drawable &d) const {}; - - /// Show or hide this window. - /** By default, most windows are shown when created. Hidden windows do not receive any events. */ - virtual void setVisible(bool v) { visible = !!v; parent->setDirty(); } - - /// Returns \c true if this window is visible. - virtual bool isVisible() const { return (!parent || parent->isVisible()) && visible; } - - /// Return parent window. - /** May return NULL if this is the topmost window (the Screen). */ - Window *getParent() const { return parent; } - - /// Get the topmost window (the Screen) - Screen *getScreen(); - - /// Returns \c true if this window has currently the keyboard focus. - virtual bool hasFocus() const { return parent->hasFocus() && *parent->children.rbegin() == this; } - - /// Mouse was moved. Returns true if event was handled. - virtual bool mouseMoved(int x, int y); - /// Mouse was moved while a button was pressed. Returns true if event was handled. - virtual bool mouseDragged(int x, int y, MouseButton button); - /// Mouse was pressed. Returns true if event was handled. - virtual bool mouseDown(int x, int y, MouseButton button); - /// Mouse was released. Returns true if event was handled. - virtual bool mouseUp(int x, int y, MouseButton button); - /// Mouse was clicked. Returns true if event was handled. - /** Clicking means pressing and releasing the mouse button while not moving it. */ - virtual bool mouseClicked(int x, int y, MouseButton button); - /// Mouse was double-clicked. Returns true if event was handled. - virtual bool mouseDoubleClicked(int x, int y, MouseButton button); - - /// Key was pressed. Returns true if event was handled. - virtual bool keyDown(const Key &key); - /// Key was released. Returns true if event was handled. - virtual bool keyUp(const Key &key); - - /// Put this window on top of all it's siblings. Preserves relative order. - /** Returns true if the window accepts the raise request. */ - virtual bool raise() { - Window *last = parent->children.back(); - for (Window *cur = parent->children.back(); cur != this; cur = parent->children.back()) { - parent->children.remove(cur); - parent->children.push_front(cur); - } - if (last != this) { - focusChanged(true); - last->focusChanged(false); - } - parent->setDirty(); - return true; - } - - /// Put this window below all of it's siblings. Does not preserve relative order. - virtual void lower() { - parent->children.remove(this); - parent->children.push_front(this); - if (this != parent->children.back()) { - parent->children.back()->focusChanged(true); - focusChanged(false); - } - parent->setDirty(); - } - - /// Return the \p n th child - Window *getChild(int n) { - for (std::list::const_iterator i = children.begin(); i != children.end(); ++i) { - if (n--) return *i; - } - return NULL; - } - -}; - -/** \brief A Screen represents the framebuffer that is the final destination of the GUI. - * - * It's main purpose is to manage the current contents of the surface and to combine - * it with all GUI elements. You can't resize and move the screen. Requests to do so - * will be ignored. - * - * This is an abstract base class. You need to use a subclass which implements rgbToSurface - * and surfaceToRGB. - * - * To make things work, Screen needs events. Call the mouse and key event functions (see Window) - * whenever such an event occurs. Call update(void *surface, int ticks) regularly, if possible about - * every 40msec (25 fps). If nothing has changed, screen updates are quite fast. - */ -class Screen : public Window { -protected: - /// Screen buffer. - Drawable *const buffer; - - /// Clipboard. - String clipboard; - - /// Currently pressed mouse button. - MouseButton button; - - /// Store a single RGB triple (8 bit each) as a native pixel value and advance pointer. - virtual void rgbToSurface(RGB color, void **pixel) = 0; - - /// Map a single framebuffer pixel to an RGB value. - virtual RGB surfaceToRGB(void *pixel) = 0; - - /// Create a new screen with the given characteristics. - Screen(Size width, Size height); - - /// Create a new screen from the given GUI::Drawable. - Screen(Drawable *d); - -public: - /// Destructor. - virtual ~Screen(); - - /// Set clipboard content. - template void setClipboard(const STR s) { this->setClipboard(String(s)); } - - /// Set clipboard content. - virtual void setClipboard(const String &s) { clipboard = s; } - - /// Get clipboard content. - virtual const String& getClipboard() { return clipboard; } - - /// Do nothing. - virtual void resize(int w, int h); - - /// Do nothing. - virtual void move(int x, int y); - - /// Screen has always focus. - virtual bool hasFocus() const { return true; } - - /// Update the given surface with this screen's content, fully honouring the alpha channel. - /** \p ticks can be set to a different value depending on how much time has passed. Timing - * doesn't need to be perfect, but try to call this at least every 40 msec. Each tick - * amounts to about 10 msec. Returns the number of ticks until the next event is scheduled, or - * 0 if none. */ - Ticks update(void *surface, Ticks ticks = 1); - - /// Default: clear screen. - virtual void paint(Drawable &d) const; -}; - -class Timer; - -/// Timer callback type -struct Timer_Callback { -public: - /// The timer has expired. - /** Callbacks for timers take one parameter, the number of ticks since - * application start. Note that this value may wrap after a little less - * than 500 days. If you want callbacks to be called again, return the - * delay in ticks relative to the scheduled time of this - * callback (which may be earlier than now() ). Otherwise return 0. */ - virtual Ticks timerExpired(Ticks time) = 0; - virtual ~Timer_Callback() {} -}; - -/** \brief Timing service. - * Time is measured in ticks. A tick is about 10 msec. - * - * Note that this is not suitable as a high-accuracy timing service. Timer - * events can be off by many ticks, and a tick may be slightly more or - * slightly less than 10 msec. Because of that, Timers are only intended for - * simple animation effects, input timeouts and similar things. - * - */ -class Timer { -protected: - /// Number of ticks since application start. - static Ticks ticks; - - /// Compare two integers for 'less-than'. - struct ltuint { bool operator()(Ticks i1, Ticks i2) const { - return (i1 < i2); - } }; - - /// Active timers. - static std::multimap timers; - -public: - /// Advance time and check for expired timers. - static void check(Ticks ticks); - - /// Add a timed callback. \p ticks is a value relative to now(). - /** \p cb is not copied. */ - static void add(Timer_Callback *cb, const Ticks ticks) { timers.insert(std::pair(ticks+Timer::ticks,cb)); } - - static void remove(const Timer_Callback *const cb); - - /// Return current time (ticks since application start) - static Ticks now() { return ticks; } - - /// Return number of ticks until next scheduled timer or 0 if no timers - static Ticks next(); -}; - - -/** \brief A 24 bit per pixel RGB framebuffer aligned to 32 bit per pixel. - * - * Warning: This framebuffer type varies with CPU endiannes. It is meant as - * a testing/debugging tool. - */ -class ScreenRGB32le : public Screen { -protected: - /// Map a single RGB triple (8 bit each) to a native pixel value. - virtual void rgbToSurface(RGB color, void **pixel) { RGB **p = (RGB **)pixel; **p = color; (*p)++; }; - - /// Map a single surface pixel to an RGB value. - virtual RGB surfaceToRGB(void *pixel) { return *(RGB*)pixel; }; -public: - ScreenRGB32le(Size width, Size height) : Screen(width,height) {}; - - virtual void paint(Drawable &d) const; -}; - - -#ifdef SDL_MAJOR_VERSION -/** \brief An SDL surface adapter. - * - * This screen type will draw on an SDL surface (honouring transparency if the - * surface is already filled) and react on SDL events. It does not provide an - * application event loop, you have to call update() and event() regularly until - * you decide to quit the application. - * - * The implementation of this class could as well have been integrated into - * GUI::Screen. That might have been a little more efficient, but this way - * this class serves as an example for custom screen classes. - * - * Note that you have to include \c SDL.h \em before \c gui_tk.h for this class - * to become available. - */ -class ScreenSDL : public Screen { -protected: - /// not used. - virtual void rgbToSurface(RGB color, void **pixel) {}; - - /// not used. - virtual RGB surfaceToRGB(void *pixel) { return 0; }; - - /// The SDL surface being drawn to. - SDL_Surface *surface; - - /// Position of last mouse down. - int downx, downy; - - /// time of last click for double-click detection. - Ticks lastclick; - -public: - - /** Initialize SDL screen with a surface - * - * The dimensions of this surface will define the screen dimensions. Changing the surface - * later on will not change the available area. - */ - ScreenSDL(SDL_Surface *surface); - - /** Change current surface - * - * The new surface may have different dimensions than the current one, but - * the screen size will not change. This means that either the screen will - * not be displayed fully, or there will be borders around the screen. - */ - void setSurface(SDL_Surface *surface) { this->surface = surface; } - - /// Retrieve current surface. - SDL_Surface *getSurface() { return surface; } - - /// Overridden: makes background transparent by default. - virtual void paint(Drawable &d) const; - - /// Use this to update the SDL surface. The screen must not be locked. - Ticks update(Ticks ticks); - - /// Process an SDL event. Returns \c true if event was handled. - bool event(const SDL_Event *ev) { return event(*ev); } - - - /// Process an SDL event. Returns \c true if event was handled. - bool event(const SDL_Event& ev); -}; -#endif - -class Font; - -/** \brief A drawable represents a rectangular off-screen drawing area. - * - * It is an off-screen buffer which can be copied to other drawables or - * to a Screen's framebuffer. The drawable's origin is at the top left. All - * operations are silently clipped to the available area. The alpha channel - * is honoured while copying one drawable to another, but not during other - * drawing operations. - * - * Drawables have a current font, color and (x,y) position. Drawing takes place - * at the given point using the given font and color. The current position is - * then moved to the final point of the drawing primitive unless otherwise - * noted. Pixel width of all lines is selectable, but be aware that visual - * appearance of lines with width > 1 is not as sophisticated as in well-known - * toolkits like Java or Qt. - * - * Some drawing primitives are overloaded to take full coordinates. These ignore - * the current position, but update it just like their regular brethren. - */ -class Drawable { -protected: - friend Ticks Screen::update(void *, Ticks); - /// The actual pixel buffer. - RGB *const buffer; - /// Total width of buffer. - const int width; - /// Total height of buffer. - const int height; - /// \c true if \a buffer must be freed by this instance. - const bool owner; - - /// Current color. - RGB color; - /// Current font. - const Font *font; - /// Current line width. - int lineWidth; - - /// X translation. - const int tx; - /// Y translation. - const int ty; - /// clip x. - const int cx; - /// clip y. - const int cy; - /// clip width. - const int cw; - /// clip height. - const int ch; - - /// Current position x coordinate. - int x; - /// Current position y coordinate. - int y; - -public: - /// Create an empty drawable object with given dimensions. - /** Optionally, the area is cleared with a given color (default: fully transparent). */ - Drawable(int w, int h, RGB clear = Color::Transparent); - - /// Deep-copying copy constructor. - /** It honours clip and translate so that the resulting drawable, if drawn - * to the source drawable at (0,0), yields the same result as drawing - * directly to the source surface. If \p fill is not explicitly set, will - * copy the original surface's contents */ - Drawable(Drawable &src, RGB clear = 0); - - /// Shallow-copying copy constructor with clip & translate. See setClipTranslate(int x, int y, int w, int h). - Drawable(Drawable &src, int x, int y, int w, int h); - - /// Destructor. - virtual ~Drawable(); - - /// Clears the surface. - void clear(RGB clear = Color::Transparent); - - /// Change current drawing color. - /** The alpha part is honoured in all drawing primitives like this: - All drawing operations in this window will unconditionally overwrite - earlier content of this window. Only when combining this window with - it's parent, the alpha channel is fully honoured. */ - void setColor(RGB c) { color = c; }; - /// Return the currently selected drawing color. - RGB getColor() { return color; }; - - /// Change current drawing font. - void setFont(const Font *f) { font = f; }; - /// Return the currently selected drawing font. - const Font *getFont() { return font; }; - - /// Change current line width. - void setLineWidth(int w) { lineWidth = w; }; - /// Return the current line width. - int getLineWidth() { return lineWidth; }; - - /// Move the current position to the given coordinates. - void gotoXY(int x, int y) { this->x = x; this->y = y; }; - /// Return current position X. - int getX() { return x; } - /// Return current position Y. - int getY() { return y; } - - /// Return clip width - int getClipX() { return cx; } - /// Return clip height - int getClipY() { return cy; } - /// Return clip width - int getClipWidth() { return cw; } - /// Return clip height - int getClipHeight() { return ch; } - - /// Paint a single pixel at the current position. - void drawPixel() { if (x >= cx && x < cw && y >= cy && y < ch) buffer[x+tx+(y+ty)*width] = color; }; - /// Paint a single pixel at the given coordinates. - void drawPixel(int x, int y) { gotoXY(x,y); drawPixel(); }; - - /// Return the pixel color at the current position. - RGB getPixel() { if (x >= cx && x < cw && y >= cy && y < ch) return buffer[x+tx+(y+ty)*width]; return Color::Transparent; }; - /// Return the pixel color at the given coordinates. - RGB getPixel(int x, int y) { gotoXY(x,y); return getPixel(); }; - - /// Draw a straight line from the current position to the given coordinates. - void drawLine(int x2, int y2); - /// Draw a straight line from (\p x1,\p y1) to (\p x2,\p y2). - void drawLine(int x1, int y1, int x2, int y2) { gotoXY(x1,y1); drawLine(x2,y2); }; - - /// Draw a circle centered at the current position with diameter \p d. - /** The current position is not changed. */ - void drawCircle(int d); - /// Draw a circle centered at the given coordinates with diameter \p d. - /** The current position is set to the center. */ - void drawCircle(int x, int y, int d) { gotoXY(x, y); drawCircle(d); }; - - /// Draw a rectangle with top left at the current position and size \p w, \p h. - /** The current position is not changed. */ - void drawRect(int w, int h); - /// Draw a rectangle with top left at the given coordinates and size \p w, \p h. - /** The current position is set to the top left corner. */ - void drawRect(int x, int y, int w, int h) { gotoXY(x, y); drawRect(w, h); }; - - /// Flood-fill an area at the current position. - /** A continuous area with the same RGB value as the selected pixel is - changed to the current color. The current position is not changed. */ - void fill(); - /// Flood-fill an area at a given position. - /** see fill(), but moves current position to the given coordinates */ - void fill(int x, int y) { gotoXY(x,y); fill(); }; - - /// Draw a filled circle centered at the current position with diameter \p d. - /** The current position is not changed. */ - void fillCircle(int d); - /// Draw a filled circle centered at the given coordinates with diameter \p d. - /** The current position is set to the center. */ - void fillCircle(int x, int y, int d) { gotoXY(x, y); fillCircle(d); }; - - /// Draw a filled rectangle with top left at the current position and size \p w, \p h. - /** The current position is not changed. */ - void fillRect(int w, int h); - /// Draw a filled rectangle with top left at the given coordinates and size \p w, \p h. - /** The current position is set to the top left corner. */ - void fillRect(int x, int y, int w, int h) { gotoXY(x, y); fillRect(w, h); }; - - /// Draw a text string. - /** Current position is the leftmost pixel on the baseline of the character. - The current position is moved to the next character. Background is not - cleared. If \p interpret is \c true, some ASCII control characters like - backspace, line-feed, tab and ANSI colors are interpreted, and text is word-wrapped at - the window borders. You can optionally pass start and length of a substring - to print */ - void drawText(const String& text, bool interpret = true, Size start = 0, Size len = (Size)-1); - - /// Draw a text string at a fixed position. - /** see drawText(const String& text, bool interpret, Size start, Size len) */ - template void drawText(int x, int y, const STR text, bool interpret, Size start, Size len = (Size)-1) { gotoXY(x,y); drawText(String(text), interpret, start, len); }; - /// Draw a single character. - /** see drawText(const STR text, bool interpret), except wrapping is - performed on this character only */ - void drawText(const Char c, bool interpret = false); - /// Draw a single character at a fixed position. - /** see drawText(const Char c, bool interpret). */ - void drawText(int x, int y, const Char c, bool interpret = false) { gotoXY(x,y); drawText(c, interpret); }; - - /// Copy the contents of another Drawable to this one. - /** The top left corner of the source Drawable is put at the current - position. The alpha channel is fully honoured. Additionally, an extra - \p alpha value may be given which is multiplied with the source - alpha channel. The current position remains unchanged. */ - void drawDrawable(Drawable &d, unsigned char alpha = 1); - /// Copy the contents of another Drawable to this one at a given position. - /** see drawDrawable(Drawable &d, unsigned char alpha). The current position - is moved to the given coordinates. */ - void drawDrawable(int x, int y, Drawable &d, unsigned char alpha = 1) { gotoXY(x,y); drawDrawable(d, alpha); }; - -}; - -/** \brief A variable- or fixed-width fixed-size Font. - * - * These Fonts can't be scaled once instantiated, but it is possible - * to subclass this abstract font class to encapsulate scalable - * fonts. Fonts can be anti-aliasing and multi-coloured, depending on - * subclass. There is no encoding enforced. The font object implicitly - * knows about it's encoding. Because of that, there is a utility - * function for string examination as well. - * - * You can't instantiate objects of this class directly, use one of the - * subclasses like BitmapFont. - * - * This class provides a font registry which allows you to register - * and retrieve font objects using a name of your choice. It is recommended - * to use a naming scheme like "FontName-variant-pixelsize-encoding" where - * variant is "normal", "bold", "italic" or "bolditalic". No one enforces - * this, however. - * - * The GUI uses some special font names. You must add them before creating - * the relevant GUI item. - * \li \c default - used if a requested font was not found - * \li \c title - GUI::ToplevelWindow title - * \li \c input - GUI::Input - * - */ -class Font { -protected: - friend void Drawable::drawText(const Char c, bool interpret); - friend void Drawable::drawText(const String& s, bool interpret, Size start, Size len); - - /// Compare two strings for 'less-than'. - struct ltstr { bool operator()(const char* s1, const char* s2) const { - return strcmp(s1, s2) < 0; - } }; - /// Font registry. Contains all known font objects indexed by name. - static std::map registry; - - /// Default constructor. - Font() {}; - - /// Draw character to a drawable at the current position. - /** \p d's current position is advanced to the position of the next character. - * The y coordinate is located at the baseline before and after the call. */ - virtual void drawChar(Drawable *d, const Char c) const = 0; - - /// Draw \p len characters to a drawable at the current position, starting at string position \p start. - /** This can be used to provide kerning. */ - virtual void drawString(Drawable *d, const String &s, Size start, Size len) const { - if (len > s.size()-start) len = (Size)(s.size()-start); - len += start; - while (start < len) drawChar(d,s[start++]); - } - -public: - /// Return a font with the given name (case-sensitive). - /** If no font was registered with that name, returns NULL. */ - static const Font *getFont(const char *name) { - std::map::iterator i = registry.find(name); - if (i == registry.end()) return(strcmp(name,"default")?getFont("default"):NULL); - return (*i).second; - } - - /// Add a font with a given name. - /** Don't delete this font once added. This class will do that for you. - * If a font with that name already exists, it will be replaced. */ - static void addFont(const char *name, Font *font) { - std::map::iterator i = registry.find(name); - if (i != registry.end()) delete (*i).second; - registry[name] = font; - } - - virtual ~Font() {}; - - /// Retrieve total height of font in pixels. - virtual int getHeight() const = 0; - - /// Retrieve the ascent, i.e. the number of pixels above the base line. - virtual int getAscent() const = 0; - - /// Return width of a string. - template int getWidth(const STR s, Size start = 0, Size len = (Size)-1) const { - return this->getWidth(String(s), start, len); - } - - /// Retrieve width of a character. - virtual int getWidth(Char c = 'M') const = 0; - - /// Retrieve width of a string of characters. - /** Can be used to provide kerning. */ - virtual int getWidth(const String &s, Size start = 0, Size len = (Size)-1) const { - int width = 0; - if (start+len > s.size()) len = (Size)(s.size()-start); - while (len--) width += getWidth(s[start++]); - return width; - } - - /// Characters with special appearance or meaning. - enum SpecialChar { CR = '\r', LF = '\n', BS = '\b', Tab = '\t', Space = ' ', ESC = 27 }; - - /// Convert a character to an equivalent SpecialChar. May return values not in SpecialChar. - virtual SpecialChar toSpecial(Char c) const { return (SpecialChar)(c<255?c:255); } - - /// Convert a SpecialChar to an equivalent character. - virtual Char fromSpecial(SpecialChar c) const { return c; } -}; - -/** \brief A bitmap font. - * This is a font which is defined by a binary bit map. Each bit in the bitmap - * defines one pixel. Bits may be arranged in various common patterns. - * - * Encoding free, character size depends on number of characters in the font. - */ -class BitmapFont : public Font { -protected: - /// The actual font data. - const unsigned char *const bitmap; - - /// Width of a character cell. - const int width; - - /// Height of all characters. - const int height; - - /// Ascent of all characters. - const int ascent; - - /// Array of character widths. If font is fixed-width, this is NULL and \a width is used. - const int *const widths; - - /// Array of character ascents. If this is NULL, \a ascent is used for all characters. - /** This allows character data to be flush to the top or bottom of it's bitmap area. */ - const int *const ascents; - - /// True if set bits are background, false otherwise. - const bool background_set; - - /// Number of bits added to get from a column to the next column. - const int col_step; - - /// Distance between 2 rows of a character, or 0 for variable-width rows. - const int row_step; - - /// Distance of two characters in the bitmap in bits. - /** This is calculated as abs(row_step*height) unless explicitly specified. */ - const int character_step; - - /// Array of pointers to font data. If set, neither \a bitmap nor \a character_step are used. - const unsigned char *const*const char_position; - - /// Array of SpecialChar equivalents. - /** If unset, encoding is assumed ASCII-like for the first 32 characters */ - const SpecialChar *const special; - - /// If \c true, then all arrays are freed on destruction. - const bool owner; - - /// Last defined character. Characters above this will be ignored. - const Char last; - - /// Draw character to a drawable at the current position. - /** \p d's current position is advanced to the position of the next character. - * The y coordinate is located at the baseline before and after the call. */ - virtual void drawChar(Drawable *d, const Char c) const; - -public: - /// Constructor. - /** The default values provide an 8 bit wide fixed-width pixel layout with each byte a row, - * arranged top-to-bottom just like a PC's VGA font. See the individual member documentation - * for details on the parameters. */ - BitmapFont(const unsigned char *data, int height, int ascent, bool owner = false, - int width = 8, bool background_set = false, - int col_step = -1, int row_step = 8, int character_step = 0, Char last = 256, - const int *widths = NULL, const int *ascents = NULL, - const unsigned char *const* char_position = NULL, - const SpecialChar *special = NULL); - - virtual ~BitmapFont(); - - /// Retrieve total height of font in pixels. - virtual int getHeight() const { return height; }; - - /// Retrieve the ascent, i.e. the number of pixels above the base line. - virtual int getAscent() const { return ascent; }; - - /// Retrieve width of a character. - virtual int getWidth(Char c = 'M') const { return (widths != NULL?widths[c]:width); }; - - /// Convert a character to an equivalent SpecialChar. See Font::toSpecial(Char c) - virtual SpecialChar toSpecial(Char c) const { return (special != NULL?special[c]:Font::toSpecial(c)); } - - /// Convert a character to an equivalent character. See Font::fromSpecial(SpecialChar c). - virtual Char fromSpecial(SpecialChar c) const { if (special == NULL) return Font::fromSpecial(c); Char i = 0; while(special[i] != c) i++; return i; } - -}; - -class ActionEventSource; -/// Callback for action events. -struct ActionEventSource_Callback { -public: - /// Handler with optional String argument. - /** If the event source doesn't provide an additional argument, the name will be used. */ - virtual void actionExecuted(ActionEventSource *source, const String &arg) = 0; - virtual ~ActionEventSource_Callback() {} -}; - -/// Event class for action events. -/** Action events are events generated by GUI elements like Buttons, Menus and by pressing Enter in - * an Input. All of these are handled similarly: The source of such an event has a name, and the - * Event may also be connected with a String describing what was executed, like the name of the - * Menu entry or the contents of the Input. - */ -class ActionEventSource { -protected: - /// List of registered action handlers. - std::list actionHandlers; - - /// This event source's name. - /** The name is primarily meant for your own purposes, for example identification of the activated - * element. One exception are Menubars, which display the name of their Menus. */ - String name; - -public: - /// Create a named event source. - template ActionEventSource(const STR name) : name(String(name)) { } - - /// Dummy destructor. - virtual ~ActionEventSource() {} - - /// Add a button press event handler. - void addActionHandler(ActionEventSource_Callback *handler) { actionHandlers.push_back(handler); } - - /// Remove a button press event handler. - void removeActionHandler(ActionEventSource_Callback *handler) { actionHandlers.remove(handler); } - - /// Set the name of this event source. - template void setName(const STR name) { this->name = String(name); } - - /// Get the name of this event source. - const String &getName() const { return name; } - - /// Execute handlers. - void executeAction(const String &arg) { - std::list::iterator i = actionHandlers.begin(); - bool end = (i == actionHandlers.end()); - while (!end) { - ActionEventSource_Callback *c = *i; - ++i; - end = (i == actionHandlers.end()); - c->actionExecuted(this,arg); - } - } - - /// Execute handlers. - void executeAction() { executeAction(name); } -}; - -/// Internal class for windows whose child content should not span the entire area. -class BorderedWindow : public Window { -protected: - /// Borders. - int border_left, border_top, border_right, border_bottom; - - /// Create a bordered window. - BorderedWindow(Window *parent, int x, int y, int w, int h, int bl, int bt, int br, int bb) : - Window(parent,x,y,w,h), border_left(bl), border_top(bt), border_right(br), border_bottom(bb) {} - -public: - virtual void paintAll(Drawable &d) const; - virtual bool mouseMoved(int x, int y); - virtual bool mouseDown(int x, int y, MouseButton button); - virtual bool mouseDragged(int x, int y, MouseButton button); - virtual int getScreenX() const { return Window::getScreenX()+border_left; } - virtual int getScreenY() const { return Window::getScreenY()+border_top; } -}; - -/// A text label -/** Text labels are positioned relative to the top left corner of their bounding box. - * They size themselves automatically and display their text in non-interpreted mode. - */ - -class Label : public Window { - /// The Font used - const Font *font; - - /// Text color - RGB color; - - /// Text - String text; - - /// multiline text? - bool interpret; - -public: - /// Create a text label with given position, \p text, \p font and \p color. - /** If \p width is given, the resulting label is a word-wrapped multiline label */ - template Label(Window *parent, int x, int y, const STR text, int width = 0, const Font *font = Font::getFont("default"), RGB color = Color::Text) : - Window(parent, x, y, (width?width:1), 1), font(font), color(color), text(text), interpret(width != 0) - { resize(); } - - /// Set a new text. Size of the label is adjusted accordingly. - template void setText(const STR text) { this->text = text; resize(); } - /// Retrieve current text - const String& getText() { return text; } - - /// Set a new font. Size of the label is adjusted accordingly. - void setFont(const Font *font) { this->font = font; resize(); } - /// Retrieve current font - const Font *getFont() { return font; } - - /// Set a new text color. - void setColor(const RGB color) { this->color = color; resize(); } - /// Retrieve current color - RGB getColor() { return color; } - - /// Calculate label size. Parameters are ignored. - virtual void resize(int w = -1, int h = -1) { - if (w == -1) w = (interpret?getWidth():0); - else interpret = (w != 0); - Drawable d((w?w:1), 1); - d.setFont(font); - d.drawText(0, font->getAscent(), text, interpret, 0); - if (interpret) Window::resize(w, d.getY()-font->getAscent()+font->getHeight()); - else Window::resize(d.getX(), font->getHeight()); - } - - /// Paint label - virtual void paint(Drawable &d) const { d.setColor(color); d.drawText(0, font->getAscent(), text, interpret, 0); } - - virtual bool raise() { return false; } -}; - - -/// A single-line text input -/** It uses Font::getFont("input") to display content. - * It supports selection, the clipboard and all well-known key bindings (except undo). - */ -class Input : public Window, public Timer_Callback, public ActionEventSource { -protected: - /// The text entered. - String text; - - /// Current position in \a text. - Size pos; - - /// Last updated position in \a text. - Size lastpos; - - /// Coordinates according to pos. - int posx, posy; - - /// Selection in \a text. - Size start_sel, end_sel; - - /// Is cursor visible at the moment? - bool blink; - - /// Insert mode? - bool insert; - - /// Multiline? - bool multi; - - /// Horizontal scrolling offset. - int offset; - - /// Ensure that pos is visible. - void checkOffset() { - if (lastpos == pos) return; - const Font *f = Font::getFont("input"); - if (multi) { - Drawable d(width-6,1); - d.setFont(f); - d.drawText(0, 0, text, multi, 0, pos); - posy = d.getY(); - posx = d.getX(); - if (posy-offset > height-8-f->getHeight()) offset = posy-height+8+f->getHeight(); - if (posy-offset < 0) offset = posy; - } else { - posy = 0; - posx = f->getWidth(text,0,pos); - if (f->getWidth(text,0,pos+1)-offset > width-10) offset = f->getWidth(text,0,pos+1)-width+10; - if (f->getWidth(text,0,(pos>0?pos-1:0))-offset < 0) offset = f->getWidth(text,0,(pos>0?pos-1:0)); - } - lastpos = pos; - setDirty(); - } - -public: - /// Create an input with given position and width. If not set, height is calculated from the font and input is single-line. - Input(Window *parent, int x, int y, int w, int h = 0) : - Window(parent,x,y,w,(h?h:Font::getFont("input")->getHeight()+10)), ActionEventSource("GUI::Input"), - text(""), pos(0), lastpos(0), posx(0), posy(0), start_sel(0), end_sel(0), blink(true), insert(true), multi(h != 0), offset(0) - { Timer::add(this,30); } - - ~Input() { - Timer::remove(this); - } - - /// Paint input. - virtual void paint(Drawable &d) const; - - /// Clear selected area. - void clearSelection() { - text.erase(text.begin()+(pos = imin(start_sel,end_sel)),text.begin()+imax(start_sel,end_sel)); - start_sel = end_sel = pos; - } - - /// Copy selection to clipboard. - void copySelection() { - setClipboard(String(text.begin()+imin(start_sel,end_sel),text.begin()+imax(start_sel,end_sel))); - } - - /// Cut selection to clipboard. - void cutSelection() { - setClipboard(String(text.begin()+imin(start_sel,end_sel),text.begin()+imax(start_sel,end_sel))); - clearSelection(); - } - - /// Paste from clipboard. - void pasteSelection() { - String c = getClipboard(); - clearSelection(); - text.insert(text.begin()+pos,c.begin(),c.end()); - start_sel = end_sel = pos += (Size)c.size(); - } - - /// get character position corresponding to coordinates - Size findPos(int x, int y); - - /// Set text to be edited. - template void setText(const STR text) { this->text = text; setDirty(); }; - /// Get the entered text. If you need it longer, copy it immediately. - const String& getText() { return text; }; - - /// Handle text input. - virtual bool keyDown(const Key &key); - - /// Handle mouse input. - virtual bool mouseDown(int x, int y, MouseButton button); - - /// Handle mouse input. - virtual bool mouseDragged(int x, int y, MouseButton button); - - /// Timer callback function - virtual Ticks timerExpired(Ticks time) - { blink = !blink; setDirty(); return 30; } - -}; - -class ToplevelWindow; -/// Callbacks for window events. -struct ToplevelWindow_Callback { -public: - /// The window has been asked to be closed. - /** Return \c false in order to block the requested action. Do not do any - * deallocation here, as other callbacks may abort the close process. - */ - virtual bool windowClosing(ToplevelWindow *win) = 0; - - /// The window will been closed. - /** Now it is safe to deallocate all external resources that applications - * may have associated with this window, like registering this window - * with external callbacks. - */ - virtual void windowClosed(ToplevelWindow *win) = 0; - virtual ~ToplevelWindow_Callback() {} -}; - -/// An actual decorated window. -class ToplevelWindow : public BorderedWindow, public ActionEventSource_Callback { -protected: - /// Title text - String title; - - /// Drag base - int dragx, dragy; - - /// List of registered event handlers. - std::list closehandlers; - - /// System menu (top left) - Menu *systemMenu; - -public: - /// Create a new GUI Frame with title bar, border and close button - template ToplevelWindow(Screen *parent, int x, int y, int w, int h, const STR title); - - /// Call cleanup handlers - ~ToplevelWindow() { - std::list::iterator i = closehandlers.begin(); - bool end = (i == closehandlers.end()); - while (!end) { - ToplevelWindow_Callback *c = *i; - ++i; - end = (i == closehandlers.end()); - c->windowClosed(this); - } - } - - /// Menu callback function - virtual void actionExecuted(ActionEventSource *src, const String &item) { - if (item == String("Close")) close(); - } - - /// Add a window event handler. - void addCloseHandler(ToplevelWindow_Callback *handler) { closehandlers.push_back(handler); } - - /// Remove a window event handler. - void removeCloseHandler(ToplevelWindow_Callback *handler) { closehandlers.remove(handler); } - - virtual void paint(Drawable &d) const; - virtual bool mouseDown(int x, int y, MouseButton button); - virtual bool mouseDoubleClicked(int x, int y, MouseButton button) { - if (button == Left && x < 32 && x > 6 && y > 4 && y < 31) { - close(); - return true; - } - BorderedWindow::mouseClicked(x,y,button); - return true; - } - virtual bool mouseUp(int x, int y, MouseButton button) { - if (button == Left && dragx >= 0 && dragy >= 0) { - dragx = dragy = -1; - return true; - } - BorderedWindow::mouseUp(x,y,button); - return true; - } - virtual bool mouseDragged(int x, int y, MouseButton button) { - if (button == Left && dragx >= 0 && dragy >= 0) { - move(x-dragx+this->x,y-dragy+this->y); - return true; - } - BorderedWindow::mouseDragged(x,y,button); - return true; - } - virtual bool mouseMoved(int x, int y) { - BorderedWindow::mouseMoved(x,y); - return true; - } - - /// Put window on top of all other windows without changing their relative order - virtual bool raise() { - Window *last = parent->children.back(); - parent->children.remove(this); - parent->children.push_back(this); - if (last != this) { - focusChanged(true); - last->focusChanged(false); - } - return true; - } - - /// Set a new title. - template void setTitle(const STR title) { this->title = title; setDirty(); } - /// Retrieve current title. - const String& getTitle() { return title; } - - /// Close window. - void close() { - bool doit = true; - std::list::iterator i = closehandlers.begin(); - bool end = (i == closehandlers.end()); - while (!end) { - ToplevelWindow_Callback *c = *i; - ++i; - end = (i == closehandlers.end()); - doit = doit && c->windowClosing(this); - } - if (doit) delete this; - } -}; - -/// A floating temporary window that is not restricted by it's parent's area. -/** They have a parent which displays them, - * but that parent is not their real parent in the window hierarchy: They are always top-level elements, thus - * they are not clipped to their logical parent's area, they can freely overlay any part of the screen. - * As another consequence, they are not automatically deleted when their logical parent is deleted. - * - * You should observe the following points: - * \li TransientWindows behave mostly as if their logical parent was their true parent, but are not - * restricted to it's area - * \li TransientWindows are deleted automatically when the ToplevelWindow is deleted in which their logical - * parent resides; do NOT delete them in your destructor or bad things will happen - * \li only the logical parent object can show/hide a TransientWindow at will - * \li it will close automatically upon clicking other GUI elements, \em except for the - * logical parent and it's children - */ -class TransientWindow : public Window, Window_Callback, ToplevelWindow_Callback { -protected: - /// The true parent window. - Window *realparent; - - /// User selected position relative to logical parent. - int relx, rely; - -public: - /// Handle automatic hiding - virtual void focusChanged(bool gained) { - Window::focusChanged(gained); - if (isVisible() && !gained) { - if (realparent->hasFocus()) raise(); - else setVisible(false); - } - } - - /// Handle automatic delete - void windowClosed(ToplevelWindow *win) { - delete this; - } - - /// No-op - bool windowClosing(ToplevelWindow *win) { return true; } - - /// Create a transient window with given position and size - /** \a parent is the logical parent. The true parent object is - * always the screen the logical parent resides on. */ - TransientWindow(Window *parent, int x, int y, int w, int h) : - Window(parent->getScreen(),x+parent->getScreenX(),y+parent->getScreenY(),w,h), - realparent(parent), relx(x), rely(y) { - Window *p = realparent, *last = NULL, *last2 = NULL; - while (p != NULL) { - p->addWindowHandler(this); - last2 = last; - last = p; - p = p->getParent(); - } - dynamic_cast(last2)->addCloseHandler(this); - } - - ~TransientWindow() { - Window *p = realparent, *last = NULL, *last2 = NULL; - while (p != NULL) { - p->removeWindowHandler(this); - last2 = last; - last = p; - p = p->getParent(); - } - dynamic_cast(last2)->removeCloseHandler(this); - } - - virtual void move(int x, int y) { relx = x; rely = y; - Window::move(x+realparent->getScreenX(),y+realparent->getScreenY()); } - virtual int getX() const { return x-realparent->getScreenX(); } - virtual int getY() const { return y-realparent->getScreenY(); } - virtual void setVisible(bool v) { if (v) raise(); Window::setVisible(v); } - virtual void windowMoved(Window *src, int x, int y) { move(relx,rely); } - - /// Put window on top of all other windows without changing their relative order - virtual bool raise() { - Window *last = parent->children.back(); - parent->children.remove(this); - parent->children.push_back(this); - if (last != this) { - focusChanged(true); - last->focusChanged(false); - } - return true; - } - -}; - -/// A popup menu. -/** Popup menus are used as context menus or as part of a menu bar. Menus are not visible when created. - * Menus have a name which can be used in event handlers to identify it, and it is used in Menubars as well. - * - * Currently, menu entries are not interpreted in any way. This may change in the future. To ensure upwards - * compatibility, avoid the \c '&' character in menu entries, since it may have a special meaning in future - * versions. Menus use the Font named "menu". - * - * Please note the general remarks in GUI::TransientWindow - */ -class Menu : public TransientWindow, public ActionEventSource { -protected: - /// List of menu items (displayed text) - std::vector items; - - /// Currently selected menu item. - /** Can be -1 if no item is currently active. */ - int selected; - - /// Flag to skip the first mouseUp-event - bool firstMouseUp; - - /// Where we grabbed the mouse from. - Window *mouseTakenFrom; - - /// Selects menu item at position (x,y). - /** \a selected is set to -1 if there is no active item at that location. */ - virtual void selectItem(int x, int y) { - y -= 2; - selected = -1; - const int height = Font::getFont("menu")->getHeight()+2; - std::vector::iterator i; - for (i = items.begin(); i != items.end() && y > 0; ++i) { - selected++; - if ((*i).size() > 0) y -= height; - else y -= 12; - } - if (y > 0 || (selected >= 0 && items[selected].size() == 0)) selected = -1; - } - - virtual Size getPreferredWidth() { - Size width = 0; - const Font *f = Font::getFont("menu"); - std::vector::iterator i; - for (i = items.begin(); i != items.end() && y > 0; ++i) { - Size newwidth = f->getWidth(*i); - if (newwidth > width) width = newwidth; - } - return width+39; - } - - virtual Size getPreferredHeight() { - Size height = 0; - const Size h = Font::getFont("menu")->getHeight()+2; - std::vector::iterator i; - for (i = items.begin(); i != items.end() && y > 0; ++i) { - height += ((*i).size() > 0?h:12); - } - return height+6; - } - -public: - /// Create a menu with given position - /** Size is determined dynamically. \a parent is the logical parent. The true parent object is - * always the screen the logical parent resides on. */ - template Menu(Window *parent, int x, int y, const STR name) : - TransientWindow(parent,x,y,4,4), ActionEventSource(name), selected(-1) - { setVisible(false); } - - ~Menu() { - setVisible(false); - } - - /// Paint button. - virtual void paint(Drawable &d) const; - - /// Highlight current item. - virtual bool mouseMoved(int x, int y) { - selectItem(x,y); - return true; - } - - /// Highlight current item. - virtual bool mouseDragged(int x, int y, MouseButton b) { - selectItem(x,y); - return true; - } - - virtual bool mouseDown(int x, int y, MouseButton button) { return true; } - - /// Possibly select item. - virtual bool mouseUp(int x, int y, MouseButton button) { - selectItem(x,y); - if (firstMouseUp) firstMouseUp = false; - else setVisible(false); - execute(); - return true; - } - - /// Handle keyboard input. - virtual bool keyDown(const Key &key) { - if (key.special == Key::Up) selected--; - else if (key.special == Key::Down) selected++; - else if (key.special == Key::Enter) { execute(); return true; } - else if (key.special == Key::Escape) { setVisible(false); return true; } - else return true; - if (items[selected].size() == 0 && items.size() > 1) return keyDown(key); - if (selected < 0) selected = (int)(items.size()-1); - if (selected >= (int)items.size()) selected = 0; - return true; - } - - - /// Add a menu item at end. An empty string denotes a separator. - template void addItem(const T item) { - items.push_back(String(item)); - resize(getPreferredWidth(),getPreferredHeight()); - } - - /// Remove an existing menu item. - template void removeItem(const T item) { - const String s(item); - std::vector::iterator i = items.begin(); - while (i != items.end() && s != (*i)) ++i; - if (i != items.end()) items.erase(i); - resize(getPreferredWidth(),getPreferredHeight()); - } - - virtual void setVisible(bool v) { - TransientWindow::setVisible(v); - if (v) { - parent->mouseChild = this; - raise(); - firstMouseUp = true; - } - } - - /// Execute menu item. - void execute() { - if (selected >= 0) { - setVisible(false); - executeAction(items[selected]); - } - } -}; - -/// A push button -/** Buttons have 3D appearance and can have any child widget as content. - * There are convenience constructors for common forms of buttons. - */ -class Button : public BorderedWindow, public ActionEventSource { -protected: - /// \c true, if button is currently pressed down. - bool pressed; - -public: - /// Create a button with given position and size - Button(Window *parent, int x, int y, int w, int h) : BorderedWindow(parent,x,y,w,h,6,5,6,5), ActionEventSource("GUI::Button"), pressed(0) {} - - /// Create a text button. - /** If a size is specified, text is centered. Otherwise, button size is adjusted for the text. */ - template Button(Window *parent, int x, int y, const T text, int w = -1, int h = -1); - - /// Paint button. - virtual void paint(Drawable &d) const; - - /// Press button. - virtual bool mouseDown(int x, int y, MouseButton button) { - border_left = 7; border_right = 5; border_top = 7; border_bottom = 3; - pressed = true; - return true; - } - - /// Release button. - virtual bool mouseUp(int x, int y, MouseButton button) { - border_left = 6; border_right = 6; border_top = 5; border_bottom = 5; - pressed = false; - return true; - } - - /// Handle mouse activation. - virtual bool mouseClicked(int x, int y, MouseButton button) { - if (button == Left) { - executeAction(); - return true; - } - return false; - } - - /// Handle keyboard input. - virtual bool keyDown(const Key &key); - - /// Handle keyboard input. - virtual bool keyUp(const Key &key); - -}; - -/// A menu bar at the top of a ToplevelWindow -/** Menu bars aggregate several Menus. They have a simple border at the bottom. If your application - * has a work area with 3D sunken look, place it so that it overlaps the menu by one row. - * - * As with Menus, avoid the character \c '&' in Menu names as it may - * have a special meaning in future versions. Menubars use the Font named "menu". - */ -class Menubar : public Window, public ActionEventSource, ActionEventSource_Callback { -protected: - /// Currently activated menu index. - int selected; - - /// Horizontal position of next menu. - int lastx; - - /// List of Menus. - std::vector menus; - -public: - /// Create a menubar with given position and size - /** Height is autocalculated from font size */ - Menubar(Window *parent, int x, int y, int w) : Window(parent,x,y,w,Font::getFont("menu")->getHeight()+5), ActionEventSource("GUI::Menubar"), selected(-1), lastx(0) {} - - /// Add a Menu. - template void addMenu(const STR name) { - const String n(name); - menus.push_back(new Menu(this,lastx,height-2,n)); - menus.back()->addActionHandler(this); - lastx += Font::getFont("menu")->getWidth(n)+14; - } - - /// Add a Menuitem. - template void addItem(int index, const STR name) { menus[index]->addItem(name); } - - /// Remove a Menuitem. - template void removeItem(int index, const STR name) { menus[index]->removeItem(name); } - - /// Paint menubar. - virtual void paint(Drawable &d) const; - - /// Open menu. - virtual bool mouseDown(int x, int y, MouseButton button) { - int oldselected = selected; - if (selected >= 0 && !menus[selected]->isVisible()) oldselected = -1; - if (selected >= 0) menus[selected]->setVisible(false); - if (x < 0 || x >= lastx) return true; - for (selected = (int)(menus.size()-1); menus[selected]->getX() > x; selected--) {}; - if (oldselected == selected) selected = -1; - else menus[selected]->setVisible(true); - return true; - } - - /// Handle keyboard input. - virtual bool keyDown(const Key &key) { return true; }; - - /// Handle keyboard input. - virtual bool keyUp(const Key &key) { return true; }; - - virtual void actionExecuted(ActionEventSource *src, const String &arg) { - std::list::iterator i = actionHandlers.begin(); - bool end = (i == actionHandlers.end()); - while (!end) { - ActionEventSource_Callback *c = *i; - ++i; - end = (i == actionHandlers.end()); - c->actionExecuted(src,arg); - } - } -}; - -/// A checkbox -/** Checkboxes can have any child widget as content. - * There are convenience constructors for common forms of checkboxes. - */ -class Checkbox : public BorderedWindow, public ActionEventSource { -protected: - /// \c true, if checkbox is currently selected. - bool checked; - -public: - /// Create a checkbox with given position and size - Checkbox(Window *parent, int x, int y, int w, int h) : BorderedWindow(parent,x,y,w,h,16,0,0,0), ActionEventSource("GUI::Checkbox"), checked(0) {} - - /// Create a checkbox with text label. - /** If a size is specified, text is centered. Otherwise, checkbox size is adjusted for the text. */ - template Checkbox(Window *parent, int x, int y, const T text, int w = -1, int h = -1); - - /// Paint checkbox. - virtual void paint(Drawable &d) const; - - /// Change checkbox state. - virtual void setChecked(bool checked) { this->checked = checked; } - - /// Get checkbox state. - virtual bool isChecked() { return checked; } - - /// Press checkbox. - virtual bool mouseDown(int x, int y, MouseButton button) { - checked = !checked; - return true; - } - - /// Release checkbox. - virtual bool mouseUp(int x, int y, MouseButton button) { - execute(); - return true; - } - - /// Handle keyboard input. - virtual bool keyDown(const Key &key); - - /// Handle keyboard input. - virtual bool keyUp(const Key &key); - - /// Execute handlers. - virtual void execute() { - String arg(name); - if (!checked) arg.insert(arg.begin(),'!'); - executeAction(arg); - } -}; - -class Frame; - -/// A radio box. -/** Radio boxes can have any child widget as content. - * There are convenience constructors for common forms of radio boxes. - */ -class Radiobox : public BorderedWindow, public ActionEventSource { -protected: - /// \c true, if radio box is currently selected. - bool checked; - -public: - /// Create a radio box with given position and size - Radiobox(Frame *parent, int x, int y, int w, int h); - - /// Create a radio box with text label. - /** If a size is specified, text is centered. Otherwise, checkbox size is adjusted for the text. */ - template Radiobox(Frame *parent, int x, int y, const T text, int w = -1, int h = -1); - - /// Paint radio box. - virtual void paint(Drawable &d) const; - - /// Change radio box state. - virtual void setChecked(bool checked) { this->checked = checked; } - - /// Get radio box state. - virtual bool isChecked() { return checked; } - - /// Press radio box. - virtual bool mouseDown(int x, int y, MouseButton button) { - checked = true; - return true; - } - - /// Release checkbox. - virtual bool mouseUp(int x, int y, MouseButton button) { - executeAction(); - return true; - } - - /// Handle keyboard input. - virtual bool keyDown(const Key &key); - - /// Handle keyboard input. - virtual bool keyUp(const Key &key); -}; - -/// A rectangular 3D sunken frame -/** These can be used as generic grouping elements and also serve as aggregators for RadioBoxes. - */ -class Frame : public BorderedWindow, public ActionEventSource, protected ActionEventSource_Callback { -protected: - friend class Radiobox; - - /// Currently selected radio box. - int selected; - - /// Label of frame. - String label; - - /// Execute handlers. - virtual void actionExecuted(ActionEventSource *src, const String &arg) { - for (std::list::iterator i = children.begin(); i != children.end(); ++i) { - Radiobox *r = dynamic_cast(*i); - if (r != NULL && src != dynamic_cast(r)) r->setChecked(false); - } - executeAction(src->getName()); - } - -public: - /// Create a non-labeled frame with given position and size - Frame(Window *parent, int x, int y, int w, int h) : BorderedWindow(parent,x,y,w,h,5,5,5,5), ActionEventSource("GUI::Frame"), selected(0) {} - - /// Create a frame with text label. - template Frame(Window *parent, int x, int y, int w, int h, const T text) : - BorderedWindow(parent,x,y,w,h,5,Font::getFont("default")->getHeight()+2,5,5), - ActionEventSource(text), selected(0), label(text) { } - - /// Paint frame. - virtual void paint(Drawable &d) const; - -}; - -/// A message box with a single "Close" button. -class MessageBox : public GUI::ToplevelWindow { -protected: - Label *message; - Button *close; -public: - /// Create a new message box - template MessageBox(Screen *parent, int x, int y, int width, const STR title, const STR text) : - ToplevelWindow(parent, x, y, width, 1, title) { - message = new Label(this, 5, 5, text, width-10); - close = new GUI::Button(this, width/2-40, 10, "Close", 70); - close->addActionHandler(this); - setText(text); - } - - /// Set a new text. Size of the box is adjusted accordingly. - template void setText(const STR text) { - message->setText(text); - close->move(width/2-40, 20+message->getHeight()); - resize(width, message->getHeight()+100); - } -}; - -template ToplevelWindow::ToplevelWindow(Screen *parent, int x, int y, int w, int h, const STR title) : - BorderedWindow(parent, x, y, w, h, 6, 33, 6, 3), title(title), - dragx(-1), dragy(-1), closehandlers(), systemMenu(new Menu(this,-1,-2,"System Menu")) { - systemMenu->addItem("Move"); - systemMenu->addItem("Resize"); - systemMenu->addItem(""); - systemMenu->addItem("Minimize"); - systemMenu->addItem("Maximize"); - systemMenu->addItem("Restore"); - systemMenu->addItem(""); - systemMenu->addItem("Close"); - systemMenu->addActionHandler(this); -} - -template Button::Button(Window *parent, int x, int y, const STR text, int w, int h) : - BorderedWindow(parent,x,y,w,h,6,5,6,5), ActionEventSource(text), pressed(0) -{ - - Label *l = new Label(this,0,0,text); - if (width < 0) resize(l->getWidth()+border_left+border_right+10,height); - if (height < 0) resize(width,l->getHeight()+border_top+border_bottom+6); - l->move((width-border_left-border_right-l->getWidth())/2, - (height-border_top-border_bottom-l->getHeight())/2); -} - -template Checkbox::Checkbox(Window *parent, int x, int y, const STR text, int w, int h) : - BorderedWindow(parent,x,y,w,h,16,0,0,0), ActionEventSource(text), checked(0) -{ - Label *l = new Label(this,0,0,text); - if (width < 0) resize(l->getWidth()+border_left+border_right+4,height); - if (height < 0) resize(width,l->getHeight()+border_top+border_bottom+4); - l->move((width-border_left-border_right-l->getWidth())/2, - (height-border_top-border_bottom-l->getHeight())/2); -} - -template Radiobox::Radiobox(Frame *parent, int x, int y, const STR text, int w, int h) : - BorderedWindow(parent,x,y,w,h,16,0,0,0), ActionEventSource(text), checked(0) -{ - Label *l = new Label(this,0,0,text); - if (width < 0) resize(l->getWidth()+border_left+border_right+4,height); - if (height < 0) resize(width,l->getHeight()+border_top+border_bottom+4); - l->move((width-border_left-border_right-l->getWidth())/2, - (height-border_top-border_bottom-l->getHeight())/2); - addActionHandler(parent); -} - -}; - -#endif diff --git a/src/libs/zmbv/Makefile.am b/src/libs/zmbv/Makefile.am deleted file mode 100644 index 7715cf7..0000000 --- a/src/libs/zmbv/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = zmbv.cpp zmbv.h diff --git a/src/libs/zmbv/drvproc.cpp b/src/libs/zmbv/drvproc.cpp deleted file mode 100644 index b912c26..0000000 --- a/src/libs/zmbv/drvproc.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -// -// Zipped Motion Block Video -// -// Based on Huffyuv by Ben Rudiak-Gould. -// which was based on MSYUV sample code, which is: -// Copyright (c) 1993 Microsoft Corporation. -// All Rights Reserved. -// - -#include "zmbv_vfw.h" - -/*************************************************************************** - * DriverProc - The entry point for an installable driver. - * - * PARAMETERS - * dwDriverId: For most messages, is the DWORD - * value that the driver returns in response to a message. - * Each time that the driver is opened, through the API, - * the driver receives a message and can return an - * arbitrary, non-zero value. The installable driver interface - * saves this value and returns a unique driver handle to the - * application. Whenever the application sends a message to the - * driver using the driver handle, the interface routes the message - * to this entry point and passes the corresponding . - * This mechanism allows the driver to use the same or different - * identifiers for multiple opens but ensures that driver handles - * are unique at the application interface layer. - * - * The following messages are not related to a particular open - * instance of the driver. For these messages, the dwDriverId - * will always be zero. - * - * DRV_LOAD, DRV_FREE, DRV_ENABLE, DRV_DISABLE, DRV_OPEN - * - * hDriver: This is the handle returned to the application by the - * driver interface. - * - * uiMessage: The requested action to be performed. Message - * values below are used for globally defined messages. - * Message values from to are used for - * defined driver protocols. Messages above are used - * for driver specific messages. - * - * lParam1: Data for this message. Defined separately for - * each message - * - * lParam2: Data for this message. Defined separately for - * each message - * - * RETURNS - * Defined separately for each message. - * - ***************************************************************************/ -LRESULT PASCAL DriverProc(DWORD dwDriverID, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2) { - CodecInst* pi = (CodecInst*)dwDriverID; - - switch (uiMessage) { - case DRV_LOAD: - return (LRESULT)1L; - - case DRV_FREE: - return (LRESULT)1L; - - case DRV_OPEN: - // GAAH! This used to return a pointer to 0xFFFF0000 when lParam==0! - return (LRESULT)(DWORD)(UINT) Open((ICOPEN*) lParam2); - - case DRV_CLOSE: - if (pi) Close(pi); - return (LRESULT)1L; - - /********************************************************************* - - state messages - - *********************************************************************/ - - // cwk - case DRV_QUERYCONFIGURE: // configuration from drivers applet - return (LRESULT)1L; - - case DRV_CONFIGURE: - pi->Configure((HWND)lParam1); - return DRV_OK; - - case ICM_CONFIGURE: - // - // return ICERR_OK if you will do a configure box, error otherwise - // - if (lParam1 == -1) - return pi->QueryConfigure() ? ICERR_OK : ICERR_UNSUPPORTED; - else - return pi->Configure((HWND)lParam1); - - case ICM_ABOUT: - // - // return ICERR_OK if you will do a about box, error otherwise - // - if (lParam1 == -1) - return pi->QueryAbout() ? ICERR_OK : ICERR_UNSUPPORTED; - else - return pi->About((HWND)lParam1); - - case ICM_GETSTATE: - return pi->GetState((LPVOID)lParam1, (DWORD)lParam2); - - case ICM_SETSTATE: - return pi->SetState((LPVOID)lParam1, (DWORD)lParam2); - - case ICM_GETINFO: - return pi->GetInfo((ICINFO*)lParam1, (DWORD)lParam2); - - case ICM_GETDEFAULTQUALITY: - if (lParam1) { - *((LPDWORD)lParam1) = 10000; - return ICERR_OK; - } - break; - - /********************************************************************* - - compression messages - - *********************************************************************/ - - case ICM_COMPRESS_QUERY: - return pi->CompressQuery((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); - - case ICM_COMPRESS_BEGIN: - return pi->CompressBegin((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); - - case ICM_COMPRESS_GET_FORMAT: - return pi->CompressGetFormat((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); - - case ICM_COMPRESS_GET_SIZE: - return pi->CompressGetSize((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); - - case ICM_COMPRESS: - return pi->Compress((ICCOMPRESS*)lParam1, (DWORD)lParam2); - - case ICM_COMPRESS_END: - return pi->CompressEnd(); - - /********************************************************************* - - decompress messages - - *********************************************************************/ - - case ICM_DECOMPRESS_QUERY: - return pi->DecompressQuery((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); - - case ICM_DECOMPRESS_BEGIN: - return pi->DecompressBegin((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); - - case ICM_DECOMPRESS_GET_FORMAT: - return pi->DecompressGetFormat((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); - - case ICM_DECOMPRESS_GET_PALETTE: - return pi->DecompressGetPalette((LPBITMAPINFOHEADER)lParam1, (LPBITMAPINFOHEADER)lParam2); - - case ICM_DECOMPRESS: - return pi->Decompress((ICDECOMPRESS*)lParam1, (DWORD)lParam2); - - case ICM_DECOMPRESS_END: - return pi->DecompressEnd(); - - /********************************************************************* - - standard driver messages - - *********************************************************************/ - - case DRV_DISABLE: - case DRV_ENABLE: - return (LRESULT)1L; - - case DRV_INSTALL: - case DRV_REMOVE: - return (LRESULT)DRV_OK; - } - - if (uiMessage < DRV_USER) - return DefDriverProc(dwDriverID, hDriver, uiMessage, lParam1, lParam2); - else - return ICERR_UNSUPPORTED; -} - - -HMODULE hmoduleCodec=0; - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD, LPVOID) { - hmoduleCodec = (HMODULE) hinstDLL; - return TRUE; -} diff --git a/src/libs/zmbv/resource.h b/src/libs/zmbv/resource.h deleted file mode 100644 index f3d9a34..0000000 --- a/src/libs/zmbv/resource.h +++ /dev/null @@ -1,21 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by zmbv_vfw.rc -// -#define IDD_ABOUT 101 -#define IDD_CONFIGURE 102 -#define IDC_HOMEPAGE 1000 -#define IDC_EMAIL 1001 -#define IDC_SLIDER1 1008 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 103 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1009 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/src/libs/zmbv/zmbv.cpp b/src/libs/zmbv/zmbv.cpp deleted file mode 100644 index 44670fb..0000000 --- a/src/libs/zmbv/zmbv.cpp +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include - -#include "zmbv.h" - -#define DBZV_VERSION_HIGH 0 -#define DBZV_VERSION_LOW 1 - -#define COMPRESSION_NONE 0 -#define COMPRESSION_ZLIB 1 - -#define MAX_VECTOR 16 - -#define Mask_KeyFrame 0x01 -#define Mask_DeltaPalette 0x02 - -zmbv_format_t BPPFormat( int bpp ) { - switch (bpp) { - case 8: - return ZMBV_FORMAT_8BPP; - case 15: - return ZMBV_FORMAT_15BPP; - case 16: - return ZMBV_FORMAT_16BPP; - case 32: - return ZMBV_FORMAT_32BPP; - } - return ZMBV_FORMAT_NONE; -} -int VideoCodec::NeededSize( int _width, int _height, zmbv_format_t _format) { - int f; - switch (_format) { - case ZMBV_FORMAT_8BPP:f = 1;break; - case ZMBV_FORMAT_15BPP:f = 2;break; - case ZMBV_FORMAT_16BPP:f = 2;break; - case ZMBV_FORMAT_32BPP:f = 4;break; - default: - return -1; - } - f = f*_width*_height + 2*(1+(_width/8)) * (1+(_height/8))+1024; - return f + f/1000; -} - -bool VideoCodec::SetupBuffers(zmbv_format_t _format, int blockwidth, int blockheight) { - FreeBuffers(); - palsize = 0; - switch (_format) { - case ZMBV_FORMAT_8BPP: - pixelsize = 1; - palsize = 256; - break; - case ZMBV_FORMAT_15BPP: - pixelsize = 2; - break; - case ZMBV_FORMAT_16BPP: - pixelsize = 2; - break; - case ZMBV_FORMAT_32BPP: - pixelsize = 4; - break; - default: - return false; - }; - bufsize = (height+2*MAX_VECTOR)*pitch*pixelsize+2048; - - buf1 = new unsigned char[bufsize]; - buf2 = new unsigned char[bufsize]; - work = new unsigned char[bufsize]; - - int xblocks = (width/blockwidth); - int xleft = width % blockwidth; - if (xleft) xblocks++; - int yblocks = (height/blockheight); - int yleft = height % blockheight; - if (yleft) yblocks++; - blockcount=yblocks*xblocks; - blocks=new FrameBlock[blockcount]; - - if (!buf1 || !buf2 || !work || !blocks) { - FreeBuffers(); - return false; - } - int y,x,i; - i=0; - for (y=0;y -INLINE int VideoCodec::PossibleBlock(int vx,int vy,FrameBlock * block) { - int ret=0; - P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx; - P * pnew=((P*)newframe)+block->start;; - for (int y=0;ydy;y+=4) { - for (int x=0;xdx;x+=4) { - int test=0-((pold[x]-pnew[x])&0x00ffffff); - ret-=(test>>31); - } - pold+=pitch*4; - pnew+=pitch*4; - } - return ret; -} - -template -INLINE int VideoCodec::CompareBlock(int vx,int vy,FrameBlock * block) { - int ret=0; - P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx; - P * pnew=((P*)newframe)+block->start;; - for (int y=0;ydy;y++) { - for (int x=0;xdx;x++) { - int test=0-((pold[x]-pnew[x])&0x00ffffff); - ret-=(test>>31); - } - pold+=pitch; - pnew+=pitch; - } - return ret; -} - -template -INLINE void VideoCodec::AddXorBlock(int vx,int vy,FrameBlock * block) { - P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx; - P * pnew=((P*)newframe)+block->start; - for (int y=0;ydy;y++) { - for (int x=0;xdx;x++) { - *((P*)&work[workUsed])=pnew[x] ^ pold[x]; - workUsed+=sizeof(P); - } - pold+=pitch; - pnew+=pitch; - } -} - -template -void VideoCodec::AddXorFrame(void) { - int written=0; - int lastvector=0; - signed char * vectors=(signed char*)&work[workUsed]; - /* Align the following xor data on 4 byte boundary*/ - workUsed=(workUsed + blockcount*2 +3) & ~3; - int totalx=0; - int totaly=0; - for (int b=0;b(0,0, block); - int possibles=64; - for (int v=0;v(vx, vy, block) < 4) { - possibles--; -// if (!possibles) Msg("Ran out of possibles, at %d of %d best %d\n",v,VectorCount,bestchange); - int testchange=CompareBlock

(vx,vy, block); - if (testchange(bestvx, bestvy, block); - } - } -} - -bool VideoCodec::SetupCompress( int _width, int _height ) { - width = _width; - height = _height; - pitch = _width + 2*MAX_VECTOR; - format = ZMBV_FORMAT_NONE; - if (deflateInit (&zstream, 4) != Z_OK) - return false; - return true; -} - -bool VideoCodec::SetupDecompress( int _width, int _height) { - width = _width; - height = _height; - pitch = _width + 2*MAX_VECTOR; - format = ZMBV_FORMAT_NONE; - if (inflateInit (&zstream) != Z_OK) - return false; - return true; -} - -bool VideoCodec::PrepareCompressFrame(int flags, zmbv_format_t _format, char * pal, void *writeBuf, int writeSize) { - int i; - unsigned char *firstByte; - - if (_format != format) { - if (!SetupBuffers( _format, 16, 16)) - return false; - flags|=1; //Force a keyframe - } - /* replace oldframe with new frame */ - unsigned char *copyFrame = newframe; - newframe = oldframe; - oldframe = copyFrame; - - compress.linesDone = 0; - compress.writeSize = writeSize; - compress.writeDone = 1; - compress.writeBuf = (unsigned char *)writeBuf; - /* Set a pointer to the first byte which will contain info about this frame */ - firstByte = compress.writeBuf; - *firstByte = 0; - //Reset the work buffer - workUsed = 0;workPos = 0; - if (flags & 1) { - /* Make a keyframe */ - *firstByte |= Mask_KeyFrame; - KeyframeHeader * header = (KeyframeHeader *)(compress.writeBuf + compress.writeDone); - header->high_version = DBZV_VERSION_HIGH; - header->low_version = DBZV_VERSION_LOW; - header->compression = COMPRESSION_ZLIB; - header->format = format; - header->blockwidth = 16; - header->blockheight = 16; - compress.writeDone += sizeof(KeyframeHeader); - /* Copy the new frame directly over */ - if (palsize) { - if (pal) - memcpy(&palette, pal, sizeof(palette)); - else - memset(&palette,0, sizeof(palette)); - /* keyframes get the full palette */ - for (i=0;i(); - break; - case ZMBV_FORMAT_15BPP: - case ZMBV_FORMAT_16BPP: - AddXorFrame(); - break; - case ZMBV_FORMAT_32BPP: - AddXorFrame(); - break; - } - } - /* Create the actual frame with compression */ - zstream.next_in = (Bytef *)work; - zstream.avail_in = workUsed; - zstream.total_in = 0; - - zstream.next_out = (Bytef *)(compress.writeBuf + compress.writeDone); - zstream.avail_out = compress.writeSize - compress.writeDone; - zstream.total_out = 0; - int res = deflate(&zstream, Z_SYNC_FLUSH); - return compress.writeDone + zstream.total_out; -} - -template -INLINE void VideoCodec::UnXorBlock(int vx,int vy,FrameBlock * block) { - P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx; - P * pnew=((P*)newframe)+block->start; - for (int y=0;ydy;y++) { - for (int x=0;xdx;x++) { - pnew[x]=pold[x]^*((P*)&work[workPos]); - workPos+=sizeof(P); - } - pold+=pitch; - pnew+=pitch; - } -} - -template -INLINE void VideoCodec::CopyBlock(int vx,int vy,FrameBlock * block) { - P * pold=((P*)oldframe)+block->start+(vy*pitch)+vx; - P * pnew=((P*)newframe)+block->start; - for (int y=0;ydy;y++) { - for (int x=0;xdx;x++) { - pnew[x]=pold[x]; - } - pold+=pitch; - pnew+=pitch; - } -} - -template -void VideoCodec::UnXorFrame(void) { - signed char * vectors=(signed char *)&work[workPos]; - workPos=(workPos + blockcount*2 + 3) & ~3; - for (int b=0;b> 1; - int vy = vectors[b*2+1] >> 1; - if (delta) UnXorBlock

(vx,vy,block); - else CopyBlock

(vx,vy,block); - } -} - -bool VideoCodec::DecompressFrame(void * framedata, int size) { - unsigned char *data=(unsigned char *)framedata; - unsigned char tag;int i; - - tag = *data++; - if (--size<=0) - return false; - if (tag & Mask_KeyFrame) { - KeyframeHeader * header = (KeyframeHeader *)data; - size -= sizeof(KeyframeHeader);data += sizeof(KeyframeHeader); - if (size<=0) - return false; - if (header->low_version != DBZV_VERSION_LOW || header->high_version != DBZV_VERSION_HIGH) - return false; - if (format != (zmbv_format_t)header->format && !SetupBuffers((zmbv_format_t)header->format, header->blockwidth, header->blockheight)) - return false; - inflateReset(&zstream); - } - zstream.next_in = (Bytef *)data; - zstream.avail_in = size; - zstream.total_in = 0; - - zstream.next_out = (Bytef *)work; - zstream.avail_out = bufsize; - zstream.total_out = 0; - int res = inflate(&zstream, Z_FINISH); - workUsed= zstream.total_out; - workPos = 0; - if (tag & Mask_KeyFrame) { - if (palsize) { - for (i=0;i(); - break; - case ZMBV_FORMAT_15BPP: - case ZMBV_FORMAT_16BPP: - UnXorFrame(); - break; - case ZMBV_FORMAT_32BPP: - UnXorFrame(); - break; - } - } - return true; -} - -void VideoCodec::Output_UpsideDown_24(void *output) { - int i; - unsigned char *r; - unsigned char *w = (unsigned char *)output; - int pad = width & 3; - - for (i=height-1;i>=0;i--) { - r = newframe + pixelsize*(MAX_VECTOR+(i+MAX_VECTOR)*pitch); - switch (format) { - case ZMBV_FORMAT_8BPP: - for (int j=0;j> 2); - *w++ = (unsigned char)(((c & 0x03e0) * 0x21) >> 7); - *w++ = (unsigned char)(((c & 0x7c00) * 0x21) >> 12); - } - break; - case ZMBV_FORMAT_16BPP: - for (int j=0;j> 2); - *w++ = (unsigned char)(((c & 0x07e0) * 0x41) >> 9); - *w++ = (unsigned char)(((c & 0xf800) * 0x21) >> 13); - } - break; - case ZMBV_FORMAT_32BPP: - for (int j=0;j - void AddXorFrame(void); - template - void UnXorFrame(void); - template - INLINE int PossibleBlock(int vx,int vy,FrameBlock * block); - template - INLINE int CompareBlock(int vx,int vy,FrameBlock * block); - template - INLINE void AddXorBlock(int vx,int vy,FrameBlock * block); - template - INLINE void UnXorBlock(int vx,int vy,FrameBlock * block); - template - INLINE void CopyBlock(int vx, int vy,FrameBlock * block); -public: - VideoCodec(); - bool SetupCompress( int _width, int _height); - bool SetupDecompress( int _width, int _height); - zmbv_format_t BPPFormat( int bpp ); - int NeededSize( int _width, int _height, zmbv_format_t _format); - - void CompressLines(int lineCount, void *lineData[]); - bool PrepareCompressFrame(int flags, zmbv_format_t _format, char * pal, void *writeBuf, int writeSize); - int FinishCompressFrame( void ); - bool DecompressFrame(void * framedata, int size); - void Output_UpsideDown_24(void * output); -}; diff --git a/src/libs/zmbv/zmbv.inf b/src/libs/zmbv/zmbv.inf deleted file mode 100644 index 2ab3ea2..0000000 --- a/src/libs/zmbv/zmbv.inf +++ /dev/null @@ -1,105 +0,0 @@ -[Version] -Signature="$CHICAGO$" -Provider=%ZMBV_PUBLISHER% -Class=MEDIA - - -[DefaultInstall] -CopyFiles=ZMBV.Files.Inf,ZMBV.Files.Dll -AddReg=ZMBV.Reg9x -UpdateInis=ZMBV.INIs - -[DefaultInstall.ntx86] -CopyFiles=ZMBV.Files.Inf,ZMBV.Files.Dll -AddReg=ZMBV.RegNTx86 -UpdateInis=ZMBV.INIs - -[DefaultInstall.ntamd64] -CopyFiles=ZMBV.Files.Inf,ZMBV.Files.Dll.NTamd64 -AddReg=ZMBV.RegNTamd64 -UpdateInis=ZMBV.INIs - -[DefaultUnInstall] -DelFiles=ZMBV.Files.Dll,ZMBV.Files.Inf,ZMBV.Files.Ini -DelReg=ZMBV.Reg9x -UpdateInis=ZMBV.INIs.Del - -[DefaultUnInstall.ntx86] -DelFiles=ZMBV.Files.Dll,ZMBV.Files.Inf,ZMBV.Files.Ini -DelReg=ZMBV.RegNTx86 -UpdateInis=ZMBV.INIs.Del - -[DefaultUnInstall.ntamd64] -DelFiles=ZMBV.Files.Dll.NTamd64,ZMBV.Files.Inf,ZMBV.Files.Ini -DelReg=ZMBV.RegNTamd64 -UpdateInis=ZMBV.INIs.Del - -[SourceDisksNames] -1="Zip Motion Block Video codec","",1 - -[SourceDisksFiles] -ZMBV.INF=1 - -[DestinationDirs] -ZMBV.Files.Inf=17 -ZMBV.Files.Dll=11 -ZMBV.Files.Dll.NTamd64=10,SysWOW64 -ZMBV.Files.Ini=25 - -[ZMBV.Files.Inf] -zmbv.inf - -[ZMBV.Files.Dll] -zmbv.dll - -[ZMBV.Files.Dll.NTamd64] -zmbv.dll - -[ZMBV.Files.Ini] -zmbv.ini - -[ZMBV.Reg9x] -HKLM,SYSTEM\CurrentControlSet\Control\MediaResources\icm\VIDC.ZMBV,Description,,"%ZMBV_DISPLAY_NAME%" -HKLM,SYSTEM\CurrentControlSet\Control\MediaResources\icm\VIDC.ZMBV,Driver,,"zmbv.dll" -HKLM,SYSTEM\CurrentControlSet\Control\MediaResources\icm\VIDC.ZMBV,FriendlyName,,"%ZMBV_DISPLAY_NAME%" - -HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV -HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,DisplayName,,"%ZMBV_UNINST_DISPLAY_NAME%" -HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,UninstallString,,"rundll.exe setupx.dll,InstallHinfSection DefaultUninstall 132 %17%\ZMBV.INF" - -[ZMBV.RegNTx86] -HKLM,SOFTWARE\Microsoft\Windows NT\CurrentVersion\drivers.desc,zmbv.dll,,"%ZMBV_DISPLAY_NAME%" -HKLM,SOFTWARE\Microsoft\Windows NT\CurrentVersion\drivers32,vidc.zmbv,,zmbv.dll - -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,DisplayName,,"%ZMBV_UNINST_DISPLAY_NAME%" -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,Publisher,,"%ZMBV_PUBLISHER%" -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,URLInfoAbout,,"%ZMBV_URL_HOMEPAGE%" -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,NoRepair,0x10001,01,00,00,00 -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,NoModify,0x10001,01,00,00,00 -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,UninstallString,,"rundll32.exe setupapi,InstallHinfSection DefaultUninstall 132 %17%\ZMBV.INF" - -[ZMBV.RegNTamd64] -HKLM,SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\drivers.desc,zmbv.dll,,"%ZMBV_DISPLAY_NAME%" -HKLM,SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\drivers32,vidc.zmbv,,zmbv.dll - -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,DisplayName,,"%ZMBV_UNINST_DISPLAY_NAME%" -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,Publisher,,"%ZMBV_PUBLISHER%" -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,URLInfoAbout,,"%ZMBV_URL_HOMEPAGE%" -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,NoRepair,0x10001,01,00,00,00 -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,NoModify,0x10001,01,00,00,00 -HKLM,SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ZMBV,UninstallString,,"rundll32.exe setupapi.dll,InstallHinfSection DefaultUninstall 132 %17%\ZMBV.INF" - -[ZMBV.INIs] -system.ini, drivers32,, "VIDC.ZMBV=zmbv.dll" - -[ZMBV.INIs.Del] -system.ini, drivers32, "VIDC.ZMBV=zmbv.dll" - -[Strings] -ZMBV_PUBLISHER = "DOSBox Team" -ZMBV_DISPLAY_NAME = "Zip Motion Block Video [ZMBV]" -ZMBV_UNINST_DISPLAY_NAME = "Zip Motion Block Video codec (Remove Only)" -ZMBV_URL_HOMEPAGE = "http://www.dosbox.com/" -CODEC_INSTALLATION_FINISHED = "Zip Motion Block Video codec installation is complete." diff --git a/src/libs/zmbv/zmbv.sln b/src/libs/zmbv/zmbv.sln deleted file mode 100644 index 07c961a..0000000 --- a/src/libs/zmbv/zmbv.sln +++ /dev/null @@ -1,21 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zmbv", "zmbv.vcproj", "{619CF3F9-C373-4BD5-93DA-025F5E16F8FA}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {619CF3F9-C373-4BD5-93DA-025F5E16F8FA}.Debug.ActiveCfg = Debug|Win32 - {619CF3F9-C373-4BD5-93DA-025F5E16F8FA}.Debug.Build.0 = Debug|Win32 - {619CF3F9-C373-4BD5-93DA-025F5E16F8FA}.Release.ActiveCfg = Release|Win32 - {619CF3F9-C373-4BD5-93DA-025F5E16F8FA}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/src/libs/zmbv/zmbv.vcproj b/src/libs/zmbv/zmbv.vcproj deleted file mode 100644 index eecc333..0000000 --- a/src/libs/zmbv/zmbv.vcproj +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/libs/zmbv/zmbv_vfw.cpp b/src/libs/zmbv/zmbv_vfw.cpp deleted file mode 100644 index 10798a4..0000000 --- a/src/libs/zmbv/zmbv_vfw.cpp +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -// -// Zipped Motion Block Video -// -// Based on Huffyuv by Ben Rudiak-Gould. -// which was based on MSYUV sample code, which is: -// Copyright (c) 1993 Microsoft Corporation. -// All Rights Reserved. -// - -#include "zmbv_vfw.h" -#include "resource.h" - -#include -#include - -TCHAR szDescription[] = TEXT("Zipped Motion Block Video v0.1"); -TCHAR szName[] = TEXT(CODEC_4CC); - -#define VERSION 0x00000001 // 0.1 - -/******************************************************************** -********************************************************************/ - -CodecInst *encode_table_owner, *decode_table_owner; - -/******************************************************************** -********************************************************************/ - -void Msg(const char fmt[], ...) { - DWORD written; - char buf[2000]; - va_list val; - - va_start(val, fmt); - wvsprintf(buf, fmt, val); - - const COORD _80x50 = {80,50}; - static BOOL startup = (AllocConsole(), SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), _80x50)); - WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), buf, lstrlen(buf), &written, 0); -} - - -/******************************************************************** -********************************************************************/ - -CodecInst::CodecInst() { - codec = 0; -} - -CodecInst* Open(ICOPEN* icinfo) { - if (icinfo && icinfo->fccType != ICTYPE_VIDEO) - return NULL; - - CodecInst* pinst = new CodecInst(); - - if (icinfo) icinfo->dwError = pinst ? ICERR_OK : ICERR_MEMORY; - - return pinst; -} - -DWORD Close(CodecInst* pinst) { -// delete pinst; // this caused problems when deleting at app close time - return 1; -} - -/******************************************************************** -********************************************************************/ - - -/******************************************************************** -********************************************************************/ - -BOOL CodecInst::QueryAbout() { return TRUE; } - -static BOOL CALLBACK AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - if (uMsg == WM_COMMAND) { - switch (LOWORD(wParam)) { - case IDOK: - EndDialog(hwndDlg, 0); - break; - case IDC_HOMEPAGE: - ShellExecute(NULL, NULL, "http://www.dosbox.com", NULL, NULL, SW_SHOW); - break; - case IDC_EMAIL: - ShellExecute(NULL, NULL, "mailto:dosbox.crew@gmail.com", NULL, NULL, SW_SHOW); - break; - } - } - return FALSE; -} -DWORD CodecInst::About(HWND hwnd) { - DialogBox(hmoduleCodec, MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDialogProc); - return ICERR_OK; -} - -static BOOL CALLBACK ConfigureDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - - if (uMsg == WM_INITDIALOG) { - - } else if (uMsg == WM_COMMAND) { - - switch (LOWORD(wParam)) { - - case IDOK: - - case IDCANCEL: - EndDialog(hwndDlg, 0); - break; - - default: - return AboutDialogProc(hwndDlg, uMsg, wParam, lParam); // handle email and home-page buttons - } - } - return FALSE; -} - -BOOL CodecInst::QueryConfigure() { return TRUE; } - -DWORD CodecInst::Configure(HWND hwnd) { - DialogBox(hmoduleCodec, MAKEINTRESOURCE(IDD_CONFIGURE), hwnd, ConfigureDialogProc); - return ICERR_OK; -} - - -/******************************************************************** -********************************************************************/ - - -// we have no state information which needs to be stored - -DWORD CodecInst::GetState(LPVOID pv, DWORD dwSize) { return 0; } - -DWORD CodecInst::SetState(LPVOID pv, DWORD dwSize) { return 0; } - - -DWORD CodecInst::GetInfo(ICINFO* icinfo, DWORD dwSize) { - if (icinfo == NULL) - return sizeof(ICINFO); - - if (dwSize < sizeof(ICINFO)) - return 0; - - icinfo->dwSize = sizeof(ICINFO); - icinfo->fccType = ICTYPE_VIDEO; - memcpy(&icinfo->fccHandler,CODEC_4CC, 4); - icinfo->dwFlags = VIDCF_FASTTEMPORALC | VIDCF_FASTTEMPORALD | VIDCF_TEMPORAL; - - icinfo->dwVersion = VERSION; - icinfo->dwVersionICM = ICVERSION; - MultiByteToWideChar(CP_ACP, 0, szDescription, -1, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, szName, -1, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR)); - - return sizeof(ICINFO); -} - -/******************************************************************** -****************************************************************/ - -static int GetInputBitDepth(const BITMAPINFOHEADER *lpbiIn) { - if (lpbiIn->biCompression == BI_RGB) { - if (lpbiIn->biPlanes != 1) - return -1; - - switch(lpbiIn->biBitCount) { - case 8: - return 8; - case 16: - return 15; // Standard Windows 16-bit RGB is 1555. - case 32: - return 32; - } - - } else if (lpbiIn->biCompression == BI_BITFIELDS) { - // BI_BITFIELDS RGB masks lie right after the BITMAPINFOHEADER structure, - // at (ptr+40). This is true even for a BITMAPV4HEADER or BITMAPV5HEADER. - const DWORD *masks = (const DWORD *)(lpbiIn + 1); - - if (lpbiIn->biBitCount == 16) { - // Test for 16 (555) - if (masks[0] == 0x7C00 && masks[1] == 0x03E0 && masks[2] == 0x001F) - return 15; - - // Test for 16 (565) - if (masks[0] == 0xF800 && masks[1] == 0x07E0 && masks[2] == 0x001F) - return 16; - } else if (lpbiIn->biBitCount == 32) { - if (masks[0] == 0xFF0000 && masks[1] == 0x00FF00 && masks[2] == 0x0000FF) - return 32; - } - } - - return -1; -} - -static bool CanCompress(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut, bool requireOutput) { - if (lpbiIn) { - if (GetInputBitDepth(lpbiIn) < 0) - return false; - } else return false; - if (lpbiOut) { - if (memcmp(&lpbiOut->biCompression,CODEC_4CC, 4)) - return false; - } else return !requireOutput; - return true; -} - -/******************************************************************** -****************************************************************/ - -DWORD CodecInst::CompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { - if (CanCompress(lpbiIn,lpbiOut,false)) return ICERR_OK; - return ICERR_BADFORMAT; -} - -DWORD CodecInst::CompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { - if (!lpbiOut) - return sizeof(BITMAPINFOHEADER); - lpbiOut->biSize = sizeof(BITMAPINFOHEADER); - lpbiOut->biWidth = lpbiIn->biWidth; - lpbiOut->biHeight = lpbiIn->biHeight; - lpbiOut->biPlanes = 1; - lpbiOut->biCompression = *(const DWORD *)CODEC_4CC; - lpbiOut->biBitCount = lpbiIn->biBitCount; - lpbiOut->biSizeImage = lpbiIn->biWidth * lpbiIn->biHeight * lpbiIn->biBitCount/8 + 1024; - lpbiOut->biXPelsPerMeter = lpbiIn->biXPelsPerMeter; - lpbiOut->biYPelsPerMeter = lpbiIn->biYPelsPerMeter; - lpbiOut->biClrUsed = 0; - lpbiOut->biClrImportant = 0; - return ICERR_OK; -} - -DWORD CodecInst::CompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { - CompressEnd(); // free resources if necessary - if (!CanCompress(lpbiIn, lpbiOut, true)) - return ICERR_BADFORMAT; - codec = new VideoCodec(); - if (!codec) - return ICERR_MEMORY; - if (!codec->SetupCompress( lpbiIn->biWidth, lpbiIn->biHeight)) - return ICERR_MEMORY; - return ICERR_OK; -} - -DWORD CodecInst::CompressGetSize(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { - if (!CanCompress(lpbiIn, lpbiOut, true)) - return ICERR_BADFORMAT; - return lpbiIn->biWidth * lpbiIn->biHeight * lpbiIn->biBitCount/8 + 1024; -} - -DWORD CodecInst::Compress(ICCOMPRESS* icinfo, DWORD dwSize) { - int i, pitch; - zmbv_format_t format; - LPBITMAPINFOHEADER lpbiIn=icinfo->lpbiInput; - LPBITMAPINFOHEADER lpbiOut=icinfo->lpbiOutput; - if (!CanCompress(lpbiIn, lpbiOut, true)) - return ICERR_BADFORMAT; - if (!icinfo->lpInput || !icinfo->lpOutput) - return ICERR_ABORT; - switch (GetInputBitDepth(lpbiIn)) { - case 8: - format = ZMBV_FORMAT_8BPP; - pitch = lpbiIn->biWidth; - break; - case 15: - format = ZMBV_FORMAT_15BPP; - pitch = lpbiIn->biWidth * 2; - break; - case 16: - format = ZMBV_FORMAT_16BPP; - pitch = lpbiIn->biWidth * 2; - break; - case 32: - format = ZMBV_FORMAT_32BPP; - pitch = lpbiIn->biWidth * 4; - break; - } - - // DIB scanlines for RGB formats are always aligned to DWORD. - pitch = (pitch + 3) & ~3; - - // force a key frame if requested by the client - int flags = 0; - if (icinfo->dwFlags & ICCOMPRESS_KEYFRAME) - flags |= 1; - - codec->PrepareCompressFrame( flags, format, 0, icinfo->lpOutput, 99999999); - char *readPt = (char *)icinfo->lpInput + pitch*(lpbiIn->biHeight - 1); - for(i = 0;ibiHeight;i++) { - codec->CompressLines(1, (void **)&readPt ); - readPt -= pitch; - } - lpbiOut->biSizeImage = codec->FinishCompressFrame(); - - if (flags & 1) - *icinfo->lpdwFlags = AVIIF_KEYFRAME; - else - *icinfo->lpdwFlags = 0; - - return ICERR_OK; -} - - -DWORD CodecInst::CompressEnd() { - if (codec) - delete codec; - codec = 0; - return ICERR_OK; -} - -/******************************************************************** -********************************************************************/ - -static bool CanDecompress(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { - if (memcmp(&lpbiIn->biCompression,CODEC_4CC,4)) - return false; - if (lpbiOut) { - if (lpbiOut->biCompression!=0) return false; - if (lpbiOut->biBitCount != 24) return false; - if (lpbiIn->biWidth!=lpbiOut->biWidth || lpbiIn->biHeight!=lpbiOut->biHeight) - return false; - } - return true; -} - -/******************************************************************** -********************************************************************/ - - -DWORD CodecInst::DecompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { - return CanDecompress(lpbiIn, lpbiOut) ? ICERR_OK : ICERR_BADFORMAT; -} - -DWORD CodecInst::DecompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { - if (memcmp(&lpbiIn->biCompression,CODEC_4CC,4)) - return ICERR_BADFORMAT; - if (!lpbiOut) return sizeof(BITMAPINFOHEADER); - *lpbiOut = *lpbiIn; - lpbiOut->biPlanes = 1; - lpbiOut->biSize = sizeof(BITMAPINFOHEADER); - lpbiOut->biBitCount = 24; - lpbiOut->biSizeImage = ((lpbiOut->biWidth*3 + 3) & ~3) * lpbiOut->biHeight; - lpbiOut->biCompression = BI_RGB; - lpbiOut->biClrUsed = 0; - lpbiOut->biClrImportant = 0; - return ICERR_OK; -} - -DWORD CodecInst::DecompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { - DecompressEnd(); // free resources if necessary - if (!CanDecompress(lpbiIn, lpbiOut)) - return ICERR_BADFORMAT; - codec=new VideoCodec(); - if (!codec) - return ICERR_MEMORY; - if (!codec->SetupDecompress( lpbiIn->biWidth, lpbiIn->biHeight)) - return ICERR_MEMORY; - return ICERR_OK; -} - -DWORD CodecInst::Decompress(ICDECOMPRESS* icinfo, DWORD dwSize) { - if (!codec || !icinfo) - return ICERR_ABORT; - if (codec->DecompressFrame( icinfo->lpInput, icinfo->lpbiInput->biSizeImage)) { - codec->Output_UpsideDown_24(icinfo->lpOutput); - } else return ICERR_DONTDRAW; - return ICERR_OK; -} - - -// palette-mapped output only -DWORD CodecInst::DecompressGetPalette(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) { - return ICERR_BADFORMAT; -} - -DWORD CodecInst::DecompressEnd() { - if (codec) - delete codec; - codec = 0; - return ICERR_OK; -} diff --git a/src/libs/zmbv/zmbv_vfw.h b/src/libs/zmbv/zmbv_vfw.h deleted file mode 100644 index 02688b9..0000000 --- a/src/libs/zmbv/zmbv_vfw.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// Huffyuv v2.1.1, by Ben Rudiak-Gould. -// http://www.math.berkeley.edu/~benrg/huffyuv.html -// -// This file is copyright 2000 Ben Rudiak-Gould, and distributed under -// the terms of the GNU General Public License, v2 or later. See -// http://www.gnu.org/copyleft/gpl.html. -// -// I edit these files in 10-point Verdana, a proportionally-spaced font. -// You may notice formatting oddities if you use a monospaced font. -// - - -#include -#include -#include -#include "zmbv.h" -#pragma hdrstop - -extern HMODULE hmoduleCodec; - - -// huffyuv.cpp - -class CodecInst { -private: - VideoCodec * codec; -public: - CodecInst(); - ~CodecInst(); - - BOOL QueryAbout(); - DWORD About(HWND hwnd); - - BOOL QueryConfigure(); - DWORD Configure(HWND hwnd); - - DWORD GetState(LPVOID pv, DWORD dwSize); - DWORD SetState(LPVOID pv, DWORD dwSize); - - DWORD GetInfo(ICINFO* icinfo, DWORD dwSize); - - DWORD CompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut); - DWORD CompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut); - DWORD CompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut); - DWORD CompressGetSize(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut); - DWORD Compress(ICCOMPRESS* icinfo, DWORD dwSize); - DWORD CompressEnd(); - - DWORD DecompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut); - DWORD DecompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut); - DWORD DecompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut); - - DWORD Decompress(ICDECOMPRESS* icinfo, DWORD dwSize); - DWORD DecompressGetPalette(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut); - DWORD DecompressEnd(); -}; - -CodecInst* Open(ICOPEN* icinfo); -DWORD Close(CodecInst* pinst); - diff --git a/src/libs/zmbv/zmbv_vfw.rc b/src/libs/zmbv/zmbv_vfw.rc deleted file mode 100644 index 4d670d5..0000000 --- a/src/libs/zmbv/zmbv_vfw.rc +++ /dev/null @@ -1,123 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_ABOUT DIALOGEX 0, 0, 167, 55 -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "DOSBox Video Codec v0.1" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,131,34,29,14 - CTEXT "Zipped Motion Block Video v 0.1\nCopyright 2009, DOSBox Team", - IDC_STATIC,7,7,153,25,SS_NOPREFIX - PUSHBUTTON "Email author",IDC_EMAIL,7,34,50,14 - PUSHBUTTON "Visit home page",IDC_HOMEPAGE,59,34,58,14 -END - -IDD_CONFIGURE DIALOGEX 0, 0, 213, 146 -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "ZMBV configuration dialog" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - PUSHBUTTON "Email author",IDC_EMAIL,44,86,50,14 - PUSHBUTTON "Visit home page",IDC_HOMEPAGE,109,87,58,14 - DEFPUSHBUTTON "OK",IDOK,44,125,50,14 - PUSHBUTTON "Cancel",IDCANCEL,117,125,50,14 - CONTROL "",IDC_SLIDER1,"msctls_trackbar32",TBS_BOTH | - TBS_NOTICKS | WS_TABSTOP,57,30,92,18 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_ABOUT, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 160 - TOPMARGIN, 7 - BOTTOMMARGIN, 48 - END - - IDD_CONFIGURE, DIALOG - BEGIN - LEFTMARGIN, 44 - RIGHTMARGIN, 167 - TOPMARGIN, 6 - BOTTOMMARGIN, 139 - END -END -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/src/misc/Makefile.am b/src/misc/Makefile.am index d359b77..3d9eff2 100644 --- a/src/misc/Makefile.am +++ b/src/misc/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include - -noinst_LIBRARIES = libmisc.a -libmisc_a_SOURCES = cross.cpp messages.cpp programs.cpp setup.cpp support.cpp +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libmisc.a +libmisc_a_SOURCES = plugins.cpp programs.cpp messages.cpp support.cpp setup.cpp diff --git a/src/misc/Makefile.in b/src/misc/Makefile.in new file mode 100644 index 0000000..46f958a --- /dev/null +++ b/src/misc/Makefile.in @@ -0,0 +1,309 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libmisc.a +libmisc_a_SOURCES = plugins.cpp programs.cpp messages.cpp support.cpp setup.cpp +subdir = src/misc +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libmisc_a_AR = $(AR) cru +libmisc_a_LIBADD = +am_libmisc_a_OBJECTS = plugins.$(OBJEXT) programs.$(OBJEXT) \ + messages.$(OBJEXT) support.$(OBJEXT) setup.$(OBJEXT) +libmisc_a_OBJECTS = $(am_libmisc_a_OBJECTS) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/messages.Po ./$(DEPDIR)/plugins.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/programs.Po ./$(DEPDIR)/setup.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/support.Po +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +CXXFLAGS = @CXXFLAGS@ +DIST_SOURCES = $(libmisc_a_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libmisc_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/misc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +AR = ar + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libmisc.a: $(libmisc_a_OBJECTS) $(libmisc_a_DEPENDENCIES) + -rm -f libmisc.a + $(libmisc_a_AR) libmisc.a $(libmisc_a_OBJECTS) $(libmisc_a_LIBADD) + $(RANLIB) libmisc.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messages.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugins.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/programs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/support.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `cygpath -w $<` +CXXDEPMODE = @CXXDEPMODE@ +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic tags uninstall uninstall-am \ + uninstall-info-am + +# 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/misc/cross.cpp b/src/misc/cross.cpp deleted file mode 100644 index 1f4d085..0000000 --- a/src/misc/cross.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: cross.cpp,v 1.5 2009/03/14 18:02:34 qbix79 Exp $ */ - -#include "dosbox.h" -#include "cross.h" -#include "support.h" -#include -#include - -#ifdef WIN32 -#ifndef _WIN32_IE -#define _WIN32_IE 0x0400 -#endif -#include -#endif - -#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H -#include -#include -#endif - - -void Cross::GetPlatformConfigDir(std::string& in) { -#ifdef WIN32 - char result[MAX_PATH] = { 0 }; - SHGetSpecialFolderPath(NULL,result,CSIDL_LOCAL_APPDATA,0); - in = result; - in += "\\DOSBox"; -#elif defined(MACOSX) - in = "~/Library/Preferences"; - ResolveHomedir(in); -#else - in = "~/.dosbox"; - ResolveHomedir(in); -#endif - in += CROSS_FILESPLIT; -} - -void Cross::GetPlatformConfigName(std::string& in) { -#ifdef WIN32 -#define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf" -#elif defined(MACOSX) -#define DEFAULT_CONFIG_FILE "DOSBox " VERSION " Preferences" -#else /*linux freebsd*/ -#define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf" -#endif - in = DEFAULT_CONFIG_FILE; -} - -void Cross::CreatePlatformConfigDir(std::string& in) { -#ifdef WIN32 - char result[MAX_PATH] = { 0 }; - SHGetSpecialFolderPath(NULL,result,CSIDL_LOCAL_APPDATA,1); //1 at end is create - in = result; - in += "\\DOSBox"; - mkdir(in.c_str()); -#elif defined(MACOSX) - in = "~/Library/Preferences/"; - ResolveHomedir(in); - //Don't create it. Assume it exists -#else - in = "~/.dosbox"; - ResolveHomedir(in); - mkdir(in.c_str(),0700); -#endif - in += CROSS_FILESPLIT; -} - -void Cross::ResolveHomedir(std::string & temp_line) { - if(!temp_line.size() || temp_line[0] != '~') return; //No ~ - - if(temp_line.size() == 1 || temp_line[1] == CROSS_FILESPLIT) { //The ~ and ~/ variant - char * home = getenv("HOME"); - if(home) temp_line.replace(0,1,std::string(home)); -#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H - } else { // The ~username variant - std::string::size_type namelen = temp_line.find(CROSS_FILESPLIT); - if(namelen == std::string::npos) namelen = temp_line.size(); - std::string username = temp_line.substr(1,namelen - 1); - struct passwd* pass = getpwnam(username.c_str()); - if(pass) temp_line.replace(0,namelen,pass->pw_dir); //namelen -1 +1(for the ~) -#endif // USERNAME lookup code - } -} - -void Cross::CreateDir(std::string const& in) { -#ifdef WIN32 - mkdir(in.c_str()); -#else - mkdir(in.c_str(),0700); -#endif -} - -#if defined (WIN32) - -dir_information* open_directory(const char* dirname) { - if (dirname == NULL) return NULL; - - size_t len = strlen(dirname); - if (len == 0) return NULL; - - static dir_information dir; - - safe_strncpy(dir.base_path,dirname,MAX_PATH); - - if (dirname[len-1]=='\\') strcat(dir.base_path,"*.*"); - else strcat(dir.base_path,"\\*.*"); - - dir.handle = INVALID_HANDLE_VALUE; - - return (access(dirname,0) ? NULL : &dir); -} - -bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) { - dirp->handle = FindFirstFile(dirp->base_path, &dirp->search_data); - if (INVALID_HANDLE_VALUE == dirp->handle) { - return false; - } - - safe_strncpy(entry_name,dirp->search_data.cFileName,(MAX_PATHsearch_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true; - else is_directory = false; - - return true; -} - -bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) { - int result = FindNextFile(dirp->handle, &dirp->search_data); - if (result==0) return false; - - safe_strncpy(entry_name,dirp->search_data.cFileName,(MAX_PATHsearch_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true; - else is_directory = false; - - return true; -} - -void close_directory(dir_information* dirp) { - if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose(dirp->handle); - dirp->handle = INVALID_HANDLE_VALUE; - } -} - -#else - -dir_information* open_directory(const char* dirname) { - static dir_information dir; - dir.dir=opendir(dirname); - safe_strncpy(dir.base_path,dirname,CROSS_LEN); - return dir.dir?&dir:NULL; -} - -bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) { - struct dirent* dentry = readdir(dirp->dir); - if (dentry==NULL) { - return false; - } - -// safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAXd_name,CROSS_LEN); - -#ifdef DIRENT_HAS_D_TYPE - if(dentry->d_type == DT_DIR) { - is_directory = true; - return true; - } else if(dentry->d_type == DT_REG) { - is_directory = false; - return true; - } -#endif - - // probably use d_type here instead of a full stat() - static char buffer[2*CROSS_LEN] = { 0 }; - buffer[0] = 0; - strcpy(buffer,dirp->base_path); - strcat(buffer,entry_name); - struct stat status; - if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0); - else is_directory = false; - - return true; -} - -bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) { - struct dirent* dentry = readdir(dirp->dir); - if (dentry==NULL) { - return false; - } - -// safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAXd_name,CROSS_LEN); - -#ifdef DIRENT_HAS_D_TYPE - if(dentry->d_type == DT_DIR) { - is_directory = true; - return true; - } else if(dentry->d_type == DT_REG) { - is_directory = false; - return true; - } -#endif - - // probably use d_type here instead of a full stat() - static char buffer[2*CROSS_LEN] = { 0 }; - buffer[0] = 0; - strcpy(buffer,dirp->base_path); - strcat(buffer,entry_name); - struct stat status; - - if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0); - else is_directory = false; - - return true; -} - -void close_directory(dir_information* dirp) { - closedir(dirp->dir); -} - -#endif diff --git a/src/misc/messages.cpp b/src/misc/messages.cpp index f46ab49..b07a11a 100644 --- a/src/misc/messages.cpp +++ b/src/misc/messages.cpp @@ -1,141 +1,107 @@ -/* - * Copyright (C) 2002-2007 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: messages.cpp,v 1.21 2009/02/01 14:18:12 qbix79 Exp $ */ - -#include -#include -#include -#include "dosbox.h" -#include "cross.h" -#include "support.h" -#include "setup.h" -#include "control.h" -#include -#include -using namespace std; - - - -#define LINE_IN_MAXLEN 2048 - -struct MessageBlock { - string name; - string val; - MessageBlock(const char* _name, const char* _val): - name(_name),val(_val){} -}; - -static list Lang; -typedef list::iterator itmb; - -void MSG_Add(const char * _name, const char* _val) { - /* Find the message */ - for(itmb tel=Lang.begin();tel!=Lang.end();tel++) { - if((*tel).name==_name) { -// LOG_MSG("double entry for %s",_name); //Message file might be loaded before default text messages - return; - } - } - /* if the message doesn't exist add it */ - Lang.push_back(MessageBlock(_name,_val)); -} - -void MSG_Replace(const char * _name, const char* _val) { - /* Find the message */ - for(itmb tel=Lang.begin();tel!=Lang.end();tel++) { - if((*tel).name==_name) { - Lang.erase(tel); - break; - } - } - /* Even if the message doesn't exist add it */ - Lang.push_back(MessageBlock(_name,_val)); -} - -static void LoadMessageFile(const char * fname) { - if (!fname) return; - if(*fname=='\0') return;//empty string=no languagefile - FILE * mfile=fopen(fname,"rt"); - /* This should never happen and since other modules depend on this use a normal printf */ - if (!mfile) { - E_Exit("MSG:Can't load messages: %s",fname); - } - char linein[LINE_IN_MAXLEN]; - char name[LINE_IN_MAXLEN]; - char string[LINE_IN_MAXLEN*10]; - /* Start out with empty strings */ - name[0]=0;string[0]=0; - while(fgets(linein, LINE_IN_MAXLEN, mfile)!=0) { - /* Parse the read line */ - /* First remove characters 10 and 13 from the line */ - char * parser=linein; - char * writer=linein; - while (*parser) { - if (*parser!=10 && *parser!=13) { - *writer++=*parser; - } - *parser++; - } - *writer=0; - /* New string name */ - if (linein[0]==':') { - string[0]=0; - strcpy(name,linein+1); - /* End of string marker */ - } else if (linein[0]=='.') { - /* Replace/Add the string to the internal langaugefile */ - MSG_Replace(name,string); - } else { - /* Normal string to be added */ - strcat(string,linein); - strcat(string,"\n"); - } - } - fclose(mfile); -} - -const char * MSG_Get(char const * msg) { - for(itmb tel=Lang.begin();tel!=Lang.end();tel++){ - if((*tel).name==msg) - { - return (*tel).val.c_str(); - } - } - return "Message not Found!\n"; -} - - -void MSG_Write(const char * location) { - FILE* out=fopen(location,"w+t"); - if(out==NULL) return;//maybe an error? - for(itmb tel=Lang.begin();tel!=Lang.end();tel++){ - fprintf(out,":%s\n%s.\n",(*tel).name.c_str(),(*tel).val.c_str()); - } - fclose(out); -} - -void MSG_Init(Section_prop * section) { - std::string file_name; - if (control->cmdline->FindString("-lang",file_name,true)) { - LoadMessageFile(file_name.c_str()); - } else { - Prop_path* pathprop = section->Get_path("language"); - if(pathprop) LoadMessageFile(pathprop->realpath.c_str()); - } -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include "dosbox.h" +#include "cross.h" +#include "support.h" +#include "setup.h" + + + +#define LINE_IN_MAXLEN 1024 + +struct MessageBlock +{ + char * name; + char * string; + MessageBlock * next; +}; + +static MessageBlock * first_message; + + +static void LoadMessageFile(char * fname) { + FILE * mfile=fopen(fname,"rb"); +/* This should never happen and since other modules depend on this use a normal printf */ + if (!mfile) { + E_Exit("MSG:Can't load messages",fname); + } + char linein[LINE_IN_MAXLEN]; + char name[LINE_IN_MAXLEN]; + char string[LINE_IN_MAXLEN*10]; + /* Start out with empty strings */ + name[0]=0;string[0]=0; + while(fgets(linein, LINE_IN_MAXLEN, mfile)!=0) { + /* Parse the read line */ + /* First remove characters 10 and 13 from the line */ + char * parser=linein; + char * writer=linein; + while (*parser) { + if (*parser!=10 && *parser!=13) { + *writer++=*parser; + } + *parser++; + } + *writer=0; + /* New string name */ + if (linein[0]==':') { + string[0]=0; + strcpy(name,linein+1); + /* End of string marker */ + } else if (linein[0]=='.') { + /* Save the string internally */ + size_t total=sizeof(MessageBlock)+strlen(name)+1+strlen(string)+1; + MessageBlock * newblock=(MessageBlock *)malloc(total); + newblock->name=((char *)newblock)+sizeof(MessageBlock); + newblock->string=newblock->name+strlen(name)+1; + strcpy(newblock->name,name); + strcpy(newblock->string,string); + newblock->next=first_message; + first_message=newblock; + } else { + /* Normal string to be added */ + strcat(string,linein); + strcat(string,"\n"); + } + } + fclose(mfile); +} + + +char * MSG_Get(char * msg) { + MessageBlock * index=first_message; + while (index) { + if (!strcmp(msg,index->name)) return index->string; + index=index->next; + } + return "Message not found"; +} + + + +void MSG_Init(void) { + /* Load the messages from "dosbox.lang file" */ + first_message=0; + char filein[CROSS_LEN]; + strcpy(filein,dosbox_basedir); + strcat(filein,"dosbox.lang"); + LoadMessageFile(filein); +} diff --git a/src/misc/plugins.cpp b/src/misc/plugins.cpp new file mode 100644 index 0000000..35cfe94 --- /dev/null +++ b/src/misc/plugins.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#ifdef WIN32 +#include +#endif + +#include "dosbox.h" +#include "regs.h" +#include "mem.h" +#include "inout.h" +#include "pic.h" +#include "modules.h" +#include "programs.h" +#include "timer.h" +#include "dma.h" +#include "mixer.h" + + +struct PLUGIN_Function { + char * name; + void * function; +}; + +struct PLUGIN_Module { +#ifdef WIN32 + HINSTANCE handle; +#endif + + PLUGIN_Module * next; +}; + + +static PLUGIN_Function functions[]={ +"IO_RegisterReadHandler", (void *)IO_RegisterReadHandler, +"IO_RegisterWriteHandler", (void *)IO_RegisterWriteHandler, +"IO_FreeReadHandler", (void *)IO_FreeReadHandler, +"IO_FreeWriteHandler", (void *)IO_FreeWriteHandler, + +"IRQ_RegisterEOIHandler", (void *)PIC_RegisterIRQ, +"IRQ_FreeEOIHandler", (void *)PIC_FreeIRQ, +"IRQ_Activate", (void *)PIC_ActivateIRQ, +"IRQ_Deactivate", (void *)PIC_DeActivateIRQ, + +"TIMER_RegisterMicroHandler", (void *)TIMER_RegisterMicroHandler, +"TIMER_RegisterTickHandler", (void *)TIMER_RegisterTickHandler, + +"DMA_8_Read", (void *)DMA_8_Read, +"DMA_16_Read", (void *)DMA_16_Read, + +"DMA_8_Write", (void *)DMA_8_Write, +"DMA_16_Write", (void *)DMA_16_Write, + +"MIXER_AddChannel", (void *)MIXER_AddChannel, +"MIXER_SetVolume", (void *)MIXER_SetVolume, +"MIXER_SetFreq", (void *)MIXER_SetFreq, +"MIXER_SetMode", (void *)MIXER_SetMode, +"MIXER_Enable", (void *)MIXER_Enable, + +0,0 +}; + + +class PLUGIN : public Program { +public: + PLUGIN(PROGRAM_Info * program_info); + void Run(void); +}; + +PLUGIN::PLUGIN(PROGRAM_Info * info):Program(info) { + +} + + +void PLUGIN::Run(void) { + +} + + + +static void PLUGIN_ProgramStart(PROGRAM_Info * info) { + PLUGIN * tempPLUGIN=new PLUGIN(info); + tempPLUGIN->Run(); + delete tempPLUGIN; +} + + + +bool PLUGIN_FindFunction(char * name,void * * function) { +/* Run through table and hope to find a match */ + Bitu index=0; + while (functions[index].name) { + if (strcmp(functions[index].name,name)==0) { + *function=functions[index].function; + return true; + }; + index++; + } + return false; +} + + +bool PLUGIN_LoadModule(char * name) { + MODULE_StartHandler starter; + +#ifdef WIN32 + HMODULE module; + module=LoadLibrary(name); + if (!module) return false; +/* Look for the module start functions */ + FARPROC address; + address=GetProcAddress(module,MODULE_START_PROC); + starter=(MODULE_StartHandler)address; +#else +//TODO LINUX + + + + +#endif + starter(PLUGIN_FindFunction); +return false; + +} + + + +void PLUGIN_Init(void) { + PROGRAMS_MakeFile("PLUGIN.COM",PLUGIN_ProgramStart); +// PLUGIN_LoadModule("c:\\dosbox\\testmod.dll"); +}; + + + + + + + + + + diff --git a/src/misc/programs.cpp b/src/misc/programs.cpp index f145d26..f66f9cf 100644 --- a/src/misc/programs.cpp +++ b/src/misc/programs.cpp @@ -1,392 +1,174 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: programs.cpp,v 1.36 2009/03/23 10:55:36 qbix79 Exp $ */ - -#include -#include -#include -#include -#include -#include -#include "programs.h" -#include "callback.h" -#include "regs.h" -#include "support.h" -#include "cross.h" -#include "control.h" -#include "shell.h" - -Bitu call_program; - -/* This registers a file on the virtual drive and creates the correct structure for it*/ - -static Bit8u exe_block[]={ - 0xbc,0x00,0x04, //MOV SP,0x400 decrease stack size - 0xbb,0x40,0x00, //MOV BX,0x040 for memory resize - 0xb4,0x4a, //MOV AH,0x4A Resize memory block - 0xcd,0x21, //INT 0x21 -//pos 12 is callback number - 0xFE,0x38,0x00,0x00, //CALLBack number - 0xb8,0x00,0x4c, //Mov ax,4c00 - 0xcd,0x21, //INT 0x21 -}; - -#define CB_POS 12 - -static std::vector internal_progs; - -void PROGRAMS_MakeFile(char const * const name,PROGRAMS_Main * main) { - Bit8u * comdata=(Bit8u *)malloc(32); //MEM LEAK - memcpy(comdata,&exe_block,sizeof(exe_block)); - comdata[CB_POS]=(Bit8u)(call_program&0xff); - comdata[CB_POS+1]=(Bit8u)((call_program>>8)&0xff); - - /* Copy save the pointer in the vector and save it's index */ - if (internal_progs.size()>255) E_Exit("PROGRAMS_MakeFile program size too large (%d)",static_cast(internal_progs.size())); - Bit8u index = (Bit8u)internal_progs.size(); - internal_progs.push_back(main); - - memcpy(&comdata[sizeof(exe_block)],&index,sizeof(index)); - Bit32u size=sizeof(exe_block)+sizeof(index); - VFILE_Register(name,comdata,size); -} - - - -static Bitu PROGRAMS_Handler(void) { - /* This sets up everything for a program start up call */ - Bitu size=sizeof(Bit8u); - Bit8u index; - /* Read the index from program code in memory */ - PhysPt reader=PhysMake(dos.psp(),256+sizeof(exe_block)); - HostPt writer=(HostPt)&index; - for (;size>0;size--) *writer++=mem_readb(reader++); - Program * new_program; - if(index > internal_progs.size()) E_Exit("something is messing with the memory"); - PROGRAMS_Main * handler = internal_progs[index]; - (*handler)(&new_program); - new_program->Run(); - delete new_program; - return CBRET_NONE; -} - - -/* Main functions used in all program */ - - -Program::Program() { - /* Find the command line and setup the PSP */ - psp = new DOS_PSP(dos.psp()); - /* Scan environment for filename */ - PhysPt envscan=PhysMake(psp->GetEnvironment(),0); - while (mem_readb(envscan)) envscan+=mem_strlen(envscan)+1; - envscan+=3; - CommandTail tail; - MEM_BlockRead(PhysMake(dos.psp(),128),&tail,128); - if (tail.count<127) tail.buffer[tail.count]=0; - else tail.buffer[126]=0; - char filename[256+1]; - MEM_StrCopy(envscan,filename,256); - cmd = new CommandLine(filename,tail.buffer); -} - -extern std::string full_arguments; - -void Program::ChangeToLongCmd() { - /* - * Get arguments directly from the shell instead of the psp. - * this is done in securemode: (as then the arguments to mount and friends - * can only be given on the shell ( so no int 21 4b) - * Securemode part is disabled as each of the internal command has already - * protection for it. (and it breaks games like cdman) - * it is also done for long arguments to as it is convient (as the total commandline can be longer then 127 characters. - * imgmount with lot's of parameters - * Length of arguments can be ~120. but switch when above 100 to be sure - */ - - if(/*control->SecureMode() ||*/ cmd->Get_arglength() > 100) { - CommandLine* temp = new CommandLine(cmd->GetFileName(),full_arguments.c_str()); - delete cmd; - cmd = temp; - } - full_arguments.assign(""); //Clear so it gets even more save -} - -void Program::WriteOut(const char * format,...) { - char buf[2048]; - va_list msg; - - va_start(msg,format); - vsnprintf(buf,2047,format,msg); - va_end(msg); - - Bit16u size = (Bit16u)strlen(buf); - DOS_WriteFile(STDOUT,(Bit8u *)buf,&size); -} - -void Program::WriteOut_NoParsing(const char * format) { - Bit16u size = (Bit16u)strlen(format); - DOS_WriteFile(STDOUT,(Bit8u *)format,&size); -} - - -bool Program::GetEnvStr(const char * entry,std::string & result) { - /* Walk through the internal environment and see for a match */ - PhysPt env_read=PhysMake(psp->GetEnvironment(),0); - char env_string[1024+1]; - result.erase(); - if (!entry[0]) return false; - do { - MEM_StrCopy(env_read,env_string,1024); - if (!env_string[0]) return false; - env_read += (PhysPt)(strlen(env_string)+1); - char* equal = strchr(env_string,'='); - if (!equal) continue; - /* replace the = with \0 to get the length */ - *equal = 0; - if (strlen(env_string) != strlen(entry)) continue; - if (strcasecmp(entry,env_string)!=0) continue; - /* restore the = to get the original result */ - *equal = '='; - result = env_string; - return true; - } while (1); - return false; -} - -bool Program::GetEnvNum(Bitu num,std::string & result) { - char env_string[1024+1]; - PhysPt env_read=PhysMake(psp->GetEnvironment(),0); - do { - MEM_StrCopy(env_read,env_string,1024); - if (!env_string[0]) break; - if (!num) { result=env_string;return true;} - env_read += (PhysPt)(strlen(env_string)+1); - num--; - } while (1); - return false; -} - -Bitu Program::GetEnvCount(void) { - PhysPt env_read=PhysMake(psp->GetEnvironment(),0); - Bitu num=0; - while (mem_readb(env_read)!=0) { - for (;mem_readb(env_read);env_read++) {}; - env_read++; - num++; - } - return num; -} - -bool Program::SetEnv(const char * entry,const char * new_string) { - PhysPt env_read=PhysMake(psp->GetEnvironment(),0); - PhysPt env_write=env_read; - char env_string[1024+1]; - do { - MEM_StrCopy(env_read,env_string,1024); - if (!env_string[0]) break; - env_read += (PhysPt)(strlen(env_string)+1); - if (!strchr(env_string,'=')) continue; /* Remove corrupt entry? */ - if ((strncasecmp(entry,env_string,strlen(entry))==0) && - env_string[strlen(entry)]=='=') continue; - MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1)); - env_write += (PhysPt)(strlen(env_string)+1); - } while (1); -/* TODO Maybe save the program name sometime. not really needed though */ - /* Save the new entry */ - if (new_string[0]) { - std::string bigentry(entry); - for (std::string::iterator it = bigentry.begin(); it != bigentry.end(); ++it) *it = toupper(*it); - sprintf(env_string,"%s=%s",bigentry.c_str(),new_string); -// sprintf(env_string,"%s=%s",entry,new_string); //oldcode - MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1)); - env_write += (PhysPt)(strlen(env_string)+1); - } - /* Clear out the final piece of the environment */ - mem_writed(env_write,0); - return true; -} - -class CONFIG : public Program { -public: - void Run(void); -}; - -void MSG_Write(const char *); - -void CONFIG::Run(void) { - FILE * f; - if (cmd->FindString("-writeconf",temp_line,true) - || cmd->FindString("-wc",temp_line,true)) { - /* In secure mode don't allow a new configfile to be created */ - if(control->SecureMode()) { - WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); - return; - } - f=fopen(temp_line.c_str(),"wb+"); - if (!f) { - WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str()); - return; - } - fclose(f); - control->PrintConfig(temp_line.c_str()); - return; - } - if (cmd->FindString("-writelang",temp_line,true) - ||cmd->FindString("-wl",temp_line,true)) { - /* In secure mode don't allow a new languagefile to be created - * Who knows which kind of file we would overwriting. */ - if(control->SecureMode()) { - WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); - return; - } - f=fopen(temp_line.c_str(),"wb+"); - if (!f) { - WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str()); - return; - } - fclose(f); - MSG_Write(temp_line.c_str()); - return; - } - - /* Code for switching to secure mode */ - if(cmd->FindExist("-securemode",true)) { - control->SwitchToSecureMode(); - WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_ON")); - return; - } - - /* Code for getting the current configuration. * - * Official format: config -get "section property" * - * As a bonus it will set %CONFIG% to this value as well */ - if(cmd->FindString("-get",temp_line,true)) { - std::string temp2 = ""; - cmd->GetStringRemain(temp2);//So -get n1 n2= can be used without quotes - if(temp2 != "") temp_line = temp_line + " " + temp2; - - std::string::size_type space = temp_line.find(" "); - if(space == std::string::npos) { - WriteOut(MSG_Get("PROGRAM_CONFIG_GET_SYNTAX")); - return; - } - //Copy the found property to a new string and erase from templine (mind the space) - std::string prop = temp_line.substr(space+1); temp_line.erase(space); - - Section* sec = control->GetSection(temp_line.c_str()); - if(!sec) { - WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),temp_line.c_str()); - return; - } - std::string val = sec->GetPropValue(prop.c_str()); - if(val == NO_SUCH_PROPERTY) { - WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),prop.c_str(),temp_line.c_str()); - return; - } - WriteOut("%s",val.c_str()); - first_shell->SetEnv("CONFIG",val.c_str()); - return; - } - - - - /* Code for the configuration changes * - * Official format: config -set "section property=value" * - * Accepted: without quotes and/or without -set and/or without section * - * and/or the "=" replaced by a " " */ - - if (cmd->FindString("-set",temp_line,true)) { //get all arguments - std::string temp2 = ""; - cmd->GetStringRemain(temp2);//So -set n1 n2=n3 can be used without quotes - if(temp2!="") temp_line = temp_line + " " + temp2; - } else if(!cmd->GetStringRemain(temp_line)) {//no set - WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE")); //and no arguments specified - return; - }; - //Wanted input: n1 n2=n3 - char copy[1024]; - strcpy(copy,temp_line.c_str()); - //seperate section from property - const char* temp = strchr(copy,' '); - if((temp && *temp) || (temp=strchr(copy,'=')) ) copy[temp++ - copy]= 0; - else { - WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE")); - return; - } - //if n1 n2 n3 then replace last space with = - const char* sign = strchr(temp,'='); - if(!sign) { - sign = strchr(temp,' '); - if(sign) { - copy[sign - copy] = '='; - } else { - //2 items specified (no space nor = between n2 and n3 - //assume that they posted: property value - //Try to determine the section. - Section* sec=control->GetSectionFromProperty(copy); - if(!sec){ - if(control->GetSectionFromProperty(temp)) return; //Weird situation:ignore - WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"),copy); - return; - } //Hack to allow config ems true - char buffer[1024];strcpy(buffer,copy);strcat(buffer,"=");strcat(buffer,temp); - sign = strchr(buffer,' '); - if(sign) buffer[sign - buffer] = '='; - strcpy(copy,sec->GetName()); - temp = buffer; - } - } - - /* Input processed. Now the real job starts - * copy contains the likely "sectionname" - * temp contains "property=value" - * the section is destroyed and a new input line is given to - * the configuration parser. Then the section is restarted. - */ - char* inputline = const_cast(temp); - Section* sec = 0; - sec = control->GetSection(copy); - if(!sec) { WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),copy);return;} - sec->ExecuteDestroy(false); - sec->HandleInputline(inputline); - sec->ExecuteInit(false); - return; -} - - -static void CONFIG_ProgramStart(Program * * make) { - *make=new CONFIG; -} - - -void PROGRAMS_Init(Section* /*sec*/) { - /* Setup a special callback to start virtual programs */ - call_program=CALLBACK_Allocate(); - CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF,"internal program"); - PROGRAMS_MakeFile("CONFIG.COM",CONFIG_ProgramStart); - - MSG_Add("PROGRAM_CONFIG_FILE_ERROR","Can't open file %s\n"); - MSG_Add("PROGRAM_CONFIG_USAGE","Config tool:\nUse -writeconf filename to write the current config.\nUse -writelang filename to write the current language strings.\n"); - MSG_Add("PROGRAM_CONFIG_SECURE_ON","Switched to secure mode.\n"); - MSG_Add("PROGRAM_CONFIG_SECURE_DISALLOW","This operation is not permitted in secure mode.\n"); - MSG_Add("PROGRAM_CONFIG_SECTION_ERROR","Section %s doesn't exist.\n"); - MSG_Add("PROGRAM_CONFIG_PROPERTY_ERROR","No such section or property.\n"); - MSG_Add("PROGRAM_CONFIG_NO_PROPERTY","There is no property %s in section %s.\n"); - MSG_Add("PROGRAM_CONFIG_GET_SYNTAX","Correct syntax: config -get \"section property\".\n"); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include "programs.h" +#include "callback.h" +#include "regs.h" +#include "support.h" +#include "cross.h" + +Bitu call_program; + +/* This registers a file on the virtual drive and creates the correct structure for it*/ + +static Bit8u exe_block[]={ + 0xbc,0x00,0x03, //MOV SP,0x300 decrease stack size + 0xbb,0x30,0x00, //MOV BX,0x030 for memory resize + 0xb4,0x4a, //MOV AH,0x4A Resize memory block + 0xcd,0x21, //INT 0x21 +//pos 12 is callback number + 0xFE,0x38,0x00,0x00, //CALLBack number + 0xb8,0x00,0x4c, //Mov ax,4c00 + 0xcd,0x21, //INT 0x21 +}; + +#define CB_POS 12 + +void PROGRAMS_MakeFile(char * name,PROGRAMS_Main * main) { + Bit8u * comdata=(Bit8u *)malloc(128); + memcpy(comdata,&exe_block,sizeof(exe_block)); + comdata[CB_POS]=call_program&0xff; + comdata[CB_POS+1]=(call_program>>8)&0xff; +/* Copy the pointer this should preserve endianes */ + memcpy(&comdata[sizeof(exe_block)],&main,sizeof(main)); + Bit32u size=sizeof(exe_block)+sizeof(main); + VFILE_Register(name,comdata,size); +} + + +static Bitu PROGRAMS_Handler(void) { + /* This sets up everything for a program start up call */ + /* First get the current psp */ + PROGRAM_Info * info=new PROGRAM_Info; + info->psp_seg=dos.psp; + MEM_BlockRead(real_phys(dos.psp,0),&info->psp_copy,sizeof(PSP)); + /* Get the file name cmd_line 0 */ + PhysOff envblock=real_phys(info->psp_copy.environment,0); + do {} while (mem_readw(envblock++)); + envblock+=3; + MEM_StrCopy(envblock,info->full_name,32); + info->psp_copy.cmdtail.buffer[info->psp_copy.cmdtail.count]=0; + info->cmd_line=info->psp_copy.cmdtail.buffer; + /* Find the program handler somewhere reference in the file */ + Bit16u handle; + DOS_OpenFile(info->full_name,0,&handle); + Bit32u pos=sizeof(PROGRAMS_Main *); + DOS_SeekFile(handle,&pos,DOS_SEEK_END); + PROGRAMS_Main * handler; + Bit16u size=sizeof(PROGRAMS_Main *); + DOS_ReadFile(handle,(Bit8u *)&handler,&size); + DOS_CloseFile(handle); + (*handler)(info); + free(info); + return CBRET_NONE; +}; + + +/* Main functions used in all program */ + + +Program::Program(PROGRAM_Info * program_info) { + prog_info=program_info; +} + +void Program::WriteOut(char * format,...) { + char buf[1024]; + va_list msg; + + va_start(msg,format); + vsprintf(buf,format,msg); + va_end(msg); + + Bit16u size=strlen(buf); + DOS_WriteFile(STDOUT,(Bit8u *)buf,&size); +} + + +char * Program::GetEnvStr(char * env_str) { + /* Walk through the internal environment and see for a match */ +/* Taking some short cuts here to not fuck around with memory structure */ + + char * envstart=(char *)real_host(prog_info->psp_copy.environment,0); + size_t len=strlen(env_str); + while (*envstart) { + if (strncasecmp(env_str,envstart,len)==0 && envstart[len]=='=') { + return envstart; + } + envstart+=strlen(envstart)+1; + } + return 0; +}; + +char * Program::GetEnvNum(Bit32u num) { + char * envstart=(char *)real_host(prog_info->psp_copy.environment,0); + while (*envstart) { + if (!num) return envstart; + envstart+=strlen(envstart)+1; + num--; + } + return 0; +} + +Bit32u Program::GetEnvCount(void) { + char * envstart=(char *)real_host(prog_info->psp_copy.environment,0); + Bit32u num=0; + while (*envstart) { + envstart+=strlen(envstart)+1; + num++; + } + return num; +} + +bool Program::SetEnv(char * env_entry,char * new_string) { + MCB * env_mcb=(MCB *)real_host(prog_info->psp_copy.environment-1,0); + upcase(env_entry); + Bit32u env_size=env_mcb->size*16; + if (!env_size) E_Exit("SHELL:Illegal environment size"); + /* First try to find the old entry */ + size_t len=strlen(env_entry); + char * envstart=(char *)real_host(prog_info->psp_copy.environment,0); + while (*envstart) { + if (strncasecmp(env_entry,envstart,len)==0 && envstart[len]=='=') { + /* Now remove this entry */ + memmove(envstart,envstart+strlen(envstart)+1,env_size); + } else { + envstart+=strlen(envstart)+1; + env_size-=(strlen(envstart)+1); + } + } + /* Now add the string if there is space available */ + if (env_size<(strlen(env_entry)+strlen(new_string)+2)) return false; + if (!*new_string) return true; + sprintf(envstart,"%s=%s",env_entry,new_string); + envstart+=strlen(envstart)+1; + *envstart++=0;*envstart++=0;*envstart++=0; + return true; +} + +//TODO Hash table :) + + +void PROGRAMS_Init(void) { + /* Setup a special callback to start virtual programs */ + call_program=CALLBACK_Allocate(); + CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF); +} diff --git a/src/misc/setup.cpp b/src/misc/setup.cpp index 40263ce..69d47cb 100644 --- a/src/misc/setup.cpp +++ b/src/misc/setup.cpp @@ -1,1003 +1,29 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: setup.cpp,v 1.55 2009/03/11 20:18:37 qbix79 Exp $ */ - -#include "dosbox.h" -#include "cross.h" -#include "setup.h" -#include "control.h" -#include "support.h" -#include -#include -#include -#include -#include -#include - -using namespace std; -static std::string current_config_dir; // Set by parseconfigfile so Prop_path can use it to construct the realpath -void Value::destroy() throw(){ - if (type == V_STRING) delete _string; -} - -Value& Value::copy(Value const& in) throw(WrongType) { - if (this != &in) { //Selfassigment! - if(type != V_NONE && type != in.type) throw WrongType(); - destroy(); - plaincopy(in); - } - return *this; -} - -void Value::plaincopy(Value const& in) throw(){ - type = in.type; - _int = in._int; - _double = in._double; - _bool = in._bool; - _hex = in._hex; - if(type == V_STRING) _string = new string(*in._string); -} - -Value::operator bool () const throw(WrongType) { - if(type != V_BOOL) throw WrongType(); - return _bool; -} - -Value::operator Hex () const throw(WrongType) { - if(type != V_HEX) throw WrongType(); - return _hex; -} - -Value::operator int () const throw(WrongType) { - if(type != V_INT) throw WrongType(); - return _int; -} - -Value::operator double () const throw(WrongType) { - if(type != V_DOUBLE) throw WrongType(); - return _double; -} - -Value::operator char const* () const throw(WrongType) { - if(type != V_STRING) throw WrongType(); - return _string->c_str(); -} - -bool Value::operator==(Value const& other) { - if(this == &other) return true; - if(type != other.type) return false; - switch(type){ - case V_BOOL: - if(_bool == other._bool) return true; - break; - case V_INT: - if(_int == other._int) return true; - break; - case V_HEX: - if(_hex == other._hex) return true; - break; - case V_DOUBLE: - if(_double == other._double) return true; - break; - case V_STRING: - if((*_string) == (*other._string)) return true; - break; - default: - E_Exit("comparing stuff that doesn't make sense"); - break; - } - return false; -} -void Value::SetValue(string const& in,Etype _type) throw(WrongType) { - /* Throw exception if the current type isn't the wanted type - * Unless the wanted type is current. - */ - if(_type == V_CURRENT && type == V_NONE) throw WrongType(); - if(_type != V_CURRENT) { - if(type != V_NONE && type != _type) throw WrongType(); - type = _type; - } - switch(type){ - case V_HEX: - set_hex(in); - break; - case V_INT: - set_int(in); - break; - case V_BOOL: - set_bool(in); - break; - case V_STRING: - set_string(in); - break; - case V_DOUBLE: - set_double(in); - break; - - case V_NONE: - case V_CURRENT: - default: - /* Shouldn't happen!/Unhandled */ - throw WrongType(); - break; - } -} - -void Value::set_hex(std::string const& in) { - istringstream input(in); - input.flags(ios::hex); - int result = 0; - input >> result; - _hex = result; -} - -void Value::set_int(string const &in) { - istringstream input(in); - int result = 0; - input >> result; - _int = result; -} -void Value::set_double(string const &in) { - istringstream input(in); - double result = 0; - input >> result; - _double = result; -} - -void Value::set_bool(string const &in) { - istringstream input(in); - string result; - input >> result; - _bool = true; - lowcase(result); - /* valid false entries: 0 ,d*, f*, off everything else gets true */ - if( !result.size() ) return; - if(result[0] == '0' || result[0] == 'd' || result[0] == 'f' || result == "off") - _bool = false; -} - -void Value::set_string(string const & in) { - if(!_string) _string = new string(); - _string->assign(in); -} - -string Value::ToString() const { - ostringstream oss; - switch(type) { - case V_HEX: - oss.flags(ios::hex); - oss << _hex; - break; - case V_INT: - oss << _int; - break; - case V_BOOL: - oss << boolalpha << _bool; - break; - case V_STRING: - oss << *_string; - break; - case V_DOUBLE: - oss.precision(2); - oss << fixed << _double; - break; - case V_NONE: - case V_CURRENT: - default: - E_Exit("ToString messed up ?"); - break; - } - return oss.str(); -} - -bool Property::CheckValue(Value const& in, bool warn){ - if(suggested_values.empty()) return true; - for(iter it = suggested_values.begin();it != suggested_values.end();it++) { - if ( (*it) == in) { //Match! - return true; - } - } - if(warn) LOG_MSG("\"%s\" is not a valid value for variable: %s.\nIt might now be reset it to default value: %s",in.ToString().c_str(),propname.c_str(),default_value.ToString().c_str()); - return false; -} - -void Property::Set_help(string const& in) { - string result = string("CONFIG_") + propname; - upcase(result); - MSG_Add(result.c_str(),in.c_str()); -} - -char const* Property::Get_help() { - string result = string("CONFIG_") + propname; - upcase(result); - return MSG_Get(result.c_str()); -} - - -bool Prop_int::CheckValue(Value const& in, bool warn) { - if(suggested_values.empty() && Property::CheckValue(in,warn)) return true; - //No >= and <= in Value type and == is ambigious - int mi = min; - int ma = max; - int va = static_cast(Value(in)); - if(mi == -1 && ma == -1) return true; - if (va >= mi && va <= ma) return true; - if(warn) LOG_MSG("%s lies outside the range %s-%s for variable: %s.\nIt might now be reset to the default value: %s",in.ToString().c_str(),min.ToString().c_str(),max.ToString().c_str(),propname.c_str(),default_value.ToString().c_str()); - return false; -} - -void Prop_double::SetValue(std::string const& input){ - Value val(input,Value::V_DOUBLE); - SetVal(val,false,true); -} - -//void Property::SetValue(char* input){ -// value.SetValue(input, Value::V_CURRENT); -//} -void Prop_int::SetValue(std::string const& input){; - Value val(input,Value::V_INT); - SetVal(val,false,true); -} - -void Prop_string::SetValue(std::string const& input){ - //Special version for lowcase stuff - std::string temp(input); - //suggested values always case insensitive. - //If there are none then it can be paths and such which are case sensitive - if(!suggested_values.empty()) lowcase(temp); - Value val(temp,Value::V_STRING); - SetVal(val,false,true); -} -bool Prop_string::CheckValue(Value const& in, bool warn){ - if(suggested_values.empty()) return true; - for(iter it = suggested_values.begin();it != suggested_values.end();it++) { - if ( (*it) == in) { //Match! - return true; - } - if((*it).ToString() == "%u") { - Bitu value; - if(sscanf(in.ToString().c_str(),"%u",&value) == 1) { - return true; - } - } - } - if(warn) LOG_MSG("\"%s\" is not a valid value for variable: %s.\nIt might now be reset it to default value: %s",in.ToString().c_str(),propname.c_str(),default_value.ToString().c_str()); - return false; -} - -void Prop_path::SetValue(std::string const& input){ - //Special version to merge realpath with it - - Value val(input,Value::V_STRING); - SetVal(val,false,true); - - if(input.empty()) { - realpath = ""; - return; - } - std::string workcopy(input); - Cross::ResolveHomedir(workcopy); //Parse ~ and friends - //Prepend config directory in it exists. Check for absolute paths later - if( current_config_dir.empty()) realpath = workcopy; - else realpath = current_config_dir + CROSS_FILESPLIT + workcopy; - //Absolute paths -#if defined (WIN32) || defined(OS2) - if( workcopy.size() > 2 && workcopy[1] == ':' ) realpath = workcopy; -#else - if( workcopy.size() > 1 && workcopy[0] == '/' ) realpath = workcopy; -#endif -} - -void Prop_bool::SetValue(std::string const& input){ - value.SetValue(input,Value::V_BOOL); -} - -void Prop_hex::SetValue(std::string const& input){ - Value val(input,Value::V_HEX); - SetVal(val,false,true); -} - -void Prop_multival::make_default_value(){ - Bitu i = 1; - Property *p = section->Get_prop(0); - if(!p) return; - - std::string result = p->Get_Default_Value().ToString(); - while( (p = section->Get_prop(i++)) ) { - std::string props = p->Get_Default_Value().ToString(); - if(props == "") continue; - result += seperator; result += props; - } - Value val(result,Value::V_STRING); - SetVal(val,false,true); -} - - - -//TODO checkvalue stuff -void Prop_multival_remain::SetValue(std::string const& input) { - Value val(input,Value::V_STRING); - SetVal(val,false,true); - - std::string local(input); - int i = 0,number_of_properties = 0; - Property *p = section->Get_prop(0); - //No properties in this section. do nothing - if(!p) return; - - while( (section->Get_prop(number_of_properties)) ) - number_of_properties++; - - string::size_type loc = string::npos; - while( (p = section->Get_prop(i++)) ) { - //trim leading seperators - loc = local.find_first_not_of(seperator); - if(loc != string::npos) local.erase(0,loc); - loc = local.find_first_of(seperator); - string in = "";//default value - /* when i == number_of_properties add the total line. (makes more then - * one string argument possible for parameters of cpu) */ - if(loc != string::npos && i < number_of_properties) { //seperator found - in = local.substr(0,loc); - local.erase(0,loc+1); - } else if(local.size()) { //last argument or last property - in = local; - local = ""; - } - //Test Value. If it fails set default - Value valtest (in,p->Get_type()); - if(!p->CheckValue(valtest,true)) { - make_default_value(); - return; - } - p->SetValue(in); - } -} - -//TODO checkvalue stuff -void Prop_multival::SetValue(std::string const& input) { - Value val(input,Value::V_STRING); - SetVal(val,false,true); - - std::string local(input); - int i = 0; - Property *p = section->Get_prop(0); - //No properties in this section. do nothing - if(!p) return; - string::size_type loc = string::npos; - while( (p = section->Get_prop(i++)) ) { - //trim leading seperators - loc = local.find_first_not_of(seperator); - if(loc != string::npos) local.erase(0,loc); - loc = local.find_first_of(seperator); - string in = "";//default value - if(loc != string::npos) { //seperator found - in = local.substr(0,loc); - local.erase(0,loc+1); - } else if(local.size()) { //last argument - in = local; - local = ""; - } - //Test Value. If it fails set default - Value valtest (in,p->Get_type()); - if(!p->CheckValue(valtest,true)) { - make_default_value(); - return; - } - p->SetValue(in); - - } -} - -const std::vector& Property::GetValues() const { - return suggested_values; -} -const std::vector& Prop_multival::GetValues() const -{ - Property *p = section->Get_prop(0); - //No properties in this section. do nothing - if(!p) return suggested_values; - int i =0; - while( (p = section->Get_prop(i++)) ) { - std::vector v = p->GetValues(); - if(!v.empty()) return p->GetValues(); - } - return suggested_values; -} - -/* -void Section_prop::Add_double(char const * const _propname, double _value) { - Property* test=new Prop_double(_propname,_value); - properties.push_back(test); -}*/ - -void Property::Set_values(const char * const *in) { - Value::Etype type = default_value.type; - int i = 0; - while (in[i]) { - Value val(in[i],type); - suggested_values.push_back(val); - i++; - } -} - -Prop_int* Section_prop::Add_int(string const& _propname, Property::Changeable::Value when, int _value) { - Prop_int* test=new Prop_int(_propname,when,_value); - properties.push_back(test); - return test; -} - -Prop_string* Section_prop::Add_string(string const& _propname, Property::Changeable::Value when, char const * const _value) { - Prop_string* test=new Prop_string(_propname,when,_value); - properties.push_back(test); - return test; -} - -Prop_path* Section_prop::Add_path(string const& _propname, Property::Changeable::Value when, char const * const _value) { - Prop_path* test=new Prop_path(_propname,when,_value); - properties.push_back(test); - return test; -} - -Prop_bool* Section_prop::Add_bool(string const& _propname, Property::Changeable::Value when, bool _value) { - Prop_bool* test=new Prop_bool(_propname,when,_value); - properties.push_back(test); - return test; -} -Prop_hex* Section_prop::Add_hex(string const& _propname, Property::Changeable::Value when, Hex _value) { - Prop_hex* test=new Prop_hex(_propname,when,_value); - properties.push_back(test); - return test; -} -Prop_multival* Section_prop::Add_multi(std::string const& _propname, Property::Changeable::Value when,std::string const& sep) { - Prop_multival* test = new Prop_multival(_propname,when,sep); - properties.push_back(test); - return test; -} -Prop_multival_remain* Section_prop::Add_multiremain(std::string const& _propname, Property::Changeable::Value when,std::string const& sep) { - Prop_multival_remain* test = new Prop_multival_remain(_propname,when,sep); - properties.push_back(test); - return test; -} - -int Section_prop::Get_int(string const&_propname) const { - for(const_it tel=properties.begin();tel!=properties.end();tel++){ - if((*tel)->propname==_propname){ - return ((*tel)->GetValue()); - } - } - return 0; -} - -bool Section_prop::Get_bool(string const& _propname) const { - for(const_it tel=properties.begin();tel!=properties.end();tel++){ - if((*tel)->propname==_propname){ - return ((*tel)->GetValue()); - } - } - return false; -} -double Section_prop::Get_double(string const& _propname) const { - for(const_it tel=properties.begin();tel!=properties.end();tel++){ - if((*tel)->propname==_propname){ - return ((*tel)->GetValue()); - } - } - return 0.0; -} - -Prop_path* Section_prop::Get_path(string const& _propname) const { - for(const_it tel=properties.begin();tel!=properties.end();tel++){ - if((*tel)->propname==_propname){ - Prop_path* val = dynamic_cast((*tel)); - if(val) return val; else return NULL; - } - } - return NULL; -} - -Prop_multival* Section_prop::Get_multival(string const& _propname) const { - for(const_it tel=properties.begin();tel!=properties.end();tel++){ - if((*tel)->propname==_propname){ - Prop_multival* val = dynamic_cast((*tel)); - if(val) return val; else return NULL; - } - } - return NULL; -} - -Prop_multival_remain* Section_prop::Get_multivalremain(string const& _propname) const { - for(const_it tel=properties.begin();tel!=properties.end();tel++){ - if((*tel)->propname==_propname){ - Prop_multival_remain* val = dynamic_cast((*tel)); - if(val) return val; else return NULL; - } - } - return NULL; -} -Property* Section_prop::Get_prop(int index){ - for(it tel=properties.begin();tel!=properties.end();tel++){ - if(!index--) return (*tel); - } - return NULL; -} - -const char* Section_prop::Get_string(string const& _propname) const { - for(const_it tel=properties.begin();tel!=properties.end();tel++){ - if((*tel)->propname==_propname){ - return ((*tel)->GetValue()); - } - } - return ""; -} -Hex Section_prop::Get_hex(string const& _propname) const { - for(const_it tel=properties.begin();tel!=properties.end();tel++){ - if((*tel)->propname==_propname){ - return ((*tel)->GetValue()); - } - } - return 0; -} - -void trim(string& in) { - string::size_type loc = in.find_first_not_of(" \r\t\f\n"); - if(loc != string::npos) in.erase(0,loc); - loc = in.find_last_not_of(" \r\t\f\n"); - if(loc != string::npos) in.erase(loc+1); -} - -//TODO double c_str -void Section_prop::HandleInputline(string const& gegevens){ - string str1 = gegevens; - string::size_type loc = str1.find('='); - if(loc == string::npos) return; - string name = str1.substr(0,loc); - string val = str1.substr(loc + 1); - /* trim the results incase there were spaces somewhere */ - trim(name);trim(val); - for(it tel=properties.begin();tel!=properties.end();tel++){ - if(!strcasecmp((*tel)->propname.c_str(),name.c_str())){ - (*tel)->SetValue(val); - return; - } - } -} - -void Section_prop::PrintData(FILE* outfile) const { - /* Now print out the individual section entries */ - for(const_it tel=properties.begin();tel!=properties.end();tel++){ - fprintf(outfile,"%s=%s\n",(*tel)->propname.c_str(),(*tel)->GetValue().ToString().c_str()); - } -} - -//TODO geen noodzaak voor 2 keer c_str -string Section_prop::GetPropValue(string const& _property) const{ - for(const_it tel=properties.begin();tel!=properties.end();tel++){ - if(!strcasecmp((*tel)->propname.c_str(),_property.c_str())){ - return (*tel)->GetValue().ToString(); - } - } - return NO_SUCH_PROPERTY; -} - -void Section_line::HandleInputline(string const& line){ - data+=line; - data+="\n"; -} - -void Section_line::PrintData(FILE* outfile) const { - fprintf(outfile,"%s",data.c_str()); -} - -string Section_line::GetPropValue(string const& /* _property*/) const { - return NO_SUCH_PROPERTY; -} - -bool Config::PrintConfig(char const * const configfilename) const { - char temp[50];char helpline[256]; - FILE* outfile=fopen(configfilename,"w+t"); - if(outfile==NULL) return false; - - /* Print start of configfile and add an return to improve readibility. */ - fprintf(outfile,MSG_Get("CONFIGFILE_INTRO"),VERSION); - fprintf(outfile,"\n"); - for (const_it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){ - /* Print out the Section header */ - Section_prop *sec = dynamic_cast(*tel); - strcpy(temp,(*tel)->GetName()); - lowcase(temp); - fprintf(outfile,"[%s]\n",temp); - - if (sec) { - Property *p; - size_t i = 0, maxwidth = 0; - while ((p = sec->Get_prop(i++))) { - size_t w = strlen(p->propname.c_str()); - if (w > maxwidth) maxwidth = w; - } - i=0; - char prefix[80]; - snprintf(prefix,80, "\n# %*s ", maxwidth, ""); - while ((p = sec->Get_prop(i++))) { - std::string help = p->Get_help(); - std::string::size_type pos = std::string::npos; - while ((pos = help.find("\n", pos+1)) != std::string::npos) { - help.replace(pos, 1, prefix); - } - - fprintf(outfile, "# %*s: %s", maxwidth, p->propname.c_str(), help.c_str()); - - std::vector values = p->GetValues(); - if (!values.empty()) { - fprintf(outfile, "%s%s:", prefix, MSG_Get("CONFIG_SUGGESTED_VALUES")); - std::vector::iterator it = values.begin(); - while (it != values.end()) { - if((*it).ToString() != "%u") { //Hack hack hack. else we need to modify GetValues, but that one is const... - if (it != values.begin()) fputs(",", outfile); - fprintf(outfile, " %s", (*it).ToString().c_str()); - } - ++it; - } - fprintf(outfile,"."); - } - fprintf(outfile, "\n"); - } - } else { - upcase(temp); - strcat(temp,"_CONFIGFILE_HELP"); - const char * helpstr=MSG_Get(temp); - char * helpwrite=helpline; - while (*helpstr) { - *helpwrite++=*helpstr; - if (*helpstr == '\n') { - *helpwrite=0; - fprintf(outfile,"# %s",helpline); - helpwrite=helpline; - } - helpstr++; - } - } - - fprintf(outfile,"\n"); - (*tel)->PrintData(outfile); - fprintf(outfile,"\n"); /* Always an empty line between sections */ - } - fclose(outfile); - return true; -} - - -Section_prop* Config::AddSection_prop(char const * const _name,void (*_initfunction)(Section*),bool canchange){ - Section_prop* blah = new Section_prop(_name); - blah->AddInitFunction(_initfunction,canchange); - sectionlist.push_back(blah); - return blah; -} - -Section_prop::~Section_prop() { -//ExecuteDestroy should be here else the destroy functions use destroyed properties - ExecuteDestroy(true); - /* Delete properties themself (properties stores the pointer of a prop */ - for(it prop = properties.begin(); prop != properties.end(); prop++) - delete (*prop); -} - - -Section_line* Config::AddSection_line(char const * const _name,void (*_initfunction)(Section*)){ - Section_line* blah = new Section_line(_name); - blah->AddInitFunction(_initfunction); - sectionlist.push_back(blah); - return blah; -} - - -void Config::Init() { - for (const_it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){ - (*tel)->ExecuteInit(); - } -} - -void Section::AddInitFunction(SectionFunction func,bool canchange) { - initfunctions.push_back(Function_wrapper(func,canchange)); -} - -void Section::AddDestroyFunction(SectionFunction func,bool canchange) { - destroyfunctions.push_front(Function_wrapper(func,canchange)); -} - - -void Section::ExecuteInit(bool initall) { - typedef std::list::iterator func_it; - for (func_it tel=initfunctions.begin(); tel!=initfunctions.end(); tel++) { - if(initall || (*tel).canchange) (*tel).function(this); - } -} - -void Section::ExecuteDestroy(bool destroyall) { - typedef std::list::iterator func_it; - for (func_it tel=destroyfunctions.begin(); tel!=destroyfunctions.end(); ) { - if(destroyall || (*tel).canchange) { - (*tel).function(this); - tel=destroyfunctions.erase(tel); //Remove destroyfunction once used - } else tel++; - } -} - -Config::~Config() { - reverse_it cnt=sectionlist.rbegin(); - while (cnt!=sectionlist.rend()) { - delete (*cnt); - cnt++; - } -} - -Section* Config::GetSection(int index){ - for (it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){ - if (!index--) return (*tel); - } - return NULL; -} -//c_str() 2x -Section* Config::GetSection(string const& _sectionname) const{ - for (const_it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){ - if (!strcasecmp((*tel)->GetName(),_sectionname.c_str())) return (*tel); - } - return NULL; -} - -Section* Config::GetSectionFromProperty(char const * const prop) const{ - for (const_it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){ - if ((*tel)->GetPropValue(prop) != NO_SUCH_PROPERTY) return (*tel); - } - return NULL; -} - - -bool Config::ParseConfigFile(char const * const configfilename){ - static bool first_configfile = true; - ifstream in(configfilename); - if (!in) return false; - const char * settings_type = first_configfile?"primary":"additional"; - first_configfile = false; - LOG_MSG("CONFIG:Loading %s settings from config file %s", settings_type,configfilename); - - //Get directory from configfilename, used with relative paths. - current_config_dir=configfilename; - std::string::size_type pos = current_config_dir.rfind(CROSS_FILESPLIT); - if(pos == std::string::npos) pos = 0; //No directory then erase string - current_config_dir.erase(pos); - - string gegevens; - Section* currentsection = NULL; - Section* testsec = NULL; - while (getline(in,gegevens)) { - - /* strip leading/trailing whitespace */ - trim(gegevens); - if(!gegevens.size()) continue; - - switch(gegevens[0]){ - case '%': - case '\0': - case '#': - case ' ': - case '\n': - continue; - break; - case '[': - { - string::size_type loc = gegevens.find(']'); - if(loc == string::npos) continue; - gegevens.erase(loc); - testsec = GetSection(gegevens.substr(1)); - if(testsec != NULL ) currentsection = testsec; - testsec = NULL; - } - break; - default: - try { - if(currentsection) currentsection->HandleInputline(gegevens); - } catch(const char* message) { - message=0; - //EXIT with message - } - break; - } - } - current_config_dir.clear();//So internal changes don't use the path information - return true; -} - -void Config::ParseEnv(char ** envp) { - for(char** env=envp; *env;env++) { - char copy[1024]; - safe_strncpy(copy,*env,1024); - if(strncasecmp(copy,"DOSBOX_",7)) - continue; - char* sec_name = ©[7]; - if(!(*sec_name)) - continue; - char* prop_name = strrchr(sec_name,'_'); - if(!prop_name || !(*prop_name)) - continue; - *prop_name++=0; - Section* sect = GetSection(sec_name); - if(!sect) - continue; - sect->HandleInputline(prop_name); - } -} - -void Config::SetStartUp(void (*_function)(void)) { - _start_function=_function; -} - - -void Config::StartUp(void) { - (*_start_function)(); -} - -bool CommandLine::FindExist(char const * const name,bool remove) { - cmd_it it; - if (!(FindEntry(name,it,false))) return false; - if (remove) cmds.erase(it); - return true; -} - -bool CommandLine::FindHex(char const * const name,int & value,bool remove) { - cmd_it it,it_next; - if (!(FindEntry(name,it,true))) return false; - it_next=it;it_next++; - sscanf((*it_next).c_str(),"%X",&value); - if (remove) cmds.erase(it,++it_next); - return true; -} - -bool CommandLine::FindInt(char const * const name,int & value,bool remove) { - cmd_it it,it_next; - if (!(FindEntry(name,it,true))) return false; - it_next=it;it_next++; - value=atoi((*it_next).c_str()); - if (remove) cmds.erase(it,++it_next); - return true; -} - -bool CommandLine::FindString(char const * const name,std::string & value,bool remove) { - cmd_it it,it_next; - if (!(FindEntry(name,it,true))) return false; - it_next=it;it_next++; - value=*it_next; - if (remove) cmds.erase(it,++it_next); - return true; -} - -bool CommandLine::FindCommand(unsigned int which,std::string & value) { - if (which<1) return false; - if (which>cmds.size()) return false; - cmd_it it=cmds.begin(); - for (;which>1;which--) it++; - value=(*it); - return true; -} - -bool CommandLine::FindEntry(char const * const name,cmd_it & it,bool neednext) { - for (it=cmds.begin();it!=cmds.end();it++) { - if (!strcasecmp((*it).c_str(),name)) { - cmd_it itnext=it;itnext++; - if (neednext && (itnext==cmds.end())) return false; - return true; - } - } - return false; -} - -bool CommandLine::FindStringBegin(char const* const begin,std::string & value, bool remove) { - size_t len = strlen(begin); - for (cmd_it it=cmds.begin();it!=cmds.end();it++) { - if (strncmp(begin,(*it).c_str(),len)==0) { - value=((*it).c_str() + len); - if (remove) cmds.erase(it); - return true; - } - } - return false; -} - -bool CommandLine::FindStringRemain(char const * const name,std::string & value) { - cmd_it it;value=""; - if (!FindEntry(name,it)) return false; - it++; - for (;it!=cmds.end();it++) { - value+=" "; - value+=(*it); - } - return true; -} - -bool CommandLine::GetStringRemain(std::string & value) { - if(!cmds.size()) return false; - - cmd_it it=cmds.begin();value=(*it++); - for(;it != cmds.end();it++) { - value+=" "; - value+=(*it); - } - return true; -} - - -unsigned int CommandLine::GetCount(void) { - return (unsigned int)cmds.size(); -} - -CommandLine::CommandLine(int argc,char const * const argv[]) { - if (argc>0) { - file_name=argv[0]; - } - int i=1; - while (i -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dosbox.h" -#include "debug.h" -#include "support.h" -#include "video.h" - - -void upcase(std::string &str) { - int (*tf)(int) = std::toupper; - std::transform(str.begin(), str.end(), str.begin(), tf); -} - -void lowcase(std::string &str) { - int (*tf)(int) = std::tolower; - std::transform(str.begin(), str.end(), str.begin(), tf); -} - - -/* - Ripped some source from freedos for this one. - -*/ - - -/* - * replaces all instances of character o with character c - */ - - -void strreplace(char * str,char o,char n) { - while (*str) { - if (*str==o) *str=n; - str++; - } -} -char *ltrim(char *str) { - while (*str && isspace(*reinterpret_cast(str))) str++; - return str; -} - -char *rtrim(char *str) { - char *p; - p = strchr(str, '\0'); - while (--p >= str && isspace(*reinterpret_cast(p))) {}; - p[1] = '\0'; - return str; -} - -char *trim(char *str) { - return ltrim(rtrim(str)); -} - -char * upcase(char * str) { - for (char* idx = str; *idx ; idx++) *idx = toupper(*reinterpret_cast(idx)); - return str; -} - -char * lowcase(char * str) { - for(char* idx = str; *idx ; idx++) *idx = tolower(*reinterpret_cast(idx)); - return str; -} - - - -bool ScanCMDBool(char * cmd,char const * const check) { - char * scan=cmd;size_t c_len=strlen(check); - while ((scan=strchr(scan,'/'))) { - /* found a / now see behind it */ - scan++; - if (strncasecmp(scan,check,c_len)==0 && (scan[c_len]==' ' || scan[c_len]=='\t' || scan[c_len]=='/' || scan[c_len]==0)) { - /* Found a math now remove it from the string */ - memmove(scan-1,scan+c_len,strlen(scan+c_len)+1); - trim(scan-1); - return true; - } - } - return false; -} - -/* This scans the command line for a remaining switch and reports it else returns 0*/ -char * ScanCMDRemain(char * cmd) { - char * scan,*found;; - if ((scan=found=strchr(cmd,'/'))) { - while ( *scan && !isspace(*reinterpret_cast(scan)) ) scan++; - *scan=0; - return found; - } else return 0; -} - -char * StripWord(char *&line) { - char * scan=line; - scan=ltrim(scan); - if (*scan=='"') { - char * end_quote=strchr(scan+1,'"'); - if (end_quote) { - *end_quote=0; - line=ltrim(++end_quote); - return (scan+1); - } - } - char * begin=scan; - for (char c = *scan ;(c = *scan);scan++) { - if (isspace(*reinterpret_cast(&c))) { - *scan++=0; - break; - } - } - line=scan; - return begin; -} - -Bits ConvDecWord(char * word) { - bool negative=false;Bitu ret=0; - if (*word=='-') { - negative=true; - word++; - } - while (char c=*word) { - ret*=10; - ret+=c-'0'; - word++; - } - if (negative) return 0-ret; - else return ret; -} - -Bits ConvHexWord(char * word) { - Bitu ret=0; - while (char c=toupper(*reinterpret_cast(word))) { - ret*=16; - if (c>='0' && c<='9') ret+=c-'0'; - else if (c>='A' && c<='F') ret+=10+(c-'A'); - word++; - } - return ret; -} - -double ConvDblWord(char * word) { - return 0.0f; -} - - -static char buf[1024]; //greater scope as else it doesn't always gets thrown right (linux/gcc2.95) -void E_Exit(const char * format,...) { -#if C_DEBUG && C_HEAVY_DEBUG - DEBUG_HeavyWriteLogInstruction(); -#endif - va_list msg; - va_start(msg,format); - vsprintf(buf,format,msg); - va_end(msg); - strcat(buf,"\n"); - - throw(buf); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include "dosbox.h" +#include "support.h" + + +/* + Ripped some source from freedos for this one. + +*/ + + +/* + * replaces all instances of character o with character c + */ + + +void strreplace(char * str,char o,char n) { + while (*str) { + if (*str==o) *str=n; + str++; + } +} +/* + * Name: ltrim() - left trims a string by removing leading spaces + * Input: str - a pointer to a string + * Output: returns a trimmed copy of str + */ +char *ltrim(char *str) { + char c; + assert(str); + + while ((c = *str++) != '\0' && isspace(c)); + return str - 1; +} + +/* + * Name: rtrim() - right trims a string by removing trailing spaces + * Input: str - a pointer to a string + * Output: str will have all spaces removed from the right. + */ +void rtrim(char * const str) { + char *p; + + assert(str); + + p = strchr(str, '\0'); + while (--p >= str && isspace(*p)); + p[1] = '\0'; +} + +/* + * Combines ltrim() & rtrim() + */ +char *trim(char *str) { + assert(str); + rtrim(str); + return ltrim(str); +} + +bool wildcmp(char *wild, char *string) { + char *cp, *mp; + while ((*string) && (*wild != '*')) { + if ((*wild != *string) && (*wild != '?')) { + return false; + } + wild++; + string++; + } + + while (*string) { + if (*wild == '*') { + if (!*++wild) { + return true; + } + mp = wild; + cp = string+1; + } else if ((*wild == *string) || (*wild == '?')) { + wild++; + string++; + } else { + wild = mp; + string = cp++; + } + } + + while (*wild == '*') { + wild++; + } + return !*wild; +} + + +bool ScanCMDBool(char * cmd,char * check) { + char * scan=cmd;size_t c_len=strlen(check); + while (scan=strchr(scan,'/')) { + /* found a / now see behind it */ + scan++; + if (strncasecmp(scan,check,c_len)==0 && (scan[c_len]==' ' || scan[c_len]==0)) { + /* Found a math now remove it from the string */ + memmove(scan-1,scan+c_len,strlen(scan+c_len)+1); + trim(scan-1); + return true; + } + } + return false; +} + + +bool ScanCMDHex(char * cmd,char * check,Bits * result) { + char * scan=cmd;size_t c_len=strlen(check); + while (scan=strchr(scan,'/')) { + /* found a / now see behind it */ + scan++; + if (strncasecmp(scan,check,c_len)==0 && (scan[c_len]==' ' || scan[c_len]==0)) { + /* Found a match now find the number and remove it from the string */ + char * begin=scan-1; + scan=ltrim(scan+c_len); + bool res=true; + *result=-1; + if (!sscanf(scan,"%X",result)) res=false; + scan=strrchr(scan,'/'); + if (scan) memmove(begin,scan,strlen(scan)+1); + else *begin=0; + trim(begin); + return res; + } + } + return false; + +} + +/* This scans the command line for a remaining switch and reports it else returns 0*/ +char * ScanCMDRemain(char * cmd) { + char * scan,*found;; + if (scan=found=strchr(cmd,'/')) { + while (*scan!=' ' && *scan!=0) scan++; + *scan=0; + return found; + } else return 0; +} + +char * StripWord(char * cmd) { + bool quoted=false; + char * begin=cmd; + if (*cmd=='"') { + quoted=true; + cmd++; + } + char * end; + if (quoted) { + end=strchr(cmd,'"'); + } else { + end=strchr(cmd,' '); + } + if (!end) { + return cmd+strlen(cmd); + } + *end=0; + if (quoted) { + memmove(begin,cmd,end-begin+1); + } + return trim(cmd+strlen(begin)+1); +} + +void GFX_ShowMsg(char * msg); +void DEBUG_ShowMsg(char * msg); + +void S_Warn(char * format,...) { + char buf[1024]; + va_list msg; + + va_start(msg,format); + vsprintf(buf,format,msg); + va_end(msg); +#ifdef C_DEBUG + DEBUG_ShowMsg(buf); +#else + GFX_ShowMsg(buf); +#endif +} + +void E_Exit(char * format,...) { + + char buf[1024]; + +// SysShutDown(); + va_list msg; + strcpy(buf,"EXIT:"); + va_start(msg,format); + vsprintf(buf+strlen(buf),format,msg); + va_end(msg); + + strcat(buf,"\n"); + printf(buf); + printf("Press ENTER to stop\n"); + fgetc(stdin); + exit(2); + +}; \ No newline at end of file diff --git a/src/platform/Makefile.am b/src/platform/Makefile.am index f240f8f..6efd890 100644 --- a/src/platform/Makefile.am +++ b/src/platform/Makefile.am @@ -1,3 +1 @@ -SUBDIRS = visualc - -EXTRA_DIST = sdl-win32.diff \ No newline at end of file +SUBDIRS = visualc \ No newline at end of file diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in new file mode 100644 index 0000000..dd4d25e --- /dev/null +++ b/src/platform/Makefile.in @@ -0,0 +1,326 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +SUBDIRS = visualc +subdir = src/platform +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = Makefile.am Makefile.in +DIST_SUBDIRS = $(SUBDIRS) +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/platform/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-recursive distclean distclean-generic \ + distclean-recursive distclean-tags distdir dvi dvi-am \ + dvi-recursive info info-am info-recursive install install-am \ + install-data install-data-am install-data-recursive \ + install-exec install-exec-am install-exec-recursive \ + install-info install-info-am install-info-recursive install-man \ + install-recursive install-strip installcheck installcheck-am \ + installdirs installdirs-am installdirs-recursive \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-recursive tags tags-recursive uninstall \ + uninstall-am uninstall-info-am uninstall-info-recursive \ + uninstall-recursive + +# 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/platform/sdl-win32.diff b/src/platform/sdl-win32.diff deleted file mode 100644 index efb89b7..0000000 --- a/src/platform/sdl-win32.diff +++ /dev/null @@ -1,55 +0,0 @@ -diff -ru SDL-1.2.12/src/main/win32/version.rc SDL-1.2.12release/src/main/win32/version.rc ---- SDL-1.2.12/src/main/win32/version.rc 2007-07-20 07:52:05.000000000 +0200 -+++ SDL-1.2.12release/src/main/win32/version.rc 2007-08-17 19:03:42.000000000 +0200 -@@ -13,7 +13,7 @@ - FILEVERSION 1,2,12,0 - PRODUCTVERSION 1,2,12,0 - FILEFLAGSMASK 0x3fL -- FILEFLAGS 0x0L -+ FILEFLAGS 0x4L - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -diff -ru SDL-1.2.12/src/video/SDL_video.c SDL-1.2.12release/src/video/SDL_video.c ---- SDL-1.2.12/src/video/SDL_video.c 2007-07-20 07:52:25.000000000 +0200 -+++ SDL-1.2.12release/src/video/SDL_video.c 2007-08-17 02:51:52.000000000 +0200 -@@ -75,12 +75,12 @@ - #if SDL_VIDEO_DRIVER_GAPI - &GAPI_bootstrap, - #endif --#if SDL_VIDEO_DRIVER_WINDIB -- &WINDIB_bootstrap, --#endif - #if SDL_VIDEO_DRIVER_DDRAW - &DIRECTX_bootstrap, - #endif -+#if SDL_VIDEO_DRIVER_WINDIB -+ &WINDIB_bootstrap, -+#endif - #if SDL_VIDEO_DRIVER_BWINDOW - &BWINDOW_bootstrap, - #endif -diff -ru SDL-1.2.12/src/video/windx5/SDL_dx5events.c SDL-1.2.12release/src/video/windx5/SDL_dx5events.c ---- SDL-1.2.12/src/video/windx5/SDL_dx5events.c 2007-07-20 07:52:25.000000000 +0200 -+++ SDL-1.2.12release/src/video/windx5/SDL_dx5events.c 2007-08-17 02:51:52.000000000 +0200 -@@ -519,7 +519,7 @@ - case WM_SYSKEYDOWN: { - /* Pass syskey to DefWindwoProc (ALT-F4, etc.) */ - } -- break; -+// break; - case WM_KEYUP: - case WM_KEYDOWN: { - /* Ignore windows keyboard messages */; -diff -ru SDL-1.2.12/src/video/windx5/SDL_dx5video.c SDL-1.2.12release/src/video/windx5/SDL_dx5video.c ---- SDL-1.2.12/src/video/windx5/SDL_dx5video.c 2007-07-20 07:52:25.000000000 +0200 -+++ SDL-1.2.12release/src/video/windx5/SDL_dx5video.c 2007-08-17 02:51:52.000000000 +0200 -@@ -1496,7 +1496,7 @@ - } - } - dd_surface3 = NULL; --#if 0 /* FIXME: enable this when SDL consistently reports lost surfaces */ -+#if 1 /* FIXME: enable this when SDL consistently reports lost surfaces */ - if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) { - video->flags |= SDL_HWSURFACE; - } else { diff --git a/src/platform/visualc/Makefile.am b/src/platform/visualc/Makefile.am index e41446c..605cef9 100644 --- a/src/platform/visualc/Makefile.am +++ b/src/platform/visualc/Makefile.am @@ -1 +1 @@ -EXTRA_DIST = dirent.c dirent.h unistd.h config.h ntddscsi.h ntddcdrm.h +EXTRA_DIST = dirent.c dirent.h unistd.h config.h diff --git a/src/platform/visualc/Makefile.in b/src/platform/visualc/Makefile.in new file mode 100644 index 0000000..7d59572 --- /dev/null +++ b/src/platform/visualc/Makefile.in @@ -0,0 +1,205 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +EXTRA_DIST = dirent.c dirent.h unistd.h config.h +subdir = src/platform/visualc +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +DIST_COMMON = Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/platform/visualc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: +tags: TAGS +TAGS: + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic uninstall uninstall-am uninstall-info-am + +# 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/platform/visualc/config.h b/src/platform/visualc/config.h index fb714ee..9ad95e1 100644 --- a/src/platform/visualc/config.h +++ b/src/platform/visualc/config.h @@ -1,77 +1,5 @@ -#define VERSION "0.72" - -/* Define to 1 to enable internal debugger, requires libcurses */ -#define C_DEBUG 0 - -/* Define to 1 to enable screenshots, requires libpng */ -#define C_SSHOT 1 - -/* Define to 1 to use opengl display output support */ -#define C_OPENGL 1 - -/* Define to 1 to enable internal modem support, requires SDL_net */ -#define C_MODEM 1 - -/* Define to 1 to enable IPX networking support, requires SDL_net */ -#define C_IPX 1 - -/* Enable some heavy debugging options */ -#define C_HEAVY_DEBUG 0 - -/* The type of cpu this host has */ -#define C_TARGETCPU X86 -//#define C_TARGETCPU X86_64 - -/* Define to 1 to use x86 dynamic cpu core */ -#define C_DYNAMIC_X86 1 - -/* Define to 1 to use recompiling cpu core. Can not be used together with the dynamic-x86 core */ -#define C_DYNREC 0 - -/* Enable memory function inlining in */ -#define C_CORE_INLINE 0 - -/* Enable the FPU module, still only for beta testing */ -#define C_FPU 1 - -/* Define to 1 to use a x86 assembly fpu core */ -#define C_FPU_X86 1 - -/* Define to 1 to use a unaligned memory access */ -#define C_UNALIGNED_MEMORY 1 - -/* environ is defined */ -#define ENVIRON_INCLUDED 1 - -/* environ can be linked */ -#define ENVIRON_LINKED 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DDRAW_H 1 - -/* Define to 1 if you want serial passthrough support (Win32 only). */ -#define C_DIRECTSERIAL 1 - -#define GCC_ATTRIBUTE(x) /* attribute not supported */ -#define GCC_UNLIKELY(x) (x) - -#define INLINE __forceinline -#define DB_FASTCALL __fastcall - -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#pragma warning(disable : 4996) -#endif - -typedef double Real64; -/* The internal types */ -typedef unsigned char Bit8u; -typedef signed char Bit8s; -typedef unsigned short Bit16u; -typedef signed short Bit16s; -typedef unsigned long Bit32u; -typedef signed long Bit32s; -typedef unsigned __int64 Bit64u; -typedef signed __int64 Bit64s; -typedef unsigned int Bitu; -typedef signed int Bits; - +#define INLINE __forceinline + +#define VERSION "0.50" + +/* Euhm */ diff --git a/src/platform/visualc/dirent.c b/src/platform/visualc/dirent.c index 531c173..1f8df13 100644 --- a/src/platform/visualc/dirent.c +++ b/src/platform/visualc/dirent.c @@ -1,97 +1,93 @@ -/* - * Implementation of the standard functions in direct.h - * - * opendir(), readdir(), closedir() and rewinddir(). - * - * 06/17/2000 by Mike Haaland - */ - -#include "dirent.h" -#include "io.h" - -#define safe_strncpy_dirent(a,b,n) do { strncpy((a),(b),(n)-1); (a)[(n)-1] = 0; } while (0) - -#ifdef WIN32 - -/** open the current directory and return a structure - * to be used in subsequent readdir() and closedir() - * calls. - * - * returns NULL if one error. - */ -DIR * opendir(const char *dirname) { - - static DIR dir; - size_t len; - - /* Stash the directory name */ - safe_strncpy_dirent(dir.pathName,dirname,260); - - len = strlen(dirname); - if ((len>0) && (dirname[len-1]=='\\')) strcat(dir.pathName,"*.*"); - else strcat(dir.pathName,"\\*.*"); - - /* set the handle to invalid and set the firstTime flag */ - dir.handle = INVALID_HANDLE_VALUE; - dir.firstTime = TRUE; - - /* Change the current directory to the one requested */ - return (access(dirname,0) ? NULL : &dir); -} - -/** Close the current directory - return 0 if success */ -int closedir(DIR *dirp) { - /* reset ourselves to the first file in the directory - * - * We just close the current handle and reset for the - * next readdir call - */ - int result = 1; - - if (dirp->handle != INVALID_HANDLE_VALUE) - { - result = FindClose(dirp->handle); - dirp->handle = INVALID_HANDLE_VALUE; - } - - return (result == 0) ? 1 : 0; -} - -/** get the next entry in the directory */ -struct dirent * readdir(DIR *dirp) { - static struct dirent d; - - if (TRUE == dirp->firstTime) - { - /** Get the first entry in the directory */ - dirp->handle = FindFirstFile(dirp->pathName, &dirp->findFileData); - dirp->firstTime = FALSE; - if (INVALID_HANDLE_VALUE == dirp->handle) - { - return NULL; - } - } - else - { - int result = FindNextFile(dirp->handle, &dirp->findFileData); - if (0 == result ) - { - return NULL; - } - } - /* we have a valid FIND_FILE_DATA, copy the filename */ - memset(&d,'\0', sizeof(struct dirent)); - - safe_strncpy_dirent(d.d_name,dirp->findFileData.cFileName,260); - d.d_namlen = (char)strlen(d.d_name); - - return &d; -} - -/** reopen the current directory */ -void rewinddir(DIR *dirp) { - closedir(dirp); - dirp->firstTime = TRUE; -} - -#endif +/* + * Implementation of the standard functions in direct.h + * + * opendir(), readdir(), closedir() and rewinddir(). + * + * 06/17/2000 by Mike Haaland + */ + +#include "dirent.h" + +#ifdef WIN32 + +/** open the current directory and return a structure + * to be used in subsequent readdir() and closedir() + * calls. + * + * returns NULL if one error. + */ +DIR * opendir(const char *dirname) { + + static DIR dir; + + /* Stash the directory name */ + strcpy(dir.pathName,dirname); + + /* set the handle to invalid and set the firstTime flag */ + dir.handle = INVALID_HANDLE_VALUE; + dir.firstTime = TRUE; + + if (strcmp(dirname, ".") == 0) { + return &dir; + } + + /* Change the current directory to the one requested */ + return (SetCurrentDirectory(dir.pathName) != 0) ? &dir : NULL; +} + +/** Close the current directory - return 0 if success */ +int closedir(DIR *dirp) { + /* reset ourselves to the first file in the directory + * + * We just close the current handle and reset for the + * next readdir call + */ + int result = 1; + + if (dirp->handle != INVALID_HANDLE_VALUE) + { + result = FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + } + + return (result == 0) ? 1 : 0; +} + +/** get the next entry in the directory */ +struct dirent * readdir(DIR *dirp) { + static struct dirent d; + + if (TRUE == dirp->firstTime) + { + /** Get the first entry in the directory */ + dirp->handle = FindFirstFile("*.*", &dirp->findFileData); + dirp->firstTime = FALSE; + if (INVALID_HANDLE_VALUE == dirp->handle) + { + return NULL; + } + } + else + { + int result = FindNextFile(dirp->handle, &dirp->findFileData); + if (0 == result ) + { + return NULL; + } + } + /* we have a valid FIND_FILE_DATA, copy the filename */ + memset(&d,'\0', sizeof(struct dirent)); + + strcpy(d.d_name,dirp->findFileData.cFileName); + d.d_namlen = strlen(d.d_name); + + return &d; +} + +/** reopen the current directory */ +void rewinddir(DIR *dirp) { + closedir(dirp); + dirp->firstTime = TRUE; +} + +#endif diff --git a/src/platform/visualc/dirent.h b/src/platform/visualc/dirent.h index 76d669e..c37dbb6 100644 --- a/src/platform/visualc/dirent.h +++ b/src/platform/visualc/dirent.h @@ -1,58 +1,58 @@ - - -/* - * Defines and structures used to implement the - * functionality standard in direct.h for: - * - * opendir(), readdir(), closedir() and rewinddir(). - * - * 06/17/2000 by Mike Haaland - */ -#ifndef _DIRENT_H_ -#define _DIRENT_H_ - -#ifdef _MSC_VER - - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -#if !defined(__GNUC__) -/* Convienience macros used with stat structures */ -#define S_ISDIR(x) (x & _S_IFDIR) -#define S_ISREG(x) (x & _S_IFREG) -#endif - - -/* Structure to keep track of the current directory status */ -typedef struct my_dir { - HANDLE handle; - WIN32_FIND_DATA findFileData; - BOOLEAN firstTime; - char pathName[MAX_PATH]; -} DIR; - -/* Standard directory name entry returned by readdir() */ -struct dirent { - char d_namlen; - char d_name[MAX_PATH]; -}; - -/* function prototypes */ -int closedir(DIR *dirp); -DIR * opendir(const char *dirname); -struct dirent * readdir(DIR *dirp); -void rewinddir(DIR *dirp); - -#ifdef __cplusplus -} -#endif - -#endif -#endif - + + +/* + * Defines and structures used to implement the + * functionality standard in direct.h for: + * + * opendir(), readdir(), closedir() and rewinddir(). + * + * 06/17/2000 by Mike Haaland + */ +#ifndef _DIRENT_H_ +#define _DIRENT_H_ + +#ifdef _MSC_VER + + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#if !defined(__GNUC__) +/* Convienience macros used with stat structures */ +#define S_ISDIR(x) (x & _S_IFDIR) +#define S_ISREG(x) (x & _S_IFREG) +#endif + + +/* Structure to keep track of the current directory status */ +typedef struct my_dir { + HANDLE handle; + WIN32_FIND_DATA findFileData; + BOOLEAN firstTime; + char pathName[MAX_PATH]; +} DIR; + +/* Standard directory name entry returned by readdir() */ +struct dirent { + char d_namlen; + char d_name[MAX_PATH]; +}; + +/* function prototypes */ +int closedir(DIR *dirp); +DIR * opendir(const char *dirname); +struct dirent * readdir(DIR *dirp); +void rewinddir(DIR *dirp); + +#ifdef __cplusplus +} +#endif + +#endif +#endif + diff --git a/src/platform/visualc/ntddcdrm.h b/src/platform/visualc/ntddcdrm.h deleted file mode 100644 index b2e592c..0000000 --- a/src/platform/visualc/ntddcdrm.h +++ /dev/null @@ -1,320 +0,0 @@ -/* - * ntddcdrm.h - * - * CDROM IOCTL interface. - * - * This file is part of the w32api package. - * - * Contributors: - * Created by Casper S. Hornstrup - * - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#ifndef __NTDDCDRM_H -#define __NTDDCDRM_H - -#if __GNUC__ >=3 -#pragma GCC system_header -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#pragma pack(push,4) - -#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM - -#define IOCTL_CDROM_CHECK_VERIFY \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_FIND_NEW_DEVICES \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_GET_CONTROL \ - CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_GET_DRIVE_GEOMETRY \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_GET_LAST_SESSION \ - CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_GET_VOLUME \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_PAUSE_AUDIO \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_PLAY_AUDIO_MSF \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_RAW_READ \ - CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) - -#define IOCTL_CDROM_READ_Q_CHANNEL \ - CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_READ_TOC \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_READ_TOC_EX \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_RESUME_AUDIO \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_SEEK_AUDIO_MSF \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_SET_VOLUME \ - CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_SIMBAD \ - CTL_CODE(IOCTL_CDROM_BASE, 0x1003, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_STOP_AUDIO \ - CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS) - - -#define MAXIMUM_NUMBER_TRACKS 100 -#define MAXIMUM_CDROM_SIZE 804 -#define MINIMUM_CDROM_READ_TOC_EX_SIZE 2 - -typedef struct _TRACK_DATA { - UCHAR Reserved; - UCHAR Control : 4; - UCHAR Adr : 4; - UCHAR TrackNumber; - UCHAR Reserved1; - UCHAR Address[4]; -} TRACK_DATA, *PTRACK_DATA; - -/* CDROM_DISK_DATA.DiskData flags */ -#define CDROM_DISK_AUDIO_TRACK 0x00000001 -#define CDROM_DISK_DATA_TRACK 0x00000002 - -typedef struct _CDROM_DISK_DATA { - ULONG DiskData; -} CDROM_DISK_DATA, *PCDROM_DISK_DATA; - -typedef struct _CDROM_PLAY_AUDIO_MSF { - UCHAR StartingM; - UCHAR StartingS; - UCHAR StartingF; - UCHAR EndingM; - UCHAR EndingS; - UCHAR EndingF; -} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF; - -/* CDROM_READ_TOC_EX.Format constants */ -#define CDROM_READ_TOC_EX_FORMAT_TOC 0x00 -#define CDROM_READ_TOC_EX_FORMAT_SESSION 0x01 -#define CDROM_READ_TOC_EX_FORMAT_FULL_TOC 0x02 -#define CDROM_READ_TOC_EX_FORMAT_PMA 0x03 -#define CDROM_READ_TOC_EX_FORMAT_ATIP 0x04 -#define CDROM_READ_TOC_EX_FORMAT_CDTEXT 0x05 - -typedef struct _CDROM_READ_TOC_EX { - UCHAR Format : 4; - UCHAR Reserved1 : 3; - UCHAR Msf : 1; - UCHAR SessionTrack; - UCHAR Reserved2; - UCHAR Reserved3; -} CDROM_READ_TOC_EX, *PCDROM_READ_TOC_EX; - -typedef struct _CDROM_SEEK_AUDIO_MSF { - UCHAR M; - UCHAR S; - UCHAR F; -} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF; - -/* CDROM_SUB_Q_DATA_FORMAT.Format constants */ -#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00 -#define IOCTL_CDROM_CURRENT_POSITION 0x01 -#define IOCTL_CDROM_MEDIA_CATALOG 0x02 -#define IOCTL_CDROM_TRACK_ISRC 0x03 - -typedef struct _CDROM_SUB_Q_DATA_FORMAT { - UCHAR Format; - UCHAR Track; -} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; - -typedef struct _CDROM_TOC { - UCHAR Length[2]; - UCHAR FirstTrack; - UCHAR LastTrack; - TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]; -} CDROM_TOC, *PCDROM_TOC; - -#define CDROM_TOC_SIZE sizeof(CDROM_TOC) - -typedef struct _CDROM_TOC_ATIP_DATA_BLOCK { - UCHAR CdrwReferenceSpeed : 3; - UCHAR Reserved3 : 1; - UCHAR WritePower : 3; - UCHAR True1 : 1; - UCHAR Reserved4 : 6; - UCHAR UnrestrictedUse : 1; - UCHAR Reserved5 : 1; - UCHAR A3Valid : 1; - UCHAR A2Valid : 1; - UCHAR A1Valid : 1; - UCHAR Reserved6 : 3; - UCHAR IsCdrw : 1; - UCHAR True2 : 1; - UCHAR Reserved7; - UCHAR LeadInMsf[3]; - UCHAR Reserved8; - UCHAR LeadOutMsf[3]; - UCHAR Reserved9; - UCHAR A1Values[3]; - UCHAR Reserved10; - UCHAR A2Values[3]; - UCHAR Reserved11; - UCHAR A3Values[3]; - UCHAR Reserved12; -} CDROM_TOC_ATIP_DATA_BLOCK, *PCDROM_TOC_ATIP_DATA_BLOCK; - -/* CDROM_TOC_CD_TEXT_DATA_BLOCK.PackType constants */ -#define CDROM_CD_TEXT_PACK_ALBUM_NAME 0x80 -#define CDROM_CD_TEXT_PACK_PERFORMER 0x81 -#define CDROM_CD_TEXT_PACK_SONGWRITER 0x82 -#define CDROM_CD_TEXT_PACK_COMPOSER 0x83 -#define CDROM_CD_TEXT_PACK_ARRANGER 0x84 -#define CDROM_CD_TEXT_PACK_MESSAGES 0x85 -#define CDROM_CD_TEXT_PACK_DISC_ID 0x86 -#define CDROM_CD_TEXT_PACK_GENRE 0x87 -#define CDROM_CD_TEXT_PACK_TOC_INFO 0x88 -#define CDROM_CD_TEXT_PACK_TOC_INFO2 0x89 -#define CDROM_CD_TEXT_PACK_UPC_EAN 0x8e -#define CDROM_CD_TEXT_PACK_SIZE_INFO 0x8f - -typedef struct _CDROM_TOC_CD_TEXT_DATA_BLOCK { - UCHAR PackType; - UCHAR TrackNumber : 7; - UCHAR ExtensionFlag : 1; - UCHAR SequenceNumber; - UCHAR CharacterPosition : 4; - UCHAR BlockNumber : 3; - UCHAR Unicode : 1; - union { - UCHAR Text[12]; - WCHAR WText[6]; - }; - UCHAR CRC[2]; -} CDROM_TOC_CD_TEXT_DATA_BLOCK, *PCDROM_TOC_CD_TEXT_DATA_BLOCK; - -/* CDROM_TOC_FULL_TOC_DATA_BLOCK.Adr constants */ -#define ADR_NO_MODE_INFORMATION 0x0 -#define ADR_ENCODES_CURRENT_POSITION 0x1 -#define ADR_ENCODES_MEDIA_CATALOG 0x2 -#define ADR_ENCODES_ISRC 0x3 - -typedef struct _CDROM_TOC_FULL_TOC_DATA_BLOCK { - UCHAR SessionNumber; - UCHAR Control : 4; - UCHAR Adr : 4; - UCHAR Reserved1; - UCHAR Point; - UCHAR MsfExtra[3]; - UCHAR Zero; - UCHAR Msf[3]; -} CDROM_TOC_FULL_TOC_DATA_BLOCK, *PCDROM_TOC_FULL_TOC_DATA_BLOCK; - -/* SUB_Q_HEADER.AudioStatus constants */ -#define AUDIO_STATUS_NOT_SUPPORTED 0x00 -#define AUDIO_STATUS_IN_PROGRESS 0x11 -#define AUDIO_STATUS_PAUSED 0x12 -#define AUDIO_STATUS_PLAY_COMPLETE 0x13 -#define AUDIO_STATUS_PLAY_ERROR 0x14 -#define AUDIO_STATUS_NO_STATUS 0x15 - -typedef struct _SUB_Q_HEADER { - UCHAR Reserved; - UCHAR AudioStatus; - UCHAR DataLength[2]; -} SUB_Q_HEADER, *PSUB_Q_HEADER; - -typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Reserved[3]; - UCHAR Reserved1 : 7; - UCHAR Mcval :1; - UCHAR MediaCatalog[15]; -} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; - -typedef struct _SUB_Q_TRACK_ISRC { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Reserved0; - UCHAR Track; - UCHAR Reserved1; - UCHAR Reserved2 : 7; - UCHAR Tcval : 1; - UCHAR TrackIsrc[15]; -} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC; - -typedef struct _SUB_Q_CURRENT_POSITION { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Control : 4; - UCHAR ADR : 4; - UCHAR TrackNumber; - UCHAR IndexNumber; - UCHAR AbsoluteAddress[4]; - UCHAR TrackRelativeAddress[4]; -} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION; - -typedef union _SUB_Q_CHANNEL_DATA { - SUB_Q_CURRENT_POSITION CurrentPosition; - SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog; - SUB_Q_TRACK_ISRC TrackIsrc; -} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA; - -/* CDROM_AUDIO_CONTROL.LbaFormat constants */ -#define AUDIO_WITH_PREEMPHASIS 0x1 -#define DIGITAL_COPY_PERMITTED 0x2 -#define AUDIO_DATA_TRACK 0x4 -#define TWO_FOUR_CHANNEL_AUDIO 0x8 - -typedef struct _CDROM_AUDIO_CONTROL { - UCHAR LbaFormat; - USHORT LogicalBlocksPerSecond; -} CDROM_AUDIO_CONTROL, *PCDROM_AUDIO_CONTROL; - -typedef struct _VOLUME_CONTROL { - UCHAR PortVolume[4]; -} VOLUME_CONTROL, *PVOLUME_CONTROL; - -typedef enum _TRACK_MODE_TYPE { - YellowMode2, - XAForm2, - CDDA -} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; - -typedef struct __RAW_READ_INFO { - LARGE_INTEGER DiskOffset; - ULONG SectorCount; - TRACK_MODE_TYPE TrackMode; -} RAW_READ_INFO, *PRAW_READ_INFO; - -#pragma pack(pop) - -#ifdef __cplusplus -} -#endif - -#endif /* __NTDDCDRM_H */ diff --git a/src/platform/visualc/ntddscsi.h b/src/platform/visualc/ntddscsi.h deleted file mode 100644 index 387862c..0000000 --- a/src/platform/visualc/ntddscsi.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * ntddscsi.h - * - * SCSI port IOCTL interface. - * - * This file is part of the w32api package. - * - * Contributors: - * Created by Casper S. Hornstrup - * - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#ifndef __NTDDSCSI_H -#define __NTDDSCSI_H - -#if __GNUC__ >=3 -#pragma GCC system_header -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#pragma pack(push,4) - -//#include "ntddk.h" - -#define DD_SCSI_DEVICE_NAME "\\Device\\ScsiPort" -#define DD_SCSI_DEVICE_NAME_U L"\\Device\\ScsiPort" - -#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER - -#define IOCTL_SCSI_GET_INQUIRY_DATA \ - CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_SCSI_GET_CAPABILITIES \ - CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_SCSI_GET_ADDRESS \ - CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_SCSI_MINIPORT \ - CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_SCSI_PASS_THROUGH \ - CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_SCSI_PASS_THROUGH_DIRECT \ - CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_SCSI_RESCAN_BUS \ - CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS) - - -DEFINE_GUID(ScsiRawInterfaceGuid, 0x53f56309L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); - -DEFINE_GUID(WmiScsiAddressGuid, 0x53f5630fL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); - -typedef struct _SCSI_PASS_THROUGH { - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - ULONG_PTR DataBufferOffset; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; - -typedef struct _SCSI_PASS_THROUGH_DIRECT { - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - PVOID DataBuffer; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; - -typedef struct _SRB_IO_CONTROL { - ULONG HeaderLength; - UCHAR Signature[8]; - ULONG Timeout; - ULONG ControlCode; - ULONG ReturnCode; - ULONG Length; -} SRB_IO_CONTROL, *PSRB_IO_CONTROL; - -typedef struct _SCSI_ADDRESS { - ULONG Length; - UCHAR PortNumber; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; -} SCSI_ADDRESS, *PSCSI_ADDRESS; - -typedef struct _SCSI_BUS_DATA { - UCHAR NumberOfLogicalUnits; - UCHAR InitiatorBusId; - ULONG InquiryDataOffset; -}SCSI_BUS_DATA, *PSCSI_BUS_DATA; - -typedef struct _SCSI_ADAPTER_BUS_INFO { - UCHAR NumberOfBuses; - SCSI_BUS_DATA BusData[1]; -} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; - -typedef struct _IO_SCSI_CAPABILITIES { - ULONG Length; - ULONG MaximumTransferLength; - ULONG MaximumPhysicalPages; - ULONG SupportedAsynchronousEvents; - ULONG AlignmentMask; - BOOLEAN TaggedQueuing; - BOOLEAN AdapterScansDown; - BOOLEAN AdapterUsesPio; -} IO_SCSI_CAPABILITIES, *PIO_SCSI_CAPABILITIES; - -typedef struct _SCSI_INQUIRY_DATA { - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - BOOLEAN DeviceClaimed; - ULONG InquiryDataLength; - ULONG NextInquiryDataOffset; - UCHAR InquiryData[1]; -} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; - -#define SCSI_IOCTL_DATA_OUT 0 -#define SCSI_IOCTL_DATA_IN 1 -#define SCSI_IOCTL_DATA_UNSPECIFIED 2 - -/* -typedef struct _DUMP_POINTERS { - PADAPTER_OBJECT AdapterObject; - PVOID MappedRegisterBase; - PVOID DumpData; - PVOID CommonBufferVa; - LARGE_INTEGER CommonBufferPa; - ULONG CommonBufferSize; - BOOLEAN AllocateCommonBuffers; - BOOLEAN UseDiskDump; - UCHAR Spare1[2]; - PVOID DeviceObject; -} DUMP_POINTERS, *PDUMP_POINTERS; -*/ -#pragma pack(pop) - -#ifdef __cplusplus -} -#endif - -#endif /* __NTDDSCSI_H */ diff --git a/src/platform/visualc/unistd.h b/src/platform/visualc/unistd.h index 65ce389..8f51f76 100644 --- a/src/platform/visualc/unistd.h +++ b/src/platform/visualc/unistd.h @@ -1,10 +1,10 @@ -/* - * This file is part of the Mingw32 package. - * - * unistd.h maps (roughly) to io.h - */ - -#ifndef __STRICT_ANSI__ -#include -#endif - +/* + * This file is part of the Mingw32 package. + * + * unistd.h maps (roughly) to io.h + */ + +#ifndef __STRICT_ANSI__ +#include +#endif + diff --git a/src/shell/Makefile.am b/src/shell/Makefile.am index 772a0e9..a9476e9 100644 --- a/src/shell/Makefile.am +++ b/src/shell/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include - -noinst_LIBRARIES = libshell.a -libshell_a_SOURCES = shell.cpp shell_batch.cpp shell_cmds.cpp shell_misc.cpp +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libshell.a +libshell_a_SOURCES = shell.cpp shell_batch.cpp shell_cmds.cpp shell_inc.h shell_misc.cpp diff --git a/src/shell/Makefile.in b/src/shell/Makefile.in new file mode 100644 index 0000000..f167e5a --- /dev/null +++ b/src/shell/Makefile.in @@ -0,0 +1,312 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +AM_CPPFLAGS = -I$(top_srcdir)/include + +noinst_LIBRARIES = libshell.a +libshell_a_SOURCES = shell.cpp shell_batch.cpp shell_cmds.cpp shell_inc.h shell_misc.cpp +subdir = src/shell +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libshell_a_AR = $(AR) cru +libshell_a_LIBADD = +am_libshell_a_OBJECTS = shell.$(OBJEXT) shell_batch.$(OBJEXT) \ + shell_cmds.$(OBJEXT) shell_misc.$(OBJEXT) +libshell_a_OBJECTS = $(am_libshell_a_OBJECTS) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/shell.Po ./$(DEPDIR)/shell_batch.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/shell_cmds.Po ./$(DEPDIR)/shell_misc.Po +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +CXXFLAGS = @CXXFLAGS@ +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libshell_a_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libshell_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/shell/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +AR = ar + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libshell.a: $(libshell_a_OBJECTS) $(libshell_a_DEPENDENCIES) + -rm -f libshell.a + $(libshell_a_AR) libshell.a $(libshell_a_OBJECTS) $(libshell_a_LIBADD) + $(RANLIB) libshell.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shell.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shell_batch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shell_cmds.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shell_misc.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.cpp.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.cpp.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CXXCOMPILE) -c -o $@ `cygpath -w $<` +CXXDEPMODE = @CXXDEPMODE@ +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic tags uninstall uninstall-am \ + uninstall-info-am + +# 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/shell/shell.cpp b/src/shell/shell.cpp index 10a8210..63e4dad 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -1,636 +1,177 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: shell.cpp,v 1.98 2009/03/23 10:55:36 qbix79 Exp $ */ - -#include -#include -#include -#include "dosbox.h" -#include "regs.h" -#include "control.h" -#include "shell.h" -#include "callback.h" -#include "support.h" - - -Bitu call_shellstop; -/* Larger scope so shell_del autoexec can use it to - * remove things from the environment */ -Program * first_shell = 0; - -static Bitu shellstop_handler(void) { - return CBRET_STOP; -} - -static void SHELL_ProgramStart(Program * * make) { - *make = new DOS_Shell; -} - -#define AUTOEXEC_SIZE 4096 -static char autoexec_data[AUTOEXEC_SIZE] = { 0 }; -static std::list autoexec_strings; -typedef std::list::iterator auto_it; - -void VFILE_Remove(const char *name); - -void AutoexecObject::Install(const std::string &in) { - if(GCC_UNLIKELY(installed)) E_Exit("autoexec: allready created %s",buf.c_str()); - installed = true; - buf = in; - autoexec_strings.push_back(buf); - this->CreateAutoexec(); - - //autoexec.bat is normally created AUTOEXEC_Init. - //But if we are allready running (first_shell) - //we have to update the envirionment to display changes - - if(first_shell) { - //create a copy as the string will be modified - std::string::size_type n = buf.size(); - char* buf2 = new char[n + 1]; - safe_strncpy(buf2, buf.c_str(), n + 1); - if((strncasecmp(buf2,"set ",4) == 0) && (strlen(buf2) > 4)){ - char* after_set = buf2 + 4;//move to variable that is being set - char* test = strpbrk(after_set,"="); - if(!test) {first_shell->SetEnv(after_set,"");return;} - *test++ = 0; - //If the shell is running/exists update the environment - first_shell->SetEnv(after_set,test); - } - delete [] buf2; - } -} - -void AutoexecObject::InstallBefore(const std::string &in) { - if(GCC_UNLIKELY(installed)) E_Exit("autoexec: allready created %s",buf.c_str()); - installed = true; - buf = in; - autoexec_strings.push_front(buf); - this->CreateAutoexec(); -} - -void AutoexecObject::CreateAutoexec(void) { - /* Remove old autoexec.bat if the shell exists */ - if(first_shell) VFILE_Remove("AUTOEXEC.BAT"); - - //Create a new autoexec.bat - autoexec_data[0] = 0; - size_t auto_len; - for(auto_it it= autoexec_strings.begin(); it != autoexec_strings.end(); it++) { - auto_len = strlen(autoexec_data); - if ((auto_len+(*it).length()+3)>AUTOEXEC_SIZE) { - E_Exit("SYSTEM:Autoexec.bat file overflow"); - } - sprintf((autoexec_data+auto_len),"%s\r\n",(*it).c_str()); - } - if(first_shell) VFILE_Register("AUTOEXEC.BAT",(Bit8u *)autoexec_data,(Bit32u)strlen(autoexec_data)); -} - -AutoexecObject::~AutoexecObject(){ - if(!installed) return; - - // Remove the line from the autoexecbuffer and update environment - for(auto_it it = autoexec_strings.begin(); it != autoexec_strings.end(); ) { - if((*it) == buf) { - it = autoexec_strings.erase(it); - std::string::size_type n = buf.size(); - char* buf2 = new char[n + 1]; - safe_strncpy(buf2, buf.c_str(), n + 1); - // If it's a environment variable remove it from there as well - if((strncasecmp(buf2,"set ",4) == 0) && (strlen(buf2) > 4)){ - char* after_set = buf2 + 4;//move to variable that is being set - char* test = strpbrk(after_set,"="); - if(!test) continue; - *test = 0; - //If the shell is running/exists update the environment - if(first_shell) first_shell->SetEnv(after_set,""); - } - delete [] buf2; - } else it++; - } - this->CreateAutoexec(); -} - -DOS_Shell::DOS_Shell():Program(){ - input_handle=STDIN; - echo=true; - exit=false; - bf=0; - call=false; - completion_start = NULL; -} - -Bitu DOS_Shell::GetRedirection(char *s, char **ifn, char **ofn,bool * append) { - - char * lr=s; - char * lw=s; - char ch; - Bitu num=0; - bool quote = false; - - while ( (ch=*lr++) ) { - if(quote && ch != '"') { /* don't parse redirection within quotes. Not perfect yet. Escaped quotes will mess the count up */ - *lw++ = ch; - continue; - } - - switch (ch) { - case '"': - quote = !quote; - break; - case '>': - *append=((*lr)=='>'); - if (*append) lr++; - lr=ltrim(lr); - if (*ofn) free(*ofn); - *ofn=lr; - while (*lr && *lr!=' ') lr++; - //if it ends on a : => remove it. - if((*ofn != lr) && (lr[-1] == ':')) lr[-1] = 0; - if(*lr && *(lr+1)) - *lr++=0; - else - *lr=0; - *ofn=strdup(*ofn); - continue; - case '<': - if (*ifn) free(*ifn); - lr=ltrim(lr); - *ifn=lr; - while (*lr && *lr!=' ') lr++; - if((*ifn != lr) && (lr[-1] == ':')) lr[-1] = 0; - if(*lr && *(lr+1)) - *lr++=0; - else - *lr=0; - *ifn=strdup(*ifn); - continue; - case '|': - ch=0; - num++; - } - *lw++=ch; - } - *lw=0; - return num; -} - -void DOS_Shell::ParseLine(char * line) { - LOG(LOG_EXEC,LOG_ERROR)("Parsing command line: %s",line); - /* Check for a leading @ */ - if (line[0] == '@') line[0] = ' '; - line = trim(line); - - /* Do redirection and pipe checks */ - - char * in = 0; - char * out = 0; - - Bit16u dummy,dummy2; - Bit32u bigdummy = 0; - Bitu num = 0; /* Number of commands in this line */ - bool append; - bool normalstdin = false; /* wether stdin/out are open on start. */ - bool normalstdout = false; /* Bug: Assumed is they are "con" */ - - num = GetRedirection(line,&in, &out,&append); - if (num>1) LOG_MSG("SHELL:Multiple command on 1 line not supported"); - if (in || out) { - normalstdin = (psp->GetFileHandle(0) != 0xff); - normalstdout = (psp->GetFileHandle(1) != 0xff); - } - if (in) { - if(DOS_OpenFile(in,OPEN_READ,&dummy)) { //Test if file exists - DOS_CloseFile(dummy); - LOG_MSG("SHELL:Redirect input from %s",in); - if(normalstdin) DOS_CloseFile(0); //Close stdin - DOS_OpenFile(in,OPEN_READ,&dummy); //Open new stdin - } - } - if (out){ - LOG_MSG("SHELL:Redirect output to %s",out); - if(normalstdout) DOS_CloseFile(1); - if(!normalstdin && !in) DOS_OpenFile("con",OPEN_READWRITE,&dummy); - bool status = true; - /* Create if not exist. Open if exist. Both in read/write mode */ - if(append) { - if( (status = DOS_OpenFile(out,OPEN_READWRITE,&dummy)) ) { - DOS_SeekFile(1,&bigdummy,DOS_SEEK_END); - } else { - status = DOS_CreateFile(out,DOS_ATTR_ARCHIVE,&dummy); //Create if not exists. - } - } else { - status = DOS_OpenFileExtended(out,OPEN_READWRITE,DOS_ATTR_ARCHIVE,0x12,&dummy,&dummy2); - } - - if(!status && normalstdout) DOS_OpenFile("con",OPEN_READWRITE,&dummy); //Read only file, open con again - if(!normalstdin && !in) DOS_CloseFile(0); - } - /* Run the actual command */ - DoCommand(line); - /* Restore handles */ - if(in) { - DOS_CloseFile(0); - if(normalstdin) DOS_OpenFile("con",OPEN_READWRITE,&dummy); - free(in); - } - if(out) { - DOS_CloseFile(1); - if(!normalstdin) DOS_OpenFile("con",OPEN_READWRITE,&dummy); - if(normalstdout) DOS_OpenFile("con",OPEN_READWRITE,&dummy); - if(!normalstdin) DOS_CloseFile(0); - free(out); - } -} - - - -void DOS_Shell::RunInternal(void) -{ - char input_line[CMD_MAXLINE] = {0}; - while(bf && bf->ReadLine(input_line)) - { - if (echo) { - if (input_line[0] != '@') { - ShowPrompt(); - WriteOut_NoParsing(input_line); - WriteOut_NoParsing("\n"); - }; - }; - ParseLine(input_line); - } - return; -} - -void DOS_Shell::Run(void) { - char input_line[CMD_MAXLINE] = {0}; - std::string line; - if (cmd->FindStringRemain("/C",line)) { - strcpy(input_line,line.c_str()); - DOS_Shell temp; - temp.echo = echo; - temp.ParseLine(input_line); //for *.exe *.com |*.bat creates the bf needed by runinternal; - temp.RunInternal(); // exits when no bf is found. - return; - } - /* Start a normal shell and check for a first command init */ - WriteOut(MSG_Get("SHELL_STARTUP_BEGIN"),VERSION); -#if C_DEBUG - WriteOut(MSG_Get("SHELL_STARTUP_DEBUG")); -#endif - if (machine == MCH_CGA) WriteOut(MSG_Get("SHELL_STARTUP_CGA")); - WriteOut(MSG_Get("SHELL_STARTUP_END")); - - if (cmd->FindString("/INIT",line,true)) { - strcpy(input_line,line.c_str()); - line.erase(); - ParseLine(input_line); - } - do { - if (bf){ - if(bf->ReadLine(input_line)) { - if (echo) { - if (input_line[0]!='@') { - ShowPrompt(); - WriteOut_NoParsing(input_line); - WriteOut_NoParsing("\n"); - }; - }; - ParseLine(input_line); - if (echo) WriteOut("\n"); - } - } else { - if (echo) ShowPrompt(); - InputCommand(input_line); - ParseLine(input_line); - if (echo && !bf) WriteOut_NoParsing("\n"); - } - } while (!exit); -} - -void DOS_Shell::SyntaxError(void) { - WriteOut(MSG_Get("SHELL_SYNTAXERROR")); -} - -class AUTOEXEC:public Module_base { -private: - AutoexecObject autoexec[17]; - AutoexecObject autoexec_echo; -public: - AUTOEXEC(Section* configuration):Module_base(configuration) { - /* Register a virtual AUOEXEC.BAT file */ - std::string line; - Section_line * section=static_cast(configuration); - - /* Check -securemode switch to disable mount/imgmount/boot after running autoexec.bat */ - bool secure = control->cmdline->FindExist("-securemode",true); - - /* add stuff from the configfile unless -noautexec or -securemode is specified. */ - char * extra = const_cast(section->data.c_str()); - if (extra && !secure && !control->cmdline->FindExist("-noautoexec",true)) { - /* detect if "echo off" is the first line */ - bool echo_off = !strncasecmp(extra,"echo off",8); - if (!echo_off) echo_off = !strncasecmp(extra,"@echo off",9); - - /* if "echo off" add it to the front of autoexec.bat */ - if(echo_off) autoexec_echo.InstallBefore("@echo off"); - - /* Install the stuff from the configfile */ - autoexec[0].Install(section->data); - } - - /* Check to see for extra command line options to be added (before the command specified on commandline) */ - /* Maximum of extra commands: 10 */ - Bitu i = 1; - while (control->cmdline->FindString("-c",line,true) && (i <= 11)) { -#if defined (WIN32) || defined (OS2) - //replace single with double quotes so that mount commands can contain spaces - for(Bitu temp = 0;temp < line.size();++temp) if(line[temp] == '\'') line[temp]='\"'; -#endif //Linux users can simply use \" in their shell - autoexec[i++].Install(line); - } - - /* Check for the -exit switch which causes dosbox to when the command on the commandline has finished */ - bool addexit = control->cmdline->FindExist("-exit",true); - - /* Check for first command being a directory or file */ - char buffer[CROSS_LEN]; - char cross_filesplit[2] = {CROSS_FILESPLIT , 0}; - /* Combining -securemode and no parameter leaves you with a lovely Z:\. */ - if ( !control->cmdline->FindCommand(1,line) ) { - if ( secure ) autoexec[12].Install("z:\\config.com -securemode"); - } else { - struct stat test; - strcpy(buffer,line.c_str()); - if (stat(buffer,&test)){ - getcwd(buffer,CROSS_LEN); - strcat(buffer,cross_filesplit); - strcat(buffer,line.c_str()); - if (stat(buffer,&test)) goto nomount; - } - if (test.st_mode & S_IFDIR) { - autoexec[12].Install(std::string("MOUNT C \"") + buffer + "\""); - autoexec[13].Install("C:"); - if(secure) autoexec[14].Install("z:\\config.com -securemode"); - } else { - char* name = strrchr(buffer,CROSS_FILESPLIT); - if (!name) { //Only a filename - line = buffer; - getcwd(buffer,CROSS_LEN); - strcat(buffer,cross_filesplit); - strcat(buffer,line.c_str()); - if(stat(buffer,&test)) goto nomount; - name = strrchr(buffer,CROSS_FILESPLIT); - if(!name) goto nomount; - } - *name++ = 0; - if (access(buffer,F_OK)) goto nomount; - autoexec[12].Install(std::string("MOUNT C \"") + buffer + "\""); - autoexec[13].Install("C:"); - upcase(name); - if(strstr(name,".BAT") != 0) { - if(secure) autoexec[14].Install("z:\\config.com -securemode"); - /* BATch files are called else exit will not work */ - autoexec[15].Install(std::string("CALL ") + name); - } else if((strstr(name,".IMG") != 0) || (strstr(name,".IMA") !=0)) { - //No secure mode here as boot is destructive and enabling securemode disables boot - /* Boot image files */ - autoexec[15].Install(std::string("BOOT ") + name); - } else { - if(secure) autoexec[14].Install("z:\\config.com -securemode"); - autoexec[15].Install(name); - } - - if(addexit) autoexec[16].Install("exit"); - } - } -nomount: - VFILE_Register("AUTOEXEC.BAT",(Bit8u *)autoexec_data,(Bit32u)strlen(autoexec_data)); - } -}; - -static AUTOEXEC* test; - -void AUTOEXEC_Init(Section * sec) { - test = new AUTOEXEC(sec); -} - -static char const * const path_string="PATH=Z:\\"; -static char const * const comspec_string="COMSPEC=Z:\\COMMAND.COM"; -static char const * const full_name="Z:\\COMMAND.COM"; -static char const * const init_line="/INIT AUTOEXEC.BAT"; - -void SHELL_Init() { - /* Add messages */ - MSG_Add("SHELL_ILLEGAL_PATH","Illegal Path.\n"); - MSG_Add("SHELL_CMD_HELP","If you want a list of all supported commands type \033[33;1mhelp /all\033[0m .\nA short list of the most often used commands:\n"); - MSG_Add("SHELL_CMD_ECHO_ON","ECHO is on.\n"); - MSG_Add("SHELL_CMD_ECHO_OFF","ECHO is off.\n"); - MSG_Add("SHELL_ILLEGAL_SWITCH","Illegal switch: %s.\n"); - MSG_Add("SHELL_MISSING_PARAMETER","Required parameter missing.\n"); - MSG_Add("SHELL_CMD_CHDIR_ERROR","Unable to change to: %s.\n"); - MSG_Add("SHELL_CMD_CHDIR_HINT","To change to different drive type \033[31m%c:\033[0m\n"); - MSG_Add("SHELL_CMD_CHDIR_HINT_2","directoryname is longer than 8 charachters and/or contains spaces.\nTry \033[31mcd %s\033[0m\n"); - MSG_Add("SHELL_CMD_CHDIR_HINT_3","You are still on drive Z:, change to a mounted drive with \033[31mC:\033[0m.\n"); - MSG_Add("SHELL_CMD_MKDIR_ERROR","Unable to make: %s.\n"); - MSG_Add("SHELL_CMD_RMDIR_ERROR","Unable to remove: %s.\n"); - MSG_Add("SHELL_CMD_DEL_ERROR","Unable to delete: %s.\n"); - MSG_Add("SHELL_SYNTAXERROR","The syntax of the command is incorrect.\n"); - MSG_Add("SHELL_CMD_SET_NOT_SET","Environment variable %s not defined.\n"); - MSG_Add("SHELL_CMD_SET_OUT_OF_SPACE","Not enough environment space left.\n"); - MSG_Add("SHELL_CMD_IF_EXIST_MISSING_FILENAME","IF EXIST: Missing filename.\n"); - MSG_Add("SHELL_CMD_IF_ERRORLEVEL_MISSING_NUMBER","IF ERRORLEVEL: Missing number.\n"); - MSG_Add("SHELL_CMD_IF_ERRORLEVEL_INVALID_NUMBER","IF ERRORLEVEL: Invalid number.\n"); - MSG_Add("SHELL_CMD_GOTO_MISSING_LABEL","No label supplied to GOTO command.\n"); - MSG_Add("SHELL_CMD_GOTO_LABEL_NOT_FOUND","GOTO: Label %s not found.\n"); - MSG_Add("SHELL_CMD_FILE_NOT_FOUND","File %s not found.\n"); - MSG_Add("SHELL_CMD_FILE_EXISTS","File %s already exists.\n"); - MSG_Add("SHELL_CMD_DIR_INTRO","Directory of %s.\n"); - MSG_Add("SHELL_CMD_DIR_BYTES_USED","%5d File(s) %17s Bytes.\n"); - MSG_Add("SHELL_CMD_DIR_BYTES_FREE","%5d Dir(s) %17s Bytes free.\n"); - MSG_Add("SHELL_EXECUTE_DRIVE_NOT_FOUND","Drive %c does not exist!\nYou must \033[31mmount\033[0m it first. Type \033[1;33mintro\033[0m or \033[1;33mintro mount\033[0m for more information.\n"); - MSG_Add("SHELL_EXECUTE_ILLEGAL_COMMAND","Illegal command: %s.\n"); - MSG_Add("SHELL_CMD_PAUSE","Press any key to continue.\n"); - MSG_Add("SHELL_CMD_PAUSE_HELP","Waits for 1 keystroke to continue.\n"); - MSG_Add("SHELL_CMD_COPY_FAILURE","Copy failure : %s.\n"); - MSG_Add("SHELL_CMD_COPY_SUCCESS"," %d File(s) copied.\n"); - MSG_Add("SHELL_CMD_SUBST_NO_REMOVE","Removing drive not supported. Doing nothing.\n"); - MSG_Add("SHELL_CMD_SUBST_FAILURE","SUBST failed. You either made an error in your commandline or the target drive is already used.\nIt's only possible to use SUBST on Local drives"); - - MSG_Add("SHELL_STARTUP_BEGIN", - "\033[44;1m\xC9\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBB\n" - "\xBA \033[32mWelcome to DOSBox v%-8s\033[37m \xBA\n" - "\xBA \xBA\n" -// "\xBA DOSBox runs real and protected mode games. \xBA\n" - "\xBA For a short introduction for new users type: \033[33mINTRO\033[37m \xBA\n" - "\xBA For supported shell commands type: \033[33mHELP\033[37m \xBA\n" - "\xBA \xBA\n" - "\xBA If you want more speed, try \033[31mctrl-F8\033[37m and \033[31mctrl-F12\033[37m. \xBA\n" - "\xBA To activate the keymapper \033[31mctrl-F1\033[37m. \xBA\n" - "\xBA For more information read the \033[36mREADME\033[37m file in the DOSBox directory. \xBA\n" - "\xBA \xBA\n" - ); - MSG_Add("SHELL_STARTUP_CGA","\xBA DOSBox supports Composite CGA mode. \xBA\n" - "\xBA Use \033[31m(alt-)F11\033[37m to change the colours when in this mode. \xBA\n" - "\xBA \xBA\n" - ); - MSG_Add("SHELL_STARTUP_DEBUG", - "\xBA Press \033[31malt-Pause\033[37m to enter the debugger or start the exe with \033[33mDEBUG\033[37m. \xBA\n" - "\xBA \xBA\n" - ); - MSG_Add("SHELL_STARTUP_END", - "\xBA \033[32mHAVE FUN!\033[37m \xBA\n" - "\xBA \033[32mThe DOSBox Team\033[37m \xBA\n" - "\xC8\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBC\033[0m\n" - //"\n" //Breaks the startup message if you type a mount and a drive change. - ); - MSG_Add("SHELL_CMD_CHDIR_HELP","Displays/changes the current directory.\n"); - MSG_Add("SHELL_CMD_CHDIR_HELP_LONG","CHDIR [drive:][path]\n" - "CHDIR [..]\n" - "CD [drive:][path]\n" - "CD [..]\n\n" - " .. Specifies that you want to change to the parent directory.\n\n" - "Type CD drive: to display the current directory in the specified drive.\n" - "Type CD without parameters to display the current drive and directory.\n"); - MSG_Add("SHELL_CMD_CLS_HELP","Clear screen.\n"); - MSG_Add("SHELL_CMD_DIR_HELP","Directory View.\n"); - MSG_Add("SHELL_CMD_ECHO_HELP","Display messages and enable/disable command echoing.\n"); - MSG_Add("SHELL_CMD_EXIT_HELP","Exit from the shell.\n"); - MSG_Add("SHELL_CMD_HELP_HELP","Show help.\n"); - MSG_Add("SHELL_CMD_MKDIR_HELP","Make Directory.\n"); - MSG_Add("SHELL_CMD_MKDIR_HELP_LONG","MKDIR [drive:][path]\n" - "MD [drive:][path]\n"); - MSG_Add("SHELL_CMD_RMDIR_HELP","Remove Directory.\n"); - MSG_Add("SHELL_CMD_RMDIR_HELP_LONG","RMDIR [drive:][path]\n" - "RD [drive:][path]\n"); - MSG_Add("SHELL_CMD_SET_HELP","Change environment variables.\n"); - MSG_Add("SHELL_CMD_IF_HELP","Performs conditional processing in batch programs.\n"); - MSG_Add("SHELL_CMD_GOTO_HELP","Jump to a labeled line in a batch script.\n"); - MSG_Add("SHELL_CMD_SHIFT_HELP","Leftshift commandline parameters in a batch script.\n"); - MSG_Add("SHELL_CMD_TYPE_HELP","Display the contents of a text-file.\n"); - MSG_Add("SHELL_CMD_TYPE_HELP_LONG","TYPE [drive:][path][filename]\n"); - MSG_Add("SHELL_CMD_REM_HELP","Add comments in a batch file.\n"); - MSG_Add("SHELL_CMD_REM_HELP_LONG","REM [comment]\n"); - MSG_Add("SHELL_CMD_NO_WILD","This is a simple version of the command, no wildcards allowed!\n"); - MSG_Add("SHELL_CMD_RENAME_HELP","Renames one or more files.\n"); - MSG_Add("SHELL_CMD_RENAME_HELP_LONG","RENAME [drive:][path]filename1 filename2.\n" - "REN [drive:][path]filename1 filename2.\n\n" - "Note that you can not specify a new drive or path for your destination file.\n"); - MSG_Add("SHELL_CMD_DELETE_HELP","Removes one or more files.\n"); - MSG_Add("SHELL_CMD_COPY_HELP","Copy files.\n"); - MSG_Add("SHELL_CMD_CALL_HELP","Start a batch file from within another batch file.\n"); - MSG_Add("SHELL_CMD_SUBST_HELP","Assign an internal directory to a drive.\n"); - MSG_Add("SHELL_CMD_LOADHIGH_HELP","Loads a program into upper memory (requires xms=true,umb=true).\n"); - MSG_Add("SHELL_CMD_CHOICE_HELP","Waits for a keypress and sets ERRORLEVEL.\n"); - MSG_Add("SHELL_CMD_CHOICE_HELP_LONG","CHOICE [/C:choices] [/N] [/S] text\n" - " /C[:]choices - Specifies allowable keys. Default is: yn.\n" - " /N - Do not display the choices at end of prompt.\n" - " /S - Enables case-sensitive choices to be selected.\n" - " text - The text to display as a prompt.\n"); - MSG_Add("SHELL_CMD_ATTRIB_HELP","Does nothing. Provided for compatibility.\n"); - MSG_Add("SHELL_CMD_PATH_HELP","Provided for compatibility.\n"); - MSG_Add("SHELL_CMD_VER_HELP","View and set the reported DOS version.\n"); - MSG_Add("SHELL_CMD_VER_VER","DOSBox version %s. Reported DOS version %d.%02d.\n"); - - /* Regular startup */ - call_shellstop=CALLBACK_Allocate(); - /* Setup the startup CS:IP to kill the last running machine when exitted */ - RealPt newcsip=CALLBACK_RealPointer(call_shellstop); - SegSet16(cs,RealSeg(newcsip)); - reg_ip=RealOff(newcsip); - - CALLBACK_Setup(call_shellstop,shellstop_handler,CB_IRET,"shell stop"); - PROGRAMS_MakeFile("COMMAND.COM",SHELL_ProgramStart); - - /* Now call up the shell for the first time */ - Bit16u psp_seg=DOS_FIRST_SHELL; - Bit16u env_seg=DOS_FIRST_SHELL+19; //DOS_GetMemory(1+(4096/16))+1; - Bit16u stack_seg=DOS_GetMemory(2048/16); - SegSet16(ss,stack_seg); - reg_sp=2046; - - /* Set up int 24 and psp (Telarium games) */ - real_writeb(psp_seg+16+1,0,0xea); /* far jmp */ - real_writed(psp_seg+16+1,1,real_readd(0,0x24*4)); - real_writed(0,0x24*4,((Bit32u)psp_seg<<16) | ((16+1)<<4)); - - /* Set up int 23 to "int 20" in the psp. Fixes what.exe */ - real_writed(0,0x23*4,((Bit32u)psp_seg<<16)); - - /* Setup MCBs */ - DOS_MCB pspmcb((Bit16u)(psp_seg-1)); - pspmcb.SetPSPSeg(psp_seg); // MCB of the command shell psp - pspmcb.SetSize(0x10+2); - pspmcb.SetType(0x4d); - DOS_MCB envmcb((Bit16u)(env_seg-1)); - envmcb.SetPSPSeg(psp_seg); // MCB of the command shell environment - envmcb.SetSize(0x28); - envmcb.SetType(0x4d); - - /* Setup environment */ - PhysPt env_write=PhysMake(env_seg,0); - MEM_BlockWrite(env_write,path_string,(Bitu)(strlen(path_string)+1)); - env_write += (PhysPt)(strlen(path_string)+1); - MEM_BlockWrite(env_write,comspec_string,(Bitu)(strlen(comspec_string)+1)); - env_write += (PhysPt)(strlen(comspec_string)+1); - mem_writeb(env_write++,0); - mem_writew(env_write,1); - env_write+=2; - MEM_BlockWrite(env_write,full_name,(Bitu)(strlen(full_name)+1)); - - DOS_PSP psp(psp_seg); - psp.MakeNew(0); - dos.psp(psp_seg); - - /* The start of the filetable in the psp must look like this: - * 01 01 01 00 02 - * In order to achieve this: First open 2 files. Close the first and - * duplicate the second (so the entries get 01) */ - Bit16u dummy=0; - DOS_OpenFile("CON",OPEN_READWRITE,&dummy); /* STDIN */ - DOS_OpenFile("CON",OPEN_READWRITE,&dummy); /* STDOUT */ - DOS_CloseFile(0); /* Close STDIN */ - DOS_ForceDuplicateEntry(1,0); /* "new" STDIN */ - DOS_ForceDuplicateEntry(1,2); /* STDERR */ - DOS_OpenFile("CON",OPEN_READWRITE,&dummy); /* STDAUX */ - DOS_OpenFile("CON",OPEN_READWRITE,&dummy); /* STDPRN */ - - psp.SetParent(psp_seg); - /* Set the environment */ - psp.SetEnvironment(env_seg); - /* Set the command line for the shell start up */ - CommandTail tail; - tail.count=(Bit8u)strlen(init_line); - strcpy(tail.buffer,init_line); - MEM_BlockWrite(PhysMake(psp_seg,128),&tail,128); - - /* Setup internal DOS Variables */ - dos.dta(RealMake(psp_seg,0x80)); - dos.psp(psp_seg); - - - SHELL_ProgramStart(&first_shell); - first_shell->Run(); - delete first_shell; - first_shell = 0;//Make clear that it shouldn't be used anymore -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include +#include +#include "shell_inc.h" + +Bitu call_shellstop; + +static Bitu shellstop_handler(void) { + return CBRET_STOP; +} + +static void SHELL_ProgramStart(PROGRAM_Info * info) { + DOS_Shell * tempshell=new DOS_Shell(info); + tempshell->Run(); + delete tempshell; +} + +#define AUTOEXEC_SIZE 4096 +static char autoexec_data[AUTOEXEC_SIZE]={0}; + +void SHELL_AddAutoexec(char * line,...) { + char buf[2048]; + va_list msg; + + va_start(msg,line); + vsprintf(buf,line,msg); + va_end(msg); + + size_t auto_len=strlen(autoexec_data); + if ((auto_len+strlen(line)+3)>AUTOEXEC_SIZE) { + E_Exit("SYSTEM:Autoexec.bat file overlow"); + } + sprintf((autoexec_data+auto_len),"%s\r\n",buf); +} + + +DOS_Shell::DOS_Shell(PROGRAM_Info * info):Program(info) { + input_handle=STDIN; + echo=true; + exit=false; + bf=0; + memset(&old.buffer,0,CMD_OLDSIZE); + old.size=0; +} + + + + +Bit32u DOS_Shell::GetRedirection(char *s, char **ifn, char **ofn) { + + + return 1; +} + + + +void DOS_Shell::ParseLine(char * line) { + + char * in=0; + char * out=0; + char * fname0=0; + char * fname1=0; + + /* Check for a leading @ */ + if (line[0]=='@') line[0]=' '; + line=trim(line); + Bit32u num=0; /* Number of commands in this line */ + + num = GetRedirection(line,&in, &out); + +/* TODO in and out redirection */ + + DoCommand(line); + +} + + + +void DOS_Shell::Run(void) { + /* Check for a direct Command */ + if (strncasecmp(prog_info->cmd_line,"/C ",3)==0) { + ParseLine(prog_info->cmd_line+3); + return; + } + /* Start a normal shell and check for a first command init */ + WriteOut(MSG_Get("SHELL_STARTUP")); + char input_line[CMD_MAXLINE]; + if (strncasecmp(prog_info->cmd_line,"/INIT ",6)==0) { + ParseLine(prog_info->cmd_line+6); + } + do { + if (bf && bf->ReadLine(input_line)) { + if (echo) { + if (input_line[0]!='@') { + ShowPrompt(); + WriteOut(input_line); + WriteOut("\n"); + }; + }; + } else { + if (echo) ShowPrompt(); + InputCommand(input_line); + + } + ParseLine(input_line); + if (echo) WriteOut("\n"); + } while (!exit); +} + +void DOS_Shell::SyntaxError(void) { + WriteOut(MSG_Get("SHELL_SYNTAXERROR")); +} + + + + +void SHELL_Init() { + call_shellstop=CALLBACK_Allocate(); + CALLBACK_Setup(call_shellstop,shellstop_handler,CB_IRET); + PROGRAMS_MakeFile("COMMAND.COM",SHELL_ProgramStart); + /* Now call up the shell for the first time */ + Bit16u psp_seg=DOS_GetMemory(16); + Bit16u env_seg=DOS_GetMemory(1+(4096/16)); + /* Setup a fake MCB for the environment */ + MCB * env_mcb=(MCB *)real_host(env_seg,0); + env_mcb->psp_segment=psp_seg; + env_mcb->size=4096/16; + real_writed(env_seg+1,0,0); + + PSP * psp=(PSP *)real_host(psp_seg,0); + Bit32u i; + for (i=0;i<20;i++) psp->files[i]=0xff; + psp->files[STDIN]=DOS_FindDevice("CON"); + psp->files[STDOUT]=DOS_FindDevice("CON"); + psp->files[STDERR]=DOS_FindDevice("CON"); + psp->files[STDAUX]=DOS_FindDevice("CON"); + psp->files[STDNUL]=DOS_FindDevice("CON"); + psp->files[STDPRN]=DOS_FindDevice("CON"); + psp->max_files=20; + psp->file_table=RealMake(psp_seg,offsetof(PSP,files)); + /* Save old DTA in psp */ + psp->dta=dos.dta; + psp->environment=env_seg+1; + + /* Setup internal DOS Variables */ + dos.dta=RealMake(psp_seg,0x80); + dos.psp=psp_seg; + PROGRAM_Info info; + strcpy(info.full_name,"Z:\\COMMAND.COM"); + info.psp_seg=psp_seg; + MEM_BlockRead(real_phys(dos.psp,0),&info.psp_copy,sizeof(PSP)); + char line[256]; + strcpy(line,"/INIT Z:\\AUTOEXEC.BAT"); + info.cmd_line=line; + +/* Handle the last AUTOEXEC.BAT Setup stuff */ + VFILE_Register("AUTOEXEC.BAT",(Bit8u *)autoexec_data,strlen(autoexec_data)); + SHELL_ProgramStart(&info); +} diff --git a/src/shell/shell_batch.cpp b/src/shell/shell_batch.cpp index 78c0a1d..499a875 100644 --- a/src/shell/shell_batch.cpp +++ b/src/shell/shell_batch.cpp @@ -1,201 +1,124 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: shell_batch.cpp,v 1.34 2009/04/22 12:28:51 qbix79 Exp $ */ - -#include -#include - -#include "shell.h" -#include "support.h" - -BatchFile::BatchFile(DOS_Shell * host,char const * const name, char const * const cmd_line) { - location = 0; - prev=host->bf; - echo=host->echo; - shell=host; - char totalname[DOS_PATHLENGTH+4]; - DOS_Canonicalize(name,totalname); // Get fullname including drive specificiation - cmd = new CommandLine(totalname,cmd_line); - - //Test if file is openable - if (!DOS_OpenFile(totalname,128,&file_handle)) { - //TODO Come up with something better - E_Exit("SHELL:Can't open BatchFile %s",totalname); - } - DOS_CloseFile(file_handle); -} - -BatchFile::~BatchFile() { - delete cmd; - shell->bf=prev; - shell->echo=echo; -} - -bool BatchFile::ReadLine(char * line) { - //Open the batchfile and seek to stored postion - if (!DOS_OpenFile(cmd->GetFileName(),128,&file_handle)) { - LOG(LOG_MISC,LOG_ERROR)("ReadLine Can't open BatchFile %s",cmd->GetFileName()); - delete this; - return false; - } - DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_SET); - - Bit8u c=0;Bit16u n=1; - char temp[CMD_MAXLINE]; -emptyline: - char * cmd_write=temp; - do { - n=1; - DOS_ReadFile(file_handle,&c,&n); - if (n>0) { - /* Why are we filtering this ? - * Exclusion list: tab for batch files - * escape for ansi - * backspace for alien odyssey */ - if (c>31 || c==0x1b || c=='\t' || c==8) - *cmd_write++=c; - } - } while (c!='\n' && n); - *cmd_write=0; - if (!n && cmd_write==temp) { - //Close file and delete bat file - DOS_CloseFile(file_handle); - delete this; - return false; - } - if (!strlen(temp)) goto emptyline; - if (temp[0]==':') goto emptyline; - - /* Now parse the line read from the bat file for % stuff */ - cmd_write=line; - char * cmd_read=temp; - char env_name[256];char * env_write; - while (*cmd_read) { - env_write=env_name; - if (*cmd_read=='%') { - cmd_read++; - if (cmd_read[0] == '%') { - cmd_read++; - *cmd_write++='%'; - continue; - } - if (cmd_read[0] == '0') { /* Handle %0 */ - const char *file_name = cmd->GetFileName(); - cmd_read++; - strcpy(cmd_write,file_name); - cmd_write+=strlen(file_name); - continue; - } - char next = cmd_read[0]; - if(next > '0' && next <= '9') { - /* Handle %1 %2 .. %9 */ - cmd_read++; //Progress reader - next -= '0'; - if (cmd->GetCount()<(unsigned int)next) continue; - std::string word; - if (!cmd->FindCommand(next,word)) continue; - strcpy(cmd_write,word.c_str()); - cmd_write+=strlen(word.c_str()); - continue; - } else { - /* Not a command line number has to be an environment */ - char * first=strchr(cmd_read,'%'); - /* No env afterall.Somewhat of a hack though as %% and % aren't handled consistent in dosbox. Maybe echo needs to parse % and %% as well. */ - if (!first) {*cmd_write++ = '%';continue;} - *first++ = 0; - std::string env; - if (shell->GetEnvStr(cmd_read,env)) { - const char * equals=strchr(env.c_str(),'='); - if (!equals) continue; - equals++; - strcpy(cmd_write,equals); - cmd_write+=strlen(equals); - } - cmd_read=first; - } - } else { - *cmd_write++=*cmd_read++; - } - } - *cmd_write=0; - //Store current location and close bat file - this->location = 0; - DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR); - DOS_CloseFile(file_handle); - return true; -} - -bool BatchFile::Goto(char * where) { - //Open bat file and search for the where string - if (!DOS_OpenFile(cmd->GetFileName(),128,&file_handle)) { - LOG(LOG_MISC,LOG_ERROR)("SHELL:Goto Can't open BatchFile %s",cmd->GetFileName()); - delete this; - return false; - } - - char cmd_buffer[CMD_MAXLINE]; - char * cmd_write; - - /* Scan till we have a match or return false */ - Bit8u c;Bit16u n; -again: - cmd_write=cmd_buffer; - do { - n=1; - DOS_ReadFile(file_handle,&c,&n); - if (n>0) { - if (c>31) - *cmd_write++=c; - } - } while (c!='\n' && n); - *cmd_write++ = 0; - char *nospace = trim(cmd_buffer); - if (nospace[0] == ':') { - nospace++; //Skip : - //Strip spaces and = from it. - while(*nospace && (isspace(*reinterpret_cast(nospace)) || (*nospace == '='))) - nospace++; - - //label is until space/=/eol - char* const beginlabel = nospace; - while(*nospace && !isspace(*reinterpret_cast(nospace)) && (*nospace != '=')) - nospace++; - - *nospace = 0; - if (strcasecmp(beginlabel,where)==0) { - //Found it! Store location and continue - this->location = 0; - DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR); - DOS_CloseFile(file_handle); - return true; - } - - } - if (!n) { - DOS_CloseFile(file_handle); - delete this; - return false; - } - goto again; - return false; -} - -void BatchFile::Shift(void) { - cmd->Shift(1); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "shell_inc.h" +#include "cpu.h" + + +BatchFile::BatchFile(DOS_Shell * host,char * name, char * cmd_line) { + /* Go through the command line */ + char * cmd_write=cmd_buffer; + prev=host->bf; + echo=host->echo; + shell=host; + cmd_count=0; + while (*cmd_line || (cmd_countbf=prev; + shell->echo=echo; +} + +bool BatchFile::ReadLine(char * line) { + Bit8u c;Bit16u n; + char temp[CMD_MAXLINE]; +emptyline: + char * cmd_write=temp; + do { + n=1; + DOS_ReadFile(file_handle,&c,&n); + if (n>0) { + if (c>31) + *cmd_write++=c; + } + } while (c!='\n' && n); + *cmd_write++=0; + if (!n) { + delete this; + return false; + } + if (!strlen(temp)) goto emptyline; + if (temp[0]==':') goto emptyline; +/* Now parse the line read from the bat file for % stuff */ + cmd_write=line; + char * cmd_read=temp; + char env_name[256];char * env_write; + while (*cmd_read) { + env_write=env_name; + if (*cmd_read=='%') { + cmd_read++; + /* Find the fullstring of this */ + + + continue; + + } else { + *cmd_write++=*cmd_read++; + } + *cmd_write=0; + } + return true; + +} + + +bool BatchFile::Goto(char * where) { + Bit32u pos=0; + char cmd[CMD_MAXLINE]; + char * cmd_write; + DOS_SeekFile(file_handle,&pos,DOS_SEEK_SET); + + /* Scan till we have a match or return false*/ + Bit8u c;Bit16u n; +again: + cmd_write=cmd; + do { + n=1; + DOS_ReadFile(file_handle,&c,&n); + if (n>0) { + if (c>31) + *cmd_write++=c; + } + } while (c!='\n' && n); + *cmd_write++=0; + if (cmd[0]==':') { + if (strcasecmp(cmd+1,where)==0) return true; + } + if (!n) { + delete this; + return false; + } + goto again; + return false; +}; diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index 8ec814d..c34624b 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -1,1065 +1,380 @@ -/* - * Copyright (C) 2002-2009 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: shell_cmds.cpp,v 1.90 2009/04/02 19:08:26 qbix79 Exp $ */ - -#include "dosbox.h" -#include "shell.h" -#include "callback.h" -#include "regs.h" -#include "../dos/drives.h" -#include "support.h" -#include "control.h" -#include -#include -#include -#include -#include - -static SHELL_Cmd cmd_list[]={ -{ "CHDIR", 1, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP"}, -{ "CD", 0, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP"}, -{ "CLS", 0, &DOS_Shell::CMD_CLS, "SHELL_CMD_CLS_HELP"}, -{ "COPY", 0, &DOS_Shell::CMD_COPY, "SHELL_CMD_COPY_HELP"}, -{ "DIR", 0, &DOS_Shell::CMD_DIR, "SHELL_CMD_DIR_HELP"}, -{ "DEL", 0, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"}, -{ "DELETE", 1, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"}, -{ "ERASE", 1, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"}, -{ "ECHO", 1, &DOS_Shell::CMD_ECHO, "SHELL_CMD_ECHO_HELP"}, -{ "EXIT", 0, &DOS_Shell::CMD_EXIT, "SHELL_CMD_EXIT_HELP"}, -{ "HELP", 1, &DOS_Shell::CMD_HELP, "SHELL_CMD_HELP_HELP"}, -{ "MKDIR", 1, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP"}, -{ "MD", 0, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP"}, -{ "RMDIR", 1, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP"}, -{ "RD", 0, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP"}, -{ "SET", 1, &DOS_Shell::CMD_SET, "SHELL_CMD_SET_HELP"}, -{ "IF", 1, &DOS_Shell::CMD_IF, "SHELL_CMD_IF_HELP"}, -{ "GOTO", 1, &DOS_Shell::CMD_GOTO, "SHELL_CMD_GOTO_HELP"}, -{ "SHIFT", 1, &DOS_Shell::CMD_SHIFT, "SHELL_CMD_SHIFT_HELP"}, -{ "TYPE", 0, &DOS_Shell::CMD_TYPE, "SHELL_CMD_TYPE_HELP"}, -{ "REM", 1, &DOS_Shell::CMD_REM, "SHELL_CMD_REM_HELP"}, -{ "RENAME", 1, &DOS_Shell::CMD_RENAME, "SHELL_CMD_RENAME_HELP"}, -{ "REN", 0, &DOS_Shell::CMD_RENAME, "SHELL_CMD_RENAME_HELP"}, -{ "PAUSE", 1, &DOS_Shell::CMD_PAUSE, "SHELL_CMD_PAUSE_HELP"}, -{ "CALL", 1, &DOS_Shell::CMD_CALL, "SHELL_CMD_CALL_HELP"}, -{ "SUBST", 1, &DOS_Shell::CMD_SUBST, "SHELL_CMD_SUBST_HELP"}, -{ "LOADHIGH", 0, &DOS_Shell::CMD_LOADHIGH, "SHELL_CMD_LOADHIGH_HELP"}, -{ "LH", 1, &DOS_Shell::CMD_LOADHIGH, "SHELL_CMD_LOADHIGH_HELP"}, -{ "CHOICE", 0, &DOS_Shell::CMD_CHOICE, "SHELL_CMD_CHOICE_HELP"}, -{ "ATTRIB", 1, &DOS_Shell::CMD_ATTRIB, "SHELL_CMD_ATTRIB_HELP"}, -{ "PATH", 1, &DOS_Shell::CMD_PATH, "SHELL_CMD_PATH_HELP"}, -{ "VER", 0, &DOS_Shell::CMD_VER, "SHELL_CMD_VER_HELP"}, -{0,0,0,0} -}; - -/* support functions */ -static char empty_char = 0; -static char* empty_string = &empty_char; -static void StripSpaces(char*&args) { - while(args && *args && isspace(*reinterpret_cast(args))) - args++; -} - -static void StripSpaces(char*&args,char also) { - while(args && *args && (isspace(*reinterpret_cast(args)) || (*args == also))) - args++; -} - -static char* ExpandDot(char*args, char* buffer) { - if(*args == '.') { - if(*(args+1) == 0){ - strcpy(buffer,"*.*"); - return buffer; - } - if( (*(args+1) != '.') && (*(args+1) != '\\') ) { - buffer[0] = '*'; - buffer[1] = 0; - strcat(buffer,args); - return buffer; - } else - strcpy (buffer, args); - } - else strcpy(buffer,args); - return buffer; -} - - - -bool DOS_Shell::CheckConfig(char* cmd_in,char*line) { - Section* test = control->GetSectionFromProperty(cmd_in); - if(!test) return false; - if(line && !line[0]) { - std::string val = test->GetPropValue(cmd_in); - if(val != NO_SUCH_PROPERTY) WriteOut("%s\n",val.c_str()); - return true; - } - char newcom[1024]; newcom[0] = 0; strcpy(newcom,"z:\\config "); - strcat(newcom,test->GetName()); strcat(newcom," "); - strcat(newcom,cmd_in);strcat(newcom,line); - DoCommand(newcom); - return true; -} - -void DOS_Shell::DoCommand(char * line) { -/* First split the line into command and arguments */ - line=trim(line); - char cmd_buffer[CMD_MAXLINE]; - char * cmd_write=cmd_buffer; - while (*line) { - if (*line==32) break; - if (*line=='/') break; - if (*line=='\t') break; - if (*line=='=') break; - if ((*line=='.') ||(*line =='\\')) { //allow stuff like cd.. and dir.exe cd\kees - *cmd_write=0; - Bit32u cmd_index=0; - while (cmd_list[cmd_index].name) { - if (strcasecmp(cmd_list[cmd_index].name,cmd_buffer)==0) { - (this->*(cmd_list[cmd_index].handler))(line); - return; - } - cmd_index++; - } - } - *cmd_write++=*line++; - } - *cmd_write=0; - if (strlen(cmd_buffer)==0) return; -/* Check the internal list */ - Bit32u cmd_index=0; - while (cmd_list[cmd_index].name) { - if (strcasecmp(cmd_list[cmd_index].name,cmd_buffer)==0) { - (this->*(cmd_list[cmd_index].handler))(line); - return; - } - cmd_index++; - } -/* This isn't an internal command execute it */ - if(Execute(cmd_buffer,line)) return; - if(CheckConfig(cmd_buffer,line)) return; - WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"),cmd_buffer); -} - -#define HELP(command) \ - if (ScanCMDBool(args,"?")) { \ - WriteOut(MSG_Get("SHELL_CMD_" command "_HELP")); \ - const char* long_m = MSG_Get("SHELL_CMD_" command "_HELP_LONG"); \ - WriteOut("\n"); \ - if(strcmp("Message not Found!\n",long_m)) WriteOut(long_m); \ - else WriteOut(command "\n"); \ - return; \ - } - -void DOS_Shell::CMD_CLS(char * args) { - HELP("CLS"); - reg_ax=0x0003; - CALLBACK_RunRealInt(0x10); -} - -void DOS_Shell::CMD_DELETE(char * args) { - HELP("DELETE"); - /* Command uses dta so set it to our internal dta */ - RealPt save_dta=dos.dta(); - dos.dta(dos.tables.tempdta); - - char * rem=ScanCMDRemain(args); - if (rem) { - WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); - return; - } - /* If delete accept switches mind the space infront of them. See the dir /p code */ - - char full[DOS_PATHLENGTH]; - char buffer[CROSS_LEN]; - args = ExpandDot(args,buffer); - StripSpaces(args); - if (!DOS_Canonicalize(args,full)) { WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));return; } -//TODO Maybe support confirmation for *.* like dos does. - bool res=DOS_FindFirst(args,0xffff & ~DOS_ATTR_VOLUME); - if (!res) { - WriteOut(MSG_Get("SHELL_CMD_DEL_ERROR"),args); - dos.dta(save_dta); - return; - } - //end can't be 0, but if it is we'll get a nice crash, who cares :) - char * end=strrchr(full,'\\')+1;*end=0; - char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u time,date;Bit8u attr; - DOS_DTA dta(dos.dta()); - while (res) { - dta.GetResult(name,size,date,time,attr); - if (!(attr & (DOS_ATTR_DIRECTORY|DOS_ATTR_READ_ONLY))) { - strcpy(end,name); - if (!DOS_UnlinkFile(full)) WriteOut(MSG_Get("SHELL_CMD_DEL_ERROR"),full); - } - res=DOS_FindNext(); - } - dos.dta(save_dta); -} - -void DOS_Shell::CMD_HELP(char * args){ - HELP("HELP"); - bool optall=ScanCMDBool(args,"ALL"); - /* Print the help */ - if(!optall) WriteOut(MSG_Get("SHELL_CMD_HELP")); - Bit32u cmd_index=0,write_count=0; - while (cmd_list[cmd_index].name) { - if (optall || !cmd_list[cmd_index].flags) { - WriteOut("<\033[34;1m%-8s\033[0m> %s",cmd_list[cmd_index].name,MSG_Get(cmd_list[cmd_index].help)); - if(!(++write_count%22)) CMD_PAUSE(empty_string); - } - cmd_index++; - } -} - -void DOS_Shell::CMD_RENAME(char * args){ - HELP("RENAME"); - StripSpaces(args); - if(!*args) {SyntaxError();return;} - if((strchr(args,'*')!=NULL) || (strchr(args,'?')!=NULL) ) { WriteOut(MSG_Get("SHELL_CMD_NO_WILD"));return;} - char * arg1=StripWord(args); - char* slash = strrchr(arg1,'\\'); - if(slash) { - slash++; - /* If directory specified (crystal caves installer) - * rename from c:\X : rename c:\abc.exe abc.shr. - * File must appear in C:\ */ - - char dir_source[DOS_PATHLENGTH]={0}; - //Copy first and then modify, makes GCC happy - strcpy(dir_source,arg1); - char* dummy = strrchr(dir_source,'\\'); - *dummy=0; - - if((strlen(dir_source) == 2) && (dir_source[1] == ':')) - strcat(dir_source,"\\"); //X: add slash - - char dir_current[DOS_PATHLENGTH]; - DOS_GetCurrentDir(0,dir_current); - if(!DOS_ChangeDir(dir_source)) { - WriteOut(MSG_Get("SHELL_ILLEGAL_PATH")); - return; - } - DOS_Rename(slash,args); - DOS_ChangeDir(dir_current); - } else { - DOS_Rename(arg1,args); - } -} - -void DOS_Shell::CMD_ECHO(char * args){ - HELP("ECHO"); - if (!*args) { - if (echo) { WriteOut(MSG_Get("SHELL_CMD_ECHO_ON"));} - else { WriteOut(MSG_Get("SHELL_CMD_ECHO_OFF"));} - return; - } - char buffer[512]; - char* pbuffer = buffer; - safe_strncpy(buffer,args,512); - StripSpaces(pbuffer); - if (strcasecmp(pbuffer,"OFF")==0) { - echo=false; - return; - } - if (strcasecmp(pbuffer,"ON")==0) { - echo=true; - return; - } - args++;//skip first character. either a slash or dot or space - size_t len = strlen(args); //TODO check input of else ook nodig is. - if(len && args[len - 1] == '\r') { - LOG(LOG_MISC,LOG_WARN)("Hu ? carriage return allready present. Is this possible?"); - WriteOut("%s\n",args); - } else WriteOut("%s\r\n",args); -} - - -void DOS_Shell::CMD_EXIT(char * args) { - HELP("EXIT"); - exit = true; -} - -void DOS_Shell::CMD_CHDIR(char * args) { - HELP("CHDIR"); - StripSpaces(args); - if (!*args) { - Bit8u drive=DOS_GetDefaultDrive()+'A'; - char dir[DOS_PATHLENGTH]; - DOS_GetCurrentDir(0,dir); - WriteOut("%c:\\%s\n",drive,dir); - } else if(strlen(args) == 2 && args[1]==':') { - WriteOut(MSG_Get("SHELL_CMD_CHDIR_HINT"),toupper(*reinterpret_cast(&args[0]))); - } else if (!DOS_ChangeDir(args)) { - /* Changedir failed. Check if the filename is longer then 8 and/or contains spaces */ - - std::string temps(args),slashpart; - std::string::size_type separator = temps.find_first_of("\\/"); - if(!separator) { - slashpart = temps.substr(0,1); - temps.erase(0,1); - } - separator = temps.find_first_of("\\/"); - if(separator != std::string::npos) temps.erase(separator); - separator = temps.rfind('.'); - if(separator != std::string::npos) temps.erase(separator); - separator = temps.find(' '); - if(separator != std::string::npos) {/* Contains spaces */ - temps.erase(separator); - if(temps.size() >6) temps.erase(6); - temps += "~1"; - WriteOut(MSG_Get("SHELL_CMD_CHDIR_HINT_2"),temps.insert(0,slashpart).c_str()); - } else if (temps.size()>8) { - temps.erase(6); - temps += "~1"; - WriteOut(MSG_Get("SHELL_CMD_CHDIR_HINT_2"),temps.insert(0,slashpart).c_str()); - } else { - Bit8u drive=DOS_GetDefaultDrive()+'A'; - if (drive=='Z') { - WriteOut(MSG_Get("SHELL_CMD_CHDIR_HINT_3")); - } else { - WriteOut(MSG_Get("SHELL_CMD_CHDIR_ERROR"),args); - } - } - } -} - -void DOS_Shell::CMD_MKDIR(char * args) { - HELP("MKDIR"); - StripSpaces(args); - char * rem=ScanCMDRemain(args); - if (rem) { - WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); - return; - } - if (!DOS_MakeDir(args)) { - WriteOut(MSG_Get("SHELL_CMD_MKDIR_ERROR"),args); - } -} - -void DOS_Shell::CMD_RMDIR(char * args) { - HELP("RMDIR"); - StripSpaces(args); - char * rem=ScanCMDRemain(args); - if (rem) { - WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); - return; - } - if (!DOS_RemoveDir(args)) { - WriteOut(MSG_Get("SHELL_CMD_RMDIR_ERROR"),args); - } -} - -static void FormatNumber(Bitu num,char * buf) { - Bitu numm,numk,numb,numg; - numb=num % 1000; - num/=1000; - numk=num % 1000; - num/=1000; - numm=num % 1000; - num/=1000; - numg=num; - if (numg) { - sprintf(buf,"%d,%03d,%03d,%03d",numg,numm,numk,numb); - return; - }; - if (numm) { - sprintf(buf,"%d,%03d,%03d",numm,numk,numb); - return; - }; - if (numk) { - sprintf(buf,"%d,%03d",numk,numb); - return; - }; - sprintf(buf,"%d",numb); -} - -void DOS_Shell::CMD_DIR(char * args) { - HELP("DIR"); - char numformat[16]; - char path[DOS_PATHLENGTH]; - - std::string line; - if(GetEnvStr("DIRCMD",line)){ - std::string::size_type idx = line.find('='); - std::string value=line.substr(idx +1 , std::string::npos); - line = std::string(args) + " " + value; - args=const_cast(line.c_str()); - } - - bool optW=ScanCMDBool(args,"W"); - ScanCMDBool(args,"S"); - bool optP=ScanCMDBool(args,"P"); - bool optAD=ScanCMDBool(args,"AD"); - char * rem=ScanCMDRemain(args); - if (rem) { - WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); - return; - } - Bit32u byte_count,file_count,dir_count; - Bitu w_count=0; - Bitu p_count=0; - Bitu w_size = optW?5:1; - byte_count=file_count=dir_count=0; - - char buffer[CROSS_LEN]; - args = trim(args); - size_t argLen = strlen(args); - if (argLen == 0) { - strcpy(args,"*.*"); //no arguments. - } else { - switch (args[argLen-1]) - { - case '\\': // handle \, C:\, etc. - case ':' : // handle C:, etc. - strcat(args,"*.*"); - break; - default: - break; - } - } - args = ExpandDot(args,buffer); - - if (!strrchr(args,'*') && !strrchr(args,'?')) { - Bit16u attribute=0; - if(DOS_GetFileAttr(args,&attribute) && (attribute&DOS_ATTR_DIRECTORY) ) { - strcat(args,"\\*.*"); // if no wildcard and a directory, get its files - } - } - if (!strrchr(args,'.')) { - strcat(args,".*"); // if no extension, get them all - } - - /* Make a full path in the args */ - if (!DOS_Canonicalize(args,path)) { - WriteOut(MSG_Get("SHELL_ILLEGAL_PATH")); - return; - } - *(strrchr(path,'\\')+1)=0; - WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),path); - - /* Command uses dta so set it to our internal dta */ - RealPt save_dta=dos.dta(); - dos.dta(dos.tables.tempdta); - DOS_DTA dta(dos.dta()); - bool ret=DOS_FindFirst(args,0xffff & ~DOS_ATTR_VOLUME); - if (!ret) { - WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args); - dos.dta(save_dta); - return; - } - - do { /* File name and extension */ - char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr; - dta.GetResult(name,size,date,time,attr); - - /* Skip non-directories if option AD is present */ - if(optAD && !(attr&DOS_ATTR_DIRECTORY) ) continue; - - char * ext = empty_string; - if (!optW && (name[0] != '.')) { - ext = strrchr(name, '.'); - if (!ext) ext = empty_string; - else *ext++ = 0; - } - Bit8u day = (Bit8u)(date & 0x001f); - Bit8u month = (Bit8u)((date >> 5) & 0x000f); - Bit16u year = (Bit16u)((date >> 9) + 1980); - Bit8u hour = (Bit8u)((time >> 5 ) >> 6); - Bit8u minute = (Bit8u)((time >> 5) & 0x003f); - - /* output the file */ - if (attr & DOS_ATTR_DIRECTORY) { - if (optW) { - WriteOut("[%s]",name); - size_t namelen = strlen(name); - if (namelen <= 14) { - for (size_t i=14-namelen;i>0;i--) WriteOut(" "); - } - } else { - WriteOut("%-8s %-3s %-16s %02d-%02d-%04d %2d:%02d\n",name,ext,"

",day,month,year,hour,minute); - } - dir_count++; - } else { - if (optW) { - WriteOut("%-16s",name); - } else { - FormatNumber(size,numformat); - WriteOut("%-8s %-3s %16s %02d-%02d-%04d %2d:%02d\n",name,ext,numformat,day,month,year,hour,minute); - } - file_count++; - byte_count+=size; - } - if (optW) { - w_count++; - } - if(optP) { - if(!(++p_count%(22*w_size))) { - CMD_PAUSE(empty_string); - } - } - } while ( (ret=DOS_FindNext()) ); - if (optW) { - if (w_count%5) WriteOut("\n"); - } - - /* Show the summary of results */ - FormatNumber(byte_count,numformat); - WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_USED"),file_count,numformat); - Bit8u drive=dta.GetSearchDrive(); - //TODO Free Space - Bitu free_space=1024*1024*100; - if (Drives[drive]) { - Bit16u bytes_sector;Bit8u sectors_cluster;Bit16u total_clusters;Bit16u free_clusters; - Drives[drive]->AllocationInfo(&bytes_sector,§ors_cluster,&total_clusters,&free_clusters); - free_space=bytes_sector*sectors_cluster*free_clusters; - } - FormatNumber(free_space,numformat); - WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_FREE"),dir_count,numformat); - dos.dta(save_dta); -} - -struct copysource { - std::string filename; - bool concat; - copysource(std::string filein,bool concatin): - filename(filein),concat(concatin){ }; - copysource():filename(""),concat(false){ }; -}; - - -void DOS_Shell::CMD_COPY(char * args) { - HELP("COPY"); - static char defaulttarget[] = "."; - StripSpaces(args); - /* Command uses dta so set it to our internal dta */ - RealPt save_dta=dos.dta(); - dos.dta(dos.tables.tempdta); - DOS_DTA dta(dos.dta()); - Bit32u size;Bit16u date;Bit16u time;Bit8u attr; - char name[DOS_NAMELENGTH_ASCII]; - std::vector sources; - // ignore /b and /t switches: always copy binary - while(ScanCMDBool(args,"B")) ; - while(ScanCMDBool(args,"T")) ; //Shouldn't this be A ? - while(ScanCMDBool(args,"A")) ; - ScanCMDBool(args,"Y"); - ScanCMDBool(args,"-Y"); - - char * rem=ScanCMDRemain(args); - if (rem) { - WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); - dos.dta(save_dta); - return; - } - // Gather all sources (extension to copy more then 1 file specified at commandline) - // Concatating files go as follows: All parts except for the last bear the concat flag. - // This construction allows them to be counted (only the non concat set) - char* source_p = NULL; - while ( (source_p = StripWord(args)) && *source_p ) { - do { - char* plus = strchr(source_p,'+'); - if(plus) *plus++ = 0; - sources.push_back(copysource(source_p,(plus)?true:false)); - source_p = plus; - } while(source_p && *source_p); - } - // At least one source has to be there - if (!sources.size() || !sources[0].filename.size()) { - WriteOut(MSG_Get("SHELL_MISSING_PARAMETER")); - dos.dta(save_dta); - return; - }; - - copysource target; - // If more then one object exists and last target is not part of a - // concat sequence then make it the target. - if(sources.size()>1 && !sources[sources.size()-2].concat){ - target = sources.back(); - sources.pop_back(); - } - //If no target => default target with concat flag true to detect a+b+c - if(target.filename.size() == 0) target = copysource(defaulttarget,true); - - copysource oldsource; - copysource source; - Bit32u count = 0; - while(sources.size()) { - /* Get next source item and keep track of old source for concat start end */ - oldsource = source; - source = sources[0]; - sources.erase(sources.begin()); - - //Skip first file if doing a+b+c. Set target to first file - if(!oldsource.concat && source.concat && target.concat) { - target = source; - continue; - } - - /* Make a full path in the args */ - char pathSource[DOS_PATHLENGTH]; - char pathTarget[DOS_PATHLENGTH]; - - if (!DOS_Canonicalize(const_cast(source.filename.c_str()),pathSource)) { - WriteOut(MSG_Get("SHELL_ILLEGAL_PATH")); - dos.dta(save_dta); - return; - } - // cut search pattern - char* pos = strrchr(pathSource,'\\'); - if (pos) *(pos+1) = 0; - - if (!DOS_Canonicalize(const_cast(target.filename.c_str()),pathTarget)) { - WriteOut(MSG_Get("SHELL_ILLEGAL_PATH")); - dos.dta(save_dta); - return; - } - char* temp = strstr(pathTarget,"*.*"); - if(temp) *temp = 0;//strip off *.* from target - - // add '\\' if target is a directoy - if (pathTarget[strlen(pathTarget)-1]!='\\') { - if (DOS_FindFirst(pathTarget,0xffff & ~DOS_ATTR_VOLUME)) { - dta.GetResult(name,size,date,time,attr); - if (attr & DOS_ATTR_DIRECTORY) - strcat(pathTarget,"\\"); - } - }; - - //Find first sourcefile - bool ret = DOS_FindFirst(const_cast(source.filename.c_str()),0xffff & ~DOS_ATTR_VOLUME); - if (!ret) { - WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),const_cast(source.filename.c_str())); - dos.dta(save_dta); - return; - } - - Bit16u sourceHandle,targetHandle; - char nameTarget[DOS_PATHLENGTH]; - char nameSource[DOS_PATHLENGTH]; - - while (ret) { - dta.GetResult(name,size,date,time,attr); - - if ((attr & DOS_ATTR_DIRECTORY)==0) { - strcpy(nameSource,pathSource); - strcat(nameSource,name); - // Open Source - if (DOS_OpenFile(nameSource,0,&sourceHandle)) { - // Create Target or open it if in concat mode - strcpy(nameTarget,pathTarget); - if (nameTarget[strlen(nameTarget)-1]=='\\') strcat(nameTarget,name); - - //Don't create a newfile when in concat mode - if (oldsource.concat || DOS_CreateFile(nameTarget,0,&targetHandle)) { - Bit32u dummy=0; - //In concat mode. Open the target and seek to the eof - if (!oldsource.concat || (DOS_OpenFile(nameTarget,OPEN_READWRITE,&targetHandle) && - DOS_SeekFile(targetHandle,&dummy,DOS_SEEK_END))) { - // Copy - static Bit8u buffer[0x8000]; // static, otherwise stack overflow possible. - bool failed = false; - Bit16u toread = 0x8000; - do { - failed |= DOS_ReadFile(sourceHandle,buffer,&toread); - failed |= DOS_WriteFile(targetHandle,buffer,&toread); - } while (toread==0x8000); - failed |= DOS_CloseFile(sourceHandle); - failed |= DOS_CloseFile(targetHandle); - WriteOut(" %s\n",name); - if(!source.concat) count++; //Only count concat files once - } else { - DOS_CloseFile(sourceHandle); - WriteOut(MSG_Get("SHELL_CMD_COPY_FAILURE"),const_cast(target.filename.c_str())); - } - } else { - DOS_CloseFile(sourceHandle); - WriteOut(MSG_Get("SHELL_CMD_COPY_FAILURE"),const_cast(target.filename.c_str())); - } - } else WriteOut(MSG_Get("SHELL_CMD_COPY_FAILURE"),const_cast(source.filename.c_str())); - }; - //On the next file - ret = DOS_FindNext(); - }; - } - - WriteOut(MSG_Get("SHELL_CMD_COPY_SUCCESS"),count); - dos.dta(save_dta); -} - -void DOS_Shell::CMD_SET(char * args) { - HELP("SET"); - StripSpaces(args); - std::string line; - if (!*args) { - /* No command line show all environment lines */ - Bitu count=GetEnvCount(); - for (Bitu a=0;a % - } else { - char * second = strchr(++p,'%'); - if(!second) continue; *second++ = 0; - std::string temp; - if (GetEnvStr(p,temp)) { - std::string::size_type equals = temp.find('='); - if (equals == std::string::npos) continue; - strcpy(p_parsed,temp.substr(equals+1).c_str()); - p_parsed += strlen(p_parsed); - } - p = second; - } - } - *p_parsed = 0; - /* Try setting the variable */ - if (!SetEnv(args,parsed)) { - WriteOut(MSG_Get("SHELL_CMD_SET_OUT_OF_SPACE")); - } - } -} - -void DOS_Shell::CMD_IF(char * args) { - HELP("IF"); - StripSpaces(args,'='); - bool has_not=false; - - while (strncasecmp(args,"NOT",3) == 0) { - if (!isspace(*reinterpret_cast(&args[3])) && (args[3] != '=')) break; - args += 3; //skip text - //skip more spaces - StripSpaces(args,'='); - has_not = !has_not; - } - - if(strncasecmp(args,"ERRORLEVEL",10) == 0) { - args += 10; //skip text - //Strip spaces and == - StripSpaces(args,'='); - char* word = StripWord(args); - if(!isdigit(*word)) { - WriteOut(MSG_Get("SHELL_CMD_IF_ERRORLEVEL_MISSING_NUMBER")); - return; - } - - Bit8u n = 0; - do n = n * 10 + (*word - '0'); - while (isdigit(*++word)); - if(*word && !isspace(*word)) { - WriteOut(MSG_Get("SHELL_CMD_IF_ERRORLEVEL_INVALID_NUMBER")); - return; - } - /* Read the error code from DOS */ - if ((dos.return_code>=n) ==(!has_not)) DoCommand(args); - return; - } - - if(strncasecmp(args,"EXIST ",6) == 0) { - args += 6; //Skip text - StripSpaces(args); - char* word = StripWord(args); - if (!*word) { - WriteOut(MSG_Get("SHELL_CMD_IF_EXIST_MISSING_FILENAME")); - return; - } - - { /* DOS_FindFirst uses dta so set it to our internal dta */ - RealPt save_dta=dos.dta(); - dos.dta(dos.tables.tempdta); - bool ret=DOS_FindFirst(word,0xffff & ~DOS_ATTR_VOLUME); - dos.dta(save_dta); - if (ret==(!has_not)) DoCommand(args); - } - return; - } - - /* Normal if string compare */ - - char* word1 = args; - // first word is until space or = - while (*args && !isspace(*reinterpret_cast(args)) && (*args != '=')) - args++; - char* end_word1 = args; - - // scan for = - while (*args && (*args != '=')) - args++; - // check for == - if ((*args==0) || (args[1] != '=')) { - SyntaxError(); - return; - } - args += 2; - StripSpaces(args,'='); - - char* word2 = args; - // second word is until space or = - while (*args && !isspace(*reinterpret_cast(args)) && (*args != '=')) - args++; - - if (*args) { - *end_word1 = 0; // mark end of first word - *args++ = 0; // mark end of second word - StripSpaces(args,'='); - - if ((strcmp(word1,word2)==0)==(!has_not)) DoCommand(args); - } -} - -void DOS_Shell::CMD_GOTO(char * args) { - HELP("GOTO"); - StripSpaces(args); - if (!bf) return; - if (*args &&(*args==':')) args++; - //label ends at the first space - char* non_space = args; - while (*non_space) { - if((*non_space == ' ') || (*non_space == '\t')) - *non_space = 0; - else non_space++; - } - if (!*args) { - WriteOut(MSG_Get("SHELL_CMD_GOTO_MISSING_LABEL")); - return; - } - if (!bf->Goto(args)) { - WriteOut(MSG_Get("SHELL_CMD_GOTO_LABEL_NOT_FOUND"),args); - return; - } -} - -void DOS_Shell::CMD_SHIFT(char * args ) { - HELP("SHIFT"); - if(bf) bf->Shift(); -} - -void DOS_Shell::CMD_TYPE(char * args) { - HELP("TYPE"); - StripSpaces(args); - if (!*args) { - WriteOut(MSG_Get("SHELL_SYNTAXERROR")); - return; - } - Bit16u handle; - char * word; -nextfile: - word=StripWord(args); - if (!DOS_OpenFile(word,0,&handle)) { - WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),word); - return; - } - Bit16u n;Bit8u c; - do { - n=1; - DOS_ReadFile(handle,&c,&n); - DOS_WriteFile(STDOUT,&c,&n); - } while (n); - DOS_CloseFile(handle); - if (*args) goto nextfile; -} - -void DOS_Shell::CMD_REM(char * args) { - HELP("REM"); -} - -void DOS_Shell::CMD_PAUSE(char * args){ - HELP("PAUSE"); - WriteOut(MSG_Get("SHELL_CMD_PAUSE")); - Bit8u c;Bit16u n=1; - DOS_ReadFile (STDIN,&c,&n); -} - -void DOS_Shell::CMD_CALL(char * args){ - HELP("CALL"); - this->call=true; /* else the old batchfile will be closed first */ - this->ParseLine(args); - this->call=false; -} - -void DOS_Shell::CMD_SUBST (char * args) { -/* If more that one type can be substed think of something else - * E.g. make basedir member dos_drive instead of localdrive - */ - HELP("SUBST"); - localDrive* ldp=0; - char mountstring[DOS_PATHLENGTH+CROSS_LEN+20]; - char temp_str[2] = { 0,0 }; - try { - strcpy(mountstring,"MOUNT "); - StripSpaces(args); - std::string arg; - CommandLine command(0,args); - - if (command.GetCount() != 2) throw 0 ; - command.FindCommand(2,arg); - if((arg=="/D" ) || (arg=="/d")) throw 1; //No removal (one day) - - command.FindCommand(1,arg); - if( (arg.size()>1) && arg[1] !=':') throw(0); - temp_str[0]=(char)toupper(args[0]); - if(Drives[temp_str[0]-'A'] ) throw 0; //targetdrive in use - strcat(mountstring,temp_str); - strcat(mountstring," "); - - command.FindCommand(2,arg); - Bit8u drive;char fulldir[DOS_PATHLENGTH]; - if (!DOS_MakeName(const_cast(arg.c_str()),fulldir,&drive)) throw 0; - - if( ( ldp=dynamic_cast(Drives[drive])) == 0 ) throw 0; - char newname[CROSS_LEN]; - strcpy(newname, ldp->basedir); - strcat(newname,fulldir); - CROSS_FILENAME(newname); - ldp->dirCache.ExpandName(newname); - strcat(mountstring,"\""); - strcat(mountstring, newname); - strcat(mountstring,"\""); - this->ParseLine(mountstring); - } - catch(int a){ - if(a == 0) { - WriteOut(MSG_Get("SHELL_CMD_SUBST_FAILURE")); - } else { - WriteOut(MSG_Get("SHELL_CMD_SUBST_NO_REMOVE")); - } - return; - } - catch(...) { //dynamic cast failed =>so no localdrive - WriteOut(MSG_Get("SHELL_CMD_SUBST_FAILURE")); - return; - } - - return; -} - -void DOS_Shell::CMD_LOADHIGH(char *args){ - HELP("LOADHIGH"); - Bit16u umb_start=dos_infoblock.GetStartOfUMBChain(); - Bit8u umb_flag=dos_infoblock.GetUMBChainState(); - Bit8u old_memstrat=(Bit8u)(DOS_GetMemAllocStrategy()&0xff); - if (umb_start==0x9fff) { - if ((umb_flag&1)==0) DOS_LinkUMBsToMemChain(1); - DOS_SetMemAllocStrategy(0x80); // search in UMBs first - this->ParseLine(args); - Bit8u current_umb_flag=dos_infoblock.GetUMBChainState(); - if ((current_umb_flag&1)!=(umb_flag&1)) DOS_LinkUMBsToMemChain(umb_flag); - DOS_SetMemAllocStrategy(old_memstrat); // restore strategy - } else this->ParseLine(args); -} - -void DOS_Shell::CMD_CHOICE(char * args){ - HELP("CHOICE"); - static char defchoice[3] = {'y','n',0}; - char *rem = NULL, *ptr; - bool optN = ScanCMDBool(args,"N"); - bool optS = ScanCMDBool(args,"S"); //Case-sensitive matching - ScanCMDBool(args,"T"); //Default Choice after timeout - if (args) { - char *last = strchr(args,0); - StripSpaces(args); - rem = ScanCMDRemain(args); - if (rem && *rem && (tolower(rem[1]) != 'c')) { - WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); - return; - } - if (args == rem) args = strchr(rem,0)+1; - if (rem) rem += 2; - if(rem && rem[0]==':') rem++; /* optional : after /c */ - if (args > last) args = NULL; - } - if (!rem || !*rem) rem = defchoice; /* No choices specified use YN */ - ptr = rem; - Bit8u c; - if(!optS) while ((c = *ptr)) *ptr++ = (char)toupper(c); /* When in no case-sensitive mode. make everything upcase */ - if(args && *args ) { - StripSpaces(args); - size_t argslen = strlen(args); - if(argslen>1 && args[0] == '"' && args[argslen-1] =='"') { - args[argslen-1] = 0; //Remove quotes - args++; - } - WriteOut(args); - } - /* Show question prompt of the form [a,b]? where a b are the choice values */ - if (!optN) { - if(args && *args) WriteOut(" "); - WriteOut("["); - size_t len = strlen(rem); - for(size_t t = 1; t < len; t++) { - WriteOut("%c,",rem[t-1]); - } - WriteOut("%c]?",rem[len-1]); - } - - Bit16u n=1; - do { - DOS_ReadFile (STDIN,&c,&n); - } while (!c || !(ptr = strchr(rem,(optS?c:toupper(c))))); - c = optS?c:(Bit8u)toupper(c); - DOS_WriteFile (STDOUT,&c, &n); - dos.return_code = (Bit8u)(ptr-rem+1); -} - -void DOS_Shell::CMD_ATTRIB(char *args){ - HELP("ATTRIB"); - // No-Op for now. -} - -void DOS_Shell::CMD_PATH(char *args){ - HELP("PATH"); - if(args && *args && strlen(args)){ - char pathstring[DOS_PATHLENGTH+CROSS_LEN+20]={ 0 }; - strcpy(pathstring,"set PATH="); - while(args && *args && (*args=='='|| *args==' ')) - args++; - strcat(pathstring,args); - this->ParseLine(pathstring); - return; - } else { - std::string line; - if(GetEnvStr("PATH",line)) { - WriteOut("%s",line.c_str()); - } else { - WriteOut("PATH=(null)"); - } - } -} - -void DOS_Shell::CMD_VER(char *args) { - HELP("VER"); - if(args && *args) { - char* word = StripWord(args); - if(strcasecmp(word,"set")) return; - word = StripWord(args); - dos.version.major = (Bit8u)(atoi(word)); - dos.version.minor = (Bit8u)(atoi(args)); - } else WriteOut(MSG_Get("SHELL_CMD_VER_VER"),VERSION,dos.version.major,dos.version.minor); -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include + +#include "shell_inc.h" +#include "callback.h" +#include "regs.h" + + + +static SHELL_Cmd cmd_list[]={ + "CD", 0, &DOS_Shell::CMD_CHDIR, "Change Directory.", + "CLS", 0, &DOS_Shell::CMD_CLS, "Clear screen.", +// "COPY", 0, &DOS_Shell::CMD_COPY, "Copy Files.", + "DIR", 0, &DOS_Shell::CMD_DIR, "Directory View.", + "ECHO", 0, &DOS_Shell::CMD_ECHO, "Display messages and enable/disable command echoing.", + "EXIT", 0, &DOS_Shell::CMD_EXIT, "Exit from the shell.", + "HELP", 0, &DOS_Shell::CMD_HELP, "Show help.", + "MD", 0, &DOS_Shell::CMD_MKDIR, "Make Directory.", + "RD", 0, &DOS_Shell::CMD_RMDIR, "Remove Directory.", + "SET", 0, &DOS_Shell::CMD_SET, "Change environment variables.", + "IF", 0, &DOS_Shell::CMD_IF, "Performs conditional processing in batch programs.", + "GOTO", 0, &DOS_Shell::CMD_GOTO, "Jump to a labeled line in a batch script.", + "TYPE", 0, &DOS_Shell::CMD_TYPE, "Display the contents of a text-file.", +/* + "CHDIR", 0, &DOS_Shell::CMD_CHDIR, "Change Directory", + "MKDIR", 0, &DOS_Shell::CMD_MKDIR, "Make Directory", + "RMDIR", 0, &DOS_Shell::CMD_RMDIR, "Remove Directory", +*/ + 0,0,0,0 +}; + +void DOS_Shell::DoCommand(char * line) { +/* First split the line into command and arguments */ + line=trim(line); + char cmd[255]; + char * cmd_write=cmd; + while (*line) { + if (*line==32) break; + if (*line=='/') break; + *cmd_write++=*line++; + } + *cmd_write=0; + if (strlen(cmd)==0) return; + line=trim(line); +/* Check the internal list */ + Bit32u cmd_index=0; + while (cmd_list[cmd_index].name) { + if (strcasecmp(cmd_list[cmd_index].name,cmd)==0) { +//TODO CHECK Flags + (this->*(cmd_list[cmd_index].handler))(line); + return; + } + cmd_index++; + } +/* This isn't an internal command execute it */ + Execute(cmd,line); +} + + +void DOS_Shell::CMD_CLS(char * args) { + reg_ax=0x0003; + CALLBACK_RunRealInt(0x10); +}; + +void DOS_Shell::CMD_HELP(char * args){ + /* Print the help */ + WriteOut(MSG_Get("SHELL_CMD_HELP")); + Bit32u cmd_index=0; + while (cmd_list[cmd_index].name) { + if (!cmd_list[cmd_index].flags) WriteOut("%-8s %s\n",cmd_list[cmd_index].name,cmd_list[cmd_index].help); + cmd_index++; + } + +} + +void DOS_Shell::CMD_ECHO(char * args) { + if (!*args) { + if (echo) { WriteOut(MSG_Get("SHELL_CMD_ECHO_ON"));} + else { WriteOut(MSG_Get("SHELL_CMD_ECHO_OFF"));} + return; + } + if (strcasecmp(args,"OFF")==0) { + echo=false; + return; + } + if (strcasecmp(args,"ON")==0) { + echo=true; + return; + } + WriteOut("%s\n",args); +}; + +void DOS_Shell::CMD_EXIT(char * args) { + exit=true; +}; + +void DOS_Shell::CMD_CHDIR(char * args) { + if (!*args) { + Bit8u drive=DOS_GetDefaultDrive()+'A'; + Bit8u dir[DOS_PATHLENGTH]; + DOS_GetCurrentDir(0,dir); + WriteOut("%c:\\%s\n",drive,dir); + } + if (DOS_ChangeDir(args)) { + + } else { + WriteOut(MSG_Get("SHELL_CMD_CHDIR_ERROR"),args); + } + +}; + +void DOS_Shell::CMD_MKDIR(char * args) { + char * rem=ScanCMDRemain(args); + if (rem) { + WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); + return; + } + if (!DOS_MakeDir(args)) { + WriteOut(MSG_Get("SHELL_CMD_MKDIR_ERROR"),args); + } +}; + +void DOS_Shell::CMD_RMDIR(char * args) { + char * rem=ScanCMDRemain(args); + if (rem) { + WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); + return; + } + if (!DOS_RemoveDir(args)) { + WriteOut(MSG_Get("SHELL_CMD_RMDIR_ERROR"),args); + } +}; + +static void FormatNumber(Bit32u num,char * buf) { + Bit32u numm,numk,numb; + numb=num % 1000; + num/=1000; + numk=num % 1000; + num/=1000; + numm=num; + if (numm) { + sprintf(buf,"%d,%03d,%03d",numm,numk,numb); + return; + }; + if (numk) { + sprintf(buf,"%d,%03d",numk,numb); + return; + }; + sprintf(buf,"%d",numb); +} + +void DOS_Shell::CMD_DIR(char * args) { + char numformat[16]; + char path[DOS_PATHLENGTH]; + + bool optW=ScanCMDBool(args,"W"); + bool optS=ScanCMDBool(args,"S"); + bool optP=ScanCMDBool(args,"P"); + char * rem=ScanCMDRemain(args); + if (rem) { + WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); + return; + } + + Bit32u byte_count,file_count,dir_count; + Bit32u w_count=0; + byte_count=file_count=dir_count=0; + + if (strlen(args)==0) args="*.*"; + + /* Make a full path in the args */ + if (!DOS_Canonicalize(args,(Bit8u*)path)) { + WriteOut(MSG_Get("SHELL_CMD_DIR_PATH_ERROR")); + return; + } + *(strrchr(path,'\\')+1)=0; + WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),path); + + DTA_FindBlock * dta; + dta=(DTA_FindBlock *)Real2Host(dos.dta); + bool ret=DOS_FindFirst(args,0xffff); + if (!ret) { + WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args); + return; + } + + while (ret) { + +/* File name and extension */ + char * ext=""; + if (!optW && (*dta->name != '.')) { + ext = strrchr(dta->name, '.'); + if (!ext) ext = ""; + else *ext++ = '\0'; + }; + + Bit8u day = dta->date & 0x001f; + Bit8u month = (dta->date >> 5) & 0x000f; + Bit8u hour = dta->time >> 5 >> 6; + Bit8u minute = (dta->time >> 5) & 0x003f; + Bit16u year = (dta->date >> 9) + 1980; + + /* output the file */ + if (dta->attr & DOS_ATTR_DIRECTORY) { + if (optW) { + WriteOut("[%s]",dta->name); + for (Bitu i=14-strlen(dta->name);i>0;i--) WriteOut(" "); + } else { + WriteOut("%-8s %-3s %-16s %02d-%02d-%04d %2d:%02d\n",dta->name,ext,"",day,month,year,hour,minute); + } + dir_count++; + } else { + if (optW) { + WriteOut("%-16s",dta->name); + } else { + FormatNumber(dta->size,numformat); + WriteOut("%-8s %-3s %16s %02d-%02d-%04d %2d:%02d\n",dta->name,ext,numformat,day,month,year,hour,minute); + } + file_count++; + byte_count+=dta->size; + } + if (optW) { + w_count++; + } + ret=DOS_FindNext(); + } + if (optW) { + if (w_count%5) WriteOut("\n"); + } + /* Show the summary of results */ + FormatNumber(byte_count,numformat); + WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_USED"),file_count,numformat); + //TODO Free Space + FormatNumber(1024*1024*100,numformat); + WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_FREE"),dir_count,numformat); +} + +void DOS_Shell::CMD_COPY(char * args) { + char * rem=ScanCMDRemain(args); + if (rem) { + WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); + return; + } + +} + +void DOS_Shell::CMD_SET(char * args) { + if (!*args) { + /* No command line show all environment lines */ + Bit32u count=GetEnvCount(); + for (Bit32u a=0;a=n) ==(!has_not)) DoCommand(args); + return; + } + /* Normal if string compare */ + if (!*args) { SyntaxError();return;}; + char * word2=args; + args=StripWord(word2); + if ((strcmp(word,word2)==0)==(!has_not)) DoCommand(args); +} + +void DOS_Shell::CMD_GOTO(char * args) { + if (!bf) return; + if (*args==':') args++; + if (!*args) { + WriteOut(MSG_Get("SHELL_CMD_GOTO_MISSING_LABEL")); + return; + } + if (!bf->Goto(args)) { + WriteOut(MSG_Get("SHELL_CMD_GOTO_LABEL_NOT_FOUND"),args); + return; + } +} + + +void DOS_Shell::CMD_TYPE(char * args) { + + if (!*args) { + WriteOut(MSG_Get("SHELL_SYNTAXERROR")); + return; + } + Bit16u handle; + char * word; +nextfile: + word=args; + args=StripWord(word); + if (!DOS_OpenFile(word,0,&handle)) { + WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),word); + return; + } + Bit16u n;Bit8u c; + do { + n=1; + DOS_ReadFile(handle,&c,&n); + DOS_WriteFile(STDOUT,&c,&n); + } while (n); + DOS_CloseFile(handle); + if (*args) goto nextfile; +} + + + diff --git a/src/shell/shell_inc.h b/src/shell/shell_inc.h new file mode 100644 index 0000000..d76d4ba --- /dev/null +++ b/src/shell/shell_inc.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include +#include "dosbox.h" +#include "mem.h" +#include "programs.h" +#include "dos_inc.h" +#include "regs.h" +#include "support.h" +#include "callback.h" + +#define CMD_MAXLINE 4096 +#define CMD_MAXCMDS 20 +#define CMD_OLDSIZE 4096 +extern Bitu call_shellstop; +class DOS_Shell; + + +class BatchFile { +public: + BatchFile(DOS_Shell * host,char * name, char * cmd_line); + ~BatchFile(); + bool ReadLine(char * line); + bool Goto(char * where); + Bit16u file_handle; + Bit32u line_count; + char * cmd_words[CMD_MAXCMDS]; + char cmd_buffer[128]; //Command line can only be 128 chars + Bit32u cmd_count; + bool echo; + DOS_Shell * shell; + BatchFile * prev; +}; + + + +class DOS_Shell : public Program { +public: + DOS_Shell(PROGRAM_Info * program_info); + void Run(void); +/* A load of subfunctions */ + void ParseLine(char * line); + Bit32u GetRedirection(char *s, char **ifn, char **ofn); + void InputCommand(char * line); + void ShowPrompt(); + void DoCommand(char * cmd); + void Execute(char * name,char * args); +/* Some internal used functions */ + char * Which(char * name); +/* Some supported commands */ + void CMD_HELP(char * args); + void CMD_CLS(char * args); + void CMD_COPY(char * args); + void CMD_DIR(char * args); + void CMD_ECHO(char * args); + void CMD_EXIT(char * args); + void CMD_MKDIR(char * args); + void CMD_CHDIR(char * args); + void CMD_RMDIR(char * args); + void CMD_SET(char * args); + void CMD_IF(char * args); + void CMD_GOTO(char * args); + void CMD_TYPE(char * args); + void SyntaxError(void); + + /* The shell's variables */ + Bit16u input_handle; + BatchFile * bf; + bool echo; + bool exit; + struct { + char buffer[CMD_OLDSIZE]; + Bitu index; + Bitu size; + } old; + +}; + +struct SHELL_Cmd { + const char * name; /* Command name*/ + Bit32u flags; /* Flags about the command */ + void (DOS_Shell::*handler)(char * args); /* Handler for this command */ + const char * help; /* String with command help */ +}; + + diff --git a/src/shell/shell_misc.cpp b/src/shell/shell_misc.cpp index e1eb505..1d003c3 100644 --- a/src/shell/shell_misc.cpp +++ b/src/shell/shell_misc.cpp @@ -1,585 +1,248 @@ -/* - * Copyright (C) 2002-2008 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* $Id: shell_misc.cpp,v 1.53 2008/09/07 10:55:16 c2woody Exp $ */ - -#include -#include -#include //std::copy -#include //std::front_inserter -#include "shell.h" -#include "regs.h" -#include "callback.h" -#include "support.h" - -void DOS_Shell::ShowPrompt(void) { - Bit8u drive=DOS_GetDefaultDrive()+'A'; - char dir[DOS_PATHLENGTH]; - dir[0] = 0; //DOS_GetCurrentDir doesn't always return something. (if drive is messed up) - DOS_GetCurrentDir(0,dir); - WriteOut("%c:\\%s>",drive,dir); -} - -static void outc(Bit8u c) { - Bit16u n=1; - DOS_WriteFile(STDOUT,&c,&n); -} - -void DOS_Shell::InputCommand(char * line) { - Bitu size=CMD_MAXLINE-2; //lastcharacter+0 - Bit8u c;Bit16u n=1; - Bitu str_len=0;Bitu str_index=0; - Bit16u len=0; - bool current_hist=false; // current command stored in history? - - line[0] = '\0'; - - std::list::iterator it_history = l_history.begin(), it_completion = l_completion.begin(); - - while (size) { - dos.echo=false; - while(!DOS_ReadFile(input_handle,&c,&n)) { - Bit16u dummy; - DOS_CloseFile(input_handle); - DOS_OpenFile("con",2,&dummy); - LOG(LOG_MISC,LOG_ERROR)("Reopening the input handle.This is a bug!"); - } - if (!n) { - size=0; //Kill the while loop - continue; - } - switch (c) { - case 0x00: /* Extended Keys */ - { - DOS_ReadFile(input_handle,&c,&n); - switch (c) { - - case 0x3d: /* F3 */ - if (!l_history.size()) break; - it_history = l_history.begin(); - if (it_history != l_history.end() && it_history->length() > str_len) { - const char *reader = &(it_history->c_str())[str_len]; - while ((c = *reader++)) { - line[str_index ++] = c; - DOS_WriteFile(STDOUT,&c,&n); - } - str_len = str_index = (Bitu)it_history->length(); - size = CMD_MAXLINE - str_index - 2; - line[str_len] = 0; - } - break; - - case 0x4B: /* LEFT */ - if (str_index) { - outc(8); - str_index --; - } - break; - - case 0x4D: /* RIGHT */ - if (str_index < str_len) { - outc(line[str_index++]); - } - break; - - case 0x47: /* HOME */ - while (str_index) { - outc(8); - str_index--; - } - break; - - case 0x4F: /* END */ - while (str_index < str_len) { - outc(line[str_index++]); - } - break; - - case 0x48: /* UP */ - if (l_history.empty() || it_history == l_history.end()) break; - - // store current command in history if we are at beginning - if (it_history == l_history.begin() && !current_hist) { - current_hist=true; - l_history.push_front(line); - } - - for (;str_index>0; str_index--) { - // removes all characters - outc(8); outc(' '); outc(8); - } - strcpy(line, it_history->c_str()); - len = (Bit16u)it_history->length(); - str_len = str_index = len; - size = CMD_MAXLINE - str_index - 2; - DOS_WriteFile(STDOUT, (Bit8u *)line, &len); - it_history ++; - break; - - case 0x50: /* DOWN */ - if (l_history.empty() || it_history == l_history.begin()) break; - - // not very nice but works .. - it_history --; - if (it_history == l_history.begin()) { - // no previous commands in history - it_history ++; - - // remove current command from history - if (current_hist) { - current_hist=false; - l_history.pop_front(); - } - break; - } else it_history --; - - for (;str_index>0; str_index--) { - // removes all characters - outc(8); outc(' '); outc(8); - } - strcpy(line, it_history->c_str()); - len = (Bit16u)it_history->length(); - str_len = str_index = len; - size = CMD_MAXLINE - str_index - 2; - DOS_WriteFile(STDOUT, (Bit8u *)line, &len); - it_history ++; - - break; - case 0x53:/* DELETE */ - { - if(str_index>=str_len) break; - Bit16u a=str_len-str_index-1; - Bit8u* text=reinterpret_cast(&line[str_index+1]); - DOS_WriteFile(STDOUT,text,&a);//write buffer to screen - outc(' ');outc(8); - for(Bitu i=str_index;i0) && (dot_pos-fs_pos>0) && (dot_pos-cl_pos>0)) - strcat(mask, "*"); - else strcat(mask, "*.*"); - } else { - strcpy(mask, "*.*"); - } - - RealPt save_dta=dos.dta(); - dos.dta(dos.tables.tempdta); - - bool res = DOS_FindFirst(mask, 0xffff & ~DOS_ATTR_VOLUME); - if (!res) { - dos.dta(save_dta); - break; // TODO: beep - } - - DOS_DTA dta(dos.dta()); - char name[DOS_NAMELENGTH_ASCII];Bit32u sz;Bit16u date;Bit16u time;Bit8u att; - - std::list executable; - while (res) { - dta.GetResult(name,sz,date,time,att); - // add result to completion list - - char *ext; // file extension - if (strcmp(name, ".") && strcmp(name, "..")) { - if (dir_only) { //Handle the dir only case different (line starts with cd) - if(att & DOS_ATTR_DIRECTORY) l_completion.push_back(name); - } else { - ext = strrchr(name, '.'); - if (ext && (strcmp(ext, ".BAT") == 0 || strcmp(ext, ".COM") == 0 || strcmp(ext, ".EXE") == 0)) - // we add executables to the a seperate list and place that list infront of the normal files - executable.push_front(name); - else - l_completion.push_back(name); - } - } - res=DOS_FindNext(); - } - /* Add excutable list to front of completion list. */ - std::copy(executable.begin(),executable.end(),std::front_inserter(l_completion)); - it_completion = l_completion.begin(); - dos.dta(save_dta); - } - - if (l_completion.size() && it_completion->length()) { - for (;str_index > completion_index; str_index--) { - // removes all characters - outc(8); outc(' '); outc(8); - } - - strcpy(&line[completion_index], it_completion->c_str()); - len = (Bit16u)it_completion->length(); - str_len = str_index = completion_index + len; - size = CMD_MAXLINE - str_index - 2; - DOS_WriteFile(STDOUT, (Bit8u *)it_completion->c_str(), &len); - } - } - break; - case 0x1b: /* ESC */ - //write a backslash and return to the next line - outc('\\'); - outc('\n'); - *line = 0; // reset the line. - if (l_completion.size()) l_completion.clear(); //reset the completion list. - this->InputCommand(line); //Get the NEW line. - size = 0; // stop the next loop - str_len = 0; // prevent multiple adds of the same line - break; - default: - if (l_completion.size()) l_completion.clear(); - if(str_index < str_len && true) { //mem_readb(BIOS_KEYBOARD_FLAGS1)&0x80) dev_con.h ? - outc(' ');//move cursor one to the right. - Bit16u a = str_len - str_index; - Bit8u* text=reinterpret_cast(&line[str_index]); - DOS_WriteFile(STDOUT,text,&a);//write buffer to screen - outc(8);//undo the cursor the right. - for(Bitu i=str_len;i>str_index;i--) { - line[i]=line[i-1]; //move internal buffer - outc(8); //move cursor back (from write buffer to screen) - } - line[++str_len]=0;//new end (as the internal buffer moved one place to the right - size--; - }; - - line[str_index]=c; - str_index ++; - if (str_index > str_len){ - line[str_index] = '\0'; - str_len++; - size--; - } - DOS_WriteFile(STDOUT,&c,&n); - break; - } - } - - if (!str_len) return; - str_len++; - - // remove current command from history if it's there - if (current_hist) { - current_hist=false; - l_history.pop_front(); - } - - // add command line to history - l_history.push_front(line); it_history = l_history.begin(); - if (l_completion.size()) l_completion.clear(); -} - -std::string full_arguments = ""; -bool DOS_Shell::Execute(char * name,char * args) { -/* return true => don't check for hardware changes in do_command - * return false => check for hardware changes in do_command */ - char fullname[DOS_PATHLENGTH+4]; //stores results from Which - char* p_fullname; - char line[CMD_MAXLINE]; - if(strlen(args)!= 0){ - if(*args != ' '){ //put a space in front - line[0]=' ';line[1]=0; - strncat(line,args,CMD_MAXLINE-2); - line[CMD_MAXLINE-1]=0; - } - else - { - safe_strncpy(line,args,CMD_MAXLINE); - } - }else{ - line[0]=0; - }; - - /* check for a drive change */ - if (((strcmp(name + 1, ":") == 0) || (strcmp(name + 1, ":\\") == 0)) && isalpha(*name)) - { - if (!DOS_SetDrive(toupper(name[0])-'A')) { - WriteOut(MSG_Get("SHELL_EXECUTE_DRIVE_NOT_FOUND"),toupper(name[0])); - } - return true; - } - /* Check for a full name */ - p_fullname = Which(name); - if (!p_fullname) return false; - strcpy(fullname,p_fullname); - const char* extension = strrchr(fullname,'.'); - - /*always disallow files without extension from being executed. */ - /*only internal commands can be run this way and they never get in this handler */ - if(extension == 0) - { - //Check if the result will fit in the parameters. Else abort - if(strlen(fullname) >( DOS_PATHLENGTH - 1) ) return false; - char temp_name[DOS_PATHLENGTH+4],* temp_fullname; - //try to add .com, .exe and .bat extensions to filename - - strcpy(temp_name,fullname); - strcat(temp_name,".COM"); - temp_fullname=Which(temp_name); - if (temp_fullname) { extension=".com";strcpy(fullname,temp_fullname); } - - else - { - strcpy(temp_name,fullname); - strcat(temp_name,".EXE"); - temp_fullname=Which(temp_name); - if (temp_fullname) { extension=".exe";strcpy(fullname,temp_fullname);} - - else - { - strcpy(temp_name,fullname); - strcat(temp_name,".BAT"); - temp_fullname=Which(temp_name); - if (temp_fullname) { extension=".bat";strcpy(fullname,temp_fullname);} - - else - { - return false; - } - - } - } - } - - if (strcasecmp(extension, ".bat") == 0) - { /* Run the .bat file */ - /* delete old batch file if call is not active*/ - bool temp_echo=echo; /*keep the current echostate (as delete bf might change it )*/ - if(bf && !call) delete bf; - bf=new BatchFile(this,fullname,line); - echo=temp_echo; //restore it. - } - else - { /* only .bat .exe .com extensions maybe be executed by the shell */ - if(strcasecmp(extension, ".com") !=0) - { - if(strcasecmp(extension, ".exe") !=0) return false; - } - /* Run the .exe or .com file from the shell */ - /* Allocate some stack space for tables in physical memory */ - reg_sp-=0x200; - //Add Parameter block - DOS_ParamBlock block(SegPhys(ss)+reg_sp); - block.Clear(); - //Add a filename - RealPt file_name=RealMakeSeg(ss,reg_sp+0x20); - MEM_BlockWrite(Real2Phys(file_name),fullname,(Bitu)(strlen(fullname)+1)); - - /* HACK: Store full commandline for mount and imgmount */ - full_arguments.assign(line); - - /* Fill the command line */ - CommandTail cmdtail; - cmdtail.count = 0; - memset(&cmdtail.buffer,0,126); //Else some part of the string is unitialized (valgrind) - if (strlen(line)>126) line[126]=0; - cmdtail.count=(Bit8u)strlen(line); - memcpy(cmdtail.buffer,line,strlen(line)); - cmdtail.buffer[strlen(line)]=0xd; - /* Copy command line in stack block too */ - MEM_BlockWrite(SegPhys(ss)+reg_sp+0x100,&cmdtail,128); - /* Parse FCB (first two parameters) and put them into the current DOS_PSP */ - Bit8u add; - FCB_Parsename(dos.psp(),0x5C,0x00,cmdtail.buffer,&add); - FCB_Parsename(dos.psp(),0x6C,0x00,&cmdtail.buffer[add],&add); - block.exec.fcb1=RealMake(dos.psp(),0x5C); - block.exec.fcb2=RealMake(dos.psp(),0x6C); - /* Set the command line in the block and save it */ - block.exec.cmdtail=RealMakeSeg(ss,reg_sp+0x100); - block.SaveData(); -#if 0 - /* Save CS:IP to some point where i can return them from */ - Bit32u oldeip=reg_eip; - Bit16u oldcs=SegValue(cs); - RealPt newcsip=CALLBACK_RealPointer(call_shellstop); - SegSet16(cs,RealSeg(newcsip)); - reg_ip=RealOff(newcsip); -#endif - /* Start up a dos execute interrupt */ - reg_ax=0x4b00; - //Filename pointer - SegSet16(ds,SegValue(ss)); - reg_dx=RealOff(file_name); - //Paramblock - SegSet16(es,SegValue(ss)); - reg_bx=reg_sp; - SETFLAGBIT(IF,false); - CALLBACK_RunRealInt(0x21); - /* Restore CS:IP and the stack */ - reg_sp+=0x200; -#if 0 - reg_eip=oldeip; - SegSet16(cs,oldcs); -#endif - } - return true; //Executable started -} - - - - -static const char * bat_ext=".BAT"; -static const char * com_ext=".COM"; -static const char * exe_ext=".EXE"; -static char which_ret[DOS_PATHLENGTH+4]; - -char * DOS_Shell::Which(char * name) { - size_t name_len = strlen(name); - if(name_len >= DOS_PATHLENGTH) return 0; - - /* Parse through the Path to find the correct entry */ - /* Check if name is already ok but just misses an extension */ - - if (DOS_FileExists(name)) return name; - /* try to find .com .exe .bat */ - strcpy(which_ret,name); - strcat(which_ret,com_ext); - if (DOS_FileExists(which_ret)) return which_ret; - strcpy(which_ret,name); - strcat(which_ret,exe_ext); - if (DOS_FileExists(which_ret)) return which_ret; - strcpy(which_ret,name); - strcat(which_ret,bat_ext); - if (DOS_FileExists(which_ret)) return which_ret; - - - /* No Path in filename look through path environment string */ - char path[DOS_PATHLENGTH];std::string temp; - if (!GetEnvStr("PATH",temp)) return 0; - const char * pathenv=temp.c_str(); - if (!pathenv) return 0; - pathenv=strchr(pathenv,'='); - if (!pathenv) return 0; - pathenv++; - Bitu i_path = 0; - while (*pathenv) { - /* remove ; and ;; at the beginning. (and from the second entry etc) */ - while(*pathenv && (*pathenv ==';')) - pathenv++; - - /* get next entry */ - i_path = 0; /* reset writer */ - while(*pathenv && (*pathenv !=';') && (i_path < DOS_PATHLENGTH) ) - path[i_path++] = *pathenv++; - - if(i_path == DOS_PATHLENGTH) { - /* If max size. move till next ; and terminate path */ - while(*pathenv != ';') - pathenv++; - path[DOS_PATHLENGTH - 1] = 0; - } else path[i_path] = 0; - - - /* check entry */ - if(size_t len = strlen(path)){ - if(len >= (DOS_PATHLENGTH - 2)) continue; - - if(path[len - 1] != '\\') { - strcat(path,"\\"); - len++; - } - - //If name too long =>next - if((name_len + len + 1) >= DOS_PATHLENGTH) continue; - strcat(path,name); - - strcpy(which_ret,path); - if (DOS_FileExists(which_ret)) return which_ret; - strcpy(which_ret,path); - strcat(which_ret,com_ext); - if (DOS_FileExists(which_ret)) return which_ret; - strcpy(which_ret,path); - strcat(which_ret,exe_ext); - if (DOS_FileExists(which_ret)) return which_ret; - strcpy(which_ret,path); - strcat(which_ret,bat_ext); - if (DOS_FileExists(which_ret)) return which_ret; - } - } - return 0; -} +/* + * Copyright (C) 2002 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include "shell_inc.h" +#include "cpu.h" + + +void DOS_Shell::ShowPrompt(void) { + Bit8u drive=DOS_GetDefaultDrive()+'A'; + Bit8u dir[DOS_PATHLENGTH]; + DOS_GetCurrentDir(0,dir); + WriteOut("%c:\\%s>",drive,dir); +} + + +static void outc(Bit8u c) { + Bit16u n=1; + DOS_WriteFile(STDOUT,&c,&n); +} + +static void outs(char * str) { + Bit16u n=strlen(str); + DOS_WriteFile(STDOUT,(Bit8u *)str,&n); +} + +void DOS_Shell::InputCommand(char * line) { + char * prev=old.buffer; + char * reader; + Bitu size=CMD_MAXLINE-1; + Bit8u c;Bit16u n=1; + Bitu str_len=0;Bitu str_index=0; + + while (size) { + DOS_ReadFile(input_handle,&c,&n); + if (!n) { + size=0; //Kill the while loop + continue; + } + switch (c) { + case 0x00: /* Extended Keys */ + { + DOS_ReadFile(input_handle,&c,&n); + switch (c) { + case 0x3d: /* F3 */ + if (strlen(old.buffer)>str_len) { + reader=&old.buffer[str_len]; + while (c=*reader++) { + line[str_index]=c; + str_len++; + str_index++; + size--; + DOS_WriteFile(STDOUT,&c,&n); + } + } + break; + default: + break; + + + } + }; + break; + case 0x08: /* BackSpace */ + if (str_index>0) { + Bit32u str_remain=str_len-str_index; + if (str_remain) { + memcpy(&line[str_index-1],&line[str_index],str_remain); + line[str_len]=0; + /* Go back to redraw */ + for (;str_remain>0;str_remain--) { + outc(8); + } + } + str_index--;str_len--; + outc(8); + outc(' '); + outc(8); + + } + break; + case 0x0a: /* New Line not handled */ + /* Don't care */ + break; + case 0x0d: /* Return */ + outc('\n'); + size=0; //Kill the while loop + break; + default: + line[str_index]=c; + str_len++;//This should depend on insert being active + str_index++; + size--; + DOS_WriteFile(STDOUT,&c,&n); + break; + } + } +/* String is inputted now save it in the buffer */ + line[str_len]=0; + if (!str_len) return; + str_len++; + //Not quite perfect last entries can get screwed :) + size_t first_len=strlen(old.buffer)+1; + memmove(&old.buffer[first_len],&old.buffer[0],CMD_OLDSIZE-first_len); + strcpy(old.buffer,line); + + + +} + +void DOS_Shell::Execute(char * name,char * args) { + char * fullname; + + /* check for a drive change */ + if ((strcmp(name + 1, ":") == 0) && isalpha(*name)) + { + if (!DOS_SetDrive(toupper(name[0])-'A')) { + WriteOut(MSG_Get("SHELL_EXECUTE_DRIVE_NOT_FOUND"),toupper(name[0])); + } + return; + } + /* Check for a full name */ + fullname=Which(name); + if (!fullname) { + WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND")); + return; + } + if (strcasecmp(strrchr(fullname, '.'), ".bat") == 0) { + /* Run the .bat file */ + bf=new BatchFile(this,fullname,args); + } else { + /* Run the .exe or .com file */ + ParamBlock block; + /* Fill the command line */ + CommandTail cmd; + if (strlen(args)>126) args[126]=0; + cmd.count=strlen(args); + memcpy(cmd.buffer,args,strlen(args)); + cmd.buffer[strlen(args)]=0xd; + + MEM_BlockWrite(real_phys(prog_info->psp_seg,128),&cmd,128); + block.exec.cmdtail=RealMake(prog_info->psp_seg,128); + block.exec.envseg=0; + block.exec.fcb1=0; + block.exec.fcb2=0; + /* Save CS:IP to some point where i can return them from */ + RealPt newcsip; + newcsip=CALLBACK_RealPointer(call_shellstop); + SetSegment_16(cs,RealSeg(newcsip)); + reg_ip=RealOff(newcsip); + + DOS_Execute(fullname,&block,0); + DOSBOX_RunMachine(); + Bit16u blah=0; + } + + +} + + + + +static char * bat_ext=".BAT"; +static char * com_ext=".COM"; +static char * exe_ext=".EXE"; +static char which_ret[DOS_PATHLENGTH]; + +char * DOS_Shell::Which(char * name) { + /* Parse through the Path to find the correct entry */ + +// if (which_result) free(which_result); + /* Check for extension */ + + + + /* Check if name is already ok but just misses an extension */ + char * ext=strrchr(name,'.'); + if (ext) if (strlen(ext)>4) ext=0; + if (ext) { + if (DOS_FileExists(name)) return name; + } else { + /* try to find .exe .com .bat */ + strcpy(which_ret,name); + strcat(which_ret,bat_ext); + if (DOS_FileExists(which_ret)) return which_ret; + strcpy(which_ret,name); + strcat(which_ret,com_ext); + if (DOS_FileExists(which_ret)) return which_ret; + strcpy(which_ret,name); + strcat(which_ret,exe_ext); + if (DOS_FileExists(which_ret)) return which_ret; + } + + /* No Path in filename look through %path% */ + + static char path[DOS_PATHLENGTH]; + char * pathenv=GetEnvStr("PATH"); + if (!pathenv) return 0; + pathenv=strchr(pathenv,'='); + if (!pathenv) return 0; + pathenv++; + char * path_write=path; + while (*pathenv) { + if (*pathenv!=';') { + *path_write++=*pathenv++; + } + if (*pathenv==';' || *(pathenv)==0) { + if (*path_write!='\\') *path_write++='\\'; + *path_write++=0; + strcat(path,name); + strcpy(which_ret,path); + if (ext) { + if (DOS_FileExists(which_ret)) return which_ret; + } else { + strcpy(which_ret,path); + strcat(which_ret,bat_ext); + if (DOS_FileExists(which_ret)) return which_ret; + strcpy(which_ret,path); + strcat(which_ret,com_ext); + if (DOS_FileExists(which_ret)) return which_ret; + strcpy(which_ret,path); + strcat(which_ret,exe_ext); + if (DOS_FileExists(which_ret)) return which_ret; + } + + path_write=path; + if (*pathenv) pathenv++; + } + } + return 0; +} + diff --git a/src/winres.rc b/src/winres.rc deleted file mode 100644 index 861e48f..0000000 --- a/src/winres.rc +++ /dev/null @@ -1,37 +0,0 @@ - -#include "afxres.h" - -// icon resource -dosbox_ico ICON "dosbox.ico" - - -// version resource -VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,72,0,0 - PRODUCTVERSION 0,72,0,0 - FILEFLAGSMASK 0x3fL - FILEFLAGS 0x0L - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "© 2002-2009 DOSBox Team, published under GNU GPL" - VALUE "CompanyName", "DOSBox Team" - VALUE "FileDescription", "DOSBox DOS Emulator" - VALUE "FileVersion", "0, 72, 0, 0" - VALUE "InternalName", "DOSBox" - VALUE "LegalCopyright", "Copyright © 2002-2009 DOSBox Team" - VALUE "OriginalFilename", "dosbox.exe" - VALUE "ProductName", "DOSBox DOS Emulator" - VALUE "ProductVersion", "0, 72, 0, 0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END diff --git a/visualc/Makefile.am b/visualc/Makefile.am new file mode 100644 index 0000000..f484b93 --- /dev/null +++ b/visualc/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = dosbox.dsw dosbox.dsp \ No newline at end of file diff --git a/visualc/Makefile.in b/visualc/Makefile.in new file mode 100644 index 0000000..05885e8 --- /dev/null +++ b/visualc/Makefile.in @@ -0,0 +1,205 @@ +# Makefile.in generated by automake 1.6.1 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +EXTRA_DIST = dosbox.dsw dosbox.dsp +subdir = visualc +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +DIST_COMMON = Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits visualc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: +tags: TAGS +TAGS: + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic uninstall uninstall-am uninstall-info-am + +# 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/visualc/dosbox.dsp b/visualc/dosbox.dsp new file mode 100644 index 0000000..f7a513b --- /dev/null +++ b/visualc/dosbox.dsp @@ -0,0 +1,639 @@ +# Microsoft Developer Studio Project File - Name="dosbox" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=dosbox - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "dosbox.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "dosbox.mak" CFG="dosbox - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "dosbox - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "dosbox - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "dosbox - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /G6 /MD /W3 /GX /O1 /Op /Ob2 /I "../include" /I "../src/platform/visualc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FAs /FD /QxMi /bQipo /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 sdlmain.lib sdl.lib curses.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "dosbox - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../include" /I "../src/platform/visualc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 sdlmain.lib sdl.lib curses.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "dosbox - Win32 Release" +# Name "dosbox - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "cpu" + +# PROP Default_Filter "" +# Begin Group "core_16" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\cpu\core_16\helpers.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_16\instructions.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_16\main.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_16\prefix_66.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_16\prefix_66_of.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_16\prefix_of.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_16\start.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_16\stop.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_16\support.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_16\table_ea.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\src\cpu\callback.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\cpu.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\flags.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\modrm.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\modrm.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\slow_16.cpp +# End Source File +# End Group +# Begin Group "debug" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\debug\debug.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\debug\debug_disasm.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\debug\debug_gui.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\debug\debug_inc.h +# End Source File +# Begin Source File + +SOURCE=..\src\debug\debug_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\debug\disasm_tables.h +# End Source File +# End Group +# Begin Group "dos" + +# PROP Default_Filter "" +# Begin Group "devices" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\dos\dev_con.h +# End Source File +# End Group +# Begin Group "drives" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\dos\drive_local.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\drive_virtual.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\drives.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\drives.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\src\dos\dos.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\dos_classes.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\dos_devices.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\dos_execute.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\dos_files.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\dos_ioctl.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\dos_memory.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\dos_misc.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\dos_programs.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\dos_tables.cpp +# End Source File +# End Group +# Begin Group "gui" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\gui\render.cpp +# End Source File +# Begin Source File + +SOURCE=..\include\render.h +# End Source File +# Begin Source File + +SOURCE=..\src\gui\sdlmain.cpp +# End Source File +# Begin Source File + +SOURCE=..\include\video.h +# End Source File +# End Group +# Begin Group "hardware" + +# PROP Default_Filter "" +# Begin Group "vga" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\hardware\vga.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\vga.h +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\vga_attr.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\vga_crtc.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\vga_dac.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\vga_draw.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\vga_fonts.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\vga_gfx.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\vga_memory.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\vga_misc.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\vga_seq.cpp +# End Source File +# End Group +# Begin Source File + +SOURCE=..\src\hardware\adlib.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\dma.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\gameblaster.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\hardware.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\iohandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\joystick.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\keyboard.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\memory.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\mixer.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\pcspeaker.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\pic.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\sblaster.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\tandy_sound.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\timer.cpp +# End Source File +# End Group +# Begin Group "ints" + +# PROP Default_Filter "" +# Begin Group "int10" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\ints\int10.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\int10.h +# End Source File +# Begin Source File + +SOURCE=..\src\ints\int10_char.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\int10_memory.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\int10_misc.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\int10_modes.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\int10_pal.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\int10_put_pixel.cpp +# End Source File +# End Group +# Begin Source File + +SOURCE=..\src\ints\bios.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\bios_disk.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\bios_keyboard.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\ems.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\mouse.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\ints\xms.cpp +# End Source File +# End Group +# Begin Group "misc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\misc\messages.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\misc\plugins.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\misc\programs.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\misc\setup.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\misc\support.cpp +# End Source File +# End Group +# Begin Group "shell" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\shell\shell.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\shell\shell_batch.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\shell\shell_cmds.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\shell\shell_inc.h +# End Source File +# Begin Source File + +SOURCE=..\src\shell\shell_misc.cpp +# End Source File +# End Group +# Begin Group "fpu" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\fpu\fpu.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\fpu\fpu_load.h +# End Source File +# End Group +# Begin Group "visualc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\platform\visualc\config.h +# End Source File +# Begin Source File + +SOURCE=..\src\platform\visualc\dirent.c +# End Source File +# Begin Source File + +SOURCE=..\src\platform\visualc\dirent.h +# End Source File +# Begin Source File + +SOURCE=..\src\platform\visualc\unistd.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\src\dosbox.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\bios.h +# End Source File +# Begin Source File + +SOURCE=..\include\callback.h +# End Source File +# Begin Source File + +SOURCE=..\include\cpu.h +# End Source File +# Begin Source File + +SOURCE=..\include\cross.h +# End Source File +# Begin Source File + +SOURCE=..\include\debug.h +# End Source File +# Begin Source File + +SOURCE=..\include\dma.h +# End Source File +# Begin Source File + +SOURCE=..\include\dos_inc.h +# End Source File +# Begin Source File + +SOURCE=..\include\dos_system.h +# End Source File +# Begin Source File + +SOURCE=..\include\dosbox.h +# End Source File +# Begin Source File + +SOURCE=..\include\hardware.h +# End Source File +# Begin Source File + +SOURCE=..\include\inout.h +# End Source File +# Begin Source File + +SOURCE=..\include\joystick.h +# End Source File +# Begin Source File + +SOURCE=..\include\keyboard.h +# End Source File +# Begin Source File + +SOURCE=..\include\mem.h +# End Source File +# Begin Source File + +SOURCE=..\include\mixer.h +# End Source File +# Begin Source File + +SOURCE=..\include\mouse.h +# End Source File +# Begin Source File + +SOURCE=..\include\pic.h +# End Source File +# Begin Source File + +SOURCE=..\include\programs.h +# End Source File +# Begin Source File + +SOURCE=..\include\regs.h +# End Source File +# Begin Source File + +SOURCE=..\settings.h +# End Source File +# Begin Source File + +SOURCE=..\include\setup.h +# End Source File +# Begin Source File + +SOURCE=..\include\support.h +# End Source File +# Begin Source File + +SOURCE=..\include\timer.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\shit.txt +# End Source File +# End Target +# End Project diff --git a/visualc/dosbox.dsw b/visualc/dosbox.dsw new file mode 100644 index 0000000..a17f1dd --- /dev/null +++ b/visualc/dosbox.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "dosbox"=".\dosbox.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/visualc_net/Makefile.am b/visualc_net/Makefile.am deleted file mode 100644 index 6d1c6dd..0000000 --- a/visualc_net/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -EXTRA_DIST = dosbox.sln dosbox.vcproj \ No newline at end of file diff --git a/visualc_net/dosbox.sln b/visualc_net/dosbox.sln deleted file mode 100644 index 503642c..0000000 --- a/visualc_net/dosbox.sln +++ /dev/null @@ -1,21 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dosbox", "dosbox.vcproj", "{7FCFFB9B-8629-4D51-849C-8490CECF8AB7}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Debug.ActiveCfg = Debug|Win32 - {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Debug.Build.0 = Debug|Win32 - {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Release.ActiveCfg = Release|Win32 - {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/visualc_net/dosbox.vcproj b/visualc_net/dosbox.vcproj deleted file mode 100644 index 83c7e8c..0000000 --- a/visualc_net/dosbox.vcproj +++ /dev/null @@ -1,892 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -