static void S9xEndScreenRefresh (void) { FLUSH_REDRAW(); PPU.GunVLatch = 1000; /* i.e., never latch */ PPU.GunHLatch = 0; if (!Settings.NormalControls && pad_read) S9xControlEOF(); pad_read = FALSE; if(Settings.SpeedhackGameID > SPEEDHACK_NONE) speedhacks_manager(); if (!(GFX.DoInterlace && GFX.InterlaceFrame == 0)) S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); S9xApplyCheats(); }
void S9xDoDMA (uint8 Channel) { uint8 Work; if (Channel > 7 || CPU.InDMA) return; CPU.InDMA = TRUE; bool8 in_sa1_dma = FALSE; uint8 *in_sdd1_dma = NULL; SDMA *d = &DMA[Channel]; int count = d->TransferBytes; if (count == 0) count = 0x10000; int inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); switch (d->BAddress) { case 0x18: case 0x19: if (IPPU.RenderThisFrame) FLUSH_REDRAW (); break; } if (Settings.SDD1) { if (d->AAddressFixed && Memory.FillRAM [0x4801] > 0) { // Hacky support for pre-decompressed S-DD1 data inc = !d->AAddressDecrement ? 1 : -1; uint32 address = (((d->ABank << 16) | d->AAddress) & 0xfffff) << 4; address |= Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)]; if(Settings.SDD1Pack) { uint8* in_ptr=GetBasePointer(((d->ABank << 16) | d->AAddress)); in_ptr+=d->AAddress; SDD1_decompress(buffer,in_ptr,d->TransferBytes); in_sdd1_dma=buffer; } else { void *ptr = bsearch (&address, Memory.SDD1Index, Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); if (ptr) in_sdd1_dma = *(uint32 *) ((uint8 *) ptr + 4) + Memory.SDD1Data; /* if (!in_sdd1_dma) { // No matching decompressed data found. Must be some new // graphics not encountered before. Log it if it hasn't been // already. uint8 *p = Memory.SDD1LoggedData; bool8 found = FALSE; uint8 SDD1Bank = Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)] | 0xf0; for (uint32 i = 0; i < Memory.SDD1LoggedDataCount; i++, p += 8) { if (*p == d->ABank || *(p + 1) == (d->AAddress >> 8) && *(p + 2) == (d->AAddress & 0xff) && *(p + 3) == (count >> 8) && *(p + 4) == (count & 0xff) && *(p + 7) == SDD1Bank) { found = TRUE; break; } } if (!found && Memory.SDD1LoggedDataCount < MEMMAP_MAX_SDD1_LOGGED_ENTRIES) { *p = d->ABank; *(p + 1) = d->AAddress >> 8; *(p + 2) = d->AAddress & 0xff; *(p + 3) = count >> 8; *(p + 4) = count & 0xff; *(p + 7) = SDD1Bank; Memory.SDD1LoggedDataCount += 1; } */ } } Memory.FillRAM [0x4801] = 0; }
void S9xSetPPU (uint8 Byte, uint16 Address) { // MAP_PPU: $2000-$3FFF if (CPU.InDMAorHDMA) { if (CPU.CurrentDMAorHDMAChannel >= 0 && DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer) { // S9xSetPPU() is called to write to DMA[].AAddress if ((Address & 0xff00) == 0x2100) { // Cannot access to Address Bus B ($2100-$21ff) via (H)DMA return; } else { // 0x2000-0x3FFF is connected to Address Bus A // SA1, SuperFX and SRTC are mapped here // I don't bother for now... return; } } else { // S9xSetPPU() is called to read from $21xx // Take care of DMA wrapping if (Address > 0x21ff) Address = 0x2100 + (Address & 0xff); } } #ifdef DEBUGGER if (CPU.InHDMA) S9xTraceFormattedMessage("--- HDMA PPU %04X -> %02X", Address, Byte); #endif if (Settings.MSU1 && (Address & 0xfff8) == 0x2000) // MSU-1 S9xMSU1WritePort(Address & 7, Byte); else if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3 // write_port will run the APU until given clock before writing value S9xAPUWritePort(Address & 3, Byte); else if (Address <= 0x2183) { switch (Address) { case 0x2100: // INIDISP if (Byte != Memory.FillRAM[0x2100]) { FLUSH_REDRAW(); if (PPU.Brightness != (Byte & 0xf)) { IPPU.ColorsChanged = TRUE; IPPU.DirectColourMapsNeedRebuild = TRUE; PPU.Brightness = Byte & 0xf; S9xFixColourBrightness(); if (PPU.Brightness > IPPU.MaxBrightness) IPPU.MaxBrightness = PPU.Brightness; } if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80)) { IPPU.ColorsChanged = TRUE; PPU.ForcedBlanking = (Byte >> 7) & 1; } } if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) { PPU.OAMAddr = PPU.SavedOAMAddr; uint8 tmp = 0; if (PPU.OAMPriorityRotation) tmp = (PPU.OAMAddr & 0xfe) >> 1; if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp) { PPU.FirstSprite = tmp; IPPU.OBJChanged = TRUE; } PPU.OAMFlip = 0; }
bool8 S9xDoDMA (uint8 Channel) { CPU.InDMA = TRUE; CPU.InDMAorHDMA = TRUE; CPU.CurrentDMAorHDMAChannel = Channel; SDMA *d = &DMA[Channel]; // Check invalid DMA first if ((d->ABank == 0x7E || d->ABank == 0x7F) && d->BAddress == 0x80 && !d->ReverseTransfer) { // Attempting a DMA from WRAM to $2180 will not work, WRAM will not be written. // Attempting a DMA from $2180 to WRAM will similarly not work, // the value written is (initially) the OpenBus value. // In either case, the address in $2181-3 is not incremented. // Does an invalid DMA actually take time? // I'd say yes, since 'invalid' is probably just the WRAM chip // not being able to read and write itself at the same time // And no, PPU.WRAM should not be updated. int32 c = d->TransferBytes; // Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. if (c == 0) c = 0x10000; // 8 cycles per channel ADD_CYCLES(SLOW_ONE_CYCLE); // 8 cycles per byte while (c) { d->TransferBytes--; d->AAddress++; c--; if (!addCyclesInDMA(Channel)) { CPU.InDMA = FALSE; CPU.InDMAorHDMA = FALSE; CPU.CurrentDMAorHDMAChannel = -1; return (FALSE); } } #ifdef DEBUGGER if (Settings.TraceDMA) { sprintf(String, "DMA[%d]: WRAM Bank:%02X->$2180", Channel, d->ABank); S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); } #endif CPU.InDMA = FALSE; CPU.InDMAorHDMA = FALSE; CPU.CurrentDMAorHDMAChannel = -1; return (TRUE); } // Prepare for accessing $2118-2119 switch (d->BAddress) { case 0x18: case 0x19: if (IPPU.RenderThisFrame) FLUSH_REDRAW(); break; } int32 inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); int32 count = d->TransferBytes; // Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. if (count == 0) count = 0x10000; // Prepare for custom chip DMA // S-DD1 uint8 *in_sdd1_dma = NULL; if (Settings.SDD1) { if (d->AAddressFixed && Memory.FillRAM[0x4801] > 0) { // XXX: Should probably verify that we're DMAing from ROM? // And somewhere we should make sure we're not running across a mapping boundary too. // Hacky support for pre-decompressed S-DD1 data inc = !d->AAddressDecrement ? 1 : -1; uint8 *in_ptr = S9xGetBasePointer(((d->ABank << 16) | d->AAddress)); if (in_ptr) { in_ptr += d->AAddress; SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes); } #ifdef DEBUGGER else { sprintf(String, "S-DD1: DMA from non-block address $%02X:%04X", d->ABank, d->AAddress); S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); } #endif in_sdd1_dma = sdd1_decode_buffer; } Memory.FillRAM[0x4801] = 0; } // SPC7110 uint8 *spc7110_dma = NULL; if (Settings.SPC7110) { if (d->AAddress == 0x4800 || d->ABank == 0x50) { spc7110_dma = new uint8[d->TransferBytes]; for (int i = 0; i < d->TransferBytes; i++) spc7110_dma[i] = s7emu.decomp.read(); int32 icount = s7emu.r4809 | (s7emu.r480a << 8); icount -= d->TransferBytes; s7emu.r4809 = icount & 0x00ff; s7emu.r480a = (icount & 0xff00) >> 8; inc = 1; d->AAddress -= count; } }