#endif // EMU_M68K\r
\r
\r
+// -----------------------------------------------------------------\r
+\r
+extern const unsigned short vcounts[];\r
+\r
+static int get_scanline(int is_from_z80)\r
+{\r
+ if (is_from_z80) {\r
+ int cycles = z80_cyclesDone();\r
+ while (cycles - z80_scanline_cycles >= 228)\r
+ z80_scanline++, z80_scanline_cycles += 228;\r
+ return z80_scanline;\r
+ }\r
+\r
+ if (Pico.m.scanline != -1)\r
+ return Pico.m.scanline;\r
+\r
+ return vcounts[SekCyclesDone()>>8];\r
+}\r
+\r
+// ym2612 DAC and timer I/O handlers for z80\r
+int ym2612_write_local(u32 a, u32 d, int is_from_z80)\r
+{\r
+ int addr;\r
+\r
+ a &= 3;\r
+ if (a == 1 && ym2612.OPN.ST.address == 0x2a) /* DAC data */\r
+ {\r
+ int scanline = get_scanline(is_from_z80);\r
+ //elprintf(EL_STATUS, "%03i -> %03i dac w %08x z80 %i", PsndDacLine, scanline, d, is_from_z80);\r
+ ym2612.dacout = ((int)d - 0x80) << 6;\r
+ if (PsndOut && ym2612.dacen && scanline >= PsndDacLine)\r
+ PsndDoDAC(scanline);\r
+ return 0;\r
+ }\r
+\r
+ switch (a)\r
+ {\r
+ case 0: /* address port 0 */\r
+ ym2612.OPN.ST.address = d;\r
+ ym2612.addr_A1 = 0;\r
+#ifdef __GP2X__\r
+ if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, -1);\r
+#endif\r
+ return 0;\r
+\r
+ case 1: /* data port 0 */\r
+ if (ym2612.addr_A1 != 0)\r
+ return 0;\r
+\r
+ addr = ym2612.OPN.ST.address;\r
+ ym2612.REGS[addr] = d;\r
+\r
+ switch (addr)\r
+ {\r
+ case 0x24: // timer A High 8\r
+ case 0x25: { // timer A Low 2\r
+ int TAnew = (addr == 0x24) ? ((ym2612.OPN.ST.TA & 0x03)|(((int)d)<<2))\r
+ : ((ym2612.OPN.ST.TA & 0x3fc)|(d&3));\r
+ if (ym2612.OPN.ST.TA != TAnew)\r
+ {\r
+ //elprintf(EL_STATUS, "timer a set %i", TAnew);\r
+ ym2612.OPN.ST.TA = TAnew;\r
+ //ym2612.OPN.ST.TAC = (1024-TAnew)*18;\r
+ //ym2612.OPN.ST.TAT = 0;\r
+ //\r
+ timer_a_step = 16495 * (1024 - TAnew);\r
+ if ((ym2612.OPN.ST.mode & 5) == 5) {\r
+ int cycles = is_from_z80 ? z80_cyclesDone() : cycles_68k_to_z80(SekCyclesDone());\r
+ timer_a_next_oflow = (cycles << 8) + timer_a_step;\r
+ //elprintf(EL_STATUS, "set to %i @ %i", timer_a_next_oflow>>8, cycles);\r
+ }\r
+ }\r
+ return 0;\r
+ }\r
+ case 0x26: // timer B\r
+ if (ym2612.OPN.ST.TB != d) {\r
+ //elprintf(EL_STATUS, "timer b set %i", d);\r
+ ym2612.OPN.ST.TB = d;\r
+ //ym2612.OPN.ST.TBC = (256-d)<<4;\r
+ //ym2612.OPN.ST.TBC *= 18;\r
+ //ym2612.OPN.ST.TBT = 0;\r
+ }\r
+ return 0;\r
+ case 0x27: { /* mode, timer control */\r
+ int old_mode = ym2612.OPN.ST.mode;\r
+ int xcycles = is_from_z80 ? z80_cyclesDone() : cycles_68k_to_z80(SekCyclesDone());\r
+ xcycles <<= 8;\r
+\r
+ //elprintf(EL_STATUS, "st mode %02x", d);\r
+\r
+ if ((ym2612.OPN.ST.mode & 5) != 5 && (d & 5) == 5) {\r
+ timer_a_next_oflow = xcycles + timer_a_step;\r
+ //elprintf(EL_STATUS, "set to %i @ %i st", timer_a_next_oflow>>8, xcycles >> 8);\r
+ }\r
+\r
+ /* reset Timer b flag */\r
+ if (d & 0x20)\r
+ ym2612.OPN.ST.status &= ~2;\r
+\r
+ /* reset Timer a flag */\r
+ if (d & 0x10) {\r
+ if (ym2612.OPN.ST.status & 1)\r
+ while (xcycles > timer_a_next_oflow)\r
+ timer_a_next_oflow += timer_a_step;\r
+ ym2612.OPN.ST.status &= ~1;\r
+ }\r
+ if (!(d & 5)) timer_a_next_oflow = 0x80000000;\r
+ ym2612.OPN.ST.mode = d;\r
+#ifdef __GP2X__\r
+ if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, get_scanline(is_from_z80));\r
+#endif\r
+ return 0;\r
+ }\r
+ case 0x2b: { /* DAC Sel (YM2612) */\r
+ int scanline = get_scanline(is_from_z80);\r
+ ym2612.dacen = d & 0x80;\r
+ if (d & 0x80) PsndDacLine = scanline;\r
+#ifdef __GP2X__\r
+ if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, scanline);\r
+#endif\r
+ return 0;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case 2: /* address port 1 */\r
+ ym2612.OPN.ST.address = d;\r
+ ym2612.addr_A1 = 1;\r
+#ifdef __GP2X__\r
+ if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, -1);\r
+#endif\r
+ return 0;\r
+\r
+ case 3: /* data port 1 */\r
+ if (ym2612.addr_A1 != 1)\r
+ return 0;\r
+\r
+ addr = ym2612.OPN.ST.address | 0x100;\r
+ ym2612.REGS[addr] = d;\r
+ break;\r
+ }\r
+\r
+#ifdef __GP2X__\r
+ if (PicoOpt & POPT_EXT_FM)\r
+ return YM2612Write_940(a, d, get_scanline(is_from_z80));\r
+#endif\r
+ return YM2612Write_(a, d);\r
+}\r
+\r
+// TODO: timer b, 68k side + asm, savestates\r
+u32 ym2612_read_local_z80(void)\r
+{\r
+ int xcycles = z80_cyclesDone() << 8;\r
+ if (timer_a_next_oflow != 0x80000000 && xcycles >= timer_a_next_oflow) {\r
+ ym2612.OPN.ST.status |= 1;\r
+ }\r
+\r
+ //elprintf(EL_STATUS, "timer %i, sched %i, @ %i|%i", ym2612.OPN.ST.status, timer_a_next_oflow>>8,\r
+ // xcycles >> 8, (xcycles >> 8) / 228);\r
+ return ym2612.OPN.ST.status;\r
+}\r
+\r
// -----------------------------------------------------------------\r
// z80 memhandlers\r
\r
\r
if ((a>>13)==2) // 0x4000-0x5fff (Charles MacDonald)\r
{\r
- if (PicoOpt&POPT_EN_FM) ret = (u8) YM2612Read();\r
+ if (PicoOpt&POPT_EN_FM) ret = ym2612_read_local_z80();\r
return ret;\r
}\r
\r
if (PicoAHW & PAHW_MCD)\r
ret = PicoReadM68k8(addr68k);\r
else ret = PicoRead8(addr68k);\r
- elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret);\r
+ if (addr68k >= 0x400000) // not many games do this\r
+ { elprintf(EL_ANOMALY, "z80->68k upper read [%06x] %02x", addr68k, ret); }\r
+ else\r
+ { elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret); }\r
return ret;\r
}\r
\r
{\r
if ((a>>13)==2) // 0x4000-0x5fff (Charles MacDonald)\r
{\r
- if(PicoOpt&POPT_EN_FM) emustatus|=YM2612Write(a, data) & 1;\r
+ if(PicoOpt&POPT_EN_FM) emustatus|=ym2612_write_local(a, data, 1) & 1;\r
return;\r
}\r
\r
and r2, r0, #0x6000\r
cmp r2, #0x4000\r
bne m_write8_z80_not_ym2612\r
- ldr r2, =PicoOpt\r
+ ldr r3, =PicoOpt\r
and r0, r0, #3\r
- ldr r2, [r2]\r
- tst r2, #1\r
+ ldr r3, [r3]\r
+ mov r2, #0 @ is_from_z80 = 0\r
+ tst r3, #1\r
bxeq lr\r
stmfd sp!,{lr}\r
-.if EXTERNAL_YM2612\r
- tst r2, #0x200\r
- ldreq r2, =YM2612Write_\r
- ldrne r2, =YM2612Write_940\r
- mov lr, pc\r
- bx r2\r
-.else\r
- bl YM2612Write_\r
-.endif\r
+ and r1, r1, #0xff\r
+ bl ym2612_write_local\r
ldr r2, =emustatus\r
ldmfd sp!,{lr}\r
ldr r1, [r2]\r
and r0, r0, #1\r
orr r1, r0, r1\r
- str r1, [r2] @ emustatus|=YM2612Write(a&3, d);\r
+ str r1, [r2] @ emustatus|=ym2612_write_local(a&3, d);\r
bx lr\r
\r
m_write8_z80_not_ym2612: @ not too likely\r
m_write8_z80_bank_reg:\r
ldr r3, =(Pico+0x22208) @ Pico.m\r
ldrh r2, [r3, #0x0a]\r
- mov r1, r1, lsr #8\r
+ mov r1, r1, lsl #8\r
orr r2, r1, r2, lsr #1\r
bic r2, r2, #0xfe00\r
strh r2, [r3, #0x0a]\r
bne OtherWrite8\r
m_write8_psg:\r
ldr r2, =PicoOpt\r
- mov r0, r1\r
+ and r0, r1, #0xff\r
ldr r2, [r2]\r
tst r2, #2\r
bxeq lr\r
{
if (!d)
{
- // this is for a nasty situation where Z80 was enabled and disabled in the same 68k timeslice (Golden Axe III)
if ((PicoOpt&POPT_EN_Z80) && Pico.m.z80Run)
{
- int lineCycles;
z80stopCycle = SekCyclesDone();
- if ((Pico.m.z80Run&2) && Pico.m.scanline != -1)
- lineCycles=(488-SekCyclesLeft)&0x1ff;
- else lineCycles=z80stopCycle-z80startCycle; // z80 was started at current line
- if (lineCycles > 0) { // && lineCycles <= 488) {
- //dprintf("zrun: %i/%i cycles", lineCycles, (lineCycles>>1)-(lineCycles>>5));
- lineCycles=(lineCycles>>1)-(lineCycles>>5);
- z80_run_nr(lineCycles);
- }
+ PicoSyncZ80(z80stopCycle);
}
} else {
if (!Pico.m.z80Run)
- z80startCycle = SekCyclesDone();
- else
- d|=Pico.m.z80Run;
+ z80_cycle_cnt = cycles_68k_to_z80(SekCyclesDone());
}
}
elprintf(EL_BUSREQ, "set_zrun: %i->%i [%i] @%06x", Pico.m.z80Run, d, SekCyclesDone(), SekPc);
if ((a&0xff4000)==0xa00000) { // z80 RAM
if (!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)d;
else {
- elprintf(EL_ANOMALY, "68k z80 write with no bus! [%06x] %02x @ %06x", a, d, SekPc);
+ elprintf(EL_ANOMALY, "68k z80 write with no bus! [%06x] %02x @ %06x", a, d&0xff, SekPc);
SekCyclesBurn(4); // hack?
}
return;
}
- if ((a&0xff6000)==0xa04000) { if(PicoOpt&1) emustatus|=YM2612Write(a&3, d)&1; return; } // FM Sound
+ if ((a&0xff6000)==0xa04000) { if(PicoOpt&1) emustatus|=ym2612_write_local(a&3, d&0xff, 0)&1; return; } // FM Sound
if ((a&0xffffe0)==0xa10000) { IoWrite8(a, d); return; } // I/O ports
#endif
if (a==0xa11100) { z80WriteBusReq(d); return; }
Pico.m.z80_reset = 0;
YM2612ResetChip();
z80_reset();
+ timers_reset();
}
return;
}
return;
}
- PicoWrite8Hook(a, d, 8);
+ PicoWrite8Hook(a, d&0xff, 8);
}
if (a==0xa11100) { z80WriteBusReq(d>>8); return; }
if ((a&0xffffe0)==0xa10000) { IoWrite8(a, d); return; } // I/O ports
if ((a&0xe700f8)==0xc00010||(a&0xff7ff8)==0xa07f10) { if(PicoOpt&2) SN76496Write(d); return; } // PSG Sound
- if ((a&0xff6000)==0xa04000) { if(PicoOpt&1) emustatus|=YM2612Write(a&3, d)&1; return; } // FM Sound (??)
+ if ((a&0xff6000)==0xa04000) { if(PicoOpt&1) emustatus|=ym2612_write_local(a&3, d&0xff, 0)&1; return; } // FM Sound
if ((a&0xff4000)==0xa00000) { // Z80 ram (MSB only)
if (!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)(d>>8);
- else elprintf(EL_ANOMALY, "68k z80 write with no bus! [%06x] %02x @ %06x", a, d, SekPc);
+ else elprintf(EL_ANOMALY, "68k z80 write with no bus! [%06x] %02x @ %06x", a, d&0xffff, SekPc);
return;
}
if (a==0xa11200) {
Pico.m.z80_reset = 0;
YM2612ResetChip();
z80_reset();
+ timers_reset();
}
return;
}
}
#endif
- PicoWrite16Hook(a, d, 16);
+ PicoWrite16Hook(a, d&0xffff, 16);
}
int PicoAHW = 0; // active addon hardware: scd_active, 32x_active, svp_active, pico_active\r
int PicoRegionOverride = 0; // override the region detection 0: Auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe\r
int PicoAutoRgnOrder = 0;\r
-int z80startCycle, z80stopCycle; // in 68k cycles\r
struct PicoSRAM SRam = {0,};\r
\r
void (*PicoWriteSound)(int len) = NULL; // called at the best time to send sound buffer (PsndOut) to hardware\r
\r
#include "PicoFrameHints.c"\r
\r
-// helper z80 runner. Runs only if z80 is enabled at this point\r
-// (z80WriteBusReq will handle the rest)\r
-static void PicoRunZ80Simple(int line_from, int line_to)\r
+\r
+int z80stopCycle;\r
+int z80_cycle_cnt; /* 'done' z80 cycles before z80_run() */\r
+int z80_cycle_aim;\r
+int z80_scanline;\r
+int z80_scanline_cycles; /* cycles done until z80_scanline */\r
+\r
+/* sync z80 to 68k */\r
+PICO_INTERNAL void PicoSyncZ80(int m68k_cycles_done)\r
{\r
- int line_from_r=line_from, line_to_r=line_to, line=0;\r
- int line_sample = Pico.m.pal ? 68 : 93;\r
-\r
- if (!(PicoOpt&POPT_EN_Z80) || Pico.m.z80Run == 0) line_to_r = 0;\r
- else {\r
- extern const unsigned short vcounts[];\r
- if (z80startCycle) {\r
- line = vcounts[z80startCycle>>8];\r
- if (line > line_from)\r
- line_from_r = line;\r
- }\r
- z80startCycle = SekCyclesDone();\r
- }\r
+ int cnt;\r
+ z80_cycle_aim = cycles_68k_to_z80(m68k_cycles_done);\r
+ cnt = z80_cycle_aim - z80_cycle_cnt;\r
\r
- if (PicoOpt&POPT_EN_FM) {\r
- // we have ym2612 enabled, so we have to run Z80 in lines, so we could update DAC and timers\r
- for (line = line_from; line < line_to; line++) {\r
- Psnd_timers_and_dac(line);\r
- if ((line == 224 || line == line_sample) && PsndOut) getSamples(line);\r
- if (line == 32 && PsndOut) emustatus &= ~1;\r
- if (line >= line_from_r && line < line_to_r)\r
- z80_run_nr(228);\r
- }\r
- } else if (line_to_r-line_from_r > 0) {\r
- z80_run_nr(228*(line_to_r-line_from_r));\r
- // samples will be taken by caller\r
- }\r
+ elprintf(EL_ANOMALY, "z80 sync %i (%i|%i -> %i|%i)", cnt, z80_cycle_cnt, z80_cycle_cnt / 228,\r
+ z80_cycle_aim, z80_cycle_aim / 228);\r
+\r
+ if (cnt > 0)\r
+ z80_cycle_cnt += z80_run(cnt);\r
}\r
\r
+\r
// Simple frame without H-Ints\r
static int PicoFrameSimple(void)\r
{\r
struct PicoVideo *pv=&Pico.video;\r
- int y=0,line=0,lines=0,lines_step=0,sects;\r
+ int y=0,lines_step=0,sects,line_last;\r
int cycles_68k_vblock,cycles_68k_block;\r
\r
// split to 16 run calls for active scan, for vblank split to 2 (ntsc), 3 (pal 240), 4 (pal 224)\r
- if (Pico.m.pal && (pv->reg[1]&8)) {\r
+ if (Pico.m.pal)\r
+ {\r
if(pv->reg[1]&8) { // 240 lines\r
- cycles_68k_block = 7329; // (488*240+148)/16.0, -4\r
- cycles_68k_vblock = 11640; // (72*488-148-68)/3.0, 0\r
+ cycles_68k_block = 7308;\r
+ cycles_68k_vblock = 11694;\r
lines_step = 15;\r
} else {\r
- cycles_68k_block = 6841; // (488*224+148)/16.0, -4\r
- cycles_68k_vblock = 10682; // (88*488-148-68)/4.0, 0\r
+ cycles_68k_block = 6821;\r
+ cycles_68k_vblock = 10719;\r
lines_step = 14;\r
}\r
+ line_last = 312-1;\r
} else {\r
// M68k cycles/frame: 127840.71\r
cycles_68k_block = 6841; // (488*224+148)/16.0, -4\r
cycles_68k_vblock = 9164; // (38*488-148-68)/2.0, 0\r
lines_step = 14;\r
+ line_last = 262-1;\r
}\r
\r
// a hack for VR, to get it running in fast mode\r
Pico.video.status|=0x200;\r
\r
Pico.m.scanline=-1;\r
- z80startCycle=0;\r
+ PsndDacLine = 0;\r
\r
SekCyclesReset();\r
+ z80_resetCycles();\r
+ timers_cycle();\r
\r
// 6 button pad: let's just say it timed out now\r
Pico.m.padTHPhase[0]=Pico.m.padTHPhase[1]=0;\r
pv->status&=~0x88; // clear V-Int, come out of vblank\r
\r
// Run in sections:\r
- for(sects=16; sects; sects--)\r
+ for (sects=16; sects; sects--)\r
{\r
if (CheckIdle()) break;\r
\r
- lines += lines_step;\r
SekRunM68k(cycles_68k_block);\r
-\r
- PicoRunZ80Simple(line, lines);\r
if (PicoLineHook) PicoLineHook(lines_step);\r
- line=lines;\r
}\r
\r
- // run Z80 for remaining sections\r
- if(sects) {\r
- int c = sects*cycles_68k_block;\r
-\r
- // this "run" is for approriate line counter, etc\r
- SekCycleCnt += c;\r
- SekCycleAim += c;\r
+ // do remaining sections without 68k\r
+ if (sects) {\r
+ SekCycleCnt += sects * cycles_68k_block;\r
+ SekCycleAim += sects * cycles_68k_block;\r
\r
- lines += sects*lines_step;\r
- PicoRunZ80Simple(line, lines);\r
if (PicoLineHook) PicoLineHook(sects*lines_step);\r
}\r
\r
#endif\r
}\r
\r
- // here we render sound if ym2612 is disabled\r
- if (!(PicoOpt&POPT_EN_FM) && PsndOut) {\r
- int len = PsndRender(0, PsndLen);\r
- if (PicoWriteSound) PicoWriteSound(len);\r
- // clear sound buffer\r
- PsndClear();\r
- }\r
-\r
// a gap between flags set and vint\r
pv->pending_ints|=0x20;\r
pv->status|=8; // go into vblank\r
SekRunM68k(68+4);\r
\r
+ if (Pico.m.z80Run && (PicoOpt&POPT_EN_Z80))\r
+ PicoSyncZ80(SekCycleCnt);\r
+\r
+ // render sound\r
+ if (PsndOut)\r
+ {\r
+ int len;\r
+ if (ym2612.dacen && PsndDacLine <= lines_step*16)\r
+ PsndDoDAC(lines_step*16);\r
+ len = PsndRender(0, PsndLen);\r
+ if (PicoWriteSound) PicoWriteSound(len);\r
+ // clear sound buffer\r
+ PsndClear();\r
+ }\r
+\r
// ---- V-Blanking period ----\r
// fix line counts\r
if(Pico.m.pal) {\r
if(pv->reg[1]&8) { // 240 lines\r
- lines = line = 240;\r
sects = 3;\r
lines_step = 24;\r
} else {\r
- lines = line = 224;\r
sects = 4;\r
lines_step = 22;\r
}\r
} else {\r
- lines = line = 224;\r
sects = 2;\r
lines_step = 19;\r
}\r
if (Pico.m.z80Run && (PicoOpt&POPT_EN_Z80))\r
z80_int();\r
\r
- while (sects)\r
+ while (1)\r
{\r
- lines += lines_step;\r
-\r
SekRunM68k(cycles_68k_vblock);\r
-\r
- PicoRunZ80Simple(line, lines);\r
if (PicoLineHook) PicoLineHook(lines_step);\r
- line=lines;\r
\r
sects--;\r
- if (sects && CheckIdle()) break;\r
+ if (sects == 0) break;\r
+ if (CheckIdle()) break;\r
}\r
\r
- // run Z80 for remaining sections\r
if (sects) {\r
- lines += sects*lines_step;\r
- PicoRunZ80Simple(line, lines);\r
+ SekCycleCnt += sects * cycles_68k_vblock;\r
+ SekCycleAim += sects * cycles_68k_vblock;\r
if (PicoLineHook) PicoLineHook(sects*lines_step);\r
}\r
\r
+ // must sync z80 before return, and extend last DAC sample\r
+ if (Pico.m.z80Run && (PicoOpt&POPT_EN_Z80))\r
+ PicoSyncZ80(SekCycleCnt);\r
+ if (PsndOut && ym2612.dacen && PsndDacLine <= line_last)\r
+ PsndDoDAC(line_last);\r
+\r
return 0;\r
}\r
\r
void (*PicoMessage)(const char *msg)=NULL;\r
\r
#if 1 // defined(__DEBUG_PRINT)\r
-// tmp debug: dump some stuff\r
#define bit(r, x) ((r>>x)&1)\r
void z80_debug(char *dstr);\r
char *debugString(void)\r
if(Pico.m.padDelay[1]++ > 25) Pico.m.padTHPhase[1]=0; \
}
-#define Z80_RUN(z80_cycles) \
-{ \
- if ((PicoOpt&POPT_EN_Z80) && Pico.m.z80Run) \
- { \
- int cnt; \
- if (Pico.m.z80Run & 2) z80CycleAim += z80_cycles; \
- else { \
- cnt = SekCyclesDone() - z80startCycle; \
- cnt = (cnt>>1)-(cnt>>5); \
- if (cnt < 0 || cnt > (z80_cycles)) cnt = z80_cycles; \
- Pico.m.z80Run |= 2; \
- z80CycleAim+=cnt; \
- } \
- cnt=z80CycleAim-total_z80; \
- if (cnt > 0) total_z80+=z80_run(cnt); \
- } \
-}
-
// CPUS_RUN
#ifndef PICO_CD
#define CPUS_RUN(m68k_cycles,z80_cycles,s68k_cycles) \
- SekRunM68k(m68k_cycles); \
- Z80_RUN(z80_cycles);
+ SekRunM68k(m68k_cycles);
#else
#define CPUS_RUN(m68k_cycles,z80_cycles,s68k_cycles) \
{ \
if ((Pico_mcd->m.busreq&3) == 1) /* no busreq/no reset */ \
SekRunS68k(s68k_cycles); \
} \
- Z80_RUN(z80_cycles); \
}
#endif
static int PicoFrameHints(void)
{
struct PicoVideo *pv=&Pico.video;
- int lines, y, lines_vis = 224, total_z80 = 0, z80CycleAim = 0, line_sample, skip;
+ int lines, y, lines_vis = 224, line_sample, skip;
int hint; // Hint counter
if ((PicoOpt&POPT_ALT_RENDERER) && !PicoSkipFrame && (pv->reg[1]&0x40)) { // fast rend., display enabled
else skip=PicoSkipFrame;
if (Pico.m.pal) {
- //cycles_68k = (int) ((double) OSC_PAL / 7 / 50 / 312 + 0.4); // should compile to a constant (488)
- //cycles_z80 = (int) ((double) OSC_PAL / 15 / 50 / 312 + 0.4); // 228
line_sample = 68;
if(pv->reg[1]&8) lines_vis = 240;
} else {
- //cycles_68k = (int) ((double) OSC_NTSC / 7 / 60 / 262 + 0.4); // 488
- //cycles_z80 = (int) ((double) OSC_NTSC / 15 / 60 / 262 + 0.4); // 228
line_sample = 93;
}
SekCyclesReset();
+ z80_resetCycles();
#ifdef PICO_CD
SekCyclesResetS68k();
#endif
+ timers_cycle();
+ PsndDacLine = 0;
pv->status&=~0x88; // clear V-Int, come out of vblank
//dprintf("-hint: %i", hint);
// This is to make active scan longer (needed for Double Dragon 2, mainly)
- // also trying to adjust for z80 overclock here (due to int line cycle counts)
- z80CycleAim = Pico.m.pal ? -40 : 7;
CPUS_RUN(CYCLES_M68K_ASD, 0, CYCLES_S68K_ASD);
for (y=0;y<lines_vis;y++)
}
}
- if (PicoOpt&POPT_EN_FM)
- Psnd_timers_and_dac(y);
-
#ifndef PICO_CD
// get samples from sound chips
if (y == 32 && PsndOut)
emustatus &= ~1;
else if ((y == 224 || y == line_sample) && PsndOut)
+ {
+ if (Pico.m.z80Run && (PicoOpt&POPT_EN_Z80))
+ PicoSyncZ80(SekCycleCnt);
+ if (ym2612.dacen && PsndDacLine <= y)
+ PsndDoDAC(y);
getSamples(y);
+ }
#endif
// Run scanline:
// also delay between F bit (bit 7) is set in SR and IRQ happens (Ex-Mutants)
// also delay between last H-int and V-int (Golden Axe 3)
SekRunM68k(CYCLES_M68K_VINT_LAG);
+
if (pv->reg[1]&0x20) {
elprintf(EL_INTS, "vint: @ %06x [%i]", SekPc, SekCycleCnt);
SekInterrupt(6);
}
if (Pico.m.z80Run && (PicoOpt&POPT_EN_Z80)) {
+ PicoSyncZ80(SekCycleCnt);
elprintf(EL_INTS, "zint");
z80_int();
}
- if (PicoOpt&POPT_EN_FM)
- Psnd_timers_and_dac(y);
-
// get samples from sound chips
#ifndef PICO_CD
if (y == 224)
#endif
if (PsndOut)
+ {
+ if (ym2612.dacen && PsndDacLine <= y)
+ PsndDoDAC(y);
getSamples(y);
+ }
// Run scanline:
if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA());
check_cd_dma();
#endif
- if (PicoOpt&POPT_EN_FM)
- Psnd_timers_and_dac(y);
-
// Run scanline:
if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA());
CPUS_RUN(CYCLES_M68K_LINE, CYCLES_Z80_LINE, CYCLES_S68K_LINE);
#endif
}
+ // sync z80
+ if (Pico.m.z80Run && (PicoOpt&POPT_EN_Z80))
+ PicoSyncZ80(SekCycleCnt);
+ if (PsndOut && ym2612.dacen && PsndDacLine <= lines-1)
+ PsndDoDAC(lines-1);
+
return 0;
}
SekCycleAim=0; \\r
}\r
#define SekCyclesBurn(c) SekCycleCnt+=c\r
-#define SekCyclesDone() (SekCycleAim-SekCyclesLeft) // nuber of cycles done in this frame (can be checked anywhere)\r
+#define SekCyclesDone() (SekCycleAim-SekCyclesLeft) // number of cycles done in this frame (can be checked anywhere)\r
#define SekCyclesDoneT() (SekCycleCntT+SekCyclesDone()) // total nuber of cycles done for this rom\r
\r
#define SekEndRun(after) { \\r
#if defined(_USE_MZ80)\r
#include "../cpu/mz80/mz80.h"\r
\r
-#define z80_run(cycles) mz80_run(cycles)\r
+#define z80_run(cycles) { mz80GetElapsedTicks(1); mz80_run(cycles) }\r
#define z80_run_nr(cycles) mz80_run(cycles)\r
#define z80_int() mz80int(0)\r
-#define z80_resetCycles() mz80GetElapsedTicks(1)\r
\r
#elif defined(_USE_DRZ80)\r
#include "../cpu/DrZ80/drz80.h"\r
drZ80.z80irqvector = 0xFF; /* default IRQ vector RST opcode */ \\r
drZ80.Z80_IRQ = 1; \\r
}\r
-#define z80_resetCycles()\r
+\r
+#define z80_cyclesLeft drZ80.cycles\r
\r
#elif defined(_USE_CZ80)\r
#include "../cpu/cz80/cz80.h"\r
#define z80_run(cycles) Cz80_Exec(&CZ80, cycles)\r
#define z80_run_nr(cycles) Cz80_Exec(&CZ80, cycles)\r
#define z80_int() Cz80_Set_IRQ(&CZ80, 0, HOLD_LINE)\r
-#define z80_resetCycles()\r
+\r
+#define z80_cyclesLeft (CZ80.ICount - CZ80.ExtraCycles)\r
\r
#else\r
\r
#define z80_run(cycles) (cycles)\r
#define z80_run_nr(cycles)\r
#define z80_int()\r
-#define z80_resetCycles()\r
\r
#endif\r
\r
+extern int z80stopCycle; /* in 68k cycles */\r
+extern int z80_cycle_cnt; /* 'done' z80 cycles before z80_run() */\r
+extern int z80_cycle_aim;\r
+extern int z80_scanline;\r
+extern int z80_scanline_cycles; /* cycles done until z80_scanline */\r
+\r
+#define z80_resetCycles() \\r
+ z80_cycle_cnt = z80_cycle_aim = z80_scanline = z80_scanline_cycles = 0;\r
+\r
+#define z80_cyclesDone() \\r
+ (z80_cycle_aim - z80_cyclesLeft)\r
+\r
+#define cycles_68k_to_z80(x) ((x)*957 >> 11)\r
+\r
// ---------------------------------------------------------\r
\r
// main oscillator clock which controls timing\r
#else\r
PICO_INTERNAL_ASM void z80_write(unsigned int a, unsigned char data);\r
#endif\r
+PICO_INTERNAL int ym2612_write_local(unsigned int a, unsigned int d, int is_from_z80);\r
extern unsigned int (*PicoRead16Hook)(unsigned int a, int realsize);\r
extern void (*PicoWrite8Hook) (unsigned int a,unsigned int d,int realsize);\r
extern void (*PicoWrite16Hook)(unsigned int a,unsigned int d,int realsize);\r
extern struct Pico Pico;\r
extern struct PicoSRAM SRam;\r
extern int emustatus;\r
-extern int z80startCycle, z80stopCycle; // in 68k cycles\r
extern void (*PicoResetHook)(void);\r
extern void (*PicoLineHook)(int count);\r
PICO_INTERNAL int CheckDMA(void);\r
PICO_INTERNAL void PicoDetectRegion(void);\r
+PICO_INTERNAL void PicoSyncZ80(int m68k_cycles_done);\r
\r
// cd/Pico.c\r
PICO_INTERNAL int PicoInitMCD(void);\r
extern short cdda_out_buffer[2*1152];\r
extern int PsndLen_exc_cnt;\r
extern int PsndLen_exc_add;\r
+extern int timer_a_next_oflow, timer_a_step; // in z80 cycles\r
+\r
+#define timers_cycle() \\r
+ if (timer_a_next_oflow > 0) timer_a_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256\r
+\r
+#define timers_reset() \\r
+ timer_a_next_oflow = 0x80000000\r
\r
// VideoPort.c\r
PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d);\r
\r
// sound/sound.c\r
PICO_INTERNAL void PsndReset(void);\r
-PICO_INTERNAL void Psnd_timers_and_dac(int raster);\r
+PICO_INTERNAL void PsndDoDAC(int line_to);\r
PICO_INTERNAL int PsndRender(int offset, int length);\r
PICO_INTERNAL void PsndClear(void);\r
// z80 functionality wrappers\r
PICO_INTERNAL void z80_unpack(unsigned char *data);\r
PICO_INTERNAL void z80_reset(void);\r
PICO_INTERNAL void z80_exit(void);\r
-\r
+extern int PsndDacLine;\r
\r
#ifdef __cplusplus\r
} // End of extern "C"\r
static int PsndBuffer[2*44100/50];\r
\r
// dac\r
-static unsigned short dac_info[312]; // pppppppp ppppllll, p - pos in buff, l - length to write for this sample\r
+static unsigned short dac_info[312+4]; // pppppppp ppppllll, p - pos in buff, l - length to write for this sample\r
\r
// cdda output buffer\r
short cdda_out_buffer[2*1152];\r
int PsndLen=0; // number of mono samples, multiply by 2 for stereo\r
int PsndLen_exc_add=0; // this is for non-integer sample counts per line, eg. 22050/60\r
int PsndLen_exc_cnt=0;\r
+int PsndDacLine=0;\r
short *PsndOut=NULL; // PCM data buffer\r
\r
+// timers\r
+int timer_a_next_oflow, timer_a_step; // in z80 cycles\r
+//int\r
+\r
// sn76496\r
extern int *sn76496_regs;\r
\r
if (PsndLen_exc_add) len++;\r
dac_info[224] = (pos<<4)|len;\r
}\r
+ for (i = lines; i < sizeof(dac_info) / sizeof(dac_info[0]); i++)\r
+ dac_info[i] = 0;\r
//for(i=len=0; i < lines; i++) {\r
// printf("%03i : %03i : %i\n", i, dac_info[i]>>4, dac_info[i]&0xf);\r
// len+=dac_info[i]&0xf;\r
// also clear the internal registers+addr line\r
ym2612_regs = YM2612GetRegs();\r
memset(ym2612_regs, 0, 0x200+4);\r
- z80startCycle = z80stopCycle = 0;\r
+ timers_reset();\r
\r
PsndRerate(0);\r
}\r
}\r
\r
\r
-// This is called once per raster (aka line), but not necessarily for every line\r
-PICO_INTERNAL void Psnd_timers_and_dac(int raster)\r
+PICO_INTERNAL void PsndDoDAC(int line_to)\r
{\r
- int pos, len;\r
- int do_dac = PsndOut && (PicoOpt&POPT_EN_FM) && *ym2612_dacen;\r
-// int do_pcm = PsndOut && (PicoAHW&1) && (PicoOpt&0x400);\r
-\r
- // Our raster lasts 63.61323/64.102564 microseconds (NTSC/PAL)\r
- YM2612PicoTick(1);\r
+ int pos, pos1, len;\r
+ int dout = ym2612.dacout;\r
+ int line_from = PsndDacLine;\r
\r
- if (!do_dac /*&& !do_pcm*/) return;\r
+ PsndDacLine = line_to + 1;\r
\r
- pos=dac_info[raster], len=pos&0xf;\r
+ pos =dac_info[line_from]>>4;\r
+ pos1=dac_info[line_to];\r
+ len = ((pos1>>4)-pos) + (pos1&0xf);\r
if (!len) return;\r
\r
- pos>>=4;\r
-\r
- if (do_dac)\r
- {\r
+ if (PicoOpt & POPT_EN_STEREO) {\r
short *d = PsndOut + pos*2;\r
- int dout = *ym2612_dacout;\r
- if(PicoOpt&POPT_EN_STEREO) {\r
- // some manual loop unrolling here :)\r
- d[0] = dout;\r
- if (len > 1) {\r
- d[2] = dout;\r
- if (len > 2)\r
- d[4] = dout;\r
- }\r
- } else {\r
- short *d = PsndOut + pos;\r
- d[0] = dout;\r
- if (len > 1) {\r
- d[1] = dout;\r
- if (len > 2)\r
- d[2] = dout;\r
- }\r
- }\r
+ for (; len > 0; len--, d+=2) *d = dout;\r
+ } else {\r
+ short *d = PsndOut + pos;\r
+ for (; len > 0; len--, d++) *d = dout;\r
}\r
\r
#if 0\r
#ifndef EXTERNAL_YM2612\r
#include <stdlib.h>\r
// let it be 1 global to simplify things\r
-static YM2612 ym2612;\r
+YM2612 ym2612;\r
\r
#else\r
extern YM2612 *ym2612_940;\r
/* YM2612 local section */\r
/*******************************************************************************/\r
\r
-int *ym2612_dacen;\r
-INT32 *ym2612_dacout;\r
FM_ST *ym2612_st;\r
\r
-\r
/* Generate samples for YM2612 */\r
int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty)\r
{\r
void YM2612Init_(int clock, int rate)\r
{\r
// notaz\r
- ym2612_dacen = &ym2612.dacen;\r
- ym2612_dacout = &ym2612.dacout;\r
ym2612_st = &ym2612.OPN.ST;\r
\r
memset(&ym2612, 0, sizeof(ym2612));\r
}\r
\r
addr = ym2612.OPN.ST.address;\r
-#ifndef EXTERNAL_YM2612\r
- ym2612.REGS[addr] = v;\r
-#endif\r
\r
switch( addr & 0xf0 )\r
{\r
ym2612.OPN.lfo_inc = 0;\r
}\r
break;\r
+#if 0 // handled elsewhere\r
case 0x24: { // timer A High 8\r
int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2);\r
if(ym2612.OPN.ST.TA != TAnew) {\r
set_timers( v );\r
ret=0;\r
break;\r
+#endif\r
case 0x28: /* key on / off */\r
{\r
UINT8 c;\r
if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4);\r
break;\r
}\r
+#if 0\r
case 0x2a: /* DAC data (YM2612) */\r
ym2612.dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */\r
ret=0;\r
ym2612.dacen = v & 0x80;\r
ret=0;\r
break;\r
+#endif\r
default:\r
break;\r
}\r
}\r
\r
addr = ym2612.OPN.ST.address | 0x100;\r
-#ifndef EXTERNAL_YM2612\r
- ym2612.REGS[addr] = v;\r
-#endif\r
\r
ret = OPNWriteReg(addr, v);\r
break;\r
} YM2612;\r
#endif\r
\r
-extern int *ym2612_dacen;\r
-extern INT32 *ym2612_dacout;\r
extern FM_ST *ym2612_st;\r
-\r
+#ifndef EXTERNAL_YM2612\r
+extern YM2612 ym2612;\r
+#endif\r
\r
#define YM2612Read() ym2612_st->status\r
\r
#define YM2612Init YM2612Init_\r
#define YM2612ResetChip YM2612ResetChip_\r
#define YM2612UpdateOne YM2612UpdateOne_\r
-#define YM2612Write YM2612Write_\r
#define YM2612PicoStateLoad YM2612PicoStateLoad_\r
#else\r
/* GP2X specific */\r
#define YM2612UpdateOne(buffer,length,stereo,is_buf_empty) \\r
(PicoOpt&0x200) ? YM2612UpdateOne_940(buffer, length, stereo, is_buf_empty) : \\r
YM2612UpdateOne_(buffer, length, stereo, is_buf_empty);\r
-#define YM2612Write(a,v) \\r
- (PicoOpt&0x200) ? YM2612Write_940(a, v) : YM2612Write_(a, v)\r
#define YM2612PicoStateLoad() { \\r
if (PicoOpt&0x200) YM2612PicoStateLoad_940(); \\r
else YM2612PicoStateLoad_(); \\r
}\r
\r
/* these will be managed locally on our side */\r
-static UINT8 *REGS = 0; /* we will also keep local copy of regs for savestates and such */\r
-static INT32 *addr_A1; /* address line A1 */\r
-\r
-static int dacen;\r
-static INT32 dacout;\r
static UINT8 ST_address; /* address register */\r
+static INT32 addr_A1; /* address line A1 */\r
\r
static int writebuff_ptr = 0;\r
\r
\r
-/* OPN Mode Register Write */\r
-static int set_timers( int v )\r
-{\r
- int change;\r
-\r
- /* b7 = CSM MODE */\r
- /* b6 = 3 slot mode */\r
- /* b5 = reset b */\r
- /* b4 = reset a */\r
- /* b3 = timer enable b */\r
- /* b2 = timer enable a */\r
- /* b1 = load b */\r
- /* b0 = load a */\r
- change = (ym2612_st->mode ^ v) & 0xc0;\r
- ym2612_st->mode = v;\r
-\r
- /* reset Timer b flag */\r
- if( v & 0x20 )\r
- ym2612_st->status &= ~2;\r
-\r
- /* reset Timer a flag */\r
- if( v & 0x10 )\r
- ym2612_st->status &= ~1;\r
-\r
- return change;\r
-}\r
-\r
/* YM2612 write */\r
/* a = address */\r
/* v = value */\r
/* returns 1 if sample affecting state changed */\r
-int YM2612Write_940(unsigned int a, unsigned int v)\r
+int YM2612Write_940(unsigned int a, unsigned int v, int scanline)\r
{\r
- int addr;\r
int upd = 1; /* the write affects sample generation */\r
\r
- v &= 0xff; /* adjust to 8 bit bus */\r
a &= 3;\r
\r
//printf("%05i:%03i: ym w ([%i] %02x)\n", Pico.m.frame_count, Pico.m.scanline, a, v);\r
\r
- switch( a ) {\r
- case 0: /* address port 0 */\r
- if (!*addr_A1 && ST_address == v)\r
- return 0; /* address already selected, don't send this command to 940 */\r
- ST_address = v;\r
- /* don't send DAC or timer related address changes to 940 */\r
- if (!*addr_A1 && (v & 0xf0) == 0x20 &&\r
- (v == 0x24 || v == 0x25 || v == 0x26 || v == 0x2a))\r
+ switch (a) {\r
+ case 0: /* address port 0 */\r
+ if (addr_A1 == 0 && ST_address == v)\r
+ return 0; /* address already selected, don't send this command to 940 */\r
+ ST_address = v;\r
+ addr_A1 = 0;\r
+ /* don't send DAC or timer related address changes to 940 */\r
+ if (v == 0x24 || v == 0x25 || v == 0x26 || v == 0x2a)\r
return 0;\r
- *addr_A1 = 0;\r
- upd = 0;\r
- break;\r
-\r
- case 1: /* data port 0 */\r
- if (*addr_A1 != 0) {\r
- return 0; /* verified on real YM2608 */\r
- }\r
+ upd = 0;\r
+ break;\r
\r
- addr = ST_address;\r
- REGS[addr] = v;\r
+ case 1: /* data port 0 */\r
+ if (ST_address == 0x2b) upd = 0; /* DAC sel */\r
+ break;\r
\r
- switch( addr & 0xf0 )\r
- {\r
- case 0x20: /* 0x20-0x2f Mode */\r
- switch( addr )\r
- {\r
- case 0x24: { // timer A High 8\r
- int TAnew = (ym2612_st->TA & 0x03)|(((int)v)<<2);\r
- if (ym2612_st->TA != TAnew) {\r
- // we should reset ticker only if new value is written. Outrun requires this.\r
- ym2612_st->TA = TAnew;\r
- ym2612_st->TAC = (1024-TAnew)*18;\r
- ym2612_st->TAT = 0;\r
- }\r
- return 0;\r
- }\r
- case 0x25: { // timer A Low 2\r
- int TAnew = (ym2612_st->TA & 0x3fc)|(v&3);\r
- if (ym2612_st->TA != TAnew) {\r
- ym2612_st->TA = TAnew;\r
- ym2612_st->TAC = (1024-TAnew)*18;\r
- ym2612_st->TAT = 0;\r
- }\r
- return 0;\r
- }\r
- case 0x26: // timer B\r
- if (ym2612_st->TB != v) {\r
- ym2612_st->TB = v;\r
- ym2612_st->TBC = (256-v)<<4;\r
- ym2612_st->TBC *= 18;\r
- ym2612_st->TBT = 0;\r
- }\r
- return 0;\r
- case 0x27: /* mode, timer control */\r
- if (set_timers( v ))\r
- break; // other side needs ST.mode for 3slot mode\r
- return 0;\r
- case 0x2a: /* DAC data (YM2612) */\r
- dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */\r
+ case 2: /* address port 1 */\r
+ if (addr_A1 == 1 && ST_address == v)\r
return 0;\r
- case 0x2b: /* DAC Sel (YM2612) */\r
- /* b7 = dac enable */\r
- dacen = v & 0x80;\r
- upd = 0;\r
- break; // other side has to know this\r
- default:\r
- break;\r
- }\r
+ ST_address = v;\r
+ addr_A1 = 1;\r
+ upd = 0;\r
break;\r
- }\r
- break;\r
-\r
- case 2: /* address port 1 */\r
- if (*addr_A1 && ST_address == v)\r
- return 0;\r
- ST_address = v;\r
- *addr_A1 = 1;\r
- upd = 0;\r
- break;\r
-\r
- case 3: /* data port 1 */\r
- if (*addr_A1 != 1) {\r
- return 0; /* verified on real YM2608 */\r
- }\r
-\r
- addr = ST_address | 0x100;\r
- REGS[addr] = v;\r
- break;\r
}\r
\r
//printf("ym pass\n");\r
\r
- if(currentConfig.EmuOpt & 4) {\r
+ if (currentConfig.EmuOpt & 4)\r
+ {\r
UINT16 *writebuff = shared_ctl->writebuffsel ? shared_ctl->writebuff0 : shared_ctl->writebuff1;\r
\r
/* detect rapid ym updates */\r
- if (upd && !(writebuff_ptr & 0x80000000) && Pico.m.scanline < 224) {\r
+ if (upd && !(writebuff_ptr & 0x80000000) && scanline < 224)\r
+ {\r
int mid = Pico.m.pal ? 68 : 93;\r
- if (Pico.m.scanline > mid) {\r
- //printf("%05i:%03i: rapid ym\n", Pico.m.frame_count, Pico.m.scanline);\r
+ if (scanline > mid) {\r
+ //printf("%05i:%03i: rapid ym\n", Pico.m.frame_count, scanline);\r
writebuff[writebuff_ptr++ & 0xffff] = 0xfffe;\r
writebuff_ptr |= 0x80000000;\r
- //printf("%05i:%03i: ym w ([%02x] %02x, upd=%i)\n", Pico.m.frame_count, Pico.m.scanline, addr, v, upd);\r
+ //printf("%05i:%03i: ym w ([%02x] %02x, upd=%i)\n", Pico.m.frame_count, scanline, addr, v, upd);\r
}\r
}\r
\r
\r
void YM2612PicoStateLoad_940(void)\r
{\r
- int i, old_A1 = *addr_A1;\r
+ UINT8 *REGS = YM2612GetRegs();\r
+\r
+ int i;\r
\r
/* make sure JOB940_PICOSTATELOAD gets done before next JOB940_YM2612UPDATEONE */\r
add_job_940(JOB940_PICOSTATELOAD);\r
\r
// feed all the registers and update internal state\r
for(i = 0; i < 0x100; i++) {\r
- YM2612Write_940(0, i);\r
- YM2612Write_940(1, REGS[i]);\r
+ YM2612Write_940(0, i, -1);\r
+ YM2612Write_940(1, REGS[i], -1);\r
}\r
for(i = 0; i < 0x100; i++) {\r
- YM2612Write_940(2, i);\r
- YM2612Write_940(3, REGS[i|0x100]);\r
+ YM2612Write_940(2, i, -1);\r
+ YM2612Write_940(3, REGS[i|0x100], -1);\r
}\r
\r
- *addr_A1 = old_A1;\r
+ addr_A1 = *(INT32 *) (REGS + 0x200);\r
}\r
\r
\r
static void internal_reset(void)\r
{\r
writebuff_ptr = 0;\r
- ym2612_st->mode = 0;\r
- ym2612_st->status = 0; /* normal mode */\r
- ym2612_st->TA = 0;\r
- ym2612_st->TAC = 0;\r
- ym2612_st->TAT = 0;\r
- ym2612_st->TB = 0;\r
- ym2612_st->TBC = 0;\r
- ym2612_st->TBT = 0;\r
- dacen = 0;\r
- dacout = 0;\r
- ST_address= 0;\r
+ ST_address = addr_A1 = -1;\r
}\r
\r
\r
/* cause local ym2612 to init REGS */\r
YM2612Init_(baseclock, rate);\r
\r
- REGS = YM2612GetRegs();\r
- addr_A1 = (INT32 *) (REGS + 0x200);\r
-\r
- ym2612_dacen = &dacen;\r
- ym2612_dacout = &dacout;\r
-\r
internal_reset();\r
\r
loaded_mp3 = 0;\r
return;\r
}\r
\r
+ YM2612ResetChip_();\r
internal_reset();\r
\r
add_job_940(JOB940_YM2612RESETCHIP);\r
void YM2612ResetChip_940(void);\r
int YM2612UpdateOne_940(int *buffer, int length, int stereo, int is_buf_empty);\r
\r
-int YM2612Write_940(unsigned int a, unsigned int v);\r
+int YM2612Write_940(unsigned int a, unsigned int v, int scanline);\r
unsigned char YM2612Read_940(void);\r
\r
int YM2612PicoTick_940(int n);\r
../../Pico/cd/Area.o ../../Pico/cd/Misc.o ../../Pico/cd/pcm.o ../../Pico/cd/buffering.o\r
endif\r
# Pico - Pico\r
-OBJS += ../../Pico/Pico/Pico.o ../../Pico/Pico/Memory.o\r
+OBJS += ../../Pico/Pico/Pico.o ../../Pico/Pico/Memory.o ../../Pico/Pico/xpcm.o\r
# Pico - carthw\r
OBJS += ../../Pico/carthw/carthw.o ../../Pico/carthw/svp/svp.o ../../Pico/carthw/svp/Memory.o \\r
../../Pico/carthw/svp/ssp16.o ../../Pico/carthw/svp/compiler.o ../../Pico/carthw/svp/stub_arm.o\r
../../cpu/musashi/m68kops.c :\r
@make -C ../../cpu/musashi\r
\r
+../../Pico/Pico.o : ../../Pico/PicoFrameHints.c ../../Pico/PicoInt.h\r
+../../Pico/Memory.o Pico/cd/Memory.o : ../../Pico/MemoryCmn.c ../../Pico/PicoInt.h\r
\r
# build helix libs\r
../common/helix/helix_mp3.a:\r
-#define VERSION "1.40c"\r
+#define VERSION "1.45"\r
\r
#include "../../Pico/PicoInt.h"
-static YM2612 ym2612;
-
-YM2612 *ym2612_940 = &ym2612;
-
// static _940_data_t shared_data_;
static _940_ctl_t shared_ctl_;
// static _940_data_t *shared_data = &shared_data_;
/***********************************************************/
-int YM2612Write_940(unsigned int a, unsigned int v)
+int YM2612Write_940(unsigned int a, unsigned int v, int scanline)
{
YM2612Write_(a, v);
mkdir -p $(DIRS)
Pico/carthw/svp/compiler.o : ../../Pico/carthw/svp/gen_arm.c
-
-Pico/Pico.o : ../../Pico/PicoFrameHints.c
+Pico/Pico.o : ../../Pico/PicoFrameHints.c ../../Pico/PicoInt.h
+Pico/Memory.o Pico/cd/Memory.o : ../../Pico/MemoryCmn.c ../../Pico/PicoInt.h
../../cpu/musashi/m68kops.c :
@make -C ../../cpu/musashi