X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=Pico%2FPico.c;h=b9fbfe613dcbc6843f09ad79d6f860cf964dcb01;hb=9112b6ce9fd42ee46adb7e8148e587a7f60e35f4;hp=dcd7dd6704bc63187ec89a583d0edfd1468d5f8b;hpb=69996cb7c62468cd97842e35bdd2b74006a28dba;p=picodrive.git diff --git a/Pico/Pico.c b/Pico/Pico.c index dcd7dd6..b9fbfe6 100644 --- a/Pico/Pico.c +++ b/Pico/Pico.c @@ -16,14 +16,13 @@ int PicoOpt=0; // disable everything by default int PicoSkipFrame=0; // skip rendering frame? int PicoRegionOverride = 0; // override the region detection 0: Auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe int PicoAutoRgnOrder = 0; -int emustatus = 0; +int emustatus = 0; // rapid_ym2612, multi_ym_updates void (*PicoWriteSound)(int len) = 0; // called once per frame at the best time to send sound buffer (PsndOut) to hardware -struct PicoSRAM SRam; +struct PicoSRAM SRam = {0,}; int z80startCycle, z80stopCycle; // in 68k cycles -//int z80ExtraCycles = 0; int PicoPad[2]; // Joypads, format is SACB RLDU -int PicoMCD = 0; // mega CD status: scd_started, reset_pending +int PicoMCD = 0; // mega CD status: scd_started // to be called once on emu init int PicoInit(void) @@ -39,7 +38,6 @@ int PicoInit(void) PicoInitMCD(); SRam.data=0; - SRam.resize=1; return 0; } @@ -59,13 +57,10 @@ int PicoReset(int hard) unsigned int region=0; int support=0,hw=0,i=0; unsigned char pal=0; + unsigned char sram_reg=Pico.m.sram_reg; // must be preserved if (Pico.romsize<=0) return 1; - // setup correct memory map - if (PicoMCD & 1) - PicoMemSetupCD(); - else PicoMemSetup(); PicoMemReset(); SekReset(); // s68k doesn't have the TAS quirk, so we just globally set normal TAS handler in MCD mode (used by Batman games). @@ -149,56 +144,17 @@ int PicoReset(int hard) return 0; } - if(SRam.resize) { - int sram_size = 0; - if(SRam.data) free(SRam.data); SRam.data=0; - Pico.m.sram_reg = 0; - - if(*(Pico.rom+0x1B1) == 'R' && *(Pico.rom+0x1B0) == 'A') { - if(*(Pico.rom+0x1B2) & 0x40) { - // EEPROM - // what kind of EEPROMs are actually used? X24C02? X24C04? (X24C01 has only 128), but we will support up to 8K - SRam.start = PicoRead32(0x1B4) & ~1; // zero address is used for clock by some games - SRam.end = PicoRead32(0x1B8); - sram_size = 0x2000; - Pico.m.sram_reg = 4; - } else { - // normal SRAM - SRam.start = PicoRead32(0x1B4) & 0xFFFF00; - SRam.end = PicoRead32(0x1B8) | 1; - sram_size = SRam.end - SRam.start + 1; - } - Pico.m.sram_reg |= 0x10; // SRAM was detected - } - if(sram_size <= 0) { - // some games may have bad headers, like S&K and Sonic3 - SRam.start = 0x200000; - SRam.end = 0x203FFF; - sram_size = 0x004000; - } + // reset sram state; enable sram access by default if it doesn't overlap with ROM + Pico.m.sram_reg=sram_reg&0x14; + if (!(Pico.m.sram_reg&4) && Pico.romsize <= SRam.start) Pico.m.sram_reg |= 1; - // enable sram access by default if it doesn't overlap with ROM - if(Pico.romsize <= SRam.start) Pico.m.sram_reg |= 1; - SRam.reg_back = Pico.m.sram_reg; - - if(sram_size) { - SRam.data = (unsigned char *) calloc(sram_size, 1); - if(!SRam.data) return 1; - } - SRam.resize=0; - // Dino Dini's Soccer malfunctions if SRAM is not filled with 0xff - if (strncmp((char *)Pico.rom+0x150, "IDOND NI'I", 10) == 0) - memset(SRam.data, 0xff, sram_size); - elprintf(EL_STATUS, "sram: det: %i; eeprom: %i; start: %06x; end: %06x", - (Pico.m.sram_reg>>4)&1, (Pico.m.sram_reg>>2)&1, SRam.start, SRam.end); - } - - Pico.m.sram_reg = SRam.reg_back; // restore sram_reg - SRam.changed = 0; + elprintf(EL_STATUS, "sram: det: %i; eeprom: %i; start: %06x; end: %06x", + (Pico.m.sram_reg>>4)&1, (Pico.m.sram_reg>>2)&1, SRam.start, SRam.end); return 0; } + // dma2vram settings are just hacks to unglitch Legend of Galahad (needs <= 104 to work) // same for Outrunners (92-121, when active is set to 24) static const int dma_timings[] = { @@ -242,7 +198,7 @@ PICO_INTERNAL int CheckDMA(void) return burn; } -static __inline void SekRun(int cyc) +static __inline void SekRunM68k(int cyc) { int cyc_do; SekCycleAim+=cyc; @@ -256,12 +212,10 @@ static __inline void SekRun(int cyc) PicoCpu.cycles=cyc_do; CycloneRun(&PicoCpu); SekCycleCnt+=cyc_do-PicoCpu.cycles; -#elif defined(EMU_A68K) - m68k_ICount=cyc_do; - M68000_RUN(); - SekCycleCnt+=cyc_do-m68k_ICount; #elif defined(EMU_M68K) SekCycleCnt+=m68k_execute(cyc_do); +#elif defined(EMU_F68K) + SekCycleCnt+=m68k_emulate(cyc_do); #endif } @@ -276,12 +230,10 @@ static __inline void SekStep(void) PicoCpu.cycles=1; CycloneRun(&PicoCpu); SekCycleCnt+=1-PicoCpu.cycles; -#elif defined(EMU_A68K) - m68k_ICount=1; - M68000_RUN(); - SekCycleCnt+=1-m68k_ICount; #elif defined(EMU_M68K) SekCycleCnt+=m68k_execute(1); +#elif defined(EMU_F68K) + SekCycleCnt+=m68k_emulate(1); #endif SekCycleAim=realaim; } @@ -308,6 +260,8 @@ static int CheckIdle(void) return 0; } +void lprintf_al(const char *fmt, ...); + // to be called on 224 or line_sample scanlines only static __inline void getSamples(int y) { @@ -465,24 +419,34 @@ static int PicoFrameHints(void) #include "PicoFrameHints.c" #endif -// helper z80 runner +// helper z80 runner. Runs only if z80 is enabled at this point +// (z80WriteBusReq will handle the rest) static void PicoRunZ80Simple(int line_from, int line_to) { - int line_from_r=line_from, line_to_r=line_to, line = line_from; + int line_from_r=line_from, line_to_r=line_to, line=0; int line_sample = Pico.m.pal ? 68 : 93; - if(!(PicoOpt&4) || Pico.m.z80Run == 0) { line_from_r = line_to_r; line_to_r = 0; } + if (!(PicoOpt&4) || Pico.m.z80Run == 0) line_to_r = 0; + else { + extern const unsigned short vcounts[]; + if (z80startCycle) { + line = vcounts[z80startCycle>>8]; + if (line > line_from) + line_from_r = line; + } + z80startCycle = SekCyclesDone(); + } - if(PicoOpt&1) { + if (PicoOpt&1) { // we have ym2612 enabled, so we have to run Z80 in lines, so we could update DAC and timers - for(; line < line_to; line++) { + for (line = line_from; line < line_to; line++) { sound_timers_and_dac(line); - if((line == 224 || line == line_sample) && PsndOut) getSamples(line); - if(line == 32 && PsndOut) emustatus &= ~1; - if(line >= line_from_r && line < line_to_r) + 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); } - } else if(line_to_r-line_from_r > 0) { + } else if (line_to_r-line_from_r > 0) { z80_run(228*(line_to_r-line_from_r)); // samples will be taken by caller } @@ -495,21 +459,21 @@ static int PicoFrameSimple(void) int y=0,line=0,lines=0,lines_step=0,sects; int cycles_68k_vblock,cycles_68k_block; - if (Pico.m.pal) { - // M68k cycles/frame: 152009.78 + // split to 16 run calls for active scan, for vblank split to 2 (ntsc), 3 (pal 240), 4 (pal 224) + if (Pico.m.pal && (pv->reg[1]&8)) { // 240 lines if(pv->reg[1]&8) { // 240 lines - cycles_68k_block = (int) ((double) OSC_PAL / 7 / 50 / 312 * 15 + 0.4); // 16 sects, 16*15=240, 7308 - cycles_68k_vblock = (int) ((double) OSC_PAL / 7 / 50 / 312 * 24 + 0.4); // 3 sects, 3*24=72, 35163? + cycles_68k_block = 7329; // (488*240+148)/16.0, -4 + cycles_68k_vblock = 11640; // (72*488-148-68)/3.0, 0 lines_step = 15; } else { - cycles_68k_block = (int) ((double) OSC_PAL / 7 / 50 / 312 * 14 + 0.4); // 16*14=224 - cycles_68k_vblock = (int) ((double) OSC_PAL / 7 / 50 / 312 * 22 + 0.4); // 4 sects, 4*22=88 + cycles_68k_block = 6841; // (488*224+148)/16.0, -4 + cycles_68k_vblock = 10682; // (88*488-148-68)/4.0, 0 lines_step = 14; } } else { // M68k cycles/frame: 127840.71 - cycles_68k_block = (int) ((double) OSC_NTSC / 7 / 60 / 262 * 14 + 0.4); // 16*14=224, 6831 - cycles_68k_vblock = (int) ((double) OSC_NTSC / 7 / 60 / 262 * 19 + 0.4); // 2 sects, 2*19=38, 18544 + cycles_68k_block = 6841; // (488*224+148)/16.0, -4 + cycles_68k_vblock = 9164; // (38*488-148-68)/2.0, 0 lines_step = 14; } @@ -524,6 +488,7 @@ static int PicoFrameSimple(void) Pico.video.status|=0x200; Pico.m.scanline=-1; + z80startCycle=0; SekCyclesReset(); @@ -539,7 +504,7 @@ static int PicoFrameSimple(void) if (CheckIdle()) break; lines += lines_step; - SekRun(cycles_68k_block); + SekRunM68k(cycles_68k_block); PicoRunZ80Simple(line, lines); line=lines; @@ -549,27 +514,29 @@ static int PicoFrameSimple(void) if(sects) { int c = sects*cycles_68k_block; - lines += sects*lines_step; - PicoRunZ80Simple(line, lines); - // this is for approriate line counter, etc + // this "run" is for approriate line counter, etc SekCycleCnt += c; SekCycleAim += c; + + lines += sects*lines_step; + PicoRunZ80Simple(line, lines); } // here we render sound if ym2612 is disabled - if(!(PicoOpt&1) && PsndOut) { + if (!(PicoOpt&1) && PsndOut) { int len = sound_render(0, PsndLen); - if(PicoWriteSound) PicoWriteSound(len); + if (PicoWriteSound) PicoWriteSound(len); // clear sound buffer sound_clear(); } // render screen - if(!PicoSkipFrame) { - if(!(PicoOpt&0x10)) + if (!PicoSkipFrame) + { + if (!(PicoOpt&0x10)) // Draw the screen #if CAN_HANDLE_240_LINES - if(pv->reg[1]&8) { + if (pv->reg[1]&8) { for (y=0;y<240;y++) PicoLine(y); } else { for (y=0;y<224;y++) PicoLine(y); @@ -580,6 +547,11 @@ static int PicoFrameSimple(void) else PicoFrameFull(); } + // a gap between flags set and vint + pv->pending_ints|=0x20; + pv->status|=8; // go into vblank + SekRunM68k(68+4); + // ---- V-Blanking period ---- // fix line counts if(Pico.m.pal) { @@ -598,27 +570,24 @@ static int PicoFrameSimple(void) lines_step = 19; } - //dprintf("vint: @ %06x [%i]", SekPc, SekCycleCnt); - pv->pending_ints|=0x20; if (pv->reg[1]&0x20) SekInterrupt(6); // Set IRQ - pv->status|=8; // go into vblank - if(Pico.m.z80Run && (PicoOpt&4)) // ? + if (Pico.m.z80Run && (PicoOpt&4)) z80_int(); - while(sects) { + while (sects) { lines += lines_step; - SekRun(cycles_68k_vblock); + SekRunM68k(cycles_68k_vblock); PicoRunZ80Simple(line, lines); line=lines; sects--; - if(sects && CheckIdle()) break; + if (sects && CheckIdle()) break; } // run Z80 for remaining sections - if(sects) { + if (sects) { lines += sects*lines_step; PicoRunZ80Simple(line, lines); } @@ -665,7 +634,7 @@ void PicoFrameDrawOnly(void) // callback to output message from emu void (*PicoMessage)(const char *msg)=NULL; -#if defined(__DEBUG_PRINT) || defined(__GP2X__) +#if 1 // defined(__DEBUG_PRINT) // tmp debug: dump some stuff #define bit(r, x) ((r>>x)&1) void z80_debug(char *dstr); @@ -689,12 +658,12 @@ char *debugString(void) sprintf(dstrp, "mode set 4: %02x\n", (r=reg[0xC])); dstrp+=strlen(dstrp); sprintf(dstrp, "interlace: %i%i, cells: %i, shadow: %i\n", bit(r,2), bit(r,1), (r&0x80) ? 40 : 32, bit(r,3)); dstrp+=strlen(dstrp); - sprintf(dstrp, "scroll size: w: %i, h: %i SRAM: %i; eeprom: %i\n", reg[0x10]&3, (reg[0x10]&0x30)>>4, - bit(Pico.m.sram_reg, 4), bit(Pico.m.sram_reg, 2)); dstrp+=strlen(dstrp); + sprintf(dstrp, "scroll size: w: %i, h: %i SRAM: %i; eeprom: %i (%i)\n", reg[0x10]&3, (reg[0x10]&0x30)>>4, + bit(Pico.m.sram_reg, 4), bit(Pico.m.sram_reg, 2), SRam.eeprom_type); dstrp+=strlen(dstrp); sprintf(dstrp, "sram range: %06x-%06x, reg: %02x\n", SRam.start, SRam.end, Pico.m.sram_reg); dstrp+=strlen(dstrp); sprintf(dstrp, "pend int: v:%i, h:%i, vdp status: %04x\n", bit(pv->pending_ints,5), bit(pv->pending_ints,4), pv->status); dstrp+=strlen(dstrp); -#ifdef EMU_C68K +#if defined(EMU_C68K) sprintf(dstrp, "M68k: PC: %06x, st_flg: %x, cycles: %u\n", SekPc, PicoCpu.state_flags, SekCyclesDoneT()); dstrp+=strlen(dstrp); sprintf(dstrp, "d0=%08x, a0=%08x, osp=%08x, irql=%i\n", PicoCpu.d[0], PicoCpu.a[0], PicoCpu.osp, PicoCpu.irq); dstrp+=strlen(dstrp); @@ -702,6 +671,10 @@ char *debugString(void) for(r=2; r < 8; r++) { sprintf(dstrp, "d%i=%08x, a%i=%08x\n", r, PicoCpu.d[r], r, PicoCpu.a[r]); dstrp+=strlen(dstrp); } +#elif defined(EMU_M68K) + sprintf(dstrp, "M68k: PC: %06x, cycles: %u, irql: %i\n", SekPc, SekCyclesDoneT(), PicoM68kCPU.int_level>>8); dstrp+=strlen(dstrp); +#elif defined(EMU_F68K) + sprintf(dstrp, "M68k: PC: %06x, cycles: %u, irql: %i\n", SekPc, SekCyclesDoneT(), PicoCpuM68k.interrupts[0]); dstrp+=strlen(dstrp); #endif sprintf(dstrp, "z80Run: %i, pal: %i, frame#: %i\n", Pico.m.z80Run, Pico.m.pal, Pico.m.frame_count); dstrp+=strlen(dstrp); z80_debug(dstrp); dstrp+=strlen(dstrp);