mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-26 07:35:40 +00:00
241 lines
5.4 KiB
C++
241 lines
5.4 KiB
C++
/**
|
|
** Supermodel
|
|
** A Sega Model 3 Arcade Emulator.
|
|
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
|
**
|
|
** This file is part of Supermodel.
|
|
**
|
|
** Supermodel 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 3 of the License, or (at your option)
|
|
** any later version.
|
|
**
|
|
** Supermodel 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 Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
|
**/
|
|
|
|
/*
|
|
* huffman.cpp
|
|
*
|
|
* Amp library internal module.
|
|
*/
|
|
|
|
|
|
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
|
*/
|
|
|
|
/* huffman.c huffman decoding
|
|
*
|
|
* Created by: tomislav uzelac Mar,Apr 1996
|
|
* Last modified by: tomislav uzelac Mar 8 97
|
|
*/
|
|
#include <stdlib.h>
|
|
#include "audio.h"
|
|
#include "getbits.h"
|
|
|
|
#define HUFFMAN
|
|
#include "huffman.h"
|
|
|
|
#include "Supermodel.h"
|
|
|
|
static inline unsigned int viewbits(int n)
|
|
{
|
|
unsigned int pos,ret_value;
|
|
|
|
pos = data >> 3;
|
|
ret_value = buffer[pos] << 24 |
|
|
buffer[pos+1] << 16 |
|
|
buffer[pos+2] << 8 |
|
|
buffer[pos+3];
|
|
ret_value <<= data & 7;
|
|
ret_value >>= 32 - n;
|
|
|
|
return ret_value;
|
|
}
|
|
|
|
static inline void sackbits(int n)
|
|
{
|
|
data += n;
|
|
data &= 8*BUFFER_SIZE-1;
|
|
}
|
|
|
|
/* huffman_decode() is supposed to be faster now
|
|
* decodes one codeword and returns no. of bits
|
|
*/
|
|
static inline int huffman_decode(int tbl,int *x,int *y)
|
|
{
|
|
unsigned int chunk;
|
|
register unsigned int *h_tab;
|
|
register unsigned int lag;
|
|
register unsigned int half_lag;
|
|
int len;
|
|
|
|
h_tab=tables[tbl];
|
|
chunk=viewbits(19);
|
|
|
|
h_tab += h_cue[tbl][chunk >> (19-NC_O)];
|
|
|
|
len=(*h_tab>>8)&0x1f;
|
|
|
|
/* check for an immediate hit, so we can decode those short codes very fast
|
|
*/
|
|
if ((*h_tab>>(32-len)) != (chunk>>(19-len))) {
|
|
if (chunk >> (19-NC_O) < N_CUE-1)
|
|
lag=(h_cue[tbl][(chunk >> (19-NC_O))+1] -
|
|
h_cue[tbl][chunk >> (19-NC_O)]);
|
|
else {
|
|
/* we strongly depend on h_cue[N_CUE-1] to point to
|
|
* the last entry in the huffman table, so we should
|
|
* not get here anyway. if it didn't, we'd have to
|
|
* have another table with huffman tables lengths, and
|
|
* it would be a mess. just in case, scream&shout.
|
|
*/
|
|
|
|
ErrorLog("Internal error in MPEG decoder (%s:%d).", __FILE__, __LINE__); // h_cue clobbered
|
|
exit (-1);
|
|
}
|
|
chunk <<= 32-19;
|
|
chunk |= 0x1ff;
|
|
|
|
half_lag = lag >> 1;
|
|
|
|
h_tab += half_lag;
|
|
lag -= half_lag;
|
|
|
|
while (lag > 1) {
|
|
half_lag = lag >> 1;
|
|
|
|
if (*h_tab < chunk)
|
|
h_tab += half_lag;
|
|
else
|
|
h_tab -= half_lag;
|
|
|
|
lag -= half_lag;
|
|
}
|
|
|
|
len=(*h_tab>>8)&0x1f;
|
|
if ((*h_tab>>(32-len)) != (chunk>>(32-len))) {
|
|
if (*h_tab > chunk)
|
|
h_tab--;
|
|
else
|
|
h_tab++;
|
|
|
|
len=(*h_tab>>8)&0x1f;
|
|
}
|
|
}
|
|
sackbits(len);
|
|
*x=(*h_tab>>4)&0xf;
|
|
*y=*h_tab&0xf;
|
|
return len;
|
|
}
|
|
|
|
static inline int _qsign(int x,int *q)
|
|
{
|
|
int ret_value=0,i;
|
|
for (i=3;i>=0;i--)
|
|
if ((x>>i) & 1) {
|
|
if (getbits(1)) *q++=-1;
|
|
else *q++=1;
|
|
ret_value++;
|
|
}
|
|
else *q++=0;
|
|
return ret_value;
|
|
}
|
|
|
|
int decode_huffman_data(struct SIDE_INFO *info,int gr,int ch,int ssize)
|
|
{
|
|
int l,i,cnt,x,y;
|
|
int q[4],r[3],linbits[3],tr[4]={0,0,0,0};
|
|
int big_value = info->big_values[gr][ch] << 1;
|
|
|
|
for (l=0;l<3;l++) {
|
|
tr[l]=info->table_select[gr][ch][l];
|
|
linbits[l]=t_linbits[info->table_select[gr][ch][l]];
|
|
}
|
|
|
|
tr[3]=32+info->count1table_select[gr][ch];
|
|
|
|
/* we have to be careful here because big_values are not necessarily
|
|
* aligned with sfb boundaries
|
|
*/
|
|
if (!info->window_switching_flag[gr][ch] && info->block_type[gr][ch]==0) {
|
|
|
|
/* this code needed some cleanup
|
|
*/
|
|
r[0]=t_l[info->region0_count[gr][ch]] + 1;
|
|
if (r[0] > big_value)
|
|
r[0]=r[1]=big_value;
|
|
else {
|
|
r[1]=t_l[ info->region0_count[gr][ch] + info->region1_count[gr][ch] + 1 ] + 1;
|
|
if (r[1] > big_value)
|
|
r[1]=big_value;
|
|
}
|
|
r[2]=big_value;
|
|
|
|
} else {
|
|
|
|
if (info->block_type[gr][ch]==2 && info->mixed_block_flag[gr][ch]==0)
|
|
r[0]=3*(t_s[2]+1);
|
|
else
|
|
r[0]=t_l[7]+1;
|
|
|
|
if (r[0] > big_value)
|
|
r[0]=big_value;
|
|
|
|
r[1]=r[2]=big_value;
|
|
}
|
|
|
|
l=0; cnt=0;
|
|
for (i=0;i<3;i++) {
|
|
for (;l<r[i];l+=2) {
|
|
int j = linbits[i];
|
|
|
|
cnt+=huffman_decode(tr[i],&x,&y);
|
|
|
|
if (x==15 && j>0) {
|
|
x+=getbits(j);
|
|
cnt+=j;
|
|
}
|
|
if (x) {
|
|
if (getbits(1)) x=-x;
|
|
cnt++;
|
|
}
|
|
if (y==15 && j>0) {
|
|
y+=getbits(j);
|
|
cnt+=j;
|
|
}
|
|
if (y) {
|
|
if (getbits(1)) y=-y;
|
|
cnt++;
|
|
}
|
|
|
|
is[ch][l]=x;
|
|
is[ch][l+1]=y;
|
|
}
|
|
}
|
|
while ((cnt < info->part2_3_length[gr][ch]-ssize) && (l<576)) {
|
|
cnt+=huffman_decode(tr[3],&x,&y);
|
|
cnt+=_qsign(x,q);
|
|
for (i=0;i<4;i++) is[ch][l+i]=q[i]; /* ziher je ziher, is[578]*/
|
|
l+=4;
|
|
}
|
|
|
|
/* set position to start of the next gr/ch
|
|
*/
|
|
if (cnt != info->part2_3_length[gr][ch] - ssize ) {
|
|
data-=cnt-(info->part2_3_length[gr][ch] - ssize);
|
|
data&= 8*BUFFER_SIZE - 1;
|
|
}
|
|
if (l<576) non_zero[ch]=l;
|
|
else non_zero[ch]=576;
|
|
/* zero out everything else
|
|
*/
|
|
for (;l<576;l++) is[ch][l]=0;
|
|
return 1;
|
|
}
|