From 6a0c0c74c0ff66dc8245c237398d516f7c10a097 Mon Sep 17 00:00:00 2001 From: "Carl.Kenner" Date: Sat, 2 May 2009 22:02:15 +0000 Subject: [PATCH] DOSBox 0.62 --- AUTHORS | 7 +- ChangeLog | 62 + Makefile.am | 3 +- Makefile.in | 39 +- NEWS | 61 + README | 605 +- acinclude.m4 | 51 +- aclocal.m4 | 51 +- config.guess | 769 ++- config.h.in | 82 +- config.sub | 57 +- configure | 2961 +++++++- configure.in | 39 +- docs/dosbox.1 | 61 +- include/Makefile.am | 3 + include/Makefile.in | 3 + include/bios.h | 67 +- include/callback.h | 2 +- include/cpu.h | 40 +- include/cross.h | 8 +- include/debug.h | 2 +- include/dma.h | 188 +- include/dos_inc.h | 217 +- include/dos_system.h | 38 +- include/dosbox.h | 25 +- include/fpu.h | 2 +- include/hardware.h | 12 +- include/inout.h | 63 +- include/ipx.h | 92 + include/ipxserver.h | 50 + include/joystick.h | 2 +- include/keyboard.h | 19 +- include/mapper.h | 40 + include/mem.h | 28 +- include/mixer.h | 57 +- include/mouse.h | 11 +- include/paging.h | 23 +- include/pic.h | 25 +- include/programs.h | 2 +- include/regs.h | 2 +- include/render.h | 16 +- include/serialport.h | 181 +- include/setup.h | 4 +- include/shell.h | 21 +- include/support.h | 17 +- include/timer.h | 16 +- include/vga.h | 90 +- include/video.h | 32 +- src/cpu/Makefile.am | 2 +- src/cpu/Makefile.in | 11 +- src/cpu/callback.cpp | 11 +- src/cpu/core_dyn_x86.cpp | 161 +- src/cpu/core_dyn_x86/cache.h | 371 +- src/cpu/core_dyn_x86/decoder.h | 749 ++- src/cpu/core_dyn_x86/helpers.h | 48 +- src/cpu/core_dyn_x86/risc_x86.h | 139 +- src/cpu/core_dyn_x86/string.h | 10 +- src/cpu/core_full.cpp | 39 +- src/cpu/core_full/load.h | 165 +- src/cpu/core_full/loadwrite.h | 48 +- src/cpu/core_full/op.h | 45 +- src/cpu/core_full/optable.h | 13 +- src/cpu/core_full/save.h | 47 +- src/cpu/core_full/string.h | 2 +- src/cpu/core_full/support.h | 13 +- src/cpu/core_normal.cpp | 174 +- src/cpu/core_normal/helpers.h | 31 +- src/cpu/core_normal/prefix_0f.h | 33 +- src/cpu/core_normal/prefix_66.h | 208 +- src/cpu/core_normal/prefix_66_0f.h | 18 +- src/cpu/core_normal/prefix_none.h | 310 +- src/cpu/core_normal/string.h | 22 +- src/cpu/core_normal/support.h | 149 +- src/cpu/core_normal/table_ea.h | 363 +- src/cpu/core_simple.cpp | 203 + src/cpu/cpu.cpp | 280 +- src/cpu/flags.cpp | 2 +- src/cpu/instructions.h | 18 +- src/cpu/lazyflags.h | 2 +- src/cpu/modrm.cpp | 2 +- src/cpu/modrm.h | 2 +- src/cpu/paging.cpp | 48 +- src/debug/debug.cpp | 146 +- src/debug/debug_gui.cpp | 19 +- src/debug/debug_inc.h | 6 +- src/debug/debug_win32.cpp | 2 +- src/debug/disasm_tables.h | 2 +- src/dos/Makefile.am | 6 +- src/dos/Makefile.in | 19 +- src/dos/cdrom.cpp | 16 +- src/dos/cdrom.h | 140 +- src/dos/cdrom_aspi_win32.cpp | 377 +- src/dos/cdrom_image.cpp | 651 ++ src/dos/cdrom_ioctl_linux.cpp | 2 +- src/dos/cdrom_ioctl_win32.cpp | 4 +- src/dos/dev_con.h | 525 +- src/dos/dos.cpp | 199 +- src/dos/dos_classes.cpp | 87 +- src/dos/dos_devices.cpp | 26 +- src/dos/dos_execute.cpp | 124 +- src/dos/dos_files.cpp | 81 +- src/dos/dos_ioctl.cpp | 8 +- src/dos/dos_memory.cpp | 29 +- src/dos/dos_misc.cpp | 53 +- src/dos/dos_mscdex.cpp | 67 +- src/dos/dos_programs.cpp | 466 +- src/dos/dos_tables.cpp | 67 +- src/dos/drive_cache.cpp | 81 +- src/dos/drive_fat.cpp | 1127 ++++ src/dos/drive_iso.cpp | 435 ++ src/dos/drive_local.cpp | 60 +- src/dos/drive_virtual.cpp | 10 +- src/dos/drives.cpp | 2 +- src/dos/drives.h | 241 +- src/dosbox.cpp | 145 +- src/fpu/fpu.cpp | 69 +- src/fpu/fpu_instructions.h | 88 +- src/fpu/fpu_types.h | 2 +- src/gui/Makefile.am | 4 +- src/gui/Makefile.in | 12 +- src/gui/midi.cpp | 148 +- src/gui/midi_alsa.h | 35 +- src/gui/midi_coreaudio.h | 10 +- src/gui/midi_oss.h | 10 +- src/gui/midi_win32.h | 9 +- src/gui/render.cpp | 353 +- src/gui/render_normal.h | 59 - src/gui/render_scale2x.h | 118 - src/gui/render_scalers.cpp | 121 + src/gui/render_scalers.h | 51 + src/gui/render_templates.h | 325 +- src/gui/sdl_mapper.cpp | 1258 ++++ src/gui/sdlmain.cpp | 731 +- src/hardware/Makefile.am | 12 +- src/hardware/Makefile.in | 31 +- src/hardware/adlib.cpp | 400 +- src/hardware/cmos.cpp | 135 +- src/hardware/directserial_win32.cpp | 198 + src/hardware/disney.cpp | 45 +- src/hardware/dma.cpp | 602 +- src/hardware/ega-switch.h | 9730 --------------------------- src/hardware/fmopl.c | 298 +- src/hardware/fmopl.h | 2 +- src/hardware/font-switch.h | 2562 ------- src/hardware/gameblaster.cpp | 47 +- src/hardware/gus.cpp | 1258 ++-- src/hardware/hardware.cpp | 47 +- src/hardware/iohandler.cpp | 180 +- src/hardware/ipx.cpp | 1188 ++++ src/hardware/ipxserver.cpp | 235 + src/hardware/joystick.cpp | 10 +- src/hardware/keyboard.cpp | 316 +- src/hardware/memory.cpp | 131 +- src/hardware/mixer.cpp | 513 +- src/hardware/mpu401.cpp | 617 +- src/hardware/pcspeaker.cpp | 402 +- src/hardware/pic.cpp | 199 +- src/hardware/sblaster.cpp | 964 +-- src/hardware/serialport.cpp | 415 +- src/hardware/softmodem.cpp | 966 +-- src/hardware/tandy_sound.cpp | 43 +- src/hardware/timer.cpp | 195 +- src/hardware/vga.cpp | 66 +- src/hardware/vga_attr.cpp | 27 +- src/hardware/vga_crtc.cpp | 120 +- src/hardware/vga_dac.cpp | 53 +- src/hardware/vga_draw.cpp | 524 +- src/hardware/vga_gfx.cpp | 27 +- src/hardware/vga_memory.cpp | 139 +- src/hardware/vga_misc.cpp | 284 +- src/hardware/vga_other.cpp | 316 + src/hardware/vga_seq.cpp | 29 +- src/hardware/vga_xga.cpp | 530 ++ src/hardware/ymf262.c | 2792 ++++++++ src/hardware/ymf262.h | 53 + src/ints/Makefile.am | 2 +- src/ints/Makefile.in | 17 +- src/ints/bios.cpp | 151 +- src/ints/bios_disk.cpp | 425 +- src/ints/bios_keyboard.cpp | 225 +- src/ints/dpmi.cpp | 3233 --------- src/ints/ems.cpp | 35 +- src/ints/int10.cpp | 29 +- src/ints/int10.h | 6 +- src/ints/int10_char.cpp | 90 +- src/ints/int10_memory.cpp | 8 +- src/ints/int10_misc.cpp | 6 +- src/ints/int10_modes.cpp | 490 +- src/ints/int10_pal.cpp | 2 +- src/ints/int10_put_pixel.cpp | 2 +- src/ints/int10_vesa.cpp | 28 +- src/ints/mouse.cpp | 163 +- src/ints/xms.cpp | 22 +- src/ints/xms.h | 2 +- src/misc/messages.cpp | 6 +- src/misc/programs.cpp | 14 +- src/misc/setup.cpp | 10 +- src/misc/support.cpp | 129 +- src/platform/visualc/config.h | 26 +- src/shell/shell.cpp | 107 +- src/shell/shell_batch.cpp | 4 +- src/shell/shell_cmds.cpp | 133 +- src/shell/shell_misc.cpp | 50 +- visualc_net/dosbox.vcproj | 57 +- 204 files changed, 25683 insertions(+), 25101 deletions(-) create mode 100644 include/ipx.h create mode 100644 include/ipxserver.h create mode 100644 include/mapper.h create mode 100644 src/cpu/core_simple.cpp create mode 100644 src/dos/cdrom_image.cpp create mode 100644 src/dos/drive_fat.cpp create mode 100644 src/dos/drive_iso.cpp delete mode 100644 src/gui/render_normal.h delete mode 100644 src/gui/render_scale2x.h create mode 100644 src/gui/render_scalers.cpp create mode 100644 src/gui/render_scalers.h create mode 100644 src/gui/sdl_mapper.cpp create mode 100644 src/hardware/directserial_win32.cpp delete mode 100644 src/hardware/ega-switch.h delete mode 100644 src/hardware/font-switch.h create mode 100644 src/hardware/ipx.cpp create mode 100644 src/hardware/ipxserver.cpp create mode 100644 src/hardware/vga_other.cpp create mode 100644 src/hardware/vga_xga.cpp create mode 100644 src/hardware/ymf262.c create mode 100644 src/hardware/ymf262.h delete mode 100644 src/ints/dpmi.cpp diff --git a/AUTHORS b/AUTHORS index 7d2b32a..23121d5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,9 +1,8 @@ The DOSBox Team --------------- -Sjoerd v.d. Berg +Sjoerd v.d. Berg Peter Veenstra -Felix Jakschitsch Ulf Wohlers -Tommy Frössman - +Tommy Frössman +Dean Beeler diff --git a/ChangeLog b/ChangeLog index a01db8e..5500e85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,65 @@ +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 diff --git a/Makefile.am b/Makefile.am index bfb4714..00c0c28 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,5 +3,6 @@ EXTRA_DIST = autogen.sh SUBDIRS = src include visualc docs visualc_net - +docdir = $(prefix)/share/doc/$(PACKAGE) +doc_DATA = README NEWS THANKS AUTHORS diff --git a/Makefile.in b/Makefile.in index 3428331..e839110 100644 --- a/Makefile.in +++ b/Makefile.in @@ -134,12 +134,17 @@ target_vendor = @target_vendor@ EXTRA_DIST = autogen.sh SUBDIRS = src include visualc docs visualc_net + +docdir = $(prefix)/share/doc/$(PACKAGE) +doc_DATA = README NEWS THANKS AUTHORS subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = DIST_SOURCES = +DATA = $(doc_DATA) + RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ ps-recursive install-info-recursive uninstall-info-recursive \ @@ -189,6 +194,24 @@ $(srcdir)/config.h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) distclean-hdr: -rm -f config.h stamp-h1 uninstall-info-am: +docDATA_INSTALL = $(INSTALL_DATA) +install-docDATA: $(doc_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(docdir) + @list='$(doc_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(docDATA_INSTALL) $$d$$p $(DESTDIR)$(docdir)/$$f"; \ + $(docDATA_INSTALL) $$d$$p $(DESTDIR)$(docdir)/$$f; \ + done + +uninstall-docDATA: + @$(NORMAL_UNINSTALL) + @list='$(doc_DATA)'; for p in $$list; do \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " rm -f $(DESTDIR)$(docdir)/$$f"; \ + rm -f $(DESTDIR)$(docdir)/$$f; \ + done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. @@ -446,9 +469,10 @@ distcleancheck: distclean exit 1; } >&2 check-am: all-am check: check-recursive -all-am: Makefile config.h +all-am: Makefile $(DATA) config.h installdirs: installdirs-recursive installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(docdir) install: install-recursive install-exec: install-exec-recursive @@ -491,7 +515,7 @@ info: info-recursive info-am: -install-data-am: +install-data-am: install-docDATA install-exec-am: @@ -519,7 +543,7 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-info-am +uninstall-am: uninstall-docDATA uninstall-info-am uninstall-info: uninstall-info-recursive @@ -529,16 +553,17 @@ uninstall-info: uninstall-info-recursive distclean-hdr distclean-recursive distclean-tags distcleancheck \ distdir distuninstallcheck 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-data-am install-data-recursive install-docDATA \ + 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 pdf pdf-am pdf-recursive ps ps-am \ ps-recursive tags tags-recursive uninstall uninstall-am \ - uninstall-info-am uninstall-info-recursive uninstall-recursive + uninstall-docDATA 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. diff --git a/NEWS b/NEWS index d3f4b51..b636030 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,64 @@ +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 diff --git a/README b/README index fedaf56..8db24d5 100644 --- a/README +++ b/README @@ -1,4 +1,5 @@ -DOSBox v0.61 +DOSBox v0.62 + ===== NOTE: @@ -6,7 +7,7 @@ NOTE: While we hope that, one day, DOSBox will run virtually all programs ever made for the PC...we are not there yet. At present, DOSBox run on a high- -end machine will roughly be the equivalent of a lowend 486 PC. While the 0.60 +end machine will roughly be the equivalent of a 486 PC. 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 @@ -14,12 +15,180 @@ earlier). Also note that "protected mode" games need substantially more resources and may require a much faster processor for you to run it properly in DOSBox. + + ====== -Usage: +INDEX: ====== +1. Quickstart +2. FAQ +3. Usage +4. Internal Programs +5. Special Keys +6. Keymapper +7. System Requirements +8. To run resource-demanding games +9. The config file +10. The language file +11. Building your own version of DOSBox +12. Special thanks +13. Contact + + +============== +1. Quickstart: +============== + +Type INTRO in DOSBox. That's it. + + + + +======= +2. FAQ: +======= + +Some Frequently Asked Questions: + +Q: I've got a Z instead of a C at the prompt. +Q: My CD-ROM doesn't work. +Q: The mouse doesn't work. +Q: The sound stutters. +Q: I can't type \ or : in DOSBox. +Q: The game/application can't find its CD-ROM. +Q: The game/application runs much too slow! +Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ. +Q: What sound hardware does DOSBox presently emulate? + + + + + + +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:\" would give + you a C in DOSBox which points at your Windows D:\ drive. + In Linux, "mount c /home/username" would give you a C in DOSBox + which points at /home/username in Linux. + + +Q: My CD-ROM doesn't work. +A: To mount your cdrom in DOSBox you have to specify some additional options + when mounting the cdrom. + To enable the most basic cdrom support: + - mount d f:\ -t cdrom + To enable low-level SDL-support: + - mount d f:\ -t cdrom -usecd 0 + To enable low-level ioctl-support(win2k/xp/linux): + - mount d f:\ -t cdrom -usecd 0 -ioctl + To enable low-level aspi-support (win98 with aspi-layer installed): + - mount d f:\ -t cdrom -usecd 0 -apsi + + In the commands: - d driveletter you in DOSBox + - f:\ location of cdrom on your PC. + - 0 The number of the cdrom drive, reported by mount -cd + See also the question: The game/application can't find its CD-ROM. + + +Q: The mouse doesn't work. +A: Normally DOSBox detects the mouse being used by a game. If you click on + the screen then it should get locked and work. + Sometimes the DOSBox mouse detection doesn't work with certain games. You + might have to force to lock the mouse then with ctrl-F10. + + +Q: The sound stutters. +A: You're using too much cpu power to keep DOSBox running at the current speed. + You can either lower the cycles or skip frames or get a faster machine. + You can also increase the prebuffer in the configfile + + +Q: I can't type \ or : in DOSBox. +A: This is a known problem. It only occurs if your keyboard layout isn't US. + Some possible fixes: + 1. Switch your keyboard layout. + 2. Use / instead. + 3. Add the commands you want to execute to dosbox.conf + 4. Start the keymapper (CTRL-F1 or add -startmapper switch to dosbox) + 5. for \ try the keys around "enter". For ":" try shift and the keys between + "enter" and "l" (US keyboard layout). + 6. Use keyb.com for FreeDOS (http://projects.freedos.net/keyb/). + + +Q: The game/application can't find its CD-ROM. +A: Be sure to mount the CD-ROM with -t cdrom switch. Also try adding the + correct label (-label LABEL). To enable more low-level CD-ROM support add + the following switch to mount: -usecd #, where # is the number of your + CD-ROM drive reported by mount -cd. If you run Win32 you can specify -ioctl + or -aspi. Look at the description elsewhere in this document for their + meaning. + + +Q: The game/application runs much too slow! +A: Look at the section "To run resource-demanding games" for more information. + + +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 dosbox.conf . + Start your favourite editor and look at all the settings present. To + start DOSBox with your new settings: dosbox -conf dosbox.conf + + +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, which is not very well documented and as such is only + a best guess as to the sound's accuracy. + - Adlib + Borrowed from MAME, this emulation is almost perfect and includes the + Adlib's ability to almost play digitized sound. + - SoundBlaster Pro + Coupled with the Adlib, DOSBox provides Soundblaster Pro level 8-bit + stereo sound. + - 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: Great README, but I still don't get it. +A: While unlikely, this seems to happen. A look at "The Newbie's + pictorial guide to DOSBox" located at + http://vogons.zetafleet.com/viewforum.php?f=39 might help you. + + +For more questions read the remainder of this README and/or check +the site/forum: +http://dosbox.sourceforge.net + + + + +========= +3. Usage: +========= + +An overview of the commandline options you can give to DOSBox: dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile] [-lang languagefile] [-machine machinetype] [-noconsole] + [-startmapper] + +dosbox -version name If "name" is a directory it'll mount that as the C: drive. @@ -43,13 +212,19 @@ dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile] Start dosbox using the language string specified in "languagefile". -noconsole (Windows Only) - Start dosbox without showing the console window, output will + Start dosbox without showing the console window. Output will be redirected to stdout.txt and stderr.txt -machine machinetype Setup dosbox to emulate a specific type of machine. Valid choices are: - auto,hercules,cga,tandy,vga. + hercules, cga, tandy, vga (default). + -startmapper + Enter the keymapper directly on startup. Useful for people with + keyboard problems. + + -version + output version information and exit. Useful for frontends. Note: If a name/command/configfile/languagefile contains a space in it, put the whole name/command/configfile/languagefile between quotes("example"). @@ -64,16 +239,16 @@ In Windows you can also drag directories/files onto the dosbox executable. -================== -Internal Programs: -================== +===================== +4. Internal Programs: +===================== DOSBox supports most of the DOS commands found in command.com. In addition, the following commands are available: MOUNT "Emulated Drive letter" "Real Drive or Directory" [-t type] [-aspi] [-ioctl] [-usecd number] [-size drivesize] - [-label drivelabel] + [-label drivelabel] [-freesize sizemb] MOUNT -cd Program to mount local directories as drives inside DOSBox. @@ -91,7 +266,11 @@ MOUNT -cd floppy, cdrom. -size drivesize - Sets the size of the drive. + Sets the size of the drive. + + -freesize sizemb + Sets the amount of free space available on a drive in MB's. This + is a more simple version of -size. -label drivelabel Sets the name of the drive to "drivelabel". Needed on some @@ -104,7 +283,7 @@ MOUNT -cd -ioctl Forces to use ioctl commands. Only valid if mounting a cdrom under - windows which support them (Win2000/XP/NT). + a Windows OS which support them (Win2000/XP/NT). -usecd number Forces to use SDL cdrom support for drive number. @@ -118,11 +297,11 @@ MOUNT -cd Basically, MOUNT allows you to connect real hardware to DOSBox's "emulated" PC. So MOUNT C C:\ tells DOSBox to use your real C: drive as drive C: in - DosBox. It also allows you to change the drive's letter identification for + DOSBox. It also allows you to change the drive's 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 it's mount command, you can trick into thinking it + drive. Using DOSBox and its mount command, you can trick into thinking it is on C drive while placing it where you want it. For example, if the game were in D:\TOUCHE, you can use the command MOUNT C D:\ would allow you to run Touche from the D drive. @@ -131,14 +310,16 @@ MOUNT -cd General MOUNT Examples: 1. To mount c:\floppy as a floppy : mount a c:\floppy -t floppy - 2. To mount system cdrom drive E as cdrom drive D in dosbox: + 2. To mount system cdrom drive E as cdrom drive D in DOSBox: mount d e:\ -t cdrom 3. To mount system cdrom drive at mountpoint /media/cdrom as cdrom drive D in dosbox: mount d /media/cdrom -t cdrom -usecd 0 - 4. To mount a drive with 870 mb free diskspace (rarely needed! experts only): + 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 4025,127,16513,1700 - 5. To mount /home/dos/dosgames as drive C in DOSBox: + 6. To mount /home/dos/dosgames as drive C in DOSBox: mount c /home/dos/dosgames MEM @@ -173,31 +354,272 @@ Examples: 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. + + +MIXER + Makes DOSBox display its current volume settings. + You can change this way: + + mixer channel left:right [/NOSHOW] + + channel + Can be one of the following: MASTER, DISNEY, SPKR, GUS, SB, FM. + + left:right + The volume levels in percentages. If you put a D in front it will be + in deciBell (example mixer gus d-10). + + /NOSHOW + Prevents DOSBox from showing the result if you set one + of the volume levels. + + +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] + + imagefile + location of the image files to mount in DOSBox. Path is relative to + a mount point already inside DOSBox. CD-ROM images can be mounted + directly as well (path on the host). + + -t + The following are valid image types: + floppy: Specifies a floppy image or images. 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. + 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 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 one needs to format it or one wants to boot + off of the disk using the BOOT command. When using the "none" + filesystem, one 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, + one would type: + "imgmount 3 d:\test.img -size 512,63,16,142 -fs none" + (without the quotes) Compare this with a mount to read the + drive in DOSBox, which would read as: + "imgmount e: d:\test.img -size 512,63,16,142" + + -size + The Cylinders, Heads and Sectors specification of the drive. + Required to mount hard drive images. + + An example of 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 to other operating systems inside DOSBox. + + BOOT [diskimg1.img diskimg2.img .. diskimgN.img] [-l driveletter] + + 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, one hits CTRL+F4 to swap out the current disk + and swap in the next disk in the list. Once the last disk in the list is + swapped out, the list loops back to the beginning. + + [-l driveletter] + This parameter allows one to specify the drive to boot from. + The default is the A drive, the floppy drive. One can also boot off of + a hard drive image mounted as master by specifying "-l C" + without the quotes, or the drive as slave by specifying "-l D" + + +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 out the commands + and relevant documentation. + + With regard to actually setting up a network, one system needs to be + the server. To set this up, in a DOSBox session, one should type + "IPXNET STARTSERVER" (without the quotes). The server DOSBox session will + automatically add itself to the virtual IPX network. In turn, for every + other 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. + + The following is an IPXNET command reference: + + IPXNET CONNECT + + IPXNET CONNECT opens a connection to an IPX tunneling server + running on another DOSBox session. The "address" parameter specifies + the IP address or host name of the server computer. One can also + specify the UDP port to use. By default IPXNET uses port 213, the + assigned IANA port for IPX tunneling, for its connection. + + The syntax for IPXNET CONNECT is: + IPXNET CONNECT address + + IPXNET DISCONNECT + + IPXNET DISCONNECT closes the connection to the IPX tunneling server. + + The syntax for IPXNET DISCONNECT is: + IPXNET DISCONNECT + + IPXNET STARTSERVER + + IPXNET STARTSERVER starts and IPX tunneling 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 tunneling server. + + The syntax for IPXNET STARTSERVER is: + IPXNET STARTSERVER + + IPXNET STOPSERVER + + IPXNET STOPSERVER stops the IPX tunneling 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 still using the IPX tunneling server. + + The syntax for IPXNET STOPSERVER is: + IPXNET STOPSERVER + + IPXNET PING + + IPXNET PING broadcasts a ping request through the IPX tunneled 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's sessions + IPX tunneling network. For a list of the computers connected to the + network use the IPXNET PING command. + +The syntax for IPXNET STATUS is: +IPXNET STATUS + For more information use the /? command line switch with the programs. -============= -Special Keys: -============= + +================ +5. Special Keys: +================ ALT-ENTER Go full screen and back. -CTRL-F5 Save a screenshot. -CTRL-F6 Start/Stop recording sound output to a wave file. -CTRL-F7 Decrease frameskip. -CTRL-F8 Increase frameskip. +CTRL-F1 Start the keymapper. +CTRL-F4 Swap mounted disk-image (Only used with imgmount). +CTRL-F5 Save a screenshot. +CTRL-F6 Start/Stop recording sound output to a wave file. +CTRL-ALT-F7 Start/Stop recording of OPL commands. +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 DOSox Cycles). +These are the default keybindings. They can be changed in the keymapper. + 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. -==================== -System requirements: -==================== + + +============= +6. Keymapper: +============= + +When you start the keymapper (either with CTRL-F1 or -startmapper as a +commandline argument) you are presented with a virtual keyboard. + +This virtual keyboard corresponds with the keys DOSBox will report to its +applications. If you click on a key with your mouse, you can see in the +lowerleft corner which key on your keyboard corresponds with it. + +Event: EVENT +BIND: BIND + Add Del +mod1 hold Next +mod2 +mod3 + + +EVENT + The key DOSBox will report to the applications being emulated. +BIND + The key on your keyboard (as reported by SDL) which is connected to the + EVENT. +mod1,2,3 + Modfiers. These are keys you need to have pressed as well, 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. Basicly add a key from your keyboard which + will produce the key EVENT in DOSBox. +Del + Delete the BIND to this EVENT. If an EVENT has no BINDS than it's not + possible to type this key in DOSBox. +Next + Cycle through the list of keys(BINDS) which map to this EVENT. + + +Example: +Q1. You want to have the X on your keyboard to type a Z in DOSBox. + A. With your mouse click on the Z on the keyboard mapper. Click "Add". + Now press the X key on your keyboard. + +Q2. If you click "Next" a few 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" till 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" till you find the + mapped key X. Click "Del". + + +If you change the default mapping you can save your changes by pressing +"Save". DOSBox will save the mapping to location specified in the configfile +(mapperfile=mapper.txt). At startup DOSBox will load your mapperfile if it's +present in the configfile. + + + +======================= +7. System requirements: +======================= Fast machine. My guess would be pentium-2 400+ to get decent emulation of games written for an 286 machine. @@ -206,9 +628,10 @@ them to run fast though!! Be sure to read the next section on how to speed it up somewhat. -================================ -To run resource-demanding games: -================================ + +=================================== +8. To run resource-demanding games: +=================================== DOSBox emulates the CPU, the sound and graphic cards, and some other stuff, all at the same time. You can overclock DOSBox by using CTRL+F12, but @@ -236,109 +659,31 @@ You can also try to disable the sound through the setup utility of the game to further reduce load on your CPU. -==== -FAQ: -==== -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 a C in DOSBox which points - at D:\ in win32. - In linux: mount c /home/username would give you a C in DOSBox - which points at /home/username in Linux. - -Q: The mouse doesn't work. -A: Normally dosbox detects the mouse being used by a game. If you click on - the screen then it should get locked and work. - Sometimes the dosbox mouse detection doesn't work with certain games. You - might have to force to lock the mouse then with ctrl-F10. - -Q: The sound stutters. -A: You're using too much cpu power to keep dosbox running at the current speed. - You can either lower the cycles or skip frames or get a faster machine. - -Q: I can't type \ in DOSBox. -A: This is a known problem. It only occurs if your keyboard layout isn't US. - Some possible fixes: - 1. Switch your keyboard layout. - 2. Use / instead. - 3. Add the commands you want to execute in dosbox.conf - -Q: The game/application can't find its CD-ROM. -A: Be sure to mount the CD-ROM with -t cdrom switch. Also try adding the cor- - rect label (-label LABEL). To enable more low-level cdrom support add - the following switch to mount: -usecd #, where # is the number of your - CD-ROM drive reported by mount -cd. If you run Win32 you can specify -ioctl - or -aspi. Look at the description elsewhere in this document for their - meaning. - -Q: The game/application runs much too slow! -A: Look at the section "To run resource-demanding games" for more information. - -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 dosbox.conf . - Startup your favourite editor and look at all the settings present. To - start DOSBox with your new settings: dosbox -conf dosbox.conf - -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, - which is not very well documented and as such is only a best guess as to the sound's accuracy. - - Adlib - Borrowed from MAME, this emulation is almost perfect and includes the Adlib's ability to almost - play digitized sound. - - SoundBlaster Pro - Coupled with the Adlib, DosBox provides Soundblaster Pro level 8-bit stereo sound. - - 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: Great README, but I still don't get it. -A: While unlikely this seems to happen. Maybe a look at "The Newbie's - pictorial guide to dosbox" located at - http://vogons.zetafleet.com/viewforum.php?f=39 might help you. - -For more questions check the site/forum: -http://dosbox.sourceforge.net - - -================ -The Config File: -================ +=================== +9. 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 which you can set. # and % indicate comment-lines. The generated configfile 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 if no configfile is specified with the -conf switch look in the -current directory for dosbox.conf. Then it will look for ~/.dosboxrc (linux), -~\dosbox.conf (win32) or "~/Library/Preferences/DOSBox Preferences" (MACOSX). +If no configfile is specified with the -conf switch, DOSBox will look in the +current directory for dosbox.conf. Then it will look for ~/.dosboxrc (Linux), +~\dosbox.conf (Win32) or "~/Library/Preferences/DOSBox Preferences" (MACOSX). -================== -The Language File: -================== +====================== +10. The Language File: +====================== A language file can be generated by CONFIG.COM. Read it and you will hopefully understand how to change it. @@ -347,16 +692,19 @@ or 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. -==================================== -Building your own version of DOSBox: -==================================== + +======================================== +11. Building your own version of DOSBox: +======================================== Download the source. Check the INSTALL in the source distribution. -=============== -Special Thanks: -=============== + + +=================== +12. 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. @@ -366,9 +714,12 @@ Pierre-Yves G Colin Snover for hosting our forum. The Beta Testers. -======== -Contact: -======== -Harekiet harekiet@zophar.net + +============ +13. Contact: +============ + +See the site: http://dosbox.sourceforge.net +for an emailaddress (The Crew-page). diff --git a/acinclude.m4 b/acinclude.m4 index f0a8266..5e72516 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,7 +1,7 @@ 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, +AC_DEFUN([AM_PATH_SDL], [dnl dnl Get the cflags and libraries from the sdl-config script dnl @@ -174,7 +174,7 @@ 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, +AC_DEFUN([AM_PATH_ALSA], [dnl Save the original CFLAGS, LDFLAGS, and LIBS alsa_save_CFLAGS="$CFLAGS" alsa_save_LDFLAGS="$LDFLAGS" @@ -305,7 +305,7 @@ AC_SUBST(ALSA_LIBS) AH_TOP([ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -331,4 +331,49 @@ AH_BOTTOM([#if C_HAS_ATTRIBUTE #define GCC_ATTRIBUTE(x) /* attribute not supported */ #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 + +]) diff --git a/aclocal.m4 b/aclocal.m4 index 5cae2fb..2ce994f 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -14,7 +14,7 @@ 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, +AC_DEFUN([AM_PATH_SDL], [dnl dnl Get the cflags and libraries from the sdl-config script dnl @@ -187,7 +187,7 @@ 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, +AC_DEFUN([AM_PATH_ALSA], [dnl Save the original CFLAGS, LDFLAGS, and LIBS alsa_save_CFLAGS="$CFLAGS" alsa_save_LDFLAGS="$LDFLAGS" @@ -318,7 +318,7 @@ AC_SUBST(ALSA_LIBS) AH_TOP([ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -344,7 +344,52 @@ AH_BOTTOM([#if C_HAS_ATTRIBUTE #define GCC_ATTRIBUTE(x) /* attribute not supported */ #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 + +]) # Do all the work for Automake. -*- Autoconf -*- diff --git a/config.guess b/config.guess index 71de137..77c7cba 100644 --- a/config.guess +++ b/config.guess @@ -1,9 +1,9 @@ #! /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. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. -timestamp='2001-03-16' +timestamp='2004-08-13' # 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 @@ -24,8 +24,9 @@ timestamp='2001-03-16' # 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 . +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and @@ -52,7 +53,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -87,33 +88,45 @@ if test $# != 0; then exit 1 fi +trap 'exit 1' 1 2 15 -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. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. -# 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. +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; 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 + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found + CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac +esac ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 8/24/94.) +# (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi @@ -127,29 +140,31 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) - # Netbsd (nbsd) targets should (where applicable) match one or + # 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 ;; + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-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) + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then @@ -165,70 +180,123 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac # 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 ;; + amd64:OpenBSD:*:*) + echo x86_64-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + cats:OpenBSD:*:*) + echo arm-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + luna88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-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 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips64-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit 0 ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then + case $UNAME_RELEASE in + *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. # 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'` + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? @@ -242,33 +310,18 @@ EOF 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} + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; @@ -286,6 +339,13 @@ EOF NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; @@ -314,7 +374,7 @@ EOF 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` + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) @@ -328,9 +388,6 @@ EOF 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 @@ -357,17 +414,8 @@ EOF *:*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} + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} @@ -385,6 +433,7 @@ EOF echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ @@ -406,12 +455,20 @@ EOF 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 + $CC_FOR_BUILD -o $dummy $dummy.c \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && exit 0 echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; @@ -459,7 +516,7 @@ EOF ????????: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:*:*) + i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) @@ -472,6 +529,7 @@ EOF exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include @@ -483,8 +541,7 @@ EOF exit(0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 @@ -493,7 +550,7 @@ EOF fi exit 0 ;; *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else @@ -533,10 +590,8 @@ EOF 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` + 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 @@ -545,12 +600,13 @@ EOF case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac - fi ;; - esac - if [ "${HP_ARCH}" = "" ]; then - sed 's/^ //' << EOF >$dummy.c + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include @@ -583,11 +639,21 @@ EOF 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 ;; + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + # avoid double evaluation of $set_cc_for_build + test -n "$CC_FOR_BUILD" || eval $set_cc_for_build + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) @@ -595,6 +661,7 @@ EOF echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) + eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int @@ -620,8 +687,7 @@ EOF exit (0); } EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) @@ -630,7 +696,7 @@ EOF 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; - *9??*:MPE/iX:*:*) + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) @@ -639,7 +705,7 @@ EOF hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; - i?86:OSF1:*:*) + i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else @@ -649,9 +715,6 @@ EOF 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 ;; @@ -670,42 +733,39 @@ EOF 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} + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' 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/ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' 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 ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + 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} + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; - i?86:BSD/386:*:* | i?86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) @@ -717,9 +777,6 @@ EOF *: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 ;; @@ -729,11 +786,17 @@ EOF i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; + x86:Interix*:[34]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit 0 ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + 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 + echo i586-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin @@ -745,112 +808,87 @@ EOF echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) + # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit 0 ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu 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; -} + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif 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 + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; 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} + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu 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 + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) @@ -867,6 +905,9 @@ EOF s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; @@ -876,78 +917,69 @@ EOF x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; - i?86:Linux:*:*) + 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 + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g - s/.*supported emulations: *// + s/.*supported targets: *// s/ .*// p'` - case "$ld_supported_emulations" in - i?86linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 - ;; - elf_i?86) + case "$ld_supported_targets" in + elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; - i?86coff) + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) 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; - ;; + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; 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; -} + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif 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 + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 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*:*) + i*86:DYNIX/ptx:4*:*) + # 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. echo i386-sequent-sysv4 exit 0 ;; - i?86:UNIX_SV:4.2MP:2.*) + 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, @@ -955,7 +987,27 @@ EOF # 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.*:*) + 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 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + 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} @@ -963,36 +1015,32 @@ EOF 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 + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; - i?86:*:3.2:*) + 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_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + (/bin/uname -X|grep '^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 @@ -1016,9 +1064,15 @@ EOF # "miniframe" echo m68010-convergent-sysv exit 0 ;; - M68*:*:R3V[567]*:*) + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; + M68*:*:R3V[5678]*:*) 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) + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` @@ -1029,22 +1083,19 @@ EOF 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.*:*) + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) 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]*:*) + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) @@ -1064,8 +1115,8 @@ EOF echo ns32k-sni-sysv fi exit 0 ;; - PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) @@ -1077,6 +1128,10 @@ EOF # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; @@ -1105,6 +1160,9 @@ EOF SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; @@ -1112,18 +1170,25 @@ EOF echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + *86) UNAME_PROCESSOR=i686 ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) - if test "${UNAME_MACHINE}" = "x86pc"; then + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo `uname -p`-${UNAME_MACHINE}-nto-qnx + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; - NSR-[KW]:NONSTOP_KERNEL:*:*) + NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) @@ -1146,11 +1211,6 @@ EOF 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 ;; @@ -1169,11 +1229,25 @@ EOF *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit 0 ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms && exit 0 ;; + I*) echo ia64-dec-vms && exit 0 ;; + V*) echo vax-dec-vms && exit 0 ;; + esac esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 +eval $set_cc_for_build cat >$dummy.c < @@ -1288,8 +1362,7 @@ main () } EOF -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 # Apollos put the system type in the environment. diff --git a/config.h.in b/config.h.in index 6d5cbe1..6e90905 100644 --- a/config.h.in +++ b/config.h.in @@ -2,7 +2,7 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,9 @@ /* Define to 1 to enable internal debugger, requires libcurses */ #undef C_DEBUG +/* Define to 1 if you want serial passthrough support (Win32 only). */ +#undef C_DIRECTSERIAL + /* Define to 1 to use x86 dynamic cpu core */ #undef C_DYNAMIC_X86 @@ -41,12 +44,21 @@ /* The type of cpu this host has */ #undef C_HOSTCPU +/* Define to 1 to enable IPX over Internet networking, requires SDL_net */ +#undef C_IPX + /* Define to 1 to enable internal modem support, requires SDL_net */ #undef C_MODEM /* Define to 1 to use opengl display output support */ #undef C_OPENGL +/* Define to 1 to enable SDL_sound support */ +#undef C_SDL_SOUND + +/* Define to 1 if you have setpriority support */ +#undef C_SET_PRIORITY + /* Define to 1 to enable screenshots, requires libpng */ #undef C_SSHOT @@ -59,6 +71,9 @@ /* Define to 1 to use ALSA for MIDI */ #undef HAVE_ALSA +/* Define to 1 if you have the header file. */ +#undef HAVE_DDRAW_H + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H @@ -113,6 +128,24 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION +/* The size of a `int *', as computed by sizeof. */ +#undef SIZEOF_INT_P + +/* The size of a `unsigned char', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_CHAR + +/* The size of a `unsigned int', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_INT + +/* The size of a `unsigned long', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_LONG + +/* The size of a `unsigned long long', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_LONG_LONG + +/* The size of a `unsigned short', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_SHORT + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS @@ -145,3 +178,50 @@ #else #define GCC_ATTRIBUTE(x) /* attribute not supported */ #endif + + +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 + + diff --git a/config.sub b/config.sub index 463186d..ac6de98 100644 --- a/config.sub +++ b/config.sub @@ -1,9 +1,9 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. -timestamp='2004-01-05' +timestamp='2004-06-24' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -70,7 +70,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -145,7 +145,7 @@ case $os in -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) + -apple | -axis | -knuth | -cray) os= basic_machine=$1 ;; @@ -237,7 +237,7 @@ case $basic_machine in | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ - | m32r | m68000 | m68k | m88k | mcore \ + | m32r | m32rle | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -262,7 +262,7 @@ case $basic_machine in | pyramid \ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ - | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ @@ -300,7 +300,7 @@ case $basic_machine in | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | cydra-* \ + | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ @@ -308,7 +308,7 @@ case $basic_machine in | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ - | m32r-* \ + | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ @@ -326,8 +326,9 @@ case $basic_machine in | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ + | mmix-* \ | msp430-* \ - | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ @@ -336,7 +337,7 @@ case $basic_machine in | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ - | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ @@ -363,6 +364,9 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; + abacus) + basic_machine=abacus-unknown + ;; adobe68k) basic_machine=m68010-adobe os=-scout @@ -442,12 +446,24 @@ case $basic_machine in basic_machine=j90-cray os=-unicos ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; da30 | da30-*) basic_machine=m68k-da30 ;; @@ -648,10 +664,6 @@ case $basic_machine in 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 @@ -732,10 +744,6 @@ case $basic_machine in np1) basic_machine=np1-gould ;; - nv1) - basic_machine=nv1-cray - os=-unicosmp - ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -1048,6 +1056,9 @@ case $basic_machine in romp) basic_machine=romp-ibm ;; + mmix) + basic_machine=mmix-knuth + ;; rs6000) basic_machine=rs6000-ibm ;; @@ -1070,7 +1081,7 @@ case $basic_machine in sh64) basic_machine=sh64-unknown ;; - sparc | sparcv9 | sparcv9b) + sparc | sparcv8 | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) @@ -1143,8 +1154,9 @@ case $os in | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ @@ -1362,6 +1374,9 @@ case $basic_machine in *-ibm) os=-aix ;; + *-knuth) + os=-mmixware + ;; *-wec) os=-proelf ;; diff --git a/configure b/configure index ca16902..5cf8b19 100644 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.59 for dosbox 0.61. +# Generated by GNU Autoconf 2.59 for dosbox 0.62. # # Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation @@ -267,8 +267,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='dosbox' PACKAGE_TARNAME='dosbox' -PACKAGE_VERSION='0.61' -PACKAGE_STRING='dosbox 0.61' +PACKAGE_VERSION='0.62' +PACKAGE_STRING='dosbox 0.62' PACKAGE_BUGREPORT='' ac_unique_file="README" @@ -786,7 +786,7 @@ 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.61 to adapt to many kinds of systems. +\`configure' configures dosbox 0.62 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -853,7 +853,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of dosbox 0.61:";; + short | recursive ) echo "Configuration of dosbox 0.62:";; esac cat <<\_ACEOF @@ -987,7 +987,7 @@ fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF -dosbox configure 0.61 +dosbox configure 0.62 generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. @@ -1001,7 +1001,7 @@ 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.61, which was +It was created by dosbox $as_me 0.62, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ @@ -1698,7 +1698,7 @@ fi # Define the identity of the package. PACKAGE='dosbox' - VERSION='0.61' + VERSION='0.62' cat >>confdefs.h <<_ACEOF @@ -4083,7 +4083,7 @@ echo "$as_me: error: *** SDL version $SDL_VERSION not found!" >&2;} rm -f conf.sdltest LIBS="$LIBS $SDL_LIBS" -CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" +CPPFLAGS="$CPPFLAGS $SDL_CFLAGS" echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 @@ -4641,6 +4641,2441 @@ _ACEOF fi +echo "$as_me:$LINENO: checking for unsigned char" >&5 +echo $ECHO_N "checking for unsigned char... $ECHO_C" >&6 +if test "${ac_cv_type_unsigned_char+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((unsigned char *) 0) + return 0; +if (sizeof (unsigned char)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_unsigned_char=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_unsigned_char=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_char" >&5 +echo "${ECHO_T}$ac_cv_type_unsigned_char" >&6 + +echo "$as_me:$LINENO: checking size of unsigned char" >&5 +echo $ECHO_N "checking size of unsigned char... $ECHO_C" >&6 +if test "${ac_cv_sizeof_unsigned_char+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_unsigned_char" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned char))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned char))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned char))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned char))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned char))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_unsigned_char=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned char), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (unsigned char), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 +echo "$as_me: error: internal error: not reached in cross-compile" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (unsigned char)); } +unsigned long ulongval () { return (long) (sizeof (unsigned char)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (unsigned char))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (unsigned char)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (unsigned char)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_unsigned_char=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned char), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (unsigned char), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_unsigned_char=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_unsigned_char" >&5 +echo "${ECHO_T}$ac_cv_sizeof_unsigned_char" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_CHAR $ac_cv_sizeof_unsigned_char +_ACEOF + + +echo "$as_me:$LINENO: checking for unsigned short" >&5 +echo $ECHO_N "checking for unsigned short... $ECHO_C" >&6 +if test "${ac_cv_type_unsigned_short+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((unsigned short *) 0) + return 0; +if (sizeof (unsigned short)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_unsigned_short=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_unsigned_short=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_short" >&5 +echo "${ECHO_T}$ac_cv_type_unsigned_short" >&6 + +echo "$as_me:$LINENO: checking size of unsigned short" >&5 +echo $ECHO_N "checking size of unsigned short... $ECHO_C" >&6 +if test "${ac_cv_sizeof_unsigned_short+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_unsigned_short" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned short))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned short))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned short))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned short))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned short))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_unsigned_short=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned short), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (unsigned short), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 +echo "$as_me: error: internal error: not reached in cross-compile" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (unsigned short)); } +unsigned long ulongval () { return (long) (sizeof (unsigned short)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (unsigned short))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (unsigned short)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (unsigned short)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_unsigned_short=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned short), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (unsigned short), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_unsigned_short=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_unsigned_short" >&5 +echo "${ECHO_T}$ac_cv_sizeof_unsigned_short" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_SHORT $ac_cv_sizeof_unsigned_short +_ACEOF + + +echo "$as_me:$LINENO: checking for unsigned int" >&5 +echo $ECHO_N "checking for unsigned int... $ECHO_C" >&6 +if test "${ac_cv_type_unsigned_int+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((unsigned int *) 0) + return 0; +if (sizeof (unsigned int)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_unsigned_int=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_unsigned_int=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_int" >&5 +echo "${ECHO_T}$ac_cv_type_unsigned_int" >&6 + +echo "$as_me:$LINENO: checking size of unsigned int" >&5 +echo $ECHO_N "checking size of unsigned int... $ECHO_C" >&6 +if test "${ac_cv_sizeof_unsigned_int+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_unsigned_int" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned int))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned int))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned int))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned int))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned int))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_unsigned_int=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned int), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (unsigned int), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 +echo "$as_me: error: internal error: not reached in cross-compile" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (unsigned int)); } +unsigned long ulongval () { return (long) (sizeof (unsigned int)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (unsigned int))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (unsigned int)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (unsigned int)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_unsigned_int=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned int), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (unsigned int), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_unsigned_int=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_unsigned_int" >&5 +echo "${ECHO_T}$ac_cv_sizeof_unsigned_int" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_INT $ac_cv_sizeof_unsigned_int +_ACEOF + + +echo "$as_me:$LINENO: checking for unsigned long" >&5 +echo $ECHO_N "checking for unsigned long... $ECHO_C" >&6 +if test "${ac_cv_type_unsigned_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((unsigned long *) 0) + return 0; +if (sizeof (unsigned long)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_unsigned_long=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_unsigned_long=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_long" >&5 +echo "${ECHO_T}$ac_cv_type_unsigned_long" >&6 + +echo "$as_me:$LINENO: checking size of unsigned long" >&5 +echo $ECHO_N "checking size of unsigned long... $ECHO_C" >&6 +if test "${ac_cv_sizeof_unsigned_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_unsigned_long" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned long))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned long))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned long))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned long))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned long))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_unsigned_long=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned long), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (unsigned long), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 +echo "$as_me: error: internal error: not reached in cross-compile" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (unsigned long)); } +unsigned long ulongval () { return (long) (sizeof (unsigned long)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (unsigned long))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (unsigned long)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (unsigned long)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_unsigned_long=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned long), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (unsigned long), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_unsigned_long=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_unsigned_long" >&5 +echo "${ECHO_T}$ac_cv_sizeof_unsigned_long" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long +_ACEOF + + +echo "$as_me:$LINENO: checking for unsigned long long" >&5 +echo $ECHO_N "checking for unsigned long long... $ECHO_C" >&6 +if test "${ac_cv_type_unsigned_long_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((unsigned long long *) 0) + return 0; +if (sizeof (unsigned long long)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_unsigned_long_long=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_unsigned_long_long=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_long_long" >&5 +echo "${ECHO_T}$ac_cv_type_unsigned_long_long" >&6 + +echo "$as_me:$LINENO: checking size of unsigned long long" >&5 +echo $ECHO_N "checking size of unsigned long long... $ECHO_C" >&6 +if test "${ac_cv_sizeof_unsigned_long_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_unsigned_long_long" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned long long))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned long long))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned long long))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned long long))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (unsigned long long))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_unsigned_long_long=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned long long), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (unsigned long long), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 +echo "$as_me: error: internal error: not reached in cross-compile" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (unsigned long long)); } +unsigned long ulongval () { return (long) (sizeof (unsigned long long)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (unsigned long long))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (unsigned long long)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (unsigned long long)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_unsigned_long_long=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (unsigned long long), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (unsigned long long), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_unsigned_long_long=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_unsigned_long_long" >&5 +echo "${ECHO_T}$ac_cv_sizeof_unsigned_long_long" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_LONG_LONG $ac_cv_sizeof_unsigned_long_long +_ACEOF + + +echo "$as_me:$LINENO: checking for int *" >&5 +echo $ECHO_N "checking for int *... $ECHO_C" >&6 +if test "${ac_cv_type_int_p+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((int * *) 0) + return 0; +if (sizeof (int *)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_int_p=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_int_p=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_int_p" >&5 +echo "${ECHO_T}$ac_cv_type_int_p" >&6 + +echo "$as_me:$LINENO: checking size of int *" >&5 +echo $ECHO_N "checking size of int *... $ECHO_C" >&6 +if test "${ac_cv_sizeof_int_p+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$ac_cv_type_int_p" = yes; then + # The cast to unsigned long works around a bug in the HP C Compiler + # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects + # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. + # This bug is HP SR number 8606223364. + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (int *))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (int *))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (int *))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (int *))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !(((long) (sizeof (int *))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_int_p=$ac_lo;; +'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int *), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (int *), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5 +echo "$as_me: error: internal error: not reached in cross-compile" >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +long longval () { return (long) (sizeof (int *)); } +unsigned long ulongval () { return (long) (sizeof (int *)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if (((long) (sizeof (int *))) < 0) + { + long i = longval (); + if (i != ((long) (sizeof (int *)))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != ((long) (sizeof (int *)))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sizeof_int_p=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: cannot compute sizeof (int *), 77 +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute sizeof (int *), 77 +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val +else + ac_cv_sizeof_int_p=0 +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sizeof_int_p" >&5 +echo "${ECHO_T}$ac_cv_sizeof_int_p" >&6 +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT_P $ac_cv_sizeof_int_p +_ACEOF + echo "$as_me:$LINENO: checking if environ can be included" >&5 @@ -5935,18 +8370,20 @@ fi -if test "${ac_cv_header_SDL_SDL_net_h+set}" = set; then - echo "$as_me:$LINENO: checking for SDL/SDL_net.h" >&5 -echo $ECHO_N "checking for SDL/SDL_net.h... $ECHO_C" >&6 -if test "${ac_cv_header_SDL_SDL_net_h+set}" = set; then + + +if test "${ac_cv_header_SDL_net_h+set}" = set; then + echo "$as_me:$LINENO: checking for SDL_net.h" >&5 +echo $ECHO_N "checking for SDL_net.h... $ECHO_C" >&6 +if test "${ac_cv_header_SDL_net_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi -echo "$as_me:$LINENO: result: $ac_cv_header_SDL_SDL_net_h" >&5 -echo "${ECHO_T}$ac_cv_header_SDL_SDL_net_h" >&6 +echo "$as_me:$LINENO: result: $ac_cv_header_SDL_net_h" >&5 +echo "${ECHO_T}$ac_cv_header_SDL_net_h" >&6 else # Is the header compilable? -echo "$as_me:$LINENO: checking SDL/SDL_net.h usability" >&5 -echo $ECHO_N "checking SDL/SDL_net.h usability... $ECHO_C" >&6 +echo "$as_me:$LINENO: checking SDL_net.h usability" >&5 +echo $ECHO_N "checking SDL_net.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF @@ -5954,7 +8391,7 @@ cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default -#include +#include _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 @@ -5989,15 +8426,15 @@ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 # Is the header present? -echo "$as_me:$LINENO: checking SDL/SDL_net.h presence" >&5 -echo $ECHO_N "checking SDL/SDL_net.h presence... $ECHO_C" >&6 +echo "$as_me:$LINENO: checking SDL_net.h presence" >&5 +echo $ECHO_N "checking SDL_net.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include +#include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 @@ -6031,25 +8468,25 @@ echo "${ECHO_T}$ac_header_preproc" >&6 # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) - { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: SDL/SDL_net.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: SDL/SDL_net.h: proceeding with the compiler's result" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL_net.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: SDL_net.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL_net.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: SDL_net.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) - { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: SDL/SDL_net.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: SDL/SDL_net.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: SDL/SDL_net.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: SDL/SDL_net.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: SDL/SDL_net.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: SDL/SDL_net.h: in the future, the compiler will take precedence" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL_net.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: SDL_net.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL_net.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: SDL_net.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL_net.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: SDL_net.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL_net.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: SDL_net.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL_net.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: SDL_net.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL_net.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: SDL_net.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## --------------------------------- ## @@ -6060,18 +8497,18 @@ _ASBOX sed "s/^/$as_me: WARNING: /" >&2 ;; esac -echo "$as_me:$LINENO: checking for SDL/SDL_net.h" >&5 -echo $ECHO_N "checking for SDL/SDL_net.h... $ECHO_C" >&6 -if test "${ac_cv_header_SDL_SDL_net_h+set}" = set; then +echo "$as_me:$LINENO: checking for SDL_net.h" >&5 +echo $ECHO_N "checking for SDL_net.h... $ECHO_C" >&6 +if test "${ac_cv_header_SDL_net_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - ac_cv_header_SDL_SDL_net_h=$ac_header_preproc + ac_cv_header_SDL_net_h=$ac_header_preproc fi -echo "$as_me:$LINENO: result: $ac_cv_header_SDL_SDL_net_h" >&5 -echo "${ECHO_T}$ac_cv_header_SDL_SDL_net_h" >&6 +echo "$as_me:$LINENO: result: $ac_cv_header_SDL_net_h" >&5 +echo "${ECHO_T}$ac_cv_header_SDL_net_h" >&6 fi -if test $ac_cv_header_SDL_SDL_net_h = yes; then +if test $ac_cv_header_SDL_net_h = yes; then have_sdl_net_h=yes fi @@ -6147,11 +8584,15 @@ if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then LIBS="$LIBS -lSDL_net" cat >>confdefs.h <<\_ACEOF #define C_MODEM 1 +_ACEOF + + cat >>confdefs.h <<\_ACEOF +#define C_IPX 1 _ACEOF else - { echo "$as_me:$LINENO: WARNING: Can't find SDL_net, internal modem disabled" >&5 -echo "$as_me: WARNING: Can't find SDL_net, internal modem disabled" >&2;} + { echo "$as_me:$LINENO: WARNING: Can't find SDL_net, internal modem and ipx disabled" >&5 +echo "$as_me: WARNING: Can't find SDL_net, internal modem and ipx disabled" >&2;} fi @@ -6455,9 +8896,433 @@ else echo "${ECHO_T}no" >&6 fi + + +if test "${ac_cv_header_SDL_SDL_sound_h+set}" = set; then + echo "$as_me:$LINENO: checking for SDL/SDL_sound.h" >&5 +echo $ECHO_N "checking for SDL/SDL_sound.h... $ECHO_C" >&6 +if test "${ac_cv_header_SDL_SDL_sound_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_SDL_SDL_sound_h" >&5 +echo "${ECHO_T}$ac_cv_header_SDL_SDL_sound_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking SDL/SDL_sound.h usability" >&5 +echo $ECHO_N "checking SDL/SDL_sound.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking SDL/SDL_sound.h presence" >&5 +echo $ECHO_N "checking SDL/SDL_sound.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: SDL/SDL_sound.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: SDL/SDL_sound.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL/SDL_sound.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: SDL/SDL_sound.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: SDL/SDL_sound.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: SDL/SDL_sound.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL/SDL_sound.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: SDL/SDL_sound.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL/SDL_sound.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: SDL/SDL_sound.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL/SDL_sound.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: SDL/SDL_sound.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL/SDL_sound.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: SDL/SDL_sound.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL/SDL_sound.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: SDL/SDL_sound.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the dosbox lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for SDL/SDL_sound.h" >&5 +echo $ECHO_N "checking for SDL/SDL_sound.h... $ECHO_C" >&6 +if test "${ac_cv_header_SDL_SDL_sound_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_SDL_SDL_sound_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_SDL_SDL_sound_h" >&5 +echo "${ECHO_T}$ac_cv_header_SDL_SDL_sound_h" >&6 + +fi +if test $ac_cv_header_SDL_SDL_sound_h = yes; then + have_SDL_sound_h=yes +fi + + +echo "$as_me:$LINENO: checking for Sound_Init in -lSDL_sound" >&5 +echo $ECHO_N "checking for Sound_Init in -lSDL_sound... $ECHO_C" >&6 +if test "${ac_cv_lib_SDL_sound_Sound_Init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lSDL_sound $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char Sound_Init (); +int +main () +{ +Sound_Init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_SDL_sound_Sound_Init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_SDL_sound_Sound_Init=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_SDL_sound_Sound_Init" >&5 +echo "${ECHO_T}$ac_cv_lib_SDL_sound_Sound_Init" >&6 +if test $ac_cv_lib_SDL_sound_Sound_Init = yes; then + have_SDL_sound_lib=yes +fi + +if test x$have_SDL_sound_h = xyes -a x$have_SDL_sound_lib = xyes ; then + LIBS="$LIBS -lSDL_sound" + cat >>confdefs.h <<\_ACEOF +#define C_SDL_SOUND 1 +_ACEOF + +else + { echo "$as_me:$LINENO: WARNING: Can't find libSDL_sound, libSDL_sound support disabled" >&5 +echo "$as_me: WARNING: Can't find libSDL_sound, libSDL_sound support disabled" >&2;} +fi + + + +echo "$as_me:$LINENO: checking for setpriority support" >&5 +echo $ECHO_N "checking for setpriority support... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF + +#include +int main(int argc,char * argv) { + return setpriority (PRIO_PROCESS, 0,PRIO_MIN+PRIO_MAX); +}; + +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6;cat >>confdefs.h <<\_ACEOF +#define C_SET_PRIORITY 1 +_ACEOF + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + case "$target" in *-*-cygwin* | *-*-mingw32*) LIBS="$LIBS -lwinmm" + +for ac_header in ddraw.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + 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 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end 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>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the dosbox lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +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 + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +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 + + +cat >>confdefs.h <<\_ACEOF +#define C_DIRECTSERIAL 1 +_ACEOF + ;; *-*-darwin*) @@ -6861,7 +9726,7 @@ _ASBOX } >&5 cat >&5 <<_CSEOF -This file was extended by dosbox $as_me 0.61, which was +This file was extended by dosbox $as_me 0.62, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -6924,7 +9789,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -dosbox config.status 0.61 +dosbox config.status 0.62 configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.in b/configure.in index ad483f7..a749e10 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Init. -AC_INIT(dosbox,0.61) +AC_INIT(dosbox,0.62) AC_PREREQ(2.50) AC_CONFIG_SRCDIR(README) @@ -26,7 +26,7 @@ AM_PATH_SDL($SDL_VERSION, AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]) ) LIBS="$LIBS $SDL_LIBS" -CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" +CPPFLAGS="$CPPFLAGS $SDL_CFLAGS" dnl Checks for header files. @@ -35,7 +35,12 @@ 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 *) AC_MSG_CHECKING(if environ can be included) AC_TRY_LINK([#include @@ -143,13 +148,15 @@ else fi AH_TEMPLATE(C_MODEM,[Define to 1 to enable internal modem support, requires SDL_net]) -AC_CHECK_HEADER(SDL/SDL_net.h,have_sdl_net_h=yes,) +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,) AC_CHECK_LIB(SDL_net, SDLNet_Init, have_sdl_net_lib=yes, , ) 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 disabled]) + 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]) @@ -170,10 +177,32 @@ else AC_MSG_RESULT(no) fi +AH_TEMPLATE(C_SDL_SOUND,[Define to 1 to enable SDL_sound support]) +AC_CHECK_HEADER(SDL/SDL_sound.h,have_SDL_sound_h=yes,) +AC_CHECK_LIB(SDL_sound, Sound_Init, have_SDL_sound_lib=yes,,) +if test x$have_SDL_sound_h = xyes -a x$have_SDL_sound_lib = xyes ; then + LIBS="$LIBS -lSDL_sound" + AC_DEFINE(C_SDL_SOUND,1) +else + AC_MSG_WARN([Can't find libSDL_sound, libSDL_sound support disabled]) +fi + +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 host 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 only).]) ;; *-*-darwin*) dnl We have a problem here: both MacOS X and Darwin report diff --git a/docs/dosbox.1 b/docs/dosbox.1 index a140290..9a885c1 100644 --- a/docs/dosbox.1 +++ b/docs/dosbox.1 @@ -1,16 +1,20 @@ .\" Hey, EMACS: -*- nroff -*- -.TH DOSBOX 1 "October 5, 2003" +.TH DOSBOX 1 "Sept 23, 2004" .\" 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] .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." @@ -22,6 +26,9 @@ A summary of options is included below. .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 .BI \-c " command" .RI "Runs the specified " command " before running " .BR file . @@ -38,6 +45,13 @@ A summary of options is included below. .TP .B \-exit .BR dosbox " will exit after running the program specified by " file . +.TP +.BI \-machine " machinetype +.RB "Setup " dosbox " to emulate a specific type of machine." +.RI "Valid choices are: " "hercules, cga, tandy, vga(default)". +.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 @@ -46,7 +60,7 @@ following extra commands are available: .BI "MOUNT [\-t " type "] [\-size " size ] .I driveletter sourcedirectory .B [\-aspi] [\-ioctl] -.BI "[\-usecd " number "] [\-label " drivelabel ] +.BI "[\-usecd " number "] [\-label " drivelabel "] [\-freesize " freesize ] .LP .B MOUNT \-cd .LP @@ -63,7 +77,11 @@ The local directory you want to have inside dosbox. Type of the mounted directory. Supported are: dir (standard), floppy, cdrom. .TP .BI \-size " drivesize" -Sets the size of the drive. +Sets the size of the drive. See the examples in the README for details. +.TP +.BI \-freesize " freesize" +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" @@ -123,6 +141,30 @@ The amount of memory to eat up (in kb). Example -32, -64 or -128 .B \-f Frees all memory eaten up by loadfix. .RE +.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 +.RB "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 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 .SH FILES Configuration and language files use a format similar to Windows .ini files. If a file named .BR dosbox.conf " is found in the current directory, it will be automatically loaded." @@ -130,10 +172,18 @@ Configuration and language files use a format similar to Windows .ini files. If .TP 12m .IP ALT\-ENTER Go full screen and back. +.IP CTRL\-F1 +Start the keymapper. +.IP CTRL\-F4 +Swap mounted disk-image (Only used with imgmount). .IP CTRL\-F5 Save a screenshot. .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 @@ -147,8 +197,9 @@ Slow down emulation (Increase DOSBox Cycles). .IP CTRL\-F12 Speed up emulation (Decrease DOSBox Cycles). .PP -.B "Note: " -Once you increase your DOSBox cycles beyond your computer's maximum +These are the default keybindings. They can be changed in the keymapper. +.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" diff --git a/include/Makefile.am b/include/Makefile.am index d0ec949..ce2c03c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -12,8 +12,11 @@ fpu.h \ hardware.h \ inout.h \ joystick.h \ +ipx.h \ +ipxserver.h \ keyboard.h \ logging.h \ +mapper.h \ mem.h \ mixer.h \ modules.h \ diff --git a/include/Makefile.in b/include/Makefile.in index 87fe5a3..d1175a6 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -143,8 +143,11 @@ fpu.h \ hardware.h \ inout.h \ joystick.h \ +ipx.h \ +ipxserver.h \ keyboard.h \ logging.h \ +mapper.h \ mem.h \ mixer.h \ modules.h \ diff --git a/include/bios.h b/include/bios.h index 18e2fb1..e80bc06 100644 --- a/include/bios.h +++ b/include/bios.h @@ -9,13 +9,16 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef _BIOS_H_ +#define _BIOS_H_ + #define BIOS_BASE_ADDRESS_COM1 0x400 #define BIOS_BASE_ADDRESS_COM2 0x402 #define BIOS_BASE_ADDRESS_COM3 0x404 @@ -88,6 +91,8 @@ #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 @@ -96,23 +101,57 @@ /* 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; +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 */ }; -class imageDisk : public BIOS_Disk { +extern diskGeo DiskGeometryList[]; + +#include +#include "mem.h" +#include "dos_inc.h" + +class imageDisk { 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; + 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); void BIOS_ZeroExtendedSize(void); void char_out(Bit8u chr,Bit32u att,Bit8u page); @@ -123,4 +162,4 @@ void INT2F_StartUp(void); void INT33_StartUp(void); void INT13_StartUp(void); - +#endif diff --git a/include/callback.h b/include/callback.h index eb299fc..ca919ab 100644 --- a/include/callback.h +++ b/include/callback.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/include/cpu.h b/include/cpu.h index f741895..9fd9bfe 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -35,6 +35,7 @@ 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); @@ -52,7 +53,6 @@ void CPU_SLDT(Bitu & selector); void CPU_SIDT(Bitu & limit,Bitu & base); void CPU_SGDT(Bitu & limit,Bitu & base); - void CPU_ARPL(Bitu & dest_sel,Bitu src_sel); void CPU_LAR(Bitu selector,Bitu & ar); void CPU_LSL(Bitu selector,Bitu & limit); @@ -61,35 +61,44 @@ bool CPU_SET_CRX(Bitu cr,Bitu value); Bitu CPU_GET_CRX(Bitu cr); void CPU_SMSW(Bitu & word); -bool CPU_LMSW(Bitu word); +Bitu CPU_LMSW(Bitu word); void CPU_VERR(Bitu selector); void CPU_VERW(Bitu selector); -void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen=0); -void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen=0); -void CPU_RET(bool use32,Bitu bytes,Bitu opLen=0); +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 - -void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen=0); +void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip); INLINE void CPU_HW_Interrupt(Bitu num) { - CPU_Interrupt(num,0); + CPU_Interrupt(num,0,reg_eip); } -INLINE void CPU_SW_Interrupt(Bitu num,Bitu OpLen) { - CPU_Interrupt(num,CPU_INT_SOFTWARE,OpLen); +INLINE void CPU_SW_Interrupt(Bitu num,Bitu oldeip) { + CPU_Interrupt(num,CPU_INT_SOFTWARE,oldeip); } +bool CPU_PrepareException(Bitu which,Bitu error); void CPU_Exception(Bitu which,Bitu error=0); -void CPU_StartException(void); -void CPU_SetupException(Bitu which,Bitu error=0); -void CPU_IRET(bool use32); bool CPU_SetSegGeneral(SegNames seg,Bitu value); -void CPU_HLT(Bitu opLen); +bool CPU_PopSeg(SegNames seg,bool use32); void CPU_CPUID(void); Bitu CPU_Pop16(void); @@ -407,5 +416,6 @@ INLINE void CPU_SetFlagsw(Bitu word) { CPU_SetFlags(word,mask); }; + #endif diff --git a/include/cross.h b/include/cross.h index 7dd7882..5ad0102 100644 --- a/include/cross.h +++ b/include/cross.h @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.7 2004/02/02 19:22:23 qbix79 Exp $ */ +/* $Id: cross.h,v 1.11 2004/09/16 21:46:03 qbix79 Exp $ */ #ifndef _CROSS_H #define _CROSS_H @@ -29,6 +29,8 @@ #include #include #define LONGTYPE(a) a##i64 +#define snprintf _snprintf +#define vsnprintf _vsnprintf #else /* LINUX / GCC */ #include #include @@ -39,7 +41,7 @@ #if defined (WIN32) /* Win 32 */ -#define CROSS_FILENAME(blah) {if(blah && *blah && (blah[strlen(blah)-1] == '\\')) strcat(blah,".");} +#define CROSS_FILENAME(blah) #define CROSS_FILESPLIT '\\' #define F_OK 0 #else diff --git a/include/debug.h b/include/debug.h index bb44a99..337e849 100644 --- a/include/debug.h +++ b/include/debug.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/include/dma.h b/include/dma.h index 4c2c955..9e8f36c 100644 --- a/include/dma.h +++ b/include/dma.h @@ -9,187 +9,85 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.9 2004/01/10 14:03:33 qbix79 Exp $ */ +/* $Id: dma.h,v 1.12 2004/08/04 09:12:50 qbix79 Exp $ */ #ifndef __DMA_H #define __DMA_H -#include "mem.h" +enum DMAEvent { + DMA_REACHED_TC, + DMA_MASKED, + DMA_UNMASKED, + DMA_TRANSFEREND +}; -#define DMA_MODE_DEMAND 0 -#define DMA_MODE_SINGLE 1 -#define DMA_MODE_BLOCK 2 -#define DMA_MODE_CASCADE 3 - -#define DMA_BASEADDR 0 -#define DMA_TRANSCOUNT 1 -#define DMA_PAGEREG 2 - -#define DMA_CMDREG 0 -#define DMA_MODEREG 1 -#define DMA_CLEARREG 2 -#define DMA_DMACREG 3 -#define DMA_CLRMASKREG 4 -#define DMA_SINGLEREG 5 -#define DMA_WRITEALLREG 6 - -static Bit8u ChannelPorts [3][8] = { 0x00, 0x02, 0x04, 0x06, 0xff, 0xc4, 0xc8, 0xcc, - 0x01, 0x03, 0x05, 0x07, 0xff, 0xc6, 0xca, 0xce, - 0x87, 0x83, 0x81, 0x82, 0xff, 0x8b, 0x89, 0x8a }; - -static Bit8u ControllerPorts [2][7] = { 0x08, 0x0b, 0x0c, 0x0d, 0x0e, 0x0a, 0xf, - 0xd0, 0xd6, 0xd8, 0xda, 0xdc, 0xd4, 0xde }; - - -typedef void (* DMA_EnableCallBack)(bool enable); - -typedef void (* DMA_NewCallBack)(void *useChannel, bool tc); - -void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback); - -void DMA_CheckEnabled(void * usechan); - -Bitu DMA_8_Read(Bitu channel,Bit8u * buffer,Bitu count); -Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count); - -Bitu DMA_16_Read(Bitu channel,Bit8u * buffer,Bitu count); -Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count); - -extern Bit8u read_dmaB(Bit32u port); -extern Bit16u read_dmaW(Bit32u port); - -extern void write_dmaB(Bit32u port,Bit8u val); -extern void write_dmaW(Bit32u port,Bit16u val); +class DmaChannel; +typedef void (* DMA_CallBack)(DmaChannel * chan,DMAEvent event); class DmaController { public: bool flipflop; Bit8u ctrlnum; + Bit8u chanbase; public: - DmaController(Bit8u num) { - int i; - for(i=0;i<7;i++) { - IO_RegisterReadBHandler(ControllerPorts[num][i],read_dmaB); - IO_RegisterReadWHandler(ControllerPorts[num][i],read_dmaW); - - IO_RegisterWriteBHandler(ControllerPorts[num][i],write_dmaB); - IO_RegisterWriteWHandler(ControllerPorts[num][i],write_dmaW); - } - flipflop = true; + flipflop = false; ctrlnum = num; + chanbase = num * 4; } - - Bit16u portRead(Bit32u port, bool eightbit); - void portWrite(Bit32u port, Bit16u val, bool eightbit); - }; - - class DmaChannel { public: - - Bit8u channum; + Bit32u pagebase; Bit16u baseaddr; - Bit16u current_addr; - Bit16u pageaddr; - PhysPt physaddr; - PhysPt curraddr; - Bit32s transcnt; - Bit32s currcnt; - DmaController *myController; - bool DMA16; - bool addr_changed; -public: - Bit8u dmamode; - bool dir; + Bit16u curraddr; + Bit16u basecnt; + Bit16u currcnt; + Bit8u channum; + Bit8u pagenum; + Bit8u DMA16; + bool increment; bool autoinit; Bit8u trantype; bool masked; - bool enabled; - DMA_EnableCallBack enable_callback; - DMA_NewCallBack newcallback; + bool tcount; + DMA_CallBack callback; - DmaChannel(Bit8u num, DmaController *useController, bool sb) { - int i; - masked = true; - enabled = false; - enable_callback = NULL; - newcallback = NULL; - if(num == 4) return; - addr_changed=false; - - for(i=0;i<3;i++) { - IO_RegisterReadBHandler(ChannelPorts[i][num],read_dmaB); - IO_RegisterReadWHandler(ChannelPorts[i][num],read_dmaW); - - IO_RegisterWriteBHandler(ChannelPorts[i][num],write_dmaB); - IO_RegisterWriteWHandler(ChannelPorts[i][num],write_dmaW); - } - myController = useController; - channum = num; - DMA16 = sb; - baseaddr = 0; - pageaddr = 0; - physaddr = 0; - curraddr = 0; - transcnt = 0; - currcnt = 0; - dir = false; - autoinit = false; + DmaChannel(Bit8u num, bool dma16); + void DoCallBack(DMAEvent event) { + if (callback) (*callback)(this,event); } - - void RegisterCallback(DMA_NewCallBack useCallBack) { newcallback = useCallBack; } - - void reset(void) { - addr_changed=false; - curraddr = physaddr; - currcnt = transcnt+1; - current_addr = baseaddr; - //LOG(LOG_DMA,LOG_NORMAL)("Setup at address %X:%X count %X",pageaddr,baseaddr,currcnt); + void SetMask(bool _mask) { + masked=_mask; + DoCallBack(masked ? DMA_MASKED : DMA_UNMASKED); } - - void MakeCallback(bool tc) { - if (newcallback != NULL) { - if(tc) { - (*newcallback)(this, true); - } else { - if ((enabled) && (!masked) && (transcnt!=0)) { - (*newcallback)(this, false); - } - } - - } + void Register_Callback(DMA_CallBack _cb) { + callback = _cb; + SetMask(masked); } - - Bit32u Read(Bit32s requestsize, Bit8u * buffer); - - Bit32u Write(Bit32s requestsize, Bit8u * buffer); - - void calcPhys(void); - - Bit16u portRead(Bit32u port, bool eightbit); - - void portWrite(Bit32u port, Bit16u val, bool eightbit); - - // Notify channel when mask changes - void Notify(void); - + void ReachedTC(void) { + tcount=true; + DoCallBack(DMA_REACHED_TC); + } + void SetPage(Bit8u val) { + pagenum=val; + pagebase=(pagenum >> DMA16) << (16+DMA16); + } + Bitu Read(Bitu size, Bit8u * buffer); + Bitu Write(Bitu size, Bit8u * buffer); }; - extern DmaChannel *DmaChannels[8]; extern DmaController *DmaControllers[2]; - - #endif + diff --git a/include/dos_inc.h b/include/dos_inc.h index 0100c2c..d3339c2 100644 --- a/include/dos_inc.h +++ b/include/dos_inc.h @@ -9,13 +9,15 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.48 2004/08/04 09:12:50 qbix79 Exp $ */ + #ifndef DOS_H_ #define DOS_H_ @@ -43,27 +45,25 @@ 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; - - Bit8u current_drive; - bool verify; - bool breakcheck; - bool echo; // if set to true dev_con::read will echo input - struct { - RealPt indosflag; - RealPt mediaid; - RealPt tempdta; - } tables; -}; + +#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}; @@ -72,7 +72,7 @@ enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3}; #define DOS_DRIVES 26 /* internal Dos Tables */ -extern DOS_Block dos; + extern DOS_File * Files[DOS_FILES]; extern DOS_Drive * Drives[DOS_DRIVES]; extern Bit8u dos_copybuf[0x10000]; @@ -100,7 +100,7 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry); bool DOS_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status); bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry); bool DOS_UnlinkFile(char * name); -bool DOS_FindFirst(char *search,Bit16u attr); +bool DOS_FindFirst(char *search,Bit16u attr,bool fcb_findfirst=false); bool DOS_FindNext(void); bool DOS_Canonicalize(char * name,char * big); bool DOS_CreateTempFile(char * name,Bit16u * entry); @@ -208,30 +208,26 @@ INLINE Bit16u DOS_PackDate(Bit16u year,Bit16u mon,Bit16u day) { /* Remains some classes used to access certain things */ - -#define sGet(s,m) GetIt(((s *)0)->m,(PhysPt)&(((s *)0)->m)) -#define sSave(s,m,val) SaveIt(((s *)0)->m,(PhysPt)&(((s *)0)->m),val) - +#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: - INLINE Bit8u GetIt(Bit8u&,PhysPt addr) { - return mem_readb(pt+addr); + INLINE 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; } - INLINE Bit16u GetIt(Bit16u&,PhysPt addr) { - return mem_readw(pt+addr); - } - INLINE Bit32u GetIt(Bit32u&,PhysPt addr) { - return mem_readd(pt+addr); - } - INLINE void SaveIt(Bit8u&,PhysPt addr,Bit8u val) { - mem_writeb(pt+addr,val); - } - INLINE void SaveIt(Bit16u&,PhysPt addr,Bit16u val) { - mem_writew(pt+addr,val); - } - INLINE void SaveIt(Bit32u&,PhysPt addr,Bit32u val) { - mem_writed(pt+addr,val); + INLINE void SaveIt(Bitu size,PhysPt addr,Bitu val) { + switch (size) { + case 1:mem_writeb(pt+addr,val);break; + case 2:mem_writew(pt+addr,val);break; + case 4:mem_writed(pt+addr,val);break; + } } INLINE void SetPt(Bit16u seg) { pt=PhysMake(seg,0);} INLINE void SetPt(Bit16u seg,Bit16u off) { pt=PhysMake(seg,off);} @@ -252,8 +248,6 @@ public: void RestoreVectors (void); void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); }; Bit16u GetSize (void) { return sGet(sPSP,next_seg); }; - void SetDTA (RealPt ptdta) { sSave(sPSP,dta,ptdta); }; - RealPt GetDTA (void) { return sGet(sPSP,dta); }; void SetEnvironment (Bit16u envseg) { sSave(sPSP,environment,envseg); }; Bit16u GetEnvironment (void) { return sGet(sPSP,environment); }; Bit16u GetSegment (void) { return seg; }; @@ -291,8 +285,11 @@ private: 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 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 */ @@ -343,25 +340,50 @@ public: void SetFirstMCB(Bit16u _first_mcb); void SetfirstFileTable(RealPt _first_table); void SetBuffers(Bit16u x,Bit16u y); + void SetCurDirStruct(Bit32u _curdirstruct); + void SetFCBTable(Bit32u _fcbtable); + void SetDeviceChainStart(Bit32u _devchain); + void SetDiskInfoBuffer(Bit32u _dinfobuf); RealPt GetPointer (void); #ifdef _MSC_VER #pragma pack(1) #endif struct sDIB { - Bit8u stuff1[22]; // -0x18 some stuff, hopefully never used.... - Bit16u firstMCB; // -0x2 first memory control block - RealPt firstDPB; // 0x00 first drive parameter block + 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 + RealPt activeCon; // 0x0c active console device header Bit16u maxSectorLength; // 0x10 maximum bytes per sector of any block device; - RealPt discInfoBuffer; // 0x12 pointer to disc info buffer + 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 - Bit8u stuff2[0x21]; // 0x1e more stuff - Bit16u buffers_x; // x in BUFFERS x,y - Bit16u buffers_y; // y in BUFFERS x,y + 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 // some more stuff, hopefully never used. } GCC_ATTRIBUTE(packed); #ifdef _MSC_VER @@ -389,9 +411,9 @@ private: #endif struct sDTA { Bit8u sdrive; /* The Drive the search is taking place */ - Bit8u sattr; /* The Attributes that need to be found */ 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 */ Bit8u fill[6]; Bit8u attr; @@ -422,6 +444,8 @@ public: void SetRandom(Bit32u _random); Bit8u GetDrive(void); bool Extended(void); + void GetAttr(Bit8u & attr); + void SetAttr(Bit8u attr); private: bool extended; PhysPt real_pt; @@ -438,8 +462,11 @@ private: Bit16u date; Bit16u time; /* Reserved Block should be 8 bytes */ + Bit8u sft_entries; + Bit8u share_attributes; + Bit8u extra_info; Bit8u file_handle; - Bit8u reserved[7]; + Bit8u reserved[4]; /* end */ Bit8u cur_rec; /* Current record in current block */ Bit32u rndm; /* Current relative record number */ @@ -476,10 +503,78 @@ private: #endif }; -extern DOS_InfoBlock dos_infoblock;; +extern Bit16u sdaseg; +#define DOS_SDA_SEG sdaseg +#define DOS_SDA_OFS 0 + + +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 sGet(sSDA,current_drive); } + Bit16u GetPSP(void) { return sGet(sSDA,current_psp); } + Bit32u GetDTA(void) { return 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 dcbs; + } tables; +}; + +extern DOS_Block dos; INLINE Bit8u RealHandle(Bit16u handle) { - DOS_PSP psp(dos.psp); + DOS_PSP psp(dos.psp()); return psp.GetFileHandle(handle); } diff --git a/include/dos_system.h b/include/dos_system.h index bd5bfd3..78a64f4 100644 --- a/include/dos_system.h +++ b/include/dos_system.h @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.20 2004/01/12 20:25:57 finsterr Exp $ */ +/* $Id: dos_system.h,v 1.24 2004/08/04 09:12:50 qbix79 Exp $ */ #ifndef DOSSYSTEM_H_ #define DOSSYSTEM_H_ @@ -54,7 +54,7 @@ class DOS_DTA; class DOS_File { public: DOS_File():flags(0) { name=0; refCtr = 0; }; - virtual ~DOS_File(){}; + 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; @@ -66,6 +66,7 @@ public: virtual bool IsName(const char* _name) { if (!name) return false; return strcmp(name,_name)==0; }; virtual void AddRef() { refCtr++; }; virtual Bits RemoveRef() { return --refCtr; }; + virtual bool UpdateDateTimeFromHost() { return true; } Bit8u type; Bit32u flags; Bit16u time; @@ -85,8 +86,8 @@ public: Bit8u fhandle; }; -#define MAX_OPENDIRS 16 - +#define MAX_OPENDIRS 2048 +//Can be high as it's only storage (16 bit variable) class DOS_Drive_Cache { public: DOS_Drive_Cache (void); @@ -104,7 +105,7 @@ public: char* GetExpandName (const char* path); bool GetShortName (const char* fullname, char* shortname); - bool FindFirst (char* path, Bitu dtaAddress, Bitu& id); + bool FindFirst (char* path, Bitu& id); bool FindNext (Bitu id, char* &result); void CacheOut (const char* path, bool ignoreLastDir = false); @@ -119,21 +120,19 @@ public: public: CFileInfo(void) { orgname[0] = shortname[0] = 0; - nextEntry = shortNr = compareCount = 0; + nextEntry = shortNr = 0; isDir = false; } ~CFileInfo(void) { for (Bit32u i=0; i fileList; std::vector longNameList; @@ -142,18 +141,18 @@ public: private: bool RemoveTrailingDot (char* shortname); - Bits GetLongName (CFileInfo* info, char* shortname); + Bits GetLongName (CFileInfo* info, char* shortname); void CreateShortName (CFileInfo* dir, CFileInfo* info); Bit16u CreateShortNameID (CFileInfo* dir, const char* name); - int CompareShortname (const char* compareName, const char* shortName); - bool SetResult (CFileInfo* dir, char * &result, Bit16u entryNr); - bool IsCachedIn (CFileInfo* dir); - CFileInfo* FindDirInfo (const char* path, char* expandedPath); + int CompareShortname (const char* compareName, const char* shortName); + bool SetResult (CFileInfo* dir, char * &result, Bit16u 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); - Bit16u GetFreeID (CFileInfo* dir); - void Clear (void); + bool OpenDir (CFileInfo* dir, const char* path, Bit16u& id); + void CreateEntry (CFileInfo* dir, const char* name); + Bit16u GetFreeID (CFileInfo* dir); + void Clear (void); CFileInfo* dirBase; char dirPath [CROSS_LEN]; @@ -169,6 +168,7 @@ private: char dirSearchName [MAX_OPENDIRS]; bool free [MAX_OPENDIRS]; CFileInfo* dirFindFirst [MAX_OPENDIRS]; + Bitu nextFreeFindFirst; char label [CROSS_LEN]; }; @@ -217,7 +217,7 @@ public: 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)=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; diff --git a/include/dosbox.h b/include/dosbox.h index b32184e..0bd156a 100644 --- a/include/dosbox.h +++ b/include/dosbox.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -24,25 +24,6 @@ void E_Exit(char * message,...); 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 -/* 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 double Real64; -#if defined(_MSC_VER) -typedef unsigned __int64 Bit64u; -typedef signed __int64 Bit64s; -#else -typedef unsigned long long Bit64u; -typedef signed long long Bit64s; -#endif - -typedef unsigned int Bitu; -typedef signed int Bits; - #include #include "config.h" @@ -63,11 +44,11 @@ enum MachineType { MCH_HERC, MCH_CGA, MCH_TANDY, - MCH_VGA, - MCH_AUTO + MCH_VGA }; extern MachineType machine; +extern bool SDLNetInited; #ifndef __LOGGING_H_ #include "logging.h" diff --git a/include/fpu.h b/include/fpu.h index a00c091..50f50e0 100644 --- a/include/fpu.h +++ b/include/fpu.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/include/hardware.h b/include/hardware.h index d0958f4..638e597 100644 --- a/include/hardware.h +++ b/include/hardware.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -19,7 +19,17 @@ #ifndef _HARDWARE_H_ #define _HARDWARE_H_ +#include +class Section; +enum OPL_Mode { + OPL_none,OPL_cms,OPL_opl2,OPL_dualopl2,OPL_opl3 +}; + +void OPL_Init(Section* sec,Bitu base,OPL_Mode mode,Bitu rate); +void CMS_Init(Section* sec,Bitu base,Bitu rate); +extern Bit8u adlib_commandreg; +FILE * OpenCaptureFile(const char * type,const char * ext); #endif diff --git a/include/inout.h b/include/inout.h index f4b7c51..bb83949 100644 --- a/include/inout.h +++ b/include/inout.h @@ -9,37 +9,51 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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_ReadBHandler)(Bit32u port); -typedef Bit16u (IO_ReadWHandler)(Bit32u port); -typedef Bit32u (IO_ReadDHandler)(Bit32u port); -typedef void (IO_WriteBHandler)(Bit32u port,Bit8u value); -typedef void (IO_WriteWHandler)(Bit32u port,Bit16u value); -typedef void (IO_WriteDHandler)(Bit32u port,Bit32u value); +#define IO_MAX (64*1024+3) -void IO_RegisterReadBHandler(Bitu port,IO_ReadBHandler * handler); -void IO_RegisterReadWHandler(Bitu port,IO_ReadWHandler * handler); -void IO_RegisterReadDHandler(Bitu port,IO_ReadDHandler * handler); +#define IO_MB 0x1 +#define IO_MW 0x2 +#define IO_MD 0x4 +#define IO_MA (IO_MB | IO_MW | IO_MD ) -void IO_RegisterWriteBHandler(Bitu port,IO_WriteBHandler * handler); -void IO_RegisterWriteWHandler(Bitu port,IO_WriteWHandler * handler); -void IO_RegisterWriteDHandler(Bitu port,IO_WriteDHandler * handler); +typedef Bitu IO_ReadHandler(Bitu port,Bitu iolen); +typedef void IO_WriteHandler(Bitu port,Bitu val,Bitu iolen); -void IO_FreeReadHandler(Bitu port); -void IO_FreeWriteHandler(Bitu port); +extern IO_WriteHandler * io_writehandlers[3][IO_MAX]; +extern IO_ReadHandler * io_readhandlers[3][IO_MAX]; -void IO_WriteB(Bitu port,Bit8u val); -Bit8u IO_ReadB(Bitu port); -void IO_WriteW(Bitu port,Bit16u val); -Bit16u IO_ReadW(Bitu port); -void IO_WriteD(Bitu port,Bit32u val); -Bit32u IO_ReadD(Bitu port); +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=0); +void IO_FreeWriteHandler(Bitu port,Bitu mask,Bitu range=0); + +INLINE void IO_WriteB(Bitu port,Bitu val) { + io_writehandlers[0][port](port,val,1); +}; +INLINE void IO_WriteW(Bitu port,Bitu val) { + io_writehandlers[1][port](port,val,2); +}; +INLINE void IO_WriteD(Bitu port,Bitu val) { + io_writehandlers[2][port](port,val,4); +}; + +INLINE Bitu IO_ReadB(Bitu port) { + return io_readhandlers[0][port](port,1); +} +INLINE Bitu IO_ReadW(Bitu port) { + return io_readhandlers[1][port](port,2); +} +INLINE Bitu IO_ReadD(Bitu port) { + return io_readhandlers[2][port](port,4); +} INLINE void IO_Write(Bitu port,Bit8u val) { IO_WriteB(port,val); @@ -48,11 +62,4 @@ INLINE Bit8u IO_Read(Bitu port){ return IO_ReadB(port); } -INLINE void IO_RegisterReadHandler(Bitu port,IO_ReadBHandler * handler,char * name) { - IO_RegisterReadBHandler(port,handler); -} -INLINE void IO_RegisterWriteHandler(Bitu port,IO_WriteBHandler * handler,char * name) { - IO_RegisterWriteBHandler(port,handler); -} - diff --git a/include/ipx.h b/include/ipx.h new file mode 100644 index 0000000..5a3e4c1 --- /dev/null +++ b/include/ipx.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _IPX_H_ +#define _IPX_H_ + +// 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); + +// 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 new file mode 100644 index 0000000..7b9f1cc --- /dev/null +++ b/include/ipxserver.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _IPXSERVER_H_ +#define _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 IPXBUFFERSIZE 1024 +#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 b0e13bc..8476525 100644 --- a/include/joystick.h +++ b/include/joystick.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/include/keyboard.h b/include/keyboard.h index 8f7bed4..614f031 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -20,6 +20,7 @@ #define _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, @@ -35,25 +36,17 @@ enum KBD_KEYS { KBD_grave,KBD_minus,KBD_equals,KBD_backslash,KBD_leftbracket,KBD_rightbracket, KBD_semicolon,KBD_quote,KBD_period,KBD_comma,KBD_slash, + 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_kpslash,KBD_kpmultiply,KBD_kpminus,KBD_kpplus,KBD_kpenter,KBD_kpperiod, + KBD_kpdivide,KBD_kpmultiply,KBD_kpminus,KBD_kpplus,KBD_kpenter,KBD_kpperiod, + KBD_LAST }; -typedef void(KEYBOARD_EventHandler)(void); - -void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler); -void KEYBOARD_AddKey(KBD_KEYS key,Bitu ascii,Bitu mod,bool pressed); -void KEYBOARD_ReadKey(Bitu & scancode,Bitu & ascii,Bitu & mod); - - -#define KBD_MOD_ALT 0x1 -#define KBD_MOD_CTRL 0x2 -#define KBD_MOD_SHIFT 0x4 - +void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed); #endif diff --git a/include/mapper.h b/include/mapper.h new file mode 100644 index 0000000..7947023 --- /dev/null +++ b/include/mapper.h @@ -0,0 +1,40 @@ + /* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef MAPPER_H_ +#define 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)(void); +void MAPPER_AddHandler(MAPPER_Handler * handler,MapKeys key,Bitu mods,char * eventname,char * buttonname); +void MAPPER_Init(void); +void MAPPER_StartUp(Section * sec); +void MAPPER_Run(void); + + + + +#define MMOD1 0x1 +#define MMOD2 0x2 + +#endif diff --git a/include/mem.h b/include/mem.h index b039ad3..f213305 100644 --- a/include/mem.h +++ b/include/mem.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -20,8 +20,6 @@ #define __MEM_H #include -#define bmemcpy(mem1,mem2,size) memcpy((void *)mem1,(void *)mem2,size) - typedef Bit32u PhysPt; typedef Bit8u * HostPt; typedef Bit32u RealPt; @@ -30,6 +28,8 @@ typedef Bit32s MemHandle; #define MEM_PAGESIZE 4096 +extern HostPt MemBase; + bool MEM_A20_Enabled(void); void MEM_A20_Enable(bool enable); @@ -123,9 +123,25 @@ void mem_writeb(PhysPt pt,Bit8u val); void mem_writew(PhysPt pt,Bit16u val); void mem_writed(PhysPt pt,Bit32u val); -void phys_writeb(PhysPt addr,Bit8u val); -void phys_writew(PhysPt addr,Bit16u val); -void phys_writed(PhysPt addr,Bit32u val); +INLINE void phys_writeb(PhysPt addr,Bit8u val) { + host_writeb(MemBase+addr,val); +} +INLINE void phys_writew(PhysPt addr,Bit16u val){ + host_writew(MemBase+addr,val); +} +INLINE void phys_writed(PhysPt addr,Bit32u val){ + host_writed(MemBase+addr,val); +} + +INLINE Bit8u phys_readb(PhysPt addr) { + return host_readb(MemBase+addr); +} +INLINE Bit16u phys_readw(PhysPt addr){ + return host_readw(MemBase+addr); +} +INLINE Bit32u phys_readd(PhysPt addr){ + return host_readd(MemBase+addr); +} /* These don't check for alignment, better be sure it's correct */ diff --git a/include/mixer.h b/include/mixer.h index 9309a7f..cf8fafd 100644 --- a/include/mixer.h +++ b/include/mixer.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -17,25 +17,54 @@ */ typedef void (*MIXER_MixHandler)(Bit8u * sampdate,Bit32u len); +typedef void (*MIXER_Handler)(Bitu len); -#define MIXER_8MONO 0 -#define MIXER_8STEREO 1 -#define MIXER_16MONO 2 -#define MIXER_16STEREO 3 +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 UpdateVolume(void); + void SetFreq(Bitu _freq); + void Mix(Bitu _needed); + void AddSilence(void); //Fill up until needed + template + void AddSamples(Bitu len,void * data); + void AddSamples_m8(Bitu len,Bit8u * data); + void AddSamples_s8(Bitu len,Bit8u * data); + void AddSamples_m16(Bitu len,Bit16s * data); + void AddSamples_s16(Bitu len,Bit16s * 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]; + Bit32s volmul[2]; + Bitu freq_add,freq_index; + Bitu done,needed; + Bits last[2]; + char * name; + bool enabled; + MixerChannel * next; +}; - -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); +MixerChannel * MIXER_AddChannel(MIXER_Handler handler,Bitu freq,char * name); +MixerChannel * MIXER_FindChannel(const char * name); /* PC Speakers functions, tightly related to the timer functions */ diff --git a/include/mouse.h b/include/mouse.h index 1851f5c..8a9c6e6 100644 --- a/include/mouse.h +++ b/include/mouse.h @@ -9,16 +9,23 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.7 2004/08/04 09:12:51 qbix79 Exp $ */ + +#ifndef _MOUSE_H_ +#define _MOUSE_H_ + void Mouse_ShowCursor(void); void Mouse_HideCursor(void); +void Mouse_SetPS2State(bool use); +void Mouse_ChangePS2Callback(Bit16u pseg, Bit16u pofs); void Mouse_CursorMoved(float x,float y); void Mouse_CursorSet(float x,float y); @@ -28,3 +35,5 @@ void Mouse_ButtonReleased(Bit8u button); void Mouse_AutoLock(bool enable); void Mouse_NewVideoMode(void); +#endif + diff --git a/include/paging.h b/include/paging.h index 4640d17..8ee2d5f 100644 --- a/include/paging.h +++ b/include/paging.h @@ -9,16 +9,19 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.11 2004/09/07 18:21:51 qbix79 Exp $ */ + #ifndef _PAGING_H_ #define _PAGING_H_ +#include "dosbox.h" #include "mem.h" class PageDirectory; @@ -70,13 +73,10 @@ bool PAGING_MakePhysPage(Bitu & page); void MEM_SetLFB(Bitu _page,Bitu _pages,HostPt _pt); void MEM_SetPageHandler(Bitu phys_page,Bitu pages,PageHandler * handler); -Bit32u MEM_PhysReadD(Bitu addr); - - - - -#pragma pack(1) -typedef struct { +#ifdef _MSC_VER +#pragma pack (1) +#endif +struct X86_PageEntryBlock{ Bit32u p:1; Bit32u wr:1; Bit32u us:1; @@ -88,8 +88,11 @@ typedef struct { Bit32u g:1; Bit32u avl:3; Bit32u base:20; -} X86_PageEntryBlock GCC_ATTRIBUTE(packed); -#pragma pack() +} GCC_ATTRIBUTE(packed); +#ifdef _MSC_VER +#pragma pack () +#endif + union X86PageEntry { Bit32u load; diff --git a/include/pic.h b/include/pic.h index 05566d7..43caaf4 100644 --- a/include/pic.h +++ b/include/pic.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -26,41 +26,36 @@ extern Bits CPU_CycleLeft; extern Bits CPU_CycleMax; typedef void (PIC_EOIHandler) (void); -typedef void (* PIC_EventHandler)(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; -INLINE Bitu PIC_Index(void) { - return ((CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)*1000)/CPU_CycleMax; +INLINE float PIC_TickIndex(void) { + return (CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)/(float)CPU_CycleMax; } -INLINE Bits PIC_MakeCycles(Bitu amount) { - return (CPU_CycleMax*amount)/1000; +INLINE Bits PIC_MakeCycles(double amount) { + return (Bits)(CPU_CycleMax*amount); } -INLINE Bit64u PIC_MicroCount(void) { - return PIC_Ticks*1000+PIC_Index(); +INLINE double PIC_FullIndex(void) { + return PIC_Ticks+PIC_TickIndex(); } void PIC_ActivateIRQ(Bitu irq); - void PIC_DeActivateIRQ(Bitu irq); void PIC_runIRQs(void); - -void PIC_RegisterIRQ(Bitu irq,PIC_EOIHandler handler,char * name); -void PIC_FreeIRQ(Bitu irq); bool PIC_RunQueue(void); -void PIC_AddEvent(PIC_EventHandler handler,Bitu delay); - +//Delay in milliseconds +void PIC_AddEvent(PIC_EventHandler handler,float delay,Bitu val=0); void PIC_RemoveEvents(PIC_EventHandler handler); void PIC_SetIRQMask(Bitu irq, bool masked); diff --git a/include/programs.h b/include/programs.h index a40090d..b5a7a3b 100644 --- a/include/programs.h +++ b/include/programs.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/include/regs.h b/include/regs.h index 92eb004..1c859b1 100644 --- a/include/regs.h +++ b/include/regs.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/include/render.h b/include/render.h index dd1adfc..8a31386 100644 --- a/include/render.h +++ b/include/render.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -19,22 +19,14 @@ #ifndef __RENDER_H #define __RENDER_H -enum RENDER_Operation { - OP_None, - OP_Shot, - OP_Normal2x, - OP_AdvMame2x, -}; +typedef void (* RENDER_Line_Handler)(const Bit8u * src); -typedef void (* RENDER_Line_Handler)(Bit8u * src); - -void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh); +void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,bool dblw,bool dblh); bool RENDER_StartUpdate(void); void RENDER_EndUpdate(void); void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue); extern RENDER_Line_Handler RENDER_DrawLine; -extern Bit8u * RENDER_TempLine; - + #endif diff --git a/include/serialport.h b/include/serialport.h index 386e760..3aac522 100644 --- a/include/serialport.h +++ b/include/serialport.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -19,118 +19,137 @@ #if !defined __SERIALPORT_H #define __SERIALPORT_H -#include +#include + +#include "dosbox.h" //If it's too high you overflow terminal clients buffers i think -#define FIFO_SIZE (1024) +#define QUEUE_SIZE 1024 // Serial port interface // -#define M_CTS 0x01 -#define M_DSR 0x02 -#define M_RI 0x04 -#define M_DCD 0x08 +#define MS_CTS 0x01 +#define MS_DSR 0x02 +#define MS_RI 0x04 +#define MS_DCD 0x08 -enum INT_TYPES { - INT_MS, - INT_TX, - INT_RX, - INT_RX_FIFO, - INT_LS, - INT_NONE, +#define MC_DTR 0x1 +#define MC_RTS 0x2 + + +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; + } + bool isFull() { + return (used >= size); + } + void addb(Bit8u _val) { + assert(used=size) where-=size; + data[where]=_val; + used++; + } + void adds(Bit8u * _str,Bitu _len) { + assert((used+_len)<=size); + Bitu where=pos+used; + used+=_len; + while (_len--) { + if (where>=size) where-=size; + data[where++]=*_str++; + } + } + Bit8u getb(void) { + if (!used) return data[pos]; + Bitu where=pos; + if (++pos>=size) pos-=size; + used--; + return data[where]; + } + void gets(Bit8u * _str,Bitu _len) { + assert(used>=_len); + used-=_len; + while (_len--) { + *_str++=data[pos]; + if (++pos>=size) pos-=size; + } + } +private: + Bit8u * data; + Bitu size,pos,used; }; -typedef void MControl_Handler(Bitu mc); - class CSerial { public: + CSerial() { + + } // Constructor takes base port (0x3f0, 0x2f0, 0x2e0, etc.), IRQ, and initial bps // CSerial (Bit16u initbase, Bit8u initirq, Bit32u initbps); virtual ~CSerial(); - // External port functions for IOHandlers // - void write_port(Bit32u port, Bit8u val); - Bit8u read_port(Bit32u port); + void write_reg(Bitu reg, Bitu val); + Bitu read_reg(Bitu reg); - static void write_serial(Bit32u port,Bit8u val); - static Bit8u read_serial(Bit32u port); - - void SetMCHandler(MControl_Handler * mcontrol); - - /* Allow the modem to change the modem status bits */ - void setmodemstatus(Bit8u status); - Bit8u getmodemstatus(void); - Bit8u getlinestatus(void); + void SetModemStatus(Bit8u status); + virtual bool CanRecv(void)=0; + virtual bool CanSend(void)=0; + virtual void Send(Bit8u val)=0; + virtual Bit8u Recv(Bit8u val)=0; + virtual void Timer(void); void checkint(void); - void raiseint(INT_TYPES type); - void lowerint(INT_TYPES type); - /* Access to the receive fifo */ - Bitu rx_free(); - void rx_addb(Bit8u byte); - void rx_adds(Bit8u * data,Bitu size); - Bitu rx_size(); - Bit8u rx_readb(void); + Bitu base; + Bitu irq; + Bitu bps; + Bit8u mctrl; - /* Access to the transmit fifo */ - Bitu tx_free(); - void tx_addb(Bit8u byte); - Bitu tx_size(); - Bit8u tx_readb(void); - - - // These variables maintain the status of the serial port - Bit16u base; - Bit16u irq; - Bit32u bps; - - bool FIFOenabled; - Bit16u FIFOsize; + CFifo *rqueue; + CFifo *tqueue; private: - - void setdivisor(Bit8u dmsb, Bit8u dlsb); - void checkforirq(void); - struct { - Bitu used; - Bitu pos; - Bit8u data[FIFO_SIZE]; - } rx_fifo,tx_fifo; - struct { - Bitu requested; - Bitu enabled; - INT_TYPES active; - } ints; - - Bitu rx_lastread; - Bit8u irq_pending; + void UpdateBaudrate(void); + bool FIFOenabled; + Bit8u FIFOsize; + bool dotxint; Bit8u scratch; Bit8u dlab; Bit8u divisor_lsb; Bit8u divisor_msb; - Bit8u wordlen; - Bit8u dtr; - Bit8u rts; - Bit8u out1; - Bit8u out2; Bit8u local_loopback; - Bit8u linectrl; - Bit8u intid; - Bit8u ierval; + Bit8u iir; + Bit8u ier; Bit8u mstatus; - Bit8u txval; - Bit8u timeout; - - MControl_Handler * mc_handler; - char remotestr[4096]; + Bit8u linectrl; + Bit8u errors; }; -// This function returns the CSerial objects for ports 1-4 // -CSerial *getComport(Bitu portnum); +#include + +typedef std::list CSerialList; +typedef std::list::iterator CSerial_it; + +extern CSerialList seriallist; #endif diff --git a/include/setup.h b/include/setup.h index ffc9915..6224aff 100644 --- a/include/setup.h +++ b/include/setup.h @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.15 2004/01/29 09:26:43 qbix79 Exp $ */ +/* $Id: setup.h,v 1.16 2004/08/04 09:12:51 qbix79 Exp $ */ #ifndef _SETUP_H_ #define _SETUP_H_ diff --git a/include/shell.h b/include/shell.h index cea4638..68eded4 100644 --- a/include/shell.h +++ b/include/shell.h @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.2 2004/01/10 14:03:33 qbix79 Exp $ */ +/* $Id: shell.h,v 1.7 2004/09/09 18:36:50 qbix79 Exp $ */ #ifndef SHELL_H_ #define SHELL_H_ @@ -57,9 +57,7 @@ public: }; class DOS_Shell : public Program { - private: - std::list l_history, l_completion; char *completion_start; @@ -102,6 +100,8 @@ public: 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); /* The shell's variables */ Bit16u input_handle; BatchFile * bf; @@ -117,15 +117,12 @@ struct SHELL_Cmd { const char * help; /* String with command help */ }; -static inline void StripSpaces(char*&args) -{ - while(*args && (*args == ' ')) +static inline void StripSpaces(char*&args) { + while(*args && ((*args == ' ') || (*args == '\t'))) args++; } - -static inline char* ExpandDot(char*args, char* buffer) -{ +static inline char* ExpandDot(char*args, char* buffer) { if(*args=='.') { if(*(args+1)==0) @@ -139,11 +136,11 @@ static inline char* ExpandDot(char*args, char* buffer) buffer[1]=0; strcat(buffer,args); return buffer; - } + } else + strcpy (buffer, args); } else strcpy(buffer,args); return buffer; } - #endif diff --git a/include/support.h b/include/support.h index 1b66334..5127d15 100644 --- a/include/support.h +++ b/include/support.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -19,11 +19,11 @@ #if !defined __SUPPORT_H #define __SUPPORT_H - -#include #include #include +#include "dosbox.h" + #if defined (_MSC_VER) /* MS Visual C++ */ #define strcasecmp(a,b) stricmp(a,b) #define strncasecmp(a,b,n) _strnicmp(a,b,n) @@ -39,13 +39,16 @@ void strreplace(char * str,char o,char n); char *ltrim(char *str); -void rtrim(char * const str); -char *trim(char *str); +char *rtrim(char *str); +char *trim(char * str); bool ScanCMDBool(char * cmd,char * check); char * ScanCMDRemain(char * cmd); -bool ScanCMDHex(char * cmd,char * check,Bits * result); -char * StripWord(char * cmd); +char * StripWord(char *&cmd); +bool IsDecWord(char * word); +bool IsHexWord(char * word); +Bits ConvDecWord(char * word); +Bits ConvHexWord(char * word); INLINE char * upcase(char * str) { for (char* idx = str; *idx ; idx++) *idx = toupper(*idx); diff --git a/include/timer.h b/include/timer.h index aada3d5..a807884 100644 --- a/include/timer.h +++ b/include/timer.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -25,19 +25,11 @@ #define GetTicks() SDL_GetTicks() -typedef void (*TIMER_TickHandler)(Bitu ticks); -typedef void (*TIMER_MicroHandler)(void); - -typedef void TIMER_Block; - +typedef void (*TIMER_TickHandler)(void); /* 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); - -/* Set the microseconds value to a new value */ -void TIMER_SetNewMicro(TIMER_Block * block,Bitu micro); +void TIMER_AddTickHandler(TIMER_TickHandler handler); +void TIMER_DelTickHandler(TIMER_TickHandler handler); /* This will add 1 milliscond to all timers */ void TIMER_AddTick(void); diff --git a/include/vga.h b/include/vga.h index b218647..a8814c0 100644 --- a/include/vga.h +++ b/include/vga.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -23,13 +23,13 @@ #include "dosbox.h" enum VGAModes { - M_TEXT2,M_TEXT16, - M_HERC, - M_CGA2,M_CGA4,M_CGA16, - M_TANDY16, - M_EGA2,M_EGA4,M_EGA16, + M_CGA2,M_CGA4, + M_EGA16, M_VGA, M_LIN8, + M_TEXT, + M_HERC_GFX,M_HERC_TEXT, + M_CGA16,M_TANDY2,M_TANDY4,M_TANDY16,M_TANDY_TEXT, M_ERROR, }; @@ -60,9 +60,7 @@ typedef struct { /* Some other screen related variables */ Bitu line_compare; - bool chained; /* Enable or Disabled Chain 4 Mode */ - bool blinking; /* Attribute bit 7 is blinking */ /* Pixel Scrolling */ Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */ @@ -91,10 +89,8 @@ typedef struct { typedef struct { bool resizing; - bool drawing; Bitu width; Bitu height; - Bitu pitch; Bitu blocks; Bitu panning; Bitu address; @@ -102,49 +98,62 @@ typedef struct { Bitu address_line_total; Bitu address_line; Bitu lines_total; - Bitu lines_left; + Bitu lines_done; Bitu lines_scaled; Bitu split_line; Bitu parts_total; Bitu parts_lines; Bitu parts_left; struct { - Bitu vtotal; - Bitu vstart; - Bitu vend; - Bitu htotal; - Bitu hstart; - Bitu hend; - Bitu parts; - } micro; - Bitu scaleh; + float vtotal; + float vstart; + float vend; + float htotal; + float hstart; + float hend; + float parts; + } delay; bool double_scan; - bool double_scan_active; - Bit8u font_height; + bool doublewidth,doubleheight; Bit8u font[64*1024]; - Bitu font1_start; - Bitu font2_start; + Bit8u * font_tables[2]; Bitu blinking; struct { + Bitu address; Bit8u sline,eline; Bit8u count,delay; Bit8u enabled; } cursor; } 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 bank; Bit8u reg_lock1; Bit8u reg_lock2; Bit8u reg_31; Bit8u reg_35; + Bit8u reg_40; // 8415/A functionality register Bit8u reg_43; + Bit8u reg_45; // Hardware graphics cursor Bit8u reg_58; Bit8u reg_51; Bit8u reg_55; Bit8u ex_hor_overflow; Bit8u ex_ver_overflow; Bit16u la_window; + Bit8u misc_control_2; + Bit8u ext_mem_ctrl; struct { Bit8u r; Bit8u n; @@ -154,6 +163,7 @@ typedef struct { Bit8u lock; Bit8u cmd; } pll; + VGA_HWCURSOR hgc; } VGA_S3; typedef struct { @@ -162,18 +172,28 @@ typedef struct { } VGA_HERC; typedef struct { - Bit8u mode_control; - Bit8u color_select; -} VGA_CGA; + Bit8u index; + Bit8u htotal; + Bit8u hdend; + Bit8u hsyncp; + Bit8u hsyncw; + Bit8u vtotal; + Bit8u vdend; + Bit8u vadjust; + Bit8u vsyncp; + Bit8u vsyncw; + Bit8u max_scanline; +} VGA_OTHER; typedef struct { + Bit8u mode_control; + Bit8u color_select; Bit8u mem_bank; Bit8u disp_bank; Bit8u reg_index; - Bit8u mode_control1; + Bit8u gfx_control; Bit8u palette_mask; Bit8u border_color; - Bit8u mode_control2; } VGA_TANDY; typedef struct { @@ -256,7 +276,6 @@ typedef struct { Bit8u read_index; Bitu first_changed; RGBEntry rgb[0x100]; - Bit8u attr[16]; } VGA_Dac; union VGA_Latch { @@ -285,8 +304,8 @@ typedef struct { VGA_Latch latch; VGA_S3 s3; VGA_HERC herc; - VGA_CGA cga; VGA_TANDY tandy; + VGA_OTHER other; VGA_Memory mem; } VGA_Type; @@ -294,12 +313,15 @@ typedef struct { /* Functions for different resolutions */ void VGA_SetMode(VGAModes mode); +void VGA_DetermineMode(void); void VGA_SetupHandlers(void); void VGA_StartResize(void); -void VGA_SetupDrawing(void); +void VGA_SetupDrawing(Bitu val); +void VGA_CheckScanLength(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 */ @@ -310,6 +332,8 @@ 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); @@ -317,6 +341,8 @@ 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); extern VGA_Type vga; diff --git a/include/video.h b/include/video.h index ced09ad..4c3b807 100644 --- a/include/video.h +++ b/include/video.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -28,21 +28,43 @@ struct GFX_PalEntry { Bit8u unused; }; -#define GFX_HASSCALING 0x0001 -#define GFX_HASCONVERT 0x0002 +#define CAN_8 0x0001 +#define CAN_16 0x0002 +#define CAN_32 0x0004 + +#define CAN_ALL (CAN_8|CAN_16|CAN_32) + +#define LOVE_8 0x0010 +#define LOVE_16 0x0020 +#define LOVE_32 0x0040 + +#define NEED_RGB 0x0100 +#define DONT_ASPECT 0x0200 + +#define HAVE_SCALING 0x1000 + + +enum GFX_Modes { + GFX_8,GFX_15,GFX_16,GFX_32,GFX_NONE, +}; void GFX_Events(void); void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries); -Bitu GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags); +Bitu GFX_GetBestMode(Bitu flags); Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue); -void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,double scalex,double scaley,GFX_ResetCallBack cb_reset); +GFX_Modes GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_ResetCallBack cb_reset); +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(void); +/* Mouse related */ +void GFX_CaptureMouse(void); +extern bool mouselocked; //true if mouse is confined to window + #endif diff --git a/src/cpu/Makefile.am b/src/cpu/Makefile.am index 261369f..62cc988 100644 --- a/src/cpu/Makefile.am +++ b/src/cpu/Makefile.am @@ -3,5 +3,5 @@ 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 \ + paging.cpp lazyflags.h core_normal.cpp core_simple.cpp \ core_dyn_x86.cpp \ No newline at end of file diff --git a/src/cpu/Makefile.in b/src/cpu/Makefile.in index f02809b..4aea35b 100644 --- a/src/cpu/Makefile.in +++ b/src/cpu/Makefile.in @@ -134,7 +134,7 @@ 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 \ + paging.cpp lazyflags.h core_normal.cpp core_simple.cpp \ core_dyn_x86.cpp subdir = src/cpu @@ -148,7 +148,8 @@ libcpu_a_AR = $(AR) cru libcpu_a_LIBADD = am_libcpu_a_OBJECTS = callback.$(OBJEXT) cpu.$(OBJEXT) flags.$(OBJEXT) \ modrm.$(OBJEXT) core_full.$(OBJEXT) paging.$(OBJEXT) \ - core_normal.$(OBJEXT) core_dyn_x86.$(OBJEXT) + core_normal.$(OBJEXT) core_simple.$(OBJEXT) \ + core_dyn_x86.$(OBJEXT) libcpu_a_OBJECTS = $(am_libcpu_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) @@ -157,8 +158,9 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/callback.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/core_dyn_x86.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/core_full.Po ./$(DEPDIR)/core_normal.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/cpu.Po ./$(DEPDIR)/flags.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/modrm.Po ./$(DEPDIR)/paging.Po +@AMDEP_TRUE@ ./$(DEPDIR)/core_simple.Po ./$(DEPDIR)/cpu.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/flags.Po ./$(DEPDIR)/modrm.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/paging.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) @@ -208,6 +210,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_dyn_x86.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_full.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_normal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_simple.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@ diff --git a/src/cpu/callback.cpp b/src/cpu/callback.cpp index 97900ef..e64a48f 100644 --- a/src/cpu/callback.cpp +++ b/src/cpu/callback.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.19 2004/01/07 20:23:48 qbix79 Exp $ */ +/* $Id: callback.cpp,v 1.22 2004/08/29 11:22:37 qbix79 Exp $ */ #include #include @@ -67,8 +67,7 @@ void CALLBACK_Idle(void) { reg_eip=oldeip; SegSet16(cs,oldcs); SETFLAGBIT(IF,oldIF); - if (CPU_CycleLeft<300) CPU_CycleLeft=1; - else CPU_CycleLeft-=300; + if (CPU_Cycles>0) CPU_Cycles=0; } static Bitu default_handler(void) { @@ -204,12 +203,14 @@ void CALLBACK_Init(Section* sec) { /* Setup the Stop Handler */ call_stop=CALLBACK_Allocate(); CallBack_Handlers[call_stop]=stop_handler; + CALLBACK_SetDescription(call_stop,"stop"); phys_writeb(CB_BASE+(call_stop<<4)+0,0xFE); phys_writeb(CB_BASE+(call_stop<<4)+1,0x38); phys_writew(CB_BASE+(call_stop<<4)+2,call_stop); /* Setup the idle handler */ call_idle=CALLBACK_Allocate(); CallBack_Handlers[call_idle]=stop_handler; + CALLBACK_SetDescription(call_idle,"idle"); for (i=0;i<=11;i++) phys_writeb(CB_BASE+(call_idle<<4)+i,0x90); phys_writeb(CB_BASE+(call_idle<<4)+12,0xFE); phys_writeb(CB_BASE+(call_idle<<4)+13,0x38); @@ -217,7 +218,7 @@ void CALLBACK_Init(Section* sec) { /* Setup all Interrupt to point to the default handler */ call_default=CALLBACK_Allocate(); - CALLBACK_Setup(call_default,&default_handler,CB_IRET); + CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default"); /* Only setup default handler for first half of interrupt table */ for (i=0;i<0x40;i++) { real_writed(0,i*4,CALLBACK_RealPointer(call_default)); diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp index e6becba..1cda8ba 100644 --- a/src/cpu/core_dyn_x86.cpp +++ b/src/cpu/core_dyn_x86.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -33,10 +33,11 @@ #include "paging.h" #include "inout.h" -#define CACHE_TOTAL (1024*1024*2) +#define CACHE_TOTAL (512*1024) #define CACHE_MAXSIZE (4096) -#define CACHE_BLOCKS (50*1024) +#define CACHE_BLOCKS (32*1024) #define CACHE_ALIGN (16) +#define CACHE_PAGES (128) #define DYN_HASH_SHIFT (4) #define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT) #define DYN_LINKS (16) @@ -68,8 +69,8 @@ enum DualOps { DOP_SUB,DOP_SBB, DOP_CMP,DOP_XOR, DOP_AND,DOP_OR, - DOP_MOV, DOP_TEST, + DOP_MOV, DOP_XCHG, }; @@ -77,7 +78,7 @@ enum ShiftOps { SHIFT_ROL,SHIFT_ROR, SHIFT_RCL,SHIFT_RCR, SHIFT_SHL,SHIFT_SHR, - SHIFT_SAR, + SHIFT_SAL,SHIFT_SAR, }; enum BranchTypes { @@ -87,19 +88,15 @@ enum BranchTypes { BR_L,BR_NL,BR_LE,BR_NLE }; -enum BlockType { - BT_Free=0, - BT_Normal, - BT_SingleLink, - BT_DualLink, - BT_CheckFlags, -}; enum BlockReturn { BR_Normal=0, BR_Cycles, BR_Link1,BR_Link2, BR_Opcode, +#if (C_DEBUG) + BR_OpcodeFull, +#endif BR_CallBack, }; @@ -153,28 +150,23 @@ struct DynState { DynReg regs[G_MAX]; }; -static void dyn_releaseregs(void) { - for (Bitu i=0;iregs[i].flags=DynRegs[i].flags; @@ -201,80 +193,61 @@ Bits CPU_Core_Dyn_X86_Run(void) { restart_core: PhysPt ip_point=SegPhys(cs)+reg_eip; Bitu ip_page=ip_point>>12; - mem_readb(ip_point); //Init whatever page we are in - PageHandler * handler=paging.tlb.handler[ip_page]; - CodePageHandler * chandler=0; #if C_HEAVY_DEBUG - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; + if (DEBUG_HeavyIsBreakpoint()) return debugCallback; #endif - if (handler->flags & PFLAG_HASCODE) { - /* Find correct Dynamic Block to run */ - chandler=(CodePageHandler *)handler; -findblock:; - CacheBlock * block=chandler->FindCacheBlock(ip_point&4095); - if (!block) { - cache.block.running=0; - block=CreateCacheBlock(ip_point,cpu.code.big,128); -// DYN_LOG("Created block size %x type %d",block->cache.size,block->type); - chandler->AddCacheBlock(block); - if (block->page.end>=4096) { - DYN_LOG("block crosses page boundary"); - } - } -run_block: - BlockReturn ret=gen_runcode(block->cache.start); - switch (ret) { - 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 - return CBRET_NONE; - case BR_CallBack: - return core_dyn.callback; - case BR_Opcode: - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=1; - return CPU_Core_Normal_Run(); - case BR_Link1: - case BR_Link2: - { - Bitu temp_ip=SegPhys(cs)+reg_eip; - Bitu temp_page=temp_ip >> 12; - CodePageHandler * temp_handler=(CodePageHandler *)paging.tlb.handler[temp_page]; - if (temp_handler->flags & PFLAG_HASCODE) { - block=temp_handler->FindCacheBlock(temp_ip & 4095); - if (!block) goto restart_core; - cache_linkblocks(cache.block.running,block,ret==BR_Link2); - goto run_block; - } - } - goto restart_core; - } - } else { - if (handler->flags & PFLAG_NOCODE) { - LOG_MSG("DYNX86:Can't run code in this page"); - return CPU_Core_Normal_Run(); - } - Bitu phys_page=ip_page; - if (!PAGING_MakePhysPage(phys_page)) { - LOG_MSG("DYNX86:Can't find physpage"); - return CPU_Core_Normal_Run(); - } - chandler=new CodePageHandler(handler); - MEM_SetPageHandler(phys_page,1,chandler); //Setup the handler - PAGING_UnlinkPages(ip_page,1); - goto findblock; + CodePageHandler * chandler=MakeCodePage(ip_page); + if (!chandler) return CPU_Core_Normal_Run(); + /* Find correct Dynamic Block to run */ + CacheBlock * block=chandler->FindCacheBlock(ip_point&4095); + if (!block) { + block=CreateCacheBlock(chandler,ip_point,32); } - return 0; +run_block: + cache.block.running=0; + BlockReturn ret=gen_runcode(block->cache.start); + switch (ret) { + 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 + return CBRET_NONE; + case BR_CallBack: + return core_dyn.callback; + case BR_Opcode: + 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: + { + Bitu temp_ip=SegPhys(cs)+reg_eip; + Bitu temp_page=temp_ip >> 12; + CodePageHandler * temp_handler=(CodePageHandler *)paging.tlb.handler[temp_page]; + 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; + } +return 0; } - void CPU_Core_Dyn_X86_Init(void) { Bits i; /* Setup the global registers and their flags */ diff --git a/src/cpu/core_dyn_x86/cache.h b/src/cpu/core_dyn_x86/cache.h index d70644f..348021d 100644 --- a/src/cpu/core_dyn_x86/cache.h +++ b/src/cpu/core_dyn_x86/cache.h @@ -1,28 +1,34 @@ -struct CacheBlock { +class CacheBlock { public: + void Clear(void); + void LinkTo(Bitu index,CacheBlock * toblock) { + assert(toblock); + link[index].to=toblock; + link[index].next=toblock->link[index].from; + toblock->link[index].from=this; + } struct { - Bit16s start,end; //Where the page is the original code - Bitu first,last; + 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; } cache; - BlockType type; - CodePageHandler * code_page; //Page containing this code - CacheBlock * page_link; //For code crossing a page boundary struct { + Bitu index; CacheBlock * next; } hash; - CacheBlock * list_next; struct { - CacheBlock * to[2]; - CacheBlock * from[DYN_LINKS]; - Bitu index; - } link; - CacheBlock * links[2]; + CacheBlock * to; + CacheBlock * next; + CacheBlock * from; + } link[2]; + CacheBlock * crossblock; }; +class CacheBlock; static struct { struct { CacheBlock * first; @@ -31,96 +37,124 @@ static struct { CacheBlock * running; } block; Bit8u * pos; - CacheBlock linkblocks[2]; + CodePageHandler * free_pages; + CodePageHandler * used_pages; + CodePageHandler * last_page; } cache; static Bit8u cache_code_link_blocks[2][16]; static Bit8u cache_code[CACHE_TOTAL+CACHE_MAXSIZE]; static CacheBlock cache_blocks[CACHE_BLOCKS]; - -static void cache_resetblock(CacheBlock * block); - +static CacheBlock link_blocks[2]; class CodePageHandler :public PageHandler { public: - CodePageHandler(PageHandler * _old_pagehandler) { + CodePageHandler() {} + 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)); } - void InvalidateRange(Bits start,Bits end) { - Bits maps=start>>DYN_HASH_SHIFT; - Bits map=maps; - Bits count=write_map[maps]; - while (map>=0 && count>0) { - CacheBlock * block=hash_map[map]; - CacheBlock * * where=&hash_map[map]; + void InvalidateRange(Bitu start,Bitu end) { + Bits index=1+(start>>DYN_HASH_SHIFT); + while (index>=0) { + Bitu map=0; + for (Bitu count=start;count<=end;count++) map+=write_map[count]; + if (!map) return; + CacheBlock * block=hash_map[index]; while (block) { CacheBlock * nextblock=block->hash.next; - if (start<=block->page.end && end>=block->page.start) { - for (Bitu i=block->page.first;i<=block->page.last;i++) write_map[i]--; - block->code_page=0; //Else resetblock will do double work - count--; - if (block==cache.block.running) LOG_MSG("Writing to current block"); - cache_resetblock(block); - *where=nextblock; - } else { - where=&block->hash.next; - } + if (start<=block->page.end && end>=block->page.start) + block->Clear(); block=nextblock; } - map--; + index--; } } void writeb(PhysPt addr,Bitu val){ - if (val!=host_readb(hostmem+(addr&4095))) { - InvalidateRange(addr&4095,addr&4095); - host_writeb(hostmem+(addr&4095),val); - } + addr&=4095; + host_writeb(hostmem+addr,val); + if (!*(Bit8u*)&write_map[addr]) { + if (active_blocks) return; + active_count--; + if (!active_count) Release(); + } else InvalidateRange(addr,addr); } void writew(PhysPt addr,Bitu val){ - if (val!=host_readw(hostmem+(addr&4095))) { - InvalidateRange(addr&4095,(addr&4095)+1); - host_writew(hostmem+(addr&4095),val); - } + addr&=4095; + host_writew(hostmem+addr,val); + if (!*(Bit16u*)&write_map[addr]) { + if (active_blocks) return; + active_count--; + if (!active_count) Release(); + } else InvalidateRange(addr,addr+1); } void writed(PhysPt addr,Bitu val){ - if (val!=host_readd(hostmem+(addr&4095))) { - InvalidateRange(addr&4095,(addr&4095)+3); - host_writed(hostmem+(addr&4095),val); - } + addr&=4095; + host_writed(hostmem+addr,val); + if (!*(Bit32u*)&write_map[addr]) { + if (active_blocks) return; + active_count--; + if (!active_count) Release(); + } else InvalidateRange(addr,addr+3); } void AddCacheBlock(CacheBlock * block) { - Bit16u first,last; - if (block->page.start<0) first=0; - else first=block->page.start>>DYN_HASH_SHIFT; - block->hash.next=hash_map[first]; - hash_map[first]=block; - if (block->page.end>=4096) last=DYN_PAGE_HASH-1; - else last=block->page.end>>DYN_HASH_SHIFT; - block->page.first=first; - block->page.last=last; - for (;first<=last;first++) { - write_map[first]++; - } - block->code_page=this; + 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) { - CacheBlock * * where=&hash_map[block->page.first]; - while (*where) { - if (*where==block) { - *where=block->hash.next; - break; - } + 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. } - for (Bitu i=block->page.first;i<=block->page.last;i++) { - write_map[i]--; + *where=block->hash.next; + 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[start>>DYN_HASH_SHIFT]; + CacheBlock * block=hash_map[1+(start>>DYN_HASH_SHIFT)]; while (block) { if (block->page.start==start) return block; block=block->hash.next; @@ -131,133 +165,153 @@ public: hostmem=old_pagehandler->GetHostPt(phys_page); return hostmem; } +public: + Bit8u write_map[4096]; + CodePageHandler * next, * prev; private: PageHandler * old_pagehandler; - CacheBlock * hash_map[DYN_PAGE_HASH]; - Bit8u write_map[DYN_PAGE_HASH]; + CacheBlock * hash_map[1+DYN_PAGE_HASH]; + Bitu active_blocks; + Bitu active_count; HostPt hostmem; + Bitu phys_page; }; +static CodePageHandler * MakeCodePage(Bitu lin_page) { + mem_readb(lin_page << 12); //Ensure page contains memory + PageHandler * handler=paging.tlb.handler[lin_page]; + if (handler->flags & PFLAG_HASCODE) return ( CodePageHandler *)handler; + if (handler->flags & PFLAG_NOCODE) { + LOG_MSG("DYNX86:Can't run code in this page"); + return 0; + } + Bitu phys_page=lin_page; + if (!PAGING_MakePhysPage(phys_page)) { + LOG_MSG("DYNX86:Can't find physpage"); + return 0; + } + /* Find a free CodePage */ + if (!cache.free_pages) { + 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); + return cpagehandler; +} + static INLINE void cache_addunsedblock(CacheBlock * block) { - block->list_next=cache.block.free; + 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->list_next; + cache.block.free=ret->cache.next; + ret->cache.next=0; return ret; } -static INLINE void cache_clearlinkfrom(CacheBlock * block,CacheBlock * from) { - for (Bitu i=0;ilink.from[i]==from) block->link.from[i]=0; +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)->link[ind].next; + } + *wherelink=(*wherelink)->link[ind].next; + } + } else + cache_addunsedblock(this); + if (crossblock) { + crossblock->crossblock=0; + crossblock->Clear(); + crossblock=0; + } + if (page.handler) { + page.handler->DelCacheBlock(this); + page.handler=0; } } -static INLINE void cache_clearlinkto(CacheBlock * block,CacheBlock * to) { - if (block->link.to[0]==to) block->link.to[0]=&cache.linkblocks[0]; - if (block->link.to[1]==to) block->link.to[1]=&cache.linkblocks[1]; -} - -static void cache_linkblocks(CacheBlock * from,CacheBlock * to,Bitu link) { - from->link.to[link]=to; - CacheBlock * clear=to->link.from[to->link.index]; - if (clear) { - DYN_LOG("backlink buffer full"); - cache_clearlinkto(to->link.from[to->link.index],to); - } - to->link.from[to->link.index]=from; - to->link.index++; - if (to->link.index>=DYN_LINKS) to->link.index=0; -} - -static void cache_resetblock(CacheBlock * block) { - Bits i; - DYN_LOG("Resetted block"); - block->type=BT_Free; - /* Clear all links to this block from other blocks */ - for (i=0;ilink.from[i]) cache_clearlinkto(block->link.from[i],block); - block->link.from[i]=0; - } - /* Clear all links from this block to other blocks */ - if (block->link.to[0]!=&cache.linkblocks[0]) { - cache_clearlinkfrom(block->link.to[0],block); - block->link.to[0]=&cache.linkblocks[0]; - } - if (block->link.to[1]!=&cache.linkblocks[1]) { - cache_clearlinkfrom(block->link.to[1],block); - block->link.to[1]=&cache.linkblocks[1]; - } - block->link.index=0; - if (block->code_page) block->code_page->DelCacheBlock(block); -} 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->list_next; + CacheBlock * nextblock=block->cache.next; + if (block->page.handler) + block->Clear(); while (sizecache.size; - CacheBlock * tempblock=nextblock->list_next; - if (nextblock->type!=BT_Free) cache_resetblock(nextblock); + CacheBlock * tempblock=nextblock->cache.next; + if (nextblock->page.handler) + nextblock->Clear(); cache_addunsedblock(nextblock); nextblock=tempblock; } skipresize: block->cache.size=size; - block->list_next=nextblock; + block->cache.next=nextblock; cache.pos=block->cache.start; return block; } -static void cache_closeblock(BlockType type) { +static void cache_closeblock(void) { CacheBlock * block=cache.block.active; - /* Setup some structures in the block determined by type */ - block->type=type; - switch (type) { - case BT_Normal: - break; - case BT_SingleLink: - block->link.to[0]=&cache.linkblocks[0]; - break; - case BT_DualLink: - block->link.to[0]=&cache.linkblocks[0]; - block->link.to[1]=&cache.linkblocks[1]; - break; - } + 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->list_next) { - if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun"); - } else E_Exit("CacheBlock overrun"); + 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; - } else new_size=block->cache.size; - CacheBlock * newblock=cache_getblock(); - newblock->cache.start=block->cache.start+new_size; - newblock->cache.size=block->cache.size-new_size; - newblock->list_next=block->list_next; - newblock->type=BT_Free; - block->cache.size=new_size; - block->list_next=newblock; + 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->list_next) { - DYN_LOG("Cache full restarting"); + if (!block->cache.next) { +// LOG_MSG("Cache full restarting"); cache.block.active=cache.block.first; } else { - cache.block.active=block->list_next; + cache.block.active=block->cache.next; } } @@ -283,20 +337,29 @@ static void cache_init(void) { memset(&cache_blocks,0,sizeof(cache_blocks)); cache.block.free=&cache_blocks[0]; for (i=0;icache.start=&cache_code[0]; block->cache.size=CACHE_TOTAL; - block->list_next=0; //Last block in the list + block->cache.next=0; //Last block in the list cache.pos=&cache_code_link_blocks[0][0]; - cache.linkblocks[0].cache.start=cache.pos; + link_blocks[0].cache.start=cache.pos; gen_return(BR_Link1); cache.pos=&cache_code_link_blocks[1][0]; - cache.linkblocks[1].cache.start=cache.pos; + link_blocks[1].cache.start=cache.pos; gen_return(BR_Link2); -} \ No newline at end of file + 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; + } +} diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index cc077ec..7027c65 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -29,6 +29,13 @@ static struct DynDecode { REP_Type rep; Bitu cycles; CacheBlock * block; + CacheBlock * active_block; + struct { + CodePageHandler * code; + Bitu index; + Bit8u * wmap; + Bitu first; + } page; struct { Bitu val; Bitu mod; @@ -38,15 +45,46 @@ static struct DynDecode { DynReg * segprefix; } decode; -static Bit8u INLINE decode_fetchb(void) { - return mem_readb(decode.code++); +static Bit8u decode_fetchb(void) { + if (decode.page.index>=4096) { + /* Advance to the next page */ + decode.active_block->page.end=4095; + decode.page.code=MakeCodePage(++decode.page.first); + 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.index=0; + } + decode.page.wmap[decode.page.index]+=0x01; + decode.page.index++; + decode.code+=1; + return mem_readb(decode.code-1); } -static Bit16u INLINE decode_fetchw(void) { - decode.code+=2; +static Bit16u decode_fetchw(void) { + if (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 INLINE decode_fetchd(void) { - decode.code+=4; +static Bit32u decode_fetchd(void) { + if (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); } @@ -69,15 +107,44 @@ static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) { else gen_call_function((void *)&mem_writew,"%Dd%Dw",addr,val); } - static void dyn_reduce_cycles(void) { + gen_protectflags(); if (!decode.cycles) decode.cycles++; - gen_lea(DREG(CYCLES),DREG(CYCLES),0,0,-(Bits)decode.cycles); + gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles); +} + +static void dyn_save_critical_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)); + 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,decode.big_op,DREG(EIP),decode.code-decode.code_start); +} + +static INLINE void dyn_set_eip_last(void) { + gen_protectflags(); + gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start); +} + static void dyn_push(DynReg * dynreg) { - gen_storeflags(); + gen_protectflags(); if (decode.big_op) { gen_dop_word_imm(DOP_SUB,true,DREG(ESP),4); } else { @@ -93,11 +160,10 @@ static void dyn_push(DynReg * dynreg) { gen_call_function((void *)&mem_writew,"%Drd%Dd",DREG(STACK),dynreg); } gen_releasereg(DREG(STACK)); - gen_restoreflags(); } static void dyn_pop(DynReg * dynreg) { - gen_storeflags(); + gen_protectflags(); gen_dop_word(DOP_MOV,true,DREG(STACK),DREG(ESP)); gen_dop_word(DOP_AND,true,DREG(STACK),DREG(SMASK)); gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS)); @@ -114,7 +180,6 @@ static void dyn_pop(DynReg * dynreg) { } } gen_releasereg(DREG(STACK)); - gen_restoreflags(); } static void INLINE dyn_get_modrm(void) { @@ -233,15 +298,38 @@ static void dyn_fill_ea(bool addseg=true) { #include "helpers.h" #include "string.h" +static void DynRunException(void) { + CPU_Exception(cpu.exception.which,cpu.exception.error); +} + +static void dyn_check_bool_exception(DynReg * check) { + Bit8u * branch;DynState state; + gen_dop_byte(DOP_OR,check,0,check,0); + branch=gen_create_branch(BR_Z); + dyn_savestate(&state); + dyn_flags_gen_to_host(); + dyn_reduce_cycles(); + dyn_set_eip_last(); + dyn_save_critical_regs(); + gen_call_function((void *)&DynRunException,""); + dyn_flags_host_to_gen(); + gen_return(BR_Normal); + dyn_loadstate(&state); + gen_fill_branch(branch); +} + + 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(); dyn_read_byte(DREG(EA),DREG(TMPB),false); + if (op<=DOP_TEST) gen_needflags(); gen_dop_byte(op,DREG(TMPB),0,rm_reg,decode.modrm.reg&4); dyn_write_byte(DREG(EA),DREG(TMPB),false); gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); } else { + if (op<=DOP_TEST) gen_needflags(); gen_dop_byte(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,decode.modrm.reg&4); } } @@ -252,9 +340,11 @@ static void dyn_dop_gbeb(DualOps op) { if (decode.modrm.mod<3) { dyn_fill_ea(); dyn_read_byte(DREG(EA),DREG(TMPB),false); + if (op<=DOP_TEST) gen_needflags(); gen_dop_byte(op,rm_reg,decode.modrm.reg&4,DREG(TMPB),0); gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); } else { + if (op<=DOP_TEST) gen_needflags(); gen_dop_byte(op,rm_reg,decode.modrm.reg&4,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); } } @@ -302,10 +392,12 @@ static void dyn_dop_evgv(DualOps op) { if (decode.modrm.mod<3) { dyn_fill_ea(); dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + if (op<=DOP_TEST) gen_needflags(); gen_dop_word(op,decode.big_op,DREG(TMPW),rm_reg); dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW)); } else { + if (op<=DOP_TEST) gen_needflags(); gen_dop_word(op,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg); } } @@ -319,6 +411,7 @@ static void dyn_imul_gvev(Bitu immsize) { } 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; @@ -334,9 +427,11 @@ static void dyn_dop_gvev(DualOps op) { if (decode.modrm.mod<3) { dyn_fill_ea(); dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + if (op<=DOP_TEST) gen_needflags(); gen_dop_word(op,decode.big_op,rm_reg,DREG(TMPW)); gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW)); } else { + if (op<=DOP_TEST) gen_needflags(); gen_dop_word(op,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm]); } } @@ -413,6 +508,7 @@ static void dyn_dshift_ev_gv(bool left,bool immediate) { 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) { @@ -428,10 +524,12 @@ static void dyn_grp1_eb_ib(void) { if (decode.modrm.mod<3) { dyn_fill_ea(); dyn_read_byte(DREG(EA),DREG(TMPB),false); + gen_needflags(); gen_dop_byte_imm(grp1_table[decode.modrm.reg],DREG(TMPB),0,decode_fetchb()); if (grp1_table[decode.modrm.reg]!=DOP_CMP) dyn_write_byte(DREG(EA),DREG(TMPB),false); gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); } else { + gen_needflags(); gen_dop_byte_imm(grp1_table[decode.modrm.reg],&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb()); } } @@ -442,79 +540,76 @@ static void dyn_grp1_ev_ivx(bool withbyte) { dyn_fill_ea(); dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw()); + gen_needflags(); gen_dop_word_imm(grp1_table[decode.modrm.reg],decode.big_op,DREG(TMPW),imm); dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW)); } else { Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw()); + gen_needflags(); gen_dop_word_imm(grp1_table[decode.modrm.reg],decode.big_op,&DynRegs[decode.modrm.rm],imm); } } - -static ShiftOps grp2_table[8]={ - SHIFT_ROL,SHIFT_ROR,SHIFT_RCL,SHIFT_RCR, - SHIFT_SHL,SHIFT_SHR,SHIFT_SHL,SHIFT_SAR -}; - enum grp2_types { grp2_1,grp2_imm,grp2_cl, }; static void dyn_grp2_eb(grp2_types type) { - dyn_get_modrm(); + dyn_get_modrm();DynReg * src;Bit8u src_i; if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_read_byte(DREG(EA),DREG(TMPB),false); - DynReg * shift; - switch (type) { - case grp2_cl:shift=DREG(ECX);break; - case grp2_1:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,1);break; - case grp2_imm:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,decode_fetchb());break; - } - gen_shift_byte(grp2_table[decode.modrm.reg],shift,DREG(TMPB),0); - dyn_write_byte(DREG(EA),DREG(TMPB),false); - gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB));gen_releasereg(DREG(SHIFT)); + dyn_fill_ea();dyn_read_byte(DREG(EA),DREG(TMPB),false); + src=DREG(TMPB); + src_i=0; } else { - DynReg * shift; - switch (type) { - case grp2_cl:shift=DREG(ECX);break; - case grp2_1:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,1);break; - case grp2_imm:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,decode_fetchb());break; - } - gen_shift_byte(grp2_table[decode.modrm.reg],shift,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); - gen_releasereg(DREG(SHIFT)); + src=&DynRegs[decode.modrm.rm&3]; + src_i=decode.modrm.rm&4; + } + gen_needflags(); + switch (type) { + case grp2_1: + gen_shift_byte_imm(decode.modrm.reg,src,src_i,1); + break; + case grp2_imm: + gen_shift_byte_imm(decode.modrm.reg,src,src_i,decode_fetchb()); + break; + case grp2_cl: + gen_shift_byte_cl (decode.modrm.reg,src,src_i,DREG(ECX)); + break; + } + if (decode.modrm.mod<3) { + dyn_write_byte(DREG(EA),src,false); + gen_releasereg(DREG(EA));gen_releasereg(src); } } static void dyn_grp2_ev(grp2_types type) { - dyn_get_modrm(); + dyn_get_modrm();DynReg * src; if (decode.modrm.mod<3) { - dyn_fill_ea(); - dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); - DynReg * shift; - switch (type) { - case grp2_cl:shift=DREG(ECX);break; - case grp2_1:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,1);break; - case grp2_imm:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,decode_fetchb());break; - } - gen_shift_word(grp2_table[decode.modrm.reg],shift,decode.big_op,DREG(TMPW)); - dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); - gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW));gen_releasereg(DREG(SHIFT)); + dyn_fill_ea();dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + src=DREG(TMPW); } else { - DynReg * shift; - switch (type) { - case grp2_cl:shift=DREG(ECX);break; - case grp2_1:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,1);break; - case grp2_imm:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,decode_fetchb());break; - } - gen_shift_word(grp2_table[decode.modrm.reg],shift,decode.big_op,&DynRegs[decode.modrm.rm]); - gen_releasereg(DREG(SHIFT)); + src=&DynRegs[decode.modrm.rm]; + } + gen_needflags(); + switch (type) { + case grp2_1: + gen_shift_word_imm(decode.modrm.reg,decode.big_op,src,1); + break; + case grp2_imm: + gen_shift_word_imm(decode.modrm.reg,decode.big_op,src,decode_fetchb()); + break; + case grp2_cl: + gen_shift_word_cl (decode.modrm.reg,decode.big_op,src,DREG(ECX)); + break; + } + if (decode.modrm.mod<3) { + dyn_write_word(DREG(EA),src,decode.big_op); + gen_releasereg(DREG(EA));gen_releasereg(src); } } static void dyn_grp3_eb(void) { - DynState state;Bit8u * branch; dyn_get_modrm();DynReg * src;Bit8u src_i; if (decode.modrm.mod<3) { dyn_fill_ea(); @@ -526,41 +621,29 @@ static void dyn_grp3_eb(void) { } switch (decode.modrm.reg) { case 0x0: /* test eb,ib */ - gen_dop_byte_imm(DOP_TEST,src,src_i,decode_fetchb()); + gen_needflags();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); + gen_needflags();gen_sop_byte(SOP_NOT,src,src_i); break; case 0x3: /* NEG Eb */ - gen_sop_byte(SOP_NEG,src,src_i); + gen_needflags();gen_sop_byte(SOP_NEG,src,src_i); break; case 0x4: /* mul Eb */ - gen_mul_byte(false,DREG(EAX),src,src_i); + gen_needflags();gen_mul_byte(false,DREG(EAX),src,src_i); goto skipsave; case 0x5: /* imul Eb */ - gen_mul_byte(true,DREG(EAX),src,src_i); + 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_storeflags();gen_releasereg(DREG(EAX)); + gen_releasereg(DREG(EAX)); gen_call_function((decode.modrm.reg==6) ? (void *)&dyn_helper_divb : (void *)&dyn_helper_idivb, "%Rd%Drl",DREG(TMPB),DREG(TMPB)); - gen_dop_word(DOP_OR,true,DREG(TMPB),DREG(TMPB)); - branch=gen_create_branch(BR_Z); - dyn_savestate(&state); - dyn_reduce_cycles(); - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.op_start-decode.code_start); - dyn_save_flags(true); - dyn_releaseregs(); - gen_call_function((void *)&CPU_Exception,"%Id%Id",0,0); - dyn_load_flags(); - gen_return(BR_Normal); - dyn_loadstate(&state); - gen_fill_branch(branch); - gen_restoreflags(); + dyn_check_bool_exception(DREG(TMPB)); goto skipsave; } /* Save the result if memory op */ @@ -570,7 +653,6 @@ skipsave: } static void dyn_grp3_ev(void) { - DynState state;Bit8u * branch; dyn_get_modrm();DynReg * src; if (decode.modrm.mod<3) { dyn_fill_ea();src=DREG(TMPW); @@ -578,43 +660,31 @@ static void dyn_grp3_ev(void) { } else src=&DynRegs[decode.modrm.rm]; switch (decode.modrm.reg) { case 0x0: /* test ev,iv */ - gen_dop_word_imm(DOP_TEST,decode.big_op,src,decode.big_op ? decode_fetchd() : decode_fetchw()); + gen_needflags();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); + gen_needflags();gen_sop_word(SOP_NOT,decode.big_op,src); break; case 0x3: /* NEG Eb */ - gen_sop_word(SOP_NEG,decode.big_op,src); + gen_needflags();gen_sop_word(SOP_NEG,decode.big_op,src); break; case 0x4: /* mul Eb */ - gen_mul_word(false,DREG(EAX),DREG(EDX),decode.big_op,src); + gen_needflags();gen_mul_word(false,DREG(EAX),DREG(EDX),decode.big_op,src); goto skipsave; case 0x5: /* imul Eb */ - gen_mul_word(true,DREG(EAX),DREG(EDX),decode.big_op,src); + 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_storeflags();gen_releasereg(DREG(EAX));gen_releasereg(DREG(EDX)); + 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%Drd",DREG(TMPW),DREG(TMPW)); - gen_dop_word(DOP_OR,true,DREG(TMPW),DREG(TMPW)); - branch=gen_create_branch(BR_Z); - dyn_savestate(&state); - dyn_reduce_cycles(); - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.op_start-decode.code_start); - dyn_save_flags(true); - dyn_releaseregs(); - gen_call_function((void *)&CPU_Exception,"%Id%Id",0,0); - dyn_load_flags(); - gen_return(BR_Normal); - dyn_loadstate(&state); - gen_fill_branch(branch); - gen_restoreflags(); + gen_call_function(func,"%Rd%Drd",DREG(TMPB),DREG(TMPW)); + dyn_check_bool_exception(DREG(TMPB)); goto skipsave; } /* Save the result if memory op */ @@ -636,29 +706,16 @@ static void dyn_mov_ev_seg(void) { gen_releasereg(DREG(TMPW)); } -static void dyn_load_seg(SegNames seg,DynReg * src,bool withpop) { +static void dyn_synch_eip(void) { + gen_protectflags(); + gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.code-decode.code_start); +} + +static void dyn_load_seg(SegNames seg,DynReg * src) { if (cpu.pmode) { - Bit8u * branch;DynState state; - gen_storeflags(); gen_call_function((void *)&CPU_SetSegGeneral,"%Rd%Id%Drw",DREG(TMPB),seg,src); - gen_dop_byte(DOP_OR,DREG(TMPB),0,DREG(TMPB),0); - branch=gen_create_branch(BR_Z); - dyn_savestate(&state); - dyn_reduce_cycles(); - if (withpop) gen_dop_word_imm(DOP_SUB,true,DREG(ESP),decode.big_op ? 4 : 2); - gen_dop_word_imm(DOP_ADD,true,DREG(EIP),decode.op_start-decode.code_start); - dyn_save_flags(true); - dyn_releaseregs(); - gen_call_function((void *)&CPU_StartException,""); - dyn_load_flags(); - gen_return(BR_Normal); - dyn_loadstate(&state); - gen_fill_branch(branch); - gen_restoreflags(); - } else { - //TODO Maybe just calculate the base directly if in realmode - gen_call_function((void *)&CPU_SetSegGeneral,"%Id%Drw",seg,src); - } + dyn_check_bool_exception(DREG(TMPB)); + } else gen_call_function((void *)CPU_SetSegGeneral,"%Id%Drw",seg,src); gen_releasereg(&DynRegs[G_ES+seg]); if (seg==ss) gen_releasereg(DREG(SMASK)); } @@ -669,7 +726,7 @@ static void dyn_load_seg_off_ea(SegNames seg) { dyn_fill_ea(); gen_lea(DREG(TMPW),DREG(EA),0,0,decode.big_op ? 4:2); dyn_read_word(DREG(TMPW),DREG(TMPW),false); - dyn_load_seg(seg,DREG(TMPW),false);gen_releasereg(DREG(TMPW)); + dyn_load_seg(seg,DREG(TMPW));gen_releasereg(DREG(TMPW)); dyn_read_word(DREG(EA),&DynRegs[decode.modrm.reg],decode.big_op); gen_releasereg(DREG(EA)); } else { @@ -684,10 +741,10 @@ static void dyn_mov_seg_ev(void) { if (decode.modrm.mod<3) { dyn_fill_ea(); dyn_read_word(DREG(EA),DREG(EA),false); - dyn_load_seg(seg,DREG(EA),false); + dyn_load_seg(seg,DREG(EA)); gen_releasereg(DREG(EA)); } else { - dyn_load_seg(seg,&DynRegs[decode.modrm.rm],false); + dyn_load_seg(seg,&DynRegs[decode.modrm.rm]); } } @@ -698,15 +755,21 @@ static void dyn_push_seg(SegNames seg) { } static void dyn_pop_seg(SegNames seg) { - gen_storeflags(); - dyn_pop(DREG(TMPW)); - dyn_load_seg(seg,DREG(TMPW),true); - gen_releasereg(DREG(TMPW)); - gen_restoreflags(); + if (!cpu.pmode) { + dyn_pop(DREG(TMPW)); + dyn_load_seg(seg,DREG(TMPW)); + gen_releasereg(DREG(TMPW)); + } else { + 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(&DynRegs[G_ES+seg]); + gen_releasereg(DREG(ESP)); + if (seg==ss) gen_releasereg(DREG(SMASK)); + } } static void dyn_pop_ev(void) { - gen_storeflags(); dyn_pop(DREG(TMPW)); dyn_get_modrm(); if (decode.modrm.mod<3) { @@ -717,11 +780,18 @@ static void dyn_pop_ev(void) { gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW)); } gen_releasereg(DREG(TMPW)); - gen_restoreflags(); +} + +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_storeflags(); + gen_protectflags(); gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(SMASK)); gen_sop_word(SOP_NOT,true,DREG(TMPW)); gen_dop_word(DOP_AND,true,DREG(ESP),DREG(TMPW)); @@ -730,7 +800,6 @@ static void dyn_leave(void) { gen_dop_word(DOP_OR,true,DREG(ESP),DREG(TMPW)); dyn_pop(DREG(EBP)); gen_releasereg(DREG(TMPW)); - gen_restoreflags(); } static void dyn_segprefix(SegNames seg) { @@ -738,129 +807,133 @@ static void dyn_segprefix(SegNames seg) { decode.segprefix=&DynRegs[G_ES+seg]; } -static void dyn_closeblock(BlockType type) { +static void dyn_closeblock(void) { //Shouldn't create empty block normally but let's do it like this - if (decode.code>decode.code_start) decode.code--; - Bitu start_page=decode.code_start >> 12; - Bitu end_page=decode.code>>12; - decode.block->page.start=(Bit16s)decode.code_start & 4095; - decode.block->page.end=(Bit16s)((end_page-start_page)*4096+(decode.code&4095)); - cache_closeblock(type); + gen_protectflags(); + cache_closeblock(); } static void dyn_normal_exit(BlockReturn code) { - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + gen_protectflags(); dyn_reduce_cycles(); - dyn_releaseregs(); + dyn_set_eip_last(); + dyn_save_critical_regs(); gen_return(code); - dyn_closeblock(BT_Normal); + dyn_closeblock(); } -static void dyn_exit_link(bool dword,Bits eip_change) { - gen_lea(DREG(EIP),DREG(EIP),0,0,(decode.code-decode.code_start)+eip_change); - if (!dword) gen_extend_word(false,DREG(EIP),DREG(EIP)); +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_releaseregs(); -// gen_return(BR_Normal); - gen_jmp_ptr(&decode.block->link.to[0],offsetof(CacheBlock,cache.start)); - dyn_closeblock(BT_SingleLink); + 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) { - dyn_reduce_cycles(); - dyn_releaseregs(); Bitu eip_base=decode.code-decode.code_start; + dyn_reduce_cycles(); + dyn_save_critical_regs(); + gen_needflags(); + gen_protectflags(); Bit8u * data=gen_create_branch(btype); /* Branch not taken */ - gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base); + gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),eip_base); gen_releasereg(DREG(EIP)); -// gen_return(BR_Normal); - gen_jmp_ptr(&decode.block->link.to[0],offsetof(CacheBlock,cache.start)); + gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); gen_fill_branch(data); /* Branch taken */ - gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base+eip_add); + gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),eip_base+eip_add); gen_releasereg(DREG(EIP)); -// gen_return(BR_Normal); - gen_jmp_ptr(&decode.block->link.to[1],offsetof(CacheBlock,cache.start)); - dyn_closeblock(BT_DualLink); + gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlock,cache.start)); + dyn_closeblock(); } enum LoopTypes { - LOOP_NONE,LOOP_NE,LOOP_E, + 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; - gen_storeflags(); - dyn_reduce_cycles(); - Bit8u * branch1; - Bit8u * branch2=0; - gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); - dyn_releaseregs(); - branch1=gen_create_branch(BR_Z); - gen_restoreflags(true); + Bit8u * branch1=0;Bit8u * branch2=0; + dyn_save_critical_regs(); switch (type) { - case LOOP_NONE: - break; case LOOP_E: - branch2=gen_create_branch(BR_NZ); + 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.to[0],offsetof(CacheBlock,cache.start)); - gen_fill_branch(branch1); - if (branch2) gen_fill_branch(branch2); + 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_restoreflags(); + gen_fill_branch(branch2); gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base); gen_releasereg(DREG(EIP)); - gen_jmp_ptr(&decode.block->link.to[1],offsetof(CacheBlock,cache.start)); - dyn_closeblock(BT_DualLink); + 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(); -//TODO maybe AND eip 0xffff, but shouldn't be needed - gen_storeflags(); dyn_pop(DREG(EIP)); if (bytes) gen_dop_word_imm(DOP_ADD,true,DREG(ESP),bytes); - dyn_releaseregs(); - gen_restoreflags(); + dyn_save_critical_regs(); gen_return(BR_Normal); - dyn_closeblock(BT_Normal); -} - -static void dyn_ret_far(Bitu bytes) { - dyn_reduce_cycles(); -//TODO maybe AND eip 0xffff, but shouldn't be needed - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); - dyn_save_flags(); - dyn_releaseregs(); - gen_call_function((void*)&CPU_RET,"%Id%Id%Id",decode.big_op,bytes,decode.code-decode.op_start); - dyn_load_flags(); - dyn_releaseregs();; - gen_return(BR_Normal); - dyn_closeblock(BT_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(); - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_set_eip_end(); dyn_push(DREG(EIP)); - gen_lea(DREG(EIP),DREG(EIP),0,0,imm); - if (!decode.big_op) gen_extend_word(false,DREG(EIP),DREG(EIP)); + gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),imm); dyn_reduce_cycles(); - dyn_releaseregs(); + 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)); + dyn_flags_host_to_gen(); gen_return(BR_Normal); -// gen_jmp_ptr(&decode.block->link.to[0],offsetof(CacheBlock,cache.start)); - dyn_closeblock(BT_SingleLink); + dyn_closeblock(); } static void dyn_call_far_imm(void) { @@ -868,61 +941,68 @@ static void dyn_call_far_imm(void) { off=decode.big_op ? decode_fetchd() : decode_fetchw(); sel=decode_fetchw(); dyn_reduce_cycles(); - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); - dyn_save_flags(); - dyn_releaseregs(); - gen_call_function((void*)&CPU_CALL,"%Id%Id%Id%Id",decode.big_op,sel,off,decode.code-decode.op_start); - dyn_load_flags(); - dyn_releaseregs(); + 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)); + dyn_flags_host_to_gen(); gen_return(BR_Normal); - dyn_closeblock(BT_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(); - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); - dyn_save_flags(); - dyn_releaseregs(); - gen_call_function((void*)&CPU_JMP,"%Id%Id%Id%Id",decode.big_op,sel,off,decode.code-decode.op_start); - dyn_load_flags(); - dyn_releaseregs(); + 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)); + dyn_flags_host_to_gen(); gen_return(BR_Normal); - dyn_closeblock(BT_Normal); + dyn_closeblock(); } static void dyn_iret(void) { - dyn_save_flags(); + gen_protectflags(); + dyn_flags_gen_to_host(); dyn_reduce_cycles(); - gen_dop_word_imm(DOP_ADD,true,DREG(EIP),decode.code-decode.code_start); - dyn_releaseregs(); - gen_call_function((void*)&CPU_IRET,"%Id%Id",decode.big_op,decode.code-decode.op_start); - dyn_load_flags(); - dyn_releaseregs(); + dyn_set_eip_last_end(DREG(TMPW)); + dyn_save_critical_regs(); + gen_call_function((void*)&CPU_IRET,"%Id%Drd",decode.big_op,DREG(TMPW)); + dyn_flags_host_to_gen(); gen_return(BR_Normal); - dyn_closeblock(BT_CheckFlags); + dyn_closeblock(); } static void dyn_interrupt(Bitu num) { - dyn_save_flags(); + gen_protectflags(); + dyn_flags_gen_to_host(); dyn_reduce_cycles(); - gen_dop_word_imm(DOP_ADD,true,DREG(EIP),decode.code-decode.code_start); - dyn_releaseregs(); - gen_call_function((void*)&CPU_Interrupt,"%Id%Id%Id",num,CPU_INT_SOFTWARE,decode.code-decode.op_start); - dyn_load_flags(); - dyn_releaseregs(); + 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)); + dyn_flags_host_to_gen(); gen_return(BR_Normal); - dyn_closeblock(BT_Normal); + dyn_closeblock(); } -static CacheBlock * CreateCacheBlock(PhysPt start,bool big,Bitu max_opcodes) { +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.block=cache_openblock(); + decode.page.code=codepage; + decode.page.index=start&4095; + decode.page.wmap=codepage->write_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=G_EAX;i--) { dyn_pop((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW)); } - gen_restoreflags();gen_releasereg(DREG(TMPW)); + 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=!big;goto restart_prefix; + case 0x66:decode.big_op=!cpu.code.big;;goto restart_prefix; //Address size - case 0x67:decode.big_addr=!big;goto restart_prefix; + 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)); @@ -1117,7 +1192,7 @@ restart_prefix: 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()); - return decode.block; + goto finish_block; /* Group 1 */ case 0x80:dyn_grp1_eb_ib();break; case 0x81:dyn_grp1_ev_ivx(false);break; @@ -1155,10 +1230,6 @@ restart_prefix: break; /* CBW/CWDE */ case 0x98: - /* - if (decode.big_op) gen_extend_word(true,DREG(EAX),DREG(EAX)); - else gen_extend_byte(true,false,DREG(EAX),DREG(EAX),0); - */ gen_cbw(decode.big_op,DREG(EAX)); break; /* CWD/CDQ */ @@ -1166,8 +1237,24 @@ restart_prefix: gen_cwd(decode.big_op,DREG(EAX),DREG(EDX)); break; /* CALL FAR Ip */ - case 0x9a:dyn_call_far_imm();return decode.block; - /* MOV AL,direct addresses */ + 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); + if (cpu.pmode) 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); + if (cpu.pmode) dyn_check_bool_exception(DREG(TMPB)); + dyn_flags_host_to_gen(); + gen_releasereg(DREG(TMPB)); + 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()); @@ -1199,8 +1286,8 @@ restart_prefix: 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_dop_byte_imm(DOP_TEST,DREG(EAX),0,decode_fetchb());break; - case 0xa9:gen_dop_word_imm(DOP_TEST,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());break; + case 0xa8:gen_needflags();gen_dop_byte_imm(DOP_TEST,DREG(EAX),0,decode_fetchb());break; + case 0xa9:gen_needflags();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; @@ -1219,32 +1306,37 @@ restart_prefix: 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());return decode.block; - case 0xc3:dyn_ret_near(0);return decode.block; + case 0xc2:dyn_ret_near(decode_fetchw());goto finish_block; + case 0xc3:dyn_ret_near(0);goto finish_block; //LES/LDS case 0xc4:dyn_load_seg_off_ea(es);break; case 0xc5:dyn_load_seg_off_ea(ds);break; // MOV Eb/Ev,Ib/Iv case 0xc6:dyn_mov_ebib();break; case 0xc7:dyn_mov_eviv();break; - // LEAVE + //ENTER and LEAVE + case 0xc8:dyn_enter();break; case 0xc9:dyn_leave();break; //RET far Iw / Ret - case 0xca:dyn_ret_far(decode_fetchw());return decode.block; - case 0xcb:dyn_ret_far(0);return decode.block; + 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());return decode.block; +// case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block; /* IRET */ - case 0xcf:dyn_iret();return decode.block; + 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; + //Loop's - case 0xe2:dyn_loop(LOOP_NONE);return decode.block; + case 0xe2:dyn_loop(LOOP_NONE);goto finish_block; + case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block; //IN AL/AX,imm + case 0xe4:gen_call_function((void*)&IO_ReadB,"%Id%Rl",decode_fetchb(),DREG(EAX));break; case 0xe5: if (decode.big_op) { @@ -1264,14 +1356,15 @@ restart_prefix: break; case 0xe8: /* CALL Ivx */ dyn_call_near_imm(); - return decode.block; + goto finish_block; case 0xe9: /* Jmp Ivx */ - dyn_exit_link(decode.big_op,decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); - return decode.block; - /* CALL FAR Ip */ - case 0xea:dyn_jmp_far_imm();return decode.block; - /* Jmp Ibx */ - case 0xeb:dyn_exit_link(decode.big_op,(Bit8s)decode_fetchb());return decode.block; + 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:gen_call_function((void*)&IO_ReadB,"%Dw%Rl",DREG(EDX),DREG(EAX));break; case 0xed: @@ -1290,6 +1383,7 @@ restart_prefix: gen_call_function((void*)&IO_WriteW,"%Dw%Dw",DREG(EDX),DREG(EAX)); } break; + case 0xf2: //REPNE/NZ decode.rep=REP_NZ; goto restart_prefix; @@ -1300,22 +1394,31 @@ restart_prefix: 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_storeflags(); - gen_dop_word_imm(DOP_AND,true,DREG(FLAGS),~FLAG_IF); - gen_restoreflags(); + gen_call_function((void *)&CPU_CLI,"%Rd",DREG(TMPB)); + if (cpu.pmode) dyn_check_bool_exception(DREG(TMPB)); break; case 0xfb: //STI - gen_storeflags(); - gen_dop_word_imm(DOP_OR,true,DREG(FLAGS),FLAG_IF); - gen_restoreflags(); + gen_call_function((void *)&CPU_STI,"%Rd",DREG(TMPB)); + if (cpu.pmode) dyn_check_bool_exception(DREG(TMPB)); 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(); @@ -1324,24 +1427,27 @@ restart_prefix: case 0x1://DEC Eb if (decode.modrm.mod<3) { dyn_fill_ea();dyn_read_byte(DREG(EA),DREG(TMPB),false); + gen_needflags(); gen_sop_byte(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,DREG(TMPB),0); dyn_write_byte(DREG(EA),DREG(TMPB),false); gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); } else { + gen_needflags(); 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()); - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_set_eip_end(); dyn_reduce_cycles(); - dyn_releaseregs(); + dyn_save_critical_regs(); gen_return(BR_CallBack); - dyn_closeblock(BT_Normal); - return decode.block; + dyn_closeblock(); + goto finish_block; } break; + case 0xff: { dyn_get_modrm();DynReg * src; @@ -1353,6 +1459,7 @@ restart_prefix: switch (decode.modrm.reg) { case 0x0://INC Ev case 0x1://DEC Ev + gen_needflags(); gen_sop_word(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,decode.big_op,src); if (decode.modrm.mod<3){ dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); @@ -1369,16 +1476,17 @@ restart_prefix: goto core_close_block; case 0x3: /* CALL Ep */ case 0x5: /* JMP Ep */ - dyn_save_flags(); + gen_protectflags(); + dyn_flags_gen_to_host(); gen_lea(DREG(EA),DREG(EA),0,0,decode.big_op ? 4: 2); - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_set_eip_last_end(DREG(TMPB)); dyn_read_word(DREG(EA),DREG(EA),false); - for (Bitu i=0;ipage.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/helpers.h b/src/cpu/core_dyn_x86/helpers.h index 7986540..6fa75b3 100644 --- a/src/cpu/core_dyn_x86/helpers.h +++ b/src/cpu/core_dyn_x86/helpers.h @@ -1,57 +1,57 @@ -static Bitu dyn_helper_divb(Bit8u val) { - if (!val) return 1; +static bool dyn_helper_divb(Bit8u val) { + if (!val) return CPU_PrepareException(0,0); Bitu quo=reg_ax / val; reg_ah=(Bit8u)(reg_ax % val); reg_al=(Bit8u)quo; - if (quo>0xff) return 1; - return 0; + if (quo>0xff) return CPU_PrepareException(0,0); + return false; } -static Bitu dyn_helper_idivb(Bit8s val) { - if (!val) return 1; +static bool dyn_helper_idivb(Bit8s val) { + if (!val) return CPU_PrepareException(0,0); Bits quo=(Bit16s)reg_ax / val; reg_ah=(Bit8s)((Bit16s)reg_ax % val); reg_al=(Bit8s)quo; - if (quo!=(Bit8s)reg_al) return 1; - return 0; + if (quo!=(Bit8s)reg_al) return CPU_PrepareException(0,0); + return false; } -static Bitu dyn_helper_divw(Bit16u val) { - if (!val) return 1; +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; reg_dx=(Bit16u)(num % val); reg_ax=(Bit16u)quo; - if (quo!=reg_ax) return 1; - return 0; + if (quo!=reg_ax) return CPU_PrepareException(0,0); + return false; } -static Bitu dyn_helper_idivw(Bit16s val) { - if (!val) return 1; +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; reg_dx=(Bit16s)(num % val); reg_ax=(Bit16s)quo; - if (quo!=(Bit16s)reg_ax) return 1; - return 0; + if (quo!=(Bit16s)reg_ax) return CPU_PrepareException(0,0); + return false; } -static Bitu dyn_helper_divd(Bit32u val) { - if (!val) return 1; +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; reg_edx=(Bit32u)(num % val); reg_eax=(Bit32u)quo; - if (quo!=(Bit64u)reg_eax) return 1; - return 0; + if (quo!=(Bit64u)reg_eax) return CPU_PrepareException(0,0); + return false; } -static Bitu dyn_helper_idivd(Bit32s val) { - if (!val) return 1; +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; reg_edx=(Bit32s)(num % val); reg_eax=(Bit32s)(quo); - if (quo!=(Bit64s)((Bit32s)reg_eax)) return 1; - return 0; + if (quo!=(Bit64s)((Bit32s)reg_eax)) return CPU_PrepareException(0,0); + return false; } diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h index ad1e4d7..bc15b74 100644 --- a/src/cpu/core_dyn_x86/risc_x86.h +++ b/src/cpu/core_dyn_x86/risc_x86.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -32,8 +32,8 @@ static void gen_init(void); #define X86_REG_MASK(_REG_) (1 << X86_REG_ ## _REG_) static struct { + bool flagsactive; Bitu last_used; - Bitu stored_flags; GenReg * regs[X86_REGS]; } x86gen; @@ -98,13 +98,13 @@ static BlockReturn gen_runcode(Bit8u * code) { push edi mov ebx,[reg_flags] and ebx,FMASK_TEST + push offset(return_address) push ebx - popfd - call eax + jmp eax /* Restore the flags */ - pushfd +return_address: + /* return here with flags in ecx */ and dword ptr [reg_flags],~FMASK_TEST - pop ecx and ecx,FMASK_TEST or [reg_flags],ecx pop edi @@ -114,23 +114,19 @@ static BlockReturn gen_runcode(Bit8u * code) { mov [retval],eax } #else + register Bit32u tempflags=reg_flags & FMASK_TEST; __asm__ volatile ( - "movl %1,%%esi \n" - "andl %2,%%esi \n" - "pushl %%ebp \n" - "pushl %%esi \n" - "popfl \n" - "calll *%4 \n" - "popl %%ebp \n" - "pushfl \n" - "andl %3,(%1) \n" - "popl %%esi \n" - "andl %2,%%esi \n" - "orl %%esi,(%1) \n" - :"=a" (retval) - :"m" (reg_flags), "n" (FMASK_TEST),"n" (~FMASK_TEST),"r" (code) - :"%ecx","%edx","%ebx","%edi","%esi","cc","memory" + "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; } @@ -232,28 +228,23 @@ static void gen_synchreg(DynReg * dnew,DynReg * dsynch) { } } -static void gen_storeflags(void) { - if (!x86gen.stored_flags) { - cache_addb(0x9c); //PUSHFD +static void gen_needflags(void) { + if (!x86gen.flagsactive) { + x86gen.flagsactive=true; + cache_addb(0x9d); //POPFD } - x86gen.stored_flags++; } -static void gen_restoreflags(bool noreduce=false) { - if (noreduce) { - cache_addb(0x9d); - return; +static void gen_protectflags(void) { + if (x86gen.flagsactive) { + x86gen.flagsactive=false; + cache_addb(0x9c); //PUSHFD } - if (x86gen.stored_flags) { - x86gen.stored_flags--; - if (!x86gen.stored_flags) - cache_addb(0x9d); //POPFD - } else IllegalOption(); } static void gen_reinit(void) { x86gen.last_used=0; - x86gen.stored_flags=0; + x86gen.flagsactive=false; for (Bitu i=0;idynreg=0; } @@ -483,55 +474,32 @@ static void gen_sop_word(SingleOps op,bool dword,DynReg * dr1) { dr1->flags|=DYNFLG_CHANGED; } -static void gen_shift_byte(ShiftOps op,DynReg * drecx,DynReg * dr1,Bit8u di1) { +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); - switch (op) { - case SHIFT_ROL:cache_addw(0xc0d2+((gr1->index+di1)<<8));break; - case SHIFT_ROR:cache_addw(0xc8d2+((gr1->index+di1)<<8));break; - case SHIFT_RCL:cache_addw(0xd0d2+((gr1->index+di1)<<8));break; - case SHIFT_RCR:cache_addw(0xd8d2+((gr1->index+di1)<<8));break; - case SHIFT_SHL:cache_addw(0xe0d2+((gr1->index+di1)<<8));break; - case SHIFT_SHR:cache_addw(0xe8d2+((gr1->index+di1)<<8));break; - case SHIFT_SAR:cache_addw(0xf8d2+((gr1->index+di1)<<8));break; - default: - IllegalOption(); - } + cache_addw(0xc0d2+(((Bit16u)op) << 11)+ ((gr1->index+di1)<<8)); dr1->flags|=DYNFLG_CHANGED; } -static void gen_shift_word(ShiftOps op,DynReg * drecx,bool dword,DynReg * dr1) { - ForceDynReg(x86gen.regs[X86_REG_ECX],drecx); +static void gen_shift_byte_imm(Bitu op,DynReg * dr1,Bit8u di1,Bit8u imm) { GenReg * gr1=FindDynReg(dr1); - if (!dword) cache_addb(0x66); - switch (op) { - case SHIFT_ROL:cache_addw(0xc0d3+((gr1->index)<<8));break; - case SHIFT_ROR:cache_addw(0xc8d3+((gr1->index)<<8));break; - case SHIFT_RCL:cache_addw(0xd0d3+((gr1->index)<<8));break; - case SHIFT_RCR:cache_addw(0xd8d3+((gr1->index)<<8));break; - case SHIFT_SHL:cache_addw(0xe0d3+((gr1->index)<<8));break; - case SHIFT_SHR:cache_addw(0xe8d3+((gr1->index)<<8));break; - case SHIFT_SAR:cache_addw(0xf8d3+((gr1->index)<<8));break; - default: - IllegalOption(); - } + cache_addw(0xc0c0+(((Bit16u)op) << 11) + ((gr1->index+di1)<<8)); + cache_addb(imm); dr1->flags|=DYNFLG_CHANGED; } -static void gen_shift_word_imm(ShiftOps op,bool dword,DynReg * dr1,Bit8u imm) { +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); - switch (op) { - case SHIFT_ROL:cache_addw(0xc0c1+((gr1->index)<<8));break; - case SHIFT_ROR:cache_addw(0xc8c1+((gr1->index)<<8));break; - case SHIFT_RCL:cache_addw(0xd0c1+((gr1->index)<<8));break; - case SHIFT_RCR:cache_addw(0xd8c1+((gr1->index)<<8));break; - case SHIFT_SHL:cache_addw(0xe0c1+((gr1->index)<<8));break; - case SHIFT_SHR:cache_addw(0xe8c1+((gr1->index)<<8));break; - case SHIFT_SAR:cache_addw(0xf8c1+((gr1->index)<<8));break; - default: - IllegalOption(); - } + 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); + if (!dword) cache_addb(0x66); + cache_addw(0xc0c1+(((Bit16u)op) << 11) + ((gr1->index)<<8)); cache_addb(imm); dr1->flags|=DYNFLG_CHANGED; } @@ -604,7 +572,7 @@ static void gen_call_function(void * func,char * ops,...) { x86gen.regs[X86_REG_EAX]->Clear(); x86gen.regs[X86_REG_EAX]->notusable=true;; /* Save the flags */ - gen_storeflags(); + gen_protectflags(); /* Scan for the amount of params */ if (ops) { va_list params; @@ -704,7 +672,6 @@ static void gen_call_function(void * func,char * ops,...) { } dynreg->flags|=DYNFLG_CHANGED; } - gen_restoreflags(); /* Restore EAX registers to be used again */ x86gen.regs[X86_REG_EAX]->notusable=false; } @@ -717,6 +684,11 @@ static Bit8u * gen_create_branch(BranchTypes type) { } 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); } @@ -747,17 +719,20 @@ static void gen_jmp_ptr(void * ptr,Bits imm=0) { } } -static void gen_save_flags(DynReg * dynreg,bool stored) { +static void gen_save_flags(DynReg * dynreg) { + if (x86gen.flagsactive) IllegalOption(); GenReg * genreg=FindDynReg(dynreg); - if (!stored) cache_addb(0x9c); //Pushfd - cache_addb(0x58+genreg->index); //POP 32 REG + cache_addb(0x8b); //MOV REG,[esp] + cache_addw(0x2404+(genreg->index << 3)); dynreg->flags|=DYNFLG_CHANGED; } static void gen_load_flags(DynReg * dynreg) { + if (x86gen.flagsactive) IllegalOption(); + cache_addw(0xc483); //ADD ESP,4 + cache_addb(0x4); GenReg * genreg=FindDynReg(dynreg); cache_addb(0x50+genreg->index); //PUSH 32 - cache_addb(0x9d); //POPFD } static void gen_save_host_direct(void * data,Bits imm) { @@ -781,9 +756,11 @@ static void gen_load_host(void * data,DynReg * dr1,Bitu size) { } static void gen_return(BlockReturn retcode) { - cache_addb(0xb8); + gen_protectflags(); + cache_addb(0x59); //POP ECX, the flags + cache_addb(0xb8); //MOV EAX, retcode cache_addd(retcode); - cache_addb(0xc3); + cache_addb(0xc3); //RET } static void gen_init(void) { diff --git a/src/cpu/core_dyn_x86/string.h b/src/cpu/core_dyn_x86/string.h index 7a713d9..10abb19 100644 --- a/src/cpu/core_dyn_x86/string.h +++ b/src/cpu/core_dyn_x86/string.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -30,7 +30,7 @@ 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_storeflags(); + gen_protectflags(); if (decode.rep) { gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles); gen_releasereg(DREG(CYCLES)); @@ -149,9 +149,8 @@ static void dyn_string(STRING_OP op) { gen_releasereg(DREG(CYCLES)); dyn_savestate(&cycle_state); Bit8u * cycle_branch=gen_create_branch(BR_NLE); - gen_lea(DREG(EIP),DREG(EIP),0,0,decode.op_start-decode.code_start); - dyn_releaseregs(); - gen_restoreflags(true); + gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start); + dyn_save_critical_regs(); gen_return(BR_Cycles); gen_fill_branch(cycle_branch); dyn_loadstate(&cycle_state); @@ -161,5 +160,4 @@ static void dyn_string(STRING_OP op) { gen_fill_jump(rep_ecx_jmp); } gen_releasereg(DREG(TMPW)); - gen_restoreflags(); } diff --git a/src/cpu/core_full.cpp b/src/cpu/core_full.cpp index 9d7868c..d1ee282 100644 --- a/src/cpu/core_full.cpp +++ b/src/cpu/core_full.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -54,47 +54,28 @@ typedef PhysPt EAPoint; #include "core_full/optable.h" #include "instructions.h" -#define LEAVECORE \ - SaveIP(); \ - FillFlags(); - #define EXCEPTION(blah) \ { \ Bit8u new_num=blah; \ - IPPoint=inst.opcode_start; \ - LEAVECORE; \ CPU_Exception(new_num,0); \ - LoadIP(); \ - goto nextopcode; \ + continue; \ } Bits CPU_Core_Full_Run(void) { FullData inst; -restart_core: - if (!cpu.code.big) { - inst.start_prefix=0x0;; - inst.start_entry=0x0; - } else { - inst.start_prefix=PREFIX_ADDR; - inst.start_entry=0x200; - } - EAPoint IPPoint; - LoadIP(); - lflags.type=t_UNKNOWN; while (CPU_Cycles-->0) { #if C_DEBUG cycle_count++; #if C_HEAVY_DEBUG - SaveIP(); if (DEBUG_HeavyIsBreakpoint()) { - LEAVECORE; + FillFlags(); return debugCallback; }; #endif #endif - inst.opcode_start=IPPoint; - inst.entry=inst.start_entry; - inst.prefix=inst.start_prefix; + LoadIP(); + inst.entry=cpu.code.big*0x200; + inst.prefix=cpu.code.big; restartopcode: inst.entry=(inst.entry & 0xffffff00) | Fetchb(); inst.code=OpCodeTable[inst.entry]; @@ -102,9 +83,13 @@ restartopcode: #include "core_full/op.h" #include "core_full/save.h" nextopcode:; + SaveIP(); + continue; +illegalopcode: + LOG_MSG("Illegal opcode"); + CPU_Exception(0x6,0); } -exit_core: - LEAVECORE; + FillFlags(); return CBRET_NONE; } diff --git a/src/cpu/core_full/load.h b/src/cpu/core_full/load.h index 74009c6..3a63a3d 100644 --- a/src/cpu/core_full/load.h +++ b/src/cpu/core_full/load.h @@ -144,18 +144,12 @@ l_M_Ed: inst.op1.d=SegValue((SegNames)inst.rm_index); break; case M_Efw: - if (inst.rm>=0xC0) { - LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw "); - goto nextopcode; - } + 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) { - LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw "); - goto nextopcode; - } + if (inst.rm>=0xc0) goto illegalopcode; inst.op1.d=LoadMd(inst.rm_eaa); inst.op2.d=LoadMw(inst.rm_eaa+4); break; @@ -183,8 +177,6 @@ l_M_Ed: inst.op2.d=1; inst.code=Groups[inst.code.op][inst.rm_index]; goto l_MODRMswitch; - - /* Should continue with normal handler afterwards */ case 0: break; default: @@ -246,9 +238,6 @@ l_M_Ed: case L_REGd: inst.op1.d=reg_32(inst.code.extra); break; - case L_FLG: - inst.op1.d = FillFlags(); - break; case L_SEG: inst.op1.d=SegValue((SegNames)inst.code.extra); break; @@ -282,10 +271,10 @@ l_M_Ed: inst.repz=true; goto restartopcode; case L_PREOP: - inst.entry=inst.start_entry ^ 0x200; + inst.entry=(cpu.code.big ^1) * 0x200; goto restartopcode; case L_PREADD: - inst.prefix^=PREFIX_ADDR; + inst.prefix=(inst.prefix & ~1) | (cpu.code.big ^ 1); goto restartopcode; case L_VAL: inst.op1.d=inst.code.extra; @@ -295,41 +284,40 @@ l_M_Ed: inst.op1.d=4; break; case D_IRETw: - LEAVECORE; - CPU_IRET(false); + FillFlags(); + CPU_IRET(false,GetIP()); if (GETFLAG(IF) && PIC_IRQCheck) { return CBRET_NONE; } - goto restart_core; + continue; case D_IRETd: - LEAVECORE; - CPU_IRET(true); - if (GETFLAG(IF) && PIC_IRQCheck) { + FillFlags(); + CPU_IRET(true,GetIP()); + if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; - } - goto restart_core; + continue; case D_RETFwIw: { Bitu words=Fetchw(); - LEAVECORE; - CPU_RET(false,words); - goto restart_core; + FillFlags(); + CPU_RET(false,words,GetIP()); + continue; } case D_RETFw: - LEAVECORE; - CPU_RET(false,0); - goto restart_core; + FillFlags(); + CPU_RET(false,0,GetIP()); + continue; case D_RETFdIw: { Bitu words=Fetchw(); - LEAVECORE; - CPU_RET(true,words); - goto restart_core; + FillFlags(); + CPU_RET(true,words,GetIP()); + continue; } case D_RETFd: - LEAVECORE; - CPU_RET(true,0); - goto restart_core; + FillFlags(); + CPU_RET(true,0,GetIP()); + continue; /* Direct operations */ case L_STRING: #include "string.h" @@ -357,18 +345,10 @@ l_M_Ed: reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32(); goto nextopcode; case D_POPSEGw: - if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_16())) { - LEAVECORE; - reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=2; - CPU_StartException();goto restart_core; - } + if (CPU_PopSeg((SegNames)inst.code.extra,false)) RunException(); goto nextopcode; case D_POPSEGd: - if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_32())) { - LEAVECORE; - reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=4; - CPU_StartException();goto restart_core; - } + if (CPU_PopSeg((SegNames)inst.code.extra,true)) RunException(); goto nextopcode; case D_SETALC: reg_al = get_CF() ? 0xFF : 0; @@ -403,14 +383,10 @@ l_M_Ed: else reg_edx=0; goto nextopcode; case D_CLI: - SETFLAGBIT(IF,false); + if (CPU_CLI()) RunException(); goto nextopcode; case D_STI: - SETFLAGBIT(IF,true); - if (GETFLAG(IF) && PIC_IRQCheck) { - LEAVECORE; - return CBRET_NONE; - } + if (CPU_STI()) RunException(); goto nextopcode; case D_STC: FillFlags();SETFLAGBIT(CF,true); @@ -430,71 +406,40 @@ l_M_Ed: SETFLAGBIT(DF,true); cpu.direction=-1; goto nextopcode; + case D_PUSHF: + FillFlags(); + if (CPU_PUSHF(inst.code.extra)) RunException(); + goto nextopcode; + case D_POPF: + if (CPU_POPF(inst.code.extra)) RunException(); + lflags.type=t_UNKNOWN; + 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_ENTERw: { - Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; - Bitu frame_ptr=reg_esp-2; - if (cpu.stack.big) { - reg_esp-=2; - mem_writew(SegBase(ss)+reg_esp,reg_bp); - for (Bitu i=1;i #include "dosbox.h" #include "mem.h" @@ -30,43 +31,23 @@ #include "debug.h" #endif - -#define SegBase(c) SegPhys(c) #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 -#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 - extern Bitu cycle_count; #if C_FPU @@ -80,122 +61,129 @@ extern Bitu cycle_count; #define OPCODE_0F 0x100 #define OPCODE_SIZE 0x200 -#define PREFIX_SEG 0x1 -#define PREFIX_ADDR 0x2 -#define PREFIX_SEG_ADDR (PREFIX_SEG|PREFIX_ADDR) -#define PREFIX_REP 0x4 +#define PREFIX_ADDR 0x1 +#define PREFIX_REP 0x2 -#define TEST_PREFIX_SEG (core.prefixes & PREFIX_SEG) #define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR) #define TEST_PREFIX_REP (core.prefixes & PREFIX_REP) #define DO_PREFIX_SEG(_SEG) \ - core.prefixes|=PREFIX_SEG; \ - core.seg_prefix_base=SegBase(_SEG); \ - goto restart_prefix; + BaseDS=SegBase(_SEG); \ + BaseSS=SegBase(_SEG); \ + goto restart_opcode; -#define DO_PREFIX_ADDR() \ - core.prefixes^=PREFIX_ADDR; \ - goto restart_prefix; +#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_prefix; + goto restart_opcode; -typedef PhysPt (*GetEATable[256])(void); +typedef PhysPt (*GetEAHandler)(void); + +static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff}; static struct { Bitu opcode_index; - Bitu prefixes; - Bitu index_default; - Bitu prefix_default; - PhysPt op_start; - PhysPt ip_lookup; - PhysPt seg_prefix_base; + PhysPt cseip; + PhysPt base_ds,base_ss; bool rep_zero; - GetEATable * ea_table; + Bitu prefixes; + GetEAHandler * ea_table; struct { bool skip; } trap; } 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" -static GetEATable * EAPrefixTable[8] = { - &GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR, - &GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR, -}; -#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) - -#define EALookupTable (*(core.ea_table)) +#define EALookupTable (core.ea_table) Bits CPU_Core_Normal_Run(void) { -decode_start: - if (cpu.code.big) { - core.index_default=0x200; - core.prefix_default=PREFIX_ADDR; - } else { - core.index_default=0; - core.prefix_default=0; - } - LOADIP; - lflags.type=t_UNKNOWN; while (CPU_Cycles-->0) { - core.op_start=core.ip_lookup; - core.opcode_index=core.index_default; - core.prefixes=core.prefix_default; + 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); #if C_DEBUG - cycle_count++; #if C_HEAVY_DEBUG - SAVEIP; if (DEBUG_HeavyIsBreakpoint()) { - LEAVECORE; + FillFlags(); return debugCallback; }; #endif + cycle_count++; #endif -restart_prefix: - core.ea_table=EAPrefixTable[core.prefixes]; 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: - ADDIPFAST(-1); -#if C_DEBUG - LOG_MSG("Unhandled code %X",core.opcode_index+Fetchb()); -#else - E_Exit("Unhandled CPU opcode"); + 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_ERROR)("Illegal/Unhandled opcode %s",tempcode); + } #endif + CPU_Exception(6,0); + continue; } + SAVEIP; } - decode_end: - LEAVECORE; + FillFlags(); + return CBRET_NONE; +decode_end: + SAVEIP; + FillFlags(); return CBRET_NONE; } @@ -206,7 +194,7 @@ Bits CPU_Core_Normal_Trap_Run(void) { core.trap.skip=false; Bits ret=CPU_Core_Normal_Run(); - if (!core.trap.skip) CPU_SW_Interrupt(1,0); + if (!core.trap.skip) CPU_SW_Interrupt(1,reg_eip); CPU_Cycles = oldCycles-1; cpudecoder = &CPU_Core_Normal_Run; diff --git a/src/cpu/core_normal/helpers.h b/src/cpu/core_normal/helpers.h index b7acd35..9f18fb2 100644 --- a/src/cpu/core_normal/helpers.h +++ b/src/cpu/core_normal/helpers.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -141,17 +141,22 @@ } \ } -#define POPSEG(_SEG_,_VAL_,_ESP_CHANGE_) \ - if (CPU_SetSegGeneral(_SEG_,_VAL_)) { \ - LEAVECORE; \ - reg_eip-=(core.ip_lookup-core.op_start);reg_esp-=_ESP_CHANGE_; \ - CPU_StartException();goto decode_start; \ - } +#define CASE_W(_WHICH) \ + case (OPCODE_NONE+_WHICH): -#define LOADSEG(_SEG_,_SEG_VAL_) \ - if (CPU_SetSegGeneral(_SEG_,_SEG_VAL_)) { \ - LEAVECORE; \ - reg_eip-=(core.ip_lookup-core.op_start); \ - CPU_StartException();goto decode_start; \ - } \ +#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 index c350944..6bea18d 100644 --- a/src/cpu/core_normal/prefix_0f.h +++ b/src/cpu/core_normal/prefix_0f.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -45,7 +45,7 @@ } break; default: - LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which); + goto illegal_opcode; } } break; @@ -77,7 +77,7 @@ break; case 0x06: /* LMSW */ limit=LoadMw(eaa); - if (!CPU_LMSW(limit)) goto decode_end; + if (CPU_LMSW(limit)) RUNEXCEPTION(); break; } } else { @@ -88,11 +88,10 @@ *earw=limit; break; case 0x06: /* LMSW */ - if (!CPU_LMSW(*earw)) goto decode_end; + if (CPU_LMSW(*earw)) RUNEXCEPTION(); break; default: - LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which); - break; + goto illegal_opcode; } } } @@ -100,7 +99,7 @@ CASE_0F_W(0x02) /* LAR Gw,Ew */ { FillFlags(); - GetRMrw;Bitu ar; + GetRMrw;Bitu ar=*rmrw; if (rm >= 0xc0) { GetEArw;CPU_LAR(*earw,ar); } else { @@ -112,7 +111,7 @@ CASE_0F_W(0x03) /* LSL Gw,Ew */ { FillFlags(); - GetRMrw;Bitu limit; + GetRMrw;Bitu limit=*rmrw; if (rm >= 0xc0) { GetEArw;CPU_LSL(*earw,limit); } else { @@ -154,11 +153,8 @@ Bitu which=(rm >> 3) & 7; if (rm >= 0xc0 ) { GetEArd; - CPU_SET_CRX(which,*eard); - } else { - GetEAa; - LOG(LOG_CPU,LOG_ERROR)("MOV CR%,XXX with non-register",which); - } + if (CPU_SET_CRX(which,*eard)) RUNEXCEPTION(); + } else goto illegal_opcode; } break; CASE_0F_B(0x23) /* MOV DRx,Rd */ @@ -241,7 +237,7 @@ CASE_0F_W(0xa0) /* PUSH FS */ Push_16(SegValue(fs));break; CASE_0F_W(0xa1) /* POP FS */ - POPSEG(fs,Pop_16(),2); + if (CPU_PopSeg(fs,false)) RUNEXCEPTION(); break; CASE_0F_B(0xa2) /* CPUID */ CPU_CPUID();break; @@ -268,7 +264,8 @@ CASE_0F_W(0xa8) /* PUSH GS */ Push_16(SegValue(gs));break; CASE_0F_W(0xa9) /* POP GS */ - POPSEG(gs,Pop_16(),2);break; + if (CPU_PopSeg(gs,false)) RUNEXCEPTION(); + break; CASE_0F_W(0xab) /* BTS Ew,Gw */ { FillFlags();GetRMrw; @@ -297,7 +294,7 @@ CASE_0F_W(0xb2) /* LSS Ew */ { GetRMrw;GetEAa; - LOADSEG(ss,LoadMw(eaa+2)); + if (CPU_SetSegGeneral(ss,LoadMw(eaa+2))) RUNEXCEPTION(); *rmrw=LoadMw(eaa); break; } @@ -320,14 +317,14 @@ CASE_0F_W(0xb4) /* LFS Ew */ { GetRMrw;GetEAa; - LOADSEG(fs,LoadMw(eaa+2)); + if (CPU_SetSegGeneral(fs,LoadMw(eaa+2))) RUNEXCEPTION(); *rmrw=LoadMw(eaa); break; } CASE_0F_W(0xb5) /* LGS Ew */ { GetRMrw;GetEAa; - LOADSEG(gs,LoadMw(eaa+2)); + if (CPU_SetSegGeneral(gs,LoadMw(eaa+2))) RUNEXCEPTION(); *rmrw=LoadMw(eaa); break; } diff --git a/src/cpu/core_normal/prefix_66.h b/src/cpu/core_normal/prefix_66.h index df16c9a..07c55b5 100644 --- a/src/cpu/core_normal/prefix_66.h +++ b/src/cpu/core_normal/prefix_66.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -25,7 +25,8 @@ CASE_D(0x06) /* PUSH ES */ Push_32(SegValue(es));break; CASE_D(0x07) /* POP ES */ - POPSEG(es,Pop_32(),4);break; + if (CPU_PopSeg(es,true)) RUNEXCEPTION(); + break; CASE_D(0x09) /* OR Ed,Gd */ RMEdGd(ORD);break; CASE_D(0x0b) /* OR Gd,Ed */ @@ -43,7 +44,7 @@ CASE_D(0x16) /* PUSH SS */ Push_32(SegValue(ss));break; CASE_D(0x17) /* POP SS */ - POPSEG(ss,Pop_32(),4); + if (CPU_PopSeg(ss,true)) RUNEXCEPTION(); CPU_Cycles++; break; CASE_D(0x19) /* SBB Ed,Gd */ @@ -55,7 +56,8 @@ CASE_D(0x1e) /* PUSH DS */ Push_32(SegValue(ds));break; CASE_D(0x1f) /* POP DS */ - POPSEG(ds,Pop_32(),4);break; + if (CPU_PopSeg(ds,true)) RUNEXCEPTION(); + break; CASE_D(0x21) /* AND Ed,Gd */ RMEdGd(ANDD);break; CASE_D(0x23) /* AND Gd,Ed */ @@ -167,6 +169,7 @@ break; CASE_D(0x63) /* ARPL Ed,Rd */ { + if (((cpu.pmode) && (reg_flags & FLAG_VM)) || (!cpu.pmode)) goto illegal_opcode; FillFlags(); GetRMrw; if (rm >= 0xc0 ) { @@ -190,6 +193,12 @@ 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 */ @@ -332,12 +341,12 @@ CASE_D(0x8d) /* LEA Gd */ { //Little hack to always use segprefixed version - core.seg_prefix_base=0; GetRMrd; + BaseDS=BaseSS=0; if (TEST_PREFIX_ADDR) { - *rmrd=(Bit32u)(*GetEA_SEG_ADDR[rm])(); + *rmrd=(Bit32u)(*EATable[256+rm])(); } else { - *rmrd=(Bit32u)(*GetEA_SEG[rm])(); + *rmrd=(Bit32u)(*EATable[rm])(); } break; } @@ -378,21 +387,17 @@ CASE_D(0x9a) /* CALL FAR Ad */ { Bit32u newip=Fetchd();Bit16u newcs=Fetchw(); - LEAVECORE; - CPU_CALL(true,newcs,newip); - goto decode_start; + FillFlags(); + CPU_CALL(true,newcs,newip,GETIP); + continue; } CASE_D(0x9c) /* PUSHFD */ FillFlags(); - Push_32(reg_flags); + if (CPU_PUSHF(true)) RUNEXCEPTION(); break; CASE_D(0x9d) /* POPFD */ - if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) { - LEAVECORE;reg_eip-=core.ip_lookup-core.op_start; - CPU_Exception(13,0); - goto decode_start; - } - SETFLAGSd(Pop_32()) + if (CPU_POPF(true)) RUNEXCEPTION(); + lflags.type=t_UNKNOWN; #if CPU_TRAP_CHECK if (GETFLAG(TF)) { cpudecoder=CPU_Core_Normal_Trap_Run; @@ -402,7 +407,6 @@ #if CPU_PIC_CHECK if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; #endif - break; CASE_D(0xa1) /* MOV EAX,Od */ { @@ -447,25 +451,23 @@ CASE_D(0xc1) /* GRP2 Ed,Ib */ GRP2D(Fetchb());break; CASE_D(0xc2) /* RETN Iw */ - { - Bit16u addsp=Fetchw(); - SETIP(Pop_32());reg_esp+=addsp; - break; - } + reg_eip=Pop_32(); + reg_esp+=Fetchw(); + continue; CASE_D(0xc3) /* RETN */ - SETIP(Pop_32()); - break; + reg_eip=Pop_32(); + continue; CASE_D(0xc4) /* LES */ { GetRMrd;GetEAa; - LOADSEG(es,LoadMw(eaa+4)); + if (CPU_SetSegGeneral(es,LoadMw(eaa+4))) RUNEXCEPTION(); *rmrd=LoadMd(eaa); break; } CASE_D(0xc5) /* LDS */ { GetRMrd;GetEAa; - LOADSEG(ds,LoadMw(eaa+4)); + if (CPU_SetSegGeneral(ds,LoadMw(eaa+4))) RUNEXCEPTION(); *rmrd=LoadMd(eaa); break; } @@ -478,36 +480,11 @@ } CASE_D(0xc8) /* ENTER Iw,Ib */ { - Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; - Bitu frame_ptr=reg_esp-4; - if (cpu.stack.big) { - reg_esp-=4; - mem_writed(SegBase(ss)+reg_esp,reg_ebp); - for (Bitu i=1;i= 0xc0 ) {GetEArd;Push_32(GETIP);SETIP(*eard);} - else {GetEAa;Push_32(GETIP);SETIP(LoadMd(eaa));} - break; + if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;} + else {GetEAa;reg_eip=LoadMd(eaa);} + Push_32(GETIP); + continue; case 0x03: /* CALL FAR Ed */ { GetEAa; Bit32u newip=LoadMd(eaa); Bit16u newcs=LoadMw(eaa+4); - LEAVECORE; - CPU_CALL(true,newcs,newip); - goto decode_start; + FillFlags(); + CPU_CALL(true,newcs,newip,GETIP); + continue; } - break; case 0x04: /* JMP NEAR Ed */ - if (rm >= 0xc0 ) {GetEArd;SETIP(*eard);} - else {GetEAa;SETIP(LoadMd(eaa));} - break; + if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;} + else {GetEAa;reg_eip=LoadMd(eaa);} + continue; case 0x05: /* JMP FAR Ed */ { GetEAa; Bit32u newip=LoadMd(eaa); Bit16u newcs=LoadMw(eaa+4); - LEAVECORE; - CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start); - goto decode_start; + FillFlags(); + CPU_JMP(true,newcs,newip,GETIP); + continue; } break; case 0x06: /* Push Ed */ diff --git a/src/cpu/core_normal/prefix_66_0f.h b/src/cpu/core_normal/prefix_66_0f.h index 39be74b..512117c 100644 --- a/src/cpu/core_normal/prefix_66_0f.h +++ b/src/cpu/core_normal/prefix_66_0f.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -101,7 +101,7 @@ CASE_0F_D(0x02) /* LAR Gd,Ed */ { FillFlags(); - GetRMrd;Bitu ar; + GetRMrd;Bitu ar=*rmrd; if (rm >= 0xc0) { GetEArw;CPU_LAR(*earw,ar); } else { @@ -113,7 +113,7 @@ CASE_0F_D(0x03) /* LSL Gd,Ew */ { FillFlags(); - GetRMrd;Bitu limit; + GetRMrd;Bitu limit=*rmrd; /* Just load 16-bit values for selectors */ if (rm >= 0xc0) { GetEArw;CPU_LSL(*earw,limit); @@ -159,7 +159,8 @@ CASE_0F_D(0xa0) /* PUSH FS */ Push_32(SegValue(fs));break; CASE_0F_D(0xa1) /* POP FS */ - POPSEG(fs,Pop_32(),4);break; + if (CPU_PopSeg(fs,true)) RUNEXCEPTION(); + break; CASE_0F_D(0xa3) /* BT Ed,Gd */ { FillFlags();GetRMrd; @@ -183,7 +184,8 @@ CASE_0F_D(0xa8) /* PUSH GS */ Push_32(SegValue(gs));break; CASE_0F_D(0xa9) /* POP GS */ - POPSEG(gs,Pop_32(),4);break; + if (CPU_PopSeg(gs,true)) RUNEXCEPTION(); + break; CASE_0F_D(0xab) /* BTS Ed,Gd */ { FillFlags();GetRMrd; @@ -215,7 +217,7 @@ CASE_0F_D(0xb2) /* LSS Ed */ { GetRMrd;GetEAa; - LOADSEG(ss,LoadMw(eaa+4)); + if (CPU_SetSegGeneral(ss,LoadMw(eaa+4))) RUNEXCEPTION(); *rmrd=LoadMd(eaa); break; } @@ -238,14 +240,14 @@ CASE_0F_D(0xb4) /* LFS Ed */ { GetRMrd;GetEAa; - LOADSEG(fs,LoadMw(eaa+4)); + if (CPU_SetSegGeneral(fs,LoadMw(eaa+4))) RUNEXCEPTION(); *rmrd=LoadMd(eaa); break; } CASE_0F_D(0xb5) /* LGS Ed */ { GetRMrd;GetEAa; - LOADSEG(gs,LoadMw(eaa+4)); + if (CPU_SetSegGeneral(gs,LoadMw(eaa+4))) RUNEXCEPTION(); *rmrd=LoadMd(eaa); break; } diff --git a/src/cpu/core_normal/prefix_none.h b/src/cpu/core_normal/prefix_none.h index 6d79d97..0cc2c35 100644 --- a/src/cpu/core_normal/prefix_none.h +++ b/src/cpu/core_normal/prefix_none.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -31,7 +31,8 @@ CASE_W(0x06) /* PUSH ES */ Push_16(SegValue(es));break; CASE_W(0x07) /* POP ES */ - POPSEG(es,Pop_16(),2);break; + if (CPU_PopSeg(es,false)) RUNEXCEPTION(); + break; CASE_B(0x08) /* OR Eb,Gb */ RMEbGb(ORB);break; CASE_W(0x09) /* OR Ew,Gw */ @@ -65,7 +66,7 @@ CASE_W(0x16) /* PUSH SS */ Push_16(SegValue(ss));break; CASE_W(0x17) /* POP SS */ - POPSEG(ss,Pop_16(),2); + if (CPU_PopSeg(ss,false)) RUNEXCEPTION(); CPU_Cycles++; //Always do another instruction break; CASE_B(0x18) /* SBB Eb,Gb */ @@ -83,7 +84,7 @@ CASE_W(0x1e) /* PUSH DS */ Push_16(SegValue(ds));break; CASE_W(0x1f) /* POP DS */ - POPSEG(ds,Pop_16(),2); + if (CPU_PopSeg(ds,false)) RUNEXCEPTION(); break; CASE_B(0x20) /* AND Eb,Gb */ RMEbGb(ANDB);break; @@ -237,6 +238,7 @@ break; CASE_W(0x63) /* ARPL Ew,Rw */ { + if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; FillFlags(); GetRMrw; if (rm >= 0xc0 ) { @@ -255,7 +257,7 @@ CASE_B(0x65) /* SEG GS: */ DO_PREFIX_SEG(gs);break; CASE_B(0x66) /* Operand Size Prefix */ - core.opcode_index=core.index_default^OPCODE_SIZE; + core.opcode_index=(cpu.code.big^0x1)*0x200; goto restart_opcode; CASE_B(0x67) /* Address Size Prefix */ DO_PREFIX_ADDR(); @@ -271,12 +273,16 @@ 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; @@ -476,12 +482,12 @@ CASE_W(0x8d) /* LEA Gw */ { //Little hack to always use segprefixed version - core.seg_prefix_base=0; + BaseDS=BaseSS=0; GetRMrw; if (TEST_PREFIX_ADDR) { - *rmrw=(Bit16u)(*GetEA_SEG_ADDR[rm])(); + *rmrw=(Bit16u)(*EATable[256+rm])(); } else { - *rmrw=(Bit16u)(*GetEA_SEG[rm])(); + *rmrw=(Bit16u)(*EATable[rm])(); } break; } @@ -497,13 +503,10 @@ case 0x03: /* MOV DS,Ew */ case 0x05: /* MOV GS,Ew */ case 0x04: /* MOV FS,Ew */ - LOADSEG((SegNames)which,val); - break; - case 0x01: /* MOV CS,Ew Illegal*/ - E_Exit("CPU:Illegal MOV CS Call"); + if (CPU_SetSegGeneral((SegNames)which,val)) RUNEXCEPTION(); break; default: - E_Exit("CPU:8E:Illegal RM Byte"); + goto illegal_opcode; } break; } @@ -545,24 +548,20 @@ break; CASE_W(0x9a) /* CALL Ap */ { + FillFlags(); Bit16u newip=Fetchw();Bit16u newcs=Fetchw(); - LEAVECORE; - CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start); - goto decode_start; + CPU_CALL(false,newcs,newip,GETIP); + continue; } CASE_B(0x9b) /* WAIT */ break; /* No waiting here */ CASE_W(0x9c) /* PUSHF */ FillFlags(); - Push_16(reg_flags); + if (CPU_PUSHF(false)) RUNEXCEPTION(); break; CASE_W(0x9d) /* POPF */ - if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) { - LEAVECORE;reg_eip-=core.ip_lookup-core.op_start; - CPU_Exception(13,0); - goto decode_start; - } - SETFLAGSw(Pop_16()); + if (CPU_POPF(false)) RUNEXCEPTION(); + lflags.type=t_UNKNOWN; #if CPU_TRAP_CHECK if (GETFLAG(TF)) { cpudecoder=CPU_Core_Normal_Trap_Run; @@ -665,25 +664,23 @@ CASE_W(0xc1) /* GRP2 Ew,Ib */ GRP2W(Fetchb());break; CASE_W(0xc2) /* RETN Iw */ - { - Bit16u addsp=Fetchw(); - SETIP(Pop_16());reg_esp+=addsp; - break; - } + reg_eip=Pop_16(); + reg_esp+=Fetchw(); + continue; CASE_W(0xc3) /* RETN */ - SETIP(Pop_16()); - break; + reg_eip=Pop_16(); + continue; CASE_W(0xc4) /* LES */ { GetRMrw;GetEAa; - LOADSEG(es,LoadMw(eaa+2)); + if (CPU_SetSegGeneral(es,LoadMw(eaa+2))) RUNEXCEPTION(); *rmrw=LoadMw(eaa); break; } CASE_W(0xc5) /* LDS */ { GetRMrw;GetEAa; - LOADSEG(ds,LoadMw(eaa+2)); + if (CPU_SetSegGeneral(ds,LoadMw(eaa+2))) RUNEXCEPTION(); *rmrw=LoadMw(eaa); break; } @@ -703,36 +700,11 @@ } CASE_W(0xc8) /* ENTER Iw,Ib */ { - Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; - Bitu frame_ptr=reg_esp-2; - if (cpu.stack.big) { - reg_esp-=2; - mem_writew(SegBase(ss)+reg_esp,reg_bp); - for (Bitu i=1;i= 0xc0 ) {GetEArw;Push_16((Bit16u)GETIP);SETIP(*earw);} - else {GetEAa;Push_16((Bit16u)GETIP);SETIP(LoadMw(eaa));} - break; + if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;} + else {GetEAa;reg_eip=LoadMw(eaa);} + Push_16(GETIP); + continue; case 0x03: /* CALL Ep */ { GetEAa; Bit16u newip=LoadMw(eaa); Bit16u newcs=LoadMw(eaa+2); - LEAVECORE; - CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start); - goto decode_start; + FillFlags(); + CPU_CALL(false,newcs,newip,GETIP); + continue; } break; case 0x04: /* JMP Ev */ - if (rm >= 0xc0 ) {GetEArw;SETIP(*earw);} - else {GetEAa;SETIP(LoadMw(eaa));} - break; + if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;} + else {GetEAa;reg_eip=LoadMw(eaa);} + continue; case 0x05: /* JMP Ep */ { GetEAa; Bit16u newip=LoadMw(eaa); Bit16u newcs=LoadMw(eaa+2); - LEAVECORE; - CPU_JMP(false,newcs,newip,core.ip_lookup-core.op_start); - goto decode_start; + FillFlags(); + CPU_JMP(false,newcs,newip,GETIP); + continue; } break; case 0x06: /* PUSH Ev */ diff --git a/src/cpu/core_normal/string.h b/src/cpu/core_normal/string.h index c2f3013..33ce3d5 100644 --- a/src/cpu/core_normal/string.h +++ b/src/cpu/core_normal/string.h @@ -17,21 +17,13 @@ static void DoString(STRING_OP type) { Bitu count,count_left; Bits add_index; - if (TEST_PREFIX_SEG) si_base=core.seg_prefix_base; - else si_base=SegBase(ds); + si_base=BaseDS; di_base=SegBase(es); - if (TEST_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 (!(TEST_PREFIX_REP)) { + 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++; @@ -40,7 +32,7 @@ static void DoString(STRING_OP type) { count_left=count-CPU_Cycles; count=CPU_Cycles; CPU_Cycles=0; - core.ip_lookup=core.op_start; //Reset IP to start of instruction + LOADIP; //RESET IP to the start } else { /* Won't interrupt scas and cmps instruction since they can interrupt themselves */ count_left=0; diff --git a/src/cpu/core_normal/support.h b/src/cpu/core_normal/support.h index e9ce3c8..910f167 100644 --- a/src/cpu/core_normal/support.h +++ b/src/cpu/core_normal/support.h @@ -9,66 +9,25 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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 SETIP(_a_) (core.ip_lookup=SegBase(cs)+_a_) -#define GETIP (Bit32u)(core.ip_lookup-SegBase(cs)) -#define SAVEIP {reg_eip=GETIP;} -#define LOADIP {core.ip_lookup=(SegBase(cs)+reg_eip);} -#define LEAVECORE \ - SAVEIP; \ - FillFlags(); +#define LoadMbs(off) (Bit8s)(LoadMb(off)) +#define LoadMws(off) (Bit16s)(LoadMw(off)) +#define LoadMds(off) (Bit32s)(LoadMd(off)) -static INLINE void ADDIPw(Bits add) { - SAVEIP; - reg_eip=(Bit16u)(reg_eip+add); - LOADIP; -} +#define LoadRb(reg) reg +#define LoadRw(reg) reg +#define LoadRd(reg) reg -static INLINE void ADDIPd(Bits add) { - SAVEIP; - reg_eip=(reg_eip+add); - LOADIP; -} - -static INLINE void ADDIPFAST(Bits blah) { -// core.ip_lookup+=blah; - SAVEIP; - reg_eip=(reg_eip+blah); - LOADIP; -} - -#define EXCEPTION(blah) \ - { \ - Bit8u new_num=blah; \ - core.ip_lookup=core.op_start; \ - LEAVECORE; \ - CPU_Exception(new_num); \ - goto decode_start; \ - } - -static INLINE Bit8u Fetchb() { - Bit8u temp=LoadMb(core.ip_lookup); - core.ip_lookup+=1; - return temp; -} - -static INLINE Bit16u Fetchw() { - Bit16u temp=LoadMw(core.ip_lookup); - core.ip_lookup+=2; - return temp; -} -static INLINE Bit32u Fetchd() { - Bit32u temp=LoadMd(core.ip_lookup); - core.ip_lookup+=4; - return temp; -} +#define SaveRb(reg,val) reg=val +#define SaveRw(reg,val) reg=val +#define SaveRd(reg,val) reg=val static INLINE Bit8s Fetchbs() { return Fetchb(); @@ -81,68 +40,48 @@ static INLINE Bit32s Fetchds() { return Fetchd(); } -#if 0 -static INLINE void Push_16(Bit16u blah) { - reg_esp-=2; - SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); -}; +#define RUNEXCEPTION() { \ + FillFlags(); \ + CPU_Exception(cpu.exception.which,cpu.exception.error); \ + continue; \ +} -static INLINE void Push_32(Bit32u blah) { - reg_esp-=4; - SaveMd(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); -}; - -static INLINE Bit16u Pop_16() { - Bit16u temp=LoadMw(SegBase(ss)+(reg_esp & cpu.stack.mask)); - reg_esp+=2; - return temp; -}; - -static INLINE Bit32u Pop_32() { - Bit32u temp=LoadMd(SegBase(ss)+(reg_esp & cpu.stack.mask)); - reg_esp+=4; - return temp; -}; - -#else - -#define Push_16 CPU_Push16 -#define Push_32 CPU_Push32 -#define Pop_16 CPU_Pop16 -#define Pop_32 CPU_Pop32 - -#endif +#define EXCEPTION(blah) \ + { \ + CPU_Exception(blah); \ + continue; \ + } //TODO Could probably make all byte operands fast? -#define JumpCond16_b(blah) \ - if (blah) { \ - ADDIPw(Fetchbs()); \ - } else { \ - ADDIPFAST(1); \ - } +#define JumpCond16_b(COND) { \ + SAVEIP; \ + if (COND) reg_ip+=Fetchbs(); \ + reg_ip+=1; \ + continue; \ +} -#define JumpCond32_b(blah) \ - if (blah) { \ - ADDIPd(Fetchbs()); \ - } else { \ - ADDIPFAST(1); \ - } +#define JumpCond16_w(COND) { \ + SAVEIP; \ + if (COND) reg_ip+=Fetchws(); \ + reg_ip+=2; \ + continue; \ +} -#define JumpCond16_w(blah) \ - if (blah) { \ - ADDIPw(Fetchws()); \ - } else { \ - ADDIPFAST(2); \ - } +#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 JumpCond32_d(blah) \ - if (blah) { \ - ADDIPd(Fetchds()); \ - } else { \ - ADDIPFAST(4); \ - } #define SETcc(cc) \ { \ diff --git a/src/cpu/core_normal/table_ea.h b/src/cpu/core_normal/table_ea.h index c6e95fc..a7352e8 100644 --- a/src/cpu/core_normal/table_ea.h +++ b/src/cpu/core_normal/table_ea.h @@ -9,207 +9,137 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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 (*GetEATable[256])(void); 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 SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si); } -static PhysPt EA_16_01_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di); } -static PhysPt EA_16_02_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si); } -static PhysPt EA_16_03_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di); } -static PhysPt EA_16_04_n(void) { return SegBase(ds)+(Bit16u)(reg_si); } -static PhysPt EA_16_05_n(void) { return SegBase(ds)+(Bit16u)(reg_di); } -static PhysPt EA_16_06_n(void) { return SegBase(ds)+(Bit16u)(Fetchw());} -static PhysPt EA_16_07_n(void) { return SegBase(ds)+(Bit16u)(reg_bx); } +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 SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); } -static PhysPt EA_16_41_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); } -static PhysPt EA_16_42_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); } -static PhysPt EA_16_43_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); } -static PhysPt EA_16_44_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchbs()); } -static PhysPt EA_16_45_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchbs()); } -static PhysPt EA_16_46_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchbs()); } -static PhysPt EA_16_47_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchbs()); } +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 SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); } -static PhysPt EA_16_81_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); } -static PhysPt EA_16_82_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); } -static PhysPt EA_16_83_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); } -static PhysPt EA_16_84_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchws()); } -static PhysPt EA_16_85_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchws()); } -static PhysPt EA_16_86_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchws()); } -static PhysPt EA_16_87_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchws()); } - -static GetEATable GetEA_NONE={ -/* 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 -}; - - - -static PhysPt EA_16_00_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si); } -static PhysPt EA_16_01_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di); } -static PhysPt EA_16_02_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si); } -static PhysPt EA_16_03_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di); } -static PhysPt EA_16_04_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si); } -static PhysPt EA_16_05_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di); } -static PhysPt EA_16_06_s(void) { return core.seg_prefix_base+(Bit16u)(Fetchw()); } -static PhysPt EA_16_07_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx); } - -static PhysPt EA_16_40_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); } -static PhysPt EA_16_41_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); } -static PhysPt EA_16_42_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); } -static PhysPt EA_16_43_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); } -static PhysPt EA_16_44_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si+Fetchbs()); } -static PhysPt EA_16_45_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di+Fetchbs()); } -static PhysPt EA_16_46_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+Fetchbs()); } -static PhysPt EA_16_47_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+Fetchbs()); } - -static PhysPt EA_16_80_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); } -static PhysPt EA_16_81_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); } -static PhysPt EA_16_82_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); } -static PhysPt EA_16_83_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); } -static PhysPt EA_16_84_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si+Fetchws()); } -static PhysPt EA_16_85_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di+Fetchws()); } -static PhysPt EA_16_86_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+Fetchws()); } -static PhysPt EA_16_87_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+Fetchws()); } - -static GetEATable GetEA_SEG={ -/* 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 -}; +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 }; -INLINE PhysPt Sib(Bitu mode) { +static INLINE PhysPt Sib(Bitu mode) { Bit8u sib=Fetchb(); PhysPt base; switch (sib&7) { case 0: /* EAX Base */ - base=SegBase(ds)+reg_eax;break; + base=BaseDS+reg_eax;break; case 1: /* ECX Base */ - base=SegBase(ds)+reg_ecx;break; + base=BaseDS+reg_ecx;break; case 2: /* EDX Base */ - base=SegBase(ds)+reg_edx;break; + base=BaseDS+reg_edx;break; case 3: /* EBX Base */ - base=SegBase(ds)+reg_ebx;break; + base=BaseDS+reg_ebx;break; case 4: /* ESP Base */ - base=SegBase(ss)+reg_esp;break; + base=BaseSS+reg_esp;break; case 5: /* #1 Base */ if (!mode) { - base=SegBase(ds)+Fetchd();break; + base=BaseDS+Fetchd();break; } else { - base=SegBase(ss)+reg_ebp;break; + base=BaseSS+reg_ebp;break; } case 6: /* ESI Base */ - base=SegBase(ds)+reg_esi;break; + base=BaseDS+reg_esi;break; case 7: /* EDI Base */ - base=SegBase(ds)+reg_edi;break; + base=BaseDS+reg_edi;break; } base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); return base; }; - -static PhysPt EA_32_00_n(void) { return SegBase(ds)+reg_eax; } -static PhysPt EA_32_01_n(void) { return SegBase(ds)+reg_ecx; } -static PhysPt EA_32_02_n(void) { return SegBase(ds)+reg_edx; } -static PhysPt EA_32_03_n(void) { return SegBase(ds)+reg_ebx; } +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 SegBase(ds)+Fetchd(); } -static PhysPt EA_32_06_n(void) { return SegBase(ds)+reg_esi; } -static PhysPt EA_32_07_n(void) { return SegBase(ds)+reg_edi; } +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 SegBase(ds)+reg_eax+Fetchbs(); } -static PhysPt EA_32_41_n(void) { return SegBase(ds)+reg_ecx+Fetchbs(); } -static PhysPt EA_32_42_n(void) { return SegBase(ds)+reg_edx+Fetchbs(); } -static PhysPt EA_32_43_n(void) { return SegBase(ds)+reg_ebx+Fetchbs(); } +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 SegBase(ss)+reg_ebp+Fetchbs(); } -static PhysPt EA_32_46_n(void) { return SegBase(ds)+reg_esi+Fetchbs(); } -static PhysPt EA_32_47_n(void) { return SegBase(ds)+reg_edi+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 SegBase(ds)+reg_eax+Fetchds(); } -static PhysPt EA_32_81_n(void) { return SegBase(ds)+reg_ecx+Fetchds(); } -static PhysPt EA_32_82_n(void) { return SegBase(ds)+reg_edx+Fetchds(); } -static PhysPt EA_32_83_n(void) { return SegBase(ds)+reg_ebx+Fetchds(); } +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 SegBase(ss)+reg_ebp+Fetchds(); } -static PhysPt EA_32_86_n(void) { return SegBase(ds)+reg_esi+Fetchds(); } -static PhysPt EA_32_87_n(void) { return SegBase(ds)+reg_edi+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 GetEATable GetEA_ADDR={ +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, @@ -244,113 +174,12 @@ static GetEATable GetEA_ADDR={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -INLINE PhysPt Sib_s(Bitu mode) { - Bit8u sib=Fetchb(); - PhysPt base; - switch (sib&7) { - case 0: /* EAX Base */ - base=reg_eax;break; - case 1: /* ECX Base */ - base=reg_ecx;break; - case 2: /* EDX Base */ - base=reg_edx;break; - case 3: /* EBX Base */ - base=reg_ebx;break; - case 4: /* ESP Base */ - base=reg_esp;break; - case 5: /* #1 Base */ - if (!mode) { - base=Fetchd();break; - } else { - base=reg_ebp;break; - } - case 6: /* ESI Base */ - base=reg_esi;break; - case 7: /* EDI Base */ - base=reg_edi;break; - } - base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); - return base; -}; - - -static PhysPt EA_32_00_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax); } -static PhysPt EA_32_01_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx); } -static PhysPt EA_32_02_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx); } -static PhysPt EA_32_03_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx); } -static PhysPt EA_32_04_s(void) { return core.seg_prefix_base+(Bit32u)(Sib_s(0));} -static PhysPt EA_32_05_s(void) { return core.seg_prefix_base+(Bit32u)(Fetchd()); } -static PhysPt EA_32_06_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi); } -static PhysPt EA_32_07_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi); } - -static PhysPt EA_32_40_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax+Fetchbs()); } -static PhysPt EA_32_41_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx+Fetchbs()); } -static PhysPt EA_32_42_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx+Fetchbs()); } -static PhysPt EA_32_43_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx+Fetchbs()); } -static PhysPt EA_32_44_s(void) { PhysPt temp=Sib_s(1);return core.seg_prefix_base+(Bit32u)(temp+Fetchbs());} -static PhysPt EA_32_45_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebp+Fetchbs()); } -static PhysPt EA_32_46_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi+Fetchbs()); } -static PhysPt EA_32_47_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi+Fetchbs()); } - -static PhysPt EA_32_80_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax+Fetchds()); } -static PhysPt EA_32_81_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx+Fetchds()); } -static PhysPt EA_32_82_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx+Fetchds()); } -static PhysPt EA_32_83_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx+Fetchds()); } -static PhysPt EA_32_84_s(void) { PhysPt temp=Sib_s(2);return core.seg_prefix_base+(Bit32u)(temp+Fetchds());} -static PhysPt EA_32_85_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebp+Fetchds()); } -static PhysPt EA_32_86_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi+Fetchds()); } -static PhysPt EA_32_87_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi+Fetchds()); } - - -static GetEATable GetEA_SEG_ADDR={ -/* 00 */ - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, -/* 01 */ - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, -/* 10 */ - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_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 -}; - -#define GetEADirect \ - PhysPt eaa; \ - if (TEST_PREFIX_SEG) { \ - if (TEST_PREFIX_ADDR) { \ - eaa=core.seg_prefix_base+Fetchd(); \ - } else { \ - eaa=core.seg_prefix_base+Fetchw(); \ - } \ - } else { \ - if (TEST_PREFIX_ADDR) { \ - eaa=SegBase(ds)+Fetchd(); \ - } else { \ - eaa=SegBase(ds)+Fetchw(); \ - } \ - } +#define GetEADirect \ + PhysPt eaa; \ + if (TEST_PREFIX_ADDR) { \ + eaa=BaseDS+Fetchd(); \ + } else { \ + eaa=BaseDS+Fetchw(); \ + } \ diff --git a/src/cpu/core_simple.cpp b/src/cpu/core_simple.cpp new file mode 100644 index 0000000..7ff744e --- /dev/null +++ b/src/cpu/core_simple.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along 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); \ + 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; + HostPt cseip; + PhysPt base_ds,base_ss; + bool rep_zero; + Bitu prefixes; + GetEAHandler * ea_table; + struct { + bool skip; + } trap; +} 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); +#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_ERROR)("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_Simple_Trap_Run(void) { + + Bits oldCycles = CPU_Cycles; + CPU_Cycles = 1; + core.trap.skip=false; + + Bits ret=CPU_Core_Normal_Run(); + if (!core.trap.skip) CPU_SW_Interrupt(1,reg_eip); + CPU_Cycles = oldCycles-1; + cpudecoder = &CPU_Core_Normal_Run; + + return ret; +} + + + +void CPU_Core_Simple_Init(void) { + +} + diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index cf8995c..acb576b 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -9,21 +9,21 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.53 2004/01/14 17:09:41 harekiet Exp $ */ +/* $Id: cpu.cpp,v 1.61 2004/08/23 12:17:29 harekiet Exp $ */ #include #include "dosbox.h" #include "cpu.h" #include "memory.h" #include "debug.h" -#include "keyboard.h" +#include "mapper.h" #include "setup.h" #include "paging.h" #include "support.h" @@ -46,12 +46,9 @@ Bits CPU_CycleUp = 0; Bits CPU_CycleDown = 0; CPU_Decoder * cpudecoder; -static struct { - Bitu which,errorcode; -} exception; - void CPU_Core_Full_Init(void); void CPU_Core_Normal_Init(void); +void CPU_Core_Simple_Init(void); void CPU_Core_Dyn_X86_Init(void); void CPU_Push16(Bitu value) { @@ -91,6 +88,48 @@ void CPU_SetFlags(Bitu word,Bitu mask) { 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_IOPL=8) ? CPU_INT_HAS_ERROR : 0)); -} - -void CPU_SetupException(Bitu which,Bitu error) { - cpu.exception.which=which; - cpu.exception.error=error; +bool CPU_IO_Exception(Bitu port,Bitu size) { + if (cpu.pmode && ((GETFLAG_IOPLcpu_tss.limit) goto doexception; + where=cpu_tss.base+ofs+(port/8); + Bitu map=mem_readw(where); + Bitu mask=(0xffff>>(16-size)) << (port&7); + if (map & mask) goto doexception; + } + return false; +doexception: + LOG_MSG("Exception"); + return CPU_PrepareException(13,0); } void CPU_Exception(Bitu which,Bitu error ) { -// LOG_MSG("Exception %d CS:%X IP:%X FLAGS:%X",num,SegValue(cs),reg_eip,reg_flags); - CPU_SetupException(which,error); - CPU_StartException(); +// 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 opLen) { +void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) { lastint=num; #if C_DEBUG switch (num) { @@ -302,10 +349,10 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) { }; #endif if (!cpu.pmode) { - /* Save everything on a 16-bit stack */ + /* Save everything on a 16-bit stack */ CPU_Push16(reg_flags & 0xffff); CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip); + CPU_Push16(oldeip); SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); /* Get the new CS:IP from vector table */ @@ -323,7 +370,6 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) { if ((reg_flags & FLAG_VM) && (type&CPU_INT_SOFTWARE)) { // LOG_MSG("Software int in v86, AH %X IOPL %x",reg_ah,(reg_flags & FLAG_IOPL) >>12); if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { - reg_eip-=opLen; CPU_Exception(13,0); return; } @@ -332,7 +378,6 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) { //TODO Check for software interrupt and check gate's dplcpu.cpl) E_Exit("Interrupt to higher privilege"); + if (cs_dpl>cpu.cpl) E_Exit("Interrupt to higher privilege"); 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: @@ -397,12 +442,12 @@ do_interrupt: if (gate.Type() & 0x8) { /* 32-bit Gate */ CPU_Push32(reg_flags); CPU_Push32(SegValue(cs)); - CPU_Push32(reg_eip); + CPU_Push32(oldeip); if (type & CPU_INT_HAS_ERROR) CPU_Push32(cpu.exception.error); } else { /* 16-bit gate */ CPU_Push16(reg_flags & 0xffff); CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip); + CPU_Push16(oldeip); if (type & CPU_INT_HAS_ERROR) CPU_Push16(cpu.exception.error); } break; @@ -410,7 +455,7 @@ do_interrupt: E_Exit("INT:Gate Selector points to illegal descriptor with type %x",cs_desc.Type()); } if (!(gate.Type()&1)) - SETFLAGBIT(IF,false); + SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); SETFLAGBIT(NT,false); SETFLAGBIT(VM,false); @@ -422,7 +467,7 @@ do_interrupt: return; } case DESC_TASK_GATE: - CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT); + 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); @@ -437,7 +482,7 @@ do_interrupt: return ; // make compiler happy } -void CPU_IRET(bool use32) { +void CPU_IRET(bool use32,Bitu oldeip) { if (!cpu.pmode) { /* RealMode IRET */ realmode_iret: if (use32) { @@ -454,7 +499,6 @@ realmode_iret: } else { /* Protected mode IRET */ if (reg_flags & FLAG_VM) { if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { - reg_eip--; CPU_Exception(13,0); return; } else goto realmode_iret; @@ -466,7 +510,7 @@ realmode_iret: if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set"); if (!cpu_tss.IsValid()) E_Exit("TASK Iret without valid TSS"); Bitu back_link=cpu_tss.Get_back(); - CPU_SwitchTask(back_link,TSwitch_IRET); + CPU_SwitchTask(back_link,TSwitch_IRET,oldeip); return; } Bitu n_cs_sel,n_eip,n_flags; @@ -506,7 +550,7 @@ realmode_iret: Bitu n_cs_rpl=n_cs_sel & 3; Descriptor n_cs_desc; cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc); - if (n_cs_rpl0; Segs.val[cs]=n_cs_sel; reg_eip=n_eip; + CPU_SetFlagsd(n_flags); LOG(LOG_CPU,LOG_NORMAL)("IRET:Same level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big); } else { @@ -545,9 +590,11 @@ realmode_iret: Segs.phys[cs]=n_cs_desc.GetBase(); cpu.code.big=n_cs_desc.Big()>0; Segs.val[cs]=n_cs_sel; + + CPU_SetFlagsd(n_flags); + cpu.cpl=n_cs_rpl; reg_eip=n_eip; - CPU_SetFlagsd(n_flags); Bitu n_ss,n_esp; if (use32) { n_esp=CPU_Pop32(); @@ -562,14 +609,15 @@ realmode_iret: } else { reg_sp=n_esp; } + //TODO Maybe validate other segments, but why would anyone use them? - LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level:%X:X big %d",n_cs_sel,n_eip,cpu.code.big); + LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big); } return; } } -void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) { +void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip) { if (!cpu.pmode || (reg_flags & FLAG_VM)) { if (!use32) { reg_eip=offset&0xffff; @@ -584,7 +632,6 @@ void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) { Descriptor desc; cpu.gdt.GetDescriptor(selector,desc); if (!desc.saved.seg.p) { - reg_eip -= opLen; CPU_Exception(0x0B,selector & 0xfffc); return; } @@ -592,8 +639,7 @@ void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) { 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 (rpl>cpu.cpl) E_Exit("JMP:NC:RPL>CPL"); - if (rpl!=desc.DPL()) E_Exit("JMP:NC:RPL != DPL"); - cpu.cpl=desc.DPL(); + if (cpu.cpl!=desc.DPL()) E_Exit("JMP:NC:RPL != DPL"); 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: @@ -610,7 +656,7 @@ CODE_jmp: if (desc.DPL()=0;i--) + CPU_Push32(mem_readd(o_stack+i*4)); CPU_Push32(SegValue(cs)); - CPU_Push32(reg_eip); + CPU_Push32(oldeip); } else { CPU_Push16(o_ss); //save old stack CPU_Push16(o_esp); - for (Bitu i=0;i<(call.saved.gate.paramcount&31);i++) - CPU_Push16(mem_readw(o_stack+i*2)); + 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(SegValue(cs)); - CPU_Push16(reg_eip); + CPU_Push16(oldeip); } + cpu.cpl = n_cs_desc.DPL(); /* Switch to new CS:EIP */ Segs.phys[cs] = n_cs_desc.GetBase(); Segs.val[cs] = (n_cs_sel & 0xfffc) | cpu.cpl; @@ -742,7 +789,7 @@ call_gate_same_privilege: if (call.DPL()0; - Segs.val[cs]=selector; + Segs.val[cs]=(selector&0xfffc) | cpu.cpl; reg_eip=offset; + // LOG(LOG_MISC,LOG_ERROR)("RET - Higher level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL()); return; } @@ -899,9 +951,8 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) { case 0: { Bitu changed=cpu.cr0 ^ value; - if (!changed) return true; + if (!changed) return false; cpu.cr0=value; -//TODO Maybe always first change to core_full for a change to cr0 if (value & CR0_PROTECTION) { cpu.pmode=true; LOG(LOG_CPU,LOG_NORMAL)("Protected mode"); @@ -911,7 +962,7 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) { PAGING_Enable(false); LOG(LOG_CPU,LOG_NORMAL)("Real mode"); } - return false; //Only changes with next CS change + break; } case 2: paging.cr2=value; @@ -946,11 +997,12 @@ void CPU_SMSW(Bitu & word) { word=cpu.cr0; } -bool CPU_LMSW(Bitu word) { +Bitu CPU_LMSW(Bitu word) { word&=0xf; if (cpu.cr0 & 1) word|=1; word|=(cpu.cr0&0xfffffff0); - return CPU_SET_CRX(0,word); + CPU_SET_CRX(0,word); + return false; } void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) { @@ -964,8 +1016,11 @@ void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) { } void CPU_LAR(Bitu selector,Bitu & ar) { + if (selector == 0) { + SETFLAGBIT(ZF,false); + return; + } Descriptor desc;Bitu rpl=selector & 3; - ar=0; if (!cpu.gdt.GetDescriptor(selector,desc)){ SETFLAGBIT(ZF,false); return; @@ -974,16 +1029,20 @@ void CPU_LAR(Bitu selector,Bitu & ar) { 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_INT_GATE: case DESC_286_TRAP_GATE: case DESC_286_CALL_GATE: case DESC_386_TSS_A: case DESC_386_TSS_B: - case DESC_386_INT_GATE: case DESC_386_TRAP_GATE: case DESC_386_CALL_GATE: @@ -1008,8 +1067,11 @@ void CPU_LAR(Bitu selector,Bitu & ar) { } void CPU_LSL(Bitu selector,Bitu & limit) { + if (selector == 0) { + SETFLAGBIT(ZF,false); + return; + } Descriptor desc;Bitu rpl=selector & 3; - limit=0; if (!cpu.gdt.GetDescriptor(selector,desc)){ SETFLAGBIT(ZF,false); return; @@ -1018,7 +1080,7 @@ void CPU_LSL(Bitu selector,Bitu & limit) { 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_LDT: case DESC_286_TSS_A: case DESC_286_TSS_B: @@ -1047,6 +1109,10 @@ void CPU_LSL(Bitu selector,Bitu & limit) { } void CPU_VERR(Bitu selector) { + if (selector == 0) { + SETFLAGBIT(ZF,false); + return; + } Descriptor desc;Bitu rpl=selector & 3; if (!cpu.gdt.GetDescriptor(selector,desc)){ SETFLAGBIT(ZF,false); @@ -1075,6 +1141,10 @@ void CPU_VERR(Bitu selector) { } void CPU_VERW(Bitu selector) { + if (selector == 0) { + SETFLAGBIT(ZF,false); + return; + } Descriptor desc;Bitu rpl=selector & 3; if (!cpu.gdt.GetDescriptor(selector,desc)){ SETFLAGBIT(ZF,false); @@ -1113,13 +1183,11 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) { if (!desc.saved.seg.p) { if (seg==ss) E_Exit("CPU_SetSegGeneral: Stack segment not present."); // Throw Exception 0x0B - Segment not present - CPU_SetupException(0x0B,value & 0xfffc); - return true; + return CPU_PrepareException(0x0B,value & 0xfffc); } else if (seg==ss) { // Stack segment loaded with illegal segment ? if ((desc.saved.seg.typeDESC_DATA_ED_RW_A)) { - CPU_SetupException(0x0D,value & 0xfffc); - return true; + return CPU_PrepareException(0x0D,value & 0xfffc); } } } @@ -1138,6 +1206,14 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) { } } +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=2 << use32; + reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+addsp)&cpu.stack.mask); + return false; +} + void CPU_CPUID(void) { switch (reg_eax) { case 0: /* Vendor ID String and maximum level? */ @@ -1168,12 +1244,12 @@ static Bits HLT_Decode(void) { return 0; } -void CPU_HLT(Bitu opLen) { +void CPU_HLT(Bitu oldeip) { if (cpu.cpl) { - reg_eip-=opLen; CPU_Exception(13,0); return; } + reg_eip=oldeip; CPU_Cycles=0; cpu.hlt.cs=SegValue(cs); cpu.hlt.eip=reg_eip; @@ -1182,8 +1258,40 @@ void CPU_HLT(Bitu opLen) { return; } +void CPU_ENTER(bool use32,Bitu bytes,Bitu level) { + level&=0x1f; + Bitu sp_index=reg_esp&cpu.stack.mask; + Bitu bp_index=reg_ebp&cpu.stack.mask; + if (!use32) { + sp_index-=2; + mem_writew(SegPhys(ss)+sp_index,reg_bp); + reg_bp=(Bit16u)(reg_esp-2); + if (level) { + for (Bitu i=1;i(sec); reg_eax=0; @@ -1240,14 +1347,13 @@ void CPU_Init(Section* sec) { /* 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(); #endif - - KEYBOARD_AddEvent(KBD_f11,KBD_MOD_CTRL,CPU_CycleDecrease); - KEYBOARD_AddEvent(KBD_f12,KBD_MOD_CTRL,CPU_CycleIncrease); - + MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles"); + MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup" ,"Inc Cycles"); CPU_Cycles=0; CPU_CycleMax=section->Get_int("cycles");; CPU_CycleUp=section->Get_int("cycleup"); @@ -1256,6 +1362,8 @@ void CPU_Init(Section* sec) { cpudecoder=&CPU_Core_Normal_Run; if (!strcasecmp(core,"normal")) { cpudecoder=&CPU_Core_Normal_Run; + } else if (!strcasecmp(core,"simple")) { + cpudecoder=&CPU_Core_Simple_Run; } else if (!strcasecmp(core,"full")) { cpudecoder=&CPU_Core_Full_Run; } @@ -1267,12 +1375,12 @@ void CPU_Init(Section* sec) { else { LOG_MSG("CPU:Unknown core type %s, switcing back to normal.",core); } - CPU_JMP(false,0,0); //Setup the first cpu core + CPU_JMP(false,0,0,0); //Setup the first cpu core if (!CPU_CycleMax) CPU_CycleMax = 2500; if(!CPU_CycleUp) CPU_CycleUp = 500; if(!CPU_CycleDown) CPU_CycleDown = 20; CPU_CycleLeft=0; - GFX_SetTitle(CPU_CycleMax,-1); + GFX_SetTitle(CPU_CycleMax,-1,false); } diff --git a/src/cpu/flags.cpp b/src/cpu/flags.cpp index bb67384..1ac9000 100644 --- a/src/cpu/flags.cpp +++ b/src/cpu/flags.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/cpu/instructions.h b/src/cpu/instructions.h index 3f94113..a53ae3e 100644 --- a/src/cpu/instructions.h +++ b/src/cpu/instructions.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -548,7 +548,7 @@ } #define MULB(op1,load,save) \ - lflags.type=t_MUL; \ + FillFlags(); \ reg_ax=reg_al*load(op1); \ if (reg_ax & 0xff00) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ @@ -558,10 +558,10 @@ #define MULW(op1,load,save) \ { \ + FillFlags(); \ Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \ reg_ax=(Bit16u)(tempu); \ reg_dx=(Bit16u)(tempu >> 16); \ - lflags.type=t_MUL; \ if (reg_dx) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ } else { \ @@ -571,10 +571,10 @@ #define MULD(op1,load,save) \ { \ + FillFlags(); \ Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \ reg_eax=(Bit32u)(tempu); \ reg_edx=(Bit32u)(tempu >> 32); \ - lflags.type=t_MUL; \ if (reg_edx) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ } else { \ @@ -651,7 +651,7 @@ #define IMULB(op1,load,save) \ { \ - lflags.type=t_MUL; \ + FillFlags(); \ reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \ if ((reg_ax & 0xff80)==0xff80 || \ (reg_ax & 0xff80)==0x0000) { \ @@ -664,10 +664,10 @@ #define IMULW(op1,load,save) \ { \ + FillFlags(); \ Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \ reg_ax=(Bit16s)(temps); \ reg_dx=(Bit16s)(temps >> 16); \ - lflags.type=t_MUL; \ if (((temps & 0xffff8000)==0xffff8000 || \ (temps & 0xffff8000)==0x0000)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -678,11 +678,11 @@ #define IMULD(op1,load,save) \ { \ + FillFlags(); \ Bit64s temps=((Bit64s)((Bit32s)reg_eax))* \ ((Bit64s)((Bit32s)(load(op1)))); \ reg_eax=(Bit32u)(temps); \ reg_edx=(Bit32u)(temps >> 32); \ - lflags.type=t_MUL; \ if ((reg_edx==0xffffffff) && \ (reg_eax & 0x80000000) ) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -696,10 +696,10 @@ #define DIMULW(op1,op2,op3,load,save) \ { \ + FillFlags(); \ Bits res; \ res=((Bit16s)op2) * ((Bit16s)op3); \ save(op1,res & 0xffff); \ - lflags.type=t_MUL; \ if ((res> -32768) && (res<32767)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ } else { \ @@ -709,9 +709,9 @@ #define DIMULD(op1,op2,op3,load,save) \ { \ + FillFlags(); \ Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \ save(op1,(Bit32s)res); \ - lflags.type=t_MUL; \ if ((res>-((Bit64s)(2147483647)+1)) && \ (res<(Bit64s)2147483647)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ diff --git a/src/cpu/lazyflags.h b/src/cpu/lazyflags.h index 897b481..9cf2a73 100644 --- a/src/cpu/lazyflags.h +++ b/src/cpu/lazyflags.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/cpu/modrm.cpp b/src/cpu/modrm.cpp index b9bad89..e726f79 100644 --- a/src/cpu/modrm.cpp +++ b/src/cpu/modrm.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/cpu/modrm.h b/src/cpu/modrm.h index 181d529..b51e0f2 100644 --- a/src/cpu/modrm.h +++ b/src/cpu/modrm.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/cpu/paging.cpp b/src/cpu/paging.cpp index 4db18bd..6198baf 100644 --- a/src/cpu/paging.cpp +++ b/src/cpu/paging.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -93,7 +93,7 @@ static Bits PageFaultCore(void) { if (!pf_queue.used) E_Exit("PF Core without PF"); PF_Entry * entry=&pf_queue.entries[pf_queue.used-1]; X86PageEntry pentry; - pentry.load=MEM_PhysReadD(entry->page_addr); + pentry.load=phys_readd(entry->page_addr); if (pentry.block.p && entry->cs == SegValue(cs) && entry->eip==reg_eip) return -1; return 0; @@ -102,6 +102,8 @@ static Bits PageFaultCore(void) { Bitu DEBUG_EnableDebugger(void); #endif +bool first=false; + void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) { /* Save the state of the cpu cores */ LazyFlags old_lflags; @@ -112,6 +114,8 @@ void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) { paging.cr2=lin_addr; PF_Entry * entry=&pf_queue.entries[pf_queue.used++]; LOG(LOG_PAGING,LOG_NORMAL)("PageFault at %X type %d queue %d",lin_addr,type,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; @@ -125,10 +129,9 @@ void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) { 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); } - -void MEM_PhysWriteD(Bitu addr,Bit32u val); class InitPageHandler : public PageHandler { public: InitPageHandler() {flags=PFLAG_INIT|PFLAG_NOCODE;} @@ -164,28 +167,28 @@ public: Bitu t_index=lin_page & 0x3ff; Bitu table_addr=(paging.base.page<<12)+d_index*4; X86PageEntry table; - table.load=MEM_PhysReadD(table_addr); + table.load=phys_readd(table_addr); if (!table.block.p) { LOG(LOG_PAGING,LOG_ERROR)("NP Table"); PAGING_PageFault(lin_addr,table_addr,0); - table.load=MEM_PhysReadD(table_addr); + table.load=phys_readd(table_addr); if (!table.block.p) E_Exit("Pagefault didn't correct table"); } table.block.a=table.block.d=1; //Set access/Dirty - MEM_PhysWriteD(table_addr,table.load); + phys_writed(table_addr,table.load); X86PageEntry entry; Bitu entry_addr=(table.block.base<<12)+t_index*4; - entry.load=MEM_PhysReadD(entry_addr); + entry.load=phys_readd(entry_addr); if (!entry.block.p) { LOG(LOG_PAGING,LOG_ERROR)("NP Page"); PAGING_PageFault(lin_addr,entry_addr,0); - entry.load=MEM_PhysReadD(entry_addr); + entry.load=phys_readd(entry_addr); if (!entry.block.p) E_Exit("Pagefault didn't correct page"); } entry.block.a=entry.block.d=1; //Set access/Dirty - MEM_PhysWriteD(entry_addr,entry.load); + phys_writed(entry_addr,entry.load); phys_page=entry.block.base; } else { if (lin_page> 10; Bitu t_index=page & 0x3ff; X86PageEntry table; - table.load=MEM_PhysReadD((paging.base.page<<12)+d_index*4); + table.load=phys_readd((paging.base.page<<12)+d_index*4); if (!table.block.p) return false; X86PageEntry entry; - entry.load=MEM_PhysReadD((table.block.base<<12)+t_index*4); + entry.load=phys_readd((table.block.base<<12)+t_index*4); if (!entry.block.p) return false; page=entry.block.base; } else { @@ -251,16 +254,21 @@ void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) { void PAGING_LinkPage(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(); + } + HostPt host_mem=handler->GetHostPt(phys_page); paging.tlb.phys_page[lin_page]=phys_page; if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=host_mem-lin_base; else paging.tlb.read[lin_page]=0; if (handler->flags & PFLAG_WRITEABLE) paging.tlb.write[lin_page]=host_mem-lin_base; else paging.tlb.write[lin_page]=0; - if (paging.links.used>=PAGING_LINKS) E_Exit("Not enough paging links"); + paging.links.entries[paging.links.used++]=lin_page; paging.tlb.handler[lin_page]=handler; } @@ -281,7 +289,7 @@ void PAGING_SetDirBase(Bitu cr3) { paging.base.page=cr3 >> 12; paging.base.addr=cr3 & ~4095; - LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,paging.base.page); +// LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,paging.base.page); if (paging.enabled) { PAGING_ClearTLB(); } @@ -292,9 +300,15 @@ void PAGING_Enable(bool enabled) { if (paging.enabled==enabled) return; paging.enabled=enabled; if (!enabled) { - LOG(LOG_PAGING,LOG_NORMAL)("Disabled"); +// LOG(LOG_PAGING,LOG_NORMAL)("Disabled"); } else { - LOG(LOG_PAGING,LOG_NORMAL)("Enabled"); + if (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(); diff --git a/src/debug/debug.cpp b/src/debug/debug.cpp index b39a7ad..2804a5b 100644 --- a/src/debug/debug.cpp +++ b/src/debug/debug.cpp @@ -9,16 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.52 2004/01/27 14:52:28 qbix79 Exp $ */ - -#include "programs.h" +/* $Id: debug.cpp,v 1.59 2004/08/31 23:11:35 harekiet Exp $ */ #include #include @@ -26,19 +24,21 @@ #include "dosbox.h" #if C_DEBUG #include "debug.h" +#include "cross.h" //snprintf #include "cpu.h" #include "video.h" #include "pic.h" -#include "keyboard.h" +#include "mapper.h" #include "cpu.h" #include "callback.h" #include "inout.h" #include "mixer.h" -#include "debug_inc.h" #include "timer.h" #include "paging.h" -#include "../ints/xms.h" +#include "support.h" #include "shell.h" +#include "programs.h" +#include "debug_inc.h" #ifdef WIN32 void WIN32_Console(); @@ -53,13 +53,17 @@ int old_cursor_state; static void DrawCode(void); static bool DEBUG_Log_Loop(int count); static void DEBUG_RaiseTimerIrq(void); +static void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num); +static void LogGDT(void); +static void LogLDT(void); +static void LogIDT(void); +static void OutputVecTable(char* filename); +static void DrawVariables(void); + char* AnalyzeInstruction(char* inst, bool saveSelector); -void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num); Bit32u GetHexValue(char* str, char*& hex); -void LogGDT(void); -void LogLDT(void); -void LogIDT(void); -void OutputVecTable(char* filename); + + class DEBUG; @@ -67,6 +71,7 @@ DEBUG* pDebugcom = 0; bool exitLoop = false; bool logHeavy = false; + // Heavy Debugging Vars for logging #if C_HEAVY_DEBUG static FILE* cpuLogFile = 0; @@ -74,6 +79,8 @@ static bool cpuLog = false; static int cpuLogCounter = 0; #endif + + static struct { Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip; } oldregs; @@ -86,6 +93,8 @@ 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));} @@ -535,35 +544,26 @@ void CBreakpoint::ShowList(void) bool DEBUG_Breakpoint(void) { /* First get the phyiscal address and check for a set Breakpoint */ -// PhysPt where=SegPhys(cs)+reg_eip-1; - PhysPt where=GetAddress(SegValue(cs),reg_eip-1); - if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip-1)) return false; + PhysPt where=GetAddress(SegValue(cs),reg_eip); + if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) return false; // Found. Breakpoint is valid - reg_eip -= 1; CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints -// exitLoop = true; -// DEBUG_Enable(); return true; }; bool DEBUG_IntBreakpoint(Bit8u intNum) { /* First get the phyiscal address and check for a set Breakpoint */ -// PhysPt where=SegPhys(cs)+reg_eip-2; - PhysPt where=GetAddress(SegValue(cs),reg_eip-2); + PhysPt where=GetAddress(SegValue(cs),reg_eip); if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah)) return false; // Found. Breakpoint is valid - reg_eip -= 2; CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints -// exitLoop = true; -// DEBUG_Enable(); return true; }; static bool StepOver() { exitLoop = false; -// PhysPt start=SegPhys(cs)+reg_eip; PhysPt start=GetAddress(SegValue(cs),reg_eip); char dline[200];Bitu size; size=DasmI386(dline, start, reg_eip, cpu.code.big); @@ -581,6 +581,10 @@ static bool StepOver() bool DEBUG_ExitLoop(void) { +#if C_HEAVY_DEBUG + DrawVariables(); +#endif + if (exitLoop) { exitLoop = false; return true; @@ -911,6 +915,30 @@ bool ParseCommand(char* str) else DEBUG_ShowMsg("DEBUG: Variable list load (%s) : failure",name); return true; } + found = strstr(str,"SR "); + if (found) { // Set register value + found+=2; + if (ChangeRegister(found)) DEBUG_ShowMsg("DEBUG: Set Register success."); + else DEBUG_ShowMsg("DEBUG: Set Register failure."); + return true; + } + found = strstr(str,"SM "); + if (found) { // Set memory with following values + found+=3; + 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); found++; + mem_writeb(GetAddress(seg,ofs+count),value); + count++; + } + }; + DEBUG_ShowMsg("DEBUG: Memory changed."); + return true; + } found = strstr(str,"BP "); if (found) { // Add new breakpoint @@ -1025,30 +1053,6 @@ bool ParseCommand(char* str) return true; } #endif - found = strstr(str,"SR "); - if (found) { // Set register value - found+=2; - if (ChangeRegister(found)) DEBUG_ShowMsg("DEBUG: Set Register success."); - else DEBUG_ShowMsg("DEBUG: Set Register failure."); - return true; - } - found = strstr(str,"SM "); - if (found) { // Set memory with following values - found+=3; - 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); found++; - mem_writeb(GetAddress(seg,ofs+count),value); - count++; - } - }; - DEBUG_ShowMsg("DEBUG: Memory changed."); - return true; - } found = strstr(str,"INTT "); if (found) { // Create Cpu log file found+=4; @@ -1433,6 +1437,7 @@ Bitu DEBUG_Loop(void) { 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); @@ -1455,13 +1460,14 @@ void DEBUG_DrawScreen(void) { DrawData(); DrawCode(); DrawRegisters(); + DrawVariables(); } static void DEBUG_RaiseTimerIrq(void) { PIC_ActivateIRQ(0); } -void LogGDT(void) +static void LogGDT(void) { char out1[512]; Descriptor desc; @@ -1480,7 +1486,7 @@ void LogGDT(void) }; }; -void LogLDT(void) +static void LogLDT(void) { char out1[512]; Descriptor desc; @@ -1501,7 +1507,7 @@ void LogLDT(void) }; }; -void LogIDT(void) +static void LogIDT(void) { char out1[512]; Descriptor desc; @@ -1681,8 +1687,7 @@ void DEBUG_Init(Section* sec) { MSG_Add("DEBUG_CONFIGFILE_HELP","Nothing to setup yet!\n"); DEBUG_DrawScreen(); /* Add some keyhandlers */ - KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable); - KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq); + MAPPER_AddHandler(DEBUG_Enable,MK_pause,0,"debugger","Debugger"); /* Clear the TBreakpoint list */ memset((void*)&codeViewData,0,sizeof(codeViewData)); /* setup debug.com */ @@ -1769,7 +1774,7 @@ bool CDebugVar::LoadVars(char* name) return true; }; -void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num) +static void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num) { FILE* f = fopen("MEMDUMP.TXT","wt"); if (!f) { @@ -1796,7 +1801,7 @@ void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num) DEBUG_ShowMsg("DEBUG: Memory dump success."); }; -void OutputVecTable(char* filename) +static void OutputVecTable(char* filename) { FILE* f = fopen(filename, "wt"); if (!f) @@ -1812,6 +1817,35 @@ void OutputVecTable(char* filename) DEBUG_ShowMsg("DEBUG: Interrupt vector table written to %s.", filename); } +#define DEBUG_VAR_BUF_LEN 16 +static void DrawVariables(void) +{ + std::list::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 = mem_readw(dv->GetAdr()); + 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 @@ -1892,9 +1926,9 @@ bool DEBUG_HeavyIsBreakpoint(void) } return false; }; - #endif // HEAVY DEBUG + #endif // DEBUG diff --git a/src/debug/debug_gui.cpp b/src/debug/debug_gui.cpp index deb4537..268fecf 100644 --- a/src/debug/debug_gui.cpp +++ b/src/debug/debug_gui.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -53,7 +53,7 @@ void DEBUG_ShowMsg(char * format,...) { va_end(msg); wprintw(dbg.win_out,"%10d: %s\n",cycle_count,buf); wrefresh(dbg.win_out); - if(debuglog) fprintf(debuglog,"%10d: %s\n",cycle_count,buf); + if(debuglog) fprintf(debuglog,"%10d: %s\n",cycle_count,buf); } void LOG::operator() (char* format, ...){ @@ -99,13 +99,15 @@ static void DrawBars(void) { attrset(COLOR_PAIR(PAIR_BLACK_BLUE)); } /* Show the Register bar */ - mvaddstr(dbg.win_reg->_begy-1,0,"---[F1](Register Overview)---"); + 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,"---[F2](Data Overview)---"); + mvaddstr(dbg.win_data->_begy-1,0,"---(Data Overview)---"); /* Show the Code Overview perhaps with special stuff in bar too */ - mvaddstr(dbg.win_code->_begy-1,0,"---[F3](Code Overview)---"); + mvaddstr(dbg.win_code->_begy-1,0,"---(Code Overview)---"); + /* 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,"---[F4](OutPut/Input)---"); + mvaddstr(dbg.win_out->_begy-1,0,"---(OutPut/Input)---"); attrset(0); } @@ -124,7 +126,10 @@ static void MakeSubWindows(void) { /* The Code Window */ dbg.win_code=subwin(dbg.win_main,11,dbg.win_main->_maxx,outy,0); outy+=12; - /* The output Window */ + /* The Variable Window */ + dbg.win_var=subwin(dbg.win_main,4,dbg.win_main->_maxx,outy,0); + outy+=5; + /* 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); diff --git a/src/debug/debug_inc.h b/src/debug/debug_inc.h index 41524ab..713e957 100644 --- a/src/debug/debug_inc.h +++ b/src/debug/debug_inc.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -17,6 +17,9 @@ */ /* Local Debug Function */ + +/* $Id: debug_inc.h,v 1.8 2004/08/28 12:51:35 qbix79 Exp $ */ + #include #include "mem.h" @@ -34,6 +37,7 @@ struct DBGBlock { 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; diff --git a/src/debug/debug_win32.cpp b/src/debug/debug_win32.cpp index 2da75fe..d1302f9 100644 --- a/src/debug/debug_win32.cpp +++ b/src/debug/debug_win32.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/debug/disasm_tables.h b/src/debug/disasm_tables.h index 9a080f2..ac1798a 100644 --- a/src/debug/disasm_tables.h +++ b/src/debug/disasm_tables.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/dos/Makefile.am b/src/dos/Makefile.am index 7bd9b5a..4d206c7 100644 --- a/src/dos/Makefile.am +++ b/src/dos/Makefile.am @@ -4,6 +4,6 @@ noinst_LIBRARIES = libdos.a EXTRA_DIST = scsidefs.h wnaspi32.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 \ - dev_con.h dos_mscdex.cpp \ - cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.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 \ + cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp diff --git a/src/dos/Makefile.in b/src/dos/Makefile.in index c1d0fb9..1d83feb 100644 --- a/src/dos/Makefile.in +++ b/src/dos/Makefile.in @@ -135,9 +135,9 @@ noinst_LIBRARIES = libdos.a EXTRA_DIST = scsidefs.h wnaspi32.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 \ - dev_con.h dos_mscdex.cpp \ - cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.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 \ + cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp subdir = src/dos ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -153,9 +153,10 @@ am_libdos_a_OBJECTS = dos.$(OBJEXT) dos_devices.$(OBJEXT) \ dos_memory.$(OBJEXT) dos_misc.$(OBJEXT) dos_classes.$(OBJEXT) \ dos_programs.$(OBJEXT) dos_tables.$(OBJEXT) drives.$(OBJEXT) \ drive_virtual.$(OBJEXT) drive_local.$(OBJEXT) \ - drive_cache.$(OBJEXT) dos_mscdex.$(OBJEXT) cdrom.$(OBJEXT) \ + drive_cache.$(OBJEXT) drive_fat.$(OBJEXT) drive_iso.$(OBJEXT) \ + dos_mscdex.$(OBJEXT) cdrom.$(OBJEXT) \ cdrom_ioctl_win32.$(OBJEXT) cdrom_aspi_win32.$(OBJEXT) \ - cdrom_ioctl_linux.$(OBJEXT) + cdrom_ioctl_linux.$(OBJEXT) cdrom_image.$(OBJEXT) libdos_a_OBJECTS = $(am_libdos_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) @@ -163,6 +164,7 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/cdrom.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/cdrom_aspi_win32.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_image.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_linux.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_win32.Po ./$(DEPDIR)/dos.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_classes.Po \ @@ -172,8 +174,8 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@ ./$(DEPDIR)/dos_misc.Po ./$(DEPDIR)/dos_mscdex.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_programs.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_tables.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/drive_cache.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/drive_local.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/drive_cache.Po ./$(DEPDIR)/drive_fat.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/drive_iso.Po ./$(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) @@ -215,6 +217,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_aspi_win32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_image.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_ioctl_linux.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_ioctl_win32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos.Po@am__quote@ @@ -229,6 +232,8 @@ distclean-compile: @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_cache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_fat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_iso.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@ diff --git a/src/dos/cdrom.cpp b/src/dos/cdrom.cpp index 423b8bc..9663313 100644 --- a/src/dos/cdrom.cpp +++ b/src/dos/cdrom.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -21,6 +21,11 @@ // SDL CDROM // ****************************************************** +#include +#include +#include +#include +#include "dosbox.h" #include "SDL.h" #include "support.h" #include "cdrom.h" @@ -175,8 +180,13 @@ int CDROM_GetMountType(char* path, int forceCD) cdName = SDL_CDName(i); if (strcmp(buffer,cdName)==0) return 0; }; - // TODO: Detect ISO - return 2; + + // Detect ISO + struct stat file_stat; + stat(path, &file_stat); + if (S_ISREG(file_stat.st_mode)) return 1; + + return 2; }; // ****************************************************** diff --git a/src/dos/cdrom.h b/src/dos/cdrom.h index 0159d86..c438209 100644 --- a/src/dos/cdrom.h +++ b/src/dos/cdrom.h @@ -5,10 +5,17 @@ #define MAX_ASPI_CDROM 5 #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 @@ -46,26 +53,28 @@ public: 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); - ~CDROM_Interface_SDL (void); + virtual ~CDROM_Interface_SDL(void); - bool SetDevice (char* path, int forceCD); - 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); - bool PauseAudio (bool resume); - bool StopAudio (void); - bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return false; }; - bool LoadUnloadMedia (bool unload); + 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); @@ -93,6 +102,106 @@ public: 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; + }; + + 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); + +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; + std::string mcn; + Bit8u subUnit; +}; + #if defined (WIN32) /* Win 32 */ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers @@ -104,7 +213,7 @@ class CDROM_Interface_Aspi : public CDROM_Interface { public: CDROM_Interface_Aspi (void); - ~CDROM_Interface_Aspi (void); + virtual ~CDROM_Interface_Aspi(void); bool SetDevice (char* path, int forceCD); @@ -151,7 +260,7 @@ class CDROM_Interface_Ioctl : public CDROM_Interface { public: CDROM_Interface_Ioctl (void); - ~CDROM_Interface_Ioctl (void); + virtual ~CDROM_Interface_Ioctl(void); bool SetDevice (char* path, int forceCD); @@ -171,6 +280,7 @@ public: bool LoadUnloadMedia (bool unload); + void InitNewMedia (void) { Close(); Open(); }; private: bool Open (void); diff --git a/src/dos/cdrom_aspi_win32.cpp b/src/dos/cdrom_aspi_win32.cpp index 7e547ce..f84dbda 100644 --- a/src/dos/cdrom_aspi_win32.cpp +++ b/src/dos/cdrom_aspi_win32.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.10 2004/01/10 14:03:34 qbix79 Exp $ */ +/* $Id: cdrom_aspi_win32.cpp,v 1.12 2004/08/04 09:12:53 qbix79 Exp $ */ #if defined (WIN32) @@ -39,6 +39,19 @@ #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) // ***************************************************************** @@ -78,34 +91,34 @@ bool GetRegistryValue(HKEY& hKey,char* valueName, char* buffer, ULONG bufferSize BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID) { - SRB_HAInquiry sh; - SRB_GDEVBlock sd; + ASPI_SRB sh; + ASPI_SRB sd; DWORD d = pGetASPI32SupportInfo(); int cnt = LOBYTE(LOWORD(d)); int i,j,k,max; for(i=0; i> 24) & 0xFF); - s.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF); - s.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF); - s.CDBByte[5] = (unsigned char)((start & 0xFF)); - s.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF); - s.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF); - s.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF); - s.CDBByte[9] = (unsigned char)(len & 0xFF); + 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); @@ -441,7 +459,7 @@ bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len CloseHandle(hEvent); - return s.SRB_Status==SS_COMP; + return s.execscsicmd.SRB_Status==SS_COMP; } bool CDROM_Interface_Aspi::StopAudio(void) @@ -451,23 +469,25 @@ bool CDROM_Interface_Aspi::StopAudio(void) bool CDROM_Interface_Aspi::PauseAudio(bool resume) { - SRB_ExecSCSICmd s;DWORD dwStatus; + //SRB_ExecSCSICmd s; + ASPI_SRB s; + DWORD dwStatus; hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); memset(&s,0,sizeof(s)); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaId = haId; - s.SRB_Target = target; - s.SRB_Lun = lun; - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_BufLen = 0x00; - s.SRB_SenseLen = SENSE_LEN; - s.SRB_CDBLen = 0x0A; - s.SRB_PostProc = (LPVOID)hEvent; - s.CDBByte[0] = 0x4B; - s.CDBByte[8] = (unsigned char)resume; // Pause + 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); @@ -476,37 +496,39 @@ bool CDROM_Interface_Aspi::PauseAudio(bool resume) CloseHandle(hEvent); - return (s.SRB_Status==SS_COMP); + 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;DWORD dwStatus; +// SRB_ExecSCSICmd s; + ASPI_SRB s; + DWORD dwStatus; hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); memset(&s,0,sizeof(s)); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaId = haId; - s.SRB_Target = target; - s.SRB_Lun = lun; - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_SenseLen = SENSE_LEN; + 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.SRB_BufLen = sizeof(pos); - s.SRB_BufPointer = (BYTE FAR *)&pos; - s.SRB_CDBLen = 10; - s.SRB_PostProc = (LPVOID)hEvent; + 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.CDBByte[0] = SCSI_SUBCHANNEL; - s.CDBByte[1] = (lun<<5)|2; // lun & msf - s.CDBByte[2] = 0x40; // subq - s.CDBByte[3] = 0x01; // curr pos info - s.CDBByte[6] = 0; // track number (only in isrc mode, ignored) - s.CDBByte[7] = 0; // alloc len - s.CDBByte[8] = sizeof(pos); + 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); @@ -516,7 +538,7 @@ bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track CloseHandle(hEvent); - if (s.SRB_Status!=SS_COMP) return false; + if (s.execscsicmd.SRB_Status!=SS_COMP) return false; attr = (pos.Control<<4) &0xEF; track = pos.TrackNumber; @@ -534,31 +556,33 @@ bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata) { SUB_Q_MEDIA_CATALOG_NUMBER upc; - SRB_ExecSCSICmd s;DWORD dwStatus; + ASPI_SRB s; + //SRB_ExecSCSICmd s; + DWORD dwStatus; hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); memset(&s,0,sizeof(s)); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaId = haId; - s.SRB_Target = target; - s.SRB_Lun = lun; - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_SenseLen = SENSE_LEN; + 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.SRB_BufLen = sizeof(upc); - s.SRB_BufPointer = (BYTE FAR *)&upc; - s.SRB_CDBLen = 10; - s.SRB_PostProc = (LPVOID)hEvent; + 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.CDBByte[0] = SCSI_SUBCHANNEL; - s.CDBByte[1] = (lun<<5)|2; // lun & msf - s.CDBByte[2] = 0x40; // subq - s.CDBByte[3] = 0x02; // get upc - s.CDBByte[6] = 0; // track number (only in isrc mode, ignored) - s.CDBByte[7] = 0; // alloc len - s.CDBByte[8] = sizeof(upc); + 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); @@ -568,15 +592,14 @@ bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata) CloseHandle(hEvent); - if (s.SRB_Status!=SS_COMP) return false; + if (s.execscsicmd.SRB_Status!=SS_COMP) return false; // attr = (upc.ADR<<4) | upc.Control; attr = 0; int pos = 0; // Convert to mscdex format -// for (int i=0; i<6; i++) upcdata[i] = (upc.MediaCatalog[pos++]<<4)+(upc.MediaCatalog[pos++]&0x0F); -// upcdata[6] = (upc.MediaCatalog[pos++]<<4); 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; }; @@ -586,31 +609,33 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause) playing = pause = false; SUB_Q_HEADER sub; - SRB_ExecSCSICmd s;DWORD dwStatus; +// SRB_ExecSCSICmd s; + ASPI_SRB s; + DWORD dwStatus; hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); memset(&s,0,sizeof(s)); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaId = haId; - s.SRB_Target = target; - s.SRB_Lun = lun; - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_SenseLen = SENSE_LEN; + 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.SRB_BufLen = sizeof(sub); - s.SRB_BufPointer = (BYTE FAR *)⊂ - s.SRB_CDBLen = 10; - s.SRB_PostProc = (LPVOID)hEvent; + s.execscsicmd.SRB_BufLen = sizeof(sub); + s.execscsicmd.SRB_BufPointer = (BYTE FAR *)⊂ + s.execscsicmd.SRB_CDBLen = 10; + s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - s.CDBByte[0] = SCSI_SUBCHANNEL; - s.CDBByte[1] = (lun<<5)|2; // lun & msf - s.CDBByte[2] = 0x00; // no subq - s.CDBByte[3] = 0x00; // dont care - s.CDBByte[6] = 0; // track number (only in isrc mode, ignored) - s.CDBByte[7] = 0; // alloc len - s.CDBByte[8] = sizeof(sub); + 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); @@ -620,7 +645,7 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause) CloseHandle(hEvent); - if (s.SRB_Status!=SS_COMP) return false; + if (s.execscsicmd.SRB_Status!=SS_COMP) return false; playing = (sub.AudioStatus==0x11); pause = (sub.AudioStatus==0x12); @@ -630,27 +655,29 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause) bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload) { - SRB_ExecSCSICmd s;DWORD dwStatus; + //SRB_ExecSCSICmd s; + ASPI_SRB s; + DWORD dwStatus; hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); memset(&s,0,sizeof(s)); - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaId = haId; - s.SRB_Target = target; - s.SRB_Lun = lun; - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_SenseLen = SENSE_LEN; + 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.SRB_BufLen = 0; - s.SRB_BufPointer = 0; - s.SRB_CDBLen = 14; - s.SRB_PostProc = (LPVOID)hEvent; + s.execscsicmd.SRB_BufLen = 0; + s.execscsicmd.SRB_BufPointer = 0; + s.execscsicmd.SRB_CDBLen = 6; // 14; + s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - s.CDBByte[0] = SCSI_LOAD_UN; - s.CDBByte[1] = (lun<<5)|1; // lun & immediate - s.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media + 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); @@ -660,7 +687,7 @@ bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload) CloseHandle(hEvent); - if (s.SRB_Status!=SS_COMP) return false; + if (s.execscsicmd.SRB_Status!=SS_COMP) return false; return true; }; @@ -684,7 +711,9 @@ bool CDROM_Interface_Aspi::GetMediaTrayStatus(bool& mediaPresent, bool& mediaCha bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { - SRB_ExecSCSICmd s;DWORD dwStatus; + //SRB_ExecSCSICmd s; + ASPI_SRB s; + DWORD dwStatus; hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); @@ -693,27 +722,27 @@ bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long se Bitu buflen = raw?2352*num:2048*num; Bit8u* bufdata = new Bit8u[buflen]; - s.SRB_Cmd = SC_EXEC_SCSI_CMD; - s.SRB_HaId = haId; - s.SRB_Target = target; - s.SRB_Lun = lun; - s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - s.SRB_SenseLen = SENSE_LEN; + 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.SRB_BufLen = buflen; - s.SRB_BufPointer = (BYTE FAR*)bufdata; - s.SRB_CDBLen = 12; - s.SRB_PostProc = (LPVOID)hEvent; + s.execscsicmd.SRB_BufLen = buflen; + s.execscsicmd.SRB_BufPointer = (BYTE FAR*)bufdata; + s.execscsicmd.SRB_CDBLen = 12; + s.execscsicmd.SRB_PostProc = (LPVOID)hEvent; - s.CDBByte[0] = 0xBE; - s.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF); - s.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF); - s.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF); - s.CDBByte[5] = (unsigned char)((sector & 0xFF)); - s.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF); - s.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF); - s.CDBByte[8] = (unsigned char) (num & 0xFF); - s.CDBByte[9] = (raw?0xF0:0x10); + 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); @@ -728,7 +757,7 @@ bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long se delete[] bufdata; - return (s.SRB_Status==SS_COMP); + return (s.execscsicmd.SRB_Status==SS_COMP); }; #endif diff --git a/src/dos/cdrom_image.cpp b/src/dos/cdrom_image.cpp new file mode 100644 index 0000000..9d88d32 --- /dev/null +++ b/src/dos/cdrom_image.cpp @@ -0,0 +1,651 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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.3 2004/08/23 09:35:15 harekiet Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cdrom.h" +#include "drives.h" + +#if !defined(WIN32) +#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 = 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, 0, false, false }; + + +CDROM_Interface_Image::CDROM_Interface_Image(Bit8u subUnit) +{ + images[subUnit] = this; + if (refCount == 0) { +#if defined(C_SDL_SOUND) + Sound_Init(); +#endif + 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) { +#if defined(C_SDL_SOUND) + Sound_Quit(); +#endif + 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 = 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 = 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 > 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) +{ + track = GetTrack(player.currFrame); + if (track < 1) return false; + 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; + for(int i = 0; i < num; i++) { + success = ReadSector(&buf[i * sectorSize], raw, sector); + 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 < 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_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 = 4; + + // 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); +} + +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 + strncpy(tmp, cuefile, MAX_FILENAME_LENGTH); +#if defined(WIN32) + string pathname(""); +#else + string pathname(dirname(tmp)); +#endif + 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 = 4; + track.mode2 = false; + } else if (type == "MODE1/2352") { + track.sectorSize = RAW_SECTOR_SIZE; + track.attr = 4; + track.mode2 = false; + } else if (type == "MODE2/2336") { + track.sectorSize = 2336; + track.attr = 4; + track.mode2 = true; + } else if (type == "MODE2/2352") { + track.sectorSize = RAW_SECTOR_SIZE; + track.attr = 4; + 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.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::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 +#if not defined(WIN32) + string tmpstr(pathname + "/" + filename); + if (stat(tmpstr.c_str(), &test) == 0) { + filename = tmpstr; + return true; + } +#endif + // finally check if file is in a dosbox local drive + char fullname[CROSS_LEN]; + char tmp[CROSS_LEN]; + strncpy(tmp, filename.c_str(), CROSS_LEN); + Bit8u drive; + if (!DOS_MakeName(tmp, fullname, &drive)) return false; + + localDrive *ldp = (localDrive*)Drives[drive]; + 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(int 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 = 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(); +} diff --git a/src/dos/cdrom_ioctl_linux.cpp b/src/dos/cdrom_ioctl_linux.cpp index f505079..fe5eac3 100644 --- a/src/dos/cdrom_ioctl_linux.cpp +++ b/src/dos/cdrom_ioctl_linux.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/dos/cdrom_ioctl_win32.cpp b/src/dos/cdrom_ioctl_win32.cpp index f73f9c0..cc5adaa 100644 --- a/src/dos/cdrom_ioctl_win32.cpp +++ b/src/dos/cdrom_ioctl_win32.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.10 2004/01/10 14:03:34 qbix79 Exp $ */ +/* $Id: cdrom_ioctl_win32.cpp,v 1.11 2004/08/04 09:12:53 qbix79 Exp $ */ #if defined (WIN32) diff --git a/src/dos/dev_con.h b/src/dos/dev_con.h index c204eae..5c78ea3 100644 --- a/src/dos/dev_con.h +++ b/src/dos/dev_con.h @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.16 2004/01/10 14:03:34 qbix79 Exp $ */ +/* $Id: dev_con.h,v 1.18 2004/08/26 19:41:20 qbix79 Exp $ */ #include "dos_inc.h" #include "../ints/int10.h" @@ -31,22 +31,22 @@ public: bool Write(Bit8u * data,Bit16u * size); bool Seek(Bit32u * pos,Bit32u type); bool Close(); - void ClearAnsi(void); + void ClearAnsi(void); Bit16u GetInformation(void); private: Bit8u cache; - struct ansi { /* should create a constructor which fills them with the appriorate values */ - bool esc; - bool sci; + 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; - } ansi; + Bit8u attr; + Bit8u data[NUMBER_ANSI_DATA]; + Bit8u numberofarg; + Bit16u nrows; + Bit16u ncols; + Bit8s savecol; + Bit8s saverow; + } ansi; }; @@ -55,11 +55,8 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { Bit16u count=0; if ((cache) && (*size)) { data[count++]=cache; - if(dos.echo) { - INT10_TeletypeOutput(cache,7); - } - cache=0; - + if(dos.echo) INT10_TeletypeOutput(cache,7); + cache=0; } while (*size>count) { reg_ah=0; @@ -68,25 +65,24 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { 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; + *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); - } + 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; + 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; default: data[count++]=reg_al; break; @@ -95,11 +91,10 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { if (*size>count) data[count++]=reg_ah; else cache=reg_ah; break; - - } - if(dos.echo) { //what to do if *size==1 and character is BS ????? - INT10_TeletypeOutput(reg_al,7); - } + } + if(dos.echo) { //what to do if *size==1 and character is BS ????? + INT10_TeletypeOutput(reg_al,7); + } } *size=count; reg_ax=oldax; @@ -109,243 +104,235 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { bool device_CON::Write(Bit8u * data,Bit16u * size) { Bit16u count=0; - Bitu i; - Bit8u col,row; + 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 { - // pass attribute only if ansi is enabled + while (*size>count) { + if (!ansi.esc){ + if(data[count]=='\033') { + /*clear the datastructure */ + ClearAnsi(); + /* start the sequence */ + ansi.esc=true; + count++; + continue; + } else { + /* pass attribute only if ansi is enabled */ INT10_TeletypeOutputAttr(data[count],ansi.attr,ansi.enabled); count++; continue; - }; - }; + } + } - if(!ansi.sci){ + 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 */ - 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++){ + 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 */ + 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=0x7; + 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|=0x8; - break; - case 4: /* underline */ - LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet"); - break; - case 5: /* blinking */ - LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for blinking yet"); - break; - case 7: /* reverse */ - LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for reverse yet"); - 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; + 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.data[0]==0) ansi.data[0]=1; + if(ansi.data[1]==0) ansi.data[1]=1; + INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),0); /*ansi=1 based, int10 is 0 based */ + ClearAnsi(); + break; - } - } - ClearAnsi(); - break; - case 'f': - case 'H':/* Cursor Pos*/ - if(ansi.data[0]==0) ansi.data[0]=1; - if(ansi.data[1]==0) ansi.data[1]=1; - INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),0); /*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(0) ; - row=CURSOR_POS_ROW(0) ; + case 'A': /* cursor up*/ + col=CURSOR_POS_COL(0) ; + row=CURSOR_POS_ROW(0) ; tempdata = (ansi.data[0]? ansi.data[0] : 1); - if(tempdata > row) - { row=0; } - else - { row-=tempdata;} + if(tempdata > row) { row=0; } + else { row-=tempdata;} INT10_SetCursorPos(row,col,0); - ClearAnsi(); - break; + ClearAnsi(); + break; case 'B': /*cursor Down */ col=CURSOR_POS_COL(0) ; - row=CURSOR_POS_ROW(0) ; + row=CURSOR_POS_ROW(0) ; 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,0); - ClearAnsi(); + { row = ansi.nrows - 1;} + else { row += tempdata; } + INT10_SetCursorPos(row,col,0); + ClearAnsi(); break; - case 'C': /*cursor forward */ - col=CURSOR_POS_COL(0); + case 'C': /*cursor forward */ + col=CURSOR_POS_COL(0); row=CURSOR_POS_ROW(0); - 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,0); - ClearAnsi(); - break; - case 'D': /*Cursor Backward */ - col=CURSOR_POS_COL(0); - row=CURSOR_POS_ROW(0); tempdata=(ansi.data[0]? ansi.data[0] : 1); - if(tempdata > col) - {col = 0;} - else - { col -= tempdata;} - INT10_SetCursorPos(row,col,0); - ClearAnsi(); - break; - case 'J': /*erase screen and move cursor home*/ - if(ansi.data[0]==0) ansi.data[0]=2; - if(ansi.data[0]!=2) {/* only number 2 (the standard one supported) */ - LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported",ansi.data[0]); - break; - } - for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true); - ClearAnsi(); - INT10_SetCursorPos(0,0,0); - 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,0); - ClearAnsi(); - break; - case 's': /* SAVE CURSOR POS */ - ansi.savecol=CURSOR_POS_COL(0); - ansi.saverow=CURSOR_POS_ROW(0); - ClearAnsi(); - break; - case 'K':/* erase till end of line */ - for(i = CURSOR_POS_COL(0);i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true); - ClearAnsi(); /* maybe set cursor back to starting place ???? */ + if(tempdata + static_cast(col) >= ansi.ncols) + { col = ansi.ncols - 1;} + else { col += tempdata;} + INT10_SetCursorPos(row,col,0); + 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++; + case 'D': /*Cursor Backward */ + col=CURSOR_POS_COL(0); + row=CURSOR_POS_ROW(0); + tempdata=(ansi.data[0]? ansi.data[0] : 1); + if(tempdata > col) {col = 0;} + else { col -= tempdata;} + INT10_SetCursorPos(row,col,0); + ClearAnsi(); + break; + case 'J': /*erase screen and move cursor home*/ + if(ansi.data[0]==0) ansi.data[0]=2; + if(ansi.data[0]!=2) {/* only number 2 (the standard one supported) */ + LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported",ansi.data[0]); + break; + } + for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true); + ClearAnsi(); + INT10_SetCursorPos(0,0,0); + 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,0); + ClearAnsi(); + break; + case 's': /* SAVE CURSOR POS */ + ansi.savecol=CURSOR_POS_COL(0); + ansi.saverow=CURSOR_POS_ROW(0); + ClearAnsi(); + break; + case 'K':/* erase till end of line */ + for(i = CURSOR_POS_COL(0);i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true); + ClearAnsi(); /* maybe set cursor back to starting place ???? */ + 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; @@ -372,22 +359,18 @@ Bit16u device_CON::GetInformation(void) { device_CON::device_CON() { name="CON"; cache=0; - ansi.esc=false; - ansi.sci=false; ansi.enabled=false; - ansi.attr=0x7; - ansi.numberofarg=0; - for(Bit8u i=0; i #include @@ -45,20 +45,20 @@ void DOS_SetError(Bit16u code) { #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-20)); + DOS_PSP psp(dos.psp()); + psp.SetStack(RealMake(SegValue(ss),reg_sp-18)); } + char name1[DOSNAMEBUF+1]; char name2[DOSNAMEBUF+1]; switch (reg_ah) { case 0x01: /* Read character from STDIN, with echo */ { Bit8u c;Bit16u n=1; - dos.echo=true; + dos.echo=true; DOS_ReadFile(STDIN,&c,&n); reg_al=c; - dos.echo=false; - + dos.echo=false; } break; case 0x02: /* Write character to STDOUT */ @@ -181,7 +181,7 @@ static Bitu DOS_21Handler(void) { break; case 0x10: /* Close File using FCB */ if(DOS_FCBClose(SegValue(ds),reg_dx)){ - reg_al=0; + reg_al=0; }else{ reg_al=0xff; } @@ -189,7 +189,7 @@ static Bitu DOS_21Handler(void) { break; case 0x11: /* Find First Matching File using FCB */ if(DOS_FCBFindFirst(SegValue(ds),reg_dx)){ - reg_al=0; + reg_al=0; }else{ reg_al=0xff; } @@ -197,7 +197,7 @@ static Bitu DOS_21Handler(void) { break; case 0x12: /* Find Next Matching File using FCB */ if(DOS_FCBFindNext(SegValue(ds),reg_dx)){ - reg_al=0; + reg_al=0; }else{ reg_al=0xff; } @@ -254,29 +254,26 @@ static Bitu DOS_21Handler(void) { 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,1024); - reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference); - reg_si+=difference; - } + { + Bit8u difference; + char string[1024]; + MEM_StrCopy(SegPhys(ds)+reg_si,string,1024); + 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; + 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); - DOS_PSP psp(dos.psp); - psp.SetDTA(dos.dta); - } + 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()); + DOS_NewPSP(reg_dx,DOS_PSP(dos.psp()).GetSize()); break; case 0x2a: /* Get System Date */ { @@ -319,29 +316,43 @@ static Bitu DOS_21Handler(void) { dos.verify=(reg_al==1); break; case 0x2f: /* Get Disk Transfer Area */ - SegSet16(es,RealSeg(dos.dta)); - reg_bx=RealOff(dos.dta); + 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_ResizeMemory(dos.psp(),®_dx); DOS_Terminate(true); - dos.return_code=reg_al; + dos.return_code=reg_al; //Officially a field in the SDA dos.return_mode=RETURN_TSR; break; + 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) drive=dos.current_drive;else drive--; + if(Drives[drive]) { + reg_al=0x00; + 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 5:reg_dl=3;break; /* Always boot from c: :) */ + 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; @@ -353,8 +364,8 @@ static Bitu DOS_21Handler(void) { } break; case 0x34: /* Get INDos Flag */ - SegSet16(es,RealSeg(dos.tables.indosflag)); - reg_bx=RealOff(dos.tables.indosflag); + 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); @@ -363,8 +374,8 @@ static Bitu DOS_21Handler(void) { case 0x36: /* Get Free Disk Space */ { Bit16u bytes,clusters,free; - Bit8u sectors; - if (DOS_GetFreeDiskSpace(reg_dl,&bytes,§ors,&clusters,&free)) { + Bit8u sectors; + if(DOS_GetFreeDiskSpace(reg_dl,&bytes,§ors,&clusters,&free)) { reg_ax=sectors; reg_bx=free; reg_cx=bytes; @@ -466,7 +477,7 @@ static Bitu DOS_21Handler(void) { case 0x3f: /* READ Read from file or device */ { Bit16u toread=reg_cx; - dos.echo=true; + dos.echo=true; if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) { MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread); reg_ax=toread; @@ -475,7 +486,7 @@ static Bitu DOS_21Handler(void) { reg_ax=dos.errorcode; CALLBACK_SCF(true); } - dos.echo=false; + dos.echo=false; break; } case 0x40: /* WRITE Write to file or device */ @@ -621,7 +632,7 @@ static Bitu DOS_21Handler(void) { break; //TODO Check for use of execution state AL=5 case 0x00: - reg_ax=0x4c00; /* Terminate Program */ + reg_ax=0x4c00; /* Terminate Program */ case 0x4c: /* EXIT Terminate with return code */ { @@ -634,7 +645,7 @@ static Bitu DOS_21Handler(void) { break; } case 0x4d: /* Get Return code */ - reg_al=dos.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 */ @@ -650,17 +661,18 @@ static Bitu DOS_21Handler(void) { case 0x4f: /* FINDNEXT Find next matching file */ if (DOS_FindNext()) { CALLBACK_SCF(false); - reg_ax=0xffff; /* Undocumented */ + /* 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; + dos.psp(reg_bx); break; case 0x51: /* Get current PSP */ - reg_bx=dos.psp; + reg_bx=dos.psp(); break; case 0x52: { /* Get list of lists */ RealPt addr=dos_infoblock.GetPointer(); @@ -671,14 +683,14 @@ static Bitu DOS_21Handler(void) { //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; + E_Exit("Unhandled Dos 21 call %02X",reg_ah); + break; case 0x54: /* Get verify flag */ - reg_al=dos.verify?1:0; + reg_al=dos.verify?1:0; break; case 0x55: /* Create Child PSP*/ DOS_ChildPSP(reg_dx,reg_si); - dos.psp = reg_dx; + dos.psp(reg_dx); break; case 0x56: /* RENAME Rename file */ MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); @@ -736,6 +748,7 @@ static Bitu DOS_21Handler(void) { MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); if (DOS_CreateTempFile(name1,&handle)) { reg_ax=handle; + MEM_BlockWrite(SegPhys(ds)+reg_dx,name1,strlen(name1)+1); CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; @@ -763,6 +776,19 @@ static Bitu DOS_21Handler(void) { } 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)) { @@ -774,7 +800,15 @@ static Bitu DOS_21Handler(void) { } break; case 0x62: /* Get Current PSP Address */ - reg_bx=dos.psp; + reg_bx=dos.psp(); + break; + case 0x63: /* DOUBLE BYTE CHARACTER SET */ + if(reg_al == 0) { + SegSet16(ds,RealSeg(dos.tables.dcbs)); + reg_si=RealOff(dos.tables.dcbs); + 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 */ E_Exit("Unhandled Dos 21 call %02X",reg_ah); @@ -787,10 +821,23 @@ static Bitu DOS_21Handler(void) { switch (reg_al) { case 1: mem_writeb(data,reg_al); - mem_writew(data+1,4); - mem_writew(data+3,1); - mem_writew(data+5,37); - reg_cx=4; + mem_writew(data+0x01,0x1c); + mem_writew(data+0x03,1); + mem_writew(data+0x05,0x01b5); + mem_writew(data+0x07,0x0000); // date format + mem_writeb(data+0x08,0x24); // currency symbol + mem_writew(data+0x0a,0x0000); + mem_writew(data+0x0c,0x0000); + mem_writew(data+0x0e,0x002c); // thousands separator + mem_writew(data+0x10,0x002e); // decimal separator + mem_writew(data+0x12,0x002d); // date separator + mem_writew(data+0x14,0x003a); // time separator + mem_writeb(data+0x16,0x00); // currency format + mem_writeb(data+0x17,0x02); // digits after decimal in currency + mem_writeb(data+0x18,0x00); // time format + mem_writed(data+0x19,CALLBACK_RealPointer(call_casemap)); + mem_writew(data+0x1d,0x002c); // list separator + reg_cx=0x1f; CALLBACK_SCF(false); break; case 2: // Get pointer to uppercase table @@ -799,9 +846,9 @@ static Bitu DOS_21Handler(void) { case 5: // Get pointer to filename terminator table case 6: // Get pointer to collating sequence table case 7: // Get pointer to double byte char set table - mem_writew(data ,0x0000); // We dont have this table... - mem_writew(data+2,0x0000); // End of table - reg_cx=4; + mem_writeb(data,reg_al); + mem_writed(data+1,dos.tables.dcbs); //used to be 0 + reg_cx=5; CALLBACK_SCF(false); break; default: @@ -821,7 +868,7 @@ static Bitu DOS_21Handler(void) { case 0x67: /* Set handle count */ /* Weird call to increase amount of file handles needs to allocate memory if >20 */ { - DOS_PSP psp(dos.psp); + DOS_PSP psp(dos.psp()); psp.SetNumFiles(reg_bx); CALLBACK_SCF(false); break; @@ -854,8 +901,8 @@ static Bitu DOS_21Handler(void) { CALLBACK_SCF(true); LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Windows long file name support call %2X",reg_al); break; + case 0x68: /* FFLUSH Commit file */ - case 0x63: /* Weirdo double byte stuff (fails but say it succeeded) available only in MSDOS 2.25 */ CALLBACK_SCF(false); //mirek case 0xE0: case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */ @@ -865,13 +912,10 @@ static Bitu DOS_21Handler(void) { case 0x6b: /* NULL Function */ case 0x61: /* UNUSED */ case 0xEF: /* Used in Ancient Art Of War CGA */ - case 0x5d: /* Network Functions ||HMMM seems to critical error info and return 1!! Maybe implement it.??*/ - /* al=06 clears cf and leaves al=6 and returns crit error flag location*/ case 0x1f: /* Get drive parameter block for default drive */ - case 0x32: /* Get drive parameter block for specific drive */ + case 0x5c: /* FLOCK File region locking */ case 0x5e: /* More Network Functions */ - case 0x5f: /* And Even 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 */ @@ -894,7 +938,7 @@ 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); + if (DOS_ResizeMemory(dos.psp(),¶)) DOS_Terminate(true); return CBRET_NONE; } static Bitu DOS_25Handler(void) { @@ -903,9 +947,10 @@ static Bitu DOS_25Handler(void) { SETFLAGBIT(CF,true); }else{ SETFLAGBIT(CF,false); - reg_ax=0; if((reg_cx != 1) ||(reg_dx != 1)) - LOG(LOG_DOSMISC,LOG_NORMAL)("int 25 called but not as diskdetection"); + LOG(LOG_DOSMISC,LOG_NORMAL)("int 25 called but not as diskdetection drive %X",reg_al); + + reg_ax=0; } return CBRET_NONE; } @@ -925,8 +970,14 @@ static Bitu DOS_28Handler(void) { } static Bitu DOS_29Handler(void) { - LOG(LOG_DOSMISC,LOG_ERROR)("int 29 called"); - return CBRET_NONE; + static bool int29warn=false; + if(!int29warn) { + LOG(LOG_DOSMISC,LOG_WARN)("Int 29 called. Redirecting to int 10:0x0e"); + int29warn=true; + } + reg_ah=0x0e; + CALLBACK_RunRealInt(0x10); + return CBRET_NONE; } static Bitu DOS_CaseMapFunc(void) { @@ -942,32 +993,32 @@ void DOS_ShutDown(Section* sec) void DOS_Init(Section* sec) { call_20=CALLBACK_Allocate(); - CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET); + CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET,"DOS Int 20"); RealSetVec(0x20,CALLBACK_RealPointer(call_20)); call_21=CALLBACK_Allocate(); - CALLBACK_Setup(call_21,DOS_21Handler,CB_IRET_STI); + CALLBACK_Setup(call_21,DOS_21Handler,CB_IRET_STI,"DOS Int 21"); RealSetVec(0x21,CALLBACK_RealPointer(call_21)); call_25=CALLBACK_Allocate(); - CALLBACK_Setup(call_25,DOS_25Handler,CB_RETF); + CALLBACK_Setup(call_25,DOS_25Handler,CB_RETF,"DOS Int 25"); RealSetVec(0x25,CALLBACK_RealPointer(call_25)); call_26=CALLBACK_Allocate(); - CALLBACK_Setup(call_26,DOS_26Handler,CB_RETF); + CALLBACK_Setup(call_26,DOS_26Handler,CB_RETF,"DOS Int 26"); RealSetVec(0x26,CALLBACK_RealPointer(call_26)); call_27=CALLBACK_Allocate(); - CALLBACK_Setup(call_27,DOS_27Handler,CB_IRET); + CALLBACK_Setup(call_27,DOS_27Handler,CB_IRET,"DOS Int 27"); RealSetVec(0x27,CALLBACK_RealPointer(call_27)); - call_28=CALLBACK_Allocate(); - CALLBACK_Setup(call_28,DOS_28Handler,CB_IRET); - RealSetVec(0x28,CALLBACK_RealPointer(call_28)); + call_28=CALLBACK_Allocate(); + CALLBACK_Setup(call_28,DOS_28Handler,CB_IRET,"DOS Int 28"); + RealSetVec(0x28,CALLBACK_RealPointer(call_28)); - call_29=CALLBACK_Allocate(); - CALLBACK_Setup(call_29,DOS_29Handler,CB_IRET); - RealSetVec(0x29,CALLBACK_RealPointer(call_29)); + call_29=CALLBACK_Allocate(); + CALLBACK_Setup(call_29,DOS_29Handler,CB_IRET,"CON Output Int 29"); + RealSetVec(0x29,CALLBACK_RealPointer(call_29)); DOS_SetupFiles(); /* Setup system File tables */ DOS_SetupDevices(); /* Setup dos devices */ @@ -995,6 +1046,6 @@ void DOS_Init(Section* sec) { /* case map routine INT 0x21 0x38 */ call_casemap = CALLBACK_Allocate(); - CALLBACK_Setup(call_casemap,DOS_CaseMapFunc,CB_RETF); + CALLBACK_Setup(call_casemap,DOS_CaseMapFunc,CB_RETF,"DOS CaseMap"); } diff --git a/src/dos/dos_classes.cpp b/src/dos/dos_classes.cpp index 100d216..3ac24c0 100644 --- a/src/dos/dos_classes.cpp +++ b/src/dos/dos_classes.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.33 2004/01/10 14:03:34 qbix79 Exp $ */ +/* $Id: dos_classes.cpp,v 1.41 2004/08/04 09:12:53 qbix79 Exp $ */ #include #include @@ -64,11 +64,45 @@ void DOS_InfoBlock::SetLocation(Bit16u segment) pt=PhysMake(seg,0); /* Clear the initual Block */ for(Bitu i=0;i16mb + + sSave(sDIB,sharingCount,(Bit16u)0); + sSave(sDIB,sharingDelay,(Bit16u)0); + + sSave(sDIB,nulNextDriver,(Bit32u)0xffffffff); + sSave(sDIB,nulAttributes,(Bit16u)0x8004); + sSave(sDIB,nulStrategy,(Bit32u)0x00000000); + sSave(sDIB,nulString[0],(Bit8u)0x4e); + sSave(sDIB,nulString[1],(Bit8u)0x55); + sSave(sDIB,nulString[2],(Bit8u)0x4c); + sSave(sDIB,nulString[3],(Bit8u)0x20); + sSave(sDIB,nulString[4],(Bit8u)0x20); + sSave(sDIB,nulString[5],(Bit8u)0x20); + sSave(sDIB,nulString[6],(Bit8u)0x20); + sSave(sDIB,nulString[7],(Bit8u)0x20); } void DOS_InfoBlock::SetFirstMCB(Bit16u _firstmcb) { - sSave(sDIB,firstMCB,_firstmcb); + sSave(sDIB,firstMCB,_firstmcb); //c2woody } void DOS_InfoBlock::SetfirstFileTable(RealPt _first_table){ @@ -81,6 +115,26 @@ void DOS_InfoBlock::SetBuffers(Bit16u x,Bit16u y) { } +void DOS_InfoBlock::SetCurDirStruct(Bit32u _curdirstruct) +{ + sSave(sDIB,curDirStructure,_curdirstruct); +} + +void DOS_InfoBlock::SetFCBTable(Bit32u _fcbtable) +{ + sSave(sDIB,fcbTable,_fcbtable); +} + +void DOS_InfoBlock::SetDeviceChainStart(Bit32u _devchain) +{ + sSave(sDIB,nulNextDriver,_devchain); +} + +void DOS_InfoBlock::SetDiskInfoBuffer(Bit32u _dinfobuf) +{ + sSave(sDIB,diskInfoBuffer,_dinfobuf); +} + RealPt DOS_InfoBlock::GetPointer(void) { return RealMake(seg,offsetof(sDIB,firstDPB)); @@ -94,7 +148,7 @@ Bit16u DOS_PSP::rootpsp = 0; void DOS_PSP::MakeNew(Bit16u mem_size) { /* get previous */ - DOS_PSP prevpsp(dos.psp); + DOS_PSP prevpsp(dos.psp()); /* Clear it first */ Bitu i; for (i=0;i +#include #include "dosbox.h" #include "mem.h" #include "dos_inc.h" @@ -26,6 +27,8 @@ #include "callback.h" #include "debug.h" +char * RunningProgram="DOSBOX"; + #ifdef _MSC_VER #pragma pack(1) #endif @@ -65,7 +68,7 @@ struct EXE_Header { static void SaveRegisters(void) { - reg_sp-=20; + 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); @@ -87,19 +90,28 @@ static void RestoreRegisters(void) { 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+=20; + reg_sp+=18; } +extern void GFX_SetTitle(Bits 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) { dos.return_code=reg_al; dos.return_mode=RETURN_EXIT; - Bit16u mempsp = dos.psp; + Bit16u mempsp = dos.psp(); - DOS_PSP curpsp(dos.psp); - if (dos.psp==curpsp.GetParent()) return true; + DOS_PSP curpsp(mempsp); + if (mempsp==curpsp.GetParent()) return true; /* Free Files owned by process */ if (!tsr) curpsp.CloseFiles(); @@ -108,10 +120,9 @@ bool DOS_Terminate(bool tsr) { /* Restore vector 22,23,24 */ curpsp.RestoreVectors(); /* Set the parent PSP */ - dos.psp = curpsp.GetParent(); + dos.psp(curpsp.GetParent()); DOS_PSP parentpsp(curpsp.GetParent()); - /* Restore the DTA of the parent psp */ - dos.dta = parentpsp.GetDTA(); + /* Restore the SS:SP to the previous one */ SegSet16(ss,RealSeg(parentpsp.GetStack())); reg_sp = RealOff(parentpsp.GetStack()); @@ -123,15 +134,13 @@ bool DOS_Terminate(bool tsr) { mem_writew(SegPhys(ss)+reg_sp+4,0x200); //stack isn't preserved // Free memory owned by process if (!tsr) DOS_FreeProcessMemory(mempsp); + DOS_UpdatePSPName(); 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); + DOS_PSP psp(dos.psp()); PhysPt envread,envwrite; Bit16u envsize=1; bool parentenv=true; @@ -173,8 +182,7 @@ static bool MakeEnv(char * name,Bit16u * segment) { } else return false; } -bool DOS_NewPSP(Bit16u segment, Bit16u size) -{ +bool DOS_NewPSP(Bit16u segment, Bit16u size) { DOS_PSP psp(segment); psp.MakeNew(size); DOS_PSP psp_parent(psp.GetParent()); @@ -182,8 +190,7 @@ bool DOS_NewPSP(Bit16u segment, Bit16u size) return true; }; -bool DOS_ChildPSP(Bit16u segment, Bit16u size) -{ +bool DOS_ChildPSP(Bit16u segment, Bit16u size) { DOS_PSP psp(segment); psp.MakeNew(size); DOS_PSP psp_parent(psp.GetParent()); @@ -194,7 +201,6 @@ bool DOS_ChildPSP(Bit16u segment, Bit16u size) }; 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); @@ -204,31 +210,14 @@ static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { DOS_PSP psp(pspseg); psp.MakeNew(memsize); psp.SetEnvironment(envseg); - /* Copy file handles //QBIX::ALWAYS COPY BUT LEFT ORIGINAL INCASE OF MISTAKES -/* if (DOS_PSP::rootpsp!=dos.psp) { */ - // TODO: Improve this - // If prog wasnt started from commandline copy file table (California Games 2) -/* DOS_PSP oldpsp(dos.psp); - psp.CopyFileTable(&oldpsp); - } else { - psp.SetFileHandle(STDIN ,DOS_FindDevice("CON")); - psp.SetFileHandle(STDOUT,DOS_FindDevice("CON")); - psp.SetFileHandle(STDERR,DOS_FindDevice("CON")); - psp.SetFileHandle(STDAUX,DOS_FindDevice("CON")); - psp.SetFileHandle(STDNUL,DOS_FindDevice("CON")); - psp.SetFileHandle(STDPRN,DOS_FindDevice("CON")); - } */ - /* Save old DTA in psp */ - DOS_PSP oldpsp(dos.psp); - psp.CopyFileTable(&oldpsp,true); - psp.SetDTA(dos.dta); - /* Setup the DTA */ - dos.dta=RealMake(pspseg,0x80); + /* Copy file handles */ + DOS_PSP oldpsp(dos.psp()); + psp.CopyFileTable(&oldpsp,true); + } -static void SetupCMDLine(Bit16u pspseg,DOS_ParamBlock & block) -{ +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); @@ -263,14 +252,8 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { if (len0x7FFF) { readsize=0x8000;DOS_ReadFile(fhandle,loadbuf,&readsize); @@ -341,7 +328,6 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { SetupPSP(pspseg,memsize,envseg); SetupCMDLine(pspseg,block); }; - CALLBACK_SCF(false); /* Carry flag cleared for caller if successfull */ if (flags==OVERLAY) return true; /* Everything done for overlays */ RealPt csip,sssp; @@ -353,14 +339,15 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { csip=RealMake(loadseg+head.initCS,head.initIP); sssp=RealMake(loadseg+head.initSS,head.initSP); } - + if (flags==LOAD) { - DOS_PSP callpsp(dos.psp); + DOS_PSP callpsp(dos.psp()); /* Save the SS:SP on the PSP of calling program */ callpsp.SetStack(RealMakeSeg(ss,reg_sp)); /* Switch the psp's */ - dos.psp=pspseg; - + dos.psp(pspseg); + DOS_PSP newpsp(dos.psp()); + dos.dta(RealMake(newpsp.GetSegment(),0x80)); block.exec.initsssp = sssp; block.exec.initcsip = csip; block.SaveData(); @@ -371,14 +358,13 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { /* Get Caller's program CS:IP of the stack and set termination address to that */ RealSetVec(0x22,RealMake(mem_readw(SegPhys(ss)+reg_sp+2),mem_readw(SegPhys(ss)+reg_sp))); SaveRegisters(); - DOS_PSP callpsp(dos.psp); + DOS_PSP callpsp(dos.psp()); /* Save the SS:SP on the PSP of calling program */ callpsp.SetStack(RealMakeSeg(ss,reg_sp)); /* Switch the psp's and set new DTA */ - dos.psp=pspseg; - DOS_PSP newpsp(dos.psp); - newpsp.SetDTA(dos.dta); /* Original: change this and line below. This way seems better(zone66 and unpack) */ - //dos.dta=newpsp.GetDTA(); + dos.psp(pspseg); + DOS_PSP newpsp(dos.psp()); + dos.dta(RealMake(newpsp.GetSegment(),0x80)); /* save vectors */ newpsp.SaveVectors(); /* copy fcbs */ @@ -399,6 +385,24 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { /* Started from debug.com, then set breakpoint at start */ DEBUG_CheckExecuteBreakpoint(RealSeg(csip),RealOff(csip)); #endif + /* Add the filename to PSP and environment MCB's */ + char stripname[8];Bitu index=0; + while (char chr=*name++) { + switch (chr) { + case ':':case '\\':case '/':index=0;break; + default:if (index<8) stripname[index++]=toupper(chr); + } + } + index=0; + while (index<8) { + if (stripname[index]=='.') break; + if (!stripname[index]) break; + index++; + } + memset(&stripname[index],0,8-index); + DOS_MCB pspmcb(dos.psp()-1); + pspmcb.SetFileName(stripname); + DOS_UpdatePSPName(); return true; } return false; diff --git a/src/dos/dos_files.cpp b/src/dos/dos_files.cpp index 817946f..da28d41 100644 --- a/src/dos/dos_files.cpp +++ b/src/dos/dos_files.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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_files.cpp,v 1.52 2004/02/02 19:20:38 qbix79 Exp $ */ +/* $Id: dos_files.cpp,v 1.57 2004/08/04 09:12:53 qbix79 Exp $ */ #include #include @@ -217,8 +217,8 @@ bool DOS_Rename(char * oldname,char * newname) { return false; } -bool DOS_FindFirst(char * search,Bit16u attr) { - DOS_DTA dta(dos.dta); +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]; if (!DOS_MakeName(search,fullsearch,&drive)) return false; @@ -234,13 +234,13 @@ bool DOS_FindFirst(char * search,Bit16u attr) { strcpy(dir,fullsearch); } dta.SetupSearch(drive,(Bit8u)attr,pattern); - if (Drives[drive]->FindFirst(dir,dta)) return true; + if (Drives[drive]->FindFirst(dir,dta,fcb_findfirst)) return true; return false; } bool DOS_FindNext(void) { - DOS_DTA dta(dos.dta); + DOS_DTA dta(dos.dta()); if (Drives[dta.GetSearchDrive()]->FindNext(dta)) return true; return false; } @@ -318,7 +318,7 @@ bool DOS_CloseFile(Bit16u entry) { /* Devices won't allow themselves to be closed or killed */ if (Files[handle]->Close()) { //if close succesfull => delete file/update psp - DOS_PSP psp(dos.psp); + DOS_PSP psp(dos.psp()); psp.SetFileHandle(entry,0xff); if (Files[handle]->RemoveRef()<=0) { delete Files[handle]; @@ -329,8 +329,13 @@ bool DOS_CloseFile(Bit16u entry) { } bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) { + // Creation of a device is the same as opening it + // Tc201 installer + if (DOS_FindDevice(name) != 255) + return DOS_OpenFile(name, 0, entry); + char fullname[DOS_PATHLENGTH];Bit8u drive; - DOS_PSP psp(dos.psp); + 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; @@ -373,7 +378,7 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) { } } - DOS_PSP psp(dos.psp); + DOS_PSP psp(dos.psp()); Bit8u handle=DOS_FindDevice((char *)name); bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i; if (handle!=255) { @@ -514,7 +519,7 @@ bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; - DOS_PSP psp(dos.psp); + DOS_PSP psp(dos.psp()); *newentry = psp.FindFreeFileEntry(); if (*newentry==0xff) { DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); @@ -551,7 +556,7 @@ bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry) { DOS_CloseFile(newentry); return false; }; - DOS_PSP psp(dos.psp); + DOS_PSP psp(dos.psp()); Files[orig]->AddRef(); psp.SetFileHandle(newentry,(Bit8u)entry); return true; @@ -711,12 +716,13 @@ static void SaveFindResult(DOS_FCB & find_fcb) { 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(); + 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)); + 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); } @@ -741,7 +747,7 @@ bool DOS_FCBOpen(Bit16u seg,Bit16u offset) { /* Check, if file is already opened */ for (Bit8u i=0;iIsOpen() && Files[i]->IsName(fullname)) { handle = psp.FindEntryByHandle(i); if (handle==0xFF) { @@ -767,23 +773,23 @@ bool DOS_FCBClose(Bit16u seg,Bit16u offset) { return true; } -bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset) -{ +bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset) { DOS_FCB fcb(seg,offset); - RealPt old_dta=dos.dta;dos.dta=dos.tables.tempdta; + RealPt old_dta=dos.dta();dos.dta(dos.tables.tempdta); char name[DOS_FCBNAME];fcb.GetName(name); - bool ret=DOS_FindFirst(name,DOS_ATTR_ARCHIVE); - dos.dta=old_dta; + 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) -{ +bool DOS_FCBFindNext(Bit16u seg,Bit16u offset) { DOS_FCB fcb(seg,offset); - RealPt old_dta=dos.dta;dos.dta=dos.tables.tempdta; + RealPt old_dta=dos.dta();dos.dta(dos.tables.tempdta); bool ret=DOS_FindNext(); - dos.dta=old_dta; + dos.dta(old_dta); if (ret) SaveFindResult(fcb); return ret; } @@ -799,11 +805,11 @@ Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset,Bit16u recno) { if (!DOS_ReadFile(fhandle,dos_copybuf,&toread)) return FCB_READ_NODATA; if (toread==0) return FCB_READ_NODATA; if (toread0;i--) mem_writeb(fill++,0); } - MEM_BlockWrite(Real2Phys(dos.dta)+recno*rec_size,dos_copybuf,rec_size); + 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; @@ -819,7 +825,7 @@ Bit8u DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u recno) 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); + 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; @@ -855,7 +861,7 @@ Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) { /* 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. + if (restore) fcb.GetRecord(old_block,old_rec);//store this for after the read. // Read records for (int i=0; iUpdateDateTimeFromHost()) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; } - struct tm *time; - if ((time=localtime(&stat_block.st_mtime))!=0) { - *otime = (time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */ - *odate = ((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday); - } else { - *otime = 6; - *odate = 4; - } + *otime = Files[handle]->time; + *odate = Files[handle]->date; return true; }; diff --git a/src/dos/dos_ioctl.cpp b/src/dos/dos_ioctl.cpp index 2aa4ae6..9de93e2 100644 --- a/src/dos/dos_ioctl.cpp +++ b/src/dos/dos_ioctl.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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_ioctl.cpp,v 1.18 2004/01/10 14:03:34 qbix79 Exp $ */ +/* $Id: dos_ioctl.cpp,v 1.20 2004/08/04 09:12:53 qbix79 Exp $ */ #include #include "dosbox.h" @@ -97,6 +97,10 @@ bool DOS_IOCTL(void) { 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; default : LOG(LOG_IOCTL,LOG_ERROR)("DOS:IOCTL Call 0D:%2X Drive %2X unhandled",reg_cl,drive); diff --git a/src/dos/dos_memory.cpp b/src/dos/dos_memory.cpp index e2e3d9d..d292db6 100644 --- a/src/dos/dos_memory.cpp +++ b/src/dos/dos_memory.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -21,7 +21,7 @@ #include "dos_inc.h" -#define MEM_START 0x60 //First Segment that DOS can use +#define MEM_START 0x68 //First Segment that DOS can use //#define MEM_START 4000 //First Segment that DOS can use static Bit16u memAllocStrategy = 0x00; @@ -72,6 +72,9 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { Bit16u bigsize=0;Bit16u mcb_segment=dos.firstMCB; 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); bool stop=false; while(!stop) { mcb.SetPt(mcb_segment); @@ -83,7 +86,7 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { bigsize=block_size; } } else if (block_size==*blocks) { - mcb.SetPSPSeg(dos.psp); + mcb.SetPSPSeg(dos.psp()); *segment=mcb_segment+1; return true; } else { @@ -96,7 +99,8 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { mcb_next.SetSize(block_size-*blocks-1); mcb.SetSize(*blocks); mcb.SetType(0x4d); - mcb.SetPSPSeg(dos.psp); + mcb.SetPSPSeg(dos.psp()); + mcb.SetFileName(psp_name); //TODO Filename *segment=mcb_segment+1; return true; @@ -107,7 +111,8 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { mcb_next.SetPt((Bit16u)(*segment-1)); mcb_next.SetSize(*blocks); mcb_next.SetType(mcb.GetType()); - mcb_next.SetPSPSeg(dos.psp); + mcb_next.SetPSPSeg(dos.psp()); + mcb_next.SetFileName(psp_name); // Old Block mcb.SetSize(block_size-*blocks-1); mcb.SetPSPSeg(MCB_FREE); @@ -180,11 +185,19 @@ bool DOS_FreeMemory(Bit16u segment) { void DOS_SetupMemory(void) { - DOS_MCB mcb((Bit16u)MEM_START); + // Create a dummy device MCB with PSPSeg=0x0008 + DOS_MCB mcb_devicedummy((Bit16u)MEM_START); + mcb_devicedummy.SetPSPSeg(0x0008); // Devices + mcb_devicedummy.SetSize(1); + mcb_devicedummy.SetType(0x4d); // More blocks will follow + + DOS_MCB mcb((Bit16u)MEM_START+2); mcb.SetPSPSeg(MCB_FREE); //Free - mcb.SetSize(0x9FFE - MEM_START); + if (machine==MCH_TANDY) { + mcb.SetSize(0x97FE - MEM_START - 2); + } else mcb.SetSize(0x9FFE - MEM_START - 2); mcb.SetType(0x5a); //Last Block + dos.firstMCB=MEM_START; dos_infoblock.SetFirstMCB(MEM_START); } - diff --git a/src/dos/dos_misc.cpp b/src/dos/dos_misc.cpp index ddfa2d2..0fa2c72 100644 --- a/src/dos/dos_misc.cpp +++ b/src/dos/dos_misc.cpp @@ -9,13 +9,15 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.12 2004/08/04 09:12:53 qbix79 Exp $ */ + #include "dosbox.h" #include "callback.h" #include "mem.h" @@ -56,11 +58,56 @@ static Bitu INT2A_Handler(void) { static bool DOS_MultiplexFunctions(void) { switch (reg_ax) { + case 0x1607: + if (reg_bx == 0x15) { + switch (reg_cx) { + case 0x0000: // query instance + reg_cx = 0x0001; + reg_dx = 0x50; // dos driver segment + SegSet16(es,0x50); // patch table seg + reg_bx = 0x60; // patch table ofs + return true; + case 0x0001: // set patches + reg_ax = 0xb97c; + reg_bx = (reg_dx & 0x16); + reg_dx = 0xa2ab; + return true; + case 0x0003: // get size of data struc + if (reg_dx==0x0001) { + // CDS size requested + reg_ax = 0xb97c; + reg_dx = 0xa2ab; + reg_cx = 0x000e; // size + } + return true; + case 0x0004: // instanced data + reg_dx = 0; // none + return true; + case 0x0005: // get device driver size + reg_ax = 0; + reg_dx = 0; + return true; + default: + return false; + } + } + else if (reg_bx == 0x18) return true; // idle callout + else return false; case 0x1680: /* RELEASE CURRENT VIRTUAL MACHINE TIME-SLICE */ //TODO Maybe do some idling but could screw up other systems :) reg_al=0; return true; + case 0x1689: /* Kernel IDLE CALL */ case 0x168f: /* Close awareness crap */ + /* Removing warning */ + return true; + case 0x4a01: /* Query free hma space */ + case 0x4a02: /* ALLOCATE HMA SPACE */ + LOG(LOG_DOSMISC,LOG_WARN)("INT 2f:4a HMA. DOSBox reports none available."); + reg_bx=0; //number of bytes available in HMA or amount succesfully allocated + //ESDI=ffff:ffff Location of HMA/Allocated memory + SegSet16(es,0xffff); + reg_di=0xffff; return true; } @@ -71,12 +118,12 @@ void DOS_SetupMisc(void) { /* Setup the dos multiplex interrupt */ first_multiplex=0; call_int2f=CALLBACK_Allocate(); - CALLBACK_Setup(call_int2f,&INT2F_Handler,CB_IRET); + CALLBACK_Setup(call_int2f,&INT2F_Handler,CB_IRET,"DOS Int 2f"); RealSetVec(0x2f,CALLBACK_RealPointer(call_int2f)); DOS_AddMultiplexHandler(DOS_MultiplexFunctions); /* Setup the dos network interrupt */ call_int2a=CALLBACK_Allocate(); - CALLBACK_Setup(call_int2a,&INT2A_Handler,CB_IRET); + CALLBACK_Setup(call_int2a,&INT2A_Handler,CB_IRET,"DOS Int 2a"); RealSetVec(0x2A,CALLBACK_RealPointer(call_int2a)); }; diff --git a/src/dos/dos_mscdex.cpp b/src/dos/dos_mscdex.cpp index 4559914..cac0e8b 100644 --- a/src/dos/dos_mscdex.cpp +++ b/src/dos/dos_mscdex.cpp @@ -9,13 +9,15 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.24 2004/08/13 19:43:02 qbix79 Exp $ */ + #include #include #include "regs.h" @@ -35,6 +37,7 @@ #define MSCDEX_MAX_DRIVES 5 // Error Codes +#define MSCDEX_ERROR_BAD_FORMAT 11 #define MSCDEX_ERROR_UNKNOWN_DRIVE 15 #define MSCDEX_ERROR_DRIVE_NOT_READY 21 @@ -95,6 +98,7 @@ public: 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); @@ -271,11 +275,9 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit) cdrom[numDrives] = new CDROM_Interface_SDL(); LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: SDL Interface."); } break; - case 0x01 : // iso cdrom interface - // FIXME: Not yet supported - LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Mounting iso file as cdrom: %s" ,physicalPath); - cdrom[numDrives] = new CDROM_Interface_Fake; - return 2; + 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; @@ -304,9 +306,8 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit) PhysPt CMscdex::GetDefaultBuffer(void) { if (defaultBuffer==0) { - Bit16u seg,size = 128; - if (!DOS_AllocateMemory(&seg,&size)) E_Exit("MSCDEX: cannot allocate default buffer."); - defaultBuffer = PhysMake(seg,0); + Bit16u size = 128; //Size in block is size in pages ? + defaultBuffer = DOS_GetMemory(size); }; return defaultBuffer; }; @@ -324,6 +325,8 @@ bool CMscdex::GetCDInfo(Bit8u subUnit, Bit8u& tr1, Bit8u& tr2, TMSF& leadOut) { if (subUnit>=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; @@ -452,8 +455,19 @@ Bit32u CMscdex::GetVolumeSize(Bit8u subUnit) bool CMscdex::ReadVTOC(Bit16u drive, Bit16u volume, PhysPt data, Bit16u& error) { - ReadSectors(GetSubUnit(drive),false,/*150+*/16,1,data) ? error=0:error=MSCDEX_ERROR_DRIVE_NOT_READY; - return (error==0); + 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) @@ -585,9 +599,12 @@ bool CMscdex::GetDirectoryEntry(Bit16u drive, bool copyFlag, PhysPt pathname, Ph if (!ReadSectors(GetSubUnit(drive),false,dirEntrySector,1,defBuffer)) return false; // Get string part foundName = false; - useName = searchPos; - searchPos = strchr(searchPos,'\\'); - if (searchPos) { *searchPos = 0; searchPos++; } + if (searchPos) { + useName = searchPos; + searchPos = strchr(searchPos,'\\'); + } + + if (searchPos) { *searchPos = 0; searchPos++; } else foundComplete = true; do { @@ -606,7 +623,7 @@ bool CMscdex::GetDirectoryEntry(Bit16u drive, bool copyFlag, PhysPt pathname, Ph if (foundName) { // TO DO : name gefunden, Daten in den Buffer kopieren if (foundComplete) { - if (copyFlag) E_Exit("MSCDEX: GetDirEntry: Unsupported copyflag"); + if (copyFlag) LOG(LOG_MISC,LOG_ERROR)("MSCDEX: GetDirEntry: Unsupported copyflag. (result structure should be different"); // Direct copy MEM_BlockCopy(buffer,defBuffer+index,entryLength); error = iso ? 1:0; @@ -708,6 +725,14 @@ Bit16u CMscdex::GetStatusWord(Bit8u subUnit) return status; }; +void CMscdex::InitNewMedia(Bit8u subUnit) +{ + if (subUnitInitNewMedia(); + } +}; + static CMscdex* mscdex = 0; static Bitu MSCDEX_Strategy_Handler(void) @@ -893,7 +918,7 @@ static bool MSCDEX_Handler(void) if (reg_ah!=0x15) return false; PhysPt data = PhysMake(SegValue(es),reg_bx); - MSCDEX_LOG("MSCDEX: INT 2F %04X",reg_ax); + MSCDEX_LOG("MSCDEX: INT 2F %04X BX= %04X CX=%04X",reg_ax,reg_bx,reg_bx); switch (reg_ax) { case 0x1500: /* Install check */ @@ -970,6 +995,7 @@ static bool MSCDEX_Handler(void) case 0x1510: /* Device driver request */ mscdex->SendDriverRequest(reg_cx,data); return true; + default : LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Unknwon call : %04X",reg_ax); return true; @@ -1011,9 +1037,12 @@ bool MSCDEX_HasMediaChanged(Bit8u subUnit) 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); - 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 (subUnit #include @@ -28,6 +28,9 @@ #include "regs.h" #include "callback.h" #include "cdrom.h" +#include "dos_system.h" +#include "dos_inc.h" +#include "bios.h" void MSCDEX_SetCDInterface(int intNr, int forceCD); @@ -42,7 +45,7 @@ public: // Show list of cdroms if (cmd->FindExist("-cd",false)) { int num = SDL_CDNumDrives(); - WriteOut("CDROMs found: %d\n",num); + WriteOut(MSG_Get("PROGRAM_MOUNT_CDROMS_FOUND"),num); for (int i=0; iFindString("-freesize",mb_size,true)) { + char teststr[1024]; + Bit16u sizemb = static_cast(atoi(mb_size.c_str())); + 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; @@ -112,7 +124,7 @@ public: return; } if (temp_line[temp_line.size()-1]!=CROSS_FILESPLIT) temp_line+=CROSS_FILESPLIT; - Bit8u bit8size=(Bit8u) sizes[1]; + Bit8u bit8size=(Bit8u) sizes[1]; if (type=="cdrom") { int num = -1; cmd->FindInt("-usecd",num,true); @@ -147,7 +159,7 @@ public: Drives[drive-'A']=newdrive; /* Set the correct media byte in the table */ mem_writeb(Real2Phys(dos.tables.mediaid)+drive-'A',newdrive->GetMediaByte()); - WriteOut("Drive %c mounted as %s\n",drive,newdrive->GetInfo()); + WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"),drive,newdrive->GetInfo()); /* check if volume label is given */ if (cmd->FindString("-label",label,true)) newdrive->dirCache.SetLabel(label.c_str()); return; @@ -196,6 +208,151 @@ static void MEM_ProgramStart(Program * * make) { *make=new MEM; } +extern Bit32u floppytype; + + + +class BOOT : public Program { +private: + FILE *getFSFile(Bit8u * filename, Bit32u *ksize, Bit32u *bsize) { + Bit8u drive; + FILE *tmpfile; + char fullname[DOS_PATHLENGTH]; + + localDrive* ldp=0; + if (!DOS_MakeName((char *)filename,fullname,&drive)) return NULL; + + try { + ldp=dynamic_cast(Drives[drive]); + if(!ldp) return NULL; + + tmpfile = ldp->GetSystemFilePtr(fullname, "r"); + if(tmpfile == NULL) { + WriteOut(MSG_Get("PROGRAM_BOOT_NOT_EXIST")); + return NULL; + } + fclose(tmpfile); + tmpfile = ldp->GetSystemFilePtr(fullname, "rb+"); + if(tmpfile == NULL) { + WriteOut(MSG_Get("PROGRAM_BOOT_NOT_OPEN")); + return NULL; + } + + fseek(tmpfile,0L, SEEK_END); + *ksize = (ftell(tmpfile) / 1024); + *bsize = ftell(tmpfile); + return tmpfile; + } + catch(...) { + return NULL; + } + + } + + void printError(void) { + WriteOut(MSG_Get("PROGRAM_BOOT_PRINT_ERROR")); + } + + +public: + + void Run(void) { + FILE *usefile; + Bitu i; + Bit32u floppysize, rombytesize; + Bit8u drive; + + if(!cmd->GetCount()) { + printError(); + return; + } + i=0; + drive = 'A'; + while(iGetCount()) { + if(cmd->FindCommand(i+1, temp_line)) { + if(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; + } + + WriteOut(MSG_Get("PROGRAM_BOOT_IMAGE_OPEN"), temp_line.c_str()); + usefile = getFSFile((Bit8u *)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); + + } 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; + } + + WriteOut(MSG_Get("PROGRAM_BOOT_BOOT"),"Booting from drive %c...\n", drive); + + bootSector bootarea; + imageDiskList[drive-65]->Read_Sector(0,0,1,(Bit8u *)&bootarea); + for(i=0;i<512;i++) real_writeb(0, 0x7c00 + i, bootarea.rawdata[i]); + + + + SegSet16(cs, 0); + reg_ip = 0x7c00; + + + + /* Most likely a PCJr ROM */ + /* Write it to E000:0000 */ + /* Code inoperable at the moment */ + + /* + Bit8u rombuff[65536]; + fseek(tmpfile,512L, SEEK_SET); + rombytesize-=512; + fread(rombuff, 1, rombytesize, tmpfile); + fclose(tmpfile); + for(i=0;iFindExist("cdrom",false)) { + WriteOut(MSG_Get("PROGRAM_INTRO_CDROM")); + return; + } WriteOut(MSG_Get("PROGRAM_INTRO")); } }; @@ -293,19 +454,213 @@ static void INTRO_ProgramStart(Program * * make) { *make=new INTRO; } +class IMGMOUNT : public Program { +public: + void Run(void) + { + DOS_Drive * newdrive; + imageDisk * newImage; + Bit32u imagesize; + char drive; + std::string label; + + std::string type="hdd"; + std::string fstype="fat"; + cmd->FindString("-t",type,true); + cmd->FindString("-fs",fstype,true); + Bit8u mediaid; + if (type=="floppy" || type=="hdd" || type=="iso") { + Bit16u sizes[4]; + + std::string str_size; + mediaid=0xF8; + + if (type=="floppy") { + mediaid=0xF0; + } else if (type=="cdrom" || 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)) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_GEOMETRY")); + return; + } + 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 + cmd->FindCommand(1,temp_line); + if ((temp_line.size() > 2) || ((temp_line.size()>1) && (temp_line[1]!=':'))) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_DRIVE")); + return; + } + drive=toupper(temp_line[0]); + if (!isalpha(drive)) { + WriteOut(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(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY2")); + return; + } + drive=temp_line[0]-'0'; + if(drive>3) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY2")); + return; + } + } else { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FORMAT_UNSUPPORTED")); + return; + } + + if (!cmd->FindCommand(2,temp_line)) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_FILE")); + return; + } + if (!temp_line.size()) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_FILE")); + return; + } + struct stat test; + if (stat(temp_line.c_str(),&test)) { + // convert dosbox filename to system filename + char fullname[CROSS_LEN]; + char tmp[CROSS_LEN]; + strncpy(tmp, temp_line.c_str(), CROSS_LEN); + + Bit8u drive; + if (!DOS_MakeName(tmp, fullname, &drive)) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNG_FILE_NOT_FOUND")); + return; + } + + localDrive *ldp = (localDrive*)Drives[drive]; + ldp->GetSystemFilename(tmp, fullname); + temp_line = tmp; + + if (stat(temp_line.c_str(),&test)) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNG_FILE_NOT_FOUND")); + return; + } + } + + if ((test.st_mode & S_IFDIR)) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNG_MOUNT")); + return; + } + + if(fstype=="fat") { + newdrive=new fatDrive(temp_line.c_str(),sizes[0],sizes[1],sizes[2],sizes[3],0); + } else if (fstype=="iso") { + int error; + newdrive = new isoDrive(drive, temp_line.c_str(), mediaid, error); + 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) { + delete newdrive; + return; + } + } 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]); + } + } + if(fstype=="fat") { + if (Drives[drive-'A']) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_ALLREADY_MOUNTED")); + if (newdrive) delete newdrive; + return; + } + if (!newdrive) WriteOut(MSG_Get("PROGRAM_IMGMOUNT_CANT_CREATE")); + Drives[drive-'A']=newdrive; + // Set the correct media byte in the table + mem_writeb(Real2Phys(dos.tables.mediaid)+drive-'A',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_ALLREADY_MOUNTED")); + if (newdrive) delete newdrive; + return; + } + if (!newdrive) WriteOut(MSG_Get("PROGRAM_IMGMOUNT_CANT_CREATE")); + Drives[drive-'A']=newdrive; + // Set the correct media byte in the table + mem_writeb(Real2Phys(dos.tables.mediaid)+drive-'A',mediaid); + WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"),drive,temp_line.c_str()); + } else if (fstype=="none") { + if(imageDiskList[drive] != NULL) delete imageDiskList[drive]; + imageDiskList[drive] = newImage; + updateDPT(); + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT_NUMBER"),drive,temp_line.c_str()); + } + + // check if volume label is given + //if (cmd->FindString("-label",label,true)) newdrive->dirCache.SetLabel(label.c_str()); + return; + } +}; + +void IMGMOUNT_ProgramStart(Program * * make) { + *make=new IMGMOUNT; +} + + void DOS_SetupPrograms(void) { - /*Add Messages */ + /*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_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_ALLREADY_MOUNTED","Drive %c already mounted with %s\n"); - MSG_Add("PROGRAM_MOUNT_USAGE","Usage MOUNT Drive-Letter Local-Directory\nSo a MOUNT c c:\\windows mounts windows directory as the c: drive in DOSBox\n"); + MSG_Add("PROGRAM_MOUNT_ALLREADY_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_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_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_LOADFIX_ALLOC","%d kb allocated.\n"); MSG_Add("PROGRAM_LOADFIX_DEALLOC","%d kb freed.\n"); @@ -323,32 +678,91 @@ void DOS_SetupPrograms(void) { MSG_Add("PROGRAM_RESCAN_SUCCESS","Drive cache cleared.\n"); MSG_Add("PROGRAM_INTRO", - "Welcome to DOSBox, an x86 emulator with sound and graphics.\n" + "\033[2J\033[33;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" "Here are some commands to get you started:\n" "Before you can use the files located on your own filesystem,\n" "You have to mount the directory containing the files.\n" - "For Windows:\n" - "\033[33mmount c c:\\dosprog\033[0m will create a C drive in dosbox with c:\\dosprog as contents.\n" + "For \033[1mWindows\033[0m:\n" + "\033[34;1mmount c c:\\dosprog\033[0m will create a C drive in DOSBox with c:\\dosprog as contents.\n" "\n" - "For other platforms:\n" - "\033[33mmount c /home/user/dosprog\033[0m will do the same.\n" + "For \033[1mother platforms\033[0m:\n" + "\033[34;1mmount c /home/user/dosprog\033[0m will do the same.\n" "\n" - "When the mount has succesfully completed you can type \033[33mc:\033[0m to go to your freshly\n" - "mounted C-drive. Typing \033[33mdir\033[0m there will show its contents." - " \033[33mcd\033[0m will allow you to\n" - "enter a directory (recognised by the [] in a directory listing).\n" - "You can run programs/files which end with .exe .bat and .com.\n" - + "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[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" "\n" - "DOSBox will stop/exit without a warning if an error occured!\n" + "For information about CD-ROM support type \033[34;1mintro cdrom\033[0m\n" + "\n" + "\033[32;1mDOSBox will stop/exit without a warning if an error occured!\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 D:\\ -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 D:\\ -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 D:\\ -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 D:\\ -t cdrom -usecd \033[33m0 \033[34m-aspi\033[0m\n" + "\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" ); - /*regular setup*/ + 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_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_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"); + 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_IMGMOUNG_FILE_NOT_FOUND","Image file not found.\n"); + MSG_Add("PROGRAM_IMGMOUNG_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_ALLREADY_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"); + + /*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); + PROGRAMS_MakeFile("IMGMOUNT.COM", IMGMOUNT_ProgramStart); } diff --git a/src/dos/dos_tables.cpp b/src/dos/dos_tables.cpp index 93d2554..37f4861 100644 --- a/src/dos/dos_tables.cpp +++ b/src/dos/dos_tables.cpp @@ -9,13 +9,15 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.15 2004/09/21 20:04:55 qbix79 Exp $ */ + #include "dosbox.h" #include "mem.h" #include "dos_inc.h" @@ -36,6 +38,8 @@ RealPt DOS_TableUpCase; RealPt DOS_TableLowCase; static Bit16u dos_memseg; +Bit16u sdaseg; + Bit16u DOS_GetMemory(Bit16u pages) { if (pages+dos_memseg>=0xe000) { E_Exit("DOS:Not enough memory for internal tables"); @@ -48,20 +52,67 @@ Bit16u DOS_GetMemory(Bit16u pages) { void DOS_SetupTables(void) { dos_memseg=0xd000; - Bit16u seg;Bitu i; + Bit16u seg,seg2;Bitu i; dos.tables.mediaid=RealMake(DOS_GetMemory(2),0); dos.tables.tempdta=RealMake(DOS_GetMemory(4),0); for (i=0;i20 detection routine */ + /* Possibly obselete when SFT is properly handled */ + real_writed(0x5d,0x0a,0x204e4f43); + real_writed(0x5d,0x1a,0x204e4f43); + real_writed(0x5d,0x2a,0x204e4f43); + + /* create a CON device driver */ + seg=0x60; + 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 SFT, so programs think there are 100 file handles */ - seg=DOS_GetMemory(1); + seg=0x62; + seg2=0x63; + real_writed(seg,0,seg2<<16); //Next File Table + real_writew(seg,4,100); //File Table supports 100 files + real_writed(seg2,0,0xffffffff); //Last File Table + real_writew(seg2,4,100); //File Table supports 100 files + dos_infoblock.SetfirstFileTable(RealMake(seg,0)); + + /* Create a fake CDS */ + seg=0x64; + real_writed(seg,0x00,0x005c3a43); + dos_infoblock.SetCurDirStruct(RealMake(seg,0)); + + + + /* Allocate DCBS DOUBLE BYTE CHARACTER SET LEAD-BYTE TABLE */ + dos.tables.dcbs=RealMake(DOS_GetMemory(12),0); + mem_writed(Real2Phys(dos.tables.dcbs),0); //empty table + + /* 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.SetfirstFileTable(RealMake(seg,0)); + dos_infoblock.SetFCBTable(RealMake(seg,0)); + + /* Create a fake disk info buffer */ + seg=DOS_GetMemory(6); + seg2=DOS_GetMemory(6); + real_writed(seg,0x00,seg2<<16); + real_writed(seg2,0x00,0xffffffff); + real_writed(seg2,0x0d,0xffffffff); + dos_infoblock.SetDiskInfoBuffer(RealMake(seg,0)); + /* Set buffers to a nice value */ dos_infoblock.SetBuffers(50,50); + } diff --git a/src/dos/drive_cache.cpp b/src/dos/drive_cache.cpp index ce259b0..587a5f2 100644 --- a/src/dos/drive_cache.cpp +++ b/src/dos/drive_cache.cpp @@ -10,30 +10,30 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.32 2004/01/12 20:25:05 finsterr Exp $ */ +/* $Id: drive_cache.cpp,v 1.38 2004/09/15 14:00:13 qbix79 Exp $ */ #include "drives.h" #include "dos_inc.h" #include "dirent.h" #include "support.h" -#if defined (WIN32) /* Win 32 */ -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from -#include -#endif - // STL stuff #include #include #include +#if defined (WIN32) /* Win 32 */ +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from +#include +#endif + int fileInfoCounter = 0; bool SortByName(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) @@ -62,20 +62,22 @@ bool SortByDirNameRev(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFi DOS_Drive_Cache::DOS_Drive_Cache(void) { - dirBase = new CFileInfo; - save_dir = 0; - srchNr = 0; - label[0] = 0; + dirBase = new CFileInfo; + save_dir = 0; + srchNr = 0; + label[0] = 0; + nextFreeFindFirst = 0; for (Bit32u i=0; i0) { if (vname[vnamePos]==0) break; if (!point && (vname[vnamePos]=='.')) { togo=4; point=true; } - label[labelPos] = vname[vnamePos]; - label[labelPos] = *upcase(&label[labelPos]); + label[labelPos] = toupper(vname[vnamePos]); labelPos++; vnamePos++; togo--; if ((togo==0) && !point) { @@ -174,6 +176,17 @@ char* DOS_Drive_Cache::GetExpandName(const char* path) GetLongName(dirInfo, dir); strcat(work,dir); } + + if(work && *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; }; @@ -431,8 +444,6 @@ void DOS_Drive_Cache::CreateShortName(CFileInfo* curDir, CFileInfo* info) // Copy number strcat(info->shortname,"~"); strcat(info->shortname,buffer); - // Create compare Count -// info->compareCount = tocopy; // Add (and cut) Extension, if available if (pos) { // Step to last extension... @@ -635,35 +646,29 @@ bool DOS_Drive_Cache::SetResult(CFileInfo* dir, char* &result, Bit16u entryNr) }; // FindFirst / FindNext -bool DOS_Drive_Cache::FindFirst(char* path, Bitu dtaAddress, Bitu& id) +bool DOS_Drive_Cache::FindFirst(char* path, Bitu& id) { Bit16u dirID; - Bitu dirFindFirstID = 0xffff; + Bitu dirFindFirstID = this->nextFreeFindFirst++; //increase it for the next search // Cache directory in if (!OpenDir(path,dirID)) return false; - // Seacrh if dta was already used before - for (Bitu n=0; ncompareCount == dtaAddress) { - // Reuse old dta - dirFindFirstID = n; break; - } - } else if (dirFindFirstID==0xffff) { - dirFindFirstID = n; - } - } - if (dirFindFirstID==0xffff) { + + if (dirFindFirstID == MAX_OPENDIRS) { // no free slot found... - LOG(LOG_MISC,LOG_ERROR)("DIRCACHE: FindFirst/Next failure : All slots full."); - // always use first then + 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; - dirFindFirst[dirFindFirstID]-> compareCount = dtaAddress; // Copy entries to use with FindNext for (Bitu i=0; ifileList.size(); i++) { diff --git a/src/dos/drive_fat.cpp b/src/dos/drive_fat.cpp new file mode 100644 index 0000000..aefbd2f --- /dev/null +++ b/src/dos/drive_fat.cpp @@ -0,0 +1,1127 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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.5 2004/09/05 14:23:04 qbix79 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 + +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; + int i; + flen = 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; + 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; + } + + sizedec = *size; + sizecount = 0; + while(sizedec != 0) { + if(seekpos >= filelength) { + *size = sizecount; + return true; + } + data[sizecount] = sectorBuffer[curSectOff]; + 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; + return true; + } + curSectOff = 0; + myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); + LOG_MSG("Reading absolute sector at %d for seekpos %d", currentSector, seekpos); + } + --sizedec; + sizecount++; + } + *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); + } + filelength = seekpos+1; + } + sectorBuffer[curSectOff] = data[sizecount]; + curSectOff++; + 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 */ + goto finalizeWrite; + + } + } + curSectOff = 0; + myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); + + loadedSector = true; + } + --sizedec; + sizecount++; + } + +finalizeWrite: + myDrive->directoryBrowse(dirCluster, &tmpentry, dirIndex); + tmpentry.entrysize = filelength; + tmpentry.loFirstClust = firstCluster; + myDrive->directoryChange(dirCluster, &tmpentry, dirIndex); + + *size =sizecount; + return true; + +} + +bool fatFile::Seek(Bit32u *pos, Bit32u type) { + Bit32s seekto; + + 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); + 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 0x202; +} + +bool fatFile::UpdateDateTimeFromHost(void) { + return true; +} + +Bit32u fatDrive::getClustFirstSect(Bit32u clustNum) { + return ((clustNum - 2) * bootbuffer.sectorspercluster) + firstDataSector; +} + +Bit32u fatDrive::getClusterValue(Bit32u clustNum) { + Bit32u fatoffset; + Bit32u fatsectnum; + Bit32u fatentoff; + + Bit32u clustValue; + + + /* Load two sectors at once for FAT12 */ + Bit8u sectbuffer[1024]; + + 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; + + loadedDisk->Read_AbsoluteSector(fatsectnum, §buffer[0]); + loadedDisk->Read_AbsoluteSector(fatsectnum+1, §buffer[512]); + + switch(fattype) { + case FAT12: + clustValue = *((Bit16u *)§buffer[fatentoff]); + if(clustNum & 0x1) { + clustValue >>= 4; + } else { + clustValue &= 0xfff; + } + break; + case FAT16: + clustValue = *((Bit16u *)§buffer[fatentoff]); + break; + case FAT32: + clustValue = *((Bit32u *)§buffer[fatentoff]); + break; + } + + return clustValue; +} + +void fatDrive::setClusterValue(Bit32u clustNum, Bit32u clustValue) { + Bit32u fatoffset; + Bit32u fatsectnum; + Bit32u fatentoff; + Bit32u tmpValue; + + + /* Load two sectors at once for FAT12 */ + Bit8u sectbuffer[1024]; + + 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; + + loadedDisk->Read_AbsoluteSector(fatsectnum, §buffer[0]); + loadedDisk->Read_AbsoluteSector(fatsectnum+1, §buffer[512]); + + switch(fattype) { + case FAT12: + tmpValue = *((Bit16u *)§buffer[fatentoff]); + if(clustNum & 0x1) { + clustValue &= 0xfff; + clustValue <<= 4; + tmpValue &= 0xf; + tmpValue |= clustValue; + + } else { + clustValue &= 0xfff; + tmpValue &= 0xf000; + tmpValue |= clustValue; + } + *((Bit16u *)§buffer[fatentoff]) = tmpValue; + break; + case FAT16: + *((Bit16u *)§buffer[fatentoff]) = clustValue; + break; + case FAT32: + *((Bit32u *)§buffer[fatentoff]) = clustValue; + break; + } + int fc; + for(fc=0;fcWrite_AbsoluteSector(fatsectnum + (fc * bootbuffer.sectorsperfat), §buffer[0]); + loadedDisk->Write_AbsoluteSector(fatsectnum+1+(fc * bootbuffer.sectorsperfat), §buffer[512]); + } +} + +bool fatDrive::getEntryName(char *fullname, char *entname) { + Bit16u len = strlen(fullname); + char dirtoken[DOS_PATHLENGTH]; + Bit32u currentClust = 0; + + direntry foundEntry; + char * findDir; + char * findFile; + strcpy(dirtoken,fullname); + + LOG_MSG("Testing for filename %s", fullname); + findDir = strtok(dirtoken,"\\"); + findFile = findDir; + while(findDir != NULL) { + findFile = findDir; + findDir = strtok(NULL,"\\"); + } + strcpy(entname, findFile); + return true; +} + +bool fatDrive::getFileDirEntry(char * filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry) { + Bit16u len = strlen(filename); + char dirtoken[DOS_PATHLENGTH]; + Bit32u currentClust = 0; + + direntry foundEntry; + char * findDir; + char * findFile; + strcpy(dirtoken,filename); + + /* 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; + currentClust = foundEntry.loFirstClust; + findDir = strtok(NULL,"\\"); + } + } else { + /* Set to root directory */ + } + + /* Search found directory for our file */ + imgDTA->SetupSearch(0,0x5,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) { + Bit16u len = 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) { + if(!FindNextInternal(currentClust, *imgDTA, &foundEntry)) return false; + } else { + if(findDir == NULL) break; + if(!FindNextInternal(currentClust, *imgDTA, &foundEntry)) return false; + } + currentClust = foundEntry.loFirstClust; + + } + *clustNum = currentClust; + return true; + } else { + /* Set to root directory */ + *clustNum = 0; + return true; + } + return false; + +} + +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); + } + + 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) { + 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) 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) { + delete this; + return; + } + + if(filesize > 2880) { + /* Set user specified harddrive parameters */ + loadedDisk->Set_Geometry(headscyl, cylinders,cylsector, bytesector); + + loadedDisk->Read_Sector(0,0,1,&mbrData); + 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; + } + } + + 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 */ + delete this; + return; + } + + if(!bootbuffer.sectorsperfat) { + /* FAT32 not implemented yet */ + delete this; + 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; + + + + +} + +bool fatDrive::AllocationInfo(Bit16u *_bytes_sector, Bit8u *_sectors_cluster, Bit16u *_total_clusters, Bit16u *_free_clusters) { + Bit32u hs, cy, sect,sectsize; + Bit32u countFree = 0; + int i; + + loadedDisk->Get_Geometry(&hs, &cy, §, §size); + *_bytes_sector = (Bit16u)sectsize; + *_sectors_cluster = bootbuffer.sectorspercluster; + *_total_clusters = CountOfClusters; + 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]; + + /* Check if file already exists */ + if(getFileDirEntry(name, &fileEntry, &dirClust, &subEntry)) return false; + + /* 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 = attributes; + 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; + + return true; +} + +bool fatDrive::FileExists(const char *name) { + direntry fileEntry; + Bit32u dummy1, dummy2; + if(!getFileDirEntry((char *)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; + + 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) //check for root dir or fcb_findfirst + LOG(LOG_DOSMISC,LOG_WARN)("findfirst for volumelabel used on fatDrive. Unhandled!!!!!"); + if(!getDirClustNum(_dir, &cwdDirCluster, false)) return false; + dta.SetDirID(0); + 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) 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) 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)) { + strcat(find_name, "."); + strcat(find_name, extension); + } + + if((attrs & (sectbuf[entryoffset].attrib | 0x21)) == 0) 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(cwdDirCluster, dta, &dummyClust); +} + +bool fatDrive::GetFileAttr(char *name, Bit16u *attr) { + /* TODO: Stub */ + return false; +} + +bool fatDrive::directoryBrowse(Bit32u dirClustNumber, direntry *useEntry, Bit32s entNum) { + 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 = 0; + char srch_pattern[DOS_NAMELENGTH_ASCII]; + char find_name[DOS_NAMELENGTH_ASCII]; + char extension[4]; + + 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; /* Index offset within sector */ + Bit32u tmpsector = 0; + Bit8u attrs; + Bit16u dirPos = 0; + char srch_pattern[DOS_NAMELENGTH_ASCII]; + char find_name[DOS_NAMELENGTH_ASCII]; + char extension[4]; + + 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; + Bit8u attrs; + Bit16u dirPos = 0; + char srch_pattern[DOS_NAMELENGTH_ASCII]; + char find_name[DOS_NAMELENGTH_ASCII]; + char extension[4]; + + while(true) { + + 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); + return true; + } + } + + + return false; +} + +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 */ + 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) { + + 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 new file mode 100644 index 0000000..53f8b2b --- /dev/null +++ b/src/dos/drive_iso.cpp @@ -0,0 +1,435 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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.1 2004/08/13 19:43:02 qbix79 Exp $ */ + +#include +#include +#include "cdrom.h" +#include "dosbox.h" +#include "dos_system.h" +#include "drives.h" + +using namespace std; + +class isoFile : public DOS_File { +public: + isoFile(isoDrive *drive, const char *name, FileStat_Block *stat, Bit32u offset, Bit16u info); + 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, Bit16u info) +{ + this->drive = drive; + time = stat->time; + date = stat->date; + attr = stat->attr; + size = stat->size; + fileBegin = offset; + filePos = fileBegin; + fileEnd = fileBegin + size; + cachedSector = -1; + open = true; + info = info; + this->name = NULL; + SetName(name); +} + +bool isoFile::Read(Bit8u *data, Bit16u *size) +{ + if (filePos + *size > fileEnd) + *size = fileEnd - filePos; + + Bit16u nowSize = 0; + int sector = filePos / ISO_FRAMESIZE; + Bit16u sectorPos = 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 info; +} + +int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit); +bool MSCDEX_HasMediaChanged(Bit8u subUnit); +bool MSCDEX_GetVolumeName(Bit8u subUnit, char* name); + +isoDrive::isoDrive(char driveLetter, const char *fileName, Bit8u mediaid, int &error) +{ + error = MSCDEX_AddDrive(driveLetter, fileName, subUnit); + + if (!error) { + if (loadImage()) { + strcpy(info, "isoDrive"); + searchCache.clear(); + dirIter = searchCache.end(); + this->mediaid = mediaid; + if (!MSCDEX_GetVolumeName(subUnit, discLabel)) strcpy(discLabel, ""); + } else error = 6; + } +} + +isoDrive::~isoDrive() { } + +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, 0x202); + (*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; + } + + Bit32u sectorStart = EXTENT_LOCATION(de); + Bit32u sectorEnd = sectorStart + DATA_LENGTH(de) / ISO_FRAMESIZE; + if (DATA_LENGTH(de) % ISO_FRAMESIZE != 0) sectorEnd++; + searchCache.clear(); + + for(Bit32u sector = sectorStart; sector < sectorEnd; sector++) { + Bit8u block[ISO_FRAMESIZE]; + readSector(block, sector); + + Bit32u pos = 0; + while (pos < ISO_FRAMESIZE && block[pos] != 0) { + isoDirEntry tmp; + int length = readDirEntry(&tmp, &block[pos]); + if (length < 0) return false; + searchCache.push_back(tmp); + pos += length; + } + } + dirIter = searchCache.begin(); + + Bit8u attr; + char pattern[ISO_MAXPATHNAME]; + dta.GetSearchParams(attr, pattern); + if ((attr & DOS_ATTR_VOLUME) && ((*dir == 0) || fcb_findfirst)) { + // Get Volume Label (DOS_ATTR_VOLUME) and only in basedir + 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); + + while (dirIter != searchCache.end()) { + isoDirEntry &de = *dirIter; + Bit8u findAttr; + if (IS_DIR(de.fileFlags)) findAttr = DOS_ATTR_DIRECTORY; + else findAttr = DOS_ATTR_ARCHIVE; + + 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]; + 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); + + dirIter++; + return true; + } + dirIter++; + } + + 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_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; +} + +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 + memcpy(de, data, data[0]); + + // 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 (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 > 31) return -1; + de->ident[de->fileIdentLength] = 0; + } + } else { + if (de->fileIdentLength > 37) 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 + int tmp = strlen((char*)de->ident); + if (tmp > 0 && de->ident[tmp - 1] == '.') de->ident[tmp - 1] = 0; + } + return de->length; +} + +bool isoDrive :: loadImage() +{ + isoPVD pvd; + readSector((Bit8u*)(&pvd), ISO_FIRST_VD); + if (pvd.type != 1 || strncmp((char*)pvd.standardIdent, "CD001", 5) || pvd.version != 1) return false; + return (readDirEntry(&this->rootEntry, pvd.rootEntry)); +} + +bool isoDrive :: lookupSingle(isoDirEntry *de, const char *name, Bit32u start, Bit32u length) +{ + Bit32u end = start + length / ISO_FRAMESIZE; + if (length % ISO_FRAMESIZE != 0) end++; + + for(Bit32u i = start; i < end; i++) { + Bit8u sector[ISO_FRAMESIZE]; + if (!readSector(sector, i)) return false; + + int pos = 0; + while (sector[pos] != 0 && pos < ISO_FRAMESIZE) { + int deLength = readDirEntry(de, §or[pos]); + if (deLength < 1) return false; + pos += deLength; + int tmp = strncasecmp((char*)de->ident, name, 38); + if (tmp == 0) return true; + } + } + return false; +} + +bool isoDrive :: lookup(isoDirEntry *de, const char *path) +{ + *de = this->rootEntry; + if (!strcmp(path, "")) return true; + + char isoPath[ISO_MAXPATHNAME]; + strncpy(isoPath, path, ISO_MAXPATHNAME); + strreplace(isoPath, '\\', '/'); + + int beginPos = 0; + int pos = 0; + while (isoPath[pos] != 0) { + if (isoPath[pos] == '/') { + char name[38]; + strncpy(name, &isoPath[beginPos], pos - beginPos); + name[pos - beginPos] = 0; + beginPos = pos + 1; + if (!IS_DIR(de->fileFlags)) return false; + if (!lookupSingle(de, name, EXTENT_LOCATION(*de), DATA_LENGTH(*de))) return false; + } + pos++; + } + return lookupSingle(de, &isoPath[beginPos], EXTENT_LOCATION(*de), DATA_LENGTH(*de)); +} diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index 98c0a1d..c9f2632 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.44 2004/01/11 16:48:32 qbix79 Exp $ */ +/* $Id: drive_local.cpp,v 1.51 2004/08/13 19:43:02 qbix79 Exp $ */ #include #include @@ -39,6 +39,7 @@ public: bool Seek(Bit32u * pos,Bit32u type); bool Close(); Bit16u GetInformation(void); + bool UpdateDateTimeFromHost(void); private: FILE * fhandle; enum { NONE,READ,WRITE } last_action; @@ -102,6 +103,26 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { return true; }; +FILE * localDrive::GetSystemFilePtr(char * name, char * 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 *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); @@ -115,7 +136,7 @@ bool localDrive::FileUnlink(char * name) { }; -bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) { +bool localDrive::FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst) { char tempDir[CROSS_LEN]; strcpy(tempDir,basedir); @@ -130,7 +151,7 @@ bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) { if (tempDir[strlen(tempDir)-1]!=CROSS_FILESPLIT) strcat(tempDir,end); Bitu id; - if (!dirCache.FindFirst(tempDir,(Bitu)dos.dta,id)) + if (!dirCache.FindFirst(tempDir,id)) { DOS_SetError(DOSERR_PATH_NOT_FOUND); return false; @@ -140,19 +161,17 @@ bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) { Bit8u sAttr; dta.GetSearchParams(sAttr,tempDir); - if ((sAttr & DOS_ATTR_VOLUME) && (*_dir==0)) { + if ( (sAttr & DOS_ATTR_VOLUME) && ( (*_dir==0) || fcb_findfirst ) ) { // Get Volume Label (DOS_ATTR_VOLUME) and only in basedir + // or it's a fcb findfirst as that always returns label if ( strcmp(dirCache.GetLabel(), "") == 0 ) { LOG(LOG_DOSMISC,LOG_ERROR)("DRIVELABEL REQUESTED: none present, returned NOLABEL"); - dta.SetResult("NOLABEL",0,0,0,DOS_ATTR_VOLUME); - return true; - } - - if (WildFileCmp(dirCache.GetLabel(),tempDir)) { - // Get Volume Label - dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); + dta.SetResult("NO_LABEL",0,0,0,DOS_ATTR_VOLUME); return true; } + // Get Volume Label && ignore search string (pandora) + dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); + return true; } return FindNext(dta); } @@ -437,6 +456,21 @@ localFile::localFile(const char* _name, FILE * handle,Bit16u devinfo) { SetName(_name); } +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 // ******************************************** @@ -505,7 +539,7 @@ bool cdromDrive::GetFileAttr(char * name,Bit16u * attr) return result; }; -bool cdromDrive::FindFirst(char * _dir,DOS_DTA & dta) +bool cdromDrive::FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst) { // If media has changed, reInit drivecache. if (MSCDEX_HasMediaChanged(subUnit)) { diff --git a/src/dos/drive_virtual.cpp b/src/dos/drive_virtual.cpp index d40a9a5..9a97833 100644 --- a/src/dos/drive_virtual.cpp +++ b/src/dos/drive_virtual.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -185,8 +185,14 @@ bool Virtual_Drive::FileExists(const char* name){ return false; } -bool Virtual_Drive::FindFirst(char * _dir,DOS_DTA & dta) { +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_ARCHIVE); + return true; + } return FindNext(dta); } diff --git a/src/dos/drives.cpp b/src/dos/drives.cpp index e5720ff..d0c0cfb 100644 --- a/src/dos/drives.cpp +++ b/src/dos/drives.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/dos/drives.h b/src/dos/drives.h index 3691fba..63eb536 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -9,21 +9,23 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.19 2004/01/10 14:03:34 qbix79 Exp $ */ +/* $Id: drives.h,v 1.23 2004/08/13 19:43:02 qbix79 Exp $ */ #ifndef _DRIVES_H__ #define _DRIVES_H__ +#include #include #include "dos_system.h" #include "shell.h" /* for DOS_Shell */ +#include "bios.h" /* for fatDrive */ bool WildFileCmp(const char * file, const char * wild); @@ -31,12 +33,14 @@ 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 * name, char * type); + virtual bool GetSystemFilename(char *sysName, char *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); + 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); @@ -61,6 +65,127 @@ private: } 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); +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; +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 * 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: @@ -72,13 +197,119 @@ public: 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); + virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false); virtual void SetDir(const char* path); virtual bool isRemote(void); private: Bit8u subUnit; }; +#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[38]; // can be smaller +} GCC_ATTRIBUTE(packed); + +#ifdef _MSC_VER +#pragma pack () +#endif + +#if defined (WORD_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_MAXPATHNAME 256 +#define ISO_FIRST_VD 16 +#define IS_DIR(fileFlags) (fileFlags & ISO_DIRECTORY) + +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); + bool readSector(Bit8u *buffer, Bit32u sector); +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); + + std::vector searchCache; + std::vector::iterator dirIter; + isoDirEntry rootEntry; + Bit8u mediaid; + Bit8u subUnit; + char discLabel[32]; +}; + struct VFILE_Block; class Virtual_Drive: public DOS_Drive { @@ -90,7 +321,7 @@ public: bool RemoveDir(char * dir); bool MakeDir(char * dir); bool TestDir(char * dir); - bool FindFirst(char * _dir,DOS_DTA & dta); + 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); diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 4a37dba..5a18410 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.61 2004/02/02 15:42:38 harekiet Exp $ */ +/* $Id: dosbox.cpp,v 1.80 2004/09/21 19:32:15 qbix79 Exp $ */ #include #include @@ -50,7 +50,7 @@ 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*); @@ -58,9 +58,11 @@ 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*); @@ -73,13 +75,23 @@ void MOUSE_Init(Section*); void SBLASTER_Init(Section*); void GUS_Init(Section*); void MPU401_Init(Section*); -void ADLIB_Init(Section*); void PCSPEAKER_Init(Section*); void TANDYSOUND_Init(Section*); -void CMS_Init(Section*); void DISNEY_Init(Section*); void SERIAL_Init(Section*); + +#if C_MODEM void MODEM_Init(Section*); +#endif + +#if C_IPX +void IPX_Init(Section*); +#endif + +#if C_DIRECTSERIAL +void DIRECTSERIAL_Init(Section* sec); +#endif +void SID_Init(Section* sec); void PIC_Init(Section*); void TIMER_Init(Section*); @@ -92,7 +104,6 @@ void MSCDEX_Init(Section*); /* Dos Internal mostly */ void EMS_Init(Section*); void XMS_Init(Section*); -void DPMI_Init(Section*); void AUTOEXEC_Init(Section*); void SHELL_Init(void); @@ -101,7 +112,9 @@ void INT10_Init(Section*); static LoopHandler * loop; -Bits RemainTicks;; +bool SDLNetInited; + +Bits RemainTicks; Bits LastTicks; static Bitu Normal_Loop(void) { @@ -166,7 +179,7 @@ static void DOSBOX_RealInit(Section * sec) { DOSBOX_SetLoop(&Normal_Loop); MSG_Init(section); - machine=MCH_AUTO;std::string cmd_machine; + machine=MCH_VGA;std::string cmd_machine; const char * mtype; if (control->cmdline->FindString("-machine",cmd_machine,true)) mtype=cmd_machine.c_str(); else mtype=section->Get_string("machine"); @@ -174,7 +187,6 @@ static void DOSBOX_RealInit(Section * sec) { else if (strcasecmp(mtype,"tandy")==0) machine=MCH_TANDY; else if (strcasecmp(mtype,"hercules")==0) machine=MCH_HERC; else if (strcasecmp(mtype,"vga")==0) machine=MCH_VGA; - else if (strcasecmp(mtype,"auto")==0) machine=MCH_AUTO; else LOG_MSG("DOSBOX:Unknown machine type %s",mtype); } @@ -183,11 +195,14 @@ void DOSBOX_Init(void) { Section_prop * secprop; Section_line * secline; + SDLNetInited = false; + /* Setup all the different modules making up DOSBox */ secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit); secprop->Add_string("language",""); - secprop->Add_string("machine","auto"); + secprop->Add_string("machine","vga"); + secprop->Add_string("captures","capture"); #if C_DEBUG LOG_StartUp(); @@ -196,6 +211,7 @@ void DOSBOX_Init(void) { secprop->AddInitFunction(&IO_Init); secprop->AddInitFunction(&PAGING_Init); secprop->AddInitFunction(&MEM_Init); + secprop->AddInitFunction(&HARDWARE_Init); secprop->Add_int("memsize",16); secprop->AddInitFunction(&CALLBACK_Init); secprop->AddInitFunction(&PIC_Init); @@ -207,30 +223,28 @@ void DOSBOX_Init(void) { MSG_Add("DOSBOX_CONFIGFILE_HELP", "language -- Select another language file.\n" "memsize -- Amount of memory dosbox has in megabytes.\n" - "machine -- The type of machine tries to emulate:auto,hercules,cga,tandy,vga.\n" - " Try a specific type if your game has problems with auto.\n" + "machine -- The type of machine tries to emulate:hercules,cga,tandy,vga.\n" + "captures -- Directory where things like wave,midi,screenshot get captured.\n" ); secprop=control->AddSection_prop("render",&RENDER_Init); secprop->Add_int("frameskip",0); - secprop->Add_string("snapdir","snaps"); secprop->Add_bool("aspect",false); secprop->Add_string("scaler","normal2x"); MSG_Add("RENDER_CONFIGFILE_HELP", "frameskip -- How many frames dosbox skips before drawing one.\n" - "snapdir -- Directory where screenshots get saved.\n" "aspect -- Do aspect correction.\n" "scaler -- Scaler used to enlarge/enhance low resolution modes.\n" - " Supported are none,normal2x,advmame2x\n" + " Supported are none,normal2x,advmame2x,advmame3x,advinterp2x,interp2x,tv2x.\n" ); secprop=control->AddSection_prop("cpu",&CPU_Init); secprop->Add_string("core","normal"); - secprop->Add_int("cycles",2500); + secprop->Add_int("cycles",3000); secprop->Add_int("cycleup",500); secprop->Add_int("cycledown",20); MSG_Add("CPU_CONFIGFILE_HELP", - "core -- CPU Core used in emulation: normal,full" + "core -- CPU Core used in emulation: simple,normal,full" #if (C_DYNAMIC_X86) ",dynamic" #endif @@ -253,7 +267,7 @@ void DOSBOX_Init(void) { secprop->Add_bool("nosound",false); secprop->Add_int("rate",22050); secprop->Add_int("blocksize",2048); - secprop->Add_string("wavedir","waves"); + secprop->Add_int("prebuffer",10); MSG_Add("MIXER_CONFIGFILE_HELP", "nosound -- Enable silent mode, sound is still emulated though.\n" @@ -261,51 +275,45 @@ void DOSBOX_Init(void) { " probably lower their sound quality.\n" "blocksize -- Mixer block size, larger blocks might help sound stuttering\n" " but sound will also be more lagged.\n" - "wavedir -- Directory where saved sound output goes when you use the\n" - " sound record key-combination, check README file.\n" + "prebuffer -- How many milliseconds of data to keep on top of the blocksize.\n" ); secprop=control->AddSection_prop("midi",&MIDI_Init); secprop->AddInitFunction(&MPU401_Init); secprop->Add_bool("mpu401",true); + secprop->Add_bool("intelligent",true); secprop->Add_string("device","default"); secprop->Add_string("config",""); MSG_Add("MIDI_CONFIGFILE_HELP", - "mpu401 -- Enable MPU-401 Emulation.\n" - "device -- Device that will receive the MIDI data from MPU-401.\n" - " This can be default,alsa,oss,win32,coreaudio,none.\n" - "config -- Special configuration options for the device.\n" + "mpu401 -- Enable MPU-401 Emulation.\n" + "intelligent -- Operate in Intelligent mode.\n" + "device -- Device that will receive the MIDI data from MPU-401.\n" + " This can be default,alsa,oss,win32,coreaudio,none.\n" + "config -- Special configuration options for the device.\n" ); #if C_DEBUG secprop=control->AddSection_prop("debug",&DEBUG_Init); #endif secprop=control->AddSection_prop("sblaster",&SBLASTER_Init); - secprop->Add_bool("sblaster",true); - secprop->Add_hex("base",0x220); + secprop->Add_string("type","sb16"); + secprop->Add_hex("base",0x220); secprop->Add_int("irq",7); secprop->Add_int("dma",1); -// secprop->Add_int("hdma",5); - secprop->Add_int("sbrate",22050); - secprop->AddInitFunction(&ADLIB_Init); - secprop->Add_bool("adlib",true); - secprop->Add_int("adlibrate",22050); - secprop->Add_string("adlibmode","adlib"); - secprop->AddInitFunction(&CMS_Init); - secprop->Add_bool("cms",false); - secprop->Add_int("cmsrate",22050); + secprop->Add_int("hdma",5); + secprop->Add_bool("mixer",true); + secprop->Add_string("oplmode","auto"); + secprop->Add_int("oplrate",22050); MSG_Add("SBLASTER_CONFIGFILE_HELP", - "sblaster -- Enable the soundblaster emulation.\n" - "base,irq,dma -- The IO/IRQ/DMA address of the soundblaster.\n" - "sbrate -- Sample rate of soundblaster emulation.\n" - "adlib -- Enable the adlib emulation.\n" - "adlibrate -- Sample rate of adlib emulation.\n" - "cms -- Enable the Creative Music System/Gameblaster emulation.\n" - " Enabling both the adlib and cms might give conflicts!\n" - "cmsrate -- Sample rate of cms emulation.\n" - ); + "type -- Type of sblaster to emulate:none,sb1,sb2,sbpro1,sbpro2,sb16.\n" + "base,irq,dma,hdma -- The IO/IRQ/DMA/High DMA address of the soundblaster.\n" + "mixer -- Allow the soundblaster mixer to modify the dosbox mixer.\n" + "oplmode -- Type of OPL emulation: auto,cms,opl2,dualopl2,opl3.\n" + " On auto the mode is determined by sblaster type.\n" + "oplrate -- Sample rate of OPL music emulation.\n" + ); secprop=control->AddSection_prop("gus",&GUS_Init); secprop->Add_bool("gus",true); @@ -332,7 +340,6 @@ void DOSBOX_Init(void) { secprop->Add_bool("pcspeaker",true); secprop->Add_int("pcrate",22050); secprop->AddInitFunction(&TANDYSOUND_Init); - secprop->Add_bool("tandy",true); secprop->Add_int("tandyrate",22050); secprop->AddInitFunction(&DISNEY_Init); secprop->Add_bool("disney",true); @@ -340,8 +347,8 @@ void DOSBOX_Init(void) { MSG_Add("SPEAKER_CONFIGFILE_HELP", "pcspeaker -- Enable PC-Speaker emulation.\n" "pcrate -- Sample rate of the PC-Speaker sound generation.\n" - "tandy -- Enable Tandy 3-Voice emulation.\n" "tandyrate -- Sample rate of the Tandy 3-Voice generation.\n" + " Tandysound emulation is present if machine is set to tandy.\n" "disney -- Enable Disney Sound Source emulation.\n" ); secprop=control->AddSection_prop("bios",&BIOS_Init); @@ -354,42 +361,54 @@ void DOSBOX_Init(void) { secprop->Add_bool("xms",true); secprop->AddInitFunction(&EMS_Init); secprop->Add_bool("ems",true); -#if (C_DEBUG) - secprop->AddInitFunction(&DPMI_Init); - secprop->Add_bool("dpmi",false); -#endif - MSG_Add("DOS_CONFIGFILE_HELP", + MSG_Add("DOS_CONFIGFILE_HELP", "xms -- Enable XMS support.\n" "ems -- Enable EMS support.\n" -#if (C_DEBUG) - "dpmi -- Enable builtin DPMI host support.\n" - " This might help in getting some games to work, but might crash others.\n" - " So be sure to try both settings.\n" -#endif ); // Mscdex secprop->AddInitFunction(&MSCDEX_Init); - #if C_MODEM secprop=control->AddSection_prop("modem",&MODEM_Init); - secprop->Add_bool("modem",true); + secprop->Add_bool("modem",false); secprop->Add_hex("comport",2); secprop->Add_int("listenport",23); MSG_Add("MODEM_CONFIGFILE_HELP", "modem -- Enable virtual modem emulation.\n" "comport -- COM Port modem is connected to.\n" - "listenport -- TCP Port the momdem listens on for incoming connections.\n" + "listenport -- TCP Port the modem listens on for incoming connections.\n" + ); +#endif +#if C_DIRECTSERIAL + secprop=control->AddSection_prop("directserial",&DIRECTSERIAL_Init); + secprop->Add_bool("directserial", false); + secprop->Add_hex("comport",1); + secprop->Add_string("realport", "COM1"); + secprop->Add_int("defaultbps", 1200); + secprop->Add_string("parity", "N"); // Could be N, E, O + secprop->Add_int("bytesize", 8); // Could be 5 to 8 + secprop->Add_int("stopbit", 1); // Could be 1 or 2 + MSG_Add("DIRECTSERIAL_CONFIGFILE_HELP", + "directserial -- Enable serial passthrough support.\n" + "comport -- COM Port inside DOSBox.\n" + "realport -- COM Port on the Host.\n" + "defaultbps -- Default BPS.\n" + "parity -- Parity of the packets. This can be N, E or O.\n" + "bytesize -- Size of each packet. This can be 5 or 8.\n" + "stopbit -- The number of stopbits. This can be 1 or 2.\n" + ); +#endif +#if C_IPX + secprop=control->AddSection_prop("ipx",&IPX_Init); + secprop->Add_bool("ipx", false); + MSG_Add("IPX_CONFIGFILE_HELP", + "ipx -- Enable ipx over UDP/IP emulation.\n" ); #endif - - secline=control->AddSection_line("autoexec",&AUTOEXEC_Init); - MSG_Add("AUTOEXEC_CONFIGFILE_HELP", "Lines in this section will be run at startup.\n" ); - control->SetStartUp(&SHELL_Init); } diff --git a/src/fpu/fpu.cpp b/src/fpu/fpu.cpp index e63a9e5..637712c 100644 --- a/src/fpu/fpu.cpp +++ b/src/fpu/fpu.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.cpp,v 1.17 2004/01/19 18:54:15 qbix79 Exp $ */ +/* $Id: fpu.cpp,v 1.22 2004/09/08 08:46:37 qbix79 Exp $ */ #include "dosbox.h" #if C_FPU @@ -61,6 +61,20 @@ INLINE void FPU_SetCW(Bitu word) { fpu.ex_mask = word & 0x3f; } +static Bit16u FPU_GetTag(void){ + Bit16u tag=0; + for(Bitu i=0;i<8;i++) + tag |= ( (fpu.tags[i]&3) <<(2*i)); + return tag; +} + +static void FPU_SetTag(Bit16u tag) +{ + for(Bitu i=0;i<8;i++) + fpu.tags[i]= static_cast((tag >>(2*i))&3); +} + + INLINE Bitu FPU_GET_TOP(void){ @@ -109,7 +123,7 @@ INLINE Bitu FPU_GET_C3(void){ /* 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; + TOP=FPU_GET_TOP() after a write; */ static void EATREE(Bitu _rm){ Bitu group=(_rm >> 3) & 7; @@ -152,7 +166,7 @@ void FPU_ESC0_EA(Bitu rm,PhysPt addr) { float f; Bit32u l; } blah; - blah.l = mem_readd(addr); + blah.l = mem_readd(addr); fpu.regs[8].d = static_cast(blah.f); EATREE(rm); } @@ -234,12 +248,18 @@ void FPU_ESC1_EA(Bitu rm,PhysPt addr) { } FPU_FPOP(); break; - case 0x05: /*FLDCW */ + case 0x04: /* FLDENV */ + FPU_FLDENV(addr); + break; + case 0x05: /* FLDCW */ { Bit16u temp =mem_readw(addr); FPU_SetCW(temp); } break; + case 0x06: /* FSTENV */ + FPU_FSTENV(addr); + break; case 0x07: /* FNSTCW*/ mem_writew(addr,fpu.cw); break; @@ -391,7 +411,23 @@ void FPU_ESC2_EA(Bitu rm,PhysPt addr) { void FPU_ESC2_Normal(Bitu rm) { Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); - LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub); + switch(group){ + case 0x05: + switch(sub){ + case 0x01: /* FUCOMPP Almost the same as FCOMPP */ + FPU_FCOM(TOP,ST(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; + } } @@ -417,10 +453,13 @@ void FPU_ESC3_EA(Bitu rm,PhysPt addr) { FPU_FPOP(); break; case 0x05: /* FLD 80 Bits Real */ - FPU_FLD80(addr); + { + Real64 val = FPU_FLD80(addr); + FPU_PUSH(val); + } break; case 0x07: /* FSTP 80 Bits Real */ - FPU_ST80(addr); + FPU_ST80(addr,TOP); FPU_FPOP(); break; default: @@ -446,7 +485,7 @@ void FPU_ESC3_Normal(Bitu rm) { break; case 0x04: //FNSETPM case 0x05: //FRSTPM - LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); +// LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); FPU_FNOP(); break; default: @@ -528,6 +567,12 @@ void FPU_ESC5_EA(Bitu rm,PhysPt addr) { mem_writed(addr+4,fpu.regs[TOP].l.upper); FPU_FPOP(); break; + case 0x04: /* FSTOR */ + FPU_FSTOR(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); @@ -664,7 +709,11 @@ void FPU_ESC7_EA(Bitu rm,PhysPt addr) { FPU_FPOP(); break; case 0x04: /* FBLD packed BCD */ - //Don't think anybody will ever use this. + { + Real64 in = FPU_FBLD(addr); + FPU_PUSH(in); + } + break; default: LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub); break; diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h index f681b80..7f8a2b3 100644 --- a/src/fpu/fpu_instructions.h +++ b/src/fpu/fpu_instructions.h @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.16 2004/01/11 09:41:52 qbix79 Exp $ */ +/* $Id: fpu_instructions.h,v 1.21 2004/09/09 18:36:50 qbix79 Exp $ */ static void FPU_FINIT(void) { @@ -262,10 +262,33 @@ static void FPU_FBST(PhysPt addr) mem_writeb(addr+9,p); } +static Real64 FPU_FBLD(PhysPt addr) +{ + 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; + return temp; +} + + #define BIAS80 16383 #define BIAS64 1023 -static void FPU_FLD80(PhysPt addr) +static Real64 FPU_FLD80(PhysPt addr) { struct{ Bit16s begin; @@ -283,20 +306,21 @@ static void FPU_FLD80(PhysPt addr) Bit64s sign = (test.begin &0x8000)?1:0; FPU_Reg result; result.ll= (sign <<63)|(exp64final << 52)| mant64; - FPU_PUSH(result.d); + return result.d; + //mant64= test.mant80/2***64 * 2 **53 } -static void FPU_ST80(PhysPt addr) +static void FPU_ST80(PhysPt addr,Bitu reg) { struct{ Bit16s begin; FPU_Reg eind; } test; - Bit64s sign80= (fpu.regs[TOP].ll&LONGTYPE(0x8000000000000000))?1:0; - Bit64s exp80 = fpu.regs[TOP].ll&LONGTYPE(0x7ff0000000000000); + 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[TOP].ll&LONGTYPE(0x000fffffffffffff); + Bit64s mant80 = fpu.regs[reg].ll&LONGTYPE(0x000fffffffffffff); Bit64s mant80final= (mant80 << 11) | LONGTYPE(0x8000000000000000); test.begin= (static_cast(sign80)<<15)| static_cast(exp80final); test.eind.ll=mant80final; @@ -320,3 +344,51 @@ static void FPU_FSCALE(void){ return; //2^x where x is chopped. } +static void FPU_FSTENV(PhysPt addr){ + 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 = mem_readd(addr+4); + tagbig = mem_readd(addr+8); + tag = static_cast(tagbig); + } + FPU_SetTag(tag); + FPU_SetCW(cw); +} + +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,i); + start+=10; + } +} + +static void FPU_FSTOR(PhysPt addr){ + FPU_FLDENV(addr); + Bitu start=(cpu.code.big?28:14); + for(Bitu i=0;i<8;i++){ + fpu.regs[i].d=FPU_FLD80(addr+start); + start+=10; + } +} + diff --git a/src/fpu/fpu_types.h b/src/fpu/fpu_types.h index e229571..16a4d74 100644 --- a/src/fpu/fpu_types.h +++ b/src/fpu/fpu_types.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 0aea374..8d76e38 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libgui.a -libgui_a_SOURCES = sdlmain.cpp \ - render.cpp render_normal.h render_scale2x.h render_templates.h \ +libgui_a_SOURCES = sdlmain.cpp sdl_mapper.cpp \ + render.cpp render_scalers.cpp render_scalers.h render_templates.h \ midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h midi_alsa.h diff --git a/src/gui/Makefile.in b/src/gui/Makefile.in index eab517b..a85c890 100644 --- a/src/gui/Makefile.in +++ b/src/gui/Makefile.in @@ -132,8 +132,8 @@ target_vendor = @target_vendor@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libgui.a -libgui_a_SOURCES = sdlmain.cpp \ - render.cpp render_normal.h render_scale2x.h render_templates.h \ +libgui_a_SOURCES = sdlmain.cpp sdl_mapper.cpp \ + render.cpp render_scalers.cpp render_scalers.h render_templates.h \ midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h midi_alsa.h subdir = src/gui @@ -145,14 +145,16 @@ LIBRARIES = $(noinst_LIBRARIES) libgui_a_AR = $(AR) cru libgui_a_LIBADD = -am_libgui_a_OBJECTS = sdlmain.$(OBJEXT) render.$(OBJEXT) midi.$(OBJEXT) +am_libgui_a_OBJECTS = sdlmain.$(OBJEXT) sdl_mapper.$(OBJEXT) \ + render.$(OBJEXT) render_scalers.$(OBJEXT) midi.$(OBJEXT) libgui_a_OBJECTS = $(am_libgui_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/midi.Po ./$(DEPDIR)/render.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/sdlmain.Po +@AMDEP_TRUE@ ./$(DEPDIR)/render_scalers.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/sdl_mapper.Po ./$(DEPDIR)/sdlmain.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) @@ -193,6 +195,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/render.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/render_scalers.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdl_mapper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdlmain.Po@am__quote@ .cpp.o: diff --git a/src/gui/midi.cpp b/src/gui/midi.cpp index bbbb2d9..80cb3cf 100644 --- a/src/gui/midi.cpp +++ b/src/gui/midi.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -24,8 +24,12 @@ #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 @@ -47,7 +51,7 @@ Bit8u MIDI_evt_len[256] = { 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xe0 - 0,2,3,2, 0,0,1,1, 1,0,1,1, 1,0,1,1 // 0xf0 + 0,2,3,2, 0,0,1,0, 1,0,1,1, 1,0,1,0 // 0xf0 }; class MidiHandler; @@ -62,7 +66,7 @@ public: }; virtual bool Open(const char * conf) { return true; }; virtual void Close(void) {}; - virtual void PlayMsg(Bit32u msg) {}; + virtual void PlayMsg(Bit8u * msg) {}; virtual void PlaySysex(Bit8u * sysex,Bitu len) {}; virtual char * GetName(void) { return "none"; }; MidiHandler * next; @@ -96,49 +100,130 @@ static struct { Bitu status; Bitu cmd_len; Bitu cmd_pos; - - Bit32u cmd_msg; - Bit8u data[4]; + Bit8u cmd_buf[8]; struct { Bit8u buf[SYSEX_SIZE]; Bitu used; - bool active; } sysex; bool available; MidiHandler * handler; + struct { + FILE * handle; + Bit8u buffer[RAWBUF+SYSEX_SIZE]; + bool capturing; + Bitu used,done; + Bit32u last; + } raw; } midi; +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 +}; + +#define ADDBUF(_VAL_) midi.raw.buffer[midi.raw.used++]=(Bit8u)(_VAL_); +static INLINE void RawAddNumber(Bit32u val) { + if (val & 0xfe00000) ADDBUF(0x80|((val >> 21) & 0x7f)); + if (val & 0xfffc000) ADDBUF(0x80|((val >> 14) & 0x7f)); + if (val & 0xfffff80) ADDBUF(0x80|((val >> 7) & 0x7f)); + ADDBUF(val & 0x7f); +} +static INLINE void RawAddDelta(void) { + if (!midi.raw.handle) { + midi.raw.handle=OpenCaptureFile("Raw Midi",".mid"); + if (!midi.raw.handle) { + midi.raw.capturing=false; + return; + } + fwrite(midi_header,1,sizeof(midi_header),midi.raw.handle); + midi.raw.last=PIC_Ticks; + } + Bit32u delta=PIC_Ticks-midi.raw.last; + midi.raw.last=PIC_Ticks; + RawAddNumber(delta); +} + +static INLINE void RawAddData(Bit8u * data,Bitu len) { + for (Bitu i=0;i=RAWBUF) { + fwrite(midi.raw.buffer,1,midi.raw.used,midi.raw.handle); + midi.raw.done+=midi.raw.used; + midi.raw.used=0; + } +} + +static void MIDI_SaveRawEvent(void) { + /* Check for previously opened wave file */ + if (midi.raw.capturing) { + LOG_MSG("Stopping raw midi saving."); + midi.raw.capturing=false; + if (!midi.raw.handle) return; + ADDBUF(0x00);//Delta time + ADDBUF(0xff);ADDBUF(0x2F);ADDBUF(0x00); //End of track event + fwrite(midi.raw.buffer,1,midi.raw.used,midi.raw.handle); + midi.raw.done+=midi.raw.used; + fseek(midi.raw.handle,18, SEEK_SET); + Bit8u size[4]; + size[0]=(Bit8u)(midi.raw.done >> 24); + size[1]=(Bit8u)(midi.raw.done >> 16); + size[2]=(Bit8u)(midi.raw.done >> 8); + size[3]=(Bit8u)(midi.raw.done >> 0); + fwrite(&size,1,4,midi.raw.handle); + fclose(midi.raw.handle); + midi.raw.handle=0; + } else { + LOG_MSG("Preparing for raw midi capture, will start with first data."); + midi.raw.used=0; + midi.raw.done=0; + midi.raw.handle=0; + midi.raw.capturing=true; + } +} + + void MIDI_RawOutByte(Bit8u data) { - /* Test for a new status byte */ - if (midi.sysex.active && !(data&0x80)) { - if (midi.sysex.used<(SYSEX_SIZE-1)) midi.sysex.buf[midi.sysex.used++]=data; - return; - } else if (data&0x80) { - if (midi.sysex.active) { - /* Play a sysex message */ + /* 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); - midi.sysex.active=false; - if (data==0xf7) return; + if (midi.raw.capturing) { + RawAddDelta(); + ADDBUF(0xf0); + RawAddNumber(midi.sysex.used-1); + RawAddData(&midi.sysex.buf[1],midi.sysex.used-1); + } } + } + if (data&0x80) { midi.status=data; midi.cmd_pos=0; - midi.cmd_msg=0; + midi.cmd_len=MIDI_evt_len[data]; if (midi.status==0xf0) { - midi.sysex.active=true; midi.sysex.buf[0]=0xf0; midi.sysex.used=1; - return; } - midi.cmd_len=MIDI_evt_len[data]; } - midi.cmd_msg|=data << (8 * midi.cmd_pos); - midi.cmd_pos++; - if (midi.cmd_pos >= midi.cmd_len) { - midi.handler->PlayMsg(midi.cmd_msg); - midi.cmd_msg=midi.status; - midi.cmd_pos=1; + if (midi.cmd_len) { + midi.cmd_buf[midi.cmd_pos++]=data; + if (midi.cmd_pos >= midi.cmd_len) { + if (midi.raw.capturing) { + RawAddDelta(); + RawAddData(midi.cmd_buf,midi.cmd_len); + } + midi.handler->PlayMsg(midi.cmd_buf); + midi.cmd_pos=1; //Use Running status + } } } @@ -146,12 +231,22 @@ bool MIDI_Available(void) { return midi.available; } +static void MIDI_Stop(Section* sec) { + if (midi.raw.handle) MIDI_SaveRawEvent(); +} + void MIDI_Init(Section * sec) { Section_prop * section=static_cast(sec); const char * dev=section->Get_string("device"); const char * conf=section->Get_string("config"); /* If device = "default" go for first handler that works */ MidiHandler * handler; + MAPPER_AddHandler(MIDI_SaveRawEvent,MK_f8,MMOD1|MMOD2,"caprawmidi","Cap MIDI"); + sec->AddDestroyFunction(&MIDI_Stop); + midi.status=0x00; + midi.cmd_pos=0; + midi.cmd_len=0; + midi.raw.capturing=false; if (!strcasecmp(dev,"default")) goto getdefault; handler=handler_list; while (handler) { @@ -180,6 +275,5 @@ getdefault: handler=handler->next; } /* This shouldn't be possible */ - midi.available=false; } diff --git a/src/gui/midi_alsa.h b/src/gui/midi_alsa.h index a3e6a5d..7246f88 100644 --- a/src/gui/midi_alsa.h +++ b/src/gui/midi_alsa.h @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.7 2004/01/26 15:10:16 qbix79 Exp $ */ +/* $Id: midi_alsa.h,v 1.9 2004/08/04 09:12:54 qbix79 Exp $ */ #define ALSA_PCM_OLD_HW_PARAMS_API #define ALSA_PCM_OLD_SW_PARAMS_API @@ -75,45 +75,38 @@ public: send_event(1); } - void PlayMsg(Bit32u msg) { + void PlayMsg(Bit8u * msg) { unsigned int midiCmd[4]; ev.type = SND_SEQ_EVENT_OSS; - if (msg == 247) // to accomadate lure of the temptress - return; + ev.data.raw32.d[0] = msg[0]; + ev.data.raw32.d[1] = msg[1]; + ev.data.raw32.d[2] = msg[2]; - midiCmd[3] = (msg & 0xFF000000) >> 24; - midiCmd[2] = (msg & 0x00FF0000) >> 16; - midiCmd[1] = (msg & 0x0000FF00) >> 8; - midiCmd[0] = (msg & 0x000000FF); - ev.data.raw32.d[0] = midiCmd[0]; - ev.data.raw32.d[1] = midiCmd[1]; - ev.data.raw32.d[2] = midiCmd[2]; - - unsigned char chanID = midiCmd[0] & 0x0F; - switch (midiCmd[0] & 0xF0) { + unsigned char chanID = msg[0] & 0x0F; + switch (msg[0] & 0xF0) { case 0x80: - snd_seq_ev_set_noteoff(&ev, chanID, midiCmd[1], midiCmd[2]); + snd_seq_ev_set_noteoff(&ev, chanID, msg[1], msg[2]); send_event(1); break; case 0x90: - snd_seq_ev_set_noteon(&ev, chanID, midiCmd[1], midiCmd[2]); + snd_seq_ev_set_noteon(&ev, chanID, msg[1], msg[2]); send_event(1); break; case 0xB0: - snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]); + snd_seq_ev_set_controller(&ev, chanID, msg[1], msg[2]); send_event(1); break; case 0xC0: - snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]); + snd_seq_ev_set_pgmchange(&ev, chanID, msg[1]); send_event(0); break; case 0xD0: - snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]); + snd_seq_ev_set_chanpress(&ev, chanID, msg[1]); send_event(0); break; case 0xE0:{ - long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000; + long theBend = ((long)msg[1] + (long)(msg[2] << 7)) - 0x2000; snd_seq_ev_set_pitchbend(&ev, chanID, theBend); send_event(1); } diff --git a/src/gui/midi_coreaudio.h b/src/gui/midi_coreaudio.h index 0d7f963..cb519d4 100644 --- a/src/gui/midi_coreaudio.h +++ b/src/gui/midi_coreaudio.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -76,12 +76,8 @@ public: } } - void PlayMsg(Bit32u msg) { - MusicDeviceMIDIEvent(m_musicDevice, - (msg & 0x000000FF), - (msg & 0x0000FF00) >> 8, - (msg & 0x00FF0000) >> 16, - 0); + void PlayMsg(Bit8u * msg) { + MusicDeviceMIDIEvent(m_musicDevice,msg[0],msg[1],msg[2],0); } void PlaySysex(Bit8u * sysex, Bitu len) { diff --git a/src/gui/midi_oss.h b/src/gui/midi_oss.h index 62e1dfa..e0bfc0d 100644 --- a/src/gui/midi_oss.h +++ b/src/gui/midi_oss.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -45,15 +45,15 @@ public: if (!isOpen) return; if (device>0) close(device); }; - void PlayMsg(Bit32u msg) { + void PlayMsg(Bit8u * msg) { Bit8u buf[128];Bitu pos=0; - Bitu len=MIDI_evt_len[msg & 0xff]; + Bitu len=MIDI_evt_len[*msg]; for (;len>0;len--) { buf[pos++] = SEQ_MIDIPUTC; - buf[pos++] = msg & 0xff; + buf[pos++] = *msg; buf[pos++] = device_num; buf[pos++] = 0; - msg >>=8; + msg++; } write(device,buf,pos); }; diff --git a/src/gui/midi_win32.h b/src/gui/midi_win32.h index b08652b..514f498 100644 --- a/src/gui/midi_win32.h +++ b/src/gui/midi_win32.h @@ -9,13 +9,16 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif #include #include @@ -42,8 +45,8 @@ public: midiOutClose(m_out); CloseHandle (m_event); }; - void PlayMsg(Bit32u msg) { - midiOutShortMsg(m_out, msg); + void PlayMsg(Bit8u * msg) { + midiOutShortMsg(m_out, *(Bit32u*)msg); }; void PlaySysex(Bit8u * sysex,Bitu len) { if (WaitForSingleObject (m_event, 2000) == WAIT_TIMEOUT) { diff --git a/src/gui/render.cpp b/src/gui/render.cpp index b059c91..e90b809 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.25 2004/01/31 22:38:27 harekiet Exp $ */ +/* $Id: render.cpp,v 1.30 2004/08/04 09:12:54 qbix79 Exp $ */ #include #include @@ -27,12 +27,12 @@ #include "video.h" #include "render.h" #include "setup.h" -#include "keyboard.h" +#include "mapper.h" #include "cross.h" +#include "hardware.h" #include "support.h" -#define RENDER_MAXWIDTH 1280 -#define RENDER_MAXHEIGHT 1024 +#include "render_scalers.h" struct PalData { struct { @@ -43,52 +43,35 @@ struct PalData { } rgb[256]; volatile Bitu first; volatile Bitu last; - union { - Bit32u bpp32[256]; - Bit16u bpp16[256]; - Bit32u yuv[256]; - } lookup; }; - static struct { struct { Bitu width; Bitu height; Bitu bpp; - Bitu pitch; - Bitu scalew; - Bitu scaleh; + bool dblw,dblh; double ratio; } src; struct { Bitu width; Bitu height; Bitu pitch; - Bitu line; - Bitu bpp; + GFX_Modes mode; RENDER_Operation type; RENDER_Operation want_type; RENDER_Line_Handler line_handler; - Bit8u * draw; - Bit8u * buffer; - Bit8u * pixels; } op; struct { Bitu count; Bitu max; } frameskip; PalData pal; - struct { - Bit8u hlines[RENDER_MAXHEIGHT]; - } normal; #if (C_SSHOT) struct { - RENDER_Operation type; - Bitu bpp,width,height,line; - const char * dir; + Bitu bpp,width,height,rowlen; Bit8u * buffer,* draw; - bool usesrc; + bool take,taking; } shot; #endif bool active; @@ -96,33 +79,19 @@ static struct { bool updating; } render; -Bit8u render_line_cache[4][RENDER_MAXWIDTH*4]; //Bit32u pixels RENDER_Line_Handler RENDER_DrawLine; -Bit8u * RENDER_TempLine; - -/* Forward declerations */ -static void RENDER_ResetPal(void); - -/* Include the different rendering routines */ -#include "render_templates.h" -#include "render_normal.h" -#include "render_scale2x.h" - #if (C_SSHOT) #include -static void RENDER_ShotDraw(Bit8u * src) { - if (render.shot.usesrc) { - memcpy(render.shot.draw,src,render.shot.line); - render.shot.draw+=render.shot.line; - } else render.op.line_handler(src); +static void RENDER_ShotDraw(const Bit8u * src) { + memcpy(render.shot.draw,src,render.shot.rowlen); + render.shot.draw+=render.shot.rowlen; + render.op.line_handler(src); } /* Take a screenshot of the data that should be rendered */ static void TakeScreenShot(Bit8u * bitmap) { - Bitu last=0;char file_name[CROSS_LEN]; - DIR * dir;struct dirent * dir_ent; png_structp png_ptr; png_infop info_ptr; png_bytep * row_pointers; @@ -130,31 +99,9 @@ static void TakeScreenShot(Bit8u * bitmap) { Bitu i; /* Find a filename to open */ - dir=opendir(render.shot.dir); - if (!dir) { - LOG_MSG("Can't open snapshot directory %s",render.shot.dir); - return; - } - while (dir_ent=readdir(dir)) { - char tempname[CROSS_LEN]; - strcpy(tempname,dir_ent->d_name); - char * test=strstr(tempname,".png"); - if (!test) continue; - *test=0; - if (strlen(tempname)<5) continue; - if (strncmp(tempname,"snap",4)!=0) continue; - Bitu num=atoi(&tempname[4]); - if (num>=last) last=num+1; - } - closedir(dir); - sprintf(file_name,"%s%csnap%04d.png",render.shot.dir,CROSS_FILESPLIT,last); /* Open the actual file */ - FILE * fp=fopen(file_name,"wb"); - if (!fp) { - LOG_MSG("Can't open file %s for snapshot",file_name); - return; - } - + FILE * fp=OpenCaptureFile("Screenshot",".png"); + if (!fp) return; /* First try to alloacte the png structures */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL); if (!png_ptr) return; @@ -193,7 +140,7 @@ static void TakeScreenShot(Bit8u * bitmap) { /*Allocate an array of scanline pointers*/ row_pointers=(png_bytep*)malloc(render.shot.height*sizeof(png_bytep)); for (i=0;irender.pal.last) return; Bitu i; - switch (render.op.bpp) { - case 8: + switch (render.op.mode) { + case GFX_8: GFX_SetPalette(render.pal.first,render.pal.last-render.pal.first+1,(GFX_PalEntry *)&render.pal.rgb[render.pal.first]); break; - case 16: + case GFX_15: + case GFX_16: 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; - render.pal.lookup.bpp16[i]=GFX_GetRGB(r,g,b); + Scaler_PaletteLut.b16[i]=GFX_GetRGB(r,g,b); } break; - case 24: - case 32: + case GFX_32: 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; - render.pal.lookup.bpp32[i]=GFX_GetRGB(r,g,b); + Scaler_PaletteLut.b32[i]=GFX_GetRGB(r,g,b); } break; } @@ -263,7 +208,7 @@ void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) { if (render.pal.last=miny) { + Bitu templines=(Bitu)lines; + lines-=templines; + linesadded+=templines; + Scaler_Data[i]=templines-miny; + } else Scaler_Data[i]=0; + } + return linesadded; } void RENDER_ReInit(void) { if (render.updating) RENDER_EndUpdate(); Bitu width=render.src.width; Bitu height=render.src.height; - - Bitu scalew=render.src.scalew; - Bitu scaleh=render.src.scaleh; + bool dblw=render.src.dblw; + bool dblh=render.src.dblh; double gfx_scalew=1.0; double gfx_scaleh=1.0; @@ -352,130 +294,83 @@ void RENDER_ReInit(void) { else gfx_scalew*=(1/render.src.ratio); Bitu gfx_flags; - Bitu bpp=GFX_GetBestMode(render.src.bpp,gfx_flags); - Bitu index; - switch (bpp) { - case 8: index=0;break; - case 16:index=1;break; - case 24:index=2;break; - case 32:index=3;break; - } - /* Initial scaler testing */ - switch (render.op.want_type) { - case OP_Normal2x: - case OP_None: + ScalerBlock * block; + if (dblh && dblw) { render.op.type=render.op.want_type; -normalop: - if (gfx_flags & GFX_HASSCALING) { - gfx_scalew*=scalew; - gfx_scaleh*=scaleh; - render.op.line_handler=Normal_8[index]; - for (Bitu i=0;i1 && (render.op.type==OP_None)) { - render.op.line_handler=Normal_8[index]; - scalew>>=1;gfx_scaleh/=2; - } else { - render.op.line_handler=Normal_2x_8[index]; - } - } else render.op.line_handler=Normal_8[index]; - width*=scalew; - double lines=0.0; - height=0; - for (Bitu i=0;i0) ? temp_lines-1 : 0; - height+=temp_lines; - } - } - break; - case OP_AdvMame2x: - if (scalew!=2){ - render.op.type=OP_Normal2x; - goto normalop; - } - if (gfx_flags & GFX_HASSCALING) { - height=scaleh*height; - } else { - height=(Bitu)(gfx_scaleh*scaleh*height); - } - width<<=1; - { - Bits i; - double src_add=(double)height/(double)render.src.height; - double src_index=0; - double src_lines=0; - Bitu src_done=0; - Bitu height=0; - am2x.cmd_index=am2x.cmd_data; - am2x.buf_pos=0;am2x.buf_used=0; - for (i=0;i<=(Bits)render.src.height;i++) { - src_lines+=src_add; - Bitu lines=(Bitu)src_lines; - src_lines-=lines; - switch (lines) { - case 0: - break; - case 1: - AdvMame2x_AddLine(i,i,i); - break; - case 2: - AdvMame2x_AddLine(i-1,i,i+1); - AdvMame2x_AddLine(i+1,i,i-1); - break; - default: - AdvMame2x_AddLine(i-1,i,i+1); - for (lines-=2;lines>0;lines--) AdvMame2x_AddLine(i,i,i); - AdvMame2x_AddLine(i+1,i,i-1); - break; - } - AdvMame2x_CheckLines(i); - } - render.op.line_handler=AdvMame2x_8_Table[index]; - } - break; + } else if (dblw) { + render.op.type=OP_Normal2x; + } else if (dblh) { + render.op.type=OP_Normal; + gfx_scaleh*=2; + } else { +forcenormal: + render.op.type=OP_Normal; } - render.op.bpp=bpp; + switch (render.op.type) { + case OP_Normal:block=&Normal_8;break; + case OP_Normal2x:block=(dblh) ? &Normal2x_8 : &NormalDbl_8;break; + case OP_AdvMame2x:block=&AdvMame2x_8;break; + case OP_AdvMame3x:block=&AdvMame3x_8;break; + case OP_Interp2x:block=&Interp2x_8;break; + case OP_AdvInterp2x:block=&AdvInterp2x_8;break; + case OP_TV2x:block=&TV2x_8;break; + } + gfx_flags=GFX_GetBestMode(block->flags); + if (!gfx_flags) { + if (render.op.type==OP_Normal) E_Exit("Failed to create a rendering output"); + else goto forcenormal; + } + /* Special test for normal2x to switch to normal with hardware scaling */ + if (gfx_flags & HAVE_SCALING && render.op.type==OP_Normal2x) { + if (dblw) gfx_scalew*=2; + if (dblh) gfx_scaleh*=2; + block=&Normal_8; + render.op.type=OP_Normal; + } + width*=block->xscale; + if (gfx_flags & HAVE_SCALING) { + height=MakeAspectTable(render.src.height,block->yscale,block->miny); + } else { + gfx_scaleh*=block->yscale; + height=MakeAspectTable(render.src.height,gfx_scaleh,block->miny); + } +/* Setup the scaler variables */ + render.op.mode=GFX_SetSize(width,height,gfx_flags,gfx_scalew,gfx_scaleh,&RENDER_ReInit);; + if (render.op.mode==GFX_NONE) E_Exit("Failed to create a rendering output"); + render.op.line_handler=block->handlers[render.op.mode]; render.op.width=width; render.op.height=height; - GFX_SetSize(width,height,bpp,gfx_scalew,gfx_scaleh,&RENDER_ReInit); + Scaler_SrcWidth=render.src.width; + Scaler_SrcHeight=render.src.height; RENDER_ResetPal(); render.active=true; } - -void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh) { - if ((!width) || (!height) || (!pitch)) { +void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,bool dblw,bool dblh) { + if (!width || !height) { render.active=false; return; } render.src.width=width; render.src.height=height; render.src.bpp=bpp; - render.src.pitch=pitch; + render.src.dblw=dblw; + render.src.dblh=dblh; render.src.ratio=render.aspect ? ratio : 1.0; - render.src.scalew=scalew; - render.src.scaleh=scaleh; RENDER_ReInit(); } -extern void GFX_SetTitle(Bits cycles, Bits frameskip); +extern void GFX_SetTitle(Bits cycles, Bits frameskip,bool paused); static void IncreaseFrameSkip(void) { if (render.frameskip.max<10) render.frameskip.max++; LOG_MSG("Frame Skip at %d",render.frameskip.max); - GFX_SetTitle(-1,render.frameskip.max); + GFX_SetTitle(-1,render.frameskip.max,false); } static void DecreaseFrameSkip(void) { if (render.frameskip.max>0) render.frameskip.max--; LOG_MSG("Frame Skip at %d",render.frameskip.max); - GFX_SetTitle(-1,render.frameskip.max); + GFX_SetTitle(-1,render.frameskip.max,false); } void RENDER_Init(Section * sec) { @@ -488,9 +383,7 @@ void RENDER_Init(Section * sec) { render.frameskip.count=0; render.updating=true; #if (C_SSHOT) - render.shot.dir=section->Get_string("snapdir"); - render.shot.usesrc=true; - KEYBOARD_AddEvent(KBD_f5,KBD_MOD_CTRL,EnableScreenShot); + MAPPER_AddHandler(EnableScreenShot,MK_f5,MMOD1,"scrshot","Screenshot"); #endif const char * scaler;std::string cline; if (control->cmdline->FindString("-scaler",cline,false)) { @@ -498,15 +391,19 @@ void RENDER_Init(Section * sec) { } else { scaler=section->Get_string("scaler"); } - if (!strcasecmp(scaler,"none")) render.op.want_type=OP_None; + if (!strcasecmp(scaler,"none")) render.op.want_type=OP_Normal; else if (!strcasecmp(scaler,"normal2x")) render.op.want_type=OP_Normal2x; else if (!strcasecmp(scaler,"advmame2x")) render.op.want_type=OP_AdvMame2x; + else if (!strcasecmp(scaler,"advmame3x")) render.op.want_type=OP_AdvMame3x; + else if (!strcasecmp(scaler,"advinterp2x")) render.op.want_type=OP_AdvInterp2x; + else if (!strcasecmp(scaler,"interp2x")) render.op.want_type=OP_Interp2x; + else if (!strcasecmp(scaler,"tv2x")) render.op.want_type=OP_TV2x; else { - render.op.want_type=OP_None; - LOG_MSG("Illegal scaler type %s,falling back to none.",scaler); + render.op.want_type=OP_Normal; + LOG_MSG("Illegal scaler type %s,falling back to normal.",scaler); } - KEYBOARD_AddEvent(KBD_f7,KBD_MOD_CTRL,DecreaseFrameSkip); - KEYBOARD_AddEvent(KBD_f8,KBD_MOD_CTRL,IncreaseFrameSkip); - GFX_SetTitle(-1,render.frameskip.max); + 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); } diff --git a/src/gui/render_normal.h b/src/gui/render_normal.h deleted file mode 100644 index 95ae4ea..0000000 --- a/src/gui/render_normal.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2002-2004 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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. - */ - -static Bit8u normal_cache[RENDER_MAXWIDTH*2*4]; - -template -static void Normal(Bit8u * src) { - Bitu line_size=LineSize(render.src.width) * (xdouble ? 2 : 1); - Bit8u * line; - if (sbpp == dbpp && !xdouble) { - line=src; - BituMove(render.op.pixels,line,line_size); - } else { - Bit8u * line_dst=&normal_cache[0]; - Bit8u * real_dst=render.op.pixels; - line=line_dst; - Bit8u * temp_src=src; - for (Bitu tempx=render.src.width;tempx;tempx--) { - Bitu val=ConvBPP(LoadSrc(temp_src)); - AddDst(line_dst,val); - AddDst(real_dst,val); - if (xdouble) { - AddDst(line_dst,val); - AddDst(real_dst,val); - } - } - } - render.op.pixels+=render.op.pitch; - for (Bitu lines=render.normal.hlines[render.op.line++];lines;lines--) { - BituMove(render.op.pixels,line,line_size); - render.op.pixels+=render.op.pitch; - } -} - - -static RENDER_Line_Handler Normal_8[4]={ - Normal<8,8 ,false>,Normal<8,16,false>, - Normal<8,24,false>,Normal<8,32,false>, -}; - -static RENDER_Line_Handler Normal_2x_8[4]={ - Normal<8,8 ,true>,Normal<8,16,true>, - Normal<8,24,true>,Normal<8,32,true>, -}; diff --git a/src/gui/render_scale2x.h b/src/gui/render_scale2x.h deleted file mode 100644 index 00705f4..0000000 --- a/src/gui/render_scale2x.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This file is part of the Scale2x project. - * - * Copyright (C) 2001-2002 Andrea Mazzoleni - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * In addition, as a special exception, Andrea Mazzoleni - * gives permission to link the code of this program with - * the MAME library (or with modified versions of MAME that use the - * same license as MAME), and distribute linked combinations including - * the two. You must obey the GNU General Public License in all - * respects for all of the code used other than MAME. If you modify - * this file, you may extend this exception to your version of the - * file, but you are not obligated to do so. If you do not wish to - * do so, delete this exception statement from your version. - */ - -/* - * This algorithm was based on the scale2x/advmame2x effect. - * http://scale2x.sourceforge.net/scale2x.html - */ - -#ifndef __SCALE2X_H -#define __SCALE2X_H - -#define AM2XBUF 16 - -static struct { - Bits buf[AM2XBUF][4]; - Bitu buf_used;Bitu buf_pos; - Bit8u cmd_data[4096]; //1024 lines should be enough? - Bit8u * cmd_index; - Bit8u * cache[4]; - Bitu cache_index; -} am2x; - - -static void AdvMame2x_AddLine(Bits s0,Bits s1,Bits s2) { - if (s0<0) s0=0; - if (s1<0) s1=0; - if (s2<0) s2=0; - if (s0>=(Bits)render.src.height) s0=render.src.height-1; - if (s1>=(Bits)render.src.height) s1=render.src.height-1; - if (s2>=(Bits)render.src.height) s2=render.src.height-1; - Bitu pos=(am2x.buf_used+am2x.buf_pos)&(AM2XBUF-1); - am2x.buf[pos][0]=s0; - am2x.buf[pos][1]=s1; - am2x.buf[pos][2]=s2; - s0=s0 > s1 ? s0 : s1; - s0=s0 > s2 ? s0 : s2; - am2x.buf[pos][3]=s0; - am2x.buf_used++; -} - -static void AdvMame2x_CheckLines(Bits last) { - Bitu lines=0;Bit8u * line_count=am2x.cmd_index++; - while (am2x.buf_used) { - if (am2x.buf[am2x.buf_pos][3]>last) break; - *am2x.cmd_index++=am2x.buf[am2x.buf_pos][0]&3; - *am2x.cmd_index++=am2x.buf[am2x.buf_pos][1]&3; - *am2x.cmd_index++=am2x.buf[am2x.buf_pos][2]&3; - am2x.buf_used--;lines++; - am2x.buf_pos=(am2x.buf_pos+1)&(AM2XBUF-1); - } - *line_count=lines; -} - -template -static void AdvMame2x_line(Bit8u * dst, const Bit8u * src0, const Bit8u * src1, const Bit8u * src2, Bitu count) { - AddDst(dst,ConvBPP(src1[0])); - AddDst(dst,ConvBPP((src1[1] == src0[0] && src2[0] != src0[0]) ? src0[0] : src1[0])); - src0++;src1++;src2++;count-=2; - /* central pixels */ - while (count) { - AddDst(dst,ConvBPP((src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) ? src0[0] : src1[0])); - AddDst(dst,ConvBPP((src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) ? src0[0] : src1[0])); - src0++;src1++;src2++;count--; - } - /* last pixel */ - AddDst(dst,ConvBPP((src1[-1] == src0[0] && src2[0] != src0[0]) ? src0[0] : src1[0])); - AddDst(dst,ConvBPP(src1[0])); -} - -template -static void AdvMame2x(Bit8u * src) { - RENDER_TempLine=render_line_cache[render.op.line&3]; - am2x.cache[render.op.line&3]=src; - Bitu lines=*am2x.cmd_index++; - while (lines--) { - Bit8u * src0=am2x.cache[*am2x.cmd_index++]; - Bit8u * src1=am2x.cache[*am2x.cmd_index++]; - Bit8u * src2=am2x.cache[*am2x.cmd_index++]; - AdvMame2x_line(render.op.pixels,src0,src1,src2,render.src.width); - render.op.pixels+=render.op.pitch; - } - render.op.line++; -} - - -static RENDER_Line_Handler AdvMame2x_8_Table[4]={ - AdvMame2x<8,8>,AdvMame2x<8,16>,AdvMame2x<8,24>,AdvMame2x<8,32> -}; - - -#endif diff --git a/src/gui/render_scalers.cpp b/src/gui/render_scalers.cpp new file mode 100644 index 0000000..a0cedbc --- /dev/null +++ b/src/gui/render_scalers.cpp @@ -0,0 +1,121 @@ +#include "dosbox.h" +#include "render_scalers.h" + +Bitu Scaler_Line; +Bitu Scaler_SrcWidth; +Bitu Scaler_SrcHeight; +Bitu Scaler_DstPitch; +Bit8u * Scaler_DstWrite; +Bit8u * Scaler_Index; +Bit8u Scaler_Data[SCALER_MAXHEIGHT*5]; //5cmds/line +PaletteLut Scaler_PaletteLut; + +static union { + Bit32u b32 [4][SCALER_MAXWIDTH]; + Bit16u b16 [4][SCALER_MAXWIDTH]; + Bit8u b8 [4][SCALER_MAXWIDTH]; +} line_cache; +static union { + Bit32u b32 [4][SCALER_MAXWIDTH*3]; + Bit16u b16 [4][SCALER_MAXWIDTH*3]; + Bit8u b8 [4][SCALER_MAXWIDTH*3]; +} write_cache; + +static Bit8u * ln[3]; + +#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 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 BituMove(_DST,_SRC,_SIZE) \ +{ \ + Bitu bsize=(_SIZE)/sizeof(Bitu); \ + Bitu * bdst=(Bitu *)(_DST); \ + Bitu * bsrc=(Bitu *)(_SRC); \ + while (bsize--) *bdst++=*bsrc++; \ +} + +#define interp_w2(P0,P1,W0,W1) \ + ((((P0&redblueMask)*W0+(P1&redblueMask)*W1)/(W0+W1)) & redblueMask) | \ + ((((P0& greenMask)*W0+(P1& greenMask)*W1)/(W0+W1)) & greenMask) +#define interp_w3(P0,P1,P2,W0,W1,W2) \ + ((((P0&redblueMask)*W0+(P1&redblueMask)*W1+(P2&redblueMask)*W2)/(W0+W1+W2)) & redblueMask) | \ + ((((P0& greenMask)*W0+(P1& greenMask)*W1+(P2& greenMask)*W2)/(W0+W1+W2)) & greenMask) +#define interp_w4(P0,P1,P2,P3,W0,W1,W2,W3) \ + ((((P0&redblueMask)*W0+(P1&redblueMask)*W1+(P2&redblueMask)*W2+(P3&redblueMask)*W3)/(W0+W1+W2+W3)) & redblueMask) | \ + ((((P0& greenMask)*W0+(P1& greenMask)*W1+(P2& greenMask)*W2+(P3& greenMask)*W3)/(W0+W1+W2+W3)) & greenMask) + +/* Include the different rendering routines */ +#define SBPP 8 +#define DBPP 8 +#include "render_templates.h" +#undef DBPP +#define DBPP 15 +#include "render_templates.h" +#undef DBPP +#define DBPP 16 +#include "render_templates.h" +#undef DBPP +#define DBPP 32 +#include "render_templates.h" +#undef SBPP +#undef DBPP + + + +ScalerBlock Normal_8={ + CAN_8|CAN_16|CAN_32|LOVE_8, + 1,1,1, + Normal_8_8,Normal_8_16,Normal_8_16,Normal_8_32 +}; + +ScalerBlock NormalDbl_8= { + CAN_8|CAN_16|CAN_32|LOVE_8, + 2,1,1, + Normal2x_8_8,Normal2x_8_16,Normal2x_8_16,Normal2x_8_32 +}; + +ScalerBlock Normal2x_8={ + CAN_8|CAN_16|CAN_32|LOVE_8, + 2,2,1, + Normal2x_8_8,Normal2x_8_16,Normal2x_8_16,Normal2x_8_32 +}; + +ScalerBlock AdvMame2x_8={ + CAN_8|CAN_16|CAN_32|LOVE_8, + 2,2,1, + AdvMame2x_8_8,AdvMame2x_8_16,AdvMame2x_8_16,AdvMame2x_8_32 +}; + +ScalerBlock AdvMame3x_8={ + CAN_8|CAN_16|CAN_32|LOVE_8, + 3,3,2, + AdvMame3x_8_8,AdvMame3x_8_16,AdvMame3x_8_16,AdvMame3x_8_32 +}; + +ScalerBlock Interp2x_8={ + CAN_16|CAN_32|LOVE_32|NEED_RGB, + 2,2,1, + 0,Interp2x_8_16,Interp2x_8_16,Interp2x_8_32 +}; + +ScalerBlock AdvInterp2x_8={ + CAN_16|CAN_32|LOVE_32|NEED_RGB, + 2,2,1, + 0,AdvInterp2x_8_16,AdvInterp2x_8_16,AdvInterp2x_8_32 +}; + +ScalerBlock TV2x_8={ + CAN_16|CAN_32|LOVE_32|NEED_RGB, + 2,2,1, + 0,TV2x_8_16,TV2x_8_16,TV2x_8_32 +}; + + diff --git a/src/gui/render_scalers.h b/src/gui/render_scalers.h new file mode 100644 index 0000000..bb6de83 --- /dev/null +++ b/src/gui/render_scalers.h @@ -0,0 +1,51 @@ +#ifndef _RENDER_SCALERS_H +#define _RENDER_SCALERS_H + +#include "render.h" +#include "video.h" + +#define SCALER_MAXWIDTH 1280 +#define SCALER_MAXHEIGHT 1024 + +extern Bitu Scaler_Line; +extern Bitu Scaler_SrcWidth; +extern Bitu Scaler_SrcHeight; +extern Bitu Scaler_DstPitch; +extern Bit8u * Scaler_DstWrite; +extern Bit8u Scaler_Data[]; +extern Bit8u * Scaler_Index; + +union PaletteLut { + Bit16u b16[256]; + Bit32u b32[256]; +}; + +extern PaletteLut Scaler_PaletteLut; + +enum RENDER_Operation { + OP_Normal, + OP_Normal2x, + OP_AdvMame2x, + OP_AdvMame3x, + OP_AdvInterp2x, + OP_Interp2x, + OP_TV2x, +}; + +struct ScalerBlock { + Bitu flags; + Bitu xscale,yscale,miny; + RENDER_Line_Handler handlers[4]; +}; + +extern ScalerBlock Normal_8; +extern ScalerBlock NormalDbl_8; +extern ScalerBlock Normal2x_8; +extern ScalerBlock AdvMame2x_8; +extern ScalerBlock AdvMame3x_8; +extern ScalerBlock AdvInterp2x_8; +extern ScalerBlock Interp2x_8; +extern ScalerBlock TV2x_8; + + +#endif diff --git a/src/gui/render_templates.h b/src/gui/render_templates.h index d5228cd..67d181e 100644 --- a/src/gui/render_templates.h +++ b/src/gui/render_templates.h @@ -1,59 +1,294 @@ -#ifdef __GNUC__ -template static INLINE void AddDst(Bit8u * & dst,Bitu val) __attribute__ ((always_inline)); -template static INLINE Bitu LineSize(Bitu pixels) __attribute__ ((always_inline)); -template static INLINE Bitu LoadSrc(Bit8u * & src) __attribute__ ((always_inline)); -template static INLINE Bitu ConvBPP(Bitu val) __attribute__ ((always_inline)); +#if DBPP == 8 +#define PSIZE 1 +#define PTYPE Bit8u +#define WC write_cache.b8 +#define LC line_cache.b8 +#define redblueMask 0 +#define greenMask 0 +#elif DBPP == 15 || DBPP == 16 +#define PSIZE 2 +#define PTYPE Bit16u +#define WC write_cache.b16 +#define LC line_cache.b16 +#if DBPP == 15 +#define redblueMask 0x7C1F +#define greenMask 0x03E0 +#elif DBPP == 16 +#define redblueMask 0xF81F +#define greenMask 0x07E0 +#endif +#elif DBPP == 32 +#define PSIZE 4 +#define PTYPE Bit32u +#define WC write_cache.b32 +#define LC line_cache.b32 +#define redblueMask 0xff00ff +#define greenMask 0xff00 #endif -template static INLINE void AddDst(Bit8u * & dst,Bitu val) { - switch (dbpp) { - case 8: *(Bit8u*)dst=val;dst+=1;break; - case 16:*(Bit16u*)dst=val;dst+=2;break; - case 24:*(Bit32u*)dst=val;dst+=3;break; - case 32:*(Bit32u*)dst=val;dst+=4;break; +#if SBPP == 8 +#if DBPP == 8 +#define PMAKE(_VAL) _VAL +#elif DBPP == 15 +#define PMAKE(_VAL) Scaler_PaletteLut.b16[_VAL] +#elif DBPP == 16 +#define PMAKE(_VAL) Scaler_PaletteLut.b16[_VAL] +#elif DBPP == 32 +#define PMAKE(_VAL) Scaler_PaletteLut.b32[_VAL] +#endif +#endif + +#define C0 LC[0][x-1] +#define C1 LC[0][x+0] +#define C2 LC[0][x+1] +#define C3 LC[1][x-1] +#define C4 LC[1][x+0] +#define C5 LC[1][x+1] +#define C6 LC[2][x-1] +#define C7 LC[2][x+0] +#define C8 LC[2][x+1] + +static void conc3d(Normal,SBPP,DBPP) (const Bit8u * src) { + const Bit8u * line; +#if SBPP == DBPP + line=src; + BituMove(Scaler_DstWrite,line,Scaler_SrcWidth*PSIZE); +#else + PTYPE * dst=(PTYPE *)Scaler_DstWrite; + line=line_cache.b8[0]; + for (Bitu x=0;x -static INLINE Bitu LineSize(Bitu pixels) { - switch (bpp) { - case 8:return pixels; - case 16:return pixels*2; - case 24:return pixels*3; - case 32:return pixels*4; +static void conc3d(Normal2x,SBPP,DBPP) (const Bit8u * src) { + PTYPE * dst=(PTYPE *)Scaler_DstWrite; + for (Bitu x=0;x -static INLINE Bitu LoadSrc(Bit8u * & src) { - Bitu val; - switch (sbpp) { - case 8:val=*(Bit8u *) src;src+=1;break; - case 16:val=*(Bit16u *) src;src+=2;break; - case 24:val=(*(Bit32u *)src)&0xffffff;src+=3;break; - case 32:val=*(Bit32u *)src;src+=4;break; +#if (DBPP > 8) +static void conc3d(TV2x,SBPP,DBPP) (const Bit8u * src) { + PTYPE * dst=(PTYPE *)Scaler_DstWrite; + for (Bitu x=0;x> 3) & redblueMask; + halfpixel|=(((pixel & greenMask) * 7) >> 3) & greenMask; + dst[x*2+0]=dst[x*2+1]=halfpixel; + LC[0][x*2+0]=LC[0][x*2+1]=pixel; + } + Scaler_DstWrite+=Scaler_DstPitch; + for (Bitu lines=*Scaler_Index++;lines;lines--) { + BituMove(Scaler_DstWrite,LC[0],Scaler_SrcWidth*2*PSIZE); + Scaler_DstWrite+=Scaler_DstPitch; } - return val; } - -template -static INLINE Bitu ConvBPP(Bitu val) { - if (sbpp==8) switch (dbpp) { - case 8:return val; - case 16:return render.pal.lookup.bpp16[val]; - case 24:return render.pal.lookup.bpp32[val]; - case 32:return render.pal.lookup.bpp32[val]; +static void conc3d(Interp2x,SBPP,DBPP) (const Bit8u * src) { + if (!Scaler_Line) { + Scaler_Line++; + for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) { + LC[1][tempx] = LC[2][tempx] = PMAKE(src[tempx]); + } + return; } - return 0; +lastagain: + Bitu x=0; + PTYPE * dst=(PTYPE *)Scaler_DstWrite; + C1=C4;C4=C7;C7=PMAKE(src[x]); + C2=C5;C5=C8;C8=PMAKE(src[x+1]); + dst[0] = interp_w2(C4,C1,3,1); + dst[1] = interp_w4(C4,C1,C2,C5,5,1,1,1); + WC[1][0] = interp_w2(C4,C7,3,1); + WC[1][1] = interp_w4(C4,C5,C8,C7,5,1,1,1); + for (x=1;x0;tempx--) { + LC[1][tempx]=LC[2][tempx]=PMAKE(src[tempx]); + } + return; + } +lastagain: + Bitu x=0; + PTYPE * dst=(PTYPE *)Scaler_DstWrite; + C1=C4;C4=C7;C7=PMAKE(src[x]); + C2=C5;C5=C8;C8=PMAKE(src[x+1]); + dst[0]=C4; + WC[1][0]=C4; + dst[1] = C5 == C1 && C7 != C1 ? C2 : C4; + WC[1][1]= C5 == C7 && C1 != C7 ? C7 : C4; + for (x=1;x0;lines--) { + BituMove(Scaler_DstWrite,&WC[1],2*Scaler_SrcWidth*PSIZE); + Scaler_DstWrite+=Scaler_DstPitch; + } + if (++Scaler_Line==Scaler_SrcHeight) goto lastagain; +} + +#endif //DBPP > 8 + +static void conc3d(AdvMame2x,SBPP,DBPP) (const Bit8u * src) { + if (!Scaler_Line) { + Scaler_Line++; + for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) { + LC[1][tempx]=LC[2][tempx]=PMAKE(src[tempx]); + } + return; + } +lastagain: + Bitu x=0; + PTYPE * dst=(PTYPE *)Scaler_DstWrite; + C1=C4;C4=C7;C7=PMAKE(src[x]); + C2=C5;C5=C8;C8=PMAKE(src[x+1]); + dst[0]=C4; + WC[1][0]=C4; + dst[1] = C5 == C1 && C7 != C1 ? C2 : C4; + WC[1][1]= C5 == C7 && C1 != C7 ? C7 : C4; + for (x=1;x0;lines--) { + BituMove(Scaler_DstWrite,&WC[1],2*Scaler_SrcWidth*PSIZE); + Scaler_DstWrite+=Scaler_DstPitch; + } + if (++Scaler_Line==Scaler_SrcHeight) goto lastagain; +} + +static void conc3d(AdvMame3x,SBPP,DBPP) (const Bit8u * src) { + if (!Scaler_Line) { + Scaler_Line++; + for (Bitu tempx=Scaler_SrcWidth;tempx>0;tempx--) { + LC[1][tempx]=LC[2][tempx]=PMAKE(src[tempx]); + } + return; + } +lastagain: + PTYPE * dst=(PTYPE *)Scaler_DstWrite; + LC[0][0]=LC[1][0];LC[1][0]=LC[2][0];LC[2][0]=PMAKE(src[0]); + LC[0][1]=LC[1][1];LC[1][1]=LC[2][1];LC[2][1]=PMAKE(src[1]); + /* first pixel */ + dst[0] = LC[1][0]; + dst[1] = LC[1][0]; + dst[2] = (LC[1][1] == LC[0][0] && LC[2][0] != LC[0][0]) ? LC[0][0] : LC[1][0]; + WC[1][0] = LC[1][0]; + WC[1][1] = LC[1][0]; + WC[1][2] = (LC[0][0] != LC[2][0]) ? (((LC[1][1] == LC[0][0] && LC[1][0] != LC[2][1]) || (LC[1][1] == LC[2][0] && LC[1][0] != LC[0][1])) ? LC[1][1] : LC[1][0]) : LC[1][0]; + WC[2][0] = LC[1][0]; + WC[2][1] = LC[1][0]; + WC[2][2] = (LC[1][1] == LC[2][0] && LC[0][0] != LC[2][0]) ? LC[2][0] : LC[1][0]; + Bitu x; + for (x=1;x0;lines--) { + BituMove(Scaler_DstWrite,&WC[2],3*Scaler_SrcWidth*PSIZE); + Scaler_DstWrite+=Scaler_DstPitch; + } + if (++Scaler_Line==Scaler_SrcHeight) goto lastagain; +} + +#undef PSIZE +#undef PTYPE +#undef PMAKE +#undef WC +#undef LC +#undef greenMask +#undef redblueMask + + diff --git a/src/gui/sdl_mapper.cpp b/src/gui/sdl_mapper.cpp new file mode 100644 index 0000000..7441d86 --- /dev/null +++ b/src/gui/sdl_mapper.cpp @@ -0,0 +1,1258 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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.7 2004/09/07 08:58:02 qbix79 Exp $ */ + +#define OLD_JOYSTICK 1 + +#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, +}; + +enum BB_Types { + BB_Next,BB_Prev,BB_Add,BB_Del, + BB_Save,BB_Reset,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 + +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 * _entry) { + strncpy(entry,_entry,16); + events.push_back(this); + bindlist.clear(); + activity=0; + } + void AddBind(CBind * bind); + virtual ~CEvent() {} + virtual void Active(bool yesno)=0; + INLINE void Activate(void) { + if (!activity) Active(true); + activity++; + } + INLINE void DeActivate(void) { + activity--; + if (!activity) Active(false); + } + void DeActivateAll(void); + void SetValue(Bits value){ + }; + char * GetName(void) { return entry;} + CBindList bindlist; +protected: + Bitu activity; + char entry[16]; +}; + +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 Activate(Bits value) { + event->SetValue(value); + if (active) return; + event->Activate(); + active=true; + } + void DeActivate(void) { + 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->DeActivate(); + } + 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)->DeActivate(); + } +} + + + +class CBindGroup { +public: + CBindGroup() { + bindgroups.push_back(this); + } + void ActivateBindList(CBindList * list,Bits value); + void DeactivateBindList(CBindList * list); + virtual CBind * CreateConfigBind(char *&buf)=0; + virtual CBind * CreateEventBind(SDL_Event * event)=0; + + virtual bool CheckEvent(SDL_Event * event)=0; + virtual char * ConfigStart(void)=0; + virtual char * BindStart(void)=0; +protected: + +}; + +class CKeyBind; +class CKeyBindGroup; + +class CKeyBind : public CBind { +public: + CKeyBind(CBindList * _list,SDLKey _key) : CBind(_list) { + key = _key; + } + void BindName(char * buf) { + sprintf(buf,"Key %s%",SDL_GetKeyName(key)); + } + void ConfigName(char * buf) { + sprintf(buf,"key %d",key); + } +public: + SDLKey key; +}; + +class CKeyBindGroup : public CBindGroup { +public: + CKeyBindGroup(Bitu _keys) : CBindGroup (){ + lists=new CBindList[_keys]; + for (Bitu i=0;i<_keys;i++) lists[i].clear(); + keys=_keys; + configname="key"; + } + ~CKeyBindGroup() { delete[] lists; } + CBind * CreateConfigBind(char *& buf) { + if (strncasecmp(buf,configname,strlen(configname))) return 0; + StripWord(buf);char * num=StripWord(buf); + CBind * bind=CreateKeyBind((SDLKey)ConvDecWord(num)); + return bind; + } + CBind * CreateEventBind(SDL_Event * event) { + if (event->type!=SDL_KEYDOWN) return 0; + return CreateKeyBind(event->key.keysym.sym); + }; + bool CheckEvent(SDL_Event * event) { + if (event->type!=SDL_KEYDOWN && event->type!=SDL_KEYUP) return false; + Bitu key=(Bitu)event->key.keysym.sym; + assert(keytype==SDL_KEYDOWN) ActivateBindList(&lists[key],0x7fff); + else DeactivateBindList(&lists[key]); + return 0; + } + CBind * CreateKeyBind(SDLKey _key) { + 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) : CBind(_list) { + group = _group; + hat=_hat; + } + void ConfigName(char * buf) { + sprintf(buf,"%s hat %d",group->ConfigStart(),hat); + } + void BindName(char * buf) { + sprintf(buf,"%s hat %d",group->BindStart(),hat); + } +protected: + CBindGroup * group; + Bitu hat; + Bitu mask; +}; + +class CStickBindGroup : public CBindGroup { +public: + CStickBindGroup(Bitu _stick) : CBindGroup (){ + stick=_stick; + sprintf(configname,"stick_%d",stick); + assert(sdl_joystick=SDL_JoystickOpen(stick)); + axes=SDL_JoystickNumAxes(sdl_joystick); + buttons=SDL_JoystickNumButtons(sdl_joystick); + hats=SDL_JoystickNumHats(sdl_joystick); + pos_axis_lists=new CBindList[axes]; + neg_axis_lists=new CBindList[axes]; + button_lists=new CBindList[buttons]; + hat_lists=new CBindList[hats]; +#if OLD_JOYSTICK + LOG_MSG("Using joystick %s with %d axes and %d buttons",SDL_JoystickName(stick),axes,buttons); + JOYSTICK_Enable(stick,true); +#endif + } + ~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); + } + return bind; + } + CBind * CreateEventBind(SDL_Event * event) { + if (event->type==SDL_JOYAXISMOTION) { + if (event->jaxis .which!=stick) return 0; + 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->jaxis .which!=stick) return 0; + return CreateButtonBind(event->jbutton.button); + } else return 0; + } + bool CheckEvent(SDL_Event * event) { +#if OLD_JOYSTICK + SDL_JoyAxisEvent * jaxis = NULL; + SDL_JoyButtonEvent * jbutton = NULL; + + switch(event->type) { + case SDL_JOYAXISMOTION: + jaxis = &event->jaxis; + if(jaxis->axis == 0) + JOYSTICK_Move_X(stick,(float)(jaxis->value/32768.0)); + else if(jaxis->axis == 1) + JOYSTICK_Move_Y(stick,(float)(jaxis->value/32768.0)); + break; + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: + jbutton = &event->jbutton; + bool state; + state=jbutton->type==SDL_JOYBUTTONDOWN; + if (jbutton->button<2) { + JOYSTICK_Button(stick,jbutton->button,state); + } + break; + } +#endif + return false; + } +private: + CBind * CreateAxisBind(Bitu axis,bool positive) { + assert(axisbegin();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)->Activate(value); + } +} + +void CBindGroup::DeactivateBindList(CBindList * list) { + Bitu validmod=0; + CBindList_it it; + for (it=list->begin();it!=list->end();it++) { + (*it)->DeActivate(); + } +} + +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) && (_ybindlist.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; + 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 CEvent { +public: + CKeyEvent(char * _entry,KBD_KEYS _key) : CEvent(_entry) { + key=_key; + } + void Active(bool yesno) { + KEYBOARD_AddKey(key,yesno); + }; + KBD_KEYS key; +}; + +class CJAxisEvent : public CEvent { +public: + CJAxisEvent(char * _entry,Bitu _stick,bool _yaxis,bool _positive) : CEvent(_entry) { + stick=_stick; + yaxis=_yaxis; + positive=_positive; + } + void Active(bool yesno) { + }; + Bitu stick; + bool yaxis,positive; +}; + +class CJButtonEvent : public CEvent { +public: + CJButtonEvent(char * _entry,Bitu _stick,Bitu _button) : CEvent(_entry) { + stick=_stick; + button=_button; + } + void Active(bool yesno) { + }; + Bitu stick,button; +}; + + +class CModEvent : public CEvent { +public: + CModEvent(char * _entry,Bitu _wmod) : CEvent(_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 CEvent { +public: + CHandlerEvent(char * _entry,MAPPER_Handler * _handler,MapKeys _key,Bitu _mod,char * _buttonname) : CEvent(_entry) { + handler=_handler; + defmod=_mod; + defkey=_key; + buttonname=_buttonname; + handlergroup.push_back(this); + } + void Active(bool yesno) { + if (yesno) (*handler)(); + }; + 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; + char * buttonname; + MAPPER_Handler * handler; +}; + + +struct { + CCaptionButton * event_title; + CCaptionButton * bind_title; + CCaptionButton * selected; + CCaptionButton * action; + CBindButton * save; + CBindButton * exit; + CBindButton * add; + CBindButton * del; + CBindButton * next; + CBindButton * prev; + CCheckButton * mod1,* mod2,* mod3,* hold; +} bind_but; + +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.prev->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) { + bind_but.action->Change("Select an event to change"); + bind_but.add->Enable(false); + SetActiveBind(0); + } else { + 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 void AddKeyButtonEvent(Bitu x,Bitu y,Bitu dx,Bitu dy,const char * title,const char * entry,KBD_KEYS key) { + char buf[64]; + strcpy(buf,"key_"); + strcat(buf,entry); + CKeyEvent * event=new CKeyEvent(buf,key); + CButton * button=new CEventButton(x,y,dx,dy,title,event); +} + +static void AddJAxisButton(Bitu x,Bitu y,Bitu dx,Bitu dy,const char * title,Bitu stick,bool yaxis,bool positive) { + char buf[64]; + sprintf(buf,"jaxis_%d%s%s",stick,yaxis ? "Y":"X",positive ? "+" : "-"); + CJAxisEvent * event=new CJAxisEvent(buf,stick,yaxis,positive); + CButton * button=new CEventButton(x,y,dx,dy,title,event); +} + +static void AddJButtonButton(Bitu x,Bitu y,Bitu dx,Bitu dy,const char * title,Bitu _stick,Bitu _button) { + char buf[64]; + sprintf(buf,"jbutton_%d_%d",_stick,_button); + CJButtonEvent * event=new CJButtonEvent(buf,_stick,_button); + CButton * button=new CEventButton(x,y,dx,dy,title,event); +} + + +static void AddModButton(Bitu x,Bitu y,Bitu dx,Bitu dy,const char * title,Bitu _mod) { + char buf[64]; + sprintf(buf,"mod_%d",_mod); + CModEvent * event=new CModEvent(buf,_mod); + CButton * button=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[10]={ + {"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 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); + + 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*3,BH,"SHIFT","lshift",KBD_leftshift); + for (i=0;i<10;i++) AddKeyButtonEvent(PX(3+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 */ + 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); + +#if (!OLD_JOYSTICK) + /* Joystick Buttons/Texts */ + AddJButtonButton(PX(17),PY(0),BW,BH,"1" ,0,0); + AddJAxisButton (PX(18),PY(0),BW,BH,"Y-",0,true,false); + AddJButtonButton(PX(19),PY(0),BW,BH,"2" ,0,1); + AddJAxisButton (PX(17),PY(1),BW,BH,"X-",0,false,false); + AddJAxisButton (PX(18),PY(1),BW,BH,"Y+",0,true,true); + AddJAxisButton (PX(19),PY(1),BW,BH,"X+",0,false,true); + + AddJButtonButton(PX(17),PY(3),BW,BH,"1" ,1,0); + AddJAxisButton (PX(18),PY(3),BW,BH,"Y-",1,true,false); + AddJButtonButton(PX(19),PY(3),BW,BH,"2" ,1,1); + AddJAxisButton (PX(17),PY(4),BW,BH,"X-",1,false,false); + AddJAxisButton (PX(18),PY(4),BW,BH,"Y+",1,true,true); + AddJAxisButton (PX(19),PY(4),BW,BH,"X+",1,false,true); +#endif + /* 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=7; + 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),00,124,20,"Keyboard Layout"); +#if (!OLD_JOYSTICK) + new CTextButton(PX(16),00,124,20,"Joystick Layout"); +#endif + bind_but.action=new CCaptionButton(200,330,0,0); + + bind_but.event_title=new CCaptionButton(0,350,0,0); + bind_but.bind_title=new CCaptionButton(00,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.prev=new CBindButton(200,400,50,20,"Prev",BB_Prev); + 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[4]={ + {0x00,0x00,0x00,0x00}, //0=black + {0xff,0xff,0xff,0x00}, //1=white + {0xff,0x00,0x00,0x00}, //2=red +}; + +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 { + 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}, + {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); + } + /* JOYSTICK */ + if (SDL_NumJoysticks()>0) { +// default mapping + } + +} + +void MAPPER_AddHandler(MAPPER_Handler * handler,MapKeys key,Bitu mods,char * eventname,char * buttonname) { + 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,"wb+"); + if (!savefile) { + LOG_MSG("Can't open %s for saving the mappings",mapper.filename); + 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); +} + +static bool MAPPER_LoadBinds(void) { + FILE * loadfile=fopen(mapper.filename,"rb+"); + if (!loadfile) return false; + char linein[512]; + while (fgets(linein,512,loadfile)) { + CreateStringBind(linein); + } + fclose(loadfile); + 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 CreateBindGroups(void) { + bindgroups.clear(); + new CKeyBindGroup(SDLK_LAST); + Bitu numsticks=SDL_NumJoysticks(); + if (numsticks) SDL_JoystickEventState(SDL_ENABLE); + for (Bitu i=0;iDeActivateAll(); + } + + bool mousetoggle=false; + if(mouselocked) { + mousetoggle=true; + GFX_CaptureMouse(); + } + + mapper.surface=SDL_SetVideoMode(640,480,8,0); + /* Set some palette entries */ + SDL_SetPalette(mapper.surface, SDL_LOGPAL|SDL_PHYSPAL, map_pal, 0, 4); + /* Go in the event loop */ + mapper.exit=false; + mapper.redraw=true; + SetActiveEvent(0); + while (!mapper.exit) { + if (mapper.redraw) { + mapper.redraw=false; + DrawButtons(); + } + BIND_MappingEvents(); + SDL_Delay(1); + } + if(mousetoggle) GFX_CaptureMouse(); + GFX_ResetScreen(); +} + +void MAPPER_Init(void) { + CreateLayout(); + CreateBindGroups(); + if (!MAPPER_LoadBinds()) CreateDefaultBinds(); +} + +void MAPPER_StartUp(Section * sec) { + Section_prop * section=static_cast(sec); + mapper.filename=section->Get_string("mapperfile"); + MAPPER_AddHandler(&MAPPER_Run,MK_f1,MMOD1,"mapper","Mapper"); +} + diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 6d6efd9..ff45c70 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.60 2004/01/30 21:11:34 harekiet Exp $ */ +/* $Id: sdlmain.cpp,v 1.79 2004/09/29 19:14:10 harekiet Exp $ */ #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -32,14 +32,15 @@ #include "dosbox.h" #include "video.h" -#include "keyboard.h" #include "mouse.h" -#include "joystick.h" #include "pic.h" #include "timer.h" #include "setup.h" #include "support.h" #include "debug.h" +#include "mapper.h" + +//#define DISABLE_JOYSTICK #if C_OPENGL #include "SDL_opengl.h" @@ -53,41 +54,52 @@ #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; -#endif + #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); -PFNGLPIXELDATARANGENVPROC glPixelDataRangeNV = NULL; #endif + +PFNGLPIXELDATARANGENVPROC glPixelDataRangeNV = NULL; + #endif #endif //C_OPENGL -//#define DISABLE_JOYSTICK - #if !(ENVIRON_INCLUDED) extern char** environ; #endif - #ifdef WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include +#if defined(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" @@ -97,12 +109,25 @@ extern char** environ; #define DEFAULT_CONFIG_FILE "/.dosboxrc" #endif +#if C_SET_PRIORITY +#include +#define PRIO_TOTAL (PRIO_MAX-PRIO_MIN) +#endif + enum SCREEN_TYPES { SCREEN_SURFACE, + SCREEN_SURFACE_DDRAW, SCREEN_OVERLAY, SCREEN_OPENGL }; +enum PRIORITY_LEVELS { + 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 @@ -110,7 +135,8 @@ struct SDL_Block { struct { Bit32u width; Bit32u height; - Bitu bpp; + Bitu flags; + GFX_Modes mode; double scalex,scaley; GFX_ResetCallBack reset; } draw; @@ -139,10 +165,20 @@ struct SDL_Block { #endif } opengl; #endif +#if defined(HAVE_DDRAW_H) && defined(WIN32) + struct { + SDL_Surface * surface; + RECT rect; + DDBLTFX fx; + } blit; +#endif + struct { + PRIORITY_LEVELS focus; + PRIORITY_LEVELS nofocus; + } priority; SDL_Rect clip; SDL_Surface * surface; SDL_Overlay * overlay; - SDL_Joystick * joy; SDL_cond *cond; struct { bool autolock; @@ -156,45 +192,99 @@ struct SDL_Block { static SDL_Block sdl; static void CaptureMouse(void); -void GFX_SetTitle(Bits cycles,Bits frameskip){ +extern char * RunningProgram; +void GFX_SetTitle(Bits cycles,Bits frameskip,bool paused){ char title[200]={0}; static Bits internal_cycles=0; static Bits internal_frameskip=0; if(cycles != -1) internal_cycles = cycles; if(frameskip != -1) internal_frameskip = frameskip; - sprintf(title,"DOSBox %s, Cpu Cycles: %8d, Frameskip %2d",VERSION,internal_cycles,internal_frameskip); + if(paused) + sprintf(title,"DOSBox %s,Cpu Cycles: %8d, Frameskip %2d, Program: %8s PAUSED",VERSION,internal_cycles,internal_frameskip,RunningProgram); + else + sprintf(title,"DOSBox %s,Cpu Cycles: %8d, Frameskip %2d, Program: %8s",VERSION,internal_cycles,internal_frameskip,RunningProgram); SDL_WM_SetCaption(title,VERSION); } +static void PauseDOSBox(void) { + GFX_SetTitle(-1,-1,true); + bool paused = true; + 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_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; + } + } + } +} + + /* Reset the screen with current values in the sdl structure */ -Bitu GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags) { - gfx_flags=0; +Bitu GFX_GetBestMode(Bitu flags) { + Bitu testbpp,gotbpp; switch (sdl.desktop.want_type) { case SCREEN_SURFACE: - if (sdl.desktop.fullscreen) { - bpp=SDL_VideoModeOK(640,480,bpp,SDL_FULLSCREEN|SDL_HWSURFACE | - (sdl.desktop.doublebuf ? SDL_DOUBLEBUF : 0) | ((bpp==8) ? SDL_HWPALETTE : 0) ); - } else { - bpp=sdl.desktop.bpp; +check_surface: + /* Check if we can satisfy the depth it loves */ + if (flags & LOVE_8) testbpp=8; + else if (flags & LOVE_16) testbpp=16; + else if (flags & LOVE_32) testbpp=32; +check_gotbpp: + 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 & CAN_8) flags&=~(CAN_16|CAN_32); + break; + case 15: + case 16: + if (flags & CAN_16) flags&=~(CAN_8|CAN_32); + break; + case 24: + case 32: + if (flags & CAN_32) flags&=~(CAN_8|CAN_16); + break; } - gfx_flags|=GFX_HASCONVERT; + /* Not a valid display depth found? Let's just hope sdl provides conversions */ break; +#if defined(HAVE_DDRAW_H) && defined(WIN32) + case SCREEN_SURFACE_DDRAW: + if (!(flags&CAN_32|CAN_16)) goto check_surface; + if (flags & LOVE_16) testbpp=16; + else if (flags & LOVE_32) testbpp=32; + else testbpp=0; + flags|=HAVE_SCALING; + goto check_gotbpp; +#endif case SCREEN_OVERLAY: - bpp=32; - gfx_flags|=GFX_HASSCALING; + if (flags & NEED_RGB || !(flags&CAN_32)) goto check_surface; + flags|=HAVE_SCALING; + flags&=~(CAN_8,CAN_16); break; #if C_OPENGL case SCREEN_OPENGL: - bpp=32; - gfx_flags|=GFX_HASSCALING; + if (flags & NEED_RGB || !(flags&CAN_32)) goto check_surface; + flags|=HAVE_SCALING; + flags&=~(CAN_8,CAN_16); break; #endif } - return bpp; + return flags; } -static void ResetScreen(void) { +void GFX_ResetScreen(void) { GFX_Stop(); if (sdl.draw.reset) (sdl.draw.reset)(); GFX_Start(); @@ -207,18 +297,53 @@ static int int_log2 (int val) { return log; } -void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,double scalex,double scaley,GFX_ResetCallBack reset) { + +static SDL_Surface * GFX_SetupSurfaceScaled(Bit32u sdl_flags,Bit32u bpp) { + if (sdl.desktop.fullscreen) { + if (sdl.desktop.fixed) { + double ratio_w=(double)sdl.desktop.width/(sdl.draw.width*sdl.draw.scalex); + double ratio_h=(double)sdl.desktop.height/(sdl.draw.height*sdl.draw.scaley); + if ( ratio_w < ratio_h) { + sdl.clip.w=(Bit16u)sdl.desktop.width; + 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)sdl.desktop.height; + } + sdl.clip.x=(Sint16)((sdl.desktop.width-sdl.clip.w)/2); + sdl.clip.y=(Sint16)((sdl.desktop.height-sdl.clip.h)/2); + return sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,bpp,sdl_flags|SDL_FULLSCREEN|SDL_HWSURFACE); + } 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); + return sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,sdl_flags|SDL_FULLSCREEN|SDL_HWSURFACE); + } + } else { + sdl.clip.x=0;sdl.clip.y=0; + sdl.clip.w=(Bit16u)(sdl.draw.width*sdl.draw.scalex*sdl.desktop.hwscale); + sdl.clip.h=(Bit16u)(sdl.draw.height*sdl.draw.scaley*sdl.desktop.hwscale); + return sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,bpp,sdl_flags|SDL_HWSURFACE); + } +} + +GFX_Modes GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_ResetCallBack reset) { if (sdl.updating) GFX_EndUpdate(); sdl.draw.width=width; sdl.draw.height=height; - sdl.draw.bpp=bpp; + sdl.draw.flags=flags; + sdl.draw.mode=GFX_NONE; sdl.draw.reset=reset; sdl.draw.scalex=scalex; sdl.draw.scaley=scaley; + Bitu bpp; switch (sdl.desktop.want_type) { case SCREEN_SURFACE: dosurface: + if (flags & CAN_8) bpp=8; + if (flags & CAN_16) bpp=16; + if (flags & CAN_32) bpp=32; sdl.desktop.type=SCREEN_SURFACE; sdl.clip.w=width; sdl.clip.h=height; @@ -227,55 +352,74 @@ dosurface: sdl.clip.x=(Sint16)((sdl.desktop.width-width)/2); sdl.clip.y=(Sint16)((sdl.desktop.height-height)/2); sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,bpp, - SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF : 0)|SDL_HWPALETTE); + SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF|SDL_ASYNCBLIT : 0)|SDL_HWPALETTE); } else { sdl.clip.x=0;sdl.clip.y=0; sdl.surface=SDL_SetVideoMode(width,height,bpp, - SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF : 0)|SDL_HWPALETTE); + SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF|SDL_ASYNCBLIT : 0)|SDL_HWPALETTE); } } else { sdl.clip.x=0;sdl.clip.y=0; sdl.surface=SDL_SetVideoMode(width,height,bpp,SDL_HWSURFACE); } - break; - case SCREEN_OVERLAY: - if (sdl.overlay) SDL_FreeYUVOverlay(sdl.overlay); - sdl.overlay=0; - if (bpp!=32) goto dosurface; - if (sdl.desktop.fullscreen) { - if (sdl.desktop.fixed) { - double ratio_w=(double)sdl.desktop.width/(width*scalex); - double ratio_h=(double)sdl.desktop.height/(height*scaley); - if ( ratio_w < ratio_h) { - sdl.clip.w=(Bit16u)sdl.desktop.width; - sdl.clip.h=(Bit16u)(height*scaley*ratio_w); - } else { - sdl.clip.w=(Bit16u)(width*scalex*ratio_h); - sdl.clip.h=(Bit16u)sdl.desktop.height; - } - sdl.clip.x=(Sint16)((sdl.desktop.width-sdl.clip.w)/2); - sdl.clip.y=(Sint16)((sdl.desktop.height-sdl.clip.h)/2); - sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,0, - SDL_FULLSCREEN|SDL_HWSURFACE); - } else { - sdl.clip.x=0;sdl.clip.y=0; - sdl.clip.w=(Bit16u)(width*scalex); - sdl.clip.h=(Bit16u)(height*scaley); - sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0, - SDL_FULLSCREEN|SDL_HWSURFACE); - } - } else { - sdl.clip.x=0;sdl.clip.y=0; - sdl.clip.w=(Bit16u)(width*scalex*sdl.desktop.hwscale); - sdl.clip.h=(Bit16u)(height*scaley*sdl.desktop.hwscale); - sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0,SDL_HWSURFACE); + if (sdl.surface) switch (sdl.surface->format->BitsPerPixel) { + case 8:sdl.draw.mode=GFX_8;break; + case 15:sdl.draw.mode=GFX_15;break; + case 16:sdl.draw.mode=GFX_16;break; + case 32:sdl.draw.mode=GFX_32;break; + default: + break; } + break; +#if defined(HAVE_DDRAW_H) && defined(WIN32) + case SCREEN_SURFACE_DDRAW: + if (flags & CAN_16) bpp=16; + if (flags & CAN_32) bpp=32; + if (sdl.blit.surface) { + SDL_FreeSurface(sdl.blit.surface); + sdl.blit.surface=0; + } + memset(&sdl.blit.fx,0,sizeof(DDBLTFX)); + sdl.blit.fx.dwSize=sizeof(DDBLTFX); + 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)) { + LOG_MSG("Failed to create ddraw surface, back to normal surface."); + goto dosurface; + } + switch (sdl.surface->format->BitsPerPixel) { + case 15:sdl.draw.mode=GFX_15;break; + case 16:sdl.draw.mode=GFX_16;break; + case 32:sdl.draw.mode=GFX_32;break; + default: + break; + } + sdl.desktop.type=SCREEN_SURFACE_DDRAW; + break; +#endif + case SCREEN_OVERLAY: + if (sdl.overlay) { + SDL_FreeYUVOverlay(sdl.overlay); + sdl.overlay=0; + } + if (!(flags&CAN_32) || (flags & NEED_RGB)) 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; + sdl.draw.mode=GFX_32; break; #if C_OPENGL case SCREEN_OPENGL: @@ -288,42 +432,14 @@ dosurface: free(sdl.opengl.framebuf); } sdl.opengl.framebuf=0; - if (bpp!=32) goto dosurface; + if (!(flags&CAN_32) || (flags & NEED_RGB)) 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 (sdl.desktop.fullscreen) { - if (sdl.desktop.fixed) { - double ratio_w=(double)sdl.desktop.width/(width*scalex); - double ratio_h=(double)sdl.desktop.height/(height*scaley); - if ( ratio_w < ratio_h) { - sdl.clip.w=(Bit16u)sdl.desktop.width; - sdl.clip.h=(Bit16u)(height*scaley*ratio_w); - } else { - sdl.clip.w=(Bit16u)(width*scalex*ratio_h); - sdl.clip.h=(Bit16u)sdl.desktop.height; - } - sdl.clip.x=(Sint16)((sdl.desktop.width-sdl.clip.w)/2); - sdl.clip.y=(Sint16)((sdl.desktop.height-sdl.clip.h)/2); - sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,0, - SDL_OPENGL|SDL_FULLSCREEN|SDL_HWSURFACE); - } else { - sdl.clip.x=0;sdl.clip.y=0; - sdl.clip.w=(Bit16u)(width*scalex); - sdl.clip.h=(Bit16u)(height*scaley); - sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0, - SDL_OPENGL|SDL_FULLSCREEN|SDL_HWSURFACE); - } - } else { - sdl.clip.x=0;sdl.clip.y=0; - sdl.clip.w=(Bit16u)(width*scalex*sdl.desktop.hwscale); - sdl.clip.h=(Bit16u)(height*scaley*sdl.desktop.hwscale); - sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0, - SDL_OPENGL|SDL_HWSURFACE); - } + 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; @@ -361,6 +477,8 @@ dosurface: 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); @@ -388,14 +506,16 @@ dosurface: glEnd(); glEndList(); sdl.desktop.type=SCREEN_OPENGL; + sdl.draw.mode=GFX_32; break; }//OPENGL #endif //C_OPENGL }//CASE - GFX_Start(); + if (sdl.draw.mode!=GFX_NONE) GFX_Start(); + return sdl.draw.mode; } - +bool mouselocked; //Global variable for mapper static void CaptureMouse(void) { sdl.mouse.locked=!sdl.mouse.locked; if (sdl.mouse.locked) { @@ -405,6 +525,11 @@ static void CaptureMouse(void) { SDL_WM_GrabInput(SDL_GRAB_OFF); SDL_ShowCursor(SDL_ENABLE); } + mouselocked=sdl.mouse.locked; +} + +void GFX_CaptureMouse(void) { + CaptureMouse(); } static void SwitchFullScreen(void) { @@ -414,7 +539,7 @@ static void SwitchFullScreen(void) { } else { if (sdl.mouse.locked) CaptureMouse(); } - ResetScreen(); + GFX_ResetScreen(); } void GFX_SwitchFullScreen(void) { @@ -428,7 +553,7 @@ bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch) { case SCREEN_SURFACE: if (SDL_MUSTLOCK(sdl.surface)) { if (SDL_LockSurface(sdl.surface)) { - LOG_MSG("SDL Lock failed"); +// LOG_MSG("SDL Lock failed"); sdl.updating=false; return false; } @@ -438,6 +563,17 @@ bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch) { pixels+=sdl.clip.x*sdl.surface->format->BytesPerPixel; pitch=sdl.surface->pitch; return true; +#if defined(HAVE_DDRAW_H) && defined(WIN32) + case SCREEN_SURFACE_DDRAW: + if (SDL_LockSurface(sdl.blit.surface)) { +// LOG_MSG("SDL Lock failed"); + sdl.updating=false; + return false; + } + pixels=(Bit8u *)sdl.blit.surface->pixels; + pitch=sdl.blit.surface->pitch; + return true; +#endif case SCREEN_OVERLAY: SDL_LockYUVOverlay(sdl.overlay); pixels=(Bit8u *)*(sdl.overlay->pixels); @@ -454,6 +590,7 @@ bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch) { } void GFX_EndUpdate(void) { + int ret; if (!sdl.updating) return; sdl.updating=false; switch (sdl.desktop.type) { @@ -463,6 +600,27 @@ void GFX_EndUpdate(void) { } SDL_Flip(sdl.surface); break; +#if defined(HAVE_DDRAW_H) && defined(WIN32) + case SCREEN_SURFACE_DDRAW: + if (SDL_MUSTLOCK(sdl.blit.surface)) { + 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); + 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); @@ -498,13 +656,18 @@ void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { 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); @@ -515,6 +678,7 @@ Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue) { } void GFX_Stop() { + if (sdl.updating) GFX_EndUpdate(); sdl.active=false; } @@ -526,12 +690,47 @@ static void GUI_ShutDown(Section * sec) { GFX_Stop(); if (sdl.mouse.locked) CaptureMouse(); if (sdl.desktop.fullscreen) SwitchFullScreen(); + SDL_Quit(); //Becareful this should be removed if on the fly renderchanges are allowed } static void KillSwitch(void){ throw 1; } +static void SetPriority(PRIORITY_LEVELS level) { + switch (level) { +#ifdef WIN32 + 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 + case PRIORITY_LEVEL_LOWER: + setpriority (PRIO_PROCESS, 0,PRIO_MIN+(PRIO_TOTAL/3)); + break; + case PRIORITY_LEVEL_NORMAL: + setpriority (PRIO_PROCESS, 0,PRIO_MIN+(PRIO_TOTAL/2)); + break; + case PRIORITY_LEVEL_HIGHER: + setpriority (PRIO_PROCESS, 0,PRIO_MIN+((3*PRIO_TOTAL)/5) ); + break; + case PRIORITY_LEVEL_HIGHEST: + setpriority (PRIO_PROCESS, 0,PRIO_MIN+((3*PRIO_TOTAL)/4) ); + break; +#endif + default: + break; + } +} + static void GUI_StartUp(Section * sec) { sec->AddDestroyFunction(&GUI_ShutDown); Section_prop * section=static_cast(sec); @@ -539,11 +738,62 @@ static void GUI_StartUp(Section * sec) { sdl.updating=false; sdl.desktop.fullscreen=section->Get_bool("fullscreen"); sdl.wait_on_error=section->Get_bool("waitonerror"); + const char * priority=section->Get_string("priority"); + if (priority && priority[0]) { + Bitu next; + if (!strncasecmp(priority,"lower",5)) { + sdl.priority.focus=PRIORITY_LEVEL_LOWER;next=5; + } else if (!strncasecmp(priority,"normal",6)) { + sdl.priority.focus=PRIORITY_LEVEL_NORMAL;next=6; + } else if (!strncasecmp(priority,"higher",6)) { + sdl.priority.focus=PRIORITY_LEVEL_HIGHER;next=6; + } else if (!strncasecmp(priority,"highest",7)) { + sdl.priority.focus=PRIORITY_LEVEL_HIGHEST;next=7; + } else { + next=0;sdl.priority.focus=PRIORITY_LEVEL_HIGHER; + } + priority=&priority[next]; + if (next && priority[0]==',' && priority[1]) { + priority++; + if (!strncasecmp(priority,"lower",5)) { + sdl.priority.nofocus=PRIORITY_LEVEL_LOWER; + } else if (!strncasecmp(priority,"normal",6)) { + sdl.priority.nofocus=PRIORITY_LEVEL_NORMAL; + } else if (!strncasecmp(priority,"higher",6)) { + sdl.priority.nofocus=PRIORITY_LEVEL_HIGHER; + } else if (!strncasecmp(priority,"highest",7)) { + sdl.priority.nofocus=PRIORITY_LEVEL_HIGHEST; + } else { + sdl.priority.nofocus=PRIORITY_LEVEL_NORMAL; + } + } else sdl.priority.nofocus=sdl.priority.focus; + } else { + sdl.priority.focus=PRIORITY_LEVEL_HIGHER; + sdl.priority.nofocus=PRIORITY_LEVEL_NORMAL; + } sdl.mouse.locked=false; + mouselocked=false; //Global for mapper sdl.mouse.requestlock=false; sdl.desktop.fixed=section->Get_bool("fullfixed"); - sdl.desktop.width=section->Get_int("fullwidth"); - sdl.desktop.height=section->Get_int("fullheight"); + const char* fullresolution=section->Get_string("fullresolution"); + if(fullresolution && *fullresolution) { + char res[100]= { 0 }; + strcpy(res,fullresolution); + fullresolution = lowcase (res);//so x and X are allowed + + char* height = strchr(fullresolution,'x'); + if(height && * height) { + *height = 0; + sdl.desktop.height = atoi(height+1); + sdl.desktop.width = atoi(res); + } else { + sdl.desktop.width = 0; + sdl.desktop.height = 0; + } + } else { + sdl.desktop.width = 0; + sdl.desktop.height = 0; + } sdl.desktop.doublebuf=section->Get_bool("fulldouble"); sdl.desktop.hwscale=section->Get_float("hwscale"); if (sdl.desktop.hwscale<0.1f) { @@ -570,6 +820,10 @@ static void GUI_StartUp(Section * sec) { const char * output=section->Get_string("output"); if (!strcasecmp(output,"surface")) { sdl.desktop.want_type=SCREEN_SURFACE; +#if defined(HAVE_DDRAW_H) && defined(WIN32) + } else if (!strcasecmp(output,"ddraw")) { + sdl.desktop.want_type=SCREEN_SURFACE_DDRAW; +#endif } else if (!strcasecmp(output,"overlay")) { sdl.desktop.want_type=SCREEN_OVERLAY; #if C_OPENGL @@ -587,6 +841,7 @@ static void GUI_StartUp(Section * sec) { 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); sdl.opengl.framebuf=0; sdl.opengl.texture=0; @@ -598,12 +853,18 @@ static void GUI_StartUp(Section * sec) { db_glFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC) wglGetProcAddress("wglFreeMemoryNV"); #endif const char * gl_ext = (const char *)glGetString (GL_EXTENSIONS); - sdl.opengl.packed_pixel=strstr(gl_ext,"EXT_packed_pixels") > 0; - sdl.opengl.paletted_texture=strstr(gl_ext,"EXT_paletted_texture") > 0; + 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=(strstr(gl_ext,"GL_NV_pixel_data_range") >0 ) && + glPixelDataRangeNV && db_glAllocateMemoryNV && db_glFreeMemoryNV; #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); @@ -611,14 +872,16 @@ static void GUI_StartUp(Section * sec) { if (sdl.desktop.bpp==24) { LOG_MSG("SDL:You are running in 24 bpp mode, this will slow down things!"); } - GFX_SetSize(640,400,8,1.0,1.0,0); - SDL_EnableKeyRepeat(250,40); - SDL_EnableUNICODE(1); -/* Get some Keybinds */ - KEYBOARD_AddEvent(KBD_f9,KBD_MOD_CTRL,KillSwitch); - KEYBOARD_AddEvent(KBD_f10,KBD_MOD_CTRL,CaptureMouse); - KEYBOARD_AddEvent(KBD_enter,KBD_MOD_ALT,SwitchFullScreen); - + 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,0,"pause","Pause"); +#endif } void Mouse_AutoLock(bool enable) { @@ -627,143 +890,6 @@ void Mouse_AutoLock(bool enable) { else sdl.mouse.requestlock=false; } -static void HandleKey(SDL_KeyboardEvent * key) { - KBD_KEYS 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; - - 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; - - /* Special Keys */ - default: - code=KBD_1; - LOG(LOG_KEYBOARD,LOG_ERROR)("Unhandled SDL keysym %d",key->keysym.sym); - break; - } - /* Check the modifiers */ - Bitu mod= - ((key->keysym.mod & KMOD_CTRL) ? KBD_MOD_CTRL : 0) | - ((key->keysym.mod & KMOD_ALT) ? KBD_MOD_ALT : 0) | - ((key->keysym.mod & KMOD_SHIFT) ? KBD_MOD_SHIFT : 0); - Bitu ascii=key->keysym.unicode<128 ? key->keysym.unicode : 0; -#ifdef MACOSX - // HACK: Fix backspace on Mac OS X - // REMOVE ME oneday - if (code==KBD_backspace) - ascii=8; -#endif - KEYBOARD_AddKey(code,ascii,mod,(key->state==SDL_PRESSED)); -} - static void HandleMouseMotion(SDL_MouseMotionEvent * motion) { if (sdl.mouse.locked) Mouse_CursorMoved((float)motion->xrel*sdl.mouse.sensitivity/100,(float)motion->yrel*sdl.mouse.sensitivity/100); @@ -805,47 +931,27 @@ static void HandleMouseButton(SDL_MouseButtonEvent * button) { } } -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 Bit8u laltstate = SDL_KEYUP; +static Bit8u raltstate = SDL_KEYUP; + void GFX_Events() { - SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_ACTIVEEVENT: if (event.active.state & SDL_APPINPUTFOCUS) { - if (!event.active.gain && sdl.mouse.locked) { - CaptureMouse(); + if (event.active.gain) { + if (sdl.desktop.fullscreen && !sdl.mouse.locked) + CaptureMouse(); + SetPriority(sdl.priority.focus); + } else { + if (sdl.mouse.locked) + CaptureMouse(); + SetPriority(sdl.priority.nofocus); } } break; - case SDL_KEYDOWN: - case SDL_KEYUP: - // ignore event lalt+tab - if (event.key.keysym.sym==SDLK_LALT) laltstate = event.key.type; - if ((event.key.keysym.sym==SDLK_TAB) && (laltstate==SDL_KEYDOWN)) break; - HandleKey(&event.key); - break; case SDL_MOUSEMOTION: HandleMouseMotion(&event.motion); break; @@ -853,19 +959,25 @@ void GFX_Events() { 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: throw(0); break; +#ifdef WIN32 + case SDL_KEYDOWN: + case SDL_KEYUP: + // ignore event alt+tab + if (event.key.keysym.sym==SDLK_LALT) laltstate = event.key.type; + if (event.key.keysym.sym==SDLK_RALT) raltstate = event.key.type; + if (((event.key.keysym.sym==SDLK_TAB)) && + ((laltstate==SDL_KEYDOWN) || (raltstate==SDL_KEYDOWN))) break; +#endif + + default: + void MAPPER_CheckEvent(SDL_Event * event); + MAPPER_CheckEvent(&event); } } } @@ -885,6 +997,12 @@ int main(int argc, char* argv[]) { CommandLine com_line(argc,argv); Config myconf(&com_line); control=&myconf; + if (control->cmdline->FindExist("-version") || + control->cmdline->FindExist("--version") ) { + printf(VERSION "\n"); + return 0; + } + /* Can't disable the console with debugger enabled */ #if defined(WIN32) && !(C_DEBUG) @@ -906,44 +1024,50 @@ int main(int argc, char* argv[]) { } } #endif //defined(WIN32) && !(C_DEBUG) - #if C_DEBUG DEBUG_SetupConsole(); #endif - - if ( SDL_Init( SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_CDROM + if ( SDL_Init( SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_CDROM #ifndef DISABLE_JOYSTICK |SDL_INIT_JOYSTICK #endif ) < 0 ) E_Exit("Can't init SDL %s",SDL_GetError()); Section_prop * sdl_sec=control->AddSection_prop("sdl",&GUI_StartUp); + sdl_sec->AddInitFunction(&MAPPER_StartUp); sdl_sec->Add_bool("fullscreen",false); sdl_sec->Add_bool("fulldouble",false); sdl_sec->Add_bool("fullfixed",false); - sdl_sec->Add_int("fullwidth",0); - sdl_sec->Add_int("fullheight",0); + sdl_sec->Add_string("fullresolution","1024x768"); sdl_sec->Add_string("output","surface"); sdl_sec->Add_float("hwscale",1.0); sdl_sec->Add_bool("autolock",true); sdl_sec->Add_int("sensitivity",100); sdl_sec->Add_bool("waitonerror",true); + sdl_sec->Add_string("priority","higher,normal"); + sdl_sec->Add_string("mapperfile","mapper.txt"); MSG_Add("SDL_CONFIGFILE_HELP", "fullscreen -- Start dosbox directly in fullscreen.\n" "fulldouble -- Use double buffering in fullscreen.\n" "fullfixed -- Don't resize the screen when in fullscreen.\n" - "fullwidth/height -- What resolution to use for fullscreen, use together with fullfixed.\n" + "fullresolution -- What resolution to use for fullscreen, use together with fullfixed.\n" "output -- What to use for output: surface,overlay" #if C_OPENGL ",opengl,openglnb" +#endif +#if defined(HAVE_DDRAW_H) && defined(WIN32) + ",ddraw" #endif ".\n" "hwscale -- Extra scaling of window if the output device supports hardware scaling.\n" "autolock -- Mouse will automatically lock, if you click on the screen.\n" "sensitiviy -- Mouse sensitivity.\n" "waitonerror -- Wait before closing the console if dosbox has an error.\n" - ); + "priority -- Priority levels for dosbox: lower,normal,higher,highest.\n" + " Second entry behind the comma is for when dosbox is not focused/minimized.\n" + "mapperfile -- File used to load/save the key/event mappings from.\n" + ); /* Init all the dosbox subsystems */ DOSBOX_Init(); std::string config_file; @@ -971,30 +1095,25 @@ int main(int argc, char* argv[]) { /* Init all the sections */ control->Init(); /* Some extra SDL Functions */ -#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 if (control->cmdline->FindExist("-fullscreen") || sdl_sec->Get_bool("fullscreen")) { if(!sdl.desktop.fullscreen) { //only switch if not allready in fullscreen SwitchFullScreen(); } } + + /* Init the keyMapper */ + MAPPER_Init(); + if (control->cmdline->FindExist("-startmapper")) MAPPER_Run(); + /* Start up main machine */ control->StartUp(); /* Shutdown everything */ } catch (char * error) { - if (sdl.desktop.fullscreen) SwitchFullScreen(); - if (sdl.mouse.locked) CaptureMouse(); LOG_MSG("Exit to error: %s",error); if(sdl.wait_on_error) { //TODO Maybe look for some way to show message in linux? #if (C_DEBUG) - LOG_MSG("Press enter to continue",error); + LOG_MSG("Press enter to continue"); fgetc(stdin); #elif defined(WIN32) Sleep(5000); @@ -1003,8 +1122,10 @@ int main(int argc, char* argv[]) { } catch (int){ - if (sdl.desktop.fullscreen) SwitchFullScreen(); - if (sdl.mouse.locked) CaptureMouse(); + ;//nothing pressed killswitch + } + catch(...){ + throw;//dunno what happened. rethrow for sdl to catch } return 0; }; diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am index d5bb84f..f51dc2a 100644 --- a/src/hardware/Makefile.am +++ b/src/hardware/Makefile.am @@ -1,12 +1,16 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -EXTRA_DIST = fmopl.c fmopl.h +EXTRA_DIST = fmopl.c fmopl.h ymf262.h ymf262.c 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_memory.cpp vga_misc.cpp vga_seq.cpp font-switch.h ega-switch.h cmos.cpp disney.cpp \ - gus.cpp mpu401.cpp serialport.cpp softmodem.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 cmos.cpp disney.cpp \ + gus.cpp mpu401.cpp serialport.cpp softmodem.cpp ipx.cpp ipxserver.cpp \ + directserial_win32.cpp + + + diff --git a/src/hardware/Makefile.in b/src/hardware/Makefile.in index 341f63d..79634dd 100644 --- a/src/hardware/Makefile.in +++ b/src/hardware/Makefile.in @@ -131,15 +131,16 @@ target_os = @target_os@ target_vendor = @target_vendor@ AM_CPPFLAGS = -I$(top_srcdir)/include -EXTRA_DIST = fmopl.c fmopl.h +EXTRA_DIST = fmopl.c fmopl.h ymf262.h ymf262.c 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_memory.cpp vga_misc.cpp vga_seq.cpp font-switch.h ega-switch.h cmos.cpp disney.cpp \ - gus.cpp mpu401.cpp serialport.cpp softmodem.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 cmos.cpp disney.cpp \ + gus.cpp mpu401.cpp serialport.cpp softmodem.cpp ipx.cpp ipxserver.cpp \ + directserial_win32.cpp subdir = src/hardware ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -157,18 +158,22 @@ am_libhardware_a_OBJECTS = adlib.$(OBJEXT) dma.$(OBJEXT) \ sblaster.$(OBJEXT) tandy_sound.$(OBJEXT) timer.$(OBJEXT) \ vga.$(OBJEXT) vga_attr.$(OBJEXT) vga_crtc.$(OBJEXT) \ vga_dac.$(OBJEXT) vga_draw.$(OBJEXT) vga_gfx.$(OBJEXT) \ - vga_memory.$(OBJEXT) vga_misc.$(OBJEXT) vga_seq.$(OBJEXT) \ - cmos.$(OBJEXT) disney.$(OBJEXT) gus.$(OBJEXT) mpu401.$(OBJEXT) \ - serialport.$(OBJEXT) softmodem.$(OBJEXT) + vga_other.$(OBJEXT) vga_memory.$(OBJEXT) vga_misc.$(OBJEXT) \ + vga_seq.$(OBJEXT) vga_xga.$(OBJEXT) cmos.$(OBJEXT) \ + disney.$(OBJEXT) gus.$(OBJEXT) mpu401.$(OBJEXT) \ + serialport.$(OBJEXT) softmodem.$(OBJEXT) ipx.$(OBJEXT) \ + ipxserver.$(OBJEXT) directserial_win32.$(OBJEXT) libhardware_a_OBJECTS = $(am_libhardware_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/adlib.Po ./$(DEPDIR)/cmos.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/directserial_win32.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/disney.Po ./$(DEPDIR)/dma.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gameblaster.Po ./$(DEPDIR)/gus.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/hardware.Po ./$(DEPDIR)/iohandler.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/ipx.Po ./$(DEPDIR)/ipxserver.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/joystick.Po ./$(DEPDIR)/keyboard.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/memory.Po ./$(DEPDIR)/mixer.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpu401.Po ./$(DEPDIR)/pcspeaker.Po \ @@ -179,16 +184,13 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@ ./$(DEPDIR)/vga_crtc.Po ./$(DEPDIR)/vga_dac.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/vga_draw.Po ./$(DEPDIR)/vga_gfx.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/vga_memory.Po ./$(DEPDIR)/vga_misc.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/vga_seq.Po +@AMDEP_TRUE@ ./$(DEPDIR)/vga_other.Po ./$(DEPDIR)/vga_seq.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/vga_xga.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -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 = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libhardware_a_SOURCES) @@ -220,12 +222,15 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adlib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmos.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/directserial_win32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disney.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)/gus.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)/ipx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipxserver.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@ @@ -246,7 +251,9 @@ distclean-compile: @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_other.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_seq.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_xga.Po@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ diff --git a/src/hardware/adlib.cpp b/src/hardware/adlib.cpp index f792f9f..01f62ad 100644 --- a/src/hardware/adlib.cpp +++ b/src/hardware/adlib.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -19,19 +19,23 @@ #include #include #include +#include +#include + #include "dosbox.h" #include "inout.h" #include "mixer.h" #include "pic.h" #include "hardware.h" #include "setup.h" +#include "mapper.h" +#include "mem.h" + /* Thanks to vdmsound for nice simple way to implement this */ -namespace MAME { - /* Defines */ -# define logerror(x) +#define logerror #ifdef _MSC_VER /* Disable recurring warnings */ @@ -39,166 +43,288 @@ namespace MAME { # pragma warning ( disable : 4244 ) #endif - /* Work around ANSI compliance problem (see driver.h) */ - struct __MALLOCPTR { - void* m_ptr; +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; } - }; - - /* Bring in the MAME OPL emulation */ -# define HAS_YM3812 1 -# include "fmopl.c" - -} - - -struct OPLTimer_t { - bool isEnabled; - bool isMasked; - bool isOverflowed; - Bit64u count; - Bit64u base; + __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; } }; -static OPLTimer_t timer1,timer2; -static Bit8u regsel; +namespace OPL2 { + #define HAS_YM3812 1 + #include "fmopl.c" + void TimerOver(Bitu val){ + YM3812TimerOver(val>>8,val & 0xff); + } + void TimerHandler(int channel,double interval_Sec) { + if (interval_Sec==0.0) return; + PIC_AddEvent(TimerOver,1000.0f*interval_Sec,channel); + } +} +#undef OSD_CPU_H +#undef TL_TAB_LEN +namespace THEOPL3 { + #define HAS_YMF262 1 + #include "ymf262.c" + void TimerOver(Bitu val){ + YMF262TimerOver(val>>8,val & 0xff); + } + void TimerHandler(int channel,double interval_Sec) { + if (interval_Sec==0.0) return; + PIC_AddEvent(TimerOver,1000.0f*interval_Sec,channel); + } +} -#define OPL_INTERNAL_FREQ 3600000 // The OPL operates at 3.6MHz -#define OPL_NUM_CHIPS 1 // Number of OPL chips -#define OPL_CHIP0 0 +#define OPL2_INTERNAL_FREQ 3600000 // The OPL2 operates at 3.6MHz +#define OPL3_INTERNAL_FREQ 14400000 // The OPL3 operates at 14.4MHz -static MIXER_Channel * adlib_chan; +#define RAW_SIZE 1024 +static struct { + bool active; + OPL_Mode mode; + MixerChannel * chan; + Bit32u last_used; + Bit16s mixbuf[2][128]; + struct { + FILE * handle; + bool capturing; + Bit32u start; + Bit32u last; + Bit8u index; + Bit8u buffer[RAW_SIZE+8]; + Bit8u regs[2][256]; + Bit32u used; + Bit32u done; + Bit8u cmd[2]; + } raw; +} opl; -static void ADLIB_CallBack(Bit8u *stream, Bit32u len) { +static void OPL_CallBack(Bitu 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(0,(MAME::INT16 *)stream,len); -} - -static Bit8u read_p388(Bit32u port) { - Bit8u ret=0; - Bit64u micro=PIC_MicroCount(); - if (timer1.isEnabled) { - if ((micro-timer1.base)>timer1.count) { - timer1.isOverflowed=true; - timer1.base=micro; - } - if (timer1.isOverflowed || !timer1.isMasked) { - ret|=0xc0; + Bitu i; + switch(opl.mode) { + case OPL_opl2: + OPL2::YM3812UpdateOne(0,(OPL2::INT16 *)MixTemp,len); + opl.chan->AddSamples_m16(len,(Bit16s*)MixTemp); + break; + case OPL_opl3: + THEOPL3::YMF262UpdateOne(0,(OPL2::INT16 *)MixTemp,len); + opl.chan->AddSamples_s16(len,(Bit16s*)MixTemp); + break; + case OPL_dualopl2: + OPL2::YM3812UpdateOne(0,(OPL2::INT16 *)opl.mixbuf[0],len); + OPL2::YM3812UpdateOne(1,(OPL2::INT16 *)opl.mixbuf[1],len); + for (i=0;iAddSamples_s16(len,(Bit16s*)MixTemp); + break; } - if (timer2.isEnabled) { - if ((micro-timer2.base)>timer2.count) { - timer2.isOverflowed=true; - timer2.base=micro; - } - if (timer2.isOverflowed || !timer2.isMasked) { - ret|=0xA0; - } + if ((PIC_Ticks-opl.last_used)>30000) { + opl.chan->Enable(false); + opl.active=false; } - return ret; } -static void write_p388(Bit32u port,Bit8u val) { - regsel=val; - - // The following writes this value to ultrasounds equivalent register. - // I don't know of any other way to do this - IO_Write(0x248,val); +static Bitu OPL_Read(Bitu port,Bitu iolen) { + Bitu addr=port & 3; + switch (opl.mode) { + case OPL_opl2: + return OPL2::YM3812Read(0,addr); + case OPL_dualopl2: + return OPL2::YM3812Read(addr>>1,addr); + case OPL_opl3: + return THEOPL3::YMF262Read(0,addr); + } + return 0xff; } -static void write_p389(Bit32u port,Bit8u val) { - switch (regsel) { - case 0x02: /* Timer 1 */ - timer1.count=val*80; +static void OPL_RawAdd(Bitu index,Bitu val); +void OPL_Write(Bitu port,Bitu val,Bitu iolen) { + opl.last_used=PIC_Ticks; + if (!opl.active) { + opl.active=true; + opl.chan->Enable(true); + } + port&=3; + if (port&1) { + Bitu index=port>>1; + opl.raw.regs[index][opl.raw.cmd[index]]=val; + if (opl.raw.capturing) OPL_RawAdd(index,val); + } else opl.raw.cmd[port>>1]=val; + if (!port) adlib_commandreg=val; + switch (opl.mode) { + case OPL_opl2: + OPL2::YM3812Write(0,port,val); + break; + case OPL_opl3: + THEOPL3::YMF262Write(0,port,val); + break; + case OPL_dualopl2: + OPL2::YM3812Write(port>>1,port,val); + break; + } +} + +static Bit8u dro_header[]={ + 'D','B','R','A', /* Bit32u ID */ + 'W','O','P','L', /* Bit32u ID */ + 0x0,0x0,0x0,0x0, /* Bit32u total milliseconds */ + 0x0,0x0,0x0,0x0, /* Bit32u total data */ + 0x0, /* Type 0=opl2,1=opl3,2=dual-opl2 */ +}; +/* Commands + 0x00 Bit8u, millisecond delay+1 + 0x01 Bit16u, millisecond delay+1 + 0x02 none, Use the low index/data pair + 0x03 none, Use the high index/data pair + 0xxx Bit8u, send command and data to current index/data pair +*/ + +static void OPL_RawEmptyBuffer(void) { + fwrite(opl.raw.buffer,1,opl.raw.used,opl.raw.handle); + opl.raw.done+=opl.raw.used; + opl.raw.used=0; +} + +#define ADDBUF(_VAL_) opl.raw.buffer[opl.raw.used++]=_VAL_; +static void OPL_RawAdd(Bitu index,Bitu val) { + /* Check if we have yet to start */ + Bit8u cmd=opl.raw.cmd[index]; + if (cmd<=3) return; + if (!opl.raw.handle) { + if (cmd<0xb0 || cmd>0xb8) return; + if (!(val&0x20)) return; + Bitu i; + opl.raw.last=PIC_Ticks; + opl.raw.start=PIC_Ticks; + opl.raw.handle=OpenCaptureFile("Raw Opl",".dro"); + if (!opl.raw.handle) { + opl.raw.capturing=false; return; - case 0x03: /* Timer 2 */ - timer2.count=val*320; - return; - case 0x04: /* IRQ clear / mask and Timer enable */ - if (val&0x80) { - timer1.isOverflowed=false; - timer2.isOverflowed=false; - return; + } + memset(opl.raw.buffer,0,sizeof(opl.raw.buffer)); + fwrite(dro_header,1,sizeof(dro_header),opl.raw.handle); + /* Check the registers to add */ + for (i=4;i<256;i++) { + if (!opl.raw.regs[0][i]) continue; + if (i>=0xb0 && i<=0xb8) continue; + ADDBUF((Bit8u)i); + ADDBUF(opl.raw.regs[0][i]); + } + bool donesecond=false; + for (i=4;i<256;i++) { + if (!opl.raw.regs[0][i]) continue; + if (i>=0xb0 && i<=0xb8) continue; + if (!donesecond) { + donesecond=true; + ADDBUF(0x3); } - if (val&0x40) timer1.isMasked=true; - else timer1.isMasked=false; - - if (val&1) { - timer1.isEnabled=true; - timer1.base=PIC_MicroCount(); - } else timer1.isEnabled=false; - if (val&0x20) timer2.isMasked=true; - else timer2.isMasked=false; - if (val&2) { - timer2.isEnabled=true; - timer2.base=PIC_MicroCount(); - } else timer2.isEnabled=false; - return; - default: /* Normal OPL call queue it */ - /* Use a little hack to directly write to the register */ - MAME::OPLWriteReg(MAME::OPL_YM3812[0],regsel,val); + ADDBUF((Bit8u)i); + ADDBUF(opl.raw.regs[0][i]); + } + if (donesecond) ADDBUF(0x2); } + /* Check how much time has passed, Allow an extra 5 milliseconds? */ + if (PIC_Ticks>(opl.raw.last+5)) { + Bitu passed=PIC_Ticks-opl.raw.last; + opl.raw.last=PIC_Ticks; + while (passed) { + passed-=1; + if (passed<256) { + ADDBUF(0x00); //8bit delay + ADDBUF((Bit8u)passed); //8bit delay + passed=0; + } else if (passed<0x10000) { + ADDBUF(0x01); //16bit delay + ADDBUF((Bit8u)(passed & 0xff)); //lo-byte + ADDBUF((Bit8u)(passed >> 8)); //hi-byte + passed=0; + } else { + ADDBUF(0x01); //16bit delay + ADDBUF(0xff); //lo-byte + ADDBUF(0xff); //hi-byte + passed-=0xffff; + } + } + } + /* Check if we're still sending to the correct index */ + if (opl.raw.index != index) { + opl.raw.index=index; + ADDBUF(opl.raw.index ? 0x3 : 0x2); + } + ADDBUF(cmd); + ADDBUF(val); + if (opl.raw.used>=RAW_SIZE) OPL_RawEmptyBuffer(); } -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"); +static void OPL_SaveRawEvent(void) { + /* Check for previously opened wave file */ + if (opl.raw.handle) { + OPL_RawEmptyBuffer(); + /* Fill in the header with useful information */ + host_writed(&dro_header[0x08],opl.raw.last-opl.raw.start); + host_writed(&dro_header[0x0c],opl.raw.done); + switch (opl.mode) { + case OPL_opl2:host_writeb(&dro_header[0x10],0x0);break; + case OPL_opl3:host_writeb(&dro_header[0x10],0x1);break; + case OPL_dualopl2:host_writeb(&dro_header[0x10],0x2);break; + } + fseek(opl.raw.handle,0,0); + fwrite(dro_header,1,sizeof(dro_header),opl.raw.handle); + fclose(opl.raw.handle); + opl.raw.handle=0; + } + if (opl.raw.capturing) { + opl.raw.capturing=false; + LOG_MSG("Stopping Raw OPL capturing."); } 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); + LOG_MSG("Preparing to capture Raw OPL, will start with first note played."); + opl.raw.capturing=true; + opl.raw.index=0; + opl.raw.used=0; + opl.raw.done=0; + opl.raw.start=0; + opl.raw.last=0; } } +static void OPL_Stop(Section* sec) { + if (opl.raw.handle) OPL_SaveRawEvent(); +} -void ADLIB_Init(Section* sec) { +void OPL_Init(Section* sec,Bitu base,OPL_Mode oplmode,Bitu rate) { Section_prop * section=static_cast(sec); - if(!section->Get_bool("adlib")) return; - - 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 - if (MAME::YM3812Init(OPL_NUM_CHIPS,OPL_INTERNAL_FREQ,ADLIB_FREQ)) { - E_Exit("Can't create adlib OPL Emulator"); + if (OPL2::YM3812Init(2,OPL2_INTERNAL_FREQ,rate)) { + E_Exit("Can't create OPL2 Emulator"); }; + OPL2::YM3812SetTimerHandler(0,OPL2::TimerHandler,0); + OPL2::YM3812SetTimerHandler(1,OPL2::TimerHandler,256); + if (THEOPL3::YMF262Init(1,OPL3_INTERNAL_FREQ,rate)) { + E_Exit("Can't create OPL3 Emulator"); + }; + THEOPL3::YMF262SetTimerHandler(0,THEOPL3::TimerHandler,0); + IO_RegisterWriteHandler(0x388,OPL_Write,IO_MB,4); + IO_RegisterReadHandler(0x388,OPL_Read,IO_MB,4); + if (oplmode>=OPL_dualopl2) { + IO_RegisterWriteHandler(base,OPL_Write,IO_MB,4); + IO_RegisterReadHandler(base,OPL_Read,IO_MB,4); + } + IO_RegisterWriteHandler(base+8,OPL_Write,IO_MB,2); + IO_RegisterReadHandler(base+8,OPL_Read,IO_MB,2); - adlib_chan=MIXER_AddChannel(ADLIB_CallBack,ADLIB_FREQ,"ADLIB"); - MIXER_SetMode(adlib_chan,MIXER_16MONO); - ADLIB_Enable(true); + opl.active=false; + opl.last_used=0; + opl.mode=oplmode; + memset(&opl.raw,0,sizeof(opl.raw)); + opl.chan=MIXER_AddChannel(OPL_CallBack,rate,"FM"); + MAPPER_AddHandler(OPL_SaveRawEvent,MK_f7,MMOD1|MMOD2,"caprawopl","Cap OPL"); + sec->AddDestroyFunction(&OPL_Stop); }; diff --git a/src/hardware/cmos.cpp b/src/hardware/cmos.cpp index 47a63a3..59cf9eb 100644 --- a/src/hardware/cmos.cpp +++ b/src/hardware/cmos.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -23,6 +23,7 @@ #include "pic.h" #include "inout.h" #include "mem.h" +#include "bios.h" static struct { Bit8u regs[0x40]; @@ -32,42 +33,36 @@ static struct { struct { bool enabled; Bit8u div; - Bitu micro; + float delay; } timer; struct { - Bit64u timer; - Bit64u ended; - Bit64u alarm; + double timer; + double ended; + double alarm; } last; - bool ack; bool update_ended; } cmos; -static void cmos_timerevent(void) { +static void cmos_timerevent(Bitu val) { PIC_ActivateIRQ(8); - if(cmos.timer.enabled) PIC_AddEvent(cmos_timerevent,cmos.timer.micro); - if (cmos.ack) { - PIC_AddEvent(cmos_timerevent,cmos.timer.micro); - cmos.regs[0x0c]|=0x0a0; - cmos.ack=false; - } + if (cmos.timer.enabled) PIC_AddEvent(cmos_timerevent,cmos.timer.delay); } static void cmos_checktimer(void) { PIC_RemoveEvents(cmos_timerevent); if (cmos.timer.div<=2) cmos.timer.div+=7; - cmos.timer.micro=(Bitu) (1000000.0/(32768.0 / (1 << (cmos.timer.div - 1)))); + 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 %f hz",1000000.0/cmos.timer.micro); - PIC_AddEvent(cmos_timerevent,cmos.timer.micro); + LOG(LOG_PIT,LOG_NORMAL)("RTC Timer at %.2f hz",1000.0/cmos.timer.delay); + PIC_AddEvent(cmos_timerevent,cmos.timer.delay); } -void cmos_selreg(Bit32u port,Bit8u val) { +void cmos_selreg(Bitu port,Bitu val,Bitu iolen) { cmos.reg=val & 0x3f; cmos.nmi=(val & 0x80)>0; } -static void cmos_writereg(Bit32u port,Bit8u val) { +static void cmos_writereg(Bitu port,Bitu val,Bitu iolen) { switch (cmos.reg) { case 0x00: /* Seconds */ case 0x02: /* Minutes */ @@ -84,10 +79,9 @@ static void cmos_writereg(Bit32u port,Bit8u val) { 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"); + if ((val & 0x70)!=0x20) LOG(LOG_BIOS,LOG_ERROR)("CMOS Illegal 22 stage divider value"); cmos.timer.div=(val & 0xf); cmos_checktimer(); break; @@ -110,11 +104,13 @@ static void cmos_writereg(Bit32u port,Bit8u val) { #define MAKE_RETURN(_VAL) (cmos.bcd ? (((_VAL / 10) << 4) | (_VAL % 10)) : _VAL); -static Bit8u cmos_readreg(Bit32u port) { +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; @@ -144,7 +140,7 @@ static Bit8u cmos_readreg(Bit32u port) { case 0x05: /* Hours Alarm */ return cmos.regs[cmos.reg]; case 0x0a: /* Status register C */ - if (PIC_Index()<0x2) { + if (PIC_TickIndex()<0.002) { return (cmos.regs[0x0a]&0x7f) | 0x80; } else { return (cmos.regs[0x0a]&0x7f); @@ -158,17 +154,96 @@ static Bit8u cmos_readreg(Bit32u port) { } else { /* Give correct values at certain times */ Bit8u val=0; - Bit64u index=PIC_MicroCount(); - if (index>=(cmos.last.timer+cmos.timer.micro)) { + double index=PIC_FullIndex(); + if (index>=(cmos.last.timer+cmos.timer.delay)) { cmos.last.timer=index; val|=0x40; } - if (index>=(cmos.last.ended+1000000)) { + 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 0x0f: /* Shutdown status byte */ case 0x17: /* Extended memory in KB Low Byte */ @@ -189,14 +264,14 @@ void CMOS_SetRegister(Bitu regNr, Bit8u val) }; void CMOS_Init(Section* sec) { - IO_RegisterWriteHandler(0x70,cmos_selreg,"CMOS"); - IO_RegisterWriteHandler(0x71,cmos_writereg,"CMOS"); - IO_RegisterReadHandler(0x71,cmos_readreg,"CMOS"); + IO_RegisterWriteHandler(0x70,cmos_selreg,IO_MB); + IO_RegisterWriteHandler(0x71,cmos_writereg,IO_MB); + IO_RegisterReadHandler(0x71,cmos_readreg,IO_MB); cmos.timer.enabled=false; cmos.reg=0xa; - cmos_writereg(0x71,0x26); + cmos_writereg(0x71,0x26,1); cmos.reg=0xb; - cmos_writereg(0x71,0); + cmos_writereg(0x71,0,1); /* Fill in extended memory size */ Bitu exsize=(MEM_TotalPages()*4)-1024; cmos.regs[0x17]=(Bit8u)exsize; diff --git a/src/hardware/directserial_win32.cpp b/src/hardware/directserial_win32.cpp new file mode 100644 index 0000000..04c1615 --- /dev/null +++ b/src/hardware/directserial_win32.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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.4 2004/08/04 13:21:20 qbix79 Exp $ */ + +#include "dosbox.h" + +#if C_DIRECTSERIAL + +/* Windows version */ +#if defined (WIN32) + +#include +#include +#include + +#include "setup.h" +#include "serialport.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 */ + + +class CDirectSerial : public CSerial { +public: + HANDLE hCom; + DCB dcb; + BOOL fSuccess; + + CDirectSerial(char * realPort, Bit16u baseAddr, Bit8u initIrq, Bit32u initBps, Bit16u bytesize, char *parity, Bit16u stopbits ) : CSerial(baseAddr, initIrq, initBps) { + LOG_MSG("Opening Windows serial port"); + hCom = CreateFile(realPort, 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) + { + LOG_MSG("CreateFile failed with error %d.\n", GetLastError()); + hCom = 0; + return; + } + + fSuccess = GetCommState(hCom, &dcb); + + if (!fSuccess) + { + // Handle the error. + LOG_MSG("GetCommState failed with error %d.\n", GetLastError()); + return; + } + + + dcb.BaudRate = initBps; // set the baud rate + dcb.ByteSize = bytesize; // data size, xmit, and rcv + if(parity[0] == 'N') + dcb.Parity = NOPARITY; // no parity bit + if(parity[1] == 'E') + dcb.Parity = EVENPARITY; // even parity bit + if(parity[2] == 'O') + dcb.Parity = ODDPARITY; // odd parity bit + + + if(stopbits == 1) + dcb.StopBits = ONESTOPBIT; // one stop bit + if(stopbits == 2) + dcb.StopBits = TWOSTOPBITS; // two stop bits + + fSuccess = SetCommState(hCom, &dcb); + + // 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); + + } + + ~CDirectSerial() { + if(hCom != INVALID_HANDLE_VALUE) CloseHandle(hCom); + } + + bool CanRecv(void) { return true; } + bool CanSend(void) { return true; } + + void Send(Bit8u val) { tqueue->addb(val); } + + Bit8u Recv(Bit8u val) { return rqueue->getb(); } + + void updatestatus(void) { + Bit8u ms=0; + DWORD stat = 0; + GetCommModemStatus(hCom, &stat); + + //Check for data carrier + if(stat & MS_RLSD_ON) ms|=MS_DCD; + if (stat & MS_RING_ON) ms|=MS_RI; + if (stat & MS_DSR_ON) ms|=MS_DSR; + if (stat & MS_CTS_ON) ms|=MS_CTS; + SetModemStatus(ms); + } + + void Timer(void) { + DWORD dwRead; + Bit8u chRead; + + if (ReadFile(hCom, &chRead, 1, &dwRead, NULL)) { + if(dwRead != 0) { + if(!rqueue->isFull()) rqueue->addb(chRead); + } + } + + updatestatus(); + + Bit8u txval; + + Bitu tx_size=tqueue->inuse(); + while (tx_size--) { + txval = tqueue->getb(); + DWORD bytesWritten; + BOOL result; + result = WriteFile(hCom, &txval, 1, &bytesWritten, NULL); + if (!result) + { + // Handle the error. + LOG_MSG("WriteFile failed with error %d.\n", GetLastError()); + return; + } + + } + } + +}; + +CDirectSerial *cds; + +void DIRECTSERIAL_Init(Section* sec) { + + unsigned long args = 1; + Section_prop * section=static_cast(sec); + + + if(!section->Get_bool("directserial")) return; + + Bit16u comport = section->Get_int("comport"); + Bit32u bps = section->Get_int("defaultbps"); + switch (comport) { + case 1: + cds = new CDirectSerial((char *)section->Get_string("realport"), 0x3f0, 4, bps, section->Get_int("bytesize"), (char *)section->Get_string("parity"), section->Get_int("stopbit")); + break; + case 2: + cds = new CDirectSerial((char *)section->Get_string("realport"), 0x2f0, 3, bps, section->Get_int("bytesize"), (char *)section->Get_string("parity"), section->Get_int("stopbit")); + break; + case 3: + cds = new CDirectSerial((char *)section->Get_string("realport"), 0x3e0, 4, bps, section->Get_int("bytesize"), (char *)section->Get_string("parity"), section->Get_int("stopbit")); + break; + case 4: + cds = new CDirectSerial((char *)section->Get_string("realport"), 0x2e0, 3, bps, section->Get_int("bytesize"), (char *)section->Get_string("parity"), section->Get_int("stopbit")); + break; + default: + cds = new CDirectSerial((char *)section->Get_string("realport"), 0x3f0, 4, bps, section->Get_int("bytesize"), (char *)section->Get_string("parity"), section->Get_int("stopbit")); + break; + + } + + + + seriallist.push_back(cds); +} +#else /*linux and others oneday maybe */ + +#endif +#endif + diff --git a/src/hardware/disney.cpp b/src/hardware/disney.cpp index 4baf3e2..36d36ef 100644 --- a/src/hardware/disney.cpp +++ b/src/hardware/disney.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -20,13 +20,8 @@ #include "dosbox.h" #include "inout.h" #include "mixer.h" -#include "dma.h" #include "pic.h" -#include "hardware.h" #include "setup.h" -#include "programs.h" - - #define DISNEY_BASE 0x0378 @@ -37,11 +32,15 @@ static struct { Bit8u status; Bit8u control; Bit8u buffer[DISNEY_SIZE]; - Bitu used; - MIXER_Channel * chan; + Bitu used;Bitu last_used; + MixerChannel * chan; } disney; -static void disney_write(Bit32u port,Bit8u val) { +static void disney_write(Bitu port,Bitu val,Bitu iolen) { + if (!disney.last_used) { + disney.chan->Enable(true); + } + disney.last_used=PIC_Ticks; switch (port-DISNEY_BASE) { case 0: /* Data Port */ disney.data=val; @@ -62,8 +61,7 @@ static void disney_write(Bit32u port,Bit8u val) { } } -static Bit8u disney_read(Bit32u port) { - +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"); @@ -83,18 +81,21 @@ static Bit8u disney_read(Bit32u port) { } -static void DISNEY_CallBack(Bit8u * stream,Bit32u len) { +static void DISNEY_CallBack(Bitu len) { if (!len) return; if (disney.used>len) { - memcpy(stream,disney.buffer,len); + disney.chan->AddSamples_m8(len,disney.buffer); memmove(disney.buffer,&disney.buffer[len],disney.used-len); disney.used-=len; - return; } else { - memcpy(stream,disney.buffer,disney.used); - memset(stream+disney.used,0x80,len-disney.used); + disney.chan->AddSamples_m8(disney.used,disney.buffer); + disney.chan->AddSilence(); disney.used=0; } + if (disney.last_used+5000Enable(false); + } } @@ -103,20 +104,14 @@ void DISNEY_Init(Section* sec) { Section_prop * section=static_cast(sec); if(!section->Get_bool("disney")) return; - IO_RegisterWriteHandler(DISNEY_BASE,disney_write,"DISNEY"); - IO_RegisterWriteHandler(DISNEY_BASE+1,disney_write,"DISNEY"); - IO_RegisterWriteHandler(DISNEY_BASE+2,disney_write,"DISNEY"); - - IO_RegisterReadHandler(DISNEY_BASE,disney_read,"DISNEY"); - IO_RegisterReadHandler(DISNEY_BASE+1,disney_read,"DISNEY"); - IO_RegisterReadHandler(DISNEY_BASE+2,disney_read,"DISNEY"); + IO_RegisterWriteHandler(DISNEY_BASE,disney_write,IO_MB,3); + IO_RegisterReadHandler(DISNEY_BASE,disney_read,IO_MB,3); disney.chan=MIXER_AddChannel(&DISNEY_CallBack,7000,"DISNEY"); - MIXER_SetMode(disney.chan,MIXER_8MONO); - MIXER_Enable(disney.chan,true); disney.status=0x84; disney.control=0; disney.used=0; + disney.last_used=0; } diff --git a/src/hardware/dma.cpp b/src/hardware/dma.cpp index e951d8e..0c63a3a 100644 --- a/src/hardware/dma.cpp +++ b/src/hardware/dma.cpp @@ -9,17 +9,13 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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 the port handling from the bochs dma code. -*/ - #include #include "dosbox.h" #include "mem.h" @@ -30,446 +26,238 @@ DmaChannel *DmaChannels[8]; DmaController *DmaControllers[2]; - -Bit16u DmaController::portRead(Bit32u port, bool eightbit) { - LOG_MSG("Reading DMA controller at %x", port); - return 0xffff; -} - -void DmaController::portWrite(Bit32u port, Bit16u val, bool eightbit) { - bool found; - found = false; - if(port == ControllerPorts[ctrlnum][DMA_CLRMASKREG]) { - found = true; - flipflop = true; - // Disable DMA requests - // Clear command and status registers - } - if(port == ControllerPorts[ctrlnum][DMA_SINGLEREG]) { - found = true; - int dmachan; - dmachan = (ctrlnum * 2) + (val & 0x3); - DmaChannels[dmachan]->masked = ((val & 0x4) == 0x4); - DmaChannels[dmachan]->Notify(); - } - if(port == ControllerPorts[ctrlnum][DMA_WRITEALLREG]) { - found = true; - int dmachan,i,r; - dmachan = (ctrlnum * 2); - r = 0; - for(i=dmachan;imasked = (((val >> r) & 0x1) == 0x1); - DmaChannels[i]->Notify(); - r++; - } - - } - if(port == ControllerPorts[ctrlnum][DMA_CLEARREG]) { - found = true; - flipflop = true; - } - if(port == ControllerPorts[ctrlnum][DMA_MODEREG]) { - found = true; - int dmachan; - dmachan = (ctrlnum * 2) + (val & 0x3); - DmaChannels[dmachan]->trantype = (val >> 2) & 0x3; - DmaChannels[dmachan]->autoinit = ((val & 0x10) == 0x10); - DmaChannels[dmachan]->dir = ((val & 0x20) == 0x20); - DmaChannels[dmachan]->dmamode = (val >> 6) & 0x3; - DmaChannels[dmachan]->Notify(); - } - if(!found) LOG_MSG("Write to DMA port %x with %x", port, val); - -} - - -Bit32u DmaChannel::Read(Bit32s requestsize, Bit8u * buffer) { - Bit32s bytesread; - bytesread = 0; - if(autoinit) { - while(requestsize>0) { - if(currcnt>=requestsize) { - MEM_BlockRead(curraddr,buffer,requestsize); - curraddr+=requestsize; - buffer+=requestsize; - currcnt-=requestsize; - bytesread+=requestsize; - requestsize=0; - break; - } else { - MEM_BlockRead(curraddr,buffer,currcnt); - bytesread+=currcnt; - buffer+=currcnt; - requestsize-=currcnt; - reset(); - MakeCallback(true); - } - } - if(currcnt==0) { - reset(); - MakeCallback(true); - } - return bytesread; - - } else { - if(currcnt>=requestsize) { - MEM_BlockRead(curraddr,buffer,requestsize); - curraddr+=requestsize; - buffer+=requestsize; - currcnt-=requestsize; - bytesread+=requestsize; +static void DMA_WriteControllerReg(DmaController * cont,Bitu reg,Bitu val,Bitu len) { + DmaChannel * chan;Bitu i; + Bitu base=cont->chanbase; + switch (reg) { + case 0x0:case 0x2:case 0x4:case 0x6: + chan=DmaChannels[base+(reg >> 1)]; + cont->flipflop=!cont->flipflop; + if (cont->flipflop) { + chan->baseaddr=(chan->baseaddr&0xff00)|val; + chan->curraddr=(chan->curraddr&0xff00)|val; } else { - MEM_BlockRead(curraddr,buffer,currcnt); - buffer+=currcnt; - requestsize-=currcnt; - bytesread+=currcnt; - currcnt=0; + chan->baseaddr=(chan->baseaddr&0x00ff)|(val << 8); + chan->curraddr=(chan->curraddr&0x00ff)|(val << 8); } - } - if(currcnt==0) MakeCallback(true); - return bytesread; -} - -Bit32u DmaChannel::Write(Bit32s requestsize, Bit8u * buffer) { - Bit32s byteswrite; - byteswrite = 0; - if(autoinit) { - while(requestsize>0) { - if(currcnt>=requestsize) { - MEM_BlockWrite(curraddr,buffer,requestsize); - curraddr+=requestsize; - buffer+=requestsize; - currcnt-=requestsize; - byteswrite+=requestsize; - requestsize=0; - break; - } else { - MEM_BlockWrite(curraddr,buffer,currcnt); - byteswrite+=currcnt; - buffer+=currcnt; - requestsize-=currcnt; - reset(); - MakeCallback(true); - } - } - if(currcnt==0) { - reset(); - MakeCallback(true); - } - return byteswrite; - - } else { - if(currcnt>=requestsize) { - MEM_BlockWrite(curraddr,buffer,requestsize); - curraddr+=requestsize; - buffer+=requestsize; - currcnt-=requestsize; - byteswrite+=requestsize; + break; + case 0x1:case 0x3:case 0x5:case 0x7: + chan=DmaChannels[base+(reg >> 1)]; + cont->flipflop=!cont->flipflop; + if (cont->flipflop) { + chan->basecnt=(chan->basecnt&0xff00)|val; + chan->currcnt=(chan->currcnt&0xff00)|val; } else { - MEM_BlockWrite(curraddr,buffer,currcnt); - buffer+=currcnt; - requestsize-=currcnt; - byteswrite+=currcnt; - currcnt=0; + 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 */ + chan=DmaChannels[base+(val & 3 )]; + chan->SetMask((val & 0x4)>0); + break; + case 0xb: /* Mode Register */ + chan=DmaChannels[base+(val & 3 )]; + chan->autoinit=(val & 0x10) > 0; + chan->increment=(val & 0x20) > 0; + //TODO Maybe other bits? + break; + case 0xc: /* Clear Flip/Flip */ + cont->flipflop=false; + break; + case 0xd: /* Master Clear/Reset */ + for (i=0;i<4;i++) { + DmaChannels[base+i]->SetMask(true); + DmaChannels[base+i]->tcount=false; + } + cont->flipflop=false; + break; + case 0xe: /* Clear Mask register */ + for (i=0;i<4;i++) { + DmaChannels[base+i]->SetMask(false); + } + break; + case 0xf: /* Multiple Mask register */ + for (i=0;i<4;i++) { + DmaChannels[base+i]->SetMask(val & 1); + val>>=1; + } + break; } - if(currcnt==0) MakeCallback(true); - return byteswrite; } - -void DmaChannel::calcPhys(void) { - if (DMA16) { - physaddr = (baseaddr << 1) | ((pageaddr >> 1) << 17); - } else { - physaddr = (baseaddr) | (pageaddr << 16); - } - curraddr = physaddr; - current_addr = baseaddr; -} - -#define ff myController->flipflop - -Bit16u DmaChannel::portRead(Bit32u port, bool eightbit) { - if (port == ChannelPorts[DMA_BASEADDR][channum]) { - if(eightbit) { - if(ff) { - ff = !ff; - return current_addr & 0xff; - } else { - ff = !ff; - return current_addr >> 8; - } +static Bitu DMA_ReadControllerReg(DmaController * cont,Bitu reg,Bitu len) { + DmaChannel * chan;Bitu i,ret; + Bitu base=cont->chanbase; + switch (reg) { + case 0x0:case 0x2:case 0x4:case 0x6: + chan=DmaChannels[base+(reg >> 1)]; + cont->flipflop=!cont->flipflop; + if (cont->flipflop) { + return chan->curraddr & 0xff; } else { - return current_addr; + return (chan->curraddr >> 8) & 0xff; } - } - if (port == ChannelPorts[DMA_TRANSCOUNT][channum]) { - if(eightbit) { - if(ff) { - ff = !ff; - return (Bit8u)(currcnt-1); - } else { - ff = !ff; - return (Bit8u)((currcnt-1) >> 8); - } + case 0x1:case 0x3:case 0x5:case 0x7: + chan=DmaChannels[base+(reg >> 1)]; + cont->flipflop=!cont->flipflop; + if (cont->flipflop) { + return chan->currcnt & 0xff; } else { - return (Bit16u)currcnt; + return (chan->currcnt >> 8) & 0xff; } - } - if (port == ChannelPorts[DMA_PAGEREG][channum]) return pageaddr; - return 0xffff; -} - -void DmaChannel::portWrite(Bit32u port, Bit16u val, bool eightbit) { - if (port == ChannelPorts[DMA_BASEADDR][channum]) { - if(eightbit) { - if(ff) { - baseaddr = (baseaddr & 0xff00) | (Bit8u)val; - } else { - baseaddr = (baseaddr & 0xff) | (val << 8); - } - ff = !ff; - } else { - baseaddr = val; + case 0x8: + ret=0; + for (i=0;i<4;i++) { + chan=DmaChannels[base+i]; + if (chan->tcount) ret|=1 << i; + chan->tcount=false; + if (chan->callback) ret|=1 << (i+4); } - calcPhys(); - addr_changed = true; - } - if (port == ChannelPorts[DMA_TRANSCOUNT][channum]) { - if(eightbit) { - if(ff) { - transcnt = (transcnt & 0xff00) | (Bit8u)val; - } else { - transcnt = (transcnt & 0xff) | (val << 8); - } - ff = !ff; - } else { - transcnt = val; - } - currcnt = transcnt+1; - addr_changed = true; - DMA_CheckEnabled(this); - MakeCallback(false); - - } - if (port == ChannelPorts[DMA_PAGEREG][channum]) { - pageaddr = val; - calcPhys(); - reset(); - } - -} - -#undef ff - -// Notify channel when mask changes -void DmaChannel::Notify(void) { - if(!masked) { - DMA_CheckEnabled(this); - MakeCallback(false); + return ret; + default: + LOG_MSG("Trying to read undefined DMA Red %x",reg); } + return 0xffffffff; } -static Bit16u readDMAPorts(Bit32u port, bool eightbit) { - int i,j; - - // Check for controller access - for(i=0;i<2;i++) { - for(j=0;j<7;j++) { - if(ControllerPorts[i][j] == port) { - return DmaControllers[i]->portRead(port, eightbit); - } - } - } - - // Check for DMA access - for(i=0;i<8;i++) { - for(j=0;j<3;j++) { - if(ChannelPorts[j][i] == port) { - return DmaChannels[i]->portRead(port, eightbit); - } - } - } - - LOG_MSG("Unmatched read port %x", port); - - return 0xffff; - -} - -static void writeDMAPorts(Bit32u port, Bit16u val, bool eightbit) { - int i,j; - - // Check for controller access - for(i=0;i<2;i++) { - for(j=0;j<7;j++) { - if(ControllerPorts[i][j] == port) { - DmaControllers[i]->portWrite(port,val,eightbit); - return; - } - } - } - - // Check for DMA access - for(i=0;i<8;i++) { - for(j=0;j<3;j++) { - if(ChannelPorts[j][i] == port) { - DmaChannels[i]->portWrite(port,val,eightbit); - return; - } - } - } - - LOG_MSG("Unmatched write port %x - val %x", port, val); - -} - -Bit8u read_dmaB(Bit32u port) { return (Bit8u)readDMAPorts(port,true); } - -Bit16u read_dmaW(Bit32u port) { return readDMAPorts(port,false); } - -void write_dmaB(Bit32u port,Bit8u val) { writeDMAPorts(port,val,true); } - -void write_dmaW(Bit32u port,Bit16u val) { writeDMAPorts(port,val,false); } - - -// Deprecated DMA read/write routines -- Keep compatibility with Sound Blaster -Bitu DMA_8_Read(Bitu dmachan,Bit8u * buffer,Bitu count) { - DmaChannel *chan=DmaChannels[dmachan]; - - if (chan->masked) return 0; - if (!count) return 0; - if (chan->addr_changed) chan->reset(); - - if (chan->currcnt>(Bits)count) { - MEM_BlockRead(chan->curraddr,buffer,count); - chan->curraddr+=count; - chan->current_addr+=count; - chan->currcnt-=count; - return count; - } else { - // Copy remaining piece of first buffer - MEM_BlockRead(chan->curraddr,buffer,chan->currcnt); - if (!chan->autoinit) { - // Set the end of counter bit - //dma[0].status_reg|=(1 << dmachan); - count=chan->currcnt; - chan->curraddr+=count; - chan->current_addr+=count; - chan->currcnt=0; - chan->enabled=false; - LOG(LOG_DMA,LOG_NORMAL)("8-bit Channel %d reached terminal count",chan->channum); - return count; - } else { - buffer+=chan->currcnt; - Bitu left=count-(Bit16u)chan->currcnt; - // Autoinit reset the dma channel - chan->reset(); - // Copy the rest of the buffer - MEM_BlockRead(chan->curraddr,buffer,left); - chan->curraddr+=left; - chan->current_addr+=left; - chan->currcnt-=left; - return count; - } +static void DMA_Write_Port(Bitu port,Bitu val,Bitu iolen) { + if (port<0x10) { + DMA_WriteControllerReg(DmaControllers[0],port,val,1); + } else if (port>=0xc0 && port <=0xdf) { + DMA_WriteControllerReg(DmaControllers[1],(port-0xc0) >> 1,val,1); + } else switch (port) { + case 0x81:DmaChannels[2]->SetPage(val);break; + case 0x82:DmaChannels[3]->SetPage(val);break; + case 0x83:DmaChannels[1]->SetPage(val);break; + case 0x89:DmaChannels[6]->SetPage(val);break; + case 0x8a:DmaChannels[7]->SetPage(val);break; + case 0x8b:DmaChannels[5]->SetPage(val);break; } } -Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { - DmaChannel *chan=DmaChannels[dmachan]; - - if (chan->masked) return 0; - if (!count) return 0; - if (chan->currcnt>(Bits)count) { - MEM_BlockWrite(chan->curraddr,buffer,count); - chan->curraddr+=count; - chan->currcnt-=count; - return count; - } else { - // Copy remaining piece of first buffer - MEM_BlockWrite(chan->curraddr,buffer,chan->currcnt); - if (!chan->autoinit) { - // Set the end of counter bit - //dma[0].status_reg|=(1 << dmachan); - count=chan->currcnt; - chan->curraddr+=count;; - chan->currcnt=0; - return count; - } else { - buffer+=chan->currcnt; - Bitu left=count-(Bit16u)chan->currcnt; - // Autoinit reset the dma channel - chan->reset(); - // Copy the rest of the buffer - MEM_BlockWrite(chan->curraddr,buffer,left); - chan->curraddr+=left; - chan->currcnt-=left; - return count; - } +static Bitu DMA_Read_Port(Bitu port,Bitu iolen) { + if (port<0x10) { + return DMA_ReadControllerReg(DmaControllers[0],port,iolen); + } else if (port>=0xc0 && port <=0xdf) { + return DMA_ReadControllerReg(DmaControllers[1],(port-0xc0) >> 1,iolen); + } else switch (port) { + case 0x81:return DmaChannels[2]->pagenum; + case 0x82:return DmaChannels[3]->pagenum; + case 0x83:return DmaChannels[1]->pagenum; + case 0x89:return DmaChannels[6]->pagenum; + case 0x8a:return DmaChannels[7]->pagenum; + case 0x8b:return DmaChannels[5]->pagenum; } -} - - -Bitu DMA_16_Read(Bitu dmachan,Bit8u * buffer,Bitu count) { - return 0; } -Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { - - - return 0; +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; } -void DMA_SetEnabled(void * usechan,bool enabled) { - DmaChannel * chan; - chan = (DmaChannel *)usechan; - - if (chan->enabled == enabled) return; - chan->enabled=enabled; - if (chan->enable_callback) (*chan->enable_callback)(enabled); -} - -void DMA_CheckEnabled(void * usechan) { - DmaChannel * chan; - chan = (DmaChannel *)usechan; - - bool enabled; - if (chan->masked) enabled=false; - else { - if (chan->autoinit) enabled=true; - else if (chan->currcnt) enabled=true; - else enabled=false; +Bitu DmaChannel::Read(Bitu want, Bit8u * buffer) { + Bitu done=0; +again: + Bitu left=(currcnt+1); + if (wantenabled=false; - chan->enable_callback=callback; - DMA_CheckEnabled(chan); -} - void DMA_Init(Section* sec) { - Bitu i; - DmaControllers[0] = new DmaController(0); DmaControllers[1] = new DmaController(1); - for(i=0;i<4;i++) { - DmaChannels[i] = new DmaChannel(i,DmaControllers[0],false); + for(i=0;i<8;i++) { + DmaChannels[i] = new DmaChannel(i,i>=4); } - for(i=4;i<8;i++) { - DmaChannels[i] = new DmaChannel(i,DmaControllers[1],true); + + for (i=0;i<0x10;i++) { + Bitu mask=IO_MB; + if (i<8) mask|=IO_MW; + IO_RegisterWriteHandler(i,DMA_Write_Port,mask); + IO_RegisterReadHandler(i,DMA_Read_Port,mask); + if (machine==MCH_VGA) { + IO_RegisterWriteHandler(0xc0+i*2,DMA_Write_Port,mask); + IO_RegisterReadHandler(0xc0+i*2,DMA_Read_Port,mask); + } } + IO_RegisterWriteHandler(0x81,DMA_Write_Port,IO_MB,3); + IO_RegisterWriteHandler(0x89,DMA_Write_Port,IO_MB,3); + IO_RegisterReadHandler(0x81,DMA_Read_Port,IO_MB,3); + IO_RegisterReadHandler(0x89,DMA_Read_Port,IO_MB,3); } diff --git a/src/hardware/ega-switch.h b/src/hardware/ega-switch.h deleted file mode 100644 index b4dff45..0000000 --- a/src/hardware/ega-switch.h +++ /dev/null @@ -1,9730 +0,0 @@ -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 b4d7c8e..9427447 100644 --- a/src/hardware/fmopl.c +++ b/src/hardware/fmopl.c @@ -3,14 +3,23 @@ ** 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 -** Copyright (C) 2002 Jarek Burczynski ** -** Version 0.60 +** 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, @@ -51,9 +60,8 @@ Revision History: #include #include -#include -#include #include + //#include "driver.h" /* use M.A.M.E. */ #include "fmopl.h" @@ -117,10 +125,45 @@ Revision History: /*#define SAVE_SAMPLE*/ #ifdef SAVE_SAMPLE +INLINE signed int acc_calc(signed int value) +{ + if (value>=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 = lt; \ + { signed int pom = acc_calc(lt); \ fputc((unsigned short)pom&0xff,sample[0]); \ fputc(((unsigned short)pom>>8)&0xff,sample[0]); \ } @@ -155,8 +198,6 @@ static FILE *sample[1]; -/* Saving is necessary for member of the 'R' mark for suspend/resume */ - typedef struct{ UINT32 ar; /* attack rate: AR<<2 */ UINT32 dr; /* decay rate: DR<<2 */ @@ -181,14 +222,12 @@ typedef struct{ 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 */ @@ -237,6 +276,7 @@ typedef struct fm_opl_f { UINT8 wavesel; /* waveform select enable flag */ int T[2]; /* timer counters */ + int TC[2]; UINT8 st[2]; /* timer enable */ #if BUILD_Y8950 @@ -244,7 +284,7 @@ typedef struct fm_opl_f { YM_DELTAT *deltat; - /* Keyboard / I/O interface unit*/ + /* Keyboard and I/O ports interface */ UINT8 portDirection; UINT8 portLatch; OPL_PORTHANDLER_R porthandler_r; @@ -375,7 +415,7 @@ static const unsigned char eg_inc[15*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 dummy (infinite time) rates */ +/* 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), @@ -410,13 +450,13 @@ 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 +/*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 dummy (infinite time) rates */ +/* 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), @@ -586,15 +626,15 @@ static const INT8 lfo_pm_table[8*8*2] = { /* 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 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 */ +static INT32 output_deltat[4]; /* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */ #endif static UINT32 LFO_AM; @@ -699,8 +739,6 @@ INLINE void advance(FM_OPL *OPL) switch(op->state) { case EG_ATT: /* attack phase */ - { - if ( !(OPL->eg_cnt & ((1<eg_sh_ar)-1) ) ) { op->volume += (~op->volume * @@ -714,8 +752,6 @@ INLINE void advance(FM_OPL *OPL) } } - - } break; case EG_DEC: /* decay phase */ @@ -792,7 +828,7 @@ INLINE void advance(FM_OPL *OPL) { block_fnum += lfo_fn_table_index_offset; block = (block_fnum&0x1c00) >> 10; - op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;//ok + op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul; } else /* LFO phase modulation = zero */ { @@ -857,15 +893,8 @@ INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigne INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab) { 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<<4) + sin_tab[ wave_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) );*/ + p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK) ]; if (p >= TL_TAB_LEN) return 0; @@ -966,7 +995,7 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise ) if (!SLOT->CON) phase_modulation = SLOT->op1_out[0]; - //else ignore output of operator 1 + /* else ignore output of operator 1 */ SLOT->op1_out[1] = 0; if( env < ENV_QUIET ) @@ -984,16 +1013,16 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise ) /* 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) + /* 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 + /* HH channel 7->slot1 */ + /* SD channel 7->slot2 */ + /* TOM channel 8->slot1 */ + /* TOP channel 8->slot2 */ /* The following formulas can be well optimized. @@ -1048,7 +1077,7 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise ) phase = 0xd0>>2; } - output[0] += op_calc(phase<wavetable) * 2; + output[0] += op_calc(phase<wavetable) * 2; } /* Snare Drum (verified on real YM3812) */ @@ -1069,13 +1098,13 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise ) if (noise) phase ^= 0x100; - output[0] += op_calc(phase<wavetable) * 2; + 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, SLOT->wavetable) * 2; + output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2; /* Top Cymbal (verified on real YM3812) */ env = volume_calc(SLOT8_2); @@ -1102,7 +1131,7 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise ) if (res2) phase = 0x300; - output[0] += op_calc(phase<wavetable) * 2; + output[0] += op_calc(phase<wavetable) * 2; } } @@ -1229,13 +1258,14 @@ 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 +#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 ); @@ -1456,25 +1486,27 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v) } else { /* set IRQ mask ,timer enable*/ - UINT8 st1 = v&1; - UINT8 st2 = (v>>1)&1; + 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)|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); - } + OPL_STATUS_RESET(OPL, v & 0x78 ); + OPL_STATUSMASK_SET(OPL, (~v) & 0x78 ); + /* timer 1 */ - if(OPL->st[0] != st1) + if(OPL->st[0]) { - double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0; - OPL->st[0] = st1; + 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 @@ -1484,34 +1516,43 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v) if(OPL->keyboardhandler_w) OPL->keyboardhandler_w(OPL->keyboard_param,v); else - logerror("OPL:write unmapped KEYBOARD port\n"); + logerror("Y8950: write unmapped KEYBOARD port\n"); } break; - case 0x07: /* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */ + 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; - case 0x08: /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */ +#endif + case 0x08: /* MODE,DELTA-T control 2 : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */ OPL->mode = v; - v&=0x1f; /* for DELTA-T unit */ +#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 */ + case 0x0f: /* ADPCM data write */ case 0x10: /* DELTA-N */ case 0x11: /* DELTA-N */ - case 0x12: /* EG-CTRL */ + case 0x12: /* ADPCM volume */ 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 */ + + 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; @@ -1524,10 +1565,10 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v) OPL->porthandler_w(OPL->port_param,v&OPL->portDirection); } break; - case 0x1a: /* PCM data */ +#endif + default: + logerror("FMOPL.C: write to unknown register: %02x\n",r); break; -#endif -#endif } break; case 0x20: /* am ON, vib ON, ksr, eg_type, mul */ @@ -1773,7 +1814,7 @@ static void OPLResetChip(FM_OPL *OPL) #endif } -/* Create one of virtual YM3812 */ +/* 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) @@ -1806,7 +1847,9 @@ static FM_OPL *OPLCreate(int type, int clock, int rate) #if BUILD_Y8950 if (type&OPL_TYPE_ADPCM) + { OPL->deltat = (YM_DELTAT *)ptr; + } ptr += sizeof(YM_DELTAT); #endif @@ -1817,8 +1860,6 @@ static FM_OPL *OPLCreate(int type, int clock, int rate) /* init global tables */ OPL_initalize(OPL); - /* reset chip */ - OPLResetChip(OPL); return OPL; } @@ -1829,7 +1870,7 @@ static void OPLDestroy(FM_OPL *OPL) free(OPL); } -/* Option handlers */ +/* Optional handlers */ static void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset) { @@ -1847,7 +1888,6 @@ static void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int OPL->UpdateParam = param; } -/* YM3812 I/O interface */ static int OPLWrite(FM_OPL *OPL,int a,int v) { if( !(a&1) ) @@ -1867,6 +1907,29 @@ 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]) { + if (OPL->TC[0]) OPL->TC[0]--; + else { + OPL->TC[0]=OPL->T[0]*20; + OPL_STATUS_SET(OPL,0x40); + } + } + if (OPL->st[1]) { + if (OPL->TC[1]) OPL->TC[1]--; + else { + OPL->TC[1]=OPL->T[1]*20; + OPL_STATUS_SET(OPL,0x40); + } + } return OPL->status & (OPL->statusmask|0x80); } @@ -1880,23 +1943,36 @@ static unsigned char OPLRead(FM_OPL *OPL,int a) if(OPL->keyboardhandler_r) return OPL->keyboardhandler_r(OPL->keyboard_param); else - logerror("OPL:read unmapped KEYBOARD port\n"); + logerror("Y8950: read unmapped KEYBOARD port\n"); } return 0; -#if 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; -#endif + case 0x19: /* I/O DATA */ if(OPL->type&OPL_TYPE_IO) { if(OPL->porthandler_r) return OPL->porthandler_r(OPL->port_param); else - logerror("OPL:read unmapped I/O port\n"); + 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 @@ -1936,7 +2012,7 @@ static int OPLTimerOver(FM_OPL *OPL,int c) } } /* reload timer */ - if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase); +// if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase); return OPL->status>>7; } @@ -1968,6 +2044,8 @@ int YM3812Init(int num, int clock, int rate) YM3812NumChips = 0; return -1; } + /* reset */ + YM3812ResetChip(i); } return 0; @@ -2076,7 +2154,10 @@ void YM3812UpdateOne(int which, INT16 *buffer, int length) lt = limit( lt , MAXOUT, MINOUT ); #ifdef SAVE_SAMPLE + if (which==0) + { SAVE_ALL_CHANNELS + } #endif /* store to sound buffer */ @@ -2114,6 +2195,8 @@ int YM3526Init(int num, int clock, int rate) YM3526NumChips = 0; return -1; } + /* reset */ + YM3526ResetChip(i); } return 0; @@ -2143,7 +2226,8 @@ int YM3526Write(int which, int a, int v) unsigned char YM3526Read(int which, int a) { - return OPLRead(OPL_YM3526[which], a); + /* YM3526 always returns bit2 and bit1 in HIGH state */ + return OPLRead(OPL_YM3526[which], a) | 0x06 ; } int YM3526TimerOver(int which, int c) { @@ -2221,7 +2305,10 @@ void YM3526UpdateOne(int which, INT16 *buffer, int length) lt = limit( lt , MAXOUT, MINOUT ); #ifdef SAVE_SAMPLE + if (which==0) + { SAVE_ALL_CHANNELS + } #endif /* store to sound buffer */ @@ -2241,6 +2328,15 @@ void YM3526UpdateOne(int which, INT16 *buffer, int length) 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; @@ -2260,6 +2356,13 @@ int Y8950Init(int num, int clock, int rate) 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; @@ -2309,11 +2412,11 @@ void Y8950SetUpdateHandler(int which,OPL_UPDATEHANDLER UpdateHandler,int param) OPLSetUpdateHandler(OPL_Y8950[which], UpdateHandler, param); } -void Y8950SetDeltaTMemory(int which, void * deltat_rom, int deltat_rom_size ) +void Y8950SetDeltaTMemory(int which, void * deltat_mem_ptr, int deltat_mem_size ) { FM_OPL *OPL = OPL_Y8950[which]; - OPL->deltat->memory = (UINT8 *)(deltat_rom); - OPL->deltat->memory_size = deltat_rom_size; + OPL->deltat->memory = (UINT8 *)(deltat_mem_ptr); + OPL->deltat->memory_size = deltat_mem_size; } /* @@ -2331,9 +2434,6 @@ void Y8950UpdateOne(int which, INT16 *buffer, int length) YM_DELTAT *DELTAT = OPL->deltat; OPLSAMPLE *buf = buffer; - /* setup DELTA-T unit */ - YM_DELTAT_DECODE_PRESET(DELTAT); - if( (void *)OPL != cur_chip ){ cur_chip = (void *)OPL; /* rhythm slots */ @@ -2353,7 +2453,7 @@ void Y8950UpdateOne(int which, INT16 *buffer, int length) advance_lfo(OPL); /* deltaT ADPCM */ - if( DELTAT->portstate ) + if( DELTAT->portstate&0x80 ) YM_DELTAT_ADPCM_CALC(DELTAT); /* FM part */ @@ -2383,7 +2483,10 @@ void Y8950UpdateOne(int which, INT16 *buffer, int length) lt = limit( lt , MAXOUT, MINOUT ); #ifdef SAVE_SAMPLE + if (which==0) + { SAVE_ALL_CHANNELS + } #endif /* store to sound buffer */ @@ -2392,15 +2495,6 @@ void Y8950UpdateOne(int which, INT16 *buffer, int length) 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; - } } void Y8950SetPortHandler(int which,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param) diff --git a/src/hardware/fmopl.h b/src/hardware/fmopl.h index 4ba2b6b..5a605fc 100644 --- a/src/hardware/fmopl.h +++ b/src/hardware/fmopl.h @@ -91,7 +91,7 @@ void YM3526SetUpdateHandler(int which, OPL_UPDATEHANDLER UpdateHandler, int para /* 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_rom, int deltat_rom_size ); +void Y8950SetDeltaTMemory(int which, void * deltat_mem_ptr, int deltat_mem_size ); int Y8950Init (int num, int clock, int rate); void Y8950Shutdown (void); diff --git a/src/hardware/font-switch.h b/src/hardware/font-switch.h deleted file mode 100644 index 80a3adf..0000000 --- a/src/hardware/font-switch.h +++ /dev/null @@ -1,2562 +0,0 @@ -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 f877bf4..5ef52c7 100644 --- a/src/hardware/gameblaster.cpp +++ b/src/hardware/gameblaster.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -131,7 +131,7 @@ static int amplitude_lookup[16] = { /* global parameters */ static double sample_rate; static SAA1099 saa1099[2]; -static MIXER_Channel * cms_chan; +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] }; @@ -363,8 +363,8 @@ static void saa1099_write_port_w( int chip, int offset, int data ) } -static void write_cms(Bit32u port,Bit8u val) { - if (last_command + 100 < PIC_Ticks) MIXER_Enable(cms_chan,true); +static void write_cms(Bitu port,Bitu val,Bitu iolen) { + if (last_command + 1000 < PIC_Ticks) cms_chan->Enable(true); last_command = PIC_Ticks; switch (port) { case 0x0220: @@ -383,7 +383,6 @@ static void write_cms(Bit32u port,Bit8u 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); @@ -391,55 +390,49 @@ static void write_cms(Bit32u port,Bit8u val) { } break; } - if (last_command > PIC_Ticks+1000) MIXER_Enable(cms_chan,true); } - static void CMS_CallBack(Bit8u * stream,Bit32u len) { + 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) *(Bit16s *)stream=MAX_AUDIO; - else if (leftMAX_AUDIO) *stream=MAX_AUDIO; + else if (leftMAX_AUDIO) *(Bit16s *)stream=MAX_AUDIO; - else if (rightMAX_AUDIO) *stream=MAX_AUDIO; + else if (rightAddSamples_s16(len,(Bit16s *)MixTemp); + if (last_command + 10000 < PIC_Ticks) cms_chan->Enable(false); } -void CMS_Init(Section* sec) { + void CMS_Init(Section* sec,Bitu base,Bitu rate) { Section_prop * section=static_cast(sec); - if(!section->Get_bool("cms")) return; - sample_rate=section->Get_int("cmsrate"); + sample_rate=rate; - IO_RegisterWriteHandler(0x220,write_cms,"CMS"); - IO_RegisterWriteHandler(0x221,write_cms,"CMS"); - IO_RegisterWriteHandler(0x222,write_cms,"CMS"); - IO_RegisterWriteHandler(0x223,write_cms,"CMS"); + IO_RegisterWriteHandler(base,write_cms,IO_MB,4); /* Register the Mixer CallBack */ - cms_chan=MIXER_AddChannel(CMS_CallBack,CMS_RATE,"CMS"); - MIXER_SetMode(cms_chan,MIXER_16STEREO); - MIXER_Enable(cms_chan,true); + cms_chan=MIXER_AddChannel(CMS_CallBack,rate,"CMS"); last_command=PIC_Ticks; for (int s=0;s<2;s++) { struct SAA1099 *saa = &saa1099[s]; - memset(saa, 0, sizeof(struct SAA1099)); } } diff --git a/src/hardware/gus.cpp b/src/hardware/gus.cpp index b5a1e51..5da7390 100644 --- a/src/hardware/gus.cpp +++ b/src/hardware/gus.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -22,27 +22,42 @@ #include "mixer.h" #include "dma.h" #include "pic.h" -#include "hardware.h" #include "setup.h" #include "programs.h" #include "math.h" #include "regs.h" +//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 USEVOLTABLE 1 #define GUS_BASE myGUS.portbase #define GUS_RATE myGUS.rate #define LOG_GUS -static MIXER_Channel * gus_chan; - -static Bit16u vol8bit[256]; -static Bit16s vol16bit[4096]; - +Bit8u adlib_commandreg; +static MixerChannel * gus_chan; static Bit8u irqtable[8] = { 0, 2, 5, 3, 7, 11, 12, 15 }; - -static Bit8u dmatable[6] = { 3, 1, 5, 5, 6, 7 }; - +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; +#if USEVOLTABLE +static Bit16u vol16bit[4096]; +#endif +static Bit32u pantable[16]; + +static Bitu show_test=0; +class GUSChannels; +static void CheckVoiceIrq(void); struct GFGus { Bit8u gRegSelect; @@ -55,22 +70,17 @@ struct GFGus { Bit8u TimerControl; Bit8u SampControl; Bit8u mixControl; - + Bit8u ActiveChannels; Bit32u basefreq; - Bit16u activechan; - Bit32s mupersamp; - Bit32s muperchan; - - Bit16u timerReg; struct GusTimer { - Bit16u bytetimer; - Bit32s countdown; - Bit32s setting; - bool active; + Bit8u value; + bool reached; + bool raiseirq; + bool masked; + bool running; + float delay; } timers[2]; - - Bit32u rate; Bit16u portbase; Bit16u dma1; @@ -80,475 +90,331 @@ struct GFGus { Bit16u irq2; char ultradir[512]; - bool irqenabled; - + bool ChangeIRQDMA; // IRQ status register values - struct IRQStat { - bool MIDITx; - bool MIDIRx; - bool T1; - bool T2; - bool Resv; - bool WaveTable; - bool VolRamp; - bool DMATC; - } irq; - + Bit8u IRQStatus; + Bit32u ActiveMask; + Bit8u IRQChan; + Bit32u RampIRQ; + Bit32u WaveIRQ; } myGUS; -#define GUSFIFOSIZE 1024 - -static void UseDMA(DmaChannel *useDMA); - -struct IRQFifoEntry { - Bit8u channum; - bool WaveIRQ; - bool RampIRQ; -}; - -struct IRQFifoDef { - IRQFifoEntry entry[GUSFIFOSIZE]; - Bit16s stackpos; -} IRQFifo; - - -// Routines to manage IRQ requests coming from the GUS -static void pushIRQ(Bit8u channum, bool WaveIRQ, bool RampIRQ) { - IRQFifo.stackpos++; - if(IRQFifo.stackpos < GUSFIFOSIZE) { - myGUS.irq.WaveTable = WaveIRQ; - myGUS.irq.VolRamp = RampIRQ; - - IRQFifo.entry[IRQFifo.stackpos].channum = channum; - IRQFifo.entry[IRQFifo.stackpos].RampIRQ = RampIRQ; - IRQFifo.entry[IRQFifo.stackpos].WaveIRQ = WaveIRQ; - - - - } else { - LOG_GUS("GUS IRQ Fifo full!"); - } -} - -static void popIRQ(IRQFifoEntry * tmpentry) { - if(IRQFifo.stackpos<0) { - tmpentry->channum = 0; - tmpentry->RampIRQ = false; - tmpentry->WaveIRQ = false; - return; - } - memcpy(tmpentry, &IRQFifo.entry[IRQFifo.stackpos], sizeof(IRQFifoEntry)); - --IRQFifo.stackpos; - if(IRQFifo.stackpos >= 0) { - myGUS.irq.WaveTable = IRQFifo.entry[IRQFifo.stackpos].WaveIRQ; - myGUS.irq.VolRamp = IRQFifo.entry[IRQFifo.stackpos].RampIRQ; - } else { - myGUS.irq.WaveTable = false; - myGUS.irq.VolRamp = false; - } -} +Bitu DEBUG_EnableDebugger(void); +static void GUS_DMA_Callback(DmaChannel * chan,DMAEvent event); // Returns a single 16-bit sample from the Gravis's RAM -INLINE Bit16s GetSample(Bit32u Delta, Bit32u CurAddr, bool eightbit) { +static INLINE Bit32s GetSample(Bit32u Delta, Bit32u CurAddr, bool eightbit) { Bit32u useAddr; Bit32u holdAddr; - useAddr = CurAddr >> 9; - if(eightbit) { - if(Delta >= 1024) { - Bit8s tmpsmall = (Bit8s)GUSRam[useAddr]; - return (Bit16s)(tmpsmall << 7); + useAddr = CurAddr >> WAVE_FRACT; + if (eightbit) { + if (Delta >= (1 << WAVE_FRACT)) { + Bit32s tmpsmall = (Bit8s)GUSRam[useAddr]; + return tmpsmall << 8; } else { - // Interpolate - Bit8s b1 = (Bit8s)GUSRam[useAddr]; - Bit8s b2 = (Bit8s)GUSRam[useAddr+1]; - Bit16s w1 = b1 << 7; - Bit16s w2 = b2 << 7; - Bit16s diff = w2 - w1; - return (Bit16s)(w1 + (((Bit32s)diff * (Bit32s)(CurAddr & 0x3fe)) >> 10)); - + 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 >= 1024) { - - return (Bit16s)((Bit16u)GUSRam[useAddr] | ((Bit16u)GUSRam[useAddr+1] << 8)) >> 2 - ; - + if(Delta >= (1 << WAVE_FRACT)) { + return (GUSRam[useAddr+0] | (((Bit8s)GUSRam[useAddr+1]) << 8)); } else { - // Interpolate - Bit16s w1 = (Bit16s)((Bit16u)GUSRam[useAddr] | ((Bit16u)GUSRam[useAddr+1] << 8)); - Bit16s w2 = (Bit16s)((Bit16u)GUSRam[useAddr+2] | ((Bit16u)GUSRam[useAddr+3] << 8)); - Bit16s diff = w2 - w1; - return (Bit16s)(w1 + (((Bit32s)diff * (Bit32s)((CurAddr) & 0x3fe)) >> 10)) >> 2; - + 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: - Bit8u voiceCont; - Bit16u FreqCont; - Bit32u RealDelta; - Bit32u StartAddr; - Bit32u EndAddr; - Bit8s VolRampRate; - Bit16s VolRampStart; - Bit16s VolRampEnd; - Bit8u VolRampStartOrg; - Bit8u VolRampEndOrg; - Bit32s CurVolume; - Bit32u CurAddr; + 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 VolControl; Bit8u channum; - - bool moving; - bool playing; - bool ramping; - bool dir; - bool voldir; - -public: - bool notifyonce; - Bit32s leftvol; - Bit32s rightvol; - Bit32s nextramp; + Bit32u irqmask; + Bit32u PanLeft; + Bit32u PanRight; + Bit32s VolLeft; + Bit32s VolRight; GUSChannels(Bit8u num) { channum = num; - playing = true; - ramping = false; - moving = false; - dir = false; - voldir = false; - StartAddr = 0; - EndAddr = 0; - CurAddr = 0; - VolRampRate = 0; - VolRampStart = 0; - VolRampEnd = 0; - leftvol = 255; - rightvol = 255; - nextramp = 0; - + 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; }; - - // Voice control register - void WriteVoiceCtrl(Bit8u val) { - voiceCont = val; - if (val & 0x3) moving = false; - if ((val & 0x3) == 0) { - //playing = true; - moving = true; - } - dir = false; - if((val & 0x40) !=0) dir = true; - + 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; } - Bit8u ReadVoiceCtrl(void) { - Bit8u tmpval = voiceCont & 0xfe; - if(!playing) tmpval++; - return tmpval; + 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(); } - - // Frequency control register - void WriteFreqCtrl(Bit16u val) { - FreqCont = val; - int fc; - fc = val; - fc = fc >> 1; - fc = fc * myGUS.basefreq; - fc = fc - (myGUS.basefreq >> 1); - fc = fc / 512; - float simple; - - simple = ((float)fc / (float)GUS_RATE) * 512; - RealDelta = (Bit32u)simple; + INLINE Bit8u ReadWaveCtrl(void) { + Bit8u ret=WaveCtrl; + if (myGUS.WaveIRQ & irqmask) ret|=0x80; + return ret; } - Bit16u ReadFreqCtrl(void) { - return FreqCont; + void UpdateWaveRamp(void) { + WriteWaveFreq(WaveFreq); + WriteRampRate(RampRate); } - - // Used when GUS changes channel numbers during playback - void UpdateFreqCtrl() { WriteFreqCtrl(FreqCont); } - - // Pan position register void WritePanPot(Bit8u val) { - if(val<8) { - leftvol = 255; - rightvol = val << 5; - } else { - rightvol = 255; - leftvol = (8-(val-8)) << 5; - } PanPot = val; + PanLeft = pantable[0x0f-(val & 0xf)]; + PanRight = pantable[(val & 0xf)]; + UpdateVolumes(); } Bit8u ReadPanPot(void) { return PanPot; } - - // Volume ramping control register - void WriteVolControl(Bit8u val) { - VolControl = val; - if (val & 0x3) ramping = false; - if ((val & 0x3) == 0) ramping = true; - voldir = false; - if((val & 0x40) !=0) voldir = true; - + 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(); } - Bit8u ReadVolControl(void) { - Bit8u tmpval = VolControl & 0xfe; - if(!ramping) tmpval++; - return tmpval; + INLINE Bit8u ReadRampCtrl(void) { + Bit8u ret=RampCtrl; + if (myGUS.RampIRQ & irqmask) ret|=0x80; + return ret; } - - - // Methods to queue IRQ on ramp or sample end - void NotifyEndSamp(void) { - if(!notifyonce) { - if((voiceCont & 0x20) != 0) { - pushIRQ(channum,true,false); - notifyonce = true; - } + 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; + } + void ShowWave(void) { + LOG_GUS("Wave %2d Ctrl %02x Current %d Start %d End %d Add %3.3f ", + channum, + ReadWaveCtrl(), + WaveAddr>>WAVE_FRACT, + WaveStart>>WAVE_FRACT, + WaveEnd>>WAVE_FRACT, + (float)WaveAdd/(float)(1 << WAVE_FRACT) + ); + } + void ShowRamp(void) { + LOG_GUS("Ramp %2d Ctrl %02X Current %d Start %d End %d Add %d", + channum, + ReadRampCtrl(), + RampVol >> RAMP_FRACT, + RampStart >> RAMP_FRACT, + RampEnd >> RAMP_FRACT, + RampAdd >> RAMP_FRACT + ); + } + 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; } } - void NotifyEndRamp(void) { - if(!notifyonce) { - if((VolControl & 0x20) != 0) { - pushIRQ(channum,false,true); - notifyonce = true; - } + INLINE void UpdateVolumes(void) { + Bit32s templeft=RampVol - PanLeft; + templeft&=~(templeft >> 31); + Bit32s tempright=RampVol - PanRight; + tempright&=~(tempright >> 31); +#if USEVOLTABLE + VolLeft=vol16bit[templeft >> RAMP_FRACT]; + VolRight=vol16bit[tempright >> RAMP_FRACT]; +#else + +#endif + } + 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(); } - - // Debug routine to show current channel position - void ShowAddr(void) { - LOG_GUS("Chan %d Start %d End %d Current %d", channum, StartAddr>>9, EndAddr>>9, CurAddr>>9); - } - - - // Generate the samples required by the callback routine - // It should be noted that unless a channel is stopped, it will - // continue to return the sample it is pointing to, regardless - // of whether or not the channel is moving or ramping. - void generateSamples(Bit16s * stream,Bit32u len) { + void generateSamples(Bit32s * stream,Bit32u len) { int i; - Bit16s tmpsamp; + Bit32s tmpsamp; bool eightbit; - eightbit = ((voiceCont & 0x4) == 0); - - notifyonce = false; - + if (RampCtrl & WaveCtrl & 3) return; + eightbit = ((WaveCtrl & 0x4) == 0); +#if 0 + if (!(show_test & 1023)) { + ShowWave(); + ShowRamp(); + } +#endif for(i=0;i<(int)len;i++) { // Get sample - tmpsamp = GetSample(RealDelta, CurAddr, eightbit); - - // Clip and convert log scale to PCM scale - if(CurVolume>4095) CurVolume = 4095; - if(CurVolume<0) CurVolume = 0; - tmpsamp = (tmpsamp * vol16bit[CurVolume]) >> 12; - + tmpsamp = GetSample(WaveAdd, WaveAddr, eightbit); // Output stereo sample - stream[i<<1] = (Bit16s)(((Bit32s)tmpsamp * (Bit32s)leftvol)>>8) ; - stream[(i<<1)+1] = (Bit16s)(((Bit32s)tmpsamp * rightvol)>>8); - - - if(dir) { - // Increment backwards - if (moving) CurAddr -= RealDelta; - - //Thought 16-bit needed this - //if ((!eightbit) && (moving)) CurAddr -= RealDelta; - - if(CurAddr <= StartAddr) { - if((VolControl & 0x4) == 0) { - if((voiceCont & 0x8) != 0) { - if((voiceCont & 0x10) != 0) { - dir = !dir; - } else { - CurAddr = EndAddr; - } - - } else { - moving = false; - } - NotifyEndSamp(); - } else { - NotifyEndSamp(); - - } - - } - - } else { - - // Increment forwards - if (moving) CurAddr += RealDelta; - - //Thought 16-bit needed this - //if ((!eightbit) && (moving)) CurAddr += RealDelta; - if(CurAddr >= EndAddr) { - if((VolControl & 0x4) == 0) { - if((voiceCont & 0x8) != 0) { - if((voiceCont & 0x10) != 0) { - dir = !dir; - } else { - CurAddr = StartAddr; - } - - } else { - moving = false; - } - NotifyEndSamp(); - } else { - NotifyEndSamp(); - } - } - } - - // Update volume - if(ramping) { - - // Subtract ramp counter by elapsed microseconds - nextramp -= myGUS.mupersamp; - bool flagged; - flagged = false; - - // Ramp volume until nextramp is a positive integer - while(nextramp <= 0) { - if(voldir) { - CurVolume -= (VolRampRate & 0x3f); - if (CurVolume <= 0) { - CurVolume = 0; - flagged = true; - } - - if((vol16bit[CurVolume]<=VolRampStart) || (flagged)){ - if((VolControl & 0x8) != 0) { - if((VolControl & 0x10) != 0) { - voldir = !voldir; - } else { - CurVolume = VolRampEndOrg; - } - } else { - ramping = false; - } - NotifyEndRamp(); - } - - } else { - CurVolume += (VolRampRate & 0x3f); - if (CurVolume >= 4095) { - CurVolume = 4095; - flagged = true; - } - - if((vol16bit[CurVolume]>=VolRampEnd) || (flagged)){ - if((VolControl & 0x8) != 0) { - if((VolControl & 0x10) != 0) { - voldir = !voldir; - } else { - CurVolume = VolRampStartOrg; - } - } else { - ramping = false; - } - NotifyEndRamp(); - } - - } - - - switch(VolRampRate >> 6) { - case 0: - nextramp += myGUS.muperchan; - break; - case 1: - nextramp += myGUS.muperchan* 8; - break; - case 2: - nextramp += myGUS.muperchan * 64; - break; - case 3: - nextramp += myGUS.muperchan * 512; - break; - default: - nextramp += myGUS.muperchan * 512; - break; - - } - - } - - } - - + stream[i<<1]+= tmpsamp * VolLeft; + stream[(i<<1)+1]+= tmpsamp * VolRight; + WaveUpdate(); + RampUpdate(); } - - } - - }; +static GUSChannels *guschan[32]; +static GUSChannels *curchan; -GUSChannels *guschan[33]; - -GUSChannels *curchan; - - -static void GUSReset(void) -{ +static void GUSReset(void) { if((myGUS.gRegData & 0x1) == 0x1) { // Reset - myGUS.timerReg = 85; - memset(&myGUS.irq, 0, sizeof(myGUS.irq)); + 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) { + if ((myGUS.gRegData & 0x4) != 0) { myGUS.irqenabled = true; } else { myGUS.irqenabled = false; } +} - myGUS.timers[0].active = false; - myGUS.timers[1].active = false; - myGUS.timers[0].bytetimer = 0x0; - myGUS.timers[1].bytetimer = 0x0; - - // Stop all channels - int i; - for(i=0;i<32;i++) { - guschan[i]->WriteVoiceCtrl(0x3); - - } - IRQFifo.stackpos = -1; +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(); + while (1) { + 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; - if(myGUS.irq.DMATC) tmpreg |= 0x40; - - myGUS.irq.DMATC = false; - PIC_DeActivateIRQ(myGUS.irq1); - + tmpreg |= (myGUS.IRQStatus & 0x80) >> 1; + myGUS.IRQStatus&=0x7f; return (Bit16u)(tmpreg << 8); case 0x42: // Dma address register return myGUS.dmaAddr; @@ -557,212 +423,182 @@ static Bit16u ExecuteReadRegister(void) { break; case 0x49: // Dma sample register tmpreg = myGUS.DMAControl & 0xbf; - if(myGUS.irq.DMATC) tmpreg |= 0x40; - - myGUS.irq.DMATC = false; - PIC_DeActivateIRQ(myGUS.irq1); - //LOG_MSG("Read sampling status, returned 0x%x", tmpreg); - + tmpreg |= (myGUS.IRQStatus & 0x80) >> 1; return (Bit16u)(tmpreg << 8); case 0x80: // Channel voice control read register - if(curchan != NULL) { - Bit8u sndout; - sndout = curchan->voiceCont & 0xFC; - if(!curchan->moving) sndout |= 0x3; + if (curchan) return curchan->ReadWaveCtrl() << 8; + else return 0x0300; - return (Bit16u)(sndout<< 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 0x82: // Channel MSB address register - if(curchan != NULL) { - return (curchan->StartAddr >> 16); - } else return 0x0000; - case 0x83: // Channel LSW address register - if(curchan != NULL) { - return (curchan->StartAddr & 0xffff); - } else return 0x0000; case 0x89: // Channel volume register - if(curchan != NULL) { - return (curchan->CurVolume << 4); - } else return 0x0000; + if (curchan) return (Bit16u)((curchan->RampVol >> RAMP_FRACT) << 4); + else return 0x0000; case 0x8a: // Channel MSB current address register - if(curchan != NULL) { - return (curchan->CurAddr >> 16); - } else return 0x0000; - + if (curchan) return (Bit16u)(curchan->WaveAddr >> (WAVE_BITS+16)); + else return 0x0000; case 0x8b: // Channel LSW current address register - if(curchan != NULL) { - return (curchan->CurAddr & 0xFFFF); - } else return 0x0000; + if (curchan) return (Bit16u)(curchan->WaveAddr >> WAVE_BITS); + else return 0x0000; + case 0x8d: // Channel volume control register - if(curchan != NULL) { - Bit8u volout; - volout = curchan->VolControl & 0xFC; - if(!curchan->ramping) volout |= 0x3; - return (volout << 8); - } else return 0x0300; - + if (curchan) return curchan->ReadRampCtrl() << 8; + else return 0x0300; case 0x8f: // General channel IRQ status register - Bit8u temp; - temp = 0x20; - IRQFifoEntry tmpentry; - PIC_DeActivateIRQ(myGUS.irq1); - popIRQ(&tmpentry); - if(!tmpentry.WaveIRQ) temp |= 0x80; - if(!tmpentry.RampIRQ) temp |= 0x40; - temp |= tmpentry.channum; - - return (Bit16u)(temp << 8); + 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: LOG_GUS("Read Register num 0x%x", myGUS.gRegSelect); 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; - //LOG_MSG("Access global register %x with %x", myGUS.gRegSelect, myGUS.gRegData); +// 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 != NULL) { - curchan->WriteVoiceCtrl((Bit8u)myGUS.gRegData); - } + if(curchan) curchan->WriteWaveCtrl((Bit16u)myGUS.gRegData>>8); break; case 0x1: // Channel frequency control register - if(curchan != NULL) { - curchan->WriteFreqCtrl(myGUS.gRegData); + 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 0x2: // Channel MSB start address register + case 0x3: // Channel LSW start address register if(curchan != NULL) { - Bit32u tmpaddr = myGUS.gRegData << 16; - curchan->StartAddr = (curchan->StartAddr & 0xFFFF) | tmpaddr; + Bit32u tmpaddr = (Bit32u)(myGUS.gRegData) << WAVE_BITS; + curchan->WaveStart = (curchan->WaveStart & WAVE_LSWMASK) | tmpaddr; } break; - case 0x3: // Channel LSB start address register + case 0x4: // Channel MSW end address register if(curchan != NULL) { - Bit32u tmpaddr = (Bit32u)(myGUS.gRegData); - curchan->StartAddr = (curchan->StartAddr & 0x1FFF0000) | tmpaddr; + Bit32u tmpaddr = (Bit32u)(myGUS.gRegData & 0x1fff) << (16+WAVE_BITS); + curchan->WaveEnd = (curchan->WaveEnd & WAVE_MSWMASK) | tmpaddr; } break; - case 0x4: // Channel MSB end address register + case 0x5: // Channel MSW end address register if(curchan != NULL) { - Bit32u tmpaddr = (Bit32u)myGUS.gRegData << 16; - curchan->EndAddr = (curchan->EndAddr & 0xFFFF) | tmpaddr; - } - break; - case 0x5: // Channel MSB end address register - if(curchan != NULL) { - Bit32u tmpaddr = (Bit32u)(myGUS.gRegData); - curchan->EndAddr = (curchan->EndAddr & 0x1FFF0000) | tmpaddr; + 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 = (Bit8u)myGUS.gRegData; - curchan->VolRampRate = tmpdata; + Bit8u tmpdata = (Bit16u)myGUS.gRegData>>8; + curchan->WriteRampRate(tmpdata); } break; case 0x7: // Channel volume ramp start register EEEEMMMM if(curchan != NULL) { - Bit8u tmpdata = (Bit8u)myGUS.gRegData; - curchan->VolRampStart = vol8bit[tmpdata]; - curchan->VolRampStartOrg = tmpdata << 4; + 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 = (Bit8u)myGUS.gRegData; - curchan->VolRampEnd = vol8bit[tmpdata]; - curchan->VolRampEndOrg = tmpdata << 4; + 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->CurVolume = tmpdata; + curchan->RampVol = tmpdata << RAMP_FRACT; + curchan->UpdateVolumes(); } break; - case 0xA: // Channel MSB current address register + case 0xA: // Channel MSW current address register if(curchan != NULL) { - curchan->CurAddr = (curchan->CurAddr & 0xFFFF) | ((Bit32u)myGUS.gRegData << 16); + 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) { - curchan->CurAddr = (curchan->CurAddr & 0xFFFF0000) | ((Bit32u)myGUS.gRegData); + Bit32u tmpaddr = (Bit32u)(myGUS.gRegData) << (WAVE_BITS); + curchan->WaveAddr = (curchan->WaveAddr & WAVE_LSWMASK) | tmpaddr; } break; case 0xC: // Channel pan pot register - if(curchan != NULL) { - curchan->WritePanPot((Bit8u)myGUS.gRegData); - } + if(curchan) curchan->WritePanPot((Bit16u)myGUS.gRegData>>8); break; case 0xD: // Channel volume control register - if(curchan != NULL) { - curchan->WriteVolControl((Bit8u)myGUS.gRegData); - } + if(curchan) curchan->WriteRampCtrl((Bit16u)myGUS.gRegData>>8); break; case 0xE: // Set active channel register - myGUS.activechan = (myGUS.gRegData & 31) +1; - if(myGUS.activechan < 14) myGUS.activechan = 14; - if(myGUS.activechan > 32) myGUS.activechan = 32; - MIXER_Enable(gus_chan,true); - myGUS.basefreq = (Bit32u)((float)1000000/(1.619695497*(float)myGUS.activechan)); - - float simple; - simple = (1.0 / (float)GUS_RATE) / 0.000001; - myGUS.mupersamp = (Bit32s)simple*1024; - myGUS.muperchan = (Bit32s)((float)1.6 * (float)myGUS.activechan * 1024); - LOG_GUS("GUS set to %d channels", myGUS.activechan); - - for(i=0;iUpdateFreqCtrl(); } - + 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))); + LOG_GUS("GUS set to %d channels", myGUS.ActiveChannels); + 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; - if ((myGUS.DMAControl & 0x1) != 0) { - //LOG_MSG("GUS request DMA transfer"); - if(DmaChannels[myGUS.dma1]->enabled) UseDMA(DmaChannels[myGUS.dma1]); - } + myGUS.DMAControl = (Bit8u)(myGUS.gRegData>>8); + DmaChannels[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) << 16; + 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; - if((myGUS.TimerControl & 0x08) !=0) myGUS.timers[1].countdown = myGUS.timers[1].setting; - if((myGUS.TimerControl & 0x04) !=0) myGUS.timers[0].countdown = myGUS.timers[0].setting; - myGUS.irq.T1 = false; - myGUS.irq.T2 = false; - PIC_DeActivateIRQ(myGUS.irq1); + 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].bytetimer = (Bit8u)myGUS.gRegData; - myGUS.timers[0].setting = ((Bit32s)0xff - (Bit32s)myGUS.timers[0].bytetimer) * ((Bit32s)80 << 10); - myGUS.timers[0].countdown = myGUS.timers[0].setting; + 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].bytetimer = (Bit8u)myGUS.gRegData; - myGUS.timers[1].setting = ((Bit32s)0xff - (Bit32s)myGUS.timers[1].bytetimer) * ((Bit32s)360 << 10); - myGUS.timers[1].countdown = myGUS.timers[1].setting; + 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; - if ((myGUS.SampControl & 0x1) != 0) { - if(DmaChannels[myGUS.dma1]->enabled) UseDMA(DmaChannels[myGUS.dma1]); - } + myGUS.SampControl = (Bit8u)(myGUS.gRegData>>8); + DmaChannels[myGUS.dma1]->Register_Callback( + (myGUS.SampControl & 0x1) ? GUS_DMA_Callback : 0); break; case 0x4c: // GUS reset register GUSReset(); @@ -774,49 +610,29 @@ static void ExecuteGlobRegister(void) { } -static Bit16u read_gus16(Bit32u port) { - - return ExecuteReadRegister(); -} - -static void write_gus16(Bit32u port,Bit16u val) { - myGUS.gRegData = val; - ExecuteGlobRegister(); -} - - -static Bit8u read_gus(Bit32u port) { - +static Bitu read_gus(Bitu port,Bitu iolen) { +// LOG_MSG("read from gus port %x",port); switch(port - GUS_BASE) { case 0x206: - Bit8u temp; - temp = 0; - if(myGUS.irq.MIDITx) temp |= 1; - if(myGUS.irq.MIDIRx) temp |= 2; - if(myGUS.irq.T1) temp |= 4; - if(myGUS.irq.T2) temp |= 8; - if(myGUS.irq.Resv) temp |= 16; - if(myGUS.irq.WaveTable) temp |= 32; - if(myGUS.irq.VolRamp) temp |= 64; - if(myGUS.irq.DMATC) temp |= 128; - PIC_DeActivateIRQ(myGUS.irq1); - return temp; + return myGUS.IRQStatus; case 0x208: Bit8u tmptime; tmptime = 0; - - if(myGUS.irq.T1) tmptime |= (1 << 6); - if(myGUS.irq.T2) tmptime |= (1 << 5); - if((myGUS.irq.T1) || (myGUS.irq.T2)) tmptime |= (1 << 7); + 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 myGUS.timerReg; + return adlib_commandreg; case 0x302: return (Bit8u)myGUS.gCurChannel; case 0x303: return myGUS.gRegSelect; case 0x304: - return ExecuteReadRegister() & 0xff; + if (iolen==2) return ExecuteReadRegister() & 0xffff; + else return ExecuteReadRegister() & 0xff; case 0x305: return ExecuteReadRegister() >> 8; case 0x307: @@ -834,56 +650,70 @@ static Bit8u read_gus(Bit32u port) { } -static void write_gus(Bit32u port,Bit8u val) { - +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; - break; + myGUS.ChangeIRQDMA = true; + return; case 0x208: - myGUS.timerReg = val; + adlib_commandreg = val; break; case 0x209: - myGUS.timers[0].active = ((val & 0x1) > 0); - myGUS.timers[1].active = ((val & 0x2) > 0); - - break; - case 0x20b: - if((myGUS.mixControl & 0x40) != 0) { - // IRQ configuration - Bit8u temp = val & 0x7; // Select GF1 irq - if(myGUS.irq1 == irqtable[temp]) { - } else { - LOG_GUS("Attempt to assign GUS to wrong IRQ - at %x set to %x", myGUS.irq1, irqtable[temp]); - } - } else { - // DMA configuration - Bit8u temp = val & 0x7; // Select playback IRQ - if(myGUS.dma1 == dmatable[temp]) { - } else { - LOG_GUS("Attempt to assign GUS to wrong DMA - at %x, assigned %x", myGUS.dma1, dmatable[temp]); - } +//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]; + LOG_GUS("Assigned GUS to IRQ %d", myGUS.irq1); + } else { + // DMA configuration, only use low bits for dma 1 + if (dmatable[val & 0x7]) myGUS.dma1=dmatable[val & 0x7]; + LOG_GUS("Assigned GUS to DMA %d", myGUS.dma1); } - break; case 0x302: - myGUS.gCurChannel = val ; - if (myGUS.gCurChannel > 32) myGUS.gCurChannel = 32; - curchan = guschan[val]; + 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 0x305: - myGUS.gRegData = (0xff00 & myGUS.gRegData) | val; - ExecuteGlobRegister(); - break; - case 0x307: if(myGUS.gDramAddr < sizeof(GUSRam)) GUSRam[myGUS.gDramAddr] = val; break; @@ -891,146 +721,84 @@ static void write_gus(Bit32u port,Bit8u val) { LOG_GUS("Write GUS at port 0x%x with %x", port, val); break; } - - } -static void UseDMA(DmaChannel *useDMA) { - Bit32s dmaaddr = myGUS.dmaAddr << 4; +static void GUS_DMA_Callback(DmaChannel * chan,DMAEvent event) { + if (event!=DMA_UNMASKED) return; + Bitu dmaaddr = myGUS.dmaAddr << 4; if((myGUS.DMAControl & 0x2) == 0) { - //Write data into UltraSound - Bit32s comsize = useDMA->currcnt; - - useDMA->Read(useDMA->currcnt,&GUSRam[dmaaddr]); + 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 - - int i; + Bitu i; if((myGUS.DMAControl & 0x40) == 0) { // 8-bit data - for(i=dmaaddr;i<(dmaaddr+comsize);i++) GUSRam[i] ^= 0x80; + for(i=dmaaddr;i<(dmaaddr+read);i++) GUSRam[i] ^= 0x80; } else { // 16-bit data - for(i=dmaaddr+1;i<(dmaaddr+comsize-1);i+=2) GUSRam[i] ^= 0x80; + for(i=dmaaddr+1;i<(dmaaddr+read-1);i+=2) GUSRam[i] ^= 0x80; } } } else { //Read data out of UltraSound - useDMA->Write(useDMA->currcnt,&GUSRam[dmaaddr]); - + 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_DMA_Callback(void *useChannel, bool tc) { - DmaChannel *myDMA; - myDMA = (DmaChannel *)useChannel; - - if(tc) { - if((myGUS.DMAControl & 0x20) != 0) { - myGUS.irq.DMATC = true; - PIC_ActivateIRQ(myGUS.irq2); +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--; } - } else { - if ((myGUS.DMAControl & 0x1) != 0) UseDMA(myDMA); + buf16[i] = (Bit16s)(sample); } - - + gus_chan->AddSamples_s16(len,buf16); + CheckVoiceIrq(); } -static void GUS_CallBack(Bit8u * stream,Bit32u len) { - - Bit16s *bufptr; - Bit16s buffer[4096]; - Bit32s tmpbuf[4096]; - - memset(&buffer[0],0,len*4); - memset(&tmpbuf[0],0,len*8); - - int i,t; - for(i=0;iplaying) { - guschan[i]->generateSamples(&buffer[0],len); - - for(t=0;t= 0) { - PIC_ActivateIRQ(myGUS.irq1); - } - } - - if(myGUS.timers[0].active) { - myGUS.timers[0].countdown-=(len * (Bit32u)myGUS.mupersamp); - if(!myGUS.irq.T1) { - // Expire Timer 1 - if(myGUS.timers[0].countdown < 0) { - if((myGUS.TimerControl & 0x04) !=0) { - PIC_ActivateIRQ(myGUS.irq1); - } - myGUS.irq.T1 = true; - //LOG_MSG("T1 timer expire"); - //myGUS.timers[0].countdown = myGUS.timers[0].setting; - } - } - } - if(myGUS.timers[1].active) { - if(!myGUS.irq.T2) { - myGUS.timers[1].countdown-=(len * (Bit32u)myGUS.mupersamp); - // Expire Timer 2 - if(myGUS.timers[1].countdown < 0) { - if((myGUS.TimerControl & 0x08) !=0) { - PIC_ActivateIRQ(myGUS.irq1); - } - myGUS.irq.T2 = true; - } - } - } - - - bufptr = (Bit16s *)stream; - for(i=0;i> 4)); - b = 1.0+((float)(i & 0xf))/(float)16; - a *= b; - a /= 16; - vol8bit[i] = (Bit16u)a; +#if USEVOLTABLE + double out = (double)(1 << 13); + for (i=4095;i>=0;i--) { + vol16bit[i]=(Bit16s)out; + out/=1.002709201; /* 0.0235 dB Steps */ } - for(i=0;i<4096;i++) { - float a,b; - a = pow(2.0f,(float)(i >> 8)); - b = 1.0+((float)(i & 0xff))/(float)256; - a *= b; - a /= 16; - vol16bit[i] = (Bit16u)a; +#endif + 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)); } - - } - void GUS_Init(Section* sec) { + if(machine!=MCH_VGA) return; + Section_prop * section=static_cast(sec); + if(!section->Get_bool("gus")) return; - memset(&myGUS,0,sizeof(myGUS)); memset(GUSRam,0,1024*1024); - Section_prop * section=static_cast(sec); - if(!section->Get_bool("gus")) return; myGUS.rate=section->Get_int("rate"); myGUS.portbase = section->Get_hex("base") - 0x200; @@ -1040,77 +808,55 @@ void GUS_Init(Section* sec) { myGUS.irq2 = section->Get_int("irq2"); strcpy(&myGUS.ultradir[0], section->Get_string("ultradir")); - myGUS.timerReg = 85; - myGUS.timers[0].active = false; - myGUS.timers[1].active = false; - - - memset(&myGUS.irq, 0, sizeof(myGUS.irq)); - IRQFifo.stackpos = -1; - myGUS.irqenabled = false; - // We'll leave the MIDI interface to the MPU-401 - // Ditto for the Joystick - // GF1 Synthesizer - - IO_RegisterWriteHandler(0x302 + GUS_BASE,write_gus,"GF1 Page Register"); - IO_RegisterReadHandler(0x302 + GUS_BASE,read_gus,"GF1 Page Register"); - IO_RegisterWriteHandler(0x303 + GUS_BASE,write_gus,"GF1 Global Register Select"); - IO_RegisterReadHandler(0x303 + GUS_BASE,read_gus,"GF1 Global Register Select"); + IO_RegisterWriteHandler(0x302 + GUS_BASE,write_gus,IO_MB); + IO_RegisterReadHandler(0x302 + GUS_BASE,read_gus,IO_MB); - IO_RegisterWriteHandler(0x304 + GUS_BASE,write_gus,"GF1 Global Data Low Byte"); - IO_RegisterReadHandler(0x304 + GUS_BASE,read_gus,"GF1 Global Data Low Byte"); + IO_RegisterWriteHandler(0x303 + GUS_BASE,write_gus,IO_MB); + IO_RegisterReadHandler(0x303 + GUS_BASE,read_gus,IO_MB); - IO_RegisterWriteWHandler(0x304 + GUS_BASE,write_gus16); - IO_RegisterReadWHandler(0x304 + GUS_BASE,read_gus16); + IO_RegisterWriteHandler(0x304 + GUS_BASE,write_gus,IO_MB|IO_MW); + IO_RegisterReadHandler(0x304 + GUS_BASE,read_gus,IO_MB|IO_MW); - IO_RegisterWriteHandler(0x305 + GUS_BASE,write_gus,"GF1 Global Data High Byte"); - IO_RegisterReadHandler(0x305 + GUS_BASE,read_gus,"GF1 Global Data High Byte"); + IO_RegisterWriteHandler(0x305 + GUS_BASE,write_gus,IO_MB); + IO_RegisterReadHandler(0x305 + GUS_BASE,read_gus,IO_MB); - IO_RegisterReadHandler(0x206 + GUS_BASE,read_gus,"GF1 IRQ Status Register"); + IO_RegisterReadHandler(0x206 + GUS_BASE,read_gus,IO_MB); - IO_RegisterWriteHandler(0x208 + GUS_BASE,write_gus,"Timer Control Reg"); - IO_RegisterReadHandler(0x208 + GUS_BASE,read_gus,"Timer Control Reg"); + IO_RegisterWriteHandler(0x208 + GUS_BASE,write_gus,IO_MB); + IO_RegisterReadHandler(0x208 + GUS_BASE,read_gus,IO_MB); - IO_RegisterWriteHandler(0x209 + GUS_BASE,write_gus,"Timer Data IO"); + IO_RegisterWriteHandler(0x209 + GUS_BASE,write_gus,IO_MB); - IO_RegisterWriteHandler(0x307 + GUS_BASE,write_gus,"DRAM IO"); - IO_RegisterReadHandler(0x307 + GUS_BASE,read_gus,"DRAM IO"); + IO_RegisterWriteHandler(0x307 + GUS_BASE,write_gus,IO_MB); + IO_RegisterReadHandler(0x307 + GUS_BASE,read_gus,IO_MB); // Board Only - IO_RegisterWriteHandler(0x200 + GUS_BASE,write_gus,"Mix Control Register"); - IO_RegisterReadHandler(0x20A + GUS_BASE,read_gus,"GUS Undocumented"); - IO_RegisterWriteHandler(0x20B + GUS_BASE,write_gus,"IRQ/DMA Control Register"); + IO_RegisterWriteHandler(0x200 + GUS_BASE,write_gus,IO_MB); + IO_RegisterReadHandler(0x20A + GUS_BASE,read_gus,IO_MB); + IO_RegisterWriteHandler(0x20B + GUS_BASE,write_gus,IO_MB); - PIC_RegisterIRQ(myGUS.irq1,0,"GUS"); - PIC_RegisterIRQ(myGUS.irq2,0,"GUS"); - - DmaChannels[myGUS.dma1]->RegisterCallback(GUS_DMA_Callback); +// DmaChannels[myGUS.dma1]->Register_TC_Callback(GUS_DMA_TC_Callback); MakeTables(); int i; - for(i=0;i<=32;i++) { + for(i=0;i<32;i++) { guschan[i] = new GUSChannels(i); } - // Register the Mixer CallBack - gus_chan=MIXER_AddChannel(GUS_CallBack,GUS_RATE,"GUS"); - MIXER_SetMode(gus_chan,MIXER_16STEREO); - MIXER_Enable(gus_chan,false); - + myGUS.gRegData=0x1; + GUSReset(); + myGUS.gRegData=0x0; int portat = 0x200+GUS_BASE; // ULTRASND=Port,DMA1,DMA2,IRQ1,IRQ2 SHELL_AddAutoexec("SET ULTRASND=%3X,%d,%d,%d,%d",portat,myGUS.dma1,myGUS.dma2,myGUS.irq1,myGUS.irq2); SHELL_AddAutoexec("SET ULTRADIR=%s", myGUS.ultradir); - - } - diff --git a/src/hardware/hardware.cpp b/src/hardware/hardware.cpp index 017ecc4..39c6bf8 100644 --- a/src/hardware/hardware.cpp +++ b/src/hardware/hardware.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -20,14 +20,55 @@ This could do with a serious revision :) */ +#include #include #include "dosbox.h" -#include "programs.h" #include "hardware.h" #include "setup.h" +#include "support.h" + +static char * capturedir; +extern char * RunningProgram; + +FILE * OpenCaptureFile(const char * type,const char * ext) { + Bitu last=0; + char file_name[CROSS_LEN]; + char file_start[16]; + DIR * dir;struct dirent * dir_ent; + /* Find a filename to open */ + dir=opendir(capturedir); + if (!dir) { + LOG_MSG("Can't open dir %s for capturing %s",capturedir,type); + return 0; + } + strcpy(file_start,RunningProgram); + strcat(file_start,"_"); + while ((dir_ent=readdir(dir))) { + char tempname[CROSS_LEN]; + strcpy(tempname,dir_ent->d_name); + 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; + } + closedir(dir); + sprintf(file_name,"%s%c%s%03d%s",capturedir,CROSS_FILESPLIT,file_start,last,ext); + lowcase(file_name); + /* 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; +} void HARDWARE_Init(Section * sec) { - + Section_prop * section=static_cast(sec); + capturedir=(char *)section->Get_string("captures"); } diff --git a/src/hardware/iohandler.cpp b/src/hardware/iohandler.cpp index 32e6e95..904af71 100644 --- a/src/hardware/iohandler.cpp +++ b/src/hardware/iohandler.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -19,130 +19,90 @@ #include "dosbox.h" #include "inout.h" -#define IO_MAX 1024 +IO_WriteHandler * io_writehandlers[3][IO_MAX]; +IO_ReadHandler * io_readhandlers[3][IO_MAX]; -static struct IO_Block { - IO_WriteBHandler * write_b[IO_MAX]; - IO_WriteWHandler * write_w[IO_MAX]; - IO_WriteDHandler * write_d[IO_MAX]; - - IO_ReadBHandler * read_b[IO_MAX]; - IO_ReadWHandler * read_w[IO_MAX]; - IO_ReadDHandler * read_d[IO_MAX]; -} io; - -void IO_WriteB(Bitu port,Bit8u val) { - if (port> 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; + } } -static Bit8u IO_ReadDefaultB(Bit32u port) { - LOG(LOG_IO,LOG_WARN)("Reading from undefined port %04X",port); - io.read_b[port]=IO_ReadBBlocked; - return 0xff; +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++; + } } -static Bit16u IO_ReadDefaultW(Bit32u port) { - return io.read_b[port](port) | (io.read_b[port+1](port+1) << 8); -} -static Bit32u IO_ReadDefaultD(Bit32u port) { - return io.read_b[port](port) | (io.read_b[port+1](port+1) << 8) | - (io.read_b[port+2](port+2) << 16) | (io.read_b[port+3](port+3) << 24); +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_WriteDefaultB(Bit32u port,Bit8u val) { - LOG(LOG_IO,LOG_WARN)("Writing %02X to undefined port %04X",static_cast(val),port); - io.write_b[port]=IO_WriteBBlocked; -} -void IO_WriteDefaultW(Bit32u port,Bit16u val) { - io.write_b[port](port,(Bit8u)val); - io.write_b[port+1](port+1,(Bit8u)(val>>8)); -} -void IO_WriteDefaultD(Bit32u port,Bit32u val) { - io.write_b[port](port,(Bit8u)val); - io.write_b[port+1](port+1,(Bit8u)(val>>8)); - io.write_b[port+2](port+2,(Bit8u)(val>>16)); - io.write_b[port+3](port+3,(Bit8u)(val>>24)); +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_RegisterReadBHandler(Bitu port,IO_ReadBHandler * handler) { - if (port>=IO_MAX) return; - io.read_b[port]=handler; -} -void IO_RegisterReadWHandler(Bitu port,IO_ReadWHandler * handler) { - if (port>=IO_MAX) return; - io.read_w[port]=handler; -} -void IO_RegisterReadDHandler(Bitu port,IO_ReadDHandler * handler) { - if (port>=IO_MAX) return; - io.read_d[port]=handler; -} -void IO_RegisterWriteBHandler(Bitu port,IO_WriteBHandler * handler) { - if (port>=IO_MAX) return; - io.write_b[port]=handler; -} -void IO_RegisterWriteWHandler(Bitu port,IO_WriteWHandler * handler) { - if (port>=IO_MAX) return; - io.write_w[port]=handler; -} -void IO_RegisterWriteDHandler(Bitu port,IO_WriteDHandler * handler) { - if (port>=IO_MAX) return; - io.write_d[port]=handler; -} - - -void IO_FreeReadHandler(Bitu port) { - if (port>=IO_MAX) return; - io.read_b[port]=IO_ReadDefaultB; - io.read_w[port]=IO_ReadDefaultW; - io.read_d[port]=IO_ReadDefaultD; -} -void IO_FreeWriteHandler(Bitu port) { - if (port>=IO_MAX) return; - io.write_b[port]=IO_WriteDefaultB; - io.write_w[port]=IO_WriteDefaultW; - io.write_d[port]=IO_WriteDefaultD; -} - -void IO_Init(Section * sect) { - for (Bitu i=0;i +#include +#include +#include "cross.h" +#include "support.h" +#include "cpu.h" +#include "SDL_net.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" + +#define SOCKTABLESIZE 150 // DOS IPX driver was limited to 150 open sockets +#define DOS_MEMSEG 0xd000; + +Bit32u tcpPort; +bool isIpxServer; +bool isIpxConnected; +IPaddress ipxClientIp; // IPAddress for client connection to server +IPaddress ipxServConnIp; // IPAddress for client connection to server +TCPsocket ipxTCPClientSocket; +UDPsocket ipxClientSocket; +int UDPChannel; // Channel used by UDP connection +Bit8u recvBuffer[IPXBUFFERSIZE]; // Incoming packet buffer +Bitu call_ipx; // Callback of RETF entrypoint +Bitu call_ipxint; // Callback of INT 7A entrypoint +Bitu call_ipxesr1; // Callback of ESR init routine +Bitu call_ipxesr2; // Callback of ESR return routine +Bit16u dospage; +static RealPt ipx_callback; +static RealPt ipx_intcallback; +static RealPt ipx_esrcallback; +static RealPt ipx_esrptraddr; +static RealPt processedECB; + +SDLNet_SocketSet clientSocketSet; +static bool inESR; + +struct ipxnetaddr { + Uint8 netnum[4]; // Both are big endian + Uint8 netnode[6]; +} localIpxAddr; + +struct fragmentDescriptor { + Bit16u offset; + Bit16u segment; + Bit16u size; +}; + +packetBuffer incomingPacket; + +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; +} + +class ECBClass { +public: + RealPt ECBAddr; + + ECBClass *prevECB; + ECBClass *nextECB; + + Bit16u getSocket(void) { + return swapByte(real_readw(RealSeg(ECBAddr), RealOff(ECBAddr) + 0xa)); + } + + Bit8u getInUseFlag(void) { + return real_readb(RealSeg(ECBAddr), RealOff(ECBAddr) + 0x8); + } + + void setInUseFlag(Bit8u flagval) { + real_writeb(RealSeg(ECBAddr), RealOff(ECBAddr) + 0x8, flagval); + } + + void setCompletionFlag(Bit8u flagval) { + real_writeb(RealSeg(ECBAddr), RealOff(ECBAddr) + 0x9, flagval); + } + + Bit16u getFragCount(void) { + return real_readw(RealSeg(ECBAddr), RealOff(ECBAddr) + 34); + } + + void 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 getESRAddr(void) { + return RealMake(real_readw(RealSeg(ECBAddr), RealOff(ECBAddr)+6), real_readw(RealSeg(ECBAddr), RealOff(ECBAddr)+4)); + } + + void NotifyESR(void) { + RealPt tmpAddr = getESRAddr(); + if(tmpAddr == 0) return; + if(!inESR) { + //LOG_MSG("Calling ESR"); + processedECB = ECBAddr; + inESR = true; + //LOG_MSG("Write %x to %x", real_readd(RealSeg(ECBAddr), RealOff(ECBAddr)+4), RealMake(RealSeg(ipx_esrptraddr), RealOff(ipx_esrptraddr))); + real_writed(RealSeg(ipx_esrptraddr), RealOff(ipx_esrptraddr),real_readd(RealSeg(ECBAddr), RealOff(ECBAddr)+4)); + CPU_CALL(false, RealSeg(ipx_esrcallback), RealOff(ipx_esrcallback),0); + } + } + + void setImmAddress(Bit8u *immAddr) { + Bits i; + for(i=0;i<6;i++) { + real_writeb(RealSeg(ECBAddr), RealOff(ECBAddr)+28, immAddr[i]); + } + } + +}; + +ECBClass *ECBList; // Linked list of ECB's + +ECBClass * CreateECB(RealPt useAddr) { + ECBClass *tmpECB; + tmpECB = new ECBClass(); + + tmpECB->ECBAddr = useAddr; + tmpECB->prevECB = NULL; + tmpECB->nextECB = NULL; + + if (ECBList == NULL) { + ECBList = tmpECB; + } else { + // Transverse the list until we hit the end + ECBClass *useECB; + useECB = ECBList; + while(useECB->nextECB != NULL) { + useECB = useECB->nextECB; + } + useECB->nextECB = tmpECB; + tmpECB->prevECB = useECB; + } + + return tmpECB; +} + +void DeleteECB(ECBClass * useECB) { + if(useECB == NULL) return; + + if(useECB->prevECB == NULL) { + ECBList = useECB->nextECB; + if(ECBList != NULL) ECBList->prevECB = NULL; + } else { + useECB->prevECB->nextECB = useECB->nextECB; + if(useECB->nextECB != NULL) useECB->nextECB->prevECB = useECB->prevECB; + } + delete useECB; +} + +Bit16u socketCount; +Bit16u opensockets[SOCKTABLESIZE]; + +static bool sockInUse(Bit16u sockNum) { + Bit16u i; + for(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; + + sockNum = swapByte(reg_dx); + if(!sockInUse(sockNum)) return; + + for(i=0;isetInUseFlag(USEFLAG_AVAILABLE); + tmpECB->setCompletionFlag(COMP_UNDELIVERABLE); + DeleteECB(tmpECB); + reg_al = 0xff; // Failure + } else { + tmpECB = CreateECB(RealMake(SegValue(es), reg_si)); + tmpECB->setInUseFlag(USEFLAG_SENDING); + reg_al = 0x00; // Success + } + //LOG_MSG("IPX: Sending packet on %4x", tmpECB->getSocket()); + break; + case 0x0004: // Listen for packet + tmpECB = CreateECB(RealMake(SegValue(es), reg_si)); + if(!sockInUse(tmpECB->getSocket())) { + reg_al = 0xff; // Socket is not open + tmpECB->setInUseFlag(USEFLAG_AVAILABLE); + tmpECB->setCompletionFlag(COMP_HARDWAREERROR); + DeleteECB(tmpECB); + } else { + reg_al = 0x00; // Success + tmpECB->setInUseFlag(USEFLAG_LISTENING); + //LOG_MSG("IPX: Listen for packet on 0x%4x - ESR address %4x:%4x", tmpECB->getSocket(), RealSeg(tmpECB->getESRAddr()), RealOff(tmpECB->getESRAddr())); + } + + + break; + case 0x0008: // Get interval marker + // ???? + break; + case 0x0009: // Get internetwork address + { + LOG_MSG("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; + Bits i; + + addrptr = (Bit8u *)&localIpxAddr; + for(i=0;i<10;i++) { + real_writeb(SegValue(es),reg_si+i,addrptr[i]); + } + break; + } + case 0x000a: // Relinquish control + // Idle thingy + 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 disconnectServer(bool unexpected) { + + // There is no Timer remove code, hence this has to be done manually + incomingPacket.connected = false; + + if(unexpected) LOG_MSG("IPX: Server disconnected unexpectedly"); + +} + +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(localIpxAddr)); + 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(localIpxAddr)); + 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; + fragmentDescriptor tmpFrag; + Bit16u i, fragCount,t; + Bit16s bufoffset; + Bit16u *bufword = (Bit16u *)buffer; + Bit16u useSocket = swapByte(bufword[8]); + Bit32u hostaddr; + 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->getInUseFlag() == USEFLAG_LISTENING) { + if(useECB->getSocket() == useSocket) { + useECB->setInUseFlag(USEFLAG_AVAILABLE); + fragCount = useECB->getFragCount(); + bufoffset = 0; + for(i=0;igetFragDesc(i,&tmpFrag); + for(t=0;t=bufSize) { + useECB->setCompletionFlag(COMP_SUCCESS); + useECB->setImmAddress(&buffer[22]); // Write in source node + hostaddr = *((Bit32u *)&buffer[24]); + + //LOG_MSG("IPX: Received packet of %d bytes from %d.%d.%d.%d (%x CRC)", bufSize, CONVIP(hostaddr), packetCRC(&buffer[30], bufSize-30)); + useECB->NotifyESR(); + DeleteECB(useECB); + return; + } + } + } + if(bufoffset < bufSize) { + useECB->setCompletionFlag(COMP_MALFORMED); + useECB->NotifyESR(); + DeleteECB(useECB); + return; + } + } + } + useECB = nextECB; + } + +} + +static void sendPacketsTCP(void) { + ECBClass *useECB; + ECBClass *nextECB; + char outbuffer[IPXBUFFERSIZE]; + fragmentDescriptor tmpFrag; + Bit16u i, fragCount,t; + Bit16s packetsize; + Bit16u *wordptr; + Bits result; + + useECB = ECBList; + while(useECB != NULL) { + nextECB = useECB->nextECB; + if(useECB->getInUseFlag() == USEFLAG_SENDING) { + useECB->setInUseFlag(USEFLAG_AVAILABLE); + packetsize = 0; + fragCount = useECB->getFragCount(); + for(i=0;igetFragDesc(i,&tmpFrag); + if(i==0) { + // Fragment containing IPX header + // Must put source address into header + Bit8u * addrptr; + Bits m; + + addrptr = (Bit8u *)&localIpxAddr.netnode; + for(m=0;m<6;m++) { + real_writeb(tmpFrag.segment,tmpFrag.offset+m+22,addrptr[m]); + } + } + for(t=0;t=IPXBUFFERSIZE) { + LOG_MSG("IPX: Packet size to be sent greater than %d bytes.", IPXBUFFERSIZE); + useECB->setCompletionFlag(COMP_MALFORMED); + useECB->NotifyESR(); + DeleteECB(useECB); + goto nextECB; + } + } + } + result = SDLNet_TCP_Send(ipxTCPClientSocket, &packetsize, 2); + if(result != 2) { + useECB->setCompletionFlag(COMP_UNDELIVERABLE); + useECB->NotifyESR(); + DeleteECB(useECB); + disconnectServer(true); + 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(useECB->getSocket()); + + result = SDLNet_TCP_Send(ipxTCPClientSocket, &outbuffer[0], packetsize); + if(result != packetsize) { + useECB->setCompletionFlag(COMP_UNDELIVERABLE); + useECB->NotifyESR(); + DeleteECB(useECB); + disconnectServer(true); + return; + } + useECB->setInUseFlag(USEFLAG_AVAILABLE); + useECB->setCompletionFlag(COMP_SUCCESS); + useECB->NotifyESR(); + DeleteECB(useECB); + + } +nextECB: + + useECB = nextECB; + } + +} + + +static void IPX_TCPClientLoop(void) { + Bits result; + + // Check for incoming packets + SDLNet_CheckSockets(clientSocketSet,0); + + if(SDLNet_SocketReady(ipxClientSocket)) { + if(!incomingPacket.inPacket) { + if(!incomingPacket.waitsize) { + result = SDLNet_TCP_Recv(ipxTCPClientSocket, &incomingPacket.packetSize, 2); + if(result!=2) { + if(result>0) { + incomingPacket.waitsize = true; + goto finishReceive; + } else { + disconnectServer(true); + goto finishReceive; + } + } + incomingPacket.packetRead = 0; + } else { + Bit8u * nextchar; + nextchar = (Bit8u *)&incomingPacket.packetSize; + nextchar++; + result = SDLNet_TCP_Recv(ipxTCPClientSocket, nextchar, 1); + if(result!=1) { + if(result>0) { + LOG_MSG("IPX: Packet overrun"); + } else { + disconnectServer(true); + goto finishReceive; + } + } + incomingPacket.waitsize = false; + incomingPacket.packetRead = 0; + } + incomingPacket.inPacket = true; + } + result = SDLNet_TCP_Recv(ipxTCPClientSocket, &incomingPacket.buffer[incomingPacket.packetRead], incomingPacket.packetSize); + if (result>0) { + incomingPacket.packetRead+=result; + incomingPacket.packetSize-=result; + if(incomingPacket.packetSize<=0) { + // IPX packet is complete. Now interpret IPX header and try to match to listening ECB + receivePacket(&incomingPacket.buffer[0], incomingPacket.packetRead); + incomingPacket.inPacket = false; + } + } else { + // Clost active socket + disconnectServer(true); + } + + } + +finishReceive:; + + +} + +static void IPX_UDPClientLoop(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); + } + +} + +static void sendPackets() { + ECBClass *useECB; + ECBClass *nextECB; + char outbuffer[IPXBUFFERSIZE]; + fragmentDescriptor tmpFrag; + Bit16u i, fragCount,t; + Bit16s packetsize; + Bit16u *wordptr; + Bits result; + UDPpacket outPacket; + + useECB = ECBList; + while(useECB != NULL) { + nextECB = useECB->nextECB; + if(useECB->getInUseFlag() == USEFLAG_SENDING) { + useECB->setInUseFlag(USEFLAG_AVAILABLE); + packetsize = 0; + fragCount = useECB->getFragCount(); + for(i=0;igetFragDesc(i,&tmpFrag); + if(i==0) { + // Fragment containing IPX header + // Must put source address into header + Bit8u * addrptr; + Bits m; + + addrptr = (Bit8u *)&localIpxAddr.netnode; + for(m=0;m<6;m++) { + real_writeb(tmpFrag.segment,tmpFrag.offset+m+22,addrptr[m]); + } + } + for(t=0;t=IPXBUFFERSIZE) { + LOG_MSG("IPX: Packet size to be sent greater than %d bytes.", IPXBUFFERSIZE); + useECB->setCompletionFlag(COMP_UNDELIVERABLE); + useECB->NotifyESR(); + DeleteECB(useECB); + goto nextECB; + } + } + } + + // 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(useECB->getSocket()); + + 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()); + useECB->setCompletionFlag(COMP_UNDELIVERABLE); + useECB->NotifyESR(); + DeleteECB(useECB); + disconnectServer(true); + return; + } + useECB->setInUseFlag(USEFLAG_AVAILABLE); + useECB->setCompletionFlag(COMP_SUCCESS); + useECB->NotifyESR(); + DeleteECB(useECB); + + } +nextECB: + + useECB = nextECB; + } + +} + +static void IPX_ClientLoop(void) { + IPX_UDPClientLoop(); + + // Send outgoing packets + sendPackets(); +} + + +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 *strAddr) { + int numsent; + UDPpacket regPacket; + IPXHeader regHeader; + + if(!SDLNet_ResolveHost(&ipxServConnIp, strAddr, (Bit16u)tcpPort)) { + + // 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 DisconnectFromServer(void) { + + if(incomingPacket.connected) { + incomingPacket.connected = false; + TIMER_DelTickHandler(&IPX_ClientLoop); + SDLNet_UDP_Close(ipxClientSocket); + } +} + +bool IPX_NetworkInit() { + + localIpxAddr.netnum[0] = 0x0; localIpxAddr.netnum[1] = 0x0; localIpxAddr.netnum[2] = 0x0; localIpxAddr.netnum[3] = 0x1; + + /* + if(SDLNet_ResolveHost(&ipxClientIp, localhostname, tcpPort)) { + LOG_MSG("IPX: Unable to resolve localname: \"%s\". IPX disabled.", localhostname); + return false; + } else { + LOG_MSG("IPX: Using localname: %s IP is: %d.%d.%d.%d", localhostname, CONVIP(ipxClientIp.host)); + } + */ + + // 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 + localIpxAddr.netnode[0] = 0x00; + localIpxAddr.netnode[1] = 0x00; + //localIpxAddr.netnode[5] = (ipxClientIp.host >> 24) & 0xff; + //localIpxAddr.netnode[4] = (ipxClientIp.host >> 16) & 0xff; + //localIpxAddr.netnode[3] = (ipxClientIp.host >> 8) & 0xff; + //localIpxAddr.netnode[2] = (ipxClientIp.host & 0xff); + //To be filled in on response from server + localIpxAddr.netnode[2] = 0x00; + localIpxAddr.netnode[3] = 0x00; + localIpxAddr.netnode[4] = 0x00; + localIpxAddr.netnode[5] = 0x00; + + socketCount = 0; + return true; +} + +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)) { + tcpPort = 213; + } else { + tcpPort = strtol(temp_line.c_str(), NULL, 10); + } + startsuccess = IPX_StartServer((Bit16u)tcpPort); + 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(); + IPX_StopServer(); + WriteOut("IPX Tunneling Server stopped."); + // Don't know how to stop the timer just yet. + } + 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)) { + tcpPort = 213; + } else { + tcpPort = 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(); + 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), tcpPort); + } 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; + } + + 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); + } + } + return; + } + + + + } + + /* + WriteOut("IPX Status\n\n"); + if(!incomingPacket.connected) { + WriteOut("IPX tunneling client not presently connected"); + return; + } + if(isIpxServer) { + WriteOut("This DosBox session is an IPX tunneling server running on port %d", tcpPort); + } else { + WriteOut("This DosBox session is an IPX tunneling client connected to: %s",SDLNet_ResolveIP(&ipxServConnIp)); + } + */ + } +}; + +static void IPXNET_ProgramStart(Program * * make) { + *make=new IPXNET; +} + +Bitu IPX_ESRHandler1(void) { + CPU_Push32(reg_flags); + CPU_Push32(reg_eax);CPU_Push32(reg_ecx);CPU_Push32(reg_edx);CPU_Push32(reg_ebx); + CPU_Push32(reg_ebp);CPU_Push32(reg_esi);CPU_Push32(reg_edi); + CPU_Push16(SegValue(ds)); CPU_Push16(SegValue(es)); + + SegSet16(es, RealSeg(processedECB)); + reg_si = RealOff(processedECB); + reg_al = 0xff; + //LOG_MSG("ESR Callback 1"); + + return CBRET_NONE; +} + +Bitu IPX_ESRHandler2(void) { + SegSet16(es, CPU_Pop16()); SegSet16(ds, CPU_Pop16()); + reg_edi=CPU_Pop32();reg_esi=CPU_Pop32();reg_ebp=CPU_Pop32(); + reg_ebx=CPU_Pop32();reg_edx=CPU_Pop32();reg_ecx=CPU_Pop32();reg_eax=CPU_Pop32(); + reg_flags=CPU_Pop32(); + + //LOG_MSG("Leaving ESR"); + inESR = false; + + return CBRET_NONE; +} + +bool IPX_ESRSetupHook(Bitu callback1, CallBack_Handler handler1, Bitu callback2, CallBack_Handler handler2, RealPt *ptrAddr) { + PhysPt phyDospage; + phyDospage = PhysMake(dospage,0); + + // Inital callback routine (should save registers, etc.) + phys_writeb(phyDospage+0,(Bit8u)0xFA); //CLI + phys_writeb(phyDospage+1,(Bit8u)0xFE); //GRP 4 + phys_writeb(phyDospage+2,(Bit8u)0x38); //Extra Callback instruction + phys_writew(phyDospage+3,callback1); //The immediate word + phys_writeb(phyDospage+5,(Bit8u)0x9a); //CALL Ap + // 0x6, 0x7, 0x8, 0x9 = address of called routine + *ptrAddr = RealMake(dospage, 6); + phys_writed(phyDospage+6,(Bit32u)0x00000000); // Called address + phys_writeb(phyDospage+0xa,(Bit8u)0xFE); //GRP 4 + phys_writeb(phyDospage+0xb,(Bit8u)0x38); //Extra Callback instruction + phys_writew(phyDospage+0xc,callback2); //The immediate word + phys_writeb(phyDospage+0xe,(Bit8u)0xFB); //STI + phys_writeb(phyDospage+0xf,(Bit8u)0xCB); //A RETF Instruction + + CallBack_Handlers[callback1]=handler1; + CallBack_Handlers[callback2]=handler2; + return true; +} + +void IPX_Init(Section* sec) { + Section_prop * section=static_cast(sec); + + 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; + + isIpxServer = false; + isIpxConnected = false; + + IPX_NetworkInit(); + + inESR = false; + + DOS_AddMultiplexHandler(IPX_Multiplex); + call_ipx=CALLBACK_Allocate(); + CALLBACK_Setup(call_ipx,&IPX_Handler,CB_RETF); + ipx_callback=CALLBACK_RealPointer(call_ipx); + + call_ipxint=CALLBACK_Allocate(); + CALLBACK_Setup(call_ipxint,&IPX_IntHandler,CB_IRET); + ipx_intcallback=CALLBACK_RealPointer(call_ipxint); + + call_ipxesr1=CALLBACK_Allocate(); + call_ipxesr2=CALLBACK_Allocate(); + //CALLBACK_SetupFarCall(call_ipxesr1, &IPX_ESRHandler1, call_ipxesr2, &IPX_ESRHandler2, &ipx_esrptraddr); + dospage = DOS_GetMemory(1); + IPX_ESRSetupHook(call_ipxesr1, &IPX_ESRHandler1, call_ipxesr2, &IPX_ESRHandler2, &ipx_esrptraddr); + // Allocate 16 bytes of memory from the DOS system area at 0xd000 + ipx_esrcallback=RealMake(dospage,0); + //CALLBACK_RealPointer(call_ipxesr1); + + RealSetVec(0x7a,ipx_intcallback); + PROGRAMS_MakeFile("IPXNET.COM",IPXNET_ProgramStart); + + //if(isIpxServer) { + // Auto-connect to server + // ConnectToServer("localhost"); + //} + +} + +#endif diff --git a/src/hardware/ipxserver.cpp b/src/hardware/ipxserver.cpp new file mode 100644 index 0000000..5e9f956 --- /dev/null +++ b/src/hardware/ipxserver.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * 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" + +#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(0, 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 +#include + #include "dosbox.h" #include "keyboard.h" #include "inout.h" @@ -27,7 +30,7 @@ #include "mixer.h" #define KEYBUFSIZE 32 -#define KEYDELAY 150 +#define KEYDELAY 0.300f //Considering 20-30 khz serial clock and 11 bits/char enum KeyCommands { CMD_NONE, @@ -36,221 +39,157 @@ enum KeyCommands { CMD_SETOUTPORT }; -enum KeyStates { - STATE_NORMAL, - STATE_EXTEND, -}; - -struct KeyCode { - Bit8u scancode; - Bit8u ascii; - KeyStates state; - Bitu mod; -}; - -struct KeyEvent { - Bits type; - Bitu state; - KEYBOARD_EventHandler * handler; - KeyEvent * next; -}; - -struct KeyBlock { +static struct { + Bit8u buffer[KEYBUFSIZE]; + Bitu used; + Bitu pos; struct { - KeyCode code[KEYBUFSIZE]; - Bitu used; - Bitu pos; - KeyStates state; - } buf; - Bitu write_state; - Bit64u last_index; + KBD_KEYS key; + Bitu wait; + Bitu pause,rate; + } repeat; KeyCommands command; - bool enabled; + Bit8u p60data; + bool p60changed; bool active; + bool scanning; bool scheduled; - bool key_on_60; -}; +} keyb; -static KeyBlock keyb; -static Bit8u cur_scancode; -static Bit8u port_61_data; -//TODO Are these initialized at 0 at startup? Hope so :) -static KeyEvent * event_handlers[KBD_LAST]; - -void KEYBOARD_ClrBuffer(void) { - keyb.buf.used=0; - keyb.buf.pos=0; - keyb.scheduled=false; - PIC_DeActivateIRQ(1); - keyb.key_on_60=false; +static void KEYBOARD_SetPort60(Bit8u val) { + keyb.p60changed=true; + keyb.p60data=val; + PIC_ActivateIRQ(1); } -/* Read an entry from the keycode buffer */ -void KEYBOARD_GetCode(void) { +static void KEYBOARD_TransferBuffer(Bitu val) { keyb.scheduled=false; - switch (keyb.buf.state) { - case STATE_NORMAL: - /* Check for a next key */ - if (!keyb.buf.used) return; - keyb.buf.used--; - keyb.buf.pos++; - if (keyb.buf.pos>=KEYBUFSIZE) keyb.buf.pos-=KEYBUFSIZE; - keyb.buf.state=keyb.buf.code[keyb.buf.pos].state; - break; - case STATE_EXTEND: - keyb.buf.state=STATE_NORMAL; - break; + if (!keyb.used) { + LOG(LOG_KEYBOARD,LOG_NORMAL)("Transfer started with empty buffer"); + return; } - keyb.key_on_60=true; - if (keyb.enabled) PIC_ActivateIRQ(1); + Bit8u data=keyb.buffer[keyb.pos]; + KEYBOARD_SetPort60(keyb.buffer[keyb.pos]); + if (++keyb.pos>=KEYBUFSIZE) keyb.pos-=KEYBUFSIZE; + keyb.used--; } -void KEYBOARD_AddCode(Bit8u scancode,Bit8u ascii,Bitu mod,KeyStates state) { -// LOG_MSG("Add key scan %d ascii %c",scancode,ascii); - if (keyb.buf.used=KEYBUFSIZE) start-=KEYBUFSIZE; - keyb.buf.code[start].scancode=scancode; - keyb.buf.code[start].ascii=ascii; - keyb.buf.code[start].state=state; - keyb.buf.code[start].mod=mod; + +static 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.key_on_60) { + if (!keyb.scheduled && !keyb.p60changed) { keyb.scheduled=true; - PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); + PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY); } } -void KEYBOARD_ReadKey(Bitu & scancode,Bitu & ascii,Bitu & mod) { - keyb.key_on_60=false; //else no new keys get scheduled :) - switch (keyb.buf.state) { - case STATE_NORMAL: - if (keyb.buf.used && !keyb.scheduled) { - keyb.scheduled=true; - PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); - } - scancode=keyb.buf.code[keyb.buf.pos].scancode; - ascii=keyb.buf.code[keyb.buf.pos].ascii; - mod=keyb.buf.code[keyb.buf.pos].mod; - break; - case STATE_EXTEND: - scancode=224; - mod=0; - ascii=0; - if (!keyb.scheduled) { - keyb.scheduled=true; - PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); - } - break; + +static Bitu read_p60(Bitu port,Bitu iolen) { + keyb.p60changed=false; + if (!keyb.scheduled && keyb.used) { + keyb.scheduled=true; + PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY); } -} - -static Bit8u read_p60(Bit32u port) { - keyb.key_on_60 = false; - switch (keyb.buf.state) { - case STATE_NORMAL: - if (keyb.buf.used && !keyb.scheduled) { //key60 is false - keyb.scheduled=true; - PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); - } - - return keyb.buf.code[keyb.buf.pos].scancode; - case STATE_EXTEND: - if (!keyb.scheduled) { - keyb.scheduled=true; - PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); - } - - return 224; - } - return 0; + return keyb.p60data; } -static void write_p60(Bit32u port,Bit8u val) { +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_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ + KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ break; case 0xee: /* Echo */ - KEYBOARD_AddCode(0xee,0,0,STATE_NORMAL); + KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ break; case 0xf2: /* Identify keyboard */ /* AT's just send acknowledge */ - KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ + KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ break; case 0xf3: /* Typematic rate programming */ keyb.command=CMD_SETTYPERATE; - KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ + KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ break; case 0xf4: /* Enable keyboard,clear buffer, start scanning */ - keyb.active=true; - KEYBOARD_ClrBuffer(); - LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated port 60"); - KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ + 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"); - KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ + 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_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ + KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ } return; case CMD_SETOUTPORT: MEM_A20_Enable((val & 2)>0); break; - case CMD_SETTYPERATE: case CMD_SETLEDS: keyb.command=CMD_NONE; - KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ + KEYBOARD_ClrBuffer(); + KEYBOARD_AddBuffer(0xfa); /* Acknowledge */ break; } } -static Bit8u read_p61(Bit32u port) { +static Bit8u port_61_data; +static Bitu read_p61(Bitu port,Bitu iolen) { port_61_data^=0x20; port_61_data^=0x10; return port_61_data; } -static void write_p61(Bit32u port,Bit8u val) { -/* - if (val & 128) if (!keyb.read_active) KEYBOARD_ReadBuffer(); - Keys should get acknowledged just by reading 0x60. - Perhaps disable controller when bit 7=1 -*/ - if ((port_61_data ^val) & 3) PCSPEAKER_SetType(val & 3); +static void write_p61(Bitu port,Bitu val,Bitu iolen) { + if ((port_61_data ^ val) & 3) PCSPEAKER_SetType(val & 3); port_61_data=val; } -static void write_p64(Bit32u port,Bit8u val) { +static void write_p64(Bitu port,Bitu val,Bitu iolen) { switch (val) { case 0xae: /* Activate keyboard */ keyb.active=true; - if (keyb.buf.used && !keyb.scheduled && !keyb.key_on_60) { + if (keyb.used && !keyb.scheduled && !keyb.p60changed) { keyb.scheduled=true; - PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); + PIC_AddEvent(KEYBOARD_TransferBuffer,KEYDELAY); } - LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated port 64"); + LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated"); break; case 0xad: /* Deactivate keyboard */ keyb.active=false; - PIC_DeActivateIRQ(1); - PIC_RemoveEvents(KEYBOARD_GetCode); LOG(LOG_KEYBOARD,LOG_NORMAL)("De-Activated"); break; case 0xd0: /* Outport on buffer */ - KEYBOARD_AddCode(MEM_A20_Enabled() ? 0x02 : 0,0,0,STATE_NORMAL); + KEYBOARD_SetPort60(MEM_A20_Enabled() ? 0x02 : 0); break; case 0xd1: /* Write to outport */ keyb.command=CMD_SETOUTPORT; @@ -261,29 +200,12 @@ static void write_p64(Bit32u port,Bit8u val) { } } -static Bit8u read_p64(Bit32u port) { -// Bit8u status= 0x1c | ((keyb.buf.used ||keyb.key_on_60)? 0x1 : 0x0); -// Old one. Digitracker 2 doesn't like this. key_on_60 is much more advanged. - Bit8u status= 0x1c | (keyb.key_on_60? 0x1 : 0x0); - keyb.key_on_60=false; +static Bitu read_p64(Bitu port,Bitu iolen) { + Bit8u status= 0x1c | (keyb.p60changed? 0x1 : 0x0); return status; } -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(LOG_KEYBOARD,LOG_ERROR)("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(KBD_KEYS keytype,Bitu unicode,Bitu mod,bool pressed) { +void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed) { Bit8u ret=0;bool extend=false; switch (keytype) { case KBD_esc:ret=1;break; @@ -386,7 +308,7 @@ void KEYBOARD_AddKey(KBD_KEYS keytype,Bitu unicode,Bitu mod,bool pressed) { 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_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; @@ -398,42 +320,52 @@ void KEYBOARD_AddKey(KBD_KEYS keytype,Bitu unicode,Bitu mod,bool pressed) { 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: + case KBD_printscreen: + /* Not handled yet. But usuable in mapper for special events */ + return; default: E_Exit("Unsupported key press"); break; } - /* check for active key events */ - KeyEvent * checkevent=event_handlers[keytype]; - while (checkevent) { - if ((mod & checkevent->state)==checkevent->state) { - if (checkevent->type==keytype && pressed) { - (*checkevent->handler)(); - return; - } - if (checkevent->type==keytype) return; - } - checkevent=checkevent->next; - } /* Add the actual key in the keyboard queue */ - if (!pressed) ret+=128; - KEYBOARD_AddCode(ret,(Bit8u)unicode,mod,extend ? STATE_EXTEND : STATE_NORMAL); + 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,"Keyboard"); - IO_RegisterReadHandler(0x60,read_p60,"Keyboard"); - IO_RegisterWriteHandler(0x61,write_p61,"Keyboard"); - IO_RegisterReadHandler(0x61,read_p61,"Keyboard"); - IO_RegisterWriteHandler(0x64,write_p64,"Keyboard"); - IO_RegisterReadHandler(0x64,read_p64,"Keyboard"); - - port_61_data=0; /* Direct Speaker control and output disabled */ -// memset(&event_handlers,0,sizeof(event_handlers)); - /* Clear the keyb struct */ + 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.enabled=true; + keyb.scanning=true; keyb.command=CMD_NONE; - keyb.last_index=0; - keyb.key_on_60=false; + keyb.p60changed=false; + keyb.repeat.key=KBD_NONE; + keyb.repeat.pause=500; + keyb.repeat.rate=33; + keyb.repeat.wait=0; KEYBOARD_ClrBuffer(); } diff --git a/src/hardware/memory.cpp b/src/hardware/memory.cpp index dddeb8c..69f8666 100644 --- a/src/hardware/memory.cpp +++ b/src/hardware/memory.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -34,11 +34,6 @@ #define LFB_PAGES 512 #define MAX_LINKS ((MAX_MEMORY*1024/4)+4096) //Hopefully enough -struct AllocBlock { - Bit8u data[PAGES_IN_BLOCK*4096]; - AllocBlock * next; -}; - struct LinkBlock { Bitu used; Bit32u pages[MAX_LINKS]; @@ -47,14 +42,8 @@ struct LinkBlock { static struct MemoryBlock { Bitu pages; PageHandler * * phandlers; - HostPt * hostpts; MemHandle * mhandles; LinkBlock links; - struct { - Bitu pages; - HostPt cur_page; - AllocBlock *cur_block; - } block; struct { Bitu start_page; Bitu end_page; @@ -67,6 +56,8 @@ static struct MemoryBlock { } a20; } memory; +HostPt MemBase; + class IllegalPageHandler : public PageHandler { public: IllegalPageHandler() { @@ -90,10 +81,7 @@ public: flags=PFLAG_READABLE|PFLAG_WRITEABLE; } HostPt GetHostPt(Bitu phys_page) { - if (!memory.hostpts[phys_page]) { - memory.hostpts[phys_page]=MEM_GetBlockPage(); - } - return memory.hostpts[phys_page]; + return MemBase+phys_page*MEM_PAGESIZE; } }; @@ -102,6 +90,15 @@ public: ROMPageHandler() { flags=PFLAG_READABLE|PFLAG_HASROM; } + void writeb(PhysPt addr,Bitu val){ + LOG_MSG("Write %x to rom at %x",val,addr); + } + void writew(PhysPt addr,Bitu val){ + LOG_MSG("Write %x to rom at %x",val,addr); + } + void writed(PhysPt addr,Bitu val){ + LOG_MSG("Write %x to rom at %x",val,addr); + } }; class LFBPageHandler : public RAMPageHandler { @@ -458,122 +455,58 @@ void mem_writed(PhysPt address,Bit32u val) { mem_writed_inline(address,val); } -void phys_writeb(PhysPt addr,Bit8u val) { - HostPt block=memory.hostpts[addr >> 12]; - if (!block) { - block=memory.hostpts[addr >> 12]=MEM_GetBlockPage(); - } - host_writeb(block+(addr & 4095),val); -} - -void phys_writew(PhysPt addr,Bit16u val) { - phys_writeb(addr,(Bit8u)val); - phys_writeb(addr+1,(Bit8u)(val >> 8)); -} - -void phys_writed(PhysPt addr,Bit32u val) { - phys_writeb(addr,(Bit8u)val); - phys_writeb(addr+1,(Bit8u)(val >> 8)); - phys_writeb(addr+2,(Bit8u)(val >> 16)); - phys_writeb(addr+3,(Bit8u)(val >> 24)); -} - -Bit32u MEM_PhysReadD(Bitu addr) { - Bitu page=addr >> 12; - Bitu index=(addr & 4095); - if (page>memory.pages) - E_Exit("Reading from illegal page"); - HostPt block=memory.hostpts[page]; - if (!block) { - E_Exit("Reading from empty page"); - } - return host_readd(block+index); -} - -void MEM_PhysWriteD(Bitu addr,Bit32u val) { - Bitu page=addr >> 12; - Bitu index=(addr & 4095); - if (page>memory.pages) - E_Exit("Writing from illegal page"); - HostPt block=memory.hostpts[page]; - if (!block) { - E_Exit("Writing to empty page"); - } - host_writed(block+index,val); -} - - -static void write_p92(Bit32u port,Bit8u 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 Bit8u read_p92(Bit32u port) { +static Bitu read_p92(Bitu port,Bitu iolen) { return memory.a20.controlport | (memory.a20.enabled ? 0x02 : 0); } -HostPt MEM_GetBlockPage(void) { - HostPt ret; - if (memory.block.pages) { - ret=memory.block.cur_page; - memory.block.pages--; - memory.block.cur_page+=4096; - } else { - AllocBlock * newblock=new AllocBlock; - memset(newblock,0,sizeof(AllocBlock)); //zero new allocated memory - newblock->next=memory.block.cur_block; - memory.block.cur_block=newblock; - - memory.block.pages=PAGES_IN_BLOCK-1; - ret=&newblock->data[0]; - memory.block.cur_page=&newblock->data[4096]; - } - return ret; -} - static void MEM_ShutDown(Section * sec) { - AllocBlock * theblock=memory.block.cur_block; - while (theblock) { - AllocBlock * next=theblock->next; - delete theblock; - theblock=next; - } + free(MemBase); } void MEM_Init(Section * sec) { Bitu i; Section_prop * section=static_cast(sec); - /* Setup Memory Block */ - memory.block.pages=0; - memory.block.cur_block=0; - /* Setup the Physical Page Links */ Bitu memsize=section->Get_int("memsize"); if (memsize<1) memsize=1; - if (memsize>MAX_MEMORY) { - LOG_MSG("Maximum memory size is %d MB",MAX_MEMORY); - memsize=MAX_MEMORY; + /* 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; } + MemBase=(HostPt)malloc(memsize*1024*1024); + if (!MemBase) E_Exit("Can't allocate main memory of %d MB",memsize); memory.pages=(memsize*1024*1024)/4096; /* Allocate the data for the different page information blocks */ - memory.hostpts=new HostPt[memory.pages]; memory.phandlers=new PageHandler * [memory.pages]; memory.mhandles=new MemHandle [memory.pages]; for (i=0;iAddDestroyFunction(&MEM_ShutDown); diff --git a/src/hardware/mixer.cpp b/src/hardware/mixer.cpp index 2886da2..f52b9c3 100644 --- a/src/hardware/mixer.cpp +++ b/src/hardware/mixer.cpp @@ -24,49 +24,32 @@ #include #include #include +#include #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 "keyboard.h" +#include "mapper.h" +#include "hardware.h" +#include "programs.h" -#define MIXER_MAXCHAN 8 -#define MIXER_BUFSIZE (16*1024) #define MIXER_SSIZE 4 -#define MIXER_SHIFT 16 +#define MIXER_SHIFT 14 #define MIXER_REMAIN ((1<MAX_AUDIO) ? (Bit16s)MAX_AUDIO : (SAMPhandler)(((Bit8u*)&mixer.temp)+sizeof(mixer.temp.TYPE[0]),sample_toread); \ - Bitu sample_index=(1 << MIXER_SHIFT) - chan->sample_left; \ - Bit32s newsample; \ - for (Bitu mix=0;mix> MIXER_SHIFT;sample_index+=chan->sample_add; \ - newsample=mixer.work[mix][0]+MAKE_##TYPE( LCHAN ); \ - mixer.work[mix][0]=MIXER_CLIP(newsample); \ - newsample=mixer.work[mix][1]+MAKE_##TYPE( RCHAN ); \ - mixer.work[mix][1]=MIXER_CLIP(newsample); \ - } \ - chan->remain=*(Bitu *)&mixer.temp.TYPE[sample_index>>MIXER_SHIFT]; \ - chan->sample_left=sample_total-sample_index; \ - break; \ -} - struct MIXER_Channel { - Bit8u volume; + double vol_main[2]; + Bits vol_mul[2]; Bit8u mode; Bitu freq; char * name; @@ -88,176 +71,287 @@ static Bit8u wavheader[]={ }; static struct { - struct { - Bit16s data[MIXER_BUFSIZE][2]; - Bitu read,write; - } out; - Bit16s work[MIXER_BUFSIZE][2]; - union { - Bit16s m16[MIXER_BUFSIZE][1]; - Bit16s s16[MIXER_BUFSIZE][2]; - Bit8u m8[MIXER_BUFSIZE][1]; - Bit8u s8[MIXER_BUFSIZE][2]; - } temp; - MIXER_Channel * channels; + Bit32s work[MIXER_BUFSIZE][2]; + Bitu pos,done; + Bitu needed,min_needed; + float mastervol[2]; + MixerChannel * channels; bool nosound; Bitu freq; Bitu blocksize; Bitu tick_add,tick_remain; struct { FILE * handle; - const char * dir; - Bit8u buf[MIXER_WAVESIZE]; + Bit16s buf[MIXER_WAVESIZE][2]; Bitu used; Bit32u length; } wave; } mixer; -MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * name) { -//TODO Find a free channel - MIXER_Channel * chan=new MIXER_Channel; - if (!chan) return 0; - chan->playing=false; - chan->volume=255; - chan->mode=MIXER_16STEREO; +Bit8u MixTemp[MIXER_BUFSIZE]; + +MixerChannel * MIXER_AddChannel(MIXER_Handler handler,Bitu freq,char * name) { + MixerChannel * chan=new MixerChannel(); chan->handler=handler; chan->name=name; - chan->sample_add=(freq<sample_left=0; + chan->SetFreq(freq); chan->next=mixer.channels; + chan->SetVolume(1,1); + chan->enabled=false; mixer.channels=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; - /* Clear work buffer */ - memset(mixer.work,0,samples*MIXER_SSIZE); - MIXER_Channel * chan=mixer.channels; +MixerChannel * MIXER_FindChannel(const char * name) { + MixerChannel * chan=mixer.channels; while (chan) { - if (chan->playing) { - /* This should always allocate 1 extra sample */ - Bitu sample_total=(samples*chan->sample_add)-chan->sample_left; - Bitu sample_toread=sample_total >> MIXER_SHIFT; - if (sample_total & MIXER_REMAIN) sample_toread++; - sample_total=(sample_toread+1)<remain; - switch (chan->mode) { - case MIXER_8MONO: - MIX_NORMAL(m8,0,0); - break; - case MIXER_8STEREO: - MIX_NORMAL(m8,0,1); - break; - case MIXER_16MONO: - MIX_NORMAL(m16,0,0); - break; - case MIXER_16STEREO: - MIX_NORMAL(s16,0,1); - break; - default: - E_Exit("MIXER:Illegal sound mode %2X",chan->mode); - break; - } - } + if (!strcasecmp(chan->name,name)) break; chan=chan->next; } - Bitu buf_remain=MIXER_BUFSIZE-mixer.out.write; - /* Fill the samples size buffer with 0's */ - if (buf_remain>samples) { - memcpy(&mixer.out.data[mixer.out.write][0],&mixer.work[0][0],samples*MIXER_SSIZE); - mixer.out.write+=samples; - } else { - memcpy(&mixer.out.data[mixer.out.write][0],&mixer.work[0][0],buf_remain*MIXER_SSIZE); - memcpy(&mixer.out.data[0][0],&mixer.work[buf_remain][0],(samples-buf_remain)*MIXER_SSIZE); - mixer.out.write=(mixer.out.write+samples)-MIXER_BUFSIZE; + return chan; +} + +void MixerChannel::UpdateVolume(void) { + volmul[0]=(Bits)((1 << MIXER_VOLSHIFT)*volmain[0]*mixer.mastervol[0]); + volmul[1]=(Bits)((1 << MIXER_VOLSHIFT)*volmain[1]*mixer.mastervol[1]); +} + +void MixerChannel::SetVolume(float _left,float _right) { + volmain[0]=_left; + volmain[1]=_right; + 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,void * data) { + Bits diff[2]; + Bit8u * data8=(Bit8u*)data; + Bit16s * data16=(Bit16s*)data; + Bitu mixpos=mixer.pos+done; + freq_index&=MIXER_REMAIN; + Bitu pos=0;Bitu new_pos; + goto thestart; + while (1) { + new_pos=freq_index >> MIXER_SHIFT; + if (pos=len) return; + if (_8bits) { + if (stereo) { + diff[0]=(((Bit8s)(data8[pos*2+0] ^ 0x80)) << 8)-last[0]; + diff[1]=(((Bit8s)(data8[pos*2+1] ^ 0x80)) << 8)-last[1]; + } else { + diff[0]=(((Bit8s)(data8[pos] ^ 0x80)) << 8)-last[0]; + } + } else { + if (stereo) { + diff[0]=data16[pos*2+0]-last[0]; + diff[1]=data16[pos*2+1]-last[1]; + } else { + diff[0]=data16[pos]-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,Bit8u * data) { + AddSamples(len,data); +} +void MixerChannel::AddSamples_s8(Bitu len,Bit8u * data) { + AddSamples(len,data); +} +void MixerChannel::AddSamples_m16(Bitu len,Bit16s * data) { + AddSamples(len,data); +} +void MixerChannel::AddSamples_s16(Bitu len,Bit16s * data) { + AddSamples(len,data); +} + +void MixerChannel::FillUp(void) { + SDL_LockAudio(); + if (!enabled || doneMix(needed); + chan=chan->next; } if (mixer.wave.handle) { - memcpy(&mixer.wave.buf[mixer.wave.used],&mixer.work[0][0],samples*MIXER_SSIZE); - mixer.wave.length+=samples*MIXER_SSIZE; - mixer.wave.used+=samples*MIXER_SSIZE; - if (mixer.wave.used>(MIXER_WAVESIZE-1024)){ - fwrite(mixer.wave.buf,1,mixer.wave.used,mixer.wave.handle); - mixer.wave.used=0; + Bitu added=needed-mixer.done; + Bitu readpos=(mixer.pos+mixer.done-added)&MIXER_BUFMASK; + while (added--) { + Bits sample=mixer.work[readpos][0] >> MIXER_VOLSHIFT; + mixer.wave.buf[mixer.wave.used][0]=MIXER_CLIP(sample); + sample=mixer.work[readpos][1] >> MIXER_VOLSHIFT; + mixer.wave.buf[mixer.wave.used][1]=MIXER_CLIP(sample); + readpos=(readpos+1)&MIXER_BUFMASK; + if (++mixer.wave.used==MIXER_WAVESIZE) { + mixer.wave.length+=MIXER_WAVESIZE*MIXER_SSIZE; + mixer.wave.used=0; + fwrite(mixer.wave.buf,MIXER_WAVESIZE*MIXER_SSIZE,1,mixer.wave.handle); + } } } + mixer.done=needed; } -static void MIXER_Mix(Bitu ticks) { +static void MIXER_Mix(void) { + SDL_LockAudio(); + MIXER_MixData(mixer.needed); mixer.tick_remain+=mixer.tick_add; - Bitu count=mixer.tick_remain>>MIXER_SHIFT; - mixer.tick_remain&=((1<=MIXER_BUFSIZE) size-=MIXER_BUFSIZE; - if (size>mixer.blocksize*2) return; - MIXER_MixData(count); + mixer.needed+=(mixer.tick_remain>>MIXER_SHIFT); + mixer.tick_remain&=MIXER_REMAIN; + SDL_UnlockAudio(); } -static void MIXER_Mix_NoSound(Bitu ticks) { +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; - Bitu count=mixer.tick_remain>>MIXER_SHIFT; - mixer.tick_remain&=((1<>MIXER_SHIFT; + mixer.tick_remain&=MIXER_REMAIN; + mixer.done=0; } static void MIXER_CallBack(void * userdata, Uint8 *stream, int len) { - /* Copy data from out buffer to the stream */ - Bitu size=MIXER_BUFSIZE+mixer.out.write-mixer.out.read; - if (size>=MIXER_BUFSIZE) size-=MIXER_BUFSIZE; - if (size*MIXER_SSIZE<(Bitu)len) { -// LOG(0,"Buffer underrun"); - /* When there's a buffer underrun, keep the data so there will be more next time */ + Bitu need=(Bitu)len/MIXER_SSIZE; + if (need>mixer.done) { +// LOG_MSG("Buffer underrun"); return; } - Bitu remain=MIXER_BUFSIZE-mixer.out.read; - if (remain>=(Bitu)len/MIXER_SSIZE) { - memcpy((void *)stream,(void *)&mixer.out.data[mixer.out.read][0],len); - } else { - memcpy((void *)stream,(void *)&mixer.out.data[mixer.out.read][0],remain*MIXER_SSIZE); - stream+=remain*MIXER_SSIZE; - memcpy((void *)stream,(void *)&mixer.out.data[0][0],(len)-remain*MIXER_SSIZE); + /* Reduce done count in all channels */ + for (MixerChannel * chan=mixer.channels;chan;chan=chan->next) { + if (chan->done>need) chan->done-=need; + else chan->done=0; + } + mixer.done-=need; + mixer.needed-=need; + if (mixer.done>mixer.min_needed) { + Bitu diff=mixer.done-mixer.min_needed; + mixer.tick_add=((mixer.freq-(diff>>2)) << MIXER_SHIFT)/1000; + } else { + Bitu diff=mixer.needed-mixer.done; + mixer.tick_add=((mixer.freq+diff*3) << MIXER_SHIFT)/1000; + } + Bit16s * output=(Bit16s *)stream; + while (need--) { + Bits sample=mixer.work[mixer.pos][0]>>MIXER_VOLSHIFT; + *output++=MIXER_CLIP(sample); + mixer.work[mixer.pos][0]=0; + sample=mixer.work[mixer.pos][1]>>MIXER_VOLSHIFT; + *output++=MIXER_CLIP(sample); + mixer.work[mixer.pos][1]=0; + mixer.pos=(mixer.pos+1)&MIXER_BUFMASK; } - mixer.out.read+=(len/MIXER_SSIZE); - if (mixer.out.read>=MIXER_BUFSIZE) mixer.out.read-=MIXER_BUFSIZE; } static void MIXER_WaveEvent(void) { - Bitu last=0;char file_name[CROSS_LEN]; - DIR * dir;struct dirent * dir_ent; - /* Check for previously opened wave file */ if (mixer.wave.handle) { - LOG_MSG("Stopped recording"); + LOG_MSG("Stopped capturing wave output."); /* Write last piece of audio in buffer */ - fwrite(mixer.wave.buf,1,mixer.wave.used,mixer.wave.handle); + fwrite(mixer.wave.buf,1,mixer.wave.used*MIXER_SSIZE,mixer.wave.handle); + mixer.wave.length+=mixer.wave.used*MIXER_SSIZE; /* Fill in the header with useful information */ - host_writed(&wavheader[4],mixer.wave.length+sizeof(wavheader)-8); + host_writed(&wavheader[0x04],mixer.wave.length+sizeof(wavheader)-8); host_writed(&wavheader[0x18],mixer.freq); host_writed(&wavheader[0x1C],mixer.freq*4); host_writed(&wavheader[0x28],mixer.wave.length); @@ -266,42 +360,76 @@ static void MIXER_WaveEvent(void) { fwrite(wavheader,1,sizeof(wavheader),mixer.wave.handle); fclose(mixer.wave.handle); mixer.wave.handle=0; - return; + } else { + mixer.wave.handle=OpenCaptureFile("Wave Output",".wav"); + if (!mixer.wave.handle) return; + mixer.wave.length=0; + mixer.wave.used=0; + fwrite(wavheader,1,sizeof(wavheader),mixer.wave.handle); } - /* Find a filename to open */ - dir=opendir(mixer.wave.dir); - if (!dir) { - LOG_MSG("Can't open waveout dir %s",mixer.wave.dir); - return; - } - while ((dir_ent=readdir(dir))) { - char tempname[CROSS_LEN]; - strcpy(tempname,dir_ent->d_name); - char * test=strstr(tempname,".wav"); - if (!test) continue; - *test=0; - if (strlen(tempname)<5) continue; - if (strncmp(tempname,"wave",4)!=0) continue; - Bitu num=atoi(&tempname[4]); - if (num>=last) last=num+1; - } - closedir(dir); - sprintf(file_name,"%s%cwave%04d.wav",mixer.wave.dir,CROSS_FILESPLIT,last); - /* Open the actual file */ - mixer.wave.handle=fopen(file_name,"wb"); - if (!mixer.wave.handle) { - LOG_MSG("Can't open file %s for waveout",file_name); - return; - } - mixer.wave.length=0; - LOG_MSG("Started recording to file %s",file_name); - fwrite(wavheader,1,sizeof(wavheader),mixer.wave.handle); } static void MIXER_Stop(Section* sec) { if (mixer.wave.handle) MIXER_WaveEvent(); } +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 ShowVolume(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 Run(void) { + 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]); + } +}; + +static void MIXER_ProgramStart(Program * * make) { + *make=new MIXER; +} + void MIXER_Init(Section* sec) { sec->AddDestroyFunction(&MIXER_Stop); Section_prop * section=static_cast(sec); @@ -309,15 +437,16 @@ void MIXER_Init(Section* sec) { mixer.freq=section->Get_int("rate"); mixer.nosound=section->Get_bool("nosound"); mixer.blocksize=section->Get_int("blocksize"); - mixer.wave.dir=section->Get_string("wavedir"); /* Initialize the internal stuff */ mixer.channels=0; - mixer.out.write=0; - mixer.out.read=0; - memset(mixer.out.data,0,sizeof(mixer.out.data)); + mixer.pos=0; + mixer.done=0; + memset(mixer.work,0,sizeof(mixer.work)); mixer.wave.handle=0; mixer.wave.used=0; + mixer.mastervol[0]=1.0f; + mixer.mastervol[1]=1.0f; /* Start the Mixer using SDL Sound at 22 khz */ SDL_AudioSpec spec; @@ -334,17 +463,23 @@ void MIXER_Init(Section* sec) { if (mixer.nosound) { LOG_MSG("MIXER:No Sound Mode Selected."); mixer.tick_add=((mixer.freq) << MIXER_SHIFT)/1000; - TIMER_RegisterTickHandler(MIXER_Mix_NoSound); + TIMER_AddTickHandler(MIXER_Mix_NoSound); } else if (SDL_OpenAudio(&spec, &obtained) <0 ) { LOG_MSG("MIXER:Can't open audio: %s , running in nosound mode.",SDL_GetError()); mixer.tick_add=((mixer.freq) << MIXER_SHIFT)/1000; - TIMER_RegisterTickHandler(MIXER_Mix_NoSound); + TIMER_AddTickHandler(MIXER_Mix_NoSound); } else { mixer.freq=obtained.freq; mixer.blocksize=obtained.samples; - mixer.tick_add=((mixer.freq+100) << MIXER_SHIFT)/1000; - TIMER_RegisterTickHandler(MIXER_Mix); + mixer.tick_add=(mixer.freq << MIXER_SHIFT)/1000; + TIMER_AddTickHandler(MIXER_Mix); SDL_PauseAudio(0); } - KEYBOARD_AddEvent(KBD_f6,KBD_MOD_CTRL,MIXER_WaveEvent); + 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.needed=mixer.min_needed+1; + MAPPER_AddHandler(MIXER_WaveEvent,MK_f6,MMOD1,"recwave","Rec Wave"); + PROGRAMS_MakeFile("MIXER.COM",MIXER_ProgramStart); } + diff --git a/src/hardware/mpu401.cpp b/src/hardware/mpu401.cpp index d68e0a3..d318560 100644 --- a/src/hardware/mpu401.cpp +++ b/src/hardware/mpu401.cpp @@ -1,19 +1,24 @@ #include #include "dosbox.h" #include "inout.h" -#include "mixer.h" -#include "dma.h" #include "pic.h" -#include "hardware.h" #include "setup.h" -#include "programs.h" +#include "cpu.h" +#include "callback.h" void MIDI_RawOutByte(Bit8u data); bool MIDI_Available(void); -#define MPU_QUEUE 32 -enum MpuMode { M_UART,M_INTELLIGENT } ; +static Bitu call_irq9; +static void MPU401_Event(Bitu); +static void MPU401_Reset(void); +static void MPU401_EOIHandler(void); +#define MPU_QUEUE 32 +#define TIMECONSTANT (60000000/1000.0f) + +enum MpuMode { M_UART,M_INTELLIGENT } ; +enum MpuDataType {OVERFLOW,MARK,MIDI_SYS,MIDI_NORM,COMMAND}; ///////////////////////////////////////////////////////////////////////////// // I/O @@ -45,6 +50,9 @@ enum MpuMode { M_UART,M_INTELLIGENT } ; Larry Troxler, Compuserve 73520,1736 + + 15.02.2004: updated and implemented intelligent mode + ****************************************************************************/ // Start/Stop Commands @@ -64,6 +72,7 @@ enum MpuMode { M_UART,M_INTELLIGENT } ; #define CMD_DISABLE_ALL_NOTES_OFF 0x30 #define CMD_DISABLE_REAL_TIME_OUT 0x32 +#define CMD_DISABLE_ALL_THRU_OFF 0x33 #define CMD_TIMING_BYTE_ALWAYS 0x34 #define CMD_MODE_MESS_ON 0x35 #define CMD_EXCLUSIVE_THRU_ON 0x37 @@ -116,21 +125,21 @@ enum MpuMode { M_UART,M_INTELLIGENT } ; #define CMD_RELATIVE_TEMPO_GRADUATION 0xe2 #define CMD_MIDI_METRONOME 0xe4 #define CMD_MEASURE_LENGTH 0xe6 -#define CMD_INTERNAL_CLOCK_LENGTH_TO_HOST /* ? */ +#define CMD_INTERNAL_CLOCK_LENGTH_TO_HOST 0xe7 #define CMD_ACTIVE_TRACK_MASK 0xec #define CMD_SEND_PLAY_COUNTER_MASK 0xed #define CMD_MIDI_CHANNEL_MASK_LO 0xee #define CMD_MIDI_CHANNEL_MASK_HI 0xef -#define CMD_EOX 0xf7 -#define CMD_TIMING_OVERFLOW 0xf8 -#define CMD_MPU_MARK 0xfc +#define CMD_EOX 0xf7 +#define CMD_TIMING_OVERFLOW 0xf8 +#define CMD_MPU_MARK 0xfc #define CMD_RESET 0xff // Commands that return data -#define CMD_REQUEST_PLAY_COUNTER 0xa0 -#define CMD_REQUEST_AND_CLEAR_PLAY_COUNTER 0xab +#define CMD_REQUEST_PLAY_COUNTER 0xa0 /* + track # */ +#define CMD_REQUEST_AND_CLEAR_REC_COUNTER 0xab #define CMD_REQUEST_VERSION 0xac #define CMD_REQUEST_REVISION 0xad #define CMD_REQUEST_TEMPO 0xaf @@ -140,21 +149,60 @@ enum MpuMode { M_UART,M_INTELLIGENT } ; // Messages ///////////////////////////////////////////////////////////////////////////// +#define MSG_TIMING_OVERFLOW 0xf8 +#define MSG_ALL_END 0xfc +#define MSG_CLOCK_TO_HOST 0xfd #define MSG_CMD_ACK 0xfe +#define MSG_REQUEST_DATA 0xf0 +#define MSG_REQUEST_COMMAND 0xf9 +#define MPU_VERSION 0x15 +#define MPU_REVISION 0x01 +///////////////////////////////////////////////////////////////////////////// static struct { + bool intelligent; MpuMode mode; + Bitu irq; Bit8u queue[MPU_QUEUE]; Bitu queue_pos,queue_used; - Bitu cmd; - + struct track { + Bits counter; + Bit8u value[8]; + Bit8u vlength,length; + MpuDataType type; + } playbuf[8],condbuf; + struct { + bool conductor,cond_req,cond_set; + bool allnotes,realtime,allthru; + bool playing; + bool wsd,wsm,wsd_start; + bool midi_thru; + 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; + } 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.queue_used=MPU_QUEUE) mpu.queue_pos-=MPU_QUEUE; if (pos>=MPU_QUEUE) pos-=MPU_QUEUE; mpu.queue_used++; mpu.queue[pos]=data; @@ -166,68 +214,529 @@ static void ClrQueue(void) { mpu.queue_pos=0; } -static void MPU401_WriteCommand(Bit32u port,Bit8u val) { - switch (val) { - case CMD_UART_MODE: /* Switch to UART Mode */ - mpu.mode=M_UART; - QueueByte(MSG_CMD_ACK); - break; - case CMD_RESET: /* Reset Commmand */ - mpu.mode=M_INTELLIGENT; - ClrQueue(); - QueueByte(MSG_CMD_ACK); - break; - - case CMD_REQUEST_TO_SEND_DATA: - case CMD_REQUEST_TO_SEND_SYSTEM_MSG: - QueueByte(MSG_CMD_ACK); - break; - - default: - LOG(LOG_MISC,LOG_NORMAL)("MPU401:Unhandled command %X",val); - QueueByte(MSG_CMD_ACK); - break; - } - -} - -static Bit8u MPU401_ReadStatus(Bit32u port) { - - Bit8u ret=0x3f; /* Bith 6 and 7 clear */ +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_WriteData(Bit32u port,Bit8u val) { - MIDI_RawOutByte(val); +static void MPU401_WriteCommand(Bitu port,Bitu val,Bitu iolen) { + LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Command %x",val); + if (val && val<=0x2f) { + switch (val&3) { + 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); + } + ClrQueue(); + break; + case 0x8: /* Play */ + mpu.state.playing=true; + PIC_RemoveEvents(MPU401_Event); + PIC_AddEvent(MPU401_Event,TIMECONSTANT/(mpu.clock.tempo*mpu.clock.timebase)); + mpu.state.irq_pending=false; + 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) { /* Request to send data */ + mpu.state.channel=val&7; + mpu.state.wsd=true; + mpu.state.wsm=false; + mpu.state.wsd_start=true; + } + else + switch (val) { + case CMD_REQUEST_TO_SEND_SYSTEM_MSG: + mpu.state.wsd=false; + mpu.state.wsm=true; + mpu.state.wsd_start=true; + break; + case CMD_CONDUCTOR_ON: + mpu.state.cond_set=true; + break; + case CMD_CONDUCTOR_OFF: + mpu.state.cond_set=false; + break; + case CMD_CLOCK_TO_HOST_OFF: + mpu.clock.clock_to_host=false; + break; + case CMD_CLOCK_TO_HOST_ON: + mpu.clock.clock_to_host=true; + break; + case CMD_REAL_TIME_AFFECTION_OFF: + break; + case CMD_REAL_TIME_AFFECTION_ON: + LOG(LOG_MISC,LOG_ERROR)("MPU401:Unimplemented:Realtime affection:ON"); + break; + case CMD_MIDI_THRU_OFF: + mpu.state.midi_thru=false; + break; + case CMD_MIDI_THRU_ON: + mpu.state.midi_thru=true; + break; + case CMD_TIMEBASE_48: /* Internal clock resolution per beat */ + mpu.clock.timebase=48; + break; + case CMD_TIMEBASE_72: + mpu.clock.timebase=72; + break; + case CMD_TIMEBASE_96: + mpu.clock.timebase=96; + break; + case CMD_TIMEBASE_120: + mpu.clock.timebase=120; + break; + case CMD_TIMEBASE_144: + mpu.clock.timebase=144; + break; + case CMD_TIMEBASE_168: + mpu.clock.timebase=168; + break; + case CMD_TIMEBASE_192: + mpu.clock.timebase=192; + break; + /* Commands with data byte */ + case CMD_MIDI_METRONOME: + case CMD_MEASURE_LENGTH: + case CMD_RELATIVE_TEMPO: + case CMD_SET_TEMPO: + case CMD_RELATIVE_TEMPO_GRADUATION: + case CMD_INTERNAL_CLOCK_LENGTH_TO_HOST: + case CMD_ACTIVE_TRACK_MASK: + case CMD_SEND_PLAY_COUNTER_MASK: + case CMD_MIDI_CHANNEL_MASK_LO: + case CMD_MIDI_CHANNEL_MASK_HI: + mpu.state.command_byte=val; + break; + /* Commands Returning Data */ + case CMD_REQUEST_VERSION: + QueueByte(MSG_CMD_ACK); + QueueByte(MPU_VERSION); + return; + case CMD_REQUEST_REVISION: + QueueByte(MSG_CMD_ACK); + QueueByte(MPU_REVISION); + return; + case CMD_REQUEST_TEMPO: + QueueByte(MSG_CMD_ACK); + QueueByte(mpu.clock.tempo); + return; + case CMD_REQUEST_AND_CLEAR_REC_COUNTER: + QueueByte(MSG_CMD_ACK); + QueueByte(0); + return; + case CMD_RESET_RELATIVE_TEMPO: + mpu.clock.tempo_rel=40; + break; + case CMD_CLEAR_PLAY_MAP: + mpu.state.tmask=0; + case CMD_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=OVERFLOW; + } + mpu.condbuf.counter=0; + mpu.condbuf.type=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; + break; + case CMD_RESET: /* Reset MPU401 */ + MPU401_Reset(); + if (mpu.intelligent) { + QueueByte(MSG_CMD_ACK); //additional ACK for interrupt routine + mpu.state.irq_pending=true; + PIC_ActivateIRQ(mpu.irq); //UNDOCUMENTED + } + break; + /* Initialization Commands */ + case CMD_UART_MODE: + mpu.mode=M_UART; + break; + case CMD_DISABLE_ALL_NOTES_OFF: + mpu.state.allnotes=false; + break; + case CMD_DISABLE_REAL_TIME_OUT: + mpu.state.realtime=false; + break; + case CMD_DISABLE_ALL_THRU_OFF: + mpu.state.allthru=false; + break; + default: + LOG(LOG_MISC,LOG_NORMAL)("MPU-401:Unhandled command %X",val); + } + QueueByte(MSG_CMD_ACK); } -static Bit8u MPU401_ReadData(Bit32u port) { +static Bitu MPU401_ReadData(Bitu port,Bitu iolen) { Bit8u ret=MSG_CMD_ACK; if (mpu.queue_used) { ret=mpu.queue[mpu.queue_pos]; - mpu.queue_pos++; if (mpu.queue_pos>=MPU_QUEUE) mpu.queue_pos-=MPU_QUEUE; - mpu.queue_used--; + mpu.queue_pos++;mpu.queue_used--; + } + if (ret>=0xf0 && ret<=0xf7) { + mpu.state.channel=ret&7; + mpu.state.data_onoff=0; + mpu.state.cond_req=false; + } + if (ret==MSG_REQUEST_COMMAND) { + mpu.state.data_onoff=0; + mpu.state.cond_req=true; + } + if (ret==MSG_ALL_END || ret==MSG_CLOCK_TO_HOST) { + 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;} + if (mpu.state.command_byte) MPU401_EOIHandler(); /* S101, Time Quest */ + switch (mpu.state.command_byte) { + case 0: + break; + case CMD_SET_TEMPO: + mpu.state.command_byte=0; + mpu.clock.tempo=val; + return; + case CMD_INTERNAL_CLOCK_LENGTH_TO_HOST: + mpu.state.command_byte=0; + mpu.clock.cth_rate=val>>2; + return; + case CMD_ACTIVE_TRACK_MASK: + mpu.state.command_byte=0; + mpu.state.tmask=val; + return; + case CMD_SEND_PLAY_COUNTER_MASK: + mpu.state.command_byte=0; + mpu.state.cmask=val; + return; + case CMD_MIDI_CHANNEL_MASK_LO: + mpu.state.command_byte=0; + mpu.state.midi_mask&=0xff00; + mpu.state.midi_mask|=val; + return; + case CMD_MIDI_CHANNEL_MASK_HI: + mpu.state.command_byte=0; + mpu.state.midi_mask&=0x00ff; + mpu.state.midi_mask|=((Bit16u)val)<<8; + return; + //case CMD_RELATIVE_TEMPO: + //case CMD_RELATIVE_TEMPO_GRADUATION: + //case CMD_MIDI_METRONOME: + //case CMD_MIDI_MEASURE: + default: + mpu.state.command_byte=0; + return; + } + static Bitu length,cnt,posd; + if (mpu.state.wsd) { + 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; + return; + default: /* MIDI with running status */ + cnt++; + MIDI_RawOutByte(mpu.playbuf[mpu.state.channel].value[0]); + } + } + if (cnt0xf7) { + mpu.playbuf[mpu.state.channel].type=MARK; + length=1; + } else { + LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal message"); + mpu.playbuf[mpu.state.channel].type=MIDI_SYS; + length=1; + } + break; + case 0xc0: case 0xd0: /* MIDI Message */ + mpu.playbuf[mpu.state.channel].type=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=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=MIDI_NORM; + length=mpu.playbuf[mpu.state.channel].length; + break; + } + } + 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 OVERFLOW: + break; + case MARK: + val=mpu.playbuf[chan].value[0]; + 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,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; + ClrQueue(); + Bitu i=0; + do { + if (mpu.state.req_mask&(1<=500) { + CPU_CycleLeft+=CPU_Cycles-500; + CPU_Cycles=500; + } + #endif + PIC_ActivateIRQ(mpu.irq); + mpu.state.irq_pending=true; +} + +static Bitu INT71_Handler() { + CALLBACK_RunRealInt(0xa); + IO_Write(0xa0,0x61); +return CBRET_NONE; +} + +static void MPU401_Reset(void) { + PIC_DeActivateIRQ(mpu.irq); + mpu.mode=(mpu.intelligent ? M_INTELLIGENT : M_UART); + mpu.state.wsd=false; + mpu.state.wsm=false; + mpu.state.conductor=false; + mpu.state.cond_req=false; + mpu.state.cond_set=false; + mpu.state.allnotes=true; + mpu.state.allthru=true; + mpu.state.realtime=true; + mpu.state.playing=false; + mpu.state.run_irq=false; + mpu.state.irq_pending=false; + mpu.state.cmask=0xff; + mpu.state.amask=mpu.state.tmask=0; + mpu.state.midi_mask=0xffff; + mpu.state.data_onoff=0; + mpu.state.command_byte=0; + mpu.clock.tempo=mpu.clock.old_tempo=100; + mpu.clock.timebase=mpu.clock.old_timebase=120; + mpu.clock.tempo_rel=mpu.clock.old_tempo_rel=40; + mpu.clock.tempo_grad=0; + mpu.clock.clock_to_host=false; + mpu.clock.cth_rate=60; + mpu.clock.cth_counter=0; + ClrQueue(); + mpu.state.req_mask=0; + mpu.condbuf.counter=0; + mpu.condbuf.type=OVERFLOW; + for (Bitu i=0;i<8;i++) {mpu.playbuf[i].type=OVERFLOW;mpu.playbuf[i].counter=0;} +} void MPU401_Init(Section* sec) { + call_irq9=CALLBACK_Allocate(); //allocate handler for irq 9 + CALLBACK_Setup(call_irq9,&INT71_Handler,CB_IRET); + RealSetVec(0x71,CALLBACK_RealPointer(call_irq9)); + Section_prop * section=static_cast(sec); if(!section->Get_bool("mpu401")) return; if (!MIDI_Available()) return; - IO_RegisterWriteHandler(0x330,&MPU401_WriteData,"MPU401"); - IO_RegisterWriteHandler(0x331,&MPU401_WriteCommand,"MPU401"); - IO_RegisterReadHandler(0x330,&MPU401_ReadData,"MPU401"); - IO_RegisterReadHandler(0x331,&MPU401_ReadStatus,"MPU401"); + IO_RegisterWriteHandler(0x330,&MPU401_WriteData,IO_MB); + IO_RegisterWriteHandler(0x331,&MPU401_WriteCommand,IO_MB); + IO_RegisterReadHandler(0x330,&MPU401_ReadData,IO_MB); + IO_RegisterReadHandler(0x331,&MPU401_ReadStatus,IO_MB); mpu.queue_used=0; mpu.queue_pos=0; + mpu.mode=M_UART; + + if (!(mpu.intelligent=section->Get_bool("intelligent"))) return; + mpu.irq=2; + MPU401_Reset(); } - - diff --git a/src/hardware/pcspeaker.cpp b/src/hardware/pcspeaker.cpp index 6862212..732d332 100644 --- a/src/hardware/pcspeaker.cpp +++ b/src/hardware/pcspeaker.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -28,202 +28,294 @@ #define PI 3.14159265358979323846 #endif -#define SPKR_BUF 4096 -#define SPKR_RATE 22050 +#define SPKR_ENTRIES 1024 #define SPKR_VOLUME 5000 +//#define SPKR_SHIFT 8 +#define SPKR_SPEED (float)((SPKR_VOLUME*2)/0.070f) -#define SPKR_SHIFT 10 - -enum SPKR_MODE { - MODE_NONE,MODE_WAVE,MODE_DELAY,MODE_ONOFF,MODE_REAL, +enum SPKR_MODES { + SPKR_OFF,SPKR_ON,SPKR_PIT_OFF,SPKR_PIT_ON }; -/* TODO - Maybe interpolate at the moment we switch between on/off - Keep track of postion of speaker conus in ONOFF mode -*/ +struct DelayEntry { + float index; + float vol; +}; static struct { - Bit16s volume; - MIXER_Channel * chan; - Bit16u buffer[SPKR_BUF]; - SPKR_MODE mode; - SPKR_MODE pit_mode; - struct { - Bit16s buf[SPKR_BUF]; - Bitu used; - } real; - struct { - Bitu index; - struct { - Bitu max,half; - } count,new_count; - } wave; - struct { - Bit16s buf[SPKR_BUF]; - Bitu pos; - } out; - struct { - Bitu index; - Bitu max; - } delay; - struct { - Bitu vol; - Bitu rate; - Bitu rate_conv; - Bitu tick_add; - } hw; - bool onoff,enabled; - Bitu buf_pos; + 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; + DelayEntry entries[SPKR_ENTRIES]; + Bitu used; } spkr; -static void GenerateSound(Bitu size) { - while (spkr.out.pos=spkr.wave.count.max) { - *stream++=+spkr.volume; - spkr.wave.index-=spkr.wave.count.max; - spkr.wave.count.max=spkr.wave.new_count.max; - spkr.wave.count.half=spkr.wave.new_count.half; - } else if (spkr.wave.index>spkr.wave.count.half) { - *stream++=-spkr.volume; - } else { - *stream++=+spkr.volume; - } +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; } - spkr.out.pos+=samples; - } - break; - case MODE_ONOFF: - { - Bit16s val=spkr.onoff ? spkr.volume : -spkr.volume; - for (Bitu i=0;i> 16]; - buf_pos+=buf_add; + } 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; } - spkr.out.pos+=samples; - break; } - case MODE_DELAY: - { - for (Bitu i=0;i0) { + /* 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; + } 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) { - Bitu index=PIC_Index(); - Bitu len=(spkr.hw.rate_conv*index)>>16; - if (spkr.mode==MODE_NONE) MIXER_Enable(spkr.chan,true); + if (!spkr.last_ticks) { + 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.enabled) return; - if (cntr>72) cntr=72; - if (spkr.mode!=MODE_REAL) GenerateSound(len); - spkr.pit_mode=MODE_REAL; - if (spkr.real.used80) { + 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 */ - GenerateSound(len); - spkr.pit_mode=MODE_WAVE; - spkr.wave.new_count.max=cntr << SPKR_SHIFT; - spkr.wave.new_count.half=(cntr/2) << SPKR_SHIFT; + if (cntr<=40) { + /* Makes DIGGER sound better */ + spkr.pit_last=0; + spkr.pit_mode=0; + return; + } + spkr.pit_new_max=(1000.0f/PIT_TICK_RATE)*cntr; + spkr.pit_new_half=spkr.pit_new_max/2; break; - case 4: /* Keep high till end of count */ - GenerateSound(len); - spkr.delay.max=cntr << SPKR_SHIFT; - spkr.delay.index=0; - spkr.pit_mode=MODE_DELAY; + case 4: /* Software triggered strobe */ + spkr.pit_last=SPKR_VOLUME; + AddDelayEntry(newindex,spkr.pit_last); + spkr.pit_index=0; + spkr.pit_max=(1000.0f/PIT_TICK_RATE)*cntr; break; + default: +#if C_DEBUG + LOG_MSG("Unhandled speaker mode %d",mode); +#endif + return; } - if (spkr.enabled) spkr.mode=spkr.pit_mode; + spkr.pit_mode=mode; } void PCSPEAKER_SetType(Bitu mode) { - Bitu index=PIC_Index(); - Bitu len=(spkr.hw.rate_conv*index)>>16; - GenerateSound(len); - if (spkr.mode==MODE_NONE) MIXER_Enable(spkr.chan,true); + if (!spkr.last_ticks) { + spkr.chan->Enable(true); + spkr.last_index=0; + } + spkr.last_ticks=PIC_Ticks; + float newindex=PIC_TickIndex(); + ForwardPIT(newindex); switch (mode) { case 0: - if (spkr.mode==MODE_ONOFF && spkr.onoff) spkr.onoff=false; - else spkr.mode=MODE_NONE; - spkr.enabled=false; + spkr.mode=SPKR_OFF; + AddDelayEntry(newindex,-SPKR_VOLUME); break; case 1: - spkr.mode=MODE_ONOFF; - spkr.enabled=false; - spkr.onoff=false; + spkr.mode=SPKR_PIT_OFF; + AddDelayEntry(newindex,-SPKR_VOLUME); break; case 2: - spkr.enabled=false; - spkr.onoff=true; - spkr.mode=MODE_ONOFF; + spkr.mode=SPKR_ON; + AddDelayEntry(newindex,SPKR_VOLUME); break; case 3: - spkr.onoff=true; - spkr.enabled=true; - spkr.mode=spkr.pit_mode; + if (spkr.mode!=SPKR_PIT_ON) { + AddDelayEntry(newindex,spkr.pit_last); + } + spkr.mode=SPKR_PIT_ON; break; }; } -static void PCSPEAKER_CallBack(Bit8u * stream,Bit32u len) { - if (spkr.out.posAddSamples_m16(len,(Bit16s*)MixTemp); + if ((spkr.last_ticks+10000)Enable(false); + } } void PCSPEAKER_Init(Section* sec) { Section_prop * section=static_cast(sec); if(!section->Get_bool("pcspeaker")) return; - spkr.volume=SPKR_VOLUME; - spkr.mode=MODE_NONE; - spkr.pit_mode=MODE_WAVE; - spkr.real.used=0; - spkr.out.pos=0; - spkr.onoff=false; -// spkr.hw.vol=section->Get_int("volume"); - spkr.hw.rate=section->Get_int("pcrate"); - spkr.hw.rate_conv=(spkr.hw.rate<<16)/1000000; - spkr.hw.tick_add=(Bitu)((double)PIT_TICK_RATE*(double)(1 << SPKR_SHIFT)/(double)spkr.hw.rate); - spkr.wave.index=0; - spkr.wave.count.max=spkr.wave.new_count.max=0x10000 << SPKR_SHIFT; - spkr.wave.count.half=spkr.wave.new_count.half=(0x10000 << SPKR_SHIFT)/2; - + 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.used=0; /* Register the sound channel */ - spkr.chan=MIXER_AddChannel(&PCSPEAKER_CallBack,spkr.hw.rate,"PC-SPEAKER"); - MIXER_Enable(spkr.chan,false); - MIXER_SetMode(spkr.chan,MIXER_16MONO); + spkr.chan=MIXER_AddChannel(&PCSPEAKER_CallBack,spkr.rate,"SPKR"); } diff --git a/src/hardware/pic.cpp b/src/hardware/pic.cpp index a5633c7..f7d1aef 100644 --- a/src/hardware/pic.cpp +++ b/src/hardware/pic.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.16 2004/01/10 14:03:35 qbix79 Exp $ */ +/* $Id: pic.cpp,v 1.24 2004/09/10 22:15:20 harekiet Exp $ */ #include @@ -33,8 +33,6 @@ struct IRQ_Block { bool active; bool inservice; Bitu vector; - char * name; - PIC_EOIHandler * handler; }; struct PIC_Controller { @@ -44,6 +42,7 @@ struct PIC_Controller { Bitu active; Bitu inservice; + bool special; bool auto_eoi; bool request_issr; Bit8u vector_base; @@ -58,7 +57,8 @@ static IRQ_Block irqs[16]; static PIC_Controller pics[2]; struct PICEntry { - Bitu index; + float index; + Bitu value; PIC_EventHandler event; PICEntry * next; }; @@ -69,12 +69,12 @@ static struct { PICEntry * next_entry; } pic; -static void write_command(Bit32u port,Bit8u val) { +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; Bit16u IRQ_priority_table[16] = - { 0,1,8,9,10,11,12,13,14,15,2,3,4,5,6,7 }; + { 0,1,2,9,10,11,12,13,14,15,3,4,5,6,7,8 }; switch (val) { case 0x0A: /* select read interrupt request register */ pic->request_issr=false; @@ -93,7 +93,6 @@ static void write_command(Bit32u port,Bit8u val) { case 0x20:case 0x21:case 0x22:case 0x23:case 0x24:case 0x25:case 0x26:case 0x27: if (PIC_IRQActive<(irq_base+8)) { irqs[PIC_IRQActive].inservice=false; - if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler(); PIC_IRQActive=PIC_NOIRQ; for (i=0; i<=15; i++){ if(irqs[IRQ_priority_table[i]].inservice) { @@ -103,11 +102,15 @@ static void write_command(Bit32u port,Bit8u val) { } } //TODO Warnings? break; + case 0x4a: /* OCW3 select read interrupt request register */ + LOG(LOG_PIC,LOG_NORMAL)("port %X : special OFF",port); + pic->special = false; + pic->request_issr = false; + break; case 0x60:case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:case 0x67: /* Spefific EOI 0-7 */ if (PIC_IRQActive==(irq_base+val-0x60U)) { irqs[PIC_IRQActive].inservice=false; - if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler(); PIC_IRQActive=PIC_NOIRQ; for (i=0; i<=15; i++) { if (irqs[IRQ_priority_table[i]].inservice) { @@ -117,6 +120,15 @@ static void write_command(Bit32u port,Bit8u val) { } }//TODO Warnings? break; + case 0x68:/* OCW3 select */ + pic->special=true; + LOG(LOG_PIC,LOG_NORMAL)("port %X : special ON",port); + break; + case 0x6b: /* OCW3 select read interrupt in-service register */ + LOG(LOG_PIC,LOG_NORMAL)("port %X : special ON",port); + pic->special = true; + pic->request_issr = true; + break; case 0xC0:case 0xC1:case 0xC2:case 0xC3:case 0xC4:case 0xC5:case 0xC6:case 0xC7: /* Priority order, no need for it */ break; @@ -125,7 +137,7 @@ static void write_command(Bit32u port,Bit8u val) { } } -static void write_data(Bit32u port,Bit8u val) { +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; @@ -175,7 +187,7 @@ static void write_data(Bit32u port,Bit8u val) { } -static Bit8u read_command(Bit32u port) { +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; @@ -193,7 +205,7 @@ static Bit8u read_command(Bit32u port) { return ret; } -static Bit8u read_data(Bit32u port) { +static Bitu read_data(Bitu port,Bitu iolen) { PIC_Controller * pic=&pics[port==0x21 ? 0 : 1]; Bitu irq_base=(port==0x21) ? 0 : 8; Bitu i;Bit8u ret=0;Bit8u b=1; @@ -204,20 +216,6 @@ static Bit8u read_data(Bit32u port) { return ret; } -void PIC_RegisterIRQ(Bitu 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(Bitu 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(Bitu irq) { if (irq<16) { @@ -240,22 +238,21 @@ void PIC_runIRQs(void) { if (!GETFLAG(IF)) return; if (!PIC_IRQCheck) return; Bit16u IRQ_priority_lookup[17] = - { 0,1,10,11,12,13,14,15,2,3,4,5,6,7,8,9,16 }; + { 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; for (i=0;i<=15;i++) { - if (IRQ_priority_lookup[i]index-PIC_Index()); + Bits cycles=PIC_MakeCycles(pic.next_entry->index-PIC_TickIndex()); if (cyclesindex=index; + entry->index=delay+PIC_TickIndex();; entry->event=handler; + entry->value=val; pic.free_entry=pic.free_entry->next; AddEntry(entry); } @@ -353,11 +350,11 @@ bool PIC_RunQueue(void) { return false; } /* Check the queue for an entry */ - Bitu index=PIC_Index(); + double index=PIC_TickIndex(); while (pic.next_entry && pic.next_entry->index<=index) { PICEntry * entry=pic.next_entry; pic.next_entry=entry->next; - (entry->event)(); + (entry->event)(entry->value); /* Put the entry in the free list */ entry->next=pic.free_entry; pic.free_entry=entry; @@ -378,90 +375,53 @@ bool PIC_RunQueue(void) { } /* The TIMER Part */ - -enum { T_TICK,T_MICRO,T_DELAY}; - -struct Timer { - Bitu type; - union { - struct { - TIMER_TickHandler handler; - } tick; - struct{ - Bits left; - Bits total; - TIMER_MicroHandler handler; - } micro; - }; +struct TickerBlock { + TIMER_TickHandler handler; + TickerBlock * next; }; -static Timer * first_timer=0; -static std::list Timers; +static TickerBlock * firstticker=0; -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; - Timers.push_front(new_timer); - TIMER_SetNewMicro(new_timer,micro); - 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.total=micro; - Bitu index=PIC_Index(); - while ((1000-index)>micro) { - PIC_AddEvent(timer->micro.handler,micro); - micro+=micro; - index+=micro; +void TIMER_DelTickHandler(TIMER_TickHandler handler) { + TickerBlock * ticker=firstticker; + TickerBlock * * where=&firstticker; + while (ticker) { + if (ticker->handler==handler) { + *where=ticker->next; + delete ticker; + return; + } + where=&ticker->next; + ticker=ticker->next; } - timer->micro.left=timer->micro.total-(1000-index); +} + +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 irq's and lower their index with 1000 */ + /* Go through the list of scheduled events and lower their index with 1000 */ PICEntry * entry=pic.next_entry; while (entry) { - if (entry->index>1000) entry->index-=1000; + if (entry->index>=1) entry->index-=1; else entry->index=0; entry=entry->next; } - Bits index; - /* Check if there are timer handlers that need to be called */ - std::list::iterator i; - for(i=Timers.begin(); i != Timers.end(); ++i) { - Timer * timers=(*i); - switch (timers->type) { - case T_TICK: - timers->tick.handler(1); - break; - case T_MICRO: - index=1000; - while (index>=timers->micro.left) { - PIC_AddEvent(timers->micro.handler,timers->micro.left); - index-=timers->micro.left; - timers->micro.left=timers->micro.total; - } - timers->micro.left-=index; - break; - default: - E_Exit("TIMER:Illegal handler type"); - } + /* Call our list of ticker handlers */ + TickerBlock * ticker=firstticker; + while (ticker) { + TickerBlock * nextticker=ticker->next; + ticker->handler(); + ticker=nextticker; } } @@ -480,6 +440,7 @@ void PIC_Init(Section* sec) { pics[i].auto_eoi=false; pics[i].auto_eoi=false; pics[i].request_issr=false; + pics[i].special=false; pics[i].icw_index=0; pics[i].icw_words=0; } @@ -497,14 +458,14 @@ void PIC_Init(Section* sec) { irqs[1].masked=false; /* Enable Keyboard IRQ */ irqs[8].masked=false; /* Enable RTC IRQ */ /* irqs[12].masked=false; moved to mouse.cpp */ /* Enable Mouse IRQ */ - IO_RegisterReadHandler(0x20,read_command,"Master PIC Command"); - IO_RegisterReadHandler(0x21,read_data,"Master PIC Data"); - IO_RegisterWriteHandler(0x20,write_command,"Master PIC Command"); - IO_RegisterWriteHandler(0x21,write_data,"Master PIC Data"); - IO_RegisterReadHandler(0xa0,read_command,"Slave PIC Command"); - IO_RegisterReadHandler(0xa1,read_data,"Slave PIC Data"); - IO_RegisterWriteHandler(0xa0,write_command,"Slave PIC Command"); - IO_RegisterWriteHandler(0xa1,write_data,"Slave PIC Data"); + IO_RegisterReadHandler(0x20,read_command,IO_MB); + IO_RegisterReadHandler(0x21,read_data,IO_MB); + IO_RegisterWriteHandler(0x20,write_command,IO_MB); + IO_RegisterWriteHandler(0x21,write_data,IO_MB); + IO_RegisterReadHandler(0xa0,read_command,IO_MB); + IO_RegisterReadHandler(0xa1,read_data,IO_MB); + IO_RegisterWriteHandler(0xa0,write_command,IO_MB); + IO_RegisterWriteHandler(0xa1,write_data,IO_MB); /* Initialize the pic queue */ for (i=0;i #include +#include #include "dosbox.h" #include "inout.h" #include "mixer.h" @@ -25,11 +26,10 @@ #include "pic.h" #include "hardware.h" #include "setup.h" +#include "support.h" #include "programs.h" #define SB_PIC_EVENTS 0 -#define SB_NEW_ADPCM 1 - #define DSP_MAJOR 3 #define DSP_MINOR 1 @@ -42,34 +42,36 @@ #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 4096 +#define DMA_BUFSIZE 1024 #define DSP_BUFSIZE 64 -#define DSP_DACSIZE 4096 +#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_SILENCE, - MODE_DMA,MODE_DMA_PAUSE,MODE_DMA_WAIT, + MODE_NONE, + MODE_DAC, + MODE_DMA, + MODE_DMA_PAUSE, + MODE_DMA_MASKED + }; enum DMA_MODES { - DMA_NONE, - DMA_8_SILENCE, - DMA_2_SINGLE, - DMA_3_SINGLE, - DMA_4_SINGLE, - DMA_8_SINGLE,DMA_8_AUTO, - DMA_16_SINGLE,DMA_16_AUTO, + DSP_DMA_NONE, + DSP_DMA_2,DSP_DMA_3,DSP_DMA_4,DSP_DMA_8, + DSP_DMA_16,DSP_DMA_16_ALIASED, }; enum { @@ -77,23 +79,26 @@ enum { }; struct SB_INFO { - Bit16u freq; + Bitu freq; struct { - bool active,stereo,filtered; + bool stereo,sign,autoinit; DMA_MODES mode; - Bitu total,left; - Bitu rate,rate_mul; - Bitu index,add_index; + 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; Bit8u time_constant; - bool use_time_constant; DSP_MODES mode; + SB_TYPES type; + OPL_Mode oplmode; struct { bool pending_8bit; bool pending_16bit; @@ -112,43 +117,33 @@ struct SB_INFO { Bitu write_busy; } dsp; struct { - Bit16s data[DSP_DACSIZE]; + Bit16s data[DSP_DACSIZE+1]; Bitu used; Bit16s last; } dac; struct { Bit8u index; - struct { - Bit8u left,right; - } dac,fm,cda,master,lin; + Bit8u dac[2],fm[2],cda[2],master[2],lin[2]; Bit8u mic; + bool stereo; + bool enabled; + bool filtered; } mixer; struct { - Bits reference,stepsize; + Bit8u reference; + Bits stepsize; + bool haveref; } adpcm; struct { Bitu base; Bit8u irq; - Bit8u dma8; - Bitu rate; - Bitu rate_conv; + Bit8u dma8,dma16; } hw; - struct { - Bit16s buf[SB_BUF_SIZE][2]; - Bitu pos; - } out; - struct { - union { - Bit16s m[DMA_BUFSIZE]; - Bit16s s[DMA_BUFSIZE][2]; - } buf; - Bitu index,add_index; - } tmp; struct { Bits value; Bitu count; } e2; - MIXER_Channel * chan; + MixerChannel * chan; }; @@ -194,12 +189,21 @@ static int E2_incr_table[4][9] = { #endif static void DSP_ChangeMode(DSP_MODES mode); -static void CheckDMAEnd(void); -static void END_DMA_Event(void); +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) { - MIXER_Enable(sb.chan,how); + if (sb.speaker==how) return; sb.speaker=how; + sb.chan->Enable(how); + if (sb.speaker) { + PIC_RemoveEvents(DMA_Silent_Event); + CheckDMAEnd(); + } else { + + } } static INLINE void SB_RaiseIRQ(SB_IRQS type) { @@ -220,60 +224,36 @@ static INLINE void DSP_FlushData(void) { sb.dsp.out.pos=0; } -static void DSP_StopDMA(void) { - DSP_ChangeMode(MODE_NONE); - sb.dma.left=0; -} - -static void DMA_Enable(bool enable) { - sb.dma.active=enable; - if (sb.mode==MODE_DMA_WAIT && enable) { - LOG(LOG_SB,LOG_NORMAL)("DMA enabled,starting output"); - DSP_ChangeMode(MODE_DMA); - CheckDMAEnd(); - return; - } - if (sb.mode==MODE_DMA && !enable) { - DSP_ChangeMode(MODE_DMA_WAIT); - LOG(LOG_SB,LOG_NORMAL)("DMA disabled,stopping output"); - return; +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 511 #define MAX_ADAPTIVE_STEP_SIZE 32767 #define DC_OFFSET_FADE 254 -INLINE Bits Clip(Bits sample) { +static INLINE Bits Clip(Bits sample) { if (sample>MAX_AUDIO) return MAX_AUDIO; if (sample> 1)); - if (adpcm & 1 ) scale = Clip(scale + (stepsize >> 2)); - scale = Clip(stepsize >> 3); - if (adpcm & 8) scale = -scale; - - reference=Clip(scale+((reference * DC_OFFSET_FADE) >> 8)); - // compute the next step size - stepsize=(stepsize * quantize[adpcm & 0x7]) >> 8; - if (stepsize < MIN_ADAPTIVE_STEP_SIZE) stepsize=MIN_ADAPTIVE_STEP_SIZE; - else if (stepsize > MAX_ADAPTIVE_STEP_SIZE) stepsize=MAX_ADAPTIVE_STEP_SIZE; - - return (Bit16s)reference; -} - -#else -INLINE Bit16s decode_ADPCM_4_sample(Bit8u sample,Bits& reference,Bits& scale) { +static INLINE Bit8u decode_ADPCM_4_sample(Bit8u sample,Bit8u & reference,Bits& scale) { static Bits scaleMap[8] = { -2, -1, 0, 0, 1, 1, 1, 1 }; if (sample & 0x08) { @@ -282,12 +262,10 @@ INLINE Bit16s decode_ADPCM_4_sample(Bit8u sample,Bits& reference,Bits& scale) { reference = min(0xff, reference + ((sample & 0x07) << scale)); } scale = max(2, min(6, scaleMap[sample & 0x07])); - return (((Bit8s)reference)^0x80)<<8; + return reference; } -#endif - -INLINE Bit16s decode_ADPCM_2_sample(Bit8u sample,Bits& reference,Bits& scale) { +static INLINE Bit8u decode_ADPCM_2_sample(Bit8u sample,Bit8u & reference,Bits& scale) { static Bits scaleMap[8] = { -2, -1, 0, 0, 1, 1, 1, 1 }; if (sample & 0x02) { @@ -296,10 +274,10 @@ INLINE Bit16s decode_ADPCM_2_sample(Bit8u sample,Bits& reference,Bits& scale) { reference = min(0xff, reference + ((sample & 0x01) << (scale+2))); } scale = max(2, min(6, scaleMap[sample & 0x07])); - return (((Bit8s)reference)^0x80)<<8; + return reference; } -INLINE Bit16s decode_ADPCM_3_sample(Bit8u sample,Bits& reference,Bits& scale) { +INLINE Bit8u decode_ADPCM_3_sample(Bit8u sample,Bit8u & reference,Bits& scale) { static Bits scaleMap[8] = { -2, -1, 0, 0, 1, 1, 1, 1 }; if (sample & 0x04) { @@ -308,301 +286,262 @@ INLINE Bit16s decode_ADPCM_3_sample(Bit8u sample,Bits& reference,Bits& scale) { reference = min(0xff, reference + ((sample & 0x03) << (scale+1))); } scale = max(2, min(6, scaleMap[sample & 0x07])); - return (((Bit8s)reference)^0x80)<<8; + return reference; } - - - - static void GenerateDMASound(Bitu size) { - /* Check some variables */ - if (!size) return; - if (!sb.dma.rate) return; - /* First check if this transfer is gonna end in the next 2 milliseconds */ - Bitu index=(Bitu)(((float)sb.dma.left*(float)1000000)/(float)sb.dma.rate); -#if (SB_PIC_EVENTS) - if (index-PIC_Index()<1000) PIC_AddEvent(END_DMA_Event,index); -#else - if (index<2000) size=sb.dma.left; -#endif - Bitu read,i,ad; + Bitu read;Bitu done=0;Bitu i=0; + if (sb.dma.left<=sb.dma.min) { + size=sb.dma.left; + } switch (sb.dma.mode) { - case DMA_2_SINGLE: - if (sb.adpcm.reference==0x1000000 && sb.dma.left) { - Bit8u ref; - read=DMA_8_Read(sb.hw.dma8,&ref,1); - if (!read) { sb.mode=MODE_NONE;return; } - sb.dma.left--; - sb.adpcm.reference=0; + 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++; } - if (sb.dma.left> 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); } - for (i=0;i> 6,sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[i*4+1]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >>4) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[i*4+2]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >>2)& 0x3,sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[i*4+3]=decode_ADPCM_2_sample(sb.dma.buf.b8[i] & 0x3,sb.adpcm.reference,sb.adpcm.stepsize); - } - read*=4; + sb.chan->AddSamples_m8(done,MixTemp); break; - case DMA_3_SINGLE: - if (sb.adpcm.reference==0x1000000 && sb.dma.left) { - Bit8u ref; - read=DMA_8_Read(sb.hw.dma8,&ref,1); - if (!read) { sb.mode=MODE_NONE;return;} - sb.dma.left--; - sb.adpcm.reference=0; + 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++; } - if (sb.dma.left>3)&7, sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[i*8+2]=decode_ADPCM_3_sample(((sb.dma.buf.b8[i*3] >>6)&3)&((sb.dma.buf.b8[i*3+1]&1)<<2),sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[i*8+3]=decode_ADPCM_3_sample((sb.dma.buf.b8[i*3+1]>>1)&7,sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[i*8+4]=decode_ADPCM_3_sample((sb.dma.buf.b8[i*3+1]>>4)&7,sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[i*8+5]=decode_ADPCM_3_sample(((sb.dma.buf.b8[i*3+1]>>7)&1)&((sb.dma.buf.b8[i*3+2]&3)<<1),sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[i*8+6]=decode_ADPCM_3_sample((sb.dma.buf.b8[i*3+2]>>2)&7,sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[i*8+7]=decode_ADPCM_3_sample((sb.dma.buf.b8[i*3+2]>>5)&7,sb.adpcm.reference,sb.adpcm.stepsize); - } - read*=8; - if (ad) { - sb.tmp.buf.m[read]=decode_ADPCM_3_sample((sb.dma.buf.b8[read*3/8])&7,sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[read+1]=decode_ADPCM_3_sample((sb.dma.buf.b8[read*3/8]>>3)&7,sb.adpcm.reference,sb.adpcm.stepsize); - read+=2; - if (ad==2) { - sb.tmp.buf.m[read]=decode_ADPCM_3_sample(((sb.dma.buf.b8[(read-2)*3/8-1]>>6)&3)&(sb.dma.buf.b8[read*3/8]&1), sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[read+1]=decode_ADPCM_3_sample((sb.dma.buf.b8[(read-2)*3/8]>>1)&7,sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[read+2]=decode_ADPCM_3_sample((sb.dma.buf.b8[(read-2)*3/8]>>4)&7,sb.adpcm.reference,sb.adpcm.stepsize); - read+=3; - } + 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_2_sample((sb.dma.buf.b8[i] >> 0) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize); } + sb.chan->AddSamples_m8(done,MixTemp); break; - case DMA_4_SINGLE: - if (sb.adpcm.reference==0x1000000 && sb.dma.left) { -//TODO Check this - Bit8u ref; - read=DMA_8_Read(sb.hw.dma8,&ref,1); - if (!read) { sb.mode=MODE_NONE;return; } //TODO warnings? - sb.dma.left--; - sb.adpcm.reference=0; + 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++; } - if (sb.dma.left> 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); } - for (i=0;i> 4,sb.adpcm.reference,sb.adpcm.stepsize); - sb.tmp.buf.m[i*2+1]=decode_ADPCM_4_sample(sb.dma.buf.b8[i] & 0xf,sb.adpcm.reference,sb.adpcm.stepsize); - } - read*=2; + sb.chan->AddSamples_m8(done,MixTemp); break; - case DMA_8_SINGLE: - if (sb.dma.leftread) { - sb.dma.left-=read; + 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; + sb.chan->AddSamples_s8(total>>1,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 { - sb.dma.left=(sb.dma.total+sb.dma.left)-read; - SB_RaiseIRQ(SB_IRQ_8); -// LOG_MSG("SB DMA AUTO IRQ Raised"); + read=sb.dma.chan->Read(size,sb.dma.buf.b8); + sb.chan->AddSamples_m8(read,sb.dma.buf.b8); + } + break; + case DSP_DMA_16: + if (sb.dma.stereo) { + read=sb.dma.chan->Read(size,(Bit8u *)&sb.dma.buf.b16[sb.dma.remain_size]); + Bitu total=read+sb.dma.remain_size; + sb.chan->AddSamples_s16(total>>1,sb.dma.buf.b16); + 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,sb.dma.buf.b8); + sb.chan->AddSamples_m16(read,sb.dma.buf.b16); + } + break; + case DSP_DMA_16_ALIASED: + if (sb.dma.stereo) { + sb.chan->AddSamples_s16(read>>2,sb.dma.buf.b16); + } else { + sb.chan->AddSamples_m16(read>>1,sb.dma.buf.b16); } - for (i=0;i(pos=sb.tmp.index>>16)) { - (*stream++)=sb.tmp.buf.m[pos]; - (*stream++)=sb.tmp.buf.m[pos]; - sb.tmp.index+=sb.tmp.add_index; - sb.out.pos++; - } - sb.tmp.index&=0xffff; - } else { - if (read&1){ - LOG_MSG("DMA Unaligned"); + 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 { - Bitu pos;read>>=1;Bitu index_add=sb.tmp.add_index >> 1; - while (read>(pos=sb.tmp.index>>16)) { - (*stream++)=sb.tmp.buf.s[pos][1]; //SB default seems to be swapped - (*stream++)=sb.tmp.buf.s[pos][0]; - sb.tmp.index+=index_add; - sb.out.pos++; + 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; } - sb.tmp.index&=0xffff; } + if (sb.dma.mode >= DSP_DMA_16) SB_RaiseIRQ(SB_IRQ_16); + else SB_RaiseIRQ(SB_IRQ_8); } } -static void GenerateSound(Bitu size) { - while (sb.out.pos0) { - *(stream++)=sb.dac.data[dac_pos>>16]; - *(stream++)=sb.dac.data[dac_pos>>16]; - dac_pos+=dac_add; - } - dac_pos-=dac_add; - sb.dac.last=sb.dac.data[dac_pos>>16]; - sb.dac.used=0; - } else { - memset(stream,sb.dac.last,samples); - sb.mode=MODE_NONE; - } - sb.out.pos+=samples; - break; - } - case MODE_DMA: - { - Bitu len=size*sb.dma.rate_mul; - if (len & 0xffff) len=1+(len>>16); - else len>>=16; - if (sb.dma.stereo && (len & 1)) len++; - GenerateDMASound(len); - break; - } - - } +static void GenerateDACSound(Bitu len) { + if (!sb.dac.used) { + sb.mode=MODE_NONE; + return; } - if (sb.out.pos>SB_BUF_SIZE) { - LOG(LOG_SB,LOG_ERROR)("Generation Buffer Full!!!!"); - sb.out.pos=0; + 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 END_DMA_Event(void) { - GenerateDMASound(sb.dma.left); +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.rate) return; - Bitu index=(Bitu)(((float)sb.dma.left*(float)1000000)/(float)sb.dma.rate); - if (index<(1000-PIC_Index())) { -#if 1 - LOG(LOG_SB,LOG_NORMAL)("Sub millisecond transfer scheduling IRQ in %d microseconds",index); - PIC_AddEvent(END_DMA_Event,index); -#else - GenerateDMASound(sb.dma.left); -#endif + if (!sb.dma.left) return; + if (!sb.speaker) { + 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.left>16); + if (sb.mode==mode) return; + else sb.chan->FillUp(); sb.mode=mode; } -static void DSP_RaiseIRQEvent(void) { +static void DSP_RaiseIRQEvent(Bitu val) { SB_RaiseIRQ(SB_IRQ_8); } -static void DSP_StartDMATranfser(DMA_MODES mode) { +static void DSP_DoDMATranfser(DMA_MODES mode,Bitu freq,bool stereo) { char * type; - /* First fill with current whatever is playing */ - DSP_ChangeMode(MODE_NONE); + sb.mode=MODE_DMA_MASKED; + sb.chan->FillUp(); sb.dma.left=sb.dma.total; - if (sb.use_time_constant) { - sb.dma.rate=(1000000 / (256 - sb.time_constant)); - }; - sb.dma.rate_mul=(sb.dma.rate<<16)/sb.hw.rate; sb.dma.mode=mode; - sb.tmp.index=0; + sb.dma.stereo=stereo; + sb.irq.pending_8bit=false; + sb.irq.pending_16bit=false; switch (mode) { - case DMA_8_SILENCE: - PIC_AddEvent(&DSP_RaiseIRQEvent,((1000000*sb.dma.left)/sb.dma.rate)); - sb.dma.mode=DMA_NONE; - return; - case DMA_8_SINGLE: - type="8-Bit Single Cycle"; - sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; + case DSP_DMA_2: + type="2-bits ADPCM"; + sb.dma.mul=(1 << SB_SH)/4; break; - case DMA_8_AUTO: - type="8-Bit Auto Init"; - sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; + case DSP_DMA_3: + type="3-bits ADPCM"; + sb.dma.mul=(1 << SB_SH)/3; break; - case DMA_4_SINGLE: - type="4-Bit ADPCM Single Cycle"; - sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; + case DSP_DMA_4: + type="4-bits ADPCM"; + sb.dma.mul=(1 << SB_SH)/2; break; - case DMA_3_SINGLE: - type="3-Bit ADPCM Single Cycle"; - sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; + case DSP_DMA_8: + type="8-bits PCM"; + sb.dma.mul=(1 << SB_SH); break; - case DMA_2_SINGLE: - type="2-Bit ADPCM Single Cycle"; - sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; + 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; } - //TODO Use the 16-bit dma for 16-bit transfers - DSP_ChangeMode(MODE_DMA_WAIT); + 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; - DMA_SetEnableCallBack(sb.hw.dma8,DMA_Enable); - //TODO with stereo divide add_index - LOG(LOG_SB,LOG_NORMAL)("DMA Transfer:%s rate %d size %d",type,sb.dma.rate,sb.dma.total); + 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) { + sb.dma.autoinit=autoinit; + if (!autoinit) sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); + sb.dma.chan=DmaChannels[sb.hw.dma8]; + DSP_DoDMATranfser(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; + sb.dma.total=length; + sb.dma.autoinit=autoinit; + if (mode==DSP_DMA_16) { + if (sb.hw.dma16!=0xff) sb.dma.chan=DmaChannels[sb.hw.dma16]; + else { + sb.dma.chan=DmaChannels[sb.hw.dma8]; + mode=DSP_DMA_16_ALIASED; + freq/=2; + } + } else sb.dma.chan=DmaChannels[sb.hw.dma8]; + DSP_DoDMATranfser(mode,freq,stereo); +} + + static void DSP_AddData(Bit8u val) { if (sb.dsp.out.usedSetFreq(22050); DSP_SetSpeaker(false); + PIC_RemoveEvents(END_DMA_Event); } @@ -650,15 +593,26 @@ static void DSP_DoReset(Bit8u val) { } } - -static void DMA_E2_Enable(bool enable) { - if (enable) { +static void DSP_E2_DMA_CallBack(DmaChannel * chan, DMAEvent event) { + if (event==DMA_UNMASKED) { Bit8u val=sb.e2.value; - DMA_8_Write(sb.hw.dma8,&val,1); - DMA_SetEnableCallBack(sb.hw.dma8,0); + DmaChannels[sb.hw.dma8]->Register_Callback(0); + DmaChannels[sb.hw.dma8]->Write(1,&val); } } +static void DSP_ADC_CallBack(DmaChannel * chan, DMAEvent event) { + if (event!=DMA_UNMASKED) return; + Bit8u val=128; + while (sb.dma.left--) { + DmaChannels[sb.hw.dma8]->Write(1,&val); + } + SB_RaiseIRQ(SB_IRQ_8); + DmaChannels[sb.hw.dma8]->Register_Callback(0); +} + +Bitu DEBUG_EnableDebugger(void); + static void DSP_DoCommand(void) { // LOG_MSG("DSP Command %X",sb.dsp.cmd); switch (sb.dsp.cmd) { @@ -670,55 +624,69 @@ static void DSP_DoCommand(void) { DSP_ChangeMode(MODE_DAC); if (sb.dac.usedRegister_Callback(DSP_ADC_CallBack); + break; case 0x14: /* Singe Cycle 8-Bit DMA DAC */ case 0x91: /* Singe Cycle 8-Bit DMA High speed DAC */ - sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); - DSP_StartDMATranfser(DMA_8_SINGLE); + DSP_PrepareDMA_Old(DSP_DMA_8,false); break; case 0x90: /* Auto Init 8-bit DMA High Speed */ case 0x1c: /* Auto Init 8-bit DMA */ - DSP_StartDMATranfser(DMA_8_AUTO); + DSP_PrepareDMA_Old(DSP_DMA_8,true); break; case 0x40: /* Set Timeconstant */ - sb.use_time_constant=true; - sb.time_constant=sb.dsp.in.data[0]; + sb.freq=(1000000 / (256 - sb.dsp.in.data[0])); + break; + case 0x41: /* Set Output Samplerate */ + case 0x42: /* Set Input Samplerate */ + sb.freq=(sb.dsp.in.data[0] << 8) | sb.dsp.in.data[1]; break; case 0x48: /* Set DMA Block Size */ //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.reference=0x1000000; + case 0x75: /* 075h : Single Cycle 4-bit ADPCM Reference */ + sb.adpcm.haveref=true; case 0x74: /* 074h : Single Cycle 4-bit ADPCM */ - sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); - DSP_StartDMATranfser(DMA_4_SINGLE); + DSP_PrepareDMA_Old(DSP_DMA_4,false); break; - case 0x77: /* 074h : Single Cycle 3-bit(2.6bit) ADPCM Reference*/ - sb.adpcm.reference=0x1000000; + 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 */ - sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); - DSP_StartDMATranfser(DMA_3_SINGLE); + DSP_PrepareDMA_Old(DSP_DMA_3,false); break; - case 0x17: /* 074h : Single Cycle 2-bit ADPCM Reference*/ - sb.adpcm.reference=0x1000000; + case 0x17: /* 017h : Single Cycle 2-bit ADPCM Reference*/ + sb.adpcm.haveref=true; case 0x16: /* 074h : Single Cycle 2-bit ADPCM */ - sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); - DSP_StartDMATranfser(DMA_2_SINGLE); + DSP_PrepareDMA_Old(DSP_DMA_2,false); break; case 0x80: /* Silence DAC */ - sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); - DSP_StartDMATranfser(DMA_8_SILENCE); + PIC_AddEvent(&DSP_RaiseIRQEvent, + (1000.0f*(1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8))/sb.freq)); + break; + case 0xb0: case 0xb2: case 0xb4: case 0xb6: + case 0xc0: case 0xc2: case 0xc4: case 0xc6: + /* 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 0xd0: /* Halt 8-bit DMA */ - if (sb.dma.left) { - DSP_ChangeMode(MODE_DMA_PAUSE); -#if SB_PIC_EVENTS - PIC_RemoveEvents(END_DMA_Event); -#endif - } else DSP_ChangeMode(MODE_NONE); + case 0xd5: /* Halt 16-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); @@ -726,13 +694,16 @@ static void DSP_DoCommand(void) { case 0xd3: /* Disable Speaker */ DSP_SetSpeaker(false); break; - case 0xd4: /* Continue DMA */ - DSP_ChangeMode(MODE_DMA_WAIT); - DMA_SetEnableCallBack(sb.hw.dma8,DMA_Enable); + case 0xd4: /* Continue DMA 8-bit*/ + case 0xd6: /* Continue DMA 16-bit */ + if (sb.mode==MODE_DMA_PAUSE) { + sb.mode=MODE_DMA_MASKED; + sb.dma.chan->Register_Callback(DSP_DMA_CallBack); + } break; case 0xda: /* Exit Autoinitialize 8-bit */ /* Set mode to single transfer so it ends with current block */ - if (sb.dma.mode==DMA_8_AUTO) sb.dma.mode=DMA_8_SINGLE; + sb.dma.autoinit=false; //Should stop itself break; case 0xe0: /* DSP Identification - SB2.0+ */ DSP_FlushData(); @@ -740,8 +711,18 @@ static void DSP_DoCommand(void) { break; case 0xe1: /* Get DSP Version */ DSP_FlushData(); - DSP_AddData(DSP_MAJOR); - DSP_AddData(DSP_MINOR); + 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; + } break; case 0xe2: /* Weird DMA identification write routine */ { @@ -750,7 +731,7 @@ static void DSP_DoCommand(void) { 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++; - DMA_SetEnableCallBack(sb.hw.dma8,DMA_E2_Enable); + DmaChannels[sb.hw.dma8]->Register_Callback(DSP_E2_DMA_CallBack); } break; case 0xe3: /* DSP Copyright */ @@ -806,73 +787,131 @@ static Bit8u DSP_ReadData(void) { return data; } -static void MIXER_Write(Bit8u val) { +//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; + chan=MIXER_FindChannel("SB"); + if (chan) chan->SetVolume(CALCVOL(sb.mixer.dac[0]),CALCVOL(sb.mixer.dac[1])); + chan=MIXER_FindChannel("FM"); + if (chan) chan->SetVolume(CALCVOL(sb.mixer.fm[0]),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; + CTMIXER_UpdateVolumes(); +} + +#define SETPROVOL(_WHICH_,_VAL_) \ + _WHICH_[0]= 0x1 | ((_VAL_ & 0xf0) >> 3); \ + _WHICH_[1]= 0x1 | ((_VAL_ & 0x0f) << 1); + +static void CTMIXER_Write(Bit8u val) { switch (sb.mixer.index) { case 0x02: /* Master Voulme (SBPRO) Obsolete? */ case 0x22: /* Master Volume (SBPRO) */ - sb.mixer.master.left= (val & 0xf) << 1; - sb.mixer.master.right=(val >> 4) << 1; + SETPROVOL(sb.mixer.master,val); break; case 0x04: /* DAC Volume (SBPRO) */ - sb.mixer.dac.left= (val & 0xf) << 1; - sb.mixer.dac.right=(val >> 4) << 1; + SETPROVOL(sb.mixer.dac,val); + CTMIXER_UpdateVolumes(); break; case 0x06: /* FM output selection, Somewhat obsolete with dual OPL SBpro */ - sb.mixer.fm.left= (val & 0xf) << 1; - sb.mixer.fm.right=(val & 0xf) << 1; + SETPROVOL(sb.mixer.fm,val); + sb.mixer.fm[1]=sb.mixer.fm[0]; + CTMIXER_UpdateVolumes(); //TODO Change FM Mode if only 1 fm channel is selected break; case 0x0a: /* Mic Level */ sb.mixer.mic=(val & 0xf) << 1; break; case 0x0e: /* Output/Stereo Select */ - sb.dma.stereo=(val & 0x2) > 0; - sb.dma.filtered=(val & 0x20) > 0; + sb.mixer.stereo=(val & 0x2) > 0; + sb.mixer.filtered=(val & 0x20) > 0; LOG(LOG_SB,LOG_WARN)("Mixer set to %s",sb.dma.stereo ? "STEREO" : "MONO"); break; case 0x26: /* FM Volume (SBPRO) */ - sb.mixer.fm.left= (val & 0xf) << 1; - sb.mixer.fm.right=(val >> 4) << 1; + SETPROVOL(sb.mixer.fm,val); + CTMIXER_UpdateVolumes(); break; case 0x28: /* CD Audio Volume (SBPRO) */ - sb.mixer.cda.left= (val & 0xf) << 1; - sb.mixer.cda.right=(val >> 4) << 1; + SETPROVOL(sb.mixer.cda,val); break; case 0x2e: /* Line-IN Volume (SBPRO) */ - sb.mixer.lin.left= (val & 0xf) << 1; - sb.mixer.lin.right=(val >> 4) << 1; + SETPROVOL(sb.mixer.lin,val); + 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: LOG(LOG_SB,LOG_WARN)("MIXER:Write %X to unhandled index %X",val,sb.mixer.index); } } -static Bit8u MIXER_Read(void) { +#define MAKEPROVOL(_WHICH_) \ + (((_WHICH_[0] & 0x1e) << 3) | ((_WHICH_[1] & 0x1e) >> 1)) + +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 Voulme (SBPRO) Obsolete? */ case 0x22: /* Master Volume (SBPRO) */ - return ((sb.mixer.master.left & 0x1e) >> 1) | - ((sb.mixer.master.right & 0x1e) << 3); + return MAKEPROVOL(sb.mixer.master); case 0x04: /* DAC Volume (SBPRO) */ - return ((sb.mixer.dac.left & 0x1e) >> 1) | - ((sb.mixer.dac.right & 0x1e) << 3); + return MAKEPROVOL(sb.mixer.dac); // case 0x06: /* FM output selection, Somewhat obsolete with dual OPL SBpro */ case 0x0a: /* Mic Level (SBPRO) */ return (sb.mixer.mic >> 1); case 0x0e: /* Output/Stereo Select */ - return 0x11|(sb.dma.stereo ? 0x02 : 0x00)|(sb.dma.filtered ? 0x20 : 0x00); + return 0x11|(sb.mixer.stereo ? 0x02 : 0x00)|(sb.mixer.filtered ? 0x20 : 0x00); case 0x26: /* FM Volume (SBPRO) */ - return ((sb.mixer.fm.left & 0x1e) >> 1) | - ((sb.mixer.fm.right & 0x1e) << 3); + return MAKEPROVOL(sb.mixer.fm); case 0x28: /* CD Audio Volume (SBPRO) */ - return ((sb.mixer.cda.left & 0x1e) >> 1) | - ((sb.mixer.cda.right & 0x1e) << 3); + return MAKEPROVOL(sb.mixer.cda); case 0x2e: /* Line-IN Volume (SBPRO) */ - return ((sb.mixer.lin.left & 0x1e) >> 1) | - ((sb.mixer.lin.right & 0x1e) << 3); + return MAKEPROVOL(sb.mixer.lin); + 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: return (sb.irq.pending_8bit ? 0x1 : 0) | (sb.irq.pending_16bit ? 0x2 : 0); @@ -884,12 +923,12 @@ static Bit8u MIXER_Read(void) { } -static Bit8u read_sb(Bit32u port) { +static Bitu read_sb(Bitu port,Bitu iolen) { switch (port-sb.hw.base) { case MIXER_INDEX: return sb.mixer.index; case MIXER_DATA: - return MIXER_Read(); + return CTMIXER_Read(); case DSP_READ_DATA: return DSP_ReadData(); case DSP_READ_STATUS: @@ -897,6 +936,9 @@ static Bit8u read_sb(Bit32u port) { 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: @@ -907,9 +949,6 @@ static Bit8u read_sb(Bit32u port) { 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: @@ -919,7 +958,7 @@ static Bit8u read_sb(Bit32u port) { return 0xff; } -static void write_sb(Bit32u port,Bit8u val) { +static void write_sb(Bitu port,Bitu val,Bitu iolen) { switch (port-sb.hw.base) { case DSP_RESET: DSP_DoReset(val); @@ -931,57 +970,118 @@ static void write_sb(Bit32u port,Bit8u val) { sb.mixer.index=val; break; case MIXER_DATA: - MIXER_Write(val); + CTMIXER_Write(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(LOG_SB,LOG_NORMAL)("Unhandled write to SB Port %4X",port); break; } } -static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) { - if (!len) return; - GenerateSound(len); - memcpy(stream,sb.out.buf,len*4); - if (sb.out.pos>=len) { - memcpy(sb.out.buf,&sb.out.buf[len],(sb.out.pos-len)*4); - sb.out.pos-=len; - } - else sb.out.pos=0; - if (sb.mode==MODE_NONE) DSP_SetSpeaker(false); - return; +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; + } +} void SBLASTER_Init(Section* sec) { Bitu i; Section_prop * section=static_cast(sec); - if(!section->Get_bool("sblaster")) return; - sb.chan=MIXER_AddChannel(&SBLASTER_CallBack,22050,"SBLASTER"); - MIXER_Enable(sb.chan,false); - sb.dsp.state=DSP_S_NORMAL; + const char * sbtype=section->Get_string("type"); sb.hw.base=section->Get_hex("base"); sb.hw.irq=section->Get_int("irq"); sb.hw.dma8=section->Get_int("dma"); - sb.hw.rate=section->Get_int("sbrate"); - sb.hw.rate_conv=(sb.hw.rate<<16)/1000000; - MIXER_SetFreq(sb.chan,sb.hw.rate); - MIXER_SetMode(sb.chan,MIXER_16STEREO); - - for (i=sb.hw.base+4;iGet_int("hdma"); + sb.mixer.enabled=section->Get_bool("mixer"); + sb.mixer.stereo=false; + if (!strcasecmp(sbtype,"sb1")) sb.type=SBT_1; + else if (!strcasecmp(sbtype,"sb2")) sb.type=SBT_2; + else if (!strcasecmp(sbtype,"sbpro1")) sb.type=SBT_PRO1; + else if (!strcasecmp(sbtype,"sbpro2")) sb.type=SBT_PRO2; + else if (!strcasecmp(sbtype,"sb16")) sb.type=SBT_16; + else if (!strcasecmp(sbtype,"none")) sb.type=SBT_NONE; + else sb.type=SBT_16; - SHELL_AddAutoexec("SET BLASTER=A%3X I%d D%d T4",sb.hw.base,sb.hw.irq,sb.hw.dma8); + if (machine!=MCH_VGA && sb.type==SBT_16) sb.type=SBT_PRO2; + + /* OPL/CMS Init */ + const char * omode=section->Get_string("oplmode"); + Bitu oplrate=section->Get_int("oplrate"); + OPL_Mode opl_mode; + 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 (sb.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; + } + } + switch (opl_mode) { + case OPL_none: + IO_RegisterWriteHandler(0x388,adlib_gusforward,IO_MB); + break; + case OPL_cms: + IO_RegisterWriteHandler(0x388,adlib_gusforward,IO_MB); + CMS_Init(section,sb.hw.base,oplrate); + break; + case OPL_opl2: + CMS_Init(section,sb.hw.base,oplrate); + case OPL_dualopl2: + case OPL_opl3: + OPL_Init(section,sb.hw.base,opl_mode,oplrate); + break; + } + if (sb.type==SBT_NONE) return; + sb.chan=MIXER_AddChannel(&SBLASTER_CallBack,22050,"SB"); + sb.dsp.state=DSP_S_NORMAL; + + 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; + IO_RegisterReadHandler(sb.hw.base+i,read_sb,IO_MB); + IO_RegisterWriteHandler(sb.hw.base+i,write_sb,IO_MB); + } + DSP_Reset(); + CTMIXER_Reset(); + char hdma[8]=""; + if (sb.type==SBT_16) { + sprintf(hdma,"H%d ",sb.hw.dma16); + } + SHELL_AddAutoexec("SET BLASTER=A%3X I%d D%d %sT%d",sb.hw.base,sb.hw.irq,sb.hw.dma8,hdma,sb.type); } + diff --git a/src/hardware/serialport.cpp b/src/hardware/serialport.cpp index a5ba389..6020b54 100644 --- a/src/hardware/serialport.cpp +++ b/src/hardware/serialport.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -17,6 +17,8 @@ */ #include +#include +#include #include "dosbox.h" #include "inout.h" @@ -29,392 +31,217 @@ #include "serialport.h" #define SERIALBASERATE 115200 -#define SERIALPORT_COUNT 2 - #define LOG_UART LOG_MSG -CSerial *serialports[SERIALPORT_COUNT]; +CSerialList seriallist; -void CSerial::setdivisor(Bit8u dmsb, Bit8u dlsb) { - Bitu divsize=(dmsb << 8) | dlsb; - if (divsize!=0) { +void CSerial::UpdateBaudrate(void) { + Bitu divsize=(divisor_msb << 8) | divisor_lsb; + if (divsize) { bps = SERIALBASERATE / divsize; } } +void CSerial::Timer(void) { + dotxint=true; + checkint(); +} + void CSerial::checkint(void) { - /* Find lowest priority interrupt to activate */ - Bitu i; - for (i=0;iinuse()) { +// LOG_MSG("RX IRQ with %d",rqueue->inuse()); + iir=0x4; + } else if ((ier & 0x2) && !tqueue->inuse() && dotxint) { + iir=0x2; + } else if ((ier & 0x8) && (mstatus & 0x0f)) { + iir=0x0; + } else { + iir=0x1; + PIC_DeActivateIRQ(irq); return; } - } - /* Not a single interrupt schedulded, lower IRQ */ - PIC_DeActivateIRQ(irq); - ints.active=INT_NONE; + if (mctrl & 0x8) PIC_ActivateIRQ(irq); + else PIC_DeActivateIRQ(irq); } -void CSerial::raiseint(INT_TYPES type) { -// LOG_MSG("Raising int %X rx size %d tx size %d",type,rx_fifo.used,tx_fifo.used); - ints.requested|=1 << type; - checkint(); -} - -void CSerial::lowerint(INT_TYPES type){ - ints.requested&=~(1 << type); - checkint(); -} - - -void CSerial::write_port(Bit32u port, Bit8u val) { - - port-=base; -// LOG_UART("Serial write %X val %x %c",port,val,val); - switch(port) { +void CSerial::write_reg(Bitu reg, Bitu val) { +// if (port!=9 && port!=8) LOG_MSG("Serial write %X val %x %c",port,val,val); + switch(reg) { case 0x8: // Transmit holding buffer + Divisor LSB if (dlab) { divisor_lsb = val; - setdivisor(divisor_msb, divisor_lsb); + UpdateBaudrate(); return; } - if (local_loopback) { - rx_addb(val); - } else tx_addb(val); + if (local_loopback) rqueue->addb(val); + else tqueue->addb(val); break; case 0x9: // Interrupt enable register + Divisor MSB if (dlab) { divisor_msb = val; - setdivisor(divisor_msb, divisor_lsb); + UpdateBaudrate(); return; + } else { + ier = val; + dotxint=true; } - /* Only enable the FIFO interrupt by default */ - ints.enabled=1 << INT_RX_FIFO; - if (val & 0x1) ints.enabled|=1 << INT_RX; - if (val & 0x2) ints.enabled|=1 << INT_TX; - if (val & 0x4) ints.enabled|=1 << INT_LS; - if (val & 0x8) ints.enabled|=1 << INT_MS; - ierval = val; - checkint(); break; case 0xa: // FIFO Control register - FIFOenabled = false; - if (val & 0x1) { -// FIFOenabled = true; - timeout = 0; - } - if (val & 0x2) { //Clear receiver FIFO - rx_fifo.used=0; - rx_fifo.pos=0; - } - if (val & 0x4) { //Clear transmit FIFO - tx_fifo.used=0; - tx_fifo.pos=0; - } + FIFOenabled = (val & 0x1) > 0; + if (val & 0x2) rqueue->clear(); //Clear receiver FIFO + if (val & 0x4) tqueue->clear(); //Clear transmit FIFO if (val & 0x8) LOG(LOG_MISC,LOG_WARN)("UART:Enabled DMA mode"); switch (val >> 6) { - case 0: - FIFOsize = 1; - break; - case 1: - FIFOsize = 4; - break; - case 2: - FIFOsize = 8; - break; - case 3: - FIFOsize = 14; - break; + case 0:FIFOsize = 1;break; + case 1:FIFOsize = 4;break; + case 2:FIFOsize = 8;break; + case 3:FIFOsize = 14;break; } break; case 0xb: // Line control register linectrl = val; - wordlen = (val & 0x3); - dlab = (val & 0x80) > 0; + dlab = (val & 0x80); break; case 0xc: // Modem control register - dtr = val & 0x01; - rts = (val & 0x02) > 0 ; - out1 = (val & 0x04) > 0; - out2 = (val & 0x08) > 0; - if (mc_handler) (*mc_handler)(val & 0xf); - local_loopback = (val & 0x10) > 0; + mctrl=val; + local_loopback = (val & 0x10); break; case 0xf: // Scratch register scratch = val; break; default: - LOG_UART("Modem: Write to 0x%x, with 0x%x '%c'\n", port,val,val); + LOG_UART("Modem: Write to 0x%x, with 0x%x '%c'\n", reg,val,val); break; } } -void CSerial::write_serial(Bit32u port, Bit8u val) { - int i; - - for(i=0;i=serialports[i]->base+0x8) && (port<=(serialports[i]->base+0xf)) ) { - serialports[i]->write_port(port,val); +static void WriteSerial(Bitu port,Bitu val,Bitu iolen) { + Bitu check=port&~0xf; + for (CSerial_it it=seriallist.begin();it!=seriallist.end();it++){ + CSerial * serial=(*it); + if (check==serial->base) { + serial->write_reg(port&0xf,val); + return; } } } -Bit8u CSerial::read_port(Bit32u port) { - Bit8u outval = 0; +static Bitu ReadSerial(Bitu port,Bitu iolen) { + Bitu check=port&~0xf; + + for (CSerial_it it=seriallist.begin();it!=seriallist.end();it++){ + CSerial * serial=(*it); + if (check==serial->base) { - port-=base; -// LOG_MSG("Serial read form %X",port); - switch(port) { + return serial->read_reg(port&0xf); + } + } + return 0; +} + +void SERIAL_Update(void) { + for (CSerial_it it=seriallist.begin();it!=seriallist.end();it++){ + CSerial * serial=(*it); + serial->Timer(); + } +} + + + +Bitu CSerial::read_reg(Bitu reg) { + Bitu retval; +// if (port!=0xd && port!=0xa) LOG_MSG("REad from port %x",reg); + switch(reg) { case 0x8: // Receive buffer + Divisor LSB if (dlab) { return divisor_lsb ; } else { - outval = rx_readb(); -// LOG_UART("Read from %X %X %c remain %d",port,outval,outval,rx_fifo.used); - return outval; + retval=rqueue->getb(); + //LOG_MSG("Received char %x %c",retval,retval); + checkint(); + return retval; } case 0x9: // Interrupt enable register + Divisor MSB if (dlab) { return divisor_msb ; } else { -// LOG_UART("Read from %X %X",port,ierval); - return ierval; + return ier; } case 0xa: // Interrupt identification register - switch (ints.active) { - case INT_MS: - outval = 0x0; - break; - case INT_TX: - outval = 0x2; - lowerint(INT_TX); - goto skipreset; - case INT_RX: - outval = 0x4; - break; - case INT_RX_FIFO: - lowerint(INT_RX_FIFO); - outval = 0xc; - goto skipreset; - case INT_LS: - outval = 0x6; - break; - case INT_NONE: - outval = 0x1; - break; + retval=iir; + if (iir==2) { + dotxint=false; + iir=1; } - ints.active=INT_NONE; -skipreset: - if (FIFOenabled) outval |= 3 << 6; -// LOG_UART("Read from %X %X",port,outval); - return outval; +// LOG_MSG("Read iir %d after %d",retval,iir); + return retval | ((FIFOenabled) ? (3 << 6) : 0); case 0xb: // Line control register - LOG_UART("Read from %X %X",port,outval); return linectrl; case 0xC: // Modem control register - outval = dtr | (rts << 1) | (out1 << 2) | (out2 << 3) | (local_loopback << 4); -// LOG_UART("Read from %X %X",port,outval); - return outval; + return mctrl; case 0xD: // Line status register - lowerint(INT_LS); - outval = 0x40; - if (FIFOenabled) { - if (!tx_fifo.used) outval|=0x20; - } else if (tx_fifo.usedinuse()) retval|=0x20; + if (rqueue->inuse()) retval|= 1; +// LOG_MSG("Read from line status %x",retval); + return retval; case 0xE: // modem status register - lowerint(INT_MS); - LOG_UART("Read from %X %X",port,outval); - outval=mstatus; + retval=mstatus; mstatus&=0xf0; - return outval; + checkint(); + return retval; case 0xF: // Scratch register return scratch; default: //LOG_DEBUG("Modem: Read from 0x%x\n", port); break; } - - return 0x00; - - - -} - -Bit8u CSerial::read_serial(Bit32u port) -{ - int i; - for(i=0;i=serialports[i]->base+0x8) && (port<=(serialports[i]->base+0xf)) ) { - return serialports[i]->read_port(port); - } - } return 0x00; } -Bitu CSerial::rx_free() { - return FIFO_SIZE-rx_fifo.used; -} -Bitu CSerial::tx_free() { - return FIFO_SIZE-tx_fifo.used; -} - -Bitu CSerial::tx_size() { - if (FIFOenabled && rx_fifo.used && (rx_lastread < (PIC_Ticks-2))) { - raiseint(INT_RX_FIFO); - } - return tx_fifo.used; -} - -Bitu CSerial::rx_size() { - return rx_fifo.used; -} - -void CSerial::rx_addb(Bit8u data) { - LOG_UART("RX add %c",data); - if (rx_fifo.used=FIFO_SIZE) where-=FIFO_SIZE; - rx_fifo.data[where]=data; - rx_fifo.used++; - if (FIFOenabled && (rx_fifo.used < FIFOsize)) return; - /* Raise rx irq if possible */ - if (ints.active != INT_RX) raiseint(INT_RX); - } -} - -void CSerial::rx_adds(Bit8u * data,Bitu size) { - if ((rx_fifo.used+size)<=FIFO_SIZE) { - Bitu where=rx_fifo.pos+rx_fifo.used; - rx_fifo.used+=size; - while (size--) { - if (where>=FIFO_SIZE) where-=FIFO_SIZE; - rx_fifo.data[where++]=*data++; - } - if (FIFOenabled && (rx_fifo.used < FIFOsize)) return; - if (ints.active != INT_RX) raiseint(INT_RX); - } -// else LOG_MSG("WTF"); -} - -void CSerial::tx_addb(Bit8u data) { - LOG_UART("TX add %c",data); - if (tx_fifo.used=FIFO_SIZE) where-=FIFO_SIZE; - tx_fifo.data[where]=data; - tx_fifo.used++; - if (tx_fifo.used<(FIFO_SIZE-16)) { - /* Only generate FIFO irq's every 16 bytes */ - if (FIFOenabled && (tx_fifo.used & 0xf)) return; - raiseint(INT_TX); - } - } else { -// LOG_MSG("tx addb"); +void CSerial::SetModemStatus(Bit8u status) { + status&=0xf; + Bit8u oldstatus=mstatus >> 4; + if (oldstatus ^ status ) { + mstatus=(mstatus & 0xf) | status << 4; + mstatus|=(oldstatus ^ status) & ((status & 0x4) | (0xf-0x4)); } } -Bit8u CSerial::rx_readb() { - if (rx_fifo.used) { - rx_lastread=PIC_Ticks; - Bit8u val=rx_fifo.data[rx_fifo.pos]; - rx_fifo.pos++; - if (rx_fifo.pos>=FIFO_SIZE) rx_fifo.pos-=FIFO_SIZE; - rx_fifo.used--; - //Don't care for FIFO Size - if (FIFOenabled || !rx_fifo.used) lowerint(INT_RX); - else raiseint(INT_RX); - return val; - } else { -// LOG_MSG("WTF rx readb"); - return 0; - } -} - -Bit8u CSerial::tx_readb() { - if (tx_fifo.used) { - Bit8u val=tx_fifo.data[tx_fifo.pos]; - tx_fifo.pos++; - if (tx_fifo.pos>=FIFO_SIZE) tx_fifo.pos-=FIFO_SIZE; - tx_fifo.used--; - if (FIFOenabled && !tx_fifo.used) raiseint(INT_TX); - return val; - } else { -// LOG_MSG("WTF tx readb"); - return 0; - } -} - - -void CSerial::setmodemstatus(Bit8u status) { - Bitu oldstatus=mstatus >> 4; - if(oldstatus ^ status ) { - mstatus=status << 4; - mstatus|=(oldstatus ^ status); - raiseint(INT_MS); - } -} - -Bit8u CSerial::getmodemstatus() { - return (mstatus >> 4); -} - -Bit8u CSerial::getlinestatus() { - return read_port(0xd); -} - - -void CSerial::SetMCHandler(MControl_Handler * mcontrol) { - mc_handler=mcontrol; -} CSerial::CSerial (Bit16u initbase, Bit8u initirq, Bit32u initbps) { - int i; + Bitu i; Bit16u initdiv; base=initbase; irq=initirq; bps=initbps; - mc_handler = 0; - tx_fifo.used = tx_fifo.pos = 0; - rx_fifo.used = rx_fifo.pos = 0; - - rx_lastread = PIC_Ticks; - linectrl = dtr = rts = out1 = out2 = 0; local_loopback = 0; - ierval = 0; - ints.enabled=1 << INT_RX_FIFO; - ints.active=INT_NONE; - ints.requested=0; + ier = 0; + iir = 1; FIFOenabled = false; FIFOsize = 1; - timeout = 0; dlab = 0; - ierval = 0; + mstatus = 0; initdiv = SERIALBASERATE / bps; - setdivisor(initdiv >> 8, initdiv & 0x0f); + UpdateBaudrate(); - for (i=8;i<=0xf;i++) { - - IO_RegisterWriteHandler(initbase+i,write_serial,"Serial Port"); - IO_RegisterReadHandler(initbase+i,read_serial,"Serial Port"); + for (i=base;i<=(base+8);i++) { + IO_RegisterWriteHandler(i+8,WriteSerial,IO_MB); + IO_RegisterReadHandler(i+8,ReadSerial,IO_MB); } - PIC_RegisterIRQ(irq,0,"SERIAL"); - - + rqueue=new CFifo(QUEUE_SIZE); + tqueue=new CFifo(QUEUE_SIZE); }; CSerial::~CSerial(void) @@ -423,20 +250,12 @@ CSerial::~CSerial(void) }; - -CSerial *getComport(Bitu portnum) -{ - return serialports[portnum-1]; -} - void SERIAL_Init(Section* sec) { - unsigned long args = 1; Section_prop * section=static_cast(sec); // if(!section->Get_bool("enabled")) return; - serialports[0] = new CSerial(0x3f0,4,SERIALBASERATE); - serialports[1] = new CSerial(0x2f0,3,SERIALBASERATE); + TIMER_AddTickHandler(&SERIAL_Update); } diff --git a/src/hardware/softmodem.cpp b/src/hardware/softmodem.cpp index 29ab9bf..0db2814 100644 --- a/src/hardware/softmodem.cpp +++ b/src/hardware/softmodem.cpp @@ -9,28 +9,25 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * 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" #if C_MODEM +#include #include #include #include "SDL_net.h" #include "inout.h" #include "mixer.h" -#include "dma.h" #include "pic.h" -#include "hardware.h" #include "setup.h" #include "programs.h" #include "debug.h" @@ -41,32 +38,25 @@ #include "serialport.h" #define MODEMSPD 57600 -#define CONNECTED (M_CTS | M_DSR | M_DCD ) -#define DISCONNECTED (M_CTS | M_DSR ) +#define SREGS 100 -/* DTMF tone generator */ -float col[] = { 1209.0, 1336.0, 1477.0, 1633.0 }; -float row[] = { 697.0, 770.0, 852.0, 941.0 }; -char positions[] = "123A456B789C*0#D"; -#define duration 1000 -#define pause 400 - -static Bit8u tmpbuf[FIFO_SIZE+1]; +static Bit8u tmpbuf[QUEUE_SIZE]; struct ModemHd { - char cmdbuf[FIFO_SIZE]; + char cmdbuf[QUEUE_SIZE]; bool commandmode; - bool cantrans; - bool incomingcall; - bool autoanswer; - bool echo; + bool answermode; + bool echo,response,numericresponse; + bool telnetmode; Bitu cmdpause; - Bits ringcounter; - Bit16u plusinc; - Bit16u cmdpos; - + Bits ringtimer; + Bits ringcount; + Bitu plusinc; + Bitu cmdpos; + Bit8u reg[SREGS]; + TCPsocket incomingsocket; TCPsocket socket; TCPsocket listensocket; SDLNet_SocketSet socketset; @@ -83,33 +73,33 @@ struct ModemHd { Bitu diallen; Bitu dialpos; char dialstr[256]; - MIXER_Channel * chan; + // TODO: Re-enable dialtons + //MIXER_Channel * chan; }; -static CSerial * mdm; -static ModemHd mhd; +enum ResTypes { + ResNONE, + ResOK,ResERROR, + ResCONNECT,ResRING, + ResBUSY,ResNODIALTONE,ResNOCARRIER, +}; -static void sendStr(const char *usestr) { - if (!mhd.echo) return; - Bitu i=0; - while (*usestr != 0) { - if (*usestr == 10) { - mdm->rx_addb(0xd); - mdm->rx_addb(0xa); - } else { - mdm->rx_addb((Bit8u)*usestr); - } - usestr++; - } -} +#define TEL_CLIENT 0 +#define TEL_SERVER 1 -static void sendOK() { - sendStr("\nOK\n"); -} +struct telnetClient { + bool binary[2]; + bool echo[2]; + bool supressGA[2]; + bool timingMark[2]; -static void sendError() { - sendStr("\nERROR\n"); -} + bool inIAC; + bool recCommand; + Bit8u command; +}; + + +#if 1 static void toUpcase(char *buffer) { Bitu i=0; @@ -119,25 +109,127 @@ static void toUpcase(char *buffer) { } } -static void openConnection() { + + +class CSerialModem : public CSerial { +public: + ModemHd mhd; + + CSerialModem(Bit16u baseAddr, Bit8u initIrq, Bit32u initBps, const char *remotestr = NULL, Bit16u lport = 27) + : CSerial(baseAddr, initIrq, initBps) + { + + + mhd.cmdpos = 0; + mhd.commandmode = true; + mhd.plusinc = 0; + mhd.incomingsocket = 0; + mhd.answermode = false; + memset(&mhd.reg,0,sizeof(mhd.reg)); + mhd.cmdpause = 0; + mhd.echo = true; + mhd.response = true; + mhd.numericresponse = false; + + /* Default to direct null modem connection. Telnet mode interprets IAC codes */ + mhd.telnetmode = false; + + /* Bind the modem to the correct serial port */ + //strcpy(mhd.remotestr, remotestr); + + /* Initialize the sockets and setup the listening port */ + mhd.socketset = SDLNet_AllocSocketSet(1); + if (!mhd.socketset) { + LOG_MSG("MODEM:Can't open socketset:%s",SDLNet_GetError()); + //TODO Should probably just exit + return; + } + mhd.socket=0; + mhd.listenport=lport; + if (mhd.listenport) { + IPaddress listen_ip; + SDLNet_ResolveHost(&listen_ip, NULL, mhd.listenport); + mhd.listensocket=SDLNet_TCP_Open(&listen_ip); + if (!mhd.listensocket) LOG_MSG("MODEM:Can't open listen port:%s",SDLNet_GetError()); + } else mhd.listensocket=0; + + // 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); + + } + + + + void SendLine(const char *line) { + rqueue->addb(0xd); + rqueue->addb(0xa); + rqueue->adds((Bit8u *)line,strlen(line)); + rqueue->addb(0xd); + rqueue->addb(0xa); + + } + + void SendRes(ResTypes response) { + char * string;char * 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"; + case ResNODIALTONE:string="NO DIALTONE";code="6";break; + case ResNOCARRIER:string="NO CARRIER";code="3";break; + case ResCONNECT:string="CONNECT 57600";code="1";break; + } + + rqueue->addb(0xd);rqueue->addb(0xa); + rqueue->adds((Bit8u *)string,strlen(string)); + rqueue->addb(0xd);rqueue->addb(0xa); + } + + void Send(Bit8u val) { + tqueue->addb(val); + } + + Bit8u Recv(Bit8u val) { + return rqueue->getb(); + + } + + void openConnection(void) { if (mhd.socket) { LOG_MSG("Huh? already connected"); SDLNet_TCP_DelSocket(mhd.socketset,mhd.socket); SDLNet_TCP_Close(mhd.socket); } - mhd.socket = SDLNet_TCP_Open(&mhd.openip); + mhd.socket = SDLNet_TCP_Open(&openip); if (mhd.socket) { SDLNet_TCP_AddSocket(mhd.socketset,mhd.socket); - sendStr("\nCONNECT 57600\n"); + SendRes(ResCONNECT); mhd.commandmode = false; - mdm->setmodemstatus(CONNECTED); + memset(&telClient, 0, sizeof(telClient)); + updatemstatus(); } else { - sendStr("\nNO DIALTONE\n"); + SendRes(ResNODIALTONE); + } } -} -static bool Dial(char * host) { + void updatemstatus(void) { + Bit8u ms=0; + //Check for data carrier, a connection that is + if (mhd.incomingsocket) ms|=MS_RI; + if (mhd.socket) ms|=MS_DCD; + if (!mhd.commandmode) ms|=MS_DSR; + //Check for DTR reply with DSR + // if (cport->mctrl & MC_DTR) ms|=MS_DSR; + //Check for RTS reply with CTS + if (mctrl & MC_RTS) ms|=MS_CTS; + SetModemStatus(ms); + } + bool Dial(char * host) { /* Scan host for port */ Bit16u port; char * hasport=strrchr(host,':'); @@ -147,163 +239,309 @@ static bool Dial(char * host) { } else port=23; /* Resolve host we're gonna dial */ LOG_MSG("host %s port %x",host,port); - if (!SDLNet_ResolveHost(&mhd.openip,host,port)) { - /* Prepare string for dial sound generator */ - int c; - char *addrptr=host; - mhd.dialstr[0] = 'd'; - mhd.dialstr[1] = 'd'; - mhd.dialstr[2] = 'd'; - mhd.dialstr[3] = 'd'; - mhd.dialstr[4] = 'd'; - mhd.dialstr[5] = 'p'; - c=6; - while(*addrptr != 0x00) { - if (strchr(positions, *addrptr)) { - mhd.dialstr[c] = *addrptr; - c++; - } - addrptr++; - } - mhd.dialstr[c] = 0x00; - - mhd.diallen = strlen(mhd.dialstr) * (Bit32u)(duration + pause); - mhd.dialpos = 0; - mhd.f1 = 0; - mhd.f2 = 0; - mhd.dialing = true; - MIXER_Enable(mhd.chan,true); + if (!SDLNet_ResolveHost(&openip,host,port)) { + openConnection(); return true; } else { LOG_MSG("Failed to resolve host %s:%s",host,SDLNet_GetError()); - sendStr("\nNO CARRIER\n"); + SendRes(ResNOCARRIER); return false; } -} - - -static void DoCommand() { - bool found = false; - bool foundat = false; - char *foundstr; - bool connResult = false; - char msgbuf[4096]; - - Bitu result; - mhd.cmdbuf[mhd.cmdpos] = 0; - toUpcase(mhd.cmdbuf); - LOG_MSG("Modem Sent Command: %s\n", mhd.cmdbuf); - mhd.cmdpos = 0; - - result = 0; - - - /* Just for kicks */ - if ((mhd.cmdbuf[0] == 'A') && (mhd.cmdbuf[1] == 'T')) foundat = true; - if (foundat) { - if (strstr(mhd.cmdbuf,"I3")) { - sendStr("\nDosBox Emulated Modem Firmware V1.00\n"); - result = 1; - } - if (strstr(mhd.cmdbuf,"I4")) { - sprintf(msgbuf, "\nModem compiled for DosBox version %s\n", VERSION); - sendStr(msgbuf); - result = 1; - } - if (strstr(mhd.cmdbuf,"S0=1")) { - mhd.autoanswer = true; - } - if (strstr(mhd.cmdbuf,"S0=0")) { - mhd.autoanswer = false; } - if (strstr(mhd.cmdbuf,"E0")) { - mhd.echo = false; - } - if (strstr(mhd.cmdbuf,"E1")) { - mhd.echo = true; + void AcceptIncomingCall(void) { + assert(!mhd.socket); + mhd.socket=mhd.incomingsocket; + SDLNet_TCP_AddSocket(mhd.socketset,mhd.socket); + SendRes(ResCONNECT); + LOG_MSG("Connected!\n"); + + mhd.incomingsocket = 0; + mhd.commandmode = false; } - if (strstr(mhd.cmdbuf,"ATH")) { - /* Check if we're actually connected */ - if (mhd.socket) { - sendStr("\nNO CARRIER\n"); + Bitu 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 HangUp(void) { + SendRes(ResNOCARRIER); SDLNet_TCP_DelSocket(mhd.socketset,mhd.socket); SDLNet_TCP_Close(mhd.socket); mhd.socket=0; - mdm->setmodemstatus(DISCONNECTED); mhd.commandmode = true; - result = 3; - } else result = 2; + updatemstatus(); } - if(strstr(mhd.cmdbuf,"ATO")) { - /* Check for connection before switching to data mode */ - if (mhd.socket) { - mhd.commandmode = false; - result=3; + + void DoCommand() { + mhd.cmdbuf[mhd.cmdpos] = 0; + mhd.cmdpos = 0; //Reset for next command + toUpcase(mhd.cmdbuf); + LOG_MSG("Modem Sent Command: %s\n", mhd.cmdbuf); + /* Check for empty line, stops dialing and autoanswer */ + if (!mhd.cmdbuf[0]) { + if(!mhd.dialing) { + mhd.answermode = false; + goto ret_none; } else { - result=2; + //MIXER_Enable(mhd.chan,false); + mhd.dialing = false; + SendRes(ResNOCARRIER); + goto ret_none; } } - if(strstr(mhd.cmdbuf,"ATDT")) { - foundstr = strstr(mhd.cmdbuf,"ATDT"); - foundstr+=4; + /* AT command set interpretation */ + if ((mhd.cmdbuf[0] != 'A') || (mhd.cmdbuf[1] != 'T')) goto ret_error; + /* Check for dial command */ + if(strncmp(mhd.cmdbuf,"ATD3",3)==0) { + char * foundstr=&mhd.cmdbuf[3]; + if (*foundstr=='T' || *foundstr=='P') foundstr++; /* Small protection against empty line */ - if (!foundstr[0]) { - result=2; - } else { - connResult = Dial(foundstr); - result=3; + if (!foundstr[0]) goto ret_error; + 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); + goto ret_none; } + char * scanbuf; + scanbuf=&mhd.cmdbuf[2];char chr;Bitu num; + while (chr=*scanbuf++) { + switch (chr) { + 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:mhd.echo = false;break; + case 1:mhd.echo = true;break; + };break; + case 'V': + switch (num=ScanNumber(scanbuf)) { + case 0:mhd.numericresponse = true;break; + case 1:mhd.numericresponse = false;break; + };break; + case 'H': //Hang up + switch (num=ScanNumber(scanbuf)) { + case 0: + if (mhd.socket) { + HangUp(); + goto ret_none; } - if(strstr(mhd.cmdbuf,"ATA")) { - if (mhd.incomingcall) { - sendStr("\nCONNECT 57600\n"); - LOG_MSG("Connected!\n"); - MIXER_Enable(mhd.chan,false); - mdm->setmodemstatus(CONNECTED); - mhd.incomingcall = false; + //Else return ok + };break; + case 'O': //Return to data mode + switch (num=ScanNumber(scanbuf)) { + case 0: + if (mhd.socket) { mhd.commandmode = false; - SDLNet_TCP_AddSocket(mhd.socketset,mhd.socket); - result = 3; + goto ret_none; } else { + goto ret_error; + } + };break; + case 'T': //Tone Dial + case 'P': //Pulse Dial + break; + case 'M': //Monitor + case 'L': //Volume + ScanNumber(scanbuf); + break; + case 'A': //Answer call + if (mhd.incomingsocket) { + AcceptIncomingCall(); + } else { + mhd.answermode = true; + } + goto ret_none; + case 'Z': //Reset and load profiles + num=ScanNumber(scanbuf); + break; + case ' ': //Space just skip + break; + case 'S': //Registers + { + Bitu index=ScanNumber(scanbuf); + bool hasequal=(*scanbuf == '='); + if (hasequal) scanbuf++; + Bitu val=ScanNumber(scanbuf); + if (index>=SREGS) goto ret_error; + if (hasequal) mhd.reg[index]=val; + else LOG_MSG("print reg %d with %d",index,mhd.reg[index]); + };break; + default: + LOG_MSG("Unhandled cmd %c%d",chr,ScanNumber(scanbuf)); + } + } + #if 0 + if (strstr(mhd.cmdbuf,"S0=1")) { mhd.autoanswer = true; - result = 3; + } + if (strstr(mhd.cmdbuf,"S0=0")) { + mhd.autoanswer = false; + } + + if (strstr(mhd.cmdbuf,"NET0")) { + mhd.telnetmode = false; + } + if (strstr(mhd.cmdbuf,"NET1")) { + mhd.telnetmode = true; + } + #endif + LOG_MSG("Sending OK"); + SendRes(ResOK); + return; + ret_error: + LOG_MSG("Sending ERROR"); + SendRes(ResERROR); + ret_none: + return; + + } + + void MC_Changed(Bitu new_mc) { + LOG_MSG("New MC %x",new_mc ); + if (!(new_mc & 1) && mhd.socket) HangUp(); + updatemstatus(); + } + + void 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); } } - if (result==0) result = 1; - } else result=2; - - if (strlen(mhd.cmdbuf)<2) { - if(!mhd.dialing) { - result = 0; - mhd.autoanswer = false; - } else { - MIXER_Enable(mhd.chan,false); - mhd.dialing = false; - sendStr("\nNO CARRIER\n"); - result = 0; - } } - switch (result) { - case 1: - sendOK(); - break; - case 2: - sendError(); - break; - } - -} - - -static void MC_Changed(Bitu new_mc) { - - -} - -static void MODEM_Hardware(Bitu ticks) { + void Timer(void) { int result =0; unsigned long args = 1; bool sendbyte = true; @@ -313,47 +551,36 @@ static void MODEM_Hardware(Bitu ticks) { /* Check for eventual break command */ if (!mhd.commandmode) mhd.cmdpause++; /* Handle incoming data from serial port, read as much as available */ - Bitu tx_size=mdm->tx_size(); + Bitu tx_size=tqueue->inuse(); while (tx_size--) { - txval = mdm->tx_readb(); + txval = tqueue->getb(); if (mhd.commandmode) { - if(txval != 0xd) { - if(txval == 0x8) { - if (mhd.cmdpos > 0) { - --mhd.cmdpos; - } - } else { - if (txval != '+') { - if(mhd.cmdposaddb(txval); + if (txval==0xa) continue; //Real modem doesn't seem to skip this? + else if (txval==0x8 && (mhd.cmdpos > 0)) --mhd.cmdpos; + else if (txval==0xd) DoCommand(); + else if (txval != '+') { + if(mhd.cmdposrx_addb(txval); - } else if (mhd.echo) { - mdm->rx_addb(10); - mdm->rx_addb(13); - } - } else { - DoCommand(); - } } else { /* 1000 ticks have passed, can check for pause command */ if (mhd.cmdpause > 1000) { if(txval == '+') { mhd.plusinc++; if(mhd.plusinc>=3) { + LOG_MSG("Entering command mode"); mhd.commandmode = true; - sendStr("\nOK\n"); + SendRes(ResOK); mhd.plusinc = 0; } sendbyte=false; } else { mhd.plusinc=0; } -//If not a special pause command, should go for bigger blocks to send + //If not a special pause command, should go for bigger blocks to send } tmpbuf[0] = txval; @@ -367,223 +594,105 @@ static void MODEM_Hardware(Bitu ticks) { } SDLNet_CheckSockets(mhd.socketset,0); - /* Handle outgoing to the serial port */ - if(!mhd.commandmode && mhd.socket && mdm->rx_free() && SDLNet_SocketReady(mhd.socket)) { - usesize = mdm->rx_free(); + /* Handle incoming to the serial port */ + if(!mhd.commandmode && mhd.socket) { + if(rqueue->left() && SDLNet_SocketReady(mhd.socket) && (mctrl & MC_RTS)) { + usesize = rqueue->left(); + if (usesize>16) usesize=16; result = SDLNet_TCP_Recv(mhd.socket, tmpbuf, usesize); if (result>0) { - mdm->rx_adds(tmpbuf,result); + if(mhd.telnetmode) { + /* Filter telnet commands */ + TelnetEmulation(tmpbuf, result); + } else { + rqueue->adds(tmpbuf,result); + } mhd.cmdpause = 0; - } else { - /* Error close the socket and disconnect */ - mdm->setmodemstatus(DISCONNECTED); - mhd.commandmode = true; - sendStr("\nNO CARRIER\n"); - SDLNet_TCP_DelSocket(mhd.socketset,mhd.socket); - SDLNet_TCP_Close(mhd.socket); - mhd.socket=0; + } else HangUp(); } } - /* Check for incoming calls */ - if (!mhd.socket && !mhd.incomingcall && mhd.listensocket) { - mhd.socket = SDLNet_TCP_Accept(mhd.listensocket); - if (mhd.socket) { - mhd.dialpos = 0; - mhd.incomingcall = true; + if (!mhd.socket && !mhd.incomingsocket && mhd.listensocket) { + mhd.incomingsocket = SDLNet_TCP_Accept(mhd.listensocket); + if (mhd.incomingsocket) { mhd.diallen = 12000; mhd.dialpos = 0; -//TODO Set ring in Modemstatus? - sendStr("\nRING\n"); - MIXER_Enable(mhd.chan,true); - mhd.ringcounter = 24000; + SendRes(ResRING); + //MIXER_Enable(mhd.chan,true); + mhd.ringtimer = 3000; + mhd.reg[1] = 0; //Reset ring counter reg } } - - if (mhd.incomingcall) { - if (mhd.ringcounter <= 0) { - if (mhd.autoanswer) { - mhd.incomingcall = false; - sendStr("\nCONNECT 57600\n"); - MIXER_Enable(mhd.chan,false); - mdm->setmodemstatus(CONNECTED); - mhd.incomingcall = false; - mhd.commandmode = false; - SDLNet_TCP_AddSocket(mhd.socketset,mhd.socket); + if (mhd.incomingsocket) { + if (mhd.ringtimer <= 0) { + mhd.reg[1]++; + if (mhd.answermode || (mhd.reg[0]==mhd.reg[1])) { + AcceptIncomingCall(); return; } - sendStr("\nRING\n"); + SendRes(ResRING); mhd.diallen = 12000; mhd.dialpos = 0; - - MIXER_Enable(mhd.chan,true); - - mhd.ringcounter = 3000; /* Ring every three seconds for accurate emulation */ - + //MIXER_Enable(mhd.chan,true); + mhd.ringtimer = 3000; } - if (mhd.ringcounter > 0) --mhd.ringcounter; - + --mhd.ringtimer; + } + updatemstatus(); } -} + bool CanSend(void) { + return true; + } -/* -03F8 -W serial port, transmitter holding register (THR), which contains the - character to be sent. Bit 0 is sent first. - bit 7-0 data bits when DLAB=0 (Divisor Latch Access Bit) -03F8 R- receiver buffer register (RBR), which contains the received - character. Bit 0 is received first - bit 7-0 data bits when DLAB=0 (Divisor Latch Access Bit) -03F8 RW divisor latch low byte (DLL) when DLAB=1 (see #P0876) -03F9 RW divisor latch high byte (DLM) when DLAB=1 (see #P0876) -03F9 RW interrupt enable register (IER) when DLAB=0 (see #P0877) -03FA R- interrupt identification register (see #P0878) - Information about a pending interrupt is stored here. When the ID - register is addressed, thehighest priority interrupt is held, and - no other interrupts are acknowledged until the CPU services that - interrupt. -03FA -W 16650 FIFO Control Register (FCR) (see #P0879) -03FB RW line control register (LCR) (see #P0880) -03FC RW modem control register (see #P0881) -03FD R- line status register (LSR) (see #P0882) -03FE R- modem status register (MSR) (see #P0883) -03FF RW scratch register (SCR) - (not used for serial I/O; available to any application using 16450, - 16550) (not present on original 8250) -*/ + bool CanRecv(void) { + return true; + } -static void MODEM_CallBack(Bit8u * stream,Bit32u len) { - char *cp; - float ci,ri; - int innum, splitnum, quad, eighth, sixth, amp; - Bit8u curchar; - Bit32s buflen = (Bit32s)len; - if(mhd.incomingcall) { + +protected: + char cmdbuf[QUEUE_SIZE]; + bool commandmode; + bool answermode; + bool echo; + bool telnetmode; + Bitu cmdpause; + Bits ringtimer; + Bits ringcount; + Bitu plusinc; + Bitu cmdpos; - if(mhd.dialpos>=mhd.diallen) { - MIXER_Enable(mhd.chan,false); - return; - } else { - quad = (mhd.diallen/14); - eighth = quad / 2; - sixth = eighth /2; + Bit8u reg[SREGS]; + IPaddress openip; + TCPsocket incomingsocket; + TCPsocket socket; + TCPsocket listensocket; + SDLNet_SocketSet socketset; - while ((buflen>0) && (mhd.dialpos=mhd.diallen) { - while(len-->0) { - *(Bit16s*)(stream) = 0; - stream+=2; - } - MIXER_Enable(mhd.chan,false); - mhd.dialing = false; - openConnection(); - return; - } else { - while ((buflen>0) && (mhd.dialposGet_int("comport"); - strcpy(mhd.remotestr, section->Get_string("remote")); - mdm = getComport(mhd.comport); - mdm->setmodemstatus(DISCONNECTED); - mdm->SetMCHandler(&MC_Changed); - - TIMER_RegisterTickHandler(&MODEM_Hardware); - - /* Initialize the sockets and setup the listening port */ - mhd.socketset = SDLNet_AllocSocketSet(1); - if (!mhd.socketset) { - LOG_MSG("MODEM:Can't open socketset:%s",SDLNet_GetError()); -//TODO Should probably just exit - return; + if(!SDLNetInited) { + if(SDLNet_Init()==-1) { + LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError()); + return; + } + SDLNetInited = true; } - mhd.socket=0; - mhd.listenport=section->Get_int("listenport"); - if (mhd.listenport) { - IPaddress listen_ip; - SDLNet_ResolveHost(&listen_ip, NULL, mhd.listenport); - mhd.listensocket=SDLNet_TCP_Open(&listen_ip); - if (!mhd.listensocket) LOG_MSG("MODEM:Can't open listen port:%s",SDLNet_GetError()); - } else mhd.listensocket=0; - mhd.chan=MIXER_AddChannel(&MODEM_CallBack,8000,"MODEM"); - MIXER_Enable(mhd.chan,false); - MIXER_SetMode(mhd.chan,MIXER_16MONO); + Bit16u comport = section->Get_int("comport"); + + csm = NULL; + + switch (comport) { + case 1: + csm = new CSerialModem(0x3f0, 4, 57600, section->Get_string("remote"), section->Get_int("listenport")); + break; + case 2: + csm = new CSerialModem(0x2f0, 3, 57600, section->Get_string("remote"), section->Get_int("listenport")); + break; + case 3: + csm = new CSerialModem(0x3e0, 4, 57600, section->Get_string("remote"), section->Get_int("listenport")); + break; + case 4: + csm = new CSerialModem(0x2e0, 3, 57600, section->Get_string("remote"), section->Get_int("listenport")); + break; + default: + // Default to COM2 + csm = new CSerialModem(0x2f0, 3, 57600, section->Get_string("remote"), section->Get_int("listenport")); + break; + + } + + if(csm != NULL) seriallist.push_back(csm); } + #endif diff --git a/src/hardware/tandy_sound.cpp b/src/hardware/tandy_sound.cpp index 4078540..0983a28 100644 --- a/src/hardware/tandy_sound.cpp +++ b/src/hardware/tandy_sound.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -28,6 +28,7 @@ #include "setup.h" #include "pic.h" +#define DAC_CLOCK 3570000 #define MAX_OUTPUT 0x7fff #define STEP 0x10000 @@ -70,20 +71,22 @@ struct SN76496 static struct SN76496 sn; static struct { - MIXER_Channel * chan; + MixerChannel * chan; bool enabled; Bitu last_write; + struct { + bool playing; + Bitu rate; + } dac; } tandy; - -static void SN76496Write(Bit32u port,Bit8u data) -{ +static void SN76496Write(Bitu port,Bitu data,Bitu iolen) { struct SN76496 *R = &sn; tandy.last_write=PIC_Ticks; if (!tandy.enabled) { - MIXER_Enable(tandy.chan,true); + tandy.chan->Enable(true); tandy.enabled=true; } @@ -155,15 +158,15 @@ static void SN76496Write(Bit32u port,Bit8u data) } } -static void SN76496Update(Bit8u * stream,Bit32u length) +static void SN76496Update(Bitu length) { - if ((tandy.last_write+1000)Enable(false); } int i; struct SN76496 *R = &sn; - Bit16s * buffer=(Bit16s *)stream; + Bit16s * buffer=(Bit16s *)MixTemp; /* If the volume is 0, increase the counter */ for (i = 0;i < 4;i++) @@ -177,7 +180,8 @@ static void SN76496Update(Bit8u * stream,Bit32u length) } } - while (length > 0) + Bitu count=length; + while (count) { int vol[4]; unsigned int out; @@ -246,8 +250,9 @@ static void SN76496Update(Bit8u * stream,Bit32u length) *(buffer++) = out / STEP; - length--; + count--; } + tandy.chan->AddSamples_m16(length,(Bit16s *)MixTemp); } @@ -267,6 +272,12 @@ static void SN76496_set_clock(int 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) { @@ -298,17 +309,17 @@ static void SN76496_set_gain(int gain) void TANDYSOUND_Init(Section* sec) { + if (machine!=MCH_TANDY) return; Section_prop * section=static_cast(sec); - if(!section->Get_bool("tandy")) return; - IO_RegisterWriteHandler(0xc0,SN76496Write,"Tandy Sound"); + IO_RegisterWriteHandler(0xc0,SN76496Write,IO_MB,2); + IO_RegisterWriteHandler(0xc4,TandyDACWrite,IO_MB,4); + Bit32u sample_rate = section->Get_int("tandyrate"); tandy.chan=MIXER_AddChannel(&SN76496Update,sample_rate,"TANDY"); - MIXER_Enable(tandy.chan,false); tandy.enabled=false; - MIXER_SetMode(tandy.chan,MIXER_16MONO); Bitu i; struct SN76496 *R = &sn; diff --git a/src/hardware/timer.cpp b/src/hardware/timer.cpp index b8a9fe8..7fe8638 100644 --- a/src/hardware/timer.cpp +++ b/src/hardware/timer.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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: timer.cpp,v 1.20 2004/01/10 11:43:41 qbix79 Exp $ */ +/* $Id: timer.cpp,v 1.29 2004/09/10 22:15:20 harekiet Exp $ */ #include "dosbox.h" #include "inout.h" @@ -26,71 +26,106 @@ #include "dosbox.h" #include "mixer.h" #include "timer.h" +#include "math.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 { - Bit8u mode; /* Current Counter Mode */ - Bitu cntr; - Bits micro; - Bit64u start; - + float delay; + double start; + + Bit16u read_latch; + Bit16u write_latch; + + Bit8u mode; Bit8u latch_mode; Bit8u read_state; - Bit16s read_latch; Bit8u write_state; - Bit16u write_latch; + + bool bcd; + bool go_read_latch; + bool new_mode; }; static PIT_Block pit[3]; -static void PIT0_Event(void) { +static void PIT0_Event(Bitu val) { PIC_ActivateIRQ(0); - if (pit[0].mode!=0) PIC_AddEvent(PIT0_Event,pit[0].micro); + if (pit[0].mode!=0) PIC_AddEvent(PIT0_Event,pit[0].delay); +} + +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; + default: + LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading output",p->mode); + return true; + } } static void counter_latch(Bitu counter) { /* Fill the read_latch of the selected counter with current count */ PIT_Block * p=&pit[counter]; - - Bit64s micro=PIC_MicroCount()-p->start; - + p->go_read_latch=false; + 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 (micro>p->micro) { - micro-=p->micro; - micro%=(Bit64u)(1000000/((float)PIT_TICK_RATE/(float)0x10000)); - p->read_latch=(Bit16u)(0x10000-(((double)micro/(double)p->micro)*(double)0x10000)); + if (index>p->delay) { + index-=p->delay; + index=fmod(index,(1000.0/PIT_TICK_RATE)*0x1000); + p->read_latch=(Bit16u)(0xffff-index*0xffff); } else { - p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); + p->read_latch=(Bit16u)(p->cntr-index*(PIT_TICK_RATE/1000.0)); } break; case 2: /* Rate Generator */ - micro%=p->micro; - p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); + index=fmod(index,(double)p->delay); + p->read_latch=(Bit16u)(p->cntr - (index/p->delay)*p->cntr); break; case 3: /* Square Wave Rate Generator */ - micro%=p->micro; - micro*=2; - if (micro>p->micro) micro-=p->micro; - p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); - break; - case 4: /* Software Triggered Strobe */ - if (micro>p->micro) p->read_latch=p->write_latch; - else p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); + 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); break; default: LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading counter %d",p->mode,counter); - micro%=p->micro; - p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); + p->read_latch=0xffff; break; } } -static void write_latch(Bit32u port,Bit8u val) { +static void write_latch(Bitu port,Bitu val,Bitu iolen) { 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); @@ -106,17 +141,22 @@ static void write_latch(Bit32u port,Bit8u val) { 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->start=PIC_MicroCount(); - p->micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)p->cntr)); + } + 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; + p->start=PIC_FullIndex(); + p->delay=(1000.0f/((float)PIT_TICK_RATE/(float)p->cntr)); switch (counter) { case 0x00: /* Timer hooked to IRQ 0 */ - PIC_RemoveEvents(PIT0_Event); - PIC_AddEvent(PIT0_Event,p->micro); - LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,(Bit32u)p->mode); + if (p->new_mode) { + p->new_mode=false; + 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 %.2f 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); @@ -128,16 +168,18 @@ static void write_latch(Bit32u port,Bit8u val) { } } -static Bit8u read_latch(Bit32u port) { +static Bitu read_latch(Bitu port,Bitu iolen) { Bit32u counter=port-0x40; - if (pit[counter].read_latch == -1) + if (pit[counter].go_read_latch == true) counter_latch(counter); Bit8u ret; + 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].read_latch = -1; + pit[counter].go_read_latch = true; break; case 3: /* read LSB followed by MSB */ ret = (pit[counter].read_latch & 0xff); @@ -147,27 +189,32 @@ static Bit8u read_latch(Bit32u port) { break; case 1: /* read LSB */ ret = (pit[counter].read_latch & 0xff); - pit[counter].read_latch = -1; + pit[counter].go_read_latch = true; break; case 2: /* read MSB */ ret = (pit[counter].read_latch >> 8) & 0xff; - pit[counter].read_latch = -1; + pit[counter].go_read_latch = true; break; default: ret=0; E_Exit("Timer.cpp: error in readlatch"); break; - } - return ret; + } + if( pit[counter].bcd == true) BCD2BIN(pit[counter].read_latch); + return ret; } -static void write_p43(Bit32u port,Bit8u val) { +static void write_p43(Bitu port,Bitu val,Bitu iolen) { Bitu latch=(val >> 6) & 0x03; switch (latch) { case 0: case 1: case 2: - if (val & 1) E_Exit("PIT:Timer %d set to unsupported bcd mode",latch); + pit[latch].bcd = (val&1)>0; + if (val & 1) { + if(pit[latch].cntr>=9999) pit[latch].cntr=9999; + } + if ((val & 0x30) == 0) { /* Counter latch command */ counter_latch(latch); @@ -175,6 +222,14 @@ static void write_p43(Bit32u port,Bit8u val) { pit[latch].read_state = (val >> 4) & 0x03; pit[latch].write_state = (val >> 4) & 0x03; pit[latch].mode = (val >> 1) & 0x07; + if (pit[latch].mode>5) + pit[latch].mode-=4; //6,7 become 2 and 3 + if (latch==0) { + PIC_RemoveEvents(PIT0_Event); + if (!counter_output(0) && pit[latch].mode) + PIC_ActivateIRQ(0); + } + pit[latch].new_mode = true; } break; case 3: @@ -191,27 +246,43 @@ static void write_p43(Bit32u port,Bit8u val) { void TIMER_Init(Section* sect) { - 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"); + IO_RegisterWriteHandler(0x40,write_latch,IO_MB); +// IO_RegisterWriteHandler(0x41,write_latch,IO_MB); + IO_RegisterWriteHandler(0x42,write_latch,IO_MB); + IO_RegisterWriteHandler(0x43,write_p43,IO_MB); + IO_RegisterReadHandler(0x40,read_latch,IO_MB); + IO_RegisterReadHandler(0x41,read_latch,IO_MB); + IO_RegisterReadHandler(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=-1; + 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].micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)pit[0].cntr)); - pit[2].micro=100; - pit[2].read_latch=-1; /* MadTv1 */ + 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[2].read_latch=0; /* 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; - PIC_AddEvent(PIT0_Event,pit[0].micro); + 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)); + + PIC_AddEvent(PIT0_Event,pit[0].delay); } diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index 3b9c325..a5f6d63 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -48,11 +48,30 @@ void VGA_SetMode(VGAModes mode) { VGA_StartResize(); } +void VGA_DetermineMode(void) { + /* Test for VGA output active or direct color modes */ + if (vga.s3.misc_control_2 & 0xf0) { + switch (vga.s3.misc_control_2 >> 4) { + case 1:VGA_SetMode(M_LIN8);break; + } + /* Test for graphics or alphanumeric mode */ + } else if (vga.attr.mode_control & 1) { + if (!(vga.crtc.mode_control & 0x1)) { + if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4); + else VGA_SetMode(M_CGA2); + } else if (vga.attr.mode_control & 0x40) { + VGA_SetMode(M_VGA); + } else VGA_SetMode(M_EGA16); + } else { + VGA_SetMode(M_TEXT); + } +} + void VGA_StartResize(void) { if (!vga.draw.resizing) { vga.draw.resizing=true; /* Start a resize after 50 ms */ - PIC_AddEvent(VGA_SetupDrawing,50000); + PIC_AddEvent(VGA_SetupDrawing,50); } } @@ -88,34 +107,57 @@ void VGA_SetClock(Bitu which,Bitu target) { 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 + } +} void VGA_Init(Section* sec) { vga.draw.resizing=false; + vga.mode=M_ERROR; //For first init VGA_SetupMemory(); 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); -#ifdef WORDS_BIGENDIAN - CGA_4_Table[i]=((i>>0)&3) | (((i>>2)&3) << 8)| (((i>>4)&3) <<16) | (((i>>6)&3) << 24); -#else - CGA_4_Table[i]=((i>>6)&3) | (((i>>4)&3) << 8)| (((i>>2)&3) <<16) | (((i>>0)&3) << 24); - - -#endif } 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 - CGA_2_Table[i]=((i>>0)&1) | (((i>>1)&1) << 8)| (((i>>1)&1) <<16) | (((i>>3)&1) << 24); FillTable[i]= ((i & 1) ? 0xff000000 : 0) | ((i & 2) ? 0x00ff0000 : 0) | @@ -127,7 +169,6 @@ void VGA_Init(Section* sec) { ((i & 4) ? 0x00ff0000 : 0) | ((i & 8) ? 0xff000000 : 0) ; #else - CGA_2_Table[i]=((i>>3)&1) | (((i>>2)&1) << 8)| (((i>>1)&1) <<16) | (((i>>0)&1) << 24); FillTable[i]= ((i & 1) ? 0x000000ff : 0) | ((i & 2) ? 0x0000ff00 : 0) | @@ -138,7 +179,6 @@ void VGA_Init(Section* sec) { ((i & 2) ? 0x00ff0000 : 0) | ((i & 4) ? 0x0000ff00 : 0) | ((i & 8) ? 0x000000ff : 0) ; - #endif } for (j=0;j<4;j++) { diff --git a/src/hardware/vga_attr.cpp b/src/hardware/vga_attr.cpp index a486344..344c91f 100644 --- a/src/hardware/vga_attr.cpp +++ b/src/hardware/vga_attr.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -23,13 +23,12 @@ #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); - else val|=(vga.attr.color_select & 0xc) << 4; + else val=(val & 63) | (vga.attr.color_select & 0xc) << 4; VGA_DAC_CombineColor(index,val); } -void write_p3c0(Bit32u port,Bit8u val) { +void write_p3c0(Bitu port,Bitu val,Bitu iolen) { if (!vga.internal.attrindex) { attr(index)=val & 0x1F; vga.internal.attrindex=true; @@ -69,16 +68,9 @@ void write_p3c0(Bit32u port,Bit8u val) { Doesn't work if they program EGA16 themselves, but haven't encountered that yet */ - if (val&0x40) { - if (vga.mode0x7) vga.config.pel_panning=0; else vga.config.pel_panning=val+1; @@ -165,7 +156,7 @@ void write_p3c0(Bit32u port,Bit8u val) { } } -Bit8u read_p3c1(Bit32u port) { +Bitu read_p3c1(Bitu port,Bitu iolen) { vga.internal.attrindex=false; switch (attr(index)) { /* Palette */ @@ -196,8 +187,10 @@ Bit8u read_p3c1(Bit32u port) { void VGA_SetupAttr(void) { - IO_RegisterWriteHandler(0x3c0,write_p3c0,"VGA Attribute controller"); - IO_RegisterReadHandler(0x3c1,read_p3c1,"VGA Attribute Read"); + if (machine==MCH_VGA) { + IO_RegisterWriteHandler(0x3c0,write_p3c0,IO_MB); + IO_RegisterReadHandler(0x3c1,read_p3c1,IO_MB); + } } diff --git a/src/hardware/vga_crtc.cpp b/src/hardware/vga_crtc.cpp index e957f8e..f764781 100644 --- a/src/hardware/vga_crtc.cpp +++ b/src/hardware/vga_crtc.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -22,19 +22,24 @@ #include "debug.h" #include "cpu.h" - #define crtc(blah) vga.crtc.blah -void write_p3d4(Bit32u port,Bit8u val) { + +void VGA_MapMMIO(void); +void VGA_UnmapMMIO(void); + +void write_p3d5_vga(Bitu port,Bitu val,Bitu iolen); +Bitu DEBUG_EnableDebugger(void); + +void write_p3d4_vga(Bitu port,Bitu val,Bitu iolen) { crtc(index)=val; } -Bit8u read_p3d4(Bit32u port) { +Bitu read_p3d4_vga(Bitu port,Bitu iolen) { return crtc(index); } - -void write_p3d5(Bit32u port,Bit8u val) { +void write_p3d5_vga(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 */ @@ -219,12 +224,10 @@ void write_p3d5(Bit32u port,Bit8u val) { */ break; case 0x13: /* Offset register */ - if (val!=crtc(offset)) { - crtc(offset)=val; - vga.config.scan_len&=0x300; - vga.config.scan_len|=val; - VGA_StartResize(); - } + 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. @@ -258,6 +261,7 @@ void write_p3d5(Bit32u port,Bit8u val) { break; case 0x17: /* Mode Control Register */ crtc(mode_control)=val; + VGA_DetermineMode(); /* 0 If clear use CGA compatible memory addressing system by substituting character row scan counter bit 0 for address bit 13, @@ -328,12 +332,15 @@ void write_p3d5(Bit32u port,Bit8u val) { case 0x39: /* CR39 Register Lock 2 */ vga.s3.reg_lock2=val; break; + case 0x40: /* CR40 System Config */ + vga.s3.reg_40 = 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_StartResize(); + VGA_CheckScanLength(); } break; /* @@ -341,6 +348,43 @@ void write_p3d5(Bit32u port,Bit8u val) { (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; + 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 = vga.s3.hgc.startaddr | ((val & 0xff) << 8); + break; + case 0x4d: /* HGC start address low byte*/ + vga.s3.hgc.startaddr = vga.s3.hgc.startaddr | (val & 0xff); + break; + case 0x4e: /* HGC pattern start X */ + vga.s3.hgc.posx = val; + break; + case 0x4f: /* HGC pattern start X */ + vga.s3.hgc.posy = val; + break; case 0x51: /* Extended System Control 2 */ vga.s3.reg_51=val & 0xc0; //Only store bits 6,7 //TODO Display start @@ -354,7 +398,7 @@ void write_p3d5(Bit32u port,Bit8u val) { if (((val & 0x30) ^ (vga.config.scan_len >> 4)) & 0x30) { vga.config.scan_len&=0xff; vga.config.scan_len|=(val & 0x30) << 4; - VGA_StartResize(); + VGA_CheckScanLength(); } break; /* @@ -377,6 +421,18 @@ void write_p3d5(Bit32u port,Bit8u val) { 7 (not 864/964) Enable EPROM Write. If set enables flash memory write control to the BIOS ROM address */ + case 0x53: + if((val & 0x10) != (vga.s3.ext_mem_ctrl & 0x10)) { + /* Map or unmap MMIO */ + if ((val & 0x10) != 0) { + LOG_MSG("VGA: Mapping Memory Mapped I/O to 0xA0000"); + VGA_MapMMIO(); + } else { + VGA_UnmapMMIO(); + } + } + vga.s3.ext_mem_ctrl = val; + break; case 0x55: /* Extended Video DAC Control */ vga.s3.reg_55=val; break; @@ -481,6 +537,21 @@ void write_p3d5(Bit32u port,Bit8u val) { (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. + 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; @@ -497,7 +568,7 @@ void write_p3d5(Bit32u port,Bit8u val) { } } -Bit8u read_p3d5(Bit32u port) { +Bitu read_p3d5_vga(Bitu port,Bitu iolen) { // LOG_MSG("VGA CRCT read from reg %X",crtc(index)); switch(crtc(index)) { case 0x00: /* Horizontal Total Register */ @@ -560,7 +631,7 @@ Bit8u read_p3d5(Bit32u port) { return 0x11; //Trio 64 id case 0x2f: /* Revision */ - return 0x80; + return 0x00; case 0x30: /* CR30 Chip ID/REV register */ return 0xe0; //Trio+ dual byte // Trio32/64 has 0xe0. extended @@ -570,7 +641,8 @@ Bit8u read_p3d5(Bit32u port) { case 0x35: /* CR35 CRT Register Lock */ return vga.s3.reg_35|(vga.s3.bank & 0xf); case 0x36: /* CR36 Reset State Read 1 */ - return 0x8f; + //return 0x8f; + return 0x8e; /* PCI version */ //2 Mb PCI and some bios settings case 0x37: /* Reset state read 2 */ return 0x2b; @@ -578,21 +650,35 @@ Bit8u read_p3d5(Bit32u port) { return vga.s3.reg_lock1; case 0x39: /* CR39 Register Lock 2 */ return vga.s3.reg_lock2; + case 0x40: /* CR40 system config */ + return vga.s3.reg_40; 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; case 0x51: /* Extended System Control 2 */ return ((vga.config.display_start >> 16) & 3 ) | ((vga.s3.bank & 0x30) >> 2) | ((vga.config.scan_len & 0x300) >> 4) | vga.s3.reg_51; + 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 */ diff --git a/src/hardware/vga_dac.cpp b/src/hardware/vga_dac.cpp index 4fcb0f8..cae4696 100644 --- a/src/hardware/vga_dac.cpp +++ b/src/hardware/vga_dac.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -51,36 +51,37 @@ Note: Each read or write of this register will cycle through first the enum {DAC_READ,DAC_WRITE}; -static void write_p3c6(Bit32u port,Bit8u val) { +static void write_p3c6(Bitu port,Bitu val,Bitu iolen) { if (val!=0xff) LOG(LOG_VGAGFX,LOG_NORMAL)("VGA:Pel Mask not 0xff"); vga.dac.pel_mask=val; } -static Bit8u read_p3c6(Bit32u port) { +static Bitu read_p3c6(Bitu port,Bitu iolen) { return vga.dac.pel_mask; } -static void write_p3c7(Bit32u port,Bit8u val) { +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; } -static Bit8u read_p3c7(Bit32u port) { +static Bitu read_p3c7(Bitu port,Bitu iolen) { if (vga.dac.state==DAC_READ) return 0x3; else return 0x0; } -static void write_p3c8(Bit32u port,Bit8u val) { +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 void write_p3c9(Bit32u port,Bit8u val) { +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; @@ -104,7 +105,7 @@ static void write_p3c9(Bit32u port,Bit8u val) { default: /* Check for attributes and DAC entry link */ for (Bitu i=0;i<16;i++) { - if (vga.dac.attr[i]==vga.dac.write_index) { + if (vga.attr.palette[i]==vga.dac.write_index) { RENDER_SetPal(i, vga.dac.rgb[vga.dac.write_index].red << 2, vga.dac.rgb[vga.dac.write_index].green << 2, @@ -120,7 +121,7 @@ static void write_p3c9(Bit32u port,Bit8u val) { }; } -static Bit8u read_p3c9(Bit32u port) { +static Bitu read_p3c9(Bitu port,Bitu iolen) { Bit8u ret; switch (vga.dac.pel_index) { case 0: @@ -144,7 +145,7 @@ static Bit8u read_p3c9(Bit32u port) { void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal) { /* Check if this is a new color */ - vga.dac.attr[attr]=pal; + vga.attr.palette[attr]=pal; switch (vga.mode) { case M_VGA: case M_LIN8: @@ -158,6 +159,20 @@ void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal) { } } +void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue) { + vga.dac.rgb[entry].red=red; + vga.dac.rgb[entry].green=green; + vga.dac.rgb[entry].blue=blue; + switch (vga.mode) { + case M_VGA: + case M_LIN8: + return; + } + for (Bitu i=0;i<16;i++) + if (vga.attr.palette[i]==entry) + RENDER_SetPal(i,red << 2,green << 2,blue << 2); +} + void VGA_SetupDAC(void) { vga.dac.first_changed=256; vga.dac.bits=6; @@ -166,14 +181,16 @@ void VGA_SetupDAC(void) { vga.dac.state=DAC_READ; vga.dac.read_index=0; vga.dac.write_index=0; - /* Setup the DAC IO port Handlers */ - IO_RegisterWriteHandler(0x3c6,write_p3c6,"PEL Mask"); - IO_RegisterReadHandler(0x3c6,read_p3c6,"PEL Mask"); - IO_RegisterWriteHandler(0x3c7,write_p3c7,"PEL Read Mode"); - IO_RegisterReadHandler(0x3c7,read_p3c7,"PEL Status Mode"); - IO_RegisterWriteHandler(0x3c8,write_p3c8,"PEL Write Mode"); - IO_RegisterWriteHandler(0x3c9,write_p3c9,"PEL Data"); - IO_RegisterReadHandler(0x3c9,read_p3c9,"PEL Data"); + if (machine==MCH_VGA) { + /* 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_RegisterWriteHandler(0x3c9,write_p3c9,IO_MB); + IO_RegisterReadHandler(0x3c9,read_p3c9,IO_MB); + } }; diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 103b821..3fcf67e 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -29,56 +29,52 @@ typedef Bit8u * (* VGA_Line_Handler)(Bitu vidstart,Bitu panning,Bitu line); static VGA_Line_Handler VGA_DrawLine; +static Bit8u TempLine[1280]; -static Bit8u * VGA_HERC_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { - Bit8u * reader=&vga.mem.linear[vidstart+(line * 8 * 1024)]; - Bit32u * draw=(Bit32u *)RENDER_TempLine; +static Bit8u * VGA_Draw_1BPP_Line(Bitu vidstart,Bitu panning,Bitu line) { + line*=8*1024;Bit32u * draw=(Bit32u *)TempLine; for (Bitu x=vga.draw.blocks;x>0;x--) { - Bitu val=*reader++; + Bitu val=vga.mem.linear[vidstart+line]; + vidstart=(vidstart+1)&0x1dfff; *draw++=CGA_2_Table[val >> 4]; *draw++=CGA_2_Table[val & 0xf]; } - return RENDER_TempLine; + return TempLine; } -static Bit8u * VGA_CGA2_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { - line*=8*1024;Bit32u * draw=(Bit32u *)RENDER_TempLine; - for (Bitu x=vga.draw.blocks;x>0;x--) { - Bitu val=vga.mem.linear[vidstart+line];vidstart=(vidstart+1)&0x1fff; - *draw++=CGA_2_Table[val >> 4]; - *draw++=CGA_2_Table[val & 0xf]; - } - return RENDER_TempLine; -} - -static Bit8u * VGA_CGA4_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { - line*=8*1024;Bit32u * draw=(Bit32u *)RENDER_TempLine; +static Bit8u * VGA_Draw_2BPP_Line(Bitu vidstart,Bitu panning,Bitu line) { + line*=8*1024;Bit32u * draw=(Bit32u *)TempLine; for (Bitu x=0;x> 4] | convert16[val & 0xf] << 16; - *draw++=full|=full<<8; + Bitu val1=*reader++; + Bitu val2=convert16[val1&0xf]; + val1=convert16[val1 >> 4]; + *draw++=(val1 << 0) | + (val1 << 8) | + (val2 << 16) | + (val2 << 24); } - return RENDER_TempLine; + return TempLine; } -static Bit8u * VGA_TANDY16_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { - Bit8u * reader=&vga.mem.linear[(vga.tandy.disp_bank << 14) + vidstart + (line * 8 * 1024)]; - Bit32u * draw=(Bit32u *)RENDER_TempLine; +static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart,Bitu panning,Bitu line) { + Bit8u * reader=&vga.mem.linear[vidstart + (line * 8 * 1024)]; + Bit32u * draw=(Bit32u *)TempLine; for (Bitu x=0;x> 4 | + (val2 & 0x0f) << 24 | + (val2 & 0xf0) << 12; + } + return TempLine; +} + + +static Bit8u * VGA_Draw_EGA_Line(Bitu vidstart,Bitu panning,Bitu line) { return &vga.mem.linear[512*1024+vidstart*8+panning]; } -static Bit8u * VGA_VGA_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { +static Bit8u * VGA_Draw_VGA_Line(Bitu vidstart,Bitu panning,Bitu line) { return &vga.mem.linear[vidstart*4+panning]; } +static Bit8u * VGA_Draw_VGA_Line_HWMouse(Bitu vidstart, Bitu panning, Bitu line) { + if(vga.s3.hgc.curmode & 0x1) { + Bitu lineat = vidstart / 160; + if((lineat < vga.s3.hgc.originy) || (lineat > (vga.s3.hgc.originy + 63))) { + return VGA_Draw_VGA_Line(vidstart, panning, line); + } else { + memcpy(TempLine, VGA_Draw_VGA_Line(vidstart, panning, line), 640); + /* Draw mouse cursor */ + Bits moff = ((Bits)lineat - (Bits)vga.s3.hgc.originy) + (Bits)vga.s3.hgc.posy; + if(moff>63) moff=moff-64; + if(moff<0) moff+=64; + Bitu xat = vga.s3.hgc.originx; + Bitu m, mat; + mat = vga.s3.hgc.posx; + + for(m=0;m<64;m++) { + switch(vga.s3.hgc.mc[moff][mat]) { + case 0: + TempLine[xat] = vga.s3.hgc.backstack[0]; + break; + case 1: + TempLine[xat] = vga.s3.hgc.forestack[0]; + break; + case 2: + //Transparent + break; + case 3: + break; + } + xat++; + mat++; + if(mat>63) mat=0; + } + return TempLine; + } + } else { + /* HW Mouse not enabled, use the tried and true call */ + return VGA_Draw_VGA_Line(vidstart, panning, line); + } +} static Bit32u FontMask[2]={0xffffffff,0x0}; static Bit8u * VGA_TEXT_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { - Bit32u * draw=(Bit32u *)RENDER_TempLine; + Bit32u * draw=(Bit32u *)TempLine; Bit8u * vidmem=&vga.mem.linear[vidstart]; for (Bitu cx=0;cx>4]; - Bit32u mask2=TXT_Font_Table[font&0xf]; Bitu col=vidmem[cx*2+1]; + Bitu font=vga.draw.font_tables[(col >> 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&=FontMask[col >> 7];mask2&=FontMask[col >> 7]; *draw++=fg&mask1 | bg&~mask1; *draw++=fg&mask2 | bg&~mask2; } - Bits font_addr=(vga.config.cursor_start*2-vidstart)/2; + Bits font_addr=(vga.draw.cursor.address-vidstart)/2; if (!vga.draw.cursor.enabled || !(vga.draw.cursor.count&0x8)) goto skip_cursor; if (font_addr>=0 && font_addrvga.draw.cursor.eline) goto skip_cursor; - draw=(Bit32u *)&RENDER_TempLine[font_addr*8]; - Bit32u att=TXT_FG_Table[vga.mem.linear[vga.config.cursor_start*2+1]&0xf]; + draw=(Bit32u *)&TempLine[font_addr*8]; + Bit32u att=TXT_FG_Table[vga.mem.linear[vga.draw.cursor.address+1]&0xf]; *draw++=att;*draw++=att; } skip_cursor: - return RENDER_TempLine; + return TempLine; } -static void VGA_VerticalDisplayEnd(void) { +static void VGA_VerticalDisplayEnd(Bitu val) { vga.config.retrace=true; vga.config.real_start=vga.config.display_start; } @@ -135,11 +184,9 @@ static void VGA_HorizontalTimer(void) { } -static void VGA_DrawPart(void) { - Bitu subline=0;Bitu vidofs=vga.config.real_start; - Bit8u * draw=0; - while (vga.draw.lines_left) { - vga.draw.lines_left--; +static void VGA_DrawPart(Bitu lines) { + while (lines--) { + vga.draw.lines_done++; Bit8u * data=VGA_DrawLine(vga.draw.address,vga.draw.panning,vga.draw.address_line); RENDER_DrawLine(data); vga.draw.address_line++; @@ -147,14 +194,17 @@ static void VGA_DrawPart(void) { vga.draw.address_line=0; vga.draw.address+=vga.draw.address_add; } - if (vga.draw.split_line==vga.draw.lines_left) { + if (vga.draw.split_line==vga.draw.lines_done) { vga.draw.address=0;vga.draw.panning=0; vga.draw.address_line=0; } } - RENDER_EndUpdate(); -// vga.draw.parts_left--; -// if (vga.draw.parts_left) PIC_AddEvent(VGA_DrawPart,vga.draw.micro.parts); + if (--vga.draw.parts_left) { + PIC_AddEvent(VGA_DrawPart,vga.draw.delay.parts, + (vga.draw.parts_left!=1) ? vga.draw.parts_lines : (vga.draw.lines_total - vga.draw.lines_done)); + } else { + RENDER_EndUpdate(); + } } void VGA_SetBlinking(Bitu enabled) { @@ -163,212 +213,284 @@ void VGA_SetBlinking(Bitu enabled) { if (enabled) { b=0;vga.draw.blinking=1; //used to -1 but blinking is unsigned vga.attr.mode_control|=0x08; - vga.cga.mode_control&=~0x20; + vga.tandy.mode_control|=0x20; } else { b=8;vga.draw.blinking=0; vga.attr.mode_control&=~0x08; - vga.cga.mode_control|=0x20; + 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); } -static void VGA_VerticalTimer(void) { +static void VGA_VerticalTimer(Bitu val) { vga.config.retrace=false; - PIC_AddEvent(VGA_VerticalTimer,vga.draw.micro.vtotal); - PIC_AddEvent(VGA_VerticalDisplayEnd,vga.draw.micro.vend); - vga.draw.parts_left=4; - vga.draw.lines_left=vga.draw.lines_total; - vga.draw.address=vga.config.real_start; - vga.draw.address_line=vga.config.hlines_skip; - vga.draw.split_line=vga.draw.lines_total-(vga.config.line_compare/vga.draw.lines_scaled); - vga.draw.panning=vga.config.pel_panning; + PIC_AddEvent(VGA_VerticalTimer,vga.draw.delay.vtotal); + PIC_AddEvent(VGA_VerticalDisplayEnd,vga.draw.delay.vend); + if (RENDER_StartUpdate()) { + vga.draw.parts_left=vga.draw.parts_total; + vga.draw.lines_done=0; + vga.draw.address=vga.config.real_start; + vga.draw.address_line=vga.config.hlines_skip; + vga.draw.split_line=(vga.config.line_compare/vga.draw.lines_scaled); + vga.draw.panning=vga.config.pel_panning; + PIC_AddEvent(VGA_DrawPart,vga.draw.delay.parts,vga.draw.parts_lines); + } switch (vga.mode) { - case M_TEXT2:case M_TEXT16: + case M_TEXT: + vga.draw.address=(vga.draw.address*2); + 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.attr.mode_control & (vga.draw.cursor.count >> 1) & 0x8) ? + FontMask[1]=(vga.draw.blinking & (vga.draw.cursor.count >> 4)) ? 0 : 0xffffffff; - vga.draw.address=(vga.draw.address*2); break; case M_CGA4:case M_CGA2:case M_CGA16: + case M_TANDY2:case M_TANDY4:case M_TANDY16: vga.draw.address=(vga.draw.address*2)&0x1fff; break; } - if (RENDER_StartUpdate()) { - VGA_DrawPart(); + if (machine==MCH_TANDY) { + vga.draw.address+=vga.tandy.disp_bank << 14; + vga.draw.cursor.address+=vga.tandy.disp_bank << 14; } } -void VGA_SetupDrawing(void) { - /* Calculate the FPS for this screen */ - double fps; - Bitu vtotal=2 + vga.crtc.vertical_total | - ((vga.crtc.overflow & 1) << 8) | ((vga.crtc.overflow & 0x20) << 4); - Bitu htotal=5 + vga.crtc.horizontal_total; - Bitu vdispend = 1 + (vga.crtc.vertical_display_end | - ((vga.crtc.overflow & 2)<<7) | ((vga.crtc.overflow & 0x40) << 3) | - ((vga.s3.ex_ver_overflow & 0x2) << 9)); - Bitu hdispend = 1 + (vga.crtc.horizontal_display_end); - - Bitu hbstart = vga.crtc.start_horizontal_blanking; - Bitu vbstart = vga.crtc.start_vertical_blanking | ((vga.crtc.overflow & 0x08) << 5) | - ((vga.crtc.maximum_scan_line & 0x20) << 4) ; - - Bitu hrstart = vga.crtc.start_horizontal_retrace; - Bitu vrstart = vga.crtc.vertical_retrace_start + ((vga.crtc.overflow & 0x04) << 6) | - ((vga.crtc.overflow & 0x80) << 2); - - if (hbstart> 2) & 3; - clock=1000*S3_CLOCK(vga.s3.clk[clock].m,vga.s3.clk[clock].n,vga.s3.clk[clock].r); - /* 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; +void VGA_CheckScanLength(void) { + switch (vga.mode) { + case M_EGA16: + case M_VGA: + case M_LIN8: + vga.draw.address_add=vga.config.scan_len*2; + 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/2; + 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; + } +} + +void VGA_SetupDrawing(Bitu val) { + if (vga.mode==M_ERROR) { + PIC_RemoveEvents(VGA_VerticalTimer); + PIC_RemoveEvents(VGA_VerticalDisplayEnd); + return; + } + /* Calculate the FPS for this screen */ + float fps;Bitu clock; + Bitu htotal,hdispend,hbstart,hrstart; + Bitu vtotal,vdispend,vbstart,vrstart; + if (machine==MCH_VGA) { + vtotal=2 + vga.crtc.vertical_total | + ((vga.crtc.overflow & 1) << 8) | ((vga.crtc.overflow & 0x20) << 4); + htotal=5 + vga.crtc.horizontal_total; + vdispend = 1 + (vga.crtc.vertical_display_end | + ((vga.crtc.overflow & 2)<<7) | ((vga.crtc.overflow & 0x40) << 3) | + ((vga.s3.ex_ver_overflow & 0x2) << 9)); + hdispend = 1 + (vga.crtc.horizontal_display_end); + hbstart = vga.crtc.start_horizontal_blanking; + vbstart = vga.crtc.start_vertical_blanking | ((vga.crtc.overflow & 0x08) << 5) | + ((vga.crtc.maximum_scan_line & 0x20) << 4) ; + hrstart = vga.crtc.start_horizontal_retrace; + vrstart = vga.crtc.vertical_retrace_start + ((vga.crtc.overflow & 0x04) << 6) | + ((vga.crtc.overflow & 0x80) << 2); + if (hbstart> 2) & 3; + clock=1000*S3_CLOCK(vga.s3.clk[clock].m,vga.s3.clk[clock].n,vga.s3.clk[clock].r); + /* 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&0xf)+1; + /* Check for dual transfer whatever thing,master clock/2 */ + if (vga.s3.pll.cmd & 0x10) clock/=2; + vga.draw.double_scan=(vga.crtc.maximum_scan_line&0x80)>0; + } else { + vga.draw.address_line_total=vga.other.max_scanline+1; + htotal=vga.other.htotal; + hdispend=vga.other.hdend; + hrstart=vga.other.hsyncp; + vtotal=vga.draw.address_line_total*vga.other.vtotal+vga.other.vadjust; + vdispend=vga.draw.address_line_total*vga.other.vdend; + vrstart=vga.draw.address_line_total*vga.other.vsyncp; + vga.draw.double_scan=false; + switch (machine) { + case MCH_CGA: + case MCH_TANDY: + clock=((vga.tandy.mode_control & 1) ? 14318180 : (14318180/2))/8; + break; + case MCH_HERC: + if (vga.herc.mode_control & 0x2) clock=14318180/16; + else clock=14318180/8; + break; + } } - /* Check for dual transfer whatever thing,master clock/2 */ - if (vga.s3.pll.cmd & 0x10) clock/=2; - LOG(LOG_VGA,LOG_NORMAL)("H total %d, V Total %d",htotal,vtotal); LOG(LOG_VGA,LOG_NORMAL)("H D End %d, V D End %d",hdispend,vdispend); - fps=clock/(vtotal*htotal); - double linemicro=(1000000/fps); + if (!htotal) return; + if (!vtotal) return; + fps=(float)clock/(vtotal*htotal); + float linetime=1000.0f/fps; vga.draw.parts_total=VGA_PARTS; - vga.draw.micro.vtotal=(Bitu)(linemicro); - linemicro/=vtotal; //Really make it the line_micro - vga.draw.micro.vend=(Bitu)(linemicro*vrstart); - vga.draw.micro.parts=(Bitu)((linemicro*vdispend)/vga.draw.parts_total); - vga.draw.micro.htotal=(Bitu)(linemicro); - vga.draw.micro.hend=(Bitu)((linemicro/htotal)*hrstart); - + vga.draw.delay.vtotal=linetime; + linetime/=vtotal; //Really make it the line_delay + vga.draw.delay.vend=linetime*vrstart; + vga.draw.delay.parts=(linetime*vdispend)/vga.draw.parts_total; + vga.draw.delay.htotal=linetime; + vga.draw.delay.hend=(linetime/htotal)*hrstart; double correct_ratio=(100.0/525.0); double aspect_ratio=((double)htotal/((double)vtotal)/correct_ratio); - - vga.draw.resizing=false; - Bitu width,height,pitch; - Bitu scalew=1; - Bitu scaleh=1; - width=hdispend; - height=vdispend; - vga.draw.double_scan=false; - vga.draw.font_height=(vga.crtc.maximum_scan_line&0xf)+1; + vga.draw.resizing=false; + Bitu width=hdispend; + Bitu height=vdispend; + bool doubleheight=false; + bool doublewidth=false; switch (vga.mode) { case M_VGA: - scalew=2; - scaleh*=vga.draw.font_height; - if (vga.crtc.maximum_scan_line&0x80) scaleh*=2; - vga.draw.lines_scaled=scaleh; - height/=scaleh; + doublewidth=true; width<<=2; - pitch=vga.config.scan_len*8; - vga.draw.address_add=vga.config.scan_len*2; - vga.draw.address_line_total=1; - VGA_DrawLine=VGA_VGA_Draw_Line; + VGA_DrawLine=VGA_Draw_VGA_Line; break; case M_LIN8: width<<=3; - scaleh*=vga.draw.font_height; - pitch=vga.config.scan_len*4; - vga.draw.address_add=vga.config.scan_len*2; - vga.draw.lines_scaled=scaleh; - vga.draw.address_line_total=1; - VGA_DrawLine=VGA_VGA_Draw_Line; + /* Use HW mouse cursor drawer if enabled */ + if(vga.s3.hgc.curmode & 0x1) { + VGA_DrawLine=VGA_Draw_VGA_Line_HWMouse; + } else { + VGA_DrawLine=VGA_Draw_VGA_Line; + } break; case M_EGA16: + doublewidth=(vga.seq.clocking_mode & 0x8) > 0; width<<=3; - pitch=vga.config.scan_len*16; - scaleh*=vga.draw.font_height; - if (vga.crtc.maximum_scan_line&0x80) scaleh*=2; - vga.draw.lines_scaled=scaleh; - height/=scaleh; - if (vga.seq.clocking_mode & 0x8) scalew*=2; - vga.draw.address_add=vga.config.scan_len*2; - vga.draw.address_line_total=1; - VGA_DrawLine=VGA_EGA_Draw_Line; + VGA_DrawLine=VGA_Draw_EGA_Line; + break; + case M_CGA16: + doublewidth=true; + doubleheight=true; + vga.draw.blocks=width*2; + width<<=3; + VGA_DrawLine=VGA_Draw_CGA16_Line; break; case M_CGA4: - case M_CGA16: //Let is use 320x200 res and double pixels myself - scaleh=2;scalew=2; - vga.draw.blocks=width; - width<<=2; - height/=2; - pitch=width; - vga.draw.lines_scaled=1; - vga.draw.address_line_total=2; - vga.draw.address_add=80; //CGA doesn't have an offset reg - VGA_DrawLine=(vga.mode == M_CGA4) ? VGA_CGA4_Draw_Line : VGA_CGA16_Draw_Line; + doublewidth=true; + vga.draw.blocks=width*2; + width<<=3; + VGA_DrawLine=VGA_Draw_2BPP_Line; break; case M_CGA2: - scaleh=2;height/=2; - vga.draw.address_line_total=2; + doubleheight=true; vga.draw.blocks=width; - width<<=3; - pitch=width; - vga.draw.address_line_total=2; - vga.draw.address_add=80; //CGA doesn't have an offset reg - vga.draw.lines_scaled=1; - VGA_DrawLine=VGA_CGA2_Draw_Line; + width<<=4; + VGA_DrawLine=VGA_Draw_1BPP_Line; break; - case M_HERC: - vga.draw.address_line_total=4; - width*=9; - vga.draw.blocks=width/8; - vga.draw.address_add=width/8; - vga.draw.lines_scaled=1; - height=348; - pitch=width; + case M_TEXT: + aspect_ratio=1.0; + vga.draw.blocks=width; + doublewidth=(vga.seq.clocking_mode & 0x8) > 0; + width<<=3; /* 8 bit wide text font */ + VGA_DrawLine=VGA_TEXT_Draw_Line; + break; + case M_HERC_GFX: aspect_ratio=1.5; - VGA_DrawLine=VGA_HERC_Draw_Line; + vga.draw.blocks=width*2; + width*=16; + VGA_DrawLine=VGA_Draw_1BPP_Line; + break; + case M_TANDY2: + aspect_ratio=1.2; + doubleheight=true; + 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; + doublewidth=(vga.tandy.mode_control & 0x10)==0; + vga.draw.blocks=width * (doublewidth ? 4:8); + width=vga.draw.blocks*2; + VGA_DrawLine=VGA_Draw_2BPP_Line; break; case M_TANDY16: - scaleh=2;scalew=2; - vga.draw.blocks=width*2; - vga.draw.address_add=160; - vga.draw.address_line_total=4; - vga.draw.lines_scaled=1; - width<<=2;height/=2; - pitch=width; - VGA_DrawLine=VGA_TANDY16_Draw_Line; + aspect_ratio=1.2; + doubleheight=true; + doublewidth=(vga.tandy.mode_control & 0x10)==0; + vga.draw.blocks=width * (doublewidth ? 2:4); + width=vga.draw.blocks*2; + VGA_DrawLine=VGA_Draw_4BPP_Line; break; - case M_TEXT2: - case M_TEXT16: - aspect_ratio=1.0; - if (vga.draw.font_height<4 && (machine640) width=640; - if (height>480) height=480; - pitch=width; + width<<=3; VGA_DrawLine=VGA_TEXT_Draw_Line; break; default: - LOG(LOG_VGA,LOG_ERROR)("Unhandled VGA type %d while checking for resolution"); + LOG(LOG_VGA,LOG_ERROR)("Unhandled VGA mode %d while checking for resolution",vga.mode); }; + VGA_CheckScanLength(); + if (vga.draw.double_scan) { + height/=2; + doubleheight=true; + } + //Only check for exra double heigh in vga modes + if (!doubleheight && (vga.mode> 3) & 1; // LOG_DEBUG("Write Mode %d Read Mode %d val %d",vga.config.write_mode,vga.config.read_mode,val); @@ -134,7 +136,6 @@ void write_p3cf(Bit32u port,Bit8u val) { 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 */ @@ -183,7 +184,7 @@ void write_p3cf(Bit32u port,Bit8u val) { } } -Bit8u read_p3cf(Bit32u port) { +static Bitu read_p3cf(Bitu port,Bitu iolen) { switch (gfx(index)) { case 0: /* Set/Reset Register */ return gfx(set_reset); @@ -212,10 +213,12 @@ Bit8u read_p3cf(Bit32u port) { 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"); + if (machine==MCH_VGA) { + IO_RegisterWriteHandler(0x3ce,write_p3ce,IO_MB); + IO_RegisterWriteHandler(0x3cf,write_p3cf,IO_MB); + IO_RegisterReadHandler(0x3ce,read_p3ce,IO_MB); + IO_RegisterReadHandler(0x3cf,read_p3cf,IO_MB); + } } diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 0842dd1..0d67a8a 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -26,6 +26,9 @@ #include "vga.h" #include "paging.h" #include "pic.h" +#include "inout.h" + +void VGA_MapMMIO(void); static Bitu VGA_NormalReadHandler(PhysPt start) { vga.latch.d=vga.mem.latched[start].d; @@ -210,11 +213,11 @@ public: flags=PFLAG_NOCODE; } Bitu readb(PhysPt addr) { - addr&=0x7fff; + addr&=0xffff; return vga.draw.font[addr]; } void writeb(PhysPt addr,Bitu val){ - addr&=0x7fff; + addr&=0xffff; if (vga.seq.map_mask & 0x4) { vga.draw.font[addr]=(Bit8u)val; } @@ -233,6 +236,7 @@ public: } }; + class VGA_MAP_PageHandler : public PageHandler { public: VGA_MAP_PageHandler() { @@ -244,31 +248,113 @@ public: } }; +class VGA_MMIO_PageHandler : public PageHandler { +public: + Bit16u regmem[16384]; + + VGA_MMIO_PageHandler() { + flags=PFLAG_NOCODE; + //memset(®mem[0], 0, sizeof(regmem)); + } + void writeb(PhysPt addr,Bitu val) { + Bitu port = addr & 0xffff; + if(port >= 0x82E8) IO_WriteB(port, val); + LOG_MSG("MMIO: Write byte to %x with %x", addr, val); + } + void writew(PhysPt addr,Bitu val) { + Bitu port = addr & 0xffff; + if(port >= 0x82E8) IO_WriteW(port, val); + if(port == 0x8118) IO_WriteW(0x9ae8, val); + if(port <= 0x0020) { + IO_WriteW(0xe2e8, val); + } + + LOG_MSG("MMIO: Write word to %x with %x", addr, val); + } + void writed(PhysPt addr,Bitu val) { + Bitu port = addr & 0xffff; + if(port >= 0x82E8) IO_WriteD(port, val); + if(port == 0x8100) { + IO_WriteW(0x86e8, (val >> 16)); + IO_WriteW(0x82e8, (val & 0xffff)); + } + if(port == 0x8148) { + IO_WriteW(0x96e8, (val >> 16)); + IO_WriteW(0xbee8, (val & 0xffff)); + } + if(port <= 0x0020) { + IO_WriteW(0xe2e8, (val & 0xffff)); + IO_WriteW(0xe2e8, (val >> 16)); + } + + LOG_MSG("MMIO: Write dword to %x with %x", addr, val); + } + + Bitu readb(PhysPt addr) { + LOG_MSG("MMIO: Read byte from %x", addr); + + return 0x00; + } + Bitu readw(PhysPt addr) { + Bitu port = addr & 0xffff; + if(port >= 0x82E8) return IO_ReadW(port); + LOG_MSG("MMIO: Read word from %x", addr); + return 0x00; + } + Bitu readd(PhysPt addr) { + LOG_MSG("MMIO: Read dword from %x", addr); + return 0x00; + } + +}; + class VGA_TANDY_PageHandler : public PageHandler { public: VGA_TANDY_PageHandler() { - flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE; + flags=PFLAG_READABLE|PFLAG_WRITEABLE; +// |PFLAG_NOCODE; } HostPt GetHostPt(Bitu phys_page) { - phys_page-=vgapages.map_base; - return &vga.mem.linear[(vga.tandy.mem_bank << 14)+(phys_page * 4096)]; + if (phys_page>=0xb8) { + phys_page-=0xb8; + return &vga.mem.linear[(vga.tandy.mem_bank << 14)+(phys_page * 4096)]; + } else { + phys_page-=0x80; + return &vga.mem.linear[phys_page * 4096]; + } } }; -static struct { +static struct vg { VGA_RAM_PageHandler hram; VGA_MAP_PageHandler hmap; VGA_TEXT_PageHandler htext; VGA_TANDY_PageHandler htandy; VGA_256_PageHandler h256; VGA_16_PageHandler h16; + VGA_MMIO_PageHandler mmio; } vgaph; void VGA_SetupHandlers(void) { PageHandler * range_handler; + switch (machine) { + case MCH_CGA: + range_handler=&vgaph.hmap; + goto range_b800; + case MCH_HERC: + range_handler=&vgaph.hmap; + if (vga.herc.mode_control&0x80) goto range_b800; + else goto range_b000; + case MCH_TANDY: + range_handler=&vgaph.htandy; + MEM_SetPageHandler(0x80,32,range_handler); + goto range_b800; + } switch (vga.mode) { + case M_ERROR: + return; case M_LIN8: range_handler=&vgaph.hmap; break; @@ -282,29 +368,15 @@ void VGA_SetupHandlers(void) { case M_EGA16: range_handler=&vgaph.h16; break; - case M_TEXT2: - case M_TEXT16: + case M_TEXT: /* Check if we're not in odd/even mode */ - if (vga.gfx.miscellaneous & 0x2) { - range_handler=&vgaph.hmap; - } else { - range_handler=&vgaph.htext; - } + if (vga.gfx.miscellaneous & 0x2) range_handler=&vgaph.hmap; + else range_handler=&vgaph.htext; break; - case M_TANDY16: - range_handler=&vgaph.htandy; - break; - case M_CGA16: case M_CGA4: case M_CGA2: range_handler=&vgaph.hmap; break; - case M_HERC: - range_handler=&vgaph.hmap; - if (vga.herc.mode_control&0x80) goto range_b800; - else goto range_b000; - default: - LOG_MSG("Unhandled vga mode %X",vga.mode); } switch ((vga.gfx.miscellaneous >> 2) & 3) { case 0: @@ -331,12 +403,15 @@ range_b800: MEM_SetPageHandler(VGA_PAGE_B0,8,&vgaph.hram); break; } + + if(((vga.s3.ext_mem_ctrl & 0x10) != 0x00) && (vga.mode == M_LIN8)) MEM_SetPageHandler(VGA_PAGE_A0, 16, &vgaph.mmio); + PAGING_ClearTLB(); } -bool lfb_update; +static bool lfb_update; -static void VGA_DoUpdateLFB(void) { +static void VGA_DoUpdateLFB(Bitu val) { lfb_update=false; MEM_SetLFB(vga.s3.la_window << 4 ,sizeof(vga.mem.linear)/4096,&vga.mem.linear[0]); } @@ -344,10 +419,20 @@ static void VGA_DoUpdateLFB(void) { void VGA_StartUpdateLFB(void) { if (!lfb_update) { lfb_update=true; - PIC_AddEvent(VGA_DoUpdateLFB,100); //100 microseconds later + PIC_AddEvent(VGA_DoUpdateLFB,0.100f); //100 microseconds later } } +void VGA_MapMMIO(void) { + MEM_SetPageHandler(VGA_PAGE_A0, 16, &vgaph.mmio); + +} + +void VGA_UnmapMMIO(void) { + //MEM_SetPageHandler(VGA_PAGE_A0, &ram_page_handler); +} + + void VGA_SetupMemory() { memset((void *)&vga.mem,0,512*1024*4); } diff --git a/src/hardware/vga_misc.cpp b/src/hardware/vga_misc.cpp index 650d56a..037a581 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_misc.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -20,26 +20,20 @@ #include "inout.h" #include "pic.h" #include "vga.h" -#include "../ints/int10.h" static Bit8u flip=0; -void write_p3d4(Bit32u port,Bit8u val); -Bit8u read_p3d4(Bit32u port); -void write_p3d5(Bit32u port,Bit8u val); -Bit8u read_p3d5(Bit32u port); +void write_p3d4_vga(Bitu port,Bitu val,Bitu iolen); +Bitu read_p3d4_vga(Bitu port,Bitu iolen); +void write_p3d5_vga(Bitu port,Bitu val,Bitu iolen); +Bitu read_p3d5_vga(Bitu port,Bitu iolen); -static void write_p3d9(Bit32u port,Bit8u val); - -static Bit8u read_p3da(Bit32u port) { +static Bitu read_p3da(Bitu port,Bitu iolen) { vga.internal.attrindex=false; if (vga.config.retrace) { - switch (vga.mode) { - case M_HERC: + switch (machine) { + case MCH_HERC: return 0x81; - case M_TEXT2: - if (machine==MCH_HERC) return 0x81; - if (machine==MCH_AUTO) return 0x89; default: return 9; } @@ -54,186 +48,33 @@ static Bit8u read_p3da(Bit32u port) { */ } -static void write_p3d8(Bit32u port,Bit8u val) { - /* Check if someone changes the blinking/hi intensity bit */ - switch (machine) { - case MCH_AUTO: - VGA_SetBlinking((val & 0x20)); - switch (vga.mode) { - case M_CGA2: - case M_CGA4: - case M_CGA16: - goto m_cga; - } - break; - case MCH_CGA: - VGA_SetBlinking((val & 0x20)); -m_cga: - if (val & 0x2) { - if (val & 0x10) { - if (val & 0x8) { - VGA_SetMode(M_CGA16); //Video burst 16 160x200 color mode - } else { - VGA_SetMode(M_CGA2); - } - } else VGA_SetMode(M_CGA4); - write_p3d9(0x3d9,vga.cga.color_select); //Setup the correct palette - } else { - VGA_SetMode(M_TEXT16); - } - vga.cga.mode_control=val; - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("Write %2X to 3d8 in mode %d",val,vga.mode); - } - /* - 3 Vertical Sync Select. If set Vertical Sync to the monitor is the - logical OR of the vertical sync and the vertical display enable. - */ -} -static void write_p3d9(Bit32u port,Bit8u val) { - Bitu i; - vga.cga.color_select=val; - switch (vga.mode) { - case M_CGA2: - /* changes attribute 1 */ - VGA_ATTR_SetPalette(0,0); - VGA_ATTR_SetPalette(1,val & 0xf); - break; - case M_CGA4: - /* changes attribute 0 */ - { - VGA_ATTR_SetPalette(0,(val & 0xf)); - Bit8u pal_base=(val & 0x10) ? 0x08 : 0; - if (val & 0x020) { - VGA_ATTR_SetPalette(1,0x03+pal_base); - VGA_ATTR_SetPalette(2,0x05+pal_base); - VGA_ATTR_SetPalette(3,0x07+pal_base); - } else { - VGA_ATTR_SetPalette(1,0x02+pal_base); - VGA_ATTR_SetPalette(2,0x04+pal_base); - VGA_ATTR_SetPalette(3,0x06+pal_base); - } - } - break; - case M_CGA16: - for(i=0;i<0x10;i++) VGA_ATTR_SetPalette(i,i); - break; - case M_TEXT16: - /* Assume a normal text palette has been set */ -// VGA_ATTR_SetPalette(0,(val & 0x8) ? ((val & 7)+32) : (val &7)); - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode); - } -} - -static void write_p3da(Bit32u port,Bit8u val) { - if (machine==MCH_TANDY) goto tandy_3da; - switch (vga.mode) { - case M_TANDY16: -tandy_3da: - vga.tandy.reg_index=val; - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode); - break; - - } -} - - -static void write_p3de(Bit32u port,Bit8u val) { - if (machine==MCH_TANDY) goto tandy_3de; - switch (vga.mode) { - case M_TANDY16: -tandy_3de: - switch (vga.tandy.reg_index) { - case 0x2: /* Border color */ - vga.tandy.border_color=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); - } - break; - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode); - break; - } -} - -static void write_p3df(Bit32u port,Bit8u val) { - if (machine==MCH_TANDY) goto tandy_3df; - switch (vga.mode) { - case M_TANDY16: -tandy_3df: - vga.tandy.disp_bank=val & ((val & 0x80) ? 0x6 : 0x7); - vga.tandy.mem_bank=(val >> 3) & ((val & 0x80) ? 0x6 : 0x7); - VGA_SetupHandlers(); - break; - /* - 0-2 Identifies the page of main memory being displayed in units of 16K. - 0: 0K, 1: 16K...7: 112K. In 32K modes (bits 6-7 = 2) only 0,2,4 and - 6 are valid, as the next page will also be used. - 3-5 Identifies the page of main memory that can be read/written at B8000h - in units of 16K. 0: 0K, 1: 16K...7: 112K. In 32K modes (bits 6-7 = 2) - only 0,2,4 and 6 are valid, as the next page will also be used. - 6-7 Display mode. 0: Text, 1: 16K graphics mode (4,5,6,8) - 2: 32K graphics mode (9,Ah) - */ - default: - LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode); - break; - } -} - -static Bit8u read_p3d9(Bit32u port) { - switch (machine) { - case MCH_AUTO: - case MCH_CGA: - case MCH_TANDY: - return vga.cga.color_select; - default: - return 0xff; - }; -} - - -static void write_p3c2(Bit32u port,Bit8u val) { +static void write_p3c2(Bitu port,Bitu val,Bitu iolen) { vga.misc_output=val; - if (val & 0x1) { - IO_RegisterWriteHandler(0x3d4,write_p3d4,"VGA:CRTC Index Select"); - IO_RegisterReadHandler(0x3d4,read_p3d4,"VGA:CRTC Index Select"); - IO_RegisterWriteHandler(0x3d5,write_p3d5,"VGA:CRTC Data Register"); - IO_RegisterReadHandler(0x3d5,read_p3d5,"VGA:CRTC Data Register"); - IO_RegisterReadHandler(0x3da,read_p3da,"VGA Input Status 1"); + IO_RegisterWriteHandler(0x3d4,write_p3d4_vga,IO_MB); + IO_RegisterReadHandler(0x3d4,read_p3d4_vga,IO_MB); + IO_RegisterWriteHandler(0x3d5,write_p3d5_vga,IO_MB); + IO_RegisterReadHandler(0x3d5,read_p3d5_vga,IO_MB); + IO_RegisterReadHandler(0x3da,read_p3da,IO_MB); - IO_FreeWriteHandler(0x3b4); - IO_FreeReadHandler(0x3b4); - IO_FreeWriteHandler(0x3b5); - IO_FreeReadHandler(0x3b5); - IO_FreeReadHandler(0x3ba); + 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,write_p3d4,"VGA:CRTC Index Select"); - IO_RegisterReadHandler(0x3b4,read_p3d4,"VGA:CRTC Index Select"); - IO_RegisterWriteHandler(0x3b5,write_p3d5,"VGA:CRTC Data Register"); - IO_RegisterReadHandler(0x3b5,read_p3d5,"VGA:CRTC Data Register"); - IO_RegisterReadHandler(0x3ba,read_p3da,"VGA Input Status 1"); + IO_RegisterWriteHandler(0x3b4,write_p3d4_vga,IO_MB); + IO_RegisterReadHandler(0x3b4,read_p3d4_vga,IO_MB); + IO_RegisterWriteHandler(0x3b5,write_p3d5_vga,IO_MB); + IO_RegisterReadHandler(0x3b5,read_p3d5_vga,IO_MB); + IO_RegisterReadHandler(0x3ba,read_p3da,IO_MB); - IO_FreeWriteHandler(0x3d4); - IO_FreeReadHandler(0x3d4); - IO_FreeWriteHandler(0x3d5); - IO_FreeReadHandler(0x3d5); - IO_FreeReadHandler(0x3da); + 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. @@ -249,72 +90,21 @@ static void write_p3c2(Bit32u port,Bit8u val) { } -static Bit8u read_p3cc(Bit32u port) { +static Bitu read_p3cc(Bitu port,Bitu iolen) { return vga.misc_output; } -static void write_hercules(Bit32u port,Bit8u val) { - switch (port) { - case 0x3b8: - vga.herc.mode_control=(vga.herc.mode_control & ~0x7d) | (val&0x7d); - if ((vga.herc.enable_bits & 1) && ((vga.herc.mode_control ^ val)&0x2)) { - vga.herc.mode_control^=0x2; - if (vga.mode != M_HERC || vga.mode != M_TEXT2) { - VGA_ATTR_SetPalette(0,0x00); - VGA_ATTR_SetPalette(1,0x07); - - /* Force 0x3b4/5 registers */ - if (vga.misc_output & 1) write_p3c2(0,vga.misc_output & ~1); - } - if (val & 0x2) { - if (vga.mode != M_HERC) VGA_SetMode(M_HERC); - } else { - if (vga.mode != M_TEXT2) VGA_SetMode(M_TEXT2); - } - } - if ((vga.herc.enable_bits & 0x2) && ((vga.herc.mode_control ^ val)&0x80)) { - vga.herc.mode_control^=0x80; - VGA_SetupHandlers(); - } - break; - case 0x3bf: - vga.herc.enable_bits=val; - break; - default: - LOG_MSG("write %x to Herc port %x",val,port); - } -} - -static Bit8u read_hercules(Bit32u port) { - switch (port) { - case 0x3b8: - default: - LOG_MSG("read from Herc port %x",port); - } - return 0; -} - - - void VGA_SetupMisc(void) { - vga.herc.enable_bits=0; - IO_RegisterWriteHandler(0x3d8,write_p3d8,"VGA Feature Control Register"); - IO_RegisterWriteHandler(0x3d9,write_p3d9,"CGA Color Select Register"); - IO_RegisterReadHandler(0x3d9,read_p3d9,"CGA Color Select Register"); - - IO_RegisterWriteHandler(0x3c2,write_p3c2,"VGA Misc Output"); - IO_RegisterReadHandler(0x3cc,read_p3cc,"VGA Misc Output"); - - if (machine==MCH_HERC || machine==MCH_AUTO) { - vga.herc.mode_control=0x8; - IO_RegisterWriteHandler(0x3b8,write_hercules,"Hercules"); - IO_RegisterWriteHandler(0x3bf,write_hercules,"Hercules"); + if (machine==MCH_VGA) { + IO_RegisterWriteHandler(0x3c2,write_p3c2,IO_MB); + IO_RegisterReadHandler(0x3cc,read_p3cc,IO_MB); + } else if (machine==MCH_CGA || machine==MCH_TANDY) { + IO_RegisterReadHandler(0x3da,read_p3da,IO_MB); + } else if (machine==MCH_HERC) { + IO_RegisterReadHandler(0x3ba,read_p3da,IO_MB); } - IO_RegisterWriteHandler(0x3de,write_p3de,"PCJR Reg Write"); - IO_RegisterWriteHandler(0x3df,write_p3df,"PCJR Bank Select"); - IO_RegisterWriteHandler(0x3da,write_p3da,"PCJR Reg Select"); } diff --git a/src/hardware/vga_other.cpp b/src/hardware/vga_other.cpp new file mode 100644 index 0000000..807d7ab --- /dev/null +++ b/src/hardware/vga_other.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along 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 "vga.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 sync width + vga.other.hsyncw=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.draw.cursor.sline = val&0x1f; + vga.draw.cursor.enabled = ((val & 0x60) != 0x20); + break; + case 0x0B: /* Cursor End Register */ + 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; + 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 sync width + return vga.other.hsyncw; + 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 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; + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("MC6845:Read from illegal index %x",vga.other.index); + } + return (Bitu)-1; +} + +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)) { + VGA_SetCGA4Table(0,1,2,3); + return; + } + Bit8u base=(val & 0x10) ? 0x08 : 0; + /* Check for BW Mode */ + if (vga.tandy.mode_control & 0x4) { + if (val & 0x20) VGA_SetCGA4Table(val & 0xf,3+base,4+base,7+base); + else VGA_SetCGA4Table(val & 0xf,2+base,4+base,6+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_TEXT: + case M_TANDY16: + break; + } +} + +static void write_mode_control(Bit8u val) { + /* Check if someone changes the blinking/hi intensity bit */ + vga.tandy.mode_control=val; + VGA_SetBlinking((val & 0x20)); + if (val & 0x2) { + if (val & 0x10) { + } else VGA_SetMode(M_CGA4); + write_color_select(vga.tandy.color_select); //Setup the correct palette + } else { + VGA_SetMode(M_TEXT); + } +} + +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 write_tandy_reg(Bit8u val) { + switch (vga.tandy.reg_index) { + case 0x2: /* Border color */ + vga.tandy.border_color=val; + break; + case 0x3: /* More control */ + vga.tandy.gfx_control=val; + TANDY_FindMode(); + 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 & 0x8 && 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; + VGA_SetBlinking(val & 0x20); + TANDY_FindMode(); + break; + case 0x3d9: + write_color_select(val); + break; + case 0x3da: + vga.tandy.reg_index=val; + break; + case 0x3de: + write_tandy_reg(val); + break; + case 0x3df: + vga.tandy.disp_bank=val & ((val & 0x80) ? 0x6 : 0x7); + vga.tandy.mem_bank=(val >> 3) & ((val & 0x80) ? 0x6 : 0x7); + VGA_SetupHandlers(); + break; + } +} + +static void write_hercules(Bitu port,Bitu val,Bitu iolen) { + switch (port) { + case 0x3b8: + if (vga.herc.enable_bits & 1) { + vga.herc.mode_control&=~0x2; + vga.herc.mode_control|=(val&0x2); + if (val & 0x2) { + VGA_SetMode(M_HERC_GFX); + } else { + VGA_SetMode(M_HERC_TEXT); + } + } + if ((vga.herc.enable_bits & 0x2) && ((vga.herc.mode_control ^ val)&0x80)) { + vga.herc.mode_control^=0x80; + VGA_SetupHandlers(); + } + 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; +} + + +void VGA_SetupOther(void) { + Bitu i; + if (machine==MCH_CGA || machine==MCH_TANDY) { + 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); + } + if (machine==MCH_HERC) { + vga.herc.enable_bits=0; + vga.herc.mode_control=0x8; + IO_RegisterWriteHandler(0x3b8,write_hercules,IO_MB); + IO_RegisterWriteHandler(0x3bf,write_hercules,IO_MB); + } + if (machine==MCH_TANDY) { + 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_CGA || machine==MCH_HERC || machine==MCH_TANDY) { + Bitu base=machine==MCH_HERC ? 0x3b4 : 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_seq.cpp b/src/hardware/vga_seq.cpp index 1ab8cc1..12db7b6 100644 --- a/src/hardware/vga_seq.cpp +++ b/src/hardware/vga_seq.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -22,15 +22,15 @@ #define seq(blah) vga.seq.blah -Bit8u read_p3c4(Bit32u port) { +Bitu read_p3c4(Bitu port,Bitu iolen) { return seq(index); } -void write_p3c4(Bit32u port,Bit8u val) { +void write_p3c4(Bitu port,Bitu val,Bitu iolen) { seq(index)=val; }; -void write_p3c5(Bit32u port,Bit8u val) { +void write_p3c5(Bitu port,Bitu val,Bitu iolen) { if (seq(index)>0x8 && vga.s3.pll.lock!=0x6) return; // LOG_MSG("SEQ WRITE reg %X val %X",seq(index),val); switch(seq(index)) { @@ -69,10 +69,10 @@ void write_p3c5(Bit32u port,Bit8u val) { case 3: /* Character Map Select */ { seq(character_map_select)=val; - Bit8u font1=(val & 0x3) | ((val & 0x10) >> 2); - vga.draw.font1_start=((font1&3) * 16*1024) + ((font1 > 4) ? (8*1024) : 0); - Bit8u font2=((val & 0xc) >> 2) | ((val & 0x20) >> 3); - vga.draw.font2_start=((font2&3) * 16*1024) + ((font2 > 4) ? (8*1024) : 0); + Bit8u font1=((val & 0x3) << 1) | ((val & 0x10) >> 4); + vga.draw.font_tables[0]=&vga.draw.font[font1*8*1024]; + Bit8u font2=((val & 0xc) >> 1) | ((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 @@ -127,7 +127,7 @@ void write_p3c5(Bit32u port,Bit8u val) { }; -Bit8u read_p3c5(Bit32u port) { +Bitu read_p3c5(Bitu port,Bitu iolen) { // LOG_MSG("VGA:SEQ:Read from index %2X",seq(index)); if (seq(index)>0x8 && vga.s3.pll.lock!=0x6) return seq(index); switch(seq(index)) { @@ -167,10 +167,11 @@ Bit8u read_p3c5(Bit32u port) { 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"); - + if (machine==MCH_VGA) { + IO_RegisterWriteHandler(0x3c4,write_p3c4,IO_MB); + IO_RegisterWriteHandler(0x3c5,write_p3c5,IO_MB); + IO_RegisterReadHandler(0x3c4,read_p3c4,IO_MB); + IO_RegisterReadHandler(0x3c5,read_p3c5,IO_MB); + } } diff --git a/src/hardware/vga_xga.cpp b/src/hardware/vga_xga.cpp new file mode 100644 index 0000000..0abb4ba --- /dev/null +++ b/src/hardware/vga_xga.cpp @@ -0,0 +1,530 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along 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 "vga.h" +#include + +struct XGAStatus { + struct scissorreg { + Bit16u x1, y1, x2, y2; + } scissors; + + Bit32u readmask; + Bit32u writemask; + + Bit32u forecolor; + Bit32u backcolor; + + Bit16u foremix; + + Bit16u curx, cury; + Bit16u destx, desty; + + Bit16u MIPcount; + Bit16u MAPcount; + + Bit16u pix_cntl; + Bit16u read_sel; + + struct XGA_WaitCmd { + bool wait; + Bit16u cmd; + Bit16u curx, cury; + Bit16u x1, y1, x2, y2; + } waitcmd; + +} xga; + +Bit8u tmpvram[2048 * 1024]; + +void XGA_Write_Multifunc(Bitu val, Bitu len) { + Bitu regselect = val >> 12; + Bitu dataval = val & 0xfff; + switch(regselect) { + case 0: + xga.MIPcount = dataval; + break; + case 1: + xga.scissors.y1 = dataval; + break; + case 2: + xga.scissors.x1 = dataval; + break; + case 3: + xga.scissors.y2 = dataval; + break; + case 4: + xga.scissors.x2 = dataval; + break; + case 0xa: + xga.pix_cntl = dataval; + break; + case 0xf: + xga.read_sel = dataval; + break; + default: + LOG_MSG("XGA: Unhandled multifunction command %x", regselect); + break; + } +} + +void XGA_DrawPoint8(Bitu x, Bitu y, Bit8u c) { + Bit32u memaddr = (y * 640) + x; + vga.mem.linear[memaddr] = c; + +} + +Bit8u XGA_GetPoint8(Bitu x, Bitu y) { + Bit32u memaddr = (y * 640) + x; + return vga.mem.linear[memaddr]; + + +} + +void XGA_DrawPoint16(Bitu x, Bitu y, Bit16u c) { + Bit16u *memptr; + Bit32u memaddr = (y * 640) + x; + memptr = (Bit16u *)&vga.mem.linear[memaddr]; + *memptr = c; +} + +void XGA_DrawRectangle(Bitu x1, Bitu y1, Bitu x2, Bitu y2) { + Bit32u xat, yat; + Bit32u xmass, xmod, xdist; + Bit32u *memptr; + Bit8u *smallptr; + Bit32u c; + Bit8u smallc; + + xdist = (x2 -x1); + xmass = (xdist) & 0xfffffffb; + xmod = (xdist) & 0x3; + + smallc = (xga.forecolor & 0xff); + c = (smallc) | ((smallc) << 8) | ((smallc) << 16) | ((smallc) << 24); + + for(yat=y1;yat<=y2;yat++) { + Bit32u memaddr = (yat * (Bit32u)640) + x1; + smallptr = &vga.mem.linear[memaddr]; + for(xat=0;xat xga.waitcmd.x2) { + xga.waitcmd.curx = xga.waitcmd.x1; + xga.waitcmd.cury++; + newline = true; + if(xga.waitcmd.cury > xga.waitcmd.y2) xga.waitcmd.wait = false; + } + return newline; +} + +void XGA_DrawWait(Bitu val, Bitu len) { + if(!xga.waitcmd.wait) return; + Bitu mixmode = (xga.pix_cntl >> 6) & 0x3; + + switch(xga.waitcmd.cmd) { + case 2: /* Rectangle */ + if(mixmode == 0) { /* FOREMIX always used */ + switch(len) { + case 1: + XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, val); + break; + case 2: + XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, (val & 0xff)); + XGA_CheckX(); + XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, (val >> 8)); + break; + case 4: + XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, (val & 0xff)); + XGA_CheckX(); + XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, ((val >> 8) & 0xff)); + XGA_CheckX(); + XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, ((val >> 16) & 0xff)); + XGA_CheckX(); + XGA_DrawPoint8(xga.waitcmd.curx++, xga.waitcmd.cury, ((val >> 24) & 0xff)); + break; + } + XGA_CheckX(); + } + if(mixmode == 2) { /* Data from PIX_TRANS selects the mix */ + Bitu bitcount; + int i; + switch(len) { + case 1: + bitcount = 8; + break; + case 2: + bitcount = 16; + val = ((val & 0xff) << 8) | ((val >> 8) & 0xff); + break; + case 4: + bitcount = 32; + break; + } + + + Bits bitneed = ((Bits)xga.waitcmd.x2 - (Bits)xga.waitcmd.x1) + 1; + xga.waitcmd.curx = xga.waitcmd.x1; + i = 15; + for(;bitneed>=0;--bitneed) { + Bitu bitval = (val >> i) & 0x1; + //XGA_DrawPoint8(xga.waitcmd.curx, xga.waitcmd.cury, i); + if(bitval != 0) XGA_DrawPoint8(xga.waitcmd.curx, xga.waitcmd.cury, xga.forecolor); + --i; + xga.waitcmd.curx++; + } + xga.waitcmd.cury++; + + + if(xga.waitcmd.cury > xga.waitcmd.y2) xga.waitcmd.wait = false; + } + break; + default: + LOG_MSG("XGA: Unhandled draw command %x", xga.waitcmd.cmd); + break; + } + +} + +void XGA_BlitRect(Bitu val) { + Bit32u xat, yat; + Bit32u xmass, xmod, xdist, memrec; + Bit8u *srcptr; + Bit8u *destptr; + Bit8u *destline; + Bit8u *srcline; + + Bit32u c; + Bit8u smallc; + Bit8u tmpclr; + bool incx = false; + bool incy = false; + + if((val >> 5) != 0) incx = true; + if((val >> 7) != 0) incy = true; + + xdist = xga.MAPcount; + + smallc = (xga.forecolor & 0xff); + memrec = 0; + Bit32u srcaddr = (xga.cury * (Bit32u)640) + xga.curx; + Bit32u destaddr = (xga.desty * (Bit32u)640) + xga.destx; + + srcptr = &vga.mem.linear[srcaddr]; + destptr = &vga.mem.linear[destaddr]; + + /* Copy source to video ram */ + for(yat=0;yat<=xga.MIPcount ;yat++) { + srcline = srcptr; + destline = destptr; + for(xat=0;xat7) addx=0; + } + addy++; + if(addy>7) addy=0; + } + +} + +void XGA_DrawCmd(Bitu val, Bitu len) { + Bit16u cmd; + cmd = val >> 13; + LOG_MSG("XGA: Draw command %x", cmd); + switch(cmd) { + case 2: /* Rectangle fill */ + if((val & 0x100) == 0) { + xga.waitcmd.wait = false; + XGA_DrawRectangle(xga.curx, xga.cury, xga.curx + xga.MAPcount, xga.cury + xga.MIPcount); + } else { + 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 = xga.curx + xga.MAPcount; + xga.waitcmd.y2 = xga.cury + xga.MIPcount; + xga.waitcmd.cmd = 2; + LOG_MSG("XGA: Draw wait rect (%d, %d)-(%d, %d)", xga.waitcmd.x1, xga.waitcmd.y1, xga.waitcmd.x2, xga.waitcmd.y2); + } + break; + case 6: /* BitBLT */ + XGA_BlitRect(val); + break; + case 7: /* Pattern fill */ + XGA_DrawPattern(); + LOG_MSG("XGA: Pattern fill (%d, %d)-(%d, %d) to (%d, %d)-(%d, %d)", xga.curx, xga.cury, xga.curx + 8, xga.cury + 8, xga.destx, xga.desty, xga.destx + xga.MAPcount, xga.desty + xga.MIPcount); + break; + default: + LOG_MSG("XGA: Unhandled draw command %x", cmd); + break; + + } +} + +void XGA_Write(Bitu port, Bitu val, Bitu len) { + switch(port) { + case 0x96e8: + xga.MAPcount = val; + break; + case 0x9ae8: + XGA_DrawCmd(val, len); + break; + case 0xa2e8: + xga.backcolor = val; + break; + case 0xa6e8: + xga.forecolor = val; + break; + case 0xaae8: + xga.writemask = val; + break; + case 0xaee8: + xga.readmask = val; + break; + case 0x82e8: + xga.cury = val; + break; + case 0x86e8: + xga.curx = val; + break; + case 0x8ae8: + xga.desty = val; + break; + case 0x8ee8: + xga.destx = val; + break; + case 0xbae8: + xga.foremix = val; + break; + case 0xbee8: + XGA_Write_Multifunc(val, len); + break; + case 0xe2e8: + XGA_DrawWait(val, len); + break; + default: + LOG_MSG("XGA: Wrote to port %x with %x, len %x", port, val, len); + break; + } + +} + +Bitu XGA_Read(Bitu port, Bitu len) { + LOG_MSG("XGA: Read from port %x, len %x", port, len); + switch(port) { + case 0x9ae8: + return 0x0; + case 0x9ae9: + if(xga.waitcmd.wait) { + return 0x4; + } else { + return 0x0; + } + case 0xa2e8: + return xga.backcolor; + default: + LOG_MSG("XGA: Read from port %x, len %x", port, len); + return 0x0; + } +} + +void XGA_UpdateHWC(void) { + Bitu mouseaddr = (Bit32u)vga.s3.hgc.startaddr * (Bit32u)1024; + Bits x, y, t, m, xat, r, z; + x = vga.s3.hgc.originx; + y = vga.s3.hgc.originy; + Bit16u bitsA, bitsB; + Bit16u ab, bb; + + /* Read mouse cursor */ + for(t=0;t<64;t++) { + xat = 0; + for(m=0;m<4;m++) { + bitsA = *(Bit16u *)&vga.mem.linear[mouseaddr]; + mouseaddr+=2; + bitsB = *(Bit16u *)&vga.mem.linear[mouseaddr]; + mouseaddr+=2; + z = 7; + for(r=15;r>=0;--r) { + vga.s3.hgc.mc[t][xat] = (((bitsA >> z) & 0x1) << 1) | ((bitsB >> z) & 0x1); + xat++; + --z; + if(z<0) z=15; + } + } + } + +} + +void VGA_SetupXGA(void) { + if (machine!=MCH_VGA) return; + + memset(&xga, 0, sizeof(XGAStatus)); + + 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(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 new file mode 100644 index 0000000..e9bd41f --- /dev/null +++ b/src/hardware/ymf262.c @@ -0,0 +1,2792 @@ +/* +** +** 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*4]; /* channels output masks (0xffffffff = enable); 4 masks per one channel */ + UINT32 pan_ctrl_value[18]; /* output control values 1 per one channel (1 value contains 4 masks) */ + + 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 DV (0.1875/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 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 ML 2 +static const UINT8 mul_tab[16]= { +/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ + 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML, + 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML +}; +#undef ML + +/* 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 = (1.0 / 64.0 ) * (1<freqbase; + + /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */ + chip->lfo_pm_inc = (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 = (1.0 / 1.0) * (1<freqbase; + + chip->eg_timer_add = (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]; + + 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-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) * 4; + + /* OPL3 mode */ + chip->pan[ base ] = (v & 0x10) ? ~0 : 0; /* ch.A */ + chip->pan[ base +1 ] = (v & 0x20) ? ~0 : 0; /* ch.B */ + chip->pan[ base +2 ] = (v & 0x40) ? ~0 : 0; /* ch.C */ + chip->pan[ base +3 ] = (v & 0x80) ? ~0 : 0; /* ch.D */ + } + else + { + int base = ((r&0xf) + ch_offset) * 4; + + /* OPL2 mode - always enabled */ + chip->pan[ base ] = ~0; /* ch.A */ + chip->pan[ base +1 ] = ~0; /* ch.B */ + chip->pan[ base +2 ] = ~0; /* ch.C */ + chip->pan[ base +3 ] = ~0; /* ch.D */ + } + + chip->pan_ctrl_value[ (r&0xf) + ch_offset ] = v; /* store control value for OPL3/OPL2 mode switching on the fly */ + + 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]) { + if (chip->TC[0]) chip->TC[0]--; + else { + chip->TC[0]=chip->T[0]*20; + OPL3_STATUS_SET(chip,0x40); + } + } + if (chip->st[1]) { + if (chip->TC[1]) chip->TC[1]--; + else { + chip->TC[1]=chip->T[1]*20; + OPL3_STATUS_SET(chip,0x40); + } + } + 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]; + OPL3SAMPLE *ch_c = buffers[2]; + OPL3SAMPLE *ch_d = buffers[3]; +#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,c,d; + + + advance_lfo(chip); + + /* clear channel outputs */ + memset(chanout, 0, sizeof(signed int) * 18); + +//profiler_mark(PROFILER_USER1); + +#if 1 + /* 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]); +#endif +//profiler_mark(PROFILER_END); + + + +//profiler_mark(PROFILER_USER2); + /* accumulator register set #1 */ + a = chanout[0] & chip->pan[0]; + b = chanout[0] & chip->pan[1]; + c = chanout[0] & chip->pan[2]; + d = chanout[0] & chip->pan[3]; +#if 1 + a += chanout[1] & chip->pan[4]; + b += chanout[1] & chip->pan[5]; + c += chanout[1] & chip->pan[6]; + d += chanout[1] & chip->pan[7]; + a += chanout[2] & chip->pan[8]; + b += chanout[2] & chip->pan[9]; + c += chanout[2] & chip->pan[10]; + d += chanout[2] & chip->pan[11]; + + a += chanout[3] & chip->pan[12]; + b += chanout[3] & chip->pan[13]; + c += chanout[3] & chip->pan[14]; + d += chanout[3] & chip->pan[15]; + a += chanout[4] & chip->pan[16]; + b += chanout[4] & chip->pan[17]; + c += chanout[4] & chip->pan[18]; + d += chanout[4] & chip->pan[19]; + a += chanout[5] & chip->pan[20]; + b += chanout[5] & chip->pan[21]; + c += chanout[5] & chip->pan[22]; + d += chanout[5] & chip->pan[23]; + + a += chanout[6] & chip->pan[24]; + b += chanout[6] & chip->pan[25]; + c += chanout[6] & chip->pan[26]; + d += chanout[6] & chip->pan[27]; + a += chanout[7] & chip->pan[28]; + b += chanout[7] & chip->pan[29]; + c += chanout[7] & chip->pan[30]; + d += chanout[7] & chip->pan[31]; + a += chanout[8] & chip->pan[32]; + b += chanout[8] & chip->pan[33]; + c += chanout[8] & chip->pan[34]; + d += chanout[8] & chip->pan[35]; + + /* accumulator register set #2 */ + a += chanout[9] & chip->pan[36]; + b += chanout[9] & chip->pan[37]; + c += chanout[9] & chip->pan[38]; + d += chanout[9] & chip->pan[39]; + a += chanout[10] & chip->pan[40]; + b += chanout[10] & chip->pan[41]; + c += chanout[10] & chip->pan[42]; + d += chanout[10] & chip->pan[43]; + a += chanout[11] & chip->pan[44]; + b += chanout[11] & chip->pan[45]; + c += chanout[11] & chip->pan[46]; + d += chanout[11] & chip->pan[47]; + + a += chanout[12] & chip->pan[48]; + b += chanout[12] & chip->pan[49]; + c += chanout[12] & chip->pan[50]; + d += chanout[12] & chip->pan[51]; + a += chanout[13] & chip->pan[52]; + b += chanout[13] & chip->pan[53]; + c += chanout[13] & chip->pan[54]; + d += chanout[13] & chip->pan[55]; + a += chanout[14] & chip->pan[56]; + b += chanout[14] & chip->pan[57]; + c += chanout[14] & chip->pan[58]; + d += chanout[14] & chip->pan[59]; + + a += chanout[15] & chip->pan[60]; + b += chanout[15] & chip->pan[61]; + c += chanout[15] & chip->pan[62]; + d += chanout[15] & chip->pan[63]; + a += chanout[16] & chip->pan[64]; + b += chanout[16] & chip->pan[65]; + c += chanout[16] & chip->pan[66]; + d += chanout[16] & chip->pan[67]; + a += chanout[17] & chip->pan[68]; + b += chanout[17] & chip->pan[69]; + c += chanout[17] & chip->pan[70]; + d += chanout[17] & chip->pan[71]; +#endif + a >>= FINAL_SH; + b >>= FINAL_SH; + c >>= FINAL_SH; + d >>= FINAL_SH; + + /* limit check */ + a = limit( a+c , MAXOUT, MINOUT ); + b = limit( b+d , MAXOUT, MINOUT ); +// c = limit( c , MAXOUT, MINOUT ); +// d = limit( d , 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; + ch_c[i] = c; + ch_d[i] = d; +#endif +//profiler_mark(PROFILER_END); + + advance(chip); + } + +} +#endif /* BUILD_YMF262 */ diff --git a/src/hardware/ymf262.h b/src/hardware/ymf262.h new file mode 100644 index 0000000..1ab2fa1 --- /dev/null +++ b/src/hardware/ymf262.h @@ -0,0 +1,53 @@ +#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 e1ffaba..7330a85 100644 --- a/src/ints/Makefile.am +++ b/src/ints/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libints.a -libints_a_SOURCES = mouse.cpp xms.cpp xms.h ems.cpp dpmi.cpp \ +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 \ bios.cpp bios_disk.cpp bios_keyboard.cpp diff --git a/src/ints/Makefile.in b/src/ints/Makefile.in index a532973..36f8c63 100644 --- a/src/ints/Makefile.in +++ b/src/ints/Makefile.in @@ -132,7 +132,7 @@ target_vendor = @target_vendor@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libints.a -libints_a_SOURCES = mouse.cpp xms.cpp xms.h ems.cpp dpmi.cpp \ +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 \ bios.cpp bios_disk.cpp bios_keyboard.cpp @@ -147,20 +147,18 @@ LIBRARIES = $(noinst_LIBRARIES) libints_a_AR = $(AR) cru libints_a_LIBADD = am_libints_a_OBJECTS = mouse.$(OBJEXT) xms.$(OBJEXT) ems.$(OBJEXT) \ - dpmi.$(OBJEXT) int10.$(OBJEXT) int10_char.$(OBJEXT) \ - int10_memory.$(OBJEXT) int10_misc.$(OBJEXT) \ - int10_modes.$(OBJEXT) int10_vesa.$(OBJEXT) int10_pal.$(OBJEXT) \ - int10_put_pixel.$(OBJEXT) bios.$(OBJEXT) bios_disk.$(OBJEXT) \ - bios_keyboard.$(OBJEXT) + int10.$(OBJEXT) int10_char.$(OBJEXT) int10_memory.$(OBJEXT) \ + int10_misc.$(OBJEXT) int10_modes.$(OBJEXT) int10_vesa.$(OBJEXT) \ + int10_pal.$(OBJEXT) int10_put_pixel.$(OBJEXT) bios.$(OBJEXT) \ + bios_disk.$(OBJEXT) bios_keyboard.$(OBJEXT) libints_a_OBJECTS = $(am_libints_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) 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)/dpmi.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/ems.Po ./$(DEPDIR)/int10.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/int10_char.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 \ @@ -208,7 +206,6 @@ distclean-compile: @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)/dpmi.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@ diff --git a/src/ints/bios.cpp b/src/ints/bios.cpp index 76c68ee..6d6693c 100644 --- a/src/ints/bios.cpp +++ b/src/ints/bios.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.28 2004/01/26 14:08:16 qbix79 Exp $ */ +/* $Id: bios.cpp,v 1.35 2004/08/04 09:12:56 qbix79 Exp $ */ #include #include "dosbox.h" @@ -29,9 +29,10 @@ #include "pic.h" #include "joystick.h" #include "dos_inc.h" +#include "mouse.h" static Bitu call_int1a,call_int11,call_int8,call_int17,call_int12,call_int15,call_int1c; -static Bitu call_int1,call_int70; +static Bitu call_int1,call_int70,call_int14; static Bit16u size_extended; static Bitu INT70_Handler(void) { @@ -47,6 +48,7 @@ static Bitu INT70_Handler(void) { 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); } @@ -94,7 +96,9 @@ static Bitu INT1A_Handler(void) { LOG(LOG_BIOS,LOG_ERROR)("INT1A:80:Setup tandy sound multiplexer to %d",reg_al); break; case 0x81: /* Tandy sound system checks */ - LOG(LOG_BIOS,LOG_ERROR)("INT1A:81:Tandy DAC Check failing"); + if (machine!=MCH_TANDY) break; + reg_ax=0xc4; + CALLBACK_SCF(false); break; /* INT 1A - Tandy 2500, Tandy 1000L series - DIGITAL SOUND - INSTALLATION CHECK @@ -135,7 +139,6 @@ static Bitu INT8_Handler(void) { Bit16u oldax = reg_ax; // run int 1c CALLBACK_RunRealInt(0x1c); - IO_Write(0x20,0x20); // restore old values SegSet16(ds,oldds); reg_dx = olddx; @@ -167,15 +170,29 @@ static Bitu INT17_Handler(void) { break; default: E_Exit("Unhandled INT 17 call %2X",reg_ah); - }; return CBRET_NONE; } +static Bitu INT14_Handler(void) { + switch (reg_ah) { + case 0x00: /* Init port */ + { + Bitu port=real_readw(0x40,reg_dx*2); + reg_ah=IO_ReadB(port+5); + reg_al=IO_ReadB(port+6); + LOG_MSG("AX %X DX %X",reg_ax,reg_dx); + } + break; + default: + LOG_MSG("Unhandled INT 14 call %2X",reg_ah); + + } + 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"); @@ -251,6 +268,21 @@ static Bitu INT15_Handler(void) { { //TODO Perhaps really wait :) Bit32u micro=(reg_cx<<16)|reg_dx; + 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 */ @@ -287,7 +319,7 @@ static Bitu INT15_Handler(void) { reg_sp+=6; //Clear stack of interrupt frame CPU_SetFlags(0,FMASK_ALL); reg_ax=0; - CPU_JMP(false,0x30,reg_cx); + CPU_JMP(false,0x30,reg_cx,0); } break; case 0x90: /* OS HOOK - DEVICE BUSY */ @@ -298,17 +330,59 @@ static Bitu INT15_Handler(void) { CALLBACK_SCF(false); reg_ah=0; break; - case 0xc3: /* set carry flag so BorlandRTM doesn't assume a VECTRA/PS2 */ - reg_ah=0x86; - CALLBACK_SCF(true); - break; + case 0xc3: /* set carry flag so BorlandRTM doesn't assume a VECTRA/PS2 */ + reg_ah=0x86; + CALLBACK_SCF(true); + break; case 0xc2: /* BIOS PS2 Pointing Device Support */ - case 0xc4: /* BIOS POS Programma option Select */ - /* - Damn programs should use the mouse drivers - So let's fail these calls - */ - LOG(LOG_BIOS,LOG_NORMAL)("INT15:Function %X called,bios mouse not supported",reg_ah); + 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 + Mouse_SetPS2State(true); + reg_ah=0; + CALLBACK_SCF(false); + } else CALLBACK_SCF(true); + break; + case 0x01: // reset + reg_bx=0x00aa; // mouse + CALLBACK_SCF(false); + break; + case 0x02: // set sampling rate + CALLBACK_SCF(false); + reg_ah=0; + break; + 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 0x05: // initialize + 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); + break; + case 0x07: // set callback + Mouse_ChangePS2Callback(SegValue(es),reg_bx); + CALLBACK_SCF(false); + break; + default: + CALLBACK_SCF(true); + break; + } + 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: @@ -345,10 +419,19 @@ void BIOS_Init(Section* sec) { //a new system call_int8=CALLBACK_Allocate(); CALLBACK_Setup(call_int8,&INT8_Handler,CB_IRET); + phys_writeb(CB_BASE+(call_int8<<4)+0,(Bit8u)0xFE); //GRP 4 + phys_writeb(CB_BASE+(call_int8<<4)+1,(Bit8u)0x38); //Extra Callback instruction + phys_writew(CB_BASE+(call_int8<<4)+2,call_int8); //The immediate word + phys_writeb(CB_BASE+(call_int8<<4)+4,(Bit8u)0x50); // push ax + phys_writeb(CB_BASE+(call_int8<<4)+5,(Bit8u)0xb0); // mov al, 0x20 + phys_writeb(CB_BASE+(call_int8<<4)+6,(Bit8u)0x20); + phys_writeb(CB_BASE+(call_int8<<4)+7,(Bit8u)0xe6); // out 0x20, al + phys_writeb(CB_BASE+(call_int8<<4)+8,(Bit8u)0x20); + phys_writeb(CB_BASE+(call_int8<<4)+9,(Bit8u)0x58); // pop ax + phys_writeb(CB_BASE+(call_int8<<4)+10,(Bit8u)0xcf); // iret + mem_writed(BIOS_TIMER,0); //Calculate the correct time RealSetVec(0x8,CALLBACK_RealPointer(call_int8)); - /* INT10 Video Bios */ - /* INT 11 Get equipment list */ call_int11=CALLBACK_Allocate(); CALLBACK_Setup(call_int11,&INT11_Handler,CB_IRET); @@ -360,6 +443,9 @@ void BIOS_Init(Section* sec) { mem_writew(BIOS_MEMORY_SIZE,640); /* INT 13 Bios Disk Support */ BIOS_SetupDisks(); + call_int14=CALLBACK_Allocate(); + CALLBACK_Setup(call_int14,&INT14_Handler,CB_IRET); + RealSetVec(0x14,CALLBACK_RealPointer(call_int14)); /* INT 15 Misc Calls */ call_int15=CALLBACK_Allocate(); CALLBACK_Setup(call_int15,&INT15_Handler,CB_IRET); @@ -393,22 +479,31 @@ void BIOS_Init(Section* sec) { if (IO_Read(0x378)!=0xff) real_writew(0x40,0x08,0x378); /* Test for serial port */ Bitu index=0; - if (IO_Read(0x3f8)!=0xff) real_writew(0x40,(index++)*2,0x3f8); - if (IO_Read(0x2f8)!=0xff) real_writew(0x40,(index++)*2,0x2f8); + if (IO_Read(0x3fa)!=0xff) real_writew(0x40,(index++)*2,0x3f8); + if (IO_Read(0x2fa)!=0xff) real_writew(0x40,(index++)*2,0x2f8); /* Setup equipment list */ + Bitu config=0x4400; //1 Floppy, 2 serial and 1 parrallel #if (C_FPU) - mem_writew(BIOS_CONFIGURATION,0xc823); //1 Floppy,FPU,2 serial, 1 parallel -#else - mem_writew(BIOS_CONFIGURATION,0xc821); //1 Floppy,FPU,2 serial, 1 parallel + config|=0x2; //FPU #endif + switch (machine) { + case MCH_HERC: + config|=0x30; //Startup monochrome + break; + case MCH_CGA: case MCH_TANDY: + config|=0x20; //Startup 80x25 color + break; + default: + config|=0; //EGA VGA + break; + } + config |= 0x04; // PS2 mouse + mem_writew(BIOS_CONFIGURATION,config); /* Setup extended memory size */ IO_Write(0x70,0x30); size_extended=IO_Read(0x71); IO_Write(0x70,0x31); size_extended|=(IO_Read(0x71) << 8); - } - - diff --git a/src/ints/bios_disk.cpp b/src/ints/bios_disk.cpp index 3e7a38f..892701d 100644 --- a/src/ints/bios_disk.cpp +++ b/src/ints/bios_disk.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -22,59 +22,416 @@ #include "regs.h" #include "mem.h" #include "dos_inc.h" /* for Drives[] */ +#include "mapper.h" -static Bitu call_int13; -static BIOS_Disk * Floppys[2]; -static BIOS_Disk * Harddisks[BIOS_MAX_DISK]; +#define MAX_SWAPPABLE_DISKS 20 + +diskGeo DiskGeometryList[] = { + {160, 8, 1, 40, 0}, + {180, 9, 1, 40, 0}, + {320, 8, 2, 40, 1}, + {360, 9, 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}, +}; + +Bitu call_int13; +Bitu diskparm0, diskparm1; static Bit8u last_status; +static Bit8u last_drive; +Bit16u imgDTASeg; +RealPt imgDTAPtr; +DOS_DTA *imgDTA; +bool killRead; + +/* 2 floppys and 2 harddrives, max */ +imageDisk *imageDiskList[4]; +imageDisk *diskSwap[MAX_SWAPPABLE_DISKS]; +Bits swapPosition; + +void updateDPT(void) { + Bit32u tmpheads, tmpcyl, tmpsect, tmpsize; + if(imageDiskList[2] != NULL) { + imageDiskList[2]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize); + real_writew(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0)),tmpcyl); + real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+2,tmpheads); + real_writew(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0x3,0); + real_writew(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0x5,(Bit16u)-1); + real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0x7,0); + real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0x8,(0xc0 | (((imageDiskList[2]->heads) > 8) << 3))); + real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0x9,0); + real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0xa,0); + real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0xb,0); + real_writew(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0xc,tmpcyl); + real_writeb(RealSeg(CALLBACK_RealPointer(diskparm0)),RealOff(CALLBACK_RealPointer(diskparm0))+0xe,tmpsect); + } + if(imageDiskList[3] != NULL) { + imageDiskList[3]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize); + real_writew(RealSeg(CALLBACK_RealPointer(diskparm1)),RealOff(CALLBACK_RealPointer(diskparm1)),tmpcyl); + real_writeb(RealSeg(CALLBACK_RealPointer(diskparm1)),RealOff(CALLBACK_RealPointer(diskparm1))+2,tmpheads); + real_writeb(RealSeg(CALLBACK_RealPointer(diskparm1)),RealOff(CALLBACK_RealPointer(diskparm1))+0xe,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; + } +} + +void swapInNextDisk(void) { + swapPosition++; + if(diskSwap[swapPosition] == NULL) swapPosition = 0; + swapInDisks(); +} -static Bitu INT13_SmallHandler(void) { - switch (reg_ah) { +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); + fwrite(data, sector_size, 1, diskimg); + + return 0x00; + +} + +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) { + founddisk = true; + active = true; + floppytype = i; + heads = DiskGeometryList[i].headscyl; + cylinders = DiskGeometryList[i].cylcount; + sectors = DiskGeometryList[i].secttrack; + break; + } + i++; + } + if(!founddisk) { + active = false; + } + } +} + +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 DiskGeometryList[floppytype].biosval; + } else return 0; +} + +Bit32u imageDisk::getSectSize(void) { + return sector_size; +} + +static Bitu GetDosDriveNumber(Bitu biosNum) { + switch(biosNum) { case 0x0: - reg_ah=0x00; + 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; + Bits readcnt; + int i,t; + last_drive = reg_dl; + drivenum = GetDosDriveNumber(reg_dl); + //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(driveInactive(drivenum)) return CBRET_NONE; + last_status = 0x00; CALLBACK_SCF(false); - LOG(LOG_BIOS,LOG_NORMAL)("reset disk return succesfull"); break; - case 0x02: /* Read Disk Sectors */ - LOG(LOG_BIOS,LOG_NORMAL)("INT13:02:Read Disk Sectors not supported failing"); - reg_ah=0x80; + 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 0x04: - if(Drives[reg_dl]!=NULL) { - reg_ah=0; + case 0x2: /* Read sectors */ + 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); - } - else{ - reg_ah=0x80; - CALLBACK_SCF(true); - } - LOG(LOG_BIOS,LOG_NORMAL)("INT 13:04 Verify sector used on %d, with result %d",reg_dl,reg_ah); - break; - - case 0x08: /* Get Drive Parameters */ - LOG(LOG_BIOS,LOG_NORMAL)("INT13:08:Get Drive parameters not supported failing"); - reg_ah=0xff; - CALLBACK_SCF(true); break; - case 0xff: + 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; + } + } + CALLBACK_SCF(false); + break; + case 0x04: /* Verify sectors */ + 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; + //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); + reg_ch = tmpcyl; + reg_cl = tmpsect; + reg_dh = tmpheads-1; + last_status = 0x00; + reg_dl = 0; + if(imageDiskList[2] != NULL) reg_dl++; + if(imageDiskList[3] != 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)("Illegal int 13h call %2X Fail it",reg_ah); + 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_SmallHandler,CB_IRET); + //CALLBACK_Setup(call_int13,&INT13_SmallHandler,CB_IRET); + CALLBACK_Setup(call_int13,&INT13_DiskHandler,CB_IRET); RealSetVec(0x13,CALLBACK_RealPointer(call_int13)); -/* Init the Disk Tables */ - last_status=0; -/* Setup the Bios Area */ - mem_writeb(BIOS_HARDDISK_COUNT,0); -}; + int i; + for(i=0;i<4;i++) { + imageDiskList[i] = NULL; + } + + for(i=0;i MAX_SCAN_CODE) goto irq1_end; - if (mod & KBD_MOD_ALT) { /* Alt is being pressed */ + 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; - } else if (mod & KBD_MOD_CTRL) { /* Ctrl is being pressed */ +#endif + } else if (flags1 & 0x04) { /* Ctrl is being pressed */ asciiscan=scan_to_scanascii[scancode].control; - } else if (mod & KBD_MOD_SHIFT) { /* Either shift is being pressed */ + } 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; + } + } add_key(asciiscan); + break; }; irq1_end: + if(scancode !=0xe0) flags3 &=~0x02; //Reset 0xE0 Flag mem_writeb(BIOS_KEYBOARD_FLAGS1,flags1); mem_writeb(BIOS_KEYBOARD_FLAGS2,flags2); mem_writeb(BIOS_KEYBOARD_FLAGS3,flags3); + mem_writeb(BIOS_KEYBOARD_LEDS,leds); irq1_return: - IO_Write(0x20,0x20); +/* IO_Write(0x20,0x20); moved out of handler to be virtualizable */ #if 0 - /* Signal the keyboard for next code */ +/* 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(0x61,old61 & 127); + IO_Write(0x64,0xae); #endif return CBRET_NONE; } @@ -313,6 +382,7 @@ static Bitu INT16_Handler(void) { if (temp==0) { CALLBACK_Idle();}; } while (temp==0); reg_ax=temp; + if(reg_al==0xe0) reg_al=0; //extended key break; } case 0x01: /* CHECK FOR KEYSTROKE */ @@ -323,13 +393,14 @@ static Bitu INT16_Handler(void) { } else { CALLBACK_SZF(false); reg_ax=temp; + if(reg_al==0xe0) reg_al=0; //extended key } break; case 0x02: /* GET SHIFT FlAGS */ reg_al=mem_readb(BIOS_KEYBOARD_FLAGS1); break; case 0x03: /* SET TYPEMATIC RATE AND DELAY */ - LOG(LOG_BIOS,LOG_ERROR)("INT16:Unhandled Typematic Rate Call %2X",reg_al); + 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 */ //TODO make add_key bool :) @@ -362,6 +433,8 @@ static void InitBiosSegment(void) { mem_writeb(BIOS_KEYBOARD_FLAGS1,0); 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,16); } void BIOS_SetupKeyboard(void) { @@ -370,9 +443,23 @@ void BIOS_SetupKeyboard(void) { /* 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_STI); + CALLBACK_Setup(call_int16,&INT16_Handler,CB_IRET_STI,"keyboard"); RealSetVec(0x16,CALLBACK_RealPointer(call_int16)); - CALLBACK_Setup(call_irq1,&IRQ1_Handler,CB_IRET); + CALLBACK_Setup(call_irq1,&IRQ1_Handler,CB_IRET,"keyboard irq"); RealSetVec(0x9,CALLBACK_RealPointer(call_irq1)); + + /* bring the all port operations outside the callback */ + phys_writeb(CB_BASE+(call_irq1<<4)+0x00,(Bit8u)0x50); // push ax + phys_writeb(CB_BASE+(call_irq1<<4)+0x01,(Bit8u)0xe4); // in al, 0x60 + phys_writeb(CB_BASE+(call_irq1<<4)+0x02,(Bit8u)0x60); + phys_writeb(CB_BASE+(call_irq1<<4)+0x03,(Bit8u)0xFE); //GRP 4 + phys_writeb(CB_BASE+(call_irq1<<4)+0x04,(Bit8u)0x38); //Extra Callback instruction + phys_writew(CB_BASE+(call_irq1<<4)+0x05,call_irq1); //The immediate word + phys_writeb(CB_BASE+(call_irq1<<4)+0x07,(Bit8u)0xb0); // mov al, 0x20 + phys_writeb(CB_BASE+(call_irq1<<4)+0x08,(Bit8u)0x20); + phys_writeb(CB_BASE+(call_irq1<<4)+0x09,(Bit8u)0xe6); // out 0x20, al + phys_writeb(CB_BASE+(call_irq1<<4)+0x0a,(Bit8u)0x20); + phys_writeb(CB_BASE+(call_irq1<<4)+0x0b,(Bit8u)0x58); // pop ax + phys_writeb(CB_BASE+(call_irq1<<4)+0x0c,(Bit8u)0xcf); // iret } diff --git a/src/ints/dpmi.cpp b/src/ints/dpmi.cpp deleted file mode 100644 index dbbe45f..0000000 --- a/src/ints/dpmi.cpp +++ /dev/null @@ -1,3233 +0,0 @@ -/* - * Copyright (C) 2002-2004 The DOSBox Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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. - */ - -// Pharlap Special Infos: -// - Dont hook hardware ints -// - CMOS Memory Size has to return 0 otherwise it tries to map physical memory -// - Set PM Int Vector : Use it on current idt, not only dpmi one (ultima 8 mouse check fails otherwise) -// - Ultima 8 wants 40 Files (Hack in PSP::SetNumFiles -// - Ultima 8 and Bioforge work with DPL 3 -// - Crusaders 1+2 seem to need DPL 0, which is bad... -// - Bioforge uses more than 2048 descriptos in ldt (4096) - -#include -#include -#include -#include "dosbox.h" -#include "dos_inc.h" -#include "callback.h" -#include "mem.h" -#include "regs.h" -#include "dos_system.h" -#include "setup.h" -#include "inout.h" -#include "cpu.h" -#include "bios.h" -#include "paging.h" - -#include "debug.h" - -//#define DPMI_LOG LOG(LOG_MISC,LOG_ERROR) -#define DPMI_LOG - -#define DPMI_LOG_ERROR LOG(LOG_MISC,LOG_ERROR) -//#define DPMI_LOG_ERROR - -#define DPMI_ALLOC_NEEDEDMEM_HIGH 1 - -#define DPMI_DPL 3 - -#define GDT_ZERO 0 -#define GDT_LDT ((0x1 << 3) | DPMI_DPL) -#define GDT_CODE ((0x2 << 3) | DPMI_DPL) -#define GDT_PROTCODE ((0x3 << 3) | DPMI_DPL) -#define GDT_DOSDATA ((0x4 << 3) | DPMI_DPL) -#define GDT_ENVIRONMENT ((0x5 << 3) | DPMI_DPL) - -#define GDT_DOSSEG40 (0x40) - -/* Amount of descriptors in each table */ -#define GDT_SIZE 32 -#define IDT_SIZE 256 -#define LDT_SIZE 4096 -#define INT_SIZE 256 - -#define TOTAL_SIZE ((GDT_SIZE+IDT_SIZE+LDT_SIZE+INT_SIZE)*8) - -#define LDT_ENTRY(BLAH_) (BLAH_ << 3) - -#define LDT_FIRSTSELECTOR 16 - -#define DPMI_ERROR_UNSUPPORTED 0x8001 -#define DPMI_ERROR_DESCRIPTOR_UNAVAILABLE 0x8011 -#define DPMI_ERROR_LINEAR_MEMORY_UNAVAILABLE 0x8012 -#define DPMI_ERROR_PHYSICAL_MEMORY_UNAVAILABLE 0x8013 -#define DPMI_ERROR_CALLBACK_UNAVAILABLE 0x8015 -#define DPMI_ERROR_INVALID_SELECTOR 0x8022 -#define DPMI_ERROR_INVALID_VALUE 0x8022 -#define DPMI_ERROR_INVALID_HANDLE 0x8023 -#define DPMI_ERROR_INVALID_CALLBACK 0x8024 -#define DPMI_ERROR_INVALID_LINEAR_ADDRESS 0x8025 - -#define DPMI_XMSHANDLES_MAX 256 -#define DPMI_XMSHANDLE_FREE 0xFFFF -#define DPMI_EXCEPTION_MAX 0x20 -#define DPMI_PAGE_SIZE (4*1024) -#define DPMI_REALMODE_CALLBACK_MAX 32 -#define DPMI_REALMODE_STACKSIZE 4096 -#define DPMI_PROTMODE_STACK_MAX 3 -#define DPMI_PROTMODE_STACKSIZE (4*1024) -#define DPMI_REALVEC_MAX 17 -#define DPMI_SAVESTACK_MAX 1024 - -#define DPMI_CB_APIMSDOSENTRY_OFFSET 256*8 -#define DPMI_CB_ENTERREALMODE_OFFSET 257*8 -#define DPMI_CB_SAVESTATE_OFFSET 258*8 -#define DPMI_CB_EXCEPTION_OFFSET 259*8 -#define DPMI_CB_EXCEPTIONRETURN_OFFSET 260*8 -#define DPMI_CB_VENDORENTRY_OFFSET 261*8 - -static bool g_hookHardwareInts = true; - -void CMOS_SetRegister(Bitu regNr, Bit8u val); - -static Bitu rmIndexToInt[DPMI_REALVEC_MAX] = -{ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x1C }; - -// General functions -void CALLBACK32_SCF(bool val) -{ - Bitu v_esp = 0; - if (cpu.stack.big) v_esp = reg_esp; else v_esp = reg_sp; - Bit32u tempf=mem_readd(SegPhys(ss)+v_esp+8) & 0xFFFFFFFE; - Bit32u newCF=(val==true); - mem_writed(SegPhys(ss)+v_esp+8,(tempf | newCF)); -}; - -#define DPMI_CALLBACK_SCF(b) if (dpmi.client.bit32) CALLBACK32_SCF(b); else CALLBACK_SCF(b) - -// ********************************************** -// SetDescriptor Class -// ********************************************** - -#pragma pack(1) -class SetDescriptor : public Descriptor { -public: - void Save(PhysPt address) { - Bit32u* data = (Bit32u*)&saved; - mem_writed(address,*data); - mem_writed(address+4,*(data+1)); - } - - void SetBase(Bitu _base) { - saved.seg.base_24_31=_base >> 24; - saved.seg.base_16_23=_base >> 16; - saved.seg.base_0_15=_base; - } - void SetLimit (Bitu _limit) { - if (_limit<1048576) saved.seg.g=false; - else { - saved.seg.g=true; - _limit>>=12; - } - saved.seg.limit_0_15=_limit; - saved.seg.limit_16_19=_limit>>16; - } - void SetOffset(Bitu _offset) { - saved.gate.offset_0_15=_offset; - saved.gate.offset_16_31=(_offset>>16); - } - void SetSelector(Bitu _selector) { - saved.gate.selector=_selector; - } - void SetType(Bitu _type) { - saved.seg.type=_type; - } - void Clear(void) { - saved.fill[0]=saved.fill[1]=0; - } -}; -#pragma pack() - -// ********************************************** -// Shared Memory -// ********************************************** - -typedef struct SSharedMem { - - std::string name; - Bitu handle; - Bitu pages; - -} TSharedMem; - -std::list g_sharedMemList; - -// ********************************************** -// DPMI Class -// ********************************************** - -class DPMI { - -public: - DPMI (void); - ~DPMI (void); - - // Settp/Startup methods - void Setup (void); - Bitu Entrypoint (void); - RealPt HookInterrupt (Bitu num, Bitu intHandler); - void RestoreHookedInterrupt (Bitu num, RealPt oldVec); - void CreateStackSpace (void); - bool HasClient (void) { return dpmi.client.have; }; - void Terminate (void); - void Reactivate (void); - - // DPMI Services - Bitu AllocateLDTDescriptor (Bitu count,Bitu & base); - Bitu AllocateLDTDescriptor2 (Bitu count,Bitu & base); // TEMP - bool AllocateMem (Bitu size, Bitu& outHandle, Bitu& linear); - Bitu CreateAlias (Bitu selector, Bit16u& alias); - void ReloadSegments (Bitu selector); - bool SetAccessRights (Bitu selector, SetDescriptor& desc, Bitu rights); - bool SetProtInterrupt (Bitu num, Bitu selector, Bitu offset); - - // Special Interrupt handlers - Bitu Int2fHandler (void); - Bitu Int31Handler (void); - - // Exceptions - Bitu CreateException (void); - void CreateException (Bitu num, Bitu errorCode); - Bitu ExceptionReturn (void); - - // Realmode callbacks - bool AllocateRealModeCallback(Bitu codeSel,Bitu codeOff,Bitu dataSel, Bitu dataOff, Bitu& segment, Bitu& offset); - Bitu RealModeCallback (void); - Bitu RealModeCallbackReturn (void); - - // Real mode reflection callbacks - void PrepareReflectToReal (Bitu num); - Bitu CallRealIRETFrame (bool callAsInt); - Bitu CallRealIRETFrameReturn (void); - Bitu SimulateInt (void); - Bitu SimulateIntReturn (void); - Bitu ptorHandler (void); - Bitu ptorHandlerReturn (void); - Bitu Int21Handler (void); - Bitu Int21HandlerReturn (void); - Bitu HWIntDefaultHandler (void); - void RemoveIntCallbacks (void); - void RestoreIntCallbacks (void); - - // Switching modes - void SaveRegisterState (Bitu num); - void LoadRegisterState (Bitu num); - Bitu EnterProtMode (void); - Bitu EnterRealMode (void); - Bitu RealSaveState (void); - Bitu ProtSaveState (void); - - // virtual interrupt flag - bool GetVirtualIntFlag (void); - void SetVirtualIntFlag (bool on); - - // Internal Stack for saving processor status - void PushStack (Bitu val) { saveStack[savePtr++] = val; }; - Bitu PopStack (void) { return saveStack[--savePtr]; }; - void SaveSegments (void); - void SaveRegister (void); - void RestoreSegments (void); - void RestoreRegister (void); - - void CopyRegistersToBuffer (PhysPt data); - void LoadRegistersFromBuffer (PhysPt data); - - void ProvideRealModeStack (PhysPt prStack, Bitu toCopy); - void UpdateRealModeStack (void); - - // xms handle information - void SetXMSHandle (Bitu handle); - void ClearXMSHandles (void); - void FreeXMSHandle (Bitu handle); - - // shared memory - void SetSharedMem (const char* name, Bitu handle, Bitu pages); - bool GetSharedMem (const char* name, Bitu& handle, Bitu& pages); - bool IsSharedMem (Bitu handle); - bool RemoveSharedMem (Bitu handle); - - // special msdos api stuff - void SetupPharlapSelectors (void); - bool Pharlap_AllocateMem (Bitu size, Bitu& outHandle, Bitu& linear); - Bitu GetSegmentFromSelector (Bitu selector); - bool GetMsdosSelector (Bitu realseg, Bitu realoff, Bitu &protsel, Bitu &protoff); - void API_Init_MSDOS (void); - Bitu API_Entry_MSDOS (void); - Bitu API_Int21_MSDOS (void); - - // debug - void Debug_ShowDescriptors (void); - -private: - Bitu Mask (Bitu value); - - Bitu saveStack[DPMI_SAVESTACK_MAX]; - Bitu savePtr; - Bitu rm_ss, rm_sp; - - struct { - struct { - bool have; - bool bit32; - Bitu psp; - } client; - Bit32s mem_handle; /* Handle for GDT/IDT */ - Bitu idtBase,idtLimit; - struct { - PhysPt base; - Bitu limit; - } gdt,idt,ldt; - struct { - bool inCall; - bool inUse; - bool stop; - Bitu callCount; - Bitu id; - Bitu dataSelector,dataOffset; - Bitu codeSelector,codeOffset; - Bitu realSegment ,realOffset; - } rmCallback[DPMI_REALMODE_CALLBACK_MAX]; - - RealPt realModeVec [DPMI_REALVEC_MAX]; - Bitu oldRealVec [DPMI_REALVEC_MAX]; - Bitu defaultHWIntFromProtMode[DPMI_REALVEC_MAX]; - - PhysPt ptorint_base; /* Base of pmode int handlers that reflect to realmode */ - Bitu exceptionSelector[DPMI_EXCEPTION_MAX],exceptionOffset[DPMI_EXCEPTION_MAX]; - - Bitu xmsHandles[DPMI_XMSHANDLES_MAX]; - Bitu protStack; - - Bitu protStackSelector[DPMI_PROTMODE_STACK_MAX]; - Bitu realStackSelector[DPMI_PROTMODE_STACK_MAX]; - Bitu dataSelector [DPMI_PROTMODE_STACK_MAX]; - Bitu protStackCurrent; - - Bitu vIntFlag; - - bool pharlap; - bool suppressRMCB; - - // Pharlap stuff - Bitu initialcs,initialds; - Bitu initialenv; - } dpmi; - - Bit32u* modIntTable; - DPMI* prevDPMI; - std::vector dosSelectorList; - - Bitu dtaAddress; - Bitu save_cs[2],save_ds[2],save_es[2],save_fs[2],save_gs[2],save_ss[2]; - Bitu save_eax[2],save_ebx[2],save_ecx[2],save_edx[2],save_esi[2],save_edi[2]; - Bitu save_ebp[2],save_esp[2],save_eip[2],save_fl[2]; -}; - -struct { - Bitu entry; - Bitu ptorint; - Bitu ptorintReturn; - Bitu int31; - Bitu int21; - Bitu int21Return; - Bitu int2f; - Bitu enterpmode; - Bitu enterrmode; - Bitu protsavestate; - Bitu realsavestate; - Bitu simint; - Bitu simintReturn; - Bitu rmIntFrame; - Bitu rmIntFrameReturn; - Bitu rmCallbackReturn; - Bitu exception; - Bitu exceptionret; - // Special callbacks for special dos extenders - Bitu apimsdosentry; - Bitu int21msdos; -} callback; - -// ************************************************ -// DPMI static functions -// ************************************************ - -#define SWITCH_TO_REALMODE CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); \ - CPU_SIDT(dpmi.idtLimit,dpmi.idtBase); \ - CPU_LIDT(256*4,0); - -#define SWITCH_TO_PROTMODE CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); \ - CPU_LIDT(dpmi.idtLimit,dpmi.idtBase); - - -static DPMI* activeDPMI = 0; -static Bit32u originalIntTable[256]; - -bool DPMI_IsActive(void) -{ - return (cpu.cr0 & CR0_PROTECTION) && activeDPMI && activeDPMI->HasClient(); -} - -void DPMI_SetVirtualIntFlag(bool on) -{ - if (activeDPMI) activeDPMI->SetVirtualIntFlag(on); -} - -void DPMI_CreateException(Bitu num, Bitu errorCode) -{ - if (activeDPMI) activeDPMI->CreateException(num,errorCode); -} - -// ************************************************ -// DPMI Methods -// ************************************************ - -DPMI::DPMI(void) -{ - memset(&dpmi,0,sizeof(dpmi)); - savePtr = 0; - dtaAddress = 0; - rm_ss = rm_sp = 0; - modIntTable = 0; - prevDPMI = activeDPMI; -}; - -DPMI::~DPMI(void) -{ - MEM_ReleasePages(dpmi.mem_handle); - dosSelectorList.clear(); - // TODO: Free all memory allocated with DOS_GetMemory - // Activate previous dpmi - activeDPMI = prevDPMI; - // Restore hookHardwareInts ability which may be changed by a pharlap program - if (!activeDPMI) g_hookHardwareInts = true; -}; - -void DPMI::ClearXMSHandles(void) -{ - for (Bitu i=0; iname = name; - smem->handle= handle; - smem->pages = pages; - g_sharedMemList.push_back(smem); -}; - -bool DPMI::GetSharedMem(const char* name, Bitu& handle, Bitu& pages) -{ - TSharedMem* smem; - std::list::iterator i; - for(i = g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) { - smem = static_cast(*i); - if (smem->name.compare(name)==0) { - handle = smem->handle; - pages = smem->pages; - return true; - } - - }; - return false; -}; - -bool DPMI::IsSharedMem(Bitu handle) -{ - std::list::iterator i; - for(i = g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) { - if ((*i)->handle==handle) return true; - }; - return false; -}; - -bool DPMI::RemoveSharedMem(Bitu handle) -{ - TSharedMem* smem; - std::list::iterator i; - for(i = g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) { - smem = static_cast(*i); - if (smem->handle==handle) { - g_sharedMemList.remove(*i); - delete smem; - return true; - } - - }; - return false; -}; - -void DPMI::SetXMSHandle(Bitu handle) { - for (Bitu i=0; i=DPMI_SAVESTACK_MAX) E_Exit("DPMI: Stack too small."); - saveStack[savePtr++] = SegValue(ds); - saveStack[savePtr++] = SegValue(es); - saveStack[savePtr++] = SegValue(fs); - saveStack[savePtr++] = SegValue(gs); - saveStack[savePtr++] = SegValue(ss); -} - -void DPMI::SaveRegister(void) -{ - SaveSegments(); - if (savePtr+8>=DPMI_SAVESTACK_MAX) E_Exit("DPMI: Stack too small."); - saveStack[savePtr++] = reg_eax; - saveStack[savePtr++] = reg_ebx; - saveStack[savePtr++] = reg_ecx; - saveStack[savePtr++] = reg_edx; - saveStack[savePtr++] = reg_esi; - saveStack[savePtr++] = reg_edi; - saveStack[savePtr++] = reg_ebp; - saveStack[savePtr++] = reg_esp; -}; - -void DPMI::RestoreSegments(void) -{ - CPU_SetSegGeneral(ss,saveStack[--savePtr]); - CPU_SetSegGeneral(gs,saveStack[--savePtr]); - CPU_SetSegGeneral(fs,saveStack[--savePtr]); - CPU_SetSegGeneral(es,saveStack[--savePtr]); - CPU_SetSegGeneral(ds,saveStack[--savePtr]); -}; - -void DPMI::RestoreRegister(void) -{ - reg_esp = saveStack[--savePtr]; - reg_ebp = saveStack[--savePtr]; - reg_edi = saveStack[--savePtr]; - reg_esi = saveStack[--savePtr]; - reg_edx = saveStack[--savePtr]; - reg_ecx = saveStack[--savePtr]; - reg_ebx = saveStack[--savePtr]; - reg_eax = saveStack[--savePtr]; - RestoreSegments(); -}; - -void DPMI::CopyRegistersToBuffer(PhysPt data) -{ - // Save Values in structure - mem_writed(data+0x00, reg_edi); - mem_writed(data+0x04, reg_esi); - mem_writed(data+0x08, reg_ebp); - mem_writed(data+0x0C, 0x0000); - mem_writed(data+0x10, reg_ebx); - mem_writed(data+0x14, reg_edx); - mem_writed(data+0x18, reg_ecx); - mem_writed(data+0x1C, reg_eax); - mem_writew(data+0x20, reg_flags); - mem_writew(data+0x22, SegValue(es)); - mem_writew(data+0x24, SegValue(ds)); - mem_writew(data+0x26, SegValue(fs)); - mem_writew(data+0x28, SegValue(gs)); - mem_writew(data+0x2A, reg_ip); - mem_writew(data+0x2C, SegValue(cs)); - mem_writew(data+0x2E, reg_sp); - mem_writew(data+0x30, SegValue(ss)); -} - -void DPMI::LoadRegistersFromBuffer(PhysPt data) -{ - reg_edi = mem_readd(data+0x00); - reg_esi = mem_readd(data+0x04); - reg_ebp = mem_readd(data+0x08); - reg_ebx = mem_readd(data+0x10); - reg_edx = mem_readd(data+0x14); - reg_ecx = mem_readd(data+0x18); - reg_eax = mem_readd(data+0x1C); - CPU_SetFlagsw(mem_readw(data+0x20)); - SegSet16(es,mem_readw(data+0x22)); - SegSet16(ds,mem_readw(data+0x24)); - SegSet16(fs,mem_readw(data+0x26)); - SegSet16(gs,mem_readw(data+0x28)); - reg_esp = mem_readw(data+0x2E); - SegSet16(ss,mem_readw(data+0x30)); - if (!dpmi.client.bit32) { - reg_eax &= 0xFFFF; - reg_ebx &= 0xFFFF; - reg_ecx &= 0xFFFF; - reg_edx &= 0xFFFF; - reg_edi &= 0xFFFF; - reg_esi &= 0xFFFF; - reg_ebp &= 0xFFFF; - reg_esp &= 0xFFFF; - }; -}; - -void DPMI::ProvideRealModeStack(PhysPt prStack, Bitu toCopy) -{ - // Check stack, if zero provide it - if ((SegValue(ss)==0) && (reg_sp==0)) { - SegSet16(ss,rm_ss); - reg_esp = rm_sp; - } else { - if (SegValue(ss)==rm_ss) reg_esp = rm_sp; - }; - // We have to be in realmode here - if (toCopy>0) { - Bitu numBytes = toCopy*2; - if (reg_espDPMI_REALMODE_STACKSIZE) E_Exit("DPMI:Realmode stack out of range: %04X",reg_esp); - rm_sp = reg_sp; - } -}; - -Bitu DPMI::AllocateLDTDescriptor(Bitu count,Bitu & base) { - - SetDescriptor test; - Bitu i=16, found=0; - PhysPt address = dpmi.ldt.base + LDT_FIRSTSELECTOR*8; - while (i0;found--) { - test.Save(address); - address+=8; - } - return true; - } - } - return false; -} - -Bitu DPMI::AllocateLDTDescriptor2(Bitu count,Bitu & base) { - - static Bitu allocated = 0; - - SetDescriptor desc; - Bitu nr = LDT_FIRSTSELECTOR + allocated; - if (nr+count < LDT_SIZE) { - desc.Clear(); - desc.SetType(DESC_DATA_EU_RW_NA); - desc.saved.seg.p = 1; - desc.saved.seg.big = dpmi.client.bit32; - desc.saved.seg.dpl = DPMI_DPL; - base = (nr << 3)|(4|DPMI_DPL); /* Make it an LDT Entry */ - allocated += count; - Bitu address = dpmi.ldt.base+(base & ~7); - for (;count>0;count--) { - desc.Save(address); - address+=8; - } - return true; - }; - return false; -} - -Bitu DPMI::CreateAlias(Bitu selector, Bit16u& alias) -{ - Descriptor oldDesc; - Bitu base; - if (!cpu.gdt.GetDescriptor(selector,oldDesc)) { alias = DPMI_ERROR_INVALID_SELECTOR; return false; }; - if (!AllocateLDTDescriptor(1,base)) { alias = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; return false; }; - SetDescriptor desc; - desc.Clear(); - desc.SetLimit(oldDesc.GetLimit()); - desc.SetBase (oldDesc.GetBase()); - desc.SetType (DESC_DATA_ED_RW_A); - desc.saved.seg.p=1; - desc.saved.seg.dpl = DPMI_DPL; - desc.Save (dpmi.ldt.base+(base & ~7)); - alias = base; - return true; -}; - -void DPMI::ReloadSegments(Bitu selector) -{ - if (SegValue(cs)==selector) CPU_SetSegGeneral(cs,selector); - if (SegValue(ds)==selector) CPU_SetSegGeneral(ds,selector); - if (SegValue(es)==selector) CPU_SetSegGeneral(es,selector); - if (SegValue(fs)==selector) CPU_SetSegGeneral(fs,selector); - if (SegValue(gs)==selector) CPU_SetSegGeneral(gs,selector); - if (SegValue(ss)==selector) CPU_SetSegGeneral(ss,selector); -}; - -Bitu DPMI::CreateException(void) -{ - // Division by Zero - CreateException(0,0); - return CBRET_NONE; -}; - -void DPMI::CreateException(Bitu num, Bitu errorCode) -{ - // Assuming Stack looks like a int has occured - Bitu stack_eip,stack_cs,stack_flags; - if (dpmi.client.bit32) { - // Clean up stack - stack_eip = CPU_Pop32(); - stack_cs = CPU_Pop32(); - stack_flags = CPU_Pop32(); - // Push values for exception handler - CPU_Push32(SegValue(ss)); - CPU_Push32(reg_esp); - CPU_Push32(stack_flags); - CPU_Push32(stack_cs); - CPU_Push32(stack_eip); - CPU_Push32(errorCode); - CPU_Push32(GDT_PROTCODE); // return cs - CPU_Push32(DPMI_CB_EXCEPTIONRETURN_OFFSET); // return eip - } else { - // Clean up stack - stack_eip = CPU_Pop16(); - stack_cs = CPU_Pop16(); - stack_flags = CPU_Pop16(); - // Push values for exception handler - CPU_Push16(SegValue(ss)); - CPU_Push16(reg_sp); - CPU_Push16(stack_flags); - CPU_Push16(stack_cs); - CPU_Push16(stack_eip); - CPU_Push16(errorCode); - CPU_Push16(GDT_PROTCODE); // return cs - CPU_Push16(DPMI_CB_EXCEPTIONRETURN_OFFSET); // return eip - }; - DPMI_LOG("DPMI: Exception occured : %04X (%04X:%08X)",num,dpmi.exceptionSelector[num],dpmi.exceptionOffset[num]); - CPU_JMP(dpmi.client.bit32,dpmi.exceptionSelector[num],dpmi.exceptionOffset[num]); -}; - -Bitu DPMI::ExceptionReturn(void) -{ - Bitu error; - // Restore Registers - Bitu newcs; - if (dpmi.client.bit32) { - error = CPU_Pop32(); - reg_eip = CPU_Pop32(); - newcs = CPU_Pop32(); - CPU_SetFlagsd(CPU_Pop32()); - reg_esp = CPU_Pop32(); - CPU_SetSegGeneral(ss,CPU_Pop32()); - } else { - error = CPU_Pop16(); - reg_eip = CPU_Pop16(); - newcs = CPU_Pop16(); - CPU_SetFlagsw(CPU_Pop16()); - reg_esp = CPU_Pop16(); - CPU_SetSegGeneral(ss,CPU_Pop16()); - }; - DPMI_LOG("DPMI: Return from Exception. Jump to %04X:%08X",SegValue(cs),reg_eip); - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - return 0; -}; - -void DPMI::RemoveIntCallbacks() -// When switching dpmi clients, remove active callbacks from hardware int -{ - Bitu i; - modIntTable = new Bit32u[256]; - // read and store interrupt table - for (i=0; i<256; i++) modIntTable[i] = mem_readd(i*4); - // set a clean interrupt table - for (i=0; i<256; i++) mem_writed(i*4,originalIntTable[i]); -}; - -void DPMI::RestoreIntCallbacks() -{ - if (modIntTable) { - // restore modified interrupt table - for (int i=0; i<256; i++) mem_writed(i*4,modIntTable[i]); - delete[] modIntTable; modIntTable = 0; - } -}; - -bool DPMI::AllocateRealModeCallback(Bitu codeSel,Bitu codeOff,Bitu dataSel, Bitu dataOff, Bitu& segment, Bitu& offset) -{ - Bitu num = 0; - for (Bitu i=0; i=DPMI_REALMODE_CALLBACK_MAX) || !dpmi.rmCallback[num].inUse) E_Exit("DPMI: Illegal Realmode callback %02X.",num); - - if (dpmi.rmCallback[num].inCall) DPMI_LOG("DPMI: Recursive Realmode callback %02X",num); - if (dpmi.protStackCurrent>DPMI_PROTMODE_STACK_MAX) E_Exit("DPMI: Too many recursive Realmode callbacks. Stack failure."); - - PushStack(num); - - DPMI_LOG("DPMI: Realmode Callback %02X (%04X:%08X) enter",num,dpmi.rmCallback[num].codeSelector,dpmi.rmCallback[num].codeOffset); - dpmi.rmCallback[num].inCall= true; - dpmi.rmCallback[num].callCount++; - - // Important! Update realmode stack - UpdateRealModeStack(); - // Setup stack selector of real mode stack - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(dpmi.realStackSelector[dpmi.protStackCurrent],desc)) { - desc.SetBase (SegValue(ss)<<4); - desc.SetLimit(0xFFFF); - desc.Save (dpmi.ldt.base+(dpmi.realStackSelector[dpmi.protStackCurrent] & ~7)); - } else E_Exit("DPMI: RealmodeCB: Could not provide real mode stack descriptor."); - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - // Setup dataSelector - Descriptor data; - Bitu dataSelector; - if (dpmi.rmCallback[num].dataSelector==0x0000) dataSelector = dpmi.dataSelector[dpmi.protStackCurrent]; - else dataSelector = dpmi.rmCallback[num].dataSelector; - if (!cpu.gdt.GetDescriptor(dataSelector,data)) E_Exit("DPMI: Init RM-Callback failed."); - - DPMI_LOG("DPMI: CB: Writing RegData at = %04X:%04X",dataSelector,dpmi.rmCallback[num].dataOffset); - // Prepare data buffer - CopyRegistersToBuffer(PhysPt(data.GetBase()+dpmi.rmCallback[num].dataOffset)); - DPMI_LOG("DPMI: CB: Stored cs:ip = %04X:%04X",SegValue(cs),reg_ip); - // setup registers for protected mode func - CPU_SetSegGeneral(ds,dpmi.realStackSelector[dpmi.protStackCurrent]); // DS:ESI = RM Stack - reg_esi = reg_esp; - CPU_SetSegGeneral(es,dataSelector); // ES:EDI = RM Register data - reg_edi = dpmi.rmCallback[num].dataOffset; - // SS:ESP = API stack - CPU_SetSegGeneral(ss,dpmi.protStackSelector[dpmi.protStackCurrent++]); - reg_esp = DPMI_PROTMODE_STACKSIZE; - // prepare stack for iret - if (dpmi.client.bit32) CPU_Push32(reg_flags); else CPU_Push16(reg_flags); - // Setup cs:ip to return to DPMI_ReturnFromRealModeCallback - CPU_SetSegGeneral(cs,GDT_CODE); - reg_eip = RealOff(CALLBACK_RealPointer(callback.rmCallbackReturn)); - // call protected mode func - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_Push32(reg_flags); - CPU_CALL(dpmi.client.bit32,dpmi.rmCallback[num].codeSelector,dpmi.rmCallback[num].codeOffset); - return 0; -}; - -Bitu DPMI::RealModeCallbackReturn(void) -{ - // returning from protected mode function, now back to real mode - Bitu num = PopStack(); - DPMI_LOG("DPMI: Realmode Callback leave %02X",num); - dpmi.suppressRMCB = false; - dpmi.rmCallback[num].inCall = false; - dpmi.rmCallback[num].stop = false; - dpmi.rmCallback[num].callCount--; - PhysPt data = PhysPt(SegPhys(es)+reg_edi); - DPMI_LOG("DPMI: CB: Reading RegData at = %04X:%04X",SegValue(es),reg_edi); - /* Swtich to real mode */ - SWITCH_TO_REALMODE - dpmi.protStackCurrent--; - // Restore Registers - LoadRegistersFromBuffer(data); - Bitu newCS = mem_readw(data+0x2C); - Bitu newIP = mem_readw(data+0x2A); - UpdateRealModeStack(); - SetVirtualIntFlag(true); - DPMI_LOG("DPMI: CB: Retored cs:ip = %04X:%04X (%d)",newCS,newIP); - CPU_JMP(false,newCS,newIP); - return 0; -}; - -static Bitu count = 0; - -Bitu DPMI::CallRealIRETFrame(bool callAsInt) -{ - Bitu calledIP = mem_readd(SegPhys(ss)+reg_esp); - Bitu calledCS = mem_readd(SegPhys(ss)+reg_esp+4); - DPMI_LOG("DPMI: ENTER REAL PROC IRETF %04X:%08X",calledCS,calledIP); - // Save changed registers - PushStack(SegValue(cs)); - SaveRegister(); - Bitu toCopy = reg_cx; - // Load Registers - PhysPt data = SegPhys(es) + reg_edi; - PhysPt prStack = SegPhys(ss) + reg_esp; - LoadRegistersFromBuffer(data); - PushStack(data); - /* Switch to real mode */ - SWITCH_TO_REALMODE - // Provide Stack - ProvideRealModeStack(prStack,toCopy); - // Push flags - if (callAsInt) CPU_Push16(reg_flags); - // Setup IP - Bitu newCS = mem_readw(data+0x2C); - Bitu newIP = mem_readw(data+0x2A); - // Setup cs:ip to return to DPMI_CallRealIRETFrame callback - SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.rmIntFrameReturn))); - reg_ip = RealOff(CALLBACK_RealPointer(callback.rmIntFrameReturn)); - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_CALL(false,newCS,newIP); - return 0; -} - -Bitu DPMI::CallRealIRETFrameReturn(void) -{ - UpdateRealModeStack(); - // returning from realmode func - DPMI_LOG("DPMI: LEAVE REAL PROC IRETF %d",count); - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - // Save registers into real mode structure - CopyRegistersToBuffer(PopStack()); - // Restore changed Resgisters - RestoreRegister(); - Bitu newcs = PopStack(); - - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - - SetVirtualIntFlag(true); - DPMI_CALLBACK_SCF(false); - return 0; -}; - -Bitu DPMI::SimulateInt(void) -{ - Bitu num = reg_bl; - DPMI_LOG("DPMI: SIM INT %02X %04X called. cs = %04X",num,reg_ax,SegValue(cs)); - // Save changed registers - PushStack(SegValue(cs)); - SaveRegister(); - Bitu toCopy = reg_cx; - // Load Registers - PhysPt data = SegPhys(es) + reg_edi; - PhysPt prStack = SegPhys(ss) + reg_esp; - LoadRegistersFromBuffer(data); - PushStack(data); - /* Switch to real mode */ - SWITCH_TO_REALMODE - // Provide Stack - ProvideRealModeStack(prStack,toCopy); - // prepare for return - SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.simintReturn))); - reg_ip = RealOff(CALLBACK_RealPointer(callback.simintReturn)); - // Push flags from structure on stack - DPMI_LOG("DPMI: SimInt1: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); - reg_flags = mem_readw(data+0x20); - CPU_SW_Interrupt(num,0); - DPMI_LOG("DPMI: SimInt2: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); - return 0; -}; - -Bitu DPMI::SimulateIntReturn(void) -{ - // returning from realmode func - DPMI_LOG("DPMI: SIM INT return"); - DPMI_LOG("DPMI: SimIntRet1: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); - - UpdateRealModeStack(); - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - // Save registers into real mode structure - CopyRegistersToBuffer(PopStack()); - // Restore changed Resgisters - RestoreRegister(); - Bitu newcs = PopStack(); - DPMI_LOG("DPMI: SimIntRet: JUMP to %04X:%08X",newcs,reg_eip); - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - SetVirtualIntFlag(true); - // Free last realmode stack - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: SimIntRet2: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); - return 0; -}; - -void DPMI::PrepareReflectToReal(Bitu num) -{ - // Save segment and stack register - SaveSegments(); - PushStack(reg_esp); - PushStack(num); - PushStack(reg_eip); - PushStack(SegValue(cs)); - /* Swtich to real mode */ - SWITCH_TO_REALMODE - // Setup cs:ip to return to intreturn - Bitu retcs = RealSeg(CALLBACK_RealPointer(callback.ptorintReturn)); - Bitu retip = RealOff(CALLBACK_RealPointer(callback.ptorintReturn)); - - SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.ptorintReturn))); - reg_ip = RealOff(CALLBACK_RealPointer(callback.ptorintReturn)); - // setup stack - SegSet16(ss,rm_ss); - reg_esp = rm_sp; -} - -Bitu DPMI::ptorHandler(void) -{ - /* Pmode interrupt handler that maps the interrupt to realmode */ - Bitu num = reg_eip >> 3; -// if (!dpmi.vIntFlag) { -// if ((num>=0x08) && (num<=0x0F)) return 0; -// if ((num>=0x70) && (num<=0x77)) return 0; -// }; - PrepareReflectToReal(num); -// if (num==0x0F) - DPMI_LOG("DPMI: INT %02X %04X called.",num,reg_ax); - // Prepare flags for real int - // CPU_SetFlagsw(reg_flags & 0x3ED5); // 0011111011010101b - CPU_SW_Interrupt(num,0); - return 0; -} - -Bitu DPMI::ptorHandlerReturn(void) -// Return from reflected real mode int -{ - UpdateRealModeStack(); - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - // Restore Registers - Bitu newcs = PopStack(); - reg_eip = PopStack(); - Bitu num = PopStack(); - reg_esp = PopStack(); - RestoreSegments(); -// if (num==0x0F) - DPMI_LOG("DPMI: INT %02X RETURN",num); - // hardware ints exit here - if (((num>=0x08) && (num<=0x0F)) || ((num>=0x70) && (num<=0x77))) { - SetVirtualIntFlag(true); - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - return 0; - } - // Change flags on stack to reflect possible results from ints - if (dpmi.client.bit32) { - Bit32u oldFlags = mem_readd(SegPhys(ss)+reg_esp+8) & ~FMASK_TEST; // leave only flags that cannot be changed by int - Bit32u userFlags = reg_flags & FMASK_NORMAL; // Mask out illegal flags not to change by int (0011111011010101b) - mem_writed(SegPhys(ss)+reg_esp+8,oldFlags|userFlags); - } else { - Bit16u oldFlags = mem_readw(SegPhys(ss)+reg_sp+4) & ~FMASK_TEST; // leave only flags that cannot be changed by int - Bit16u userFlags = reg_flags & FMASK_NORMAL; // Mask out illegal flags not to change by int (0011111011010101b) - mem_writew(SegPhys(ss)+reg_sp+4,oldFlags|userFlags); - }; - SetVirtualIntFlag(true); - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - return 0; -} - -Bitu DPMI::Int21Handler(void) -{ - // Check for exit - if (reg_ah==0x4C) { - DPMI_LOG("DPMI: INT 21: Terminating."); - Terminate(); - } - // Save segment and stack register - PushStack(SegValue(ss)); - PushStack(reg_esp); - PushStack(SegValue(ds)); - PushStack(SegValue(es)); - PushStack(SegValue(cs)); - - /* Swtich to real mode */ - SWITCH_TO_REALMODE - // Setup cs:ip to return to intreturn - SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.int21Return))); - reg_ip = RealOff(CALLBACK_RealPointer(callback.int21Return)); - // setup stack - SegSet16(ss,rm_ss); - reg_esp = rm_sp; - // Call realmode interrupt - DPMI_LOG("DPMI: INT 21 %04X called.",reg_ax); - CPU_SW_Interrupt(0x21,0); - if (reg_ah==0x4C) { - // Shut doen dpmi and restore previous one - delete this; - if (activeDPMI) activeDPMI->Reactivate(); - } - return 0; -}; - -Bitu DPMI::Int21HandlerReturn(void) -{ - UpdateRealModeStack(); - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - // Restore Registers - Bitu newcs = PopStack(); - CPU_SetSegGeneral(es,PopStack()); - CPU_SetSegGeneral(ds,PopStack()); - reg_esp = PopStack(); - CPU_SetSegGeneral(ss,PopStack()); - // Set carry flag - DPMI_CALLBACK_SCF(reg_flags & 1); - DPMI_LOG("DPMI: INT 21 RETURN"); - SetVirtualIntFlag(true); - CPU_JMP(dpmi.client.bit32,newcs,reg_eip); - return 0; -} - -Bitu DPMI::HWIntDefaultHandler() -// Wir sind hier im Protected mode -// a) durch einen INTerrupt im protected mode -// b) durch einen INTerrupt im real mode (durch RMCB) -{ - Bitu index = mem_readw(PhysPt(SegPhys(cs)+reg_eip-2)) - dpmi.defaultHWIntFromProtMode[0]; - if (index>=DPMI_REALVEC_MAX) E_Exit("DPMI: Illegal realmode interrupt callback: %02X",index); - Bitu num = rmIndexToInt[index]; - - RealPt vec = RealGetVec(num); - - if (dpmi.rmCallback[index].callCount==0) { - // INT PROT (Use Handler is already done). - // Wenn rmcb noch in Realmode Int table installiert, dann originalMethode aufrufef - if (vec==dpmi.realModeVec[index]) { - // originalroutine aufrufen - dpmi.rmCallback[index].stop = false; - PrepareReflectToReal(num); - CPU_Push16(reg_flags); - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_CALL(false,RealSeg(dpmi.oldRealVec[index]),RealOff(dpmi.oldRealVec[index])); - } else { - // user real mode handler in real mode int table aktiv. - // Moeglich, dass dieser den RMCB von Hand noch aufruft - // dann wird aber callCount>0 sein (da RMCB aktiv) und - // dann die alte Routine aufgerufen... - // RMCB sperren, um einen erneuten Aufruf des User Handlers zu vermeiden,.. - - // This is a hack for cybermage wich wont work otherwise. But why ? - if (num==0x0F) { - if (dpmi.suppressRMCB) { - dpmi.suppressRMCB = false; - return 0; - } else { - dpmi.suppressRMCB = true; - } - }; - PrepareReflectToReal(num); - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_Push16(reg_flags); - CPU_CALL(false,RealSeg(vec),RealOff(vec)); - } - } else { - // INT REAL (vom RMCB aktiviert) - // Falls user handler schon aktiv war (int von prot->reflected to real) - // rufe original routine auf - if (dpmi.rmCallback[index].stop) { - dpmi.rmCallback[index].stop = false; - PrepareReflectToReal(num); - CPU_Push16(reg_flags); - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_CALL(false,RealSeg(dpmi.oldRealVec[index]),RealOff(dpmi.oldRealVec[index])); - } else { - // User routine wurde noch nicht aktiviert, callback aber ausgeführt - // falls spezieller protected mode handler aktiviert wurde, - // wird dieser jetzt aufgerufen (user routine im protected mode) - Descriptor gate; - gate.Load(dpmi.idt.base+num*8); - if ((gate.GetSelector()!=GDT_CODE) || (gate.GetOffset()!=RealOff(dpmi.defaultHWIntFromProtMode[index]))) { - dpmi.rmCallback[index].stop = true; // vermeide rekursion - CPU_JMP(dpmi.client.bit32,gate.GetSelector(),gate.GetOffset()); - } else { - // kein spezieller Protmode handler - Rufe originalroutine auf - PrepareReflectToReal(num); - CPU_Push16(reg_flags); - SetVirtualIntFlag(false); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - CPU_CALL(false,RealSeg(dpmi.oldRealVec[index]),RealOff(dpmi.oldRealVec[index])); - }; - }; - } - return 0; -}; - -void DPMI::SaveRegisterState(Bitu num) -// Copy Current Registers to structure -{ - return; - save_cs[num] = SegValue(cs); - save_ds[num] = SegValue(ds); - save_es[num] = SegValue(es); - save_fs[num] = SegValue(fs); - save_gs[num] = SegValue(gs); - save_ss[num] = SegValue(ss); - save_eip[num] = reg_eip; - save_eax[num] = reg_eax; - save_ebx[num] = reg_ebx; - save_ecx[num] = reg_ecx; - save_edx[num] = reg_edx; - save_esi[num] = reg_esi; - save_edi[num] = reg_edi; - save_ebp[num] = reg_ebp; - save_esp[num] = reg_esp; - save_fl [num] = reg_flags; -}; - -void DPMI::LoadRegisterState(Bitu num) -// Copy Current Registers to structure -{ - return; - CPU_SetSegGeneral(fs,save_fs[num]); - CPU_SetSegGeneral(gs,save_gs[num]); - reg_eax = save_eax[num]; - reg_ebx = save_ebx[num]; - reg_ecx = save_ecx[num]; - reg_edx = save_edx[num]; - reg_esi = save_esi[num]; - reg_edi = save_edi[num]; - reg_flags = save_fl [num]; -}; - -Bitu DPMI::EnterProtMode(void) { - - /* Save real mode register state */ - SaveRegisterState(0); - - /* Switch to protected mode */ - SWITCH_TO_PROTMODE - - CPU_SetSegGeneral(ds,reg_ax); - CPU_SetSegGeneral(es,reg_cx); - CPU_SetSegGeneral(ss,reg_dx); - CPU_SetSegGeneral(ds,reg_ax); - - if (dpmi.client.bit32) { - reg_esp = reg_ebx; - CPU_JMP(true,reg_si,reg_edi); - } else { - reg_sp = reg_bx; - CPU_JMP(false,reg_si,reg_di); - }; - - /* Load prot mode register state (all other unchanged registers */ - LoadRegisterState(1); - - DPMI_LOG("DPMI: Switch to protected mode."); - return 0; -} - -Bitu DPMI::EnterRealMode(void) { - - /* Save Prot Mode Registers */ - SaveRegisterState(1); - - /* Swtich to real mode */ - SWITCH_TO_REALMODE - // (E)BP will be preserved across the mode switch call so it can be used as a pointer. - // TODO: If interrupts are disabled when the mode switch procedure is invoked, - // they will not be re-enabled by the DPMI host (even temporarily). - SegSet16(ds,reg_ax); - SegSet16(es,reg_cx); - SegSet16(ss,reg_dx); - SegSet16(fs,0); - SegSet16(gs,0); - if (dpmi.client.bit32) { - reg_esp = reg_ebx; - CPU_JMP(true,reg_si,reg_edi); - } else { - reg_sp = reg_bx; - CPU_JMP(false,reg_si,reg_di); - }; - - /* Load real mode register state (all other unchanged registers) */ - LoadRegisterState(0); - DPMI_LOG("DPMI: Switch to real mode."); - return CBRET_NONE; -}; - -Bitu DPMI::RealSaveState(void) -{ - return CBRET_NONE; - /* Save Protected mode state */ - if (reg_al==0) { - PhysPt data = SegPhys(es) + reg_edi; - mem_writew(data+ 0,save_cs[1]); - mem_writew(data+ 2,save_ds[1]); - mem_writew(data+ 4,save_es[1]); - mem_writew(data+ 6,save_fs[1]); - mem_writew(data+ 8,save_gs[1]); - mem_writew(data+10,save_ss[1]); - mem_writed(data+12,save_eax[1]); - mem_writed(data+16,save_ebx[1]); - mem_writed(data+20,save_ecx[1]); - mem_writed(data+24,save_edx[1]); - mem_writed(data+28,save_esi[1]); - mem_writed(data+32,save_edi[1]); - mem_writed(data+36,save_ebp[1]); - mem_writed(data+40,save_esp[1]); - mem_writed(data+44,save_fl [1]); - DPMI_LOG("DPMI: Prot Save State."); - } else if (reg_al==1) { - /* restore state of prot mode registers */ - PhysPt data = SegPhys(es) + reg_edi; - save_cs [1] = mem_readw(data+ 0); - save_ds [1] = mem_readw(data+ 2); - save_es [1] = mem_readw(data+ 4); - save_fs [1] = mem_readw(data+ 6); - save_gs [1] = mem_readw(data+ 8); - save_ss [1] = mem_readw(data+10); - save_eax[1] = mem_readd(data+12); - save_ebx[1] = mem_readd(data+16); - save_ecx[1] = mem_readd(data+20); - save_edx[1] = mem_readd(data+24); - save_edi[1] = mem_readd(data+28); - save_esi[1] = mem_readd(data+32); - save_ebp[1] = mem_readd(data+36); - save_esp[1] = mem_readd(data+40); -// save_eip[1] = mem_readd(data+44); - save_fl [1] = mem_readd(data+44); - DPMI_LOG("DPMI: Prot Restore State."); - }; - return CBRET_NONE; -}; - -Bitu DPMI::ProtSaveState(void) -{ - return CBRET_NONE; - if (reg_al==0) { - /* Save State of real mode registers */ - PhysPt data = SegPhys(es) + reg_edi; - mem_writew(data+ 0,save_cs[0]); - mem_writew(data+ 2,save_ds[0]); - mem_writew(data+ 4,save_es[0]); - mem_writew(data+ 6,save_fs[0]); - mem_writew(data+ 8,save_gs[0]); - mem_writew(data+10,save_ss[0]); - mem_writed(data+12,save_eax[0]); - mem_writed(data+16,save_ebx[0]); - mem_writed(data+20,save_ecx[0]); - mem_writed(data+24,save_edx[0]); - mem_writed(data+28,save_esi[0]); - mem_writed(data+32,save_edi[0]); - mem_writed(data+36,save_ebp[0]); - mem_writed(data+40,save_esp[0]); - mem_writed(data+44,save_eip[0]); - mem_writed(data+48,save_fl [0]); - DPMI_LOG("DPMI: Real Save State."); - } else if (reg_al==1) { - /* restore state of real mode registers */ - PhysPt data = SegPhys(es) + reg_edi; - save_cs [0] = mem_readw(data+ 0); - save_ds [0] = mem_readw(data+ 2); - save_es [0] = mem_readw(data+ 4); - save_fs [0] = mem_readw(data+ 6); - save_gs [0] = mem_readw(data+ 8); - save_ss [0] = mem_readw(data+10); - save_eax[0] = mem_readd(data+12); - save_ebx[0] = mem_readd(data+16); - save_ecx[0] = mem_readd(data+20); - save_edx[0] = mem_readd(data+24); - save_edi[0] = mem_readd(data+28); - save_esi[0] = mem_readd(data+32); - save_ebp[0] = mem_readd(data+36); - save_esp[0] = mem_readd(data+40); - save_eip[0] = mem_readd(data+44); - save_fl [0] = mem_readd(data+48); - DPMI_LOG("DPMI: Real Restore State."); - }; - return CBRET_NONE; -}; - -bool DPMI::GetVirtualIntFlag(void) -// only to call from int 31 cos it uses the pushed flags on int stack -{ - if (dpmi.client.bit32) return (mem_readd(SegPhys(ss)+reg_esp+8) & FLAG_IF)>0; - else return (mem_readd(SegPhys(ss)+reg_sp+4) & FLAG_IF)>0; -}; - -void DPMI::SetVirtualIntFlag(bool on) -{ - dpmi.vIntFlag = 1; //on; -}; - -bool DPMI::AllocateMem(Bitu size, Bitu& outHandle, Bitu& linear) -{ - Bitu pages = (size/DPMI_PAGE_SIZE) + ((size%DPMI_PAGE_SIZE)>0); // Convert to 4KB pages - outHandle = MEM_AllocatePages(pages,true); - linear = outHandle*DPMI_PAGE_SIZE; - if (outHandle!=0) SetXMSHandle(outHandle); - return (outHandle!=0); -}; - -bool DPMI::SetAccessRights(Bitu selector, SetDescriptor& desc, Bitu rights) -{ - // must equal caller DPL - if (((rights & 0x60)>>5)!=DPMI_DPL) { - DPMI_LOG("DPMI: Set Rights %04X : %04X failure (dpl=%02X)",selector,rights,(rights & 0x60)>>5); -// return false; - } - // must be 1 - if ((rights & 0x10)==0) { - DPMI_LOG_ERROR("DPMI: Set Rights %04X : %04X failure (must be 1)",selector,rights); - return false; - }; - // must be 0 - if (dpmi.client.bit32 && desc.saved.seg.p && (rights & 0x2000)) { - DPMI_LOG_ERROR("DPMI: Set Rights %04X : %04X failure (must be 0)",selector,rights); - return false; - }; - // all tests passed, set rights for 16 + 32 Bit - desc.SetType (rights&0x1F); - desc.saved.seg.dpl = (rights&0x60)>>5; - desc.saved.seg.dpl = DPMI_DPL; - desc.saved.seg.p = (rights&0x80)>0; - // extended rights for 32 Bit apps - if (dpmi.client.bit32) { - desc.saved.seg.avl = (rights&0x1000)>0; - desc.saved.seg.r = (rights&0x2000)>0; - desc.saved.seg.big = (rights&0x4000)>0; - desc.saved.seg.g = (rights&0x8000)>0; - }; - return true; -}; - -Bitu DPMI::Int31Handler(void) -{ - switch (reg_ax) { - - case 0x0000:{// Allocate LDT Descriptors - Bitu base; - Descriptor desc; - if (AllocateLDTDescriptor(reg_cx,base)) { - reg_ax = base; - DPMI_LOG("DPMI: 0000: Allocate %d descriptors: %04X",reg_cx,base); - DPMI_CALLBACK_SCF(false); - } else { - DPMI_LOG_ERROR("DPMI: 0000: Allocate %d descriptors failure",reg_cx); - reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0001:{// Free Descriptor - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - desc.saved.seg.p = 0; - desc.Save (dpmi.ldt.base+(reg_bx & ~7)); - DPMI_LOG("DPMI: 0001: Free Descriptor: %04X",reg_bx); - DPMI_CALLBACK_SCF(false); - } else { - DPMI_LOG_ERROR("DPMI: 0001: Free Descriptor failure : %04X",reg_bx); - reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0002:{// Segment to Descriptor - SetDescriptor desc; Bitu base; - if (AllocateLDTDescriptor(1,base)) { - desc.Load (dpmi.ldt.base+(base & ~7)); - desc.SetLimit(0xFFFF); - desc.SetBase (reg_bx<<4); - desc.saved.seg.dpl=3; - desc.Save (dpmi.ldt.base+(base & ~7)); - reg_ax = base; - DPMI_LOG("DPMI: 0000: Seg %04X to Desc: %04X",reg_bx,base); - DPMI_CALLBACK_SCF(false); - } else { - // No more Descriptors available - DPMI_LOG_ERROR("DPMI: 0002: No more Descriptors available."); - reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0003:// Get Next Selector Increment Value - reg_ax = 8; - DPMI_LOG("DPMI: 0003: Get Selector Inc Value: %04X",reg_ax); - DPMI_CALLBACK_SCF(false); - break; - case 0x0004:// undocumented (reserved) lock selector - case 0x0005:// undocumented (reserved) unlock selector - DPMI_LOG("DPMI: 0004: Undoc: (un)lock selector",reg_ax); - DPMI_CALLBACK_SCF(true); - break; - case 0x0006:{ // Get Segment Base Address - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - DPMI_LOG("DPMI: 0006: Get Base %04X : B:%08X",reg_bx,desc.GetBase()); - reg_cx = (Bit16u)(desc.GetBase()>>16); - reg_dx = (Bit16u)(desc.GetBase()&0xFFFF); - DPMI_CALLBACK_SCF(false); - } else { - DPMI_LOG_ERROR("DPMI: 0006: Invalid Selector: %04X",reg_bx); - reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0007:{// Set Segment base address - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - Bitu base; - if (!dpmi.client.bit32) base = (reg_cl<<16)+reg_dx; - else base = (reg_cx<<16)+reg_dx; - desc.SetBase(base); - desc.Save (dpmi.ldt.base+(reg_bx & ~7)); - ReloadSegments(reg_bx); - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: 0007: Set Base %04X : B:%08X",reg_bx,base); - } else { - DPMI_LOG_ERROR("DPMI: 0007: Invalid Selector: %04X",reg_bx); - reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0008:{// Set Segment limit - SetDescriptor desc; - if ((!dpmi.client.bit32) && (reg_cx!=0)) { - // 16-bit DPMI implementations can not set segment limits greater - // than 0FFFFh (64K) so CX must be zero when calling - DPMI_LOG_ERROR("DPMI: 0008: Set Segment Limit invalid: %04X (%04X%04X)",reg_bx,reg_cx,reg_dx); - reg_ax = DPMI_ERROR_INVALID_VALUE; - DPMI_CALLBACK_SCF(true); - } else if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - desc.SetLimit((reg_cx<<16)+reg_dx); - desc.Save (dpmi.ldt.base+(reg_bx & ~7)); - ReloadSegments(reg_bx); - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: 0008: Set Limit %08X",(reg_cx<<16)+reg_dx); - } else { - DPMI_LOG_ERROR("DPMI: 0008: Invalid Selector: %04X",reg_bx); - reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x0009:{// Set Descriptor Access Rights - SetDescriptor desc; - Bit8u rcl = reg_cl; - Bit8u rch = reg_ch; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - if (!SetAccessRights(reg_bx,desc,reg_cx)) { - DPMI_LOG_ERROR("DPMI: 0009: Set Rights %04X : failure",reg_bx); - reg_ax = DPMI_ERROR_INVALID_VALUE; - DPMI_CALLBACK_SCF(true); - break; - }; - desc.Save(dpmi.ldt.base+(reg_bx & ~7)); - ReloadSegments(reg_bx); - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: 0009: Set Rights %04X : %04X",reg_bx,reg_cx); - } else { - DPMI_LOG_ERROR("DPMI: 0009: Set Rights %04X : invalid selector",reg_bx); - reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x000A:{// Create Alias Descriptor - Descriptor desc; - if (CreateAlias(reg_bx, reg_ax)) { - DPMI_LOG("DPMI: 000A: Create Alias : %04X - %04X",reg_bx,reg_ax); - DPMI_CALLBACK_SCF(false); - } else { - DPMI_CALLBACK_SCF(true); - DPMI_LOG_ERROR("DPMI: 000A: Invalid Selector: %04X",reg_bx); - }; }; break; - case 0x000B:{//Get Descriptor - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - desc.Save(SegPhys(es)+Mask(reg_edi)); - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: 000B: Get Descriptor %04X : B:%08X L:%08X",reg_bx,desc.GetBase(),desc.GetLimit()); - } else { - DPMI_LOG_ERROR("DPMI: 000B: Get Descriptor %04X : failure",reg_bx); - reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x000C:{//Set Descriptor - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { - desc.Load (SegPhys(es)+Mask(reg_edi)); - Bitu rights = (mem_readb(SegPhys(es)+Mask(reg_edi)+6)<<8) + mem_readb(SegPhys(es)+Mask(reg_edi)+5); - if (!SetAccessRights(reg_bx,desc,rights)) { - DPMI_LOG_ERROR("DPMI: 000C: Set Rights %04X : failure",reg_bx); - reg_ax = DPMI_ERROR_INVALID_VALUE; - DPMI_CALLBACK_SCF(true); - break; - }; - // TEMP : Test -/* if (!dpmi.client.bit32) { - if (desc.GetLimit()>0xFFFF) { - DPMI_LOG_ERROR("DPMI: 000C: Set Limit %04X : failure (%08X)",reg_bx,desc.GetLimit()); - desc.SetLimit(0xFFFF); - } - if (desc.GetBase ()>0xFFFFFF) { - DPMI_LOG_ERROR("DPMI: 000C: Set Base %04X : failure (%08X)",reg_bx,desc.GetBase()); - desc.SetBase(desc.GetBase() % 0xFFFFFF); - } - }*/ - desc.Save(dpmi.ldt.base+(reg_bx & ~7)); - ReloadSegments(reg_bx); - DPMI_LOG("DPMI: 000B: Set Descriptor %04X : B:%08X L:%08X : P %01X",reg_bx,desc.GetBase(),desc.GetLimit(),desc.saved.seg.p); - DPMI_CALLBACK_SCF(false); - } else { - DPMI_LOG_ERROR("DPMI: 000C: Set Descriptor %04X failed",reg_bx); - reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x000D:{ // Allocate specific LDT Descriptor : TODO: Support it - DPMI_LOG("DPMI: 000D: Alloc Specific LDT Selector: %04X",reg_bx); - SetDescriptor desc; - if (cpu.gdt.GetDescriptor(reg_bx,desc)) { -// if (!desc.saved.seg.p) { - desc.saved.seg.p = 1; -// desc.SetLimit(0xDEADAAAA); -// desc.SetBase (0xDEADBBBB); - desc.Save (dpmi.ldt.base+(reg_bx & ~7)); - DPMI_CALLBACK_SCF(false); - break; -// } else { -// DPMI_LOG_ERROR("DPMI: 000D: Invalid Selector: %04X",reg_bx); -// reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; -// }; - } else reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - }; break; - case 0x0100:{// Allocate DOS Memory Block - Bit16u blocks = reg_bx; - DPMI_LOG("DPMI: 0100: Allocate DOS Mem: (%04X Blocks)",blocks); - if (DOS_AllocateMemory(®_ax,&blocks)) { - // Allocate Selector for block - SetDescriptor desc; Bitu base; Bitu numDesc; - numDesc = reg_bx/0x1000 + ((reg_bx%0x1000)>0); - if (AllocateLDTDescriptor(numDesc,base)) { - reg_dx = base; - // First selector - if (numDesc>1) { - Bitu descBase = reg_ax*16; - Bitu length = reg_bx*16; - desc.Load (dpmi.ldt.base+(base & ~7)); - desc.SetBase (descBase); - desc.SetLimit(dpmi.client.bit32?length:0xFFFF); - desc.Save (dpmi.ldt.base+(base & ~7)); - for (Bitu i=1; i>4; - DOS_MCB mcb(seg-1); - Bitu size = mcb.GetSize()*16; - if (DOS_FreeMemory(seg)) { - while (size>0) { - desc.Load(dpmi.ldt.base+(sel & ~7)); - desc.saved.seg.p = 0; - desc.Save(dpmi.ldt.base+(sel & ~7)); - size -= (size>=0x10000)?0x10000:size; - sel+=8; - }; - DPMI_CALLBACK_SCF(false); - DPMI_LOG("DPMI: 0101: Free Dos Mem: %04X",reg_dx); - break; - } - } - DPMI_LOG_ERROR("DPMI: 0101: Invalid Selector: %04X",reg_bx); - reg_ax = DPMI_ERROR_INVALID_SELECTOR; - DPMI_CALLBACK_SCF(true); - };break; - case 0x0200:{// Get Real Mode Interrupt Vector - RealPt vec = RealGetVec(reg_bl); - reg_cx = RealSeg(vec); - reg_dx = RealOff(vec); - DPMI_LOG("DPMI: 0200: Get Real Int Vector %02X (%04X:%04X)",reg_bl,reg_cx,reg_dx); - DPMI_CALLBACK_SCF(false); - }; break; - case 0x0201:{// Set Real Mode Interrupt Vector - DPMI_LOG("DPMI: 0201: Set Real Int Vector %02X (%04X:%04X)",reg_bl,reg_cx,reg_dx); - RealSetVec(reg_bl,RealMake(reg_cx,reg_dx)); - DPMI_CALLBACK_SCF(false); - }; break; - case 0x0202:// Get Processor Exception Handler Vector - if (reg_bl>16; - reg_di = handle&0xFFFF; - reg_bx = linear>>16; - reg_cx = linear&0xFFFF; - DPMI_CALLBACK_SCF(false); - // TEMP -// Bitu total = MEM_FreeLargest(); // in KB -// DPMI_LOG_ERROR("DPMI: 0501: Allocation success: H:%04X%04X (%d KB) (R:%d KB)",reg_si,reg_di,length/1024 + ((length%1024)>0),total*4); - } else { - reg_ax = DPMI_ERROR_PHYSICAL_MEMORY_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - // TEMP - Bitu total = MEM_FreeLargest(); // in KB - DPMI_LOG("DPMI: 0501: Allocation failure (%d KB) (R:%d KB)",length/1024 + ((length%1024)>0),total*4); - }; - }; break; - case 0x0502://Free Memory Block - DPMI_LOG("DPMI: 0502: Free Mem: H:%04X%04X",reg_si,reg_di); - MEM_ReleasePages((reg_si<<16)+reg_di); - FreeXMSHandle((reg_si<<16)+reg_di); - DPMI_CALLBACK_SCF(false); - break; - case 0x0503:{//Resize Memory Block - Bitu linear,newHandle; - Bitu newByte = (reg_bx<<16)+reg_cx; - Bitu newSize = (newByte/DPMI_PAGE_SIZE)+((newByte & (DPMI_PAGE_SIZE-1))>0); - MemHandle handle = (reg_si<<16)+reg_di; - DPMI_LOG("DPMI: 0503: Resize Memory: H:%08X (%d KB)",handle,newSize*4); - if (MEM_ReAllocatePages(handle,newSize,true)) { - linear = handle * DPMI_PAGE_SIZE; - reg_si = (Bit16u)(handle>>16); - reg_di = (Bit16u)(handle&0xFFFF); - reg_bx = (Bit16u)(linear>>16); - reg_cx = (Bit16u)(linear&0xFFFF); - DPMI_CALLBACK_SCF(false); - } else if (AllocateMem(newByte,newHandle,linear)) { - // Not possible, try to allocate - DPMI_LOG("DPMI: 0503: Reallocated Memory: %d KB",newSize*4); - reg_si = (Bit16u)(newHandle>>16); - reg_di = (Bit16u)(newHandle&0xFFFF); - reg_bx = (Bit16u)(linear>>16); - reg_cx = (Bit16u)(linear&0xFFFF); - // copy contents - Bitu size = MEM_AllocatedPages(handle); - if (newSize>16; - reg_cx = linear & 0xFFFF; - DPMI_LOG_ERROR("DPMI: 0800: Phys-adr-map not supported : Start:%08X (Size:%08X) - Linear:%08X.",phys,size,linear); - DPMI_CALLBACK_SCF(false); - }; break; - case 0x0801:// Free physical address mapping - DPMI_LOG("DPMI: 0801: Free physical address mapping"); - DPMI_CALLBACK_SCF(false); - break; - case 0x0900://Get and Disable Virtual Interrupt State - reg_al = dpmi.vIntFlag; - dpmi.vIntFlag = 0; - DPMI_LOG("DPMI: 0900: Get and disbale vi : %01X",reg_al); - DPMI_CALLBACK_SCF(false); - break; - case 0x0901://Get and Enable Virtual Interrupt State - reg_al = dpmi.vIntFlag; - dpmi.vIntFlag = 1; - DPMI_LOG("DPMI: 0901: Get and enable vi : %01X",reg_al); - DPMI_CALLBACK_SCF(false); - break; - case 0x0902:{//Get Virtual Interrupt State - reg_al = 0; //dpmi.vIntFlag; - DPMI_LOG("DPMI: 0902: Get vi : %01X",reg_al); - DPMI_CALLBACK_SCF(false); - }; break; - case 0x0A00:{//Get Vendor Specific API Entry Point - char name[256]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_esi),name,255); - LOG(LOG_MISC,LOG_WARN)("DPMI: Get API: %s",name); - if (strcmp(name,"MS-DOS")==0) { - CPU_SetSegGeneral(es,GDT_PROTCODE); - if (dpmi.client.bit32) reg_edi = DPMI_CB_APIMSDOSENTRY_OFFSET; - else reg_di = DPMI_CB_APIMSDOSENTRY_OFFSET; - API_Init_MSDOS(); - DPMI_CALLBACK_SCF(false); - } else if (strstr(name,"HWINT_SUPPORT")!=0) { - reg_ax = DPMI_ERROR_UNSUPPORTED; - DPMI_CALLBACK_SCF(true); - } else if (strstr(name,"CE_SUPPORT")!=0) { - reg_ax = DPMI_ERROR_UNSUPPORTED; - DPMI_CALLBACK_SCF(true); - } else if (strstr(name,"PHARLAP")!=0) { - CPU_SetSegGeneral(es,GDT_PROTCODE); - if (dpmi.client.bit32) reg_edi = DPMI_CB_APIMSDOSENTRY_OFFSET; - else reg_di = DPMI_CB_APIMSDOSENTRY_OFFSET; - API_Init_MSDOS(); - DPMI_CALLBACK_SCF(false); - dpmi.pharlap = true; - } else { - reg_ax = DPMI_ERROR_UNSUPPORTED; - DPMI_CALLBACK_SCF(true); - } - }; break; - case 0x0D00:{//Allocate Shared Memory - char name[256]; - PhysPt data = SegPhys(es)+Mask(reg_edi); - Bitu length = mem_readd(data); - Bitu pages = (length/DPMI_PAGE_SIZE)+((length%DPMI_PAGE_SIZE)>0); - Bitu handle = mem_readd(data+0x08); - Bitu linear = mem_readd(data+0x0C); - Bitu strOffset = mem_readd(data+0x10); - Bitu strSelect = mem_readw(data+0x14); - - Descriptor desc; - if (!cpu.gdt.GetDescriptor(strSelect,desc)) { - DPMI_LOG_ERROR("DPMI: 0D00: shared memory: invalid name selector"); - reg_ax = DPMI_ERROR_INVALID_VALUE; - DPMI_CALLBACK_SCF(true); - return false; - }; - MEM_StrCopy(desc.GetBase()+strOffset,name,256); - - // Already allocated ? - if (!GetSharedMem(name,handle,pages)) { - if (!AllocateMem(length,handle,linear)) { - DPMI_LOG_ERROR("DPMI: 0D00: Allocation shared failure %s (%d KB)",name,pages*4); - reg_ax = DPMI_ERROR_PHYSICAL_MEMORY_UNAVAILABLE; - DPMI_CALLBACK_SCF(true); - break; - }; - // Init first paragraph with zeros - for (Bitu i=0; i<16; i++) mem_writeb(linear+i,0); - SetSharedMem(name,handle,pages); - DPMI_LOG("DPMI: 0D00: Allocate shared memory %s (%d KB) ",name,pages*4); - } else { - linear = handle*DPMI_PAGE_SIZE; - DPMI_LOG("DPMI: 0D00: Reuse shared memory %s (%d KB) ",name,pages*4); - }; - - mem_writed(data+0x04,pages*DPMI_PAGE_SIZE); - mem_writed(data+0x08,handle); - mem_writed(data+0x0C,linear); - DPMI_CALLBACK_SCF(false); - }; break; - case 0x0B00:// Set debug watchpoint - case 0x0B01:// Clear debug watchpoint - DPMI_CALLBACK_SCF(true); - break; - case 0x0E00:// Get Coprocessor Status - DPMI_LOG("DPMI: 0E00: Get Coprocessor status"); - reg_ax = 0x45; // nope, no coprocessor - DPMI_CALLBACK_SCF(false); - break; - case 0x0E01:// Set Coprocessor Emulation - DPMI_LOG("DPMI: 0E01: Set Coprocessor emulation"); - DPMI_CALLBACK_SCF(true); // failure - break; - default :LOG(LOG_MISC,LOG_ERROR)("DPMI: Unsupported func %04X",reg_ax); - reg_ax = DPMI_ERROR_UNSUPPORTED; - DPMI_CALLBACK_SCF(true); // failure - break; - }; - return 0; -} - -Bitu DPMI::Int2fHandler(void) -{ - // Only available in ProtectedMode - // LOG(LOG_MISC,LOG_WARN)("DPMI: 0x2F %04x",reg_ax); - switch (reg_ax) { - case 0x1686: /* Get CPU Mode */ - reg_ax = 0; - break; - case 0x168A: // Only available in protected mode - // Get Vendor-Specific API Entry Point - char name[256]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_esi),name,255); - LOG(LOG_MISC,LOG_WARN)("DPMI: 0x2F 0x168A: Get Specific API :%s",name); - if (strcmp(name,"MS-DOS")==0) { - CPU_SetSegGeneral(es,GDT_PROTCODE); - if (dpmi.client.bit32) reg_edi = DPMI_CB_APIMSDOSENTRY_OFFSET; - else reg_di = DPMI_CB_APIMSDOSENTRY_OFFSET; - reg_al = 0x00; // Success, whatever they want... - API_Init_MSDOS(); - }; - break; - default : // reflect to real - ptorHandler(); - break; - } - return 0; -}; - -// ********************************************************************* -// Callbacks and Callback-Returns -// ********************************************************************* - -static Bitu DPMI_Exception(void) { if (activeDPMI) return activeDPMI->CreateException(); return 0;}; -static Bitu DPMI_ExceptionReturn(void) { if (activeDPMI) return activeDPMI->ExceptionReturn(); return 0;}; -static Bitu DPMI_RealModeCallback(void) { if (activeDPMI) return activeDPMI->RealModeCallback(); return 0;}; -static Bitu DPMI_RealModeCallbackReturn(void) { if (activeDPMI) return activeDPMI->RealModeCallbackReturn(); return 0;}; -static Bitu DPMI_CallRealIRETFrame(void) { if (activeDPMI) return activeDPMI->CallRealIRETFrame(true); return 0;}; -static Bitu DPMI_CallRealIRETFrameReturn(void) { if (activeDPMI) return activeDPMI->CallRealIRETFrameReturn(); return 0;}; -static Bitu DPMI_SimulateInt(void) { if (activeDPMI) return activeDPMI->SimulateInt(); return 0;}; -static Bitu DPMI_SimulateIntReturn(void) { if (activeDPMI) return activeDPMI->SimulateIntReturn(); return 0;}; -static Bitu DPMI_ptorHandler(void) { if (activeDPMI) return activeDPMI->ptorHandler(); return 0;}; -static Bitu DPMI_ptorHandlerReturn(void) { if (activeDPMI) return activeDPMI->ptorHandlerReturn(); return 0;}; -static Bitu DPMI_Int21Handler(void) { if (activeDPMI) return activeDPMI->Int21Handler(); return 0;}; -static Bitu DPMI_Int21HandlerReturn(void) { if (activeDPMI) return activeDPMI->Int21HandlerReturn(); return 0;}; -static Bitu DPMI_HWIntDefaultHandler(void) { if (activeDPMI) return activeDPMI->HWIntDefaultHandler(); return 0;}; -static Bitu DPMI_EnterProtMode(void) { if (activeDPMI) return activeDPMI->EnterProtMode(); return 0;}; -static Bitu DPMI_EnterRealMode(void) { if (activeDPMI) return activeDPMI->EnterRealMode(); return 0;}; -static Bitu DPMI_RealSaveState(void) { if (activeDPMI) return activeDPMI->RealSaveState(); return 0;}; -static Bitu DPMI_ProtSaveState(void) { if (activeDPMI) return activeDPMI->ProtSaveState(); return 0;}; -static Bitu DPMI_Int2fHandler(void) { if (activeDPMI) return activeDPMI->Int2fHandler(); return 0;}; -static Bitu DPMI_Int31Handler(void) { if (activeDPMI) return activeDPMI->Int31Handler(); return 0;}; -static Bitu DPMI_API_Int21_MSDOS(void) { if (activeDPMI) return activeDPMI->API_Int21_MSDOS(); return 0;}; -static Bitu DPMI_API_Entry_MSDOS(void) { if (activeDPMI) return activeDPMI->API_Entry_MSDOS(); return 0;}; - - -// **************************************************************** -// Setup stuff -// **************************************************************** - -bool DPMI::SetProtInterrupt(Bitu num, Bitu selector, Bitu offset) -{ - // Nobody messes with the div0 vector - if (num==0) return true; - - SetDescriptor gate; - gate.Clear(); - gate.saved.seg.p=1; - gate.SetSelector(selector); - gate.SetOffset (Mask(offset)); - gate.SetType (dpmi.client.bit32?DESC_386_INT_GATE:DESC_286_INT_GATE); - gate.saved.seg.dpl = DPMI_DPL; - gate.Save(dpmi.idt.base+num*8); - // Special Pharlap stuff - if (dpmi.pharlap) { - gate.Save(cpu.idt.GetBase()+num*8); - DPMI_LOG("DPMI: 0205: Pharlap: Set Prot Int Vector %02X (%04X:%08X)",reg_bl,reg_cx,reg_edx); - } - return true; -}; - -RealPt DPMI::HookInterrupt(Bitu num, Bitu intHandler) -{ - // Setup realmode hook - RealPt oldVec; - Bitu segment, offset; - // Allocate Realmode callback - RealPt func = CALLBACK_RealPointer(intHandler); - if (AllocateRealModeCallback(GDT_CODE,RealOff(func),0x0000,0x0000,segment,offset)) { - oldVec = RealGetVec(num); - RealSetVec(num,RealMake(segment,offset)); - } else E_Exit("DPMI: Couldnt allocate Realmode-Callback for INT %04X",num); - // Setup protmode hook - func = CALLBACK_RealPointer(intHandler); - SetProtInterrupt(num,GDT_CODE,RealOff(func)); - return oldVec; -} - -void DPMI::RestoreHookedInterrupt(Bitu num, RealPt oldVec) -{ - //.Restore hooked int - RealSetVec(num,oldVec); - RealPt func = CALLBACK_RealPointer(callback.ptorint); - SetDescriptor gate; - gate.Load (dpmi.idt.base+num*8); - gate.SetSelector(GDT_CODE); - gate.SetOffset (RealOff(func)); - gate.Save (dpmi.idt.base+num*8); -} - -void DPMI::Debug_ShowDescriptors(void) -{ - char out1[512]; - SetDescriptor desc; - Bitu i=0; - PhysPt address = dpmi.ldt.base; - while (iRemoveIntCallbacks(); - } - activeDPMI = new DPMI(); - return activeDPMI->Entrypoint(); -} - -Bitu DPMI::Entrypoint(void) -{ - /* This should switch to pmode */ - if (dpmi.client.have) E_Exit("DPMI:Already have a client"); - - LOG(LOG_MISC,LOG_ERROR)("DPMI: Entrypoint (%d Bit)",(reg_ax & 1) ? 32:16); - - MEM_A20_Enable(true); - // Create gdt, ldt, idt and other stuff - Setup(); - - // Save Realmode Registers - SaveRegisterState(0); - - dpmi.client.have = true; - dpmi.client.bit32 = reg_ax & 1; - - // Clear XMS Handles - ClearXMSHandles(); - /* Clear the LDT */ - Bitu i; - for (i=0;i::iterator i; - for(i=g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) - delete static_cast(*i); - (g_sharedMemList.clear)(); -}; - -void DPMI_Init(Section* sec) -{ - Section_prop * section=static_cast(sec); - if (!section->Get_bool("dpmi")) return; - - BIOS_ZeroExtendedSize(); - memset(&callback,0,sizeof(callback)); - - /* setup Real mode Callbacks */ - callback.entry=CALLBACK_Allocate(); - CALLBACK_Setup(callback.entry,DPMI_EntryPoint,CB_RETF,"Entrypoint"); - callback.enterpmode=CALLBACK_Allocate(); - CALLBACK_Setup(callback.enterpmode,DPMI_EnterProtMode,CB_RETF,"Enter PMode"); - callback.realsavestate=CALLBACK_Allocate(); - CALLBACK_Setup(callback.realsavestate,DPMI_RealSaveState,CB_RETF,"Save RealState"); - callback.simint=CALLBACK_Allocate(); - CALLBACK_Setup(callback.simint,DPMI_SimulateInt,CB_IRET,"Sim INT"); - callback.simintReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.simintReturn,DPMI_SimulateIntReturn,CB_IRET,"Sim INT RET"); - callback.rmIntFrame=CALLBACK_Allocate(); - CALLBACK_Setup(callback.rmIntFrame,DPMI_CallRealIRETFrame,CB_IRET,"Call REAL IRET"); - callback.rmIntFrameReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.rmIntFrameReturn,DPMI_CallRealIRETFrameReturn,CB_IRET,"Call REAL IRET RET"); - callback.ptorint=CALLBACK_Allocate(); - CALLBACK_Setup(callback.ptorint,DPMI_ptorHandler,CB_IRET,"INT Handler"); - callback.ptorintReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.ptorintReturn,DPMI_ptorHandlerReturn,CB_IRET,"INT Handler RET"); - callback.int21Return=CALLBACK_Allocate(); - CALLBACK_Setup(callback.int21Return,DPMI_Int21HandlerReturn,CB_IRET,"INT 21 RET"); - callback.rmCallbackReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.rmCallbackReturn,DPMI_RealModeCallbackReturn,CB_IRET,"RMCB RET"); - callback.int21msdos=CALLBACK_Allocate(); - CALLBACK_Setup(callback.int21msdos,DPMI_API_Int21_MSDOS,CB_IRET,"MSDOS INT 21 API"); - - /* Setup multiplex */ - DOS_AddMultiplexHandler(DPMI_Multiplex); - - /* shutdown function */ - sec->AddDestroyFunction(&DPMI_ShutDown); -} - -void DPMI::Reactivate() -{ - /* Load GDT and IDT */ - CPU_LIDT(dpmi.idt.limit,dpmi.idt.base); - CPU_LGDT(dpmi.gdt.limit,dpmi.gdt.base); - CPU_LLDT(GDT_LDT); - cpu.cpl = DPMI_DPL; - RestoreIntCallbacks(); -}; - -void DPMI::Setup() -{ - Bitu i; - Bitu xmssize = (TOTAL_SIZE|(DPMI_PAGE_SIZE-1))+1; - Bitu protStackSize = ((DPMI_PROTMODE_STACK_MAX*DPMI_PROTMODE_STACKSIZE)|(DPMI_PAGE_SIZE-1))+1; - Bitu numPages = ((xmssize+protStackSize) >> 12); - -#if DPMI_ALLOC_NEEDEDMEM_HIGH - // Allocate the GDT,LDT,IDT Stack space (High Mem) - Bitu max = MEM_FreeLargest(); - Bitu temphandle = MEM_AllocatePages(max-numPages,true); - dpmi.mem_handle = MEM_AllocatePages(numPages,true); - if (dpmi.mem_handle==0) { - LOG_MSG("DPMI:Can't allocate XMS memory, disabling dpmi support."); - return; - } - Bitu address = dpmi.mem_handle*DPMI_PAGE_SIZE;; - MEM_ReleasePages(temphandle); -#else - // load LDT and stuff in low mem ( - Bit16u segment; - Bit16u blocks = numPages*4096/16; - if (!DOS_AllocateMemory(&segment,&blocks)) { - LOG_MSG("DPMI:Can't allocate XMS memory, disabling dpmi support."); - return; - }; - Bitu address = segment * 16; -#endif - // Allocate real mode stack space - rm_ss = DOS_GetMemory(DPMI_REALMODE_STACKSIZE/16); - rm_sp = DPMI_REALMODE_STACKSIZE; - // Get Begin of protected mode stack - dpmi.protStack = address + xmssize; - /* Clear the memory */ - PhysPt w; - for (w=address;w0); // Convert to 4KB pages - Bitu maxPages = MEM_FreeLargest(); - if (maxPages0xFFFFF) || (base & 0x0F)) E_Exit("DPMI:MSDOS: Invalid Selector (convert to segment not possible)"); - base >>= 4; - } else E_Exit("DPMI:MSDOS: Invalid Selector (not found)"); - return base; -}; - -bool DPMI::GetMsdosSelector(Bitu realseg, Bitu realoff, Bitu &protsel, Bitu &protoff) -{ - // Check if selector is already in list - for (Bitu i=0; i0xFFFF) E_Exit("DPMI:DOS: Read file size > 0xffff"); - - Bit16u toread = Mask(reg_ecx); - dos.echo = true; - if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) { - MEM_BlockWrite(SegPhys(ds)+Mask(reg_edx),dos_copybuf,toread); - if (dpmi.client.bit32) reg_eax=toread; else reg_ax=toread; -// LOG(LOG_MISC,LOG_ERROR)("READ FILE Handle:%d Size:%d Read:%d",reg_bx,toread,reg_eax); - DPMI_CALLBACK_SCF(false); - - } else { - LOG(LOG_MISC,LOG_ERROR)("DOS: Read file %d failed",reg_bx); - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - } - dos.echo=false; - break; - } - case 0x40: {/* WRITE Write to file or device */ - Bit16u towrite = Mask(reg_ecx); - MEM_BlockRead(SegPhys(ds)+Mask(reg_edx),dos_copybuf,towrite); -// if (reg_bx<=5) LOG(LOG_MISC,LOG_ERROR)("INT 21 40: %s",(char *)dos_copybuf); - if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) { - if (dpmi.client.bit32) reg_eax=towrite; - else reg_ax =towrite; - DPMI_CALLBACK_SCF(false); - } else { - DPMI_LOG("DPMI:MSDOS:Write %d file failure.",reg_bx); - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - } - }; break; - case 0x41: { /* UNLINK Delete file */ - char name1[256]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,255); - if (DOS_UnlinkFile(name1)) { - DPMI_CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - } - }; break; - case 0x42: /* LSEEK Set current file position */ - { - Bit32u pos=(reg_cx<<16) + reg_dx; - Bit32u topos = pos; - if (DOS_SeekFile(reg_bx,&pos,reg_al)) { - reg_dx=(Bit16u)(pos >> 16); - reg_ax=(Bit16u)(pos & 0xFFFF); - DPMI_CALLBACK_SCF(false); - if ((reg_al==0) && (topos!=pos)) { - LOG(LOG_MISC,LOG_ERROR)("SEEK FILE Handle:%d Seek:%d Pos:%d",reg_bx,topos,pos); - LOG(LOG_MISC,LOG_ERROR)("SEEK FILE ERROR : Pos differs"); - } - } else { - LOG(LOG_MISC,LOG_ERROR)("DOS: Seek file %d failed",reg_bx); - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - } - break; - } - case 0x43: { /* Get/Set file attributes */ - char name1[256]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,255); - switch (reg_al) - case 0x00: /* Get */ - { - if (DOS_GetFileAttr(name1,®_cx)) { - DPMI_CALLBACK_SCF(false); - } else { - DPMI_CALLBACK_SCF(true); - reg_ax=dos.errorcode; - } - break; - case 0x01: /* Set */ - DPMI_LOG("DOS:Set File Attributes for %s not supported",name1); - DPMI_CALLBACK_SCF(false); - break; - default: - E_Exit("DOS:0x43:Illegal subfunction %2X",reg_al); - } - }; break; - - case 0x47: { /* CWD Get current directory */ - char name1[256]; - if (DOS_GetCurrentDir(reg_dl,name1)) { - MEM_BlockWrite(SegPhys(ds)+Mask(reg_esi),name1,strlen(name1)+1); - LOG(LOG_MISC,LOG_ERROR)("DOS: Get Dir %s ",name1); - reg_ax=0x0100; - CALLBACK_SCF(false); - } else { - LOG(LOG_MISC,LOG_ERROR)("DOS: Get Dir failed %s ",name1); - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } - }; break; - - case 0x4E: {/* Get first dir entry */ - char name1[256]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,255); - if (DOS_FindFirst(name1,reg_cx)) { - LOG(LOG_MISC,LOG_ERROR)("DOS: Find Dir entry %s success",name1); - DPMI_CALLBACK_SCF(false); - // Copy result to internal dta - if (dtaAddress) MEM_BlockCopy(dtaAddress,PhysMake(RealSeg(dos.dta),RealOff(dos.dta)),dpmi.pharlap?43:128); - reg_ax=0; /* Undocumented */ - } else { - LOG(LOG_MISC,LOG_ERROR)("DOS: Find Dir entry %s failure",name1); - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - }; - }; break; - case 0x4f: /* FINDNEXT Find next matching file */ - // Copy data to dos dta - if (dtaAddress) MEM_BlockCopy(PhysMake(RealSeg(dos.dta),RealOff(dos.dta)),dtaAddress,dpmi.pharlap?43:128); - if (DOS_FindNext()) { - LOG(LOG_MISC,LOG_ERROR)("DOS: FindNext Dir entry success"); - CALLBACK_SCF(false); - // Copy result to internal dta - if (dtaAddress) MEM_BlockCopy(dtaAddress,PhysMake(RealSeg(dos.dta),RealOff(dos.dta)),dpmi.pharlap?43:128); - reg_ax=0xffff; /* Undocumented */ - } else { - LOG(LOG_MISC,LOG_ERROR)("DOS: FindNext Dir entry failure"); - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - }; - break; - case 0x50: /* Set current PSP */ - if (dpmi.pharlap) dos.psp = reg_bx; // pharlap uses real mode paragraph address - else - dos.psp = GetSegmentFromSelector(reg_bx); - DPMI_LOG("DPMI:MSDOS:0x50:Set current psp:%04X",reg_bx); - break; - case 0x51: /* Get current PSP */ - if (dpmi.pharlap) reg_bx = dos.psp; // pharlap uses real mode paragraph address - else { - GetMsdosSelector(dos.psp,0x0000,protsel,protoff); - reg_bx = protsel; - }; - DPMI_LOG("DPMI:MSDOS:0x51:Get current psp:%04X",reg_bx); - break; - case 0x55 : { // Neuen PSP erstellen - Bitu segment = GetSegmentFromSelector(reg_dx); - DOS_ChildPSP(segment,reg_si); - dos.psp = segment; - DPMI_LOG("DPMI:MSDOS:0x55:Create new psp:%04X",segment); - }; break; - case 0x56: { /* RENAME Rename file */ - char name1[256+1]; - char name2[256+1]; - MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,256); - MEM_StrCopy(SegPhys(es)+Mask(reg_edi),name2,256); - if (DOS_Rename(name1,name2)) { - DPMI_CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - DPMI_CALLBACK_SCF(true); - } - }; break; - case 0x5D : // Get Address of dos swappable area - // FIXME: This is totally faked... - // FIXME: Add size in bytes (at least pharlap) - // FIXME: Depending on al, two functions (pharlap) - GetMsdosSelector(0xDEAD,0xDEAD,protsel,protoff); - CPU_SetSegGeneral(ds,protsel); - reg_si = protoff; - DPMI_LOG("DPMI:MSDOS:0x5D:Get Addres of DOS SwapArea:%04X",reg_si); - break; - case 0x62 : /* Get Current PSP Address */ - GetMsdosSelector(dos.psp,0x0000,protsel,protoff); - reg_bx = protsel; - DPMI_LOG("DPMI:MSDOS:0x62:Get current psp:%04X",reg_bx); - break; - case 0x68: // Flush file to disc - DPMI_CALLBACK_SCF(false); - break; - - case 0x09: - case 0x0A: - case 0x0C: - case 0x1B: - case 0x1C: - case 0x26: // Pharlap != MS-DOS -// case 0x30: // Pharlap extended information - case 0x31: - case 0x32: - case 0x3A: - case 0x48: // Pharlap = 4KB mem pages - case 0x49: - case 0x4A: // Pharlap = 4KB mem pages - case 0x4B: - case 0x52: - case 0x53: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5E: - case 0x5F: - case 0x60: -// case 0x62: - case 0x65: - case 0x6C: - E_Exit("DPMI:MSDOS-API:function %04X not yet supported.",reg_ax); - break; - - // *** PASS THROUGH *** - case 0x44: if ((reg_al==0x02) || (reg_al==0x03) || (reg_al==0x04) || (reg_al==0x05) || (reg_al==0x0C) || (reg_al==0x0D)) { - E_Exit("DPMI:MSDOS-API:function %04X not yet supported.",reg_ax); - }; - case 0x07: case 0x0B: case 0x0E: case 0x19: case 0x2A: case 0x2C: case 0x2D: case 0x30: - case 0x36: case 0x3E: case 0x4C: case 0x58: case 0x67: - { - // reflect to real mode - DPMI_Int21Handler(); - }; - break; - default: E_Exit("DPMI:MSDOS-API:Missing function %04X",reg_ax); - - }; - return 0; -}; diff --git a/src/ints/ems.cpp b/src/ints/ems.cpp index 34ad243..718a2d5 100644 --- a/src/ints/ems.cpp +++ b/src/ints/ems.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.31 2004/02/02 20:23:54 qbix79 Exp $ */ +/* $Id: ems.cpp,v 1.34 2004/08/04 09:12:56 qbix79 Exp $ */ #include #include @@ -150,9 +150,20 @@ 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; - /* Check to do unmapping or mappning */ + if (log_page> 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; + } + IO_WriteB(0x3df,crtcpu); + real_writeb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE,crtcpu); + } else INT10_SetActivePage(reg_al); break; case 0x06: /* Scroll Up */ @@ -342,7 +361,7 @@ graphics_chars: break; case 0x06: reg_al=0x4f; - reg_ah=VESA_ScanLineLength(reg_al,reg_bx,reg_cx,reg_dx); + reg_ah=VESA_ScanLineLength(reg_bl,reg_bx,reg_cx,reg_dx); break; case 0x07: switch (reg_bl) { @@ -437,7 +456,7 @@ static void SetupTandyBios(void) { 0x64, 0x2e, 0x0d, 0x0a, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x61, 0x6e, 0x64, 0x79 }; Bitu i; - real_writeb(0xffff,0xe,0xff); + phys_writeb(0xffffe,0xff); for(i=0;i<130;i++) { phys_writeb(0xf0000+i+0xc000, TandyConfig[i]); } @@ -445,7 +464,7 @@ static void SetupTandyBios(void) { void INT10_Init(Section* sec) { INT10_InitVGA(); - if (machine==MCH_TANDY || machine==MCH_AUTO) SetupTandyBios(); + if (machine==MCH_TANDY) SetupTandyBios(); /* Setup the INT 10 vector */ call_10=CALLBACK_Allocate(); CALLBACK_Setup(call_10,&INT10_Handler,CB_IRET); diff --git a/src/ints/int10.h b/src/ints/int10.h index 417def0..a0bed3a 100644 --- a/src/ints/int10.h +++ b/src/ints/int10.h @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -39,6 +39,7 @@ #define BIOSMEM_SWITCHES 0x88 #define BIOSMEM_MODESET_CTL 0x89 #define BIOSMEM_DCC_INDEX 0x8A +#define BIOSMEM_CRTCPU_PAGE 0x8A #define BIOSMEM_VS_POINTER 0xA8 @@ -104,11 +105,10 @@ struct VideoModeBlock { Bitu htotal,vtotal; Bitu hdispend,vdispend; - Bitu rate; Bitu special; }; -extern VideoModeBlock ModeList[]; +extern VideoModeBlock ModeList_VGA[]; extern VideoModeBlock * CurMode; typedef struct { diff --git a/src/ints/int10_char.cpp b/src/ints/int10_char.cpp index cf463b3..04a4ef8 100644 --- a/src/ints/int10_char.cpp +++ b/src/ints/int10_char.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.22 2004/01/28 18:04:18 harekiet Exp $ */ +/* $Id: int10_char.cpp,v 1.30 2004/09/10 22:08:45 harekiet Exp $ */ /* Character displaying moving functions */ @@ -68,8 +68,8 @@ static INLINE void TANDY16_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rne static INLINE void EGA16_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) { PhysPt src,dest;Bitu copy; Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); - dest=base+(CurMode->twidth*rnew)*cheight+cleft; - src=base+(CurMode->twidth*rold)*cheight+cleft; + dest=base+(CurMode->twidth*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 */ @@ -85,6 +85,19 @@ static INLINE void EGA16_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew, IO_Write(0x3ce,5);IO_Write(0x3cf,0); /* Normal transfer mode */ } +static INLINE void VGA_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) { + PhysPt src,dest;Bitu copy; + Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); + dest=base+8*((CurMode->twidth*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*row)*cheight+cleft)*4; + PhysPt dest=base+((CurMode->twidth*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; + PhysPt dest=base+(CurMode->twidth*row)*cheight+cleft; Bitu nextline=CurMode->twidth; - Bitu copy = cheight; Bitu rowsize=(cright-cleft); + 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;xtype>M_TEXT16) page=0xff; + if (CurMode->type!=M_TEXT) page=0xff; BIOS_NCOLS;BIOS_NROWS; if(rul>rlr) return; if(cul>clr) return; @@ -204,8 +227,7 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit while (start!=end) { start+=next; switch (CurMode->type) { - case M_TEXT2: - case M_TEXT16: + case M_TEXT: TEXT_CopyRow(cul,clr,start,start+nlines,base);break; case M_CGA2: CGA2_CopyRow(cul,clr,start,start+nlines,base);break; @@ -215,6 +237,8 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit TANDY16_CopyRow(cul,clr,start,start+nlines,base);break; case M_EGA16: 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); } @@ -229,8 +253,7 @@ filling: } for (;nlines>0;nlines--) { switch (CurMode->type) { - case M_TEXT2: - case M_TEXT16: + case M_TEXT: TEXT_FillRow(cul,clr,start,base,attr);break; case M_CGA2: CGA2_FillRow(cul,clr,start,base,attr);break; @@ -240,6 +263,8 @@ filling: TANDY16_FillRow(cul,clr,start,base,attr);break; case M_EGA16: 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); } @@ -273,6 +298,8 @@ void INT10_SetActivePage(Bit8u 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 (machine==MCH_TANDY) 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 */ @@ -283,7 +310,7 @@ void INT10_SetCursorShape(Bit8u first,Bit8u last) { } /* Check if we need to convert CGA Bios cursor values */ if (!(real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & 0x1)) { - if (CurMode->mode>0x3) goto dowrite; //Only mode 0-3 are text modes on cga +// 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 */ @@ -319,7 +346,6 @@ dowrite: IO_Write(base,0xb);IO_Write(base+1,last); } - void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page) { Bit16u address; @@ -357,14 +383,12 @@ void INT10_ReadCharAttr(Bit16u * result,Bit8u page) { *result=mem_readw(where); } - static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool useattr) { PhysPt fontdata; Bitu x,y; Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); switch (CurMode->type) { - case M_TEXT2: - case M_TEXT16: + case M_TEXT: { // Compute the address Bit16u address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); @@ -380,10 +404,10 @@ static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool case M_CGA4: case M_CGA2: case M_TANDY16: - if (chr<128) fontdata=Real2Phys(RealGetVec(0x43))+chr*cheight; //was plain 8 + if (chr<128) fontdata=Real2Phys(RealGetVec(0x43))+chr*cheight; else { chr-=128; - fontdata=Real2Phys(RealGetVec(0x1F))+(chr)*cheight; //was plain 8 + fontdata=Real2Phys(RealGetVec(0x1F))+(chr)*cheight; } break; default: @@ -391,26 +415,25 @@ static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool break; } x=8*col; - y=cheight*row; + y=cheight*row;Bit8u xor_mask=(CurMode->type == M_VGA) ? 0x0 : 0x80; //TODO Check for out of bounds for (Bit8u h=0;h>=1; } y++; } - } void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) { //TODO Check if this page thing is correct - if (CurMode->type>M_TEXT16) page=0xff; + if (CurMode->type!=M_TEXT) page=0xff; 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); @@ -432,7 +455,6 @@ void INT10_TeletypeOutputAttr(Bit8u chr,Bit8u attr,bool useattr) { BIOS_NCOLS;BIOS_NROWS; Bit8u cur_row=CURSOR_POS_ROW(page); Bit8u cur_col=CURSOR_POS_COL(page); - switch (chr) { case 7: //TODO BEEP @@ -472,14 +494,13 @@ void INT10_TeletypeOutputAttr(Bit8u chr,Bit8u attr,bool useattr) { INT10_SetCursorPos(cur_row,cur_col,page); } - void INT10_TeletypeOutput(Bit8u chr,Bit8u attr) { - INT10_TeletypeOutputAttr(chr,attr,CurMode->type>M_TEXT16); + 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) { //TODO Check if this page thing is correct - if (CurMode->type>M_TEXT16) page=0xff; + if (CurMode->type!=M_TEXT) page=0xff; if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); BIOS_NCOLS;BIOS_NROWS; @@ -491,7 +512,6 @@ void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,B row=cur_row; col=cur_col; } - INT10_SetCursorPos(row,col,page); while (count>0) { Bit8u chr=mem_readb(string); @@ -499,11 +519,11 @@ void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,B if (flag&2) { attr=mem_readb(string); string++; - } else attr=7; - INT10_TeletypeOutputAttr(chr,attr,flag & 2); + }; + INT10_TeletypeOutputAttr(chr,attr,true); count--; } - if (flag & 1) { + 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 ceb725f..2a78806 100644 --- a/src/ints/int10_memory.cpp +++ b/src/ints/int10_memory.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -80,8 +80,10 @@ void INT10_SetupRomMemory(void) { PhysPt rom_base=PhysMake(0xc000,0); Bitu i; int10.rom.used=3; // int10.rom.used=2; Size of ROM added - phys_writew(rom_base+0,0xaa55); - phys_writeb(rom_base+2,0x40); // Size of ROM: 64 512-blocks = 32KB + if (machine==MCH_VGA) { + phys_writew(rom_base+0,0xaa55); + phys_writeb(rom_base+2,0x40); // Size of ROM: 64 512-blocks = 32KB + } 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]); diff --git a/src/ints/int10_misc.cpp b/src/ints/int10_misc.cpp index 3afefc0..99f0e25 100644 --- a/src/ints/int10_misc.cpp +++ b/src/ints/int10_misc.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software @@ -91,10 +91,8 @@ void INT10_GetFuncStateInformation(PhysPt save) { mem_writeb(save+0x25,real_readb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX)); Bit16u col_count=0; switch (CurMode->type) { - case M_TEXT16: + case M_TEXT: col_count=16;break; - case M_TEXT2: - col_count=2;break; // ?? case M_CGA2: col_count=2;break; case M_CGA4: diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index 0f17c4e..0968678 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.cpp @@ -5,6 +5,7 @@ #include "inout.h" #include "int10.h" #include "mouse.h" +#include "vga.h" #define _EGA_HALF_CLOCK 0x0001 #define _EGA_LINE_DOUBLE 0x0002 @@ -13,41 +14,56 @@ #define GFX_REGS 0x09 #define ATT_REGS 0x15 -VideoModeBlock ModeList[]={ -/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde ,rate,special flags */ -{ 0x000 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK }, -{ 0x001 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK }, -{ 0x002 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 }, -{ 0x003 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 }, -{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0 }, -{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0}, -{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0 }, -{ 0x007 ,M_TEXT2 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 }, -/* 8,9,0xa are tandy modes */ -{ 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,100 ,449 ,80 ,400 ,60 ,0}, - -{ 0x00D ,M_EGA16 ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE }, -{ 0x00E ,M_EGA16 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,70 ,_EGA_LINE_DOUBLE }, -{ 0x00F ,M_EGA2 ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,400 ,70 ,0 }, -{ 0x010 ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,70 ,0 }, -{ 0x011 ,M_EGA2 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,449 ,80 ,480 ,70 ,0 }, -{ 0x012 ,M_EGA16 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,70 ,0 }, -{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x0000 ,100 ,449 ,80 ,400 ,70 ,0 }, +VideoModeBlock ModeList_VGA[]={ +/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */ +{ 0x000 ,M_TEXT ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, +{ 0x001 ,M_TEXT ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, +{ 0x002 ,M_TEXT ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, +{ 0x003 ,M_TEXT ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, +{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, +{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE}, +{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE }, +{ 0x007 ,M_TEXT ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, -{ 0x100 ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 ,0 }, -{ 0x101 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 ,0 }, -{ 0x103 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,70 ,0 }, +{ 0x00D ,M_EGA16 ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE }, +{ 0x00E ,M_EGA16 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE }, +{ 0x00F ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,400 ,0 },/*was EGA_2*/ +{ 0x010 ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 }, +{ 0x011 ,M_EGA16 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },/*was EGA_2 */ +{ 0x012 ,M_EGA16 ,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 ,0x0000 ,100 ,449 ,80 ,400 ,0 }, +{ 0x054 ,M_TEXT ,1056 ,688, 132,43, 8, 8, 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 }, +{ 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 }, +{ 0x103 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0 }, +{ 0x150 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _EGA_LINE_DOUBLE }, +{ 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _EGA_LINE_DOUBLE }, +{ 0x152 ,M_LIN8 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , 0 }, +{ 0x153 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , 0 }, -{ 0x150 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 , 0}, -{ 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 , 0}, -{ 0x152 ,M_LIN8 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 , 0 }, -{ 0x153 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 , 0 }, - -{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 ,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 ,40 ,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}, @@ -72,18 +88,10 @@ static Bit8u ega_palette[64][3]= {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f} }; -#if 0 -static Bit8u cga_palette[64][3]= { - {0x00,0x00,0x00}, {0x00,0x00,0x1f}, {0x00,0x1f,0x00}, {0x00,0x1f,0x1f}, {0x1f,0x00,0x00}, {0x1f,0x00,0x1f}, {0x1f,0x1f,0x00}, {0x1f,0x1f,0x1f}, - {0x0f,0x0f,0x0f}, {0x00,0x00,0x3f}, {0x00,0x3f,0x00}, {0x00,0x3f,0x3f}, {0x3f,0x00,0x00}, {0x3f,0x00,0x3f}, {0x3f,0x3f,0x00}, {0x3f,0x3f,0x3f}, -}; -#else 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}, }; -#endif - static Bit8u vga_palette[256][3]= { @@ -126,31 +134,208 @@ static Bit8u vga_palette[256][3]= VideoModeBlock * CurMode; -bool INT10_SetVideoMode(Bitu mode) { - - - bool clearmem=true; - Bit8u modeset_ctl,video_ctl,vga_switches; - - if (mode<256) { - if (mode & 128) { - clearmem=false; - mode-=128; - } - } else { - /* Check for special vesa mode bits */ - mode&=0xfff; - } - LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode); +static bool SetCurMode(VideoModeBlock modeblock[],Bitu mode) { Bitu i=0; - while (ModeList[i].mode!=0xffff) { - if (ModeList[i].mode==mode) goto foundmode; + while ( modeblock[i].mode!=0xffff) { + if ( modeblock[i].mode==mode) goto foundmode; i++; } - LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode); return false; foundmode: - CurMode=&ModeList[i]; + CurMode=&modeblock[i]; + return true; +} + + +static void FinishSetMode(bool clearmem) { + Bitu i; + /* Clear video memory if needs be */ + if (clearmem) { + switch (CurMode->type) { + case M_CGA4: + case M_CGA2: + for (i=0;i<16*1024;i++) { + real_writew(0xb800,i*2,0x0000); + } + break; + case M_TEXT: + if (CurMode->mode==7) for (i=0;i<16*1024;i++) { + real_writew(0xb000,i*2,0x0120); + } else for (i=0;i<16*1024;i++) { + real_writew(0xb800,i*2,0x0720); + } + break; + case M_EGA16: + case M_VGA: + case M_LIN8: + /* Hack we just acess the memory directly */ + memset(&vga.mem,0,sizeof(vga.mem)); + } + } + /* 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 ? 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 << 7))); + real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09); + 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 + if (machine==MCH_VGA) 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); + + // 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 MCH_TANDY: + 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: + if (mode!=7) return false; + 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; + switch(CurMode->type) { + case M_TEXT: + if (machine==MCH_HERC) scanline=14; + else scanline=8; + break; + case M_CGA2: + scanline=2; + case M_CGA4: + if (CurMode->mode!=0xa) scanline=2; + else scanline=4; + 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,0x1e,0x29, //4-7 + 0x2a,0x2b,0x3b //8-a + }; + Bit8u mode_control,color_select; + switch (machine) { + case MCH_HERC: + IO_WriteB(0x3bf,0x3); //Enable changing all bits + IO_WriteB(0x3b8,0x8); //TEXT mode and non-blinking characters + IO_WriteB(0x3bf,0x0); //Disable changing all bits + VGA_DAC_CombineColor(1,0xf); + 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); //block 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; + } + 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; + } + FinishSetMode(clearmem); + return true; +} + + +bool INT10_SetVideoMode(Bitu mode) { + bool clearmem=true;Bitu i; + if ((mode<256) && (mode & 128)) { + clearmem=false; + mode-=128; + } + LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode); + if (machine!=MCH_VGA) return INT10_SetVideoMode_OTHER(mode,clearmem); + Bit8u modeset_ctl,video_ctl,vga_switches; + if (!SetCurMode(ModeList_VGA,mode)){ + LOG(LOG_INT10,LOG_ERROR)("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); @@ -158,15 +343,11 @@ foundmode: modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); /* Setup the VGA to the correct mode */ - VGA_SetMode(CurMode->type); - + Bit16u crtc_base; - bool mono_mode=CurMode->type == M_TEXT2; - if (mono_mode) { - crtc_base=0x3b4; - } else { - crtc_base=0x3d4; - } + bool mono_mode=(mode == 7); + if (mono_mode) crtc_base=0x3b4; + else crtc_base=0x3d4; /* Setup MISC Output Register */ Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1); IO_Write(0x3c2,misc_output); //Setup for 3b4 or 3d4 @@ -178,8 +359,7 @@ foundmode: (CurMode->special & _EGA_HALF_CLOCK) ? 0x08 : 0x00; seq_data[4]|=0x02; //More than 64kb switch (CurMode->type) { - case M_TEXT2: - case M_TEXT16: + case M_TEXT: seq_data[2]|=0x3; //Enable plane 0 and 1 seq_data[4]|=0x05; //Alpanumeric and odd/even enabled break; @@ -223,28 +403,17 @@ foundmode: blank_end = (CurMode->htotal-2) & 0x7f; } IO_Write(crtc_base,0x03);IO_Write(crtc_base+1,0x80|(blank_end & 0x1f)); -// hor_overflow|=(blank_end & 0x40) >> 3; - /* Start Horizontal Retrace */ Bitu ret_start; - if (CurMode->special & _EGA_HALF_CLOCK) { - ret_start = (CurMode->hdispend+2); - } else { - ret_start = (CurMode->hdispend+4); - } + if (CurMode->special & _EGA_HALF_CLOCK) ret_start = (CurMode->hdispend+2); + 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) { - ret_end = (CurMode->htotal-2) & 0x3f; - } else { - ret_end = (CurMode->htotal-4) & 0x3f; - } + if (CurMode->special & _EGA_HALF_CLOCK) ret_end = (CurMode->htotal-2) & 0x3f; + else ret_end = (CurMode->htotal-4) & 0x3f; IO_Write(crtc_base,0x05);IO_Write(crtc_base+1,(ret_end & 0x1f) | (blank_end & 0x20) << 2); -// hor_overflow|=(ret_end & 0x20); -//TODO Be sure about these ending values in extended overflow of s3 - /* Vertical Total */ IO_Write(crtc_base,0x06);IO_Write(crtc_base+1,(CurMode->vtotal-2)); overflow|=((CurMode->vtotal-2) & 0x100) >> 8; @@ -277,7 +446,7 @@ foundmode: /* Vertical Retrace End */ IO_Write(crtc_base,0x16);IO_Write(crtc_base+1,(CurMode->vtotal-8)); /* Line Compare */ - Bitu line_compare=(mode>=256) ? 2047 : 1023; + 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; @@ -286,8 +455,7 @@ foundmode: /* Maximum scanline / Underline Location */ if (CurMode->special & _EGA_LINE_DOUBLE) max_scanline|=0x80; switch (CurMode->type) { - case M_TEXT2: - case M_TEXT16: + case M_TEXT: max_scanline|=CurMode->cheight-1; underline=0x1f; break; @@ -297,7 +465,9 @@ foundmode: break; case M_LIN8: underline=0x60; //Seems to enable the every 4th clock on my s3 -// if (CurMode->special & _VGA_LINE_DOUBLE) max_scanline|=1; + break; + case M_CGA4: + max_scanline|=1; break; } IO_Write(crtc_base,0x09);IO_Write(crtc_base+1,max_scanline); @@ -328,8 +498,7 @@ foundmode: case M_EGA16: mode_control=0xe3; break; - case M_TEXT2: - case M_TEXT16: + case M_TEXT: case M_VGA: mode_control=0xa3; break; @@ -342,34 +511,34 @@ foundmode: IO_Write(crtc_base,0x11); IO_Write(crtc_base+1,IO_Read(crtc_base+1)|0x80); /* Setup the correct clock */ - switch (CurMode->type) { - case M_VGA: - case M_TEXT2: - case M_TEXT16: - case M_EGA16: - //Stick to 25mhz clock for now - break; - default: + if (CurMode->mode>=0x100) { misc_output|=0xef; //Select clock 3 - Bitu clock=CurMode->vtotal*8*CurMode->htotal*CurMode->rate; + 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: + if (CurMode->swidth < 640) misc_control_2=0x0; //Use single pixel mode,M_VGA then + else misc_control_2=0x10; + break; + default: + misc_control_2=0x0; + break; + } + IO_WriteB(0x3d4,0x67);IO_WriteB(0x3d5,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_TEXT2: + case M_TEXT: gfx_data[0x5]|=0x10; //Odd-Even Mode - gfx_data[0x6]|=0x0a; //alphanumeric mode at 0xb000=0x7fff - break; - case M_TEXT16: - gfx_data[0x5]|=0x10; //Odd-Even Mode - gfx_data[0x6]|=0x0e; //alphanumeric mode at 0xb800=0xbfff + gfx_data[0x6]|=mono_mode ? 0x0a : 0x0e; //Either b800 or b000 break; case M_LIN8: case M_VGA: @@ -393,9 +562,10 @@ foundmode: Bit8u att_data[ATT_REGS]; memset(att_data,0,ATT_REGS); att_data[0x12]=0xf; //Always have all color planes enabled - /* Porgram Attribute Controller */ + /* Program Attribute Controller */ switch (CurMode->type) { case M_EGA16: + att_data[0x10]=0x01; //Color Graphics if (CurMode->mode>0xe) goto att_text16; for (i=0;i<8;i++) { att_data[i]=i; @@ -404,12 +574,9 @@ foundmode: break; case M_TANDY16: att_data[0x10]=0x01; //Color Graphics - for (i=0;i<16;i++) { - att_data[i]=i; - } + for (i=0;i<16;i++) att_data[i]=i; break; - case M_TEXT2: - case M_TEXT16: + case M_TEXT: 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 att_text16: @@ -417,30 +584,34 @@ att_text16: att_data[i]=i; att_data[i+8]=i+0x38; } + att_data[0x06]=0x14; //Odd Color 6 yellow/brown. break; case M_CGA2: - IO_Write(0x3d9,0x7); //Setup using CGA color select register - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x7); - goto skipatt; + att_data[0x10]=0x01; //Color Graphics + att_data[0]=0x0; + att_data[1]=0xf; + att_data[0x12]=0x1; //Only enable 1 plane + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x3f); + break; case M_CGA4: - IO_Write(0x3d9,0x30); //Setup using CGA color select register + att_data[0x10]=0x01; //Color Graphics + att_data[0]=0x0; + att_data[1]=0x3; + att_data[2]=0x5; + att_data[3]=0x7; real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30); - goto skipatt; + break; case M_VGA: case M_LIN8: - for (i=0;i<16;i++) { - att_data[i]=i; - } + 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); for (i=0;itype) { @@ -461,8 +632,7 @@ skipatt: IO_Write(0x3c9,cga_palette[i][2]); } break; - case M_TEXT2: - case M_TEXT16: + case M_TEXT: dac_text16: for (i=0;i<64;i++) { IO_Write(0x3c9,text_palette[i][0]); @@ -484,22 +654,16 @@ dac_text16: switch (CurMode->type) { case M_CGA2: feature=(feature&~0x30)|0x20; - IO_Write(0x3d8,0x12); //Setup using CGA color select register real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x12); break; case M_CGA4: feature=(feature&~0x30)|0x20; - IO_Write(0x3d8,0x2); //Setup using CGA color select register real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2); break; case M_TANDY16: feature=(feature&~0x30)|0x20; - IO_Write(0x3df,0x80); //Enter 32k mode and banks on 0 break; - case M_TEXT2: - feature=(feature&~0x30)|0x30; - break; - case M_TEXT16: + case M_TEXT: feature=(feature&~0x30)|0x20; break; case M_EGA16: @@ -523,72 +687,12 @@ dac_text16: 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 - + + FinishSetMode(clearmem); /* Load text mode font */ - if (CurMode->type<=M_TEXT16) { + if (CurMode->type==M_TEXT) { INT10_LoadFont(Real2Phys(int10.rom.font_16),true,256,0,0,16); } - /* Clear video memory if needs be */ - if (clearmem) { - switch (CurMode->type) { - case M_CGA4: - case M_CGA2: - for (i=0;i<16*1024;i++) { - real_writew(0xb800,i*2,0x0000); - } - break; - case M_TEXT2: - for (i=0;i<16*1024;i++) { - real_writew(0xb000,i*2,0x0120); - } - break; - case M_TEXT16: - for (i=0;i<16*1024;i++) { - real_writew(0xb800,i*2,0x0720); - } - break; - case M_EGA16: - case M_VGA: - case M_LIN8: - /* Just clear the whole 2 mb of memory */ - for (i=0;i<2*1024*1024/4;i++) { - mem_writed(S3_LFB_BASE+i*4,0); - } - } - } - /* Setup the BIOS */ - if (mode<128) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode); - else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,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,crtc_base); - 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 << 7))); - real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09); - 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); - - // Set cursor shape - if(CurMode->type<=M_TEXT16) { - 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(); return true; } diff --git a/src/ints/int10_pal.cpp b/src/ints/int10_pal.cpp index f39c793..44cdf0a 100644 --- a/src/ints/int10_pal.cpp +++ b/src/ints/int10_pal.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/ints/int10_put_pixel.cpp b/src/ints/int10_put_pixel.cpp index b44e359..13c5bfe 100644 --- a/src/ints/int10_put_pixel.cpp +++ b/src/ints/int10_put_pixel.cpp @@ -9,7 +9,7 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software diff --git a/src/ints/int10_vesa.cpp b/src/ints/int10_vesa.cpp index 8159f02..41fea05 100644 --- a/src/ints/int10_vesa.cpp +++ b/src/ints/int10_vesa.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.7 2004/01/11 09:27:52 harekiet Exp $ */ +/* $Id: int10_vesa.cpp,v 1.12 2004/09/10 22:09:54 harekiet Exp $ */ #include #include @@ -125,12 +125,12 @@ Bit8u VESA_GetSVGAModeInformation(Bit16u mode,Bit16u seg,Bit16u off) { Bitu i=0; if (mode<0x100) return 0x01; - while (ModeList[i].mode!=0xffff) { - if (mode==ModeList[i].mode) goto foundit; else i++; + while (ModeList_VGA[i].mode!=0xffff) { + if (mode==ModeList_VGA[i].mode) goto foundit; else i++; } return 0x01; foundit: - VideoModeBlock * mblock=&ModeList[i]; + VideoModeBlock * mblock=&ModeList_VGA[i]; switch (mblock->type) { case M_LIN8: //Linear 8-bit WLE(minfo.ModeAttributes,0x9b); @@ -161,7 +161,7 @@ foundit: Bit8u VESA_SetSVGAMode(Bit16u mode) { - if (INT10_SetVideoMode(mode)) return 0x00; + if (INT10_SetVideoMode(mode & 0xfff)) return 0x00; return 0x01; }; @@ -231,8 +231,8 @@ Bit8u VESA_ScanLineLength(Bit8u subcall,Bit16u & bytes,Bit16u & pixels,Bit16u & case 0x00: /* Set in pixels */ bytes=(pixels*bpp); case 0x02: /* Set in bytes */ - scan_len=bytes/4; - if (bytes % 4) scan_len++; + scan_len=bytes/8; + if (bytes % 8) scan_len++; vga.config.scan_len=scan_len; VGA_StartResize(); break; @@ -246,8 +246,8 @@ Bit8u VESA_ScanLineLength(Bit8u subcall,Bit16u & bytes,Bit16u & pixels,Bit16u & return 0x1; //Illegal call } /* Write the scan line to video card the simple way */ - pixels=(vga.config.scan_len*4)/bpp; - bytes=vga.config.scan_len*4; + pixels=(vga.config.scan_len*8)/bpp; + bytes=vga.config.scan_len*8; return 0x0; } @@ -299,7 +299,7 @@ Bit8u VESA_GetDisplayStart(Bit16u & x,Bit16u & y) { static Bitu SetWindowPositionHandler(void) { if (reg_bh) reg_ah=VESA_GetCPUWindow(reg_bl,reg_dx); - else reg_ah=VESA_SetCPUWindow(reg_bl,reg_dx); + else reg_ah=VESA_SetCPUWindow(reg_bl,(Bit8u)reg_dx); reg_al=0x4f; return 0; } @@ -310,9 +310,9 @@ void INT10_SetupVESA(void) { 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[i].mode!=0xffff) { - if (ModeList[i].mode>=0x100){ - phys_writew(PhysMake(0xc000,int10.rom.used),ModeList[i].mode); + while (ModeList_VGA[i].mode!=0xffff) { + if (ModeList_VGA[i].mode>=0x100){ + phys_writew(PhysMake(0xc000,int10.rom.used),ModeList_VGA[i].mode); int10.rom.used+=2; } i++; diff --git a/src/ints/mouse.cpp b/src/ints/mouse.cpp index d55a572..8e546d6 100644 --- a/src/ints/mouse.cpp +++ b/src/ints/mouse.cpp @@ -9,28 +9,37 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.31 2004/01/31 22:42:49 harekiet Exp $ */ +/* $Id: mouse.cpp,v 1.42 2004/08/04 09:12:56 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" -static Bitu call_int33,call_int74; +static Bitu call_int33,call_int74; +static Bit16u ps2cbseg,ps2cbofs; +static bool useps2callback; +static Bit16u call_ps2; +static RealPt ps2_callback; +static Bit16s oldmouseX, oldmouseY; // forward void WriteMouseIntVector(void); @@ -100,6 +109,8 @@ static struct { float mickeysPerPixel_y; float pixelPerMickey_x; float pixelPerMickey_y; + float senv_x; + float senv_y; Bit16u updateRegion_x[2]; Bit16u updateRegion_y[2]; Bit16u page; @@ -110,6 +121,56 @@ static struct { Bit16s oldshown; } mouse; +void Mouse_SetPS2State(bool use) { + if ((SegValue(es)!=0) && (reg_bx!=0)) useps2callback = use; + else useps2callback = false; + Mouse_AutoLock(useps2callback); +} + +void Mouse_ChangePS2Callback(Bit16u pseg, Bit16u pofs) { + if ((pseg==0) && (pofs==0)) useps2callback = false; + else useps2callback = true; + ps2cbseg = pseg; + ps2cbofs = pofs; + Mouse_AutoLock(useps2callback); +} + +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) { + reg_sp += 8; // remove the 4 words + return CBRET_NONE; +} + + #define X_MICKEY 8 #define Y_MICKEY 8 @@ -283,7 +344,7 @@ void DrawCursor() { // Get Clipping ranges // In Textmode ? - if (CurMode->type<=M_TEXT16) { + if (CurMode->type==M_TEXT) { DrawCursorText(); return; } @@ -344,19 +405,25 @@ void DrawCursor() { } void Mouse_CursorMoved(float x,float y) { - float dx = x * mouse.pixelPerMickey_x; float dy = y * mouse.pixelPerMickey_y; + if((fabs(x) > 1.0) || (mouse.senv_y < 1.0)) dx *= mouse.senv_x; + + if((fabs(y) > 1.0) || (mouse.senv_y < 1.0)) dy *= mouse.senv_y; + mouse.mickey_x += dx; mouse.mickey_y += dy; - mouse.x += dx; - if (mouse.x>mouse.max_x) mouse.x=mouse.max_x; - if (mouse.xmouse.max_y) mouse.y=mouse.max_y; - if (mouse.y 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_MOVED); DrawCursor(); } @@ -407,8 +474,8 @@ void Mouse_ButtonReleased(Bit8u button) { mouse.last_released_y[button]=POS_Y; } -static void SetMickeyPixelRate(Bit16s px, Bit16s py) -{ +static void SetMickeyPixelRate(Bit16s px, Bit16s py){ + if ((px!=0) && (py!=0)) { mouse.mickeysPerPixel_x = (float)px/X_MICKEY; mouse.mickeysPerPixel_y = (float)py/Y_MICKEY; @@ -416,6 +483,15 @@ static void SetMickeyPixelRate(Bit16s px, Bit16s py) mouse.pixelPerMickey_y = Y_MICKEY/(float)py; } }; +static void SetSensitivity(Bit16s px, Bit16s py){ + 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.0 +1.0/3.0; + mouse.senv_y=(static_cast(py)*py)/3600.0 +1.0/3.0; + } +}; + static void mouse_reset_hardware(void){ PIC_SetIRQMask(MOUSE_IRQ,false); @@ -425,13 +501,11 @@ void Mouse_NewVideoMode(void) { //Does way to much. Many of this stuff should be moved to mouse_reset one day WriteMouseIntVector(); -// real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74)); if(MOUSE_IRQ > 7) { real_writed(0,((0x70+MOUSE_IRQ-8)<<2),CALLBACK_RealPointer(call_int74)); } else { real_writed(0,((0x8+MOUSE_IRQ)<<2),CALLBACK_RealPointer(call_int74)); } - mouse.shown=-1; /* Get the correct resolution from the current video mode */ Bitu mode=mem_readb(BIOS_VIDEO_MODE); @@ -444,6 +518,9 @@ void Mouse_NewVideoMode(void) case 0x05: case 0x06: case 0x07: + case 0x08: + case 0x09: + case 0x0a: case 0x0d: case 0x0e: case 0x13: @@ -462,15 +539,15 @@ void Mouse_NewVideoMode(void) LOG(LOG_MOUSE,LOG_ERROR)("Unhandled videomode %X on reset",mode); break; } - mouse.max_x=639; - mouse.min_x=0; - mouse.min_y=0; + mouse.max_x = 639; + mouse.min_x = 0; + mouse.min_y = 0; // Dont set max coordinates here. it is done by SetResolution! - mouse.x=0; // civ wont work otherwise - mouse.y=static_cast(mouse.max_y/2); - mouse.events=0; - mouse.mickey_x=0; - mouse.mickey_y=0; + mouse.x = static_cast(mouse.max_x / 2); + mouse.y = static_cast(mouse.max_y / 2); + mouse.events = 0; + mouse.mickey_x = 0; + mouse.mickey_y = 0; mouse.hotx = 0; mouse.hoty = 0; @@ -491,6 +568,12 @@ void Mouse_NewVideoMode(void) mouse.oldshown=-1; SetMickeyPixelRate(8,16); + oldmouseX = static_cast(mouse.x); + + oldmouseY = static_cast(mouse.y); + + + } @@ -502,6 +585,10 @@ static void mouse_reset(void) { mouse.sub_mask=0; mouse.sub_seg=0; mouse.sub_ofs=0; + mouse.senv_x=1.0; + + mouse.senv_y=1.0; + //Added this for cd-v19 } @@ -526,7 +613,7 @@ static Bitu INT33_Handler(void) { break; case 0x02: /* Hide Mouse */ { - if (CurMode->type>M_TEXT16) RestoreCursorBackground(); + if (CurMode->type!=M_TEXT) RestoreCursorBackground(); else RestoreCursorBackgroundText(); mouse.shown--; } @@ -565,10 +652,11 @@ static Bitu INT33_Handler(void) { } 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 Bits 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;} - //if(max - min + 1 > 640) max = min + 640 - 1; mouse.min_x=min; mouse.max_x=max; LOG(LOG_MOUSE,LOG_NORMAL)("Define Hortizontal range min:%d max:%d",min,max); @@ -581,7 +669,6 @@ static Bitu INT33_Handler(void) { Bits 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;} - // if(static_cast(max - min + 1) > CurMode->sheight) max = min + CurMode->sheight - 1; mouse.min_y=min; mouse.max_y=max; LOG(LOG_MOUSE,LOG_NORMAL)("Define Vertical range min:%d max:%d",min,max); @@ -665,12 +752,19 @@ static Bitu INT33_Handler(void) { } break; case 0x1a: /* Set mouse sensitivity */ - SetMickeyPixelRate(reg_bx,reg_cx); + SetSensitivity(reg_bx,reg_cx); + + LOG(LOG_MOUSE,LOG_WARN)("Set sensitivity used with %d %d",reg_bx,reg_cx); + // ToDo : double mouse speed value break; case 0x1b: /* Get mouse sensitivity */ - reg_bx = Bit16s(X_MICKEY * mouse.mickeysPerPixel_x); - reg_cx = Bit16s(Y_MICKEY * mouse.mickeysPerPixel_y); + reg_bx = Bit16s((60.0* sqrt(mouse.senv_x- (1.0/3.0)) ) +1.0); + + reg_cx = Bit16s((60.0* sqrt(mouse.senv_y- (1.0/3.0)) ) +1.0); + + LOG(LOG_MOUSE,LOG_WARN)("Get sensitivity %d %d",reg_bx,reg_cx); + // ToDo : double mouse speed value reg_dx = 64; break; @@ -759,6 +853,8 @@ static Bitu INT74_Handler(void) { SegSet16(ds,oldds); SegSet16(es,oldes); SegSet16(ss,oldss); // Save segments } + DoPS2Callback(mouse.event_queue[mouse.events].buttons, POS_X, POS_Y); + } IO_Write(0xa0,0x20); IO_Write(0x20,0x20); @@ -780,7 +876,8 @@ void CreateMouseCallback(void) { // Create callback call_int33=CALLBACK_Allocate(); - CALLBACK_Setup(call_int33,&INT33_Handler,CB_IRET); + CALLBACK_Setup(call_int33,&INT33_Handler,CB_IRET,"Mouse"); + // Create a mouse vector with weird address // for strange mouse detection routines in Sim City & Wasteland Bit16u ofs = call_int33<<4; @@ -797,15 +894,17 @@ void MOUSE_Init(Section* sec) { // Callback 0x33 CreateMouseCallback(); - call_int74=CALLBACK_Allocate(); - CALLBACK_Setup(call_int74,&INT74_Handler,CB_IRET); + CALLBACK_Setup(call_int74,&INT74_Handler,CB_IRET,"int 74"); if(MOUSE_IRQ > 7) { real_writed(0,((0x70+MOUSE_IRQ-8)<<2),CALLBACK_RealPointer(call_int74)); } else { real_writed(0,((0x8+MOUSE_IRQ)<<2),CALLBACK_RealPointer(call_int74)); } - + useps2callback = false; + call_ps2=CALLBACK_Allocate(); + CALLBACK_Setup(call_ps2,&PS2_Handler,CB_IRET,"ps2 bios callback"); + ps2_callback=CALLBACK_RealPointer(call_ps2); memset(&mouse,0,sizeof(mouse)); mouse_reset_hardware(); mouse_reset(); diff --git a/src/ints/xms.cpp b/src/ints/xms.cpp index 7d43450..8ab5fc2 100644 --- a/src/ints/xms.cpp +++ b/src/ints/xms.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.31 2004/01/14 20:54:41 finsterr Exp $ */ +/* $Id: xms.cpp,v 1.33 2004/08/04 09:12:56 qbix79 Exp $ */ #include #include @@ -128,7 +128,7 @@ Bitu XMS_AllocateMemory(Bitu size, Bit16u& handle) } Bitu pages=(size/4) + ((size & 3) ? 1 : 0); MemHandle mem=MEM_AllocatePages(pages,true); - if (!mem) return XMS_OUT_OF_SPACE; + if ((!mem) && (size != 0)) return XMS_OUT_OF_SPACE; xms_handles[index].free=false; xms_handles[index].mem=mem; xms_handles[index].locked=0; @@ -305,11 +305,11 @@ Bitu XMS_Handler(void) { case XMS_LOCK_EXTENDED_MEMORY_BLOCK: { /* 0c */ Bit32u address; reg_bl = XMS_LockMemory(reg_dx, address); + reg_ax = (reg_bl==0); if (reg_bl==0) { // success reg_bx=(Bit16u)(address & 0xFFFF); reg_dx=(Bit16u)(address >> 16); }; - reg_ax = (reg_bl==0); }; break; case XMS_UNLOCK_EXTENDED_MEMORY_BLOCK: /* 0d */ reg_bl = XMS_UnlockMemory(reg_dx); @@ -350,8 +350,20 @@ void XMS_Init(Section* sec) { BIOS_ZeroExtendedSize(); DOS_AddMultiplexHandler(multiplex_xms); call_xms=CALLBACK_Allocate(); - CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF); + CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF, "XMS Handler"); xms_callback=CALLBACK_RealPointer(call_xms); + + /* Overide the callback with one that can be hooked */ + phys_writeb(CB_BASE+(call_xms<<4)+0,(Bit8u)0xeb); //jump near + phys_writeb(CB_BASE+(call_xms<<4)+1,(Bit8u)0x03); //offset + phys_writeb(CB_BASE+(call_xms<<4)+2,(Bit8u)0x90); //NOP + phys_writeb(CB_BASE+(call_xms<<4)+3,(Bit8u)0x90); //NOP + phys_writeb(CB_BASE+(call_xms<<4)+4,(Bit8u)0x90); //NOP + phys_writeb(CB_BASE+(call_xms<<4)+5,(Bit8u)0xFE); //GRP 4 + phys_writeb(CB_BASE+(call_xms<<4)+6,(Bit8u)0x38); //Extra Callback instruction + phys_writew(CB_BASE+(call_xms<<4)+7,call_xms); //The immediate word + phys_writeb(CB_BASE+(call_xms<<4)+9,(Bit8u)0xCB); //A RETF Instruction + for (i=0;icmdline->FindString("-lang",file_name)) { + if (control->cmdline->FindString("-lang",file_name,true)) { LoadMessageFile(file_name.c_str()); } else LoadMessageFile(section->Get_string("language")); } diff --git a/src/misc/programs.cpp b/src/misc/programs.cpp index 99fa6ea..c531e32 100644 --- a/src/misc/programs.cpp +++ b/src/misc/programs.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.12 2004/01/09 12:34:53 qbix79 Exp $ */ +/* $Id: programs.cpp,v 1.15 2004/09/16 21:47:39 qbix79 Exp $ */ #include #include @@ -65,7 +65,7 @@ static Bitu PROGRAMS_Handler(void) { PROGRAMS_Main * handler=0; //It will get sneakily itinialized Bitu size=sizeof(PROGRAMS_Main *); /* Read the handler from program code in memory */ - PhysPt reader=PhysMake(dos.psp,256+sizeof(exe_block)); + PhysPt reader=PhysMake(dos.psp(),256+sizeof(exe_block)); HostPt writer=(HostPt)&handler; for (;size>0;size--) *writer++=mem_readb(reader++); Program * new_program; @@ -81,13 +81,13 @@ static Bitu PROGRAMS_Handler(void) { Program::Program() { /* Find the command line and setup the PSP */ - psp = new DOS_PSP(dos.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); + 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]; @@ -96,11 +96,11 @@ Program::Program() { } void Program::WriteOut(const char * format,...) { - char buf[1024]; + char buf[2048]; va_list msg; va_start(msg,format); - vsprintf(buf,format,msg); + vsnprintf(buf,2047,format,msg); va_end(msg); Bit16u size=strlen(buf); diff --git a/src/misc/setup.cpp b/src/misc/setup.cpp index 45b81f7..254b2eb 100644 --- a/src/misc/setup.cpp +++ b/src/misc/setup.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.19 2004/01/29 09:26:52 qbix79 Exp $ */ +/* $Id: setup.cpp,v 1.22 2004/08/04 09:12:56 qbix79 Exp $ */ #include "dosbox.h" #include "cross.h" @@ -46,8 +46,9 @@ void Prop_string::SetValue(char* input){ } void Prop_bool::SetValue(char* input){ - input=trim(input); - if((input[0]=='0') ||(input[0]=='D')||( (input[0]=='O') && (input[0]=='F'))||(input[0]=='f')){ + input=lowcase(trim(input)); + /* valid false entries: 0 ,d*, of* ,f* everything else gets true */ + if((input[0]=='0') || (input[0]=='d') || ( (input[0]=='o') && (input[1]=='f')) || (input[0]=='f')){ __value._bool=false; }else{ __value._bool=true; @@ -385,6 +386,7 @@ bool CommandLine::FindStringBegin(char * begin,std::string & value, bool remove) for (it=cmds.begin();it!=cmds.end();it++) { if (strncmp(begin,(*it).c_str(),strlen(begin))==0) { value=((*it).c_str()+strlen(begin)); + if (remove) cmds.erase(it); return true; } } diff --git a/src/misc/support.cpp b/src/misc/support.cpp index 7be9568..e1c23ab 100644 --- a/src/misc/support.cpp +++ b/src/misc/support.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.cpp,v 1.21 2004/01/10 14:03:35 qbix79 Exp $ */ +/* $Id: support.cpp,v 1.25 2004/08/04 09:12:56 qbix79 Exp $ */ #include #include @@ -47,41 +47,21 @@ void strreplace(char * str,char o,char 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; + while (*str && (*str==' ' || *str=='\t')) str++; + return str; } -/* - * 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 *rtrim(char *str) { char *p; - - assert(str); - p = strchr(str, '\0'); while (--p >= str && isspace(*p)); p[1] = '\0'; + return str; } -/* - * Combines ltrim() & rtrim() - */ char *trim(char *str) { - assert(str); - rtrim(str); - return ltrim(str); + return ltrim(rtrim(str)); } @@ -90,7 +70,7 @@ bool ScanCMDBool(char * cmd,char * 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]=='/' || scan[c_len]==0)) { + 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); @@ -100,63 +80,70 @@ bool ScanCMDBool(char * cmd,char * check) { 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++; + while (*scan!=' ' && *scan!='\t' && *scan!=0) scan++; *scan=0; return found; } else return 0; } -char * StripWord(char * cmd) { +char * StripWord(char *&line) { bool quoted=false; - char * begin=cmd; - if (*cmd=='"') { - quoted=true; - cmd++; + 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 * end; - if (quoted) { - end=strchr(cmd,'"'); - } else { - end=strchr(cmd,' '); + char * begin=scan; + for (;char c=*scan;scan++) { + if (c==' ' || c=='\t') { + *scan++=0; + break; + } } - if (!end) { - return cmd+strlen(cmd); - } - *end=0; - if (quoted) { - memmove(begin,cmd,end-begin+1); - } - return trim(cmd+strlen(begin)+1); + 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(*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(char * format,...) { #if C_DEBUG && C_HEAVY_DEBUG diff --git a/src/platform/visualc/config.h b/src/platform/visualc/config.h index 42aeeeb..bf95d64 100644 --- a/src/platform/visualc/config.h +++ b/src/platform/visualc/config.h @@ -1,6 +1,7 @@ #define INLINE __forceinline -#define VERSION "0.60" +#define VERSION "0.62" + /* Define to 1 to enable internal debugger, requires libcurses */ #define C_DEBUG 1 @@ -14,6 +15,9 @@ /* 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 @@ -35,4 +39,24 @@ /* 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 */ + +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; + diff --git a/src/shell/shell.cpp b/src/shell/shell.cpp index 24dfbf6..1677a4a 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.39 2004/02/03 08:35:29 qbix79 Exp $ */ +/* $Id: shell.cpp,v 1.49 2004/09/28 15:31:21 qbix79 Exp $ */ #include #include @@ -47,7 +47,7 @@ void SHELL_AddAutoexec(char * line,...) { size_t auto_len=strlen(autoexec_data); if ((auto_len+strlen(line)+3)>AUTOEXEC_SIZE) { - E_Exit("SYSTEM:Autoexec.bat file overlow"); + E_Exit("SYSTEM:Autoexec.bat file overflow"); } sprintf((autoexec_data+auto_len),"%s\r\n",buf); } @@ -108,7 +108,7 @@ Bitu DOS_Shell::GetRedirection(char *s, char **ifn, char **ofn,bool * append) { } 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); @@ -138,7 +138,6 @@ void DOS_Shell::ParseLine(char * line) { free(out); } #endif - DoCommand(line); } @@ -167,7 +166,6 @@ void DOS_Shell::RunInternal(void) void DOS_Shell::Run(void) { char input_line[CMD_MAXLINE]; std::string line; - if (cmd->FindStringRemain("/C",line)) { strcpy(input_line,line.c_str()); DOS_Shell temp; @@ -188,7 +186,7 @@ void DOS_Shell::Run(void) { if(bf->ReadLine(input_line)) { if (echo) { if (input_line[0]!='@') { - ShowPrompt(); + ShowPrompt(); WriteOut(input_line); WriteOut("\n"); }; @@ -244,7 +242,15 @@ void AUTOEXEC_Init(Section * sec) { if (access(buffer,F_OK)) goto nomount; SHELL_AddAutoexec("MOUNT C \"%s\"",buffer); SHELL_AddAutoexec("C:"); - SHELL_AddAutoexec(name); + upcase(name); + if(strstr(name,".BAT")==0) { + SHELL_AddAutoexec(name); + } else { + char call[CROSS_LEN] = { 0 }; + strcpy(call,"CALL "); + strcat(call,name); + SHELL_AddAutoexec(call); + } if(addexit) SHELL_AddAutoexec("exit"); } } @@ -259,17 +265,17 @@ static char * init_line="/INIT AUTOEXEC.BAT"; void SHELL_Init() { /* Add messages */ - MSG_Add("SHELL_ILLEGAL_PATH","Illegal Path\n"); + MSG_Add("SHELL_ILLEGAL_PATH","Illegal Path.\n"); MSG_Add("SHELL_CMD_HELP","supported commands are:\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_CMD_CHDIR_ERROR","Unable to change to: %s\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_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_CMD_CHDIR_ERROR","Unable to change to: %s.\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_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"); @@ -279,9 +285,9 @@ void SHELL_Init() { 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!\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 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"); @@ -290,37 +296,51 @@ void SHELL_Init() { 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","DOSBox Shell v" VERSION "\n" - "This version runs some protected mode games!\n" - "For supported shell commands type: HELP\n" - "For a short introduction type: INTRO\n\n" - "If you want more speed, try ctrl-F8 and ctrl-F12.\n" - "For more information read the README file in DOSBox directory.\n" - "\nHAVE FUN!\nThe DOSBox Team\n\n" + MSG_Add("SHELL_STARTUP", + "\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[32mDOSBox Shell v" VERSION "\033[37m \xBA\n" + "\xBA DOSBox runs real and protected mode games. \xBA\n" + "\xBA For supported shell commands type: \033[1;33mHELP\033[37m \xBA\n" + "\xBA For a short introduction type: \033[33mINTRO\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" + "\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","Change 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_RMDIR_HELP","Remove Directory.\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_TYPE_HELP","Display the contents of a text-file.\n"); - MSG_Add("SHELL_CMD_REM_HELP","Add comments in a batch file.\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_RMDIR_HELP","Remove Directory.\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_TYPE_HELP","Display the contents of a text-file.\n"); + MSG_Add("SHELL_CMD_REM_HELP","Add comments in a batch file.\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 files.\n"); MSG_Add("SHELL_CMD_DELETE_HELP","Removes 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_SUBST_HELP","Assign an internal directory to a drive.\n"); MSG_Add("SHELL_CMD_LOADHIGH_HELP","Run a program. For batch file compatibility only.\n"); + MSG_Add("SHELL_CMD_CHOICE_HELP","Waits for a keypress and sets ERRORLEVEL.\n"); + MSG_Add("SHELL_CMD_ATTRIB_HELP","Does nothing. Provided for compatibility.\n"); - /* Regular startup */ + /* 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); @@ -368,8 +388,9 @@ void SHELL_Init() { strcpy(tail.buffer,init_line); MEM_BlockWrite(PhysMake(psp_seg,128),&tail,128); /* Setup internal DOS Variables */ - dos.dta=psp.GetDTA(); - dos.psp=psp_seg; + + dos.dta(RealMake(psp_seg,0x80)); + dos.psp(psp_seg); Program * new_program; SHELL_ProgramStart(&new_program); diff --git a/src/shell/shell_batch.cpp b/src/shell/shell_batch.cpp index 4642a2b..c1742d7 100644 --- a/src/shell/shell_batch.cpp +++ b/src/shell/shell_batch.cpp @@ -9,13 +9,15 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.14 2004/08/04 09:12:57 qbix79 Exp $ */ + #include #include diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index 2de9dfc..545963d 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -9,16 +9,17 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.37 2004/01/10 14:03:36 qbix79 Exp $ */ +/* $Id: shell_cmds.cpp,v 1.47 2004/09/18 10:20:54 qbix79 Exp $ */ #include +#include #include "shell.h" #include "callback.h" @@ -36,7 +37,7 @@ static SHELL_Cmd cmd_list[]={ { "ERASE", 1, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"}, { "ECHO", 0, &DOS_Shell::CMD_ECHO, "SHELL_CMD_ECHO_HELP"}, { "EXIT", 0, &DOS_Shell::CMD_EXIT, "SHELL_CMD_EXIT_HELP"}, -{ "HELP", 0, &DOS_Shell::CMD_HELP, "SHELL_CMD_HELP_HELP"}, +{ "HELP", 1, &DOS_Shell::CMD_HELP, "SHELL_CMD_HELP_HELP"}, { "MKDIR", 0, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP"}, { "MD", 1, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP"}, { "RMDIR", 0, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP"}, @@ -53,13 +54,15 @@ static SHELL_Cmd cmd_list[]={ { "SUBST", 0, &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", 0, &DOS_Shell::CMD_ATTRIB, "SHELL_CMD_ATTRIB_HELP"}, {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[CMD_MAXLINE]; char * cmd_write=cmd; while (*line) { if (*line==32) break; @@ -121,7 +124,7 @@ void DOS_Shell::CMD_DELETE(char * args) { //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); + DOS_DTA dta(dos.dta()); while (res) { dta.GetResult(name,size,date,time,attr); if (!(attr & (DOS_ATTR_DIRECTORY|DOS_ATTR_READ_ONLY))) { @@ -147,8 +150,8 @@ void DOS_Shell::CMD_RENAME(char * args){ StripSpaces(args); if(!*args) {SyntaxError();return;} if((strchr(args,'*')!=NULL) || (strchr(args,'?')!=NULL) ) { WriteOut(MSG_Get("SHELL_CMD_NO_WILD"));return;} - char * arg2 =StripWord(args); - DOS_Rename(args,arg2); + char * arg1=StripWord(args); + DOS_Rename(arg1,args); } void DOS_Shell::CMD_ECHO(char * args){ @@ -185,13 +188,9 @@ void DOS_Shell::CMD_CHDIR(char * args) { char dir[DOS_PATHLENGTH]; DOS_GetCurrentDir(0,dir); WriteOut("%c:\\%s\n",drive,dir); + } else if (!DOS_ChangeDir(args)) { + WriteOut(MSG_Get("SHELL_CMD_CHDIR_ERROR"),args); } - if (DOS_ChangeDir(args)) { - - } else { - WriteOut(MSG_Get("SHELL_CMD_CHDIR_ERROR"),args); - } - }; void DOS_Shell::CMD_MKDIR(char * args) { @@ -240,9 +239,18 @@ void DOS_Shell::CMD_DIR(char * args) { 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"); bool optS=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); @@ -290,17 +298,20 @@ void DOS_Shell::CMD_DIR(char * args) { *(strrchr(path,'\\')+1)=0; WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),path); - DOS_DTA dta(dos.dta); + 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); return; } - while (ret) { -/* File name and extension */ + + 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=""; if (!optW && (name[0] != '.')) { ext = strrchr(name, '.'); @@ -335,13 +346,12 @@ void DOS_Shell::CMD_DIR(char * args) { if (optW) { w_count++; } - ret=DOS_FindNext(); if(optP) { if(!(++p_count%(22*w_size))) { CMD_PAUSE(args); } } - } + } while ( (ret=DOS_FindNext()) ); if (optW) { if (w_count%5) WriteOut("\n"); } @@ -362,19 +372,26 @@ void DOS_Shell::CMD_DIR(char * args) { } void DOS_Shell::CMD_COPY(char * args) { + static char defaulttarget[] = "."; StripSpaces(args); - DOS_DTA dta(dos.dta); + DOS_DTA dta(dos.dta()); Bit32u size;Bit16u date;Bit16u time;Bit8u attr; char name[DOS_NAMELENGTH_ASCII]; + // ignore /b and /t switches: always copy binary + ScanCMDBool(args,"B"); + ScanCMDBool(args,"T"); + char * rem=ScanCMDRemain(args); if (rem) { WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); return; } // source/target - char* source = args; - char* target = StripWord(source); + char* source = StripWord(args); + char* target = NULL; + if (args && *args) target = StripWord(args); + if (!target || !*target) target = defaulttarget; // Target and Source have to be there if (!source || !strlen(source)) { @@ -410,7 +427,7 @@ void DOS_Shell::CMD_COPY(char * args) { } }; - bool ret=DOS_FindFirst(args,0xffff & ~DOS_ATTR_VOLUME); + bool ret=DOS_FindFirst(source,0xffff & ~DOS_ATTR_VOLUME); if (!ret) { WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args); return; @@ -491,26 +508,23 @@ void DOS_Shell::CMD_IF(char * args) { *comp++=' '; *comp++=' '; }; - char * word; - word=args; - args=StripWord(word); + char * word=StripWord(args); if (strcasecmp(word,"NOT")==0) { - word=args; + word=StripWord(args); has_not=true; - args=StripWord(word); } if (strcasecmp(word,"EXIST")==0) { - word=args;args=StripWord(word); + word=StripWord(args); if (!*word) { WriteOut(MSG_Get("SHELL_CMD_IF_EXIST_MISSING_FILENAME")); return; }; - if (DOS_FindFirst(word,0xFFFF)==(!has_not)) DoCommand(args); + if (DOS_FindFirst(word,0xffff & ~DOS_ATTR_VOLUME)==(!has_not)) DoCommand(args); return; } if (strcasecmp(word,"ERRORLEVEL")==0) { - word=args;args=StripWord(word); + word=StripWord(args); if(!isdigit(*word)) { WriteOut(MSG_Get("SHELL_CMD_IF_ERRORLEVEL_MISSING_NUMBER")); return; @@ -529,8 +543,7 @@ void DOS_Shell::CMD_IF(char * args) { } /* Normal if string compare */ if (!*args) { SyntaxError();return;}; - char * word2=args; - args=StripWord(word2); + char * word2=StripWord(args); if ((strcmp(word,word2)==0)==(!has_not)) DoCommand(args); } @@ -558,8 +571,7 @@ void DOS_Shell::CMD_TYPE(char * args) { Bit16u handle; char * word; nextfile: - word=args; - args=StripWord(word); + word=StripWord(args); if (!DOS_OpenFile(word,0,&handle)) { WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),word); return; @@ -583,7 +595,6 @@ void DOS_Shell::CMD_PAUSE(char * args){ DOS_ReadFile (STDIN,&c,&n); } - void DOS_Shell::CMD_CALL(char * args){ this->call=true; /* else the old batchfile will be closed first */ this->ParseLine(args); @@ -620,11 +631,13 @@ void DOS_Shell::CMD_SUBST (char * args) { if( ( ldp=dynamic_cast(Drives[drive])) == 0 ) throw 0; char newname[CROSS_LEN]; - strcpy(newname, ldp->basedir); + 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){ @@ -635,10 +648,56 @@ void DOS_Shell::CMD_SUBST (char * args) { } return; } - + catch(...) { //dynamic cast failed =>so no localdrive + WriteOut(MSG_Get("SHELL_CMD_SUBST_FAILURE")); + return; + } + return; } void DOS_Shell::CMD_LOADHIGH(char *args){ this->ParseLine(args); } + +void DOS_Shell::CMD_CHOICE(char * args){ + static char defargs[] = "[YN]"; + static char defchoice[] = "yn"; + char *rem = NULL, *ptr; + bool optN = false; + if (args) { + char *last = strchr(args,0); + StripSpaces(args); + optN=ScanCMDBool(args,"N"); + rem=ScanCMDRemain(args); + if (rem && *rem && (tolower(rem[1]) != 'c' || rem[2] != ':')) { + WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); + return; + } + if (args == rem) args = strchr(rem,0)+1; + if (rem) rem += 3; + if (args > last) args = NULL; + } + if (!args || !*args) args = defargs; + if (!rem || !*rem) rem = defchoice; + ptr = rem; + Bit8u c; + while ((c = *ptr)) *ptr++ = tolower(c); + + WriteOut(args); + if (!optN) WriteOut("\r\n"); + Bit16u n=1; + do { + DOS_ReadFile (STDIN,&c,&n); + } while (!c || !(ptr = strchr(rem,tolower(c)))); + if (optN) { + DOS_WriteFile (STDOUT,&c, &n); + WriteOut("\r\n"); + } + dos.return_code = ptr-rem+1; +} + +void DOS_Shell::CMD_ATTRIB(char *args){ + // No-Op for now. +} + diff --git a/src/shell/shell_misc.cpp b/src/shell/shell_misc.cpp index 7490986..ddd79ae 100644 --- a/src/shell/shell_misc.cpp +++ b/src/shell/shell_misc.cpp @@ -9,14 +9,14 @@ * This program is distributed in the hope that 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. + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public 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.28 2004/01/10 14:03:36 qbix79 Exp $ */ +/* $Id: shell_misc.cpp,v 1.32 2004/09/08 18:58:48 qbix79 Exp $ */ #include #include @@ -42,7 +42,7 @@ static void outs(char * str) { } void DOS_Shell::InputCommand(char * line) { - Bitu size=CMD_MAXLINE-1; + Bitu size=CMD_MAXLINE-2; //lastcharacter+0 Bit8u c;Bit16u n=1; Bitu str_len=0;Bitu str_index=0; Bit16u len; @@ -52,7 +52,7 @@ void DOS_Shell::InputCommand(char * line) { std::list::iterator it_history = l_history.begin(), it_completion = l_completion.begin(); while (size) { - dos.echo=false; + dos.echo=false; DOS_ReadFile(input_handle,&c,&n); if (!n) { size=0; //Kill the while loop @@ -74,7 +74,7 @@ void DOS_Shell::InputCommand(char * line) { DOS_WriteFile(STDOUT,&c,&n); } str_len = str_index = it_history->length(); - size = CMD_MAXLINE - str_index - 1; + size = CMD_MAXLINE - str_index - 2; } break; @@ -101,7 +101,7 @@ void DOS_Shell::InputCommand(char * line) { strcpy(line, it_history->c_str()); len = it_history->length(); str_len = str_index = len; - size = CMD_MAXLINE - str_index - 1; + size = CMD_MAXLINE - str_index - 2; DOS_WriteFile(STDOUT, (Bit8u *)line, &len); it_history ++; @@ -125,7 +125,7 @@ void DOS_Shell::InputCommand(char * line) { strcpy(line, it_history->c_str()); len = it_history->length(); str_len = str_index = len; - size = CMD_MAXLINE - str_index - 1; + size = CMD_MAXLINE - str_index - 2; DOS_WriteFile(STDOUT, (Bit8u *)line, &len); it_history ++; @@ -140,6 +140,7 @@ void DOS_Shell::InputCommand(char * line) { if (str_index) { outc(8); Bit32u str_remain=str_len - str_index; + size++; if (str_remain) { memmove(&line[str_index-1],&line[str_index],str_remain); line[--str_len]=0; @@ -183,6 +184,10 @@ void DOS_Shell::InputCommand(char * line) { completion_index = 0; } + char *path; + if ((path = strrchr(line+completion_index,'\\'))) completion_index = path-line+1; + if ((path = strrchr(line+completion_index,'/'))) completion_index = path-line+1; + // build the completion list char mask[DOS_PATHLENGTH]; if (completion_start) { @@ -196,7 +201,7 @@ void DOS_Shell::InputCommand(char * line) { bool res = DOS_FindFirst(mask, 0xffff & ~DOS_ATTR_VOLUME); if (!res) break; // TODO: beep - DOS_DTA dta(dos.dta); + DOS_DTA dta(dos.dta()); char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr; while (res) { @@ -228,7 +233,7 @@ void DOS_Shell::InputCommand(char * line) { strcpy(&line[completion_index], it_completion->c_str()); len = it_completion->length(); str_len = str_index = completion_index + len; - size = CMD_MAXLINE - str_index - 1; + size = CMD_MAXLINE - str_index - 2; DOS_WriteFile(STDOUT, (Bit8u *)it_completion->c_str(), &len); } } @@ -247,9 +252,12 @@ void DOS_Shell::InputCommand(char * line) { if (l_completion.size()) l_completion.clear(); line[str_index]=c; str_index ++; - if (str_index > str_len) line[str_index] = '\0'; - str_len++;//This should depend on insert being active - size--; + if (str_index > str_len){ + line[str_index] = '\0'; + str_len++;//This should depend on insert being active + size--; + } + DOS_WriteFile(STDOUT,&c,&n); break; } @@ -265,7 +273,7 @@ void DOS_Shell::InputCommand(char * line) { void DOS_Shell::Execute(char * name,char * args) { char * fullname; - char line[255]; + char line[CMD_MAXLINE]; if(strlen(args)!= 0){ if(*args != ' '){ //put a space in front line[0]=' ';line[1]=0; @@ -369,10 +377,10 @@ void DOS_Shell::Execute(char * name,char * args) { MEM_BlockWrite(SegPhys(ss)+reg_sp+0x100,&cmd,128); /* Parse FCB (first two parameters) and put them into the current DOS_PSP */ Bit8u add; - FCB_Parsename(dos.psp,0x5C,0x00,cmd.buffer,&add); - FCB_Parsename(dos.psp,0x6C,0x00,&cmd.buffer[add],&add); - block.exec.fcb1=RealMake(dos.psp,0x5C); - block.exec.fcb2=RealMake(dos.psp,0x6C); + FCB_Parsename(dos.psp(),0x5C,0x00,cmd.buffer,&add); + FCB_Parsename(dos.psp(),0x6C,0x00,&cmd.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(); @@ -409,11 +417,14 @@ void DOS_Shell::Execute(char * name,char * args) { static char * bat_ext=".BAT"; static char * com_ext=".COM"; static char * exe_ext=".EXE"; -static char which_ret[DOS_PATHLENGTH]; +static char which_ret[DOS_PATHLENGTH+4]; char * DOS_Shell::Which(char * name) { + if(strlen(name) >= 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); @@ -453,6 +464,9 @@ char * DOS_Shell::Which(char * name) { if(Bitu len=strlen(path)){ if(path[strlen(path)-1]!='\\') strcat(path,"\\"); strcat(path,name); + //If name too long =>next + if(strlen(path) >= DOS_PATHLENGTH) continue; + strcpy(which_ret,path); if (DOS_FileExists(which_ret)) return which_ret; strcpy(which_ret,path); diff --git a/visualc_net/dosbox.vcproj b/visualc_net/dosbox.vcproj index 5d30ae3..f397a0f 100644 --- a/visualc_net/dosbox.vcproj +++ b/visualc_net/dosbox.vcproj @@ -25,6 +25,7 @@ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" BasicRuntimeChecks="3" RuntimeLibrary="3" + RuntimeTypeInfo="TRUE" PrecompiledHeaderFile=".\Debug/dosbox.pch" AssemblerListingLocation=".\Debug/" ObjectFile=".\Debug/" @@ -97,6 +98,7 @@ RuntimeLibrary="2" BufferSecurityCheck="FALSE" EnableFunctionLevelLinking="TRUE" + RuntimeTypeInfo="TRUE" PrecompiledHeaderFile=".\Release/dosbox.pch" AssemblerOutput="4" AssemblerListingLocation=".\Release/" @@ -171,6 +173,9 @@ + + @@ -305,6 +310,9 @@ + + @@ -344,12 +352,18 @@ + + + + @@ -390,6 +404,9 @@ + + @@ -402,6 +419,12 @@ + + + + @@ -453,9 +476,15 @@ + + + + + + + + + + + + - - - - - - - - - -