diff --git a/Makefile.libretro b/Makefile.libretro index 9effd3c8..aa20d456 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -281,12 +281,9 @@ else ifeq ($(platform), wiiu) CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - CFLAGS += -DGEKKO -DWIIU -DHW_RVL -mwup -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST + CFLAGS += -DGEKKO -DWIIU -DHW_RVL -DHW_WUP -mwup -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST STATIC_LINKING = 1 NO_MMAP = 1 - # Wii U has memory mapped in a way not suitable for DRC - use_sh2drc = 0 - use_svpdrc = 0 # Nintendo Switch (libtransistor) else ifeq ($(platform), switch) diff --git a/cpu/cz80/cz80.c b/cpu/cz80/cz80.c index 41d58199..888478ef 100644 --- a/cpu/cz80/cz80.c +++ b/cpu/cz80/cz80.c @@ -196,7 +196,7 @@ void Cz80_Init(cz80_struc *CPU) CPU->pzR16[0] = pzBC; CPU->pzR16[1] = pzDE; CPU->pzR16[2] = pzHL; - CPU->pzR16[3] = pzAF; + CPU->pzR16[3] = pzFA; zIX = zIY = 0xffff; @@ -339,13 +339,13 @@ UINT32 Cz80_Get_Reg(cz80_struc *CPU, INT32 regnum) { case CZ80_PC: return (CPU->PC - CPU->BasePC); case CZ80_SP: return zSP; - case CZ80_AF: return zAF; + case CZ80_FA: return zFA; case CZ80_BC: return zBC; case CZ80_DE: return zDE; case CZ80_HL: return zHL; case CZ80_IX: return zIX; case CZ80_IY: return zIY; - case CZ80_AF2: return zAF2; + case CZ80_FA2: return zFA2; case CZ80_BC2: return zBC2; case CZ80_DE2: return zDE2; case CZ80_HL2: return zHL2; @@ -378,13 +378,13 @@ void Cz80_Set_Reg(cz80_struc *CPU, INT32 regnum, UINT32 val) break; case CZ80_SP: zSP = val; break; - case CZ80_AF: zAF = val; break; + case CZ80_FA: zFA = val; break; case CZ80_BC: zBC = val; break; case CZ80_DE: zDE = val; break; case CZ80_HL: zHL = val; break; case CZ80_IX: zIX = val; break; case CZ80_IY: zIY = val; break; - case CZ80_AF2: zAF2 = val; break; + case CZ80_FA2: zFA2 = val; break; case CZ80_BC2: zBC2 = val; break; case CZ80_DE2: zDE2 = val; break; case CZ80_HL2: zHL2 = val; break; diff --git a/cpu/cz80/cz80.h b/cpu/cz80/cz80.h index a49d1f18..894ef5c3 100644 --- a/cpu/cz80/cz80.h +++ b/cpu/cz80/cz80.h @@ -79,12 +79,12 @@ extern "C" { #define zR8(A) (*CPU->pzR8[A]) #define zR16(A) (CPU->pzR16[A]->W) -#define pzAF &(CPU->AF) -#define zAF CPU->AF.W -#define zlAF CPU->AF.B.L -#define zhAF CPU->AF.B.H -#define zA zhAF -#define zF zlAF +#define pzFA &(CPU->FA) +#define zFA CPU->FA.W +#define zlFA CPU->FA.B.L +#define zhFA CPU->FA.B.H +#define zA zlFA +#define zF zhFA #define pzBC &(CPU->BC) #define zBC CPU->BC.W @@ -107,11 +107,11 @@ extern "C" { #define zH zhHL #define zL zlHL -#define zAF2 CPU->AF2.W -#define zlAF2 CPU->AF2.B.L -#define zhAF2 CPU->AF2.B.H -#define zA2 zhAF2 -#define zF2 zlAF2 +#define zFA2 CPU->FA2.W +#define zlFA2 CPU->FA2.B.L +#define zhFA2 CPU->FA2.B.H +#define zA2 zhFA2 +#define zF2 zlFA2 #define zBC2 CPU->BC2.W #define zDE2 CPU->DE2.W @@ -187,13 +187,13 @@ enum { CZ80_PC = 1, CZ80_SP, - CZ80_AF, + CZ80_FA, CZ80_BC, CZ80_DE, CZ80_HL, CZ80_IX, CZ80_IY, - CZ80_AF2, + CZ80_FA2, CZ80_BC2, CZ80_DE2, CZ80_HL2, @@ -232,7 +232,7 @@ typedef struct cz80_t union16 BC; union16 DE; union16 HL; - union16 AF; + union16 FA; }; }; @@ -244,7 +244,7 @@ typedef struct cz80_t union16 BC2; union16 DE2; union16 HL2; - union16 AF2; + union16 FA2; union16 R; union16 IFF; diff --git a/cpu/cz80/cz80_op.c b/cpu/cz80/cz80_op.c index a46210e6..cf3062e2 100644 --- a/cpu/cz80/cz80_op.c +++ b/cpu/cz80/cz80_op.c @@ -200,9 +200,15 @@ OP_LD_mNN_xx: POP -----------------------------------------*/ + OP(0xf1): // POP AF +OP_POP_AF: + POP_16(res) + zA = res >> 8; + zF = res & 0xFF; + RET(10) + OP(0xc1): // POP BC OP(0xd1): // POP DE - OP(0xf1): // POP AF OP_POP_RR: data = CPU->pzR16[(Opcode >> 4) & 3]; @@ -215,9 +221,14 @@ OP_POP: PUSH -----------------------------------------*/ + OP(0xf5): // PUSH AF +OP_PUSH_AF: + PUSH_16((zA << 8) | zF); + RET(11) + + OP(0xc5): // PUSH BC OP(0xd5): // PUSH DE - OP(0xf5): // PUSH AF OP_PUSH_RR: data = CPU->pzR16[(Opcode >> 4) & 3]; @@ -232,9 +243,9 @@ OP_PUSH: OP(0x08): // EX AF,AF' OP_EX_AF_AF2: - res = zAF; - zAF = zAF2; - zAF2 = res; + res = zFA; + zFA = zFA2; + zFA2 = res; RET(4) OP(0xeb): // EX DE,HL diff --git a/cpu/cz80/cz80_opXY.c b/cpu/cz80/cz80_opXY.c index b02e4011..a73c3fc9 100644 --- a/cpu/cz80/cz80_opXY.c +++ b/cpu/cz80/cz80_opXY.c @@ -194,8 +194,9 @@ switch (Opcode) OPXY(0xc1): // POP BC OPXY(0xd1): // POP DE - OPXY(0xf1): // POP AF goto OP_POP_RR; + OPXY(0xf1): // POP AF + goto OP_POP_AF; OPXY(0xe1): // POP IX goto OP_POP; @@ -206,8 +207,9 @@ switch (Opcode) OPXY(0xc5): // PUSH BC OPXY(0xd5): // PUSH DE - OPXY(0xf5): // PUSH AF goto OP_PUSH_RR; + OPXY(0xf5): // PUSH AF + goto OP_PUSH_AF; OPXY(0xe5): // PUSH IX goto OP_PUSH; diff --git a/pico/mode4.c b/pico/mode4.c index 9ae8b713..06c15c61 100644 --- a/pico/mode4.c +++ b/pico/mode4.c @@ -428,17 +428,18 @@ static void DrawSpritesTMS(int scanline) if (sat[MEM_LE2(i+3)] & 0x80) x -= 32; c = sat[MEM_LE2(i+3)] & 0x0f; + // c may be 0 (transparent): sprite invisible if (x > 0) { pack = PicoMem.vramb[MEM_LE2(sprites_addr[s])]; - if (zoomed) TileDoubleSprTMS(x, pack, c); - else TileNormSprTMS(x, pack, c); - if (!m) m = CollisionDetect(mb, x, pack, zoomed); + if (zoomed && c) TileDoubleSprTMS(x, pack, c); + else if (c) TileNormSprTMS(x, pack, c); + if (!m) m = CollisionDetect(mb, x, pack, zoomed); } if((pv->reg[1] & 0x2) && (x+=w) > 0) { pack = PicoMem.vramb[MEM_LE2(sprites_addr[s]+0x10)]; - if (zoomed) TileDoubleSprTMS(x, pack, c); - else TileNormSprTMS(x, pack, c); - if (!m) m = CollisionDetect(mb, x, pack, zoomed); + if (zoomed && c) TileDoubleSprTMS(x, pack, c); + else if (c) TileNormSprTMS(x, pack, c); + if (!m) m = CollisionDetect(mb, x, pack, zoomed); } } if (m) @@ -615,6 +616,7 @@ void PicoFrameStartSMS(void) void PicoLineSMS(int line) { int skip = skip_next_line; + unsigned bgcolor; // GG LCD, render only visible part of screen if ((Pico.m.hardware & 0x3) == 0x3 && (line < 24 || line >= 24+144)) @@ -629,7 +631,8 @@ void PicoLineSMS(int line) } // Draw screen: - BackFill(Pico.video.reg[7] & 0x0f, 0, &Pico.est); + bgcolor = (Pico.video.reg[7] & 0x0f) | ((Pico.video.reg[0] & 0x04) << 2); + BackFill(bgcolor, 0, &Pico.est); // bgcolor is from 2nd palette in mode 4 if (Pico.video.reg[1] & 0x40) { if (Pico.video.reg[0] & 0x04) DrawDisplayM4(line); else if (Pico.video.reg[0] & 0x02) DrawDisplayM2(line); @@ -649,8 +652,13 @@ norender: /* Fixed palette for TMS9918 modes */ static u16 tmspal[32] = { +#if 1 // SMS palette 0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0, 0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff, +#else // TMS palette + 0x0000, 0x0000, 0x04c2, 0x07d5, 0x0e55, 0x0f77, 0x045d, 0x0fe4, + 0x055f, 0x077f, 0x05cd, 0x08ce, 0x03b2, 0x0b5c, 0x0ccc, 0x0fff, +#endif }; void PicoDoHighPal555SMS(void) @@ -668,15 +676,11 @@ void PicoDoHighPal555SMS(void) if (FinalizeLineSMS == FinalizeLineRGB555SMS) spal = (void *)PicoMem.cram; - // fixed palette in TMS modes - if (!(Pico.video.reg[0] & 0x4)) { - spal = (u32 *)tmspal; - cnt = 1; - } - /* SMS 6 bit cram data was already converted to MD/GG format by vdp write, * hence GG/SMS/TMS can all be handled the same here */ for (j = cnt; j > 0; j--) { + if (!(Pico.video.reg[0] & 0x4)) + spal = (u32 *)tmspal; // fixed palette in TMS modes for (i = 0x20/2; i > 0; i--, spal++, dpal++) { t = *spal; #if defined(USE_BGR555) diff --git a/pico/sms.c b/pico/sms.c index 9f70a408..48806989 100644 --- a/pico/sms.c +++ b/pico/sms.c @@ -10,7 +10,6 @@ * TODO: * - start in a state as if BIOS ran * - region support - * - H counter */ #include "pico_int.h" #include "memory.h" @@ -164,7 +163,7 @@ static unsigned char z80_sms_in(unsigned short a) break; case 0x41: /* H counter */ - d = Pico.ms.vdp_hlatch; + d = Pico.ms.vdp_hlatch; elprintf(EL_HVCNT, "H counter read: %02x", d); break; @@ -178,15 +177,13 @@ static unsigned char z80_sms_in(unsigned short a) case 0xc0: /* I/O port A and B */ d = ~((PicoIn.pad[0] & 0x3f) | (PicoIn.pad[1] << 6)); - if (Pico.ms.io_ctl & 0x01) d &= ~0x20; break; case 0xc1: /* I/O port B and miscellaneous */ d = (Pico.ms.io_ctl & 0x80) | ((Pico.ms.io_ctl << 1) & 0x40) | 0x30; d |= ~(PicoIn.pad[1] >> 2) & 0x0f; - if (Pico.ms.io_ctl & 0x08) d &= ~0x80; - if (Pico.ms.io_ctl & 0x04) d &= ~0x08; - if (Pico.ms.io_ctl & 0x02) d &= ~0x40; + if (Pico.ms.io_ctl & 0x08) d |= 0x80; // TH as input is unconnected + if (Pico.ms.io_ctl & 0x02) d |= 0x40; break; } } @@ -244,7 +241,7 @@ static void z80_sms_out(unsigned short a, unsigned char d) case 0x40: case 0x41: - PsndDoPSG(Pico.m.scanline*228 + 228-z80_cyclesLeft); + PsndDoPSG(z80_cyclesDone()); SN76496Write(d); break; @@ -276,7 +273,7 @@ static void write_sram(unsigned short a, unsigned char d) // 16KB bank mapping for Sega mapper static void write_bank_sega(unsigned short a, unsigned char d) { - if (Pico.ms.mapper != 1 && d == 0) return; + if (Pico.ms.mapper != 1 && (Pico.ms.mapper || d == 0)) return; elprintf(EL_Z80BNK, "bank 16k %04x %02x @ %04x", a, d, z80_pc()); Pico.ms.mapper = 1; Pico.ms.carthw[a & 0x0f] = d; @@ -313,7 +310,7 @@ static void write_bank_sega(unsigned short a, unsigned char d) // 8KB ROM mapping for MSX mapper static void write_bank_msx(unsigned short a, unsigned char d) { - if (Pico.ms.mapper != 2 && (a|d) == 0) return; + if (Pico.ms.mapper != 2 && (Pico.ms.mapper || (a|d) == 0)) return; elprintf(EL_Z80BNK, "bank 8k %04x %02x @ %04x", a, d, z80_pc()); Pico.ms.mapper = 2; // TODO define (more) mapper types Pico.ms.carthw[a] = d; @@ -323,6 +320,17 @@ static void write_bank_msx(unsigned short a, unsigned char d) z80_map_set(z80_read_map, a, a+0x1fff, Pico.rom + (d << 13), 0); } +static void write_bank_32k(unsigned short a, unsigned char d) +{ + if (Pico.ms.mapper != 3 && (Pico.ms.mapper || z80_pc() < 0xc000)) return; + elprintf(EL_Z80BNK, "bank 32k %04x %02x @ %04x", a, d, z80_pc()); + Pico.ms.mapper = 3; // TODO define (more) mapper types + Pico.ms.carthw[0xf] = d; + + d &= bank_mask >> 1; + z80_map_set(z80_read_map, 0, 0x7fff, Pico.rom + (d << 15), 0); +} + // TODO mapping is currently auto-selecting, but that's not very reliable. static void xwrite(unsigned int a, unsigned char d) { @@ -330,21 +338,25 @@ static void xwrite(unsigned int a, unsigned char d) if (a >= 0xc000) PicoMem.zram[a & 0x1fff] = d; + // korean 32k. 1 selectable 32KB bank at the bottom + if (a == 0xffff) + write_bank_32k(a, d); // Sega. Maps 4 bank 16KB each - if (a >= 0xfff8 && Pico.ms.mapper != 2) + if (a >= 0xfff8) write_bank_sega(a, d); // Codemasters. Similar to Sega, but different addresses -// if (a == 0x0000 && Pico.ms.mapper != 2) +// NB mapping on 0x0000 collides with MSX mapper, but AFAICT CM isn't using it +// if (a == 0x0000) // write_bank_sega(0xfffd, d); - if (a == 0x4000 && Pico.ms.mapper != 2) + if (a == 0x4000) write_bank_sega(0xfffe, d); - if (a == 0x8000 && Pico.ms.mapper != 2) + if (a == 0x8000) write_bank_sega(0xffff, d); // Korean. 1 selectable 16KB bank at the top - if (a == 0xa000 && Pico.ms.mapper != 2) + if (a == 0xa000) write_bank_sega(0xffff, d); // MSX. 4 selectable 8KB banks at the top - if (a <= 0x0003 && Pico.ms.mapper != 1) + if (a <= 0x0003) write_bank_msx(a, d); } @@ -376,7 +388,7 @@ void PicoResetMS(void) // reset memory mapping PicoMemSetupMS(); - // BIOS values for VDP initialisation + // BIOS, VDP intialisation Pico.video.reg[0] = 0x36; Pico.video.reg[1] = 0xa0; Pico.video.reg[2] = 0xff; @@ -388,6 +400,9 @@ void PicoResetMS(void) Pico.video.reg[8] = 0x00; Pico.video.reg[9] = 0x00; Pico.video.reg[10] = 0xff; + + // BIOS, clean zram + memset(PicoMem.zram, 0, sizeof(PicoMem.zram)); } void PicoPowerMS(void) @@ -399,9 +414,6 @@ void PicoPowerMS(void) memset(&Pico.m,0,sizeof(Pico.m)); Pico.m.pal = 0; - for (s = 0; s < sizeof(PicoMem.zram); s++) - PicoMem.zram[s] = rand(); - // calculate a mask for bank writes. // ROM loader has aligned the size for us, so this is safe. s = 0; tmp = Pico.romsize; @@ -442,6 +454,8 @@ void PicoMemSetupMS(void) xwrite(0x0001, 0); xwrite(0x0002, 0); xwrite(0x0003, 0); + } else if (Pico.ms.mapper == 3) { + xwrite(0xffff, 0); } else { xwrite(0xfffc, 0); xwrite(0xfffd, 0); @@ -459,6 +473,8 @@ void PicoStateLoadedMS(void) xwrite(0x0001, Pico.ms.carthw[1]); xwrite(0x0002, Pico.ms.carthw[2]); xwrite(0x0003, Pico.ms.carthw[3]); + } else if (Pico.ms.mapper == 3) { + xwrite(0xffff, Pico.ms.carthw[0x0f]); } else { xwrite(0xfffc, Pico.ms.carthw[0x0c]); xwrite(0xfffd, Pico.ms.carthw[0x0d]); @@ -515,7 +531,7 @@ void PicoFrameMS(void) if ((pv->reg[0] & 0x10) && (pv->pending_ints & 2)) { elprintf(EL_INTS, "hint"); z80_int_assert(1); - } + } pv->pending_ints &= ~2; } } diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index ea640c22..4a12c686 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -572,8 +572,12 @@ void plat_munmap(void *ptr, size_t size) void *plat_mem_get_for_drc(size_t size) { void *mem = NULL; -#ifdef VITA +#if defined VITA sceKernelGetMemBlockBase(sceBlock, &mem); +#elif defined HW_WUP + // For WiiU, a slice of RWX memory left from the exploit is used, see: + // https://github.com/embercold/pcsx_rearmed/commit/af0453223 + mem = (void *)(0x01000000 - size); #endif return mem; }