Author Topic: PSX version battle backgrounds  (Read 23553 times)

Micky

  • *
  • Posts: 300
    • View Profile
PSX version battle backgrounds
« on: 2004-06-28 00:09:17 »
I haven't found any other documentation on this, except (I think) for the PC version. This is for the PSX version.
Code: [Select]

Battle Backgrounds PSX
======================

Backgrounds are stored in probably the easiest model format used in FF7. I reconstructed this from the code for my background-to-Maya converter, so there could be errors. I haven't seen any other documentation on this, so please excuse any duplication...

The backgrounds are stored in LZS files in the STAGE1 and STAGE2 directories. They are using the ff7-standard lzs compression.

They begin with a directory: The first word is the number of sections, then there is one pointer for each sections.
Each section contains a mesh for the background, except for the first that contains some unknown data and the last that contains the TIM-format texture and palettes.

Each section starts with vertex data, followed by a triangle and a quad data.

Vertex data:
1 u32 size of vertex data

8 byte per vertex:
3 u16 x,y,z
1 u16 pad(?)

Triangle data
1 u16 number of triangles
1 u16 texture page (among other flags)

16 bytes per triangle:
3 u16 offset into vertex table
1 u16 unknown
2 u8 u1, v1
1 u16 palette (and some other flags)
2 u8 u2, v2
2 u8 u3, v3
 
Quad data
1 u16 number of quads
1 u16 texture page (among other flags)

20 bytes per quad:
4 u16 offset into vertex table
2 u8 u1, v1
1 u16 palette
2 u8 u2, v2
2 u8 u3, v3
2 u8 u4, v4
1 u16 unknown

Displaying the backgrounds is a bit tricky on modern graphics boards, as they don't support palletised textures anymore. Which is understandable given the large number of fetches that would be required for displaying a properly filtered texture - but not very helpful. I solved that by a pre-process that stores the palette on each pixel and then looks up the colour during export.

mirex

  • *
  • Posts: 1645
    • View Profile
    • http://mirex.mypage.sk
PSX version battle backgrounds
« Reply #1 on: 2004-06-28 07:42:32 »
Nice progress.

Micky

  • *
  • Posts: 300
    • View Profile
PSX version battle backgrounds
« Reply #2 on: 2004-06-29 20:41:38 »
And some code to display them with OpenGL. Works on my Mac, but as I'm using GLUT it should work on Windows, too.
I'm not sure if this is enough to make spell effects work, but you can always calculate normals and add a colour array as well.
Could probably be optimised a bit more, but even in this form it should draw a lot faster than on the PSX...
It doesn't do alpha-blending, just some alpha-kill so you can see through trees and bushes.
Enjoy.
(Small fix to remember the current directory.)
Code: [Select]

// System
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// STL
#include <string>
#include <cassert>

#if 1
// GLUT
#include <GLUT/glut.h>

// OpenGL
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
// GLUT
#include <glut/glut.h>

// OpenGL
#include <gl/gl.h>
#include <gl/glu.h>
#endif

using namespace std;

typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned long int u32;

typedef signed char s8;
typedef signed short int s16;
typedef signed long int s32;

// utility functions

u16 get_u16le(void const * const buf)
{
return ((u8*)buf)[0] | (((u8*)buf)[1]<<8);
}

u32 get_u32le(void const * const buf)
{
return ((u8*)buf)[0] | (((u8*)buf)[1]<<8) | (((u8*)buf)[2]<<16) | (((u8*)buf)[3]<<24);
}

int load( const string & name, void ** data )
{
        size_t size = 0;
        *data = NULL;
        int fd = open( name.c_str(), O_RDONLY, 0 );
        if (fd >= 0) {
                struct stat sb;
                if ( fstat( fd, &sb ) >= 0) {
                        assert( sb.st_size > 0 );
                        void *tmp = malloc( sb.st_size );
                        if ( tmp!=NULL ) {
                                if (read( fd, tmp, sb.st_size ) == sb.st_size) {
                                        *data = tmp;
                                        size = sb.st_size;
                                } else {
                                        free(tmp);
                                }
                        }
                }
                close( fd );
        }
        return size;
}

int load_lzs(const string & name, void ** data )
{
// read compressed data
u8 *buf;
int tsize = load( name, (void**)&buf );
int isize = get_u32le(buf) + 4;

if (isize != tsize) {
free(buf);
*data = NULL;
return 0;
}

// decompress;
int osize = (isize + 255) & ~255;
u8 * obuf = (u8 *)malloc(osize);
int iofs = 4, oofs = 0;
u8 cmd=0, bit=0;
while (iofs < isize) {
if (bit == 0) {
cmd = buf[iofs++];
bit = 8;
}
if (cmd&1) {
obuf[oofs++]=buf[iofs++];
if (oofs==osize) {
osize+=256;
obuf = (u8*)realloc(obuf, osize);
}
} else {
u8 a = buf[iofs++];
u8 b = buf[iofs++];
u16 o = a | ((b&0xF0)<<4);
u8 len = (b&0xF)+3;

int rofs =  oofs - ((oofs - 18 - o) & 0xFFF);
for (int j=0; j<len; j++) {
if (rofs < 0) {
obuf[oofs++]=0;
} else {
obuf[oofs++]=obuf[rofs];
}
if (oofs==osize) {
osize+=256;
obuf = (u8*)realloc(obuf, osize);
}
rofs++;
}
}
cmd>>=1;
bit--;
}
free( buf );

*data = obuf;
return oofs;
}


// Background loading and storage

struct Vertex {
s16 x, y, z;
s16 u, v;
};

struct Element {
u16 a, b, c, s; // s = shader
};

struct Mesh {
int texture;
int element_start;
int element_count;
};

struct Shader {
int texture;
int palette;
};

struct Background {
int vertex_count;
Vertex *vertex;
int element_count;
Element *element;
int *indexbuffer;
int shader_count;
Shader *shader;
GLuint *textures;
int mesh_count;
Mesh *mesh;
};

int
add_vertex(Background *bg, s16 x, s16 y, s16 z, u8 u, u8 v)
{
for (int i=0; i<bg->vertex_count; i++) {
if (bg->vertex[i].x == x && bg->vertex[i].y == y && bg->vertex[i].z == z && bg->vertex[i].u == u && bg->vertex[i].v == v) {
return i;
}
}

int idx = bg->vertex_count++;
bg->vertex = (Vertex *)realloc(bg->vertex, bg->vertex_count * sizeof(Vertex));
bg->vertex[idx].x = x;
bg->vertex[idx].y = y;
bg->vertex[idx].z = z;
bg->vertex[idx].u = u;
bg->vertex[idx].v = v;
return idx;
}

int
add_triangle(Background *bg, u16 a, u16 b, u16 c, u16 s)
{
int idx = bg->element_count++;
bg->element = (Element*)realloc(bg->element, bg->element_count * sizeof(Element));
bg->element[idx].a = a;
bg->element[idx].b = b;
bg->element[idx].c = c;
bg->element[idx].s = s;
return idx;
}

int
add_shader(Background *bg, int texture, int palette)
{
for (int i=0; i<bg->shader_count; i++) {
if (bg->shader[i].texture == texture && bg->shader[i].palette == palette) {
return i;
}
}

int idx = bg->shader_count++;
bg->shader = (Shader *)realloc(bg->shader, bg->shader_count * sizeof(Shader));
bg->shader[idx].texture = texture;
bg->shader[idx].palette = palette;

return idx;
}

void
load_background(const string & filename, Background *bg)
{
bg->vertex_count = 0;
bg->vertex = NULL;
bg->element_count = 0;
bg->element = NULL;
bg->textures = NULL;
bg->shader_count = 0;
bg->shader = NULL;
bg->mesh_count = 0;
bg->mesh = NULL;

u8 * data;
int size = load_lzs(filename, (void**)&data);

int num_pointer = get_u32le(data);

// background texture
int texdata = get_u32le(data + num_pointer * 4);
int npal = get_u16le(data + texdata + 18);
int paldata_size = get_u32le(data+texdata+8);
int pal_ofs = texdata + 20;
int picdata_size = get_u32le(data+texdata+8+paldata_size);
int pic_ofs = texdata + 20 + npal*512 + 12;

int xsize = get_u16le(data+pic_ofs-4)*2;
int ysize = get_u16le(data+pic_ofs-2);

// convert mesh data
for (int i=1; i<num_pointer-1; i++) {
int base = get_u32le(data + 4 + i * 4);

// triangles
int triangle_offset = base + 4 + get_u32le(data + base);
int num_triangles = get_u16le(data + triangle_offset);
int mesh_tri_flags = get_u16le(data + triangle_offset + 2);

int texture_idx = ((mesh_tri_flags & 0x0E)-6) / 2;
for (int j=0; j<num_triangles; j++) {
int point[3];
int ofs = triangle_offset + 4 + j * 16;
for (int k=0; k<3; k++) {
int p = get_u16le(data + ofs + k * 2) + base + 4;
s16 x =  ((s16)get_u16le(data + p + 0*2));
s16 y = -((s16)get_u16le(data + p + 1*2));
s16 z =  ((s16)get_u16le(data + p + 2*2));

const int uv_offsets[3] = { 8, 12, 14 };
u8 u = data[ofs + uv_offsets[k] + 0];
u8 v = data[ofs + uv_offsets[k] + 1];
point[k] = add_vertex(bg, x,y,z,u,v);
}

u16 flags1 = get_u16le(data + ofs + 6);
u16 flags2 = get_u16le(data + ofs + 10);

int palette_idx = (flags2 >> 6) & 7;
int shader_idx = add_shader(bg, texture_idx, palette_idx);

add_triangle(bg, point[0], point[1], point[2], shader_idx);
}

// quads
int quad_offset = triangle_offset + 4 + num_triangles * 16;
int num_quads = get_u16le(data + quad_offset);
int mesh_quad_flags = get_u16le(data + quad_offset + 2);
for (int j=0; j<num_quads; j++) {
int point[4];
int ofs = quad_offset + 4 + j * 20;
for (int k=0; k<4; k++) {
int p = get_u16le(data + ofs + k * 2) + base + 4;
s16 x =  ((s16)get_u16le(data + p + 0 * 2));
s16 y = -((s16)get_u16le(data + p + 1 * 2));
s16 z =  ((s16)get_u16le(data + p + 2 * 2));

const int uv_offsets[4] = { 8, 12, 14, 16 };
u8 u = data[ofs + uv_offsets[k] + 0];
u8 v = data[ofs + uv_offsets[k] + 1];
point[k] = add_vertex(bg, x,y,z,u,v);
}
u16 flags1 = get_u16le(data + ofs + 18);
u16 flags2 = get_u16le(data + ofs + 10);

int palette_idx = (flags2 >> 6) & 7;
int shader_idx = add_shader(bg, texture_idx, palette_idx);

add_triangle(bg, point[0], point[1], point[2], shader_idx);
add_triangle(bg, point[3], point[2], point[1], shader_idx);
}
}

// build meshes
bg->indexbuffer = (int*)malloc(bg->element_count * 3 * sizeof(int));
int cur_mesh = 0;
for (int i=0; i<bg->element_count; i++) {
bg->indexbuffer[i * 3 + 0] = bg->element[i].a;
bg->indexbuffer[i * 3 + 1] = bg->element[i].b;
bg->indexbuffer[i * 3 + 2] = bg->element[i].c;

if (bg->mesh_count > 0 && bg->mesh[cur_mesh].texture == bg->element[i].s) {
bg->mesh[cur_mesh].element_count++;
} else {
cur_mesh = bg->mesh_count++;
bg->mesh = (Mesh*)realloc(bg->mesh, bg->mesh_count * sizeof(Mesh));
bg->mesh[cur_mesh].texture = bg->element[i].s;
bg->mesh[cur_mesh].element_start = i*3;
bg->mesh[cur_mesh].element_count = 1;
}
}

// build required textures
struct RGBA {
u8 r, g, b, a;
};

RGBA *clut = (RGBA*)malloc(sizeof(RGBA) * 256 * (npal));
for (int j = 0; j < npal; j++) {
for (int i=0; i<256; i++) {
u16 col = (data[i*2 + pal_ofs + j*512 + 1]<<8) | data[i*2 + pal_ofs + j * 512];
clut[i+j*256].r = (((col      ) & 31) * 255 + 15) / 31;
clut[i+j*256].g = (((col >>  5) & 31) * 255 + 15) / 31;
clut[i+j*256].b = (((col >> 10) & 31) * 255 + 15) / 31;
clut[i+j*256].a = ((col & 0x8000) || (col == 0)) ? 0 : 255;
}
}

bg->textures = (GLuint*)malloc(sizeof(GLuint) * bg->shader_count);
glGenTextures( bg->shader_count, bg->textures);
RGBA *texture = (RGBA*)malloc(sizeof(RGBA) * 256 * 256);
for (int i=0; i<bg->shader_count; i++) {
// build
#if 1
if ( bg->shader[i].palette >= npal ) {
printf("%i %i\n", bg->shader[i].palette, npal);
bg->shader[i].palette = 0;
}
#endif
for (int y=0; y<256; y++) {
for (int x=0; x<256; x++) {
texture[y*256+x] = clut[data[pic_ofs + y * xsize + x + bg->shader[i].texture * 256] + bg->shader[i].palette * 256];
}
}

// copy to GL
glBindTexture( GL_TEXTURE_2D, bg->textures[i]);
#if 0
// blocky
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, texture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
#else
// interpolated
gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, texture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
#endif
}
free(texture);
free(clut);
free(data);
}

// GLUT and OpenGL stuff
Background battle;
int rot_y;
int rot_x;

void ReshapeWindowFunc(int width, int height)
{
const double kFOVy = 0.57735;
const double kZNear = 0.1;

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLdouble aspect = ((GLfloat)width / (GLfloat)height) * (kZNear * kFOVy);
glFrustum(-aspect, aspect, -(kZNear * kFOVy), (kZNear * kFOVy), kZNear, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void MainRenderLoop(void)
{
// render
glClearColor(0, 0, 0, 1.00);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LEQUAL );
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 1.0f/255.0f);
glEnable( GL_TEXTURE_2D );
glEnable( GL_CULL_FACE );
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
        glDisable( GL_LIGHTING );
glDisable( GL_BLEND );

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef( (float)rot_x * 360.0f / 256.0f, 1.0f, 0.0f, 0.0f );
glRotatef( (float)rot_y * 360.0f / 256.0f, 0.0f, 1.0f, 0.0f );
glTranslatef( 0, -16, 0);
glScalef( 1.0f/256.0f, 1.0f/256.0f, 1.0f/256.0f );

glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(1.0f/256.0f, 1.0f/256.0f, 0);
glTranslatef( 0.5f, 0.5f, 0);

glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );

glVertexPointer( 3, GL_SHORT, sizeof(Vertex), &(battle.vertex[0].x) );
glTexCoordPointer( 2, GL_SHORT, sizeof(Vertex), &(battle.vertex[0].u) );

for (int i = 0; i < battle.mesh_count; i++) {
glBindTexture(GL_TEXTURE_2D, battle.textures[battle.mesh[i].texture]);
glDrawElements(GL_TRIANGLES, battle.mesh[i].element_count * 3, GL_UNSIGNED_INT, battle.indexbuffer + battle.mesh[i].element_start);
}

glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );

glFlush();
}

void SpecialHandler(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_UP:
rot_x -= 4;
if (rot_x < -64) {
rot_x = -64;
}
break;
case GLUT_KEY_DOWN:
rot_x += 4;
if (rot_x > 64) {
rot_x = 64;
}
break;
case GLUT_KEY_LEFT:
rot_y -= 5;
break;
case GLUT_KEY_RIGHT:
rot_y += 5;
break;
}
glutPostRedisplay();
}

void KeyboardHandler(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}

int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "stageview <stage.lzs>\n");
} else {
// get current directory
char cwd[1024];
getcwd(cwd, sizeof(cwd));

              string path;
if (argv[1][0] != 0 && argv[1][0] != '/' && argv[1][1] != 0 && argv[1][1] != ':' && argv[1][2] != 0 && argv[1][2] != '\\') {
path = string(cwd) + "/";
}

// init opengl and glut
glutInit(&argc, (char **) argv);
glutInitWindowSize(640, 480);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow(argv[0]);
glutDisplayFunc(MainRenderLoop);
glutIdleFunc(MainRenderLoop);
glutReshapeFunc(ReshapeWindowFunc);
glutKeyboardFunc(KeyboardHandler);
glutSpecialFunc(SpecialHandler);

// load data
load_background(path + argv[1], &battle);

rot_y = rot_x = 0;

// main (this will never return)
glutMainLoop();
}
return 0;
}

sfx1999

  • *
  • Posts: 1142
    • View Profile
PSX version battle backgrounds
« Reply #3 on: 2004-06-29 21:52:08 »
I sucessfully built it with MinGW, but do not have the data to test it with. Of course I had to add a couple includes, but that's it.

Here it is:

http://bin.mypage.sk/FILES/mickysprogram.zip

It requires GLUT to run. Get GLUT at http://www.xmission.com/~nate/glut.html.

Micky

  • *
  • Posts: 300
    • View Profile
PSX version battle backgrounds
« Reply #4 on: 2004-06-29 21:55:08 »
I called it "stageview", but in the end you can call it mickysprogram if you like.  :D

Anakin

  • *
  • Posts: 42
    • View Profile
PSX version battle backgrounds
« Reply #5 on: 2004-06-29 23:02:38 »
I put all the files of GLUT bin for Win32 in WINDOWS/System32 folder(XPpro)
and the stageview crashes
have I done something wrong?
Thanks

sfx1999

  • *
  • Posts: 1142
    • View Profile
PSX version battle backgrounds
« Reply #6 on: 2004-06-30 02:08:51 »
Glut dlls go in the system folder, not system32.

Did you open it in a DOS box? You gave it parameters, right?

Anakin

  • *
  • Posts: 42
    • View Profile
PSX version battle backgrounds
« Reply #7 on: 2004-06-30 05:39:36 »
Actually in the begining I put the dll in System folder but the program crashed so I changed the location to System32 without any results
anyway I'll try to recompile
Thx

sfx1999

  • *
  • Posts: 1142
    • View Profile
PSX version battle backgrounds
« Reply #8 on: 2004-06-30 05:41:33 »
What was the error message?

Anakin

  • *
  • Posts: 42
    • View Profile
PSX version battle backgrounds
« Reply #9 on: 2004-06-30 05:57:10 »
stageview.exe has encontered a problem and needs to close

Code: [Select]
<?xml version="1.0" encoding="UTF-16"?>
<DATABASE>
<EXE NAME="SYSTEM INFO" FILTER="GRABMI_FILTER_SYSTEM">
    <MATCHING_FILE NAME="advapi32.dll" SIZE="549888" CHECKSUM="0x4F484D70" BIN_FILE_VERSION="5.1.2600.0" BIN_PRODUCT_VERSION="5.1.2600.0" PRODUCT_VERSION="5.1.2600.0" FILE_DESCRIPTION="Advanced Windows 32 Base API" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Windows® Operating System" FILE_VERSION="5.1.2600.0 (XPClient.010817-1148)" ORIGINAL_FILENAME="advapi32.dll" INTERNAL_NAME="advapi32.dll" LEGAL_COPYRIGHT="© Microsoft Corporation. All rights reserved." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x8F9C5" LINKER_VERSION="0x50001" UPTO_BIN_FILE_VERSION="5.1.2600.0" UPTO_BIN_PRODUCT_VERSION="5.1.2600.0" LINK_DATE="08/18/2001 05:33:02" UPTO_LINK_DATE="08/18/2001 05:33:02" VER_LANGUAGE="English (United States) [0x409]" />
    <MATCHING_FILE NAME="gdi32.dll" SIZE="241664" CHECKSUM="0x63C03AF9" BIN_FILE_VERSION="5.1.2600.132" BIN_PRODUCT_VERSION="5.1.2600.132" PRODUCT_VERSION="5.1.2600.132" FILE_DESCRIPTION="GDI Client DLL" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Windows® Operating System" FILE_VERSION="5.1.2600.132 (xpclnt_qfe.021108-2107)" ORIGINAL_FILENAME="gdi32" INTERNAL_NAME="gdi32" LEGAL_COPYRIGHT="© Microsoft Corporation. All rights reserved." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x4A673" LINKER_VERSION="0x50001" UPTO_BIN_FILE_VERSION="5.1.2600.132" UPTO_BIN_PRODUCT_VERSION="5.1.2600.132" LINK_DATE="03/30/2004 01:25:40" UPTO_LINK_DATE="03/30/2004 01:25:40" VER_LANGUAGE="English (United States) [0x409]" />
    <MATCHING_FILE NAME="kernel32.dll" SIZE="926720" CHECKSUM="0x6262EEA5" BIN_FILE_VERSION="5.1.2600.0" BIN_PRODUCT_VERSION="5.1.2600.0" PRODUCT_VERSION="5.1.2600.0" FILE_DESCRIPTION="Windows NT BASE API Client DLL" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Windows® Operating System" FILE_VERSION="5.1.2600.0 (xpclient.010817-1148)" ORIGINAL_FILENAME="kernel32" INTERNAL_NAME="kernel32" LEGAL_COPYRIGHT="© Microsoft Corporation. All rights reserved." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0xE8792" LINKER_VERSION="0x50001" UPTO_BIN_FILE_VERSION="5.1.2600.0" UPTO_BIN_PRODUCT_VERSION="5.1.2600.0" LINK_DATE="08/18/2001 05:33:02" UPTO_LINK_DATE="08/18/2001 05:33:02" VER_LANGUAGE="English (United States) [0x409]" />
    <MATCHING_FILE NAME="ntdll.dll" SIZE="651264" CHECKSUM="0xEA9C095" BIN_FILE_VERSION="5.1.2600.114" BIN_PRODUCT_VERSION="5.1.2600.114" PRODUCT_VERSION="5.1.2600.114" FILE_DESCRIPTION="NT Layer DLL" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Windows® Operating System" FILE_VERSION="5.1.2600.114 (xpclnt_qfe.021108-2107)" ORIGINAL_FILENAME="ntdll.dll" INTERNAL_NAME="ntdll.dll" LEGAL_COPYRIGHT="© Microsoft Corporation. All rights reserved." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0xA2397" LINKER_VERSION="0x50001" UPTO_BIN_FILE_VERSION="5.1.2600.114" UPTO_BIN_PRODUCT_VERSION="5.1.2600.114" LINK_DATE="05/02/2003 18:03:00" UPTO_LINK_DATE="05/02/2003 18:03:00" VER_LANGUAGE="English (United States) [0x409]" />
    <MATCHING_FILE NAME="ole32.dll" SIZE="1105408" CHECKSUM="0x9E050449" BIN_FILE_VERSION="5.1.2600.136" BIN_PRODUCT_VERSION="5.1.2600.136" PRODUCT_VERSION="5.1.2600.136" FILE_DESCRIPTION="Microsoft OLE for Windows" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Windows® Operating System" FILE_VERSION="5.1.2600.136 (xpclnt_qfe.021108-2107)" ORIGINAL_FILENAME="OLE32.DLL" INTERNAL_NAME="OLE32.DLL" LEGAL_COPYRIGHT="© Microsoft Corporation. All rights reserved." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x11DC8A" LINKER_VERSION="0x50001" UPTO_BIN_FILE_VERSION="5.1.2600.136" UPTO_BIN_PRODUCT_VERSION="5.1.2600.136" LINK_DATE="03/06/2004 02:05:11" UPTO_LINK_DATE="03/06/2004 02:05:11" VER_LANGUAGE="English (United States) [0x409]" />
    <MATCHING_FILE NAME="oleaut32.dll" SIZE="569344" CHECKSUM="0x33FCD4B1" BIN_FILE_VERSION="3.50.5014.0" BIN_PRODUCT_VERSION="3.50.5014.0" PRODUCT_VERSION="3.50.5014.0" FILE_DESCRIPTION="Microsoft OLE 3.50  for Windows NT(TM) and Windows 95(TM) Operating Systems" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft OLE 3.50  for Windows NT(TM) and Windows 95(TM) Operating Systems" FILE_VERSION="3.50.5014.0" INTERNAL_NAME="OLEAUT32.DLL" LEGAL_COPYRIGHT="Copyright © Microsoft Corp. 1993-1999." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x9AC05" LINKER_VERSION="0x0" UPTO_BIN_FILE_VERSION="3.50.5014.0" UPTO_BIN_PRODUCT_VERSION="3.50.5014.0" LINK_DATE="08/18/2001 05:33:04" UPTO_LINK_DATE="08/18/2001 05:33:04" VER_LANGUAGE="English (United States) [0x409]" />
    <MATCHING_FILE NAME="shell32.dll" SIZE="8223744" CHECKSUM="0x14E5D605" BIN_FILE_VERSION="6.0.2600.115" BIN_PRODUCT_VERSION="6.0.2600.115" PRODUCT_VERSION="6.00.2600.115" FILE_DESCRIPTION="Windows Shell Common Dll" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Windows® Operating System" FILE_VERSION="6.00.2600.115 (xpclnt_qfe.021108-2107)" ORIGINAL_FILENAME="SHELL32.DLL" INTERNAL_NAME="SHELL32" LEGAL_COPYRIGHT="© Microsoft Corporation. All rights reserved." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x7E7306" LINKER_VERSION="0x50001" UPTO_BIN_FILE_VERSION="6.0.2600.115" UPTO_BIN_PRODUCT_VERSION="6.0.2600.115" LINK_DATE="06/11/2003 20:53:04" UPTO_LINK_DATE="06/11/2003 20:53:04" VER_LANGUAGE="English (United States) [0x409]" />
    <MATCHING_FILE NAME="user32.dll" SIZE="528896" CHECKSUM="0x19795864" BIN_FILE_VERSION="5.1.2600.118" BIN_PRODUCT_VERSION="5.1.2600.118" PRODUCT_VERSION="5.1.2600.118" FILE_DESCRIPTION="Windows XP USER API Client DLL" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Windows® Operating System" FILE_VERSION="5.1.2600.118 (xpclnt_qfe.021108-2107)" ORIGINAL_FILENAME="user32" INTERNAL_NAME="user32" LEGAL_COPYRIGHT="© Microsoft Corporation. All rights reserved." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x8BA11" LINKER_VERSION="0x50001" UPTO_BIN_FILE_VERSION="5.1.2600.118" UPTO_BIN_PRODUCT_VERSION="5.1.2600.118" LINK_DATE="09/26/2003 18:51:30" UPTO_LINK_DATE="09/26/2003 18:51:30" VER_LANGUAGE="English (United States) [0x409]" />
    <MATCHING_FILE NAME="WININET.DLL" SIZE="585216" CHECKSUM="0x6668671E" BIN_FILE_VERSION="6.0.2737.800" BIN_PRODUCT_VERSION="6.0.2737.800" PRODUCT_VERSION="6.00.2737.800" FILE_DESCRIPTION="Internet Extensions for Win32" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Windows® Operating System" FILE_VERSION="6.00.2737.800" ORIGINAL_FILENAME="wininet.dll" INTERNAL_NAME="wininet.dll" LEGAL_COPYRIGHT="© Microsoft Corporation. All rights reserved." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x953E8" LINKER_VERSION="0x50001" UPTO_BIN_FILE_VERSION="6.0.2737.800" UPTO_BIN_PRODUCT_VERSION="6.0.2737.800" LINK_DATE="01/08/2004 22:23:34" UPTO_LINK_DATE="01/08/2004 22:23:34" VER_LANGUAGE="English (United States) [0x409]" />
    <MATCHING_FILE NAME="winsock.dll" SIZE="2864" CHECKSUM="0x73AE8088" BIN_FILE_VERSION="3.10.0.103" BIN_PRODUCT_VERSION="3.10.0.103" PRODUCT_VERSION="3.10" FILE_DESCRIPTION="Windows Socket 16-Bit DLL" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Windows(TM) Operating System" FILE_VERSION="3.10" ORIGINAL_FILENAME="WINSOCK.DLL" INTERNAL_NAME="WINSOCK" LEGAL_COPYRIGHT="Copyright © Microsoft Corp. 1981-1996" VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x10001" VERFILETYPE="0x2" MODULE_TYPE="WIN16" S16BIT_DESCRIPTION="BSD Socket API for Windows" S16BIT_MODULE_NAME="WINSOCK" UPTO_BIN_FILE_VERSION="3.10.0.103" UPTO_BIN_PRODUCT_VERSION="3.10.0.103" VER_LANGUAGE="English (United States) [0x409]" />
</EXE>
</DATABASE>

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
PSX version battle backgrounds
« Reply #10 on: 2004-06-30 06:37:22 »
Under linux:

NVIDIA has no OpenGL.h lib

for some reason it was trying to include it. I forced it not to.

I get this at compile time

Code: [Select]

halkun@naru:~/lab> gcc stageview.cpp -o stage
stageview.cpp: In function `int load(const std::string&, void**)':
stageview.cpp:62: error: `assert' undeclared (first use this function)
stageview.cpp:62: error: (Each undeclared identifier is reported only once for each function it appears in.)


Of course this is useless without a makefile. I have to include my X11 libs and my GL libs at link time, I'm just seeing of it would even compile first

Micky

  • *
  • Posts: 300
    • View Profile
PSX version battle backgrounds
« Reply #11 on: 2004-06-30 07:38:51 »
Anakin: You can put glut.dll into the same directory as sceneview.exe. When windows looks for DLLs it looks into the current directory first.

halkun: OpenGL.h is a Mac library that provides stuff that is similar to the glx stuff on Linux and wgl stuff on windows. you don't need to include that.
for assert:
#include <cassert>
or
#include <assert.h>

Sorry about that.

Makefile make more sense if you have more then one file... And as I can't attach a zip file to a message I wanted to have it as simple as possible. Please try a bash script for now.

It works fine here, so if you can give me a stack trace I can have a look:
Code: [Select]

gdb stageview
(inside gdb)
r <somestagefile.lzs>
bt

Anakin

  • *
  • Posts: 42
    • View Profile
PSX version battle backgrounds
« Reply #12 on: 2004-06-30 14:47:04 »
Quote from: Micky
Anakin: You can put glut.dll into the same directory as sceneview.exe. When windows looks for DLLs it looks into the current directory first.
[/code]


still no
it crashes after a while though, as if it "tries" but cannot initialize a graphics window or something

Micky

  • *
  • Posts: 300
    • View Profile
PSX version battle backgrounds
« Reply #13 on: 2004-06-30 16:50:29 »
Something seems to change the current directory and then the file loading fails. This worked fine for me, because my development directory is far away from the data directory and I always use the absolute path...

So what you can do is run stageview with the absolute path to the file:
Code: [Select]
stageview D:\STAGE1\STAGE09.LZS
(if D: is your CD drive)

I did a small fix to the code above. It is not very elegant, but should cover both Unix-y and Windows-y operating systems.

Cyberman

  • *
  • Posts: 1572
    • View Profile
PSX version battle backgrounds
« Reply #14 on: 2004-06-30 19:24:19 »
Heh.. It's following the pattern of all the files that are on the FF7 disks for the PSX.
Essentially That's binary RSD texture data.  And it's using a standard archive style used in FF7

Now if I could only make more sense of BCX files.. things could role, there is something funny with them and I just can't quite figure out what they did differently with them.

I should have at least the beginings of these decoded (IE just the vertices and wire frame for now).  I suppose I can add POV output in a little while (grin).

Here are what I use for FF7 models in my program (which has like 20 different files now).

Code: [Select]

// Pallette/Color Look Up Tables for TIM files
typedef  UINT16 CLUT_4bpp[16];
typedef  UINT16 CLUT_8bpp[256];

// PSX FF7 Model data

typedef struct
{
   UINT16   Parent;
   INT16    Length;
   UINT32   Offset;
}
PSX_UNK_BM;

typedef struct
{
   UINT8 R;
   UINT8 G;
   UINT8 B;
   UINT8 U;
}
PSX_FF7_CLR;

typedef struct
{
   INT16   X;
   INT16   Y;
   INT16   Z;
   UINT16   U;

}
PSX_FF7_VERTEX;

typedef struct
{
   UINT16   A;
   UINT16   B;
   UINT16   C;
   UINT16   D;
}
PSX_FF7_POLY;

typedef struct
{
   PSX_FF7_POLY  Vertexs;
   PSX_FF7_CLR   Colors[3];
}
PSX_FF7_TRI;

typedef struct
{
   PSX_FF7_POLY  Vertexs;
   PSX_FF7_CLR   Colors[4];
}
PSX_FF7_QUAD;

typedef struct
{
   PSX_FF7_POLY   Vertexs;
   UINT8          U0, V0;
   UINT8          PAL, ZZ;
   UINT8          U1, V1;
   UINT8          U2, V2;
}
PSX_FF7_TTRI;

typedef struct
{
   PSX_FF7_POLY   Vertexs;
   UINT8          U0, V0;
   UINT8          PAL, ZZ0;
   UINT8          U1, V1;
   UINT8          U2, V2;
   UINT8          U3, V3;
   UINT16         ZZ1;
}
PSX_FF7_TQUAD;


Cyb

Micky

  • *
  • Posts: 300
    • View Profile
PSX version battle backgrounds
« Reply #15 on: 2004-06-30 19:55:10 »
Quote from: Cyberman
Heh.. It's following the pattern of all the files that are on the FF7 disks for the PSX.

It is obviously arranged that way so that it can be fed into the hardware as fast as possible. Which doesn't match the PC hardware, so I arrange it into a vertex array and triangle list. The triangle list isn't the best format, but should do. And I don't have to include a triangle stripper.  :)

Now if someone could just help decode the animation data for player and monster models... I've got the body parts and the weapons, and I've got the skeleton hierarchy. But that's useless without the angles.

BTW: Did anyone get useable data out of a Xenogears disc image? Or any other Square game?

Darkdevil

  • *
  • Posts: 728
    • View Profile
    • Http://darkdevil177.5u.com
PSX version battle backgrounds
« Reply #16 on: 2004-06-30 20:18:55 »
Quote from: Micky


Now if someone could just help decode the animation data for player and monster models..


Thats the whole problem at the moment, we CANT decode the the data...Hell, I dont even think we can FIND it.  I may be wrong though.

Micky

  • *
  • Posts: 300
    • View Profile
PSX version battle backgrounds
« Reply #17 on: 2004-06-30 21:56:45 »
Quote from: Darkdevil
I dont even think we can FIND it.  I may be wrong though.

Oh, that's easy. There is a lot of data in the battle models that is not covered by the mesh and texture.
But so far I haven't found a system, which suggest that the data is compressed.
Can anyone tell me if the pyramid "monster" from the test battle (ENEMY000.LZS) is meant to be animated?

sfx1999

  • *
  • Posts: 1142
    • View Profile
PSX version battle backgrounds
« Reply #18 on: 2004-06-30 22:53:03 »
Quote from: halkun
Under linux:

NVIDIA has no OpenGL.h lib

for some reason it was trying to include it. I forced it not to.

I get this at compile time

Code: [Select]

halkun@naru:~/lab> gcc stageview.cpp -o stage
stageview.cpp: In function `int load(const std::string&, void**)':
stageview.cpp:62: error: `assert' undeclared (first use this function)
stageview.cpp:62: error: (Each undeclared identifier is reported only once for each function it appears in.)


Of course this is useless without a makefile. I have to include my X11 libs and my GL libs at link time, I'm just seeing of it would even compile first


These are the includes I used. I think you are missing a couple.

Code: [Select]
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>

// STL
#include <string>

// OpenGL
#include <GL/gl.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <GL/glut.h>


Also, when you link it, you will need to use -lgl -lglu -lglut.

Cyberman

  • *
  • Posts: 1572
    • View Profile
PSX version battle backgrounds
« Reply #19 on: 2004-06-30 23:31:23 »
Quote from: Micky
Quote from: Cyberman
Heh.. It's following the pattern of all the files that are on the FF7 disks for the PSX.

It is obviously arranged that way so that it can be fed into the hardware as fast as possible. Which doesn't match the PC hardware, so I arrange it into a vertex array and triangle list. The triangle list isn't the best format, but should do. And I don't have to include a triangle stripper.  :)

You might be better off creating a DList for that instead, which you can rotate seperately. Currently I generate everything but the textures over and over again.  I figured out what I had been doing with the textures (wrong that is).  Because of the way windows does things is the problem.  Essentially OGL was not initialized until I clicked where the data was being displayed (stupid).  None of the textures were valid because of this (dang it).  I have to reorganize it so things are done in the proper order.  How I create the textures is run through the textured triangles and Quads finding the max and mins, then use the palette data to draw on a bitmap that region.  This is done for all the textured objects.  My biggest problem has been detecting transparency in a texture.  Currently I assume color zero is transparent in all paletted textures.

Quote from: Micky

Now if someone could just help decode the animation data for player and monster models... I've got the body parts and the weapons, and I've got the skeleton hierarchy. But that's useless without the angles.

BTW: Did anyone get useable data out of a Xenogears disc image? Or any other Square game?


If you looked VERY carefully at what I listed in those data structures you'll note I have the COMPLETE bone setup for FF7 in there (it's not hard to find LOL).  I found the weapons a while back too.  One needs the animation files to display the complete figure (as you might guess).  I'm sure you read my 'findings' in the FF7 model viewer thread.  The only thing I need now is (drum roll) the animation rotation information for the bones and joints like you.  

I am positive section 2 is VERY important in figuring out the animation I'm just not sure how.

Not Xeno but I have actually gotten somewhere with Ff8 and FF9.

Quote from: Micky

But so far I haven't found a system, which suggest that the data is compressed.
Can anyone tell me if the pyramid "monster" from the test battle (ENEMY000.LZS) is meant to be animated?

As for compressed... It's possible but why compress something twice?  I can do a second decompression on that data and see if anything interesting comes out I suppose.

ENEMY000.LZS
I think it's a bare bones thing, if you get into the debug room you might be able to battle those debug objects and find out.  As far as I know it is just 4 triangles and a quad.  Section 2 is very suspicious here because it still is about the same size as always.

If a model has more parts (see CLOUD.LZS) then section 2 grows. It's size varies depending on the number of sections.

Cyb

Micky

  • *
  • Posts: 300
    • View Profile
PSX version battle backgrounds
« Reply #20 on: 2004-07-01 13:11:01 »
Quote from: Cyberman
As for compressed... It's possible but why compress something twice?  I can do a second decompression on that data and see if anything interesting comes out I suppose.

You are right, applying something like LZS twice doesn't make sense. But the animation data could be in a special animation-compression format, that gets read and decompressed while playing the animation. Similar to the ADPCM compression that you can do to audio data.

Does the fixed version of the bg viewer now work for everybody, or are there still problems? I know the first few stages crash, but from then on every stage I tried worked.

Anakin

  • *
  • Posts: 42
    • View Profile
PSX version battle backgrounds
« Reply #21 on: 2004-07-01 14:44:23 »
still no,
and it doesn't run even in Cygwin
Also I tried to compile (making the changes you suggested) with MinGW and with Cygwin without success
But I didn't find the fixed version

As for the pyramid monster, I believe it was not supposed to be animated, since it most probably derives from a boss -RENO- attack which is called 'Pyramid' and it causes the member of the player team to freeze, and the only way to break it is to attack your affected team member with another

Micky

  • *
  • Posts: 300
    • View Profile
PSX version battle backgrounds
« Reply #22 on: 2004-07-01 15:33:06 »
Quote from: Anakin
still no,
and it doesn't run even in Cygwin
Also I tried to compile (making the changes you suggested) with MinGW and with Cygwin without success
But I didn't find the fixed version

I put the fixes directly into the sourcecode that I posted. Can you show me a stack trace?

Anakin

  • *
  • Posts: 42
    • View Profile
PSX version battle backgrounds
« Reply #23 on: 2004-07-01 15:51:13 »
I used the new source changing only the name of the folder OpenGL to glut
and in Cygwin I get>     stageview.c:7: string No such file or directory
(the same in MinGW)
and if I remove the
Code: [Select]
#include <string>
I get a series of errors starting with: stageview.c:27: parse error before 'namespace'

Micky

  • *
  • Posts: 300
    • View Profile
PSX version battle backgrounds
« Reply #24 on: 2004-07-01 16:27:09 »
Quote from: Anakin
I get a series of errors starting with: stageview.c:27: parse error before 'namespace'

It is a C++ program, rename it to "stageview.cpp". That should make it recognise the "string" include header as well.