mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +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
8 changed files with 218 additions and 1 deletions
|
@ -12,6 +12,7 @@ list(APPEND SOURCE
|
|||
registers.c
|
||||
timer.c
|
||||
ps2.c
|
||||
speaker.c
|
||||
vga.c
|
||||
ntvdm.c
|
||||
ntvdm.rc
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "bios.h"
|
||||
#include "bop.h"
|
||||
#include "dos.h"
|
||||
#include "speaker.h"
|
||||
#include "vga.h"
|
||||
#include "pic.h"
|
||||
#include "ps2.h"
|
||||
|
@ -125,6 +126,12 @@ static VOID WINAPI EmulatorReadIo(PFAST486_STATE State, ULONG Port, PVOID Buffer
|
|||
break;
|
||||
}
|
||||
|
||||
case SPEAKER_CONTROL_PORT:
|
||||
{
|
||||
*(Address++) = SpeakerReadStatus();
|
||||
break;
|
||||
}
|
||||
|
||||
case VGA_AC_WRITE:
|
||||
case VGA_AC_READ:
|
||||
case VGA_SEQ_INDEX:
|
||||
|
@ -204,6 +211,12 @@ static VOID WINAPI EmulatorWriteIo(PFAST486_STATE State, ULONG Port, PVOID Buffe
|
|||
break;
|
||||
}
|
||||
|
||||
case SPEAKER_CONTROL_PORT:
|
||||
{
|
||||
SpeakerWriteCommand(*(Address++));
|
||||
break;
|
||||
}
|
||||
|
||||
case VGA_AC_WRITE:
|
||||
case VGA_AC_READ:
|
||||
case VGA_SEQ_INDEX:
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "ntvdm.h"
|
||||
#include "emulator.h"
|
||||
#include "bios.h"
|
||||
#include "speaker.h"
|
||||
#include "vga.h"
|
||||
#include "dos.h"
|
||||
#include "timer.h"
|
||||
|
@ -117,6 +118,9 @@ INT wmain(INT argc, WCHAR *argv[])
|
|||
goto Cleanup;
|
||||
}
|
||||
|
||||
/* Initialize the PC Speaker */
|
||||
SpeakerInitialize();
|
||||
|
||||
/* Initialize the VDM DOS kernel */
|
||||
if (!DosInitialize())
|
||||
{
|
||||
|
@ -133,7 +137,7 @@ INT wmain(INT argc, WCHAR *argv[])
|
|||
|
||||
/* Start the input thread */
|
||||
InputThread = CreateThread(NULL, 0, &InputThreadProc, NULL, 0, NULL);
|
||||
|
||||
|
||||
/* Set the last timer tick to the current time */
|
||||
QueryPerformanceCounter(&LastTimerTick);
|
||||
|
||||
|
@ -187,6 +191,7 @@ INT wmain(INT argc, WCHAR *argv[])
|
|||
|
||||
Cleanup:
|
||||
if (InputThread != NULL) CloseHandle(InputThread);
|
||||
SpeakerCleanup();
|
||||
BiosCleanup();
|
||||
EmulatorCleanup();
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <conio.h>
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.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 **********************************************************/
|
||||
|
||||
static PIT_CHANNEL PitChannels[PIT_CHANNELS];
|
||||
PPIT_CHANNEL PitChannel2 = &PitChannels[2];
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@ typedef struct _PIT_CHANNEL
|
|||
BYTE AccessMode;
|
||||
} PIT_CHANNEL, *PPIT_CHANNEL;
|
||||
|
||||
extern PPIT_CHANNEL PitChannel2; // Needed for PC Speaker
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID PitWriteCommand(BYTE Value);
|
||||
|
|
Loading…
Reference in a new issue