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