Esempio n. 1
0
/////////////////////////////////////////////////////////////////////////////
//
// Upload PS-X EXE - must INCLUDE the header.
// If the header includes the strings "North America", "Japan", or "Europe",
// the appropriate refresh rate is set.
// Returns nonzero on error.
// Will return error for PS2.
//
sint32 EMU_CALL psx_upload_psxexe(void *state, void *program, uint32 size) {
  uint32 init_pc;
  uint32 init_sp;
  uint32 text_start;
  uint32 text_size;

  if(PSXSTATE->version != 1) return -1;

  if(size < 0x801) return -1;
  if(memcmp(program, "PS-X EXE", 8)) return -1;

  text_start = get32lsb(((uint8*)program) + 0x18);
  text_size  = get32lsb(((uint8*)program) + 0x1C);
  init_pc    = get32lsb(((uint8*)program) + 0x10);
  init_sp    = get32lsb(((uint8*)program) + 0x30);

  // Try to determine the region, or leave it at the default if it's not found
       if(string_exists(program, 0x800, "North America")) { psx_set_refresh(state, 60); }
  else if(string_exists(program, 0x800, "Japan"        )) { psx_set_refresh(state, 60); }
  else if(string_exists(program, 0x800, "Europe"       )) { psx_set_refresh(state, 50); }

  if(text_size > (size - 0x800)) { text_size = (size - 0x800); }

  iop_upload_to_ram(IOPSTATE, text_start, ((uint8*)program) + 0x800, text_size);

  r3000_setreg(iop_get_r3000_state(IOPSTATE), R3000_REG_PC    , init_pc);
  r3000_setreg(iop_get_r3000_state(IOPSTATE), R3000_REG_GEN+29, init_sp);

  return 0;
}
Esempio n. 2
0
void EMU_CALL psx_clear_state(void *state, uint8 version) {
  uint32 offset;
  //
  // If we haven't initialized, we really SHOULD have.
  //
  if(!library_was_initialized) psx_hang("library not initialized");

  if(version != 2) version = 1;
  // Clear local struct
  memset(state, 0, sizeof(struct PSX_STATE));
  // Set local version
  PSXSTATE->version = version;
  // Set up offsets
  offset = sizeof(struct PSX_STATE);
  if(version == 2) {
    PSXSTATE->offset_to_vfs = offset; offset += vfs_get_state_size();
  }
  PSXSTATE->offset_to_iop = offset; offset += iop_get_state_size(version);
  // Take care of VFS state
  if(HAVE_VFS) vfs_clear_state(VFSSTATE);
  // Take care of IOP state
  if(HAVE_IOP) iop_clear_state(IOPSTATE, version);
  //
  // Do some final inits
  //
  switch(version) {
  case 1:
    //
    // preboot for PS1
    //
    preboot(PSXSTATE, 0xBFC00000 | (ps1preboot & 0x003FFFFF));
    r3000_setreg(iop_get_r3000_state(IOPSTATE), R3000_REG_PC    , 0x80010000);
    r3000_setreg(iop_get_r3000_state(IOPSTATE), R3000_REG_GEN+29, 0x801FFFF0);
    break;
  case 2:
    //
    // preboot for PS2
    //
    preboot(PSXSTATE, 0xBFC00000 | (ps2preboot & 0x003FFFFF));
    //
    // simulate jr $v0 to transfer execution to loadcore
    //
    r3000_setreg(iop_get_r3000_state(IOPSTATE), R3000_REG_PC,
      r3000_getreg(iop_get_r3000_state(IOPSTATE), R3000_REG_GEN+2)
    );
    break;
  }
  // Done
}
Esempio n. 3
0
int psf1_load(void * context, const uint8_t * exe, size_t exe_size,
                                  const uint8_t * reserved, size_t reserved_size)
{
    struct psf_load_state * state = ( struct psf_load_state * ) context;

    psxexe_hdr_t *psx = (psxexe_hdr_t *) exe;

    if ( exe_size < 0x800 ) return -1;

    uint32_t addr = get_le32( &psx->exec.t_addr );
    uint32_t size = exe_size - 0x800;

    addr &= 0x1fffff;
    if ( ( addr < 0x10000 ) || ( size > 0x1f0000 ) || ( addr + size > 0x200000 ) ) return -1;

    void * pIOP = psx_get_iop_state( state->emu );
    iop_upload_to_ram( pIOP, addr, exe + 0x800, size );

    if ( !state->refresh )
    {
        if (!strncasecmp((const char *) exe + 113, "Japan", 5)) state->refresh = 60;
        else if (!strncasecmp((const char *) exe + 113, "Europe", 6)) state->refresh = 50;
        else if (!strncasecmp((const char *) exe + 113, "North America", 13)) state->refresh = 60;
    }

    if ( state->first )
    {
        void * pR3000 = iop_get_r3000_state( pIOP );
        r3000_setreg(pR3000, R3000_REG_PC, get_le32( &psx->exec.pc0 ) );
        r3000_setreg(pR3000, R3000_REG_GEN+29, get_le32( &psx->exec.s_ptr ) );
        state->first = 0;
    }

    return 0;
}
Esempio n. 4
0
static EMU_INLINE void EMU_CALL preboot(struct PSX_STATE *state, uint32 target_address) {
  sint32 r;
  for(;;) {
    uint32 s = 10000;
    r = iop_execute(IOPSTATE, state, 10000, NULL, &s, 0);
    if(r < 0) break;
    if(r3000_getreg(iop_get_r3000_state(IOPSTATE), R3000_REG_PC) == target_address) break;
  }
}