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.
Problems displaying TIM file...
-
- What is PSXDEV?
- Posts: 1
- Joined: Jun 21, 2020
Problems displaying TIM file...
You do not have the required permissions to view the files attached to this post.
-
inc^lightforce Verified
- Psy-Q Enthusiast
- Posts: 249
- Joined: Mar 07, 2013
- I am a: Programmer Windows+PS1, GFX Artist
- PlayStation Model: Black
- Location: Germany
Hi,
this should you help to get into the matter:
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
inc.
this should you help to get into the matter:
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()
//-------------------------------------------------------------------------------
You do not have the required permissions to view the files attached to this post.
Who is online
Users browsing this forum: No registered users and 1 guest