mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-24 02:01:48 +01:00
code cleanup
This commit is contained in:
parent
822de1bd3f
commit
00a61b4762
@ -17,10 +17,10 @@ include $(DEVKITPPC)/gamecube_rules
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := genplus_cube
|
||||
BUILD := build_cube
|
||||
SOURCES := source source/m68k source/z80 source/sound source/cart_hw \
|
||||
source/cart_hw/svp source/ngc source/ngc/gui source/sound/SRC source/ntsc
|
||||
INCLUDES := source source/m68k source/z80 source/sound source/cart_hw \
|
||||
source/cart_hw/svp source/ngc source/ngc/gui source/sound/SRC source/ntsc
|
||||
SOURCES := source source/m68k source/z80 source/sound source/sound/SRC source/ntsc \
|
||||
source/cart_hw source/cart_hw/svp source/ngc source/ngc/gui source/ngc/fileio
|
||||
INCLUDES := source source/m68k source/z80 source/sound source/sound/SRC source/ntsc \
|
||||
source/cart_hw source/cart_hw/svp source/ngc source/ngc/gui source/ngc/fileio
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
|
@ -17,10 +17,10 @@ include $(DEVKITPPC)/wii_rules
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := genplus_wii
|
||||
BUILD := build_wii
|
||||
SOURCES := source source/m68k source/z80 source/sound source/cart_hw\
|
||||
source/cart_hw/svp source/ngc source/ngc/gui source/sound/SRC source/ntsc
|
||||
INCLUDES := source source/m68k source/z80 source/sound source/cart_hw\
|
||||
source/cart_hw/svp source/ngc source/ngc/gui source/sound/SRC source/ntsc
|
||||
SOURCES := source source/m68k source/z80 source/sound source/sound/SRC source/ntsc \
|
||||
source/cart_hw source/cart_hw/svp source/ngc source/ngc/gui source/ngc/fileio
|
||||
INCLUDES := source source/m68k source/z80 source/sound source/sound/SRC source/ntsc \
|
||||
source/cart_hw source/cart_hw/svp source/ngc source/ngc/gui source/ngc/fileio
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
|
@ -43,71 +43,71 @@ void special_regs_w(uint32 address, uint32 data);
|
||||
/* Cart database entry */
|
||||
typedef struct
|
||||
{
|
||||
uint16 chk_1; /* header checksum */
|
||||
uint16 chk_2; /* real checksum */
|
||||
uint8 bank_start; /* first mapped bank in $400000-$7fffff region */
|
||||
uint8 bank_end; /* last mapped bank in $400000-$7fffff region */
|
||||
T_CART_HW cart_hw; /* hardware description */
|
||||
uint16 chk_1; /* header checksum */
|
||||
uint16 chk_2; /* real checksum */
|
||||
uint8 bank_start; /* first mapped bank in $400000-$7fffff region */
|
||||
uint8 bank_end; /* last mapped bank in $400000-$7fffff region */
|
||||
T_CART_HW cart_hw; /* hardware description */
|
||||
} T_CART_ENTRY;
|
||||
|
||||
/* Games that need extra hardware emulation:
|
||||
- copy protection device
|
||||
- custom ROM banking device
|
||||
- copy protection device
|
||||
- custom ROM banking device
|
||||
*/
|
||||
T_CART_ENTRY rom_database[CART_CNT] =
|
||||
{
|
||||
/* Game no Kanzume Otokuyou */
|
||||
{0x0000,0xf9d1,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,seganet_mapper_w,0,0}},
|
||||
{0x0000,0xf9d1,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,seganet_mapper_w,0,0}},
|
||||
/* RADICA (Volume 1) (not byteswapped) */
|
||||
{0x0000,0x2326,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
|
||||
{0x0000,0x2326,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
|
||||
/* RADICA (Volume 2) */
|
||||
{0x4f10,0x0836,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
|
||||
{0x4f10,0x0836,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
|
||||
/* RADICA (Volume 1) */
|
||||
{0xf424,0x9f82,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
|
||||
{0xf424,0x9f82,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
|
||||
/* Funny World & Balloon Boy */
|
||||
{0x0000,0x06ab,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
|
||||
{0x0000,0x06ab,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
|
||||
/* Whac-a-Critter */
|
||||
{0xffff,0xf863,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
|
||||
{0xffff,0xf863,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
|
||||
/* Earth Defense */
|
||||
{0xffff,0x44fb,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
|
||||
{0xffff,0x44fb,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
|
||||
/* Super Mario 2 1998 */
|
||||
{0xffff,0x0474,0,0,{{0x0a,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,0,default_regs_r,0,0,0}},
|
||||
{0xffff,0x0474,0,0,{{0x0a,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,0,default_regs_r,0,0,0}},
|
||||
/* Super Mario 2 1998 */
|
||||
{0x2020,0xb4eb,0,0,{{0x1c,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,0,default_regs_r,0,0,0}},
|
||||
{0x2020,0xb4eb,0,0,{{0x1c,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,0,default_regs_r,0,0,0}},
|
||||
/* Supper Bubble Bobble */
|
||||
{0x0000,0x16cd,0x40,0x40,{{0x55,0x0f,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x400002,0,0},0,0,0,0,default_regs_r,0}},
|
||||
{0x0000,0x16cd,0x40,0x40,{{0x55,0x0f,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x400002,0,0},0,0,0,0,default_regs_r,0}},
|
||||
/* Mahjong Lover */
|
||||
{0x0000,0x7037,0x40,0x40,{{0x90,0xd3,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x401000,0,0},0,0,0,0,default_regs_r,0}},
|
||||
{0x0000,0x7037,0x40,0x40,{{0x90,0xd3,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x401000,0,0},0,0,0,0,default_regs_r,0}},
|
||||
/* Lion King 2 */
|
||||
{0xffff,0x1d9b,0x40,0x40,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,0,default_regs_r,default_regs_w}},
|
||||
{0xffff,0x1d9b,0x40,0x40,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,0,default_regs_r,default_regs_w}},
|
||||
/* Squirell King */
|
||||
{0x0000,0x8ec8,0x40,0x40,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,0,default_regs_r,default_regs_w}},
|
||||
{0x0000,0x8ec8,0x40,0x40,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,0,default_regs_r,default_regs_w}},
|
||||
/* Rockman X3 */
|
||||
{0x0000,0x9d0e,0x40,0x40,{{0x0c,0x88,0,0},{0xffffff,0xffffff,0,0},{0xa13000,0x400004,0,0},0,0,default_regs_r,0,default_regs_r,0}},
|
||||
{0x0000,0x9d0e,0x40,0x40,{{0x0c,0x88,0,0},{0xffffff,0xffffff,0,0},{0xa13000,0x400004,0,0},0,0,default_regs_r,0,default_regs_r,0}},
|
||||
/* A Bug's Life */
|
||||
{0x7f7f,0x2aad,0,0,{{0x28,0x1f,0x01,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
|
||||
{0x7f7f,0x2aad,0,0,{{0x28,0x1f,0x01,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
|
||||
/* King of Fighter 99 */
|
||||
{0x0000,0x21e,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
|
||||
{0x0000,0x21e,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
|
||||
/* Pocket Monster */
|
||||
{0xd6fc,0x1eb1,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
|
||||
{0xd6fc,0x1eb1,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
|
||||
/* Lion King 3 */
|
||||
{0x0000,0x507c,0x60,0x7f,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,1,0,0,default_regs_r,special_regs_w}},
|
||||
{0x0000,0x507c,0x60,0x7f,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,1,0,0,default_regs_r,special_regs_w}},
|
||||
/* Super King Kong 99 */
|
||||
{0x0000,0x7d6e,0x60,0x7f,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,1,0,0,default_regs_r,special_regs_w}},
|
||||
{0x0000,0x7d6e,0x60,0x7f,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,1,0,0,default_regs_r,special_regs_w}},
|
||||
/* Pokemon Stadium */
|
||||
{0x0000,0x843c,0x70,0x7f,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,0,0,0,special_regs_w}},
|
||||
{0x0000,0x843c,0x70,0x7f,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,0,0,0,special_regs_w}},
|
||||
/* Elf Wor */
|
||||
{0x0080,0x3dba,0x40,0x40,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
{0x0080,0x3dba,0x40,0x40,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
/* Huan Le Tao Qi Shu - Smart Mouse */
|
||||
{0x0000,0x1a28,0x40,0x40,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
{0x0000,0x1a28,0x40,0x40,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
/* Ya-Se Chuanshuo */
|
||||
{0xffff,0xd472,0x40,0x40,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
{0xffff,0xd472,0x40,0x40,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
/* Soul Blade */
|
||||
{0x0000,0x0c5b,0x40,0x40,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
{0x0000,0x0c5b,0x40,0x40,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
/* King of Fighter 98 */
|
||||
{0x0000,0xd0a0,0x48,0x4f,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,0,0,default_regs_r,0}},
|
||||
{0x0000,0xd0a0,0x48,0x4f,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,0,0,default_regs_r,0}},
|
||||
/* Lian Huan Pao - Barver Battle Saga */
|
||||
{0x30b9,0x1c2a,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,0,default_regs_r,0}}
|
||||
{0x30b9,0x1c2a,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,0,default_regs_r,0}}
|
||||
};
|
||||
|
||||
|
||||
@ -118,7 +118,7 @@ int old_system[2] = {-1,-1};
|
||||
uint8 mem_chunk[0x10000];
|
||||
|
||||
/************************************************************
|
||||
Cart Hardware initialization
|
||||
Cart Hardware initialization
|
||||
*************************************************************/
|
||||
|
||||
/* hardware that need to be reseted on power on */
|
||||
@ -132,34 +132,34 @@ void cart_hw_reset()
|
||||
for (i=0x00; i<0x40; i++)
|
||||
m68k_memory_map[i].base = cart_rom + (i<<16);
|
||||
}
|
||||
|
||||
/* Realtec mapper */
|
||||
if (cart_hw.realtec & 1)
|
||||
{
|
||||
/* enable BOOTROM */
|
||||
|
||||
/* Realtec mapper */
|
||||
if (cart_hw.realtec & 1)
|
||||
{
|
||||
/* enable BOOTROM */
|
||||
for (i=0; i<0x40; i++) m68k_memory_map[i].base = mem_chunk;
|
||||
for (i=0; i<8; i++) memcpy(mem_chunk + i*0x2000, cart_rom + 0x7e000, 0x2000);
|
||||
cart_hw.realtec |= 2;
|
||||
}
|
||||
|
||||
cart_hw.realtec |= 2;
|
||||
}
|
||||
|
||||
/* save default cartridge slot mapping */
|
||||
default_rom = m68k_memory_map[0].base;
|
||||
|
||||
/* SVP chip */
|
||||
if (svp) svp_reset();
|
||||
/* SVP chip */
|
||||
if (svp) svp_reset();
|
||||
}
|
||||
|
||||
/* cart hardware detection */
|
||||
void cart_hw_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
/**********************************************
|
||||
DEFAULT CARTRIDGE MAPPING
|
||||
***********************************************/
|
||||
for (i=0; i<0x40; i++)
|
||||
{
|
||||
/* cartridge ROM */
|
||||
int i;
|
||||
|
||||
/**********************************************
|
||||
DEFAULT CARTRIDGE MAPPING
|
||||
***********************************************/
|
||||
for (i=0; i<0x40; i++)
|
||||
{
|
||||
/* cartridge ROM */
|
||||
m68k_memory_map[i].base = cart_rom + (i<<16);
|
||||
m68k_memory_map[i].read8 = NULL;
|
||||
m68k_memory_map[i].read16 = NULL;
|
||||
@ -167,33 +167,33 @@ void cart_hw_init()
|
||||
m68k_memory_map[i].write16 = m68k_unused_16_w;
|
||||
zbank_memory_map[i].read = NULL;
|
||||
zbank_memory_map[i].write = zbank_unused_w;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0x40; i<0x80; i++)
|
||||
{
|
||||
/* unused area */
|
||||
for (i=0x40; i<0x80; i++)
|
||||
{
|
||||
/* unused area */
|
||||
m68k_memory_map[i].read8 = m68k_read_bus_8;
|
||||
m68k_memory_map[i].read16 = m68k_read_bus_16;
|
||||
m68k_memory_map[i].write8 = m68k_unused_8_w;
|
||||
m68k_memory_map[i].write16 = m68k_unused_16_w;
|
||||
zbank_memory_map[i].read = zbank_unused_r;
|
||||
zbank_memory_map[i].write = zbank_unused_w;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* restore previous setting */
|
||||
if (old_system[0] != -1) input.system[0] = old_system[0];
|
||||
if (old_system[1] != -1) input.system[1] = old_system[1];
|
||||
|
||||
/**********************************************
|
||||
EXTERNAL RAM
|
||||
***********************************************/
|
||||
sram_init();
|
||||
eeprom_init();
|
||||
if (sram.on)
|
||||
{
|
||||
if (sram.custom)
|
||||
{
|
||||
/* serial EEPROM */
|
||||
/**********************************************
|
||||
EXTERNAL RAM
|
||||
***********************************************/
|
||||
sram_init();
|
||||
eeprom_init();
|
||||
if (sram.on)
|
||||
{
|
||||
if (sram.custom)
|
||||
{
|
||||
/* serial EEPROM */
|
||||
m68k_memory_map[eeprom.type.sda_out_adr >> 16].read8 = eeprom_read_byte;
|
||||
m68k_memory_map[eeprom.type.sda_out_adr >> 16].read16 = eeprom_read_word;
|
||||
m68k_memory_map[eeprom.type.sda_in_adr >> 16].read8 = eeprom_read_byte;
|
||||
@ -203,10 +203,10 @@ void cart_hw_init()
|
||||
zbank_memory_map[eeprom.type.sda_out_adr >> 16].read = eeprom_read_byte;
|
||||
zbank_memory_map[eeprom.type.sda_in_adr >> 16].read = eeprom_read_byte;
|
||||
zbank_memory_map[eeprom.type.scl_adr >> 16].write = eeprom_write_byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Static RAM (64k max.) */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Static RAM (64k max.) */
|
||||
m68k_memory_map[sram.start >> 16].base = sram.sram;
|
||||
m68k_memory_map[sram.start >> 16].read8 = NULL;
|
||||
m68k_memory_map[sram.start >> 16].read16 = NULL;
|
||||
@ -214,16 +214,16 @@ void cart_hw_init()
|
||||
m68k_memory_map[sram.start >> 16].write16 = NULL;
|
||||
zbank_memory_map[sram.start >> 16].read = NULL;
|
||||
zbank_memory_map[sram.start >> 16].write = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
SVP CHIP
|
||||
***********************************************/
|
||||
svp = NULL;
|
||||
if (strstr(rominfo.international,"Virtua Racing") != NULL)
|
||||
{
|
||||
svp_init();
|
||||
/**********************************************
|
||||
SVP CHIP
|
||||
***********************************************/
|
||||
svp = NULL;
|
||||
if (strstr(rominfo.international,"Virtua Racing") != NULL)
|
||||
{
|
||||
svp_init();
|
||||
|
||||
m68k_memory_map[0x30].base = svp->dram;
|
||||
m68k_memory_map[0x30].read16 = NULL;
|
||||
@ -235,30 +235,30 @@ void cart_hw_init()
|
||||
|
||||
m68k_memory_map[0x39].read16 = svp_read_cell_1;
|
||||
m68k_memory_map[0x3a].read16 = svp_read_cell_2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* default GUN settings */
|
||||
input.x_offset = 0x00;
|
||||
input.y_offset = 0x00;
|
||||
|
||||
/**********************************************
|
||||
SEGA MENACER
|
||||
***********************************************/
|
||||
/**********************************************
|
||||
SEGA MENACER
|
||||
***********************************************/
|
||||
if (strstr(rominfo.international,"MENACER") != NULL)
|
||||
{
|
||||
/* save current setting */
|
||||
{
|
||||
/* save current setting */
|
||||
if (old_system[0] == -1) old_system[0] = input.system[0];
|
||||
if (old_system[1] == -1) old_system[1] = input.system[1];
|
||||
|
||||
|
||||
input.system[0] = NO_SYSTEM;
|
||||
input.system[1] = SYSTEM_MENACER;
|
||||
input.x_offset = 0x52;
|
||||
input.y_offset = 0x00;
|
||||
}
|
||||
else if (strstr(rominfo.international,"T2 ; THE ARCADE GAME") != NULL)
|
||||
}
|
||||
else if (strstr(rominfo.international,"T2 ; THE ARCADE GAME") != NULL)
|
||||
{
|
||||
/* save current setting */
|
||||
/* save current setting */
|
||||
if (old_system[0] == -1) old_system[0] = input.system[0];
|
||||
if (old_system[1] == -1) old_system[1] = input.system[1];
|
||||
|
||||
@ -266,10 +266,10 @@ void cart_hw_init()
|
||||
input.system[1] = SYSTEM_MENACER;
|
||||
input.x_offset = 0x84;
|
||||
input.y_offset = 0x08;
|
||||
}
|
||||
else if (strstr(rominfo.international,"BODY COUNT") != NULL)
|
||||
}
|
||||
else if (strstr(rominfo.international,"BODY COUNT") != NULL)
|
||||
{
|
||||
/* save current setting */
|
||||
/* save current setting */
|
||||
if (old_system[0] == -1) old_system[0] = input.system[0];
|
||||
if (old_system[1] == -1) old_system[1] = input.system[1];
|
||||
|
||||
@ -277,14 +277,14 @@ void cart_hw_init()
|
||||
input.system[1] = SYSTEM_MENACER;
|
||||
input.x_offset = 0x44;
|
||||
input.y_offset = 0x18;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
KONAMI JUSTIFIER
|
||||
***********************************************/
|
||||
if (strstr(rominfo.international,"LETHAL ENFORCERS II") != NULL)
|
||||
/**********************************************
|
||||
KONAMI JUSTIFIER
|
||||
***********************************************/
|
||||
if (strstr(rominfo.international,"LETHAL ENFORCERS II") != NULL)
|
||||
{
|
||||
/* save current setting */
|
||||
/* save current setting */
|
||||
if (old_system[0] == -1) old_system[0] = input.system[0];
|
||||
if (old_system[1] == -1) old_system[1] = input.system[1];
|
||||
|
||||
@ -292,10 +292,10 @@ void cart_hw_init()
|
||||
input.system[1] = SYSTEM_JUSTIFIER;
|
||||
input.x_offset = 0x18;
|
||||
input.y_offset = 0x00;
|
||||
}
|
||||
else if (strstr(rominfo.international,"LETHAL ENFORCERS") != NULL)
|
||||
}
|
||||
else if (strstr(rominfo.international,"LETHAL ENFORCERS") != NULL)
|
||||
{
|
||||
/* save current setting */
|
||||
/* save current setting */
|
||||
if (old_system[0] == -1) old_system[0] = input.system[0];
|
||||
if (old_system[1] == -1) old_system[1] = input.system[1];
|
||||
|
||||
@ -305,22 +305,22 @@ void cart_hw_init()
|
||||
input.y_offset = 0x00;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
J-CART
|
||||
***********************************************/
|
||||
j_cart = 0;
|
||||
if (((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x168b)) || /* Super Skidmarks, Micro Machines Military*/
|
||||
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x165e)) || /* Pete Sampras Tennis (1991), Micro Machines 96 */
|
||||
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0xcee0)) || /* Micro Machines Military (bad) */
|
||||
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x2c41)) || /* Micro Machines 96 (bad) */
|
||||
((strstr(rominfo.product,"XXXXXXXX") != NULL) && (rominfo.checksum == 0xdf39)) || /* Sampras Tennis 96 */
|
||||
((strstr(rominfo.product,"T-123456") != NULL) && (rominfo.checksum == 0x1eae)) || /* Sampras Tennis 96 */
|
||||
((strstr(rominfo.product,"T-120066") != NULL) && (rominfo.checksum == 0x16a4)) || /* Pete Sampras Tennis (1994)*/
|
||||
(strstr(rominfo.product,"T-120096") != NULL)) /* Micro Machines 2 */
|
||||
{
|
||||
if (genromsize <= 0x380000) /* just to be sure (checksum might not be enough) */
|
||||
{
|
||||
j_cart = 1;
|
||||
/**********************************************
|
||||
J-CART
|
||||
***********************************************/
|
||||
j_cart = 0;
|
||||
if (((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x168b)) || /* Super Skidmarks, Micro Machines Military*/
|
||||
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x165e)) || /* Pete Sampras Tennis (1991), Micro Machines 96 */
|
||||
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0xcee0)) || /* Micro Machines Military (bad) */
|
||||
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x2c41)) || /* Micro Machines 96 (bad) */
|
||||
((strstr(rominfo.product,"XXXXXXXX") != NULL) && (rominfo.checksum == 0xdf39)) || /* Sampras Tennis 96 */
|
||||
((strstr(rominfo.product,"T-123456") != NULL) && (rominfo.checksum == 0x1eae)) || /* Sampras Tennis 96 */
|
||||
((strstr(rominfo.product,"T-120066") != NULL) && (rominfo.checksum == 0x16a4)) || /* Pete Sampras Tennis (1994)*/
|
||||
(strstr(rominfo.product,"T-120096") != NULL)) /* Micro Machines 2 */
|
||||
{
|
||||
if (genromsize <= 0x380000) /* just to be sure (checksum might not be enough) */
|
||||
{
|
||||
j_cart = 1;
|
||||
m68k_memory_map[0x38].read16 = jcart_read;
|
||||
m68k_memory_map[0x38].write16 = jcart_write;
|
||||
m68k_memory_map[0x3f].read16 = jcart_read;
|
||||
@ -333,47 +333,47 @@ void cart_hw_init()
|
||||
/* PORT B by default */
|
||||
input.system[0] = SYSTEM_GAMEPAD;
|
||||
input.system[1] = SYSTEM_GAMEPAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
Mappers & HW registers
|
||||
***********************************************/
|
||||
memset(&cart_hw, 0, sizeof(cart_hw));
|
||||
/**********************************************
|
||||
Mappers & HW registers
|
||||
***********************************************/
|
||||
memset(&cart_hw, 0, sizeof(cart_hw));
|
||||
|
||||
/* search for game into database */
|
||||
for (i=0; i < CART_CNT + 1; i++)
|
||||
{
|
||||
/* known cart found ! */
|
||||
if ((rominfo.checksum == rom_database[i].chk_1) &&
|
||||
(realchecksum == rom_database[i].chk_2))
|
||||
{
|
||||
/* retrieve hardware information */
|
||||
memcpy(&cart_hw, &(rom_database[i].cart_hw), sizeof(cart_hw));
|
||||
for (i=0; i < CART_CNT + 1; i++)
|
||||
{
|
||||
/* known cart found ! */
|
||||
if ((rominfo.checksum == rom_database[i].chk_1) &&
|
||||
(realchecksum == rom_database[i].chk_2))
|
||||
{
|
||||
/* retrieve hardware information */
|
||||
memcpy(&cart_hw, &(rom_database[i].cart_hw), sizeof(cart_hw));
|
||||
|
||||
/* initialize memory handlers for $400000-$7fffff region */
|
||||
int j = rom_database[i].bank_start;
|
||||
while (j <= rom_database[i].bank_end)
|
||||
{
|
||||
if (cart_hw.regs_r)
|
||||
/* initialize memory handlers for $400000-$7fffff region */
|
||||
int j = rom_database[i].bank_start;
|
||||
while (j <= rom_database[i].bank_end)
|
||||
{
|
||||
if (cart_hw.regs_r)
|
||||
{
|
||||
m68k_memory_map[j].read8 = cart_hw.regs_r;
|
||||
m68k_memory_map[j].read16 = cart_hw.regs_r;
|
||||
zbank_memory_map[j].read = cart_hw.regs_r;
|
||||
}
|
||||
}
|
||||
if (cart_hw.regs_w)
|
||||
{
|
||||
m68k_memory_map[j].write8 = cart_hw.regs_w;
|
||||
m68k_memory_map[j].write16 = cart_hw.regs_w;
|
||||
zbank_memory_map[j].write = cart_hw.regs_w;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
/* leave loop */
|
||||
i = CART_CNT + 1;
|
||||
}
|
||||
}
|
||||
/* leave loop */
|
||||
i = CART_CNT + 1;
|
||||
}
|
||||
}
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
/* default behavior */
|
||||
@ -403,26 +403,26 @@ void cart_hw_init()
|
||||
cart_hw.bankshift = 1;
|
||||
}
|
||||
|
||||
/* default write handler for !TIME signal */
|
||||
if (!cart_hw.time_w) cart_hw.time_w = default_time_w;
|
||||
/* default write handler for !TIME signal */
|
||||
if (!cart_hw.time_w) cart_hw.time_w = default_time_w;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
MAPPER handlers
|
||||
MAPPER handlers
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
"official" ROM/RAM switch
|
||||
"official" ROM/RAM switch
|
||||
*/
|
||||
static inline void sega_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
uint32 i,slot = (address >> 1) & 7;
|
||||
uint32 i,slot = (address >> 1) & 7;
|
||||
uint8 *src;
|
||||
|
||||
switch (slot)
|
||||
{
|
||||
case 0:
|
||||
/* ROM/SRAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
|
||||
|
||||
switch (slot)
|
||||
{
|
||||
case 0:
|
||||
/* ROM/SRAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
|
||||
if (data & 1)
|
||||
{
|
||||
/* SRAM enabled */
|
||||
@ -448,38 +448,38 @@ static inline void sega_mapper_w(uint32 address, uint32 data)
|
||||
/* ROM enabled */
|
||||
m68k_memory_map[0x20].base = cart_rom + 0x200000;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ROM Bankswitch (Super Street Fighter 2)
|
||||
documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt)
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ROM Bankswitch (Super Street Fighter 2)
|
||||
documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt)
|
||||
*/
|
||||
slot = slot << 3; /* 8 x 512k banks */
|
||||
src = cart_rom + (data << 19);
|
||||
for (i=0; i<8; i++) m68k_memory_map[slot++].base = src + (i<<16);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
custom ROM Bankswitch used by pirate "Multi-in-1" carts
|
||||
custom ROM Bankswitch used by pirate "Multi-in-1" carts
|
||||
*/
|
||||
static inline void multi_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
cart_hw.bankshift = 1;
|
||||
|
||||
/* 64 x 64k banks */
|
||||
/* 64 x 64k banks */
|
||||
for (i=0; i<64; i++)
|
||||
{
|
||||
{
|
||||
m68k_memory_map[i].base = &cart_rom[((address++) & 0x3f) << 16];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Special ROM Bankswitch used for copy protection
|
||||
Used by unlicensed cartridges (Lion King III, Super King Kong 99)
|
||||
Special ROM Bankswitch used for copy protection
|
||||
Used by unlicensed cartridges (Lion King III, Super King Kong 99)
|
||||
*/
|
||||
void special_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
@ -490,60 +490,60 @@ void special_mapper_w(uint32 address, uint32 data)
|
||||
}
|
||||
|
||||
/*
|
||||
Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter)
|
||||
Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter)
|
||||
*/
|
||||
void realtec_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
int i;
|
||||
uint32 base;
|
||||
uint32 base;
|
||||
|
||||
/* 32 x 128k banks */
|
||||
switch (address)
|
||||
{
|
||||
case 0x404000: /* three lower bits of ROM base address */
|
||||
cart_hw.regs[0] = data & 7;
|
||||
base = ((data & 7) | (cart_hw.regs[1] << 2));
|
||||
/* 32 x 128k banks */
|
||||
switch (address)
|
||||
{
|
||||
case 0x404000: /* three lower bits of ROM base address */
|
||||
cart_hw.regs[0] = data & 7;
|
||||
base = ((data & 7) | (cart_hw.regs[1] << 2));
|
||||
for (i=0; i<=cart_hw.regs[2]; i++)
|
||||
{
|
||||
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16];
|
||||
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16];
|
||||
}
|
||||
return;
|
||||
return;
|
||||
|
||||
case 0x400000: /* two higher bits of ROM base address */
|
||||
cart_hw.regs[1] = data & 6;
|
||||
base = cart_hw.regs[0] | ((data & 6) << 2);
|
||||
case 0x400000: /* two higher bits of ROM base address */
|
||||
cart_hw.regs[1] = data & 6;
|
||||
base = cart_hw.regs[0] | ((data & 6) << 2);
|
||||
for (i=0; i<=cart_hw.regs[2]; i++)
|
||||
{
|
||||
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16];
|
||||
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16];
|
||||
}
|
||||
return;
|
||||
return;
|
||||
|
||||
case 0x402000: /* number of 128k blocks to map */
|
||||
cart_hw.regs[2] = data & 0x1f;
|
||||
base = cart_hw.regs[0] | (cart_hw.regs[1] << 2);
|
||||
case 0x402000: /* number of 128k blocks to map */
|
||||
cart_hw.regs[2] = data & 0x1f;
|
||||
base = cart_hw.regs[0] | (cart_hw.regs[1] << 2);
|
||||
for (i=0; i<=(data & 0x1f); i++)
|
||||
{
|
||||
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16];
|
||||
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16];
|
||||
}
|
||||
return;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Game no Kanzume Otokuyou ROM Mapper */
|
||||
void seganet_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
if ((address & 0xff) == 0xf1)
|
||||
if ((address & 0xff) == 0xf1)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
if (data & 1)
|
||||
{
|
||||
/* ROM Write protected */
|
||||
for (i=0; i<0x40; i++)
|
||||
{
|
||||
{
|
||||
m68k_memory_map[i].write8 = m68k_unused_8_w;
|
||||
m68k_memory_map[i].write16 = m68k_unused_16_w;
|
||||
zbank_memory_map[i].write = zbank_unused_w;
|
||||
@ -557,99 +557,99 @@ void seganet_mapper_w(uint32 address, uint32 data)
|
||||
m68k_memory_map[i].write8 = NULL;
|
||||
m68k_memory_map[i].write16 = NULL;
|
||||
zbank_memory_map[i].write = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
RADICA ROM Bankswitch (use !TIME)
|
||||
RADICA ROM Bankswitch (use !TIME)
|
||||
*/
|
||||
uint32 radica_mapper_r(uint32 address)
|
||||
{
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
address = (address >> 1);
|
||||
|
||||
/* 64 x 64k banks */
|
||||
/* 64 x 64k banks */
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = &cart_rom[((address++)& 0x3f)<< 16];
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
default !TIME signal handler
|
||||
default !TIME signal handler
|
||||
*************************************************************/
|
||||
|
||||
/* default ROM bankswitch */
|
||||
void default_time_w(uint32 address, uint32 data)
|
||||
{
|
||||
if ((address & 0xf1) == 0xf1) sega_mapper_w(address, data);
|
||||
else if (address < 0xa13040) multi_mapper_w(address, data);
|
||||
if ((address & 0xf1) == 0xf1) sega_mapper_w(address, data);
|
||||
else if (address < 0xa13040) multi_mapper_w(address, data);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
Internal register handlers
|
||||
Internal register handlers
|
||||
*************************************************************/
|
||||
|
||||
uint32 default_regs_r(uint32 address)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
|
||||
return cart_hw.regs[i];
|
||||
}
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
|
||||
return cart_hw.regs[i];
|
||||
}
|
||||
|
||||
/* unused */
|
||||
return 0xffff;
|
||||
/* unused */
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
void default_regs_w(uint32 address, uint32 data)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
|
||||
{
|
||||
cart_hw.regs[i] = data;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
|
||||
{
|
||||
cart_hw.regs[i] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* special register behaviour (Lion King III, Super Donkey Kong 99) */
|
||||
void special_regs_w(uint32 address, uint32 data)
|
||||
{
|
||||
/* ROM bankswitch */
|
||||
if ((address >> 16) > 0x6f)
|
||||
{
|
||||
special_mapper_w(address, data);
|
||||
return;
|
||||
}
|
||||
/* ROM bankswitch */
|
||||
if ((address >> 16) > 0x6f)
|
||||
{
|
||||
special_mapper_w(address, data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* write regs */
|
||||
default_regs_w(address, data);
|
||||
/* write regs */
|
||||
default_regs_w(address, data);
|
||||
|
||||
/* bitswapping (documented by Haze) */
|
||||
uint32 temp = cart_hw.regs[0];
|
||||
switch (cart_hw.regs[1])
|
||||
{
|
||||
case 1:
|
||||
cart_hw.regs[2] = (temp >> 1);
|
||||
return;
|
||||
/* bitswapping (documented by Haze) */
|
||||
uint32 temp = cart_hw.regs[0];
|
||||
switch (cart_hw.regs[1])
|
||||
{
|
||||
case 1:
|
||||
cart_hw.regs[2] = (temp >> 1);
|
||||
return;
|
||||
|
||||
case 2:
|
||||
cart_hw.regs[2] = ((temp >> 4) | ((temp & 0x0F) << 4));
|
||||
return;
|
||||
case 2:
|
||||
cart_hw.regs[2] = ((temp >> 4) | ((temp & 0x0F) << 4));
|
||||
return;
|
||||
|
||||
default:
|
||||
cart_hw.regs[2] = (((temp >> 7) & 0x01) | ((temp >> 5) & 0x02) |
|
||||
((temp >> 3) & 0x04) | ((temp >> 1) & 0x08) |
|
||||
((temp << 1) & 0x10) | ((temp << 3) & 0x20) |
|
||||
((temp << 5) & 0x40) | ((temp << 7) & 0x80));
|
||||
return;
|
||||
}
|
||||
default:
|
||||
cart_hw.regs[2] = (((temp >> 7) & 0x01) | ((temp >> 5) & 0x02) |
|
||||
((temp >> 3) & 0x04) | ((temp >> 1) & 0x08) |
|
||||
((temp << 1) & 0x10) | ((temp << 3) & 0x20) |
|
||||
((temp << 5) & 0x40) | ((temp << 7) & 0x80));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -30,15 +30,15 @@
|
||||
/* Hardware description */
|
||||
typedef struct
|
||||
{
|
||||
uint8 regs[4]; /* internal registers (R/W) */
|
||||
uint32 mask[4]; /* registers address mask */
|
||||
uint32 addr[4]; /* registers address */
|
||||
uint32 realtec; /* bit 0: realtec mapper detected, bit 1: bootrom enabled */
|
||||
uint32 bankshift; /* cartridge with bankshift mecanism */
|
||||
unsigned int (*time_r)(unsigned int address); /* !TIME signal ($a130xx) read handler */
|
||||
void (*time_w)(unsigned int address, unsigned int data); /* !TIME signal ($a130xx) write handler */
|
||||
unsigned int (*regs_r)(unsigned int address); /* cart hardware region ($400000-$7fffff) read handler */
|
||||
void (*regs_w)(unsigned int address, unsigned int data); /* cart hardware region ($400000-$7fffff) write handler */
|
||||
uint8 regs[4]; /* internal registers (R/W) */
|
||||
uint32 mask[4]; /* registers address mask */
|
||||
uint32 addr[4]; /* registers address */
|
||||
uint32 realtec; /* bit 0: realtec mapper detected, bit 1: bootrom enabled */
|
||||
uint32 bankshift; /* cartridge with bankshift mecanism */
|
||||
unsigned int (*time_r)(unsigned int address); /* !TIME signal ($a130xx) read handler */
|
||||
void (*time_w)(unsigned int address, unsigned int data); /* !TIME signal ($a130xx) write handler */
|
||||
unsigned int (*regs_r)(unsigned int address); /* cart hardware region ($400000-$7fffff) read handler */
|
||||
void (*regs_w)(unsigned int address, unsigned int data); /* cart hardware region ($400000-$7fffff) write handler */
|
||||
} T_CART_HW;
|
||||
|
||||
/* global variables */
|
||||
|
@ -23,53 +23,53 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char game_id[14];
|
||||
uint16 chk;
|
||||
T_EEPROM_TYPE type;
|
||||
char game_id[14];
|
||||
uint16 chk;
|
||||
T_EEPROM_TYPE type;
|
||||
} T_GAME_ENTRY;
|
||||
|
||||
T_GAME_ENTRY database[24] =
|
||||
{
|
||||
/* ACCLAIM mappers */
|
||||
/* 24C02 (old mapper) */
|
||||
{{"T-081326" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (UE) */
|
||||
{{"T-81033" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (J) */
|
||||
/* ACCLAIM mappers */
|
||||
/* 24C02 (old mapper) */
|
||||
{{"T-081326" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (UE) */
|
||||
{{"T-81033" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (J) */
|
||||
|
||||
/* 24C02 */
|
||||
{{"T-81406" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NBA Jam TE */
|
||||
{{"T-081276" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club */
|
||||
/* 24C16 */
|
||||
{{"T-081586" }, 0, {8, 0x7FF, 0x7FF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club '96 */
|
||||
/* 24C65 */
|
||||
{{"T-81576" }, 0, {16, 0x1FFF, 0x1FFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* College Slam */
|
||||
{{"T-81476" }, 0, {16, 0x1FFF, 0x1FFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* Frank Thomas Big Hurt Baseball */
|
||||
|
||||
/* EA mapper (24C01 only) */
|
||||
{{"T-50396" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* NHLPA Hockey 93 (UE) */
|
||||
{{"T-50176" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* Rings of Power */
|
||||
|
||||
/* SEGA mapper (24C01 only) */
|
||||
{{"T-12046" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Megaman - The Wily Wars */
|
||||
{{"T-12053" }, 0xEA80, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Rockman Mega World (J) [A] */
|
||||
{{"MK-1215" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Evander 'Real Deal' Holyfield's Boxing */
|
||||
{{"MK-1228" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (U) */
|
||||
{{"G-5538" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (J) */
|
||||
{{"PR-1993" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (E) */
|
||||
{{"G-4060" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Wonderboy in Monster World */
|
||||
{{"00001211-00"}, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Sports Talk Baseball */
|
||||
|
||||
/* CODEMASTERS mapper */
|
||||
/* 24C01 */
|
||||
{{"T-120106"}, 0, {7, 0x7F, 0x7F, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Brian Lara Cricket */
|
||||
/* 24C08 */
|
||||
{{"T-120096" }, 0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines 2 - Turbo Tournament (E) */
|
||||
{{"00000000-00"}, 0x168B, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military */
|
||||
{{"00000000-00"}, 0xCEE0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military (Bad)*/
|
||||
/* 24C16 */
|
||||
{{"00000000-00"}, 0x165E, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Turbo Tournament 96 */
|
||||
{{"00000000-00"}, 0x2C41, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Turbo Tournament 96 (Bad)*/
|
||||
/* 24C65 */
|
||||
{{"T-120146-50"}, 0, {16, 0x1FFF, 0x1FFF, 0x300000, 0x380001, 0x300000, 0, 7, 1}} /* Brian Lara Cricket 96, Shane Warne Cricket */
|
||||
/* 24C02 */
|
||||
{{"T-81406" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NBA Jam TE */
|
||||
{{"T-081276" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club */
|
||||
/* 24C16 */
|
||||
{{"T-081586" }, 0, {8, 0x7FF, 0x7FF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club '96 */
|
||||
/* 24C65 */
|
||||
{{"T-81576" }, 0, {16, 0x1FFF, 0x1FFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* College Slam */
|
||||
{{"T-81476" }, 0, {16, 0x1FFF, 0x1FFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* Frank Thomas Big Hurt Baseball */
|
||||
|
||||
/* EA mapper (24C01 only) */
|
||||
{{"T-50396" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* NHLPA Hockey 93 (UE) */
|
||||
{{"T-50176" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* Rings of Power */
|
||||
|
||||
/* SEGA mapper (24C01 only) */
|
||||
{{"T-12046" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Megaman - The Wily Wars */
|
||||
{{"T-12053" }, 0xEA80, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Rockman Mega World (J) [A] */
|
||||
{{"MK-1215" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Evander 'Real Deal' Holyfield's Boxing */
|
||||
{{"MK-1228" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (U) */
|
||||
{{"G-5538" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (J) */
|
||||
{{"PR-1993" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (E) */
|
||||
{{"G-4060" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Wonderboy in Monster World */
|
||||
{{"00001211-00"}, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Sports Talk Baseball */
|
||||
|
||||
/* CODEMASTERS mapper */
|
||||
/* 24C01 */
|
||||
{{"T-120106"}, 0, {7, 0x7F, 0x7F, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Brian Lara Cricket */
|
||||
/* 24C08 */
|
||||
{{"T-120096" }, 0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines 2 - Turbo Tournament (E) */
|
||||
{{"00000000-00"}, 0x168B, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military */
|
||||
{{"00000000-00"}, 0xCEE0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military (Bad)*/
|
||||
/* 24C16 */
|
||||
{{"00000000-00"}, 0x165E, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Turbo Tournament 96 */
|
||||
{{"00000000-00"}, 0x2C41, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Turbo Tournament 96 (Bad)*/
|
||||
/* 24C65 */
|
||||
{{"T-120146-50"}, 0, {16, 0x1FFF, 0x1FFF, 0x300000, 0x380001, 0x300000, 0, 7, 1}} /* Brian Lara Cricket 96, Shane Warne Cricket */
|
||||
};
|
||||
|
||||
|
||||
@ -77,85 +77,85 @@ T_EEPROM eeprom;
|
||||
|
||||
void eeprom_init()
|
||||
{
|
||||
uint8 i = 0;
|
||||
|
||||
/* initialize eeprom */
|
||||
memset(&eeprom, 0, sizeof(T_EEPROM));
|
||||
eeprom.sda = eeprom.old_sda = 1;
|
||||
eeprom.scl = eeprom.old_scl = 1;
|
||||
eeprom.state = STAND_BY;
|
||||
uint8 i = 0;
|
||||
|
||||
sram.custom = 0;
|
||||
|
||||
/* look into game database */
|
||||
while ((i<24) && (!sram.custom))
|
||||
{
|
||||
if (strstr(rominfo.product,database[i].game_id) != NULL)
|
||||
{
|
||||
/* additional check (Micro Machines, Rockman Mega World) */
|
||||
if ((database[i].chk == 0) || (database[i].chk == rominfo.checksum))
|
||||
{
|
||||
sram.custom = 1;
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
memcpy(&eeprom.type, &database[i].type, sizeof(T_EEPROM_TYPE));
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
/* initialize eeprom */
|
||||
memset(&eeprom, 0, sizeof(T_EEPROM));
|
||||
eeprom.sda = eeprom.old_sda = 1;
|
||||
eeprom.scl = eeprom.old_scl = 1;
|
||||
eeprom.state = STAND_BY;
|
||||
|
||||
/* Game not found in database but header seems to indicate it uses EEPROM */
|
||||
sram.custom = 0;
|
||||
|
||||
/* look into game database */
|
||||
while ((i<24) && (!sram.custom))
|
||||
{
|
||||
if (strstr(rominfo.product,database[i].game_id) != NULL)
|
||||
{
|
||||
/* additional check (Micro Machines, Rockman Mega World) */
|
||||
if ((database[i].chk == 0) || (database[i].chk == rominfo.checksum))
|
||||
{
|
||||
sram.custom = 1;
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
memcpy(&eeprom.type, &database[i].type, sizeof(T_EEPROM_TYPE));
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Game not found in database but header seems to indicate it uses EEPROM */
|
||||
if (!sram.custom)
|
||||
{
|
||||
{
|
||||
if ((sram.end - sram.start) < 2)
|
||||
{
|
||||
sram.custom = 1;
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
|
||||
/* set SEGA mapper as default */
|
||||
memcpy(&eeprom.type, &database[9].type, sizeof(T_EEPROM_TYPE));
|
||||
}
|
||||
}
|
||||
{
|
||||
sram.custom = 1;
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
|
||||
/* set SEGA mapper as default */
|
||||
memcpy(&eeprom.type, &database[9].type, sizeof(T_EEPROM_TYPE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Detect_START()
|
||||
{
|
||||
if (eeprom.old_scl && eeprom.scl)
|
||||
{
|
||||
if (eeprom.old_sda && !eeprom.sda)
|
||||
{
|
||||
eeprom.cycles = 0;
|
||||
eeprom.slave_mask = 0;
|
||||
if (eeprom.type.address_bits == 7)
|
||||
{
|
||||
eeprom.word_address = 0;
|
||||
eeprom.state = GET_WORD_ADR_7BITS;
|
||||
}
|
||||
else eeprom.state = GET_SLAVE_ADR;
|
||||
}
|
||||
}
|
||||
if (eeprom.old_scl && eeprom.scl)
|
||||
{
|
||||
if (eeprom.old_sda && !eeprom.sda)
|
||||
{
|
||||
eeprom.cycles = 0;
|
||||
eeprom.slave_mask = 0;
|
||||
if (eeprom.type.address_bits == 7)
|
||||
{
|
||||
eeprom.word_address = 0;
|
||||
eeprom.state = GET_WORD_ADR_7BITS;
|
||||
}
|
||||
else eeprom.state = GET_SLAVE_ADR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Detect_STOP()
|
||||
{
|
||||
if (eeprom.old_scl && eeprom.scl)
|
||||
{
|
||||
if (!eeprom.old_sda && eeprom.sda)
|
||||
{
|
||||
eeprom.state = STAND_BY;
|
||||
}
|
||||
}
|
||||
if (eeprom.old_scl && eeprom.scl)
|
||||
{
|
||||
if (!eeprom.old_sda && eeprom.sda)
|
||||
{
|
||||
eeprom.state = STAND_BY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_write(uint32 address, uint32 value, uint32 word_access)
|
||||
{
|
||||
/* decode SCL and SDA value */
|
||||
/* decode SCL and SDA value */
|
||||
if (word_access)
|
||||
{
|
||||
/* 16-bits access */
|
||||
if (eeprom.type.sda_in_adr == address) eeprom.sda = (value >> (8 + eeprom.type.sda_in_bit)) & 1; /* MSB */
|
||||
else if (eeprom.type.sda_in_adr == (address | 1)) eeprom.sda = (value >> eeprom.type.sda_in_bit) & 1; /* LSB */
|
||||
if (eeprom.type.sda_in_adr == address) eeprom.sda = (value >> (8 + eeprom.type.sda_in_bit)) & 1; /* MSB */
|
||||
else if (eeprom.type.sda_in_adr == (address | 1)) eeprom.sda = (value >> eeprom.type.sda_in_bit) & 1; /* LSB */
|
||||
else eeprom.sda = eeprom.old_sda;
|
||||
|
||||
if (eeprom.type.scl_adr == address) eeprom.scl = (value >> (8 + eeprom.type.scl_bit)) & 1; /* MSB */
|
||||
@ -170,284 +170,282 @@ void eeprom_write(uint32 address, uint32 value, uint32 word_access)
|
||||
if (eeprom.type.scl_adr == address) eeprom.scl = (value >> eeprom.type.scl_bit) & 1;
|
||||
else eeprom.scl = eeprom.old_scl;
|
||||
}
|
||||
|
||||
/* EEPROM current state */
|
||||
switch (eeprom.state)
|
||||
{
|
||||
/* Standby Mode */
|
||||
case STAND_BY:
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
break;
|
||||
|
||||
/* EEPROM current state */
|
||||
switch (eeprom.state)
|
||||
{
|
||||
/* Standby Mode */
|
||||
case STAND_BY:
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
break;
|
||||
|
||||
/* Suspended Mode */
|
||||
case WAIT_STOP:
|
||||
Detect_STOP();
|
||||
break;
|
||||
|
||||
/* Get Word Address 7 bits: MODE-1 only (24C01)
|
||||
* and R/W bit
|
||||
*/
|
||||
case GET_WORD_ADR_7BITS:
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
|
||||
/* look for SCL LOW to HIGH transition */
|
||||
if (!eeprom.old_scl && eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles == 0) eeprom.cycles ++;
|
||||
}
|
||||
|
||||
|
||||
/* Suspended Mode */
|
||||
case WAIT_STOP:
|
||||
Detect_STOP();
|
||||
break;
|
||||
|
||||
|
||||
/* Get Word Address 7 bits: MODE-1 only (24C01)
|
||||
* and R/W bit
|
||||
*/
|
||||
case GET_WORD_ADR_7BITS:
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
|
||||
/* look for SCL LOW to HIGH transition */
|
||||
if (!eeprom.old_scl && eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles == 0) eeprom.cycles ++;
|
||||
}
|
||||
|
||||
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl && (eeprom.cycles > 0))
|
||||
{
|
||||
if (eeprom.cycles < 8)
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl && (eeprom.cycles > 0))
|
||||
{
|
||||
if (eeprom.cycles < 8)
|
||||
{
|
||||
eeprom.word_address |= (eeprom.old_sda << (7 - eeprom.cycles));
|
||||
}
|
||||
}
|
||||
else if (eeprom.cycles == 8)
|
||||
{
|
||||
eeprom.rw = eeprom.old_sda;
|
||||
}
|
||||
else
|
||||
{ /* ACK CYCLE */
|
||||
eeprom.cycles = 0;
|
||||
eeprom.word_address &= eeprom.type.size_mask;
|
||||
eeprom.state = eeprom.rw ? READ_DATA : WRITE_DATA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* ACK CYCLE */
|
||||
eeprom.cycles = 0;
|
||||
eeprom.word_address &= eeprom.type.size_mask;
|
||||
eeprom.state = eeprom.rw ? READ_DATA : WRITE_DATA;
|
||||
}
|
||||
|
||||
eeprom.cycles ++;
|
||||
}
|
||||
break;
|
||||
eeprom.cycles ++;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* Get Slave Address (3bits) : MODE-2 & MODE-3 only (24C01 - 24C512) (0-3bits, depending on the array size)
|
||||
* or/and Word Address MSB: MODE-2 only (24C04 - 24C16) (0-3bits, depending on the array size)
|
||||
* and R/W bit
|
||||
*/
|
||||
case GET_SLAVE_ADR:
|
||||
/* Get Slave Address (3bits) : MODE-2 & MODE-3 only (24C01 - 24C512) (0-3bits, depending on the array size)
|
||||
* or/and Word Address MSB: MODE-2 only (24C04 - 24C16) (0-3bits, depending on the array size)
|
||||
* and R/W bit
|
||||
*/
|
||||
case GET_SLAVE_ADR:
|
||||
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
|
||||
/* look for SCL LOW to HIGH transition */
|
||||
if (!eeprom.old_scl && eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles == 0) eeprom.cycles ++;
|
||||
}
|
||||
/* look for SCL LOW to HIGH transition */
|
||||
if (!eeprom.old_scl && eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles == 0) eeprom.cycles ++;
|
||||
}
|
||||
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl && (eeprom.cycles > 0))
|
||||
{
|
||||
if ((eeprom.cycles > 4) && (eeprom.cycles <8))
|
||||
{
|
||||
if ((eeprom.type.address_bits == 16) ||
|
||||
(eeprom.type.size_mask < (1 << (15 - eeprom.cycles))))
|
||||
{
|
||||
/* this is a SLAVE ADDRESS bit */
|
||||
eeprom.slave_mask |= (eeprom.old_sda << (7 - eeprom.cycles));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this is a WORD ADDRESS high bit */
|
||||
if (eeprom.old_sda) eeprom.word_address |= (1 << (15 - eeprom.cycles));
|
||||
else eeprom.word_address &= ~(1 << (15 - eeprom.cycles));
|
||||
}
|
||||
}
|
||||
else if (eeprom.cycles == 8) eeprom.rw = eeprom.old_sda;
|
||||
else if (eeprom.cycles > 8)
|
||||
{
|
||||
/* ACK CYCLE */
|
||||
eeprom.cycles = 0;
|
||||
if (eeprom.type.address_bits == 16)
|
||||
{
|
||||
/* two ADDRESS bytes */
|
||||
eeprom.state = eeprom.rw ? READ_DATA : GET_WORD_ADR_HIGH;
|
||||
eeprom.slave_mask <<= 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* one ADDRESS byte */
|
||||
eeprom.state = eeprom.rw ? READ_DATA : GET_WORD_ADR_LOW;
|
||||
eeprom.slave_mask <<= 8;
|
||||
}
|
||||
}
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl && (eeprom.cycles > 0))
|
||||
{
|
||||
if ((eeprom.cycles > 4) && (eeprom.cycles <8))
|
||||
{
|
||||
if ((eeprom.type.address_bits == 16) ||
|
||||
(eeprom.type.size_mask < (1 << (15 - eeprom.cycles))))
|
||||
{
|
||||
/* this is a SLAVE ADDRESS bit */
|
||||
eeprom.slave_mask |= (eeprom.old_sda << (7 - eeprom.cycles));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this is a WORD ADDRESS high bit */
|
||||
if (eeprom.old_sda) eeprom.word_address |= (1 << (15 - eeprom.cycles));
|
||||
else eeprom.word_address &= ~(1 << (15 - eeprom.cycles));
|
||||
}
|
||||
}
|
||||
else if (eeprom.cycles == 8) eeprom.rw = eeprom.old_sda;
|
||||
else if (eeprom.cycles > 8)
|
||||
{
|
||||
/* ACK CYCLE */
|
||||
eeprom.cycles = 0;
|
||||
if (eeprom.type.address_bits == 16)
|
||||
{
|
||||
/* two ADDRESS bytes */
|
||||
eeprom.state = eeprom.rw ? READ_DATA : GET_WORD_ADR_HIGH;
|
||||
eeprom.slave_mask <<= 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* one ADDRESS byte */
|
||||
eeprom.state = eeprom.rw ? READ_DATA : GET_WORD_ADR_LOW;
|
||||
eeprom.slave_mask <<= 8;
|
||||
}
|
||||
}
|
||||
|
||||
eeprom.cycles ++;
|
||||
}
|
||||
break;
|
||||
eeprom.cycles ++;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Get Word Address MSB (4-8bits depending on the array size)
|
||||
* MODE-3 only (24C32 - 24C512)
|
||||
*/
|
||||
case GET_WORD_ADR_HIGH:
|
||||
/* Get Word Address MSB (4-8bits depending on the array size)
|
||||
* MODE-3 only (24C32 - 24C512)
|
||||
*/
|
||||
case GET_WORD_ADR_HIGH:
|
||||
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles < 9)
|
||||
{
|
||||
if ((eeprom.type.size_mask + 1) < (1 << (17 - eeprom.cycles)))
|
||||
{
|
||||
/* ignored bit: slave mask should be right-shifted by one */
|
||||
eeprom.slave_mask >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this is a WORD ADDRESS high bit */
|
||||
if (eeprom.old_sda) eeprom.word_address |= (1 << (16 - eeprom.cycles));
|
||||
else eeprom.word_address &= ~(1 << (16 - eeprom.cycles));
|
||||
}
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles < 9)
|
||||
{
|
||||
if ((eeprom.type.size_mask + 1) < (1 << (17 - eeprom.cycles)))
|
||||
{
|
||||
/* ignored bit: slave mask should be right-shifted by one */
|
||||
eeprom.slave_mask >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this is a WORD ADDRESS high bit */
|
||||
if (eeprom.old_sda) eeprom.word_address |= (1 << (16 - eeprom.cycles));
|
||||
else eeprom.word_address &= ~(1 << (16 - eeprom.cycles));
|
||||
}
|
||||
|
||||
eeprom.cycles ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ACK CYCLE */
|
||||
eeprom.cycles = 1;
|
||||
eeprom.state = GET_WORD_ADR_LOW;
|
||||
}
|
||||
}
|
||||
break;
|
||||
eeprom.cycles ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ACK CYCLE */
|
||||
eeprom.cycles = 1;
|
||||
eeprom.state = GET_WORD_ADR_LOW;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* Get Word Address LSB: 7bits (24C01) or 8bits (24C02-24C512)
|
||||
* MODE-2 and MODE-3 only (24C01 - 24C512)
|
||||
*/
|
||||
case GET_WORD_ADR_LOW:
|
||||
/* Get Word Address LSB: 7bits (24C01) or 8bits (24C02-24C512)
|
||||
* MODE-2 and MODE-3 only (24C01 - 24C512)
|
||||
*/
|
||||
case GET_WORD_ADR_LOW:
|
||||
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles < 9)
|
||||
{
|
||||
if ((eeprom.type.size_mask + 1) < (1 << (9 - eeprom.cycles)))
|
||||
{
|
||||
/* ignored bit (X24C01): slave mask should be right-shifted by one */
|
||||
eeprom.slave_mask >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this is a WORD ADDRESS high bit */
|
||||
if (eeprom.old_sda) eeprom.word_address |= (1 << (8 - eeprom.cycles));
|
||||
else eeprom.word_address &= ~(1 << (8 - eeprom.cycles));
|
||||
}
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles < 9)
|
||||
{
|
||||
if ((eeprom.type.size_mask + 1) < (1 << (9 - eeprom.cycles)))
|
||||
{
|
||||
/* ignored bit (X24C01): slave mask should be right-shifted by one */
|
||||
eeprom.slave_mask >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this is a WORD ADDRESS high bit */
|
||||
if (eeprom.old_sda) eeprom.word_address |= (1 << (8 - eeprom.cycles));
|
||||
else eeprom.word_address &= ~(1 << (8 - eeprom.cycles));
|
||||
}
|
||||
|
||||
eeprom.cycles ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ACK CYCLE */
|
||||
eeprom.cycles = 1;
|
||||
eeprom.word_address &= eeprom.type.size_mask;
|
||||
eeprom.state = WRITE_DATA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
eeprom.cycles ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ACK CYCLE */
|
||||
eeprom.cycles = 1;
|
||||
eeprom.word_address &= eeprom.type.size_mask;
|
||||
eeprom.state = WRITE_DATA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
* Read Cycle
|
||||
*/
|
||||
case READ_DATA:
|
||||
/*
|
||||
* Read Cycle
|
||||
*/
|
||||
case READ_DATA:
|
||||
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles < 9) eeprom.cycles ++;
|
||||
else
|
||||
{
|
||||
eeprom.cycles = 1;
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles < 9) eeprom.cycles ++;
|
||||
else
|
||||
{
|
||||
eeprom.cycles = 1;
|
||||
|
||||
/* ACK not received */
|
||||
if (eeprom.old_sda) eeprom.state = WAIT_STOP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* ACK not received */
|
||||
if (eeprom.old_sda) eeprom.state = WAIT_STOP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
* Write Cycle
|
||||
*/
|
||||
case WRITE_DATA:
|
||||
/*
|
||||
* Write Cycle
|
||||
*/
|
||||
case WRITE_DATA:
|
||||
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
Detect_START();
|
||||
Detect_STOP();
|
||||
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles < 9)
|
||||
{
|
||||
/* Write DATA bits (max 64kBytes) */
|
||||
uint16 sram_address = (eeprom.slave_mask | eeprom.word_address) & 0xFFFF;
|
||||
if (eeprom.old_sda) sram.sram[sram_address] |= (1 << (8 - eeprom.cycles));
|
||||
else sram.sram[sram_address] &= ~(1 << (8 - eeprom.cycles));
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl)
|
||||
{
|
||||
if (eeprom.cycles < 9)
|
||||
{
|
||||
/* Write DATA bits (max 64kBytes) */
|
||||
uint16 sram_address = (eeprom.slave_mask | eeprom.word_address) & 0xFFFF;
|
||||
if (eeprom.old_sda) sram.sram[sram_address] |= (1 << (8 - eeprom.cycles));
|
||||
else sram.sram[sram_address] &= ~(1 << (8 - eeprom.cycles));
|
||||
|
||||
if (eeprom.cycles == 8)
|
||||
{
|
||||
/* WORD ADDRESS is incremented (roll up at maximum pagesize) */
|
||||
eeprom.word_address = (eeprom.word_address & (0xFFFF - eeprom.type.pagewrite_mask)) |
|
||||
((eeprom.word_address + 1) & eeprom.type.pagewrite_mask);
|
||||
}
|
||||
if (eeprom.cycles == 8)
|
||||
{
|
||||
/* WORD ADDRESS is incremented (roll up at maximum pagesize) */
|
||||
eeprom.word_address = (eeprom.word_address & (0xFFFF - eeprom.type.pagewrite_mask)) |
|
||||
((eeprom.word_address + 1) & eeprom.type.pagewrite_mask);
|
||||
}
|
||||
|
||||
eeprom.cycles ++;
|
||||
}
|
||||
else eeprom.cycles = 1; /* ACK cycle */
|
||||
}
|
||||
break;
|
||||
}
|
||||
eeprom.cycles ++;
|
||||
}
|
||||
else eeprom.cycles = 1; /* ACK cycle */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
eeprom.old_scl = eeprom.scl;
|
||||
eeprom.old_sda = eeprom.sda;
|
||||
eeprom.old_scl = eeprom.scl;
|
||||
eeprom.old_sda = eeprom.sda;
|
||||
}
|
||||
|
||||
uint32 eeprom_read(uint32 address, uint32 word_access)
|
||||
{
|
||||
uint8 sda_out = eeprom.sda;
|
||||
uint8 sda_out = eeprom.sda;
|
||||
|
||||
/* EEPROM state */
|
||||
switch (eeprom.state)
|
||||
{
|
||||
case READ_DATA:
|
||||
if (eeprom.cycles < 9)
|
||||
{
|
||||
/* Return DATA bits (max 64kBytes) */
|
||||
uint16 sram_address = (eeprom.slave_mask | eeprom.word_address) & 0xffff;
|
||||
sda_out = (sram.sram[sram_address] >> (8 - eeprom.cycles)) & 1;
|
||||
/* EEPROM state */
|
||||
switch (eeprom.state)
|
||||
{
|
||||
case READ_DATA:
|
||||
if (eeprom.cycles < 9)
|
||||
{
|
||||
/* Return DATA bits (max 64kBytes) */
|
||||
uint16 sram_address = (eeprom.slave_mask | eeprom.word_address) & 0xffff;
|
||||
sda_out = (sram.sram[sram_address] >> (8 - eeprom.cycles)) & 1;
|
||||
|
||||
if (eeprom.cycles == 8)
|
||||
{
|
||||
/* WORD ADDRESS is incremented (roll up at maximum array size) */
|
||||
eeprom.word_address ++;
|
||||
eeprom.word_address &= eeprom.type.size_mask;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (eeprom.cycles == 8)
|
||||
{
|
||||
/* WORD ADDRESS is incremented (roll up at maximum array size) */
|
||||
eeprom.word_address ++;
|
||||
eeprom.word_address &= eeprom.type.size_mask;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_WORD_ADR_7BITS:
|
||||
case GET_SLAVE_ADR:
|
||||
case GET_WORD_ADR_HIGH:
|
||||
case GET_WORD_ADR_LOW:
|
||||
case WRITE_DATA:
|
||||
if (eeprom.cycles == 9) sda_out = 0;
|
||||
break;
|
||||
case GET_WORD_ADR_7BITS:
|
||||
case GET_SLAVE_ADR:
|
||||
case GET_WORD_ADR_HIGH:
|
||||
case GET_WORD_ADR_LOW:
|
||||
case WRITE_DATA:
|
||||
if (eeprom.cycles == 9) sda_out = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* memory access */
|
||||
if (word_access)
|
||||
|
@ -24,14 +24,14 @@
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STAND_BY = 0,
|
||||
WAIT_STOP,
|
||||
GET_SLAVE_ADR,
|
||||
GET_WORD_ADR_7BITS,
|
||||
GET_WORD_ADR_HIGH,
|
||||
GET_WORD_ADR_LOW,
|
||||
WRITE_DATA,
|
||||
READ_DATA,
|
||||
STAND_BY = 0,
|
||||
WAIT_STOP,
|
||||
GET_SLAVE_ADR,
|
||||
GET_WORD_ADR_7BITS,
|
||||
GET_WORD_ADR_HIGH,
|
||||
GET_WORD_ADR_LOW,
|
||||
WRITE_DATA,
|
||||
READ_DATA,
|
||||
|
||||
} T_EEPROM_STATE;
|
||||
|
||||
@ -53,31 +53,31 @@ typedef enum
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 address_bits; /* number of bits needed to address memory: 7, 8 or 16 */
|
||||
uint16 size_mask; /* depends on the max size of the memory (in bytes) */
|
||||
uint16 pagewrite_mask; /* depends on the maximal number of bytes that can be written in a single write cycle */
|
||||
uint32 sda_in_adr; /* 68000 memory address mapped to SDA_IN */
|
||||
uint32 sda_out_adr; /* 68000 memory address mapped to SDA_OUT */
|
||||
uint32 scl_adr; /* 68000 memory address mapped to SCL */
|
||||
uint8 sda_in_bit; /* bit offset for SDA_IN */
|
||||
uint8 sda_out_bit; /* bit offset for SDA_OUT */
|
||||
uint8 scl_bit; /* bit offset for SCL */
|
||||
uint8 address_bits; /* number of bits needed to address memory: 7, 8 or 16 */
|
||||
uint16 size_mask; /* depends on the max size of the memory (in bytes) */
|
||||
uint16 pagewrite_mask; /* depends on the maximal number of bytes that can be written in a single write cycle */
|
||||
uint32 sda_in_adr; /* 68000 memory address mapped to SDA_IN */
|
||||
uint32 sda_out_adr; /* 68000 memory address mapped to SDA_OUT */
|
||||
uint32 scl_adr; /* 68000 memory address mapped to SCL */
|
||||
uint8 sda_in_bit; /* bit offset for SDA_IN */
|
||||
uint8 sda_out_bit; /* bit offset for SDA_OUT */
|
||||
uint8 scl_bit; /* bit offset for SCL */
|
||||
|
||||
} T_EEPROM_TYPE;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 sda; /* current /SDA line state */
|
||||
uint8 scl; /* current /SCL line state */
|
||||
uint8 old_sda; /* previous /SDA line state */
|
||||
uint8 old_scl; /* previous /SCL line state */
|
||||
uint8 cycles; /* current operation cycle number (0-9) */
|
||||
uint8 rw; /* operation type (1:READ, 0:WRITE) */
|
||||
uint16 slave_mask; /* device address (shifted by the memory address width)*/
|
||||
uint16 word_address; /* memory address */
|
||||
T_EEPROM_STATE state; /* current operation state */
|
||||
T_EEPROM_TYPE type; /* EEPROM characteristics for this game */
|
||||
uint8 sda; /* current /SDA line state */
|
||||
uint8 scl; /* current /SCL line state */
|
||||
uint8 old_sda; /* previous /SDA line state */
|
||||
uint8 old_scl; /* previous /SCL line state */
|
||||
uint8 cycles; /* current operation cycle number (0-9) */
|
||||
uint8 rw; /* operation type (1:READ, 0:WRITE) */
|
||||
uint16 slave_mask; /* device address (shifted by the memory address width)*/
|
||||
uint16 word_address; /* memory address */
|
||||
T_EEPROM_STATE state; /* current operation state */
|
||||
T_EEPROM_TYPE type; /* EEPROM characteristics for this game */
|
||||
|
||||
} T_EEPROM;
|
||||
|
||||
|
@ -29,9 +29,9 @@ T_SRAM sram;
|
||||
*
|
||||
* The SRAM definition is held at offset 0x1b0 of the ROM header.
|
||||
*
|
||||
* 1B0h: dc.b 'RA', %1x1yz000, %00100000
|
||||
* 1B4h: dc.l RAM start address
|
||||
* 1B8h: dc.l RAM end address
|
||||
* 1B0h: dc.b 'RA', %1x1yz000, %00100000
|
||||
* 1B4h: dc.l RAM start address
|
||||
* 1B8h: dc.l RAM end address
|
||||
* x 1 for BACKUP and 0 If not BACKUP
|
||||
* yz 10 if even address only
|
||||
* 11 if odd address only
|
||||
@ -48,51 +48,51 @@ void sram_init()
|
||||
if ((cart_rom[0x1b0] == 0x52) && (cart_rom[0x1b1] == 0x41))
|
||||
{
|
||||
/* retrieve informations from headezr */
|
||||
sram.detected = 1;
|
||||
sram.detected = 1;
|
||||
sram.start = READ_WORD_LONG(cart_rom, 0x1b4);
|
||||
sram.end = READ_WORD_LONG(cart_rom, 0x1b8);
|
||||
|
||||
/* fixe some bad header informations */
|
||||
if ((sram.start > sram.end) || ((sram.end - sram.start) >= 0x10000))
|
||||
sram.end = sram.start + 0xffff;
|
||||
sram.start &= 0xfffffffe;
|
||||
/* fixe some bad header informations */
|
||||
if ((sram.start > sram.end) || ((sram.end - sram.start) >= 0x10000))
|
||||
sram.end = sram.start + 0xffff;
|
||||
sram.start &= 0xfffffffe;
|
||||
sram.end |= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* default SRAM region */
|
||||
sram.start = 0x200000;
|
||||
/* default SRAM region */
|
||||
sram.start = 0x200000;
|
||||
sram.end = 0x20ffff;
|
||||
}
|
||||
|
||||
/* set SRAM ON by default when ROM is not mapped */
|
||||
if (genromsize <= sram.start)
|
||||
{
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
}
|
||||
|
||||
/* Some games with bad header or specific configuration */
|
||||
if (strstr(rominfo.product,"T-113016") != NULL)
|
||||
{
|
||||
/* Pugsy (try accessing unmapped area for copy protection) */
|
||||
sram.on = 0;
|
||||
sram.write = 0;
|
||||
/* Pugsy (try accessing unmapped area for copy protection) */
|
||||
sram.on = 0;
|
||||
sram.write = 0;
|
||||
}
|
||||
else if ((strstr(rominfo.product,"T-26013") != NULL) && (rominfo.checksum == 0xa837))
|
||||
{
|
||||
/* Psy-O-Blade (bad header) */
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
sram.start = 0x200001;
|
||||
sram.end = 0x203fff;
|
||||
/* Psy-O-Blade (bad header) */
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
sram.start = 0x200001;
|
||||
sram.end = 0x203fff;
|
||||
}
|
||||
else if (((realchecksum == 0xaeaa) || (realchecksum == 0x8dba)) && (rominfo.checksum == 0x8104))
|
||||
{
|
||||
/* Xin Qigai Wangzi, aka Beggar Prince (no header, use uncommon area) */
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
sram.start = 0x400000;
|
||||
sram.end = 0x40ffff;
|
||||
/* Xin Qigai Wangzi, aka Beggar Prince (no header, use uncommon area) */
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
sram.start = 0x400000;
|
||||
sram.end = 0x40ffff;
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,14 @@
|
||||
vscroll: 1 (0); 209 (26) - alternates every 4 frames
|
||||
vram range for patterns: 0000-999f (low scr 0000-395f,72e0-999f; high 3980-999f)
|
||||
name table address: c000
|
||||
seen DMAs (in order): [300002-3026c3]->[0020-26e1] len 4961
|
||||
[3026c2-303943]->[26e0-3961] len 2369
|
||||
[303942-306003]->[72e0-99a1] len 4961
|
||||
---
|
||||
[306002-3086c3]->[3980-6041] len 4961
|
||||
[3086c2-309943]->[6040-72c1] len 2369
|
||||
[309942-30c003]->[72e0-99a2] len 4961
|
||||
seen DMAs (in order):
|
||||
[300002-3026c3]->[0020-26e1] len 4961
|
||||
[3026c2-303943]->[26e0-3961] len 2369
|
||||
[303942-306003]->[72e0-99a1] len 4961
|
||||
---
|
||||
[306002-3086c3]->[3980-6041] len 4961
|
||||
[3086c2-309943]->[6040-72c1] len 2369
|
||||
[309942-30c003]->[72e0-99a2] len 4961
|
||||
tile arrangement:
|
||||
|
||||
000: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,56 +23,56 @@
|
||||
|
||||
/* register names */
|
||||
enum {
|
||||
SSP_GR0, SSP_X, SSP_Y, SSP_A,
|
||||
SSP_ST, SSP_STACK, SSP_PC, SSP_P,
|
||||
SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST,
|
||||
SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL
|
||||
SSP_GR0, SSP_X, SSP_Y, SSP_A,
|
||||
SSP_ST, SSP_STACK, SSP_PC, SSP_P,
|
||||
SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST,
|
||||
SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
unsigned int v;
|
||||
struct {
|
||||
unsigned int v;
|
||||
struct {
|
||||
#ifdef LSB_FIRST
|
||||
unsigned short l;
|
||||
unsigned short h;
|
||||
unsigned short l;
|
||||
unsigned short h;
|
||||
#else
|
||||
unsigned short h;
|
||||
unsigned short l;
|
||||
unsigned short h;
|
||||
unsigned short l;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
} ssp_reg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union {
|
||||
unsigned short RAM[256*2]; // 2 internal RAM banks
|
||||
struct {
|
||||
unsigned short RAM0[256];
|
||||
unsigned short RAM1[256];
|
||||
};
|
||||
};
|
||||
ssp_reg_t gr[16]; // general registers
|
||||
union {
|
||||
unsigned char r[8]; // BANK pointers
|
||||
struct {
|
||||
unsigned char r0[4];
|
||||
unsigned char r1[4];
|
||||
};
|
||||
};
|
||||
unsigned short stack[6];
|
||||
unsigned int pmac_read[6]; // read modes/addrs for PM0-PM5
|
||||
unsigned int pmac_write[6]; // write ...
|
||||
//
|
||||
#define SSP_PMC_HAVE_ADDR 0x0001 // address written to PMAC, waiting for mode
|
||||
#define SSP_PMC_SET 0x0002 // PMAC is set
|
||||
#define SSP_HANG 0x1000 // 68000 hangs SVP
|
||||
#define SSP_WAIT_PM0 0x2000 // bit1 in PM0
|
||||
#define SSP_WAIT_30FE06 0x4000 // ssp tight loops on 30FE08 to become non-zero
|
||||
#define SSP_WAIT_30FE08 0x8000 // same for 30FE06
|
||||
#define SSP_WAIT_MASK 0xf000
|
||||
unsigned int emu_status;
|
||||
unsigned int pad[30];
|
||||
union {
|
||||
unsigned short RAM[256*2]; // 2 internal RAM banks
|
||||
struct {
|
||||
unsigned short RAM0[256];
|
||||
unsigned short RAM1[256];
|
||||
};
|
||||
};
|
||||
ssp_reg_t gr[16]; // general registers
|
||||
union {
|
||||
unsigned char r[8]; // BANK pointers
|
||||
struct {
|
||||
unsigned char r0[4];
|
||||
unsigned char r1[4];
|
||||
};
|
||||
};
|
||||
unsigned short stack[6];
|
||||
unsigned int pmac_read[6]; // read modes/addrs for PM0-PM5
|
||||
unsigned int pmac_write[6]; // write ...
|
||||
|
||||
#define SSP_PMC_HAVE_ADDR 0x0001 // address written to PMAC, waiting for mode
|
||||
#define SSP_PMC_SET 0x0002 // PMAC is set
|
||||
#define SSP_HANG 0x1000 // 68000 hangs SVP
|
||||
#define SSP_WAIT_PM0 0x2000 // bit1 in PM0
|
||||
#define SSP_WAIT_30FE06 0x4000 // ssp tight loops on 30FE08 to become non-zero
|
||||
#define SSP_WAIT_30FE08 0x8000 // same for 30FE06
|
||||
#define SSP_WAIT_MASK 0xf000
|
||||
unsigned int emu_status;
|
||||
unsigned int pad[30];
|
||||
} ssp1601_t;
|
||||
|
||||
|
||||
|
@ -15,14 +15,14 @@ uint16 SVP_cycles = 850;
|
||||
|
||||
void svp_init(void)
|
||||
{
|
||||
svp = (void *) ((char *)cart_rom + 0x200000);
|
||||
memset(svp, 0, sizeof(*svp));
|
||||
svp = (void *) ((char *)cart_rom + 0x200000);
|
||||
memset(svp, 0, sizeof(*svp));
|
||||
}
|
||||
|
||||
void svp_reset(void)
|
||||
{
|
||||
memcpy(svp->iram_rom + 0x800, cart_rom + 0x800, 0x20000 - 0x800);
|
||||
ssp1601_reset(&svp->ssp1601);
|
||||
memcpy(svp->iram_rom + 0x800, cart_rom + 0x800, 0x20000 - 0x800);
|
||||
ssp1601_reset(&svp->ssp1601);
|
||||
}
|
||||
|
||||
void svp_write_dram(uint32 address, uint32 data)
|
||||
|
@ -16,9 +16,9 @@
|
||||
#include "ssp16.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char iram_rom[0x20000]; // IRAM (0-0x7ff) and program ROM (0x800-0x1ffff)
|
||||
unsigned char dram[0x20000];
|
||||
ssp1601_t ssp1601;
|
||||
unsigned char iram_rom[0x20000]; // IRAM (0-0x7ff) and program ROM (0x800-0x1ffff)
|
||||
unsigned char dram[0x20000];
|
||||
ssp1601_t ssp1601;
|
||||
} svp_t;
|
||||
|
||||
extern svp_t *svp;
|
||||
|
@ -31,33 +31,33 @@ t_input input;
|
||||
*****************************************************************************/
|
||||
/* H counter values for a 256-pixel wide display (342 pixel max.) */
|
||||
uint8 hc_256[171] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93,
|
||||
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* H counter values for a 320-pixel wide display (442 pixels max.) */
|
||||
uint8 hc_320[210] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
|
||||
0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED,
|
||||
0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD,
|
||||
@ -77,7 +77,7 @@ static inline void lightgun_update(int num)
|
||||
/* HL enabled ? */
|
||||
if (io_reg[5] & 0x80)
|
||||
{
|
||||
/* External Interrupt ? */
|
||||
/* External Interrupt ? */
|
||||
if (reg[11] & 0x08) {irq_status &= 0xff; irq_status |= 0x12;}
|
||||
|
||||
/* HVC Latch:
|
||||
@ -86,11 +86,8 @@ static inline void lightgun_update(int num)
|
||||
H-Counter range is approx. 292 pixel clocks
|
||||
*/
|
||||
hc_latch = 0x100;
|
||||
if (reg[12] & 1)
|
||||
hc_latch |= hc_320[((input.analog[num][0] * 290) / (2 * 320) + input.x_offset) % 210];
|
||||
else
|
||||
hc_latch |= hc_256[(input.analog[num][0] / 2 + input.x_offset)%171];
|
||||
|
||||
if (reg[12] & 1) hc_latch |= hc_320[((input.analog[num][0] * 290) / (2 * 320) + input.x_offset) % 210];
|
||||
else hc_latch |= hc_256[(input.analog[num][0] / 2 + input.x_offset)%171];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,59 +69,59 @@
|
||||
/* CPU types for use in m68k_set_cpu_type() */
|
||||
enum
|
||||
{
|
||||
M68K_CPU_TYPE_INVALID,
|
||||
M68K_CPU_TYPE_68000,
|
||||
M68K_CPU_TYPE_68008,
|
||||
M68K_CPU_TYPE_68010,
|
||||
M68K_CPU_TYPE_68EC020,
|
||||
M68K_CPU_TYPE_68020,
|
||||
M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */
|
||||
M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */
|
||||
M68K_CPU_TYPE_INVALID,
|
||||
M68K_CPU_TYPE_68000,
|
||||
M68K_CPU_TYPE_68008,
|
||||
M68K_CPU_TYPE_68010,
|
||||
M68K_CPU_TYPE_68EC020,
|
||||
M68K_CPU_TYPE_68020,
|
||||
M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */
|
||||
M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */
|
||||
};
|
||||
|
||||
/* Registers used by m68k_get_reg() and m68k_set_reg() */
|
||||
typedef enum
|
||||
{
|
||||
/* Real registers */
|
||||
M68K_REG_D0, /* Data registers */
|
||||
M68K_REG_D1,
|
||||
M68K_REG_D2,
|
||||
M68K_REG_D3,
|
||||
M68K_REG_D4,
|
||||
M68K_REG_D5,
|
||||
M68K_REG_D6,
|
||||
M68K_REG_D7,
|
||||
M68K_REG_A0, /* Address registers */
|
||||
M68K_REG_A1,
|
||||
M68K_REG_A2,
|
||||
M68K_REG_A3,
|
||||
M68K_REG_A4,
|
||||
M68K_REG_A5,
|
||||
M68K_REG_A6,
|
||||
M68K_REG_A7,
|
||||
M68K_REG_PC, /* Program Counter */
|
||||
M68K_REG_SR, /* Status Register */
|
||||
M68K_REG_SP, /* The current Stack Pointer (located in A7) */
|
||||
M68K_REG_USP, /* User Stack Pointer */
|
||||
M68K_REG_ISP, /* Interrupt Stack Pointer */
|
||||
M68K_REG_MSP, /* Master Stack Pointer */
|
||||
M68K_REG_SFC, /* Source Function Code */
|
||||
M68K_REG_DFC, /* Destination Function Code */
|
||||
M68K_REG_VBR, /* Vector Base Register */
|
||||
M68K_REG_CACR, /* Cache Control Register */
|
||||
M68K_REG_CAAR, /* Cache Address Register */
|
||||
/* Real registers */
|
||||
M68K_REG_D0, /* Data registers */
|
||||
M68K_REG_D1,
|
||||
M68K_REG_D2,
|
||||
M68K_REG_D3,
|
||||
M68K_REG_D4,
|
||||
M68K_REG_D5,
|
||||
M68K_REG_D6,
|
||||
M68K_REG_D7,
|
||||
M68K_REG_A0, /* Address registers */
|
||||
M68K_REG_A1,
|
||||
M68K_REG_A2,
|
||||
M68K_REG_A3,
|
||||
M68K_REG_A4,
|
||||
M68K_REG_A5,
|
||||
M68K_REG_A6,
|
||||
M68K_REG_A7,
|
||||
M68K_REG_PC, /* Program Counter */
|
||||
M68K_REG_SR, /* Status Register */
|
||||
M68K_REG_SP, /* The current Stack Pointer (located in A7) */
|
||||
M68K_REG_USP, /* User Stack Pointer */
|
||||
M68K_REG_ISP, /* Interrupt Stack Pointer */
|
||||
M68K_REG_MSP, /* Master Stack Pointer */
|
||||
M68K_REG_SFC, /* Source Function Code */
|
||||
M68K_REG_DFC, /* Destination Function Code */
|
||||
M68K_REG_VBR, /* Vector Base Register */
|
||||
M68K_REG_CACR, /* Cache Control Register */
|
||||
M68K_REG_CAAR, /* Cache Address Register */
|
||||
|
||||
/* Assumed registers */
|
||||
/* These are cheat registers which emulate the 1-longword prefetch
|
||||
/* Assumed registers */
|
||||
/* These are cheat registers which emulate the 1-longword prefetch
|
||||
* present in the 68000 and 68010.
|
||||
*/
|
||||
M68K_REG_PREF_ADDR, /* Last prefetch address */
|
||||
M68K_REG_PREF_DATA, /* Last prefetch data */
|
||||
M68K_REG_PREF_ADDR, /* Last prefetch address */
|
||||
M68K_REG_PREF_DATA, /* Last prefetch data */
|
||||
|
||||
/* Convenience registers */
|
||||
M68K_REG_PPC, /* Previous value in the program counter */
|
||||
M68K_REG_IR, /* Instruction register */
|
||||
M68K_REG_CPU_TYPE /* Type of CPU being run */
|
||||
/* Convenience registers */
|
||||
M68K_REG_PPC, /* Previous value in the program counter */
|
||||
M68K_REG_IR, /* Instruction register */
|
||||
M68K_REG_CPU_TYPE /* Type of CPU being run */
|
||||
} m68k_register_t;
|
||||
|
||||
/* ======================================================================== */
|
||||
@ -180,7 +180,7 @@ _m68k_memory_map m68k_memory_map[256];
|
||||
|
||||
/* Read data immediately following the PC */
|
||||
#define m68k_read_immediate_16(address) *(uint16 *)(m68k_memory_map[((address)>>16)&0xff].base + ((address) & 0xffff))
|
||||
#define m68k_read_immediate_32(address) (m68k_read_immediate_16(address) << 16) | (m68k_read_immediate_16(address+2))
|
||||
#define m68k_read_immediate_32(address) (m68k_read_immediate_16(address) << 16) | (m68k_read_immediate_16(address+2))
|
||||
|
||||
/* Read data relative to the PC */
|
||||
#define m68k_read_pcrelative_8(address) READ_BYTE(m68k_memory_map[((address)>>16)&0xff].base, (address) & 0xffff)
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
45976
source/m68k/m68kops.c
45976
source/m68k/m68kops.c
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,27 @@
|
||||
/****************************************************************************
|
||||
* config.c
|
||||
*
|
||||
* Genesis Plus GX configuration file support
|
||||
*
|
||||
* code by Eke-Eke (2008)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
|
||||
#include <fat.h>
|
||||
#include <sys/dir.h>
|
||||
|
||||
#ifdef HW_RVL
|
||||
|
@ -1,3 +1,25 @@
|
||||
/****************************************************************************
|
||||
* config.c
|
||||
*
|
||||
* Genesis Plus GX configuration file support
|
||||
*
|
||||
* code by Eke-Eke (2008)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
@ -1,19 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Nintendo Gamecube DVD Reading Library
|
||||
*
|
||||
* Low-Level DVD access
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _DVD_H_
|
||||
#define _DVD_H_
|
||||
|
||||
extern u32 dvd_read (void *dst, u32 len, u64 offset);
|
||||
extern void dvd_motor_off ();
|
||||
|
||||
#ifndef HW_RVL
|
||||
extern void uselessinquiry ();
|
||||
extern void dvd_drive_detect();
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,9 +1,26 @@
|
||||
/****************************************************************************
|
||||
* Nintendo Gamecube DVD Reading Library
|
||||
/*
|
||||
* dvd.c
|
||||
*
|
||||
* Low-level DVD access
|
||||
*
|
||||
* Low-Level DVD access
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
***************************************************************************/
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
#ifdef HW_RVL
|
36
source/ngc/fileio/dvd.h
Normal file
36
source/ngc/fileio/dvd.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* dvd.c
|
||||
*
|
||||
* Low-level DVD access
|
||||
*
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
|
||||
#ifndef _DVD_H_
|
||||
#define _DVD_H_
|
||||
|
||||
extern u32 dvd_read (void *dst, u32 len, u64 offset);
|
||||
extern void dvd_motor_off ();
|
||||
|
||||
#ifndef HW_RVL
|
||||
extern void uselessinquiry ();
|
||||
extern void dvd_drive_detect();
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,14 +1,31 @@
|
||||
/****************************************************************************
|
||||
/*
|
||||
* file_dvd.c
|
||||
*
|
||||
* generic ISO9660/Joliet DVD loading support
|
||||
*
|
||||
* DVD ISO9660/Joliet loading support
|
||||
* code by Eke-Eke (2008)
|
||||
*
|
||||
***************************************************************************/
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "fileio_dvd.h"
|
||||
#include "filesel.h"
|
||||
#include "fileio.h"
|
||||
#include "dvd.h"
|
||||
#include "unzip.h"
|
||||
#include "filesel.h"
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include "di/di.h"
|
||||
@ -269,7 +286,7 @@ int DVD_ParseDirectory ()
|
||||
* This functions return the actual size of data copied into the buffer
|
||||
*
|
||||
****************************************************************************/
|
||||
int DVD_LoadFile (unsigned char *buffer)
|
||||
int DVD_LoadFile (u8 *buffer)
|
||||
{
|
||||
/* file size */
|
||||
int length = filelist[selection].length;
|
||||
@ -284,6 +301,9 @@ int DVD_LoadFile (unsigned char *buffer)
|
||||
/* determine file type */
|
||||
if (!IsZipFile ((char *) readbuffer))
|
||||
{
|
||||
char msg[50];
|
||||
sprintf(msg,"Loading %d bytes...", length);
|
||||
ShowAction(msg);
|
||||
/* How many 2k blocks to read */
|
||||
int blocks = length / 2048;
|
||||
int readoffset = 0;
|
||||
@ -310,7 +330,7 @@ int DVD_LoadFile (unsigned char *buffer)
|
||||
}
|
||||
else
|
||||
{
|
||||
return UnZipDVD (buffer, discoffset, length);
|
||||
return UnZipBuffer (buffer, discoffset, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,7 +343,7 @@ int DVD_LoadFile (unsigned char *buffer)
|
||||
* Function to load a DVD directory and display to user.
|
||||
****************************************************************************/
|
||||
|
||||
int DVD_Open ()
|
||||
int DVD_Open (u8 *buffer)
|
||||
{
|
||||
/* reset flags */
|
||||
useFAT = 0;
|
||||
@ -385,7 +405,7 @@ int DVD_Open ()
|
||||
selection = 0;
|
||||
old_offset = 0;
|
||||
old_selection = 0;
|
||||
return FileSelector ();
|
||||
return FileSelector (buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -395,5 +415,5 @@ int DVD_Open ()
|
||||
}
|
||||
}
|
||||
|
||||
return FileSelector ();
|
||||
return FileSelector (buffer);
|
||||
}
|
32
source/ngc/fileio/file_dvd.h
Normal file
32
source/ngc/fileio/file_dvd.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* file_dvd.c
|
||||
*
|
||||
* generic ISO9660/Joliet DVD loading support
|
||||
*
|
||||
* code by Eke-Eke (2008)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef _FILE_DVD_H
|
||||
#define _FILE_DVD_H
|
||||
|
||||
extern int DVD_UpdateDir(int go_up);
|
||||
extern int DVD_ParseDirectory();
|
||||
extern int DVD_LoadFile(u8 *buffer);
|
||||
extern int DVD_Open (u8 *buffer);
|
||||
|
||||
#endif
|
@ -1,16 +1,35 @@
|
||||
/****************************************************************************
|
||||
* FAT loading support
|
||||
/*
|
||||
* file_fat.c
|
||||
*
|
||||
* generic FAT loading support
|
||||
*
|
||||
***************************************************************************/
|
||||
* code by Eke-Eke (2008)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "fileio_fat.h"
|
||||
#include "filesel.h"
|
||||
#include "fileio.h"
|
||||
#include "history.h"
|
||||
#include "unzip.h"
|
||||
#include "filesel.h"
|
||||
#include "file_fat.h"
|
||||
|
||||
/* current FAT directory */
|
||||
static char fatdir[256];
|
||||
static char fatdir[MAXPATHLEN];
|
||||
|
||||
/* current FAT device */
|
||||
static int fat_type = 0;
|
||||
@ -149,7 +168,7 @@ int FAT_ParseDirectory()
|
||||
* This functions return the actual size of data copied into the buffer
|
||||
*
|
||||
****************************************************************************/
|
||||
int FAT_LoadFile (unsigned char *buffer)
|
||||
int FAT_LoadFile (u8 *buffer)
|
||||
{
|
||||
/* If loading from history then we need to setup a few more things. */
|
||||
if(useHistory)
|
||||
@ -203,6 +222,9 @@ int FAT_LoadFile (unsigned char *buffer)
|
||||
sdfile = fopen(fname, "rb");
|
||||
if (sdfile)
|
||||
{
|
||||
char msg[50];
|
||||
sprintf(msg,"Loading %d bytes...", length);
|
||||
ShowAction(msg);
|
||||
fread(buffer, 1, length, sdfile);
|
||||
fclose(sdfile);
|
||||
return length;
|
||||
@ -211,7 +233,7 @@ int FAT_LoadFile (unsigned char *buffer)
|
||||
else
|
||||
{
|
||||
/* unzip file */
|
||||
return UnZipFAT(buffer, fname);
|
||||
return UnZipBuffer (buffer, 0, fname);
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,7 +245,7 @@ int FAT_LoadFile (unsigned char *buffer)
|
||||
*
|
||||
* Function to load a FAT directory and display to user.
|
||||
****************************************************************************/
|
||||
int FAT_Open(int type)
|
||||
int FAT_Open(int type, u8 *buffer)
|
||||
{
|
||||
int max = 0;
|
||||
char root[10] = "";
|
||||
@ -299,7 +321,7 @@ int FAT_Open(int type)
|
||||
selection = 0;
|
||||
old_offset = 0;
|
||||
old_selection = 0;
|
||||
return FileSelector ();
|
||||
return FileSelector (buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -309,5 +331,5 @@ int FAT_Open(int type)
|
||||
}
|
||||
}
|
||||
|
||||
return FileSelector ();
|
||||
return FileSelector (buffer);
|
||||
}
|
39
source/ngc/fileio/file_fat.h
Normal file
39
source/ngc/fileio/file_fat.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* file_fat.c
|
||||
*
|
||||
* generic FAT loading support
|
||||
*
|
||||
* code by Eke-Eke (2008)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef _FILE_FAT_H
|
||||
#define _FILE_FAT_H
|
||||
|
||||
#define TYPE_RECENT 0
|
||||
#define TYPE_SD 1
|
||||
|
||||
#ifdef HW_RVL
|
||||
#define TYPE_USB 2
|
||||
#endif
|
||||
|
||||
extern int FAT_UpdateDir(int go_up);
|
||||
extern int FAT_ParseDirectory(void);
|
||||
extern int FAT_LoadFile(u8* buffer);
|
||||
extern int FAT_Open (int type, u8 *buffer);
|
||||
|
||||
#endif
|
@ -1,19 +1,30 @@
|
||||
/****************************************************************************
|
||||
* ROM Selection Interface
|
||||
/*
|
||||
* filesel.c
|
||||
*
|
||||
* File Selection menu
|
||||
*
|
||||
* The following features are implemented:
|
||||
* . SDCARD access with LFN support (through softdev's VFAT library)
|
||||
* . DVD access
|
||||
* . easy subdirectory browsing
|
||||
* . ROM browser
|
||||
* . alphabetical file sorting (Marty Disibio)
|
||||
* . load from history list (Marty Disibio)
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
***************************************************************************/
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "fileio_dvd.h"
|
||||
#include "fileio_fat.h"
|
||||
#include "file_dvd.h"
|
||||
#include "file_fat.h"
|
||||
#include "filesel.h"
|
||||
|
||||
/* Global Variables */
|
||||
@ -27,6 +38,7 @@ int useHistory = 0;
|
||||
int haveDVDdir = 0;
|
||||
int haveFATdir = 0;
|
||||
|
||||
FILEENTRIES filelist[MAXFILES];
|
||||
|
||||
/***************************************************************************
|
||||
* ShowFiles
|
||||
@ -46,8 +58,8 @@ static void ShowFiles (int offset, int selection)
|
||||
memset(text,0,MAXJOLIET+2);
|
||||
if (filelist[i].flags) sprintf(text, "[%s]", filelist[i].filename + filelist[i].filename_offset);
|
||||
else sprintf (text, "%s", filelist[i].filename + filelist[i].filename_offset);
|
||||
if (j == (selection - offset)) WriteCentre_HL ((j * fheight) + 120, text);
|
||||
else WriteCentre ((j * fheight) + 120, text);
|
||||
if (j == (selection - offset)) WriteCentre_HL ((j * fheight) + PAGEOFFSET, text);
|
||||
else WriteCentre ((j * fheight) + PAGEOFFSET, text);
|
||||
j++;
|
||||
}
|
||||
SetScreen ();
|
||||
@ -57,8 +69,11 @@ static void ShowFiles (int offset, int selection)
|
||||
* FileSelector
|
||||
*
|
||||
* Let user select a file from the File listing
|
||||
.* ROM file buffer is provided as input
|
||||
* ROM size is returned
|
||||
*
|
||||
****************************************************************************/
|
||||
int FileSelector()
|
||||
int FileSelector(unsigned char *buffer)
|
||||
{
|
||||
short p;
|
||||
int redraw = 1;
|
||||
@ -168,10 +183,15 @@ int FileSelector()
|
||||
if (filelist[selection].flags)
|
||||
{
|
||||
/* get new directory */
|
||||
ret = useFAT ? FAT_UpdateDir(go_up) : DVD_UpdateDir(go_up);
|
||||
if (useFAT) ret =FAT_UpdateDir(go_up);
|
||||
else ret = DVD_UpdateDir(go_up);
|
||||
|
||||
/* get new entry list or quit */
|
||||
if (ret) maxfiles = useFAT ? FAT_ParseDirectory() : DVD_ParseDirectory();
|
||||
if (ret)
|
||||
{
|
||||
if (useFAT) maxfiles = FAT_ParseDirectory();
|
||||
else maxfiles = DVD_ParseDirectory();
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
@ -179,16 +199,8 @@ int FileSelector()
|
||||
else
|
||||
{
|
||||
/* Load file */
|
||||
genromsize = useFAT ? FAT_LoadFile(cart_rom) : DVD_LoadFile(cart_rom);
|
||||
if (genromsize)
|
||||
{
|
||||
memfile_autosave();
|
||||
reloadrom();
|
||||
memfile_autoload();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (useFAT) return FAT_LoadFile(buffer);
|
||||
else return DVD_LoadFile(buffer);
|
||||
}
|
||||
redraw = 1;
|
||||
}
|
59
source/ngc/fileio/filesel.h
Normal file
59
source/ngc/fileio/filesel.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* filesel.c
|
||||
*
|
||||
* File Selection menu
|
||||
*
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef _FILESEL_H
|
||||
#define _FILESEL_H
|
||||
|
||||
#define MAXJOLIET 256
|
||||
#define MAXFILES 1000
|
||||
|
||||
/* this is emulator specific ! */
|
||||
#define PAGESIZE 12
|
||||
#define PAGEOFFSET 120
|
||||
|
||||
|
||||
/* Filelist structure */
|
||||
typedef struct
|
||||
{
|
||||
u64 offset;
|
||||
unsigned int length;
|
||||
char flags;
|
||||
char filename[MAXJOLIET];
|
||||
u16 filename_offset;
|
||||
}FILEENTRIES;
|
||||
|
||||
|
||||
/* Global Variables */
|
||||
extern FILEENTRIES filelist[MAXFILES];
|
||||
extern int maxfiles;
|
||||
extern int offset;
|
||||
extern int selection;
|
||||
extern int old_selection;
|
||||
extern int old_offset;
|
||||
extern int useFAT;
|
||||
extern int haveDVDdir;
|
||||
extern int haveFATdir;
|
||||
|
||||
extern int FileSelector(unsigned char *buffer);
|
||||
|
||||
#endif
|
@ -1,11 +1,25 @@
|
||||
/*
|
||||
* history.c
|
||||
* genplusgx-mdisibio
|
||||
*
|
||||
* Created by Martin Disibio on 6/17/08.
|
||||
* Copyright 2008 __MyCompanyName__. All rights reserved.
|
||||
* Generic ROM history list managment
|
||||
*
|
||||
*/
|
||||
* code by Martin Disibio (6/17/08)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "history.h"
|
51
source/ngc/fileio/history.h
Normal file
51
source/ngc/fileio/history.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* history.c
|
||||
*
|
||||
* Generic ROM history list managment
|
||||
*
|
||||
* code by Martin Disibio (6/17/08)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef _HISTORY_H
|
||||
#define _HISTORY_H
|
||||
|
||||
#include "filesel.h"
|
||||
|
||||
#define NUM_HISTORY_ENTRIES (10)
|
||||
|
||||
/****************************************************************************
|
||||
* ROM Play History
|
||||
*
|
||||
****************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
char filepath[MAXJOLIET];
|
||||
char filename[MAXJOLIET];
|
||||
} t_history_entry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
t_history_entry entries[NUM_HISTORY_ENTRIES];
|
||||
} t_history;
|
||||
|
||||
extern t_history history;
|
||||
extern void history_add_file(char *filepath, char *filename);
|
||||
extern void history_load();
|
||||
extern void set_history_defaults();
|
||||
|
||||
#endif
|
@ -1,16 +1,33 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Nintendo Gamecube Zip Support
|
||||
* unzip.c
|
||||
*
|
||||
* Only partial support is included, in that only the first file within the archive
|
||||
* is considered to be a ROM image.
|
||||
***************************************************************************/
|
||||
* Zip Support
|
||||
*
|
||||
* Only partial support is included, in that only the first file within the archive
|
||||
* is considered to be a ROM image.
|
||||
*
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "dvd.h"
|
||||
#include "font.h"
|
||||
#include "unzip.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
/*
|
||||
* PKWare Zip Header - adopted into zip standard
|
||||
@ -72,12 +89,12 @@ int IsZipFile (char *buffer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
/*****************************************************************************
|
||||
* UnZipBuffer
|
||||
*
|
||||
* It should be noted that there is a limit of 5MB total size for any ROM
|
||||
******************************************************************************/
|
||||
int UnZipDVD (unsigned char *outbuffer, u64 discoffset, int length)
|
||||
int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, char *filename)
|
||||
{
|
||||
PKZIPHEADER pkzip;
|
||||
int zipoffset = 0;
|
||||
@ -89,9 +106,25 @@ int UnZipDVD (unsigned char *outbuffer, u64 discoffset, int length)
|
||||
int have = 0;
|
||||
char readbuffer[2048];
|
||||
char msg[128];
|
||||
FILE *fatfile = NULL;
|
||||
|
||||
/*** FAT file support ***/
|
||||
if (filename)
|
||||
{
|
||||
fatfile = fopen(filename, "rb");
|
||||
if (fatfile == NULL) return 0;
|
||||
}
|
||||
|
||||
/*** Read Zip Header ***/
|
||||
dvd_read (&readbuffer, 2048, discoffset);
|
||||
if (fatfile)
|
||||
{
|
||||
fseek(fatfile, 0, SEEK_SET);
|
||||
fread(readbuffer, 1, 2048, fatfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
dvd_read (&readbuffer, 2048, discoffset);
|
||||
}
|
||||
|
||||
/*** Copy PKZip header to local, used as info ***/
|
||||
memcpy (&pkzip, &readbuffer, sizeof (PKZIPHEADER));
|
||||
@ -125,7 +158,7 @@ int UnZipDVD (unsigned char *outbuffer, u64 discoffset, int length)
|
||||
{
|
||||
zs.avail_out = ZIPCHUNK;
|
||||
zs.next_out = (Bytef *) & out;
|
||||
res = inflate (&zs, Z_NO_FLUSH);
|
||||
res = inflate (&zs, Z_NO_FLUSH);
|
||||
|
||||
if (res == Z_MEM_ERROR)
|
||||
{
|
||||
@ -147,13 +180,23 @@ int UnZipDVD (unsigned char *outbuffer, u64 discoffset, int length)
|
||||
zipoffset = 0;
|
||||
zipchunk = ZIPCHUNK;
|
||||
|
||||
discoffset += 2048;
|
||||
dvd_read (&readbuffer, 2048, discoffset);
|
||||
if (fatfile)
|
||||
{
|
||||
fread(readbuffer, 1, 2048, fatfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
discoffset += 2048;
|
||||
dvd_read (&readbuffer, 2048, discoffset);
|
||||
}
|
||||
}
|
||||
while (res != Z_STREAM_END);
|
||||
|
||||
inflateEnd (&zs);
|
||||
|
||||
/* close file */
|
||||
if (fatfile) fclose(fatfile);
|
||||
|
||||
if (res == Z_STREAM_END)
|
||||
{
|
||||
if (FLIP32 (pkzip.uncompressedSize) == (u32) bufferoffset) return bufferoffset;
|
||||
@ -163,72 +206,5 @@ int UnZipDVD (unsigned char *outbuffer, u64 discoffset, int length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UnZipFAT (unsigned char *outbuffer, char *filename)
|
||||
{
|
||||
unzFile *fd = NULL;
|
||||
unz_file_info info;
|
||||
int ret = 0;
|
||||
int size;
|
||||
char msg[128];
|
||||
|
||||
/* Attempt to open the archive */
|
||||
fd = unzOpen(filename);
|
||||
if(!fd) return (0);
|
||||
|
||||
/* Go to first file in archive */
|
||||
ret = unzGoToFirstFile(fd);
|
||||
if(ret != UNZ_OK)
|
||||
{
|
||||
unzClose(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
ret = unzGetCurrentFileInfo(fd, &info, NULL, 0, NULL, 0, NULL, 0);
|
||||
if(ret != UNZ_OK)
|
||||
{
|
||||
unzClose(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Open the file for reading */
|
||||
ret = unzOpenCurrentFile(fd);
|
||||
if(ret != UNZ_OK)
|
||||
{
|
||||
unzClose(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Allocate file data buffer */
|
||||
size = info.uncompressed_size;
|
||||
|
||||
sprintf (msg, "Unzipping %d bytes ... Wait", size);
|
||||
ShowAction (msg);
|
||||
|
||||
/* Read (decompress) the file */
|
||||
ret = unzReadCurrentFile(fd, outbuffer, info.uncompressed_size);
|
||||
if(ret != info.uncompressed_size)
|
||||
{
|
||||
unzCloseCurrentFile(fd);
|
||||
unzClose(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Close the current file */
|
||||
ret = unzCloseCurrentFile(fd);
|
||||
if(ret != UNZ_OK)
|
||||
{
|
||||
unzClose(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Close the archive */
|
||||
ret = unzClose(fd);
|
||||
if(ret != UNZ_OK)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Update file size and return pointer to file data */
|
||||
return (size);
|
||||
}
|
||||
|
@ -5,11 +5,10 @@
|
||||
* Only partial support is included, in that only the first file within the archive
|
||||
* is considered to be a ROM image.
|
||||
***************************************************************************/
|
||||
#ifndef _FILEIO_H_
|
||||
#define _FILEIO_H_
|
||||
#ifndef _UNZIP_H_
|
||||
#define _UNZIP_H_
|
||||
|
||||
extern int IsZipFile (char *buffer);
|
||||
int UnZipDVD (unsigned char *outbuffer, u64 discoffset, int length);
|
||||
int UnZipFAT (unsigned char *outbuffer, char *filename);
|
||||
int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, char *filename);
|
||||
|
||||
#endif
|
@ -1,14 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* DVD ISO9660/Joliet loading support
|
||||
*
|
||||
***************************************************************************/
|
||||
#ifndef _FILEIO_DVD_H
|
||||
#define _FILEIO_DVD_H
|
||||
|
||||
extern int DVD_UpdateDir(int go_up);
|
||||
extern int DVD_ParseDirectory();
|
||||
extern int DVD_LoadFile(unsigned char* buffer);
|
||||
extern int DVD_Open ();
|
||||
|
||||
#endif
|
@ -1,21 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* FAT loading support
|
||||
*
|
||||
***************************************************************************/
|
||||
#ifndef _FILEIO_FAT_H
|
||||
#define _FILEIO_FAT_H
|
||||
|
||||
#define TYPE_RECENT 0
|
||||
#define TYPE_SD 1
|
||||
|
||||
#ifdef HW_RVL
|
||||
#define TYPE_USB 2
|
||||
#endif
|
||||
|
||||
extern int FAT_UpdateDir(int go_up);
|
||||
extern int FAT_ParseDirectory(void);
|
||||
extern int FAT_LoadFile(unsigned char* buffer);
|
||||
extern int FAT_Open (int device);
|
||||
|
||||
#endif
|
@ -1,8 +1,26 @@
|
||||
/***************************************************************************
|
||||
* SDCARD/MEMCARD File support
|
||||
/*
|
||||
* filemem.c
|
||||
*
|
||||
* FAT and Memory Card SRAM/Savestate files managment
|
||||
*
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "saveicon.h"
|
||||
@ -11,7 +29,6 @@
|
||||
#include "dvd.h"
|
||||
#endif
|
||||
|
||||
#include <fat.h>
|
||||
#include <sys/dir.h>
|
||||
|
||||
/* Support for MemCards */
|
@ -1,11 +1,27 @@
|
||||
/**
|
||||
* Nintendo GameCube ARAM Wrapper for libOGC aram.c
|
||||
/****************************************************************************
|
||||
* gcaram.c
|
||||
*
|
||||
* This is an often overlooked area of ~16Mb extra RAM
|
||||
* It's use in Genesis Plus is to shadow the ROM.
|
||||
* Actually, only SSF2TNC needs shadowing, but it's always
|
||||
* Good to know :)
|
||||
*/
|
||||
* ARAM wrapper for libogc
|
||||
*
|
||||
* code by Softdev (2006)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
#define ARAMSTART 0x8000
|
||||
|
@ -1,11 +1,25 @@
|
||||
/**
|
||||
* Nintendo GameCube ARAM Wrapper for libOGC aram.c
|
||||
/****************************************************************************
|
||||
* gcaram.c
|
||||
*
|
||||
* This is an often overlooked area of ~16Mb extra RAM
|
||||
* It's use in Genesis Plus is to shadow the ROM.
|
||||
* Actually, only SSF2TNC needs shadowing, but it's always
|
||||
* Good to know :)
|
||||
*/
|
||||
* ARAM wrapper for libogc
|
||||
*
|
||||
* code by Softdev (2006)
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _ARAM_H
|
||||
#define _ARAM_H
|
||||
|
@ -1,35 +0,0 @@
|
||||
/****************************************************************************
|
||||
* ROM Selection Interface
|
||||
*
|
||||
***************************************************************************/
|
||||
#ifndef _FILESEL_H
|
||||
#define _FILESEL_H
|
||||
|
||||
#define MAXJOLIET 256
|
||||
#define MAXFILES 1000
|
||||
#define PAGESIZE 12
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u64 offset;
|
||||
unsigned int length;
|
||||
char flags;
|
||||
char filename[MAXJOLIET];
|
||||
u16 filename_offset;
|
||||
}FILEENTRIES;
|
||||
|
||||
FILEENTRIES filelist[MAXFILES];
|
||||
|
||||
/* Global Variables */
|
||||
extern int maxfiles;
|
||||
extern int offset;
|
||||
extern int selection;
|
||||
extern int old_selection;
|
||||
extern int old_offset;
|
||||
extern int useFAT;
|
||||
extern int haveDVDdir;
|
||||
extern int haveFATdir;
|
||||
|
||||
extern int FileSelector();
|
||||
|
||||
#endif
|
@ -1,9 +1,27 @@
|
||||
/*****************************************************************************
|
||||
* IPL FONT Engine
|
||||
* font.c
|
||||
*
|
||||
* Based on Qoob MP3 Player Font
|
||||
* Added IPL font extraction
|
||||
*****************************************************************************/
|
||||
* IPL FONT Engine, based on Qoob MP3 Player Font
|
||||
*
|
||||
* code by Softdev (2006), Eke-Eke(2007-2008)
|
||||
*
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "gpback.h"
|
||||
|
||||
|
@ -1,9 +1,27 @@
|
||||
/*****************************************************************************
|
||||
* IPL FONT Engine
|
||||
* font.c
|
||||
*
|
||||
* Based on Qoob MP3 Player Font
|
||||
* Added IPL font extraction
|
||||
*****************************************************************************/
|
||||
* IPL FONT Engine, based on Qoob MP3 Player Font
|
||||
*
|
||||
* code by Softdev (2006), Eke-Eke(2007-2008)
|
||||
*
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef _FONT_H
|
||||
#define _FONT_H
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* ggentry.c
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
* Genesis Plus GX Game Genie
|
||||
*
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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
|
||||
@ -17,7 +19,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Nintendo Gamecube Game Genie Entry
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
|
@ -1,7 +1,9 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* legal.c
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
* generic legal informations screen
|
||||
*
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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
|
||||
@ -16,8 +18,10 @@
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "dkpro.h"
|
||||
|
@ -1,7 +1,9 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* menu.c
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
* Genesis Plus GX menu
|
||||
*
|
||||
* code by Softdev (March 2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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
|
||||
@ -17,15 +19,13 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Nintendo Gamecube Menus
|
||||
* Please put any user menus here! - softdev March 12 2006
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "dvd.h"
|
||||
#include "font.h"
|
||||
#include "fileio_dvd.h"
|
||||
#include "fileio_fat.h"
|
||||
#include "file_dvd.h"
|
||||
#include "file_fat.h"
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include <wiiuse/wpad.h>
|
||||
@ -896,10 +896,9 @@ static u8 dvd_on = 0;
|
||||
int loadmenu ()
|
||||
{
|
||||
int prevmenu = menu;
|
||||
int ret;
|
||||
int ret,count,size;
|
||||
int quit = 0;
|
||||
#ifdef HW_RVL
|
||||
int count = 4 + dvd_on;
|
||||
char item[5][25] = {
|
||||
{"Load Recent"},
|
||||
{"Load from SD"},
|
||||
@ -908,7 +907,6 @@ int loadmenu ()
|
||||
{"Stop DVD Motor"}
|
||||
};
|
||||
#else
|
||||
int count = 3 + dvd_on;
|
||||
char item[4][25] = {
|
||||
{"Load Recent"},
|
||||
{"Load from SD"},
|
||||
@ -921,6 +919,11 @@ int loadmenu ()
|
||||
|
||||
while (quit == 0)
|
||||
{
|
||||
#ifdef HW_RVL
|
||||
count = 4 + dvd_on;
|
||||
#else
|
||||
count = 3 + dvd_on;
|
||||
#endif
|
||||
strcpy (menutitle, "Press B to return");
|
||||
ret = domenu (&item[0], count, 0);
|
||||
switch (ret)
|
||||
@ -937,9 +940,14 @@ int loadmenu ()
|
||||
case 2:
|
||||
#endif
|
||||
load_menu = menu;
|
||||
if (DVD_Open())
|
||||
size = DVD_Open(cart_rom);
|
||||
if (size)
|
||||
{
|
||||
dvd_on = 1;
|
||||
genromsize = size;
|
||||
memfile_autosave();
|
||||
reloadrom();
|
||||
memfile_autoload();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
@ -952,18 +960,21 @@ int loadmenu ()
|
||||
#endif
|
||||
dvd_motor_off();
|
||||
dvd_on = 0;
|
||||
#ifdef HW_RVL
|
||||
count = 4 + dvd_on;
|
||||
#else
|
||||
count = 3 + dvd_on;
|
||||
#endif
|
||||
menu = load_menu;
|
||||
break;
|
||||
|
||||
/*** Load from FAT device ***/
|
||||
default:
|
||||
load_menu = menu;
|
||||
if (FAT_Open(ret)) return 1;
|
||||
size = FAT_Open(ret,cart_rom);
|
||||
if (size)
|
||||
{
|
||||
genromsize = size;
|
||||
memfile_autosave();
|
||||
reloadrom();
|
||||
memfile_autoload();
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* history.h
|
||||
* genplusgx-mdisibio
|
||||
*
|
||||
* Created by Martin Disibio on 6/17/08.
|
||||
*
|
||||
*/
|
||||
#ifndef _HISTORY_H
|
||||
#define _HISTORY_H
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "filesel.h"
|
||||
|
||||
#define NUM_HISTORY_ENTRIES (10)
|
||||
|
||||
/****************************************************************************
|
||||
* ROM Play History
|
||||
*
|
||||
****************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
char filepath[MAXJOLIET];
|
||||
char filename[MAXJOLIET];
|
||||
} t_history_entry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
t_history_entry entries[NUM_HISTORY_ENTRIES];
|
||||
} t_history;
|
||||
|
||||
extern t_history history;
|
||||
extern void history_add_file(char *filepath, char *filename);
|
||||
extern void history_load();
|
||||
extern void set_history_defaults();
|
||||
|
||||
#endif
|
20
source/ngc/libogc_license.txt
Normal file
20
source/ngc/libogc_license.txt
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (C) 2004 - 2008
|
||||
Michael Wiedenbauer (shagkur)
|
||||
Dave Murphy (WinterMute)
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any
|
||||
purpose, including commercial applications, and to alter it and
|
||||
redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you use
|
||||
this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and
|
||||
must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
@ -1,7 +1,9 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* ngc.c
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
* Genesis Plus GX main
|
||||
*
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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
|
||||
@ -16,7 +18,9 @@
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "gcaram.h"
|
||||
#include "font.h"
|
||||
@ -54,7 +58,7 @@ static void load_bios()
|
||||
config.bios_enabled &= ~2;
|
||||
|
||||
/* open file */
|
||||
sprintf (pathname, "%s/BIOS.bin", DEFAULT_PATH);
|
||||
sprintf (pathname, "%s/BIOS.bin",DEFAULT_PATH);
|
||||
FILE *fp = fopen(pathname, "rb");
|
||||
if (fp == NULL) return;
|
||||
|
||||
|
@ -1,26 +1,27 @@
|
||||
/******************************************************************************
|
||||
/****************************************************************************
|
||||
* ogc_video.c
|
||||
*
|
||||
* Genesis Plus - Sega Megadrive / Genesis Emulator
|
||||
* Genesis Plus GX audio support
|
||||
*
|
||||
* NGC/Wii Audio support
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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 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.
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "ogc_input.h"
|
||||
|
||||
/* global datas */
|
||||
unsigned char soundbuffer[16][3840] ATTRIBUTE_ALIGN(32);
|
||||
|
@ -1,23 +1,26 @@
|
||||
/******************************************************************************
|
||||
/****************************************************************************
|
||||
* ogc_video.c
|
||||
*
|
||||
* SMS Plus - Sega Master System / GameGear Emulator
|
||||
* Genesis Plus GX audio support
|
||||
*
|
||||
* NGC/Wii Audio support
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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 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.
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _GC_AUDIO_H_
|
||||
#define _GC_AUDIO_H_
|
||||
|
||||
|
@ -1,22 +1,24 @@
|
||||
/******************************************************************************
|
||||
/****************************************************************************
|
||||
* ogc_input.c
|
||||
*
|
||||
* SMS Plus GX - Sega Master System / GameGear Emulator
|
||||
* Genesis Plus GX input support
|
||||
*
|
||||
* SMS Plus - Sega Master System / GameGear Emulator
|
||||
* code by Eke-Eke (2008)
|
||||
*
|
||||
* 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 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.
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
|
@ -1,23 +1,27 @@
|
||||
/******************************************************************************
|
||||
/****************************************************************************
|
||||
* ogc_input.c
|
||||
*
|
||||
* SMS Plus - Sega Master System / GameGear Emulator
|
||||
* Genesis Plus GX input support
|
||||
*
|
||||
* NGC/Wii Controller support
|
||||
* code by Eke-Eke (2008)
|
||||
*
|
||||
* 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 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.
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef _GC_INPUT_H_
|
||||
#define _GC_INPUT_H_
|
||||
|
||||
|
@ -1,24 +1,27 @@
|
||||
/******************************************************************************
|
||||
/****************************************************************************
|
||||
* ogc_video.c
|
||||
*
|
||||
* Genesis Plus - Sega Megadrive / Genesis Emulator
|
||||
* Genesis Plus GX video support
|
||||
*
|
||||
* NGC/Wii Video support
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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 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.
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "gcaram.h"
|
||||
|
@ -1,23 +1,26 @@
|
||||
/******************************************************************************
|
||||
/****************************************************************************
|
||||
* ogc_video.c
|
||||
*
|
||||
* SMS Plus - Sega Master System / GameGear Emulator
|
||||
* Genesis Plus GX video support
|
||||
*
|
||||
* NGC/Wii Video support
|
||||
* code by Softdev (2006), Eke-Eke (2007,2008)
|
||||
*
|
||||
* 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 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.
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _GC_VIDEO_H_
|
||||
#define _GC_VIDEO_H_
|
||||
|
||||
|
@ -16,12 +16,11 @@
|
||||
#include "ogc_audio.h"
|
||||
#include "ogc_video.h"
|
||||
#include "config.h"
|
||||
#include "history.h"
|
||||
|
||||
#define DEFAULT_PATH "/genplus"
|
||||
|
||||
#define update_input() ogc_input__update()
|
||||
|
||||
#define DEFAULT_PATH "/genplus"
|
||||
|
||||
/* globals */
|
||||
extern u32 diff_usec(long long start,long long end);
|
||||
extern long long gettime();
|
||||
@ -35,9 +34,6 @@ extern void MainMenu();
|
||||
extern void set_region();
|
||||
extern int ManageSRAM(u8 direction, u8 device);
|
||||
extern int ManageState(u8 direction, u8 device);
|
||||
extern int OpenDVD();
|
||||
extern int OpenFAT(char *name);
|
||||
extern int OpenHistory();
|
||||
extern void memfile_autosave();
|
||||
extern void memfile_autoload();
|
||||
|
||||
|
@ -38,65 +38,65 @@ md_ntsc_setup_t const md_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1, 0,
|
||||
|
||||
/* 2 input pixels -> 4 composite samples */
|
||||
pixel_info_t const md_ntsc_pixels [alignment_count] = {
|
||||
{ PIXEL_OFFSET( -4, -9 ), { 0.1f, 0.9f, 0.9f, 0.1f } },
|
||||
{ PIXEL_OFFSET( -2, -7 ), { 0.1f, 0.9f, 0.9f, 0.1f } },
|
||||
{ PIXEL_OFFSET( -4, -9 ), { 0.1f, 0.9f, 0.9f, 0.1f } },
|
||||
{ PIXEL_OFFSET( -2, -7 ), { 0.1f, 0.9f, 0.9f, 0.1f } },
|
||||
};
|
||||
|
||||
static void correct_errors( md_ntsc_rgb_t color, md_ntsc_rgb_t* out )
|
||||
{
|
||||
unsigned i;
|
||||
for ( i = 0; i < rgb_kernel_size / 4; i++ )
|
||||
{
|
||||
md_ntsc_rgb_t error = color -
|
||||
out [i ] - out [i + 2 +16] - out [i + 4 ] - out [i + 6 +16] -
|
||||
out [i + 8] - out [(i+10)%16+16] - out [(i+12)%16] - out [(i+14)%16+16];
|
||||
CORRECT_ERROR( i + 6 + 16 );
|
||||
/*DISTRIBUTE_ERROR( 2+16, 4, 6+16 );*/
|
||||
}
|
||||
unsigned i;
|
||||
for ( i = 0; i < rgb_kernel_size / 4; i++ )
|
||||
{
|
||||
md_ntsc_rgb_t error = color -
|
||||
out [i ] - out [i + 2 +16] - out [i + 4 ] - out [i + 6 +16] -
|
||||
out [i + 8] - out [(i+10)%16+16] - out [(i+12)%16] - out [(i+14)%16+16];
|
||||
CORRECT_ERROR( i + 6 + 16 );
|
||||
/*DISTRIBUTE_ERROR( 2+16, 4, 6+16 );*/
|
||||
}
|
||||
}
|
||||
|
||||
void md_ntsc_init( md_ntsc_t* ntsc, md_ntsc_setup_t const* setup )
|
||||
{
|
||||
int entry;
|
||||
init_t impl;
|
||||
if ( !setup )
|
||||
setup = &md_ntsc_composite;
|
||||
init( &impl, setup );
|
||||
int entry;
|
||||
init_t impl;
|
||||
if ( !setup )
|
||||
setup = &md_ntsc_composite;
|
||||
init( &impl, setup );
|
||||
|
||||
for ( entry = 0; entry < md_ntsc_palette_size; entry++ )
|
||||
{
|
||||
float bb = impl.to_float [entry >> 6 & 7];
|
||||
float gg = impl.to_float [entry >> 3 & 7];
|
||||
float rr = impl.to_float [entry & 7];
|
||||
for ( entry = 0; entry < md_ntsc_palette_size; entry++ )
|
||||
{
|
||||
float bb = impl.to_float [entry >> 6 & 7];
|
||||
float gg = impl.to_float [entry >> 3 & 7];
|
||||
float rr = impl.to_float [entry & 7];
|
||||
|
||||
float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i );
|
||||
float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i );
|
||||
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g );
|
||||
md_ntsc_rgb_t rgb = PACK_RGB( r, g, b );
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g );
|
||||
md_ntsc_rgb_t rgb = PACK_RGB( r, g, b );
|
||||
|
||||
if ( setup->palette_out )
|
||||
RGB_PALETTE_OUT( rgb, &setup->palette_out [entry * 3] );
|
||||
if ( setup->palette_out )
|
||||
RGB_PALETTE_OUT( rgb, &setup->palette_out [entry * 3] );
|
||||
|
||||
if ( ntsc )
|
||||
{
|
||||
gen_kernel( &impl, y, i, q, ntsc->table [entry] );
|
||||
correct_errors( rgb, ntsc->table [entry] );
|
||||
}
|
||||
}
|
||||
if ( ntsc )
|
||||
{
|
||||
gen_kernel( &impl, y, i, q, ntsc->table [entry] );
|
||||
correct_errors( rgb, ntsc->table [entry] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MD_NTSC_NO_BLITTERS
|
||||
/* modified blitters to work on a line basis with genesis plus renderer*/
|
||||
void md_ntsc_blit( md_ntsc_t const* ntsc, MD_NTSC_IN_T const* table, unsigned char* input,
|
||||
int in_width, int vline)
|
||||
int in_width, int vline)
|
||||
{
|
||||
int const chunk_count = in_width / md_ntsc_in_chunk - 1;
|
||||
int const chunk_count = in_width / md_ntsc_in_chunk - 1;
|
||||
MD_NTSC_IN_T border = table[0];
|
||||
|
||||
MD_NTSC_BEGIN_ROW( ntsc, border,
|
||||
MD_NTSC_ADJ_IN( table[*input++] ),
|
||||
MD_NTSC_ADJ_IN( table[*input++] ),
|
||||
MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_BEGIN_ROW( ntsc, border,
|
||||
MD_NTSC_ADJ_IN( table[*input++] ),
|
||||
MD_NTSC_ADJ_IN( table[*input++] ),
|
||||
MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
|
||||
#ifdef NGC
|
||||
/* directly fill the RGB565 texture */
|
||||
@ -112,52 +112,52 @@ void md_ntsc_blit( md_ntsc_t const* ntsc, MD_NTSC_IN_T const* table, unsigned ch
|
||||
int n;
|
||||
|
||||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* order of input and output pixels must not be altered */
|
||||
MD_NTSC_COLOR_IN( 0, ntsc, MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_RGB_OUT( 0, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 1, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
{
|
||||
/* order of input and output pixels must not be altered */
|
||||
MD_NTSC_COLOR_IN( 0, ntsc, MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_RGB_OUT( 0, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 1, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
|
||||
MD_NTSC_COLOR_IN( 1, ntsc, MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_RGB_OUT( 2, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 3, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_COLOR_IN( 1, ntsc, MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_RGB_OUT( 2, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 3, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
|
||||
#ifdef NGC
|
||||
line_out += 12;
|
||||
#endif
|
||||
|
||||
MD_NTSC_COLOR_IN( 2, ntsc, MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_RGB_OUT( 4, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 5, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_COLOR_IN( 2, ntsc, MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_RGB_OUT( 4, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 5, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
|
||||
MD_NTSC_COLOR_IN( 3, ntsc, MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_RGB_OUT( 6, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 7, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_COLOR_IN( 3, ntsc, MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_RGB_OUT( 6, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 7, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
|
||||
#ifdef NGC
|
||||
line_out += 12;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* finish final pixels */
|
||||
MD_NTSC_COLOR_IN( 0, ntsc, MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_RGB_OUT( 0, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 1, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
/* finish final pixels */
|
||||
MD_NTSC_COLOR_IN( 0, ntsc, MD_NTSC_ADJ_IN( table[*input++] ) );
|
||||
MD_NTSC_RGB_OUT( 0, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 1, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
|
||||
MD_NTSC_COLOR_IN( 1, ntsc, border );
|
||||
MD_NTSC_RGB_OUT( 2, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 3, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 2, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 3, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
|
||||
#ifdef NGC
|
||||
line_out += 12;
|
||||
#endif
|
||||
|
||||
MD_NTSC_COLOR_IN( 2, ntsc, border );
|
||||
MD_NTSC_RGB_OUT( 4, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 5, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 4, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 5, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
|
||||
MD_NTSC_COLOR_IN( 3, ntsc, border );
|
||||
MD_NTSC_RGB_OUT( 6, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 7, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_COLOR_IN( 3, ntsc, border );
|
||||
MD_NTSC_RGB_OUT( 6, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
MD_NTSC_RGB_OUT( 7, *line_out++, MD_NTSC_OUT_DEPTH );
|
||||
}
|
||||
#endif
|
||||
|
@ -7,29 +7,29 @@
|
||||
#include "md_ntsc_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown
|
||||
in parenthesis and should remain fairly stable in future versions. */
|
||||
typedef struct md_ntsc_setup_t
|
||||
{
|
||||
/* Basic parameters */
|
||||
double hue; /* -1 = -180 degrees +1 = +180 degrees */
|
||||
double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */
|
||||
double contrast; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double brightness; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double sharpness; /* edge contrast enhancement/blurring */
|
||||
/* Basic parameters */
|
||||
double hue; /* -1 = -180 degrees +1 = +180 degrees */
|
||||
double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */
|
||||
double contrast; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double brightness; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double sharpness; /* edge contrast enhancement/blurring */
|
||||
|
||||
/* Advanced parameters */
|
||||
double gamma; /* -1 = dark (1.5) +1 = light (0.5) */
|
||||
double resolution; /* image resolution */
|
||||
double artifacts; /* artifacts caused by color changes */
|
||||
double fringing; /* color artifacts caused by brightness changes */
|
||||
double bleed; /* color bleed (color resolution reduction) */
|
||||
float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */
|
||||
/* Advanced parameters */
|
||||
double gamma; /* -1 = dark (1.5) +1 = light (0.5) */
|
||||
double resolution; /* image resolution */
|
||||
double artifacts; /* artifacts caused by color changes */
|
||||
double fringing; /* color artifacts caused by brightness changes */
|
||||
double bleed; /* color bleed (color resolution reduction) */
|
||||
float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */
|
||||
|
||||
unsigned char* palette_out; /* optional RGB palette out, 3 bytes per color */
|
||||
unsigned char* palette_out; /* optional RGB palette out, 3 bytes per color */
|
||||
} md_ntsc_setup_t;
|
||||
|
||||
/* Video format presets */
|
||||
@ -50,17 +50,17 @@ and output RGB depth is set by MD_NTSC_OUT_DEPTH. Both default to 16-bit RGB.
|
||||
In_row_width is the number of pixels to get to the next input row. Out_pitch
|
||||
is the number of *bytes* to get to the next output row. */
|
||||
void md_ntsc_blit( md_ntsc_t const* ntsc, MD_NTSC_IN_T const* table, unsigned char* input,
|
||||
int in_width, int vline);
|
||||
int in_width, int vline);
|
||||
|
||||
/* Number of output pixels written by blitter for given input width. */
|
||||
#define MD_NTSC_OUT_WIDTH( in_width ) \
|
||||
(((in_width) - 3) / md_ntsc_in_chunk * md_ntsc_out_chunk + md_ntsc_out_chunk)
|
||||
(((in_width) - 3) / md_ntsc_in_chunk * md_ntsc_out_chunk + md_ntsc_out_chunk)
|
||||
|
||||
/* Number of input pixels that will fit within given output width. Might be
|
||||
rounded down slightly; use MD_NTSC_OUT_WIDTH() on result to find rounded
|
||||
value. */
|
||||
#define MD_NTSC_IN_WIDTH( out_width ) \
|
||||
((out_width) / md_ntsc_out_chunk * md_ntsc_in_chunk - md_ntsc_in_chunk + 3)
|
||||
((out_width) / md_ntsc_out_chunk * md_ntsc_in_chunk - md_ntsc_in_chunk + 3)
|
||||
|
||||
|
||||
/* Interface for user-defined custom blitters */
|
||||
@ -73,22 +73,22 @@ enum { md_ntsc_black = 0 }; /* palette index for black */
|
||||
Use md_ntsc_black for unused pixels. Declares variables, so must be before first
|
||||
statement in a block (unless you're using C++). */
|
||||
#define MD_NTSC_BEGIN_ROW( ntsc, pixel0, pixel1, pixel2, pixel3 ) \
|
||||
unsigned const md_pixel0_ = (pixel0);\
|
||||
md_ntsc_rgb_t const* kernel0 = MD_NTSC_IN_FORMAT( ntsc, md_pixel0_ );\
|
||||
unsigned const md_pixel1_ = (pixel1);\
|
||||
md_ntsc_rgb_t const* kernel1 = MD_NTSC_IN_FORMAT( ntsc, md_pixel1_ );\
|
||||
unsigned const md_pixel2_ = (pixel2);\
|
||||
md_ntsc_rgb_t const* kernel2 = MD_NTSC_IN_FORMAT( ntsc, md_pixel2_ );\
|
||||
unsigned const md_pixel3_ = (pixel3);\
|
||||
md_ntsc_rgb_t const* kernel3 = MD_NTSC_IN_FORMAT( ntsc, md_pixel3_ );\
|
||||
md_ntsc_rgb_t const* kernelx0;\
|
||||
md_ntsc_rgb_t const* kernelx1 = kernel0;\
|
||||
md_ntsc_rgb_t const* kernelx2 = kernel0;\
|
||||
md_ntsc_rgb_t const* kernelx3 = kernel0
|
||||
unsigned const md_pixel0_ = (pixel0);\
|
||||
md_ntsc_rgb_t const* kernel0 = MD_NTSC_IN_FORMAT( ntsc, md_pixel0_ );\
|
||||
unsigned const md_pixel1_ = (pixel1);\
|
||||
md_ntsc_rgb_t const* kernel1 = MD_NTSC_IN_FORMAT( ntsc, md_pixel1_ );\
|
||||
unsigned const md_pixel2_ = (pixel2);\
|
||||
md_ntsc_rgb_t const* kernel2 = MD_NTSC_IN_FORMAT( ntsc, md_pixel2_ );\
|
||||
unsigned const md_pixel3_ = (pixel3);\
|
||||
md_ntsc_rgb_t const* kernel3 = MD_NTSC_IN_FORMAT( ntsc, md_pixel3_ );\
|
||||
md_ntsc_rgb_t const* kernelx0;\
|
||||
md_ntsc_rgb_t const* kernelx1 = kernel0;\
|
||||
md_ntsc_rgb_t const* kernelx2 = kernel0;\
|
||||
md_ntsc_rgb_t const* kernelx3 = kernel0
|
||||
|
||||
/* Begin input pixel */
|
||||
#define MD_NTSC_COLOR_IN( index, ntsc, color ) \
|
||||
MD_NTSC_COLOR_IN_( index, color, MD_NTSC_IN_FORMAT, ntsc )
|
||||
MD_NTSC_COLOR_IN_( index, color, MD_NTSC_IN_FORMAT, ntsc )
|
||||
|
||||
/* Generate output pixel. Bits can be 24, 16, 15, 32 (treated as 24), or 0:
|
||||
24: RRRRRRRR GGGGGGGG BBBBBBBB
|
||||
@ -96,11 +96,11 @@ statement in a block (unless you're using C++). */
|
||||
15: RRRRRGG GGGBBBBB
|
||||
0: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format; x = junk bits) */
|
||||
#define MD_NTSC_RGB_OUT( x, rgb_out, bits ) {\
|
||||
md_ntsc_rgb_t raw_ =\
|
||||
kernel0 [x+ 0] + kernel1 [(x+6)%8+16] + kernel2 [(x+4)%8 ] + kernel3 [(x+2)%8+16] +\
|
||||
kernelx0 [x+ 8] + kernelx1 [(x+6)%8+24] + kernelx2 [(x+4)%8+8] + kernelx3 [(x+2)%8+24];\
|
||||
MD_NTSC_CLAMP_( raw_, 0 );\
|
||||
MD_NTSC_RGB_OUT_( rgb_out, bits, 0 );\
|
||||
md_ntsc_rgb_t raw_ =\
|
||||
kernel0 [x+ 0] + kernel1 [(x+6)%8+16] + kernel2 [(x+4)%8 ] + kernel3 [(x+2)%8+16] +\
|
||||
kernelx0 [x+ 8] + kernelx1 [(x+6)%8+24] + kernelx2 [(x+4)%8+8] + kernelx3 [(x+2)%8+24];\
|
||||
MD_NTSC_CLAMP_( raw_, 0 );\
|
||||
MD_NTSC_RGB_OUT_( rgb_out, bits, 0 );\
|
||||
}
|
||||
|
||||
|
||||
@ -108,41 +108,41 @@ statement in a block (unless you're using C++). */
|
||||
enum { md_ntsc_entry_size = 2 * 16 };
|
||||
typedef unsigned long md_ntsc_rgb_t;
|
||||
struct md_ntsc_t {
|
||||
md_ntsc_rgb_t table [md_ntsc_palette_size] [md_ntsc_entry_size];
|
||||
md_ntsc_rgb_t table [md_ntsc_palette_size] [md_ntsc_entry_size];
|
||||
};
|
||||
|
||||
#define MD_NTSC_BGR9( ntsc, n ) (ntsc)->table [n & 0x1FF]
|
||||
|
||||
#define MD_NTSC_RGB16( ntsc, n ) \
|
||||
(md_ntsc_rgb_t*) ((char*) (ntsc)->table +\
|
||||
((n << 9 & 0x3800) | (n & 0x0700) | (n >> 8 & 0x00E0)) *\
|
||||
(md_ntsc_entry_size * sizeof (md_ntsc_rgb_t) / 32))
|
||||
(md_ntsc_rgb_t*) ((char*) (ntsc)->table +\
|
||||
((n << 9 & 0x3800) | (n & 0x0700) | (n >> 8 & 0x00E0)) *\
|
||||
(md_ntsc_entry_size * sizeof (md_ntsc_rgb_t) / 32))
|
||||
|
||||
/* common ntsc macros */
|
||||
#define md_ntsc_rgb_builder ((1L << 21) | (1 << 11) | (1 << 1))
|
||||
#define md_ntsc_clamp_mask (md_ntsc_rgb_builder * 3 / 2)
|
||||
#define md_ntsc_clamp_add (md_ntsc_rgb_builder * 0x101)
|
||||
#define MD_NTSC_CLAMP_( io, shift ) {\
|
||||
md_ntsc_rgb_t sub = (io) >> (9-(shift)) & md_ntsc_clamp_mask;\
|
||||
md_ntsc_rgb_t clamp = md_ntsc_clamp_add - sub;\
|
||||
io |= clamp;\
|
||||
clamp -= sub;\
|
||||
io &= clamp;\
|
||||
md_ntsc_rgb_t sub = (io) >> (9-(shift)) & md_ntsc_clamp_mask;\
|
||||
md_ntsc_rgb_t clamp = md_ntsc_clamp_add - sub;\
|
||||
io |= clamp;\
|
||||
clamp -= sub;\
|
||||
io &= clamp;\
|
||||
}
|
||||
|
||||
#define MD_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\
|
||||
unsigned color_;\
|
||||
kernelx##index = kernel##index;\
|
||||
kernel##index = (color_ = (color), ENTRY( table, color_ ));\
|
||||
unsigned color_;\
|
||||
kernelx##index = kernel##index;\
|
||||
kernel##index = (color_ = (color), ENTRY( table, color_ ));\
|
||||
}
|
||||
|
||||
/* x is always zero except in snes_ntsc library */
|
||||
#define MD_NTSC_RGB_OUT_( rgb_out, bits, x ) {\
|
||||
rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\
|
||||
rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -22,22 +22,22 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
#define PI 3.14159265358979323846f
|
||||
|
||||
#ifndef LUMA_CUTOFF
|
||||
#define LUMA_CUTOFF 0.20
|
||||
#define LUMA_CUTOFF 0.20
|
||||
#endif
|
||||
#ifndef gamma_size
|
||||
#define gamma_size 1
|
||||
#define gamma_size 1
|
||||
#endif
|
||||
#ifndef rgb_bits
|
||||
#define rgb_bits 8
|
||||
#define rgb_bits 8
|
||||
#endif
|
||||
#ifndef artifacts_max
|
||||
#define artifacts_max (artifacts_mid * 1.5f)
|
||||
#define artifacts_max (artifacts_mid * 1.5f)
|
||||
#endif
|
||||
#ifndef fringing_max
|
||||
#define fringing_max (fringing_mid * 2)
|
||||
#define fringing_max (fringing_mid * 2)
|
||||
#endif
|
||||
#ifndef STD_HUE_CONDITION
|
||||
#define STD_HUE_CONDITION( setup ) 1
|
||||
#define STD_HUE_CONDITION( setup ) 1
|
||||
#endif
|
||||
|
||||
#define ext_decoder_hue (std_decoder_hue + 15)
|
||||
@ -50,236 +50,236 @@ enum { kernel_size = kernel_half * 2 + 1 };
|
||||
|
||||
typedef struct init_t
|
||||
{
|
||||
float to_rgb [burst_count * 6];
|
||||
float to_float [gamma_size];
|
||||
float contrast;
|
||||
float brightness;
|
||||
float artifacts;
|
||||
float fringing;
|
||||
float kernel [rescale_out * kernel_size * 2];
|
||||
float to_rgb [burst_count * 6];
|
||||
float to_float [gamma_size];
|
||||
float contrast;
|
||||
float brightness;
|
||||
float artifacts;
|
||||
float fringing;
|
||||
float kernel [rescale_out * kernel_size * 2];
|
||||
} init_t;
|
||||
|
||||
#define ROTATE_IQ( i, q, sin_b, cos_b ) {\
|
||||
float t;\
|
||||
t = i * cos_b - q * sin_b;\
|
||||
q = i * sin_b + q * cos_b;\
|
||||
i = t;\
|
||||
float t;\
|
||||
t = i * cos_b - q * sin_b;\
|
||||
q = i * sin_b + q * cos_b;\
|
||||
i = t;\
|
||||
}
|
||||
|
||||
static void init_filters( init_t* impl, md_ntsc_setup_t const* setup )
|
||||
{
|
||||
#if rescale_out > 1
|
||||
float kernels [kernel_size * 2];
|
||||
float kernels [kernel_size * 2];
|
||||
#else
|
||||
float* const kernels = impl->kernel;
|
||||
float* const kernels = impl->kernel;
|
||||
#endif
|
||||
|
||||
/* generate luma (y) filter using sinc kernel */
|
||||
{
|
||||
/* sinc with rolloff (dsf) */
|
||||
float const rolloff = 1 + (float) setup->sharpness * (float) 0.032;
|
||||
float const maxh = 32;
|
||||
float const pow_a_n = (float) pow( rolloff, maxh );
|
||||
float sum;
|
||||
int i;
|
||||
/* quadratic mapping to reduce negative (blurring) range */
|
||||
float to_angle = (float) setup->resolution + 1;
|
||||
to_angle = PI / maxh * (float) LUMA_CUTOFF * (to_angle * to_angle + 1);
|
||||
/* generate luma (y) filter using sinc kernel */
|
||||
{
|
||||
/* sinc with rolloff (dsf) */
|
||||
float const rolloff = 1 + (float) setup->sharpness * (float) 0.032;
|
||||
float const maxh = 32;
|
||||
float const pow_a_n = (float) pow( rolloff, maxh );
|
||||
float sum;
|
||||
int i;
|
||||
/* quadratic mapping to reduce negative (blurring) range */
|
||||
float to_angle = (float) setup->resolution + 1;
|
||||
to_angle = PI / maxh * (float) LUMA_CUTOFF * (to_angle * to_angle + 1);
|
||||
|
||||
kernels [kernel_size * 3 / 2] = maxh; /* default center value */
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
int x = i - kernel_half;
|
||||
float angle = x * to_angle;
|
||||
/* instability occurs at center point with rolloff very close to 1.0 */
|
||||
if ( x || pow_a_n > (float) 1.056 || pow_a_n < (float) 0.981 )
|
||||
{
|
||||
float rolloff_cos_a = rolloff * (float) cos( angle );
|
||||
float num = 1 - rolloff_cos_a -
|
||||
pow_a_n * (float) cos( maxh * angle ) +
|
||||
pow_a_n * rolloff * (float) cos( (maxh - 1) * angle );
|
||||
float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
|
||||
float dsf = num / den;
|
||||
kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - (float) 0.5;
|
||||
}
|
||||
}
|
||||
kernels [kernel_size * 3 / 2] = maxh; /* default center value */
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
int x = i - kernel_half;
|
||||
float angle = x * to_angle;
|
||||
/* instability occurs at center point with rolloff very close to 1.0 */
|
||||
if ( x || pow_a_n > (float) 1.056 || pow_a_n < (float) 0.981 )
|
||||
{
|
||||
float rolloff_cos_a = rolloff * (float) cos( angle );
|
||||
float num = 1 - rolloff_cos_a -
|
||||
pow_a_n * (float) cos( maxh * angle ) +
|
||||
pow_a_n * rolloff * (float) cos( (maxh - 1) * angle );
|
||||
float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
|
||||
float dsf = num / den;
|
||||
kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - (float) 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
/* apply blackman window and find sum */
|
||||
sum = 0;
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
float x = PI * 2 / (kernel_half * 2) * i;
|
||||
float blackman = 0.42f - 0.5f * (float) cos( x ) + 0.08f * (float) cos( x * 2 );
|
||||
sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman);
|
||||
}
|
||||
/* apply blackman window and find sum */
|
||||
sum = 0;
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
float x = PI * 2 / (kernel_half * 2) * i;
|
||||
float blackman = 0.42f - 0.5f * (float) cos( x ) + 0.08f * (float) cos( x * 2 );
|
||||
sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman);
|
||||
}
|
||||
|
||||
/* normalize kernel */
|
||||
sum = 1.0f / sum;
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
int x = kernel_size * 3 / 2 - kernel_half + i;
|
||||
kernels [x] *= sum;
|
||||
assert( kernels [x] == kernels [x] ); /* catch numerical instability */
|
||||
}
|
||||
}
|
||||
/* normalize kernel */
|
||||
sum = 1.0f / sum;
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
int x = kernel_size * 3 / 2 - kernel_half + i;
|
||||
kernels [x] *= sum;
|
||||
assert( kernels [x] == kernels [x] ); /* catch numerical instability */
|
||||
}
|
||||
}
|
||||
|
||||
/* generate chroma (iq) filter using gaussian kernel */
|
||||
{
|
||||
float const cutoff_factor = -0.03125f;
|
||||
float cutoff = (float) setup->bleed;
|
||||
int i;
|
||||
/* generate chroma (iq) filter using gaussian kernel */
|
||||
{
|
||||
float const cutoff_factor = -0.03125f;
|
||||
float cutoff = (float) setup->bleed;
|
||||
int i;
|
||||
|
||||
if ( cutoff < 0 )
|
||||
{
|
||||
/* keep extreme value accessible only near upper end of scale (1.0) */
|
||||
cutoff *= cutoff;
|
||||
cutoff *= cutoff;
|
||||
cutoff *= cutoff;
|
||||
cutoff *= -30.0f / 0.65f;
|
||||
}
|
||||
cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff;
|
||||
if ( cutoff < 0 )
|
||||
{
|
||||
/* keep extreme value accessible only near upper end of scale (1.0) */
|
||||
cutoff *= cutoff;
|
||||
cutoff *= cutoff;
|
||||
cutoff *= cutoff;
|
||||
cutoff *= -30.0f / 0.65f;
|
||||
}
|
||||
cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff;
|
||||
|
||||
for ( i = -kernel_half; i <= kernel_half; i++ )
|
||||
kernels [kernel_size / 2 + i] = (float) exp( i * i * cutoff );
|
||||
for ( i = -kernel_half; i <= kernel_half; i++ )
|
||||
kernels [kernel_size / 2 + i] = (float) exp( i * i * cutoff );
|
||||
|
||||
/* normalize even and odd phases separately */
|
||||
for ( i = 0; i < 2; i++ )
|
||||
{
|
||||
float sum = 0;
|
||||
int x;
|
||||
for ( x = i; x < kernel_size; x += 2 )
|
||||
sum += kernels [x];
|
||||
/* normalize even and odd phases separately */
|
||||
for ( i = 0; i < 2; i++ )
|
||||
{
|
||||
float sum = 0;
|
||||
int x;
|
||||
for ( x = i; x < kernel_size; x += 2 )
|
||||
sum += kernels [x];
|
||||
|
||||
sum = 1.0f / sum;
|
||||
for ( x = i; x < kernel_size; x += 2 )
|
||||
{
|
||||
kernels [x] *= sum;
|
||||
assert( kernels [x] == kernels [x] ); /* catch numerical instability */
|
||||
}
|
||||
}
|
||||
}
|
||||
sum = 1.0f / sum;
|
||||
for ( x = i; x < kernel_size; x += 2 )
|
||||
{
|
||||
kernels [x] *= sum;
|
||||
assert( kernels [x] == kernels [x] ); /* catch numerical instability */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
printf( "luma:\n" );
|
||||
for ( i = kernel_size; i < kernel_size * 2; i++ )
|
||||
printf( "%f\n", kernels [i] );
|
||||
printf( "chroma:\n" );
|
||||
for ( i = 0; i < kernel_size; i++ )
|
||||
printf( "%f\n", kernels [i] );
|
||||
*/
|
||||
/*
|
||||
printf( "luma:\n" );
|
||||
for ( i = kernel_size; i < kernel_size * 2; i++ )
|
||||
printf( "%f\n", kernels [i] );
|
||||
printf( "chroma:\n" );
|
||||
for ( i = 0; i < kernel_size; i++ )
|
||||
printf( "%f\n", kernels [i] );
|
||||
*/
|
||||
|
||||
/* generate linear rescale kernels */
|
||||
#if rescale_out > 1
|
||||
{
|
||||
float weight = 1.0f;
|
||||
float* out = impl->kernel;
|
||||
int n = rescale_out;
|
||||
do
|
||||
{
|
||||
float remain = 0;
|
||||
int i;
|
||||
weight -= 1.0f / rescale_in;
|
||||
for ( i = 0; i < kernel_size * 2; i++ )
|
||||
{
|
||||
float cur = kernels [i];
|
||||
float m = cur * weight;
|
||||
*out++ = m + remain;
|
||||
remain = cur - m;
|
||||
}
|
||||
}
|
||||
while ( --n );
|
||||
}
|
||||
#endif
|
||||
/* generate linear rescale kernels */
|
||||
#if rescale_out > 1
|
||||
{
|
||||
float weight = 1.0f;
|
||||
float* out = impl->kernel;
|
||||
int n = rescale_out;
|
||||
do
|
||||
{
|
||||
float remain = 0;
|
||||
int i;
|
||||
weight -= 1.0f / rescale_in;
|
||||
for ( i = 0; i < kernel_size * 2; i++ )
|
||||
{
|
||||
float cur = kernels [i];
|
||||
float m = cur * weight;
|
||||
*out++ = m + remain;
|
||||
remain = cur - m;
|
||||
}
|
||||
}
|
||||
while ( --n );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static float const default_decoder [6] =
|
||||
{ 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f };
|
||||
{ 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f };
|
||||
|
||||
static void init( init_t* impl, md_ntsc_setup_t const* setup )
|
||||
{
|
||||
impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset;
|
||||
impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit;
|
||||
#ifdef default_palette_contrast
|
||||
if ( !setup->palette )
|
||||
impl->contrast *= default_palette_contrast;
|
||||
#endif
|
||||
impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset;
|
||||
impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit;
|
||||
#ifdef default_palette_contrast
|
||||
if ( !setup->palette )
|
||||
impl->contrast *= default_palette_contrast;
|
||||
#endif
|
||||
|
||||
impl->artifacts = (float) setup->artifacts;
|
||||
if ( impl->artifacts > 0 )
|
||||
impl->artifacts *= artifacts_max - artifacts_mid;
|
||||
impl->artifacts = impl->artifacts * artifacts_mid + artifacts_mid;
|
||||
impl->artifacts = (float) setup->artifacts;
|
||||
if ( impl->artifacts > 0 )
|
||||
impl->artifacts *= artifacts_max - artifacts_mid;
|
||||
impl->artifacts = impl->artifacts * artifacts_mid + artifacts_mid;
|
||||
|
||||
impl->fringing = (float) setup->fringing;
|
||||
if ( impl->fringing > 0 )
|
||||
impl->fringing *= fringing_max - fringing_mid;
|
||||
impl->fringing = impl->fringing * fringing_mid + fringing_mid;
|
||||
impl->fringing = (float) setup->fringing;
|
||||
if ( impl->fringing > 0 )
|
||||
impl->fringing *= fringing_max - fringing_mid;
|
||||
impl->fringing = impl->fringing * fringing_mid + fringing_mid;
|
||||
|
||||
init_filters( impl, setup );
|
||||
init_filters( impl, setup );
|
||||
|
||||
/* generate gamma table */
|
||||
if ( gamma_size > 1 )
|
||||
{
|
||||
float const to_float = 1.0f / (gamma_size - (gamma_size > 1));
|
||||
float const gamma = 1.1333f - (float) setup->gamma * 0.5f;
|
||||
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
|
||||
int i;
|
||||
for ( i = 0; i < gamma_size; i++ )
|
||||
impl->to_float [i] =
|
||||
(float) pow( i * to_float, gamma ) * impl->contrast + impl->brightness;
|
||||
}
|
||||
/* generate gamma table */
|
||||
if ( gamma_size > 1 )
|
||||
{
|
||||
float const to_float = 1.0f / (gamma_size - (gamma_size > 1));
|
||||
float const gamma = 1.1333f - (float) setup->gamma * 0.5f;
|
||||
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
|
||||
int i;
|
||||
for ( i = 0; i < gamma_size; i++ )
|
||||
impl->to_float [i] =
|
||||
(float) pow( i * to_float, gamma ) * impl->contrast + impl->brightness;
|
||||
}
|
||||
|
||||
/* setup decoder matricies */
|
||||
{
|
||||
float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue;
|
||||
float sat = (float) setup->saturation + 1;
|
||||
float const* decoder = setup->decoder_matrix;
|
||||
if ( !decoder )
|
||||
{
|
||||
decoder = default_decoder;
|
||||
if ( STD_HUE_CONDITION( setup ) )
|
||||
hue += PI / 180 * (std_decoder_hue - ext_decoder_hue);
|
||||
}
|
||||
/* setup decoder matricies */
|
||||
{
|
||||
float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue;
|
||||
float sat = (float) setup->saturation + 1;
|
||||
float const* decoder = setup->decoder_matrix;
|
||||
if ( !decoder )
|
||||
{
|
||||
decoder = default_decoder;
|
||||
if ( STD_HUE_CONDITION( setup ) )
|
||||
hue += PI / 180 * (std_decoder_hue - ext_decoder_hue);
|
||||
}
|
||||
|
||||
{
|
||||
float s = (float) sin( hue ) * sat;
|
||||
float c = (float) cos( hue ) * sat;
|
||||
float* out = impl->to_rgb;
|
||||
int n;
|
||||
{
|
||||
float s = (float) sin( hue ) * sat;
|
||||
float c = (float) cos( hue ) * sat;
|
||||
float* out = impl->to_rgb;
|
||||
int n;
|
||||
|
||||
n = burst_count;
|
||||
do
|
||||
{
|
||||
float const* in = decoder;
|
||||
int n = 3;
|
||||
do
|
||||
{
|
||||
float i = *in++;
|
||||
float q = *in++;
|
||||
*out++ = i * c - q * s;
|
||||
*out++ = i * s + q * c;
|
||||
}
|
||||
while ( --n );
|
||||
if ( burst_count <= 1 )
|
||||
break;
|
||||
ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */
|
||||
}
|
||||
while ( --n );
|
||||
}
|
||||
}
|
||||
n = burst_count;
|
||||
do
|
||||
{
|
||||
float const* in = decoder;
|
||||
int n = 3;
|
||||
do
|
||||
{
|
||||
float i = *in++;
|
||||
float q = *in++;
|
||||
*out++ = i * c - q * s;
|
||||
*out++ = i * s + q * c;
|
||||
}
|
||||
while ( --n );
|
||||
if ( burst_count <= 1 )
|
||||
break;
|
||||
ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */
|
||||
}
|
||||
while ( --n );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* kernel generation */
|
||||
|
||||
#define RGB_TO_YIQ( r, g, b, y, i ) (\
|
||||
(y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\
|
||||
(i = (r) * 0.596f - (g) * 0.275f - (b) * 0.321f),\
|
||||
((r) * 0.212f - (g) * 0.523f + (b) * 0.311f)\
|
||||
(y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\
|
||||
(i = (r) * 0.596f - (g) * 0.275f - (b) * 0.321f),\
|
||||
((r) * 0.212f - (g) * 0.523f + (b) * 0.311f)\
|
||||
)
|
||||
|
||||
#define YIQ_TO_RGB( y, i, q, to_rgb, type, r, g ) (\
|
||||
r = (type) (y + to_rgb [0] * i + to_rgb [1] * q),\
|
||||
g = (type) (y + to_rgb [2] * i + to_rgb [3] * q),\
|
||||
(type) (y + to_rgb [4] * i + to_rgb [5] * q)\
|
||||
r = (type) (y + to_rgb [0] * i + to_rgb [1] * q),\
|
||||
g = (type) (y + to_rgb [2] * i + to_rgb [3] * q),\
|
||||
(type) (y + to_rgb [4] * i + to_rgb [5] * q)\
|
||||
)
|
||||
|
||||
#define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1)
|
||||
@ -289,24 +289,24 @@ enum { rgb_bias = rgb_unit * 2 * md_ntsc_rgb_builder };
|
||||
|
||||
typedef struct pixel_info_t
|
||||
{
|
||||
int offset;
|
||||
float negate;
|
||||
float kernel [4];
|
||||
int offset;
|
||||
float negate;
|
||||
float kernel [4];
|
||||
} pixel_info_t;
|
||||
|
||||
#if rescale_in > 1
|
||||
#define PIXEL_OFFSET_( ntsc, scaled ) \
|
||||
(kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \
|
||||
(kernel_size * 2 * scaled))
|
||||
#define PIXEL_OFFSET_( ntsc, scaled ) \
|
||||
(kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \
|
||||
(kernel_size * 2 * scaled))
|
||||
|
||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
||||
PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\
|
||||
(((scaled) + rescale_out * 10) % rescale_out) ),\
|
||||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
||||
PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\
|
||||
(((scaled) + rescale_out * 10) % rescale_out) ),\
|
||||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#else
|
||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
||||
(kernel_size / 2 + (ntsc) - (scaled)),\
|
||||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
||||
(kernel_size / 2 + (ntsc) - (scaled)),\
|
||||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#endif
|
||||
|
||||
extern pixel_info_t const md_ntsc_pixels [alignment_count];
|
||||
@ -314,126 +314,126 @@ extern pixel_info_t const md_ntsc_pixels [alignment_count];
|
||||
/* Generate pixel at all burst phases and column alignments */
|
||||
static void gen_kernel( init_t* impl, float y, float i, float q, md_ntsc_rgb_t* out )
|
||||
{
|
||||
/* generate for each scanline burst phase */
|
||||
float const* to_rgb = impl->to_rgb;
|
||||
int burst_remain = burst_count;
|
||||
y -= rgb_offset;
|
||||
do
|
||||
{
|
||||
/* Encode yiq into *two* composite signals (to allow control over artifacting).
|
||||
Convolve these with kernels which: filter respective components, apply
|
||||
sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack
|
||||
into integer. Based on algorithm by NewRisingSun. */
|
||||
pixel_info_t const* pixel = md_ntsc_pixels;
|
||||
int alignment_remain = alignment_count;
|
||||
do
|
||||
{
|
||||
/* negate is -1 when composite starts at odd multiple of 2 */
|
||||
float const yy = y * impl->fringing * pixel->negate;
|
||||
float const ic0 = (i + yy) * pixel->kernel [0];
|
||||
float const qc1 = (q + yy) * pixel->kernel [1];
|
||||
float const ic2 = (i - yy) * pixel->kernel [2];
|
||||
float const qc3 = (q - yy) * pixel->kernel [3];
|
||||
/* generate for each scanline burst phase */
|
||||
float const* to_rgb = impl->to_rgb;
|
||||
int burst_remain = burst_count;
|
||||
y -= rgb_offset;
|
||||
do
|
||||
{
|
||||
/* Encode yiq into *two* composite signals (to allow control over artifacting).
|
||||
Convolve these with kernels which: filter respective components, apply
|
||||
sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack
|
||||
into integer. Based on algorithm by NewRisingSun. */
|
||||
pixel_info_t const* pixel = md_ntsc_pixels;
|
||||
int alignment_remain = alignment_count;
|
||||
do
|
||||
{
|
||||
/* negate is -1 when composite starts at odd multiple of 2 */
|
||||
float const yy = y * impl->fringing * pixel->negate;
|
||||
float const ic0 = (i + yy) * pixel->kernel [0];
|
||||
float const qc1 = (q + yy) * pixel->kernel [1];
|
||||
float const ic2 = (i - yy) * pixel->kernel [2];
|
||||
float const qc3 = (q - yy) * pixel->kernel [3];
|
||||
|
||||
float const factor = impl->artifacts * pixel->negate;
|
||||
float const ii = i * factor;
|
||||
float const yc0 = (y + ii) * pixel->kernel [0];
|
||||
float const yc2 = (y - ii) * pixel->kernel [2];
|
||||
float const factor = impl->artifacts * pixel->negate;
|
||||
float const ii = i * factor;
|
||||
float const yc0 = (y + ii) * pixel->kernel [0];
|
||||
float const yc2 = (y - ii) * pixel->kernel [2];
|
||||
|
||||
float const qq = q * factor;
|
||||
float const yc1 = (y + qq) * pixel->kernel [1];
|
||||
float const yc3 = (y - qq) * pixel->kernel [3];
|
||||
float const qq = q * factor;
|
||||
float const yc1 = (y + qq) * pixel->kernel [1];
|
||||
float const yc3 = (y - qq) * pixel->kernel [3];
|
||||
|
||||
float const* k = &impl->kernel [pixel->offset];
|
||||
int n;
|
||||
++pixel;
|
||||
for ( n = rgb_kernel_size; n; --n )
|
||||
{
|
||||
float i = k[0]*ic0 + k[2]*ic2;
|
||||
float q = k[1]*qc1 + k[3]*qc3;
|
||||
float y = k[kernel_size+0]*yc0 + k[kernel_size+1]*yc1 +
|
||||
k[kernel_size+2]*yc2 + k[kernel_size+3]*yc3 + rgb_offset;
|
||||
if ( rescale_out <= 1 )
|
||||
k--;
|
||||
else if ( k < &impl->kernel [kernel_size * 2 * (rescale_out - 1)] )
|
||||
k += kernel_size * 2 - 1;
|
||||
else
|
||||
k -= kernel_size * 2 * (rescale_out - 1) + 2;
|
||||
{
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, to_rgb, int, r, g );
|
||||
*out++ = PACK_RGB( r, g, b ) - rgb_bias;
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( alignment_count > 1 && --alignment_remain );
|
||||
float const* k = &impl->kernel [pixel->offset];
|
||||
int n;
|
||||
++pixel;
|
||||
for ( n = rgb_kernel_size; n; --n )
|
||||
{
|
||||
float i = k[0]*ic0 + k[2]*ic2;
|
||||
float q = k[1]*qc1 + k[3]*qc3;
|
||||
float y = k[kernel_size+0]*yc0 + k[kernel_size+1]*yc1 +
|
||||
k[kernel_size+2]*yc2 + k[kernel_size+3]*yc3 + rgb_offset;
|
||||
if ( rescale_out <= 1 )
|
||||
k--;
|
||||
else if ( k < &impl->kernel [kernel_size * 2 * (rescale_out - 1)] )
|
||||
k += kernel_size * 2 - 1;
|
||||
else
|
||||
k -= kernel_size * 2 * (rescale_out - 1) + 2;
|
||||
{
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, to_rgb, int, r, g );
|
||||
*out++ = PACK_RGB( r, g, b ) - rgb_bias;
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( alignment_count > 1 && --alignment_remain );
|
||||
|
||||
if ( burst_count <= 1 )
|
||||
break;
|
||||
if ( burst_count <= 1 )
|
||||
break;
|
||||
|
||||
to_rgb += 6;
|
||||
to_rgb += 6;
|
||||
|
||||
ROTATE_IQ( i, q, -0.866025f, -0.5f ); /* -120 degrees */
|
||||
}
|
||||
while ( --burst_remain );
|
||||
ROTATE_IQ( i, q, -0.866025f, -0.5f ); /* -120 degrees */
|
||||
}
|
||||
while ( --burst_remain );
|
||||
}
|
||||
|
||||
static void correct_errors( md_ntsc_rgb_t color, md_ntsc_rgb_t* out );
|
||||
|
||||
#if DISABLE_CORRECTION
|
||||
#define CORRECT_ERROR( a ) { out [i] += rgb_bias; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) { out [i] += rgb_bias; }
|
||||
#define CORRECT_ERROR( a ) { out [i] += rgb_bias; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) { out [i] += rgb_bias; }
|
||||
#else
|
||||
#define CORRECT_ERROR( a ) { out [a] += error; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) {\
|
||||
md_ntsc_rgb_t fourth = (error + 2 * md_ntsc_rgb_builder) >> 2;\
|
||||
fourth &= (rgb_bias >> 1) - md_ntsc_rgb_builder;\
|
||||
fourth -= rgb_bias >> 2;\
|
||||
out [a] += fourth;\
|
||||
out [b] += fourth;\
|
||||
out [c] += fourth;\
|
||||
out [i] += error - (fourth * 3);\
|
||||
}
|
||||
#define CORRECT_ERROR( a ) { out [a] += error; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) {\
|
||||
md_ntsc_rgb_t fourth = (error + 2 * md_ntsc_rgb_builder) >> 2;\
|
||||
fourth &= (rgb_bias >> 1) - md_ntsc_rgb_builder;\
|
||||
fourth -= rgb_bias >> 2;\
|
||||
out [a] += fourth;\
|
||||
out [b] += fourth;\
|
||||
out [c] += fourth;\
|
||||
out [i] += error - (fourth * 3);\
|
||||
}
|
||||
#endif
|
||||
|
||||
#define RGB_PALETTE_OUT( rgb, out_ )\
|
||||
{\
|
||||
unsigned char* out = (out_);\
|
||||
md_ntsc_rgb_t clamped = (rgb);\
|
||||
MD_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\
|
||||
out [0] = (unsigned char) (clamped >> 21);\
|
||||
out [1] = (unsigned char) (clamped >> 11);\
|
||||
out [2] = (unsigned char) (clamped >> 1);\
|
||||
unsigned char* out = (out_);\
|
||||
md_ntsc_rgb_t clamped = (rgb);\
|
||||
MD_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\
|
||||
out [0] = (unsigned char) (clamped >> 21);\
|
||||
out [1] = (unsigned char) (clamped >> 11);\
|
||||
out [2] = (unsigned char) (clamped >> 1);\
|
||||
}
|
||||
|
||||
/* blitter related */
|
||||
|
||||
#ifndef restrict
|
||||
#if defined (__GNUC__)
|
||||
#define restrict __restrict__
|
||||
#elif defined (_MSC_VER) && _MSC_VER > 1300
|
||||
#define restrict
|
||||
#else
|
||||
/* no support for restricted pointers */
|
||||
#define restrict
|
||||
#endif
|
||||
#if defined (__GNUC__)
|
||||
#define restrict __restrict__
|
||||
#elif defined (_MSC_VER) && _MSC_VER > 1300
|
||||
#define restrict
|
||||
#else
|
||||
/* no support for restricted pointers */
|
||||
#define restrict
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if MD_NTSC_OUT_DEPTH <= 16
|
||||
#if USHRT_MAX == 0xFFFF
|
||||
typedef unsigned short md_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 16-bit int type"
|
||||
#endif
|
||||
#if USHRT_MAX == 0xFFFF
|
||||
typedef unsigned short md_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 16-bit int type"
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if UINT_MAX == 0xFFFFFFFF
|
||||
typedef unsigned int md_ntsc_out_t;
|
||||
#elif ULONG_MAX == 0xFFFFFFFF
|
||||
typedef unsigned long md_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 32-bit int type"
|
||||
#endif
|
||||
#if UINT_MAX == 0xFFFFFFFF
|
||||
typedef unsigned int md_ntsc_out_t;
|
||||
#elif ULONG_MAX == 0xFFFFFFFF
|
||||
typedef unsigned long md_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 32-bit int type"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -35,71 +35,71 @@ sms_ntsc_setup_t const sms_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.70, -1, -1,-1,
|
||||
|
||||
/* 3 input pixels -> 8 composite samples */
|
||||
pixel_info_t const sms_ntsc_pixels [alignment_count] = {
|
||||
{ PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } },
|
||||
{ PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } },
|
||||
{ PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } },
|
||||
{ PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } },
|
||||
{ PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } },
|
||||
{ PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } },
|
||||
};
|
||||
|
||||
static void correct_errors( sms_ntsc_rgb_t color, sms_ntsc_rgb_t* out )
|
||||
{
|
||||
unsigned i;
|
||||
for ( i = 0; i < rgb_kernel_size / 2; i++ )
|
||||
{
|
||||
sms_ntsc_rgb_t error = color -
|
||||
out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] -
|
||||
out [i + 7] - out [i + 5 +14] - out [i + 3 +28];
|
||||
CORRECT_ERROR( i + 3 + 28 );
|
||||
}
|
||||
unsigned i;
|
||||
for ( i = 0; i < rgb_kernel_size / 2; i++ )
|
||||
{
|
||||
sms_ntsc_rgb_t error = color -
|
||||
out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] -
|
||||
out [i + 7] - out [i + 5 +14] - out [i + 3 +28];
|
||||
CORRECT_ERROR( i + 3 + 28 );
|
||||
}
|
||||
}
|
||||
|
||||
void sms_ntsc_init( sms_ntsc_t* ntsc, sms_ntsc_setup_t const* setup )
|
||||
{
|
||||
int entry;
|
||||
init_t impl;
|
||||
if ( !setup )
|
||||
setup = &sms_ntsc_composite;
|
||||
init( &impl, setup );
|
||||
|
||||
for ( entry = 0; entry < sms_ntsc_palette_size; entry++ )
|
||||
{
|
||||
float bb = impl.to_float [entry >> 8 & 0x0F];
|
||||
float gg = impl.to_float [entry >> 4 & 0x0F];
|
||||
float rr = impl.to_float [entry & 0x0F];
|
||||
|
||||
float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i );
|
||||
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g );
|
||||
sms_ntsc_rgb_t rgb = PACK_RGB( r, g, b );
|
||||
|
||||
if ( setup->palette_out )
|
||||
RGB_PALETTE_OUT( rgb, &setup->palette_out [entry * 3] );
|
||||
|
||||
if ( ntsc )
|
||||
{
|
||||
gen_kernel( &impl, y, i, q, ntsc->table [entry] );
|
||||
correct_errors( rgb, ntsc->table [entry] );
|
||||
}
|
||||
}
|
||||
int entry;
|
||||
init_t impl;
|
||||
if ( !setup )
|
||||
setup = &sms_ntsc_composite;
|
||||
init( &impl, setup );
|
||||
|
||||
for ( entry = 0; entry < sms_ntsc_palette_size; entry++ )
|
||||
{
|
||||
float bb = impl.to_float [entry >> 8 & 0x0F];
|
||||
float gg = impl.to_float [entry >> 4 & 0x0F];
|
||||
float rr = impl.to_float [entry & 0x0F];
|
||||
|
||||
float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i );
|
||||
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g );
|
||||
sms_ntsc_rgb_t rgb = PACK_RGB( r, g, b );
|
||||
|
||||
if ( setup->palette_out )
|
||||
RGB_PALETTE_OUT( rgb, &setup->palette_out [entry * 3] );
|
||||
|
||||
if ( ntsc )
|
||||
{
|
||||
gen_kernel( &impl, y, i, q, ntsc->table [entry] );
|
||||
correct_errors( rgb, ntsc->table [entry] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SMS_NTSC_NO_BLITTERS
|
||||
|
||||
/* modified blitters to work on a line basis with genesis plus renderer*/
|
||||
void sms_ntsc_blit( sms_ntsc_t const* ntsc, SMS_NTSC_IN_T const* table, unsigned char* input,
|
||||
int in_width, int vline)
|
||||
int in_width, int vline)
|
||||
{
|
||||
int const chunk_count = in_width / sms_ntsc_in_chunk;
|
||||
|
||||
/* handle extra 0, 1, or 2 pixels by placing them at beginning of row */
|
||||
int const in_extra = in_width - chunk_count * sms_ntsc_in_chunk;
|
||||
unsigned const extra2 = (unsigned) -(in_extra >> 1 & 1); /* (unsigned) -1 = ~0 */
|
||||
unsigned const extra1 = (unsigned) -(in_extra & 1) | extra2;
|
||||
int const chunk_count = in_width / sms_ntsc_in_chunk;
|
||||
|
||||
/* handle extra 0, 1, or 2 pixels by placing them at beginning of row */
|
||||
int const in_extra = in_width - chunk_count * sms_ntsc_in_chunk;
|
||||
unsigned const extra2 = (unsigned) -(in_extra >> 1 & 1); /* (unsigned) -1 = ~0 */
|
||||
unsigned const extra1 = (unsigned) -(in_extra & 1) | extra2;
|
||||
|
||||
SMS_NTSC_IN_T border = table[0];
|
||||
|
||||
SMS_NTSC_BEGIN_ROW( ntsc, border,
|
||||
(SMS_NTSC_ADJ_IN( table[input[0]] )) & extra2,
|
||||
(SMS_NTSC_ADJ_IN( table[input[extra2 & 1]] )) & extra1 );
|
||||
|
||||
SMS_NTSC_BEGIN_ROW( ntsc, border,
|
||||
(SMS_NTSC_ADJ_IN( table[input[0]] )) & extra2,
|
||||
(SMS_NTSC_ADJ_IN( table[input[extra2 & 1]] )) & extra1 );
|
||||
|
||||
#ifdef NGC
|
||||
/* directly fill the RGB565 texture */
|
||||
@ -113,83 +113,83 @@ void sms_ntsc_blit( sms_ntsc_t const* ntsc, SMS_NTSC_IN_T const* table, unsigned
|
||||
sms_ntsc_out_t* restrict line_out = (sms_ntsc_out_t*)(&bitmap.data[(vline * bitmap.pitch)]);
|
||||
#endif
|
||||
int n;
|
||||
input += in_extra;
|
||||
|
||||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* order of input and output pixels must not be altered */
|
||||
SMS_NTSC_COLOR_IN( 0, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
|
||||
input += in_extra;
|
||||
|
||||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* order of input and output pixels must not be altered */
|
||||
SMS_NTSC_COLOR_IN( 0, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 0, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 0, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
SMS_NTSC_RGB_OUT( 1, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 1, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 0, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 1, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 0, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 1, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
|
||||
SMS_NTSC_COLOR_IN( 1, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
|
||||
|
||||
SMS_NTSC_COLOR_IN( 1, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 2, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 2, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
SMS_NTSC_RGB_OUT( 3, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 3, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 2, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 3, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 2, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 3, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
|
||||
SMS_NTSC_COLOR_IN( 2, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
|
||||
|
||||
SMS_NTSC_COLOR_IN( 2, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 4, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 4, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
SMS_NTSC_RGB_OUT( 5, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 5, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
SMS_NTSC_RGB_OUT( 6, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 6, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 4, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 5, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 4, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 5, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* finish final pixels */
|
||||
SMS_NTSC_COLOR_IN( 0, ntsc, border );
|
||||
}
|
||||
|
||||
/* finish final pixels */
|
||||
SMS_NTSC_COLOR_IN( 0, ntsc, border );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 0, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 0, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
SMS_NTSC_RGB_OUT( 1, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 1, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 0, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 1, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 0, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 1, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
|
||||
SMS_NTSC_COLOR_IN( 1, ntsc, border );
|
||||
|
||||
SMS_NTSC_COLOR_IN( 1, ntsc, border );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 2, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 2, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
SMS_NTSC_RGB_OUT( 3, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 3, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 2, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 3, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 2, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 3, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
|
||||
SMS_NTSC_COLOR_IN( 2, ntsc, border );
|
||||
|
||||
SMS_NTSC_COLOR_IN( 2, ntsc, border );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 4, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 4, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
SMS_NTSC_RGB_OUT( 5, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 5, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
SMS_NTSC_RGB_OUT( 6, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 6, line_out[offset++], SMS_NTSC_OUT_DEPTH );
|
||||
if ((offset % 4) == 0) offset += 12;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 4, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 5, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 4, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 5, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
@ -7,29 +7,29 @@
|
||||
#include "sms_ntsc_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown
|
||||
in parenthesis and should remain fairly stable in future versions. */
|
||||
typedef struct sms_ntsc_setup_t
|
||||
{
|
||||
/* Basic parameters */
|
||||
double hue; /* -1 = -180 degrees +1 = +180 degrees */
|
||||
double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */
|
||||
double contrast; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double brightness; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double sharpness; /* edge contrast enhancement/blurring */
|
||||
|
||||
/* Advanced parameters */
|
||||
double gamma; /* -1 = dark (1.5) +1 = light (0.5) */
|
||||
double resolution; /* image resolution */
|
||||
double artifacts; /* artifacts caused by color changes */
|
||||
double fringing; /* color artifacts caused by brightness changes */
|
||||
double bleed; /* color bleed (color resolution reduction) */
|
||||
float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */
|
||||
|
||||
unsigned char* palette_out; /* optional RGB palette out, 3 bytes per color */
|
||||
/* Basic parameters */
|
||||
double hue; /* -1 = -180 degrees +1 = +180 degrees */
|
||||
double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */
|
||||
double contrast; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double brightness; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double sharpness; /* edge contrast enhancement/blurring */
|
||||
|
||||
/* Advanced parameters */
|
||||
double gamma; /* -1 = dark (1.5) +1 = light (0.5) */
|
||||
double resolution; /* image resolution */
|
||||
double artifacts; /* artifacts caused by color changes */
|
||||
double fringing; /* color artifacts caused by brightness changes */
|
||||
double bleed; /* color bleed (color resolution reduction) */
|
||||
float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */
|
||||
|
||||
unsigned char* palette_out; /* optional RGB palette out, 3 bytes per color */
|
||||
} sms_ntsc_setup_t;
|
||||
|
||||
/* Video format presets */
|
||||
@ -50,17 +50,17 @@ and output RGB depth is set by SMS_NTSC_OUT_DEPTH. Both default to 16-bit RGB.
|
||||
In_row_width is the number of pixels to get to the next input row. Out_pitch
|
||||
is the number of *bytes* to get to the next output row. */
|
||||
void sms_ntsc_blit( sms_ntsc_t const* ntsc, SMS_NTSC_IN_T const* table, unsigned char* input,
|
||||
int in_width, int vline);
|
||||
int in_width, int vline);
|
||||
|
||||
/* Number of output pixels written by blitter for given input width. */
|
||||
#define SMS_NTSC_OUT_WIDTH( in_width ) \
|
||||
(((in_width) / sms_ntsc_in_chunk + 1) * sms_ntsc_out_chunk)
|
||||
(((in_width) / sms_ntsc_in_chunk + 1) * sms_ntsc_out_chunk)
|
||||
|
||||
/* Number of input pixels that will fit within given output width. Might be
|
||||
rounded down slightly; use SMS_NTSC_OUT_WIDTH() on result to find rounded
|
||||
value. */
|
||||
#define SMS_NTSC_IN_WIDTH( out_width ) \
|
||||
(((out_width) / sms_ntsc_out_chunk - 1) * sms_ntsc_in_chunk + 2)
|
||||
(((out_width) / sms_ntsc_out_chunk - 1) * sms_ntsc_in_chunk + 2)
|
||||
|
||||
|
||||
/* Interface for user-defined custom blitters */
|
||||
@ -73,11 +73,11 @@ enum { sms_ntsc_black = 0 }; /* palette index for black */
|
||||
Use sms_ntsc_black for unused pixels. Declares variables, so must be before first
|
||||
statement in a block (unless you're using C++). */
|
||||
#define SMS_NTSC_BEGIN_ROW( ntsc, pixel0, pixel1, pixel2 ) \
|
||||
SMS_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, SMS_NTSC_IN_FORMAT, ntsc )
|
||||
SMS_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, SMS_NTSC_IN_FORMAT, ntsc )
|
||||
|
||||
/* Begins input pixel */
|
||||
#define SMS_NTSC_COLOR_IN( in_index, ntsc, color_in ) \
|
||||
SMS_NTSC_COLOR_IN_( in_index, color_in, SMS_NTSC_IN_FORMAT, ntsc )
|
||||
SMS_NTSC_COLOR_IN_( in_index, color_in, SMS_NTSC_IN_FORMAT, ntsc )
|
||||
|
||||
/* Generates output pixel. Bits can be 24, 16, 15, 32 (treated as 24), or 0:
|
||||
24: RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8 RGB)
|
||||
@ -85,46 +85,46 @@ statement in a block (unless you're using C++). */
|
||||
15: RRRRRGG GGGBBBBB (5-5-5 RGB)
|
||||
0: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format; x = junk bits) */
|
||||
#define SMS_NTSC_RGB_OUT( index, rgb_out, bits ) \
|
||||
SMS_NTSC_RGB_OUT_14_( index, rgb_out, bits, 0 )
|
||||
SMS_NTSC_RGB_OUT_14_( index, rgb_out, bits, 0 )
|
||||
|
||||
|
||||
/* private */
|
||||
enum { sms_ntsc_entry_size = 3 * 14 };
|
||||
typedef unsigned long sms_ntsc_rgb_t;
|
||||
struct sms_ntsc_t {
|
||||
sms_ntsc_rgb_t table [sms_ntsc_palette_size] [sms_ntsc_entry_size];
|
||||
sms_ntsc_rgb_t table [sms_ntsc_palette_size] [sms_ntsc_entry_size];
|
||||
};
|
||||
|
||||
#define SMS_NTSC_BGR12( ntsc, n ) (ntsc)->table [n & 0xFFF]
|
||||
|
||||
#define SMS_NTSC_RGB16( ntsc, n ) \
|
||||
(sms_ntsc_rgb_t const*) ((char const*) (ntsc)->table +\
|
||||
((n << 10 & 0x7800) | (n & 0x0780) | (n >> 9 & 0x0078)) *\
|
||||
(sms_ntsc_entry_size * sizeof (sms_ntsc_rgb_t) / 8))
|
||||
(sms_ntsc_rgb_t const*) ((char const*) (ntsc)->table +\
|
||||
((n << 10 & 0x7800) | (n & 0x0780) | (n >> 9 & 0x0078)) *\
|
||||
(sms_ntsc_entry_size * sizeof (sms_ntsc_rgb_t) / 8))
|
||||
|
||||
#define SMS_NTSC_RGB15( ntsc, n ) \
|
||||
(sms_ntsc_rgb_t const*) ((char const*) (ntsc)->table +\
|
||||
((n << 9 & 0x3C00) | (n & 0x03C0) | (n >> 9 & 0x003C)) *\
|
||||
(sms_ntsc_entry_size * sizeof (sms_ntsc_rgb_t) / 4))
|
||||
(sms_ntsc_rgb_t const*) ((char const*) (ntsc)->table +\
|
||||
((n << 9 & 0x3C00) | (n & 0x03C0) | (n >> 9 & 0x003C)) *\
|
||||
(sms_ntsc_entry_size * sizeof (sms_ntsc_rgb_t) / 4))
|
||||
|
||||
/* common 3->7 ntsc macros */
|
||||
#define SMS_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, ENTRY, table ) \
|
||||
unsigned const sms_ntsc_pixel0_ = (pixel0);\
|
||||
sms_ntsc_rgb_t const* kernel0 = ENTRY( table, sms_ntsc_pixel0_ );\
|
||||
unsigned const sms_ntsc_pixel1_ = (pixel1);\
|
||||
sms_ntsc_rgb_t const* kernel1 = ENTRY( table, sms_ntsc_pixel1_ );\
|
||||
unsigned const sms_ntsc_pixel2_ = (pixel2);\
|
||||
sms_ntsc_rgb_t const* kernel2 = ENTRY( table, sms_ntsc_pixel2_ );\
|
||||
sms_ntsc_rgb_t const* kernelx0;\
|
||||
sms_ntsc_rgb_t const* kernelx1 = kernel0;\
|
||||
sms_ntsc_rgb_t const* kernelx2 = kernel0
|
||||
unsigned const sms_ntsc_pixel0_ = (pixel0);\
|
||||
sms_ntsc_rgb_t const* kernel0 = ENTRY( table, sms_ntsc_pixel0_ );\
|
||||
unsigned const sms_ntsc_pixel1_ = (pixel1);\
|
||||
sms_ntsc_rgb_t const* kernel1 = ENTRY( table, sms_ntsc_pixel1_ );\
|
||||
unsigned const sms_ntsc_pixel2_ = (pixel2);\
|
||||
sms_ntsc_rgb_t const* kernel2 = ENTRY( table, sms_ntsc_pixel2_ );\
|
||||
sms_ntsc_rgb_t const* kernelx0;\
|
||||
sms_ntsc_rgb_t const* kernelx1 = kernel0;\
|
||||
sms_ntsc_rgb_t const* kernelx2 = kernel0
|
||||
|
||||
#define SMS_NTSC_RGB_OUT_14_( x, rgb_out, bits, shift ) {\
|
||||
sms_ntsc_rgb_t raw_ =\
|
||||
kernel0 [x ] + kernel1 [(x+12)%7+14] + kernel2 [(x+10)%7+28] +\
|
||||
kernelx0 [(x+7)%14] + kernelx1 [(x+ 5)%7+21] + kernelx2 [(x+ 3)%7+35];\
|
||||
SMS_NTSC_CLAMP_( raw_, shift );\
|
||||
SMS_NTSC_RGB_OUT_( rgb_out, bits, shift );\
|
||||
sms_ntsc_rgb_t raw_ =\
|
||||
kernel0 [x ] + kernel1 [(x+12)%7+14] + kernel2 [(x+10)%7+28] +\
|
||||
kernelx0 [(x+7)%14] + kernelx1 [(x+ 5)%7+21] + kernelx2 [(x+ 3)%7+35];\
|
||||
SMS_NTSC_CLAMP_( raw_, shift );\
|
||||
SMS_NTSC_RGB_OUT_( rgb_out, bits, shift );\
|
||||
}
|
||||
|
||||
/* common ntsc macros */
|
||||
@ -132,26 +132,26 @@ struct sms_ntsc_t {
|
||||
#define sms_ntsc_clamp_mask (sms_ntsc_rgb_builder * 3 / 2)
|
||||
#define sms_ntsc_clamp_add (sms_ntsc_rgb_builder * 0x101)
|
||||
#define SMS_NTSC_CLAMP_( io, shift ) {\
|
||||
sms_ntsc_rgb_t sub = (io) >> (9-(shift)) & sms_ntsc_clamp_mask;\
|
||||
sms_ntsc_rgb_t clamp = sms_ntsc_clamp_add - sub;\
|
||||
io |= clamp;\
|
||||
clamp -= sub;\
|
||||
io &= clamp;\
|
||||
sms_ntsc_rgb_t sub = (io) >> (9-(shift)) & sms_ntsc_clamp_mask;\
|
||||
sms_ntsc_rgb_t clamp = sms_ntsc_clamp_add - sub;\
|
||||
io |= clamp;\
|
||||
clamp -= sub;\
|
||||
io &= clamp;\
|
||||
}
|
||||
|
||||
#define SMS_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\
|
||||
unsigned color_;\
|
||||
kernelx##index = kernel##index;\
|
||||
kernel##index = (color_ = (color), ENTRY( table, color_ ));\
|
||||
unsigned color_;\
|
||||
kernelx##index = kernel##index;\
|
||||
kernel##index = (color_ = (color), ENTRY( table, color_ ));\
|
||||
}
|
||||
|
||||
/* x is always zero except in snes_ntsc library */
|
||||
#define SMS_NTSC_RGB_OUT_( rgb_out, bits, x ) {\
|
||||
rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\
|
||||
rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -22,22 +22,22 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
#define PI 3.14159265358979323846f
|
||||
|
||||
#ifndef LUMA_CUTOFF
|
||||
#define LUMA_CUTOFF 0.20
|
||||
#define LUMA_CUTOFF 0.20
|
||||
#endif
|
||||
#ifndef gamma_size
|
||||
#define gamma_size 1
|
||||
#define gamma_size 1
|
||||
#endif
|
||||
#ifndef rgb_bits
|
||||
#define rgb_bits 8
|
||||
#define rgb_bits 8
|
||||
#endif
|
||||
#ifndef artifacts_max
|
||||
#define artifacts_max (artifacts_mid * 1.5f)
|
||||
#define artifacts_max (artifacts_mid * 1.5f)
|
||||
#endif
|
||||
#ifndef fringing_max
|
||||
#define fringing_max (fringing_mid * 2)
|
||||
#define fringing_max (fringing_mid * 2)
|
||||
#endif
|
||||
#ifndef STD_HUE_CONDITION
|
||||
#define STD_HUE_CONDITION( setup ) 1
|
||||
#define STD_HUE_CONDITION( setup ) 1
|
||||
#endif
|
||||
|
||||
#define ext_decoder_hue (std_decoder_hue + 15)
|
||||
@ -50,236 +50,236 @@ enum { kernel_size = kernel_half * 2 + 1 };
|
||||
|
||||
typedef struct init_t
|
||||
{
|
||||
float to_rgb [burst_count * 6];
|
||||
float to_float [gamma_size];
|
||||
float contrast;
|
||||
float brightness;
|
||||
float artifacts;
|
||||
float fringing;
|
||||
float kernel [rescale_out * kernel_size * 2];
|
||||
float to_rgb [burst_count * 6];
|
||||
float to_float [gamma_size];
|
||||
float contrast;
|
||||
float brightness;
|
||||
float artifacts;
|
||||
float fringing;
|
||||
float kernel [rescale_out * kernel_size * 2];
|
||||
} init_t;
|
||||
|
||||
#define ROTATE_IQ( i, q, sin_b, cos_b ) {\
|
||||
float t;\
|
||||
t = i * cos_b - q * sin_b;\
|
||||
q = i * sin_b + q * cos_b;\
|
||||
i = t;\
|
||||
float t;\
|
||||
t = i * cos_b - q * sin_b;\
|
||||
q = i * sin_b + q * cos_b;\
|
||||
i = t;\
|
||||
}
|
||||
|
||||
static void init_filters( init_t* impl, sms_ntsc_setup_t const* setup )
|
||||
{
|
||||
#if rescale_out > 1
|
||||
float kernels [kernel_size * 2];
|
||||
float kernels [kernel_size * 2];
|
||||
#else
|
||||
float* const kernels = impl->kernel;
|
||||
float* const kernels = impl->kernel;
|
||||
#endif
|
||||
|
||||
/* generate luma (y) filter using sinc kernel */
|
||||
{
|
||||
/* sinc with rolloff (dsf) */
|
||||
float const rolloff = 1 + (float) setup->sharpness * (float) 0.032;
|
||||
float const maxh = 32;
|
||||
float const pow_a_n = (float) pow( rolloff, maxh );
|
||||
float sum;
|
||||
int i;
|
||||
/* quadratic mapping to reduce negative (blurring) range */
|
||||
float to_angle = (float) setup->resolution + 1;
|
||||
to_angle = PI / maxh * (float) LUMA_CUTOFF * (to_angle * to_angle + 1);
|
||||
|
||||
kernels [kernel_size * 3 / 2] = maxh; /* default center value */
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
int x = i - kernel_half;
|
||||
float angle = x * to_angle;
|
||||
/* instability occurs at center point with rolloff very close to 1.0 */
|
||||
if ( x || pow_a_n > (float) 1.056 || pow_a_n < (float) 0.981 )
|
||||
{
|
||||
float rolloff_cos_a = rolloff * (float) cos( angle );
|
||||
float num = 1 - rolloff_cos_a -
|
||||
pow_a_n * (float) cos( maxh * angle ) +
|
||||
pow_a_n * rolloff * (float) cos( (maxh - 1) * angle );
|
||||
float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
|
||||
float dsf = num / den;
|
||||
kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - (float) 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
/* apply blackman window and find sum */
|
||||
sum = 0;
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
float x = PI * 2 / (kernel_half * 2) * i;
|
||||
float blackman = 0.42f - 0.5f * (float) cos( x ) + 0.08f * (float) cos( x * 2 );
|
||||
sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman);
|
||||
}
|
||||
|
||||
/* normalize kernel */
|
||||
sum = 1.0f / sum;
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
int x = kernel_size * 3 / 2 - kernel_half + i;
|
||||
kernels [x] *= sum;
|
||||
assert( kernels [x] == kernels [x] ); /* catch numerical instability */
|
||||
}
|
||||
}
|
||||
/* generate luma (y) filter using sinc kernel */
|
||||
{
|
||||
/* sinc with rolloff (dsf) */
|
||||
float const rolloff = 1 + (float) setup->sharpness * (float) 0.032;
|
||||
float const maxh = 32;
|
||||
float const pow_a_n = (float) pow( rolloff, maxh );
|
||||
float sum;
|
||||
int i;
|
||||
/* quadratic mapping to reduce negative (blurring) range */
|
||||
float to_angle = (float) setup->resolution + 1;
|
||||
to_angle = PI / maxh * (float) LUMA_CUTOFF * (to_angle * to_angle + 1);
|
||||
|
||||
kernels [kernel_size * 3 / 2] = maxh; /* default center value */
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
int x = i - kernel_half;
|
||||
float angle = x * to_angle;
|
||||
/* instability occurs at center point with rolloff very close to 1.0 */
|
||||
if ( x || pow_a_n > (float) 1.056 || pow_a_n < (float) 0.981 )
|
||||
{
|
||||
float rolloff_cos_a = rolloff * (float) cos( angle );
|
||||
float num = 1 - rolloff_cos_a -
|
||||
pow_a_n * (float) cos( maxh * angle ) +
|
||||
pow_a_n * rolloff * (float) cos( (maxh - 1) * angle );
|
||||
float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
|
||||
float dsf = num / den;
|
||||
kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - (float) 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
/* apply blackman window and find sum */
|
||||
sum = 0;
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
float x = PI * 2 / (kernel_half * 2) * i;
|
||||
float blackman = 0.42f - 0.5f * (float) cos( x ) + 0.08f * (float) cos( x * 2 );
|
||||
sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman);
|
||||
}
|
||||
|
||||
/* normalize kernel */
|
||||
sum = 1.0f / sum;
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
int x = kernel_size * 3 / 2 - kernel_half + i;
|
||||
kernels [x] *= sum;
|
||||
assert( kernels [x] == kernels [x] ); /* catch numerical instability */
|
||||
}
|
||||
}
|
||||
|
||||
/* generate chroma (iq) filter using gaussian kernel */
|
||||
{
|
||||
float const cutoff_factor = -0.03125f;
|
||||
float cutoff = (float) setup->bleed;
|
||||
int i;
|
||||
|
||||
if ( cutoff < 0 )
|
||||
{
|
||||
/* keep extreme value accessible only near upper end of scale (1.0) */
|
||||
cutoff *= cutoff;
|
||||
cutoff *= cutoff;
|
||||
cutoff *= cutoff;
|
||||
cutoff *= -30.0f / 0.65f;
|
||||
}
|
||||
cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff;
|
||||
|
||||
for ( i = -kernel_half; i <= kernel_half; i++ )
|
||||
kernels [kernel_size / 2 + i] = (float) exp( i * i * cutoff );
|
||||
|
||||
/* normalize even and odd phases separately */
|
||||
for ( i = 0; i < 2; i++ )
|
||||
{
|
||||
float sum = 0;
|
||||
int x;
|
||||
for ( x = i; x < kernel_size; x += 2 )
|
||||
sum += kernels [x];
|
||||
|
||||
sum = 1.0f / sum;
|
||||
for ( x = i; x < kernel_size; x += 2 )
|
||||
{
|
||||
kernels [x] *= sum;
|
||||
assert( kernels [x] == kernels [x] ); /* catch numerical instability */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
printf( "luma:\n" );
|
||||
for ( i = kernel_size; i < kernel_size * 2; i++ )
|
||||
printf( "%f\n", kernels [i] );
|
||||
printf( "chroma:\n" );
|
||||
for ( i = 0; i < kernel_size; i++ )
|
||||
printf( "%f\n", kernels [i] );
|
||||
*/
|
||||
|
||||
/* generate linear rescale kernels */
|
||||
#if rescale_out > 1
|
||||
{
|
||||
float weight = 1.0f;
|
||||
float* out = impl->kernel;
|
||||
int n = rescale_out;
|
||||
do
|
||||
{
|
||||
float remain = 0;
|
||||
int i;
|
||||
weight -= 1.0f / rescale_in;
|
||||
for ( i = 0; i < kernel_size * 2; i++ )
|
||||
{
|
||||
float cur = kernels [i];
|
||||
float m = cur * weight;
|
||||
*out++ = m + remain;
|
||||
remain = cur - m;
|
||||
}
|
||||
}
|
||||
while ( --n );
|
||||
}
|
||||
#endif
|
||||
/* generate chroma (iq) filter using gaussian kernel */
|
||||
{
|
||||
float const cutoff_factor = -0.03125f;
|
||||
float cutoff = (float) setup->bleed;
|
||||
int i;
|
||||
|
||||
if ( cutoff < 0 )
|
||||
{
|
||||
/* keep extreme value accessible only near upper end of scale (1.0) */
|
||||
cutoff *= cutoff;
|
||||
cutoff *= cutoff;
|
||||
cutoff *= cutoff;
|
||||
cutoff *= -30.0f / 0.65f;
|
||||
}
|
||||
cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff;
|
||||
|
||||
for ( i = -kernel_half; i <= kernel_half; i++ )
|
||||
kernels [kernel_size / 2 + i] = (float) exp( i * i * cutoff );
|
||||
|
||||
/* normalize even and odd phases separately */
|
||||
for ( i = 0; i < 2; i++ )
|
||||
{
|
||||
float sum = 0;
|
||||
int x;
|
||||
for ( x = i; x < kernel_size; x += 2 )
|
||||
sum += kernels [x];
|
||||
|
||||
sum = 1.0f / sum;
|
||||
for ( x = i; x < kernel_size; x += 2 )
|
||||
{
|
||||
kernels [x] *= sum;
|
||||
assert( kernels [x] == kernels [x] ); /* catch numerical instability */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
printf( "luma:\n" );
|
||||
for ( i = kernel_size; i < kernel_size * 2; i++ )
|
||||
printf( "%f\n", kernels [i] );
|
||||
printf( "chroma:\n" );
|
||||
for ( i = 0; i < kernel_size; i++ )
|
||||
printf( "%f\n", kernels [i] );
|
||||
*/
|
||||
|
||||
/* generate linear rescale kernels */
|
||||
#if rescale_out > 1
|
||||
{
|
||||
float weight = 1.0f;
|
||||
float* out = impl->kernel;
|
||||
int n = rescale_out;
|
||||
do
|
||||
{
|
||||
float remain = 0;
|
||||
int i;
|
||||
weight -= 1.0f / rescale_in;
|
||||
for ( i = 0; i < kernel_size * 2; i++ )
|
||||
{
|
||||
float cur = kernels [i];
|
||||
float m = cur * weight;
|
||||
*out++ = m + remain;
|
||||
remain = cur - m;
|
||||
}
|
||||
}
|
||||
while ( --n );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static float const default_decoder [6] =
|
||||
{ 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f };
|
||||
{ 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f };
|
||||
|
||||
static void init( init_t* impl, sms_ntsc_setup_t const* setup )
|
||||
{
|
||||
impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset;
|
||||
impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit;
|
||||
#ifdef default_palette_contrast
|
||||
if ( !setup->palette )
|
||||
impl->contrast *= default_palette_contrast;
|
||||
#endif
|
||||
|
||||
impl->artifacts = (float) setup->artifacts;
|
||||
if ( impl->artifacts > 0 )
|
||||
impl->artifacts *= artifacts_max - artifacts_mid;
|
||||
impl->artifacts = impl->artifacts * artifacts_mid + artifacts_mid;
|
||||
impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset;
|
||||
impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit;
|
||||
#ifdef default_palette_contrast
|
||||
if ( !setup->palette )
|
||||
impl->contrast *= default_palette_contrast;
|
||||
#endif
|
||||
|
||||
impl->artifacts = (float) setup->artifacts;
|
||||
if ( impl->artifacts > 0 )
|
||||
impl->artifacts *= artifacts_max - artifacts_mid;
|
||||
impl->artifacts = impl->artifacts * artifacts_mid + artifacts_mid;
|
||||
|
||||
impl->fringing = (float) setup->fringing;
|
||||
if ( impl->fringing > 0 )
|
||||
impl->fringing *= fringing_max - fringing_mid;
|
||||
impl->fringing = impl->fringing * fringing_mid + fringing_mid;
|
||||
|
||||
init_filters( impl, setup );
|
||||
|
||||
/* generate gamma table */
|
||||
if ( gamma_size > 1 )
|
||||
{
|
||||
float const to_float = 1.0f / (gamma_size - (gamma_size > 1));
|
||||
float const gamma = 1.1333f - (float) setup->gamma * 0.5f;
|
||||
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
|
||||
int i;
|
||||
for ( i = 0; i < gamma_size; i++ )
|
||||
impl->to_float [i] =
|
||||
(float) pow( i * to_float, gamma ) * impl->contrast + impl->brightness;
|
||||
}
|
||||
|
||||
/* setup decoder matricies */
|
||||
{
|
||||
float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue;
|
||||
float sat = (float) setup->saturation + 1;
|
||||
float const* decoder = setup->decoder_matrix;
|
||||
if ( !decoder )
|
||||
{
|
||||
decoder = default_decoder;
|
||||
if ( STD_HUE_CONDITION( setup ) )
|
||||
hue += PI / 180 * (std_decoder_hue - ext_decoder_hue);
|
||||
}
|
||||
|
||||
{
|
||||
float s = (float) sin( hue ) * sat;
|
||||
float c = (float) cos( hue ) * sat;
|
||||
float* out = impl->to_rgb;
|
||||
int n;
|
||||
|
||||
n = burst_count;
|
||||
do
|
||||
{
|
||||
float const* in = decoder;
|
||||
int n = 3;
|
||||
do
|
||||
{
|
||||
float i = *in++;
|
||||
float q = *in++;
|
||||
*out++ = i * c - q * s;
|
||||
*out++ = i * s + q * c;
|
||||
}
|
||||
while ( --n );
|
||||
if ( burst_count <= 1 )
|
||||
break;
|
||||
ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */
|
||||
}
|
||||
while ( --n );
|
||||
}
|
||||
}
|
||||
impl->fringing = (float) setup->fringing;
|
||||
if ( impl->fringing > 0 )
|
||||
impl->fringing *= fringing_max - fringing_mid;
|
||||
impl->fringing = impl->fringing * fringing_mid + fringing_mid;
|
||||
|
||||
init_filters( impl, setup );
|
||||
|
||||
/* generate gamma table */
|
||||
if ( gamma_size > 1 )
|
||||
{
|
||||
float const to_float = 1.0f / (gamma_size - (gamma_size > 1));
|
||||
float const gamma = 1.1333f - (float) setup->gamma * 0.5f;
|
||||
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
|
||||
int i;
|
||||
for ( i = 0; i < gamma_size; i++ )
|
||||
impl->to_float [i] =
|
||||
(float) pow( i * to_float, gamma ) * impl->contrast + impl->brightness;
|
||||
}
|
||||
|
||||
/* setup decoder matricies */
|
||||
{
|
||||
float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue;
|
||||
float sat = (float) setup->saturation + 1;
|
||||
float const* decoder = setup->decoder_matrix;
|
||||
if ( !decoder )
|
||||
{
|
||||
decoder = default_decoder;
|
||||
if ( STD_HUE_CONDITION( setup ) )
|
||||
hue += PI / 180 * (std_decoder_hue - ext_decoder_hue);
|
||||
}
|
||||
|
||||
{
|
||||
float s = (float) sin( hue ) * sat;
|
||||
float c = (float) cos( hue ) * sat;
|
||||
float* out = impl->to_rgb;
|
||||
int n;
|
||||
|
||||
n = burst_count;
|
||||
do
|
||||
{
|
||||
float const* in = decoder;
|
||||
int n = 3;
|
||||
do
|
||||
{
|
||||
float i = *in++;
|
||||
float q = *in++;
|
||||
*out++ = i * c - q * s;
|
||||
*out++ = i * s + q * c;
|
||||
}
|
||||
while ( --n );
|
||||
if ( burst_count <= 1 )
|
||||
break;
|
||||
ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */
|
||||
}
|
||||
while ( --n );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* kernel generation */
|
||||
|
||||
#define RGB_TO_YIQ( r, g, b, y, i ) (\
|
||||
(y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\
|
||||
(i = (r) * 0.596f - (g) * 0.275f - (b) * 0.321f),\
|
||||
((r) * 0.212f - (g) * 0.523f + (b) * 0.311f)\
|
||||
(y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\
|
||||
(i = (r) * 0.596f - (g) * 0.275f - (b) * 0.321f),\
|
||||
((r) * 0.212f - (g) * 0.523f + (b) * 0.311f)\
|
||||
)
|
||||
|
||||
#define YIQ_TO_RGB( y, i, q, to_rgb, type, r, g ) (\
|
||||
r = (type) (y + to_rgb [0] * i + to_rgb [1] * q),\
|
||||
g = (type) (y + to_rgb [2] * i + to_rgb [3] * q),\
|
||||
(type) (y + to_rgb [4] * i + to_rgb [5] * q)\
|
||||
r = (type) (y + to_rgb [0] * i + to_rgb [1] * q),\
|
||||
g = (type) (y + to_rgb [2] * i + to_rgb [3] * q),\
|
||||
(type) (y + to_rgb [4] * i + to_rgb [5] * q)\
|
||||
)
|
||||
|
||||
#define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1)
|
||||
@ -289,24 +289,24 @@ enum { rgb_bias = rgb_unit * 2 * sms_ntsc_rgb_builder };
|
||||
|
||||
typedef struct pixel_info_t
|
||||
{
|
||||
int offset;
|
||||
float negate;
|
||||
float kernel [4];
|
||||
int offset;
|
||||
float negate;
|
||||
float kernel [4];
|
||||
} pixel_info_t;
|
||||
|
||||
#if rescale_in > 1
|
||||
#define PIXEL_OFFSET_( ntsc, scaled ) \
|
||||
(kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \
|
||||
(kernel_size * 2 * scaled))
|
||||
#define PIXEL_OFFSET_( ntsc, scaled ) \
|
||||
(kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \
|
||||
(kernel_size * 2 * scaled))
|
||||
|
||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
||||
PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\
|
||||
(((scaled) + rescale_out * 10) % rescale_out) ),\
|
||||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
||||
PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\
|
||||
(((scaled) + rescale_out * 10) % rescale_out) ),\
|
||||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#else
|
||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
||||
(kernel_size / 2 + (ntsc) - (scaled)),\
|
||||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
||||
(kernel_size / 2 + (ntsc) - (scaled)),\
|
||||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#endif
|
||||
|
||||
extern pixel_info_t const sms_ntsc_pixels [alignment_count];
|
||||
@ -314,126 +314,126 @@ extern pixel_info_t const sms_ntsc_pixels [alignment_count];
|
||||
/* Generate pixel at all burst phases and column alignments */
|
||||
static void gen_kernel( init_t* impl, float y, float i, float q, sms_ntsc_rgb_t* out )
|
||||
{
|
||||
/* generate for each scanline burst phase */
|
||||
float const* to_rgb = impl->to_rgb;
|
||||
int burst_remain = burst_count;
|
||||
y -= rgb_offset;
|
||||
do
|
||||
{
|
||||
/* Encode yiq into *two* composite signals (to allow control over artifacting).
|
||||
Convolve these with kernels which: filter respective components, apply
|
||||
sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack
|
||||
into integer. Based on algorithm by NewRisingSun. */
|
||||
pixel_info_t const* pixel = sms_ntsc_pixels;
|
||||
int alignment_remain = alignment_count;
|
||||
do
|
||||
{
|
||||
/* negate is -1 when composite starts at odd multiple of 2 */
|
||||
float const yy = y * impl->fringing * pixel->negate;
|
||||
float const ic0 = (i + yy) * pixel->kernel [0];
|
||||
float const qc1 = (q + yy) * pixel->kernel [1];
|
||||
float const ic2 = (i - yy) * pixel->kernel [2];
|
||||
float const qc3 = (q - yy) * pixel->kernel [3];
|
||||
|
||||
float const factor = impl->artifacts * pixel->negate;
|
||||
float const ii = i * factor;
|
||||
float const yc0 = (y + ii) * pixel->kernel [0];
|
||||
float const yc2 = (y - ii) * pixel->kernel [2];
|
||||
|
||||
float const qq = q * factor;
|
||||
float const yc1 = (y + qq) * pixel->kernel [1];
|
||||
float const yc3 = (y - qq) * pixel->kernel [3];
|
||||
|
||||
float const* k = &impl->kernel [pixel->offset];
|
||||
int n;
|
||||
++pixel;
|
||||
for ( n = rgb_kernel_size; n; --n )
|
||||
{
|
||||
float i = k[0]*ic0 + k[2]*ic2;
|
||||
float q = k[1]*qc1 + k[3]*qc3;
|
||||
float y = k[kernel_size+0]*yc0 + k[kernel_size+1]*yc1 +
|
||||
k[kernel_size+2]*yc2 + k[kernel_size+3]*yc3 + rgb_offset;
|
||||
if ( rescale_out <= 1 )
|
||||
k--;
|
||||
else if ( k < &impl->kernel [kernel_size * 2 * (rescale_out - 1)] )
|
||||
k += kernel_size * 2 - 1;
|
||||
else
|
||||
k -= kernel_size * 2 * (rescale_out - 1) + 2;
|
||||
{
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, to_rgb, int, r, g );
|
||||
*out++ = PACK_RGB( r, g, b ) - rgb_bias;
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( alignment_count > 1 && --alignment_remain );
|
||||
|
||||
if ( burst_count <= 1 )
|
||||
break;
|
||||
|
||||
to_rgb += 6;
|
||||
|
||||
ROTATE_IQ( i, q, -0.866025f, -0.5f ); /* -120 degrees */
|
||||
}
|
||||
while ( --burst_remain );
|
||||
/* generate for each scanline burst phase */
|
||||
float const* to_rgb = impl->to_rgb;
|
||||
int burst_remain = burst_count;
|
||||
y -= rgb_offset;
|
||||
do
|
||||
{
|
||||
/* Encode yiq into *two* composite signals (to allow control over artifacting).
|
||||
Convolve these with kernels which: filter respective components, apply
|
||||
sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack
|
||||
into integer. Based on algorithm by NewRisingSun. */
|
||||
pixel_info_t const* pixel = sms_ntsc_pixels;
|
||||
int alignment_remain = alignment_count;
|
||||
do
|
||||
{
|
||||
/* negate is -1 when composite starts at odd multiple of 2 */
|
||||
float const yy = y * impl->fringing * pixel->negate;
|
||||
float const ic0 = (i + yy) * pixel->kernel [0];
|
||||
float const qc1 = (q + yy) * pixel->kernel [1];
|
||||
float const ic2 = (i - yy) * pixel->kernel [2];
|
||||
float const qc3 = (q - yy) * pixel->kernel [3];
|
||||
|
||||
float const factor = impl->artifacts * pixel->negate;
|
||||
float const ii = i * factor;
|
||||
float const yc0 = (y + ii) * pixel->kernel [0];
|
||||
float const yc2 = (y - ii) * pixel->kernel [2];
|
||||
|
||||
float const qq = q * factor;
|
||||
float const yc1 = (y + qq) * pixel->kernel [1];
|
||||
float const yc3 = (y - qq) * pixel->kernel [3];
|
||||
|
||||
float const* k = &impl->kernel [pixel->offset];
|
||||
int n;
|
||||
++pixel;
|
||||
for ( n = rgb_kernel_size; n; --n )
|
||||
{
|
||||
float i = k[0]*ic0 + k[2]*ic2;
|
||||
float q = k[1]*qc1 + k[3]*qc3;
|
||||
float y = k[kernel_size+0]*yc0 + k[kernel_size+1]*yc1 +
|
||||
k[kernel_size+2]*yc2 + k[kernel_size+3]*yc3 + rgb_offset;
|
||||
if ( rescale_out <= 1 )
|
||||
k--;
|
||||
else if ( k < &impl->kernel [kernel_size * 2 * (rescale_out - 1)] )
|
||||
k += kernel_size * 2 - 1;
|
||||
else
|
||||
k -= kernel_size * 2 * (rescale_out - 1) + 2;
|
||||
{
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, to_rgb, int, r, g );
|
||||
*out++ = PACK_RGB( r, g, b ) - rgb_bias;
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( alignment_count > 1 && --alignment_remain );
|
||||
|
||||
if ( burst_count <= 1 )
|
||||
break;
|
||||
|
||||
to_rgb += 6;
|
||||
|
||||
ROTATE_IQ( i, q, -0.866025f, -0.5f ); /* -120 degrees */
|
||||
}
|
||||
while ( --burst_remain );
|
||||
}
|
||||
|
||||
static void correct_errors( sms_ntsc_rgb_t color, sms_ntsc_rgb_t* out );
|
||||
|
||||
#if DISABLE_CORRECTION
|
||||
#define CORRECT_ERROR( a ) { out [i] += rgb_bias; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) { out [i] += rgb_bias; }
|
||||
#define CORRECT_ERROR( a ) { out [i] += rgb_bias; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) { out [i] += rgb_bias; }
|
||||
#else
|
||||
#define CORRECT_ERROR( a ) { out [a] += error; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) {\
|
||||
sms_ntsc_rgb_t fourth = (error + 2 * sms_ntsc_rgb_builder) >> 2;\
|
||||
fourth &= (rgb_bias >> 1) - sms_ntsc_rgb_builder;\
|
||||
fourth -= rgb_bias >> 2;\
|
||||
out [a] += fourth;\
|
||||
out [b] += fourth;\
|
||||
out [c] += fourth;\
|
||||
out [i] += error - (fourth * 3);\
|
||||
}
|
||||
#define CORRECT_ERROR( a ) { out [a] += error; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) {\
|
||||
sms_ntsc_rgb_t fourth = (error + 2 * sms_ntsc_rgb_builder) >> 2;\
|
||||
fourth &= (rgb_bias >> 1) - sms_ntsc_rgb_builder;\
|
||||
fourth -= rgb_bias >> 2;\
|
||||
out [a] += fourth;\
|
||||
out [b] += fourth;\
|
||||
out [c] += fourth;\
|
||||
out [i] += error - (fourth * 3);\
|
||||
}
|
||||
#endif
|
||||
|
||||
#define RGB_PALETTE_OUT( rgb, out_ )\
|
||||
{\
|
||||
unsigned char* out = (out_);\
|
||||
sms_ntsc_rgb_t clamped = (rgb);\
|
||||
SMS_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\
|
||||
out [0] = (unsigned char) (clamped >> 21);\
|
||||
out [1] = (unsigned char) (clamped >> 11);\
|
||||
out [2] = (unsigned char) (clamped >> 1);\
|
||||
unsigned char* out = (out_);\
|
||||
sms_ntsc_rgb_t clamped = (rgb);\
|
||||
SMS_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\
|
||||
out [0] = (unsigned char) (clamped >> 21);\
|
||||
out [1] = (unsigned char) (clamped >> 11);\
|
||||
out [2] = (unsigned char) (clamped >> 1);\
|
||||
}
|
||||
|
||||
/* blitter related */
|
||||
|
||||
#ifndef restrict
|
||||
#if defined (__GNUC__)
|
||||
#define restrict __restrict__
|
||||
#elif defined (_MSC_VER) && _MSC_VER > 1300
|
||||
#define restrict __restrict
|
||||
#else
|
||||
/* no support for restricted pointers */
|
||||
#define restrict
|
||||
#endif
|
||||
#if defined (__GNUC__)
|
||||
#define restrict __restrict__
|
||||
#elif defined (_MSC_VER) && _MSC_VER > 1300
|
||||
#define restrict __restrict
|
||||
#else
|
||||
/* no support for restricted pointers */
|
||||
#define restrict
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if SMS_NTSC_OUT_DEPTH <= 16
|
||||
#if USHRT_MAX == 0xFFFF
|
||||
typedef unsigned short sms_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 16-bit int type"
|
||||
#endif
|
||||
#if USHRT_MAX == 0xFFFF
|
||||
typedef unsigned short sms_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 16-bit int type"
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if UINT_MAX == 0xFFFFFFFF
|
||||
typedef unsigned int sms_ntsc_out_t;
|
||||
#elif ULONG_MAX == 0xFFFFFFFF
|
||||
typedef unsigned long sms_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 32-bit int type"
|
||||
#endif
|
||||
#if UINT_MAX == 0xFFFFFFFF
|
||||
typedef unsigned int sms_ntsc_out_t;
|
||||
#elif ULONG_MAX == 0xFFFFFFFF
|
||||
typedef unsigned long sms_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 32-bit int type"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,12 +1,12 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
|
@ -22,8 +22,8 @@ Win32
|
||||
There are detailed instructions for building libsamplerate on Win32
|
||||
in the file
|
||||
|
||||
doc/win32.html
|
||||
|
||||
doc/win32.html
|
||||
|
||||
|
||||
MacOSX
|
||||
------
|
||||
@ -36,15 +36,15 @@ OTHER PLATFORMS
|
||||
To compile libsamplerate on platforms which have a Bourne Shell compatible
|
||||
shell, an ANSI C compiler and a make utility should require no more that
|
||||
the following three commands :
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
CONTACTS
|
||||
--------
|
||||
|
||||
libsamplerate was written by Erik de Castro Lopo (erikd AT mega-nerd DOT com).
|
||||
The libsamplerate home page is at :
|
||||
|
||||
http://www.mega-nerd.com/libsamplerate/
|
||||
http://www.mega-nerd.com/libsamplerate/
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
|
||||
** use license for this code is available, please see:
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H_INCLUDED
|
||||
@ -28,87 +28,87 @@
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif (SIZEOF_INT == 4)
|
||||
typedef int int32_t ;
|
||||
typedef int int32_t ;
|
||||
#elif (SIZEOF_LONG == 4)
|
||||
typedef long int32_t ;
|
||||
typedef long int32_t ;
|
||||
#endif
|
||||
|
||||
#define SRC_MAX_RATIO 256
|
||||
#define SRC_MIN_RATIO_DIFF (1e-20)
|
||||
#define SRC_MAX_RATIO 256
|
||||
#define SRC_MIN_RATIO_DIFF (1e-20)
|
||||
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
|
||||
#define OFFSETOF(type,member) ((int) (&((type*) 0)->member))
|
||||
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
|
||||
#define OFFSETOF(type,member) ((int) (&((type*) 0)->member))
|
||||
|
||||
#define MAKE_MAGIC(a,b,c,d,e,f) ((a) + ((b) << 4) + ((c) << 8) + ((d) << 12) + ((e) << 16) + ((f) << 20))
|
||||
#define MAKE_MAGIC(a,b,c,d,e,f) ((a) + ((b) << 4) + ((c) << 8) + ((d) << 12) + ((e) << 16) + ((f) << 20))
|
||||
|
||||
|
||||
#include "samplerate.h"
|
||||
|
||||
enum
|
||||
{ SRC_FALSE = 0,
|
||||
SRC_TRUE = 1,
|
||||
{ SRC_FALSE = 0,
|
||||
SRC_TRUE = 1,
|
||||
|
||||
SRC_MODE_PROCESS = 555,
|
||||
SRC_MODE_CALLBACK = 556
|
||||
SRC_MODE_PROCESS = 555,
|
||||
SRC_MODE_CALLBACK = 556
|
||||
} ;
|
||||
|
||||
enum
|
||||
{ SRC_ERR_NO_ERROR = 0,
|
||||
{ SRC_ERR_NO_ERROR = 0,
|
||||
|
||||
SRC_ERR_MALLOC_FAILED,
|
||||
SRC_ERR_BAD_STATE,
|
||||
SRC_ERR_BAD_DATA,
|
||||
SRC_ERR_BAD_DATA_PTR,
|
||||
SRC_ERR_NO_PRIVATE,
|
||||
SRC_ERR_BAD_SRC_RATIO,
|
||||
SRC_ERR_BAD_PROC_PTR,
|
||||
SRC_ERR_SHIFT_BITS,
|
||||
SRC_ERR_FILTER_LEN,
|
||||
SRC_ERR_BAD_CONVERTER,
|
||||
SRC_ERR_BAD_CHANNEL_COUNT,
|
||||
SRC_ERR_SINC_BAD_BUFFER_LEN,
|
||||
SRC_ERR_SIZE_INCOMPATIBILITY,
|
||||
SRC_ERR_BAD_PRIV_PTR,
|
||||
SRC_ERR_BAD_SINC_STATE,
|
||||
SRC_ERR_DATA_OVERLAP,
|
||||
SRC_ERR_BAD_CALLBACK,
|
||||
SRC_ERR_BAD_MODE,
|
||||
SRC_ERR_NULL_CALLBACK,
|
||||
SRC_ERR_NO_VARIABLE_RATIO,
|
||||
SRC_ERR_MALLOC_FAILED,
|
||||
SRC_ERR_BAD_STATE,
|
||||
SRC_ERR_BAD_DATA,
|
||||
SRC_ERR_BAD_DATA_PTR,
|
||||
SRC_ERR_NO_PRIVATE,
|
||||
SRC_ERR_BAD_SRC_RATIO,
|
||||
SRC_ERR_BAD_PROC_PTR,
|
||||
SRC_ERR_SHIFT_BITS,
|
||||
SRC_ERR_FILTER_LEN,
|
||||
SRC_ERR_BAD_CONVERTER,
|
||||
SRC_ERR_BAD_CHANNEL_COUNT,
|
||||
SRC_ERR_SINC_BAD_BUFFER_LEN,
|
||||
SRC_ERR_SIZE_INCOMPATIBILITY,
|
||||
SRC_ERR_BAD_PRIV_PTR,
|
||||
SRC_ERR_BAD_SINC_STATE,
|
||||
SRC_ERR_DATA_OVERLAP,
|
||||
SRC_ERR_BAD_CALLBACK,
|
||||
SRC_ERR_BAD_MODE,
|
||||
SRC_ERR_NULL_CALLBACK,
|
||||
SRC_ERR_NO_VARIABLE_RATIO,
|
||||
|
||||
/* This must be the last error number. */
|
||||
SRC_ERR_MAX_ERROR
|
||||
/* This must be the last error number. */
|
||||
SRC_ERR_MAX_ERROR
|
||||
} ;
|
||||
|
||||
typedef struct SRC_PRIVATE_tag
|
||||
{ double last_ratio, last_position ;
|
||||
{ double last_ratio, last_position ;
|
||||
|
||||
int error ;
|
||||
int channels ;
|
||||
int error ;
|
||||
int channels ;
|
||||
|
||||
/* SRC_MODE_PROCESS or SRC_MODE_CALLBACK */
|
||||
int mode ;
|
||||
/* SRC_MODE_PROCESS or SRC_MODE_CALLBACK */
|
||||
int mode ;
|
||||
|
||||
/* Pointer to data to converter specific data. */
|
||||
void *private_data ;
|
||||
/* Pointer to data to converter specific data. */
|
||||
void *private_data ;
|
||||
|
||||
/* Varispeed process function. */
|
||||
int (*vari_process) (struct SRC_PRIVATE_tag *psrc, SRC_DATA *data) ;
|
||||
/* Varispeed process function. */
|
||||
int (*vari_process) (struct SRC_PRIVATE_tag *psrc, SRC_DATA *data) ;
|
||||
|
||||
/* Constant speed process function. */
|
||||
int (*const_process) (struct SRC_PRIVATE_tag *psrc, SRC_DATA *data) ;
|
||||
/* Constant speed process function. */
|
||||
int (*const_process) (struct SRC_PRIVATE_tag *psrc, SRC_DATA *data) ;
|
||||
|
||||
/* State reset. */
|
||||
void (*reset) (struct SRC_PRIVATE_tag *psrc) ;
|
||||
/* State reset. */
|
||||
void (*reset) (struct SRC_PRIVATE_tag *psrc) ;
|
||||
|
||||
/* Data specific to SRC_MODE_CALLBACK. */
|
||||
src_callback_t callback_func ;
|
||||
void *user_callback_data ;
|
||||
long saved_frames ;
|
||||
float *saved_data ;
|
||||
/* Data specific to SRC_MODE_CALLBACK. */
|
||||
src_callback_t callback_func ;
|
||||
void *user_callback_data ;
|
||||
long saved_frames ;
|
||||
float *saved_data ;
|
||||
} SRC_PRIVATE ;
|
||||
|
||||
/* In src_sinc.c */
|
||||
@ -130,19 +130,19 @@ const char* zoh_get_description (int src_enum) ;
|
||||
int zoh_set_converter (SRC_PRIVATE *psrc, int src_enum) ;
|
||||
|
||||
/*----------------------------------------------------------
|
||||
** Common static inline functions.
|
||||
** Common static inline functions.
|
||||
*/
|
||||
|
||||
static inline double
|
||||
fmod_one (double x)
|
||||
{ double res ;
|
||||
{ double res ;
|
||||
|
||||
res = x - lrint (x) ;
|
||||
if (res < 0.0)
|
||||
return res + 1.0 ;
|
||||
res = x - lrint (x) ;
|
||||
if (res < 0.0)
|
||||
return res + 1.0 ;
|
||||
|
||||
return res ;
|
||||
return res ;
|
||||
} /* fmod_one */
|
||||
|
||||
#endif /* COMMON_H_INCLUDED */
|
||||
#endif /* COMMON_H_INCLUDED */
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
|
||||
** use license for this code is available, please see:
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -32,10 +32,10 @@
|
||||
*/
|
||||
|
||||
static const struct fastest_coeffs_s
|
||||
{ int increment ;
|
||||
coeff_t coeffs [2464] ;
|
||||
{ int increment ;
|
||||
coeff_t coeffs [2464] ;
|
||||
} fastest_coeffs =
|
||||
{ 128,
|
||||
{ 128,
|
||||
{
|
||||
8.31472372954840555082e-01,
|
||||
8.31414005540308198583e-01,
|
||||
@ -2500,6 +2500,6 @@ static const struct fastest_coeffs_s
|
||||
-3.59691078491283933177e-07,
|
||||
-2.38952398011216803052e-07,
|
||||
-1.22889677382464548894e-07,
|
||||
0.0 /* Need a final zero coefficient */
|
||||
0.0 /* Need a final zero coefficient */
|
||||
}
|
||||
} ; /* fastest_coeffs */
|
||||
|
@ -22,231 +22,231 @@
|
||||
#define FLOAT_CAST_HEADER
|
||||
|
||||
/*============================================================================
|
||||
** On Intel Pentium processors (especially PIII and probably P4), converting
|
||||
** from float to int is very slow. To meet the C specs, the code produced by
|
||||
** most C compilers targeting Pentium needs to change the FPU rounding mode
|
||||
** before the float to int conversion is performed.
|
||||
** On Intel Pentium processors (especially PIII and probably P4), converting
|
||||
** from float to int is very slow. To meet the C specs, the code produced by
|
||||
** most C compilers targeting Pentium needs to change the FPU rounding mode
|
||||
** before the float to int conversion is performed.
|
||||
**
|
||||
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
|
||||
** is this flushing of the pipeline which is so slow.
|
||||
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
|
||||
** is this flushing of the pipeline which is so slow.
|
||||
**
|
||||
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
|
||||
** llrint and llrintf which fix this problem as a side effect.
|
||||
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
|
||||
** llrint and llrintf which fix this problem as a side effect.
|
||||
**
|
||||
** On Unix-like systems, the configure process should have detected the
|
||||
** presence of these functions. If they weren't found we have to replace them
|
||||
** here with a standard C cast.
|
||||
** On Unix-like systems, the configure process should have detected the
|
||||
** presence of these functions. If they weren't found we have to replace them
|
||||
** here with a standard C cast.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The C99 prototypes for lrint and lrintf are as follows:
|
||||
** The C99 prototypes for lrint and lrintf are as follows:
|
||||
**
|
||||
** long int lrintf (float x) ;
|
||||
** long int lrint (double x) ;
|
||||
** long int lrintf (float x) ;
|
||||
** long int lrint (double x) ;
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/*
|
||||
** The presence of the required functions are detected during the configure
|
||||
** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
|
||||
** the config.h file.
|
||||
** The presence of the required functions are detected during the configure
|
||||
** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
|
||||
** the config.h file.
|
||||
*/
|
||||
|
||||
#define HAVE_LRINT_REPLACEMENT 0
|
||||
#define HAVE_LRINT_REPLACEMENT 0
|
||||
|
||||
#if (HAVE_LRINT && HAVE_LRINTF)
|
||||
|
||||
/*
|
||||
** These defines enable functionality introduced with the 1999 ISO C
|
||||
** standard. They must be defined before the inclusion of math.h to
|
||||
** engage them. If optimisation is enabled, these functions will be
|
||||
** inlined. With optimisation switched off, you have to link in the
|
||||
** maths library using -lm.
|
||||
*/
|
||||
/*
|
||||
** These defines enable functionality introduced with the 1999 ISO C
|
||||
** standard. They must be defined before the inclusion of math.h to
|
||||
** engage them. If optimisation is enabled, these functions will be
|
||||
** inlined. With optimisation switched off, you have to link in the
|
||||
** maths library using -lm.
|
||||
*/
|
||||
|
||||
#define _ISOC9X_SOURCE 1
|
||||
#define _ISOC99_SOURCE 1
|
||||
#define _ISOC9X_SOURCE 1
|
||||
#define _ISOC99_SOURCE 1
|
||||
|
||||
#define __USE_ISOC9X 1
|
||||
#define __USE_ISOC99 1
|
||||
#define __USE_ISOC9X 1
|
||||
#define __USE_ISOC99 1
|
||||
|
||||
#include <math.h>
|
||||
#include <math.h>
|
||||
|
||||
#elif (defined (__CYGWIN__))
|
||||
|
||||
#include <math.h>
|
||||
#include <math.h>
|
||||
|
||||
#undef HAVE_LRINT_REPLACEMENT
|
||||
#define HAVE_LRINT_REPLACEMENT 1
|
||||
#undef HAVE_LRINT_REPLACEMENT
|
||||
#define HAVE_LRINT_REPLACEMENT 1
|
||||
|
||||
#undef lrint
|
||||
#undef lrintf
|
||||
#undef lrint
|
||||
#undef lrintf
|
||||
|
||||
#define lrint double2int
|
||||
#define lrintf float2int
|
||||
#define lrint double2int
|
||||
#define lrintf float2int
|
||||
|
||||
/*
|
||||
** The native CYGWIN lrint and lrintf functions are buggy:
|
||||
** http://sourceware.org/ml/cygwin/2005-06/msg00153.html
|
||||
** http://sourceware.org/ml/cygwin/2005-09/msg00047.html
|
||||
** and slow.
|
||||
** These functions (pulled from the Public Domain MinGW math.h header)
|
||||
** replace the native versions.
|
||||
*/
|
||||
/*
|
||||
** The native CYGWIN lrint and lrintf functions are buggy:
|
||||
** http://sourceware.org/ml/cygwin/2005-06/msg00153.html
|
||||
** http://sourceware.org/ml/cygwin/2005-09/msg00047.html
|
||||
** and slow.
|
||||
** These functions (pulled from the Public Domain MinGW math.h header)
|
||||
** replace the native versions.
|
||||
*/
|
||||
|
||||
static inline long double2int (double in)
|
||||
{ long retval ;
|
||||
static inline long double2int (double in)
|
||||
{ long retval ;
|
||||
|
||||
__asm__ __volatile__
|
||||
( "fistpl %0"
|
||||
: "=m" (retval)
|
||||
: "t" (in)
|
||||
: "st"
|
||||
) ;
|
||||
__asm__ __volatile__
|
||||
( "fistpl %0"
|
||||
: "=m" (retval)
|
||||
: "t" (in)
|
||||
: "st"
|
||||
) ;
|
||||
|
||||
return retval ;
|
||||
} /* double2int */
|
||||
return retval ;
|
||||
} /* double2int */
|
||||
|
||||
static inline long float2int (float in)
|
||||
{ long retval ;
|
||||
static inline long float2int (float in)
|
||||
{ long retval ;
|
||||
|
||||
__asm__ __volatile__
|
||||
( "fistpl %0"
|
||||
: "=m" (retval)
|
||||
: "t" (in)
|
||||
: "st"
|
||||
) ;
|
||||
__asm__ __volatile__
|
||||
( "fistpl %0"
|
||||
: "=m" (retval)
|
||||
: "t" (in)
|
||||
: "st"
|
||||
) ;
|
||||
|
||||
return retval ;
|
||||
} /* float2int */
|
||||
return retval ;
|
||||
} /* float2int */
|
||||
|
||||
#elif (defined (WIN32) || defined (_WIN32))
|
||||
|
||||
#undef HAVE_LRINT_REPLACEMENT
|
||||
#define HAVE_LRINT_REPLACEMENT 1
|
||||
#undef HAVE_LRINT_REPLACEMENT
|
||||
#define HAVE_LRINT_REPLACEMENT 1
|
||||
|
||||
#include <math.h>
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
** Win32 doesn't seem to have these functions.
|
||||
** Therefore implement inline versions of these functions here.
|
||||
*/
|
||||
/*
|
||||
** Win32 doesn't seem to have these functions.
|
||||
** Therefore implement inline versions of these functions here.
|
||||
*/
|
||||
|
||||
__inline long int
|
||||
lrint (double flt)
|
||||
{ int intgr ;
|
||||
__inline long int
|
||||
lrint (double flt)
|
||||
{ int intgr ;
|
||||
|
||||
_asm
|
||||
{ fld flt
|
||||
fistp intgr
|
||||
} ;
|
||||
_asm
|
||||
{ fld flt
|
||||
fistp intgr
|
||||
} ;
|
||||
|
||||
return intgr ;
|
||||
}
|
||||
return intgr ;
|
||||
}
|
||||
|
||||
__inline long int
|
||||
lrintf (float flt)
|
||||
{ int intgr ;
|
||||
__inline long int
|
||||
lrintf (float flt)
|
||||
{ int intgr ;
|
||||
|
||||
_asm
|
||||
{ fld flt
|
||||
fistp intgr
|
||||
} ;
|
||||
_asm
|
||||
{ fld flt
|
||||
fistp intgr
|
||||
} ;
|
||||
|
||||
return intgr ;
|
||||
}
|
||||
return intgr ;
|
||||
}
|
||||
|
||||
#elif (defined (__MWERKS__) && defined (macintosh))
|
||||
|
||||
/* This MacOS 9 solution was provided by Stephane Letz */
|
||||
/* This MacOS 9 solution was provided by Stephane Letz */
|
||||
|
||||
#undef HAVE_LRINT_REPLACEMENT
|
||||
#define HAVE_LRINT_REPLACEMENT 1
|
||||
#include <math.h>
|
||||
#undef HAVE_LRINT_REPLACEMENT
|
||||
#define HAVE_LRINT_REPLACEMENT 1
|
||||
#include <math.h>
|
||||
|
||||
#undef lrint
|
||||
#undef lrintf
|
||||
#undef lrint
|
||||
#undef lrintf
|
||||
|
||||
#define lrint double2int
|
||||
#define lrintf float2int
|
||||
#define lrint double2int
|
||||
#define lrintf float2int
|
||||
|
||||
inline int
|
||||
float2int (register float in)
|
||||
{ long res [2] ;
|
||||
inline int
|
||||
float2int (register float in)
|
||||
{ long res [2] ;
|
||||
|
||||
asm
|
||||
{ fctiw in, in
|
||||
stfd in, res
|
||||
}
|
||||
return res [1] ;
|
||||
} /* float2int */
|
||||
asm
|
||||
{ fctiw in, in
|
||||
stfd in, res
|
||||
}
|
||||
return res [1] ;
|
||||
} /* float2int */
|
||||
|
||||
inline int
|
||||
double2int (register double in)
|
||||
{ long res [2] ;
|
||||
inline int
|
||||
double2int (register double in)
|
||||
{ long res [2] ;
|
||||
|
||||
asm
|
||||
{ fctiw in, in
|
||||
stfd in, res
|
||||
}
|
||||
return res [1] ;
|
||||
} /* double2int */
|
||||
asm
|
||||
{ fctiw in, in
|
||||
stfd in, res
|
||||
}
|
||||
return res [1] ;
|
||||
} /* double2int */
|
||||
|
||||
#elif (defined (__MACH__) && defined (__APPLE__))
|
||||
|
||||
/* For Apple MacOSX. */
|
||||
/* For Apple MacOSX. */
|
||||
|
||||
#undef HAVE_LRINT_REPLACEMENT
|
||||
#define HAVE_LRINT_REPLACEMENT 1
|
||||
#include <math.h>
|
||||
#undef HAVE_LRINT_REPLACEMENT
|
||||
#define HAVE_LRINT_REPLACEMENT 1
|
||||
#include <math.h>
|
||||
|
||||
#undef lrint
|
||||
#undef lrintf
|
||||
#undef lrint
|
||||
#undef lrintf
|
||||
|
||||
#define lrint double2int
|
||||
#define lrintf float2int
|
||||
#define lrint double2int
|
||||
#define lrintf float2int
|
||||
|
||||
inline static long
|
||||
float2int (register float in)
|
||||
{ int res [2] ;
|
||||
inline static long
|
||||
float2int (register float in)
|
||||
{ int res [2] ;
|
||||
|
||||
__asm__ __volatile__
|
||||
( "fctiw %1, %1\n\t"
|
||||
"stfd %1, %0"
|
||||
: "=m" (res) /* Output */
|
||||
: "f" (in) /* Input */
|
||||
: "memory"
|
||||
) ;
|
||||
__asm__ __volatile__
|
||||
( "fctiw %1, %1\n\t"
|
||||
"stfd %1, %0"
|
||||
: "=m" (res) /* Output */
|
||||
: "f" (in) /* Input */
|
||||
: "memory"
|
||||
) ;
|
||||
|
||||
return res [1] ;
|
||||
} /* lrintf */
|
||||
return res [1] ;
|
||||
} /* lrintf */
|
||||
|
||||
inline static long
|
||||
double2int (register double in)
|
||||
{ int res [2] ;
|
||||
inline static long
|
||||
double2int (register double in)
|
||||
{ int res [2] ;
|
||||
|
||||
__asm__ __volatile__
|
||||
( "fctiw %1, %1\n\t"
|
||||
"stfd %1, %0"
|
||||
: "=m" (res) /* Output */
|
||||
: "f" (in) /* Input */
|
||||
: "memory"
|
||||
) ;
|
||||
__asm__ __volatile__
|
||||
( "fctiw %1, %1\n\t"
|
||||
"stfd %1, %0"
|
||||
: "=m" (res) /* Output */
|
||||
: "f" (in) /* Input */
|
||||
: "memory"
|
||||
) ;
|
||||
|
||||
return res [1] ;
|
||||
} /* lrint */
|
||||
return res [1] ;
|
||||
} /* lrint */
|
||||
|
||||
#else
|
||||
#ifndef __sgi
|
||||
#warning "Don't have the functions lrint() and lrintf()."
|
||||
#warning "Replacing these functions with a standard C cast."
|
||||
#endif
|
||||
#ifndef __sgi
|
||||
#warning "Don't have the functions lrint() and lrintf()."
|
||||
#warning "Replacing these functions with a standard C cast."
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <math.h>
|
||||
|
||||
#define lrint(dbl) ((long) (dbl))
|
||||
#define lrintf(flt) ((long) (flt))
|
||||
#define lrint(dbl) ((long) (dbl))
|
||||
#define lrintf(flt) ((long) (flt))
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
|
||||
** use license for this code is available, please see:
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -31,10 +31,10 @@
|
||||
** increment : 2381
|
||||
*/
|
||||
static const struct slow_high_qual_coeffs_s
|
||||
{ int increment ;
|
||||
coeff_t coeffs [340239] ;
|
||||
{ int increment ;
|
||||
coeff_t coeffs [340239] ;
|
||||
} slow_high_qual_coeffs =
|
||||
{ 2381,
|
||||
{ 2381,
|
||||
{
|
||||
9.657284235393746030e-01,
|
||||
9.657281621412726613e-01,
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
|
||||
** use license for this code is available, please see:
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -32,10 +32,10 @@
|
||||
*/
|
||||
|
||||
static const struct slow_mid_qual_coeffs_s
|
||||
{ int increment ;
|
||||
coeff_t coeffs [22438] ;
|
||||
{ int increment ;
|
||||
coeff_t coeffs [22438] ;
|
||||
} slow_mid_qual_coeffs =
|
||||
{ 491,
|
||||
{ 491,
|
||||
{
|
||||
9.190632349861385109e-01,
|
||||
9.190579273831620544e-01,
|
||||
|
@ -19,255 +19,255 @@
|
||||
/*
|
||||
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
|
||||
** use license for this code is available, please see:
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "samplerate.h"
|
||||
#include "float_cast.h"
|
||||
#include "common.h"
|
||||
#include "samplerate.h"
|
||||
#include "float_cast.h"
|
||||
#include "common.h"
|
||||
|
||||
static int psrc_set_converter (SRC_PRIVATE *psrc, int converter_type) ;
|
||||
static int psrc_set_converter (SRC_PRIVATE *psrc, int converter_type) ;
|
||||
|
||||
|
||||
static inline int
|
||||
is_bad_src_ratio (double ratio)
|
||||
{ return (ratio < (1.0 / SRC_MAX_RATIO) || ratio > (1.0 * SRC_MAX_RATIO)) ;
|
||||
{ return (ratio < (1.0 / SRC_MAX_RATIO) || ratio > (1.0 * SRC_MAX_RATIO)) ;
|
||||
} /* is_bad_src_ratio */
|
||||
|
||||
SRC_STATE *
|
||||
src_new (int converter_type, int channels, int *error)
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
|
||||
if (error)
|
||||
*error = SRC_ERR_NO_ERROR ;
|
||||
if (error)
|
||||
*error = SRC_ERR_NO_ERROR ;
|
||||
|
||||
if (channels < 1)
|
||||
{ if (error)
|
||||
*error = SRC_ERR_BAD_CHANNEL_COUNT ;
|
||||
return NULL ;
|
||||
} ;
|
||||
if (channels < 1)
|
||||
{ if (error)
|
||||
*error = SRC_ERR_BAD_CHANNEL_COUNT ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
if ((psrc = calloc (1, sizeof (*psrc))) == NULL)
|
||||
{ if (error)
|
||||
*error = SRC_ERR_MALLOC_FAILED ;
|
||||
return NULL ;
|
||||
} ;
|
||||
if ((psrc = calloc (1, sizeof (*psrc))) == NULL)
|
||||
{ if (error)
|
||||
*error = SRC_ERR_MALLOC_FAILED ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
psrc->channels = channels ;
|
||||
psrc->mode = SRC_MODE_PROCESS ;
|
||||
psrc->channels = channels ;
|
||||
psrc->mode = SRC_MODE_PROCESS ;
|
||||
|
||||
if (psrc_set_converter (psrc, converter_type) != SRC_ERR_NO_ERROR)
|
||||
{ if (error)
|
||||
*error = SRC_ERR_BAD_CONVERTER ;
|
||||
free (psrc) ;
|
||||
psrc = NULL ;
|
||||
} ;
|
||||
if (psrc_set_converter (psrc, converter_type) != SRC_ERR_NO_ERROR)
|
||||
{ if (error)
|
||||
*error = SRC_ERR_BAD_CONVERTER ;
|
||||
free (psrc) ;
|
||||
psrc = NULL ;
|
||||
} ;
|
||||
|
||||
src_reset ((SRC_STATE*) psrc) ;
|
||||
src_reset ((SRC_STATE*) psrc) ;
|
||||
|
||||
return (SRC_STATE*) psrc ;
|
||||
return (SRC_STATE*) psrc ;
|
||||
} /* src_new */
|
||||
|
||||
SRC_STATE*
|
||||
src_callback_new (src_callback_t func, int converter_type, int channels, int *error, void* cb_data)
|
||||
{ SRC_STATE *src_state ;
|
||||
{ SRC_STATE *src_state ;
|
||||
|
||||
if (func == NULL)
|
||||
{ if (error)
|
||||
*error = SRC_ERR_BAD_CALLBACK ;
|
||||
return NULL ;
|
||||
} ;
|
||||
if (func == NULL)
|
||||
{ if (error)
|
||||
*error = SRC_ERR_BAD_CALLBACK ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
if (error != NULL)
|
||||
*error = 0 ;
|
||||
if (error != NULL)
|
||||
*error = 0 ;
|
||||
|
||||
src_state = src_new (converter_type, channels, error) ;
|
||||
src_state = src_new (converter_type, channels, error) ;
|
||||
|
||||
src_reset (src_state) ;
|
||||
src_reset (src_state) ;
|
||||
|
||||
((SRC_PRIVATE*) src_state)->mode = SRC_MODE_CALLBACK ;
|
||||
((SRC_PRIVATE*) src_state)->callback_func = func ;
|
||||
((SRC_PRIVATE*) src_state)->user_callback_data = cb_data ;
|
||||
((SRC_PRIVATE*) src_state)->mode = SRC_MODE_CALLBACK ;
|
||||
((SRC_PRIVATE*) src_state)->callback_func = func ;
|
||||
((SRC_PRIVATE*) src_state)->user_callback_data = cb_data ;
|
||||
|
||||
return src_state ;
|
||||
return src_state ;
|
||||
} /* src_callback_new */
|
||||
|
||||
SRC_STATE *
|
||||
src_delete (SRC_STATE *state)
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
|
||||
psrc = (SRC_PRIVATE*) state ;
|
||||
if (psrc)
|
||||
{ if (psrc->private_data)
|
||||
free (psrc->private_data) ;
|
||||
memset (psrc, 0, sizeof (SRC_PRIVATE)) ;
|
||||
free (psrc) ;
|
||||
} ;
|
||||
psrc = (SRC_PRIVATE*) state ;
|
||||
if (psrc)
|
||||
{ if (psrc->private_data)
|
||||
free (psrc->private_data) ;
|
||||
memset (psrc, 0, sizeof (SRC_PRIVATE)) ;
|
||||
free (psrc) ;
|
||||
} ;
|
||||
|
||||
return NULL ;
|
||||
return NULL ;
|
||||
} /* src_state */
|
||||
|
||||
int
|
||||
src_process (SRC_STATE *state, SRC_DATA *data)
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
int error ;
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
int error ;
|
||||
|
||||
psrc = (SRC_PRIVATE*) state ;
|
||||
psrc = (SRC_PRIVATE*) state ;
|
||||
|
||||
if (psrc == NULL)
|
||||
return SRC_ERR_BAD_STATE ;
|
||||
if (psrc->vari_process == NULL || psrc->const_process == NULL)
|
||||
return SRC_ERR_BAD_PROC_PTR ;
|
||||
if (psrc == NULL)
|
||||
return SRC_ERR_BAD_STATE ;
|
||||
if (psrc->vari_process == NULL || psrc->const_process == NULL)
|
||||
return SRC_ERR_BAD_PROC_PTR ;
|
||||
|
||||
if (psrc->mode != SRC_MODE_PROCESS)
|
||||
return SRC_ERR_BAD_MODE ;
|
||||
if (psrc->mode != SRC_MODE_PROCESS)
|
||||
return SRC_ERR_BAD_MODE ;
|
||||
|
||||
/* Check for valid SRC_DATA first. */
|
||||
if (data == NULL)
|
||||
return SRC_ERR_BAD_DATA ;
|
||||
/* Check for valid SRC_DATA first. */
|
||||
if (data == NULL)
|
||||
return SRC_ERR_BAD_DATA ;
|
||||
|
||||
/* Check src_ratio is in range. */
|
||||
if (is_bad_src_ratio (data->src_ratio))
|
||||
return SRC_ERR_BAD_SRC_RATIO ;
|
||||
/* Check src_ratio is in range. */
|
||||
if (is_bad_src_ratio (data->src_ratio))
|
||||
return SRC_ERR_BAD_SRC_RATIO ;
|
||||
|
||||
/* And that data_in and data_out are valid. */
|
||||
if (data->data_in == NULL || data->data_out == NULL)
|
||||
return SRC_ERR_BAD_DATA_PTR ;
|
||||
/* And that data_in and data_out are valid. */
|
||||
if (data->data_in == NULL || data->data_out == NULL)
|
||||
return SRC_ERR_BAD_DATA_PTR ;
|
||||
|
||||
if (data->data_in == NULL)
|
||||
data->input_frames = 0 ;
|
||||
if (data->data_in == NULL)
|
||||
data->input_frames = 0 ;
|
||||
|
||||
if (data->input_frames < 0)
|
||||
data->input_frames = 0 ;
|
||||
if (data->output_frames < 0)
|
||||
data->output_frames = 0 ;
|
||||
if (data->input_frames < 0)
|
||||
data->input_frames = 0 ;
|
||||
if (data->output_frames < 0)
|
||||
data->output_frames = 0 ;
|
||||
|
||||
if (data->data_in < data->data_out)
|
||||
{ if (data->data_in + data->input_frames * psrc->channels > data->data_out)
|
||||
{ /*-printf ("\n\ndata_in: %p data_out: %p\n",
|
||||
(void*) (data->data_in + data->input_frames * psrc->channels), (void*) data->data_out) ;-*/
|
||||
return SRC_ERR_DATA_OVERLAP ;
|
||||
} ;
|
||||
}
|
||||
else if (data->data_out + data->output_frames * psrc->channels > data->data_in)
|
||||
{ /*-printf ("\n\ndata_in : %p ouput frames: %ld data_out: %p\n", (void*) data->data_in, data->output_frames, (void*) data->data_out) ;
|
||||
if (data->data_in < data->data_out)
|
||||
{ if (data->data_in + data->input_frames * psrc->channels > data->data_out)
|
||||
{ /*-printf ("\n\ndata_in: %p data_out: %p\n",
|
||||
(void*) (data->data_in + data->input_frames * psrc->channels), (void*) data->data_out) ;-*/
|
||||
return SRC_ERR_DATA_OVERLAP ;
|
||||
} ;
|
||||
}
|
||||
else if (data->data_out + data->output_frames * psrc->channels > data->data_in)
|
||||
{ /*-printf ("\n\ndata_in : %p ouput frames: %ld data_out: %p\n", (void*) data->data_in, data->output_frames, (void*) data->data_out) ;
|
||||
|
||||
printf ("data_out: %p (%p) data_in: %p\n", (void*) data->data_out,
|
||||
(void*) (data->data_out + data->input_frames * psrc->channels), (void*) data->data_in) ;-*/
|
||||
return SRC_ERR_DATA_OVERLAP ;
|
||||
} ;
|
||||
printf ("data_out: %p (%p) data_in: %p\n", (void*) data->data_out,
|
||||
(void*) (data->data_out + data->input_frames * psrc->channels), (void*) data->data_in) ;-*/
|
||||
return SRC_ERR_DATA_OVERLAP ;
|
||||
} ;
|
||||
|
||||
/* Set the input and output counts to zero. */
|
||||
data->input_frames_used = 0 ;
|
||||
data->output_frames_gen = 0 ;
|
||||
/* Set the input and output counts to zero. */
|
||||
data->input_frames_used = 0 ;
|
||||
data->output_frames_gen = 0 ;
|
||||
|
||||
/* Special case for when last_ratio has not been set. */
|
||||
if (psrc->last_ratio < (1.0 / SRC_MAX_RATIO))
|
||||
psrc->last_ratio = data->src_ratio ;
|
||||
/* Special case for when last_ratio has not been set. */
|
||||
if (psrc->last_ratio < (1.0 / SRC_MAX_RATIO))
|
||||
psrc->last_ratio = data->src_ratio ;
|
||||
|
||||
/* Now process. */
|
||||
if (fabs (psrc->last_ratio - data->src_ratio) < 1e-15)
|
||||
error = psrc->const_process (psrc, data) ;
|
||||
else
|
||||
error = psrc->vari_process (psrc, data) ;
|
||||
/* Now process. */
|
||||
if (fabs (psrc->last_ratio - data->src_ratio) < 1e-15)
|
||||
error = psrc->const_process (psrc, data) ;
|
||||
else
|
||||
error = psrc->vari_process (psrc, data) ;
|
||||
|
||||
return error ;
|
||||
return error ;
|
||||
} /* src_process */
|
||||
|
||||
long
|
||||
src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data)
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
SRC_DATA src_data ;
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
SRC_DATA src_data ;
|
||||
|
||||
long output_frames_gen ;
|
||||
int error = 0 ;
|
||||
long output_frames_gen ;
|
||||
int error = 0 ;
|
||||
|
||||
if (state == NULL)
|
||||
return 0 ;
|
||||
if (state == NULL)
|
||||
return 0 ;
|
||||
|
||||
if (frames <= 0)
|
||||
return 0 ;
|
||||
if (frames <= 0)
|
||||
return 0 ;
|
||||
|
||||
psrc = (SRC_PRIVATE*) state ;
|
||||
psrc = (SRC_PRIVATE*) state ;
|
||||
|
||||
if (psrc->mode != SRC_MODE_CALLBACK)
|
||||
{ psrc->error = SRC_ERR_BAD_MODE ;
|
||||
return 0 ;
|
||||
} ;
|
||||
if (psrc->mode != SRC_MODE_CALLBACK)
|
||||
{ psrc->error = SRC_ERR_BAD_MODE ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if (psrc->callback_func == NULL)
|
||||
{ psrc->error = SRC_ERR_NULL_CALLBACK ;
|
||||
return 0 ;
|
||||
} ;
|
||||
if (psrc->callback_func == NULL)
|
||||
{ psrc->error = SRC_ERR_NULL_CALLBACK ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
memset (&src_data, 0, sizeof (src_data)) ;
|
||||
memset (&src_data, 0, sizeof (src_data)) ;
|
||||
|
||||
/* Check src_ratio is in range. */
|
||||
if (is_bad_src_ratio (src_ratio))
|
||||
{ psrc->error = SRC_ERR_BAD_SRC_RATIO ;
|
||||
return 0 ;
|
||||
} ;
|
||||
/* Check src_ratio is in range. */
|
||||
if (is_bad_src_ratio (src_ratio))
|
||||
{ psrc->error = SRC_ERR_BAD_SRC_RATIO ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
/* Switch modes temporarily. */
|
||||
src_data.src_ratio = src_ratio ;
|
||||
src_data.data_out = data ;
|
||||
src_data.output_frames = frames ;
|
||||
/* Switch modes temporarily. */
|
||||
src_data.src_ratio = src_ratio ;
|
||||
src_data.data_out = data ;
|
||||
src_data.output_frames = frames ;
|
||||
|
||||
src_data.data_in = psrc->saved_data ;
|
||||
src_data.input_frames = psrc->saved_frames ;
|
||||
src_data.data_in = psrc->saved_data ;
|
||||
src_data.input_frames = psrc->saved_frames ;
|
||||
|
||||
output_frames_gen = 0 ;
|
||||
while (output_frames_gen < frames)
|
||||
{
|
||||
if (src_data.input_frames == 0)
|
||||
{ float *ptr ;
|
||||
output_frames_gen = 0 ;
|
||||
while (output_frames_gen < frames)
|
||||
{
|
||||
if (src_data.input_frames == 0)
|
||||
{ float *ptr ;
|
||||
|
||||
src_data.input_frames = psrc->callback_func (psrc->user_callback_data, &ptr) ;
|
||||
src_data.data_in = ptr ;
|
||||
src_data.input_frames = psrc->callback_func (psrc->user_callback_data, &ptr) ;
|
||||
src_data.data_in = ptr ;
|
||||
|
||||
if (src_data.input_frames == 0)
|
||||
src_data.end_of_input = 1 ;
|
||||
} ;
|
||||
if (src_data.input_frames == 0)
|
||||
src_data.end_of_input = 1 ;
|
||||
} ;
|
||||
|
||||
/*
|
||||
** Now call process function. However, we need to set the mode
|
||||
** to SRC_MODE_PROCESS first and when we return set it back to
|
||||
** SRC_MODE_CALLBACK.
|
||||
*/
|
||||
psrc->mode = SRC_MODE_PROCESS ;
|
||||
error = src_process (state, &src_data) ;
|
||||
psrc->mode = SRC_MODE_CALLBACK ;
|
||||
/*
|
||||
** Now call process function. However, we need to set the mode
|
||||
** to SRC_MODE_PROCESS first and when we return set it back to
|
||||
** SRC_MODE_CALLBACK.
|
||||
*/
|
||||
psrc->mode = SRC_MODE_PROCESS ;
|
||||
error = src_process (state, &src_data) ;
|
||||
psrc->mode = SRC_MODE_CALLBACK ;
|
||||
|
||||
if (error != 0)
|
||||
break ;
|
||||
if (error != 0)
|
||||
break ;
|
||||
|
||||
src_data.data_in += src_data.input_frames_used * psrc->channels ;
|
||||
src_data.input_frames -= src_data.input_frames_used ;
|
||||
src_data.data_in += src_data.input_frames_used * psrc->channels ;
|
||||
src_data.input_frames -= src_data.input_frames_used ;
|
||||
|
||||
src_data.data_out += src_data.output_frames_gen * psrc->channels ;
|
||||
src_data.output_frames -= src_data.output_frames_gen ;
|
||||
src_data.data_out += src_data.output_frames_gen * psrc->channels ;
|
||||
src_data.output_frames -= src_data.output_frames_gen ;
|
||||
|
||||
output_frames_gen += src_data.output_frames_gen ;
|
||||
output_frames_gen += src_data.output_frames_gen ;
|
||||
|
||||
if (src_data.end_of_input == SRC_TRUE && src_data.output_frames_gen == 0)
|
||||
break ;
|
||||
} ;
|
||||
if (src_data.end_of_input == SRC_TRUE && src_data.output_frames_gen == 0)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
psrc->saved_data = src_data.data_in ;
|
||||
psrc->saved_frames = src_data.input_frames ;
|
||||
psrc->saved_data = src_data.data_in ;
|
||||
psrc->saved_frames = src_data.input_frames ;
|
||||
|
||||
if (error != 0)
|
||||
{ psrc->error = error ;
|
||||
return 0 ;
|
||||
} ;
|
||||
if (error != 0)
|
||||
{ psrc->error = error ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
return output_frames_gen ;
|
||||
return output_frames_gen ;
|
||||
} /* src_callback_read */
|
||||
|
||||
/*==========================================================================
|
||||
@ -275,265 +275,265 @@ src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data)
|
||||
|
||||
int
|
||||
src_set_ratio (SRC_STATE *state, double new_ratio)
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
|
||||
psrc = (SRC_PRIVATE*) state ;
|
||||
psrc = (SRC_PRIVATE*) state ;
|
||||
|
||||
if (psrc == NULL)
|
||||
return SRC_ERR_BAD_STATE ;
|
||||
if (psrc->vari_process == NULL || psrc->const_process == NULL)
|
||||
return SRC_ERR_BAD_PROC_PTR ;
|
||||
if (psrc == NULL)
|
||||
return SRC_ERR_BAD_STATE ;
|
||||
if (psrc->vari_process == NULL || psrc->const_process == NULL)
|
||||
return SRC_ERR_BAD_PROC_PTR ;
|
||||
|
||||
if (is_bad_src_ratio (new_ratio))
|
||||
return SRC_ERR_BAD_SRC_RATIO ;
|
||||
if (is_bad_src_ratio (new_ratio))
|
||||
return SRC_ERR_BAD_SRC_RATIO ;
|
||||
|
||||
psrc->last_ratio = new_ratio ;
|
||||
psrc->last_ratio = new_ratio ;
|
||||
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
} /* src_set_ratio */
|
||||
|
||||
int
|
||||
src_reset (SRC_STATE *state)
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
{ SRC_PRIVATE *psrc ;
|
||||
|
||||
if ((psrc = (SRC_PRIVATE*) state) == NULL)
|
||||
return SRC_ERR_BAD_STATE ;
|
||||
if ((psrc = (SRC_PRIVATE*) state) == NULL)
|
||||
return SRC_ERR_BAD_STATE ;
|
||||
|
||||
if (psrc->reset != NULL)
|
||||
psrc->reset (psrc) ;
|
||||
if (psrc->reset != NULL)
|
||||
psrc->reset (psrc) ;
|
||||
|
||||
psrc->last_position = 0.0 ;
|
||||
psrc->last_ratio = 0.0 ;
|
||||
psrc->last_position = 0.0 ;
|
||||
psrc->last_ratio = 0.0 ;
|
||||
|
||||
psrc->saved_data = NULL ;
|
||||
psrc->saved_frames = 0 ;
|
||||
psrc->saved_data = NULL ;
|
||||
psrc->saved_frames = 0 ;
|
||||
|
||||
psrc->error = SRC_ERR_NO_ERROR ;
|
||||
psrc->error = SRC_ERR_NO_ERROR ;
|
||||
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
} /* src_reset */
|
||||
|
||||
/*==============================================================================
|
||||
** Control functions.
|
||||
** Control functions.
|
||||
*/
|
||||
|
||||
const char *
|
||||
src_get_name (int converter_type)
|
||||
{ const char *desc ;
|
||||
{ const char *desc ;
|
||||
|
||||
if ((desc = sinc_get_name (converter_type)) != NULL)
|
||||
return desc ;
|
||||
if ((desc = sinc_get_name (converter_type)) != NULL)
|
||||
return desc ;
|
||||
|
||||
if ((desc = zoh_get_name (converter_type)) != NULL)
|
||||
return desc ;
|
||||
if ((desc = zoh_get_name (converter_type)) != NULL)
|
||||
return desc ;
|
||||
|
||||
if ((desc = linear_get_name (converter_type)) != NULL)
|
||||
return desc ;
|
||||
if ((desc = linear_get_name (converter_type)) != NULL)
|
||||
return desc ;
|
||||
|
||||
return NULL ;
|
||||
return NULL ;
|
||||
} /* src_get_name */
|
||||
|
||||
const char *
|
||||
src_get_description (int converter_type)
|
||||
{ const char *desc ;
|
||||
{ const char *desc ;
|
||||
|
||||
if ((desc = sinc_get_description (converter_type)) != NULL)
|
||||
return desc ;
|
||||
if ((desc = sinc_get_description (converter_type)) != NULL)
|
||||
return desc ;
|
||||
|
||||
if ((desc = zoh_get_description (converter_type)) != NULL)
|
||||
return desc ;
|
||||
if ((desc = zoh_get_description (converter_type)) != NULL)
|
||||
return desc ;
|
||||
|
||||
if ((desc = linear_get_description (converter_type)) != NULL)
|
||||
return desc ;
|
||||
if ((desc = linear_get_description (converter_type)) != NULL)
|
||||
return desc ;
|
||||
|
||||
return NULL ;
|
||||
return NULL ;
|
||||
} /* src_get_description */
|
||||
|
||||
const char *
|
||||
src_get_version (void)
|
||||
{ return PACKAGE "-" VERSION " (c) 2002-2008 Erik de Castro Lopo" ;
|
||||
{ return PACKAGE "-" VERSION " (c) 2002-2008 Erik de Castro Lopo" ;
|
||||
} /* src_get_version */
|
||||
|
||||
int
|
||||
src_is_valid_ratio (double ratio)
|
||||
{
|
||||
if (is_bad_src_ratio (ratio))
|
||||
return SRC_FALSE ;
|
||||
if (is_bad_src_ratio (ratio))
|
||||
return SRC_FALSE ;
|
||||
|
||||
return SRC_TRUE ;
|
||||
return SRC_TRUE ;
|
||||
} /* src_is_valid_ratio */
|
||||
|
||||
/*==============================================================================
|
||||
** Error reporting functions.
|
||||
** Error reporting functions.
|
||||
*/
|
||||
|
||||
int
|
||||
src_error (SRC_STATE *state)
|
||||
{ if (state)
|
||||
return ((SRC_PRIVATE*) state)->error ;
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
{ if (state)
|
||||
return ((SRC_PRIVATE*) state)->error ;
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
} /* src_error */
|
||||
|
||||
const char*
|
||||
src_strerror (int error)
|
||||
{
|
||||
switch (error)
|
||||
{ case SRC_ERR_NO_ERROR :
|
||||
return "No error." ;
|
||||
case SRC_ERR_MALLOC_FAILED :
|
||||
return "Malloc failed." ;
|
||||
case SRC_ERR_BAD_STATE :
|
||||
return "SRC_STATE pointer is NULL." ;
|
||||
case SRC_ERR_BAD_DATA :
|
||||
return "SRC_DATA pointer is NULL." ;
|
||||
case SRC_ERR_BAD_DATA_PTR :
|
||||
return "SRC_DATA->data_out is NULL." ;
|
||||
case SRC_ERR_NO_PRIVATE :
|
||||
return "Internal error. No private data." ;
|
||||
case SRC_ERR_BAD_SRC_RATIO :
|
||||
return "SRC ratio outside [1/12, 12] range." ;
|
||||
case SRC_ERR_BAD_SINC_STATE :
|
||||
return "src_process() called without reset after end_of_input." ;
|
||||
case SRC_ERR_BAD_PROC_PTR :
|
||||
return "Internal error. No process pointer." ;
|
||||
case SRC_ERR_SHIFT_BITS :
|
||||
return "Internal error. SHIFT_BITS too large." ;
|
||||
case SRC_ERR_FILTER_LEN :
|
||||
return "Internal error. Filter length too large." ;
|
||||
case SRC_ERR_BAD_CONVERTER :
|
||||
return "Bad converter number." ;
|
||||
case SRC_ERR_BAD_CHANNEL_COUNT :
|
||||
return "Channel count must be >= 1." ;
|
||||
case SRC_ERR_SINC_BAD_BUFFER_LEN :
|
||||
return "Internal error. Bad buffer length. Please report this." ;
|
||||
case SRC_ERR_SIZE_INCOMPATIBILITY :
|
||||
return "Internal error. Input data / internal buffer size difference. Please report this." ;
|
||||
case SRC_ERR_BAD_PRIV_PTR :
|
||||
return "Internal error. Private pointer is NULL. Please report this." ;
|
||||
case SRC_ERR_DATA_OVERLAP :
|
||||
return "Input and output data arrays overlap." ;
|
||||
case SRC_ERR_BAD_CALLBACK :
|
||||
return "Supplied callback function pointer is NULL." ;
|
||||
case SRC_ERR_BAD_MODE :
|
||||
return "Calling mode differs from initialisation mode (ie process v callback)." ;
|
||||
case SRC_ERR_NULL_CALLBACK :
|
||||
return "Callback function pointer is NULL in src_callback_read ()." ;
|
||||
case SRC_ERR_NO_VARIABLE_RATIO :
|
||||
return "This converter only allows constant conversion ratios." ;
|
||||
switch (error)
|
||||
{ case SRC_ERR_NO_ERROR :
|
||||
return "No error." ;
|
||||
case SRC_ERR_MALLOC_FAILED :
|
||||
return "Malloc failed." ;
|
||||
case SRC_ERR_BAD_STATE :
|
||||
return "SRC_STATE pointer is NULL." ;
|
||||
case SRC_ERR_BAD_DATA :
|
||||
return "SRC_DATA pointer is NULL." ;
|
||||
case SRC_ERR_BAD_DATA_PTR :
|
||||
return "SRC_DATA->data_out is NULL." ;
|
||||
case SRC_ERR_NO_PRIVATE :
|
||||
return "Internal error. No private data." ;
|
||||
case SRC_ERR_BAD_SRC_RATIO :
|
||||
return "SRC ratio outside [1/12, 12] range." ;
|
||||
case SRC_ERR_BAD_SINC_STATE :
|
||||
return "src_process() called without reset after end_of_input." ;
|
||||
case SRC_ERR_BAD_PROC_PTR :
|
||||
return "Internal error. No process pointer." ;
|
||||
case SRC_ERR_SHIFT_BITS :
|
||||
return "Internal error. SHIFT_BITS too large." ;
|
||||
case SRC_ERR_FILTER_LEN :
|
||||
return "Internal error. Filter length too large." ;
|
||||
case SRC_ERR_BAD_CONVERTER :
|
||||
return "Bad converter number." ;
|
||||
case SRC_ERR_BAD_CHANNEL_COUNT :
|
||||
return "Channel count must be >= 1." ;
|
||||
case SRC_ERR_SINC_BAD_BUFFER_LEN :
|
||||
return "Internal error. Bad buffer length. Please report this." ;
|
||||
case SRC_ERR_SIZE_INCOMPATIBILITY :
|
||||
return "Internal error. Input data / internal buffer size difference. Please report this." ;
|
||||
case SRC_ERR_BAD_PRIV_PTR :
|
||||
return "Internal error. Private pointer is NULL. Please report this." ;
|
||||
case SRC_ERR_DATA_OVERLAP :
|
||||
return "Input and output data arrays overlap." ;
|
||||
case SRC_ERR_BAD_CALLBACK :
|
||||
return "Supplied callback function pointer is NULL." ;
|
||||
case SRC_ERR_BAD_MODE :
|
||||
return "Calling mode differs from initialisation mode (ie process v callback)." ;
|
||||
case SRC_ERR_NULL_CALLBACK :
|
||||
return "Callback function pointer is NULL in src_callback_read ()." ;
|
||||
case SRC_ERR_NO_VARIABLE_RATIO :
|
||||
return "This converter only allows constant conversion ratios." ;
|
||||
|
||||
case SRC_ERR_MAX_ERROR :
|
||||
return "Placeholder. No error defined for this error number." ;
|
||||
case SRC_ERR_MAX_ERROR :
|
||||
return "Placeholder. No error defined for this error number." ;
|
||||
|
||||
default : break ;
|
||||
}
|
||||
default : break ;
|
||||
}
|
||||
|
||||
return NULL ;
|
||||
return NULL ;
|
||||
} /* src_strerror */
|
||||
|
||||
/*==============================================================================
|
||||
** Simple interface for performing a single conversion from input buffer to
|
||||
** output buffer at a fixed conversion ratio.
|
||||
** Simple interface for performing a single conversion from input buffer to
|
||||
** output buffer at a fixed conversion ratio.
|
||||
*/
|
||||
|
||||
int
|
||||
src_simple (SRC_DATA *src_data, int converter, int channels)
|
||||
{ SRC_STATE *src_state ;
|
||||
int error ;
|
||||
{ SRC_STATE *src_state ;
|
||||
int error ;
|
||||
|
||||
if ((src_state = src_new (converter, channels, &error)) == NULL)
|
||||
return error ;
|
||||
if ((src_state = src_new (converter, channels, &error)) == NULL)
|
||||
return error ;
|
||||
|
||||
src_data->end_of_input = 1 ; /* Only one buffer worth of input. */
|
||||
src_data->end_of_input = 1 ; /* Only one buffer worth of input. */
|
||||
|
||||
error = src_process (src_state, src_data) ;
|
||||
error = src_process (src_state, src_data) ;
|
||||
|
||||
src_state = src_delete (src_state) ;
|
||||
src_state = src_delete (src_state) ;
|
||||
|
||||
return error ;
|
||||
return error ;
|
||||
} /* src_simple */
|
||||
|
||||
void
|
||||
src_short_to_float_array (const short *in, float *out, int len)
|
||||
{
|
||||
while (len)
|
||||
{ len -- ;
|
||||
out [len] = (float) (in [len] / (1.0 * 0x8000)) ;
|
||||
} ;
|
||||
while (len)
|
||||
{ len -- ;
|
||||
out [len] = (float) (in [len] / (1.0 * 0x8000)) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
return ;
|
||||
} /* src_short_to_float_array */
|
||||
|
||||
void
|
||||
src_float_to_short_array (const float *in, short *out, int len)
|
||||
{ double scaled_value ;
|
||||
{ double scaled_value ;
|
||||
|
||||
while (len)
|
||||
{ len -- ;
|
||||
while (len)
|
||||
{ len -- ;
|
||||
|
||||
scaled_value = in [len] * (8.0 * 0x10000000) ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
|
||||
{ out [len] = 32767 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
|
||||
{ out [len] = -32768 ;
|
||||
continue ;
|
||||
} ;
|
||||
scaled_value = in [len] * (8.0 * 0x10000000) ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
|
||||
{ out [len] = 32767 ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
|
||||
{ out [len] = -32768 ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
out [len] = (short) (lrint (scaled_value) >> 16) ;
|
||||
} ;
|
||||
out [len] = (short) (lrint (scaled_value) >> 16) ;
|
||||
} ;
|
||||
|
||||
} /* src_float_to_short_array */
|
||||
|
||||
void
|
||||
src_int_to_float_array (const int *in, float *out, int len)
|
||||
{
|
||||
while (len)
|
||||
{ len -- ;
|
||||
out [len] = (float) (in [len] / (8.0 * 0x10000000)) ;
|
||||
} ;
|
||||
while (len)
|
||||
{ len -- ;
|
||||
out [len] = (float) (in [len] / (8.0 * 0x10000000)) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
return ;
|
||||
} /* src_int_to_float_array */
|
||||
|
||||
void
|
||||
src_float_to_int_array (const float *in, int *out, int len)
|
||||
{ double scaled_value ;
|
||||
{ double scaled_value ;
|
||||
|
||||
while (len)
|
||||
{ len -- ;
|
||||
while (len)
|
||||
{ len -- ;
|
||||
|
||||
scaled_value = in [len] * (8.0 * 0x10000000) ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
|
||||
{ out [len] = 0x7fffffff ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
|
||||
{ out [len] = -1 - 0x7fffffff ;
|
||||
continue ;
|
||||
} ;
|
||||
scaled_value = in [len] * (8.0 * 0x10000000) ;
|
||||
if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
|
||||
{ out [len] = 0x7fffffff ;
|
||||
continue ;
|
||||
} ;
|
||||
if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
|
||||
{ out [len] = -1 - 0x7fffffff ;
|
||||
continue ;
|
||||
} ;
|
||||
|
||||
out [len] = lrint (scaled_value) ;
|
||||
} ;
|
||||
out [len] = lrint (scaled_value) ;
|
||||
} ;
|
||||
|
||||
} /* src_float_to_int_array */
|
||||
|
||||
/*==============================================================================
|
||||
** Private functions.
|
||||
** Private functions.
|
||||
*/
|
||||
|
||||
static int
|
||||
psrc_set_converter (SRC_PRIVATE *psrc, int converter_type)
|
||||
psrc_set_converter (SRC_PRIVATE *psrc, int converter_type)
|
||||
{
|
||||
if (sinc_set_converter (psrc, converter_type) == SRC_ERR_NO_ERROR)
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
if (sinc_set_converter (psrc, converter_type) == SRC_ERR_NO_ERROR)
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
|
||||
if (zoh_set_converter (psrc, converter_type) == SRC_ERR_NO_ERROR)
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
if (zoh_set_converter (psrc, converter_type) == SRC_ERR_NO_ERROR)
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
|
||||
if (linear_set_converter (psrc, converter_type) == SRC_ERR_NO_ERROR)
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
if (linear_set_converter (psrc, converter_type) == SRC_ERR_NO_ERROR)
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
|
||||
return SRC_ERR_BAD_CONVERTER ;
|
||||
return SRC_ERR_BAD_CONVERTER ;
|
||||
} /* psrc_set_converter */
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
|
||||
** use license for this code is available, please see:
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/* Opaque data type SRC_STATE. */
|
||||
@ -40,20 +40,20 @@ typedef struct SRC_STATE_tag SRC_STATE ;
|
||||
|
||||
/* SRC_DATA is used to pass data to src_simple() and src_process(). */
|
||||
typedef struct
|
||||
{ float *data_in, *data_out ;
|
||||
{ float *data_in, *data_out ;
|
||||
|
||||
long input_frames, output_frames ;
|
||||
long input_frames_used, output_frames_gen ;
|
||||
long input_frames, output_frames ;
|
||||
long input_frames_used, output_frames_gen ;
|
||||
|
||||
int end_of_input ;
|
||||
int end_of_input ;
|
||||
|
||||
double src_ratio ;
|
||||
double src_ratio ;
|
||||
} SRC_DATA ;
|
||||
|
||||
/* SRC_CB_DATA is used with callback based API. */
|
||||
typedef struct
|
||||
{ long frames ;
|
||||
float *data_in ;
|
||||
{ long frames ;
|
||||
float *data_in ;
|
||||
} SRC_CB_DATA ;
|
||||
|
||||
/*
|
||||
@ -68,49 +68,49 @@ typedef struct
|
||||
typedef long (*src_callback_t) (void *cb_data, float **data) ;
|
||||
|
||||
/*
|
||||
** Standard initialisation function : return an anonymous pointer to the
|
||||
** internal state of the converter. Choose a converter from the enums below.
|
||||
** Error returned in *error.
|
||||
** Standard initialisation function : return an anonymous pointer to the
|
||||
** internal state of the converter. Choose a converter from the enums below.
|
||||
** Error returned in *error.
|
||||
*/
|
||||
|
||||
SRC_STATE* src_new (int converter_type, int channels, int *error) ;
|
||||
|
||||
/*
|
||||
** Initilisation for callback based API : return an anonymous pointer to the
|
||||
** internal state of the converter. Choose a converter from the enums below.
|
||||
** The cb_data pointer can point to any data or be set to NULL. Whatever the
|
||||
** value, when processing, user supplied function "func" gets called with
|
||||
** cb_data as first parameter.
|
||||
** Initilisation for callback based API : return an anonymous pointer to the
|
||||
** internal state of the converter. Choose a converter from the enums below.
|
||||
** The cb_data pointer can point to any data or be set to NULL. Whatever the
|
||||
** value, when processing, user supplied function "func" gets called with
|
||||
** cb_data as first parameter.
|
||||
*/
|
||||
|
||||
SRC_STATE* src_callback_new (src_callback_t func, int converter_type, int channels,
|
||||
int *error, void* cb_data) ;
|
||||
int *error, void* cb_data) ;
|
||||
|
||||
/*
|
||||
** Cleanup all internal allocations.
|
||||
** Always returns NULL.
|
||||
** Cleanup all internal allocations.
|
||||
** Always returns NULL.
|
||||
*/
|
||||
|
||||
SRC_STATE* src_delete (SRC_STATE *state) ;
|
||||
|
||||
/*
|
||||
** Standard processing function.
|
||||
** Returns non zero on error.
|
||||
** Standard processing function.
|
||||
** Returns non zero on error.
|
||||
*/
|
||||
|
||||
int src_process (SRC_STATE *state, SRC_DATA *data) ;
|
||||
|
||||
/*
|
||||
** Callback based processing function. Read up to frames worth of data from
|
||||
** the converter int *data and return frames read or -1 on error.
|
||||
** Callback based processing function. Read up to frames worth of data from
|
||||
** the converter int *data and return frames read or -1 on error.
|
||||
*/
|
||||
long src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *data) ;
|
||||
|
||||
/*
|
||||
** Simple interface for performing a single conversion from input buffer to
|
||||
** output buffer at a fixed conversion ratio.
|
||||
** Simple interface does not require initialisation as it can only operate on
|
||||
** a single buffer worth of audio.
|
||||
** Simple interface for performing a single conversion from input buffer to
|
||||
** output buffer at a fixed conversion ratio.
|
||||
** Simple interface does not require initialisation as it can only operate on
|
||||
** a single buffer worth of audio.
|
||||
*/
|
||||
|
||||
int src_simple (SRC_DATA *data, int converter_type, int channels) ;
|
||||
@ -129,18 +129,18 @@ const char *src_get_description (int converter_type) ;
|
||||
const char *src_get_version (void) ;
|
||||
|
||||
/*
|
||||
** Set a new SRC ratio. This allows step responses
|
||||
** in the conversion ratio.
|
||||
** Returns non zero on error.
|
||||
** Set a new SRC ratio. This allows step responses
|
||||
** in the conversion ratio.
|
||||
** Returns non zero on error.
|
||||
*/
|
||||
|
||||
int src_set_ratio (SRC_STATE *state, double new_ratio) ;
|
||||
|
||||
/*
|
||||
** Reset the internal SRC state.
|
||||
** Does not modify the quality settings.
|
||||
** Does not free any memory allocations.
|
||||
** Returns non zero on error.
|
||||
** Reset the internal SRC state.
|
||||
** Does not modify the quality settings.
|
||||
** Does not free any memory allocations.
|
||||
** Returns non zero on error.
|
||||
*/
|
||||
|
||||
int src_reset (SRC_STATE *state) ;
|
||||
@ -153,13 +153,13 @@ int src_reset (SRC_STATE *state) ;
|
||||
int src_is_valid_ratio (double ratio) ;
|
||||
|
||||
/*
|
||||
** Return an error number.
|
||||
** Return an error number.
|
||||
*/
|
||||
|
||||
int src_error (SRC_STATE *state) ;
|
||||
|
||||
/*
|
||||
** Convert the error number into a string.
|
||||
** Convert the error number into a string.
|
||||
*/
|
||||
const char* src_strerror (int error) ;
|
||||
|
||||
@ -170,11 +170,11 @@ const char* src_strerror (int error) ;
|
||||
|
||||
enum
|
||||
{
|
||||
SRC_SINC_BEST_QUALITY = 0,
|
||||
SRC_SINC_MEDIUM_QUALITY = 1,
|
||||
SRC_SINC_FASTEST = 2,
|
||||
SRC_ZERO_ORDER_HOLD = 3,
|
||||
SRC_LINEAR = 4,
|
||||
SRC_SINC_BEST_QUALITY = 0,
|
||||
SRC_SINC_MEDIUM_QUALITY = 1,
|
||||
SRC_SINC_FASTEST = 2,
|
||||
SRC_ZERO_ORDER_HOLD = 3,
|
||||
SRC_LINEAR = 4,
|
||||
} ;
|
||||
|
||||
/*
|
||||
@ -190,8 +190,8 @@ void src_float_to_int_array (const float *in, int *out, int len) ;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SAMPLERATE_H */
|
||||
#endif /* SAMPLERATE_H */
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
|
||||
** use license for this code is available, please see:
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -36,17 +36,17 @@ static void linear_reset (SRC_PRIVATE *psrc) ;
|
||||
/*========================================================================================
|
||||
*/
|
||||
|
||||
#define LINEAR_MAGIC_MARKER MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r')
|
||||
#define LINEAR_MAGIC_MARKER MAKE_MAGIC ('l', 'i', 'n', 'e', 'a', 'r')
|
||||
|
||||
#define SRC_DEBUG 0
|
||||
#define SRC_DEBUG 0
|
||||
|
||||
typedef struct
|
||||
{ int linear_magic_marker ;
|
||||
int channels ;
|
||||
int reset ;
|
||||
long in_count, in_used ;
|
||||
long out_count, out_gen ;
|
||||
float last_value [1] ;
|
||||
{ int linear_magic_marker ;
|
||||
int channels ;
|
||||
int reset ;
|
||||
long in_count, in_used ;
|
||||
long out_count, out_gen ;
|
||||
float last_value [1] ;
|
||||
} LINEAR_DATA ;
|
||||
|
||||
/*----------------------------------------------------------------------------------------
|
||||
@ -54,95 +54,95 @@ typedef struct
|
||||
|
||||
static int
|
||||
linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
|
||||
{ LINEAR_DATA *linear ;
|
||||
double src_ratio, input_index, rem ;
|
||||
int ch ;
|
||||
{ LINEAR_DATA *linear ;
|
||||
double src_ratio, input_index, rem ;
|
||||
int ch ;
|
||||
|
||||
if (psrc->private_data == NULL)
|
||||
return SRC_ERR_NO_PRIVATE ;
|
||||
if (psrc->private_data == NULL)
|
||||
return SRC_ERR_NO_PRIVATE ;
|
||||
|
||||
linear = (LINEAR_DATA*) psrc->private_data ;
|
||||
linear = (LINEAR_DATA*) psrc->private_data ;
|
||||
|
||||
if (linear->reset)
|
||||
{ /* If we have just been reset, set the last_value data. */
|
||||
for (ch = 0 ; ch < linear->channels ; ch++)
|
||||
linear->last_value [ch] = data->data_in [ch] ;
|
||||
linear->reset = 0 ;
|
||||
} ;
|
||||
if (linear->reset)
|
||||
{ /* If we have just been reset, set the last_value data. */
|
||||
for (ch = 0 ; ch < linear->channels ; ch++)
|
||||
linear->last_value [ch] = data->data_in [ch] ;
|
||||
linear->reset = 0 ;
|
||||
} ;
|
||||
|
||||
linear->in_count = data->input_frames * linear->channels ;
|
||||
linear->out_count = data->output_frames * linear->channels ;
|
||||
linear->in_used = linear->out_gen = 0 ;
|
||||
linear->in_count = data->input_frames * linear->channels ;
|
||||
linear->out_count = data->output_frames * linear->channels ;
|
||||
linear->in_used = linear->out_gen = 0 ;
|
||||
|
||||
src_ratio = psrc->last_ratio ;
|
||||
input_index = psrc->last_position ;
|
||||
src_ratio = psrc->last_ratio ;
|
||||
input_index = psrc->last_position ;
|
||||
|
||||
/* Calculate samples before first sample in input array. */
|
||||
while (input_index < 1.0 && linear->out_gen < linear->out_count)
|
||||
{
|
||||
if (linear->in_used + linear->channels * input_index > linear->in_count)
|
||||
break ;
|
||||
/* Calculate samples before first sample in input array. */
|
||||
while (input_index < 1.0 && linear->out_gen < linear->out_count)
|
||||
{
|
||||
if (linear->in_used + linear->channels * input_index > linear->in_count)
|
||||
break ;
|
||||
|
||||
if (linear->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
|
||||
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / linear->out_count ;
|
||||
if (linear->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
|
||||
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / linear->out_count ;
|
||||
|
||||
for (ch = 0 ; ch < linear->channels ; ch++)
|
||||
{ data->data_out [linear->out_gen] = (float) (linear->last_value [ch] + input_index *
|
||||
(data->data_in [ch] - linear->last_value [ch])) ;
|
||||
linear->out_gen ++ ;
|
||||
} ;
|
||||
for (ch = 0 ; ch < linear->channels ; ch++)
|
||||
{ data->data_out [linear->out_gen] = (float) (linear->last_value [ch] + input_index *
|
||||
(data->data_in [ch] - linear->last_value [ch])) ;
|
||||
linear->out_gen ++ ;
|
||||
} ;
|
||||
|
||||
/* Figure out the next index. */
|
||||
input_index += 1.0 / src_ratio ;
|
||||
} ;
|
||||
/* Figure out the next index. */
|
||||
input_index += 1.0 / src_ratio ;
|
||||
} ;
|
||||
|
||||
rem = fmod_one (input_index) ;
|
||||
linear->in_used += linear->channels * lrint (input_index - rem) ;
|
||||
input_index = rem ;
|
||||
rem = fmod_one (input_index) ;
|
||||
linear->in_used += linear->channels * lrint (input_index - rem) ;
|
||||
input_index = rem ;
|
||||
|
||||
/* Main processing loop. */
|
||||
while (linear->out_gen < linear->out_count && linear->in_used + linear->channels * input_index <= linear->in_count)
|
||||
{
|
||||
if (linear->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
|
||||
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / linear->out_count ;
|
||||
/* Main processing loop. */
|
||||
while (linear->out_gen < linear->out_count && linear->in_used + linear->channels * input_index <= linear->in_count)
|
||||
{
|
||||
if (linear->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
|
||||
src_ratio = psrc->last_ratio + linear->out_gen * (data->src_ratio - psrc->last_ratio) / linear->out_count ;
|
||||
|
||||
if (SRC_DEBUG && linear->in_used < linear->channels && input_index < 1.0)
|
||||
{ printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", linear->in_used, linear->channels, input_index) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
if (SRC_DEBUG && linear->in_used < linear->channels && input_index < 1.0)
|
||||
{ printf ("Whoops!!!! in_used : %ld channels : %d input_index : %f\n", linear->in_used, linear->channels, input_index) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
for (ch = 0 ; ch < linear->channels ; ch++)
|
||||
{ data->data_out [linear->out_gen] = (float) (data->data_in [linear->in_used - linear->channels + ch] + input_index *
|
||||
(data->data_in [linear->in_used + ch] - data->data_in [linear->in_used - linear->channels + ch])) ;
|
||||
linear->out_gen ++ ;
|
||||
} ;
|
||||
for (ch = 0 ; ch < linear->channels ; ch++)
|
||||
{ data->data_out [linear->out_gen] = (float) (data->data_in [linear->in_used - linear->channels + ch] + input_index *
|
||||
(data->data_in [linear->in_used + ch] - data->data_in [linear->in_used - linear->channels + ch])) ;
|
||||
linear->out_gen ++ ;
|
||||
} ;
|
||||
|
||||
/* Figure out the next index. */
|
||||
input_index += 1.0 / src_ratio ;
|
||||
rem = fmod_one (input_index) ;
|
||||
/* Figure out the next index. */
|
||||
input_index += 1.0 / src_ratio ;
|
||||
rem = fmod_one (input_index) ;
|
||||
|
||||
linear->in_used += linear->channels * lrint (input_index - rem) ;
|
||||
input_index = rem ;
|
||||
} ;
|
||||
linear->in_used += linear->channels * lrint (input_index - rem) ;
|
||||
input_index = rem ;
|
||||
} ;
|
||||
|
||||
if (linear->in_used > linear->in_count)
|
||||
{ input_index += (linear->in_used - linear->in_count) / linear->channels ;
|
||||
linear->in_used = linear->in_count ;
|
||||
} ;
|
||||
if (linear->in_used > linear->in_count)
|
||||
{ input_index += (linear->in_used - linear->in_count) / linear->channels ;
|
||||
linear->in_used = linear->in_count ;
|
||||
} ;
|
||||
|
||||
psrc->last_position = input_index ;
|
||||
psrc->last_position = input_index ;
|
||||
|
||||
if (linear->in_used > 0)
|
||||
for (ch = 0 ; ch < linear->channels ; ch++)
|
||||
linear->last_value [ch] = data->data_in [linear->in_used - linear->channels + ch] ;
|
||||
if (linear->in_used > 0)
|
||||
for (ch = 0 ; ch < linear->channels ; ch++)
|
||||
linear->last_value [ch] = data->data_in [linear->in_used - linear->channels + ch] ;
|
||||
|
||||
/* Save current ratio rather then target ratio. */
|
||||
psrc->last_ratio = src_ratio ;
|
||||
/* Save current ratio rather then target ratio. */
|
||||
psrc->last_ratio = src_ratio ;
|
||||
|
||||
data->input_frames_used = linear->in_used / linear->channels ;
|
||||
data->output_frames_gen = linear->out_gen / linear->channels ;
|
||||
data->input_frames_used = linear->in_used / linear->channels ;
|
||||
data->output_frames_gen = linear->out_gen / linear->channels ;
|
||||
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
} /* linear_vari_process */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
@ -151,53 +151,53 @@ linear_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
|
||||
const char*
|
||||
linear_get_name (int src_enum)
|
||||
{
|
||||
if (src_enum == SRC_LINEAR)
|
||||
return "Linear Interpolator" ;
|
||||
if (src_enum == SRC_LINEAR)
|
||||
return "Linear Interpolator" ;
|
||||
|
||||
return NULL ;
|
||||
return NULL ;
|
||||
} /* linear_get_name */
|
||||
|
||||
const char*
|
||||
linear_get_description (int src_enum)
|
||||
{
|
||||
if (src_enum == SRC_LINEAR)
|
||||
return "Linear interpolator, very fast, poor quality." ;
|
||||
if (src_enum == SRC_LINEAR)
|
||||
return "Linear interpolator, very fast, poor quality." ;
|
||||
|
||||
return NULL ;
|
||||
return NULL ;
|
||||
} /* linear_get_descrition */
|
||||
|
||||
int
|
||||
linear_set_converter (SRC_PRIVATE *psrc, int src_enum)
|
||||
{ LINEAR_DATA *linear = NULL ;
|
||||
{ LINEAR_DATA *linear = NULL ;
|
||||
|
||||
if (src_enum != SRC_LINEAR)
|
||||
return SRC_ERR_BAD_CONVERTER ;
|
||||
if (src_enum != SRC_LINEAR)
|
||||
return SRC_ERR_BAD_CONVERTER ;
|
||||
|
||||
if (psrc->private_data != NULL)
|
||||
{ linear = (LINEAR_DATA*) psrc->private_data ;
|
||||
if (linear->linear_magic_marker != LINEAR_MAGIC_MARKER)
|
||||
{ free (psrc->private_data) ;
|
||||
psrc->private_data = NULL ;
|
||||
} ;
|
||||
} ;
|
||||
if (psrc->private_data != NULL)
|
||||
{ linear = (LINEAR_DATA*) psrc->private_data ;
|
||||
if (linear->linear_magic_marker != LINEAR_MAGIC_MARKER)
|
||||
{ free (psrc->private_data) ;
|
||||
psrc->private_data = NULL ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psrc->private_data == NULL)
|
||||
{ linear = calloc (1, sizeof (*linear) + psrc->channels * sizeof (float)) ;
|
||||
if (linear == NULL)
|
||||
return SRC_ERR_MALLOC_FAILED ;
|
||||
psrc->private_data = linear ;
|
||||
} ;
|
||||
if (psrc->private_data == NULL)
|
||||
{ linear = calloc (1, sizeof (*linear) + psrc->channels * sizeof (float)) ;
|
||||
if (linear == NULL)
|
||||
return SRC_ERR_MALLOC_FAILED ;
|
||||
psrc->private_data = linear ;
|
||||
} ;
|
||||
|
||||
linear->linear_magic_marker = LINEAR_MAGIC_MARKER ;
|
||||
linear->channels = psrc->channels ;
|
||||
linear->linear_magic_marker = LINEAR_MAGIC_MARKER ;
|
||||
linear->channels = psrc->channels ;
|
||||
|
||||
psrc->const_process = linear_vari_process ;
|
||||
psrc->vari_process = linear_vari_process ;
|
||||
psrc->reset = linear_reset ;
|
||||
psrc->const_process = linear_vari_process ;
|
||||
psrc->vari_process = linear_vari_process ;
|
||||
psrc->reset = linear_reset ;
|
||||
|
||||
linear_reset (psrc) ;
|
||||
linear_reset (psrc) ;
|
||||
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
} /* linear_set_converter */
|
||||
|
||||
/*===================================================================================
|
||||
@ -205,15 +205,15 @@ linear_set_converter (SRC_PRIVATE *psrc, int src_enum)
|
||||
|
||||
static void
|
||||
linear_reset (SRC_PRIVATE *psrc)
|
||||
{ LINEAR_DATA *linear = NULL ;
|
||||
{ LINEAR_DATA *linear = NULL ;
|
||||
|
||||
linear = (LINEAR_DATA*) psrc->private_data ;
|
||||
if (linear == NULL)
|
||||
return ;
|
||||
linear = (LINEAR_DATA*) psrc->private_data ;
|
||||
if (linear == NULL)
|
||||
return ;
|
||||
|
||||
linear->channels = psrc->channels ;
|
||||
linear->reset = 1 ;
|
||||
linear->channels = psrc->channels ;
|
||||
linear->reset = 1 ;
|
||||
|
||||
memset (linear->last_value, 0, sizeof (linear->last_value [0]) * linear->channels) ;
|
||||
memset (linear->last_value, 0, sizeof (linear->last_value [0]) * linear->channels) ;
|
||||
} /* linear_reset */
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
|
||||
** use license for this code is available, please see:
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -30,22 +30,22 @@
|
||||
#include "float_cast.h"
|
||||
#include "common.h"
|
||||
|
||||
#define SINC_MAGIC_MARKER MAKE_MAGIC (' ', 's', 'i', 'n', 'c', ' ')
|
||||
#define SINC_MAGIC_MARKER MAKE_MAGIC (' ', 's', 'i', 'n', 'c', ' ')
|
||||
|
||||
/*========================================================================================
|
||||
*/
|
||||
|
||||
#define MAKE_INCREMENT_T(x) ((increment_t) (x))
|
||||
#define MAKE_INCREMENT_T(x) ((increment_t) (x))
|
||||
|
||||
#define SHIFT_BITS 12
|
||||
#define FP_ONE ((double) (((increment_t) 1) << SHIFT_BITS))
|
||||
#define INV_FP_ONE (1.0 / FP_ONE)
|
||||
#define SHIFT_BITS 12
|
||||
#define FP_ONE ((double) (((increment_t) 1) << SHIFT_BITS))
|
||||
#define INV_FP_ONE (1.0 / FP_ONE)
|
||||
|
||||
/*========================================================================================
|
||||
*/
|
||||
|
||||
typedef int32_t increment_t ;
|
||||
typedef float coeff_t ;
|
||||
typedef float coeff_t ;
|
||||
|
||||
#include "fastest_coeffs.h"
|
||||
#ifndef NGC
|
||||
@ -54,20 +54,20 @@ typedef float coeff_t ;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{ int sinc_magic_marker ;
|
||||
{ int sinc_magic_marker ;
|
||||
|
||||
int channels ;
|
||||
long in_count, in_used ;
|
||||
long out_count, out_gen ;
|
||||
int channels ;
|
||||
long in_count, in_used ;
|
||||
long out_count, out_gen ;
|
||||
|
||||
int coeff_half_len, index_inc ;
|
||||
int coeff_half_len, index_inc ;
|
||||
|
||||
double src_ratio, input_index ;
|
||||
double src_ratio, input_index ;
|
||||
|
||||
coeff_t const *coeffs ;
|
||||
coeff_t const *coeffs ;
|
||||
|
||||
int b_current, b_end, b_real_end, b_len ;
|
||||
float buffer [1] ;
|
||||
int b_current, b_end, b_real_end, b_len ;
|
||||
float buffer [1] ;
|
||||
} SINC_FILTER ;
|
||||
|
||||
static int sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data) ;
|
||||
@ -80,29 +80,29 @@ static void sinc_reset (SRC_PRIVATE *psrc) ;
|
||||
|
||||
static inline increment_t
|
||||
double_to_fp (double x)
|
||||
{ if (sizeof (increment_t) == 8)
|
||||
return (llrint ((x) * FP_ONE)) ;
|
||||
return (lrint ((x) * FP_ONE)) ;
|
||||
{ if (sizeof (increment_t) == 8)
|
||||
return (llrint ((x) * FP_ONE)) ;
|
||||
return (lrint ((x) * FP_ONE)) ;
|
||||
} /* double_to_fp */
|
||||
|
||||
static inline increment_t
|
||||
int_to_fp (int x)
|
||||
{ return (((increment_t) (x)) << SHIFT_BITS) ;
|
||||
{ return (((increment_t) (x)) << SHIFT_BITS) ;
|
||||
} /* int_to_fp */
|
||||
|
||||
static inline int
|
||||
fp_to_int (increment_t x)
|
||||
{ return (((x) >> SHIFT_BITS)) ;
|
||||
{ return (((x) >> SHIFT_BITS)) ;
|
||||
} /* fp_to_int */
|
||||
|
||||
static inline increment_t
|
||||
fp_fraction_part (increment_t x)
|
||||
{ return ((x) & ((((increment_t) 1) << SHIFT_BITS) - 1)) ;
|
||||
{ return ((x) & ((((increment_t) 1) << SHIFT_BITS) - 1)) ;
|
||||
} /* fp_fraction_part */
|
||||
|
||||
static inline double
|
||||
fp_to_double (increment_t x)
|
||||
{ return fp_fraction_part (x) * INV_FP_ONE ;
|
||||
{ return fp_fraction_part (x) * INV_FP_ONE ;
|
||||
} /* fp_to_double */
|
||||
|
||||
|
||||
@ -112,245 +112,245 @@ fp_to_double (increment_t x)
|
||||
const char*
|
||||
sinc_get_name (int src_enum)
|
||||
{
|
||||
switch (src_enum)
|
||||
{
|
||||
switch (src_enum)
|
||||
{
|
||||
#ifndef NGC
|
||||
case SRC_SINC_BEST_QUALITY :
|
||||
return "Best Sinc Interpolator" ;
|
||||
return "Best Sinc Interpolator" ;
|
||||
|
||||
case SRC_SINC_MEDIUM_QUALITY :
|
||||
return "Medium Sinc Interpolator" ;
|
||||
case SRC_SINC_MEDIUM_QUALITY :
|
||||
return "Medium Sinc Interpolator" ;
|
||||
#endif
|
||||
|
||||
case SRC_SINC_FASTEST :
|
||||
return "Fastest Sinc Interpolator" ;
|
||||
case SRC_SINC_FASTEST :
|
||||
return "Fastest Sinc Interpolator" ;
|
||||
|
||||
default: break ;
|
||||
} ;
|
||||
default: break ;
|
||||
} ;
|
||||
|
||||
return NULL ;
|
||||
return NULL ;
|
||||
} /* sinc_get_descrition */
|
||||
|
||||
const char*
|
||||
sinc_get_description (int src_enum)
|
||||
{
|
||||
switch (src_enum)
|
||||
{
|
||||
switch (src_enum)
|
||||
{
|
||||
#ifndef NGC
|
||||
case SRC_SINC_FASTEST :
|
||||
return "Band limited sinc interpolation, fastest, 97dB SNR, 80% BW." ;
|
||||
return "Band limited sinc interpolation, fastest, 97dB SNR, 80% BW." ;
|
||||
|
||||
case SRC_SINC_MEDIUM_QUALITY :
|
||||
return "Band limited sinc interpolation, medium quality, 121dB SNR, 90% BW." ;
|
||||
case SRC_SINC_MEDIUM_QUALITY :
|
||||
return "Band limited sinc interpolation, medium quality, 121dB SNR, 90% BW." ;
|
||||
#endif
|
||||
|
||||
case SRC_SINC_BEST_QUALITY :
|
||||
return "Band limited sinc interpolation, best quality, 145dB SNR, 96% BW." ;
|
||||
case SRC_SINC_BEST_QUALITY :
|
||||
return "Band limited sinc interpolation, best quality, 145dB SNR, 96% BW." ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return NULL ;
|
||||
return NULL ;
|
||||
} /* sinc_get_descrition */
|
||||
|
||||
int
|
||||
sinc_set_converter (SRC_PRIVATE *psrc, int src_enum)
|
||||
{ SINC_FILTER *filter, temp_filter ;
|
||||
increment_t count ;
|
||||
int bits ;
|
||||
{ SINC_FILTER *filter, temp_filter ;
|
||||
increment_t count ;
|
||||
int bits ;
|
||||
|
||||
/* Quick sanity check. */
|
||||
if (SHIFT_BITS >= sizeof (increment_t) * 8 - 1)
|
||||
return SRC_ERR_SHIFT_BITS ;
|
||||
/* Quick sanity check. */
|
||||
if (SHIFT_BITS >= sizeof (increment_t) * 8 - 1)
|
||||
return SRC_ERR_SHIFT_BITS ;
|
||||
|
||||
if (psrc->private_data != NULL)
|
||||
{ filter = (SINC_FILTER*) psrc->private_data ;
|
||||
if (filter->sinc_magic_marker != SINC_MAGIC_MARKER)
|
||||
{ free (psrc->private_data) ;
|
||||
psrc->private_data = NULL ;
|
||||
} ;
|
||||
} ;
|
||||
if (psrc->private_data != NULL)
|
||||
{ filter = (SINC_FILTER*) psrc->private_data ;
|
||||
if (filter->sinc_magic_marker != SINC_MAGIC_MARKER)
|
||||
{ free (psrc->private_data) ;
|
||||
psrc->private_data = NULL ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
memset (&temp_filter, 0, sizeof (temp_filter)) ;
|
||||
memset (&temp_filter, 0, sizeof (temp_filter)) ;
|
||||
|
||||
temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ;
|
||||
temp_filter.channels = psrc->channels ;
|
||||
temp_filter.sinc_magic_marker = SINC_MAGIC_MARKER ;
|
||||
temp_filter.channels = psrc->channels ;
|
||||
|
||||
psrc->const_process = sinc_vari_process ;
|
||||
psrc->vari_process = sinc_vari_process ;
|
||||
psrc->reset = sinc_reset ;
|
||||
psrc->const_process = sinc_vari_process ;
|
||||
psrc->vari_process = sinc_vari_process ;
|
||||
psrc->reset = sinc_reset ;
|
||||
|
||||
switch (src_enum)
|
||||
{ case SRC_SINC_FASTEST :
|
||||
temp_filter.coeffs = fastest_coeffs.coeffs ;
|
||||
temp_filter.coeff_half_len = ARRAY_LEN (fastest_coeffs.coeffs) - 1 ;
|
||||
temp_filter.index_inc = fastest_coeffs.increment ;
|
||||
break ;
|
||||
switch (src_enum)
|
||||
{ case SRC_SINC_FASTEST :
|
||||
temp_filter.coeffs = fastest_coeffs.coeffs ;
|
||||
temp_filter.coeff_half_len = ARRAY_LEN (fastest_coeffs.coeffs) - 1 ;
|
||||
temp_filter.index_inc = fastest_coeffs.increment ;
|
||||
break ;
|
||||
|
||||
#ifndef NGC
|
||||
case SRC_SINC_MEDIUM_QUALITY :
|
||||
temp_filter.coeffs = slow_mid_qual_coeffs.coeffs ;
|
||||
temp_filter.coeff_half_len = ARRAY_LEN (slow_mid_qual_coeffs.coeffs) - 1 ;
|
||||
temp_filter.index_inc = slow_mid_qual_coeffs.increment ;
|
||||
break ;
|
||||
case SRC_SINC_MEDIUM_QUALITY :
|
||||
temp_filter.coeffs = slow_mid_qual_coeffs.coeffs ;
|
||||
temp_filter.coeff_half_len = ARRAY_LEN (slow_mid_qual_coeffs.coeffs) - 1 ;
|
||||
temp_filter.index_inc = slow_mid_qual_coeffs.increment ;
|
||||
break ;
|
||||
|
||||
case SRC_SINC_BEST_QUALITY :
|
||||
temp_filter.coeffs = slow_high_qual_coeffs.coeffs ;
|
||||
temp_filter.coeff_half_len = ARRAY_LEN (slow_high_qual_coeffs.coeffs) - 1 ;
|
||||
temp_filter.index_inc = slow_high_qual_coeffs.increment ;
|
||||
break ;
|
||||
temp_filter.coeffs = slow_high_qual_coeffs.coeffs ;
|
||||
temp_filter.coeff_half_len = ARRAY_LEN (slow_high_qual_coeffs.coeffs) - 1 ;
|
||||
temp_filter.index_inc = slow_high_qual_coeffs.increment ;
|
||||
break ;
|
||||
#endif
|
||||
|
||||
default :
|
||||
return SRC_ERR_BAD_CONVERTER ;
|
||||
} ;
|
||||
default :
|
||||
return SRC_ERR_BAD_CONVERTER ;
|
||||
} ;
|
||||
|
||||
/*
|
||||
** FIXME : This needs to be looked at more closely to see if there is
|
||||
** a better way. Need to look at prepare_data () at the same time.
|
||||
*/
|
||||
/*
|
||||
** FIXME : This needs to be looked at more closely to see if there is
|
||||
** a better way. Need to look at prepare_data () at the same time.
|
||||
*/
|
||||
|
||||
temp_filter.b_len = 2 * lrint (1.0 + temp_filter.coeff_half_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ;
|
||||
temp_filter.b_len = MAX (temp_filter.b_len, 4096) ;
|
||||
temp_filter.b_len *= temp_filter.channels ;
|
||||
temp_filter.b_len = 2 * lrint (1.0 + temp_filter.coeff_half_len / (temp_filter.index_inc * 1.0) * SRC_MAX_RATIO) ;
|
||||
temp_filter.b_len = MAX (temp_filter.b_len, 4096) ;
|
||||
temp_filter.b_len *= temp_filter.channels ;
|
||||
|
||||
if ((filter = calloc (1, sizeof (SINC_FILTER) + sizeof (filter->buffer [0]) * (temp_filter.b_len + temp_filter.channels))) == NULL)
|
||||
return SRC_ERR_MALLOC_FAILED ;
|
||||
if ((filter = calloc (1, sizeof (SINC_FILTER) + sizeof (filter->buffer [0]) * (temp_filter.b_len + temp_filter.channels))) == NULL)
|
||||
return SRC_ERR_MALLOC_FAILED ;
|
||||
|
||||
*filter = temp_filter ;
|
||||
memset (&temp_filter, 0xEE, sizeof (temp_filter)) ;
|
||||
*filter = temp_filter ;
|
||||
memset (&temp_filter, 0xEE, sizeof (temp_filter)) ;
|
||||
|
||||
psrc->private_data = filter ;
|
||||
psrc->private_data = filter ;
|
||||
|
||||
sinc_reset (psrc) ;
|
||||
sinc_reset (psrc) ;
|
||||
|
||||
count = filter->coeff_half_len ;
|
||||
for (bits = 0 ; (MAKE_INCREMENT_T (1) << bits) < count ; bits++)
|
||||
count |= (MAKE_INCREMENT_T (1) << bits) ;
|
||||
count = filter->coeff_half_len ;
|
||||
for (bits = 0 ; (MAKE_INCREMENT_T (1) << bits) < count ; bits++)
|
||||
count |= (MAKE_INCREMENT_T (1) << bits) ;
|
||||
|
||||
if (bits + SHIFT_BITS - 1 >= (int) (sizeof (increment_t) * 8))
|
||||
return SRC_ERR_FILTER_LEN ;
|
||||
if (bits + SHIFT_BITS - 1 >= (int) (sizeof (increment_t) * 8))
|
||||
return SRC_ERR_FILTER_LEN ;
|
||||
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
} /* sinc_set_converter */
|
||||
|
||||
static void
|
||||
sinc_reset (SRC_PRIVATE *psrc)
|
||||
{ SINC_FILTER *filter ;
|
||||
{ SINC_FILTER *filter ;
|
||||
|
||||
filter = (SINC_FILTER*) psrc->private_data ;
|
||||
if (filter == NULL)
|
||||
return ;
|
||||
filter = (SINC_FILTER*) psrc->private_data ;
|
||||
if (filter == NULL)
|
||||
return ;
|
||||
|
||||
filter->b_current = filter->b_end = 0 ;
|
||||
filter->b_real_end = -1 ;
|
||||
filter->b_current = filter->b_end = 0 ;
|
||||
filter->b_real_end = -1 ;
|
||||
|
||||
filter->src_ratio = filter->input_index = 0.0 ;
|
||||
filter->src_ratio = filter->input_index = 0.0 ;
|
||||
|
||||
memset (filter->buffer, 0, filter->b_len * sizeof (filter->buffer [0])) ;
|
||||
memset (filter->buffer, 0, filter->b_len * sizeof (filter->buffer [0])) ;
|
||||
|
||||
/* Set this for a sanity check */
|
||||
memset (filter->buffer + filter->b_len, 0xAA, filter->channels * sizeof (filter->buffer [0])) ;
|
||||
/* Set this for a sanity check */
|
||||
memset (filter->buffer + filter->b_len, 0xAA, filter->channels * sizeof (filter->buffer [0])) ;
|
||||
} /* sinc_reset */
|
||||
|
||||
/*========================================================================================
|
||||
** Beware all ye who dare pass this point. There be dragons here.
|
||||
** Beware all ye who dare pass this point. There be dragons here.
|
||||
*/
|
||||
|
||||
static int
|
||||
sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
|
||||
{ SINC_FILTER *filter ;
|
||||
double input_index, src_ratio, count, float_increment, terminate, rem ;
|
||||
increment_t increment, start_filter_index ;
|
||||
int half_filter_chan_len, samples_in_hand, ch ;
|
||||
{ SINC_FILTER *filter ;
|
||||
double input_index, src_ratio, count, float_increment, terminate, rem ;
|
||||
increment_t increment, start_filter_index ;
|
||||
int half_filter_chan_len, samples_in_hand, ch ;
|
||||
|
||||
if (psrc->private_data == NULL)
|
||||
return SRC_ERR_NO_PRIVATE ;
|
||||
if (psrc->private_data == NULL)
|
||||
return SRC_ERR_NO_PRIVATE ;
|
||||
|
||||
filter = (SINC_FILTER*) psrc->private_data ;
|
||||
filter = (SINC_FILTER*) psrc->private_data ;
|
||||
|
||||
/* If there is not a problem, this will be optimised out. */
|
||||
if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
|
||||
return SRC_ERR_SIZE_INCOMPATIBILITY ;
|
||||
/* If there is not a problem, this will be optimised out. */
|
||||
if (sizeof (filter->buffer [0]) != sizeof (data->data_in [0]))
|
||||
return SRC_ERR_SIZE_INCOMPATIBILITY ;
|
||||
|
||||
filter->in_count = data->input_frames * filter->channels ;
|
||||
filter->out_count = data->output_frames * filter->channels ;
|
||||
filter->in_used = filter->out_gen = 0 ;
|
||||
filter->in_count = data->input_frames * filter->channels ;
|
||||
filter->out_count = data->output_frames * filter->channels ;
|
||||
filter->in_used = filter->out_gen = 0 ;
|
||||
|
||||
src_ratio = psrc->last_ratio ;
|
||||
src_ratio = psrc->last_ratio ;
|
||||
|
||||
/* Check the sample rate ratio wrt the buffer len. */
|
||||
count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
|
||||
if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
|
||||
count /= MIN (psrc->last_ratio, data->src_ratio) ;
|
||||
/* Check the sample rate ratio wrt the buffer len. */
|
||||
count = (filter->coeff_half_len + 2.0) / filter->index_inc ;
|
||||
if (MIN (psrc->last_ratio, data->src_ratio) < 1.0)
|
||||
count /= MIN (psrc->last_ratio, data->src_ratio) ;
|
||||
|
||||
/* Maximum coefficientson either side of center point. */
|
||||
half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
|
||||
/* Maximum coefficientson either side of center point. */
|
||||
half_filter_chan_len = filter->channels * (lrint (count) + 1) ;
|
||||
|
||||
input_index = psrc->last_position ;
|
||||
float_increment = filter->index_inc ;
|
||||
input_index = psrc->last_position ;
|
||||
float_increment = filter->index_inc ;
|
||||
|
||||
rem = fmod_one (input_index) ;
|
||||
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
|
||||
input_index = rem ;
|
||||
rem = fmod_one (input_index) ;
|
||||
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
|
||||
input_index = rem ;
|
||||
|
||||
terminate = 1.0 / src_ratio + 1e-20 ;
|
||||
terminate = 1.0 / src_ratio + 1e-20 ;
|
||||
|
||||
/* Main processing loop. */
|
||||
while (filter->out_gen < filter->out_count)
|
||||
{
|
||||
/* Need to reload buffer? */
|
||||
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
|
||||
/* Main processing loop. */
|
||||
while (filter->out_gen < filter->out_count)
|
||||
{
|
||||
/* Need to reload buffer? */
|
||||
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
|
||||
|
||||
if (samples_in_hand <= half_filter_chan_len)
|
||||
{ prepare_data (filter, data, half_filter_chan_len) ;
|
||||
if (samples_in_hand <= half_filter_chan_len)
|
||||
{ prepare_data (filter, data, half_filter_chan_len) ;
|
||||
|
||||
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
|
||||
if (samples_in_hand <= half_filter_chan_len)
|
||||
break ;
|
||||
} ;
|
||||
samples_in_hand = (filter->b_end - filter->b_current + filter->b_len) % filter->b_len ;
|
||||
if (samples_in_hand <= half_filter_chan_len)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
/* This is the termination condition. */
|
||||
if (filter->b_real_end >= 0)
|
||||
{ if (filter->b_current + input_index + terminate >= filter->b_real_end)
|
||||
break ;
|
||||
} ;
|
||||
/* This is the termination condition. */
|
||||
if (filter->b_real_end >= 0)
|
||||
{ if (filter->b_current + input_index + terminate >= filter->b_real_end)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
|
||||
src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
|
||||
if (filter->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > 1e-10)
|
||||
src_ratio = psrc->last_ratio + filter->out_gen * (data->src_ratio - psrc->last_ratio) / filter->out_count ;
|
||||
|
||||
float_increment = filter->index_inc * 1.0 ;
|
||||
if (src_ratio < 1.0)
|
||||
float_increment = filter->index_inc * src_ratio ;
|
||||
float_increment = filter->index_inc * 1.0 ;
|
||||
if (src_ratio < 1.0)
|
||||
float_increment = filter->index_inc * src_ratio ;
|
||||
|
||||
increment = double_to_fp (float_increment) ;
|
||||
increment = double_to_fp (float_increment) ;
|
||||
|
||||
start_filter_index = double_to_fp (input_index * float_increment) ;
|
||||
start_filter_index = double_to_fp (input_index * float_increment) ;
|
||||
|
||||
for (ch = 0 ; ch < filter->channels ; ch++)
|
||||
{ data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
|
||||
calc_output (filter, increment, start_filter_index, ch)) ;
|
||||
filter->out_gen ++ ;
|
||||
} ;
|
||||
for (ch = 0 ; ch < filter->channels ; ch++)
|
||||
{ data->data_out [filter->out_gen] = (float) ((float_increment / filter->index_inc) *
|
||||
calc_output (filter, increment, start_filter_index, ch)) ;
|
||||
filter->out_gen ++ ;
|
||||
} ;
|
||||
|
||||
/* Figure out the next index. */
|
||||
input_index += 1.0 / src_ratio ;
|
||||
rem = fmod_one (input_index) ;
|
||||
/* Figure out the next index. */
|
||||
input_index += 1.0 / src_ratio ;
|
||||
rem = fmod_one (input_index) ;
|
||||
|
||||
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
|
||||
input_index = rem ;
|
||||
} ;
|
||||
filter->b_current = (filter->b_current + filter->channels * lrint (input_index - rem)) % filter->b_len ;
|
||||
input_index = rem ;
|
||||
} ;
|
||||
|
||||
psrc->last_position = input_index ;
|
||||
psrc->last_position = input_index ;
|
||||
|
||||
/* Save current ratio rather then target ratio. */
|
||||
psrc->last_ratio = src_ratio ;
|
||||
/* Save current ratio rather then target ratio. */
|
||||
psrc->last_ratio = src_ratio ;
|
||||
|
||||
data->input_frames_used = filter->in_used / filter->channels ;
|
||||
data->output_frames_gen = filter->out_gen / filter->channels ;
|
||||
data->input_frames_used = filter->in_used / filter->channels ;
|
||||
data->output_frames_gen = filter->out_gen / filter->channels ;
|
||||
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
} /* sinc_vari_process */
|
||||
|
||||
/*----------------------------------------------------------------------------------------
|
||||
@ -358,121 +358,121 @@ sinc_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
|
||||
|
||||
static void
|
||||
prepare_data (SINC_FILTER *filter, SRC_DATA *data, int half_filter_chan_len)
|
||||
{ int len = 0 ;
|
||||
{ int len = 0 ;
|
||||
|
||||
if (filter->b_real_end >= 0)
|
||||
return ; /* This doesn't make sense, so return. */
|
||||
if (filter->b_real_end >= 0)
|
||||
return ; /* This doesn't make sense, so return. */
|
||||
|
||||
if (filter->b_current == 0)
|
||||
{ /* Initial state. Set up zeros at the start of the buffer and
|
||||
** then load new data after that.
|
||||
*/
|
||||
len = filter->b_len - 2 * half_filter_chan_len ;
|
||||
if (filter->b_current == 0)
|
||||
{ /* Initial state. Set up zeros at the start of the buffer and
|
||||
** then load new data after that.
|
||||
*/
|
||||
len = filter->b_len - 2 * half_filter_chan_len ;
|
||||
|
||||
filter->b_current = filter->b_end = half_filter_chan_len ;
|
||||
}
|
||||
else if (filter->b_end + half_filter_chan_len + filter->channels < filter->b_len)
|
||||
{ /* Load data at current end position. */
|
||||
len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ;
|
||||
}
|
||||
else
|
||||
{ /* Move data at end of buffer back to the start of the buffer. */
|
||||
len = filter->b_end - filter->b_current ;
|
||||
memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len,
|
||||
(half_filter_chan_len + len) * sizeof (filter->buffer [0])) ;
|
||||
filter->b_current = filter->b_end = half_filter_chan_len ;
|
||||
}
|
||||
else if (filter->b_end + half_filter_chan_len + filter->channels < filter->b_len)
|
||||
{ /* Load data at current end position. */
|
||||
len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ;
|
||||
}
|
||||
else
|
||||
{ /* Move data at end of buffer back to the start of the buffer. */
|
||||
len = filter->b_end - filter->b_current ;
|
||||
memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len,
|
||||
(half_filter_chan_len + len) * sizeof (filter->buffer [0])) ;
|
||||
|
||||
filter->b_current = half_filter_chan_len ;
|
||||
filter->b_end = filter->b_current + len ;
|
||||
filter->b_current = half_filter_chan_len ;
|
||||
filter->b_end = filter->b_current + len ;
|
||||
|
||||
/* Now load data at current end of buffer. */
|
||||
len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ;
|
||||
} ;
|
||||
/* Now load data at current end of buffer. */
|
||||
len = MAX (filter->b_len - filter->b_current - half_filter_chan_len, 0) ;
|
||||
} ;
|
||||
|
||||
len = MIN (filter->in_count - filter->in_used, len) ;
|
||||
len -= (len % filter->channels) ;
|
||||
len = MIN (filter->in_count - filter->in_used, len) ;
|
||||
len -= (len % filter->channels) ;
|
||||
|
||||
memcpy (filter->buffer + filter->b_end, data->data_in + filter->in_used,
|
||||
len * sizeof (filter->buffer [0])) ;
|
||||
memcpy (filter->buffer + filter->b_end, data->data_in + filter->in_used,
|
||||
len * sizeof (filter->buffer [0])) ;
|
||||
|
||||
filter->b_end += len ;
|
||||
filter->in_used += len ;
|
||||
filter->b_end += len ;
|
||||
filter->in_used += len ;
|
||||
|
||||
if (filter->in_used == filter->in_count &&
|
||||
filter->b_end - filter->b_current < 2 * half_filter_chan_len && data->end_of_input)
|
||||
{ /* Handle the case where all data in the current buffer has been
|
||||
** consumed and this is the last buffer.
|
||||
*/
|
||||
if (filter->in_used == filter->in_count &&
|
||||
filter->b_end - filter->b_current < 2 * half_filter_chan_len && data->end_of_input)
|
||||
{ /* Handle the case where all data in the current buffer has been
|
||||
** consumed and this is the last buffer.
|
||||
*/
|
||||
|
||||
if (filter->b_len - filter->b_end < half_filter_chan_len + 5)
|
||||
{ /* If necessary, move data down to the start of the buffer. */
|
||||
len = filter->b_end - filter->b_current ;
|
||||
memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len,
|
||||
(half_filter_chan_len + len) * sizeof (filter->buffer [0])) ;
|
||||
if (filter->b_len - filter->b_end < half_filter_chan_len + 5)
|
||||
{ /* If necessary, move data down to the start of the buffer. */
|
||||
len = filter->b_end - filter->b_current ;
|
||||
memmove (filter->buffer, filter->buffer + filter->b_current - half_filter_chan_len,
|
||||
(half_filter_chan_len + len) * sizeof (filter->buffer [0])) ;
|
||||
|
||||
filter->b_current = half_filter_chan_len ;
|
||||
filter->b_end = filter->b_current + len ;
|
||||
} ;
|
||||
filter->b_current = half_filter_chan_len ;
|
||||
filter->b_end = filter->b_current + len ;
|
||||
} ;
|
||||
|
||||
filter->b_real_end = filter->b_end ;
|
||||
len = half_filter_chan_len + 5 ;
|
||||
filter->b_real_end = filter->b_end ;
|
||||
len = half_filter_chan_len + 5 ;
|
||||
|
||||
memset (filter->buffer + filter->b_end, 0, len * sizeof (filter->buffer [0])) ;
|
||||
filter->b_end += len ;
|
||||
} ;
|
||||
memset (filter->buffer + filter->b_end, 0, len * sizeof (filter->buffer [0])) ;
|
||||
filter->b_end += len ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
return ;
|
||||
} /* prepare_data */
|
||||
|
||||
|
||||
static double
|
||||
calc_output (SINC_FILTER *filter, increment_t increment, increment_t start_filter_index, int ch)
|
||||
{ double fraction, left, right, icoeff ;
|
||||
increment_t filter_index, max_filter_index ;
|
||||
int data_index, coeff_count, indx ;
|
||||
{ double fraction, left, right, icoeff ;
|
||||
increment_t filter_index, max_filter_index ;
|
||||
int data_index, coeff_count, indx ;
|
||||
|
||||
/* Convert input parameters into fixed point. */
|
||||
max_filter_index = int_to_fp (filter->coeff_half_len) ;
|
||||
/* Convert input parameters into fixed point. */
|
||||
max_filter_index = int_to_fp (filter->coeff_half_len) ;
|
||||
|
||||
/* First apply the left half of the filter. */
|
||||
filter_index = start_filter_index ;
|
||||
coeff_count = (max_filter_index - filter_index) / increment ;
|
||||
filter_index = filter_index + coeff_count * increment ;
|
||||
data_index = filter->b_current - filter->channels * coeff_count + ch ;
|
||||
/* First apply the left half of the filter. */
|
||||
filter_index = start_filter_index ;
|
||||
coeff_count = (max_filter_index - filter_index) / increment ;
|
||||
filter_index = filter_index + coeff_count * increment ;
|
||||
data_index = filter->b_current - filter->channels * coeff_count + ch ;
|
||||
|
||||
left = 0.0 ;
|
||||
do
|
||||
{ fraction = fp_to_double (filter_index) ;
|
||||
indx = fp_to_int (filter_index) ;
|
||||
left = 0.0 ;
|
||||
do
|
||||
{ fraction = fp_to_double (filter_index) ;
|
||||
indx = fp_to_int (filter_index) ;
|
||||
|
||||
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
|
||||
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
|
||||
|
||||
left += icoeff * filter->buffer [data_index] ;
|
||||
left += icoeff * filter->buffer [data_index] ;
|
||||
|
||||
filter_index -= increment ;
|
||||
data_index = data_index + filter->channels ;
|
||||
}
|
||||
while (filter_index >= MAKE_INCREMENT_T (0)) ;
|
||||
filter_index -= increment ;
|
||||
data_index = data_index + filter->channels ;
|
||||
}
|
||||
while (filter_index >= MAKE_INCREMENT_T (0)) ;
|
||||
|
||||
/* Now apply the right half of the filter. */
|
||||
filter_index = increment - start_filter_index ;
|
||||
coeff_count = (max_filter_index - filter_index) / increment ;
|
||||
filter_index = filter_index + coeff_count * increment ;
|
||||
data_index = filter->b_current + filter->channels * (1 + coeff_count) + ch ;
|
||||
/* Now apply the right half of the filter. */
|
||||
filter_index = increment - start_filter_index ;
|
||||
coeff_count = (max_filter_index - filter_index) / increment ;
|
||||
filter_index = filter_index + coeff_count * increment ;
|
||||
data_index = filter->b_current + filter->channels * (1 + coeff_count) + ch ;
|
||||
|
||||
right = 0.0 ;
|
||||
do
|
||||
{ fraction = fp_to_double (filter_index) ;
|
||||
indx = fp_to_int (filter_index) ;
|
||||
right = 0.0 ;
|
||||
do
|
||||
{ fraction = fp_to_double (filter_index) ;
|
||||
indx = fp_to_int (filter_index) ;
|
||||
|
||||
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
|
||||
icoeff = filter->coeffs [indx] + fraction * (filter->coeffs [indx + 1] - filter->coeffs [indx]) ;
|
||||
|
||||
right += icoeff * filter->buffer [data_index] ;
|
||||
right += icoeff * filter->buffer [data_index] ;
|
||||
|
||||
filter_index -= increment ;
|
||||
data_index = data_index - filter->channels ;
|
||||
}
|
||||
while (filter_index > MAKE_INCREMENT_T (0)) ;
|
||||
filter_index -= increment ;
|
||||
data_index = data_index - filter->channels ;
|
||||
}
|
||||
while (filter_index > MAKE_INCREMENT_T (0)) ;
|
||||
|
||||
return (left + right) ;
|
||||
return (left + right) ;
|
||||
} /* calc_output */
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
** This code is part of Secret Rabibt Code aka libsamplerate. A commercial
|
||||
** use license for this code is available, please see:
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
** http://www.mega-nerd.com/SRC/procedure.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -36,15 +36,15 @@ static void zoh_reset (SRC_PRIVATE *psrc) ;
|
||||
/*========================================================================================
|
||||
*/
|
||||
|
||||
#define ZOH_MAGIC_MARKER MAKE_MAGIC ('s', 'r', 'c', 'z', 'o', 'h')
|
||||
#define ZOH_MAGIC_MARKER MAKE_MAGIC ('s', 'r', 'c', 'z', 'o', 'h')
|
||||
|
||||
typedef struct
|
||||
{ int zoh_magic_marker ;
|
||||
int channels ;
|
||||
int reset ;
|
||||
long in_count, in_used ;
|
||||
long out_count, out_gen ;
|
||||
float last_value [1] ;
|
||||
{ int zoh_magic_marker ;
|
||||
int channels ;
|
||||
int reset ;
|
||||
long in_count, in_used ;
|
||||
long out_count, out_gen ;
|
||||
float last_value [1] ;
|
||||
} ZOH_DATA ;
|
||||
|
||||
/*----------------------------------------------------------------------------------------
|
||||
@ -52,88 +52,88 @@ typedef struct
|
||||
|
||||
static int
|
||||
zoh_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
|
||||
{ ZOH_DATA *zoh ;
|
||||
double src_ratio, input_index, rem ;
|
||||
int ch ;
|
||||
{ ZOH_DATA *zoh ;
|
||||
double src_ratio, input_index, rem ;
|
||||
int ch ;
|
||||
|
||||
if (psrc->private_data == NULL)
|
||||
return SRC_ERR_NO_PRIVATE ;
|
||||
if (psrc->private_data == NULL)
|
||||
return SRC_ERR_NO_PRIVATE ;
|
||||
|
||||
zoh = (ZOH_DATA*) psrc->private_data ;
|
||||
zoh = (ZOH_DATA*) psrc->private_data ;
|
||||
|
||||
if (zoh->reset)
|
||||
{ /* If we have just been reset, set the last_value data. */
|
||||
for (ch = 0 ; ch < zoh->channels ; ch++)
|
||||
zoh->last_value [ch] = data->data_in [ch] ;
|
||||
zoh->reset = 0 ;
|
||||
} ;
|
||||
if (zoh->reset)
|
||||
{ /* If we have just been reset, set the last_value data. */
|
||||
for (ch = 0 ; ch < zoh->channels ; ch++)
|
||||
zoh->last_value [ch] = data->data_in [ch] ;
|
||||
zoh->reset = 0 ;
|
||||
} ;
|
||||
|
||||
zoh->in_count = data->input_frames * zoh->channels ;
|
||||
zoh->out_count = data->output_frames * zoh->channels ;
|
||||
zoh->in_used = zoh->out_gen = 0 ;
|
||||
zoh->in_count = data->input_frames * zoh->channels ;
|
||||
zoh->out_count = data->output_frames * zoh->channels ;
|
||||
zoh->in_used = zoh->out_gen = 0 ;
|
||||
|
||||
src_ratio = psrc->last_ratio ;
|
||||
input_index = psrc->last_position ;
|
||||
src_ratio = psrc->last_ratio ;
|
||||
input_index = psrc->last_position ;
|
||||
|
||||
/* Calculate samples before first sample in input array. */
|
||||
while (input_index < 1.0 && zoh->out_gen < zoh->out_count)
|
||||
{
|
||||
if (zoh->in_used + zoh->channels * input_index >= zoh->in_count)
|
||||
break ;
|
||||
/* Calculate samples before first sample in input array. */
|
||||
while (input_index < 1.0 && zoh->out_gen < zoh->out_count)
|
||||
{
|
||||
if (zoh->in_used + zoh->channels * input_index >= zoh->in_count)
|
||||
break ;
|
||||
|
||||
if (zoh->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
|
||||
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / zoh->out_count ;
|
||||
if (zoh->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
|
||||
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / zoh->out_count ;
|
||||
|
||||
for (ch = 0 ; ch < zoh->channels ; ch++)
|
||||
{ data->data_out [zoh->out_gen] = zoh->last_value [ch] ;
|
||||
zoh->out_gen ++ ;
|
||||
} ;
|
||||
for (ch = 0 ; ch < zoh->channels ; ch++)
|
||||
{ data->data_out [zoh->out_gen] = zoh->last_value [ch] ;
|
||||
zoh->out_gen ++ ;
|
||||
} ;
|
||||
|
||||
/* Figure out the next index. */
|
||||
input_index += 1.0 / src_ratio ;
|
||||
} ;
|
||||
/* Figure out the next index. */
|
||||
input_index += 1.0 / src_ratio ;
|
||||
} ;
|
||||
|
||||
rem = fmod_one (input_index) ;
|
||||
zoh->in_used += zoh->channels * lrint (input_index - rem) ;
|
||||
input_index = rem ;
|
||||
rem = fmod_one (input_index) ;
|
||||
zoh->in_used += zoh->channels * lrint (input_index - rem) ;
|
||||
input_index = rem ;
|
||||
|
||||
/* Main processing loop. */
|
||||
while (zoh->out_gen < zoh->out_count && zoh->in_used + zoh->channels * input_index <= zoh->in_count)
|
||||
{
|
||||
if (zoh->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
|
||||
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / zoh->out_count ;
|
||||
/* Main processing loop. */
|
||||
while (zoh->out_gen < zoh->out_count && zoh->in_used + zoh->channels * input_index <= zoh->in_count)
|
||||
{
|
||||
if (zoh->out_count > 0 && fabs (psrc->last_ratio - data->src_ratio) > SRC_MIN_RATIO_DIFF)
|
||||
src_ratio = psrc->last_ratio + zoh->out_gen * (data->src_ratio - psrc->last_ratio) / zoh->out_count ;
|
||||
|
||||
for (ch = 0 ; ch < zoh->channels ; ch++)
|
||||
{ data->data_out [zoh->out_gen] = data->data_in [zoh->in_used - zoh->channels + ch] ;
|
||||
zoh->out_gen ++ ;
|
||||
} ;
|
||||
for (ch = 0 ; ch < zoh->channels ; ch++)
|
||||
{ data->data_out [zoh->out_gen] = data->data_in [zoh->in_used - zoh->channels + ch] ;
|
||||
zoh->out_gen ++ ;
|
||||
} ;
|
||||
|
||||
/* Figure out the next index. */
|
||||
input_index += 1.0 / src_ratio ;
|
||||
rem = fmod_one (input_index) ;
|
||||
/* Figure out the next index. */
|
||||
input_index += 1.0 / src_ratio ;
|
||||
rem = fmod_one (input_index) ;
|
||||
|
||||
zoh->in_used += zoh->channels * lrint (input_index - rem) ;
|
||||
input_index = rem ;
|
||||
} ;
|
||||
zoh->in_used += zoh->channels * lrint (input_index - rem) ;
|
||||
input_index = rem ;
|
||||
} ;
|
||||
|
||||
if (zoh->in_used > zoh->in_count)
|
||||
{ input_index += (zoh->in_used - zoh->in_count) / zoh->channels ;
|
||||
zoh->in_used = zoh->in_count ;
|
||||
} ;
|
||||
if (zoh->in_used > zoh->in_count)
|
||||
{ input_index += (zoh->in_used - zoh->in_count) / zoh->channels ;
|
||||
zoh->in_used = zoh->in_count ;
|
||||
} ;
|
||||
|
||||
psrc->last_position = input_index ;
|
||||
psrc->last_position = input_index ;
|
||||
|
||||
if (zoh->in_used > 0)
|
||||
for (ch = 0 ; ch < zoh->channels ; ch++)
|
||||
zoh->last_value [ch] = data->data_in [zoh->in_used - zoh->channels + ch] ;
|
||||
if (zoh->in_used > 0)
|
||||
for (ch = 0 ; ch < zoh->channels ; ch++)
|
||||
zoh->last_value [ch] = data->data_in [zoh->in_used - zoh->channels + ch] ;
|
||||
|
||||
/* Save current ratio rather then target ratio. */
|
||||
psrc->last_ratio = src_ratio ;
|
||||
/* Save current ratio rather then target ratio. */
|
||||
psrc->last_ratio = src_ratio ;
|
||||
|
||||
data->input_frames_used = zoh->in_used / zoh->channels ;
|
||||
data->output_frames_gen = zoh->out_gen / zoh->channels ;
|
||||
data->input_frames_used = zoh->in_used / zoh->channels ;
|
||||
data->output_frames_gen = zoh->out_gen / zoh->channels ;
|
||||
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
} /* zoh_vari_process */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
@ -142,53 +142,53 @@ zoh_vari_process (SRC_PRIVATE *psrc, SRC_DATA *data)
|
||||
const char*
|
||||
zoh_get_name (int src_enum)
|
||||
{
|
||||
if (src_enum == SRC_ZERO_ORDER_HOLD)
|
||||
return "ZOH Interpolator" ;
|
||||
if (src_enum == SRC_ZERO_ORDER_HOLD)
|
||||
return "ZOH Interpolator" ;
|
||||
|
||||
return NULL ;
|
||||
return NULL ;
|
||||
} /* zoh_get_name */
|
||||
|
||||
const char*
|
||||
zoh_get_description (int src_enum)
|
||||
{
|
||||
if (src_enum == SRC_ZERO_ORDER_HOLD)
|
||||
return "Zero order hold interpolator, very fast, poor quality." ;
|
||||
if (src_enum == SRC_ZERO_ORDER_HOLD)
|
||||
return "Zero order hold interpolator, very fast, poor quality." ;
|
||||
|
||||
return NULL ;
|
||||
return NULL ;
|
||||
} /* zoh_get_descrition */
|
||||
|
||||
int
|
||||
zoh_set_converter (SRC_PRIVATE *psrc, int src_enum)
|
||||
{ ZOH_DATA *zoh = NULL ;
|
||||
{ ZOH_DATA *zoh = NULL ;
|
||||
|
||||
if (src_enum != SRC_ZERO_ORDER_HOLD)
|
||||
return SRC_ERR_BAD_CONVERTER ;
|
||||
if (src_enum != SRC_ZERO_ORDER_HOLD)
|
||||
return SRC_ERR_BAD_CONVERTER ;
|
||||
|
||||
if (psrc->private_data != NULL)
|
||||
{ zoh = (ZOH_DATA*) psrc->private_data ;
|
||||
if (zoh->zoh_magic_marker != ZOH_MAGIC_MARKER)
|
||||
{ free (psrc->private_data) ;
|
||||
psrc->private_data = NULL ;
|
||||
} ;
|
||||
} ;
|
||||
if (psrc->private_data != NULL)
|
||||
{ zoh = (ZOH_DATA*) psrc->private_data ;
|
||||
if (zoh->zoh_magic_marker != ZOH_MAGIC_MARKER)
|
||||
{ free (psrc->private_data) ;
|
||||
psrc->private_data = NULL ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psrc->private_data == NULL)
|
||||
{ zoh = calloc (1, sizeof (*zoh) + psrc->channels * sizeof (float)) ;
|
||||
if (zoh == NULL)
|
||||
return SRC_ERR_MALLOC_FAILED ;
|
||||
psrc->private_data = zoh ;
|
||||
} ;
|
||||
if (psrc->private_data == NULL)
|
||||
{ zoh = calloc (1, sizeof (*zoh) + psrc->channels * sizeof (float)) ;
|
||||
if (zoh == NULL)
|
||||
return SRC_ERR_MALLOC_FAILED ;
|
||||
psrc->private_data = zoh ;
|
||||
} ;
|
||||
|
||||
zoh->zoh_magic_marker = ZOH_MAGIC_MARKER ;
|
||||
zoh->channels = psrc->channels ;
|
||||
zoh->zoh_magic_marker = ZOH_MAGIC_MARKER ;
|
||||
zoh->channels = psrc->channels ;
|
||||
|
||||
psrc->const_process = zoh_vari_process ;
|
||||
psrc->vari_process = zoh_vari_process ;
|
||||
psrc->reset = zoh_reset ;
|
||||
psrc->const_process = zoh_vari_process ;
|
||||
psrc->vari_process = zoh_vari_process ;
|
||||
psrc->reset = zoh_reset ;
|
||||
|
||||
zoh_reset (psrc) ;
|
||||
zoh_reset (psrc) ;
|
||||
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
return SRC_ERR_NO_ERROR ;
|
||||
} /* zoh_set_converter */
|
||||
|
||||
/*===================================================================================
|
||||
@ -196,16 +196,16 @@ zoh_set_converter (SRC_PRIVATE *psrc, int src_enum)
|
||||
|
||||
static void
|
||||
zoh_reset (SRC_PRIVATE *psrc)
|
||||
{ ZOH_DATA *zoh ;
|
||||
{ ZOH_DATA *zoh ;
|
||||
|
||||
zoh = (ZOH_DATA*) psrc->private_data ;
|
||||
if (zoh == NULL)
|
||||
return ;
|
||||
zoh = (ZOH_DATA*) psrc->private_data ;
|
||||
if (zoh == NULL)
|
||||
return ;
|
||||
|
||||
zoh->channels = psrc->channels ;
|
||||
zoh->reset = 1 ;
|
||||
memset (zoh->last_value, 0, sizeof (zoh->last_value [0]) * zoh->channels) ;
|
||||
zoh->channels = psrc->channels ;
|
||||
zoh->reset = 1 ;
|
||||
memset (zoh->last_value, 0, sizeof (zoh->last_value [0]) * zoh->channels) ;
|
||||
|
||||
return ;
|
||||
return ;
|
||||
} /* zoh_reset */
|
||||
|
||||
|
1916
source/sound/fm.c
1916
source/sound/fm.c
File diff suppressed because it is too large
Load Diff
@ -37,7 +37,7 @@ static const int PSGVolumeValues[2][16] = {
|
||||
/* These values are taken from a real SMS2's output */
|
||||
{892,892,892,760,623,497,404,323,257,198,159,123,96,75,60,0}, /* I can't remember why 892... :P some scaling I did at some point */
|
||||
/* these values are true volumes for 2dB drops at each step (multiply previous by 10^-0.1), normalised at 760 */
|
||||
{1516,1205,957,760,603,479,381,303,240,191,152,120,96,76,60,0}
|
||||
{1516,1205,957,760,603,479,381,303,240,191,152,120,96,76,60,0}
|
||||
};
|
||||
|
||||
static SN76489_Context SN76489[MAX_SN76489];
|
||||
@ -126,33 +126,33 @@ void SN76489_Write(int which, int data)
|
||||
{
|
||||
SN76489_Context *p = &SN76489[which];
|
||||
|
||||
if (data&0x80) {
|
||||
if (data&0x80) {
|
||||
/* Latch/data byte %1 cc t dddd */
|
||||
p->LatchedRegister=((data>>4)&0x07);
|
||||
p->Registers[p->LatchedRegister]=
|
||||
(p->Registers[p->LatchedRegister] & 0x3f0) /* zero low 4 bits */
|
||||
| (data&0xf); /* and replace with data */
|
||||
} else {
|
||||
} else {
|
||||
/* Data byte %0 - dddddd */
|
||||
if (!(p->LatchedRegister%2)&&(p->LatchedRegister<5))
|
||||
/* Tone register */
|
||||
p->Registers[p->LatchedRegister]=
|
||||
(p->Registers[p->LatchedRegister] & 0x00f) /* zero high 6 bits */
|
||||
| ((data&0x3f)<<4); /* and replace with data */
|
||||
else
|
||||
else
|
||||
/* Other register */
|
||||
p->Registers[p->LatchedRegister]=data&0x0f; /* Replace with data */
|
||||
}
|
||||
switch (p->LatchedRegister) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 0:
|
||||
case 2:
|
||||
case 4: /* Tone channels */
|
||||
if (p->Registers[p->LatchedRegister]==0) p->Registers[p->LatchedRegister]=1; /* Zero frequency changed to 1 to avoid div/0 */
|
||||
break;
|
||||
break;
|
||||
case 6: /* Noise */
|
||||
p->NoiseShiftRegister=NoiseInitialState; /* reset shift register */
|
||||
p->NoiseFreq=0x10<<(p->Registers[6]&0x3); /* set noise signal generator frequency */
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,56 +48,56 @@ int fm_reg[2][0x100];
|
||||
/* return the number of samples that should have been rendered so far */
|
||||
static inline uint32 fm_sample_cnt(uint8 is_z80)
|
||||
{
|
||||
if (is_z80) return (uint32) ((double)(count_z80 + current_z80 - z80_ICount) / z80cycles_per_sample[0]);
|
||||
else return (uint32) ((double) count_m68k / m68cycles_per_sample[0]);
|
||||
if (is_z80) return (uint32) ((double)(count_z80 + current_z80 - z80_ICount) / z80cycles_per_sample[0]);
|
||||
else return (uint32) ((double) count_m68k / m68cycles_per_sample[0]);
|
||||
}
|
||||
|
||||
static inline uint32 psg_sample_cnt(uint8 is_z80)
|
||||
{
|
||||
if (is_z80) return (uint32) ((double)(count_z80 + current_z80 - z80_ICount) / z80cycles_per_sample[1]);
|
||||
else return (uint32) ((double) count_m68k / m68cycles_per_sample[1]);
|
||||
if (is_z80) return (uint32) ((double)(count_z80 + current_z80 - z80_ICount) / z80cycles_per_sample[1]);
|
||||
else return (uint32) ((double) count_m68k / m68cycles_per_sample[1]);
|
||||
}
|
||||
|
||||
/* update FM samples */
|
||||
static inline void fm_update()
|
||||
{
|
||||
if(snd.fm.curStage - snd.fm.lastStage > 0)
|
||||
{
|
||||
int *tempBuffer[2];
|
||||
if(snd.fm.curStage - snd.fm.lastStage > 0)
|
||||
{
|
||||
int *tempBuffer[2];
|
||||
|
||||
if (config.hq_fm && !config.fm_core)
|
||||
{
|
||||
tempBuffer[0] = src_buffer[0] + snd.fm.lastStage;
|
||||
tempBuffer[1] = src_buffer[1] + snd.fm.lastStage;
|
||||
tempBuffer[1] = src_buffer[1] + snd.fm.lastStage;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempBuffer[0] = snd.fm.buffer[0] + snd.fm.lastStage;
|
||||
tempBuffer[1] = snd.fm.buffer[1] + snd.fm.lastStage;
|
||||
tempBuffer[1] = snd.fm.buffer[1] + snd.fm.lastStage;
|
||||
}
|
||||
|
||||
_YM2612_Update(tempBuffer, snd.fm.curStage - snd.fm.lastStage);
|
||||
snd.fm.lastStage = snd.fm.curStage;
|
||||
}
|
||||
_YM2612_Update(tempBuffer, snd.fm.curStage - snd.fm.lastStage);
|
||||
snd.fm.lastStage = snd.fm.curStage;
|
||||
}
|
||||
}
|
||||
|
||||
/* update PSG samples */
|
||||
static inline void psg_update()
|
||||
{
|
||||
if(snd.psg.curStage - snd.psg.lastStage > 0)
|
||||
{
|
||||
int16 *tempBuffer = snd.psg.buffer + snd.psg.lastStage;
|
||||
SN76489_Update (0, tempBuffer, snd.psg.curStage - snd.psg.lastStage);
|
||||
snd.psg.lastStage = snd.psg.curStage;
|
||||
}
|
||||
if(snd.psg.curStage - snd.psg.lastStage > 0)
|
||||
{
|
||||
int16 *tempBuffer = snd.psg.buffer + snd.psg.lastStage;
|
||||
SN76489_Update (0, tempBuffer, snd.psg.curStage - snd.psg.lastStage);
|
||||
snd.psg.lastStage = snd.psg.curStage;
|
||||
}
|
||||
}
|
||||
|
||||
void sound_init(int rate)
|
||||
{
|
||||
double vclk = (vdp_pal ? (double)CLOCK_PAL : (double)CLOCK_NTSC) / 7.0; /* 68000 and YM2612 clock */
|
||||
double zclk = (vdp_pal ? (double)CLOCK_PAL : (double)CLOCK_NTSC) / 15.0; /* Z80 and SN76489 clock */
|
||||
double vclk = (vdp_pal ? (double)CLOCK_PAL : (double)CLOCK_NTSC) / 7.0; /* 68000 and YM2612 clock */
|
||||
double zclk = (vdp_pal ? (double)CLOCK_PAL : (double)CLOCK_NTSC) / 15.0; /* Z80 and SN76489 clock */
|
||||
|
||||
/* cycle-accurate FM samples */
|
||||
/* cycle-accurate FM samples */
|
||||
if (config.hq_fm && !config.fm_core)
|
||||
{
|
||||
m68cycles_per_sample[0] = 144.0;
|
||||
@ -113,44 +113,44 @@ void sound_init(int rate)
|
||||
else
|
||||
{
|
||||
m68cycles_per_sample[0] = ((double)m68cycles_per_line * (double)lines_per_frame) / (double) (rate / vdp_rate);
|
||||
z80cycles_per_sample[0] = ((double)z80cycles_per_line * (double)lines_per_frame) / (double) (rate / vdp_rate);
|
||||
z80cycles_per_sample[0] = ((double)z80cycles_per_line * (double)lines_per_frame) / (double) (rate / vdp_rate);
|
||||
}
|
||||
|
||||
/* cycle-accurate PSG samples */
|
||||
m68cycles_per_sample[1] = ((double)m68cycles_per_line * (double)lines_per_frame) / (double) (rate / vdp_rate);
|
||||
z80cycles_per_sample[1] = ((double)z80cycles_per_line * (double)lines_per_frame) / (double) (rate / vdp_rate);
|
||||
|
||||
/* initialize sound chips */
|
||||
SN76489_Init(0, (int)zclk, rate);
|
||||
SN76489_Config(0, MUTE_ALLON, VOL_FULL, FB_SEGAVDP, SRW_SEGAVDP, 0);
|
||||
/* initialize sound chips */
|
||||
SN76489_Init(0, (int)zclk, rate);
|
||||
SN76489_Config(0, MUTE_ALLON, VOL_FULL, FB_SEGAVDP, SRW_SEGAVDP, 0);
|
||||
|
||||
if (config.fm_core)
|
||||
{
|
||||
_YM2612_Write = YM2612_Write;
|
||||
_YM2612_Read = YM2612_Read;
|
||||
_YM2612_Update = YM2612_Update;
|
||||
_YM2612_Reset = YM2612_Reset;
|
||||
YM2612_Init((int)vclk, rate, config.hq_fm);
|
||||
}
|
||||
else
|
||||
{
|
||||
_YM2612_Write = YM2612Write;
|
||||
_YM2612_Read = YM2612Read;
|
||||
_YM2612_Update = YM2612UpdateOne;
|
||||
_YM2612_Reset = YM2612ResetChip;
|
||||
YM2612Init ((int)vclk, rate);
|
||||
}
|
||||
if (config.fm_core)
|
||||
{
|
||||
_YM2612_Write = YM2612_Write;
|
||||
_YM2612_Read = YM2612_Read;
|
||||
_YM2612_Update = YM2612_Update;
|
||||
_YM2612_Reset = YM2612_Reset;
|
||||
YM2612_Init((int)vclk, rate, config.hq_fm);
|
||||
}
|
||||
else
|
||||
{
|
||||
_YM2612_Write = YM2612Write;
|
||||
_YM2612_Read = YM2612Read;
|
||||
_YM2612_Update = YM2612UpdateOne;
|
||||
_YM2612_Reset = YM2612ResetChip;
|
||||
YM2612Init ((int)vclk, rate);
|
||||
}
|
||||
}
|
||||
|
||||
void sound_update(void)
|
||||
{
|
||||
/* finalize sound buffers */
|
||||
snd.fm.curStage = (config.hq_fm && !config.fm_core) ? src_data.input_frames : snd.buffer_size;
|
||||
snd.psg.curStage = snd.buffer_size;
|
||||
/* finalize sound buffers */
|
||||
snd.fm.curStage = (config.hq_fm && !config.fm_core) ? src_data.input_frames : snd.buffer_size;
|
||||
snd.psg.curStage = snd.buffer_size;
|
||||
|
||||
/* update last samples (if needed) */
|
||||
fm_update();
|
||||
psg_update();
|
||||
/* update last samples (if needed) */
|
||||
fm_update();
|
||||
psg_update();
|
||||
|
||||
/* Resampling */
|
||||
if (config.hq_fm && !config.fm_core)
|
||||
@ -158,18 +158,18 @@ void sound_update(void)
|
||||
double scaled_value ;
|
||||
int len = src_data.input_frames;
|
||||
|
||||
/* this is basically libsamplerate "src_int_to_float_array" function, adapted to interlace samples */
|
||||
/* this is basically libsamplerate "src_int_to_float_array" function, adapted to interlace samples */
|
||||
while (len)
|
||||
{
|
||||
{
|
||||
len -- ;
|
||||
src_in[len*2] = (float) (src_buffer[0] [len] / (8.0 * 0x10000000));
|
||||
src_in[len*2 + 1] = (float) (src_buffer[1] [len] / (8.0 * 0x10000000));
|
||||
}
|
||||
src_in[len*2] = (float) (src_buffer[0] [len] / (8.0 * 0x10000000));
|
||||
src_in[len*2 + 1] = (float) (src_buffer[1] [len] / (8.0 * 0x10000000));
|
||||
}
|
||||
|
||||
/* samplerate conversion */
|
||||
src_simple (&src_data, (config.hq_fm&1) ? SRC_LINEAR : SRC_SINC_FASTEST, 2);
|
||||
|
||||
/* this is basically libsamplerate "src_float_to_int_array" function, adapted to interlace samples */
|
||||
/* this is basically libsamplerate "src_float_to_int_array" function, adapted to interlace samples */
|
||||
len = snd.buffer_size;
|
||||
while (len)
|
||||
{
|
||||
@ -194,28 +194,28 @@ void sound_update(void)
|
||||
}
|
||||
|
||||
/* reset samples count */
|
||||
snd.fm.curStage = 0;
|
||||
snd.fm.lastStage = 0;
|
||||
snd.psg.curStage = 0;
|
||||
snd.psg.lastStage = 0;
|
||||
snd.fm.curStage = 0;
|
||||
snd.fm.lastStage = 0;
|
||||
snd.psg.curStage = 0;
|
||||
snd.psg.lastStage = 0;
|
||||
}
|
||||
|
||||
/* YM2612 control */
|
||||
/* restore FM registers */
|
||||
void fm_restore(void)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
_YM2612_Reset();
|
||||
_YM2612_Reset();
|
||||
|
||||
/* feed all the registers and update internal state */
|
||||
for(i = 0; i < 0x100; i++)
|
||||
{
|
||||
_YM2612_Write(0, i);
|
||||
_YM2612_Write(1, fm_reg[0][i]);
|
||||
_YM2612_Write(2, i);
|
||||
_YM2612_Write(3, fm_reg[1][i]);
|
||||
}
|
||||
/* feed all the registers and update internal state */
|
||||
for(i = 0; i < 0x100; i++)
|
||||
{
|
||||
_YM2612_Write(0, i);
|
||||
_YM2612_Write(1, fm_reg[0][i]);
|
||||
_YM2612_Write(2, i);
|
||||
_YM2612_Write(3, fm_reg[1][i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* write FM chip */
|
||||
@ -224,7 +224,7 @@ void fm_write(unsigned int cpu, unsigned int address, unsigned int data)
|
||||
if (address & 1)
|
||||
{
|
||||
snd.fm.curStage = fm_sample_cnt(cpu);
|
||||
fm_update();
|
||||
fm_update();
|
||||
}
|
||||
_YM2612_Write(address & 3, data);
|
||||
}
|
||||
@ -232,16 +232,16 @@ void fm_write(unsigned int cpu, unsigned int address, unsigned int data)
|
||||
/* read FM status */
|
||||
unsigned int fm_read(unsigned int cpu, unsigned int address)
|
||||
{
|
||||
snd.fm.curStage = fm_sample_cnt(cpu);
|
||||
fm_update();
|
||||
return (_YM2612_Read() & 0xff);
|
||||
snd.fm.curStage = fm_sample_cnt(cpu);
|
||||
fm_update();
|
||||
return (_YM2612_Read() & 0xff);
|
||||
}
|
||||
|
||||
|
||||
/* PSG write */
|
||||
void psg_write(unsigned int cpu, unsigned int data)
|
||||
{
|
||||
snd.psg.curStage = psg_sample_cnt(cpu);
|
||||
psg_update();
|
||||
SN76489_Write(0, data);
|
||||
snd.psg.curStage = psg_sample_cnt(cpu);
|
||||
psg_update();
|
||||
SN76489_Write(0, data);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,93 +14,93 @@
|
||||
#define _YM2612_H_
|
||||
|
||||
// Change it if you need to do long update
|
||||
#define MAX_UPDATE_LENGHT 2000
|
||||
#define MAX_UPDATE_LENGHT 2000
|
||||
|
||||
// Gens always uses 16 bits sound (in 32 bits buffer) and do the convertion later if needed.
|
||||
#define OUTPUT_BITS 16
|
||||
|
||||
typedef struct slot__ {
|
||||
int *DT; // paramètre detune
|
||||
int MUL; // paramètre "multiple de fréquence"
|
||||
int TL; // Total Level = volume lorsque l'enveloppe est au plus haut
|
||||
int TLL; // Total Level ajusted
|
||||
int SLL; // Sustin Level (ajusted) = volume où l'enveloppe termine sa première phase de régression
|
||||
int KSR_S; // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe
|
||||
int KSR; // Key Scale Rate = cette valeur est calculée par rapport à la fréquence actuelle, elle va influer
|
||||
// sur les différents paramètres de l'enveloppe comme l'attaque, le decay ... comme dans la réalité !
|
||||
int SEG; // Type enveloppe SSG
|
||||
int *AR; // Attack Rate (table pointeur) = Taux d'attaque (AR[KSR])
|
||||
int *DR; // Decay Rate (table pointeur) = Taux pour la régression (DR[KSR])
|
||||
int *SR; // Sustin Rate (table pointeur) = Taux pour le maintien (SR[KSR])
|
||||
int *RR; // Release Rate (table pointeur) = Taux pour le relâchement (RR[KSR])
|
||||
int Fcnt; // Frequency Count = compteur-fréquence pour déterminer l'amplitude actuelle (SIN[Finc >> 16])
|
||||
int Finc; // frequency step = pas d'incrémentation du compteur-fréquence
|
||||
// plus le pas est grand, plus la fréquence est aïgu (ou haute)
|
||||
int Ecurp; // Envelope current phase = cette variable permet de savoir dans quelle phase
|
||||
// de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...
|
||||
// en fonction de la valeur de cette variable, on va appeler une fonction permettant
|
||||
// de mettre à jour l'enveloppe courante.
|
||||
int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir où l'on se trouve dans l'enveloppe
|
||||
int Einc; // Envelope step courant
|
||||
int Ecmp; // Envelope counter limite pour la prochaine phase
|
||||
int EincA; // Envelope step for Attack = pas d'incrémentation du compteur durant la phase d'attaque
|
||||
// cette valeur est égal à AR[KSR]
|
||||
int EincD; // Envelope step for Decay = pas d'incrémentation du compteur durant la phase de regression
|
||||
// cette valeur est égal à DR[KSR]
|
||||
int EincS; // Envelope step for Sustain = pas d'incrémentation du compteur durant la phase de maintenue
|
||||
// cette valeur est égal à SR[KSR]
|
||||
int EincR; // Envelope step for Release = pas d'incrémentation du compteur durant la phase de relâchement
|
||||
// cette valeur est égal à RR[KSR]
|
||||
int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot à l'entrée
|
||||
// d'un autre ou carrement à la sortie de la voie
|
||||
int INd; // input data of the slot = données en entrée du slot
|
||||
int ChgEnM; // Change envelop mask.
|
||||
int AMS; // AMS depth level of this SLOT = degré de modulation de l'amplitude par le LFO
|
||||
int AMSon; // AMS enable flag = drapeau d'activation de l'AMS
|
||||
int *DT; // paramètre detune
|
||||
int MUL; // paramètre "multiple de fréquence"
|
||||
int TL; // Total Level = volume lorsque l'enveloppe est au plus haut
|
||||
int TLL; // Total Level ajusted
|
||||
int SLL; // Sustin Level (ajusted) = volume où l'enveloppe termine sa première phase de régression
|
||||
int KSR_S; // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe
|
||||
int KSR; // Key Scale Rate = cette valeur est calculée par rapport à la fréquence actuelle, elle va influer
|
||||
// sur les différents paramètres de l'enveloppe comme l'attaque, le decay ... comme dans la réalité !
|
||||
int SEG; // Type enveloppe SSG
|
||||
int *AR; // Attack Rate (table pointeur) = Taux d'attaque (AR[KSR])
|
||||
int *DR; // Decay Rate (table pointeur) = Taux pour la régression (DR[KSR])
|
||||
int *SR; // Sustin Rate (table pointeur) = Taux pour le maintien (SR[KSR])
|
||||
int *RR; // Release Rate (table pointeur) = Taux pour le relâchement (RR[KSR])
|
||||
int Fcnt; // Frequency Count = compteur-fréquence pour déterminer l'amplitude actuelle (SIN[Finc >> 16])
|
||||
int Finc; // frequency step = pas d'incrémentation du compteur-fréquence
|
||||
// plus le pas est grand, plus la fréquence est aïgu (ou haute)
|
||||
int Ecurp; // Envelope current phase = cette variable permet de savoir dans quelle phase
|
||||
// de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...
|
||||
// en fonction de la valeur de cette variable, on va appeler une fonction permettant
|
||||
// de mettre à jour l'enveloppe courante.
|
||||
int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir où l'on se trouve dans l'enveloppe
|
||||
int Einc; // Envelope step courant
|
||||
int Ecmp; // Envelope counter limite pour la prochaine phase
|
||||
int EincA; // Envelope step for Attack = pas d'incrémentation du compteur durant la phase d'attaque
|
||||
// cette valeur est égal à AR[KSR]
|
||||
int EincD; // Envelope step for Decay = pas d'incrémentation du compteur durant la phase de regression
|
||||
// cette valeur est égal à DR[KSR]
|
||||
int EincS; // Envelope step for Sustain = pas d'incrémentation du compteur durant la phase de maintenue
|
||||
// cette valeur est égal à SR[KSR]
|
||||
int EincR; // Envelope step for Release = pas d'incrémentation du compteur durant la phase de relâchement
|
||||
// cette valeur est égal à RR[KSR]
|
||||
int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot à l'entrée
|
||||
// d'un autre ou carrement à la sortie de la voie
|
||||
int INd; // input data of the slot = données en entrée du slot
|
||||
int ChgEnM; // Change envelop mask.
|
||||
int AMS; // AMS depth level of this SLOT = degré de modulation de l'amplitude par le LFO
|
||||
int AMSon; // AMS enable flag = drapeau d'activation de l'AMS
|
||||
} slot_;
|
||||
|
||||
typedef struct channel__ {
|
||||
int S0_OUT[4]; // anciennes sorties slot 0 (pour le feed back)
|
||||
int Old_OUTd; // ancienne sortie de la voie (son brut)
|
||||
int OUTd; // sortie de la voie (son brut)
|
||||
int LEFT; // LEFT enable flag
|
||||
int RIGHT; // RIGHT enable flag
|
||||
int ALGO; // Algorythm = détermine les connections entre les opérateurs
|
||||
int FB; // shift count of self feed back = degré de "Feed-Back" du SLOT 1 (il est son unique entrée)
|
||||
int FMS; // Fréquency Modulation Sensitivity of channel = degré de modulation de la fréquence sur la voie par le LFO
|
||||
int AMS; // Amplitude Modulation Sensitivity of channel = degré de modulation de l'amplitude sur la voie par le LFO
|
||||
int FNUM[4]; // hauteur fréquence de la voie (+ 3 pour le mode spécial)
|
||||
int FOCT[4]; // octave de la voie (+ 3 pour le mode spécial)
|
||||
int KC[4]; // Key Code = valeur fonction de la fréquence (voir KSR pour les slots, KSR = KC >> KSR_S)
|
||||
struct slot__ SLOT[4]; // four slot.operators = les 4 slots de la voie
|
||||
int FFlag; // Frequency step recalculation flag
|
||||
int S0_OUT[4]; // anciennes sorties slot 0 (pour le feed back)
|
||||
int Old_OUTd; // ancienne sortie de la voie (son brut)
|
||||
int OUTd; // sortie de la voie (son brut)
|
||||
int LEFT; // LEFT enable flag
|
||||
int RIGHT; // RIGHT enable flag
|
||||
int ALGO; // Algorythm = détermine les connections entre les opérateurs
|
||||
int FB; // shift count of self feed back = degré de "Feed-Back" du SLOT 1 (il est son unique entrée)
|
||||
int FMS; // Fréquency Modulation Sensitivity of channel = degré de modulation de la fréquence sur la voie par le LFO
|
||||
int AMS; // Amplitude Modulation Sensitivity of channel = degré de modulation de l'amplitude sur la voie par le LFO
|
||||
int FNUM[4]; // hauteur fréquence de la voie (+ 3 pour le mode spécial)
|
||||
int FOCT[4]; // octave de la voie (+ 3 pour le mode spécial)
|
||||
int KC[4]; // Key Code = valeur fonction de la fréquence (voir KSR pour les slots, KSR = KC >> KSR_S)
|
||||
struct slot__ SLOT[4]; // four slot.operators = les 4 slots de la voie
|
||||
int FFlag; // Frequency step recalculation flag
|
||||
} channel_;
|
||||
|
||||
typedef struct ym2612__ {
|
||||
int Clock; // Horloge YM2612
|
||||
int Rate; // Sample Rate (11025/22050/44100)
|
||||
int TimerBase; // TimerBase calculation
|
||||
int Status; // YM2612 Status (timer overflow)
|
||||
int OPNAadr; // addresse pour l'écriture dans l'OPN A (propre à l'émulateur)
|
||||
int OPNBadr; // addresse pour l'écriture dans l'OPN B (propre à l'émulateur)
|
||||
int LFOcnt; // LFO counter = compteur-fréquence pour le LFO
|
||||
int LFOinc; // LFO step counter = pas d'incrémentation du compteur-fréquence du LFO
|
||||
// plus le pas est grand, plus la fréquence est grande
|
||||
int TimerA; // timerA limit = valeur jusqu'à laquelle le timer A doit compter
|
||||
int TimerAL;
|
||||
int TimerAcnt; // timerA counter = valeur courante du Timer A
|
||||
int TimerB; // timerB limit = valeur jusqu'à laquelle le timer B doit compter
|
||||
int TimerBL;
|
||||
int TimerBcnt; // timerB counter = valeur courante du Timer B
|
||||
int Mode; // Mode actuel des voie 3 et 6 (normal / spécial)
|
||||
int DAC; // DAC enabled flag
|
||||
int DACdata; // DAC data
|
||||
double Frequence; // Fréquence de base, se calcul par rapport à l'horlage et au sample rate
|
||||
unsigned int Inter_Cnt; // Interpolation Counter
|
||||
unsigned int Inter_Step; // Interpolation Step
|
||||
struct channel__ CHANNEL[6]; // Les 6 voies du YM2612
|
||||
int REG[2][0x100]; // Sauvegardes des valeurs de tout les registres, c'est facultatif
|
||||
// cela nous rend le débuggage plus facile
|
||||
int Clock; // Horloge YM2612
|
||||
int Rate; // Sample Rate (11025/22050/44100)
|
||||
int TimerBase; // TimerBase calculation
|
||||
int Status; // YM2612 Status (timer overflow)
|
||||
int OPNAadr; // addresse pour l'écriture dans l'OPN A (propre à l'émulateur)
|
||||
int OPNBadr; // addresse pour l'écriture dans l'OPN B (propre à l'émulateur)
|
||||
int LFOcnt; // LFO counter = compteur-fréquence pour le LFO
|
||||
int LFOinc; // LFO step counter = pas d'incrémentation du compteur-fréquence du LFO
|
||||
// plus le pas est grand, plus la fréquence est grande
|
||||
int TimerA; // timerA limit = valeur jusqu'à laquelle le timer A doit compter
|
||||
int TimerAL;
|
||||
int TimerAcnt; // timerA counter = valeur courante du Timer A
|
||||
int TimerB; // timerB limit = valeur jusqu'à laquelle le timer B doit compter
|
||||
int TimerBL;
|
||||
int TimerBcnt; // timerB counter = valeur courante du Timer B
|
||||
int Mode; // Mode actuel des voie 3 et 6 (normal / spécial)
|
||||
int DAC; // DAC enabled flag
|
||||
int DACdata; // DAC data
|
||||
double Frequence; // Fréquence de base, se calcul par rapport à l'horlage et au sample rate
|
||||
unsigned int Inter_Cnt; // Interpolation Counter
|
||||
unsigned int Inter_Step; // Interpolation Step
|
||||
struct channel__ CHANNEL[6]; // Les 6 voies du YM2612
|
||||
int REG[2][0x100]; // Sauvegardes des valeurs de tout les registres, c'est facultatif
|
||||
// cela nous rend le débuggage plus facile
|
||||
} ym2612_;
|
||||
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
#define uint8 unsigned char
|
||||
#define uint16 unsigned short
|
||||
#define uint32 unsigned int
|
||||
#define uint32 unsigned int
|
||||
#define int8 signed char
|
||||
#define int16 signed short
|
||||
#define int32 signed long int
|
||||
#define int32 signed long int
|
||||
|
||||
|
1301
source/unzip.c
1301
source/unzip.c
File diff suppressed because it is too large
Load Diff
274
source/unzip.h
274
source/unzip.h
@ -1,274 +0,0 @@
|
||||
/* unzip.h -- IO for uncompress .zip files using zlib
|
||||
Version 0.15 beta, Mar 19th, 1998,
|
||||
|
||||
Copyright (C) 1998 Gilles Vollant
|
||||
|
||||
This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
|
||||
WinZip, InfoZip tools and compatible.
|
||||
Encryption and multi volume ZipFile (span) are not supported.
|
||||
Old compressions used by old PKZip 1.x are not supported
|
||||
|
||||
THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
|
||||
CAN CHANGE IN FUTURE VERSION !!
|
||||
I WAIT FEEDBACK at mail info@winimage.com
|
||||
Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
|
||||
|
||||
Condition of use and distribution are the same than zlib :
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* for more info about .ZIP format, see
|
||||
ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
|
||||
PkWare has also a specification at :
|
||||
ftp://ftp.pkware.com/probdesc.zip */
|
||||
|
||||
#ifndef _unz_H
|
||||
#define _unz_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagunzFile__ { int unused; } unzFile__;
|
||||
typedef unzFile__ *unzFile;
|
||||
#else
|
||||
typedef voidp unzFile;
|
||||
#endif
|
||||
|
||||
|
||||
#define UNZ_OK (0)
|
||||
#define UNZ_END_OF_LIST_OF_FILE (-100)
|
||||
#define UNZ_ERRNO (Z_ERRNO)
|
||||
#define UNZ_EOF (0)
|
||||
#define UNZ_PARAMERROR (-102)
|
||||
#define UNZ_BADZIPFILE (-103)
|
||||
#define UNZ_INTERNALERROR (-104)
|
||||
#define UNZ_CRCERROR (-105)
|
||||
|
||||
/* tm_unz contain date/time info */
|
||||
typedef struct tm_unz_s
|
||||
{
|
||||
uInt tm_sec; /* seconds after the minute - [0,59] */
|
||||
uInt tm_min; /* minutes after the hour - [0,59] */
|
||||
uInt tm_hour; /* hours since midnight - [0,23] */
|
||||
uInt tm_mday; /* day of the month - [1,31] */
|
||||
uInt tm_mon; /* months since January - [0,11] */
|
||||
uInt tm_year; /* years - [1980..2044] */
|
||||
} tm_unz;
|
||||
|
||||
/* unz_global_info structure contain global data about the ZIPfile
|
||||
These data comes from the end of central dir */
|
||||
typedef struct unz_global_info_s
|
||||
{
|
||||
uLong number_entry; /* total number of entries in
|
||||
the central dir on this disk */
|
||||
uLong size_comment; /* size of the global comment of the zipfile */
|
||||
} unz_global_info;
|
||||
|
||||
|
||||
/* unz_file_info contain information about a file in the zipfile */
|
||||
typedef struct unz_file_info_s
|
||||
{
|
||||
uLong version; /* version made by 2 bytes */
|
||||
uLong version_needed; /* version needed to extract 2 bytes */
|
||||
uLong flag; /* general purpose bit flag 2 bytes */
|
||||
uLong compression_method; /* compression method 2 bytes */
|
||||
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
|
||||
uLong crc; /* crc-32 4 bytes */
|
||||
uLong compressed_size; /* compressed size 4 bytes */
|
||||
uLong uncompressed_size; /* uncompressed size 4 bytes */
|
||||
uLong size_filename; /* filename length 2 bytes */
|
||||
uLong size_file_extra; /* extra field length 2 bytes */
|
||||
uLong size_file_comment; /* file comment length 2 bytes */
|
||||
|
||||
uLong disk_num_start; /* disk number start 2 bytes */
|
||||
uLong internal_fa; /* internal file attributes 2 bytes */
|
||||
uLong external_fa; /* external file attributes 4 bytes */
|
||||
|
||||
tm_unz tmu_date;
|
||||
} unz_file_info;
|
||||
|
||||
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
|
||||
const char* fileName2,
|
||||
int iCaseSensitivity));
|
||||
/*
|
||||
Compare two filename (fileName1,fileName2).
|
||||
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
|
||||
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
|
||||
or strcasecmp)
|
||||
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
|
||||
(like 1 on Unix, 2 on Windows)
|
||||
*/
|
||||
|
||||
|
||||
extern unzFile ZEXPORT unzOpen OF((const char *path));
|
||||
/*
|
||||
Open a Zip file. path contain the full pathname (by example,
|
||||
on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
|
||||
"zlib/zlib111.zip".
|
||||
If the zipfile cannot be opened (file don't exist or in not valid), the
|
||||
return value is NULL.
|
||||
Else, the return value is a unzFile Handle, usable with other function
|
||||
of this unzip package.
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzClose OF((unzFile file));
|
||||
/*
|
||||
Close a ZipFile opened with unzipOpen.
|
||||
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
|
||||
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
|
||||
unz_global_info *pglobal_info));
|
||||
/*
|
||||
Write info about the ZipFile in the *pglobal_info structure.
|
||||
No preparation of the structure is needed
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
|
||||
extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
|
||||
char *szComment,
|
||||
uLong uSizeBuf));
|
||||
/*
|
||||
Get the global comment string of the ZipFile, in the szComment buffer.
|
||||
uSizeBuf is the size of the szComment buffer.
|
||||
return the number of byte copied or an error code <0
|
||||
*/
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* Unzip package allow you browse the directory of the zipfile */
|
||||
|
||||
extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
|
||||
/*
|
||||
Set the current file of the zipfile to the first file.
|
||||
return UNZ_OK if there is no problem
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzGoToNextFile OF((unzFile file));
|
||||
/*
|
||||
Set the current file of the zipfile to the next file.
|
||||
return UNZ_OK if there is no problem
|
||||
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzLocateFile OF((unzFile file,
|
||||
const char *szFileName,
|
||||
int iCaseSensitivity));
|
||||
/*
|
||||
Try locate the file szFileName in the zipfile.
|
||||
For the iCaseSensitivity signification, see unzStringFileNameCompare
|
||||
|
||||
return value :
|
||||
UNZ_OK if the file is found. It becomes the current file.
|
||||
UNZ_END_OF_LIST_OF_FILE if the file is not found
|
||||
*/
|
||||
|
||||
|
||||
extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
|
||||
unz_file_info *pfile_info,
|
||||
char *szFileName,
|
||||
uLong fileNameBufferSize,
|
||||
void *extraField,
|
||||
uLong extraFieldBufferSize,
|
||||
char *szComment,
|
||||
uLong commentBufferSize));
|
||||
/*
|
||||
Get Info about the current file
|
||||
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
|
||||
the current file
|
||||
if szFileName!=NULL, the filemane string will be copied in szFileName
|
||||
(fileNameBufferSize is the size of the buffer)
|
||||
if extraField!=NULL, the extra field information will be copied in extraField
|
||||
(extraFieldBufferSize is the size of the buffer).
|
||||
This is the Central-header version of the extra field
|
||||
if szComment!=NULL, the comment string of the file will be copied in szComment
|
||||
(commentBufferSize is the size of the buffer)
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
/* for reading the content of the current zipfile, you can open it, read data
|
||||
from it, and close it (you can close it before reading all the file)
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
|
||||
/*
|
||||
Open for reading data the current file in the zipfile.
|
||||
If there is no error, the return value is UNZ_OK.
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
|
||||
/*
|
||||
Close the file in zip opened with unzOpenCurrentFile
|
||||
Return UNZ_CRCERROR if all the file was read but the CRC is not good
|
||||
*/
|
||||
|
||||
|
||||
extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
|
||||
voidp buf,
|
||||
unsigned len));
|
||||
/*
|
||||
Read bytes from the current file (opened by unzOpenCurrentFile)
|
||||
buf contain buffer where data must be copied
|
||||
len the size of buf.
|
||||
|
||||
return the number of byte copied if somes bytes are copied
|
||||
return 0 if the end of file was reached
|
||||
return <0 with error code if there is an error
|
||||
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
|
||||
*/
|
||||
|
||||
extern z_off_t ZEXPORT unztell OF((unzFile file));
|
||||
/*
|
||||
Give the current position in uncompressed data
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzeof OF((unzFile file));
|
||||
/*
|
||||
return 1 if the end of file was reached, 0 elsewhere
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
|
||||
voidp buf,
|
||||
unsigned len));
|
||||
/*
|
||||
Read extra field from the current file (opened by unzOpenCurrentFile)
|
||||
This is the local-header version of the extra field (sometimes, there is
|
||||
more info in the local-header version than in the central-header)
|
||||
|
||||
if buf==NULL, it return the size of the local extra field
|
||||
|
||||
if buf!=NULL, len is the size of the buffer, the extra header is copied in
|
||||
buf.
|
||||
the return value is the number of bytes copied in buf, or (if <0)
|
||||
the error code
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _unz_H */
|
@ -7,48 +7,48 @@
|
||||
/* Interrupt line constants */
|
||||
enum
|
||||
{
|
||||
/* line states */
|
||||
CLEAR_LINE = 0, /* clear (a fired, held or pulsed) line */
|
||||
ASSERT_LINE, /* assert an interrupt immediately */
|
||||
HOLD_LINE, /* hold interrupt line until acknowledged */
|
||||
PULSE_LINE, /* pulse interrupt line for one instruction */
|
||||
/* line states */
|
||||
CLEAR_LINE = 0, /* clear (a fired, held or pulsed) line */
|
||||
ASSERT_LINE, /* assert an interrupt immediately */
|
||||
HOLD_LINE, /* hold interrupt line until acknowledged */
|
||||
PULSE_LINE, /* pulse interrupt line for one instruction */
|
||||
|
||||
/* internal flags (not for use by drivers!) */
|
||||
INTERNAL_CLEAR_LINE = 100 + CLEAR_LINE,
|
||||
INTERNAL_ASSERT_LINE = 100 + ASSERT_LINE,
|
||||
/* internal flags (not for use by drivers!) */
|
||||
INTERNAL_CLEAR_LINE = 100 + CLEAR_LINE,
|
||||
INTERNAL_ASSERT_LINE = 100 + ASSERT_LINE,
|
||||
|
||||
/* input lines */
|
||||
MAX_INPUT_LINES = 32+3,
|
||||
INPUT_LINE_IRQ0 = 0,
|
||||
INPUT_LINE_IRQ1 = 1,
|
||||
INPUT_LINE_IRQ2 = 2,
|
||||
INPUT_LINE_IRQ3 = 3,
|
||||
INPUT_LINE_IRQ4 = 4,
|
||||
INPUT_LINE_IRQ5 = 5,
|
||||
INPUT_LINE_IRQ6 = 6,
|
||||
INPUT_LINE_IRQ7 = 7,
|
||||
INPUT_LINE_IRQ8 = 8,
|
||||
INPUT_LINE_IRQ9 = 9,
|
||||
INPUT_LINE_NMI = MAX_INPUT_LINES - 3,
|
||||
/* input lines */
|
||||
MAX_INPUT_LINES = 32+3,
|
||||
INPUT_LINE_IRQ0 = 0,
|
||||
INPUT_LINE_IRQ1 = 1,
|
||||
INPUT_LINE_IRQ2 = 2,
|
||||
INPUT_LINE_IRQ3 = 3,
|
||||
INPUT_LINE_IRQ4 = 4,
|
||||
INPUT_LINE_IRQ5 = 5,
|
||||
INPUT_LINE_IRQ6 = 6,
|
||||
INPUT_LINE_IRQ7 = 7,
|
||||
INPUT_LINE_IRQ8 = 8,
|
||||
INPUT_LINE_IRQ9 = 9,
|
||||
INPUT_LINE_NMI = MAX_INPUT_LINES - 3,
|
||||
|
||||
/* special input lines that are implemented in the core */
|
||||
INPUT_LINE_RESET = MAX_INPUT_LINES - 2,
|
||||
INPUT_LINE_HALT = MAX_INPUT_LINES - 1,
|
||||
/* special input lines that are implemented in the core */
|
||||
INPUT_LINE_RESET = MAX_INPUT_LINES - 2,
|
||||
INPUT_LINE_HALT = MAX_INPUT_LINES - 1,
|
||||
|
||||
/* output lines */
|
||||
MAX_OUTPUT_LINES = 32
|
||||
/* output lines */
|
||||
MAX_OUTPUT_LINES = 32
|
||||
};
|
||||
|
||||
|
||||
/* daisy-chain link */
|
||||
typedef struct {
|
||||
void (*reset)(int); /* reset callback */
|
||||
int (*interrupt_entry)(int); /* entry callback */
|
||||
void (*interrupt_reti)(int); /* reti callback */
|
||||
int irq_param; /* callback paramater */
|
||||
} Z80_DaisyChain;
|
||||
void (*reset)(int); /* reset callback */
|
||||
int (*interrupt_entry)(int); /* entry callback */
|
||||
void (*interrupt_reti)(int); /* reti callback */
|
||||
int irq_param; /* callback paramater */
|
||||
} Z80_DaisyChain;
|
||||
|
||||
#define Z80_MAXDAISY 4 /* maximum of daisy chan device */
|
||||
#define Z80_MAXDAISY 4 /* maximum of daisy chan device */
|
||||
|
||||
#define Z80_INT_REQ 0x01 /* interrupt request mask */
|
||||
#define Z80_INT_IEO 0x02 /* interrupt disable mask(IEO) */
|
||||
@ -56,4 +56,4 @@ typedef struct {
|
||||
#define Z80_VECTOR(device,state) (((device)<<8)|(state))
|
||||
|
||||
|
||||
#endif /* CPUINTRF_H */
|
||||
#endif /* CPUINTRF_H */
|
||||
|
@ -1,24 +1,24 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Define size independent data types and operations. *
|
||||
* *
|
||||
* The following types must be supported by all platforms: *
|
||||
* *
|
||||
* UINT8 - Unsigned 8-bit Integer INT8 - Signed 8-bit integer *
|
||||
* UINT16 - Unsigned 16-bit Integer INT16 - Signed 16-bit integer *
|
||||
* UINT32 - Unsigned 32-bit Integer INT32 - Signed 32-bit integer *
|
||||
* UINT64 - Unsigned 64-bit Integer INT64 - Signed 64-bit integer *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* Define size independent data types and operations. *
|
||||
* *
|
||||
* The following types must be supported by all platforms: *
|
||||
* *
|
||||
* UINT8 - Unsigned 8-bit Integer INT8 - Signed 8-bit integer *
|
||||
* UINT16 - Unsigned 16-bit Integer INT16 - Signed 16-bit integer *
|
||||
* UINT32 - Unsigned 32-bit Integer INT32 - Signed 32-bit integer *
|
||||
* UINT64 - Unsigned 64-bit Integer INT64 - Signed 64-bit integer *
|
||||
* *
|
||||
* *
|
||||
* The macro names for the artithmatic operations are composed as follows: *
|
||||
* *
|
||||
* XXX_R_A_B, where XXX - 3 letter operation code (ADD, SUB, etc.) *
|
||||
* R - The type of the result *
|
||||
* A - The type of operand 1 *
|
||||
* B - The type of operand 2 (if binary operation) *
|
||||
* *
|
||||
* Each type is one of: U8,8,U16,16,U32,32,U64,64 *
|
||||
* *
|
||||
* *
|
||||
* XXX_R_A_B, where XXX - 3 letter operation code (ADD, SUB, etc.) *
|
||||
* R - The type of the result *
|
||||
* A - The type of operand 1 *
|
||||
* B - The type of operand 2 (if binary operation) *
|
||||
* *
|
||||
* Each type is one of: U8,8,U16,16,U32,32,U64,64 *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
@ -35,14 +35,14 @@
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
typedef unsigned char UINT8;
|
||||
typedef unsigned short UINT16;
|
||||
typedef unsigned char UINT8;
|
||||
typedef unsigned short UINT16;
|
||||
//#ifdef DOS
|
||||
typedef unsigned int UINT32;
|
||||
__extension__ typedef unsigned long long UINT64;
|
||||
//#endif
|
||||
typedef signed char INT8;
|
||||
typedef signed short INT16;
|
||||
typedef signed char INT8;
|
||||
typedef signed short INT16;
|
||||
//#ifdef DOS
|
||||
typedef signed int INT32;
|
||||
__extension__ typedef signed long long INT64;
|
||||
@ -53,20 +53,20 @@ __extension__ typedef signed long long INT64;
|
||||
#define COMBINE_U64_U32_U32(A,B) COMBINE_64_32_32(A,B)
|
||||
|
||||
/* Return upper 32 bits of a 64-bit integer */
|
||||
#define HI32_32_64(A) (((UINT64)(A)) >> 32)
|
||||
#define HI32_U32_U64(A) HI32_32_64(A)
|
||||
#define HI32_32_64(A) (((UINT64)(A)) >> 32)
|
||||
#define HI32_U32_U64(A) HI32_32_64(A)
|
||||
|
||||
/* Return lower 32 bits of a 64-bit integer */
|
||||
#define LO32_32_64(A) ((A) & 0xffffffff)
|
||||
#define LO32_U32_U64(A) LO32_32_64(A)
|
||||
#define LO32_32_64(A) ((A) & 0xffffffff)
|
||||
#define LO32_U32_U64(A) LO32_32_64(A)
|
||||
|
||||
#define DIV_64_64_32(A,B) ((A)/(B))
|
||||
#define DIV_64_64_32(A,B) ((A)/(B))
|
||||
#define DIV_U64_U64_U32(A,B) ((A)/(UINT32)(B))
|
||||
|
||||
#define MOD_32_64_32(A,B) ((A)%(B))
|
||||
#define MOD_32_64_32(A,B) ((A)%(B))
|
||||
#define MOD_U32_U64_U32(A,B) ((A)%(UINT32)(B))
|
||||
|
||||
#define MUL_64_32_32(A,B) ((A)*(INT64)(B))
|
||||
#define MUL_64_32_32(A,B) ((A)*(INT64)(B))
|
||||
#define MUL_U64_U32_U32(A,B) ((A)*(UINT64)(UINT32)(B))
|
||||
|
||||
|
||||
@ -79,13 +79,13 @@ __extension__ typedef signed long long INT64;
|
||||
******************************************************************************/
|
||||
typedef union {
|
||||
#ifdef LSB_FIRST
|
||||
struct { UINT8 l,h,h2,h3; } b;
|
||||
struct { UINT16 l,h; } w;
|
||||
struct { UINT8 l,h,h2,h3; } b;
|
||||
struct { UINT16 l,h; } w;
|
||||
#else
|
||||
struct { UINT8 h3,h2,h,l; } b;
|
||||
struct { UINT16 h,l; } w;
|
||||
struct { UINT8 h3,h2,h,l; } b;
|
||||
struct { UINT16 h,l; } w;
|
||||
#endif
|
||||
UINT32 d;
|
||||
} PAIR;
|
||||
UINT32 d;
|
||||
} PAIR;
|
||||
|
||||
#endif /* defined OSD_CPU_H */
|
||||
#endif /* defined OSD_CPU_H */
|
||||
|
5190
source/z80/z80.c
5190
source/z80/z80.c
File diff suppressed because it is too large
Load Diff
@ -4,21 +4,21 @@
|
||||
#include "cpuintrf.h"
|
||||
|
||||
enum {
|
||||
Z80_PC=1, Z80_SP, Z80_A, Z80_B,
|
||||
Z80_C, Z80_D, Z80_E, Z80_H, Z80_L,
|
||||
Z80_AF, Z80_BC, Z80_DE, Z80_HL,
|
||||
Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2,
|
||||
Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT,
|
||||
Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3
|
||||
Z80_PC=1, Z80_SP, Z80_A, Z80_B,
|
||||
Z80_C, Z80_D, Z80_E, Z80_H, Z80_L,
|
||||
Z80_AF, Z80_BC, Z80_DE, Z80_HL,
|
||||
Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2,
|
||||
Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT,
|
||||
Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3
|
||||
};
|
||||
|
||||
enum {
|
||||
Z80_TABLE_op,
|
||||
Z80_TABLE_cb,
|
||||
Z80_TABLE_ed,
|
||||
Z80_TABLE_xy,
|
||||
Z80_TABLE_xycb,
|
||||
Z80_TABLE_ex /* cycles counts for taken jr/jp/call and interrupt latency (rst opcodes) */
|
||||
Z80_TABLE_op,
|
||||
Z80_TABLE_cb,
|
||||
Z80_TABLE_ed,
|
||||
Z80_TABLE_xy,
|
||||
Z80_TABLE_xycb,
|
||||
Z80_TABLE_ex /* cycles counts for taken jr/jp/call and interrupt latency (rst opcodes) */
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
@ -27,16 +27,16 @@ enum {
|
||||
/****************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
PAIR prvpc,pc,sp,af,bc,de,hl,ix,iy;
|
||||
PAIR af2,bc2,de2,hl2;
|
||||
UINT8 r,r2,iff1,iff2,halt,im,i;
|
||||
UINT8 nmi_state; /* nmi line state */
|
||||
UINT8 nmi_pending; /* nmi pending */
|
||||
UINT8 irq_state; /* irq line state */
|
||||
UINT8 after_ei; /* are we in the EI shadow? */
|
||||
const struct z80_irq_daisy_chain *daisy;
|
||||
int (*irq_callback)(int irqline);
|
||||
} Z80_Regs;
|
||||
PAIR prvpc,pc,sp,af,bc,de,hl,ix,iy;
|
||||
PAIR af2,bc2,de2,hl2;
|
||||
UINT8 r,r2,iff1,iff2,halt,im,i;
|
||||
UINT8 nmi_state; /* nmi line state */
|
||||
UINT8 nmi_pending; /* nmi pending */
|
||||
UINT8 irq_state; /* irq line state */
|
||||
UINT8 after_ei; /* are we in the EI shadow? */
|
||||
const struct z80_irq_daisy_chain *daisy;
|
||||
int (*irq_callback)(int irqline);
|
||||
} Z80_Regs;
|
||||
|
||||
|
||||
extern int z80_ICount;
|
||||
|
Loading…
Reference in New Issue
Block a user