Import 0.5.1
This commit is contained in:
parent
1f86fdea2d
commit
100218a3c2
|
@ -1,3 +1,8 @@
|
|||
* release 0.5.1
|
||||
- added looping for DOS .prf music
|
||||
- changed audio mixer to stereo
|
||||
- updated timings for cutscenes
|
||||
|
||||
* release 0.5.0
|
||||
- added CD-i widescreen mode (flashp*bob)
|
||||
- added support for DOS .prf music (Adlib, MT32)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
REminiscence README
|
||||
Release version: 0.5.0
|
||||
Release version: 0.5.1
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
|
|
@ -120,7 +120,8 @@ bool CpcPlayer::mix(int16_t *buf, int len) {
|
|||
for (int i = 0; i < len; ++i) {
|
||||
_sampleL = decodeSDX2(_sampleL, readSampleData());
|
||||
_sampleR = decodeSDX2(_sampleR, readSampleData());
|
||||
*buf++ = (_sampleL + _sampleR) / 2;
|
||||
*buf++ = _sampleL;
|
||||
*buf++ = _sampleR;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
15
cutscene.cpp
15
cutscene.cpp
|
@ -35,15 +35,16 @@ const uint8_t *Cutscene::getPolygonData() const {
|
|||
return _res->_pol;
|
||||
}
|
||||
|
||||
void Cutscene::sync() {
|
||||
void Cutscene::sync(int frameDelay) {
|
||||
if (_stub->_pi.quit) {
|
||||
return;
|
||||
}
|
||||
if (_stub->_pi.dbgMask & PlayerInput::DF_FASTMODE) {
|
||||
return;
|
||||
}
|
||||
static const int frameHz = 60;
|
||||
const int32_t delay = _stub->getTimeStamp() - _tstamp;
|
||||
const int32_t pause = _frameDelay * TIMER_SLICE - delay;
|
||||
const int32_t pause = frameDelay * (1000 / frameHz) - delay;
|
||||
if (pause > 0) {
|
||||
_stub->sleep(pause);
|
||||
}
|
||||
|
@ -72,7 +73,7 @@ void Cutscene::updatePalette() {
|
|||
}
|
||||
|
||||
void Cutscene::updateScreen() {
|
||||
sync();
|
||||
sync(_frameDelay - 1);
|
||||
updatePalette();
|
||||
SWAP(_frontPage, _backPage);
|
||||
_stub->copyRect(0, 0, _vid->_w, _vid->_h, _frontPage, _vid->_w);
|
||||
|
@ -343,7 +344,7 @@ void Cutscene::op_waitForSync() {
|
|||
_creditsSlowText = false;
|
||||
} else {
|
||||
_frameDelay = fetchNextCmdByte() * 4;
|
||||
sync(); // XXX handle input
|
||||
sync(_frameDelay);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,7 +471,7 @@ void Cutscene::op_drawCaptionText() {
|
|||
} else if (_id == kCineEspions) {
|
||||
// cutscene relies on drawCaptionText opcodes for timing
|
||||
_frameDelay = 100;
|
||||
sync();
|
||||
sync(_frameDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1257,7 +1258,7 @@ void Cutscene::playText(const char *str) {
|
|||
_stub->_pi.backspace = false;
|
||||
break;
|
||||
}
|
||||
_stub->sleep(TIMER_SLICE);
|
||||
_stub->sleep(30);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1467,7 +1468,7 @@ void Cutscene::playSet(const uint8_t *p, int offset) {
|
|||
|
||||
_stub->copyRect(0, 0, _vid->_w, _vid->_h, _backPage, _vid->_w);
|
||||
_stub->updateScreen(0);
|
||||
const int diff = 6 * TIMER_SLICE - (_stub->getTimeStamp() - timestamp);
|
||||
const int diff = 90 - (_stub->getTimeStamp() - timestamp);
|
||||
_stub->sleep((diff < 16) ? 16 : diff);
|
||||
_stub->processEvents();
|
||||
if (_stub->_pi.backspace) {
|
||||
|
|
|
@ -19,8 +19,7 @@ struct Cutscene {
|
|||
|
||||
enum {
|
||||
MAX_VERTICES = 128,
|
||||
NUM_OPCODES = 15,
|
||||
TIMER_SLICE = 15
|
||||
NUM_OPCODES = 15
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -58,7 +57,8 @@ struct Cutscene {
|
|||
static const uint8_t _creditsDataDOS[];
|
||||
static const uint8_t _creditsDataAmiga[];
|
||||
static const uint16_t _creditsCutSeq[];
|
||||
static const uint8_t _musicTable[];
|
||||
static const uint8_t _musicTableDOS[];
|
||||
static const uint8_t _musicTableAmiga[];
|
||||
static const uint8_t _protectionShapeData[];
|
||||
static const Text _frTextsTable[];
|
||||
static const Text _enTextsTable[];
|
||||
|
@ -122,7 +122,7 @@ struct Cutscene {
|
|||
const uint8_t *getCommandData() const;
|
||||
const uint8_t *getPolygonData() const;
|
||||
|
||||
void sync();
|
||||
void sync(int delay);
|
||||
void copyPalette(const uint8_t *pal, uint16_t num);
|
||||
void updatePalette();
|
||||
void updateScreen();
|
||||
|
|
27
game.cpp
27
game.cpp
|
@ -133,7 +133,6 @@ void Game::run() {
|
|||
_skillLevel = _menu._skill;
|
||||
_currentLevel = _menu._level;
|
||||
}
|
||||
_mix.stopMusic();
|
||||
break;
|
||||
case kResourceTypeAmiga:
|
||||
displayTitleScreenAmiga();
|
||||
|
@ -143,6 +142,7 @@ void Game::run() {
|
|||
displayTitleScreenMac(Menu::kMacTitleScreen_Flashback);
|
||||
break;
|
||||
}
|
||||
_mix.stopMusic();
|
||||
}
|
||||
if (_stub->_pi.quit) {
|
||||
break;
|
||||
|
@ -544,7 +544,18 @@ void Game::playCutscene(int id) {
|
|||
}
|
||||
}
|
||||
}
|
||||
_mix.playMusic(Cutscene::_musicTable[_cut._id]);
|
||||
if (_res.isAmiga()) {
|
||||
const int num = Cutscene::_musicTableAmiga[_cut._id * 2];
|
||||
if (num != 0xFF) {
|
||||
const int bpm = Cutscene::_musicTableAmiga[_cut._id * 2 + 1];
|
||||
_mix.playMusic(num, bpm);
|
||||
}
|
||||
} else {
|
||||
const int num = Cutscene::_musicTableDOS[_cut._id];
|
||||
if (num != 0xFF) {
|
||||
_mix.playMusic(num);
|
||||
}
|
||||
}
|
||||
_cut.play();
|
||||
if (id == 0xD && !_cut._interrupted) {
|
||||
if (!_res.isAmiga()) {
|
||||
|
@ -1713,6 +1724,18 @@ void Game::loadLevelData() {
|
|||
char name[64];
|
||||
snprintf(name, sizeof(name), "DUMP/level%d_room%02d.bmp", _currentLevel, i);
|
||||
saveBMP(name, _vid._backLayer, palette, _vid._w, _vid._h);
|
||||
|
||||
memcpy(_vid._frontLayer, _vid._backLayer, _vid._layerSize);
|
||||
for (int y = 0; y < 7; ++y) {
|
||||
for (int x = 0; x < 16; ++x) {
|
||||
const uint8_t num = _res._ctData[0x100 + _currentRoom * 0x70 + y * 16 + x];
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%d", num);
|
||||
_vid.drawString(buf, x * 16, y * 36 + 8, 0xE7);
|
||||
}
|
||||
}
|
||||
snprintf(name, sizeof(name), "DUMP/level%d_room%02d_grid.bmp", _currentLevel, i);
|
||||
saveBMP(name, _vid._frontLayer, palette, _vid._w, _vid._h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
3
intern.h
3
intern.h
|
@ -52,8 +52,7 @@ inline int16_t S8_to_S16(int a) {
|
|||
} else if (a > 127) {
|
||||
return 32767;
|
||||
} else {
|
||||
const uint8_t u8 = (a ^ 0x80);
|
||||
return ((u8 << 8) | u8) - 32768;
|
||||
return ((uint8_t)a) * 257;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
12
main.cpp
12
main.cpp
|
@ -260,12 +260,16 @@ int main(int argc, char *argv[]) {
|
|||
{ LANG_JP, "JP" },
|
||||
{ -1, 0 }
|
||||
};
|
||||
for (int i = 0; languages[i].str; ++i) {
|
||||
int i = 0;
|
||||
for (; languages[i].str; ++i) {
|
||||
if (strcasecmp(languages[i].str, optarg) == 0) {
|
||||
forcedLanguage = languages[i].lang;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!languages[i].str) {
|
||||
warning("Invalid language '%s'", optarg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
|
@ -286,12 +290,16 @@ int main(int argc, char *argv[]) {
|
|||
{ MODE_MT32, "mt32" },
|
||||
{ -1, 0 }
|
||||
};
|
||||
for (int i = 0; drivers[i].str; ++i) {
|
||||
int i = 0;
|
||||
for (; drivers[i].str; ++i) {
|
||||
if (strcasecmp(drivers[i].str, optarg) == 0) {
|
||||
midiDriver = drivers[i].mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!drivers[i].str) {
|
||||
warning("Invalid MIDI driver '%s'", optarg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -6,10 +6,15 @@
|
|||
#include "midi_parser.h"
|
||||
#include "util.h"
|
||||
|
||||
static uint32_t readVLQ(File *f) {
|
||||
void MidiTrack::rewind() {
|
||||
endOfTrack = false;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
static uint32_t readVLQ(const uint8_t *data, uint32_t& offset) {
|
||||
uint32_t value = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
const uint8_t b = f->readByte();
|
||||
const uint8_t b = data[offset++];
|
||||
value = (value << 7) | (b & 0x7F);
|
||||
if ((b & 0x80) == 0) {
|
||||
break;
|
||||
|
@ -18,39 +23,42 @@ static uint32_t readVLQ(File *f) {
|
|||
return value;
|
||||
}
|
||||
|
||||
static void loadTrk(File *f, int len, MidiTrack &track) {
|
||||
const uint32_t end = f->tell() + len;
|
||||
while (f->tell() < end) {
|
||||
MidiEvent ev;
|
||||
ev.timestamp = readVLQ(f);
|
||||
ev.command = f->readByte();
|
||||
const MidiEvent *MidiTrack::nextEvent() {
|
||||
while (offset < size) {
|
||||
MidiEvent &ev = event;
|
||||
ev.timestamp = readVLQ(data, offset);
|
||||
ev.command = data[offset++];
|
||||
switch (ev.command & 0xF0) {
|
||||
case MIDI_COMMAND_NOTE_OFF:
|
||||
case MIDI_COMMAND_NOTE_ON:
|
||||
ev.param1 = f->readByte();
|
||||
ev.param2 = f->readByte();
|
||||
//fprintf(stdout, "\t Note %s: note %d vel %d timestamp %d\n", (((ev.command & 0xF0) == MIDI_COMMAND_NOTE_OFF) ? "Off" : "On"), ev.param1, ev.param2, ev.timestamp);
|
||||
ev.param1 = data[offset++];
|
||||
ev.param2 = data[offset++];
|
||||
debug(DBG_MIDI, "Note %s: note %d vel %d timestamp %d", (((ev.command & 0xF0) == MIDI_COMMAND_NOTE_OFF) ? "Off" : "On"), ev.param1, ev.param2, ev.timestamp);
|
||||
break;
|
||||
case MIDI_COMMAND_PROGRAM_CHANGE:
|
||||
ev.param1 = f->readByte();
|
||||
//fprintf(stdout, "\t Program %d timestamp %d\n", ev.param1, ev.timestamp);
|
||||
ev.param1 = data[offset++];
|
||||
debug(DBG_MIDI, "Program %d timestamp %d", ev.param1, ev.timestamp);
|
||||
break;
|
||||
case MIDI_COMMAND_CHANNEL_PRESSURE:
|
||||
ev.param1 = f->readByte();
|
||||
//fprintf(stdout, "\t Channel pressure %d timestamp %d\n", ev.param1, ev.timestamp);
|
||||
ev.param1 = data[offset++];
|
||||
debug(DBG_MIDI, "Channel pressure %d timestamp %d", ev.param1, ev.timestamp);
|
||||
break;
|
||||
case MIDI_COMMAND_PITCH_BEND:
|
||||
ev.param1 = f->readByte();
|
||||
ev.param2 = f->readByte();
|
||||
//fprintf(stdout, "\t Pitch Bend %d,%d\n", ev.param1, ev.param2);
|
||||
ev.param1 = data[offset++];
|
||||
ev.param2 = data[offset++];
|
||||
debug(DBG_MIDI, "Pitch Bend %d,%d", ev.param1, ev.param2);
|
||||
break;
|
||||
case MIDI_COMMAND_SYSEX:
|
||||
if (ev.command == 0xFF) {
|
||||
f->readByte(); /* type */
|
||||
const int len = readVLQ(f);
|
||||
f->seek(f->tell() + len);
|
||||
//fprintf(stdout, "\t SysEx timestamp %d\n", ev.timestamp);
|
||||
const int num = data[offset++];
|
||||
const int len = readVLQ(data, offset);
|
||||
offset += len;
|
||||
debug(DBG_MIDI, "SysEx timestamp %d", ev.timestamp);
|
||||
assert(ev.timestamp == 0);
|
||||
if (num == MIDI_SYSEX_END_OF_TRACK) {
|
||||
endOfTrack = true;
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* fall-through */
|
||||
|
@ -58,14 +66,22 @@ static void loadTrk(File *f, int len, MidiTrack &track) {
|
|||
warning("Unhandled MIDI command 0x%x", ev.command);
|
||||
break;
|
||||
}
|
||||
track.events.push(ev);
|
||||
return &event;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MidiParser::MidiParser() {
|
||||
memset(_tracks, 0, sizeof(_tracks));
|
||||
_tracksCount = 0;
|
||||
}
|
||||
|
||||
void MidiParser::loadMid(File *f) {
|
||||
for (int i = 0; i < MAX_TRACKS; ++i) {
|
||||
_tracks[i].events = std::queue<MidiEvent>();
|
||||
free(_tracks[i].data);
|
||||
_tracks[i].data = 0;
|
||||
}
|
||||
memset(_tracks, 0, sizeof(_tracks));
|
||||
_tracksCount = 0;
|
||||
char tag[4];
|
||||
f->read(tag, 4);
|
||||
|
@ -73,18 +89,26 @@ void MidiParser::loadMid(File *f) {
|
|||
const uint32_t len = f->readUint32BE();
|
||||
assert(len == 6);
|
||||
f->readByte();
|
||||
/* const int type = */ f->readByte();
|
||||
const int type = f->readByte();
|
||||
const int tracksCount = f->readUint16BE();
|
||||
assert(tracksCount <= MAX_TRACKS);
|
||||
/* const int ppqn = */ f->readUint16BE();
|
||||
//fprintf(stdout, "MThd type %d tracks %d ppqn %d len %d\n", type, tracksCount, ppqn, len);
|
||||
const int ppqn = f->readUint16BE();
|
||||
debug(DBG_MIDI, "MThd type %d tracks %d ppqn %d len %d", type, tracksCount, ppqn, len);
|
||||
for (int i = 0; i < tracksCount; ++i) {
|
||||
f->read(tag, 4);
|
||||
assert(memcmp(tag, "MTrk", 4) == 0);
|
||||
const uint32_t len = f->readUint32BE();
|
||||
//fprintf(stdout, "Track #%d len %d\n", i, len);
|
||||
loadTrk(f, len, _tracks[i]);
|
||||
//fprintf(stdout, "Track #%d events %ld\n", i, track.events.size());
|
||||
debug(DBG_MIDI, "Track #%d len %d", i, len);
|
||||
MidiTrack *track = &_tracks[i];
|
||||
track->data = (uint8_t *)malloc(len);
|
||||
if (!track->data) {
|
||||
warning("Failed to allocate %d bytes for MIDI track %d", len, i);
|
||||
} else {
|
||||
track->endOfTrack = false;
|
||||
track->offset = 0;
|
||||
track->size = len;
|
||||
f->read(track->data, len);
|
||||
}
|
||||
}
|
||||
_tracksCount = tracksCount;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#ifndef MIDI_PARSER_H__
|
||||
#define MIDI_PARSER_H__
|
||||
|
||||
#include <queue>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MIDI_COMMAND_NOTE_OFF 0x80
|
||||
|
@ -12,6 +11,8 @@
|
|||
#define MIDI_COMMAND_PITCH_BEND 0xE0
|
||||
#define MIDI_COMMAND_SYSEX 0xF0 /* unused */
|
||||
|
||||
#define MIDI_SYSEX_END_OF_TRACK 0x2F
|
||||
|
||||
struct MidiEvent {
|
||||
uint32_t timestamp;
|
||||
uint8_t command;
|
||||
|
@ -20,7 +21,13 @@ struct MidiEvent {
|
|||
};
|
||||
|
||||
struct MidiTrack {
|
||||
std::queue<MidiEvent> events;
|
||||
bool endOfTrack;
|
||||
uint8_t *data;
|
||||
uint32_t offset, size;
|
||||
MidiEvent event;
|
||||
|
||||
void rewind();
|
||||
const MidiEvent *nextEvent();
|
||||
};
|
||||
|
||||
struct File;
|
||||
|
@ -28,6 +35,9 @@ struct File;
|
|||
#define MAX_TRACKS 16
|
||||
|
||||
struct MidiParser {
|
||||
|
||||
MidiParser();
|
||||
|
||||
void loadMid(File *f);
|
||||
|
||||
int _tracksCount;
|
||||
|
|
19
mixer.cpp
19
mixer.cpp
|
@ -90,8 +90,8 @@ static bool isMusicSfx(int num) {
|
|||
return (num >= 68 && num <= 75);
|
||||
}
|
||||
|
||||
void Mixer::playMusic(int num) {
|
||||
debug(DBG_SND, "Mixer::playMusic(%d)", num);
|
||||
void Mixer::playMusic(int num, int tempo) {
|
||||
debug(DBG_SND, "Mixer::playMusic(%d, %d)", num, tempo);
|
||||
int trackNum = -1;
|
||||
if (num == 1) { // menu screen
|
||||
trackNum = 2;
|
||||
|
@ -119,7 +119,7 @@ void Mixer::playMusic(int num) {
|
|||
_musicType = MT_SFX;
|
||||
}
|
||||
} else { // cutscene
|
||||
_mod.play(num);
|
||||
_mod.play(num, tempo);
|
||||
if (_mod._playing) {
|
||||
_musicType = MT_MOD;
|
||||
return;
|
||||
|
@ -156,7 +156,7 @@ void Mixer::stopMusic() {
|
|||
break;
|
||||
}
|
||||
_musicType = MT_NONE;
|
||||
if (_musicTrack != -1) {
|
||||
if (_musicTrack > 2) { // do not resume menu music
|
||||
switch (_backgroundMusicType) {
|
||||
case MT_OGG:
|
||||
_ogg.resumeTrack();
|
||||
|
@ -194,18 +194,21 @@ void Mixer::mix(int16_t *out, int len) {
|
|||
MixerChannel *ch = &_channels[i];
|
||||
if (ch->active) {
|
||||
for (int pos = 0; pos < len; ++pos) {
|
||||
if ((ch->chunkPos >> FRAC_BITS) >= (ch->chunk.len - 1)) {
|
||||
const uint32_t cpos = ch->chunkPos >> FRAC_BITS;
|
||||
if (cpos >= ch->chunk.len) {
|
||||
ch->active = false;
|
||||
break;
|
||||
}
|
||||
const int sample = ch->chunk.getPCM(ch->chunkPos >> FRAC_BITS) * ch->volume / Mixer::MAX_VOLUME;
|
||||
out[pos] = ADDC_S16(out[pos], S8_to_S16(sample));
|
||||
const int sample8 = ch->chunk.getPCM(cpos) * ch->volume / Mixer::MAX_VOLUME;
|
||||
const int sample16 = S8_to_S16(sample8);
|
||||
out[2 * pos] = ADDC_S16(out[2 * pos], sample16);
|
||||
out[2 * pos + 1] = ADDC_S16(out[2 * pos + 1], sample16);
|
||||
ch->chunkPos += ch->chunkInc;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (kUseNr) {
|
||||
nr(out, len);
|
||||
nr(out, len * 2); // stereo
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
mixer.h
2
mixer.h
|
@ -84,7 +84,7 @@ struct Mixer {
|
|||
bool isPlaying(const uint8_t *data) const;
|
||||
uint32_t getSampleRate() const;
|
||||
void stopAll();
|
||||
void playMusic(int num);
|
||||
void playMusic(int num, int tempo = 0);
|
||||
void stopMusic();
|
||||
void mix(int16_t *buf, int len);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ struct ModPlayer_impl {
|
|||
|
||||
ModPlugFile *_mf;
|
||||
ModPlug_Settings _settings;
|
||||
int _songTempo;
|
||||
bool _repeatIntro;
|
||||
|
||||
ModPlayer_impl()
|
||||
|
@ -26,7 +27,7 @@ struct ModPlayer_impl {
|
|||
memset(&_settings, 0, sizeof(_settings));
|
||||
ModPlug_GetSettings(&_settings);
|
||||
_settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION;
|
||||
_settings.mChannels = 1;
|
||||
_settings.mChannels = 2;
|
||||
_settings.mBits = 16;
|
||||
_settings.mFrequency = rate;
|
||||
_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
|
||||
|
@ -59,7 +60,7 @@ struct ModPlayer_impl {
|
|||
ModPlug_SeekOrder(_mf, 1);
|
||||
_repeatIntro = false;
|
||||
}
|
||||
const int count = ModPlug_Read(_mf, buf, len * sizeof(int16_t));
|
||||
const int count = ModPlug_Read(_mf, buf, len * sizeof(int16_t) * 2);
|
||||
// setting mLoopCount to non-zero does not trigger any looping in
|
||||
// my test and ModPlug_Read returns 0.
|
||||
// looking at the libmodplug-0.8.8 tarball, it seems the variable
|
||||
|
@ -82,6 +83,7 @@ struct ModPlayer_impl {
|
|||
NUM_TRACKS = 4,
|
||||
NUM_PATTERNS = 128,
|
||||
FRAC_BITS = 12,
|
||||
BASE_TEMPO = 125,
|
||||
PAULA_FREQ = 3546897
|
||||
};
|
||||
|
||||
|
@ -234,7 +236,7 @@ bool ModPlayer_impl::load(File *f) {
|
|||
_currentTick = 0;
|
||||
_patternDelay = 0;
|
||||
_songSpeed = 6;
|
||||
_songTempo = 125;
|
||||
_songTempo = BASE_TEMPO;
|
||||
_patternLoopPos = 0;
|
||||
_patternLoopCount = -1;
|
||||
_samplesLeft = 0;
|
||||
|
@ -506,6 +508,7 @@ void ModPlayer_impl::handleEffect(int trackNum, bool tick) {
|
|||
tk->volume = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xD: // delay sample
|
||||
if (!tick) {
|
||||
tk->delayCounter = effectY;
|
||||
|
@ -616,8 +619,11 @@ void ModPlayer_impl::mixSamples(int16_t *buf, int samplesLen) {
|
|||
curLen = 0;
|
||||
}
|
||||
while (count--) {
|
||||
const int out = si->getPCM(pos >> FRAC_BITS) * tk->volume / 64;
|
||||
*mixbuf = ADDC_S16(*mixbuf, S8_to_S16(out));
|
||||
const int sample8 = si->getPCM(pos >> FRAC_BITS) * tk->volume / 64;
|
||||
const int sample16 = S8_to_S16(sample8);
|
||||
*mixbuf = ADDC_S16(*mixbuf, sample16);
|
||||
++mixbuf;
|
||||
*mixbuf = ADDC_S16(*mixbuf, sample16);
|
||||
++mixbuf;
|
||||
pos += deltaPos;
|
||||
}
|
||||
|
@ -628,9 +634,9 @@ void ModPlayer_impl::mixSamples(int16_t *buf, int samplesLen) {
|
|||
}
|
||||
|
||||
bool ModPlayer_impl::mix(int16_t *buf, int len) {
|
||||
memset(buf, 0, sizeof(int16_t) * len);
|
||||
memset(buf, 0, sizeof(int16_t) * len * 2); // stereo
|
||||
if (_playing) {
|
||||
const int samplesPerTick = _mixingRate / (50 * _songTempo / 125);
|
||||
const int samplesPerTick = _mixingRate / (50 * _songTempo / BASE_TEMPO);
|
||||
while (len != 0) {
|
||||
if (_samplesLeft == 0) {
|
||||
handleTick();
|
||||
|
@ -643,7 +649,7 @@ bool ModPlayer_impl::mix(int16_t *buf, int len) {
|
|||
_samplesLeft -= count;
|
||||
len -= count;
|
||||
mixSamples(buf, count);
|
||||
buf += count;
|
||||
buf += count * 2; // stereo
|
||||
}
|
||||
}
|
||||
return _playing;
|
||||
|
@ -659,20 +665,24 @@ ModPlayer::~ModPlayer() {
|
|||
delete _impl;
|
||||
}
|
||||
|
||||
void ModPlayer::play(int num) {
|
||||
if (num < _modulesFilesCount) {
|
||||
void ModPlayer::play(int num, int tempo) {
|
||||
if (num * 2 < _namesCount) {
|
||||
File f;
|
||||
for (uint8_t i = 0; i < ARRAYSIZE(_modulesFiles[num]); ++i) {
|
||||
if (f.open(_modulesFiles[num][i], "rb", _fs)) {
|
||||
_impl->init(_mix->getSampleRate());
|
||||
if (_impl->load(&f)) {
|
||||
_impl->_repeatIntro = (num == 0) && !_isAmiga;
|
||||
_mix->setPremixHook(mixCallback, _impl);
|
||||
_playing = true;
|
||||
}
|
||||
if (!f.open(_names[num * 2], "rb", _fs)) {
|
||||
const char *p = _names[num * 2 + 1];
|
||||
char name[32];
|
||||
snprintf(name, sizeof(name), "mod.flashback-%s", p ? p : _names[num * 2]);
|
||||
if (!f.open(name, "rb", _fs)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_impl->init(_mix->getSampleRate());
|
||||
if (_impl->load(&f)) {
|
||||
_impl->_songTempo = tempo;
|
||||
_impl->_repeatIntro = (num == 0) && !_isAmiga;
|
||||
_mix->setPremixHook(mixCallback, _impl);
|
||||
_playing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ struct ModPlayer_impl;
|
|||
struct ModPlayer {
|
||||
|
||||
static const uint16_t _periodTable[];
|
||||
static const char *_modulesFiles[][2];
|
||||
static const int _modulesFilesCount;
|
||||
static const char *_names[];
|
||||
static const int _namesCount;
|
||||
|
||||
bool _isAmiga;
|
||||
bool _playing;
|
||||
|
@ -28,7 +28,7 @@ struct ModPlayer {
|
|||
ModPlayer(Mixer *mixer, FileSystem *fs);
|
||||
~ModPlayer();
|
||||
|
||||
void play(int num);
|
||||
void play(int num, int tempo);
|
||||
void stop();
|
||||
|
||||
static bool mixCallback(void *param, int16_t *buf, int len);
|
||||
|
|
|
@ -119,8 +119,9 @@ struct OggDecoder_impl {
|
|||
case 2:
|
||||
assert((len & 3) == 0);
|
||||
for (int i = 0; i < len / 2; i += 2) {
|
||||
const int16_t s16 = (_readBuf[i] + _readBuf[i + 1]) / 2;
|
||||
*dst = ADDC_S16(*dst, s16);
|
||||
*dst = ADDC_S16(*dst, _readBuf[i]);
|
||||
++dst;
|
||||
*dst = ADDC_S16(*dst, _readBuf[i + 1]);
|
||||
++dst;
|
||||
}
|
||||
break;
|
||||
|
@ -128,6 +129,8 @@ struct OggDecoder_impl {
|
|||
for (int i = 0; i < len / 2; ++i) {
|
||||
*dst = ADDC_S16(*dst, _readBuf[i]);
|
||||
++dst;
|
||||
*dst = ADDC_S16(*dst, _readBuf[i]);
|
||||
++dst;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -187,8 +190,9 @@ struct OggDecoder_impl {
|
|||
if (_decodedSamplesLen != 0) {
|
||||
const int len = MIN(_decodedSamplesLen, samples);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
const int sample = (_decodedSamples[0][i] + _decodedSamples[1][i]) / 2;
|
||||
*dst = ADDC_S16(*dst, ((sample * kMusicVolume) >> 8));
|
||||
*dst = ADDC_S16(*dst, ((_decodedSamples[0][i] * kMusicVolume) >> 8));
|
||||
++dst;
|
||||
*dst = ADDC_S16(*dst, ((_decodedSamples[1][i] * kMusicVolume) >> 8));
|
||||
++dst;
|
||||
}
|
||||
total += len;
|
||||
|
@ -229,8 +233,9 @@ struct OggDecoder_impl {
|
|||
for (int i = 0; i < len; ++i) {
|
||||
const int l = int(outputs[0][i] * 32768 + .5);
|
||||
const int r = int(outputs[1][i] * 32768 + .5);
|
||||
const int sample = (l + r) / 2;
|
||||
*dst = ADDC_S16(*dst, ((sample * kMusicVolume) >> 8));
|
||||
*dst = ADDC_S16(*dst, ((l * kMusicVolume) >> 8));
|
||||
++dst;
|
||||
*dst = ADDC_S16(*dst, ((r * kMusicVolume) >> 8));
|
||||
++dst;
|
||||
}
|
||||
if (count > remain) {
|
||||
|
@ -270,12 +275,15 @@ OggPlayer::~OggPlayer() {
|
|||
_impl = 0;
|
||||
}
|
||||
|
||||
// https://www.amigaremix.com/remix/191
|
||||
static const char *kMenuThemeRemix = "deadly_cookie_-_flashback.ogg";
|
||||
|
||||
bool OggPlayer::playTrack(int num) {
|
||||
stopTrack();
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "track%02d.ogg", num);
|
||||
if (_impl->load(buf, _fs, _mix->getSampleRate())) {
|
||||
debug(DBG_INFO, "Playing '%s'", buf);
|
||||
if (_impl->load(buf, _fs, _mix->getSampleRate())
|
||||
|| (num == 2 && _impl->load(kMenuThemeRemix, _fs, _mix->getSampleRate()))) {
|
||||
_mix->setPremixHook(mixCallback, this);
|
||||
return true;
|
||||
}
|
||||
|
|
31
piege.cpp
31
piege.cpp
|
@ -1641,21 +1641,24 @@ int Game::pge_o_unk0x71(ObjectOpcodeArgs *args) {
|
|||
}
|
||||
|
||||
int Game::pge_o_unk0x72(ObjectOpcodeArgs *args) {
|
||||
int8_t *var4 = &_res._ctData[0x100] + args->pge->room_location * 0x70;
|
||||
var4 += (((args->pge->pos_y / 36) & ~1) + args->a) * 16 + (args->pge->pos_x + 8) / 16;
|
||||
int8_t *grid_data = &_res._ctData[0x100] + args->pge->room_location * 0x70;
|
||||
int16_t pge_pos_y = ((args->pge->pos_y / 36) & ~1) + args->a;
|
||||
int16_t pge_pos_x = (args->pge->pos_x + 8) >> 4;
|
||||
grid_data += pge_pos_y * 16 + pge_pos_x;
|
||||
|
||||
CollisionSlot2 *_di = _col_slots2Next;
|
||||
int _cx = 0x100;
|
||||
while (_di && _cx != 0) {
|
||||
if (_di->unk2 != var4) {
|
||||
int count = 256; // ARRAYSIZE(_col_slots2)
|
||||
while (_di && count != 0) {
|
||||
if (_di->unk2 != grid_data) {
|
||||
_di = _di->next_slot;
|
||||
--_cx;
|
||||
--count;
|
||||
} else {
|
||||
memcpy(_di->unk2, _di->data_buf, _di->data_size + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0xFFFF; // XXX var4;
|
||||
// original returns the pointer to ctData
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
int Game::pge_o_unk0x73(ObjectOpcodeArgs *args) {
|
||||
|
@ -2079,7 +2082,21 @@ int Game::pge_updateCollisionState(LivePGE *pge, int16_t pge_dy, uint8_t value)
|
|||
memset(grid_data, value, pge_collision_data_len);
|
||||
return 1;
|
||||
} else {
|
||||
// the increment looks wrong but matches the DOS disassembly
|
||||
//
|
||||
// seg000:667B inc cx
|
||||
// seg000:667C mov si, bx
|
||||
// seg000:667E mov bx, [bx+t_collision_slot2.next_slot]
|
||||
// seg000:6680 loop loc_0_1665B
|
||||
//
|
||||
// interestingly Amiga does not have it
|
||||
//
|
||||
// CODE:000042BA movea.l a4,a5
|
||||
// CODE:000042BC movea.l 0(a4),a4
|
||||
// CODE:000042C0 dbf d0,loc_4290
|
||||
|
||||
++i;
|
||||
|
||||
slot1 = slot1->next_slot;
|
||||
if (--i == 0) {
|
||||
break;
|
||||
|
|
|
@ -167,8 +167,10 @@ void PrfPlayer::play() {
|
|||
for (int i = 0; i < _parser._tracksCount; ++i) {
|
||||
PrfTrack *current_track = &_tracks[i];
|
||||
MidiTrack *track = &_parser._tracks[i];
|
||||
MidiEvent ev = track->events.front();
|
||||
current_track->counter = ev.timestamp;
|
||||
track->rewind();
|
||||
const MidiEvent *ev = track->nextEvent();
|
||||
current_track->counter = ev ? ev->timestamp : 0;
|
||||
current_track->counter2 = current_track->counter % _prfData.timerMod;
|
||||
}
|
||||
_timerTick = _musicTick = 0;
|
||||
_samplesLeft = 0;
|
||||
|
@ -233,7 +235,7 @@ void PrfPlayer::adlibNoteOff(int track, int note, int velocity) {
|
|||
void PrfPlayer::handleTick() {
|
||||
for (int i = 0; i < _parser._tracksCount; ++i) {
|
||||
MidiTrack *track = &_parser._tracks[i];
|
||||
if (track->events.size() == 0) {
|
||||
if (track->endOfTrack) {
|
||||
continue;
|
||||
}
|
||||
const int track_index = i;
|
||||
|
@ -242,12 +244,8 @@ void PrfPlayer::handleTick() {
|
|||
--current_track->counter;
|
||||
continue;
|
||||
}
|
||||
next_event:
|
||||
MidiEvent ev = track->events.front();
|
||||
track->events.pop();
|
||||
if (current_track->loop_flag) {
|
||||
track->events.push(ev);
|
||||
}
|
||||
while (1) {
|
||||
const MidiEvent &ev = track->event;
|
||||
switch (ev.command & 0xF0) {
|
||||
case MIDI_COMMAND_NOTE_OFF: {
|
||||
int note = ev.param1;
|
||||
|
@ -358,14 +356,25 @@ next_event:
|
|||
warning("Unhandled MIDI event command 0x%x", ev.command);
|
||||
break;
|
||||
}
|
||||
if (track->events.size() != 0) {
|
||||
ev = track->events.front();
|
||||
current_track->counter = ev.timestamp;
|
||||
if (current_track->counter == 0) {
|
||||
goto next_event;
|
||||
const MidiEvent *next = track->nextEvent();
|
||||
if (!next) {
|
||||
if (current_track->loop_flag == 0) {
|
||||
track->rewind();
|
||||
const MidiEvent *next = track->nextEvent();
|
||||
if (next) {
|
||||
current_track->counter = _prfData.timerMod - current_track->counter2 + next->timestamp - 1;
|
||||
current_track->counter2 = next->timestamp % _prfData.timerMod;
|
||||
}
|
||||
}
|
||||
--current_track->counter;
|
||||
break;
|
||||
}
|
||||
current_track->counter = next->timestamp;
|
||||
current_track->counter2 = (current_track->counter + current_track->counter2) % _prfData.timerMod;
|
||||
if (current_track->counter != 0) {
|
||||
--current_track->counter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,19 +386,13 @@ int PrfPlayer::readSamples(int16_t *samples, int count) {
|
|||
const int total = count;
|
||||
while (count != 0) {
|
||||
if (_samplesLeft == 0) {
|
||||
//++_timerTick;
|
||||
//if (_timerTick == _prfData.timerTicks) {
|
||||
//fprintf(stdout, "musicTick #%d of %d\n", _musicTick, _prfData.totalDurationTicks);
|
||||
handleTick();
|
||||
//_timerTick = 0;
|
||||
if (_prfData.totalDurationTicks != 0) {
|
||||
++_musicTick;
|
||||
if (_musicTick == _prfData.totalDurationTicks + 1) {
|
||||
debug(DBG_PRF, "End of music");
|
||||
//break;
|
||||
}
|
||||
handleTick();
|
||||
if (_prfData.totalDurationTicks != 0) {
|
||||
++_musicTick;
|
||||
if (_musicTick == _prfData.totalDurationTicks + 1) {
|
||||
debug(DBG_PRF, "End of music");
|
||||
}
|
||||
//}
|
||||
}
|
||||
_samplesLeft = _samplesPerTick * _prfData.timerTicks;
|
||||
}
|
||||
const int len = (count < _samplesLeft) ? count : _samplesLeft;
|
||||
|
@ -406,16 +409,6 @@ bool PrfPlayer::mixCallback(void *param, int16_t *buf, int len) {
|
|||
}
|
||||
|
||||
bool PrfPlayer::mix(int16_t *buf, int len) {
|
||||
int16_t *p = (int16_t *)alloca(len * sizeof(int16_t) * 2);
|
||||
if (p) {
|
||||
const int count = readSamples(p, len);
|
||||
/* stereo to mono */
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const int16_t l = *p++;
|
||||
const int16_t r = *p++;
|
||||
buf[i] = CLIP((l + r) / 2, -32768, 32767);
|
||||
}
|
||||
return count != 0;
|
||||
}
|
||||
return false;
|
||||
const int count = readSamples(buf, len);
|
||||
return count != 0;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ struct PrfData {
|
|||
struct PrfTrack {
|
||||
uint8_t instrument_num;
|
||||
uint32_t counter;
|
||||
uint32_t counter2;
|
||||
uint8_t hw_channel_num;
|
||||
uint8_t mt32_program_num;
|
||||
uint8_t loop_flag;
|
||||
|
|
|
@ -334,8 +334,12 @@ bool SeqPlayer::mix(int16_t *buf, int samples) {
|
|||
}
|
||||
while (_soundQueue && samples > 0) {
|
||||
const int count = MIN(samples, _soundQueue->size - _soundQueue->read);
|
||||
memcpy(buf, _soundQueue->data + _soundQueue->read, count * sizeof(int16_t));
|
||||
buf += count;
|
||||
const int16_t *src = (const int16_t *)(_soundQueue->data + _soundQueue->read);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const int16_t sample = *src++;
|
||||
*buf++ = sample;
|
||||
*buf++ = sample;
|
||||
}
|
||||
_soundQueue->read += count;
|
||||
if (_soundQueue->read == _soundQueue->size) {
|
||||
SoundBufferQueue *next = _soundQueue->next;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
static const int kMasterVolume = 64 * 3;
|
||||
|
||||
// 12 dB/oct Butterworth low-pass filter at 3.3 kHz
|
||||
static const bool kLowPassFilter = true;
|
||||
static const bool kLowPassFilter = false;
|
||||
|
||||
#define NZEROS 2
|
||||
#define NPOLES 2
|
||||
|
@ -151,8 +151,11 @@ void SfxPlayer::mixSamples(int16_t *buf, int samplesLen) {
|
|||
curLen = 0;
|
||||
}
|
||||
while (count--) {
|
||||
const int out = si->getPCM(pos >> FRAC_BITS) * si->vol / kMasterVolume;
|
||||
*mixbuf = ADDC_S16(*mixbuf, S8_to_S16(out));
|
||||
const int sample8 = si->getPCM(pos >> FRAC_BITS) * si->vol / kMasterVolume;
|
||||
const int sample16 = S8_to_S16(sample8);
|
||||
*mixbuf = ADDC_S16(*mixbuf, sample16);
|
||||
++mixbuf;
|
||||
*mixbuf = ADDC_S16(*mixbuf, sample16);
|
||||
++mixbuf;
|
||||
pos += deltaPos;
|
||||
}
|
||||
|
@ -163,7 +166,7 @@ void SfxPlayer::mixSamples(int16_t *buf, int samplesLen) {
|
|||
}
|
||||
|
||||
bool SfxPlayer::mix(int16_t *buf, int len) {
|
||||
memset(buf, 0, sizeof(int16_t) * len);
|
||||
memset(buf, 0, sizeof(int16_t) * len * 2); // stereo
|
||||
if (_playing) {
|
||||
const int samplesPerTick = _mix->getSampleRate() / 50;
|
||||
while (len != 0) {
|
||||
|
@ -179,9 +182,9 @@ bool SfxPlayer::mix(int16_t *buf, int len) {
|
|||
len -= count;
|
||||
mixSamples(buf, count);
|
||||
if (kLowPassFilter) {
|
||||
butterworth(buf, count);
|
||||
butterworth(buf, count * 2); // stereo
|
||||
}
|
||||
buf += count;
|
||||
buf += count * 2; // stereo
|
||||
}
|
||||
}
|
||||
return _playing;
|
||||
|
|
|
@ -537,7 +537,7 @@ const uint16_t Cutscene::_creditsCutSeq[] = {
|
|||
0x00, 0x05, 0x2F, 0x32, 0x36, 0x3E, 0x30, 0x39, 0x3F, 0x14, 0x34, 0xFFFF
|
||||
};
|
||||
|
||||
const uint8_t Cutscene::_musicTable[] = {
|
||||
const uint8_t Cutscene::_musicTableDOS[] = {
|
||||
0x10, 0x15, 0x15, 0xFF, 0x15, 0x19, 0x0F, 0xFF, 0x15, 0x04, 0x15, 0xFF, 0xFF, 0x00, 0x19, 0x15,
|
||||
0x15, 0x0D, 0x15, 0x0D, 0x18, 0x13, 0xFF, 0xFF, 0xFF, 0x14, 0x14, 0x14, 0x14, 0x14, 0xFF, 0xFF,
|
||||
0x13, 0x13, 0x13, 0x13, 0x15, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x13, 0x11, 0xFF, 0x03,
|
||||
|
@ -545,6 +545,19 @@ const uint8_t Cutscene::_musicTable[] = {
|
|||
0x0B, 0x0C, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
const uint8_t Cutscene::_musicTableAmiga[] = {
|
||||
0x10, 0x7D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x7D, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x04, 0x73, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x6B, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x0D, 0x7D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0x7D, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x13, 0x7D, 0x13, 0x7D, 0x13, 0x7D, 0x13, 0x7D, 0xFF, 0xFF, 0x14, 0x7D, 0x14, 0x7D, 0x14, 0x7D,
|
||||
0x14, 0x7D, 0x14, 0x7D, 0x14, 0x7D, 0x13, 0x9B, 0x13, 0x9B, 0x11, 0x7D, 0xFF, 0xFF, 0x03, 0x78,
|
||||
0x0E, 0x7D, 0x13, 0x7D, 0x12, 0x6E, 0xFF, 0xFF, 0x06, 0x87, 0x07, 0x7D, 0x0A, 0x7D, 0x0A, 0x7D,
|
||||
0xFF, 0xFF, 0x05, 0x7D, 0x13, 0x7D, 0x02, 0x7D, 0xFF, 0xFF, 0x09, 0x7D, 0xFF, 0xFF, 0x08, 0x7D,
|
||||
0x0B, 0x7D, 0x0C, 0x7D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x25, 0x27, 0x28
|
||||
};
|
||||
|
||||
const uint8_t Cutscene::_protectionShapeData[] = {
|
||||
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x06, 0xD4, 0x00, 0x00, 0x00, 0x92,
|
||||
0x00, 0x00, 0x08, 0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x28, 0x00, 0x54, 0x00, 0x8C, 0x00, 0xB2,
|
||||
|
@ -4419,36 +4432,31 @@ const uint16_t ModPlayer::_periodTable[] = {
|
|||
216, 203, 192, 181, 171, 161, 152, 144, 136, 128, 121, 114 // C-3 to B-3 Finetune -1
|
||||
};
|
||||
|
||||
const char *ModPlayer::_modulesFiles[][2] = {
|
||||
{ "intro", "mod.flashback-introb" }, // introl3
|
||||
{ "options", "mod.flashback-options2" }, // option3
|
||||
{ "journal", "mod.flashback-options1" }, // journal3
|
||||
{ "ceinture", "mod.flashback-ceinturea" }, // chute3
|
||||
{ "desinteg", "mod.flashback-desintegr" }, // desinte3
|
||||
{ "reunion", "mod.flashback-reunion" }, // capture3
|
||||
{ "voyage", "mod.flashback-voyage" }, // voyage3
|
||||
{ "level4", "mod.flashback-teleporta" }, // telepor3
|
||||
{ "planetexplo", "mod.flashback-teleport2" }, // planexp3
|
||||
{ "fin", "mod.flashback-fin" }, // end31
|
||||
{ "ascenseur", "mod.flashback-ascenseur" }, // lift3
|
||||
{ "logo", "mod.flashback-logo" }, // present3
|
||||
{ "game_over", "mod.flashback-game_over" }, // gameove3
|
||||
{ "holocube", "mod.flashback-holocube" }, // holo3
|
||||
{ "memoire", "mod.flashback-memoire" }, // memory3
|
||||
{ "chute", "mod.flashback-chute" }, // chutevi3
|
||||
{ "debut", "mod.flashback-jungle" }, // reveil3
|
||||
{ "missions", "mod.flashback-missionca" }, // misvali3
|
||||
{ "taxi", "mod.flashback-taxi" }, // taxi3
|
||||
{ "donneobj", "mod.flashback-donneobjt" }, // donner3
|
||||
{ "missions2", "mod.flashback-fin2" } // mission3
|
||||
// { 0, 0, }, // objet3
|
||||
// { 0, 0, }, // recharg3
|
||||
// { 0, 0, }, // generat3
|
||||
// { 0, 0, }, // pont3
|
||||
// { 0, 0, } // rechage3
|
||||
const char *ModPlayer::_names[] = {
|
||||
"intro", "introb",
|
||||
"options", "options2",
|
||||
"journal", "options1",
|
||||
"ceinture", "ceinturea",
|
||||
"desinteg", "desintegr",
|
||||
"reunion", 0,
|
||||
"voyage", 0,
|
||||
"level4", "teleporta",
|
||||
"planetexplo", "teleport2",
|
||||
"fin", 0,
|
||||
"ascenseur", 0,
|
||||
"logo", 0,
|
||||
"game_over", 0,
|
||||
"holocube", 0,
|
||||
"memoire", 0,
|
||||
"chute", 0,
|
||||
"debut", "jungle",
|
||||
"missions", "missionca",
|
||||
"taxi", 0,
|
||||
"donneobj", "donneobjt",
|
||||
"missions2", "fin2",
|
||||
};
|
||||
|
||||
const int ModPlayer::_modulesFilesCount = ARRAYSIZE(_modulesFiles);
|
||||
const int ModPlayer::_namesCount = ARRAYSIZE(_names);
|
||||
|
||||
const char *SeqPlayer::_namesTable[] = {
|
||||
/* 0x00 */
|
||||
|
|
|
@ -928,7 +928,8 @@ uint32_t SystemStub_SDL::getTimeStamp() {
|
|||
static void mixAudioS16(void *param, uint8_t *buf, int len) {
|
||||
SystemStub_SDL *stub = (SystemStub_SDL *)param;
|
||||
memset(buf, 0, len);
|
||||
stub->_audioCbProc(stub->_audioCbData, (int16_t *)buf, len / 2);
|
||||
assert((len & 3) == 0);
|
||||
stub->_audioCbProc(stub->_audioCbData, (int16_t *)buf, len / (sizeof(int16_t) * 2));
|
||||
}
|
||||
|
||||
void SystemStub_SDL::startAudio(AudioCallback callback, void *param) {
|
||||
|
@ -936,7 +937,7 @@ void SystemStub_SDL::startAudio(AudioCallback callback, void *param) {
|
|||
memset(&desired, 0, sizeof(desired));
|
||||
desired.freq = kAudioHz;
|
||||
desired.format = AUDIO_S16SYS;
|
||||
desired.channels = 1;
|
||||
desired.channels = 2;
|
||||
desired.samples = 2048;
|
||||
desired.callback = mixAudioS16;
|
||||
desired.userdata = this;
|
||||
|
|
Loading…
Reference in New Issue