Simplify sound and add windows instructions
This commit is contained in:
parent
f2c3b79c2d
commit
ef1a152983
71
docs/windows.md
Normal file
71
docs/windows.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Windows Installation Instructions
|
||||
|
||||
Please note that this software is still in the alpha phase, and it's very unlikely any games will be fully playable.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Windows 10 build 2004 or higher
|
||||
- WSL2
|
||||
- Ubuntu 22.04
|
||||
|
||||
## Building & Installation
|
||||
|
||||
Launch Ubuntu 22.04 and and reset the root password.
|
||||
|
||||
```
|
||||
sudo passwd root
|
||||
su root
|
||||
```
|
||||
|
||||
Now that you're in the root user you can install the dependencies:
|
||||
|
||||
```
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt update && apt list --upgradable && apt upgrade
|
||||
sudo apt install wsl g++ mesa-utils cmake make-guile gcc-multilib xorg-dev libxmu6:i386 libstdc++5:i386 libopenal-dev:i386 freeglut3:i386 freeglut3-dev:i386 libglew-dev
|
||||
```
|
||||
|
||||
Now you will need to build libalut (the audio library) from source:
|
||||
|
||||
```
|
||||
git clone --recursive https://github.com/vancegroup/freealut.git
|
||||
cd freealut
|
||||
cmake . -DCMAKE_INSTALL_PREFIX:STRING="/usr" -DCMAKE_C_FLAGS:STRING="-m32 -O2"
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
Now you should add yourself to the following groups.
|
||||
|
||||
```
|
||||
sudo addgroup $USER dialout
|
||||
sudo addgroup $USER input
|
||||
```
|
||||
|
||||
Now you can clone and build the lindbergh loader repository.
|
||||
|
||||
```
|
||||
cd
|
||||
git clone https://github.com/bobbydilley/lindbergh-loader.git
|
||||
cd lindbergh-loader
|
||||
make
|
||||
```
|
||||
|
||||
You should then see the 3 .so files produced in the `build` directory.
|
||||
|
||||
## Launching a game
|
||||
|
||||
You should copy the 3 files from the `lindbergh-loader/build` directory to the directory with the game elf in.
|
||||
|
||||
Then open powershell in windows and do the following steps.
|
||||
|
||||
```
|
||||
cd C:\rom\hod4\elf
|
||||
bash
|
||||
cp ~/lindbergh-loader/build/* .
|
||||
LD_PRELOAD=lindbergh.so LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./hod4M.elf
|
||||
```
|
||||
|
||||
## Thanks
|
||||
|
||||
Thanks to dorminirko for the testing and writing of the original guide.
|
@ -10,11 +10,12 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "segaapi.h"
|
||||
#include "tsf.h"
|
||||
|
||||
//#define DEBUG_OUTPUT
|
||||
// #define DEBUG_OUTPUT
|
||||
|
||||
const GUID EAX_NULL_GUID;
|
||||
const GUID EAX_FREQUENCYSHIFTER_EFFECT;
|
||||
@ -78,122 +79,41 @@ void dbgPrint(const char *format, ...)
|
||||
}
|
||||
#endif
|
||||
|
||||
ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
|
||||
/**
|
||||
* Returns the OpenAL Format Enum from the sampleFormat and channels
|
||||
* of the SEGA API.
|
||||
*
|
||||
* @param sampleFormat SEGA API Sample Format
|
||||
* @param channels Amount of channels to use
|
||||
* @returns The OpenAL Format
|
||||
*/
|
||||
ALenum getAlFormat(unsigned int sampleFormat, unsigned int channels)
|
||||
{
|
||||
switch (channels)
|
||||
{
|
||||
case AL_MONO_SOFT:
|
||||
size *= 1;
|
||||
break;
|
||||
case AL_STEREO_SOFT:
|
||||
size *= 2;
|
||||
break;
|
||||
case AL_REAR_SOFT:
|
||||
size *= 2;
|
||||
break;
|
||||
case AL_QUAD_SOFT:
|
||||
size *= 4;
|
||||
break;
|
||||
case AL_5POINT1_SOFT:
|
||||
size *= 6;
|
||||
break;
|
||||
case AL_6POINT1_SOFT:
|
||||
size *= 7;
|
||||
break;
|
||||
case AL_7POINT1_SOFT:
|
||||
size *= 8;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case AL_BYTE_SOFT:
|
||||
size *= sizeof(ALbyte);
|
||||
break;
|
||||
case AL_UNSIGNED_BYTE_SOFT:
|
||||
size *= sizeof(ALubyte);
|
||||
break;
|
||||
case AL_SHORT_SOFT:
|
||||
size *= sizeof(ALshort);
|
||||
break;
|
||||
case AL_UNSIGNED_SHORT_SOFT:
|
||||
size *= sizeof(ALushort);
|
||||
break;
|
||||
case AL_INT_SOFT:
|
||||
size *= sizeof(ALint);
|
||||
break;
|
||||
case AL_UNSIGNED_INT_SOFT:
|
||||
size *= sizeof(ALuint);
|
||||
break;
|
||||
case AL_FLOAT_SOFT:
|
||||
size *= sizeof(ALfloat);
|
||||
break;
|
||||
case AL_DOUBLE_SOFT:
|
||||
size *= sizeof(ALdouble);
|
||||
break;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static unsigned int bufferSampleSize(SEGAContext *context)
|
||||
{
|
||||
return context->channels * ((context->sampleFormat == SIGNED_16PCM) ? 2 : 1);
|
||||
}
|
||||
|
||||
static void updateBufferLoop(SEGAContext *context)
|
||||
{
|
||||
return;
|
||||
if (context == NULL)
|
||||
return;
|
||||
|
||||
unsigned int sampleSize = bufferSampleSize(context);
|
||||
alSourcei(context->alSource, AL_BUFFER, AL_NONE);
|
||||
|
||||
/*
|
||||
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();
|
||||
*/
|
||||
}
|
||||
|
||||
static void updateBufferData(SEGAContext *context, unsigned int offset, size_t length)
|
||||
{
|
||||
|
||||
ALenum alFormat = -1;
|
||||
ALenum alChannels = -1;
|
||||
ALenum alType;
|
||||
|
||||
switch (context->sampleFormat)
|
||||
switch (sampleFormat)
|
||||
{
|
||||
case UNSIGNED_8PCM: /* Unsigned (offset 128) 8-bit PCM */
|
||||
alType = AL_BYTE_SOFT;
|
||||
switch (context->channels)
|
||||
switch (channels)
|
||||
{
|
||||
case 1:
|
||||
alFormat = AL_MONO8_SOFT;
|
||||
alChannels = AL_MONO_SOFT;
|
||||
break;
|
||||
case 2:
|
||||
alFormat = AL_STEREO8_SOFT;
|
||||
alChannels = AL_STEREO_SOFT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SIGNED_16PCM: /* Signed 16-bit PCM */
|
||||
alType = AL_SHORT_SOFT;
|
||||
switch (context->channels)
|
||||
switch (channels)
|
||||
{
|
||||
case 1:
|
||||
alFormat = AL_MONO16_SOFT;
|
||||
alChannels = AL_MONO_SOFT;
|
||||
break;
|
||||
case 2:
|
||||
alFormat = AL_STEREO16_SOFT;
|
||||
alChannels = AL_STEREO_SOFT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -204,31 +124,18 @@ static void updateBufferData(SEGAContext *context, unsigned int offset, size_t l
|
||||
|
||||
if (alFormat == -1)
|
||||
{
|
||||
printf("SEGAAPI: Unknown format! 0x%X with %u channels!\n", context->sampleFormat, context->channels);
|
||||
printf("SEGAAPI Fatal Error: Unknown format - 0x%X with %d channels!\n", sampleFormat, channels);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (offset != -1)
|
||||
{
|
||||
|
||||
unsigned int sampleSize = bufferSampleSize(context);
|
||||
|
||||
ALint position;
|
||||
alGetSourcei(context->alSource, AL_SAMPLE_OFFSET, &position);
|
||||
|
||||
alSourcei(context->alSource, AL_BUFFER, AL_NONE);
|
||||
// alBufferData(context->alBuffer, alFormat, context->data + (offset / sampleSize), FramesToBytes(context->size / bufferSampleSize(context), alChannels, alType), context->sampleRate);
|
||||
alBufferData(context->alBuffer, alFormat, context->data, FramesToBytes(context->size / bufferSampleSize(context), alChannels, alType), context->sampleRate);
|
||||
alSourcei(context->alSource, AL_BUFFER, context->alBuffer);
|
||||
alSourcei(context->alSource, AL_SAMPLE_OFFSET, position);
|
||||
return;
|
||||
}
|
||||
return alFormat;
|
||||
}
|
||||
|
||||
static void updateBufferData(SEGAContext *context, unsigned int offset, size_t length)
|
||||
{
|
||||
alSourcei(context->alSource, AL_BUFFER, AL_NONE);
|
||||
alBufferData(context->alBuffer, alFormat, context->data, FramesToBytes(context->size / bufferSampleSize(context), alChannels, alType), context->sampleRate);
|
||||
alBufferData(context->alBuffer, getAlFormat(context->sampleFormat, context->channels), context->data, context->size, context->sampleRate);
|
||||
alSourcei(context->alSource, AL_BUFFER, context->alBuffer);
|
||||
|
||||
// updateBufferLoop(context);
|
||||
}
|
||||
|
||||
static void resetBuffer(SEGAContext *context)
|
||||
@ -253,12 +160,10 @@ static void resetBuffer(SEGAContext *context)
|
||||
TSF_MEMSET(res, 0, sizeof(tsf));
|
||||
res->presetNum = 0;
|
||||
res->outSampleRate = context->sampleRate;
|
||||
|
||||
context->synth = res;
|
||||
|
||||
struct tsf_region *region = malloc(sizeof(struct tsf_region));
|
||||
memset(region, 0, sizeof(struct tsf_region));
|
||||
|
||||
tsf_region_clear(region, 0);
|
||||
|
||||
region->ampenv.delay = 0;
|
||||
@ -270,9 +175,9 @@ static void resetBuffer(SEGAContext *context)
|
||||
|
||||
context->region = region;
|
||||
|
||||
// * - Buffer is in the stop state.
|
||||
// * - Play position is set to 0.
|
||||
updateBufferData(context, -1, -1);
|
||||
alSourcei(context->alSource, AL_BUFFER, AL_NONE);
|
||||
alSourcei(context->alSource, AL_BYTE_OFFSET, 0);
|
||||
alSourceStop(context->alSource);
|
||||
}
|
||||
|
||||
int SEGAAPI_Play(void *hHandle)
|
||||
@ -280,23 +185,26 @@ int SEGAAPI_Play(void *hHandle)
|
||||
dbgPrint("SEGAAPI_Play() 0x%x", hHandle);
|
||||
|
||||
SEGAContext *context = hHandle;
|
||||
|
||||
if (context == NULL)
|
||||
return SEGA_ERROR_BAD_PARAM;
|
||||
|
||||
// alSourcei(context->alSource, AL_LOOPING, context->loop ? AL_TRUE : AL_FALSE);
|
||||
alSourcei(context->alSource, AL_LOOPING, AL_FALSE);
|
||||
alSourcei(context->alSource, AL_BUFFER, context->alBuffer);
|
||||
alSourcePlay(context->alSource);
|
||||
|
||||
return SEGA_SUCCESS;
|
||||
}
|
||||
|
||||
int SEGAAPI_Pause(void *hHandle)
|
||||
{
|
||||
dbgPrint("SEGAAPI_Pause() 0x%x", hHandle);
|
||||
|
||||
SEGAContext *context = hHandle;
|
||||
|
||||
if (context == NULL)
|
||||
return SEGA_ERROR_BAD_PARAM;
|
||||
|
||||
alSourcePause(context->alSource);
|
||||
|
||||
return SEGA_SUCCESS;
|
||||
}
|
||||
|
||||
@ -305,6 +213,7 @@ int SEGAAPI_Stop(void *hHandle)
|
||||
dbgPrint("SEGAAPI_Stop() 0x%x", hHandle);
|
||||
|
||||
SEGAContext *context = hHandle;
|
||||
|
||||
if (context == NULL)
|
||||
return SEGA_ERROR_BAD_PARAM;
|
||||
|
||||
@ -316,12 +225,14 @@ int SEGAAPI_Stop(void *hHandle)
|
||||
int SEGAAPI_PlayWithSetup(void *hHandle)
|
||||
{
|
||||
dbgPrint("SEGAAPI_PlayWithSetup() 0x%x", hHandle);
|
||||
|
||||
SEGAContext *context = hHandle;
|
||||
|
||||
if (context == NULL)
|
||||
return SEGA_ERROR_BAD_PARAM;
|
||||
alSourcei(context->alSource, AL_LOOPING, context->loop ? AL_TRUE : AL_FALSE);
|
||||
alSourcei(context->alSource, AL_BUFFER, context->alBuffer);
|
||||
|
||||
alSourcePlay(context->alSource);
|
||||
|
||||
return SEGA_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@ -343,6 +254,7 @@ PlaybackStatus SEGAAPI_GetPlaybackStatus(void *hHandle)
|
||||
case AL_PAUSED:
|
||||
return PLAYBACK_STATUS_PAUSE;
|
||||
case AL_INITIAL:
|
||||
return PLAYBACK_STATUS_ACTIVE;
|
||||
case AL_STOPPED:
|
||||
return PLAYBACK_STATUS_STOP;
|
||||
default:
|
||||
@ -373,7 +285,9 @@ int SEGAAPI_SetSampleRate(void *hHandle, unsigned int dwSampleRate)
|
||||
|
||||
SEGAContext *context = hHandle;
|
||||
context->sampleRate = dwSampleRate;
|
||||
|
||||
updateBufferData(context, -1, -1);
|
||||
|
||||
return SEGA_SUCCESS;
|
||||
}
|
||||
|
||||
@ -384,6 +298,7 @@ unsigned int SEGAAPI_GetSampleRate(void *hHandle)
|
||||
return SEGA_ERROR_BAD_HANDLE;
|
||||
|
||||
SEGAContext *context = hHandle;
|
||||
|
||||
return context->sampleRate;
|
||||
}
|
||||
|
||||
@ -441,7 +356,7 @@ int SEGAAPI_SetSendLevel(void *hHandle, unsigned int dwChannel, unsigned int dwS
|
||||
unsigned int SEGAAPI_GetSendLevel(void *hHandle, unsigned int dwChannel, unsigned int dwSend)
|
||||
{
|
||||
dbgPrint("SEGAAPI_GetSendLevel() 0x%x 0x%x 0x%x", hHandle, dwChannel, dwSend);
|
||||
return 0;
|
||||
return SEGA_SUCCESS;
|
||||
}
|
||||
|
||||
int SEGAAPI_SetChannelVolume(void *hHandle, unsigned int dwChannel, unsigned int dwVolume)
|
||||
@ -510,7 +425,6 @@ int SEGAAPI_SetStartLoopOffset(void *hHandle, unsigned int dwOffset)
|
||||
SEGAContext *context = hHandle;
|
||||
|
||||
context->startLoop = dwOffset;
|
||||
updateBufferLoop(context);
|
||||
|
||||
return SEGA_SUCCESS;
|
||||
}
|
||||
@ -534,7 +448,6 @@ int SEGAAPI_SetEndLoopOffset(void *hHandle, unsigned int dwOffset)
|
||||
|
||||
SEGAContext *context = hHandle;
|
||||
context->endLoop = dwOffset;
|
||||
updateBufferLoop(context);
|
||||
|
||||
return SEGA_SUCCESS;
|
||||
}
|
||||
@ -580,8 +493,9 @@ int SEGAAPI_SetLoopState(void *hHandle, int loop)
|
||||
return SEGA_ERROR_BAD_HANDLE;
|
||||
|
||||
SEGAContext *context = hHandle;
|
||||
|
||||
context->loop = loop;
|
||||
alSourcei(context->alSource, AL_LOOPING, context->loop ? AL_TRUE : AL_FALSE);
|
||||
|
||||
return SEGA_SUCCESS;
|
||||
}
|
||||
|
||||
@ -682,6 +596,7 @@ int SEGAAPI_SetReleaseState(void *hHandle, int enterReleasePhase)
|
||||
|
||||
SEGAContext *context = hHandle;
|
||||
|
||||
|
||||
if (!enterReleasePhase)
|
||||
return SEGA_SUCCESS;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user