diff --git a/Makefiles/Makefile.SDL.Win32.MSVC b/Makefiles/Makefile.SDL.Win32.MSVC index afe4961..0d9191a 100644 --- a/Makefiles/Makefile.SDL.Win32.MSVC +++ b/Makefiles/Makefile.SDL.Win32.MSVC @@ -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 \ No newline at end of file diff --git a/Src/CPU/68K/M68K.cpp b/Src/CPU/68K/68K.cpp similarity index 69% rename from Src/CPU/68K/M68K.cpp rename to Src/CPU/68K/68K.cpp index 29d0e41..4962321 100644 --- a/Src/CPU/68K/M68K.cpp +++ b/Src/CPU/68K/68K.cpp @@ -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,26 +30,28 @@ #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) { m68k_register_t r; @@ -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" diff --git a/Src/CPU/68K/M68K.h b/Src/CPU/68K/68K.h similarity index 65% rename from Src/CPU/68K/M68K.h rename to Src/CPU/68K/68K.h index 4b08ded..b4a0965 100644 --- a/Src/CPU/68K/M68K.h +++ b/Src/CPU/68K/68K.h @@ -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 \ No newline at end of file +#endif // INCLUDED_68K_H \ No newline at end of file diff --git a/Src/CPU/68K/Musashi/m68kconf.h b/Src/CPU/68K/Musashi/m68kconf.h index cda2eac..94ab663 100644 --- a/Src/CPU/68K/Musashi/m68kconf.h +++ b/Src/CPU/68K/Musashi/m68kconf.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) diff --git a/Src/Games.cpp b/Src/Games.cpp index 4ed74e0..a2c3f7b 100644 --- a/Src/Games.cpp +++ b/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,61 +47,70 @@ 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 }, - - // 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 }, - - // 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 }, - - // 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 }, - { "CROMxx", "mpr21145.12", 0x0E6A3AE3, 0x400000, 2, 0x4000000, 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 }, - { "CROMxx", "mpr21149.16", 0x9E4EBE58, 0x400000, 2, 0x6000000, 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", "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", "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", "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 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 CROM3 (note: appears at offset 0x6000000 rather than 0x5000000 as expected) + { "CROMxx", "mpr21149.16", 0x9E4EBE58, 0x400000, 2, 0x6000000, 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 }, - { "VROM", "mpr21155.27", 0xACA19901, 0x400000, 2, 2, 32, FALSE }, - { "VROM", "mpr21156.28", 0x5C9DF226, 0x400000, 2, 4, 32, FALSE }, - { "VROM", "mpr21157.29", 0xF6FB1279, 0x400000, 2, 6, 32, FALSE }, - { "VROM", "mpr21158.30", 0x61707554, 0x400000, 2, 8, 32, FALSE }, - { "VROM", "mpr21159.31", 0xFCC791F5, 0x400000, 2, 10, 32, FALSE }, - { "VROM", "mpr21160.32", 0xB40A38D3, 0x400000, 2, 12, 32, FALSE }, - { "VROM", "mpr21161.33", 0x559063F0, 0x400000, 2, 14, 32, FALSE }, - { "VROM", "mpr21162.34", 0xACC4B2E4, 0x400000, 2, 16, 32, FALSE }, - { "VROM", "mpr21163.35", 0x653C54C7, 0x400000, 2, 18, 32, FALSE }, - { "VROM", "mpr21164.36", 0x902FD1E0, 0x400000, 2, 20, 32, FALSE }, - { "VROM", "mpr21165.37", 0x50B3BE05, 0x400000, 2, 22, 32, FALSE }, - { "VROM", "mpr21166.38", 0x8F87A782, 0x400000, 2, 24, 32, FALSE }, - { "VROM", "mpr21167.39", 0x0F3994D0, 0x400000, 2, 26, 32, FALSE }, - { "VROM", "mpr21168.40", 0xC58BE980, 0x400000, 2, 28, 32, FALSE }, - { "VROM", "mpr21169.41", 0xAA3B2CC0, 0x400000, 2, 30, 32, FALSE }, + { "VROM", "mpr21154.26", 0x3B76F8E8, 0x400000, 2, 0, 32, FALSE }, + { "VROM", "mpr21155.27", 0xACA19901, 0x400000, 2, 2, 32, FALSE }, + { "VROM", "mpr21156.28", 0x5C9DF226, 0x400000, 2, 4, 32, FALSE }, + { "VROM", "mpr21157.29", 0xF6FB1279, 0x400000, 2, 6, 32, FALSE }, + { "VROM", "mpr21158.30", 0x61707554, 0x400000, 2, 8, 32, FALSE }, + { "VROM", "mpr21159.31", 0xFCC791F5, 0x400000, 2, 10, 32, FALSE }, + { "VROM", "mpr21160.32", 0xB40A38D3, 0x400000, 2, 12, 32, FALSE }, + { "VROM", "mpr21161.33", 0x559063F0, 0x400000, 2, 14, 32, FALSE }, + { "VROM", "mpr21162.34", 0xACC4B2E4, 0x400000, 2, 16, 32, FALSE }, + { "VROM", "mpr21163.35", 0x653C54C7, 0x400000, 2, 18, 32, FALSE }, + { "VROM", "mpr21164.36", 0x902FD1E0, 0x400000, 2, 20, 32, FALSE }, + { "VROM", "mpr21165.37", 0x50B3BE05, 0x400000, 2, 22, 32, FALSE }, + { "VROM", "mpr21166.38", 0x8F87A782, 0x400000, 2, 24, 32, FALSE }, + { "VROM", "mpr21167.39", 0x0F3994D0, 0x400000, 2, 26, 32, FALSE }, + { "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,60 +128,61 @@ 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", "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", "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", "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", "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", "mpr20333.16", 0x76B8E0FA, 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 }, - { "VROM", "mpr20337.27", 0x2C7E9EB8, 0x400000, 2, 2, 32, FALSE }, - { "VROM", "mpr20338.28", 0x0AA626DF, 0x400000, 2, 4, 32, FALSE }, - { "VROM", "mpr20339.29", 0x7AF05417, 0x400000, 2, 6, 32, FALSE }, - { "VROM", "mpr20340.30", 0x82EF4A21, 0x400000, 2, 8, 32, FALSE }, - { "VROM", "mpr20341.31", 0x9373096E, 0x400000, 2, 10, 32, FALSE }, - { "VROM", "mpr20342.32", 0xEF98CD37, 0x400000, 2, 12, 32, FALSE }, - { "VROM", "mpr20343.33", 0x9825A46B, 0x400000, 2, 14, 32, FALSE }, - { "VROM", "mpr20344.34", 0xACBBCD68, 0x400000, 2, 16, 32, FALSE }, - { "VROM", "mpr20345.35", 0x431E7585, 0x400000, 2, 18, 32, FALSE }, - { "VROM", "mpr20346.36", 0x4F87F2D2, 0x400000, 2, 20, 32, FALSE }, - { "VROM", "mpr20347.37", 0x389A2D98, 0x400000, 2, 22, 32, FALSE }, - { "VROM", "mpr20348.38", 0x8BE8D4D2, 0x400000, 2, 24, 32, FALSE }, - { "VROM", "mpr20349.39", 0xA3240428, 0x400000, 2, 26, 32, FALSE }, - { "VROM", "mpr20350.40", 0xC48F9ACE, 0x400000, 2, 28, 32, FALSE }, - { "VROM", "mpr20351.41", 0x1FBD3E10, 0x400000, 2, 30, 32, FALSE }, + { "VROM", "mpr20336.26", 0x261E3D39, 0x400000, 2, 0, 32, FALSE }, + { "VROM", "mpr20337.27", 0x2C7E9EB8, 0x400000, 2, 2, 32, FALSE }, + { "VROM", "mpr20338.28", 0x0AA626DF, 0x400000, 2, 4, 32, FALSE }, + { "VROM", "mpr20339.29", 0x7AF05417, 0x400000, 2, 6, 32, FALSE }, + { "VROM", "mpr20340.30", 0x82EF4A21, 0x400000, 2, 8, 32, FALSE }, + { "VROM", "mpr20341.31", 0x9373096E, 0x400000, 2, 10, 32, FALSE }, + { "VROM", "mpr20342.32", 0xEF98CD37, 0x400000, 2, 12, 32, FALSE }, + { "VROM", "mpr20343.33", 0x9825A46B, 0x400000, 2, 14, 32, FALSE }, + { "VROM", "mpr20344.34", 0xACBBCD68, 0x400000, 2, 16, 32, FALSE }, + { "VROM", "mpr20345.35", 0x431E7585, 0x400000, 2, 18, 32, FALSE }, + { "VROM", "mpr20346.36", 0x4F87F2D2, 0x400000, 2, 20, 32, FALSE }, + { "VROM", "mpr20347.37", 0x389A2D98, 0x400000, 2, 22, 32, FALSE }, + { "VROM", "mpr20348.38", 0x8BE8D4D2, 0x400000, 2, 24, 32, FALSE }, + { "VROM", "mpr20349.39", 0xA3240428, 0x400000, 2, 26, 32, FALSE }, + { "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,43 +200,45 @@ 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 }, - - // 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 }, + { "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 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 }, + // Banked CROM0 + { "CROMxx", "mpr21426.4", 0xCE77E26E, 0x400000, 2, 0x0000000, 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 }, - { "VROM", "mpr21408.27", 0x3E00A7EF, 0x400000, 2, 2, 32, FALSE }, - { "VROM", "mpr21409.28", 0xA4673BBF, 0x400000, 2, 4, 32, FALSE }, - { "VROM", "mpr21410.29", 0xC9F43B4A, 0x400000, 2, 6, 32, FALSE }, - { "VROM", "mpr21411.30", 0xF14957C7, 0x400000, 2, 8, 32, FALSE }, - { "VROM", "mpr21412.31", 0xEC24091F, 0x400000, 2, 10, 32, FALSE }, - { "VROM", "mpr21413.32", 0xEA9049E0, 0x400000, 2, 12, 32, FALSE }, - { "VROM", "mpr21414.33", 0x79BC5FFD, 0x400000, 2, 14, 32, FALSE }, - { "VROM", "mpr21415.34", 0xF96FE7A2, 0x400000, 2, 16, 32, FALSE }, - { "VROM", "mpr21416.35", 0x84A08B3E, 0x400000, 2, 18, 32, FALSE }, - { "VROM", "mpr21417.36", 0x6094975C, 0x400000, 2, 20, 32, FALSE }, - { "VROM", "mpr21418.37", 0x7BB868BA, 0x400000, 2, 22, 32, FALSE }, - { "VROM", "mpr21419.38", 0xBE7325C2, 0x400000, 2, 24, 32, FALSE }, - { "VROM", "mpr21420.39", 0x8B577E7B, 0x400000, 2, 26, 32, FALSE }, - { "VROM", "mpr21421.40", 0x71E4E9FC, 0x400000, 2, 28, 32, FALSE }, - { "VROM", "mpr21422.41", 0xFECA77A5, 0x400000, 2, 30, 32, FALSE }, + { "VROM", "mpr21407.26", 0x3FFB416C, 0x400000, 2, 0, 32, FALSE }, + { "VROM", "mpr21408.27", 0x3E00A7EF, 0x400000, 2, 2, 32, FALSE }, + { "VROM", "mpr21409.28", 0xA4673BBF, 0x400000, 2, 4, 32, FALSE }, + { "VROM", "mpr21410.29", 0xC9F43B4A, 0x400000, 2, 6, 32, FALSE }, + { "VROM", "mpr21411.30", 0xF14957C7, 0x400000, 2, 8, 32, FALSE }, + { "VROM", "mpr21412.31", 0xEC24091F, 0x400000, 2, 10, 32, FALSE }, + { "VROM", "mpr21413.32", 0xEA9049E0, 0x400000, 2, 12, 32, FALSE }, + { "VROM", "mpr21414.33", 0x79BC5FFD, 0x400000, 2, 14, 32, FALSE }, + { "VROM", "mpr21415.34", 0xF96FE7A2, 0x400000, 2, 16, 32, FALSE }, + { "VROM", "mpr21416.35", 0x84A08B3E, 0x400000, 2, 18, 32, FALSE }, + { "VROM", "mpr21417.36", 0x6094975C, 0x400000, 2, 20, 32, FALSE }, + { "VROM", "mpr21418.37", 0x7BB868BA, 0x400000, 2, 22, 32, FALSE }, + { "VROM", "mpr21419.38", 0xBE7325C2, 0x400000, 2, 24, 32, FALSE }, + { "VROM", "mpr21420.39", 0x8B577E7B, 0x400000, 2, 26, 32, FALSE }, + { "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,54 +256,55 @@ 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 }, - - // 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 }, - - // 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 }, - - // 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 }, + { "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 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 }, + // Banked CROM0 + { "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-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-20267.12", 0x48989191, 0x400000, 2, 0x2000000, 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 }, - { "VROM", "mpr-20271.27", 0x4B01C3A4, 0x200000, 2, 2, 32, FALSE }, - { "VROM", "mpr-20272.28", 0xA658DA23, 0x200000, 2, 4, 32, FALSE }, - { "VROM", "mpr-20273.29", 0x577E9FFA, 0x200000, 2, 6, 32, FALSE }, - { "VROM", "mpr-20274.30", 0x7C7056AE, 0x200000, 2, 8, 32, FALSE }, - { "VROM", "mpr-20275.31", 0xE739F77A, 0x200000, 2, 10, 32, FALSE }, - { "VROM", "mpr-20276.32", 0xCBF966C0, 0x200000, 2, 12, 32, FALSE }, - { "VROM", "mpr-20277.33", 0x9C75200B, 0x200000, 2, 14, 32, FALSE }, - { "VROM", "mpr-20278.34", 0xDB3991BA, 0x200000, 2, 16, 32, FALSE }, - { "VROM", "mpr-20279.35", 0x995A11B8, 0x200000, 2, 18, 32, FALSE }, - { "VROM", "mpr-20280.36", 0xC2C8F9F5, 0x200000, 2, 20, 32, FALSE }, - { "VROM", "mpr-20281.37", 0xDA84B967, 0x200000, 2, 22, 32, FALSE }, - { "VROM", "mpr-20282.38", 0x1869FF49, 0x200000, 2, 24, 32, FALSE }, - { "VROM", "mpr-20283.39", 0x7D8FB469, 0x200000, 2, 26, 32, FALSE }, - { "VROM", "mpr-20284.40", 0x5C7F3A6F, 0x200000, 2, 28, 32, FALSE }, - { "VROM", "mpr-20285.41", 0x4AADC573, 0x200000, 2, 30, 32, FALSE }, + { "VROM", "mpr-20270.26", 0xDF68A7A7, 0x200000, 2, 0, 32, FALSE }, + { "VROM", "mpr-20271.27", 0x4B01C3A4, 0x200000, 2, 2, 32, FALSE }, + { "VROM", "mpr-20272.28", 0xA658DA23, 0x200000, 2, 4, 32, FALSE }, + { "VROM", "mpr-20273.29", 0x577E9FFA, 0x200000, 2, 6, 32, FALSE }, + { "VROM", "mpr-20274.30", 0x7C7056AE, 0x200000, 2, 8, 32, FALSE }, + { "VROM", "mpr-20275.31", 0xE739F77A, 0x200000, 2, 10, 32, FALSE }, + { "VROM", "mpr-20276.32", 0xCBF966C0, 0x200000, 2, 12, 32, FALSE }, + { "VROM", "mpr-20277.33", 0x9C75200B, 0x200000, 2, 14, 32, FALSE }, + { "VROM", "mpr-20278.34", 0xDB3991BA, 0x200000, 2, 16, 32, FALSE }, + { "VROM", "mpr-20279.35", 0x995A11B8, 0x200000, 2, 18, 32, FALSE }, + { "VROM", "mpr-20280.36", 0xC2C8F9F5, 0x200000, 2, 20, 32, FALSE }, + { "VROM", "mpr-20281.37", 0xDA84B967, 0x200000, 2, 22, 32, FALSE }, + { "VROM", "mpr-20282.38", 0x1869FF49, 0x200000, 2, 24, 32, FALSE }, + { "VROM", "mpr-20283.39", 0x7D8FB469, 0x200000, 2, 26, 32, FALSE }, + { "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,49 +322,50 @@ 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-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-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-21030.8", 0xF8E51BEC, 0x400000, 2, 0x1000000, 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 }, - { "VROM", "mpr-21035.27", 0x618B7D6A, 0x400000, 2, 2, 32, FALSE }, - { "VROM", "mpr-21036.28", 0x0E665BB2, 0x400000, 2, 4, 32, FALSE }, - { "VROM", "mpr-21037.29", 0x90B98493, 0x400000, 2, 6, 32, FALSE }, - { "VROM", "mpr-21038.30", 0x9B59D2C2, 0x400000, 2, 8, 32, FALSE }, - { "VROM", "mpr-21039.31", 0x61407B07, 0x400000, 2, 10, 32, FALSE }, - { "VROM", "mpr-21040.32", 0xB550C229, 0x400000, 2, 12, 32, FALSE }, - { "VROM", "mpr-21041.33", 0x8F1AC988, 0x400000, 2, 14, 32, FALSE }, - { "VROM", "mpr-21042.34", 0x1DAB621D, 0x400000, 2, 16, 32, FALSE }, - { "VROM", "mpr-21043.35", 0x707015C8, 0x400000, 2, 18, 32, FALSE }, - { "VROM", "mpr-21044.36", 0x776F9580, 0x400000, 2, 20, 32, FALSE }, - { "VROM", "mpr-21045.37", 0xA28AD02F, 0x400000, 2, 22, 32, FALSE }, - { "VROM", "mpr-21046.38", 0x05C995AE, 0x400000, 2, 24, 32, FALSE }, - { "VROM", "mpr-21047.39", 0x06B7826F, 0x400000, 2, 26, 32, FALSE }, - { "VROM", "mpr-21048.40", 0x96849974, 0x400000, 2, 28, 32, FALSE }, - { "VROM", "mpr-21049.41", 0x91E8161A, 0x400000, 2, 30, 32, FALSE }, + { "VROM", "mpr-21034.26", 0xACBA5CA6, 0x400000, 2, 0, 32, FALSE }, + { "VROM", "mpr-21035.27", 0x618B7D6A, 0x400000, 2, 2, 32, FALSE }, + { "VROM", "mpr-21036.28", 0x0E665BB2, 0x400000, 2, 4, 32, FALSE }, + { "VROM", "mpr-21037.29", 0x90B98493, 0x400000, 2, 6, 32, FALSE }, + { "VROM", "mpr-21038.30", 0x9B59D2C2, 0x400000, 2, 8, 32, FALSE }, + { "VROM", "mpr-21039.31", 0x61407B07, 0x400000, 2, 10, 32, FALSE }, + { "VROM", "mpr-21040.32", 0xB550C229, 0x400000, 2, 12, 32, FALSE }, + { "VROM", "mpr-21041.33", 0x8F1AC988, 0x400000, 2, 14, 32, FALSE }, + { "VROM", "mpr-21042.34", 0x1DAB621D, 0x400000, 2, 16, 32, FALSE }, + { "VROM", "mpr-21043.35", 0x707015C8, 0x400000, 2, 18, 32, FALSE }, + { "VROM", "mpr-21044.36", 0x776F9580, 0x400000, 2, 20, 32, FALSE }, + { "VROM", "mpr-21045.37", 0xA28AD02F, 0x400000, 2, 22, 32, FALSE }, + { "VROM", "mpr-21046.38", 0x05C995AE, 0x400000, 2, 24, 32, FALSE }, + { "VROM", "mpr-21047.39", 0x06B7826F, 0x400000, 2, 26, 32, FALSE }, + { "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,55 +741,63 @@ 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 - { "CROM", "epr-20686b.20", 0x3EA4DE9F, 0x200000, 2, 0x0000000, 8, TRUE }, - { "CROM", "epr-20685b.19", 0xAE82CB35, 0x200000, 2, 0x0000002, 8, TRUE }, - { "CROM", "epr-20684b.18", 0x1FC15431, 0x200000, 2, 0x0000004, 8, TRUE }, - { "CROM", "epr-20683b.17", 0x59D9C974, 0x200000, 2, 0x0000006, 8, TRUE }, - + { "CROM", "epr-20686b.20", 0x3EA4DE9F, 0x200000, 2, 0x0000000, 8, TRUE }, + { "CROM", "epr-20685b.19", 0xAE82CB35, 0x200000, 2, 0x0000002, 8, TRUE }, + { "CROM", "epr-20684b.18", 0x1FC15431, 0x200000, 2, 0x0000004, 8, TRUE }, + { "CROM", "epr-20683b.17", 0x59D9C974, 0x200000, 2, 0x0000006, 8, TRUE }, + // Banked CROM0 - { "CROMxx", "mpr-20650.4", 0x81F96649, 0x400000, 2, 0x0000000, 8, TRUE }, - { "CROMxx", "mpr-20649.3", 0xb8FD56BA, 0x400000, 2, 0x0000002, 8, TRUE }, - { "CROMxx", "mpr-20648.2", 0x107309E0, 0x400000, 2, 0x0000004, 8, TRUE }, - { "CROMxx", "mpr-20647.1", 0xe8586380, 0x400000, 2, 0x0000006, 8, TRUE }, - + { "CROMxx", "mpr-20650.4", 0x81F96649, 0x400000, 2, 0x0000000, 8, TRUE }, + { "CROMxx", "mpr-20649.3", 0xb8FD56BA, 0x400000, 2, 0x0000002, 8, TRUE }, + { "CROMxx", "mpr-20648.2", 0x107309E0, 0x400000, 2, 0x0000004, 8, TRUE }, + { "CROMxx", "mpr-20647.1", 0xe8586380, 0x400000, 2, 0x0000006, 8, TRUE }, + // Banked CROM1 - { "CROMxx", "mpr-20654.8", 0x763EF905, 0x400000, 2, 0x1000000, 8, TRUE }, - { "CROMxx", "mpr-20653.7", 0x858E6BBA, 0x400000, 2, 0x1000002, 8, TRUE }, - { "CROMxx", "mpr-20652.6", 0x64C6FBB6, 0x400000, 2, 0x1000004, 8, TRUE }, - { "CROMxx", "mpr-20651.5", 0x8373CAB3, 0x400000, 2, 0x1000006, 8, TRUE }, - + { "CROMxx", "mpr-20654.8", 0x763EF905, 0x400000, 2, 0x1000000, 8, TRUE }, + { "CROMxx", "mpr-20653.7", 0x858E6BBA, 0x400000, 2, 0x1000002, 8, TRUE }, + { "CROMxx", "mpr-20652.6", 0x64C6FBB6, 0x400000, 2, 0x1000004, 8, TRUE }, + { "CROMxx", "mpr-20651.5", 0x8373CAB3, 0x400000, 2, 0x1000006, 8, TRUE }, + // Banked CROM2 - { "CROMxx", "mpr-20658.12", 0xB80175B9, 0x400000, 2, 0x2000000, 8, TRUE }, - { "CROMxx", "mpr-20657.11", 0x14BF8964, 0x400000, 2, 0x2000002, 8, TRUE }, - { "CROMxx", "mpr-20656.10", 0x466BEE13, 0x400000, 2, 0x2000004, 8, TRUE }, - { "CROMxx", "mpr-20655.9", 0xF0A471E9, 0x400000, 2, 0x2000006, 8, TRUE }, - + { "CROMxx", "mpr-20658.12", 0xB80175B9, 0x400000, 2, 0x2000000, 8, TRUE }, + { "CROMxx", "mpr-20657.11", 0x14BF8964, 0x400000, 2, 0x2000002, 8, TRUE }, + { "CROMxx", "mpr-20656.10", 0x466BEE13, 0x400000, 2, 0x2000004, 8, TRUE }, + { "CROMxx", "mpr-20655.9", 0xF0A471E9, 0x400000, 2, 0x2000006, 8, TRUE }, + // Banked CROM3 - { "CROMxx", "mpr-20662.16", 0x7130CB61, 0x400000, 2, 0x3000000, 8, TRUE }, - { "CROMxx", "mpr-20661.15", 0x50E6189E, 0x400000, 2, 0x3000002, 8, TRUE }, - { "CROMxx", "mpr-20660.14", 0xD961D385, 0x400000, 2, 0x3000004, 8, TRUE }, - { "CROMxx", "mpr-20659.13", 0xEDB63E7B, 0x400000, 2, 0x3000006, 8, TRUE }, - + { "CROMxx", "mpr-20662.16", 0x7130CB61, 0x400000, 2, 0x3000000, 8, TRUE }, + { "CROMxx", "mpr-20661.15", 0x50E6189E, 0x400000, 2, 0x3000002, 8, TRUE }, + { "CROMxx", "mpr-20660.14", 0xD961D385, 0x400000, 2, 0x3000004, 8, TRUE }, + { "CROMxx", "mpr-20659.13", 0xEDB63E7B, 0x400000, 2, 0x3000006, 8, TRUE }, + // Video ROM - { "VROM", "mpr-20667.26", 0x321E006F, 0x400000, 2, 0, 32, FALSE }, - { "VROM", "mpr-20668.27", 0xC2DD8053, 0x400000, 2, 2, 32, FALSE }, - { "VROM", "mpr-20669.28", 0x63432497, 0x400000, 2, 4, 32, FALSE }, - { "VROM", "mpr-20670.29", 0xF7B554FD, 0x400000, 2, 6, 32, FALSE }, - { "VROM", "mpr-20671.30", 0xFEE1A49B, 0x400000, 2, 8, 32, FALSE }, - { "VROM", "mpr-20672.31", 0xE4B8C6E6, 0x400000, 2, 10, 32, FALSE }, - { "VROM", "mpr-20673.32", 0xE7B6403B, 0x400000, 2, 12, 32, FALSE }, - { "VROM", "mpr-20674.33", 0x9BE22E13, 0x400000, 2, 14, 32, FALSE }, - { "VROM", "mpr-20675.34", 0x6A7C3862, 0x400000, 2, 16, 32, FALSE }, - { "VROM", "mpr-20676.35", 0xDD299648, 0x400000, 2, 18, 32, FALSE }, - { "VROM", "mpr-20677.36", 0x3FC5F330, 0x400000, 2, 20, 32, FALSE }, - { "VROM", "mpr-20678.37", 0x62F794A1, 0x400000, 2, 22, 32, FALSE }, - { "VROM", "mpr-20679.38", 0x35A37C53, 0x400000, 2, 24, 32, FALSE }, - { "VROM", "mpr-20680.39", 0x81FEC46E, 0x400000, 2, 26, 32, FALSE }, - { "VROM", "mpr-20681.40", 0xD517873B, 0x400000, 2, 28, 32, FALSE }, - { "VROM", "mpr-20682.41", 0x5B43250C, 0x400000, 2, 30, 32, FALSE }, + { "VROM", "mpr-20667.26", 0x321E006F, 0x400000, 2, 0, 32, FALSE }, + { "VROM", "mpr-20668.27", 0xC2DD8053, 0x400000, 2, 2, 32, FALSE }, + { "VROM", "mpr-20669.28", 0x63432497, 0x400000, 2, 4, 32, FALSE }, + { "VROM", "mpr-20670.29", 0xF7B554FD, 0x400000, 2, 6, 32, FALSE }, + { "VROM", "mpr-20671.30", 0xFEE1A49B, 0x400000, 2, 8, 32, FALSE }, + { "VROM", "mpr-20672.31", 0xE4B8C6E6, 0x400000, 2, 10, 32, FALSE }, + { "VROM", "mpr-20673.32", 0xE7B6403B, 0x400000, 2, 12, 32, FALSE }, + { "VROM", "mpr-20674.33", 0x9BE22E13, 0x400000, 2, 14, 32, FALSE }, + { "VROM", "mpr-20675.34", 0x6A7C3862, 0x400000, 2, 16, 32, FALSE }, + { "VROM", "mpr-20676.35", 0xDD299648, 0x400000, 2, 18, 32, FALSE }, + { "VROM", "mpr-20677.36", 0x3FC5F330, 0x400000, 2, 20, 32, FALSE }, + { "VROM", "mpr-20678.37", 0x62F794A1, 0x400000, 2, 22, 32, FALSE }, + { "VROM", "mpr-20679.38", 0x35A37C53, 0x400000, 2, 24, 32, FALSE }, + { "VROM", "mpr-20680.39", 0x81FEC46E, 0x400000, 2, 26, 32, FALSE }, + { "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,60 +815,61 @@ 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 - { "CROM", "epr-20920.20", 0x428D05FC, 0x100000, 2, 0x0400000, 8, TRUE }, - { "CROM", "epr-20919.19", 0x7A0713D2, 0x100000, 2, 0x0400002, 8, TRUE }, - { "CROM", "epr-20918.18", 0x0E9CDC5B, 0x100000, 2, 0x0400004, 8, TRUE }, - { "CROM", "epr-20917.17", 0xC3BBB270, 0x100000, 2, 0x0400006, 8, TRUE }, - + { "CROM", "epr-20920.20", 0x428D05FC, 0x100000, 2, 0x0400000, 8, TRUE }, + { "CROM", "epr-20919.19", 0x7A0713D2, 0x100000, 2, 0x0400002, 8, TRUE }, + { "CROM", "epr-20918.18", 0x0E9CDC5B, 0x100000, 2, 0x0400004, 8, TRUE }, + { "CROM", "epr-20917.17", 0xC3BBB270, 0x100000, 2, 0x0400006, 8, TRUE }, + // Banked CROM0 - { "CROMxx", "mpr-19894.4", 0x09C065CC, 0x400000, 2, 0x0000000, 8, TRUE }, - { "CROMxx", "mpr-19893.3", 0x5C83DCAA, 0x400000, 2, 0x0000002, 8, TRUE }, - { "CROMxx", "mpr-19892.2", 0x8E5D3FE7, 0x400000, 2, 0x0000004, 8, TRUE }, - { "CROMxx", "mpr-19891.1", 0x9ECB0B39, 0x400000, 2, 0x0000006, 8, TRUE }, - + { "CROMxx", "mpr-19894.4", 0x09C065CC, 0x400000, 2, 0x0000000, 8, TRUE }, + { "CROMxx", "mpr-19893.3", 0x5C83DCAA, 0x400000, 2, 0x0000002, 8, TRUE }, + { "CROMxx", "mpr-19892.2", 0x8E5D3FE7, 0x400000, 2, 0x0000004, 8, TRUE }, + { "CROMxx", "mpr-19891.1", 0x9ECB0B39, 0x400000, 2, 0x0000006, 8, TRUE }, + // Banked CROM1 - { "CROMxx", "mpr-19776.8", 0x5B31C7C1, 0x400000, 2, 0x1000000, 8, TRUE }, - { "CROMxx", "mpr-19775.7", 0xA6B32BD9, 0x400000, 2, 0x1000002, 8, TRUE }, - { "CROMxx", "mpr-19774.6", 0x1D61D287, 0x400000, 2, 0x1000004, 8, TRUE }, - { "CROMxx", "mpr-19773.5", 0x4E381AE7, 0x400000, 2, 0x1000006, 8, TRUE }, - + { "CROMxx", "mpr-19776.8", 0x5B31C7C1, 0x400000, 2, 0x1000000, 8, TRUE }, + { "CROMxx", "mpr-19775.7", 0xA6B32BD9, 0x400000, 2, 0x1000002, 8, TRUE }, + { "CROMxx", "mpr-19774.6", 0x1D61D287, 0x400000, 2, 0x1000004, 8, TRUE }, + { "CROMxx", "mpr-19773.5", 0x4E381AE7, 0x400000, 2, 0x1000006, 8, TRUE }, + // Banked CROM2 - { "CROMxx", "mpr-20898.12", 0x94040D37, 0x400000, 2, 0x2000000, 8, TRUE }, - { "CROMxx", "mpr-20897.11", 0xC5CF067A, 0x400000, 2, 0x2000002, 8, TRUE }, - { "CROMxx", "mpr-20896.10", 0xBF1CBD5E, 0x400000, 2, 0x2000004, 8, TRUE }, - { "CROMxx", "mpr-20895.9", 0x9B51CBF5, 0x400000, 2, 0x2000006, 8, TRUE }, - + { "CROMxx", "mpr-20898.12", 0x94040D37, 0x400000, 2, 0x2000000, 8, TRUE }, + { "CROMxx", "mpr-20897.11", 0xC5CF067A, 0x400000, 2, 0x2000002, 8, TRUE }, + { "CROMxx", "mpr-20896.10", 0xBF1CBD5E, 0x400000, 2, 0x2000004, 8, TRUE }, + { "CROMxx", "mpr-20895.9", 0x9B51CBF5, 0x400000, 2, 0x2000006, 8, TRUE }, + // Banked CROM3 - { "CROMxx", "mpr-20902.16", 0xF4D3FF3A, 0x400000, 2, 0x3000000, 8, TRUE }, - { "CROMxx", "mpr-20901.15", 0x3492DDC8, 0x400000, 2, 0x3000002, 8, TRUE }, - { "CROMxx", "mpr-20900.14", 0x7A38B571, 0x400000, 2, 0x3000004, 8, TRUE }, - { "CROMxx", "mpr-20899.13", 0x65422425, 0x400000, 2, 0x3000006, 8, TRUE }, - + { "CROMxx", "mpr-20902.16", 0xF4D3FF3A, 0x400000, 2, 0x3000000, 8, TRUE }, + { "CROMxx", "mpr-20901.15", 0x3492DDC8, 0x400000, 2, 0x3000002, 8, TRUE }, + { "CROMxx", "mpr-20900.14", 0x7A38B571, 0x400000, 2, 0x3000004, 8, TRUE }, + { "CROMxx", "mpr-20899.13", 0x65422425, 0x400000, 2, 0x3000006, 8, TRUE }, + // Video ROM - { "VROM", "mpr-19787.26", 0x856CC4AD, 0x200000, 2, 0, 32, FALSE }, - { "VROM", "mpr-19788.27", 0x72EF970A, 0x200000, 2, 2, 32, FALSE }, - { "VROM", "mpr-19789.28", 0x076ADD9A, 0x200000, 2, 4, 32, FALSE }, - { "VROM", "mpr-19790.29", 0x74CE238C, 0x200000, 2, 6, 32, FALSE }, - { "VROM", "mpr-19791.30", 0x75A98F96, 0x200000, 2, 8, 32, FALSE }, - { "VROM", "mpr-19792.31", 0x85C81633, 0x200000, 2, 10, 32, FALSE }, - { "VROM", "mpr-19793.32", 0x7F288CC4, 0x200000, 2, 12, 32, FALSE }, - { "VROM", "mpr-19794.33", 0xE0C1C370, 0x200000, 2, 14, 32, FALSE }, - { "VROM", "mpr-19795.34", 0x90989B20, 0x200000, 2, 16, 32, FALSE }, - { "VROM", "mpr-19796.35", 0x5D1AAB8D, 0x200000, 2, 18, 32, FALSE }, - { "VROM", "mpr-19797.36", 0xF5EDC891, 0x200000, 2, 20, 32, FALSE }, - { "VROM", "mpr-19798.37", 0xAE2DA90F, 0x200000, 2, 22, 32, FALSE }, - { "VROM", "mpr-19799.38", 0x92B18AD7, 0x200000, 2, 24, 32, FALSE }, - { "VROM", "mpr-19800.39", 0x4A57B16C, 0x200000, 2, 26, 32, FALSE }, - { "VROM", "mpr-19801.40", 0xBEB79A00, 0x200000, 2, 28, 32, FALSE }, - { "VROM", "mpr-19802.41", 0xF2C3A7B7, 0x200000, 2, 30, 32, FALSE }, - + { "VROM", "mpr-19787.26", 0x856CC4AD, 0x200000, 2, 0, 32, FALSE }, + { "VROM", "mpr-19788.27", 0x72EF970A, 0x200000, 2, 2, 32, FALSE }, + { "VROM", "mpr-19789.28", 0x076ADD9A, 0x200000, 2, 4, 32, FALSE }, + { "VROM", "mpr-19790.29", 0x74CE238C, 0x200000, 2, 6, 32, FALSE }, + { "VROM", "mpr-19791.30", 0x75A98F96, 0x200000, 2, 8, 32, FALSE }, + { "VROM", "mpr-19792.31", 0x85C81633, 0x200000, 2, 10, 32, FALSE }, + { "VROM", "mpr-19793.32", 0x7F288CC4, 0x200000, 2, 12, 32, FALSE }, + { "VROM", "mpr-19794.33", 0xE0C1C370, 0x200000, 2, 14, 32, FALSE }, + { "VROM", "mpr-19795.34", 0x90989B20, 0x200000, 2, 16, 32, FALSE }, + { "VROM", "mpr-19796.35", 0x5D1AAB8D, 0x200000, 2, 18, 32, FALSE }, + { "VROM", "mpr-19797.36", 0xF5EDC891, 0x200000, 2, 20, 32, FALSE }, + { "VROM", "mpr-19798.37", 0xAE2DA90F, 0x200000, 2, 22, 32, FALSE }, + { "VROM", "mpr-19799.38", 0x92B18AD7, 0x200000, 2, 24, 32, FALSE }, + { "VROM", "mpr-19800.39", 0x4A57B16C, 0x200000, 2, 26, 32, FALSE }, + { "VROM", "mpr-19801.40", 0xBEB79A00, 0x200000, 2, 28, 32, FALSE }, + { "VROM", "mpr-19802.41", 0xF2C3A7B7, 0x200000, 2, 30, 32, FALSE }, + // Sound ROMs - { "SndProg","epr-20921.21", 0x30F032A7, 0x80000, 2, 0, 2, TRUE }, - { "Samples","mpr-20903.22", 0xE343E131, 0x400000, 2, 0x000000, 2, FALSE }, - { "Samples","mpr-20904.24", 0x21A91B84, 0x400000, 2, 0x400000, 2, FALSE }, + { "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 }, { NULL, NULL, 0, 0, 0, 0, 0, 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,55 +1117,63 @@ 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 - { "CROM", "epr-20599a.20", 0x9DF02AB9, 0x200000, 2, 0x0000000, 8, TRUE }, - { "CROM", "epr-20598a.19", 0x87BD070F, 0x200000, 2, 0x0000002, 8, TRUE }, - { "CROM", "epr-20597a.18", 0x6FCEE322, 0x200000, 2, 0x0000004, 8, TRUE }, - { "CROM", "epr-20596a.17", 0x969AB801, 0x200000, 2, 0x0000006, 8, TRUE }, - + { "CROM", "epr-20599a.20", 0x9DF02AB9, 0x200000, 2, 0x0000000, 8, TRUE }, + { "CROM", "epr-20598a.19", 0x87BD070F, 0x200000, 2, 0x0000002, 8, TRUE }, + { "CROM", "epr-20597a.18", 0x6FCEE322, 0x200000, 2, 0x0000004, 8, TRUE }, + { "CROM", "epr-20596a.17", 0x969AB801, 0x200000, 2, 0x0000006, 8, TRUE }, + // Banked CROM0 - { "CROMxx", "mpr-20563.4", 0x999848AC, 0x400000, 2, 0x0000000, 8, TRUE }, - { "CROMxx", "mpr-20562.3", 0x96E4942E, 0x400000, 2, 0x0000002, 8, TRUE }, - { "CROMxx", "mpr-20561.2", 0x38A0F112, 0x400000, 2, 0x0000004, 8, TRUE }, - { "CROMxx", "mpr-20560.1", 0xB0F6584D, 0x400000, 2, 0x0000006, 8, TRUE }, - + { "CROMxx", "mpr-20563.4", 0x999848AC, 0x400000, 2, 0x0000000, 8, TRUE }, + { "CROMxx", "mpr-20562.3", 0x96E4942E, 0x400000, 2, 0x0000002, 8, TRUE }, + { "CROMxx", "mpr-20561.2", 0x38A0F112, 0x400000, 2, 0x0000004, 8, TRUE }, + { "CROMxx", "mpr-20560.1", 0xB0F6584D, 0x400000, 2, 0x0000006, 8, TRUE }, + // Banked CROM1 - { "CROMxx", "mpr-20567.8", 0x80F4EBA7, 0x400000, 2, 0x1000000, 8, TRUE }, - { "CROMxx", "mpr-20566.7", 0x2901883B, 0x400000, 2, 0x1000002, 8, TRUE }, - { "CROMxx", "mpr-20565.6", 0xD6BBE638, 0x400000, 2, 0x1000004, 8, TRUE }, - { "CROMxx", "mpr-20564.5", 0xBE69FCA0, 0x400000, 2, 0x1000006, 8, TRUE }, - + { "CROMxx", "mpr-20567.8", 0x80F4EBA7, 0x400000, 2, 0x1000000, 8, TRUE }, + { "CROMxx", "mpr-20566.7", 0x2901883B, 0x400000, 2, 0x1000002, 8, TRUE }, + { "CROMxx", "mpr-20565.6", 0xD6BBE638, 0x400000, 2, 0x1000004, 8, TRUE }, + { "CROMxx", "mpr-20564.5", 0xBE69FCA0, 0x400000, 2, 0x1000006, 8, TRUE }, + // Banked CROM2 - { "CROMxx", "mpr-20571.12", 0x40B459AF, 0x400000, 2, 0x2000000, 8, TRUE }, - { "CROMxx", "mpr-20570.11", 0x2C0D91FC, 0x400000, 2, 0x2000002, 8, TRUE }, - { "CROMxx", "mpr-20569.10", 0x136C014F, 0x400000, 2, 0x2000004, 8, TRUE }, - { "CROMxx", "mpr-20568.9", 0xFF23CF1C, 0x400000, 2, 0x2000006, 8, TRUE }, + { "CROMxx", "mpr-20571.12", 0x40B459AF, 0x400000, 2, 0x2000000, 8, TRUE }, + { "CROMxx", "mpr-20570.11", 0x2C0D91FC, 0x400000, 2, 0x2000002, 8, TRUE }, + { "CROMxx", "mpr-20569.10", 0x136C014F, 0x400000, 2, 0x2000004, 8, TRUE }, + { "CROMxx", "mpr-20568.9", 0xFF23CF1C, 0x400000, 2, 0x2000006, 8, TRUE }, // Banked CROM3 - { "CROMxx", "mpr-20575.16", 0xEBC99D8A, 0x400000, 2, 0x3000000, 8, TRUE }, - { "CROMxx", "mpr-20574.15", 0x68567771, 0x400000, 2, 0x3000002, 8, TRUE }, - { "CROMxx", "mpr-20573.14", 0xE0DEE793, 0x400000, 2, 0x3000004, 8, TRUE }, - { "CROMxx", "mpr-20572.13", 0xD4A41A0B, 0x400000, 2, 0x3000006, 8, TRUE }, - + { "CROMxx", "mpr-20575.16", 0xEBC99D8A, 0x400000, 2, 0x3000000, 8, TRUE }, + { "CROMxx", "mpr-20574.15", 0x68567771, 0x400000, 2, 0x3000002, 8, TRUE }, + { "CROMxx", "mpr-20573.14", 0xE0DEE793, 0x400000, 2, 0x3000004, 8, TRUE }, + { "CROMxx", "mpr-20572.13", 0xD4A41A0B, 0x400000, 2, 0x3000006, 8, TRUE }, + // Video ROM - { "VROM", "mpr-20580.26", 0x6D42775E, 0x400000, 2, 0, 32, FALSE }, - { "VROM", "mpr-20581.27", 0xAC9EEC04, 0x400000, 2, 2, 32, FALSE }, - { "VROM", "mpr-20582.28", 0xB202F7BD, 0x400000, 2, 4, 32, FALSE }, - { "VROM", "mpr-20583.29", 0x0D6D508A, 0x400000, 2, 6, 32, FALSE }, - { "VROM", "mpr-20584.30", 0xECCF4DE6, 0x400000, 2, 8, 32, FALSE }, - { "VROM", "mpr-20585.31", 0xB383F4E5, 0x400000, 2, 10, 32, FALSE }, - { "VROM", "mpr-20586.32", 0xE7CD5DFB, 0x400000, 2, 12, 32, FALSE }, - { "VROM", "mpr-20587.33", 0xE2B2ABE1, 0x400000, 2, 14, 32, FALSE }, - { "VROM", "mpr-20588.34", 0x84F4162D, 0x400000, 2, 16, 32, FALSE }, - { "VROM", "mpr-20589.35", 0x4E653D02, 0x400000, 2, 18, 32, FALSE }, - { "VROM", "mpr-20590.36", 0x527049BE, 0x400000, 2, 20, 32, FALSE }, - { "VROM", "mpr-20591.37", 0x3BE20243, 0x400000, 2, 22, 32, FALSE }, - { "VROM", "mpr-20592.38", 0xD7985B28, 0x400000, 2, 24, 32, FALSE }, - { "VROM", "mpr-20593.39", 0xE670C4D3, 0x400000, 2, 26, 32, FALSE }, - { "VROM", "mpr-20594.40", 0x35578240, 0x400000, 2, 28, 32, FALSE }, - { "VROM", "mpr-20595.41", 0x1D4A2CAD, 0x400000, 2, 30, 32, FALSE }, + { "VROM", "mpr-20580.26", 0x6D42775E, 0x400000, 2, 0, 32, FALSE }, + { "VROM", "mpr-20581.27", 0xAC9EEC04, 0x400000, 2, 2, 32, FALSE }, + { "VROM", "mpr-20582.28", 0xB202F7BD, 0x400000, 2, 4, 32, FALSE }, + { "VROM", "mpr-20583.29", 0x0D6D508A, 0x400000, 2, 6, 32, FALSE }, + { "VROM", "mpr-20584.30", 0xECCF4DE6, 0x400000, 2, 8, 32, FALSE }, + { "VROM", "mpr-20585.31", 0xB383F4E5, 0x400000, 2, 10, 32, FALSE }, + { "VROM", "mpr-20586.32", 0xE7CD5DFB, 0x400000, 2, 12, 32, FALSE }, + { "VROM", "mpr-20587.33", 0xE2B2ABE1, 0x400000, 2, 14, 32, FALSE }, + { "VROM", "mpr-20588.34", 0x84F4162D, 0x400000, 2, 16, 32, FALSE }, + { "VROM", "mpr-20589.35", 0x4E653D02, 0x400000, 2, 18, 32, FALSE }, + { "VROM", "mpr-20590.36", 0x527049BE, 0x400000, 2, 20, 32, FALSE }, + { "VROM", "mpr-20591.37", 0x3BE20243, 0x400000, 2, 22, 32, FALSE }, + { "VROM", "mpr-20592.38", 0xD7985B28, 0x400000, 2, 24, 32, FALSE }, + { "VROM", "mpr-20593.39", 0xE670C4D3, 0x400000, 2, 26, 32, FALSE }, + { "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,49 +1191,57 @@ 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-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-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-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-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 }, - { "VROM", "mpr-20378.27", 0x5AD7C0EC, 0x400000, 2, 2, 32, FALSE }, - { "VROM", "mpr-20379.28", 0x1E51C9F0, 0x400000, 2, 4, 32, FALSE }, - { "VROM", "mpr-20380.29", 0xE10D35AE, 0x400000, 2, 6, 32, FALSE }, - { "VROM", "mpr-20381.30", 0x76CD36A2, 0x400000, 2, 8, 32, FALSE }, - { "VROM", "mpr-20382.31", 0xF089AE37, 0x400000, 2, 10, 32, FALSE }, - { "VROM", "mpr-20383.32", 0x9E96D3BE, 0x400000, 2, 12, 32, FALSE }, - { "VROM", "mpr-20384.33", 0x5BDFBB52, 0x400000, 2, 14, 32, FALSE }, - { "VROM", "mpr-20385.34", 0x12DB1729, 0x400000, 2, 16, 32, FALSE }, - { "VROM", "mpr-20386.35", 0xDB2CCAF8, 0x400000, 2, 18, 32, FALSE }, - { "VROM", "mpr-20387.36", 0xC5DDE91B, 0x400000, 2, 20, 32, FALSE }, - { "VROM", "mpr-20388.37", 0xAEAA862E, 0x400000, 2, 22, 32, FALSE }, - { "VROM", "mpr-20389.38", 0x49BB6593, 0x400000, 2, 24, 32, FALSE }, - { "VROM", "mpr-20390.39", 0x1D4A8EFE, 0x400000, 2, 26, 32, FALSE }, - { "VROM", "mpr-20391.40", 0x5DC452DC, 0x400000, 2, 28, 32, FALSE }, - { "VROM", "mpr-20392.41", 0x892208CB, 0x400000, 2, 30, 32, FALSE }, + { "VROM", "mpr-20377.26", 0x4D2887E5, 0x400000, 2, 0, 32, FALSE }, + { "VROM", "mpr-20378.27", 0x5AD7C0EC, 0x400000, 2, 2, 32, FALSE }, + { "VROM", "mpr-20379.28", 0x1E51C9F0, 0x400000, 2, 4, 32, FALSE }, + { "VROM", "mpr-20380.29", 0xE10D35AE, 0x400000, 2, 6, 32, FALSE }, + { "VROM", "mpr-20381.30", 0x76CD36A2, 0x400000, 2, 8, 32, FALSE }, + { "VROM", "mpr-20382.31", 0xF089AE37, 0x400000, 2, 10, 32, FALSE }, + { "VROM", "mpr-20383.32", 0x9E96D3BE, 0x400000, 2, 12, 32, FALSE }, + { "VROM", "mpr-20384.33", 0x5BDFBB52, 0x400000, 2, 14, 32, FALSE }, + { "VROM", "mpr-20385.34", 0x12DB1729, 0x400000, 2, 16, 32, FALSE }, + { "VROM", "mpr-20386.35", 0xDB2CCAF8, 0x400000, 2, 18, 32, FALSE }, + { "VROM", "mpr-20387.36", 0xC5DDE91B, 0x400000, 2, 20, 32, FALSE }, + { "VROM", "mpr-20388.37", 0xAEAA862E, 0x400000, 2, 22, 32, FALSE }, + { "VROM", "mpr-20389.38", 0x49BB6593, 0x400000, 2, 24, 32, FALSE }, + { "VROM", "mpr-20390.39", 0x1D4A8EFE, 0x400000, 2, 26, 32, FALSE }, + { "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,49 +1259,57 @@ 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", "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", "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 }, - { "CROMxx", "mpr21457.7", 0x2034DBD4, 0x400000, 2, 0x1000002, 8, TRUE }, - { "CROMxx", "mpr21456.6", 0x73A50547, 0x400000, 2, 0x1000004, 8, TRUE }, - { "CROMxx", "mpr21455.5", 0x0B4A3CC5, 0x400000, 2, 0x1000006, 8, TRUE }, - + { "CROMxx", "mpr21458.8", 0xB748F5A1, 0x400000, 2, 0x1000000, 8, TRUE }, + { "CROMxx", "mpr21457.7", 0x2034DBD4, 0x400000, 2, 0x1000002, 8, TRUE }, + { "CROMxx", "mpr21456.6", 0x73A50547, 0x400000, 2, 0x1000004, 8, TRUE }, + { "CROMxx", "mpr21455.5", 0x0B4A3CC5, 0x400000, 2, 0x1000006, 8, TRUE }, + // Banked CROM2 - { "CROMxx", "mpr21462.12", 0x03D22EE8, 0x400000, 2, 0x2000000, 8, TRUE }, - { "CROMxx", "mpr21462.11", 0x33D8F0DA, 0x400000, 2, 0x2000002, 8, TRUE }, - { "CROMxx", "mpr21461.10", 0x02268361, 0x400000, 2, 0x2000004, 8, TRUE }, - { "CROMxx", "mpr21460.9", 0x71A7B6B3, 0x400000, 2, 0x2000006, 8, TRUE }, + { "CROMxx", "mpr21462.12", 0x03D22EE8, 0x400000, 2, 0x2000000, 8, TRUE }, + { "CROMxx", "mpr21462.11", 0x33D8F0DA, 0x400000, 2, 0x2000002, 8, TRUE }, + { "CROMxx", "mpr21461.10", 0x02268361, 0x400000, 2, 0x2000004, 8, TRUE }, + { "CROMxx", "mpr21460.9", 0x71A7B6B3, 0x400000, 2, 0x2000006, 8, TRUE }, // Video ROM - { "VROM", "mpr21467.26", 0x73635100, 0x400000, 2, 0, 32, FALSE }, - { "VROM", "mpr21468.27", 0x462E5C81, 0x400000, 2, 2, 32, FALSE }, - { "VROM", "mpr21469.28", 0x4BA3F192, 0x400000, 2, 4, 32, FALSE }, - { "VROM", "mpr21470.29", 0x670F0DF5, 0x400000, 2, 6, 32, FALSE }, - { "VROM", "mpr21471.30", 0x1F07E6E3, 0x400000, 2, 8, 32, FALSE }, - { "VROM", "mpr21472.31", 0xE6DC64A3, 0x400000, 2, 10, 32, FALSE }, - { "VROM", "mpr21473.32", 0xD1C9B54A, 0x400000, 2, 12, 32, FALSE }, - { "VROM", "mpr21474.33", 0xAA2F19AE, 0x400000, 2, 14, 32, FALSE }, - { "VROM", "mpr21475.34", 0xBAE9B381, 0x400000, 2, 16, 32, FALSE }, - { "VROM", "mpr21476.35", 0x3833DF51, 0x400000, 2, 18, 32, FALSE }, - { "VROM", "mpr21477.36", 0x46032C35, 0x400000, 2, 20, 32, FALSE }, - { "VROM", "mpr21478.37", 0x35EF75B8, 0x400000, 2, 22, 32, FALSE }, - { "VROM", "mpr21479.38", 0x783E8ECE, 0x400000, 2, 24, 32, FALSE }, - { "VROM", "mpr21480.39", 0xC947BCB8, 0x400000, 2, 26, 32, FALSE }, - { "VROM", "mpr21481.40", 0x6CE566AC, 0x400000, 2, 28, 32, FALSE }, - { "VROM", "mpr21482.41", 0xE995F554, 0x400000, 2, 30, 32, FALSE }, + { "VROM", "mpr21467.26", 0x73635100, 0x400000, 2, 0, 32, FALSE }, + { "VROM", "mpr21468.27", 0x462E5C81, 0x400000, 2, 2, 32, FALSE }, + { "VROM", "mpr21469.28", 0x4BA3F192, 0x400000, 2, 4, 32, FALSE }, + { "VROM", "mpr21470.29", 0x670F0DF5, 0x400000, 2, 6, 32, FALSE }, + { "VROM", "mpr21471.30", 0x1F07E6E3, 0x400000, 2, 8, 32, FALSE }, + { "VROM", "mpr21472.31", 0xE6DC64A3, 0x400000, 2, 10, 32, FALSE }, + { "VROM", "mpr21473.32", 0xD1C9B54A, 0x400000, 2, 12, 32, FALSE }, + { "VROM", "mpr21474.33", 0xAA2F19AE, 0x400000, 2, 14, 32, FALSE }, + { "VROM", "mpr21475.34", 0xBAE9B381, 0x400000, 2, 16, 32, FALSE }, + { "VROM", "mpr21476.35", 0x3833DF51, 0x400000, 2, 18, 32, FALSE }, + { "VROM", "mpr21477.36", 0x46032C35, 0x400000, 2, 20, 32, FALSE }, + { "VROM", "mpr21478.37", 0x35EF75B8, 0x400000, 2, 22, 32, FALSE }, + { "VROM", "mpr21479.38", 0x783E8ECE, 0x400000, 2, 24, 32, FALSE }, + { "VROM", "mpr21480.39", 0xC947BCB8, 0x400000, 2, 26, 32, FALSE }, + { "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", "mpr21091.14", 0x10671951, 0x800000, 2, 0x6000004, 8, TRUE }, - { "CROMxx", "mpr21090.13", 0x749d7979, 0x800000, 2, 0x6000006, 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 }, // 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,49 +1467,57 @@ 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", "epr22898.20", 0xEFB96701, 0x200000, 2, 0x0000000, 8, TRUE }, - { "CROM", "epr22897.19", 0x9755DD8C, 0x200000, 2, 0x0000002, 8, TRUE }, - { "CROM", "epr22896.18", 0x0FF828A8, 0x200000, 2, 0x0000004, 8, TRUE }, - { "CROM", "epr22895.17", 0x07DF16A0, 0x200000, 2, 0x0000006, 8, TRUE }, - + { "CROM", "epr22898.20", 0xEFB96701, 0x200000, 2, 0x0000000, 8, TRUE }, + { "CROM", "epr22897.19", 0x9755DD8C, 0x200000, 2, 0x0000002, 8, TRUE }, + { "CROM", "epr22896.18", 0x0FF828A8, 0x200000, 2, 0x0000004, 8, TRUE }, + { "CROM", "epr22895.17", 0x07DF16A0, 0x200000, 2, 0x0000006, 8, TRUE }, + // Banked CROM0 - { "CROMxx", "mpr22873.4", 0xDD406330, 0x400000, 2, 0x0000000, 8, TRUE }, - { "CROMxx", "mpr22872.3", 0x4FDE63A1, 0x400000, 2, 0x0000002, 8, TRUE }, - { "CROMxx", "mpr22871.2", 0xCF5BB5B5, 0x400000, 2, 0x0000004, 8, TRUE }, - { "CROMxx", "mpr22870.1", 0x52054043, 0x400000, 2, 0x0000006, 8, TRUE }, - + { "CROMxx", "mpr22873.4", 0xDD406330, 0x400000, 2, 0x0000000, 8, TRUE }, + { "CROMxx", "mpr22872.3", 0x4FDE63A1, 0x400000, 2, 0x0000002, 8, TRUE }, + { "CROMxx", "mpr22871.2", 0xCF5BB5B5, 0x400000, 2, 0x0000004, 8, TRUE }, + { "CROMxx", "mpr22870.1", 0x52054043, 0x400000, 2, 0x0000006, 8, TRUE }, + // Banked CROM1 - { "CROMxx", "mpr22877.8", 0xE53B8764, 0x400000, 2, 0x1000000, 8, TRUE }, - { "CROMxx", "mpr22876.7", 0xA7561249, 0x400000, 2, 0x1000002, 8, TRUE }, - { "CROMxx", "mpr22875.6", 0x1BB5C018, 0x400000, 2, 0x1000004, 8, TRUE }, - { "CROMxx", "mpr22874.5", 0x5E990497, 0x400000, 2, 0x1000006, 8, TRUE }, - + { "CROMxx", "mpr22877.8", 0xE53B8764, 0x400000, 2, 0x1000000, 8, TRUE }, + { "CROMxx", "mpr22876.7", 0xA7561249, 0x400000, 2, 0x1000002, 8, TRUE }, + { "CROMxx", "mpr22875.6", 0x1BB5C018, 0x400000, 2, 0x1000004, 8, TRUE }, + { "CROMxx", "mpr22874.5", 0x5E990497, 0x400000, 2, 0x1000006, 8, TRUE }, + // Banked CROM3 - { "CROMxx", "mpr22885.16", 0x3525B46D, 0x400000, 2, 0x3000000, 8, TRUE }, - { "CROMxx", "mpr22884.15", 0x254C3B63, 0x400000, 2, 0x3000002, 8, TRUE }, - { "CROMxx", "mpr22883.14", 0x86D90148, 0x400000, 2, 0x3000004, 8, TRUE }, - { "CROMxx", "mpr22882.13", 0xB161416F, 0x400000, 2, 0x3000006, 8, TRUE }, - + { "CROMxx", "mpr22885.16", 0x3525B46D, 0x400000, 2, 0x3000000, 8, TRUE }, + { "CROMxx", "mpr22884.15", 0x254C3B63, 0x400000, 2, 0x3000002, 8, TRUE }, + { "CROMxx", "mpr22883.14", 0x86D90148, 0x400000, 2, 0x3000004, 8, TRUE }, + { "CROMxx", "mpr22882.13", 0xB161416F, 0x400000, 2, 0x3000006, 8, TRUE }, + // Video ROM - { "VROM", "mpr22854.26", 0x97A23D16, 0x400000, 2, 0, 32, FALSE }, - { "VROM", "mpr22855.27", 0x7249CDC9, 0x400000, 2, 2, 32, FALSE }, - { "VROM", "mpr22856.28", 0x9C0D1D1B, 0x400000, 2, 4, 32, FALSE }, - { "VROM", "mpr22857.29", 0x44E6CE2B, 0x400000, 2, 6, 32, FALSE }, - { "VROM", "mpr22858.30", 0x0AF40AAE, 0x400000, 2, 8, 32, FALSE }, - { "VROM", "mpr22859.31", 0xC64F0158, 0x400000, 2, 10, 32, FALSE }, - { "VROM", "mpr22860.32", 0x053AF14B, 0x400000, 2, 12, 32, FALSE }, - { "VROM", "mpr22861.33", 0xD26343DA, 0x400000, 2, 14, 32, FALSE }, - { "VROM", "mpr22862.34", 0x38347C14, 0x400000, 2, 16, 32, FALSE }, - { "VROM", "mpr22863.35", 0x28B558E6, 0x400000, 2, 18, 32, FALSE }, - { "VROM", "mpr22864.36", 0x31ED02F6, 0x400000, 2, 20, 32, FALSE }, - { "VROM", "mpr22865.37", 0x3E3A211A, 0x400000, 2, 22, 32, FALSE }, - { "VROM", "mpr22866.38", 0xA863A3C8, 0x400000, 2, 24, 32, FALSE }, - { "VROM", "mpr22867.39", 0x1CE6C7B2, 0x400000, 2, 26, 32, FALSE }, - { "VROM", "mpr22868.40", 0x2DB40CF8, 0x400000, 2, 28, 32, FALSE }, - { "VROM", "mpr22869.41", 0xC6D62634, 0x400000, 2, 30, 32, FALSE }, + { "VROM", "mpr22854.26", 0x97A23D16, 0x400000, 2, 0, 32, FALSE }, + { "VROM", "mpr22855.27", 0x7249CDC9, 0x400000, 2, 2, 32, FALSE }, + { "VROM", "mpr22856.28", 0x9C0D1D1B, 0x400000, 2, 4, 32, FALSE }, + { "VROM", "mpr22857.29", 0x44E6CE2B, 0x400000, 2, 6, 32, FALSE }, + { "VROM", "mpr22858.30", 0x0AF40AAE, 0x400000, 2, 8, 32, FALSE }, + { "VROM", "mpr22859.31", 0xC64F0158, 0x400000, 2, 10, 32, FALSE }, + { "VROM", "mpr22860.32", 0x053AF14B, 0x400000, 2, 12, 32, FALSE }, + { "VROM", "mpr22861.33", 0xD26343DA, 0x400000, 2, 14, 32, FALSE }, + { "VROM", "mpr22862.34", 0x38347C14, 0x400000, 2, 16, 32, FALSE }, + { "VROM", "mpr22863.35", 0x28B558E6, 0x400000, 2, 18, 32, FALSE }, + { "VROM", "mpr22864.36", 0x31ED02F6, 0x400000, 2, 20, 32, FALSE }, + { "VROM", "mpr22865.37", 0x3E3A211A, 0x400000, 2, 22, 32, FALSE }, + { "VROM", "mpr22866.38", 0xA863A3C8, 0x400000, 2, 24, 32, FALSE }, + { "VROM", "mpr22867.39", 0x1CE6C7B2, 0x400000, 2, 26, 32, FALSE }, + { "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 }, diff --git a/Src/Games.h b/Src/Games.h index c136fd9..575f998 100644 --- a/Src/Games.h +++ b/Src/Games.h @@ -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]; }; diff --git a/Src/Graphics/Render.h b/Src/Graphics/Render.h deleted file mode 100644 index cea99d3..0000000 --- a/Src/Graphics/Render.h +++ /dev/null @@ -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 . - **/ - -/* - * 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 diff --git a/Src/Model3/DSB.cpp b/Src/Model3/DSB.cpp new file mode 100644 index 0000000..d79ecf9 --- /dev/null +++ b/Src/Model3/DSB.cpp @@ -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 . + **/ + +/* + * 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"); +} \ No newline at end of file diff --git a/Src/Model3/DSB.h b/Src/Model3/DSB.h new file mode 100644 index 0000000..590b9d2 --- /dev/null +++ b/Src/Model3/DSB.h @@ -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 . + **/ + +/* + * 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 diff --git a/Src/Model3/Model3.cpp b/Src/Model3/Model3.cpp index 2a71980..e156bd6 100644 --- a/Src/Model3/Model3.cpp +++ b/Src/Model3/Model3.cpp @@ -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; diff --git a/Src/Model3/Model3.h b/Src/Model3/Model3.h index 4bb795a..22af53a 100644 --- a/Src/Model3/Model3.h +++ b/Src/Model3/Model3.h @@ -250,7 +250,7 @@ public: */ CModel3(void); ~CModel3(void); - + /* * Private Property. * Tresspassers will be shot! ;) @@ -265,14 +265,14 @@ private: UINT8 ReadSystemRegister(unsigned reg); void WriteSystemRegister(unsigned reg, UINT8 data); void Patch(void); - + void RunMainBoardFrame(); // Runs the main board (PPC) for a frame - bool StartThreads(); // Starts all threads + bool StartThreads(); // Starts all threads void StopThreads(); // Stops all threads void DeleteThreadObjects(); // Deletes all threads and synchronization objects - - static int StartSoundBoardThread(void *data); // Callback to start sound board thread -#ifdef SUPERMODEL_DRIVEBOARD + + static int StartSoundBoardThread(void *data); // Callback to start sound board thread +#ifdef SUPERMODEL_DRIVEBOARD static int StartDriveBoardThread(void *data); // Callback to start drive board thread #endif @@ -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 @@ -318,23 +320,23 @@ private: unsigned ppcFrequency; // clock frequency (Hz) // Multiple threading - bool multiThreaded; // True if should run CPUs in multiple threads, otherwise everything is run in a single thread - bool startedThreads; // True if threads have been created and started - CThread *sndBrdThread; // Sound board thread -#ifdef SUPERMODEL_DRIVEBOARD - CThread *drvBrdThread; // Drive board thread -#endif - bool sndBrdThreadDone; // Flag to indicate sound board thread has finished processing for current frame -#ifdef SUPERMODEL_DRIVEBOARD - bool drvBrdThreadDone; // Flag to indicate drive board thread has finished processing for current frame -#endif - - // Thread synchronization objects - CSemaphore *sndBrdThreadSync; -#ifdef SUPERMODEL_DRIVEBOARD - CSemaphore *drvBrdThreadSync; -#endif - CMutex *notifyLock; + bool multiThreaded; // True if should run CPUs in multiple threads, otherwise everything is run in a single thread + bool startedThreads; // True if threads have been created and started + CThread *sndBrdThread; // Sound board thread +#ifdef SUPERMODEL_DRIVEBOARD + CThread *drvBrdThread; // Drive board thread +#endif + bool sndBrdThreadDone; // Flag to indicate sound board thread has finished processing for current frame +#ifdef SUPERMODEL_DRIVEBOARD + bool drvBrdThreadDone; // Flag to indicate drive board thread has finished processing for current frame +#endif + + // Thread synchronization objects + CSemaphore *sndBrdThreadSync; +#ifdef SUPERMODEL_DRIVEBOARD + CSemaphore *drvBrdThreadSync; +#endif + CMutex *notifyLock; CCondVar *notifySync; // Other devices @@ -346,7 +348,8 @@ private: C93C46 EEPROM; // 93C46 EEPROM CTileGen TileGen; // Sega 2D tile generator CReal3D GPU; // Real3D graphics hardware - CSoundBoard SoundBoard; // Sound board + CSoundBoard SoundBoard; // Sound board + CDSB *DSB; // Digital Sound Board (type determined dynamically at load time) #ifdef SUPERMODEL_DRIVEBOARD CDriveBoard DriveBoard; // Drive board #endif diff --git a/Src/Model3/SoundBoard.cpp b/Src/Model3/SoundBoard.cpp index 8b4e50d..94f19e8 100644 --- a/Src/Model3/SoundBoard.cpp +++ b/Src/Model3/SoundBoard.cpp @@ -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]; - - // SCSP RAM 2 - else if ((a >= 0x200000) && (a <= 0x2FFFFF)) - return sbRAM2[(a-0x200000)^1]; + switch ((a>>20)&0xF) + { + case 0x0: // SCSP RAM 1 (master): 000000-0FFFFF + return ram1[a^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]; - - // SCSP RAM 2 - else if ((a >= 0x200000) && (a <= 0x2FFFFF)) - return *(UINT16 *) &sbRAM2[(a-0x200000)]; + switch ((a>>20)&0xF) + { + case 0x0: // SCSP RAM 1 (master): 000000-0FFFFF + return *(UINT16 *) &ram1[a]; - // 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) -{ - // SCSP RAM 1 - if ((a >= 0x000000) && (a <= 0x0FFFFF)) - return (Read16(a)<<16)|Read16(a+2); +UINT32 CSoundBoard::Read32(UINT32 a) +{ + 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) { - - // 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)) - SCSP_Master_w8(a,d); - - // SCSP (Slave) - else if ((a >= 0x300000) && (a <= 0x30FFFF)) - SCSP_Slave_w8(a,d); - - // Bank register - else if (a == 0x400001) + switch ((a>>20)&0xF) { - if ((d&0x10)) + case 0x0: // SCSP RAM 1 (master): 000000-0FFFFF + ram1[a^1] = d; + break; + + case 0x1: // SCSP registers (master): 100000-10FFFF + SCSP_Master_w8(a,d); + break; + + 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; + + default: + if (a == 0x400001) { - sbSampleBankLo = &sbSampleROM[0xA00000]; - sbSampleBankHi = &sbSampleROM[0xE00000]; + if ((d&0x10)) + { + sampleBankLo = &sampleROM[0xA00000]; + sampleBankHi = &sampleROM[0xE00000]; + } + else + { + sampleBankLo = &sampleROM[0x200000]; + sampleBankHi = &sampleROM[0x600000]; + } } else - { - sbSampleBankLo = &sbSampleROM[0x200000]; - sbSampleBankHi = &sbSampleROM[0x600000]; - } + printf("68K: Unknown write8 %06X=%02X\n", a, d); + break; } - - // Unknown - else - printf("68K: Unknown write8 %06X=%02X\n", a, d); } -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)) - SCSP_Slave_w16(a,d); - - // Unknown - else - printf("68K: Unknown write16 %06X=%04X\n", a, d); + 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; + + 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); - - // Unknown - else + break; + + 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]; + audioL = (INT16 *) &memoryPool[OFFSET_AUDIO_LEFT]; + audioR = (INT16 *) &memoryPool[OFFSET_AUDIO_RIGHT]; - // Make global copies of memory pointers for 68K access handlers - sbRAM1 = ram1; - sbRAM2 = ram2; - sbSoundROM = soundROM; - sbSampleROM = sampleROM; - sbSampleBankLo = &sampleROM[0x200000]; - sbSampleBankHi = &sampleROM[0x600000]; - // 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"); } diff --git a/Src/Model3/SoundBoard.h b/Src/Model3/SoundBoard.h index 566b892..1d8ec60 100644 --- a/Src/Model3/SoundBoard.h +++ b/Src/Model3/SoundBoard.h @@ -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) }; diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index 28c57d2..07338fa 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -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()) diff --git a/Src/ROMLoad.cpp b/Src/ROMLoad.cpp index 00498bd..89610fb 100644 --- a/Src/ROMLoad.cpp +++ b/Src/ROMLoad.cpp @@ -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,8 +206,9 @@ const struct GameInfo * LoadROMSetFromZIPFile(const struct ROMMap *Map, const st { unzFile zf; unz_file_info fileInfo; - const struct GameInfo *Game = NULL, *CurGame; - int romIdx; // index within Game->ROM + 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; unsigned i, n, maxSize; @@ -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,54 +238,73 @@ 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++) ; - + // If not all ROMs were present, tell the user err = OKAY; 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,13 +333,14 @@ 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 - { - if (OKAY == LoadROM(buf, maxSize, Map, &Game->ROM[romIdx], zf, zipFile, loadAll)) - romsFound[romIdx] = 1; // success! mark as loaded - } + + // 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 @@ -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; diff --git a/Src/ROMLoad.h b/Src/ROMLoad.h index 1d03174..53c23a4 100644 --- a/Src/ROMLoad.h +++ b/Src/ROMLoad.h @@ -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) diff --git a/Src/Sound/MPEG/MPEG.h b/Src/Sound/MPEG/MPEG.h new file mode 100644 index 0000000..29025d3 --- /dev/null +++ b/Src/Sound/MPEG/MPEG.h @@ -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 . + **/ + +/* + * 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 \ No newline at end of file diff --git a/Src/Sound/MPEG/amp.h b/Src/Sound/MPEG/amp.h new file mode 100644 index 0000000..7bc0002 --- /dev/null +++ b/Src/Sound/MPEG/amp.h @@ -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; diff --git a/Src/Sound/MPEG/audio.cpp b/Src/Sound/MPEG/audio.cpp new file mode 100644 index 0000000..dee1a23 --- /dev/null +++ b/Src/Sound/MPEG/audio.cpp @@ -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 +#include +#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; +} + diff --git a/Src/Sound/MPEG/audio.h b/Src/Sound/MPEG/audio.h new file mode 100644 index 0000000..0d0bbfb --- /dev/null +++ b/Src/Sound/MPEG/audio.h @@ -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 + +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 */ diff --git a/Src/Sound/MPEG/config.h b/Src/Sound/MPEG/config.h new file mode 100644 index 0000000..b448ee1 --- /dev/null +++ b/Src/Sound/MPEG/config.h @@ -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 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 and . */ +//#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 header file. */ +/* #undef HAVE_DMEDIA_AUDIO_H */ + +/* Define if you have the header file. */ +//#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +//#define HAVE_LINUX_SOUNDCARD_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_MACHINE_SOUNDCARD_H */ + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define if you have the header file. */ +//#define HAVE_SYS_IOCTL_H 1 + +/* Define if you have the header file. */ +//#define HAVE_SYS_SELECT_H 1 + +/* Define if you have the header file. */ +//#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* define if you want playing to use Linux realtime features */ +/* #undef LINUX_REALTIME */ diff --git a/Src/Sound/MPEG/dump.cpp b/Src/Sound/MPEG/dump.cpp new file mode 100644 index 0000000..cc53403 --- /dev/null +++ b/Src/Sound/MPEG/dump.cpp @@ -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 +#include + +#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> (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); +} diff --git a/Src/Sound/MPEG/dump.h b/Src/Sound/MPEG/dump.h new file mode 100644 index 0000000..79ebbcd --- /dev/null +++ b/Src/Sound/MPEG/dump.h @@ -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 */ diff --git a/Src/Sound/MPEG/formats.h b/Src/Sound/MPEG/formats.h new file mode 100644 index 0000000..7146258 --- /dev/null +++ b/Src/Sound/MPEG/formats.h @@ -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 */ diff --git a/Src/Sound/MPEG/getbits.cpp b/Src/Sound/MPEG/getbits.cpp new file mode 100644 index 0000000..424307e --- /dev/null +++ b/Src/Sound/MPEG/getbits.cpp @@ -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 +#include +#include +#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;chscfsi[ch][scfsi_band]=_getbits(1); + + for (gr=0;gr<(header->ID ? 2:1);gr++) + for (ch=0;chpart2_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 */ +} diff --git a/Src/Sound/MPEG/getbits.h b/Src/Sound/MPEG/getbits.h new file mode 100644 index 0000000..3aa9c5a --- /dev/null +++ b/Src/Sound/MPEG/getbits.h @@ -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 */ + diff --git a/Src/Sound/MPEG/getdata.cpp b/Src/Sound/MPEG/getdata.cpp new file mode 100644 index 0000000..fe1f8a5 --- /dev/null +++ b/Src/Sound/MPEG/getdata.cpp @@ -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;kblock_type[0][ch]==2) + { + if (!info->mixed_block_flag[0][ch]) { + sfb=0; + for (j=1;j<=4;j++) + for (k=0;k +#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 (;l0) { + 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; +} diff --git a/Src/Sound/MPEG/huffman.h b/Src/Sound/MPEG/huffman.h new file mode 100644 index 0000000..440d258 --- /dev/null +++ b/Src/Sound/MPEG/huffman.h @@ -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 */ diff --git a/Src/Sound/MPEG/layer2.cpp b/Src/Sound/MPEG/layer2.cpp new file mode 100644 index 0000000..852dcdc --- /dev/null +++ b/Src/Sound/MPEG/layer2.cpp @@ -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>2]; + } + } + } else + for (s=0;s<3;s++) subband_sample[ch][sb][3*gr+s]=0; + + + /* + * joint stereo ******************************************** + */ + + for (sb=bound;sb>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;chmode!=3) { + for (ch=0;chmode!=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; +} diff --git a/Src/Sound/MPEG/layer2.h b/Src/Sound/MPEG/layer2.h new file mode 100644 index 0000000..5dacc4f --- /dev/null +++ b/Src/Sound/MPEG/layer2.h @@ -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 */ diff --git a/Src/Sound/MPEG/layer3.cpp b/Src/Sound/MPEG/layer3.cpp new file mode 100644 index 0000000..a0161fb --- /dev/null +++ b/Src/Sound/MPEG/layer3.cpp @@ -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;chmode!=1 || (header->mode==1 && header->mode_extension==0)) + for (ch=0;chmode!=3) nch=2; + + } /* for (gr... */ + + /* return status: 0 for ok, errors will be added + */ + return 0; +} + diff --git a/Src/Sound/MPEG/layer3.h b/Src/Sound/MPEG/layer3.h new file mode 100644 index 0000000..d8c08ed --- /dev/null +++ b/Src/Sound/MPEG/layer3.h @@ -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 */ diff --git a/Src/Sound/MPEG/misc2.cpp b/Src/Sound/MPEG/misc2.cpp new file mode 100644 index 0000000..fd5b7e5 --- /dev/null +++ b/Src/Sound/MPEG/misc2.cpp @@ -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 +#include + +#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 (lsubblock_gain[gr][ch][window]; + a=fras_s(global_gain,subblock_gain,scalefac_scale,scalefac); + for (i=0;iID][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 (lsubblock_gain[gr][ch][window]; + float a=fras_s(global_gain,subblock_gain,scalefac_scale,scalefac); + for (i=0;iID][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 (lmode_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;imixed_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]=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 (lsubblock_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;isubblock_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;ipreflag[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>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>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); +} diff --git a/Src/Sound/MPEG/misc2.h b/Src/Sound/MPEG/misc2.h new file mode 100644 index 0000000..51fc987 --- /dev/null +++ b/Src/Sound/MPEG/misc2.h @@ -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 diff --git a/Src/Sound/MPEG/position.cpp b/Src/Sound/MPEG/position.cpp new file mode 100644 index 0000000..0e231f8 --- /dev/null +++ b/Src/Sound/MPEG/position.cpp @@ -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 +#include +#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) + */ diff --git a/Src/Sound/MPEG/position.h b/Src/Sound/MPEG/position.h new file mode 100644 index 0000000..cce0856 --- /dev/null +++ b/Src/Sound/MPEG/position.h @@ -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 diff --git a/Src/Sound/MPEG/proto.h b/Src/Sound/MPEG/proto.h new file mode 100644 index 0000000..3524812 --- /dev/null +++ b/Src/Sound/MPEG/proto.h @@ -0,0 +1,26 @@ +/* From: util.c */ +void die(char *, ...); +void warn(char *, ...); +void msg(char *, ...); +void debugSetup(char *); +void debugOptions(); + +/* From: audioIO_.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(); diff --git a/Src/Sound/MPEG/rtbuf.h b/Src/Sound/MPEG/rtbuf.h new file mode 100644 index 0000000..de67400 --- /dev/null +++ b/Src/Sound/MPEG/rtbuf.h @@ -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 */ + diff --git a/Src/Sound/MPEG/transform.cpp b/Src/Sound/MPEG/transform.cpp new file mode 100644 index 0000000..03dfbb3 --- /dev/null +++ b/Src/Sound/MPEG/transform.cpp @@ -0,0 +1,1518 @@ +/* this file is a part of amp software, (C) tomislav uzelac 1996,1997 +*/ + +/* transform.c imdct and polyphase(DCT) transforms + * + * Created by: tomislav uzelac May 1996 + * Karl Anders Oygard optimized this for speed, Mar 13 97 + * Some optimisations based on ideas from Michael Hipp's mpg123 package + */ + +/* + * Comments for this file: + * + * The polyphase algorithm is clearly the most cpu consuming part of mpeg 1 + * layer 3 decoding. Thus, there has been some effort to optimise this + * particular algorithm. Currently, everything has been kept in straight C + * with no assembler optimisations, but in order to provide efficient paths + * for different architectures, alternative implementations of some + * critical sections has been done. You may want to experiment with these, + * to see which suits your architecture better. + * + * Selection of the different implementations is done with the following + * defines: + * + * HAS_AUTOINCREMENT + * + * Define this if your architecture supports preincrementation of + * pointers when referencing (applies to e.g. 68k) + * + * For those who are optimising amp, check out the Pentium rdtsc code + * (define PENTIUM_RDTSC). This code uses the rdtsc counter for showing + * how many cycles are spent in different parts of the code. + */ + +#include + +#include "audio.h" +#include "getdata.h" +#include "misc2.h" + +#define TRANSFORM +#include "transform.h" + +#define PI12 0.261799387f +#define PI36 0.087266462f + +void imdct_init() +{ + int i; + + for(i=0;i<36;i++) /* 0 */ + win[0][i] = (float) sin(PI36 *(i+0.5)); + for(i=0;i<18;i++) /* 1 */ + win[1][i] = (float) sin(PI36 *(i+0.5)); + for(i=18;i<24;i++) + win[1][i] = 1.0f; + for(i=24;i<30;i++) + win[1][i] = (float) sin(PI12 *(i+0.5-18)); + for(i=30;i<36;i++) + win[1][i] = 0.0f; + for(i=0;i<6;i++) /* 3 */ + win[3][i] = 0.0f; + for(i=6;i<12;i++) + win[3][i] = (float) sin(PI12 * (i+ 0.5 - 6.0)); + for(i=12;i<18;i++) + win[3][i] = 1.0f; + for(i=18;i<36;i++) + win[3][i] = (float) sin(PI36 * (i + 0.5)); +} + +/* This uses Byeong Gi Lee's Fast Cosine Transform algorithm to decompose + the 36 point and 12 point IDCT's into 9 point and 3 point IDCT's, + respectively. Then the 9 point IDCT is computed by a modified version of + Mikko Tommila's IDCT algorithm, based on the WFTA. See his comments + before the first 9 point IDCT. The 3 point IDCT is already efficient to + implement. -- Jeff Tsay. */ +/* I got the unrolled IDCT from Jeff Tsay; the code is presumably by + Francois-Raymond Boyer - I unrolled it a little further. tu */ + +void imdct(int win_type,int sb,int ch) +{ +/*------------------------------------------------------------------*/ +/* */ +/* Function: Calculation of the inverse MDCT */ +/* In the case of short blocks the 3 output vectors are already */ +/* overlapped and added in this modul. */ +/* */ +/* New layer3 */ +/* */ +/*------------------------------------------------------------------*/ + + float tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11; + + register float save; + float pp1, pp2; + float *win_bt; + int i, p, ss; + float *in = xr[ch][sb]; + float *s_p = s[ch][sb]; + float *res_p = res[sb]; + float out[36]; + + if(win_type == 2){ + for(p=0;p<36;p+=9) { + out[p] = out[p+1] = out[p+2] = out[p+3] = + out[p+4] = out[p+5] = out[p+6] = out[p+7] = + out[p+8] = 0.0f; + } + + for(ss=0;ss<18;ss+=6) { + + /* + * 12 point IMDCT + */ + + /* Begin 12 point IDCT */ + + /* Input aliasing for 12 pt IDCT */ + in[5+ss]+=in[4+ss];in[4+ss]+=in[3+ss];in[3+ss]+=in[2+ss]; + in[2+ss]+=in[1+ss];in[1+ss]+=in[0+ss]; + + /* Input aliasing on odd indices (for 6 point IDCT) */ + in[5+ss] += in[3+ss]; in[3+ss] += in[1+ss]; + + /* 3 point IDCT on even indices */ + + pp2 = in[4+ss] * 0.500000000f; + pp1 = in[2+ss] * 0.866025403f; + save = in[0+ss] + pp2; + tmp1 = in[0+ss] - in[4+ss]; + tmp0 = save + pp1; + tmp2 = save - pp1; + + /* End 3 point IDCT on even indices */ + + /* 3 point IDCT on odd indices (for 6 point IDCT) */ + + pp2 = in[5+ss] * 0.500000000f; + pp1 = in[3+ss] * 0.866025403f; + save = in[1+ss] + pp2; + tmp4 = in[1+ss] - in[5+ss]; + tmp5 = save + pp1; + tmp3 = save - pp1; + + /* End 3 point IDCT on odd indices */ + + /* Twiddle factors on odd indices (for 6 point IDCT) */ + + tmp3 *= 1.931851653f; + tmp4 *= 0.707106781f; + tmp5 *= 0.517638090f; + + /* Output butterflies on 2 3 point IDCT's (for 6 point IDCT) */ + + save = tmp0; + tmp0 += tmp5; + tmp5 = save - tmp5; + + save = tmp1; + tmp1 += tmp4; + tmp4 = save - tmp4; + + save = tmp2; + tmp2 += tmp3; + tmp3 = save - tmp3; + + /* End 6 point IDCT */ + + /* Twiddle factors on indices (for 12 point IDCT) */ + + tmp0 *= 0.504314480f; + tmp1 *= 0.541196100f; + tmp2 *= 0.630236207f; + tmp3 *= 0.821339815f; + tmp4 *= 1.306562965f; + tmp5 *= 3.830648788f; + + /* End 12 point IDCT */ + + /* Shift to 12 point modified IDCT, multiply by window type 2 */ + tmp8 = tmp0 * -0.793353340f; + tmp9 = tmp0 * -0.608761429f; + tmp7 = tmp1 * -0.923879532f; + tmp10 = tmp1 * -0.382683432f; + tmp6 = tmp2 * -0.991444861f; + tmp11 = tmp2 * -0.130526192f; + + tmp0 = tmp3; + tmp1 = tmp4 * 0.382683432f; + tmp2 = tmp5 * 0.608761429f; + + tmp3 = tmp5 * -0.793353340f; + tmp4 = tmp4 * -0.923879532f; + tmp5 = tmp0 * -0.991444861f; + + tmp0 *= 0.130526192f; + + out[ss + 6] += tmp0; + out[ss + 7] += tmp1; + out[ss + 8] += tmp2; + out[ss + 9] += tmp3; + out[ss + 10] += tmp4; + out[ss + 11] += tmp5; + out[ss + 12] += tmp6; + out[ss + 13] += tmp7; + out[ss + 14] += tmp8; + out[ss + 15] += tmp9; + out[ss + 16] += tmp10; + out[ss + 17] += tmp11; + + } + if (sb&1) { + for (i=0;i<18;i+=2) res_p[i]=out[i] + s_p[i]; + for (i=1;i<18;i+=2) res_p[i]=-out[i] - s_p[i]; + } else + for (i=0;i<18;i++) res_p[i]=out[i] + s_p[i]; + for (i=18;i<36;i++) s_p[i-18]=out[i]; + + } else { +/* + * 36 point IDCT **************************************************************** + */ + float tmp[18]; + + /* input aliasing for 36 point IDCT */ + in[17]+=in[16]; in[16]+=in[15]; in[15]+=in[14]; in[14]+=in[13]; + in[13]+=in[12]; in[12]+=in[11]; in[11]+=in[10]; in[10]+=in[9]; + in[9] +=in[8]; in[8] +=in[7]; in[7] +=in[6]; in[6] +=in[5]; + in[5] +=in[4]; in[4] +=in[3]; in[3] +=in[2]; in[2] +=in[1]; + in[1] +=in[0]; + + /* 18 point IDCT for odd indices */ + + /* input aliasing for 18 point IDCT */ + in[17]+=in[15]; in[15]+=in[13]; in[13]+=in[11]; in[11]+=in[9]; + in[9] +=in[7]; in[7] +=in[5]; in[5] +=in[3]; in[3] +=in[1]; + + +{ + float tmp0,tmp1,tmp2,tmp3,tmp4,tmp0_,tmp1_,tmp2_,tmp3_; + float tmp0o,tmp1o,tmp2o,tmp3o,tmp4o,tmp0_o,tmp1_o,tmp2_o,tmp3_o; + +/* Fast 9 Point Inverse Discrete Cosine Transform +// +// By Francois-Raymond Boyer +// mailto:boyerf@iro.umontreal.ca +// http://www.iro.umontreal.ca/~boyerf +// +// The code has been optimized for Intel processors +// (takes a lot of time to convert float to and from iternal FPU representation) +// +// It is a simple "factorization" of the IDCT matrix. +*/ + /* 9 point IDCT on even indices */ + { + /* 5 points on odd indices (not realy an IDCT) */ + float i0 = in[0]+in[0]; + float i0p12 = i0 + in[12]; + + tmp0 = i0p12 + in[4]*1.8793852415718f + in[8]*1.532088886238f + in[16]*0.34729635533386f; + tmp1 = i0 + in[4] - in[8] - in[12] - in[12] - in[16]; + tmp2 = i0p12 - in[4]*0.34729635533386f - in[8]*1.8793852415718f + in[16]*1.532088886238f; + tmp3 = i0p12 - in[4]*1.532088886238f + in[8]*0.34729635533386f - in[16]*1.8793852415718f; + tmp4 = in[0] - in[4] + in[8] - in[12] + in[16]; + } + { + float i6_ = in[6]*1.732050808f; + + tmp0_ = in[2]*1.9696155060244f + i6_ + in[10]*1.2855752193731f + in[14]*0.68404028665134f; + tmp1_ = (in[2] - in[10] - in[14])*1.732050808f; + tmp2_ = in[2]*1.2855752193731f - i6_ - in[10]*0.68404028665134f + in[14]*1.9696155060244f; + tmp3_ = in[2]*0.68404028665134f - i6_ + in[10]*1.9696155060244f - in[14]*1.2855752193731f; + } + + /* 9 point IDCT on odd indices */ + { + /* 5 points on odd indices (not realy an IDCT) */ + float i0 = in[0+1]+in[0+1]; + float i0p12 = i0 + in[12+1]; + + tmp0o = i0p12 + in[4+1]*1.8793852415718f + in[8+1]*1.532088886238f + in[16+1]*0.34729635533386f; + tmp1o = i0 + in[4+1] - in[8+1] - in[12+1] - in[12+1] - in[16+1]; + tmp2o = i0p12 - in[4+1]*0.34729635533386f - in[8+1]*1.8793852415718f + in[16+1]*1.532088886238f; + tmp3o = i0p12 - in[4+1]*1.532088886238f + in[8+1]*0.34729635533386f - in[16+1]*1.8793852415718f; + tmp4o = (in[0+1] - in[4+1] + in[8+1] - in[12+1] + in[16+1])*0.707106781f; /* Twiddled */ + } + { + /* 4 points on even indices */ + float i6_ = in[6+1]*1.732050808f; /* Sqrt[3] */ + + tmp0_o = in[2+1]*1.9696155060244f + i6_ + in[10+1]*1.2855752193731f + in[14+1]*0.68404028665134f; + tmp1_o = (in[2+1] - in[10+1] - in[14+1])*1.732050808f; + tmp2_o = in[2+1]*1.2855752193731f - i6_ - in[10+1]*0.68404028665134f + in[14+1]*1.9696155060244f; + tmp3_o = in[2+1]*0.68404028665134f - i6_ + in[10+1]*1.9696155060244f - in[14+1]*1.2855752193731f; + } + + /* Twiddle factors on odd indices + // and + // Butterflies on 9 point IDCT's + // and + // twiddle factors for 36 point IDCT + */ + { + float e, o; + e = tmp0 + tmp0_; o = (tmp0o + tmp0_o)*0.501909918f; tmp[0] = (e + o)*(-0.500476342f*.5f); tmp[17] = (e - o)*(-11.46279281f*.5f); + e = tmp1 + tmp1_; o = (tmp1o + tmp1_o)*0.517638090f; tmp[1] = (e + o)*(-0.504314480f*.5f); tmp[16] = (e - o)*(-3.830648788f*.5f); + e = tmp2 + tmp2_; o = (tmp2o + tmp2_o)*0.551688959f; tmp[2] = (e + o)*(-0.512139757f*.5f); tmp[15] = (e - o)*(-2.310113158f*.5f); + e = tmp3 + tmp3_; o = (tmp3o + tmp3_o)*0.610387294f; tmp[3] = (e + o)*(-0.524264562f*.5f); tmp[14] = (e - o)*(-1.662754762f*.5f); + tmp[4] = (tmp4 + tmp4o)*(-0.541196100f); tmp[13] = (tmp4 - tmp4o)*(-1.306562965f); + e = tmp3 - tmp3_; o = (tmp3o - tmp3_o)*0.871723397f; tmp[5] = (e + o)*(-0.563690973f*.5f); tmp[12] = (e - o)*(-1.082840285f*.5f); + e = tmp2 - tmp2_; o = (tmp2o - tmp2_o)*1.183100792f; tmp[6] = (e + o)*(-0.592844523f*.5f); tmp[11] = (e - o)*(-0.930579498f*.5f); + e = tmp1 - tmp1_; o = (tmp1o - tmp1_o)*1.931851653f; tmp[7] = (e + o)*(-0.630236207f*.5f); tmp[10] = (e - o)*(-0.821339815f*.5f); + e = tmp0 - tmp0_; o = (tmp0o - tmp0_o)*5.736856623f; tmp[8] = (e + o)*(-0.678170852f*.5f); tmp[9] = (e - o)*(-0.740093616f*.5f); + } + } + /* shift to modified IDCT */ + win_bt = win[win_type]; + + if (sb&1) { + res_p[0] = -tmp[9] * win_bt[0] + s_p[0]; + res_p[1] =-(-tmp[10] * win_bt[1] + s_p[1]); + res_p[2] = -tmp[11] * win_bt[2] + s_p[2]; + res_p[3] =-(-tmp[12] * win_bt[3] + s_p[3]); + res_p[4] = -tmp[13] * win_bt[4] + s_p[4]; + res_p[5] =-(-tmp[14] * win_bt[5] + s_p[5]); + res_p[6] = -tmp[15] * win_bt[6] + s_p[6]; + res_p[7] =-(-tmp[16] * win_bt[7] + s_p[7]); + res_p[8] = -tmp[17] * win_bt[8] + s_p[8]; + + res_p[9] = -(tmp[17] * win_bt[9] + s_p[9]); + res_p[10]= tmp[16] * win_bt[10] + s_p[10]; + res_p[11]=-(tmp[15] * win_bt[11] + s_p[11]); + res_p[12]= tmp[14] * win_bt[12] + s_p[12]; + res_p[13]=-(tmp[13] * win_bt[13] + s_p[13]); + res_p[14]= tmp[12] * win_bt[14] + s_p[14]; + res_p[15]=-(tmp[11] * win_bt[15] + s_p[15]); + res_p[16]= tmp[10] * win_bt[16] + s_p[16]; + res_p[17]=-(tmp[9] * win_bt[17] + s_p[17]); + } else { + res_p[0] = -tmp[9] * win_bt[0] + s_p[0]; + res_p[1] = -tmp[10] * win_bt[1] + s_p[1]; + res_p[2] = -tmp[11] * win_bt[2] + s_p[2]; + res_p[3] = -tmp[12] * win_bt[3] + s_p[3]; + res_p[4] = -tmp[13] * win_bt[4] + s_p[4]; + res_p[5] = -tmp[14] * win_bt[5] + s_p[5]; + res_p[6] = -tmp[15] * win_bt[6] + s_p[6]; + res_p[7] = -tmp[16] * win_bt[7] + s_p[7]; + res_p[8] = -tmp[17] * win_bt[8] + s_p[8]; + + res_p[9] = tmp[17] * win_bt[9] + s_p[9]; + res_p[10]= tmp[16] * win_bt[10] + s_p[10]; + res_p[11]= tmp[15] * win_bt[11] + s_p[11]; + res_p[12]= tmp[14] * win_bt[12] + s_p[12]; + res_p[13]= tmp[13] * win_bt[13] + s_p[13]; + res_p[14]= tmp[12] * win_bt[14] + s_p[14]; + res_p[15]= tmp[11] * win_bt[15] + s_p[15]; + res_p[16]= tmp[10] * win_bt[16] + s_p[16]; + res_p[17]= tmp[9] * win_bt[17] + s_p[17]; + } + + s_p[0]= tmp[8] * win_bt[18]; + s_p[1]= tmp[7] * win_bt[19]; + s_p[2]= tmp[6] * win_bt[20]; + s_p[3]= tmp[5] * win_bt[21]; + s_p[4]= tmp[4] * win_bt[22]; + s_p[5]= tmp[3] * win_bt[23]; + s_p[6]= tmp[2] * win_bt[24]; + s_p[7]= tmp[1] * win_bt[25]; + s_p[8]= tmp[0] * win_bt[26]; + + s_p[9]= tmp[0] * win_bt[27]; + s_p[10]= tmp[1] * win_bt[28]; + s_p[11]= tmp[2] * win_bt[29]; + s_p[12]= tmp[3] * win_bt[30]; + s_p[13]= tmp[4] * win_bt[31]; + s_p[14]= tmp[5] * win_bt[32]; + s_p[15]= tmp[6] * win_bt[33]; + s_p[16]= tmp[7] * win_bt[34]; + s_p[17]= tmp[8] * win_bt[35]; + } +} + +/* fast DCT according to Lee[84] + * reordering according to Konstantinides[94] + */ +void poly(const int ch,int f) +{ +static float u[2][2][17][16]; /* no v[][], it's redundant */ +static int u_start[2]={0,0}; /* first element of u[][] */ +static int u_div[2]={0,0}; /* which part of u[][] is currently used */ +int start = u_start[ch]; +int div = u_div[ch]; +float (*u_p)[16]; + +#if defined(PENTIUM_RDTSC) +unsigned int cnt4, cnt3, cnt2, cnt1; +static int min_cycles = 99999999; + + __asm__(".byte 0x0f,0x31" : "=a" (cnt1), "=d" (cnt4)); +#endif + + { + float d16,d17,d18,d19,d20,d21,d22,d23,d24,d25,d26,d27,d28,d29,d30,d31; + float d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15; + + /* step 1: initial reordering and 1st (16 wide) butterflies + */ + + d0 = res[ 0][f]; d16=(d0 - res[31][f]) * b1; d0 += res[31][f]; + d1 = res[ 1][f]; d17=(d1 - res[30][f]) * b3; d1 += res[30][f]; + d3 = res[ 2][f]; d19=(d3 - res[29][f]) * b5; d3 += res[29][f]; + d2 = res[ 3][f]; d18=(d2 - res[28][f]) * b7; d2 += res[28][f]; + d6 = res[ 4][f]; d22=(d6 - res[27][f]) * b9; d6 += res[27][f]; + d7 = res[ 5][f]; d23=(d7 - res[26][f]) * b11; d7 += res[26][f]; + d5 = res[ 6][f]; d21=(d5 - res[25][f]) * b13; d5 += res[25][f]; + d4 = res[ 7][f]; d20=(d4 - res[24][f]) * b15; d4 += res[24][f]; + d12= res[ 8][f]; d28=(d12 - res[23][f]) * b17; d12+= res[23][f]; + d13= res[ 9][f]; d29=(d13 - res[22][f]) * b19; d13+= res[22][f]; + d15= res[10][f]; d31=(d15 - res[21][f]) * b21; d15+= res[21][f]; + d14= res[11][f]; d30=(d14 - res[20][f]) * b23; d14+= res[20][f]; + d10= res[12][f]; d26=(d10 - res[19][f]) * b25; d10+= res[19][f]; + d11= res[13][f]; d27=(d11 - res[18][f]) * b27; d11+= res[18][f]; + d9 = res[14][f]; d25=(d9 - res[17][f]) * b29; d9 += res[17][f]; + d8 = res[15][f]; d24=(d8 - res[16][f]) * b31; d8 += res[16][f]; + + { + float c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15; + +/* a test to see what can be done with memory separation + * first we process indexes 0-15 +*/ + c0 = d0 + d8 ; c8 = ( d0 - d8 ) * b2; + c1 = d1 + d9 ; c9 = ( d1 - d9 ) * b6; + c2 = d2 + d10; c10= ( d2 - d10) * b14; + c3 = d3 + d11; c11= ( d3 - d11) * b10; + c4 = d4 + d12; c12= ( d4 - d12) * b30; + c5 = d5 + d13; c13= ( d5 - d13) * b26; + c6 = d6 + d14; c14= ( d6 - d14) * b18; + c7 = d7 + d15; c15= ( d7 - d15) * b22; + + /* step 3: 4-wide butterflies + */ + d0 = c0 + c4 ; d4 = ( c0 - c4 ) * b4; + d1 = c1 + c5 ; d5 = ( c1 - c5 ) * b12; + d2 = c2 + c6 ; d6 = ( c2 - c6 ) * b28; + d3 = c3 + c7 ; d7 = ( c3 - c7 ) * b20; + + d8 = c8 + c12; d12= ( c8 - c12) * b4; + d9 = c9 + c13; d13= ( c9 - c13) * b12; + d10= c10+ c14; d14= (c10 - c14) * b28; + d11= c11+ c15; d15= (c11 - c15) * b20; + + + /* step 4: 2-wide butterflies + */ + { + float rb8 = b8; + float rb24 = b24; + +/**/ c0 = d0 + d2 ; c2 = ( d0 - d2 ) * rb8; + c1 = d1 + d3 ; c3 = ( d1 - d3 ) * rb24; +/**/ c4 = d4 + d6 ; c6 = ( d4 - d6 ) * rb8; + c5 = d5 + d7 ; c7 = ( d5 - d7 ) * rb24; +/**/ c8 = d8 + d10; c10= ( d8 - d10) * rb8; + c9 = d9 + d11; c11= ( d9 - d11) * rb24; +/**/ c12= d12+ d14; c14= (d12 - d14) * rb8; + c13= d13+ d15; c15= (d13 - d15) * rb24; + } + + /* step 5: 1-wide butterflies + */ + { + float rb16 = b16; + + /* this is a little 'hacked up' + */ + d0 = (-c0 -c1) * 2; d1 = ( c0 - c1 ) * rb16; + d2 = c2 + c3; d3 = ( c2 - c3 ) * rb16; + d3 -= d2; + + d4 = c4 +c5; d5 = ( c4 - c5 ) * rb16; + d5 += d4; + d7 = -d5; + d7 += ( c6 - c7 ) * rb16; d6 = +c6 +c7; + + d8 = c8 + c9 ; d9 = ( c8 - c9 ) * rb16; + d11= +d8 +d9; + d11 +=(c10 - c11) * rb16; d10= c10+ c11; + + d12 = c12+ c13; d13 = (c12 - c13) * rb16; + d13 += -d8-d9+d12; + d14 = c14+ c15; d15 = (c14 - c15) * rb16; + d15-=d11; + d14 += -d8 -d10; + } + + /* step 6: final resolving & reordering + * the other 32 are stored for use with the next granule + */ + + u_p = (float (*)[16]) &u[ch][div][0][start]; + +/*16*/ u_p[ 0][0] =+d1 ; + u_p[ 2][0] = +d9 -d14; +/*20*/ u_p[ 4][0] = +d5 -d6; + u_p[ 6][0] = -d10 +d13; +/*24*/ u_p[ 8][0] =d3; + u_p[10][0] = -d8 -d9 +d11 -d13; +/*28*/ u_p[12][0] = +d7; + u_p[14][0] = +d15; + + /* the other 32 are stored for use with the next granule + */ + + u_p = (float (*)[16]) &u[ch][!div][0][start]; + +/*0*/ u_p[16][0] = d0; + u_p[14][0] = -(+d8 ); +/*4*/ u_p[12][0] = -(+d4 ); + u_p[10][0] = -(-d8 +d12 ); +/*8*/ u_p[ 8][0] = -(+d2 ); + u_p[ 6][0] = -(+d8 +d10 -d12 ); +/*12*/ u_p[ 4][0] = -(-d4 +d6 ); + u_p[ 2][0] = -d14; + u_p[ 0][0] = -d1; + } + + { + float c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14,c15; + +/* memory separation, second part +*/ +/* 2 +*/ + c0=d16 + d24; c8= (d16 - d24) * b2; + c1=d17 + d25; c9= (d17 - d25) * b6; + c2=d18 + d26; c10= (d18 - d26) * b14; + c3=d19 + d27; c11= (d19 - d27) * b10; + c4=d20 + d28; c12= (d20 - d28) * b30; + c5=d21 + d29; c13= (d21 - d29) * b26; + c6=d22 + d30; c14= (d22 - d30) * b18; + c7=d23 + d31; c15= (d23 - d31) * b22; + +/* 3 +*/ + d16= c0+ c4; d20= (c0 - c4) * b4; + d17= c1+ c5; d21= (c1 - c5) * b12; + d18= c2+ c6; d22= (c2 - c6) * b28; + d19= c3+ c7; d23= (c3 - c7) * b20; + + d24= c8+ c12; d28= (c8 - c12) * b4; + d25= c9+ c13; d29= (c9 - c13) * b12; + d26= c10+ c14; d30= (c10 - c14) * b28; + d27= c11+ c15; d31= (c11 - c15) * b20; + +/* 4 +*/ + { + float rb8 = b8; + float rb24 = b24; + +/**/ c0= d16+ d18; c2= (d16 - d18) * rb8; + c1= d17+ d19; c3= (d17 - d19) * rb24; +/**/ c4= d20+ d22; c6= (d20 - d22) * rb8; + c5= d21+ d23; c7= (d21 - d23) * rb24; +/**/ c8= d24+ d26; c10= (d24 - d26) * rb8; + c9= d25+ d27; c11= (d25 - d27) * rb24; +/**/ c12= d28+ d30; c14= (d28 - d30) * rb8; + c13= d29+ d31; c15= (d29 - d31) * rb24; + } + +/* 5 +*/ + { + float rb16 = b16; + d16= c0+ c1; d17= (c0 - c1) * rb16; + d18= c2+ c3; d19= (c2 - c3) * rb16; + + d20= c4+ c5; d21= (c4 - c5) * rb16; + d20+=d16; d21+=d17; + d22= c6+ c7; d23= (c6 - c7) * rb16; + d22+=d16; d22+=d18; + d23+=d16; d23+=d17; d23+=d19; + + + d24= c8+ c9; d25= (c8 - c9) * rb16; + d26= c10+ c11; d27= (c10 - c11) * rb16; + d26+=d24; + d27+=d24; d27+=d25; + + d28= c12+ c13; d29= (c12 - c13) * rb16; + d28-=d20; d29+=d28; d29-=d21; + d30= c14+ c15; d31= (c14 - c15) * rb16; + d30-=d22; + d31-=d23; + } + + /* step 6: final resolving & reordering + * the other 32 are stored for use with the next granule + */ + + u_p = (float (*)[16]) &u[ch][!div][0][start]; + + u_p[ 1][0] = -(+d30 ); + u_p[ 3][0] = -(+d22 -d26 ); + u_p[ 5][0] = -(-d18 -d20 +d26 ); + u_p[ 7][0] = -(+d18 -d28 ); + u_p[ 9][0] = -(+d28 ); + u_p[11][0] = -(+d20 -d24 ); + u_p[13][0] = -(-d16 +d24 ); + u_p[15][0] = -(+d16 ); + + /* the other 32 are stored for use with the next granule + */ + + u_p = (float (*)[16]) &u[ch][div][0][start]; + + u_p[15][0] = +d31; + u_p[13][0] = +d23 -d27; + u_p[11][0] = -d19 -d20 -d21 +d27; + u_p[ 9][0] = +d19 -d29; + u_p[ 7][0] = -d18 +d29; + u_p[ 5][0] = +d18 +d20 +d21 -d25 -d26; + u_p[ 3][0] = -d17 -d22 +d25 +d26; + u_p[ 1][0] = +d17 -d30; + } + } + +#if defined(PENTIUM_RDTSC) + __asm__(".byte 0x0f,0x31" : "=a" (cnt3), "=d" (cnt4)); +#endif + + /* we're doing dewindowing and calculating final samples now + */ + +#if defined(ARCH_i586) + /* x86 assembler optimisations. These optimisations are tuned + specifically for Intel Pentiums. */ + + asm("movl $15,%%eax\n\t"\ + "1:\n\t"\ + "flds (%0)\n\t"\ + "fmuls (%1)\n\t"\ + "flds 4(%0)\n\t"\ + "fmuls 4(%1)\n\t"\ + "flds 8(%0)\n\t"\ + "fmuls 8(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 12(%0)\n\t"\ + "fmuls 12(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 16(%0)\n\t"\ + "fmuls 16(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 20(%0)\n\t"\ + "fmuls 20(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 24(%0)\n\t"\ + "fmuls 24(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 28(%0)\n\t"\ + "fmuls 28(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 32(%0)\n\t"\ + "fmuls 32(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 36(%0)\n\t"\ + "fmuls 36(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 40(%0)\n\t"\ + "fmuls 40(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 44(%0)\n\t"\ + "fmuls 44(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 48(%0)\n\t"\ + "fmuls 48(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 52(%0)\n\t"\ + "fmuls 52(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 56(%0)\n\t"\ + "fmuls 56(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 60(%0)\n\t"\ + "fmuls 60(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "addl $64,%0\n\t"\ + "addl $128,%1\n\t"\ + "subl $4,%%esp\n\t"\ + "faddp\n\t"\ + "fistpl (%%esp)\n\t"\ + "popl %%ecx\n\t"\ + "cmpl $32767,%%ecx\n\t"\ + "jle 2f\n\t"\ + "movw $32767,%%cx\n\t"\ + "jmp 3f\n\t"\ + "2: cmpl $-32768,%%ecx\n\t"\ + "jge 3f\n\t"\ + "movw $-32768,%%cx\n\t"\ + "3: movw %%cx,(%2)\n\t"\ + "addl %3,%2\n\t"\ + "decl %%eax\n\t"\ + "jns 1b\n\t"\ + + "testb $1,%4\n\t"\ + "je 4f\n\t" + + "flds (%0)\n\t"\ + "fmuls (%1)\n\t"\ + "flds 8(%0)\n\t"\ + "fmuls 8(%1)\n\t"\ + "flds 16(%0)\n\t"\ + "fmuls 16(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 24(%0)\n\t"\ + "fmuls 24(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 32(%0)\n\t"\ + "fmuls 32(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 40(%0)\n\t"\ + "fmuls 40(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 48(%0)\n\t"\ + "fmuls 48(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 56(%0)\n\t"\ + "fmuls 56(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "subl $4,%%esp\n\t"\ + "subl $64,%0\n\t"\ + "subl $192,%1\n\t"\ + "faddp\n\t"\ + "fistpl (%%esp)\n\t"\ + "popl %%ecx\n\t"\ + "cmpl $32767,%%ecx\n\t"\ + "jle 2f\n\t"\ + "movw $32767,%%cx\n\t"\ + "jmp 3f\n\t"\ + "2: cmpl $-32768,%%ecx\n\t"\ + "jge 3f\n\t"\ + "movw $-32768,%%cx\n\t"\ + "3: movw %%cx,(%2)\n\t"\ + + "movl %5,%%ecx\n\t"\ + "sall $3,%%ecx\n\t"\ + "addl %%ecx,%1\n\t"\ + "addl %3,%2\n\t"\ + "movl $14,%%eax\n\t"\ + + "1:flds 4(%0)\n\t"\ + "fmuls 56(%1)\n\t"\ + "flds (%0)\n\t"\ + "fmuls 60(%1)\n\t"\ + "flds 12(%0)\n\t"\ + "fmuls 48(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubp\n\t"\ + "flds 8(%0)\n\t"\ + "fmuls 52(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 20(%0)\n\t"\ + "fmuls 40(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 16(%0)\n\t"\ + "fmuls 44(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 28(%0)\n\t"\ + "fmuls 32(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 24(%0)\n\t"\ + "fmuls 36(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 36(%0)\n\t"\ + "fmuls 24(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 32(%0)\n\t"\ + "fmuls 28(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 44(%0)\n\t"\ + "fmuls 16(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 40(%0)\n\t"\ + "fmuls 20(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 52(%0)\n\t"\ + "fmuls 8(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 48(%0)\n\t"\ + "fmuls 12(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 60(%0)\n\t"\ + "fmuls (%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 56(%0)\n\t"\ + "fmuls 4(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "subl $64,%0\n\t"\ + "subl $128,%1\n\t"\ + "subl $4,%%esp\n\t"\ + "fsubp\n\t"\ + "fistpl (%%esp)\n\t"\ + "popl %%ecx\n\t"\ + "cmpl $32767,%%ecx\n\t"\ + "jle 2f\n\t"\ + "movw $32767,%%cx\n\t"\ + "jmp 3f\n\t"\ + "2: cmpl $-32768,%%ecx\n\t"\ + "jge 3f\n\t"\ + "movw $-32768,%%cx\n\t"\ + "3: movw %%cx,(%2)\n\t"\ + "addl %3,%2\n\t"\ + "decl %%eax\n\t"\ + "jns 1b\n\t"\ + "jmp 5f\n\t"\ + + "4:flds 4(%0)\n\t"\ + "fmuls 4(%1)\n\t"\ + "flds 12(%0)\n\t"\ + "fmuls 12(%1)\n\t"\ + "flds 20(%0)\n\t"\ + "fmuls 20(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 28(%0)\n\t"\ + "fmuls 28(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 36(%0)\n\t"\ + "fmuls 36(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 44(%0)\n\t"\ + "fmuls 44(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 52(%0)\n\t"\ + "fmuls 52(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 60(%0)\n\t"\ + "fmuls 60(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "subl $4,%%esp\n\t"\ + "subl $64,%0\n\t"\ + "subl $192,%1\n\t"\ + "faddp\n\t"\ + "fistpl (%%esp)\n\t"\ + "popl %%ecx\n\t"\ + "cmpl $32767,%%ecx\n\t"\ + "jle 2f\n\t"\ + "movw $32767,%%cx\n\t"\ + "jmp 3f\n\t"\ + "2: cmpl $-32768,%%ecx\n\t"\ + "jge 3f\n\t"\ + "movw $-32768,%%cx\n\t"\ + "3: movw %%cx,(%2)\n\t"\ + + "movl %5,%%ecx\n\t"\ + "sall $3,%%ecx\n\t"\ + "addl %%ecx,%1\n\t"\ + "addl %3,%2\n\t"\ + + "movl $14,%%eax\n\t"\ + "1:flds (%0)\n\t"\ + "fmuls 60(%1)\n\t"\ + "flds 4(%0)\n\t"\ + "fmuls 56(%1)\n\t"\ + "flds 8(%0)\n\t"\ + "fmuls 52(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubp\n\t"\ + "flds 12(%0)\n\t"\ + "fmuls 48(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 16(%0)\n\t"\ + "fmuls 44(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 20(%0)\n\t"\ + "fmuls 40(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 24(%0)\n\t"\ + "fmuls 36(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 28(%0)\n\t"\ + "fmuls 32(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 32(%0)\n\t"\ + "fmuls 28(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 36(%0)\n\t"\ + "fmuls 24(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 40(%0)\n\t"\ + "fmuls 20(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 44(%0)\n\t"\ + "fmuls 16(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 48(%0)\n\t"\ + "fmuls 12(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 52(%0)\n\t"\ + "fmuls 8(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "flds 56(%0)\n\t"\ + "fmuls 4(%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "fsubrp\n\t"\ + "flds 60(%0)\n\t"\ + "fmuls (%1)\n\t"\ + "fxch %%st(2)\n\t"\ + "faddp\n\t"\ + "subl $64,%0\n\t"\ + "subl $128,%1\n\t"\ + "subl $4,%%esp\n\t"\ + "fsubp\n\t"\ + "fistpl (%%esp)\n\t"\ + "popl %%ecx\n\t"\ + "cmpl $32767,%%ecx\n\t"\ + "jle 2f\n\t"\ + "movw $32767,%%cx\n\t"\ + "jmp 3f\n\t"\ + "2: cmpl $-32768,%%ecx\n\t"\ + "jge 3f\n\t"\ + "movw $-32768,%%cx\n\t"\ + "3: movw %%cx,(%2)\n\t"\ + "addl %3,%2\n\t"\ + "decl %%eax\n\t"\ + "jns 1b\n\t"\ + + "5:"\ + : : "b" (u[ch][div]), "d" (t_dewindow[0] + 16 - start), "S" (&sample_buffer[f>>(2-nch)][nch==2?0:(f&1?16:0)][ch]), "m" (sizeof(short) * nch), "m" (div), "m" (start)\ + : "eax", "ecx", "memory"); +#else + { + short *samples = (&sample_buffer[f>>(2-nch)][nch==2?0:(f&1?16:0)][ch]); + int out, j; + +#define PUT_SAMPLE(out) \ + if (out > 32767) \ + *samples = 32767; \ + else \ + if (out < -32768) \ + *samples = -32768; \ + else \ + *samples = out; \ + \ + samples += nch; + +#if defined(SUPERHACK) + /* These is a simple implementation which should be nicer to the + cache; computation of samples are done in one pass rather than + two. However, for various reasons which I do not have time to + investigate, it runs quite a lot slower than two pass + computations. If you have time, you are welcome to look into + it. */ + + { + float (*u_ptr)[16] = u[ch][div]; + const float *dewindow2 = t_dewindow[0] + start; + + { + float outf1, outf2, outf3, outf4; + + outf1 = u_ptr[0][ 0] * dewindow[0x0]; + outf2 = u_ptr[0][ 1] * dewindow[0x1]; + outf3 = u_ptr[0][ 2] * dewindow[0x2]; + outf4 = u_ptr[0][ 3] * dewindow[0x3]; + outf1 += u_ptr[0][ 4] * dewindow[0x4]; + outf2 += u_ptr[0][ 5] * dewindow[0x5]; + outf3 += u_ptr[0][ 6] * dewindow[0x6]; + outf4 += u_ptr[0][ 7] * dewindow[0x7]; + outf1 += u_ptr[0][ 8] * dewindow[0x8]; + outf2 += u_ptr[0][ 9] * dewindow[0x9]; + outf3 += u_ptr[0][10] * dewindow[0xa]; + outf4 += u_ptr[0][11] * dewindow[0xb]; + outf1 += u_ptr[0][12] * dewindow[0xc]; + outf2 += u_ptr[0][13] * dewindow[0xd]; + outf3 += u_ptr[0][14] * dewindow[0xe]; + outf4 += u_ptr[0][15] * dewindow[0xf]; + + out = outf1 + outf2 + outf3 + outf4; + + dewindow += 32; + dewindow2 += 32; + u_ptr++; + + if (out > 32767) + samples[0] = 32767; + else + if (out < -32768) + samples[0] = -32768; + else + samples[0] = out; + } + + if (div & 0x1) { + for (j = 1; j < 16; ++j) { + float outf1, outf2, outf3, outf4; + + outf1 = u_ptr[0][ 0] * dewindow[0x0]; + outf3 = u_ptr[0][ 0] * dewindow2[0xf]; + outf2 = u_ptr[0][ 1] * dewindow[0x1]; + outf4 = u_ptr[0][ 1] * dewindow2[0xe]; + outf1 += u_ptr[0][ 2] * dewindow[0x2]; + outf3 += u_ptr[0][ 2] * dewindow2[0xd]; + outf2 += u_ptr[0][ 3] * dewindow[0x3]; + outf4 += u_ptr[0][ 3] * dewindow2[0xc]; + outf1 += u_ptr[0][ 4] * dewindow[0x4]; + outf3 += u_ptr[0][ 4] * dewindow2[0xb]; + outf2 += u_ptr[0][ 5] * dewindow[0x5]; + outf4 += u_ptr[0][ 5] * dewindow2[0xa]; + outf1 += u_ptr[0][ 6] * dewindow[0x6]; + outf3 += u_ptr[0][ 6] * dewindow2[0x9]; + outf2 += u_ptr[0][ 7] * dewindow[0x7]; + outf4 += u_ptr[0][ 7] * dewindow2[0x8]; + outf1 += u_ptr[0][ 8] * dewindow[0x8]; + outf3 += u_ptr[0][ 8] * dewindow2[0x7]; + outf2 += u_ptr[0][ 9] * dewindow[0x9]; + outf4 += u_ptr[0][ 9] * dewindow2[0x6]; + outf1 += u_ptr[0][10] * dewindow[0xa]; + outf3 += u_ptr[0][10] * dewindow2[0x5]; + outf2 += u_ptr[0][11] * dewindow[0xb]; + outf4 += u_ptr[0][11] * dewindow2[0x4]; + outf1 += u_ptr[0][12] * dewindow[0xc]; + outf3 += u_ptr[0][12] * dewindow2[0x3]; + outf2 += u_ptr[0][13] * dewindow[0xd]; + outf4 += u_ptr[0][13] * dewindow2[0x2]; + outf1 += u_ptr[0][14] * dewindow[0xe]; + outf3 += u_ptr[0][14] * dewindow2[0x1]; + outf2 += u_ptr[0][15] * dewindow[0xf]; + outf4 += u_ptr[0][15] * dewindow2[0x0]; + + dewindow += 32; + dewindow2 += 32; + u_ptr++; + + out = outf1 + outf2; + + if (out > 32767) + samples[j * 2] = 32767; + else + if (out < -32768) + samples[j * 2] = -32768; + else + samples[j * 2] = out; + + out = outf4 - outf3; + + if (out > 32767) + samples[64 - (j * 2)] = 32767; + else + if (out < -32768) + samples[64 - (j * 2)] = -32768; + else + samples[64 - (j * 2)] = out; + } + + { + float outf2, outf4; + + outf2 = u_ptr[0][ 0] * dewindow[0x0]; + outf4 = u_ptr[0][ 2] * dewindow[0x2]; + outf2 += u_ptr[0][ 4] * dewindow[0x4]; + outf4 += u_ptr[0][ 6] * dewindow[0x6]; + outf2 += u_ptr[0][ 8] * dewindow[0x8]; + outf4 += u_ptr[0][10] * dewindow[0xa]; + outf2 += u_ptr[0][12] * dewindow[0xc]; + outf4 += u_ptr[0][14] * dewindow[0xe]; + + out = outf2 + outf4; + + if (out > 32767) + samples[16 * 2] = 32767; + else + if (out < -32768) + samples[16 * 2] = -32768; + else + samples[16 * 2] = out; + } + } else { + for (j = 1; j < 16; ++j) { + float outf1, outf2, outf3, outf4; + + outf1 = u_ptr[0][ 0] * dewindow[0x0]; + outf3 = u_ptr[0][ 0] * dewindow2[0xf]; + outf2 = u_ptr[0][ 1] * dewindow[0x1]; + outf4 = u_ptr[0][ 1] * dewindow2[0xe]; + outf1 += u_ptr[0][ 2] * dewindow[0x2]; + outf3 += u_ptr[0][ 2] * dewindow2[0xd]; + outf2 += u_ptr[0][ 3] * dewindow[0x3]; + outf4 += u_ptr[0][ 3] * dewindow2[0xc]; + outf1 += u_ptr[0][ 4] * dewindow[0x4]; + outf3 += u_ptr[0][ 4] * dewindow2[0xb]; + outf2 += u_ptr[0][ 5] * dewindow[0x5]; + outf4 += u_ptr[0][ 5] * dewindow2[0xa]; + outf1 += u_ptr[0][ 6] * dewindow[0x6]; + outf3 += u_ptr[0][ 6] * dewindow2[0x9]; + outf2 += u_ptr[0][ 7] * dewindow[0x7]; + outf4 += u_ptr[0][ 7] * dewindow2[0x8]; + outf1 += u_ptr[0][ 8] * dewindow[0x8]; + outf3 += u_ptr[0][ 8] * dewindow2[0x7]; + outf2 += u_ptr[0][ 9] * dewindow[0x9]; + outf4 += u_ptr[0][ 9] * dewindow2[0x6]; + outf1 += u_ptr[0][10] * dewindow[0xa]; + outf3 += u_ptr[0][10] * dewindow2[0x5]; + outf2 += u_ptr[0][11] * dewindow[0xb]; + outf4 += u_ptr[0][11] * dewindow2[0x4]; + outf1 += u_ptr[0][12] * dewindow[0xc]; + outf3 += u_ptr[0][12] * dewindow2[0x3]; + outf2 += u_ptr[0][13] * dewindow[0xd]; + outf4 += u_ptr[0][13] * dewindow2[0x2]; + outf1 += u_ptr[0][14] * dewindow[0xe]; + outf3 += u_ptr[0][14] * dewindow2[0x1]; + outf2 += u_ptr[0][15] * dewindow[0xf]; + outf4 += u_ptr[0][15] * dewindow2[0x0]; + + dewindow += 32; + dewindow2 += 32; + u_ptr++; + + out = outf1 + outf2; + + if (out > 32767) + samples[j * 2] = 32767; + else + if (out < -32768) + samples[j * 2] = -32768; + else + samples[j * 2] = out; + + out = outf3 - outf4; + + if (out > 32767) + samples[64 - (j * 2)] = 32767; + else + if (out < -32768) + samples[64 - (j * 2)] = -32768; + else + samples[64 - (j * 2)] = out; + } + + { + float outf2, outf4; + + outf2 = u_ptr[0][ 1] * dewindow[0x1]; + outf4 = u_ptr[0][ 3] * dewindow[0x3]; + outf2 += u_ptr[0][ 5] * dewindow[0x5]; + outf4 += u_ptr[0][ 7] * dewindow[0x7]; + outf2 += u_ptr[0][ 9] * dewindow[0x9]; + outf4 += u_ptr[0][11] * dewindow[0xb]; + outf2 += u_ptr[0][13] * dewindow[0xd]; + outf4 += u_ptr[0][15] * dewindow[0xf]; + + out = outf2 + outf4; + + if (out > 32767) + samples[16 * 2] = 32767; + else + if (out < -32768) + samples[16 * 2] = -32768; + else + samples[16 * 2] = out; + } + } + } +#elif defined(HAS_AUTOINCREMENT) + const float *dewindow = t_dewindow[0] + 15 - start; + + /* This is tuned specifically for architectures with + autoincrement and -decrement. */ + + { + float *u_ptr = (float*) u[ch][div]; + + u_ptr--; + + for (j = 0; j < 16; ++j) { + float outf1, outf2, outf3, outf4; + + outf1 = *++u_ptr * *++dewindow; + outf2 = *++u_ptr * *++dewindow; + outf3 = *++u_ptr * *++dewindow; + outf4 = *++u_ptr * *++dewindow; + outf1 += *++u_ptr * *++dewindow; + outf2 += *++u_ptr * *++dewindow; + outf3 += *++u_ptr * *++dewindow; + outf4 += *++u_ptr * *++dewindow; + outf1 += *++u_ptr * *++dewindow; + outf2 += *++u_ptr * *++dewindow; + outf3 += *++u_ptr * *++dewindow; + outf4 += *++u_ptr * *++dewindow; + outf1 += *++u_ptr * *++dewindow; + outf2 += *++u_ptr * *++dewindow; + outf3 += *++u_ptr * *++dewindow; + outf4 += *++u_ptr * *++dewindow; + + out = outf1 + outf2 + outf3 + outf4; + + dewindow += 16; + + PUT_SAMPLE(out) + } + + if (div & 0x1) { + { + float outf2, outf4; + + outf2 = u_ptr[ 1] * dewindow[0x1]; + outf4 = u_ptr[ 3] * dewindow[0x3]; + outf2 += u_ptr[ 5] * dewindow[0x5]; + outf4 += u_ptr[ 7] * dewindow[0x7]; + outf2 += u_ptr[ 9] * dewindow[0x9]; + outf4 += u_ptr[11] * dewindow[0xb]; + outf2 += u_ptr[13] * dewindow[0xd]; + outf4 += u_ptr[15] * dewindow[0xf]; + + out = outf2 + outf4; + + PUT_SAMPLE(out) + } + + dewindow -= 31; + dewindow += start; + dewindow += start; + u_ptr -= 16; + + for (; j < 31; ++j) { + float outf1, outf2, outf3, outf4; + + outf1 = *++u_ptr * *--dewindow; + outf2 = *++u_ptr * *--dewindow; + outf3 = *++u_ptr * *--dewindow; + outf4 = *++u_ptr * *--dewindow; + outf1 += *++u_ptr * *--dewindow; + outf2 += *++u_ptr * *--dewindow; + outf3 += *++u_ptr * *--dewindow; + outf4 += *++u_ptr * *--dewindow; + outf1 += *++u_ptr * *--dewindow; + outf2 += *++u_ptr * *--dewindow; + outf3 += *++u_ptr * *--dewindow; + outf4 += *++u_ptr * *--dewindow; + outf1 += *++u_ptr * *--dewindow; + outf2 += *++u_ptr * *--dewindow; + outf3 += *++u_ptr * *--dewindow; + outf4 += *++u_ptr * *--dewindow; + + out = outf2 - outf1 + outf4 - outf3; + + dewindow -= 16; + u_ptr -= 32; + + PUT_SAMPLE(out) + } + } else { + { + float outf2, outf4; + + outf2 = u_ptr[ 2] * dewindow[ 0x2]; + outf4 = u_ptr[ 4] * dewindow[ 0x4]; + outf2 += u_ptr[ 6] * dewindow[ 0x6]; + outf4 += u_ptr[ 8] * dewindow[ 0x8]; + outf2 += u_ptr[10] * dewindow[ 0xa]; + outf4 += u_ptr[12] * dewindow[ 0xc]; + outf2 += u_ptr[14] * dewindow[ 0xe]; + outf4 += u_ptr[16] * dewindow[0x10]; + + out = outf2 + outf4; + + PUT_SAMPLE(out) + } + + dewindow -= 31; + dewindow += start; + dewindow += start; + u_ptr -= 16; + + for (; j < 31; ++j) { + float outf1, outf2, outf3, outf4; + + outf1 = *++u_ptr * *--dewindow; + outf2 = *++u_ptr * *--dewindow; + outf3 = *++u_ptr * *--dewindow; + outf4 = *++u_ptr * *--dewindow; + outf1 += *++u_ptr * *--dewindow; + outf2 += *++u_ptr * *--dewindow; + outf3 += *++u_ptr * *--dewindow; + outf4 += *++u_ptr * *--dewindow; + outf1 += *++u_ptr * *--dewindow; + outf2 += *++u_ptr * *--dewindow; + outf3 += *++u_ptr * *--dewindow; + outf4 += *++u_ptr * *--dewindow; + outf1 += *++u_ptr * *--dewindow; + outf2 += *++u_ptr * *--dewindow; + outf3 += *++u_ptr * *--dewindow; + outf4 += *++u_ptr * *--dewindow; + + out = outf1 - outf2 + outf3 - outf4; + + dewindow -= 16; + u_ptr -= 32; + + PUT_SAMPLE(out) + } + } + } +#else + const float *dewindow = t_dewindow[0] + 16 - start; + + /* These optimisations are tuned specifically for architectures + without autoincrement and -decrement. */ + + { + float (*u_ptr)[16] = u[ch][div]; + + for (j = 0; j < 16; ++j) { + float outf1, outf2, outf3, outf4; + + outf1 = u_ptr[0][ 0] * dewindow[0x0]; + outf2 = u_ptr[0][ 1] * dewindow[0x1]; + outf3 = u_ptr[0][ 2] * dewindow[0x2]; + outf4 = u_ptr[0][ 3] * dewindow[0x3]; + outf1 += u_ptr[0][ 4] * dewindow[0x4]; + outf2 += u_ptr[0][ 5] * dewindow[0x5]; + outf3 += u_ptr[0][ 6] * dewindow[0x6]; + outf4 += u_ptr[0][ 7] * dewindow[0x7]; + outf1 += u_ptr[0][ 8] * dewindow[0x8]; + outf2 += u_ptr[0][ 9] * dewindow[0x9]; + outf3 += u_ptr[0][10] * dewindow[0xa]; + outf4 += u_ptr[0][11] * dewindow[0xb]; + outf1 += u_ptr[0][12] * dewindow[0xc]; + outf2 += u_ptr[0][13] * dewindow[0xd]; + outf3 += u_ptr[0][14] * dewindow[0xe]; + outf4 += u_ptr[0][15] * dewindow[0xf]; + + out = (int) (outf1 + outf2 + outf3 + outf4); + + dewindow += 32; + u_ptr++; + + PUT_SAMPLE(out) + } + + if (div & 0x1) { + { + float outf2, outf4; + + outf2 = u_ptr[0][ 0] * dewindow[0x0]; + outf4 = u_ptr[0][ 2] * dewindow[0x2]; + outf2 += u_ptr[0][ 4] * dewindow[0x4]; + outf4 += u_ptr[0][ 6] * dewindow[0x6]; + outf2 += u_ptr[0][ 8] * dewindow[0x8]; + outf4 += u_ptr[0][10] * dewindow[0xa]; + outf2 += u_ptr[0][12] * dewindow[0xc]; + outf4 += u_ptr[0][14] * dewindow[0xe]; + + out = (int) (outf2 + outf4); + + PUT_SAMPLE(out) + } + + dewindow -= 48; + dewindow += start; + dewindow += start; + + for (; j < 31; ++j) { + float outf1, outf2, outf3, outf4; + + --u_ptr; + + outf1 = u_ptr[0][ 0] * dewindow[0xf]; + outf2 = u_ptr[0][ 1] * dewindow[0xe]; + outf3 = u_ptr[0][ 2] * dewindow[0xd]; + outf4 = u_ptr[0][ 3] * dewindow[0xc]; + outf1 += u_ptr[0][ 4] * dewindow[0xb]; + outf2 += u_ptr[0][ 5] * dewindow[0xa]; + outf3 += u_ptr[0][ 6] * dewindow[0x9]; + outf4 += u_ptr[0][ 7] * dewindow[0x8]; + outf1 += u_ptr[0][ 8] * dewindow[0x7]; + outf2 += u_ptr[0][ 9] * dewindow[0x6]; + outf3 += u_ptr[0][10] * dewindow[0x5]; + outf4 += u_ptr[0][11] * dewindow[0x4]; + outf1 += u_ptr[0][12] * dewindow[0x3]; + outf2 += u_ptr[0][13] * dewindow[0x2]; + outf3 += u_ptr[0][14] * dewindow[0x1]; + outf4 += u_ptr[0][15] * dewindow[0x0]; + + out = (int) (-outf1 + outf2 - outf3 + outf4); + + dewindow -= 32; + + PUT_SAMPLE(out) + } + } else { + { + float outf2, outf4; + + outf2 = u_ptr[0][ 1] * dewindow[0x1]; + outf4 = u_ptr[0][ 3] * dewindow[0x3]; + outf2 += u_ptr[0][ 5] * dewindow[0x5]; + outf4 += u_ptr[0][ 7] * dewindow[0x7]; + outf2 += u_ptr[0][ 9] * dewindow[0x9]; + outf4 += u_ptr[0][11] * dewindow[0xb]; + outf2 += u_ptr[0][13] * dewindow[0xd]; + outf4 += u_ptr[0][15] * dewindow[0xf]; + + out = (int) (outf2 + outf4); + + PUT_SAMPLE(out) + } + + dewindow -= 48; + dewindow += start; + dewindow += start; + + for (; j < 31; ++j) { + float outf1, outf2, outf3, outf4; + + --u_ptr; + + outf1 = u_ptr[0][ 0] * dewindow[0xf]; + outf2 = u_ptr[0][ 1] * dewindow[0xe]; + outf3 = u_ptr[0][ 2] * dewindow[0xd]; + outf4 = u_ptr[0][ 3] * dewindow[0xc]; + outf1 += u_ptr[0][ 4] * dewindow[0xb]; + outf2 += u_ptr[0][ 5] * dewindow[0xa]; + outf3 += u_ptr[0][ 6] * dewindow[0x9]; + outf4 += u_ptr[0][ 7] * dewindow[0x8]; + outf1 += u_ptr[0][ 8] * dewindow[0x7]; + outf2 += u_ptr[0][ 9] * dewindow[0x6]; + outf3 += u_ptr[0][10] * dewindow[0x5]; + outf4 += u_ptr[0][11] * dewindow[0x4]; + outf1 += u_ptr[0][12] * dewindow[0x3]; + outf2 += u_ptr[0][13] * dewindow[0x2]; + outf3 += u_ptr[0][14] * dewindow[0x1]; + outf4 += u_ptr[0][15] * dewindow[0x0]; + + out = (int) (outf1 - outf2 + outf3 - outf4); + + dewindow -= 32; + + PUT_SAMPLE(out) + } + } + } +#endif + } +#endif + + --u_start[ch]; + u_start[ch] &= 0xf; + u_div[ch]=u_div[ch] ? 0 : 1; + +#if defined(PENTIUM_RDTSC) + __asm__(".byte 0x0f,0x31" : "=a" (cnt2), "=d" (cnt4)); + + if (cnt2-cnt1 < min_cycles) { + min_cycles = cnt2-cnt1; + printf("%d, %d cycles, %d\n", cnt3-cnt1, min_cycles, start); + } +#endif +} + +void premultiply() +{ + int i,t; + + for (i = 0; i < 17; ++i) + for (t = 0; t < 32; ++t) + t_dewindow[i][t] *= 16383.5f; +} diff --git a/Src/Sound/MPEG/transform.h b/Src/Sound/MPEG/transform.h new file mode 100644 index 0000000..2c846f4 --- /dev/null +++ b/Src/Sound/MPEG/transform.h @@ -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 */ diff --git a/Src/Sound/MPEG/util.cpp b/Src/Sound/MPEG/util.cpp new file mode 100644 index 0000000..30b6d44 --- /dev/null +++ b/Src/Sound/MPEG/util.cpp @@ -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 +#include +#include + +#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 +} + diff --git a/Src/Sound/SCSP.cpp b/Src/Sound/SCSP.cpp index aaed44d..56357c5 100644 --- a/Src/Sound/SCSP.cpp +++ b/Src/Sound/SCSP.cpp @@ -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; diff --git a/Src/Sound/SCSP.h b/Src/Sound/SCSP.h index feb803c..6c8af8f 100644 --- a/Src/Sound/SCSP.h +++ b/Src/Sound/SCSP.h @@ -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); diff --git a/Src/Supermodel.h b/Src/Supermodel.h index 52cadcf..b77a910 100644 --- a/Src/Supermodel.h +++ b/Src/Supermodel.h @@ -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" /******************************************************************************