Update libsegaapi and graphics
This commit is contained in:
parent
7fb47dc43d
commit
e9352c051a
14
README.md
14
README.md
@ -60,3 +60,17 @@ This is an emulation of the driver that games use to route sound out of the Crea
|
||||
## Config
|
||||
|
||||
A default configuration file is provided in `docs/lindbergh.conf`. It should be placed in the same folder as the game is run from. If no config file is present a default setting will be used.
|
||||
|
||||
## Installation
|
||||
|
||||
1. Make sure you have the nvidia drivers
|
||||
|
||||
```
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get install gcc-multilib
|
||||
sudo apt-get install freeglut3:i386 freeglut3-dev:i386 libglew-dev
|
||||
sudo apt-get install xorg-dev
|
||||
sudo apt-get install libopenal1 libopenal-dev
|
||||
sudo apt-get install libxmu6:i386
|
||||
sudo apt-get install libstdc++5:i386
|
||||
```
|
||||
|
@ -31,20 +31,6 @@
|
||||
//#define DUMP_WAV
|
||||
//#define DUMP_BUFFER
|
||||
|
||||
#define CHECK() \
|
||||
{ \
|
||||
printf("%s %d\n", __func__, __LINE__); \
|
||||
unsigned int err; \
|
||||
if ((err = alGetError()) != AL_NO_ERROR) \
|
||||
{ \
|
||||
printf("%s %d\n", __func__, __LINE__); \
|
||||
dbgPrint(":%i AL Error: 0x%08X\n", __LINE__, err); \
|
||||
exit(2); \
|
||||
} \
|
||||
}
|
||||
|
||||
int g_LastStatus = SEGA_SUCCESS;
|
||||
|
||||
// outrun2 will complain if these aren't present
|
||||
const GUID EAX_NULL_GUID;
|
||||
// DEFINE_GUID(EAX_NULL_GUID, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
@ -70,6 +56,7 @@ const GUID EAXPROPERTYID_EAX40_FXSlot3;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// SEGA API Parts
|
||||
void *userData;
|
||||
HAWOSEGABUFFERCALLBACK callback;
|
||||
bool synthesizer;
|
||||
@ -84,19 +71,16 @@ typedef struct
|
||||
size_t size;
|
||||
bool playing;
|
||||
bool paused;
|
||||
bool playWithSetup;
|
||||
|
||||
// OpenAL Parts
|
||||
ALuint alBuffer;
|
||||
ALuint alSource;
|
||||
|
||||
// TinySoundFont Parts
|
||||
tsf *synth;
|
||||
struct tsf_region *region;
|
||||
} segaapiContext_t;
|
||||
|
||||
// LPALBUFFERSAMPLESSOFT alBufferSamplesSOFT = NULL;
|
||||
// LPALBUFFERSUBSAMPLESSOFT alBufferSubSamplesSOFT = NULL;
|
||||
// LPALGETBUFFERSAMPLESSOFT alGetBufferSamplesSOFT = NULL;
|
||||
|
||||
#ifdef DEBUG_OUTPUT
|
||||
void dbgPrint(const char *format, ...)
|
||||
{
|
||||
@ -113,106 +97,6 @@ void dbgPrint(const char *format, ...)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DUMP_BUFFER
|
||||
static void dumpBuffer(const char *path, void *data, size_t size)
|
||||
{
|
||||
FILE *soundFile = NULL;
|
||||
|
||||
soundFile = fopen(path, "wb");
|
||||
fwrite(data, size, 1, soundFile);
|
||||
fclose(soundFile);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DUMP_WAV
|
||||
static void dumpWaveBuffer(const char *path, unsigned int channels, unsigned int sampleRate, unsigned int sampleBits, void *data, size_t size)
|
||||
{
|
||||
|
||||
struct RIFF_Header
|
||||
{
|
||||
char chunkID[4];
|
||||
long chunkSize; // size not including chunkSize or chunkID
|
||||
char format[4];
|
||||
};
|
||||
|
||||
struct WAVE_Format
|
||||
{
|
||||
char subChunkID[4];
|
||||
long subChunkSize;
|
||||
short audioFormat;
|
||||
short numChannels;
|
||||
long sampleRate;
|
||||
long byteRate;
|
||||
short blockAlign;
|
||||
short bitsPerSample;
|
||||
};
|
||||
|
||||
struct WAVE_Data
|
||||
{
|
||||
char subChunkID[4]; // should contain the word data
|
||||
long subChunk2Size; // Stores the size of the data block
|
||||
};
|
||||
|
||||
// Local Declarations
|
||||
FILE *soundFile = NULL;
|
||||
struct WAVE_Format wave_format;
|
||||
struct RIFF_Header riff_header;
|
||||
struct WAVE_Data wave_data;
|
||||
|
||||
soundFile = fopen(path, "wb");
|
||||
|
||||
// check for RIFF and WAVE tag in memeory
|
||||
riff_header.chunkID[0] = 'R';
|
||||
riff_header.chunkID[1] = 'I';
|
||||
riff_header.chunkID[2] = 'F';
|
||||
riff_header.chunkID[3] = 'F';
|
||||
riff_header.format[0] = 'W';
|
||||
riff_header.format[1] = 'A';
|
||||
riff_header.format[2] = 'V';
|
||||
riff_header.format[3] = 'E';
|
||||
|
||||
// Read in the first chunk into the struct
|
||||
fwrite(&riff_header, sizeof(struct RIFF_Header), 1, soundFile);
|
||||
|
||||
// check for fmt tag in memory
|
||||
wave_format.subChunkID[0] = 'f';
|
||||
wave_format.subChunkID[1] = 'm';
|
||||
wave_format.subChunkID[2] = 't';
|
||||
wave_format.subChunkID[3] = ' ';
|
||||
|
||||
wave_format.audioFormat = 1;
|
||||
wave_format.sampleRate = sampleRate;
|
||||
wave_format.numChannels = channels;
|
||||
wave_format.bitsPerSample = sampleBits;
|
||||
wave_format.byteRate = (sampleRate * sampleBits * channels) / 8;
|
||||
wave_format.blockAlign = (sampleBits * channels) / 8;
|
||||
wave_format.subChunkSize = 16;
|
||||
|
||||
// Read in the 2nd chunk for the wave info
|
||||
fwrite(&wave_format, sizeof(struct WAVE_Format), 1, soundFile);
|
||||
|
||||
// Read in the the last byte of data before the sound file
|
||||
|
||||
// check for data tag in memory
|
||||
wave_data.subChunkID[0] = 'd';
|
||||
wave_data.subChunkID[1] = 'a';
|
||||
wave_data.subChunkID[2] = 't';
|
||||
wave_data.subChunkID[3] = 'a';
|
||||
|
||||
wave_data.subChunk2Size = size;
|
||||
|
||||
fwrite(&wave_data, sizeof(struct WAVE_Data), 1, soundFile);
|
||||
|
||||
// Read in the sound data into the soundData variable
|
||||
fwrite(data, wave_data.subChunk2Size, 1, soundFile);
|
||||
|
||||
// clean up and return true if successful
|
||||
fclose(soundFile);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
|
||||
{
|
||||
switch (channels)
|
||||
@ -272,29 +156,24 @@ ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
|
||||
}
|
||||
|
||||
static unsigned int bufferSampleSize(segaapiContext_t *context)
|
||||
{ // printf("%s %d\n", __func__, __LINE__);
|
||||
{
|
||||
return context->channels * ((context->sampleFormat == HASF_SIGNED_16PCM) ? 2 : 1);
|
||||
}
|
||||
|
||||
static void updateBufferLoop(segaapiContext_t *context)
|
||||
{ // printf("%s %d\n", __func__, __LINE__);
|
||||
{
|
||||
if (context == NULL)
|
||||
return;
|
||||
|
||||
unsigned int sampleSize = bufferSampleSize(context);
|
||||
alSourcei(context->alSource, AL_BUFFER, AL_NONE);
|
||||
// CHECK();
|
||||
|
||||
/*
|
||||
FIXME: Re-enable, only crashed before - so fix this too..
|
||||
ALint loopPoints[] = { buffer->startLoop / sampleSize, buffer->endLoop / sampleSize };
|
||||
alBufferiv(buffer->alBuffer,AL_LOOP_POINTS_SOFT,loopPoints);
|
||||
CHECK();
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data)
|
||||
{
|
||||
alBufferData(buffer, internalformat, data, FramesToBytes(samples, channels, type), samplerate);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data, ALuint samplerate, ALenum internalformat)
|
||||
@ -350,63 +229,44 @@ static void updateBufferData(segaapiContext_t *context, unsigned int offset, siz
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (alFormat == -1)
|
||||
{
|
||||
dbgPrint("Unknown format! 0x%X with %u channels!\n", context->sampleFormat, context->channels);
|
||||
abort();
|
||||
}
|
||||
|
||||
ALint position;
|
||||
alGetSourcei(context->alSource, AL_SAMPLE_OFFSET, &position); // TODO: Patch if looping is active
|
||||
// CHECK();
|
||||
|
||||
ALint unsafe[2];
|
||||
alGetSourceiv(context->alSource, AL_BYTE_RW_OFFSETS_SOFT, unsafe); // AL_BYTE_OFFSET
|
||||
// CHECK();
|
||||
|
||||
// We should update the playing buffer
|
||||
// OpenAL doesn't want to let us do this!!
|
||||
if (offset != -1)
|
||||
{
|
||||
|
||||
alBufferSubSamplesSOFT(context->alBuffer, offset / bufferSampleSize(context), length / bufferSampleSize(context), alChannels, alType, &context->data[offset], context->sampleRate, alFormat);
|
||||
// CHECK();
|
||||
// alBufferSubSamplesSOFT(context->alBuffer, offset / bufferSampleSize(context), length / bufferSampleSize(context), alChannels, alType, &context->data[offset], context->sampleRate, alFormat);
|
||||
dbgPrint("Soft update in buffer %X at %u (%u bytes) - buffer playing at %u, unsafe region is %u to %u\n", (uintptr_t)context, offset, length, position, unsafe[0], unsafe[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
ALint position;
|
||||
alGetSourcei(context->alSource, AL_BYTE_OFFSET, &position);
|
||||
alSourcei(context->alSource, AL_BUFFER, AL_NONE);
|
||||
// CHECK();
|
||||
alBufferSamplesSOFT(context->alBuffer, context->sampleRate, alFormat, context->size / bufferSampleSize(context), alChannels, alType, context->data);
|
||||
// CHECK();
|
||||
alBufferData(context->alBuffer, alFormat, context->data, FramesToBytes(context->size / bufferSampleSize(context), alChannels, alType), context->sampleRate);
|
||||
alSourcei(context->alSource, AL_BUFFER, context->alBuffer);
|
||||
// CHECK();
|
||||
updateBufferLoop(context);
|
||||
dbgPrint("Hard update in buffer %X (%u bytes) - buffer playing at %u, unsafe region is %u to %u\n", (uintptr_t)context, context->size, position, unsafe[0], unsafe[1]);
|
||||
alSourcei(context->alSource, AL_BYTE_OFFSET, position);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DUMP_WAV
|
||||
// This dumps the buffer
|
||||
if (context->data != NULL)
|
||||
{
|
||||
uint8_t *nonZero = context->data;
|
||||
while (*nonZero++ == 0x00)
|
||||
;
|
||||
if ((nonZero - (uint8_t *)context->data) < context->size)
|
||||
{
|
||||
printf("%s %d\n", __func__, __LINE__);
|
||||
char buf[1000];
|
||||
sprintf(buf, "SAMPLE-%X-%i-%04X-%u.wav", (uintptr_t)context, context->channels, context->sampleFormat, context->sampleRate);
|
||||
dbgPrint("Writing: %s (%i)", buf, context->size);
|
||||
void *tmp = malloc(context->size);
|
||||
if (tmp != NULL)
|
||||
{
|
||||
alGetBufferSamplesSOFT(context->alBuffer, 0, context->size / bufferSampleSize(context), alChannels, alType, tmp);
|
||||
// CHECK();
|
||||
dumpWaveBuffer(buf, context->channels, context->sampleRate, (context->sampleFormat == HASF_SIGNED_16PCM) ? 16 : 8, tmp, context->size);
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
// Clear the buffer and write again
|
||||
alSourcei(context->alSource, AL_BUFFER, AL_NONE);
|
||||
alBufferData(context->alBuffer, alFormat, context->data, FramesToBytes(context->size / bufferSampleSize(context), alChannels, alType), context->sampleRate);
|
||||
alSourcei(context->alSource, AL_BUFFER, context->alBuffer);
|
||||
// updateBufferLoop(context);
|
||||
dbgPrint("Hard update in buffer %X (%u bytes) - buffer playing at %u, unsafe region is %u to %u\n", (uintptr_t)context, context->size, position, unsafe[0], unsafe[1]);
|
||||
}
|
||||
|
||||
static void resetBuffer(segaapiContext_t *context)
|
||||
@ -425,7 +285,6 @@ static void resetBuffer(segaapiContext_t *context)
|
||||
// * - No loop.
|
||||
context->loop = false;
|
||||
context->paused = false;
|
||||
context->playWithSetup = false;
|
||||
|
||||
tsf *res = (tsf *)TSF_MALLOC(sizeof(tsf));
|
||||
TSF_MEMSET(res, 0, sizeof(tsf));
|
||||
@ -456,24 +315,10 @@ static void resetBuffer(segaapiContext_t *context)
|
||||
int SEGAAPI_Play(void *hHandle)
|
||||
{
|
||||
dbgPrint("SEGAAPI_Play() 0x%x", hHandle);
|
||||
|
||||
segaapiContext_t *context = hHandle;
|
||||
if (context == NULL)
|
||||
return SEGAERR_BAD_PARAM;
|
||||
#ifdef DUMP_BUFFER
|
||||
if (context->data != NULL)
|
||||
{
|
||||
if (context->synthesizer)
|
||||
{
|
||||
if (context->data)
|
||||
{
|
||||
char filename[1000];
|
||||
sprintf(filename, "SYNTH-%X-%i-%04X-%u.bin", (uintptr_t)context, context->channels, context->sampleFormat, context->sampleRate);
|
||||
dbgPrint("Writing: %s (%i)", filename, context->size);
|
||||
dumpBuffer(filename, context->data, context->size);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
alSourcei(context->alSource, AL_LOOPING, context->loop ? AL_TRUE : AL_FALSE);
|
||||
alSourcei(context->alSource, AL_BUFFER, context->alBuffer);
|
||||
@ -554,10 +399,10 @@ int SEGAAPI_GetFormat(void *hHandle, HAWOSEFORMAT *pFormat)
|
||||
int SEGAAPI_SetSampleRate(void *hHandle, unsigned int dwSampleRate)
|
||||
{
|
||||
dbgPrint("SEGAAPI_SetSampleRate() 0x%x 0x%x", hHandle, dwSampleRate);
|
||||
|
||||
if (hHandle == NULL)
|
||||
{ // Not sure if this is correct here, but ABC currently tries to call this with a null pointer..
|
||||
return SEGAERR_BAD_HANDLE;
|
||||
}
|
||||
|
||||
segaapiContext_t *context = hHandle;
|
||||
context->sampleRate = dwSampleRate;
|
||||
updateBufferData(context, -1, -1);
|
||||
@ -926,16 +771,17 @@ int SEGAAPI_CreateBuffer(HAWOSEBUFFERCONFIG *pConfig, HAWOSEGABUFFERCALLBACK pCa
|
||||
dbgPrint("SEGAAPI_CreateBuffer() 0x%x 0x%x 0x%x 0x%x", pConfig, pCallback, dwFlags, phHandle);
|
||||
if ((phHandle == NULL) || (pConfig == NULL))
|
||||
{
|
||||
g_LastStatus = SEGAERR_BAD_POINTER;
|
||||
dbgPrint("SEGAAPI_CreateBuffer() SEGAERR_BAD_POINTER");
|
||||
return SEGAERR_BAD_POINTER;
|
||||
}
|
||||
|
||||
segaapiContext_t *context = malloc(sizeof(segaapiContext_t));
|
||||
if (context == NULL)
|
||||
{
|
||||
dbgPrint("SEGAAPI_CreateBuffer() SEGAERR_OUT_OF_MEMORY");
|
||||
return SEGAERR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// dbgPrint("SEGAAPI_CreateBuffer() allocated %i bytes",sizeof(segaapiContext_t));
|
||||
context->playing = false;
|
||||
context->callback = pCallback;
|
||||
@ -1131,38 +977,14 @@ int SEGAAPI_Init(void)
|
||||
{
|
||||
dbgPrint("SEGAAPI_Init()");
|
||||
|
||||
int res = alutInit(NULL, NULL);
|
||||
if (res == AL_FALSE)
|
||||
if (alutInit(NULL, NULL) == AL_FALSE)
|
||||
{
|
||||
dbgPrint("SEGAAPI_Init() alutInit failed");
|
||||
dbgPrint("SEGAAPI_Init() alutInit() failed!");
|
||||
return SEGAERR_FAIL;
|
||||
}
|
||||
/*
|
||||
alBufferSamplesSOFT = alGetProcAddress("alBufferSamplesSOFT");
|
||||
if (alBufferSamplesSOFT == NULL)
|
||||
{
|
||||
dbgPrint("Warning: Could not resolve AL extension!\n");
|
||||
// exit(1);
|
||||
}
|
||||
|
||||
alBufferSubSamplesSOFT = alGetProcAddress("alBufferSubSamplesSOFT");
|
||||
if (alBufferSubSamplesSOFT == NULL)
|
||||
{
|
||||
dbgPrint("Warning: Could not resolve AL extension!\n");
|
||||
// exit(1);
|
||||
}
|
||||
alGetBufferSamplesSOFT = alGetProcAddress("alGetBufferSamplesSOFT");
|
||||
if (alGetBufferSamplesSOFT == NULL)
|
||||
{
|
||||
dbgPrint("Warning: Could not resolve AL extension!\n");
|
||||
// exit(1);
|
||||
}
|
||||
*/
|
||||
SEGAAPI_SetGlobalEAXProperty((GUID *)&EAXPROPERTYID_EAX40_FXSlot2, 0, (void *)&EAX_NULL_GUID, 16);
|
||||
|
||||
SEGAAPI_SetSPDIFOutChannelRouting(0, 0);
|
||||
SEGAAPI_SetSPDIFOutChannelRouting(1, 1);
|
||||
SEGAAPI_SetSPDIFOutSampleRate(1);
|
||||
return SEGA_SUCCESS;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -76,6 +76,9 @@ Window XCreateWindow(Display *display, Window parent, int x, int y, unsigned int
|
||||
width = getConfig()->width;
|
||||
height = getConfig()->height;
|
||||
|
||||
width = 10;
|
||||
height = 10;
|
||||
|
||||
// Ensure that the windows will respond with keyboard and mouse events
|
||||
attributes->event_mask = attributes->event_mask | KeyPressMask | KeyReleaseMask | PointerMotionMask;
|
||||
attributes->override_redirect = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user