sync with official

This commit is contained in:
dborth 2009-10-09 06:22:57 +00:00
parent d4f4b6ce52
commit f0f4e75fe3
75 changed files with 3928 additions and 2794 deletions

36
README
View File

@ -1,39 +1,5 @@
DOSBox Wii (Port of DOSBox v0.73) DOSBox v0.73
http://code.google.com/p/dosbox-wii/
====
WII:
====
Report bugs at: http://code.google.com/p/dosbox-wii/issues/list
You can also view and download the source code from there.
To run homebrew applications, such as this one, on your Wii,
please see http://www.wiibrew.org/wiki/Main_Page
See the wiki for more information:
http://www.wiibrew.org/wiki/DOSBox_Wii
You currently need a USB keyboard to use DOSBox.
The Wii Remote can be used as a mouse by pointing and using the A
and B buttons. The Wii Remote, Nunchuk, Classic Controller and
Gamecube Controller can also be used as a joystick.
HOME will exit back to the homebrew channel, as will the RESET
button on the console.
The C: drive will automatically be mounted to sd:/DOSBox/ if loaded
from apps/dosbox-wii/. Otherwise, the directory the dol is loaded
from will be mounted as C, and sd:/DOSBox as D (if present).
The Z: driver is a virtual drive that is part of DOSBox.
Other drives can be mounted using the MOUNT command.
Prefix sd: for an SD card, and usb: for a USB drive.
The Wii's DVD drive and network folders can't be mounted at this time.
The configuration is loaded from the directory the dol is located in
(if present) and sd:/DOSBox/dosbox.conf otherwise
This file will be created automatically after you start DOSBox.
Please edit it with a text editor to choose settings appropriate
for each game.
===== =====
NOTE: NOTE:

View File

@ -1,6 +1,12 @@
Some notes about porting DOSBox to systems with certain restrictions, Some notes about porting DOSBox to systems with certain restrictions,
like handheld devices. like handheld devices.
General:
- depending on where you start off with the port, assure that the
config.h entries are correct/exhausting, like GCC_ATTRIBUTE is
required (struct packing) but is undefined if you base the port
on msvc sources which have a special config.h
If memory is a constraint: If memory is a constraint:
- in paging.h out-comment the USE_FULL_TLB define to enable special - in paging.h out-comment the USE_FULL_TLB define to enable special
TLB linking code that uses less memory TLB linking code that uses less memory

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH DOSBOX 1 "Jul 01, 2007" .TH DOSBOX 1 "May 27, 2009"
.\" Please adjust this date whenever revising the manpage. .\" Please adjust this date whenever revising the manpage.
.SH NAME .SH NAME
dosbox \- an x86/DOS emulator with sound/graphics dosbox \- an x86/DOS emulator with sound/graphics
@ -18,7 +18,15 @@ dosbox \- an x86/DOS emulator with sound/graphics
.B [\-exit] .B [\-exit]
.BI "[\-machine " machinetype ] .BI "[\-machine " machinetype ]
.LP .LP
.B dosbox -version .B dosbox \-version
.LP
.BI "dosbox \-editconf" " program"
.LP
.BI "dosbox \-opencaptures" " program"
.LP
.B dosbox \-printconf
.LP
.B dosbox \-eraseconf
.SH DESCRIPTION .SH DESCRIPTION
This manual page briefly documents This manual page briefly documents
.BR "dosbox" ", an x86/DOS emulator." .BR "dosbox" ", an x86/DOS emulator."
@ -74,17 +82,31 @@ wish to execute on startup. Multiple
.RB "Start " dosbox " with the language specified in " .RB "Start " dosbox " with the language specified in "
.IR langfile . .IR langfile .
.TP .TP
.B \-exit .B "\-exit "
.BR dosbox " will close itself when the DOS program specified by "file " ends." .BR "dosbox" " will close itself when the DOS program specified by "file " ends."
.TP .TP
.BI \-machine " machinetype .BI \-machine " machinetype
.RB "Setup " dosbox " to emulate a specific type of machine." .RB "Setup " dosbox " to emulate a specific type of machine."
.RI "Valid choices are: " "hercules, cga, pcjr, tandy, vga(default)". .RI "Valid choices are: " "hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3(default), svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe".
The machinetype has influence on both the videocard and the available The machinetype has influence on both the videocard and the available
soundcards. soundcards.
.TP .TP
.B \-version .B \-version
Output version information and exit. Useful for frontends. Output version information and exit. Useful for frontends.
.TP
.BI \-editconf " program"
.RI calls " program" " with as first parameter the configuration file."
.R You can specify this command more than once. In this case it will
.RI " move to second " program " if the first one fails to start."
.TP
.BI \-opencaptures " program"
.RI "calls " program " with as first paramater the location of the captures folder."
.TP
.B \-printconf
.R prints the location of the default configuration file.
.TP
.B \-eraseconf
.R removes the default configuration file.
.SH "INTERNAL COMMANDS" .SH "INTERNAL COMMANDS"
.B dosbox .B dosbox
supports most of the DOS commands found in command.com. In addition, the supports most of the DOS commands found in command.com. In addition, the
@ -243,11 +265,13 @@ Keyb can change the keyboardlayout and the codepage used inside dosbox.
.RE .RE
.SH FILES .SH FILES
Configuration and language files use a format similar to Windows .ini files. Configuration and language files use a format similar to Windows .ini files.
First ~/.dosboxrc (if present) will be loaded. If no If no configfile is specified at the commandline, a file named
configfile is specified at the commandline, a file named
.BR dosbox.conf " (if present in the current directory) will be" .BR dosbox.conf " (if present in the current directory) will be"
loaded automatically afterwards. If a configfile is specified at the commandline loaded automatically. If a configfile is specified at the commandline
that one will be used instead. that one will be used instead. If no configfile is specified or found
in the current directory
.RB " then dosbox will load one from " ~/.dosbox/ ". It will try to create "
one if there is none.
.SH "SPECIAL KEYS" .SH "SPECIAL KEYS"
.TP 12m .TP 12m
.IP ALT\-ENTER .IP ALT\-ENTER

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: callback.h,v 1.25 2009/06/11 16:05:17 c2woody Exp $ */ /* $Id: callback.h,v 1.26 2009/08/23 17:24:54 c2woody Exp $ */
#ifndef DOSBOX_CALLBACK_H #ifndef DOSBOX_CALLBACK_H
#define DOSBOX_CALLBACK_H #define DOSBOX_CALLBACK_H
@ -71,6 +71,7 @@ bool CALLBACK_Free(Bitu callback);
void CALLBACK_SCF(bool val); void CALLBACK_SCF(bool val);
void CALLBACK_SZF(bool val); void CALLBACK_SZF(bool val);
void CALLBACK_SIF(bool val);
extern Bitu call_priv_io; extern Bitu call_priv_io;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dma.h,v 1.19 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: dma.h,v 1.20 2009/07/24 09:56:14 c2woody Exp $ */
#ifndef DOSBOX_DMA_H #ifndef DOSBOX_DMA_H
#define DOSBOX_DMA_H #define DOSBOX_DMA_H
@ -35,7 +35,7 @@ class DmaChannel {
public: public:
Bit32u pagebase; Bit32u pagebase;
Bit16u baseaddr; Bit16u baseaddr;
Bit16u curraddr; Bit32u curraddr;
Bit16u basecnt; Bit16u basecnt;
Bit16u currcnt; Bit16u currcnt;
Bit8u channum; Bit8u channum;
@ -114,4 +114,6 @@ DmaChannel * GetDMAChannel(Bit8u chan);
void CloseSecondDMAController(void); void CloseSecondDMAController(void);
bool SecondDMAControllerAvailable(void); bool SecondDMAControllerAvailable(void);
static Bit32u dma_wrapping = 0xffff;
#endif #endif

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dos_inc.h,v 1.78 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: dos_inc.h,v 1.82 2009/10/04 14:28:06 c2woody Exp $ */
#ifndef DOSBOX_DOS_INC_H #ifndef DOSBOX_DOS_INC_H
#define DOSBOX_DOS_INC_H #define DOSBOX_DOS_INC_H
@ -86,7 +86,7 @@ enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
#define DOS_SDA_OFS 0 #define DOS_SDA_OFS 0
#define DOS_CDS_SEG 0x108 #define DOS_CDS_SEG 0x108
#define DOS_FIRST_SHELL 0x118 #define DOS_FIRST_SHELL 0x118
#define DOS_MEM_START 0x158 //First Segment that DOS can use #define DOS_MEM_START 0x16f //First Segment that DOS can use
#define DOS_PRIVATE_SEGMENT 0xc800 #define DOS_PRIVATE_SEGMENT 0xc800
#define DOS_PRIVATE_SEGMENT_END 0xd000 #define DOS_PRIVATE_SEGMENT_END 0xd000
@ -154,7 +154,7 @@ void DOS_SetupDevices(void);
bool DOS_NewPSP(Bit16u pspseg,Bit16u size); bool DOS_NewPSP(Bit16u pspseg,Bit16u size);
bool DOS_ChildPSP(Bit16u pspseg,Bit16u size); bool DOS_ChildPSP(Bit16u pspseg,Bit16u size);
bool DOS_Execute(char * name,PhysPt block,Bit8u flags); bool DOS_Execute(char * name,PhysPt block,Bit8u flags);
bool DOS_Terminate(bool tsr,Bit8u exitcode); void DOS_Terminate(Bit16u pspseg,bool tsr,Bit8u exitcode);
/* Memory Handling Routines */ /* Memory Handling Routines */
void DOS_SetupMemory(void); void DOS_SetupMemory(void);
@ -489,7 +489,7 @@ private:
class DOS_FCB: public MemStruct { class DOS_FCB: public MemStruct {
public: public:
DOS_FCB(Bit16u seg,Bit16u off); DOS_FCB(Bit16u seg,Bit16u off,bool allow_extended=true);
void Create(bool _extended); void Create(bool _extended);
void SetName(Bit8u _drive,char * _fname,char * _ext); void SetName(Bit8u _drive,char * _fname,char * _ext);
void SetSizeDateTime(Bit32u _size,Bit16u _date,Bit16u _time); void SetSizeDateTime(Bit32u _size,Bit16u _date,Bit16u _time);

View File

@ -16,16 +16,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: serialport.h,v 1.17 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: serialport.h,v 1.18 2009/09/25 23:40:48 h-a-l-9000 Exp $ */
#ifndef DOSBOX_SERIALPORT_H #ifndef DOSBOX_SERIALPORT_H
#define DOSBOX_SERIALPORT_H #define DOSBOX_SERIALPORT_H
#define SERIAL_DEBUG 0
// Uncomment this for a lot of debug messages:
//#define LOG_UART
#ifndef DOSBOX_DOSBOX_H #ifndef DOSBOX_DOSBOX_H
#include "dosbox.h" #include "dosbox.h"
#endif #endif
@ -42,12 +37,91 @@
#include "programs.h" #include "programs.h"
#endif #endif
// set this to 1 for serial debugging in release mode
#define SERIAL_DBG_FORCED 0
#if (C_DEBUG || SERIAL_DBG_FORCED)
#define SERIAL_DEBUG 1
#endif
#if SERIAL_DEBUG #if SERIAL_DEBUG
#include "hardware.h" #include "hardware.h"
#endif #endif
// Serial port interface // Serial port interface
class MyFifo {
public:
MyFifo(Bitu maxsize_) {
maxsize=size=maxsize_;
pos=used=0;
data=new Bit8u[size];
}
~MyFifo() {
delete[] data;
}
INLINE Bitu getFree(void) {
return size-used;
}
bool isEmpty() {
return used==0;
}
bool isFull() {
return (size-used)==0;
}
INLINE Bitu getUsage(void) {
return used;
}
void setSize(Bitu newsize)
{
size=newsize;
pos=used=0;
}
void clear(void) {
pos=used=0;
data[0]=0;
}
bool addb(Bit8u _val) {
Bitu where=pos+used;
if (where>=size) where-=size;
if(used>=size) {
// overwrite last byte
if(where==0) where=size-1;
else where--;
data[where]=_val;
return false;
}
data[where]=_val;
used++;
return true;
}
Bit8u getb() {
if (!used) return data[pos];
Bitu where=pos;
if (++pos>=size) pos-=size;
used--;
return data[where];
}
Bit8u getTop() {
Bitu where=pos+used;
if (where>=size) where-=size;
if(used>=size) {
if(where==0) where=size-1;
else where--;
}
return data[where];
}
Bit8u probeByte() {
return data[pos];
}
private:
Bit8u * data;
Bitu maxsize,size,pos,used;
};
class CSerial { class CSerial {
public: public:
@ -58,7 +132,7 @@ public:
bool dbg_register; bool dbg_register;
bool dbg_interrupt; bool dbg_interrupt;
bool dbg_aux; bool dbg_aux;
void log_ser(bool active, char const* format,...);
#endif #endif
static bool getBituSubstring(const char* name,Bitu* data, CommandLine* cmd); static bool getBituSubstring(const char* name,Bitu* data, CommandLine* cmd);
@ -92,8 +166,9 @@ public:
#define SERIAL_RX_EVENT 4 #define SERIAL_RX_EVENT 4
#define SERIAL_POLLING_EVENT 5 #define SERIAL_POLLING_EVENT 5
#define SERIAL_THR_EVENT 6 #define SERIAL_THR_EVENT 6
#define SERIAL_RX_TIMEOUT_EVENT 7
#define SERIAL_BASE_EVENT_COUNT 6 #define SERIAL_BASE_EVENT_COUNT 7
#define COMNUMBER idnumber+1 #define COMNUMBER idnumber+1
@ -144,6 +219,7 @@ public:
// If a byte comes from loopback or prepherial, put it in here. // If a byte comes from loopback or prepherial, put it in here.
void receiveByte(Bit8u data); void receiveByte(Bit8u data);
void receiveByteEx(Bit8u data, Bit8u error);
// If an error was received, put it here (in LSR register format) // If an error was received, put it here (in LSR register format)
void receiveError(Bit8u errorword); void receiveError(Bit8u errorword);
@ -177,7 +253,7 @@ private:
DOS_Device* mydosdevice; DOS_Device* mydosdevice;
// I used this spec: http://www.exar.com/products/st16c450v420.pdf // I used this spec: st16c450v420.pdf
void ComputeInterrupts(); void ComputeInterrupts();
@ -191,22 +267,19 @@ private:
#define RX_PRIORITY 1 // a byte has been received #define RX_PRIORITY 1 // a byte has been received
#define TX_PRIORITY 2 // tx buffer has become empty #define TX_PRIORITY 2 // tx buffer has become empty
#define MSR_PRIORITY 8 // CRS, DSR, RI, DCD change #define MSR_PRIORITY 8 // CRS, DSR, RI, DCD change
#define TIMEOUT_PRIORITY 0x10
#define NONE_PRIORITY 0 #define NONE_PRIORITY 0
Bit8u waiting_interrupts; // these are on, but maybe not enabled Bit8u waiting_interrupts; // these are on, but maybe not enabled
// 16C450 (no FIFO) // 16C550
// read/write name // read/write name
Bit16u baud_divider; Bit16u baud_divider;
Bit8u RHR; // r Receive Holding Register, also LSB of Divisor Latch (r/w) #define RHR_OFFSET 0 // r Receive Holding Register, also LSB of Divisor Latch (r/w)
#define RHR_OFFSET 0
// Data: whole byte // Data: whole byte
#define THR_OFFSET 0 // w Transmit Holding Register
Bit8u THR; // w Transmit Holding Register
#define THR_OFFSET 0
// Data: whole byte // Data: whole byte
Bit8u IER; // r/w Interrupt Enable Register, also MSB of Divisor Latch Bit8u IER; // r/w Interrupt Enable Register, also MSB of Divisor Latch
#define IER_OFFSET 1 #define IER_OFFSET 1
@ -221,6 +294,7 @@ private:
#define ISR_OFFSET 2 #define ISR_OFFSET 2
#define ISR_CLEAR_VAL 0x1 #define ISR_CLEAR_VAL 0x1
#define ISR_FIFOTIMEOUT_VAL 0xc
#define ISR_ERROR_VAL 0x6 #define ISR_ERROR_VAL 0x6
#define ISR_RX_VAL 0x4 #define ISR_RX_VAL 0x4
#define ISR_TX_VAL 0x2 #define ISR_TX_VAL 0x2
@ -292,6 +366,7 @@ private:
Bitu framingErrors; Bitu framingErrors;
Bitu parityErrors; Bitu parityErrors;
Bitu overrunErrors; Bitu overrunErrors;
Bitu txOverrunErrors;
Bitu overrunIF0; Bitu overrunIF0;
Bitu breakErrors; Bitu breakErrors;
@ -329,16 +404,28 @@ private:
void transmitLoopbackByte(Bit8u val, bool value); void transmitLoopbackByte(Bit8u val, bool value);
// 16C550 (FIFO) // 16C550 (FIFO)
// TODO public: // todo remove
MyFifo* rxfifo;
private:
MyFifo* txfifo;
MyFifo* errorfifo;
Bitu errors_in_fifo;
Bitu rx_interrupt_threshold;
Bitu fifosize;
Bit8u FCR;
bool sync_guardtime;
#define FIFO_STATUS_ACTIVE 0xc0 // FIFO is active AND works ;)
#define FIFO_ERROR 0x80
#define FCR_ACTIVATE 0x01
#define FCR_CLEAR_RX 0x02
#define FCR_CLEAR_TX 0x04
#define FCR_OFFSET 2 #define FCR_OFFSET 2
bool fifo_warn; #define FIFO_FLOWCONTROL 0x20
//Bit8u FCR; // FIFO Control Register
}; };
extern CSerial* serialports[]; extern CSerial* serialports[];
const Bit8u serial_defaultirq[4] = { 4, 3, 4, 3 }; const Bit8u serial_defaultirq[] = { 4, 3, 4, 3 };
const Bit16u serial_baseaddr[4] = {0x3f8,0x2f8,0x3e8,0x2e8}; const Bit16u serial_baseaddr[] = {0x3f8,0x2f8,0x3e8,0x2e8};
const char* const serial_comname[]={"COM1","COM2","COM3","COM4"}; const char* const serial_comname[]={"COM1","COM2","COM3","COM4"};
// the COM devices // the COM devices
@ -358,4 +445,3 @@ private:
}; };
#endif #endif

View File

@ -26,7 +26,9 @@
#pragma warning ( disable : 4290 ) #pragma warning ( disable : 4290 )
#endif #endif
#ifdef HW_RVL
#include <stdio.h> #include <stdio.h>
#endif
#ifndef CH_LIST #ifndef CH_LIST
#define CH_LIST #define CH_LIST

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: shell.h,v 1.27 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: shell.h,v 1.28 2009/07/03 19:36:57 qbix79 Exp $ */
#ifndef DOSBOX_SHELL_H #ifndef DOSBOX_SHELL_H
#define DOSBOX_SHELL_H #define DOSBOX_SHELL_H
@ -55,6 +55,7 @@ public:
DOS_Shell * shell; DOS_Shell * shell;
BatchFile * prev; BatchFile * prev;
CommandLine * cmd; CommandLine * cmd;
std::string filename;
}; };
class AutoexecEditor; class AutoexecEditor;

View File

@ -1,8 +1,8 @@
!define VER_MAYOR 0 !define VER_MAYOR 0
!define VER_MINOR 72 !define VER_MINOR 73
!define APP_NAME "DOSBox ${VER_MAYOR}.${VER_MINOR} Installer" !define APP_NAME "DOSBox ${VER_MAYOR}.${VER_MINOR} Installer"
!define COMP_NAME "DOSBox Team" !define COMP_NAME "DOSBox Team"
!define COPYRIGHT "Copyright © 2002-2008 DOSBox Team" !define COPYRIGHT "Copyright © 2002-2009 DOSBox Team"
!define DESCRIPTION "DOSBox Installer" !define DESCRIPTION "DOSBox Installer"
VIProductVersion "${VER_MAYOR}.${VER_MINOR}.0.0" VIProductVersion "${VER_MAYOR}.${VER_MINOR}.0.0"
@ -32,10 +32,13 @@ LicenseText "DOSBox v${VER_MAYOR}.${VER_MINOR} License" "Next >"
; Else vista enables compatibility mode ; Else vista enables compatibility mode
RequestExecutionLevel admin RequestExecutionLevel admin
; Shortcuts in all users
ComponentText "Select components for DOSBox" ComponentText "Select components for DOSBox"
; The stuff to install ; The stuff to install
Section "!Core files" Core Section "!Core files" Core
SetShellVarContext all
; Set output path to the installation directory. ; Set output path to the installation directory.
ClearErrors ClearErrors
SetOutPath $INSTDIR SetOutPath $INSTDIR
@ -44,7 +47,6 @@ Section "!Core files" Core
; Put file there ; Put file there
CreateDirectory "$INSTDIR\capture"
CreateDirectory "$INSTDIR\zmbv" CreateDirectory "$INSTDIR\zmbv"
File /oname=README.txt README File /oname=README.txt README
File /oname=COPYING.txt COPYING File /oname=COPYING.txt COPYING
@ -53,7 +55,6 @@ Section "!Core files" Core
File /oname=AUTHORS.txt AUTHORS File /oname=AUTHORS.txt AUTHORS
File /oname=INSTALL.txt INSTALL File /oname=INSTALL.txt INSTALL
File DOSBox.exe File DOSBox.exe
File dosbox.conf
File SDL.dll File SDL.dll
File SDL_net.dll File SDL_net.dll
File /oname=zmbv\zmbv.dll zmbv.dll File /oname=zmbv\zmbv.dll zmbv.dll
@ -62,12 +63,14 @@ Section "!Core files" Core
CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}" CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}"
CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video" CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video"
CreateDirectory "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration"
CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.lnk" "$INSTDIR\DOSBox.exe" "-conf $\"$INSTDIR\dosbox.conf$\"" "$INSTDIR\DOSBox.exe" 0 CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.lnk" "$INSTDIR\DOSBox.exe" "" "$INSTDIR\DOSBox.exe" 0
CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox (noconsole).lnk" "$INSTDIR\DOSBox.exe" "-noconsole -conf $\"$INSTDIR\dosbox.conf$\"" "$INSTDIR\DOSBox.exe" 0 CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox (noconsole).lnk" "$INSTDIR\DOSBox.exe" "-noconsole" "$INSTDIR\DOSBox.exe" 0
CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\README.lnk" "$INSTDIR\README.txt" CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\README.lnk" "$INSTDIR\README.txt"
CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.conf.lnk" "notepad.exe" "$INSTDIR\dosbox.conf" CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration\Edit Configuration.lnk" "$INSTDIR\DOSBox.exe" "-editconf notepad.exe -editconf $\"%SystemRoot%\system32\notepad.exe$\" -editconf $\"%WINDIR%\notepad.exe$\""
CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Capture folder.lnk" "$INSTDIR\capture" CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration\Reset Configuration.lnk" "$INSTDIR\DOSBox.exe" "-eraseconf"
CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Capture folder.lnk" "$INSTDIR\DOSBox.exe" "-opencaptures explorer.exe"
CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Video instructions.lnk" "$INSTDIR\zmbv\README.txt" CreateShortCut "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Video instructions.lnk" "$INSTDIR\zmbv\README.txt"
;change outpath so the working directory gets set to zmbv ;change outpath so the working directory gets set to zmbv
SetOutPath "$INSTDIR\zmbv" SetOutPath "$INSTDIR\zmbv"
@ -97,8 +100,9 @@ end_section:
SectionEnd ; end the section SectionEnd ; end the section
Section "Desktop Shortcut" SecDesktop Section "Desktop Shortcut" SecDesktop
SetShellVarContext all
CreateShortCut "$DESKTOP\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" "$INSTDIR\DOSBox.exe" "-conf $\"$INSTDIR\dosbox.conf$\"" "$INSTDIR\DOSBox.exe" 0 CreateShortCut "$DESKTOP\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" "$INSTDIR\DOSBox.exe" "" "$INSTDIR\DOSBox.exe" 0
SectionEnd ; end the section SectionEnd ; end the section
@ -106,6 +110,10 @@ CreateShortCut "$DESKTOP\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" "$INSTDIR\DOSBox.
UninstallText "This will uninstall DOSBox v${VER_MAYOR}.${VER_MINOR}. Hit next to continue." UninstallText "This will uninstall DOSBox v${VER_MAYOR}.${VER_MINOR}. Hit next to continue."
Section "Uninstall" Section "Uninstall"
; Shortcuts in all users
SetShellVarContext all
Delete "$DESKTOP\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk" Delete "$DESKTOP\DOSBox ${VER_MAYOR}.${VER_MINOR}.lnk"
; remove registry keys ; remove registry keys
; remove files ; remove files
@ -116,7 +124,6 @@ Section "Uninstall"
Delete $INSTDIR\AUTHORS.txt Delete $INSTDIR\AUTHORS.txt
Delete $INSTDIR\INSTALL.txt Delete $INSTDIR\INSTALL.txt
Delete $INSTDIR\DOSBox.exe Delete $INSTDIR\DOSBox.exe
Delete $INSTDIR\dosbox.conf
Delete $INSTDIR\SDL.dll Delete $INSTDIR\SDL.dll
Delete $INSTDIR\SDL_net.dll Delete $INSTDIR\SDL_net.dll
Delete $INSTDIR\zmbv\zmbv.dll Delete $INSTDIR\zmbv\zmbv.dll
@ -134,14 +141,15 @@ Section "Uninstall"
Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\README.lnk" Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\README.lnk"
Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.lnk" Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.lnk"
Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox (noconsole).lnk" Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox (noconsole).lnk"
Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\DOSBox.conf.lnk" Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration\Edit Configuration.lnk"
Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration\Reset Configuration.lnk"
Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Capture folder.lnk" Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Capture folder.lnk"
Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Install movie codec.lnk" Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Install movie codec.lnk"
Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Video instructions.lnk" Delete "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video\Video instructions.lnk"
; remove directories used. ; remove directories used.
RMDir "$INSTDIR\zmbv" RMDir "$INSTDIR\zmbv"
RMDir "$INSTDIR\capture"
RMDir "$INSTDIR" RMDir "$INSTDIR"
RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Configuration"
RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video" RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}\Video"
RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}" RMDir "$SMPROGRAMS\DOSBox-${VER_MAYOR}.${VER_MINOR}"
SectionEnd SectionEnd

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: callback.cpp,v 1.41 2009/06/11 16:05:17 c2woody Exp $ */ /* $Id: callback.cpp,v 1.42 2009/08/23 17:24:54 c2woody Exp $ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -109,15 +109,24 @@ void CALLBACK_RunRealInt(Bit8u intnum) {
} }
void CALLBACK_SZF(bool val) { void CALLBACK_SZF(bool val) {
Bit16u tempf=mem_readw(SegPhys(ss)+reg_sp+4) & 0xFFBF; Bit16u tempf = mem_readw(SegPhys(ss)+reg_sp+4);
Bit16u newZF=(val==true) << 6; if (val) tempf |= FLAG_ZF;
mem_writew(SegPhys(ss)+reg_sp+4,(tempf | newZF)); else tempf &= ~FLAG_ZF;
mem_writew(SegPhys(ss)+reg_sp+4,tempf);
} }
void CALLBACK_SCF(bool val) { void CALLBACK_SCF(bool val) {
Bit16u tempf=mem_readw(SegPhys(ss)+reg_sp+4) & 0xFFFE; Bit16u tempf = mem_readw(SegPhys(ss)+reg_sp+4);
Bit16u newCF=(val==true); if (val) tempf |= FLAG_CF;
mem_writew(SegPhys(ss)+reg_sp+4,(tempf | newCF)); else tempf &= ~FLAG_CF;
mem_writew(SegPhys(ss)+reg_sp+4,tempf);
}
void CALLBACK_SIF(bool val) {
Bit16u tempf = mem_readw(SegPhys(ss)+reg_sp+4);
if (val) tempf |= FLAG_IF;
else tempf &= ~FLAG_IF;
mem_writew(SegPhys(ss)+reg_sp+4,tempf);
} }
void CALLBACK_SetDescription(Bitu nr, const char* descr) { void CALLBACK_SetDescription(Bitu nr, const char* descr) {

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: core_dyn_x86.cpp,v 1.35 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: core_dyn_x86.cpp,v 1.36 2009/07/20 17:55:52 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
@ -306,7 +306,10 @@ run_block:
return debugCallback; return debugCallback;
} }
#endif #endif
if (!GETFLAG(TF)) goto restart_core; if (!GETFLAG(TF)) {
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
goto restart_core;
}
cpudecoder=CPU_Core_Dyn_X86_Trap_Run; cpudecoder=CPU_Core_Dyn_X86_Trap_Run;
if (!dyn_dh_fpu.state_used) return CBRET_NONE; if (!dyn_dh_fpu.state_used) return CBRET_NONE;
DH_FPU_SAVE_REINIT DH_FPU_SAVE_REINIT

View File

@ -1,3 +1,23 @@
/*
* Copyright (C) 2002-2009 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: cache.h,v 1.20 2009/07/12 20:13:05 c2woody Exp $ */
class CacheBlock { class CacheBlock {
public: public:
void Clear(void); void Clear(void);
@ -88,6 +108,10 @@ public:
return is_current_block; return is_current_block;
} }
void writeb(PhysPt addr,Bitu val){ void writeb(PhysPt addr,Bitu val){
if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return;
if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
E_Exit("wb:non-readable code page found that is no ROM page");
}
addr&=4095; addr&=4095;
if (host_readb(hostmem+addr)==(Bit8u)val) return; if (host_readb(hostmem+addr)==(Bit8u)val) return;
host_writeb(hostmem+addr,val); host_writeb(hostmem+addr,val);
@ -104,6 +128,10 @@ public:
InvalidateRange(addr,addr); InvalidateRange(addr,addr);
} }
void writew(PhysPt addr,Bitu val){ void writew(PhysPt addr,Bitu val){
if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return;
if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
E_Exit("ww:non-readable code page found that is no ROM page");
}
addr&=4095; addr&=4095;
if (host_readw(hostmem+addr)==(Bit16u)val) return; if (host_readw(hostmem+addr)==(Bit16u)val) return;
host_writew(hostmem+addr,val); host_writew(hostmem+addr,val);
@ -120,6 +148,10 @@ public:
InvalidateRange(addr,addr+1); InvalidateRange(addr,addr+1);
} }
void writed(PhysPt addr,Bitu val){ void writed(PhysPt addr,Bitu val){
if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return;
if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
E_Exit("wd:non-readable code page found that is no ROM page");
}
addr&=4095; addr&=4095;
if (host_readd(hostmem+addr)==(Bit32u)val) return; if (host_readd(hostmem+addr)==(Bit32u)val) return;
host_writed(hostmem+addr,val); host_writed(hostmem+addr,val);
@ -136,6 +168,10 @@ public:
InvalidateRange(addr,addr+3); InvalidateRange(addr,addr+3);
} }
bool writeb_checked(PhysPt addr,Bitu val) { bool writeb_checked(PhysPt addr,Bitu val) {
if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return false;
if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
E_Exit("cb:non-readable code page found that is no ROM page");
}
addr&=4095; addr&=4095;
if (host_readb(hostmem+addr)==(Bit8u)val) return false; if (host_readb(hostmem+addr)==(Bit8u)val) return false;
if (!*(Bit8u*)&write_map[addr]) { if (!*(Bit8u*)&write_map[addr]) {
@ -158,6 +194,10 @@ public:
return false; return false;
} }
bool writew_checked(PhysPt addr,Bitu val) { bool writew_checked(PhysPt addr,Bitu val) {
if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return false;
if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
E_Exit("cw:non-readable code page found that is no ROM page");
}
addr&=4095; addr&=4095;
if (host_readw(hostmem+addr)==(Bit16u)val) return false; if (host_readw(hostmem+addr)==(Bit16u)val) return false;
if (!*(Bit16u*)&write_map[addr]) { if (!*(Bit16u*)&write_map[addr]) {
@ -180,6 +220,10 @@ public:
return false; return false;
} }
bool writed_checked(PhysPt addr,Bitu val) { bool writed_checked(PhysPt addr,Bitu val) {
if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return false;
if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
E_Exit("cd:non-readable code page found that is no ROM page");
}
addr&=4095; addr&=4095;
if (host_readd(hostmem+addr)==(Bit32u)val) return false; if (host_readd(hostmem+addr)==(Bit32u)val) return false;
if (!*(Bit32u*)&write_map[addr]) { if (!*(Bit32u*)&write_map[addr]) {

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: decoder.h,v 1.57 2009/03/29 17:32:20 qbix79 Exp $ */ /* $Id: decoder.h,v 1.58 2009/10/08 20:01:31 c2woody Exp $ */
#define X86_DYNFPU_DH_ENABLED #define X86_DYNFPU_DH_ENABLED
#define X86_INLINED_MEMACCESS #define X86_INLINED_MEMACCESS
@ -187,6 +187,11 @@ static INLINE void decode_increase_wmapmask(Bitu size) {
static bool decode_fetchb_imm(Bitu & val) { static bool decode_fetchb_imm(Bitu & val) {
if (decode.page.index<4096) { if (decode.page.index<4096) {
if (decode.page.invmap != NULL) {
if (decode.page.invmap[decode.page.index] == 0) {
val=(Bit32u)decode_fetchb();
return false;
}
HostPt tlb_addr=get_tlb_read(decode.code); HostPt tlb_addr=get_tlb_read(decode.code);
if (tlb_addr) { if (tlb_addr) {
val=(Bitu)(tlb_addr+decode.code); val=(Bitu)(tlb_addr+decode.code);
@ -196,11 +201,19 @@ static bool decode_fetchb_imm(Bitu & val) {
return true; return true;
} }
} }
}
val=(Bit32u)decode_fetchb(); val=(Bit32u)decode_fetchb();
return false; return false;
} }
static bool decode_fetchw_imm(Bitu & val) { static bool decode_fetchw_imm(Bitu & val) {
if (decode.page.index<4095) { if (decode.page.index<4095) {
if (decode.page.invmap != NULL) {
if ((decode.page.invmap[decode.page.index] == 0) &&
(decode.page.invmap[decode.page.index + 1] == 0)
) {
val=decode_fetchw();
return false;
}
HostPt tlb_addr=get_tlb_read(decode.code); HostPt tlb_addr=get_tlb_read(decode.code);
if (tlb_addr) { if (tlb_addr) {
val=(Bitu)(tlb_addr+decode.code); val=(Bitu)(tlb_addr+decode.code);
@ -210,11 +223,21 @@ static bool decode_fetchw_imm(Bitu & val) {
return true; return true;
} }
} }
}
val=decode_fetchw(); val=decode_fetchw();
return false; return false;
} }
static bool decode_fetchd_imm(Bitu & val) { static bool decode_fetchd_imm(Bitu & val) {
if (decode.page.index<4093) { if (decode.page.index<4093) {
if (decode.page.invmap != NULL) {
if ((decode.page.invmap[decode.page.index] == 0) &&
(decode.page.invmap[decode.page.index + 1] == 0) &&
(decode.page.invmap[decode.page.index + 2] == 0) &&
(decode.page.invmap[decode.page.index + 3] == 0)
) {
val=decode_fetchd();
return false;
}
HostPt tlb_addr=get_tlb_read(decode.code); HostPt tlb_addr=get_tlb_read(decode.code);
if (tlb_addr) { if (tlb_addr) {
val=(Bitu)(tlb_addr+decode.code); val=(Bitu)(tlb_addr+decode.code);
@ -224,6 +247,7 @@ static bool decode_fetchd_imm(Bitu & val) {
return true; return true;
} }
} }
}
val=decode_fetchd(); val=decode_fetchd();
return false; return false;
} }
@ -2649,8 +2673,13 @@ restart_prefix:
goto illegalopcode; goto illegalopcode;
} }
} }
/* Normal exit because of max opcodes reached */ // link to next block because the maximal number of opcodes has been reached
dyn_set_eip_end(); dyn_set_eip_end();
dyn_reduce_cycles();
dyn_save_critical_regs();
gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
dyn_closeblock();
goto finish_block;
core_close_block: core_close_block:
dyn_reduce_cycles(); dyn_reduce_cycles();
dyn_save_critical_regs(); dyn_save_critical_regs();

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dyn_fpu.h,v 1.4 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: dyn_fpu.h,v 1.5 2009/09/23 20:55:19 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
#if C_FPU #if C_FPU
@ -593,6 +593,11 @@ static void dyn_fpu_esc7(){
Bitu sub=(decode.modrm.val & 7); Bitu sub=(decode.modrm.val & 7);
if (decode.modrm.val >= 0xc0) { if (decode.modrm.val >= 0xc0) {
switch (group){ switch (group){
case 0x00: /* FFREEP STi*/
dyn_fpu_top();
gen_call_function((void*)&FPU_FFREE,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x01: /* FXCH STi*/ case 0x01: /* FXCH STi*/
dyn_fpu_top(); dyn_fpu_top();
gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA)); gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dyn_fpu_dh.h,v 1.6 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: dyn_fpu_dh.h,v 1.7 2009/09/23 20:55:19 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
#if C_FPU #if C_FPU
@ -408,6 +408,10 @@ static void dh_fpu_esc7(){
Bitu sub=(decode.modrm.val & 7); Bitu sub=(decode.modrm.val & 7);
if (decode.modrm.val >= 0xc0) { if (decode.modrm.val >= 0xc0) {
switch (group){ switch (group){
case 0x00: /* FFREEP STi*/
cache_addb(0xdf);
cache_addb(decode.modrm.val);
break;
case 0x01: /* FXCH STi*/ case 0x01: /* FXCH STi*/
cache_addb(0xdf); cache_addb(0xdf);
cache_addb(decode.modrm.val); cache_addb(decode.modrm.val);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: core_dynrec.cpp,v 1.12 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: core_dynrec.cpp,v 1.15 2009/08/02 16:52:33 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
@ -51,6 +51,7 @@
#include "paging.h" #include "paging.h"
#include "inout.h" #include "inout.h"
#include "lazyflags.h" #include "lazyflags.h"
#include "pic.h"
#define CACHE_MAXSIZE (4096*2) #define CACHE_MAXSIZE (4096*2)
#define CACHE_TOTAL (1024*1024*8) #define CACHE_TOTAL (1024*1024*8)
@ -99,9 +100,9 @@
#define DRCD_SEG_PHYS(seg) (&Segs.phys[seg]) #define DRCD_SEG_PHYS(seg) (&Segs.phys[seg])
// access to an 8bit general register // access to an 8bit general register
#define DRCD_REG_BYTE(reg,idx) (&cpu_regs.regs[reg].byte[idx]) #define DRCD_REG_BYTE(reg,idx) (&cpu_regs.regs[reg].byte[idx?BH_INDEX:BL_INDEX])
// access to 16/32bit general registers // access to 16/32bit general registers
#define DRCD_REG_WORD(reg,dwrd) ((dwrd)?((void*)(&cpu_regs.regs[reg].dword)):((void*)(&cpu_regs.regs[reg].word))) #define DRCD_REG_WORD(reg,dwrd) ((dwrd)?((void*)(&cpu_regs.regs[reg].dword[DW_INDEX])):((void*)(&cpu_regs.regs[reg].word[W_INDEX])))
enum BlockReturn { enum BlockReturn {
@ -139,6 +140,7 @@ static struct {
#define X86_64 0x02 #define X86_64 0x02
#define MIPSEL 0x03 #define MIPSEL 0x03
#define ARMV4LE 0x04 #define ARMV4LE 0x04
#define POWERPC 0x04
#if C_TARGETCPU == X86_64 #if C_TARGETCPU == X86_64
#include "core_dynrec/risc_x64.h" #include "core_dynrec/risc_x64.h"
@ -148,6 +150,8 @@ static struct {
#include "core_dynrec/risc_mipsel32.h" #include "core_dynrec/risc_mipsel32.h"
#elif C_TARGETCPU == ARMV4LE #elif C_TARGETCPU == ARMV4LE
#include "core_dynrec/risc_armv4le.h" #include "core_dynrec/risc_armv4le.h"
#elif C_TARGETCPU == POWERPC
#include "core_dynrec/risc_ppc.h"
#endif #endif
#include "core_dynrec/decoder.h" #include "core_dynrec/decoder.h"
@ -233,7 +237,10 @@ run_block:
#if C_HEAVY_DEBUG #if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback; if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif #endif
if (!GETFLAG(TF)) break; if (!GETFLAG(TF)) {
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
break;
}
// trapflag is set, switch to the trap-aware decoder // trapflag is set, switch to the trap-aware decoder
cpudecoder=CPU_Core_Dynrec_Trap_Run; cpudecoder=CPU_Core_Dynrec_Trap_Run;
return CBRET_NONE; return CBRET_NONE;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: decoder.h,v 1.6 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: decoder.h,v 1.7 2009/10/08 20:01:31 c2woody Exp $ */
#include "decoder_basic.h" #include "decoder_basic.h"
@ -574,8 +574,12 @@ restart_prefix:
goto illegalopcode; goto illegalopcode;
} }
} }
// normal exit because the maximal number of opcodes has been reached // link to next block because the maximal number of opcodes has been reached
dyn_set_eip_end(); dyn_set_eip_end();
dyn_reduce_cycles();
gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start));
dyn_closeblock();
goto finish_block;
core_close_block: core_close_block:
dyn_reduce_cycles(); dyn_reduce_cycles();
dyn_return(BR_Normal); dyn_return(BR_Normal);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: decoder_basic.h,v 1.15 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: decoder_basic.h,v 1.16 2009/10/08 20:01:31 c2woody Exp $ */
/* /*
@ -290,8 +290,15 @@ static bool decode_fetchb_imm(Bitu & val) {
if (GCC_UNLIKELY(decode.page.index>=4096)) { if (GCC_UNLIKELY(decode.page.index>=4096)) {
decode_advancepage(); decode_advancepage();
} }
HostPt tlb_addr=get_tlb_read(decode.code);
// see if position is directly accessible // see if position is directly accessible
if (decode.page.invmap != NULL) {
if (decode.page.invmap[decode.page.index] == 0) {
// position not yet modified
val=(Bit32u)decode_fetchb();
return false;
}
HostPt tlb_addr=get_tlb_read(decode.code);
if (tlb_addr) { if (tlb_addr) {
val=(Bitu)(tlb_addr+decode.code); val=(Bitu)(tlb_addr+decode.code);
decode_increase_wmapmask(1); decode_increase_wmapmask(1);
@ -299,7 +306,8 @@ static bool decode_fetchb_imm(Bitu & val) {
decode.page.index++; decode.page.index++;
return true; return true;
} }
// not directly accessible, just fetch the value }
// first time decoding or not directly accessible, just fetch the value
val=(Bit32u)decode_fetchb(); val=(Bit32u)decode_fetchb();
return false; return false;
} }
@ -308,6 +316,14 @@ static bool decode_fetchb_imm(Bitu & val) {
// otherwise val contains the current value read from the position // otherwise val contains the current value read from the position
static bool decode_fetchw_imm(Bitu & val) { static bool decode_fetchw_imm(Bitu & val) {
if (decode.page.index<4095) { if (decode.page.index<4095) {
if (decode.page.invmap != NULL) {
if ((decode.page.invmap[decode.page.index] == 0) &&
(decode.page.invmap[decode.page.index + 1] == 0)) {
// position not yet modified
val=decode_fetchw();
return false;
}
HostPt tlb_addr=get_tlb_read(decode.code); HostPt tlb_addr=get_tlb_read(decode.code);
// see if position is directly accessible // see if position is directly accessible
if (tlb_addr) { if (tlb_addr) {
@ -318,7 +334,8 @@ static bool decode_fetchw_imm(Bitu & val) {
return true; return true;
} }
} }
// not directly accessible, just fetch the value }
// first time decoding or not directly accessible, just fetch the value
val=decode_fetchw(); val=decode_fetchw();
return false; return false;
} }
@ -327,6 +344,16 @@ static bool decode_fetchw_imm(Bitu & val) {
// otherwise val contains the current value read from the position // otherwise val contains the current value read from the position
static bool decode_fetchd_imm(Bitu & val) { static bool decode_fetchd_imm(Bitu & val) {
if (decode.page.index<4093) { if (decode.page.index<4093) {
if (decode.page.invmap != NULL) {
if ((decode.page.invmap[decode.page.index] == 0) &&
(decode.page.invmap[decode.page.index + 1] == 0) &&
(decode.page.invmap[decode.page.index + 2] == 0) &&
(decode.page.invmap[decode.page.index + 3] == 0)) {
// position not yet modified
val=decode_fetchd();
return false;
}
HostPt tlb_addr=get_tlb_read(decode.code); HostPt tlb_addr=get_tlb_read(decode.code);
// see if position is directly accessible // see if position is directly accessible
if (tlb_addr) { if (tlb_addr) {
@ -337,7 +364,8 @@ static bool decode_fetchd_imm(Bitu & val) {
return true; return true;
} }
} }
// not directly accessible, just fetch the value }
// first time decoding or not directly accessible, just fetch the value
val=decode_fetchd(); val=decode_fetchd();
return false; return false;
} }

View File

@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dyn_fpu.h,v 1.8 2009/09/23 20:55:19 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
#if C_FPU #if C_FPU
@ -602,6 +604,11 @@ static void dyn_fpu_esc7(){
dyn_get_modrm(); dyn_get_modrm();
if (decode.modrm.val >= 0xc0) { if (decode.modrm.val >= 0xc0) {
switch (decode.modrm.reg){ switch (decode.modrm.reg){
case 0x00: /* FFREEP STi */
dyn_fpu_top();
gen_call_function_R((void*)&FPU_FFREE,FC_OP2);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x01: /* FXCH STi*/ case 0x01: /* FXCH STi*/
dyn_fpu_top(); dyn_fpu_top();
gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2);

View File

@ -356,6 +356,63 @@
CASE_0F_W(0xaf) /* IMUL Gw,Ew */ CASE_0F_W(0xaf) /* IMUL Gw,Ew */
RMGwEwOp3(DIMULW,*rmrw); RMGwEwOp3(DIMULW,*rmrw);
break; break;
CASE_0F_B(0xb0) /* cmpxchg Eb,Gb */
{
if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
FillFlags();
GetRMrb;
if (rm >= 0xc0 ) {
GetEArb;
if (reg_al == *earb) {
*earb=*rmrb;
SETFLAGBIT(ZF,1);
} else {
reg_al = *earb;
SETFLAGBIT(ZF,0);
}
} else {
GetEAa;
Bit8u val = LoadMb(eaa);
if (reg_al == val) {
SaveMb(eaa,*rmrb);
SETFLAGBIT(ZF,1);
} else {
SaveMb(eaa,val); // cmpxchg always issues a write
reg_al = val;
SETFLAGBIT(ZF,0);
}
}
break;
}
CASE_0F_W(0xb1) /* cmpxchg Ew,Gw */
{
if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
FillFlags();
GetRMrw;
if (rm >= 0xc0 ) {
GetEArw;
if(reg_ax == *earw) {
*earw = *rmrw;
SETFLAGBIT(ZF,1);
} else {
reg_ax = *earw;
SETFLAGBIT(ZF,0);
}
} else {
GetEAa;
Bit16u val = LoadMw(eaa);
if(reg_ax == val) {
SaveMw(eaa,*rmrw);
SETFLAGBIT(ZF,1);
} else {
SaveMw(eaa,val); // cmpxchg always issues a write
reg_ax = val;
SETFLAGBIT(ZF,0);
}
}
break;
}
CASE_0F_W(0xb2) /* LSS Ew */ CASE_0F_W(0xb2) /* LSS Ew */
{ {
GetRMrw; GetRMrw;

View File

@ -256,7 +256,7 @@
SaveMd(eaa,*rmrd); SaveMd(eaa,*rmrd);
SETFLAGBIT(ZF,1); SETFLAGBIT(ZF,1);
} else { } else {
SaveMd(eaa,val); SaveMd(eaa,val); // cmpxchg always issues a write
reg_eax=val; reg_eax=val;
SETFLAGBIT(ZF,0); SETFLAGBIT(ZF,0);
} }

View File

@ -23,14 +23,10 @@
#include "dosbox.h" #include "dosbox.h"
#include "cpu.h" #include "cpu.h"
#ifdef HW_RVL #ifdef HW_RVL
// memory.h doesn't exist for Wii #include "string.h"
#else
#ifdef HW_DOL
// memory.h doesn't exist for Gamecube
#else #else
#include "memory.h" #include "memory.h"
#endif #endif
#endif
#include "debug.h" #include "debug.h"
#include "mapper.h" #include "mapper.h"
#include "setup.h" #include "setup.h"

View File

@ -398,6 +398,7 @@ static char const *fop_52[] = { "*fsubrp %GF,st" };
static char const *fop_53[] = { "*fsubp %GF,st" }; static char const *fop_53[] = { "*fsubp %GF,st" };
static char const *fop_54[] = { "*fdivrp %GF,st" }; static char const *fop_54[] = { "*fdivrp %GF,st" };
static char const *fop_55[] = { "*fdivp %GF,st" }; static char const *fop_55[] = { "*fdivp %GF,st" };
static char const *fop_56[] = { "*ffreep %GF" };
static char const *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 }; static char const *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 };
static char const **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */ static char const **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
@ -408,7 +409,7 @@ static char const **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means
fop_32, fop_33, fop_34, fop_35, fop_36, fop_37, fop_38, fop_39, fop_32, fop_33, fop_34, fop_35, fop_36, fop_37, fop_38, fop_39,
fop_40, fop_41, fop_42, fop_43, fop_44, fop_45, f0, f0, fop_40, fop_41, fop_42, fop_43, fop_44, fop_45, f0, f0,
fop_48, fop_49, fop_50, fop_51, fop_52, fop_53, fop_54, fop_55, fop_48, fop_49, fop_50, fop_51, fop_52, fop_53, fop_54, fop_55,
f0, f0, f0, f0, fop_60, f0, f0, f0, fop_56, f0, f0, f0, fop_60, f0, f0, f0,
}; };
static const char *floatops[] = { /* assumed " %EF" at end of each. mod != 3 only */ static const char *floatops[] = { /* assumed " %EF" at end of each. mod != 3 only */

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dos.cpp,v 1.117 2009/04/16 12:16:52 qbix79 Exp $ */ /* $Id: dos.cpp,v 1.120 2009/10/04 14:28:07 c2woody Exp $ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -70,6 +70,9 @@ static Bitu DOS_21Handler(void) {
char name1[DOSNAMEBUF+2+DOS_NAMELENGTH_ASCII]; char name1[DOSNAMEBUF+2+DOS_NAMELENGTH_ASCII];
char name2[DOSNAMEBUF+2+DOS_NAMELENGTH_ASCII]; char name2[DOSNAMEBUF+2+DOS_NAMELENGTH_ASCII];
switch (reg_ah) { switch (reg_ah) {
case 0x00: /* Terminate Program */
DOS_Terminate(mem_readw(SegPhys(ss)+reg_sp+2),false,0);
break;
case 0x01: /* Read character from STDIN, with echo */ case 0x01: /* Read character from STDIN, with echo */
{ {
Bit8u c;Bit16u n=1; Bit8u c;Bit16u n=1;
@ -83,6 +86,8 @@ static Bitu DOS_21Handler(void) {
{ {
Bit8u c=reg_dl;Bit16u n=1; Bit8u c=reg_dl;Bit16u n=1;
DOS_WriteFile(STDOUT,&c,&n); DOS_WriteFile(STDOUT,&c,&n);
//Not in the official specs, but happens nonetheless. (last written character)
reg_al = c;// reg_al=(c==9)?0x20:c; //Officially: tab to spaces
} }
break; break;
case 0x03: /* Read character from STDAUX */ case 0x03: /* Read character from STDAUX */
@ -115,7 +120,7 @@ static Bitu DOS_21Handler(void) {
switch (reg_dl) { switch (reg_dl) {
case 0xFF: /* Input */ case 0xFF: /* Input */
{ {
//TODO Make this better according to standards //TODO Make this better according to standards
if (!DOS_GetSTDINStatus()) { if (!DOS_GetSTDINStatus()) {
reg_al=0; reg_al=0;
CALLBACK_SZF(true); CALLBACK_SZF(true);
@ -388,17 +393,17 @@ static Bitu DOS_21Handler(void) {
reg_cx=0x0000; reg_cx=0x0000;
break; break;
case 0x31: /* Terminate and stay resident */ case 0x31: /* Terminate and stay resident */
//TODO First get normal files executing
// Important: This service does not set the carry flag! // Important: This service does not set the carry flag!
DOS_ResizeMemory(dos.psp(),&reg_dx); DOS_ResizeMemory(dos.psp(),&reg_dx);
DOS_Terminate(true,reg_al); DOS_Terminate(dos.psp(),true,reg_al);
dos.return_mode=RETURN_TSR;
break; break;
case 0x1f: /* Get drive parameter block for default drive */ case 0x1f: /* Get drive parameter block for default drive */
case 0x32: /* Get drive parameter block for specific drive */ case 0x32: /* Get drive parameter block for specific drive */
{ /* Officially a dpb should be returned as well. The disk detection part is implemented */ { /* Officially a dpb should be returned as well. The disk detection part is implemented */
Bitu drive=reg_dl;if(!drive || reg_ah==0x1f) drive = DOS_GetDefaultDrive();else drive--; Bit8u drive=reg_dl;
if(Drives[drive]) { if (!drive || reg_ah==0x1f) drive = DOS_GetDefaultDrive();
else drive--;
if (Drives[drive]) {
reg_al = 0x00; reg_al = 0x00;
SegSet16(ds,dos.tables.dpb); SegSet16(ds,dos.tables.dpb);
reg_bx = drive;//Faking only the first entry (that is the driveletter) reg_bx = drive;//Faking only the first entry (that is the driveletter)
@ -704,18 +709,9 @@ static Bitu DOS_21Handler(void) {
} }
break; break;
//TODO Check for use of execution state AL=5 //TODO Check for use of execution state AL=5
case 0x00:
reg_ax=0x4c00; /* Terminate Program */
case 0x4c: /* EXIT Terminate with return code */ case 0x4c: /* EXIT Terminate with return code */
{ DOS_Terminate(dos.psp(),false,reg_al);
if (DOS_Terminate(false,reg_al)) {
/* This can't ever return false normally */
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break; break;
}
case 0x4d: /* Get Return code */ case 0x4d: /* Get Return code */
reg_al=dos.return_code;/* Officially read from SDA and clear when read */ reg_al=dos.return_code;/* Officially read from SDA and clear when read */
reg_ah=dos.return_mode; reg_ah=dos.return_mode;
@ -813,6 +809,8 @@ static Bitu DOS_21Handler(void) {
break; break;
default: default:
LOG(LOG_DOSMISC,LOG_ERROR)("DOS:58:Not Supported Set//Get memory allocation call %X",reg_al); LOG(LOG_DOSMISC,LOG_ERROR)("DOS:58:Not Supported Set//Get memory allocation call %X",reg_al);
reg_ax=1;
CALLBACK_SCF(true);
} }
break; break;
case 0x59: /* Get Extended error information */ case 0x59: /* Get Extended error information */
@ -945,7 +943,7 @@ static Bitu DOS_21Handler(void) {
{ {
int in = reg_dl; int in = reg_dl;
int out = toupper(in); int out = toupper(in);
reg_dl = out; reg_dl = (Bit8u)out;
} }
CALLBACK_SCF(false); CALLBACK_SCF(false);
break; break;
@ -960,8 +958,8 @@ static Bitu DOS_21Handler(void) {
MEM_BlockRead(data,dos_copybuf,len); MEM_BlockRead(data,dos_copybuf,len);
dos_copybuf[len] = 0; dos_copybuf[len] = 0;
//No upcase as String(0x21) might be multiple asciz strings //No upcase as String(0x21) might be multiple asciz strings
for(Bitu count = 0; count < len;count++) for (Bitu count = 0; count < len;count++)
dos_copybuf[count] = toupper(*reinterpret_cast<unsigned char*>(dos_copybuf+count)); dos_copybuf[count] = (Bit8u)toupper(*reinterpret_cast<unsigned char*>(dos_copybuf+count));
MEM_BlockWrite(data,dos_copybuf,len); MEM_BlockWrite(data,dos_copybuf,len);
} }
CALLBACK_SCF(false); CALLBACK_SCF(false);
@ -1045,7 +1043,7 @@ static Bitu DOS_21Handler(void) {
static Bitu DOS_20Handler(void) { static Bitu DOS_20Handler(void) {
reg_ax=0x4c00; reg_ah=0x00;
DOS_21Handler(); DOS_21Handler();
return CBRET_NONE; return CBRET_NONE;
} }
@ -1053,7 +1051,8 @@ static Bitu DOS_20Handler(void) {
static Bitu DOS_27Handler(void) { static Bitu DOS_27Handler(void) {
// Terminate & stay resident // Terminate & stay resident
Bit16u para = (reg_dx/16)+((reg_dx % 16)>0); Bit16u para = (reg_dx/16)+((reg_dx % 16)>0);
if (DOS_ResizeMemory(dos.psp(),&para)) DOS_Terminate(true,0); Bit16u psp = mem_readw(SegPhys(ss)+reg_sp+2);
if (DOS_ResizeMemory(psp,&para)) DOS_Terminate(psp,true,0);
return CBRET_NONE; return CBRET_NONE;
} }
@ -1149,7 +1148,7 @@ public:
static DOS* test; static DOS* test;
void DOS_ShutDown(Section* sec) { void DOS_ShutDown(Section* /*sec*/) {
delete test; delete test;
} }

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dos_classes.cpp,v 1.57 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: dos_classes.cpp,v 1.58 2009/07/09 20:06:57 c2woody Exp $ */
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -32,14 +32,14 @@ void DOS_ParamBlock::Clear(void) {
} }
void DOS_ParamBlock::LoadData(void) { void DOS_ParamBlock::LoadData(void) {
exec.envseg=sGet(sExec,envseg); exec.envseg=(Bit16u)sGet(sExec,envseg);
exec.cmdtail=sGet(sExec,cmdtail); exec.cmdtail=sGet(sExec,cmdtail);
exec.fcb1=sGet(sExec,fcb1); exec.fcb1=sGet(sExec,fcb1);
exec.fcb2=sGet(sExec,fcb2); exec.fcb2=sGet(sExec,fcb2);
exec.initsssp=sGet(sExec,initsssp); exec.initsssp=sGet(sExec,initsssp);
exec.initcsip=sGet(sExec,initcsip); exec.initcsip=sGet(sExec,initcsip);
overlay.loadseg=sGet(sOverlay,loadseg); overlay.loadseg=(Bit16u)sGet(sOverlay,loadseg);
overlay.relocation=sGet(sOverlay,relocation); overlay.relocation=(Bit16u)sGet(sOverlay,relocation);
} }
void DOS_ParamBlock::SaveData(void) { void DOS_ParamBlock::SaveData(void) {
@ -143,7 +143,7 @@ void DOS_InfoBlock::SetDiskBufferHeadPt(Bit32u _dbheadpt) {
} }
Bit16u DOS_InfoBlock::GetStartOfUMBChain(void) { Bit16u DOS_InfoBlock::GetStartOfUMBChain(void) {
return sGet(sDIB,startOfUMBChain); return (Bit16u)sGet(sDIB,startOfUMBChain);
} }
void DOS_InfoBlock::SetStartOfUMBChain(Bit16u _umbstartseg) { void DOS_InfoBlock::SetStartOfUMBChain(Bit16u _umbstartseg) {
@ -151,7 +151,7 @@ void DOS_InfoBlock::SetStartOfUMBChain(Bit16u _umbstartseg) {
} }
Bit8u DOS_InfoBlock::GetUMBChainState(void) { Bit8u DOS_InfoBlock::GetUMBChainState(void) {
return sGet(sDIB,chainingUMB); return (Bit8u)sGet(sDIB,chainingUMB);
} }
void DOS_InfoBlock::SetUMBChainState(Bit8u _umbchaining) { void DOS_InfoBlock::SetUMBChainState(Bit8u _umbchaining) {
@ -202,7 +202,7 @@ void DOS_PSP::MakeNew(Bit16u mem_size) {
/* Init file pointer and max_files */ /* Init file pointer and max_files */
sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files))); sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files)));
sSave(sPSP,max_files,20); sSave(sPSP,max_files,20);
for (i=0;i<20;i++) SetFileHandle(i,0xff); for (Bit16u ct=0;ct<20;ct++) SetFileHandle(ct,0xff);
/* User Stack pointer */ /* User Stack pointer */
// if (prevpsp.GetSegment()!=0) sSave(sPSP,stack,prevpsp.GetStack()); // if (prevpsp.GetSegment()!=0) sSave(sPSP,stack,prevpsp.GetStack());
@ -309,7 +309,7 @@ bool DOS_PSP::SetNumFiles(Bit16u fileNum) {
sSave(sPSP,file_table,data); sSave(sPSP,file_table,data);
sSave(sPSP,max_files,fileNum); sSave(sPSP,max_files,fileNum);
Bit16u i; Bit16u i;
for (i=0; i<20; i++) SetFileHandle(i,sGet(sPSP,files[i])); for (i=0; i<20; i++) SetFileHandle(i,(Bit8u)sGet(sPSP,files[i]));
for (i=20; i<fileNum; i++) SetFileHandle(i,0xFF); for (i=20; i<fileNum; i++) SetFileHandle(i,0xFF);
} else { } else {
sSave(sPSP,max_files,fileNum); sSave(sPSP,max_files,fileNum);
@ -349,17 +349,17 @@ void DOS_DTA::SetResult(const char * _name,Bit32u _size,Bit16u _date,Bit16u _tim
void DOS_DTA::GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr) { void DOS_DTA::GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr) {
MEM_BlockRead(pt+offsetof(sDTA,name),_name,DOS_NAMELENGTH_ASCII); MEM_BlockRead(pt+offsetof(sDTA,name),_name,DOS_NAMELENGTH_ASCII);
_size=sGet(sDTA,size); _size=sGet(sDTA,size);
_date=sGet(sDTA,date); _date=(Bit16u)sGet(sDTA,date);
_time=sGet(sDTA,time); _time=(Bit16u)sGet(sDTA,time);
_attr=sGet(sDTA,attr); _attr=(Bit8u)sGet(sDTA,attr);
} }
Bit8u DOS_DTA::GetSearchDrive(void) { Bit8u DOS_DTA::GetSearchDrive(void) {
return sGet(sDTA,sdrive); return (Bit8u)sGet(sDTA,sdrive);
} }
void DOS_DTA::GetSearchParams(Bit8u & attr,char * pattern) { void DOS_DTA::GetSearchParams(Bit8u & attr,char * pattern) {
attr=sGet(sDTA,sattr); attr=(Bit8u)sGet(sDTA,sattr);
char temp[11]; char temp[11];
MEM_BlockRead(pt+offsetof(sDTA,sname),temp,11); MEM_BlockRead(pt+offsetof(sDTA,sname),temp,11);
memcpy(pattern,temp,8); memcpy(pattern,temp,8);
@ -369,13 +369,16 @@ void DOS_DTA::GetSearchParams(Bit8u & attr,char * pattern) {
} }
DOS_FCB::DOS_FCB(Bit16u seg,Bit16u off) { DOS_FCB::DOS_FCB(Bit16u seg,Bit16u off,bool allow_extended) {
SetPt(seg,off); SetPt(seg,off);
real_pt=pt; real_pt=pt;
extended=false;
if (allow_extended) {
if (sGet(sFCB,drive)==0xff) { if (sGet(sFCB,drive)==0xff) {
pt+=7; pt+=7;
extended=true; extended=true;
} else extended=false; }
}
} }
bool DOS_FCB::Extended(void) { bool DOS_FCB::Extended(void) {
@ -410,13 +413,13 @@ void DOS_FCB::SetSizeDateTime(Bit32u _size,Bit16u _date,Bit16u _time) {
void DOS_FCB::GetSizeDateTime(Bit32u & _size,Bit16u & _date,Bit16u & _time) { void DOS_FCB::GetSizeDateTime(Bit32u & _size,Bit16u & _date,Bit16u & _time) {
_size=sGet(sFCB,filesize); _size=sGet(sFCB,filesize);
_date=sGet(sFCB,date); _date=(Bit16u)sGet(sFCB,date);
_time=sGet(sFCB,time); _time=(Bit16u)sGet(sFCB,time);
} }
void DOS_FCB::GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec) { void DOS_FCB::GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec) {
_cur_block=sGet(sFCB,cur_block); _cur_block=(Bit16u)sGet(sFCB,cur_block);
_cur_rec=sGet(sFCB,cur_rec); _cur_rec=(Bit8u)sGet(sFCB,cur_rec);
} }
@ -426,8 +429,8 @@ void DOS_FCB::SetRecord(Bit16u _cur_block,Bit8u _cur_rec) {
} }
void DOS_FCB::GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size) { void DOS_FCB::GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size) {
_fhandle=sGet(sFCB,file_handle); _fhandle=(Bit8u)sGet(sFCB,file_handle);
_rec_size=sGet(sFCB,rec_size); _rec_size=(Bit16u)sGet(sFCB,rec_size);
} }
@ -462,12 +465,12 @@ bool DOS_FCB::Valid() {
} }
void DOS_FCB::FileClose(Bit8u & _fhandle) { void DOS_FCB::FileClose(Bit8u & _fhandle) {
_fhandle=sGet(sFCB,file_handle); _fhandle=(Bit8u)sGet(sFCB,file_handle);
sSave(sFCB,file_handle,0xff); sSave(sFCB,file_handle,0xff);
} }
Bit8u DOS_FCB::GetDrive(void) { Bit8u DOS_FCB::GetDrive(void) {
Bit8u drive=sGet(sFCB,drive); Bit8u drive=(Bit8u)sGet(sFCB,drive);
if (!drive) return DOS_GetDefaultDrive(); if (!drive) return DOS_GetDefaultDrive();
else return drive-1; else return drive-1;
} }

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dos_execute.cpp,v 1.67 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: dos_execute.cpp,v 1.68 2009/10/04 14:28:07 c2woody Exp $ */
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
@ -104,15 +104,13 @@ void DOS_UpdatePSPName(void) {
GFX_SetTitle(-1,-1,false); GFX_SetTitle(-1,-1,false);
} }
bool DOS_Terminate(bool tsr,Bit8u exitcode) { void DOS_Terminate(Bit16u pspseg,bool tsr,Bit8u exitcode) {
dos.return_code=exitcode; dos.return_code=exitcode;
dos.return_mode=RETURN_EXIT; dos.return_mode=(tsr)?RETURN_TSR:RETURN_EXIT;
Bit16u mempsp = dos.psp(); DOS_PSP curpsp(pspseg);
if (pspseg==curpsp.GetParent()) return;
DOS_PSP curpsp(mempsp);
if (mempsp==curpsp.GetParent()) return true;
/* Free Files owned by process */ /* Free Files owned by process */
if (!tsr) curpsp.CloseFiles(); if (!tsr) curpsp.CloseFiles();
@ -136,10 +134,10 @@ bool DOS_Terminate(bool tsr,Bit8u exitcode) {
interrupts enabled, test flags cleared */ interrupts enabled, test flags cleared */
mem_writew(SegPhys(ss)+reg_sp+4,0x7202); mem_writew(SegPhys(ss)+reg_sp+4,0x7202);
// Free memory owned by process // Free memory owned by process
if (!tsr) DOS_FreeProcessMemory(mempsp); if (!tsr) DOS_FreeProcessMemory(pspseg);
DOS_UpdatePSPName(); DOS_UpdatePSPName();
if ((!(CPU_AutoDetermineMode>>CPU_AUTODETERMINE_SHIFT)) || (cpu.pmode)) return true; if ((!(CPU_AutoDetermineMode>>CPU_AUTODETERMINE_SHIFT)) || (cpu.pmode)) return;
CPU_AutoDetermineMode>>=CPU_AUTODETERMINE_SHIFT; CPU_AutoDetermineMode>>=CPU_AUTODETERMINE_SHIFT;
if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CYCLES) { if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CYCLES) {
@ -159,7 +157,7 @@ bool DOS_Terminate(bool tsr,Bit8u exitcode) {
} }
#endif #endif
return true; return;
} }
static bool MakeEnv(char * name,Bit16u * segment) { static bool MakeEnv(char * name,Bit16u * segment) {

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dos_files.cpp,v 1.111 2009/06/18 18:17:54 c2woody Exp $ */ /* $Id: dos_files.cpp,v 1.113 2009/08/31 18:03:08 qbix79 Exp $ */
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -188,7 +188,7 @@ bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive) {
bool DOS_GetCurrentDir(Bit8u drive,char * const buffer) { bool DOS_GetCurrentDir(Bit8u drive,char * const buffer) {
if (drive==0) drive=DOS_GetDefaultDrive(); if (drive==0) drive=DOS_GetDefaultDrive();
else drive--; else drive--;
if ((drive>DOS_DRIVES) || (!Drives[drive])) { if ((drive>=DOS_DRIVES) || (!Drives[drive])) {
DOS_SetError(DOSERR_INVALID_DRIVE); DOS_SetError(DOSERR_INVALID_DRIVE);
return false; return false;
} }
@ -665,7 +665,7 @@ bool DOS_Canonicalize(char const * const name,char * const big) {
bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * clusters,Bit16u * free) { bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * clusters,Bit16u * free) {
if (drive==0) drive=DOS_GetDefaultDrive(); if (drive==0) drive=DOS_GetDefaultDrive();
else drive--; else drive--;
if ((drive>DOS_DRIVES) || (!Drives[drive])) { if ((drive>=DOS_DRIVES) || (!Drives[drive])) {
DOS_SetError(DOSERR_INVALID_DRIVE); DOS_SetError(DOSERR_INVALID_DRIVE);
return false; return false;
} }
@ -768,11 +768,17 @@ static bool isvalid(const char in){
#define PARSE_RET_BADDRIVE 0xff #define PARSE_RET_BADDRIVE 0xff
Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change) { Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change) {
char * string_begin=string;Bit8u ret=0; char * string_begin=string;
DOS_FCB fcb(seg,offset); Bit8u ret=0;
if (!(parser & PARSE_DFLT_DRIVE)) {
// default drive forced, this intentionally invalidates an extended FCB
mem_writeb(PhysMake(seg,offset),0);
}
DOS_FCB fcb(seg,offset,false); // always a non-extended FCB
bool hasdrive,hasname,hasext,finished; bool hasdrive,hasname,hasext,finished;
hasdrive=hasname=hasext=finished=false; hasdrive=hasname=hasext=finished=false;
Bitu index=0;Bit8u fill=' '; Bitu index=0;
Bit8u fill=' ';
/* First get the old data from the fcb */ /* First get the old data from the fcb */
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma pack (1) #pragma pack (1)

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dos_keyboard_layout.cpp,v 1.21 2009/04/01 18:30:41 c2woody Exp $ */ /* $Id: dos_keyboard_layout.cpp,v 1.22 2009/09/06 19:25:33 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
#include "bios.h" #include "bios.h"
@ -935,8 +935,7 @@ Bitu keyboard_layout::read_codepage_file(const char* codepage_file_name, Bit32s
// update font if necessary // update font if necessary
if (font_changed && (CurMode->type==M_TEXT) && (IS_EGAVGA_ARCH)) { if (font_changed && (CurMode->type==M_TEXT) && (IS_EGAVGA_ARCH)) {
if (IS_VGA_ARCH) INT10_LoadFont(Real2Phys(int10.rom.font_16),true,256,0,0,16); INT10_ReloadFont();
else INT10_LoadFont(Real2Phys(int10.rom.font_14),true,256,0,0,14);
} }
INT10_SetupRomMemoryChecksum(); INT10_SetupRomMemoryChecksum();

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dos_memory.cpp,v 1.44 2009/06/08 17:20:02 c2woody Exp $ */ /* $Id: dos_memory.cpp,v 1.45 2009/07/15 17:05:07 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
#include "mem.h" #include "mem.h"
@ -347,7 +347,7 @@ bool DOS_LinkUMBsToMemChain(Bit16u linkstate) {
Bit16u umb_start=dos_infoblock.GetStartOfUMBChain(); Bit16u umb_start=dos_infoblock.GetStartOfUMBChain();
if (umb_start!=UMB_START_SEG) { if (umb_start!=UMB_START_SEG) {
if (umb_start!=0xffff) LOG(LOG_DOSMISC,LOG_ERROR)("Corrupt UMB chain: %x",umb_start); if (umb_start!=0xffff) LOG(LOG_DOSMISC,LOG_ERROR)("Corrupt UMB chain: %x",umb_start);
return true; return false;
} }
if ((linkstate&1)==(dos_infoblock.GetUMBChainState()&1)) return true; if ((linkstate&1)==(dos_infoblock.GetUMBChainState()&1)) return true;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dos_misc.cpp,v 1.23 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: dos_misc.cpp,v 1.24 2009/09/25 20:51:21 qbix79 Exp $ */
#include "dosbox.h" #include "dosbox.h"
#include "callback.h" #include "callback.h"
@ -184,8 +184,7 @@ static bool DOS_MultiplexFunctions(void) {
else return false; else return false;
case 0x1680: /* RELEASE CURRENT VIRTUAL MACHINE TIME-SLICE */ case 0x1680: /* RELEASE CURRENT VIRTUAL MACHINE TIME-SLICE */
//TODO Maybe do some idling but could screw up other systems :) //TODO Maybe do some idling but could screw up other systems :)
reg_al=0; return true; //So no warning in the debugger anymore
return true;
case 0x1689: /* Kernel IDLE CALL */ case 0x1689: /* Kernel IDLE CALL */
case 0x168f: /* Close awareness crap */ case 0x168f: /* Close awareness crap */
/* Removing warning */ /* Removing warning */

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: drive_iso.cpp,v 1.26 2009/06/19 18:28:10 c2woody Exp $ */ /* $Id: drive_iso.cpp,v 1.27 2009/09/22 21:48:08 c2woody Exp $ */
#include <cctype> #include <cctype>
#include <cstring> #include <cstring>
@ -430,7 +430,11 @@ void isoDrive::FreeDirIterator(const int dirIterator) {
// if this was the last aquired iterator decrement nextFreeIterator // if this was the last aquired iterator decrement nextFreeIterator
if ((dirIterator + 1) % MAX_OPENDIRS == nextFreeDirIterator) { if ((dirIterator + 1) % MAX_OPENDIRS == nextFreeDirIterator) {
if (nextFreeDirIterator>0) {
nextFreeDirIterator--; nextFreeDirIterator--;
} else {
nextFreeDirIterator = MAX_OPENDIRS-1;
}
} }
} }

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: drive_local.cpp,v 1.81 2009/06/18 18:17:54 c2woody Exp $ */ /* $Id: drive_local.cpp,v 1.82 2009/07/18 18:42:55 c2woody Exp $ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -83,7 +83,7 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
const char* type; const char* type;
switch (flags&0xf) { switch (flags&0xf) {
case OPEN_READ:type="rb"; break; case OPEN_READ:type="rb"; break;
case OPEN_WRITE:type="wb"; break; case OPEN_WRITE:type="rb+"; break;
case OPEN_READWRITE:type="rb+"; break; case OPEN_READWRITE:type="rb+"; break;
default: default:
DOS_SetError(DOSERR_ACCESS_CODE_INVALID); DOS_SetError(DOSERR_ACCESS_CODE_INVALID);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 82 KiB

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: fpu.cpp,v 1.30 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: fpu.cpp,v 1.31 2009/09/16 18:01:53 qbix79 Exp $ */
#include "dosbox.h" #include "dosbox.h"
#if C_FPU #if C_FPU
@ -594,6 +594,10 @@ void FPU_ESC7_Normal(Bitu rm) {
Bitu group=(rm >> 3) & 7; Bitu group=(rm >> 3) & 7;
Bitu sub=(rm & 7); Bitu sub=(rm & 7);
switch (group){ switch (group){
case 0x00: /* FFREEP STi*/
fpu.tags[STV(sub)]=TAG_Empty;
FPU_FPOP();
break;
case 0x01: /* FXCH STi*/ case 0x01: /* FXCH STi*/
FPU_FXCH(TOP,STV(sub)); FPU_FXCH(TOP,STV(sub));
break; break;

File diff suppressed because it is too large Load Diff

View File

@ -349,12 +349,12 @@ static void conc3d(Cache,SBPP,DBPP) (const void * s) {
line0[0]=P; \ line0[0]=P; \
line0[1]=P & greenMask; \ line0[1]=P & greenMask; \
line0[2]=P & blueMask; \ line0[2]=P & blueMask; \
line1[0]=P & blueMask; \ line1[0]=P & greenMask; \
line1[1]=P; \ line1[1]=P & redMask; \
line1[2]=P & redMask; \ line1[2]=P; \
line2[0]=P & redMask; \ line2[0]=P; \
line2[1]=P & greenMask; \ line2[1]=P & blueMask; \
line2[2]=P; line2[2]=P & redMask;
#include "render_simple.h" #include "render_simple.h"
#undef SCALERNAME #undef SCALERNAME
#undef SCALERWIDTH #undef SCALERWIDTH

View File

@ -111,12 +111,7 @@ static GUI::ScreenSDL *UI_Startup(GUI::ScreenSDL *screen) {
old_unicode = SDL_EnableUNICODE(1); old_unicode = SDL_EnableUNICODE(1);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL);
#ifdef HW_RVL
// This won't work because the Masks are wrong for 16-bit.
screenshot = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 16, GUI::Color::RedMask, GUI::Color::GreenMask, GUI::Color::BlueMask, 0);
#else
screenshot = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, GUI::Color::RedMask, GUI::Color::GreenMask, GUI::Color::BlueMask, 0); screenshot = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, GUI::Color::RedMask, GUI::Color::GreenMask, GUI::Color::BlueMask, 0);
#endif
// create screenshot for fade effect // create screenshot for fade effect
int rs = screenshot->format->Rshift, gs = screenshot->format->Gshift, bs = screenshot->format->Bshift, am = GUI::Color::AlphaMask; int rs = screenshot->format->Rshift, gs = screenshot->format->Gshift, bs = screenshot->format->Bshift, am = GUI::Color::AlphaMask;
@ -129,12 +124,7 @@ static GUI::ScreenSDL *UI_Startup(GUI::ScreenSDL *screen) {
} }
} }
#ifdef HW_RVL
// This won't work because the Masks are wrong for 16-bit.
background = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 16, GUI::Color::RedMask, GUI::Color::GreenMask, GUI::Color::BlueMask, GUI::Color::AlphaMask);
#else
background = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, GUI::Color::RedMask, GUI::Color::GreenMask, GUI::Color::BlueMask, GUI::Color::AlphaMask); background = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, GUI::Color::RedMask, GUI::Color::GreenMask, GUI::Color::BlueMask, GUI::Color::AlphaMask);
#endif
// use a blurred and sepia-toned screenshot as menu background // use a blurred and sepia-toned screenshot as menu background
for (int y = 0; y < h; y++) { for (int y = 0; y < h; y++) {
Bit32u *bg = (Bit32u*)(y*background->pitch + (char*)background->pixels); Bit32u *bg = (Bit32u*)(y*background->pitch + (char*)background->pixels);
@ -165,8 +155,7 @@ static GUI::ScreenSDL *UI_Startup(GUI::ScreenSDL *screen) {
SDL_Surface* sdlscreen = SDL_SetVideoMode(w, h, 16, SDL_SWSURFACE|(fs?SDL_FULLSCREEN:0)); SDL_Surface* sdlscreen = SDL_SetVideoMode(w, h, 16, SDL_SWSURFACE|(fs?SDL_FULLSCREEN:0));
#else #else
SDL_Surface* sdlscreen = SDL_SetVideoMode(w, h, 32, SDL_SWSURFACE|(fs?SDL_FULLSCREEN:0)); SDL_Surface* sdlscreen = SDL_SetVideoMode(w, h, 32, SDL_SWSURFACE|(fs?SDL_FULLSCREEN:0));
#endif #endif if (sdlscreen == NULL) E_Exit("Could not initialize video mode %ix%ix32 for UI: %s", w, h, SDL_GetError());
if (sdlscreen == NULL) E_Exit("Could not initialize video mode %ix%ix32 for UI: %s", w, h, SDL_GetError());
// fade out // fade out
SDL_Event event; SDL_Event event;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dma.cpp,v 1.40 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: dma.cpp,v 1.41 2009/07/24 09:56:14 c2woody Exp $ */
#include <string.h> #include <string.h>
#include "dosbox.h" #include "dosbox.h"
@ -41,28 +41,40 @@ static void UpdateEMSMapping(void) {
} }
/* read a block from physical memory */ /* read a block from physical memory */
static void DMA_BlockRead(PhysPt pt,void * data,Bitu size) { static void DMA_BlockRead(PhysPt spage,PhysPt offset,void * data,Bitu size,Bit8u dma16) {
Bit8u * write=(Bit8u *) data; Bit8u * write=(Bit8u *) data;
for ( ; size ; size--, pt++) { Bitu highpart_addr_page = spage>>12;
Bitu page = pt >> 12; size <<= dma16;
offset <<= dma16;
Bit32u dma_wrap = ((0xffff<<dma16)+dma16) | dma_wrapping;
for ( ; size ; size--, offset++) {
if (offset>(dma_wrapping<<dma16)) E_Exit("DMA segbound wrapping (read)");
offset &= dma_wrap;
Bitu page = highpart_addr_page+(offset >> 12);
/* care for EMS pageframe etc. */ /* care for EMS pageframe etc. */
if (page < EMM_PAGEFRAME4K) page = paging.firstmb[page]; if (page < EMM_PAGEFRAME4K) page = paging.firstmb[page];
else if (page < EMM_PAGEFRAME4K+0x10) page = ems_board_mapping[page]; else if (page < EMM_PAGEFRAME4K+0x10) page = ems_board_mapping[page];
else if (page < LINK_START) page = paging.firstmb[page]; else if (page < LINK_START) page = paging.firstmb[page];
*write++=phys_readb(page*4096 + (pt & 4095)); *write++=phys_readb(page*4096 + (offset & 4095));
} }
} }
/* write a block into physical memory */ /* write a block into physical memory */
static void DMA_BlockWrite(PhysPt pt,void * data,Bitu size) { static void DMA_BlockWrite(PhysPt spage,PhysPt offset,void * data,Bitu size,Bit8u dma16) {
Bit8u * read=(Bit8u *) data; Bit8u * read=(Bit8u *) data;
for ( ; size ; size--, pt++) { Bitu highpart_addr_page = spage>>12;
Bitu page = pt >> 12; size <<= dma16;
offset <<= dma16;
Bit32u dma_wrap = ((0xffff<<dma16)+dma16) | dma_wrapping;
for ( ; size ; size--, offset++) {
if (offset>(dma_wrapping<<dma16)) E_Exit("DMA segbound wrapping (write)");
offset &= dma_wrap;
Bitu page = highpart_addr_page+(offset >> 12);
/* care for EMS pageframe etc. */ /* care for EMS pageframe etc. */
if (page < EMM_PAGEFRAME4K) page = paging.firstmb[page]; if (page < EMM_PAGEFRAME4K) page = paging.firstmb[page];
else if (page < EMM_PAGEFRAME4K+0x10) page = ems_board_mapping[page]; else if (page < EMM_PAGEFRAME4K+0x10) page = ems_board_mapping[page];
else if (page < LINK_START) page = paging.firstmb[page]; else if (page < LINK_START) page = paging.firstmb[page];
phys_writeb(page*4096 + (pt & 4095), *read++); phys_writeb(page*4096 + (offset & 4095), *read++);
} }
} }
@ -91,7 +103,7 @@ bool SecondDMAControllerAvailable(void) {
else return false; else return false;
} }
static void DMA_Write_Port(Bitu port,Bitu val,Bitu iolen) { static void DMA_Write_Port(Bitu port,Bitu val,Bitu /*iolen*/) {
if (port<0x10) { if (port<0x10) {
/* write to the first DMA controller (channels 0-3) */ /* write to the first DMA controller (channels 0-3) */
DmaControllers[0]->WriteControllerReg(port,val,1); DmaControllers[0]->WriteControllerReg(port,val,1);
@ -102,12 +114,12 @@ static void DMA_Write_Port(Bitu port,Bitu val,Bitu iolen) {
UpdateEMSMapping(); UpdateEMSMapping();
switch (port) { switch (port) {
/* write DMA page register */ /* write DMA page register */
case 0x81:GetDMAChannel(2)->SetPage(val);break; case 0x81:GetDMAChannel(2)->SetPage((Bit8u)val);break;
case 0x82:GetDMAChannel(3)->SetPage(val);break; case 0x82:GetDMAChannel(3)->SetPage((Bit8u)val);break;
case 0x83:GetDMAChannel(1)->SetPage(val);break; case 0x83:GetDMAChannel(1)->SetPage((Bit8u)val);break;
case 0x89:GetDMAChannel(6)->SetPage(val);break; case 0x89:GetDMAChannel(6)->SetPage((Bit8u)val);break;
case 0x8a:GetDMAChannel(7)->SetPage(val);break; case 0x8a:GetDMAChannel(7)->SetPage((Bit8u)val);break;
case 0x8b:GetDMAChannel(5)->SetPage(val);break; case 0x8b:GetDMAChannel(5)->SetPage((Bit8u)val);break;
} }
} }
} }
@ -131,13 +143,13 @@ static Bitu DMA_Read_Port(Bitu port,Bitu iolen) {
return 0; return 0;
} }
void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu len) { void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu /*len*/) {
DmaChannel * chan;Bitu i; DmaChannel * chan;
switch (reg) { switch (reg) {
/* set base address of DMA transfer (1st byte low part, 2nd byte high part) */ /* set base address of DMA transfer (1st byte low part, 2nd byte high part) */
case 0x0:case 0x2:case 0x4:case 0x6: case 0x0:case 0x2:case 0x4:case 0x6:
UpdateEMSMapping(); UpdateEMSMapping();
chan=GetChannel(reg >> 1); chan=GetChannel((Bit8u)(reg >> 1));
flipflop=!flipflop; flipflop=!flipflop;
if (flipflop) { if (flipflop) {
chan->baseaddr=(chan->baseaddr&0xff00)|val; chan->baseaddr=(chan->baseaddr&0xff00)|val;
@ -150,7 +162,7 @@ void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu len) {
/* set DMA transfer count (1st byte low part, 2nd byte high part) */ /* set DMA transfer count (1st byte low part, 2nd byte high part) */
case 0x1:case 0x3:case 0x5:case 0x7: case 0x1:case 0x3:case 0x5:case 0x7:
UpdateEMSMapping(); UpdateEMSMapping();
chan=GetChannel(reg >> 1); chan=GetChannel((Bit8u)(reg >> 1));
flipflop=!flipflop; flipflop=!flipflop;
if (flipflop) { if (flipflop) {
chan->basecnt=(chan->basecnt&0xff00)|val; chan->basecnt=(chan->basecnt&0xff00)|val;
@ -181,8 +193,8 @@ void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu len) {
flipflop=false; flipflop=false;
break; break;
case 0xd: /* Master Clear/Reset */ case 0xd: /* Master Clear/Reset */
for (i=0;i<4;i++) { for (Bit8u ct=0;ct<4;ct++) {
chan=GetChannel(i); chan=GetChannel(ct);
chan->SetMask(true); chan->SetMask(true);
chan->tcount=false; chan->tcount=false;
} }
@ -190,15 +202,15 @@ void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu len) {
break; break;
case 0xe: /* Clear Mask register */ case 0xe: /* Clear Mask register */
UpdateEMSMapping(); UpdateEMSMapping();
for (i=0;i<4;i++) { for (Bit8u ct=0;ct<4;ct++) {
chan=GetChannel(i); chan=GetChannel(ct);
chan->SetMask(false); chan->SetMask(false);
} }
break; break;
case 0xf: /* Multiple Mask register */ case 0xf: /* Multiple Mask register */
UpdateEMSMapping(); UpdateEMSMapping();
for (i=0;i<4;i++) { for (Bit8u ct=0;ct<4;ct++) {
chan=GetChannel(i); chan=GetChannel(ct);
chan->SetMask(val & 1); chan->SetMask(val & 1);
val>>=1; val>>=1;
} }
@ -206,12 +218,12 @@ void DmaController::WriteControllerReg(Bitu reg,Bitu val,Bitu len) {
} }
} }
Bitu DmaController::ReadControllerReg(Bitu reg,Bitu len) { Bitu DmaController::ReadControllerReg(Bitu reg,Bitu /*len*/) {
DmaChannel * chan;Bitu i,ret; DmaChannel * chan;Bitu ret;
switch (reg) { switch (reg) {
/* read base address of DMA transfer (1st byte low part, 2nd byte high part) */ /* read base address of DMA transfer (1st byte low part, 2nd byte high part) */
case 0x0:case 0x2:case 0x4:case 0x6: case 0x0:case 0x2:case 0x4:case 0x6:
chan=GetChannel(reg >> 1); chan=GetChannel((Bit8u)(reg >> 1));
flipflop=!flipflop; flipflop=!flipflop;
if (flipflop) { if (flipflop) {
return chan->curraddr & 0xff; return chan->curraddr & 0xff;
@ -220,7 +232,7 @@ Bitu DmaController::ReadControllerReg(Bitu reg,Bitu len) {
} }
/* read DMA transfer count (1st byte low part, 2nd byte high part) */ /* read DMA transfer count (1st byte low part, 2nd byte high part) */
case 0x1:case 0x3:case 0x5:case 0x7: case 0x1:case 0x3:case 0x5:case 0x7:
chan=GetChannel(reg >> 1); chan=GetChannel((Bit8u)(reg >> 1));
flipflop=!flipflop; flipflop=!flipflop;
if (flipflop) { if (flipflop) {
return chan->currcnt & 0xff; return chan->currcnt & 0xff;
@ -229,12 +241,11 @@ Bitu DmaController::ReadControllerReg(Bitu reg,Bitu len) {
} }
case 0x8: /* Status Register */ case 0x8: /* Status Register */
ret=0; ret=0;
for (i=0;i<4;i++) { for (Bit8u ct=0;ct<4;ct++) {
chan=GetChannel(i); chan=GetChannel(ct);
if (chan->tcount) ret|=1 << i; if (chan->tcount) ret|=1 << ct;
chan->tcount=false; chan->tcount=false;
// if (chan->callback) ret|=1 << (i+4); if (chan->request) ret|=1 << (4+ct);
if (chan->request) ret|=1 << (4+i);
} }
return ret; return ret;
default: default:
@ -264,15 +275,16 @@ DmaChannel::DmaChannel(Bit8u num, bool dma16) {
Bitu DmaChannel::Read(Bitu want, Bit8u * buffer) { Bitu DmaChannel::Read(Bitu want, Bit8u * buffer) {
Bitu done=0; Bitu done=0;
curraddr &= dma_wrapping;
again: again:
Bitu left=(currcnt+1); Bitu left=(currcnt+1);
if (want<left) { if (want<left) {
DMA_BlockRead(pagebase+(curraddr << DMA16),buffer,want << DMA16); DMA_BlockRead(pagebase,curraddr,buffer,want,DMA16);
done+=want; done+=want;
curraddr+=want; curraddr+=want;
currcnt-=want; currcnt-=want;
} else { } else {
DMA_BlockRead(pagebase+(curraddr << DMA16),buffer,left << DMA16); DMA_BlockRead(pagebase,curraddr,buffer,want,DMA16);
buffer+=left << DMA16; buffer+=left << DMA16;
want-=left; want-=left;
done+=left; done+=left;
@ -295,15 +307,16 @@ again:
Bitu DmaChannel::Write(Bitu want, Bit8u * buffer) { Bitu DmaChannel::Write(Bitu want, Bit8u * buffer) {
Bitu done=0; Bitu done=0;
curraddr &= dma_wrapping;
again: again:
Bitu left=(currcnt+1); Bitu left=(currcnt+1);
if (want<left) { if (want<left) {
DMA_BlockWrite(pagebase+(curraddr << DMA16),buffer,want << DMA16); DMA_BlockWrite(pagebase,curraddr,buffer,want,DMA16);
done+=want; done+=want;
curraddr+=want; curraddr+=want;
currcnt-=want; currcnt-=want;
} else { } else {
DMA_BlockWrite(pagebase+(curraddr << DMA16),buffer,left << DMA16); DMA_BlockWrite(pagebase,curraddr,buffer,left,DMA16);
buffer+=left << DMA16; buffer+=left << DMA16;
want-=left; want-=left;
done+=left; done+=left;
@ -366,12 +379,17 @@ public:
} }
}; };
void DMA_SetWrapping(Bitu wrap) {
dma_wrapping = wrap;
}
static DMA* test; static DMA* test;
void DMA_Destroy(Section* sec){ void DMA_Destroy(Section* /*sec*/){
delete test; delete test;
} }
void DMA_Init(Section* sec) { void DMA_Init(Section* sec) {
DMA_SetWrapping(0xffff);
test = new DMA(sec); test = new DMA(sec);
sec->AddDestroyFunction(&DMA_Destroy); sec->AddDestroyFunction(&DMA_Destroy);
Bitu i; Bitu i;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: gus.cpp,v 1.36 2009/04/27 17:11:26 qbix79 Exp $ */ /* $Id: gus.cpp,v 1.37 2009/09/03 16:03:01 c2woody Exp $ */
#include <string.h> #include <string.h>
#include <iomanip> #include <iomanip>
@ -338,7 +338,9 @@ static void GUSReset(void) {
myGUS.timers[1].value = 0xff; myGUS.timers[1].value = 0xff;
myGUS.timers[0].delay = 0.080f; myGUS.timers[0].delay = 0.080f;
myGUS.timers[1].delay = 0.320f; myGUS.timers[1].delay = 0.320f;
myGUS.ChangeIRQDMA = false; myGUS.ChangeIRQDMA = false;
myGUS.mixControl = 0x0b; // latches enabled by default LINEs disabled
// Stop all channels // Stop all channels
int i; int i;
for(i=0;i<32;i++) { for(i=0;i<32;i++) {
@ -633,11 +635,11 @@ static void write_gus(Bitu port,Bitu val,Bitu iolen) {
// LOG_MSG("Write gus port %x val %x",port,val); // LOG_MSG("Write gus port %x val %x",port,val);
switch(port - GUS_BASE) { switch(port - GUS_BASE) {
case 0x200: case 0x200:
myGUS.mixControl = val; myGUS.mixControl = (Bit8u)val;
myGUS.ChangeIRQDMA = true; myGUS.ChangeIRQDMA = true;
return; return;
case 0x208: case 0x208:
adlib_commandreg = val; adlib_commandreg = (Bit8u)val;
break; break;
case 0x209: case 0x209:
//TODO adlib_commandreg should be 4 for this to work else it should just latch the value //TODO adlib_commandreg should be 4 for this to work else it should just latch the value
@ -684,21 +686,21 @@ static void write_gus(Bitu port,Bitu val,Bitu iolen) {
curchan = guschan[myGUS.gCurChannel]; curchan = guschan[myGUS.gCurChannel];
break; break;
case 0x303: case 0x303:
myGUS.gRegSelect = val; myGUS.gRegSelect = (Bit8u)val;
myGUS.gRegData = 0; myGUS.gRegData = 0;
break; break;
case 0x304: case 0x304:
if (iolen==2) { if (iolen==2) {
myGUS.gRegData=val; myGUS.gRegData=(Bit16u)val;
ExecuteGlobRegister(); ExecuteGlobRegister();
} else myGUS.gRegData = val; } else myGUS.gRegData = (Bit16u)val;
break; break;
case 0x305: case 0x305:
myGUS.gRegData = (0x00ff & myGUS.gRegData) | val << 8; myGUS.gRegData = (Bit16u)((0x00ff & myGUS.gRegData) | val << 8);
ExecuteGlobRegister(); ExecuteGlobRegister();
break; break;
case 0x307: case 0x307:
if(myGUS.gDramAddr < sizeof(GUSRam)) GUSRam[myGUS.gDramAddr] = val; if(myGUS.gDramAddr < sizeof(GUSRam)) GUSRam[myGUS.gDramAddr] = (Bit8u)val;
break; break;
default: default:
#if LOG_GUS #if LOG_GUS

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: mixer.cpp,v 1.53 2009/04/28 21:48:24 harekiet Exp $ */ /* $Id: mixer.cpp,v 1.54 2009/09/05 11:10:04 qbix79 Exp $ */
/* /*
Remove the sdl code from here and have it handeld in the sdlmain. Remove the sdl code from here and have it handeld in the sdlmain.
@ -147,12 +147,8 @@ void MixerChannel::Mix(Bitu _needed) {
needed=_needed; needed=_needed;
while (enabled && needed>done) { while (enabled && needed>done) {
Bitu todo=needed-done; Bitu todo=needed-done;
todo*=freq_add; todo *= freq_add;
if (todo & MIXER_REMAIN) { todo = (todo >> MIXER_SHIFT) + ((todo & MIXER_REMAIN)!=0);
todo=(todo >> MIXER_SHIFT) + 1;
} else {
todo=(todo >> MIXER_SHIFT);
}
handler(todo); handler(todo);
} }
} }

View File

@ -26,7 +26,9 @@
#include <math.h> #include <math.h>
#ifdef HW_RVL
#include <string.h> #include <string.h>
#endif
#include <stdlib.h> // rand() #include <stdlib.h> // rand()
#include "dosbox.h" #include "dosbox.h"
#include "opl.h" #include "opl.h"

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: sblaster.cpp,v 1.76 2009/06/10 17:44:59 c2woody Exp $ */ /* $Id: sblaster.cpp,v 1.77 2009/07/11 10:39:38 harekiet Exp $ */
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
@ -938,7 +938,7 @@ static void DSP_DoCommand(void) {
DSP_FlushData(); DSP_FlushData();
switch (sb.type) { switch (sb.type) {
case SBT_1: case SBT_1:
DSP_AddData(0x1);DSP_AddData(0x1);break; DSP_AddData(0x1);DSP_AddData(0x05);break;
case SBT_2: case SBT_2:
DSP_AddData(0x2);DSP_AddData(0x1);break; DSP_AddData(0x2);DSP_AddData(0x1);break;
case SBT_PRO1: case SBT_PRO1:

View File

@ -2,9 +2,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libserial.a noinst_LIBRARIES = libserial.a
libserial_a_SOURCES = directserial_win32.cpp directserial_win32.h \ libserial_a_SOURCES = directserial.cpp directserial.h \
libserial.cpp libserial.h \
serialdummy.cpp serialdummy.h serialport.cpp \ serialdummy.cpp serialdummy.h serialport.cpp \
softmodem.cpp softmodem.h misc_util.cpp misc_util.h \ softmodem.cpp softmodem.h misc_util.cpp misc_util.h \
directserial_os2.h directserial_os2.cpp \
directserial_posix.h directserial_posix.cpp \
nullmodem.cpp nullmodem.h nullmodem.cpp nullmodem.h

View File

@ -0,0 +1,319 @@
/*
* Copyright (C) 2002-2009 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: directserial.cpp,v 1.2 2009/09/26 09:15:19 h-a-l-9000 Exp $ */
#include "dosbox.h"
#if C_DIRECTSERIAL
#include "serialport.h"
#include "directserial.h"
#include "misc_util.h"
#include "pic.h"
#include "libserial.h"
/* This is a serial passthrough class. Its amazingly simple to */
/* write now that the serial ports themselves were abstracted out */
CDirectSerial::CDirectSerial (Bitu id, CommandLine* cmd)
:CSerial (id, cmd) {
InstallationSuccessful = false;
comport = 0;
rx_retry = 0;
rx_retry_max = 0;
std::string tmpstring;
if(!cmd->FindStringBegin("realport:",tmpstring,false)) return;
LOG_MSG ("Serial%d: Opening %s", COMNUMBER, tmpstring.c_str());
if(!SERIAL_open(tmpstring.c_str(), &comport)) {
char errorbuffer[256];
SERIAL_getErrorString(errorbuffer, sizeof(errorbuffer));
LOG_MSG("Serial%d: Serial Port \"%s\" could not be opened.",
COMNUMBER, tmpstring.c_str());
LOG_MSG("%s",errorbuffer);
return;
}
#if SERIAL_DEBUG
dbgmsg_poll_block=false;
dbgmsg_rx_block=false;
#endif
// rxdelay: How many milliseconds to wait before causing an
// overflow when the application is unresponsive.
if(getBituSubstring("rxdelay:", &rx_retry_max, cmd)) {
if(!(rx_retry_max<=10000)) {
rx_retry_max=0;
}
}
CSerial::Init_Registers();
InstallationSuccessful = true;
rx_state = D_RX_IDLE;
setEvent(SERIAL_POLLING_EVENT, 1); // millisecond receive tick
}
CDirectSerial::~CDirectSerial () {
if(comport) SERIAL_close(comport);
// We do not use own events so we don't have to clear them.
}
// CanReceive: true:UART part has room left
// doReceive: true:there was really a byte to receive
// rx_retry is incremented in polling events
// in POLLING_EVENT: always add new polling event
// D_RX_IDLE + CanReceive + doReceive -> D_RX_WAIT , add RX_EVENT
// D_RX_IDLE + CanReceive + not doReceive -> D_RX_IDLE
// D_RX_IDLE + not CanReceive -> D_RX_BLOCKED, add RX_EVENT
// D_RX_BLOCKED + CanReceive + doReceive -> D_RX_FASTWAIT, rem RX_EVENT
// rx_retry=0 , add RX_EVENT
// D_RX_BLOCKED + CanReceive + !doReceive -> D_RX_IDLE, rem RX_EVENT
// rx_retry=0
// D_RX_BLOCKED + !CanReceive + doReceive + retry < max -> D_RX_BLOCKED, rx_retry++
// D_RX_BLOCKED + !CanReceive + doReceive + retry >=max -> rx_retry=0
// to be continued...
void CDirectSerial::handleUpperEvent(Bit16u type) {
switch(type) {
case SERIAL_POLLING_EVENT: {
setEvent(SERIAL_POLLING_EVENT, 1.0f);
// update Modem input line states
switch(rx_state) {
case D_RX_IDLE:
if(CanReceiveByte()) {
if(doReceive()) {
// a byte was received
rx_state=D_RX_WAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
} // else still idle
} else {
#if SERIAL_DEBUG
if(!dbgmsg_poll_block) {
log_ser(dbg_aux,"Directserial: block on polling.");
dbgmsg_poll_block=true;
}
#endif
rx_state=D_RX_BLOCKED;
// have both delays (1ms + bytetime)
setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
}
break;
case D_RX_BLOCKED:
// one timeout tick
if(!CanReceiveByte()) {
rx_retry++;
if(rx_retry>=rx_retry_max) {
// it has timed out:
rx_retry=0;
removeEvent(SERIAL_RX_EVENT);
if(doReceive()) {
// read away everything
// this will set overrun errors
while(doReceive());
rx_state=D_RX_WAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
} else {
// much trouble about nothing
rx_state=D_RX_IDLE;
}
} // else wait further
} else {
// good: we can receive again
#if SERIAL_DEBUG
dbgmsg_poll_block=false;
dbgmsg_rx_block=false;
#endif
removeEvent(SERIAL_RX_EVENT);
rx_retry=0;
if(doReceive()) {
rx_state=D_RX_FASTWAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.65f);
} else {
// much trouble about nothing
rx_state=D_RX_IDLE;
}
}
break;
case D_RX_WAIT:
case D_RX_FASTWAIT:
break;
}
updateMSR();
break;
}
case SERIAL_RX_EVENT: {
switch(rx_state) {
case D_RX_IDLE:
LOG_MSG("internal error in directserial");
break;
case D_RX_BLOCKED: // try to receive
case D_RX_WAIT:
case D_RX_FASTWAIT:
if(CanReceiveByte()) {
// just works or unblocked
rx_retry=0; // not waiting anymore
if(doReceive()) {
if(rx_state==D_RX_WAIT) setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
else {
// maybe unblocked
rx_state=D_RX_FASTWAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.65f);
}
} else {
// didn't receive anything
rx_state=D_RX_IDLE;
}
} else {
// blocking now or still blocked
#if SERIAL_DEBUG
if(rx_state==D_RX_BLOCKED) {
if(!dbgmsg_rx_block) {
log_ser(dbg_aux,"Directserial: rx still blocked (retry=%d)",rx_retry);
dbgmsg_rx_block=true;
}
}
else log_ser(dbg_aux,"Directserial: block on continued rx (retry=%d).",rx_retry);
#endif
setEvent(SERIAL_RX_EVENT, bytetime*0.65f);
rx_state=D_RX_BLOCKED;
}
break;
}
updateMSR();
break;
}
case SERIAL_TX_EVENT: {
// Maybe echo cirquit works a bit better this way
if(rx_state==D_RX_IDLE && CanReceiveByte()) {
if(doReceive()) {
// a byte was received
rx_state=D_RX_WAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
}
}
ByteTransmitted();
updateMSR();
break;
}
case SERIAL_THR_EVENT: {
ByteTransmitting();
setEvent(SERIAL_TX_EVENT,bytetime*1.1f);
break;
}
}
}
bool CDirectSerial::doReceive() {
int value = SERIAL_getextchar(comport);
if(value) {
receiveByteEx((Bit8u)(value&0xff),(Bit8u)((value&0xff00)>>8));
return true;
}
return false;
}
// updatePortConfig is called when emulated app changes the serial port
// parameters baudrate, stopbits, number of databits, parity.
void CDirectSerial::updatePortConfig (Bit16u divider, Bit8u lcr) {
Bit8u parity = 0;
switch ((lcr & 0x38)>>3) {
case 0x1: parity='o'; break;
case 0x3: parity='e'; break;
case 0x5: parity='m'; break;
case 0x7: parity='s'; break;
default: parity='n'; break;
}
Bit8u bytelength = (lcr & 0x3)+5;
// baudrate
Bitu baudrate;
if(divider==0) baudrate=115200;
else baudrate = 115200 / divider;
// stopbits
Bit8u stopbits;
if (lcr & 0x4) {
if (bytelength == 5) stopbits = SERIAL_15STOP;
else stopbits = SERIAL_2STOP;
} else stopbits = SERIAL_1STOP;
if(!SERIAL_setCommParameters(comport, baudrate, parity, stopbits, bytelength)) {
#if SERIAL_DEBUG
log_ser(dbg_aux,"Serial port settings not supported by host." );
#endif
LOG_MSG ("Serial%d: Desired serial mode not supported (%d,%d,%c,%d)",
COMNUMBER, baudrate,bytelength,parity,stopbits);
}
CDirectSerial::setRTSDTR(getRTS(), getDTR());
}
void CDirectSerial::updateMSR () {
int new_status = SERIAL_getmodemstatus(comport);
setCTS(new_status&SERIAL_CTS? true:false);
setDSR(new_status&SERIAL_DSR? true:false);
setRI(new_status&SERIAL_RI? true:false);
setCD(new_status&SERIAL_CD? true:false);
}
void CDirectSerial::transmitByte (Bit8u val, bool first) {
if(!SERIAL_sendchar(comport, val))
LOG_MSG("Serial%d: COM port error: write failed!", COMNUMBER);
if(first) setEvent(SERIAL_THR_EVENT, bytetime/8);
else setEvent(SERIAL_TX_EVENT, bytetime);
}
// setBreak(val) switches break on or off
void CDirectSerial::setBreak (bool value) {
SERIAL_setBREAK(comport,value);
}
// updateModemControlLines(mcr) sets DTR and RTS.
void CDirectSerial::setRTSDTR(bool rts, bool dtr) {
SERIAL_setRTS(comport,rts);
SERIAL_setDTR(comport,dtr);
}
void CDirectSerial::setRTS(bool val) {
SERIAL_setRTS(comport,val);
}
void CDirectSerial::setDTR(bool val) {
SERIAL_setDTR(comport,val);
}
#endif

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2002-2009 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: directserial.h,v 1.2 2009/09/26 09:15:19 h-a-l-9000 Exp $ */
// include guard
#ifndef DOSBOX_DIRECTSERIAL_WIN32_H
#define DOSBOX_DIRECTSERIAL_WIN32_H
#include "dosbox.h"
#if C_DIRECTSERIAL
#define DIRECTSERIAL_AVAILIBLE
#include "serialport.h"
#include "libserial.h"
class CDirectSerial : public CSerial {
public:
CDirectSerial(Bitu id, CommandLine* cmd);
~CDirectSerial();
void updatePortConfig(Bit16u divider, Bit8u lcr);
void updateMSR();
void transmitByte(Bit8u val, bool first);
void setBreak(bool value);
void setRTSDTR(bool rts, bool dtr);
void setRTS(bool val);
void setDTR(bool val);
void handleUpperEvent(Bit16u type);
private:
COMPORT comport;
Bitu rx_state;
#define D_RX_IDLE 0
#define D_RX_WAIT 1
#define D_RX_BLOCKED 2
#define D_RX_FASTWAIT 3
Bitu rx_retry; // counter of retries (every millisecond)
Bitu rx_retry_max; // how many POLL_EVENTS to wait before causing
// an overrun error.
bool doReceive();
#if SERIAL_DEBUG
bool dbgmsg_poll_block;
bool dbgmsg_rx_block;
#endif
};
#endif // C_DIRECTSERIAL
#endif // include guard

View File

@ -0,0 +1,706 @@
/*
* Copyright (C) 2002-2009 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: libserial.cpp,v 1.2 2009/09/26 09:15:19 h-a-l-9000 Exp $ */
#include "libserial.h"
#include "config.h"
#ifdef WIN32
#include <windows.h>
#include <stdio.h>
struct _COMPORT {
HANDLE porthandle;
bool breakstatus;
DCB orig_dcb;
};
bool SERIAL_open(const char* portname, COMPORT* port) {
// allocate COMPORT structure
COMPORT cp = (_COMPORT*)malloc(sizeof(_COMPORT));
if(cp == NULL) return false;
cp->breakstatus=false;
// open the port in NT object space (recommended by Microsoft)
// allows the user to open COM10+ and custom port names.
int len = strlen(portname);
if(len > 240) {
SetLastError(ERROR_BUFFER_OVERFLOW);
return false;
}
char extended_portname[256] = "\\\\.\\";
memcpy(extended_portname+4,portname,len+1);
cp->porthandle = CreateFile (extended_portname,
GENERIC_READ | GENERIC_WRITE, 0,
// must be opened with exclusive-access
NULL, // no security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
0, // non overlapped I/O
NULL // hTemplate must be NULL for comm devices
);
if (cp->porthandle == INVALID_HANDLE_VALUE) goto cleanup_error;
cp->orig_dcb.DCBlength=sizeof(DCB);
if(!GetCommState(cp->porthandle, &cp->orig_dcb)) {
goto cleanup_error;
}
// configure the port for polling
DCB newdcb;
memcpy(&newdcb,&cp->orig_dcb,sizeof(DCB));
newdcb.fBinary=true;
newdcb.fParity=true;
newdcb.fOutxCtsFlow=false;
newdcb.fOutxDsrFlow=false;
newdcb.fDtrControl=DTR_CONTROL_DISABLE;
newdcb.fDsrSensitivity=false;
newdcb.fOutX=false;
newdcb.fInX=false;
newdcb.fErrorChar=0;
newdcb.fNull=false;
newdcb.fRtsControl=RTS_CONTROL_DISABLE;
newdcb.fAbortOnError=false;
if(!SetCommState(cp->porthandle, &newdcb)) {
goto cleanup_error;
}
// Configure timeouts to effectively use polling
COMMTIMEOUTS ct;
ct.ReadIntervalTimeout = MAXDWORD;
ct.ReadTotalTimeoutConstant = 0;
ct.ReadTotalTimeoutMultiplier = 0;
ct.WriteTotalTimeoutConstant = 0;
ct.WriteTotalTimeoutMultiplier = 0;
if(!SetCommTimeouts(cp->porthandle, &ct)) {
goto cleanup_error;
}
if(!ClearCommBreak(cp->porthandle)) {
// Bluetooth Bluesoleil seems to not implement it
//goto cleanup_error;
}
DWORD errors;
if(!ClearCommError(cp->porthandle, &errors, NULL)) {
goto cleanup_error;
}
*port = cp;
return true;
cleanup_error:
if (cp->porthandle != INVALID_HANDLE_VALUE) CloseHandle(cp->porthandle);
free(cp);
return false;
}
void SERIAL_close(COMPORT port) {
// restore original DCB, close handle, free the COMPORT struct
if (port->porthandle != INVALID_HANDLE_VALUE) {
SetCommState(port->porthandle, &port->orig_dcb);
CloseHandle(port->porthandle);
}
free(port);
}
void SERIAL_getErrorString(char* buffer, int length) {
int error = GetLastError();
if(length < 50) return;
memset(buffer,0,length);
// get the error message text from the operating system
LPVOID sysmessagebuffer;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &sysmessagebuffer,
0,NULL);
const char* err5text = "The specified port is already in use.\n";
const char* err2text = "The specified port does not exist.\n";
int sysmsg_offset = 0;
if(error == 5) {
sysmsg_offset = strlen(err5text);
memcpy(buffer,err5text,sysmsg_offset);
} else if(error == 2) {
sysmsg_offset = strlen(err2text);
memcpy(buffer,err2text,sysmsg_offset);
}
if((length - sysmsg_offset - strlen((const char*)sysmessagebuffer)) >= 0)
memcpy(buffer + sysmsg_offset, sysmessagebuffer,
strlen((const char*)sysmessagebuffer));
LocalFree(sysmessagebuffer);
}
void SERIAL_setDTR(COMPORT port, bool value) {
EscapeCommFunction(port->porthandle, value ? SETDTR:CLRDTR);
}
void SERIAL_setRTS(COMPORT port, bool value) {
EscapeCommFunction(port->porthandle, value ? SETRTS:CLRRTS);
}
void SERIAL_setBREAK(COMPORT port, bool value) {
EscapeCommFunction(port->porthandle, value ? SETBREAK:CLRBREAK);
port->breakstatus = value;
}
int SERIAL_getmodemstatus(COMPORT port) {
DWORD retval = 0;
GetCommModemStatus (port->porthandle, &retval);
return (int)retval;
}
bool SERIAL_sendchar(COMPORT port, char data) {
DWORD bytesWritten;
// mean bug: with break = 1, WriteFile will never return.
if(port->breakstatus) return true; // true or false?!
WriteFile (port->porthandle, &data, 1, &bytesWritten, NULL);
if(bytesWritten==1) return true;
else return false;
}
// 0-7 char data, higher=flags
int SERIAL_getextchar(COMPORT port) {
DWORD errors = 0; // errors from API
DWORD dwRead = 0; // Number of chars read
char chRead;
int retval = 0;
// receive a byte; TODO communicate faliure
if (ReadFile (port->porthandle, &chRead, 1, &dwRead, NULL)) {
if (dwRead) {
// check for errors
ClearCommError(port->porthandle, &errors, NULL);
// mask bits are identical
errors &= CE_BREAK|CE_FRAME|CE_RXPARITY|CE_OVERRUN;
retval |= (errors<<8);
retval |= (chRead & 0xff);
retval |= 0x10000;
}
}
return retval;
}
bool SERIAL_setCommParameters(COMPORT port,
int baudrate, char parity, int stopbits, int length) {
DCB dcb;
dcb.DCBlength=sizeof(dcb);
GetCommState(port->porthandle,&dcb);
// parity
switch (parity) {
case 'n': dcb.Parity = NOPARITY; break;
case 'o': dcb.Parity = ODDPARITY; break;
case 'e': dcb.Parity = EVENPARITY; break;
case 'm': dcb.Parity = MARKPARITY; break;
case 's': dcb.Parity = SPACEPARITY; break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
// stopbits
switch(stopbits) {
case SERIAL_1STOP: dcb.StopBits = ONESTOPBIT; break;
case SERIAL_2STOP: dcb.StopBits = TWOSTOPBITS; break;
case SERIAL_15STOP: dcb.StopBits = ONE5STOPBITS; break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
// byte length
if(length > 8 || length < 5) {
SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
dcb.ByteSize = length;
dcb.BaudRate = baudrate;
if (!SetCommState (port->porthandle, &dcb)) return false;
return true;
}
#endif
#if defined (LINUX) || defined (MACOSX)
#include <memory.h> // strlen
#include <malloc.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h> // sprinf
struct _COMPORT {
int porthandle;
bool breakstatus;
termios backup;
};
bool SERIAL_open(const char* portname, COMPORT* port) {
int result;
// allocate COMPORT structure
COMPORT cp = (_COMPORT*)malloc(sizeof(_COMPORT));
if(cp == NULL) return false;
cp->breakstatus=false;
int len = strlen(portname);
if(len > 240) {
///////////////////////////////////SetLastError(ERROR_BUFFER_OVERFLOW);
return false;
}
char extended_portname[256] = "/dev/";
memcpy(extended_portname+5,portname,len);
cp->porthandle = open (extended_portname, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (cp->porthandle < 0) goto cleanup_error;
result = tcgetattr(cp->porthandle,&cp->backup);
if (result==-1) goto cleanup_error;
// get port settings
termios termInfo;
memcpy(&termInfo,&cp->backup,sizeof(termios));
// initialize the port
termInfo.c_cflag = CS8 | CREAD | CLOCAL; // noparity, 1 stopbit
termInfo.c_iflag = PARMRK | INPCK;
termInfo.c_oflag = 0;
termInfo.c_lflag = 0;
termInfo.c_cc[VMIN] = 0;
termInfo.c_cc[VTIME] = 0;
tcflush (cp->porthandle, TCIFLUSH);
tcsetattr (cp->porthandle, TCSANOW, &termInfo);
*port = cp;
return true;
cleanup_error:
if (cp->porthandle != 0) close(cp->porthandle);
free(cp);
return false;
}
void SERIAL_close(COMPORT port) {
// restore original termios, close handle, free the COMPORT struct
if (port->porthandle >= 0) {
tcsetattr(port->porthandle, TCSANOW, &port->backup);
close(port->porthandle);
}
free(port);
}
void SERIAL_getErrorString(char* buffer, int length) {
int error = errno;
if(length < 50) return;
memset(buffer,0,length);
// get the error message text from the operating system
// TODO (or not)
const char* err5text = "The specified port is already in use.\n";
const char* err2text = "The specified port does not exist.\n";
int sysmsg_offset = 0;
if(error == EBUSY) {
sysmsg_offset = strlen(err5text);
memcpy(buffer,err5text,sysmsg_offset);
} else if(error == 2) {
sysmsg_offset = strlen(err2text);
memcpy(buffer,err2text,sysmsg_offset);
}
sprintf(buffer + sysmsg_offset, "System error %d.",error);
}
int SERIAL_getmodemstatus(COMPORT port) {
long flags = 0;
ioctl (port->porthandle, TIOCMGET, &flags);
int retval = 0;
if (flags & TIOCM_CTS) retval |= SERIAL_CTS;
if (flags & TIOCM_DSR) retval |= SERIAL_DSR;
if (flags & TIOCM_RI) retval |= SERIAL_RI;
if (flags & TIOCM_CD) retval |= SERIAL_CD;
return retval;
}
bool SERIAL_sendchar(COMPORT port, char data) {
if(port->breakstatus) return true; // true or false?!; Does POSIX need this check?
int bytesWritten = write(port->porthandle, &data, 1);
if(bytesWritten==1) return true;
else return false;
}
int SERIAL_getextchar(COMPORT port) {
unsigned char chRead = 0;
int dwRead = 0;
unsigned char error = 0;
int retval = 0;
dwRead=read(port->porthandle,&chRead,1);
if (dwRead==1) {
if(chRead==0xff) // error escape
{
dwRead=read(port->porthandle,&chRead,1);
if(chRead==0x00) // an error
{
dwRead=read(port->porthandle,&chRead,1);
if(chRead==0x0) error=SERIAL_BREAK_ERR;
else error=SERIAL_FRAMING_ERR;
}
}
retval |= (error<<8);
retval |= chRead;
retval |= 0x10000;
}
return retval;
}
bool SERIAL_setCommParameters(COMPORT port,
int baudrate, char parity, int stopbits, int length) {
termios termInfo;
int result = tcgetattr(port->porthandle, &termInfo);
if (result==-1) return false;
termInfo.c_cflag = CREAD | CLOCAL;
// parity
// "works on many systems"
#define CMSPAR 010000000000
switch (parity) {
case 'n': break;
case 'o': termInfo.c_cflag |= (PARODD | PARENB); break;
case 'e': termInfo.c_cflag |= PARENB; break;
case 'm': termInfo.c_cflag |= (PARENB | CMSPAR | PARODD); break;
case 's': termInfo.c_cflag |= (PARENB | CMSPAR); break;
default:
return false;
}
// stopbits
switch(stopbits) {
case SERIAL_1STOP: break;
case SERIAL_2STOP:
case SERIAL_15STOP: termInfo.c_cflag |= CSTOPB; break;
default:
return false;
}
// byte length
if(length > 8 || length < 5) return false;
switch (length) {
case 5: termInfo.c_cflag |= CS5; break;
case 6: termInfo.c_cflag |= CS6; break;
case 7: termInfo.c_cflag |= CS7; break;
case 8: termInfo.c_cflag |= CS8; break;
}
// baudrate
int posix_baudrate=0;
switch(baudrate) {
case 115200: posix_baudrate = B115200; break;
case 57600: posix_baudrate = B57600; break;
case 38400: posix_baudrate = B38400; break;
case 19200: posix_baudrate = B19200; break;
case 9600: posix_baudrate = B9600; break;
case 4800: posix_baudrate = B4800; break;
case 2400: posix_baudrate = B2400; break;
case 1200: posix_baudrate = B1200; break;
case 600: posix_baudrate = B600; break;
case 300: posix_baudrate = B300; break;
case 110: posix_baudrate = B110; break;
default: return false;
}
cfsetospeed (&termInfo, posix_baudrate);
cfsetispeed (&termInfo, posix_baudrate);
int retval = tcsetattr(port->porthandle, TCSANOW, &termInfo);
if(retval==-1) return false;
return true;
}
void SERIAL_setBREAK(COMPORT port, bool value) {
ioctl(port->porthandle, value?TIOCSBRK:TIOCCBRK);
}
void SERIAL_setDTR(COMPORT port, bool value) {
long flag = TIOCM_DTR;
ioctl(port->porthandle, value?TIOCMBIS:TIOCMBIC, &flag);
}
void SERIAL_setRTS(COMPORT port, bool value) {
long flag = TIOCM_RTS;
ioctl(port->porthandle, value?TIOCMBIS:TIOCMBIC, &flag);
}
#endif
#ifdef OS2
// OS/2 related headers
#define INCL_DOSFILEMGR
#define INCL_DOSERRORS
#define INCL_DOSDEVICES
#define INCL_DOSDEVIOCTL
#define INCL_DOSPROCESS
#include <os2.h>
struct _COMPORT {
HFILE porthandle;
bool breakstatus;
DCBINFO backup;
};
// TODO: THIS IS INCOMPLETE and UNTESTED.
bool SERIAL_open(const char* portname, COMPORT* port) {
// allocate COMPORT structure
COMPORT cp = (_COMPORT*)malloc(sizeof(_COMPORT));
if(cp == NULL) return false;
cp->porthandle=0;
cp->breakstatus=false;
ULONG ulAction = 0;
APIRET rc = DosOpen(portname, &cp->porthandle,
&ulAction, 0L, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | OPEN_FLAGS_SEQUENTIAL, 0L);
if (rc != NO_ERROR) {
goto cleanup_error;
}
ULONG ulParmLen = sizeof(DCBINFO);
rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETDCBINFO,
0, 0, 0, &cp->orig_dcb, ulParmLen, &ulParmLen);
if ( rc != NO_ERROR) {
goto cleanup_error;
}
// configure the port for polling
DCBINFO newdcb;
memcpy(&newdcb,&cp->orig_dcb,sizeof(DCBINFO));
newdcb.usWriteTimeout = 0;
newdcb.usReadTimeout = 0; //65535;
newdcb.fbCtlHndShake = dcb.fbFlowReplace = 0;
newdcb.fbTimeout = 6;
rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETDCBINFO,
&newdcb, ulParmLen, &ulParmLen, 0, 0, 0);
if ( rc != NO_ERROR) {
goto cleanup_error;
}
USHORT errors = 0;
ulParmLen = sizeof(errors);
rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_GETCOMMERROR,
0, 0, 0, &errors, ulParmLen, &ulParmLen);
if ( rc != NO_ERROR) {
goto cleanup_error;
}
*port = cp;
return true;
cleanup_error:
// TODO error string - rc value
if (cp->porthandle != 0) CloseHandle(cp->porthandle);
free(cp);
return false;
}
void SERIAL_getErrorString(char* buffer, int length) {
sprintf(buffer, "TODO: error handling is not fun");
}
void SERIAL_close(COMPORT port) {
ULONG ulParmLen = sizeof(DCBINFO);
// restore original DCB, close handle, free the COMPORT struct
if (port->porthandle != 0) {
DosDevIOCtl(port->porthandle, IOCTL_ASYNC, ASYNC_SETDCBINFO,
&port->orig_dcb, ulParmLen, &ulParmLen, 0, 0, 0);
SetCmmState(port->porthandle, &port->orig_dcb);
DosClose (port->porthandle);
}
free(port);
}
bool SERIAL_sendchar(COMPORT port, char data) {
ULONG bytesWritten = 0;
if(port->breakstatus) return true; // does OS/2 need this?
APIRET rc = DosWrite(port->porthandle, &data, 1, &bytesWritten);
if (rc == NO_ERROR && bytesWritten > 0) return true;
else return false;
}
void SERIAL_setBREAK(COMPORT port, bool value) {
USHORT error;
ULONG ulParmLen = sizeof(error);
DosDevIOCtl(port->porthandle, IOCTL_ASYNC,
value? ASYNC_SETBREAKON:ASYNC_SETBREAKOFF,
0,0,0, &error, ulParmLen, &ulParmLen);
}
int SERIAL_getextchar(COMPORT port) {
ULONG dwRead = 0; // Number of chars read
char chRead;
int retval = 0;
// receive a byte; TODO communicate faliure
if (DosRead(port->porthandle, &chRead, 1, &dwRead) == NO_ERROR) {
if (dwRead) {
// check for errors; will OS/2 clear the error on reading its data?
// if yes then this is in wrong order
USHORT errors = 0, event = 0;
ULONG ulParmLen = sizeof(errors);
DosDevIOCtl(port->porthandle, IOCTL_ASYNC, ASYNC_GETCOMMEVENT,
0, 0, 0, &event, ulParmLen, &ulParmLen);
if (event & (64 + 128) ) { // Break (Bit 6) or Frame or Parity (Bit 7) error
Bit8u errreg = 0;
if (event & 64) retval |= SERIAL_BREAK_ERR;
if (event & 128) {
DosDevIOCtl(port->porthandle, IOCTL_ASYNC, ASYNC_GETCOMMERROR,
0, 0, 0, &errors, ulParmLen, &ulParmLen);
if (errors & 8) retval |= SERIAL_FRAMING_ERR;
if (errors & 4) retval |= SERIAL_PARITY_ERR;
}
}
retval |= (chRead & 0xff);
retval |= 0x10000;
}
}
return retval;
}
int SERIAL_getmodemstatus(COMPORT port) {
UCHAR dptr = 0;
ULONG ulParmLen = sizeof(dptr);
DosDevIOCtl(port->porthandle, IOCTL_ASYNC, ASYNC_GETMODEMINPUT,
0, 0, 0, &dptr, ulParmLen, &ulParmLen);
// bits are the same as return value
return (int)dptr;
}
void SERIAL_setDTR(COMPORT port, bool value) {
UCHAR masks[2];
ULONG ulParmLen = sizeof(masks);
if(value) {
masks[0]=0x01;
masks[1]=0xFF;
} else {
masks[0]=0x00;
masks[1]=0xFE;
}
DosDevIOCtl(port->porthandle, IOCTL_ASYNC, ASYNC_SETMODEMCTRL,
0,0,0, &masks, ulParmLen, &ulParmLen);
}
void SERIAL_setRTS(COMPORT port, bool value) {
UCHAR masks[2];
ULONG ulParmLen = sizeof(masks);
if(value) {
masks[0]=0x02;
masks[1]=0xFF;
} else {
masks[0]=0x00;
masks[1]=0xFD;
}
DosDevIOCtl(port->porthandle, IOCTL_ASYNC, ASYNC_SETMODEMCTRL,
0,0,0, &masks, ulParmLen, &ulParmLen);
}
bool SERIAL_setCommParameters(COMPORT port,
int baudrate, char parity, int stopbits, int length) {
// baud
struct {
ULONG baud;
BYTE fraction;
} setbaud;
setbaud.baud = baudrate;
setbaud.fraction = 0;
ULONG ulParmLen = sizeof(setbaud);
APIRET rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_EXTSETBAUDRATE,
&setbaud, ulParmLen, &ulParmLen, 0, 0, 0);
if (rc != NO_ERROR) {
return false;
}
struct {
UCHAR data;
UCHAR parity;
UCHAR stop;
} paramline;
// byte length
if(length > 8 || length < 5) {
// TODO SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
paramline.data = length;
// parity
switch (parity) {
case 'n': paramline.parity = 0; break;
case 'o': paramline.parity = 1; break;
case 'e': paramline.parity = 2; break;
case 'm': paramline.parity = 3; break;
case 's': paramline.parity = 4; break;
default:
// TODO SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
// stopbits
switch(stopbits) {
case SERIAL_1STOP: paramline.stop = 0; break;
case SERIAL_2STOP: paramline.stop = 2; break;
case SERIAL_15STOP: paramline.stop = 1; break;
default:
// TODO SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
// set it
ulParmLen = sizeof(paramline);
rc = DosDevIOCtl(hCom, IOCTL_ASYNC, ASYNC_SETLINECTRL,
&paramline, ulParmLen, &ulParmLen, 0, 0, 0);
if ( rc != NO_ERROR)
return false;
return true;
}
#endif

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2002-2009 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: libserial.h,v 1.2 2009/09/26 09:15:19 h-a-l-9000 Exp $ */
typedef struct _COMPORT *COMPORT;
bool SERIAL_open(const char* portname, COMPORT* port);
void SERIAL_close(COMPORT port);
void SERIAL_getErrorString(char* buffer, int length);
#define SERIAL_1STOP 1
#define SERIAL_2STOP 2
#define SERIAL_15STOP 0
// parity: n, o, e, m, s
bool SERIAL_setCommParameters(COMPORT port,
int baudrate, char parity, int stopbits, int length);
void SERIAL_setDTR(COMPORT port, bool value);
void SERIAL_setRTS(COMPORT port, bool value);
void SERIAL_setBREAK(COMPORT port, bool value);
#define SERIAL_CTS 0x10
#define SERIAL_DSR 0x20
#define SERIAL_RI 0x40
#define SERIAL_CD 0x80
int SERIAL_getmodemstatus(COMPORT port);
bool SERIAL_setmodemcontrol(COMPORT port, int flags);
bool SERIAL_sendchar(COMPORT port, char data);
// 0-7 char data, higher=flags
#define SERIAL_BREAK_ERR 0x10
#define SERIAL_FRAMING_ERR 0x08
#define SERIAL_PARITY_ERR 0x04
#define SERIAL_OVERRUN_ERR 0x02
int SERIAL_getextchar(COMPORT port);

View File

@ -1,3 +1,24 @@
/*
* Copyright (C) 2002-2009 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id $ */
#include "config.h" #include "config.h"
#if C_MODEM #if C_MODEM
@ -161,7 +182,7 @@ bool TCPClientSocket::GetRemoteAddressString(Bit8u* buffer) {
bool TCPClientSocket::ReceiveArray(Bit8u* data, Bitu* size) { bool TCPClientSocket::ReceiveArray(Bit8u* data, Bitu* size) {
if(SDLNet_CheckSockets(listensocketset,0)) if(SDLNet_CheckSockets(listensocketset,0))
{ {
Bitu retval = SDLNet_TCP_Recv(mysock, data, *size); Bits retval = SDLNet_TCP_Recv(mysock, data, *size);
if(retval<1) { if(retval<1) {
isopen=false; isopen=false;
*size=0; *size=0;

View File

@ -1,3 +1,23 @@
/*
* Copyright (C) 2002-2009 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: misc_util.h,v 1.5 2009/09/25 23:40:47 h-a-l-9000 Exp $ */
#ifndef SDLNETWRAPPER_H #ifndef SDLNETWRAPPER_H
#define SDLNETWRAPPER_H #define SDLNETWRAPPER_H

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: nullmodem.cpp,v 1.7 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: nullmodem.cpp,v 1.8 2009/09/25 23:40:47 h-a-l-9000 Exp $ */
#include "dosbox.h" #include "dosbox.h"
@ -36,7 +36,8 @@ CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) {
clientport = 0; clientport = 0;
rx_retry = 0; rx_retry = 0;
rx_retry_max = 100; rx_retry_max = 20;
rx_state=N_RX_DISC;
tx_gather = 12; tx_gather = 12;
@ -51,7 +52,7 @@ CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) {
// usedtr: The nullmodem will // usedtr: The nullmodem will
// 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 transfer 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;
@ -105,6 +106,9 @@ CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) {
clientsocket = new TCPClientSocket(sock); clientsocket = new TCPClientSocket(sock);
if(!clientsocket->isopen) { if(!clientsocket->isopen) {
LOG_MSG("Serial%d: Connection failed.",COMNUMBER); LOG_MSG("Serial%d: Connection failed.",COMNUMBER);
#if SERIAL_DEBUG
log_ser(dbg_aux,"Nullmodem: Connection failed.");
#endif
delete clientsocket; delete clientsocket;
clientsocket=0; clientsocket=0;
return; return;
@ -115,6 +119,9 @@ CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) {
if(!transparent) setRTSDTR(getRTS(), getDTR()); if(!transparent) setRTSDTR(getRTS(), getDTR());
LOG_MSG("Serial%d: Connected to %s",COMNUMBER,peernamebuf); 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); setEvent(SERIAL_POLLING_EVENT, 1);
CSerial::Init_Registers (); CSerial::Init_Registers ();
@ -204,7 +211,7 @@ Bits CNullModem::readChar() {
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) receiveError(0x10); if(rxchar&0x4) receiveByteEx(0x0,0x10);
return -1; // no "payload" received return -1; // no "payload" received
} else return rxchar; } else return rxchar;
} }
@ -223,14 +230,16 @@ void CNullModem::ClientConnect(){
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;
LOG_MSG("Serial%d: Connected to %s",idnumber+1,peernamebuf); LOG_MSG("Serial%d: Connected to %s",idnumber+1,peernamebuf);
setEvent(SERIAL_POLLING_EVENT, 1); setEvent(SERIAL_POLLING_EVENT, 1);
} }
void CNullModem::Disconnect() { void CNullModem::Disconnect() {
removeEvent(SERIAL_POLLING_EVENT);
removeEvent(SERIAL_RX_EVENT);
// it was disconnected; free the socket and restart the server socket // it was disconnected; free the socket and restart the server socket
LOG_MSG("Serial%d: Disconnected.",idnumber+1); LOG_MSG("Serial%d: Disconnected.",COMNUMBER);
delete clientsocket; delete clientsocket;
clientsocket=0; clientsocket=0;
setDSR(false); setDSR(false);
@ -249,48 +258,115 @@ void CNullModem::handleUpperEvent(Bit16u type) {
case SERIAL_POLLING_EVENT: { case SERIAL_POLLING_EVENT: {
// periodically check if new data arrived, disconnect // periodically check if new data arrived, disconnect
// if required. Add it back. // if required. Add it back.
if(!receiveblock && clientsocket) { setEvent(SERIAL_POLLING_EVENT, 1.0f);
if(((!(LSR&LSR_RX_DATA_READY_MASK)) || rx_retry>=rx_retry_max ) // update Modem input line states
&&(!dtrrespect | (dtrrespect&& getDTR()) )) { updateMSR();
rx_retry=0; switch(rx_state) {
Bits rxchar = readChar(); case N_RX_IDLE:
if(rxchar>=0) { if(CanReceiveByte()) {
receiveblock=true; if(doReceive()) {
setEvent(SERIAL_RX_EVENT, bytetime-0.01f); // a byte was received
receiveByte((Bit8u)rxchar); rx_state=N_RX_WAIT;
} setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
else if(rxchar==-2) Disconnect(); } // else still idle
else setEvent(SERIAL_POLLING_EVENT, 1);
} else { } else {
rx_retry++; #if SERIAL_DEBUG
setEvent(SERIAL_POLLING_EVENT, 1); log_ser(dbg_aux,"Nullmodem: block on polling.");
#endif
rx_state=N_RX_BLOCKED;
// have both delays (1ms + bytetime)
setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
} }
break;
case N_RX_BLOCKED:
// one timeout tick
if(!CanReceiveByte()) {
rx_retry++;
if(rx_retry>=rx_retry_max) {
// it has timed out:
rx_retry=0;
removeEvent(SERIAL_RX_EVENT);
if(doReceive()) {
// read away everything
while(doReceive());
rx_state=N_RX_WAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
} else {
// much trouble about nothing
rx_state=N_RX_IDLE;
#if SERIAL_DEBUG
log_ser(dbg_aux,"Nullmodem: unblock due to no more data",rx_retry);
#endif
}
} // else wait further
} else {
// good: we can receive again
removeEvent(SERIAL_RX_EVENT);
rx_retry=0;
if(doReceive()) {
rx_state=N_RX_FASTWAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.65f);
} else {
// much trouble about nothing
rx_state=N_RX_IDLE;
}
}
break;
case N_RX_WAIT:
case N_RX_FASTWAIT:
break;
} }
break; break;
} }
case SERIAL_RX_EVENT: { case SERIAL_RX_EVENT: {
// receive time is up, try to receive another byte. switch(rx_state) {
receiveblock=false; case N_RX_IDLE:
LOG_MSG("internal error in nullmodem");
break;
if((!(LSR&LSR_RX_DATA_READY_MASK) || rx_retry>=rx_retry_max) case N_RX_BLOCKED: // try to receive
&&(!dtrrespect | (dtrrespect&& getDTR()) ) case N_RX_WAIT:
) { case N_RX_FASTWAIT:
rx_retry=0; if(CanReceiveByte()) {
Bits rxchar = readChar(); // just works or unblocked
if(rxchar>=0) { if(doReceive()) {
receiveblock=true; rx_retry=0; // not waiting anymore
setEvent(SERIAL_RX_EVENT, bytetime-0.01f); if(rx_state==N_RX_WAIT) setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
receiveByte((Bit8u)rxchar); else {
// maybe unblocked
rx_state=N_RX_FASTWAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.65f);
} }
else if(rxchar==-2) Disconnect();
else setEvent(SERIAL_POLLING_EVENT, 1);
} else { } else {
setEvent(SERIAL_POLLING_EVENT, 1); // didn't receive anything
rx_retry++; rx_retry=0;
rx_state=N_RX_IDLE;
}
} else {
// blocking now or still blocked
#if SERIAL_DEBUG
if(rx_state==N_RX_BLOCKED)
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);
#endif
setEvent(SERIAL_RX_EVENT, bytetime*0.65f);
rx_state=N_RX_BLOCKED;
}
break;
} }
break; break;
} }
case SERIAL_TX_EVENT: { case SERIAL_TX_EVENT: {
// Maybe echo cirquit works a bit better this way
if(rx_state==N_RX_IDLE && CanReceiveByte() && clientsocket) {
if(doReceive()) {
// a byte was received
rx_state=N_RX_WAIT;
setEvent(SERIAL_RX_EVENT, bytetime*0.9f);
}
}
ByteTransmitted(); ByteTransmitted();
break; break;
} }
@ -301,15 +377,18 @@ void CNullModem::handleUpperEvent(Bit16u type) {
break; break;
} }
case SERIAL_SERVER_POLLING_EVENT: { case SERIAL_SERVER_POLLING_EVENT: {
// As long as nothing is connected to out server poll the // As long as nothing is connected to our server poll the
// connection. // connection.
clientsocket=serversocket->Accept(); clientsocket=serversocket->Accept();
if(clientsocket) { if(clientsocket) {
Bit8u peeripbuf[16]; Bit8u peeripbuf[16];
clientsocket->GetRemoteAddressString(peeripbuf); clientsocket->GetRemoteAddressString(peeripbuf);
LOG_MSG("Serial%d: A client (%s) has connected.",idnumber+1,peeripbuf); LOG_MSG("Serial%d: A client (%s) has connected.",COMNUMBER,peeripbuf);
// new socket found... #if SERIAL_DEBUG
log_ser(dbg_aux,"Nullmodem: A client (%s) has connected.", peeripbuf);
#endif// new socket found...
clientsocket->SetSendBufferSize(256); clientsocket->SetSendBufferSize(256);
rx_state=N_RX_IDLE;
setEvent(SERIAL_POLLING_EVENT, 1); setEvent(SERIAL_POLLING_EVENT, 1);
// we don't accept further connections // we don't accept further connections
@ -350,15 +429,23 @@ void CNullModem::updateMSR () {
} }
void CNullModem::transmitByte (Bit8u val, bool first) { bool CNullModem::doReceive () {
Bits rxchar = readChar();
// transmit it later in THR_Event if(rxchar>=0) {
if(first) { receiveByteEx((Bit8u)rxchar,0);
setEvent(SERIAL_THR_EVENT, bytetime/8); return true;
} else {
//if(clientsocket) clientsocket->Putchar(val);
setEvent(SERIAL_TX_EVENT, bytetime);
} }
else if(rxchar==-2) {
Disconnect();
}
return false;
}
void CNullModem::transmitByte (Bit8u val, bool first) {
// transmit it later in THR_Event
if(first) setEvent(SERIAL_THR_EVENT, bytetime/8);
else setEvent(SERIAL_TX_EVENT, bytetime);
// disable 0xff escaping when transparent mode is enabled // disable 0xff escaping when transparent mode is enabled
if (!transparent && (val==0xff)) WriteChar(0xff); if (!transparent && (val==0xff)) WriteChar(0xff);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: nullmodem.h,v 1.3 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: nullmodem.h,v 1.4 2009/09/25 23:40:47 h-a-l-9000 Exp $ */
// include guard // include guard
#ifndef DOSBOX_NULLMODEM_WIN32_H #ifndef DOSBOX_NULLMODEM_WIN32_H
@ -57,6 +57,14 @@ public:
void setDTR(bool val); void setDTR(bool val);
void handleUpperEvent(Bit16u type); void handleUpperEvent(Bit16u type);
Bitu rx_state;
#define N_RX_IDLE 0
#define N_RX_WAIT 1
#define N_RX_BLOCKED 2
#define N_RX_FASTWAIT 3
#define N_RX_DISC 4
bool doReceive();
void ClientConnect(); void ClientConnect();
void Disconnect(); void Disconnect();
Bits readChar(); Bits readChar();

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: serialport.cpp,v 1.12 2009/05/27 09:15:41 qbix79 Exp $ */ /* $Id: serialport.cpp,v 1.14 2009/10/01 17:25:28 h-a-l-9000 Exp $ */
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
@ -30,15 +30,14 @@
#include "callback.h" // CALLBACK_Idle #include "callback.h" // CALLBACK_Idle
#include "serialport.h" #include "serialport.h"
#include "directserial_win32.h" #include "directserial.h"
#include "directserial_posix.h"
#include "directserial_os2.h"
#include "serialdummy.h" #include "serialdummy.h"
#include "softmodem.h" #include "softmodem.h"
#include "nullmodem.h" #include "nullmodem.h"
#include "cpu.h" #include "cpu.h"
#define LOG_SER(x) log_ser
bool device_COM::Read(Bit8u * data,Bit16u * size) { bool device_COM::Read(Bit8u * data,Bit16u * size) {
// DTR + RTS on // DTR + RTS on
@ -98,10 +97,19 @@ device_COM::~device_COM() {
CSerial* serialports[4] ={0,0,0,0}; CSerial* serialports[4] ={0,0,0,0};
static Bitu SERIAL_Read (Bitu port, Bitu iolen) { static Bitu SERIAL_Read (Bitu port, Bitu iolen) {
for(Bitu i = 0; i < 4; i++) { Bitu i;
if(serial_baseaddr[i]==(port&0xfff8) && (serialports[i]!=0)) { Bitu retval;
Bitu retval=0xff; Bitu index = port & 0x7;
switch (port & 0x7) { switch(port&0xff8) {
case 0x3f8: i=0; break;
case 0x2f8: i=1; break;
case 0x3e8: i=2; break;
case 0x2e8: i=3; break;
default: return 0xff;
}
if(serialports[i]==0) return 0xff;
switch (index) {
case RHR_OFFSET: case RHR_OFFSET:
retval = serialports[i]->Read_RHR(); retval = serialports[i]->Read_RHR();
break; break;
@ -130,30 +138,40 @@ static Bitu SERIAL_Read (Bitu port, Bitu iolen) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
const char* const dbgtext[]= const char* const dbgtext[]=
{"RHR","IER","ISR","LCR","MCR","LSR","MSR","SPR"}; {"RHR","IER","ISR","LCR","MCR","LSR","MSR","SPR","DLL","DLM"};
if(serialports[i]->dbg_register) if(serialports[i]->dbg_register) {
fprintf(serialports[i]->debugfp,"%12.3f read 0x%x from %s.\r\n", if((index<2) && ((serialports[i]->LCR)&LCR_DIVISOR_Enable_MASK))
PIC_FullIndex(),retval,dbgtext[port&0x7]); index += 8;
serialports[i]->log_ser(serialports[i]->dbg_register,
"read 0x%2x from %s.",retval,dbgtext[index]);
}
#endif #endif
return retval; return retval;
}
}
return 0xff;
} }
static void SERIAL_Write (Bitu port, Bitu val, Bitu) { static void SERIAL_Write (Bitu port, Bitu val, Bitu) {
Bitu i;
for(Bitu i = 0; i < 4; i++) { Bitu index = port & 0x7;
if(serial_baseaddr[i]==(port&0xfff8) && serialports[i]) { switch(port&0xff8) {
case 0x3f8: i=0; break;
case 0x2f8: i=1; break;
case 0x3e8: i=2; break;
case 0x2e8: i=3; break;
default: return;
}
if(serialports[i]==0) return;
#if SERIAL_DEBUG #if SERIAL_DEBUG
const char* const dbgtext[]={"THR","IER","FCR","LCR","MCR","!LSR","MSR","SPR"}; const char* const dbgtext[]={"THR","IER","FCR",
if(serialports[i]->dbg_register) "LCR","MCR","!LSR","MSR","SPR","DLL","DLM"};
fprintf(serialports[i]->debugfp,"%12.3f write 0x%x to %s.\r\n", if(serialports[i]->dbg_register) {
PIC_FullIndex(),val,dbgtext[port&0x7]); Bitu debugindex=index;
if((index<2) && ((serialports[i]->LCR)&LCR_DIVISOR_Enable_MASK))
debugindex += 8;
serialports[i]->log_ser(serialports[i]->dbg_register,
"write 0x%2x to %s.",val,dbgtext[debugindex]);
}
#endif #endif
switch (index) {
switch (port & 0x7) {
case THR_OFFSET: case THR_OFFSET:
serialports[i]->Write_THR (val); serialports[i]->Write_THR (val);
return; return;
@ -178,17 +196,41 @@ static void SERIAL_Write (Bitu port, Bitu val, Bitu) {
default: default:
serialports[i]->Write_reserved (val, port & 0x7); serialports[i]->Write_reserved (val, port & 0x7);
} }
} }
#if SERIAL_DEBUG
void CSerial::log_ser(bool active, char const* format,...) {
if(active) {
// copied from DEBUG_SHOWMSG
char buf[512];
buf[0]=0;
sprintf(buf,"%12.3f [% 7u] ",PIC_FullIndex(), SDL_GetTicks());
va_list msg;
va_start(msg,format);
vsprintf(buf+strlen(buf),format,msg);
va_end(msg);
// Add newline if not present
Bitu len=strlen(buf);
if(buf[len-1]!='\n') strcat(buf,"\r\n");
fputs(buf,debugfp);
} }
} }
#endif
void CSerial::changeLineProperties() { void CSerial::changeLineProperties() {
// update the event wait time // update the event wait time
float bitlen;
float bitlen = (1000.0f/115200.0f)*(float)baud_divider; if(baud_divider==0) bitlen=(1000.0f/115200.0f);
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; // stopbit
#if SERIAL_DEBUG
const char* const dbgtext[]={"none","odd","none","even","none","mark","none","space"};
log_ser(dbg_serialtraffic,"New COM parameters: baudrate %5.0f, parity %s, wordlen %d, stopbits %d",
1.0/bitlen*1000.0f,dbgtext[(LCR&0x38)>>3],(LCR&0x3)+5,((LCR&0x4)>>2)+1);
#endif
updatePortConfig (baud_divider, LCR); updatePortConfig (baud_divider, LCR);
} }
@ -212,35 +254,38 @@ void CSerial::handleEvent(Bit16u type) {
case SERIAL_TX_LOOPBACK_EVENT: { case SERIAL_TX_LOOPBACK_EVENT: {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_serialtraffic) log_ser(dbg_serialtraffic,loopback_data<0x10?
fprintf(debugfp,loopback_data<0x10? "%12.3f tx 0x%02x (%u) (loopback)\r\n": "tx 0x%02x (%u) (loopback)":"tx 0x%02x (%c) (loopback)",
"%12.3f tx 0x%02x (%c) (loopback)\r\n", loopback_data, loopback_data);
PIC_FullIndex(),loopback_data,
loopback_data);
#endif #endif
receiveByte (loopback_data); receiveByte (loopback_data);
ByteTransmitted (); ByteTransmitted ();
break; break;
} }
case SERIAL_THR_LOOPBACK_EVENT: { case SERIAL_THR_LOOPBACK_EVENT: {
loopback_data=txfifo->probeByte();
ByteTransmitting(); ByteTransmitting();
loopback_data=THR;
setEvent(SERIAL_TX_LOOPBACK_EVENT,bytetime); setEvent(SERIAL_TX_LOOPBACK_EVENT,bytetime);
break; break;
} }
case SERIAL_ERRMSG_EVENT: { case SERIAL_ERRMSG_EVENT: {
LOG_MSG("Serial%d: Errors occured: "\ LOG_MSG("Serial%d: Errors: "\
"Framing %d, Parity %d, Overrun %d (IF0:%d), Break %d", COMNUMBER, "Framing %d, Parity %d, Overrun RX:%d (IF0:%d), TX:%d, Break %d",
framingErrors, parityErrors, overrunErrors, overrunIF0, breakErrors); COMNUMBER, framingErrors, parityErrors, overrunErrors,
overrunIF0,txOverrunErrors, breakErrors);
errormsg_pending=false; errormsg_pending=false;
framingErrors=0; framingErrors=0;
parityErrors=0; parityErrors=0;
overrunErrors=0; overrunErrors=0;
txOverrunErrors=0;
overrunIF0=0; overrunIF0=0;
breakErrors=0; breakErrors=0;
break; break;
} }
case SERIAL_RX_TIMEOUT_EVENT: {
rise(TIMEOUT_PRIORITY);
break;
}
default: handleUpperEvent(type); default: handleUpperEvent(type);
} }
} }
@ -250,20 +295,14 @@ void CSerial::handleEvent(Bit16u type) {
/*****************************************************************************/ /*****************************************************************************/
void CSerial::rise (Bit8u priority) { void CSerial::rise (Bit8u priority) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_interrupt)
{
if(priority&TX_PRIORITY && !(waiting_interrupts&TX_PRIORITY)) if(priority&TX_PRIORITY && !(waiting_interrupts&TX_PRIORITY))
fprintf(debugfp,"%12.3f tx interrupt on.\r\n",PIC_FullIndex()); log_ser(dbg_interrupt,"tx interrupt on.");
if(priority&RX_PRIORITY && !(waiting_interrupts&RX_PRIORITY)) if(priority&RX_PRIORITY && !(waiting_interrupts&RX_PRIORITY))
fprintf(debugfp,"%12.3f rx interrupt on.\r\n",PIC_FullIndex()); log_ser(dbg_interrupt,"rx interrupt on.");
if(priority&MSR_PRIORITY && !(waiting_interrupts&MSR_PRIORITY)) if(priority&MSR_PRIORITY && !(waiting_interrupts&MSR_PRIORITY))
fprintf(debugfp,"%12.3f msr interrupt on.\r\n",PIC_FullIndex()); log_ser(dbg_interrupt,"msr interrupt on.");
if(priority&TIMEOUT_PRIORITY && !(waiting_interrupts&TIMEOUT_PRIORITY))
if(priority&ERROR_PRIORITY && !(waiting_interrupts&ERROR_PRIORITY)) log_ser(dbg_interrupt,"fifo rx timeout interrupt on.");
fprintf(debugfp,"%12.3f error interrupt on.\r\n",PIC_FullIndex());
}
#endif #endif
waiting_interrupts |= priority; waiting_interrupts |= priority;
@ -274,23 +313,15 @@ void CSerial::rise (Bit8u priority) {
void CSerial::clear (Bit8u priority) { void CSerial::clear (Bit8u priority) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_interrupt)
{
if(priority&TX_PRIORITY && (waiting_interrupts&TX_PRIORITY)) if(priority&TX_PRIORITY && (waiting_interrupts&TX_PRIORITY))
fprintf(debugfp,"%12.3f tx interrupt off.\r\n",PIC_FullIndex()); log_ser(dbg_interrupt,"tx interrupt off.");
if(priority&RX_PRIORITY && (waiting_interrupts&RX_PRIORITY)) if(priority&RX_PRIORITY && (waiting_interrupts&RX_PRIORITY))
fprintf(debugfp,"%12.3f rx interrupt off.\r\n",PIC_FullIndex()); log_ser(dbg_interrupt,"rx interrupt off.");
if(priority&MSR_PRIORITY && (waiting_interrupts&MSR_PRIORITY)) if(priority&MSR_PRIORITY && (waiting_interrupts&MSR_PRIORITY))
fprintf(debugfp,"%12.3f msr interrupt off.\r\n",PIC_FullIndex()); log_ser(dbg_interrupt,"msr interrupt off.");
if(priority&ERROR_PRIORITY && (waiting_interrupts&ERROR_PRIORITY)) if(priority&ERROR_PRIORITY && (waiting_interrupts&ERROR_PRIORITY))
fprintf(debugfp,"%12.3f error interrupt off.\r\n",PIC_FullIndex()); log_ser(dbg_interrupt,"error interrupt off.");
}
#endif #endif
waiting_interrupts &= (~priority); waiting_interrupts &= (~priority);
ComputeInterrupts(); ComputeInterrupts();
} }
@ -300,138 +331,128 @@ void CSerial::ComputeInterrupts () {
Bitu val = IER & waiting_interrupts; Bitu val = IER & waiting_interrupts;
if (val & ERROR_PRIORITY) ISR = ISR_ERROR_VAL; if (val & ERROR_PRIORITY) ISR = ISR_ERROR_VAL;
else if (val & TIMEOUT_PRIORITY) ISR = ISR_FIFOTIMEOUT_VAL;
else if (val & RX_PRIORITY) ISR = ISR_RX_VAL; else if (val & RX_PRIORITY) ISR = ISR_RX_VAL;
else if (val & TX_PRIORITY) ISR = ISR_TX_VAL; else if (val & TX_PRIORITY) ISR = ISR_TX_VAL;
else if (val & MSR_PRIORITY) ISR = ISR_MSR_VAL; else if (val & MSR_PRIORITY) ISR = ISR_MSR_VAL;
else ISR = ISR_CLEAR_VAL; else ISR = ISR_CLEAR_VAL;
if(val && !irq_active) { if(val && !irq_active)
{
irq_active=true; irq_active=true;
if(op2) {
PIC_ActivateIRQ(irq); PIC_ActivateIRQ(irq);
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_interrupt) log_ser(dbg_interrupt,"IRQ%d on.",irq);
fprintf(debugfp,"%12.3f IRQ%d on.\r\n",PIC_FullIndex(),irq);
#endif #endif
} }
} else if((!val) && irq_active) {
if(!val && irq_active) {
irq_active=false; irq_active=false;
if(op2) {
PIC_DeActivateIRQ(irq); PIC_DeActivateIRQ(irq);
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_interrupt) log_ser(dbg_interrupt,"IRQ%d off.",irq);
fprintf(debugfp,"%12.3f IRQ%d off.\r\n",PIC_FullIndex(),irq);
#endif #endif
} }
}
} }
/*****************************************************************************/ /*****************************************************************************/
/* Can a byte be received? **/ /* Can a byte be received? **/
/*****************************************************************************/ /*****************************************************************************/
bool CSerial::CanReceiveByte() { bool CSerial::CanReceiveByte() {
return (LSR & LSR_RX_DATA_READY_MASK) == 0; return !rxfifo->isFull();
} }
/*****************************************************************************/ /*****************************************************************************/
/* A byte was received **/ /* A byte was received **/
/*****************************************************************************/ /*****************************************************************************/
void CSerial::receiveByte (Bit8u data) { void CSerial::receiveByteEx (Bit8u data, Bit8u error) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_serialtraffic) log_ser(dbg_serialtraffic,data<0x10 ? "\t\t\t\trx 0x%02x (%u)":
fprintf(debugfp,loopback_data<0x10? "%12.3f rx 0x%02x (%u)\r\n": "\t\t\t\trx 0x%02x (%c)", data, data);
"%12.3f rx 0x%02x (%c)\r\n",
PIC_FullIndex(), data, data);
#endif #endif
if (!(rxfifo->addb(data))) {
// Overrun error ;o
error |= LSR_OVERRUN_ERROR_MASK;
}
removeEvent(SERIAL_RX_TIMEOUT_EVENT);
if(rxfifo->getUsage()==rx_interrupt_threshold) rise (RX_PRIORITY);
else setEvent(SERIAL_RX_TIMEOUT_EVENT,bytetime*4.0f);
if (LSR & LSR_RX_DATA_READY_MASK) { // Overrun error ;o if(error) {
// A lot of UART chips generate a framing error too when receiving break
if(error&LSR_RX_BREAK_MASK) error |= LSR_FRAMING_ERROR_MASK;
#if SERIAL_DEBUG
log_ser(dbg_serialtraffic,"with error: framing=%d,overrun=%d,break=%d,parity=%d",
(error&LSR_FRAMING_ERROR_MASK)>0,(error&LSR_OVERRUN_ERROR_MASK)>0,
(error&LSR_RX_BREAK_MASK)>0,(error&LSR_PARITY_ERROR_MASK)>0);
#endif
if(FCR&FCR_ACTIVATE) {
// error and FIFO active
if(!errorfifo->isFull()) {
errors_in_fifo++;
errorfifo->addb(error);
}
else {
Bit8u toperror=errorfifo->getTop();
if(!toperror) errors_in_fifo++;
errorfifo->addb(error|toperror);
}
if(errorfifo->probeByte()) {
// the next byte in the error fifo has an error
rise (ERROR_PRIORITY);
LSR |= error;
}
} else {
// error and FIFO inactive
rise (ERROR_PRIORITY);
LSR |= error;
};
if(error&LSR_PARITY_ERROR_MASK) {
parityErrors++;
};
if(error&LSR_OVERRUN_ERROR_MASK) {
overrunErrors++;
if(!GETFLAG(IF)) overrunIF0++;
#if SERIAL_DEBUG
log_ser(dbg_serialtraffic,"rx overrun (IF=%d)", GETFLAG(IF)>0);
#endif
};
if(error&LSR_FRAMING_ERROR_MASK) {
framingErrors++;
}
if(error&LSR_RX_BREAK_MASK) {
breakErrors++;
}
// trigger status window error notification
if(!errormsg_pending) { if(!errormsg_pending) {
errormsg_pending=true; errormsg_pending=true;
setEvent(SERIAL_ERRMSG_EVENT,1000); setEvent(SERIAL_ERRMSG_EVENT,1000);
} }
overrunErrors++;
Bitu iflag= GETFLAG(IF);
if(!iflag)overrunIF0++;
#if SERIAL_DEBUG
if(dbg_serialtraffic)
fprintf(debugfp, "%12.3f rx overrun (IF=%d)\r\n",
PIC_FullIndex(), iflag);
#endif
LSR |= LSR_OVERRUN_ERROR_MASK;
rise (ERROR_PRIORITY);
} else { } else {
RHR = data; // no error
LSR |= LSR_RX_DATA_READY_MASK; if(FCR&FCR_ACTIVATE) {
rise (RX_PRIORITY); errorfifo->addb(error);
}
} }
} }
/*****************************************************************************/ void CSerial::receiveByte (Bit8u data) {
/* A line error was received **/ receiveByteEx(data,0);
/*****************************************************************************/
void CSerial::receiveError (Bit8u errorword) {
if(!errormsg_pending) {
errormsg_pending=true;
setEvent(SERIAL_ERRMSG_EVENT,1000);
}
if(errorword&LSR_PARITY_ERROR_MASK) {
parityErrors++;
#if SERIAL_DEBUG
if(dbg_serialtraffic)
fprintf(debugfp, "%12.3f parity error\r\n",
PIC_FullIndex());
#endif
}
if(errorword&LSR_FRAMING_ERROR_MASK) {
framingErrors++;
#if SERIAL_DEBUG
if(dbg_serialtraffic)
fprintf(debugfp, "%12.3f framing error\r\n",
PIC_FullIndex());
#endif
}
if(errorword&LSR_RX_BREAK_MASK) {
breakErrors++;
#if SERIAL_DEBUG
if(dbg_serialtraffic)
fprintf(debugfp, "%12.3f break received\r\n",
PIC_FullIndex());
#endif
}
LSR |= errorword;
rise (ERROR_PRIORITY);
} }
/*****************************************************************************/ /*****************************************************************************/
/* ByteTransmitting: Byte has made it from THR to TX. **/ /* ByteTransmitting: Byte has made it from THR to TX. **/
/*****************************************************************************/ /*****************************************************************************/
void CSerial::ByteTransmitting() { void CSerial::ByteTransmitting() {
switch(LSR&(LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK)) if(sync_guardtime) {
{ //LOG_MSG("byte transmitting after guard");
case LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK: //if(txfifo->isEmpty()) LOG_MSG("Serial port: FIFO empty when it should not");
// bad case there must have been one sync_guardtime=false;
case LSR_TX_HOLDING_EMPTY_MASK: txfifo->getb();
case LSR_TX_EMPTY_MASK: // holding full but workreg empty impossible } //else LOG_MSG("byte transmitting");
LOG_MSG("Internal error in serial port(1)(0x%x).",LSR); if(txfifo->isEmpty())rise (TX_PRIORITY);
break;
case 0: // THR is empty now.
LSR |= LSR_TX_HOLDING_EMPTY_MASK;
// trigger interrupt
rise (TX_PRIORITY);
break;
}
} }
@ -439,39 +460,23 @@ void CSerial::ByteTransmitting() {
/* ByteTransmitted: When a byte was sent, notify here. **/ /* ByteTransmitted: When a byte was sent, notify here. **/
/*****************************************************************************/ /*****************************************************************************/
void CSerial::ByteTransmitted () { void CSerial::ByteTransmitted () {
switch(LSR&(LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK)) if(!txfifo->isEmpty()) {
{ // there is more data
case LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK: Bit8u data = txfifo->getb();
// bad case there must have been one #if SERIAL_DEBUG
case LSR_TX_EMPTY_MASK: // holding full but workreg empty impossible log_ser(dbg_serialtraffic,data<0x10?
LOG_MSG("Internal error in serial port(2)."); "\t\t\t\t\ttx 0x%02x (%u) (from buffer)":
break; "\t\t\t\t\ttx 0x%02x (%c) (from buffer)",data,data);
#endif
if (loopback) setEvent(SERIAL_TX_LOOPBACK_EVENT, bytetime);
else transmitByte(data,false);
if(txfifo->isEmpty())rise (TX_PRIORITY);
case LSR_TX_HOLDING_EMPTY_MASK: // now both are empty } else {
#if SERIAL_DEBUG
log_ser(dbg_serialtraffic,"tx buffer empty.");
#endif
LSR |= LSR_TX_EMPTY_MASK; LSR |= LSR_TX_EMPTY_MASK;
break;
case 0: // now one is empty, send the other one
LSR |= LSR_TX_HOLDING_EMPTY_MASK;
if (loopback) {
loopback_data=THR;
setEvent(SERIAL_TX_LOOPBACK_EVENT, bytetime);
}
else {
#if SERIAL_DEBUG
if(dbg_serialtraffic)
fprintf(debugfp,THR<0x10? "%12.3f tx 0x%02x (%u) (from THR)\r\n":
"%12.3f tx 0x%02x (%c) (from THR)\r\n",
PIC_FullIndex(),THR,
THR);
#endif
transmitByte(THR,false);
}
// It's ok here.
rise (TX_PRIORITY);
break;
} }
} }
@ -490,49 +495,41 @@ void CSerial::Write_THR (Bit8u data) {
// write to THR // write to THR
clear (TX_PRIORITY); clear (TX_PRIORITY);
switch(LSR&(LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK)) if((LSR & LSR_TX_EMPTY_MASK))
{ { // we were idle before
case 0: // both full - overflow //LOG_MSG("starting new transmit cycle");
#if SERIAL_DEBUG //if(sync_guardtime) LOG_MSG("Serial port internal error 1");
if(dbg_serialtraffic) fprintf(debugfp, "%12.3f tx overflow\r\n", //if(!(LSR & LSR_TX_EMPTY_MASK)) LOG_MSG("Serial port internal error 2");
PIC_FullIndex()); //if(txfifo->getUsage()) LOG_MSG("Serial port internal error 3");
#endif
// overwrite THR
THR = data;
break;
case LSR_TX_EMPTY_MASK: // holding full but workreg empty impossible // need "warming up" time
LOG_MSG("Internal error in serial port(3)."); sync_guardtime=true;
break; // block the fifo so it returns THR full (or not in case of FIFO on)
txfifo->addb(data);
case LSR_TX_HOLDING_EMPTY_MASK: // now both are full // transmit shift register is busy
LSR &= (~LSR_TX_HOLDING_EMPTY_MASK);
THR = data;
break;
case LSR_TX_HOLDING_EMPTY_MASK|LSR_TX_EMPTY_MASK:
// both are full until the first delay has passed
THR=data;
LSR &= (~LSR_TX_EMPTY_MASK); LSR &= (~LSR_TX_EMPTY_MASK);
LSR &= (~LSR_TX_HOLDING_EMPTY_MASK);
if(loopback) setEvent(SERIAL_THR_LOOPBACK_EVENT, bytetime/10); if(loopback) setEvent(SERIAL_THR_LOOPBACK_EVENT, bytetime/10);
else { else {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_serialtraffic) log_ser(dbg_serialtraffic,data<0x10?
fprintf(debugfp,data<0x10? "%12.3f tx 0x%02x (%u)\r\n": "\t\t\t\t\ttx 0x%02x (%u) [FIFO=%2d]":
"%12.3f tx 0x%02x (%c)\r\n", "\t\t\t\t\ttx 0x%02x (%c) [FIFO=%2d]",data,data,txfifo->getUsage());
PIC_FullIndex(),data,
data);
#endif #endif
transmitByte (data,true); transmitByte (data,true);
} }
} else {
// triggered // shift register is transmitting
// when holding gets empty if(!txfifo->addb(data)) {
// rise (TX_PRIORITY); // TX overflow
break; #if SERIAL_DEBUG
log_ser(dbg_serialtraffic,"tx overflow");
#endif
txOverrunErrors++;
if(!errormsg_pending) {
errormsg_pending=true;
setEvent(SERIAL_ERRMSG_EVENT,1000);
}
}
} }
} }
} }
@ -545,9 +542,26 @@ Bitu CSerial::Read_RHR () {
// 0-7 received data // 0-7 received data
if ((LCR & LCR_DIVISOR_Enable_MASK)) return baud_divider&0xff; if ((LCR & LCR_DIVISOR_Enable_MASK)) return baud_divider&0xff;
else { else {
clear (RX_PRIORITY); Bit8u data=rxfifo->getb();
LSR &= (~LSR_RX_DATA_READY_MASK); if(FCR&FCR_ACTIVATE) {
return RHR; Bit8u error=errorfifo->getb();
if(error) errors_in_fifo--;
// new error
if(!rxfifo->isEmpty()) {
error=errorfifo->probeByte();
if(error) {
LSR |= error;
rise(ERROR_PRIORITY);
}
}
}
// Reading RHR resets the FIFO timeout
clear (TIMEOUT_PRIORITY);
// RX int. is cleared if the buffer holds less data than the threshold
if(rxfifo->getUsage()<rx_interrupt_threshold)clear(RX_PRIORITY);
removeEvent(SERIAL_RX_TIMEOUT_EVENT);
if(!rxfifo->isEmpty()) setEvent(SERIAL_RX_TIMEOUT_EVENT,bytetime*4.0f);
return data;
} }
} }
@ -564,7 +578,7 @@ Bitu CSerial::Read_IER () {
// 4-7 0 // 4-7 0
if (LCR & LCR_DIVISOR_Enable_MASK) return baud_divider>>8; if (LCR & LCR_DIVISOR_Enable_MASK) return baud_divider>>8;
else return IER; else return IER&0x0f;
} }
void CSerial::Write_IER (Bit8u data) { void CSerial::Write_IER (Bit8u data) {
@ -573,11 +587,12 @@ void CSerial::Write_IER (Bit8u data) {
baud_divider |= ((Bit16u)data)<<8; baud_divider |= ((Bit16u)data)<<8;
changeLineProperties(); changeLineProperties();
} else { } else {
// Retrigger TX interrupt
IER = data&0xF; if (txfifo->isEmpty()&& (data&TX_PRIORITY))
if ((LSR & LSR_TX_HOLDING_EMPTY_MASK) && (IER&TX_PRIORITY))
waiting_interrupts |= TX_PRIORITY; waiting_interrupts |= TX_PRIORITY;
IER = data&0xF;
if((FCR&FCR_ACTIVATE)&&data&RX_PRIORITY) IER |= TIMEOUT_PRIORITY;
ComputeInterrupts(); ComputeInterrupts();
} }
} }
@ -593,6 +608,7 @@ Bitu CSerial::Read_ISR () {
// 1-3 identification // 1-3 identification
// 011 LSR // 011 LSR
// 010 RXRDY // 010 RXRDY
// 110 RX_TIMEOUT
// 001 TXRDY // 001 TXRDY
// 000 MSR // 000 MSR
// 4-7 0 // 4-7 0
@ -601,14 +617,44 @@ Bitu CSerial::Read_ISR () {
Bit8u retval = ISR; Bit8u retval = ISR;
// clear changes ISR!! mean.. // clear changes ISR!! mean..
if(ISR==ISR_TX_VAL) clear (TX_PRIORITY); if(ISR==ISR_TX_VAL) clear(TX_PRIORITY);
if(FCR&FCR_ACTIVATE) retval |= FIFO_STATUS_ACTIVE;
return retval; return retval;
} }
#define BIT_CHANGE_H(oldv,newv,bitmask) (!(oldv&bitmask) && (newv&bitmask))
#define BIT_CHANGE_L(oldv,newv,bitmask) ((oldv&bitmask) && !(newv&bitmask))
void CSerial::Write_FCR (Bit8u data) { void CSerial::Write_FCR (Bit8u data) {
if((!fifo_warn) && (data&0x1)) { if(BIT_CHANGE_H(FCR,data,FCR_ACTIVATE)) {
fifo_warn=true; // FIFO was switched on
LOG_MSG("Serial%d: Warning: Tried to activate FIFO.",COMNUMBER); errors_in_fifo=0; // should already be 0
errorfifo->setSize(fifosize);
rxfifo->setSize(fifosize);
txfifo->setSize(fifosize);
} else if(BIT_CHANGE_L(FCR,data,FCR_ACTIVATE)) {
// FIFO was switched off
errors_in_fifo=0;
errorfifo->setSize(1);
rxfifo->setSize(1);
txfifo->setSize(1);
rx_interrupt_threshold=1;
}
FCR=data&0xCF;
if(FCR&FCR_CLEAR_RX) {
errors_in_fifo=0;
errorfifo->clear();
rxfifo->clear();
}
if(FCR&FCR_CLEAR_TX) txfifo->clear();
if(FCR&FCR_ACTIVATE) {
switch(FCR>>6) {
case 0: rx_interrupt_threshold=1; break;
case 1: rx_interrupt_threshold=4; break;
case 2: rx_interrupt_threshold=8; break;
case 3: rx_interrupt_threshold=14; break;
}
} }
} }
@ -643,10 +689,8 @@ void CSerial::Write_LCR (Bit8u data) {
// TODO: set loopback break event to reveiveError after // TODO: set loopback break event to reveiveError after
} }
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_serialtraffic) log_ser(dbg_serialtraffic,((LCR & LCR_BREAK_MASK)!=0) ?
fprintf(debugfp,((LCR & LCR_BREAK_MASK)!=0)? "break on.":"break off.");
"%12.3f break on.\r\n":
"%12.3f break off.\r\n", PIC_FullIndex());
#endif #endif
} }
} }
@ -675,7 +719,7 @@ Bitu CSerial::Read_MCR () {
void CSerial::Write_MCR (Bit8u data) { void CSerial::Write_MCR (Bit8u data) {
// WARNING: At the time setRTSDTR is called rts and dsr members are still wrong. // WARNING: At the time setRTSDTR is called rts and dsr members are still wrong.
if(data&FIFO_FLOWCONTROL) LOG_MSG("Warning: tried to activate hardware handshake.");
bool temp_dtr = data & MCR_DTR_MASK? true:false; bool temp_dtr = data & MCR_DTR_MASK? true:false;
bool temp_rts = data & MCR_RTS_MASK? true:false; bool temp_rts = data & MCR_RTS_MASK? true:false;
bool temp_op1 = data & MCR_OP1_MASK? true:false; bool temp_op1 = data & MCR_OP1_MASK? true:false;
@ -718,34 +762,34 @@ void CSerial::Write_MCR (Bit8u data) {
// both difference // both difference
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_modemcontrol) log_ser(dbg_modemcontrol,"RTS %x.",temp_rts);
{ log_ser(dbg_modemcontrol,"DTR %x.",temp_dtr);
fprintf(debugfp,temp_rts?"%12.3f RTS on.\r\n":
"%12.3f RTS off.\r\n", PIC_FullIndex());
fprintf(debugfp,temp_dtr?"%12.3f DTR on.\r\n":
"%12.3f DTR off.\r\n", PIC_FullIndex());
}
#endif #endif
setRTSDTR(temp_rts, temp_dtr); setRTSDTR(temp_rts, temp_dtr);
} else { } else {
// only RTS // only RTS
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_modemcontrol) log_ser(dbg_modemcontrol,"RTS %x.",temp_rts);
fprintf(debugfp,temp_rts?"%12.3f RTS on.\r\n":"%12.3f RTS off.\r\n", PIC_FullIndex());
#endif #endif
setRTS(temp_rts); setRTS(temp_rts);
} }
} else if(temp_dtr!=dtr) { } else if(temp_dtr!=dtr) {
// only DTR // only DTR
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_modemcontrol) log_ser(dbg_modemcontrol,"%DTR %x.",temp_dtr);
fprintf(debugfp,temp_dtr?"%12.3f DTR on.\r\n":"%12.3f DTR off.\r\n", PIC_FullIndex());
#endif #endif
setDTR(temp_dtr); setDTR(temp_dtr);
} }
} }
// interrupt logic: if OP2 is 0, the IRQ line is tristated (pulled high)
if((!op2) && temp_op2) {
// irq has been enabled (tristate high -> irq level)
if(!irq_active) PIC_DeActivateIRQ(irq);
} else if(op2 && (!temp_op2)) {
if(!irq_active) PIC_ActivateIRQ(irq);
}
dtr=temp_dtr; dtr=temp_dtr;
rts=temp_rts; rts=temp_rts;
op1=temp_op1; op1=temp_op1;
@ -761,7 +805,10 @@ void CSerial::Write_MCR (Bit8u data) {
// - event from real serial port // - event from real serial port
// - loopback // - loopback
Bitu CSerial::Read_LSR () { Bitu CSerial::Read_LSR () {
Bitu retval = LSR; Bitu retval = LSR & (LSR_ERROR_MASK|LSR_TX_EMPTY_MASK);
if(txfifo->isEmpty()) retval |= LSR_TX_HOLDING_EMPTY_MASK;
if(!(rxfifo->isEmpty()))retval |= LSR_RX_DATA_READY_MASK;
if(errors_in_fifo) retval |= FIFO_ERROR;
LSR &= (~LSR_ERROR_MASK); // clear error bits on read LSR &= (~LSR_ERROR_MASK); // clear error bits on read
clear (ERROR_PRIORITY); clear (ERROR_PRIORITY);
return retval; return retval;
@ -872,8 +919,7 @@ void CSerial::setRI (bool value) {
if (value != ri) { if (value != ri) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_modemcontrol) log_ser(dbg_modemcontrol,"%RI %x.",value);
fprintf(debugfp,value?"%12.3f RI on.\r\n":"%12.3f RI off.\r\n", PIC_FullIndex());
#endif #endif
// don't change delta when in loopback mode // don't change delta when in loopback mode
ri=value; ri=value;
@ -887,8 +933,7 @@ void CSerial::setRI (bool value) {
void CSerial::setDSR (bool value) { void CSerial::setDSR (bool value) {
if (value != dsr) { if (value != dsr) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_modemcontrol) log_ser(dbg_modemcontrol,"DSR %x.",value);
fprintf(debugfp,value?"%12.3f DSR on.\r\n":"%12.3f DSR off.\r\n", PIC_FullIndex());
#endif #endif
// don't change delta when in loopback mode // don't change delta when in loopback mode
dsr=value; dsr=value;
@ -902,8 +947,7 @@ void CSerial::setDSR (bool value) {
void CSerial::setCD (bool value) { void CSerial::setCD (bool value) {
if (value != cd) { if (value != cd) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_modemcontrol) log_ser(dbg_modemcontrol,"CD %x.",value);
fprintf(debugfp,value?"%12.3f CD on.\r\n":"%12.3f CD off.\r\n", PIC_FullIndex());
#endif #endif
// don't change delta when in loopback mode // don't change delta when in loopback mode
cd=value; cd=value;
@ -917,8 +961,7 @@ void CSerial::setCD (bool value) {
void CSerial::setCTS (bool value) { void CSerial::setCTS (bool value) {
if (value != cts) { if (value != cts) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_modemcontrol) log_ser(dbg_modemcontrol,"CTS %x.",value);
fprintf(debugfp,value?"%12.3f CTS on.\r\n":"%12.3f CTS off.\r\n", PIC_FullIndex());
#endif #endif
// don't change delta when in loopback mode // don't change delta when in loopback mode
cts=value; cts=value;
@ -945,8 +988,6 @@ void CSerial::Init_Registers () {
Bit8u lcrresult = 0; Bit8u lcrresult = 0;
Bit16u baudresult = 0; Bit16u baudresult = 0;
RHR = 0;
THR = 0;
IER = 0; IER = 0;
ISR = 0x1; ISR = 0x1;
LCR = 0; LCR = 0;
@ -957,6 +998,10 @@ void CSerial::Init_Registers () {
op1=true; op1=true;
op2=true; op2=true;
sync_guardtime=false;
FCR=0xff;
Write_FCR(0x00);
LSR = 0x60; LSR = 0x60;
d_cts = true; d_cts = true;
@ -1023,6 +1068,12 @@ void CSerial::Init_Registers () {
} }
CSerial::CSerial(Bitu id, CommandLine* cmd) { CSerial::CSerial(Bitu id, CommandLine* cmd) {
idnumber=id;
Bit16u base = serial_baseaddr[id];
irq = serial_defaultirq[id];
getBituSubstring("irq:",&irq, cmd);
if (irq < 2 || irq > 15) irq = serial_defaultirq[id];
#if SERIAL_DEBUG #if SERIAL_DEBUG
dbg_serialtraffic = cmd->FindExist("dbgtr", false); dbg_serialtraffic = cmd->FindExist("dbgtr", false);
@ -1031,43 +1082,54 @@ CSerial::CSerial(Bitu id, CommandLine* cmd) {
dbg_interrupt = cmd->FindExist("dbgirq", false); dbg_interrupt = cmd->FindExist("dbgirq", false);
dbg_aux = cmd->FindExist("dbgaux", false); dbg_aux = cmd->FindExist("dbgaux", false);
if(cmd->FindExist("dbgall", false)) {
dbg_serialtraffic=
dbg_modemcontrol=
dbg_register=
dbg_interrupt=
dbg_aux= true;
}
if(dbg_serialtraffic|dbg_modemcontrol|dbg_register|dbg_interrupt|dbg_aux) if(dbg_serialtraffic|dbg_modemcontrol|dbg_register|dbg_interrupt|dbg_aux)
debugfp=OpenCaptureFile("serlog",".serlog.txt"); debugfp=OpenCaptureFile("serlog",".serlog.txt");
else debugfp=0; else debugfp=0;
if(debugfp == 0) {
dbg_serialtraffic=
dbg_modemcontrol=
dbg_register=
dbg_interrupt=
dbg_aux= false;
} else {
std::string cleft;
cmd->GetStringRemain(cleft);
log_ser(true,"Serial%d: BASE %3x, IRQ %d, initstring \"%s\"\r\n\r\n",
COMNUMBER,base,irq,cleft.c_str());
}
#endif #endif
fifosize=16;
errorfifo = new MyFifo(fifosize);
rxfifo = new MyFifo(fifosize);
txfifo = new MyFifo(fifosize);
idnumber=id;
mydosdevice=new device_COM(this); mydosdevice=new device_COM(this);
DOS_AddDevice(mydosdevice); DOS_AddDevice(mydosdevice);
Bit16u base = serial_baseaddr[id];
fifo_warn=false;
errormsg_pending=false; errormsg_pending=false;
framingErrors=0; framingErrors=0;
parityErrors=0; parityErrors=0;
overrunErrors=0; overrunErrors=0;
txOverrunErrors=0;
overrunIF0=0; overrunIF0=0;
breakErrors=0; breakErrors=0;
// find the IRQ
irq = serial_defaultirq[id];
getBituSubstring("irq:",&irq, cmd);
if (irq < 2 || irq > 15) irq = serial_defaultirq[id];
for (Bitu i = 0; i <= 7; i++) { for (Bitu i = 0; i <= 7; i++) {
WriteHandler[i].Install (i + base, SERIAL_Write, IO_MB); WriteHandler[i].Install (i + base, SERIAL_Write, IO_MB);
ReadHandler[i].Install (i + base, SERIAL_Read, IO_MB); ReadHandler[i].Install (i + base, SERIAL_Read, IO_MB);
} }
#if SERIAL_DEBUG
if(debugfp) fprintf(debugfp,"COM%d: BASE %3x, IRQ %d\r\n\r\n",
COMNUMBER,base,irq);
#endif
} }
bool CSerial::getBituSubstring(const char* name,Bitu* data, CommandLine* cmd) { bool CSerial::getBituSubstring(const char* name,Bitu* data, CommandLine* cmd) {
@ -1082,19 +1144,16 @@ CSerial::~CSerial(void) {
DOS_DelDevice(mydosdevice); DOS_DelDevice(mydosdevice);
for(Bitu i = 0; i <= SERIAL_BASE_EVENT_COUNT; i++) for(Bitu i = 0; i <= SERIAL_BASE_EVENT_COUNT; i++)
removeEvent(i); removeEvent(i);
} };
bool CSerial::Getchar(Bit8u* data, Bit8u* lsr, bool wait_dsr, Bitu timeout) { bool CSerial::Getchar(Bit8u* data, Bit8u* lsr, bool wait_dsr, Bitu timeout) {
double starttime=PIC_FullIndex(); double starttime=PIC_FullIndex();
// wait for it to become empty
// wait for DSR on // wait for DSR on
if(wait_dsr) { if(wait_dsr) {
while((!(Read_MSR()&0x20))&&(starttime>PIC_FullIndex()-timeout)) while((!(Read_MSR()&0x20))&&(starttime>PIC_FullIndex()-timeout))
CALLBACK_Idle(); CALLBACK_Idle();
if(!(starttime>PIC_FullIndex()-timeout)) { if(!(starttime>PIC_FullIndex()-timeout)) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_aux) log_ser(dbg_aux,"Getchar status timeout: MSR 0x%x",Read_MSR());
fprintf(debugfp,"%12.3f Getchar status timeout: MSR 0x%x\r\n", PIC_FullIndex(),Read_MSR());
#endif #endif
return false; return false;
} }
@ -1104,21 +1163,16 @@ if(dbg_aux)
CALLBACK_Idle(); CALLBACK_Idle();
if(!(starttime>PIC_FullIndex()-timeout)) { if(!(starttime>PIC_FullIndex()-timeout)) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_aux) log_ser(dbg_aux,"Getchar data timeout: MSR 0x%x",Read_MSR());
fprintf(debugfp,"%12.3f Getchar data timeout: MSR 0x%x\r\n", PIC_FullIndex(),Read_MSR());
#endif #endif
return false; return false;
} }
*data=Read_RHR(); *data=Read_RHR();
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_aux) log_ser(dbg_aux,"Getchar read 0x%x",*data);
fprintf(debugfp,"%12.3f API read success: 0x%x\r\n", PIC_FullIndex(),*data);
#endif #endif
return true; return true;
} }
@ -1126,9 +1180,8 @@ if(dbg_aux)
bool CSerial::Putchar(Bit8u data, bool wait_dsr, bool wait_cts, Bitu timeout) { bool CSerial::Putchar(Bit8u data, bool wait_dsr, bool wait_cts, Bitu timeout) {
double starttime=PIC_FullIndex(); double starttime=PIC_FullIndex();
//Bit16u starttime=
// wait for it to become empty // wait for it to become empty
while(!(LSR&0x20)) { while(!(Read_LSR()&0x20)) {
CALLBACK_Idle(); CALLBACK_Idle();
} }
// wait for DSR+CTS on // wait for DSR+CTS on
@ -1142,13 +1195,10 @@ bool CSerial::Putchar(Bit8u data, bool wait_dsr, bool wait_cts, Bitu timeout) {
} else if(wait_cts) { } else if(wait_cts) {
while(!(Read_MSR()&0x10)&&(starttime>PIC_FullIndex()-timeout)) while(!(Read_MSR()&0x10)&&(starttime>PIC_FullIndex()-timeout))
CALLBACK_Idle(); CALLBACK_Idle();
} }
if(!(starttime>PIC_FullIndex()-timeout)) { if(!(starttime>PIC_FullIndex()-timeout)) {
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_aux) log_ser(dbg_aux,"Putchar timeout: MSR 0x%x",Read_MSR());
fprintf(debugfp,"%12.3f Putchar timeout: MSR 0x%x\r\n",
PIC_FullIndex(),Read_MSR());
#endif #endif
return false; return false;
} }
@ -1156,8 +1206,7 @@ bool CSerial::Putchar(Bit8u data, bool wait_dsr, bool wait_cts, Bitu timeout) {
Write_THR(data); Write_THR(data);
#if SERIAL_DEBUG #if SERIAL_DEBUG
if(dbg_aux) log_ser(dbg_aux,"Putchar 0x%x",data);
fprintf(debugfp,"%12.3f API write success: 0x%x\r\n", PIC_FullIndex(),data);
#endif #endif
return true; return true;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: softmodem.cpp,v 1.11 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: softmodem.cpp,v 1.12 2009/10/04 20:57:40 h-a-l-9000 Exp $ */
#include "dosbox.h" #include "dosbox.h"
@ -77,17 +77,22 @@ CSerialModem::~CSerialModem() {
} }
void CSerialModem::handleUpperEvent(Bit16u type) { void CSerialModem::handleUpperEvent(Bit16u type) {
switch(type) switch (type) {
{ case SERIAL_RX_EVENT: {
case SERIAL_RX_EVENT: // check for bytes to be sent to port
{ if(CSerial::CanReceiveByte())
if(rqueue->inuse() && (CSerial::getRTS()||(flowcontrol!=3))) {
Bit8u rbyte = rqueue->getb();
//LOG_MSG("Modem: sending byte %2x back to UART3",rbyte);
CSerial::receiveByte(rbyte);
}
if(CSerial::CanReceiveByte()) setEvent(SERIAL_RX_EVENT, bytetime*0.98f);
break; break;
} }
case MODEM_TX_EVENT: case MODEM_TX_EVENT: {
{ if (tqueue->left()) {
if(tqueue->left()) {
tqueue->addb(waiting_tx_character); tqueue->addb(waiting_tx_character);
if(tqueue->left() < 2) { if (tqueue->left() < 2) {
CSerial::setCTS(false); CSerial::setCTS(false);
} }
} else { } else {
@ -98,18 +103,19 @@ void CSerialModem::handleUpperEvent(Bit16u type) {
} }
} }
ByteTransmitted(); ByteTransmitted();
break; break;
} }
case SERIAL_POLLING_EVENT: case SERIAL_POLLING_EVENT: {
{ if (rqueue->inuse()) {
removeEvent(SERIAL_RX_EVENT);
setEvent(SERIAL_RX_EVENT, (float)0.01);
}
Timer2(); Timer2();
setEvent(SERIAL_POLLING_EVENT,1); setEvent(SERIAL_POLLING_EVENT,1);
break; break;
} }
case MODEM_RING_EVENT: case MODEM_RING_EVENT: {
{
break; break;
} }
} }
@ -216,6 +222,12 @@ Bitu CSerialModem::ScanNumber(char * & scan) {
return ret; return ret;
} }
char CSerialModem::GetChar(char * & scan) {
char ch = *scan;
scan++;
return ch;
}
void CSerialModem::Reset(){ void CSerialModem::Reset(){
EnterIdleState(); EnterIdleState();
cmdpos = 0; cmdpos = 0;
@ -304,21 +316,19 @@ void CSerialModem::DoCommand() {
if (!cmdbuf[0]) { if (!cmdbuf[0]) {
reg[0]=0; // autoanswer off reg[0]=0; // autoanswer off
return; return;
// } }
//else { //else {
//MIXER_Enable(mhd.chan,false); //MIXER_Enable(mhd.chan,false);
// dialing = false; // dialing = false;
// SendRes(ResNOCARRIER); // SendRes(ResNOCARRIER);
// goto ret_none; // goto ret_none;
// } //}
}
/* AT command set interpretation */ /* AT command set interpretation */
if ((cmdbuf[0] != 'A') || (cmdbuf[1] != 'T')) { if ((cmdbuf[0] != 'A') || (cmdbuf[1] != 'T')) {
SendRes(ResERROR); SendRes(ResERROR);
return; return;
} }
if (strstr(cmdbuf,"NET0")) { if (strstr(cmdbuf,"NET0")) {
telnetmode = false; telnetmode = false;
SendRes(ResOK); SendRes(ResOK);
@ -330,14 +340,12 @@ void CSerialModem::DoCommand() {
return; return;
} }
char * scanbuf; char * scanbuf = &cmdbuf[2];
scanbuf=&cmdbuf[2]; while (1) {
char chr; // LOG_MSG("loopstart ->%s<-",scanbuf);
Bitu num; char chr = GetChar(scanbuf);
while (chr=*scanbuf++) {
switch (chr) { switch (chr) {
case 'D': // Dial case 'D': { // Dial
{
char * foundstr=&scanbuf[0]; char * foundstr=&scanbuf[0];
if (*foundstr=='T' || *foundstr=='P') foundstr++; if (*foundstr=='T' || *foundstr=='P') foundstr++;
// Small protection against empty line and long string // Small protection against empty line and long string
@ -359,8 +367,7 @@ void CSerialModem::DoCommand() {
// Check if supplied parameter only consists of digits // Check if supplied parameter only consists of digits
bool isNum = true; bool isNum = true;
for (Bitu i=0; i<strlen(foundstr); i++) for (Bitu i=0; i<strlen(foundstr); i++)
if (foundstr[i] < '0' || foundstr[i] > '9') if (foundstr[i] < '0' || foundstr[i] > '9') isNum = false;
isNum = false;
if (isNum) { if (isNum) {
// Parameter is a number with at least 12 digits => this cannot // Parameter is a number with at least 12 digits => this cannot
// be a valid IP/name // be a valid IP/name
@ -384,34 +391,37 @@ void CSerialModem::DoCommand() {
Dial(foundstr); Dial(foundstr);
return; return;
} }
case 'I': //Some strings about firmware case 'I': // Some strings about firmware
switch (num=ScanNumber(scanbuf)) { switch (ScanNumber(scanbuf)) {
case 3:SendLine("DosBox Emulated Modem Firmware V1.00");break; case 3: SendLine("DosBox Emulated Modem Firmware V1.00"); break;
case 4:SendLine("Modem compiled for DosBox version " VERSION);break; case 4: SendLine("Modem compiled for DosBox version " VERSION); break;
};break; }
case 'E': //Echo on/off break;
switch (num=ScanNumber(scanbuf)) { case 'E': // Echo on/off
case 0:echo = false;break; switch (ScanNumber(scanbuf)) {
case 1:echo = true;break; case 0: echo = false; break;
};break; case 1: echo = true; break;
}
break;
case 'V': case 'V':
switch (num=ScanNumber(scanbuf)) { switch (ScanNumber(scanbuf)) {
case 0:numericresponse = true;break; case 0: numericresponse = true; break;
case 1:numericresponse = false;break; case 1: numericresponse = false; break;
};break; }
case 'H': //Hang up break;
switch (num=ScanNumber(scanbuf)) { case 'H': // Hang up
switch (ScanNumber(scanbuf)) {
case 0: case 0:
if (connected) { if (connected) {
SendRes(ResNOCARRIER); SendRes(ResNOCARRIER);
EnterIdleState(); EnterIdleState();
return; return;
} }
//Else return ok // else return ok
};break; }
case 'O': //Return to data mode break;
switch (num=ScanNumber(scanbuf)) case 'O': // Return to data mode
{ switch (ScanNumber(scanbuf)) {
case 0: case 0:
if (clientsocket) { if (clientsocket) {
commandmode = false; commandmode = false;
@ -420,15 +430,16 @@ void CSerialModem::DoCommand() {
SendRes(ResERROR); SendRes(ResERROR);
return; return;
} }
};break; }
case 'T': //Tone Dial
case 'P': //Pulse Dial
break; break;
case 'M': //Monitor case 'T': // Tone Dial
case 'L': //Volume case 'P': // Pulse Dial
break;
case 'M': // Monitor
case 'L': // Volume
ScanNumber(scanbuf); ScanNumber(scanbuf);
break; break;
case 'A': //Answer call case 'A': // Answer call
if (waitingclientsocket) { if (waitingclientsocket) {
AcceptIncomingCall(); AcceptIncomingCall();
} else { } else {
@ -436,18 +447,18 @@ void CSerialModem::DoCommand() {
return; return;
} }
return; return;
case 'Z': //Reset and load profiles case 'Z': { // Reset and load profiles
{
// scan the number away, if any // scan the number away, if any
ScanNumber(scanbuf); ScanNumber(scanbuf);
if (clientsocket/*socket*/) SendRes(ResNOCARRIER); if (clientsocket) SendRes(ResNOCARRIER);
Reset(); Reset();
break; break;
} }
case ' ': //Space just skip case ' ': // skip space
break; break;
case 'Q': // Response options case 'Q': {
{ // 0 = all on, 1 = all off, // Response options
// 0 = all on, 1 = all off,
// 2 = no ring and no connect/carrier in answermode // 2 = no ring and no connect/carrier in answermode
Bitu val = ScanNumber(scanbuf); Bitu val = ScanNumber(scanbuf);
if(!(val>2)) { if(!(val>2)) {
@ -458,8 +469,7 @@ void CSerialModem::DoCommand() {
return; return;
} }
} }
case 'S': //Registers case 'S': { // Registers
{
Bitu index=ScanNumber(scanbuf); Bitu index=ScanNumber(scanbuf);
if(index>=SREGS) { if(index>=SREGS) {
SendRes(ResERROR); SendRes(ResERROR);
@ -483,14 +493,10 @@ void CSerialModem::DoCommand() {
//else LOG_MSG("print reg %d with %d",index,reg[index]); //else LOG_MSG("print reg %d with %d",index,reg[index]);
} }
break; break;
case '&': case '&': { // & escaped commands
{ char cmdchar = GetChar(scanbuf);
if(scanbuf[0]!=0) { switch(cmdchar) {
char ch = scanbuf[0]; case 'K': {
scanbuf++;
switch(ch) {
case 'K':
{
Bitu val = ScanNumber(scanbuf); Bitu val = ScanNumber(scanbuf);
if(val<5) flowcontrol=val; if(val<5) flowcontrol=val;
else { else {
@ -499,28 +505,45 @@ void CSerialModem::DoCommand() {
} }
break; break;
} }
case '\0':
// end of string
SendRes(ResERROR);
return;
default: default:
{ LOG_MSG("Modem: Unhandled command: &%c%d",cmdchar,ScanNumber(scanbuf));
scanbuf++;
LOG_MSG("Modem: Unhandled command: &%c%d",ch,ScanNumber(scanbuf));
break; break;
} }
break;
} }
} else { case '\\': { // \ escaped commands
char cmdchar = GetChar(scanbuf);
switch(cmdchar) {
case 'N':
// error correction stuff - not emulated
if (ScanNumber(scanbuf) > 5) {
SendRes(ResERROR); SendRes(ResERROR);
return; return;
} }
break;
case '\0':
// end of string
SendRes(ResERROR);
return;
default:
LOG_MSG("Modem: Unhandled command: \\%c%d",cmdchar, ScanNumber(scanbuf));
break;
} }
break; break;
default:
LOG_MSG("Modem: Unhandled command: %c%d",chr,ScanNumber(scanbuf));
} }
} case '\0':
SendRes(ResOK); SendRes(ResOK);
return; return;
default:
LOG_MSG("Modem: Unhandled command: %c%d",chr,ScanNumber(scanbuf));
break;
} }
}
}
void CSerialModem::TelnetEmulation(Bit8u * data, Bitu size) { void CSerialModem::TelnetEmulation(Bit8u * data, Bitu size) {
Bitu i; Bitu i;
@ -631,13 +654,6 @@ void CSerialModem::Timer2(void) {
Bit8u txval; Bit8u txval;
Bitu txbuffersize =0; Bitu txbuffersize =0;
// check for bytes to be sent to port
if(CSerial::CanReceiveByte())
if(rqueue->inuse() && (CSerial::getRTS()||(flowcontrol!=3))) {
Bit8u rbyte = rqueue->getb();
//LOG_MSG("Modem: sending byte %2x back to UART3",rbyte);
CSerial::receiveByte(rbyte);
}
// Check for eventual break command // Check for eventual break command
if (!commandmode) cmdpause++; if (!commandmode) cmdpause++;
// Handle incoming data from serial port, read as much as available // Handle incoming data from serial port, read as much as available
@ -684,8 +700,10 @@ void CSerialModem::Timer2(void) {
if (clientsocket && sendbyte && txbuffersize) { if (clientsocket && sendbyte && txbuffersize) {
// down here it saves a lot of network traffic // down here it saves a lot of network traffic
clientsocket->SendArray(tmpbuf,txbuffersize); if(!clientsocket->SendArray(tmpbuf,txbuffersize)) {
//TODO error testing SendRes(ResNOCARRIER);
EnterIdleState();
}
} }
// Handle incoming to the serial port // Handle incoming to the serial port
if(!commandmode && clientsocket && rqueue->left()) { if(!commandmode && clientsocket && rqueue->left()) {
@ -695,7 +713,6 @@ void CSerialModem::Timer2(void) {
SendRes(ResNOCARRIER); SendRes(ResNOCARRIER);
EnterIdleState(); EnterIdleState();
} else if(usesize) { } else if(usesize) {
// LOG_MSG("rcv:%d", result);
// Filter telnet commands // Filter telnet commands
if(telnetmode) TelnetEmulation(tmpbuf, usesize); if(telnetmode) TelnetEmulation(tmpbuf, usesize);
else rqueue->adds(tmpbuf,usesize); else rqueue->adds(tmpbuf,usesize);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: softmodem.h,v 1.10 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: softmodem.h,v 1.12 2009/10/04 20:57:40 h-a-l-9000 Exp $ */
#ifndef DOSBOX_SERIALMODEM_H #ifndef DOSBOX_SERIALMODEM_H
#define DOSBOX_SERIALMODEM_H #define DOSBOX_SERIALMODEM_H
@ -92,7 +92,7 @@ public:
static Bits lcount=0; static Bits lcount=0;
if (lcount<1000) { if (lcount<1000) {
lcount++; lcount++;
LOG_MSG("MODEM: FIFO Overflow! (adds len %d)",_len); LOG_MSG("MODEM: FIFO Overflow! (adds len %u)",_len);
} }
return; return;
} }
@ -102,7 +102,7 @@ public:
used+=_len; used+=_len;
while (_len--) { while (_len--) {
if (where>=size) where-=size; if (where>=size) where-=size;
//LOG_MSG("+%x",*_str); //LOG_MSG("+'%x'",*_str);
data[where++]=*_str++; data[where++]=*_str++;
} }
} }
@ -172,6 +172,7 @@ public:
bool Dial(char * host); bool Dial(char * host);
void AcceptIncomingCall(void); void AcceptIncomingCall(void);
Bitu ScanNumber(char * & scan); Bitu ScanNumber(char * & scan);
char GetChar(char * & scan);
void DoCommand(); void DoCommand();

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: vga_draw.cpp,v 1.109 2009/06/29 18:43:33 c2woody Exp $ */ /* $Id: vga_draw.cpp,v 1.111 2009/09/10 17:44:57 h-a-l-9000 Exp $ */
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
@ -344,11 +344,24 @@ static Bit8u * VGA_Draw_LIN32_Line_HWMouse(Bitu vidstart, Bitu /*line*/) {
} }
} }
static const Bit8u* VGA_Text_Memwrap(Bitu vidstart) {
vidstart &= vga.draw.linear_mask;
Bitu line_end = 2 * vga.draw.blocks;
if (GCC_UNLIKELY((vidstart + line_end) > vga.draw.linear_mask)) {
// wrapping in this line
Bitu break_pos = (vga.draw.linear_mask - vidstart) + 1;
// need a temporary storage - TempLine/2 is ok for a bit more than 132 columns
memcpy(&TempLine[sizeof(TempLine)/2], &vga.tandy.draw_base[vidstart], break_pos);
memcpy(&TempLine[sizeof(TempLine)/2 + break_pos],&vga.tandy.draw_base[0], line_end - break_pos);
return &TempLine[sizeof(TempLine)/2];
} else return &vga.tandy.draw_base[vidstart];
}
static Bit32u FontMask[2]={0xffffffff,0x0}; static Bit32u FontMask[2]={0xffffffff,0x0};
static Bit8u * VGA_TEXT_Draw_Line(Bitu vidstart, Bitu line) { static Bit8u * VGA_TEXT_Draw_Line(Bitu vidstart, Bitu line) {
Bits font_addr; Bits font_addr;
Bit32u * draw=(Bit32u *)TempLine; Bit32u * draw=(Bit32u *)TempLine;
const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; const Bit8u* vidmem = VGA_Text_Memwrap(vidstart);
for (Bitu cx=0;cx<vga.draw.blocks;cx++) { for (Bitu cx=0;cx<vga.draw.blocks;cx++) {
Bitu chr=vidmem[cx*2]; Bitu chr=vidmem[cx*2];
Bitu col=vidmem[cx*2+1]; Bitu col=vidmem[cx*2+1];
@ -376,7 +389,7 @@ skip_cursor:
static Bit8u * VGA_TEXT_Herc_Draw_Line(Bitu vidstart, Bitu line) { static Bit8u * VGA_TEXT_Herc_Draw_Line(Bitu vidstart, Bitu line) {
Bits font_addr; Bits font_addr;
Bit32u * draw=(Bit32u *)TempLine; Bit32u * draw=(Bit32u *)TempLine;
const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; const Bit8u* vidmem = VGA_Text_Memwrap(vidstart);
for (Bitu cx=0;cx<vga.draw.blocks;cx++) { for (Bitu cx=0;cx<vga.draw.blocks;cx++) {
Bitu chr=vidmem[cx*2]; Bitu chr=vidmem[cx*2];
@ -415,8 +428,16 @@ static Bit8u * VGA_TEXT_Herc_Draw_Line(Bitu vidstart, Bitu line) {
if (line<vga.draw.cursor.sline) goto skip_cursor; if (line<vga.draw.cursor.sline) goto skip_cursor;
if (line>vga.draw.cursor.eline) goto skip_cursor; if (line>vga.draw.cursor.eline) goto skip_cursor;
draw=(Bit32u *)&TempLine[font_addr*8]; draw=(Bit32u *)&TempLine[font_addr*8];
Bit32u att=TXT_FG_Table[vga.tandy.draw_base[vga.draw.cursor.address+1]&0xf]; Bit8u attr = vga.tandy.draw_base[vga.draw.cursor.address+1];
*draw++=att;*draw++=att; Bit32u cg;
if (attr&0x8) {
cg = TXT_FG_Table[0xf];
} else if ((attr&0x77)==0x70) {
cg = TXT_FG_Table[0x0];
} else {
cg = TXT_FG_Table[0x7];
}
*draw++=cg;*draw++=cg;
} }
skip_cursor: skip_cursor:
return TempLine; return TempLine;
@ -425,7 +446,7 @@ skip_cursor:
static Bit8u * VGA_TEXT_Xlat16_Draw_Line(Bitu vidstart, Bitu line) { static Bit8u * VGA_TEXT_Xlat16_Draw_Line(Bitu vidstart, Bitu line) {
Bits font_addr; Bits font_addr;
Bit16u * draw=(Bit16u *)TempLine; Bit16u * draw=(Bit16u *)TempLine;
const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; const Bit8u* vidmem = VGA_Text_Memwrap(vidstart);
for (Bitu cx=0;cx<vga.draw.blocks;cx++) { for (Bitu cx=0;cx<vga.draw.blocks;cx++) {
Bitu chr=vidmem[cx*2]; Bitu chr=vidmem[cx*2];
Bitu col=vidmem[cx*2+1]; Bitu col=vidmem[cx*2+1];
@ -467,7 +488,7 @@ static Bit8u * VGA_TEXT_Draw_Line_9(Bitu vidstart, Bitu line) {
bool underline=(Bitu)(vga.crtc.underline_location&0x1f)==line; bool underline=(Bitu)(vga.crtc.underline_location&0x1f)==line;
Bit8u pel_pan=(Bit8u)vga.draw.panning; Bit8u pel_pan=(Bit8u)vga.draw.panning;
if ((vga.attr.mode_control&0x20) && (vga.draw.lines_done>=vga.draw.split_line)) pel_pan=0; if ((vga.attr.mode_control&0x20) && (vga.draw.lines_done>=vga.draw.split_line)) pel_pan=0;
const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; const Bit8u* vidmem = VGA_Text_Memwrap(vidstart);
Bit8u chr=vidmem[0]; Bit8u chr=vidmem[0];
Bit8u col=vidmem[1]; Bit8u col=vidmem[1];
Bit8u font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<<pel_pan; Bit8u font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<<pel_pan;
@ -526,7 +547,7 @@ static Bit8u * VGA_TEXT_Xlat16_Draw_Line_9(Bitu vidstart, Bitu line) {
bool underline=(Bitu)(vga.crtc.underline_location&0x1f)==line; bool underline=(Bitu)(vga.crtc.underline_location&0x1f)==line;
Bit8u pel_pan=(Bit8u)vga.draw.panning; Bit8u pel_pan=(Bit8u)vga.draw.panning;
if ((vga.attr.mode_control&0x20) && (vga.draw.lines_done>=vga.draw.split_line)) pel_pan=0; if ((vga.attr.mode_control&0x20) && (vga.draw.lines_done>=vga.draw.split_line)) pel_pan=0;
const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; const Bit8u* vidmem = VGA_Text_Memwrap(vidstart);
Bit8u chr=vidmem[0]; Bit8u chr=vidmem[0];
Bit8u col=vidmem[1]; Bit8u col=vidmem[1];
Bit8u font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<<pel_pan; Bit8u font=(vga.draw.font_tables[(col >> 3)&1][chr*32+line])<<pel_pan;
@ -809,14 +830,16 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
#endif #endif
break; break;
case M_TEXT: case M_TEXT:
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) vga.draw.byte_panning_shift = 2; vga.draw.byte_panning_shift = 2;
else vga.draw.byte_panning_shift = 0; vga.draw.address += vga.draw.bytes_skip;
if ((IS_VGA_ARCH) && (svgaCard==SVGA_None)) vga.draw.address = vga.config.real_start * 2; // fall-through
else vga.draw.address = vga.config.display_start * 2;
vga.draw.address += vga.draw.bytes_skip*vga.draw.byte_panning_shift;
case M_TANDY_TEXT: case M_TANDY_TEXT:
case M_HERC_TEXT: case M_HERC_TEXT:
if (machine==MCH_HERC) vga.draw.linear_mask = 0xfff; // 1 page
else if (IS_EGAVGA_ARCH) vga.draw.linear_mask = 0x7fff; // 8 pages
else vga.draw.linear_mask = 0x3fff; // CGA, Tandy 4 pages
vga.draw.cursor.address=vga.config.cursor_start*2; vga.draw.cursor.address=vga.config.cursor_start*2;
vga.draw.address *= 2;
vga.draw.cursor.count++; vga.draw.cursor.count++;
/* check for blinking and blinking change delay */ /* check for blinking and blinking change delay */
FontMask[1]=(vga.draw.blinking & (vga.draw.cursor.count >> 4)) ? FontMask[1]=(vga.draw.blinking & (vga.draw.cursor.count >> 4)) ?

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: vga_memory.cpp,v 1.52 2009/03/22 21:04:41 c2woody Exp $ */ /* $Id: vga_memory.cpp,v 1.53 2009/07/04 21:23:35 qbix79 Exp $ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -114,6 +114,7 @@ INLINE static Bit32u ModeOperation(Bit8u val) {
break; break;
case 0x03: case 0x03:
// Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory. // Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
val=((val >> vga.config.data_rotate) | (val << (8-vga.config.data_rotate)));
full=RasterOp(vga.config.full_set_reset,ExpandTable[val] & vga.config.full_bit_mask); full=RasterOp(vga.config.full_set_reset,ExpandTable[val] & vga.config.full_bit_mask);
break; break;
default: default:

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: vga_other.cpp,v 1.27 2009/06/29 18:43:33 c2woody Exp $ */ /* $Id: vga_other.cpp,v 1.28 2009/07/11 10:25:24 c2woody Exp $ */
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
@ -68,6 +68,7 @@ static void write_crtc_data_other(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
vga.other.vsyncp=(Bit8u)val; vga.other.vsyncp=(Bit8u)val;
break; break;
case 0x09: //Max scanline case 0x09: //Max scanline
val &= 0x1f; // VGADOC says bit 0-3 but the MC6845 datasheet says bit 0-4
if (vga.other.max_scanline ^ val) VGA_StartResize(); if (vga.other.max_scanline ^ val) VGA_StartResize();
vga.other.max_scanline=(Bit8u)val; vga.other.max_scanline=(Bit8u)val;
break; break;
@ -522,6 +523,7 @@ void VGA_SetupOther(void) {
Bitu i; Bitu i;
memset( &vga.tandy, 0, sizeof( vga.tandy )); memset( &vga.tandy, 0, sizeof( vga.tandy ));
vga.attr.enabled = true; vga.attr.enabled = true;
vga.config.bytes_skip=0;
//Initialize values common for most machines, can be overwritten //Initialize values common for most machines, can be overwritten
vga.tandy.draw_base = vga.mem.linear; vga.tandy.draw_base = vga.mem.linear;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: bios_disk.cpp,v 1.38 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: bios_disk.cpp,v 1.40 2009/08/23 17:24:54 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
#include "callback.h" #include "callback.h"
@ -196,7 +196,7 @@ imageDisk::imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHard
active = false; active = false;
hardDrive = isHardDisk; hardDrive = isHardDisk;
if(!isHardDisk) { if(!isHardDisk) {
Bitu i=0; Bit8u i=0;
bool founddisk = false; bool founddisk = false;
while (DiskGeometryList[i].ksize!=0x0) { while (DiskGeometryList[i].ksize!=0x0) {
if ((DiskGeometryList[i].ksize==imgSizeK) || if ((DiskGeometryList[i].ksize==imgSizeK) ||
@ -309,6 +309,9 @@ static Bitu INT13_DiskHandler(void) {
if(imageDiskList[i]) any_images=true; if(imageDiskList[i]) any_images=true;
} }
// unconditionally enable the interrupt flag
CALLBACK_SIF(true);
//drivenum = 0; //drivenum = 0;
//LOG_MSG("INT13: Function %x called on drive %x (dos drive %d)", reg_ah, reg_dl, drivenum); //LOG_MSG("INT13: Function %x called on drive %x (dos drive %d)", reg_ah, reg_dl, drivenum);
switch(reg_ah) { switch(reg_ah) {
@ -349,12 +352,15 @@ static Bitu INT13_DiskHandler(void) {
CALLBACK_SCF(true); CALLBACK_SCF(true);
return CBRET_NONE; return CBRET_NONE;
} }
if(!any_images && (reg_dh == 0)) { // Inherit the Earth cdrom (uses it as disk test) if (!any_images) {
// Inherit the Earth cdrom (uses it as disk test)
if (((reg_dl&0x80)==0x80) && (reg_dh==0) && ((reg_cl&0x3f)==1)) {
reg_ah = 0; reg_ah = 0;
CALLBACK_SCF(false); CALLBACK_SCF(false);
return CBRET_NONE; return CBRET_NONE;
} }
if(driveInactive(drivenum)) { }
if (driveInactive(drivenum)) {
reg_ah = 0xff; reg_ah = 0xff;
CALLBACK_SCF(true); CALLBACK_SCF(true);
return CBRET_NONE; return CBRET_NONE;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: int10.cpp,v 1.55 2009/04/11 07:58:39 qbix79 Exp $ */ /* $Id: int10.cpp,v 1.56 2009/09/06 19:25:34 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
#include "mem.h" #include "mem.h"
@ -329,11 +329,42 @@ graphics_chars:
case 0x20: /* Set alternate printscreen */ case 0x20: /* Set alternate printscreen */
break; break;
case 0x30: /* Select vertical resolution */ case 0x30: /* Select vertical resolution */
{
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_WARN)("Function 12:Call %2X (select vertical resolution)",reg_bl);
if (reg_al>2) reg_al=0; //invalid subfunction if (svgaCard != SVGA_None) {
else reg_al=0x12; //fake a success call if (reg_al > 2) {
reg_al=0; // invalid subfunction
break; break;
}
}
Bit8u modeset_ctl = real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
Bit8u video_switches = real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES)&0xf0;
switch(reg_al) {
case 0: // 200
modeset_ctl &= 0xef;
modeset_ctl |= 0x80;
video_switches |= 8; // ega normal/cga emulation
break;
case 1: // 350
modeset_ctl &= 0x6f;
video_switches |= 9; // ega enhanced
break;
case 2: // 400
modeset_ctl &= 0x6f;
modeset_ctl |= 0x10; // use 400-line mode at next mode set
video_switches |= 9; // ega enhanced
break;
default:
modeset_ctl &= 0xef;
video_switches |= 8; // ega normal/cga emulation
break;
}
real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset_ctl);
real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,video_switches);
reg_al=0x12; // success
break;
}
case 0x31: /* Palette loading on modeset */ case 0x31: /* Palette loading on modeset */
{ {
if (!IS_VGA_ARCH) break; if (!IS_VGA_ARCH) break;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: int10.h,v 1.39 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: int10.h,v 1.42 2009/09/06 19:25:34 c2woody Exp $ */
#include "vga.h" #include "vga.h"
@ -95,14 +95,14 @@
#define VGAMEM_MTEXT 0xB000 #define VGAMEM_MTEXT 0xB000
#define BIOS_NCOLS Bit16u ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); #define BIOS_NCOLS Bit16u ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
#define BIOS_NROWS Bit16u nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; #define BIOS_NROWS Bit16u nrows=(Bit16u)real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
extern Bit8u int10_font_08[256 * 8]; extern Bit8u int10_font_08[256 * 8];
extern Bit8u int10_font_14[256 * 14]; extern Bit8u int10_font_14[256 * 14];
extern Bit8u int10_font_16[256 * 16]; extern Bit8u int10_font_16[256 * 16];
struct VideoModeBlock { struct VideoModeBlock {
Bitu mode; Bit16u mode;
VGAModes type; VGAModes type;
Bitu swidth, sheight; Bitu swidth, sheight;
Bitu twidth, theight; Bitu twidth, theight;
@ -137,9 +137,9 @@ typedef struct {
Bit16u pmode_interface_start; Bit16u pmode_interface_start;
Bit16u pmode_interface_window; Bit16u pmode_interface_window;
Bit16u pmode_interface_palette; Bit16u pmode_interface_palette;
Bitu used; Bit16u used;
} rom; } rom;
Bitu vesa_setmode; Bit16u vesa_setmode;
bool vesa_nolfb; bool vesa_nolfb;
bool vesa_oldvbe; bool vesa_oldvbe;
} Int10Data; } Int10Data;
@ -154,7 +154,7 @@ static Bit8u CURSOR_POS_ROW(Bit8u page) {
return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2+1); return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2+1);
} }
bool INT10_SetVideoMode(Bitu mode); bool INT10_SetVideoMode(Bit16u mode);
void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page); void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page);
@ -175,6 +175,7 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color);
/* Font Stuff */ /* Font Stuff */
void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu height); void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu height);
void INT10_ReloadFont(void);
/* Palette Group */ /* Palette Group */
void INT10_SetBackgroundBorder(Bit8u val); void INT10_SetBackgroundBorder(Bit8u val);
@ -230,4 +231,5 @@ bool INT10_VideoState_Save(Bitu state,RealPt buffer);
bool INT10_VideoState_Restore(Bitu state,RealPt buffer); bool INT10_VideoState_Restore(Bitu state,RealPt buffer);
/* Video Parameter Tables */ /* Video Parameter Tables */
Bitu INT10_SetupVideoParameterTable(PhysPt basepos); Bit16u INT10_SetupVideoParameterTable(PhysPt basepos);
void INT10_SetupBasicVideoParameterTable(void);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: int10_char.cpp,v 1.58 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: int10_char.cpp,v 1.59 2009/07/11 10:25:25 c2woody Exp $ */
/* Character displaying moving functions */ /* Character displaying moving functions */
@ -272,12 +272,19 @@ filling:
void INT10_SetActivePage(Bit8u page) { void INT10_SetActivePage(Bit8u page) {
Bit16u mem_address; Bit16u mem_address;
if (page>7) LOG(LOG_INT10,LOG_ERROR)("INT10_SetActivePage page %d",page); if (page>7) LOG(LOG_INT10,LOG_ERROR)("INT10_SetActivePage page %d",page);
if (IS_EGAVGA_ARCH && (svgaCard==SVGA_S3Trio)) page &= 7;
mem_address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); mem_address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE);
/* Write the new page start */ /* Write the new page start */
real_writew(BIOSMEM_SEG,BIOSMEM_CURRENT_START,mem_address); real_writew(BIOSMEM_SEG,BIOSMEM_CURRENT_START,mem_address);
if (IS_EGAVGA_ARCH && CurMode->mode<0x8) mem_address>>=1; if (IS_EGAVGA_ARCH) {
if (CurMode->mode<8) mem_address>>=1;
// rare alternative: if (CurMode->type==M_TEXT) mem_address>>=1;
} else {
mem_address>>=1;
}
/* Write the new start address in vgahardware */ /* Write the new start address in vgahardware */
Bit16u base=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); Bit16u base=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
IO_Write(base,0x0c); IO_Write(base,0x0c);
@ -587,7 +594,7 @@ static void INT10_TeletypeOutputAttr(Bit8u chr,Bit8u attr,bool useattr,Bit8u pag
if(cur_row==nrows) { if(cur_row==nrows) {
//Fill with black on non-text modes and with 0x7 on textmode //Fill with black on non-text modes and with 0x7 on textmode
Bit8u fill = (CurMode->type == M_TEXT)?0x7:0; Bit8u fill = (CurMode->type == M_TEXT)?0x7:0;
INT10_ScrollWindow(0,0,nrows-1,ncols-1,-1,fill,page); INT10_ScrollWindow(0,0,(Bit8u)(nrows-1),ncols-1,-1,fill,page);
cur_row--; cur_row--;
} }
// Set the cursor for the page // Set the cursor for the page

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: int10_memory.cpp,v 1.28 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: int10_memory.cpp,v 1.30 2009/09/06 19:25:34 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
#include "mem.h" #include "mem.h"
@ -47,7 +47,7 @@ static Bit16u map_offset[8]={
}; };
void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu height) { void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu height) {
PhysPt ftwhere=PhysMake(0xa000,map_offset[map & 0x7]+offset*32); 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 adressing
@ -58,7 +58,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,old_6); //odd/even and b8000 adressing if (IS_VGA_ARCH) IO_Write(0x3cf,(Bit8u)old_6); //odd/even and b8000 adressing
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) {
@ -69,11 +69,26 @@ void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu
//Vertical display end bios says, but should stay the same? //Vertical display end bios says, but should stay the same?
//Rows setting in bios segment //Rows setting in bios segment
real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,(CurMode->sheight/height)-1); real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,(CurMode->sheight/height)-1);
real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,height); real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,(Bit8u)height);
//TODO Reprogram cursor size? //TODO Reprogram cursor size?
} }
} }
void INT10_ReloadFont(void) {
switch(CurMode->cheight) {
case 8:
INT10_LoadFont(Real2Phys(int10.rom.font_8_first),true,256,0,0,8);
break;
case 14:
INT10_LoadFont(Real2Phys(int10.rom.font_14),true,256,0,0,14);
break;
case 16:
default:
INT10_LoadFont(Real2Phys(int10.rom.font_16),true,256,0,0,16);
break;
}
}
void INT10_SetupRomMemory(void) { void INT10_SetupRomMemory(void) {
/* This should fill up certain structures inside the Video Bios Rom Area */ /* This should fill up certain structures inside the Video Bios Rom Area */
@ -181,6 +196,8 @@ void INT10_SetupRomMemory(void) {
phys_writed(rom_base+int10.rom.used,0); int10.rom.used+=4; phys_writed(rom_base+int10.rom.used,0); int10.rom.used+=4;
} }
INT10_SetupBasicVideoParameterTable();
if (IS_TANDY_ARCH) { if (IS_TANDY_ARCH) {
RealSetVec(0x44,int10.rom.font_8_first); RealSetVec(0x44,int10.rom.font_8_first);
} }
@ -216,7 +233,7 @@ void INT10_SetupRomMemoryChecksum(void) {
Bitu last_rombyte = 32*1024 - 1; //32 KB romsize Bitu last_rombyte = 32*1024 - 1; //32 KB romsize
for (Bitu i = 0;i < last_rombyte;i++) for (Bitu i = 0;i < last_rombyte;i++)
sum += phys_readb(rom_base + i); //OVERFLOW IS OKAY sum += phys_readb(rom_base + i); //OVERFLOW IS OKAY
sum = 256 - sum; sum = (Bit8u)((256 - (Bitu)sum)&0xff);
phys_writeb(rom_base + last_rombyte,sum); phys_writeb(rom_base + last_rombyte,sum);
} }
} }

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: int10_modes.cpp,v 1.86 2009/06/28 14:56:14 c2woody Exp $ */ /* $Id: int10_modes.cpp,v 1.90 2009/09/06 19:25:34 c2woody Exp $ */
#include <string.h> #include <string.h>
@ -124,6 +124,22 @@ VideoModeBlock ModeList_VGA[]={
{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, {0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
}; };
VideoModeBlock ModeList_VGA_Text_200lines[]={
/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
{ 0x000 ,M_TEXT ,320 ,200 ,40 ,25 ,8 , 8 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
{ 0x001 ,M_TEXT ,320 ,200 ,40 ,25 ,8 , 8 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
{ 0x002 ,M_TEXT ,640 ,200 ,80 ,25 ,8 , 8 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE },
{ 0x003 ,M_TEXT ,640 ,200 ,80 ,25 ,8 , 8 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE }
};
VideoModeBlock ModeList_VGA_Text_350lines[]={
/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
{ 0x000 ,M_TEXT ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,350 ,_EGA_HALF_CLOCK },
{ 0x001 ,M_TEXT ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,350 ,_EGA_HALF_CLOCK },
{ 0x002 ,M_TEXT ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,350 ,0 },
{ 0x003 ,M_TEXT ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,350 ,0 }
};
VideoModeBlock ModeList_VGA_Tseng[]={ VideoModeBlock ModeList_VGA_Tseng[]={
/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */ /* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
{ 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK }, { 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
@ -232,7 +248,7 @@ VideoModeBlock ModeList_OTHER[]={
}; };
VideoModeBlock Hercules_Mode= VideoModeBlock Hercules_Mode=
{ 0x007 ,M_TEXT ,640 ,400 ,80 ,25 ,8 ,14 ,4 ,0xB0000 ,0x1000 ,97 ,25 ,80 ,25 ,0 }; { 0x007 ,M_TEXT ,640 ,400 ,80 ,25 ,8 ,14 ,1 ,0xB0000 ,0x1000 ,97 ,25 ,80 ,25 ,0 };
static Bit8u text_palette[64][3]= static Bit8u text_palette[64][3]=
{ {
@ -340,7 +356,7 @@ static Bit8u vga_palette[256][3]=
}; };
VideoModeBlock * CurMode; VideoModeBlock * CurMode;
static bool SetCurMode(VideoModeBlock modeblock[],Bitu mode) { static bool SetCurMode(VideoModeBlock modeblock[],Bit16u mode) {
Bitu i=0; Bitu i=0;
while (modeblock[i].mode!=0xffff) { while (modeblock[i].mode!=0xffff) {
if (modeblock[i].mode!=mode) i++; if (modeblock[i].mode!=mode) i++;
@ -394,7 +410,6 @@ static void FinishSetMode(bool clearmem) {
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,(Bit16u)CurMode->cheight); real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,(Bit16u)CurMode->cheight);
real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem?0:0x80))); real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem?0:0x80)));
real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09); real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09);
real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
// this is an index into the dcc table: // this is an index into the dcc table:
if (IS_VGA_ARCH) real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x0b); if (IS_VGA_ARCH) real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x0b);
@ -418,7 +433,7 @@ static void FinishSetMode(bool clearmem) {
Mouse_NewVideoMode(); Mouse_NewVideoMode();
} }
bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) { bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) {
switch (machine) { switch (machine) {
case MCH_CGA: case MCH_CGA:
if (mode>6) return false; if (mode>6) return false;
@ -569,12 +584,44 @@ bool INT10_SetVideoMode_OTHER(Bitu mode,bool clearmem) {
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select); real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
break; break;
} }
RealPt vparams = RealGetVec(0x1d);
if ((vparams != RealMake(0xf000,0xf0a4)) && (mode < 8)) {
// load crtc parameters from video params table
Bit16u crtc_block_index = 0;
if (mode < 2) crtc_block_index = 0;
else if (mode < 4) crtc_block_index = 1;
else if (mode < 7) crtc_block_index = 2;
else {
if (machine==MCH_PCJR) {
if (mode < 9) crtc_block_index = 2;
else crtc_block_index = 3;
} else {
if (mode == 7) crtc_block_index = 3;
}
}
// init CRTC registers
for (Bit16u i = 0; i < 16; i++)
IO_WriteW(crtc_base, i | (real_readb(RealSeg(vparams),
RealOff(vparams) + i + crtc_block_index*16) << 8));
if (machine==MCH_CGA) {
// mode register
IO_WriteB(crtc_base + 4, real_readb(RealSeg(vparams),
RealOff(vparams) + 4*16 + 24 + mode));
}
if (machine==MCH_TANDY) {
E_Exit("INT10 modeset: video parameter table changed");
}
}
FinishSetMode(clearmem); FinishSetMode(clearmem);
return true; return true;
} }
bool INT10_SetVideoMode(Bitu mode) { bool INT10_SetVideoMode(Bit16u mode) {
bool clearmem=true;Bitu i; bool clearmem=true;Bitu i;
if (mode>=0x100) { if (mode>=0x100) {
if ((mode & 0x4000) && int10.vesa_nolfb) return false; if ((mode & 0x4000) && int10.vesa_nolfb) return false;
@ -588,7 +635,11 @@ bool INT10_SetVideoMode(Bitu mode) {
int10.vesa_setmode=0xffff; int10.vesa_setmode=0xffff;
LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode); LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
if (!IS_EGAVGA_ARCH) return INT10_SetVideoMode_OTHER(mode,clearmem); if (!IS_EGAVGA_ARCH) return INT10_SetVideoMode_OTHER(mode,clearmem);
Bit8u modeset_ctl,video_ctl,vga_switches;
/* First read mode setup settings from bios area */
// Bit8u video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
// Bit8u vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES);
Bit8u modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
if (IS_VGA_ARCH) { if (IS_VGA_ARCH) {
if (svga.accepts_mode) { if (svga.accepts_mode) {
@ -615,6 +666,18 @@ bool INT10_SetVideoMode(Bitu mode) {
return false; return false;
} }
} }
// check for scanline backwards compatibility (VESA text modes??)
if (CurMode->type==M_TEXT) {
if ((modeset_ctl&0x90)==0x80) { // 200 lines emulation
if (CurMode->mode <= 3) {
CurMode = &ModeList_VGA_Text_200lines[CurMode->mode];
}
} else if ((modeset_ctl&0x90)==0x00) { // 350 lines emulation
if (CurMode->mode <= 3) {
CurMode = &ModeList_VGA_Text_350lines[CurMode->mode];
}
}
}
} else { } else {
if (!SetCurMode(ModeList_EGA,mode)){ if (!SetCurMode(ModeList_EGA,mode)){
LOG(LOG_INT10,LOG_ERROR)("EGA:Trying to set illegal mode %X",mode); LOG(LOG_INT10,LOG_ERROR)("EGA:Trying to set illegal mode %X",mode);
@ -622,11 +685,6 @@ bool INT10_SetVideoMode(Bitu mode) {
} }
} }
/* First read mode setup settings from bios area */
video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES);
modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
/* Setup the VGA to the correct mode */ /* Setup the VGA to the correct mode */
Bit16u crtc_base; Bit16u crtc_base;
@ -643,11 +701,14 @@ bool INT10_SetVideoMode(Bitu mode) {
/* Setup MISC Output Register */ /* Setup MISC Output Register */
Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1); Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1);
if ((CurMode->type==M_TEXT) && (CurMode->cwidth==9)) {
// 28MHz (16MHz EGA) clock for 9-pixel wide chars
misc_output|=0x4;
}
switch (CurMode->vdispend) { switch (CurMode->vdispend) {
case 400: case 400:
misc_output|=0x60; misc_output|=0x60;
if (CurMode->type==M_TEXT) // && (CurMode->pstart==0xB8000))
misc_output|=0x4;
break; break;
case 480: case 480:
misc_output|=0xe0; misc_output|=0xe0;
@ -663,12 +724,13 @@ bool INT10_SetVideoMode(Bitu mode) {
/* Program Sequencer */ /* Program Sequencer */
Bit8u seq_data[SEQ_REGS]; Bit8u seq_data[SEQ_REGS];
memset(seq_data,0,SEQ_REGS); memset(seq_data,0,SEQ_REGS);
if (CurMode->cwidth==8) seq_data[1]|=1; //8 dot fonts by default seq_data[1]|=0x01; //8 dot fonts by default
if (CurMode->special & _EGA_HALF_CLOCK) seq_data[1]|=0x08; //Check for half clock if (CurMode->special & _EGA_HALF_CLOCK) seq_data[1]|=0x08; //Check for half clock
if ((machine==MCH_EGA) && (CurMode->special & _EGA_HALF_CLOCK)) seq_data[1]|=0x02; if ((machine==MCH_EGA) && (CurMode->special & _EGA_HALF_CLOCK)) seq_data[1]|=0x02;
seq_data[4]|=0x02; //More than 64kb seq_data[4]|=0x02; //More than 64kb
switch (CurMode->type) { switch (CurMode->type) {
case M_TEXT: case M_TEXT:
if (CurMode->cwidth==9) seq_data[1] &= ~1;
seq_data[2]|=0x3; //Enable plane 0 and 1 seq_data[2]|=0x3; //Enable plane 0 and 1
seq_data[4]|=0x01; //Alpanumeric seq_data[4]|=0x01; //Alpanumeric
if (IS_VGA_ARCH) seq_data[4]|=0x04; //odd/even enabled if (IS_VGA_ARCH) seq_data[4]|=0x04; //odd/even enabled
@ -1035,12 +1097,12 @@ bool INT10_SetVideoMode(Bitu mode) {
for (Bit8u ct=0;ct<16;ct++) att_data[ct]=ct; for (Bit8u ct=0;ct<16;ct++) att_data[ct]=ct;
break; break;
case M_TEXT: case M_TEXT:
if (machine==MCH_EGA) { if (CurMode->cwidth==9) {
att_data[0x13]=0x00;
att_data[0x10]=0x08; //8 Bit characters
} else {
att_data[0x13]=0x08; //Pel panning on 8, although we don't have 9 dot text mode att_data[0x13]=0x08; //Pel panning on 8, although we don't have 9 dot text mode
att_data[0x10]=0x0C; //Color Text with blinking att_data[0x10]=0x0C; //Color Text with blinking, 9 Bit characters
} else {
att_data[0x13]=0x00;
att_data[0x10]=0x08; //Color Text with blinking, 8 Bit characters
} }
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30); real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30);
att_text16: att_text16:
@ -1308,8 +1370,7 @@ dac_text16:
/* Load text mode font */ /* Load text mode font */
if (CurMode->type==M_TEXT) { if (CurMode->type==M_TEXT) {
if (IS_VGA_ARCH) INT10_LoadFont(Real2Phys(int10.rom.font_16),true,256,0,0,16); INT10_ReloadFont();
else INT10_LoadFont(Real2Phys(int10.rom.font_14),true,256,0,0,14);
} }
return true; return true;
} }

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: int10_vesa.cpp,v 1.39 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: int10_vesa.cpp,v 1.40 2009/07/31 15:36:01 c2woody Exp $ */
#include <string.h> #include <string.h>
#include <stddef.h> #include <stddef.h>
@ -271,7 +271,7 @@ Bit8u VESA_SetSVGAMode(Bit16u mode) {
Bit8u VESA_GetSVGAMode(Bit16u & mode) { Bit8u VESA_GetSVGAMode(Bit16u & mode) {
if (int10.vesa_setmode!=0xffff) mode=int10.vesa_setmode; if (int10.vesa_setmode!=0xffff) mode=int10.vesa_setmode;
else mode=(Bit16u)(CurMode->mode); else mode=CurMode->mode;
return 0x00; return 0x00;
} }
@ -297,7 +297,7 @@ Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count) {
Bit8u r,g,b; Bit8u r,g,b;
if (index>255) return 0x1; if (index>255) return 0x1;
if (index+count>256) return 0x1; if (index+count>256) return 0x1;
IO_Write(0x3c8,index); IO_Write(0x3c8,(Bit8u)index);
while (count) { while (count) {
b = mem_readb(data++); b = mem_readb(data++);
g = mem_readb(data++); g = mem_readb(data++);
@ -316,7 +316,7 @@ Bit8u VESA_GetPalette(PhysPt data,Bitu index,Bitu count) {
Bit8u r,g,b; Bit8u r,g,b;
if (index>255) return 0x1; if (index>255) return 0x1;
if (index+count>256) return 0x1; if (index+count>256) return 0x1;
IO_Write(0x3c7,index); IO_Write(0x3c7,(Bit8u)index);
while (count) { while (count) {
r = IO_Read(0x3c9); r = IO_Read(0x3c9);
g = IO_Read(0x3c9); g = IO_Read(0x3c9);
@ -428,8 +428,8 @@ Bit8u VESA_GetDisplayStart(Bit16u & x,Bit16u & y) {
Bitu pan=vga.config.pel_panning; Bitu pan=vga.config.pel_panning;
switch (CurMode->type) { switch (CurMode->type) {
case M_LIN8: case M_LIN8:
y=times; y=(Bit16u)times;
x=rem+pan; x=(Bit16u)(rem+pan);
break; break;
default: default:
return 0x1; return 0x1;
@ -503,17 +503,17 @@ void INT10_SetupVESA(void) {
int10.rom.pmode_interface_window = int10.rom.used - RealOff( int10.rom.pmode_interface ); int10.rom.pmode_interface_window = int10.rom.used - RealOff( int10.rom.pmode_interface );
phys_writew( Real2Phys(int10.rom.pmode_interface) + 0, int10.rom.pmode_interface_window ); phys_writew( Real2Phys(int10.rom.pmode_interface) + 0, int10.rom.pmode_interface_window );
callback.pmWindow=CALLBACK_Allocate(); callback.pmWindow=CALLBACK_Allocate();
int10.rom.used += CALLBACK_Setup(callback.pmWindow, VESA_PMSetWindow, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Window"); int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmWindow, VESA_PMSetWindow, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Window");
/* PM Set start call */ /* PM Set start call */
int10.rom.pmode_interface_start = int10.rom.used - RealOff( int10.rom.pmode_interface ); int10.rom.pmode_interface_start = int10.rom.used - RealOff( int10.rom.pmode_interface );
phys_writew( Real2Phys(int10.rom.pmode_interface) + 2, int10.rom.pmode_interface_start); phys_writew( Real2Phys(int10.rom.pmode_interface) + 2, int10.rom.pmode_interface_start);
callback.pmStart=CALLBACK_Allocate(); callback.pmStart=CALLBACK_Allocate();
int10.rom.used += CALLBACK_Setup(callback.pmStart, VESA_PMSetStart, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Start"); int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmStart, VESA_PMSetStart, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Start");
/* PM Set Palette call */ /* PM Set Palette call */
int10.rom.pmode_interface_palette = int10.rom.used - RealOff( int10.rom.pmode_interface ); int10.rom.pmode_interface_palette = int10.rom.used - RealOff( int10.rom.pmode_interface );
phys_writew( Real2Phys(int10.rom.pmode_interface) + 4, int10.rom.pmode_interface_palette); phys_writew( Real2Phys(int10.rom.pmode_interface) + 4, int10.rom.pmode_interface_palette);
callback.pmPalette=CALLBACK_Allocate(); callback.pmPalette=CALLBACK_Allocate();
int10.rom.used += CALLBACK_Setup(callback.pmPalette, VESA_PMSetPalette, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Palette"); int10.rom.used += (Bit16u)CALLBACK_Setup(callback.pmPalette, VESA_PMSetPalette, CB_RETN, PhysMake(0xc000,int10.rom.used), "VESA PM Set Palette");
/* Finalize the size and clear the required ports pointer */ /* Finalize the size and clear the required ports pointer */
phys_writew( Real2Phys(int10.rom.pmode_interface) + 6, 0); phys_writew( Real2Phys(int10.rom.pmode_interface) + 6, 0);
int10.rom.pmode_interface_size=int10.rom.used - RealOff( int10.rom.pmode_interface ); int10.rom.pmode_interface_size=int10.rom.used - RealOff( int10.rom.pmode_interface );

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: int10_vptable.cpp,v 1.4 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: int10_vptable.cpp,v 1.6 2009/08/01 13:39:48 c2woody Exp $ */
#include "dosbox.h" #include "dosbox.h"
#include "mem.h" #include "mem.h"
@ -24,6 +24,77 @@
#include "int10.h" #include "int10.h"
const Bit8u vparams[] = {
// 40x25 mode 0 and 1 crtc registers
0x38, 0x28, 0x2d, 0x0a, 0x1f, 0x06, 0x19, 0x1c, 0x02, 0x07, 0x06, 0x07, 0,0,0,0,
// 80x25 mode 2 and 3 crtc registers
0x71, 0x50, 0x5a, 0x0a, 0x1f, 0x06, 0x19, 0x1c, 0x02, 0x07, 0x06, 0x07, 0,0,0,0,
// graphics modes 4, 5 and 6
0x38, 0x28, 0x2d, 0x0a, 0x7f, 0x06, 0x64, 0x70, 0x02, 0x01, 0x06, 0x07, 0,0,0,0,
// mode 7 MDA text
0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19, 0x02, 0x0d, 0x0b, 0x0c, 0,0,0,0,
// buffer length words 2048, 4096, 16384, 16384
0x00, 0x08, 0x00, 0x10, 0x00, 0x40, 0x00, 0x40,
// columns
40, 40, 80, 80, 40, 40, 80, 80,
// CGA mode register
0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29
};
const Bit8u vparams_pcjr[] = {
// 40x25 mode 0 and 1 crtc registers
0x38, 0x28, 0x2c, 0x06, 0x1f, 0x06, 0x19, 0x1c, 0x02, 0x07, 0x06, 0x07, 0,0,0,0,
// 80x25 mode 2 and 3 crtc registers
0x71, 0x50, 0x5a, 0x0c, 0x1f, 0x06, 0x19, 0x1c, 0x02, 0x07, 0x06, 0x07, 0,0,0,0,
// graphics modes 4, 5, 6, 8
0x38, 0x28, 0x2b, 0x06, 0x7f, 0x06, 0x64, 0x70, 0x02, 0x01, 0x26, 0x07, 0,0,0,0,
// other graphics modes
0x71, 0x50, 0x56, 0x0c, 0x3f, 0x06, 0x32, 0x38, 0x02, 0x03, 0x26, 0x07, 0,0,0,0,
// buffer length words 2048, 4096, 16384, 16384
0x00, 0x08, 0x00, 0x10, 0x00, 0x40, 0x00, 0x40,
// columns
40, 40, 80, 80, 40, 40, 80, 80,
// CGA mode register
0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29
};
const Bit8u vparams_tandy[] = {
// 40x25 mode 0 and 1 crtc registers
0x38, 0x28, 0x2c, 0x08, 0x1f, 0x06, 0x19, 0x1c, 0x02, 0x07, 0x06, 0x07, 0,0,0,0,
// 80x25 mode 2 and 3 crtc registers
0x71, 0x50, 0x58, 0x10, 0x1f, 0x06, 0x19, 0x1c, 0x02, 0x07, 0x06, 0x07, 0,0,0,0,
// graphics modes 4, 5 and 6
0x38, 0x28, 0x2c, 0x08, 0x7f, 0x06, 0x64, 0x70, 0x02, 0x01, 0x06, 0x07, 0,0,0,0,
// graphics mode 7
0x71, 0x50, 0x58, 0x10, 0x3f, 0x06, 0x32, 0x38, 0x02, 0x03, 0x06, 0x07, 0,0,0,0,
// buffer length words 2048, 4096, 16384, 16384
0x00, 0x08, 0x00, 0x10, 0x00, 0x40, 0x00, 0x40,
// columns
40, 40, 80, 80, 40, 40, 80, 80,
// CGA mode register
0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29
};
const Bit8u vparams_tandy_td[] = {
// 40x25 mode 0 and 1 crtc registers
0x38, 0x28, 0x2d, 0x0a, 0x1f, 0x06, 0x19, 0x1c, 0x02, 0x07, 0x06, 0x07, 0,0,0,0,
// 80x25 mode 2 and 3 crtc registers
0x71, 0x50, 0x5a, 0x0a, 0x1f, 0x06, 0x19, 0x1c, 0x02, 0x07, 0x06, 0x07, 0,0,0,0,
// graphics modes 4, 5 and 6
0x38, 0x28, 0x2d, 0x0a, 0x7f, 0x06, 0x64, 0x70, 0x02, 0x01, 0x06, 0x07, 0,0,0,0,
// mode 7 MDA text
0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19, 0x02, 0x0d, 0x0b, 0x0c, 0,0,0,0,
// ?? mode 2 and 3 crtc registers
0x71, 0x50, 0x5a, 0x0a, 0x3f, 0x06, 0x32, 0x38, 0x02, 0x03, 0x06, 0x07, 0,0,0,0,
// buffer length words 2048, 4096, 16384, 16384
0x00, 0x08, 0x00, 0x10, 0x00, 0x40, 0x00, 0x40,
// columns
40, 40, 80, 80, 40, 40, 80, 80,
// CGA mode register
0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29
};
static Bit8u video_parameter_table_vga[0x40*0x1d]={ static Bit8u video_parameter_table_vga[0x40*0x1d]={
// video parameter table for mode 0 (cga emulation) // video parameter table for mode 0 (cga emulation)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -447,7 +518,7 @@ static Bit8u video_parameter_table_ega[0x40*0x17]={
}; };
Bitu INT10_SetupVideoParameterTable(PhysPt basepos) { Bit16u INT10_SetupVideoParameterTable(PhysPt basepos) {
if (IS_VGA_ARCH) { if (IS_VGA_ARCH) {
for (Bitu i=0;i<0x40*0x1d;i++) { for (Bitu i=0;i<0x40*0x1d;i++) {
phys_writeb(basepos+i,video_parameter_table_vga[i]); phys_writeb(basepos+i,video_parameter_table_vga[i]);
@ -461,6 +532,28 @@ Bitu INT10_SetupVideoParameterTable(PhysPt basepos) {
} }
} }
void INT10_SetupBasicVideoParameterTable(void) {
/* video parameter table at F000:F0A4 */
RealSetVec(0x1d,RealMake(0xF000, 0xF0A4));
switch (machine) {
case MCH_TANDY:
for (Bit16u i = 0; i < sizeof(vparams_tandy); i++) {
phys_writeb(0xFF0A4+i,vparams_tandy[i]);
}
break;
case MCH_PCJR:
for (Bit16u i = 0; i < sizeof(vparams_pcjr); i++) {
phys_writeb(0xFF0A4+i,vparams_pcjr[i]);
}
break;
default:
for (Bit16u i = 0; i < sizeof(vparams); i++) {
phys_writeb(0xFF0A4+i,vparams[i]);
}
break;
}
}
#if 0 #if 0
void INT10_GenerateVideoParameterTable(void) { void INT10_GenerateVideoParameterTable(void) {
if (!IS_VGA_ARCH) E_Exit("Be sure that all graphics registers are readable!"); if (!IS_VGA_ARCH) E_Exit("Be sure that all graphics registers are readable!");

View File

@ -1566,21 +1566,12 @@ int main(int argc, char *argv[])
atexit(SDL_Quit); atexit(SDL_Quit);
#ifdef HW_RVL
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);
if (screen == NULL) {
fprintf(stderr, "Couldn't set 640x480x16 video mode: %s\n", SDL_GetError());
exit(1);
}
printf("GUI:: color depth %i\n",screen->format->BitsPerPixel);
#else
screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE); screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
if (screen == NULL) { if (screen == NULL) {
fprintf(stderr, "Couldn't set 640x480x32 video mode: %s\n", SDL_GetError()); fprintf(stderr, "Couldn't set 640x480x32 video mode: %s\n", SDL_GetError());
exit(1); exit(1);
} }
printf("GUI:: color depth %i\n",screen->format->BitsPerPixel); printf("GUI:: color depth %i\n",screen->format->BitsPerPixel);
#endif
SDL_EnableUNICODE(true); SDL_EnableUNICODE(true);
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL);

View File

@ -4,7 +4,7 @@
#define C_DEBUG 0 #define C_DEBUG 0
/* Define to 1 to enable screenshots, requires libpng */ /* Define to 1 to enable screenshots, requires libpng */
#define C_SSHOT 0 #define C_SSHOT 1
/* Define to 1 to use opengl display output support */ /* Define to 1 to use opengl display output support */
#define C_OPENGL 1 #define C_OPENGL 1

View File

@ -28,7 +28,7 @@
#define C_DYNREC 0 #define C_DYNREC 0
/* Enable memory function inlining in */ /* Enable memory function inlining in */
#define C_CORE_INLINE 0 #define C_CORE_INLINE 1
/* Enable the FPU module, still only for beta testing */ /* Enable the FPU module, still only for beta testing */
#define C_FPU 1 #define C_FPU 1

View File

@ -20,22 +20,27 @@ void WiiInit()
void CreateAppPath(char origpath[]) void CreateAppPath(char origpath[])
{ {
char path[1024]; char * path = strdup(origpath); // make a copy so we don't mess up original
strncpy(path, origpath, 1024); // make a copy
char * loc; if(!path)
int pos = -1; return;
loc = strrchr(path,'/'); char * loc = strrchr(path,'/');
if (loc != NULL) if (loc != NULL)
*loc = 0; // strip file name *loc = 0; // strip file name
loc = strchr(path,'/'); // looking for / from fat:/ (or sd:/) int pos = 0;
if (loc != NULL)
pos = loc - path + 1;
if(pos >= 0 && pos < 1024) // replace fat:/ with sd:/
sprintf(appPath, "sd:/%s", &(path[pos])); if(strncmp(path, "fat:/", 5) == 0)
{
pos++;
path[1] = 's';
path[2] = 'd';
}
strncpy(appPath, &path[pos], MAXPATHLEN);
appPath[MAXPATHLEN-1] = 0;
free(path);
} }
void WiiFinished() void WiiFinished()

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: shell.cpp,v 1.99 2009/05/14 18:44:54 qbix79 Exp $ */ /* $Id: shell.cpp,v 1.100 2009/07/08 20:05:41 c2woody Exp $ */
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
@ -621,7 +621,7 @@ void SHELL_Init() {
pspmcb.SetType(0x4d); pspmcb.SetType(0x4d);
DOS_MCB envmcb((Bit16u)(env_seg-1)); DOS_MCB envmcb((Bit16u)(env_seg-1));
envmcb.SetPSPSeg(psp_seg); // MCB of the command shell environment envmcb.SetPSPSeg(psp_seg); // MCB of the command shell environment
envmcb.SetSize(0x28); envmcb.SetSize(DOS_MEM_START-env_seg);
envmcb.SetType(0x4d); envmcb.SetType(0x4d);
/* Setup environment */ /* Setup environment */

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: shell_batch.cpp,v 1.35 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: shell_batch.cpp,v 1.36 2009/07/03 19:36:56 qbix79 Exp $ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -32,6 +32,7 @@ BatchFile::BatchFile(DOS_Shell * host,char const * const name, char const * cons
char totalname[DOS_PATHLENGTH+4]; char totalname[DOS_PATHLENGTH+4];
DOS_Canonicalize(name,totalname); // Get fullname including drive specificiation DOS_Canonicalize(name,totalname); // Get fullname including drive specificiation
cmd = new CommandLine(totalname,cmd_line); cmd = new CommandLine(totalname,cmd_line);
filename = totalname;
//Test if file is openable //Test if file is openable
if (!DOS_OpenFile(totalname,128,&file_handle)) { if (!DOS_OpenFile(totalname,128,&file_handle)) {
@ -49,8 +50,8 @@ BatchFile::~BatchFile() {
bool BatchFile::ReadLine(char * line) { bool BatchFile::ReadLine(char * line) {
//Open the batchfile and seek to stored postion //Open the batchfile and seek to stored postion
if (!DOS_OpenFile(cmd->GetFileName(),128,&file_handle)) { if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) {
LOG(LOG_MISC,LOG_ERROR)("ReadLine Can't open BatchFile %s",cmd->GetFileName()); LOG(LOG_MISC,LOG_ERROR)("ReadLine Can't open BatchFile %s",filename.c_str());
delete this; delete this;
return false; return false;
} }
@ -143,8 +144,8 @@ emptyline:
bool BatchFile::Goto(char * where) { bool BatchFile::Goto(char * where) {
//Open bat file and search for the where string //Open bat file and search for the where string
if (!DOS_OpenFile(cmd->GetFileName(),128,&file_handle)) { if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) {
LOG(LOG_MISC,LOG_ERROR)("SHELL:Goto Can't open BatchFile %s",cmd->GetFileName()); LOG(LOG_MISC,LOG_ERROR)("SHELL:Goto Can't open BatchFile %s",filename.c_str());
delete this; delete this;
return false; return false;
} }

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: shell_cmds.cpp,v 1.90 2009/04/02 19:08:26 qbix79 Exp $ */ /* $Id: shell_cmds.cpp,v 1.93 2009/09/21 21:04:25 h-a-l-9000 Exp $ */
#include "dosbox.h" #include "dosbox.h"
#include "shell.h" #include "shell.h"
@ -404,6 +404,10 @@ void DOS_Shell::CMD_DIR(char * args) {
bool optW=ScanCMDBool(args,"W"); bool optW=ScanCMDBool(args,"W");
ScanCMDBool(args,"S"); ScanCMDBool(args,"S");
bool optP=ScanCMDBool(args,"P"); bool optP=ScanCMDBool(args,"P");
if (ScanCMDBool(args,"WP") || ScanCMDBool(args,"PW")) {
optW=optP=true;
}
bool optB=ScanCMDBool(args,"B");
bool optAD=ScanCMDBool(args,"AD"); bool optAD=ScanCMDBool(args,"AD");
char * rem=ScanCMDRemain(args); char * rem=ScanCMDRemain(args);
if (rem) { if (rem) {
@ -450,7 +454,7 @@ void DOS_Shell::CMD_DIR(char * args) {
return; return;
} }
*(strrchr(path,'\\')+1)=0; *(strrchr(path,'\\')+1)=0;
WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),path); if (!optB) WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),path);
/* Command uses dta so set it to our internal dta */ /* Command uses dta so set it to our internal dta */
RealPt save_dta=dos.dta(); RealPt save_dta=dos.dta();
@ -458,7 +462,7 @@ void DOS_Shell::CMD_DIR(char * args) {
DOS_DTA dta(dos.dta()); DOS_DTA dta(dos.dta());
bool ret=DOS_FindFirst(args,0xffff & ~DOS_ATTR_VOLUME); bool ret=DOS_FindFirst(args,0xffff & ~DOS_ATTR_VOLUME);
if (!ret) { if (!ret) {
WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args); if (!optB) WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args);
dos.dta(save_dta); dos.dta(save_dta);
return; return;
} }
@ -483,6 +487,13 @@ void DOS_Shell::CMD_DIR(char * args) {
Bit8u minute = (Bit8u)((time >> 5) & 0x003f); Bit8u minute = (Bit8u)((time >> 5) & 0x003f);
/* output the file */ /* output the file */
if (optB) {
// this overrides pretty much everything
if (strcmp(".",name) && strcmp("..",name)) {
if ((attr & DOS_ATTR_DIRECTORY)||(strlen(ext)==0)) WriteOut("%s\n",name);
else WriteOut("%s.%s\n",name,ext);
}
} else {
if (attr & DOS_ATTR_DIRECTORY) { if (attr & DOS_ATTR_DIRECTORY) {
if (optW) { if (optW) {
WriteOut("[%s]",name); WriteOut("[%s]",name);
@ -507,16 +518,17 @@ void DOS_Shell::CMD_DIR(char * args) {
if (optW) { if (optW) {
w_count++; w_count++;
} }
if(optP) { if (optP) {
if(!(++p_count%(22*w_size))) { if (!(++p_count%(22*w_size))) {
CMD_PAUSE(empty_string); CMD_PAUSE(empty_string);
} }
} }
}
} while ( (ret=DOS_FindNext()) ); } while ( (ret=DOS_FindNext()) );
if (optW) { if (optW) {
if (w_count%5) WriteOut("\n"); if (w_count%5) WriteOut("\n");
} }
if (!optB) {
/* Show the summary of results */ /* Show the summary of results */
FormatNumber(byte_count,numformat); FormatNumber(byte_count,numformat);
WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_USED"),file_count,numformat); WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_USED"),file_count,numformat);
@ -530,6 +542,7 @@ void DOS_Shell::CMD_DIR(char * args) {
} }
FormatNumber(free_space,numformat); FormatNumber(free_space,numformat);
WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_FREE"),dir_count,numformat); WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_FREE"),dir_count,numformat);
}
dos.dta(save_dta); dos.dta(save_dta);
} }
@ -570,11 +583,25 @@ void DOS_Shell::CMD_COPY(char * args) {
// Concatating files go as follows: All parts except for the last bear the concat flag. // Concatating files go as follows: All parts except for the last bear the concat flag.
// This construction allows them to be counted (only the non concat set) // This construction allows them to be counted (only the non concat set)
char* source_p = NULL; char* source_p = NULL;
char source_x[DOS_PATHLENGTH+CROSS_LEN];
while ( (source_p = StripWord(args)) && *source_p ) { while ( (source_p = StripWord(args)) && *source_p ) {
do { do {
char* plus = strchr(source_p,'+'); char* plus = strchr(source_p,'+');
if(plus) *plus++ = 0; if (plus) *plus++ = 0;
sources.push_back(copysource(source_p,(plus)?true:false)); safe_strncpy(source_x,source_p,CROSS_LEN);
bool has_drive_spec = false;
size_t source_x_len = strlen(source_x);
if (source_x_len>0) {
if (source_x[source_x_len-1]==':') has_drive_spec = true;
}
if (!has_drive_spec) {
if (DOS_FindFirst(source_p,0xffff & ~DOS_ATTR_VOLUME)) {
dta.GetResult(name,size,date,time,attr);
if (attr & DOS_ATTR_DIRECTORY && !strstr(source_p,"*.*"))
strcat(source_x,"\\*.*");
}
}
sources.push_back(copysource(source_x,(plus)?true:false));
source_p = plus; source_p = plus;
} while(source_p && *source_p); } while(source_p && *source_p);
} }

View File

@ -1,19 +1,21 @@
Microsoft Visual Studio Solution File, Format Version 10.00 Microsoft Visual Studio Solution File, Format Version 8.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dosbox", "dosbox.vcproj", "{7FCFFB9B-8629-4D51-849C-8490CECF8AB7}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dosbox", "dosbox.vcproj", "{7FCFFB9B-8629-4D51-849C-8490CECF8AB7}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfiguration) = preSolution
Debug|Win32 = Debug|Win32 Debug = Debug
Release|Win32 = Release|Win32 Release = Release
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfiguration) = postSolution
{7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Debug|Win32.ActiveCfg = Debug|Win32 {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Debug.ActiveCfg = Debug|Win32
{7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Debug|Win32.Build.0 = Debug|Win32 {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Debug.Build.0 = Debug|Win32
{7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Release|Win32.ActiveCfg = Release|Win32 {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Release.ActiveCfg = Release|Win32
{7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Release|Win32.Build.0 = Release|Win32 {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Release.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(ExtensibilityGlobals) = postSolution
HideSolutionNode = FALSE EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

File diff suppressed because it is too large Load Diff