code cleanup

This commit is contained in:
ekeeke31 2008-12-11 17:38:29 +00:00
parent 822de1bd3f
commit 00a61b4762
83 changed files with 33831 additions and 35082 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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 */

View File

@ -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)

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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];
}
}
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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
View 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

View File

@ -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);
}

View 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

View File

@ -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);
}

View 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

View File

@ -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;
}

View 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

View File

@ -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"

View 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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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;
}

View File

@ -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

View 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.

View File

@ -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;

View File

@ -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);

View File

@ -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_

View File

@ -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"

View File

@ -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_

View File

@ -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"

View File

@ -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_

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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/

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}

View File

@ -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

View File

@ -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_;

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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;