1 /*---------------------------------------------------------------------------*
2   Project:     KPAD sample program
3   File:        main.c
4   Programmer:  Keizo Ohta
5                HIRATSU Daisuke
6 
7   Copyright 2005-2006 Nintendo. All rights reserved.
8 
9   These coded instructions, statements, and computer programs contain
10   proprietary information of Nintendo of America Inc. and/or Nintendo
11   Company Ltd., and are protected by Federal copyright law.  They may
12   not be disclosed to third parties or copied or duplicated in any form,
13   in whole or in part, without the prior written consent of Nintendo.
14  *---------------------------------------------------------------------------*/
15 
16 #include	<revolution.h>
17 #include	<math.h>
18 
19 #include	<revolution/kpadOld.h>
20 #include	<revolution/mem.h>
21 
22 #include	"main.h"
23 #include	"kfont.h"
24 #include	"sample.h"
25 
26 
27 /***************************************************************
28 	GXFIFO
29  ***************************************************************/
30 #define GX_FIFO_SIZE	( 1 * 1024*1024 )	// Large enough (The smaller the FIFO, the larger the chance of waiting for space to open when a command is issued.)
31 
32 static void      *gx_fifo_p ;       // Pointer to buffer
33 static GXFifoObj *gx_fifo_obj ;     // Management structure
34 
35 
36 /***************************************************************
37 	Frame buffer
38  ***************************************************************/
39 GXRenderModeObj		*rmode_p ;		// Pointer to drawing mode
40 static u8		vfilter[7] = { 0,8, 16,16,16, 8,0 } ;
41 
42 static void		*xfb_p[ 2 ] ;		// Pointer to double buffer
43 static s32		draw_xfb_idx ;		// XFB being drawn by GX
44 static s32		disp_xfb_idx ;		// XFB being displayed by VI
45 
46 
47 /***************************************************************
48 	Controller
49  ***************************************************************/
50 KPADStatus	kpads[ WPAD_MAX_CONTROLLERS ][ KPAD_MAX_READ_BUFS ] ;
51 s32		kpad_reads ;
52 
53 
54 /*******************************************************************************
55 	Memory initialization
56  *******************************************************************************/
init_memory(void)57 static void init_memory( void )
58 {
59     void         *arenaLo, *arenaHi ;
60     OSHeapHandle  heap ;
61 
62 
63     //----- Check available memory
64     arenaLo = OSGetArenaLo() ;
65     arenaHi = OSGetArenaHi() ;
66 
67     //----- Declare the creation of one heap that takes up all available memory
68     arenaLo = OSInitAlloc( arenaLo, arenaHi, 1 ) ;
69     OSSetArenaLo( arenaLo ) ;	// Reset because the available memory changes
70 
71     //----- Create a heap which takes up all available memory and set it as the current heap
72     heap = OSCreateHeap( arenaLo, arenaHi ) ;
73     (void)OSSetCurrentHeap( heap ) ;
74 
75     //----- Make it clear ahead of time that available memory has been utilized
76     arenaLo = arenaHi ;
77     OSSetArenaLo( arenaLo ) ;
78 }
79 
80 
81 /*******************************************************************************
82 	Initialize memory (MEM2)
83  *******************************************************************************/
84 static MEMAllocator	s_mem2Allocator;
85 static MEMHeapHandle s_handle;
86 
init_memory2(void)87 static void init_memory2(void)
88 {
89     void *lo = OSGetMEM2ArenaLo();
90     void *hi = OSGetMEM2ArenaHi();
91     s_handle = MEMCreateFrmHeap(lo, (u32)hi - (u32)lo);
92     if ( s_handle == MEM_HEAP_INVALID_HANDLE )
93     {
94         OSHalt("MEM2 heap allocation error.\n");
95     }
96     else
97     {
98         OSSetMEM2ArenaLo(hi);
99         MEMInitAllocatorForFrmHeap(&s_mem2Allocator, s_handle, 32);   // Buffer requires 32-byte alignment.
100     }
101 }
102 
alloc32(u32 size)103 static void* alloc32(u32 size)
104 {
105     return MEMAllocFromAllocator(&s_mem2Allocator, size);
106 
107 }
108 
free32(void * addr)109 static u8 free32(void *addr)
110 {
111     MEMFreeToAllocator(&s_mem2Allocator, addr);
112     return 1;
113 }
114 
115 
116 /*******************************************************************************
117 	Initialize relationship with display device
118  *******************************************************************************/
init_display(void)119 static void init_display( void )
120 {
121     u32			xfb_size ;
122 
123 
124     //----- Select drawing mode
125     rmode_p = &GXNtsc480IntDf ;
126 
127     //----- Allocate frame buffer
128     xfb_size = VIPadFrameBufferWidth(rmode_p->fbWidth) * rmode_p->xfbHeight * (u32)VI_DISPLAY_PIX_SZ ;
129     xfb_p[0] = OSAlloc( xfb_size ) ;
130     xfb_p[1] = OSAlloc( xfb_size ) ;
131 
132     //----- Select a drawing buffer and display buffer
133     draw_xfb_idx = 0 ;
134     disp_xfb_idx = 1 ;
135 
136     //----- Initialize VI
137     VIConfigure( rmode_p ) ;
138     VISetNextFrameBuffer( xfb_p[ disp_xfb_idx ] ) ;
139     VIFlush() ;
140 
141     VIWaitForRetrace() ;	// In order to enable Configure,
142     VIWaitForRetrace() ;	//  you need to wait two times.
143 }
144 
145 
146 /*******************************************************************************
147 	Initialize GX relationship
148  *******************************************************************************/
init_gx(void)149 static void init_gx( void )
150 {
151     GXColor		clear_clr = { 0,0,0, 0 } ;
152 
153 
154     //----- Create GXFIFO
155     gx_fifo_p   = OSAlloc( GX_FIFO_SIZE ) ;
156     gx_fifo_obj = GXInit( gx_fifo_p, GX_FIFO_SIZE ) ;
157 
158     //----- Select pixel format
159     GXSetPixelFmt( GX_PF_RGB8_Z24, GX_ZC_LINEAR ) ;
160     GXSetDither( GX_DISABLE ) ;
161 
162     //----- Initialize settings for copying from EFB to XFB
163     GXSetDispCopySrc( 0, 0, rmode_p->fbWidth, rmode_p->efbHeight ) ;
164     GXSetDispCopyDst( rmode_p->fbWidth, rmode_p->xfbHeight ) ;
165     (void)GXSetDispCopyYScale( (f32)(rmode_p->xfbHeight) / (f32)(rmode_p->efbHeight) ) ;
166     GXSetDispCopyGamma( GX_GM_1_0 ) ;
167 
168     GXSetCopyFilter( rmode_p->aa, rmode_p->sample_pattern, GX_ENABLE, vfilter ) ;
169     GXSetCopyClear( clear_clr, 0x00FFFFFF ) ;
170 
171     //----- Initialize EFB drawing area
172     GXSetViewport( 0.0f, 0.0f, rmode_p->fbWidth, rmode_p->efbHeight, 0.0f, 1.0f ) ;
173     GXSetScissor( 0, 0, (u32)rmode_p->fbWidth, (u32)rmode_p->efbHeight ) ;
174 
175     //----- Clear EFB and XFB
176     GXCopyDisp( xfb_p[0], GX_ENABLE ) ;	// The EFB is cleared and garbage is placed in XFB[0]
177     GXCopyDisp( xfb_p[0], GX_DISABLE ) ;	// The cleared EFB is placed in XFB[0]
178     GXCopyDisp( xfb_p[1], GX_DISABLE ) ;	// The cleared EFB is placed in XFB[1]
179     GXDrawDone() ;
180 }
181 
182 
183 /*******************************************************************************
184 	Main
185  *******************************************************************************/
main(void)186 void main( void )
187 {
188     /***********************************************************************
189 		Initialization processing
190      ***********************************************************************/
191     //----- Highest-priority hardware initialization
192     VIInit() ;
193 
194     //----- Other priority initializations
195     init_memory() ;		// Enable allocation and release of memory
196     init_memory2();
197     init_display() ;	// Display device-related
198     init_gx() ;		// GX-related
199     WPADRegisterAllocator(alloc32, free32);
200     KPADInit() ;		// Controller
201 
202 
203 
204     //----- Initialize application
205     init_kfont_texture() ;
206     init_sample() ;
207 
208     //----- Screen display ON
209     VISetBlack( FALSE ) ;
210     VIFlush() ;
211 
212 
213     /***********************************************************************
214 		Main loop
215      ***********************************************************************/
216     while (1) {
217         /***************************************************************
218 			First, perform calculations by the CPU
219 			Then find coordinates based on controller input,
220 			And prepare the data necessary to issue a GX command
221          ***************************************************************/
222         //----- Load controller
223         kpad_reads = KPADRead( 0, &kpads[0][0], KPAD_MAX_READ_BUFS ) ;
224 
225         //----- Various calculations
226         work_sample() ;
227 
228 
229         /***************************************************************
230 			Issue GX command and go on drawing to EFB
231          ***************************************************************/
232         //----- Cast spell to start issuing the command
233         GXInvalidateVtxCache() ;
234         GXInvalidateTexAll() ;
235 
236         //----- Issue various commands
237         draw_sample() ;
238 
239         //----- Finally, copy from EFB to XFB
240         GXCopyDisp( xfb_p[ draw_xfb_idx ], GX_ENABLE ) ;
241         GXDrawDone() ;
242 
243 
244         /***************************************************************
245 			The XFB copied here can be selected for display on the TV
246          ***************************************************************/
247         disp_xfb_idx = draw_xfb_idx ;
248         VISetNextFrameBuffer( xfb_p[ disp_xfb_idx ] ) ;
249         VIFlush() ;
250 
251         //----- Wait for the display to actually switch
252         VIWaitForRetrace() ;
253 
254         //----- Switch to the no longer displayed XFB ahead of time for the next drawing
255         draw_xfb_idx ^= 1 ;
256     }
257 }
258 
259