diff options
| author | Xavi Del Campo <xavi.dcr@tutanota.com> | 2020-01-31 10:32:23 +0100 |
|---|---|---|
| committer | Xavi Del Campo <xavi.dcr@tutanota.com> | 2020-01-31 10:32:23 +0100 |
| commit | 7c24e9a9b02b04dcaf9507acb94091ea70a2c02d (patch) | |
| tree | c28d0748652ad4b4222309e46e6cfc82c0906220 /examples | |
| parent | a2b7b6bb1cc2f4a3258b7b2dbc92399d151f864d (diff) | |
| download | psxsdk-7c24e9a9b02b04dcaf9507acb94091ea70a2c02d.tar.gz | |
Imported pristine psxsdk-20190410 from official repo
Diffstat (limited to 'examples')
33 files changed, 3538 insertions, 0 deletions
diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000..90bb904 --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,25 @@ +include ../Makefile.cfg + +all: + $(MAKE_COMMAND) -C mandel + $(MAKE_COMMAND) -C memview + $(MAKE_COMMAND) -C psxmod + $(MAKE_COMMAND) -C psxpaint + $(MAKE_COMMAND) -C psxsnake + $(MAKE_COMMAND) -C puzzle + $(MAKE_COMMAND) -C rottest + $(MAKE_COMMAND) -C psxs3m + $(MAKE_COMMAND) -C gtecube + +clean: + $(MAKE_COMMAND) -C mandel clean + $(MAKE_COMMAND) -C memview clean + $(MAKE_COMMAND) -C psxmod clean + $(MAKE_COMMAND) -C psxpaint clean + $(MAKE_COMMAND) -C psxsnake clean + $(MAKE_COMMAND) -C puzzle clean + $(MAKE_COMMAND) -C rottest clean + $(MAKE_COMMAND) -C psxs3m clean + $(MAKE_COMMAND) -C gtecube clean + +distclean: clean diff --git a/examples/gtecube/Makefile b/examples/gtecube/Makefile new file mode 100644 index 0000000..98789d3 --- /dev/null +++ b/examples/gtecube/Makefile @@ -0,0 +1,8 @@ +PROJNAME = gtecube +PROJ_LIBS = -lmeidogte + +include ../project.mk + +$(PROJNAME)_extra: + +$(PROJNAME)_clean_extra: diff --git a/examples/gtecube/gtecube.c b/examples/gtecube/gtecube.c new file mode 100644 index 0000000..b5dda19 --- /dev/null +++ b/examples/gtecube/gtecube.c @@ -0,0 +1,448 @@ +/* + * GTE Graphics Example (Spinning Cube) + * 2019 Meido-Tek Productions + * 2019 modified by nextvolume for PSXSDK + * + * licensed under Mozilla Public License v2.0 + */ + +#include <stdio.h> +#include <string.h> +#include <psx.h> +#include <psxgpu.h> +#include <meidogte.h> + +/* Screen resolution */ +#define SCREEN_XRES 320 +#define SCREEN_YRES 240 + +/* Screen center position */ +#define CENTERX SCREEN_XRES>>1 +#define CENTERY SCREEN_YRES>>1 + +#define OT_LEN 0x8000 + +/* For easier handling of vertex indices */ +typedef struct { + short v0,v1,v2,v3; +} INDEX; + +/* Cube vertices */ +SVECTOR cube_verts[] = { + { -100, -100, -100, 0 }, + { 100, -100, -100, 0 }, + { -100, 100, -100, 0 }, + { 100, 100, -100, 0 }, + { 100, -100, 100, 0 }, + { -100, -100, 100, 0 }, + { 100, 100, 100, 0 }, + { -100, 100, 100, 0 } +}; + +/* Cube face normals */ +SVECTOR cube_norms[] = { + { 0, 0, -ONE, 0 }, + { 0, 0, ONE, 0 }, + { 0, -ONE, 0, 0 }, + { 0, ONE, 0, 0 }, + { -ONE, 0, 0, 0 }, + { ONE, 0, 0, 0 } +}; + +/* Cube vertex indices */ +INDEX cube_indices[] = { + { 0, 1, 2, 3 }, + { 4, 5, 6, 7 }, + { 5, 4, 0, 1 }, + { 6, 7, 3, 2 }, + { 0, 2, 5, 7 }, + { 3, 1, 6, 4 } +}; + +/* Number of faces of cube */ +#define CUBE_FACES 6 + +/* Light color matrix */ +/* Each column represents the color matrix of each light source and is */ +/* used as material color when using gte_ncs() or multiplied by a */ +/* source color when using gte_nccs(). 4096 is 1.0 in this matrix */ +/* A column of zeroes disables the light source. */ +MATRIX color_mtx = { .m = { + {ONE, 0, 0}, /* Red */ + {ONE, 0, 0}, /* Green */ + {ONE, 0, 0} /* Blue */ } +}; + +/* Light matrix */ +/* Each row represents a vector direction of each light source. */ +/* An entire row of zeroes disables the light source. */ +MATRIX light_mtx = { .m = { + /* X, Y, Z */ + { -2048 , -2048 , -2048}, + {0 , 0 , 0}, + {0 , 0 , 0} } +}; + + +/* Function declarations */ +void init(void); +void display(void); + +unsigned int prim_list[OT_LEN]; +int current_buf = 0; +volatile int vblank_happened = 0; + +GsPoly4 poly[CUBE_FACES]; /* Flat shaded quad primitive */ + +static void program_vblank_handler(void) { + vblank_happened = 1; +} + +enum { + OP_SPIN, + OP_COLORR1, OP_COLORG1, OP_COLORB1, + OP_COLORR2, OP_COLORG2, OP_COLORB2, + OP_COLORR3, OP_COLORG3, OP_COLORB3, + OP_LIGHTX1, OP_LIGHTY1, OP_LIGHTZ1, + OP_LIGHTX2, OP_LIGHTY2, OP_LIGHTZ2, + OP_LIGHTX3, OP_LIGHTY3, OP_LIGHTZ3, + OP_SCRXOFF, OP_SCRYOFF, + OP_SCRDEPTH, + OP_TRANSVX, OP_TRANSVY, OP_TRANSVZ, + OP_END +}; + +const char *operationNames[] = {"Change spinning speed", + "Change light color R1", "Change light color G1", "Change light color B1", + "Change light color R2", "Change light color G2", "Change light color B2", + "Change light color R3", "Change light color G3", "Change light color B3", + "Change light X1", "Change light Y1", "Change light Z1", + "Change light X2", "Change light Y2", "Change light Z2", + "Change light X3", "Change light Y3", "Change light Z3", + "Change screen X offset", "Change screen Y offset", + "Change screen depth", + "Change translation vector X", "Change translation vector Y", + "Change translation vector Z", + }; + +int stopped = 0; +int currentOperation = 0; + +int spinningSpeed = 16; +int screenXOffset = CENTERX; +int screenYOffset = CENTERY; +int screenDepth = CENTERX; + +VECTOR pos = { .vx = 0, .vy = 0, .vz = 400 }; /* Translation vector for TransMatrix */ + +#define COLOR_STEP 32 +#define LIGHT_STEP 128 + +/* Main function */ +int main() { + + int i,p,wasStart=0,wasLeft=0,wasRight=0; + int a,b; + short coord[2]; + unsigned char rgb[3] = {255, 255, 0}; + unsigned short padbuf; + + SVECTOR rot; /* Rotation vector for Rotmatrix */ + MATRIX mtx,lmtx; /* Rotation matrices for geometry and lighting */ + + bzero(&rot, sizeof(rot)); + + /* Init graphics and GTE */ + init(); + + /* Main loop */ + while( 1 ) { + /* Set GTE offset (recommended method of centering) */ + gte_SetGeomOffset( screenXOffset, screenYOffset ); + + /* Set screen depth (basically FOV control, W/2 works best) */ + gte_SetGeomScreen(screenDepth); + + /* Set light ambient color and light color matrix */ + gte_SetBackColor( 63, 63, 63 ); + gte_SetColorMatrix( &color_mtx ); + + /* Set rotation and translation to the matrix */ + RotMatrix( &rot, &mtx ); + TransMatrix( &mtx, &pos ); + + /* Multiply light matrix by rotation matrix so light source */ + /* won't appear relative to the model's rotation */ + MulMatrix0( &light_mtx, &mtx, &lmtx ); + + /* Set rotation and translation matrix */ + gte_SetRotMatrix( &mtx ); + gte_SetTransMatrix( &mtx ); + + /* Set light matrix */ + gte_SetLightMatrix( &lmtx ); + + if (!stopped) { + /* Make the cube SPEEN */ + rot.vx += spinningSpeed; + rot.vz += spinningSpeed; + } + + for( i=0; i<CUBE_FACES; i++ ) { + + /* Load the first 3 vertices of a quad to the GTE */ + gte_ldv3( + &cube_verts[cube_indices[i].v0], + &cube_verts[cube_indices[i].v1], + &cube_verts[cube_indices[i].v2] ); + + /* Rotation, Translation and Perspective Triple */ + gte_rtpt(); + + /* Compute normal clip for backface culling */ + gte_nclip(); + + /* Get result*/ + gte_stopz( &p ); + + /* Skip this face if backfaced */ + if( p < 0 ) { + poly[i].attribute = -1; + continue; + } + + /* Calculate average Z for depth sorting */ + gte_avsz4(); + gte_stotz( &p ); + + /* Skip if clipping off */ + /* (the shift right operator is to scale the depth precision) */ + if( (p>>2) > OT_LEN ) { + poly[i].attribute = -1; + continue; + } + + /* Set the projected vertices to the primitive */ + gte_stsxy0( &coord ); + poly[i].x[0] = coord[0]; + poly[i].y[0] = coord[1]; + + gte_stsxy1( &coord ); + poly[i].x[1] = coord[0]; + poly[i].y[1] = coord[1]; + + gte_stsxy2( &coord ); + poly[i].x[2] = coord[0]; + poly[i].y[2] = coord[1]; + + /* Compute the last vertex and set the result */ + gte_ldv0( &cube_verts[cube_indices[i].v3] ); + gte_rtps(); + gte_stsxy( &coord ); + poly[i].x[3] = coord[0]; + poly[i].y[3] = coord[1]; + + rgb[0] = 255; + rgb[1] = 255; + rgb[2] = 255; + + gte_ldrgb( &rgb ); + + /* Load the face normal */ + gte_ldv0( &cube_norms[i] ); + + /* Normal Color Single */ + gte_nccs(); + + /* Store result to the primitive */ + gte_strgb( &rgb ); + + poly[i].r = rgb[0]; + poly[i].g = rgb[1]; + poly[i].b = rgb[2]; + + poly[i].attribute = 0; + } + + /* Swap buffers and draw the primitives */ + display(); + + /* Wait for VBlank to happen */ + vblank_happened = 0; + while(!vblank_happened); + + /* Read joypad status */ + PSX_ReadPad(&padbuf, NULL); + + /* Logic for real-time 'configuration' of the cube */ + if ((padbuf & PAD_START) && !wasStart) { + stopped = !stopped; + wasStart = 1; + } + + if ((padbuf & PAD_LEFT) && !wasLeft) { + currentOperation--; + + if (currentOperation < 0) + currentOperation = OP_END - 1; + + wasLeft = 1; + } + + if ((padbuf & PAD_RIGHT) && !wasRight) { + currentOperation++; + + if (currentOperation >= OP_END) + currentOperation = 0; + + wasRight = 1; + } + + if (padbuf & PAD_UP) { + switch(currentOperation) { + case OP_SPIN: + spinningSpeed++; + break; + case OP_COLORR1 ... OP_COLORB3: + a = (currentOperation - OP_COLORR1); + b = a % 3; + a /= 3; + + if(color_mtx.m[b][a] < ONE) + color_mtx.m[b][a]+=COLOR_STEP; + break; + case OP_LIGHTX1 ... OP_LIGHTZ3: + a = (currentOperation - OP_LIGHTX1); + b = a % 3; + a /= 3; + + if(light_mtx.m[a][b] < ONE) + light_mtx.m[a][b]+=LIGHT_STEP; + break; + case OP_SCRXOFF: + screenXOffset++; + break; + case OP_SCRYOFF: + screenYOffset++; + break; + case OP_SCRDEPTH: + screenDepth++; + break; + case OP_TRANSVX: + pos.vx++; + break; + case OP_TRANSVY: + pos.vy++; + break; + case OP_TRANSVZ: + pos.vz++; + break; + } + } + + if (padbuf & PAD_DOWN) { + switch(currentOperation) { + case OP_SPIN: + spinningSpeed--; + break; + case OP_COLORR1 ... OP_COLORB3: + a = (currentOperation - OP_COLORR1); + b = a % 3; + a /= 3; + + if(color_mtx.m[b][a] > 0) + color_mtx.m[b][a]-=COLOR_STEP; + break; + case OP_LIGHTX1 ... OP_LIGHTZ3: + a = (currentOperation - OP_LIGHTX1); + b = a % 3; + a /= 3; + + if(light_mtx.m[a][b] > 0) + light_mtx.m[a][b]-=LIGHT_STEP; + break; + case OP_SCRXOFF: + screenXOffset--; + break; + case OP_SCRYOFF: + screenYOffset--; + break; + case OP_SCRDEPTH: + screenDepth--; + break; + case OP_TRANSVX: + pos.vx--; + break; + case OP_TRANSVY: + pos.vy--; + break; + case OP_TRANSVZ: + pos.vz--; + break; + } + } + + if (!(padbuf & PAD_START)) + wasStart = 0; + + if (!(padbuf & PAD_LEFT)) + wasLeft = 0; + + if (!(padbuf & PAD_RIGHT)) + wasRight = 0; + } + + return 0; +} + +void init(void) { + /* Initialize PSXSDK */ + PSX_InitEx( 0 ); + /* Initialize the Graphic Synthesizer */ + GsInit(); + /* Clear video memory */ + GsClearMem(); + /* Set primitive list pointer */ + GsSetList( prim_list ); + /* Set automatic GPU waiting */ + GsSetAutoWait(); + /* Set 320x240 video mode */ + GsSetVideoMode(320, 240, EXAMPLES_VMODE); + /* Set VBlank Handler */ + SetVBlankHandler( program_vblank_handler ); + + /* Load text font in video memory */ + GsLoadFont(768, 0, 768, 256); + + /* Initialize the MeidoGTE library */ + InitGeom(); +} + +void display(void) { + int i; + + /* Change display and drawing environment settings */ + /* for double buffering */ + GsSetDispEnvSimple(0, current_buf ? 0 : 256); + GsSetDrawEnvSimple(0, current_buf ? 256 : 0, SCREEN_XRES, SCREEN_YRES); + current_buf = !current_buf; + + /* Clear the screen with the specified color */ + GsSortCls(63, 0, 127); + + /* Add cube faces to drawing list */ + for(i=0;i<CUBE_FACES;i++) { + if(poly[i].attribute != -1) + GsSortPoly4(&poly[i]); + } + + /* If stopped, show so on the screen */ + if (stopped) + GsPrintFont(0, 0, "Stopped"); + + /* Print current operation name on screen */ + GsPrintFont(0, GsScreenH-16, "%s", operationNames[currentOperation]); + + /* Draw list */ + GsDrawList(); +} diff --git a/examples/mandel/Makefile b/examples/mandel/Makefile new file mode 100644 index 0000000..74759a0 --- /dev/null +++ b/examples/mandel/Makefile @@ -0,0 +1,7 @@ +PROJNAME = mandel + +include ../project.mk + +$(PROJNAME)_extra: + +$(PROJNAME)_clean_extra: diff --git a/examples/mandel/mandel.c b/examples/mandel/mandel.c new file mode 100644 index 0000000..77eda4e --- /dev/null +++ b/examples/mandel/mandel.c @@ -0,0 +1,347 @@ +/* + * Simple fractal generator for the PlayStation + * + * by Giuseppe Gatta + * Placed in the Public Domain. + * + * Consider enabling compiler optimizations, for instance this code is much faster + * if you add -O3 to the gcc command line. + * + * The fractals are rendered at a 160x120 resolution in an array in memory, + * then this array is uploaded to video memory and handled as 8-bit image data. + * We render at 160x120 to speed rendering up because the PlayStation is a slow machine + * for doing this kind of thing. + * + * A sprite primitive is used to display the image data on the screen, and the primitive + * is scaled twice horizontally and vertically to cover the 320x240 screen with a 160x120 + * image. + * + * The fractal drawing code by default also exploits the simmetry of the Mandrelbot + * and Tricorn sets to further speed rendering up (2x). To have a real rendering of + * the Burning Ship fractal, though, you must disable simmetry because that fractal + * does not have this property. + * + * This is the description of the controls of this program: + * + * SELECT - Toggle palette (Red->Green->Blue->Yellow->Violet->Red->...) + * START - Render fractal + * X - Toggle type of fractal to render (Mandelbrot->Tricorn->Burning Ship->Mandelbrot->...) + * O - Toggle simmetry (on the screen as 'S') + * LEFT - Decrease multibrot power (displayed on the screen as 'M') + * RIGHT - Increase multibrot power + * UP - Decrease number of maximum iterations (on the screen as 'I') + * DOWN - Increase number of maximum iterations + */ + +#include <psx.h> +#include <stdio.h> + +unsigned char fractal_image_data[120][160]; +unsigned int prim_list[0x4000]; +unsigned short clut_buf[256]; + +volatile int frac_x=0, frac_y=0; + +enum +{ + FRAC_MANDELBROT, // Normal mandelbrot + FRAC_TRICORN, + FRAC_BSHIP, + FRAC_TF, + + FRAC_NOSIMM = 0x200, +}; + +/* + * Code based on http://reocities.com/CapeCanaveral/5003/mandel.htm + */ + +void mandrelbrot_int(int width, int height, int maxI, int type, int M) +{ + #define FIXSIZE 25 + #define mul(a,b) ((((long long)a)*(b))>>FIXSIZE) + #define fixpt(a) ((int)(((a)*(1<<FIXSIZE)))) + #define integer(a) (((a)+(1<<(FIXSIZE-1)))>>FIXSIZE) + + int x0,y0,x1,y1,p,q,xn; + double xmin=-2.5,ymin=-1.5,xmax=1.5,ymax=1.5,xs,ys; + int i,x,y,t; + int m; + + xs=(xmax-xmin)/width; + ys=(ymax-ymin)/height; + + t = type & 0xff; + + for (y=0;y<((type&FRAC_NOSIMM)?height:(height/2));y++) + { + for (x=0;x<width;x++) + { + p=fixpt(xmin+x*xs); // c_re + q=fixpt(ymin+y*ys); + xn=0; + x0=0; + y0=0; + i=0; + + while ((mul(xn,xn)+mul(y0,y0))<fixpt(4) && ++i<maxI) + { + switch(t) + { + case FRAC_BSHIP: + if(x0<0)x0=-x0; + if(y0<0)y0=-y0; + break; + case FRAC_TRICORN: + y0=-y0; + break; + } + + x1=x0; + y1=y0; + + for(m=1;m<M;m++) + { + xn=mul(x0,x1) - mul(y0,y1); + y0=mul(y0,x1) + mul(x0,y1); + x0=xn; + } + + x0=xn; + x0+=p; + y0+=q; + } + + if (i==maxI) i=1; + fractal_image_data[y][x] = (i*256)/maxI; + + if(!(type & FRAC_NOSIMM)) + fractal_image_data[(height-1)-y][x] = (i*256)/maxI; + } + } +} + +volatile int display_is_old = 1; +volatile int time_counter = 0; + +void prog_vblank_handler() +{ + display_is_old = 1; + time_counter++; +} + +int frac_type = FRAC_MANDELBROT; +unsigned int frac_maxI = 64; +int frac_M=2; + +const char *frac_type_string[] = + { "Mandelbrot", + "Tricorn", + "BurningShip"}; + +GsSprite frac_sprite; + +int main() +{ + int x, dbuf=0; + + int waspal=0; + int wastype=0; + int wasrender=0; + int wassimm=0; + int wasMm=0,wasMp=0, wasIm=0, wasIp=0; + int rendering_time = -1; + + unsigned short padbuf; + + PSX_InitEx(PSX_INIT_CD); + + GsInit(); + GsSetList(prim_list); + GsClearMem(); + GsSetVideoMode(320, 240, EXAMPLES_VMODE); + GsLoadFont(768, 0, 768, 256); + SetVBlankHandler(prog_vblank_handler); + +// Fill & upload CLUTs + +// Red CLUT + for(x = 0; x < 256; x++) + clut_buf[x] = ((x*4)>255?255:x*4)>>3; + + LoadImage(clut_buf, 512, 256, 256, 1); + while(GsIsDrawing()); + +// Green CLUT + for(x = 0; x < 256; x++) + clut_buf[x] = (((x*4)>255?255:x*4)>>3)<<5; + + LoadImage(clut_buf, 512, 257, 256, 1); + while(GsIsDrawing()); + +// Blue CLUT + for(x = 0; x < 256; x++) + clut_buf[x] = (((x*4)>255?255:x*4)>>3)<<10; + + LoadImage(clut_buf, 512, 258, 256, 1); + while(GsIsDrawing()); + + +// Yellow CLUT + for(x = 0; x < 256; x++) + { + clut_buf[x] = ((x*4)>255?255:x*4)>>3; + clut_buf[x]|= clut_buf[x]<<5; + } + + LoadImage(clut_buf, 512, 259, 256, 1); + while(GsIsDrawing()); + +// Violet CLUT + for(x = 0; x < 256; x++) + { + clut_buf[x] = ((x*4)>255?255:x*4)>>3; + clut_buf[x]|= clut_buf[x]<<10; + } + + LoadImage(clut_buf, 512, 260, 256, 1); + while(GsIsDrawing()); + + frac_sprite.tpage = 5; + frac_sprite.attribute = COLORMODE(COLORMODE_8BPP); + frac_sprite.u = 0; + frac_sprite.v = 0; + frac_sprite.cx = 512; + frac_sprite.cy = 256; + frac_sprite.x = 0; + frac_sprite.y = 0; + frac_sprite.w = 160; + frac_sprite.h = 120; + frac_sprite.r = frac_sprite.g = frac_sprite.b = NORMAL_LUMINOSITY; + frac_sprite.scalex = SCALE_ONE*2; + frac_sprite.scaley = SCALE_ONE*2; + + time_counter = 0; + mandrelbrot_int(160, 120, frac_maxI, frac_type, frac_M); + rendering_time = time_counter * (GsScreenM==VMODE_NTSC?17:20); + LoadImage(fractal_image_data, 320, 0, 80, 120); + while(GsIsDrawing()); + + while(1) + { + if(display_is_old) + { + dbuf=!dbuf; + GsSetDispEnvSimple(0, dbuf?0:256); + GsSetDrawEnvSimple(0, dbuf?256:0, 320, 240); + + GsSortCls(0,0,0); + GsSortSprite(&frac_sprite); + + GsPrintFont(0, 0, "Type: %s", frac_type_string[(frac_type&0xff)]); + GsPrintFont(0, 8, "I=%d, M=%d, S=%c", frac_maxI, frac_M, + frac_type&FRAC_NOSIMM?'N':'Y'); + GsPrintFont(0, 16, "Time: %d.%03d", rendering_time / 1000, rendering_time % 1000); + + GsDrawList(); + while(GsIsDrawing()); + + PSX_ReadPad(&padbuf, NULL); + + if((padbuf & PAD_SELECT) && !waspal) + { + frac_sprite.cy++; + if(frac_sprite.cy>260) + frac_sprite.cy = 256; + + waspal=1; + } + + if((padbuf & PAD_CROSS) && !wastype) + { + frac_type++; + if((frac_type & 0xff) >= FRAC_TF) + frac_type&=~0xff; + + wastype=1; + } + + if((padbuf & PAD_START) && !wasrender) + { + GsPrintFont(0, 224, "Rendering..."); + GsDrawList(); + while(GsIsDrawing()); + + dbuf=!dbuf; + GsSetDispEnvSimple(0, dbuf?0:256); + GsSetDrawEnvSimple(0, dbuf?256:0, 320, 240); + + time_counter = 0; + mandrelbrot_int(160, 120, frac_maxI, frac_type, frac_M); + rendering_time = time_counter * (GsScreenM==VMODE_NTSC?17:20); + LoadImage(fractal_image_data, 320, 0, 80, 120); + while(GsIsDrawing()); + + wasrender=1; + } + + if((padbuf & PAD_CIRCLE) && !wassimm) + { + frac_type ^= FRAC_NOSIMM; + wassimm=1; + } + + if((padbuf & PAD_LEFT) && !wasMm) + { + if(frac_M>2)frac_M--; + wasMm=1; + } + + if((padbuf & PAD_RIGHT) && !wasMp) + { + frac_M++; + wasMp=1; + } + + if((padbuf & PAD_UP) && !wasIm) + { + if(frac_maxI>1)frac_maxI--; + wasIm=1; + } + + if((padbuf & PAD_DOWN) && !wasIp) + { + frac_maxI++; + wasIp=1; + } + + if(!(padbuf & PAD_SELECT)) + waspal=0; + + if(!(padbuf & PAD_CROSS)) + wastype=0; + + if(!(padbuf & PAD_START)) + wasrender=0; + + if(!(padbuf & PAD_CIRCLE)) + wassimm=0; + + if(!(padbuf & PAD_LEFT)) + wasMm=0; + + if(!(padbuf & PAD_RIGHT)) + wasMp=0; + + if(!(padbuf & PAD_UP)) + wasIm=0; + + if(!(padbuf & PAD_DOWN)) + wasIp=0; + + display_is_old=0; + } + } + + return 0; +} diff --git a/examples/memview/Makefile b/examples/memview/Makefile new file mode 100644 index 0000000..55f05eb --- /dev/null +++ b/examples/memview/Makefile @@ -0,0 +1,7 @@ +PROJNAME = memview + +include ../project.mk + +$(PROJNAME)_extra: + +$(PROJNAME)_clean_extra: diff --git a/examples/memview/memview.c b/examples/memview/memview.c new file mode 100644 index 0000000..bf2e04a --- /dev/null +++ b/examples/memview/memview.c @@ -0,0 +1,249 @@ +/** + * PlayStation Memory Viewer + * by Giuseppe Gatta a.k.a. nextvolume + * + * PSXSDK Example - released to the Public Domain + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <psx.h> + +unsigned int cur_addr = 0x80000000; +unsigned int prim_list[0x20000]; + +int display_is_old = 1; +volatile int should_read_pad = 1; + +void pshex_vblank_handler() +{ + should_read_pad = 1; +} + +int main() +{ + unsigned short padbuf; + int y, f, x, x1; + int highres_mode=0; + int srp=0; + int wasup=0, wasdown=0, wasleft=0, wasright=0, wasl1=0, wasr1=0, + wasl2=0; + int wascross=0, wascircle=0, wasstart=0,wasselect=0; + unsigned int go_address = 0x80000000; + int go_pos = 0; + GsRectangle pshex_rect; + + + PSX_InitEx(0); + + GsInit(); + GsClearMem(); + + GsSetVideoMode(640, 240, VMODE_PAL); + GsSetList(prim_list); + GsSetDispEnvSimple(0, 0); + GsSetDrawEnvSimple(0, 0, 640, 240); + GsLoadFont(768, 0, 768, 256); + + SetVBlankHandler(pshex_vblank_handler); + + GsPrintFont(16, 16, "PAL/NTSC SELECTION"); + GsPrintFont(16, 32, "X - PAL"); + GsPrintFont(16, 40, "O - NTSC"); + GsDrawList(); + while(GsIsDrawing()); + + while(1) + { + if(should_read_pad) + { + PSX_ReadPad(&padbuf, NULL); + + if((padbuf & PAD_CROSS)) + { + GsSetVideoModeEx(640, 480, VMODE_PAL, 0, 1, 0); + wascross=1; + break; + } + + if((padbuf & PAD_CIRCLE)) + { + GsSetVideoModeEx(640, 480, VMODE_NTSC, 0, 1, 0); + wascircle=1; + break; + } + + should_read_pad=0; + } + } + + GsSetDrawEnvSimple(0, (GsScreenM==VMODE_PAL?8:0), 640, 480); + + while(1) + { + if(display_is_old) + { + GsSortCls(0, 0, 255); + + for(y = 0; y < (highres_mode?58:28); y++) + { + f = GsPrintFont(24, y*8, "%08x", cur_addr + (y*0x10)); + x1 = prfont_get_fx(f) + 16; + + for(x = 0; x < 16; x++) + { + if(( (x&3) == 0) && x>0) + x1+=16; + + f = GsPrintFont(x1, y*8, "%02x", *((unsigned char*)(cur_addr + (y*0x10) + x))); + x1 = prfont_get_fx(f) + 8; + } + + x1+=8; + + for(x=0;x<16;x++) + { + GsPrintFont(x1, y*8, "%c", *((unsigned char*)(cur_addr + (y*0x10) + x))); + x1+=8; + } + } + + pshex_rect.x = (go_pos * 8)+24; + pshex_rect.y = highres_mode?472:232; + pshex_rect.r = 255; + pshex_rect.g = 69; + pshex_rect.b = 0; + pshex_rect.attribute = 0; + pshex_rect.w = 8; + pshex_rect.h = 8; + GsSortRectangle(&pshex_rect); + + GsPrintFont(24, highres_mode?472:232, "%08X", go_address); + + GsDrawList(); + while(GsIsDrawing()); + display_is_old = 0; + } + + if(should_read_pad) + { + PSX_ReadPad(&padbuf, NULL); + + if((padbuf & PAD_UP) && !wasup) + { + cur_addr -= 0x10; + display_is_old = 1; + wasup = 1; + } + + if((padbuf & PAD_DOWN) && !wasdown) + { + cur_addr += 0x10; + display_is_old = 1; + wasdown = 1; + } + + if((padbuf & PAD_LEFT) && !wasleft) + { + cur_addr -= 0x100; + display_is_old = 1; + wasleft=1; + } + + if((padbuf & PAD_RIGHT) && !wasright) + { + cur_addr += 0x100; + display_is_old = 1; + wasright=1; + } + + if((padbuf & PAD_L1) && !wasl1) + { + if(go_pos>0)go_pos--; + display_is_old = 1; + wasl1=1; + } + + if((padbuf & PAD_R1) && !wasr1) + { + if(go_pos<7)go_pos++; + display_is_old = 1; + wasr1=1; + } + + if((padbuf & PAD_L2) && !wasl2) + { + go_pos = 0; + wasl2 = 1; + } + + if((padbuf & PAD_CROSS) && !wascross) + { + if(((go_address >> ((7-go_pos)<<2))&0xf) < 0xf) + go_address += 1 << ((7-go_pos)<<2); + + display_is_old = 1; + wascross=1; + } + + if((padbuf & PAD_CIRCLE) && !wascircle) + { + if(((go_address >> ((7-go_pos)<<2))&0xf) > 0) + go_address -= 1 << ((7-go_pos)<<2); + + display_is_old = 1; + wascircle = 1; + } + + if((padbuf & PAD_START) && !wasstart) + { + cur_addr = go_address; + display_is_old = 1; + wasstart=1; + } + + if((padbuf & PAD_SELECT) && !wasselect) + { + highres_mode = !highres_mode; + + GsSortCls(0,0,255); + GsDrawList(); + while(GsIsDrawing()); + + if(highres_mode) + { + GsSetVideoModeEx(640, 480, GsScreenM, 0, 1, 0); + GsSetDrawEnvSimple(0, (GsScreenM==VMODE_PAL)?8:0, 640, 480); + } + else + { + GsSetVideoMode(640, 240, GsScreenM); + GsSetDrawEnvSimple(0, (GsScreenM==VMODE_PAL)?8:0, 640, 240); + } + + display_is_old = 1; + wasselect = 1; + } + + if(!(padbuf & PAD_UP) || srp==5)wasup=0; + if(!(padbuf & PAD_DOWN) || srp==5)wasdown=0; + if(!(padbuf & PAD_LEFT) || srp==5)wasleft=0; + if(!(padbuf & PAD_RIGHT) || srp==5)wasright=0; + if(!(padbuf & PAD_L1))wasl1=0; + if(!(padbuf & PAD_R1))wasr1=0; + if(!(padbuf & PAD_L2))wasl2=0; + if(!(padbuf & PAD_CROSS) || srp==5)wascross=0; + if(!(padbuf & PAD_CIRCLE) || srp==5)wascircle=0; + if(!(padbuf & PAD_START)) wasstart=0; + if(!(padbuf & PAD_SELECT)) wasselect=0; + + should_read_pad = 0; + srp++; + if(srp > 5) srp=0; + } + } +} + +//AAAAAAAA 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF abcd diff --git a/examples/memview/memview.txt b/examples/memview/memview.txt new file mode 100644 index 0000000..dd21b57 --- /dev/null +++ b/examples/memview/memview.txt @@ -0,0 +1,70 @@ +This is a simple memory viewer for the PlayStation. +It shows you what is contained at the desired memory addresses in a way similar to that of hex editors. + +Obviously it is not as straigthforward to use as similar programs for general purpose computers because the PlayStation lacks a keyboard. +Also, *remember* that reading certain memory areas will crash the PlayStation hardware, and if that happens the only thing you can do is to reset the console. +See "Surefire Areas" below for areas which surely won't crash your hardware. + +At start, the memory viewer will begin viewing memory at 0x80000000 (start of RAM), +the resolution will be 640x240 (low-res) and the Go-Address will be 0x80000000. + +Terms: +Go-Address The address that will be used for the + "jump-to address" operation + +Control: +UP Decrease current address by 0x10 +DOWN Increase current address by 0x10 +LEFT Decrease current address by 0x100 +RIGHT Increase current address by 0x100 + +L1 Move to previous location in Go-Address +R1 Move to next location in Go-Address +L2 Move to first location in Go-Address +CROSS Increase nibble at current Go-Address location +CIRCLE Decrease nibble at current Go-Address location + +START Jump to Go-Address, + i.e. make the Go-Address the current address + +SELECT Switch between hi-res and low-res mode + Hi-res mode: 640x480 + Low-res mode: 640x240 (default) + +Surefire areas: +0x80000000-0x801fffff PlayStation RAM (2 megabytes) +0xbfc00000-0xbfc7ffff PlayStation BIOS ROM (512 kilobytes) + +Example of setting a Go-Address and jumping: + +Imagine that the current go-address is 0x80000000 and we want to jump to 0xC001D00D. +NOTE: A nibble is 4-bits long, and each digit in a hexadecimal number is a nibble. + +- Move to the first location in Go-Address -> L2 +- Increase the nibble at current Go-Address location until it is 0xC + -> as its current value is 0x8, due to the current go-address being 0x80000000, + press CROSS 4 times + >> after this operation, the current address is 0xC0000000 +- Move to the next location in Go-Address -> R1 +- The nibble at this location is already 0x0, so move to the next location -> R1 + >> after this operation, the current address is 0xC0000000 +- The nibble at this location is already 0x0, so move to the next location -> R1 + >> after this operation, the current address is 0xC0000000 +- Increase the nibble at current Go-Address location until it is 0x1 + -> as its current value is 0x0, press CROSS once + >> after this operation, the current address will be 0xC0010000 +- Move to the next location in Go-Address -> R1 +- Increase the nibble at current Go-Address location until it is 0xD + -> as its current value is 0x0, press CROSS 13 times + >> after this operation, the current address will be 0xC001D000 +- Move to the next location in Go-Address -> R1 +- The nibble at this location is already 0x0, so move to the next location -> R1 + >> after this operation, the current address is 0xC001D000 +- The nibble at this location is already 0x0, so move to the next location -> R1 + >> after this operation, the current address is 0xC001D000 +- Increase the nibble at current Go-Address location until it is 0xD + -> as its current value is 0x0, press CROSS 13 times + >> after this operation, the current address will be 0xC001D00D +- Jump to Go-Address -> START + >> The current address is now 0xC001D00D + diff --git a/examples/project.mk b/examples/project.mk new file mode 100644 index 0000000..5a72a80 --- /dev/null +++ b/examples/project.mk @@ -0,0 +1,18 @@ +# project.mk + +include ../../Makefile.cfg + +all: $(PROJNAME)_extra + mkdir -p cd_root + $(EXAMPLES_CC) $(EXAMPLES_CFLAGS) -DEXAMPLES_VMODE=$(EXAMPLES_VMODE) -o $(PROJNAME).elf $(PROJNAME).c \ + $(EXAMPLES_LIBS) $(PROJ_LIBS) $(EXAMPLES_LDFLAGS) + elf2exe $(PROJNAME).elf $(PROJNAME).exe + cp $(PROJNAME).exe cd_root + systemcnf $(PROJNAME).exe > cd_root/system.cnf + $(MKISOFS_COMMAND) -o $(PROJNAME).hsf -V $(PROJNAME) -sysid PLAYSTATION cd_root + mkpsxiso $(PROJNAME).hsf $(PROJNAME).bin $(CDLIC_FILE) + rm -f $(PROJNAME).hsf + +clean: $(PROJNAME)_clean_extra + rm -f $(PROJNAME).bin $(PROJNAME).cue $(PROJNAME).exe $(PROJNAME).elf + rm -fr cd_root diff --git a/examples/psxmod/Makefile b/examples/psxmod/Makefile new file mode 100644 index 0000000..7a410ec --- /dev/null +++ b/examples/psxmod/Makefile @@ -0,0 +1,16 @@ +PROJNAME = psxmod +PROJ_LIBS = -lmodplay -lm -ladpcm + +include ../project.mk + +SAMPLES = $(patsubst mods/%.mod, mods/%.smp, $(wildcard mods/*.mod)) + +$(PROJNAME)_extra: $(SAMPLES) + mkdir -p cd_root + cp -r mods cd_root + +$(PROJNAME)_clean_extra: + rm -f mods/*.smp + +mods/%.smp: mods/%.mod + mod4psx $< $@ diff --git a/examples/psxmod/psxmod.c b/examples/psxmod/psxmod.c new file mode 100644 index 0000000..f11f164 --- /dev/null +++ b/examples/psxmod/psxmod.c @@ -0,0 +1,472 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <psx.h> +#include <modplay.h> + +#if defined(EXAMPLES_VMODE) == VMODE_PAL + #define TICKS_PER_SECOND 50 +#else + #define TICKS_PER_SECOND 60 +#endif + +unsigned char fileBuffer[0x80000]; // 512 kilobytes + +unsigned int primList[0x8000]; +int dbuf = 0; +volatile int display_is_old = 1; +char current_dir[256] = "cdrom:"; +char name_buf[24]; +char name_buf2[32]; +ModMusic *music = NULL; +int music_loop; +char *music_player_fname; +int music_player_time; +short music_player_vol; +int music_player_vol_pc; + +GsRectangle prog_rect; + +void program_vblank_handler() +{ + display_is_old = 1; +} + +struct +{ + char name[20]; + int size; + int type; /* 0 = file, 1 = directory */ +}file_list[256]; + +int file_list_size = 0; +int file_list_pos = 0; + +int wasUp = 0; +int wasDown = 0; +int wasEnter = 0; +int wasLeft = 0; +int wasRight = 0; + +void update_file_list() +{ + struct DIRENTRY de; + struct DIRENTRY *r; + char *cp; + int i, k=0; + + if(strcmp(current_dir, "cdrom:") != 0) + { + strcpy(file_list[0].name, ".."); + file_list[0].type = 1; + k=1; + } + + r = firstfile("cdrom:*", &de); + + for(i = k; i < 256 && r; i++) + { + if(de.name[0] == 0x1) + { +// Throw away useless entry. + r = nextfile(&de); + i--; + continue; + } + + memcpy(file_list[i].name, de.name, 20); + + if((cp = strrchr(file_list[i].name, ';'))) + { + *cp = '\0'; + file_list[i].type = 0; + } + else + file_list[i].type = 1; + + file_list[i].size = de.size; + + r = nextfile(&de); + } + + file_list[i].size = -1; + file_list_size = i; +} + +void file_browser(int redraw) +{ + int i, k, ok, allowed_ext; + unsigned short padbuf; + char *cp; + FILE *f; + + PSX_ReadPad(&padbuf, NULL); + + if(wasUp) + wasUp++; + + if(wasDown) + wasDown++; + + if((padbuf & PAD_UP) && !wasUp) + { + if(file_list_pos > 0) + { + file_list_pos--; + redraw=1; + } + + wasUp=1; + } + + if((padbuf & PAD_DOWN) && !wasDown) + { + file_list_pos++; + + if(file_list[file_list_pos].size == -1) + file_list_pos--; + else + redraw = 1; + + wasDown = 1; + } + + if((padbuf & PAD_CROSS) && !wasEnter) + { + if(file_list[file_list_pos].type == 1) + allowed_ext = 1; + else + allowed_ext = 0; + + if((cp = strchr(file_list[file_list_pos].name, '.'))) + { + if(strcmp(cp+1, "MOD") == 0) + allowed_ext = 1; + } + + if(allowed_ext) + { + if(file_list[file_list_pos].type == 0) + { + if(music != NULL) + { + MODUnload(music); + music = NULL; + } + +// It is a file, we will play it + +// First check if there is a file which contains the +// samples + strcpy(name_buf, file_list[file_list_pos].name); + + if((cp = strchr(name_buf, '.'))) + *(cp+1) = '\0'; + + strcat(name_buf, "SMP"); + + ok = 0; + + if(!(padbuf & PAD_SELECT)) + { + for(i = 0; file_list[i].size != -1; i++) + { + if(strcmp(name_buf, file_list[i].name) == 0) + { + ok = 1; + break; + } + } + } + + if(ok) + { +// We found a sample file + printf("Loading sample file for %s...\n", + file_list[file_list_pos].name); + + sprintf(name_buf2, "cdrom:%s;1", name_buf); + printf("namebuf2=%s\n",name_buf2); + + f = fopen(name_buf2, "rb"); + + // printf("SZ = %d\n", file_list[i].size); + + fread(fileBuffer, sizeof(char), file_list[i].size, f); + fclose(f); + + memcpy(name_buf, fileBuffer, 8); + name_buf[8] = 0; + + MOD4PSX_Upload(fileBuffer, SPU_DATA_BASE_ADDR); + } + else + printf("No sample file found for %s!\n", + file_list[file_list_pos].name); + + sprintf(name_buf2, "cdrom:%s;1", file_list[file_list_pos].name); + + f = fopen(name_buf2, "rb"); + + fread(fileBuffer, sizeof(char), file_list[file_list_pos].size, f); + + fclose(f); + + music = MODLoadEx(fileBuffer, ok?MODLOAD_NOSAMPLES:0); + + if(!ok) + MODUploadSamples(music, SPU_DATA_BASE_ADDR); + + music_player_fname = file_list[file_list_pos].name; + music_player_time = 0; + music_player_vol = SPU_MAXVOL+1; + music_player_vol_pc = 100; + MODSetMaxVolume(music_player_vol-1); + music_loop = -1; + } + else + { +// It is a directory, we will go inside it + if(strcmp(file_list[file_list_pos].name, "..") == 0) + { + *(strrchr(current_dir, '\\')) = '\0'; + + if(strcmp(current_dir, "cdrom:") == 0) + chdir("cdrom:\\"); + else + chdir(current_dir); + } + else + { + strcat(current_dir, "\\"); + strcat(current_dir, file_list[file_list_pos].name); + chdir(current_dir); + } + + file_list_pos = 0; + update_file_list(); + redraw = 1; + } + } + + wasEnter = 1; + } + + if(!(padbuf & PAD_UP) || wasUp >= 15) + wasUp = 0; + if(!(padbuf & PAD_DOWN) || wasDown >= 15) + wasDown = 0; + if(!(padbuf & PAD_CROSS)) + wasEnter = 0; + + /* Drawing */ + if(!redraw) + return; + + + + GsSortCls(0, 0, 0); + GsPrintFont(0, 0, "-= PsxMod =-"); + GsPrintFont(0, 8, "Folder: <root>%s", current_dir + 6); + GsPrintFont(0, 16, "X to play, hold SELECT to convert SFX"); + + k=0; + + if(file_list_size > 24) + { + if(file_list_pos > 12) + { + k = file_list_pos - 12; + + if(k > (file_list_size - 26)) + k = file_list_size - 26; + } + } + + prog_rect.x = 0; + prog_rect.y = 32 + ((file_list_pos-k) * 8); + prog_rect.w = GsScreenW / 2; + prog_rect.h = 8; + prog_rect.r = 0; + prog_rect.g = 0; + prog_rect.b = 255; + prog_rect.attribute = 0; + GsSortRectangle(&prog_rect); + + for(i = 0; file_list[i+k].size != -1; i++) + { + if(file_list[i+k].type == 1) + GsPrintFont(0, 32 + (i * 8), " +- %s", file_list[i+k].name); + else + GsPrintFont(0, 32 + (i * 8), " %s", file_list[i+k].name); + } + + GsDrawList(); + + dbuf = !dbuf; + GsSetDispEnvSimple(0, dbuf?256:0); + GsSetDrawEnvSimple(0, dbuf?0:256, 320, 240); +} + +void music_player_draw() +{ + unsigned short padbuf; + static int old_song_pos = 10000; + int change_vol = 0; + + GsSortCls(0, 0, 0); + GsPrintFont(0, 0, "-= PsxMod =-"); + GsPrintFont(0, 8, "File: %s", music_player_fname); + GsPrintFont(0, 16, "Title: %s", music->title); + GsPrintFont(0, 24, "pat:%03d/%03d pos:%02X spd:%d/%d", + music->song_pos, music->song_pos_num - 1, music->pat_pos, + music->ticks_division, music->beats_minute); + + GsPrintFont(0, 32, "vol: %03d%%/100%% time: %d:%02d chn: %d", + music_player_vol_pc, music_player_time / (TICKS_PER_SECOND * 60), + (music_player_time % (TICKS_PER_SECOND * 60) ) / TICKS_PER_SECOND, + music->channel_num); + + GsPrintFont(0, 56, "Press X to change music."); + + dbuf = !dbuf; + GsSetDispEnvSimple(0, dbuf?256:0); + GsSetDrawEnvSimple(0, dbuf?0:256, 320, 240); + GsDrawList(); + + if(old_song_pos > music->song_pos) + music_player_time = 0; + + PSX_ReadPad(&padbuf, NULL); + + if(padbuf & PAD_UP) + { + music_player_vol+=32; + change_vol = 1; + } + + if(padbuf & PAD_DOWN) + { + music_player_vol-=32; + change_vol = 1; + } + + if(padbuf & PAD_LEFT) + { + if(!wasLeft) + { + music->pat_pos = 0; + + if(music->song_pos > 0) + music->song_pos--; + } + + wasLeft++; + } + + if(padbuf & PAD_RIGHT) + { + if(!wasRight) + { + music->pat_pos = 0; + + if(music->song_pos < (music->song_pos_num - 1)) + music->song_pos++; + else + music->song_pos = 0; + } + + wasRight++; + } + + if(!(padbuf & PAD_LEFT) || wasLeft >= 15) + wasLeft = 0; + + if(!(padbuf & PAD_RIGHT) || wasRight >= 15) + wasRight = 0; + + if((padbuf & PAD_CROSS) && !wasEnter) + { + MODStop(music); + MODUnload(music); + music = NULL; + wasEnter = 1; + } + + if(!(padbuf & PAD_CROSS)) + wasEnter = 0; + + if(music_player_vol < 0) + music_player_vol = 0; + + if(music_player_vol > (SPU_MAXVOL+1)) + music_player_vol = SPU_MAXVOL+1; + + if(change_vol) + { + music_player_vol_pc = (int)((float)100 * ((float)music_player_vol / (float)(SPU_MAXVOL+1))); + MODSetMaxVolume((music_player_vol == 0)?0:(music_player_vol-1)); + } + + music_player_time++; + + old_song_pos = music->song_pos; +} + +int main() +{ + int redraw=1; + FILE *f; + + PSX_Init(); + GsInit(); + SsInit(); + + GsClearMem(); + GsSetAutoWait(); + GsSetList(primList); + GsSetVideoMode(320, 240, EXAMPLES_VMODE); + GsLoadFont(768, 0, 768, 256); + + SetVBlankHandler(program_vblank_handler); + +// Open any existing file before calling firstfile() for the first time. +// If before calling firstfile() for the first time, you have never called open() on an existing file before, +// every subsequent read will fail but it will report that files are opened ok! +// This bug happens at least with the SCPH1001 BIOS version. +// We try to open PSX.EXE and SYSTEM.CNF, as one of them must exist in order to boot from CDROM. + + f = fopen("cdrom:PSX.EXE;1", "rb"); + if(f)fclose(f); + + f = fopen("cdrom:SYSTEM.CNF;1", "rb"); + if(f)fclose(f); + + update_file_list(); + + dbuf = !dbuf; + GsSetDispEnvSimple(0, dbuf?256:0); + GsSetDrawEnvSimple(0, dbuf?0:256, 320, 240); + + while(1) + { + if(display_is_old) + { + /* Update music */ + if(music) + { + redraw = 1; + MODPlay(music, &music_loop); + music_player_draw(); + } + else + { + file_browser(redraw); + redraw=0; + } + + display_is_old = 0; + } + } +} diff --git a/examples/psxpaint/Makefile b/examples/psxpaint/Makefile new file mode 100644 index 0000000..d1d5698 --- /dev/null +++ b/examples/psxpaint/Makefile @@ -0,0 +1,7 @@ +PROJNAME = psxpaint + +include ../project.mk + +$(PROJNAME)_extra: + +$(PROJNAME)_clean_extra: diff --git a/examples/psxpaint/cursor.h b/examples/psxpaint/cursor.h new file mode 100644 index 0000000..4f1a9cf --- /dev/null +++ b/examples/psxpaint/cursor.h @@ -0,0 +1,20 @@ +unsigned char cursor_tim[] = +{ +16, 0, 0, 0, 8, 0, 0, 0, 44, 0, 0, 0, 128, 2, 224, 1, +16, 0, 1, 0, +0, 0, 0, 128, 255, 127, 0, 128, 0, 128, 0, 128, +0, 128, 0, 128, 0, 128, 0, 128, 0, 8, 0, 128, 64, 16, 0, 128, +64, 16, 0, 128, 204, 0, 0, 0, 128, 2, 0, 0, 4, 0, 24, 0, +1, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, +33, 1, 0, 0, 0, 0, 0, 0, 33, 18, 0, 0, 0, 0, 0, 0, +33, 34, 1, 0, 0, 0, 0, 0, 33, 34, 18, 0, 0, 0, 0, 0, +33, 34, 34, 1, 0, 0, 0, 0, 33, 34, 34, 18, 0, 0, 0, 0, +33, 34, 34, 34, 1, 0, 0, 0, 33, 34, 34, 34, 18, 0, 0, 0, +33, 34, 34, 34, 34, 1, 0, 0, 33, 34, 34, 18, 17, 17, 0, 0, +33, 34, 33, 18, 0, 0, 0, 0, 33, 18, 33, 18, 0, 0, 0, 0, +33, 1, 16, 34, 1, 0, 0, 0, 17, 0, 16, 34, 1, 0, 0, 0, +1, 0, 0, 33, 18, 0, 0, 0, 0, 0, 0, 33, 18, 0, 0, 0, +0, 0, 0, 16, 34, 1, 0, 0, 0, 0, 0, 16, 34, 1, 0, 0, +0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; diff --git a/examples/psxpaint/psxpaint.c b/examples/psxpaint/psxpaint.c new file mode 100644 index 0000000..726b13b --- /dev/null +++ b/examples/psxpaint/psxpaint.c @@ -0,0 +1,371 @@ +/* + * PSXPaint + */ + +/* + * Video memory layout: + * + * [0-639],[0-479] - Screen memory + * [640-895],[480-511] - Color Look Up Tables + * [640-643],[0-23] - Cursor Image (16x24) (4bpp - real width: 16) + * [992-1023],[0-31] - Cursor Dirty Rectangle (32x32) + */ + +#include <stdio.h> +#include <psx.h> +#include <psxgpu.h> +#include "cursor.h" + +int cursor_x = 0, cursor_y = 0, cursor_speed = 1; +int old_cursor_x, old_cursor_y; +volatile unsigned int speed_counter = 0; +int brush_type = 0; + +unsigned int primitive_list[4000]; + +int paint_colors[20][3] = { + { 0, 0, 0 }, // #0 Black + { 255, 255, 255 }, // #1 White + { 255, 0, 0 }, // #2 Red + { 0, 255, 0 }, // #3 Green + { 0, 0, 255 }, // #4 Blue + { 255, 255, 0}, // #5 Yellow + { 255, 0, 255}, // #6 Magenta (Fuchsia) + { 0, 255, 255}, // #7 Aqua Green + { 255, 128, 0}, // #8 Orange + { 128, 255,0}, // #9 Lime Green + + { 192, 192,255},// #10 Sky Blue + { 128,128,128}, // #11 Grey + { 128, 0,0 }, // #12 Dark Red + { 0, 128, 0}, // #13 Dark Green + { 0, 0, 128}, // #14 Dark Blue + { 128, 128, 0}, // #15 Dark Yellow + { 128, 0, 128}, // #16 Purple + { 0, 128, 128}, // #17 Dark Aqua + { 128, 64, 0}, // #18 Brown + { 64, 128, 0}, // #19 Dark Lime Green + + /*{ 128, 0, 255}, // #10 Violet + { 128,128,128}, // #11 Grey + { 128, 0,0 }, // #12 Dark Red + { 0, 128, 0}, // #13 Dark Green + { 0, 0, 128}, // #14 Dark Blue + { 192, 192,255},// #15 Sky Blue + { 128, 128, 0}, // #16 Dark Yellow + { 150, 75, 0}, // #17 Brown + { 64, 64, 64}, // #18 Dark Grey + { 128, 255,0}, // #19 Lime Green + */ +}; + +int current_color[3]; + +void sort_color_boxes() +{ + GsRectangle colorbox; + int x, y, c=0; + + for(y = 384; y < (384+32); y+=16) + { + for(x = 0; x < 640; x+=64) + { + colorbox.x = x; + colorbox.y = y; + colorbox.w = 64; + colorbox.h = 16; + colorbox.r = paint_colors[c][0]; + colorbox.g = paint_colors[c][1]; + colorbox.b = paint_colors[c][2]; + colorbox.attribute = 0; + + GsSortRectangle(&colorbox); + + c++; + } + } +} + +void load_ui_graphics() +{ + GsImage my_image; + + GsImageFromTim(&my_image, cursor_tim); + GsUploadImage(&my_image); +} + +void my_vblank_handler(); + +void my_vblank_handler() +{ + speed_counter++; +} + +int main() +{ + GsDispEnv my_dispenv; + GsDrawEnv my_drawenv; + GsSprite my_sprite; + GsRectangle colorbox; + GsDot my_dot; + unsigned short pad1; + unsigned int WasL2=0, WasR2=0, WasL1=0, WasR1=0, WasSelect = 0; + int x, y; + + PSX_InitEx(PSX_INIT_NOBIOS); + GsInit(); + GsClearMem(); + SetVBlankHandler(my_vblank_handler); + + // This has to be interlaced + GsSetVideoModeEx(640, 480, EXAMPLES_VMODE, 0, 1, 0); + + my_dispenv.x = 0; + my_dispenv.y = 0; + + GsSetDispEnv(&my_dispenv); + + my_drawenv.dither = 0; + my_drawenv.draw_on_display = 1; + my_drawenv.x = 0; + my_drawenv.y = 0; + my_drawenv.w = 640; + my_drawenv.h = 512; + my_drawenv.ignore_mask = 0; + my_drawenv.set_mask = 0; + + GsSetDrawEnv(&my_drawenv); + + GsSetList(primitive_list); + + load_ui_graphics(); + while(GsIsDrawing()); + + colorbox.x = 0; + colorbox.y = 0; + colorbox.w = 640; + colorbox.h = 511; + colorbox.r = 255; + colorbox.g = 255; + colorbox.b = 255; + colorbox.attribute = 0; + + GsSortRectangle(&colorbox); + + sort_color_boxes(); + + + my_sprite.x = 0; + my_sprite.y = 0; + my_sprite.tpage = 10; + my_sprite.u = 0; + my_sprite.v = 0; + my_sprite.attribute = 0; + my_sprite.cx = 640; + my_sprite.cy = 480; + my_sprite.r = my_sprite.g = my_sprite.b = NORMAL_LUMINOSITY; + my_sprite.scalex = my_sprite.scaley = 0; + my_sprite.w = 16; + my_sprite.h = 24; + + GsDrawList(); + while(GsIsDrawing()); + + // Backup 32x32 area + MoveImage(cursor_x, cursor_y, 992, 0, 32, 32); + + my_dot.attribute = 0; + + while(1) + { + while(speed_counter) + { + old_cursor_x = cursor_x; + old_cursor_y = cursor_y; + + // Restore 32x32 area + MoveImage(992, 0, old_cursor_x, old_cursor_y, 32, 32); + while(GsIsDrawing()); + + PSX_ReadPad(&pad1, NULL); + + if(pad1 & PAD_LEFT) + cursor_x-=cursor_speed; + + if(pad1 & PAD_RIGHT) + cursor_x+=cursor_speed; + + if(pad1 & PAD_UP) + cursor_y-=cursor_speed; + + if(pad1 & PAD_DOWN) + cursor_y+=cursor_speed; + + if(cursor_x <= 0) + cursor_x = 0; + + if(pad1 & PAD_CROSS) + { + if(cursor_y >= 384) + { + y = (cursor_y - 384) >> 4; + x = cursor_x >> 6; + + current_color[0] = paint_colors[(y * 10)+x][0]; + current_color[1] = paint_colors[(y * 10)+x][1]; + current_color[2] = paint_colors[(y * 10)+x][2]; + } + else + { + + switch(brush_type) + { + case 0: + if(cursor_y >= 384) + { + break; + } + + my_dot.r = current_color[0]; + my_dot.g = current_color[1]; + my_dot.b = current_color[2]; + my_dot.x = cursor_x; + my_dot.y = cursor_y; + + GsSortDot(&my_dot); + break; + case 1: + if(cursor_y >= 380) + { + break; + } + + my_dot.r = current_color[0]; + my_dot.g = current_color[1]; + my_dot.b = current_color[2]; + my_dot.x = cursor_x + 1; + my_dot.y = cursor_y; + + GsSortDot(&my_dot); + + my_dot.x++; + + GsSortDot(&my_dot); + + my_dot.y++; + my_dot.x-=2; + + GsSortDot(&my_dot); + + my_dot.x++; + + GsSortDot(&my_dot); + + my_dot.x++; + + GsSortDot(&my_dot); + + my_dot.x++; + + GsSortDot(&my_dot); + + my_dot.y++; + my_dot.x-=2; + + GsSortDot(&my_dot); + + my_dot.x++; + + GsSortDot(&my_dot); + break; + } + + } + + GsDrawList(); + while(GsIsDrawing()); + } + + if((pad1 & PAD_R2) && !WasR2) + { + cursor_speed++; + WasR2 = 1; + } + + if((pad1 & PAD_L2) && !WasL2) + { + cursor_speed--; + WasL2 = 1; + } + + if(!(pad1 & PAD_R2)) + WasR2 = 0; + + if(!(pad1 & PAD_L2)) + WasL2 = 0; + + if((pad1 & PAD_R1) && !WasR1) + { + brush_type++; + WasR1 = 1; + } + + if((pad1 & PAD_L1) && !WasL1) + { + brush_type--; + WasL1 = 1; + } + + if((pad1 & PAD_SELECT) && !WasSelect) + { + my_sprite.attribute ^= (ENABLE_TRANS | TRANS_MODE(0)); + my_dot.attribute ^= (ENABLE_TRANS | TRANS_MODE(0)); + WasSelect = 1; + } + + if(!(pad1 & PAD_SELECT)) + WasSelect = 0; + + if(!(pad1 & PAD_R1)) + WasR1 = 0; + + if(!(pad1 & PAD_L1)) + WasL1 = 0; + + if(cursor_speed <= 0) + cursor_speed = 1; + + if(cursor_speed >= 8) + cursor_speed = 7; + + if(brush_type <= 0) + brush_type = 0; + + if(brush_type > 1) + brush_type = 1; + + // Backup 32x32 area + MoveImage(cursor_x, cursor_y, 992, 0, 32, 32); + while(GsIsDrawing()); + + // if(cursor_x != old_cursor_x || cursor_y != old_cursor_y) + // { + // printf("cx = %d, cy = %d, cursor_speed = %d, brush_type = %d\n", + // cursor_x, cursor_y, cursor_speed, brush_type); + + + + + + my_sprite.x = cursor_x; + my_sprite.y = cursor_y; + GsSortSimpleSprite(&my_sprite); + + GsDrawList(); + while(GsIsDrawing()); + // } + + speed_counter--; + } + } +} diff --git a/examples/psxs3m/Makefile b/examples/psxs3m/Makefile new file mode 100644 index 0000000..81465be --- /dev/null +++ b/examples/psxs3m/Makefile @@ -0,0 +1,10 @@ +PROJNAME = psxs3m +PROJ_LIBS = -lf3m + +include ../project.mk + +$(PROJNAME)_extra: $(SAMPLES) + mkdir -p cd_root + cp -r mods cd_root + +$(PROJNAME)_clean_extra: diff --git a/examples/psxs3m/mods/mario2_2.s3m b/examples/psxs3m/mods/mario2_2.s3m Binary files differnew file mode 100644 index 0000000..96220e9 --- /dev/null +++ b/examples/psxs3m/mods/mario2_2.s3m diff --git a/examples/psxs3m/mods/mario3.s3m b/examples/psxs3m/mods/mario3.s3m Binary files differnew file mode 100644 index 0000000..2d2cabc --- /dev/null +++ b/examples/psxs3m/mods/mario3.s3m diff --git a/examples/psxs3m/psxs3m.c b/examples/psxs3m/psxs3m.c new file mode 100644 index 0000000..9fe677f --- /dev/null +++ b/examples/psxs3m/psxs3m.c @@ -0,0 +1,412 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <psx.h> +#include <f3m.h> + +#if defined(EXAMPLES_VMODE) == VMODE_PAL + #define TICKS_PER_SECOND 50 +#else + #define TICKS_PER_SECOND 60 +#endif + +unsigned int primList[0x8000]; +int dbuf = 0; +volatile int display_is_old = 1; +char current_dir[256] = "cdrom:"; +char name_buf[24]; +char name_buf2[32]; +mod_s *music = NULL; +player_s player; +int music_loop; +char *music_player_fname; +int music_player_time; +short music_player_vol; +int music_player_vol_pc; + +GsRectangle prog_rect; + +void program_vblank_handler() +{ + display_is_old = 1; +} + +struct +{ + char name[20]; + int size; + int type; /* 0 = file, 1 = directory */ +}file_list[256]; + +int file_list_size = 0; +int file_list_pos = 0; + +int wasUp = 0; +int wasDown = 0; +int wasEnter = 0; +int wasLeft = 0; +int wasRight = 0; + +void update_file_list() +{ + struct DIRENTRY de; + struct DIRENTRY *r; + char *cp; + int i, k=0; + + if(strcmp(current_dir, "cdrom:") != 0) + { + strcpy(file_list[0].name, ".."); + file_list[0].type = 1; + k=1; + } + + r = firstfile("cdrom:*", &de); + + for(i = k; i < 256 && r; i++) + { + if(de.name[0] == 0x1) + { +// Throw away useless entry. + r = nextfile(&de); + i--; + continue; + } + + memcpy(file_list[i].name, de.name, 20); + + if((cp = strrchr(file_list[i].name, ';'))) + { + *cp = '\0'; + file_list[i].type = 0; + } + else + file_list[i].type = 1; + + file_list[i].size = de.size; + + r = nextfile(&de); + } + + file_list[i].size = -1; + file_list_size = i; +} + +void file_browser(int redraw) +{ + int i, k, allowed_ext; + unsigned short padbuf; + char *cp; + + PSX_ReadPad(&padbuf, NULL); + + if(wasUp) + wasUp++; + + if(wasDown) + wasDown++; + + if((padbuf & PAD_UP) && !wasUp) + { + if(file_list_pos > 0) + { + file_list_pos--; + redraw=1; + } + + wasUp=1; + } + + if((padbuf & PAD_DOWN) && !wasDown) + { + file_list_pos++; + + if(file_list[file_list_pos].size == -1) + file_list_pos--; + else + redraw = 1; + + wasDown = 1; + } + + if((padbuf & PAD_CROSS) && !wasEnter) + { + if(file_list[file_list_pos].type == 1) + allowed_ext = 1; + else + allowed_ext = 0; + + if((cp = strchr(file_list[file_list_pos].name, '.'))) + { + if(strcmp(cp+1, "S3M") == 0) + allowed_ext = 1; + } + + if(allowed_ext) + { + if(file_list[file_list_pos].type == 0) + { + if(music != NULL) + { + f3m_mod_free(music); + music = NULL; + } + +// It is a file, we will play it + sprintf(name_buf2, "cdrom:%s;1", file_list[file_list_pos].name); + + music = f3m_mod_load_filename(name_buf2); + f3m_player_init(&player, music); + + music_player_fname = file_list[file_list_pos].name; + music_player_time = 0; + music_player_vol = SPU_MAXVOL+1; + music_player_vol_pc = 100; + + f3m_set_max_volume(&player, music_player_vol-1); + + music_loop = -1; + } + else + { +// It is a directory, we will go inside it + if(strcmp(file_list[file_list_pos].name, "..") == 0) + { + *(strrchr(current_dir, '\\')) = '\0'; + + if(strcmp(current_dir, "cdrom:") == 0) + chdir("cdrom:\\"); + else + chdir(current_dir); + } + else + { + strcat(current_dir, "\\"); + strcat(current_dir, file_list[file_list_pos].name); + chdir(current_dir); + } + + file_list_pos = 0; + update_file_list(); + redraw = 1; + } + } + + wasEnter = 1; + } + + if(!(padbuf & PAD_UP) || wasUp >= 15) + wasUp = 0; + if(!(padbuf & PAD_DOWN) || wasDown >= 15) + wasDown = 0; + if(!(padbuf & PAD_CROSS)) + wasEnter = 0; + + /* Drawing */ + if(!redraw) + return; + + + + GsSortCls(0, 0, 0); + GsPrintFont(0, 0, "-= PsxS3M =-"); + GsPrintFont(0, 8, "Folder: <root>%s", current_dir + 6); + GsPrintFont(0, 16, "X to play, hold SELECT to convert SFX"); + + k=0; + + if(file_list_size > 24) + { + if(file_list_pos > 12) + { + k = file_list_pos - 12; + + if(k > (file_list_size - 26)) + k = file_list_size - 26; + } + } + + prog_rect.x = 0; + prog_rect.y = 32 + ((file_list_pos-k) * 8); + prog_rect.w = GsScreenW / 2; + prog_rect.h = 8; + prog_rect.r = 0; + prog_rect.g = 0; + prog_rect.b = 255; + prog_rect.attribute = 0; + GsSortRectangle(&prog_rect); + + for(i = 0; file_list[i+k].size != -1; i++) + { + if(file_list[i+k].type == 1) + GsPrintFont(0, 32 + (i * 8), " +- %s", file_list[i+k].name); + else + GsPrintFont(0, 32 + (i * 8), " %s", file_list[i+k].name); + } + + GsDrawList(); + + dbuf = !dbuf; + GsSetDispEnvSimple(0, dbuf?256:0); + GsSetDrawEnvSimple(0, dbuf?0:256, 320, 240); +} + +void music_player_draw() +{ + unsigned short padbuf; + static int old_song_pos = 10000; + int change_vol = 0; + + GsSortCls(0, 0, 0); + GsPrintFont(0, 0, "-= PsxS3M =-"); + GsPrintFont(0, 8, "File: %s", music_player_fname); + GsPrintFont(0, 16, "Title: %s", music->name); + GsPrintFont(0, 24, "ord:%03d/%03d pat:%03d/%03d pos:%02X spd:%d/%d", + player.cord, music->ord_num - 1, player.cpat, music->pat_num - 1, player.crow, + music->ispeed, music->itempo); + GsPrintFont(0, 32, "vol: %03d%%/100%% time: %d:%02d", + music_player_vol_pc, music_player_time / (TICKS_PER_SECOND * 60), + (music_player_time % (TICKS_PER_SECOND * 60) ) / TICKS_PER_SECOND); + + GsPrintFont(0, 56, "Press X to change music."); + + dbuf = !dbuf; + GsSetDispEnvSimple(0, dbuf?256:0); + GsSetDrawEnvSimple(0, dbuf?0:256, 320, 240); + GsDrawList(); + + if(old_song_pos > player.cord) + music_player_time = 0; + + PSX_ReadPad(&padbuf, NULL); + + if(padbuf & PAD_UP) + { + music_player_vol+=32; + change_vol = 1; + } + + if(padbuf & PAD_DOWN) + { + music_player_vol-=32; + change_vol = 1; + } + + if(padbuf & PAD_LEFT) + { + if(!wasLeft) + { + player.crow = 0; + player.cord--; + player.crow = 64; + + if(player.cord > -1) + player.cord--; + } + + wasLeft++; + } + + if(padbuf & PAD_RIGHT) + { + if(!wasRight) + { + player.crow = 64; + } + + wasRight++; + } + + if(!(padbuf & PAD_LEFT) || wasLeft >= 15) + wasLeft = 0; + + if(!(padbuf & PAD_RIGHT) || wasRight >= 15) + wasRight = 0; + + if((padbuf & PAD_CROSS) && !wasEnter) + { + f3m_player_stop(&player); + f3m_mod_free(music); + music = NULL; + + wasEnter = 1; + } + + if(!(padbuf & PAD_CROSS)) + wasEnter = 0; + + if(music_player_vol < 0) + music_player_vol = 0; + + if(music_player_vol > (SPU_MAXVOL+1)) + music_player_vol = SPU_MAXVOL+1; + + if(change_vol) + { + music_player_vol_pc = (int)((float)100 * ((float)music_player_vol / (float)(SPU_MAXVOL+1))); + f3m_set_max_volume(&player, (music_player_vol == 0)?0:(music_player_vol-1)); + } + + music_player_time++; + + old_song_pos = player.cord; +} + +int main() +{ + int redraw=1; + FILE *f; + + PSX_Init(); + GsInit(); + SsInit(); + + GsClearMem(); + GsSetAutoWait(); + GsSetList(primList); + GsSetVideoMode(320, 240, EXAMPLES_VMODE); + GsLoadFont(768, 0, 768, 256); + + SetVBlankHandler(program_vblank_handler); + +// Open any existing file before calling firstfile() for the first time. +// If before calling firstfile() for the first time, you have never called open() on an existing file before, +// every subsequent read will fail but it will report that files are opened ok! +// This bug happens at least with the SCPH1001 BIOS version. +// We try to open PSX.EXE and SYSTEM.CNF, as one of them must exist in order to boot from CDROM. + + f = fopen("cdrom:PSX.EXE;1", "rb"); + if(f)fclose(f); + + f = fopen("cdrom:SYSTEM.CNF;1", "rb"); + if(f)fclose(f); + + update_file_list(); + + dbuf = !dbuf; + GsSetDispEnvSimple(0, dbuf?256:0); + GsSetDrawEnvSimple(0, dbuf?0:256, 320, 240); + + while(1) + { + if(display_is_old) + { + /* Update music */ + if(music) + { + redraw = 1; + f3m_player_play(&player); + // MODPlay(music, &music_loop); + music_player_draw(); + } + else + { + file_browser(redraw); + redraw=0; + } + + display_is_old = 0; + } + } +} diff --git a/examples/psxsnake/Makefile b/examples/psxsnake/Makefile new file mode 100644 index 0000000..033e1bc --- /dev/null +++ b/examples/psxsnake/Makefile @@ -0,0 +1,12 @@ +PROJNAME = psxsnake + +include ../project.mk + +$(PROJNAME)_extra: + $(MAKE_COMMAND) -C data + mkdir -p cd_root + cp data/*.tim cd_root + cp data/*.raw cd_root + +$(PROJNAME)_clean_extra: + $(MAKE_COMMAND) -C data clean diff --git a/examples/psxsnake/data/Makefile b/examples/psxsnake/data/Makefile new file mode 100644 index 0000000..da14ec1 --- /dev/null +++ b/examples/psxsnake/data/Makefile @@ -0,0 +1,21 @@ +include ../../../Makefile.cfg + +data: backgrnd.tim font.tim music.raw bomb.raw apple.raw + +backgrnd.tim: backgrnd.bmp + bmp2tim backgrnd.bmp backgrnd.tim 16 -org=320,0 + +font.tim: font.bmp + bmp2tim font.bmp font.tim 4 -org=640,0 + +music.raw: music.wav + wav2vag music.wav music.raw -L -raw + +bomb.raw: bomb.wav + wav2vag bomb.wav bomb.raw -raw + +apple.raw: apple.wav + wav2vag apple.wav apple.raw -raw + +clean: + rm -f *.tim *.raw diff --git a/examples/psxsnake/data/apple.txt b/examples/psxsnake/data/apple.txt new file mode 100644 index 0000000..dbcfc27 --- /dev/null +++ b/examples/psxsnake/data/apple.txt @@ -0,0 +1,14 @@ +File:
+ Name: "Apple_Crunch_16.wav"
+ Url: http://www.freesound.org/samplesViewSingle.php?id=20279
+ Date of upload: 2006-06-28 11:44:45
+
+Designer / Creator / Uploader:
+ Name: "Koops"
+ Url: http://www.freesound.org/usersViewSingle.php?id=29508
+
+Description:
+ By "Koops" : 16/18 Apple related eating noises. Recorded in my studio with a matched pair of Rode NT5\'s in the XY configuration. Stereo, WAV, 44.1KHz, 16Bit, Unprocessed.
+
+Tags:
+ apple bite crunch eating food snack squelch
\ No newline at end of file diff --git a/examples/psxsnake/data/apple.wav b/examples/psxsnake/data/apple.wav Binary files differnew file mode 100644 index 0000000..2643783 --- /dev/null +++ b/examples/psxsnake/data/apple.wav diff --git a/examples/psxsnake/data/backgrnd.bmp b/examples/psxsnake/data/backgrnd.bmp Binary files differnew file mode 100644 index 0000000..d70e1eb --- /dev/null +++ b/examples/psxsnake/data/backgrnd.bmp diff --git a/examples/psxsnake/data/bomb.wav b/examples/psxsnake/data/bomb.wav Binary files differnew file mode 100644 index 0000000..a3935e0 --- /dev/null +++ b/examples/psxsnake/data/bomb.wav diff --git a/examples/psxsnake/data/font.bmp b/examples/psxsnake/data/font.bmp Binary files differnew file mode 100644 index 0000000..070704c --- /dev/null +++ b/examples/psxsnake/data/font.bmp diff --git a/examples/psxsnake/data/music.wav b/examples/psxsnake/data/music.wav Binary files differnew file mode 100644 index 0000000..ae5c8df --- /dev/null +++ b/examples/psxsnake/data/music.wav diff --git a/examples/psxsnake/psxsnake.c b/examples/psxsnake/psxsnake.c new file mode 100644 index 0000000..c4260b2 --- /dev/null +++ b/examples/psxsnake/psxsnake.c @@ -0,0 +1,666 @@ +/* + * Snake clone for the PSX + */ + +#include <psx.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int vmode; +volatile int speed_counter = 0; +volatile int screen_old = 0; + +int snake_array[29][40]; +int scc = 0; +int vibration_cntdown = 0; + +int snake_size = 3; +int game_over = 0; + +int rectangle_mode = 0; +int l1_pressed = 0; + +int level_number = 1; +int score = 0; +volatile int seed_counter = 0; + +int sample_pos[3]; // 0 = music, 1 = collision, 2 = apple + +unsigned int game_draw_list[0x4000]; /* 128 kilobytes */ + +enum +{ + SNAKE_DIR_LEFT, SNAKE_DIR_RIGHT, SNAKE_DIR_UP, SNAKE_DIR_DOWN +}; + +int snake_dir = SNAKE_DIR_RIGHT; + +unsigned char file_buffer[0x30000]; /* 192 kilobytes */ + +void game_init(); +void game_vblank_handler(); +void game_run(); +void game_run_gameover(); +int pal_or_ntsc_selection(); +int main(); +int check_snake_collision(int x, int y); +int load_file_into_buffer(char *fname); +void game_print(char *string, int x, int y); +void game_center_print(char *string, int x, int y); +void setup_snake_field(); +void game_setup(); + +GsDrawEnv game_drawenv; +GsDispEnv game_dispenv; + +GsImage game_image; +GsSprite game_sprite; +GsRectangle game_rect; + +unsigned short game_clut[16]; + +char string_buf[256]; + +int cross_pressed = 0; +int circle_pressed = 0; + +void game_init() +{ +// Initialize the PSXSDK library + PSX_Init(); + +// Initialize graphics + GsInit(); + +// Clear video memory + GsClearMem(); + +// Set up drawing environment + game_drawenv.dither = 0; + game_drawenv.draw_on_display = 0; + game_drawenv.x = 0; + game_drawenv.y = 0; + game_drawenv.w = 320; + game_drawenv.h = 240; + game_drawenv.ignore_mask = 0; + game_drawenv.set_mask = 0; + + GsSetDrawEnv(&game_drawenv); + +// Set up display environment + game_dispenv.x = 0; + game_dispenv.y = 256; + + GsSetDispEnv(&game_dispenv); + +// Set drawing list + GsSetList(game_draw_list); + +// Initialize sound + SsInit(); + + +} + +void game_vblank_handler() +{ + speed_counter++; + seed_counter++; + screen_old = 1; +} + +int pal_or_ntsc_selection() +{ + unsigned short padbuf; + int x; + + game_drawenv.draw_on_display = 1; + x = game_drawenv.y; + game_drawenv.y = game_dispenv.y; + GsSetDrawEnv(&game_drawenv); + + game_rect.x = 0; + game_rect.y = 0; + game_rect.w = 320; + game_rect.h = 240; + game_rect.r = 0; + game_rect.g = 0; + game_rect.b = 0; + game_rect.attribute = 0; + + GsSortRectangle(&game_rect); + + game_print("PAL/NTSC SELECTION", 128, 64); + game_print("X - PAL", 128, 80); + game_print("O - NTSC", 128, 88); + + GsDrawList(); + + while(GsIsDrawing()); + + game_drawenv.draw_on_display = 0; + game_drawenv.y = x; + GsSetDrawEnv(&game_drawenv); + + while(1) + { + PSX_ReadPad(&padbuf, NULL); + + if((padbuf & PAD_CROSS) && !cross_pressed) + return VMODE_PAL; // PAL + + if((padbuf & PAD_CIRCLE) && !circle_pressed) + { + //printf("circle_pressed = %d\n", circle_pressed); + return VMODE_NTSC; // NTSC + } + + + if(!(padbuf & PAD_CROSS)) + cross_pressed = 0; + + if(!(padbuf & PAD_CIRCLE)) + circle_pressed = 0; + } +} + +void new_apple() +{ + int a, b; + + do + { + while((a = rand()%40) < 1); + srand(seed_counter); + while((b = rand()%29) < 2); + srand(seed_counter); + }while(snake_array[b][a]); + + snake_array[b][a] = 0x80; +} + +int main() +{ + int c; + +// Initialize + game_init(); + + printf("PSXsnake\n"); + printf("(c) 2009 Giuseppe Gatta\n"); + printf("Made with PSXSDK\n\n"); + + load_file_into_buffer("cdrom:FONT.TIM;1"); + GsImageFromTim(&game_image, file_buffer); + + GsUploadImage(&game_image); + + game_clut[0] = 0x0; + game_clut[1] = 0x7fff; + + LoadImage(game_clut, 640, 24, 16, 1); + + GsSetVideoMode(320, 240, EXAMPLES_VMODE); + + vmode = pal_or_ntsc_selection(); + + //printf("vmode = %d\n", vmode); + + GsSetVideoMode(320, 240, vmode); + + + load_file_into_buffer("cdrom:BACKGRND.TIM;1"); + GsImageFromTim(&game_image, file_buffer); + + GsUploadImage(&game_image); + + sample_pos[0] = SPU_DATA_BASE_ADDR; + c = load_file_into_buffer("cdrom:MUSIC.RAW;1"); + SsUpload(file_buffer, c, sample_pos[0]); + + if(c&0x7) + { + c|=0x7; + c++; + } + + sample_pos[1] = c + sample_pos[0]; + c = load_file_into_buffer("cdrom:BOMB.RAW;1"); + SsUpload(file_buffer, c, sample_pos[1]); + + /* ... */ + if(c&0x7) + { + c|=0x7; + c++; + } + + sample_pos[2] = c + sample_pos[1]; + c = load_file_into_buffer("cdrom:APPLE.RAW;1"); + SsUpload(file_buffer, c, sample_pos[2]); + + SsVoiceStartAddr(0, sample_pos[0]); + SsVoiceStartAddr(1, sample_pos[1]); + SsVoiceStartAddr(2, sample_pos[2]); + + SsVoiceVol(0, 0x3fff, 0x3fff); + SsVoiceVol(1, 0x3fff, 0x3fff); + SsVoiceVol(2, 0x3fff, 0x3fff); + + SsVoicePitch(0, 0x1000 / (44100 / 11025)); + SsVoicePitch(1, 0x1000 / (44100 / 11025)); + SsVoicePitch(2, 0x1000); + + game_setup(); + + SetVBlankHandler(game_vblank_handler); + + + while(1) + game_run(); + + return 0; +} + +int check_snake_collision(int x, int y) +{ + if(snake_array[y][x] == 0x80) + return 2; // Snake ate an apple + else if(snake_array[y][x] == 0) + return 1; // Collided with nothing + + return 0; // Die, because snake collided with itself +} + +void game_run() +{ + int x, y, a, b, c; + + unsigned short padbuf; + + while(speed_counter > 0) + { + scc++; + + if(vibration_cntdown > 0) + { + printf("vibration = %d\n", vibration_cntdown); + pad_enable_vibration(0); + pad_set_vibration(0, 0xFF, 0x80); + vibration_cntdown--; + + if(vibration_cntdown == 0) + pad_set_vibration(0, 0, 0); + } + + PSX_ReadPad(&padbuf, NULL); + + if(scc == 5 && !game_over) + { + if(snake_dir <= SNAKE_DIR_RIGHT) + { + if(padbuf & PAD_UP) + snake_dir = SNAKE_DIR_UP; + + if(padbuf & PAD_DOWN) + snake_dir = SNAKE_DIR_DOWN; + } + else + { + if(padbuf & PAD_LEFT) + snake_dir = SNAKE_DIR_LEFT; + + if(padbuf & PAD_RIGHT) + snake_dir = SNAKE_DIR_RIGHT; + } + + for(y = 0; y < 29; y++) + for(x = 0; x < 40; x++) + { + if(snake_array[y][x] == snake_size) + { + switch(snake_dir) + { + case SNAKE_DIR_LEFT: + b = y; + a = x-1; + break; + case SNAKE_DIR_RIGHT: + b = y; + a = x+1; + break; + case SNAKE_DIR_UP: + b = y-1; + a = x; + break; + case SNAKE_DIR_DOWN: + b = y+1; + a = x; + break; + } + + c = check_snake_collision(a,b); + + if(c) + { + snake_array[b][a] = snake_size+1; + + if(c==2) + { + snake_size++; + score+=100; + //printf("%d\n", score); + SsKeyOn(2); + new_apple(); + } + } + else + { + vibration_cntdown = 10; + game_over = 1; + SsKeyOff(0); + SsKeyOn(1); + scc = 0; + } + + if(snake_array[y][x] == 1 && c!=2) + snake_array[y][x] = 0; + + goto out_of_collision_checking; + } + } +out_of_collision_checking: + for(y = 0; y < 29; y++) + for(x = 0; x < 40; x++) + if(snake_array[y][x]&&snake_array[y][x]<0x80&&c!=2) + snake_array[y][x]--; + + scc = 0; + } + else if(game_over) + { + scc++; + + if(scc >= 510) + { + if((padbuf & PAD_CROSS) && !cross_pressed) + { + game_setup(); + cross_pressed = 1; + } + else if((padbuf & PAD_CIRCLE) && !circle_pressed) + { + circle_pressed = 1; + GsSetVideoMode(320, 240, pal_or_ntsc_selection()); + game_setup(); + } + + if(!(padbuf & PAD_CROSS)) + cross_pressed = 0; + + if(!(padbuf & PAD_CIRCLE)) + circle_pressed = 0; + } + } + + speed_counter--; + } + + + if(screen_old) + { + game_rect.x = 0; + game_rect.y = 0; + game_rect.w = 320; + game_rect.h = 240; + game_rect.r = 0; + game_rect.g = 0; + game_rect.b = 0; + game_rect.attribute = 0; + + GsSortRectangle(&game_rect); + + game_sprite.x = 0; + game_sprite.y = 0; + game_sprite.w = 256; + game_sprite.h = 240; + game_sprite.u = 0; + game_sprite.v = 0; + game_sprite.r = NORMAL_LUMINOSITY; + game_sprite.g = NORMAL_LUMINOSITY; + game_sprite.b = NORMAL_LUMINOSITY; + game_sprite.tpage = 5; + game_sprite.attribute = COLORMODE(COLORMODE_16BPP); + + GsSortSimpleSprite(&game_sprite); + + game_sprite.x += 256; + game_sprite.w = 64; + game_sprite.tpage = 9; + + GsSortSimpleSprite(&game_sprite); + + game_rect.w = 8; + game_rect.h = 8; + game_rect.attribute = ENABLE_TRANS | TRANS_MODE(0); + + for(y = 0; y < 29; y++) + { + for(x = 0; x < 40; x++) + { + game_rect.x = x * 8; + game_rect.y = y * 8; + + if(snake_array[y][x] >= 1 && snake_array[y][x] <= 0x7F) + { + game_rect.r = 0; + game_rect.g = 255; + game_rect.b = 0; + GsSortRectangle(&game_rect); + } + else if(snake_array[y][x] == 0x80) + { + game_rect.r = 255; + game_rect.g = 0; + game_rect.b = 255; + GsSortRectangle(&game_rect); + } + else if(snake_array[y][x] == 0x81) + { + game_rect.r = 0; + game_rect.g = 0; + game_rect.b = 128; + GsSortRectangle(&game_rect); + } + } + } + + sprintf(string_buf, "SCORE: %d", score); + game_print(string_buf, 0, 232); + + if(game_over) + { + + game_rect.w = 320; + game_rect.h = 240; + + game_rect.x = 0; + game_rect.y = 0; + + if(scc<=255)x=scc;else x=255; + + game_rect.r = x; + game_rect.g = x; + game_rect.b = x; + game_rect.attribute = ENABLE_TRANS|TRANS_MODE(2); + + GsSortRectangle(&game_rect); + + if(scc>=300) + { + game_center_print("GAME OVER!", 160, 120); + } + + if(scc>=420) + game_center_print("WHAT DO YOU WANT TO DO NOW?", 160, 136); + + if(scc>=450) + game_center_print("PRESS X TO RESTART THE GAME.",160, 152); + + if(scc>=480) + game_center_print("PRESS O FOR PAL/NTSC SELECTION SCREEN.",160,168); + + if(scc>=510) + game_center_print("MADE WITH PSXSDK BY GIUSEPPE GATTA, 2010", 160, 200); + } + + GsDrawList(); + +// While the graphic synthesizer (video card) is drawing +// just sleep. + while(GsIsDrawing()); + +// Swap drawing and display Y position, and swap list array +// to use. In this way we achieve a double buffer. + + if(game_dispenv.y == 0) + { + game_dispenv.y = 256; + game_drawenv.y = 0; + } + else + { + game_dispenv.y = 0; + game_drawenv.y = 256; + } + + GsSetDispEnv(&game_dispenv); + GsSetDrawEnv(&game_drawenv); + + screen_old = 0; + } +} + +void game_run_gameover() +{ + printf("GAME OVER!\n"); + while(1); +} + +int load_file_into_buffer(char *fname) +{ + FILE *f; + int sz; + + /*int fd; + + fd = open(fname, O_RDONLY); + + printf("%s (%d)\n", fname, get_file_size(fname)); + + read(fd, file_buffer, get_file_size(fname)); + + close(fd);*/ + f = fopen(fname, "rb"); + + //f->pos = 0; + fseek(f, 0, SEEK_END); + + sz = ftell(f); + + fseek(f, 0, SEEK_SET); + + printf("%s (%d)\n", fname, sz); + + fread(file_buffer, sizeof(char), sz, f); + + fclose(f); + + return sz; +} + +void game_print(char *string, int x, int y) +{ + GsSprite print_char; + char q; + + print_char.x = x; + print_char.y = y; + print_char.w = 8; + print_char.h = 8; + print_char.r = NORMAL_LUMINOSITY; + print_char.g = NORMAL_LUMINOSITY; + print_char.b = NORMAL_LUMINOSITY; + print_char.cx = 640; + print_char.cy = 24; + print_char.tpage = 10; + print_char.attribute = COLORMODE(COLORMODE_4BPP); + + while(*string) + { + if(*string >= 0x20 && *string <= 0x7F) + { + q = *string; + q -= 0x20; + + print_char.u = (q&0x1f)<<3; + print_char.v = (q/0x20)<<3; + GsSortSimpleSprite(&print_char); + } + print_char.x+=8; + string++; + } +} + +void game_center_print(char *string, int x, int y) +{ + int l = strlen(string); + l<<=2; + + game_print(string, x - l, y); +} + + + + + +void setup_snake_field() +{ + int x, y; + + for(y=0;y<29;y++) + for(x=0;x<40;x++) + snake_array[y][x] = 0; + + for(y=0;y<29;y++) + { + snake_array[y][0] = 0x81; + snake_array[y][39] = 0x81; + } + + for(x=0;x<40;x++) + { + snake_array[0][x] = 0x81; + snake_array[28][x] = 0x81; + } + + new_apple(); + + for(x=1;x<=snake_size;x++) + snake_array[1][x]=x; + + snake_dir = SNAKE_DIR_RIGHT; +} + +void game_setup() +{ + game_over = 0; + scc = 0; + snake_size = 3; + speed_counter = 0; + score = 0; + setup_snake_field(); + SsKeyOn(0); +} + diff --git a/examples/puzzle/Makefile b/examples/puzzle/Makefile new file mode 100644 index 0000000..ee00787 --- /dev/null +++ b/examples/puzzle/Makefile @@ -0,0 +1,9 @@ +PROJNAME = puzzle + +include ../project.mk + +$(PROJNAME)_extra: + mkdir -p cd_root + bmp2tim puzzle.bmp cd_root/puzzle.tim 16 -org=320,0 + +$(PROJNAME)_clean_extra: diff --git a/examples/puzzle/puzzle.bmp b/examples/puzzle/puzzle.bmp Binary files differnew file mode 100644 index 0000000..ed689c8 --- /dev/null +++ b/examples/puzzle/puzzle.bmp diff --git a/examples/puzzle/puzzle.c b/examples/puzzle/puzzle.c new file mode 100644 index 0000000..8f2786f --- /dev/null +++ b/examples/puzzle/puzzle.c @@ -0,0 +1,216 @@ +#include <psx.h> +#include <stdio.h> +#include <stdlib.h> + + +unsigned char puzzle_pieces[7][7]; +unsigned char piece_taken[7 * 7]; + +int puzzle_x = 0, puzzle_y = 0; + +volatile int display_is_old = 1; + +void prog_vblank_handler() +{ + display_is_old=1; +} + +GsImage puzzle_image; +unsigned int prim_list[0x4000]; +unsigned char data_buffer[0x40000]; // 256 kilobytes + +int main() +{ + int x, y, ex, ey; + int wasleft=0; + int wasright=0; + int wasup=0; + int wasdown=0; + int wasexh=0; + int wasexv=0; + int dbuf=0; + unsigned char b; + unsigned short padbuf; + FILE *f; + GsSprite tile_sprite; + GsRectangle tile_rectangle; + + PSX_Init(); + GsInit(); + GsClearMem(); + GsSetList(prim_list); + GsSetVideoMode(320, 240, EXAMPLES_VMODE); + + f = fopen("cdrom:\\PUZZLE.TIM;1", "rb"); + fseek(f, 0, SEEK_END); + x = ftell(f); + fseek(f, 0, SEEK_SET); + + fread(data_buffer, sizeof(char), x, f); + fclose(f); + + GsImageFromTim(&puzzle_image, data_buffer); + + GsUploadImage(&puzzle_image); + while(GsIsDrawing()); + + GsLoadFont(768, 0, 768, 256); + while(GsIsDrawing()); + + tile_sprite.tpage = 5; + tile_sprite.w = 32; + tile_sprite.h = 32; + tile_sprite.attribute = COLORMODE(COLORMODE_16BPP); + tile_sprite.r = tile_sprite.g = tile_sprite.b = NORMAL_LUMINOSITY; + + SetVBlankHandler(prog_vblank_handler); + + for(x=0;x<sizeof(piece_taken);x++) + piece_taken[x] = 0; + + for(y = 0; y < 7; y++) + { + for(x = 0; x < 7; x++) + { + do + { + puzzle_pieces[y][x] = (rand() % 49) + 1; + }while(piece_taken[puzzle_pieces[y][x]] == 1); + + piece_taken[puzzle_pieces[y][x]] = 1; + } + } + + while(1) + { + if(display_is_old) + { + GsSetDispEnvSimple(0, dbuf?256:0); + GsSetDrawEnvSimple(0, dbuf?0:256, 320, 240); + dbuf=!dbuf; + + PSX_ReadPad(&padbuf, NULL); + + if((padbuf & PAD_LEFT) && !wasleft) + { + if(puzzle_x>0) + puzzle_x--; + + wasleft=1; + } + + if((padbuf & PAD_RIGHT) && !wasright) + { + if(puzzle_x<6) + puzzle_x++; + + wasright=1; + } + + if((padbuf & PAD_UP) && !wasup) + { + if(puzzle_y>0) + puzzle_y--; + + wasup=1; + } + + if((padbuf & PAD_DOWN) && !wasdown) + { + if(puzzle_y<6) + puzzle_y++; + + wasdown=1; + } + + if(!(padbuf & PAD_LEFT)) + wasleft=0; + + if(!(padbuf & PAD_RIGHT)) + wasright=0; + + if(!(padbuf & PAD_UP)) + wasup=0; + + if(!(padbuf & PAD_DOWN)) + wasdown=0; + + if((padbuf & PAD_CROSS) && !wasexh) // x <--> y + { + ey = puzzle_y; + if(puzzle_x < 6) + ex = puzzle_x+1; + else + ex = puzzle_x-1; + + b = puzzle_pieces[puzzle_y][puzzle_x]; + puzzle_pieces[puzzle_y][puzzle_x] = + puzzle_pieces[ey][ex]; + puzzle_pieces[ey][ex] = b; + + wasexh=1; + } + + if((padbuf & PAD_CIRCLE) && !wasexv) + { + ex = puzzle_x; + if(puzzle_y < 6) + ey = puzzle_y+1; + else + ey = puzzle_y-1; + + b = puzzle_pieces[puzzle_y][puzzle_x]; + puzzle_pieces[puzzle_y][puzzle_x] = + puzzle_pieces[ey][ex]; + puzzle_pieces[ey][ex] = b; + + wasexv=1; + } + + if(!(padbuf & PAD_CROSS)) + wasexh=0; + + if(!(padbuf & PAD_CIRCLE)) + wasexv=0; + + GsSortCls(0, 0, 255); + + for(y = 0; y < 7; y++) + { + for(x = 0; x < 7; x++) + { + tile_sprite.x = x * 32; + tile_sprite.y = y * 32; + tile_sprite.u = ((puzzle_pieces[y][x]-1) % 7) * 32; + tile_sprite.v = ((puzzle_pieces[y][x]-1) / 7) * 32; + GsSortSimpleSprite(&tile_sprite); + + if(x == puzzle_x && y == puzzle_y) + { + tile_rectangle.x = x * 32; + tile_rectangle.y = y * 32; + tile_rectangle.r = 255; + tile_rectangle.g = 0; + tile_rectangle.b = 255; + tile_rectangle.w = 32; + tile_rectangle.h = 32; + tile_rectangle.attribute = ENABLE_TRANS; + GsSortRectangle(&tile_rectangle); + } + } + } + + GsPrintFont(232, 16, "Resolve\nPuzzle\n\n" + "Exchange:\n" + "\nX\nHorizontal\n" + "\nO\nVertical"); + + GsDrawList(); + while(GsIsDrawing()); + + display_is_old = 0; + } + } + + return 0; +} diff --git a/examples/rottest/Makefile b/examples/rottest/Makefile new file mode 100644 index 0000000..be7c0c0 --- /dev/null +++ b/examples/rottest/Makefile @@ -0,0 +1,9 @@ +PROJNAME = rottest + +include ../project.mk + +$(PROJNAME)_extra: + mkdir -p cd_root + bmp2tim image.bmp cd_root/image.tim 16 -org=320,0 + +$(PROJNAME)_clean_extra: diff --git a/examples/rottest/image.bmp b/examples/rottest/image.bmp Binary files differnew file mode 100644 index 0000000..e08b3af --- /dev/null +++ b/examples/rottest/image.bmp diff --git a/examples/rottest/rottest.c b/examples/rottest/rottest.c new file mode 100644 index 0000000..4d4f341 --- /dev/null +++ b/examples/rottest/rottest.c @@ -0,0 +1,104 @@ +#include <psx.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +unsigned int prim_list[0x4000]; +unsigned char filebuf[0x40000]; + +volatile int display_is_old = 0; + +void prog_vblank_handler() +{ + display_is_old = 1; +} + +int main() +{ + FILE *f; + GsSprite my_sprite; + GsImage my_image; + int y = 0; + int ro = 0; + int sc_x = SCALE_ONE; + int sc_y = SCALE_ONE; + unsigned short padbuf; + + PSX_Init(); + + GsInit(); + GsSetList(prim_list); + GsSetVideoMode(320, 240, EXAMPLES_VMODE); + + GsClearMem(); + GsSetDrawEnvSimple(0, 256, 320, 240); + GsSetDispEnvSimple(0, 0); + + f = fopen("cdrom:\\IMAGE.TIM;1", "rb"); + fseek(f, 0, SEEK_END); + y = ftell(f); + fseek(f, 0, SEEK_SET); + fread(filebuf, sizeof(char), y, f); + fclose(f); + + GsImageFromTim(&my_image, filebuf); + GsSpriteFromImage(&my_sprite, &my_image, 1); + + SetVBlankHandler(prog_vblank_handler); + + GsLoadFont(768, 0, 768, 128); + while(GsIsWorking()); + + while(1) + { + if(display_is_old) + { + PSX_ReadPad(&padbuf, NULL); + if(padbuf & PAD_LEFT) + { + ro--; + if(ro < 0) ro = 359; + } + + if(padbuf & PAD_RIGHT) + { + ro++; + if(ro>=360) ro = 0; + } + + if(padbuf & PAD_UP) + sc_x+=128; + + if(padbuf & PAD_DOWN) + sc_x-=128; + + if(padbuf & PAD_CROSS) + sc_y-=128; + + if(padbuf & PAD_CIRCLE) + sc_y+=128; + + GsSortCls(0, 0, 0); + + my_sprite.x = 100; + my_sprite.y = 100; + my_sprite.r = my_sprite.g = my_sprite.b = NORMAL_LUMINOSITY; + my_sprite.rotate = ROTATE_ONE*ro; + my_sprite.scalex = sc_x; + my_sprite.scaley = sc_y; + my_sprite.mx = (my_sprite.w/2) * (my_sprite.scalex / 4096); + my_sprite.my = (my_sprite.h/2) * (my_sprite.scaley / 4096); + GsSortSprite(&my_sprite); + + GsPrintFont(0, 0, "ro=%d\nsc_x=%d\nsc_y=%d", ro, sc_x, sc_y); + + GsDrawList(); + while(GsIsWorking()); + + y=!y; + GsSetDrawEnvSimple(0, y?0:256, 320, 240); + GsSetDispEnvSimple(0, y?256:0); + display_is_old = 0; + } + } +} |
