mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-25 23:25:40 +00:00
- Improved 68K interface. Now supports context switching.
- CSoundBoard is not derived from CBus. - Optimized sound board memory handlers (now using switch statements). - Added DSB emulation (based on R. Belmont's M1 source code). - Improved ROM loading: only unique ROMs (those not shared amongst games) are used to identify games. The ROM loader will no longer get confused as easily. - General cleanup here and there, removed unused Render.h file.
This commit is contained in:
parent
62f695cc96
commit
ddd6fa92ef
|
@ -119,11 +119,11 @@ CC = "$(VC_BIN)\cl.exe"
|
|||
LD = "$(VC_BIN)\link.exe"
|
||||
COMPILER_FLAGS = /I "$(SDL_INCLUDEPATH)" /I "$(ZLIB_INCLUDEPATH)" /I "$(DIRECTX_INCLUDEPATH)" /I "Src" /I "Src\\OSD" /I "Src\\OSD\\SDL" \
|
||||
/I "Src\\OSD\\Windows" /Ox /D "SUPERMODEL_WIN32" /D "GLEW_STATIC" /D "_MBCS" /D "_CRT_SECURE_NO_WARNINGS" /MT /Gy /W3 /nologo /c /Zi /GL \
|
||||
/D "DEBUG" /DEBUG
|
||||
/DEBUG /Zi #/D "DEBUG" /DEBUG
|
||||
CFLAGS = $(COMPILER_FLAGS) /TC
|
||||
CPPFLAGS = $(COMPILER_FLAGS) /TP /EHsc
|
||||
LFLAGS = /MACHINE:$(ARCH) $(ARCH_LIBS) /LIBPATH:"$(SDL_LIBPATH)" /LIBPATH:"$(ZLIB_LIBPATH)" /LIBPATH:"$(DIRECTX_LIBPATH)" /OUT:"$(OUTFILE)" \
|
||||
/MANIFEST:NO /SUBSYSTEM:CONSOLE /NOLOGO /OPT:REF /OPT:ICF /DYNAMICBASE /NXCOMPAT /LTCG #/DEBUG
|
||||
/MANIFEST:NO /SUBSYSTEM:CONSOLE /NOLOGO /OPT:REF /OPT:ICF /DYNAMICBASE /NXCOMPAT /LTCG /DEBUG
|
||||
OBJ_LIBS = kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \
|
||||
odbc32.lib odbccp32.lib OpenGL32.lib GLu32.lib SDL.lib SDLmain.lib zlib.lib dinput8.lib dxguid.lib
|
||||
|
||||
|
@ -160,10 +160,15 @@ OBJ = $(OBJ_DIR)/PPCDisasm.obj $(OBJ_DIR)/Games.obj $(OBJ_DIR)/INIFile.obj $(OBJ
|
|||
$(OBJ_DIR)/ROMLoad.obj $(OBJ_DIR)/unzip.obj $(OBJ_DIR)/ioapi.obj $(OBJ_DIR)/Error.obj $(OBJ_DIR)/glew.obj $(OBJ_DIR)/Shader.obj \
|
||||
$(OBJ_DIR)/Real3D.obj $(OBJ_DIR)/Render3D.obj $(OBJ_DIR)/Models.obj $(OBJ_DIR)/Render2D.obj $(OBJ_DIR)/TileGen.obj \
|
||||
$(OBJ_DIR)/Model3.obj $(OBJ_DIR)/ppc.obj $(OBJ_DIR)/Main.obj $(OBJ_DIR)/Audio.obj $(OBJ_DIR)/Thread.obj $(OBJ_DIR)/SoundBoard.obj \
|
||||
$(OBJ_DIR)/SCSP.obj $(OBJ_DIR)/SCSPDSP.obj $(OBJ_DIR)/M68K.obj $(OBJ_DIR)/m68kcpu.obj $(OBJ_DIR)/m68kopnz.obj $(OBJ_DIR)/m68kopdm.obj \
|
||||
$(OBJ_DIR)/m68kopac.obj $(OBJ_DIR)/m68kops.obj $(OBJ_DIR)/IRQ.obj $(OBJ_DIR)/53C810.obj $(OBJ_DIR)/PCI.obj $(OBJ_DIR)/RTC72421.obj \
|
||||
$(OBJ_DIR)/SCSP.obj $(OBJ_DIR)/SCSPDSP.obj $(OBJ_DIR)/68K.obj $(OBJ_DIR)/m68kcpu.obj $(OBJ_DIR)/m68kopnz.obj $(OBJ_DIR)/m68kopdm.obj \
|
||||
$(OBJ_DIR)/m68kopac.obj $(OBJ_DIR)/m68kops.obj $(OBJ_DIR)/DSB.obj $(OBJ_DIR)/Z80.obj \
|
||||
$(OBJ_DIR)/IRQ.obj $(OBJ_DIR)/53C810.obj $(OBJ_DIR)/PCI.obj $(OBJ_DIR)/RTC72421.obj \
|
||||
$(OBJ_DIR)/MPC10x.obj $(OBJ_DIR)/Input.obj $(OBJ_DIR)/Inputs.obj $(OBJ_DIR)/InputSource.obj $(OBJ_DIR)/InputSystem.obj \
|
||||
$(OBJ_DIR)/InputTypes.obj $(OBJ_DIR)/MultiInputSource.obj $(OBJ_DIR)/SDLInputSystem.obj $(OBJ_DIR)/DirectInputSystem.obj
|
||||
$(OBJ_DIR)/InputTypes.obj $(OBJ_DIR)/MultiInputSource.obj $(OBJ_DIR)/SDLInputSystem.obj $(OBJ_DIR)/DirectInputSystem.obj \
|
||||
$(OBJ_DIR)/amp_audio.obj $(OBJ_DIR)/amp_dump.obj $(OBJ_DIR)/amp_getbits.obj $(OBJ_DIR)/amp_getdata.obj $(OBJ_DIR)/amp_huffman.obj \
|
||||
$(OBJ_DIR)/amp_layer2.obj $(OBJ_DIR)/amp_layer3.obj $(OBJ_DIR)/amp_misc2.obj $(OBJ_DIR)/amp_position.obj $(OBJ_DIR)/amp_transform.obj \
|
||||
$(OBJ_DIR)/amp_util.obj
|
||||
|
||||
|
||||
# If built-in debugger enabled, include all debugging classes
|
||||
ifeq ($(strip $(ENABLE_DEBUGGER)),yes)
|
||||
|
@ -278,6 +283,9 @@ $(OBJ_DIR)/%.obj: Src/CPU/PowerPC/%.cpp Src/CPU/PowerPC/%.h Src/CPU/PowerPC/ppc6
|
|||
$(OBJ_DIR)/%.obj: Src/CPU/68K/%.cpp Src/CPU/68K/%.h $(HEADERS)
|
||||
$(CC) $< $(CPPFLAGS) /Fo$(OBJ_DIR)/$(*F).obj
|
||||
|
||||
$(OBJ_DIR)/%.obj: Src/CPU/Z80/%.cpp Src/CPU/Z80/%.h $(HEADERS)
|
||||
$(CC) $< $(CPPFLAGS) /Fo$(OBJ_DIR)/$(*F).obj
|
||||
|
||||
$(OBJ_DIR)/%.obj: Src/Inputs/%.cpp Src/Inputs/%.h $(HEADERS)
|
||||
$(CC) $< $(CPPFLAGS) /Fo$(OBJ_DIR)/$(*F).obj
|
||||
|
||||
|
@ -295,3 +303,14 @@ $(OBJ_DIR)/%.obj: Src/Pkgs/%.c Src/Pkgs/%.h
|
|||
|
||||
$(OBJ_DIR)/%.obj: Src/Pkgs/%.c
|
||||
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/$(*F).obj
|
||||
|
||||
#
|
||||
# AMP MPEG decoder library
|
||||
#
|
||||
# To eliminate name conflicts, object files have the prefix "amp_" attached.
|
||||
#
|
||||
$(OBJ_DIR)/amp_%.obj: Src/Sound/MPEG/%.cpp Src/Sound/MPEG/%.h
|
||||
$(CC) $< $(CPPFLAGS) /Fo$(OBJ_DIR)/amp_$(*F).obj
|
||||
|
||||
$(OBJ_DIR)/amp_%.obj: Src/Sound/MPEG/%.cpp
|
||||
$(CC) $< $(CPPFLAGS) /Fo$(OBJ_DIR)/amp_$(*F).obj
|
|
@ -20,7 +20,7 @@
|
|||
**/
|
||||
|
||||
/*
|
||||
* M68K.cpp
|
||||
* 68K.cpp
|
||||
*
|
||||
* 68K CPU interface. This is presently just a wrapper for the Musashi 68K core
|
||||
* and therefore, only a single CPU is supported. In the future, we may want to
|
||||
|
@ -30,24 +30,26 @@
|
|||
#include "Supermodel.h"
|
||||
#include "Musashi/m68k.h" // Musashi 68K core
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Internal Context
|
||||
|
||||
An active context must be mapped before calling M68K interface functions. Only
|
||||
the bus and IRQ handlers are copied here; the CPU context is passed directly
|
||||
to Musashi.
|
||||
******************************************************************************/
|
||||
|
||||
// Bus
|
||||
static CBus *Bus = NULL;
|
||||
|
||||
// IRQ callback
|
||||
static int (*IRQAck)(int nIRQ) = NULL;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
68K Interface
|
||||
******************************************************************************/
|
||||
|
||||
// Interface function pointers
|
||||
static int (*IRQAck)(int nIRQ) = NULL;
|
||||
static UINT8 (*Fetch8)(UINT32 addr) = NULL;
|
||||
static UINT16 (*Fetch16)(UINT32 addr) = NULL;
|
||||
static UINT32 (*Fetch32)(UINT32 addr) = NULL;
|
||||
static UINT8 (*Read8)(UINT32 addr) = NULL;
|
||||
static UINT16 (*Read16)(UINT32 addr) = NULL;
|
||||
static UINT32 (*Read32)(UINT32 addr) = NULL;
|
||||
static void (*Write8)(UINT32 addr, UINT8 data) = NULL;
|
||||
static void (*Write16)(UINT32 addr, UINT16 data) = NULL;
|
||||
static void (*Write32)(UINT32 addr, UINT32 data) = NULL;
|
||||
|
||||
extern "C" {
|
||||
|
||||
// CPU state
|
||||
|
||||
UINT32 M68KGetARegister(int n)
|
||||
|
@ -110,6 +112,7 @@ int M68KRun(int numCycles)
|
|||
void M68KReset(void)
|
||||
{
|
||||
m68k_pulse_reset();
|
||||
DebugLog("68K reset\n");
|
||||
}
|
||||
|
||||
// Callback setup
|
||||
|
@ -119,49 +122,26 @@ void M68KSetIRQCallback(int (*F)(int nIRQ))
|
|||
IRQAck = F;
|
||||
}
|
||||
|
||||
void M68KSetFetch8Callback(UINT8 (*F)(UINT32))
|
||||
void M68KAttachBus(CBus *BusPtr)
|
||||
{
|
||||
Fetch8 = F;
|
||||
Bus = BusPtr;
|
||||
DebugLog("Attached bus to 68K\n");
|
||||
}
|
||||
|
||||
void M68KSetFetch16Callback(UINT16 (*F)(UINT32))
|
||||
// Context switching
|
||||
|
||||
void M68KGetContext(M68KCtx *Dest)
|
||||
{
|
||||
Fetch16 = F;
|
||||
Dest->IRQAck = IRQAck;
|
||||
Dest->Bus = Bus;
|
||||
m68k_get_context(Dest->musashiCtx);
|
||||
}
|
||||
|
||||
void M68KSetFetch32Callback(UINT32 (*F)(UINT32))
|
||||
void M68KSetContext(M68KCtx *Src)
|
||||
{
|
||||
Fetch32 = F;
|
||||
}
|
||||
|
||||
void M68KSetRead8Callback(UINT8 (*F)(UINT32))
|
||||
{
|
||||
Read8 = F;
|
||||
}
|
||||
|
||||
void M68KSetRead16Callback(UINT16 (*F)(UINT32))
|
||||
{
|
||||
Read16 = F;
|
||||
}
|
||||
|
||||
void M68KSetRead32Callback(UINT32 (*F)(UINT32))
|
||||
{
|
||||
Read32 = F;
|
||||
}
|
||||
|
||||
void M68KSetWrite8Callback(void (*F)(UINT32,UINT8))
|
||||
{
|
||||
Write8 = F;
|
||||
}
|
||||
|
||||
void M68KSetWrite16Callback(void (*F)(UINT32,UINT16))
|
||||
{
|
||||
Write16 = F;
|
||||
}
|
||||
|
||||
void M68KSetWrite32Callback(void (*F)(UINT32,UINT32))
|
||||
{
|
||||
Write32 = F;
|
||||
IRQAck = Src->IRQAck;
|
||||
Bus = Src->Bus;
|
||||
m68k_set_context(Src->musashiCtx);
|
||||
}
|
||||
|
||||
// One-time initialization
|
||||
|
@ -171,11 +151,12 @@ BOOL M68KInit(void)
|
|||
m68k_init();
|
||||
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||
m68k_set_int_ack_callback(M68KIRQCallback);
|
||||
Bus = NULL;
|
||||
|
||||
DebugLog("Initialized 68K\n");
|
||||
return OKAY;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Musashi 68K Handlers
|
||||
|
@ -187,55 +168,58 @@ extern "C" {
|
|||
|
||||
int M68KIRQCallback(int nIRQ)
|
||||
{
|
||||
if (NULL == IRQAck)
|
||||
if (NULL == IRQAck) // no handler, use default behavior
|
||||
{
|
||||
m68k_set_irq(0); // clear line
|
||||
return M68K_IRQ_AUTOVECTOR;
|
||||
}
|
||||
else
|
||||
return IRQAck(nIRQ);
|
||||
}
|
||||
|
||||
unsigned int FASTCALL M68KFetch8(unsigned int a)
|
||||
{
|
||||
return Fetch8(a);
|
||||
return Bus->Read8(a);
|
||||
}
|
||||
|
||||
unsigned int FASTCALL M68KFetch16(unsigned int a)
|
||||
{
|
||||
return Fetch16(a);
|
||||
return Bus->Read16(a);
|
||||
}
|
||||
|
||||
unsigned int FASTCALL M68KFetch32(unsigned int a)
|
||||
{
|
||||
return Fetch32(a);
|
||||
return Bus->Read32(a);
|
||||
}
|
||||
|
||||
unsigned int FASTCALL M68KRead8(unsigned int a)
|
||||
{
|
||||
return Read8(a);
|
||||
return Bus->Read8(a);
|
||||
}
|
||||
|
||||
unsigned int FASTCALL M68KRead16(unsigned int a)
|
||||
{
|
||||
return Read16(a);
|
||||
return Bus->Read16(a);
|
||||
}
|
||||
|
||||
unsigned int FASTCALL M68KRead32(unsigned int a)
|
||||
{
|
||||
return Read32(a);
|
||||
return Bus->Read32(a);
|
||||
}
|
||||
|
||||
void FASTCALL M68KWrite8(unsigned int a, unsigned int d)
|
||||
{
|
||||
Write8(a, d);
|
||||
Bus->Write8(a, d);
|
||||
}
|
||||
|
||||
void FASTCALL M68KWrite16(unsigned int a, unsigned int d)
|
||||
{
|
||||
Write16(a, d);
|
||||
Bus->Write16(a, d);
|
||||
}
|
||||
|
||||
void FASTCALL M68KWrite32(unsigned int a, unsigned int d)
|
||||
{
|
||||
Write32(a, d);
|
||||
Bus->Write32(a, d);
|
||||
}
|
||||
|
||||
} // extern "C"
|
|
@ -20,26 +20,21 @@
|
|||
**/
|
||||
|
||||
/*
|
||||
* M68K.h
|
||||
* 68K.h
|
||||
*
|
||||
* Header file for 68K CPU interface. Caution: there is only a single 68K core
|
||||
* available to Supermodel right now. Therefore, multiple 68K CPUs are not
|
||||
* presently supported. See M68K.c for more details.
|
||||
* Header file for 68K CPU interface. Caution: 68K emulator is not thread-safe.
|
||||
*
|
||||
* TO-DO List:
|
||||
* -----------
|
||||
* - Optimize things, perhaps by using FASTCALL
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_M68K_H
|
||||
#define INCLUDED_M68K_H
|
||||
#ifndef INCLUDED_68K_H
|
||||
#define INCLUDED_68K_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "Musashi/m68k.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "CPU/Bus.h"
|
||||
|
||||
// This doesn't work for now (needs to be added to the prototypes in m68k.h for m68k_read_memory*)
|
||||
//#ifndef FASTCALL
|
||||
|
@ -57,8 +52,44 @@ extern "C" {
|
|||
#define M68K_IRQ_SPURIOUS M68K_INT_ACK_SPURIOUS // signals a spurious interrupt
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
CPU Context
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* M68KCtx:
|
||||
*
|
||||
* Complete state of a single 68K. Do NOT manipulate these directly. Set the
|
||||
* context and then use the M68K* functions below to attach a bus and IRQ
|
||||
* callback to the active context.
|
||||
*/
|
||||
typedef struct SM68KCtx
|
||||
{
|
||||
public:
|
||||
CBus *Bus; // memory handlers
|
||||
int (*IRQAck)(int); // IRQ acknowledge callback
|
||||
unsigned char *musashiCtx; // holds CPU state
|
||||
|
||||
SM68KCtx(void)
|
||||
{
|
||||
Bus = NULL;
|
||||
IRQAck = NULL;
|
||||
musashiCtx = new unsigned char[m68k_context_size()];
|
||||
}
|
||||
|
||||
~SM68KCtx(void)
|
||||
{
|
||||
Bus = NULL;
|
||||
IRQAck = NULL;
|
||||
delete [] musashiCtx;
|
||||
}
|
||||
} M68KCtx;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
68K Interface
|
||||
|
||||
Unless otherwise noted, all functions operate on the active context.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
|
@ -124,8 +155,8 @@ extern void M68KReset(void);
|
|||
/*
|
||||
* M68KSetIRQCallback(F):
|
||||
*
|
||||
* Installs an interrupt acknowledge callback. The default behavior is to
|
||||
* always assume autovectored interrupts.
|
||||
* Installs an interrupt acknowledge callback for the currently active CPU. The
|
||||
* default behavior is to always assume autovectored interrupts.
|
||||
*
|
||||
* Parameters:
|
||||
* F Callback function.
|
||||
|
@ -133,44 +164,50 @@ extern void M68KReset(void);
|
|||
extern void M68KSetIRQCallback(int (*F)(int));
|
||||
|
||||
/*
|
||||
* M68KSetFetch8Callback(F):
|
||||
* M68KSetFetch16Callback(F):
|
||||
* M68KSetFetch32Callback(F):
|
||||
* M68KSetRead8Callback(F):
|
||||
* M68KSetRead16Callback(F):
|
||||
* M68KSetRead32Callback(F):
|
||||
* M68KSetWrite8Callback(F):
|
||||
* M68KSetWrite16Callback(F):
|
||||
* M68KSetWrite32Callback(F):
|
||||
* M68KAttachBus(CBus *BusPtr):
|
||||
*
|
||||
* Installs address space handler callbacks. There is no default behavior;
|
||||
* these must all be set up before any 68K-related emulation functions are
|
||||
* invoked.
|
||||
* Attaches a bus object to the 68K, which will be used to perform all address
|
||||
* space accesses. The 8, 16, and 32-bit read and write handlers are used.
|
||||
* This must be set up before any 68K-related emulation functions are invoked
|
||||
* or the program will crash!
|
||||
*
|
||||
* Parameters:
|
||||
* F Callback function.
|
||||
* BusPtr Pointer to bus object to use for all address space accesses.
|
||||
*/
|
||||
extern void M68KSetFetch8Callback(UINT8 (*F)(UINT32));
|
||||
extern void M68KSetFetch16Callback(UINT16 (*F)(UINT32));
|
||||
extern void M68KSetFetch32Callback(UINT32 (*F)(UINT32));
|
||||
extern void M68KSetRead8Callback(UINT8 (*F)(UINT32));
|
||||
extern void M68KSetRead16Callback(UINT16 (*F)(UINT32));
|
||||
extern void M68KSetRead32Callback(UINT32 (*F)(UINT32));
|
||||
extern void M68KSetWrite8Callback(void (*F)(UINT32,UINT8));
|
||||
extern void M68KSetWrite16Callback(void (*F)(UINT32,UINT16));
|
||||
extern void M68KSetWrite32Callback(void (*F)(UINT32,UINT32));
|
||||
extern void M68KAttachBus(CBus *BusPtr);
|
||||
|
||||
/*
|
||||
* M68KInit():
|
||||
*
|
||||
* Initializes the 68K emulator. Must be called once per program session prior
|
||||
* to any other 68K interface calls.
|
||||
* to any 68K emulation functions. A context must be mapped before calling
|
||||
* this.
|
||||
*
|
||||
* Returns:
|
||||
* Always returns OKAY.
|
||||
*/
|
||||
extern BOOL M68KInit(void);
|
||||
|
||||
/*
|
||||
* M68KGetContext(M68KCtx *Dest):
|
||||
*
|
||||
* Copies the internal (active) 68K context back to the destination.
|
||||
*
|
||||
* Parameters:
|
||||
* Dest Location to which to copy 68K context.
|
||||
*/
|
||||
extern void M68KGetContext(M68KCtx *Dest);
|
||||
|
||||
/*
|
||||
* M68KSetContext(M68KCtx *Src):
|
||||
*
|
||||
* Sets the specified 68K context by copying it to the internal context.
|
||||
*
|
||||
* Parameters:
|
||||
* Src Location from which to copy 68K context.
|
||||
*/
|
||||
extern void M68KSetContext(M68KCtx *Src);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
68K Handlers
|
||||
|
@ -178,6 +215,8 @@ extern BOOL M68KInit(void);
|
|||
Intended for use directly by the 68K core.
|
||||
******************************************************************************/
|
||||
|
||||
extern "C" {
|
||||
|
||||
/*
|
||||
* M68KIRQCallback(nIRQ):
|
||||
*
|
||||
|
@ -243,10 +282,7 @@ void FASTCALL M68KWrite8(unsigned int a, unsigned int d);
|
|||
void FASTCALL M68KWrite16(unsigned int a, unsigned int d);
|
||||
void FASTCALL M68KWrite32(unsigned int a, unsigned int d);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
} // extern "C"
|
||||
|
||||
|
||||
#endif // INCLUDED_M68K_H
|
||||
#endif // INCLUDED_68K_H
|
|
@ -203,7 +203,20 @@
|
|||
Supermodel Interface
|
||||
******************************************************************************/
|
||||
|
||||
#include "../M68K.h" // Supermodel's 68K interface
|
||||
// Supermodel 68K interface (these functions defined in CPU/68K.cpp)
|
||||
//#ifndef FASTCALL (this doesn't work for now (needs to be added to the prototypes in m68k.h for m68k_read_memory*)
|
||||
#undef FASTCALL
|
||||
#define FASTCALL
|
||||
//#endif
|
||||
unsigned int FASTCALL M68KFetch8(unsigned int a);
|
||||
unsigned int FASTCALL M68KFetch16(unsigned int a);
|
||||
unsigned int FASTCALL M68KFetch32(unsigned int a);
|
||||
unsigned int FASTCALL M68KRead8(unsigned int a);
|
||||
unsigned int FASTCALL M68KRead16(unsigned int a);
|
||||
unsigned int FASTCALL M68KRead32(unsigned int a);
|
||||
void FASTCALL M68KWrite8(unsigned int a, unsigned int d);
|
||||
void FASTCALL M68KWrite16(unsigned int a, unsigned int d);
|
||||
void FASTCALL M68KWrite32(unsigned int a, unsigned int d);
|
||||
|
||||
/* Read data relative to the PC */
|
||||
#define m68k_read_pcrelative_8(address) M68KFetch8(address)
|
||||
|
|
390
Src/Games.cpp
390
Src/Games.cpp
|
@ -23,6 +23,11 @@
|
|||
* Games.cpp
|
||||
*
|
||||
* Model 3 game and ROM information.
|
||||
*
|
||||
* ROMs are loaded in their native orientation. For example, PowerPC and 68K
|
||||
* ROMs will be laid out in memory as they would appear to those processors.
|
||||
* Any byte swapping that is done for performance-enhancing reasons by the
|
||||
* emulator is handled elsewhere.
|
||||
*/
|
||||
|
||||
#include "Supermodel.h"
|
||||
|
@ -42,43 +47,38 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_JOYSTICK1|GAME_INPUT_FIGHTING,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
{ "CROM", "epr21214c.17", 0x8DC0A85C, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROM", "epr21215c.18", 0xE2878221, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr21216c.19", 0x867D3A0F, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr21217c.20", 0xEA8C30CE, 0x200000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROM", "epr21216c.19", 0x867D3A0F, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr21215c.18", 0xE2878221, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr21214c.17", 0x8DC0A85C, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM0
|
||||
{ "CROMxx", "mpr21134.1", 0x65399935, 0x800000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21135.2", 0xF3FA7C50, 0x800000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21136.3", 0xB730FE50, 0x800000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21137.4", 0x3572D417, 0x800000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21136.3", 0xB730FE50, 0x800000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21135.2", 0xF3FA7C50, 0x800000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21134.1", 0x65399935, 0x800000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM1
|
||||
{ "CROMxx", "mpr21138.5", 0xA9A2DE2C, 0x800000, 2, 0x2000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21139.6", 0x06D441F5, 0x800000, 2, 0x2000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21140.7", 0x1390746D, 0x800000, 2, 0x2000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21141.8", 0x1D0763CB, 0x800000, 2, 0x2000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21140.7", 0x1390746D, 0x800000, 2, 0x2000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21139.6", 0x06D441F5, 0x800000, 2, 0x2000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21138.5", 0xA9A2DE2C, 0x800000, 2, 0x2000006, 8, TRUE },
|
||||
|
||||
// Banked CROM1
|
||||
{ "CROMxx", "mpr21142.9", 0xDA35CD51, 0x400000, 2, 0x4000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21143.10", 0xDDCADA10, 0x400000, 2, 0x4000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21144.11", 0xD93D778C, 0x400000, 2, 0x4000002, 8, TRUE },
|
||||
// Banked CROM2
|
||||
{ "CROMxx", "mpr21145.12", 0x0E6A3AE3, 0x400000, 2, 0x4000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21144.11", 0xD93D778C, 0x400000, 2, 0x4000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21143.10", 0xDDCADA10, 0x400000, 2, 0x4000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21142.9", 0xDA35CD51, 0x400000, 2, 0x4000006, 8, TRUE },
|
||||
|
||||
// Banked CROM2 (note: appears at offset 0x6000000 rather than 0x5000000 as expected)
|
||||
{ "CROMxx", "mpr21146.13", 0x85F55311, 0x400000, 2, 0x6000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21147.14", 0xA1F2B73F, 0x400000, 2, 0x6000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21148.15", 0x56D980AD, 0x400000, 2, 0x6000002, 8, TRUE },
|
||||
// Banked CROM3 (note: appears at offset 0x6000000 rather than 0x5000000 as expected)
|
||||
{ "CROMxx", "mpr21149.16", 0x9E4EBE58, 0x400000, 2, 0x6000000, 8, TRUE },
|
||||
|
||||
// Banked CROM0
|
||||
//{ "CROMxx", "mpr21150.22", 0x125201CE, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
//{ "CROMxx", "mpr21151.23", 0x599527B9, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
//{ "CROMxx", "mpr21152.24", 0x0AFDEE87, 0x400000, 2, 0x0000000, 8, TRUE },
|
||||
//{ "CROMxx", "mpr21153.25", 0x4155F307, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21148.15", 0x56D980AD, 0x400000, 2, 0x6000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21147.14", 0xA1F2B73F, 0x400000, 2, 0x6000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21146.13", 0x85F55311, 0x400000, 2, 0x6000006, 8, TRUE },
|
||||
|
||||
// Video ROM
|
||||
{ "VROM", "mpr21154.26", 0x3B76F8E8, 0x400000, 2, 0, 32, FALSE },
|
||||
|
@ -98,6 +98,20 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr21168.40", 0xC58BE980, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr21169.41", 0xAA3B2CC0, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr21218.21", 0x5821001A, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr21150.22", 0x125201CE, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr21152.24", 0x0AFDEE87, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr21151.23", 0x599527B9, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "Samples","mpr21153.25", 0x4155F307, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
// Unused ROMs
|
||||
//{ "Prog", "epr21219.ic2", 0x4E042B21, 0x20000, 2, 0x??????, 2, TRUE },
|
||||
//{ "ROM", "mpr21170.ic18", 0xF51F7CE3, 0x400000, 2, 0x??????, 2, FALSE },
|
||||
//{ "ROM", "mpr21171.ic20", 0x8D3BD5B6, 0x400000, 2, 0x??????, 2, FALSE },
|
||||
//{ "ROM", "mpr21172.ic22", 0xBE221E27, 0x400000, 2, 0x??????, 2, FALSE },
|
||||
//{ "ROM", "mpr21173.ic24", 0xCA7226D6, 0x400000, 2, 0x??????, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
},
|
||||
|
@ -114,42 +128,38 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
{ "CROM", "epr20352.17", 0xC92C2545, 0x200000, 2, 0x0400006, 8, TRUE },
|
||||
{ "CROM", "epr20354.18", 0xACA62BF8, 0x200000, 2, 0x0400004, 8, TRUE },
|
||||
{ "CROM", "epr20353.19", 0xBADF5F04, 0x200000, 2, 0x0400002, 8, TRUE },
|
||||
{ "CROM", "epr20355.20", 0x7A784E67, 0x200000, 2, 0x0400000, 8, TRUE },
|
||||
{ "CROM", "epr20353.19", 0xBADF5F04, 0x200000, 2, 0x0400002, 8, TRUE },
|
||||
{ "CROM", "epr20354.18", 0xACA62BF8, 0x200000, 2, 0x0400004, 8, TRUE },
|
||||
{ "CROM", "epr20352.17", 0xC92C2545, 0x200000, 2, 0x0400006, 8, TRUE },
|
||||
|
||||
// Banked CROM0
|
||||
{ "CROMxx", "mpr20318.1", 0xB0CAD2C8, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr20319.2", 0x228047F3, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr20320.3", 0xEDC9A9E5, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr20321.4", 0x698A97EE, 0x400000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr20320.3", 0xEDC9A9E5, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr20319.2", 0x228047F3, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr20318.1", 0xB0CAD2C8, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM1
|
||||
{ "CROMxx", "mpr20322.5", 0x2F69B205, 0x400000, 2, 0x1000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr20323.6", 0x075DE2AE, 0x400000, 2, 0x1000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr20324.7", 0x8F5848D0, 0x400000, 2, 0x1000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr20325.8", 0xCB0EB133, 0x400000, 2, 0x1000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr20324.7", 0x8F5848D0, 0x400000, 2, 0x1000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr20323.6", 0x075DE2AE, 0x400000, 2, 0x1000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr20322.5", 0x2F69B205, 0x400000, 2, 0x1000006, 8, TRUE },
|
||||
|
||||
// Banked CROM2
|
||||
{ "CROMxx", "mpr20326.9", 0xB63E1CB4, 0x400000, 2, 0x2000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr20327.10", 0xF55F51B2, 0x400000, 2, 0x2000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr20328.11", 0x5FA5E9F5, 0x400000, 2, 0x2000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr20329.12", 0x0807EA33, 0x400000, 2, 0x2000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr20328.11", 0x5FA5E9F5, 0x400000, 2, 0x2000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr20327.10", 0xF55F51B2, 0x400000, 2, 0x2000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr20326.9", 0xB63E1CB4, 0x400000, 2, 0x2000006, 8, TRUE },
|
||||
|
||||
// Banked CROM3
|
||||
{ "CROMxx", "mpr20330.13", 0xFBC7BBD5, 0x400000, 2, 0x3000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr20331.14", 0xC4C45FB1, 0x400000, 2, 0x3000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr20332.15", 0x500DB1EE, 0x400000, 2, 0x3000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr20333.16", 0x76B8E0FA, 0x400000, 2, 0x3000000, 8, TRUE },
|
||||
|
||||
// Banked CROM4
|
||||
//{ "CROMxx", "epr20356.21", 0x4E4015D0, 0x80000, 2, 0x3000004, 8, TRUE },
|
||||
//{ "CROMxx", "mpr20334.22", 0xDE1D67CD, 0x400000, 2, 0x3000002, 8, TRUE },
|
||||
//{ "CROMxx", "mpr20335.24", 0x7300D0A2, 0x400000, 2, 0x3000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr20332.15", 0x500DB1EE, 0x400000, 2, 0x3000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr20331.14", 0xC4C45FB1, 0x400000, 2, 0x3000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr20330.13", 0xFBC7BBD5, 0x400000, 2, 0x3000006, 8, TRUE },
|
||||
|
||||
// Video ROM
|
||||
{ "VROM", "mpr20336.26", 0x261E3D39, 0x400000, 2, 0, 32, FALSE },
|
||||
|
@ -169,6 +179,11 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr20350.40", 0xC48F9ACE, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr20351.41", 0x1FBD3E10, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr20356.21", 0x4E4015D0, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr20334.22", 0xDE1D67CD, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr20335.24", 0x7300D0A2, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
},
|
||||
|
@ -185,25 +200,20 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
{ "CROM", "epr21435.17", 0x9B169446, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROM", "epr21433.18", 0x60AA9D76, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr21436.19", 0x22BCBCA3, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr21434.20", 0xE028D7CA, 0x200000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROM", "epr21436.19", 0x22BCBCA3, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr21433.18", 0x60AA9D76, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr21435.17", 0x9B169446, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM0
|
||||
{ "CROMxx", "mpr21423.1", 0x4EE0060A, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21424.2", 0x25358FDF, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21425.3", 0xAD235849, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21426.4", 0xCE77E26E, 0x400000, 2, 0x0000000, 8, TRUE },
|
||||
|
||||
// Banked CROM3
|
||||
{ "CROMxx", "epr21438.21", 0x6815AF9E, 0x80000, 2, 0x1000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21427.22", 0x884566F6, 0x400000, 2, 0x1000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21431.23", 0x0EF8F7BB, 0x400000, 2, 0x1000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21428.24", 0x162D1E43, 0x400000, 2, 0x1000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21425.3", 0xAD235849, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21424.2", 0x25358FDF, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21423.1", 0x4EE0060A, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Video ROM
|
||||
{ "VROM", "mpr21407.26", 0x3FFB416C, 0x400000, 2, 0, 32, FALSE },
|
||||
|
@ -223,6 +233,13 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr21421.40", 0x71E4E9FC, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr21422.41", 0xFECA77A5, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr21438.21", 0x6815AF9E, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr21427.22", 0x884566F6, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr21428.24", 0x162D1E43, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr21431.23", 0x0EF8F7BB, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "Samples","mpr21432.25", 0x59C0F6DF, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
},
|
||||
|
@ -239,36 +256,32 @@ const struct GameInfo Model3GameList[] =
|
|||
0x2000000, // 32 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_JOYSTICK1,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
{ "CROM", "epr-20643.17", 0xDAF02716, 0x80000, 2, 0x0600006, 8, TRUE },
|
||||
{ "CROM", "epr-20644.18", 0xC28DB2B6, 0x80000, 2, 0x0600004, 8, TRUE },
|
||||
{ "CROM", "epr-20645.19", 0x8EEFA2B0, 0x80000, 2, 0x0600002, 8, TRUE },
|
||||
{ "CROM", "epr-20646.20", 0xD740AE06, 0x80000, 2, 0x0600000, 8, TRUE },
|
||||
{ "CROM", "epr-20645.19", 0x8EEFA2B0, 0x80000, 2, 0x0600002, 8, TRUE },
|
||||
{ "CROM", "epr-20644.18", 0xC28DB2B6, 0x80000, 2, 0x0600004, 8, TRUE },
|
||||
{ "CROM", "epr-20643.17", 0xDAF02716, 0x80000, 2, 0x0600006, 8, TRUE },
|
||||
|
||||
// Banked CROM0
|
||||
{ "CROMxx", "mpr-20256.1", 0x115302AC, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20257.2", 0x025BC06D, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20258.3", 0x7B78B071, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20259.4", 0x40052562, 0x400000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20258.3", 0x7B78B071, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20257.2", 0x025BC06D, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20256.1", 0x115302AC, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM1
|
||||
{ "CROMxx", "mpr-20260.5", 0xC56B4C10, 0x400000, 2, 0x1000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20261.6", 0xB1E9D44A, 0x400000, 2, 0x1000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20262.7", 0x52B0674D, 0x400000, 2, 0x1000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20263.8", 0x1CF4CBA9, 0x400000, 2, 0x1000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20262.7", 0x52B0674D, 0x400000, 2, 0x1000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20261.6", 0xB1E9D44A, 0x400000, 2, 0x1000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20260.5", 0xC56B4C10, 0x400000, 2, 0x1000006, 8, TRUE },
|
||||
|
||||
// Banked CROM2
|
||||
{ "CROMxx", "mpr-20264.9", 0x8D995196, 0x400000, 2, 0x2000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20265.10", 0x28F76E3E, 0x400000, 2, 0x2000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20266.11", 0xABD2DB85, 0x400000, 2, 0x2000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20267.12", 0x48989191, 0x400000, 2, 0x2000000, 8, TRUE },
|
||||
|
||||
// Banked CROM3
|
||||
{ "CROMxx", "epr-20313.21", 0x863A7857, 0x80000, 2, 0x3000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20268.22", 0x3631E93E, 0x400000, 2, 0x3000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20269.24", 0x105A3181, 0x400000, 2, 0x3000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20266.11", 0xABD2DB85, 0x400000, 2, 0x2000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20265.10", 0x28F76E3E, 0x400000, 2, 0x2000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20264.9", 0x8D995196, 0x400000, 2, 0x2000006, 8, TRUE },
|
||||
|
||||
// Video ROM
|
||||
{ "VROM", "mpr-20270.26", 0xDF68A7A7, 0x200000, 2, 0, 32, FALSE },
|
||||
|
@ -288,6 +301,11 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr-20284.40", 0x5C7F3A6F, 0x200000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr-20285.41", 0x4AADC573, 0x200000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr-20313.21", 0x863A7857, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr-20268.22", 0x3631E93E, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-20269.24", 0x105A3181, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
},
|
||||
|
@ -304,31 +322,26 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
{ "CROM", "epr-21062a.17", 0x64B55254, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROM", "epr-21063a.18", 0x6AB7EB32, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr-21064a.19", 0x2A01F9AD, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr-21065a.20", 0x3223DB1A, 0x200000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROM", "epr-21064a.19", 0x2A01F9AD, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr-21063a.18", 0x6AB7EB32, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr-21062a.17", 0x64B55254, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM0
|
||||
{ "CROMxx", "mpr-21023.1", 0x932A3724, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21024.2", 0xEDE859B0, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21025.3", 0x6591C66E, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21026.4", 0xF4937E3F, 0x400000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21025.3", 0x6591C66E, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21024.2", 0xEDE859B0, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21023.1", 0x932A3724, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM1
|
||||
{ "CROMxx", "mpr-21027.5", 0x74E1496A, 0x400000, 2, 0x1000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21028.6", 0xDB11F50A, 0x400000, 2, 0x1000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21029.7", 0x89867D8A, 0x400000, 2, 0x1000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21030.8", 0xF8E51BEC, 0x400000, 2, 0x1000000, 8, TRUE },
|
||||
|
||||
// Banked CROM3
|
||||
{ "CROMxx", "epr-21066.21", 0xF7ED2582, 0x80000, 2, 0x2000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21031.22", 0x32F6B23A, 0x400000, 2, 0x2000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21032.23", 0x3D3FF407, 0x400000, 2, 0x2000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21033.24", 0x253D3C70, 0x400000, 2, 0x2000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21029.7", 0x89867D8A, 0x400000, 2, 0x1000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21028.6", 0xDB11F50A, 0x400000, 2, 0x1000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-21027.5", 0x74E1496A, 0x400000, 2, 0x1000006, 8, TRUE },
|
||||
|
||||
// Video ROM
|
||||
{ "VROM", "mpr-21034.26", 0xACBA5CA6, 0x400000, 2, 0, 32, FALSE },
|
||||
|
@ -348,6 +361,12 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr-21048.40", 0x96849974, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr-21049.41", 0x91E8161A, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr-21066.21", 0xF7ED2582, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr-21031.22", 0x32F6B23A, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-21033.24", 0x253D3C70, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr-21032.23", 0x3D3FF407, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
},
|
||||
|
@ -364,6 +383,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x2000000, // 32 MB of VROM (will need to be mirrored)
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_JOYSTICK1|GAME_INPUT_JOYSTICK2|GAME_INPUT_FIGHTING,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -435,6 +455,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x2000000, // 32 MB of VROM (will need to be mirrored)
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE|GAME_INPUT_VR|GAME_INPUT_SHIFT4, // for now, Shift Up/Down mapped to Shift 3/4
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -500,6 +521,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x2000000, // 32 MB of VROM (will need to be mirrored)
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE|GAME_INPUT_VR|GAME_INPUT_SHIFT4,
|
||||
1, // DSB1 MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM (mirroring behavior here is special and handled manually by CModel3)
|
||||
|
@ -548,6 +570,11 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "SndProg","epr-19692.21", 0xA94F5521, 0x80000, 2, 0, 2, TRUE },
|
||||
{ "Samples","mpr-19670.22", 0xBD31CC06, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-19671.24", 0x8E8526AB, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "DSBProg","epr-19612.2", 0x13978FD4, 0x20000, 2, 0, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-19603.57", 0xB1B1765F, 0x200000, 2, 0x000000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-19604.58", 0x6AC85B49, 0x200000, 2, 0x200000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-19605.59", 0xBEC891EB, 0x200000, 2, 0x400000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-19606.60", 0xADAD46B2, 0x200000, 2, 0x600000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
|
@ -565,6 +592,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x2000000, // 32 MB of VROM (will need to be mirrored)
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE|GAME_INPUT_VR|GAME_INPUT_SHIFT4,
|
||||
1, // DSB1 MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM (mirroring behavior here is special and handled manually by CModel3)
|
||||
|
@ -619,6 +647,11 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "SndProg","epr-20096a.21",0x0FEF288B, 0x80000, 2, 0, 2, TRUE },
|
||||
{ "Samples","mpr-19670.22", 0xBD31CC06, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-20101.24", 0x66D1E31F, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "DSBProg","epr-19612.2", 0x13978FD4, 0x20000, 2, 0, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-19603.57", 0xB1B1765F, 0x200000, 2, 0x000000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-19604.58", 0x6AC85B49, 0x200000, 2, 0x200000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-19605.59", 0xBEC891EB, 0x200000, 2, 0x400000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-19606.60", 0xADAD46B2, 0x200000, 2, 0x600000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
|
@ -636,6 +669,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x2000000, // 32 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_GUN1|GAME_INPUT_GUN2,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -707,6 +741,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_TWIN_JOYSTICKS,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -757,6 +792,13 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr-20681.40", 0xD517873B, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr-20682.41", 0x5B43250C, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr-20687.21", 0xFA084DE5, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr-20663.22", 0x977EB6A4, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-20665.24", 0x0EFC0CA8, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr-20664.23", 0x89220782, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "Samples","mpr-20666.25", 0x3ECB2606, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
},
|
||||
|
@ -773,6 +815,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x2000000, // 32 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_JOYSTICK1|GAME_INPUT_JOYSTICK2|GAME_INPUT_SOCCER,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -824,7 +867,7 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr-19802.41", 0xF2C3A7B7, 0x200000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr-20921.21", 0x30F032A7, 0x80000, 2, 0, 2, TRUE },
|
||||
{ "SndProg","epr-20921.21", 0x30F032A7, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr-20903.22", 0xE343E131, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-20904.24", 0x21A91B84, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
|
||||
|
@ -844,6 +887,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE|GAME_INPUT_RALLY|GAME_INPUT_SHIFT4,
|
||||
2, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -892,6 +936,11 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "SndProg","epr-20636.21", 0x7139EBF8, 0x80000, 2, 0, 2, TRUE },
|
||||
{ "Samples","mpr-20614.22", 0xA3930E4A, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-20615.24", 0x62E8A94A, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "DSBProg","epr-20641.2", 0xC9B82035, 0x20000, 2, 0, 2, TRUE },
|
||||
{ "DSBMPEG","mpr-20637.57", 0xD66E8A02, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-20638.58", 0xD1513382, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-20639.59", 0xF6603B7B, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-20640.60", 0x9EEA07B7, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
|
@ -909,6 +958,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x1000000, // 16 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE|GAME_INPUT_VR|GAME_INPUT_SHIFT4,
|
||||
2, // DSB2 MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -965,6 +1015,12 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "Samples","mpr-20868.24", 0xFA0C7EC0, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr-20867.23", 0xA579C884, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "Samples","mpr-20869.25", 0x1F338832, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
{ "DSBProg","epr-20886.ic2", 0x65B05F98, 0x20000, 2, 0, 2, TRUE },
|
||||
{ "DSBMPEG","mpr-20887.ic18", 0xA0757684, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-20888.ic20", 0xB495FE65, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-20889.ic22", 0x18EEC79E, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-20890.ic24", 0xAAC96FA2, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
|
@ -982,6 +1038,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x1000000, // 16 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE|GAME_INPUT_VR|GAME_INPUT_SHIFT4,
|
||||
2, // DSB2 MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -1038,6 +1095,11 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "Samples","mpr-21287.24", 0x06B66F17, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr-21286.23", 0x749DFEF0, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "Samples","mpr-21288.25", 0x14BEE38E, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
{ "DSBProg","epr-20886.ic2", 0x65B05F98, 0x20000, 2, 0, 2, TRUE },
|
||||
{ "DSBMPEG","mpr-20887.ic18", 0xA0757684, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-20888.ic20", 0xB495FE65, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-20889.ic22", 0x18EEC79E, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "DSBMPEG","mpr-20890.ic24", 0xAAC96FA2, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
|
@ -1055,6 +1117,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_JOYSTICK1|GAME_INPUT_JOYSTICK2|GAME_INPUT_FIGHTING,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -1105,6 +1168,13 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr-20594.40", 0x35578240, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr-20595.41", 0x1D4A2CAD, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr-20600a.21",0xF0E7DB7E, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr-20576", 0x1EEB540B, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-20578", 0xD222F2D4, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr-20577", 0x3B236187, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "Samples","mpr-20579", 0x08788436, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
},
|
||||
|
@ -1121,31 +1191,32 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
{ "CROM", "epr-20393a.17", 0xB5646556, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROM", "epr-20394a.18", 0xCE29E2B6, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr-20395a.19", 0x761F4976, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr-20396a.20", 0x16B0106B, 0x200000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROM", "epr-20395a.19", 0x761F4976, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr-20394a.18", 0xCE29E2B6, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr-20393a.17", 0xB5646556, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM0
|
||||
{ "CROMxx", "mpr-20361.1", 0xDDB66C2F, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20362.2", 0xF7E60DFD, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20363.3", 0x3E3CC6FF, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20364.4", 0xA2A68EF2, 0x400000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20363.3", 0x3E3CC6FF, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20362.2", 0xF7E60DFD, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20361.1", 0xDDB66C2F, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM1
|
||||
{ "CROMxx", "mpr-20365.5", 0x7DD50361, 0x400000, 2, 0x1000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20366.6", 0x45E3850E, 0x400000, 2, 0x1000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20367.7", 0x6C3F9748, 0x400000, 2, 0x1000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20368.8", 0x100C9846, 0x400000, 2, 0x1000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20367.7", 0x6C3F9748, 0x400000, 2, 0x1000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20366.6", 0x45E3850E, 0x400000, 2, 0x1000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr-20365.5", 0x7DD50361, 0x400000, 2, 0x1000006, 8, TRUE },
|
||||
|
||||
// Banked CROM3
|
||||
{ "CROMxx", "epr-20409.13", 0x58CAAA75, 0x200000, 2, 0x3800006, 8, TRUE },
|
||||
{ "CROMxx", "epr-20410.14", 0x98B126F2, 0x200000, 2, 0x3800004, 8, TRUE },
|
||||
{ "CROMxx", "epr-20411.15", 0x848DAAF7, 0x200000, 2, 0x3800002, 8, TRUE },
|
||||
{ "CROMxx", "epr-20412.16", 0x0D51BB34, 0x200000, 2, 0x3800000, 8, TRUE },
|
||||
{ "CROMxx", "epr-20411.15", 0x848DAAF7, 0x200000, 2, 0x3800002, 8, TRUE },
|
||||
{ "CROMxx", "epr-20410.14", 0x98B126F2, 0x200000, 2, 0x3800004, 8, TRUE },
|
||||
{ "CROMxx", "epr-20409.13", 0x58CAAA75, 0x200000, 2, 0x3800006, 8, TRUE },
|
||||
|
||||
// Video ROM
|
||||
{ "VROM", "mpr-20377.26", 0x4D2887E5, 0x400000, 2, 0, 32, FALSE },
|
||||
|
@ -1165,6 +1236,13 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr-20391.40", 0x5DC452DC, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr-20392.41", 0x892208CB, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr-20397.21", 0x5B20B54A, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr-20373.22", 0xC684E8A3, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-20375.24", 0x906ACE86, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr-20374.23", 0xFCF6EA21, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "Samples","mpr-20376.25", 0xDEEED366, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
},
|
||||
|
@ -1181,19 +1259,20 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_ANALOG_JOYSTICK,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
{ "CROM", "epr21486.20", 0x940637C2, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROM", "epr21485.19", 0x58102168, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr21484.18", 0xF68F7703, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr21483.17", 0x64DE433F, 0x200000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROM", "epr21484.18", 0xF68F7703, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr21485.19", 0x58102168, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr21486.20", 0x940637C2, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM0
|
||||
{ "CROMxx", "mpr21454.4", 0x42BDC56C, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21453.3", 0x01AC050C, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21452.2", 0x082D98AB, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21451.1", 0x97FF94A7, 0x400000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21452.2", 0x082D98AB, 0x400000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21453.3", 0x01AC050C, 0x400000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21454.4", 0x42BDC56C, 0x400000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM1
|
||||
{ "CROMxx", "mpr21458.8", 0xB748F5A1, 0x400000, 2, 0x1000000, 8, TRUE },
|
||||
|
@ -1225,6 +1304,13 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr21481.40", 0x6CE566AC, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr21482.41", 0xE995F554, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr21487.21", 0xC2942448, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr21463.22", 0x0E6d6C0E, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr21465.24", 0x1A62D925, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr21464.23", 0x8230C1DE, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "Samples","mpr21466.25", 0xCA20359E, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
},
|
||||
|
@ -1241,51 +1327,60 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM (will need to be mirrored)
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_ANALOG_JOYSTICK,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
{ "CROM", "epr21117.20", 0x3adfcb9d, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
{ "CROM", "epr21116.19", 0x0bb9c107, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr21115.18", 0x69e31e85, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr21114.17", 0x58d985f1, 0x200000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROM", "epr21114.17", 0x58D985f1, 0x200000, 2, 0x0000000, 8, TRUE },
|
||||
{ "CROM", "epr21115.18", 0x69E31E85, 0x200000, 2, 0x0000002, 8, TRUE },
|
||||
{ "CROM", "epr21116.19", 0x0BB9C107, 0x200000, 2, 0x0000004, 8, TRUE },
|
||||
{ "CROM", "epr21117.20", 0x3ADFCB9D, 0x200000, 2, 0x0000006, 8, TRUE },
|
||||
|
||||
// Banked CROM1
|
||||
{ "CROMxx", "mpr21085.8", 0x5056ad33, 0x800000, 2, 0x2000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21084.7", 0xfdec6a23, 0x800000, 2, 0x2000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21083.6", 0xc1c6b554, 0x800000, 2, 0x2000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21082.5", 0x2b7224d3, 0x800000, 2, 0x2000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21082.5", 0x2B7224D3, 0x800000, 2, 0x2000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21083.6", 0xC1C6B554, 0x800000, 2, 0x2000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21084.7", 0xFDEC6A23, 0x800000, 2, 0x2000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21085.8", 0x5056AD33, 0x800000, 2, 0x2000006, 8, TRUE },
|
||||
|
||||
// Banked CROM2
|
||||
{ "CROMxx", "mpr21089.12", 0x2e8f88bd, 0x800000, 2, 0x4000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21088.11", 0x7ed71c8c, 0x800000, 2, 0x4000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21087.10", 0xcff28641, 0x800000, 2, 0x4000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21086.9", 0x3f12e1d0, 0x800000, 2, 0x4000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21089.12", 0x2E8F88BD, 0x800000, 2, 0x4000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21088.11", 0x7ED71C8C, 0x800000, 2, 0x4000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21087.10", 0xCFF28641, 0x800000, 2, 0x4000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21086.9", 0x3F12E1D0, 0x800000, 2, 0x4000006, 8, TRUE },
|
||||
|
||||
// Banked CROM3
|
||||
{ "CROMxx", "mpr21093.16", 0xbdfbf357, 0x800000, 2, 0x6000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21092.15", 0x5b1ced40, 0x800000, 2, 0x6000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21093.16", 0xBDFBF357, 0x800000, 2, 0x6000000, 8, TRUE },
|
||||
{ "CROMxx", "mpr21092.15", 0x5B1CED40, 0x800000, 2, 0x6000002, 8, TRUE },
|
||||
{ "CROMxx", "mpr21091.14", 0x10671951, 0x800000, 2, 0x6000004, 8, TRUE },
|
||||
{ "CROMxx", "mpr21090.13", 0x749d7979, 0x800000, 2, 0x6000006, 8, TRUE },
|
||||
{ "CROMxx", "mpr21090.13", 0x749D7979, 0x800000, 2, 0x6000006, 8, TRUE },
|
||||
|
||||
// Video ROM
|
||||
{ "VROM", "mpr21098.26", 0x91e71855, 0x400000, 2, 0, 32, FALSE },
|
||||
{ "VROM", "mpr21099.27", 0x308a2768, 0x400000, 2, 2, 32, FALSE },
|
||||
{ "VROM", "mpr21100.28", 0x5149b286, 0x400000, 2, 4, 32, FALSE },
|
||||
{ "VROM", "mpr21101.29", 0xe9ed4250, 0x400000, 2, 6, 32, FALSE },
|
||||
{ "VROM", "mpr21102.30", 0x06c6d4fc, 0x400000, 2, 8, 32, FALSE },
|
||||
{ "VROM", "mpr21103.31", 0x17c4b27a, 0x400000, 2, 10, 32, FALSE },
|
||||
{ "VROM", "mpr21104.32", 0xf6f80ffb, 0x400000, 2, 12, 32, FALSE },
|
||||
{ "VROM", "mpr21105.33", 0x99bdb52b, 0x400000, 2, 14, 32, FALSE },
|
||||
{ "VROM", "mpr21106.34", 0xad2b7981, 0x400000, 2, 16, 32, FALSE },
|
||||
{ "VROM", "mpr21107.35", 0xe108ff62, 0x400000, 2, 18, 32, FALSE },
|
||||
{ "VROM", "mpr21108.36", 0xcddc7a6e, 0x400000, 2, 20, 32, FALSE },
|
||||
{ "VROM", "mpr21109.37", 0x92d6141d, 0x400000, 2, 22, 32, FALSE },
|
||||
{ "VROM", "mpr21110.38", 0x4d6e3148, 0x400000, 2, 24, 32, FALSE },
|
||||
{ "VROM", "mpr21111.39", 0x0a046d7a, 0x400000, 2, 26, 32, FALSE },
|
||||
{ "VROM", "mpr21112.40", 0x9afd9feb, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr21113.41", 0x864bf325, 0x400000, 2, 30, 32, FALSE },
|
||||
{ "VROM", "mpr21098.26", 0x91E71855, 0x400000, 2, 0, 32, FALSE },
|
||||
{ "VROM", "mpr21099.27", 0x308A2768, 0x400000, 2, 2, 32, FALSE },
|
||||
{ "VROM", "mpr21100.28", 0x5149B286, 0x400000, 2, 4, 32, FALSE },
|
||||
{ "VROM", "mpr21101.29", 0xE9ED4250, 0x400000, 2, 6, 32, FALSE },
|
||||
{ "VROM", "mpr21102.30", 0x06C6D4FC, 0x400000, 2, 8, 32, FALSE },
|
||||
{ "VROM", "mpr21103.31", 0x17C4B27A, 0x400000, 2, 10, 32, FALSE },
|
||||
{ "VROM", "mpr21104.32", 0xF6F80FFB, 0x400000, 2, 12, 32, FALSE },
|
||||
{ "VROM", "mpr21105.33", 0x99BDB52B, 0x400000, 2, 14, 32, FALSE },
|
||||
{ "VROM", "mpr21106.34", 0xAD2B7981, 0x400000, 2, 16, 32, FALSE },
|
||||
{ "VROM", "mpr21107.35", 0xE108FF62, 0x400000, 2, 18, 32, FALSE },
|
||||
{ "VROM", "mpr21108.36", 0xCDDC7A6E, 0x400000, 2, 20, 32, FALSE },
|
||||
{ "VROM", "mpr21109.37", 0x92D6141D, 0x400000, 2, 22, 32, FALSE },
|
||||
{ "VROM", "mpr21110.38", 0x4D6E3148, 0x400000, 2, 24, 32, FALSE },
|
||||
{ "VROM", "mpr21111.39", 0x0A046D7A, 0x400000, 2, 26, 32, FALSE },
|
||||
{ "VROM", "mpr21112.40", 0x9AFD9FEB, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr21113.41", 0x864BF325, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr21118.21", 0x598C00F0, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr21094.22", 0xC262B80A, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr21096.24", 0x0A0021A0, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr21095.23", 0x16D27A0A, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "Samples","mpr21097.25", 0x0D8033FC, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1301,6 +1396,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_ANALOG_JOYSTICK,
|
||||
2, // DSB2 MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -1346,9 +1442,14 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr-21374.41", 0xAE6C4D28, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr-21383.21", 0x544d1e28, 0x80000, 2, 0, 2, TRUE },
|
||||
{ "Samples","mpr-21355.22", 0xc1b2d326, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-21357.24", 0x02703fab, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "SndProg","epr-21383.21", 0x544D1E28, 0x80000, 2, 0, 2, TRUE },
|
||||
{ "Samples","mpr-21355.22", 0xC1B2D326, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr-21357.24", 0x02703FAB, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "DSBProg","ep21384.2", 0x12FA4780, 0x20000, 2, 0, 2, TRUE },
|
||||
{ "DSBMPEG","mp21375.18", 0x735157a9, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "DSBMPEG","mp21376.20", 0xE635F81E, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "DSBMPEG","mp21377.22", 0x720621F8, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "DSBMPEG","mp21378.24", 0x1FCF715E, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
|
@ -1366,6 +1467,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0x4000000, // 64 MB of VROM
|
||||
0x800000, // 8 MB of sample ROMs
|
||||
GAME_INPUT_COMMON|GAME_INPUT_VEHICLE,
|
||||
0, // no MPEG board
|
||||
|
||||
{
|
||||
// Fixed CROM
|
||||
|
@ -1410,6 +1512,13 @@ const struct GameInfo Model3GameList[] =
|
|||
{ "VROM", "mpr22868.40", 0x2DB40CF8, 0x400000, 2, 28, 32, FALSE },
|
||||
{ "VROM", "mpr22869.41", 0xC6D62634, 0x400000, 2, 30, 32, FALSE },
|
||||
|
||||
// Sound ROMs
|
||||
{ "SndProg","epr22886.21", 0x374EC1C6, 0x80000, 2, 0x000000, 2, TRUE },
|
||||
{ "Samples","mpr22887.22", 0x7D04A867, 0x400000, 2, 0x000000, 2, FALSE },
|
||||
{ "Samples","mpr22889.24", 0x4F9BA45D, 0x400000, 2, 0x400000, 2, FALSE },
|
||||
{ "Samples","mpr22888.23", 0x018FCF22, 0x400000, 2, 0x800000, 2, FALSE },
|
||||
{ "Samples","mpr22890.25", 0xB638BD7C, 0x400000, 2, 0xC00000, 2, FALSE },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0, 0, 0, FALSE }
|
||||
}
|
||||
},
|
||||
|
@ -1427,6 +1536,7 @@ const struct GameInfo Model3GameList[] =
|
|||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
||||
{
|
||||
{ NULL, NULL, 0, 0, 0, 0, FALSE },
|
||||
|
|
|
@ -74,9 +74,10 @@ struct GameInfo
|
|||
unsigned vromSize; // size of video ROMs (32 or 64 MB; if 32 MB, will have to be mirrored)
|
||||
unsigned sampleSize; // size of sample ROMS (8 or 16 MB; if 8 MB, will have to be mirrored)
|
||||
unsigned inputFlags; // game input types
|
||||
int mpegBoard; // MPEG music board type: 0 = none, 1 = DSB1 (Z80), 2 = DSB2 (68K).
|
||||
|
||||
// ROM files
|
||||
struct ROMInfo ROM[42];
|
||||
struct ROMInfo ROM[48];
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011 Bart Trzynadlowski
|
||||
**
|
||||
** 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/>.
|
||||
**/
|
||||
|
||||
/*
|
||||
* Render.h
|
||||
*
|
||||
* Header file defining the CRender class: container for both the 2D and 3D
|
||||
* renderers.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_RENDER_H
|
||||
#define INCLUDED_RENDER_H
|
||||
|
||||
/*
|
||||
* CRender:
|
||||
*
|
||||
* Tile generator graphics engine. This must be constructed and initialized
|
||||
* before being attached to any objects that want to make use of it. Apart from
|
||||
* the constructor, all members assume that a global GL device
|
||||
* context is available and that GL functions may be called.
|
||||
*/
|
||||
class CRender2D
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* BeginFrame(layerFormats):
|
||||
*
|
||||
* Prepare to render a new frame. Must be called once per frame prior to
|
||||
* drawing anything.
|
||||
*
|
||||
* Parameters:
|
||||
* layerFormats A bit field indicating how to interpret each of the
|
||||
* four layers: 0=8-bit pixels, 1=4-bit pixels. Bits
|
||||
* 3-0 correspond to layers 3-0.
|
||||
*/
|
||||
void BeginFrame(unsigned layerFormats);
|
||||
|
||||
/*
|
||||
* EndFrame(void):
|
||||
*
|
||||
* Signals the end of rendering for this frame. Must be called last during
|
||||
* the frame.
|
||||
*/
|
||||
void EndFrame(void);
|
||||
|
||||
/*
|
||||
* WriteVRAM(addr, data):
|
||||
*
|
||||
* Indicates what will be written next to the tile generator's RAM. The
|
||||
* VRAM address must not have yet been updated, to allow the renderer to
|
||||
* check for changes. Data is accepted in the same form as the tile
|
||||
* generator: the MSB is what was written to addr+3. This function is
|
||||
* intended to facilitate on-the-fly decoding of tiles and palette data.
|
||||
*
|
||||
* Parameters:
|
||||
* addr Address in tile generator RAM. Caller must ensure it is
|
||||
* clamped to the range 0x000000 to 0x11FFFF because this
|
||||
* function does not.
|
||||
* data The data to write.
|
||||
*/
|
||||
void WriteVRAM(unsigned addr, UINT32 data);
|
||||
|
||||
/*
|
||||
* AttachRegisters(regPtr):
|
||||
*
|
||||
* Attaches tile generator registers. This must be done prior to any
|
||||
* rendering otherwise the program may crash with an access violation.
|
||||
*
|
||||
* Parameters:
|
||||
* regPtr Pointer to the base of the tile generator registers.
|
||||
* There are assumed to be 64 in all.
|
||||
*/
|
||||
void AttachRegisters(const UINT32 *regPtr);
|
||||
|
||||
/*
|
||||
* AttachVRAM(vramPtr):
|
||||
*
|
||||
* Attaches tile generator RAM. This must be done prior to any rendering
|
||||
* otherwise the program may crash with an access violation.
|
||||
*
|
||||
* Parameters:
|
||||
* vramPtr Pointer to the base of the tile generator RAM (0x120000
|
||||
* bytes). VRAM is assumed to be in little endian format.
|
||||
*/
|
||||
void AttachVRAM(const UINT8 *vramPtr);
|
||||
|
||||
/*
|
||||
* Init(xOffset, yOffset, xRes, yRes):
|
||||
*
|
||||
* One-time initialization of the context. Must be called before any other
|
||||
* members (meaning it should be called even before being attached to any
|
||||
* other objects that want to use it).
|
||||
*
|
||||
* Parameters:
|
||||
* xOffset X offset within OpenGL display surface in pixels.
|
||||
* yOffset Y offset.
|
||||
* xRes Horizontal resolution of display surface in pixels.
|
||||
* yRes Vertical resolution.
|
||||
*
|
||||
* Returns:
|
||||
* OKAY is successful, otherwise FAILED if a non-recoverable error
|
||||
* occurred. Prints own error messages.
|
||||
*/
|
||||
BOOL Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes);
|
||||
|
||||
/*
|
||||
* CRender2D(void):
|
||||
* ~CRender2D(void):
|
||||
*
|
||||
* Constructor and destructor.
|
||||
*/
|
||||
CRender2D(void);
|
||||
~CRender2D(void);
|
||||
|
||||
private:
|
||||
// Private member functions
|
||||
void DrawTile4Bit(unsigned tile, UINT32 *buf, unsigned pitch);
|
||||
void DrawTile8Bit(unsigned tile, UINT32 *buf, unsigned pitch);
|
||||
void DrawRect(int layerNum, UINT32 *layerSurf, const UINT32 *nameTable, unsigned x, unsigned y, unsigned w, unsigned h);
|
||||
void UpdateLayer(int layerNum);
|
||||
void DisplayLayer(int layerNum, GLfloat z, GLfloat scroll);
|
||||
void Setup2D(void);
|
||||
|
||||
// Data received from tile generator device object
|
||||
const UINT32 *vram;
|
||||
const UINT32 *regs;
|
||||
|
||||
// OpenGL data
|
||||
GLuint texID[4]; // IDs for the 4 layer textures
|
||||
unsigned xPixels, yPixels; // display surface resolution
|
||||
unsigned xOffs, yOffs; // offset
|
||||
|
||||
// Shader programs and input data locations
|
||||
GLuint shaderProgram; // shader program object
|
||||
GLuint vertexShader; // vertex shader handle
|
||||
GLuint fragmentShader; // fragment shader
|
||||
GLuint textureMapLoc; // location of "textureMap" uniform
|
||||
GLuint bottomLayerLoc; // uniform
|
||||
|
||||
|
||||
// Dirty rectangles (non-zero indicates region is dirty)
|
||||
UINT8 dirty[4][64/DIRTY_RECT_HEIGHT][64/DIRTY_RECT_WIDTH];
|
||||
BOOL allDirty; // global dirty flag (forces everything to be updated)
|
||||
|
||||
// Buffers
|
||||
UINT8 *memoryPool; // all memory is allocated here
|
||||
UINT32 *surf; // 4 512x512x32bpp pixel surfaces
|
||||
UINT32 *pal; // 0x20000 byte (32K colors) palette
|
||||
};
|
||||
|
||||
|
||||
#endif // INCLUDED_RENDER2D_H
|
877
Src/Model3/DSB.cpp
Normal file
877
Src/Model3/DSB.cpp
Normal file
|
@ -0,0 +1,877 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011 Bart Trzynadlowski
|
||||
**
|
||||
** 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/>.
|
||||
**/
|
||||
|
||||
/*
|
||||
* DSB.cpp
|
||||
*
|
||||
* Sega Digital Sound Board (MPEG audio). Implementation of the CDSB1 and CDSB2
|
||||
* classes. Based on code donated by R. Belmont. Many Bothans died to bring us
|
||||
* this emulation.
|
||||
*
|
||||
* TODO List
|
||||
* ---------
|
||||
* - Music looping on DSB2 does not work in Daytona 2 (will play next track).
|
||||
* - Check actual MPEG sample rate. So far, all games seem to use 32 KHz, which
|
||||
* may be a hardware requirement, but if other sampling rates are allowable,
|
||||
* the code here will fail (it is hard coded for 32 KHz).
|
||||
* - Should we do some bounds checking on the MPEG start/end points?
|
||||
*/
|
||||
|
||||
#include "Supermodel.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Resampler
|
||||
|
||||
MPEG Layer 2 audio can be 32, 44.1, or 48 KHz. Here, an up-sampling algorithm
|
||||
is provided, which should work for any frequency less than 44.1 KHz and an
|
||||
output frequency of 44.1 KHz. Down-sampling is not yet implemented, but would
|
||||
work in a similar fashion. The chief difference is that the input index would
|
||||
sometimes advance by more than one for a single output sample and the
|
||||
fractions, nFrac and pFrac, would sometimes exceed 1.0.
|
||||
|
||||
Up-Sampling Description
|
||||
-----------------------
|
||||
|
||||
Linear interpolation is used to up-sample. Not as accurate as the Shannon
|
||||
reconstruction equation but it seems to work quite well.
|
||||
|
||||
1. Linear Interpolation
|
||||
|
||||
Input samples for a given frame (here, this means 1/60Hz, not to be confused
|
||||
with an MPEG frame, which is shorter) are numbered 0 ... L-1 (L samples in
|
||||
total). Output samples are 0 ... M-1.
|
||||
|
||||
For two adjacent input samples at times p ("previous") and n ("next"), in[p]
|
||||
and in[n], and output out[t] at time t, linear interpolation yields:
|
||||
|
||||
out[t] = (n-t)/(n-p) * in[p] + (t-p)/(n-p) * in[n]
|
||||
|
||||
Note that (n-p) = 1/fin (fin being the input sampling frequency).
|
||||
|
||||
Let pFrac = (n-t)/(n-p) and nFrac = (t-p)/(n-p). As t moves from p to n, pFrac
|
||||
moves from 1 to 0 and nFrac from 0 to 1, as we expect.
|
||||
|
||||
If we proceed one output sample at a time, we must add the time difference
|
||||
between output samples, 1/fout, to t. Call this delta_t. If we divide delta_t
|
||||
by (n-p), we can add it directly to nFrac and subtract from pFrac. Therefore:
|
||||
|
||||
delta = (1/fout)/(n-p) = fin/fout
|
||||
|
||||
What happens when nFrac exceeds 1.0 or pFrac goes below 0.0? That can't
|
||||
be allowed to happen -- it means that we've actually moved along the line into
|
||||
the region between the next set of samples. We use pFrac < 0 as the condition
|
||||
to update the input samples.
|
||||
|
||||
It so happens that when fin < fout, pFrac and nFrac will never exceed 1.0. So
|
||||
there is no need to check or mask the fixed point values when using them to
|
||||
interpolate samples.
|
||||
|
||||
2. Input Buffer Overflows
|
||||
|
||||
For some low sampling rates, particularly those that are a factor of 2 or 4
|
||||
smaller, it is possible that the very last sample or two needed from the input
|
||||
stream will be beyond the end. Fetching two extra samples (which can introduce
|
||||
an update lag of two samples -- imperceptible and inconsequential) fixes this,
|
||||
and so we do it.
|
||||
|
||||
3. Continuity Between Frames
|
||||
|
||||
The very last output sample will typically sit somewhere between two input
|
||||
samples. It is wrong to start the next frame by assuming everything is lined
|
||||
up again. The first sample of the next frame will often have to be interpol-
|
||||
ated with the last sample of the previous frame. To facilitate this, we check
|
||||
to see how many input samples remain unprocessed when up-sampling is finished,
|
||||
and then copy those to the beginning of the buffer. We then return the number
|
||||
of samples so that the buffer update function will know to skip them.
|
||||
|
||||
We also must maintain the state of pFrac and nFrac to resume interpolation
|
||||
correctly. Therefore, these variables are persistent.
|
||||
|
||||
4. Fixed Point Arithmetic
|
||||
|
||||
Fixed point arithmetic is used to track fractions. For such numbers, the low
|
||||
8 bits represent a fraction (0x100 would be 1.0, 0x080 would be 0.5, etc.)
|
||||
and the upper bits are the integral portion.
|
||||
******************************************************************************/
|
||||
|
||||
void CDSBResampler::Reset(void)
|
||||
{
|
||||
// Initial state of fractions (24.8 fixed point)
|
||||
nFrac = 0<<8; // fraction of next sample to use (0->1.0 as x moves p->n)
|
||||
pFrac = 1<<8; // previous sample (1.0->0 as x moves p->n)
|
||||
}
|
||||
|
||||
// Mixes 16-bit samples (sign extended in a and b)
|
||||
static inline INT16 MixAndClip(INT32 a, INT32 b)
|
||||
{
|
||||
a += b;
|
||||
if (a > 32767)
|
||||
a = 32767;
|
||||
else if (a < -32768)
|
||||
a = -32768;
|
||||
return (INT16) a;
|
||||
}
|
||||
|
||||
// Mixes audio and returns number of samples copied back to start of buffer (ie. offset at which new samples should be written)
|
||||
int CDSBResampler::UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *inR, int sizeOut, int sizeIn, int outRate, int inRate)
|
||||
{
|
||||
int delta = (inRate<<8)/outRate; // (1/fout)/(1/fin)=fin/fout, 24.8 fixed point
|
||||
int outIdx = 0;
|
||||
int inIdx = 0;
|
||||
INT16 leftSample, rightSample;
|
||||
|
||||
while (outIdx < sizeOut)
|
||||
{
|
||||
// nFrac, pFrac will never exceed 1.0 (0x100) (only true if delta does not exceed 1)
|
||||
leftSample = ((int)inL[inIdx]*pFrac+(int)inL[inIdx+1]*nFrac) >> 8; // left channel
|
||||
rightSample = ((int)inR[inIdx]*pFrac+(int)inR[inIdx+1]*nFrac) >> 8; // right channel
|
||||
|
||||
|
||||
outL[outIdx] = MixAndClip(outL[outIdx], leftSample);
|
||||
outR[outIdx] = MixAndClip(outR[outIdx], rightSample);
|
||||
outIdx++;
|
||||
|
||||
// Time step
|
||||
pFrac -= delta;
|
||||
nFrac += delta;
|
||||
|
||||
// Time to move to next samples?
|
||||
if (pFrac <= 0) // when pFrac becomes 0, advance samples, reset pFrac to 1
|
||||
{
|
||||
pFrac += (1<<8);
|
||||
nFrac -= (1<<8);
|
||||
inIdx++; // advance samples (for upsampling only; downsampling may advance by more than one -- add delta every loop iteration)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Copy remaining "active" input samples to start of buffer
|
||||
int i = 0;
|
||||
int j = inIdx;
|
||||
while (j < sizeIn)
|
||||
{
|
||||
inL[i] = inL[j];
|
||||
inR[i] = inR[j];
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
return i; // first free position in input buffer to copy next MPEG update to
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Digital Sound Board Type 1: Z80 CPU
|
||||
******************************************************************************/
|
||||
|
||||
UINT8 CDSB1::Read8(UINT32 addr)
|
||||
{
|
||||
// ROM: 0x0000-0x7FFF
|
||||
if (addr < 0x8000)
|
||||
return progROM[addr];
|
||||
|
||||
// RAM: 0x8000-0xFFFF
|
||||
return ram[addr&0x7FFF];
|
||||
}
|
||||
|
||||
void CDSB1::Write8(UINT32 addr, UINT8 data)
|
||||
{
|
||||
if (addr >= 0x8000)
|
||||
ram[addr&0x7FFF] = data;
|
||||
}
|
||||
|
||||
void CDSB1::IOWrite8(UINT32 addr, UINT8 data)
|
||||
{
|
||||
switch ((addr&0xFF))
|
||||
{
|
||||
case 0xE0: // MPEG trigger
|
||||
mpegState = data;
|
||||
|
||||
if (data == 0) // stop
|
||||
{
|
||||
MPEG_StopPlaying();
|
||||
return;
|
||||
}
|
||||
|
||||
if (data == 1) // play without loop
|
||||
{
|
||||
MPEG_SetLoop(NULL, 0);
|
||||
//printf("====> Playing %06X\n", mpegStart);
|
||||
MPEG_PlayMemory((const char *) &mpegROM[mpegStart], mpegEnd-mpegStart);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data == 2) // play with loop
|
||||
{
|
||||
//printf("====> Playing %06X\n", mpegStart);
|
||||
MPEG_PlayMemory((const char *) &mpegROM[mpegStart], mpegEnd-mpegStart);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE2: // MPEG start, high byte
|
||||
startLatch &= 0x00FFFF;
|
||||
startLatch |= ((UINT32)data) << 16;
|
||||
break;
|
||||
|
||||
case 0xE3: // MPEG start, middle byte
|
||||
startLatch &= 0xFF00FF;
|
||||
startLatch |= ((UINT32)data) << 8;
|
||||
break;
|
||||
|
||||
case 0xE4: // MPEG start, low byte
|
||||
startLatch &= 0xFFFF00;
|
||||
startLatch |= data;
|
||||
|
||||
if (mpegState == 0)
|
||||
{
|
||||
mpegStart = startLatch;
|
||||
//printf("mpegStart = %08X\n", mpegStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
loopStart = startLatch;
|
||||
//printf("loopStart = %08X\n", loopStart);
|
||||
// SWA: if loop end is zero, it means "keep previous end marker"
|
||||
if (loopEnd == 0)
|
||||
{
|
||||
MPEG_SetLoop((const char *) &mpegROM[loopStart], mpegEnd-loopStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
MPEG_SetLoop((const char *) &mpegROM[loopStart], loopEnd-loopStart);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0xE5: // MPEG end, high byte
|
||||
endLatch &= 0x00FFFF;
|
||||
endLatch |= ((UINT32)data) << 16;
|
||||
break;
|
||||
|
||||
case 0xE6: // MPEG end, middle byte
|
||||
endLatch &= 0xFF00FF;
|
||||
endLatch |= ((UINT32)data) << 8;
|
||||
break;
|
||||
|
||||
case 0xE7: // MPEG end, low byte
|
||||
endLatch &= 0xFFFF00;
|
||||
endLatch |= data;
|
||||
|
||||
if (mpegState == 0)
|
||||
{
|
||||
mpegEnd = endLatch;
|
||||
//printf("mpegEnd = %08X\n", mpegEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
loopEnd = endLatch;
|
||||
//printf("loopEnd = %08X\n", loopEnd);
|
||||
MPEG_SetLoop((const char *) &mpegROM[loopStart], loopEnd-loopStart);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE8: // MPEG volume
|
||||
break;
|
||||
|
||||
case 0xE9: // MPEG stereo
|
||||
break;
|
||||
|
||||
case 0xF0: // command echo back
|
||||
break;
|
||||
|
||||
default:
|
||||
//printf("Z80 Port %02X=%08X\n", addr, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 CDSB1::IORead8(UINT32 addr)
|
||||
{
|
||||
int progress;
|
||||
|
||||
switch ((addr&0xFF))
|
||||
{
|
||||
case 0xE2: // MPEG position, high byte
|
||||
progress = MPEG_GetProgress() + mpegStart; // byte address currently playing
|
||||
return (progress>>16)&0xFF;
|
||||
|
||||
case 0xE3: // MPEG position, middle byte
|
||||
progress = MPEG_GetProgress() + mpegStart;
|
||||
return (progress>>8)&0xFF;
|
||||
|
||||
case 0xE4: // MPEG position, low byte
|
||||
progress = MPEG_GetProgress() + mpegStart;
|
||||
return progress&0xFF;
|
||||
|
||||
case 0xF0: // Latch
|
||||
UINT8 d;
|
||||
d = fifo[fifoIdxR]; // retrieve next command byte
|
||||
if (fifoIdxR != fifoIdxW) // if these are equal, nothing has been written yet (don't advance)
|
||||
{
|
||||
fifoIdxR++;
|
||||
fifoIdxR &= 127;
|
||||
}
|
||||
|
||||
if (fifoIdxR == fifoIdxW) // FIFO empty?
|
||||
status &= ~2; // yes, indicate no commands left
|
||||
else
|
||||
status |= 2;
|
||||
|
||||
Z80.SetINT(FALSE); // clear IRQ
|
||||
//printf("Z80: INT cleared, read from FIFO\n");
|
||||
return d;
|
||||
|
||||
case 0xF1: // Status
|
||||
/*
|
||||
* Bit 0: Must be 1 for most games.
|
||||
* Bit 1: Command pending (used by SWA instead of IRQ)
|
||||
* SWA requires (status&0x38)==0 or else it loops endlessly
|
||||
*/
|
||||
return status;
|
||||
}
|
||||
|
||||
//printf("Z80 Port Read %02X\n", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Z80IRQCallback(CZ80 *Z80)
|
||||
{
|
||||
return 0x38;
|
||||
}
|
||||
|
||||
void CDSB1::SendCommand(UINT8 data)
|
||||
{
|
||||
/*
|
||||
* Commands are buffered in a FIFO. This probably does not actually exist
|
||||
* on the real DSB but is necessary because the Z80 is not really synced
|
||||
* up with the other CPUs and must process all commands it has received
|
||||
* over the course of a frame at once.
|
||||
*/
|
||||
fifo[fifoIdxW++] = data;
|
||||
fifoIdxW &= 127;
|
||||
//printf("Write FIFO: %02X\n", data);
|
||||
|
||||
// Have we caught up to the read pointer?
|
||||
#ifdef DEBUG
|
||||
if (fifoIdxW == fifoIdxR)
|
||||
printf("DSB1 FIFO overflow!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void CDSB1::RunFrame(INT16 *audioL, INT16 *audioR)
|
||||
{
|
||||
#ifdef SUPERMODEL_SOUND
|
||||
int cycles;
|
||||
|
||||
// While FIFO not empty, fire interrupts, run for up to one frame
|
||||
for (cycles = (4000000/60)/4; (cycles > 0) && (fifoIdxR != fifoIdxW); )
|
||||
{
|
||||
Z80.SetINT(TRUE); // fire an IRQ to indicate pending command
|
||||
//printf("Z80 INT fired\n");
|
||||
cycles -= Z80.Run(500);
|
||||
}
|
||||
|
||||
// Run remaining cycles
|
||||
Z80.Run(cycles);
|
||||
|
||||
// Decode MPEG for this frame
|
||||
INT16 *mpegFill[2] = { &mpegL[retainedSamples], &mpegR[retainedSamples] };
|
||||
MPEG_Decode(mpegFill, 32000/60-retainedSamples+2);
|
||||
retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, 44100/60, 32000/60+2, 44100, 32000);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void CDSB1::Reset(void)
|
||||
{
|
||||
MPEG_StopPlaying();
|
||||
Resampler.Reset();
|
||||
retainedSamples = 0;
|
||||
|
||||
memset(fifo, 0, sizeof(fifo));
|
||||
fifoIdxW = fifoIdxR = 0;
|
||||
|
||||
status = 1;
|
||||
mpegState = 0; // why doesn't RB ever init this?
|
||||
|
||||
Z80.Reset();
|
||||
DebugLog("DSB1 Reset\n");
|
||||
}
|
||||
|
||||
// Offsets of memory regions within DSB2's pool
|
||||
#define DSB1_OFFSET_RAM 0 // 32KB Z80 RAM
|
||||
#define DSB1_OFFSET_MPEG_LEFT 0x8000 // 1604 bytes (48 KHz max., 1/60th second, 2 extra = 2*(48000/60+2)) left MPEG buffer
|
||||
#define DSB1_OFFSET_MPEG_RIGHT 0x8644 // 1604 bytes right MPEG buffer
|
||||
#define DSB1_MEMORY_POOL_SIZE (0x8000+0x644+0x644)
|
||||
|
||||
BOOL CDSB1::Init(const UINT8 *progROMPtr, const UINT8 *mpegROMPtr)
|
||||
{
|
||||
float memSizeMB = (float)DSB1_MEMORY_POOL_SIZE/(float)0x100000;
|
||||
|
||||
// Receive ROM
|
||||
progROM = progROMPtr;
|
||||
mpegROM = mpegROMPtr;
|
||||
|
||||
// Allocate memory pool
|
||||
memoryPool = new(std::nothrow) UINT8[DSB1_MEMORY_POOL_SIZE];
|
||||
if (NULL == memoryPool)
|
||||
return ErrorLog("Insufficient memory for DSB1 board (needs %1.1f MB).", memSizeMB);
|
||||
memset(memoryPool, 0, DSB1_MEMORY_POOL_SIZE);
|
||||
|
||||
// Set up memory pointers
|
||||
ram = &memoryPool[DSB1_OFFSET_RAM];
|
||||
mpegL = (INT16 *) &memoryPool[DSB1_OFFSET_MPEG_LEFT];
|
||||
mpegR = (INT16 *) &memoryPool[DSB1_OFFSET_MPEG_RIGHT];
|
||||
|
||||
// Initialize Z80 CPU
|
||||
Z80.Init(this, Z80IRQCallback);
|
||||
|
||||
// MPEG decoder
|
||||
if (OKAY != MPEG_Init())
|
||||
return ErrorLog("Insufficient memory to initialize MPEG decoder.");
|
||||
retainedSamples = 0;
|
||||
|
||||
return OKAY;
|
||||
}
|
||||
|
||||
CDSB1::CDSB1(void)
|
||||
{
|
||||
progROM = NULL;
|
||||
mpegROM = NULL;
|
||||
memoryPool = NULL;
|
||||
ram = NULL;
|
||||
mpegL = NULL;
|
||||
mpegR = NULL;
|
||||
|
||||
DebugLog("Built DSB1 Board\n");
|
||||
}
|
||||
|
||||
CDSB1::~CDSB1(void)
|
||||
{
|
||||
MPEG_Shutdown();
|
||||
|
||||
if (memoryPool != NULL)
|
||||
{
|
||||
delete [] memoryPool;
|
||||
memoryPool = NULL;
|
||||
}
|
||||
|
||||
progROM = NULL;
|
||||
mpegROM = NULL;
|
||||
ram = NULL;
|
||||
mpegL = NULL;
|
||||
mpegR = NULL;
|
||||
|
||||
DebugLog("Destroyed DSB1 Board\n");
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Digital Sound Board Type 2: 68K CPU
|
||||
******************************************************************************/
|
||||
|
||||
enum
|
||||
{
|
||||
ST_IDLE = 0,
|
||||
ST_GOT14, // start/loop addr
|
||||
ST_14_0,
|
||||
ST_14_1,
|
||||
ST_GOT24, // end addr
|
||||
ST_24_0,
|
||||
ST_24_1,
|
||||
ST_GOT74,
|
||||
ST_GOTA0,
|
||||
ST_GOTA1,
|
||||
ST_GOTA4,
|
||||
ST_GOTA5,
|
||||
ST_GOTB0,
|
||||
ST_GOTB1,
|
||||
ST_GOTB4,
|
||||
ST_GOTB5,
|
||||
};
|
||||
|
||||
void CDSB2::WriteMPEGFIFO(UINT8 byte)
|
||||
{
|
||||
//printf("fifo: %x (state %d)\n", byte, mpegState);
|
||||
switch (mpegState)
|
||||
{
|
||||
case ST_IDLE:
|
||||
if (byte == 0x14) mpegState = ST_GOT14;
|
||||
else if (byte == 0x15) mpegState = ST_GOT14;
|
||||
else if (byte == 0x24) mpegState = ST_GOT24;
|
||||
else if (byte == 0x25) mpegState = ST_GOT24;
|
||||
|
||||
else if (byte == 0x74 || byte == 0x75) // "start play"
|
||||
{
|
||||
MPEG_PlayMemory((const char *) &mpegROM[mpegStart], mpegEnd-mpegStart);
|
||||
mpegState = ST_IDLE;
|
||||
playing = 1;
|
||||
}
|
||||
|
||||
else if (byte == 0x84 || byte == 0x85)
|
||||
{
|
||||
MPEG_StopPlaying();
|
||||
playing = 0;
|
||||
}
|
||||
|
||||
else if (byte == 0xa0) mpegState = ST_GOTA0;
|
||||
else if (byte == 0xa1) mpegState = ST_GOTA1;
|
||||
else if (byte == 0xa4) mpegState = ST_GOTA4;
|
||||
else if (byte == 0xa5) mpegState = ST_GOTA5;
|
||||
|
||||
else if (byte == 0xb0) mpegState = ST_GOTB0;
|
||||
else if (byte == 0xb1) mpegState = ST_GOTB1;
|
||||
else if (byte == 0xb4) mpegState = ST_GOTB4;
|
||||
else if (byte == 0xb5) mpegState = ST_GOTB5;
|
||||
|
||||
break;
|
||||
|
||||
case ST_GOT14:
|
||||
mpegStart &= ~0xff0000;
|
||||
mpegStart |= (byte<<16);
|
||||
mpegState++;
|
||||
break;
|
||||
case ST_14_0:
|
||||
mpegStart &= ~0xff00;
|
||||
mpegStart |= (byte<<8);
|
||||
mpegState++;
|
||||
break;
|
||||
case ST_14_1:
|
||||
mpegStart &= ~0xff;
|
||||
mpegStart |= (byte);
|
||||
mpegState = ST_IDLE;
|
||||
|
||||
if (playing)
|
||||
{
|
||||
//printf("Setting loop point to %x\n", mpegStart);
|
||||
MPEG_PlayMemory((const char *) &mpegROM[mpegStart], mpegEnd-mpegStart);
|
||||
}
|
||||
|
||||
//printf("mpegStart=%x\n", mpegStart);
|
||||
break;
|
||||
case ST_GOT24:
|
||||
mpegEnd &= ~0xff0000;
|
||||
mpegEnd |= (byte<<16);
|
||||
mpegState++;
|
||||
break;
|
||||
case ST_24_0:
|
||||
mpegEnd &= ~0xff00;
|
||||
mpegEnd |= (byte<<8);
|
||||
mpegState++;
|
||||
break;
|
||||
case ST_24_1:
|
||||
mpegEnd &= ~0xff;
|
||||
mpegEnd |= (byte);
|
||||
//printf("mpegEnd=%x\n", mpegEnd);
|
||||
|
||||
// default to full stereo
|
||||
// mixer_set_stereo_volume(0, 255, 255);
|
||||
// mixer_set_stereo_pan(0, MIXER_PAN_RIGHT, MIXER_PAN_LEFT);
|
||||
mpegState = ST_IDLE;
|
||||
break;
|
||||
case ST_GOTA0:
|
||||
// ch 0 mono
|
||||
// mixer_set_stereo_volume(0, 0, 255);
|
||||
// printf("ch 0 mono\n");
|
||||
// mixer_set_stereo_pan(0, MIXER_PAN_CENTER, MIXER_PAN_CENTER);
|
||||
mpegState = ST_IDLE;
|
||||
break;
|
||||
case ST_GOTA1:
|
||||
mpegState = ST_IDLE;
|
||||
break;
|
||||
case ST_GOTA4:
|
||||
mpegState = ST_IDLE;
|
||||
break;
|
||||
case ST_GOTA5:
|
||||
mpegState = ST_IDLE;
|
||||
break;
|
||||
case ST_GOTB0:
|
||||
mpegState = ST_IDLE;
|
||||
break;
|
||||
case ST_GOTB1:
|
||||
// ch 1 mono
|
||||
// printf("ch 1 mono\n");
|
||||
// mixer_set_stereo_volume(0, 255, 0);
|
||||
// mixer_set_stereo_pan(0, MIXER_PAN_CENTER, MIXER_PAN_CENTER);
|
||||
mpegState = ST_IDLE;
|
||||
break;
|
||||
case ST_GOTB4:
|
||||
mpegState = ST_IDLE;
|
||||
break;
|
||||
case ST_GOTB5:
|
||||
mpegState = ST_IDLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 CDSB2::Read8(UINT32 addr)
|
||||
{
|
||||
if (addr < (128*1024))
|
||||
return progROM[addr^1];
|
||||
|
||||
if (addr == 0xc00001)
|
||||
{
|
||||
return cmdLatch;
|
||||
}
|
||||
if (addr == 0xc00003) // bit 0 = command valid
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (addr == 0xe80001)
|
||||
{
|
||||
return 0x01; // MPEG busy status: bit 1 = busy
|
||||
} // polled by irq2, stored | 0x10 at f01010
|
||||
|
||||
if ((addr >= 0xf00000) && (addr < 0xf10000))
|
||||
{
|
||||
addr &= 0x1ffff;
|
||||
return ram[addr^1];
|
||||
}
|
||||
|
||||
// printf("R8 @ %x\n", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 CDSB2::Read16(UINT32 addr)
|
||||
{
|
||||
if (addr < (128*1024))
|
||||
{
|
||||
return *(UINT16 *) &progROM[addr];
|
||||
}
|
||||
if ((addr >= 0xf00000) && (addr < 0xf20000))
|
||||
{
|
||||
addr &= 0x1ffff;
|
||||
return *(UINT16 *) &ram[addr];
|
||||
}
|
||||
|
||||
// printf("R16 @ %x\n", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT32 CDSB2::Read32(UINT32 addr)
|
||||
{
|
||||
UINT32 hi, lo;
|
||||
|
||||
if (addr < (128*1024))
|
||||
{
|
||||
hi = *(UINT16 *) &progROM[addr];
|
||||
lo = *(UINT16 *) &progROM[addr+2];
|
||||
return (hi<<16)|lo;
|
||||
}
|
||||
if ((addr >= 0xf00000) && (addr < 0xf20000))
|
||||
{
|
||||
addr &= 0x1ffff;
|
||||
hi = *(UINT16 *) &ram[addr];
|
||||
lo = *(UINT16 *) &ram[addr+2];
|
||||
return (hi<<16)|lo;
|
||||
}
|
||||
// printf("R32 @ %x\n", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CDSB2::Write8(UINT32 addr, UINT8 data)
|
||||
{
|
||||
if ((addr >= 0xf00000) && (addr < 0xf20000))
|
||||
{
|
||||
addr &= 0x1ffff;
|
||||
ram[addr^1] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr == 0xd00001) return;
|
||||
|
||||
if (addr == 0xe00003)
|
||||
{
|
||||
WriteMPEGFIFO(data);
|
||||
return;
|
||||
}
|
||||
|
||||
// printf("W8: %x @ %x (PC=%x)\n", data, addr, m68k_get_reg(NULL, M68K_REG_PC));
|
||||
}
|
||||
|
||||
void CDSB2::Write16(UINT32 addr, UINT16 data)
|
||||
{
|
||||
if ((addr >= 0xf00000) && (addr < 0xf20000))
|
||||
{
|
||||
addr &= 0x1ffff;
|
||||
*(UINT16 *) &ram[addr] = data;
|
||||
return;
|
||||
}
|
||||
// printf("W16: %x @ %x\n", data, addr);
|
||||
}
|
||||
|
||||
void CDSB2::Write32(UINT32 addr, UINT32 data)
|
||||
{
|
||||
if ((addr >= 0xf00000) && (addr < 0xf20000))
|
||||
{
|
||||
addr &= 0x1ffff;
|
||||
*(UINT16 *) &ram[addr+0] = (data>>16);
|
||||
*(UINT16 *) &ram[addr+2] = data&0xFFFF;
|
||||
return;
|
||||
}
|
||||
// printf("W32: %x @ %x\n", data, addr);
|
||||
}
|
||||
|
||||
void CDSB2::SendCommand(UINT8 data)
|
||||
{
|
||||
/*
|
||||
* Commands are buffered in a FIFO. This probably does not actually exist
|
||||
* on the real DSB but is necessary because the Z80 is not really synced
|
||||
* up with the other CPUs and must process all commands it has received
|
||||
* over the course of a frame at once.
|
||||
*/
|
||||
fifo[fifoIdxW++] = data;
|
||||
fifoIdxW &= 127;
|
||||
//printf("Write FIFO: %02X\n", data);
|
||||
|
||||
// Have we caught up to the read pointer?
|
||||
#ifdef DEBUG
|
||||
if (fifoIdxW == fifoIdxR)
|
||||
printf("DSB2 FIFO overflow!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CDSB2::RunFrame(INT16 *audioL, INT16 *audioR)
|
||||
{
|
||||
#ifdef SUPERMODEL_SOUND
|
||||
M68KSetContext(&M68K);
|
||||
|
||||
// While FIFO not empty...
|
||||
while (fifoIdxR != fifoIdxW)
|
||||
{
|
||||
cmdLatch = fifo[fifoIdxR]; // retrieve next command byte
|
||||
fifoIdxR++;
|
||||
fifoIdxR &= 127;
|
||||
|
||||
M68KSetIRQ(1); // indicate pending command
|
||||
//printf("68K INT fired\n");
|
||||
M68KRun(500);
|
||||
}
|
||||
|
||||
// Per-frame interrupt
|
||||
M68KSetIRQ(2);
|
||||
M68KRun(4000000/60);
|
||||
|
||||
M68KGetContext(&M68K);
|
||||
|
||||
// Decode MPEG for this frame
|
||||
INT16 *mpegFill[2] = { &mpegL[retainedSamples], &mpegR[retainedSamples] };
|
||||
MPEG_Decode(mpegFill, 32000/60-retainedSamples+2);
|
||||
retainedSamples = Resampler.UpSampleAndMix(audioL, audioR, mpegL, mpegR, 44100/60, 32000/60+2, 44100, 32000);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void CDSB2::Reset(void)
|
||||
{
|
||||
MPEG_StopPlaying();
|
||||
Resampler.Reset();
|
||||
retainedSamples = 0;
|
||||
|
||||
memset(fifo, 0, sizeof(fifo));
|
||||
fifoIdxW = fifoIdxR = 0;
|
||||
|
||||
mpegState = ST_IDLE;
|
||||
playing = 0;
|
||||
|
||||
M68KSetContext(&M68K);
|
||||
M68KReset();
|
||||
M68KGetContext(&M68K);
|
||||
|
||||
DebugLog("DSB2 Reset\n");
|
||||
}
|
||||
|
||||
// Offsets of memory regions within DSB2's pool
|
||||
#define DSB2_OFFSET_RAM 0 // 128KB 68K RAM
|
||||
#define DSB2_OFFSET_MPEG_LEFT 0x20000 // 1604 bytes (48 KHz max., 1/60th second, 2 extra = 2*(48000/60+2)) left MPEG buffer
|
||||
#define DSB2_OFFSET_MPEG_RIGHT 0x20644 // 1604 bytes right MPEG buffer
|
||||
#define DSB2_MEMORY_POOL_SIZE (0x20000+0x644+0x644)
|
||||
|
||||
BOOL CDSB2::Init(const UINT8 *progROMPtr, const UINT8 *mpegROMPtr)
|
||||
{
|
||||
float memSizeMB = (float)DSB2_MEMORY_POOL_SIZE/(float)0x100000;
|
||||
|
||||
// Receive ROM
|
||||
progROM = progROMPtr;
|
||||
mpegROM = mpegROMPtr;
|
||||
|
||||
// Allocate memory pool
|
||||
memoryPool = new(std::nothrow) UINT8[DSB2_MEMORY_POOL_SIZE];
|
||||
if (NULL == memoryPool)
|
||||
return ErrorLog("Insufficient memory for DSB2 board (needs %1.1f MB).", memSizeMB);
|
||||
memset(memoryPool, 0, DSB2_MEMORY_POOL_SIZE);
|
||||
|
||||
// Set up memory pointers
|
||||
ram = &memoryPool[DSB2_OFFSET_RAM];
|
||||
mpegL = (INT16 *) &memoryPool[DSB2_OFFSET_MPEG_LEFT];
|
||||
mpegR = (INT16 *) &memoryPool[DSB2_OFFSET_MPEG_RIGHT];
|
||||
|
||||
// Initialize 68K CPU
|
||||
M68KSetContext(&M68K);
|
||||
M68KInit();
|
||||
M68KAttachBus(this);
|
||||
M68KSetIRQCallback(NULL); // use default behavior (autovector, clear interrupt)
|
||||
M68KGetContext(&M68K);
|
||||
|
||||
// MPEG decoder
|
||||
if (OKAY != MPEG_Init())
|
||||
return ErrorLog("Insufficient memory to initialize MPEG decoder.");
|
||||
retainedSamples = 0;
|
||||
|
||||
return OKAY;
|
||||
}
|
||||
|
||||
CDSB2::CDSB2(void)
|
||||
{
|
||||
progROM = NULL;
|
||||
mpegROM = NULL;
|
||||
memoryPool = NULL;
|
||||
ram = NULL;
|
||||
mpegL = NULL;
|
||||
mpegR = NULL;
|
||||
|
||||
DebugLog("Built DSB2 Board\n");
|
||||
}
|
||||
|
||||
CDSB2::~CDSB2(void)
|
||||
{
|
||||
MPEG_Shutdown();
|
||||
|
||||
if (memoryPool != NULL)
|
||||
{
|
||||
delete [] memoryPool;
|
||||
memoryPool = NULL;
|
||||
}
|
||||
|
||||
progROM = NULL;
|
||||
mpegROM = NULL;
|
||||
ram = NULL;
|
||||
mpegL = NULL;
|
||||
mpegR = NULL;
|
||||
|
||||
DebugLog("Destroyed DSB2 Board\n");
|
||||
}
|
256
Src/Model3/DSB.h
Normal file
256
Src/Model3/DSB.h
Normal file
|
@ -0,0 +1,256 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011 Bart Trzynadlowski
|
||||
**
|
||||
** 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/>.
|
||||
**/
|
||||
|
||||
/*
|
||||
* DSB.h
|
||||
*
|
||||
* Header file for the Sega Digital Sound Board (Type 1 and 2) devices. CDSB1
|
||||
* is an implementation of the Z80-based DSB Type 1, and CDSB2 is the 68K-based
|
||||
* Type 2 board. Only one may be active at a time because they rely on non-
|
||||
* reentrant MPEG playback code.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_DSB_H
|
||||
#define INCLUDED_DSB_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "CPU/Bus.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Resampling
|
||||
|
||||
Used internally by the DSB's MPEG code. If this becomes sufficiently generic,
|
||||
it can be moved to Sound/. Not intended for general use for now.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* CDSBResampler:
|
||||
*
|
||||
* Frame-by-frame resampler. Resamples one single frame of audio and maintains
|
||||
* continuity between frames by copying unprocessed input samples to the
|
||||
* beginning of the buffer and retaining the internal interpolation state.
|
||||
*
|
||||
* See DSB.cpp for a detailed description of how this works.
|
||||
*
|
||||
* NOTE: If the sampling frequencies change, it is probably best to call
|
||||
* Reset(). Whether the resampler will otherwise behave correctly and stay
|
||||
* within array bounds has not been verified.
|
||||
*
|
||||
* Designed for use at 60 Hz, for input frequencies of 11.025, 22.05, 16, and
|
||||
* 32 KHz and 44.1 KHz output frequencies. Theoretically, it should be able to
|
||||
* operate on most output frequencies and input frequencies that are simply
|
||||
* lower, but it has not been extensively verified.
|
||||
*/
|
||||
class CDSBResampler
|
||||
{
|
||||
public:
|
||||
int UpSampleAndMix(INT16 *outL, INT16 *outR, INT16 *inL, INT16 *inR, int sizeOut, int sizeIn, int outRate, int inRate);
|
||||
void Reset(void);
|
||||
private:
|
||||
int nFrac;
|
||||
int pFrac;
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
DSB Base Class
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* CDSB:
|
||||
*
|
||||
* Abstract base class defining the common interface for both DSB board types.
|
||||
*/
|
||||
|
||||
class CDSB: public CBus
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* SendCommand(data):
|
||||
*
|
||||
* Send a MIDI command to the DSB board.
|
||||
*/
|
||||
virtual void SendCommand(UINT8 data) = 0;
|
||||
|
||||
/*
|
||||
* RunFrame(audioL, audioR):
|
||||
*
|
||||
* Runs one frame and updates the MPEG audio. Audio is mixed into the
|
||||
* supplied buffers (they are assumed to already contain audio data).
|
||||
*
|
||||
* Parameters:
|
||||
* audioL Left audio channel, one frame (44 KHz, 1/60th second).
|
||||
* audioR Right audio channel.
|
||||
*/
|
||||
virtual void RunFrame(INT16 *audioL, INT16 *audioR) = 0;
|
||||
|
||||
/*
|
||||
* Reset(void):
|
||||
*
|
||||
* Resets the DSB. Must be called prior to RunFrame().
|
||||
*/
|
||||
virtual void Reset(void) = 0;
|
||||
|
||||
/*
|
||||
* Init(progROMPtr, mpegROMPtr):
|
||||
*
|
||||
* Initializes the DSB board. This member must be called first.
|
||||
*
|
||||
* Parameters:
|
||||
* progROMPtr Program (68K or Z80) ROM.
|
||||
* mpegROMPtr MPEG data ROM.
|
||||
*
|
||||
* Returns:
|
||||
* OKAY if successful, otherwise FAIL.
|
||||
*/
|
||||
virtual BOOL Init(const UINT8 *progROMPtr, const UINT8 *mpegROMPtr) = 0;
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
DSB Classes
|
||||
|
||||
DSB1 and DSB2 hardware. The base class, CDSB, should ideally be dynamically
|
||||
allocated using one of these. See CDSB for descriptions of member functions.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* CDSB1:
|
||||
*
|
||||
* Sega Digital Sound Board Type 1: Z80 plus custom gate array for MPEG
|
||||
* decoding.
|
||||
*/
|
||||
class CDSB1: public CDSB
|
||||
{
|
||||
public:
|
||||
// Read and write handlers for the Z80 (required by CBus)
|
||||
UINT8 IORead8(UINT32 addr);
|
||||
void IOWrite8(UINT32 addr, UINT8 data);
|
||||
UINT8 Read8(UINT32 addr);
|
||||
void Write8(UINT32 addr, UINT8 data);
|
||||
|
||||
// DSB interface (see CDSB definition)
|
||||
void SendCommand(UINT8 data);
|
||||
void RunFrame(INT16 *audioL, INT16 *audioR);
|
||||
void Reset(void);
|
||||
BOOL Init(const UINT8 *progROMPtr, const UINT8 *mpegROMPtr);
|
||||
|
||||
// Constructor and destructor
|
||||
CDSB1(void);
|
||||
~CDSB1(void);
|
||||
|
||||
private:
|
||||
// Resampler
|
||||
CDSBResampler Resampler;
|
||||
int retainedSamples; // how many MPEG samples carried over from previous frame
|
||||
|
||||
// MPEG decode buffers (48KHz, 1/60th second + 2 extra padding samples)
|
||||
INT16 *mpegL, *mpegR;
|
||||
|
||||
// DSB memory
|
||||
const UINT8 *progROM; // Z80 program ROM (passed in from parent object)
|
||||
const UINT8 *mpegROM; // MPEG music ROM
|
||||
UINT8 *memoryPool; // all memory allocated here
|
||||
UINT8 *ram; // Z80 RAM
|
||||
|
||||
// Command FIFO
|
||||
UINT8 fifo[128];
|
||||
int fifoIdxR; // read position
|
||||
int fifoIdxW; // write position
|
||||
|
||||
// MPEG playback variables
|
||||
int mpegStart;
|
||||
int mpegEnd;
|
||||
int mpegState;
|
||||
int loopStart;
|
||||
int loopEnd;
|
||||
|
||||
// Registers
|
||||
UINT32 startLatch; // MPEG start address latch
|
||||
UINT32 endLatch; // MPEG end address latch
|
||||
UINT8 status;
|
||||
UINT8 chain;
|
||||
UINT8 cmdLatch;
|
||||
|
||||
// Z80 CPU
|
||||
CZ80 Z80;
|
||||
};
|
||||
|
||||
/*
|
||||
* CDSB2:
|
||||
*
|
||||
* Sega Digital Sound Board Type 2: 68K CPU.
|
||||
*/
|
||||
class CDSB2: public CDSB
|
||||
{
|
||||
public:
|
||||
// Read and write handlers for the 68K (required by CBus)
|
||||
UINT8 Read8(UINT32 addr);
|
||||
UINT16 Read16(UINT32 addr);
|
||||
UINT32 Read32(UINT32 addr);
|
||||
void Write8(UINT32 addr, UINT8 data);
|
||||
void Write16(UINT32 addr, UINT16 data);
|
||||
void Write32(UINT32 addr, UINT32 data);
|
||||
|
||||
// DSB interface (see definition of CDSB)
|
||||
void SendCommand(UINT8 data);
|
||||
void RunFrame(INT16 *audioL, INT16 *audioR);
|
||||
void Reset(void);
|
||||
BOOL Init(const UINT8 *progROMPtr, const UINT8 *mpegROMPtr);
|
||||
|
||||
// Constructor and destructor
|
||||
CDSB2(void);
|
||||
~CDSB2(void);
|
||||
|
||||
private:
|
||||
// Private helper functions
|
||||
void WriteMPEGFIFO(UINT8 byte);
|
||||
|
||||
// Resampler
|
||||
CDSBResampler Resampler;
|
||||
int retainedSamples; // how many MPEG samples carried over from previous frame
|
||||
|
||||
// MPEG decode buffers (48KHz, 1/60th second + 2 extra padding samples)
|
||||
INT16 *mpegL, *mpegR;
|
||||
|
||||
// DSB memory
|
||||
const UINT8 *progROM; // Z80 program ROM (passed in from parent object)
|
||||
const UINT8 *mpegROM; // MPEG music ROM
|
||||
UINT8 *memoryPool; // all memory allocated here
|
||||
UINT8 *ram; // Z80 RAM
|
||||
|
||||
// Command FIFO
|
||||
UINT8 fifo[128];
|
||||
int fifoIdxR; // read position
|
||||
int fifoIdxW; // write position
|
||||
|
||||
// Registers
|
||||
int cmdLatch;
|
||||
int mpegState;
|
||||
int mpegStart, mpegEnd, playing;
|
||||
|
||||
// M68K CPU
|
||||
M68KCtx M68K;
|
||||
};
|
||||
|
||||
|
||||
#endif // INCLUDED_DSB_H
|
|
@ -1,5 +1,6 @@
|
|||
//TODO: Update save state file format (must output) MIDI control port; will no longer be compatible with 0.1a save states
|
||||
//TODO: should sample roms be byteswapped? They currently are. This could also be done in the game list with the byteswap flag...
|
||||
//TODO: Star Wars expects bit 0x80 to be set when reading from MIDI control port. This should be made explicit! Lostwsga may behave similarly
|
||||
|
||||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
|
@ -1125,7 +1126,7 @@ void CModel3::Write8(UINT32 addr, UINT8 data)
|
|||
|
||||
// Sound Board
|
||||
case 0x08:
|
||||
printf("PPC: %08X=%02X * (PC=%08X, LR=%08X)\n", addr, data, ppc_get_pc(), ppc_get_lr());
|
||||
//printf("PPC: %08X=%02X * (PC=%08X, LR=%08X)\n", addr, data, ppc_get_pc(), ppc_get_lr());
|
||||
if ((addr&0xF) == 0) // MIDI data port
|
||||
SoundBoard.WriteMIDIPort(data);
|
||||
else if ((addr&0xF) == 4) // MIDI control port
|
||||
|
@ -2112,23 +2113,38 @@ void CModel3::RunMainBoardFrame(void)
|
|||
IRQ.Assert(0x02);
|
||||
ppc_execute(10000); // TO-DO: Vblank probably needs to be longer. Maybe that's why some games run too fast/slow
|
||||
|
||||
// Sound
|
||||
/*
|
||||
* Sound:
|
||||
*
|
||||
* Bit 0x20 of the MIDI control port appears to enable periodic interrupts,
|
||||
* which are used to send MIDI commands. Often games will write 0x27, send
|
||||
* a series of commands, and write 0x06 to stop. Other games, like Star
|
||||
* Wars Trilogy and Sega Rally 2, will enable interrupts at the beginning
|
||||
* by writing 0x37 and will disable/enable interrupts to control command
|
||||
* output.
|
||||
*/
|
||||
int irqCount = 0;
|
||||
while (midiCtrlPort == 0x27) // 27 triggers IRQ sequence, 06 stops it
|
||||
while ((midiCtrlPort&0x20))
|
||||
//while (midiCtrlPort == 0x27) // 27 triggers IRQ sequence, 06 stops it
|
||||
{
|
||||
// Don't waste time firing MIDI interrupts if game has disabled them
|
||||
if ((IRQ.ReadIRQEnable()&0x40) == 0)
|
||||
break;
|
||||
|
||||
// Process MIDI interrupt
|
||||
IRQ.Assert(0x40);
|
||||
ppc_execute(200);
|
||||
ppc_execute(200); // give PowerPC time to acknowledge IRQ
|
||||
IRQ.Deassert(0x40);
|
||||
ppc_execute(200);
|
||||
ppc_execute(200); // acknowledge that IRQ was deasserted (TODO: is this really needed?)
|
||||
|
||||
++irqCount;
|
||||
if (irqCount > (128))
|
||||
if (irqCount > 128)
|
||||
{
|
||||
printf("MIDI TIMEOUT!\n");
|
||||
printf("MIDI FIFO OVERFLOW!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
IRQ.Deassert(0x40);
|
||||
IRQ.Deassert(0x40); //todo: no longer needed, remove it
|
||||
}
|
||||
|
||||
void CModel3::Reset(void)
|
||||
|
@ -2409,9 +2425,11 @@ static void Dump(const char *file, UINT8 *buf, unsigned size, BOOL reverse32, BO
|
|||
#define OFFSET_VROM 0x9000000 // 64 MB
|
||||
#define OFFSET_BACKUPRAM 0xD000000 // 128 KB
|
||||
#define OFFSET_SECURITYRAM 0xD020000 // 128 KB
|
||||
#define OFFSET_SOUNDROM 0xD040000 // 512 KB
|
||||
#define OFFSET_SAMPLEROM 0xD0C0000 // 16 MB
|
||||
#define MEMORY_POOL_SIZE (0x800000+0x800000+0x8000000+0x4000000+0x20000+0x20000+0x80000+0x1000000)
|
||||
#define OFFSET_SOUNDROM 0xD040000 // 512 KB (68K sound board program)
|
||||
#define OFFSET_SAMPLEROM 0xD0C0000 // 16 MB (sound board samples)
|
||||
#define OFFSET_DSBPROGROM 0xE0C0000 // 128 KB (DSB program)
|
||||
#define OFFSET_DSBMPEGROM 0xE0E0000 // 16 MB (DSB MPEG data -- Z80 version only uses 8MB)
|
||||
#define MEMORY_POOL_SIZE (0x800000+0x800000+0x8000000+0x4000000+0x20000+0x20000+0x80000+0x1000000+0x20000+0x1000000)
|
||||
|
||||
const struct GameInfo * CModel3::GetGameInfo(void)
|
||||
{
|
||||
|
@ -2428,6 +2446,8 @@ BOOL CModel3::LoadROMSet(const struct GameInfo *GameList, const char *zipFile)
|
|||
{ "VROM", vrom },
|
||||
{ "SndProg", soundROM },
|
||||
{ "Samples", sampleROM },
|
||||
{ "DSBProg", dsbROM },
|
||||
{ "DSBMPEG", mpegROM },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
PPC_CONFIG PPCConfig;
|
||||
|
@ -2450,9 +2470,9 @@ BOOL CModel3::LoadROMSet(const struct GameInfo *GameList, const char *zipFile)
|
|||
// Byte reverse the PowerPC ROMs (convert to little endian words)
|
||||
Reverse32(crom, 0x800000+0x8000000);
|
||||
|
||||
// Byte swap 68K ROMs
|
||||
// Byte swap sound board 68K ROMs
|
||||
Reverse16(soundROM, 0x80000);
|
||||
Reverse16(sampleROM, 0x1000000); // is this correct?
|
||||
Reverse16(sampleROM, 0x1000000);
|
||||
|
||||
// Initialize CPU and configure hardware (CPU speed is set in Init())
|
||||
if (Game->step >= 0x20) // Step 2.0+
|
||||
|
@ -2499,6 +2519,26 @@ BOOL CModel3::LoadROMSet(const struct GameInfo *GameList, const char *zipFile)
|
|||
|
||||
ppc_set_fetch(PPCFetchRegions);
|
||||
|
||||
// DSB board (if present)
|
||||
if (Game->mpegBoard == 1) // Z80 board, do not byte swap program ROM
|
||||
{
|
||||
DSB = new(std::nothrow) CDSB1();
|
||||
if (NULL == DSB)
|
||||
return ErrorLog("Insufficient memory for Digital Sound Board object.");
|
||||
if (OKAY != DSB->Init(dsbROM,mpegROM))
|
||||
return FAIL;
|
||||
}
|
||||
else if (Game->mpegBoard == 2) // 68K board
|
||||
{
|
||||
Reverse16(dsbROM, 0x20000); // byte swap program ROM
|
||||
DSB = new(std::nothrow) CDSB2();
|
||||
if (NULL == DSB)
|
||||
return ErrorLog("Insufficient memory for Digital Sound Board object.");
|
||||
if (OKAY != DSB->Init(dsbROM,mpegROM))
|
||||
return FAIL;
|
||||
}
|
||||
SoundBoard.AttachDSB(DSB);
|
||||
|
||||
// Apply ROM patches
|
||||
Patch();
|
||||
|
||||
|
@ -2525,6 +2565,7 @@ void CModel3::AttachInputs(CInputs *InputsPtr)
|
|||
DebugLog("Model 3 attached inputs\n");
|
||||
}
|
||||
|
||||
// Model 3 initialization. Some initialization is deferred until ROMs are loaded in LoadROMSet()
|
||||
BOOL CModel3::Init(unsigned ppcFrequencyParam, BOOL multiThreadedParam)
|
||||
{
|
||||
float memSizeMB = (float)MEMORY_POOL_SIZE/(float)0x100000;
|
||||
|
@ -2546,11 +2587,13 @@ BOOL CModel3::Init(unsigned ppcFrequencyParam, BOOL multiThreadedParam)
|
|||
vrom = &memoryPool[OFFSET_VROM];
|
||||
soundROM = &memoryPool[OFFSET_SOUNDROM];
|
||||
sampleROM = &memoryPool[OFFSET_SAMPLEROM];
|
||||
dsbROM = &memoryPool[OFFSET_DSBPROGROM];
|
||||
mpegROM = &memoryPool[OFFSET_DSBMPEGROM];
|
||||
backupRAM = &memoryPool[OFFSET_BACKUPRAM];
|
||||
securityRAM = &memoryPool[OFFSET_SECURITYRAM];
|
||||
SetCROMBank(0xFF);
|
||||
|
||||
// Initialize other devices
|
||||
// Initialize other devices (PowerPC and DSB initialized after ROMs loaded)
|
||||
IRQ.Init();
|
||||
PCIBridge.Init();
|
||||
PCIBus.Init();
|
||||
|
@ -2561,8 +2604,9 @@ BOOL CModel3::Init(unsigned ppcFrequencyParam, BOOL multiThreadedParam)
|
|||
return FAIL;
|
||||
if (OKAY != GPU.Init(vrom,this,&IRQ,0x100)) // same for Real3D DMA interrupt
|
||||
return FAIL;
|
||||
if (OKAY != SoundBoard.Init(soundROM,sampleROM,&IRQ,0x40))
|
||||
if (OKAY != SoundBoard.Init(soundROM,sampleROM))
|
||||
return FAIL;
|
||||
|
||||
#ifdef SUPERMODEL_DRIVEBOARD
|
||||
DriveBoard.Init();
|
||||
#endif
|
||||
|
@ -2589,10 +2633,14 @@ CModel3::CModel3(void)
|
|||
vrom = NULL;
|
||||
soundROM = NULL;
|
||||
sampleROM = NULL;
|
||||
dsbROM = NULL;
|
||||
mpegROM = NULL;
|
||||
cromBank = NULL;
|
||||
backupRAM = NULL;
|
||||
securityRAM = NULL;
|
||||
|
||||
DSB = NULL;
|
||||
|
||||
securityPtr = 0;
|
||||
|
||||
multiThreaded = true;
|
||||
|
@ -2630,18 +2678,27 @@ CModel3::~CModel3(void)
|
|||
// Stop all threads
|
||||
StopThreads();
|
||||
|
||||
// Free memory
|
||||
if (memoryPool != NULL)
|
||||
{
|
||||
delete [] memoryPool;
|
||||
memoryPool = NULL;
|
||||
}
|
||||
|
||||
if (DSB != NULL)
|
||||
{
|
||||
delete DSB;
|
||||
DSB = NULL;
|
||||
}
|
||||
|
||||
Game = NULL;
|
||||
ram = NULL;
|
||||
crom = NULL;
|
||||
vrom = NULL;
|
||||
soundROM = NULL;
|
||||
sampleROM = NULL;
|
||||
dsbROM = NULL;
|
||||
mpegROM = NULL;
|
||||
cromBank = NULL;
|
||||
backupRAM = NULL;
|
||||
securityRAM = NULL;
|
||||
|
|
|
@ -303,6 +303,8 @@ private:
|
|||
UINT8 *vrom; // 64 MB VROM (video ROM, visible only to Real3D)
|
||||
UINT8 *soundROM; // 512 KB sound ROM (68K program)
|
||||
UINT8 *sampleROM; // 8 MB samples (68K)
|
||||
UINT8 *dsbROM; // 128 KB DSB ROM (Z80 program)
|
||||
UINT8 *mpegROM; // 8 MB DSB MPEG ROM
|
||||
UINT8 *backupRAM; // 128 KB Backup RAM (battery backed)
|
||||
UINT8 *securityRAM; // 128 KB Security Board RAM
|
||||
|
||||
|
@ -347,6 +349,7 @@ private:
|
|||
CTileGen TileGen; // Sega 2D tile generator
|
||||
CReal3D GPU; // Real3D graphics hardware
|
||||
CSoundBoard SoundBoard; // Sound board
|
||||
CDSB *DSB; // Digital Sound Board (type determined dynamically at load time)
|
||||
#ifdef SUPERMODEL_DRIVEBOARD
|
||||
CDriveBoard DriveBoard; // Drive board
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
//TODO: clean up M68K interface. pass a bus pointer (SoundBoard should be derived from it), so that M68K handlers have access to CSoundBoard
|
||||
//TODO: must store actual value of bank register so we can save it to save states
|
||||
/**
|
||||
** Supermodel
|
||||
|
@ -26,11 +25,7 @@
|
|||
*
|
||||
* Model 3 sound board. Implementation of the CSoundBoard class. This class can
|
||||
* only be instantiated once because it relies on global variables (the non-OOP
|
||||
* 68K core).
|
||||
*
|
||||
* TO-DO List
|
||||
* ----------
|
||||
* - Optimize memory handlers (jump table).
|
||||
* 68K core and an IRQ line).
|
||||
*
|
||||
* Bank Switching
|
||||
* --------------
|
||||
|
@ -62,248 +57,261 @@
|
|||
|
||||
#include "Supermodel.h"
|
||||
|
||||
//TEMP: these need to be dynamically allocated in the memory pool
|
||||
static INT16 leftBuffer[44100/60],rightBuffer[44100/60];
|
||||
// DEBUG
|
||||
//#define SUPERMODEL_LOG_AUDIO // define this to log all audio to sound.bin
|
||||
#ifdef SUPERMODEL_LOG_AUDIO
|
||||
static FILE *soundFP;
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
68K Access Handlers
|
||||
******************************************************************************/
|
||||
|
||||
// Memory regions passed out of CSoundBoard object for global access handlers
|
||||
static UINT8 *sbRAM1, *sbRAM2;
|
||||
static const UINT8 *sbSoundROM, *sbSampleROM, *sbSampleBankLo, *sbSampleBankHi;
|
||||
|
||||
static UINT8 Read8(UINT32 a)
|
||||
UINT8 CSoundBoard::Read8(UINT32 a)
|
||||
{
|
||||
// SCSP RAM 1
|
||||
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||
return sbRAM1[a^1];
|
||||
switch ((a>>20)&0xF)
|
||||
{
|
||||
case 0x0: // SCSP RAM 1 (master): 000000-0FFFFF
|
||||
return ram1[a^1];
|
||||
|
||||
// SCSP RAM 2
|
||||
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||
return sbRAM2[(a-0x200000)^1];
|
||||
|
||||
// Program ROM
|
||||
else if ((a >= 0x600000) && (a <= 0x67FFFF))
|
||||
return sbSoundROM[(a-0x600000)^1];
|
||||
|
||||
// Sample ROM (low 2MB, fixed)
|
||||
else if ((a >= 0x800000) && (a <= 0x9FFFFF))
|
||||
return sbSampleROM[(a-0x800000)^1];
|
||||
|
||||
// Sample ROM (bank)
|
||||
else if ((a >= 0xA00000) && (a <= 0xDFFFFF))
|
||||
return sbSampleBankLo[(a-0xA00000)^1];
|
||||
|
||||
// Sample ROM (bank)
|
||||
else if ((a >= 0xE00000) && (a <= 0xFFFFFF))
|
||||
return sbSampleBankHi[(a-0xE00000)^1];
|
||||
|
||||
// SCSP (Master)
|
||||
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||
case 0x1: // SCSP registers (master): 100000-10FFFF (unlike real hardware, we mirror up to 1FFFFF)
|
||||
return SCSP_Master_r8(a);
|
||||
|
||||
// SCSP (Slave)
|
||||
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||
case 0x2: // SCSP RAM 2 (slave): 200000-2FFFFF
|
||||
return ram2[(a&0x0FFFFF)^1];
|
||||
|
||||
case 0x3: // SCSP registers (slave): 300000-30FFFF (unlike real hardware, we mirror up to 3FFFFF)
|
||||
return SCSP_Slave_r8(a);
|
||||
|
||||
// Unknown
|
||||
else
|
||||
{
|
||||
case 0x6: // Program ROM: 600000-67FFFF (unlike real hardware, we mirror up to 6FFFFF here)
|
||||
return soundROM[(a&0x07FFFF)^1];
|
||||
|
||||
case 0x8: // Sample ROM (low 2MB, fixed): 800000-9FFFFF
|
||||
case 0x9:
|
||||
return sampleROM[(a&0x1FFFFF)^1];
|
||||
|
||||
case 0xA: // Sample ROM (bank): A00000-DFFFFF
|
||||
case 0xB:
|
||||
case 0xC:
|
||||
case 0xD:
|
||||
return sampleBankLo[(a-0xA00000)^1];
|
||||
|
||||
case 0xE: // Sample ROM (bank): E00000-FFFFFF
|
||||
case 0xF:
|
||||
return sampleBankHi[(a&0x1FFFFF)^1];
|
||||
|
||||
default:
|
||||
printf("68K: Unknown read8 %06X\n", a);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT16 Read16(UINT32 a)
|
||||
UINT16 CSoundBoard::Read16(UINT32 a)
|
||||
{
|
||||
// SCSP RAM 1
|
||||
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||
return *(UINT16 *) &sbRAM1[a];
|
||||
switch ((a>>20)&0xF)
|
||||
{
|
||||
case 0x0: // SCSP RAM 1 (master): 000000-0FFFFF
|
||||
return *(UINT16 *) &ram1[a];
|
||||
|
||||
// SCSP RAM 2
|
||||
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||
return *(UINT16 *) &sbRAM2[(a-0x200000)];
|
||||
|
||||
// Program ROM
|
||||
else if ((a >= 0x600000) && (a <= 0x67FFFF))
|
||||
return *(UINT16 *) &sbSoundROM[(a-0x600000)];
|
||||
|
||||
// Sample ROM (low 2MB, fixed)
|
||||
else if ((a >= 0x800000) && (a <= 0x9FFFFF))
|
||||
return *(UINT16 *) &sbSampleROM[(a-0x800000)];
|
||||
|
||||
// Sample ROM (bank)
|
||||
else if ((a >= 0xA00000) && (a <= 0xDFFFFF))
|
||||
return *(UINT16 *) &sbSampleBankLo[(a-0xA00000)];
|
||||
|
||||
// Sample ROM (bank)
|
||||
else if ((a >= 0xE00000) && (a <= 0xFFFFFF))
|
||||
return *(UINT16 *) &sbSampleBankHi[(a-0xE00000)];
|
||||
|
||||
// SCSP (Master)
|
||||
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||
case 0x1: // SCSP registers (master): 100000-10FFFF
|
||||
return SCSP_Master_r16(a);
|
||||
|
||||
// SCSP (Slave)
|
||||
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||
case 0x2: // SCSP RAM 2 (slave): 200000-2FFFFF
|
||||
return *(UINT16 *) &ram2[a&0x0FFFFF];
|
||||
|
||||
case 0x3: // SCSP registers (slave): 300000-30FFFF
|
||||
return SCSP_Slave_r16(a);
|
||||
|
||||
// Unknown
|
||||
else
|
||||
{
|
||||
case 0x6: // Program ROM: 600000-67FFFF
|
||||
return *(UINT16 *) &soundROM[a&0x07FFFF];
|
||||
|
||||
case 0x8: // Sample ROM (low 2MB, fixed): 800000-9FFFFF
|
||||
case 0x9:
|
||||
return *(UINT16 *) &sampleROM[a&0x1FFFFF];
|
||||
|
||||
case 0xA: // Sample ROM (bank): A00000-DFFFFF
|
||||
case 0xB:
|
||||
case 0xC:
|
||||
case 0xD:
|
||||
return *(UINT16 *) &sampleBankLo[a-0xA00000];
|
||||
|
||||
case 0xE: // Sample ROM (bank): E00000-FFFFFF
|
||||
case 0xF:
|
||||
return *(UINT16 *) &sampleBankHi[a&0x1FFFFF];
|
||||
|
||||
default:
|
||||
printf("68K: Unknown read16 %06X\n", a);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT32 Read32(UINT32 a)
|
||||
UINT32 CSoundBoard::Read32(UINT32 a)
|
||||
{
|
||||
// SCSP RAM 1
|
||||
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||
return (Read16(a)<<16)|Read16(a+2);
|
||||
UINT32 hi, lo;
|
||||
|
||||
// SCSP RAM 2
|
||||
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||
return (Read16(a)<<16)|Read16(a+2);
|
||||
switch ((a>>20)&0xF)
|
||||
{
|
||||
case 0x0: // SCSP RAM 1 (master): 000000-0FFFFF
|
||||
hi = *(UINT16 *) &ram1[a];
|
||||
lo = *(UINT16 *) &ram1[a+2]; // TODO: clamp? Possible bounds hazard.
|
||||
return (hi<<16)|lo;
|
||||
|
||||
// Program ROM
|
||||
else if ((a >= 0x600000) && (a <= 0x67FFFF))
|
||||
return (Read16(a)<<16)|Read16(a+2);
|
||||
|
||||
// Sample ROM (low 2MB, fixed)
|
||||
else if ((a >= 0x800000) && (a <= 0x9FFFFF))
|
||||
return (Read16(a)<<16)|Read16(a+2);
|
||||
|
||||
// Sample ROM (bank)
|
||||
else if ((a >= 0xA00000) && (a <= 0xDFFFFF))
|
||||
return (Read16(a)<<16)|Read16(a+2);
|
||||
|
||||
// Sample ROM (bank)
|
||||
else if ((a >= 0xE00000) && (a <= 0xFFFFFF))
|
||||
return (Read16(a)<<16)|Read16(a+2);
|
||||
|
||||
// SCSP (Master)
|
||||
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||
case 0x1: // SCSP registers (master): 100000-10FFFF
|
||||
return SCSP_Master_r32(a);
|
||||
|
||||
// SCSP (Slave)
|
||||
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||
case 0x2: // SCSP RAM 2 (slave): 200000-2FFFFF
|
||||
hi = *(UINT16 *) &ram2[a&0x0FFFFF];
|
||||
lo = *(UINT16 *) &ram2[(a+2)&0x0FFFFF];
|
||||
return (hi<<16)|lo;
|
||||
|
||||
case 0x3: // SCSP registers (slave): 300000-30FFFF
|
||||
return SCSP_Slave_r32(a);
|
||||
|
||||
// Unknown
|
||||
else
|
||||
{
|
||||
case 0x6: // Program ROM: 600000-67FFFF
|
||||
hi = *(UINT16 *) &soundROM[a&0x07FFFF];
|
||||
lo = *(UINT16 *) &soundROM[(a+2)&0x07FFFF];
|
||||
return (hi<<16)|lo;
|
||||
|
||||
case 0x8: // Sample ROM (low 2MB, fixed): 800000-9FFFFF
|
||||
case 0x9:
|
||||
hi = *(UINT16 *) &sampleROM[a&0x1FFFFF];
|
||||
lo = *(UINT16 *) &sampleROM[(a+2)&0x1FFFFF];
|
||||
return (hi<<16)|lo;
|
||||
|
||||
case 0xA: // Sample ROM (bank): A00000-DFFFFF
|
||||
case 0xB:
|
||||
case 0xC:
|
||||
case 0xD:
|
||||
hi = *(UINT16 *) &sampleBankLo[a-0xA00000];
|
||||
lo = *(UINT16 *) &sampleBankLo[a+2-0xA00000];
|
||||
return (hi<<16)|lo;
|
||||
|
||||
case 0xE: // Sample ROM (bank): E00000-FFFFFF
|
||||
case 0xF:
|
||||
hi = *(UINT16 *) &sampleBankHi[a&0x1FFFFF];
|
||||
lo = *(UINT16 *) &sampleBankHi[(a+2)&0x1FFFFF];
|
||||
return (hi<<16)|lo;
|
||||
|
||||
default:
|
||||
printf("68K: Unknown read32 %06X\n", a);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Write8(unsigned int a,unsigned char d)
|
||||
void CSoundBoard::Write8(unsigned int a,unsigned char d)
|
||||
{
|
||||
switch ((a>>20)&0xF)
|
||||
{
|
||||
case 0x0: // SCSP RAM 1 (master): 000000-0FFFFF
|
||||
ram1[a^1] = d;
|
||||
break;
|
||||
|
||||
// SCSP RAM 1
|
||||
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||
sbRAM1[a^1] = d;
|
||||
|
||||
// SCSP RAM 2
|
||||
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||
sbRAM2[(a-0x200000)^1] = d;
|
||||
|
||||
// SCSP (Master)
|
||||
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||
case 0x1: // SCSP registers (master): 100000-10FFFF
|
||||
SCSP_Master_w8(a,d);
|
||||
break;
|
||||
|
||||
// SCSP (Slave)
|
||||
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||
case 0x2: // SCSP RAM 2 (slave): 200000-2FFFFF
|
||||
ram2[(a&0x0FFFFF)^1] = d;
|
||||
break;
|
||||
|
||||
case 0x3: // SCSP registers (slave): 300000-30FFFF
|
||||
SCSP_Slave_w8(a,d);
|
||||
break;
|
||||
|
||||
// Bank register
|
||||
else if (a == 0x400001)
|
||||
default:
|
||||
if (a == 0x400001)
|
||||
{
|
||||
if ((d&0x10))
|
||||
{
|
||||
sbSampleBankLo = &sbSampleROM[0xA00000];
|
||||
sbSampleBankHi = &sbSampleROM[0xE00000];
|
||||
sampleBankLo = &sampleROM[0xA00000];
|
||||
sampleBankHi = &sampleROM[0xE00000];
|
||||
}
|
||||
else
|
||||
{
|
||||
sbSampleBankLo = &sbSampleROM[0x200000];
|
||||
sbSampleBankHi = &sbSampleROM[0x600000];
|
||||
sampleBankLo = &sampleROM[0x200000];
|
||||
sampleBankHi = &sampleROM[0x600000];
|
||||
}
|
||||
}
|
||||
|
||||
// Unknown
|
||||
else
|
||||
printf("68K: Unknown write8 %06X=%02X\n", a, d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Write16(unsigned int a,unsigned short d)
|
||||
void CSoundBoard::Write16(unsigned int a,unsigned short d)
|
||||
{
|
||||
switch ((a>>20)&0xF)
|
||||
{
|
||||
case 0x0: // SCSP RAM 1 (master): 000000-0FFFFF
|
||||
*(UINT16 *) &ram1[a] = d;
|
||||
break;
|
||||
|
||||
// SCSP RAM 1
|
||||
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||
*(UINT16 *) &sbRAM1[a] = d;
|
||||
|
||||
// SCSP RAM 2
|
||||
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||
*(UINT16 *) &sbRAM2[(a-0x200000)] = d;
|
||||
|
||||
// SCSP (Master)
|
||||
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||
case 0x1: // SCSP registers (master): 100000-10FFFF
|
||||
SCSP_Master_w16(a,d);
|
||||
break;
|
||||
|
||||
// SCSP (Slave)
|
||||
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||
case 0x2: // SCSP RAM 2 (slave): 200000-2FFFFF
|
||||
*(UINT16 *) &ram2[a&0x0FFFFF] = d;
|
||||
break;
|
||||
|
||||
case 0x3: // SCSP registers (slave): 300000-30FFFF
|
||||
SCSP_Slave_w16(a,d);
|
||||
break;
|
||||
|
||||
// Unknown
|
||||
else
|
||||
default:
|
||||
printf("68K: Unknown write16 %06X=%04X\n", a, d);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Write32(unsigned int a,unsigned int d)
|
||||
void CSoundBoard::Write32(unsigned int a,unsigned int d)
|
||||
{
|
||||
// SCSP RAM 1
|
||||
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||
switch ((a>>20)&0xF)
|
||||
{
|
||||
Write16(a,d>>16);
|
||||
Write16(a+2,d&0xFFFF);
|
||||
}
|
||||
case 0x0: // SCSP RAM 1 (master): 000000-0FFFFF
|
||||
*(UINT16 *) &ram1[a] = (d>>16);
|
||||
*(UINT16 *) &ram1[a+2] = (d&0xFFFF);
|
||||
break;
|
||||
|
||||
// SCSP RAM 2
|
||||
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||
{
|
||||
Write16(a,d>>16);
|
||||
Write16(a+2,d&0xFFFF);
|
||||
}
|
||||
|
||||
// SCSP (Master)
|
||||
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||
case 0x1: // SCSP registers (master): 100000-10FFFF
|
||||
SCSP_Master_w32(a,d);
|
||||
break;
|
||||
|
||||
// SCSP (Slave)
|
||||
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||
case 0x2: // SCSP RAM 2 (slave): 200000-2FFFFF
|
||||
*(UINT16 *) &ram2[a&0x0FFFFF] = (d>>16);
|
||||
*(UINT16 *) &ram2[(a+2)&0x0FFFFF] = (d&0xFFFF);
|
||||
break;
|
||||
|
||||
case 0x3: // SCSP registers (slave): 300000-30FFFF
|
||||
SCSP_Slave_w32(a,d);
|
||||
break;
|
||||
|
||||
// Unknown
|
||||
else
|
||||
default:
|
||||
printf("68K: Unknown write32 %06X=%08X\n", a, d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
SCSP 68K Callbacks
|
||||
|
||||
The SCSP emulator drives the 68K via callbacks.
|
||||
The SCSP emulator drives the 68K via callbacks. These have to live outside of
|
||||
the CSoundBoard object for now, unfortunately.
|
||||
******************************************************************************/
|
||||
|
||||
// Status of IRQ pins (IPL2-0) on 68K
|
||||
// TODO: can we get rid of this global variable altogether?
|
||||
static int irqLine = 0;
|
||||
|
||||
// Interrupt acknowledge callback (TODO: don't need this, default behavior in M68K.cpp is fine)
|
||||
// Interrupt acknowledge callback (TODO: don't need this, default behavior in M68K.cpp should be fine)
|
||||
int IRQAck(int irqLevel)
|
||||
{
|
||||
M68KSetIRQ(0);
|
||||
|
@ -334,41 +342,55 @@ int SCSP68KRunCallback(int numCycles)
|
|||
|
||||
|
||||
/******************************************************************************
|
||||
Sound Board Emulation
|
||||
Sound Board Interface
|
||||
******************************************************************************/
|
||||
|
||||
void CSoundBoard::WriteMIDIPort(UINT8 data)
|
||||
{
|
||||
SCSP_MidiIn(data);
|
||||
if (NULL != DSB) // DSB receives all commands as well
|
||||
DSB->SendCommand(data);
|
||||
}
|
||||
|
||||
void CSoundBoard::RunFrame(void)
|
||||
{
|
||||
#ifdef SUPERMODEL_SOUND
|
||||
// Run sound board first to generate SCSP audio
|
||||
M68KSetContext(&M68K);
|
||||
SCSP_Update();
|
||||
M68KGetContext(&M68K);
|
||||
|
||||
// Run DSB and mix with existing audio
|
||||
if (NULL != DSB)
|
||||
DSB->RunFrame(audioL, audioR);
|
||||
|
||||
// Output the audio buffers
|
||||
OutputAudio(44100/60, leftBuffer, rightBuffer);
|
||||
OutputAudio(44100/60, audioL, audioR);
|
||||
|
||||
#ifdef SUPERMODEL_LOG_AUDIO
|
||||
// Output to binary file
|
||||
INT16 s;
|
||||
for (int i = 0; i < 44100/60; i++)
|
||||
{
|
||||
s = ((UINT16)leftBuffer[i]>>8) | ((leftBuffer[i]&0xFF)<<8);
|
||||
s = audioL[i];
|
||||
fwrite(&s, sizeof(INT16), 1, soundFP); // left channel
|
||||
s = ((UINT16)rightBuffer[i]>>8) | ((rightBuffer[i]&0xFF)<<8);
|
||||
s = audioR[i];
|
||||
fwrite(&s, sizeof(INT16), 1, soundFP); // right channel
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSoundBoard::Reset(void)
|
||||
{
|
||||
// lets hope he does better... ->
|
||||
memcpy(ram1, soundROM, 16); // copy 68K vector table
|
||||
sbSampleBankLo = &sampleROM[0x200000]; // default banks
|
||||
sbSampleBankHi = &sampleROM[0x600000];
|
||||
sampleBankLo = &sampleROM[0x200000]; // default banks
|
||||
sampleBankHi = &sampleROM[0x600000];
|
||||
M68KSetContext(&M68K);
|
||||
M68KReset();
|
||||
M68KGetContext(&M68K);
|
||||
if (NULL != DSB)
|
||||
DSB->Reset();
|
||||
DebugLog("Sound Board Reset\n");
|
||||
}
|
||||
|
||||
|
@ -377,22 +399,28 @@ void CSoundBoard::Reset(void)
|
|||
Configuration, Initialization, and Shutdown
|
||||
******************************************************************************/
|
||||
|
||||
void CSoundBoard::AttachDSB(CDSB *DSBPtr)
|
||||
{
|
||||
DSB = DSBPtr;
|
||||
DebugLog("Sound Board connected to DSB\n");
|
||||
}
|
||||
|
||||
// Offsets of memory regions within sound board's pool
|
||||
#define OFFSET_RAM1 0 // 1 MB SCSP1 RAM
|
||||
#define OFFSET_RAM2 0x100000 // 1 MB SCSP2 RAM
|
||||
#define MEMORY_POOL_SIZE (0x100000+0x100000)
|
||||
#define OFFSET_AUDIO_LEFT 0x200000 // 1470 bytes (16 bits, 44.1 KHz, 1/60th second) left audio channel
|
||||
#define OFFSET_AUDIO_RIGHT 0x2005BE // 1470 bytes right audio channel
|
||||
#define MEMORY_POOL_SIZE (0x100000+0x100000+0x5BE+0x5BE)
|
||||
|
||||
BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ *ppcIRQObjectPtr, unsigned soundIRQBit)
|
||||
BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr)
|
||||
{
|
||||
float memSizeMB = (float)MEMORY_POOL_SIZE/(float)0x100000;
|
||||
|
||||
// Attach IRQ controller
|
||||
ppcIRQ = ppcIRQObjectPtr;
|
||||
ppcSoundIRQBit = soundIRQBit;
|
||||
|
||||
// Receive sound ROMs
|
||||
soundROM = soundROMPtr;
|
||||
sampleROM = sampleROMPtr;
|
||||
sampleBankLo = &sampleROM[0x200000];
|
||||
sampleBankHi = &sampleROM[0x600000];
|
||||
|
||||
// Allocate all memory for RAM
|
||||
memoryPool = new(std::nothrow) UINT8[MEMORY_POOL_SIZE];
|
||||
|
@ -403,37 +431,25 @@ BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ
|
|||
// Set up memory pointers
|
||||
ram1 = &memoryPool[OFFSET_RAM1];
|
||||
ram2 = &memoryPool[OFFSET_RAM2];
|
||||
|
||||
// Make global copies of memory pointers for 68K access handlers
|
||||
sbRAM1 = ram1;
|
||||
sbRAM2 = ram2;
|
||||
sbSoundROM = soundROM;
|
||||
sbSampleROM = sampleROM;
|
||||
sbSampleBankLo = &sampleROM[0x200000];
|
||||
sbSampleBankHi = &sampleROM[0x600000];
|
||||
audioL = (INT16 *) &memoryPool[OFFSET_AUDIO_LEFT];
|
||||
audioR = (INT16 *) &memoryPool[OFFSET_AUDIO_RIGHT];
|
||||
|
||||
// Initialize 68K core
|
||||
M68KSetContext(&M68K);
|
||||
M68KInit();
|
||||
M68KAttachBus(this);
|
||||
M68KSetIRQCallback(IRQAck);
|
||||
M68KSetFetch8Callback(Read8);
|
||||
M68KSetFetch16Callback(Read16);
|
||||
M68KSetFetch32Callback(Read32);
|
||||
M68KSetRead8Callback(Read8);
|
||||
M68KSetRead16Callback(Read16);
|
||||
M68KSetRead32Callback(Read32);
|
||||
M68KSetWrite8Callback(Write8);
|
||||
M68KSetWrite16Callback(Write16);
|
||||
M68KSetWrite32Callback(Write32);
|
||||
M68KGetContext(&M68K);
|
||||
|
||||
// Initialize SCSPs
|
||||
SCSP_SetBuffers(leftBuffer, rightBuffer, 44100/60);
|
||||
SCSP_SetCB(SCSP68KRunCallback, SCSP68KIRQCallback, ppcIRQ, ppcSoundIRQBit);
|
||||
SCSP_SetBuffers(audioL, audioR, 44100/60);
|
||||
SCSP_SetCB(SCSP68KRunCallback, SCSP68KIRQCallback);
|
||||
SCSP_Init(2);
|
||||
SCSP_SetRAM(0, ram1);
|
||||
SCSP_SetRAM(1, ram2);
|
||||
|
||||
// Binary logging
|
||||
#ifdef SUPERMODEL_SOUND
|
||||
#ifdef SUPERMODEL_LOG_AUDIO
|
||||
soundFP = fopen("sound.bin","wb"); // delete existing file
|
||||
fclose(soundFP);
|
||||
soundFP = fopen("sound.bin","ab"); // append mode
|
||||
|
@ -444,9 +460,14 @@ BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ
|
|||
|
||||
CSoundBoard::CSoundBoard(void)
|
||||
{
|
||||
DSB = NULL;
|
||||
memoryPool = NULL;
|
||||
ram1 = NULL;
|
||||
ram2 = NULL;
|
||||
audioL = NULL;
|
||||
audioR = NULL;
|
||||
soundROM = NULL;
|
||||
sampleROM = NULL;
|
||||
|
||||
DebugLog("Built Sound Board\n");
|
||||
}
|
||||
|
@ -466,35 +487,15 @@ static void Reverse16(UINT8 *buf, unsigned size)
|
|||
|
||||
CSoundBoard::~CSoundBoard(void)
|
||||
{
|
||||
#ifdef SUPERMODEL_SOUND
|
||||
#ifdef SUPERMODEL_LOG_AUDIO
|
||||
// close binary log file
|
||||
fclose(soundFP);
|
||||
//#if 0
|
||||
FILE *fp;
|
||||
|
||||
Reverse16(ram1, 0x100000);
|
||||
Reverse16(ram2, 0x100000);
|
||||
fp = fopen("scspRAM1", "wb");
|
||||
if (NULL != fp)
|
||||
{
|
||||
fwrite(ram1, sizeof(UINT8), 0x100000, fp);
|
||||
fclose(fp);
|
||||
printf("dumped %s\n", "scspRAM1");
|
||||
|
||||
}
|
||||
fp = fopen("scspRAM2", "wb");
|
||||
if (NULL != fp)
|
||||
{
|
||||
fwrite(ram2, sizeof(UINT8), 0x100000, fp);
|
||||
fclose(fp);
|
||||
printf("dumped %s\n", "scspRAM2");
|
||||
|
||||
}
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
SCSP_Deinit();
|
||||
|
||||
DSB = NULL;
|
||||
|
||||
if (memoryPool != NULL)
|
||||
{
|
||||
delete [] memoryPool;
|
||||
|
@ -502,5 +503,10 @@ CSoundBoard::~CSoundBoard(void)
|
|||
}
|
||||
ram1 = NULL;
|
||||
ram2 = NULL;
|
||||
audioL = NULL;
|
||||
audioR = NULL;
|
||||
soundROM = NULL;
|
||||
sampleROM = NULL;
|
||||
|
||||
DebugLog("Destroyed Sound Board\n");
|
||||
}
|
||||
|
|
|
@ -28,15 +28,52 @@
|
|||
#ifndef INCLUDED_SOUNDBOARD_H
|
||||
#define INCLUDED_SOUNDBOARD_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "CPU/Bus.h"
|
||||
#include "Model3/DSB.h"
|
||||
|
||||
/*
|
||||
* CSoundBoard:
|
||||
*
|
||||
* Model 3 sound board (68K CPU + 2 x SCSP).
|
||||
*/
|
||||
class CSoundBoard
|
||||
class CSoundBoard: public CBus
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Read8(addr):
|
||||
* Read16(addr):
|
||||
* Read32(addr):
|
||||
* Read64(addr):
|
||||
*
|
||||
* Read a byte, 16-bit word, or 32-bit long word from the 68K address
|
||||
* space.
|
||||
*
|
||||
* Parameters:
|
||||
* addr Address to read.
|
||||
*
|
||||
* Returns:
|
||||
* Data at the address.
|
||||
*/
|
||||
UINT8 Read8(UINT32 addr);
|
||||
UINT16 Read16(UINT32 addr);
|
||||
UINT32 Read32(UINT32 addr);
|
||||
|
||||
/*
|
||||
* Write8(addr, data):
|
||||
* Write16(addr, data):
|
||||
* Write32(addr, data):
|
||||
*
|
||||
* Write a byte, word, or long word to the 68K address space.
|
||||
*
|
||||
* Parameters:
|
||||
* addr Address to write.
|
||||
* data Data to write.
|
||||
*/
|
||||
void Write8(UINT32 addr, UINT8 data);
|
||||
void Write16(UINT32 addr, UINT16 data);
|
||||
void Write32(UINT32 addr, UINT32 data);
|
||||
|
||||
/*
|
||||
* WriteMIDIPort(data):
|
||||
*
|
||||
|
@ -61,6 +98,18 @@ public:
|
|||
*/
|
||||
void Reset(void);
|
||||
|
||||
/*
|
||||
* AttachDSB(CDSB *DSBPtr):
|
||||
*
|
||||
* Connects a Digital Sound Board. The sound board passes MIDI commands,
|
||||
* resets the board, and runs it each frame to generate audio. If there is
|
||||
* no DSB, this function does not need to be called.
|
||||
*
|
||||
* Parameters:
|
||||
* DSBPtr Pointer to DSB object.
|
||||
*/
|
||||
void AttachDSB(CDSB *DSBPtr);
|
||||
|
||||
/*
|
||||
* Init(soundROMPtr, sampleROMPtr):
|
||||
*
|
||||
|
@ -69,14 +118,12 @@ public:
|
|||
* Parameters:
|
||||
* soundROMPtr Pointer to sound ROM (68K program).
|
||||
* sampleROMPtr Pointer to sample ROM.
|
||||
* ppcIRQObjectPtr Pointer to PowerPC-side IRQ object.
|
||||
* soundIRQBit IRQ bit mask to use for sound board PowerPC IRQs.
|
||||
*
|
||||
* Returns:
|
||||
* OKAY if successful, FAIL if unable to allocate memory. Prints own
|
||||
* error messages.
|
||||
*/
|
||||
BOOL Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ *ppcIRQObjectPtr, unsigned soundIRQBit);
|
||||
BOOL Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr);
|
||||
|
||||
/*
|
||||
* CSoundBoard(void):
|
||||
|
@ -88,15 +135,22 @@ public:
|
|||
~CSoundBoard(void);
|
||||
|
||||
private:
|
||||
// PowerPC IRQ controller
|
||||
CIRQ *ppcIRQ;
|
||||
unsigned ppcSoundIRQBit;
|
||||
// Digital Sound Board
|
||||
CDSB *DSB;
|
||||
|
||||
// 68K context
|
||||
M68KCtx M68K;
|
||||
|
||||
// Sound board memory
|
||||
const UINT8 *soundROM; // 68K program ROM (passed in from parent object)
|
||||
const UINT8 *sampleROM; // 68K sample ROM (passed in from parent object)
|
||||
const UINT8 *sampleBankLo; // sample ROM bank switching
|
||||
const UINT8 *sampleBankHi;
|
||||
UINT8 *memoryPool; // single allocated region for all sound board RAM
|
||||
UINT8 *ram1, *ram2; // SCSP1 and SCSP2 RAM
|
||||
|
||||
// Audio
|
||||
INT16 *audioL, *audioR; // left and right audio channels (1/60th second, 44.1 KHz)
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -534,27 +534,6 @@ int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, BOOL
|
|||
// Toggle frame limiting
|
||||
noThrottle = !noThrottle;
|
||||
printf("Frame limiting: %s\n", noThrottle?"Off":"On");
|
||||
/*
|
||||
SCSP_MidiIn(0xA0);
|
||||
SCSP_MidiIn(0x00);
|
||||
SCSP_MidiIn(0x01); // stop?
|
||||
|
||||
SCSP_MidiIn(0xA0);
|
||||
SCSP_MidiIn(0x11);
|
||||
SCSP_MidiIn(0x2E);
|
||||
|
||||
SCSP_MidiIn(0xA1);
|
||||
SCSP_MidiIn(0x70);
|
||||
SCSP_MidiIn(0x03);
|
||||
|
||||
SCSP_MidiIn(0xAF);SCSP_MidiIn(0x10);SCSP_MidiIn(0x01);
|
||||
*/
|
||||
SCSP_MidiIn(0xAF);SCSP_MidiIn(0x10);SCSP_MidiIn(0x00);
|
||||
//static int snd=0xF;
|
||||
//SCSP_MidiIn(0xA0);SCSP_MidiIn(0x11);SCSP_MidiIn(snd++);
|
||||
//Sound codes:
|
||||
// A0 11 xx (0F=time extend, 11=jumbo left right)
|
||||
// AF 10 xx (music -- 01 seems to work)
|
||||
}
|
||||
#ifdef SUPERMODEL_DEBUGGER
|
||||
else if (Inputs->uiEnterDebugger->Pressed())
|
||||
|
|
|
@ -68,7 +68,7 @@ static BOOL FindROMByCRCInGame(const struct GameInfo **gamePtr, int *romIdxPtr,
|
|||
{
|
||||
if (crc == Game->ROM[j].crc) // found it!
|
||||
{
|
||||
*gamePtr = Game;
|
||||
*gamePtr = Game; // I know this seems redundant, but we do it here because FindROMByCRC() uses this function
|
||||
*romIdxPtr = j;
|
||||
return OKAY;
|
||||
}
|
||||
|
@ -97,6 +97,23 @@ static BOOL FindROMByCRC(const struct GameInfo **gamePtr, int *romIdxPtr, const
|
|||
return FAIL;
|
||||
}
|
||||
|
||||
// Returns TRUE if this ROM appears only a single time in the entire game list (ie., it is not shared between games)
|
||||
static BOOL ROMIsUnique(const struct GameInfo *GameList, UINT32 crc)
|
||||
{
|
||||
int timesFound = 0;
|
||||
|
||||
for (int i = 0; GameList[i].title != NULL; i++)
|
||||
{
|
||||
for (int j = 0; GameList[i].ROM[j].region != NULL; j++)
|
||||
{
|
||||
if (crc == GameList[i].ROM[j].crc)
|
||||
timesFound++;
|
||||
}
|
||||
}
|
||||
|
||||
return (timesFound == 1) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static void ByteSwap(UINT8 *buf, unsigned size)
|
||||
{
|
||||
unsigned i;
|
||||
|
@ -189,7 +206,8 @@ const struct GameInfo * LoadROMSetFromZIPFile(const struct ROMMap *Map, const st
|
|||
{
|
||||
unzFile zf;
|
||||
unz_file_info fileInfo;
|
||||
const struct GameInfo *Game = NULL, *CurGame;
|
||||
const struct GameInfo *Game = NULL;
|
||||
const struct GameInfo *CurGame; // this is the game to which the last ROM found is thought to belong
|
||||
int romIdx; // index within Game->ROM
|
||||
unsigned romsFound[sizeof(Game->ROM)/sizeof(struct ROMInfo)], numROMs;
|
||||
int err;
|
||||
|
@ -205,8 +223,7 @@ const struct GameInfo * LoadROMSetFromZIPFile(const struct ROMMap *Map, const st
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Check ROMs: scan ZIP file for first known ROM and check to ensure all ROMs are present
|
||||
memset(romsFound, 0, sizeof(romsFound));
|
||||
// First pass: scan every file and determine the game
|
||||
err = unzGoToFirstFile(zf);
|
||||
if (UNZ_OK != err)
|
||||
{
|
||||
|
@ -221,34 +238,54 @@ const struct GameInfo * LoadROMSetFromZIPFile(const struct ROMMap *Map, const st
|
|||
continue;
|
||||
if (OKAY != FindROMByCRC(&CurGame, &romIdx, GameList, Game, fileInfo.crc))
|
||||
continue;
|
||||
|
||||
// If the ROM appears in multiple games, do not use it to identify the game!
|
||||
if (!ROMIsUnique(GameList, fileInfo.crc))
|
||||
continue;
|
||||
|
||||
// We have a unique ROM used by a single game; identify that game
|
||||
if (Game == NULL) // this is the first game we've identified within the ZIP
|
||||
{
|
||||
Game = CurGame;
|
||||
DebugLog("%ROM set identified: %s (%s), %s\n", Game->id, Game->title, zipFile);
|
||||
DebugLog("ROM set identified: %s (%s), %s\n", Game->id, Game->title, zipFile);
|
||||
}
|
||||
else
|
||||
else // we've already identified a game
|
||||
{
|
||||
if (CurGame != Game)
|
||||
if (CurGame != Game) // another game?
|
||||
{
|
||||
DebugLog("%s also contains: %s (%s)\n", zipFile, CurGame->id, CurGame->title);
|
||||
if (multipleGameError == FALSE) // only warn about this once
|
||||
{
|
||||
printf("ROM=%s\n", CurGame->ROM[romIdx].fileName);
|
||||
ErrorLog("Multiple games were found in %s; loading \"%s\".", zipFile, Game->title);
|
||||
multipleGameError = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have found a ROM for the correct game, mark it
|
||||
if (Game == CurGame)
|
||||
romsFound[romIdx] = 1;
|
||||
}
|
||||
|
||||
if (Game == NULL)
|
||||
// Second pass: check if all ROM files for the identified game are present
|
||||
err = unzGoToFirstFile(zf);
|
||||
if (UNZ_OK != err)
|
||||
{
|
||||
ErrorLog("%s contains no supported games.", zipFile);
|
||||
ErrorLog("Unable to read the contents of %s (code %X)", zipFile, err);
|
||||
return NULL;
|
||||
}
|
||||
memset(romsFound, 0, sizeof(romsFound)); // here, romsFound[] indicates which ROMs were found in the ZIP file for the game
|
||||
for (; err != UNZ_END_OF_LIST_OF_FILE; err = unzGoToNextFile(zf))
|
||||
{
|
||||
// Identify the file we're looking at
|
||||
err = unzGetCurrentFileInfo(zf, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
|
||||
if (err != UNZ_OK)
|
||||
continue;
|
||||
|
||||
// If it's not part of the game we've identified, skip it
|
||||
if (OKAY != FindROMByCRCInGame(&CurGame, &romIdx, Game, fileInfo.crc))
|
||||
continue;
|
||||
|
||||
// If we have found a ROM for the correct game, mark its corresponding indicator
|
||||
romsFound[romIdx] = 1;
|
||||
}
|
||||
|
||||
// Compute how many ROM files this game has
|
||||
for (numROMs = 0; Game->ROM[numROMs].region != NULL; numROMs++)
|
||||
|
@ -259,16 +296,15 @@ const struct GameInfo * LoadROMSetFromZIPFile(const struct ROMMap *Map, const st
|
|||
for (i = 0; i < numROMs; i++)
|
||||
{
|
||||
if (romsFound[i] == 0)
|
||||
err |= ErrorLog("%s (CRC=%08X) is missing from %s.", Game->ROM[i].file, Game->ROM[i].crc, zipFile);
|
||||
err |= ErrorLog("%s (CRC=%08X) is missing from %s.", Game->ROM[i].fileName, Game->ROM[i].crc, zipFile);
|
||||
}
|
||||
if (err != OKAY)
|
||||
{
|
||||
unzClose(zf);
|
||||
return NULL;
|
||||
//return FAIL;
|
||||
}
|
||||
|
||||
// Allocate memory for the largest ROM to load
|
||||
// Allocate a scratch buffer big enough to hold the biggest ROM
|
||||
maxSize = 0;
|
||||
for (i = 0; i < numROMs; i++)
|
||||
{
|
||||
|
@ -283,8 +319,8 @@ const struct GameInfo * LoadROMSetFromZIPFile(const struct ROMMap *Map, const st
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Load ROMs
|
||||
memset(romsFound, 0, sizeof(romsFound));
|
||||
// Third pass: load the ROMs
|
||||
memset(romsFound, 0, sizeof(romsFound)); // now, romsFound[] is used to indicate whether we successfully loaded the ROM
|
||||
err = unzGoToFirstFile(zf);
|
||||
if (UNZ_OK != err)
|
||||
{
|
||||
|
@ -297,14 +333,15 @@ const struct GameInfo * LoadROMSetFromZIPFile(const struct ROMMap *Map, const st
|
|||
err = unzGetCurrentFileInfo(zf, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
|
||||
if (err != UNZ_OK)
|
||||
continue;
|
||||
if (OKAY != FindROMByCRC(&CurGame, &romIdx, GameList, Game, fileInfo.crc))
|
||||
|
||||
// If this ROM is not part of the game we're loading, skip it
|
||||
if (OKAY != FindROMByCRCInGame(&CurGame, &romIdx, Game, fileInfo.crc))
|
||||
continue;
|
||||
if (CurGame == Game) // if ROM belongs to correct game
|
||||
{
|
||||
|
||||
// Load the ROM and mark that we did so successfully
|
||||
if (OKAY == LoadROM(buf, maxSize, Map, &Game->ROM[romIdx], zf, zipFile, loadAll))
|
||||
romsFound[romIdx] = 1; // success! mark as loaded
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure all ROMs were loaded
|
||||
if (loadAll)
|
||||
|
@ -315,7 +352,7 @@ const struct GameInfo * LoadROMSetFromZIPFile(const struct ROMMap *Map, const st
|
|||
if (romsFound[i])
|
||||
++n;
|
||||
else
|
||||
ErrorLog("Failed to load %s (CRC=%08X) from %s.", Game->ROM[i].file, Game->ROM[i].crc, zipFile);
|
||||
ErrorLog("Failed to load %s (CRC=%08X) from %s.", Game->ROM[i].fileName, Game->ROM[i].crc, zipFile);
|
||||
}
|
||||
if (n < numROMs)
|
||||
err = FAIL;
|
||||
|
|
|
@ -44,7 +44,7 @@ struct ROMInfo
|
|||
const char *region; // ROM region identifier (used as a key to search ROMMap)
|
||||
|
||||
// Information used to identify files
|
||||
const char *file; // file name
|
||||
const char *fileName; // file name
|
||||
UINT32 crc; // CRC-32 checksum (same as zip format)
|
||||
unsigned fileSize; // file size in bytes (must be the same as all other ROMs with same region ID)
|
||||
|
||||
|
|
114
Src/Sound/MPEG/MPEG.h
Normal file
114
Src/Sound/MPEG/MPEG.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011 Bart Trzynadlowski
|
||||
**
|
||||
** 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/>.
|
||||
**/
|
||||
|
||||
/*
|
||||
* MPEG.cpp
|
||||
*
|
||||
* Header file for MPEG decoder based on AMP by Tomislav Uzalec, modified to
|
||||
* play from memory buffers by R. Belmont for his music player, M1.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_MPEG_H
|
||||
#define INCLUDED_MPEG_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Functions
|
||||
|
||||
The MPEG decoder is not thread-safe and must not be used by multiple sources.
|
||||
These functions are located in audio.cpp and getbits.cpp.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* MPEG_GetProgress(void):
|
||||
*
|
||||
* Returns:
|
||||
* The current byte offset within the MPEG stream.
|
||||
*/
|
||||
extern int MPEG_GetProgress(void);
|
||||
|
||||
/*
|
||||
* MPEG_SetLoop(loop, loopend):
|
||||
*
|
||||
* Sets the start and end offsets for looped playback.
|
||||
*
|
||||
* Parameters:
|
||||
* loop Start address.
|
||||
* loopend End address.
|
||||
*/
|
||||
extern void MPEG_SetLoop(const char *loop, int loopend);
|
||||
|
||||
/*
|
||||
* MPEG_Decode(outputs, length):
|
||||
*
|
||||
* Decodes the requested number of samples from the currently playing MPEG
|
||||
* stream and updates the internal play position. If an MPEG is not playing,
|
||||
* writes silence (zeros).
|
||||
*
|
||||
* Parameters:
|
||||
* outputs A two-element array of pointers to equal-length signed 16-
|
||||
* bit sample buffers. The first is the left channel and the
|
||||
* second is the right channel. Audio is decoded to these.
|
||||
* length Number of samples to decode.
|
||||
*/
|
||||
extern void MPEG_Decode(INT16 **outputs, int length);
|
||||
|
||||
/*
|
||||
* MPEG_PlayMemory(sa, length):
|
||||
*
|
||||
* Specifies the memory buffer to decode from. This initializes the playback
|
||||
* process and will decode the first MPEG frame internally.
|
||||
*
|
||||
* Parameters:
|
||||
* sa Start address of MPEG stream.
|
||||
* length Length in bytes.
|
||||
*/
|
||||
extern void MPEG_PlayMemory(const char *sa, int length);
|
||||
|
||||
/*
|
||||
* MPEG_StopPlaying(void):
|
||||
*
|
||||
* Stop playing the current MPEG stream. The decoder will return silence.
|
||||
*/
|
||||
extern void MPEG_StopPlaying(void);
|
||||
|
||||
/*
|
||||
* MPEG_Init(void):
|
||||
*
|
||||
* Initializes the MPEG decoder. This should be called once per program
|
||||
* session. Allocates an internal buffer for MPEG decoding.
|
||||
*
|
||||
* Returns:
|
||||
* OKAY if successful, FAIL if internal buffer could not be allocated.
|
||||
*/
|
||||
extern BOOL MPEG_Init(void);
|
||||
|
||||
/*
|
||||
* MPEG_Shutdown(void):
|
||||
*
|
||||
* Shuts down the MPEG decoder. Releases internal memory.
|
||||
*/
|
||||
extern void MPEG_Shutdown(void);
|
||||
|
||||
|
||||
#endif // INCLUDED_MPEG_H
|
63
Src/Sound/MPEG/amp.h
Normal file
63
Src/Sound/MPEG/amp.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* these should not be touched
|
||||
*/
|
||||
#define SYNCWORD 0xfff
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/* version
|
||||
*/
|
||||
#define MAJOR 0
|
||||
#define MINOR 7
|
||||
#define PATCH 6
|
||||
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define MAX3(a,b,c) ((a) > (b) ? MAX(a, c) : MAX(b, c))
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
|
||||
/* Debugging flags */
|
||||
|
||||
struct debugFlags_t {
|
||||
int audio,args,buffer,buffer2,misc,misc2;
|
||||
};
|
||||
|
||||
struct debugLookup_t {
|
||||
char *name; int *var;
|
||||
};
|
||||
|
||||
extern struct debugFlags_t debugFlags;
|
||||
|
||||
/* This is only here to keep all the debug stuff together */
|
||||
#ifdef AMP_UTIL
|
||||
struct debugLookup_t debugLookup[] = {
|
||||
{"audio", &debugFlags.audio},
|
||||
{"args", &debugFlags.args},
|
||||
{"buffer", &debugFlags.buffer},
|
||||
{"buffer2", &debugFlags.buffer2},
|
||||
{"misc", &debugFlags.misc},
|
||||
{"misc2", &debugFlags.misc2},
|
||||
{0,0}
|
||||
};
|
||||
#endif /* AMP_UTIL */
|
||||
|
||||
extern struct debugLookup_t debugLookup[];
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DB(type,cmd) if (debugFlags.type) { cmd ; }
|
||||
#else
|
||||
#define DB(type,cmd)
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "proto.h"
|
||||
|
||||
|
||||
extern int AUDIO_BUFFER_SIZE;
|
396
Src/Sound/MPEG/audio.cpp
Normal file
396
Src/Sound/MPEG/audio.cpp
Normal file
|
@ -0,0 +1,396 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* audio.c main amp source file
|
||||
*
|
||||
* Created by: tomislav uzelac Apr 1996
|
||||
* Karl Anders Oygard added the IRIX code, 10 Mar 1997.
|
||||
* Ilkka Karvinen fixed /dev/dsp initialization, 11 Mar 1997.
|
||||
* Lutz Vieweg added the HP/UX code, 14 Mar 1997.
|
||||
* Dan Nelson added FreeBSD modifications, 23 Mar 1997.
|
||||
* Andrew Richards complete reorganisation, new features, 25 Mar 1997
|
||||
* Edouard Lafargue added sajber jukebox support, 12 May 1997
|
||||
*/
|
||||
|
||||
|
||||
#include "amp.h"
|
||||
|
||||
#define AUDIO
|
||||
#include "audio.h"
|
||||
#include "formats.h"
|
||||
#include "getbits.h"
|
||||
#include "huffman.h"
|
||||
#include "layer2.h"
|
||||
#include "layer3.h"
|
||||
#include "position.h"
|
||||
#include "rtbuf.h"
|
||||
#include "transform.h"
|
||||
|
||||
//#ifndef __BEOS__
|
||||
//typedef int bool;
|
||||
//#endif
|
||||
|
||||
#include <new>
|
||||
#include <cstring>
|
||||
#include "Types.h"
|
||||
#include "MPEG.h"
|
||||
|
||||
//#include "m1snd.h"
|
||||
//#include "oss.h"
|
||||
//#include "mpeg.h"
|
||||
|
||||
#define BUF_SIZE (1152 * sizeof(short) * 2)
|
||||
|
||||
void calculate_t43(void);
|
||||
|
||||
static int decoder_init = 0;
|
||||
static int cnt = 0;
|
||||
static int stream = -1;
|
||||
static char *buf0;
|
||||
static int playing = 0;
|
||||
static int outpos = 0;
|
||||
static int mpeg_eof = 0;
|
||||
static char *dst, *readbuf;
|
||||
static struct AUDIO_HEADER m1hdr;;
|
||||
|
||||
void statusDisplay(struct AUDIO_HEADER *header, int frameNo)
|
||||
{
|
||||
int minutes,seconds;
|
||||
|
||||
if ((A_SHOW_CNT || A_SHOW_TIME) && !(frameNo%10))
|
||||
msg("\r");
|
||||
if (A_SHOW_CNT && !(frameNo%10) ) {
|
||||
msg("{ %d } ",frameNo);
|
||||
}
|
||||
if (A_SHOW_TIME && !(frameNo%10)) {
|
||||
seconds=frameNo*1152/t_sampling_frequency[header->ID][header->sampling_frequency];
|
||||
minutes=seconds/60;
|
||||
seconds=seconds % 60;
|
||||
msg("[%d:%02d]",minutes,seconds);
|
||||
}
|
||||
if (A_SHOW_CNT || A_SHOW_TIME)
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
// one mpeg frame is 576 samples.
|
||||
int decodeMPEGOneFrame(struct AUDIO_HEADER *header)
|
||||
{
|
||||
int snd_eof = 0, g;
|
||||
|
||||
if ((g=gethdr(header))!=0) {
|
||||
report_header_error(g);
|
||||
snd_eof=1;
|
||||
return snd_eof;
|
||||
}
|
||||
|
||||
if (header->protection_bit==0) getcrc();
|
||||
|
||||
statusDisplay(header,0);
|
||||
|
||||
if (header->layer==1) {
|
||||
if (layer3_frame(header,cnt)) {
|
||||
warn(" error. blip.\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (header->layer==2)
|
||||
if (layer2_frame(header,cnt)) {
|
||||
warn(" error. blip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cnt++;
|
||||
|
||||
return snd_eof;
|
||||
}
|
||||
|
||||
int decodeMPEG(void)
|
||||
{
|
||||
struct AUDIO_HEADER header;
|
||||
int g,snd_eof=0;
|
||||
|
||||
initialise_globals();
|
||||
|
||||
cnt = 0;
|
||||
|
||||
if ((g=gethdr(&header))!=0) {
|
||||
report_header_error(g);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (header.protection_bit==0) getcrc();
|
||||
|
||||
printf("%d Hz, layer %d\n", t_sampling_frequency[header.ID][header.sampling_frequency], header.layer);
|
||||
|
||||
if (setup_audio(&header)!=0) {
|
||||
warn("Cannot set up audio. Exiting\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (header.layer==1) {
|
||||
if (layer3_frame(&header,cnt)) {
|
||||
warn(" error. blip.\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (header.layer==2)
|
||||
if (layer2_frame(&header,cnt)) {
|
||||
warn(" error. blip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* decoder loop **********************************
|
||||
*/
|
||||
snd_eof=0;
|
||||
while (!snd_eof) {
|
||||
while (!snd_eof && ready_audio()) {
|
||||
snd_eof = decodeMPEGOneFrame(&header);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* call this once at the beginning
|
||||
*/
|
||||
void initialise_decoder(void)
|
||||
{
|
||||
premultiply();
|
||||
imdct_init();
|
||||
calculate_t43();
|
||||
}
|
||||
|
||||
/* call this before each file is played
|
||||
*/
|
||||
void initialise_globals(void)
|
||||
{
|
||||
append=data=nch=0;
|
||||
f_bdirty=TRUE;
|
||||
bclean_bytes=0;
|
||||
|
||||
memset(s,0,sizeof s);
|
||||
memset(res,0,sizeof res);
|
||||
}
|
||||
|
||||
void report_header_error(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case GETHDR_ERR: die("error reading mpeg bitstream. exiting.\n");
|
||||
break;
|
||||
case GETHDR_NS : warn("this is a file in MPEG 2.5 format, which is not defined\n");
|
||||
warn("by ISO/MPEG. It is \"a special Fraunhofer format\".\n");
|
||||
warn("amp does not support this format. sorry.\n");
|
||||
break;
|
||||
case GETHDR_FL1: warn("ISO/MPEG layer 1 is not supported by amp.\n");
|
||||
break;
|
||||
case GETHDR_FF : warn("free format bitstreams are not supported. sorry.\n");
|
||||
break;
|
||||
case GETHDR_SYN: warn("oops, we're out of sync.\n");
|
||||
break;
|
||||
case GETHDR_EOF:
|
||||
default: ; /* some stupid compilers need the semicolon */
|
||||
}
|
||||
}
|
||||
|
||||
int setup_audio(struct AUDIO_HEADER *header)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void close_audio(void)
|
||||
{
|
||||
}
|
||||
|
||||
int ready_audio(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// callback: called by the engine to output a frame of audio
|
||||
void printout(void)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (nch==2)
|
||||
{
|
||||
j=32 * 18 * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
j=32 * 18;
|
||||
}
|
||||
|
||||
// printf("printout: %x, %d\n", (unsigned int), j*2);
|
||||
memcpy(dst, sample_buffer, j*2);
|
||||
|
||||
dst += j*2;
|
||||
outpos += j/2;
|
||||
}
|
||||
|
||||
void MPEG_Decode(INT16 **outputs, int length)
|
||||
{
|
||||
int i, remaining, bias;
|
||||
INT16 *get;
|
||||
|
||||
remaining = length;
|
||||
|
||||
// printf("%d: %x %x\n", length, (unsigned int)outputs[0], (unsigned int)outputs[1]);
|
||||
|
||||
if (!playing)
|
||||
{
|
||||
memset(&outputs[0][0], 0, length * sizeof(INT16));
|
||||
memset(&outputs[1][0], 0, length * sizeof(INT16));
|
||||
return;
|
||||
}
|
||||
|
||||
bias = 0;
|
||||
|
||||
// will we need more data from the decoder?
|
||||
if (outpos < length)
|
||||
{
|
||||
// if there's anything left in the current buffer, drain it first
|
||||
if (outpos != 0)
|
||||
{
|
||||
get = (INT16 *)readbuf;
|
||||
|
||||
for (i = 0; i < outpos; i++)
|
||||
{
|
||||
outputs[1][i] = *get++;
|
||||
outputs[0][i] = *get++;
|
||||
}
|
||||
|
||||
remaining -= outpos;
|
||||
bias = outpos;
|
||||
readbuf += (outpos * 4);
|
||||
}
|
||||
|
||||
outpos = 0;
|
||||
dst = buf0;
|
||||
while ((outpos < remaining) && (playing))
|
||||
{
|
||||
mpeg_eof = decodeMPEGOneFrame(&m1hdr);
|
||||
if (mpeg_eof)
|
||||
{
|
||||
MPEG_StopPlaying();
|
||||
}
|
||||
}
|
||||
|
||||
// reset read pointer
|
||||
readbuf = buf0;
|
||||
}
|
||||
|
||||
get = (INT16 *)readbuf;
|
||||
|
||||
for (i = 0; i < remaining; i++)
|
||||
{
|
||||
outputs[1][i+bias] = *get++;
|
||||
outputs[0][i+bias] = *get++;
|
||||
}
|
||||
|
||||
outpos -= remaining;
|
||||
readbuf += (remaining * 4);
|
||||
}
|
||||
|
||||
void MPEG_PlayFile(char *filename)
|
||||
{
|
||||
memset(buf0, 0, BUF_SIZE);
|
||||
|
||||
in_file = fopen(filename, "rb");
|
||||
|
||||
initialise_globals();
|
||||
|
||||
cnt = 0;
|
||||
mpeg_eof = 0;
|
||||
outpos = 0;
|
||||
dst = buf0;
|
||||
readbuf = buf0;
|
||||
|
||||
gethdr(&m1hdr);
|
||||
if (m1hdr.protection_bit == 0) getcrc();
|
||||
|
||||
// printf("%d Hz, layer %d\n", t_sampling_frequency[m1hdr.ID][m1hdr.sampling_frequency], m1hdr.layer);
|
||||
|
||||
// stream_set_srate(stream, t_sampling_frequency[m1hdr.ID][m1hdr.sampling_frequency]);
|
||||
|
||||
// prime the stream
|
||||
if (m1hdr.layer == 1)
|
||||
{
|
||||
layer3_frame(&m1hdr, cnt);
|
||||
}
|
||||
else if (m1hdr.layer == 2)
|
||||
{
|
||||
layer2_frame(&m1hdr, cnt);
|
||||
}
|
||||
|
||||
playing = 1;
|
||||
}
|
||||
|
||||
extern void m1setfile(const char *mstart, int mend);
|
||||
void MPEG_PlayMemory(const char *sa, int length)
|
||||
{
|
||||
memset(buf0, 0, BUF_SIZE);
|
||||
|
||||
m1setfile(sa, length);
|
||||
|
||||
initialise_globals();
|
||||
|
||||
cnt = 0;
|
||||
mpeg_eof = 0;
|
||||
outpos = 0;
|
||||
dst = buf0;
|
||||
readbuf = buf0;
|
||||
|
||||
gethdr(&m1hdr);
|
||||
if (m1hdr.protection_bit == 0) getcrc();
|
||||
|
||||
// printf("%d Hz, layer %d\n", t_sampling_frequency[m1hdr.ID][m1hdr.sampling_frequency], m1hdr.layer);
|
||||
|
||||
// stream_set_srate(stream, t_sampling_frequency[m1hdr.ID][m1hdr.sampling_frequency]);
|
||||
|
||||
// prime the stream
|
||||
if (m1hdr.layer == 1)
|
||||
{
|
||||
layer3_frame(&m1hdr, cnt);
|
||||
}
|
||||
else if (m1hdr.layer == 2)
|
||||
{
|
||||
layer2_frame(&m1hdr, cnt);
|
||||
}
|
||||
|
||||
in_file = NULL;
|
||||
|
||||
playing = 1;
|
||||
}
|
||||
|
||||
void MPEG_StopPlaying(void)
|
||||
{
|
||||
if (playing)
|
||||
{
|
||||
playing = 0;
|
||||
if (in_file)
|
||||
fclose(in_file);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL MPEG_Init(void)
|
||||
{
|
||||
if (!decoder_init)
|
||||
{
|
||||
initialise_decoder(); /* initialise decoder */
|
||||
decoder_init = 1;
|
||||
buf0 = new(std::nothrow) char[BUF_SIZE];
|
||||
if (NULL == buf0)
|
||||
return FAIL;
|
||||
memset(buf0, 0, BUF_SIZE);
|
||||
playing = 0;
|
||||
}
|
||||
|
||||
return OKAY;
|
||||
}
|
||||
|
||||
void MPEG_Shutdown( void )
|
||||
{
|
||||
decoder_init = 0;
|
||||
if (buf0 != NULL)
|
||||
delete [] buf0;
|
||||
buf0 = NULL;
|
||||
}
|
||||
|
180
Src/Sound/MPEG/audio.h
Normal file
180
Src/Sound/MPEG/audio.h
Normal file
|
@ -0,0 +1,180 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* audio.h some global variables
|
||||
*
|
||||
* Created by: tomislav uzelac Mar/Apr, Jul 96
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
struct AUDIO_HEADER {
|
||||
int ID;
|
||||
int layer;
|
||||
int protection_bit;
|
||||
int bitrate_index;
|
||||
int sampling_frequency;
|
||||
int padding_bit;
|
||||
int private_bit;
|
||||
int mode;
|
||||
int mode_extension;
|
||||
int copyright;
|
||||
int original;
|
||||
int emphasis;
|
||||
};
|
||||
|
||||
struct SIDE_INFO {
|
||||
int main_data_begin;
|
||||
int scfsi[2][4];
|
||||
int part2_3_length[2][2];
|
||||
int big_values[2][2];
|
||||
int global_gain[2][2];
|
||||
int scalefac_compress[2][2];
|
||||
int window_switching_flag[2][2];
|
||||
int block_type[2][2];
|
||||
int mixed_block_flag[2][2];
|
||||
int table_select[2][2][3];
|
||||
int subblock_gain[2][2][3];
|
||||
int region0_count[2][2];
|
||||
int region1_count[2][2];
|
||||
int preflag[2][2];
|
||||
int scalefac_scale[2][2];
|
||||
int count1table_select[2][2];
|
||||
};
|
||||
|
||||
|
||||
/* global stuff
|
||||
*/
|
||||
|
||||
extern FILE *in_file,*out_file;
|
||||
|
||||
extern void statusDisplay(struct AUDIO_HEADER *header, int frameNo);
|
||||
extern int decodeMPEG(void);
|
||||
extern void initialise_globals(void);
|
||||
extern void report_header_error(int err);
|
||||
|
||||
extern int scalefac_l[2][2][22];
|
||||
extern int scalefac_s[2][2][13][3];
|
||||
extern int t_b8_l[2][3][22];
|
||||
extern int t_b8_s[2][3][13];
|
||||
extern short t_bitrate[2][3][15];
|
||||
|
||||
extern int is[2][578];
|
||||
extern float xr[2][32][18];
|
||||
|
||||
extern int *t_l,*t_s;
|
||||
extern int nch;
|
||||
extern int t_sampling_frequency[2][3];
|
||||
|
||||
extern int A_QUIET,A_SHOW_CNT,A_FORMAT_WAVE,A_DUMP_BINARY;
|
||||
extern int A_WRITE_TO_AUDIO,A_WRITE_TO_FILE;
|
||||
extern short pcm_sample[64];
|
||||
extern int A_AUDIO_PLAY;
|
||||
extern int A_SET_VOLUME,A_SHOW_TIME;
|
||||
extern int A_MSG_STDOUT;
|
||||
extern int A_DOWNMIX;
|
||||
|
||||
/* GUI CONTROL STUFF */
|
||||
extern int GUI_PLAY;
|
||||
extern int GUI_PLAYING;
|
||||
extern int GUI_PAUSE;
|
||||
extern int GUI_PAUSED;
|
||||
extern int GUI_STOP;
|
||||
extern int GUI_STOPPED;
|
||||
extern int GUI_FD_TO_PLAY;
|
||||
extern int GUI_NEXT_FILE_READY;
|
||||
|
||||
/* GUI control stuff */
|
||||
extern int send_fd;
|
||||
extern int receive_fd;
|
||||
|
||||
extern int stop_flag;
|
||||
extern int quit_flag;
|
||||
|
||||
/* ...
|
||||
*/
|
||||
|
||||
#ifdef AUDIO
|
||||
|
||||
FILE *in_file,*out_file;
|
||||
|
||||
int scalefac_l[2][2][22];
|
||||
int scalefac_s[2][2][13][3];
|
||||
|
||||
int is[2][578];
|
||||
float xr[2][32][18];
|
||||
|
||||
int *t_l,*t_s;
|
||||
int nch;
|
||||
int t_sampling_frequency[2][3] = {
|
||||
{ 22050 , 24000 , 16000},
|
||||
{ 44100 , 48000 , 32000}
|
||||
};
|
||||
|
||||
/* GUI control stuff */
|
||||
int send_fd;
|
||||
int receive_fd;
|
||||
|
||||
int stop_flag;
|
||||
int quit_flag;
|
||||
|
||||
int GUI_PLAY,GUI_PLAYING,GUI_STOP,GUI_STOPPED,GUI_PAUSE,GUI_PAUSED;
|
||||
int GUI_FD_TO_PLAY,GUI_NEXT_FILE_READY;
|
||||
|
||||
int A_QUIET,A_SHOW_CNT,A_FORMAT_WAVE,A_DUMP_BINARY;
|
||||
int A_WRITE_TO_FILE;
|
||||
int A_AUDIO_PLAY;
|
||||
int A_SET_VOLUME, A_SHOW_TIME;
|
||||
int A_MSG_STDOUT;
|
||||
int A_DOWNMIX;
|
||||
|
||||
short pcm_sample[64];
|
||||
|
||||
short t_bitrate[2][3][15] = {{
|
||||
{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256},
|
||||
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160},
|
||||
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160}
|
||||
},{
|
||||
{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},
|
||||
{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384},
|
||||
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}
|
||||
}};
|
||||
|
||||
/* the last sfb is given implicitly on pg.28. of the standard. scalefactors
|
||||
* for that one are 0, pretab also
|
||||
*/
|
||||
/* leftmost index denotes ID, so first three tables are for MPEG2 (header->ID==0)
|
||||
* and the other three are for MPEG1 (header->ID==1)
|
||||
*/
|
||||
/* 22.05, 24, 16 */
|
||||
int t_b8_l[2][3][22]={{ /* table B.8b ISO/IEC 11172-3 */
|
||||
{5,11,17,23,29,35,43,53,65,79,95,115,139,167,199,237,283,335,395,463,521,575},
|
||||
{5,11,17,23,29,35,43,53,65,79,95,113,135,161,193,231,277,331,393,463,539,575},
|
||||
{5,11,17,23,29,35,43,53,65,79,95,115,139,167,199,237,283,335,395,463,521,575}
|
||||
},{
|
||||
{3,7,11,15,19,23,29,35,43,51,61,73,89,109,133,161,195,237,287,341,417,575},
|
||||
{3,7,11,15,19,23,29,35,41,49,59,71,87,105,127,155,189,229,275,329,383,575},
|
||||
{3,7,11,15,19,23,29,35,43,53,65,81,101,125,155,193,239,295,363,447,549,575}
|
||||
}};
|
||||
int t_b8_s[2][3][13]={{ /* table B.8b ISO/IEC 11172-3 */
|
||||
{3,7,11,17,23,31,41,55,73,99,131,173,191},
|
||||
{3,7,11,17,25,35,47,61,79,103,135,179,191},
|
||||
{3,7,11,17,25,35,47,61,79,103,133,173,191}
|
||||
},{
|
||||
{3,7,11,15,21,29,39,51,65,83,105,135,191},
|
||||
{3,7,11,15,21,27,37,49,63,79,99,125,191},
|
||||
{3,7,11,15,21,29,41,57,77,103,137,179,191}
|
||||
}};
|
||||
|
||||
int args(int argc,char **argv);
|
||||
void initialise_decoder(void);
|
||||
int decodeMPEG(void);
|
||||
void initialise_globals(void);
|
||||
void report_header_error(int err);
|
||||
int setup_audio(struct AUDIO_HEADER *header);
|
||||
void close_audio(void);
|
||||
int ready_audio(void);
|
||||
|
||||
void play(char *inFileStr, char *outFileStr);
|
||||
|
||||
#endif /* AUDIO */
|
62
Src/Sound/MPEG/config.h
Normal file
62
Src/Sound/MPEG/config.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Define to empty if the keyword does not work. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define if you don't have vprintf but do have _doprnt. */
|
||||
/* #undef HAVE_DOPRNT */
|
||||
|
||||
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
//#define HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define if you have the vprintf function. */
|
||||
//#define HAVE_VPRINTF 1
|
||||
|
||||
/* Define as __inline if that's what the C compiler calls it. */
|
||||
/* #undef inline */
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define if you can safely include both <sys/time.h> and <time.h>. */
|
||||
//#define TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Define if you have the mlock function. */
|
||||
//#define HAVE_MLOCK 1
|
||||
|
||||
/* Define if you have the mlockall function. */
|
||||
//#define HAVE_MLOCKALL 1
|
||||
|
||||
/* Define if you have the sched_setscheduler function. */
|
||||
//#define HAVE_SCHED_SETSCHEDULER 1
|
||||
|
||||
/* Define if you have the select function. */
|
||||
//#define HAVE_SELECT 1
|
||||
|
||||
/* Define if you have the <dmedia/audio.h> header file. */
|
||||
/* #undef HAVE_DMEDIA_AUDIO_H */
|
||||
|
||||
/* Define if you have the <fcntl.h> header file. */
|
||||
//#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define if you have the <linux/soundcard.h> header file. */
|
||||
//#define HAVE_LINUX_SOUNDCARD_H 1
|
||||
|
||||
/* Define if you have the <machine/soundcard.h> header file. */
|
||||
/* #undef HAVE_MACHINE_SOUNDCARD_H */
|
||||
|
||||
/* Define if you have the <sys/audioio.h> header file. */
|
||||
/* #undef HAVE_SYS_AUDIOIO_H */
|
||||
|
||||
/* Define if you have the <sys/ioctl.h> header file. */
|
||||
//#define HAVE_SYS_IOCTL_H 1
|
||||
|
||||
/* Define if you have the <sys/select.h> header file. */
|
||||
//#define HAVE_SYS_SELECT_H 1
|
||||
|
||||
/* Define if you have the <sys/time.h> header file. */
|
||||
//#define HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* define if you want playing to use Linux realtime features */
|
||||
/* #undef LINUX_REALTIME */
|
64
Src/Sound/MPEG/dump.cpp
Normal file
64
Src/Sound/MPEG/dump.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* dump.c binary/hex dump from buffer
|
||||
*
|
||||
* Created by: tomislav uzelac May 1996
|
||||
* Last modified by: tomislav May 31 1997
|
||||
*/
|
||||
//#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "audio.h"
|
||||
#include "getbits.h"
|
||||
|
||||
#define DUMP
|
||||
#include "dump.h"
|
||||
|
||||
/* no hex dump, sorry
|
||||
*/
|
||||
void dump(int *length) /* in fact int length[4] */
|
||||
{
|
||||
int i,j;
|
||||
int _data,space=0;
|
||||
printf(" *********** binary dump\n");
|
||||
_data=data;
|
||||
for (i=0;i<4;i++) {
|
||||
for (j=0;j<space;j++) printf(" ");
|
||||
for (j=0;j<length[i];j++) {
|
||||
printf("%1d",(buffer[_data/8] >> (7-(_data&7)) )&1 );
|
||||
space++;
|
||||
_data++;
|
||||
_data&=8*BUFFER_SIZE-1;
|
||||
if (!(_data & 7)) {
|
||||
printf(" ");
|
||||
space++;
|
||||
if (space>70) {
|
||||
printf("\n");
|
||||
space=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("~\n");
|
||||
}
|
||||
}
|
||||
|
||||
void show_header(struct AUDIO_HEADER *header)
|
||||
{
|
||||
int bitrate=t_bitrate[header->ID][3-header->layer][header->bitrate_index];
|
||||
int fs=t_sampling_frequency[header->ID][header->sampling_frequency];
|
||||
int mpg,layer;
|
||||
char stm[8];
|
||||
if (A_QUIET) return;
|
||||
layer=4-header->layer;
|
||||
if (header->ID==1) mpg=1;
|
||||
else mpg=2;
|
||||
if (header->mode==3) strcpy(stm,"mono");
|
||||
else strcpy(stm,"stereo");
|
||||
|
||||
printf("\n\
|
||||
Properties: %s %dHz\n\
|
||||
Coding Method: MPEG%1d.0 layer%1d\n\
|
||||
Bitrate: %dkbit/s\n"\
|
||||
,stm,fs,mpg,layer,bitrate);
|
||||
}
|
18
Src/Sound/MPEG/dump.h
Normal file
18
Src/Sound/MPEG/dump.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
/* dump.h
|
||||
*
|
||||
* Last modified by: tomislav uzelac May 31 1997
|
||||
*/
|
||||
|
||||
extern void dump(int *length);
|
||||
extern void show_header(struct AUDIO_HEADER *header);
|
||||
|
||||
#ifdef DUMP
|
||||
void dump(int *length);
|
||||
void show_header(struct AUDIO_HEADER *header);
|
||||
/*
|
||||
static char *t_modes[] = {
|
||||
"stereo","joint_stereo","dual_channel","single_channel"};
|
||||
*/
|
||||
#endif /* DUMP */
|
14
Src/Sound/MPEG/formats.h
Normal file
14
Src/Sound/MPEG/formats.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* formats.h
|
||||
*
|
||||
* Created by: tomislav uzelac Dec 22 1996
|
||||
*/
|
||||
extern void wav_end(struct AUDIO_HEADER *header);
|
||||
extern void wav_begin(void);
|
||||
|
||||
#ifdef FORMATS
|
||||
void wav_end(struct AUDIO_HEADER *header);
|
||||
void wav_begin(void);
|
||||
#endif /* FORMATS */
|
370
Src/Sound/MPEG/getbits.cpp
Normal file
370
Src/Sound/MPEG/getbits.cpp
Normal file
|
@ -0,0 +1,370 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* getbits.c bit level routines, input buffer
|
||||
*
|
||||
* Created by: tomislav uzelac Apr 1996
|
||||
* better synchronization, tomislav uzelac, Apr 23 1997
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "amp.h"
|
||||
#include "audio.h"
|
||||
#include "formats.h"
|
||||
#include "rtbuf.h"
|
||||
|
||||
#define GETBITS
|
||||
#include "getbits.h"
|
||||
|
||||
static const char *fstart, *lstart;
|
||||
static int offset, end, eof, lend;
|
||||
|
||||
int MPEG_GetProgress(void)
|
||||
{
|
||||
if (in_file) return ftell(in_file);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void m1setfile(const char *mstart, int mend)
|
||||
{
|
||||
fstart = mstart;
|
||||
offset = 0;
|
||||
eof = 0;
|
||||
end = mend;
|
||||
lstart = NULL;
|
||||
}
|
||||
|
||||
void MPEG_SetLoop(const char *loop, int loopend)
|
||||
{
|
||||
lstart = loop;
|
||||
lend = loopend;
|
||||
}
|
||||
|
||||
int m1fread(unsigned char *buf, int size1, int size2, void *f)
|
||||
{
|
||||
int total = size1 * size2;
|
||||
|
||||
if (in_file) return fread(buf, size1, size2, (FILE *) f);
|
||||
|
||||
// if past EOF
|
||||
if ((total + offset) >= end)
|
||||
{
|
||||
if (lstart == NULL)
|
||||
{
|
||||
total = end - offset;
|
||||
eof = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if past the end, do the xfer in 2 pieces
|
||||
if ((total + offset) > end)
|
||||
{
|
||||
memcpy(buf, fstart + offset, end-offset);
|
||||
buf += (end-offset);
|
||||
total -= (end-offset);
|
||||
}
|
||||
|
||||
fstart = lstart;
|
||||
offset = 0;
|
||||
end = lend;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(buf, fstart + offset, total);
|
||||
|
||||
offset += total;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
int m1feof(void *f)
|
||||
{
|
||||
if (in_file) return feof((FILE *)f);
|
||||
return eof;
|
||||
}
|
||||
|
||||
int m1fseek(void *f, int offs, int whence)
|
||||
{
|
||||
if (in_file) return fseek((FILE *) f, offs, whence);
|
||||
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_CUR:
|
||||
if ((offset + offs) < 0)
|
||||
{
|
||||
offset = 0;
|
||||
eof = 0;
|
||||
return -1;
|
||||
}
|
||||
if ((offset + offs) > end)
|
||||
{
|
||||
offset = end;
|
||||
eof = 1;
|
||||
return end;
|
||||
}
|
||||
offset += offs;
|
||||
eof = 0;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* buffer and bit manipulation functions ***************************************
|
||||
*/
|
||||
static inline int _fillbfr(unsigned int size)
|
||||
{
|
||||
_bptr=0;
|
||||
return get_input(_buffer, size);
|
||||
}
|
||||
|
||||
static inline int readsync()
|
||||
{
|
||||
_bptr=0;
|
||||
_buffer[0]=_buffer[1];
|
||||
_buffer[1]=_buffer[2];
|
||||
_buffer[2]=_buffer[3];
|
||||
return get_input(&_buffer[3],1);
|
||||
}
|
||||
|
||||
static inline unsigned int _getbits(int n)
|
||||
{
|
||||
unsigned int pos,ret_value;
|
||||
|
||||
pos = _bptr >> 3;
|
||||
ret_value = _buffer[pos] << 24 |
|
||||
_buffer[pos+1] << 16 |
|
||||
_buffer[pos+2] << 8 |
|
||||
_buffer[pos+3];
|
||||
ret_value <<= _bptr & 7;
|
||||
ret_value >>= 32 - n;
|
||||
_bptr += n;
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
int fillbfr(unsigned int advance)
|
||||
{
|
||||
int overflow,retval;
|
||||
|
||||
retval=get_input(&buffer[append], advance);
|
||||
|
||||
if ( append + advance >= BUFFER_SIZE ) {
|
||||
overflow = append + advance - BUFFER_SIZE;
|
||||
memcpy (buffer,&buffer[BUFFER_SIZE], overflow);
|
||||
if (overflow < 4) memcpy(&buffer[BUFFER_SIZE],buffer,4);
|
||||
append = overflow;
|
||||
} else {
|
||||
if (append==0) memcpy(&buffer[BUFFER_SIZE],buffer,4);
|
||||
append+=advance;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
unsigned int getbits(int n)
|
||||
{
|
||||
if (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;
|
||||
|
||||
data += n;
|
||||
data &= (8*BUFFER_SIZE)-1;
|
||||
|
||||
return ret_value;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* header and side info parsing stuff ******************************************
|
||||
*/
|
||||
static inline void parse_header(struct AUDIO_HEADER *header)
|
||||
{
|
||||
header->ID=_getbits(1);
|
||||
header->layer=_getbits(2);
|
||||
header->protection_bit=_getbits(1);
|
||||
header->bitrate_index=_getbits(4);
|
||||
header->sampling_frequency=_getbits(2);
|
||||
header->padding_bit=_getbits(1);
|
||||
header->private_bit=_getbits(1);
|
||||
header->mode=_getbits(2);
|
||||
header->mode_extension=_getbits(2);
|
||||
if (!header->mode) header->mode_extension=0;
|
||||
header->copyright=_getbits(1);
|
||||
header->original=_getbits(1);
|
||||
header->emphasis=_getbits(2);
|
||||
}
|
||||
|
||||
static inline int header_sanity_check(struct AUDIO_HEADER *header)
|
||||
{
|
||||
if ( header->layer==0 ||
|
||||
header->bitrate_index==15 ||
|
||||
header->sampling_frequency==3) return -1;
|
||||
|
||||
/* an additional check to make shure that stuffing never gets mistaken
|
||||
* for a syncword. This rules out some legal layer1 streams, but who
|
||||
* cares about layer1 anyway :-). I must get this right sometime.
|
||||
*/
|
||||
if ( header->ID==1 && header->layer==3 && header->protection_bit==1) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int gethdr(struct AUDIO_HEADER *header)
|
||||
{
|
||||
int s,retval;
|
||||
struct AUDIO_HEADER tmp;
|
||||
|
||||
/* TODO: add a simple byte counter to check only first, say, 1024
|
||||
* bytes for a new header and then return GETHDR_SYN
|
||||
*/
|
||||
if ((retval=_fillbfr(4))!=0) return retval;
|
||||
|
||||
for(;;) {
|
||||
while ((s=_getbits(12)) != 0xfff) {
|
||||
if (s==0xffe) {
|
||||
parse_header(&tmp);
|
||||
if (header_sanity_check(&tmp)==0) return GETHDR_NS;
|
||||
}
|
||||
if ((retval=readsync())!=0) return retval;
|
||||
}
|
||||
|
||||
parse_header(&tmp);
|
||||
if (header_sanity_check(&tmp)!=0) {
|
||||
if ((retval=readsync())!=0) return retval;
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (tmp.layer==3) return GETHDR_FL1;
|
||||
/* if (tmp.layer==2) return GETHDR_FL2; */
|
||||
if (tmp.bitrate_index==0) return GETHDR_FF;
|
||||
|
||||
//printf("layer: %d\n", tmp.layer);
|
||||
//printf("sampling frequency: %d\n", tmp.sampling_frequency);
|
||||
|
||||
memcpy(header,&tmp,sizeof(tmp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* dummy function, to get crc out of the way
|
||||
*/
|
||||
void getcrc()
|
||||
{
|
||||
_fillbfr(2);
|
||||
_getbits(16);
|
||||
}
|
||||
|
||||
/* sizes of side_info:
|
||||
* MPEG1 1ch 17 2ch 32
|
||||
* MPEG2 1ch 9 2ch 17
|
||||
*/
|
||||
void getinfo(struct AUDIO_HEADER *header,struct SIDE_INFO *info)
|
||||
{
|
||||
int gr,ch,scfsi_band,region,window;
|
||||
int nch;
|
||||
if (header->mode==3) {
|
||||
nch=1;
|
||||
if (header->ID) {
|
||||
_fillbfr(17);
|
||||
info->main_data_begin=_getbits(9);
|
||||
_getbits(5);
|
||||
} else {
|
||||
_fillbfr(9);
|
||||
info->main_data_begin=_getbits(8);
|
||||
_getbits(1);
|
||||
}
|
||||
} else {
|
||||
nch=2;
|
||||
if (header->ID) {
|
||||
_fillbfr(32);
|
||||
info->main_data_begin=_getbits(9);
|
||||
_getbits(3);
|
||||
} else {
|
||||
_fillbfr(17);
|
||||
info->main_data_begin=_getbits(8);
|
||||
_getbits(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (header->ID) for (ch=0;ch<nch;ch++)
|
||||
for (scfsi_band=0;scfsi_band<4;scfsi_band++)
|
||||
info->scfsi[ch][scfsi_band]=_getbits(1);
|
||||
|
||||
for (gr=0;gr<(header->ID ? 2:1);gr++)
|
||||
for (ch=0;ch<nch;ch++) {
|
||||
info->part2_3_length[gr][ch]=_getbits(12);
|
||||
info->big_values[gr][ch]=_getbits(9);
|
||||
info->global_gain[gr][ch]=_getbits(8);
|
||||
if (header->ID) info->scalefac_compress[gr][ch]=_getbits(4);
|
||||
else info->scalefac_compress[gr][ch]=_getbits(9);
|
||||
info->window_switching_flag[gr][ch]=_getbits(1);
|
||||
|
||||
if (info->window_switching_flag[gr][ch]) {
|
||||
info->block_type[gr][ch]=_getbits(2);
|
||||
info->mixed_block_flag[gr][ch]=_getbits(1);
|
||||
|
||||
for (region=0;region<2;region++)
|
||||
info->table_select[gr][ch][region]=_getbits(5);
|
||||
info->table_select[gr][ch][2]=0;
|
||||
|
||||
for (window=0;window<3;window++)
|
||||
info->subblock_gain[gr][ch][window]=_getbits(3);
|
||||
} else {
|
||||
for (region=0;region<3;region++)
|
||||
info->table_select[gr][ch][region]=_getbits(5);
|
||||
|
||||
info->region0_count[gr][ch]=_getbits(4);
|
||||
info->region1_count[gr][ch]=_getbits(3);
|
||||
info->block_type[gr][ch]=0;
|
||||
}
|
||||
|
||||
if (header->ID) info->preflag[gr][ch]=_getbits(1);
|
||||
info->scalefac_scale[gr][ch]=_getbits(1);
|
||||
info->count1table_select[gr][ch]=_getbits(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int dummy_getinfo(int n)
|
||||
{
|
||||
n-=4;
|
||||
if ( m1fseek(in_file,n,SEEK_CUR) != 0)
|
||||
{
|
||||
if (m1feof(in_file)) return GETHDR_EOF;
|
||||
else return GETHDR_ERR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rewind_stream(int nbytes)
|
||||
{
|
||||
nbytes+=5;
|
||||
if (m1fseek(in_file, -nbytes, SEEK_CUR) != 0) {
|
||||
/* what if we need to be at the very beginning? */
|
||||
nbytes--;
|
||||
if (m1fseek(in_file, -nbytes, SEEK_CUR) != 0) return GETHDR_ERR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int get_input(unsigned char* bp, unsigned int size)
|
||||
{
|
||||
#ifdef LINUX_REALTIME
|
||||
return prefetch_get_input(bp,size);
|
||||
#else /* LINUX_REALTIME */
|
||||
if ( m1fread( bp , 1, size, in_file) != size)
|
||||
{
|
||||
if (m1feof(in_file)) return GETHDR_EOF;
|
||||
else return GETHDR_ERR;
|
||||
}
|
||||
return 0;
|
||||
#endif /* LINUX_REALTIME */
|
||||
}
|
79
Src/Sound/MPEG/getbits.h
Normal file
79
Src/Sound/MPEG/getbits.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* getbits.h
|
||||
*
|
||||
* Created by: tomislav uzelac Apr 1996
|
||||
*/
|
||||
|
||||
/* gethdr() error codes
|
||||
*/
|
||||
#define GETHDR_ERR 0x1
|
||||
#define GETHDR_NS 0x2
|
||||
#define GETHDR_FL1 0x4
|
||||
#define GETHDR_FL2 0x8
|
||||
#define GETHDR_FF 0x10
|
||||
#define GETHDR_SYN 0x20
|
||||
#define GETHDR_EOF 0x30
|
||||
|
||||
/* buffer for the 'bit reservoir'
|
||||
*/
|
||||
#define BUFFER_SIZE 4096
|
||||
#define BUFFER_AUX 2048
|
||||
extern unsigned char buffer[];
|
||||
extern int append,data,f_bdirty,bclean_bytes;
|
||||
|
||||
/* exports
|
||||
*/
|
||||
extern int fillbfr(unsigned int advance);
|
||||
extern unsigned int getbits(int n);
|
||||
extern int gethdr(struct AUDIO_HEADER *header);
|
||||
extern void getcrc();
|
||||
extern void getinfo(struct AUDIO_HEADER *header,struct SIDE_INFO *info);
|
||||
extern int dummy_getinfo(int n);
|
||||
extern int rewind_stream(int nbytes);
|
||||
|
||||
|
||||
#ifdef GETBITS
|
||||
|
||||
/* buffer, AUX is used in case of input buffer "overflow", and its contents
|
||||
* are copied to the beginning of the buffer
|
||||
*/
|
||||
unsigned char buffer[BUFFER_SIZE+BUFFER_AUX];
|
||||
|
||||
/* buffer pointers: append counts in bytes, data in bits
|
||||
*/
|
||||
int append,data;
|
||||
|
||||
/* bit reservoir stuff. f_bdirty must be set to TRUE when starting play!
|
||||
*/
|
||||
int f_bdirty,bclean_bytes;
|
||||
|
||||
/* internal buffer, _bptr holds the position in _bits_
|
||||
*/
|
||||
static unsigned char _buffer[32];
|
||||
static int _bptr;
|
||||
|
||||
|
||||
/* buffer and bit manipulation functions
|
||||
*/
|
||||
static inline int _fillbfr(unsigned int size);
|
||||
static inline int readsync();
|
||||
static inline int get_input(unsigned char* bp, unsigned int size);
|
||||
static inline unsigned int _getbits(int n);
|
||||
int fillbfr(unsigned int advance);
|
||||
unsigned int getbits(int n);
|
||||
int dummy_getinfo(int n);
|
||||
int rewind_stream(int nbytes);
|
||||
|
||||
/* header and side info parsing stuff
|
||||
*/
|
||||
static inline void parse_header(struct AUDIO_HEADER *header);
|
||||
static inline int header_sanity_check(struct AUDIO_HEADER *header);
|
||||
|
||||
int gethdr(struct AUDIO_HEADER *header);
|
||||
void getcrc();
|
||||
void getinfo(struct AUDIO_HEADER *header,struct SIDE_INFO *info);
|
||||
|
||||
#endif /* GETBITS */
|
||||
|
232
Src/Sound/MPEG/getdata.cpp
Normal file
232
Src/Sound/MPEG/getdata.cpp
Normal file
|
@ -0,0 +1,232 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* getdata.c scalefactor & huffman data extraction
|
||||
*
|
||||
* Created by: tomislav uzelac Apr 1996
|
||||
* Last modified by: tomislav uzelac Feb 27 1997
|
||||
*/
|
||||
#include "amp.h"
|
||||
#include "audio.h"
|
||||
#include "getbits.h"
|
||||
#include "huffman.h"
|
||||
|
||||
#define GETDATA
|
||||
#include "getdata.h"
|
||||
|
||||
/* layer3 scalefactor decoding. should we check for the number
|
||||
* of bits read, just in case?
|
||||
*/
|
||||
int decode_scalefactors(struct SIDE_INFO *info,struct AUDIO_HEADER *header,int gr,int ch)
|
||||
{
|
||||
int sfb,window;
|
||||
int slen1,slen2;
|
||||
int i1,i2,i=0;
|
||||
int j,k;
|
||||
if (header->ID==1) {
|
||||
/* this is MPEG-1 scalefactors format, quite different than
|
||||
* the MPEG-2 format.
|
||||
*/
|
||||
slen1=t_slen1[info->scalefac_compress[gr][ch]];
|
||||
slen2=t_slen2[info->scalefac_compress[gr][ch]];
|
||||
i1=3*slen1;
|
||||
i2=3*slen2;
|
||||
|
||||
if (info->window_switching_flag[gr][ch] && info->block_type[gr][ch]==2) {
|
||||
if (info->mixed_block_flag[gr][ch]) {
|
||||
for (sfb=0;sfb<8;sfb++) {
|
||||
scalefac_l[gr][ch][sfb]=getbits(slen1);
|
||||
i+=slen1;
|
||||
}
|
||||
for (sfb=3;sfb<6;sfb++) {
|
||||
for (window=0;window<3;window++)
|
||||
scalefac_s[gr][ch][sfb][window]=getbits(slen1);
|
||||
i+=i1;
|
||||
}
|
||||
for (;sfb<12;sfb++) {
|
||||
for (window=0;window<3;window++)
|
||||
scalefac_s[gr][ch][sfb][window]=getbits(slen2);
|
||||
i+=i2;
|
||||
}
|
||||
} else { /* !mixed_block_flag */
|
||||
for (sfb=0;sfb<6;sfb++) {
|
||||
for (window=0;window<3;window++)
|
||||
scalefac_s[gr][ch][sfb][window]=getbits(slen1);
|
||||
i+=i1;
|
||||
}
|
||||
for (;sfb<12;sfb++) {
|
||||
for (window=0;window<3;window++)
|
||||
scalefac_s[gr][ch][sfb][window]=getbits(slen2);
|
||||
i+=i2;
|
||||
}
|
||||
}
|
||||
for (window=0;window<3;window++)
|
||||
scalefac_s[gr][ch][12][window]=0;
|
||||
} else { /* block_type!=2 */
|
||||
if ( !info->scfsi[ch][0] || !gr )
|
||||
for (sfb=0;sfb<6;sfb++) {
|
||||
scalefac_l[gr][ch][sfb]=getbits(slen1);
|
||||
i+=slen1;
|
||||
}
|
||||
else for (sfb=0;sfb<6;sfb++) {
|
||||
scalefac_l[1][ch][sfb]=scalefac_l[0][ch][sfb];
|
||||
}
|
||||
if ( !info->scfsi[ch][1] || !gr )
|
||||
for (sfb=6;sfb<11;sfb++) {
|
||||
scalefac_l[gr][ch][sfb]=getbits(slen1);
|
||||
i+=slen1;
|
||||
}
|
||||
else for (sfb=6;sfb<11;sfb++) {
|
||||
scalefac_l[1][ch][sfb]=scalefac_l[0][ch][sfb];
|
||||
}
|
||||
if ( !info->scfsi[ch][2] || !gr )
|
||||
for (sfb=11;sfb<16;sfb++) {
|
||||
scalefac_l[gr][ch][sfb]=getbits(slen2);
|
||||
i+=slen2;
|
||||
}
|
||||
else for (sfb=11;sfb<16;sfb++) {
|
||||
scalefac_l[1][ch][sfb]=scalefac_l[0][ch][sfb];
|
||||
}
|
||||
if ( !info->scfsi[ch][3] || !gr )
|
||||
for (sfb=16;sfb<21;sfb++) {
|
||||
scalefac_l[gr][ch][sfb]=getbits(slen2);
|
||||
i+=slen2;
|
||||
}
|
||||
else for (sfb=16;sfb<21;sfb++) {
|
||||
scalefac_l[1][ch][sfb]=scalefac_l[0][ch][sfb];
|
||||
}
|
||||
scalefac_l[gr][ch][21]=0;
|
||||
}
|
||||
} else { /* ID==0 */
|
||||
int index=0,index2,spooky_index;
|
||||
int slen[6],nr_of_sfb[6]; /* actually, there's four of each, not five, labelled 1 through 4, but
|
||||
* what's a word of storage compared to one's sanity. so [0] is irellevant.
|
||||
*/
|
||||
|
||||
/* ok, so we got 3 indexes.
|
||||
* spooky_index - indicates whether we use the normal set of slen eqs and nr_of_sfb tables
|
||||
* or the one for the right channel of intensity stereo coded frame
|
||||
* index - corresponds to the value of scalefac_compress, as listed in the standard
|
||||
* index2 - 0 for long blocks, 1 for short wo/ mixed_block_flag, 2 for short with it
|
||||
*/
|
||||
if ( (header->mode_extension==1 || header->mode_extension==3) && ch==1) { /* right ch... */
|
||||
int int_scalefac_compress=info->scalefac_compress[0][ch]>>1;
|
||||
intensity_scale=info->scalefac_compress[0][1]&1;
|
||||
spooky_index=1;
|
||||
if (int_scalefac_compress < 180) {
|
||||
slen[1]=int_scalefac_compress/36;
|
||||
slen[2]=(int_scalefac_compress%36)/6;
|
||||
slen[3]=(int_scalefac_compress%36)%6;
|
||||
slen[4]=0;
|
||||
info->preflag[0][ch]=0;
|
||||
index=0;
|
||||
}
|
||||
if ( 180 <= int_scalefac_compress && int_scalefac_compress < 244) {
|
||||
slen[1]=((int_scalefac_compress-180)%64)>>4;
|
||||
slen[2]=((int_scalefac_compress-180)%16)>>2;
|
||||
slen[3]=(int_scalefac_compress-180)%4;
|
||||
slen[4]=0;
|
||||
info->preflag[0][ch]=0;
|
||||
index=1;
|
||||
}
|
||||
if ( 244 <= int_scalefac_compress && int_scalefac_compress < 255) {
|
||||
slen[1]=(int_scalefac_compress-244)/3;
|
||||
slen[2]=(int_scalefac_compress-244)%3;
|
||||
slen[3]=0;
|
||||
slen[4]=0;
|
||||
info->preflag[0][ch]=0;
|
||||
index=2;
|
||||
}
|
||||
} else { /* the usual */
|
||||
spooky_index=0;
|
||||
if (info->scalefac_compress[0][ch] < 400) {
|
||||
slen[1]=(info->scalefac_compress[0][ch]>>4)/5;
|
||||
slen[2]=(info->scalefac_compress[0][ch]>>4)%5;
|
||||
slen[3]=(info->scalefac_compress[0][ch]%16)>>2;
|
||||
slen[4]=info->scalefac_compress[0][ch]%4;
|
||||
info->preflag[0][ch]=0;
|
||||
index=0;
|
||||
}
|
||||
if (info->scalefac_compress[0][ch] >= 400 && info->scalefac_compress[0][ch] < 500) {
|
||||
slen[1]=((info->scalefac_compress[0][ch]-400)>>2)/5;
|
||||
slen[2]=((info->scalefac_compress[0][ch]-400)>>2)%5;
|
||||
slen[3]=(info->scalefac_compress[0][ch]-400)%4;
|
||||
slen[4]=0;
|
||||
info->preflag[0][ch]=0;
|
||||
index=1;
|
||||
}
|
||||
if (info->scalefac_compress[0][ch] >= 500 && info->scalefac_compress[0][ch] < 512) {
|
||||
slen[1]=(info->scalefac_compress[0][ch]-500)/3;
|
||||
slen[2]=(info->scalefac_compress[0][ch]-500)%3;
|
||||
slen[3]=0;
|
||||
slen[4]=0;
|
||||
info->preflag[0][ch]=1;
|
||||
index=2;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->window_switching_flag[0][ch] && info->block_type[0][ch]==2)
|
||||
if (info->mixed_block_flag[0][ch]) index2=2;
|
||||
else index2=1;
|
||||
else index2=0;
|
||||
|
||||
for (j=1;j<=4;j++) nr_of_sfb[j]=spooky_table[spooky_index][index][index2][j-1];
|
||||
|
||||
/* now we'll do some actual scalefactor extraction, and a little more.
|
||||
* for each scalefactor band we'll set the value of is_max to indicate
|
||||
* illegal is_pos, since with MPEG2 it's not 'hardcoded' to 7.
|
||||
*/
|
||||
if (!info->window_switching_flag[0][ch] || (info->window_switching_flag[0][ch] && info->block_type[0][ch]!=2)) {
|
||||
sfb=0;
|
||||
for (j=1;j<=4;j++)
|
||||
for (k=0;k<nr_of_sfb[j];k++) {
|
||||
scalefac_l[0][ch][sfb]=getbits(slen[j]);
|
||||
i+=slen[j];
|
||||
if (ch) is_max[sfb]=(1<<slen[j])-1;
|
||||
sfb++;
|
||||
}
|
||||
} else if (info->block_type[0][ch]==2)
|
||||
{
|
||||
if (!info->mixed_block_flag[0][ch]) {
|
||||
sfb=0;
|
||||
for (j=1;j<=4;j++)
|
||||
for (k=0;k<nr_of_sfb[j];k+=3) {
|
||||
/* we assume here that nr_of_sfb is divisible by 3. it is.
|
||||
*/
|
||||
scalefac_s[0][ch][sfb][0]=getbits(slen[j]);
|
||||
scalefac_s[0][ch][sfb][1]=getbits(slen[j]);
|
||||
scalefac_s[0][ch][sfb][2]=getbits(slen[j]);
|
||||
i+=3*slen[j];
|
||||
if (ch) is_max[sfb+6]=(1<<slen[j])-1;
|
||||
sfb++;
|
||||
}
|
||||
} else {
|
||||
/* what we do here is:
|
||||
* 1. assume that for every fs, the two lowest subbands are equal to the
|
||||
* six lowest scalefactor bands for long blocks/MPEG2. they are.
|
||||
* 2. assume that for every fs, the two lowest subbands are equal to the
|
||||
* three lowest scalefactor bands for short blocks. they are.
|
||||
*/
|
||||
sfb=0;
|
||||
for (k=0;k<6;k++) {
|
||||
scalefac_l[0][ch][sfb]=getbits(slen[1]);
|
||||
i+=slen[j];
|
||||
if (ch) is_max[sfb]=(1<<slen[1])-1;
|
||||
sfb++;
|
||||
}
|
||||
nr_of_sfb[1]-=6;
|
||||
sfb=3;
|
||||
for (j=1;j<=4;j++)
|
||||
for (k=0;k<nr_of_sfb[j];k+=3) {
|
||||
scalefac_s[0][ch][sfb][0]=getbits(slen[j]);
|
||||
scalefac_s[0][ch][sfb][1]=getbits(slen[j]);
|
||||
scalefac_s[0][ch][sfb][2]=getbits(slen[j]);
|
||||
i+=3*slen[j];
|
||||
if (ch) is_max[sfb+6]=(1<<slen[j])-1;
|
||||
sfb++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
42
Src/Sound/MPEG/getdata.h
Normal file
42
Src/Sound/MPEG/getdata.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* getdata.h
|
||||
*
|
||||
* tomislav uzelac Apr 1996
|
||||
*/
|
||||
|
||||
extern int decode_scalefactors(struct SIDE_INFO *info,struct AUDIO_HEADER *header,int gr,int ch);
|
||||
|
||||
extern int is_max[21];
|
||||
extern int intensity_scale;
|
||||
|
||||
#ifdef GETDATA
|
||||
|
||||
static char t_slen1[16]={0,0,0,0,3,1,1,1,2,2,2,3,3,3,4,4};
|
||||
static char t_slen2[16]={0,1,2,3,0,1,2,3,1,2,3,1,2,3,2,3};
|
||||
|
||||
int is_max[21]; /* the maximum value of is_pos. for short blocks is_max[sfb=0] == is_max[6],
|
||||
* it's sloppy but i'm sick of waisting storage. blaah...
|
||||
*/
|
||||
int intensity_scale;
|
||||
|
||||
int decode_scalefactors(struct SIDE_INFO *info,struct AUDIO_HEADER *header,int gr,int ch);
|
||||
|
||||
/* my implementation of MPEG2 scalefactor decoding is, admitably, horrible
|
||||
* anyway, just take a look at pg.18 of MPEG2 specs, and you'll know what
|
||||
* this is all about
|
||||
*/
|
||||
static const char spooky_table[2][3][3][4]={
|
||||
{
|
||||
{ {6,5,5,5}, {9,9,9,9}, {6,9,9,9} },
|
||||
{ {6,5,7,3}, {9,9,12,6}, {6,9,12,6}},
|
||||
{ {11,10,0,0}, {18,18,0,0}, {15,18,0,0}}
|
||||
},
|
||||
{
|
||||
{ {7,7,7,0}, {12,12,12,0}, {6,15,12,0}},
|
||||
{ {6,6,6,3}, {12,9,9,6}, {6,12,9,6}},
|
||||
{ {8,8,5,0}, {15,12,9,0}, {6,18,9,0}}
|
||||
}};
|
||||
|
||||
#endif /* GETDATA */
|
209
Src/Sound/MPEG/huffman.cpp
Normal file
209
Src/Sound/MPEG/huffman.cpp
Normal file
|
@ -0,0 +1,209 @@
|
|||
/* 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"
|
||||
|
||||
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.
|
||||
*/
|
||||
printf(" h_cue clobbered. this is a bug. blip.\n");
|
||||
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;
|
||||
}
|
259
Src/Sound/MPEG/huffman.h
Normal file
259
Src/Sound/MPEG/huffman.h
Normal file
|
@ -0,0 +1,259 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* huffman.h
|
||||
*
|
||||
* Created by: tomislav uzelac Mar 1996
|
||||
* Last edited by: tomislav uzelac Mar 8 97
|
||||
*/
|
||||
|
||||
extern int decode_huffman_data(struct SIDE_INFO *info,int gr,int ch,int ssize);
|
||||
|
||||
extern int non_zero[2];
|
||||
extern int t_linbits[32];
|
||||
|
||||
#ifdef HUFFMAN
|
||||
|
||||
static inline unsigned int viewbits(int n);
|
||||
static inline void sackbits(int n);
|
||||
static inline int huffman_decode(int tbl,int *x,int *y);
|
||||
static inline int _qsign(int x,int *q);
|
||||
int decode_huffman_data(struct SIDE_INFO *info,int gr,int ch,int ssize);
|
||||
|
||||
int non_zero[2]; /* this is 2*bigvalues+4*count1, i guess...*/
|
||||
|
||||
#define N_CUE 16
|
||||
#define NC_O 4
|
||||
|
||||
int t_linbits[32]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,6,8,10,13,4,5,6,7,8,9,11,13};
|
||||
|
||||
/* these are the huffman tables, rearranged for lookup
|
||||
*/
|
||||
unsigned int h0[1]={0x0};
|
||||
unsigned int h1[4]={0x311, 0x20000301, 0x40000210, 0x80000100};
|
||||
unsigned int h2[9]={0x622, 0x4000602, 0x8000512, 0x10000521, 0x18000520, 0x20000311, 0x40000301, 0x60000310,
|
||||
0x80000100};
|
||||
unsigned int h3[9]={ 0x622, 0x4000602, 0x8000512, 0x10000521, 0x18000520, 0x20000310, 0x40000211, 0x80000201,
|
||||
0xc0000200};
|
||||
unsigned int h5[16]={0x833, 0x1000823, 0x2000732, 0x4000631, 0x8000713, 0xa000703, 0xc000730, 0xe000722,
|
||||
0x10000612, 0x14000621, 0x18000602, 0x1c000620, 0x20000311, 0x40000301, 0x60000310, 0x80000100};
|
||||
unsigned int h6[16]={0x733, 0x2000703, 0x4000623, 0x8000632, 0xc000630, 0x10000513, 0x18000531, 0x20000522,
|
||||
0x28000502, 0x30000412, 0x40000421, 0x50000420, 0x60000301, 0x80000211, 0xc0000310, 0xe0000300};
|
||||
unsigned int h7[36]={ 0xa55, 0x400a45, 0x800a54, 0xc00a53, 0x1000935, 0x1800944, 0x2000925, 0x2800952,
|
||||
0x3000815, 0x4000851, 0x5000905, 0x5800934, 0x6000850, 0x7000943, 0x7800933, 0x8000824,
|
||||
0x9000842, 0xa000714, 0xc000741, 0xe000740, 0x10000804, 0x11000823, 0x12000832, 0x13000803,
|
||||
0x14000713, 0x16000731, 0x18000730, 0x1a000722, 0x1c000612, 0x20000521, 0x28000602, 0x2c000620,
|
||||
0x30000411, 0x40000301, 0x60000310, 0x80000100};
|
||||
unsigned int h8[36]={0xb55, 0x200b54, 0x400a45, 0x800953, 0x1000a35, 0x1400a44, 0x1800925, 0x2000952,
|
||||
0x2800905, 0x3000815, 0x4000851, 0x5000934, 0x5800943, 0x6000950, 0x6800933, 0x7000824,
|
||||
0x8000842, 0x9000814, 0xa000741, 0xc000804, 0xd000840, 0xe000823, 0xf000832, 0x10000813,
|
||||
0x11000831, 0x12000803, 0x13000830, 0x14000622, 0x18000602, 0x1c000620, 0x20000412, 0x30000421,
|
||||
0x40000211, 0x80000301, 0xa0000310, 0xc0000200};
|
||||
unsigned int h9[36]={ 0x955, 0x800945, 0x1000835, 0x2000853, 0x3000954, 0x3800905, 0x4000844, 0x5000825,
|
||||
0x6000852, 0x7000815, 0x8000751, 0xa000734, 0xc000743, 0xe000850, 0xf000804, 0x10000724,
|
||||
0x12000742, 0x14000733, 0x16000740, 0x18000614, 0x1c000641, 0x20000623, 0x24000632, 0x28000513,
|
||||
0x30000531, 0x38000603, 0x3c000630, 0x40000522, 0x48000502, 0x50000412, 0x60000421, 0x70000420,
|
||||
0x80000311, 0xa0000301, 0xc0000310, 0xe0000300};
|
||||
unsigned int h10[64]={ 0xb77, 0x200b67, 0x400b76, 0x600b57, 0x800b75, 0xa00b66, 0xc00a47, 0x1000a74,
|
||||
0x1400a56, 0x1800a65, 0x1c00a37, 0x2000a73, 0x2400a46, 0x2800b55, 0x2a00b54, 0x2c00a63,
|
||||
0x3000927, 0x3800972, 0x4000a64, 0x4400a07, 0x4800970, 0x5000962, 0x5800a45, 0x5c00a35,
|
||||
0x6000906, 0x6800a53, 0x6c00a44, 0x7000817, 0x8000871, 0x9000936, 0x9800926, 0xa000a25,
|
||||
0xa400a52, 0xa800915, 0xb000951, 0xb800a34, 0xbc00a43, 0xc000816, 0xd000861, 0xe000860,
|
||||
0xf000905, 0xf800950, 0x10000924, 0x10800942, 0x11000933, 0x11800904, 0x12000814, 0x13000841,
|
||||
0x14000840, 0x15000823, 0x16000832, 0x17000803, 0x18000713, 0x1a000731, 0x1c000730, 0x1e000722,
|
||||
0x20000612, 0x24000621, 0x28000602, 0x2c000620, 0x30000411, 0x40000301, 0x60000310, 0x80000100};
|
||||
unsigned int h11[64]={ 0xa77, 0x400a67, 0x800a76, 0xc00a75, 0x1000a66, 0x1400a47, 0x1800a74, 0x1c00b57,
|
||||
0x1e00b55, 0x2000a56, 0x2400a65, 0x2800937, 0x3000973, 0x3800946, 0x4000a45, 0x4400a54,
|
||||
0x4800a35, 0x4c00a53, 0x5000827, 0x6000872, 0x7000964, 0x7800907, 0x8000771, 0xa000817,
|
||||
0xb000870, 0xc000836, 0xd000863, 0xe000860, 0xf000944, 0xf800925, 0x10000952, 0x10800905,
|
||||
0x11000815, 0x12000762, 0x14000826, 0x15000806, 0x16000716, 0x18000761, 0x1a000851, 0x1b000834,
|
||||
0x1c000850, 0x1d000943, 0x1d800933, 0x1e000824, 0x1f000842, 0x20000814, 0x21000841, 0x22000804,
|
||||
0x23000840, 0x24000723, 0x26000732, 0x28000613, 0x2c000631, 0x30000703, 0x32000730, 0x34000622,
|
||||
0x38000521, 0x40000412, 0x50000502, 0x58000520, 0x60000311, 0x80000301, 0xa0000310, 0xc0000200};
|
||||
unsigned int h12[64]={ 0xa77, 0x400a67, 0x800976, 0x1000957, 0x1800975, 0x2000966, 0x2800947, 0x3000974,
|
||||
0x3800965, 0x4000856, 0x5000837, 0x6000973, 0x6800955, 0x7000827, 0x8000872, 0x9000846,
|
||||
0xa000864, 0xb000817, 0xc000871, 0xd000907, 0xd800970, 0xe000836, 0xf000863, 0x10000845,
|
||||
0x11000854, 0x12000844, 0x13000906, 0x13800905, 0x14000726, 0x16000762, 0x18000761, 0x1a000816,
|
||||
0x1b000860, 0x1c000835, 0x1d000853, 0x1e000825, 0x1f000852, 0x20000715, 0x22000751, 0x24000734,
|
||||
0x26000743, 0x28000850, 0x29000804, 0x2a000724, 0x2c000742, 0x2e000714, 0x30000633, 0x34000641,
|
||||
0x38000623, 0x3c000632, 0x40000740, 0x42000703, 0x44000630, 0x48000513, 0x50000531, 0x58000522,
|
||||
0x60000412, 0x70000421, 0x80000502, 0x88000520, 0x90000400, 0xa0000311, 0xc0000301, 0xe0000310};
|
||||
unsigned int h13[256]={
|
||||
0x13fe, 0x33fc, 0x52fd, 0x91ed, 0x110ff, 0x210ef, 0x310df, 0x410ee,
|
||||
0x510cf, 0x610de, 0x710bf, 0x810fb, 0x910ce, 0xa10dc, 0xb11af, 0xb91e9,
|
||||
0xc0fec, 0xe0fdd, 0x1010fa, 0x1110cd, 0x120fbe, 0x140feb, 0x160f9f, 0x180ff9,
|
||||
0x1a0fea, 0x1c0fbd, 0x1e0fdb, 0x200f8f, 0x220ff8, 0x240fcc, 0x2610ae, 0x27109e,
|
||||
0x280f8e, 0x2a107f, 0x2b107e, 0x2c0ef7, 0x300eda, 0x340fad, 0x360fbc, 0x380fcb,
|
||||
0x3a0ff6, 0x3c0e6f, 0x400ee8, 0x440e5f, 0x480e9d, 0x4c0ed9, 0x500ef5, 0x540ee7,
|
||||
0x580eac, 0x5c0ebb, 0x600e4f, 0x640ef4, 0x680fca, 0x6a0fe6, 0x6c0ef3, 0x700d3f,
|
||||
0x780e8d, 0x7c0ed8, 0x800d2f, 0x880df2, 0x900e6e, 0x940e9c, 0x980d0f, 0xa00ec9,
|
||||
0xa40e5e, 0xa80dab, 0xb00e7d, 0xb40ed7, 0xb80d4e, 0xc00ec8, 0xc40ed6, 0xc80d3e,
|
||||
0xd00db9, 0xd80e9b, 0xdc0eaa, 0xe00c1f, 0xf00cf1, 0x1000cf0, 0x1100dba, 0x1180de5,
|
||||
0x1200de4, 0x1280d8c, 0x1300d6d, 0x1380de3, 0x1400ce2, 0x1500d2e, 0x1580d0e, 0x1600c1e,
|
||||
0x1700ce1, 0x1800de0, 0x1880d5d, 0x1900dd5, 0x1980d7c, 0x1a00dc7, 0x1a80d4d, 0x1b00d8b,
|
||||
0x1b80db8, 0x1c00dd4, 0x1c80d9a, 0x1d00da9, 0x1d80d6c, 0x1e00cc6, 0x1f00c3d, 0x2000dd3,
|
||||
0x2080d7b, 0x2100c2d, 0x2200cd2, 0x2300c1d, 0x2400cb7, 0x2500d5c, 0x2580dc5, 0x2600d99,
|
||||
0x2680d7a, 0x2700cc3, 0x2800da7, 0x2880d97, 0x2900c4b, 0x2a00bd1, 0x2c00c0d, 0x2d00cd0,
|
||||
0x2e00c8a, 0x2f00ca8, 0x3000c4c, 0x3100cc4, 0x3200c6b, 0x3300cb6, 0x3400b3c, 0x3600b2c,
|
||||
0x3800bc2, 0x3a00b5b, 0x3c00cb5, 0x3d00c89, 0x3e00b1c, 0x4000bc1, 0x4200c98, 0x4300c0c,
|
||||
0x4400bc0, 0x4600cb4, 0x4700c6a, 0x4800ca6, 0x4900c79, 0x4a00b3b, 0x4c00bb3, 0x4e00c88,
|
||||
0x4f00c5a, 0x5000b2b, 0x5200ca5, 0x5300c69, 0x5400ba4, 0x5600c78, 0x5700c87, 0x5800b94,
|
||||
0x5a00c77, 0x5b00c76, 0x5c00ab2, 0x6000a1b, 0x6400ab1, 0x6800b0b, 0x6a00bb0, 0x6c00b96,
|
||||
0x6e00b4a, 0x7000b3a, 0x7200ba3, 0x7400b59, 0x7600b95, 0x7800a2a, 0x7c00aa2, 0x8000a1a,
|
||||
0x8400aa1, 0x8800b0a, 0x8a00b68, 0x8c00aa0, 0x9000b86, 0x9200b49, 0x9400a93, 0x9800b39,
|
||||
0x9a00b58, 0x9c00b85, 0x9e00b67, 0xa000a29, 0xa400a92, 0xa800b57, 0xaa00b75, 0xac00a38,
|
||||
0xb000a83, 0xb400b66, 0xb600b47, 0xb800b74, 0xba00b56, 0xbc00b65, 0xbe00b73, 0xc000919,
|
||||
0xc800991, 0xd000a09, 0xd400a90, 0xd800a48, 0xdc00a84, 0xe000a72, 0xe400b46, 0xe600b64,
|
||||
0xe800928, 0xf000982, 0xf800918, 0x10000a37, 0x10400a27, 0x10800917, 0x11000971, 0x11800a55,
|
||||
0x11c00a07, 0x12000a70, 0x12400a36, 0x12800a63, 0x12c00a45, 0x13000a54, 0x13400a26, 0x13800a62,
|
||||
0x13c00a35, 0x14000881, 0x15000908, 0x15800980, 0x16000916, 0x16800961, 0x17000906, 0x17800960,
|
||||
0x18000a53, 0x18400a44, 0x18800925, 0x19000952, 0x19800905, 0x1a000815, 0x1b000851, 0x1c000934,
|
||||
0x1c800943, 0x1d000950, 0x1d800924, 0x1e000942, 0x1e800933, 0x1f000814, 0x20000741, 0x22000804,
|
||||
0x23000840, 0x24000823, 0x25000832, 0x26000713, 0x28000731, 0x2a000703, 0x2c000730, 0x2e000722,
|
||||
0x30000612, 0x34000621, 0x38000602, 0x3c000620, 0x40000411, 0x50000401, 0x60000310, 0x80000100};
|
||||
unsigned int h15[256]={ 0xdff, 0x80def, 0x100dfe, 0x180ddf, 0x200cee, 0x300dfd, 0x380dcf, 0x400dfc,
|
||||
0x480dde, 0x500ded, 0x580dbf, 0x600cfb, 0x700dce, 0x780dec, 0x800cdd, 0x900caf,
|
||||
0xa00cfa, 0xb00cbe, 0xc00ceb, 0xd00ccd, 0xe00cdc, 0xf00c9f, 0x1000cf9, 0x1100cea,
|
||||
0x1200cbd, 0x1300cdb, 0x1400c8f, 0x1500cf8, 0x1600ccc, 0x1700c9e, 0x1800ce9, 0x1900c7f,
|
||||
0x1a00cf7, 0x1b00cad, 0x1c00cda, 0x1d00cbc, 0x1e00c6f, 0x1f00dae, 0x1f80d0f, 0x2000bcb,
|
||||
0x2200bf6, 0x2400c8e, 0x2500ce8, 0x2600c5f, 0x2700c9d, 0x2800bf5, 0x2a00b7e, 0x2c00be7,
|
||||
0x2e00bac, 0x3000bca, 0x3200bbb, 0x3400cd9, 0x3500c8d, 0x3600b4f, 0x3800bf4, 0x3a00b3f,
|
||||
0x3c00bf3, 0x3e00bd8, 0x4000be6, 0x4200b2f, 0x4400bf2, 0x4600c6e, 0x4700cf0, 0x4800b1f,
|
||||
0x4a00bf1, 0x4c00b9c, 0x4e00bc9, 0x5000b5e, 0x5200bab, 0x5400bba, 0x5600be5, 0x5800b7d,
|
||||
0x5a00bd7, 0x5c00b4e, 0x5e00be4, 0x6000b8c, 0x6200bc8, 0x6400b3e, 0x6600b6d, 0x6800bd6,
|
||||
0x6a00be3, 0x6c00b9b, 0x6e00bb9, 0x7000b2e, 0x7200baa, 0x7400be2, 0x7600b1e, 0x7800be1,
|
||||
0x7a00c0e, 0x7b00ce0, 0x7c00b5d, 0x7e00bd5, 0x8000b7c, 0x8200bc7, 0x8400b4d, 0x8600b8b,
|
||||
0x8800ad4, 0x8c00bb8, 0x8e00b9a, 0x9000ba9, 0x9200b6c, 0x9400bc6, 0x9600b3d, 0x9800ad3,
|
||||
0x9c00ad2, 0xa000b2d, 0xa200b0d, 0xa400a1d, 0xa800a7b, 0xac00ab7, 0xb000ad1, 0xb400b5c,
|
||||
0xb600bd0, 0xb800ac5, 0xbc00a8a, 0xc000aa8, 0xc400a4c, 0xc800ac4, 0xcc00a6b, 0xd000ab6,
|
||||
0xd400b99, 0xd600b0c, 0xd800a3c, 0xdc00ac3, 0xe000a7a, 0xe400aa7, 0xe800aa6, 0xec00bc0,
|
||||
0xee00b0b, 0xf0009c2, 0xf800a2c, 0xfc00a5b, 0x10000ab5, 0x10400a1c, 0x10800a89, 0x10c00a98,
|
||||
0x11000ac1, 0x11400a4b, 0x11800ab4, 0x11c00a6a, 0x12000a3b, 0x12400a79, 0x128009b3, 0x13000a97,
|
||||
0x13400a88, 0x13800a2b, 0x13c00a5a, 0x140009b2, 0x14800aa5, 0x14c00a1b, 0x150009b1, 0x15800ab0,
|
||||
0x15c00a69, 0x16000a96, 0x16400a4a, 0x16800aa4, 0x16c00a78, 0x17000a87, 0x17400a3a, 0x178009a3,
|
||||
0x18000959, 0x18800995, 0x1900092a, 0x198009a2, 0x1a00091a, 0x1a8009a1, 0x1b000a0a, 0x1b400aa0,
|
||||
0x1b800968, 0x1c000986, 0x1c800949, 0x1d000994, 0x1d800939, 0x1e000993, 0x1e800a77, 0x1ec00a09,
|
||||
0x1f000958, 0x1f800985, 0x20000929, 0x20800967, 0x21000976, 0x21800992, 0x22000891, 0x23000919,
|
||||
0x23800990, 0x24000948, 0x24800984, 0x25000957, 0x25800975, 0x26000938, 0x26800983, 0x27000966,
|
||||
0x27800947, 0x28000828, 0x29000882, 0x2a000818, 0x2b000881, 0x2c000974, 0x2c800908, 0x2d000980,
|
||||
0x2d800956, 0x2e000965, 0x2e800937, 0x2f000973, 0x2f800946, 0x30000827, 0x31000872, 0x32000864,
|
||||
0x33000817, 0x34000855, 0x35000871, 0x36000907, 0x36800970, 0x37000836, 0x38000863, 0x39000845,
|
||||
0x3a000854, 0x3b000826, 0x3c000862, 0x3d000816, 0x3e000906, 0x3e800960, 0x3f000835, 0x40000761,
|
||||
0x42000853, 0x43000844, 0x44000725, 0x46000752, 0x48000715, 0x4a000751, 0x4c000805, 0x4d000850,
|
||||
0x4e000734, 0x50000743, 0x52000724, 0x54000742, 0x56000733, 0x58000641, 0x5c000714, 0x5e000704,
|
||||
0x60000623, 0x64000632, 0x68000740, 0x6a000703, 0x6c000613, 0x70000631, 0x74000630, 0x78000522,
|
||||
0x80000512, 0x88000521, 0x90000502, 0x98000520, 0xa0000311, 0xc0000401, 0xd0000410, 0xe0000300};
|
||||
unsigned int h16[256]={ 0xbef, 0x200bfe, 0x400bdf, 0x600bfd, 0x800bcf, 0xa00bfc, 0xc00bbf, 0xe00bfb,
|
||||
0x1000aaf, 0x1400bfa, 0x1600b9f, 0x1800bf9, 0x1a00bf8, 0x1c00a8f, 0x2000a7f, 0x2400af7,
|
||||
0x2800a6f, 0x2c00af6, 0x30008ff, 0x4000a5f, 0x4400af5, 0x480094f, 0x50009f4, 0x58009f3,
|
||||
0x60009f0, 0x6800a3f, 0x6c010ce, 0x6c111ec, 0x6c191dd, 0x6c20fde, 0x6c40fe9, 0x6c610ea,
|
||||
0x6c710d9, 0x6c80eee, 0x6cc0fed, 0x6ce0feb, 0x6d00ebe, 0x6d40ecd, 0x6d80fdc, 0x6da0fdb,
|
||||
0x6dc0eae, 0x6e00ecc, 0x6e40fad, 0x6e60fda, 0x6e80f7e, 0x6ea0fac, 0x6ec0eca, 0x6f00fc9,
|
||||
0x6f20f7d, 0x6f40e5e, 0x6f80dbd, 0x70008f2, 0x800092f, 0x880090f, 0x900081f, 0xa0008f1,
|
||||
0xb000d9e, 0xb080ebc, 0xb0c0ecb, 0xb100e8e, 0xb140ee8, 0xb180e9d, 0xb1c0ee7, 0xb200ebb,
|
||||
0xb240e8d, 0xb280ed8, 0xb2c0e6e, 0xb300de6, 0xb380d9c, 0xb400eab, 0xb440eba, 0xb480ee5,
|
||||
0xb4c0ed7, 0xb500d4e, 0xb580ee4, 0xb5c0e8c, 0xb600dc8, 0xb680d3e, 0xb700d6d, 0xb780ed6,
|
||||
0xb7c0e9b, 0xb800eb9, 0xb840eaa, 0xb880de1, 0xb900dd4, 0xb980eb8, 0xb9c0ea9, 0xba00d7b,
|
||||
0xba80eb7, 0xbac0ed0, 0xbb00ce3, 0xbc00d0e, 0xbc80de0, 0xbd00d5d, 0xbd80dd5, 0xbe00d7c,
|
||||
0xbe80dc7, 0xbf00d4d, 0xbf80d8b, 0xc000d9a, 0xc080d6c, 0xc100dc6, 0xc180d3d, 0xc200d5c,
|
||||
0xc280dc5, 0xc300c0d, 0xc400d8a, 0xc480da8, 0xc500d99, 0xc580d4c, 0xc600db6, 0xc680d7a,
|
||||
0xc700c3c, 0xc800d5b, 0xc880d89, 0xc900c1c, 0xca00cc0, 0xcb00d98, 0xcb80d79, 0xcc00be2,
|
||||
0xce00c2e, 0xcf00c1e, 0xd000cd3, 0xd100c2d, 0xd200cd2, 0xd300cd1, 0xd400c3b, 0xd500d97,
|
||||
0xd580d88, 0xd600b1d, 0xd800cc4, 0xd900c6b, 0xda00cc3, 0xdb00ca7, 0xdc00b2c, 0xde00cc2,
|
||||
0xdf00cb5, 0xe000cc1, 0xe100c0c, 0xe200c4b, 0xe300cb4, 0xe400c6a, 0xe500ca6, 0xe600bb3,
|
||||
0xe800c5a, 0xe900ca5, 0xea00b2b, 0xec00bb2, 0xee00b1b, 0xf000bb1, 0xf200c0b, 0xf300cb0,
|
||||
0xf400c69, 0xf500c96, 0xf600c4a, 0xf700ca4, 0xf800c78, 0xf900c87, 0xfa00ba3, 0xfc00c3a,
|
||||
0xfd00c59, 0xfe00b2a, 0x10000c95, 0x10100c68, 0x10200ba1, 0x10400c86, 0x10500c77, 0x10600b94,
|
||||
0x10800c49, 0x10900c57, 0x10a00b67, 0x10c00aa2, 0x11000a1a, 0x11400b0a, 0x11600ba0, 0x11800b39,
|
||||
0x11a00b93, 0x11c00b58, 0x11e00b85, 0x12000a29, 0x12400a92, 0x12800b76, 0x12a00b09, 0x12c00a19,
|
||||
0x13000a91, 0x13400b90, 0x13600b48, 0x13800b84, 0x13a00b75, 0x13c00b38, 0x13e00b83, 0x14000b66,
|
||||
0x14200b28, 0x14400a82, 0x14800b47, 0x14a00b74, 0x14c00a18, 0x15000a81, 0x15400a80, 0x15800b08,
|
||||
0x15a00b56, 0x15c00a37, 0x16000a73, 0x16400b65, 0x16600b46, 0x16800a27, 0x16c00a72, 0x17000b64,
|
||||
0x17200b55, 0x17400a07, 0x17800917, 0x18000971, 0x18800a70, 0x18c00a36, 0x19000a63, 0x19400a45,
|
||||
0x19800a54, 0x19c00a26, 0x1a000962, 0x1a800916, 0x1b000961, 0x1b800a06, 0x1bc00a60, 0x1c000953,
|
||||
0x1c800a35, 0x1cc00a44, 0x1d000925, 0x1d800952, 0x1e000851, 0x1f000915, 0x1f800905, 0x20000934,
|
||||
0x20800943, 0x21000950, 0x21800924, 0x22000942, 0x22800933, 0x23000814, 0x24000841, 0x25000904,
|
||||
0x25800940, 0x26000823, 0x27000832, 0x28000713, 0x2a000731, 0x2c000803, 0x2d000830, 0x2e000722,
|
||||
0x30000612, 0x34000621, 0x38000602, 0x3c000620, 0x40000411, 0x50000401, 0x60000310, 0x80000100};
|
||||
unsigned int h24[256]={ 0x8ef, 0x10008fe, 0x20008df, 0x30008fd, 0x40008cf, 0x50008fc, 0x60008bf, 0x70008fb,
|
||||
0x80007fa, 0xa0008af, 0xb00089f, 0xc0007f9, 0xe0007f8, 0x1000088f, 0x1100087f, 0x120007f7,
|
||||
0x1400076f, 0x160007f6, 0x1800075f, 0x1a0007f5, 0x1c00074f, 0x1e0007f4, 0x2000073f, 0x220007f3,
|
||||
0x2400072f, 0x260007f2, 0x280007f1, 0x2a00081f, 0x2b0008f0, 0x2c00090f, 0x2c800bee, 0x2ca00bde,
|
||||
0x2cc00bed, 0x2ce00bce, 0x2d000bec, 0x2d200bdd, 0x2d400bbe, 0x2d600beb, 0x2d800bcd, 0x2da00bdc,
|
||||
0x2dc00bae, 0x2de00bea, 0x2e000bbd, 0x2e200bdb, 0x2e400bcc, 0x2e600b9e, 0x2e800be9, 0x2ea00bad,
|
||||
0x2ec00bda, 0x2ee00bbc, 0x2f000bcb, 0x2f200b8e, 0x2f400be8, 0x2f600b9d, 0x2f800bd9, 0x2fa00b7e,
|
||||
0x2fc00be7, 0x2fe00bac, 0x300004ff, 0x40000bca, 0x40200bbb, 0x40400b8d, 0x40600bd8, 0x40800c0e,
|
||||
0x40900ce0, 0x40a00b0d, 0x40c00ae6, 0x41000b6e, 0x41200b9c, 0x41400ac9, 0x41800a5e, 0x41c00aba,
|
||||
0x42000ae5, 0x42400bab, 0x42600b7d, 0x42800ad7, 0x42c00ae4, 0x43000a8c, 0x43400ac8, 0x43800b4e,
|
||||
0x43a00b2e, 0x43c00a3e, 0x44000a6d, 0x44400ad6, 0x44800ae3, 0x44c00a9b, 0x45000ab9, 0x45400aaa,
|
||||
0x45800ae2, 0x45c00a1e, 0x46000ae1, 0x46400a5d, 0x46800ad5, 0x46c00a7c, 0x47000ac7, 0x47400a4d,
|
||||
0x47800a8b, 0x47c00ab8, 0x48000ad4, 0x48400a9a, 0x48800aa9, 0x48c00a6c, 0x49000ac6, 0x49400a3d,
|
||||
0x49800ad3, 0x49c00a2d, 0x4a000ad2, 0x4a400a1d, 0x4a800a7b, 0x4ac00ab7, 0x4b000ad1, 0x4b400a5c,
|
||||
0x4b800ac5, 0x4bc00a8a, 0x4c000aa8, 0x4c400a99, 0x4c800a4c, 0x4cc00ac4, 0x4d000a6b, 0x4d400ab6,
|
||||
0x4d800bd0, 0x4da00b0c, 0x4dc00a3c, 0x4e000ac3, 0x4e400a7a, 0x4e800aa7, 0x4ec00a2c, 0x4f000ac2,
|
||||
0x4f400a5b, 0x4f800ab5, 0x4fc00a1c, 0x50000a89, 0x50400a98, 0x50800ac1, 0x50c00a4b, 0x51000bc0,
|
||||
0x51200b0b, 0x51400a3b, 0x51800bb0, 0x51a00b0a, 0x51c00a1a, 0x520009b4, 0x52800a6a, 0x52c00aa6,
|
||||
0x53000a79, 0x53400a97, 0x53800ba0, 0x53a00b09, 0x53c00a90, 0x540009b3, 0x54800988, 0x55000a2b,
|
||||
0x55400a5a, 0x558009b2, 0x56000aa5, 0x56400a1b, 0x56800ab1, 0x56c00a69, 0x57000996, 0x578009a4,
|
||||
0x58000a4a, 0x58400a78, 0x58800987, 0x5900093a, 0x598009a3, 0x5a000959, 0x5a800995, 0x5b00092a,
|
||||
0x5b8009a2, 0x5c0009a1, 0x5c800968, 0x5d000986, 0x5d800977, 0x5e000949, 0x5e800994, 0x5f000939,
|
||||
0x5f800993, 0x60000958, 0x60800985, 0x61000929, 0x61800967, 0x62000976, 0x62800992, 0x63000919,
|
||||
0x63800991, 0x64000948, 0x64800984, 0x65000957, 0x65800975, 0x66000938, 0x66800983, 0x67000966,
|
||||
0x67800928, 0x68000982, 0x68800918, 0x69000947, 0x69800974, 0x6a000981, 0x6a800a08, 0x6ac00a80,
|
||||
0x6b000956, 0x6b800965, 0x6c000917, 0x6c800a07, 0x6cc00a70, 0x6d000873, 0x6e000937, 0x6e800927,
|
||||
0x6f000872, 0x70000846, 0x71000864, 0x72000855, 0x73000871, 0x74000836, 0x75000863, 0x76000845,
|
||||
0x77000854, 0x78000826, 0x79000862, 0x7a000816, 0x7b000861, 0x7c000906, 0x7c800960, 0x7d000835,
|
||||
0x7e000853, 0x7f000844, 0x80000825, 0x81000852, 0x82000815, 0x83000905, 0x83800950, 0x84000751,
|
||||
0x86000834, 0x87000843, 0x88000724, 0x8a000742, 0x8c000733, 0x8e000714, 0x90000741, 0x92000804,
|
||||
0x93000840, 0x94000723, 0x96000732, 0x98000613, 0x9c000631, 0xa0000703, 0xa2000730, 0xa4000622,
|
||||
0xa8000512, 0xb0000521, 0xb8000602, 0xbc000620, 0xc0000411, 0xd0000401, 0xe0000410, 0xf0000400};
|
||||
unsigned int hA[16]={ 0x6b0, 0x40006f0, 0x80006d0, 0xc0006e0, 0x10000670, 0x14000650, 0x18000590, 0x20000560,
|
||||
0x28000530, 0x300005a0, 0x380005c0, 0x40000420, 0x50000410, 0x60000440, 0x70000480, 0x80000100};
|
||||
unsigned int hB[16]={ 0x4f0, 0x100004e0, 0x200004d0, 0x300004c0, 0x400004b0, 0x500004a0, 0x60000490, 0x70000480,
|
||||
0x80000470, 0x90000460, 0xa0000450, 0xb0000440, 0xc0000430, 0xd0000420, 0xe0000410, 0xf0000400};
|
||||
|
||||
/* now the cues, remember to change these tables if you change N_CUE
|
||||
*/
|
||||
unsigned char h_cue[34][N_CUE]={
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3},
|
||||
{0,3,5,5,6,6,7,7,8,8,8,8,8,8,8,8},
|
||||
{0,3,5,5,6,6,6,6,7,7,7,7,8,8,8,8},
|
||||
{0,8,12,12,13,13,14,14,15,15,15,15,15,15,15,15},
|
||||
{0,8,12,12,13,13,14,14,15,15,15,15,15,15,15,15},
|
||||
{0,5,7,9,10,11,12,12,13,13,13,13,14,14,15,15},
|
||||
{0,20,29,32,33,33,34,34,35,35,35,35,35,35,35,35},
|
||||
{0,23,30,31,32,32,32,32,33,33,34,34,35,35,35,35},
|
||||
{0,15,21,24,27,29,30,31,32,32,33,33,34,34,35,35},
|
||||
{0,42,56,60,61,61,62,62,63,63,63,63,63,63,63,63},
|
||||
{0,30,45,53,57,58,60,60,61,61,62,62,63,63,63,63},
|
||||
{0,23,37,46,50,54,56,57,58,60,61,61,62,62,63,63},
|
||||
{0,203,238,248,252,253,254,254,255,255,255,255,255,255,255,255},
|
||||
{0,132,178,205,223,233,240,245,248,250,252,252,253,254,255,255},
|
||||
{0,132,178,205,223,233,240,245,248,250,252,252,253,254,255,255},
|
||||
{0,162,231,248,252,253,254,254,255,255,255,255,255,255,255,255},
|
||||
{0,162,231,248,252,253,254,254,255,255,255,255,255,255,255,255},
|
||||
{0,162,231,248,252,253,254,254,255,255,255,255,255,255,255,255},
|
||||
{0,162,231,248,252,253,254,254,255,255,255,255,255,255,255,255},
|
||||
{0,162,231,248,252,253,254,254,255,255,255,255,255,255,255,255},
|
||||
{0,162,231,248,252,253,254,254,255,255,255,255,255,255,255,255},
|
||||
{0,162,231,248,252,253,254,254,255,255,255,255,255,255,255,255},
|
||||
{0,162,231,248,252,253,254,254,255,255,255,255,255,255,255,255},
|
||||
{0,13,22,58,59,131,177,209,226,238,245,249,252,253,254,255},
|
||||
{0,13,22,58,59,131,177,209,226,238,245,249,252,253,254,255},
|
||||
{0,13,22,58,59,131,177,209,226,238,245,249,252,253,254,255},
|
||||
{0,13,22,58,59,131,177,209,226,238,245,249,252,253,254,255},
|
||||
{0,13,22,58,59,131,177,209,226,238,245,249,252,253,254,255},
|
||||
{0,13,22,58,59,131,177,209,226,238,245,249,252,253,254,255},
|
||||
{0,13,22,58,59,131,177,209,226,238,245,249,252,253,254,255},
|
||||
{0,13,22,58,59,131,177,209,226,238,245,249,252,253,254,255},
|
||||
{0,4,7,9,11,12,13,14,15,15,15,15,15,15,15,15},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
|
||||
};
|
||||
|
||||
/* h4->h5, h14->h15 as suggested by Fraunhofer
|
||||
* tomislav Aug 21 1997
|
||||
*/
|
||||
unsigned int *tables[34]={h0,h1,h2,h3,h5,h5,h6,h7,h8,h9,h10,h11,h12,h13,h15,h15,
|
||||
h16,h16,h16,h16,h16,h16,h16,h16,h24,h24,h24,h24,h24,h24,h24,h24,hA,hB};
|
||||
#endif /* HUFFMAN */
|
324
Src/Sound/MPEG/layer2.cpp
Normal file
324
Src/Sound/MPEG/layer2.cpp
Normal file
|
@ -0,0 +1,324 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* layer2.c MPEG audio layer2 support
|
||||
*
|
||||
* Created by: Tomislav Uzelac Mar 1996
|
||||
* merged with amp, May 19 1997
|
||||
*/
|
||||
#include "amp.h"
|
||||
#include "audio.h"
|
||||
#include "getbits.h"
|
||||
#include "transform.h"
|
||||
|
||||
#define LAYER2
|
||||
#include "layer2.h"
|
||||
|
||||
int layer2_frame(struct AUDIO_HEADER *header,int cnt)
|
||||
{
|
||||
int i,s,sb,ch,gr,bitrate,bound=0;
|
||||
char (*nbal)[],(*bit_alloc_index)[][16];
|
||||
unsigned char allocation[2][32];
|
||||
unsigned char scfsi[2][32];
|
||||
float scalefactor[2][32][3];
|
||||
float subband_sample[2][32][36];
|
||||
int sblimit,nlevels,grouping;
|
||||
|
||||
float c,d;
|
||||
int no_of_bits,mpi;
|
||||
unsigned short sb_sample_buf[3];
|
||||
|
||||
int hsize,fs,mean_frame_size;
|
||||
|
||||
bit_alloc_index=(char (*)[][16])&t_alloc0;
|
||||
nbal=(char (*)[])&t_nbal0; // shut up compiler
|
||||
sblimit = 0;
|
||||
|
||||
hsize=4;
|
||||
if (header->protection_bit==0) hsize+=2;
|
||||
|
||||
bitrate=t_bitrate[header->ID][3-header->layer][header->bitrate_index];
|
||||
fs=t_sampling_frequency[header->ID][header->sampling_frequency];
|
||||
if (header->ID) mean_frame_size=144000*bitrate/fs;
|
||||
else mean_frame_size=72000*bitrate/fs;
|
||||
|
||||
/* layers 1 and 2 do not have a 'bit reservoir'
|
||||
*/
|
||||
append=data=0;
|
||||
|
||||
fillbfr(mean_frame_size + header->padding_bit - hsize);
|
||||
|
||||
switch (header->mode)
|
||||
{
|
||||
case 0 :
|
||||
case 2 : nch=2; bound=32; bitrate=bitrate/2;
|
||||
break;
|
||||
case 3 : nch=1; bound=32;
|
||||
break;
|
||||
case 1 : nch=2; bitrate=bitrate/2; bound=(header->mode_extension+1)*4;
|
||||
}
|
||||
|
||||
if (header->ID==1) switch (header->sampling_frequency) {
|
||||
case 0 : switch (bitrate) /* 0 = 44.1 kHz */
|
||||
{
|
||||
case 56 :
|
||||
case 64 :
|
||||
case 80 : bit_alloc_index=(char (*)[][16])&t_alloc0;
|
||||
nbal=(char (*)[])&t_nbal0;
|
||||
sblimit=27;
|
||||
break;
|
||||
case 96 :
|
||||
case 112 :
|
||||
case 128 :
|
||||
case 160 :
|
||||
case 192 : bit_alloc_index=(char (*)[][16])&t_alloc1;
|
||||
nbal=(char (*)[])&t_nbal1;
|
||||
sblimit=30;
|
||||
break;
|
||||
case 32 :
|
||||
case 48 : bit_alloc_index=(char (*)[][16])&t_alloc2;
|
||||
nbal=(char (*)[])&t_nbal2;
|
||||
sblimit=8;
|
||||
break;
|
||||
default : printf(" bit alloc info no gud ");
|
||||
}
|
||||
break;
|
||||
case 1 : switch (bitrate) /* 1 = 48 kHz */
|
||||
{
|
||||
case 56 :
|
||||
case 64 :
|
||||
case 80 :
|
||||
case 96 :
|
||||
case 112 :
|
||||
case 128 :
|
||||
case 160 :
|
||||
case 192 : bit_alloc_index=(char (*)[][16])&t_alloc0;
|
||||
nbal=(char (*)[])&t_nbal0;
|
||||
sblimit=27;
|
||||
break;
|
||||
case 32 :
|
||||
case 48 : bit_alloc_index=(char (*)[][16])&t_alloc2;
|
||||
nbal=(char (*)[])&t_nbal2;
|
||||
sblimit=8;
|
||||
break;
|
||||
default : printf(" bit alloc info no gud ");
|
||||
}
|
||||
break;
|
||||
case 2 : switch (bitrate) /* 2 = 32 kHz */
|
||||
{
|
||||
case 56 :
|
||||
case 64 :
|
||||
case 80 : bit_alloc_index=(char (*)[][16])&t_alloc0;
|
||||
nbal=(char (*)[])&t_nbal0;
|
||||
sblimit=27;
|
||||
break;
|
||||
case 96 :
|
||||
case 112 :
|
||||
case 128 :
|
||||
case 160 :
|
||||
case 192 : bit_alloc_index=(char (*)[][16])&t_alloc1;
|
||||
nbal=(char (*)[])&t_nbal1;
|
||||
sblimit=30;
|
||||
break;
|
||||
case 32 :
|
||||
case 48 : bit_alloc_index=(char (*)[][16])&t_alloc3;
|
||||
nbal=(char (*)[])&t_nbal3;
|
||||
sblimit=12;
|
||||
break;
|
||||
default : printf("bit alloc info not ok\n");
|
||||
}
|
||||
break;
|
||||
default : printf("sampling freq. not ok/n");
|
||||
} else {
|
||||
bit_alloc_index=(char (*)[][16])&t_allocMPG2;
|
||||
nbal=(char (*)[])&t_nbalMPG2;
|
||||
sblimit=30;
|
||||
}
|
||||
|
||||
/*
|
||||
* bit allocation per subband per channel decoding *****************************
|
||||
*/
|
||||
|
||||
if (bound==32) bound=sblimit; /* bound=32 means there is no intensity stereo */
|
||||
|
||||
for (sb=0;sb<bound;sb++)
|
||||
for (ch=0;ch<nch;ch++)
|
||||
allocation[ch][sb]=getbits((*nbal)[sb]);
|
||||
|
||||
for (sb=bound;sb<sblimit;sb++)
|
||||
allocation[1][sb] = allocation[0][sb] = getbits((*nbal)[sb]);
|
||||
|
||||
|
||||
/*
|
||||
* scfsi ***********************************************************************
|
||||
*/
|
||||
|
||||
for (sb=0;sb<sblimit;sb++)
|
||||
for (ch=0;ch<nch;ch++)
|
||||
if (allocation[ch][sb]!=0) scfsi[ch][sb]=getbits(2);
|
||||
else scfsi[ch][sb]=0;
|
||||
|
||||
/*
|
||||
* scalefactors ****************************************************************
|
||||
*/
|
||||
|
||||
for (sb=0;sb<sblimit;sb++)
|
||||
for (ch=0;ch<nch;ch++)
|
||||
if (allocation[ch][sb]!=0) {
|
||||
scalefactor[ch][sb][0]=(float)t_scalefactor[getbits(6)];
|
||||
switch (scfsi[ch][sb])
|
||||
{
|
||||
case 0: scalefactor[ch][sb][1]=(float)t_scalefactor[getbits(6)];
|
||||
scalefactor[ch][sb][2]=(float)t_scalefactor[getbits(6)];
|
||||
break;
|
||||
case 1: scalefactor[ch][sb][2]=(float)t_scalefactor[getbits(6)];
|
||||
scalefactor[ch][sb][1]=scalefactor[ch][sb][0];
|
||||
break;
|
||||
case 2: scalefactor[ch][sb][1]=(float)scalefactor[ch][sb][0];
|
||||
scalefactor[ch][sb][2]=scalefactor[ch][sb][0];
|
||||
break;
|
||||
case 3: scalefactor[ch][sb][2]=(float)t_scalefactor[getbits(6)];
|
||||
scalefactor[ch][sb][1]=scalefactor[ch][sb][2];
|
||||
}
|
||||
}
|
||||
else scalefactor[ch][sb][0]=scalefactor[ch][sb][1]=\
|
||||
scalefactor[ch][sb][2]=0.0;
|
||||
|
||||
|
||||
/*
|
||||
* samples *********************************************************************
|
||||
*/
|
||||
|
||||
for (gr=0;gr<12;gr++) {
|
||||
/*
|
||||
* normal ********************************
|
||||
*/
|
||||
|
||||
for (sb=0;sb<bound;sb++)
|
||||
for (ch=0;ch<nch;ch++)
|
||||
if (allocation[ch][sb]!=0) {
|
||||
mpi=(*bit_alloc_index)[sb][allocation[ch][sb]];
|
||||
no_of_bits=t_bpc[mpi];
|
||||
c=(float)t_c[mpi];
|
||||
d=(float)t_d[mpi];
|
||||
grouping=t_grouping[mpi];
|
||||
nlevels=t_nlevels[mpi];
|
||||
|
||||
if (grouping) {
|
||||
int samplecode=getbits(no_of_bits);
|
||||
convert_samplecode(samplecode,grouping,sb_sample_buf);
|
||||
|
||||
for (s=0;s<3;s++)
|
||||
subband_sample[ch][sb][3*gr+s]=requantize_sample (sb_sample_buf[s],nlevels,c,d,scalefactor[ch][sb][gr/4]);
|
||||
} else {
|
||||
for (s=0;s<3;s++) sb_sample_buf[s]=getbits(no_of_bits);
|
||||
|
||||
for (s=0;s<3;s++) {
|
||||
/*subband_sample[ch][sb][3*gr+s]=requantize_sample (sb_sample_buf[s],nlevels,c,d,scalefactor[ch][sb][gr/4]);*/
|
||||
subband_sample[ch][sb][3*gr+s]=(t_dd[mpi]+sb_sample_buf[s]*t_nli[mpi])*c*scalefactor[ch][sb][gr>>2];
|
||||
}
|
||||
}
|
||||
} else
|
||||
for (s=0;s<3;s++) subband_sample[ch][sb][3*gr+s]=0;
|
||||
|
||||
|
||||
/*
|
||||
* joint stereo ********************************************
|
||||
*/
|
||||
|
||||
for (sb=bound;sb<sblimit;sb++)
|
||||
if (allocation[0][sb]!=0) {
|
||||
/*ispravka!
|
||||
*/
|
||||
mpi=(*bit_alloc_index)[sb][allocation[0][sb]];
|
||||
no_of_bits=t_bpc[mpi];
|
||||
c=(float)t_c[mpi];
|
||||
d=(float)t_d[mpi];
|
||||
grouping=t_grouping[mpi];
|
||||
nlevels=t_nlevels[mpi];
|
||||
|
||||
if (grouping) {
|
||||
int samplecode=getbits(no_of_bits);
|
||||
convert_samplecode(samplecode,grouping,sb_sample_buf);
|
||||
|
||||
for (s=0;s<3;s++) {
|
||||
subband_sample[0][sb][3*gr+s]=requantize_sample (sb_sample_buf[s],nlevels,c,d,scalefactor[0][sb][gr/4]);
|
||||
subband_sample[1][sb][3*gr+s]=subband_sample[0][sb][3*gr+s];
|
||||
}
|
||||
} else {
|
||||
for (s=0;s<3;s++) sb_sample_buf[s]=getbits(no_of_bits);
|
||||
|
||||
for (s=0;s<3;s++) {
|
||||
subband_sample[0][sb][3*gr+s]=subband_sample[1][sb][3*gr+s]=\
|
||||
(t_dd[mpi]+sb_sample_buf[s]*t_nli[mpi])*c*scalefactor[0][sb][gr>>2];
|
||||
}
|
||||
}
|
||||
|
||||
} else for (s=0;s<3;s++) {
|
||||
subband_sample[0][sb][3*gr+s]=0;
|
||||
subband_sample[1][sb][3*gr+s]=0;
|
||||
}
|
||||
|
||||
/*
|
||||
* the rest *******************************************
|
||||
*/
|
||||
for (sb=sblimit;sb<32;sb++)
|
||||
for (ch=0;ch<nch;ch++)
|
||||
|
||||
for (s=0;s<3;s++) subband_sample[ch][sb][3*gr+s]=0;
|
||||
}
|
||||
|
||||
/*
|
||||
* this is, in fact, horrible, but I had to adjust it to amp/mp3. The hack to make downmixing
|
||||
* work is as ugly as possible.
|
||||
*/
|
||||
|
||||
if (A_DOWNMIX && header->mode!=3) {
|
||||
for (ch=0;ch<nch;ch++)
|
||||
for (sb=0;sb<32;sb++)
|
||||
for (i=0;i<36;i++)
|
||||
subband_sample[0][sb][i]=(subband_sample[0][sb][i]+subband_sample[1][sb][i])*0.5f;
|
||||
nch=1;
|
||||
}
|
||||
|
||||
for (ch=0;ch<nch;ch++) {
|
||||
for (sb=0;sb<32;sb++)
|
||||
for (i=0;i<18;i++) res[sb][i]=subband_sample[ch][sb][i];
|
||||
for (i=0;i<18;i++)
|
||||
poly(ch,i);
|
||||
}
|
||||
printout();
|
||||
for (ch=0;ch<nch;ch++) {
|
||||
for (sb=0;sb<32;sb++)
|
||||
for (i=0;i<18;i++) res[sb][i]=subband_sample[ch][sb][i+18];
|
||||
for (i=0;i<18;i++)
|
||||
poly(ch,i);
|
||||
}
|
||||
printout();
|
||||
|
||||
if (A_DOWNMIX && header->mode!=3) nch=2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/****************************************************************************/
|
||||
/****************************************************************************/
|
||||
|
||||
void convert_samplecode(unsigned int samplecode,unsigned int nlevels,unsigned short* sb_sample_buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<3;i++) {
|
||||
*sb_sample_buf=samplecode%nlevels;
|
||||
samplecode=samplecode/nlevels;
|
||||
sb_sample_buf++;
|
||||
}
|
||||
}
|
||||
|
||||
float requantize_sample(unsigned short s4,unsigned short nlevels,float c,float d,float factor)
|
||||
{
|
||||
register float s,s2,s3;
|
||||
s3=(float) (-1.0+s4*2.0/(nlevels+1));
|
||||
s2=c*(s3+d);
|
||||
s=factor*s2;
|
||||
return s;
|
||||
}
|
190
Src/Sound/MPEG/layer2.h
Normal file
190
Src/Sound/MPEG/layer2.h
Normal file
|
@ -0,0 +1,190 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
/* layer2.h
|
||||
* Tomislav Uzelac - cca. Feb 1996
|
||||
*/
|
||||
|
||||
|
||||
extern int layer2_frame(struct AUDIO_HEADER *header,int cnt);
|
||||
|
||||
#ifdef LAYER2
|
||||
|
||||
int layer2_frame(struct AUDIO_HEADER *header,int cnt);
|
||||
float requantize_sample(unsigned short s4,unsigned short nlevels,float c,float d,float factor);
|
||||
void convert_samplecode(unsigned int samplecode,unsigned int nlevels,unsigned short* sb_sample_buf);
|
||||
|
||||
char t_nbal0[27]={4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2};
|
||||
char t_nbal1[30]={4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2};
|
||||
char t_nbal2[8] ={4,4,3,3,3,3,3,3};
|
||||
char t_nbal3[12]={4,4,3,3,3,3,3,3,3,3,3,3};
|
||||
char t_nbalMPG2[30]={4,4,4,4,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};
|
||||
|
||||
char t_alloc0[27][16] = { /* table B.2a ISO/IEC 11172-3 */
|
||||
{0,1,3,5,6,7,8,9,10,11,12,13,14,15,16,17},
|
||||
{0,1,3,5,6,7,8,9,10,11,12,13,14,15,16,17},
|
||||
{0,1,3,5,6,7,8,9,10,11,12,13,14,15,16,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,17},
|
||||
{0,1,2,17},
|
||||
{0,1,2,17},
|
||||
{0,1,2,17}};
|
||||
|
||||
char t_alloc1[30][16] = { /* table B.2b ISO/IEC 11172-3 */
|
||||
{0,1,3,5,6,7,8,9,10,11,12,13,14,15,16,17},
|
||||
{0,1,3,5,6,7,8,9,10,11,12,13,14,15,16,17},
|
||||
{0,1,3,5,6,7,8,9,10,11,12,13,14,15,16,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,3,4,5,6,17},
|
||||
{0,1,2,17},
|
||||
{0,1,2,17},
|
||||
{0,1,2,17},
|
||||
{0,1,2,17},
|
||||
{0,1,2,17},
|
||||
{0,1,2,17},
|
||||
{0,1,2,17}};
|
||||
|
||||
char t_alloc2[8][16] = { /* table B.2c ISO/IEC 11172-3 */
|
||||
{0,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16},
|
||||
{0,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127}};
|
||||
|
||||
char t_alloc3[12][16] = { /* table B.2d ISO/IEC 11172-3 */
|
||||
{0,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16},
|
||||
{0,1,2,4,5,6,7,8,9,10,11,12,13,14,15,16},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127},
|
||||
{0,1,2,4,5,6,7,127}};
|
||||
|
||||
char t_allocMPG2[30][16] = { /* table B.1. ISO/IEC 13818-3 */
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
|
||||
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
|
||||
{0,1,2,4,5,6,7,8},
|
||||
{0,1,2,4,5,6,7,8},
|
||||
{0,1,2,4,5,6,7,8},
|
||||
{0,1,2,4,5,6,7,8},
|
||||
{0,1,2,4,5,6,7,8},
|
||||
{0,1,2,4,5,6,7,8},
|
||||
{0,1,2,4,5,6,7,8},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4},
|
||||
{0,1,2,4}};
|
||||
|
||||
double t_scalefactor[64] = {
|
||||
2.00000000000000, 1.58740105196820, 1.25992104989487,
|
||||
1.00000000000000, 0.79370052598410, 0.62996052494744, 0.50000000000000,
|
||||
0.39685026299205, 0.31498026247372, 0.25000000000000, 0.19842513149602,
|
||||
0.15749013123686, 0.12500000000000, 0.09921256574801, 0.07874506561843,
|
||||
0.06250000000000, 0.04960628287401, 0.03937253280921, 0.03125000000000,
|
||||
0.02480314143700, 0.01968626640461, 0.01562500000000, 0.01240157071850,
|
||||
0.00984313320230, 0.00781250000000, 0.00620078535925, 0.00492156660115,
|
||||
0.00390625000000, 0.00310039267963, 0.00246078330058, 0.00195312500000,
|
||||
0.00155019633981, 0.00123039165029, 0.00097656250000, 0.00077509816991,
|
||||
0.00061519582514, 0.00048828125000, 0.00038754908495, 0.00030759791257,
|
||||
0.00024414062500, 0.00019377454248, 0.00015379895629, 0.00012207031250,
|
||||
0.00009688727124, 0.00007689947814, 0.00006103515625, 0.00004844363562,
|
||||
0.00003844973907, 0.00003051757813, 0.00002422181781, 0.00001922486954,
|
||||
0.00001525878906, 0.00001211090890, 0.00000961243477, 0.00000762939453,
|
||||
0.00000605545445, 0.00000480621738, 0.00000381469727, 0.00000302772723,
|
||||
0.00000240310869, 0.00000190734863, 0.00000151386361, 0.00000120155435,
|
||||
1E-20};
|
||||
|
||||
double t_c[18] = { 0,
|
||||
1.33333333333, 1.60000000000, 1.14285714286,
|
||||
1.77777777777, 1.06666666666, 1.03225806452,
|
||||
1.01587301587, 1.00787401575, 1.00392156863,
|
||||
1.00195694716, 1.00097751711, 1.00048851979,
|
||||
1.00024420024, 1.00012208522, 1.00006103888,
|
||||
1.00003051851, 1.00001525902 };
|
||||
|
||||
double t_d[18] = {0,
|
||||
0.500000000, 0.500000000, 0.250000000, 0.500000000,
|
||||
0.125000000, 0.062500000, 0.031250000, 0.015625000,
|
||||
0.007812500, 0.003906250, 0.001953125, 0.0009765625,
|
||||
0.00048828125,0.00024414063,0.00012207031,
|
||||
0.00006103516,0.00003051758 };
|
||||
|
||||
float t_dd[18]={ -1.0f, -0.5f, -0.5f, -0.75f, -0.5f, -0.875f, -0.9375f, -0.96875f, -0.984375f,
|
||||
-0.992188f, -0.996094f, -0.998047f, -0.999023f, -0.999512f, -0.999756f, -0.999878f, -0.999939f,
|
||||
-0.999969f};
|
||||
|
||||
char t_grouping[18]={0,3,5,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
/*
|
||||
int t_nlevels[18] = {0,3,5,7,9,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535};
|
||||
*/
|
||||
int t_nlevels[18] = {0,3,7,7,15,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535};
|
||||
|
||||
|
||||
float t_nli[18]={ 0.0f, 0.5f, 0.25f, 0.25f, 0.125f, 0.125f, 0.0625f, 0.03125f, 0.015625f, 0.0078125f, 0.00390625f,
|
||||
0.00195313f, 0.000976563f, 0.000488281f, 0.000244141f, 0.00012207f, 6.10352e-05f, 3.05176e-05f};
|
||||
|
||||
int t_bpc[18] = {0,5,7,3,10,4,5,6,7,8,9,10,11,12,13,14,15,16};
|
||||
|
||||
#endif /* LAYER2 */
|
197
Src/Sound/MPEG/layer3.cpp
Normal file
197
Src/Sound/MPEG/layer3.cpp
Normal file
|
@ -0,0 +1,197 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* layer3.c layer3 audio decoding
|
||||
*
|
||||
* Created by: tomislav uzelac Mar 1 97
|
||||
* Last modified by:
|
||||
*/
|
||||
#include "amp.h"
|
||||
#include "audio.h"
|
||||
#include "dump.h"
|
||||
#include "getbits.h"
|
||||
#include "getdata.h"
|
||||
#include "huffman.h"
|
||||
#include "misc2.h"
|
||||
#include "rtbuf.h"
|
||||
#include "transform.h"
|
||||
|
||||
#define LAYER3
|
||||
#include "layer3.h"
|
||||
|
||||
void requantize_downmix(int gr,struct SIDE_INFO *info,struct AUDIO_HEADER *header);
|
||||
|
||||
/* this function decodes one layer3 audio frame, except for the header decoding
|
||||
* which is done in main() [audio.c]. returns 0 if everything is ok.
|
||||
*/
|
||||
int layer3_frame(struct AUDIO_HEADER *header,int cnt)
|
||||
{
|
||||
static struct SIDE_INFO info;
|
||||
|
||||
int gr,ch,sb,i;
|
||||
int mean_frame_size,bitrate,fs,hsize,ssize;
|
||||
|
||||
/* we need these later, hsize is the size of header+side_info
|
||||
*/
|
||||
if (header->ID)
|
||||
if (header->mode==3) {
|
||||
nch=1;
|
||||
hsize=21;
|
||||
} else {
|
||||
nch=2;
|
||||
hsize=36;
|
||||
}
|
||||
else
|
||||
if (header->mode==3) {
|
||||
nch=1;
|
||||
hsize=13;
|
||||
} else {
|
||||
nch=2;
|
||||
hsize=21;
|
||||
}
|
||||
|
||||
/* crc increases hsize by 2
|
||||
*/
|
||||
if (header->protection_bit==0) hsize+=2;
|
||||
|
||||
|
||||
/* read layer3 specific side_info
|
||||
*/
|
||||
getinfo(header,&info);
|
||||
|
||||
|
||||
/* MPEG2 only has one granule
|
||||
*/
|
||||
bitrate=t_bitrate[header->ID][3-header->layer][header->bitrate_index];
|
||||
fs=t_sampling_frequency[header->ID][header->sampling_frequency];
|
||||
if (header->ID) mean_frame_size=144000*bitrate/fs;
|
||||
else mean_frame_size=72000*bitrate/fs;
|
||||
|
||||
|
||||
/* check if mdb is too big for the first few frames. this means that
|
||||
* a part of the stream could be missing. We must still fill the buffer
|
||||
*
|
||||
* don't forget to (re)initialise bclean_bytes to 0, and f_bdirty to FALSE!!!
|
||||
*/
|
||||
if (f_bdirty)
|
||||
{
|
||||
if (info.main_data_begin > bclean_bytes) {
|
||||
fillbfr(mean_frame_size + header->padding_bit - hsize);
|
||||
bclean_bytes+=mean_frame_size + header->padding_bit - hsize;
|
||||
/* warn(" frame %d discarded, incomplete main_data\n",cnt); */
|
||||
return 0;
|
||||
} else {
|
||||
/* re-initialise */
|
||||
f_bdirty=FALSE;
|
||||
bclean_bytes=0;
|
||||
}
|
||||
}
|
||||
|
||||
/* now update the data 'pointer' (counting in bits) according to
|
||||
* the main_data_begin information
|
||||
*/
|
||||
data = 8 * ((append - info.main_data_begin) & (BUFFER_SIZE-1));
|
||||
|
||||
|
||||
/* read into the buffer all bytes up to the start of next header
|
||||
*/
|
||||
fillbfr(mean_frame_size + header->padding_bit - hsize);
|
||||
|
||||
|
||||
/* these two should go away
|
||||
*/
|
||||
t_l=&t_b8_l[header->ID][header->sampling_frequency][0];
|
||||
t_s=&t_b8_s[header->ID][header->sampling_frequency][0];
|
||||
|
||||
/* debug/dump stuff
|
||||
*/
|
||||
if (A_DUMP_BINARY) dump((int *)info.part2_3_length);
|
||||
|
||||
/* decode the scalefactors and huffman data
|
||||
* this part needs to be enhanced for error robustness
|
||||
*/
|
||||
for (gr=0;gr < ((header->ID) ? 2 : 1);gr++) {
|
||||
for (ch=0;ch<nch;ch++) {
|
||||
ssize=decode_scalefactors(&info,header,gr,ch);
|
||||
decode_huffman_data(&info,gr,ch,ssize);
|
||||
}
|
||||
|
||||
/* requantization, stereo processing, reordering(shortbl)
|
||||
*/
|
||||
|
||||
if (A_DOWNMIX && nch==2) requantize_downmix(gr,&info,header);
|
||||
else
|
||||
if (header->mode!=1 || (header->mode==1 && header->mode_extension==0))
|
||||
for (ch=0;ch<nch;ch++) requantize_mono(gr,ch,&info,header);
|
||||
else requantize_ms(gr,&info,header);
|
||||
|
||||
/* just which window?
|
||||
*/
|
||||
|
||||
/* this is a very temporary, very ugly hack.
|
||||
*/
|
||||
if (A_DOWNMIX) nch=1;
|
||||
|
||||
for (ch=0; ch < (A_DOWNMIX ? 1:nch) ;ch++) {
|
||||
int win_type; /* same as in the standard, long=0, start=1 ,.... */
|
||||
int window_switching_flag = info.window_switching_flag[gr][ch];
|
||||
int block_type = info.block_type[gr][ch];
|
||||
int mixed_block_flag = info.mixed_block_flag[gr][ch];
|
||||
|
||||
/* antialiasing butterflies
|
||||
*/
|
||||
if (!(window_switching_flag &&
|
||||
block_type==2))
|
||||
alias_reduction(ch);
|
||||
|
||||
if (window_switching_flag &&
|
||||
block_type==2 &&
|
||||
mixed_block_flag)
|
||||
win_type=0;
|
||||
else
|
||||
if (!window_switching_flag) win_type=0;
|
||||
else win_type=block_type;
|
||||
|
||||
/* imdct ...
|
||||
*/
|
||||
for (sb=0;sb<2;sb++)
|
||||
imdct(win_type,sb,ch);
|
||||
|
||||
if (window_switching_flag &&
|
||||
block_type==2 &&
|
||||
mixed_block_flag)
|
||||
win_type=2;
|
||||
|
||||
/* no_of_imdcts tells us how many subbands from the top are all zero
|
||||
* it is set by the requantize functions in misc2.c
|
||||
*/
|
||||
for (sb=2;sb<no_of_imdcts[ch];sb++)
|
||||
imdct(win_type,sb,ch);
|
||||
|
||||
for (;sb<32;sb++)
|
||||
for (i=0;i<18;i++) {
|
||||
res[sb][i]=s[ch][sb][i];
|
||||
s[ch][sb][i]=0.0f;
|
||||
}
|
||||
|
||||
/* polyphase filterbank
|
||||
*/
|
||||
/* if (nch == 2) this was a bug, tomislav */
|
||||
for (i=0;i<18;i++)
|
||||
poly(ch,i);
|
||||
}
|
||||
|
||||
printout();
|
||||
|
||||
/* this is part2 of a particularily ugly hack. this should vanish as soon as nch isn't
|
||||
a global variable anymore
|
||||
*/
|
||||
if (A_DOWNMIX && header->mode!=3) nch=2;
|
||||
|
||||
} /* for (gr... */
|
||||
|
||||
/* return status: 0 for ok, errors will be added
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
16
Src/Sound/MPEG/layer3.h
Normal file
16
Src/Sound/MPEG/layer3.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* layer3.h
|
||||
*
|
||||
* Created by: tomislav uzelac Mar 1 97
|
||||
* Last modified by:
|
||||
*/
|
||||
|
||||
extern int layer3_frame(struct AUDIO_HEADER *header,int cnt);
|
||||
|
||||
#ifdef LAYER3
|
||||
|
||||
int layer3_frame(struct AUDIO_HEADER *header,int cnt);
|
||||
|
||||
#endif /* LAYER3 */
|
822
Src/Sound/MPEG/misc2.cpp
Normal file
822
Src/Sound/MPEG/misc2.cpp
Normal file
|
@ -0,0 +1,822 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* misc2.c requantization, stereo processing, reordering(shortbl) and antialiasing butterflies
|
||||
*
|
||||
* misc.c was created by tomislav uzelac in May 1996, and was completely awful
|
||||
* Created by: tomislav uzelac Dec 22 1996
|
||||
* some more speed injected, cca. Jun 1 1997
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "amp.h"
|
||||
#include "audio.h"
|
||||
#include "getdata.h"
|
||||
#include "huffman.h"
|
||||
|
||||
#define MISC2
|
||||
#include "misc2.h"
|
||||
|
||||
/*
|
||||
* fras == Formula for Requantization and All Scaling **************************
|
||||
*/
|
||||
static inline float fras_l(int sfb,int global_gain,int scalefac_scale,int scalefac,int preflag)
|
||||
{
|
||||
register int a,scale;
|
||||
/*
|
||||
if (scalefac_scale) scale=2;
|
||||
else scale=1;
|
||||
*/
|
||||
scale=scalefac_scale+1;
|
||||
a= global_gain -210 -(scalefac << scale);
|
||||
if (preflag) a-=(t_pretab[sfb] << scale);
|
||||
|
||||
/* bugfix, Mar 13 97: shifting won't produce a legal result if we shift by more than 31
|
||||
* since global_gain<256, this can only occur for (very) negative values of a.
|
||||
*/
|
||||
if (a < -127) return 0;
|
||||
|
||||
/* a minor change here as well, no point in abs() if we now that a<0
|
||||
*/
|
||||
if (a>=0) return tab[a&3]*(1 << (a>>2));
|
||||
else return tabi[(-a)&3]/(1 << ((-a) >> 2));
|
||||
}
|
||||
|
||||
static inline float fras_s(int global_gain,int subblock_gain,int scalefac_scale,int scalefac)
|
||||
{
|
||||
int a;
|
||||
a=global_gain - 210 - (subblock_gain << 3);
|
||||
if (scalefac_scale) a-= (scalefac << 2);
|
||||
else a-= (scalefac << 1);
|
||||
|
||||
if (a < -127) return 0;
|
||||
|
||||
if (a>=0) return tab[a&3]*(1 << (a>>2));
|
||||
else return tabi[(-a)&3]/(1 << ((-a) >> 2));
|
||||
}
|
||||
|
||||
/* this should be faster than pow()
|
||||
*/
|
||||
static inline float fras2(int is,float a)
|
||||
{
|
||||
if (is > 0) return t_43[is]*a;
|
||||
else return -t_43[-is]*a;
|
||||
}
|
||||
|
||||
/*
|
||||
* requantize_mono *************************************************************
|
||||
*/
|
||||
|
||||
/* generally, the two channels do not have to be of the same block type - that's why we do two passes with requantize_mono.
|
||||
* if ms or intensity stereo is enabled we do a single pass with requantize_ms because both channels are same block type
|
||||
*/
|
||||
|
||||
void requantize_mono(int gr,int ch,struct SIDE_INFO *info,struct AUDIO_HEADER *header)
|
||||
{
|
||||
int l,i,sfb;
|
||||
float a;
|
||||
int global_gain=info->global_gain[gr][ch];
|
||||
int scalefac_scale=info->scalefac_scale[gr][ch];
|
||||
int sfreq=header->sampling_frequency;
|
||||
|
||||
|
||||
no_of_imdcts[0]=no_of_imdcts[1]=32;
|
||||
|
||||
if (info->window_switching_flag[gr][ch] && info->block_type[gr][ch]==2)
|
||||
if (info->mixed_block_flag[gr][ch]) {
|
||||
/*
|
||||
* requantize_mono - mixed blocks/long block part **********************
|
||||
*/
|
||||
int window,window_len,preflag=0; /* pretab is all zero in this low frequency area */
|
||||
int scalefac=scalefac_l[gr][ch][0];
|
||||
|
||||
l=0;sfb=0;
|
||||
a=fras_l(sfb,global_gain,scalefac_scale,scalefac,preflag);
|
||||
while (l<36) {
|
||||
xr[ch][0][l]=fras2(is[ch][l],a);
|
||||
if (l==t_l[sfb]) {
|
||||
scalefac=scalefac_l[gr][ch][++sfb];
|
||||
a=fras_l(sfb,global_gain,scalefac_scale,scalefac,preflag);
|
||||
}
|
||||
l++;
|
||||
}
|
||||
/*
|
||||
* requantize_mono - mixed blocks/short block part *********************
|
||||
*/
|
||||
sfb=3;
|
||||
window_len=t_s[sfb]-t_s[sfb-1];
|
||||
while (l<non_zero[ch]) {
|
||||
for (window=0;window<3;window++) {
|
||||
int scalefac=scalefac_s[gr][ch][sfb][window];
|
||||
int subblock_gain=info->subblock_gain[gr][ch][window];
|
||||
a=fras_s(global_gain,subblock_gain,scalefac_scale,scalefac);
|
||||
for (i=0;i<window_len;i++) {
|
||||
xr[ch][0][t_reorder[header->ID][sfreq][l]]=fras2(is[ch][l],a);
|
||||
l++;
|
||||
}
|
||||
}
|
||||
sfb++;
|
||||
window_len=t_s[sfb]-t_s[sfb-1];
|
||||
}
|
||||
while (l<576) xr[ch][0][t_reorder[header->ID][sfreq][l++]]=0;
|
||||
} else {
|
||||
/*
|
||||
* requantize mono - short blocks **************************************
|
||||
*/
|
||||
int window,window_len;
|
||||
|
||||
sfb=0; l=0;
|
||||
window_len=t_s[0]+1;
|
||||
while (l<non_zero[ch]) {
|
||||
for (window=0;window<3;window++) {
|
||||
int scalefac=scalefac_s[gr][ch][sfb][window];
|
||||
int subblock_gain=info->subblock_gain[gr][ch][window];
|
||||
float a=fras_s(global_gain,subblock_gain,scalefac_scale,scalefac);
|
||||
for (i=0;i<window_len;i++) {
|
||||
xr[ch][0][t_reorder[header->ID][sfreq][l]]=fras2(is[ch][l],a);
|
||||
l++;
|
||||
}
|
||||
}
|
||||
sfb++;
|
||||
window_len=t_s[sfb]-t_s[sfb-1];
|
||||
}
|
||||
while (l<576) xr[ch][0][t_reorder[header->ID][sfreq][l++]]=0;
|
||||
}
|
||||
else {
|
||||
/* long blocks */
|
||||
int preflag=info->preflag[gr][ch];
|
||||
int scalefac=scalefac_l[gr][ch][0];
|
||||
|
||||
sfb=0; l=0;
|
||||
a=fras_l(sfb,global_gain,scalefac_scale,scalefac,preflag);
|
||||
while (l<non_zero[ch]) {
|
||||
xr[ch][0][l]=fras2(is[ch][l],a);
|
||||
if (l==t_l[sfb]) {
|
||||
scalefac=scalefac_l[gr][ch][++sfb];
|
||||
a=fras_l(sfb,global_gain,scalefac_scale,scalefac,preflag);
|
||||
}
|
||||
l++;
|
||||
}
|
||||
while (l<576) xr[ch][0][l++]=0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* stereo stuff ****************************************************************
|
||||
*/
|
||||
static int find_isbound(int isbound[3],int gr,struct SIDE_INFO *info,struct AUDIO_HEADER *header)
|
||||
{
|
||||
int sfb,window,window_len,ms_flag,tmp,i;
|
||||
|
||||
isbound[0]=isbound[1]=isbound[2]=-1;
|
||||
no_of_imdcts[0]=no_of_imdcts[1]=32;
|
||||
|
||||
if (header->mode_extension==1 || header->mode_extension==3) {
|
||||
if (info->window_switching_flag[gr][0] && info->block_type[gr][0]==2) {
|
||||
|
||||
/* find that isbound!
|
||||
*/
|
||||
tmp=non_zero[1];
|
||||
sfb=0; while ((3*t_s[sfb]+2) < tmp && sfb < 12) sfb++;
|
||||
while ((isbound[0]<0 || isbound[1]<0 || isbound[2]<0) && !(info->mixed_block_flag[gr][0] && sfb<3) && sfb) {
|
||||
for (window=0;window<3;window++) {
|
||||
if (sfb==0) {
|
||||
window_len=t_s[0]+1;
|
||||
tmp=(window+1)*window_len - 1;
|
||||
} else {
|
||||
window_len=t_s[sfb]-t_s[sfb-1];
|
||||
tmp=(3*t_s[sfb-1]+2) + (window+1)*window_len;
|
||||
}
|
||||
if (isbound[window] < 0)
|
||||
for (i=0;i<window_len;i++)
|
||||
if (is[1][tmp--] != 0) {
|
||||
isbound[window]=t_s[sfb]+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sfb--;
|
||||
}
|
||||
|
||||
/* mixed block magic now...
|
||||
*/
|
||||
if (sfb==2 && info->mixed_block_flag[gr][0])
|
||||
{
|
||||
if (isbound[0]<0 && isbound[1]<0 && isbound[2]<0)
|
||||
{
|
||||
tmp=35;
|
||||
while (is[1][tmp] == 0) tmp--;
|
||||
sfb=0; while (t_l[sfb] < tmp && sfb < 21) sfb++;
|
||||
isbound[0]=isbound[1]=isbound[2]=t_l[sfb]+1;
|
||||
}
|
||||
else for (window=0;window<3;window++)
|
||||
if (isbound[window]<0) isbound[window]=36;
|
||||
}
|
||||
if (header->ID==1) isbound[0]=isbound[1]=isbound[2]=MAX(isbound[0],MAX(isbound[1],isbound[2]));
|
||||
|
||||
/* just how many imdcts?
|
||||
*/
|
||||
tmp=non_zero[0];
|
||||
sfb=0; while ((3*t_s[sfb]+2) < tmp && sfb < 12) sfb++;
|
||||
no_of_imdcts[0]=no_of_imdcts[1]=(t_s[sfb]-1)/6+1;
|
||||
} else {
|
||||
|
||||
/* long blocks now
|
||||
*/
|
||||
tmp=non_zero[1];
|
||||
while (is[1][tmp] == 0) tmp--;
|
||||
sfb=0; while (t_l[sfb] < tmp && sfb < 21) sfb++;
|
||||
isbound[0]=isbound[1]=isbound[2]=t_l[sfb]+1;
|
||||
no_of_imdcts[0]=no_of_imdcts[1]=(non_zero[0]-1)/18+1;
|
||||
}
|
||||
if (header->mode_extension==1) ms_flag=0;
|
||||
else ms_flag=1;
|
||||
} else {
|
||||
|
||||
/* intensity stereo is, regretably, turned off
|
||||
*/
|
||||
ms_flag=1;
|
||||
|
||||
/* i really put a lot of work in this, but it still looks like shit (works, though)
|
||||
*/
|
||||
if (!info->window_switching_flag[gr][0] || (info->window_switching_flag[gr][0] && info->block_type[gr][0]!=2))
|
||||
isbound[0]=isbound[1]=isbound[2]=(MAX(non_zero[0],non_zero[1]));
|
||||
else isbound[0]=isbound[1]=isbound[2]=576;
|
||||
|
||||
if (info->window_switching_flag[gr][0] && info->block_type[gr][0]==2) {
|
||||
/* should do for mixed blocks too, though i havent tested... */
|
||||
tmp=(MAX(non_zero[0],non_zero[1]))/3;
|
||||
sfb=0; while (t_s[sfb]<tmp && sfb<12) sfb++;
|
||||
no_of_imdcts[0]=no_of_imdcts[1]=(t_s[sfb]-1)/6+1;
|
||||
}
|
||||
else no_of_imdcts[0]=no_of_imdcts[1]=(isbound[0]-1)/18+1;
|
||||
|
||||
}
|
||||
|
||||
return ms_flag;
|
||||
}
|
||||
|
||||
static inline void stereo_s(int l,float a[2],int pos,int ms_flag,int is_pos,struct AUDIO_HEADER *header)
|
||||
{
|
||||
float ftmp,Mi,Si;
|
||||
|
||||
if (l>=576) return; /* brrr... */
|
||||
|
||||
if ((is_pos != IS_ILLEGAL) && (header->ID==1)) {
|
||||
ftmp=fras2(is[0][l],a[0]);
|
||||
xr[0][0][pos]=(1-t_is[is_pos])*ftmp;
|
||||
xr[1][0][pos]=t_is[is_pos]*ftmp;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((is_pos != IS_ILLEGAL) && (header->ID==0)) {
|
||||
ftmp=fras2(is[0][l],a[0]);
|
||||
if (is_pos&1) {
|
||||
xr[0][0][pos]= t_is2[intensity_scale][(is_pos+1)>>1] * ftmp;
|
||||
xr[1][0][pos]= ftmp;
|
||||
} else {
|
||||
xr[0][0][pos]= ftmp;
|
||||
xr[1][0][pos]= t_is2[intensity_scale][is_pos>>1] * ftmp;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ms_flag) {
|
||||
Mi=fras2(is[0][l],a[0]);
|
||||
Si=fras2(is[1][l],a[1]);
|
||||
xr[0][0][pos]=(Mi+Si)*i_sq2;
|
||||
xr[1][0][pos]=(Mi-Si)*i_sq2;
|
||||
} else {
|
||||
xr[0][0][pos]=fras2(is[0][l],a[0]);
|
||||
xr[1][0][pos]=fras2(is[1][l],a[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void stereo_l(int l,float a[2],int ms_flag,int is_pos,struct AUDIO_HEADER *header)
|
||||
{
|
||||
float ftmp,Mi,Si;
|
||||
if (l>=576) return;
|
||||
|
||||
/* new code by ???
|
||||
*/
|
||||
if (is_pos != IS_ILLEGAL) {
|
||||
ftmp = fras2(is[0][l], a[0]);
|
||||
if (header -> ID ==1) {
|
||||
xr[0][0][l] = (1 - t_is[is_pos]) * ftmp;
|
||||
xr[1][0][l] = t_is[is_pos] * ftmp;
|
||||
return;
|
||||
} else if (is_pos & 1) {
|
||||
xr[0][0][l] = t_is2[intensity_scale][(is_pos + 1) >> 1] * ftmp;
|
||||
xr[1][0][l] = ftmp;
|
||||
} else {
|
||||
xr[0][0][l] = ftmp;
|
||||
xr[1][0][l] = t_is2[intensity_scale][is_pos >> 1] * ftmp;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ms_flag) {
|
||||
Mi=fras2(is[0][l],a[0]);
|
||||
Si=fras2(is[1][l],a[1]);
|
||||
xr[0][0][l]=(Mi+Si)*i_sq2;
|
||||
xr[1][0][l]=(Mi-Si)*i_sq2;
|
||||
} else {
|
||||
xr[0][0][l]=fras2(is[0][l],a[0]);
|
||||
xr[1][0][l]=fras2(is[1][l],a[1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* requantize_ms ***************************************************************
|
||||
*/
|
||||
void requantize_ms(int gr,struct SIDE_INFO *info,struct AUDIO_HEADER *header)
|
||||
{
|
||||
int l,sfb,ms_flag,is_pos,i,ch;
|
||||
int *global_gain,subblock_gain[2],*scalefac_scale,scalefac[2],isbound[3];
|
||||
int sfreq=header->sampling_frequency;
|
||||
int id = header->ID;
|
||||
float a[2];
|
||||
|
||||
memset(a, 0, sizeof(a));
|
||||
|
||||
global_gain=info->global_gain[gr];
|
||||
scalefac_scale=info->scalefac_scale[gr];
|
||||
|
||||
if (info->window_switching_flag[gr][0] && info->block_type[gr][0]==2)
|
||||
if (info->mixed_block_flag[gr][0]) {
|
||||
/*
|
||||
* mixed blocks w/stereo processing - long block part ******************
|
||||
*/
|
||||
int window,window_len;
|
||||
int preflag[2]={0,0};
|
||||
|
||||
ms_flag=find_isbound(isbound,gr,info,header);
|
||||
|
||||
sfb=0; l=0;
|
||||
for (ch=0;ch<2;ch++) {
|
||||
scalefac[ch]=scalefac_l[gr][ch][0];
|
||||
a[ch]=fras_l(0,global_gain[ch],scalefac_scale[ch],scalefac[ch],preflag[ch]);
|
||||
}
|
||||
|
||||
|
||||
while (l<36) {
|
||||
int is_pos;
|
||||
if (l<isbound[0]) is_pos=IS_ILLEGAL;
|
||||
else {
|
||||
is_pos=scalefac[1];
|
||||
if (id==1) /* MPEG1 */
|
||||
{
|
||||
if (is_pos==7) is_pos=IS_ILLEGAL;
|
||||
}
|
||||
else /* MPEG2 */
|
||||
{
|
||||
if (is_pos==is_max[sfb]) is_pos=IS_ILLEGAL;
|
||||
}
|
||||
}
|
||||
|
||||
stereo_l(l,a,ms_flag,is_pos,header);
|
||||
|
||||
if (l==t_l[sfb]) {
|
||||
sfb++;
|
||||
for (ch=0;ch<2;ch++) {
|
||||
scalefac[ch]=scalefac_l[gr][ch][sfb];
|
||||
a[ch]=fras_l(sfb,global_gain[ch],scalefac_scale[ch],scalefac[ch],preflag[ch]);
|
||||
}
|
||||
}
|
||||
|
||||
l++;
|
||||
}
|
||||
/*
|
||||
* mixed blocks w/stereo processing - short block part *****************
|
||||
*/
|
||||
sfb=3;
|
||||
window_len=t_s[sfb]-t_s[sfb-1];
|
||||
|
||||
while (l<(MAX(non_zero[0],non_zero[1]))) {
|
||||
for (window=0;window<3;window++) {
|
||||
subblock_gain[0]=info->subblock_gain[gr][0][window];
|
||||
subblock_gain[1]=info->subblock_gain[gr][1][window];
|
||||
scalefac[0]=scalefac_s[gr][0][sfb][window];
|
||||
scalefac[1]=scalefac_s[gr][1][sfb][window];
|
||||
|
||||
if (t_s[sfb] < isbound[window]) {
|
||||
is_pos=IS_ILLEGAL;
|
||||
a[0]=fras_s(global_gain[0],subblock_gain[0],scalefac_scale[0],scalefac[0]);
|
||||
a[1]=fras_s(global_gain[1],subblock_gain[1],scalefac_scale[1],scalefac[1]);
|
||||
} else {
|
||||
is_pos=scalefac[1];
|
||||
if (id==1) /* MPEG1 */
|
||||
{
|
||||
if (is_pos==7) is_pos=IS_ILLEGAL;
|
||||
}
|
||||
else /* MPEG2 */
|
||||
{
|
||||
if (is_pos==is_max[sfb+6]) is_pos=IS_ILLEGAL;
|
||||
}
|
||||
|
||||
a[0]=fras_s(global_gain[0],subblock_gain[0],scalefac_scale[0],scalefac[0]);
|
||||
}
|
||||
|
||||
for (i=0;i<window_len;i++) {
|
||||
stereo_s(l,a,t_reorder[id][sfreq][l],ms_flag,is_pos,header);
|
||||
l++;
|
||||
}
|
||||
}
|
||||
sfb++;
|
||||
window_len=t_s[sfb]-t_s[sfb-1];
|
||||
}
|
||||
while (l<576) {
|
||||
int reorder = t_reorder[id][sfreq][l++];
|
||||
|
||||
xr[0][0][reorder]=xr[1][0][reorder]=0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* requantize_ms - short blocks w/stereo processing ********************
|
||||
*/
|
||||
int window,window_len;
|
||||
|
||||
ms_flag=find_isbound(isbound,gr,info,header);
|
||||
sfb=0; l=0;
|
||||
window_len=t_s[0]+1;
|
||||
|
||||
while (l<(MAX(non_zero[0],non_zero[1]))) {
|
||||
for (window=0;window<3;window++) {
|
||||
subblock_gain[0]=info->subblock_gain[gr][0][window];
|
||||
subblock_gain[1]=info->subblock_gain[gr][1][window];
|
||||
scalefac[0]=scalefac_s[gr][0][sfb][window];
|
||||
scalefac[1]=scalefac_s[gr][1][sfb][window];
|
||||
|
||||
if (t_s[sfb] < isbound[window]) {
|
||||
is_pos=IS_ILLEGAL;
|
||||
a[0]=fras_s(global_gain[0],subblock_gain[0],scalefac_scale[0],scalefac[0]);
|
||||
a[1]=fras_s(global_gain[1],subblock_gain[1],scalefac_scale[1],scalefac[1]);
|
||||
} else {
|
||||
is_pos=scalefac[1];
|
||||
if (id==1) /* MPEG1 */
|
||||
{
|
||||
if (is_pos==7) is_pos=IS_ILLEGAL;
|
||||
}
|
||||
else /* MPEG2 */
|
||||
{
|
||||
if (is_pos==is_max[sfb+6]) is_pos=IS_ILLEGAL;
|
||||
}
|
||||
a[0]=fras_s(global_gain[0],subblock_gain[0],scalefac_scale[0],scalefac[0]);
|
||||
}
|
||||
|
||||
for (i=0;i<window_len;i++) {
|
||||
stereo_s(l,a,t_reorder[id][sfreq][l],ms_flag,is_pos,header);
|
||||
l++;
|
||||
}
|
||||
}
|
||||
/* this won't do anymore
|
||||
* window_len=-t_s[sfb]+t_s[++sfb];
|
||||
*/
|
||||
window_len = -t_s[sfb++];
|
||||
window_len += t_s[sfb];
|
||||
|
||||
}
|
||||
while (l<576) {
|
||||
int reorder = t_reorder[id][sfreq][l++];
|
||||
|
||||
xr[0][0][reorder]=xr[1][0][reorder]=0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* long blocks w/stereo processing *************************************
|
||||
*/
|
||||
int *preflag=info->preflag[gr];
|
||||
|
||||
ms_flag=find_isbound(isbound,gr,info,header);
|
||||
|
||||
sfb=0; l=0;
|
||||
scalefac[0]=scalefac_l[gr][0][sfb];
|
||||
a[0]=fras_l(sfb,global_gain[0],scalefac_scale[0],scalefac[0],preflag[0]);
|
||||
scalefac[1]=scalefac_l[gr][1][sfb];
|
||||
a[1]=fras_l(sfb,global_gain[1],scalefac_scale[1],scalefac[1],preflag[1]);
|
||||
|
||||
/* no intensity stereo part
|
||||
*/
|
||||
if (ms_flag)
|
||||
while (l< isbound[0]) {
|
||||
#if defined(PENTIUM_RDTSC)
|
||||
|
||||
unsigned int cnt4, cnt3, cnt2, cnt1;
|
||||
static int min_cycles = 99999999;
|
||||
|
||||
__asm__(".byte 0x0f,0x31" : "=a" (cnt1), "=d" (cnt4));
|
||||
#endif
|
||||
|
||||
{
|
||||
register float Mi = fras2(is[0][l],a[0]);
|
||||
register float Si = fras2(is[1][l],a[1]);
|
||||
register float tmp = i_sq2;
|
||||
xr[0][0][l]=(Mi+Si)*tmp;
|
||||
xr[1][0][l]=(Mi-Si)*tmp;
|
||||
}
|
||||
|
||||
#if defined(PENTIUM_RDTSC)
|
||||
__asm__(".byte 0x0f,0x31" : "=a" (cnt2), "=d" (cnt4));
|
||||
|
||||
if (cnt2-cnt1 < min_cycles) {
|
||||
min_cycles = cnt2-cnt1;
|
||||
printf("%d cycles\n", min_cycles);
|
||||
}
|
||||
|
||||
#endif
|
||||
if (l==t_l[sfb]) {
|
||||
#if defined(PENTIUM_RDTSC2)
|
||||
|
||||
unsigned int cnt4, cnt2, cnt1;
|
||||
static int min_cycles = 99999999;
|
||||
|
||||
__asm__(".byte 0x0f,0x31" : "=a" (cnt1), "=d" (cnt4));
|
||||
#endif
|
||||
|
||||
sfb++;
|
||||
scalefac[0]=scalefac_l[gr][0][sfb];
|
||||
a[0]=fras_l(sfb,global_gain[0],scalefac_scale[0],scalefac[0],preflag[0]);
|
||||
scalefac[1]=scalefac_l[gr][1][sfb];
|
||||
a[1]=fras_l(sfb,global_gain[1],scalefac_scale[1],scalefac[1],preflag[1]);
|
||||
#if defined(PENTIUM_RDTSC2)
|
||||
__asm__(".byte 0x0f,0x31" : "=a" (cnt2), "=d" (cnt4));
|
||||
|
||||
if (cnt2-cnt1 < min_cycles) {
|
||||
min_cycles = cnt2-cnt1;
|
||||
printf("%d cycles, sfb %d\n", min_cycles, sfb);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
l++;
|
||||
}
|
||||
else
|
||||
while (l< isbound[0]) {
|
||||
xr[0][0][l]=fras2(is[0][l],a[0]);
|
||||
xr[1][0][l]=fras2(is[1][l],a[1]);
|
||||
if (l==t_l[sfb]) {
|
||||
sfb++;
|
||||
scalefac[0]=scalefac_l[gr][0][sfb];
|
||||
a[0]=fras_l(sfb,global_gain[0],scalefac_scale[0],scalefac[0],preflag[0]);
|
||||
scalefac[1]=scalefac_l[gr][1][sfb];
|
||||
a[1]=fras_l(sfb,global_gain[1],scalefac_scale[1],scalefac[1],preflag[1]);
|
||||
}
|
||||
l++;
|
||||
}
|
||||
|
||||
|
||||
/* intensity stereo part
|
||||
*/
|
||||
while (l<(MAX(non_zero[0],non_zero[1]))) {
|
||||
int is_pos=scalefac[1];
|
||||
|
||||
if (id==1) /* MPEG1 */
|
||||
{
|
||||
if (is_pos==7) is_pos=IS_ILLEGAL;
|
||||
}
|
||||
else /* MPEG2 */
|
||||
{
|
||||
if (is_pos==is_max[sfb]) is_pos=IS_ILLEGAL;
|
||||
}
|
||||
stereo_l(l,a,ms_flag,is_pos,header);
|
||||
|
||||
if (l==t_l[sfb]) {
|
||||
sfb++;
|
||||
scalefac[0]=scalefac_l[gr][0][sfb];
|
||||
scalefac[1]=scalefac_l[gr][1][sfb];
|
||||
a[0]=fras_l(sfb,global_gain[0],scalefac_scale[0],scalefac[0],preflag[0]);
|
||||
}
|
||||
l++;
|
||||
}
|
||||
|
||||
while (l<576) {
|
||||
xr[0][0][l]=0;
|
||||
xr[1][0][l]=0;
|
||||
l++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* requantize_downmix **********************************************************
|
||||
*/
|
||||
void requantize_downmix(int gr,struct SIDE_INFO *info,struct AUDIO_HEADER *header)
|
||||
{
|
||||
int l,sfb,ms_flag,i;
|
||||
int *global_gain,subblock_gain[2],*scalefac_scale,scalefac[2];
|
||||
int sfreq=header->sampling_frequency;
|
||||
int id = header->ID;
|
||||
float a[2];
|
||||
|
||||
/* first set some variables
|
||||
*/
|
||||
global_gain=info->global_gain[gr];
|
||||
scalefac_scale=info->scalefac_scale[gr];
|
||||
|
||||
if (header->mode_extension==2 || header->mode_extension==3) ms_flag=1;
|
||||
else ms_flag=0;
|
||||
|
||||
/* ... and then we're off for requantization
|
||||
*/
|
||||
if (info->window_switching_flag[gr][0] && info->block_type[gr][0]==2)
|
||||
if (info->mixed_block_flag[gr][0]) {
|
||||
die("mixed block? hmmmm...., downmix for mixed blocks is not yet implemented\n");
|
||||
} else {
|
||||
int window,window_len;
|
||||
int isbound[3];
|
||||
int is_pos;
|
||||
|
||||
memset(isbound, 0, sizeof(isbound));
|
||||
|
||||
sfb=0; l=0; window_len=t_s[0]+1;
|
||||
|
||||
while (l<(MAX(non_zero[0],non_zero[1]))) {
|
||||
for (window=0;window<3;window++) {
|
||||
subblock_gain[0]=info->subblock_gain[gr][0][window];
|
||||
subblock_gain[1]=info->subblock_gain[gr][1][window];
|
||||
scalefac[0]=scalefac_s[gr][0][sfb][window];
|
||||
is_pos=scalefac[1]=scalefac_s[gr][1][sfb][window];
|
||||
|
||||
if (t_s[sfb] < isbound[window]) {
|
||||
a[0]=fras_s(global_gain[0],subblock_gain[0],scalefac_scale[0],scalefac[0]);
|
||||
if (ms_flag) {
|
||||
for (i=0;i<window_len;i++) {
|
||||
register float Mi=fras2(is[0][l],a[0]);
|
||||
xr[0][0][t_reorder[id][sfreq][l]]=Mi*i_sq2;
|
||||
l++;
|
||||
}
|
||||
} else {
|
||||
a[1]=fras_s(global_gain[1],subblock_gain[1],scalefac_scale[1],scalefac[1]);
|
||||
for (i=0;i<window_len;i++) {
|
||||
register float tmp1=fras2(is[0][l],a[0]);
|
||||
register float tmp2=fras2(is[1][l],a[1]);
|
||||
xr[0][0][t_reorder[id][sfreq][l]]=(tmp1+tmp2)*0.5f;
|
||||
l++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
a[0]=fras_s(global_gain[0],subblock_gain[0],scalefac_scale[0],scalefac[0]);
|
||||
for (i=0;i<window_len;i++) {
|
||||
register float ftmp = fras2(is[0][l], a[0]);
|
||||
if (id==0 && is_pos<is_max[sfb])
|
||||
ftmp*=t_downmix[intensity_scale][(is_pos+1)>>1];
|
||||
xr[0][0][t_reorder[id][sfreq][l]] = ftmp;
|
||||
l++;
|
||||
}
|
||||
}
|
||||
}
|
||||
window_len = -t_s[sfb++];
|
||||
window_len += t_s[sfb];
|
||||
}
|
||||
while (l<576) {
|
||||
xr[0][0][l]=0;
|
||||
l++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int *preflag=info->preflag[gr];
|
||||
int isbound;
|
||||
|
||||
if (header->mode_extension==1 || header->mode_extension==3) {
|
||||
int tmp=non_zero[1];
|
||||
while (is[1][tmp] == 0) tmp--;
|
||||
sfb=0; while (t_l[sfb] < tmp && sfb < 21) sfb++;
|
||||
isbound=t_l[sfb]+1;
|
||||
no_of_imdcts[0]=no_of_imdcts[1]=(non_zero[0]-1)/18+1;
|
||||
} else {
|
||||
isbound=(MAX(non_zero[0],non_zero[1]));
|
||||
no_of_imdcts[0]=no_of_imdcts[1]=(isbound-1)/18+1;
|
||||
}
|
||||
|
||||
sfb=0; l=0;
|
||||
scalefac[0]=scalefac_l[gr][0][sfb];
|
||||
a[0]=fras_l(sfb,global_gain[0],scalefac_scale[0],scalefac[0],preflag[0]);
|
||||
scalefac[1]=scalefac_l[gr][1][sfb];
|
||||
a[1]=fras_l(sfb,global_gain[1],scalefac_scale[1],scalefac[1],preflag[1]);
|
||||
|
||||
/* no intensity stereo part
|
||||
*/
|
||||
if (ms_flag)
|
||||
while (l < isbound) {
|
||||
register float Mi = fras2(is[0][l],a[0]);
|
||||
register float tmp = i_sq2;
|
||||
xr[0][0][l]=Mi*tmp;
|
||||
|
||||
if (l==t_l[sfb]) {
|
||||
sfb++;
|
||||
scalefac[0]=scalefac_l[gr][0][sfb];
|
||||
a[0]=fras_l(sfb,global_gain[0],scalefac_scale[0],scalefac[0],preflag[0]);
|
||||
scalefac[1]=scalefac_l[gr][1][sfb];
|
||||
}
|
||||
l++;
|
||||
}
|
||||
else
|
||||
while (l < isbound) {
|
||||
register float tmp1=fras2(is[0][l],a[0]);
|
||||
register float tmp2=fras2(is[1][l],a[1]);
|
||||
xr[0][0][l]=(tmp1+tmp2)*0.5f;
|
||||
if (l==t_l[sfb]) {
|
||||
sfb++;
|
||||
scalefac[0]=scalefac_l[gr][0][sfb];
|
||||
a[0]=fras_l(sfb,global_gain[0],scalefac_scale[0],scalefac[0],preflag[0]);
|
||||
scalefac[1]=scalefac_l[gr][1][sfb];
|
||||
a[1]=fras_l(sfb,global_gain[1],scalefac_scale[1],scalefac[1],preflag[1]);
|
||||
}
|
||||
l++;
|
||||
}
|
||||
/* intensity stereo part
|
||||
*/
|
||||
while (l<(MAX(non_zero[0],non_zero[1]))) {
|
||||
int is_pos=scalefac[1];
|
||||
register float ftmp=fras2(is[0][l], a[0]);
|
||||
|
||||
if (id==0 && is_pos<is_max[sfb]) {
|
||||
ftmp*=t_downmix[intensity_scale][(is_pos+1)>>1];
|
||||
}
|
||||
|
||||
xr[0][0][l] = ftmp;
|
||||
|
||||
if (l==t_l[sfb]) {
|
||||
sfb++;
|
||||
scalefac[0]=scalefac_l[gr][0][sfb];
|
||||
a[0]=fras_l(sfb,global_gain[0],scalefac_scale[0],scalefac[0],preflag[0]);
|
||||
scalefac[1]=scalefac_l[gr][1][sfb];
|
||||
}
|
||||
l++;
|
||||
}
|
||||
|
||||
/* _always_ zero out everything else
|
||||
*/
|
||||
while (l<576) {
|
||||
xr[0][0][l]=0;
|
||||
l++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* antialiasing butterflies ****************************************************
|
||||
*
|
||||
*/
|
||||
void alias_reduction(int ch)
|
||||
{
|
||||
unsigned int sb;
|
||||
|
||||
for (sb=1;sb<32;sb++) {
|
||||
float *x = xr[ch][sb];
|
||||
register float a, b;
|
||||
|
||||
a = x[0];
|
||||
b = x[-1];
|
||||
x[-1] = b * Cs[0] - a * Ca[0];
|
||||
x[0] = a * Cs[0] + b * Ca[0];
|
||||
|
||||
a = x[1];
|
||||
b = x[-2];
|
||||
x[-2] = b * Cs[1] - a * Ca[1];
|
||||
x[1] = a * Cs[1] + b * Ca[1];
|
||||
|
||||
a = x[2];
|
||||
b = x[-3];
|
||||
x[-3] = b * Cs[2] - a * Ca[2];
|
||||
x[2] = a * Cs[2] + b * Ca[2];
|
||||
|
||||
a = x[3];
|
||||
b = x[-4];
|
||||
x[-4] = b * Cs[3] - a * Ca[3];
|
||||
x[3] = a * Cs[3] + b * Ca[3];
|
||||
|
||||
a = x[4];
|
||||
b = x[-5];
|
||||
x[-5] = b * Cs[4] - a * Ca[4];
|
||||
x[4] = a * Cs[4] + b * Ca[4];
|
||||
|
||||
a = x[5];
|
||||
b = x[-6];
|
||||
x[-6] = b * Cs[5] - a * Ca[5];
|
||||
x[5] = a * Cs[5] + b * Ca[5];
|
||||
|
||||
a = x[6];
|
||||
b = x[-7];
|
||||
x[-7] = b * Cs[6] - a * Ca[6];
|
||||
x[6] = a * Cs[6] + b * Ca[6];
|
||||
|
||||
a = x[7];
|
||||
b = x[-8];
|
||||
x[-8] = b * Cs[7] - a * Ca[7];
|
||||
x[7] = a * Cs[7] + b * Ca[7];
|
||||
}
|
||||
}
|
||||
|
||||
/* calculating t_43 instead of having that big table in misc2.h
|
||||
*/
|
||||
|
||||
void calculate_t43(void)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<8192;i++)
|
||||
t_43[i]=(float)pow((float)i,1.33333333333f);
|
||||
}
|
253
Src/Sound/MPEG/misc2.h
Normal file
253
Src/Sound/MPEG/misc2.h
Normal file
|
@ -0,0 +1,253 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* misc2.h
|
||||
*
|
||||
* Created by: tomislav uzelac May 1996
|
||||
* Last modified by: tomislav uzelac Jan 8 1997
|
||||
*/
|
||||
|
||||
extern void requantize_mono(int gr,int ch,struct SIDE_INFO *info,struct AUDIO_HEADER *header);
|
||||
extern void requantize_ms(int gr,struct SIDE_INFO *info,struct AUDIO_HEADER *header);
|
||||
extern void alias_reduction(int ch);
|
||||
extern void calculate_t43(void);
|
||||
|
||||
extern int no_of_imdcts[2];
|
||||
|
||||
#ifdef MISC2
|
||||
|
||||
#define i_sq2 0.707106781188
|
||||
#define IS_ILLEGAL 0xfeed
|
||||
|
||||
void requantize_mono(int gr,int ch,struct SIDE_INFO *info,struct AUDIO_HEADER *header);
|
||||
void requantize_ms(int gr,struct SIDE_INFO *info,struct AUDIO_HEADER *header);
|
||||
void alias_reduction(int ch);
|
||||
|
||||
static inline float fras_l(int sfb,int global_gain,int scalefac_scale,int scalefac,int preflag);
|
||||
static inline float fras_s(int global_gain,int subblock_gain,int scalefac_scale,int scalefac);
|
||||
static inline float fras2(int is,float a);
|
||||
static int find_isbound(int isbound[3],int gr,struct SIDE_INFO *info,struct AUDIO_HEADER *header);
|
||||
static inline void stereo_s(int l,float a[2],int pos,int ms_flag,int is_pos,struct AUDIO_HEADER *header);
|
||||
static inline void stereo_l(int l,float a[2],int ms_flag,int is_pos,struct AUDIO_HEADER *header);
|
||||
|
||||
int no_of_imdcts[2];
|
||||
|
||||
static const int t_pretab[22]={0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0};
|
||||
static const float t_is[7]={ 1.0f, 0.788675134596f, 0.633974596215f,
|
||||
0.5f, 0.366025403784f, 0.211324865405f, 0.0f};
|
||||
static const float t_is2[2][32]={
|
||||
{ 1.0f, 0.840896f, 0.707107f, 0.594604f, 0.5f, 0.420448f,
|
||||
0.353553f, 0.297302f, 0.25f, 0.210224f, 0.176777f, 0.148651f,
|
||||
0.125f, 0.105112f, 0.0883883f, 0.0743254f},
|
||||
{ 1.0f, 0.707107f, 0.5f, 0.353553f, 0.25f, 0.176777f,
|
||||
0.125f, 0.0883883f, 0.0625f, 0.0441942f, 0.03125f, 0.0220971f,
|
||||
0.015625f, 0.0110485f, 0.0078125f, 0.00552427f}
|
||||
};
|
||||
static const float t_downmix[2][32]={
|
||||
{ 1.000000f, 0.920448f, 0.853554f, 0.797302f, 0.750000f, 0.710224f,
|
||||
0.676776f, 0.648651f, 0.625000f, 0.605112f, 0.588389f, 0.574326f,
|
||||
0.562500f, 0.552556f, 0.544194f, 0.537163f},
|
||||
{ 1.000000f, 0.853554f, 0.750000f, 0.676776f, 0.625000f, 0.588389f,
|
||||
0.562500f, 0.544194f, 0.531250f, 0.522097f, 0.515625f, 0.511049f,
|
||||
0.507813f, 0.505524f, 0.503906f, 0.502762f}
|
||||
};
|
||||
|
||||
static const float Cs[8]={0.857492925712f, 0.881741997318f, 0.949628649103f,
|
||||
0.983314592492f, 0.995517816065f, 0.999160558175f,
|
||||
0.999899195243f, 0.999993155067f};
|
||||
static const float Ca[8]={-0.5144957554270f, -0.4717319685650f, -0.3133774542040f,
|
||||
-0.1819131996110f, -0.0945741925262f, -0.0409655828852f,
|
||||
-0.0141985685725f, -0.00369997467375f};
|
||||
static const float tab[4]={1.0f,1.189207115f,1.414213562f,1.6817928301f};
|
||||
static const float tabi[4]={1.0f,0.840896415f,0.707106781f,0.594603557f};
|
||||
|
||||
static float t_43[8192];
|
||||
|
||||
|
||||
/* leftmost index denotes header->ID, so first three are for MPEG2
|
||||
* and the others are for MPEG1
|
||||
*/
|
||||
static const short t_reorder[2][3][576]={{
|
||||
{ 0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15, 4, 5, 18, 19, 10, 11, 24, 25,
|
||||
16, 17, 30, 31, 20, 21, 22, 23, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 90, 91,
|
||||
78, 79, 80, 81, 82, 83, 96, 97, 84, 85, 86, 87, 88, 89, 102, 103, 92, 93, 94, 95,
|
||||
108, 109, 110, 111, 112, 113, 98, 99, 100, 101, 114, 115, 116, 117, 118, 119, 104, 105, 106, 107,
|
||||
120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 144, 145, 146, 147, 148, 149, 162, 163,
|
||||
132, 133, 134, 135, 136, 137, 150, 151, 152, 153, 154, 155, 168, 169, 138, 139, 140, 141, 142, 143,
|
||||
156, 157, 158, 159, 160, 161, 174, 175, 164, 165, 166, 167, 180, 181, 182, 183, 184, 185, 198, 199,
|
||||
200, 201, 202, 203, 216, 217, 170, 171, 172, 173, 186, 187, 188, 189, 190, 191, 204, 205, 206, 207,
|
||||
208, 209, 222, 223, 176, 177, 178, 179, 192, 193, 194, 195, 196, 197, 210, 211, 212, 213, 214, 215,
|
||||
228, 229, 218, 219, 220, 221, 234, 235, 236, 237, 238, 239, 252, 253, 254, 255, 256, 257, 270, 271,
|
||||
272, 273, 274, 275, 288, 289, 290, 291, 224, 225, 226, 227, 240, 241, 242, 243, 244, 245, 258, 259,
|
||||
260, 261, 262, 263, 276, 277, 278, 279, 280, 281, 294, 295, 296, 297, 230, 231, 232, 233, 246, 247,
|
||||
248, 249, 250, 251, 264, 265, 266, 267, 268, 269, 282, 283, 284, 285, 286, 287, 300, 301, 302, 303,
|
||||
292, 293, 306, 307, 308, 309, 310, 311, 324, 325, 326, 327, 328, 329, 342, 343, 344, 345, 346, 347,
|
||||
360, 361, 362, 363, 364, 365, 378, 379, 380, 381, 382, 383, 298, 299, 312, 313, 314, 315, 316, 317,
|
||||
330, 331, 332, 333, 334, 335, 348, 349, 350, 351, 352, 353, 366, 367, 368, 369, 370, 371, 384, 385,
|
||||
386, 387, 388, 389, 304, 305, 318, 319, 320, 321, 322, 323, 336, 337, 338, 339, 340, 341, 354, 355,
|
||||
356, 357, 358, 359, 372, 373, 374, 375, 376, 377, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399,
|
||||
400, 401, 414, 415, 416, 417, 418, 419, 432, 433, 434, 435, 436, 437, 450, 451, 452, 453, 454, 455,
|
||||
468, 469, 470, 471, 472, 473, 486, 487, 488, 489, 490, 491, 504, 505, 506, 507, 508, 509, 402, 403,
|
||||
404, 405, 406, 407, 420, 421, 422, 423, 424, 425, 438, 439, 440, 441, 442, 443, 456, 457, 458, 459,
|
||||
460, 461, 474, 475, 476, 477, 478, 479, 492, 493, 494, 495, 496, 497, 510, 511, 512, 513, 514, 515,
|
||||
408, 409, 410, 411, 412, 413, 426, 427, 428, 429, 430, 431, 444, 445, 446, 447, 448, 449, 462, 463,
|
||||
464, 465, 466, 467, 480, 481, 482, 483, 484, 485, 498, 499, 500, 501, 502, 503, 516, 517, 518, 519,
|
||||
520, 521, 522, 523, 524, 525, 526, 527, 540, 541, 542, 543, 544, 545, 558, 559, 560, 561, 562, 563,
|
||||
528, 529, 530, 531, 532, 533, 546, 547, 548, 549, 550, 551, 564, 565, 566, 567, 568, 569, 534, 535,
|
||||
536, 537, 538, 539, 552, 553, 554, 555, 556, 557, 570, 571, 572, 573, 574, 575},
|
||||
|
||||
{ 0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15, 4, 5, 18, 19, 10, 11, 24, 25,
|
||||
16, 17, 30, 31, 20, 21, 22, 23, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||
72, 73, 60, 61, 62, 63, 64, 65, 78, 79, 66, 67, 68, 69, 70, 71, 84, 85, 74, 75,
|
||||
76, 77, 90, 91, 92, 93, 94, 95, 80, 81, 82, 83, 96, 97, 98, 99, 100, 101, 86, 87,
|
||||
88, 89, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 126, 127, 128, 129, 130, 131,
|
||||
114, 115, 116, 117, 118, 119, 132, 133, 134, 135, 136, 137, 120, 121, 122, 123, 124, 125, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 162, 163, 164, 165, 166, 167, 180, 181, 150, 151,
|
||||
152, 153, 154, 155, 168, 169, 170, 171, 172, 173, 186, 187, 156, 157, 158, 159, 160, 161, 174, 175,
|
||||
176, 177, 178, 179, 192, 193, 182, 183, 184, 185, 198, 199, 200, 201, 202, 203, 216, 217, 218, 219,
|
||||
220, 221, 234, 235, 188, 189, 190, 191, 204, 205, 206, 207, 208, 209, 222, 223, 224, 225, 226, 227,
|
||||
240, 241, 194, 195, 196, 197, 210, 211, 212, 213, 214, 215, 228, 229, 230, 231, 232, 233, 246, 247,
|
||||
236, 237, 238, 239, 252, 253, 254, 255, 256, 257, 270, 271, 272, 273, 274, 275, 288, 289, 290, 291,
|
||||
292, 293, 306, 307, 242, 243, 244, 245, 258, 259, 260, 261, 262, 263, 276, 277, 278, 279, 280, 281,
|
||||
294, 295, 296, 297, 298, 299, 312, 313, 248, 249, 250, 251, 264, 265, 266, 267, 268, 269, 282, 283,
|
||||
284, 285, 286, 287, 300, 301, 302, 303, 304, 305, 318, 319, 308, 309, 310, 311, 324, 325, 326, 327,
|
||||
328, 329, 342, 343, 344, 345, 346, 347, 360, 361, 362, 363, 364, 365, 378, 379, 380, 381, 382, 383,
|
||||
396, 397, 398, 399, 314, 315, 316, 317, 330, 331, 332, 333, 334, 335, 348, 349, 350, 351, 352, 353,
|
||||
366, 367, 368, 369, 370, 371, 384, 385, 386, 387, 388, 389, 402, 403, 404, 405, 320, 321, 322, 323,
|
||||
336, 337, 338, 339, 340, 341, 354, 355, 356, 357, 358, 359, 372, 373, 374, 375, 376, 377, 390, 391,
|
||||
392, 393, 394, 395, 408, 409, 410, 411, 400, 401, 414, 415, 416, 417, 418, 419, 432, 433, 434, 435,
|
||||
436, 437, 450, 451, 452, 453, 454, 455, 468, 469, 470, 471, 472, 473, 486, 487, 488, 489, 490, 491,
|
||||
504, 505, 506, 507, 508, 509, 522, 523, 524, 525, 526, 527, 406, 407, 420, 421, 422, 423, 424, 425,
|
||||
438, 439, 440, 441, 442, 443, 456, 457, 458, 459, 460, 461, 474, 475, 476, 477, 478, 479, 492, 493,
|
||||
494, 495, 496, 497, 510, 511, 512, 513, 514, 515, 528, 529, 530, 531, 532, 533, 412, 413, 426, 427,
|
||||
428, 429, 430, 431, 444, 445, 446, 447, 448, 449, 462, 463, 464, 465, 466, 467, 480, 481, 482, 483,
|
||||
484, 485, 498, 499, 500, 501, 502, 503, 516, 517, 518, 519, 520, 521, 534, 535, 536, 537, 538, 539,
|
||||
540, 541, 542, 543, 544, 545, 558, 559, 560, 561, 562, 563, 546, 547, 548, 549, 550, 551, 564, 565,
|
||||
566, 567, 568, 569, 552, 553, 554, 555, 556, 557, 570, 571, 572, 573, 574, 575},
|
||||
|
||||
{ 0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15, 4, 5, 18, 19, 10, 11, 24, 25,
|
||||
16, 17, 30, 31, 20, 21, 22, 23, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||
72, 73, 60, 61, 62, 63, 64, 65, 78, 79, 66, 67, 68, 69, 70, 71, 84, 85, 74, 75,
|
||||
76, 77, 90, 91, 92, 93, 94, 95, 80, 81, 82, 83, 96, 97, 98, 99, 100, 101, 86, 87,
|
||||
88, 89, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 126, 127, 128, 129, 130, 131,
|
||||
114, 115, 116, 117, 118, 119, 132, 133, 134, 135, 136, 137, 120, 121, 122, 123, 124, 125, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 162, 163, 164, 165, 166, 167, 180, 181, 150, 151,
|
||||
152, 153, 154, 155, 168, 169, 170, 171, 172, 173, 186, 187, 156, 157, 158, 159, 160, 161, 174, 175,
|
||||
176, 177, 178, 179, 192, 193, 182, 183, 184, 185, 198, 199, 200, 201, 202, 203, 216, 217, 218, 219,
|
||||
220, 221, 234, 235, 188, 189, 190, 191, 204, 205, 206, 207, 208, 209, 222, 223, 224, 225, 226, 227,
|
||||
240, 241, 194, 195, 196, 197, 210, 211, 212, 213, 214, 215, 228, 229, 230, 231, 232, 233, 246, 247,
|
||||
236, 237, 238, 239, 252, 253, 254, 255, 256, 257, 270, 271, 272, 273, 274, 275, 288, 289, 290, 291,
|
||||
292, 293, 306, 307, 242, 243, 244, 245, 258, 259, 260, 261, 262, 263, 276, 277, 278, 279, 280, 281,
|
||||
294, 295, 296, 297, 298, 299, 312, 313, 248, 249, 250, 251, 264, 265, 266, 267, 268, 269, 282, 283,
|
||||
284, 285, 286, 287, 300, 301, 302, 303, 304, 305, 318, 319, 308, 309, 310, 311, 324, 325, 326, 327,
|
||||
328, 329, 342, 343, 344, 345, 346, 347, 360, 361, 362, 363, 364, 365, 378, 379, 380, 381, 382, 383,
|
||||
396, 397, 314, 315, 316, 317, 330, 331, 332, 333, 334, 335, 348, 349, 350, 351, 352, 353, 366, 367,
|
||||
368, 369, 370, 371, 384, 385, 386, 387, 388, 389, 402, 403, 320, 321, 322, 323, 336, 337, 338, 339,
|
||||
340, 341, 354, 355, 356, 357, 358, 359, 372, 373, 374, 375, 376, 377, 390, 391, 392, 393, 394, 395,
|
||||
408, 409, 398, 399, 400, 401, 414, 415, 416, 417, 418, 419, 432, 433, 434, 435, 436, 437, 450, 451,
|
||||
452, 453, 454, 455, 468, 469, 470, 471, 472, 473, 486, 487, 488, 489, 490, 491, 504, 505, 506, 507,
|
||||
508, 509, 404, 405, 406, 407, 420, 421, 422, 423, 424, 425, 438, 439, 440, 441, 442, 443, 456, 457,
|
||||
458, 459, 460, 461, 474, 475, 476, 477, 478, 479, 492, 493, 494, 495, 496, 497, 510, 511, 512, 513,
|
||||
514, 515, 410, 411, 412, 413, 426, 427, 428, 429, 430, 431, 444, 445, 446, 447, 448, 449, 462, 463,
|
||||
464, 465, 466, 467, 480, 481, 482, 483, 484, 485, 498, 499, 500, 501, 502, 503, 516, 517, 518, 519,
|
||||
520, 521, 522, 523, 524, 525, 526, 527, 540, 541, 542, 543, 544, 545, 558, 559, 560, 561, 562, 563,
|
||||
528, 529, 530, 531, 532, 533, 546, 547, 548, 549, 550, 551, 564, 565, 566, 567, 568, 569, 534, 535,
|
||||
536, 537, 538, 539, 552, 553, 554, 555, 556, 557, 570, 571, 572, 573, 574, 575}
|
||||
},
|
||||
{
|
||||
{ 0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15, 4, 5, 18, 19, 10, 11, 24, 25,
|
||||
16, 17, 30, 31, 20, 21, 22, 23, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
42, 43, 44, 45, 48, 49, 50, 51, 40, 41, 54, 55, 56, 57, 46, 47, 60, 61, 62, 63,
|
||||
52, 53, 66, 67, 68, 69, 58, 59, 72, 73, 74, 75, 76, 77, 64, 65, 78, 79, 80, 81,
|
||||
82, 83, 70, 71, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 108, 109, 110, 111,
|
||||
96, 97, 98, 99, 100, 101, 114, 115, 116, 117, 102, 103, 104, 105, 106, 107, 120, 121, 122, 123,
|
||||
112, 113, 126, 127, 128, 129, 130, 131, 144, 145, 146, 147, 118, 119, 132, 133, 134, 135, 136, 137,
|
||||
150, 151, 152, 153, 124, 125, 138, 139, 140, 141, 142, 143, 156, 157, 158, 159, 148, 149, 162, 163,
|
||||
164, 165, 166, 167, 180, 181, 182, 183, 184, 185, 154, 155, 168, 169, 170, 171, 172, 173, 186, 187,
|
||||
188, 189, 190, 191, 160, 161, 174, 175, 176, 177, 178, 179, 192, 193, 194, 195, 196, 197, 198, 199,
|
||||
200, 201, 202, 203, 216, 217, 218, 219, 220, 221, 234, 235, 236, 237, 238, 239, 204, 205, 206, 207,
|
||||
208, 209, 222, 223, 224, 225, 226, 227, 240, 241, 242, 243, 244, 245, 210, 211, 212, 213, 214, 215,
|
||||
228, 229, 230, 231, 232, 233, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 270, 271,
|
||||
272, 273, 274, 275, 288, 289, 290, 291, 292, 293, 306, 307, 308, 309, 258, 259, 260, 261, 262, 263,
|
||||
276, 277, 278, 279, 280, 281, 294, 295, 296, 297, 298, 299, 312, 313, 314, 315, 264, 265, 266, 267,
|
||||
268, 269, 282, 283, 284, 285, 286, 287, 300, 301, 302, 303, 304, 305, 318, 319, 320, 321, 310, 311,
|
||||
324, 325, 326, 327, 328, 329, 342, 343, 344, 345, 346, 347, 360, 361, 362, 363, 364, 365, 378, 379,
|
||||
380, 381, 382, 383, 396, 397, 398, 399, 316, 317, 330, 331, 332, 333, 334, 335, 348, 349, 350, 351,
|
||||
352, 353, 366, 367, 368, 369, 370, 371, 384, 385, 386, 387, 388, 389, 402, 403, 404, 405, 322, 323,
|
||||
336, 337, 338, 339, 340, 341, 354, 355, 356, 357, 358, 359, 372, 373, 374, 375, 376, 377, 390, 391,
|
||||
392, 393, 394, 395, 408, 409, 410, 411, 400, 401, 414, 415, 416, 417, 418, 419, 432, 433, 434, 435,
|
||||
436, 437, 450, 451, 452, 453, 454, 455, 468, 469, 470, 471, 472, 473, 486, 487, 488, 489, 490, 491,
|
||||
504, 505, 506, 507, 508, 509, 522, 523, 524, 525, 526, 527, 540, 541, 542, 543, 544, 545, 558, 559,
|
||||
560, 561, 562, 563, 406, 407, 420, 421, 422, 423, 424, 425, 438, 439, 440, 441, 442, 443, 456, 457,
|
||||
458, 459, 460, 461, 474, 475, 476, 477, 478, 479, 492, 493, 494, 495, 496, 497, 510, 511, 512, 513,
|
||||
514, 515, 528, 529, 530, 531, 532, 533, 546, 547, 548, 549, 550, 551, 564, 565, 566, 567, 568, 569,
|
||||
412, 413, 426, 427, 428, 429, 430, 431, 444, 445, 446, 447, 448, 449, 462, 463, 464, 465, 466, 467,
|
||||
480, 481, 482, 483, 484, 485, 498, 499, 500, 501, 502, 503, 516, 517, 518, 519, 520, 521, 534, 535,
|
||||
536, 537, 538, 539, 552, 553, 554, 555, 556, 557, 570, 571, 572, 573, 574, 575},
|
||||
|
||||
{ 0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15, 4, 5, 18, 19, 10, 11, 24, 25,
|
||||
16, 17, 30, 31, 20, 21, 22, 23, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
42, 43, 44, 45, 48, 49, 50, 51, 40, 41, 54, 55, 56, 57, 46, 47, 60, 61, 62, 63,
|
||||
52, 53, 66, 67, 68, 69, 58, 59, 72, 73, 74, 75, 64, 65, 78, 79, 80, 81, 70, 71,
|
||||
84, 85, 86, 87, 76, 77, 90, 91, 92, 93, 94, 95, 108, 109, 82, 83, 96, 97, 98, 99,
|
||||
100, 101, 114, 115, 88, 89, 102, 103, 104, 105, 106, 107, 120, 121, 110, 111, 112, 113, 126, 127,
|
||||
128, 129, 130, 131, 144, 145, 116, 117, 118, 119, 132, 133, 134, 135, 136, 137, 150, 151, 122, 123,
|
||||
124, 125, 138, 139, 140, 141, 142, 143, 156, 157, 146, 147, 148, 149, 162, 163, 164, 165, 166, 167,
|
||||
180, 181, 182, 183, 152, 153, 154, 155, 168, 169, 170, 171, 172, 173, 186, 187, 188, 189, 158, 159,
|
||||
160, 161, 174, 175, 176, 177, 178, 179, 192, 193, 194, 195, 184, 185, 198, 199, 200, 201, 202, 203,
|
||||
216, 217, 218, 219, 220, 221, 234, 235, 190, 191, 204, 205, 206, 207, 208, 209, 222, 223, 224, 225,
|
||||
226, 227, 240, 241, 196, 197, 210, 211, 212, 213, 214, 215, 228, 229, 230, 231, 232, 233, 246, 247,
|
||||
236, 237, 238, 239, 252, 253, 254, 255, 256, 257, 270, 271, 272, 273, 274, 275, 288, 289, 290, 291,
|
||||
242, 243, 244, 245, 258, 259, 260, 261, 262, 263, 276, 277, 278, 279, 280, 281, 294, 295, 296, 297,
|
||||
248, 249, 250, 251, 264, 265, 266, 267, 268, 269, 282, 283, 284, 285, 286, 287, 300, 301, 302, 303,
|
||||
292, 293, 306, 307, 308, 309, 310, 311, 324, 325, 326, 327, 328, 329, 342, 343, 344, 345, 346, 347,
|
||||
360, 361, 362, 363, 364, 365, 298, 299, 312, 313, 314, 315, 316, 317, 330, 331, 332, 333, 334, 335,
|
||||
348, 349, 350, 351, 352, 353, 366, 367, 368, 369, 370, 371, 304, 305, 318, 319, 320, 321, 322, 323,
|
||||
336, 337, 338, 339, 340, 341, 354, 355, 356, 357, 358, 359, 372, 373, 374, 375, 376, 377, 378, 379,
|
||||
380, 381, 382, 383, 396, 397, 398, 399, 400, 401, 414, 415, 416, 417, 418, 419, 432, 433, 434, 435,
|
||||
436, 437, 450, 451, 452, 453, 454, 455, 468, 469, 470, 471, 472, 473, 486, 487, 488, 489, 490, 491,
|
||||
504, 505, 506, 507, 508, 509, 522, 523, 524, 525, 526, 527, 540, 541, 542, 543, 544, 545, 558, 559,
|
||||
560, 561, 562, 563, 384, 385, 386, 387, 388, 389, 402, 403, 404, 405, 406, 407, 420, 421, 422, 423,
|
||||
424, 425, 438, 439, 440, 441, 442, 443, 456, 457, 458, 459, 460, 461, 474, 475, 476, 477, 478, 479,
|
||||
492, 493, 494, 495, 496, 497, 510, 511, 512, 513, 514, 515, 528, 529, 530, 531, 532, 533, 546, 547,
|
||||
548, 549, 550, 551, 564, 565, 566, 567, 568, 569, 390, 391, 392, 393, 394, 395, 408, 409, 410, 411,
|
||||
412, 413, 426, 427, 428, 429, 430, 431, 444, 445, 446, 447, 448, 449, 462, 463, 464, 465, 466, 467,
|
||||
480, 481, 482, 483, 484, 485, 498, 499, 500, 501, 502, 503, 516, 517, 518, 519, 520, 521, 534, 535,
|
||||
536, 537, 538, 539, 552, 553, 554, 555, 556, 557, 570, 571, 572, 573, 574, 575},
|
||||
|
||||
{ 0, 1, 2, 3, 6, 7, 8, 9, 12, 13, 14, 15, 4, 5, 18, 19, 10, 11, 24, 25,
|
||||
16, 17, 30, 31, 20, 21, 22, 23, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
42, 43, 44, 45, 48, 49, 50, 51, 40, 41, 54, 55, 56, 57, 46, 47, 60, 61, 62, 63,
|
||||
52, 53, 66, 67, 68, 69, 58, 59, 72, 73, 74, 75, 76, 77, 64, 65, 78, 79, 80, 81,
|
||||
82, 83, 70, 71, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 108, 109, 110, 111,
|
||||
112, 113, 96, 97, 98, 99, 100, 101, 114, 115, 116, 117, 118, 119, 102, 103, 104, 105, 106, 107,
|
||||
120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 144, 145, 146, 147, 148, 149, 162, 163,
|
||||
164, 165, 132, 133, 134, 135, 136, 137, 150, 151, 152, 153, 154, 155, 168, 169, 170, 171, 138, 139,
|
||||
140, 141, 142, 143, 156, 157, 158, 159, 160, 161, 174, 175, 176, 177, 166, 167, 180, 181, 182, 183,
|
||||
184, 185, 198, 199, 200, 201, 202, 203, 216, 217, 218, 219, 220, 221, 172, 173, 186, 187, 188, 189,
|
||||
190, 191, 204, 205, 206, 207, 208, 209, 222, 223, 224, 225, 226, 227, 178, 179, 192, 193, 194, 195,
|
||||
196, 197, 210, 211, 212, 213, 214, 215, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
|
||||
252, 253, 254, 255, 256, 257, 270, 271, 272, 273, 274, 275, 288, 289, 290, 291, 292, 293, 306, 307,
|
||||
240, 241, 242, 243, 244, 245, 258, 259, 260, 261, 262, 263, 276, 277, 278, 279, 280, 281, 294, 295,
|
||||
296, 297, 298, 299, 312, 313, 246, 247, 248, 249, 250, 251, 264, 265, 266, 267, 268, 269, 282, 283,
|
||||
284, 285, 286, 287, 300, 301, 302, 303, 304, 305, 318, 319, 308, 309, 310, 311, 324, 325, 326, 327,
|
||||
328, 329, 342, 343, 344, 345, 346, 347, 360, 361, 362, 363, 364, 365, 378, 379, 380, 381, 382, 383,
|
||||
396, 397, 398, 399, 400, 401, 314, 315, 316, 317, 330, 331, 332, 333, 334, 335, 348, 349, 350, 351,
|
||||
352, 353, 366, 367, 368, 369, 370, 371, 384, 385, 386, 387, 388, 389, 402, 403, 404, 405, 406, 407,
|
||||
320, 321, 322, 323, 336, 337, 338, 339, 340, 341, 354, 355, 356, 357, 358, 359, 372, 373, 374, 375,
|
||||
376, 377, 390, 391, 392, 393, 394, 395, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419,
|
||||
432, 433, 434, 435, 436, 437, 450, 451, 452, 453, 454, 455, 468, 469, 470, 471, 472, 473, 486, 487,
|
||||
488, 489, 490, 491, 504, 505, 506, 507, 508, 509, 522, 523, 524, 525, 526, 527, 420, 421, 422, 423,
|
||||
424, 425, 438, 439, 440, 441, 442, 443, 456, 457, 458, 459, 460, 461, 474, 475, 476, 477, 478, 479,
|
||||
492, 493, 494, 495, 496, 497, 510, 511, 512, 513, 514, 515, 528, 529, 530, 531, 532, 533, 426, 427,
|
||||
428, 429, 430, 431, 444, 445, 446, 447, 448, 449, 462, 463, 464, 465, 466, 467, 480, 481, 482, 483,
|
||||
484, 485, 498, 499, 500, 501, 502, 503, 516, 517, 518, 519, 520, 521, 534, 535, 536, 537, 538, 539,
|
||||
540, 541, 542, 543, 544, 545, 558, 559, 560, 561, 562, 563, 546, 547, 548, 549, 550, 551, 564, 565,
|
||||
566, 567, 568, 569, 552, 553, 554, 555, 556, 557, 570, 571, 572, 573, 574, 575}
|
||||
}};
|
||||
|
||||
#endif
|
103
Src/Sound/MPEG/position.cpp
Normal file
103
Src/Sound/MPEG/position.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
/* position.c ffwd/rew within a stream
|
||||
*
|
||||
* Creted by: Tomislav Uzelac, May 10 1997
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "amp.h"
|
||||
#include "audio.h"
|
||||
#include "getbits.h"
|
||||
|
||||
#define POSITION
|
||||
#include "position.h"
|
||||
|
||||
/* Returns the number of frames actually skipped, -1 on error.
|
||||
*
|
||||
* Values in header are not changed if retval!=nframes.
|
||||
* This is not necessary because gethdr() doesn't clobber
|
||||
* the contents of header, but I don't want to rely on that.
|
||||
*/
|
||||
int ffwd(struct AUDIO_HEADER *header, int nframes)
|
||||
{
|
||||
int cnt=0,g;
|
||||
int hsize,bitrate,fs,mean_frame_size;
|
||||
struct AUDIO_HEADER tmp;
|
||||
memcpy(&tmp,header,sizeof(tmp));
|
||||
|
||||
while (cnt < nframes) {
|
||||
if (tmp.ID)
|
||||
if (tmp.mode==3) hsize=21;
|
||||
else hsize=36;
|
||||
else
|
||||
if (tmp.mode==3) hsize=13;
|
||||
else hsize=21;
|
||||
if (tmp.protection_bit==0) hsize+=2;
|
||||
if ((g=dummy_getinfo(hsize))) /* dummy_getinfo: reads hsize-4 bytes */
|
||||
switch (g) {
|
||||
case GETHDR_EOF: return cnt;
|
||||
case GETHDR_ERR:
|
||||
default: return -1;
|
||||
}
|
||||
|
||||
bitrate=t_bitrate[tmp.ID][3-tmp.layer][tmp.bitrate_index];
|
||||
fs=t_sampling_frequency[tmp.ID][tmp.sampling_frequency];
|
||||
if (tmp.ID) mean_frame_size=144000*bitrate/fs;
|
||||
else mean_frame_size=72000*bitrate/fs;
|
||||
fillbfr(mean_frame_size + tmp.padding_bit - hsize);
|
||||
|
||||
if ((g=gethdr(&tmp)))
|
||||
switch (g) {
|
||||
case GETHDR_EOF: return cnt;
|
||||
case GETHDR_ERR:
|
||||
default: return -1;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
|
||||
memcpy(header,&tmp,sizeof(tmp));
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* Mostly the same as ffwd. Some streams might be 'tough', i.e.
|
||||
* the ones switching bitrates.
|
||||
*/
|
||||
int rew(struct AUDIO_HEADER *header, int nframes)
|
||||
{
|
||||
int cnt=0;
|
||||
int bitrate,fs,mean_frame_size;
|
||||
struct AUDIO_HEADER tmp;
|
||||
memcpy(&tmp,header,sizeof(tmp));
|
||||
|
||||
while (cnt < nframes) {
|
||||
/* ffwd/rew functions are to be called right after the header has been parsed
|
||||
* so we have to go back one frame + 4 bytes + 1 byte (in case padding was used).
|
||||
*/
|
||||
bitrate=t_bitrate[tmp.ID][3-tmp.layer][tmp.bitrate_index];
|
||||
fs=t_sampling_frequency[tmp.ID][tmp.sampling_frequency];
|
||||
if (tmp.ID) mean_frame_size=144000*bitrate/fs;
|
||||
else mean_frame_size=72000*bitrate/fs;
|
||||
|
||||
if (rewind_stream(mean_frame_size) !=0) {
|
||||
memcpy(header,&tmp,sizeof(tmp));
|
||||
return cnt;
|
||||
}
|
||||
if ((gethdr(&tmp))) return -1;
|
||||
cnt++;
|
||||
}
|
||||
/* We have to make sure that the bit reservoir contains enough data.
|
||||
* Hopefully, layer3_frame will take care of that.
|
||||
*/
|
||||
f_bdirty=TRUE;
|
||||
bclean_bytes=0;
|
||||
|
||||
memcpy(header,&tmp,sizeof(tmp));
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* TODO: after the gethdr function is enhanced with the counter to count
|
||||
* the number of bytes to search for the next syncword, make the call to
|
||||
* gethdr() from rew() have that counter something like (frame_size-1) so
|
||||
* that we don't go back again and again to the same header. (not very important)
|
||||
*/
|
10
Src/Sound/MPEG/position.h
Normal file
10
Src/Sound/MPEG/position.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
extern int ffwd(struct AUDIO_HEADER *header, int nframes);
|
||||
extern int rew(struct AUDIO_HEADER *header, int nframes);
|
||||
|
||||
#ifdef POSITION
|
||||
int ffwd(struct AUDIO_HEADER *header, int nframes);
|
||||
int rew(struct AUDIO_HEADER *header, int nframes);
|
||||
#endif
|
26
Src/Sound/MPEG/proto.h
Normal file
26
Src/Sound/MPEG/proto.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* From: util.c */
|
||||
void die(char *, ...);
|
||||
void warn(char *, ...);
|
||||
void msg(char *, ...);
|
||||
void debugSetup(char *);
|
||||
void debugOptions();
|
||||
|
||||
/* From: audioIO_<OSTYPE>.c */
|
||||
void audioOpen(int frequency, int stereo, int volume);
|
||||
void audioSetVolume(int);
|
||||
void audioFlush();
|
||||
void audioClose();
|
||||
int audioWrite(char *, int);
|
||||
int getAudioFd();
|
||||
void audioBufferOn(int);
|
||||
|
||||
|
||||
/* From: buffer.c */
|
||||
void printout(void);
|
||||
int audioBufferOpen(int, int, int);
|
||||
void audioBufferClose();
|
||||
void audioBufferWrite(char *, int);
|
||||
void audioBufferFlush();
|
||||
|
||||
/* From: audio.c */
|
||||
void displayUsage();
|
63
Src/Sound/MPEG/rtbuf.h
Normal file
63
Src/Sound/MPEG/rtbuf.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* rtbuf.h -- Linux realtime audio output.
|
||||
*
|
||||
* Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*
|
||||
* This is the Linux realtime sound output driver
|
||||
*/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef HAVE_MLOCKALL
|
||||
#undef LINUX_REALTIME
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SCHED_SETSCHEDULER
|
||||
#undef LINUX_REALTIME
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#ifndef _POSIX_MEMLOCK
|
||||
#undef LINUX_REALTIME
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_PRIORITY_SCHEDULING
|
||||
#undef LINUX_REALTIME
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LINUX_REALTIME
|
||||
|
||||
int prefetch_get_input(unsigned char *bp, int bytes);
|
||||
int rt_play(char *file);
|
||||
void rt_printout(short *sbuf, int ln);
|
||||
int setup_fancy_audio(struct AUDIO_HEADER *mpegheader);
|
||||
int start_fancy_audio(struct AUDIO_HEADER *mpegheader);
|
||||
int stop_fancy_audio(void);
|
||||
int block_fancy_audio(int snd_eof);
|
||||
int ready_fancy_audio(void);
|
||||
void cleanup_fancy_audio(void);
|
||||
void prefetch_initial_fill(void);
|
||||
int set_realtime_priority(void);
|
||||
|
||||
#endif /* LINUX_REALTIME */
|
||||
|
1518
Src/Sound/MPEG/transform.cpp
Normal file
1518
Src/Sound/MPEG/transform.cpp
Normal file
File diff suppressed because it is too large
Load diff
168
Src/Sound/MPEG/transform.h
Normal file
168
Src/Sound/MPEG/transform.h
Normal file
|
@ -0,0 +1,168 @@
|
|||
/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
|
||||
*/
|
||||
|
||||
/* transform.h tables galore
|
||||
*
|
||||
* Created by: tomislav uzelac May 1996
|
||||
* Last modified by: tomislav uzelac Mar 1 97
|
||||
*/
|
||||
extern void imdct_init();
|
||||
extern void imdct(int win_type,int sb,int ch);
|
||||
extern void poly(int ch,int i);
|
||||
extern void premultiply();
|
||||
|
||||
extern short sample_buffer[18][32][2];
|
||||
extern float res[32][18];
|
||||
extern float s[2][32][18];
|
||||
|
||||
#ifdef TRANSFORM
|
||||
|
||||
void imdct_init();
|
||||
void imdct(int win_type,int sb,int ch);
|
||||
void poly(int ch,int i);
|
||||
void premultiply();
|
||||
|
||||
short sample_buffer[18][32][2];
|
||||
float s[2][32][18];
|
||||
float res[32][18];
|
||||
float win[4][36];
|
||||
|
||||
static const float t_sin[4][36]={{
|
||||
-0.032160f, 0.103553f, -0.182543f, 0.266729f, -0.353554f, 0.440377f,
|
||||
-0.524563f, 0.603553f, -0.674947f, 0.736575f, -0.786566f, 0.823400f,
|
||||
-0.845957f, 0.853554f, -0.845957f, 0.823399f, -0.786566f, 0.736575f,
|
||||
-0.674947f, 0.603553f, -0.524564f, 0.440378f, -0.353553f, 0.266729f,
|
||||
-0.182544f, 0.103553f, -0.032160f, -0.029469f, 0.079459f, -0.116293f,
|
||||
0.138851f, -0.146446f, 0.138851f, -0.116293f, 0.079459f, -0.029469f
|
||||
},{
|
||||
-0.032160f, 0.103553f, -0.182543f, 0.266729f, -0.353554f, 0.440377f,
|
||||
-0.524563f, 0.603553f, -0.674947f, 0.736575f, -0.786566f, 0.823400f,
|
||||
-0.845957f, 0.853554f, -0.845957f, 0.823399f, -0.786566f, 0.736575f,
|
||||
-0.675590f, 0.608761f, -0.537300f, 0.461749f, -0.382683f, 0.300706f,
|
||||
-0.214588f, 0.120590f, -0.034606f, -0.026554f, 0.049950f, -0.028251f,
|
||||
0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f
|
||||
},{
|
||||
-0.103553f, 0.353554f, -0.603553f, 0.786566f, -0.853554f, 0.786566f,
|
||||
-0.603553f, 0.353553f, -0.103553f, -0.079459f, 0.146446f, -0.079459f,
|
||||
0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
|
||||
0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
|
||||
0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
|
||||
0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f
|
||||
},{
|
||||
0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
|
||||
-0.127432f, 0.379410f, -0.608182f, 0.792598f, -0.915976f, 0.967944f,
|
||||
-0.953717f, 0.923880f, -0.887011f, 0.843391f, -0.793353f, 0.737277f,
|
||||
-0.674947f, 0.603553f, -0.524564f, 0.440378f, -0.353553f, 0.266729f,
|
||||
-0.182544f, 0.103553f, -0.032160f, -0.029469f, 0.079459f, -0.116293f,
|
||||
0.138851f, -0.146446f, 0.138851f, -0.116293f, 0.079459f, -0.029469f
|
||||
}};
|
||||
|
||||
static const float t_2cos[4][18]={
|
||||
{ -0.174311f, -0.517638f, -0.845237f, -1.147153f, -1.414214f, -1.638304f, -1.812616f, -1.931852f, -1.992389f,
|
||||
0.174311f, 0.517638f, 0.845237f, 1.147153f, 1.414214f, 1.638304f, 1.812616f, 1.931852f, 1.992389f},
|
||||
{ -0.174311f, -0.517638f, -0.845237f, -1.147153f, -1.414214f, -1.638304f, -1.812616f, -1.931852f, -1.992389f,
|
||||
0.174311f, 0.517638f, 0.845237f, 1.147153f, 1.414214f, 1.638304f, 1.812616f, 1.931852f, 1.992389f},
|
||||
{ -0.517638f, -1.41421f, -1.93185f, 0.517638f, 1.41421f, 1.93185f,0,0,0,0,0,0,0,0,0,0,0,0},
|
||||
{ -0.174311f, -0.517638f, -0.845237f, -1.147153f, -1.414214f, -1.638304f, -1.812616f, -1.931852f, -1.992389f,
|
||||
0.174311f, 0.517638f, 0.845237f, 1.147153f, 1.414214f, 1.638304f, 1.812616f, 1.931852f, 1.992389f}
|
||||
};
|
||||
|
||||
static const float b1 = 1.997590912f; static const float b2 = 1.990369453f; static const float b3 = 1.978353019f;
|
||||
static const float b4 = 1.961570560f; static const float b5 = 1.940062506f; static const float b6 = 1.913880671f;
|
||||
static const float b7 = 1.883088130f; static const float b8 = 1.847759065f; static const float b9 = 1.807978586f;
|
||||
static const float b10= 1.763842529f; static const float b11= 1.715457220f; static const float b12= 1.662939225f;
|
||||
static const float b13= 1.606415063f; static const float b14= 1.546020907f; static const float b15= 1.481902251f;
|
||||
static const float b16= 1.414213562f; static const float b17= 1.343117910f; static const float b18= 1.268786568f;
|
||||
static const float b19= 1.191398609f; static const float b20= 1.111140466f; static const float b21= 1.028205488f;
|
||||
static const float b22= 0.942793474f; static const float b23= 0.855110187f; static const float b24= 0.765366865f;
|
||||
static const float b25= 0.673779707f; static const float b26= 0.580569355f; static const float b27= 0.485960360f;
|
||||
static const float b28= 0.390180644f; static const float b29= 0.293460949f; static const float b30= 0.196034281f;
|
||||
static const float b31= 0.098135349f;
|
||||
|
||||
static float t_dewindow[17][32] = {{
|
||||
0.000000000f,-0.000442505f, 0.003250122f,-0.007003784f, 0.031082153f,-0.078628540f, 0.100311279f,-0.572036743f,
|
||||
1.144989014f, 0.572036743f, 0.100311279f, 0.078628540f, 0.031082153f, 0.007003784f, 0.003250122f, 0.000442505f,
|
||||
0.000000000f,-0.000442505f, 0.003250122f,-0.007003784f, 0.031082153f,-0.078628540f, 0.100311279f,-0.572036743f,
|
||||
1.144989014f, 0.572036743f, 0.100311279f, 0.078628540f, 0.031082153f, 0.007003784f, 0.003250122f, 0.000442505f,
|
||||
},{
|
||||
-0.000015259f,-0.000473022f, 0.003326416f,-0.007919312f, 0.030517578f,-0.084182739f, 0.090927124f,-0.600219727f,
|
||||
1.144287109f, 0.543823242f, 0.108856201f, 0.073059082f, 0.031478882f, 0.006118774f, 0.003173828f, 0.000396729f,
|
||||
-0.000015259f,-0.000473022f, 0.003326416f,-0.007919312f, 0.030517578f,-0.084182739f, 0.090927124f,-0.600219727f,
|
||||
1.144287109f, 0.543823242f, 0.108856201f, 0.073059082f, 0.031478882f, 0.006118774f, 0.003173828f, 0.000396729f,
|
||||
},{
|
||||
-0.000015259f,-0.000534058f, 0.003387451f,-0.008865356f, 0.029785156f,-0.089706421f, 0.080688477f,-0.628295898f,
|
||||
1.142211914f, 0.515609741f, 0.116577148f, 0.067520142f, 0.031738281f, 0.005294800f, 0.003082275f, 0.000366211f,
|
||||
-0.000015259f,-0.000534058f, 0.003387451f,-0.008865356f, 0.029785156f,-0.089706421f, 0.080688477f,-0.628295898f,
|
||||
1.142211914f, 0.515609741f, 0.116577148f, 0.067520142f, 0.031738281f, 0.005294800f, 0.003082275f, 0.000366211f,
|
||||
},{
|
||||
-0.000015259f,-0.000579834f, 0.003433228f,-0.009841919f, 0.028884888f,-0.095169067f, 0.069595337f,-0.656219482f,
|
||||
1.138763428f, 0.487472534f, 0.123474121f, 0.061996460f, 0.031845093f, 0.004486084f, 0.002990723f, 0.000320435f,
|
||||
-0.000015259f,-0.000579834f, 0.003433228f,-0.009841919f, 0.028884888f,-0.095169067f, 0.069595337f,-0.656219482f,
|
||||
1.138763428f, 0.487472534f, 0.123474121f, 0.061996460f, 0.031845093f, 0.004486084f, 0.002990723f, 0.000320435f,
|
||||
},{
|
||||
-0.000015259f,-0.000625610f, 0.003463745f,-0.010848999f, 0.027801514f,-0.100540161f, 0.057617187f,-0.683914185f,
|
||||
1.133926392f, 0.459472656f, 0.129577637f, 0.056533813f, 0.031814575f, 0.003723145f, 0.002899170f, 0.000289917f,
|
||||
-0.000015259f,-0.000625610f, 0.003463745f,-0.010848999f, 0.027801514f,-0.100540161f, 0.057617187f,-0.683914185f,
|
||||
1.133926392f, 0.459472656f, 0.129577637f, 0.056533813f, 0.031814575f, 0.003723145f, 0.002899170f, 0.000289917f,
|
||||
},{
|
||||
-0.000015259f,-0.000686646f, 0.003479004f,-0.011886597f, 0.026535034f,-0.105819702f, 0.044784546f,-0.711318970f,
|
||||
1.127746582f, 0.431655884f, 0.134887695f, 0.051132202f, 0.031661987f, 0.003005981f, 0.002792358f, 0.000259399f,
|
||||
-0.000015259f,-0.000686646f, 0.003479004f,-0.011886597f, 0.026535034f,-0.105819702f, 0.044784546f,-0.711318970f,
|
||||
1.127746582f, 0.431655884f, 0.134887695f, 0.051132202f, 0.031661987f, 0.003005981f, 0.002792358f, 0.000259399f,
|
||||
},{
|
||||
-0.000015259f,-0.000747681f, 0.003479004f,-0.012939453f, 0.025085449f,-0.110946655f, 0.031082153f,-0.738372803f,
|
||||
1.120223999f, 0.404083252f, 0.139450073f, 0.045837402f, 0.031387329f, 0.002334595f, 0.002685547f, 0.000244141f,
|
||||
-0.000015259f,-0.000747681f, 0.003479004f,-0.012939453f, 0.025085449f,-0.110946655f, 0.031082153f,-0.738372803f,
|
||||
1.120223999f, 0.404083252f, 0.139450073f, 0.045837402f, 0.031387329f, 0.002334595f, 0.002685547f, 0.000244141f,
|
||||
},{
|
||||
-0.000030518f,-0.000808716f, 0.003463745f,-0.014022827f, 0.023422241f,-0.115921021f, 0.016510010f,-0.765029907f,
|
||||
1.111373901f, 0.376800537f, 0.143264771f, 0.040634155f, 0.031005859f, 0.001693726f, 0.002578735f, 0.000213623f,
|
||||
-0.000030518f,-0.000808716f, 0.003463745f,-0.014022827f, 0.023422241f,-0.115921021f, 0.016510010f,-0.765029907f,
|
||||
1.111373901f, 0.376800537f, 0.143264771f, 0.040634155f, 0.031005859f, 0.001693726f, 0.002578735f, 0.000213623f,
|
||||
},{
|
||||
-0.000030518f,-0.000885010f, 0.003417969f,-0.015121460f, 0.021575928f,-0.120697021f, 0.001068115f,-0.791213989f,
|
||||
1.101211548f, 0.349868774f, 0.146362305f, 0.035552979f, 0.030532837f, 0.001098633f, 0.002456665f, 0.000198364f,
|
||||
-0.000030518f,-0.000885010f, 0.003417969f,-0.015121460f, 0.021575928f,-0.120697021f, 0.001068115f,-0.791213989f,
|
||||
1.101211548f, 0.349868774f, 0.146362305f, 0.035552979f, 0.030532837f, 0.001098633f, 0.002456665f, 0.000198364f,
|
||||
},{
|
||||
-0.000030518f,-0.000961304f, 0.003372192f,-0.016235352f, 0.019531250f,-0.125259399f,-0.015228271f,-0.816864014f,
|
||||
1.089782715f, 0.323318481f, 0.148773193f, 0.030609131f, 0.029937744f, 0.000549316f, 0.002349854f, 0.000167847f,
|
||||
-0.000030518f,-0.000961304f, 0.003372192f,-0.016235352f, 0.019531250f,-0.125259399f,-0.015228271f,-0.816864014f,
|
||||
1.089782715f, 0.323318481f, 0.148773193f, 0.030609131f, 0.029937744f, 0.000549316f, 0.002349854f, 0.000167847f,
|
||||
},{
|
||||
-0.000030518f,-0.001037598f, 0.003280640f,-0.017349243f, 0.017257690f,-0.129562378f,-0.032379150f,-0.841949463f,
|
||||
1.077117920f, 0.297210693f, 0.150497437f, 0.025817871f, 0.029281616f, 0.000030518f, 0.002243042f, 0.000152588f,
|
||||
-0.000030518f,-0.001037598f, 0.003280640f,-0.017349243f, 0.017257690f,-0.129562378f,-0.032379150f,-0.841949463f,
|
||||
1.077117920f, 0.297210693f, 0.150497437f, 0.025817871f, 0.029281616f, 0.000030518f, 0.002243042f, 0.000152588f,
|
||||
},{
|
||||
-0.000045776f,-0.001113892f, 0.003173828f,-0.018463135f, 0.014801025f,-0.133590698f,-0.050354004f,-0.866363525f,
|
||||
1.063217163f, 0.271591187f, 0.151596069f, 0.021179199f, 0.028533936f,-0.000442505f, 0.002120972f, 0.000137329f,
|
||||
-0.000045776f,-0.001113892f, 0.003173828f,-0.018463135f, 0.014801025f,-0.133590698f,-0.050354004f,-0.866363525f,
|
||||
1.063217163f, 0.271591187f, 0.151596069f, 0.021179199f, 0.028533936f,-0.000442505f, 0.002120972f, 0.000137329f,
|
||||
},{
|
||||
-0.000045776f,-0.001205444f, 0.003051758f,-0.019577026f, 0.012115479f,-0.137298584f,-0.069168091f,-0.890090942f,
|
||||
1.048156738f, 0.246505737f, 0.152069092f, 0.016708374f, 0.027725220f,-0.000869751f, 0.002014160f, 0.000122070f,
|
||||
-0.000045776f,-0.001205444f, 0.003051758f,-0.019577026f, 0.012115479f,-0.137298584f,-0.069168091f,-0.890090942f,
|
||||
1.048156738f, 0.246505737f, 0.152069092f, 0.016708374f, 0.027725220f,-0.000869751f, 0.002014160f, 0.000122070f,
|
||||
},{
|
||||
-0.000061035f,-0.001296997f, 0.002883911f,-0.020690918f, 0.009231567f,-0.140670776f,-0.088775635f,-0.913055420f,
|
||||
1.031936646f, 0.221984863f, 0.151962280f, 0.012420654f, 0.026840210f,-0.001266479f, 0.001907349f, 0.000106812f,
|
||||
-0.000061035f,-0.001296997f, 0.002883911f,-0.020690918f, 0.009231567f,-0.140670776f,-0.088775635f,-0.913055420f,
|
||||
1.031936646f, 0.221984863f, 0.151962280f, 0.012420654f, 0.026840210f,-0.001266479f, 0.001907349f, 0.000106812f,
|
||||
},{
|
||||
-0.000061035f,-0.001388550f, 0.002700806f,-0.021789551f, 0.006134033f,-0.143676758f,-0.109161377f,-0.935195923f,
|
||||
1.014617920f, 0.198059082f, 0.151306152f, 0.008316040f, 0.025909424f,-0.001617432f, 0.001785278f, 0.000106812f,
|
||||
-0.000061035f,-0.001388550f, 0.002700806f,-0.021789551f, 0.006134033f,-0.143676758f,-0.109161377f,-0.935195923f,
|
||||
1.014617920f, 0.198059082f, 0.151306152f, 0.008316040f, 0.025909424f,-0.001617432f, 0.001785278f, 0.000106812f,
|
||||
},{
|
||||
-0.000076294f,-0.001480103f, 0.002487183f,-0.022857666f, 0.002822876f,-0.146255493f,-0.130310059f,-0.956481934f,
|
||||
0.996246338f, 0.174789429f, 0.150115967f, 0.004394531f, 0.024932861f,-0.001937866f, 0.001693726f, 0.000091553f,
|
||||
-0.000076294f,-0.001480103f, 0.002487183f,-0.022857666f, 0.002822876f,-0.146255493f,-0.130310059f,-0.956481934f,
|
||||
0.996246338f, 0.174789429f, 0.150115967f, 0.004394531f, 0.024932861f,-0.001937866f, 0.001693726f, 0.000091553f,
|
||||
},{
|
||||
-0.000076294f,-0.001586914f, 0.002227783f,-0.023910522f,-0.000686646f,-0.148422241f,-0.152206421f,-0.976852417f,
|
||||
0.976852417f, 0.152206421f, 0.148422241f, 0.000686646f, 0.023910522f,-0.002227783f, 0.001586914f, 0.000076294f,
|
||||
-0.000076294f,-0.001586914f, 0.002227783f,-0.023910522f,-0.000686646f,-0.148422241f,-0.152206421f,-0.976852417f,
|
||||
0.976852417f, 0.152206421f, 0.148422241f, 0.000686646f, 0.023910522f,-0.002227783f, 0.001586914f, 0.000076294f,
|
||||
} };
|
||||
#endif /* TRANSFORM */
|
110
Src/Sound/MPEG/util.cpp
Normal file
110
Src/Sound/MPEG/util.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
/* this file is a part of amp software
|
||||
|
||||
util.c: created by Andrew Richards
|
||||
|
||||
*/
|
||||
|
||||
#define AMP_UTIL
|
||||
#include "amp.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
struct debugFlags_t debugFlags;
|
||||
|
||||
|
||||
/* die - for terminal conditions prints the error message and exits */
|
||||
/* can not be suppressed with -q,-quiet */
|
||||
void
|
||||
die(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap,fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
|
||||
|
||||
/* warn - for warning messages. Can be suppressed by -q,-quiet */
|
||||
void
|
||||
warn(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap,fmt);
|
||||
if (!A_QUIET) {
|
||||
fprintf(stderr,"Warning: ");
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* msg - for general output. Can be suppressed by -q,-quiet. Output */
|
||||
/* goes to stderr so it doesn't conflict with stdout output */
|
||||
void
|
||||
msg(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap,fmt);
|
||||
|
||||
if (!A_QUIET)
|
||||
{
|
||||
if (A_MSG_STDOUT) {
|
||||
vfprintf(stdout, fmt, ap);
|
||||
fflush(stdout);
|
||||
} else {
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
debugOptions()
|
||||
{
|
||||
int idx;
|
||||
msg("Possible options are: ");
|
||||
for(idx=0;debugLookup[idx].name!=0;idx++)
|
||||
msg("%s,",debugLookup[idx].name);
|
||||
msg("\010 \n");
|
||||
}
|
||||
|
||||
|
||||
/* debugSetup - if debugging is turned on sets up the debug flags from */
|
||||
/* the command line arguments */
|
||||
|
||||
void
|
||||
debugSetup(char *dbgFlags)
|
||||
{
|
||||
#ifndef DEBUG
|
||||
warn("Debugging has not been compiled into this version of amp\n");
|
||||
#else
|
||||
char *ptr;
|
||||
int idx;
|
||||
|
||||
memset(&debugFlags,0,sizeof(debugFlags));
|
||||
|
||||
ptr=strtok(dbgFlags,",");
|
||||
while(ptr) {
|
||||
for(idx=0;debugLookup[idx].name!=0;idx++) {
|
||||
if (strcmp(debugLookup[idx].name,ptr)==0) {
|
||||
*(debugLookup[idx].var)=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (debugLookup[idx].name==0) {
|
||||
warn("Debug option, %s, does not exist\n",ptr);
|
||||
debugOptions();
|
||||
exit(1);
|
||||
}
|
||||
ptr=strtok(NULL,",");
|
||||
}
|
||||
|
||||
DB(args,
|
||||
for(idx=0;debugLookup[idx].name!=0;idx++)
|
||||
printf("Flag: %s = %d\n",debugLookup[idx].name,*(debugLookup[idx].var));
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -113,8 +113,6 @@ unsigned int RevR,RevW;
|
|||
#define DWORD UINT32
|
||||
#endif
|
||||
|
||||
static CIRQ *ppcIRQ;
|
||||
static unsigned ppcSoundIRQBit;
|
||||
static int (*Run68kCB)(int cycles);
|
||||
static void (*Int68kCB)(int irq);
|
||||
static void (*RetIntCB)();
|
||||
|
@ -745,7 +743,7 @@ void SCSP_UpdateSlotReg(int s,int r)
|
|||
if(KEYONB(s2) && (!s2->active || (s2->active && s2->EG.state==RELEASE)))
|
||||
{
|
||||
DebugLog("KEYON %d",sl);
|
||||
printf("68K: KEYON %d\n",sl);
|
||||
//printf("68K: KEYON %d\n",sl);
|
||||
SCSP_StartSlot(s2);
|
||||
}
|
||||
if(!KEYONB(s2) && s2->active)
|
||||
|
@ -1851,12 +1849,10 @@ void SCSP_Update()
|
|||
SCSP_DoMasterSamples(length);
|
||||
}
|
||||
|
||||
void SCSP_SetCB(int (*Run68k)(int cycles),void (*Int68k)(int irq), CIRQ *ppcIRQObjectPtr, unsigned ppcIRQBit)
|
||||
void SCSP_SetCB(int (*Run68k)(int cycles),void (*Int68k)(int irq))
|
||||
{
|
||||
Int68kCB=Int68k;
|
||||
Run68kCB=Run68k;
|
||||
ppcIRQ = ppcIRQObjectPtr;
|
||||
ppcSoundIRQBit = ppcIRQBit;
|
||||
}
|
||||
|
||||
void SCSP_MidiIn(BYTE val)
|
||||
|
@ -1872,7 +1868,7 @@ void SCSP_MidiIn(BYTE val)
|
|||
|
||||
void SCSP_MidiOutW(BYTE val)
|
||||
{
|
||||
printf("68K: MIDI out\n");
|
||||
//printf("68K: MIDI out\n");
|
||||
DebugLog("Midi Out Buffer push %02X",val);
|
||||
MidiStack[MidiOutW++]=val;
|
||||
MidiOutW&=7;
|
||||
|
|
|
@ -36,7 +36,7 @@ unsigned char SCSP_r8(unsigned int addr);
|
|||
unsigned short SCSP_r16(unsigned int addr);
|
||||
unsigned int SCSP_r32(unsigned int addr);
|
||||
|
||||
void SCSP_SetCB(int (*Run68k)(int cycles),void (*Int68k)(int irq), CIRQ *ppcIRQObjectPtr, unsigned soundIRQBit);
|
||||
void SCSP_SetCB(int (*Run68k)(int cycles),void (*Int68k)(int irq));
|
||||
void SCSP_Update();
|
||||
void SCSP_MidiIn(unsigned char);
|
||||
void SCSP_MidiOutW(unsigned char);
|
||||
|
|
|
@ -147,7 +147,7 @@ extern void InfoLog(const char *fmt, ...);
|
|||
#include "CPU/Bus.h"
|
||||
#include "CPU/PowerPC/PPCDisasm.h"
|
||||
#include "CPU/PowerPC/ppc.h"
|
||||
#include "CPU/68K/M68K.h"
|
||||
#include "CPU/68K/68K.h"
|
||||
#include "CPU/Z80/Z80.h"
|
||||
#include "Inputs/Input.h"
|
||||
#include "Inputs/Inputs.h"
|
||||
|
@ -164,7 +164,9 @@ extern void InfoLog(const char *fmt, ...);
|
|||
#include "Model3/TileGen.h"
|
||||
#include "Model3/Real3D.h"
|
||||
#include "Sound/SCSP.h"
|
||||
#include "Sound/MPEG/MPEG.h"
|
||||
#include "Model3/SoundBoard.h"
|
||||
#include "Model3/DSB.h"
|
||||
#include "Model3/Model3.h"
|
||||
|
||||
/******************************************************************************
|
||||
|
|
Loading…
Reference in a new issue