VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

When running the Megarace demo install.exe, eventually sound starts to play, which seems to be pure noise. Anyone can see if there's an error in my sound blaster emulation? Or is it simply an error in the 80386 emulation?

https://bitbucket.org/superfury/unipcemu/src/ … ter.c?at=master

updateSoundBlaster handles timing and rendering. The in/out functions handle I/O. DMA should be obvious.

Edit: Since the normal disks using 8-bit output work correctly, could this mean a problem with ADPCM deconpression?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 1 of 5, by superfury

User metadata
Rank l33t++
Rank
l33t++

This is what I'm getting using the current commit of UniPCemu:
https://www.dropbox.com/s/giujq663k5eblhn/Meg … 9_0114.wav?dl=0

Sound Blaster code used: https://bitbucket.org/superfury/unipcemu/src/ … ter.c?at=master

- updateSoundBlaster updates timing and rendering.
- inSoundBlaster/outSoundBlaster handle I/O to the sound blaster.
- SoundBlaster_readDMA8/SoundBlaster_writeDMA8 handle input/output from DMA.
- SoundBlaster_DREQ handles DREQ updating.
- SoundBlaster_DACK/SoundBlaster_TC handles DACK and TC from the DMA controller.
- StartPendingSoundBlasterIRQ handles IRQ from the Sound Blaster being acnowledged by the PIC.
- SoundBlaster_SoundGenerator renders from the double buffer to the real renderer.

Anyone can see what's going wrong with the MegaRace installer playback? Or is there a fault in the CPU that must be causing this?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 2 of 5, by superfury

User metadata
Rank l33t++
Rank
l33t++

This is the UniPCemu ADPCM decoding, based on Dosbox's:

//ADPCM decoder from Dosbox
OPTINLINE byte decode_ADPCM_4_sample(byte sample, byte *reference, int_32 *scale)
{
static const sbyte scaleMap[64] = {
0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7,
1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15,
2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30,
4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60
};
static const byte adjustMap[64] = {
0, 0, 0, 0, 0, 16, 16, 16,
0, 0, 0, 0, 0, 16, 16, 16,
240, 0, 0, 0, 0, 16, 16, 16,
240, 0, 0, 0, 0, 16, 16, 16,
240, 0, 0, 0, 0, 16, 16, 16,
240, 0, 0, 0, 0, 16, 16, 16,
240, 0, 0, 0, 0, 0, 0, 0,
240, 0, 0, 0, 0, 0, 0, 0
};

int_32 samp = sample + *scale;

if ((samp < 0) || (samp > 63)) {
//LOG(LOG_SB, LOG_ERROR)("Bad ADPCM-4 sample");
if (samp < 0) samp = 0;
if (samp > 63) samp = 63;
}

int_32 ref = *reference + scaleMap[samp];
if (ref > 0xff) *reference = 0xff;
else if (ref < 0x00) *reference = 0x00;
else *reference = (byte)(ref & 0xff);
*scale = (*scale + adjustMap[samp]) & 0xff;

return (byte)*reference;
}

OPTINLINE byte decode_ADPCM_2_sample(byte sample, byte *reference, int_32 *scale)
{
static const sbyte scaleMap[24] = {
0, 1, 0, -1, 1, 3, -1, -3,
2, 6, -2, -6, 4, 12, -4, -12,
8, 24, -8, -24, 6, 48, -16, -48
};
static const byte adjustMap[24] = {
0, 4, 0, 4,
252, 4, 252, 4, 252, 4, 252, 4,
252, 4, 252, 4, 252, 4, 252, 4,
252, 0, 252, 0
};

int_32 samp = sample + *scale;
if ((samp < 0) || (samp > 23)) {
//LOG(LOG_SB, LOG_ERROR)("Bad ADPCM-2 sample");
if (samp < 0) samp = 0;
if (samp > 23) samp = 23;
}

int_32 ref = *reference + scaleMap[samp];
if (ref > 0xff) *reference = 0xff;
Show last 40 lines
	else if (ref < 0x00) *reference = 0x00;
else *reference = (byte)(ref & 0xff);
*scale = (*scale + adjustMap[samp]) & 0xff;

return (byte)*reference;
}

OPTINLINE byte decode_ADPCM_3_sample(byte sample, byte *reference,int_32 *scale)
{
static const sbyte scaleMap[40] = {
0, 1, 2, 3, 0, -1, -2, -3,
1, 3, 5, 7, -1, -3, -5, -7,
2, 6, 10, 14, -2, -6, -10, -14,
4, 12, 20, 28, -4, -12, -20, -28,
5, 15, 25, 35, -5, -15, -25, -35
};
static const byte adjustMap[40] = {
0, 0, 0, 8, 0, 0, 0, 8,
248, 0, 0, 8, 248, 0, 0, 8,
248, 0, 0, 8, 248, 0, 0, 8,
248, 0, 0, 8, 248, 0, 0, 8,
248, 0, 0, 0, 248, 0, 0, 0
};

int_32 samp = sample + *scale;
if ((samp < 0) || (samp > 39)) {
//LOG(LOG_SB, LOG_ERROR)("Bad ADPCM-3 sample");
if (samp < 0) samp = 0;
if (samp > 39) samp = 39;
}

int_32 ref = *reference + scaleMap[samp];
if (ref > 0xff) *reference = 0xff;
else if (ref < 0x00) *reference = 0x00;
else *reference = (byte)(ref & 0xff);
*scale = (*scale + adjustMap[samp]) & 0xff;

return (byte)*reference;
}

The decoding used, when data is written from DMA:

				if (SOUNDBLASTER.ADPCM_format) //Format specified? Use ADPCM!
{
if (SOUNDBLASTER.ADPCM_reference) //We're the reference byte?
{
SOUNDBLASTER.ADPCM_reference = 0; //No reference anymore!
SOUNDBLASTER.ADPCM_currentreference = data;
SOUNDBLASTER.ADPCM_stepsize = MIN_ADAPTIVE_STEP_SIZE; //Initialise the step size!
writefifobuffer(SOUNDBLASTER.DSPoutdata, data); //Send the current sample for rendering!
}
else //Data based on the reference?
{
switch (SOUNDBLASTER.ADPCM_format) //What format?
{
case ADPCM_FORMAT_2BIT: //Dosbox DSP_DMA_2
writefifobuffer(SOUNDBLASTER.DSPoutdata, decode_ADPCM_2_sample((data >> 6) & 0x3, &SOUNDBLASTER.ADPCM_currentreference, &SOUNDBLASTER.ADPCM_stepsize)); //Send the partial sample for rendering!
writefifobuffer(SOUNDBLASTER.DSPoutdata, decode_ADPCM_2_sample((data >> 4) & 0x3, &SOUNDBLASTER.ADPCM_currentreference, &SOUNDBLASTER.ADPCM_stepsize)); //Send the partial sample for rendering!
writefifobuffer(SOUNDBLASTER.DSPoutdata, decode_ADPCM_2_sample((data >> 2) & 0x3, &SOUNDBLASTER.ADPCM_currentreference, &SOUNDBLASTER.ADPCM_stepsize)); //Send the partial sample for rendering!
writefifobuffer(SOUNDBLASTER.DSPoutdata, decode_ADPCM_2_sample((data >> 0) & 0x3, &SOUNDBLASTER.ADPCM_currentreference, &SOUNDBLASTER.ADPCM_stepsize)); //Send the partial sample for rendering!
break;
case ADPCM_FORMAT_26BIT: //Dosbox DSP_DMA_3
writefifobuffer(SOUNDBLASTER.DSPoutdata, decode_ADPCM_3_sample((data >> 5) & 0x7, &SOUNDBLASTER.ADPCM_currentreference, &SOUNDBLASTER.ADPCM_stepsize)); //Send the partial sample for rendering!
writefifobuffer(SOUNDBLASTER.DSPoutdata, decode_ADPCM_3_sample((data >> 2) & 0x7, &SOUNDBLASTER.ADPCM_currentreference, &SOUNDBLASTER.ADPCM_stepsize)); //Send the partial sample for rendering!
writefifobuffer(SOUNDBLASTER.DSPoutdata, decode_ADPCM_3_sample((data & 3) << 0x1, &SOUNDBLASTER.ADPCM_currentreference, &SOUNDBLASTER.ADPCM_stepsize)); //Send the partial sample for rendering!
break;
case ADPCM_FORMAT_4BIT: //Dosbox DSP_DMA_4
writefifobuffer(SOUNDBLASTER.DSPoutdata, decode_ADPCM_4_sample((data >> 4) & 0xF, &SOUNDBLASTER.ADPCM_currentreference, &SOUNDBLASTER.ADPCM_stepsize)); //Send the partial sample for rendering!
writefifobuffer(SOUNDBLASTER.DSPoutdata, decode_ADPCM_4_sample(data & 0xF, &SOUNDBLASTER.ADPCM_currentreference, &SOUNDBLASTER.ADPCM_stepsize)); //Send the partial sample for rendering!
break;
default: //Unknown format?
//Ignore output!
writefifobuffer(SOUNDBLASTER.DSPoutdata, 0x80); //Send the empty sample for rendering!
break;
}
}
}
else //Normal 8-bit sample?
{
writefifobuffer(SOUNDBLASTER.DSPoutdata, data); //Send the current sample for rendering!
}
if (--SOUNDBLASTER.dataleft==0) //One data used! Finished? Give IRQ!
{
SoundBlaster_IRQ8(); //Raise the 8-bit IRQ!
if (SOUNDBLASTER.AutoInit) //Autoinit enabled?
{
SoundBlaster_DetectDMALength((byte)SOUNDBLASTER.command, SOUNDBLASTER.AutoInitBlockSize); //Reload the length of the DMA transfer to play back, in bytes!
}
}
SOUNDBLASTER.DREQ |= 2; //Wait for the next sample to be played, according to the sample rate!

Setting DREQ bit 2(the final line) makes it wait for the samples to be rendered before reasserting DREQ(which depends on the amount of samples in the buffer).

Is that behaviour correct?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 3 of 5, by superfury

User metadata
Rank l33t++
Rank
l33t++

With the latest bugfixes(ModR/M address size vs Operand size, protected mode privilege checks only on segment register loads and MOV to/from CR/DR/TR registers being fixed), Megarace(only himem.sys loaded) starts, switches to graphics mode and finally returns to MS-DOS complaining that there's not enough memory. In a system with 6MB RAM installed!

Anyone knows why this hapoens? Jepael? Dosbox developers?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 4 of 5, by vladstamate

User metadata
Rank Oldbie
Rank
Oldbie
superfury wrote:

With the latest bugfixes(ModR/M address size vs Operand size, protected mode privilege checks only on segment register loads and MOV to/from CR/DR/TR registers being fixed), Megarace(only himem.sys loaded) starts, switches to graphics mode and finally returns to MS-DOS complaining that there's not enough memory. In a system with 6MB RAM installed!

Anyone knows why this hapoens? Jepael? Dosbox developers?

I am pretty sure they mean base memory (<640k) and not high/up/xms/ems. The game's requirement is only 2Mb of memory, so 6 is enough.

What does "mem /p" show?

You could also try to run in FreeDos.

YouTube channel: https://www.youtube.com/channel/UC7HbC_nq8t1S9l7qGYL0mTA
Collection: http://www.digiloguemuseum.com/index.html
Emulator: https://sites.google.com/site/capex86/
Raytracer: https://sites.google.com/site/opaqueraytracer/

Reply 5 of 5, by superfury

User metadata
Rank l33t++
Rank
l33t++

mem /p shows(after a big list of memory locations up to address 0317A0 size 06E450 -- Free --):

654336 bytes total conventional memory
654336 bytes available to MS-DOS
547664 largest executable program size

2097152 bytes total EMS memory
2097152 bytes free EMS memory

No emm386 is loaded.

After reinstallation and reboot:

654336 bytes total conventional memory
654336 bytes available to MS-DOS
549008 largest executable program size

5636096 total contiguous extended memory
0 bytes available contiguous extended memory
5570560 bytes available XMS memory
64Kb High Memory Area available

Edit: Whoops, the first one was during XT emulation(with Inboard 386 CPU). The second one is AT with 80386 CPU.

Loading EMM386 after HIMEM.SYS crashes(force shutdown) the emulator because of an #UD.

Edit: Now retrying with the following MS-DOS 5.0a CONFIG.SYS:

DEVICE=HIMEM.SYS
REM DEVICE=EMM386.EXE
DEVICEHIGH=C:\SB\DRV\CTSB2.SYS /UNIT=0 /BLASTER=A:220 I:5 D:1
DEVICEHIGH=C:\SB\DRV\CTMMSYS.SYS
DOS=HIGH,UMB
REM ** DEVICE=D:\SB\DRV\CTSB2.SYS /UNIT=0 /BLASTER=A:220 I:5 D:1
REM ** DEVICE=D:\SB\DRV\CTMMSYS.SYS
FILES=40
REM ** files= 30
DEVICE=D:\MSDOS\LTEMM.EXE /n
DEVICE=d:\uniide\vide-cdd.sys /D:MSCD001

Although the D:\ device drivers don't exist in the current configuration.

Edit: Now the application doesn't complain about memory and simply hangs with the following screen:

342.jpg
Filename
342.jpg
File size
74.08 KiB
Views
248 views
File comment
Megarace not refusing to start with loading high device drivers.
File license
Fair use/fair dealing exception

Edit: It seems to be hanging in the BIOS somewhere(segment F000)?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io