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)
|
||||
{
|
||||
while (count--)
|
||||
|
|
|
@ -47,6 +47,8 @@ extern void (*PicoWriteSound)(int len); // called once per frame at the best tim
|
|||
|
||||
int PicoFrameMCD(void);
|
||||
|
||||
extern int PicoCDBuffers;
|
||||
|
||||
// Area.c
|
||||
typedef size_t (arearw)(void *p, size_t _size, size_t _n, void *file);
|
||||
typedef size_t (areaeof)(void *file);
|
||||
|
@ -61,6 +63,10 @@ extern areaseek *areaSeek;
|
|||
extern areaclose *areaClose;
|
||||
extern void (*PicoStateProgressCB)(const char *str);
|
||||
|
||||
// cd/buffering.c
|
||||
void PicoCDBufferInit(void);
|
||||
void PicoCDBufferFree(void);
|
||||
|
||||
// Cart.c
|
||||
typedef enum
|
||||
{
|
||||
|
|
|
@ -300,6 +300,7 @@ void SRAMWriteEEPROM(unsigned int d);
|
|||
unsigned int SRAMReadEEPROM();
|
||||
void SRAMUpdPending(unsigned int a, unsigned int d);
|
||||
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 memset32(int *dest, int c, int count);
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ static void DmaSlow(int len)
|
|||
r = Pico.cram;
|
||||
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
|
||||
a2+=inc;
|
||||
// didn't src overlap?
|
||||
|
|
|
@ -70,7 +70,7 @@ void LC89510_Reset(void)
|
|||
|
||||
void Update_CDC_TRansfer(int which)
|
||||
{
|
||||
unsigned int DMA_Adr, dep, length, len;
|
||||
unsigned int DMA_Adr, dep, length;
|
||||
unsigned short *dest;
|
||||
unsigned char *src;
|
||||
|
||||
|
@ -96,7 +96,7 @@ void Update_CDC_TRansfer(int which)
|
|||
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;
|
||||
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);
|
||||
|
||||
// TODO: bswapcpy
|
||||
for (len = length; len > 0; len--, src+=2, dest++)
|
||||
*dest = (src[0]<<8) | src[1];
|
||||
memcpy16bswap(dest, src, length);
|
||||
|
||||
{ // debug
|
||||
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",
|
||||
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);
|
||||
dest = (unsigned short *) (Pico_mcd->word_ram2M + dep);
|
||||
|
||||
for (len = length; len > 0; len--, src+=2, dest++)
|
||||
*dest = (src[0]<<8) | src[1];
|
||||
memcpy16bswap(dest, src, length);
|
||||
|
||||
{ // debug
|
||||
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",
|
||||
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
|
||||
dest = (unsigned char *) Ram_PCM;
|
||||
dep = ((DMA_Adr & 0x03FF) << 2) + PCM_Chip.Bank;
|
||||
#else
|
||||
dprintf("FIXME: CD DMA # %04x -> PCM", Pico_mcd->cdc.DAC.N);
|
||||
#endif
|
||||
dep = (DMA_Adr & 0x03FF) << 2;
|
||||
dprintf("CD DMA # %04x -> PCM[%i] # %04x, len=%i",
|
||||
Pico_mcd->cdc.DAC.N, Pico_mcd->pcm.bank, dep, length);
|
||||
dest = (unsigned short *) (Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank] + dep);
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -157,12 +156,11 @@ void Update_CDC_TRansfer(int which)
|
|||
cdprintf("CD DMA # %04x -> prg_ram # %06x, len=%i",
|
||||
Pico_mcd->cdc.DAC.N, dep, length);
|
||||
|
||||
for (len = length; len > 0; len--, src+=2, dest++)
|
||||
*dest = (src[0]<<8) | src[1];
|
||||
memcpy16bswap(dest, src, length);
|
||||
|
||||
{ // debug
|
||||
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",
|
||||
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
|
||||
else a &= 0x1fffe;
|
||||
d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);
|
||||
//d = 0xaaaa;
|
||||
} else {
|
||||
// allow access in any mode, like Gens does
|
||||
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)
|
||||
|
@ -958,13 +1016,10 @@ void PicoWriteS68k8(u32 a,u8 d)
|
|||
|
||||
// word RAM (2M area)
|
||||
if ((a&0xfc0000)==0x080000) { // 080000-0bffff
|
||||
int r3 = Pico_mcd->s68k_regs[3];
|
||||
wrdprintf("s68k_wram2M w8: [%06x] %02x @%06x", a, d, SekPcS68k);
|
||||
if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
|
||||
int bank = !(Pico_mcd->s68k_regs[3]&1);
|
||||
if (a&1) d &= 0x0f;
|
||||
else d >>= 4;
|
||||
Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff]=d;
|
||||
dprintf("FIXME: decode");
|
||||
if (r3 & 4) { // 1M decode mode?
|
||||
decode_write8(a, d, r3);
|
||||
} else {
|
||||
// allow access in any mode, like Gens does
|
||||
*(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;
|
||||
|
@ -1039,12 +1094,10 @@ void PicoWriteS68k16(u32 a,u16 d)
|
|||
|
||||
// word RAM (2M area)
|
||||
if ((a&0xfc0000)==0x080000) { // 080000-0bffff
|
||||
int r3 = Pico_mcd->s68k_regs[3];
|
||||
wrdprintf("s68k_wram2M w16: [%06x] %04x @%06x", a, d, SekPcS68k);
|
||||
if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
|
||||
int bank = !(Pico_mcd->s68k_regs[3]&1);
|
||||
d &= ~0xf0; d |= d >> 8;
|
||||
Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff] = d;
|
||||
dprintf("FIXME: decode");
|
||||
if (r3 & 4) { // 1M decode mode?
|
||||
decode_write16(a, d, r3);
|
||||
} else {
|
||||
// allow access in any mode, like Gens does
|
||||
*(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;
|
||||
|
@ -1121,14 +1174,11 @@ void PicoWriteS68k32(u32 a,u32 d)
|
|||
|
||||
// word RAM (2M area)
|
||||
if ((a&0xfc0000)==0x080000) { // 080000-0bffff
|
||||
int r3 = Pico_mcd->s68k_regs[3];
|
||||
wrdprintf("s68k_wram2M w32: [%06x] %08x @%06x", a, d, SekPcS68k);
|
||||
if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?
|
||||
int bank = !(Pico_mcd->s68k_regs[3]&1);
|
||||
a >>= 1;
|
||||
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");
|
||||
if (r3 & 4) { // 1M decode mode?
|
||||
decode_write16(a , d >> 16, r3);
|
||||
decode_write16(a+2, d , r3);
|
||||
} else {
|
||||
// allow access in any mode, like Gens does
|
||||
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 where_read = 0;
|
||||
// static char cp_buf[2560];
|
||||
|
||||
if (Pico_mcd->s68k_regs[0x36] & 1) // DATA
|
||||
{
|
||||
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..
|
||||
//fseek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET);
|
||||
//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;
|
||||
|
||||
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
|
||||
// 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
|
||||
{
|
||||
int where_read = 0;
|
||||
|
||||
// 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->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;
|
||||
//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_read(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, 2048, Pico_mcd->TOC.Tracks[0].F);
|
||||
//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);
|
||||
PicoCDBufferRead(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, where_read);
|
||||
|
||||
#ifdef DEBUG_CD
|
||||
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;
|
||||
|
||||
// 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)
|
||||
{
|
||||
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
|
||||
|
||||
memcpy32:
|
||||
|
|
|
@ -43,7 +43,7 @@ OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Utils.o ../../Pico/Memory
|
|||
# Pico - CD
|
||||
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/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
|
||||
ifeq "$(asm_render)" "1"
|
||||
DEFINC += -D_ASM_DRAW_C
|
||||
|
|
|
@ -496,6 +496,7 @@ int emu_ReadConfig(int game)
|
|||
currentConfig.KeyBinds[23] = 1<<29; // vol up
|
||||
currentConfig.KeyBinds[22] = 1<<30; // vol down
|
||||
currentConfig.gamma = 100;
|
||||
currentConfig.PicoCDBuffers = 64;
|
||||
strncpy(cfg, PicoConfigFile, 511);
|
||||
cfg[511] = 0;
|
||||
} else {
|
||||
|
@ -517,6 +518,7 @@ int emu_ReadConfig(int game)
|
|||
PsndRate = currentConfig.PsndRate;
|
||||
PicoRegionOverride = currentConfig.PicoRegion;
|
||||
PicoAutoRgnOrder = currentConfig.PicoAutoRgnOrder;
|
||||
PicoCDBuffers = currentConfig.PicoCDBuffers;
|
||||
if (PicoOpt & 0x20) {
|
||||
actionNames[ 8] = "Z"; actionNames[ 9] = "Y";
|
||||
actionNames[10] = "X"; actionNames[11] = "MODE";
|
||||
|
@ -555,6 +557,7 @@ int emu_WriteConfig(int game)
|
|||
currentConfig.PsndRate = PsndRate;
|
||||
currentConfig.PicoRegion = PicoRegionOverride;
|
||||
currentConfig.PicoAutoRgnOrder = PicoAutoRgnOrder;
|
||||
currentConfig.PicoCDBuffers = PicoCDBuffers;
|
||||
bwrite = fwrite(¤tConfig, 1, sizeof(currentConfig), f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
@ -1068,6 +1071,9 @@ void emu_Loop(void)
|
|||
PsndOut = 0;
|
||||
}
|
||||
|
||||
// prepare CD buffer
|
||||
if (PicoMCD & 1) PicoCDBufferInit();
|
||||
|
||||
// loop?
|
||||
while (engineState == PGS_Running)
|
||||
{
|
||||
|
@ -1253,6 +1259,9 @@ if (Pico.m.frame_count == 31563) {
|
|||
frames_done++; frames_shown++;
|
||||
}
|
||||
|
||||
|
||||
if (PicoMCD & 1) PicoCDBufferFree();
|
||||
|
||||
// save SRAM
|
||||
if((currentConfig.EmuOpt & 1) && SRam.changed) {
|
||||
osd_text(4, 232, "Writing SRAM/BRAM..");
|
||||
|
|
|
@ -31,6 +31,7 @@ typedef struct {
|
|||
int gamma;
|
||||
int JoyBinds[4][32];
|
||||
int PicoAutoRgnOrder;
|
||||
int PicoCDBuffers;
|
||||
} currentConfig_t;
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
//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), "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), "ReadAhead buffer %s", ra_buff); // 7
|
||||
gp2x_text_out8(tl_x, (y+=10), "Done");
|
||||
|
||||
// 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)
|
||||
{
|
||||
int menu_sel = 0, menu_sel_max = 7;
|
||||
int menu_sel = 0, menu_sel_max = 8;
|
||||
unsigned long inp = 0;
|
||||
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 5: currentConfig.PicoOpt^=0x0400; 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;
|
||||
|
|
|
@ -32,7 +32,7 @@ OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Utils.o ../../Pico/Memory
|
|||
# Pico - CD
|
||||
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/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
|
||||
OBJS += ../../Pico/sound/sound.o ../../Pico/sound/sn76496.o ../../Pico/sound/ym2612.o ../../Pico/sound/mix.o
|
||||
# zlib
|
||||
|
|
|
@ -3,43 +3,149 @@ About
|
|||
-----
|
||||
|
||||
This version of PicoDrive is another enhanced version of Dave's
|
||||
Megadrive / Genesis emulator for Pocket PC. The original Dave's code was
|
||||
heavily modified (including Cyclone core), parts of it were rewritten in
|
||||
asm, many features added, accuracy increased. This version is aimed at
|
||||
ARM-based handheld devices, so ports exist for GP2X handheld console,
|
||||
Symbian smartphones and PocketPC devices.
|
||||
Megadrive / Genesis emulator for Pocket PC, which now can also emulate
|
||||
Sega/Mega CD. The original Dave's code was heavily modified (including
|
||||
Cyclone core), parts of it were rewritten in asm, many features added,
|
||||
accuracy increased. Sega/Mega CD emulation is mostly based on Gens code.
|
||||
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
|
||||
------------------
|
||||
|
||||
GP2X:
|
||||
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.
|
||||
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),
|
||||
make sure you enable "Accurate timing", "Emulate Z80" and then disable
|
||||
"Fast renderer". This way you will get the best compatibility this emulator can
|
||||
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
|
||||
-------------
|
||||
|
||||
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
|
||||
----------------------
|
||||
|
||||
* 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,
|
||||
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
|
||||
between the emulated chips.
|
||||
|
||||
|
@ -67,13 +173,18 @@ MultiArcadeMachineEmulator (MAME) development
|
|||
Texas Instruments SN76489 / SN76496 programmable tone /noise generator
|
||||
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
|
||||
-----------------
|
||||
|
||||
* Charles MacDonald (http://cgfm2.emuviews.com/) for old but still very useful
|
||||
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.
|
||||
* Bart Trzynadlowski for his SSFII and 68000 docs.
|
||||
* Haze for his research (http://haze.mameworld.info).
|
||||
|
@ -100,6 +211,47 @@ Symbian:
|
|||
|
||||
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
|
||||
* GP2X: Fixed a sound buffer underflow issue on lower sample rate modes, which was
|
||||
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)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
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