SCI: Replaced memory ref counting code in the SongIterator code by a simple Common::Array<byte> object; also doxygenified some source comments
svn-id: r40032
This commit is contained in:
parent
5325f9b76e
commit
3eab407cd5
2 changed files with 78 additions and 218 deletions
|
@ -26,6 +26,7 @@
|
||||||
/* Song iterators */
|
/* Song iterators */
|
||||||
|
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
#include "sci/sfx/iterator_internal.h"
|
#include "sci/sfx/iterator_internal.h"
|
||||||
#include "sci/sfx/player.h"
|
#include "sci/sfx/player.h"
|
||||||
#include "sci/tools.h"
|
#include "sci/tools.h"
|
||||||
|
@ -36,102 +37,6 @@
|
||||||
|
|
||||||
namespace Sci {
|
namespace Sci {
|
||||||
|
|
||||||
/****************************************/
|
|
||||||
/* Refcounting garbage collected memory */
|
|
||||||
/****************************************/
|
|
||||||
|
|
||||||
#define REFCOUNT_OVERHEAD (sizeof(uint32) * 3)
|
|
||||||
#define REFCOUNT_MAGIC_LIVE_1 0xebdc1741
|
|
||||||
#define REFCOUNT_MAGIC_LIVE_2 0x17015ac9
|
|
||||||
#define REFCOUNT_MAGIC_DEAD_1 0x11dead11
|
|
||||||
#define REFCOUNT_MAGIC_DEAD_2 0x22dead22
|
|
||||||
|
|
||||||
#define REFCOUNT_CHECK(p) ((((uint32 *)(p))[-3] == REFCOUNT_MAGIC_LIVE_2) && (((uint32 *)(p))[-1] == REFCOUNT_MAGIC_LIVE_1))
|
|
||||||
|
|
||||||
#define REFCOUNT(p) (((uint32 *)p)[-2])
|
|
||||||
|
|
||||||
#undef TRACE_REFCOUNT
|
|
||||||
|
|
||||||
/* Allocates "garbage" memory
|
|
||||||
** Parameters: (size_t) length: Number of bytes to allocate
|
|
||||||
** Returns : (void *) The allocated memory
|
|
||||||
** Memory allocated in this fashion will be marked as holding one reference.
|
|
||||||
** It cannot be freed with 'free()', only by using sci_refcount_decref().
|
|
||||||
*/
|
|
||||||
static void *sci_refcount_alloc(size_t length) {
|
|
||||||
uint32 *data = (uint32 *)sci_malloc(REFCOUNT_OVERHEAD + length);
|
|
||||||
#ifdef TRACE_REFCOUNT
|
|
||||||
fprintf(stderr, "[] REF: Real-alloc at %p\n", data);
|
|
||||||
#endif
|
|
||||||
data += 3;
|
|
||||||
|
|
||||||
data[-1] = REFCOUNT_MAGIC_LIVE_1;
|
|
||||||
data[-3] = REFCOUNT_MAGIC_LIVE_2;
|
|
||||||
REFCOUNT(data) = 1;
|
|
||||||
#ifdef TRACE_REFCOUNT
|
|
||||||
fprintf(stderr, "[] REF: Alloc'd %p (ref=%d) OK=%d\n", data, REFCOUNT(data),
|
|
||||||
REFCOUNT_CHECK(data));
|
|
||||||
#endif
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adds another reference to refcounted memory
|
|
||||||
** Parameters: (void *) data: The data to add a reference to
|
|
||||||
** Returns : (void *) data
|
|
||||||
*/
|
|
||||||
static void *sci_refcount_incref(void *data) {
|
|
||||||
if (!REFCOUNT_CHECK(data)) {
|
|
||||||
BREAKPOINT();
|
|
||||||
} else
|
|
||||||
REFCOUNT(data)++;
|
|
||||||
|
|
||||||
#ifdef TRACE_REFCOUNT
|
|
||||||
fprintf(stderr, "[] REF: Inc'ing %p (now ref=%d)\n", data, REFCOUNT(data));
|
|
||||||
#endif
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decrements the reference count for refcounted memory
|
|
||||||
** Parameters: (void *) data: The data to add a reference to
|
|
||||||
** Returns : (void *) data
|
|
||||||
** If the refcount reaches zero, the memory will be deallocated
|
|
||||||
*/
|
|
||||||
static void sci_refcount_decref(void *data) {
|
|
||||||
#ifdef TRACE_REFCOUNT
|
|
||||||
fprintf(stderr, "[] REF: Dec'ing %p (prev ref=%d) OK=%d\n", data, REFCOUNT(data),
|
|
||||||
REFCOUNT_CHECK(data));
|
|
||||||
#endif
|
|
||||||
if (!REFCOUNT_CHECK(data)) {
|
|
||||||
BREAKPOINT();
|
|
||||||
} else if (--REFCOUNT(data) == 0) {
|
|
||||||
uint32 *fdata = (uint32 *)data;
|
|
||||||
|
|
||||||
fdata[-1] = REFCOUNT_MAGIC_DEAD_1;
|
|
||||||
fdata[-3] = REFCOUNT_MAGIC_DEAD_2;
|
|
||||||
|
|
||||||
#ifdef TRACE_REFCOUNT
|
|
||||||
fprintf(stderr, "[] REF: Freeing (%p)...\n", fdata - 3);
|
|
||||||
#endif
|
|
||||||
free(fdata - 3);
|
|
||||||
#ifdef TRACE_REFCOUNT
|
|
||||||
fprintf(stderr, "[] REF: Done.\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Duplicates non-refcounted memory into a refcounted block
|
|
||||||
** Parameters: (void *) data: The memory to copy from
|
|
||||||
** (size_t) len: The number of bytes to copy/allocate
|
|
||||||
** Returns : (void *) Newly allocated refcounted memory
|
|
||||||
** The number of references accounted for will be one.
|
|
||||||
*/
|
|
||||||
static void *sci_refcount_memdup(void *data, size_t len) {
|
|
||||||
void *dest = sci_refcount_alloc(len);
|
|
||||||
memcpy(dest, data, len);
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const int MIDI_cmdlen[16] = {0, 0, 0, 0, 0, 0, 0, 0,
|
static const int MIDI_cmdlen[16] = {0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
2, 2, 2, 2, 1, 1, 2, 0
|
2, 2, 2, 2, 1, 1, 2, 0
|
||||||
|
@ -147,52 +52,9 @@ static void print_tabs_id(int nr, songit_id_t id) {
|
||||||
fprintf(stderr, "[%08lx] ", id);
|
fprintf(stderr, "[%08lx] ", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte *sci_memchr(byte *data, int c, int n) {
|
BaseSongIterator::BaseSongIterator(byte *data, uint size, songit_id_t id)
|
||||||
while (n && *data != c) {
|
: _data(data, size) {
|
||||||
++data;
|
|
||||||
--n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n)
|
|
||||||
return data;
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseSongIterator::BaseSongIterator(byte *data, uint size, songit_id_t id) {
|
|
||||||
ID = id;
|
ID = id;
|
||||||
|
|
||||||
_data = (byte *)sci_refcount_memdup(data, size);
|
|
||||||
_size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseSongIterator::BaseSongIterator(const BaseSongIterator& bsi) : SongIterator(bsi) {
|
|
||||||
memcpy(polyphony, bsi.polyphony, sizeof(polyphony));
|
|
||||||
memcpy(importance, bsi.importance, sizeof(importance));
|
|
||||||
ccc = bsi.ccc;
|
|
||||||
resetflag = bsi.resetflag;
|
|
||||||
_deviceId = bsi._deviceId;
|
|
||||||
active_channels = bsi.active_channels;
|
|
||||||
_size = bsi._size;
|
|
||||||
_data = bsi._data;
|
|
||||||
loops = bsi.loops;
|
|
||||||
recover_delay = bsi.recover_delay;
|
|
||||||
|
|
||||||
if (_data) {
|
|
||||||
#ifdef DEBUG_VERBOSE
|
|
||||||
fprintf(stderr, "** CLONE INCREF for new %p from %p at %p\n", mem, this, mem->_data);
|
|
||||||
#endif
|
|
||||||
sci_refcount_incref(_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseSongIterator::~BaseSongIterator() {
|
|
||||||
#ifdef DEBUG_VERBOSE
|
|
||||||
fprintf(stderr, "** FREEING it %p: data at %p\n", this, _data);
|
|
||||||
#endif
|
|
||||||
if (_data)
|
|
||||||
sci_refcount_decref(_data);
|
|
||||||
_data = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************/
|
/************************************/
|
||||||
|
@ -207,8 +69,8 @@ BaseSongIterator::~BaseSongIterator() {
|
||||||
#define SCI0_PCM_DATA_OFFSET 0x2c
|
#define SCI0_PCM_DATA_OFFSET 0x2c
|
||||||
|
|
||||||
#define CHECK_FOR_END_ABSOLUTE(offset) \
|
#define CHECK_FOR_END_ABSOLUTE(offset) \
|
||||||
if (offset > self->_size) { \
|
if (offset > self->_data.size()) { \
|
||||||
warning(SIPFX "Reached end of song without terminator (%x/%x) at %d!", offset, self->_size, __LINE__); \
|
warning(SIPFX "Reached end of song without terminator (%x/%x) at %d!", offset, self->_data.size(), __LINE__); \
|
||||||
return SI_FINISHED; \
|
return SI_FINISHED; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +169,7 @@ static int _parse_sci_midi_command(BaseSongIterator *self, byte *buf,
|
||||||
|
|
||||||
|
|
||||||
CHECK_FOR_END(paramsleft);
|
CHECK_FOR_END(paramsleft);
|
||||||
memcpy(buf + 1, self->_data + channel->offset, paramsleft);
|
memcpy(buf + 1, self->_data.begin() + channel->offset, paramsleft);
|
||||||
*result = 1 + paramsleft;
|
*result = 1 + paramsleft;
|
||||||
|
|
||||||
channel->offset += paramsleft;
|
channel->offset += paramsleft;
|
||||||
|
@ -477,8 +339,8 @@ static int _sci_midi_process_state(BaseSongIterator *self, byte *buf, int *resul
|
||||||
switch (channel->state) {
|
switch (channel->state) {
|
||||||
|
|
||||||
case SI_STATE_PCM: {
|
case SI_STATE_PCM: {
|
||||||
if (*(self->_data + channel->offset) == 0
|
if (self->_data[channel->offset] == 0
|
||||||
&& *(self->_data + channel->offset + 1) == SCI_MIDI_EOT)
|
&& self->_data[channel->offset + 1] == SCI_MIDI_EOT)
|
||||||
/* Fake one extra tick to trick the interpreter into not killing the song iterator right away */
|
/* Fake one extra tick to trick the interpreter into not killing the song iterator right away */
|
||||||
channel->state = SI_STATE_PCM_MAGIC_DELTA;
|
channel->state = SI_STATE_PCM_MAGIC_DELTA;
|
||||||
else
|
else
|
||||||
|
@ -510,9 +372,9 @@ static int _sci_midi_process_state(BaseSongIterator *self, byte *buf, int *resul
|
||||||
|
|
||||||
case SI_STATE_DELTA_TIME: {
|
case SI_STATE_DELTA_TIME: {
|
||||||
int offset;
|
int offset;
|
||||||
int ticks = _parse_ticks(self->_data + channel->offset,
|
int ticks = _parse_ticks(self->_data.begin() + channel->offset,
|
||||||
&offset,
|
&offset,
|
||||||
self->_size - channel->offset);
|
self->_data.size() - channel->offset);
|
||||||
|
|
||||||
channel->offset += offset;
|
channel->offset += offset;
|
||||||
channel->delay += ticks;
|
channel->delay += ticks;
|
||||||
|
@ -589,7 +451,7 @@ static int _sci0_header_magic_p(byte *data, int offset, int size) {
|
||||||
static int _sci0_get_pcm_data(Sci0SongIterator *self,
|
static int _sci0_get_pcm_data(Sci0SongIterator *self,
|
||||||
sfx_pcm_config_t *format, int *xoffset, uint *xsize) {
|
sfx_pcm_config_t *format, int *xoffset, uint *xsize) {
|
||||||
int tries = 2;
|
int tries = 2;
|
||||||
int found_it = 0;
|
bool found_it = false;
|
||||||
byte *pcm_data;
|
byte *pcm_data;
|
||||||
int size;
|
int size;
|
||||||
uint offset = SCI0_MIDI_OFFSET;
|
uint offset = SCI0_MIDI_OFFSET;
|
||||||
|
@ -598,23 +460,23 @@ static int _sci0_get_pcm_data(Sci0SongIterator *self,
|
||||||
return 1;
|
return 1;
|
||||||
/* No such luck */
|
/* No such luck */
|
||||||
|
|
||||||
while ((tries--) && (offset < self->_size) && (!found_it)) {
|
while ((tries--) && (offset < self->_data.size()) && (!found_it)) {
|
||||||
/* Search through the garbage manually */
|
// Search through the garbage manually
|
||||||
byte *fc = sci_memchr(self->_data + offset,
|
// FIXME: Replace offset by an iterator
|
||||||
SCI0_END_OF_SONG,
|
Common::Array<byte>::iterator iter = Common::find(self->_data.begin() + offset, self->_data.end(), SCI0_END_OF_SONG);
|
||||||
self->_size - offset);
|
|
||||||
|
|
||||||
if (!fc) {
|
if (iter == self->_data.end()) {
|
||||||
warning(SIPFX "Playing unterminated song!");
|
warning(SIPFX "Playing unterminated song!");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add one to move it past the END_OF_SONG marker */
|
// add one to move it past the END_OF_SONG marker
|
||||||
offset = fc - self->_data + 1;
|
iter++;
|
||||||
|
offset = iter - self->_data.begin(); // FIXME
|
||||||
|
|
||||||
|
|
||||||
if (_sci0_header_magic_p(self->_data, offset, self->_size))
|
if (_sci0_header_magic_p(self->_data.begin(), offset, self->_data.size()))
|
||||||
found_it = 1;
|
found_it = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found_it) {
|
if (!found_it) {
|
||||||
|
@ -624,7 +486,7 @@ static int _sci0_get_pcm_data(Sci0SongIterator *self,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pcm_data = self->_data + offset;
|
pcm_data = self->_data.begin() + offset;
|
||||||
|
|
||||||
size = READ_LE_UINT16(pcm_data + SCI0_PCM_SIZE_OFFSET);
|
size = READ_LE_UINT16(pcm_data + SCI0_PCM_SIZE_OFFSET);
|
||||||
|
|
||||||
|
@ -633,12 +495,12 @@ static int _sci0_get_pcm_data(Sci0SongIterator *self,
|
||||||
format->stereo = SFX_PCM_MONO;
|
format->stereo = SFX_PCM_MONO;
|
||||||
format->rate = READ_LE_UINT16(pcm_data + SCI0_PCM_SAMPLE_RATE_OFFSET);
|
format->rate = READ_LE_UINT16(pcm_data + SCI0_PCM_SAMPLE_RATE_OFFSET);
|
||||||
|
|
||||||
if (offset + SCI0_PCM_DATA_OFFSET + size != self->_size) {
|
if (offset + SCI0_PCM_DATA_OFFSET + size != self->_data.size()) {
|
||||||
int d = offset + SCI0_PCM_DATA_OFFSET + size - self->_size;
|
int d = offset + SCI0_PCM_DATA_OFFSET + size - self->_data.size();
|
||||||
|
|
||||||
warning(SIPFX "PCM advertizes %d bytes of data, but %d"
|
warning(SIPFX "PCM advertizes %d bytes of data, but %d"
|
||||||
" bytes are trailing in the resource!",
|
" bytes are trailing in the resource!",
|
||||||
size, self->_size - (offset + SCI0_PCM_DATA_OFFSET));
|
size, self->_data.size() - (offset + SCI0_PCM_DATA_OFFSET));
|
||||||
|
|
||||||
if (d > 0)
|
if (d > 0)
|
||||||
size -= d; /* Fix this */
|
size -= d; /* Fix this */
|
||||||
|
@ -682,7 +544,7 @@ Audio::AudioStream *Sci0SongIterator::getAudioStream() {
|
||||||
|
|
||||||
channel.state = SI_STATE_FINISHED; /* Don't play both PCM and music */
|
channel.state = SI_STATE_FINISHED; /* Don't play both PCM and music */
|
||||||
|
|
||||||
return makeStream(_data + offset + SCI0_PCM_DATA_OFFSET, size, conf);
|
return makeStream(_data.begin() + offset + SCI0_PCM_DATA_OFFSET, size, conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
SongIterator *Sci0SongIterator::handleMessage(Message msg) {
|
SongIterator *Sci0SongIterator::handleMessage(Message msg) {
|
||||||
|
@ -692,7 +554,7 @@ SongIterator *Sci0SongIterator::handleMessage(Message msg) {
|
||||||
case _SIMSG_BASEMSG_PRINT:
|
case _SIMSG_BASEMSG_PRINT:
|
||||||
print_tabs_id(msg._arg.i, ID);
|
print_tabs_id(msg._arg.i, ID);
|
||||||
fprintf(stderr, "SCI0: dev=%d, active-chan=%d, size=%d, loops=%d\n",
|
fprintf(stderr, "SCI0: dev=%d, active-chan=%d, size=%d, loops=%d\n",
|
||||||
_deviceId, active_channels, _size, loops);
|
_deviceId, active_channels, _data.size(), loops);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case _SIMSG_BASEMSG_SET_LOOPS:
|
case _SIMSG_BASEMSG_SET_LOOPS:
|
||||||
|
@ -787,7 +649,7 @@ void Sci0SongIterator::init() {
|
||||||
|
|
||||||
ccc = 0; /* Reset cumulative cue counter */
|
ccc = 0; /* Reset cumulative cue counter */
|
||||||
active_channels = 1;
|
active_channels = 1;
|
||||||
_base_init_channel(&channel, 0, SCI0_MIDI_OFFSET, _size);
|
_base_init_channel(&channel, 0, SCI0_MIDI_OFFSET, _data.size());
|
||||||
channel.resetSynthChannels();
|
channel.resetSynthChannels();
|
||||||
|
|
||||||
if (_data[0] == 2) /* Do we have an embedded PCM? */
|
if (_data[0] == 2) /* Do we have an embedded PCM? */
|
||||||
|
@ -833,20 +695,20 @@ static int _sci1_sample_init(Sci1SongIterator *self, int offset) {
|
||||||
sciprintf("[iterator-1] In sample at offset 0x04x: Byte #1 is %02x instead of zero\n",
|
sciprintf("[iterator-1] In sample at offset 0x04x: Byte #1 is %02x instead of zero\n",
|
||||||
self->_data[offset + 1]);
|
self->_data[offset + 1]);
|
||||||
|
|
||||||
rate = (int16)READ_LE_UINT16(self->_data + offset + 2);
|
rate = (int16)READ_LE_UINT16(self->_data.begin() + offset + 2);
|
||||||
length = READ_LE_UINT16(self->_data + offset + 4);
|
length = READ_LE_UINT16(self->_data.begin() + offset + 4);
|
||||||
begin = (int16)READ_LE_UINT16(self->_data + offset + 6);
|
begin = (int16)READ_LE_UINT16(self->_data.begin() + offset + 6);
|
||||||
end = (int16)READ_LE_UINT16(self->_data + offset + 8);
|
end = (int16)READ_LE_UINT16(self->_data.begin() + offset + 8);
|
||||||
|
|
||||||
CHECK_FOR_END_ABSOLUTE((uint)(offset + 10 + length));
|
CHECK_FOR_END_ABSOLUTE((uint)(offset + 10 + length));
|
||||||
|
|
||||||
sample.delta = begin;
|
sample.delta = begin;
|
||||||
sample.size = length;
|
sample.size = length;
|
||||||
sample._data = self->_data + offset + 10;
|
sample._data = self->_data.begin() + offset + 10;
|
||||||
|
|
||||||
#ifdef DEBUG_VERBOSE
|
#ifdef DEBUG_VERBOSE
|
||||||
fprintf(stderr, "[SAMPLE] %x/%x/%x/%x l=%x\n",
|
fprintf(stderr, "[SAMPLE] %x/%x/%x/%x l=%x\n",
|
||||||
offset + 10, begin, end, self->_size, length);
|
offset + 10, begin, end, self->_data.size(), length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sample.format.format = SFX_PCM_FORMAT_U8;
|
sample.format.format = SFX_PCM_FORMAT_U8;
|
||||||
|
@ -904,8 +766,8 @@ static int _sci1_song_init(Sci1SongIterator *self) {
|
||||||
|
|
||||||
CHECK_FOR_END_ABSOLUTE(offset + 4);
|
CHECK_FOR_END_ABSOLUTE(offset + 4);
|
||||||
|
|
||||||
track_offset = READ_LE_UINT16(self->_data + offset);
|
track_offset = READ_LE_UINT16(self->_data.begin() + offset);
|
||||||
end = READ_LE_UINT16(self->_data + offset + 2);
|
end = READ_LE_UINT16(self->_data.begin() + offset + 2);
|
||||||
|
|
||||||
CHECK_FOR_END_ABSOLUTE(track_offset - 1);
|
CHECK_FOR_END_ABSOLUTE(track_offset - 1);
|
||||||
|
|
||||||
|
|
|
@ -29,21 +29,11 @@
|
||||||
#include "sci/sfx/iterator.h"
|
#include "sci/sfx/iterator.h"
|
||||||
#include "sci/sfx/sci_midi.h"
|
#include "sci/sfx/sci_midi.h"
|
||||||
|
|
||||||
|
#include "common/array.h"
|
||||||
#include "common/list.h"
|
#include "common/list.h"
|
||||||
|
|
||||||
namespace Sci {
|
namespace Sci {
|
||||||
|
|
||||||
/* States */
|
|
||||||
|
|
||||||
#define SI_STATE_UNINITIALISED -1
|
|
||||||
#define SI_STATE_DELTA_TIME 0 /* Now at a delta time */
|
|
||||||
#define SI_STATE_COMMAND 1 /* Now at a MIDI operation */
|
|
||||||
#define SI_STATE_PENDING 2 /* Pending for loop */
|
|
||||||
#define SI_STATE_FINISHED 3 /* End of song */
|
|
||||||
#define SI_STATE_PCM 4 /* Should report a PCM next (-> DELTA_TIME) */
|
|
||||||
#define SI_STATE_PCM_MAGIC_DELTA 5 /* Should report a ``magic'' one tick delta time next (goes on to FINISHED) */
|
|
||||||
|
|
||||||
|
|
||||||
/* Iterator types */
|
/* Iterator types */
|
||||||
|
|
||||||
#define SCI_SONG_ITERATOR_TYPE_SCI0 0
|
#define SCI_SONG_ITERATOR_TYPE_SCI0 0
|
||||||
|
@ -52,29 +42,42 @@ namespace Sci {
|
||||||
#define SIPFX __FILE__" : "
|
#define SIPFX __FILE__" : "
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SI_STATE_UNINITIALISED = -1,
|
||||||
|
SI_STATE_DELTA_TIME = 0, //!< Now at a delta time
|
||||||
|
SI_STATE_COMMAND = 1, //!< Now at a MIDI operation
|
||||||
|
SI_STATE_PENDING = 2, //!< Pending for loop
|
||||||
|
SI_STATE_FINISHED = 3, //!< End of song
|
||||||
|
SI_STATE_PCM = 4, //!< Should report a PCM next (-> DELTA_TIME)
|
||||||
|
SI_STATE_PCM_MAGIC_DELTA = 5 //!< Should report a ``magic'' one tick delta time next (goes on to FINISHED)
|
||||||
|
};
|
||||||
|
|
||||||
struct SongIteratorChannel {
|
struct SongIteratorChannel {
|
||||||
int state; /* SI_STATE_* */
|
|
||||||
int offset; /* Offset into the data chunk */
|
int state; //!< State of this song iterator channel
|
||||||
int end; /* Last allowed byte in track */
|
int offset; //!< Offset into the data chunk */
|
||||||
int id; /* Some channel ID */
|
int end; //!< Last allowed byte in track */
|
||||||
int loop_offset;
|
int id; //!< Some channel ID */
|
||||||
int delay; /* Number of ticks before the
|
|
||||||
** specified channel is next
|
/**
|
||||||
** used, or
|
* Number of ticks before the specified channel is next used, or
|
||||||
** CHANNEL_DELAY_MISSING to
|
* CHANNEL_DELAY_MISSING to indicate that the delay has not yet
|
||||||
** indicate that the delay has
|
* been read.
|
||||||
** not yet been read */
|
*/
|
||||||
|
int delay;
|
||||||
|
|
||||||
/* Two additional offsets for recovering: */
|
/* Two additional offsets for recovering: */
|
||||||
|
int loop_offset;
|
||||||
int initial_offset;
|
int initial_offset;
|
||||||
int playmask; /* Active playmask (MIDI channels to play in here) */
|
|
||||||
int notes_played; /* #of notes played since the last loop start */
|
|
||||||
int loop_timepos; /* Total delay for this channel's loop marker */
|
|
||||||
int total_timepos; /* Number of ticks since the beginning, ignoring loops */
|
|
||||||
int timepos_increment; /* Number of ticks until the next command (to add) */
|
|
||||||
|
|
||||||
int saw_notes; /* Bitmask of channels we have currently played notes on */
|
int playmask; //!< Active playmask (MIDI channels to play in here) */
|
||||||
byte last_cmd; /* Last operation executed, for running status */
|
int notes_played; //!< #of notes played since the last loop start */
|
||||||
|
int loop_timepos; //!< Total delay for this channel's loop marker */
|
||||||
|
int total_timepos; //!< Number of ticks since the beginning, ignoring loops */
|
||||||
|
int timepos_increment; //!< Number of ticks until the next command (to add) */
|
||||||
|
|
||||||
|
int saw_notes; //!< Bitmask of channels we have currently played notes on */
|
||||||
|
byte last_cmd; //!< Last operation executed, for running status */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void resetSynthChannels();
|
void resetSynthChannels();
|
||||||
|
@ -82,27 +85,21 @@ public:
|
||||||
|
|
||||||
class BaseSongIterator : public SongIterator {
|
class BaseSongIterator : public SongIterator {
|
||||||
public:
|
public:
|
||||||
int polyphony[MIDI_CHANNELS]; /* # of simultaneous notes on each */
|
int polyphony[MIDI_CHANNELS]; //!< # of simultaneous notes on each
|
||||||
int importance[MIDI_CHANNELS]; /* priority rating for each channel, 0 means unrated. */
|
int importance[MIDI_CHANNELS]; //!< priority rating for each channel, 0 means unrated.
|
||||||
|
|
||||||
|
|
||||||
int ccc; /* Cumulative cue counter, for those who need it */
|
int ccc; //!< Cumulative cue counter, for those who need it
|
||||||
byte resetflag; /* for 0x4C -- on DoSound StopSound, do we return to start? */
|
byte resetflag; //!< for 0x4C -- on DoSound StopSound, do we return to start?
|
||||||
int _deviceId; /* ID of the device we generating events for */
|
int _deviceId; //!< ID of the device we generating events for
|
||||||
int active_channels; /* Number of active channels */
|
int active_channels; //!< Number of active channels
|
||||||
uint _size; /* Song size */
|
Common::Array<byte> _data; //!< Song data
|
||||||
byte *_data;
|
|
||||||
|
|
||||||
int loops; /* Number of loops remaining */
|
int loops; //!< Number of loops remaining
|
||||||
int recover_delay;
|
int recover_delay;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BaseSongIterator(byte *data, uint size, songit_id_t id);
|
BaseSongIterator(byte *data, uint size, songit_id_t id);
|
||||||
|
|
||||||
// Copy constructor taking care of memory handling
|
|
||||||
BaseSongIterator(const BaseSongIterator&);
|
|
||||||
|
|
||||||
~BaseSongIterator();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/********************************/
|
/********************************/
|
||||||
|
@ -131,7 +128,8 @@ public:
|
||||||
|
|
||||||
|
|
||||||
struct Sci1Sample {
|
struct Sci1Sample {
|
||||||
/* Time left-- initially, this is 'Sample point 1'.
|
/**
|
||||||
|
* Time left-- initially, this is 'Sample point 1'.
|
||||||
* After initialisation, it is 'sample point 1 minus the sample
|
* After initialisation, it is 'sample point 1 minus the sample
|
||||||
* point of the previous sample'
|
* point of the previous sample'
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue