Welcome to Spyro the Dragon Forums!

You are not logged in.

#1 Jul 31, 2015 3:31 PM

Sheep
Member
Award: Skateboard Contest Winner
From: Norway
Registered: Jan 24, 2008
Posts: 983
Gems: 0
Birthday: 20 January
Age: 30 years old
Gender: Male
Website

Collision data hacking

  1: xxxx xxxx]    | 8 bits for the least significant part of the absolute x coordinate
  2: [ww][xx xxxx  | 2 bits, and then 6 bits for the most significant part of absolute x coordinate
  3: [xxxx xxxx]   | 8 bits for the first relative x coordinate
  4: [xxxx xxxx]   | 8 bits for the second relative x coordinate

  5: yyyy yyyy]    | 8 bits for the least significant part of the absolute y coordinate
  6: [ww][yy yyyy  | 2 bits, and then 6 bits for the most significant part of absolute y coordinate
  7: [yyyy yyyy]   | 8 bits for the first relative y coordinate
  8: [yyyy yyyy]   | 8 bits for the second relative y coordinate

  9: zzzz zzzz]    | 8 bits for the least significant part of the absolute z coordinate
 10: [tt][zz zzzz  | 2 bits for terrain type, and then 6 bits for the most significant part of absolute z coordinate
 11: [zzzz zzzz]   | 8 bits for the first relative z coordinate
 12: [zzzz zzzz]   | 8 bits for the second relative z coordinate

Offline

#2 Jul 31, 2015 9:00 PM

Gekoncze
Baby Dragon
Award: Speedway Contest Winner Final
From: Czech Republic
Registered: May 16, 2009
Posts: 5,389
Gems: 145
Age: 30 years old
Gender: Male

Re: Collision data hacking

Wow o.o this is incredible. I don't think I would have the patience to research it so deeply.

Offline

#3 Aug 02, 2015 7:42 AM

CrystalFissure
Member
From: Adelaide
Registered: May 16, 2015
Posts: 77
Gems: 0
Gender: Male
Website

Re: Collision data hacking

This is insane. Thanks a heap for showing this. I'll send it to Kly_Men_COmpany and see what he thinks.

Offline

#4 Aug 02, 2015 9:28 AM

Sheep
Member
Award: Skateboard Contest Winner
From: Norway
Registered: Jan 24, 2008
Posts: 983
Gems: 0
Birthday: 20 January
Age: 30 years old
Gender: Male
Website

Re: Collision data hacking

Some new bits...

Directly following the collision model, there is a rather long list of byte values that also decide the type or material of triangles. Here it does not seem to be about 'not water'/'water', but different kinds of solid surfaces. First there are a lot of 191-s, which applies to the bridge triangles and makes it make that creaky wooden sound when you walk on it. Then there are lots of 193-s, which is what makes Spyro recognize the lava as lava.

I could change the bridge triangles into lava triangles and the other way around, but most of the triangles in the level don't seem to have values in this list of bytes, so I couldn't change their material. I initially thought there was a value for each triangle, but changing some of the later values made the sky disappear. How it is decided which triangles have values and which don't, I don't know.

Also, most special materials, like lava, seem to only be solid when they're within some degree of being horizontal. As walls, they pretty much don't exist.

Last edited by Sheep (Aug 02, 2015 9:39 AM)

Offline

#5 Aug 03, 2015 3:23 PM

aleksusklim
Member
From: Uzbekistan
Registered: Aug 03, 2015
Posts: 12
Gems: 0
Birthday: 30 May
Age: 31 years old
Gender: Male
Website

Re: Collision data hacking

Offline

#6 Aug 03, 2015 4:52 PM

Sheep
Member
Award: Skateboard Contest Winner
From: Norway
Registered: Jan 24, 2008
Posts: 983
Gems: 0
Birthday: 20 January
Age: 30 years old
Gender: Male
Website

Re: Collision data hacking

Offline

#7 Aug 03, 2015 9:33 PM

aleksusklim
Member
From: Uzbekistan
Registered: Aug 03, 2015
Posts: 12
Gems: 0
Birthday: 30 May
Age: 31 years old
Gender: Male
Website

Re: Collision data hacking

var wordX,wordY,wordZ,vertX1,vertX2,vertX3,vertY1,vertY2,vertY3,vertZ1,vertZ2,vertZ3,terrT,normX,normY,normZ,normL,col1,col2,col3;

wordX=file_bin_read_byte(buffer)|(file_bin_read_byte(buffer)<<8)|(file_bin_read_byte(buffer)<<16)|(file_bin_read_byte(buffer)<<24);
wordY=file_bin_read_byte(buffer)|(file_bin_read_byte(buffer)<<8)|(file_bin_read_byte(buffer)<<16)|(file_bin_read_byte(buffer)<<24);
wordZ=file_bin_read_byte(buffer)|(file_bin_read_byte(buffer)<<8)|(file_bin_read_byte(buffer)<<16)|(file_bin_read_byte(buffer)<<24);

vertX1=wordX&((1<<14)-1);
vertY1=wordY&((1<<14)-1);

vertX2=(wordX>>14)&((1<<9)-1);
vertY2=(wordY>>14)&((1<<9)-1);

vertX3=(wordX>>(14+9))&((1<<9)-1);
vertY3=(wordY>>(14+9))&((1<<9)-1);

vertX2-=(1<<9)*((vertX2&(1<<8))>0);
vertX3-=(1<<9)*((vertX3&(1<<8))>0);
vertY2-=(1<<9)*((vertY2&(1<<8))>0);
vertY3-=(1<<9)*((vertY3&(1<<8))>0);

vertZ1=wordZ&((1<<14)-1);
terrT=(wordZ>>14)&((1<<2)-1);

vertZ2=(wordZ>>(14+2))&((1<<8)-1);
vertZ3=(wordZ>>(14+2+8))&((1<<8)-1);

normX=vertZ2*vertY3-vertY2*vertZ3;
normY=vertX2*vertZ3-vertZ2*vertX3;
normZ=vertY2*vertX3-vertX2*vertY3;
normL=sqrt(normX*normX+normY*normY+normZ*normZ);
normX/=normL;
normY/=normL;
normZ/=normL;

vertX2+=vertX1;
vertX3+=vertX1;
vertY2+=vertY1;
vertY3+=vertY1;
vertZ2+=vertZ1;
vertZ3+=vertZ1;

if terrT&1 {
col1=c_blue;
col2=c_aqua;
col3=c_fuchsia;
}else{
col1=c_lime;
col2=c_yellow;
col3=c_red;
}

d3d_model_vertex_normal_color(collmodel,vertY1,vertX1,vertZ1,normY,normX,normZ,col1,1);
d3d_model_vertex_normal_color(collmodel,vertY2,vertX2,vertZ2,normY,normX,normZ,col2,1);
d3d_model_vertex_normal_color(collmodel,vertY3,vertX3,vertZ3,normY,normX,normZ,col3,1);

Offline

#8 Aug 03, 2015 10:07 PM

Sheep
Member
Award: Skateboard Contest Winner
From: Norway
Registered: Jan 24, 2008
Posts: 983
Gems: 0
Birthday: 20 January
Age: 30 years old
Gender: Male
Website

Re: Collision data hacking

Last edited by Sheep (Aug 04, 2015 10:59 AM)

Offline

#9 Aug 04, 2015 9:50 PM

aleksusklim
Member
From: Uzbekistan
Registered: Aug 03, 2015
Posts: 12
Gems: 0
Birthday: 30 May
Age: 31 years old
Gender: Male
Website

Re: Collision data hacking

Language: Delphi7.
Example usage in batch: (file "Spyro3_WAD.bat")

@echo off
if _%1_ == __ goto :eof
cd /D %~dp0
set name=.\Spyro3\
mkdir %name%>nul
for /L %%i in (98,2,170) do (
for /L %%j in (1,1,5) do (
echo %%i %%j
CollisionCracker.exe %1 %%i %%j %name%Coll_%%i_%%j 
)
)
pause

____________________
program CollisionCracker;
{$APPTYPE CONSOLE}
uses Classes,SysUtils;

// <Color output console functions>
    function GetStdHandle(std:integer):integer;stdcall;external'kernel32.dll';
    function SetConsoleTextAttribute(handle,color:integer):boolean;stdcall;external'kernel32.dll';
    function GetConsoleScreenBufferInfo(handle:integer;csbi:Pointer):boolean;stdcall;external'kernel32.dll';
    function SetConsoleScreenBufferInfo(handle:integer;csbi:Pointer):boolean;stdcall;external'kernel32.dll';
    type _csbi=record c1,c2:integer;color:word;c3,c4,c5,c6:integer;end;var def:Word;con:integer;csbi:_csbi;
    procedure InitCol();begin con:=GetStdHandle(-11);GetConsoleScreenBufferInfo(con,@csbi);def:=csbi.color;end;
    procedure WriteCol(str:string;col:Word);begin SetConsoleTextAttribute(con,col);Writeln(str);SetConsoleTextAttribute(con,def);end;
    const cOK:Word=10;cInfo:Word=14;cErr:Word=12;
// </>

var
i,wad,sub:integer;
pos,size,pos_,size_:Cardinal;
stream:TFileStream;
tgt:string;
parts:array[1..6]of Cardinal;

procedure jump(cnt:Cardinal);
var i:integer;
off:Cardinal;
begin
for i:=1 to cnt do begin
stream.ReadBuffer(off,4);
stream.Seek(off-4,soFromCurrent);
if stream.Position>size then Abort;
end;
end;

procedure move(off:Integer);
begin
stream.Seek(off,soFromCurrent);
if stream.Position>size then Abort;
end;

procedure subfile(num:Cardinal);
var from,off,cnt:Cardinal;
begin
from:=stream.Position;
stream.Seek((num-1)*8,soFromCurrent);
stream.ReadBuffer(off,4);
stream.ReadBuffer(cnt,4);
if (off=0)or(cnt=0) then begin
WriteCol('Empty',cInfo);
Halt(0);
end;
if pos+off+cnt>size then Abort;
stream.Seek(from+off,soFromBeginning);
size:=from+off+cnt;
end;

procedure save2file(cnt:Cardinal;name:string);
var from:Cardinal;
save:TFileStream;
begin
if cnt=0 then exit;
if cnt>1024*1024*10 then Abort;
from:=stream.Position;
save:=TFileStream.Create(name,fmCreate);
save.CopyFrom(stream,cnt);
save.Free;
stream.Seek(from,soFromBeginning);
end;

function read4():cardinal;
begin
stream.ReadBuffer(Result,4);
if stream.Position>size then Abort;
end;

begin
if ParamCount<>4 then begin
Writeln('');
Writeln('CollisionCracker v1.0, Kly_Men_COmpany!');
Writeln('Usage: "input.wad" (subfile) (sublevel) "output"');
Writeln('"input.wad" = name of source WAD.WAD or an already extracted subfile.');
Writeln('(subfile) = 0 for WAD.WAD or number of subfile to take.');
Writeln('(sublevel) =0 for Spyro1, =-1 for Spyro2 and >=1 for Spyro3 sublevels.');
Writeln('"output" = main name to save resulst, also will be "output.1" .. "output.5"');
Writeln('');
exit;
end;

try
stream:=TFileStream.Create(ParamStr(1),fmOpenRead or fmShareDenyNone);
except Writeln('Open file error!');
exit;
end;

try
wad:=StrToInt64(ParamStr(2));
sub:=StrToInt64(ParamStr(3));
except Writeln('Wrong integer!');
exit;
end;

InitCol();
tgt:=ParamStr(4);
size:=stream.Size;

if wad>0 then try
subfile(wad);
except Writeln('WAD seeking error!');
exit;
end;

pos_:=stream.Position;
size_:=size;

try
if sub>1 then subfile(5+(sub-2)*2) else subfile(2);
except Writeln('SUB seeking error!');
exit;
end;

try
jump(1);
if sub>1 then move(384);
jump(3);
if sub>1 then jump(1);
if sub<0 then jump(2);
if (sub=1)or(sub=-1) then move(12);
except Writeln('SUB-SUB seeking error!');
exit;
end;

try
parts[6]:=read4()-4;
if parts[6]=0 then begin
stream.Seek(pos_,soFromBeginning);
size:=size_;
subfile(3);
move(4);
jump(2);
move(4);
parts[6]:=read4()-4;
end;
pos:=stream.Position;
save2file(parts[6],tgt);
if sub=0 then move(8) else move(12);
for i:=1 to 5 do parts[i]:=read4();
for i:=1 to 5 do begin
stream.Seek(pos+parts[i],soFromBeginning);
save2file(parts[i+1]-parts[i],tgt+'.'+IntToStr(i));
end;
except WriteCol('ERROR',cErr);
exit;
end;

WriteCol('Done!',cOK);
stream.Free;
end.

Last edited by aleksusklim (Aug 06, 2015 8:55 PM)

Offline

#10 Aug 06, 2015 10:17 PM

Sheep
Member
Award: Skateboard Contest Winner
From: Norway
Registered: Jan 24, 2008
Posts: 983
Gems: 0
Birthday: 20 January
Age: 30 years old
Gender: Male
Website

Re: Collision data hacking

Last edited by Sheep (Aug 07, 2015 11:41 PM)

Offline

#11 Aug 08, 2015 3:12 PM

aleksusklim
Member
From: Uzbekistan
Registered: Aug 03, 2015
Posts: 12
Gems: 0
Birthday: 30 May
Age: 31 years old
Gender: Male
Website

Re: Collision data hacking

Offline

#12 Aug 08, 2015 4:12 PM

Sheep
Member
Award: Skateboard Contest Winner
From: Norway
Registered: Jan 24, 2008
Posts: 983
Gems: 0
Birthday: 20 January
Age: 30 years old
Gender: Male
Website

Re: Collision data hacking

Offline

#13 Aug 08, 2015 6:06 PM

aleksusklim
Member
From: Uzbekistan
Registered: Aug 03, 2015
Posts: 12
Gems: 0
Birthday: 30 May
Age: 31 years old
Gender: Male
Website

Re: Collision data hacking

Offline

#14 Aug 08, 2015 6:47 PM

Sheep
Member
Award: Skateboard Contest Winner
From: Norway
Registered: Jan 24, 2008
Posts: 983
Gems: 0
Birthday: 20 January
Age: 30 years old
Gender: Male
Website

Re: Collision data hacking

Last edited by Sheep (Aug 09, 2015 8:01 AM)

Offline

#15 Aug 09, 2015 7:35 AM

CrystalFissure
Member
From: Adelaide
Registered: May 16, 2015
Posts: 77
Gems: 0
Gender: Male
Website

Re: Collision data hacking

Last edited by CrystalFissure (Aug 09, 2015 7:38 AM)

Offline

#16 Aug 12, 2015 10:49 PM

aleksusklim
Member
From: Uzbekistan
Registered: Aug 03, 2015
Posts: 12
Gems: 0
Birthday: 30 May
Age: 31 years old
Gender: Male
Website

Re: Collision data hacking

#include <bladeps.h>
u_char ot[2000];
void copy(char*from,char*to){
while(*from)*(to--)=*(from++);
}
void code(char*a0,char*a1,char*a2,char*a3){
copy(a0,(char*)0x8000000f);
copy(a1,(char*)0x801fffff);
copy(a2,(char*)0x1f80000f);
copy(a3,(char*)0x1f8003ff);
while(1);;
}
void main (void){
GsInitGraphQuick (320, 240);
GsSetWorkBase(&ot[0]);
GsSortClear(0,255,0);
GsDrawOT ((u_long *) &ot[0]);
code("!MARniaMfOtratS!","!!MARniaMfOdnE!!","!hctarcSfOtratS!","!!hctarcSfOdnE!!");
}
//   "!StartOfMainRAM!","!!EndOfMainRAM!!","!StartOfScratch!","!!EndOfScratch!!"

Offline

#17 Aug 13, 2015 9:41 AM

Sheep
Member
Award: Skateboard Contest Winner
From: Norway
Registered: Jan 24, 2008
Posts: 983
Gems: 0
Birthday: 20 January
Age: 30 years old
Gender: Male
Website

Re: Collision data hacking

Wow, this is really way above my experience and skill level!! I can understand it took you a few days. Also, clever way of finding the addresses!

I ran the test, using ePSXe 1.7.0 and got:
0x0094C020
9748512

The screen flickering was really painful, though, so I suggest replacing it with something else if more people need to go through it tongue

Offline

#18 Aug 14, 2015 7:38 PM

aleksusklim
Member
From: Uzbekistan
Registered: Aug 03, 2015
Posts: 12
Gems: 0
Birthday: 30 May
Age: 31 years old
Gender: Male
Website

Re: Collision data hacking

// for PS1 SDK

void copy(char*from,char*to){
while(*from)*(to--)=*(from++);
}
void code(char*a0,char*a1,char*a2,char*a3){
copy(a0,(char*)0x8000000f);
copy(a1,(char*)0x801fffff);
copy(a2,(char*)0x1f80000f);
copy(a3,(char*)0x1f8003ff);
}

#include <r3000.h>
#include <asm.h>
#include <libapi.h>
#include <sys/file.h>
#include <sys/types.h>
#include <libgte.h>
#include <libgpu.h>
#include <libetc.h>

typedef struct {
 DRAWENV draw;
 DISPENV disp;
} DB;
DB db[2];
DB *cdb;
int i;
main()
{
	ResetGraph(0);
	SetDefDrawEnv(&db[0].draw, 0,   0, 320, 240);
	SetDefDispEnv(&db[0].disp, 0, 240, 320, 240);
	SetDefDrawEnv(&db[1].draw, 0, 240, 320, 240);
	SetDefDispEnv(&db[1].disp, 0,   0, 320, 240);

code("!MARniaMfOtratS!","!!MARniaMfOdnE!!","!hctarcSfOtratS!","!!hctarcSfOdnE!!");
//   "!StartOfMainRAM!","!!EndOfMainRAM!!","!StartOfScratch!","!!EndOfScratch!!"

	db[0].draw.isbg = 1;
	setRGB0(&db[0].draw, 0, 255, 0);
	db[1].draw.isbg = 1;
	setRGB0(&db[1].draw, 0, 0, 255);
	SetDispMask(1);
	DrawSync(0);
	VSync(0);
	while(1) {
		cdb = (cdb==db)?db+1:db;
		PutDrawEnv(&cdb->draw);
		PutDispEnv(&cdb->disp);
		DrawSync(0);
		for(i=0;i<60;i++)VSync(0);
	}
}

Last edited by aleksusklim (Aug 14, 2015 7:42 PM)

Offline

#19 Aug 16, 2015 1:06 AM

spyroyo
Member
Registered: Nov 24, 2013
Posts: 16
Gems: 0

Re: Collision data hacking

// for PS1 SDK

void copy(char*from,char*to){
while(*from)*(to--)=*(from++);
}
void code(char*a0,char*a1,char*a2,char*a3){
copy(a0,(char*)0x8000000f);
copy(a1,(char*)0x801fffff);
copy(a2,(char*)0x1f80000f);
copy(a3,(char*)0x1f8003ff);
}

#include <r3000.h>
#include <asm.h>
#include <libapi.h>
#include <sys/file.h>
#include <sys/types.h>
#include <libgte.h>
#include <libgpu.h>
#include <libetc.h>

typedef struct {
 DRAWENV draw;
 DISPENV disp;
} DB;
DB db[2];
DB *cdb;
int i;
main()
{
	ResetGraph(0);
	SetDefDrawEnv(&db[0].draw, 0,   0, 320, 240);
	SetDefDispEnv(&db[0].disp, 0, 240, 320, 240);
	SetDefDrawEnv(&db[1].draw, 0, 240, 320, 240);
	SetDefDispEnv(&db[1].disp, 0,   0, 320, 240);

code("!MARniaMfOtratS!","!!MARniaMfOdnE!!","!hctarcSfOtratS!","!!hctarcSfOdnE!!");
//   "!StartOfMainRAM!","!!EndOfMainRAM!!","!StartOfScratch!","!!EndOfScratch!!"

	db[0].draw.isbg = 1;
	setRGB0(&db[0].draw, 0, 255, 0);
	db[1].draw.isbg = 1;
	setRGB0(&db[1].draw, 0, 0, 255);
	SetDispMask(1);
	DrawSync(0);
	VSync(0);
	while(1) {
		cdb = (cdb==db)?db+1:db;
		PutDrawEnv(&cdb->draw);
		PutDispEnv(&cdb->disp);
		DrawSync(0);
		for(i=0;i<60;i++)VSync(0);
	}
}

Offline

#20 Aug 16, 2015 11:23 AM

aleksusklim
Member
From: Uzbekistan
Registered: Aug 03, 2015
Posts: 12
Gems: 0
Birthday: 30 May
Age: 31 years old
Gender: Male
Website

Re: Collision data hacking

Offline

#21 Aug 16, 2015 3:13 PM

Sheep
Member
Award: Skateboard Contest Winner
From: Norway
Registered: Jan 24, 2008
Posts: 983
Gems: 0
Birthday: 20 January
Age: 30 years old
Gender: Male
Website

Re: Collision data hacking

Finally got some time today to test out your hack, aleksusklim... Wow, this is amazing big_smile
Like... really, really amazing! So fun to stop the time, kill enemies, and then see them die all at once. Spyro suddenly got super powers!
Edit:
Playing some in Sunny Villa... apart from the fact that they don't do damage, the iron bar gates turn into what would have been deadly traps. Slowly lift, *bam* fall down, slowly lift, *bam* fall down...

Edit:
Skateboarding: I don't know how it happened, and I'm not able to replicate it, but somehow the Skateboard got more disconnected from Spyro than usual, so it looks like Spyro casually slips away from it while in the air, and then impressively lands back onto it again. Looks awesome! (although while on the ground, he sat at the back end of the Skateboard, rather than on the middle)

Last edited by Sheep (Aug 16, 2015 3:34 PM)

Offline

#22 Aug 16, 2015 9:57 PM

aleksusklim
Member
From: Uzbekistan
Registered: Aug 03, 2015
Posts: 12
Gems: 0
Birthday: 30 May
Age: 31 years old
Gender: Male
Website

Re: Collision data hacking

Offline

#23 Aug 19, 2015 5:24 PM

Sheep
Member
Award: Skateboard Contest Winner
From: Norway
Registered: Jan 24, 2008
Posts: 983
Gems: 0
Birthday: 20 January
Age: 30 years old
Gender: Male
Website

Re: Collision data hacking

Offline

#24 Aug 19, 2015 9:16 PM

aleksusklim
Member
From: Uzbekistan
Registered: Aug 03, 2015
Posts: 12
Gems: 0
Birthday: 30 May
Age: 31 years old
Gender: Male
Website

Re: Collision data hacking

buffer=NAME+'.1';
buffer=file_bin_open(buffer,0);
var zz,yy,xx,Z,Y,X,FF,Lz,Ly,Lx,Lv,mm;
mm=256;
FF=$FFFF;
Lz=0;
Z=file_bin_read_byte(buffer)|(file_bin_read_byte(buffer)<<8);
for(zz=1;zz<=Z;zz+=1){
file_bin_seek(buffer,Lz+zz*2);
Ly=file_bin_read_byte(buffer)|(file_bin_read_byte(buffer)<<8);
if Ly=FF then continue;
file_bin_seek(buffer,Ly);
Y=file_bin_read_byte(buffer)|(file_bin_read_byte(buffer)<<8);
for(yy=1;yy<=Y;yy+=1){
file_bin_seek(buffer,Ly+yy*2);
Lx=file_bin_read_byte(buffer)|(file_bin_read_byte(buffer)<<8);
if Lx=FF then continue;
file_bin_seek(buffer,Lx);
X=file_bin_read_byte(buffer)|(file_bin_read_byte(buffer)<<8);
for(xx=1;xx<=X;xx+=1){
file_bin_seek(buffer,Lx+xx*2);
Lv=file_bin_read_byte(buffer)|(file_bin_read_byte(buffer)<<8);
if Lv=FF then continue;
d3d_model_block(myboxcollmod,(yy-1)*mm,(xx-1)*mm,(zz-1)*mm,yy*mm,xx*mm,zz*mm,1,1);
}}}
file_bin_close(buffer);

Offline

#25 Aug 20, 2015 3:40 AM

CrystalFissure
Member
From: Adelaide
Registered: May 16, 2015
Posts: 77
Gems: 0
Gender: Male
Website

Re: Collision data hacking

Offline

Board footer

Powered by FluxBB