bool Mp3PspStream::initStreamME() { // The following will eventually go into the thread memset(_codecParams, 0, sizeof(_codecParams)); // Init the MP3 hardware int ret = 0; ret = sceAudiocodecCheckNeedMem(_codecParams, 0x1002); if (ret < 0) { PSP_ERROR("failed to init MP3 ME module. sceAudiocodecCheckNeedMem returned 0x%x.\n", ret); return false; } PSP_DEBUG_PRINT("sceAudiocodecCheckNeedMem returned %d\n", ret); ret = sceAudiocodecGetEDRAM(_codecParams, 0x1002); if (ret < 0) { PSP_ERROR("failed to init MP3 ME module. sceAudiocodecGetEDRAM returned 0x%x.\n", ret); return false; } PSP_DEBUG_PRINT("sceAudioCodecGetEDRAM returned %d\n", ret); PSP_DEBUG_PRINT("samplerate[%d]\n", _sampleRate); _codecParams[10] = _sampleRate; ret = sceAudiocodecInit(_codecParams, 0x1002); if (ret < 0) { PSP_ERROR("failed to init MP3 ME module. sceAudiocodecInit returned 0x%x.\n", ret); return false; } return true; }
void *VramAllocator::allocate(int32 size, bool smallAllocation /* = false */) { DEBUG_ENTER_FUNC(); assert(size > 0); byte *lastAddress = smallAllocation ? (byte *)VRAM_SMALL_ADDRESS : (byte *)VRAM_START_ADDRESS; Common::List<Allocation>::iterator i; // Find a block that fits, starting from the beginning for (i = _allocList.begin(); i != _allocList.end(); ++i) { byte *currAddress = (*i).address; if (currAddress - lastAddress >= size) // We found a match break; if ((*i).getEnd() > lastAddress) lastAddress = (byte *)(*i).getEnd(); } if (lastAddress + size > (byte *)VRAM_END_ADDRESS) { PSP_DEBUG_PRINT("No space for allocation of %d bytes. %d bytes already allocated.\n", size, _bytesAllocated); return NULL; } _allocList.insert(i, Allocation(lastAddress, size)); _bytesAllocated += size; PSP_DEBUG_PRINT("Allocated in VRAM, size %u at %p.\n", size, lastAddress); PSP_DEBUG_PRINT("Total allocated %u, remaining %u.\n", _bytesAllocated, (2 * 1024 * 1024) - _bytesAllocated); return lastAddress; }
// return true if we really rendered or no dirty. False otherwise bool DisplayManager::renderAll() { DEBUG_ENTER_FUNC(); #ifdef USE_DISPLAY_CALLBACK if (!_masterGuRenderer.isRenderFinished()) { PSP_DEBUG_PRINT("Callback render not finished.\n"); return false; // didn't render } #endif /* USE_DISPLAY_CALLBACK */ // This is cheaper than checking time, so we do it first // Any one of these being dirty causes everything to draw if (!_screen->isDirty() && !_overlay->isDirty() && !_cursor->isDirty() && !_keyboard->isDirty() && !_imageViewer->isDirty()) { PSP_DEBUG_PRINT("Nothing dirty\n"); return true; // nothing to render } if (!isTimeToUpdate()) return false; // didn't render PSP_DEBUG_PRINT("dirty: screen[%s], overlay[%s], cursor[%s], keyboard[%s], imageViewer[%s]\n", _screen->isDirty() ? "true" : "false", _overlay->isDirty() ? "true" : "false", _cursor->isDirty() ? "true" : "false", _keyboard->isDirty() ? "true" : "false", _imageViewer->isDirty() ? "true" : "false", ); _masterGuRenderer.guPreRender(); // Set up rendering _screen->render(); _screen->setClean(); // clean out dirty bit if (_imageViewer->isVisible()) _imageViewer->render(); _imageViewer->setClean(); if (_overlay->isVisible()) _overlay->render(); _overlay->setClean(); if (_cursor->isVisible()) _cursor->render(); _cursor->setClean(); if (_keyboard->isVisible()) _keyboard->render(); _keyboard->setClean(); _masterGuRenderer.guPostRender(); return true; // rendered successfully }
bool PspAudio::open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, callbackFunc callback, void *userData) { DEBUG_ENTER_FUNC(); if (_init) { PSP_ERROR("audio device already initialized\n"); return true; } PSP_DEBUG_PRINT("freq[%d], numOfChannels[%d], numOfSamples[%d], callback[%p], userData[%x]\n", freq, numOfChannels, numOfSamples, callback, (uint32)userData); numOfSamples = PSP_AUDIO_SAMPLE_ALIGN(numOfSamples); uint32 bufLen = numOfSamples * numOfChannels * NUM_BUFFERS * sizeof(uint16); PSP_DEBUG_PRINT("total buffer size[%d]\n", bufLen); _buffers[0] = (byte *)memalign(64, bufLen); if (!_buffers[0]) { PSP_ERROR("failed to allocate memory for audio buffers\n"); return false; } memset(_buffers[0], 0, bufLen); // clean the buffer // Fill in the rest of the buffer pointers byte *pBuffer = _buffers[0]; for (int i = 1; i < NUM_BUFFERS; i++) { pBuffer += numOfSamples * numOfChannels * sizeof(uint16); _buffers[i] = pBuffer; } // Reserve a HW channel for our audio _pspChannel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, numOfSamples, numOfChannels == 2 ? PSP_AUDIO_FORMAT_STEREO : PSP_AUDIO_FORMAT_MONO); if (_pspChannel < 0) { PSP_ERROR("failed to reserve audio channel\n"); return false; } PSP_DEBUG_PRINT("reserved channel[%d] for audio\n", _pspChannel); // Save our data _numOfChannels = numOfChannels; _numOfSamples = numOfSamples; _bufferSize = numOfSamples * numOfChannels * sizeof(uint16); // should be the right size to send the app _callback = callback; _userData = userData; _bufferToFill = 0; _bufferToPlay = 0; _init = true; _paused = true; // start in paused mode threadCreateAndStart("audioThread", PRIORITY_AUDIO_THREAD, STACK_AUDIO_THREAD); // start the consumer thread return true; }
/* Function to open the file pointed to by the path. * */ void *PspIoStream::open() { DEBUG_ENTER_FUNC(); if (PowerMan.beginCriticalSection()) { // No need to open? Just return the _handle resume() already opened PSP_DEBUG_PRINT_FUNC("suspended\n"); } _handle = sceIoOpen(_path.c_str(), _writeMode ? PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC : PSP_O_RDONLY, 0777); if (!_handle) { _error = true; _handle = NULL; } // Get the file size. This way is much faster than going to the end of the file and back SceIoStat stat; sceIoGetstat(_path.c_str(), &stat); _fileSize = *((uint32 *)(void *)&stat.st_size); // 4GB file (32 bits) is big enough for us PSP_DEBUG_PRINT("%s filesize[%d]\n", _path.c_str(), _fileSize); PowerMan.registerForSuspend(this); // Register with the powermanager to be suspended PowerMan.endCriticalSection(); return (void *)_handle; }
bool PngLoader::load() { DEBUG_ENTER_FUNC(); // Try to load the image _file.seek(0); // Go back to start if (!loadImageIntoBuffer()) { PSP_DEBUG_PRINT("failed to load image\n"); return false; } PSP_DEBUG_PRINT("succeded in loading image\n"); if (_paletteSize == 16) // 4-bit _buffer->flipNibbles(); // required because of PNG 4-bit format return true; }
// Sleep on the render mutex if the rendering thread hasn't finished its work // void MasterGuRenderer::sleepUntilRenderFinished() { if (!isRenderFinished()) { _renderSema.take(); // sleep on the semaphore _renderSema.give(); PSP_DEBUG_PRINT("slept on the rendering semaphore\n"); } }
void PspMemory::copy(byte *dst, const byte *src, uint32 bytes) { DEBUG_ENTER_FUNC(); #ifdef TEST_MEMORY_COPY uint32 debugBytes = bytes; const byte *debugDst = dst, *debugSrc = src; #endif PSP_DEBUG_PRINT("copy(): dst[%p], src[%p], bytes[%d]\n", dst, src, bytes); // align the destination pointer first uint32 prefixDst = (((uint32)dst) & 0x3); if (prefixDst) { prefixDst = 4 - prefixDst; // prefix only if we have address % 4 != 0 PSP_DEBUG_PRINT("prefixDst[%d]\n", prefixDst); bytes -= prefixDst; // remember we assume bytes >= 4 if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) { // check if it's worthwhile to continue copy8(dst, src, bytes + prefixDst); #ifdef TEST_MEMORY_COPY testCopy(debugDst, debugSrc, debugBytes); #endif return; } while (prefixDst--) { *dst++ = *src++; } } // check the source pointer alignment now uint32 alignSrc = (((uint32)src) & 0x3); if (alignSrc) { // we'll need to realign our reads copy32Misaligned((uint32 *)dst, src, bytes, alignSrc); } else { copy32Aligned((uint32 *)dst, (uint32 *)src, bytes); } #ifdef TEST_MEMORY_COPY testCopy(debugDst, debugSrc, debugBytes); #endif }
// Deallocate a block from VRAM void VramAllocator::deallocate(void *address) { DEBUG_ENTER_FUNC(); address = (byte *)CACHED(address); // Make sure all addresses are the same Common::List<Allocation>::iterator i; // Find the Allocator to deallocate for (i = _allocList.begin(); i != _allocList.end(); ++i) { if ((*i).address == address) { _bytesAllocated -= (*i).size; _allocList.erase(i); PSP_DEBUG_PRINT("Deallocated address[%p], size[%u]\n", (*i).address, (*i).size); return; } } PSP_DEBUG_PRINT("Address[%p] not allocated.\n", address); }
/* Get the width and height of a png image */ bool PngLoader::findImageDimensions() { DEBUG_ENTER_FUNC(); bool status = basicImageLoad(); PSP_DEBUG_PRINT("width[%d], height[%d], paletteSize[%d], bitDepth[%d], channels[%d], rowBytes[%d]\n", _width, _height, _paletteSize, _bitDepth, _channels, _infoPtr->rowbytes); png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); return status; }
inline void Mp3PspStream::updatePcmLength() { uint32 mpegVer = HEADER_GET_MPEG_VERSION(_stream.this_frame); // sadly, MAD can't do this for us PSP_DEBUG_PRINT("mpeg ver[%x]\n", mpegVer); switch (mpegVer) { case MPEG_VER1_HEADER: mpegVer = MPEG_VER1; break; case MPEG_VER2_HEADER: mpegVer = MPEG_VER2; break; case MPEG_VER2_5_HEADER: mpegVer = MPEG_VER2_5; break; default: PSP_ERROR("Unknown MPEG version %x\n", mpegVer); break; } PSP_DEBUG_PRINT("layer[%d]\n", _header.layer); _pcmLength = mp3SamplesPerFrame[(mpegVer * 3) + _header.layer - 1]; }
// // Load a texture from a png image // bool PngLoader::loadImageIntoBuffer() { DEBUG_ENTER_FUNC(); if (!basicImageLoad()) { png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); return false; } png_set_strip_16(_pngPtr); // Strip off 16 bit channels in case they occur if (_paletteSize) { // Copy the palette png_colorp srcPal = _infoPtr->palette; for (int i = 0; i < _infoPtr->num_palette; i++) { unsigned char alphaVal = (i < _infoPtr->num_trans) ? _infoPtr->trans[i] : 0xFF; // Load alpha if it's there _palette->setSingleColorRGBA(i, srcPal->red, srcPal->green, srcPal->blue, alphaVal); srcPal++; } } else { // Not a palettized image if (_colorType == PNG_COLOR_TYPE_GRAY && _bitDepth < 8) png_set_gray_1_2_4_to_8(_pngPtr); // Round up grayscale images if (png_get_valid(_pngPtr, _infoPtr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(_pngPtr); // Convert trans channel to alpha for 32 bits png_set_add_alpha(_pngPtr, 0xff, PNG_FILLER_AFTER); // Filler for alpha if none exists } uint32 rowBytes = png_get_rowbytes(_pngPtr, _infoPtr); // there seems to be a bug in libpng where it doesn't increase the rowbytes or the // channel even after we add the alpha channel if (_channels == 3 && (rowBytes / _width) == 3) { _channels = 4; rowBytes = _width * _channels; } PSP_DEBUG_PRINT("rowBytes[%d], channels[%d]\n", rowBytes, _channels); unsigned char *line = (unsigned char*) malloc(rowBytes); if (!line) { png_destroy_read_struct(&_pngPtr, png_infopp_NULL, png_infopp_NULL); PSP_ERROR("Couldn't allocate line\n"); return false; } for (size_t y = 0; y < _height; y++) { png_read_row(_pngPtr, line, png_bytep_NULL); _buffer->copyFromRect(line, rowBytes, 0, y, _width, 1); // Copy into buffer } free(line); png_read_end(_pngPtr, _infoPtr); png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); return true; }
// The real thread function void PspAudio::threadFunction() { assert(_callback); PSP_DEBUG_PRINT_FUNC("audio thread started\n"); while (_init) { // Keep looping so long as we haven't been told to stop if (_paused) PSP_DEBUG_PRINT("audio thread paused\n"); while (_paused) { // delay until we stop pausing PspThread::delayMicros(100000); // 100ms if (!_paused) PSP_DEBUG_PRINT("audio thread unpaused\n"); } PSP_DEBUG_PRINT("remaining samples[%d]\n", _remainingSamples); PSP_DEBUG_PRINT("filling buffer[%d]\n", _bufferToFill); _callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in data nextBuffer(_bufferToFill); PSP_DEBUG_PRINT("playing buffer[%d].\n", _bufferToPlay); playBuffer(); nextBuffer(_bufferToPlay); } // while _init // destroy everything free(_buffers[0]); sceAudioChRelease(_pspChannel); PSP_DEBUG_PRINT("audio thread exiting. ****************************\n"); }
// this function gets called by PspThread when starting the new thread void MasterGuRenderer::threadFunction() { DEBUG_ENTER_FUNC(); // Create the callback. It should always get the pointer to MasterGuRenderer _callbackId = sceKernelCreateCallback("Display Callback", guCallback, this); if (_callbackId < 0) { PSP_ERROR("failed to create display callback\n"); } PSP_DEBUG_PRINT("created callback. Going to sleep\n"); sceKernelSleepThreadCB(); // sleep until we get a callback }
bool Mp3PspStream::initDecoder() { DEBUG_ENTER_FUNC(); if (_decoderInit) { PSP_ERROR("Already initialized!"); return true; } // Based on PSP firmware version, we need to do different things to do Media Engine processing uint32 firmware = sceKernelDevkitVersion(); PSP_DEBUG_PRINT("Firmware version 0x%x\n", firmware); if (firmware == 0x01050001){ if (!loadStartAudioModule((char *)(void *)"flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL)) { PSP_ERROR("failed to load me_for_vsh.prx. ME cannot start.\n"); _decoderFail = true; return false; } if (!loadStartAudioModule((char *)(void *)"flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL)) { PSP_ERROR("failed to load audiocodec.prx. ME cannot start.\n"); _decoderFail = true; return false; } } else { if (sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC) < 0) { PSP_ERROR("failed to load AVCODEC module. ME cannot start.\n"); _decoderFail = true; return false; } } PSP_DEBUG_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening _decoderInit = true; return true; }
void DisplayManager::setSizeAndPixelFormat(uint width, uint height, const Graphics::PixelFormat *format) { DEBUG_ENTER_FUNC(); PSP_DEBUG_PRINT("w[%u], h[%u], pformat[%p]\n", width, height, format); _screen->deallocate(); _screen->setScummvmPixelFormat(format); _screen->setSize(width, height); _screen->allocate(); _cursor->setScreenPaletteScummvmPixelFormat(format); _displayParams.screenSource.width = width; _displayParams.screenSource.height = height; calculateScaleParams(); }
void Screen::setScummvmPixelFormat(const Graphics::PixelFormat *format) { DEBUG_ENTER_FUNC(); PSP_DEBUG_PRINT("format[%p], _buffer[%p], _palette[%p]\n", format, &_buffer, &_palette); if (!format) { bzero(&_pixelFormat, sizeof(_pixelFormat)); _pixelFormat.bytesPerPixel = 1; // default } else { _pixelFormat = *format; } PSPPixelFormat::Type bufferFormat, paletteFormat; bool swapRedBlue = false; PSPPixelFormat::convertFromScummvmPixelFormat(format, bufferFormat, paletteFormat, swapRedBlue); _buffer.setPixelFormat(bufferFormat, swapRedBlue); _palette.setPixelFormats(paletteFormat, bufferFormat, swapRedBlue); }
bool DefaultDisplayClient::allocate(bool bufferInVram /* = false */, bool paletteInVram /* = false */) { DEBUG_ENTER_FUNC(); if (!_buffer.allocate(bufferInVram)) { PSP_ERROR("Couldn't allocate buffer.\n"); return false; } if (_buffer.hasPalette()) { PSP_DEBUG_PRINT("_palette[%p]\n", &_palette); if (!_palette.allocate()) { PSP_ERROR("Couldn't allocate palette.\n"); return false; } } return true; }
void MasterGuRenderer::guProgramDisplayBufferSizes() { DEBUG_ENTER_FUNC(); PSP_DEBUG_PRINT("Outputbits[%u]\n", GuRenderer::_displayManager->getOutputBitsPerPixel()); switch (GuRenderer::_displayManager->getOutputBitsPerPixel()) { case 16: sceGuDrawBuffer(GU_PSM_4444, (void *)0, PSP_BUFFER_WIDTH); sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, (void*)(PSP_FRAME_SIZE * sizeof(uint16)), PSP_BUFFER_WIDTH); sceGuDepthBuffer((void*)(PSP_FRAME_SIZE * sizeof(uint16) * 2), PSP_BUFFER_WIDTH); VramAllocator::instance().allocate(PSP_FRAME_SIZE * sizeof(uint16) * 2); break; case 32: sceGuDrawBuffer(GU_PSM_8888, (void *)0, PSP_BUFFER_WIDTH); sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, (void*)(PSP_FRAME_SIZE * sizeof(uint32)), PSP_BUFFER_WIDTH); sceGuDepthBuffer((void*)(PSP_FRAME_SIZE * sizeof(uint32) * 2), PSP_BUFFER_WIDTH); VramAllocator::instance().allocate(PSP_FRAME_SIZE * sizeof(uint32) * 2); break; } }
uint32 PspIoStream::read(void *ptr, uint32 len) { DEBUG_ENTER_FUNC(); PSP_DEBUG_PRINT_FUNC("filename[%s], len[0x%x], ptr[%p], _pos[%x], _physPos[%x]\n", _path.c_str(), len, ptr, _pos, _physicalPos); if (_error || _eos || len <= 0) return 0; uint32 lenRemainingInFile = _fileSize - _pos; // check for getting EOS if (len > lenRemainingInFile) { len = lenRemainingInFile; _eos = true; } if (PowerMan.beginCriticalSection()) PSP_DEBUG_PRINT_FUNC("suspended\n"); // check if we need to seek if (_pos != _physicalPos) PSP_DEBUG_PRINT("seeking from %x to %x\n", _physicalPos, _pos); if (!physicalSeekFromCur(_pos - _physicalPos)) { _error = true; return 0; } int ret = sceIoRead(_handle, ptr, len); PowerMan.endCriticalSection(); _physicalPos += ret; // Update position _pos = _physicalPos; if (ret != (int)len) { // error PSP_ERROR("sceIoRead returned [0x%x] instead of len[0x%x]\n", ret, len); _error = true; _errorSource = 4; } return ret; }
// // used to swap red and blue void PspMemorySwap::swap(uint16 *dst16, const uint16 *src16, uint32 bytes, PSPPixelFormat &format) { DEBUG_ENTER_FUNC(); #ifdef TEST_MEMORY_COPY uint32 debugBytes = bytes; const uint16 *debugDst = dst16, *debugSrc = src16; #endif // align the destination pointer first uint32 prefixDst = (((uint32)dst16) & 0x3); // for swap, we can only have 2 or 0 as our prefix if (prefixDst) { bytes -= prefixDst; // remember we assume bytes > 4 *dst16++ = format.swapRedBlue16(*src16++); if (bytes < MIN_AMOUNT_FOR_COMPLEX_COPY) { // check if it's worthwhile to continue swap16(dst16, src16, bytes, format); #ifdef TEST_MEMORY_COPY testSwap(debugDst, debugSrc, debugBytes, format); #endif return; } } // check the source pointer alignment now uint32 alignSrc = (((uint32)src16) & 0x3); if (alignSrc) { // we'll need to realign our reads PSP_DEBUG_PRINT("misaligned copy of %u bytes from %p to %p\n", bytes, src16, dst16); swap32Misaligned((uint32 *)dst16, src16, bytes, format); } else { swap32Aligned((uint32 *)dst16, (const uint32 *)src16, bytes, format); } #ifdef TEST_MEMORY_COPY testSwap(debugDst, debugSrc, debugBytes, format); #endif }
// Note that after we fill up 32 bits ie 50 days we'll loop back to 0, which may cause // unpredictable results uint32 PspRtc::getMillis(bool skipRecord) { uint32 ticks[2]; sceRtcGetCurrentTick((u64 *)ticks); // can introduce weird thread delays uint32 millis = ticks[0]/1000; millis -= _startMillis; // get ms since start of program if ((int)_lastMillis - (int)millis > MS_LOOP_CHECK) { // we must have looped around if (_looped == false) { // check to make sure threads do this once _looped = true; _milliOffset += MS_LOOP_AROUND; // add the needed offset PSP_DEBUG_PRINT("looping around. last ms[%d], curr ms[%d]\n", _lastMillis, millis); } } else { _looped = false; } _lastMillis = millis; return millis + _milliOffset; }
void PspMemory::copy32Aligned(uint32 *dst32, const uint32 *src32, uint32 bytes) { PSP_DEBUG_PRINT("copy32Aligned(): dst32[%p], src32[%p], bytes[%d]\n", dst32, src32, bytes); int words8 = bytes >> 5; // try blocks of 8 words at a time if (words8) { while (words8--) { uint32 a, b, c, d; a = src32[0]; b = src32[1]; c = src32[2]; d = src32[3]; dst32[0] = a; dst32[1] = b; dst32[2] = c; dst32[3] = d; a = src32[4]; b = src32[5]; c = src32[6]; d = src32[7]; dst32[4] = a; dst32[5] = b; dst32[6] = c; dst32[7] = d; dst32 += 8; src32 += 8; } } int words4 = (bytes & 0x1F) >> 4; // try blocks of 4 words at a time if (words4) { uint32 a, b, c, d; a = src32[0]; b = src32[1]; c = src32[2]; d = src32[3]; dst32[0] = a; dst32[1] = b; dst32[2] = c; dst32[3] = d; dst32 += 4; src32 += 4; } int bytesLeft = (bytes & 0xF); // only look at bytes left after we did the above int wordsLeft = bytesLeft >> 2; // now just do single words while (wordsLeft) { *dst32++ = *src32++; wordsLeft--; } bytesLeft = bytes & 0x3; // get remaining bytes PSP_DEBUG_PRINT("bytesLeft[%d]\n", bytesLeft); byte *dst = (byte *)dst32; byte *src = (byte *)src32; while (bytesLeft--) { *dst++ = *src++; } }
/* load the keyboard into memory */ bool PSPKeyboard::load() { DEBUG_ENTER_FUNC(); if (_init) { PSP_DEBUG_PRINT("keyboard already loaded into memory\n"); return true; } // For the shell, we must use a hack #ifdef PSP_KB_SHELL Common::FSNode node(PSP_KB_SHELL_PATH); #else /* normal mode */ Common::FSNode node("."); // Look in current directory #endif PSP_DEBUG_PRINT("path[%s]\n", node.getPath().c_str()); Common::Archive *fileArchive = NULL; Common::Archive *zipArchive = NULL; Common::SeekableReadStream * file = 0; if (node.getChild("kbd").exists() && node.getChild("kbd").isDirectory()) { PSP_DEBUG_PRINT("found directory ./kbd\n"); fileArchive = new Common::FSDirectory(node.getChild("kbd")); } if (node.getChild("kbd.zip").exists()) { PSP_DEBUG_PRINT("found kbd.zip\n"); zipArchive = Common::makeZipArchive(node.getChild("kbd.zip")); } int i; // Loop through all png images for (i = 0; i < guiStringsSize; i++) { PSP_DEBUG_PRINT("Opening %s.\n", _guiStrings[i]); // Look for the file in the kbd directory if (fileArchive && fileArchive->hasFile(_guiStrings[i])) { PSP_DEBUG_PRINT("found it in kbd directory.\n"); file = fileArchive->createReadStreamForMember(_guiStrings[i]); if (!file) { PSP_ERROR("Can't open kbd/%s for keyboard. No keyboard will load.\n", _guiStrings[i]); goto ERROR; } } // We didn't find it. Look for it in the zip file else if (zipArchive && zipArchive->hasFile(_guiStrings[i])) { PSP_DEBUG_PRINT("found it in kbd.zip.\n"); file = zipArchive->createReadStreamForMember(_guiStrings[i]); if (!file) { PSP_ERROR("Can't open %s in kbd.zip for keyboard. No keyboard will load.\n", _guiStrings[i]); goto ERROR; } } else { // Couldn't find the file PSP_ERROR("Can't find %s for keyboard. No keyboard will load.\n", _guiStrings[i]); goto ERROR; } PngLoader image(file, _buffers[i], _palettes[i]); if (image.allocate() != PngLoader::OK) { PSP_ERROR("Failed to allocate memory for keyboard image %s\n", _guiStrings[i]); goto ERROR; } if (!image.load()) { PSP_ERROR("Failed to load image from file %s\n", _guiStrings[i]); goto ERROR; } delete file; } /* for loop */ _init = true; delete fileArchive; delete zipArchive; return true; ERROR: delete file; delete fileArchive; delete zipArchive; for (int j = 0; j < i; j++) { _buffers[j].deallocate(); _palettes[j].deallocate(); } _init = false; return false; }
// More challenging -- need to shift // Assume dst is aligned void PspMemory::copy32Misaligned(uint32 *dst32, const byte *src, uint32 bytes, uint32 alignSrc) { PSP_DEBUG_PRINT("copy32Misaligned: dst32[%p], src[%p], bytes[%d], alignSrc[%d]\n", dst32, src, bytes, alignSrc); uint32 *src32 = (uint32 *)(((uint32)src) & 0xFFFFFFFC); // remove misalignment uint32 shiftValue, lastShiftValue; switch (alignSrc) { case 1: shiftValue = 8; lastShiftValue = 24; break; case 2: shiftValue = 16; lastShiftValue = 16; break; default: /* 3 */ shiftValue = 24; lastShiftValue = 8; break; } uint32 dstWord, srcWord; // Try to do groups of 4 words uint32 words4 = bytes >> 4; srcWord = *src32; // preload 1st word so we read ahead for (; words4; words4--) { dstWord = srcWord >> shiftValue; srcWord = src32[1]; dstWord |= srcWord << lastShiftValue; dst32[0] = dstWord; dstWord = srcWord >> shiftValue; srcWord = src32[2]; dstWord |= srcWord << lastShiftValue; dst32[1] = dstWord; dstWord = srcWord >> shiftValue; srcWord = src32[3]; dstWord |= srcWord << lastShiftValue; dst32[2] = dstWord; dstWord = srcWord >> shiftValue; srcWord = src32[4]; dstWord |= srcWord << lastShiftValue; dst32[3] = dstWord; src32 += 4; dst32 += 4; } uint32 words = (bytes & 0xF) >> 2; // now get remaining words // we read one word ahead of what we write // setup the first read for (; words ;words--) { dstWord = srcWord >> shiftValue; srcWord = src32[1]; // we still go one ahead src32++; dstWord |= srcWord << lastShiftValue; *dst32++ = dstWord; } uint32 bytesLeft = bytes & 3; // and remaining bytes if (bytesLeft) { byte *dst8 = (byte *)dst32; byte *src8 = ((byte *)src32) + ((uint32)src & 0x3); // get exact location we should be at for(; bytesLeft; bytesLeft--) { *dst8++ = *src8++; } } }
void PspAudio::close() { PSP_DEBUG_PRINT("close has been called ***************\n"); _init = false; }
void Mp3PspStream::decodeMP3Data() { DEBUG_ENTER_FUNC(); do { if (_state == MP3_STATE_INIT) { initStream(); initStreamME(); } if (_state == MP3_STATE_EOS) return; findValidHeader(); // seach for next valid header while (_state == MP3_STATE_READY) { // not a real 'while'. Just for easy flow _stream.error = MAD_ERROR_NONE; uint32 frame_size = _stream.next_frame - _stream.this_frame; updatePcmLength(); // Retrieve the number of PCM samples. // We seem to change this, so it needs to be dynamic PSP_DEBUG_PRINT("MP3 frame size[%d]. pcmLength[%d]\n", frame_size, _pcmLength); memcpy(_codecInBuffer, _stream.this_frame, frame_size); // we need it aligned // set up parameters for ME _codecParams[6] = (unsigned long)_codecInBuffer; _codecParams[8] = (unsigned long)_pcmSamples; _codecParams[7] = frame_size; _codecParams[9] = _pcmLength * 2; // x2 for stereo, though this one's not so important // debug #ifdef PRINT_BUFFERS PSP_DEBUG_PRINT("mp3 frame:\n"); for (int i=0; i < (int)frame_size; i++) { PSP_DEBUG_PRINT_SAMELN("%x ", _codecInBuffer[i]); } PSP_DEBUG_PRINT("\n"); #endif // Decode the next frame // This function blocks. We'll want to put it in a thread int ret = sceAudiocodecDecode(_codecParams, 0x1002); if (ret < 0) { PSP_INFO_PRINT("failed to decode MP3 data in ME. sceAudiocodecDecode returned 0x%x\n", ret); } #ifdef PRINT_BUFFERS PSP_DEBUG_PRINT("PCM frame:\n"); for (int i=0; i < (int)_codecParams[9]; i+=2) { // changed from i+=2 PSP_DEBUG_PRINT_SAMELN("%d ", (int16)_pcmSamples[i]); } PSP_DEBUG_PRINT("\n"); #endif _posInFrame = 0; break; } } while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN); if (_stream.error != MAD_ERROR_NONE) // catch EOS _state = MP3_STATE_EOS; }