sync to dosbox r3778

This commit is contained in:
dborth 2012-02-09 02:35:43 +00:00
parent 033d4e91e4
commit ccd97a1f39
63 changed files with 1043 additions and 393 deletions

106
README
View File

@ -220,11 +220,11 @@ CD-ROM: My CD-ROM doesn't work.
To enable SDL-support (does not include low-level CD access!): To enable SDL-support (does not include low-level CD access!):
- mount d f:\ -t cdrom -usecd 0 -noioctl - mount d f:\ -t cdrom -usecd 0 -noioctl
To enable ioctl access using digital audio extraction for CD audio To enable ioctl access using digital audio extraction for CD audio
(windows-only, useful for Vista): (Windows-only, useful for Vista):
- mount d f:\ -t cdrom -ioctl_dx - mount d f:\ -t cdrom -ioctl_dx
To enable ioctl access using MCI for CD audio (windows-only): To enable ioctl access using MCI for CD audio (Windows-only):
- mount d f:\ -t cdrom -ioctl_mci - mount d f:\ -t cdrom -ioctl_mci
To force ioctl-only access (windows-only): To force ioctl-only access (Windows-only):
- mount d f:\ -t cdrom -ioctl_dio - mount d f:\ -t cdrom -ioctl_dio
To enable low-level aspi-support (win98 with aspi-layer installed): To enable low-level aspi-support (win98 with aspi-layer installed):
- mount d f:\ -t cdrom -aspi - mount d f:\ -t cdrom -aspi
@ -265,7 +265,7 @@ SOUND: There is no sound.
Be sure that the sound is correctly configured in the game. This might be Be sure that the sound is correctly configured in the game. This might be
done during the installation or with a setup/setsound utility that done during the installation or with a setup/setsound utility that
accompanies the game. First see if an autodetection option is provided. If accompanies the game. First see if an autodetection option is provided. If
there is none try selecting Soundblaster or Soundblaster 16 with the default there is none try selecting SoundBlaster or SoundBlaster 16 with the default
settings being "address=220 irq=7 dma=1" (sometimes highdma=5). You might settings being "address=220 irq=7 dma=1" (sometimes highdma=5). You might
also want to select Sound Canvas/SCC/MPU-401/General MIDI/Wave Blaster also want to select Sound Canvas/SCC/MPU-401/General MIDI/Wave Blaster
at "address=330 IRQ=2" as music device. at "address=330 IRQ=2" as music device.
@ -275,8 +275,8 @@ SOUND: There is no sound.
configuration and use some lower fixed cycles value (like cycles=2000). Also configuration and use some lower fixed cycles value (like cycles=2000). Also
assure that your host operating sound does provide sound. assure that your host operating sound does provide sound.
In certain cases it might be useful to use a different emulated sound device In certain cases it might be useful to use a different emulated sound device
like a soundblaster pro (sbtype=sbpro1 in the DOSBox configuration file) or like a SoundBlaster Pro (sbtype=sbpro1 in the DOSBox configuration file) or
the gravis ultrasound (gus=true). the Gravis Ultrasound (gus=true).
SOUND: What sound hardware does DOSBox presently emulate? SOUND: What sound hardware does DOSBox presently emulate?
@ -286,21 +286,21 @@ SOUND: What sound hardware does DOSBox presently emulate?
digital sound output through the internal speaker. digital sound output through the internal speaker.
- Creative CMS/Gameblaster - Creative CMS/Gameblaster
The is the first card released by Creative Labs(R). The default The is the first card released by Creative Labs(R). The default
configuration places it on address 220. It is disabled as default. configuration places it on address 220. It is disabled by default.
- Tandy 3 voice - Tandy 3 voice
The emulation of this sound hardware is complete with the exception of The emulation of this sound hardware is complete with the exception of
the noise channel. The noise channel is not very well documented and as the noise channel. The noise channel is not very well documented and as
such is only a best guess as to the sound's accuracy. It is disabled as such is only a best guess as to the sound's accuracy. It is disabled as
default. default.
- Tandy DAC - Tandy DAC
Some games may require turning off sound blaster emulation (sbtype=none) Some games may require turning off SoundBlaster emulation (sbtype=none)
for better tandy DAC sound support. Don't forget to set the sbtype back to for better Tandy DAC sound support. Don't forget to set the sbtype back to
sb16 if you don't use tandy sound. sb16 if you don't use Tandy sound.
- Adlib - Adlib
This emulation is almost perfect and includes the Adlib's ability to This emulation is almost perfect and includes the Adlib's ability to
almost play digitized sound. Placed at address 220 (also on 388). almost play digitized sound. Placed at address 220 (also on 388).
- SoundBlaster 16 / SoundBlaster Pro I & II / SoundBlaster I & II - SoundBlaster 16 / SoundBlaster Pro I & II / SoundBlaster I & II
By default DOSBox provides Soundblaster 16 level 16-bit stereo sound. By default DOSBox provides SoundBlaster 16 level 16-bit stereo sound.
You can select a different SoundBlaster version in the configuration of You can select a different SoundBlaster version in the configuration of
DOSBox. AWE32 music is not emulated as you can use MPU-401 instead DOSBox. AWE32 music is not emulated as you can use MPU-401 instead
(see below). (see below).
@ -311,14 +311,14 @@ SOUND: What sound hardware does DOSBox presently emulate?
The emulation of this hardware is nearly complete, though the MIDI The emulation of this hardware is nearly complete, though the MIDI
capabilities have been left out, since an MPU-401 has been emulated capabilities have been left out, since an MPU-401 has been emulated
in other code. For Gravis music you also have to install Gravis drivers in other code. For Gravis music you also have to install Gravis drivers
inside DOSBox. It is disabled as default. inside DOSBox. It is disabled by default.
- MPU-401 - MPU-401
A MIDI passthrough interface is also emulated. This method of sound A MIDI passthrough interface is also emulated. This method of sound
output will only work when used with external device/emulator. output will only work when used with external device/emulator.
Every Windows XP/Vista/7 and MAC OS has got a default emulator compatible Every Windows XP/Vista/7 and Mac OS X has got a default emulator
with: Sound Canvas/SCC/General Standard/General MIDI/Wave Blaster. compatible with: Sound Canvas/SCC/General Standard/General MIDI/Wave
A different device/emulator is needed for Roland LAPC/CM-32L/MT-32 Blaster. A different device/emulator is needed for
compatibility. Roland LAPC/CM-32L/MT-32 compatibility.
SOUND: The sound stutters or sounds stretched/weird. SOUND: The sound stutters or sounds stretched/weird.
@ -387,7 +387,7 @@ CRASH: The game/application does not run at all/crashes!
Look at Section 11: "Troubleshooting". Look at Section 11: "Troubleshooting".
CRASH: DOSBox crashes on startup!. CRASH: DOSBox crashes on startup!
Look at Section 11: "Troubleshooting". Look at Section 11: "Troubleshooting".
@ -429,7 +429,7 @@ See Section 13: "The configuration (options) file".
To be able to use Command Line Parameters: To be able to use Command Line Parameters:
(Windows) open cmd.exe or command.com or edit the shortcut to dosbox.exe (Windows) open cmd.exe or command.com or edit the shortcut to dosbox.exe
(Linux) use console (Linux) use console
(MAC OS X) start terminal.app and navigate to: (Mac OS X) start terminal.app and navigate to:
/applications/dosbox.app/contents/macos/dosbox /applications/dosbox.app/contents/macos/dosbox
The options are valid for all operating systems unless noted in the option The options are valid for all operating systems unless noted in the option
@ -482,15 +482,15 @@ dosbox -erasemapper
-machine machinetype -machine machinetype
Setup DOSBox to emulate a specific type of machine. Valid choices are: Setup DOSBox to emulate a specific type of machine. Valid choices are:
hercules, cga, ega, pcjr, tandy, svga_s3 (default) as well as hercules, cga, ega, pcjr, tandy, svga_s3 (default) as well as
the additional svga chipsets listed in the DOSBox configuration file. the additional SVGA chipsets listed in the DOSBox configuration file.
svga_s3 enables vesa emulation as well. svga_s3 enables VESA emulation as well.
For some special vga effects the machinetype vgaonly can be used, For some special VGA effects the machinetype vgaonly can be used,
note that this disables svga capabilities and might be slower due to the note that this disables SVGA capabilities and might be slower due to the
higher emulation precision. higher emulation precision.
The machinetype affects the video card and the available sound cards. The machinetype affects the video card and the available sound cards.
-noconsole (Windows Only) -noconsole (Windows Only)
Start DOSBox without showing DOSBox Status Window (console). Start DOSBox without showing the DOSBox status window (console).
Output will be redirected to stdout.txt and stderr.txt Output will be redirected to stdout.txt and stderr.txt
-startmapper -startmapper
@ -630,7 +630,7 @@ MOUNT -u "Emulated Drive letter"
Forces use of the SDL CD-ROM layer. Valid on all systems. Forces use of the SDL CD-ROM layer. Valid on all systems.
-usecd number -usecd number
Valid on all systems, under windows the -noioctl switch has to be Valid on all systems, under Windows the -noioctl switch has to be
present to make use of the -usecd switch. present to make use of the -usecd switch.
Enables to select the drive that should be used by SDL. Use this if Enables to select the drive that should be used by SDL. Use this if
the wrong or no CD-ROM drive is mounted while using the SDL CD-ROM the wrong or no CD-ROM drive is mounted while using the SDL CD-ROM
@ -882,10 +882,19 @@ LOADFIX -f
loadfix -f loadfix -f
RESCAN RESCAN [Drive:] [-All]
Make DOSBox reread the directory structure. Useful if you changed something Make DOSBox reread the directory structure. Useful if you changed something
on a mounted drive outside of DOSBox. (CTRL - F4 does this as well!) on a mounted drive outside of DOSBox. (CTRL - F4 does this as well!)
Drive:
Drive to refresh.
-All
Refresh all drives.
if both a Drive: and -All are missing, then the current drive will be
refreshed.
MIXER MIXER
Makes DOSBox display its current volume settings. Makes DOSBox display its current volume settings.
@ -1170,8 +1179,8 @@ CTRL-F11 Slow down emulation (Decrease DOSBox Cycles).
CTRL-F12 Speed up emulation (Increase DOSBox Cycles)*. CTRL-F12 Speed up emulation (Increase DOSBox Cycles)*.
ALT-F12 Unlock speed (turbo button/fast forward)**. ALT-F12 Unlock speed (turbo button/fast forward)**.
CTRL-ALT-HOME Restart DOSBox. CTRL-ALT-HOME Restart DOSBox.
F11, ALT-F11 (machine=cga) change tint in NTSC output modes*** F11, ALT-F11 (machine=cga) change tint in NTSC output modes***.
F11 (machine=hercules) cycle through amber, green, white colouring*** F11 (machine=hercules) cycle through amber, green, white colouring***.
*NOTE: Once you increase your DOSBox cycles beyond your computer CPU resources, *NOTE: Once you increase your DOSBox cycles beyond your computer CPU resources,
it will produce the same effect as slowing down the emulation. it will produce the same effect as slowing down the emulation.
@ -1187,13 +1196,14 @@ F11 (machine=hercules) cycle through amber, green, white colouring***
These are the default keybindings. They can be changed in the keymapper These are the default keybindings. They can be changed in the keymapper
(see Section 7: "KeyMapper"). (see Section 7: "KeyMapper").
In MAC OS you can try using cmd(applekey) together with Ctrl if the key doesn't In Mac OS X you can try using cmd(applekey) together with Ctrl (and/or ) Fn,
work eg. cmd-ctrl-F1, but some keys may still need remapping (in Linux too). if the key doesn't work i.e. fn-cmd-ctrl-F1, but some keys may still need
remapping (in Linux too).
Saved/recorded files can be found in: Saved/recorded files can be found in:
(Windows) "Start/WinLogo Menu"->"All Programs"->DOSBox-0.74->Extras (Windows) "Start/WinLogo Menu"->"All Programs"->DOSBox-0.74->Extras
(Linux) ~/.dosbox/capture (Linux) ~/.dosbox/capture
(MAC OS X) "~/Library/Preferences/capture" (Mac OS X) "~/Library/Preferences/capture"
This can be changed in the DOSBox configuration file. This can be changed in the DOSBox configuration file.
@ -1231,7 +1241,7 @@ connected, or with a different joystick setting, your new setting will not work
properly, or not work at all, until you reset DOSBox's mapperfile. properly, or not work at all, until you reset DOSBox's mapperfile.
If controller is working properly outside DOSBox, but doesn't calibrate properly If controller is working properly outside DOSBox, but doesn't calibrate properly
inside DOSBox, try different 'timed' setting in DOSBox's configuration file. inside DOSBox, try a different 'timed' setting in DOSBox's configuration file.
@ -1239,8 +1249,8 @@ inside DOSBox, try different 'timed' setting in DOSBox's configuration file.
7. KeyMapper: 7. KeyMapper:
============= =============
You start the DOSBox mapper either with CTRL-F1 (see Section 5: "Special Keys") Start the DOSBox mapper either with CTRL-F1 (see Section 5: "Special Keys") or
or -startmapper (see Section 3: "Command Line Parameters"). -startmapper (see Section 3: "Command Line Parameters").
You are presented with a virtual keyboard and a virtual joystick. You are presented with a virtual keyboard and a virtual joystick.
These virtual devices correspond to the keys and events DOSBox will These virtual devices correspond to the keys and events DOSBox will
@ -1296,7 +1306,7 @@ Q3. If you try it out in DOSBox, you will notice that pressing X makes ZX
mapped key X. Click "Del". mapped key X. Click "Del".
Examples about remapping the joystick: Examples of remapping the joystick:
You have a joystick attached, it is working fine under DOSBox and you You have a joystick attached, it is working fine under DOSBox and you
want to play some keyboard-only game with the joystick (it is assumed want to play some keyboard-only game with the joystick (it is assumed
that the game is controlled by the arrows on the keyboard): that the game is controlled by the arrows on the keyboard):
@ -1318,7 +1328,7 @@ Examples about remapping the joystick:
If you want to remap anything to your d-pad/hat you will have to change If you want to remap anything to your d-pad/hat you will have to change
'joysticktype=auto' to 'joysticktype=fcs' in configuration file. Maybe this 'joysticktype=auto' to 'joysticktype=fcs' in configuration file. Maybe this
will be improved in the next dosbox version. will be improved in the next DOSBox version.
If you change the default mapping, you can save your changes by clicking on If you change the default mapping, you can save your changes by clicking on
@ -1333,12 +1343,12 @@ your mapperfile, if it is present in the DOSBox configuration file.
=================== ===================
To switch to a different keyboard layout, either the entry "keyboardlayout" To switch to a different keyboard layout, either the entry "keyboardlayout"
in the [dos] section of the DOSBox configuration file can be used, or the in the [dos] section of the DOSBox configuration file or the internal DOSBox
internal DOSBox program keyb.com (Section 4: "Internal Programs"). Both accept program keyb.com (Section 4: "Internal Programs") can be used. Both accept
DOS conforming language codes (see below), but only by using keyb.com a DOS conforming language codes (see below), but only by using keyb.com a
custom codepage can be specified. custom codepage can be specified.
The default keyboardlayout=auto currently works under windows only. The language The default keyboardlayout=auto currently works under Windows only. The language
is chosen according to the OS language, but the keyboard layout is not detected. is chosen according to the OS language, but the keyboard layout is not detected.
Layout switching Layout switching
@ -1411,7 +1421,7 @@ of the nullmodem connection. These are all parameters:
* port: - TCP port number. Default: 23 * port: - TCP port number. Default: 23
* rxdelay: - how long (milliseconds) to delay received data if the * rxdelay: - how long (milliseconds) to delay received data if the
interface is not ready. Increase this value if you encounter interface is not ready. Increase this value if you encounter
overrun errors in the DOSBox Status Window. Default: 100 overrun errors in the DOSBox status window. Default: 100
* txdelay: - how long to gather data before sending a packet. Default: 12 * txdelay: - how long to gather data before sending a packet. Default: 12
(reduces Network overhead) (reduces Network overhead)
* server: - This nullmodem will be a client connecting to the specified * server: - This nullmodem will be a client connecting to the specified
@ -1517,7 +1527,7 @@ Example:
==================== ====================
General tip: General tip:
Check messages in DOSBox Status Window. See Section 12: "DOSBox Status Window". Check messages in the DOSBox status window. See Section 12: "DOSBox Status Window".
DOSBox crashes right after starting it: DOSBox crashes right after starting it:
- use different values for the output= entry in your DOSBox - use different values for the output= entry in your DOSBox
@ -1563,14 +1573,14 @@ The game exits to the DOSBox prompt with some error message:
12. DOSBox Status Window: 12. DOSBox Status Window:
========================= =========================
DOSBox's Staus window contains many useful information about your currant DOSBox's status window contains useful information about your current
configuration, your actions in DOSBox, errors that happened and more. configuration, your actions in DOSBox, errors which occurred and more.
Whenever you have any problem with DOSBox check these messages. Check these messages in case you encounter any problems with DOSBox.
To start DOSBox Status Window: To display the DOSBox status window:
(Windows) Status Window is being started together with main DOSBox window. (Windows) The status window is being started together with main DOSBox window.
(Linux) You may have to start DOSBox from a console to see Status Window. (Linux) You may have to start DOSBox from a console to see the status window.
(MAC OS X) Right click on DOSBox.app, choose "Show Package Contents"-> (Mac OS X) Right click on DOSBox.app, choose "Show Package Contents"->
->enter "Contents"->enter "MacOS"->run "DOSBox" ->enter "Contents"->enter "MacOS"->run "DOSBox"
@ -1583,7 +1593,7 @@ The configuration file is automatically created the first time you run DOSBox.
The file can be found in: The file can be found in:
(Windows) "Start/WinLogo Menu"->"All Programs"->DOSBox-0.74->Options (Windows) "Start/WinLogo Menu"->"All Programs"->DOSBox-0.74->Options
(Linux) ~/.dosbox/dosbox-0.74.conf (Linux) ~/.dosbox/dosbox-0.74.conf
(MAC OS X) "~/Library/Preferences/DOSBox 0.74 Preferences" (Mac OS X) "~/Library/Preferences/DOSBox 0.74 Preferences"
The file is divided into several sections. Each section starts with a The file is divided into several sections. Each section starts with a
[section name] line. The settings are the property=value lines where value can [section name] line. The settings are the property=value lines where value can
be altered to customize DOSBox. be altered to customize DOSBox.

View File

@ -205,7 +205,7 @@ which is located on the local filesystem. Not a mounted drive in
.RS .RS
.TP .TP
.B \-securemode .B \-securemode
.RB Switches dosbox " to a more secure mode. In this mode the" .RB "Switches " dosbox " to a more secure mode. In this mode the"
.RI "internal commands " MOUNT ", " IMGMOUNT " and " BOOT " won\'t work." .RI "internal commands " MOUNT ", " IMGMOUNT " and " BOOT " won\'t work."
It\'s not possible It\'s not possible
either to create a new configfile or languagefile in this mode. either to create a new configfile or languagefile in this mode.
@ -216,7 +216,7 @@ either to create a new configfile or languagefile in this mode.
The configuration file controls various settings of The configuration file controls various settings of
.BR dosbox ": The amount of emulated memory," .BR dosbox ": The amount of emulated memory,"
the emulated soundcards and many the emulated soundcards and many
.RI "more things. It futher allows acces to " AUTOEXEC.BAT . .RI "more things. It further allows access to " AUTOEXEC.BAT .
.LP .LP
The language file controls all visible output of the internal commands and The language file controls all visible output of the internal commands and
the internal dos. the internal dos.
@ -242,11 +242,21 @@ The amount of memory to eat up (in kb). Example \-32, \-64 or \-128
Frees all memory eaten up by loadfix. Frees all memory eaten up by loadfix.
.RE .RE
.TP .TP
.B RESCAN .B RESCAN [\-All] [Drive:]
.LP .LP
.RB "Make " dosbox " reread the directory structure. Useful if you changed .RB "Make " dosbox " reread the directory structure. Useful if you changed
.RB "something on a mounted drive outside " dosbox ".(CTRL\-F4 does" .RB "something on a mounted drive outside " dosbox ".(CTRL\-F4 does"
this as well!) this as well!)
.RS
.TP
.B \-All
.R Reread directory structure for all drives.
.TP
.B Drive:
.RB "Reread directory structure for drive " Drive:
.RE
.LP
.RB "If both " \-All " and " Drive: " are missing, then the current drive is used.
.TP .TP
.B IMGMOUNT .B IMGMOUNT
.LP .LP
@ -335,7 +345,7 @@ gets saved/recorded !
capacity, it will produce the same effect as slowing down the emulation. capacity, it will produce the same effect as slowing down the emulation.
This maximum will vary from computer to computer, there is no standard. This maximum will vary from computer to computer, there is no standard.
.SH "SYSTEM REQUIREMENTS" .SH "SYSTEM REQUIREMENTS"
Fast machine. My guess would be pentium\-2 400+ to get decent emulation Fast machine. My guess would be Pentium\-2 400+ to get decent emulation
of games written for an 286 machine. of games written for an 286 machine.
For protected mode games a 1 Ghz machine is recommended and don't expect For protected mode games a 1 Ghz machine is recommended and don't expect
them to run fast though!! Be sure to read the next section on how to speed them to run fast though!! Be sure to read the next section on how to speed

View File

@ -69,6 +69,7 @@ public:
}; };
void updateDPT(void); void updateDPT(void);
void incrementFDD(void);
#define MAX_HDD_IMAGES 2 #define MAX_HDD_IMAGES 2

View File

@ -30,7 +30,7 @@ extern CallBack_Handler CallBack_Handlers[];
enum { CB_RETN,CB_RETF,CB_RETF8,CB_IRET,CB_IRETD,CB_IRET_STI,CB_IRET_EOI_PIC1, enum { CB_RETN,CB_RETF,CB_RETF8,CB_IRET,CB_IRETD,CB_IRET_STI,CB_IRET_EOI_PIC1,
CB_IRQ0,CB_IRQ1,CB_IRQ9,CB_IRQ12,CB_IRQ12_RET,CB_IRQ6_PCJR,CB_MOUSE, CB_IRQ0,CB_IRQ1,CB_IRQ9,CB_IRQ12,CB_IRQ12_RET,CB_IRQ6_PCJR,CB_MOUSE,
CB_INT29,CB_INT16,CB_HOOKABLE,CB_TDE_IRET,CB_IPXESR,CB_IPXESR_RET, CB_INT29,CB_INT16,CB_HOOKABLE,CB_TDE_IRET,CB_IPXESR,CB_IPXESR_RET,
CB_INT21 }; CB_INT21,CB_INT13 };
#define CB_MAX 128 #define CB_MAX 128
#define CB_SIZE 32 #define CB_SIZE 32

View File

@ -61,16 +61,17 @@ public:
PCI_Device* GetSubdevice(Bits subfct); PCI_Device* GetSubdevice(Bits subfct);
Bit16u NumSubdevices(void) { Bit16u NumSubdevices(void) {
if (num_subdevices>PCI_MAX_PCIFUNCTIONS-1) return PCI_MAX_PCIFUNCTIONS-1; if (num_subdevices>PCI_MAX_PCIFUNCTIONS-1) return (Bit16u)(PCI_MAX_PCIFUNCTIONS-1);
return num_subdevices; return (Bit16u)num_subdevices;
} }
Bits GetNextSubdeviceNumber(void) { Bits GetNextSubdeviceNumber(void) {
if (num_subdevices>=PCI_MAX_PCIFUNCTIONS-1) return -1; if (num_subdevices>=PCI_MAX_PCIFUNCTIONS-1) return -1;
return num_subdevices+1; return (Bits)num_subdevices+1;
} }
virtual Bits ParseReadRegister(Bit8u regnum)=0; virtual Bits ParseReadRegister(Bit8u regnum)=0;
virtual bool OverrideReadRegister(Bit8u regnum, Bit8u* rval, Bit8u* rval_mask)=0;
virtual Bits ParseWriteRegister(Bit8u regnum,Bit8u value)=0; virtual Bits ParseWriteRegister(Bit8u regnum,Bit8u value)=0;
virtual bool InitializeRegisters(Bit8u registers[256])=0; virtual bool InitializeRegisters(Bit8u registers[256])=0;

View File

@ -50,6 +50,7 @@ public:
bool FindCommand(unsigned int which,std::string & value); bool FindCommand(unsigned int which,std::string & value);
bool FindStringBegin(char const * const begin,std::string & value, bool remove=false); bool FindStringBegin(char const * const begin,std::string & value, bool remove=false);
bool FindStringRemain(char const * const name,std::string & value); bool FindStringRemain(char const * const name,std::string & value);
bool FindStringRemainBegin(char const * const name,std::string & value);
bool GetStringRemain(std::string & value); bool GetStringRemain(std::string & value);
int GetParameterFromList(const char* const params[], std::vector<std::string> & output); int GetParameterFromList(const char* const params[], std::vector<std::string> & output);
void FillVector(std::vector<std::string> & vector); void FillVector(std::vector<std::string> & vector);

View File

@ -166,6 +166,7 @@ typedef struct {
} cursor; } cursor;
Drawmode mode; Drawmode mode;
bool vret_triggered; bool vret_triggered;
bool vga_override;
} VGA_Draw; } VGA_Draw;
typedef struct { typedef struct {
@ -448,6 +449,8 @@ void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3);
void VGA_ActivateHardwareCursor(void); void VGA_ActivateHardwareCursor(void);
void VGA_KillDrawing(void); void VGA_KillDrawing(void);
void VGA_SetOverride(bool vga_override);
extern VGA_Type vga; extern VGA_Type vga;
/* Support for modular SVGA implementation */ /* Support for modular SVGA implementation */

View File

@ -433,7 +433,18 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
phys_writeb(physAddress+0x09,(Bit8u)0x59); // pop cx phys_writeb(physAddress+0x09,(Bit8u)0x59); // pop cx
phys_writeb(physAddress+0x0A,(Bit8u)0xCF); //An IRET Instruction phys_writeb(physAddress+0x0A,(Bit8u)0xCF); //An IRET Instruction
return (use_cb?15:11); return (use_cb?15:11);
case CB_INT13:
phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI
if (use_cb) {
phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word
physAddress+=4;
}
phys_writeb(physAddress+0x01,(Bit8u)0xCF); //An IRET Instruction
phys_writew(physAddress+0x02,(Bit16u)0x0ECD); // int 0e
phys_writeb(physAddress+0x04,(Bit8u)0xCF); //An IRET Instruction
return (use_cb?9:5);
default: default:
E_Exit("CALLBACK:Setup:Illegal type %d",type); E_Exit("CALLBACK:Setup:Illegal type %d",type);
} }

View File

@ -247,8 +247,8 @@ static void dyn_restoreregister(DynReg * src_reg, DynReg * dst_reg) {
{ \ { \
__asm__ volatile ( \ __asm__ volatile ( \
"fnsave %0 \n" \ "fnsave %0 \n" \
: "=m" (dyn_dh_fpu.state[0]) \
: \ : \
: "m" (dyn_dh_fpu.state[0]) \
: "memory" \ : "memory" \
); \ ); \
dyn_dh_fpu.state_used=false; \ dyn_dh_fpu.state_used=false; \
@ -303,7 +303,10 @@ run_block:
} }
#endif #endif
if (!GETFLAG(TF)) { if (!GETFLAG(TF)) {
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; if (GETFLAG(IF) && PIC_IRQCheck) {
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return CBRET_NONE;
}
goto restart_core; goto restart_core;
} }
cpudecoder=CPU_Core_Dyn_X86_Trap_Run; cpudecoder=CPU_Core_Dyn_X86_Trap_Run;
@ -450,8 +453,8 @@ void CPU_Core_Dyn_X86_Init(void) {
"finit \n" "finit \n"
"fsave %0 \n" "fsave %0 \n"
"fstcw %1 \n" "fstcw %1 \n"
: "=m" (dyn_dh_fpu.state[0]), "=m" (dyn_dh_fpu.host_cw)
: :
: "m" (dyn_dh_fpu.state[0]), "m" (dyn_dh_fpu.host_cw)
: "memory" : "memory"
); );
#endif #endif
@ -468,8 +471,62 @@ void CPU_Core_Dyn_X86_Cache_Close(void) {
cache_close(); cache_close();
} }
void CPU_Core_Dyn_X86_Cache_Reset(void) {
cache_reset();
}
void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu) { void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu) {
dyn_dh_fpu.dh_fpu_enabled=dh_fpu; dyn_dh_fpu.dh_fpu_enabled=dh_fpu;
} }
Bit32u fpu_state[32];
void CPU_Core_Dyn_X86_SaveDHFPUState(void) {
if (dyn_dh_fpu.dh_fpu_enabled) {
if (dyn_dh_fpu.state_used!=0) {
#if defined (_MSC_VER)
__asm {
__asm fsave fpu_state[0]
__asm finit
}
#else
__asm__ volatile (
"fsave %0 \n"
"finit \n"
: "=m" (fpu_state[0])
:
: "memory"
);
#endif
}
}
}
void CPU_Core_Dyn_X86_RestoreDHFPUState(void) {
if (dyn_dh_fpu.dh_fpu_enabled) {
if (dyn_dh_fpu.state_used!=0) {
#if defined (_MSC_VER)
__asm {
__asm frstor fpu_state[0]
}
#else
__asm__ volatile (
"frstor %0 \n"
:
: "m" (fpu_state[0])
:
);
#endif
}
}
}
#else
void CPU_Core_Dyn_X86_SaveDHFPUState(void) {
}
void CPU_Core_Dyn_X86_RestoreDHFPUState(void) {
}
#endif #endif

View File

@ -569,3 +569,75 @@ static void cache_close(void) {
cache_code_link_blocks = NULL; cache_code_link_blocks = NULL;
cache_initialized = false; */ cache_initialized = false; */
} }
static void cache_reset(void) {
if (cache_initialized) {
for (;;) {
if (cache.used_pages) {
CodePageHandler * cpage=cache.used_pages;
CodePageHandler * npage=cache.used_pages->next;
cpage->ClearRelease();
delete cpage;
cache.used_pages=npage;
} else break;
}
if (cache_blocks == NULL) {
cache_blocks=(CacheBlock*)malloc(CACHE_BLOCKS*sizeof(CacheBlock));
if(!cache_blocks) E_Exit("Allocating cache_blocks has failed");
}
memset(cache_blocks,0,sizeof(CacheBlock)*CACHE_BLOCKS);
cache.block.free=&cache_blocks[0];
for (Bits i=0;i<CACHE_BLOCKS-1;i++) {
cache_blocks[i].link[0].to=(CacheBlock *)1;
cache_blocks[i].link[1].to=(CacheBlock *)1;
cache_blocks[i].cache.next=&cache_blocks[i+1];
}
if (cache_code_start_ptr==NULL) {
#if defined (WIN32)
cache_code_start_ptr=(Bit8u*)VirtualAlloc(0,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP,
MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if (!cache_code_start_ptr)
cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
#else
cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
#endif
if (!cache_code_start_ptr) E_Exit("Allocating dynamic core cache memory failed");
cache_code=(Bit8u*)(((int)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //MEM LEAK. store old pointer if you want to free it.
cache_code_link_blocks=cache_code;
cache_code+=PAGESIZE_TEMP;
#if (C_HAVE_MPROTECT)
if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
LOG_MSG("Setting excute permission on the code cache has failed!");
#endif
}
CacheBlock * block=cache_getblock();
cache.block.first=block;
cache.block.active=block;
block->cache.start=&cache_code[0];
block->cache.size=CACHE_TOTAL;
block->cache.next=0; //Last block in the list
/* Setup the default blocks for block linkage returns */
cache.pos=&cache_code_link_blocks[0];
link_blocks[0].cache.start=cache.pos;
gen_return(BR_Link1);
cache.pos=&cache_code_link_blocks[32];
link_blocks[1].cache.start=cache.pos;
gen_return(BR_Link2);
cache.free_pages=0;
cache.last_page=0;
cache.used_pages=0;
/* Setup the code pages */
for (Bitu i=0;i<CACHE_PAGES;i++) {
CodePageHandler * newpage=new CodePageHandler();
newpage->next=cache.free_pages;
cache.free_pages=newpage;
}
}
}

View File

@ -2677,7 +2677,7 @@ restart_prefix:
goto illegalopcode; goto illegalopcode;
} }
} }
// link to next block because the maximal number of opcodes has been reached // link to next block because the maximum number of opcodes has been reached
dyn_set_eip_end(); dyn_set_eip_end();
dyn_reduce_cycles(); dyn_reduce_cycles();
dyn_save_critical_regs(); dyn_save_critical_regs();

View File

@ -246,7 +246,7 @@ run_block:
// the block was exited due to a non-predictable control flow // the block was exited due to a non-predictable control flow
// modifying instruction (like ret) or some nontrivial cpu state // modifying instruction (like ret) or some nontrivial cpu state
// changing instruction (for example switch to/from pmode), // changing instruction (for example switch to/from pmode),
// or the maximal number of instructions to translate was reached // or the maximum number of instructions to translate was reached
#if C_HEAVY_DEBUG #if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback; if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif #endif

View File

@ -53,7 +53,7 @@ public:
CacheBlockDynRec * to; // this block can transfer control to the to-block CacheBlockDynRec * to; // this block can transfer control to the to-block
CacheBlockDynRec * next; CacheBlockDynRec * next;
CacheBlockDynRec * from; // the from-block can transfer control to this block CacheBlockDynRec * from; // the from-block can transfer control to this block
} link[2]; // maximal two links (conditional jumps) } link[2]; // maximum two links (conditional jumps)
CacheBlockDynRec * crossblock; CacheBlockDynRec * crossblock;
}; };

View File

@ -26,7 +26,7 @@
/* /*
The function CreateCacheBlock translates the instruction stream The function CreateCacheBlock translates the instruction stream
until either an unhandled instruction is found, the maximal until either an unhandled instruction is found, the maximum
number of translated instructions is reached or some critical number of translated instructions is reached or some critical
instruction is encountered. instruction is encountered.
*/ */
@ -586,7 +586,7 @@ restart_prefix:
goto illegalopcode; goto illegalopcode;
} }
} }
// link to next block because the maximal number of opcodes has been reached // link to next block because the maximum number of opcodes has been reached
dyn_set_eip_end(); dyn_set_eip_end();
dyn_reduce_cycles(); dyn_reduce_cycles();
gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start));

View File

@ -502,7 +502,7 @@ l_M_Ed:
continue; continue;
case D_RDTSC: { case D_RDTSC: {
if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUMSLOW) goto illegalopcode; if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUMSLOW) goto illegalopcode;
Bit64s tsc=(Bit64s)(PIC_FullIndex()*(double)CPU_CycleMax); Bit64s tsc=(Bit64s)(PIC_FullIndex()*(double)(CPU_CycleAutoAdjust?70000:CPU_CycleMax));
reg_edx=(Bit32u)(tsc>>32); reg_edx=(Bit32u)(tsc>>32);
reg_eax=(Bit32u)(tsc&0xffffffff); reg_eax=(Bit32u)(tsc&0xffffffff);
break; break;

View File

@ -228,7 +228,8 @@
CASE_0F_B(0x31) /* RDTSC */ CASE_0F_B(0x31) /* RDTSC */
{ {
if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUMSLOW) goto illegal_opcode; if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUMSLOW) goto illegal_opcode;
Bit64s tsc=(Bit64s)(PIC_FullIndex()*(double)CPU_CycleMax); /* Use a fixed number when in auto cycles mode as else the reported value changes constantly */
Bit64s tsc=(Bit64s)(PIC_FullIndex()*(double) (CPU_CycleAutoAdjust?70000:CPU_CycleMax));
reg_edx=(Bit32u)(tsc>>32); reg_edx=(Bit32u)(tsc>>32);
reg_eax=(Bit32u)(tsc&0xffffffff); reg_eax=(Bit32u)(tsc&0xffffffff);
} }

View File

@ -19,6 +19,7 @@
#include <assert.h> #include <assert.h>
#include <sstream> #include <sstream>
#include <stddef.h>
#include "dosbox.h" #include "dosbox.h"
#include "cpu.h" #include "cpu.h"
#ifdef HW_RVL #ifdef HW_RVL

View File

@ -849,7 +849,7 @@ void PAGING_SetDirBase(Bitu cr3) {
} }
void PAGING_Enable(bool enabled) { void PAGING_Enable(bool enabled) {
/* If paging is disable we work from a default paging table */ /* If paging is disabled, we work from a default paging table */
if (paging.enabled==enabled) return; if (paging.enabled==enabled) return;
paging.enabled=enabled; paging.enabled=enabled;
if (enabled) { if (enabled) {

View File

@ -402,7 +402,7 @@ void CBreakpoint::ActivateBreakpoints(PhysPt adr, bool activate)
CBreakpoint* bp; CBreakpoint* bp;
for(i=BPoints.begin(); i != BPoints.end(); i++) { for(i=BPoints.begin(); i != BPoints.end(); i++) {
bp = (*i); bp = (*i);
// Do not activate, when bp is an actual adress // Do not activate, when bp is an actual address
if (activate && (bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) { if (activate && (bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) {
// Do not activate :) // Do not activate :)
continue; continue;
@ -412,7 +412,7 @@ void CBreakpoint::ActivateBreakpoints(PhysPt adr, bool activate)
}; };
bool CBreakpoint::CheckBreakpoint(Bitu seg, Bitu off) bool CBreakpoint::CheckBreakpoint(Bitu seg, Bitu off)
// Checks if breakpoint is valid an should stop execution // Checks if breakpoint is valid and should stop execution
{ {
if ((ignoreAddressOnce!=0) && (GetAddress(seg,off)==ignoreAddressOnce)) { if ((ignoreAddressOnce!=0) && (GetAddress(seg,off)==ignoreAddressOnce)) {
ignoreAddressOnce = 0; ignoreAddressOnce = 0;
@ -476,7 +476,7 @@ bool CBreakpoint::CheckBreakpoint(Bitu seg, Bitu off)
}; };
bool CBreakpoint::CheckIntBreakpoint(PhysPt adr, Bit8u intNr, Bit16u ahValue) bool CBreakpoint::CheckIntBreakpoint(PhysPt adr, Bit8u intNr, Bit16u ahValue)
// Checks if interrupt breakpoint is valid an should stop execution // Checks if interrupt breakpoint is valid and should stop execution
{ {
if ((ignoreAddressOnce!=0) && (adr==ignoreAddressOnce)) { if ((ignoreAddressOnce!=0) && (adr==ignoreAddressOnce)) {
ignoreAddressOnce = 0; ignoreAddressOnce = 0;
@ -491,7 +491,7 @@ bool CBreakpoint::CheckIntBreakpoint(PhysPt adr, Bit8u intNr, Bit16u ahValue)
bp = (*i); bp = (*i);
if ((bp->GetType()==BKPNT_INTERRUPT) && bp->IsActive() && (bp->GetIntNr()==intNr)) { if ((bp->GetType()==BKPNT_INTERRUPT) && bp->IsActive() && (bp->GetIntNr()==intNr)) {
if ((bp->GetValue()==BPINT_ALL) || (bp->GetValue()==ahValue)) { if ((bp->GetValue()==BPINT_ALL) || (bp->GetValue()==ahValue)) {
// Ignoie it once ? // Ignore it once ?
if (ignoreOnce==bp) { if (ignoreOnce==bp) {
ignoreOnce=0; ignoreOnce=0;
bp->Activate(true); bp->Activate(true);
@ -681,7 +681,7 @@ static void DrawData(void) {
Bit32u address; Bit32u address;
/* Data win */ /* Data win */
for (int y=0; y<8; y++) { for (int y=0; y<8; y++) {
// Adress // Address
if (add<0x10000) mvwprintw (dbg.win_data,1+y,0,"%04X:%04X ",dataSeg,add); if (add<0x10000) mvwprintw (dbg.win_data,1+y,0,"%04X:%04X ",dataSeg,add);
else mvwprintw (dbg.win_data,1+y,0,"%04X:%08X ",dataSeg,add); else mvwprintw (dbg.win_data,1+y,0,"%04X:%08X ",dataSeg,add);
for (int x=0; x<16; x++) { for (int x=0; x<16; x++) {
@ -1402,7 +1402,7 @@ char* AnalyzeInstruction(char* inst, bool saveSelector) {
// Variable found ? // Variable found ?
CDebugVar* var = CDebugVar::FindVar(address); CDebugVar* var = CDebugVar::FindVar(address);
if (var) { if (var) {
// Replace occurance // Replace occurence
char* pos1 = strchr(inst,'['); char* pos1 = strchr(inst,'[');
char* pos2 = strchr(inst,']'); char* pos2 = strchr(inst,']');
if (pos1 && pos2) { if (pos1 && pos2) {
@ -2424,7 +2424,7 @@ void DEBUG_HeavyWriteLogInstruction(void) {
out << hex << noshowbase << setfill('0') << uppercase; out << hex << noshowbase << setfill('0') << uppercase;
Bit32u startLog = logCount; Bit32u startLog = logCount;
do { do {
// Write Intructions // Write Instructions
TLogInst & inst = logInst[startLog]; TLogInst & inst = logInst[startLog];
out << setw(4) << inst.s_cs << ":" << setw(8) << inst.eip << " " out << setw(4) << inst.s_cs << ":" << setw(8) << inst.eip << " "
<< inst.dline << " " << inst.res << " EAX:" << setw(8)<< inst.eax << inst.dline << " " << inst.res << " EAX:" << setw(8)<< inst.eax

View File

@ -283,8 +283,10 @@ static char const *second[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* 3 */ /* 3 */
0, 0, 0, 0, 0, 0, 0, 0, 0, "rdtsc", 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
/* 4 */ /* 4 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -947,7 +949,9 @@ static void percent(char type, char subtype)
break; break;
case '2': /* old [pop cs]! now indexes */ case '2': /* old [pop cs]! now indexes */
ua_str(second[getbyte()]); /* instructions in 386/486 */ c = getbyte();
wordop = c & 1;
ua_str(second[c]); /* instructions in 386/486 */
break; break;
case 'g': /* modrm group `subtype' (0--7) */ case 'g': /* modrm group `subtype' (0--7) */

View File

@ -161,7 +161,7 @@ static void DrawBars(void) {
static void MakeSubWindows(void) { static void MakeSubWindows(void) {
/* The Std output win should go in bottem */ /* The Std output win should go at the bottom */
/* Make all the subwindows */ /* Make all the subwindows */
int win_main_maxy, win_main_maxx; getmaxyx(dbg.win_main,win_main_maxy,win_main_maxx); int win_main_maxy, win_main_maxx; getmaxyx(dbg.win_main,win_main_maxy,win_main_maxx);
int outy=1; //Match values with above int outy=1; //Match values with above

View File

@ -37,7 +37,7 @@ public:
private: private:
Bit8u readcache; Bit8u readcache;
Bit8u lastwrite; Bit8u lastwrite;
struct ansi { /* should create a constructor which fills them with the appriorate values */ struct ansi { /* should create a constructor, which would fill them with the appropriate values */
bool esc; bool esc;
bool sci; bool sci;
bool enabled; bool enabled;
@ -128,7 +128,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) {
count++; count++;
continue; continue;
} else { } else {
/* Some sort of "hack" now that \n doesn't set col to 0 (int10_char.cpp old chessgame) */ /* Some sort of "hack" now that '\n' doesn't set col to 0 (int10_char.cpp old chessgame) */
if((data[count] == '\n') && (lastwrite != '\r')) INT10_TeletypeOutputAttr('\r',ansi.attr,ansi.enabled); if((data[count] == '\n') && (lastwrite != '\r')) INT10_TeletypeOutputAttr('\r',ansi.attr,ansi.enabled);
/* pass attribute only if ansi is enabled */ /* pass attribute only if ansi is enabled */
INT10_TeletypeOutputAttr(data[count],ansi.attr,ansi.enabled); INT10_TeletypeOutputAttr(data[count],ansi.attr,ansi.enabled);

View File

@ -220,6 +220,7 @@ static Bitu DOS_21Handler(void) {
Bit8u free=mem_readb(data); Bit8u free=mem_readb(data);
Bit8u read=0;Bit8u c;Bit16u n=1; Bit8u read=0;Bit8u c;Bit16u n=1;
if (!free) break; if (!free) break;
free--;
for(;;) { for(;;) {
DOS_ReadFile(STDIN,&c,&n); DOS_ReadFile(STDIN,&c,&n);
if (c == 8) { // Backspace if (c == 8) { // Backspace
@ -232,7 +233,7 @@ static Bitu DOS_21Handler(void) {
} }
continue; continue;
} }
if (read >= free) { // Keyboard buffer full if (read == free && c != 13) { // Keyboard buffer full
Bit8u bell = 7; Bit8u bell = 7;
DOS_WriteFile(STDOUT, &bell, &n); DOS_WriteFile(STDOUT, &bell, &n);
continue; continue;

View File

@ -97,6 +97,7 @@ DOS_File::DOS_File(const DOS_File& orig) {
attr=orig.attr; attr=orig.attr;
refCtr=orig.refCtr; refCtr=orig.refCtr;
open=orig.open; open=orig.open;
hdrive=orig.hdrive;
name=0; name=0;
if(orig.name) { if(orig.name) {
name=new char [strlen(orig.name) + 1];strcpy(name,orig.name); name=new char [strlen(orig.name) + 1];strcpy(name,orig.name);
@ -110,6 +111,7 @@ DOS_File & DOS_File::operator= (const DOS_File & orig) {
attr=orig.attr; attr=orig.attr;
refCtr=orig.refCtr; refCtr=orig.refCtr;
open=orig.open; open=orig.open;
hdrive=orig.hdrive;
if(name) { if(name) {
delete [] name; name=0; delete [] name; name=0;
} }

View File

@ -93,8 +93,13 @@ void DOS_UpdatePSPName(void) {
DOS_MCB mcb(dos.psp()-1); DOS_MCB mcb(dos.psp()-1);
static char name[9]; static char name[9];
mcb.GetFileName(name); mcb.GetFileName(name);
name[8] = 0;
if (!strlen(name)) strcpy(name,"DOSBOX"); if (!strlen(name)) strcpy(name,"DOSBOX");
RunningProgram=name; for(Bitu i = 0;i < 8;i++) { //Don't put garbage in the title bar. Mac OS X doesn't like it
if (name[i] == 0) break;
if ( !isprint(*reinterpret_cast<unsigned char*>(&name[i])) ) name[i] = '?';
}
RunningProgram = name;
GFX_SetTitle(-1,-1,false); GFX_SetTitle(-1,-1,false);
} }

View File

@ -299,7 +299,7 @@ bool DOS_Rename(char const * const oldname,char const * const newname) {
} }
if (Drives[drivenew]->Rename(fullold,fullnew)) return true; if (Drives[drivenew]->Rename(fullold,fullnew)) return true;
/* If it still fails. which error should we give ? PATH NOT FOUND or EACCESS */ /* If it still fails, which error should we give ? PATH NOT FOUND or EACCESS */
LOG(LOG_FILES,LOG_NORMAL)("Rename fails for %s to %s, no proper errorcode returned.",oldname,newname); LOG(LOG_FILES,LOG_NORMAL)("Rename fails for %s to %s, no proper errorcode returned.",oldname,newname);
DOS_SetError(DOSERR_FILE_NOT_FOUND); DOS_SetError(DOSERR_FILE_NOT_FOUND);
return false; return false;
@ -924,7 +924,10 @@ bool DOS_FCBCreate(Bit16u seg,Bit16u offset) {
DOS_FCB fcb(seg,offset); DOS_FCB fcb(seg,offset);
char shortname[DOS_FCBNAME];Bit16u handle; char shortname[DOS_FCBNAME];Bit16u handle;
fcb.GetName(shortname); fcb.GetName(shortname);
if (!DOS_CreateFile(shortname,DOS_ATTR_ARCHIVE,&handle)) return false; Bit8u attr = DOS_ATTR_ARCHIVE;
fcb.GetAttr(attr);
if (!attr) attr = DOS_ATTR_ARCHIVE; //Better safe than sorry
if (!DOS_CreateFile(shortname,attr,&handle)) return false;
fcb.FileOpen((Bit8u)handle); fcb.FileOpen((Bit8u)handle);
return true; return true;
} }
@ -1164,10 +1167,11 @@ bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset){
* stored. This can not be the tempdta as that one is used by fcbfindfirst * stored. This can not be the tempdta as that one is used by fcbfindfirst
*/ */
RealPt old_dta=dos.dta();dos.dta(dos.tables.tempdta_fcbdelete); RealPt old_dta=dos.dta();dos.dta(dos.tables.tempdta_fcbdelete);
DOS_FCB fcb(RealSeg(dos.dta()),RealOff(dos.dta())); RealPt new_dta=dos.dta();
bool nextfile = false; bool nextfile = false;
bool return_value = false; bool return_value = false;
nextfile = DOS_FCBFindFirst(seg,offset); nextfile = DOS_FCBFindFirst(seg,offset);
DOS_FCB fcb(RealSeg(new_dta),RealOff(new_dta));
while(nextfile) { while(nextfile) {
char shortname[DOS_FCBNAME] = { 0 }; char shortname[DOS_FCBNAME] = { 0 };
fcb.GetName(shortname); fcb.GetName(shortname);

View File

@ -40,7 +40,7 @@ bool DOS_IOCTL(void) {
} else if (reg_al<0x12) { /* those use a diskdrive except 0x0b */ } else if (reg_al<0x12) { /* those use a diskdrive except 0x0b */
if (reg_al!=0x0b) { if (reg_al!=0x0b) {
drive=reg_bl;if (!drive) drive = DOS_GetDefaultDrive();else drive--; drive=reg_bl;if (!drive) drive = DOS_GetDefaultDrive();else drive--;
if( !(( drive < DOS_DRIVES ) && Drives[drive]) ) { if( (drive >= 2) && !(( drive < DOS_DRIVES ) && Drives[drive]) ) {
DOS_SetError(DOSERR_INVALID_DRIVE); DOS_SetError(DOSERR_INVALID_DRIVE);
return false; return false;
} }
@ -133,7 +133,7 @@ bool DOS_IOCTL(void) {
} }
return true; return true;
case 0x09: /* Check if block device remote */ case 0x09: /* Check if block device remote */
if (Drives[drive]->isRemote()) { if ((drive >= 2) && Drives[drive]->isRemote()) {
reg_dx=0x1000; // device is remote reg_dx=0x1000; // device is remote
// undocumented bits always clear // undocumented bits always clear
} else { } else {
@ -151,7 +151,7 @@ bool DOS_IOCTL(void) {
return true; return true;
case 0x0D: /* Generic block device request */ case 0x0D: /* Generic block device request */
{ {
if (Drives[drive]->isRemovable()) { if ((drive < 2) || Drives[drive]->isRemovable()) {
DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
return false; return false;
} }
@ -202,11 +202,14 @@ bool DOS_IOCTL(void) {
return true; return true;
} }
case 0x0E: /* Get Logical Drive Map */ case 0x0E: /* Get Logical Drive Map */
if (Drives[drive]->isRemovable()) { if (drive < 2) {
if (Drives[drive]) reg_al=drive+1;
else reg_al=1;
} else if (Drives[drive]->isRemovable()) {
DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
return false; return false;
} } else reg_al=0; /* Only 1 logical drive assigned */
reg_al = 0; /* Only 1 logical drive assigned */ reg_ah=0x07;
return true; return true;
default: default:
LOG(LOG_DOSMISC,LOG_ERROR)("DOS:IOCTL Call %2X unhandled",reg_al); LOG(LOG_DOSMISC,LOG_ERROR)("DOS:IOCTL Call %2X unhandled",reg_al);

View File

@ -48,6 +48,7 @@ Bitu DEBUG_EnableDebugger(void);
#endif #endif
void MSCDEX_SetCDInterface(int intNr, int forceCD); void MSCDEX_SetCDInterface(int intNr, int forceCD);
static Bitu ZDRIVE_NUM = 25;
#ifdef HW_RVL #ifdef HW_RVL
// Mounts a folder as a harddrive before starting the shell // Mounts a folder as a harddrive before starting the shell
@ -121,23 +122,51 @@ int MountDOSBoxDir(char DriveLetter, const char *path) {
class MOUNT : public Program { class MOUNT : public Program {
public: public:
void Run(void) void ListMounts(void) {
{ char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr;
/* Command uses dta so set it to our internal dta */
RealPt save_dta = dos.dta();
dos.dta(dos.tables.tempdta);
DOS_DTA dta(dos.dta());
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_1"));
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_FORMAT"),"Drive","Type","Label");
for(int p = 0;p < 8;p++) WriteOut("----------");
for (int d = 0;d < DOS_DRIVES;d++) {
if (!Drives[d]) continue;
char root[4] = {'A'+d,':','\\',0};
bool ret = DOS_FindFirst(root,DOS_ATTR_VOLUME);
if (ret) {
dta.GetResult(name,size,date,time,attr);
DOS_FindNext(); //Mark entry as invalid
} else name[0] = 0;
/* Change 8.3 to 11.0 */
char* dot = strchr(name,'.');
if(dot && (dot - name == 8) ) {
name[8] = name[9];name[9] = name[10];name[10] = name[11];name[11] = 0;
}
root[1] = 0; //This way, the format string can be reused.
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_FORMAT"),root, Drives[d]->GetInfo(),name);
}
dos.dta(save_dta);
}
void Run(void) {
DOS_Drive * newdrive;char drive; DOS_Drive * newdrive;char drive;
std::string label; std::string label;
std::string umount; std::string umount;
std::string newz;
//Hack To allow long commandlines //Hack To allow long commandlines
ChangeToLongCmd(); ChangeToLongCmd();
/* Parse the command line */ /* Parse the command line */
/* if the command line is empty show current mounts */ /* if the command line is empty show current mounts */
if (!cmd->GetCount()) { if (!cmd->GetCount()) {
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_1")); ListMounts();
for (int d=0;d<DOS_DRIVES;d++) {
if (Drives[d]) {
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"),d+'A',Drives[d]->GetInfo());
}
}
return; return;
} }
@ -152,12 +181,12 @@ public:
if (cmd->FindString("-u",umount,false)) { if (cmd->FindString("-u",umount,false)) {
umount[0] = toupper(umount[0]); umount[0] = toupper(umount[0]);
int i_drive = umount[0]-'A'; int i_drive = umount[0]-'A';
if(i_drive < DOS_DRIVES && i_drive >= 0 && Drives[i_drive]) { if (i_drive < DOS_DRIVES && i_drive >= 0 && Drives[i_drive]) {
switch (DriveManager::UnmountDrive(i_drive)) { switch (DriveManager::UnmountDrive(i_drive)) {
case 0: case 0:
Drives[i_drive] = 0; Drives[i_drive] = 0;
if(i_drive == DOS_GetDefaultDrive()) if(i_drive == DOS_GetDefaultDrive())
DOS_SetDrive(toupper('Z') - 'A'); DOS_SetDrive(ZDRIVE_NUM);
WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_SUCCESS"),umount[0]); WriteOut(MSG_Get("PROGRAM_MOUNT_UMOUNT_SUCCESS"),umount[0]);
break; break;
case 1: case 1:
@ -173,7 +202,45 @@ public:
return; return;
} }
// Show list of cdroms /* Check for moving Z: */
/* Only allowing moving it once. It is merely a convenience added for the wine team */
if (ZDRIVE_NUM == 25 && cmd->FindString("-z", newz,false)) {
newz[0] = toupper(newz[0]);
int i_newz = newz[0] - 'A';
if (i_newz >= 0 && i_newz < DOS_DRIVES-1 && !Drives[i_newz]) {
ZDRIVE_NUM = i_newz;
/* remap drives */
Drives[i_newz] = Drives[25];
Drives[25] = 0;
DOS_Shell *fs = static_cast<DOS_Shell *>(first_shell); //dynamic ?
/* Update environment */
std::string line = "";
char ppp[2] = {newz[0],0};
std::string tempenv = ppp; tempenv += ":\\";
if (fs->GetEnvStr("PATH",line)){
std::string::size_type idx = line.find('=');
std::string value = line.substr(idx +1 , std::string::npos);
while ( (idx = value.find("Z:\\")) != std::string::npos ||
(idx = value.find("z:\\")) != std::string::npos )
value.replace(idx,3,tempenv);
line = value;
}
if (!line.size()) line = tempenv;
fs->SetEnv("PATH",line.c_str());
tempenv += "COMMAND.COM";
fs->SetEnv("COMSPEC",tempenv.c_str());
/* Update batch file if running from Z: (very likely: autoexec) */
if(fs->bf) {
std::string &name = fs->bf->filename;
if(name.length() >2 && name[0] == 'Z' && name[1] == ':') name[0] = newz[0];
}
/* Change the active drive */
if (DOS_GetDefaultDrive() == 25) DOS_SetDrive(i_newz);
}
return;
}
/* Show list of cdroms */
if (cmd->FindExist("-cd",false)) { if (cmd->FindExist("-cd",false)) {
int num = SDL_CDNumDrives(); int num = SDL_CDNumDrives();
WriteOut(MSG_Get("PROGRAM_MOUNT_CDROMS_FOUND"),num); WriteOut(MSG_Get("PROGRAM_MOUNT_CDROMS_FOUND"),num);
@ -393,6 +460,7 @@ public:
label = drive; label += "_FLOPPY"; label = drive; label += "_FLOPPY";
newdrive->dirCache.SetLabel(label.c_str(),iscdrom,true); newdrive->dirCache.SetLabel(label.c_str(),iscdrom,true);
} }
if(type == "floppy") incrementFDD();
return; return;
showusage: showusage:
#if defined (WIN32) || defined(OS2) #if defined (WIN32) || defined(OS2)
@ -982,12 +1050,30 @@ public:
void RESCAN::Run(void) void RESCAN::Run(void)
{ {
// Get current drive bool all = false;
Bit8u drive = DOS_GetDefaultDrive(); Bit8u drive = DOS_GetDefaultDrive();
if (Drives[drive]) {
if(cmd->FindCommand(1,temp_line)) {
//-A -All /A /All
if(temp_line.size() >= 2 && (temp_line[0] == '-' ||temp_line[0] =='/')&& (temp_line[1] == 'a' || temp_line[1] =='A') ) all = true;
else if(temp_line.size() == 2 && temp_line[1] == ':') {
lowcase(temp_line);
drive = temp_line[0] - 'a';
}
}
// Get current drive
if (all) {
for(Bitu i =0; i<DOS_DRIVES;i++) {
if (Drives[i]) Drives[i]->EmptyCache();
}
WriteOut(MSG_Get("PROGRAM_RESCAN_SUCCESS"));
} else {
if (drive < DOS_DRIVES && Drives[drive]) {
Drives[drive]->EmptyCache(); Drives[drive]->EmptyCache();
WriteOut(MSG_Get("PROGRAM_RESCAN_SUCCESS")); WriteOut(MSG_Get("PROGRAM_RESCAN_SUCCESS"));
} }
}
} }
static void RESCAN_ProgramStart(Program * * make) { static void RESCAN_ProgramStart(Program * * make) {
@ -1423,8 +1509,9 @@ void DOS_SetupPrograms(void) {
/*Add Messages */ /*Add Messages */
MSG_Add("PROGRAM_MOUNT_CDROMS_FOUND","CDROMs found: %d\n"); MSG_Add("PROGRAM_MOUNT_CDROMS_FOUND","CDROMs found: %d\n");
MSG_Add("PROGRAM_MOUNT_STATUS_FORMAT","%-5s %-58s %-12s\n");
MSG_Add("PROGRAM_MOUNT_STATUS_2","Drive %c is mounted as %s\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_STATUS_1","The currently mounted drives are:\n");
MSG_Add("PROGRAM_MOUNT_ERROR_1","Directory %s doesn't exist.\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_2","%s isn't a directory\n");
MSG_Add("PROGRAM_MOUNT_ILL_TYPE","Illegal type %s\n"); MSG_Add("PROGRAM_MOUNT_ILL_TYPE","Illegal type %s\n");

View File

@ -378,6 +378,60 @@ bool DOS_Drive_Cache::RemoveTrailingDot(char* shortname) {
return false; return false;
} }
#define WINE_DRIVE_SUPPORT 1
#if WINE_DRIVE_SUPPORT
//Changes to interact with WINE by supporting their namemangling.
//The code is rather slow, because orglist is unordered, so it needs to be avoided if possible.
//Hence the tests in GetLongFileName
// From the Wine project
static Bits wine_hash_short_file_name( char* name, char* buffer )
{
static const char hash_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
static const char invalid_chars[] = { '*','?','<','>','|','"','+','=',',',';','[',']',' ','\345','~','.',0 };
char* p;
char* ext;
char* end = name + strlen(name);
char* dst;
unsigned short hash;
int i;
// Compute the hash code of the file name
for (p = name, hash = 0xbeef; p < end - 1; p++)
hash = (hash<<3) ^ (hash>>5) ^ tolower(*p) ^ (tolower(p[1]) << 8);
hash = (hash<<3) ^ (hash>>5) ^ tolower(*p); // Last character
// Find last dot for start of the extension
for (p = name + 1, ext = NULL; p < end - 1; p++) if (*p == '.') ext = p;
// Copy first 4 chars, replacing invalid chars with '_'
for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
{
if (p == end || p == ext) break;
*dst++ = (*p < 0 || strchr( invalid_chars, *p ) != NULL) ? '_' : toupper(*p);
}
// Pad to 5 chars with '~'
while (i-- >= 0) *dst++ = '~';
// Insert hash code converted to 3 ASCII chars
*dst++ = hash_chars[(hash >> 10) & 0x1f];
*dst++ = hash_chars[(hash >> 5) & 0x1f];
*dst++ = hash_chars[hash & 0x1f];
// Copy the first 3 chars of the extension (if any)
if (ext)
{
*dst++ = '.';
for (i = 3, ext++; (i > 0) && ext < end; i--, ext++)
*dst++ = (*ext < 0 || strchr( invalid_chars, *ext ) != NULL) ? '_' : toupper(*ext);
}
return dst - buffer;
}
#endif
Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) { Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) {
std::vector<CFileInfo*>::size_type filelist_size = curDir->fileList.size(); std::vector<CFileInfo*>::size_type filelist_size = curDir->fileList.size();
if (GCC_UNLIKELY(filelist_size<=0)) return -1; if (GCC_UNLIKELY(filelist_size<=0)) return -1;
@ -398,6 +452,21 @@ Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) {
return mid; return mid;
}; };
} }
#ifdef WINE_DRIVE_SUPPORT
if (strlen(shortName) < 8 || shortName[4] != '~' || shortName[5] == '.' || shortName[6] == '.' || shortName[7] == '.') return -1; // not available
// else it's most likely a Wine style short name ABCD~###, # = not dot (length at least 8)
// The above test is rather strict as the following loop can be really slow if filelist_size is large.
char buff[CROSS_LEN];
for (Bitu i = 0; i < filelist_size; i++) {
res = wine_hash_short_file_name(curDir->fileList[i]->orgname,buff);
buff[res] = 0;
if (!strcmp(shortName,buff)) {
// Found
strcpy(shortName,curDir->fileList[i]->orgname);
return (Bits)i;
}
}
#endif
// not available // not available
return -1; return -1;
} }

View File

@ -101,7 +101,7 @@ bool Virtual_File::Read(Bit8u * data,Bit16u * size) {
} }
bool Virtual_File::Write(Bit8u * data,Bit16u * size){ bool Virtual_File::Write(Bit8u * data,Bit16u * size){
/* Not really writeable */ /* Not really writable */
return false; return false;
} }

View File

@ -506,6 +506,7 @@ void DOSBOX_Init(void) {
Pstring = secprop->Add_string("midiconfig",Property::Changeable::WhenIdle,""); Pstring = secprop->Add_string("midiconfig",Property::Changeable::WhenIdle,"");
Pstring->Set_help("Special configuration options for the device driver. This is usually the id of the device you want to use.\n" Pstring->Set_help("Special configuration options for the device driver. This is usually the id of the device you want to use.\n"
" or in the case of coreaudio, you can specify a soundfont here.\n"
" When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues.\n" " When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues.\n"
" In that case, add 'delaysysex', for example: midiconfig=2 delaysysex\n" " In that case, add 'delaysysex', for example: midiconfig=2 delaysysex\n"
" See the README/Manual for more details."); " See the README/Manual for more details.");
@ -733,8 +734,8 @@ void DOSBOX_Init(void) {
"You can put your MOUNT lines here.\n" "You can put your MOUNT lines here.\n"
); );
MSG_Add("CONFIGFILE_INTRO", MSG_Add("CONFIGFILE_INTRO",
"# This is the configurationfile for DOSBox %s. (Please use the latest version of DOSBox)\n" "# This is the configuration file for DOSBox %s. (Please use the latest version of DOSBox)\n"
"# Lines starting with a # are commentlines and are ignored by DOSBox.\n" "# Lines starting with a # are comment lines and are ignored by DOSBox.\n"
"# They are used to (briefly) document the effect of each option.\n"); "# They are used to (briefly) document the effect of each option.\n");
MSG_Add("CONFIG_SUGGESTED_VALUES", "Possible values"); MSG_Add("CONFIG_SUGGESTED_VALUES", "Possible values");

View File

@ -32,6 +32,7 @@ class MidiHandler_coreaudio : public MidiHandler {
private: private:
AUGraph m_auGraph; AUGraph m_auGraph;
AudioUnit m_synth; AudioUnit m_synth;
const char *soundfont;
public: public:
MidiHandler_coreaudio() : m_auGraph(0), m_synth(0) {} MidiHandler_coreaudio() : m_auGraph(0), m_synth(0) {}
const char * GetName(void) { return "coreaudio"; } const char * GetName(void) { return "coreaudio"; }
@ -71,6 +72,22 @@ public:
// Get the music device from the graph. // Get the music device from the graph.
RequireNoErr(AUGraphGetNodeInfo(m_auGraph, synthNode, NULL, NULL, NULL, &m_synth)); RequireNoErr(AUGraphGetNodeInfo(m_auGraph, synthNode, NULL, NULL, NULL, &m_synth));
// Optionally load a soundfont
if (conf && conf[0]) {
soundfont = conf;
FSRef soundfontRef;
RequireNoErr(FSPathMakeRef((const UInt8*)soundfont, &soundfontRef, NULL));
RequireNoErr(AudioUnitSetProperty(
m_synth,
kMusicDeviceProperty_SoundBankFSRef,
kAudioUnitScope_Global,
0,
&soundfontRef,
sizeof(soundfontRef)
));
LOG_MSG("MIDI:coreaudio: loaded soundfont: %s",soundfont);
}
// Finally: Start the graph! // Finally: Start the graph!
RequireNoErr(AUGraphStart(m_auGraph)); RequireNoErr(AUGraphStart(m_auGraph));

View File

@ -2107,7 +2107,7 @@ static void CreateDefaultBinds(void) {
} }
void MAPPER_AddHandler(MAPPER_Handler * handler,MapKeys key,Bitu mods,char const * const eventname,char const * const buttonname) { void MAPPER_AddHandler(MAPPER_Handler * handler,MapKeys key,Bitu mods,char const * const eventname,char const * const buttonname) {
//Check if it allready exists=> if so return. //Check if it already exists=> if so return.
for(CHandlerEventVector_it it=handlergroup.begin();it!=handlergroup.end();it++) for(CHandlerEventVector_it it=handlergroup.begin();it!=handlergroup.end();it++)
if(strcmp((*it)->buttonname,buttonname) == 0) return; if(strcmp((*it)->buttonname,buttonname) == 0) return;

View File

@ -174,6 +174,8 @@ struct SDL_Block {
} window; } window;
Bit8u bpp; Bit8u bpp;
bool fullscreen; bool fullscreen;
bool lazy_fullscreen;
bool lazy_fullscreen_req;
bool doublebuf; bool doublebuf;
SCREEN_TYPES type; SCREEN_TYPES type;
SCREEN_TYPES want_type; SCREEN_TYPES want_type;
@ -247,6 +249,12 @@ void GFX_SetTitle(Bit32s cycles,Bits frameskip,bool paused){
SDL_WM_SetCaption(title,VERSION); SDL_WM_SetCaption(title,VERSION);
} }
static void KillSwitch(bool pressed) {
if (!pressed)
return;
throw 1;
}
static void PauseDOSBox(bool pressed) { static void PauseDOSBox(bool pressed) {
if (!pressed) if (!pressed)
return; return;
@ -263,15 +271,22 @@ static void PauseDOSBox(bool pressed) {
SDL_WaitEvent(&event); // since we're not polling, cpu usage drops to 0. SDL_WaitEvent(&event); // since we're not polling, cpu usage drops to 0.
switch (event.type) { switch (event.type) {
case SDL_QUIT: throw(0); break; case SDL_QUIT: KillSwitch(true); break;
case SDL_KEYDOWN: // Must use Pause/Break Key to resume. case SDL_KEYDOWN: // Must use Pause/Break Key to resume.
case SDL_KEYUP: case SDL_KEYUP:
if(event.key.keysym.sym==SDLK_PAUSE) { if(event.key.keysym.sym == SDLK_PAUSE) {
paused=false; paused = false;
GFX_SetTitle(-1,-1,false); GFX_SetTitle(-1,-1,false);
break; break;
} }
#if defined (MACOSX)
if (event.key.keysym.sym == SDLK_q && (event.key.keysym.mod == KMOD_RMETA || event.key.keysym.mod == KMOD_LMETA) ) {
/* On macs, all aps exit when pressing cmd-q */
KillSwitch(true);
break;
}
#endif
} }
} }
} }
@ -356,6 +371,16 @@ void GFX_ResetScreen(void) {
CPU_Reset_AutoAdjust(); CPU_Reset_AutoAdjust();
} }
void GFX_ForceFullscreenExit(void) {
if (sdl.desktop.lazy_fullscreen) {
// sdl.desktop.lazy_fullscreen_req=true;
LOG_MSG("GFX LF: invalid screen change");
} else {
sdl.desktop.fullscreen=false;
GFX_ResetScreen();
}
}
static int int_log2 (int val) { static int int_log2 (int val) {
int log = 0; int log = 0;
while ((val >>= 1) != 0) while ((val >>= 1) != 0)
@ -408,6 +433,16 @@ static SDL_Surface * GFX_SetupSurfaceScaled(Bit32u sdl_flags, Bit32u bpp) {
} }
} }
void GFX_TearDown(void) {
if (sdl.updating)
GFX_EndUpdate( 0 );
if (sdl.blit.surface) {
SDL_FreeSurface(sdl.blit.surface);
sdl.blit.surface=0;
}
}
Bitu GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_CallBack_t callback) { Bitu GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_CallBack_t callback) {
if (sdl.updating) if (sdl.updating)
GFX_EndUpdate( 0 ); GFX_EndUpdate( 0 );
@ -673,6 +708,18 @@ void GFX_CaptureMouse(void) {
mouselocked=sdl.mouse.locked; mouselocked=sdl.mouse.locked;
} }
void GFX_UpdateSDLCaptureState(void) {
if (sdl.mouse.locked) {
SDL_WM_GrabInput(SDL_GRAB_ON);
SDL_ShowCursor(SDL_DISABLE);
} else {
SDL_WM_GrabInput(SDL_GRAB_OFF);
if (sdl.mouse.autoenable || !sdl.mouse.autolock) SDL_ShowCursor(SDL_ENABLE);
}
CPU_Reset_AutoAdjust();
GFX_SetTitle(-1,-1,false);
}
bool mouselocked; //Global variable for mapper bool mouselocked; //Global variable for mapper
static void CaptureMouse(bool pressed) { static void CaptureMouse(bool pressed) {
if (!pressed) if (!pressed)
@ -680,12 +727,40 @@ static void CaptureMouse(bool pressed) {
GFX_CaptureMouse(); GFX_CaptureMouse();
} }
#if defined (WIN32)
STICKYKEYS stick_keys = {sizeof(STICKYKEYS), 0};
void sticky_keys(bool restore){
static bool inited = false;
if (!inited){
inited = true;
SystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &stick_keys, 0);
}
if (restore) {
SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &stick_keys, 0);
return;
}
//Get current sticky keys layout:
STICKYKEYS s = {sizeof(STICKYKEYS), 0};
SystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &s, 0);
if ( !(s.dwFlags & SKF_STICKYKEYSON)) { //Not on already
s.dwFlags &= ~SKF_HOTKEYACTIVE;
SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &s, 0);
}
}
#endif
void GFX_SwitchFullScreen(void) { void GFX_SwitchFullScreen(void) {
sdl.desktop.fullscreen=!sdl.desktop.fullscreen; sdl.desktop.fullscreen=!sdl.desktop.fullscreen;
if (sdl.desktop.fullscreen) { if (sdl.desktop.fullscreen) {
if (!sdl.mouse.locked) GFX_CaptureMouse(); if (!sdl.mouse.locked) GFX_CaptureMouse();
#if defined (WIN32)
sticky_keys(false); //disable sticky keys in fullscreen mode
#endif
} else { } else {
if (sdl.mouse.locked) GFX_CaptureMouse(); if (sdl.mouse.locked) GFX_CaptureMouse();
#if defined (WIN32)
sticky_keys(true); //restore sticky keys to default state in windowed mode.
#endif
} }
GFX_ResetScreen(); GFX_ResetScreen();
} }
@ -693,7 +768,32 @@ void GFX_SwitchFullScreen(void) {
static void SwitchFullScreen(bool pressed) { static void SwitchFullScreen(bool pressed) {
if (!pressed) if (!pressed)
return; return;
if (sdl.desktop.lazy_fullscreen) {
// sdl.desktop.lazy_fullscreen_req=true;
LOG_MSG("GFX LF: fullscreen switching not supported");
} else {
GFX_SwitchFullScreen(); GFX_SwitchFullScreen();
}
}
void GFX_SwitchLazyFullscreen(bool lazy) {
sdl.desktop.lazy_fullscreen=lazy;
sdl.desktop.lazy_fullscreen_req=false;
}
void GFX_SwitchFullscreenNoReset(void) {
sdl.desktop.fullscreen=!sdl.desktop.fullscreen;
}
bool GFX_LazyFullscreenRequested(void) {
if (sdl.desktop.lazy_fullscreen) return sdl.desktop.lazy_fullscreen_req;
return false;
}
void GFX_RestoreMode(void) {
GFX_SetSize(sdl.draw.width,sdl.draw.height,sdl.draw.flags,sdl.draw.scalex,sdl.draw.scaley,sdl.draw.callback);
GFX_UpdateSDLCaptureState();
} }
@ -907,11 +1007,6 @@ static void GUI_ShutDown(Section * /*sec*/) {
if (sdl.desktop.fullscreen) GFX_SwitchFullScreen(); if (sdl.desktop.fullscreen) GFX_SwitchFullScreen();
} }
static void KillSwitch(bool pressed) {
if (!pressed)
return;
throw 1;
}
static void SetPriority(PRIORITY_LEVELS level) { static void SetPriority(PRIORITY_LEVELS level) {
@ -1010,6 +1105,9 @@ static void GUI_StartUp(Section * sec) {
SDL_WM_SetIcon(logos,NULL); SDL_WM_SetIcon(logos,NULL);
#endif #endif
sdl.desktop.lazy_fullscreen=false;
sdl.desktop.lazy_fullscreen_req=false;
sdl.desktop.fullscreen=section->Get_bool("fullscreen"); sdl.desktop.fullscreen=section->Get_bool("fullscreen");
sdl.wait_on_error=section->Get_bool("waitonerror"); sdl.wait_on_error=section->Get_bool("waitonerror");
@ -1186,7 +1284,7 @@ static void GUI_StartUp(Section * sec) {
//#endif //#endif
/* Please leave the Splash screen stuff in working order in DOSBox. We spend a lot of time making DOSBox. */ /* Please leave the Splash screen stuff in working order in DOSBox. We spend a lot of time making DOSBox. */
/* #ifndef HW_RVL
SDL_Surface* splash_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, 640, 400, 32, rmask, gmask, bmask, 0); SDL_Surface* splash_surf = SDL_CreateRGBSurface(SDL_SWSURFACE, 640, 400, 32, rmask, gmask, bmask, 0);
if (splash_surf) { if (splash_surf) {
SDL_FillRect(splash_surf, NULL, SDL_MapRGB(splash_surf->format, 0, 0, 0)); SDL_FillRect(splash_surf, NULL, SDL_MapRGB(splash_surf->format, 0, 0, 0));
@ -1246,7 +1344,7 @@ static void GUI_StartUp(Section * sec) {
delete [] tmpbufp; delete [] tmpbufp;
} }
*/ #endif
/* Get some Event handlers */ /* Get some Event handlers */
MAPPER_AddHandler(KillSwitch,MK_f9,MMOD1,"shutdown","ShutDown"); MAPPER_AddHandler(KillSwitch,MK_f9,MMOD1,"shutdown","ShutDown");
MAPPER_AddHandler(CaptureMouse,MK_f10,MMOD1,"capmouse","Cap Mouse"); MAPPER_AddHandler(CaptureMouse,MK_f10,MMOD1,"capmouse","Cap Mouse");
@ -1327,6 +1425,10 @@ void GFX_LosingFocus(void) {
MAPPER_LosingFocus(); MAPPER_LosingFocus();
} }
bool GFX_IsFullscreen(void) {
return sdl.desktop.fullscreen;
}
void GFX_Events() { void GFX_Events() {
#ifdef HW_RVL #ifdef HW_RVL
// check for home button // check for home button
@ -1363,8 +1465,7 @@ void GFX_Events() {
#ifdef WIN32 #ifdef WIN32
if (sdl.desktop.fullscreen) { if (sdl.desktop.fullscreen) {
VGA_KillDrawing(); VGA_KillDrawing();
sdl.desktop.fullscreen=false; GFX_ForceFullscreenExit();
GFX_ResetScreen();
} }
#endif #endif
GFX_CaptureMouse(); GFX_CaptureMouse();
@ -1446,6 +1547,15 @@ void GFX_Events() {
if (event.key.keysym.sym==SDLK_RALT) sdl.raltstate = event.key.type; if (event.key.keysym.sym==SDLK_RALT) sdl.raltstate = event.key.type;
if (((event.key.keysym.sym==SDLK_TAB)) && if (((event.key.keysym.sym==SDLK_TAB)) &&
((sdl.laltstate==SDL_KEYDOWN) || (sdl.raltstate==SDL_KEYDOWN))) break; ((sdl.laltstate==SDL_KEYDOWN) || (sdl.raltstate==SDL_KEYDOWN))) break;
#endif
#if defined (MACOSX)
case SDL_KEYDOWN:
case SDL_KEYUP:
/* On macs CMD-Q is the default key to close an application */
if (event.key.keysym.sym == SDLK_q && (event.key.keysym.mod == KMOD_RMETA || event.key.keysym.mod == KMOD_LMETA) ) {
KillSwitch(true);
break;
}
#endif #endif
default: default:
void MAPPER_CheckEvent(SDL_Event * event); void MAPPER_CheckEvent(SDL_Event * event);
@ -1933,7 +2043,7 @@ int main(int argc, char* argv[]) {
Section_prop * sdl_sec=static_cast<Section_prop *>(control->GetSection("sdl")); Section_prop * sdl_sec=static_cast<Section_prop *>(control->GetSection("sdl"));
if (control->cmdline->FindExist("-fullscreen") || sdl_sec->Get_bool("fullscreen")) { if (control->cmdline->FindExist("-fullscreen") || sdl_sec->Get_bool("fullscreen")) {
if(!sdl.desktop.fullscreen) { //only switch if not allready in fullscreen if(!sdl.desktop.fullscreen) { //only switch if not already in fullscreen
GFX_SwitchFullScreen(); GFX_SwitchFullScreen();
} }
} }
@ -1957,6 +2067,9 @@ int main(int argc, char* argv[]) {
control->StartUp(); control->StartUp();
/* Shutdown everything */ /* Shutdown everything */
} catch (char * error) { } catch (char * error) {
#if defined (WIN32)
sticky_keys(true);
#endif
GFX_ShowMsg("Exit to error: %s",error); GFX_ShowMsg("Exit to error: %s",error);
fflush(NULL); fflush(NULL);
if(sdl.wait_on_error) { if(sdl.wait_on_error) {
@ -1975,11 +2088,17 @@ int main(int argc, char* argv[]) {
;//nothing pressed killswitch ;//nothing pressed killswitch
} }
catch(...){ catch(...){
#if defined (WIN32)
sticky_keys(true);
#endif
//Force visible mouse to end user. Somehow this sometimes doesn't happen //Force visible mouse to end user. Somehow this sometimes doesn't happen
SDL_WM_GrabInput(SDL_GRAB_OFF); SDL_WM_GrabInput(SDL_GRAB_OFF);
SDL_ShowCursor(SDL_ENABLE); SDL_ShowCursor(SDL_ENABLE);
throw;//dunno what happened. rethrow for sdl to catch throw;//dunno what happened. rethrow for sdl to catch
} }
#if defined (WIN32)
sticky_keys(true); //Might not be needed if the shutdown function switches to windowed mode, but it doesn't hurt
#endif
//Force visible mouse to end user. Somehow this sometimes doesn't happen //Force visible mouse to end user. Somehow this sometimes doesn't happen
SDL_WM_GrabInput(SDL_GRAB_OFF); SDL_WM_GrabInput(SDL_GRAB_OFF);
SDL_ShowCursor(SDL_ENABLE); SDL_ShowCursor(SDL_ENABLE);

View File

@ -323,7 +323,7 @@ void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags,
/* Open the actual file */ /* Open the actual file */
FILE * fp=OpenCaptureFile("Screenshot",".png"); FILE * fp=OpenCaptureFile("Screenshot",".png");
if (!fp) goto skip_shot; if (!fp) goto skip_shot;
/* First try to alloacte the png structures */ /* First try to allocate the png structures */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL);
if (!png_ptr) goto skip_shot; if (!png_ptr) goto skip_shot;
info_ptr = png_create_info_struct(png_ptr); info_ptr = png_create_info_struct(png_ptr);
@ -359,7 +359,23 @@ void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags,
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
} }
#ifdef PNG_TEXT_SUPPORTED
int fields = 1;
png_text text[1];
const char* text_s = "DOSBox " VERSION;
size_t strl = strlen(text_s);
char* ptext_s = new char[strl + 1];
strcpy(ptext_s, text_s);
char software[9] = { 'S','o','f','t','w','a','r','e',0};
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
text[0].key = software;
text[0].text = ptext_s;
png_set_text(png_ptr, info_ptr, text, fields);
#endif
png_write_info(png_ptr, info_ptr); png_write_info(png_ptr, info_ptr);
#ifdef PNG_TEXT_SUPPORTED
delete [] ptext_s;
#endif
for (i=0;i<height;i++) { for (i=0;i<height;i++) {
void *rowPointer; void *rowPointer;
void *srcLine; void *srcLine;

View File

@ -347,13 +347,16 @@ void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed) {
} }
/* Add the actual key in the keyboard queue */ /* Add the actual key in the keyboard queue */
if (pressed) { if (pressed) {
if (keyb.repeat.key==keytype) keyb.repeat.wait=keyb.repeat.rate; if (keyb.repeat.key == keytype) keyb.repeat.wait = keyb.repeat.rate;
else keyb.repeat.wait=keyb.repeat.pause; else keyb.repeat.wait = keyb.repeat.pause;
keyb.repeat.key=keytype; keyb.repeat.key = keytype;
} else { } else {
keyb.repeat.key=KBD_NONE; if (keyb.repeat.key == keytype) {
keyb.repeat.wait=0; /* repeated key being released */
ret+=128; keyb.repeat.key = KBD_NONE;
keyb.repeat.wait = 0;
}
ret += 128;
} }
if (extend) KEYBOARD_AddBuffer(0xe0); if (extend) KEYBOARD_AddBuffer(0xe0);
KEYBOARD_AddBuffer(ret); KEYBOARD_AddBuffer(ret);

View File

@ -601,7 +601,7 @@ MixerChannel* MixerObject::Install(MIXER_Handler handler,Bitu freq,const char *
installed = true; installed = true;
return MIXER_AddChannel(handler,freq,name); return MIXER_AddChannel(handler,freq,name);
} else { } else {
E_Exit("allready added mixer channel."); E_Exit("already added mixer channel.");
return 0; //Compiler happy return 0; //Compiler happy
} }
} }

View File

@ -131,6 +131,12 @@ static Bit8u read_pci_register(PCI_Device* dev,Bit8u regnum) {
if ((parsed_regnum>=0) && (parsed_regnum<256)) if ((parsed_regnum>=0) && (parsed_regnum<256))
return pci_cfg_data[dev->PCIId()][dev->PCISubfunction()][parsed_regnum]; return pci_cfg_data[dev->PCIId()][dev->PCISubfunction()][parsed_regnum];
Bit8u newval, mask;
if (dev->OverrideReadRegister(regnum, &newval, &mask)) {
Bit8u oldval=pci_cfg_data[dev->PCIId()][dev->PCISubfunction()][regnum] & (~mask);
return oldval | (newval & mask);
}
return 0xff; return 0xff;
} }

View File

@ -871,6 +871,11 @@ static void DSP_DoCommand(void) {
case 0x76: /* 074h : Single Cycle 3-bit(2.6bit) ADPCM */ case 0x76: /* 074h : Single Cycle 3-bit(2.6bit) ADPCM */
DSP_PrepareDMA_Old(DSP_DMA_3,false,false); DSP_PrepareDMA_Old(DSP_DMA_3,false,false);
break; break;
case 0x7d: /* Auto Init 4-bit ADPCM Reference */
DSP_SB2_ABOVE;
sb.adpcm.haveref=true;
DSP_PrepareDMA_Old(DSP_DMA_4,true,false);
break;
case 0x17: /* 017h : Single Cycle 2-bit ADPCM Reference*/ case 0x17: /* 017h : Single Cycle 2-bit ADPCM Reference*/
sb.adpcm.haveref=true; sb.adpcm.haveref=true;
case 0x16: /* 074h : Single Cycle 2-bit ADPCM */ case 0x16: /* 074h : Single Cycle 2-bit ADPCM */
@ -996,7 +1001,7 @@ static void DSP_DoCommand(void) {
DSP_SB2_ABOVE; DSP_SB2_ABOVE;
LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented MIDI UART command %2X",sb.dsp.cmd); LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented MIDI UART command %2X",sb.dsp.cmd);
break; break;
case 0x7d: case 0x7f: case 0x1f: case 0x7f: case 0x1f:
DSP_SB2_ABOVE; DSP_SB2_ABOVE;
LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented auto-init DMA ADPCM command %2X",sb.dsp.cmd); LOG(LOG_SB,LOG_ERROR)("DSP:Unimplemented auto-init DMA ADPCM command %2X",sb.dsp.cmd);
break; break;
@ -1158,10 +1163,15 @@ static void CTMIXER_Write(Bit8u val) {
break; break;
case 0x08: /* CDA Volume (SB2 Only) */ case 0x08: /* CDA Volume (SB2 Only) */
SETPROVOL(sb.mixer.cda,(val&0xf)|(val<<4)); SETPROVOL(sb.mixer.cda,(val&0xf)|(val<<4));
CTMIXER_UpdateVolumes();
break; break;
case 0x0a: /* Mic Level (SBPRO) or DAC Volume (SB2): 2-bit, 3-bit on SB16 */ case 0x0a: /* Mic Level (SBPRO) or DAC Volume (SB2): 2-bit, 3-bit on SB16 */
if (sb.type==SBT_2) sb.mixer.dac[0]=sb.mixer.dac[1]=((val & 0x6) << 2)|3; if (sb.type==SBT_2) {
else sb.mixer.mic=((val & 0x7) << 2)|(sb.type==SBT_16?1:3); sb.mixer.dac[0]=sb.mixer.dac[1]=((val & 0x6) << 2)|3;
CTMIXER_UpdateVolumes();
} else {
sb.mixer.mic=((val & 0x7) << 2)|(sb.type==SBT_16?1:3);
}
break; break;
case 0x0e: /* Output/Stereo Select */ case 0x0e: /* Output/Stereo Select */
sb.mixer.stereo=(val & 0x2) > 0; sb.mixer.stereo=(val & 0x2) > 0;
@ -1179,6 +1189,7 @@ static void CTMIXER_Write(Bit8u val) {
break; break;
case 0x28: /* CD Audio Volume (SBPRO) */ case 0x28: /* CD Audio Volume (SBPRO) */
SETPROVOL(sb.mixer.cda,val); SETPROVOL(sb.mixer.cda,val);
CTMIXER_UpdateVolumes();
break; break;
case 0x2e: /* Line-in Volume (SBPRO) */ case 0x2e: /* Line-in Volume (SBPRO) */
SETPROVOL(sb.mixer.lin,val); SETPROVOL(sb.mixer.lin,val);

View File

@ -197,7 +197,7 @@ int SERIAL_getextchar(COMPORT port) {
char chRead; char chRead;
int retval = 0; int retval = 0;
// receive a byte; TODO communicate faliure // receive a byte; TODO communicate failure
if (ReadFile (port->porthandle, &chRead, 1, &dwRead, NULL)) { if (ReadFile (port->porthandle, &chRead, 1, &dwRead, NULL)) {
if (dwRead) { if (dwRead) {
// check for errors // check for errors
@ -580,7 +580,7 @@ int SERIAL_getextchar(COMPORT port) {
char chRead; char chRead;
int retval = 0; int retval = 0;
// receive a byte; TODO communicate faliure // receive a byte; TODO communicate failure
if (DosRead(port->porthandle, &chRead, 1, &dwRead) == NO_ERROR) { if (DosRead(port->porthandle, &chRead, 1, &dwRead) == NO_ERROR) {
if (dwRead) { if (dwRead) {
// check for errors; will OS/2 clear the error on reading its data? // check for errors; will OS/2 clear the error on reading its data?

View File

@ -52,87 +52,59 @@ CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) {
// 1) when it is client connect to the server not immediately but // 1) when it is client connect to the server not immediately but
// as soon as a modem-aware application is started (DTR is switched on). // as soon as a modem-aware application is started (DTR is switched on).
// 2) only receive data when DTR is on. // 2) only receive data when DTR is on.
if(getBituSubstring("usedtr:", &bool_temp, cmd)) { if (getBituSubstring("usedtr:", &bool_temp, cmd)) {
if(bool_temp==1) { if (bool_temp==1) {
dtrrespect=true; dtrrespect=true;
transparent=true; transparent=true;
DTR_delta=false; // connect immediately when DTR is already 1
} }
} }
// transparent: don't add additional handshake control. // transparent: don't add additional handshake control.
if(getBituSubstring("transparent:", &bool_temp, cmd)) { if (getBituSubstring("transparent:", &bool_temp, cmd)) {
if(bool_temp==1) transparent=true; if (bool_temp==1) transparent=true;
else transparent=false; else transparent=false;
} }
// telnet: interpret telnet commands. // telnet: interpret telnet commands.
if(getBituSubstring("telnet:", &bool_temp, cmd)) { if (getBituSubstring("telnet:", &bool_temp, cmd)) {
if(bool_temp==1) { if (bool_temp==1) {
transparent=true; transparent=true;
telnet=true; telnet=true;
} }
} }
// rxdelay: How many milliseconds to wait before causing an // rxdelay: How many milliseconds to wait before causing an
// overflow when the application is unresponsive. // overflow when the application is unresponsive.
if(getBituSubstring("rxdelay:", &rx_retry_max, cmd)) { if (getBituSubstring("rxdelay:", &rx_retry_max, cmd)) {
if(!(rx_retry_max<=10000)) { if (!(rx_retry_max<=10000)) {
rx_retry_max=50; rx_retry_max=50;
} }
} }
// txdelay: How many milliseconds to wait before sending data. // txdelay: How many milliseconds to wait before sending data.
// This reduces network overhead quite a lot. // This reduces network overhead quite a lot.
if(getBituSubstring("txdelay:", &tx_gather, cmd)) { if (getBituSubstring("txdelay:", &tx_gather, cmd)) {
if(!(tx_gather<=500)) { if (!(tx_gather<=500)) {
tx_gather=12; tx_gather=12;
} }
} }
// port is for both server and client // port is for both server and client
if(getBituSubstring("port:", &temptcpport, cmd)) { if (getBituSubstring("port:", &temptcpport, cmd)) {
if(!(temptcpport>0&&temptcpport<65536)) { if (!(temptcpport>0&&temptcpport<65536)) {
temptcpport=23; temptcpport=23;
} }
} }
// socket inheritance // socket inheritance (client-alike)
if(getBituSubstring("inhsocket:", &bool_temp, cmd)) { if (getBituSubstring("inhsocket:", &bool_temp, cmd)) {
#ifdef NATIVESOCKETS #ifdef NATIVESOCKETS
if(Netwrapper_GetCapabilities()&NETWRAPPER_TCP_NATIVESOCKET) { if (Netwrapper_GetCapabilities()&NETWRAPPER_TCP_NATIVESOCKET) {
if(bool_temp==1) { if (bool_temp==1) {
int sock; int sock;
if (control->cmdline->FindInt("-socket",sock,true)) { if (control->cmdline->FindInt("-socket",sock,true)) {
dtrrespect=false; dtrrespect=false;
transparent=true; transparent=true;
// custom connect LOG_MSG("Inheritance socket handle: %d",sock);
Bit8u peernamebuf[16]; if (!ClientConnect(new TCPClientSocket(sock)))
LOG_MSG("inheritance port: %d",sock);
clientsocket = new TCPClientSocket(sock);
if(!clientsocket->isopen) {
LOG_MSG("Serial%d: Connection failed.",COMNUMBER);
#if SERIAL_DEBUG
log_ser(dbg_aux,"Nullmodem: Connection failed.");
#endif
delete clientsocket;
clientsocket=0;
return;
}
clientsocket->SetSendBufferSize(256);
clientsocket->GetRemoteAddressString(peernamebuf);
// transmit the line status
if(!transparent) setRTSDTR(getRTS(), getDTR());
LOG_MSG("Serial%d: Connected to %s",COMNUMBER,peernamebuf);
#if SERIAL_DEBUG
log_ser(dbg_aux,"Nullmodem: Connected to %s",peernamebuf);
#endif
setEvent(SERIAL_POLLING_EVENT, 1);
CSerial::Init_Registers ();
InstallationSuccessful = true;
setCTS(true);
setDSR(true);
setRI (false);
setCD (true);
return; return;
} else { } else {
LOG_MSG("Serial%d: -socket start parameter missing.",COMNUMBER); LOG_MSG("Serial%d: -socket parameter missing.",COMNUMBER);
return; return;
} }
} }
@ -144,47 +116,44 @@ CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) {
#else #else
LOG_MSG("Serial%d: socket inheritance not available.", COMNUMBER); LOG_MSG("Serial%d: socket inheritance not available.", COMNUMBER);
#endif #endif
} } else {
// normal server/client
std::string tmpstring; std::string tmpstring;
if(cmd->FindStringBegin("server:",tmpstring,false)) { if (cmd->FindStringBegin("server:",tmpstring,false)) {
// we are a client // we are a client
const char* hostnamechar=tmpstring.c_str(); const char* hostnamechar=tmpstring.c_str();
size_t hostlen=strlen(hostnamechar)+1; size_t hostlen=strlen(hostnamechar)+1;
if(hostlen>sizeof(hostnamebuffer)) { if (hostlen>sizeof(hostnamebuffer)) {
hostlen=sizeof(hostnamebuffer); hostlen=sizeof(hostnamebuffer);
hostnamebuffer[sizeof(hostnamebuffer)-1]=0; hostnamebuffer[sizeof(hostnamebuffer)-1]=0;
} }
memcpy(hostnamebuffer,hostnamechar,hostlen); memcpy(hostnamebuffer,hostnamechar,hostlen);
clientport=(Bit16u)temptcpport; clientport=(Bit16u)temptcpport;
if(dtrrespect) { if (dtrrespect) {
// we connect as soon as DTR is switched on // we connect as soon as DTR is switched on
setEvent(SERIAL_NULLMODEM_DTR_EVENT, 50); setEvent(SERIAL_NULLMODEM_DTR_EVENT, 50);
LOG_MSG("Serial%d: Waiting for DTR...",COMNUMBER); LOG_MSG("Serial%d: Waiting for DTR...",COMNUMBER);
} else ClientConnect(); } else if (!ClientConnect(
new TCPClientSocket((char*)hostnamebuffer,(Bit16u)clientport)))
return;
} else { } else {
// we are a server // we are a server
serverport = (Bit16u)temptcpport; serverport = (Bit16u)temptcpport;
serversocket = new TCPServerSocket(serverport); if (!ServerListen()) return;
if(!serversocket->isopen) return;
LOG_MSG("Serial%d: Nullmodem server waiting for connection on port %d...",
COMNUMBER,serverport);
setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
} }
}
// .... CSerial::Init_Registers();
CSerial::Init_Registers ();
InstallationSuccessful = true; InstallationSuccessful = true;
setCTS(dtrrespect||transparent); setCTS(dtrrespect||transparent);
setDSR(dtrrespect||transparent); setDSR(dtrrespect||transparent);
setRI (false); setRI(false);
setCD (dtrrespect); setCD(clientsocket > 0); // CD on if connection established
} }
CNullModem::~CNullModem () { CNullModem::~CNullModem() {
if(serversocket) delete serversocket; if (serversocket) delete serversocket;
if(clientsocket) delete clientsocket; if (clientsocket) delete clientsocket;
// remove events // remove events
for(Bit16u i = SERIAL_BASE_EVENT_COUNT+1; for(Bit16u i = SERIAL_BASE_EVENT_COUNT+1;
i <= SERIAL_NULLMODEM_EVENT_COUNT; i++) { i <= SERIAL_NULLMODEM_EVENT_COUNT; i++) {
@ -193,9 +162,8 @@ CNullModem::~CNullModem () {
} }
void CNullModem::WriteChar(Bit8u data) { void CNullModem::WriteChar(Bit8u data) {
if (clientsocket)clientsocket->SendByteBuffered(data);
if(clientsocket)clientsocket->SendByteBuffered(data); if (!tx_block) {
if(!tx_block) {
//LOG_MSG("setevreduct"); //LOG_MSG("setevreduct");
setEvent(SERIAL_TX_REDUCTION, (float)tx_gather); setEvent(SERIAL_TX_REDUCTION, (float)tx_gather);
tx_block=true; tx_block=true;
@ -203,37 +171,75 @@ void CNullModem::WriteChar(Bit8u data) {
} }
Bits CNullModem::readChar() { Bits CNullModem::readChar() {
Bits rxchar = clientsocket->GetcharNonBlock(); Bits rxchar = clientsocket->GetcharNonBlock();
if(telnet && rxchar>=0) return TelnetEmulation((Bit8u)rxchar); if (telnet && rxchar>=0) return TelnetEmulation((Bit8u)rxchar);
else if(rxchar==0xff && !transparent) {// escape char else if (rxchar==0xff && !transparent) {// escape char
// get the next char // get the next char
Bits rxchar = clientsocket->GetcharNonBlock(); Bits rxchar = clientsocket->GetcharNonBlock();
if(rxchar==0xff) return rxchar; // 0xff 0xff -> 0xff was meant if (rxchar==0xff) return rxchar; // 0xff 0xff -> 0xff was meant
rxchar&0x1? setCTS(true) : setCTS(false); rxchar&0x1? setCTS(true) : setCTS(false);
rxchar&0x2? setDSR(true) : setDSR(false); rxchar&0x2? setDSR(true) : setDSR(false);
if(rxchar&0x4) receiveByteEx(0x0,0x10); if (rxchar&0x4) receiveByteEx(0x0,0x10);
return -1; // no "payload" received return -1; // no "payload" received
} else return rxchar; } else return rxchar;
} }
void CNullModem::ClientConnect(){ bool CNullModem::ClientConnect(TCPClientSocket* newsocket) {
Bit8u peernamebuf[16]; Bit8u peernamebuf[16];
clientsocket = new TCPClientSocket((char*)hostnamebuffer, clientsocket = newsocket;
(Bit16u)clientport);
if(!clientsocket->isopen) { if (!clientsocket->isopen) {
LOG_MSG("Serial%d: Connection failed.",idnumber+1); LOG_MSG("Serial%d: Connection failed.",COMNUMBER);
delete clientsocket; delete clientsocket;
clientsocket=0; clientsocket=0;
return; setCD(false);
return false;
} }
clientsocket->SetSendBufferSize(256); clientsocket->SetSendBufferSize(256);
clientsocket->GetRemoteAddressString(peernamebuf); clientsocket->GetRemoteAddressString(peernamebuf);
// transmit the line status // transmit the line status
if(!transparent) setRTSDTR(getRTS(), getDTR()); if (!transparent) setRTSDTR(getRTS(), getDTR());
rx_state=N_RX_IDLE; rx_state=N_RX_IDLE;
LOG_MSG("Serial%d: Connected to %s",idnumber+1,peernamebuf); LOG_MSG("Serial%d: Connected to %s",COMNUMBER,peernamebuf);
setEvent(SERIAL_POLLING_EVENT, 1); setEvent(SERIAL_POLLING_EVENT, 1);
setCD(true);
return true;
}
bool CNullModem::ServerListen() {
// Start the server listen port.
serversocket = new TCPServerSocket(serverport);
if (!serversocket->isopen) return false;
LOG_MSG("Serial%d: Nullmodem server waiting for connection on port %d...",
COMNUMBER,serverport);
setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
setCD(false);
return true;
}
bool CNullModem::ServerConnect() {
// check if a connection is available.
clientsocket=serversocket->Accept();
if (!clientsocket) return false;
Bit8u peeripbuf[16];
clientsocket->GetRemoteAddressString(peeripbuf);
LOG_MSG("Serial%d: A client (%s) has connected.",COMNUMBER,peeripbuf);
#if SERIAL_DEBUG
log_ser(dbg_aux,"Nullmodem: A client (%s) has connected.", peeripbuf);
#endif
clientsocket->SetSendBufferSize(256);
rx_state=N_RX_IDLE;
setEvent(SERIAL_POLLING_EVENT, 1);
// we don't accept further connections
delete serversocket;
serversocket=0;
// transmit the line status
setRTSDTR(getRTS(), getDTR());
if (transparent) setCD(true);
return true;
} }
void CNullModem::Disconnect() { void CNullModem::Disconnect() {
@ -245,11 +251,16 @@ void CNullModem::Disconnect() {
clientsocket=0; clientsocket=0;
setDSR(false); setDSR(false);
setCTS(false); setCTS(false);
if(serverport) { setCD(false);
if (serverport) {
serversocket = new TCPServerSocket(serverport); serversocket = new TCPServerSocket(serverport);
if(serversocket->isopen) if (serversocket->isopen)
setEvent(SERIAL_SERVER_POLLING_EVENT, 50); setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
else delete serversocket; else delete serversocket;
} else if (dtrrespect) {
setEvent(SERIAL_NULLMODEM_DTR_EVENT,50);
DTR_delta = getDTR(); // try to reconnect the next time DTR is set
} }
} }
@ -264,8 +275,8 @@ void CNullModem::handleUpperEvent(Bit16u type) {
updateMSR(); updateMSR();
switch(rx_state) { switch(rx_state) {
case N_RX_IDLE: case N_RX_IDLE:
if(CanReceiveByte()) { if (CanReceiveByte()) {
if(doReceive()) { if (doReceive()) {
// a byte was received // a byte was received
rx_state=N_RX_WAIT; rx_state=N_RX_WAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.9f); setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
@ -281,13 +292,13 @@ void CNullModem::handleUpperEvent(Bit16u type) {
break; break;
case N_RX_BLOCKED: case N_RX_BLOCKED:
// one timeout tick // one timeout tick
if(!CanReceiveByte()) { if (!CanReceiveByte()) {
rx_retry++; rx_retry++;
if(rx_retry>=rx_retry_max) { if (rx_retry>=rx_retry_max) {
// it has timed out: // it has timed out:
rx_retry=0; rx_retry=0;
removeEvent(SERIAL_RX_EVENT); removeEvent(SERIAL_RX_EVENT);
if(doReceive()) { if (doReceive()) {
// read away everything // read away everything
while(doReceive()); while(doReceive());
rx_state=N_RX_WAIT; rx_state=N_RX_WAIT;
@ -304,7 +315,7 @@ void CNullModem::handleUpperEvent(Bit16u type) {
// good: we can receive again // good: we can receive again
removeEvent(SERIAL_RX_EVENT); removeEvent(SERIAL_RX_EVENT);
rx_retry=0; rx_retry=0;
if(doReceive()) { if (doReceive()) {
rx_state=N_RX_FASTWAIT; rx_state=N_RX_FASTWAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.65f); setEvent(SERIAL_RX_EVENT, bytetime*0.65f);
} else { } else {
@ -329,11 +340,11 @@ void CNullModem::handleUpperEvent(Bit16u type) {
case N_RX_BLOCKED: // try to receive case N_RX_BLOCKED: // try to receive
case N_RX_WAIT: case N_RX_WAIT:
case N_RX_FASTWAIT: case N_RX_FASTWAIT:
if(CanReceiveByte()) { if (CanReceiveByte()) {
// just works or unblocked // just works or unblocked
if(doReceive()) { if (doReceive()) {
rx_retry=0; // not waiting anymore rx_retry=0; // not waiting anymore
if(rx_state==N_RX_WAIT) setEvent(SERIAL_RX_EVENT, bytetime*0.9f); if (rx_state==N_RX_WAIT) setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
else { else {
// maybe unblocked // maybe unblocked
rx_state=N_RX_FASTWAIT; rx_state=N_RX_FASTWAIT;
@ -347,7 +358,7 @@ void CNullModem::handleUpperEvent(Bit16u type) {
} else { } else {
// blocking now or still blocked // blocking now or still blocked
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(rx_state==N_RX_BLOCKED) if (rx_state==N_RX_BLOCKED)
log_ser(dbg_aux,"Nullmodem: rx still blocked (retry=%d)",rx_retry); log_ser(dbg_aux,"Nullmodem: rx still blocked (retry=%d)",rx_retry);
else log_ser(dbg_aux,"Nullmodem: block on continued rx (retry=%d).",rx_retry); else log_ser(dbg_aux,"Nullmodem: block on continued rx (retry=%d).",rx_retry);
#endif #endif
@ -361,8 +372,8 @@ void CNullModem::handleUpperEvent(Bit16u type) {
} }
case SERIAL_TX_EVENT: { case SERIAL_TX_EVENT: {
// Maybe echo cirquit works a bit better this way // Maybe echo cirquit works a bit better this way
if(rx_state==N_RX_IDLE && CanReceiveByte() && clientsocket) { if (rx_state==N_RX_IDLE && CanReceiveByte() && clientsocket) {
if(doReceive()) { if (doReceive()) {
// a byte was received // a byte was received
rx_state=N_RX_WAIT; rx_state=N_RX_WAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.9f); setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
@ -380,25 +391,7 @@ void CNullModem::handleUpperEvent(Bit16u type) {
case SERIAL_SERVER_POLLING_EVENT: { case SERIAL_SERVER_POLLING_EVENT: {
// As long as nothing is connected to our server poll the // As long as nothing is connected to our server poll the
// connection. // connection.
clientsocket=serversocket->Accept(); if (!ServerConnect()) {
if(clientsocket) {
Bit8u peeripbuf[16];
clientsocket->GetRemoteAddressString(peeripbuf);
LOG_MSG("Serial%d: A client (%s) has connected.",COMNUMBER,peeripbuf);
#if SERIAL_DEBUG
log_ser(dbg_aux,"Nullmodem: A client (%s) has connected.", peeripbuf);
#endif// new socket found...
clientsocket->SetSendBufferSize(256);
rx_state=N_RX_IDLE;
setEvent(SERIAL_POLLING_EVENT, 1);
// we don't accept further connections
delete serversocket;
serversocket=0;
// transmit the line status
setRTSDTR(getRTS(), getDTR());
} else {
// continue looking // continue looking
setEvent(SERIAL_SERVER_POLLING_EVENT, 50); setEvent(SERIAL_SERVER_POLLING_EVENT, 50);
} }
@ -406,13 +399,19 @@ void CNullModem::handleUpperEvent(Bit16u type) {
} }
case SERIAL_TX_REDUCTION: { case SERIAL_TX_REDUCTION: {
// Flush the data in the transmitting buffer. // Flush the data in the transmitting buffer.
if(clientsocket) clientsocket->FlushBuffer(); if (clientsocket) clientsocket->FlushBuffer();
tx_block=false; tx_block=false;
break; break;
} }
case SERIAL_NULLMODEM_DTR_EVENT: { case SERIAL_NULLMODEM_DTR_EVENT: {
if(getDTR()) ClientConnect(); if ((!DTR_delta) && getDTR()) {
else setEvent(SERIAL_NULLMODEM_DTR_EVENT,50); // DTR went positive. Try to connect.
if (ClientConnect(new TCPClientSocket((char*)hostnamebuffer,
(Bit16u)clientport)))
break; // no more DTR wait event when connected
}
DTR_delta = getDTR();
setEvent(SERIAL_NULLMODEM_DTR_EVENT,50);
break; break;
} }
} }
@ -432,11 +431,11 @@ void CNullModem::updateMSR () {
bool CNullModem::doReceive () { bool CNullModem::doReceive () {
Bits rxchar = readChar(); Bits rxchar = readChar();
if(rxchar>=0) { if (rxchar>=0) {
receiveByteEx((Bit8u)rxchar,0); receiveByteEx((Bit8u)rxchar,0);
return true; return true;
} }
else if(rxchar==-2) { else if (rxchar==-2) {
Disconnect(); Disconnect();
} }
return false; return false;
@ -444,7 +443,7 @@ bool CNullModem::doReceive () {
void CNullModem::transmitByte (Bit8u val, bool first) { void CNullModem::transmitByte (Bit8u val, bool first) {
// transmit it later in THR_Event // transmit it later in THR_Event
if(first) setEvent(SERIAL_THR_EVENT, bytetime/8); if (first) setEvent(SERIAL_THR_EVENT, bytetime/8);
else setEvent(SERIAL_TX_EVENT, bytetime); else setEvent(SERIAL_TX_EVENT, bytetime);
// disable 0xff escaping when transparent mode is enabled // disable 0xff escaping when transparent mode is enabled
@ -455,73 +454,73 @@ void CNullModem::transmitByte (Bit8u val, bool first) {
Bits CNullModem::TelnetEmulation(Bit8u data) { Bits CNullModem::TelnetEmulation(Bit8u data) {
Bit8u response[3]; Bit8u response[3];
if(telClient.inIAC) { if (telClient.inIAC) {
if(telClient.recCommand) { if (telClient.recCommand) {
if((data != 0) && (data != 1) && (data != 3)) { if ((data != 0) && (data != 1) && (data != 3)) {
LOG_MSG("Serial%d: Unrecognized telnet option %d",COMNUMBER, data); LOG_MSG("Serial%d: Unrecognized telnet option %d",COMNUMBER, data);
if(telClient.command>250) { if (telClient.command>250) {
/* Reject anything we don't recognize */ /* Reject anything we don't recognize */
response[0]=0xff; response[0]=0xff;
response[1]=252; response[1]=252;
response[2]=data; /* We won't do crap! */ response[2]=data; /* We won't do crap! */
if(clientsocket) clientsocket->SendArray(response, 3); if (clientsocket) clientsocket->SendArray(response, 3);
} }
} }
switch(telClient.command) { switch(telClient.command) {
case 251: /* Will */ case 251: /* Will */
if(data == 0) telClient.binary[TEL_SERVER] = true; if (data == 0) telClient.binary[TEL_SERVER] = true;
if(data == 1) telClient.echo[TEL_SERVER] = true; if (data == 1) telClient.echo[TEL_SERVER] = true;
if(data == 3) telClient.supressGA[TEL_SERVER] = true; if (data == 3) telClient.supressGA[TEL_SERVER] = true;
break; break;
case 252: /* Won't */ case 252: /* Won't */
if(data == 0) telClient.binary[TEL_SERVER] = false; if (data == 0) telClient.binary[TEL_SERVER] = false;
if(data == 1) telClient.echo[TEL_SERVER] = false; if (data == 1) telClient.echo[TEL_SERVER] = false;
if(data == 3) telClient.supressGA[TEL_SERVER] = false; if (data == 3) telClient.supressGA[TEL_SERVER] = false;
break; break;
case 253: /* Do */ case 253: /* Do */
if(data == 0) { if (data == 0) {
telClient.binary[TEL_CLIENT] = true; telClient.binary[TEL_CLIENT] = true;
response[0]=0xff; response[0]=0xff;
response[1]=251; response[1]=251;
response[2]=0; /* Will do binary transfer */ response[2]=0; /* Will do binary transfer */
if(clientsocket) clientsocket->SendArray(response, 3); if (clientsocket) clientsocket->SendArray(response, 3);
} }
if(data == 1) { if (data == 1) {
telClient.echo[TEL_CLIENT] = false; telClient.echo[TEL_CLIENT] = false;
response[0]=0xff; response[0]=0xff;
response[1]=252; response[1]=252;
response[2]=1; /* Won't echo (too lazy) */ response[2]=1; /* Won't echo (too lazy) */
if(clientsocket) clientsocket->SendArray(response, 3); if (clientsocket) clientsocket->SendArray(response, 3);
} }
if(data == 3) { if (data == 3) {
telClient.supressGA[TEL_CLIENT] = true; telClient.supressGA[TEL_CLIENT] = true;
response[0]=0xff; response[0]=0xff;
response[1]=251; response[1]=251;
response[2]=3; /* Will Suppress GA */ response[2]=3; /* Will Suppress GA */
if(clientsocket) clientsocket->SendArray(response, 3); if (clientsocket) clientsocket->SendArray(response, 3);
} }
break; break;
case 254: /* Don't */ case 254: /* Don't */
if(data == 0) { if (data == 0) {
telClient.binary[TEL_CLIENT] = false; telClient.binary[TEL_CLIENT] = false;
response[0]=0xff; response[0]=0xff;
response[1]=252; response[1]=252;
response[2]=0; /* Won't do binary transfer */ response[2]=0; /* Won't do binary transfer */
if(clientsocket) clientsocket->SendArray(response, 3); if (clientsocket) clientsocket->SendArray(response, 3);
} }
if(data == 1) { if (data == 1) {
telClient.echo[TEL_CLIENT] = false; telClient.echo[TEL_CLIENT] = false;
response[0]=0xff; response[0]=0xff;
response[1]=252; response[1]=252;
response[2]=1; /* Won't echo (fine by me) */ response[2]=1; /* Won't echo (fine by me) */
if(clientsocket) clientsocket->SendArray(response, 3); if (clientsocket) clientsocket->SendArray(response, 3);
} }
if(data == 3) { if (data == 3) {
telClient.supressGA[TEL_CLIENT] = true; telClient.supressGA[TEL_CLIENT] = true;
response[0]=0xff; response[0]=0xff;
response[1]=251; response[1]=251;
response[2]=3; /* Will Suppress GA (too lazy) */ response[2]=3; /* Will Suppress GA (too lazy) */
if(clientsocket) clientsocket->SendArray(response, 3); if (clientsocket) clientsocket->SendArray(response, 3);
} }
break; break;
default: default:
@ -532,7 +531,7 @@ Bits CNullModem::TelnetEmulation(Bit8u data) {
telClient.recCommand = false; telClient.recCommand = false;
return -1; //continue; return -1; //continue;
} else { } else {
if(data==249) { if (data==249) {
/* Go Ahead received */ /* Go Ahead received */
telClient.inIAC = false; telClient.inIAC = false;
return -1; //continue; return -1; //continue;
@ -540,7 +539,7 @@ Bits CNullModem::TelnetEmulation(Bit8u data) {
telClient.command = data; telClient.command = data;
telClient.recCommand = true; telClient.recCommand = true;
if((telClient.binary[TEL_SERVER]) && (data == 0xff)) { if ((telClient.binary[TEL_SERVER]) && (data == 0xff)) {
/* Binary data with value of 255 */ /* Binary data with value of 255 */
telClient.inIAC = false; telClient.inIAC = false;
telClient.recCommand = false; telClient.recCommand = false;
@ -548,7 +547,7 @@ Bits CNullModem::TelnetEmulation(Bit8u data) {
} }
} }
} else { } else {
if(data == 0xff) { if (data == 0xff) {
telClient.inIAC = true; telClient.inIAC = true;
return -1; return -1;
} }
@ -570,14 +569,14 @@ void CNullModem::setBreak (bool /*value*/) {
/* updateModemControlLines(mcr) sets DTR and RTS. **/ /* updateModemControlLines(mcr) sets DTR and RTS. **/
/*****************************************************************************/ /*****************************************************************************/
void CNullModem::setRTSDTR(bool xrts, bool xdtr) { void CNullModem::setRTSDTR(bool xrts, bool xdtr) {
if(!transparent) { if (!transparent) {
Bit8u control[2]; Bit8u control[2];
control[0]=0xff; control[0]=0xff;
control[1]=0x0; control[1]=0x0;
if(xrts) control[1]|=1; if (xrts) control[1]|=1;
if(xdtr) control[1]|=2; if (xdtr) control[1]|=2;
if(LCR&LCR_BREAK_MASK) control[1]|=4; if (LCR&LCR_BREAK_MASK) control[1]|=4;
if(clientsocket) clientsocket->SendArray(control, 2); if (clientsocket) clientsocket->SendArray(control, 2);
} }
} }
void CNullModem::setRTS(bool val) { void CNullModem::setRTS(bool val) {

View File

@ -35,16 +35,8 @@
class CNullModem : public CSerial { class CNullModem : public CSerial {
public: public:
TCPServerSocket* serversocket;
TCPClientSocket* clientsocket;
CNullModem(Bitu id, CommandLine* cmd); CNullModem(Bitu id, CommandLine* cmd);
~CNullModem(); ~CNullModem();
bool receiveblock; // It's not a block of data it rather blocks
Bit16u serverport; // we are a server if this is nonzero
Bit16u clientport;
Bit8u hostnamebuffer[128]; // the name passed to us by the user
void updatePortConfig(Bit16u divider, Bit8u lcr); void updatePortConfig(Bit16u divider, Bit8u lcr);
void updateMSR(); void updateMSR();
@ -56,6 +48,16 @@ public:
void setDTR(bool val); void setDTR(bool val);
void handleUpperEvent(Bit16u type); void handleUpperEvent(Bit16u type);
private:
TCPServerSocket* serversocket;
TCPClientSocket* clientsocket;
bool receiveblock; // It's not a block of data it rather blocks
Bit16u serverport; // we are a server if this is nonzero
Bit16u clientport;
Bit8u hostnamebuffer[128]; // the name passed to us by the user
Bitu rx_state; Bitu rx_state;
#define N_RX_IDLE 0 #define N_RX_IDLE 0
#define N_RX_WAIT 1 #define N_RX_WAIT 1
@ -64,11 +66,17 @@ public:
#define N_RX_DISC 4 #define N_RX_DISC 4
bool doReceive(); bool doReceive();
void ClientConnect(); bool ClientConnect(TCPClientSocket* newsocket);
bool ServerListen();
bool ServerConnect();
void Disconnect(); void Disconnect();
Bits readChar(); Bits readChar();
void WriteChar(Bit8u data); void WriteChar(Bit8u data);
bool DTR_delta; // with dtrrespect, we try to establish a connection
// whenever DTR switches to 1. This variable is
// used to remember the old state.
bool tx_block; // true while the SERIAL_TX_REDUCTION event bool tx_block; // true while the SERIAL_TX_REDUCTION event
// is pending // is pending

View File

@ -223,7 +223,8 @@ void CSerial::changeLineProperties() {
else bitlen = (1000.0f/115200.0f)*(float)baud_divider; else bitlen = (1000.0f/115200.0f)*(float)baud_divider;
bytetime=bitlen*(float)(1+5+1); // startbit + minimum length + stopbit bytetime=bitlen*(float)(1+5+1); // startbit + minimum length + stopbit
bytetime+= bitlen*(float)(LCR&0x3); // databits bytetime+= bitlen*(float)(LCR&0x3); // databits
if(LCR&0x4) bytetime+=bitlen; // stopbit if(LCR&0x4) bytetime+=bitlen; // 2nd stopbit
if(LCR&0x8) bytetime+=bitlen; // parity
#if SERIAL_DEBUG #if SERIAL_DEBUG
const char* const dbgtext[]={"none","odd","none","even","none","mark","none","space"}; const char* const dbgtext[]={"none","odd","none","even","none","mark","none","space"};

View File

@ -77,20 +77,20 @@ static Bitu temp[643]={0};
static Bit8u * VGA_Draw_CGA16_Line(Bitu vidstart, Bitu line) { static Bit8u * VGA_Draw_CGA16_Line(Bitu vidstart, Bitu line) {
const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift); const Bit8u *base = vga.tandy.draw_base + ((line & vga.tandy.line_mask) << vga.tandy.line_shift);
const Bit8u *reader = base + vidstart; #define CGA16_READER(OFF) (base[(vidstart +(OFF))& (8*1024 -1)])
Bit32u * draw=(Bit32u *)TempLine; Bit32u * draw=(Bit32u *)TempLine;
//Generate a temporary bitline to calculate the avarage //Generate a temporary bitline to calculate the avarage
//over bit-2 bit-1 bit bit+1. //over bit-2 bit-1 bit bit+1.
//Combine this number with the current colour to get //Combine this number with the current colour to get
//an unigue index in the pallete. Or it with bit 7 as they are stored //an unique index in the pallette. Or it with bit 7 as they are stored
//in the upperpart to keep them from interfering the regular cga stuff //in the upperpart to keep them from interfering the regular cga stuff
for(Bitu x = 0; x < 640; x++) for(Bitu x = 0; x < 640; x++)
temp[x+2] = (( reader[(x>>3)] >> (7-(x&7)) )&1) << 4; temp[x+2] = (( CGA16_READER(x>>3)>> (7-(x&7)) )&1) << 4;
//shift 4 as that is for the index. //shift 4 as that is for the index.
Bitu i = 0,temp1,temp2,temp3,temp4; Bitu i = 0,temp1,temp2,temp3,temp4;
for (Bitu x=0;x<vga.draw.blocks;x++) { for (Bitu x=0;x<vga.draw.blocks;x++) {
Bitu val1 = *reader++; Bitu val1 = CGA16_READER(x);
Bitu val2 = val1&0xf; Bitu val2 = val1&0xf;
val1 >>= 4; val1 >>= 4;
@ -113,6 +113,7 @@ static Bit8u * VGA_Draw_CGA16_Line(Bitu vidstart, Bitu line) {
((temp4|val2) <<24); ((temp4|val2) <<24);
} }
return TempLine; return TempLine;
#undef CGA16_READER
} }
static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart, Bitu line) { static Bit8u * VGA_Draw_4BPP_Line(Bitu vidstart, Bitu line) {
@ -824,7 +825,7 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
break; break;
} }
//Check if we can actually render, else skip the rest (frameskip) //Check if we can actually render, else skip the rest (frameskip)
if (!RENDER_StartUpdate()) if (vga.draw.vga_override || !RENDER_StartUpdate())
return; return;
vga.draw.address_line = vga.config.hlines_skip; vga.draw.address_line = vga.config.hlines_skip;
@ -1556,7 +1557,9 @@ void VGA_SetupDrawing(Bitu /*val*/) {
LOG(LOG_VGA,LOG_NORMAL)("%s width, %s height aspect %f", LOG(LOG_VGA,LOG_NORMAL)("%s width, %s height aspect %f",
doublewidth ? "double":"normal",doubleheight ? "double":"normal",aspect_ratio); doublewidth ? "double":"normal",doubleheight ? "double":"normal",aspect_ratio);
#endif #endif
RENDER_SetSize(width,height,bpp,(float)fps,aspect_ratio,doublewidth,doubleheight); if (!vga.draw.vga_override)
RENDER_SetSize(width, height, bpp, (float)fps, aspect_ratio,
doublewidth, doubleheight);
} }
} }
@ -1566,5 +1569,19 @@ void VGA_KillDrawing(void) {
PIC_RemoveEvents(VGA_DrawEGASingleLine); PIC_RemoveEvents(VGA_DrawEGASingleLine);
vga.draw.parts_left = 0; vga.draw.parts_left = 0;
vga.draw.lines_done = ~0; vga.draw.lines_done = ~0;
RENDER_EndUpdate(true); if (!vga.draw.vga_override) RENDER_EndUpdate(true);
}
void VGA_SetOverride(bool vga_override) {
if (vga.draw.vga_override!=vga_override) {
if (vga_override) {
VGA_KillDrawing();
vga.draw.vga_override=true;
} else {
vga.draw.vga_override=false;
vga.draw.width=0; // change it so the output window gets updated
VGA_SetupDrawing(0);
}
}
} }

View File

@ -700,6 +700,7 @@ public:
// |PFLAG_NOCODE; // |PFLAG_NOCODE;
} }
HostPt GetHostReadPt(Bitu phys_page) { HostPt GetHostReadPt(Bitu phys_page) {
// Odd banks are limited to 16kB and repeated
if (vga.tandy.mem_bank & 1) if (vga.tandy.mem_bank & 1)
phys_page&=0x03; phys_page&=0x03;
else else
@ -719,8 +720,8 @@ public:
} }
HostPt GetHostReadPt(Bitu phys_page) { HostPt GetHostReadPt(Bitu phys_page) {
phys_page-=0xb8; phys_page-=0xb8;
//test for a unaliged bank, then replicate 2x16kb // The 16kB map area is repeated in the 32kB range
if (vga.tandy.mem_bank & 1) // On CGA CPU A14 is not decoded so it repeats there too
phys_page&=0x03; phys_page&=0x03;
return vga.tandy.mem_base + (phys_page * 4096); return vga.tandy.mem_base + (phys_page * 4096);
} }

View File

@ -83,7 +83,9 @@ static void write_crtc_data_other(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
vga.draw.cursor.eline = (Bit8u)(val&0x1f); vga.draw.cursor.eline = (Bit8u)(val&0x1f);
break; break;
case 0x0C: /* Start Address High Register */ case 0x0C: /* Start Address High Register */
vga.config.display_start=(vga.config.display_start & 0x00FF) | (val << 8); // Bit 12 (depending on video mode) and 13 are actually masked too,
// but so far no need to implement it.
vga.config.display_start=(vga.config.display_start & 0x00FF) | ((val&0x3F) << 8);
break; break;
case 0x0D: /* Start Address Low Register */ case 0x0D: /* Start Address Low Register */
vga.config.display_start=(vga.config.display_start & 0xFF00) | val; vga.config.display_start=(vga.config.display_start & 0xFF00) | val;
@ -491,10 +493,18 @@ static void write_tandy(Bitu port,Bitu val,Bitu /*iolen*/) {
write_tandy_reg((Bit8u)val); write_tandy_reg((Bit8u)val);
break; break;
case 0x3df: case 0x3df:
// CRT/processor page register
// See the comments on the PCJr version of this register.
// A difference to it is:
// Bit 3-5: Processor page CPU_PG
// The remapped range is 32kB instead of 16. Therefore CPU_PG bit 0
// appears to be ORed with CPU A14 (to preserve some sort of
// backwards compatibility?), resulting in odd pages being mapped
// as 2x16kB. Implemeted in vga_memory.cpp Tandy handler.
vga.tandy.line_mask = (Bit8u)(val >> 6); vga.tandy.line_mask = (Bit8u)(val >> 6);
vga.tandy.draw_bank = val & ((vga.tandy.line_mask&2) ? 0x6 : 0x7); vga.tandy.draw_bank = val & ((vga.tandy.line_mask&2) ? 0x6 : 0x7);
if(vga.tandy.line_mask==3) vga.tandy.draw_bank &= ~1; // LSB unused in 32k modes vga.tandy.mem_bank = (val >> 3) & 7;
vga.tandy.mem_bank = (val >> 3) & ((vga.tandy.line_mask&2) ? 0x6 : 0x7);
TandyCheckLineMask(); TandyCheckLineMask();
VGA_SetupHandlers(); VGA_SetupHandlers();
break; break;
@ -514,9 +524,38 @@ static void write_pcjr(Bitu port,Bitu val,Bitu /*iolen*/) {
vga.tandy.pcjr_flipflop=!vga.tandy.pcjr_flipflop; vga.tandy.pcjr_flipflop=!vga.tandy.pcjr_flipflop;
break; break;
case 0x3df: case 0x3df:
// CRT/processor page register
// Bit 0-2: CRT page PG0-2
// In one- and two bank modes, bit 0-2 select the 16kB memory
// area of system RAM that is displayed on the screen.
// In 4-banked modes, bit 1-2 select the 32kB memory area.
// Bit 2 only has effect when the PCJR upgrade to 128k is installed.
// Bit 3-5: Processor page CPU_PG
// Selects the 16kB area of system RAM that is mapped to
// the B8000h IBM PC video memory window. Since A14-A16 of the
// processor are unconditionally replaced with these bits when
// B8000h is accessed, the 16kB area is mapped to the 32kB
// range twice in a row. (Scuba Venture writes across the boundary)
// Bit 6-7: Video Address mode
// 0: CRTC addresses A0-12 directly, accessing 8k characters
// (+8k attributes). Used in text modes (one bank).
// PG0-2 in effect. 16k range.
// 1: CRTC A12 is replaced with CRTC RA0 (see max_scanline).
// This results in the even/odd scanline two bank system.
// PG0-2 in effect. 16k range.
// 2: Documented as unused. CRTC addresses A0-12, PG0 is replaced
// with RA1. Looks like nonsense.
// PG1-2 in effect. 32k range which cannot be used completely.
// 3: CRTC A12 is replaced with CRTC RA0, PG0 is replaced with
// CRTC RA1. This results in the 4-bank mode.
// PG1-2 in effect. 32k range.
vga.tandy.line_mask = (Bit8u)(val >> 6); vga.tandy.line_mask = (Bit8u)(val >> 6);
vga.tandy.draw_bank = val & ((vga.tandy.line_mask&2) ? 0x6 : 0x7); vga.tandy.draw_bank = val & ((vga.tandy.line_mask&2) ? 0x6 : 0x7);
vga.tandy.mem_bank = (val >> 3) & ((vga.tandy.line_mask&2) ? 0x6 : 0x7); vga.tandy.mem_bank = (val >> 3) & 7;
vga.tandy.draw_base = &MemBase[vga.tandy.draw_bank * 16 * 1024]; vga.tandy.draw_base = &MemBase[vga.tandy.draw_bank * 16 * 1024];
vga.tandy.mem_base = &MemBase[vga.tandy.mem_bank * 16 * 1024]; vga.tandy.mem_base = &MemBase[vga.tandy.mem_bank * 16 * 1024];
TandyCheckLineMask(); TandyCheckLineMask();
@ -674,6 +713,9 @@ void VGA_SetupOther(void) {
write_pcjr( 0x3df, 0x7 | (0x7 << 3), 0 ); write_pcjr( 0x3df, 0x7 | (0x7 << 3), 0 );
IO_RegisterWriteHandler(0x3da,write_pcjr,IO_MB); IO_RegisterWriteHandler(0x3da,write_pcjr,IO_MB);
IO_RegisterWriteHandler(0x3df,write_pcjr,IO_MB); IO_RegisterWriteHandler(0x3df,write_pcjr,IO_MB);
// additional CRTC access documented
IO_RegisterWriteHandler(0x3d0,write_crtc_index_other,IO_MB);
IO_RegisterWriteHandler(0x3d1,write_crtc_data_other,IO_MB);
} }
if (machine==MCH_HERC) { if (machine==MCH_HERC) {
Bitu base=0x3b0; Bitu base=0x3b0;

View File

@ -341,7 +341,7 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) {
vga.svga.bank_write = vga.svga.bank_read; vga.svga.bank_write = vga.svga.bank_read;
VGA_SetupHandlers(); VGA_SetupHandlers();
break; break;
case 0x6b: // BIOS scratchpad: LFB adress case 0x6b: // BIOS scratchpad: LFB address
vga.s3.reg_6b=(Bit8u)val; vga.s3.reg_6b=(Bit8u)val;
break; break;
default: default:

View File

@ -38,7 +38,6 @@
#include <ogc/lwp_watchdog.h> #include <ogc/lwp_watchdog.h>
#endif #endif
/* if mem_systems 0 then size_extended is reported as the real size else /* if mem_systems 0 then size_extended is reported as the real size else
* zero is reported. ems and xms can increase or decrease the other_memsystems * zero is reported. ems and xms can increase or decrease the other_memsystems
* counter using the BIOS_ZeroExtendedSize call */ * counter using the BIOS_ZeroExtendedSize call */
@ -850,6 +849,7 @@ static Bitu INT15_Handler(void) {
CALLBACK_Idle(); CALLBACK_Idle();
} }
CALLBACK_SCF(false); CALLBACK_SCF(false);
break;
} }
case 0x87: /* Copy extended memory */ case 0x87: /* Copy extended memory */
{ {

View File

@ -85,13 +85,26 @@ void updateDPT(void) {
} }
} }
void incrementFDD(void) {
Bit16u equipment=mem_readw(BIOS_CONFIGURATION);
if(equipment&1) {
Bitu numofdisks = (equipment>>6)&3;
numofdisks++;
if(numofdisks > 1) numofdisks=1;//max 2 floppies at the moment
equipment&=~0x00C0;
equipment|=(numofdisks<<6);
} else equipment|=1;
mem_writew(BIOS_CONFIGURATION,equipment);
CMOS_SetRegister(0x14, (Bit8u)(equipment&0xff));
}
void swapInDisks(void) { void swapInDisks(void) {
bool allNull = true; bool allNull = true;
Bits diskcount = 0; Bits diskcount = 0;
Bits swapPos = swapPosition; Bits swapPos = swapPosition;
int i; int i;
/* Check to make sure there's atleast one setup image */ /* Check to make sure that there is at least one setup image */
for(i=0;i<MAX_SWAPPABLE_DISKS;i++) { for(i=0;i<MAX_SWAPPABLE_DISKS;i++) {
if(diskSwap[i]!=NULL) { if(diskSwap[i]!=NULL) {
allNull = false; allNull = false;
@ -219,16 +232,7 @@ imageDisk::imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHard
if(!founddisk) { if(!founddisk) {
active = false; active = false;
} else { } else {
Bit16u equipment=mem_readw(BIOS_CONFIGURATION); incrementFDD();
if(equipment&1) {
Bitu numofdisks = (equipment>>6)&3;
numofdisks++;
if(numofdisks > 1) numofdisks=1;//max 2 floppies at the moment
equipment&=~0x00C0;
equipment|=(numofdisks<<6);
} else equipment|=1;
mem_writew(BIOS_CONFIGURATION,equipment);
CMOS_SetRegister(0x14, (Bit8u)(equipment&0xff));
} }
} }
} }
@ -329,12 +333,14 @@ static Bitu INT13_DiskHandler(void) {
if ((machine==MCH_CGA) || (machine==MCH_PCJR)) { if ((machine==MCH_CGA) || (machine==MCH_PCJR)) {
/* those bioses call floppy drive reset for invalid drive values */ /* those bioses call floppy drive reset for invalid drive values */
if (((imageDiskList[0]) && (imageDiskList[0]->active)) || ((imageDiskList[1]) && (imageDiskList[1]->active))) { if (((imageDiskList[0]) && (imageDiskList[0]->active)) || ((imageDiskList[1]) && (imageDiskList[1]->active))) {
if (reg_dl<0x80) reg_ip++;
last_status = 0x00; last_status = 0x00;
CALLBACK_SCF(false); CALLBACK_SCF(false);
} }
} }
return CBRET_NONE; return CBRET_NONE;
} }
if (reg_dl<0x80) reg_ip++;
last_status = 0x00; last_status = 0x00;
CALLBACK_SCF(false); CALLBACK_SCF(false);
} }
@ -496,7 +502,7 @@ static Bitu INT13_DiskHandler(void) {
void BIOS_SetupDisks(void) { void BIOS_SetupDisks(void) {
/* TODO Start the time correctly */ /* TODO Start the time correctly */
call_int13=CALLBACK_Allocate(); call_int13=CALLBACK_Allocate();
CALLBACK_Setup(call_int13,&INT13_DiskHandler,CB_IRET,"Int 13 Bios disk"); CALLBACK_Setup(call_int13,&INT13_DiskHandler,CB_INT13,"Int 13 Bios disk");
RealSetVec(0x13,CALLBACK_RealPointer(call_int13)); RealSetVec(0x13,CALLBACK_RealPointer(call_int13));
int i; int i;
for(i=0;i<4;i++) { for(i=0;i<4;i++) {

View File

@ -382,7 +382,7 @@ static Bitu IRQ1_Handler(void) {
add_key(scan_to_scanascii[scancode].normal+0x5000); add_key(scan_to_scanascii[scancode].normal+0x5000);
} else if (flags1 &0x04) { } else if (flags1 &0x04) {
add_key((scan_to_scanascii[scancode].control&0xff00)|0xe0); add_key((scan_to_scanascii[scancode].control&0xff00)|0xe0);
} else if( ((flags1 &0x3) != 0) || ((flags1 &0x20) != 0) ) { } else if( ((flags1 &0x3) != 0) || ((flags1 &0x20) != 0) ) { //Due to |0xe0 results are identical.
add_key((scan_to_scanascii[scancode].shift&0xff00)|0xe0); add_key((scan_to_scanascii[scancode].shift&0xff00)|0xe0);
} else add_key((scan_to_scanascii[scancode].normal&0xff00)|0xe0); } else add_key((scan_to_scanascii[scancode].normal&0xff00)|0xe0);
break; break;
@ -393,7 +393,7 @@ static Bitu IRQ1_Handler(void) {
mem_writeb(BIOS_KEYBOARD_TOKEN,token); mem_writeb(BIOS_KEYBOARD_TOKEN,token);
} else if (flags1 &0x04) { } else if (flags1 &0x04) {
add_key(scan_to_scanascii[scancode].control); add_key(scan_to_scanascii[scancode].control);
} else if( ((flags1 &0x3) != 0) || ((flags1 &0x20) != 0) ) { } else if( ((flags1 &0x3) != 0) ^ ((flags1 &0x20) != 0) ) { //Xor shift and numlock (both means off)
add_key(scan_to_scanascii[scancode].shift); add_key(scan_to_scanascii[scancode].shift);
} else add_key(scan_to_scanascii[scancode].normal); } else add_key(scan_to_scanascii[scancode].normal);
break; break;
@ -546,7 +546,7 @@ static Bitu INT16_Handler(void) {
reg_ax=temp; reg_ax=temp;
} }
break; break;
case 0x02: /* GET SHIFT FlAGS */ case 0x02: /* GET SHIFT FLAGS */
reg_al=mem_readb(BIOS_KEYBOARD_FLAGS1); reg_al=mem_readb(BIOS_KEYBOARD_FLAGS1);
break; break;
case 0x03: /* SET TYPEMATIC RATE AND DELAY */ case 0x03: /* SET TYPEMATIC RATE AND DELAY */
@ -594,7 +594,7 @@ static void InitBiosSegment(void) {
mem_writew(BIOS_KEYBOARD_BUFFER_HEAD,0x1e); mem_writew(BIOS_KEYBOARD_BUFFER_HEAD,0x1e);
mem_writew(BIOS_KEYBOARD_BUFFER_TAIL,0x1e); mem_writew(BIOS_KEYBOARD_BUFFER_TAIL,0x1e);
Bit8u flag1 = 0; Bit8u flag1 = 0;
Bit8u leds = 16; /* Ack recieved */ Bit8u leds = 16; /* Ack received */
#if SDL_VERSION_ATLEAST(1, 2, 14) #if SDL_VERSION_ATLEAST(1, 2, 14)
//Nothing, mapper handles all. //Nothing, mapper handles all.

View File

@ -489,7 +489,7 @@ static Bit8u EMM_PartialPageMapping(void) {
mem_writew(data,segment);data+=2; mem_writew(data,segment);data+=2;
MEM_BlockWrite(data,&emm_mappings[page],sizeof(EMM_Mapping)); MEM_BlockWrite(data,&emm_mappings[page],sizeof(EMM_Mapping));
data+=sizeof(EMM_Mapping); data+=sizeof(EMM_Mapping);
} else if (((segment>=EMM_PAGEFRAME-0x1000) && (segment<EMM_PAGEFRAME)) || ((segment>=0xa000) && (segment<0xb000))) { } else if ((ems_type==1) || (ems_type==3) || ((segment>=EMM_PAGEFRAME-0x1000) && (segment<EMM_PAGEFRAME)) || ((segment>=0xa000) && (segment<0xb000))) {
mem_writew(data,segment);data+=2; mem_writew(data,segment);data+=2;
MEM_BlockWrite(data,&emm_segmentmappings[segment>>10],sizeof(EMM_Mapping)); MEM_BlockWrite(data,&emm_segmentmappings[segment>>10],sizeof(EMM_Mapping));
data+=sizeof(EMM_Mapping); data+=sizeof(EMM_Mapping);
@ -506,7 +506,7 @@ static Bit8u EMM_PartialPageMapping(void) {
if ((segment>=EMM_PAGEFRAME) && (segment<EMM_PAGEFRAME+0x1000)) { if ((segment>=EMM_PAGEFRAME) && (segment<EMM_PAGEFRAME+0x1000)) {
Bit16u page = (segment-EMM_PAGEFRAME) / (EMM_PAGE_SIZE>>4); Bit16u page = (segment-EMM_PAGEFRAME) / (EMM_PAGE_SIZE>>4);
MEM_BlockRead(data,&emm_mappings[page],sizeof(EMM_Mapping)); MEM_BlockRead(data,&emm_mappings[page],sizeof(EMM_Mapping));
} else if (((segment>=EMM_PAGEFRAME-0x1000) && (segment<EMM_PAGEFRAME)) || ((segment>=0xa000) && (segment<0xb000))) { } else if ((ems_type==1) || (ems_type==3) || ((segment>=EMM_PAGEFRAME-0x1000) && (segment<EMM_PAGEFRAME)) || ((segment>=0xa000) && (segment<0xb000))) {
MEM_BlockRead(data,&emm_segmentmappings[segment>>10],sizeof(EMM_Mapping)); MEM_BlockRead(data,&emm_segmentmappings[segment>>10],sizeof(EMM_Mapping));
} else { } else {
return EMM_ILL_PHYS; return EMM_ILL_PHYS;
@ -1079,7 +1079,7 @@ static Bitu V86_Monitor() {
reg_esp+=6; // skip ip of CALL and error code of EXCEPTION 0x0d reg_esp+=6; // skip ip of CALL and error code of EXCEPTION 0x0d
/* Get adress of faulting instruction */ /* Get address of faulting instruction */
Bit16u v86_cs=mem_readw(SegPhys(ss)+((reg_esp+4) & cpu.stack.mask)); Bit16u v86_cs=mem_readw(SegPhys(ss)+((reg_esp+4) & cpu.stack.mask));
Bit16u v86_ip=mem_readw(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask)); Bit16u v86_ip=mem_readw(SegPhys(ss)+((reg_esp+0) & cpu.stack.mask));
Bit8u v86_opcode=mem_readb((v86_cs<<4)+v86_ip); Bit8u v86_opcode=mem_readb((v86_cs<<4)+v86_ip);

View File

@ -375,7 +375,7 @@ graphics_chars:
reg_al=0x12; reg_al=0x12;
break; break;
} }
case 0x32: /* Video adressing */ case 0x32: /* Video addressing */
if (!IS_VGA_ARCH) break; if (!IS_VGA_ARCH) break;
LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl); LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl);
if (svgaCard==SVGA_TsengET4K) reg_al&=1; if (svgaCard==SVGA_TsengET4K) reg_al&=1;

View File

@ -49,7 +49,7 @@ void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu
PhysPt ftwhere=PhysMake(0xa000,map_offset[map & 0x7]+(Bit16u)(offset*32)); PhysPt ftwhere=PhysMake(0xa000,map_offset[map & 0x7]+(Bit16u)(offset*32));
IO_Write(0x3c4,0x2);IO_Write(0x3c5,0x4); //Enable plane 2 IO_Write(0x3c4,0x2);IO_Write(0x3c5,0x4); //Enable plane 2
IO_Write(0x3ce,0x6);Bitu old_6=IO_Read(0x3cf); IO_Write(0x3ce,0x6);Bitu old_6=IO_Read(0x3cf);
IO_Write(0x3cf,0x0); //Disable odd/even and a0000 adressing IO_Write(0x3cf,0x0); //Disable odd/even and a0000 addressing
for (Bitu i=0;i<count;i++) { for (Bitu i=0;i<count;i++) {
MEM_BlockCopy(ftwhere,font,height); MEM_BlockCopy(ftwhere,font,height);
ftwhere+=32; ftwhere+=32;
@ -57,7 +57,7 @@ void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu
} }
IO_Write(0x3c4,0x2);IO_Write(0x3c5,0x3); //Enable textmode planes (0,1) IO_Write(0x3c4,0x2);IO_Write(0x3c5,0x3); //Enable textmode planes (0,1)
IO_Write(0x3ce,0x6); IO_Write(0x3ce,0x6);
if (IS_VGA_ARCH) IO_Write(0x3cf,(Bit8u)old_6); //odd/even and b8000 adressing if (IS_VGA_ARCH) IO_Write(0x3cf,(Bit8u)old_6); //odd/even and b8000 addressing
else IO_Write(0x3cf,0x0e); else IO_Write(0x3cf,0x0e);
/* Reload tables and registers with new values based on this height */ /* Reload tables and registers with new values based on this height */
if (reload) { if (reload) {
@ -154,7 +154,7 @@ void INT10_SetupRomMemory(void) {
int10.rom.video_dcc_table=RealMake(0xC000,int10.rom.used); int10.rom.video_dcc_table=RealMake(0xC000,int10.rom.used);
phys_writeb(rom_base+int10.rom.used++,0x10); // number of entries phys_writeb(rom_base+int10.rom.used++,0x10); // number of entries
phys_writeb(rom_base+int10.rom.used++,1); // version number phys_writeb(rom_base+int10.rom.used++,1); // version number
phys_writeb(rom_base+int10.rom.used++,8); // maximal display code phys_writeb(rom_base+int10.rom.used++,8); // maximum display code
phys_writeb(rom_base+int10.rom.used++,0); // reserved phys_writeb(rom_base+int10.rom.used++,0); // reserved
// display combination codes // display combination codes
phys_writew(rom_base+int10.rom.used,0x0000); int10.rom.used+=2; phys_writew(rom_base+int10.rom.used,0x0000); int10.rom.used+=2;

View File

@ -405,7 +405,7 @@ static void FinishSetMode(bool clearmem) {
case M_LIN15: case M_LIN15:
case M_LIN16: case M_LIN16:
case M_LIN32: case M_LIN32:
/* Hack we just acess the memory directly */ /* Hack we just access the memory directly */
memset(vga.mem.linear,0,vga.vmemsize); memset(vga.mem.linear,0,vga.vmemsize);
memset(vga.fastmem, 0, vga.vmemsize<<1); memset(vga.fastmem, 0, vga.vmemsize<<1);
} }

View File

@ -321,7 +321,7 @@ void INT10_SetBackgroundBorder(Bit8u val) {
} }
else if (IS_EGAVGA_ARCH) { else if (IS_EGAVGA_ARCH) {
val = ((val << 1) & 0x10) | (val & 0x7); val = ((val << 1) & 0x10) | (val & 0x7);
/* Aways set the overscan color */ /* Always set the overscan color */
INT10_SetSinglePaletteRegister( 0x11, val ); INT10_SetSinglePaletteRegister( 0x11, val );
/* Don't set any extra colors when in text mode */ /* Don't set any extra colors when in text mode */
if (CurMode->mode <= 3) if (CurMode->mode <= 3)

View File

@ -50,8 +50,8 @@ struct button_event {
#define QUEUE_SIZE 32 #define QUEUE_SIZE 32
#define MOUSE_BUTTONS 3 #define MOUSE_BUTTONS 3
#define MOUSE_IRQ 12 #define MOUSE_IRQ 12
#define POS_X ((Bit16s)(mouse.x) & mouse.granMask) #define POS_X (static_cast<Bit16s>(mouse.x) & mouse.gran_x)
#define POS_Y (Bit16s)(mouse.y) #define POS_Y (static_cast<Bit16s>(mouse.y) & mouse.gran_y)
#define CURSORX 16 #define CURSORX 16
#define CURSORY 16 #define CURSORY 16
@ -125,7 +125,7 @@ static struct {
bool timer_in_progress; bool timer_in_progress;
bool in_UIR; bool in_UIR;
Bit8u mode; Bit8u mode;
Bit16s granMask; Bit16s gran_x,gran_y;
} mouse; } mouse;
bool Mouse_SetPS2State(bool use) { bool Mouse_SetPS2State(bool use) {
@ -255,6 +255,7 @@ void DrawCursorText() {
// Save Background // Save Background
mouse.backposx = POS_X>>3; mouse.backposx = POS_X>>3;
mouse.backposy = POS_Y>>3; mouse.backposy = POS_Y>>3;
if (mouse.mode < 2) mouse.backposx >>= 1;
//use current page (CV program) //use current page (CV program)
Bit8u page = real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); Bit8u page = real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
@ -582,43 +583,48 @@ static void Mouse_ResetHardware(void){
//Does way to much. Many things should be moved to mouse reset one day //Does way to much. Many things should be moved to mouse reset one day
void Mouse_NewVideoMode(void) { void Mouse_NewVideoMode(void) {
mouse.inhibit_draw=false; mouse.inhibit_draw = false;
/* Get the correct resolution from the current video mode */ /* Get the correct resolution from the current video mode */
Bit8u mode=mem_readb(BIOS_VIDEO_MODE); Bit8u mode = mem_readb(BIOS_VIDEO_MODE);
if(mode == mouse.mode) {LOG(LOG_MOUSE,LOG_NORMAL)("New video is the same as the old"); /*return;*/} if(mode == mouse.mode) {LOG(LOG_MOUSE,LOG_NORMAL)("New video is the same as the old"); /*return;*/}
mouse.gran_x = (Bit16s)0xffff;
mouse.gran_y = (Bit16s)0xffff;
switch (mode) { switch (mode) {
case 0x00: case 0x00:
case 0x01: case 0x01:
case 0x02: case 0x02:
case 0x03: { case 0x03:
Bitu rows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS); case 0x07: {
if ((rows==0) || (rows>250)) rows=25-1; mouse.gran_x = (mode<2)?0xfff0:0xfff8;
mouse.max_y=8*(rows+1)-1; mouse.gran_y = (Bit16s)0xfff8;
Bitu rows = real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS);
if ((rows == 0) || (rows > 250)) rows = 25 - 1;
mouse.max_y = 8*(rows+1) - 1;
break; break;
} }
case 0x04: case 0x04:
case 0x05: case 0x05:
case 0x06: case 0x06:
case 0x07:
case 0x08: case 0x08:
case 0x09: case 0x09:
case 0x0a: case 0x0a:
case 0x0d: case 0x0d:
case 0x0e: case 0x0e:
case 0x13: case 0x13:
mouse.max_y=199; if (mode == 0x0d || mode == 0x13) mouse.gran_x = (Bit16s)0xfffe;
mouse.max_y = 199;
break; break;
case 0x0f: case 0x0f:
case 0x10: case 0x10:
mouse.max_y=349; mouse.max_y = 349;
break; break;
case 0x11: case 0x11:
case 0x12: case 0x12:
mouse.max_y=479; mouse.max_y = 479;
break; break;
default: default:
LOG(LOG_MOUSE,LOG_ERROR)("Unhandled videomode %X on reset",mode); LOG(LOG_MOUSE,LOG_ERROR)("Unhandled videomode %X on reset",mode);
mouse.inhibit_draw=true; mouse.inhibit_draw = true;
return; return;
} }
mouse.mode = mode; mouse.mode = mode;
@ -626,7 +632,6 @@ void Mouse_NewVideoMode(void) {
mouse.max_x = 639; mouse.max_x = 639;
mouse.min_x = 0; mouse.min_x = 0;
mouse.min_y = 0; mouse.min_y = 0;
mouse.granMask = (mode == 0x0d || mode == 0x13) ? 0xfffe : 0xffff;
mouse.events = 0; mouse.events = 0;
mouse.timer_in_progress = false; mouse.timer_in_progress = false;
@ -1007,7 +1012,7 @@ static Bitu INT74_Handler(void) {
} else if (useps2callback) { } else if (useps2callback) {
CPU_Push16(RealSeg(CALLBACK_RealPointer(int74_ret_callback))); CPU_Push16(RealSeg(CALLBACK_RealPointer(int74_ret_callback)));
CPU_Push16(RealOff(CALLBACK_RealPointer(int74_ret_callback))); CPU_Push16(RealOff(CALLBACK_RealPointer(int74_ret_callback)));
DoPS2Callback(mouse.event_queue[mouse.events].buttons, POS_X, POS_Y); DoPS2Callback(mouse.event_queue[mouse.events].buttons, static_cast<Bit16s>(mouse.x), static_cast<Bit16s>(mouse.y));
} else { } else {
SegSet16(cs, RealSeg(CALLBACK_RealPointer(int74_ret_callback))); SegSet16(cs, RealSeg(CALLBACK_RealPointer(int74_ret_callback)));
reg_ip = RealOff(CALLBACK_RealPointer(int74_ret_callback)); reg_ip = RealOff(CALLBACK_RealPointer(int74_ret_callback));

View File

@ -19,6 +19,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stddef.h>
#include "dosbox.h" #include "dosbox.h"
#include "callback.h" #include "callback.h"
#include "mem.h" #include "mem.h"

View File

@ -98,7 +98,7 @@ static void LoadMessageFile(const char * fname) {
strcpy(name,linein+1); strcpy(name,linein+1);
/* End of string marker */ /* End of string marker */
} else if (linein[0]=='.') { } else if (linein[0]=='.') {
/* Replace/Add the string to the internal langaugefile */ /* Replace/Add the string to the internal languagefile */
/* Remove last newline (marker is \n.\n) */ /* Remove last newline (marker is \n.\n) */
size_t ll = strlen(string); size_t ll = strlen(string);
if(ll && string[ll - 1] == '\n') string[ll - 1] = 0; //Second if should not be needed, but better be safe. if(ll && string[ll - 1] == '\n') string[ll - 1] = 0; //Second if should not be needed, but better be safe.

View File

@ -128,6 +128,7 @@ void Program::ChangeToLongCmd() {
full_arguments.assign(""); //Clear so it gets even more save full_arguments.assign(""); //Clear so it gets even more save
} }
static char last_written_character = 0;//For 0xA to OxD 0xA expansion
void Program::WriteOut(const char * format,...) { void Program::WriteOut(const char * format,...) {
char buf[2048]; char buf[2048];
va_list msg; va_list msg;
@ -139,10 +140,10 @@ void Program::WriteOut(const char * format,...) {
Bit16u size = (Bit16u)strlen(buf); Bit16u size = (Bit16u)strlen(buf);
for(Bit16u i = 0; i < size;i++) { for(Bit16u i = 0; i < size;i++) {
Bit8u out;Bit16u s=1; Bit8u out;Bit16u s=1;
if (buf[i] == 0xA && i > 0 && buf[i-1] !=0xD) { if (buf[i] == 0xA && last_written_character != 0xD) {
out = 0xD;DOS_WriteFile(STDOUT,&out,&s); out = 0xD;DOS_WriteFile(STDOUT,&out,&s);
} }
out = buf[i]; last_written_character = out = buf[i];
DOS_WriteFile(STDOUT,&out,&s); DOS_WriteFile(STDOUT,&out,&s);
} }
@ -154,10 +155,10 @@ void Program::WriteOut_NoParsing(const char * format) {
char const* buf = format; char const* buf = format;
for(Bit16u i = 0; i < size;i++) { for(Bit16u i = 0; i < size;i++) {
Bit8u out;Bit16u s=1; Bit8u out;Bit16u s=1;
if (buf[i] == 0xA && i > 0 && buf[i-1] !=0xD) { if (buf[i] == 0xA && last_written_character != 0xD) {
out = 0xD;DOS_WriteFile(STDOUT,&out,&s); out = 0xD;DOS_WriteFile(STDOUT,&out,&s);
} }
out = buf[i]; last_written_character = out = buf[i];
DOS_WriteFile(STDOUT,&out,&s); DOS_WriteFile(STDOUT,&out,&s);
} }

View File

@ -955,6 +955,39 @@ bool CommandLine::FindStringRemain(char const * const name,std::string & value)
return true; return true;
} }
/* Only used for parsing command.com /C
* Allowing /C dir and /Cdir
* Restoring quotes back into the commands so command /C mount d "/tmp/a b" works as intended
*/
bool CommandLine::FindStringRemainBegin(char const * const name,std::string & value) {
cmd_it it;value="";
if (!FindEntry(name,it)) {
size_t len = strlen(name);
for (it=cmds.begin();it!=cmds.end();it++) {
if (strncasecmp(name,(*it).c_str(),len)==0) {
std::string temp = ((*it).c_str() + len);
//Restore quotes for correct parsing in later stages
if(temp.find(" ") != std::string::npos)
value = std::string("\"") + temp + std::string("\"");
else
value = temp;
break;
}
}
if( it == cmds.end()) return false;
}
it++;
for (;it!=cmds.end();it++) {
value += " ";
std::string temp = (*it);
if(temp.find(" ") != std::string::npos)
value += std::string("\"") + temp + std::string("\"");
else
value += temp;
}
return true;
}
bool CommandLine::GetStringRemain(std::string & value) { bool CommandLine::GetStringRemain(std::string & value) {
if(!cmds.size()) return false; if(!cmds.size()) return false;

View File

@ -52,14 +52,14 @@ typedef std::list<std::string>::iterator auto_it;
void VFILE_Remove(const char *name); void VFILE_Remove(const char *name);
void AutoexecObject::Install(const std::string &in) { void AutoexecObject::Install(const std::string &in) {
if(GCC_UNLIKELY(installed)) E_Exit("autoexec: allready created %s",buf.c_str()); if(GCC_UNLIKELY(installed)) E_Exit("autoexec: already created %s",buf.c_str());
installed = true; installed = true;
buf = in; buf = in;
autoexec_strings.push_back(buf); autoexec_strings.push_back(buf);
this->CreateAutoexec(); this->CreateAutoexec();
//autoexec.bat is normally created AUTOEXEC_Init. //autoexec.bat is normally created AUTOEXEC_Init.
//But if we are allready running (first_shell) //But if we are already running (first_shell)
//we have to update the envirionment to display changes //we have to update the envirionment to display changes
if(first_shell) { if(first_shell) {
@ -80,7 +80,7 @@ void AutoexecObject::Install(const std::string &in) {
} }
void AutoexecObject::InstallBefore(const std::string &in) { void AutoexecObject::InstallBefore(const std::string &in) {
if(GCC_UNLIKELY(installed)) E_Exit("autoexec: allready created %s",buf.c_str()); if(GCC_UNLIKELY(installed)) E_Exit("autoexec: already created %s",buf.c_str());
installed = true; installed = true;
buf = in; buf = in;
autoexec_strings.push_front(buf); autoexec_strings.push_front(buf);
@ -288,7 +288,7 @@ void DOS_Shell::RunInternal(void)
void DOS_Shell::Run(void) { void DOS_Shell::Run(void) {
char input_line[CMD_MAXLINE] = {0}; char input_line[CMD_MAXLINE] = {0};
std::string line; std::string line;
if (cmd->FindStringRemain("/C",line)) { if (cmd->FindStringRemainBegin("/C",line)) {
strcpy(input_line,line.c_str()); strcpy(input_line,line.c_str());
char* sep = strpbrk(input_line,"\r\n"); //GTA installer char* sep = strpbrk(input_line,"\r\n"); //GTA installer
if (sep) *sep = 0; if (sep) *sep = 0;

View File

@ -123,11 +123,12 @@ void DOS_Shell::DoCommand(char * line) {
char cmd_buffer[CMD_MAXLINE]; char cmd_buffer[CMD_MAXLINE];
char * cmd_write=cmd_buffer; char * cmd_write=cmd_buffer;
while (*line) { while (*line) {
if (*line==32) break; if (*line == 32) break;
if (*line=='/') break; if (*line == '/') break;
if (*line=='\t') break; if (*line == '\t') break;
if (*line=='=') break; if (*line == '=') break;
if ((*line=='.') ||(*line =='\\')) { //allow stuff like cd.. and dir.exe cd\kees // if (*line == ':') break; //This breaks drive switching as that is handled at a later stage.
if ((*line == '.') ||(*line == '\\')) { //allow stuff like cd.. and dir.exe cd\kees
*cmd_write=0; *cmd_write=0;
Bit32u cmd_index=0; Bit32u cmd_index=0;
while (cmd_list[cmd_index].name) { while (cmd_list[cmd_index].name) {
@ -287,7 +288,7 @@ void DOS_Shell::CMD_ECHO(char * args){
args++;//skip first character. either a slash or dot or space args++;//skip first character. either a slash or dot or space
size_t len = strlen(args); //TODO check input of else ook nodig is. size_t len = strlen(args); //TODO check input of else ook nodig is.
if(len && args[len - 1] == '\r') { if(len && args[len - 1] == '\r') {
LOG(LOG_MISC,LOG_WARN)("Hu ? carriage return allready present. Is this possible?"); LOG(LOG_MISC,LOG_WARN)("Hu ? carriage return already present. Is this possible?");
WriteOut("%s\n",args); WriteOut("%s\n",args);
} else WriteOut("%s\r\n",args); } else WriteOut("%s\r\n",args);
} }
@ -573,6 +574,7 @@ void DOS_Shell::CMD_COPY(char * args) {
while(ScanCMDBool(args,"A")) ; while(ScanCMDBool(args,"A")) ;
ScanCMDBool(args,"Y"); ScanCMDBool(args,"Y");
ScanCMDBool(args,"-Y"); ScanCMDBool(args,"-Y");
ScanCMDBool(args,"V");
char * rem=ScanCMDRemain(args); char * rem=ScanCMDRemain(args);
if (rem) { if (rem) {

View File

@ -56,7 +56,7 @@ void DOS_Shell::InputCommand(char * line) {
Bit16u dummy; Bit16u dummy;
DOS_CloseFile(input_handle); DOS_CloseFile(input_handle);
DOS_OpenFile("con",2,&dummy); DOS_OpenFile("con",2,&dummy);
LOG(LOG_MISC,LOG_ERROR)("Reopening the input handle.This is a bug!"); LOG(LOG_MISC,LOG_ERROR)("Reopening the input handle. This is a bug!");
} }
if (!n) { if (!n) {
size=0; //Kill the while loop size=0; //Kill the while loop
@ -174,6 +174,24 @@ void DOS_Shell::InputCommand(char * line) {
size++; size++;
} }
break; break;
case 15: /* Shift-Tab */
if (l_completion.size()) {
if (it_completion == l_completion.begin()) it_completion = l_completion.end ();
it_completion--;
if (it_completion->length()) {
for (;str_index > completion_index; str_index--) {
// removes all characters
outc(8); outc(' '); outc(8);
}
strcpy(&line[completion_index], it_completion->c_str());
len = (Bit16u)it_completion->length();
str_len = str_index = completion_index + len;
size = CMD_MAXLINE - str_index - 2;
DOS_WriteFile(STDOUT, (Bit8u *)it_completion->c_str(), &len);
}
}
default: default:
break; break;
} }
@ -281,7 +299,7 @@ void DOS_Shell::InputCommand(char * line) {
} }
res=DOS_FindNext(); res=DOS_FindNext();
} }
/* Add excutable list to front of completion list. */ /* Add executable list to front of completion list. */
std::copy(executable.begin(),executable.end(),std::front_inserter(l_completion)); std::copy(executable.begin(),executable.end(),std::front_inserter(l_completion));
it_completion = l_completion.begin(); it_completion = l_completion.begin();
dos.dta(save_dta); dos.dta(save_dta);