diff --git a/common/stream.h b/common/stream.h index 3b6d7a8d346..43ff55b2e47 100644 --- a/common/stream.h +++ b/common/stream.h @@ -119,58 +119,47 @@ public: class MemoryReadStream : public ReadStream { private: const byte *_ptr; - const byte *_ptrOrig; - uint32 _size; - uint32 _sizeOrig; + const byte * const _ptrOrig; + const uint32 _bufSize; uint32 _pos; public: - MemoryReadStream(const byte *ptr, uint32 size) : _ptr(ptr), _ptrOrig(ptr), _size(size), _sizeOrig(size), _pos(0) {} + MemoryReadStream(const byte *buf, uint32 len) : _ptr(buf), _ptrOrig(buf), _bufSize(len), _pos(0) {} - uint32 read(void *ptr, uint32 size) { - if (size > _size) - size = _size; - memcpy(ptr, _ptr, size); - _size -= size; - _ptr += size; - _pos += size; - return size; + uint32 read(void *ptr, uint32 len) { + // Read at most as many bytes as are still available... + if (len > _bufSize - _pos) + len = _bufSize - _pos; + memcpy(ptr, _ptr, len); + _ptr += len; + _pos += len; + return len; } - uint32 tell() { return _pos; } - - void rewind() { - _ptr = _ptrOrig; - _size = _sizeOrig; - _pos = 0; - } + bool eof() { return _pos == _bufSize; } + uint32 pos() { return _pos; } + uint32 size() { return _bufSize; } void seek(uint32 offs, int whence = SEEK_SET) { + // Pre-Condition + assert(_pos <= _bufSize); switch (whence) { + case SEEK_END: + // SEEK_END works just like SEEK_SET, only 'reversed', + // i.e. from the end. + offs = _bufSize - offs; + // Fall through case SEEK_SET: - rewind(); - if (offs > _size) - offs = _size; - _size -= offs; - _ptr += offs; - _pos += offs; + _ptr = _ptrOrig + offs; + _pos = offs; break; case SEEK_CUR: - _size -= offs; - _ptr += offs; - _pos += offs; - break; - - case SEEK_END: - rewind(); - if (offs > _size) - offs = 0; - offs = _size - offs; - _size -= offs; _ptr += offs; _pos += offs; break; } + // Post-Condition + assert(_pos <= _bufSize); } }; diff --git a/saga/animation.cpp b/saga/animation.cpp index 09c50f40648..c347a9c34b7 100644 --- a/saga/animation.cpp +++ b/saga/animation.cpp @@ -583,7 +583,7 @@ int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_ *nextf_p = NULL; for (; cont_flag; decoded_data = 1) { - in_ch_offset = readS->tell(); + in_ch_offset = readS->pos(); in_ch = readS->readByte(); switch (in_ch) { case 0x0F: // 15: Frame header @@ -595,7 +595,7 @@ int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_ int param5; int param6; - if (thisf_len - readS->tell() < 13) { + if (thisf_len - readS->pos() < 13) { warning("0x%02X: Input buffer underrun", in_ch); return R_FAILURE; } @@ -625,7 +625,7 @@ int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_ break; case 0x10: // Long Unencoded Run runcount = readS->readSint16BE(); - if (thisf_len - readS->tell() < runcount) { + if (thisf_len - readS->pos() < runcount) { warning("0x%02X: Input buffer underrun", in_ch); return R_FAILURE; } @@ -646,7 +646,7 @@ int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_ continue; break; case 0x1F: // 31: Unusued? - if (thisf_len - readS->tell() < 3) { + if (thisf_len - readS->pos() < 3) { warning("0x%02X: Input buffer underrun", in_ch); return R_FAILURE; } @@ -657,7 +657,7 @@ int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_ continue; break; case 0x20: // Long compressed run - if (thisf_len - readS->tell() <= 3) { + if (thisf_len - readS->pos() <= 3) { warning("0x%02X: Input buffer underrun", in_ch); return R_FAILURE; } @@ -674,7 +674,7 @@ int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_ break; case 0x2F: // End of row - if (thisf_len - readS->tell() <= 4) { + if (thisf_len - readS->pos() <= 4) { return R_FAILURE; } @@ -686,7 +686,7 @@ int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_ continue; break; case 0x30: // Reposition command - if (thisf_len - readS->tell() < 2) { + if (thisf_len - readS->pos() < 2) { return R_FAILURE; } @@ -704,9 +704,9 @@ int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_ case 0x3F: // 68: Frame end marker debug(1, "0x3F: Frame end marker"); - if (decoded_data && (thisf_len - readS->tell() > 0)) { - *nextf_p = thisf_p + readS->tell(); - *nextf_len = thisf_len - readS->tell(); + if (decoded_data && (thisf_len - readS->pos() > 0)) { + *nextf_p = thisf_p + readS->pos(); + *nextf_len = thisf_len - readS->pos(); } else { *nextf_p = NULL; *nextf_len = 0; @@ -736,7 +736,7 @@ int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_ break; case 0x80: // Run of compressed data runcount = param_ch + 1; - if ((outbuf_remain < runcount) || (thisf_len - readS->tell() <= 1)) { + if ((outbuf_remain < runcount) || (thisf_len - readS->pos() <= 1)) { return R_FAILURE; } @@ -751,7 +751,7 @@ int IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *thisf_ break; case 0x40: // Uncompressed run runcount = param_ch + 1; - if ((outbuf_remain < runcount) || (thisf_len - readS->tell() < runcount)) { + if ((outbuf_remain < runcount) || (thisf_len - readS->pos() < runcount)) { return R_FAILURE; } @@ -887,7 +887,7 @@ int ANIM_GetFrameOffset(const byte *resdata, size_t resdata_len, uint16 find_fra } while (mark_byte != 63); } - *frame_offset_p = readS->tell(); + *frame_offset_p = readS->pos(); return R_SUCCESS; } diff --git a/saga/font.cpp b/saga/font.cpp index 1e72e1eb57f..56671455bd3 100644 --- a/saga/font.cpp +++ b/saga/font.cpp @@ -168,7 +168,7 @@ int FONT_Load(uint32 font_rn, int font_id) { normal_font->fce[c].tracking = readS->readByte(); } - if (readS->tell() != R_FONT_DESCSIZE) { + if (readS->pos() != R_FONT_DESCSIZE) { warning("Invalid font resource size."); return R_FAILURE; } diff --git a/saga/isomap.cpp b/saga/isomap.cpp index 8396ea10b06..8b20a4d2796 100644 --- a/saga/isomap.cpp +++ b/saga/isomap.cpp @@ -57,7 +57,7 @@ int ISOMAP_LoadTileset(const byte *tileres_p, size_t tileres_len) { IsoModule.tile_ct = first_entry.tile_offset / SAGA_ISOTILE_ENTRY_LEN; - readS->rewind(); + readS->seek(0); tile_tbl = (R_ISOTILE_ENTRY *)malloc(IsoModule.tile_ct * sizeof *tile_tbl); if (tile_tbl == NULL) { diff --git a/saga/script.cpp b/saga/script.cpp index 925addc3be2..a449ac6934e 100644 --- a/saga/script.cpp +++ b/saga/script.cpp @@ -104,12 +104,12 @@ int SCRIPT_Init() { // Convert LUT resource to logical LUT MemoryReadStream *readS = new MemoryReadStream(rsc_ptr, rsc_len); for (i = 0; i < ScriptModule.script_lut_max; i++) { - prevTell = readS->tell(); + prevTell = readS->pos(); ScriptModule.script_lut[i].script_rn = readS->readUint16LE(); ScriptModule.script_lut[i].diag_list_rn = readS->readUint16LE(); ScriptModule.script_lut[i].voice_lut_rn = readS->readUint16LE(); // Skip the unused portion of the structure - for (j = readS->tell(); j < prevTell + ScriptModule.script_lut_entrylen; j++) + for (j = readS->pos(); j < prevTell + ScriptModule.script_lut_entrylen; j++) readS->readByte(); } @@ -365,7 +365,7 @@ R_SCRIPT_BYTECODE *SCRIPT_LoadBytecode(byte *bytecode_p, size_t bytecode_len) { // Read in the entrypoint table - while (readS->tell() < ep_tbl_offset) + while (readS->pos() < ep_tbl_offset) readS->readByte(); for (i = 0; i < n_entrypoints; i++) { @@ -439,7 +439,7 @@ R_DIALOGUE_LIST *SCRIPT_LoadDialogue(const byte *dialogue_p, size_t dialogue_len } // Read in tables from dialogue list resource - readS->rewind(); + readS->seek(0); for (i = 0; i < n_dialogue; i++) { offset = readS->readUint16LE(); if (offset > dialogue_len) { diff --git a/saga/sndres.cpp b/saga/sndres.cpp index 418c39c550c..f7aca3be323 100644 --- a/saga/sndres.cpp +++ b/saga/sndres.cpp @@ -157,16 +157,16 @@ int SndRes::loadVocSound(byte *snd_res, size_t snd_res_len, R_SOUNDBUFFER *snd_b voc_hb.voc_version = readS->readUint16LE(); voc_hb.voc_fileid = readS->readUint16LE(); - if ((int32)(snd_res_len - readS->tell()) < (int32)(voc_hb.db_offset + R_VOC_GENBLOCK_LEN)) { + if ((int32)(snd_res_len - readS->pos()) < (int32)(voc_hb.db_offset + R_VOC_GENBLOCK_LEN)) { return R_FAILURE; } - while (readS->tell() < voc_hb.db_offset) + while (readS->pos() < voc_hb.db_offset) readS->readByte(); for (;;) { /* Read generic block header */ - if (snd_res_len - readS->tell() < R_VOC_GENBLOCK_LEN) { + if (snd_res_len - readS->pos() < R_VOC_GENBLOCK_LEN) { return R_FAILURE; } @@ -197,8 +197,8 @@ int SndRes::loadVocSound(byte *snd_res, size_t snd_res_len, R_SOUNDBUFFER *snd_b snd_buf_i->res_data = snd_res; snd_buf_i->res_len = snd_res_len; - snd_buf_i->s_buf = snd_res + readS->tell(); - snd_buf_i->s_buf_len = snd_res_len - readS->tell() - 1; /* -1 for end block */ + snd_buf_i->s_buf = snd_res + readS->pos(); + snd_buf_i->s_buf_len = snd_res_len - readS->pos() - 1; /* -1 for end block */ snd_buf_i->s_signed = 0; return R_SUCCESS; diff --git a/saga/sprite.cpp b/saga/sprite.cpp index be31d6e0e46..dd3eb9b8870 100644 --- a/saga/sprite.cpp +++ b/saga/sprite.cpp @@ -216,7 +216,7 @@ int SPRITE_Draw(R_SURFACE *ds, R_SPRITELIST *sprite_list, int sprite_num, int sp s_width = readS->readByte(); s_height = readS->readByte(); - sprite_data_p = sprite_p + readS->tell(); + sprite_data_p = sprite_p + readS->pos(); spr_x += x_align; spr_y += y_align; @@ -326,7 +326,7 @@ int SPRITE_DrawOccluded(R_SURFACE *ds, R_SPRITELIST *sprite_list, int sprite_num s_width = readS->readByte(); s_height = readS->readByte(); - sprite_data_p = sprite_p + readS->tell(); + sprite_data_p = sprite_p + readS->pos(); // Create actor Z occlusion LUT SCENE_GetZInfo(&zinfo); diff --git a/saga/sthread.cpp b/saga/sthread.cpp index f6f5b026b09..e612f798f2a 100644 --- a/saga/sthread.cpp +++ b/saga/sthread.cpp @@ -325,7 +325,7 @@ int STHREAD_Run(R_SCRIPT_THREAD *thread, int instr_limit, int msec) { temp = readS->readByte(); temp2 = readS->readByte(); param1 = (SDataWord_T)readS->readUint16LE(); - data = readS->tell(); + data = readS->pos(); //SSTACK_Push(thread->stack, (SDataWord_T)temp); SSTACK_Push(thread->stack, data); thread->i_offset = (unsigned long)param1; @@ -775,7 +775,7 @@ int STHREAD_Run(R_SCRIPT_THREAD *thread, int instr_limit, int msec) { // Set instruction offset only if a previous instruction didn't branch if (saved_offset == thread->i_offset) { - thread->i_offset = readS->tell(); + thread->i_offset = readS->pos(); } if (unhandled) { CON_Print(S_ERROR_PREFIX "%X: Unhandled opcode.\n", thread->i_offset);