00001
00002
00003 This file is subject to the terms and conditions of the GNU Lesser
00004 General Public License Version 2.1. See the file "COPYING" in the
00005 main directory of this archive for more details. */
00006
00007 #include <stdlib.h>
00008 #include <stdio.h>
00009 #include <math.h>
00010 #include <linux/ps2/gs.h>
00011 #include <sys/ioctl.h>
00012
00013 #include <sys/mman.h>
00014
00015 #include "ps2gs.h"
00016 #include "ps2dma.h"
00017 #include "ps2vpu.h"
00018 #include "ps2vpufile.h"
00019
00020
00021 #include "sjoy.h"
00022
00023 #include "GL/glut.h"
00024 #include "GL/ps2gl.h"
00025
00026 #include "ps2s/timer.h"
00027 #include "ps2s/gs.h"
00028 #include "ps2s/packet.h"
00029 #include "ps2s/displayenv.h"
00030
00031 #include "ps2gl/debug.h"
00032
00033
00034
00035 struct ps2_vpu_struct {
00036 int fd;
00037 int vpu;
00038 unsigned int mapsize;
00039 void *text;
00040 unsigned int text_size;
00041 void *data;
00042 unsigned int data_size;
00043 };
00044
00045
00046 * some function pointer types
00047 */
00048
00049 typedef void (* tFunctionPtr_ii) (int, int);
00050 typedef void (* tFunctionPtr_ucii) (unsigned char, int, int);
00051 typedef void (* tFunctionPtr_iii) (int, int, int);
00052 typedef void (* tFunctionPtr) (void);
00053 typedef void (* tFunctionPtr_i) (int);
00054
00055
00056 * local functions
00057 */
00058
00059 static void initGsMemory();
00060 static bool doPads( int frameCount );
00061 static void parse_cl( int *argcp, char **argv );
00062
00063
00064 * local data
00065 */
00066
00067 tFunctionPtr DisplayFunc = NULL;
00068 tFunctionPtr_ii ReshapeFunc = NULL;
00069 tFunctionPtr_ucii KeyboardFunc = NULL;
00070 tFunctionPtr_i VisibilityFunc = NULL;
00071 tFunctionPtr IdleFunc = NULL;
00072 tFunctionPtr_iii SpecialFunc = NULL;
00073
00074 static CEETimer *Timer2, *Timer3;
00075
00076
00077
00078 int g_inter;
00079 int g_out_mode;
00080 int g_ff_mode;
00081 int g_resolution;
00082 int g_refresh_rate;
00083 int g_psm;
00084 int g_zpsm;
00085 int g_zbits;
00086
00087 int g_fd_gs;
00088 ps2_vpu *g_vpu0, *g_vpu1;
00089
00090 typedef enum { eNtsc, eVesa0 } screen_mode_t;
00091 screen_mode_t screen_mode = eVesa0;
00092
00093 int release(void)
00094 {
00095 if (g_vpu1) {
00096 ps2_vpu_close(g_vpu1);
00097 g_vpu1 = NULL;
00098 }
00099
00100 if (g_vpu0) {
00101 ps2_vpu_close(g_vpu0);
00102 g_vpu0 = NULL;
00103 }
00104
00105 if (g_fd_gs >= 0) {
00106 ps2_gs_close();
00107 g_fd_gs = -1;
00108 }
00109
00110 return PS2_GS_VC_REL_SUCCESS;
00111 }
00112
00113 int acquire(void)
00114 {
00115 g_fd_gs = ps2_gs_open(-1);
00116 g_vpu0 = ps2_vpu_open(0);
00117 g_vpu1 = ps2_vpu_open(1);
00118
00119 if (g_fd_gs < 0 || g_vpu0 == NULL || g_vpu1 == NULL) {
00120 release();
00121 return PS2_GS_VC_ACQ_FAILURE;
00122 }
00123
00124 ps2_vpu_reset(g_vpu1);
00125 ps2_vpu_reset(g_vpu0);
00126
00127 ps2_gs_reset(0, g_inter, g_out_mode, g_ff_mode, g_resolution,
00128 g_refresh_rate);
00129
00130 return PS2_GS_VC_ACQ_SUCCESS;
00131 }
00132
00133
00134 * glut implementation (loosely speaking..)
00135 */
00136
00155
00156 extern "C" int setcrtmode(int argc, char **argv, int gs_fd);
00157
00158 # include <unistd.h>
00159 # include <sys/stat.h>
00160 # include <fcntl.h>
00161 # include <errno.h>
00162 #include <string.h>
00163
00164 int Ps2stuffDeviceFd = -1;
00165 bool WaitForVsync = true;
00166
00174 void glutInit(int *argcp, char **argv)
00175 {
00176 parse_cl( argcp, argv );
00177
00178 if ( screen_mode == eVesa0 ) {
00179 printf("vesa0 mode\n");
00180 g_inter = PS2_GS_NOINTERLACE;
00181 g_out_mode = PS2_GS_VESA;
00182 g_ff_mode = PS2_GS_FRAME;
00183 g_resolution = PS2_GS_640x480;
00184 }
00185 else if ( screen_mode == eNtsc ) {
00186 printf("ntsc1 mode\n");
00187 g_inter = PS2_GS_NOINTERLACE;
00188 g_out_mode = PS2_GS_NTSC;
00189 g_ff_mode = PS2_GS_FRAME;
00190 g_resolution = PS2_GS_640x480;
00191 }
00192
00193 g_refresh_rate = PS2_GS_60Hz;
00194 g_psm = PS2_GS_PSMCT32;
00195 g_zpsm = PS2_GS_PSMZ32;
00196 g_zbits = 32;
00197
00198 ps2_gs_vc_graphicsmode();
00199
00200 g_fd_gs = ps2_gs_open(-1);
00201 g_vpu0 = ps2_vpu_open(0);
00202 g_vpu1 = ps2_vpu_open(1);
00203
00204 Ps2stuffDeviceFd = open( "/dev/ps2stuff", O_RDWR );
00205 if ( Ps2stuffDeviceFd < 0 ) {
00206 fprintf( stderr, "Couldn't open /dev/ps2stuff: %s\n", strerror(errno) );
00207 exit(-1);
00208 }
00209
00210 ioctl( Ps2stuffDeviceFd, PS2STUFF_IOCTMEMRESET );
00211
00212
00213
00214 CDmaPacket::InitFileDescriptors( g_fd_gs, g_vpu0->fd, g_vpu1->fd, Ps2stuffDeviceFd );
00215 GS::CDisplayEnv::InitGsFd( g_fd_gs );
00216
00217 ps2_gs_reset(0, g_inter, g_out_mode, g_ff_mode, g_resolution,
00218 g_refresh_rate);
00219
00220 ps2_gs_start_display(1);
00221
00222 ps2_gs_vc_enablevcswitch(acquire, release);
00223
00224 ps2_gs_sync_v(0);
00225
00226
00227
00228 if ( ! pglHasLibraryBeenInitted() ) {
00229 mWarn( "ps2gl library has not been initialized by the user; using default values." );
00230 int immBufferVertexSize = 8 * 1024;
00231 pglInit( immBufferVertexSize, 1000 );
00232 }
00233
00234
00235
00236 if ( ! pglHasGsMemBeenInitted() ) {
00237 mWarn("GS memory has not been allocated by the user; using default values.");
00238 initGsMemory();
00239 }
00240
00241
00242
00243 Timer2 = new CEETimer( CEETimer::Timer2 );
00244
00245
00246
00247 mInitTimers( Timer2, CEETimer::BusClock_256th );
00248
00249
00250 sjoy_open();
00251 }
00252
00256 void glutDisplayFunc(void (*func)(void))
00257 {
00258 DisplayFunc = func;
00259 }
00260
00266 void glutReshapeFunc(void (*func)(int width, int height))
00267 {
00268 ReshapeFunc = func;
00269 }
00270
00276 void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y))
00277 {
00278 KeyboardFunc = func;
00279 }
00280
00286 void glutVisibilityFunc(void (*func)(int state))
00287 {
00288 VisibilityFunc = func;
00289 }
00290
00295 void glutIdleFunc(void (*func)(void))
00296 {
00297 IdleFunc = func;
00298 }
00299
00305 void glutSpecialFunc(void (*func)(int key, int x, int y))
00306 {
00307 SpecialFunc = func;
00308 }
00309
00314 void glutMainLoop( void )
00315 {
00316 mErrorIf( DisplayFunc == NULL, "ps2glut: No display function!" );
00317
00318 if ( ReshapeFunc )
00319 ReshapeFunc( 640, 480 );
00320
00321 if ( VisibilityFunc )
00322 VisibilityFunc( GLUT_VISIBLE );
00323
00324 int frameCount = 0;
00325
00326 while(1) {
00327 mUpdateTimers();
00328
00329 mStartTimer("frame time");
00330
00331
00332
00333 bool printTimes = doPads( frameCount );
00334
00335 if ( DisplayFunc ) {
00336 mStartTimer("DisplayFunc()");
00337 pglBeginGeometry();
00338 DisplayFunc();
00339 pglEndGeometry();
00340 mStopTimer("DisplayFunc()");
00341 }
00342
00343 if ( IdleFunc ) {
00344 mStartTimer("IdleFunc()");
00345 IdleFunc();
00346 mStopTimer("IdleFunc()");
00347 }
00348
00349 mStartTimer("wait for vu1");
00350 pglFinishRenderingGeometry( PGL_DONT_FORCE_IMMEDIATE_STOP );
00351 mStopTimer("wait for vu1");
00352
00353 mStopTimer("frame time");
00354
00355 if ( printTimes ) {
00356 mDisplayTimers();
00357 printTimes = false;
00358 }
00359
00360 if ( WaitForVsync )
00361 pglWaitForVSync();
00362
00363 pglSwapBuffers();
00364
00365 pglRenderGeometry();
00366
00367 frameCount++;
00368
00369
00370 }
00371 }
00372
00374
00375 static void
00376 parse_cl( int *argcp, char **argv )
00377 {
00378 for ( int i = 0; i < *argcp; i++ ) {
00379 bool found = false;
00380
00381 if ( strstr(argv[i], "-ntsc1") == argv[i] ) {
00382 screen_mode = eNtsc;
00383 found = true;
00384 }
00385 else if ( strstr(argv[i], "-vesa0") == argv[i] ) {
00386 screen_mode = eVesa0;
00387 found = true;
00388 }
00389
00390 if ( found ) argv[i] = NULL;
00391 }
00392
00393
00394
00395 int numArgs = *argcp;
00396 for ( int i = 0; i < numArgs; i++ ) {
00397 if ( argv[i] == NULL ) {
00398
00399 for ( int j = i; j < numArgs - 1; j++ )
00400 argv[j] = argv[j+1];
00401 *argcp -= 1;
00402 }
00403 }
00404 }
00405
00406 static bool
00407 doPads( int frameCount )
00408 {
00409 static int paddata = 0;
00410
00411 sjoy_poll();
00412 paddata = sjoy_get_ps2_button(0);
00413
00414 bool printTimes = ( paddata & SJOY_PS2_START );
00415
00416 if ( SpecialFunc ) {
00417 if ( (frameCount % 15) == 0 ) {
00418 if ( paddata & SJOY_PS2_L_UP ) {
00419 SpecialFunc( GLUT_KEY_UP, 0, 0 );
00420 }
00421 if ( paddata & SJOY_PS2_L_DOWN ) {
00422 SpecialFunc( GLUT_KEY_DOWN, 0, 0 );
00423 }
00424 if ( paddata & SJOY_PS2_L_RIGHT ) {
00425 SpecialFunc( GLUT_KEY_RIGHT, 0, 0 );
00426 }
00427 if ( paddata & SJOY_PS2_L_LEFT ) {
00428 SpecialFunc( GLUT_KEY_LEFT, 0, 0 );
00429 }
00430
00431 if ( paddata & SJOY_PS2_L1 ) {
00432 SpecialFunc( GLUT_KEY_HOME, 0, 0 );
00433 }
00434 if ( paddata & SJOY_PS2_L2 ) {
00435 SpecialFunc( GLUT_KEY_END, 0, 0 );
00436 }
00437
00438 if ( paddata & SJOY_PS2_R1 ) {
00439 WaitForVsync = ! WaitForVsync;
00440 SpecialFunc( GLUT_KEY_PAGE_UP, 0, 0 );
00441 }
00442 if ( paddata & SJOY_PS2_R2 ) {
00443 SpecialFunc( GLUT_KEY_PAGE_DOWN, 0, 0 );
00444 }
00445 }
00446 }
00447
00448 if ( KeyboardFunc ) {
00449 if ( paddata & SJOY_PS2_R_UP ) {
00450 KeyboardFunc( '8', 0, 0 );
00451 }
00452 if ( paddata & SJOY_PS2_R_DOWN ) {
00453 KeyboardFunc( '2', 0, 0 );
00454 }
00455 if ( paddata & SJOY_PS2_R_LEFT ) {
00456 KeyboardFunc( '4', 0, 0 );
00457 }
00458 if ( paddata & SJOY_PS2_R_RIGHT ) {
00459 KeyboardFunc( '6', 0, 0 );
00460 }
00461 }
00462
00463 return printTimes;
00464 }
00465
00466
00467 void glutInitDisplayMode(unsigned int mode)
00468 {
00469 mNotImplemented( );
00470 }
00471
00472 void glutInitWindowPosition( int x, int y )
00473 {
00474 mNotImplemented( );
00475 }
00476
00477 void glutInitWindowSize( int x, int y )
00478 {
00479 mNotImplemented( );
00480 }
00481
00482 int glutCreateWindow(const char *title)
00483 {
00484 mNotImplemented( );
00485
00486 return 1;
00487 }
00488
00489 void glutPostRedisplay(void)
00490 {
00491
00492 }
00493
00494 void glutSwapBuffers( void )
00495 {
00496 }
00497
00498 int glutGet(GLenum type)
00499 {
00500 mNotImplemented( );
00501 return 0;
00502 }
00503
00504 void*
00505 pglutAllocDmaMem( unsigned int num_bytes )
00506 {
00507
00508 return mmap(0, num_bytes,
00509 PROT_READ | PROT_WRITE,
00510 MAP_SHARED, Ps2stuffDeviceFd,
00511 0 );
00512 }
00513
00514 void
00515 pglutFreeDmaMem( void *mem )
00516 {
00517
00518 munmap( mem, 0 );
00519 }
00520
00521
00522 * local function definitions
00523 */
00524
00525 static void
00526 initGsMemory()
00527 {
00528
00529 pgl_slot_handle_t frame_slot_0, frame_slot_1, depth_slot;
00530 frame_slot_0 = pglAddGsMemSlot( 0, 150, GS::kPsm32 );
00531 frame_slot_1 = pglAddGsMemSlot( 150, 150, GS::kPsm32 );
00532 depth_slot = pglAddGsMemSlot( 300, 150, GS::kPsmz24 );
00533
00534 pglLockGsMemSlot( frame_slot_0 );
00535 pglLockGsMemSlot( frame_slot_1 );
00536 pglLockGsMemSlot( depth_slot );
00537
00538
00539
00540
00541 int fb_height = 480, interlace = PGL_NONINTERLACED;
00542
00543 if ( screen_mode == eNtsc ) {
00544 fb_height = 224;
00545 interlace = PGL_INTERLACED;
00546 }
00547
00548
00549 pgl_area_handle_t frame_area_0, frame_area_1, depth_area;
00550 frame_area_0 = pglCreateGsMemArea( 640, fb_height, GS::kPsm24 );
00551 frame_area_1 = pglCreateGsMemArea( 640, fb_height, GS::kPsm24 );
00552 depth_area = pglCreateGsMemArea( 640, fb_height, GS::kPsmz24 );
00553
00554 pglBindGsMemAreaToSlot( frame_area_0, frame_slot_0 );
00555 pglBindGsMemAreaToSlot( frame_area_1, frame_slot_1 );
00556 pglBindGsMemAreaToSlot( depth_area, depth_slot );
00557
00558
00559 pglSetDrawBuffers( interlace, frame_area_0, frame_area_1, depth_area );
00560
00561 pglSetDisplayBuffers( interlace, frame_area_0, frame_area_1 );
00562
00563
00564
00565
00566 pglAddGsMemSlot( 450, 1, GS::kPsm32 );
00567 pglAddGsMemSlot( 451, 1, GS::kPsm32 );
00568
00569 pglAddGsMemSlot( 452, 2, GS::kPsm32 );
00570 pglAddGsMemSlot( 454, 2, GS::kPsm32 );
00571
00572 pglAddGsMemSlot( 456, 8, GS::kPsm32 );
00573 pglAddGsMemSlot( 464, 8, GS::kPsm32 );
00574 pglAddGsMemSlot( 472, 8, GS::kPsm32 );
00575
00576 pglAddGsMemSlot( 480, 32, GS::kPsm32 );
00577
00578 pglPrintGsMemAllocation();
00579 }