optimizations, fixes, hacks, psp, ...

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@295 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2007-11-15 23:01:20 +00:00
parent 8022f53da6
commit b542be4686
37 changed files with 928 additions and 548 deletions

View file

@ -66,7 +66,7 @@ void blockcpy_or(void *dst, void *src, size_t n, int pat)
#endif
#ifdef _ASM_DRAW_C_MIPS
#ifdef _ASM_DRAW_C_AMIPS
int TileNorm(int sx,int addr,int pal);
int TileFlip(int sx,int addr,int pal);
#else
@ -1127,8 +1127,7 @@ static void DrawAllSprites(int *hcache, int maxwidth, int prio, int sh)
#ifndef _ASM_DRAW_C
static void BackFill(int reg7, int sh)
{
unsigned int back=0;
unsigned int *pd=NULL,*end=NULL;
unsigned int back;
// Start with a blank scanline (background colour):
back=reg7&0x3f;
@ -1136,10 +1135,7 @@ static void BackFill(int reg7, int sh)
back|=back<<8;
back|=back<<16;
pd= (unsigned int *)(HighCol+8);
end=(unsigned int *)(HighCol+8+320);
do { pd[0]=pd[1]=pd[2]=pd[3]=back; pd+=4; } while (pd<end);
memset32((int *)(HighCol+8), back, 320/4);
}
#endif

View file

@ -485,8 +485,7 @@ static void DrawAllSpritesFull(int prio, int maxwidth)
#ifndef _ASM_DRAW_C
static void BackFillFull(int reg7)
{
unsigned int back, i;
unsigned int *p=(unsigned int *)PicoDraw2FB;
unsigned int back;
// Start with a background color:
// back=PicoCramHigh[reg7&0x3f];
@ -494,12 +493,7 @@ static void BackFillFull(int reg7)
back|=back<<8;
back|=back<<16;
for(i = LINE_WIDTH*(8+(END_ROW-START_ROW)*8)/16; i; i--) {
*p++ = back; // do 16 pixels per iteration
*p++ = back;
*p++ = back;
*p++ = back;
}
memset32((int *)PicoDraw2FB, back, LINE_WIDTH*(8+(END_ROW-START_ROW)*8)/4);
}
#endif

View file

@ -334,9 +334,12 @@ PICO_INTERNAL_ASM u32 PicoRead8(u32 a)
log_io(a, 8, 0);
if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram
d=OtherRead16(a&~1, 8); if ((a&1)==0) d>>=8;
if ((a&0xe700e0)==0xc00000) // VDP
d=PicoVideoRead(a);
else d=OtherRead16(a&~1, 8);
if ((a&1)==0) d>>=8;
end:
#ifdef __debug_io
dprintf("r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPc);
#endif
@ -370,7 +373,9 @@ PICO_INTERNAL_ASM u32 PicoRead16(u32 a)
if (a<Pico.romsize) { d = *(u16 *)(Pico.rom+a); goto end; } // Rom
log_io(a, 16, 0);
d = OtherRead16(a, 16);
if ((a&0xe700e0)==0xc00000)
d = PicoVideoRead(a);
else d = OtherRead16(a, 16);
end:
#ifdef __debug_io
@ -404,7 +409,9 @@ PICO_INTERNAL_ASM u32 PicoRead32(u32 a)
if (a<Pico.romsize) { u16 *pm=(u16 *)(Pico.rom+a); d = (pm[0]<<16)|pm[1]; goto end; } // Rom
log_io(a, 32, 0);
d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);
if ((a&0xe700e0)==0xc00000)
d = (PicoVideoRead(a)<<16)|PicoVideoRead(a+2);
else d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);
end:
#ifdef __debug_io
@ -454,6 +461,7 @@ void PicoWrite16(u32 a,u16 d)
log_io(a, 16, 1);
a&=0xfffffe;
if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; } // VDP
OtherWrite16(a,d);
}
@ -476,6 +484,14 @@ static void PicoWrite32(u32 a,u32 d)
log_io(a, 32, 1);
a&=0xfffffe;
if ((a&0xe700e0)==0xc00000)
{
// VDP:
PicoVideoWrite(a, (u16)(d>>16));
PicoVideoWrite(a+2,(u16)d);
return;
}
OtherWrite16(a, (u16)(d>>16));
OtherWrite16(a+2,(u16)d);
}
@ -660,10 +676,6 @@ PICO_INTERNAL unsigned char z80_read(unsigned short a)
{
u8 ret = 0;
#ifndef _USE_DRZ80
if (a<0x4000) return Pico.zram[a&0x1fff];
#endif
if ((a>>13)==2) // 0x4000-0x5fff (Charles MacDonald)
{
if (PicoOpt&1) ret = (u8) YM2612Read();
@ -681,10 +693,8 @@ PICO_INTERNAL unsigned char z80_read(unsigned short a)
return ret;
}
#ifdef _USE_DRZ80
// should not be needed || dprintf("z80_read RAM");
// should not be needed, cores should be able to access RAM themselves
if (a<0x4000) return Pico.zram[a&0x1fff];
#endif
elprintf(EL_ANOMALY, "z80 invalid r8 [%06x] %02x", a, ret);
return ret;
@ -696,10 +706,6 @@ PICO_INTERNAL_ASM void z80_write(unsigned char data, unsigned short a)
PICO_INTERNAL_ASM void z80_write(unsigned int a, unsigned char data)
#endif
{
#ifndef _USE_DRZ80
if (a<0x4000) { Pico.zram[a&0x1fff]=data; return; }
#endif
if ((a>>13)==2) // 0x4000-0x5fff (Charles MacDonald)
{
if(PicoOpt&1) emustatus|=YM2612Write(a, data) & 1;
@ -730,10 +736,8 @@ PICO_INTERNAL_ASM void z80_write(unsigned int a, unsigned char data)
return;
}
#ifdef _USE_DRZ80
// should not be needed, drZ80 knows how to access RAM itself || dprintf("z80_write RAM @ %08x", lr);
// should not be needed
if (a<0x4000) { Pico.zram[a&0x1fff]=data; return; }
#endif
elprintf(EL_ANOMALY, "z80 invalid w8 [%06x] %02x", a, data);
}

View file

@ -386,17 +386,14 @@ m_read8_misc2:
cmp r2, #0x4000
mvnne r0, #0
bxne lr @ invalid
.if EXTERNAL_YM2612
ldr r1, =PicoOpt
ldr r1, [r1]
tst r1, #1
beq m_read8_fake_ym2612
tst r1, #0x200
beq YM2612Read_
b YM2612Read_940
.else
b YM2612Read_
.endif
ldrne r1, =ym2612_st
ldrne r1, [r1]
ldrneb r0, [r1, #0x11] @ ym2612_st->status
bxne lr
m_read8_fake_ym2612:
ldr r3, =(Pico+0x22200)

View file

@ -72,9 +72,9 @@ static
void z80WriteBusReq(u32 d)
{
d&=1; d^=1;
//if (Pico.m.scanline != -1)
{
if(!d) {
if (!d)
{
// this is for a nasty situation where Z80 was enabled and disabled in the same 68k timeslice (Golden Axe III)
if (Pico.m.z80Run) {
int lineCycles;
@ -85,7 +85,7 @@ void z80WriteBusReq(u32 d)
if (lineCycles > 0) { // && lineCycles <= 488) {
//dprintf("zrun: %i/%i cycles", lineCycles, (lineCycles>>1)-(lineCycles>>5));
lineCycles=(lineCycles>>1)-(lineCycles>>5);
z80_run(lineCycles);
z80_run_nr(lineCycles);
}
}
} else {
@ -136,10 +136,6 @@ u32 OtherRead16(u32 a, int realsize)
goto end;
}
#ifndef _ASM_MEMORY_C
if ((a&0xe700e0)==0xc00000) { d=PicoVideoRead(a); goto end; }
#endif
d = OtherRead16End(a, realsize);
end:
@ -204,7 +200,6 @@ static
#endif
void OtherWrite16(u32 a,u32 d)
{
if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; }
if (a==0xa11100) { z80WriteBusReq(d>>8); return; }
if (a==0xa11200) { dprintf("write z80reset: %04x", d); if(!(d&0x100)) z80_reset(); return; }
if ((a&0xffffe0)==0xa10000) { IoWrite8(a, d); return; } // I/O ports

View file

@ -425,8 +425,10 @@ m_read8_z80_misc:
andi $t0, 1
beqz $t0, m_read8_fake_ym2612
lui $t0, %hi(Pico+0x22208)
j YM2612Read_
nop
lui $t0, %hi(ym2612_st)
lw $t0, %lo(ym2612_st)($t0)
jr $ra
lb $v0, 0x11($t0)
m_read8_fake_ym2612:
lb $v0, %lo(Pico+0x22208)($t0) # Pico.m.rotate

View file

@ -353,7 +353,7 @@ PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count)
*dest++ = (src_[0] << 8) | src_[1];
}
#ifndef _ASM_MISC_C_AMIPS
PICO_INTERNAL_ASM void memcpy32(int *dest, int *src, int count)
{
intblock *bd = (intblock *) dest, *bs = (intblock *) src;
@ -376,5 +376,7 @@ PICO_INTERNAL_ASM void memset32(int *dest, int c, int count)
while (count--)
*dest++ = c;
}
void memset32_uncached(int *dest, int c, int count) { memset32(dest, c, count); }
#endif
#endif

171
Pico/Misc_amips.s Normal file
View file

@ -0,0 +1,171 @@
# vim:filetype=mips
.set noreorder
.set noat
.text
.align 4
.globl memset32 # int *dest, int c, int count
memset32:
ms32_aloop:
andi $t0, $a0, 0x3f
beqz $t0, ms32_bloop_prep
nop
sw $a1, 0($a0)
addiu $a2, -1
beqz $a2, ms32_return
addiu $a0, 4
j ms32_aloop
nop
ms32_bloop_prep:
srl $t0, $a2, 4 # we will do 64 bytes per iteration (cache line)
beqz $t0, ms32_bloop_end
ms32_bloop:
addiu $t0, -1
cache 0x18, ($a0) # create dirty exclusive
sw $a1, 0x00($a0)
sw $a1, 0x04($a0)
sw $a1, 0x08($a0)
sw $a1, 0x0c($a0)
sw $a1, 0x10($a0)
sw $a1, 0x14($a0)
sw $a1, 0x18($a0)
sw $a1, 0x1c($a0)
sw $a1, 0x20($a0)
sw $a1, 0x24($a0)
sw $a1, 0x28($a0)
sw $a1, 0x2c($a0)
sw $a1, 0x30($a0)
sw $a1, 0x34($a0)
sw $a1, 0x38($a0)
sw $a1, 0x3c($a0)
bnez $t0, ms32_bloop
addiu $a0, 0x40
ms32_bloop_end:
andi $a2, $a2, 0x0f
beqz $a2, ms32_return
ms32_cloop:
addiu $a2, -1
sw $a1, 0($a0)
bnez $a2, ms32_cloop
addiu $a0, 4
ms32_return:
jr $ra
nop
.globl memset32_uncached # int *dest, int c, int count
memset32_uncached:
srl $t0, $a2, 3 # we will do 32 bytes per iteration
beqz $t0, ms32u_bloop_end
ms32u_bloop:
addiu $t0, -1
sw $a1, 0x00($a0)
sw $a1, 0x04($a0)
sw $a1, 0x08($a0)
sw $a1, 0x0c($a0)
sw $a1, 0x10($a0)
sw $a1, 0x14($a0)
sw $a1, 0x18($a0)
sw $a1, 0x1c($a0)
bnez $t0, ms32u_bloop
addiu $a0, 0x20
ms32u_bloop_end:
andi $a2, $a2, 0x0f
beqz $a2, ms32u_return
ms32u_cloop:
addiu $a2, -1
sw $a1, 0($a0)
bnez $a2, ms32u_cloop
addiu $a0, 4
ms32u_return:
jr $ra
nop
.globl memcpy32 # int *dest, int *src, int count
memcpy32:
mc32_aloop:
andi $t0, $a0, 0x3f
beqz $t0, mc32_bloop_prep
nop
lw $t1, 0($a1)
addiu $a2, -1
sw $t1, 0($a0)
beqz $a2, mc32_return
addiu $a0, 4
j mc32_aloop
addiu $a1, 4
mc32_bloop_prep:
srl $t0, $a2, 4 # we will do 64 bytes per iteration (cache line)
beqz $t0, mc32_bloop_end
mc32_bloop:
addiu $t0, -1
cache 0x18, ($a0) # create dirty exclusive
lw $t2, 0x00($a1)
lw $t3, 0x04($a1)
lw $t4, 0x08($a1)
lw $t5, 0x0c($a1)
lw $t6, 0x10($a1)
lw $t7, 0x14($a1)
lw $t8, 0x18($a1)
lw $t9, 0x1c($a1)
sw $t2, 0x00($a0)
sw $t3, 0x04($a0)
sw $t4, 0x08($a0)
sw $t5, 0x0c($a0)
sw $t6, 0x10($a0)
sw $t7, 0x14($a0)
sw $t8, 0x18($a0)
sw $t9, 0x1c($a0)
lw $t2, 0x20($a1)
lw $t3, 0x24($a1)
lw $t4, 0x28($a1)
lw $t5, 0x2c($a1)
lw $t6, 0x30($a1)
lw $t7, 0x34($a1)
lw $t8, 0x38($a1)
lw $t9, 0x3c($a1)
sw $t2, 0x20($a0)
sw $t3, 0x24($a0)
sw $t4, 0x28($a0)
sw $t5, 0x2c($a0)
sw $t6, 0x30($a0)
sw $t7, 0x34($a0)
sw $t8, 0x38($a0)
sw $t9, 0x3c($a0)
addiu $a0, 0x40
bnez $t0, mc32_bloop
addiu $a1, 0x40
mc32_bloop_end:
andi $a2, $a2, 0x0f
beqz $a2, mc32_return
mc32_cloop:
lw $t1, 0($a1)
addiu $a2, -1
addiu $a1, 4
sw $t1, 0($a0)
bnez $a2, mc32_cloop
addiu $a0, 4
mc32_return:
jr $ra
nop

View file

@ -297,10 +297,10 @@ static void PicoRunZ80Simple(int line_from, int line_to)
if ((line == 224 || line == line_sample) && PsndOut) getSamples(line);
if (line == 32 && PsndOut) emustatus &= ~1;
if (line >= line_from_r && line < line_to_r)
z80_run(228);
z80_run_nr(228);
}
} else if (line_to_r-line_from_r > 0) {
z80_run(228*(line_to_r-line_from_r));
z80_run_nr(228*(line_to_r-line_from_r));
// samples will be taken by caller
}
}

View file

@ -49,6 +49,9 @@ extern struct Cyclone PicoCpuCM68k, PicoCpuCS68k;
#define SekSetStop(x) { PicoCpuCM68k.state_flags&=~1; if (x) { PicoCpuCM68k.state_flags|=1; PicoCpuCM68k.cycles=0; } }
#define SekSetStopS68k(x) { PicoCpuCS68k.state_flags&=~1; if (x) { PicoCpuCS68k.state_flags|=1; PicoCpuCS68k.cycles=0; } }
#define SekShouldInterrupt (PicoCpuCM68k.irq > (PicoCpuCM68k.srh&7))
#define SekInterrupt(i) PicoCpuCM68k.irq=i
#ifdef EMU_M68K
#define EMU_CORE_DEBUG
#endif
@ -56,7 +59,7 @@ extern struct Cyclone PicoCpuCM68k, PicoCpuCS68k;
#ifdef EMU_F68K
#include "../cpu/fame/fame.h"
M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k;
extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k;
#define SekCyclesLeftNoMCD PicoCpuFM68k.io_cycle_counter
#define SekCyclesLeft \
(((PicoMCD&1) && (PicoOpt & 0x2000)) ? (SekCycleAim-SekCycleCnt) : SekCyclesLeftNoMCD)
@ -77,6 +80,9 @@ M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k;
if (x) { PicoCpuFS68k.execinfo |= FM68K_HALTED; PicoCpuFS68k.io_cycle_counter = 0; } \
}
#define SekShouldInterrupt fm68k_would_interrupt()
#define SekInterrupt(irq) PicoCpuFM68k.interrupts[0]=irq
#ifdef EMU_M68K
#define EMU_CORE_DEBUG
#endif
@ -106,6 +112,14 @@ extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k;
else PicoCpuMS68k.stopped=0; \
}
#define SekShouldInterrupt (CPU_INT_LEVEL > FLAG_INT_MASK)
#define SekInterrupt(irq) {
void *oldcontext = m68ki_cpu_p; \
m68k_set_context(&PicoCpuMM68k); \
m68k_set_irq(irq); \
m68k_set_context(oldcontext); \
}
#endif
#endif
@ -148,6 +162,46 @@ extern int SekCycleAimS68k;
#define SekEndRun(c)
#endif
// ----------------------- Z80 CPU -----------------------
#if defined(_USE_MZ80)
#include "../../cpu/mz80/mz80.h"
#define z80_run(cycles) mz80_run(cycles)
#define z80_run_nr(cycles) mz80_run(cycles)
#define z80_int() mz80int(0)
#define z80_resetCycles() mz80GetElapsedTicks(1)
#elif defined(_USE_DRZ80)
#include "../../cpu/DrZ80/drz80.h"
extern struct DrZ80 drZ80;
#define z80_run(cycles) ((cycles) - DrZ80Run(&drZ80, cycles))
#define z80_run_nr(cycles) DrZ80Run(&drZ80, cycles)
#define z80_int() { \
drZ80.z80irqvector = 0xFF; /* default IRQ vector RST opcode */ \
drZ80.Z80_IRQ = 1; \
}
#define z80_resetCycles()
#elif defined(_USE_CZ80)
#include "../../cpu/cz80/cz80.h"
#define z80_run(cycles) Cz80_Exec(&CZ80, cycles)
#define z80_run_nr(cycles) Cz80_Exec(&CZ80, cycles)
#define z80_int() Cz80_Set_IRQ(&CZ80, 0, HOLD_LINE)
#define z80_resetCycles()
#else
#define z80_run(cycles) (cycles)
#define z80_run_nr(cycles)
#define z80_int()
#define z80_resetCycles()
#endif
// ---------------------------------------------------------
extern int PicoMCD;
@ -358,7 +412,6 @@ PICO_INTERNAL int PicoFrameMCD(void);
// Sek.c
PICO_INTERNAL int SekInit(void);
PICO_INTERNAL int SekReset(void);
PICO_INTERNAL int SekInterrupt(int irq);
PICO_INTERNAL void SekState(int *data);
PICO_INTERNAL void SekSetRealTAS(int use_real);
@ -398,9 +451,6 @@ PICO_INTERNAL int PsndRender(int offset, int length);
PICO_INTERNAL void PsndClear(void);
// z80 functionality wrappers
PICO_INTERNAL void z80_init(void);
PICO_INTERNAL void z80_resetCycles(void);
PICO_INTERNAL void z80_int(void);
PICO_INTERNAL int z80_run(int cycles);
PICO_INTERNAL void z80_pack(unsigned char *data);
PICO_INTERNAL void z80_unpack(unsigned char *data);
PICO_INTERNAL void z80_reset(void);

View file

@ -165,33 +165,6 @@ PICO_INTERNAL int SekReset()
}
PICO_INTERNAL int SekInterrupt(int irq)
{
#ifdef EMU_CORE_DEBUG
{
extern int dbg_irq_level;
dbg_irq_level=irq;
return 0;
}
#endif
#ifdef EMU_C68K
PicoCpuCM68k.irq=irq;
#endif
#ifdef EMU_M68K
{
void *oldcontext = m68ki_cpu_p;
m68k_set_context(&PicoCpuMM68k);
m68k_set_irq(irq); // raise irq (gets lowered after taken or must be done in ack)
m68k_set_context(oldcontext);
}
#endif
#ifdef EMU_F68K
PicoCpuFM68k.interrupts[0]=irq;
#endif
return 0;
}
// data must be word aligned
PICO_INTERNAL void SekState(int *data)
{

View file

@ -164,8 +164,12 @@ static int g_read_offs = 0;
g_read_offs += len;
#define CHECKED_READ2(len2,data) \
if (len2 != len) R_ERROR_RETURN("unexpected len, wanted " #len2); \
CHECKED_READ(len2, data)
if (len2 != len) { \
printf("unexpected len %i, wanted %i (%s)", len, len2, #len2); \
if (len > len2) R_ERROR_RETURN("failed."); \
/* else read anyway and hope for the best.. */ \
} \
CHECKED_READ(len, data)
#define CHECKED_READ_BUFF(buff) CHECKED_READ2(sizeof(buff), &buff);

View file

@ -454,38 +454,62 @@ static u32 PicoReadM68k8(u32 a)
{
u32 d=0;
if ((a&0xe00000)==0xe00000) { d = *(u8 *)(Pico.ram+((a^1)&0xffff)); goto end; } // Ram
a&=0xffffff;
if (a < 0x20000) { d = *(u8 *)(Pico_mcd->bios+(a^1)); goto end; } // bios
// prg RAM
if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
switch (a >> 17)
{
case 0x00>>1: // BIOS: 000000 - 020000
d = *(u8 *)(Pico_mcd->bios+(a^1));
break;
case 0x02>>1: // prg RAM
if ((Pico_mcd->m.busreq&3)!=1) {
u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
d = *(prg_bank+((a^1)&0x1ffff));
goto end;
}
// word RAM
if ((a&0xfc0000)==0x200000) {
break;
case 0x20>>1: // word RAM: 200000 - 220000
wrdprintf("m68k_wram r8: [%06x] @%06x", a, SekPc);
a &= 0x1ffff;
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
int bank = Pico_mcd->s68k_regs[3]&1;
d = Pico_mcd->word_ram1M[bank][a^1];
} else {
// allow access in any mode, like Gens does
d = Pico_mcd->word_ram2M[a^1];
}
wrdprintf("ret = %02x", (u8)d);
break;
case 0x22>>1: // word RAM: 220000 - 240000
wrdprintf("m68k_wram r8: [%06x] @%06x", a, SekPc);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
int bank = Pico_mcd->s68k_regs[3]&1;
if (a >= 0x220000)
a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged
else a &= 0x1ffff;
d = Pico_mcd->word_ram1M[bank][a^1];
} else {
// allow access in any mode, like Gens does
d = Pico_mcd->word_ram2M[(a^1)&0x3ffff];
}
wrdprintf("ret = %02x", (u8)d);
goto end;
break;
case 0xc0>>1: case 0xc2>>1: case 0xc4>>1: case 0xc6>>1:
case 0xc8>>1: case 0xca>>1: case 0xcc>>1: case 0xce>>1:
case 0xd0>>1: case 0xd2>>1: case 0xd4>>1: case 0xd6>>1:
case 0xd8>>1: case 0xda>>1: case 0xdc>>1: case 0xde>>1:
// VDP
if ((a&0xe700e0)==0xc00000) {
d=PicoVideoRead(a);
if ((a&1)==0) d>>=8;
}
if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram
break;
case 0xe0>>1: case 0xe2>>1: case 0xe4>>1: case 0xe6>>1:
case 0xe8>>1: case 0xea>>1: case 0xec>>1: case 0xee>>1:
case 0xf0>>1: case 0xf2>>1: case 0xf4>>1: case 0xf6>>1:
case 0xf8>>1: case 0xfa>>1: case 0xfc>>1: case 0xfe>>1:
// RAM:
d = *(u8 *)(Pico.ram+((a^1)&0xffff));
break;
default:
if ((a&0xff4000)==0xa00000) { d=z80Read8(a); break; } // Z80 Ram
if ((a&0xffffc0)==0xa12000)
rdprintf("m68k_regs r8: [%02x] @%06x", a&0x3f, SekPc);
@ -493,8 +517,9 @@ static u32 PicoReadM68k8(u32 a)
if ((a&0xffffc0)==0xa12000)
rdprintf("ret = %02x", (u8)d);
break;
}
end:
#ifdef __debug_io
dprintf("r8 : %06x, %02x @%06x", a&0xffffff, (u8)d, SekPc);
@ -517,38 +542,61 @@ static u32 PicoReadM68k16(u32 a)
{
u32 d=0;
if ((a&0xe00000)==0xe00000) { d=*(u16 *)(Pico.ram+(a&0xfffe)); goto end; } // Ram
a&=0xfffffe;
if (a < 0x20000) { d = *(u16 *)(Pico_mcd->bios+a); goto end; } // bios
// prg RAM
if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
switch (a >> 17)
{
case 0x00>>1: // BIOS: 000000 - 020000
d = *(u16 *)(Pico_mcd->bios+a);
break;
case 0x02>>1: // prg RAM
if ((Pico_mcd->m.busreq&3)!=1) {
u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
wrdprintf("m68k_prgram r16: [%i,%06x] @%06x", Pico_mcd->s68k_regs[3]>>6, a, SekPc);
d = *(u16 *)(prg_bank+(a&0x1fffe));
wrdprintf("ret = %04x", d);
goto end;
}
// word RAM
if ((a&0xfc0000)==0x200000) {
break;
case 0x20>>1: // word RAM: 200000 - 220000
wrdprintf("m68k_wram r16: [%06x] @%06x", a, SekPc);
a &= 0x1fffe;
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
int bank = Pico_mcd->s68k_regs[3]&1;
d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);
} else {
// allow access in any mode, like Gens does
d = *(u16 *)(Pico_mcd->word_ram2M+a);
}
wrdprintf("ret = %04x", d);
break;
case 0x22>>1: // word RAM: 220000 - 240000
wrdprintf("m68k_wram r16: [%06x] @%06x", a, SekPc);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
int bank = Pico_mcd->s68k_regs[3]&1;
if (a >= 0x220000)
a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged
else a &= 0x1fffe;
d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);
} else {
// allow access in any mode, like Gens does
d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
}
wrdprintf("ret = %04x", d);
goto end;
}
break;
case 0xc0>>1: case 0xc2>>1: case 0xc4>>1: case 0xc6>>1:
case 0xc8>>1: case 0xca>>1: case 0xcc>>1: case 0xce>>1:
case 0xd0>>1: case 0xd2>>1: case 0xd4>>1: case 0xd6>>1:
case 0xd8>>1: case 0xda>>1: case 0xdc>>1: case 0xde>>1:
// VDP
if ((a&0xe700e0)==0xc00000)
d=PicoVideoRead(a);
break;
case 0xe0>>1: case 0xe2>>1: case 0xe4>>1: case 0xe6>>1:
case 0xe8>>1: case 0xea>>1: case 0xec>>1: case 0xee>>1:
case 0xf0>>1: case 0xf2>>1: case 0xf4>>1: case 0xf6>>1:
case 0xf8>>1: case 0xfa>>1: case 0xfc>>1: case 0xfe>>1:
// RAM:
d=*(u16 *)(Pico.ram+(a&0xfffe));
break;
default:
if ((a&0xffffc0)==0xa12000)
rdprintf("m68k_regs r16: [%02x] @%06x", a&0x3f, SekPc);
@ -556,8 +604,9 @@ static u32 PicoReadM68k16(u32 a)
if ((a&0xffffc0)==0xa12000)
rdprintf("ret = %04x", d);
break;
}
end:
#ifdef __debug_io
dprintf("r16: %06x, %04x @%06x", a&0xffffff, d, SekPc);
@ -580,43 +629,70 @@ static u32 PicoReadM68k32(u32 a)
{
u32 d=0;
if ((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); d = (pm[0]<<16)|pm[1]; goto end; } // Ram
a&=0xfffffe;
if (a < 0x20000) { u16 *pm=(u16 *)(Pico_mcd->bios+a); d = (pm[0]<<16)|pm[1]; goto end; } // bios
// prg RAM
if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
switch (a >> 17)
{
case 0x00>>1: { // BIOS: 000000 - 020000
u16 *pm=(u16 *)(Pico_mcd->bios+a);
d = (pm[0]<<16)|pm[1];
break;
}
case 0x02>>1: // prg RAM
if ((Pico_mcd->m.busreq&3)!=1) {
u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));
d = (pm[0]<<16)|pm[1];
goto end;
}
// word RAM
if ((a&0xfc0000)==0x200000) {
break;
case 0x20>>1: // word RAM: 200000 - 220000
wrdprintf("m68k_wram r32: [%06x] @%06x", a, SekPc);
a&=0x1fffe;
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
int bank = Pico_mcd->s68k_regs[3]&1;
if (a >= 0x220000) { // cell arranged
u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+a);
d = (pm[0]<<16)|pm[1];
} else {
// allow access in any mode, like Gens does
u16 *pm=(u16 *)(Pico_mcd->word_ram2M+a);
d = (pm[0]<<16)|pm[1];
}
wrdprintf("ret = %08x", d);
break;
case 0x22>>1: // word RAM: 220000 - 240000
wrdprintf("m68k_wram r32: [%06x] @%06x", a, SekPc);
if (Pico_mcd->s68k_regs[3]&4) { // 1M mode, cell arranged?
u32 a1, a2;
int bank = Pico_mcd->s68k_regs[3]&1;
a1 = (a&2) | (cell_map(a >> 2) << 2);
if (a&2) a2 = cell_map((a+2) >> 2) << 2;
else a2 = a1 + 2;
d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a1) << 16;
d |= *(u16 *)(Pico_mcd->word_ram1M[bank]+a2);
} else {
u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe)); d = (pm[0]<<16)|pm[1];
}
} else {
// allow access in any mode, like Gens does
u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];
u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
d = (pm[0]<<16)|pm[1];
}
wrdprintf("ret = %08x", d);
goto end;
break;
case 0xc0>>1: case 0xc2>>1: case 0xc4>>1: case 0xc6>>1:
case 0xc8>>1: case 0xca>>1: case 0xcc>>1: case 0xce>>1:
case 0xd0>>1: case 0xd2>>1: case 0xd4>>1: case 0xd6>>1:
case 0xd8>>1: case 0xda>>1: case 0xdc>>1: case 0xde>>1:
// VDP
d = (PicoVideoRead(a)<<16)|PicoVideoRead(a+2);
break;
case 0xe0>>1: case 0xe2>>1: case 0xe4>>1: case 0xe6>>1:
case 0xe8>>1: case 0xea>>1: case 0xec>>1: case 0xee>>1:
case 0xf0>>1: case 0xf2>>1: case 0xf4>>1: case 0xf6>>1:
case 0xf8>>1: case 0xfa>>1: case 0xfc>>1: case 0xfe>>1: {
// RAM:
u16 *pm=(u16 *)(Pico.ram+(a&0xfffe));
d = (pm[0]<<16)|pm[1];
break;
}
default:
if ((a&0xffffc0)==0xa12000)
rdprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);
@ -624,8 +700,10 @@ static u32 PicoReadM68k32(u32 a)
if ((a&0xffffc0)==0xa12000)
rdprintf("ret = %08x", d);
break;
}
end:
#ifdef __debug_io
dprintf("r32: %06x, %08x @%06x", a&0xffffff, d, SekPc);
#endif
@ -659,8 +737,6 @@ static void PicoWriteM68k8(u32 a,u8 d)
return;
}
a&=0xffffff;
// prg RAM
if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
@ -668,6 +744,8 @@ static void PicoWriteM68k8(u32 a,u8 d)
return;
}
a&=0xffffff;
// word RAM
if ((a&0xfc0000)==0x200000) {
wrdprintf("m68k_wram w8: [%06x] %02x @%06x", a, d, SekPc);
@ -712,8 +790,6 @@ static void PicoWriteM68k16(u32 a,u16 d)
return;
}
a&=0xfffffe;
// prg RAM
if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
@ -722,6 +798,8 @@ static void PicoWriteM68k16(u32 a,u16 d)
return;
}
a&=0xfffffe;
// word RAM
if ((a&0xfc0000)==0x200000) {
wrdprintf("m68k_wram w16: [%06x] %04x @%06x", a, d, SekPc);
@ -756,6 +834,12 @@ static void PicoWriteM68k16(u32 a,u16 d)
return;
}
// VDP
if ((a&0xe700e0)==0xc00000) {
PicoVideoWrite(a,(u16)d);
return;
}
OtherWrite16(a,d);
}
#endif
@ -781,8 +865,6 @@ static void PicoWriteM68k32(u32 a,u32 d)
return;
}
a&=0xfffffe;
// prg RAM
if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {
u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];
@ -791,6 +873,8 @@ static void PicoWriteM68k32(u32 a,u32 d)
return;
}
a&=0xfffffe;
// word RAM
if ((a&0xfc0000)==0x200000) {
if (d != 0) // don't log clears
@ -821,6 +905,14 @@ static void PicoWriteM68k32(u32 a,u32 d)
if ((a&0x3e) == 0xe) dprintf("m68k FIXME: w32 [%02x]", a&0x3f);
}
// VDP
if ((a&0xe700e0)==0xc00000)
{
PicoVideoWrite(a, (u16)(d>>16));
PicoVideoWrite(a+2,(u16)d);
return;
}
OtherWrite16(a, (u16)(d>>16));
OtherWrite16(a+2,(u16)d);
}

View file

@ -79,6 +79,7 @@ PICO_INTERNAL int PicoResetMCD(int hard)
SRam.data = NULL;
if (PicoOpt&0x8000)
SRam.data = calloc(1, 0x12000);
SRam.start = SRam.end = 0; // unused
return 0;
}

View file

@ -80,6 +80,7 @@ PICO_INTERNAL void PicoCDBufferRead(void *dest, int lba)
dprintf("CD buffer seek %i -> %i\n", prev_lba, lba);
pm_seek(Pico_mcd->TOC.Tracks[0].F, where_seek, SEEK_SET);
}
else if (prev_lba == 0x80000000) printf("wtf?\n");
dprintf("CD buffer miss %i -> %i\n", prev_lba, lba);
@ -89,6 +90,7 @@ PICO_INTERNAL void PicoCDBufferRead(void *dest, int lba)
dprintf("CD buffer move=%i, read_len=%i", PicoCDBuffers - read_len, read_len);
memmove(cd_buffer + read_len*2048, cd_buffer, (PicoCDBuffers - read_len)*2048);
moved = 1;
if (prev_lba == 0x80000000) printf("wtf?\n");
}
else
{
@ -104,17 +106,20 @@ PICO_INTERNAL void PicoCDBufferRead(void *dest, int lba)
{
int i = 0;
#if REDUCE_IO_CALLS
int bufs = (read_len*2048+304) / (2048+304);
int bufs = (read_len*2048) / (2048+304);
pm_read(cd_buffer, bufs*(2048+304), Pico_mcd->TOC.Tracks[0].F);
for (i = 1; i < bufs; i++)
// should really use memmove here, but my memcpy32 implementation is also suitable here
memcpy32((int *)(cd_buffer + i*2048), (int *)(cd_buffer + i*(2048+304)), 2048/4);
#endif
for (; i < read_len; i++)
for (; i < read_len - 1; i++)
{
pm_read(cd_buffer + i*2048, 2048 + 304, Pico_mcd->TOC.Tracks[0].F);
// pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR); // seeking is slower, in PSP case even more
}
// further data might be moved, do not overwrite
pm_read(cd_buffer + i*2048, 2048, Pico_mcd->TOC.Tracks[0].F);
pm_seek(Pico_mcd->TOC.Tracks[0].F, 304, SEEK_CUR);
}
else
{

View file

@ -1,7 +1,7 @@
// This is part of Pico Library
// (c) Copyright 2004 Dave, All rights reserved.
// (c) Copyright 2006 notaz, All rights reserved.
// (c) Copyright 2006,2007 notaz, All rights reserved.
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
@ -11,14 +11,6 @@
#include "ym2612.h"
#include "sn76496.h"
#if defined(_USE_MZ80)
#include "../../cpu/mz80/mz80.h"
#elif defined(_USE_DRZ80)
#include "../../cpu/DrZ80/drz80.h"
#elif defined(_USE_CZ80)
#include "../../cpu/cz80/cz80.h"
#endif
#include "../PicoInt.h"
#include "../cd/pcm.h"
#include "mix.h"
@ -36,11 +28,6 @@ int PsndLen_exc_add=0; // this is for non-integer sample counts per line, eg. 22
int PsndLen_exc_cnt=0;
short *PsndOut=NULL; // PCM data buffer
// from ym2612.c
extern int *ym2612_dacen;
extern INT32 *ym2612_dacout;
void YM2612TimerHandler(int c,int cnt);
// sn76496
extern int *sn76496_regs;
@ -306,9 +293,16 @@ static struct z80PortWrite mz80_io_write[]={
{(UINT16) -1,(UINT16) -1,NULL}
};
int mz80_run(int cycles)
{
int ticks_pre = mz80GetElapsedTicks(0);
mz80exec(cycles);
return mz80GetElapsedTicks(0) - ticks_pre;
}
#elif defined(_USE_DRZ80)
static struct DrZ80 drZ80;
struct DrZ80 drZ80;
static unsigned int DrZ80_rebasePC(unsigned short a)
{
@ -379,7 +373,7 @@ PICO_INTERNAL void z80_init(void)
Cz80_Init(&CZ80);
Cz80_Set_Fetch(&CZ80, 0x0000, 0x1fff, (UINT32)Pico.zram); // main RAM
Cz80_Set_Fetch(&CZ80, 0x2000, 0x3fff, (UINT32)Pico.zram - 0x2000); // mirror
Cz80_Set_ReadB(&CZ80, (UINT8 (*)(UINT32 address))z80_read);
Cz80_Set_ReadB(&CZ80, (UINT8 (*)(UINT32 address))z80_read); // unused (hacked in)
Cz80_Set_WriteB(&CZ80, z80_write);
Cz80_Set_INPort(&CZ80, z80_in);
Cz80_Set_OUTPort(&CZ80, z80_out);
@ -405,40 +399,6 @@ PICO_INTERNAL void z80_reset(void)
Pico.m.z80_fakeval = 0; // for faking when Z80 is disabled
}
PICO_INTERNAL void z80_resetCycles(void)
{
#if defined(_USE_MZ80)
mz80GetElapsedTicks(1);
#endif
}
PICO_INTERNAL void z80_int(void)
{
#if defined(_USE_MZ80)
mz80int(0);
#elif defined(_USE_DRZ80)
drZ80.z80irqvector = 0xFF; // default IRQ vector RST opcode
drZ80.Z80_IRQ = 1;
#elif defined(_USE_CZ80)
Cz80_Set_IRQ(&CZ80, 0, HOLD_LINE);
#endif
}
// returns number of cycles actually executed
PICO_INTERNAL int z80_run(int cycles)
{
#if defined(_USE_MZ80)
int ticks_pre = mz80GetElapsedTicks(0);
mz80exec(cycles);
return mz80GetElapsedTicks(0) - ticks_pre;
#elif defined(_USE_DRZ80)
return cycles - DrZ80Run(&drZ80, cycles);
#elif defined(_USE_CZ80)
return Cz80_Exec(&CZ80, cycles);
#else
return cycles;
#endif
}
PICO_INTERNAL void z80_pack(unsigned char *data)
{

View file

@ -553,20 +553,21 @@ INLINE void set_timers( int v )
}
INLINE void FM_KEYON(FM_CH *CH , int s )
INLINE void FM_KEYON(int c , int s )
{
FM_SLOT *SLOT = &CH->SLOT[s];
FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];
if( !SLOT->key )
{
SLOT->key = 1;
SLOT->phase = 0; /* restart Phase Generator */
SLOT->state = EG_ATT; /* phase -> Attack */
ym2612.slot_mask |= (1<<s) << (c*4);
}
}
INLINE void FM_KEYOFF(FM_CH *CH , int s )
INLINE void FM_KEYOFF(int c , int s )
{
FM_SLOT *SLOT = &CH->SLOT[s];
FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s];
if( SLOT->key )
{
SLOT->key = 0;
@ -844,6 +845,9 @@ typedef struct
UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16]
UINT32 algo; /* 50: algo[3], was_update */
INT32 op1_out;
#ifdef _MIPS_ARCH_ALLEGREX
UINT32 pad1[3+8];
#endif
} chan_rend_context;
@ -905,16 +909,6 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
switch( ct->CH->ALGO )
{
#if 0
case 0: smp = upd_algo0(ct); break;
case 1: smp = upd_algo1(ct); break;
case 2: smp = upd_algo2(ct); break;
case 3: smp = upd_algo3(ct); break;
case 4: smp = upd_algo4(ct); break;
case 5: smp = upd_algo5(ct); break;
case 6: smp = upd_algo6(ct); break;
case 7: smp = upd_algo7(ct); break;
#else
case 0:
{
/* M1---C1---MEM---M2---C2---OUT */
@ -1064,7 +1058,6 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
}
break;
}
#endif
}
/* done calculating channel sample */
@ -1092,55 +1085,54 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length);
#endif
static chan_rend_context __attribute__((aligned(64))) crct;
static int chan_render(int *buffer, int length, FM_CH *CH, UINT32 flags) // flags: stereo, lastchan, disabled, ?, pan_r, pan_l
static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l
{
chan_rend_context ct;
crct.CH = &ym2612.CH[c];
crct.mem = crct.CH->mem_value; /* one sample delay memory */
crct.lfo_cnt = ym2612.OPN.lfo_cnt;
crct.lfo_inc = ym2612.OPN.lfo_inc;
ct.CH = CH;
ct.mem = CH->mem_value; /* one sample delay memory */
ct.lfo_cnt = ym2612.OPN.lfo_cnt;
ct.lfo_inc = ym2612.OPN.lfo_inc;
flags &= 0x35;
flags &= 0x37;
if (ct.lfo_inc) {
if (crct.lfo_inc) {
flags |= 8;
flags |= g_lfo_ampm << 16;
flags |= CH->AMmasks << 8;
if (CH->ams == 8) // no ams
flags |= crct.CH->AMmasks << 8;
if (crct.CH->ams == 8) // no ams
flags &= ~0xf00;
else flags |= (CH->ams&3)<<6;
else flags |= (crct.CH->ams&3)<<6;
}
flags |= (CH->FB&0xf)<<12; /* feedback shift */
ct.pack = flags;
flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */
crct.pack = flags;
ct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */
ct.eg_timer = ym2612.OPN.eg_timer;
ct.eg_timer_add = ym2612.OPN.eg_timer_add;
crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */
crct.eg_timer = ym2612.OPN.eg_timer;
crct.eg_timer_add = ym2612.OPN.eg_timer_add;
/* precalculate phase modulation incr */
ct.phase1 = CH->SLOT[SLOT1].phase;
ct.phase2 = CH->SLOT[SLOT2].phase;
ct.phase3 = CH->SLOT[SLOT3].phase;
ct.phase4 = CH->SLOT[SLOT4].phase;
crct.phase1 = crct.CH->SLOT[SLOT1].phase;
crct.phase2 = crct.CH->SLOT[SLOT2].phase;
crct.phase3 = crct.CH->SLOT[SLOT3].phase;
crct.phase4 = crct.CH->SLOT[SLOT4].phase;
/* current output from EG circuit (without AM from LFO) */
ct.vol_out1 = CH->SLOT[SLOT1].tl + ((UINT32)CH->SLOT[SLOT1].volume);
ct.vol_out2 = CH->SLOT[SLOT2].tl + ((UINT32)CH->SLOT[SLOT2].volume);
ct.vol_out3 = CH->SLOT[SLOT3].tl + ((UINT32)CH->SLOT[SLOT3].volume);
ct.vol_out4 = CH->SLOT[SLOT4].tl + ((UINT32)CH->SLOT[SLOT4].volume);
crct.vol_out1 = crct.CH->SLOT[SLOT1].tl + ((UINT32)crct.CH->SLOT[SLOT1].volume);
crct.vol_out2 = crct.CH->SLOT[SLOT2].tl + ((UINT32)crct.CH->SLOT[SLOT2].volume);
crct.vol_out3 = crct.CH->SLOT[SLOT3].tl + ((UINT32)crct.CH->SLOT[SLOT3].volume);
crct.vol_out4 = crct.CH->SLOT[SLOT4].tl + ((UINT32)crct.CH->SLOT[SLOT4].volume);
ct.op1_out = CH->op1_out;
ct.algo = CH->ALGO & 7;
crct.op1_out = crct.CH->op1_out;
crct.algo = crct.CH->ALGO & 7;
if(CH->pms)
if(crct.CH->pms)
{
/* add support for 3 slot mode */
UINT32 block_fnum = CH->block_fnum;
UINT32 block_fnum = crct.CH->block_fnum;
UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;
INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + ((ct.pack>>16)&0xff) ];
INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ];
if (lfo_fn_table_index_offset) /* LFO phase modulation active */
{
@ -1158,45 +1150,51 @@ static int chan_render(int *buffer, int length, FM_CH *CH, UINT32 flags) // flag
/* phase increment counter */
fc = fn_table[fn]>>(7-blk);
ct.incr1 = ((fc+CH->SLOT[SLOT1].DT[kc])*CH->SLOT[SLOT1].mul) >> 1;
ct.incr2 = ((fc+CH->SLOT[SLOT2].DT[kc])*CH->SLOT[SLOT2].mul) >> 1;
ct.incr3 = ((fc+CH->SLOT[SLOT3].DT[kc])*CH->SLOT[SLOT3].mul) >> 1;
ct.incr4 = ((fc+CH->SLOT[SLOT4].DT[kc])*CH->SLOT[SLOT4].mul) >> 1;
crct.incr1 = ((fc+crct.CH->SLOT[SLOT1].DT[kc])*crct.CH->SLOT[SLOT1].mul) >> 1;
crct.incr2 = ((fc+crct.CH->SLOT[SLOT2].DT[kc])*crct.CH->SLOT[SLOT2].mul) >> 1;
crct.incr3 = ((fc+crct.CH->SLOT[SLOT3].DT[kc])*crct.CH->SLOT[SLOT3].mul) >> 1;
crct.incr4 = ((fc+crct.CH->SLOT[SLOT4].DT[kc])*crct.CH->SLOT[SLOT4].mul) >> 1;
}
else /* LFO phase modulation = zero */
{
ct.incr1 = CH->SLOT[SLOT1].Incr;
ct.incr2 = CH->SLOT[SLOT2].Incr;
ct.incr3 = CH->SLOT[SLOT3].Incr;
ct.incr4 = CH->SLOT[SLOT4].Incr;
crct.incr1 = crct.CH->SLOT[SLOT1].Incr;
crct.incr2 = crct.CH->SLOT[SLOT2].Incr;
crct.incr3 = crct.CH->SLOT[SLOT3].Incr;
crct.incr4 = crct.CH->SLOT[SLOT4].Incr;
}
}
else /* no LFO phase modulation */
{
ct.incr1 = CH->SLOT[SLOT1].Incr;
ct.incr2 = CH->SLOT[SLOT2].Incr;
ct.incr3 = CH->SLOT[SLOT3].Incr;
ct.incr4 = CH->SLOT[SLOT4].Incr;
crct.incr1 = crct.CH->SLOT[SLOT1].Incr;
crct.incr2 = crct.CH->SLOT[SLOT2].Incr;
crct.incr3 = crct.CH->SLOT[SLOT3].Incr;
crct.incr4 = crct.CH->SLOT[SLOT4].Incr;
}
chan_render_loop(&ct, buffer, length);
chan_render_loop(&crct, buffer, length);
// write back persistent stuff:
if (flags & 2) { /* last channel */
ym2612.OPN.eg_cnt = ct.eg_cnt;
ym2612.OPN.eg_timer = ct.eg_timer;
g_lfo_ampm = ct.pack >> 16;
ym2612.OPN.lfo_cnt = ct.lfo_cnt;
crct.CH->op1_out = crct.op1_out;
crct.CH->mem_value = crct.mem;
if (crct.CH->SLOT[SLOT1].state | crct.CH->SLOT[SLOT2].state | crct.CH->SLOT[SLOT3].state | crct.CH->SLOT[SLOT4].state)
{
crct.CH->SLOT[SLOT1].phase = crct.phase1;
crct.CH->SLOT[SLOT2].phase = crct.phase2;
crct.CH->SLOT[SLOT3].phase = crct.phase3;
crct.CH->SLOT[SLOT4].phase = crct.phase4;
}
else
ym2612.slot_mask &= ~(0xf << (c*4));
// if this the last call, write back persistent stuff:
if ((ym2612.slot_mask >> ((c+1)*4)) == 0)
{
ym2612.OPN.eg_cnt = crct.eg_cnt;
ym2612.OPN.eg_timer = crct.eg_timer;
g_lfo_ampm = crct.pack >> 16;
ym2612.OPN.lfo_cnt = crct.lfo_cnt;
}
CH->op1_out = ct.op1_out;
CH->SLOT[SLOT1].phase = ct.phase1;
CH->SLOT[SLOT2].phase = ct.phase2;
CH->SLOT[SLOT3].phase = ct.phase3;
CH->SLOT[SLOT4].phase = ct.phase4;
CH->mem_value = ct.mem;
return (ct.algo & 8) >> 3; // had output
return (crct.algo & 8) >> 3; // had output
}
/* update phase increment and envelope generator */
@ -1274,7 +1272,7 @@ static void init_timetables(const UINT8 *dttable)
}
static void reset_channels(FM_CH *CH, int num)
static void reset_channels(FM_CH *CH)
{
int c,s;
@ -1284,7 +1282,7 @@ static void reset_channels(FM_CH *CH, int num)
ym2612.OPN.ST.TB = 0;
ym2612.OPN.ST.TBC = 0;
for( c = 0 ; c < num ; c++ )
for( c = 0 ; c < 6 ; c++ )
{
CH[c].fc = 0;
for(s = 0 ; s < 4 ; s++ )
@ -1293,6 +1291,7 @@ static void reset_channels(FM_CH *CH, int num)
CH[c].SLOT[s].volume = MAX_ATT_INDEX;
}
}
ym2612.slot_mask = 0;
}
/* initialize generic tables */
@ -1401,6 +1400,7 @@ static void init_tables(void)
/* CSM Key Controll */
#if 0
INLINE void CSMKeyControll(FM_CH *CH)
{
/* this is wrong, atm */
@ -1411,6 +1411,7 @@ INLINE void CSMKeyControll(FM_CH *CH)
FM_KEYON(CH,SLOT3);
FM_KEYON(CH,SLOT4);
}
#endif
/* prescaler set (and make time tables) */
@ -1585,6 +1586,7 @@ static int OPNWriteReg(int r, int v)
int *ym2612_dacen;
INT32 *ym2612_dacout;
FM_ST *ym2612_st;
/* Generate samples for YM2612 */
@ -1596,6 +1598,24 @@ int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)
// if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash
if (is_buf_empty) memset32(buffer, 0, length<<stereo);
/*
{
int c, s;
ppp();
for (c = 0; c < 6; c++) {
int slr = 0, slm;
printf("%i: ", c);
for (s = 0; s < 4; s++) {
if (ym2612.CH[c].SLOT[s].state != EG_OFF) slr = 1;
printf(" %i", ym2612.CH[c].SLOT[s].state != EG_OFF);
}
slm = (ym2612.slot_mask&(0xf<<(c*4))) ? 1 : 0;
printf(" | %i", slm);
printf(" | %i\n", ym2612.CH[c].SLOT[SLOT1].Incr==-1);
if (slr != slm) exit(1);
}
}
*/
/* refresh PG and EG */
refresh_fc_eg_chan( &ym2612.CH[0] );
refresh_fc_eg_chan( &ym2612.CH[1] );
@ -1618,13 +1638,13 @@ int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)
if (stereo) stereo = 1;
/* mix to 32bit dest */
// flags: stereo, lastchan, disabled, ?, pan_r, pan_l
active_chs |= chan_render(buffer, length, &ym2612.CH[0], stereo|((pan&0x003)<<4)) << 0;
active_chs |= chan_render(buffer, length, &ym2612.CH[1], stereo|((pan&0x00c)<<2)) << 1;
active_chs |= chan_render(buffer, length, &ym2612.CH[2], stereo|((pan&0x030) )) << 2;
active_chs |= chan_render(buffer, length, &ym2612.CH[3], stereo|((pan&0x0c0)>>2)) << 3;
active_chs |= chan_render(buffer, length, &ym2612.CH[4], stereo|((pan&0x300)>>4)) << 4;
active_chs |= chan_render(buffer, length, &ym2612.CH[5], stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)|2) << 5;
// flags: stereo, ?, disabled, ?, pan_r, pan_l
if (ym2612.slot_mask & 0x00000f) active_chs |= chan_render(buffer, length, 0, stereo|((pan&0x003)<<4)) << 0;
if (ym2612.slot_mask & 0x0000f0) active_chs |= chan_render(buffer, length, 1, stereo|((pan&0x00c)<<2)) << 1;
if (ym2612.slot_mask & 0x000f00) active_chs |= chan_render(buffer, length, 2, stereo|((pan&0x030) )) << 2;
if (ym2612.slot_mask & 0x00f000) active_chs |= chan_render(buffer, length, 3, stereo|((pan&0x0c0)>>2)) << 3;
if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, stereo|((pan&0x300)>>4)) << 4;
if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)) << 5;
return active_chs; // 1 if buffer updated
}
@ -1636,6 +1656,7 @@ void YM2612Init_(int clock, int rate)
// notaz
ym2612_dacen = &ym2612.dacen;
ym2612_dacout = &ym2612.dacout;
ym2612_st = &ym2612.OPN.ST;
memset(&ym2612, 0, sizeof(ym2612));
init_tables();
@ -1663,7 +1684,7 @@ void YM2612ResetChip_(void)
ym2612.OPN.eg_cnt = 0;
ym2612.OPN.ST.status = 0;
reset_channels( &ym2612.CH[0] , 6 );
reset_channels( &ym2612.CH[0] );
for(i = 0xb6 ; i >= 0xb4 ; i-- )
{
OPNWriteReg(i ,0xc0);
@ -1763,16 +1784,14 @@ int YM2612Write_(unsigned int a, unsigned int v)
case 0x28: /* key on / off */
{
UINT8 c;
FM_CH *CH;
c = v & 0x03;
if( c == 3 ) { ret=0; break; }
if( v&0x04 ) c+=3;
CH = &ym2612.CH[c];
if(v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
if(v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
if(v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
if(v&0x80) FM_KEYON(CH,SLOT4); else FM_KEYOFF(CH,SLOT4);
if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1);
if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2);
if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3);
if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);
break;
}
case 0x2a: /* DAC data (YM2612) */
@ -1823,12 +1842,12 @@ int YM2612Write_(unsigned int a, unsigned int v)
return ret;
}
#if 0
UINT8 YM2612Read_(void)
{
return ym2612.OPN.ST.status;
}
int YM2612PicoTick_(int n)
{
int ret = 0;
@ -1852,14 +1871,14 @@ int YM2612PicoTick_(int n)
return ret;
}
#endif
void YM2612PicoStateLoad_(void)
{
#ifndef EXTERNAL_YM2612
int i, real_A1 = ym2612.addr_A1;
reset_channels( &ym2612.CH[0], 6 );
reset_channels( &ym2612.CH[0] );
// feed all the registers and update internal state
for(i = 0; i < 0x100; i++) {
@ -1874,11 +1893,10 @@ void YM2612PicoStateLoad_(void)
ym2612.addr_A1 = real_A1;
#else
reset_channels( &ym2612.CH[0], 6 );
reset_channels( &ym2612.CH[0] );
#endif
}
#ifndef EXTERNAL_YM2612
void *YM2612GetRegs(void)
{

View file

@ -76,15 +76,16 @@ typedef struct
{
int clock; /* master clock (Hz) */
int rate; /* sampling rate (Hz) */
double freqbase; /* frequency base */
UINT8 address; /* address register */
UINT8 status; /* status flag */
double freqbase; /* 08 frequency base */
UINT8 address; /* 10 address register */
UINT8 status; /* 11 status flag */
UINT8 mode; /* mode CSM / 3SLOT */
UINT8 fn_h; /* freq latch */
int TA; /* timer a */
int TAC; /* timer a maxval */
int TAT; /* timer a ticker */
UINT8 TB; /* timer b */
UINT8 pad[3];
int TBC; /* timer b maxval */
int TBT; /* timer b ticker */
/* local time tables */
@ -135,9 +136,32 @@ typedef struct
INT32 dacout;
FM_OPN OPN; /* OPN state */
UINT32 slot_mask; /* active slot mask (performance hack) */
} YM2612;
#endif
extern int *ym2612_dacen;
extern INT32 *ym2612_dacout;
extern FM_ST *ym2612_st;
#define YM2612Read() ym2612_st->status
#define YM2612PicoTick(n) \
{ \
/* timer A */ \
if(ym2612_st->mode & 0x01 && (ym2612_st->TAT+=64*n) >= ym2612_st->TAC) { \
ym2612_st->TAT -= ym2612_st->TAC; \
if(ym2612_st->mode & 0x04) ym2612_st->status |= 1; \
} \
\
/* timer B */ \
if(ym2612_st->mode & 0x02 && (ym2612_st->TBT+=64*n) >= ym2612_st->TBC) { \
ym2612_st->TBT -= ym2612_st->TBC; \
if(ym2612_st->mode & 0x08) ym2612_st->status |= 2; \
} \
}
void YM2612Init_(int baseclock, int rate);
@ -157,8 +181,6 @@ void *YM2612GetRegs(void);
#define YM2612ResetChip YM2612ResetChip_
#define YM2612UpdateOne YM2612UpdateOne_
#define YM2612Write YM2612Write_
#define YM2612Read YM2612Read_
#define YM2612PicoTick YM2612PicoTick_
#define YM2612PicoStateLoad YM2612PicoStateLoad_
#else
/* GP2X specific */
@ -177,10 +199,6 @@ extern int PicoOpt;
YM2612UpdateOne_(buffer, length, stereo, is_buf_empty);
#define YM2612Write(a,v) \
(PicoOpt&0x200) ? YM2612Write_940(a, v) : YM2612Write_(a, v)
#define YM2612Read() \
(PicoOpt&0x200) ? YM2612Read_940() : YM2612Read_()
#define YM2612PicoTick(n) \
(PicoOpt&0x200) ? YM2612PicoTick_940(n) : YM2612PicoTick_(n)
#define YM2612PicoStateLoad() { \
if (PicoOpt&0x200) YM2612PicoStateLoad_940(); \
else YM2612PicoStateLoad_(); \

View file

@ -21,14 +21,10 @@
.endif
.if DRZ80_FOR_PICODRIVE
.include "port_config.s"
.extern YM2612Read_
.if EXTERNAL_YM2612
.extern YM2612Read_940
.endif
.extern PicoRead8
.extern Pico
.extern z80_write
.extern ym2612_st
.endif
DrZ80Ver: .long 0x0001
@ -111,37 +107,18 @@ DrZ80Ver: .long 0x0001
.if DRZ80_FOR_PICODRIVE
.macro YM2612Read_and_ret8
stmfd sp!,{r3,r12,lr}
.if EXTERNAL_YM2612
ldr r1,=PicoOpt
ldr r1,[r1]
tst r1,#0x200
ldrne r2, =YM2612Read_940
ldreq r2, =YM2612Read_
mov lr,pc
bx r2
.else
bl YM2612Read_
.endif
ldmfd sp!,{r3,r12,pc}
ldr r0, =ym2612_st
ldr r0, [r0]
ldrb r0, [r0, #0x11] ;@ ym2612_st->status
bx lr
.endm
.macro YM2612Read_and_ret16
stmfd sp!,{r3,r12,lr}
.if EXTERNAL_YM2612
ldr r0,=PicoOpt
ldr r0, =ym2612_st
ldr r0, [r0]
tst r0,#0x200
ldrne r2, =YM2612Read_940
ldreq r2, =YM2612Read_
mov lr,pc
bx r2
ldrb r0, [r0, #0x11] ;@ ym2612_st->status
orr r0,r0,r0,lsl #8
.else
bl YM2612Read_
orr r0,r0,r0,lsl #8
.endif
ldmfd sp!,{r3,r12,pc}
bx lr
.endm
pico_z80_read8: @ addr

View file

@ -13,6 +13,10 @@
#include <string.h>
#include "cz80.h"
#if PICODRIVE_HACKS
#include <Pico/PicoInt.h>
#endif
#ifndef ALIGN_DATA
#define ALIGN_DATA __attribute__((aligned(4)))
#endif
@ -203,6 +207,13 @@ void Cz80_Reset(cz80_struc *CPU)
Cz80_Set_Reg(CPU, CZ80_PC, 0);
}
/* */
#if PICODRIVE_HACKS
static inline unsigned char picodrive_read(unsigned short a)
{
return (a < 0x4000) ? Pico.zram[a&0x1fff] : z80_read(a);
}
#endif
/*--------------------------------------------------------
CPUŽÀ<EFBFBD>s

View file

@ -52,6 +52,7 @@ extern "C" {
#define CZ80_FETCH_SFT (16 - CZ80_FETCH_BITS)
#define CZ80_FETCH_BANK (1 << CZ80_FETCH_BITS)
#define PICODRIVE_HACKS 1
#define CZ80_LITTLE_ENDIAN 1
#define CZ80_USE_JUMPTABLE 1
#define CZ80_BIG_FLAGS_ARRAY 1

View file

@ -57,7 +57,11 @@
//#ifndef BUILD_CPS1PSP
//#define READ_MEM8(A) memory_region_cpu2[(A)]
//#else
#if PICODRIVE_HACKS
#define READ_MEM8(A) picodrive_read(A)
#else
#define READ_MEM8(A) CPU->Read_Byte(A)
#endif
//#endif
#if CZ80_LITTLE_ENDIAN
#define READ_MEM16(A) (READ_MEM8(A) | (READ_MEM8((A) + 1) << 8))
@ -65,7 +69,16 @@
#define READ_MEM16(A) ((READ_MEM8(A) << 8) | READ_MEM8((A) + 1))
#endif
#if PICODRIVE_HACKS
#define WRITE_MEM8(A, D) { \
unsigned short a = A; \
unsigned char d = D; \
if (a < 0x4000) Pico.zram[a&0x1fff] = d; \
else z80_write(a, d); \
}
#else
#define WRITE_MEM8(A, D) CPU->Write_Byte(A, D);
#endif
#if CZ80_LITTLE_ENDIAN
#define WRITE_MEM16(A, D) { WRITE_MEM8(A, D); WRITE_MEM8((A) + 1, (D) >> 8); }
#else

View file

@ -16,8 +16,8 @@
// Options //
#define FAMEC_ROLL_INLINE
#define FAMEC_EMULATE_TRACE
#define FAMEC_CHECK_BRANCHES
//#define FAMEC_EMULATE_TRACE
//#define FAMEC_CHECK_BRANCHES
#define FAMEC_EXTRA_INLINE
// #define FAMEC_DEBUG
//#define FAMEC_NO_GOTOS
@ -280,11 +280,18 @@ typedef signed int s32;
((u32)PC - BasePC)
#ifdef FAMEC_CHECK_BRANCHES
#define FORCE_ALIGNMENT(pc)
#else
#define FORCE_ALIGNMENT(pc) pc&=~1;
#endif
#ifndef FAMEC_32BIT_PC
#define SET_PC(A) \
{ \
u32 pc = A; \
FORCE_ALIGNMENT(pc); \
BasePC = m68kcontext.Fetch[(pc >> M68K_FETCHSFT) & M68K_FETCHMASK]; \
PC = (u16*)((pc & M68K_ADR_MASK) + BasePC); \
}
@ -294,6 +301,7 @@ typedef signed int s32;
#define SET_PC(A) \
{ \
u32 pc = A; \
FORCE_ALIGNMENT(pc); \
BasePC = m68kcontext.Fetch[(pc >> M68K_FETCHSFT) & M68K_FETCHMASK]; \
BasePC -= pc & 0xFF000000; \
PC = (u16*)(pc + BasePC); \
@ -734,7 +742,9 @@ static FAMEC_EXTRA_INLINE u32 execute_exception(s32 vect, u32 oldPC, u32 oldSR)
#ifndef FAMEC_32BIT_PC
newPC&=M68K_ADR_MASK
#endif
#ifdef FAMEC_CHECK_BRANCHES
newPC&=~1; // don't crash on games with bad vector tables
#endif
// SET_PC(newPC)
@ -948,6 +958,7 @@ famec_End:
#ifdef PICODRIVE_HACK
dualcore_mode:
while (1)
{
extern int SekCycleAim, SekCycleCnt, SekCycleAimS68k, SekCycleCntS68k;
#define PS_STEP_M68K ((488<<16)/20) // ~24
@ -989,7 +1000,6 @@ dualcore_mode:
}
cycles = m68kcontext.io_cycle_counter = 0;
}
goto dualcore_mode;
}
#endif

View file

@ -51,22 +51,12 @@ static FILE *loaded_mp3 = 0;
}
/* these will be managed locally on our side */
extern int *ym2612_dacen;
extern INT32 *ym2612_dacout;
static UINT8 *REGS = 0; /* we will also keep local copy of regs for savestates and such */
static INT32 *addr_A1; /* address line A1 */
static int dacen;
static INT32 dacout;
static UINT8 ST_address; /* address register */
static UINT8 ST_status; /* status flag */
static UINT8 ST_mode; /* mode CSM / 3SLOT */
static int ST_TA; /* timer a */
static int ST_TAC; /* timer a maxval */
static int ST_TAT; /* timer a ticker */
static UINT8 ST_TB; /* timer b */
static int ST_TBC; /* timer b maxval */
static int ST_TBT; /* timer b ticker */
static int writebuff_ptr = 0;
@ -84,16 +74,16 @@ static int set_timers( int v )
/* b2 = timer enable a */
/* b1 = load b */
/* b0 = load a */
change = (ST_mode ^ v) & 0xc0;
ST_mode = v;
change = (ym2612_st->mode ^ v) & 0xc0;
ym2612_st->mode = v;
/* reset Timer b flag */
if( v & 0x20 )
ST_status &= ~2;
ym2612_st->status &= ~2;
/* reset Timer a flag */
if( v & 0x10 )
ST_status &= ~1;
ym2612_st->status &= ~1;
return change;
}
@ -139,30 +129,30 @@ int YM2612Write_940(unsigned int a, unsigned int v)
switch( addr )
{
case 0x24: { // timer A High 8
int TAnew = (ST_TA & 0x03)|(((int)v)<<2);
if(ST_TA != TAnew) {
int TAnew = (ym2612_st->TA & 0x03)|(((int)v)<<2);
if (ym2612_st->TA != TAnew) {
// we should reset ticker only if new value is written. Outrun requires this.
ST_TA = TAnew;
ST_TAC = (1024-TAnew)*18;
ST_TAT = 0;
ym2612_st->TA = TAnew;
ym2612_st->TAC = (1024-TAnew)*18;
ym2612_st->TAT = 0;
}
return 0;
}
case 0x25: { // timer A Low 2
int TAnew = (ST_TA & 0x3fc)|(v&3);
if(ST_TA != TAnew) {
ST_TA = TAnew;
ST_TAC = (1024-TAnew)*18;
ST_TAT = 0;
int TAnew = (ym2612_st->TA & 0x3fc)|(v&3);
if (ym2612_st->TA != TAnew) {
ym2612_st->TA = TAnew;
ym2612_st->TAC = (1024-TAnew)*18;
ym2612_st->TAT = 0;
}
return 0;
}
case 0x26: // timer B
if(ST_TB != v) {
ST_TB = v;
ST_TBC = (256-v)<<4;
ST_TBC *= 18;
ST_TBT = 0;
if (ym2612_st->TB != v) {
ym2612_st->TB = v;
ym2612_st->TBC = (256-v)<<4;
ym2612_st->TBC *= 18;
ym2612_st->TBT = 0;
}
return 0;
case 0x27: /* mode, timer control */
@ -229,38 +219,6 @@ int YM2612Write_940(unsigned int a, unsigned int v)
return 0; // cause the engine to do updates once per frame only
}
UINT8 YM2612Read_940(void)
{
return ST_status;
}
int YM2612PicoTick_940(int n)
{
//int ret = 0;
// timer A
if(ST_mode & 0x01 && (ST_TAT+=64*n) >= ST_TAC) {
ST_TAT -= ST_TAC;
if(ST_mode & 0x04) ST_status |= 1;
// CSM mode total level latch and auto key on
/* FIXME
if(ST_mode & 0x80) {
CSMKeyControll( &(ym2612_940->CH[2]) ); // Vectorman2, etc.
ret = 1;
}
*/
}
// timer B
if(ST_mode & 0x02 && (ST_TBT+=64*n) >= ST_TBC) {
ST_TBT -= ST_TBC;
if(ST_mode & 0x08) ST_status |= 2;
}
return 0;
}
#define CHECK_BUSY(job) \
(gp2x_memregs[0x3b46>>1] & (1<<(job-1)))
@ -339,12 +297,14 @@ void YM2612PicoStateLoad_940(void)
static void internal_reset(void)
{
writebuff_ptr = 0;
ST_mode = 0;
ST_status = 0; /* normal mode */
ST_TA = 0;
ST_TAC = 0;
ST_TB = 0;
ST_TBC = 0;
ym2612_st->mode = 0;
ym2612_st->status = 0; /* normal mode */
ym2612_st->TA = 0;
ym2612_st->TAC = 0;
ym2612_st->TAT = 0;
ym2612_st->TB = 0;
ym2612_st->TBC = 0;
ym2612_st->TBT = 0;
dacen = 0;
dacout = 0;
ST_address= 0;

View file

@ -138,15 +138,10 @@ endif
all: PicoDrive.gpe
PicoDrive.gpe : $(OBJS) ../common/helix/helix_mp3.a
@echo $@
@$(GCC) -o $@ $(COPT) $^ -lm -lpng -Wl,-Map=PicoDrive.map
@echo ">>>" $@
$(GCC) -o $@ $(COPT) $^ -lm -lpng -Wl,-Map=PicoDrive.map
ifeq ($(DEBUG),)
@$(STRIP) $@
endif
# @$(GCC) $(COPT) $(OBJS) -lm -o PicoDrive_.gpe
# @gpecomp PicoDrive_.gpe $@
ifeq "$(up)" "1"
@cmd //C copy $@ \\\\10.0.1.2\\gp2x\\mnt\\sd\\games\\PicoDrive\\
$(STRIP) $@
endif
up: PicoDrive.gpe
@ -155,45 +150,40 @@ up: PicoDrive.gpe
# @cmd //C copy PicoDrive.gpe \\\\10.0.1.2\\gp2x\\mnt\\sd\\games\\PicoDrive\\
testrefr.gpe : test.o gp2x.o
@echo $@
@$(GCC) $(COPT) $^ -o $@
@$(STRIP) $@
.c.o:
@echo $<
@$(GCC) $(COPT) $(DEFINC) -c $< -o $@
@echo ">>>" $<
$(GCC) $(COPT) $(DEFINC) -c $< -o $@
.s.o:
@echo $<
@$(GCC) $(COPT) $(DEFINC) -c $< -o $@
@echo ">>>" $<
$(GCC) $(COPT) $(DEFINC) -c $< -o $@
../../Pico/draw_asm.o : ../../Pico/Draw.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
@echo ">>>" $<
$(AS) $(ASOPT) $< -o $@
../../Pico/draw2_asm.o : ../../Pico/Draw2.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
@echo ">>>" $<
$(AS) $(ASOPT) $< -o $@
../../Pico/memory_asm.o : ../../Pico/Memory.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
@echo ">>>" $<
$(AS) $(ASOPT) $< -o $@
../../Pico/sound/ym2612_asm.o : ../../Pico/sound/ym2612.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
@echo ">>>" $<
$(AS) $(ASOPT) $< -o $@
../../Pico/sound/mix_asm.o : ../../Pico/sound/mix.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
@echo ">>>" $<
$(AS) $(ASOPT) $< -o $@
../../Pico/misc_asm.o : ../../Pico/Misc.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
@echo ">>>" $<
$(AS) $(ASOPT) $< -o $@
../../Pico/cd/pico_asm.o : ../../Pico/cd/Pico.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
@echo ">>>" $<
$(AS) $(ASOPT) $< -o $@
../../Pico/cd/memory_asm.o : ../../Pico/cd/Memory.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
@echo ">>>" $<
$(AS) $(ASOPT) $< -o $@
../../Pico/cd/misc_asm.o : ../../Pico/cd/Misc.s
@echo $<
@$(AS) $(ASOPT) $< -o $@
@echo ">>>" $<
$(AS) $(ASOPT) $< -o $@
# build Cyclone
../../cpu/Cyclone/proj/Cyclone.s :

View file

@ -1,2 +1,2 @@
#define VERSION "1.34"
#define VERSION "1.35"

View file

@ -40,19 +40,6 @@ int YM2612Write_940(unsigned int a, unsigned int v)
return 0; // cause the engine to do updates once per frame only
}
UINT8 YM2612Read_940(void)
{
return YM2612Read_();
}
int YM2612PicoTick_940(int n)
{
YM2612PicoTick_(n);
return 0;
}
void YM2612PicoStateLoad_940(void)
{

View file

@ -13,8 +13,8 @@ STRIP = strip
AS = gcc
ifeq "$(profile)" "1"
COPT_COMMON = -s -O3 -ftracer -fstrength-reduce -Wall -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math -fprofile-generate # -static
COPT = $(COPT_COMMON) # -mtune=arm920t
COPT_COMMON = -s -O3 -ftracer -fstrength-reduce -Wall -funroll-loops -fomit-frame-pointer -fstrict-aliasing -ffast-math -fprofile-generate
COPT = $(COPT_COMMON)
else
COPT = -ggdb -Wall -fno-strict-aliasing # -pg -O3 -ftracer -fstrength-reduce -funroll-loops -fomit-frame-pointer -ffast-math
COPT_COMMON = $(COPT)

View file

@ -6,23 +6,19 @@ PSPSDK = $(shell psp-config --pspsdk-path)
#use_musashi = 1
#use_mz80 = 1
amalgamate = 0
#profile = 1
#up = 1
CFLAGS += -I../.. -I. -DNO_SYNC -DLPRINTF_STDIO
CFLAGS += -Wall -Winline -G0
CFLAGS += -DLPRINTF_STDIO
#CFLAGS += -fprofile-generate
#CFLAGS += -fprofile-use
#CFLAGS += -pg
ifeq ($(DEBUG),)
CFLAGS += -O2 -ftracer -fstrength-reduce -ffast-math
else
CFLAGS += -ggdb
endif
ifeq "$(profile)" "1"
CFLAGS += -fprofile-generate
endif
ifeq "$(profile)" "2"
CFLAGS += -fprofile-use
endif
# frontend
@ -37,7 +33,7 @@ OBJS += ../../PicoAll.o
else
OBJS += ../../Pico/Area.o ../../Pico/Cart.o ../../Pico/Memory.o ../../Pico/Misc.o \
../../Pico/Pico.o ../../Pico/Sek.o ../../Pico/VideoPort.o ../../Pico/Draw2.o ../../Pico/Draw.o \
../../Pico/Patch.o ../../Pico/Draw_amips.o ../../Pico/Memory_amips.o
../../Pico/Patch.o ../../Pico/Draw_amips.o ../../Pico/Memory_amips.o ../../Pico/Misc_amips.o
# 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 \
@ -77,8 +73,10 @@ OBJS += data/bg32.o data/bg40.o
LIBS += -lpng -lm -lpspgu -lpsppower -lpspaudio -lpsprtc -lpspaudiocodec
#LIBS += -lpspprof
LDFLAGS += -Wl,-Map=PicoDrive.map
# target
TARGET = PicoDrive
EXTRA_TARGETS = EBOOT.PBP
@ -114,7 +112,11 @@ AS := psp-as
../../Pico/Draw.o : ../../Pico/Draw.c
@echo ">>>" $<
$(CC) $(CFLAGS) -c $< -o $@ -D_ASM_DRAW_C_MIPS
$(CC) $(CFLAGS) -c $< -o $@ -D_ASM_DRAW_C_AMIPS
../../Pico/Misc.o : ../../Pico/Misc.c
@echo ">>>" $<
$(CC) $(CFLAGS) -c $< -o $@ -D_ASM_MISC_C_AMIPS
readme.txt: ../../tools/textfilter ../base_readme.txt
../../tools/textfilter ../base_readme.txt $@ PSP
@ -152,6 +154,5 @@ endif
# ?
rel: EBOOT.PBP readme.txt
zip -9 -j ../../PicoDrive_$(VER).zip $^
# zip -9 -r ../../PicoDrive_$(VER).zip skin -i \*.png -i \*.txt
zip -9 -r ../../PicoDrive_$(VER).zip skin -i \*.png -i \*.txt

View file

@ -11,6 +11,7 @@
#include "psp.h"
#include "menu.h"
#include "emu.h"
#include "mp3.h"
#include "../common/emu.h"
#include "../common/lprintf.h"
#include "../../Pico/PicoInt.h"
@ -57,7 +58,7 @@ static void osd_text(int x, const char *text, int is_active, int clear_all)
for (h = 0; h < 8; h++) {
p = (int *) (screen+x+512*(264+h));
p = (int *) ((int)p & ~3); // align
memset32(p, 0, len);
memset32_uncached(p, 0, len);
}
if (is_active) { tmp = psp_screen; psp_screen = screen; } // nasty pointer tricks
emu_textOut16(x, 264, text);
@ -126,8 +127,8 @@ void emu_setDefaultConfig(void)
{
memset(&currentConfig, 0, sizeof(currentConfig));
currentConfig.lastRomFile[0] = 0;
currentConfig.EmuOpt = 0x1f | 0x680; // | confirm_save, cd_leds, 16bit rend
currentConfig.PicoOpt = 0x0f | 0xc00; // | cd_pcm, cd_cdda
currentConfig.EmuOpt = 0x1d | 0x680; // | confirm_save, cd_leds, acc rend
currentConfig.PicoOpt = 0x0f | 0x1c00; // | gfx_cd, cd_pcm, cd_cdda
currentConfig.PsndRate = 22050;
currentConfig.PicoRegion = 0; // auto
currentConfig.PicoAutoRgnOrder = 0x184; // US, EU, JP
@ -172,7 +173,7 @@ static int fbimg_offs = 0;
static void set_scaling_params(void)
{
int src_width, fbimg_width, fbimg_height, fbimg_xoffs, fbimg_yoffs;
int src_width, fbimg_width, fbimg_height, fbimg_xoffs, fbimg_yoffs, border_hack = 0;
g_vertices[0].x = g_vertices[0].y =
g_vertices[0].z = g_vertices[1].z = 0;
@ -185,9 +186,13 @@ static void set_scaling_params(void)
src_width = 256;
}
if (fbimg_width & 1) fbimg_width++; // make even
if (fbimg_height & 1) fbimg_height++;
if (fbimg_width >= 480) {
g_vertices[0].u = (fbimg_width-480)/2;
g_vertices[1].u = src_width - (fbimg_width-480)/2;
g_vertices[1].u = src_width - (fbimg_width-480)/2 - 1;
if (fbimg_width == 480) border_hack = 1;
fbimg_width = 480;
fbimg_xoffs = 0;
} else {
@ -211,6 +216,12 @@ static void set_scaling_params(void)
g_vertices[1].y = fbimg_height;
if (fbimg_xoffs < 0) fbimg_xoffs = 0;
if (fbimg_yoffs < 0) fbimg_yoffs = 0;
if (border_hack) {
g_vertices[0].u++;
g_vertices[0].x++;
g_vertices[1].u--;
g_vertices[1].x--;
}
fbimg_offs = (fbimg_yoffs*512 + fbimg_xoffs) * 2; // dst is always 16bit
/*
@ -371,7 +382,7 @@ static void cd_leds(void)
*p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r;
}
#if 0
static void dbg_text(void)
{
int *p, h, len;
@ -382,11 +393,11 @@ static void dbg_text(void)
for (h = 0; h < 8; h++) {
p = (int *) ((unsigned short *) psp_screen+2+512*(256+h));
p = (int *) ((int)p & ~3); // align
memset32(p, 0, len);
memset32_uncached(p, 0, len);
}
emu_textOut16(2, 256, text);
}
#endif
/* called after rendering is done, but frame emulation is not finished */
void blit1(void)
@ -415,7 +426,7 @@ static void blit2(const char *fps, const char *notice, int lagging_behind)
if (emu_opt & 2) osd_text(OSD_FPS_X, fps, 0, 0);
}
dbg_text();
//dbg_text();
if ((emu_opt & 0x400) && (PicoMCD & 1))
cd_leds();
@ -431,15 +442,15 @@ static void blit2(const char *fps, const char *notice, int lagging_behind)
static void clearArea(int full)
{
if (full) {
memset32(psp_screen, 0, 512*272*2/4);
memset32_uncached(psp_screen, 0, 512*272*2/4);
psp_video_flip(0);
memset32(psp_screen, 0, 512*272*2/4);
memset32_uncached(psp_screen, 0, 512*272*2/4);
memset32(VRAM_CACHED_STUFF, 0xe0e0e0e0, 512*240/4);
memset32((int *)VRAM_CACHED_STUFF+512*240/4, 0, 512*240*2/4);
} else {
void *fb = psp_video_get_active_fb();
memset32((int *)((char *)psp_screen + 512*264*2), 0, 512*8*2/4);
memset32((int *)((char *)fb + 512*264*2), 0, 512*8*2/4);
memset32_uncached((int *)((char *)psp_screen + 512*264*2), 0, 512*8*2/4);
memset32_uncached((int *)((char *)fb + 512*264*2), 0, 512*8*2/4);
}
}
@ -659,7 +670,7 @@ void emu_forcedFrame(void)
vidResetMode();
memset32(VRAM_CACHED_STUFF, 0xe0e0e0e0, 512*8/4); // borders
memset32((int *)VRAM_CACHED_STUFF + 512*232/4, 0xe0e0e0e0, 512*8/4);
memset32((int *)psp_screen + 512*264*2/4, 0, 512*8*2/4);
memset32_uncached((int *)psp_screen + 512*264*2/4, 0, 512*8*2/4);
PicoDrawSetColorFormat(-1);
PicoScan = EmuScanSlow;
@ -1036,7 +1047,7 @@ void emu_Loop(void)
}
// clear fps counters and stuff
memset32((int *)psp_video_get_active_fb() + 512*264*2/4, 0, 512*8*2/4);
memset32_uncached((int *)psp_video_get_active_fb() + 512*264*2/4, 0, 512*8*2/4);
}

View file

@ -28,4 +28,6 @@ void emu_forcedFrame(void);
void emu_msg_cb(const char *msg);
// actually comes from Pico/Misc_amips.s
void memset32_uncached(int *dest, int c, int count);

View file

@ -154,7 +154,7 @@ void menu_romload_prepare(const char *rom_name)
psp_video_switch_to_single();
if (rom_data) menu_draw_begin();
else memset32(psp_screen, 0, 512*272*2/4);
else memset32_uncached(psp_screen, 0, 512*272*2/4);
smalltext_out16(1, 1, "Loading", 0xffff);
smalltext_out16_lim(1, 10, p, 0xffff, 80);
@ -453,8 +453,10 @@ static void draw_debug(void)
static void debug_menu_loop(void)
{
int ret = 0;
draw_debug();
wait_for_input(BTN_X|BTN_CIRCLE, 0);
while (!(ret & (BTN_X|BTN_CIRCLE)))
ret = wait_for_input(BTN_X|BTN_CIRCLE, 0);
}
// ------------ patch/gg menu ------------
@ -1059,7 +1061,7 @@ static void menu_opt3_preview(int is_32col)
lprintf("uncompress returned %i\n", ret);
}
memset32(psp_screen, 0, 512*272*2/4);
memset32_uncached(psp_screen, 0, 512*272*2/4);
emu_forcedFrame();
menu_prepare_bg(1, 0);
@ -1119,6 +1121,7 @@ static void dispmenu_loop_options(void)
if (setting != NULL) {
while ((inp = psp_pad_read(0)) & (BTN_LEFT|BTN_RIGHT)) {
*setting += (inp & BTN_LEFT) ? -0.01 : 0.01;
if (*setting <= 0) *setting = 0.01;
menu_opt3_preview(is_32col);
draw_dispmenu_options(menu_sel); // will wait vsync
}
@ -1735,12 +1738,12 @@ static void menu_prepare_bg(int use_game_bg, int use_fg)
int i;
for (i = 272; i > 0; i--, dst += 480, src += 512)
menu_darken_bg(dst, src, 480, 1);
//memset32((int *)(bg_buffer + 480*264), 0, 480*8*2/4);
//memset32_uncached((int *)(bg_buffer + 480*264), 0, 480*8*2/4);
}
else
{
// should really only happen once, on startup..
memset32((int *)(void *)bg_buffer, 0, sizeof(bg_buffer)/4);
memset32_uncached((int *)(void *)bg_buffer, 0, sizeof(bg_buffer)/4);
readpng(bg_buffer, "skin/background.png", READPNG_BG);
}
sceKernelDcacheWritebackAll();
@ -1814,7 +1817,7 @@ int menu_loop_tray(void)
for (;;)
{
draw_menu_tray(menu_sel);
inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_X, 0);
inp = wait_for_input(BTN_UP|BTN_DOWN|BTN_CIRCLE, 0);
if(inp & BTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; }
if(inp & BTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; }
if(inp & BTN_CIRCLE) {

View file

@ -181,8 +181,6 @@ int mp3_init(void)
goto fail2;
}
lprintf("thread_busy_sem: %08x, thread_job_sem: %08x\n", thread_busy_sem, thread_job_sem);
thread_exit = 0;
thid = sceKernelCreateThread("mp3decode_thread", decode_thread, 30, 0x2000, 0, 0); /* use slightly higher prio then main */
if (thid < 0) {
@ -273,7 +271,7 @@ static int decode_thread(SceSize args, void *argp)
int mp3_get_bitrate(FILE *f, int size)
{
int ret = -1, sample_rate, bitrate;
int ret, retval = -1, sample_rate, bitrate;
// filenames are stored instead handles in PSP, due to stupid max open file limit
char *fname = (char *)f;
@ -307,14 +305,14 @@ int mp3_get_bitrate(FILE *f, int size)
}
/* looking good.. */
ret = bitrate;
retval = bitrate;
end:
if (mp3_handle >= 0) sceIoClose(mp3_handle);
mp3_handle = -1;
mp3_fname = NULL;
psp_sem_unlock(thread_busy_sem);
if (ret < 0) mp3_last_error = -1; // remember we had a problem..
return ret;
if (retval < 0) mp3_last_error = -1; // remember we had a problem..
return retval;
}

8
platform/psp/mp3.h Normal file
View file

@ -0,0 +1,8 @@
// additional stuff for PSP mp3 decoder implementation
extern int mp3_last_error;
int mp3_init(void);
void mp3_deinit(void);

View file

@ -10,6 +10,7 @@
#include <pspgu.h>
#include "psp.h"
#include "emu.h"
#include "../common/lprintf.h"
PSP_MODULE_INFO("PicoDrive", 0, 1, 34);
@ -28,6 +29,19 @@ static int exit_callback(int arg1, int arg2, void *common)
return 0;
}
/* Power Callback */
static int power_callback(int unknown, int pwrflags, void *common)
{
/* check for power switch and suspending as one is manual and the other automatic */
if (pwrflags & PSP_POWER_CB_POWER_SWITCH || pwrflags & PSP_POWER_CB_SUSPENDING)
{
lprintf("power_callback: flags: 0x%08X: suspending\n", pwrflags);
engineState = PGS_Menu;
}
sceDisplayWaitVblankStart();
return 0;
}
/* Callback thread */
static int callback_thread(SceSize args, void *argp)
{
@ -38,6 +52,8 @@ static int callback_thread(SceSize args, void *argp)
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
cbid = sceKernelCreateCallback("Power Callback", power_callback, NULL);
scePowerRegisterCallback(0, cbid);
sceKernelSleepThreadCB();

View file

@ -1,2 +1,2 @@
#define VERSION "1.34"
#define VERSION "1.35"

110
tools/gcda.c Normal file
View file

@ -0,0 +1,110 @@
#include <stdio.h>
//#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int search_gcda(const char *str, int len)
{
int i;
for (i = 0; i < len - 6; i++)
if (str[i] == '.' && str[i+1] == 'g' && str[i+2] == 'c' &&
str[i+3] == 'd' && str[i+4] == 'a' && str[i+5] == 0)
return i;
return -1;
}
static int is_good_char(char c)
{
return c >= ' ' && c < 0x7f;
}
static int is_good_path(char *path)
{
int len = strlen(path);
path[len-2] = 'n';
path[len-1] = 'o';
FILE *f = fopen(path, "rb");
path[len-2] = 'd';
path[len-1] = 'a';
if (f) {
fclose(f);
return 1;
}
return 0;
}
int main(int argc, char *argv[])
{
char buff[1024], *p;
char cwd[4096];
FILE *f;
int l, pos, pos1, old_len, cwd_len;
if (argc != 2) return 1;
getcwd(cwd, sizeof(cwd));
cwd_len = strlen(cwd);
if (cwd[cwd_len-1] != '/') {
cwd[cwd_len++] = '/';
cwd[cwd_len] = 0;
}
f = fopen(argv[1], "rb+");
if (f == NULL) return 2;
while (1)
{
readnext:
l = fread(buff, 1, sizeof(buff), f);
if (l <= 16) break;
pos = 0;
while (pos < l)
{
pos1 = search_gcda(buff + pos, l - pos);
if (pos1 < 0) {
fseek(f, -5, SEEK_CUR);
goto readnext;
}
pos += pos1;
while (pos > 0 && is_good_char(buff[pos-1])) pos--;
if (pos == 0) {
fseek(f, -16, SEEK_CUR);
goto readnext;
}
// paths must start with /
while (pos < l && buff[pos] != '/') pos++;
p = buff + pos;
old_len = strlen(p);
if (!is_good_path(p)) {
pos += old_len;
continue;
}
if (strncmp(p, cwd, cwd_len) != 0) {
printf("can't handle: %s\n", p);
pos += old_len;
continue;
}
memmove(p, p + cwd_len, old_len - cwd_len + 1);
fseek(f, -(sizeof(buff) - pos), SEEK_CUR);
fwrite(p, 1, old_len, f);
goto readnext;
}
}
fclose(f);
return 0;
}