mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-17 15:18:11 +00:00
671 lines
17 KiB
C++
671 lines
17 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "common/debug.h"
|
|
|
|
#include "cryo/cryolib.h"
|
|
|
|
namespace Cryo {
|
|
|
|
static bool safe_palette = false;
|
|
static int16 pred_r = 0, pred_l = 0;
|
|
static bool use_adpcm = false;
|
|
static float hnm_rate = 0.0;
|
|
static float next_frame_time = 0.0;
|
|
static float expected_frame_time = 0.0;
|
|
static float time_drift = 0.0;
|
|
static bool use_mono = false;
|
|
static bool use_sound = false;
|
|
static bool use_sound_sync = false;
|
|
static int16 pending_sounds = 0;
|
|
static bool sound_started = false;
|
|
static bool preserve_color0 = false;
|
|
static soundchannel_t *soundChannel_adpcm = 0;
|
|
static soundgroup_t *soundGroup_adpcm = 0;
|
|
static soundchannel_t *soundChannel = 0;
|
|
static soundgroup_t *soundGroup = 0;
|
|
static void (*custom_chunk_handler)(byte *buffer, int size, int16 id, char h6, char h7) = 0;
|
|
static int16 decomp_table[256];
|
|
|
|
void CLHNM_Desentrelace320(byte *frame_buffer, byte *final_buffer, uint16 height);
|
|
|
|
void CLHNM_DecompLempelZiv(byte *buffer, byte *output) {
|
|
byte *inp = buffer;
|
|
byte *out = output;
|
|
|
|
unsigned int queue = 0;
|
|
int qpos = -1;
|
|
|
|
//TODO: fix for BE
|
|
#define GetBit() ( 1 & ( (qpos >= 0) ? (queue >> qpos--) : (queue = *(unsigned int*)((inp += 4) - 4)) >> ((qpos = 30) + 1) ) )
|
|
|
|
for (;;) {
|
|
if (GetBit()) {
|
|
*out++ = *inp++;
|
|
} else {
|
|
int l, o;
|
|
if (GetBit()) {
|
|
l = *inp & 7;
|
|
o = *(uint16 *)inp >> 3;
|
|
inp += 2;
|
|
o -= 8192;
|
|
if (!l)
|
|
l = *inp++;
|
|
if (!l)
|
|
break;
|
|
} else {
|
|
l = GetBit() * 2 + GetBit();
|
|
o = *(inp++) - 256;
|
|
}
|
|
l += 2;
|
|
while (l--) {
|
|
*out = *(out + o);
|
|
out++;
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef GetBit
|
|
|
|
return;
|
|
}
|
|
|
|
void CLHNM_DecompUBA(byte *output, byte *curr_buffer, byte *prev_buffer,
|
|
byte *input, int width, char flags) {
|
|
unsigned int code;
|
|
byte mode, count, color;
|
|
uint16 offs;
|
|
byte *ref;
|
|
byte *out_start = output;
|
|
byte swap;
|
|
int shft1, shft2;
|
|
// return;
|
|
if ((flags & 1) == 0) {
|
|
//HNM4 classic
|
|
int twolinesabove = -(width * 2);
|
|
for (;;) {
|
|
code = PLE32(input) & 0xFFFFFF; //input++;
|
|
count = code & 0x1F;
|
|
if (count) {
|
|
input += 3;
|
|
mode = (code >> 5) & 0xF;
|
|
offs = code >> 9;
|
|
//
|
|
swap = mode >> 3;
|
|
ref = ((mode & 1) ? prev_buffer : curr_buffer) + (output - out_start) + (offs * 2) - 32768;
|
|
if (mode & 2) {
|
|
// ref += twolinesabove;
|
|
shft1 = twolinesabove + 1;
|
|
shft2 = 0;
|
|
//swap ^= 1;
|
|
} else {
|
|
shft1 = 0;
|
|
shft2 = 1;
|
|
}
|
|
while (count--) {
|
|
byte b0 = ref[shft1];
|
|
byte b1 = ref[shft2];
|
|
output[swap] = b0;
|
|
output[swap ^ 1] = b1;
|
|
output += 2;
|
|
ref += (mode & 4) ? -2 : 2;
|
|
}
|
|
} else {
|
|
input++;
|
|
mode = code & 0xFF; // bits 0..4 are zero
|
|
switch (mode) {
|
|
case 0:
|
|
*(output++) = *(input++);
|
|
*(output++) = *(input++);
|
|
break;
|
|
case 0x20:
|
|
output += 2 * *(input++);
|
|
break;
|
|
case 0x40:
|
|
output += 2 * (code >> 8);
|
|
input += 2;
|
|
break;
|
|
case 0x60:
|
|
count = *(input++);
|
|
color = *(input++);
|
|
while (count--) {
|
|
*(output++) = color;
|
|
*(output++) = color;
|
|
}
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
assert(0);
|
|
//HNM4 hires
|
|
for (;;) {
|
|
code = PLE32(input) & 0xFFFFFF;
|
|
input++;
|
|
count = code & 0x3F;
|
|
if (count) {
|
|
mode = (code >> 5) & 0xF;
|
|
offs = code >> 9;
|
|
//
|
|
} else {
|
|
mode = code & 0xFF; // bits 0..5 are zero
|
|
switch (mode) {
|
|
case 0x00:
|
|
output += *input++;
|
|
break;
|
|
case 0x40:
|
|
*output++ = *input++;
|
|
*(output++ + width) = *input++;
|
|
break;
|
|
case 0x80:
|
|
output += width;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CLHNM_Init() {
|
|
custom_chunk_handler = 0;
|
|
preserve_color0 = false;
|
|
}
|
|
|
|
void CLHNM_Done() {
|
|
}
|
|
|
|
void CLHNM_SetupTimer(float rate) {
|
|
hnm_rate = 100.0 / rate;
|
|
}
|
|
|
|
void CLHNM_WaitLoop(hnm_t *hnm) {
|
|
expected_frame_time += hnm_rate;
|
|
next_frame_time = expected_frame_time - time_drift;
|
|
if (use_sound_sync && TimerTicks > 1000.0 + next_frame_time)
|
|
use_sound = false;
|
|
while (TimerTicks < next_frame_time) ; // waste time
|
|
time_drift = TimerTicks - next_frame_time;
|
|
}
|
|
|
|
void CLHNM_SetupSound(int16 numSounds, int16 arg4, int16 sampleSize, float rate, int16 mode) {
|
|
soundChannel = CLSoundChannel_New(mode);
|
|
soundGroup = CLSoundGroup_New(numSounds, arg4, sampleSize, rate, mode);
|
|
if (sampleSize == 16)
|
|
CLSoundGroup_Reverse16All(soundGroup);
|
|
}
|
|
|
|
void CLHNM_SetupSoundADPCM(int16 numSounds, int16 arg4, int16 sampleSize, float rate, int16 mode) {
|
|
soundChannel_adpcm = CLSoundChannel_New(mode);
|
|
soundGroup_adpcm = CLSoundGroup_New(numSounds, arg4, sampleSize, rate, mode);
|
|
}
|
|
|
|
void CLHNM_CloseSound() {
|
|
if (soundChannel) {
|
|
CLSoundChannel_Stop(soundChannel);
|
|
CLSoundChannel_Free(soundChannel);
|
|
soundChannel = 0;
|
|
}
|
|
if (soundGroup) {
|
|
CLSoundGroup_Free(soundGroup);
|
|
soundGroup = 0;
|
|
}
|
|
if (soundChannel_adpcm) {
|
|
CLSoundChannel_Stop(soundChannel_adpcm);
|
|
CLSoundChannel_Free(soundChannel_adpcm);
|
|
soundChannel = 0;
|
|
}
|
|
if (soundGroup_adpcm) {
|
|
CLSoundGroup_Free(soundGroup_adpcm);
|
|
soundGroup = 0;
|
|
}
|
|
}
|
|
|
|
void CLHNM_SetForceZero2Black(bool forceblack) {
|
|
preserve_color0 = forceblack;
|
|
}
|
|
|
|
hnm_t *CLHNM_New(int preload_size) {
|
|
hnm_t *hnm = (hnm_t *)malloc(sizeof(*hnm));
|
|
|
|
hnm->_frameNum = 0;
|
|
hnm->ff_4 = 0;
|
|
hnm->_file = nullptr;
|
|
hnm->tmpBuffer[0] = nullptr;
|
|
hnm->tmpBuffer[1] = nullptr;
|
|
hnm->finalBuffer = nullptr;
|
|
hnm->_readBuffer = nullptr;
|
|
hnm->ff_896 = 0;
|
|
hnm->_totalRead = 0;
|
|
for (int i = 0; i < 256; i++) {
|
|
hnm->_palette[i].a = 0;
|
|
hnm->_palette[i].r = 0;
|
|
hnm->_palette[i].g = 0;
|
|
hnm->_palette[i].b = 0;
|
|
}
|
|
|
|
return hnm;
|
|
}
|
|
|
|
void CLHNM_Dispose(hnm_t *hnm) {
|
|
free(hnm);
|
|
}
|
|
|
|
|
|
void CLHNM_SetFile(hnm_t *hnm, file_t *file) {
|
|
hnm->_file = file;
|
|
}
|
|
|
|
void CLHNM_SetFinalBuffer(hnm_t *hnm, byte *buffer) {
|
|
hnm->finalBuffer = buffer;
|
|
}
|
|
|
|
void CLHNM_AllocMemory(hnm_t *hnm) {
|
|
hnm->tmpBuffer[0] = (byte *)malloc(hnm->_header._bufferSize + 2);
|
|
|
|
if (!hnm->tmpBuffer[0])
|
|
return;
|
|
|
|
hnm->tmpBuffer[1] = (byte *)malloc(hnm->_header._bufferSize + 2);
|
|
|
|
if (!hnm->tmpBuffer[1]) {
|
|
free(hnm->tmpBuffer[0]);
|
|
hnm->tmpBuffer[0] = nullptr;
|
|
return;
|
|
}
|
|
|
|
hnm->_readBuffer = (byte *)malloc(hnm->_header._bufferSize + 2);
|
|
if (!hnm->_readBuffer) {
|
|
free(hnm->tmpBuffer[0]);
|
|
hnm->tmpBuffer[0] = nullptr;
|
|
free(hnm->tmpBuffer[1]);
|
|
hnm->tmpBuffer[1] = nullptr;
|
|
}
|
|
}
|
|
|
|
void CLHNM_DeallocMemory(hnm_t *hnm) {
|
|
free(hnm->tmpBuffer[0]);
|
|
free(hnm->tmpBuffer[1]);
|
|
free(hnm->_readBuffer);
|
|
|
|
hnm->tmpBuffer[0] = nullptr;
|
|
hnm->tmpBuffer[1] = nullptr;
|
|
hnm->_readBuffer = nullptr;
|
|
}
|
|
|
|
void CLHNM_Read(hnm_t *hnm, int size) {
|
|
int32 size_ = size;
|
|
CLFile_Read(*hnm->_file, hnm->_readBuffer, &size_);
|
|
}
|
|
|
|
void CLHNM_GiveTime(hnm_t *hnm) {
|
|
}
|
|
|
|
void CLHNM_CanLoop(hnm_t *hnm, bool canLoop) {
|
|
hnm->_canLoop = canLoop;
|
|
}
|
|
|
|
void CLHNM_SelectBuffers(hnm_t *hnm) {
|
|
if (hnm->_frameNum % 2) {
|
|
hnm->_newFrameBuffer = hnm->tmpBuffer[1];
|
|
hnm->_oldFrameBuffer = hnm->tmpBuffer[0];
|
|
} else {
|
|
hnm->_newFrameBuffer = hnm->tmpBuffer[0];
|
|
hnm->_oldFrameBuffer = hnm->tmpBuffer[1];
|
|
}
|
|
}
|
|
|
|
void CLHNM_ChangePalette(hnm_t *hnm) {
|
|
int16 mincolor, maxcolor;
|
|
uint16 fst, cnt;
|
|
byte *pal;
|
|
color_t *color;
|
|
CLPalette_GetLastPalette(hnm->_palette);
|
|
pal = hnm->_dataPtr;
|
|
if (*(uint16 *)pal == 0xFFFF)
|
|
return;
|
|
mincolor = 255;
|
|
maxcolor = 0;
|
|
do {
|
|
fst = *pal++;
|
|
cnt = *pal++;
|
|
if (cnt == 0)
|
|
cnt = 256;
|
|
debug("hnm: setting palette, fst = %d, cnt = %d, last = %d", fst, cnt, fst + cnt - 1);
|
|
assert(fst + cnt <= 256);
|
|
if (mincolor > fst)
|
|
mincolor = fst;
|
|
if (maxcolor < fst + cnt)
|
|
maxcolor = fst + cnt;
|
|
color = hnm->_palette + fst;
|
|
if (safe_palette) {
|
|
while (cnt--) {
|
|
byte r = *pal++;
|
|
byte g = *pal++;
|
|
byte b = *pal++;
|
|
int16 rr = r << 10;
|
|
int16 gg = g << 10;
|
|
int16 bb = b << 10;
|
|
if (color->r != rr || color->g != gg || color->b != bb)
|
|
CLBlitter_OneBlackFlash();
|
|
color->r = rr;
|
|
color->g = gg;
|
|
color->b = bb;
|
|
color++;
|
|
}
|
|
} else {
|
|
while (cnt--) {
|
|
byte r = *pal++;
|
|
byte g = *pal++;
|
|
byte b = *pal++;
|
|
color->r = r << 10;
|
|
color->g = g << 10;
|
|
color->b = b << 10;
|
|
color++;
|
|
}
|
|
}
|
|
|
|
} while (*(uint16 *)pal != 0xFFFF);
|
|
#if 0
|
|
if (preserve_color0) {
|
|
hnm->palette[0].r = 0;
|
|
hnm->palette[0].g = 0;
|
|
hnm->palette[0].b = 0;
|
|
}
|
|
#endif
|
|
// CLBlitter_Send2ScreenNextCopy(hnm->palette, mincolor, maxcolor - mincolor);
|
|
CLBlitter_Send2ScreenNextCopy(hnm->_palette, 0, 256);
|
|
}
|
|
|
|
void CLHNM_Desentrelace(hnm_t *hnm) {
|
|
switch (hnm->_header._width) {
|
|
case 320:
|
|
CLHNM_Desentrelace320(hnm->_newFrameBuffer, hnm->finalBuffer, hnm->_header._height);
|
|
break;
|
|
// case 480:
|
|
// CLHNM_Desentrelace480(hnm->new_frame_buffer, hnm->final_buffer, hnm->header.height);
|
|
// break;
|
|
default:
|
|
error("CLHNM_Desentrelace - Unexpected width");
|
|
}
|
|
}
|
|
|
|
void CLHNM_FlushPreloadBuffer(hnm_t *hnm) {
|
|
}
|
|
|
|
soundchannel_t *CLHNM_GetSoundChannel() {
|
|
return soundChannel;
|
|
}
|
|
|
|
|
|
void CLHNM_TryRead(hnm_t *hnm, int size) {
|
|
CLHNM_Read(hnm, size);
|
|
}
|
|
|
|
void CLHNM_ResetInternalTimer() {
|
|
time_drift = 0.0;
|
|
next_frame_time = expected_frame_time = TimerTicks;
|
|
}
|
|
|
|
void CLHNM_Reset(hnm_t *hnm) {
|
|
hnm->_frameNum = 0;
|
|
hnm->ff_4 = 0;
|
|
hnm->_totalRead = 0;
|
|
sound_started = false;
|
|
pending_sounds = 0;
|
|
CLHNM_ResetInternalTimer();
|
|
}
|
|
|
|
int16 CLHNM_LoadFrame(hnm_t *hnm) {
|
|
int chunk;
|
|
CLHNM_TryRead(hnm, 4);
|
|
chunk = *(int *)hnm->_readBuffer;
|
|
chunk = LE32(chunk);
|
|
chunk &= 0xFFFFFF; // upper bit - keyframe mark?
|
|
if (!chunk)
|
|
return 0;
|
|
|
|
if (chunk - 4 > hnm->_header._bufferSize)
|
|
error("CLHNM_LoadFrame - Chunk size");
|
|
|
|
CLHNM_TryRead(hnm, chunk - 4);
|
|
hnm->_dataPtr = hnm->_readBuffer;
|
|
hnm->_totalRead += chunk;
|
|
return 1;
|
|
}
|
|
|
|
void CLHNM_WantsSound(bool sound) {
|
|
use_sound = sound;
|
|
}
|
|
|
|
void CLHNM_LoadDecompTable(int16 *buffer) {
|
|
int16 i;
|
|
int16 e;
|
|
for (i = 0; i < 256; i++) {
|
|
e = *buffer++;
|
|
decomp_table[i] = LE16(e);
|
|
}
|
|
}
|
|
|
|
void CLHNM_DecompADPCM(byte *buffer, int16 *output, int size) {
|
|
int16 l = pred_l, r = pred_r;
|
|
size &= ~1;
|
|
while (size--) {
|
|
*output++ = l += decomp_table[*buffer++];
|
|
*output++ = r += decomp_table[*buffer++];
|
|
if (l > 512 || r > 512)
|
|
error("CLHNM_DecompADPCM - Unexpected values");
|
|
}
|
|
pred_l = l;
|
|
pred_r = r;
|
|
}
|
|
|
|
void CLHNM_SoundInADPCM(bool isAdpcm) {
|
|
use_adpcm = isAdpcm;
|
|
}
|
|
|
|
void CLHNM_SoundMono(bool isMono) {
|
|
use_mono = isMono;
|
|
}
|
|
|
|
bool CLHNM_NextElement(hnm_t *hnm) {
|
|
int sz;
|
|
int16 id;
|
|
char h6, h7;
|
|
int16 i;
|
|
if (hnm->_frameNum == 0) {
|
|
CLHNM_ResetInternalTimer();
|
|
pred_l = pred_r = 0;
|
|
}
|
|
if (hnm->_frameNum == hnm->_header._numbFrame)
|
|
return false;
|
|
|
|
if (!CLHNM_LoadFrame(hnm))
|
|
return false;
|
|
|
|
for (;;) {
|
|
sz = PLE32(hnm->_dataPtr) & 0xFFFFFF;
|
|
hnm->_dataPtr += 4;
|
|
id = *(int16 *)hnm->_dataPtr;
|
|
hnm->_dataPtr += 2;
|
|
h6 = *hnm->_dataPtr;
|
|
hnm->_dataPtr += 1;
|
|
h7 = *hnm->_dataPtr;
|
|
hnm->_dataPtr += 1;
|
|
hnm->_chunkId = id;
|
|
switch (id) {
|
|
case BE16('PL'):
|
|
CLHNM_ChangePalette(hnm);
|
|
hnm->_dataPtr += sz - 8;
|
|
break;
|
|
case BE16('IZ'):
|
|
hnm->_frameNum++;
|
|
CLHNM_SelectBuffers(hnm);
|
|
CLHNM_DecompLempelZiv(hnm->_dataPtr + 4, hnm->_newFrameBuffer);
|
|
switch (hnm->_header._width) {
|
|
// case 320: CLBlitter_RawCopy320ASM(hnm->new_frame_buffer, hnm->old_frame_buffer, hnm->header.height); break;
|
|
// case 480: CLBlitter_RawCopy480ASM(hnm->new_frame_buffer, hnm->old_frame_buffer, hnm->header.height); break;
|
|
// case 640: CLBlitter_RawCopy640ASM(hnm->new_frame_buffer, hnm->old_frame_buffer, hnm->header.height); break;
|
|
// default: memcpy(hnm->old_frame_buffer, hnm->new_frame_buffer, hnm->header.width * hnm->header.height);
|
|
default:
|
|
memcpy(hnm->_oldFrameBuffer, hnm->_newFrameBuffer, hnm->_header._bufferSize); //TODO strange buffer size here
|
|
}
|
|
if (!(h6 & 1))
|
|
CLHNM_Desentrelace(hnm);
|
|
else {
|
|
// if(hnm->header.width == 640)
|
|
// CLBlitter_RawCopy640(hnm->new_frame_buffer, hnm->final_buffer, hnm->header.height);
|
|
// else
|
|
memcpy(hnm->finalBuffer, hnm->_newFrameBuffer, hnm->_header._height); //TODO: wrong size?
|
|
}
|
|
if (use_adpcm) {
|
|
if (!sound_started) {
|
|
for (i = 0; i < pending_sounds; i++)
|
|
CLSoundGroup_PlayNextSample(soundGroup_adpcm, soundChannel);
|
|
sound_started = true;
|
|
}
|
|
} else if (!sound_started) {
|
|
for (i = 0; i < pending_sounds; i++)
|
|
CLSoundGroup_PlayNextSample(soundGroup, soundChannel);
|
|
sound_started = true;
|
|
}
|
|
|
|
return true;
|
|
case BE16('IU'):
|
|
hnm->_frameNum++;
|
|
CLHNM_SelectBuffers(hnm);
|
|
CLHNM_DecompUBA(hnm->_newFrameBuffer, hnm->_newFrameBuffer, hnm->_oldFrameBuffer, hnm->_dataPtr, hnm->_header._width, h6);
|
|
if (!(h6 & 1))
|
|
CLHNM_Desentrelace(hnm);
|
|
else {
|
|
// if(hnm->header.width == 640)
|
|
// CLBlitter_RawCopy640(hnm->new_frame_buffer, hnm->final_buffer, hnm->header.height);
|
|
// else
|
|
memcpy(hnm->finalBuffer, hnm->_newFrameBuffer, hnm->_header._width * hnm->_header._height);
|
|
}
|
|
return true;
|
|
|
|
case BE16('sd'):
|
|
case BE16('SD'):
|
|
if (use_sound) {
|
|
if (!h6) {
|
|
int sound_size = sz - 8;
|
|
if (!use_adpcm) {
|
|
CLSoundGroup_SetDatas(soundGroup, hnm->_dataPtr, sound_size - 2, 0);
|
|
if (sound_started)
|
|
CLSoundGroup_PlayNextSample(soundGroup, soundChannel);
|
|
else
|
|
pending_sounds++;
|
|
} else {
|
|
int16 *sound_buffer = (int16 *)CLSoundGroup_GetNextBuffer(soundGroup_adpcm);
|
|
if (!pending_sounds) {
|
|
const int kDecompTableSize = 256 * sizeof(int16);
|
|
CLHNM_LoadDecompTable((int16 *)hnm->_dataPtr);
|
|
CLHNM_DecompADPCM(hnm->_dataPtr + kDecompTableSize, sound_buffer, sound_size - kDecompTableSize);
|
|
CLSoundGroup_AssignDatas(soundGroup_adpcm, sound_buffer, (sound_size - kDecompTableSize) * 2, 0);
|
|
} else {
|
|
CLHNM_DecompADPCM(hnm->_dataPtr, sound_buffer, sound_size);
|
|
CLSoundGroup_AssignDatas(soundGroup_adpcm, sound_buffer, sound_size * 2, 0);
|
|
}
|
|
pending_sounds++;
|
|
if (sound_started)
|
|
CLSoundGroup_PlayNextSample(soundGroup_adpcm, soundChannel);
|
|
}
|
|
} else
|
|
error("CLHNM_NextElement - unexpected flag");
|
|
}
|
|
hnm->_dataPtr += sz - 8;
|
|
break;
|
|
default:
|
|
if (custom_chunk_handler)
|
|
custom_chunk_handler(hnm->_dataPtr, sz - 8, id, h6, h7);
|
|
hnm->_dataPtr += sz - 8;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CLHNM_ReadHeader(hnm_t *hnm) {
|
|
int32 size = sizeof(hnm->_header);
|
|
CLFile_Read(*hnm->_file, &hnm->_header, &size);
|
|
|
|
hnm->_header._width = LE16(hnm->_header._width);
|
|
hnm->_header._height = LE16(hnm->_header._height);
|
|
hnm->_header._unusedFileSize = LE32(hnm->_header._unusedFileSize);
|
|
hnm->_header._numbFrame = LE32(hnm->_header._numbFrame);
|
|
hnm->_header._unusedTableOffset = LE32(hnm->_header._unusedTableOffset);
|
|
hnm->_header._unusedSpeed = LE16(hnm->_header._unusedSpeed);
|
|
hnm->_header._unusedMaxBuffer = LE16(hnm->_header._unusedMaxBuffer);
|
|
hnm->_header._bufferSize = LE32(hnm->_header._bufferSize);
|
|
hnm->_header._unusedUnknown = LE16(hnm->_header._unusedUnknown);
|
|
hnm->_header._bufferSize += 4096; //TODO: checkme
|
|
}
|
|
|
|
int16 CLHNM_GetVersion(hnm_t *hnm) {
|
|
if (hnm->_header._signature == BE32('HNM4'))
|
|
return 4;
|
|
return -1;
|
|
}
|
|
|
|
int CLHNM_GetFrameNum(hnm_t *hnm) {
|
|
return hnm->_frameNum;
|
|
}
|
|
|
|
void CLHNM_DeactivatePreloadBuffer() {
|
|
}
|
|
|
|
void CLHNM_Prepare2Read(hnm_t *hnm, int mode) {
|
|
}
|
|
|
|
void CLHNM_SetPosIntoFile(hnm_t *hnm, int32 pos) {
|
|
CLFile_SetPosition(*hnm->_file, 1, pos);
|
|
}
|
|
|
|
void CLHNM_Desentrelace320(byte *frame_buffer, byte *final_buffer, uint16 height) {
|
|
unsigned int *input = (unsigned int *)frame_buffer;
|
|
unsigned int *line0 = (unsigned int *)final_buffer;
|
|
unsigned int *line1 = (unsigned int *)(final_buffer + 320);
|
|
int count = (height) / 2;
|
|
while (count--) {
|
|
int16 i;
|
|
for (i = 0; i < 320 / 4; i++) {
|
|
unsigned int p0 = *input++;
|
|
unsigned int p4 = *input++;
|
|
#if 0
|
|
*line0++ = ((p4 & 0xFF00) >> 8) | ((p4 & 0xFF000000) >> 16) | ((p0 & 0xFF00) << 8) | (p0 & 0xFF000000);
|
|
// *line0++ = (p0 & 0xFF000000) | ((p0 & 0xFF00) << 8) | ((p4 & 0xFF000000) >> 16) | ((p4 & 0xFF00) >> 8);
|
|
*line1++ = ((p0 & 0xFF0000) << 8) | ((p0 & 0xFF) << 16) | ((p4 & 0xFF0000) >> 8) | (p4 & 0xFF);
|
|
#else
|
|
*line0++ = (p0 & 0xFF) | ((p0 & 0xFF0000) >> 8) | ((p4 & 0xFF) << 16) | ((p4 & 0xFF0000) << 8);
|
|
*line1++ = ((p0 & 0xFF00) >> 8) | ((p0 & 0xFF000000) >> 16) | ((p4 & 0xFF00) << 8) | (p4 & 0xFF000000);
|
|
#endif
|
|
}
|
|
line0 += 320 / 4;
|
|
line1 += 320 / 4;
|
|
}
|
|
}
|
|
|
|
} // End of namespace Cryo
|