mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
buffering, PCM DMA, memcpy12bswap
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@66 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
83bd0b76ab
commit
0a051f558c
15 changed files with 395 additions and 70 deletions
|
@ -313,6 +313,15 @@ void memcpy16(unsigned short *dest, unsigned short *src, int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void memcpy16bswap(unsigned short *dest, void *src, int count)
|
||||||
|
{
|
||||||
|
unsigned char *src_ = src;
|
||||||
|
|
||||||
|
for (; count; count--, src_ += 2)
|
||||||
|
*dest++ = (src_[0] << 8) | src_[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void memcpy32(int *dest, int *src, int count)
|
void memcpy32(int *dest, int *src, int count)
|
||||||
{
|
{
|
||||||
while (count--)
|
while (count--)
|
||||||
|
|
|
@ -47,6 +47,8 @@ extern void (*PicoWriteSound)(int len); // called once per frame at the best tim
|
||||||
|
|
||||||
int PicoFrameMCD(void);
|
int PicoFrameMCD(void);
|
||||||
|
|
||||||
|
extern int PicoCDBuffers;
|
||||||
|
|
||||||
// Area.c
|
// Area.c
|
||||||
typedef size_t (arearw)(void *p, size_t _size, size_t _n, void *file);
|
typedef size_t (arearw)(void *p, size_t _size, size_t _n, void *file);
|
||||||
typedef size_t (areaeof)(void *file);
|
typedef size_t (areaeof)(void *file);
|
||||||
|
@ -61,6 +63,10 @@ extern areaseek *areaSeek;
|
||||||
extern areaclose *areaClose;
|
extern areaclose *areaClose;
|
||||||
extern void (*PicoStateProgressCB)(const char *str);
|
extern void (*PicoStateProgressCB)(const char *str);
|
||||||
|
|
||||||
|
// cd/buffering.c
|
||||||
|
void PicoCDBufferInit(void);
|
||||||
|
void PicoCDBufferFree(void);
|
||||||
|
|
||||||
// Cart.c
|
// Cart.c
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
|
|
@ -300,6 +300,7 @@ void SRAMWriteEEPROM(unsigned int d);
|
||||||
unsigned int SRAMReadEEPROM();
|
unsigned int SRAMReadEEPROM();
|
||||||
void SRAMUpdPending(unsigned int a, unsigned int d);
|
void SRAMUpdPending(unsigned int a, unsigned int d);
|
||||||
void memcpy16(unsigned short *dest, unsigned short *src, int count);
|
void memcpy16(unsigned short *dest, unsigned short *src, int count);
|
||||||
|
void memcpy16bswap(unsigned short *dest, void *src, int count);
|
||||||
void memcpy32(int *dest, int *src, int count);
|
void memcpy32(int *dest, int *src, int count);
|
||||||
void memset32(int *dest, int c, int count);
|
void memset32(int *dest, int c, int count);
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ static void DmaSlow(int len)
|
||||||
r = Pico.cram;
|
r = Pico.cram;
|
||||||
for(a2=a&0x7f; len; len--)
|
for(a2=a&0x7f; len; len--)
|
||||||
{
|
{
|
||||||
r[a2>>1] = (u16)*pd++;; // bit 0 is ignored
|
r[a2>>1] = (u16)*pd++; // bit 0 is ignored
|
||||||
// AutoIncrement
|
// AutoIncrement
|
||||||
a2+=inc;
|
a2+=inc;
|
||||||
// didn't src overlap?
|
// didn't src overlap?
|
||||||
|
|
|
@ -70,7 +70,7 @@ void LC89510_Reset(void)
|
||||||
|
|
||||||
void Update_CDC_TRansfer(int which)
|
void Update_CDC_TRansfer(int which)
|
||||||
{
|
{
|
||||||
unsigned int DMA_Adr, dep, length, len;
|
unsigned int DMA_Adr, dep, length;
|
||||||
unsigned short *dest;
|
unsigned short *dest;
|
||||||
unsigned char *src;
|
unsigned char *src;
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ void Update_CDC_TRansfer(int which)
|
||||||
else length = CDC_DMA_SPEED;
|
else length = CDC_DMA_SPEED;
|
||||||
|
|
||||||
|
|
||||||
// TODO: dst bounds checking? DAC.N alignment?
|
// TODO: dst bounds checking?
|
||||||
src = Pico_mcd->cdc.Buffer + Pico_mcd->cdc.DAC.N;
|
src = Pico_mcd->cdc.Buffer + Pico_mcd->cdc.DAC.N;
|
||||||
DMA_Adr = (Pico_mcd->s68k_regs[0xA]<<8) | Pico_mcd->s68k_regs[0xB];
|
DMA_Adr = (Pico_mcd->s68k_regs[0xA]<<8) | Pico_mcd->s68k_regs[0xB];
|
||||||
|
|
||||||
|
@ -112,13 +112,11 @@ void Update_CDC_TRansfer(int which)
|
||||||
|
|
||||||
dest = (unsigned short *) (Pico_mcd->word_ram1M[bank] + dep);
|
dest = (unsigned short *) (Pico_mcd->word_ram1M[bank] + dep);
|
||||||
|
|
||||||
// TODO: bswapcpy
|
memcpy16bswap(dest, src, length);
|
||||||
for (len = length; len > 0; len--, src+=2, dest++)
|
|
||||||
*dest = (src[0]<<8) | src[1];
|
|
||||||
|
|
||||||
{ // debug
|
{ // debug
|
||||||
unsigned char *b1 = Pico_mcd->word_ram1M[bank] + dep;
|
unsigned char *b1 = Pico_mcd->word_ram1M[bank] + dep;
|
||||||
unsigned char *b2 = (unsigned char *)dest - 8;
|
unsigned char *b2 = (unsigned char *)(dest+length) - 8;
|
||||||
dprintf("%02x %02x %02x %02x .. %02x %02x %02x %02x",
|
dprintf("%02x %02x %02x %02x .. %02x %02x %02x %02x",
|
||||||
b1[0], b1[1], b1[4], b1[5], b2[0], b2[1], b2[4], b2[5]);
|
b1[0], b1[1], b1[4], b1[5], b2[0], b2[1], b2[4], b2[5]);
|
||||||
}
|
}
|
||||||
|
@ -130,25 +128,26 @@ void Update_CDC_TRansfer(int which)
|
||||||
Pico_mcd->cdc.DAC.N, dep, length);
|
Pico_mcd->cdc.DAC.N, dep, length);
|
||||||
dest = (unsigned short *) (Pico_mcd->word_ram2M + dep);
|
dest = (unsigned short *) (Pico_mcd->word_ram2M + dep);
|
||||||
|
|
||||||
for (len = length; len > 0; len--, src+=2, dest++)
|
memcpy16bswap(dest, src, length);
|
||||||
*dest = (src[0]<<8) | src[1];
|
|
||||||
|
|
||||||
{ // debug
|
{ // debug
|
||||||
unsigned char *b1 = Pico_mcd->word_ram2M + dep;
|
unsigned char *b1 = Pico_mcd->word_ram2M + dep;
|
||||||
unsigned char *b2 = (unsigned char *)dest - 4;
|
unsigned char *b2 = (unsigned char *)(dest+length) - 4;
|
||||||
dprintf("%02x %02x %02x %02x .. %02x %02x %02x %02x",
|
dprintf("%02x %02x %02x %02x .. %02x %02x %02x %02x",
|
||||||
b1[0], b1[1], b1[2], b1[3], b2[0], b2[1], b2[2], b2[3]);
|
b1[0], b1[1], b1[2], b1[3], b2[0], b2[1], b2[2], b2[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (which == 4) // PCM RAM
|
else if (which == 4) // PCM RAM (check: popful Mail)
|
||||||
{
|
{
|
||||||
#if 0
|
dep = (DMA_Adr & 0x03FF) << 2;
|
||||||
dest = (unsigned char *) Ram_PCM;
|
dprintf("CD DMA # %04x -> PCM[%i] # %04x, len=%i",
|
||||||
dep = ((DMA_Adr & 0x03FF) << 2) + PCM_Chip.Bank;
|
Pico_mcd->cdc.DAC.N, Pico_mcd->pcm.bank, dep, length);
|
||||||
#else
|
dest = (unsigned short *) (Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank] + dep);
|
||||||
dprintf("FIXME: CD DMA # %04x -> PCM", Pico_mcd->cdc.DAC.N);
|
|
||||||
#endif
|
if (Pico_mcd->cdc.DAC.N & 1) /* unaligned src? */
|
||||||
|
memcpy(dest, src, length*2);
|
||||||
|
else memcpy16(dest, (unsigned short *) src, length);
|
||||||
}
|
}
|
||||||
else if (which == 5) // PRG RAM
|
else if (which == 5) // PRG RAM
|
||||||
{
|
{
|
||||||
|
@ -157,12 +156,11 @@ void Update_CDC_TRansfer(int which)
|
||||||
cdprintf("CD DMA # %04x -> prg_ram # %06x, len=%i",
|
cdprintf("CD DMA # %04x -> prg_ram # %06x, len=%i",
|
||||||
Pico_mcd->cdc.DAC.N, dep, length);
|
Pico_mcd->cdc.DAC.N, dep, length);
|
||||||
|
|
||||||
for (len = length; len > 0; len--, src+=2, dest++)
|
memcpy16bswap(dest, src, length);
|
||||||
*dest = (src[0]<<8) | src[1];
|
|
||||||
|
|
||||||
{ // debug
|
{ // debug
|
||||||
unsigned char *b1 = Pico_mcd->prg_ram + dep;
|
unsigned char *b1 = Pico_mcd->prg_ram + dep;
|
||||||
unsigned char *b2 = (unsigned char *)dest - 4;
|
unsigned char *b2 = (unsigned char *)(dest+length) - 4;
|
||||||
dprintf("%02x %02x %02x %02x .. %02x %02x %02x %02x",
|
dprintf("%02x %02x %02x %02x .. %02x %02x %02x %02x",
|
||||||
b1[0], b1[1], b1[2], b1[3], b2[0], b2[1], b2[2], b2[3]);
|
b1[0], b1[1], b1[2], b1[3], b2[0], b2[1], b2[2], b2[3]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,6 +421,7 @@ u16 PicoReadM68k16(u32 a)
|
||||||
a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged
|
a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged
|
||||||
else a &= 0x1fffe;
|
else a &= 0x1fffe;
|
||||||
d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);
|
d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);
|
||||||
|
//d = 0xaaaa;
|
||||||
} else {
|
} else {
|
||||||
// allow access in any mode, like Gens does
|
// allow access in any mode, like Gens does
|
||||||
d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
|
d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
|
||||||
|
@ -929,6 +930,63 @@ u32 PicoReadS68k32(u32 a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* check: jaguar xj 220 (draws entire world using decode) */
|
||||||
|
static void decode_write8(u32 a, u8 d, int r3)
|
||||||
|
{
|
||||||
|
u8 *pd = Pico_mcd->word_ram1M[!(r3 & 1)] + (((a>>1)^1)&0x1ffff);
|
||||||
|
u8 oldmask = (a&1) ? 0xf0 : 0x0f;
|
||||||
|
|
||||||
|
//if ((a & 0x3ffff) < 0x28000) return;
|
||||||
|
//return;
|
||||||
|
|
||||||
|
r3 &= 0x18;
|
||||||
|
d &= 0x0f;
|
||||||
|
if (!(a&1)) d <<= 4;
|
||||||
|
|
||||||
|
//dprintf("FIXME: decode, r3 = %02x", r3);
|
||||||
|
|
||||||
|
if (r3 == 8) {
|
||||||
|
if ((!(*pd & (~oldmask))) && d) goto do_it;
|
||||||
|
} else if (r3 > 8) {
|
||||||
|
if (d) goto do_it;
|
||||||
|
} else {
|
||||||
|
goto do_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
do_it:
|
||||||
|
*pd = d | (*pd & oldmask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void decode_write16(u32 a, u16 d, int r3)
|
||||||
|
{
|
||||||
|
u8 *pd = Pico_mcd->word_ram1M[!(r3 & 1)] + (((a>>1)^1)&0x1ffff);
|
||||||
|
|
||||||
|
//if ((a & 0x3ffff) < 0x28000) return;
|
||||||
|
|
||||||
|
r3 &= 0x18;
|
||||||
|
d &= 0x0f0f;
|
||||||
|
d |= d >> 4;
|
||||||
|
|
||||||
|
if (r3 == 8) {
|
||||||
|
u8 dold = *pd;
|
||||||
|
if (!(dold & 0xf0)) dold |= d & 0xf0;
|
||||||
|
if (!(dold & 0x0f)) dold |= d & 0x0f;
|
||||||
|
*pd = dold;
|
||||||
|
} else if (r3 > 8) {
|
||||||
|
u8 dold = *pd;
|
||||||
|
if (!(d & 0xf0)) d |= dold & 0xf0;
|
||||||
|
if (!(d & 0x0f)) d |= dold & 0x0f;
|
||||||
|
*pd = d;
|
||||||
|
} else {
|
||||||
|
*pd = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
//dprintf("FIXME: decode");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
|
||||||
void PicoWriteS68k8(u32 a,u8 d)
|
void PicoWriteS68k8(u32 a,u8 d)
|
||||||
|
@ -958,13 +1016,10 @@ void PicoWriteS68k8(u32 a,u8 d)
|
||||||
|
|
||||||
// word RAM (2M area)
|
// word RAM (2M area)
|
||||||
if ((a&0xfc0000)==0x080000) { // 080000-0bffff
|
if ((a&0xfc0000)==0x080000) { // 080000-0bffff
|
||||||
|
int r3 = Pico_mcd->s68k_regs[3];
|
||||||
wrdprintf("s68k_wram2M w8: [%06x] %02x @%06x", a, d, SekPcS68k);
|
wrdprintf("s68k_wram2M w8: [%06x] %02x @%06x", a, d, SekPcS68k);
|
||||||
if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
|
if (r3 & 4) { // 1M decode mode?
|
||||||
int bank = !(Pico_mcd->s68k_regs[3]&1);
|
decode_write8(a, d, r3);
|
||||||
if (a&1) d &= 0x0f;
|
|
||||||
else d >>= 4;
|
|
||||||
Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff]=d;
|
|
||||||
dprintf("FIXME: decode");
|
|
||||||
} else {
|
} else {
|
||||||
// allow access in any mode, like Gens does
|
// allow access in any mode, like Gens does
|
||||||
*(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;
|
*(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;
|
||||||
|
@ -1039,12 +1094,10 @@ void PicoWriteS68k16(u32 a,u16 d)
|
||||||
|
|
||||||
// word RAM (2M area)
|
// word RAM (2M area)
|
||||||
if ((a&0xfc0000)==0x080000) { // 080000-0bffff
|
if ((a&0xfc0000)==0x080000) { // 080000-0bffff
|
||||||
|
int r3 = Pico_mcd->s68k_regs[3];
|
||||||
wrdprintf("s68k_wram2M w16: [%06x] %04x @%06x", a, d, SekPcS68k);
|
wrdprintf("s68k_wram2M w16: [%06x] %04x @%06x", a, d, SekPcS68k);
|
||||||
if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
|
if (r3 & 4) { // 1M decode mode?
|
||||||
int bank = !(Pico_mcd->s68k_regs[3]&1);
|
decode_write16(a, d, r3);
|
||||||
d &= ~0xf0; d |= d >> 8;
|
|
||||||
Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff] = d;
|
|
||||||
dprintf("FIXME: decode");
|
|
||||||
} else {
|
} else {
|
||||||
// allow access in any mode, like Gens does
|
// allow access in any mode, like Gens does
|
||||||
*(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;
|
*(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;
|
||||||
|
@ -1121,14 +1174,11 @@ void PicoWriteS68k32(u32 a,u32 d)
|
||||||
|
|
||||||
// word RAM (2M area)
|
// word RAM (2M area)
|
||||||
if ((a&0xfc0000)==0x080000) { // 080000-0bffff
|
if ((a&0xfc0000)==0x080000) { // 080000-0bffff
|
||||||
|
int r3 = Pico_mcd->s68k_regs[3];
|
||||||
wrdprintf("s68k_wram2M w32: [%06x] %08x @%06x", a, d, SekPcS68k);
|
wrdprintf("s68k_wram2M w32: [%06x] %08x @%06x", a, d, SekPcS68k);
|
||||||
if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
|
if (r3 & 4) { // 1M decode mode?
|
||||||
int bank = !(Pico_mcd->s68k_regs[3]&1);
|
decode_write16(a , d >> 16, r3);
|
||||||
a >>= 1;
|
decode_write16(a+2, d , r3);
|
||||||
d &= 0x0f0f0f0f; d |= d >> 4;
|
|
||||||
Pico_mcd->word_ram1M[bank][((a+0)^1)&0x1ffff] = d >> 16;
|
|
||||||
Pico_mcd->word_ram1M[bank][((a+1)^1)&0x1ffff] = d;
|
|
||||||
dprintf("FIXME: decode");
|
|
||||||
} else {
|
} else {
|
||||||
// allow access in any mode, like Gens does
|
// allow access in any mode, like Gens does
|
||||||
u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
|
u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
|
||||||
|
|
|
@ -141,24 +141,17 @@ void Unload_ISO(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PicoCDBufferRead(void *dest, int lba);
|
||||||
|
|
||||||
|
|
||||||
int FILE_Read_One_LBA_CDC(void)
|
int FILE_Read_One_LBA_CDC(void)
|
||||||
{
|
{
|
||||||
int where_read = 0;
|
|
||||||
// static char cp_buf[2560];
|
// static char cp_buf[2560];
|
||||||
|
|
||||||
if (Pico_mcd->s68k_regs[0x36] & 1) // DATA
|
if (Pico_mcd->s68k_regs[0x36] & 1) // DATA
|
||||||
{
|
{
|
||||||
if (Pico_mcd->TOC.Tracks[0].F == NULL) return -1;
|
if (Pico_mcd->TOC.Tracks[0].F == NULL) return -1;
|
||||||
|
|
||||||
if (Pico_mcd->scd.Cur_LBA < 0)
|
|
||||||
where_read = 0;
|
|
||||||
else if (Pico_mcd->scd.Cur_LBA >= Pico_mcd->TOC.Tracks[0].Length)
|
|
||||||
where_read = Pico_mcd->TOC.Tracks[0].Length - 1;
|
|
||||||
else where_read = Pico_mcd->scd.Cur_LBA;
|
|
||||||
|
|
||||||
if (Pico_mcd->TOC.Tracks[0].ftype == TYPE_ISO) where_read <<= 11;
|
|
||||||
else where_read = (where_read * 2352 + 16);
|
|
||||||
|
|
||||||
// moved below..
|
// moved below..
|
||||||
//fseek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET);
|
//fseek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET);
|
||||||
//fread(cp_buf, 1, 2048, Pico_mcd->TOC.Tracks[0].F);
|
//fread(cp_buf, 1, 2048, Pico_mcd->TOC.Tracks[0].F);
|
||||||
|
@ -169,7 +162,7 @@ int FILE_Read_One_LBA_CDC(void)
|
||||||
{
|
{
|
||||||
// int rate, channel;
|
// int rate, channel;
|
||||||
|
|
||||||
if (Pico_mcd->TOC.Tracks[Pico_mcd->scd.Cur_Track - 1].ftype == TYPE_MP3)
|
// if (Pico_mcd->TOC.Tracks[Pico_mcd->scd.Cur_Track - 1].ftype == TYPE_MP3)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
// MP3_Update(cp_buf, &rate, &channel, 0);
|
// MP3_Update(cp_buf, &rate, &channel, 0);
|
||||||
|
@ -189,8 +182,16 @@ int FILE_Read_One_LBA_CDC(void)
|
||||||
{
|
{
|
||||||
if (Pico_mcd->cdc.CTRL.B.B0 & 0x04) // WRRQ : this bit enable write to buffer
|
if (Pico_mcd->cdc.CTRL.B.B0 & 0x04) // WRRQ : this bit enable write to buffer
|
||||||
{
|
{
|
||||||
|
int where_read = 0;
|
||||||
|
|
||||||
// CAUTION : lookahead bit not implemented
|
// CAUTION : lookahead bit not implemented
|
||||||
|
|
||||||
|
if (Pico_mcd->scd.Cur_LBA < 0)
|
||||||
|
where_read = 0;
|
||||||
|
else if (Pico_mcd->scd.Cur_LBA >= Pico_mcd->TOC.Tracks[0].Length)
|
||||||
|
where_read = Pico_mcd->TOC.Tracks[0].Length - 1;
|
||||||
|
else where_read = Pico_mcd->scd.Cur_LBA;
|
||||||
|
|
||||||
Pico_mcd->scd.Cur_LBA++;
|
Pico_mcd->scd.Cur_LBA++;
|
||||||
|
|
||||||
Pico_mcd->cdc.WA.N = (Pico_mcd->cdc.WA.N + 2352) & 0x7FFF; // add one sector to WA
|
Pico_mcd->cdc.WA.N = (Pico_mcd->cdc.WA.N + 2352) & 0x7FFF; // add one sector to WA
|
||||||
|
@ -199,8 +200,9 @@ int FILE_Read_One_LBA_CDC(void)
|
||||||
*(unsigned int *)(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N) = Pico_mcd->cdc.HEAD.N;
|
*(unsigned int *)(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N) = Pico_mcd->cdc.HEAD.N;
|
||||||
//memcpy(&Pico_mcd->cdc.Buffer[Pico_mcd->cdc.PT.N + 4], cp_buf, 2048);
|
//memcpy(&Pico_mcd->cdc.Buffer[Pico_mcd->cdc.PT.N + 4], cp_buf, 2048);
|
||||||
|
|
||||||
pm_seek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET);
|
//pm_seek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET);
|
||||||
pm_read(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, 2048, Pico_mcd->TOC.Tracks[0].F);
|
//pm_read(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, 2048, Pico_mcd->TOC.Tracks[0].F);
|
||||||
|
PicoCDBufferRead(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, where_read);
|
||||||
|
|
||||||
#ifdef DEBUG_CD
|
#ifdef DEBUG_CD
|
||||||
cdprintf("Read -> WA = %d Buffer[%d] =", Pico_mcd->cdc.WA.N, Pico_mcd->cdc.PT.N & 0x3FFF);
|
cdprintf("Read -> WA = %d Buffer[%d] =", Pico_mcd->cdc.WA.N, Pico_mcd->cdc.PT.N & 0x3FFF);
|
||||||
|
|
|
@ -210,7 +210,7 @@ void gfx_cd_reset(void)
|
||||||
|
|
||||||
typedef unsigned short u16;
|
typedef unsigned short u16;
|
||||||
|
|
||||||
// check: Heart of the alien
|
// check: Heart of the alien, jaguar xj 220
|
||||||
void DmaSlowCell(unsigned int source, unsigned int a, int len, unsigned char inc)
|
void DmaSlowCell(unsigned int source, unsigned int a, int len, unsigned char inc)
|
||||||
{
|
{
|
||||||
unsigned char *base;
|
unsigned char *base;
|
||||||
|
|
78
Pico/misc.s
78
Pico/misc.s
|
@ -40,6 +40,84 @@ mcp16_cant_align:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ 0x12345678 -> 0x34127856
|
||||||
|
@ r4=temp, lr=0x00ff00ff
|
||||||
|
.macro bswap reg
|
||||||
|
and r4, \reg, lr
|
||||||
|
and \reg, lr, \reg, lsr #8
|
||||||
|
orr \reg, \reg, r4, lsl #8
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
@ dest must be halfword aligned, src can be unaligned
|
||||||
|
.global memcpy16bswap @ unsigned short *dest, void *src, int count
|
||||||
|
|
||||||
|
memcpy16bswap:
|
||||||
|
tst r1, #1
|
||||||
|
bne mcp16bs_cant_align2
|
||||||
|
|
||||||
|
eor r3, r0, r1
|
||||||
|
tst r3, #2
|
||||||
|
bne mcp16bs_cant_align
|
||||||
|
|
||||||
|
tst r0, #2
|
||||||
|
beq mcp16bs_aligned
|
||||||
|
ldrh r3, [r1], #2
|
||||||
|
sub r2, r2, #1
|
||||||
|
orr r3, r3, r3, lsl #16
|
||||||
|
mov r3, r3, lsr #8
|
||||||
|
strh r3, [r0], #2
|
||||||
|
|
||||||
|
mcp16bs_aligned:
|
||||||
|
stmfd sp!, {r4,lr}
|
||||||
|
mov lr, #0xff
|
||||||
|
orr lr, lr, lr, lsl #16
|
||||||
|
|
||||||
|
subs r2, r2, #4
|
||||||
|
bmi mcp16bs_fin4
|
||||||
|
|
||||||
|
mcp16bs_loop:
|
||||||
|
ldmia r1!, {r3,r12}
|
||||||
|
subs r2, r2, #4
|
||||||
|
bswap r3
|
||||||
|
bswap r12
|
||||||
|
stmia r0!, {r3,r12}
|
||||||
|
bpl mcp16bs_loop
|
||||||
|
|
||||||
|
mcp16bs_fin4:
|
||||||
|
tst r2, #2
|
||||||
|
beq mcp16bs_fin2
|
||||||
|
ldr r3, [r1], #4
|
||||||
|
bswap r3
|
||||||
|
str r3, [r0], #4
|
||||||
|
|
||||||
|
mcp16bs_fin2:
|
||||||
|
ldmfd sp!, {r4,lr}
|
||||||
|
ands r2, r2, #1
|
||||||
|
bxeq lr
|
||||||
|
|
||||||
|
mcp16bs_cant_align:
|
||||||
|
ldrh r3, [r1], #2
|
||||||
|
subs r2, r2, #1
|
||||||
|
orr r3, r3, r3, lsl #16
|
||||||
|
mov r3, r3, lsr #8
|
||||||
|
strh r3, [r0], #2
|
||||||
|
bne mcp16bs_cant_align
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
@ worst case
|
||||||
|
mcp16bs_cant_align2:
|
||||||
|
ldrb r3, [r1], #1
|
||||||
|
ldrb r12,[r1], #1
|
||||||
|
subs r2, r2, #1
|
||||||
|
mov r3, r3, lsl #8
|
||||||
|
orr r3, r3, r12
|
||||||
|
strh r3, [r0], #2
|
||||||
|
bne mcp16bs_cant_align2
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.global memcpy32 @ int *dest, int *src, int count
|
.global memcpy32 @ int *dest, int *src, int count
|
||||||
|
|
||||||
memcpy32:
|
memcpy32:
|
||||||
|
|
|
@ -43,7 +43,7 @@ OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Utils.o ../../Pico/Memory
|
||||||
# Pico - CD
|
# Pico - CD
|
||||||
OBJS += ../../Pico/cd/Pico.o ../../Pico/cd/Memory.o ../../Pico/cd/Sek.o ../../Pico/cd/LC89510.o \
|
OBJS += ../../Pico/cd/Pico.o ../../Pico/cd/Memory.o ../../Pico/cd/Sek.o ../../Pico/cd/LC89510.o \
|
||||||
../../Pico/cd/cd_sys.o ../../Pico/cd/cd_file.o ../../Pico/cd/gfx_cd.o \
|
../../Pico/cd/cd_sys.o ../../Pico/cd/cd_file.o ../../Pico/cd/gfx_cd.o \
|
||||||
../../Pico/cd/Area.o ../../Pico/cd/Misc.o ../../Pico/cd/pcm.o
|
../../Pico/cd/Area.o ../../Pico/cd/Misc.o ../../Pico/cd/pcm.o ../../Pico/cd/buffering.o
|
||||||
# asm stuff
|
# asm stuff
|
||||||
ifeq "$(asm_render)" "1"
|
ifeq "$(asm_render)" "1"
|
||||||
DEFINC += -D_ASM_DRAW_C
|
DEFINC += -D_ASM_DRAW_C
|
||||||
|
|
|
@ -496,6 +496,7 @@ int emu_ReadConfig(int game)
|
||||||
currentConfig.KeyBinds[23] = 1<<29; // vol up
|
currentConfig.KeyBinds[23] = 1<<29; // vol up
|
||||||
currentConfig.KeyBinds[22] = 1<<30; // vol down
|
currentConfig.KeyBinds[22] = 1<<30; // vol down
|
||||||
currentConfig.gamma = 100;
|
currentConfig.gamma = 100;
|
||||||
|
currentConfig.PicoCDBuffers = 64;
|
||||||
strncpy(cfg, PicoConfigFile, 511);
|
strncpy(cfg, PicoConfigFile, 511);
|
||||||
cfg[511] = 0;
|
cfg[511] = 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -517,6 +518,7 @@ int emu_ReadConfig(int game)
|
||||||
PsndRate = currentConfig.PsndRate;
|
PsndRate = currentConfig.PsndRate;
|
||||||
PicoRegionOverride = currentConfig.PicoRegion;
|
PicoRegionOverride = currentConfig.PicoRegion;
|
||||||
PicoAutoRgnOrder = currentConfig.PicoAutoRgnOrder;
|
PicoAutoRgnOrder = currentConfig.PicoAutoRgnOrder;
|
||||||
|
PicoCDBuffers = currentConfig.PicoCDBuffers;
|
||||||
if (PicoOpt & 0x20) {
|
if (PicoOpt & 0x20) {
|
||||||
actionNames[ 8] = "Z"; actionNames[ 9] = "Y";
|
actionNames[ 8] = "Z"; actionNames[ 9] = "Y";
|
||||||
actionNames[10] = "X"; actionNames[11] = "MODE";
|
actionNames[10] = "X"; actionNames[11] = "MODE";
|
||||||
|
@ -555,6 +557,7 @@ int emu_WriteConfig(int game)
|
||||||
currentConfig.PsndRate = PsndRate;
|
currentConfig.PsndRate = PsndRate;
|
||||||
currentConfig.PicoRegion = PicoRegionOverride;
|
currentConfig.PicoRegion = PicoRegionOverride;
|
||||||
currentConfig.PicoAutoRgnOrder = PicoAutoRgnOrder;
|
currentConfig.PicoAutoRgnOrder = PicoAutoRgnOrder;
|
||||||
|
currentConfig.PicoCDBuffers = PicoCDBuffers;
|
||||||
bwrite = fwrite(¤tConfig, 1, sizeof(currentConfig), f);
|
bwrite = fwrite(¤tConfig, 1, sizeof(currentConfig), f);
|
||||||
fflush(f);
|
fflush(f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
@ -1068,6 +1071,9 @@ void emu_Loop(void)
|
||||||
PsndOut = 0;
|
PsndOut = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepare CD buffer
|
||||||
|
if (PicoMCD & 1) PicoCDBufferInit();
|
||||||
|
|
||||||
// loop?
|
// loop?
|
||||||
while (engineState == PGS_Running)
|
while (engineState == PGS_Running)
|
||||||
{
|
{
|
||||||
|
@ -1253,6 +1259,9 @@ if (Pico.m.frame_count == 31563) {
|
||||||
frames_done++; frames_shown++;
|
frames_done++; frames_shown++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (PicoMCD & 1) PicoCDBufferFree();
|
||||||
|
|
||||||
// save SRAM
|
// save SRAM
|
||||||
if((currentConfig.EmuOpt & 1) && SRam.changed) {
|
if((currentConfig.EmuOpt & 1) && SRam.changed) {
|
||||||
osd_text(4, 232, "Writing SRAM/BRAM..");
|
osd_text(4, 232, "Writing SRAM/BRAM..");
|
||||||
|
|
|
@ -31,6 +31,7 @@ typedef struct {
|
||||||
int gamma;
|
int gamma;
|
||||||
int JoyBinds[4][32];
|
int JoyBinds[4][32];
|
||||||
int PicoAutoRgnOrder;
|
int PicoAutoRgnOrder;
|
||||||
|
int PicoCDBuffers;
|
||||||
} currentConfig_t;
|
} currentConfig_t;
|
||||||
|
|
||||||
extern char romFileName[];
|
extern char romFileName[];
|
||||||
|
|
|
@ -729,6 +729,10 @@ static void kc_sel_loop(void)
|
||||||
static void draw_cd_menu_options(int menu_sel, char *b_us, char *b_eu, char *b_jp)
|
static void draw_cd_menu_options(int menu_sel, char *b_us, char *b_eu, char *b_jp)
|
||||||
{
|
{
|
||||||
int tl_x = 25, tl_y = 60, y;
|
int tl_x = 25, tl_y = 60, y;
|
||||||
|
char ra_buff[16];
|
||||||
|
|
||||||
|
if (PicoCDBuffers > 1) sprintf(ra_buff, "%5iK", PicoCDBuffers * 2);
|
||||||
|
else strcpy(ra_buff, " OFF");
|
||||||
|
|
||||||
y = tl_y;
|
y = tl_y;
|
||||||
//memset(gp2x_screen, 0, 320*240);
|
//memset(gp2x_screen, 0, 320*240);
|
||||||
|
@ -741,6 +745,7 @@ static void draw_cd_menu_options(int menu_sel, char *b_us, char *b_eu, char *b_j
|
||||||
gp2x_text_out8(tl_x, (y+=10), "CDDA audio (using mp3s) %s", (currentConfig.PicoOpt&0x0800)?"ON":"OFF"); // 4
|
gp2x_text_out8(tl_x, (y+=10), "CDDA audio (using mp3s) %s", (currentConfig.PicoOpt&0x0800)?"ON":"OFF"); // 4
|
||||||
gp2x_text_out8(tl_x, (y+=10), "PCM audio %s", (currentConfig.PicoOpt&0x0400)?"ON":"OFF"); // 5
|
gp2x_text_out8(tl_x, (y+=10), "PCM audio %s", (currentConfig.PicoOpt&0x0400)?"ON":"OFF"); // 5
|
||||||
gp2x_text_out8(tl_x, (y+=10), "Better sync (very slow) %s", (currentConfig.PicoOpt&0x2000)?"ON":"OFF"); // 6
|
gp2x_text_out8(tl_x, (y+=10), "Better sync (very slow) %s", (currentConfig.PicoOpt&0x2000)?"ON":"OFF"); // 6
|
||||||
|
gp2x_text_out8(tl_x, (y+=10), "ReadAhead buffer %s", ra_buff); // 7
|
||||||
gp2x_text_out8(tl_x, (y+=10), "Done");
|
gp2x_text_out8(tl_x, (y+=10), "Done");
|
||||||
|
|
||||||
// draw cursor
|
// draw cursor
|
||||||
|
@ -756,7 +761,7 @@ static void draw_cd_menu_options(int menu_sel, char *b_us, char *b_eu, char *b_j
|
||||||
|
|
||||||
static void cd_menu_loop_options(void)
|
static void cd_menu_loop_options(void)
|
||||||
{
|
{
|
||||||
int menu_sel = 0, menu_sel_max = 7;
|
int menu_sel = 0, menu_sel_max = 8;
|
||||||
unsigned long inp = 0;
|
unsigned long inp = 0;
|
||||||
char bios_us[32], bios_eu[32], bios_jp[32], *bios, *p;
|
char bios_us[32], bios_eu[32], bios_jp[32], *bios, *p;
|
||||||
|
|
||||||
|
@ -787,7 +792,17 @@ static void cd_menu_loop_options(void)
|
||||||
case 4: currentConfig.PicoOpt^=0x0800; break;
|
case 4: currentConfig.PicoOpt^=0x0800; break;
|
||||||
case 5: currentConfig.PicoOpt^=0x0400; break;
|
case 5: currentConfig.PicoOpt^=0x0400; break;
|
||||||
case 6: currentConfig.PicoOpt^=0x2000; break;
|
case 6: currentConfig.PicoOpt^=0x2000; break;
|
||||||
case 7: return;
|
case 7:
|
||||||
|
if (inp & GP2X_LEFT) {
|
||||||
|
PicoCDBuffers >>= 1;
|
||||||
|
if (PicoCDBuffers < 64) PicoCDBuffers = 0;
|
||||||
|
} else {
|
||||||
|
if (PicoCDBuffers < 64) PicoCDBuffers = 64;
|
||||||
|
else PicoCDBuffers <<= 1;
|
||||||
|
if (PicoCDBuffers > 4096) PicoCDBuffers = 4096;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 8: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(inp & (GP2X_X|GP2X_A)) return;
|
if(inp & (GP2X_X|GP2X_A)) return;
|
||||||
|
|
|
@ -32,7 +32,7 @@ OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Utils.o ../../Pico/Memory
|
||||||
# Pico - CD
|
# Pico - CD
|
||||||
OBJS += ../../Pico/cd/Pico.o ../../Pico/cd/Memory.o ../../Pico/cd/Sek.o ../../Pico/cd/LC89510.o \
|
OBJS += ../../Pico/cd/Pico.o ../../Pico/cd/Memory.o ../../Pico/cd/Sek.o ../../Pico/cd/LC89510.o \
|
||||||
../../Pico/cd/cd_sys.o ../../Pico/cd/cd_file.o ../../Pico/cd/gfx_cd.o \
|
../../Pico/cd/cd_sys.o ../../Pico/cd/cd_file.o ../../Pico/cd/gfx_cd.o \
|
||||||
../../Pico/cd/Area.o ../../Pico/cd/Misc.o ../../Pico/cd/pcm.o
|
../../Pico/cd/Area.o ../../Pico/cd/Misc.o ../../Pico/cd/pcm.o ../../Pico/cd/buffering.o
|
||||||
# Pico - sound
|
# Pico - sound
|
||||||
OBJS += ../../Pico/sound/sound.o ../../Pico/sound/sn76496.o ../../Pico/sound/ym2612.o ../../Pico/sound/mix.o
|
OBJS += ../../Pico/sound/sound.o ../../Pico/sound/sn76496.o ../../Pico/sound/ym2612.o ../../Pico/sound/mix.o
|
||||||
# zlib
|
# zlib
|
||||||
|
|
|
@ -3,43 +3,149 @@ About
|
||||||
-----
|
-----
|
||||||
|
|
||||||
This version of PicoDrive is another enhanced version of Dave's
|
This version of PicoDrive is another enhanced version of Dave's
|
||||||
Megadrive / Genesis emulator for Pocket PC. The original Dave's code was
|
Megadrive / Genesis emulator for Pocket PC, which now can also emulate
|
||||||
heavily modified (including Cyclone core), parts of it were rewritten in
|
Sega/Mega CD. The original Dave's code was heavily modified (including
|
||||||
asm, many features added, accuracy increased. This version is aimed at
|
Cyclone core), parts of it were rewritten in asm, many features added,
|
||||||
ARM-based handheld devices, so ports exist for GP2X handheld console,
|
accuracy increased. Sega/Mega CD emulation is mostly based on Gens code.
|
||||||
Symbian smartphones and PocketPC devices.
|
This version is aimed at ARM-based handheld devices, so ports exist for
|
||||||
|
GP2X handheld console, Symbian smartphones and other devices.
|
||||||
|
|
||||||
|
|
||||||
How to make it run
|
How to make it run
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
GP2X:
|
|
||||||
Copy PicoDrive.gpe, code940.bin and mmuhack.o to any place in your filesystem
|
Copy PicoDrive.gpe, code940.bin and mmuhack.o to any place in your filesystem
|
||||||
(all 3 files must be in the same directory) and run PicoDrive.gpe.
|
(all 3 files must be in the same directory) and run PicoDrive.gpe.
|
||||||
Then load a ROM and enjoy!
|
Then load a ROM and enjoy! ROMs can be in .smd or .bin format and can be zipped.
|
||||||
|
|
||||||
Symbian:
|
|
||||||
Select PicoDrive from application (tools) menu and run it. That's it!
|
|
||||||
|
|
||||||
All:
|
|
||||||
If you have any problems (game does not boot, sound is glitchy, broken graphics),
|
If you have any problems (game does not boot, sound is glitchy, broken graphics),
|
||||||
make sure you enable "Accurate timing", "Emulate Z80" and then disable
|
make sure you enable "Accurate timing", "Emulate Z80" and then disable
|
||||||
"Fast renderer". This way you will get the best compatibility this emulator can
|
"Fast renderer". This way you will get the best compatibility this emulator can
|
||||||
provide.
|
provide.
|
||||||
|
|
||||||
|
|
||||||
|
How to run Sega/Mega CD games
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
To play any game, you need BIOS files. These files must be copied to the same
|
||||||
|
directory as PicoDrive.gpe. Files can be named as follows:
|
||||||
|
US: us_scd1_9210.bin us_scd2_9306.bin SegaCDBIOS9303.bin
|
||||||
|
EU: eu_mcd1_9210.bin eu_mcd2_9303.bin eu_mcd2_9306.bin
|
||||||
|
JP: jp_mcd1_9112.bin jp_mcd1_9111.bin
|
||||||
|
these files can also be zipped.
|
||||||
|
|
||||||
|
The game must be dumped to ISO format, but BIN can be used too. If you want
|
||||||
|
CD music, you must use ISO+mp3 files. Audio from BIN files won't be read at
|
||||||
|
all due to SD access issues. Also BIN files are usually larger, so it's better
|
||||||
|
to use ISO. ISO+mp3 files can be named similarly as for other emus.
|
||||||
|
Here are some examples:
|
||||||
|
|
||||||
|
SonicCD.iso data track
|
||||||
|
SonicCD_02.mp3 audio track 1 (CD track 2)
|
||||||
|
SonicCD_03.mp3
|
||||||
|
...
|
||||||
|
|
||||||
|
Sonic the Hedgehog CD (US) - Track 01.iso
|
||||||
|
Sonic the Hedgehog CD (US) - Track 02.mp3
|
||||||
|
Sonic the Hedgehog CD (US) - Track 03.mp3
|
||||||
|
...
|
||||||
|
|
||||||
|
ISO files can also be zipped (but not mp3 files, as they are already
|
||||||
|
compressed). Note that this can cause very long loading times, which may
|
||||||
|
take up to several minutes. File naming is similar as with uncompressed ISOs.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
SonicCD.zip data track
|
||||||
|
SonicCD_02.mp3 audio track 1 (CD track 2)
|
||||||
|
SonicCD_03.mp3
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
See config.txt file.
|
See config.txt file.
|
||||||
|
|
||||||
|
|
||||||
|
Other important stuff
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
* When you use both GP2X CPUs, keep in mind that you can't overclock as high as
|
||||||
|
when using ARM920 only. For example my GP2X when run singlecore can reach
|
||||||
|
280MHz, but with both cores it's about 250MHz. When overclocked too much,
|
||||||
|
it may start hanging and producing random noise.
|
||||||
|
* PicoDrive is not a mp3 player, so all mp3s MUST be encoded at 44.1kHz stereo.
|
||||||
|
Otherwise mp3s will play too fast or too slow.
|
||||||
|
* Due to internal implementation mp3s must not be larger that ~15MB
|
||||||
|
(15548416 bytes). Larger mp3s will not be fully loaded.
|
||||||
|
* Use lower bitrate for better performance (96 or 128kbps CBRs recommended).
|
||||||
|
* RAM timings option is good for dualcore operation (it is disabled by
|
||||||
|
default because it doesn't work on every GP2X, so enable it in advanced
|
||||||
|
options).
|
||||||
|
|
||||||
|
|
||||||
|
Cheat support
|
||||||
|
-------------
|
||||||
|
|
||||||
|
To use GG/patch codes, you must type them into your favorite text editor, one
|
||||||
|
per line. Comments may follow code after a whitespace. Only GameGenie and
|
||||||
|
Genecyst patch formats are supported.
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
Genecyst patch (this example is for Sonic):
|
||||||
|
|
||||||
|
00334A:0005 Start with five lives
|
||||||
|
012D24:0001 Keep invincibility until end of stage
|
||||||
|
009C76:5478 each ring worth 2
|
||||||
|
009C76:5678 each ring worth 3
|
||||||
|
...
|
||||||
|
|
||||||
|
Game Genie patch (for Sonic 2):
|
||||||
|
|
||||||
|
ACLA-ATD4 Hidden palace instead of death egg in level select
|
||||||
|
...
|
||||||
|
|
||||||
|
Both GG and patch codes can be mixed in one file.
|
||||||
|
|
||||||
|
When the file is ready, name it just like your ROM file, but with additional
|
||||||
|
.pat extension, making sure that case matches.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
ROM: Sonic.zip
|
||||||
|
PATCH FILE: Sonic.zip.pat
|
||||||
|
|
||||||
|
ROM: Sonic 2.bin
|
||||||
|
PATCH FILE: Sonic 2.bin.pat
|
||||||
|
|
||||||
|
Put the file into your ROMs directory. Then load the .pat file as you would
|
||||||
|
a ROM. Then Cheat Menu Option should appear in main menu.
|
||||||
|
|
||||||
|
|
||||||
|
What is emulated?
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Genesis/MegaDrive:
|
||||||
|
main 68k @ 7.6MHz: yes, Cyclone core
|
||||||
|
z80 @ 3.6MHz: yes, DrZ80 core
|
||||||
|
VDP: yes, except some quirks not used by games
|
||||||
|
YM2612 FM: yes, optimized MAME core
|
||||||
|
SN76489 PSG: yes, MAME core
|
||||||
|
|
||||||
|
Sega/Mega CD:
|
||||||
|
another 68k @ 12.5MHz: yes, Cyclone too
|
||||||
|
gfx scaling/rotation chip (custom ASIC): not yet (faked only)
|
||||||
|
PCM sound source: yes
|
||||||
|
CD-ROM controller: yes (mostly)
|
||||||
|
bram (internal backup RAM): yes
|
||||||
|
|
||||||
|
|
||||||
Problems / limitations
|
Problems / limitations
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
* 32x, Sega CD, SVP are not emulated.
|
* 32x and SVP are not emulated.
|
||||||
* Various VDP quirks (window bug, scroll size 2, etc.) are not emulated,
|
* Various VDP quirks (window bug, scroll size 2, etc.) are not emulated,
|
||||||
as very few games use this.
|
as very few games use this (if any at all).
|
||||||
* Some games don't work or have glitches because of inaccurate timing and sync
|
* Some games don't work or have glitches because of inaccurate timing and sync
|
||||||
between the emulated chips.
|
between the emulated chips.
|
||||||
|
|
||||||
|
@ -67,13 +173,18 @@ MultiArcadeMachineEmulator (MAME) development
|
||||||
Texas Instruments SN76489 / SN76496 programmable tone /noise generator
|
Texas Instruments SN76489 / SN76496 programmable tone /noise generator
|
||||||
Homepage: http://www.mame.net/
|
Homepage: http://www.mame.net/
|
||||||
|
|
||||||
|
Stephane Dallongeville
|
||||||
|
Gens, MD/Mega CD/32X emulator. Most Sega CD code is based on this emu.
|
||||||
|
|
||||||
|
Helix community
|
||||||
|
Helix mp3 decoder
|
||||||
|
|
||||||
|
|
||||||
Additional thanks
|
Additional thanks
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
* Charles MacDonald (http://cgfm2.emuviews.com/) for old but still very useful
|
* Charles MacDonald (http://cgfm2.emuviews.com/) for old but still very useful
|
||||||
info about genesis hardware.
|
info about genesis hardware.
|
||||||
* Stéphane Dallongeville for creating Gens and making it open-source.
|
|
||||||
* Steve Snake for all that he has done for Genesis emulation scene.
|
* Steve Snake for all that he has done for Genesis emulation scene.
|
||||||
* Bart Trzynadlowski for his SSFII and 68000 docs.
|
* Bart Trzynadlowski for his SSFII and 68000 docs.
|
||||||
* Haze for his research (http://haze.mameworld.info).
|
* Haze for his research (http://haze.mameworld.info).
|
||||||
|
@ -100,6 +211,47 @@ Symbian:
|
||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
---------
|
---------
|
||||||
|
1.2x
|
||||||
|
+ ISO files now can be zipped. Note that this causes VERY long loading times.
|
||||||
|
+ Added data pre-buffering support, this allows to reduce frequency of short pauses
|
||||||
|
in FMV games, but makes those pauses longer.
|
||||||
|
* Fixed PCM DMA transfers (intro FMV in Popful Mail).
|
||||||
|
|
||||||
|
1.201
|
||||||
|
+ Added basic cheat support (GameGenie and Genecyst patches).
|
||||||
|
|
||||||
|
1.20
|
||||||
|
* Fixed a long-standing problem in audio mixing code which caused slight distortions
|
||||||
|
at lower sample rates.
|
||||||
|
* Changed the way 920 and 940 communicates (again), should be more reliable and give
|
||||||
|
slight performance increase.
|
||||||
|
* Some optimizations in audio mixing code.
|
||||||
|
* Some menu changes (background added, smaller font in ROM browser, savestate loader
|
||||||
|
now can select slots).
|
||||||
|
+ 1M mode DMA transfers implemented (used by FMV games like Night Trap and Sewer Shark).
|
||||||
|
+ Games now can run code from WORD RAM in 1M mode (fixes Adventures of Willy Beamish).
|
||||||
|
+ "Cell arrange" address mapping is now emulated (Heart of the alien).
|
||||||
|
+ "Color numeric operation" is now emulated (text in Lunar 2, Silpheed intro graphics).
|
||||||
|
+ "Better sync" option added (prevents some games from hanging).
|
||||||
|
|
||||||
|
1.14
|
||||||
|
+ Region autodetection now can be customized.
|
||||||
|
* When CDDA music tracks changed, old buffer contents were incorrectly played. Fixed.
|
||||||
|
* BRAM is now automatically formatted (no need to enter BIOS menu and format any more).
|
||||||
|
* Games now can be reset, CDDA music no longer breaks after loading another ISO.
|
||||||
|
* Fixed a race condition between 920 and 940 which sometimes caused CDDA music not to play.
|
||||||
|
+ Savestates implemented for Sega/Mega CD.
|
||||||
|
+ PCM sound added.
|
||||||
|
* Some mixer code rewritten in asm. 22kHz and 11kHz sound rates are now supported in
|
||||||
|
Mega CD mode (but mp3s must still be 44kHz stereo).
|
||||||
|
+ Timer emulation added.
|
||||||
|
* CDC DMA tansfers fixed. Snatcher and probably some more games now boot.
|
||||||
|
* 2M word RAM -> VDP transfers fixed, no more corruption in Ecco and some other games.
|
||||||
|
|
||||||
|
1.10
|
||||||
|
+ GP2X: Added experimental Sega CD support.
|
||||||
|
+ GP2X: Added partial gmv movie playback support.
|
||||||
|
|
||||||
0.964
|
0.964
|
||||||
* GP2X: Fixed a sound buffer underflow issue on lower sample rate modes, which was
|
* GP2X: Fixed a sound buffer underflow issue on lower sample rate modes, which was
|
||||||
happening for NTSC games and causing sound clicks.
|
happening for NTSC games and causing sound clicks.
|
||||||
|
@ -299,3 +451,7 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
SEGA/Genesis/MegaDrive/SEGA-CD/Mega-CD/32X are trademarks of
|
||||||
|
Sega Enterprises Ltd.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue