1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - MI - demos - uncompressStream-1
3   File:     main.c
4 
5   Copyright 2003-2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-10-02#$
14   $Rev: 8827 $
15   $Author: yosizaki $
16  *---------------------------------------------------------------------------*/
17 
18 //---------------------------------------------------------------------------
19 // A sample that displays an image uncompressed by streaming
20 //
21 // If display mode is VRAM display mode, a bitmap image on VRAM is displayed.
22 // This sample loads different four images compressed different format to VRAM A-D,
23 // and displays them by turns.
24 //
25 //---------------------------------------------------------------------------
26 
27 #include <nitro.h>
28 #include <nitro/mi/uncomp_stream.h>
29 #include "DEMO.h"
30 
31 #define TEMP_BUF_SIZE   512
32 
33 static u8 *data_uncomp_buf;
34 static u8 doubleBuf[2][TEMP_BUF_SIZE] ATTRIBUTE_ALIGN(32);
35 
InitAlloc(void)36 static void InitAlloc(void)
37 {
38     void   *tempLo;
39     OSHeapHandle hh;
40 
41     tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
42     OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
43     hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
44     if (hh < 0)
45     {
46         OS_Panic("ARM9: Fail to create heap...\n");
47     }
48     hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
49 }
50 
51 
NitroMain(void)52 void NitroMain(void)
53 {
54     int     vram_slot = 0, count = 0;
55     u8     *tmpBuf = doubleBuf[0];
56 
57     //---------------------------------------------------------------------------
58     // Initialize:
59     // Enable IRQ interrupts and initialize VRAM
60     //---------------------------------------------------------------------------
61     DEMOInitCommon();
62     DEMOInitVRAM();
63     InitAlloc();
64     FS_Init(3);
65     OS_InitTick();
66 
67     //---------------------------------------------------------------------------
68     // Map VRAM bank A-D onto LCDC.
69     //---------------------------------------------------------------------------
70     GX_SetBankForLCDC(GX_VRAM_LCDC_A | GX_VRAM_LCDC_B | GX_VRAM_LCDC_C | GX_VRAM_LCDC_D);
71 
72     //---------------------------------------------------------------------------
73     // Download images
74     //---------------------------------------------------------------------------
75 
76     //===========================
77     // Uncompressed data
78     //===========================
79     {
80         FSFile  file;
81         u32     read_len;
82 
83         // Open the file
84         FS_InitFile(&file);
85         if (!FS_OpenFileEx(&file, "/data/image1.bin", FS_FILEMODE_R))
86         {
87             OS_TPrintf(" Open File /data/image1.bin fail\n");
88             return;
89         }
90         // Secure a region for loading the data
91         read_len = FS_GetFileLength(&file);
92         data_uncomp_buf = (u8 *)OS_Alloc(read_len);
93 
94         // Transfer file
95         (void)FS_ReadFile(&file, data_uncomp_buf, 256 * 192 * 2);
96 
97         // Transfer to VRAM
98         MI_DmaCopy32(3, data_uncomp_buf, (void *)HW_LCDC_VRAM_A,
99                      256 * 192 * sizeof(unsigned short));
100 
101         OS_Free(data_uncomp_buf);
102         (void)FS_CloseFile(&file);
103 
104     }
105 
106     //===========================
107     // Run-length compressed data
108     //===========================
109     {
110         FSFile  file;
111         MIUncompContextRL context;
112         s32     read_len;
113         u32     data_size;
114 
115         // Open the file
116         FS_InitFile(&file);
117         if (!FS_OpenFileEx(&file, "/data/image2_RL.bin", FS_FILEMODE_R))
118         {
119             OS_TPrintf(" Open File /data/image2_RL.bin fail\n");
120             return;
121         }
122 
123         // Get the header part of the compressed data
124         (void)FS_ReadFile(&file, tmpBuf, sizeof(MICompressionHeader));
125 
126         // Secure a region for uncompressed data
127         data_size = MI_GetUncompressedSize(tmpBuf);
128         data_uncomp_buf = (u8 *)OS_Alloc(data_size);
129 
130         // Context initialization
131         MI_InitUncompContextRL(&context, data_uncomp_buf, (MICompressionHeader *)tmpBuf);
132 
133         while (1)
134         {
135             // Read an arbitrary size of data and perform streaming uncompression
136             read_len = FS_ReadFile(&file, tmpBuf, TEMP_BUF_SIZE);
137             if (read_len <= 0)
138             {
139                 OS_TPanic("can't read file\n");
140             }
141             // If extracting in memory, use the high-speed 8bit-access function.
142             if (MI_ReadUncompRL8(&context, tmpBuf, (u32)read_len) == 0)
143             {
144                 break;
145             }
146         }
147 
148         // Transfer to VRAM
149         DC_FlushRange(data_uncomp_buf, data_size);      // Flush the cache
150         /* I/O register is accessed using DMA operation, so cache wait is not needed */
151         // DC_WaitWriteBufferEmpty();
152         MI_DmaCopy32(3, data_uncomp_buf, (void *)HW_LCDC_VRAM_B,
153                      256 * 192 * sizeof(unsigned short));
154 
155         OS_Free(data_uncomp_buf);
156         (void)FS_CloseFile(&file);
157 
158     }
159 
160     //===========================
161     // LZ77 compressed data - Sample of direct uncompression to VRAM
162     //===========================
163     {
164         FSFile  file;
165         MIUncompContextLZ context;
166         s32     read_len;
167 
168         // Open the file
169         FS_InitFile(&file);
170         if (!FS_OpenFileEx(&file, "/data/image3_LZ.bin", FS_FILEMODE_R))
171         {
172             OS_TPrintf(" Open File /data/image3_LZ.bin fail\n");
173             return;
174         }
175 
176         // Get the header part of the compressed data
177         (void)FS_ReadFile(&file, tmpBuf, sizeof(MICompressionHeader));
178 
179         // If extracting directly to VRAM, initialize the context and specify VRAM for the dest address
180         MI_InitUncompContextLZ(&context, (void *)HW_LCDC_VRAM_C, (MICompressionHeader *)tmpBuf);
181 
182         while (1)
183         {
184             // Load an arbitrary size of data and perform streaming uncompression
185             read_len = FS_ReadFile(&file, tmpBuf, TEMP_BUF_SIZE);
186             if (read_len <= 0)
187             {
188                 OS_TPanic("can't read file\n");
189             }
190 
191             // If extracting directly to VRAM, use the 16-bit-access function
192             if (MI_ReadUncompLZ16(&context, tmpBuf, (u32)read_len) == 0)
193             {
194                 break;
195             }
196         }
197 
198         (void)FS_CloseFile(&file);
199     }
200 
201     //===========================
202     // Huffman compressed data - Sample that executes extraction while reading data asynchronously from Card
203     //===========================
204     {
205         FSFile  file;
206         MIUncompContextHuffman context;
207         u32     data_size;
208         s32     read_len[2];
209         u8      read_select;
210         u8      uncomp_select;
211 
212         // Open the file
213         FS_InitFile(&file);
214         if (!FS_OpenFileEx(&file, "/data/image4_HUFF.bin", FS_FILEMODE_R))
215         {
216             OS_TPrintf(" Open File /data/image4_HUFF.bin fail\n");
217             return;
218         }
219 
220         // Get the header part of the compressed data
221         (void)FS_ReadFile(&file, tmpBuf, sizeof(MICompressionHeader));
222 
223         // Secure a region for uncompressed data
224         data_size = MI_GetUncompressedSize(tmpBuf);
225         data_uncomp_buf = (u8 *)OS_Alloc(data_size);
226 
227         // Context initialization
228         MI_InitUncompContextHuffman(&context, data_uncomp_buf, (MICompressionHeader *)tmpBuf);
229 
230         read_select = 0;
231         uncomp_select = 1;
232         read_len[0] = 0;
233         read_len[1] = 0;
234 
235         // To read files asynchronously, the load location must be 512-byte aligned.
236         // The 4-byte header portion is loaded first, so the remaining 512 - 4-bytes should be read.
237         read_len[read_select] =
238             FS_ReadFileAsync(&file, doubleBuf[read_select], 512 - sizeof(MICompressionHeader));
239 
240         /* Executes extraction while asynchronously reading from the card */
241         while (1)
242         {
243             // Switch double buffers
244             read_select ^= 0x1;
245             uncomp_select ^= 0x1;
246 
247             // Wait for end of reading of card
248             (void)FS_WaitAsync(&file);
249 
250             // Read an arbitrary size of data and perform streaming uncompression
251             read_len[read_select] = FS_ReadFileAsync(&file, doubleBuf[read_select], TEMP_BUF_SIZE);
252 
253             if (read_len[uncomp_select] == 0)
254             {
255                 continue;
256             }
257             if (read_len[uncomp_select] == -1)
258             {
259                 OS_TPanic("can't read file\n");
260             }
261 
262             if (MI_ReadUncompHuffman
263                 (&context, doubleBuf[uncomp_select], (u32)read_len[uncomp_select]) == 0)
264             {
265                 // Extraction of data completed
266                 break;
267             }
268         }
269 
270         // Transfer to VRAM
271         DC_FlushRange(data_uncomp_buf, data_size);      // Flush the cache
272         /* I/O register is accessed using DMA operation, so cache wait is not needed */
273         // DC_WaitWriteBufferEmpty();
274         MI_DmaCopy32(3, data_uncomp_buf, (void *)HW_LCDC_VRAM_D,
275                      256 * 192 * sizeof(unsigned short));
276 
277         OS_Free(data_uncomp_buf);
278         (void)FS_CloseFile(&file);
279     }
280 
281     //---------------------------------------------------------------------------
282     // Set graphics mode VRAM display mode
283     //---------------------------------------------------------------------------
284     GX_SetGraphicsMode(GX_DISPMODE_VRAM_A,      // Display VRAM-A
285                        (GXBGMode)0,    // Dummy
286                        (GXBG0As)0);    // Dummy
287 
288     DEMOStartDisplay();
289     while (1)
290     {
291         OS_WaitVBlankIntr();           // Waiting for the end of the V-Blank interrupt
292 
293         //---------------------------------------------------------------------------
294         // Change the VRAM slot displayed every 90 frames
295         //---------------------------------------------------------------------------
296         if (count++ > 90)
297         {
298             vram_slot++;
299             vram_slot &= 0x03;
300             switch (vram_slot)
301             {
302             case 0:
303                 GX_SetGraphicsMode(GX_DISPMODE_VRAM_A,  // Display VRAM-A
304                                    (GXBGMode)0, // Dummy
305                                    (GXBG0As)0); // Dummy
306                 break;
307             case 1:
308                 GX_SetGraphicsMode(GX_DISPMODE_VRAM_B,  // Display VRAM-B
309                                    (GXBGMode)0, // Dummy
310                                    (GXBG0As)0); // Dummy
311                 break;
312             case 2:
313                 GX_SetGraphicsMode(GX_DISPMODE_VRAM_C,  // Display VRAM-C
314                                    (GXBGMode)0, // Dummy
315                                    (GXBG0As)0); // Dummy
316                 break;
317             case 3:
318                 GX_SetGraphicsMode(GX_DISPMODE_VRAM_D,  // Display VRAM-D
319                                    (GXBGMode)0, // Dummy
320                                    (GXBG0As)0); // Dummy
321                 break;
322             }
323             // Reset a counter
324             count = 0;
325         }
326     }
327 }
328 
329 //---------------------------------------------------------------------------
330 // V-Blank interrupt function:
331 //
332 // Interrupt handlers are registered on the interrupt table by OS_SetIRQFunction.
333 // OS_EnableIrqMask selects IRQ interrupts to enable, and
334 // OS_EnableIrq enables IRQ interrupts.
335 // Notice that you have to call OS_SetIrqCheckFlag to check a V-Blank interrupt.
336 //---------------------------------------------------------------------------
VBlankIntr(void)337 void VBlankIntr(void)
338 {
339     OS_SetIrqCheckFlag(OS_IE_V_BLANK); // Checking V-Blank interrupt
340 }
341