Example #1
0
void MDFNSS_LoadSM(Stream *st, bool data_only)
{
	if(MDFN_LIKELY(data_only))
	{
	 StateMem sm(st);
	 MDFN_StateAction(&sm, MEDNAFEN_VERSION_NUMERIC, true);
	 sm.ThrowDeferred();
	}
	else
	{
         uint8 header[32];
	 uint32 width, height, preview_len;
  	 uint32 stateversion;
	 uint32 total_len;
	 int64 start_pos;
	 bool svbe;

	 start_pos = st->tell();
         st->read(header, 32);

         if(memcmp(header, "MEDNAFENSVESTATE", 16) && memcmp(header, "MDFNSVST", 8))
	  throw MDFN_Error(0, _("Missing/Wrong save state header ID."));

	 stateversion = MDFN_de32lsb(header + 16);
	 total_len = MDFN_de32lsb(header + 20) & 0x7FFFFFFF;
         svbe = MDFN_de32lsb(header + 20) & 0x80000000;
         width = MDFN_de32lsb(header + 24);
         height = MDFN_de32lsb(header + 28);
	 preview_len = width * height * 3;

	 if((int)stateversion < 0x900)	// Ensuring that (int)stateversion is > 0 is the most important part.
	  throw MDFN_Error(0, _("Invalid/Unsupported version in save state header."));

	 st->seek(preview_len, SEEK_CUR);				// Skip preview

	 StateMem sm(st, start_pos + total_len, svbe);
	 MDFN_StateAction(&sm, stateversion, false);			// Load state data.
	 sm.ThrowDeferred();

	 st->seek(start_pos + total_len, SEEK_SET);			// Seek to just beyond end of save state before returning.
	}
}
Example #2
0
INLINE void PS_CPU::WriteMemory(pscpu_timestamp_t &timestamp, uint32 address, uint32 value, bool DS24)
{
 if(MDFN_LIKELY(!(CP0.SR & 0x10000)))
 {
  if(sizeof(T) == 1)
   PSX_MemWrite8(timestamp, address, value);
  else if(sizeof(T) == 2)
   PSX_MemWrite16(timestamp, address, value);
  else
  {
   if(DS24)
    PSX_MemWrite24(timestamp, address, value);
   else
    PSX_MemWrite32(timestamp, address, value);
  }
 }
 else
 {
#if PS_CPU_EMULATE_ICACHE
  if(BIU & 0x800)	// Instruction cache is enabled/active
  {
   if(BIU & 0x4)	// TAG test mode.
   {
    // TODO: Respect written value.
    __ICache *ICI = &ICache[((address & 0xFF0) >> 2)];
    const uint8 valid_bits = 0x00;

    ICI[0].TV = ((valid_bits & 0x01) ? 0x00 : 0x02) | ((BIU & 0x800) ? 0x0 : 0x1);
    ICI[1].TV = ((valid_bits & 0x02) ? 0x00 : 0x02) | ((BIU & 0x800) ? 0x0 : 0x1);
    ICI[2].TV = ((valid_bits & 0x04) ? 0x00 : 0x02) | ((BIU & 0x800) ? 0x0 : 0x1);
    ICI[3].TV = ((valid_bits & 0x08) ? 0x00 : 0x02) | ((BIU & 0x800) ? 0x0 : 0x1);
   }
   else if(!(BIU & 0x1))
   {
    ICache[(address & 0xFFC) >> 2].Data = value << ((address & 0x3) * 8);
   }
Example #3
0
//
// Remember to handle an end condition on the same iteration of the while(DMACH[ch].ClockCounter > 0) loop that caused it,
// otherwise RecalcHalt() might take the CPU out of a halted state before the end-of-DMA is signaled(especially a problem considering our largeish
// DMA update timing granularity).
//
static INLINE void RunChannelI(const unsigned ch, const uint32_t CRModeCache, int32_t clocks)
{
   //const uint32_t dc = (DMAControl >> (ch * 4)) & 0xF;

   DMACH[ch].ClockCounter += clocks;

   while(MDFN_LIKELY(DMACH[ch].ClockCounter > 0))
   {
      if(DMACH[ch].WordCounter == 0)	// Begin WordCounter reload.
      {
         if(!(DMACH[ch].ChanControl & (1 << 24)))	// Needed for the forced-DMA-stop kludge(see DMA_Write()).
            break;

         if(!ChCan(ch, CRModeCache))
            break;

         DMACH[ch].CurAddr = DMACH[ch].BaseAddr;

         if(CRModeCache & (1U << 10))
         {
            uint32_t header;

            if(MDFN_UNLIKELY(DMACH[ch].CurAddr & 0x800000))
            {
               DMACH[ch].ChanControl &= ~(0x11 << 24);
               DMAIntControl |= 0x8000;
               RecalcIRQOut();
               break;
            }

            header = MainRAM.ReadU32(DMACH[ch].CurAddr & 0x1FFFFC);
            DMACH[ch].CurAddr = (DMACH[ch].CurAddr + 4) & 0xFFFFFF;

            DMACH[ch].WordCounter = header >> 24;
            DMACH[ch].BaseAddr = header & 0xFFFFFF;

            // printf to debug Soul Reaver ;)
            //if(DMACH[ch].WordCounter > 0x10) 
            // printf("What the lala?  0x%02x @ 0x%08x\n", DMACH[ch].WordCounter, DMACH[ch].CurAddr - 4);

            if(DMACH[ch].WordCounter)
               DMACH[ch].ClockCounter -= 15;
            else
               DMACH[ch].ClockCounter -= 10;

            goto SkipPayloadStuff;	// 3 cheers for gluten-free spaghetticode(necessary because the newly-loaded WordCounter might be 0, and we actually
            // want 0 to mean 0 and not 65536 in this context)!
         }
         else
         {
            DMACH[ch].WordCounter = DMACH[ch].BlockControl & 0xFFFF;

            if(CRModeCache & (1U << 9))
            {
               if(ch == 2)	// Technically should apply to all channels, but since we don't implement CPU read penalties for channels other than 2 yet, it's like this to avoid making DMA longer than what games can handle.
                  DMACH[ch].ClockCounter -= 7;

               DMACH[ch].BlockControl = (DMACH[ch].BlockControl & 0xFFFF) | ((DMACH[ch].BlockControl - (1U << 16)) & 0xFFFF0000);
            }
         }
      }	// End WordCounter reload.
Example #4
0
//
// When updating this function make sure to adhere to the guarantees in state.h.
//
bool MDFNSS_StateAction(StateMem *sm, const unsigned load, const bool data_only, SFORMAT *sf, const char *sname, const bool optional) noexcept
{
 //printf("Section: %s %zu\n", sname, strlen(sname));

 if(MDFN_UNLIKELY(sm->deferred_error))
 {
  return(load ? false : true);
 }

 try
 {
  Stream* st = sm->st;

  if(MDFN_LIKELY(data_only))	// Not particularly likely, but it's more important to optimize for this code path...
  {
   static const uint8 SSFastCanary[8] = { 0x42, 0xA3, 0x10, 0x87, 0xBC, 0x6D, 0xF2, 0x79 };
   char sname_canary[32 + 8];

   if(load)
   {
    st->read(sname_canary, 32 + 8);

    if(strncmp(sname_canary, sname, 32))
     throw MDFN_Error(0, _("Section name mismatch in state loading fast path."));

    if(memcmp(sname_canary + 32, SSFastCanary, 8))
     throw MDFN_Error(0, _("Section canary is a zombie AAAAAAAAAAGH!"));

    FastRWChunk<true>(st, sf);
   }
   else
   {
    memset(sname_canary, 0, sizeof(sname_canary));
    strncpy(sname_canary, sname, 32);
    memcpy(sname_canary + 32, SSFastCanary, 8);
    st->write(sname_canary, 32 + 8);

    FastRWChunk<false>(st, sf);
   }
  }
  else
  {
   if(load)
   {
    char sname_tmp[32];
    bool found = false;
    uint32 tmp_size;
    uint32 total = 0;

    while(st->tell() < sm->sss_bound)
    {
     st->read(sname_tmp, 32);
     tmp_size = st->get_LE<uint32>();

     total += tmp_size + 32 + 4;

     // Yay, we found the section
     if(!strncmp(sname_tmp, sname, 32))
     {
      ReadStateChunk(st, sf, tmp_size, sm->svbe);
      found = true;
      break;
     } 
     else
     {
      st->seek(tmp_size, SEEK_CUR);
     }
    }

    st->seek(-(int64)total, SEEK_CUR);

    if(!found)
    {
     if(optional)
     {
      printf("Missing optional section: %.32s\n", sname);
      return(false);
     }
     else
      throw MDFN_Error(0, _("Section missing: %.32s"), sname);
    }
   }
   else
   {
    int64 data_start_pos;
    int64 end_pos;
    uint8 sname_tmp[32];

    memset(sname_tmp, 0, sizeof(sname_tmp));
    strncpy((char *)sname_tmp, sname, 32);

    if(strlen(sname) > 32)
     printf("Warning: section name is too long: %s\n", sname);

    st->write(sname_tmp, 32);

    st->put_LE<uint32>(0);                // We'll come back and write this later.

    data_start_pos = st->tell();
    SubWrite(st, sf);
    end_pos = st->tell();

    st->seek(data_start_pos - 4, SEEK_SET);
    st->put_LE<uint32>(end_pos - data_start_pos);
    st->seek(end_pos, SEEK_SET);
   }
  }
 }
 catch(...)
 {
  sm->deferred_error = std::current_exception();
  return(load ? false : true);
 }
 return(true);
}
Example #5
0
sscpu_timestamp_t Update(sscpu_timestamp_t timestamp)
{
 if(MDFN_UNLIKELY(timestamp < lastts))
 {
  // Don't else { } normal execution, since this bug condition miiight occur in the call from SetHBVB(),
  // and we need drawing to start ASAP before silly games overwrite the beginning of the command table.
  //
  SS_DBGTI(SS_DBG_WARNING | SS_DBG_VDP1, "[VDP1] [BUG] timestamp(%d) < lastts(%d)", timestamp, lastts);
  timestamp = lastts;
 }
 //
 // 
 //
 int32 cycles = timestamp - lastts;
 lastts = timestamp;

 CycleCounter += cycles;
 if(CycleCounter > VDP1_UpdateTimingGran)
  CycleCounter = VDP1_UpdateTimingGran;

 if(CycleCounter > 0 && SCU_CheckVDP1HaltKludge())
 {
  //puts("Kludge");
  CycleCounter = 0;
 }
 else if(DrawingActive)
 {
  while(CycleCounter > 0)
  {
   uint16 cmd_data[0x10];

   // Fetch command data
   memcpy(cmd_data, &VRAM[CurCommandAddr], sizeof(cmd_data));
   CycleCounter -= 16;

   //SS_DBGTI(SS_DBG_WARNING | SS_DBG_VDP1, "[VDP1] Command @ 0x%06x: 0x%04x\n", CurCommandAddr, cmd_data[0]);

   if(MDFN_LIKELY(!(cmd_data[0] & 0xC000)))
   {
    const unsigned cc = cmd_data[0] & 0xF;

    if(MDFN_UNLIKELY(cc >= 0xC))
    {
     DrawingActive = false;
     break;
    }
    else
    {
     static int32 (*const command_table[0xC])(const uint16* cmd_data) =
     {
      /* 0x0 */         /* 0x1 */         /* 0x2 */            /* 0x3 */
      CMD_NormalSprite, CMD_ScaledSprite, CMD_DistortedSprite, CMD_DistortedSprite,

      /* 0x4 */    /* 0x5 */     /* 0x6 */ /* 0x7 */
      CMD_Polygon, CMD_Polyline, CMD_Line, CMD_Polyline,

      /* 0x8*/         /* 0x9 */           /* 0xA */          /* 0xB */
      CMD_SetUserClip, CMD_SetSystemClip,  CMD_SetLocalCoord, CMD_SetUserClip
     };

     CycleCounter -= command_table[cc](cmd_data);
    }
   }
   else if(MDFN_UNLIKELY(cmd_data[0] & 0x8000))
   {
    SS_DBGTI(SS_DBG_VDP1, "[VDP1] Drawing finished at 0x%05x", CurCommandAddr);
    DrawingActive = false;

    EDSR |= 0x2;	// TODO: Does EDSR reflect IRQ out status?

    SCU_SetInt(SCU_INT_VDP1, true);
    SCU_SetInt(SCU_INT_VDP1, false);
    break;
   }

   CurCommandAddr = (CurCommandAddr + 0x10) & 0x3FFFF;
   switch((cmd_data[0] >> 12) & 0x3)
   {
    case 0:
	break;

    case 1:
	CurCommandAddr = (cmd_data[1] << 2) &~ 0xF;
	break;

    case 2:
	if(RetCommandAddr < 0)
	 RetCommandAddr = CurCommandAddr;

	CurCommandAddr = (cmd_data[1] << 2) &~ 0xF;
	break;

    case 3:
	if(RetCommandAddr >= 0)
	{
	 CurCommandAddr = RetCommandAddr;
	 RetCommandAddr = -1;
	}
	break;
   }
  }
 }

 return timestamp + (DrawingActive ? std::max<int32>(VDP1_UpdateTimingGran, 0 - CycleCounter) : VDP1_IdleTimingGran);
}