/*---------------------------------------------------------------------------* Project: TwlSDK - MI - demos - uncompressStream-1 File: main.c Copyright 2003-2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2008-10-02#$ $Rev: 8827 $ $Author: yosizaki $ *---------------------------------------------------------------------------*/ //--------------------------------------------------------------------------- // A sample that displays an image uncompressed by streaming // // If display mode is VRAM display mode, a bitmap image on VRAM is displayed. // This sample loads different four images compressed different format to VRAM A-D, // and displays them by turns. // //--------------------------------------------------------------------------- #include #include #include "DEMO.h" #define TEMP_BUF_SIZE 512 static u8 *data_uncomp_buf; static u8 doubleBuf[2][TEMP_BUF_SIZE] ATTRIBUTE_ALIGN(32); static void InitAlloc(void) { void *tempLo; OSHeapHandle hh; tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1); OS_SetArenaLo(OS_ARENA_MAIN, tempLo); hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi()); if (hh < 0) { OS_Panic("ARM9: Fail to create heap...\n"); } hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh); } void NitroMain(void) { int vram_slot = 0, count = 0; u8 *tmpBuf = doubleBuf[0]; //--------------------------------------------------------------------------- // Initialize: // Enable IRQ interrupts and initialize VRAM //--------------------------------------------------------------------------- DEMOInitCommon(); DEMOInitVRAM(); InitAlloc(); FS_Init(3); OS_InitTick(); //--------------------------------------------------------------------------- // Map VRAM bank A-D onto LCDC. //--------------------------------------------------------------------------- GX_SetBankForLCDC(GX_VRAM_LCDC_A | GX_VRAM_LCDC_B | GX_VRAM_LCDC_C | GX_VRAM_LCDC_D); //--------------------------------------------------------------------------- // Download images //--------------------------------------------------------------------------- //=========================== // Uncompressed data //=========================== { FSFile file; u32 read_len; // Open the file FS_InitFile(&file); if (!FS_OpenFileEx(&file, "/data/image1.bin", FS_FILEMODE_R)) { OS_TPrintf(" Open File /data/image1.bin fail\n"); return; } // Secure a region for loading the data read_len = FS_GetFileLength(&file); data_uncomp_buf = (u8 *)OS_Alloc(read_len); // Transfer file (void)FS_ReadFile(&file, data_uncomp_buf, 256 * 192 * 2); // Transfer to VRAM MI_DmaCopy32(3, data_uncomp_buf, (void *)HW_LCDC_VRAM_A, 256 * 192 * sizeof(unsigned short)); OS_Free(data_uncomp_buf); (void)FS_CloseFile(&file); } //=========================== // Run-length compressed data //=========================== { FSFile file; MIUncompContextRL context; s32 read_len; u32 data_size; // Open the file FS_InitFile(&file); if (!FS_OpenFileEx(&file, "/data/image2_RL.bin", FS_FILEMODE_R)) { OS_TPrintf(" Open File /data/image2_RL.bin fail\n"); return; } // Get the header part of the compressed data (void)FS_ReadFile(&file, tmpBuf, sizeof(MICompressionHeader)); // Secure a region for uncompressed data data_size = MI_GetUncompressedSize(tmpBuf); data_uncomp_buf = (u8 *)OS_Alloc(data_size); // Context initialization MI_InitUncompContextRL(&context, data_uncomp_buf, (MICompressionHeader *)tmpBuf); while (1) { // Read an arbitrary size of data and perform streaming uncompression read_len = FS_ReadFile(&file, tmpBuf, TEMP_BUF_SIZE); if (read_len <= 0) { OS_TPanic("can't read file\n"); } // If extracting in memory, use the high-speed 8bit-access function. if (MI_ReadUncompRL8(&context, tmpBuf, (u32)read_len) == 0) { break; } } // Transfer to VRAM DC_FlushRange(data_uncomp_buf, data_size); // Flush the cache /* I/O register is accessed using DMA operation, so cache wait is not needed */ // DC_WaitWriteBufferEmpty(); MI_DmaCopy32(3, data_uncomp_buf, (void *)HW_LCDC_VRAM_B, 256 * 192 * sizeof(unsigned short)); OS_Free(data_uncomp_buf); (void)FS_CloseFile(&file); } //=========================== // LZ77 compressed data - Sample of direct uncompression to VRAM //=========================== { FSFile file; MIUncompContextLZ context; s32 read_len; // Open the file FS_InitFile(&file); if (!FS_OpenFileEx(&file, "/data/image3_LZ.bin", FS_FILEMODE_R)) { OS_TPrintf(" Open File /data/image3_LZ.bin fail\n"); return; } // Get the header part of the compressed data (void)FS_ReadFile(&file, tmpBuf, sizeof(MICompressionHeader)); // If extracting directly to VRAM, initialize the context and specify VRAM for the dest address MI_InitUncompContextLZ(&context, (void *)HW_LCDC_VRAM_C, (MICompressionHeader *)tmpBuf); while (1) { // Load an arbitrary size of data and perform streaming uncompression read_len = FS_ReadFile(&file, tmpBuf, TEMP_BUF_SIZE); if (read_len <= 0) { OS_TPanic("can't read file\n"); } // If extracting directly to VRAM, use the 16-bit-access function if (MI_ReadUncompLZ16(&context, tmpBuf, (u32)read_len) == 0) { break; } } (void)FS_CloseFile(&file); } //=========================== // Huffman compressed data - Sample that executes extraction while reading data asynchronously from Card //=========================== { FSFile file; MIUncompContextHuffman context; u32 data_size; s32 read_len[2]; u8 read_select; u8 uncomp_select; // Open the file FS_InitFile(&file); if (!FS_OpenFileEx(&file, "/data/image4_HUFF.bin", FS_FILEMODE_R)) { OS_TPrintf(" Open File /data/image4_HUFF.bin fail\n"); return; } // Get the header part of the compressed data (void)FS_ReadFile(&file, tmpBuf, sizeof(MICompressionHeader)); // Secure a region for uncompressed data data_size = MI_GetUncompressedSize(tmpBuf); data_uncomp_buf = (u8 *)OS_Alloc(data_size); // Context initialization MI_InitUncompContextHuffman(&context, data_uncomp_buf, (MICompressionHeader *)tmpBuf); read_select = 0; uncomp_select = 1; read_len[0] = 0; read_len[1] = 0; // To read files asynchronously, the load location must be 512-byte aligned. // The 4-byte header portion is loaded first, so the remaining 512 - 4-bytes should be read. read_len[read_select] = FS_ReadFileAsync(&file, doubleBuf[read_select], 512 - sizeof(MICompressionHeader)); /* Executes extraction while asynchronously reading from the card */ while (1) { // Switch double buffers read_select ^= 0x1; uncomp_select ^= 0x1; // Wait for end of reading of card (void)FS_WaitAsync(&file); // Read an arbitrary size of data and perform streaming uncompression read_len[read_select] = FS_ReadFileAsync(&file, doubleBuf[read_select], TEMP_BUF_SIZE); if (read_len[uncomp_select] == 0) { continue; } if (read_len[uncomp_select] == -1) { OS_TPanic("can't read file\n"); } if (MI_ReadUncompHuffman (&context, doubleBuf[uncomp_select], (u32)read_len[uncomp_select]) == 0) { // Extraction of data completed break; } } // Transfer to VRAM DC_FlushRange(data_uncomp_buf, data_size); // Flush the cache /* I/O register is accessed using DMA operation, so cache wait is not needed */ // DC_WaitWriteBufferEmpty(); MI_DmaCopy32(3, data_uncomp_buf, (void *)HW_LCDC_VRAM_D, 256 * 192 * sizeof(unsigned short)); OS_Free(data_uncomp_buf); (void)FS_CloseFile(&file); } //--------------------------------------------------------------------------- // Set graphics mode VRAM display mode //--------------------------------------------------------------------------- GX_SetGraphicsMode(GX_DISPMODE_VRAM_A, // Display VRAM-A (GXBGMode)0, // Dummy (GXBG0As)0); // Dummy DEMOStartDisplay(); while (1) { OS_WaitVBlankIntr(); // Waiting for the end of the V-Blank interrupt //--------------------------------------------------------------------------- // Change the VRAM slot displayed every 90 frames //--------------------------------------------------------------------------- if (count++ > 90) { vram_slot++; vram_slot &= 0x03; switch (vram_slot) { case 0: GX_SetGraphicsMode(GX_DISPMODE_VRAM_A, // Display VRAM-A (GXBGMode)0, // Dummy (GXBG0As)0); // Dummy break; case 1: GX_SetGraphicsMode(GX_DISPMODE_VRAM_B, // Display VRAM-B (GXBGMode)0, // Dummy (GXBG0As)0); // Dummy break; case 2: GX_SetGraphicsMode(GX_DISPMODE_VRAM_C, // Display VRAM-C (GXBGMode)0, // Dummy (GXBG0As)0); // Dummy break; case 3: GX_SetGraphicsMode(GX_DISPMODE_VRAM_D, // Display VRAM-D (GXBGMode)0, // Dummy (GXBG0As)0); // Dummy break; } // Reset a counter count = 0; } } } //--------------------------------------------------------------------------- // V-Blank interrupt function: // // Interrupt handlers are registered on the interrupt table by OS_SetIRQFunction. // OS_EnableIrqMask selects IRQ interrupts to enable, and // OS_EnableIrq enables IRQ interrupts. // Notice that you have to call OS_SetIrqCheckFlag to check a V-Blank interrupt. //--------------------------------------------------------------------------- void VBlankIntr(void) { OS_SetIrqCheckFlag(OS_IE_V_BLANK); // Checking V-Blank interrupt }