mirror of
https://github.com/reactos/reactos.git
synced 2024-08-05 02:50:55 +00:00
[NTVDM]
Start to implement a basic emulated PC speaker, using the Beep driver. svn path=/branches/ntvdm/; revision=60853
This commit is contained in:
parent
6ecc2dfd24
commit
e9f8b230a6
|
@ -12,6 +12,7 @@ list(APPEND SOURCE
|
||||||
registers.c
|
registers.c
|
||||||
timer.c
|
timer.c
|
||||||
ps2.c
|
ps2.c
|
||||||
|
speaker.c
|
||||||
vga.c
|
vga.c
|
||||||
ntvdm.c
|
ntvdm.c
|
||||||
ntvdm.rc
|
ntvdm.rc
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
#include "bop.h"
|
#include "bop.h"
|
||||||
#include "dos.h"
|
#include "dos.h"
|
||||||
|
#include "speaker.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
#include "ps2.h"
|
#include "ps2.h"
|
||||||
|
@ -125,6 +126,12 @@ static VOID WINAPI EmulatorReadIo(PFAST486_STATE State, ULONG Port, PVOID Buffer
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SPEAKER_CONTROL_PORT:
|
||||||
|
{
|
||||||
|
*(Address++) = SpeakerReadStatus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case VGA_AC_WRITE:
|
case VGA_AC_WRITE:
|
||||||
case VGA_AC_READ:
|
case VGA_AC_READ:
|
||||||
case VGA_SEQ_INDEX:
|
case VGA_SEQ_INDEX:
|
||||||
|
@ -204,6 +211,12 @@ static VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffe
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SPEAKER_CONTROL_PORT:
|
||||||
|
{
|
||||||
|
SpeakerWriteCommand(*(Address++));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case VGA_AC_WRITE:
|
case VGA_AC_WRITE:
|
||||||
case VGA_AC_READ:
|
case VGA_AC_READ:
|
||||||
case VGA_SEQ_INDEX:
|
case VGA_SEQ_INDEX:
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "ntvdm.h"
|
#include "ntvdm.h"
|
||||||
#include "emulator.h"
|
#include "emulator.h"
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
|
#include "speaker.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
#include "dos.h"
|
#include "dos.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
@ -117,6 +118,9 @@ INT wmain(INT argc, WCHAR *argv[])
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize the PC Speaker */
|
||||||
|
SpeakerInitialize();
|
||||||
|
|
||||||
/* Initialize the VDM DOS kernel */
|
/* Initialize the VDM DOS kernel */
|
||||||
if (!DosInitialize())
|
if (!DosInitialize())
|
||||||
{
|
{
|
||||||
|
@ -187,6 +191,7 @@ INT wmain(INT argc, WCHAR *argv[])
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (InputThread != NULL) CloseHandle(InputThread);
|
if (InputThread != NULL) CloseHandle(InputThread);
|
||||||
|
SpeakerCleanup();
|
||||||
BiosCleanup();
|
BiosCleanup();
|
||||||
EmulatorCleanup();
|
EmulatorCleanup();
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
165
subsystems/ntvdm/speaker.c
Normal file
165
subsystems/ntvdm/speaker.c
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Virtual DOS Machine
|
||||||
|
* FILE: speaker.c
|
||||||
|
* PURPOSE: PC Speaker emulation
|
||||||
|
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
|
||||||
|
#include "speaker.h"
|
||||||
|
#include "emulator.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
/* Extra PSDK/NDK Headers */
|
||||||
|
#include <ndk/iofuncs.h>
|
||||||
|
#include <ndk/obfuncs.h>
|
||||||
|
#include <ndk/rtlfuncs.h>
|
||||||
|
|
||||||
|
/* DDK Driver Headers */
|
||||||
|
#include <ntddbeep.h>
|
||||||
|
|
||||||
|
/* PRIVATE VARIABLES **********************************************************/
|
||||||
|
|
||||||
|
static BYTE Port61hState = 0x00;
|
||||||
|
HANDLE hBeep = NULL;
|
||||||
|
|
||||||
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
|
VOID SpeakerInitialize(VOID)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
UNICODE_STRING BeepDevice;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
|
||||||
|
/* Adapted from kernel32:Beep() */
|
||||||
|
|
||||||
|
//
|
||||||
|
// On TS systems, we need to Load Winsta.dll and call WinstationBeepOpen
|
||||||
|
// after doing a GetProcAddress for it
|
||||||
|
//
|
||||||
|
|
||||||
|
/* Open the device */
|
||||||
|
RtlInitUnicodeString(&BeepDevice, L"\\Device\\Beep");
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes, &BeepDevice, 0, NULL, NULL);
|
||||||
|
Status = NtCreateFile(&hBeep,
|
||||||
|
FILE_READ_DATA | FILE_WRITE_DATA,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
FILE_OPEN_IF,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to open Beep driver, Status 0x%08lx\n", Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID SpeakerCleanup(VOID)
|
||||||
|
{
|
||||||
|
NtClose(hBeep);
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE SpeakerReadStatus(VOID)
|
||||||
|
{
|
||||||
|
// DPRINT1("SpeakerReadStatus() == 0x%x\n", Port61hState);
|
||||||
|
return Port61hState;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID SpeakerWriteCommand(BYTE Value)
|
||||||
|
{
|
||||||
|
BOOLEAN IsConnectedToPITChannel2;
|
||||||
|
UCHAR SpeakerData;
|
||||||
|
|
||||||
|
// DPRINT1("SpeakerWriteCommand(0x%x)\n", Value);
|
||||||
|
|
||||||
|
Port61hState = Value;
|
||||||
|
IsConnectedToPITChannel2 = ((Port61hState & 0x01) != 0);
|
||||||
|
SpeakerData = (Port61hState & 0x02);
|
||||||
|
|
||||||
|
if (PitChannel2 && IsConnectedToPITChannel2)
|
||||||
|
{
|
||||||
|
/* Set bit 5 of Port 61h */
|
||||||
|
Port61hState |= 1 << 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Clear bit 5 of Port 61h */
|
||||||
|
Port61hState &= ~(1 << 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PitChannel2 && IsConnectedToPITChannel2 && (SpeakerData != 0))
|
||||||
|
{
|
||||||
|
/* Start beeping - Adapted from kernel32:Beep() */
|
||||||
|
NTSTATUS Status;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
BEEP_SET_PARAMETERS BeepSetParameters;
|
||||||
|
|
||||||
|
DWORD PitChannel2ReloadValue = PitChannel2->ReloadValue;
|
||||||
|
if (PitChannel2ReloadValue == 0) PitChannel2ReloadValue = 65536;
|
||||||
|
|
||||||
|
/* Set beep data */
|
||||||
|
BeepSetParameters.Frequency = (PIT_BASE_FREQUENCY / PitChannel2ReloadValue) *
|
||||||
|
(PitChannel2->Mode == PIT_MODE_SQUARE_WAVE ? 2 : 1);
|
||||||
|
BeepSetParameters.Duration = INFINITE;
|
||||||
|
|
||||||
|
/* Send the beep */
|
||||||
|
Status = NtDeviceIoControlFile(hBeep,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&IoStatusBlock,
|
||||||
|
IOCTL_BEEP_SET,
|
||||||
|
&BeepSetParameters,
|
||||||
|
sizeof(BeepSetParameters),
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Beep (%lu, %lu) failed, Status 0x%08lx\n",
|
||||||
|
BeepSetParameters.Frequency,
|
||||||
|
BeepSetParameters.Duration,
|
||||||
|
Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Stop beeping */
|
||||||
|
NTSTATUS Status;
|
||||||
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
|
BEEP_SET_PARAMETERS BeepSetParameters;
|
||||||
|
|
||||||
|
/* Set beep data */
|
||||||
|
BeepSetParameters.Frequency = 0x00;
|
||||||
|
BeepSetParameters.Duration = 0x00;
|
||||||
|
|
||||||
|
/* Send the beep */
|
||||||
|
Status = NtDeviceIoControlFile(hBeep,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&IoStatusBlock,
|
||||||
|
IOCTL_BEEP_SET,
|
||||||
|
&BeepSetParameters,
|
||||||
|
sizeof(BeepSetParameters),
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Beep (%lu, %lu) failed, Status 0x%08lx\n",
|
||||||
|
BeepSetParameters.Frequency,
|
||||||
|
BeepSetParameters.Duration,
|
||||||
|
Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
29
subsystems/ntvdm/speaker.h
Normal file
29
subsystems/ntvdm/speaker.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: GPL - See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Virtual DOS Machine
|
||||||
|
* FILE: speaker.h
|
||||||
|
* PURPOSE: PC Speaker emulation
|
||||||
|
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SPEAKER_H_
|
||||||
|
#define _SPEAKER_H_
|
||||||
|
|
||||||
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
|
#include "ntvdm.h"
|
||||||
|
|
||||||
|
/* DEFINES ********************************************************************/
|
||||||
|
|
||||||
|
#define SPEAKER_CONTROL_PORT 0x61
|
||||||
|
|
||||||
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
|
VOID SpeakerInitialize(VOID);
|
||||||
|
VOID SpeakerCleanup(VOID);
|
||||||
|
BYTE SpeakerReadStatus(VOID);
|
||||||
|
VOID SpeakerWriteCommand(BYTE Value);
|
||||||
|
|
||||||
|
#endif // _SPEAKER_H_
|
||||||
|
|
||||||
|
/* EOF */
|
|
@ -16,6 +16,7 @@
|
||||||
/* PRIVATE VARIABLES **********************************************************/
|
/* PRIVATE VARIABLES **********************************************************/
|
||||||
|
|
||||||
static PIT_CHANNEL PitChannels[PIT_CHANNELS];
|
static PIT_CHANNEL PitChannels[PIT_CHANNELS];
|
||||||
|
PPIT_CHANNEL PitChannel2 = &PitChannels[2];
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ typedef struct _PIT_CHANNEL
|
||||||
BYTE AccessMode;
|
BYTE AccessMode;
|
||||||
} PIT_CHANNEL, *PPIT_CHANNEL;
|
} PIT_CHANNEL, *PPIT_CHANNEL;
|
||||||
|
|
||||||
|
extern PPIT_CHANNEL PitChannel2; // Needed for PC Speaker
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
|
||||||
VOID PitWriteCommand(BYTE Value);
|
VOID PitWriteCommand(BYTE Value);
|
||||||
|
|
Loading…
Reference in a new issue