mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-22 04:43:08 +02:00
#368 GBA remove experimental 9-bit audio support, move sound.h to platform dependent sound.cpp
This commit is contained in:
@@ -19,7 +19,6 @@
|
|||||||
#define MODE4
|
#define MODE4
|
||||||
#define USE_DIV_TABLE
|
#define USE_DIV_TABLE
|
||||||
#define ROM_READ
|
#define ROM_READ
|
||||||
//#define USE_9BIT_SOUND
|
|
||||||
|
|
||||||
#include <tonc.h>
|
#include <tonc.h>
|
||||||
#elif defined(__TNS__)
|
#elif defined(__TNS__)
|
||||||
@@ -41,8 +40,13 @@
|
|||||||
#define USE_DIV_TABLE // TODO_3DO remove
|
#define USE_DIV_TABLE // TODO_3DO remove
|
||||||
#define CPU_BIG_ENDIAN
|
#define CPU_BIG_ENDIAN
|
||||||
|
|
||||||
#define MAX_RAM (800 * 1024)
|
#define MAX_RAM_LVL (800 * 1024)
|
||||||
#define MAX_VRAM (640 * 1024)
|
#define MAX_RAM_TEX (640 * 1024)
|
||||||
|
#define MAX_RAM_CEL (MAX_FACES * sizeof(CCB))
|
||||||
|
|
||||||
|
extern void* RAM_LVL;
|
||||||
|
extern void* RAM_TEX;
|
||||||
|
extern void* RAM_CEL;
|
||||||
|
|
||||||
#include <displayutils.h>
|
#include <displayutils.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -126,6 +130,8 @@
|
|||||||
#define NAV_STEPS 1
|
#define NAV_STEPS 1
|
||||||
// the maximum of active enemies
|
// the maximum of active enemies
|
||||||
#define MAX_ENEMIES 3
|
#define MAX_ENEMIES 3
|
||||||
|
// set the maximum number of simultaneously played channels
|
||||||
|
#define SND_CHANNELS 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NAV_STEPS
|
#ifndef NAV_STEPS
|
||||||
@@ -222,7 +228,7 @@ X_INLINE int32 abs(int32 x) {
|
|||||||
extern int32 osGetSystemTimeMS();
|
extern int32 osGetSystemTimeMS();
|
||||||
extern void osJoyVibrate(int32 index, int32 L, int32 R);
|
extern void osJoyVibrate(int32 index, int32 L, int32 R);
|
||||||
extern void osSetPalette(const uint16* palette);
|
extern void osSetPalette(const uint16* palette);
|
||||||
extern void osLoadLevel(const char* name);
|
extern void* osLoadLevel(const char* name);
|
||||||
|
|
||||||
#ifdef PROFILING
|
#ifdef PROFILING
|
||||||
#define PROFILE_FRAME\
|
#define PROFILE_FRAME\
|
||||||
@@ -343,7 +349,11 @@ extern int32 fps;
|
|||||||
#define FIXED_SHIFT 14
|
#define FIXED_SHIFT 14
|
||||||
|
|
||||||
#define SND_MAX_DIST (8 * 1024)
|
#define SND_MAX_DIST (8 * 1024)
|
||||||
#define SND_CHANNELS 6
|
|
||||||
|
#ifndef SND_CHANNELS
|
||||||
|
#define SND_CHANNELS 6
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SND_FIXED_SHIFT 8
|
#define SND_FIXED_SHIFT 8
|
||||||
#define SND_VOL_SHIFT 6
|
#define SND_VOL_SHIFT 6
|
||||||
#define SND_PITCH_SHIFT 7
|
#define SND_PITCH_SHIFT 7
|
||||||
@@ -362,14 +372,8 @@ extern int32 fps;
|
|||||||
#define SND_SAMPLE_FREQ 22050
|
#define SND_SAMPLE_FREQ 22050
|
||||||
#define SND_ENCODE(x) (x)
|
#define SND_ENCODE(x) (x)
|
||||||
#define SND_DECODE(x) ((x) - 128)
|
#define SND_DECODE(x) ((x) - 128)
|
||||||
|
|
||||||
#ifdef USE_9BIT_SOUND
|
|
||||||
#define SND_MIN -255
|
|
||||||
#define SND_MAX 254
|
|
||||||
#else
|
|
||||||
#define SND_MIN -128
|
#define SND_MIN -128
|
||||||
#define SND_MAX 127
|
#define SND_MAX 127
|
||||||
#endif
|
|
||||||
#elif defined(__DOS__)
|
#elif defined(__DOS__)
|
||||||
#define SND_SAMPLES 1024
|
#define SND_SAMPLES 1024
|
||||||
#define SND_OUTPUT_FREQ 11025
|
#define SND_OUTPUT_FREQ 11025
|
||||||
@@ -580,10 +584,12 @@ struct Matrix
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Quad {
|
struct Quad {
|
||||||
|
#ifdef __3DO__
|
||||||
|
Index indices[4];
|
||||||
|
uint32 flags;
|
||||||
|
#else
|
||||||
Index indices[4];
|
Index indices[4];
|
||||||
uint16 flags;
|
uint16 flags;
|
||||||
#ifdef __3DO__
|
|
||||||
uint16 _unused;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1689,6 +1695,12 @@ enum EffectType
|
|||||||
FX_TR1_FLICKER = 16
|
FX_TR1_FLICKER = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SoundMode {
|
||||||
|
UNIQUE,
|
||||||
|
REPLAY,
|
||||||
|
LOOP
|
||||||
|
};
|
||||||
|
|
||||||
enum SoundID
|
enum SoundID
|
||||||
{
|
{
|
||||||
SND_NO = 2,
|
SND_NO = 2,
|
||||||
@@ -1866,6 +1878,8 @@ struct Level
|
|||||||
uint16 itemsCount;
|
uint16 itemsCount;
|
||||||
uint16 camerasCount;
|
uint16 camerasCount;
|
||||||
uint16 cameraFramesCount;
|
uint16 cameraFramesCount;
|
||||||
|
uint16 soundOffsetsCount;
|
||||||
|
uint16 _reserved;
|
||||||
|
|
||||||
const uint16* palette;
|
const uint16* palette;
|
||||||
const uint8* lightmap;
|
const uint8* lightmap;
|
||||||
@@ -1991,10 +2005,6 @@ extern ItemObj items[MAX_ITEMS];
|
|||||||
extern bool enableClipping;
|
extern bool enableClipping;
|
||||||
extern bool enableMaxSort;
|
extern bool enableMaxSort;
|
||||||
|
|
||||||
#ifdef __3DO__
|
|
||||||
extern uint8* VRAM_TEX;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
X_INLINE void swap(T &a, T &b) {
|
X_INLINE void swap(T &a, T &b) {
|
||||||
T tmp = a;
|
T tmp = a;
|
||||||
@@ -2162,10 +2172,17 @@ bool useSwitch(ItemObj* item, int32 timer);
|
|||||||
bool useKey(ItemObj* item, ItemObj* lara);
|
bool useKey(ItemObj* item, ItemObj* lara);
|
||||||
bool usePickup(ItemObj* item);
|
bool usePickup(ItemObj* item);
|
||||||
|
|
||||||
void musicPlay(int32 track);
|
|
||||||
void musicStop();
|
|
||||||
int32 doTutorial(ItemObj* lara, int32 track);
|
int32 doTutorial(ItemObj* lara, int32 track);
|
||||||
|
|
||||||
|
void sndInit();
|
||||||
|
void sndInitSamples();
|
||||||
|
void sndFill(uint8* buffer, int32 count);
|
||||||
|
void* sndPlaySample(int32 index, int32 volume, int32 pitch, int32 mode);
|
||||||
|
void sndPlayTrack(int32 track);
|
||||||
|
void sndStopTrack();
|
||||||
|
void sndStopSample(int32 index);
|
||||||
|
void sndStop();
|
||||||
|
|
||||||
X_INLINE void dmaFill(void *dst, uint8 value, uint32 count)
|
X_INLINE void dmaFill(void *dst, uint8 value, uint32 count)
|
||||||
{
|
{
|
||||||
ASSERT((count & 3) == 0);
|
ASSERT((count & 3) == 0);
|
||||||
|
@@ -135,7 +135,7 @@ int32 getTextWidth(const char* text)
|
|||||||
int32 w = 0;
|
int32 w = 0;
|
||||||
|
|
||||||
char c;
|
char c;
|
||||||
while (c = *text++)
|
while ((c = *text++))
|
||||||
{
|
{
|
||||||
if (c == ' ') {
|
if (c == ' ') {
|
||||||
w += 6;
|
w += 6;
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
#define H_GAME
|
#define H_GAME
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "sound.h"
|
|
||||||
#include "room.h"
|
#include "room.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
@@ -31,9 +30,8 @@ struct Game
|
|||||||
animTexFrame = 0;
|
animTexFrame = 0;
|
||||||
dynSectorsCount = 0;
|
dynSectorsCount = 0;
|
||||||
|
|
||||||
osLoadLevel(name);
|
void* data = osLoadLevel(name);
|
||||||
|
loadLevel(data);
|
||||||
loadLevel(levelData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadLevel(const void* data)
|
void loadLevel(const void* data)
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
#define H_ITEM
|
#define H_ITEM
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "sound.h"
|
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "room.h"
|
#include "room.h"
|
||||||
|
|
||||||
@@ -28,11 +27,8 @@ int32 alignOffset(int32 a, int32 b)
|
|||||||
return -(a + 1);
|
return -(a + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mixer::Sample* soundPlay(int16 id, const vec3i &pos)
|
void* soundPlay(int16 id, const vec3i &pos)
|
||||||
{
|
{
|
||||||
#ifdef __3DO__
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
// TODO gym
|
// TODO gym
|
||||||
// 0 -> 200
|
// 0 -> 200
|
||||||
// 4 -> 204
|
// 4 -> 204
|
||||||
@@ -76,13 +72,7 @@ Mixer::Sample* soundPlay(int16 id, const vec3i &pos)
|
|||||||
index += (rand_draw() * b->flags.count) >> 15;
|
index += (rand_draw() * b->flags.count) >> 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8 *data = level.soundData + level.soundOffsets[index];
|
return sndPlaySample(index, volume, pitch, b->flags.mode);
|
||||||
|
|
||||||
int32 size;
|
|
||||||
memcpy(&size, data + 40, 4); // TODO preprocess and remove wave header
|
|
||||||
data += 44;
|
|
||||||
|
|
||||||
return mixer.playSample(data, size, volume, pitch, b->flags.mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void soundStop(int16 id)
|
void soundStop(int16 id)
|
||||||
@@ -96,48 +86,10 @@ void soundStop(int16 id)
|
|||||||
|
|
||||||
for (int32 i = 0; i < b->flags.count; i++)
|
for (int32 i = 0; i < b->flags.count; i++)
|
||||||
{
|
{
|
||||||
int32 index = b->index + i;
|
sndStopSample(b->index + i);
|
||||||
|
|
||||||
const uint8 *data = level.soundData + level.soundOffsets[index];
|
|
||||||
|
|
||||||
int32 size;
|
|
||||||
memcpy(&size, data + 40, 4); // TODO preprocess and remove wave header
|
|
||||||
data += 44;
|
|
||||||
|
|
||||||
mixer.stopSample(data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void musicPlay(int32 track)
|
|
||||||
{
|
|
||||||
#ifdef __3DO__
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
if (track == 13) {
|
|
||||||
gCurTrack = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (track == gCurTrack)
|
|
||||||
return;
|
|
||||||
|
|
||||||
gCurTrack = track;
|
|
||||||
|
|
||||||
struct TrackInfo {
|
|
||||||
int32 offset;
|
|
||||||
int32 size;
|
|
||||||
} *info = (TrackInfo*)((uint8*)TRACKS_IMA + track * 8);
|
|
||||||
|
|
||||||
if (!info->size)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mixer.playMusic((uint8*)TRACKS_IMA + info->offset, info->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void musicStop()
|
|
||||||
{
|
|
||||||
mixer.stopMusic();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 ItemObj::getFrames(const AnimFrame* &frameA, const AnimFrame* &frameB, int32 &animFrameRate) const
|
int32 ItemObj::getFrames(const AnimFrame* &frameA, const AnimFrame* &frameB, int32 &animFrameRate) const
|
||||||
{
|
{
|
||||||
const Anim* anim = level.anims + animIndex;
|
const Anim* anim = level.anims + animIndex;
|
||||||
|
@@ -67,6 +67,7 @@ void readLevel_GBA(const uint8* data)
|
|||||||
for (int32 i = 0; i < level.modelsCount; i++)
|
for (int32 i = 0; i < level.modelsCount; i++)
|
||||||
{
|
{
|
||||||
const Model* model = level.models + i;
|
const Model* model = level.models + i;
|
||||||
|
ASSERT(model->type < MAX_MODELS);
|
||||||
models[model->type] = *model;
|
models[model->type] = *model;
|
||||||
}
|
}
|
||||||
level.models = models;
|
level.models = models;
|
||||||
@@ -120,9 +121,10 @@ void readLevel_GBA(const uint8* data)
|
|||||||
for (int32 i = 0; i < level.texturesCount; i++)
|
for (int32 i = 0; i < level.texturesCount; i++)
|
||||||
{
|
{
|
||||||
Texture* tex = level.textures + i;
|
Texture* tex = level.textures + i;
|
||||||
tex->data += intptr_t(VRAM_TEX);
|
tex->data += intptr_t(RAM_TEX);
|
||||||
tex->plut += intptr_t(VRAM_TEX);
|
tex->plut += intptr_t(RAM_TEX);
|
||||||
}
|
}
|
||||||
|
sndInitSamples();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1279,9 +1279,9 @@ void checkTrigger(const FloorData* fd, ItemObj* lara)
|
|||||||
|
|
||||||
if (flags.mask == ITEM_FLAGS_MASK_ALL) {
|
if (flags.mask == ITEM_FLAGS_MASK_ALL) {
|
||||||
flags.once |= FD_ONCE(data);
|
flags.once |= FD_ONCE(data);
|
||||||
musicPlay(track);
|
sndPlayTrack(track);
|
||||||
} else {
|
} else {
|
||||||
musicStop();
|
sndStopTrack();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1295,7 +1295,7 @@ void checkTrigger(const FloorData* fd, ItemObj* lara)
|
|||||||
if (gSaveGame.secrets & (1 << FD_ARGS(triggerCmd)))
|
if (gSaveGame.secrets & (1 << FD_ARGS(triggerCmd)))
|
||||||
break;
|
break;
|
||||||
gSaveGame.secrets |= (1 << FD_ARGS(triggerCmd));
|
gSaveGame.secrets |= (1 << FD_ARGS(triggerCmd));
|
||||||
musicPlay(13);
|
sndPlayTrack(13);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,206 +0,0 @@
|
|||||||
#ifndef H_SOUND
|
|
||||||
#define H_SOUND
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
void decodeIMA(IMA_STATE &state, const uint8* data, int32* buffer, int32 size);
|
|
||||||
|
|
||||||
struct Mixer
|
|
||||||
{
|
|
||||||
enum SoundMode {
|
|
||||||
UNIQUE,
|
|
||||||
REPLAY,
|
|
||||||
LOOP,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Music
|
|
||||||
{
|
|
||||||
const uint8* data;
|
|
||||||
int32 size;
|
|
||||||
int32 pos;
|
|
||||||
IMA_STATE state;
|
|
||||||
|
|
||||||
void fill(int32* buffer, int32 count)
|
|
||||||
{
|
|
||||||
int32 len = X_MIN(size - pos, count >> 1);
|
|
||||||
|
|
||||||
decodeIMA(state, data + pos, buffer, len);
|
|
||||||
|
|
||||||
pos += len;
|
|
||||||
|
|
||||||
if (pos >= size)
|
|
||||||
{
|
|
||||||
data = NULL;
|
|
||||||
memset(buffer, 0, (count - (len << 1)) * sizeof(buffer[0]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Sample
|
|
||||||
{
|
|
||||||
const uint8* data;
|
|
||||||
int32 size;
|
|
||||||
int32 pos;
|
|
||||||
int32 inc;
|
|
||||||
int32 volume;
|
|
||||||
|
|
||||||
void fill(int32* buffer, int32 count)
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
buffer[i] += SND_DECODE(data[pos >> SND_FIXED_SHIFT]) * volume;
|
|
||||||
|
|
||||||
pos += inc;
|
|
||||||
if (pos >= size)
|
|
||||||
{
|
|
||||||
// TODO LOOP
|
|
||||||
data = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Music music;
|
|
||||||
Sample channels[SND_CHANNELS];
|
|
||||||
int32 channelsCount;
|
|
||||||
|
|
||||||
#define CALC_INC (((SND_SAMPLE_FREQ << SND_FIXED_SHIFT) / SND_OUTPUT_FREQ) * pitch >> SND_PITCH_SHIFT)
|
|
||||||
|
|
||||||
Sample* playSample(const uint8* data, int32 size, int32 volume, int32 pitch, int32 mode)
|
|
||||||
{
|
|
||||||
if (mode == UNIQUE || mode == REPLAY)
|
|
||||||
{
|
|
||||||
for (int32 i = 0; i < channelsCount; i++)
|
|
||||||
{
|
|
||||||
Sample* sample = channels + i;
|
|
||||||
|
|
||||||
if (sample->data != data)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
sample->inc = CALC_INC;
|
|
||||||
sample->volume = volume;
|
|
||||||
|
|
||||||
if (mode == REPLAY)
|
|
||||||
{
|
|
||||||
sample->pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sample;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channelsCount >= SND_CHANNELS)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
#ifdef USE_9BIT_SOUND
|
|
||||||
// expand 8 to 9-bit
|
|
||||||
volume <<= 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Sample* sample = channels + channelsCount++;
|
|
||||||
sample->data = data;
|
|
||||||
sample->size = size << SND_FIXED_SHIFT;
|
|
||||||
sample->pos = 0;
|
|
||||||
sample->inc = CALC_INC;
|
|
||||||
sample->volume = volume;
|
|
||||||
|
|
||||||
return sample;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopSample(const uint8* data)
|
|
||||||
{
|
|
||||||
int32 i = channelsCount;
|
|
||||||
|
|
||||||
while (--i >= 0)
|
|
||||||
{
|
|
||||||
if (channels[i].data == data)
|
|
||||||
{
|
|
||||||
channels[i] = channels[--channelsCount];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopSamples()
|
|
||||||
{
|
|
||||||
channelsCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void playMusic(const void* data, int32 size)
|
|
||||||
{
|
|
||||||
music.data = (uint8*)data;
|
|
||||||
music.size = size;
|
|
||||||
music.pos = 0;
|
|
||||||
//music.volume = (1 << SND_VOL_SHIFT);
|
|
||||||
music.state.smp = 0;
|
|
||||||
music.state.idx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopMusic()
|
|
||||||
{
|
|
||||||
music.data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init()
|
|
||||||
{
|
|
||||||
channelsCount = 0;
|
|
||||||
music.data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill(uint8* bufferA, uint8* bufferB, int32 count)
|
|
||||||
{
|
|
||||||
#ifdef PROFILE_SOUNDTIME
|
|
||||||
PROFILE_CLEAR();
|
|
||||||
PROFILE(CNT_SOUND);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((channelsCount == 0) && !music.data)
|
|
||||||
{
|
|
||||||
dmaFill(bufferA, SND_ENCODE(0), count);
|
|
||||||
#ifdef USE_9BIT_SOUND
|
|
||||||
dmaFill(bufferB, SND_ENCODE(0), count);
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 tmp[SND_SAMPLES];
|
|
||||||
|
|
||||||
if (music.data) {
|
|
||||||
music.fill(tmp, count);
|
|
||||||
} else {
|
|
||||||
dmaFill(tmp, 0, sizeof(tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 ch = channelsCount;
|
|
||||||
while (ch--)
|
|
||||||
{
|
|
||||||
Sample* sample = channels + ch;
|
|
||||||
|
|
||||||
sample->fill(tmp, count);
|
|
||||||
|
|
||||||
if (!sample->data) {
|
|
||||||
channels[ch] = channels[--channelsCount];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32 i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
#ifdef USE_9BIT_SOUND
|
|
||||||
int32 samp = tmp[i] >> (SND_VOL_SHIFT - 1);
|
|
||||||
//samp += (rand_draw() & 1) - 1;
|
|
||||||
samp = X_CLAMP(samp, SND_MIN, SND_MAX);
|
|
||||||
|
|
||||||
bufferA[i] = SND_ENCODE((samp >> 1));
|
|
||||||
bufferB[i] = SND_ENCODE((samp >> 1) + (samp & 1));
|
|
||||||
#else
|
|
||||||
int32 samp = X_CLAMP(tmp[i] >> SND_VOL_SHIFT, SND_MIN, SND_MAX);
|
|
||||||
|
|
||||||
bufferA[i] = SND_ENCODE(samp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Mixer mixer;
|
|
||||||
|
|
||||||
#endif
|
|
@@ -22,6 +22,7 @@
|
|||||||
<ClCompile Include="..\..\fixed\common.cpp" />
|
<ClCompile Include="..\..\fixed\common.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
<ClCompile Include="render.cpp" />
|
<ClCompile Include="render.cpp" />
|
||||||
|
<ClCompile Include="sound.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\fixed\camera.h" />
|
<ClInclude Include="..\..\fixed\camera.h" />
|
||||||
@@ -36,7 +37,6 @@
|
|||||||
<ClInclude Include="..\..\fixed\nav.h" />
|
<ClInclude Include="..\..\fixed\nav.h" />
|
||||||
<ClInclude Include="..\..\fixed\object.h" />
|
<ClInclude Include="..\..\fixed\object.h" />
|
||||||
<ClInclude Include="..\..\fixed\room.h" />
|
<ClInclude Include="..\..\fixed\room.h" />
|
||||||
<ClInclude Include="..\..\fixed\sound.h" />
|
|
||||||
<ClInclude Include="rasterizer_mode13.h" />
|
<ClInclude Include="rasterizer_mode13.h" />
|
||||||
<ClInclude Include="rasterizer_mode4.h" />
|
<ClInclude Include="rasterizer_mode4.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
const void* levelData;
|
const void* levelData;
|
||||||
#elif defined(__GBA__)
|
#elif defined(__GBA__)
|
||||||
#include "TRACKS_IMA.h"
|
#include "TRACKS_IMA.h"
|
||||||
#include "LEVEL2_PKD.h"
|
#include "LEVEL1_PKD.h"
|
||||||
const void* levelData = LEVEL2_PKD;
|
const void* levelData = LEVEL1_PKD;
|
||||||
#elif defined(__TNS__)
|
#elif defined(__TNS__)
|
||||||
const void* levelData;
|
const void* levelData;
|
||||||
#endif
|
#endif
|
||||||
@@ -299,10 +299,7 @@ int32 fpsCounter = 0;
|
|||||||
void osJoyVibrate(int32 index, int32 L, int32 R) {}
|
void osJoyVibrate(int32 index, int32 L, int32 R) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EWRAM_DATA ALIGN16 uint8 soundBufferA[2 * SND_SAMPLES + 32]; // 32 bytes of silence for DMA overrun while interrupt
|
EWRAM_DATA ALIGN16 uint8 soundBuffer[2 * SND_SAMPLES + 32]; // 32 bytes of silence for DMA overrun while interrupt
|
||||||
#ifdef USE_9BIT_SOUND
|
|
||||||
EWRAM_DATA ALIGN16 uint8 soundBufferB[2 * SND_SAMPLES + 32]; // for 9-bit mixer support via Direct Mixer B channel
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32 curSoundBuffer = 0;
|
uint32 curSoundBuffer = 0;
|
||||||
|
|
||||||
@@ -311,8 +308,9 @@ HWAVEOUT waveOut;
|
|||||||
WAVEFORMATEX waveFmt = { WAVE_FORMAT_PCM, 1, SND_OUTPUT_FREQ, SND_OUTPUT_FREQ, 1, 8, sizeof(waveFmt) };
|
WAVEFORMATEX waveFmt = { WAVE_FORMAT_PCM, 1, SND_OUTPUT_FREQ, SND_OUTPUT_FREQ, 1, 8, sizeof(waveFmt) };
|
||||||
WAVEHDR waveBuf[2];
|
WAVEHDR waveBuf[2];
|
||||||
|
|
||||||
void soundInit() {
|
void soundInit()
|
||||||
mixer.init();
|
{
|
||||||
|
sndInit();
|
||||||
|
|
||||||
if (waveOutOpen(&waveOut, WAVE_MAPPER, &waveFmt, (INT_PTR)hWnd, 0, CALLBACK_WINDOW) != MMSYSERR_NOERROR) {
|
if (waveOutOpen(&waveOut, WAVE_MAPPER, &waveFmt, (INT_PTR)hWnd, 0, CALLBACK_WINDOW) != MMSYSERR_NOERROR) {
|
||||||
return;
|
return;
|
||||||
@@ -322,16 +320,17 @@ void soundInit() {
|
|||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
WAVEHDR *waveHdr = waveBuf + i;
|
WAVEHDR *waveHdr = waveBuf + i;
|
||||||
waveHdr->dwBufferLength = SND_SAMPLES;
|
waveHdr->dwBufferLength = SND_SAMPLES;
|
||||||
waveHdr->lpData = (LPSTR)(soundBufferA + i * SND_SAMPLES);
|
waveHdr->lpData = (LPSTR)(soundBuffer + i * SND_SAMPLES);
|
||||||
waveOutPrepareHeader(waveOut, waveHdr, sizeof(WAVEHDR));
|
waveOutPrepareHeader(waveOut, waveHdr, sizeof(WAVEHDR));
|
||||||
waveOutWrite(waveOut, waveHdr, sizeof(WAVEHDR));
|
waveOutWrite(waveOut, waveHdr, sizeof(WAVEHDR));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void soundFill() {
|
void soundFill()
|
||||||
|
{
|
||||||
WAVEHDR *waveHdr = waveBuf + curSoundBuffer;
|
WAVEHDR *waveHdr = waveBuf + curSoundBuffer;
|
||||||
waveOutUnprepareHeader(waveOut, waveHdr, sizeof(WAVEHDR));
|
waveOutUnprepareHeader(waveOut, waveHdr, sizeof(WAVEHDR));
|
||||||
mixer.fill((uint8*)waveHdr->lpData, NULL, SND_SAMPLES);
|
sndFill((uint8*)waveHdr->lpData, SND_SAMPLES);
|
||||||
waveOutPrepareHeader(waveOut, waveHdr, sizeof(WAVEHDR));
|
waveOutPrepareHeader(waveOut, waveHdr, sizeof(WAVEHDR));
|
||||||
waveOutWrite(waveOut, waveHdr, sizeof(WAVEHDR));
|
waveOutWrite(waveOut, waveHdr, sizeof(WAVEHDR));
|
||||||
curSoundBuffer ^= 1;
|
curSoundBuffer ^= 1;
|
||||||
@@ -339,43 +338,24 @@ void soundFill() {
|
|||||||
#elif defined(__GBA__)
|
#elif defined(__GBA__)
|
||||||
void soundInit()
|
void soundInit()
|
||||||
{
|
{
|
||||||
mixer.init();
|
sndInit();
|
||||||
|
|
||||||
REG_SOUNDCNT_X = SSTAT_ENABLE;
|
REG_SOUNDCNT_X = SSTAT_ENABLE;
|
||||||
#ifdef USE_9BIT_SOUND
|
|
||||||
REG_SOUNDCNT_H = SDS_ATMR0 | SDS_AL | SDS_AR | SDS_ARESET | SDS_A50 |
|
|
||||||
SDS_BTMR0 | SDS_BL | SDS_BR | SDS_BRESET | SDS_B50;
|
|
||||||
#else
|
|
||||||
REG_SOUNDCNT_H = SDS_ATMR0 | SDS_AL | SDS_AR | SDS_ARESET | SDS_A100;
|
REG_SOUNDCNT_H = SDS_ATMR0 | SDS_AL | SDS_AR | SDS_ARESET | SDS_A100;
|
||||||
#endif
|
|
||||||
REG_TM0D = 65536 - (16777216 / SND_OUTPUT_FREQ);
|
REG_TM0D = 65536 - (16777216 / SND_OUTPUT_FREQ);
|
||||||
REG_TM0CNT = TM_ENABLE;
|
REG_TM0CNT = TM_ENABLE;
|
||||||
REG_DMA1DAD = (u32)®_FIFO_A;
|
REG_DMA1DAD = (u32)®_FIFO_A;
|
||||||
#ifdef USE_9BIT_SOUND
|
|
||||||
REG_DMA2DAD = (u32)®_FIFO_B;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void soundFill()
|
void soundFill()
|
||||||
{
|
{
|
||||||
if (curSoundBuffer == 1) {
|
if (curSoundBuffer == 1) {
|
||||||
REG_DMA1CNT = 0;
|
REG_DMA1CNT = 0;
|
||||||
REG_DMA1SAD = (u32)soundBufferA;
|
REG_DMA1SAD = (u32)soundBuffer;
|
||||||
REG_DMA1CNT = DMA_DST_FIXED | DMA_REPEAT | DMA_16 | DMA_AT_FIFO | DMA_ENABLE;
|
REG_DMA1CNT = DMA_DST_FIXED | DMA_REPEAT | DMA_16 | DMA_AT_FIFO | DMA_ENABLE;
|
||||||
#ifdef USE_9BIT_SOUND
|
|
||||||
REG_DMA2CNT = 0;
|
|
||||||
REG_DMA2SAD = (u32)soundBufferB;
|
|
||||||
REG_DMA2CNT = DMA_DST_FIXED | DMA_REPEAT | DMA_16 | DMA_AT_FIFO | DMA_ENABLE;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mixer.fill(soundBufferA + curSoundBuffer * SND_SAMPLES,
|
sndFill(soundBuffer + curSoundBuffer * SND_SAMPLES, SND_SAMPLES);
|
||||||
#ifdef USE_9BIT_SOUND
|
|
||||||
soundBufferB + curSoundBuffer * SND_SAMPLES,
|
|
||||||
#else
|
|
||||||
NULL,
|
|
||||||
#endif
|
|
||||||
SND_SAMPLES);
|
|
||||||
curSoundBuffer ^= 1;
|
curSoundBuffer ^= 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -453,7 +433,7 @@ void vblank() {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int32 gLevelID = 2;
|
int32 gLevelID = 1;
|
||||||
|
|
||||||
static const char* gLevelNames[] = {
|
static const char* gLevelNames[] = {
|
||||||
"GYM",
|
"GYM",
|
||||||
@@ -474,10 +454,9 @@ static const char* gLevelNames[] = {
|
|||||||
// "LEVEL10C"
|
// "LEVEL10C"
|
||||||
};
|
};
|
||||||
|
|
||||||
void osLoadLevel(const char* name)
|
void* osLoadLevel(const char* name)
|
||||||
{
|
{
|
||||||
mixer.stopMusic();
|
sndStop();
|
||||||
mixer.stopSamples();
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__TNS__) || defined(__DOS__)
|
#if defined(_WIN32) || defined(__TNS__) || defined(__DOS__)
|
||||||
{
|
{
|
||||||
@@ -497,7 +476,7 @@ void osLoadLevel(const char* name)
|
|||||||
FILE *f = fopen(buf, "rb");
|
FILE *f = fopen(buf, "rb");
|
||||||
|
|
||||||
if (!f)
|
if (!f)
|
||||||
return;
|
return NULL;
|
||||||
|
|
||||||
{
|
{
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
@@ -516,7 +495,7 @@ void osLoadLevel(const char* name)
|
|||||||
{
|
{
|
||||||
FILE *f = fopen("data/TRACKS.IMA", "rb");
|
FILE *f = fopen("data/TRACKS.IMA", "rb");
|
||||||
if (!f)
|
if (!f)
|
||||||
return;
|
return NULL;
|
||||||
|
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
int32 size = ftell(f);
|
int32 size = ftell(f);
|
||||||
@@ -530,6 +509,7 @@ void osLoadLevel(const char* name)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return (void*)levelData;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
@@ -605,7 +585,7 @@ int main(void) {
|
|||||||
|
|
||||||
fastAccessReg = 0x0E000020; // fast EWRAM
|
fastAccessReg = 0x0E000020; // fast EWRAM
|
||||||
|
|
||||||
vu32* fastAccessMem = (vu32*)soundBufferA; // check EWRAM access
|
vu32* fastAccessMem = (vu32*)soundBuffer; // check EWRAM access
|
||||||
// write
|
// write
|
||||||
for (int32 i = 0; i < 16; i++)
|
for (int32 i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
|
@@ -34,6 +34,34 @@ inline void swap(T &a, T &b) {
|
|||||||
b = tmp;
|
b = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void launchApp(const char* cmdline)
|
||||||
|
{
|
||||||
|
STARTUPINFOA si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
|
||||||
|
memset(&si, 0, sizeof(si));
|
||||||
|
memset(&pi, 0, sizeof(pi));
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
|
||||||
|
CreateProcess(
|
||||||
|
NULL,
|
||||||
|
(char*)cmdline,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&si,
|
||||||
|
&pi
|
||||||
|
);
|
||||||
|
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
CloseHandle(pi.hThread);
|
||||||
|
}
|
||||||
|
|
||||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
|
||||||
@@ -312,6 +340,19 @@ struct FileStream
|
|||||||
return aligned;
|
return aligned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 align16()
|
||||||
|
{
|
||||||
|
uint32 pos = getPos();
|
||||||
|
uint32 aligned = (pos + 15) & ~15;
|
||||||
|
|
||||||
|
if (aligned != pos) {
|
||||||
|
static const uint32 zero = 0;
|
||||||
|
fwrite(&zero, 1, aligned - pos, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return aligned;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void read(T &result)
|
void read(T &result)
|
||||||
{
|
{
|
||||||
@@ -600,8 +641,7 @@ struct LevelPC
|
|||||||
struct Quad3DO
|
struct Quad3DO
|
||||||
{
|
{
|
||||||
uint16 indices[4];
|
uint16 indices[4];
|
||||||
uint16 flags;
|
uint32 flags;
|
||||||
uint16 _unused;
|
|
||||||
|
|
||||||
void write(FileStream &f) const
|
void write(FileStream &f) const
|
||||||
{
|
{
|
||||||
@@ -610,7 +650,6 @@ struct LevelPC
|
|||||||
f.write(indices[2]);
|
f.write(indices[2]);
|
||||||
f.write(indices[3]);
|
f.write(indices[3]);
|
||||||
f.write(flags);
|
f.write(flags);
|
||||||
f.write(_unused);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -636,7 +675,6 @@ struct LevelPC
|
|||||||
comp.indices[2] = indices[2];
|
comp.indices[2] = indices[2];
|
||||||
comp.indices[3] = indices[3];
|
comp.indices[3] = indices[3];
|
||||||
comp.flags = flags;
|
comp.flags = flags;
|
||||||
comp._unused = 0;
|
|
||||||
comp.write(f);
|
comp.write(f);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1373,14 +1411,16 @@ struct LevelPC
|
|||||||
uint16 index;
|
uint16 index;
|
||||||
uint16 volume;
|
uint16 volume;
|
||||||
uint16 chance;
|
uint16 chance;
|
||||||
uint16 flags;
|
uint8 flagsA;
|
||||||
|
uint8 flagsB;
|
||||||
|
|
||||||
void write(FileStream &f) const
|
void write(FileStream &f) const
|
||||||
{
|
{
|
||||||
f.write(index);
|
f.write(index);
|
||||||
f.write(volume);
|
f.write(volume);
|
||||||
f.write(chance);
|
f.write(chance);
|
||||||
f.write(flags);
|
f.write(flagsA);
|
||||||
|
f.write(flagsB);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1653,6 +1693,8 @@ struct LevelPC
|
|||||||
uint16 itemsCount;
|
uint16 itemsCount;
|
||||||
uint16 camerasCount;
|
uint16 camerasCount;
|
||||||
uint16 cameraFramesCount;
|
uint16 cameraFramesCount;
|
||||||
|
uint16 soundOffsetsCount;
|
||||||
|
uint16 _reserved;
|
||||||
|
|
||||||
uint32 palette;
|
uint32 palette;
|
||||||
uint32 lightmap;
|
uint32 lightmap;
|
||||||
@@ -1700,6 +1742,9 @@ struct LevelPC
|
|||||||
f.write(itemsCount);
|
f.write(itemsCount);
|
||||||
f.write(camerasCount);
|
f.write(camerasCount);
|
||||||
f.write(cameraFramesCount);
|
f.write(cameraFramesCount);
|
||||||
|
f.write(soundOffsetsCount);
|
||||||
|
f.write(_reserved);
|
||||||
|
|
||||||
f.write(palette);
|
f.write(palette);
|
||||||
f.write(lightmap);
|
f.write(lightmap);
|
||||||
f.write(tiles);
|
f.write(tiles);
|
||||||
@@ -1744,13 +1789,13 @@ struct LevelPC
|
|||||||
Room::VertexComp roomVertices[MAX_ROOM_VERTICES];
|
Room::VertexComp roomVertices[MAX_ROOM_VERTICES];
|
||||||
int32 roomVerticesCount;
|
int32 roomVerticesCount;
|
||||||
|
|
||||||
int32 addRoomVertex(const Room::Vertex &v)
|
int32 addRoomVertex(const Room::Vertex &v, bool ignoreG = false)
|
||||||
{
|
{
|
||||||
Room::VertexComp comp;
|
Room::VertexComp comp;
|
||||||
comp.x = v.pos.x / 1024;
|
comp.x = v.pos.x / 1024;
|
||||||
comp.y = v.pos.y / 256;
|
comp.y = v.pos.y / 256;
|
||||||
comp.z = v.pos.z / 1024;
|
comp.z = v.pos.z / 1024;
|
||||||
comp.g = v.lighting >> 5;
|
comp.g = ignoreG ? 0 : (v.lighting >> 5);
|
||||||
|
|
||||||
for (int32 i = 0; i < roomVerticesCount; i++)
|
for (int32 i = 0; i < roomVerticesCount; i++)
|
||||||
{
|
{
|
||||||
@@ -2134,6 +2179,8 @@ struct LevelPC
|
|||||||
header.itemsCount = itemsCount;
|
header.itemsCount = itemsCount;
|
||||||
header.camerasCount = camerasCount;
|
header.camerasCount = camerasCount;
|
||||||
header.cameraFramesCount = cameraFramesCount;
|
header.cameraFramesCount = cameraFramesCount;
|
||||||
|
header.soundOffsetsCount = soundOffsetsCount;
|
||||||
|
header._reserved = 0;
|
||||||
|
|
||||||
header.palette = f.align4();
|
header.palette = f.align4();
|
||||||
|
|
||||||
@@ -3338,6 +3385,8 @@ struct LevelPC
|
|||||||
header.itemsCount = itemsCount;
|
header.itemsCount = itemsCount;
|
||||||
header.camerasCount = camerasCount;
|
header.camerasCount = camerasCount;
|
||||||
header.cameraFramesCount = cameraFramesCount;
|
header.cameraFramesCount = cameraFramesCount;
|
||||||
|
header.soundOffsetsCount = soundOffsetsCount;
|
||||||
|
header._reserved = 0;
|
||||||
|
|
||||||
header.palette = 0;
|
header.palette = 0;
|
||||||
header.lightmap = 0;
|
header.lightmap = 0;
|
||||||
@@ -3394,12 +3443,72 @@ struct LevelPC
|
|||||||
{
|
{
|
||||||
Quad q = room->quads[i];
|
Quad q = room->quads[i];
|
||||||
calcQuadFlip(q);
|
calcQuadFlip(q);
|
||||||
q.indices[0] = addRoomVertex(room->vertices[q.indices[0]]);
|
|
||||||
q.indices[1] = addRoomVertex(room->vertices[q.indices[1]]);
|
|
||||||
q.indices[2] = addRoomVertex(room->vertices[q.indices[2]]);
|
|
||||||
q.indices[3] = addRoomVertex(room->vertices[q.indices[3]]);
|
|
||||||
|
|
||||||
q.write3DO(f);
|
const Room::Vertex &v0 = room->vertices[q.indices[0]];
|
||||||
|
const Room::Vertex &v1 = room->vertices[q.indices[1]];
|
||||||
|
const Room::Vertex &v2 = room->vertices[q.indices[2]];
|
||||||
|
const Room::Vertex &v3 = room->vertices[q.indices[3]];
|
||||||
|
|
||||||
|
|
||||||
|
uint32 intensity = (v0.lighting + v1.lighting + v2.lighting + v3.lighting) >> (2 + 5);
|
||||||
|
ASSERT(intensity <= 255);
|
||||||
|
|
||||||
|
q.indices[0] = addRoomVertex(v0, true);
|
||||||
|
q.indices[1] = addRoomVertex(v1, true);
|
||||||
|
q.indices[2] = addRoomVertex(v2, true);
|
||||||
|
q.indices[3] = addRoomVertex(v3, true);
|
||||||
|
|
||||||
|
vec3i a, b, n;
|
||||||
|
a.x = v1.pos.x - v0.pos.x;
|
||||||
|
a.y = v1.pos.y - v0.pos.y;
|
||||||
|
a.z = v1.pos.z - v0.pos.z;
|
||||||
|
|
||||||
|
b.x = v2.pos.x - v0.pos.x;
|
||||||
|
b.y = v2.pos.y - v0.pos.y;
|
||||||
|
b.z = v2.pos.z - v0.pos.z;
|
||||||
|
|
||||||
|
n.x = b.y * a.z - b.z * a.y;
|
||||||
|
n.y = b.z * a.x - b.x * a.z;
|
||||||
|
n.z = b.x * a.y - b.y * a.x;
|
||||||
|
|
||||||
|
if (n.x < 0) n.x = -1;
|
||||||
|
if (n.x > 0) n.x = +1;
|
||||||
|
if (n.y < 0) n.y = -1;
|
||||||
|
if (n.y > 0) n.y = +1;
|
||||||
|
if (n.z < 0) n.z = -1;
|
||||||
|
if (n.z > 0) n.z = +1;
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
int32 x, y, z;
|
||||||
|
int32 mask;
|
||||||
|
} normals[9] = {
|
||||||
|
{ -1, 0, 0, 2 << 0 },
|
||||||
|
{ 1, 0, 0, 1 << 0 },
|
||||||
|
{ 0, -1, 0, 2 << 2 },
|
||||||
|
{ 0, 1, 0, 1 << 2 },
|
||||||
|
{ 0, 0, -1, 2 << 4 },
|
||||||
|
{ 0, 0, 1, 1 << 4 }
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32 normalMask = 255;
|
||||||
|
for (int32 i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
if (n.x == normals[i].x &&
|
||||||
|
n.y == normals[i].y &&
|
||||||
|
n.z == normals[i].z)
|
||||||
|
{
|
||||||
|
normalMask = normals[i].mask;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Quad3DO comp;
|
||||||
|
comp.indices[0] = q.indices[0];
|
||||||
|
comp.indices[1] = q.indices[1];
|
||||||
|
comp.indices[2] = q.indices[2];
|
||||||
|
comp.indices[3] = q.indices[3];
|
||||||
|
comp.flags = q.flags | (normalMask << 16) | (intensity << 24);
|
||||||
|
comp.write(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
info.triangles = f.align4();
|
info.triangles = f.align4();
|
||||||
@@ -3862,7 +3971,45 @@ struct LevelPC
|
|||||||
f.writeObj(soundInfo, soundInfoCount);
|
f.writeObj(soundInfo, soundInfoCount);
|
||||||
|
|
||||||
header.soundData = f.align4();
|
header.soundData = f.align4();
|
||||||
//f.write(soundData, soundDataSize);
|
|
||||||
|
uint8* soundBuf = new uint8[2 * 1024 * 1024];
|
||||||
|
|
||||||
|
for (int32 i = 0; i < soundOffsetsCount; i++)
|
||||||
|
{
|
||||||
|
{ // save wav to the temporary file
|
||||||
|
uint8* data = soundData + soundOffsets[i];
|
||||||
|
int32 size = *(int32*)(data + 4) + 8;
|
||||||
|
|
||||||
|
FILE* f = fopen("tmp.wav", "wb");
|
||||||
|
fwrite(data, 1, size, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
launchApp("C:\\Program Files\\ffmpeg\\ffmpeg.exe -y -i tmp.wav -ac 1 -ar 4000 -acodec pcm_s8 tmp.aiff");
|
||||||
|
|
||||||
|
int32 soundSize;
|
||||||
|
{ // read converted aiff
|
||||||
|
FILE* f = fopen("tmp.aiff", "rb");
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
soundSize = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
fread(soundBuf, 1, soundSize, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update sound sample offset
|
||||||
|
soundOffsets[i] = f.align4() - header.soundData + 2;
|
||||||
|
|
||||||
|
uint16 zero = 0;
|
||||||
|
f.write(zero);
|
||||||
|
|
||||||
|
//ASSERT(soundOffsets[i] % 16 == 0);
|
||||||
|
|
||||||
|
// write aiff sound data
|
||||||
|
f.write(soundBuf, soundSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] soundBuf;
|
||||||
|
|
||||||
header.soundOffsets = f.align4();
|
header.soundOffsets = f.align4();
|
||||||
f.write(soundOffsets, soundOffsetsCount);
|
f.write(soundOffsets, soundOffsetsCount);
|
||||||
|
206
src/platform/gba/sound.cpp
Normal file
206
src/platform/gba/sound.cpp
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
void decodeIMA(IMA_STATE &state, const uint8* data, int32* buffer, int32 size);
|
||||||
|
|
||||||
|
struct Music
|
||||||
|
{
|
||||||
|
const uint8* data;
|
||||||
|
int32 size;
|
||||||
|
int32 pos;
|
||||||
|
IMA_STATE state;
|
||||||
|
|
||||||
|
void fill(int32* buffer, int32 count)
|
||||||
|
{
|
||||||
|
int32 len = X_MIN(size - pos, count >> 1);
|
||||||
|
|
||||||
|
decodeIMA(state, data + pos, buffer, len);
|
||||||
|
|
||||||
|
pos += len;
|
||||||
|
|
||||||
|
if (pos >= size)
|
||||||
|
{
|
||||||
|
data = NULL;
|
||||||
|
memset(buffer, 0, (count - (len << 1)) * sizeof(buffer[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sample
|
||||||
|
{
|
||||||
|
const uint8* data;
|
||||||
|
int32 size;
|
||||||
|
int32 pos;
|
||||||
|
int32 inc;
|
||||||
|
int32 volume;
|
||||||
|
|
||||||
|
void fill(int32* buffer, int32 count)
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
buffer[i] += SND_DECODE(data[pos >> SND_FIXED_SHIFT]) * volume;
|
||||||
|
|
||||||
|
pos += inc;
|
||||||
|
if (pos >= size)
|
||||||
|
{
|
||||||
|
// TODO LOOP
|
||||||
|
data = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Music music;
|
||||||
|
Sample channels[SND_CHANNELS];
|
||||||
|
int32 channelsCount;
|
||||||
|
|
||||||
|
#ifdef __GBA__
|
||||||
|
extern const uint8_t TRACKS_IMA[];
|
||||||
|
#else
|
||||||
|
extern const void* TRACKS_IMA;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CALC_INC (((SND_SAMPLE_FREQ << SND_FIXED_SHIFT) / SND_OUTPUT_FREQ) * pitch >> SND_PITCH_SHIFT)
|
||||||
|
|
||||||
|
void sndInit()
|
||||||
|
{
|
||||||
|
// initialized in main.cpp
|
||||||
|
}
|
||||||
|
|
||||||
|
void sndInitSamples()
|
||||||
|
{
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
void* sndPlaySample(int32 index, int32 volume, int32 pitch, int32 mode)
|
||||||
|
{
|
||||||
|
const uint8 *data = level.soundData + level.soundOffsets[index];
|
||||||
|
|
||||||
|
int32 size;
|
||||||
|
memcpy(&size, data + 40, 4); // TODO preprocess and remove wave header
|
||||||
|
data += 44;
|
||||||
|
|
||||||
|
if (mode == UNIQUE || mode == REPLAY)
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < channelsCount; i++)
|
||||||
|
{
|
||||||
|
Sample* sample = channels + i;
|
||||||
|
|
||||||
|
if (sample->data != data)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sample->inc = CALC_INC;
|
||||||
|
sample->volume = volume;
|
||||||
|
|
||||||
|
if (mode == REPLAY)
|
||||||
|
{
|
||||||
|
sample->pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelsCount >= SND_CHANNELS)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Sample* sample = channels + channelsCount++;
|
||||||
|
sample->data = data;
|
||||||
|
sample->size = size << SND_FIXED_SHIFT;
|
||||||
|
sample->pos = 0;
|
||||||
|
sample->inc = CALC_INC;
|
||||||
|
sample->volume = volume;
|
||||||
|
|
||||||
|
return sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sndPlayTrack(int32 track)
|
||||||
|
{
|
||||||
|
if (track == gCurTrack)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gCurTrack = track;
|
||||||
|
|
||||||
|
struct TrackInfo {
|
||||||
|
int32 offset;
|
||||||
|
int32 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
const TrackInfo* info = (const TrackInfo*)TRACKS_IMA + track;
|
||||||
|
|
||||||
|
if (!info->size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
music.data = (uint8*)TRACKS_IMA + info->offset;
|
||||||
|
music.size = info->size;
|
||||||
|
music.pos = 0;
|
||||||
|
//music.volume = (1 << SND_VOL_SHIFT);
|
||||||
|
music.state.smp = 0;
|
||||||
|
music.state.idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sndStopTrack()
|
||||||
|
{
|
||||||
|
music.data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sndStopSample(int32 index)
|
||||||
|
{
|
||||||
|
const uint8 *data = level.soundData + level.soundOffsets[index] + 44;
|
||||||
|
|
||||||
|
int32 i = channelsCount;
|
||||||
|
|
||||||
|
while (--i >= 0)
|
||||||
|
{
|
||||||
|
if (channels[i].data == data)
|
||||||
|
{
|
||||||
|
channels[i] = channels[--channelsCount];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sndStop()
|
||||||
|
{
|
||||||
|
channelsCount = 0;
|
||||||
|
music.data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sndFill(uint8* buffer, int32 count)
|
||||||
|
{
|
||||||
|
#ifdef PROFILE_SOUNDTIME
|
||||||
|
PROFILE_CLEAR();
|
||||||
|
PROFILE(CNT_SOUND);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((channelsCount == 0) && !music.data)
|
||||||
|
{
|
||||||
|
dmaFill(buffer, SND_ENCODE(0), count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 tmp[SND_SAMPLES];
|
||||||
|
|
||||||
|
if (music.data) {
|
||||||
|
music.fill(tmp, count);
|
||||||
|
} else {
|
||||||
|
dmaFill(tmp, 0, sizeof(tmp));
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 ch = channelsCount;
|
||||||
|
while (ch--)
|
||||||
|
{
|
||||||
|
Sample* sample = channels + ch;
|
||||||
|
|
||||||
|
sample->fill(tmp, count);
|
||||||
|
|
||||||
|
if (!sample->data) {
|
||||||
|
channels[ch] = channels[--channelsCount];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32 i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
int32 samp = X_CLAMP(tmp[i] >> SND_VOL_SHIFT, SND_MIN, SND_MAX);
|
||||||
|
buffer[i] = SND_ENCODE(samp);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user