Problems displaying TIM file...

Graphic based area of development (Graphics Processing Unit), including the Geometry Transform Engine (GTE), TIM, STR (MDEC), etc.
Post Reply
SuperWill29
What is PSXDEV?
What is PSXDEV?
Posts: 1
Joined: Jun 21, 2020

Problems displaying TIM file...

Post by SuperWill29 » June 24th, 2020, 4:22 am

I'm new to programming here, and have tried working on displaying a TIM image. The example I have used was converted from an old PC game I made at DigiPen that I later plan on remaking. However, when I try to display it, I always get the same problem: the first 4/5 of the screen is displayed correctly, but the last 1/5th is replaced with the first part repeated. My code has been based on several examples, but no matter what I try, I can't get it fixed. I have attached my source code and the image below. I am also using a 4-bit TIM since it is the most compact and most of my images are within 16 colors.

Also, it seems that the image is slightly off vertical position, since there are some vertical rows of pixels that are cut off at the top. Does anyone know what the deal with this is? I tried setting the vertical resolution to 256, but it makes nothing display at all, just a black screen.
You do not have the required permissions to view the files attached to this post.

User avatar
inc^lightforce
Verified
Psy-Q Enthusiast
Psy-Q Enthusiast
Posts: 248
Joined: Mar 07, 2013
I am a: Programmer Windows+PS1, GFX Artist
PlayStation Model: Black
Location: Germany

Post by inc^lightforce » June 25th, 2020, 1:51 pm

Hi,

this should you help to get into the matter:

Image

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 your images. Load this into the TimTool and find out what's happen here.

regards

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 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()
//-------------------------------------------------------------------------------
inc.
You do not have the required permissions to view the files attached to this post.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest