This simple Tutorial should help all beginner to get into the matter of Demo/ Cracktro Coding.

all necessary files you will find attached to this post
don't forget to fix the path in the batch files
- i made a "TimTool_Map.PSX" for the used images. Load this MAP into the TimTool and find out what's happen here.
regards
Today:
- coding a Snowstorm
- a Lava Wobbler
- displaying correctly a 2 tiled Background Picture ( made by SUPERWILL29 )
- playing music
- and have a nice sinus scroll text
Code: Select all
//--------------------------------------------------------------------------
//
// - just a simple democode to display a separated 16 bit Background image
// - a 16 bit Font Image
// - a lava like Wobbler
// - Snow on 4 planes with GsLine
// - Music
//
// to run the Demo directly after compiling use the following Batch Command:
//
// ePSXe.exe demo.exe -nogui
//
// have a closer look in the Batch File, alter your personal path
//
//
// This Sourcecode Blueprint was altered for you from different Projects
// that i made in the late nineties
//
// Inc^Lightforce in June 2020
//
// our retro webpage from the Paradox days:
// http://www.inc-games-design.de/oldHosting/UCA/news.html
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// I N C L U D E S
//--------------------------------------------------------------------------
#include <sys/types.h>
#include <stdlib.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#include <libgs.h>
#include <libsnd.h>
#include <libmath.h>
#include <libspu.h>
#include "hitmod.h" // MUSIC PLAYER
#include "pad.h" // USE GAMEPAD
#include "sinuss.h" // SINUS FOR SCROLLER
#include "colorsin.h" // SINUS MIX for WOBBLER
#include "sinstuff.h" // SINUS MIX for WOBBLER
//---------------------------------------------------------------------
// ASM ADRESS DEFINITION
//---------------------------------------------------------------------
#define NOP 0x00000000
#define PAL 0x24020001
#define NTSC 0x24020000
//---------------------------------------------------------------------
#define ORDERING_TABLE_LENGTH (12)
#define MAX_NO_PACKETS (4000)
#define rnd(max) ((rand()*(max))/(32768)+1)
#define SCRSPEED 2 // Scrollspeed Scroll Text
#define YPOS 100 // Y-Position Scroll Text
//---------------------------------------------------------------------
// STARS as SNOW
//---------------------------------------------------------------------
#define STARSC 1000 // Amount of Stars
#define SPEED 1 // Max Scroll-Speed
#define PLANE 4 // Amount of Stars, Layers
//---------------------------------------------------------------------
//
// G L O B A L S
//
//---------------------------------------------------------------------
GsOT othWorld[2];
GsOT_TAG otWorld[2][1<<ORDERING_TABLE_LENGTH];
PACKET out_packet[2][(MAX_NO_PACKETS * 24)];
u_long PADstatus=0; // Var to store PAD-Status
u_char HZMode=MODE_NTSC;
int currentBuffer; // actual Buffer for "double buffering"
int v_countGFX=0, v_countCODE=0; // HSync Counter
int Xangle,Yangle,depth;
int Xangle2,Yangle2;
int iScrollOffset=0;
//---------------------------------------------------------------------
// LOCATE FILENAMES from Data\*.OBJ
//---------------------------------------------------------------------
extern char sound[]; // music
extern char font[]; // our scroll font
extern char LeftBck[]; // Background Image Left Side ---> using a 320pix large Image can not displayed by PS1, thats why we split
extern char RightBck[]; // Background Image Right Side ---> using a 320pix large Image can not displayed by PS1, thats why we split
//---------------------------------------------------------------------
// DEFINE STARS COORDINATES
//---------------------------------------------------------------------
typedef struct
{
int x; // X-Koordinate des Sterns
int y; // Y-Koordinate des Sterns
int z; // PLANE-ID
} STAR;
STAR Stars[STARSC];
GsLINE line; // TO DISPLAY a DOT for our STARS
//---------------------------------------------------------------------
// DEFINE the vertical Wobble
//---------------------------------------------------------------------
GsGLINE Wobble[320]; //Wobble Lines
GsSPRITE sprLeftBck; // create Sprite from Background Image Left Side
GsSPRITE sprRightBck; // create Sprite from Background Image Right Side
int Video_MODE=0;
//---------------------------------------------------------------------
//----------DEFINE TEXT and Sinus for our Scrollerl Wobble-------------
//---------------------------------------------------------------------
GsSPRITE sprLetter;
static int iSinOff1=0;
#define MAXSINVALUE 256 // Sin-height
static char scrtxt[] = " HELLO SUPERWILL29=== NOW A SMALL TEST INTRO TO CHECK OUT YOUR " "BACKGROUND IMAGE= THE SOUND IS PLAYING WELL=== " "I ALSO ADDED SOME SNOW AND A LAVA LIKE WOBBLER=== " "IF THE INTRO SHOULD START A GAME PRESS X AND PLAY====== CODE BY INC= 2020= " "MUSIC BY OTIS= PEACE ";
char *pBaseText = scrtxt;
//--------------------------------------------------------------------------
//
// P R O T O T Y P E S
//
//--------------------------------------------------------------------------
void InitialiseGraphics(int,int,int); // Width, Height, MODE
void UpdateWorld();
void RenderWorld(char cClear);
void LoadTIMData (u_long *tMemAddress); // RAM -> VRam
void SetSpriteInfo(GsSPRITE *tSprite, u_long tMemAddress, long tX, long tY, int tCut);
void InitStars(void);
void MoveStars(void);
void init_Wobble(void);
void do_Wobble(void);
void DrawScroller(void);
int logosinoff=0;
int savedlogosin=0;
int logosinoff2=0; //Wobble Sin
int savedlogosin2=0; //Wobble Sin
int anzfontabc=0;
static int isinit=0;
//--------------------------------------------------------------------------
//
//
//
// Procedure Main()
//
//
//
//--------------------------------------------------------------------------
int main()
{
u_long lTmp1;
u_long *ficken;
PadInit(0); // Joypad Init
//---------------------------------------------------------------------
// Init the Line and prepare only a DOT for the STAR Procedure
//---------------------------------------------------------------------
InitStars();
//---------------------------------------------------------------------
// Setup the Video Mode for the first start
//---------------------------------------------------------------------
if (*(char *)0xbfc7ff52=='E') // E(urope) --> PAL; A(merica) and J(apan) both use NTSC
{
HZMode=MODE_PAL;
}
else
{
HZMode=MODE_NTSC;
}
InitialiseGraphics(320,240,HZMode); // GFX Init, inkl. Init akt. Buffer...
//---------------------------------------------------------------------
// Init the MOD Player and start music
//---------------------------------------------------------------------
MOD_Init();
MOD_Load((u_char *) sound);
MOD_Start();
//---------------------------------------------------------------------
// LOCATE FILENAMES and load them from Data\*.OBJ
//---------------------------------------------------------------------
LoadTIMData((u_long*)font);
LoadTIMData((u_long*)RightBck);
LoadTIMData((u_long*)LeftBck);
init_Wobble(); // Init Wobble als GsGLINE´s
//---------------------------------------------------------------------
// Correct the Background Images to its right positions
//---------------------------------------------------------------------
SetSpriteInfo(&sprLeftBck,(u_long)LeftBck,0,0,0);
SetSpriteInfo(&sprRightBck,(u_long)RightBck,0,0,0);
sprLeftBck.mx=sprRightBck.mx=0;
sprRightBck.my=sprLeftBck.my=0;
//--------------------------------------------------------------------------
// Init the Letters from our Font Image
//--------------------------------------------------------------------------
SetSpriteInfo(&sprLetter,(u_long)font,0,0,3); //x, y, z
sprLetter.w=sprLetter.h=32; // height of one Letter
sprLetter.mx=sprLetter.my=0;
sprLetter.v=sprLetter.u=0;
{
GsSortSprite(&sprLetter,&othWorld[currentBuffer],2);
RenderWorld(1);
}
//--------------------------------------------------------------------------
// Show us a short Text on Startup
//--------------------------------------------------------------------------
{
int iTmp1;
for (iTmp1=0;iTmp1<60;iTmp1+=1) // set time to stay ---> change 60
{
FntLoad(960,256);
FntOpen(8,100,300,140,0,200);//x,y
FntPrint("\t\tJust a simple Tutorial\n\n\t by Inc of Lightforce\n\n\n\t\t\t ");
RenderWorld(1);
VSync(2);
}
}
//--------------------------------------------------------------------------
//
//
// MAIN LOOP
//
//
//--------------------------------------------------------------------------
while(1)
{
int iTmp1,iTmp2,iTmp3,iTmp4,iTmp5;
PADstatus=PadRead(4);
if(PADstatus&Pad1x){Video_MODE=1; break; } // press X on Pad - run Game in Pal Mode
if(PADstatus&Pad1crc){Video_MODE=2; break; } // press O on Pad - run Game in NTSC Mode
do_Wobble(); // start the Lava Wobbler
//--------------------------------------------------------------------------
// DECLARE BOTH SIDES on the correct position of our BACKGROUND IMAGES
//--------------------------------------------------------------------------
sprLeftBck.x=0;
sprLeftBck.y=sprRightBck.y=0;
sprRightBck.x=160;
GsSortFastSprite(&sprLeftBck,&othWorld[currentBuffer],10);
GsSortFastSprite(&sprRightBck,&othWorld[currentBuffer],10);
//--------------------------------------------------------------------------
MoveStars();
DrawScroller();
RenderWorld(60);
}
//--------------------------------------------------------------------------
// If Pad Break, free Mem
//--------------------------------------------------------------------------
SpuInit();
SpuQuit();
MOD_Stop();
MOD_Free();
//VSync(3);
PadStop();
ResetGraph(0);
StopCallback();
//--------------------------------------------------------------------------
//
// PATCH Values if creating a PAL to NTSC Selector: Video_MODE==1 (PAL)
// Video_MODE==2 (NTSC)
//--------------------------------------------------------------------------
//
//if(Video_MODE==1)
//{
//ficken = (u_long *) 0x80063bbc; *ficken = 0x24020001; // Get Video
//ficken = (u_long *) 0x80063bc0; *ficken = NOP; // Get Video
//
//ficken = (u_long *)0x80068dc8; *ficken = 0x24910030; // X-Delta
//ficken = (u_long *)0x80068dcc; *ficken = 0x24910030; // X-Delta
//}
//--------------------------------------------------------------------------
//
//
// IF PATCHING a PS1 GAME ADD THE CORRECT LOAD ADDRESS to START THE GAME
//
//
//--------------------------------------------------------------------------
// asm("nop");
// asm("j 0x80011bd8"); // ExecAdresse to run the Game
// asm("nop");
//return 0;
}
//--------------------------------------------------------------------------
//
//
// GLOBAL HARDWARE VALUES AND DEFINITIONS
//
//
//--------------------------------------------------------------------------
void InitialiseGraphics(int SCRWidth,int SCRHeight,int HZMode)
{
SetVideoMode(HZMode);
if ((HZMode == MODE_NTSC) && (SCRHeight==256)) SCRHeight=240;
GsInitGraph(SCRWidth, SCRHeight, GsNONINTER|GsOFSGPU, 0, 0);
// define double buffering for draw mode
// (X-Coordinate , Y-Coordinate -> Buffer 0 (0,0)
// X-Coordinate , Y-Coordinate -> Buffer 1 (0,YRes) )
GsDefDispBuff(0, 0, 0, SCRHeight);
// correct Errors from the Library
if (SCRHeight == 256) GsDISPENV.screen.h=256;
othWorld[0].length = ORDERING_TABLE_LENGTH;
othWorld[1].length = ORDERING_TABLE_LENGTH;
othWorld[0].org = otWorld[0];
othWorld[1].org = otWorld[1];
GsClearOt(0,0,&othWorld[0]);
GsClearOt(0,0,&othWorld[1]);
// get the current Buffer
currentBuffer=GsGetActiveBuff();
// create address for "Packet"
GsSetWorkBase((PACKET*)out_packet[currentBuffer]);
}
void RenderWorld(char cClear)
{
// ------------------------------------ "Old List"
v_countCODE=VSync(1);
DrawSync(0);
v_countGFX = VSync(1);
VSync(0); // wait for the GPU until old List is ready
// swap Buffer: (Display / Drawing)
GsSwapDispBuff();
// ------------------------------------ "Current List"
// "register" a "ClearScreen"-Command in OT
// R, G, B
if (cClear==1) GsSortClear(0, 0, 0,&othWorld[currentBuffer]);
if (cClear==60) GsSortClear(0, 0, 0,&othWorld[currentBuffer]);
if (cClear==255) GsSortClear(0, 0, 0,&othWorld[currentBuffer]);
// start DrawMode (the GPU is drawing the OT in the background)
GsDrawOt(&othWorld[currentBuffer]);
FntFlush(-1);
// ------------------------------------ "New List Liste"
// init next OT !!!
// get the current Buffer
currentBuffer=GsGetActiveBuff();
// set address for packet building
GsSetWorkBase((PACKET*)out_packet[currentBuffer]);
// delete the content of the OT
GsClearOt(0, 0, &othWorld[currentBuffer]);
// OT is now ready to receive GsSort... Commands
}
void LoadTIMData(u_long *tMemAddress)
{
RECT tRect;
GsIMAGE tTim;
DrawSync(0);
tMemAddress++;
GsGetTimInfo(tMemAddress, &tTim); // save TIM-Information in tTim
tRect.x = tTim.px;
tRect.y = tTim.py;
tRect.w = tTim.pw;
tRect.h = tTim.ph;
LoadImage(&tRect, tTim.pixel); // load TIM-Data into the VideoRam
DrawSync(0);
if ((tTim.pmode >> 3) & 0x01)
{
tRect.x = tTim.cx;
tRect.y = tTim.cy;
tRect.w = tTim.cw;
tRect.h = tTim.ch;
LoadImage(&tRect, tTim.clut); // load CLUT into the VideoRam
};
DrawSync(0); // warte until the GPU is ready
}
void SetSpriteInfo(GsSPRITE *tSprite, u_long tMemAddress, long tX, long tY, int tCut)
{
GsIMAGE tTim; // TIM image Information
tMemAddress += 4; // Pointer to any Data
GsGetTimInfo((u_long *) tMemAddress, &tTim); // get TIM Info from tTim
tSprite->x = tX; // set Coordinates according to
tSprite->y = tY; // the Info at a Call
switch (tTim.pmode & 3) // X-Value depending from the BitDepht
{
case 0: tSprite->w = tTim.pw << 2;
tSprite->u = (tTim.px & 0x3f) * 4;
break;
case 1: tSprite->w = tTim.pw << 1;
tSprite->u = (tTim.px & 0x3f) * 2;
break;
default: tSprite->w = tTim.pw;
tSprite->u = tTim.px & 0x3f;
};
tSprite->h = tTim.ph;
tSprite->v = tTim.py & 0xff;
tSprite->tpage = GetTPage((tTim.pmode & 3),0,tTim.px,tTim.py);
tSprite->attribute = (tTim.pmode & 3) << 24;
tSprite->cx = tTim.cx; // Set CLUT from Sprite
tSprite->cy = tTim.cy;
tSprite->r = tSprite->g = tSprite->b = 128; // normal Intensiti (of Colors)
// set as Standard
tSprite->mx = tSprite->w/2; // Reference the sprite to the middle coordinates
tSprite->my = tSprite->h/2; // not necessary
tSprite->scalex = tSprite->scaley = ONE; // skale to 1 (normale Size)
tSprite->rotate = 0; // Angle of rotation to 0
if (tCut) // trim Sprite if the Tim
tSprite->w -= tCut; // have a "illegal" range
};
//-------------------------------------------------------------------------------
// Procedure Scroller()
//-------------------------------------------------------------------------------
void DrawScroller(void)
{
int iTmp1,iTmp2,iTmp3;
char *pText;
iSinOff1+=8;iSinOff1%=MAXSINVALUE;
if (iScrollOffset<=-32) {pBaseText++;iScrollOffset+=32;}
iScrollOffset-=SCRSPEED;
if (*pBaseText==NULL) // Scroll End
pBaseText=scrtxt;
pText=pBaseText; // Temp Textpointer
for (iTmp1=0;iTmp1<30;iTmp1++) // view max 11 Letter
{
iTmp2=*pText;
if (iTmp2) // If Letter >0
{
if (iTmp2>'Z') iTmp2=' ';
iTmp2-=' ';
// Destination Coordinates
sprLetter.x=iScrollOffset+32*iTmp1;
iTmp3=SinusS1[(iSinOff1+sprLetter.x)%MAXSINVALUE];
sprLetter.y=YPOS+iTmp3; // Source Coordinates
sprLetter.x+= SinusS1[(iSinOff1+sprLetter.x)%MAXSINVALUE]*4/3;//2+logosin[logosinoff2]/2+logosin3[i]/2;
sprLetter.u=(iTmp2%8)*32;
sprLetter.v=(iTmp2/8)*32;
GsSortSprite(&sprLetter,&othWorld[currentBuffer],3); // "3" Scroller Z Order
pText++;
}
}
}
//-------------------------------------------------------------------------------
// EndProcedure Scroller
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
// Procedure STARS()
//-------------------------------------------------------------------------------
void InitStars(void)
{
int l,zi;
srand(1);
for(l=0;l<STARSC;l++)
{
zi=rand()%320;
Stars[l].x=zi;
zi=rand()%240;
Stars[l].y=zi;
zi=rand()%PLANE;
Stars[l].z=zi+1;
}
}
void MoveStars(void)
{
int i;
for(i=0; i<STARSC; i++)
{
Stars[i].y+=SPEED*Stars[i].z;
if(Stars[i].y>320)
Stars[i].y=0;
line.x0 = line.x1 = Stars[i].x+colorsin[logosinoff2]+scalesin[i];
line.y0 = line.y1 = Stars[i].y;//=240+logosin[logosinoff2]+2+logosin3[i];
line.r = 255;
line.g = line.b =Stars[i].z*255;
GsSortLine(&line,&othWorld[currentBuffer],1);
}
}
//-------------------------------------------------------------------------------
// EndProcedure STARS
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
// Procedure LavaWobbler()
//-------------------------------------------------------------------------------
void init_Wobble()
{
int i=0;
for(i=0;i<241;i++)
{
Wobble[i]=Wobble[0];
Wobble[i].y0=Wobble[i].y1=i;//80;
Wobble[i].x0=0;
Wobble[i].x1=50;//i;
Wobble[i].r0=Wobble[i].b0=Wobble[i].g0=0;
Wobble[i].r1=Wobble[i].b1=Wobble[i].g1=0;
}
}
void do_Wobble()
{
int j;
int i;
logosinoff2=savedlogosin2;
for(i=0;i<241;i++)
{
j=i+1;
Wobble[i].r0=20;
Wobble[i].g0=147;
Wobble[i].b0=130;//colorsin;
Wobble[i].r1=0;
Wobble[i].g1=5;
Wobble[i].b1=65;//0;
Wobble[i].attribute=(2<<24)+(0<<29)+(1<<30);
Wobble[i].x0=10+logosin[logosinoff2]/2+logosin1[i]/2+colorsin[i]/2;
Wobble[i].x1=100+logosin[logosinoff2]/2+logosin3[i]/2;
GsSortGLine(&Wobble[i],&othWorld[currentBuffer], 1);
logosinoff2++;
if(logosinoff2==520)logosinoff2=0;
}
savedlogosin2++;
if(savedlogosin2==520) savedlogosin2=0;
}
//-------------------------------------------------------------------------------
// EndProcedure LavaWobbler()
//-------------------------------------------------------------------------------