mirror of
https://github.com/pj64team/Project64-Legacy.git
synced 2026-04-02 04:36:25 +00:00
196 lines
5.6 KiB
C
196 lines
5.6 KiB
C
/*
|
|
* Project 64 - A Nintendo 64 emulator.
|
|
*
|
|
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
* Jabo (jabo@emulation64.com).
|
|
*
|
|
* pj64 homepage: www.pj64.net
|
|
*
|
|
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
* providing that this license information and copyright notice appear with
|
|
* all copies and any derived work.
|
|
*
|
|
* This software is provided 'as-is', without any express or implied
|
|
* warranty. In no event shall the authors be held liable for any damages
|
|
* arising from the use of this software.
|
|
*
|
|
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
* seek permission of the copyright holders first. Commercial use includes
|
|
* charging money for Project64 or software derived from Project64.
|
|
*
|
|
* The copyright holders request that bug fixes and improvements to the code
|
|
* should be forwarded to them so if they want them.
|
|
*
|
|
*/
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include "main.h"
|
|
#include "CPU.h"
|
|
#include "Debugger.h"
|
|
#include "plugin.h"
|
|
#include "EmulateAI.h"
|
|
#include "settings.h"
|
|
#include "resource.h"
|
|
|
|
DWORD EmuAI_DUMMY_STATUS;
|
|
DWORD EmuAI_Frequency, EmuAI_VICntFrame, EmuAI_BitRate;
|
|
DWORD EmuAI_Buffer[2];
|
|
int EmuAI_FrameRate;
|
|
double CountsPerByte;
|
|
DWORD LastVICntFrame;
|
|
|
|
int Start_COUNT;
|
|
|
|
// Hooks to the original functions from the Audio Plugin
|
|
void (__cdecl *AiDacrateChangedPlugin) ( int SystemType );
|
|
void (__cdecl *AiLenChangedPlugin) ( void );
|
|
DWORD (__cdecl *AiReadLengthPlugin) ( void );
|
|
|
|
void __cdecl EmuAI_AiLenChanged (void)
|
|
{
|
|
EmuAI_BitRate = AI_BITRATE_REG+1;
|
|
if (AI_LEN_REG == 0) return;
|
|
|
|
// Determine our COUNT cycles per byte - should only need recalculation if VICntFrame changes.
|
|
// Frequency, BitRate and FrameRate shouldn't change?
|
|
if (LastVICntFrame != EmuAI_VICntFrame && EmuAI_Frequency > 0)
|
|
{
|
|
CountsPerByte = (double)(EmuAI_FrameRate * EmuAI_VICntFrame) / (double)(EmuAI_Frequency * (EmuAI_BitRate/4));
|
|
LastVICntFrame = EmuAI_VICntFrame;
|
|
}
|
|
|
|
// Mini-hack used for Twisted Edge -- The plugin spec doesn't capture control register writes to enable DMA
|
|
if (CountsPerByte == 0) CountsPerByte = (double)(EmuAI_FrameRate * EmuAI_VICntFrame) / (double)(22050 * (16/4));
|
|
|
|
if (EmuAI_Buffer[0] == 0)
|
|
{
|
|
// Set the base
|
|
Start_COUNT = COUNT_REGISTER;
|
|
EmuAI_Buffer[0] = AI_LEN_REG&0x3FFF8;
|
|
// Set our Status Register to DMA BUSY
|
|
AI_STATUS_REG |= 0x40000000;
|
|
// Set our timer
|
|
ChangeTimer(AiTimer, (int)(CountsPerByte * (double)(EmuAI_Buffer[0])));
|
|
} else if (EmuAI_Buffer[1] == 0) {
|
|
EmuAI_Buffer[1] = AI_LEN_REG&0x3FFF8;
|
|
// Set our Status Register to FIFO FULL
|
|
AI_STATUS_REG |= 0x80000000;
|
|
} else {
|
|
AI_STATUS_REG |= 0x80000000;
|
|
DisplayError("AI FIFO FULL But still received an AI");
|
|
}
|
|
|
|
// Call our plugin to process the Length register
|
|
if (AiLenChangedPlugin != NULL) AiLenChangedPlugin();
|
|
}
|
|
|
|
DWORD __cdecl EmuAI_AiReadLength (void)
|
|
{
|
|
DWORD SetTimer, RemainingCount;
|
|
DWORD retVal = 0;
|
|
|
|
SetTimer = (DWORD)(int)(CountsPerByte * (double)(EmuAI_Buffer[0]));
|
|
RemainingCount = SetTimer - (COUNT_REGISTER - Start_COUNT);
|
|
|
|
if (EmuAI_Buffer[0] == 0) return 0;
|
|
|
|
retVal = (DWORD)((double)RemainingCount / CountsPerByte);
|
|
if (retVal < 8) retVal = 8;
|
|
|
|
AiReadLengthPlugin();
|
|
return retVal & ~0x7;
|
|
}
|
|
|
|
void __cdecl EmuAI_AiDacrateChanged (int SystemType)
|
|
{
|
|
DWORD video_clock;
|
|
|
|
switch (SystemType) {
|
|
case SYSTEM_NTSC: video_clock = 48681812; break;
|
|
case SYSTEM_PAL : video_clock = 49656530; break;
|
|
case SYSTEM_MPAL: video_clock = 48628316; break;
|
|
default : video_clock = 48681812;
|
|
}
|
|
EmuAI_Frequency = video_clock / (AI_DACRATE_REG + 1);
|
|
if ((EmuAI_Frequency > 7000) && (EmuAI_Frequency < 9000))
|
|
EmuAI_Frequency = 8000;
|
|
else if ((EmuAI_Frequency > 10000) && (EmuAI_Frequency < 12000))
|
|
EmuAI_Frequency = 11025;
|
|
else if ((EmuAI_Frequency > 21000) && (EmuAI_Frequency < 23000))
|
|
EmuAI_Frequency = 22050;
|
|
else if ((EmuAI_Frequency > 31000) && (EmuAI_Frequency < 33000))
|
|
EmuAI_Frequency = 32000;
|
|
else if ((EmuAI_Frequency > 43000) && (EmuAI_Frequency < 45000))
|
|
EmuAI_Frequency = 44100;
|
|
else if ((EmuAI_Frequency > 47000) && (EmuAI_Frequency < 49000))
|
|
EmuAI_Frequency = 48000;
|
|
|
|
if (AiDacrateChangedPlugin != NULL) AiDacrateChangedPlugin(SystemType);
|
|
}
|
|
|
|
void EmuAI_ClearAudio()
|
|
{
|
|
LastVICntFrame = 0;
|
|
CountsPerByte = 0;
|
|
EmuAI_Buffer[0] = EmuAI_Buffer[1] = 0;
|
|
EmuAI_Frequency = 0;
|
|
AI_STATUS_REG = 0;
|
|
if (AI_LEN_REG > 0)
|
|
{
|
|
Start_COUNT = COUNT_REGISTER;
|
|
AudioIntrReg |= MI_INTR_AI;
|
|
AiCheckInterrupts();
|
|
}
|
|
}
|
|
|
|
void EmuAI_InitializePluginHook()
|
|
{
|
|
LastVICntFrame = 0;
|
|
CountsPerByte = 0;
|
|
EmuAI_Buffer[0] = EmuAI_Buffer[1] = 0;
|
|
EmuAI_Frequency = 0;
|
|
if (AiDacrateChanged == EmuAI_AiDacrateChanged) return;
|
|
// Backup Old Values
|
|
AiDacrateChangedPlugin = AiDacrateChanged;
|
|
AiLenChangedPlugin = AiLenChanged;
|
|
AiReadLengthPlugin = AiReadLength;
|
|
|
|
// Need to override AiLenChanged, AiReadLength
|
|
AiDacrateChanged = EmuAI_AiDacrateChanged;
|
|
AiLenChanged = EmuAI_AiLenChanged;
|
|
AiReadLength = EmuAI_AiReadLength;
|
|
}
|
|
|
|
void EmuAI_SetFrameRate(int frameRate)
|
|
{
|
|
EmuAI_FrameRate = frameRate;
|
|
}
|
|
|
|
void EmuAI_SetVICountPerFrame(DWORD value)
|
|
{
|
|
EmuAI_VICntFrame = value;
|
|
}
|
|
|
|
void EmuAI_SetNextTimer ()
|
|
{
|
|
// Buffer Switch
|
|
EmuAI_Buffer[0] = EmuAI_Buffer[1];
|
|
EmuAI_Buffer[1] = 0;
|
|
|
|
// Remove Status Full Flag
|
|
AI_STATUS_REG &= ~0x80000000;
|
|
|
|
if (EmuAI_Buffer[0] > 0)
|
|
{
|
|
AI_STATUS_REG |= 0x40000000;
|
|
// Set our timer
|
|
ChangeTimer(AiTimer, (int)(CountsPerByte * (double)(EmuAI_Buffer[0])));
|
|
// Set the base
|
|
Start_COUNT = COUNT_REGISTER;
|
|
} else {
|
|
// Remove DMA Busy Flag
|
|
AI_STATUS_REG &= ~0x40000000;
|
|
ChangeTimer(AiTimer, 0);
|
|
}
|
|
} |