VOGONS


First post, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

I was writing some code just for the hell of it to initialize and play sound through the (fake) GUS provided by DOSBox. The Gravis SDK documents a panning register, but DOSBox doesn't seem to be emulating it at all. Everything is stuck in center, no matter how you modify the panning register. [DOSBox 0.74]

I did a quick hack to hardware/gus.cpp to modify how the panning register is emulated. I noticed the original code computes a 16-step log from 0 to 15 but then applies it to both L and R in a mirrored fashion that might as well not have any effect. I modified it to zero out entries 0...7 of the pantable and then compute 8 steps on the other side, with the 15th entry as large as possible to silence the channel. It's probably not quite accurate and might be far away from what the actual GUS does but it seems to bring out stereo music in a lot of old DOS demos.

new code:

src/hardware/gus.cpp

void WritePanPot(Bit8u val) {
PanPot = val;
if ((val & 0xf) >= 8 ) PanLeft = pantable[val & 0xf];
else PanLeft = 0;
if ((val & 0xf) < 7) PanRight = pantable[0xf - (val & 0xf)];
else PanRight = 0;
UpdateVolumes();
}

....................

// Generate logarithmic to linear volume conversion tables
static void MakeTables(void) {
int i;
double out = (double)(1 << 13);
for (i=4095;i>=0;i--) {
vol16bit=(Bit16s)out;
out/=1.002709201; /* 0.0235 dB Steps */
}
for (i=0;i < 8;i++)
pantable = 0;
for (i=8;i < 15;i++)
pantable=(Bit32u)(-128.0*(log((double)(15-i)/7.0)/log(2.0))*(double)(1 << RAMP_FRACT));
/* if the program cranks the pan register all the way, ensure the
* opposite channel is crushed to silence */
pantable[15] = 1UL << 30UL;
}

Also before I forget, I think I also found a typo in sblaster.cpp that affects 2-bit ADPCM decoding. Is the last row of scaleMap[] supposed to be "6, 48, -16, -48" ?

Reply 1 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

I also maintain a private "fork" of DOSBox 0.74 with other changes that might be of interest to you guys:

* Numerous fixes to your 8042 keyboard emulation to make it more complete and accurate. Including controller reset, alt scan codes, setting the LEDs, and other arcane features. Hopefully DOS games or debuggers that rely on control of the keyboard will benefit from this.

* Emulation of the "AUX" port on the 8042 keyboard to emulate an attached PS/2 mouse (NOT through INT 15H/INT 33H). Obviously this conflicts with your INT 33H emulation, so the code is written to disable AUX emulation when INT 33H "driver reset" is called, and to disable the INT 33H driver when command 0xFF (reset) is sent to the 8042 AUX port.

* A bug fix to your INT 15H BIOS "extended memory copy" emulation. Your code used the wrong byte of the GDT for bits 24-31 and got the memory address wrong. Using the "limit/global/default" byte is not correct and can cause DOSBox to spill error messages about "invalid memory access 8Fxxxxxx" if asked to work with a 386-style GDT.

* machine=cga with accurate CGA snow emulation. Programs that check port 0x3DA to wait for retrace will not trigger it, while writing to video RAM at any other time will trigger it. I used to own an IBM XT luggable that had this problem so I'm very familiar with what CGA snow looks like :) The mod also adds a builtin command that you can use to enable/disable the effect at runtime.

* The ability to force a refresh rate regardless of video mode. You can specify an integer rate, a fraction (like 60000/1001), or two presets "ntsc" or "pal". I was motivated to add that when I used DOSBox 0.72 to record various programs from the demoscene. Forcing the refresh rate to 59.94 made it easier to edit and convert to DVD without the horrible "judder" you see with scan converters. Some games and demos are sensitive to refresh rate though, so it's not always a good idea to force it. Also adds an internal command to change the forced refresh rate at runtime.

Reply 2 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

Alright never mind, I see someone also fixed the pantable:

http://dosbox.svn.sourceforge.net/viewvc/dosb … up&pathrev=3727

Still though, anyone interested in the above patches?

Reply 3 of 48, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

the extended memory copy thing, although it is not used very often.
but feel free to post any patch that you want to share with us.

Water flows down the stream
How to ask questions the smart way!

Reply 5 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

Fix for extended memcpy (INT 15H AH=0x87):

case 0x87: /* Copy extended memory */
{
bool enabled = MEM_A20_Enabled();
MEM_A20_Enable(true);
Bitu bytes = reg_cx * 2;
PhysPt data = SegPhys(es)+reg_si;
PhysPt source = (mem_readd(data+0x12) & 0x00FFFFFF) + (mem_readb(data+0x17)<<24);
PhysPt dest = (mem_readd(data+0x1A) & 0x00FFFFFF) + (mem_readb(data+0x1F)<<24);
MEM_BlockCopy(dest,source,bytes);
reg_ax = 0x00;
MEM_A20_Enable(enabled);
CALLBACK_SCF(false);
break;
}

The original code was using byte 0x16 and byte 0x1E for bits 24-31 of the memory address. According to http://wiki.osdev.org/Global_Descriptor_Table that byte holds bits 16-19 of the limit and the flags on 386 or higher systems.

Here is a tarball of my modified copy: http://jon.nerdgrounds.com/dosbox-x-hackipedi … 820-0016.tar.gz . I will break out the individual changes when I have time, some of the changes are all over the place especially the 8042 and AUX PS/2 changes.

Last edited by TheGreatCodeholio on 2011-08-20, 07:30. Edited 2 times in total.

Reply 6 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

No problem here.

dosultrinit.jpg

[gus]
gus=true
gusrate=44100
gusbase=240
gusirq=5
gusdma=3
ultradir=C:\ULTRASND

Are you using normal GUS settings? I know it's possible in DOSBox to use DMA and IRQ assignments the GUS normally can't do...

Reply 7 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

Hey, just found another mistake. In your HIMEM.SYS XMS emulation:

The original code was responding to the extended version of ALLOCATE MEMORY (function 0x89) but then chopping off the upper 16 bits of EDX. A program asking for 64MB of RAM would get 0. The whole point of the extended version is to use all 32 bits of EDX to allow larger amounts, up to 4GB.

Corrected code:

case XMS_ALLOCATE_ANY_MEMORY: /* 89 */
{ /* Chopping off bits 16-31 to fall through to ALLOCATE_EXTENDED_MEMORY is inaccurate.
The Extended Memory Specification states you use all of EDX, so programs can request
64MB or more. Even if DOSBox does not (yet) support >= 64MB of RAM. */
Bit16u handle = 0;
SET_RESULT(XMS_AllocateMemory(reg_edx,handle));
reg_dx = handle;
}; break;
case XMS_ALLOCATE_EXTENDED_MEMORY: /* 09 */
{
Bit16u handle = 0;
SET_RESULT(XMS_AllocateMemory(reg_dx,handle));
reg_dx = handle;
}; break;

The original code AND'd EDX with 0xFFFF then fell through to the original system call to allocate memory.

I know DOSBox does not yet do more than 64MB of memory but at least handle the system call properly.

Extended memory specification:
http://hackipedia.org/Operating%20Systems/DOS … i.txt.utf-8.txt

Reply 8 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

Alright so with the fixed XMS implementation, I changed MAX_MEMORY in src/hardware/memory.cpp to 256 and ran various DOS games I have with memsize=256 (256MB of RAM). No problems that I saw. Some test programs I've written also work just as good as they do under QEMU and VirtualBox with >= 64MB of memory. Even Windows 3.11 correctly reports the amount of memory when memsize=256.

Could future versions of DOSBox lift the 64MB limit or at least make the limit a compile-time option?

Reply 9 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

OK I found the 2.28 version of ULTRINIT. I get the same failure. But you can get it to work apparently by setting sbtype=none (disabling Sound Blaster emulation). The GUS and SB IRQ+DMA settings do not overlap, so I don't really understand (yet) why this causes the program to fail.

Their setup program will pass the GUS emulation for playback and Ultrasound IRQ but will fail recording sometimes. It will also complain that the NMI interrupt doesn't work.

Latest tarball: http://jon.nerdgrounds.com/dosbox-x-hackipedi … 820-0638.tar.gz

Reply 10 of 48, by orynider

User metadata
Rank Newbie
Rank
Newbie

dosboxultrsetup.png

Yes, is working when I put before ultrinit the line for UltraSound Max:
@SET ULTRA16=34C,0,0,1,0
@SET ULTRADIR=C:\ULTRASND
@C:\ULTRASND\ULTRINIT.EXE -dj

Note that with older version of DosBox is working with no extra line and I get no error, but with 0.74 it only works with this line or if I put an invalid parameter after UltrInit:
@C:\ULTRASND\ULTRINIT.EXE /?

dosboxultrinit.png

dosboxiplay.png

I only have VS2003 at the moment and can't do a custon build...

Reply 11 of 48, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

A program asking for 64MB of RAM would get 0.

That's intentional. Maximum memory is limited to 63mb.

Could future versions of DOSBox lift the 64MB limit or at least make the limit a compile-time option?

Nope.

Reply 12 of 48, by orynider

User metadata
Rank Newbie
Rank
Newbie

from the conf workaround

[sblaster]
sbtype=none
# Using 'none' I get: Can't find matching event for hand_caprawopl
# Having 'sb16' 220, 230, and 240 base adresses are taken but still can use 240 for gus with -? option...
sbbase=220
irq=5
dma=6
hdma=6
sbmixer=true
oplmode=auto
oplemu=default
oplrate=44100
hardwarebase=210

[gus]
gus=ace
gusrate=44100
gusbase=240
# gusirq=7
# gusdma=3
# irq1=7
# irq2=7
# dma1=3
# dma2=3
ultradir=C:\ULTRASND

[innova]
innova=false
samplerate=22050
sidbase=280
quality=0

[speaker]
pcspeaker=true
pcrate=44100
tandy=auto
tandyrate=44100
disney=false
ps1audio=auto
ps1audiorate=22050

[joystick]
joysticktype=auto
timed=true
autofire=false
swap34=false
buttonwrap=false

[serial]
serial1=dummy
serial2=dummy
serial3=disabled
serial4=disabled

[printer]
printer=true
dpi=360
width=85
height=110
printoutput=png
Show last 55 lines
multipage=false
docpath=.
timeout=0

[parallel]
parallel1=disabled
parallel2=disabled
parallel3=disabled

[glide]
glide=true
grport=600
lfb=full

[dos]
xms=true
ems=true
umb=true
automount=true
keyboardlayout=auto
files=127

[ipx]
ipx=false

[ne2000]
ne2000=true
nicbase=390
nicirq=10
macaddr=AC:DE:48:88:99:AE
realnic=3

[autoexec]
# Lines in this section will be run at startup.
# You can put your MOUNT lines here.
VER set 7 10
# mount d: e:\kitt\images\
mount c c:\
mount d f:\
mount e e:\
mount i i:\
mount h d:\
@echo off
@C:\ULTRASND\ULTRINIT.EXE -? -dj -L -m1024
# This is forcing ultrinit to load with 'sbtype=sb16'
set EXPAND=YES
PATH=C:\WIN98;C:\WIN98\COMMAND;C:\Win98\Command\norton;C:\ULTRASND;C:\NC;C:\SB16
@SET TEMP=C:\Win98\Command
@SET TMP=C:\TEMP
@SET NC=C:\NC
SET BUGS=OFF
ECHO.
C:
cd ultrasnd

dosboxutrasndtest.png
dosboxutrasndwin.png

Reply 13 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

I understand where you're coming from, XMS function 9 takes the memory size from DX (lower 16 bits of EDX). That's correct behavior. What is NOT correct behavior is doing the same to function 0x89 which the Extended Memory Specification states takes the size in EDX (all 32 bits) not DX. DOS programs calling that function expect your XMS emulation to use all 32 bits, because that is what the specification says.

You can avoid some subtle DOS crashes by not lying to the program about how much was actually allocated. If the DOS program expected to allocate >= 64MB of RAM the best you can do is report insufficient memory instead of only parsing the lower 16 bits and giving the DOS program the false impression allocation succeeded. It would prevent the DOS program from rampaging into undefined memory it thought it allocated.

Allocate Extended Memory Block (Function 09h):
----------------------------------------------

ARGS: AH = 09h
DX = Amount of extended memory being requested in K-bytes
RETS: AX = 0001h if the block is allocated, 0000h otherwise
DX = 16-bit handle to the allocated block
ERRS: BL = 80h if the function is not implemented
BL = 81h if a VDISK device is detected
BL = A0h if all available extended memory is allocated
BL = A1h if all available extended memory handles are in use

This function attempts to allocate a block of the given size out of the
pool of free extended memory. If a block is available, it is reserved
for the caller and a 16-bit handle to that block is returned. The handle
should be used in all subsequent extended memory calls. If no memory was
allocated, the returned handle is null.

NOTE: Extended memory handles are scarce resources. Programs should
try to allocate as few as possible at any one time. When all
of a driver's handles are in use, any free extended memory is
unavailable.



Allocate Any Extended Memory (Function 89h)

Entry:
AH = 89h
EDX = Amount of extended memory requested, in Kb.
Exit:
AX = 1 if the block is allocated, 0 if not
DX = Handle to allocated block.
Errors:
BL = 80h if the function is not implemented.
BL = 81h if a VDISK device is detected.
BL = A0h if all available extended memory is allocated.
BL = A1h if all available extended memory handles are in use.

This function is similar to the existing Allocate Extended Memory, except that it uses a 32-bit instead of a 16-bit value to specify the amount of memory requested. It allocates from the same memory and handle pool as the current function. Since it requires a 32-bit register, this function can be supported only on 80386 and higher processors, and XMS drivers on 80286 machines should return error code 80h.

Reply 14 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

I also want to point out I modified src/hardware/memory.cpp to raise the limit to 256MB and I fixed src/ints/xms.cpp to work as I described. I ran DOS games and Windows 3.1 in DOSBox with memsize=256 with no noticeable problems. It could be I fixed precisely what made you cap memory at 64MB in the first place. Compatibility with DOS programs not using function 0x89 is preserved by capping the return value at 64MB or less.

DOSBox with memsize=256
dosbox_256mb.png

Windows 3.1 with swap enabled and 256MB
win31_256mb_w_swap.png

Windows 3.1 with swap turned off and 256MB
win31_256mb.png

I also tested with 65MB, 96MB, 192MB, 144MB, and other odd memory sizes to try and find any case where DOS programs would act as if memsize modulo 64MB were present. Didn't happen.

Wolfenstein 3D: Obviously uses the older XMS API. Startup screen reported >= 1MB of XMS regardless of memsize=63, memsize=64, memsize=65, and memsize=256

Modifying XMS emulation to follow spec that also brings it much closer to what HIMEM.SYS does under Windows 95/98 when more than 64MB of RAM is installed.

Reply 15 of 48, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

You can avoid some subtle DOS crashes

For example?

Modifying XMS emulation to follow spec that also brings it much closer to what HIMEM.SYS does under Windows 95/98

I don't care, and I don't want >63mb of available memory. The interface (including capping edx)
has been chosen on purpose and works fine.

Reply 16 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

Subtle DOS crashes like a program requesting 64MB of RAM, DOSBox allocating 0MB (65536KB & 0xFFFF == 0KB), and the program then tromping on unrelated memory blocks in extended memory because it thinks it allocated 64MB of RAM. Memory corruption. Crash.

I'm willing to assume not every DOS programmer back then was paranoid enough to allocate memory then call "get EMB handle" to verify it.

If you don't want >= 64MB of RAM that's fine by me.

You might consider modifying src/ints/xms.cpp then:

        case XMS_ALLOCATE_ANY_MEMORY:                                                           /* 89 */
if (reg_edx >= 65536) { /* 64MB or more not allowed */
/* FIXME: return an error, however you do that */
}
/* fall through, reg_edx < 65536 */
case XMS_ALLOCATE_EXTENDED_MEMORY: /* 09 */
{
Bit16u handle = 0;
SET_RESULT(XMS_AllocateMemory(reg_dx,handle));
reg_dx = handle;
}; break;

Reply 18 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

Just to clarify: you're telling the ultrasound software it's an Ultrasound Max?

I thought DOSBox only emulated the classic GUS.

The Ultrasound Max has a few extra I/O ports according to the SDK at 3X6 and 7X6 (where if GUS_BASE is at 0x240 they would be at 0x340 and 0x740). DOSBox as far as I can tell doesn't emulate these ports.

Is there a way to tell the program you have a classic GUS?

Reply 19 of 48, by TheGreatCodeholio

User metadata
Rank Oldbie
Rank
Oldbie

The "classic" version of the function (0x09), yes. You mask the upper 16 bits and use DX.

The "allocate any memory" version (0x89), no. The specs I have say full EDX is used. Masking to 16 bits violates the standard and can confuse DOS programs. Returning an error if EDX >= 64MB at least prevents DOS programs from getting into problems with the DOSBox 64MB limit.

http://en.wikipedia.org/wiki/Extended_memory# … ation_.28XMS.29

http://www.ousob.com/ng/xms30/ng9053.php