public int sceKernelUnlockLwMutex(int workAreaAddr, int count) {
    Memory mem = Processor.memory;

    int uid = mem.read32(workAreaAddr);

    if (log.isDebugEnabled()) {
      log.debug(
          "sceKernelUnlockLwMutex (workAreaAddr=0x"
              + Integer.toHexString(workAreaAddr)
              + ", count="
              + count
              + ")");
    }

    SceKernelLwMutexInfo info = lwMutexMap.get(uid);
    if (info == null) {
      log.warn("sceKernelUnlockLwMutex unknown uid");
      return ERROR_KERNEL_LWMUTEX_NOT_FOUND;
    }
    if (info.lockedCount == 0) {
      log.debug("sceKernelUnlockLwMutex not locked");
      return ERROR_KERNEL_LWMUTEX_UNLOCKED;
    }
    if (info.lockedCount < 0) {
      log.warn("sceKernelUnlockLwMutex underflow");
      return ERROR_KERNEL_LWMUTEX_UNLOCK_UNDERFLOW;
    }

    info.lockedCount -= count;
    if (info.lockedCount == 0) {
      onLwMutexModified(info);
    }

    return 0;
  }
  public int sceKernelReferLwMutexStatus(int workAreaAddr, int addr) {
    Memory mem = Processor.memory;

    int uid = mem.read32(workAreaAddr);

    if (log.isDebugEnabled()) {
      log.debug(
          "sceKernelReferLwMutexStatus (workAreaAddr=0x"
              + Integer.toHexString(workAreaAddr)
              + ", addr=0x"
              + addr
              + ")");
    }

    SceKernelLwMutexInfo info = lwMutexMap.get(uid);
    if (info == null) {
      log.warn("sceKernelReferLwMutexStatus unknown UID " + Integer.toHexString(uid));
      return ERROR_KERNEL_LWMUTEX_NOT_FOUND;
    }
    if (!Memory.isAddressGood(addr)) {
      log.warn("sceKernelReferLwMutexStatus bad address 0x" + Integer.toHexString(addr));
      return -1;
    }

    info.write(mem, addr);

    return 0;
  }
예제 #3
0
  @HLEFunction(nid = 0x4C06E472, version = 150)
  public int sceGeContinue() {
    PspGeList list;
    if (ExternalGE.isActive()) {
      list = ExternalGE.getCurrentList();
    } else {
      list = VideoEngine.getInstance().getCurrentList();
    }

    if (list != null) {
      synchronized (this) {
        if (list.status == PSP_GE_LIST_END_REACHED) {
          Memory mem = Memory.getInstance();
          if (mem.read32(list.getPc()) == (GeCommands.FINISH << 24)
              && mem.read32(list.getPc() + 4) == (GeCommands.END << 24)) {
            list.readNextInstruction();
            list.readNextInstruction();
          }
        }
        list.restartList();
      }
    }

    return 0;
  }
  public int sceKernelTryLockLwMutex(int workAreaAddr, int count) {
    Memory mem = Processor.memory;

    int uid = mem.read32(workAreaAddr);

    if (log.isDebugEnabled()) {
      log.debug("sceKernelTryLockLwMutex redirecting to hleKernelLockLwMutex");
    }
    return hleKernelLockLwMutex(uid, count, 0, false, false);
  }
  public int sceKernelLockLwMutexCB(int workAreaAddr, int count, int timeout_addr) {
    Memory mem = Processor.memory;

    int uid = mem.read32(workAreaAddr);

    if (log.isDebugEnabled()) {
      log.debug("sceKernelLockLwMutexCB redirecting to hleKernelLockLwMutex");
    }
    return hleKernelLockLwMutex(uid, count, timeout_addr, true, true);
  }
예제 #6
0
  protected int copySamplesToMem(int address) {
    Memory mem = Memory.getInstance();

    int bytes = me.getCurrentAudioSamples(samplesBuffer);
    if (bytes > 0) {
      atracEndSample += bytes;
      mem.copyToMemory(address, ByteBuffer.wrap(samplesBuffer, 0, bytes), bytes);
    }

    return bytes / bytesPerSample;
  }
예제 #7
0
  public static void init() {
    if (!isInitialized) {
      List<String> libraries = new LinkedList<String>();
      if (NativeCpuInfo.isAvailable()) {
        NativeCpuInfo.init();
        if (NativeCpuInfo.hasAVX2()) {
          libraries.add("software-ge-renderer-AVX2");
        }
        if (NativeCpuInfo.hasAVX()) {
          libraries.add("software-ge-renderer-AVX");
        }
        if (NativeCpuInfo.hasSSE41()) {
          libraries.add("software-ge-renderer-SSE41");
        }
        if (NativeCpuInfo.hasSSE3()) {
          libraries.add("software-ge-renderer-SSE3");
        }
        if (NativeCpuInfo.hasSSE2()) {
          libraries.add("software-ge-renderer-SSE2");
        }
      }
      libraries.add("software-ge-renderer");

      boolean libraryExisting = false;
      // Search for an available library in preference order
      for (String library : libraries) {
        if (Utilities.isSystemLibraryExisting(library)) {
          libraryExisting = true;
          try {
            System.loadLibrary(library);
            if (Memory.getInstance() instanceof FastMemory) {
              memoryInt = ((FastMemory) Memory.getInstance()).getAll();
            }
            initNative();
            log.info(String.format("Loaded %s library", library));
            isAvailable = true;
          } catch (UnsatisfiedLinkError e) {
            log.error(String.format("Could not load external software library %s: %s", library, e));
            isAvailable = false;
          }
          break;
        }
      }
      if (!libraryExisting) {
        log.error(String.format("Missing external software library"));
      }

      isInitialized = true;
    }
  }
  public CaptureRAM(int address, int length) throws IOException {
    packetSize = 8 + length;
    this.address = address;
    this.length = length;

    Memory mem = Memory.getInstance();
    if (Memory.isAddressGood(address)) {
      buffer = mem.getBuffer(address, length);
    }

    if (buffer == null) {
      throw new IOException(
          String.format(
              "CaptureRAM: Unable to read buffer %08x - %08x", address, address + length));
    }
  }
예제 #9
0
  public int getAddress(Memory mem, int i) {
    if (ptr_index != 0 && index != 0) {
      int addr = ptr_index + i * index;
      switch (index) {
        case 1:
          i = mem.read8(addr);
          break; // GU_INDEX_8BIT
        case 2:
          i = mem.read16(addr);
          break; // GU_INDEX_16BIT
        case 3:
          i = mem.read32(addr);
          break; // GU_INDEX_UNK3 (assume 32bit)
      }
    }

    return ptr_vertex + i * vertexSize;
  }
예제 #10
0
  @Override
  public void resolve(Memory mem, int address) {
    if (!hasSavedValue) {
      savedValue = mem.read32(getImportAddress());
      hasSavedValue = true;
    }

    // Perform a R_MIPS_32 relocation

    // Retrieve the current 32bit value
    int value = mem.read32(getImportAddress());

    // Relocate the value
    value += address;

    // Write back the relocated 32bit value
    mem.write32(getImportAddress(), value);
  }
예제 #11
0
  public static Memory getInstance() {
    if (instance == null) {
      //
      // The following memory implementations are available:
      // - StandardMemory:  low memory requirements, performs address checking, slow
      // - SafeFastMemory: high memory requirements, performs address checking, fast
      // - FastMemory    : high memory requirements, no address checking, very fast
      //
      // Best choices are currently
      // 1) SafeFastMemory (address check is useful when debugging programs)
      // 2) StandardMemory when available memory is not sufficient for 1st choice
      //
      if (useSafeMemory) {
        instance = new SafeFastMemory();
      } else {
        instance = new FastMemory();
      }

      if (instance != null) {
        if (!instance.allocate()) {
          instance = null;
        }
      }

      if (instance == null) {
        instance = new StandardMemory();
        if (!instance.allocate()) {
          instance = null;
        }
      }

      if (instance == null) {
        throw new OutOfMemoryError("Cannot allocate memory");
      }

      if (useDebuggerMemory || new File(DebuggerMemory.mBrkFilePath).exists()) {
        DebuggerMemory.install();
      }

      log.debug("Using " + instance.getClass().getName());
    }

    return instance;
  }
  public int sceKernelDeleteLwMutex(int workAreaAddr) {
    Memory mem = Processor.memory;

    int uid = mem.read32(workAreaAddr);

    if (log.isDebugEnabled()) {
      log.debug("sceKernelDeleteLwMutex (workAreaAddr='" + Integer.toHexString(workAreaAddr) + ")");
    }

    SceKernelLwMutexInfo info = lwMutexMap.remove(uid);
    if (info == null) {
      log.warn("sceKernelDeleteLwMutex unknown UID " + Integer.toHexString(uid));
      return ERROR_KERNEL_LWMUTEX_NOT_FOUND;
    }

    mem.write32(workAreaAddr, 0); // Clear uid.
    onLwMutexDeleted(uid);

    return 0;
  }
예제 #13
0
  @Override
  public void unresolve(Memory mem) {
    if (hasSavedValue) {
      mem.write32(getImportAddress(), savedValue);
    }

    if (sourceModule != null) {
      // Add this stub back to the list of unresolved imports from the source module
      sourceModule.unresolvedImports.add(this);
    }
  }
  /**
   * @return the UID assigned to the module or negative on error TODO need to figure out how the
   *     uids work when 1 prx contains several modules.
   */
  public int LoadFlash0Module(String prxname) {
    if (prxname != null) {
      List<HLEModule> modules = flash0prxMap.get(prxname.toLowerCase());
      if (modules != null) {
        for (HLEModule module : modules) {
          installModuleWithAnnotations(module, firmwareVersion);
        }
      }
    }

    SceModule fakeModule = new SceModule(true);
    fakeModule.modname = prxname;
    fakeModule.write(Memory.getInstance(), fakeModule.address);
    Managers.modules.addModule(fakeModule);

    return fakeModule.modid;
  }
예제 #15
0
  public void setMemorySize(int memorySize) {
    if (MemoryMap.SIZE_RAM != memorySize) {
      int previousMemorySize = MemoryMap.SIZE_RAM;
      MemoryMap.END_RAM = MemoryMap.START_RAM + memorySize - 1;
      MemoryMap.END_USERSPACE = MemoryMap.END_RAM;
      MemoryMap.SIZE_RAM = MemoryMap.END_RAM - MemoryMap.START_RAM + 1;

      if (!Memory.getInstance().allocate()) {
        log.error(
            String.format(
                "Failed to resize the PSP memory from 0x%X to 0x%X",
                previousMemorySize, memorySize));
        Emulator.PauseEmuWithStatus(Emulator.EMU_STATUS_MEM_ANY);
      }

      reset();
    }
  }
 public void commit() {
   Memory.getInstance().copyToMemory(address, (ByteBuffer) buffer, length);
 }
예제 #17
0
  public int atracDecodeData(int atracID, int address, int channels) {
    int samples = 0;
    boolean isEnded = false;

    if (checkMediaEngineState()) {
      if (me.getContainer() == null && atracChannel != null) {
        if (requireAllAtracData) {
          if (atracChannel.length() >= atracFileSize) {
            requireAllAtracData = false;
            if (checkMediaEngineState() && ExternalDecoder.isEnabled()) {
              String decodedFile =
                  externalDecoder.decodeAtrac(
                      atracChannel, atracBufferAddress, atracFileSize, atracHash);
              if (decodedFile != null) {
                Modules.log.info(
                    "AT3+ data decoded by the external decoder (all AT3+ data retrieved).");
                me.finish();
                atracChannel = null;
                me.init(new FileProtocolHandler(decodedFile), false, true, 0, 0);
                atracEndSample = -1;
              } else {
                Modules.log.info(
                    "AT3+ data could not be decoded by the external decoder, even after retrieving all AT3+ data.");
                me = null;
              }
            } else {
              Modules.log.info(
                  "AT3+ data could not be decoded by the external decoder, even after retrieving all AT3+ data.");
              me = null;
            }
            if (me == null) {
              return atracDecodeData(atracID, address, channels);
            }
          } else {
            // Fake returning 1 sample with remainFrames == 0
            // to force a call to sceAtracAddStreamData.
            samples = 1;
            Memory.getInstance().memset(address, (byte) 0, samples * bytesPerSample);
          }
        } else if (atracChannel.length() >= getAtracChannelStartLength()
            || atracChannel.length() >= atracFileSize) {
          me.init(atracChannel, false, true, 0, 0);
        } else {
          // Fake returning 1 sample with remainFrames == 0
          // to force a call to sceAtracAddStreamData.
          samples = 1;
          Memory.getInstance().memset(address, (byte) 0, samples * bytesPerSample);
        }
      }
      setChannels(channels);
      if (me.stepAudio(atracMaxSamples * bytesPerSample, channels)) {
        samples = copySamplesToMem(address);
      }
      if (samples == 0) {
        isEnded = true;
      }
    } else if (decodedStream != null) {
      try {
        int length = decodedStream.read(atracDecodeBuffer);
        if (length > 0) {
          samples = length / 4;
          Memory.getInstance()
              .copyToMemory(address, ByteBuffer.wrap(atracDecodeBuffer, 0, length), length);
          long restLength = decodedStream.length() - decodedStream.getFilePointer();
          if (restLength <= 0) {
            isEnded = true;
          }
        } else {
          isEnded = true;
        }
      } catch (IOException e) {
        Modules.log.warn(e);
      }
    } else {
      samples = -1;
      isEnded = true;
    }

    if (isEnded) {
      atracEnd = 1;
    } else {
      atracEnd = 0;
    }

    return samples;
  }
예제 #18
0
  public void atracSetData(
      int atracID, int codecType, int address, int length, int atracFileSize, int atracHash) {
    this.atracFileSize = atracFileSize;
    this.atracBufferAddress = address;
    this.atracHash = atracHash;
    id = generateID(address, length, atracFileSize);
    closeStreams();
    atracEndSample = -1;
    requireAllAtracData = false;

    int memoryCodecType = sceAtrac3plus.getCodecType(address);
    if (memoryCodecType != codecType && memoryCodecType != 0) {
      Modules.log.info(
          String.format(
              "Different CodecType received %d != %d, assuming %d",
              codecType, memoryCodecType, memoryCodecType));
      codecType = memoryCodecType;
    }

    if (codecType == 0x00001001) {
      Modules.log.info("Decodable AT3 data detected.");
      if (checkMediaEngineState()) {
        me.finish();
        atracChannel = new PacketChannel();
        atracChannel.setTotalStreamSize(atracFileSize);
        atracChannel.setFarRewindAllowed(true);
        atracChannel.write(address, length);
        // Defer the initialization of the MediaEngine until atracDecodeData()
        // to ensure we have enough data into the channel.
        atracEndSample = 0;
        return;
      }
    } else if (codecType == 0x00001000) {
      if (checkMediaEngineState() && ExternalDecoder.isEnabled()) {
        String decodedFile =
            externalDecoder.decodeAtrac(address, length, atracFileSize, atracHash, this);
        if (decodedFile != null) {
          Modules.log.info("AT3+ data decoded by the external decoder.");
          me.finish();
          atracChannel = null;
          me.init(new FileProtocolHandler(decodedFile), false, true, 0, 0);
          atracEndSample = -1;
          return;
        } else if (requireAllAtracData) {
          // The external decoder requires all the atrac data
          // before it can try to decode the atrac.
          me.finish();
          atracChannel = new PacketChannel();
          atracChannel.setTotalStreamSize(atracFileSize);
          atracChannel.write(address, length);
          return;
        }
        Modules.log.info("AT3+ data could not be decoded by the external decoder.");
      } else {
        Modules.log.info("Undecodable AT3+ data detected.");
      }
    }
    me = null;

    File decodedFile = new File(getCompleteFileName(decodedAtracSuffix));

    if (!decodedFile.canRead()) {
      // Try to read the decoded file using an alternate file name,
      // without HashCode. These files can be generated by external tools
      // decoding the Atrac3+ files. These tools can't generate the HashCode.
      //
      // Use the following alternate file name scheme:
      //       Atrac-SSSSSSSS-NNNNNNNN-DDDDDDDD.at3.decoded
      // where SSSSSSSS is the file size in Hex
      //       NNNNNNNN is the number of samples in Hex found in the "fact" Chunk
      //       DDDDDDDD are the first 32-bit in Hex found in the "data" Chunk
      int numberOfSamples = 0;
      int data = 0;

      // Scan the Atrac data for NNNNNNNN and DDDDDDDD values
      Memory mem = Memory.getInstance();
      int scanAddress = address + 12;
      int endScanAddress = address + length;
      while (scanAddress < endScanAddress) {
        int chunkHeader = mem.read32(scanAddress);
        int chunkSize = mem.read32(scanAddress + 4);

        if (chunkHeader == waveFactChunkHeader) {
          numberOfSamples = mem.read32(scanAddress + 8);
        } else if (chunkHeader == waveDataChunkHeader) {
          data = mem.read32(scanAddress + 8);
          break;
        }

        // Go to the next Chunk
        scanAddress += chunkSize + 8;
      }

      File alternateDecodedFile =
          new File(
              String.format(
                  "%sAtrac-%08X-%08X-%08X%s",
                  getBaseDirectory(), atracFileSize, numberOfSamples, data, decodedAtracSuffix));
      if (alternateDecodedFile.canRead()) {
        decodedFile = alternateDecodedFile;
      }
    }

    File atracFile = new File(getCompleteFileName(atracSuffix));
    if (decodedFile.canRead()) {
      try {
        decodedStream = new RandomAccessFile(decodedFile, "r");
        atracEndSample = (int) (decodedFile.length() / 4);
      } catch (FileNotFoundException e) {
        // Decoded file should already be present
        Modules.log.warn(e);
      }
    } else if (atracFile.canRead() && atracFile.length() == atracFileSize) {
      // Atrac file is already written, no need to write it again
    } else if (sceAtrac3plus.isEnableConnector()) {
      commandFileDirty = true;
      displayInstructions();
      new File(getBaseDirectory()).mkdirs();

      try {
        atracStream = new FileOutputStream(getCompleteFileName(atracSuffix));
        byte[] buffer = new byte[length];
        IMemoryReader memoryReader = MemoryReader.getMemoryReader(address, length, 1);
        for (int i = 0; i < length; i++) {
          buffer[i] = (byte) memoryReader.readNext();
        }
        atracStream.write(buffer);
      } catch (IOException e) {
        Modules.log.warn(e);
      }
      generateCommandFile();
    }
  }