Browse Source

optimizations, fixes, hacks, psp, ...

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@295 be3aeb3a-fb24-0410-a615-afba39da0efa
notaz 16 years ago
parent
commit
b542be4686

+ 3 - 7
Pico/Draw.c

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

+ 2 - 8
Pico/Draw2.c

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

+ 22 - 18
Pico/Memory.c

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

+ 5 - 8
Pico/Memory.s

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

+ 3 - 8
Pico/MemoryCmn.c

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

+ 4 - 2
Pico/Memory_amips.s

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

+ 3 - 1
Pico/Misc.c

@@ -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 - 0
Pico/Misc_amips.s

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

+ 2 - 2
Pico/Pico.c

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

+ 55 - 5
Pico/PicoInt.h

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

+ 0 - 27
Pico/Sek.c

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

+ 6 - 2
Pico/cd/Area.c

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

+ 199 - 107
Pico/cd/Memory.c

@@ -454,47 +454,72 @@ 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
+  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));
+      }
+      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;
+        a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged
+        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);
+      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;
+      }
+      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);
 
-  // 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];
-    d = *(prg_bank+((a^1)&0x1ffff));
-    goto end;
-  }
+      d=OtherRead16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;
 
-  // word RAM
-  if ((a&0xfc0000)==0x200000) {
-    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;
+      if ((a&0xffffc0)==0xa12000)
+        rdprintf("ret = %02x", (u8)d);
+      break;
   }
 
-  if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram
-
-  if ((a&0xffffc0)==0xa12000)
-    rdprintf("m68k_regs r8: [%02x] @%06x", a&0x3f, SekPc);
-
-  d=OtherRead16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;
-
-  if ((a&0xffffc0)==0xa12000)
-    rdprintf("ret = %02x", (u8)d);
-
-  end:
 
 #ifdef __debug_io
   dprintf("r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPc);
@@ -517,47 +542,71 @@ 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
+  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);
+      }
+      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;
+        a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged
+        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);
+      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);
 
-  // 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];
-    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;
-  }
+      d = OtherRead16(a, 16);
 
-  // word RAM
-  if ((a&0xfc0000)==0x200000) {
-    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;
+      if ((a&0xffffc0)==0xa12000)
+        rdprintf("ret = %04x", d);
+      break;
   }
 
-  if ((a&0xffffc0)==0xa12000)
-    rdprintf("m68k_regs r16: [%02x] @%06x", a&0x3f, SekPc);
-
-  d = OtherRead16(a, 16);
-
-  if ((a&0xffffc0)==0xa12000)
-    rdprintf("ret = %04x", d);
-
-  end:
 
 #ifdef __debug_io
   dprintf("r16: %06x, %04x  @%06x", a&0xffffff, d, SekPc);
@@ -580,52 +629,81 @@ 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) {
-    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) {
-    wrdprintf("m68k_wram r32: [%06x] @%06x", a, SekPc);
-    if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?
-      int bank = Pico_mcd->s68k_regs[3]&1;
-      if (a >= 0x220000) { // cell arranged
+  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];
+      }
+      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;
+        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];
+        // allow access in any mode, like Gens does
+        u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));
+	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];
+      wrdprintf("ret = %08x", d);
+      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;
     }
-    wrdprintf("ret = %08x", d);
-    goto end;
-  }
+    default:
+      if ((a&0xffffc0)==0xa12000)
+        rdprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);
 
-  if ((a&0xffffc0)==0xa12000)
-    rdprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);
+      d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);
 
-  d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);
+      if ((a&0xffffc0)==0xa12000)
+        rdprintf("ret = %08x", d);
+      break;
+  }
 
-  if ((a&0xffffc0)==0xa12000)
-    rdprintf("ret = %08x", d);
 
-  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);
 }

+ 1 - 0
Pico/cd/Pico.c

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

+ 7 - 2
Pico/cd/buffering.c

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

+ 10 - 50
Pico/sound/sound.c

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

+ 111 - 93
Pico/sound/ym2612.c

@@ -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;
-
-	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;
+	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;
 
-	flags &= 0x37;
+	flags &= 0x35;
 
-	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 &= ~0xf00;
-		else flags |= (CH->ams&3)<<6;
+		flags |= crct.CH->AMmasks << 8;
+		if (crct.CH->ams == 8) // no ams
+		     flags &= ~0xf00;
+		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));
 
-	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;
+	// 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;
+	}
 
-	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)
 {

+ 27 - 9
Pico/sound/ym2612.h

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

+ 11 - 34
cpu/DrZ80/drz80.s

@@ -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,[r0]
-    tst r0,#0x200
-    ldrne r2, =YM2612Read_940
-    ldreq r2, =YM2612Read_
-    mov lr,pc
-    bx r2
+    ldr r0, =ym2612_st
+    ldr r0, [r0]
+    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
@@ -214,13 +191,13 @@ pico_z80_read16: @ addr
     add r0,r4,#1
     bl PicoRead8
     orr r0,r5,r0,lsl #8
-	ldmfd sp!,{r3-r5,r12,pc}
+    ldmfd sp!,{r3-r5,r12,pc}
 1:
     mov r1,r0,lsr #13
     cmp r1,#2              @ YM2612 (0x4000-0x5fff)
     bne 0f
     and r0,r0,#3
-	YM2612Read_and_ret16
+    YM2612Read_and_ret16
 0:
     cmp r0,#0x4000
     movge r0,#0xff

+ 11 - 0
cpu/cz80/cz80.c

@@ -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ŽÀ�s

+ 1 - 0
cpu/cz80/cz80.h

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

+ 13 - 0
cpu/cz80/cz80macro.h

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

+ 13 - 3
cpu/fame/famec.c

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

+ 27 - 67
platform/gp2x/940ctl.c

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

+ 25 - 35
platform/gp2x/Makefile

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

+ 1 - 1
platform/gp2x/version.h

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

+ 0 - 13
platform/linux/940ctl_ym2612.c

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

+ 2 - 2
platform/linux/Makefile

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

+ 13 - 12
platform/psp/Makefile

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

+ 26 - 15
platform/psp/emu.c

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

+ 2 - 0
platform/psp/emu.h

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

+ 9 - 6
platform/psp/menu.c

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

+ 4 - 6
platform/psp/mp3.c

@@ -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 - 0
platform/psp/mp3.h

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

+ 16 - 0
platform/psp/psp.c

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

+ 1 - 1
platform/psp/version.h

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

+ 110 - 0
tools/gcda.c

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