Maybe someone will wright some tutorials or make some videos on how to use them.
OLD Stuff Below now!!!
-------------------------------------------------------------- NEW NEWS 7/26/2013
Added links to Animation tools and maxscripts for importing generations models into Max.
NEW NEWS 5/1/2012
Kay Guys. Update: Sorry I haven't kept up with this post to make front page updates. ( been busy renovating my house)
That hasn't slown down many of you from submitting stuff.
I'm here to inform everybody that Generations has been cracked wider than Humpty Dumpty and custom levels are an ongoing event!
(wish I could get you guys to PM me links to important recourses, tools and other miscellaneous things related to the topic.
so that I can post them here on the front page for easy grabs)
-----------------------------------old news------------------------------------------
I'll start by sharing All of the Ripped Texture graphics recourses from the demo.
(If its in the game than it will be found in these packs.
Title screen, backgrounds, character skins, fonts, loading screen and level textures among other very rare finds.
( like new never before seen screen shots)
DaGuAr from sonicreikai.com Assisted in setting me up with the ripping strategies.
all credit goes to him for that.
I just ripped and Batch converted them in photoshop.
Lets see what everyone will bring to the thread,
Any Recourses are welcome.
Edit:
Watch for lots of incoming shit for full game
1. Extract AAX files from CPKs/CSBs
b) convert AAX files to ADX using AAX2ADX
III. convert ADX files to wav
Vier. Convert wav files to MP3/OGG/FLAC/Whatever you.
Import Model to Max Maxscript:
1:Copy past the code below to a new notepad.
2: change the extention to .MS
3: Drag and drop the maxscript to a max viewport.
4: Enjoy!
Spoiler
clearlistener()
mdlScale = 1.0
if (heapSize < 20000000) then
heapSize = 200000000 -- allow ~ 40 MB instead of just 7.5 MB. Prevents "Runtime Error: Out of scripter memory"
fn PrintOffset Var =
(
local Var = Var
print ("This is the offset 0x" + (bit.intAsHex Var) as string)
Var
)
y = 180
PrintOffset y
x = 200
print ("This is the number 0x" + (bit.intAsHex x) as string)
fn floatSwap2 f =
(
I = bit.floatAsInt f
h = bit.intashex I
while h.count < 8 do h = "0" + h
s = (substring h 7 2) + (substring h 5 2) + (substring h 3 2) + (substring h 1 2)
bit.intAsFloat (bit.hexasint s)
)
fn ReadBEHalfFloat Fstream = (
local BH = readByte Fstream #unsigned
local BL = readByte Fstream #unsigned
local N = BH*256 + BL
local S = floor((mod N 65536) / 32768)
local Ef = floor((mod N 32768) / 1024)
local M = mod N 1024
if (Ef==0)AND(M==0) then return ( (-1.0)^S * 0.0 )
if (Ef==0)AND(M!=0) then return ( (-1.0)^S * 2.0^-14 * (M / 2.0^10) )
if (Ef>0)AND(Ef<31) then return ( (-1.0)^S * 2.0^(Ef-15) * (1 + M/2.0^10) )
if (Ef==31)AND(M==0) then return ( (-1.0)^S * 1/0.0 )
if (Ef==31)AND(M!=0) then return 0 --hack-- should be #inf
)--end fn ReadBEHalfFloat
fn ReadBElong fstream = (
long = readlong fstream
long = bit.swapBytes long 1 4
long = bit.swapBytes long 2 3
return long
)
fn ImportTextureGenerations mm index texfilename filepath = (
matdata = fopen (filepath + texfilename + ".material") "rb"
fname = GetOpenFileName caption:"Open Sonic Model File" types:"Sonic Model File(*.model)|*.model"
if (fname!=undefined) and ((doesFileExist fname)==true) then (
f = fopen fname "rb" --open file in read only format
filepath = GetFilenamePath fname
ExtraMeshAreaCount = MeshDataOffset / 4
for I = 1 to ExtraMeshAreaCount Do (
append Extra_Mesh_Area (ReadBELong f + 0x18)
)
BeforeExtra = ftell f
ExtraMeshCount = 0
Extra_Meshes = #()
for I = 1 to ExtraMeshAreaCount Do (
fseek f Extra_Mesh_Area[I] #seek_set
ThisAreaExtra = (ReadBELong f)
ExtraMeshCount = ExtraMeshCount + ThisAreaExtra
ThisAreaHead = ReadBELong f + 0x18
for j = 1 To ThisAreaExtra Do (
append Extra_Meshes (ThisAreaHead + (j-1) * 4)
)
)
fseek f BeforeExtra #seek_set
MeshCount = ReadBElong f
UnkCount2 = ReadBElong f
AddMeshCount = ReadBElong f
AddMeshBegin =ReadBElong f + 0x18
ExtraMeshCount = ExtraMeshCount + AddMeshCount
for I = 1 to AddMeshCount Do (
append Extra_Meshes (AddMeshBegin + (I-1) * 4)
)
AlphaMeshCount = ReadBElong f
AlphaMeshBegin = ReadBElong f + 0x18
ExtraMeshCount = ExtraMeshCount + AlphaMeshCount
for I = 1 to AlphaMeshCount Do (
append Extra_Meshes (AlphaMeshBegin + (I-1) * 4)
)
fseek f BoneTableOffset#seek_set
struct BoneOffset (
BoneTOffset
)
Bone_Offset_array = #()
for I = 1 to BoneCount Do (
BoneTOffset = ReadBElong f + 0x18
append Bone_Offset_array (BoneOffset BoneTOffset:BoneTOffset)
)
print Bone_Offset_array
Bone_Data_array = #()
BoneID = -1
for k in Bone_Offset_array Do (
fseek f k.BoneTOffset#seek_set
BoneID += 1
BoneParentID = ReadBElong f
BoneNameOffset = ReadBElong f
BoneName = readstring f
append Bone_Data_array ( BoneDData BoneID:BoneID BoneNameOffset:BoneNameOffset BoneName:BoneName BoneParentID:BoneParentID )
)
print Bone_Data_array
fseek f BoneTableOffset2 #seek_set
--if CinematicMesh == 1 Do (
--fseek f 0x1#seek_cur
--)
BNArr = #()
for I = 1 to MorphFaceSetsCount Do
(
FaceSetStart = ReadBElong f + 0x18
append MorphFaceSets FaceSetStart
)
for I = 1 to MorphFaceSetsCount Do
(
fseek f MorphFaceSets[I] #seek_set
PrintOffset (ftell f)
TextureOffset = ReadBElong f + 0x18
MorphFaceCount = ReadBElong f
MorphFaceOffset = ReadBElong f + 0x18
--ReadBElong f
--MorphVertSize = ReadBElong f
--MorphDataTable = ReadBElong f + 0x18
if ( I == 1) then
(
BackJump = ftell f
fseek f TextureOffset #seek_set
Texture = readstring f
fseek f BackJump #seek_set
fseek f 0x10 #seek_cur
boneidcount = ReadBElong f
boneidstart = (ReadBElong f) + 0x18
fseek f boneidstart #seek_set
for j=1 to boneidcount do
(
addboneid = (ReadByte f #unsigned)
append Bone_ids1 (addboneid + 1)
)
)
--Read data table
/*
CoordinatesFound = false
UVDataFound = false
BoneIndicesFound = false
BoneWeightsFound = false
DataTableEnd = false
fseek f MorphDataTable #seek_set
PrintOffset(MorphDataTable)
while(not DataTableEnd) do (
DataOffset = ReadBElong f
DataType = ReadBElong f
EntryType = ReadBEword f
SubId = ReadByte f
Padding = ReadByte f
if(DataType != -1) then (
append DataTable (VertexDeclarationEntry DataOffset: DataOffset DataType: DataType EntryType: EntryType SubId: SubId)
if(EntryType == 0) then CoordinatesFound = true
if(EntryType == 1) then BoneWeightsFound = true
if(EntryType == 2) then BoneIndicesFound = true
if(EntryType == 5) then UVDataFound = true
) else (
DataTableEnd = true
)
)
if((not CoordinatesFound) or (not BoneWeightsFound) or (not BoneIndicesFound) or (not UVDataFound)) then (
throw "NOOOOO!"
)*/
fseek f MorphFaceOffset#seek_set
StartDirection = 1
f1 = (ReadBEword f) + 1
f2 = (ReadBEword f) + 1
FaceDirection = StartDirection
Do (
f3 = (ReadBEword f)
if (f3==0xFFFF) then (
f1 = (ReadBEword f) + 1
f2 = (ReadBEword f) + 1
FaceDirection = StartDirection
) else (
f3 += 1
FaceDirection *= -1
if (f1!=f2)AND(f2!=f3)AND(f3!=f1) then (
if FaceDirection > 0 then append Morph_Face_array [f1,f2,f3]
else append Morph_Face_array [f1,f3,f2]
)
f1 = f2
f2 = f3
)
) while ((ftell f) != (MorphFaceOffset + (MorphFaceCount * 2)))
)
fseek f MorphTableEnd #seek_set
Vert_array1 = #() --define arrays for verts, normals, UV and Faces
--Normal_array1 = #()
UV_array1 = #()
Weight_array1 = #()
for k = 1 to MorphVertCount Do (
--Ignoring data table for speed reasons!
vx = ReadBEfloat f --read xyz coordinates
vy = ReadBEfloat f
vz = ReadBEfloat f
fseek f 0x24#seek_cur
tu = ReadBEFloat f --read UV float value
tv = ReadBEFloat f * -1
fseek f 0x28#seek_cur
if(bone1 != 0xFF) then
maxweight = maxweight + weight1
if(bone2 != 0xFF) then
maxweight = maxweight + weight2
if(bone3 != 0xFF) then
maxweight = maxweight + weight3
if(bone4 != 0xFF) then
maxweight = maxweight + weight4
if(maxweight != 0) then
(
mxw = 255.0
if(bone1 != 0xFF) then
(
w1 = weight1 as float
append w.boneids (Bone_ids1[bone1+1])
append w.weights (w1 / mxw)
)
if(bone2 != 0xFF) then
(
w2 = weight2 as float
append w.boneids (Bone_ids1[bone2+1])
append w.weights (w2 / mxw)
)
if(bone3 != 0xFF) then
(
w3 = weight3 as float
append w.boneids (Bone_ids1[bone3+1])
append w.weights (w3 / mxw)
)
if(bone4 != 0xFF) then
(
w4 = weight4 as float
append w.boneids (Bone_ids1[bone4+1])
append w.weights (w4 / mxw)
)
)
append Vert_array1 [vx*mdlScale,(-1)*vz*mdlScale,vy*mdlScale]
append UV_array1 [tu,tv,0] --save UVs to UV_array
append Weight_array1 w
)
msh = mesh vertices:Vert_array1 faces:Morph_Face_array --build mesh
msh.numTVerts = UV_array1.count
buildTVFaces msh
ImportTextureMesh msh Texture filepath
msh.name = "Mouth"
for j = 1 to UV_array1.count do setTVert msh j UV_array1[j]
for j = 1 to Morph_Face_array.count do setTVFace msh j Morph_Face_array[j]
--for j = 1 to Normal_array1.count do setNormal msh j Normal_array1[j]
select $Mouth
MorphMod = morpher ()
addModifier $Mouth MorphMod
$Mouth.morpher.Autoload_of_targets = 1
--$Mouth.parent = $Neck
fseek f MorphTableStart#seek_set
for I = 1 to MorphCount Do (
append MorphArr (ReadBElong f + 0x18)
)
for I = 1 to MorphCount Do (
append MorphArr2 (ReadBElong f + 0x18)
)
for I = 1 to MorphCount Do (
fseek f MorphArr[I]#seek_set
MorphName = readstring f
fseek f MorphArr2[I]#seek_set
Morph_Vert_array = #()
Morph_UV_array = #()
--Morph_Normal_array = #()
for k = 1 to MorphVertCount Do (
vx = ((ReadBEfloat f) ) + Vert_array1[k].x / mdlScale
vy = ((ReadBEfloat f) ) + Vert_array1[k].z / mdlScale
vz = ((ReadBEfloat f) ) + (-1) * Vert_array1[k].y / mdlScale
append Morph_Vert_array [vx * mdlScale,-vz * mdlScale,vy * mdlScale]
)
msh = mesh vertices:Morph_Vert_array faces:Morph_Face_array --build mesh
msh.numTVerts = UV_array1.count
buildTVFaces msh
msh.name = MorphName
for j = 1 to UV_array1.count do setTVert msh j UV_array1[j]
for j = 1 to Morph_Face_array.count do setTVFace msh j Morph_Face_array[j]
--for j = 1 to Morph_Normal_array.count do setNormal msh j Morph_Normal_array[j]
append Morph_Name_array msh
)
max modify mode
select $mouth
skinMod = skin ()
addModifier $mouth skinMod
for I = 1 to BNArr.count do
(
maxbone = getnodebyname BNArr[I].name
if I != BNArr.count then
skinOps.addBone skinMod maxbone 0
else
skinOps.addBone skinMod maxbone 1
)
modPanel.setCurrentObject skinMod
for I = 1 to Weight_array1.count do
(
w = Weight_array1[I]
bi = #() --bone index array
wv = #() --weight value array
for j = 1 to w.boneids.count do
(
boneid = w.boneids[j]
weight = w.weights[j]
append bi boneid
append wv weight
)
offsetstart = (ReadBElong f) + 0x18
tablestart = ftell f
fseek f offsetstart#seek_set
PrintOffset (ftell f)
TextureOffset = ReadBElong f + 0x18
BackJump = ftell f
fseek f TextureOffset #seek_set
Texture = readstring f
--print (Texture)
fseek f BackJump #seek_set
FaceCount = ReadBElong f
FaceStart = ReadBElong f + 0x18
VertCount = ReadBElong f
VertSize = ReadBElong f
VertStart = ReadBElong f + 0x18
DataTableStart = ReadBElong f + 0x18
SecBoneCount = ReadBElong f
SecBoneIDs = (ReadBElong f) + 0x18
BackJump = ftell f
fseek f SecBoneIDs #seek_set
for I = 1 to SecBoneCount do
(
addboneid = (ReadByte f #unsigned)
append BoneID_array (addboneid + 1)
)
fseek f BackJump #seek_set
Count10 = ReadBElong f
Count11 = ReadBElong f
FaceStart = ftell f
VerStart = (FaceCount * 2) + FaceStart
--Read data table
BackJump = ftell f
CoordinatesFound = false
UVDataFound = false
BoneIndicesFound = false
BoneWeightsFound = false
DataTableEnd = false
DataTable = #()
fseek f DataTableStart #seek_set
while(not DataTableEnd) do (
DataOffset = ReadBElong f
DataType = ReadBElong f
EntryType = ReadBEword f
SubId = ReadByte f
Padding = ReadByte f
if(DataType != -1) then (
append DataTable (VertexDeclarationEntry DataOffset: DataOffset DataType: DataType EntryType: EntryType SubId: SubId)
if(EntryType == 0) then CoordinatesFound = true
if(EntryType == 1) then BoneWeightsFound = true
if(EntryType == 2) then BoneIndicesFound = true
if(EntryType == 5) then UVDataFound = true
) else (
DataTableEnd = true
)
)
if((not CoordinatesFound) or (not BoneWeightsFound) or (not BoneIndicesFound) or (not UVDataFound)) then (
throw "NOOOOO!"
)
fseek f BackJump #seek_set
--end read data table
StartDirection = 1
f1 = (ReadBEword f) + 1
f2 = (ReadBEword f) + 1
FaceDirection = StartDirection
Do (
f3 = (ReadBEword f)
if (f3==0xFFFF) then (
f1 = (ReadBEword f) + 1
f2 = (ReadBEword f) + 1
FaceDirection = StartDirection
) else (
f3 += 1
FaceDirection *= -1
if (f1!=f2)AND(f2!=f3)AND(f3!=f1) then (
if FaceDirection > 0 then append Face_array [f1,f2,f3]
else append Face_array [f1,f3,f2]
)
f1 = f2
f2 = f3
)
) while ((ftell f) != (VerStart))
fseek f VerStart#seek_set
test = readshort f
if test != 0x0000 Do (
fseek f -2 #seek_cur
)
fseek f VertStart#seek_set
for v = 1 to VertCount Do (
vx = 0
vy = 0
vz = 0
tu = 0
tv = 0
bone1 = 0xFF
bone2 = 0xFF
bone3 = 0xFF
bone4 = 0xFF
weight1 = 0
weight2 = 0
weight3 = 0
weight4 = 0
UVSubZeroFound = false
UVFound = false
VertexDataStart = ftell f
for x = 1 to DataTable.count Do (
Entry = DataTable[x]
fseek f Entry.DataOffset #seek_cur
if(Entry.EntryType == 0) Then (
vx = ReadBEfloat f
vy = ReadBEfloat f
vz = ReadBEfloat f
)
if(Entry.EntryType == 1) Then (
weight1 = readbyte f#unsigned
weight2 = readbyte f#unsigned
weight3 = readbyte f#unsigned
weight4 = readbyte f#unsigned
)
if(Entry.EntryType == 2) Then (
bone1 = readbyte f#unsigned
bone2 = readbyte f#unsigned
bone3 = readbyte f#unsigned
bone4 = readbyte f#unsigned
)
if(Entry.EntryType == 5) Then (
SubId = Entry.SubId
ReadThisUV = (not UVFound) or (not UVSubZeroFound and SubId == 0)
if(ReadThisUV) then (
UVFound = true
if(SubId == 0) then
UVSubZeroFound = true
if(Entry.DataType == 2892709) then (
tu = ReadBEfloat f
tv = ReadBEfloat f
) else (
tu = ReadBEHalfFloat f
tv = ReadBEHalfFloat f
)
tv = tv * (-1)
)
)
fseek f VertexDataStart #seek_set
)
fseek f VertSize #seek_cur
w = (weight_data boneids:#() weights:#())
maxweight = 0
if(bone1 != 0xFF) then
maxweight = maxweight + weight1
if(bone2 != 0xFF) then
maxweight = maxweight + weight2
if(bone3 != 0xFF) then
maxweight = maxweight + weight3
if(bone4 != 0xFF) then
maxweight = maxweight + weight4
if(maxweight != 0) then
(
mxw = 255.0
if(bone1 != 0xFF) then
(
w1 = weight1 as float
append w.boneids (BoneID_array[bone1+1])
append w.weights (w1 / mxw)
)
if(bone2 != 0xFF) then
(
w2 = weight2 as float
append w.boneids (BoneID_array[bone2+1])
append w.weights (w2 / mxw)
)
if(bone3 != 0xFF) then
(
w3 = weight3 as float
append w.boneids (BoneID_array[bone3+1])
append w.weights (w3 / mxw)
)
if(bone4 != 0xFF) then
(
w4 = weight4 as float
append w.boneids (BoneID_array[bone4+1])
append w.weights (w4 / mxw)
)
)
append Vert_array [vx * mdlScale,(-1)*vz * mdlScale,vy * mdlScale] --save verts to Vert_array
--append Normal_array [nx,ny,nz] --save normals to Normal_array
append UV_array [tu,tv,0] --save UVs to UV_array
append Weight_array w
)
fseek f tablestart#seek_set
for I = 1 to Face_array.count do (
vertices = Face_array[I]
append All_Face_array [vertices[1] + AllVertexCount, vertices[2] + AllVertexCount, vertices[3] + AllVertexCount]
append All_Mat_Face_array c
)
buildTVFaces msh
for j = 1 to UV_array.count do setTVert msh j UV_array[j]
for j = 1 to Face_array.count do setTVFace msh j Face_array[j]
--for j = 1 to Normal_array.count do setNormal msh j Normal_array[j]
max modify mode
select msh
skinMod = skin ()
addModifier msh skinMod
for I = 1 to BNArr.count do
(
maxbone = getnodebyname BNArr[I].name
if I != BNArr.count then
skinOps.addBone skinMod maxbone 0
else
skinOps.addBone skinMod maxbone 1
)
modPanel.setCurrentObject skinMod
for I = 1 to Weight_array.count do
(
w = Weight_array[I]
bi = #() --bone index array
wv = #() --weight value array
for j = 1 to w.boneids.count do
(
boneid = w.boneids[j]
weight = w.weights[j]
append bi boneid
append wv weight
)
skinOps.ReplaceVertexWeights skinMod I bi wv
)
max create mode*/
)
max create mode
msh = mesh vertices:All_Vert_array faces:All_Face_array --build mesh
msh.numTVerts = All_UV_array.count
if (BNArr.count >= 1) then msh.name = BNArr[1].name
buildTVFaces msh
for j = 1 to All_UV_array.count do setTVert msh j All_UV_array[j]
for j = 1 to All_Face_array.count do (
setTVFace msh j All_Face_array[j]
setFaceMatID msh j All_Mat_Face_array[j]
)
max modify mode
select msh
skinMod = skin ()
addModifier msh skinMod
for I = 1 to BNArr.count do
(
maxbone = getnodebyname BNArr[I].name
if I != BNArr.count then
skinOps.addBone skinMod maxbone 0
else
skinOps.addBone skinMod maxbone 1
)
modPanel.setCurrentObject skinMod
for I = 1 to All_Weight_array.count do
(
w = All_Weight_array[I]
bi = #() --bone index array
wv = #() --weight value array
for j = 1 to w.boneids.count do
(
boneid = w.boneids[j]
weight = w.weights[j]
append bi boneid
append wv weight
)
Direct link to maxscript just in case it gets updated: http://sonic-glvl.go...%206-07-2012.ms
Maxscript Credits:
chrrox, kentilan, darkspinesonic35, and TZ, And a little myself early on( batch importing models)... am I forgetting anyone ?
1) Install Niftools plugin into 3ds max
2) Convert the .hkx files into .kf using hkxcmd. Use the following command line parameters:
hkxcmd.exe exportkf FILE.skl.hkx FILE.anm.hkx FILE.kf
FILE.skl.hkx -> the skeleton file of the model, like "chr_Sonic_HD.skl.hkx"
FILE.anm.hkx -> the animation file you want to convert, like "sn_run_loop.anm.hkx"
FILE.kf -> the output .kf file
3) Use the model importer maxscript (like "Model Importer-Updated 6-07-2012.ms") to import the .model file into 3ds max
4) Once you have the 3d model opened in 3ds Max, import the .kf file in 3ds max with the niftools plugin (you may have to import the animation a few times to get it to work perfectly.)
(Animation tools explanation credit to DaGuar)
This post has been edited by Andrew75: 12 May 2015 - 01:46 PM
This was found in SonicClassic.prm.xml. So if you ever wanted to use the homingattack as Classic Sonic, it's as easy as turning on a variable and repacking the game. yay
I think if we activated the game's debugger, we can modify these variables in real time so it'd be a lot easier. SonicClassic.prm.xml is full of variables for the Classic Sonic physics.
EDIT1: Here's one possibility to activating the debugger.
In #Application.ar.00, there are two lua files called ApplicationSetting.lua and ApplicationSettingDebug.lua. By default, the demo looks at ApplicationSetting.lua, here are the settings:
I think one thing the game might consider when loading the debug is the "DemoKind" string. The plan is to set the DemoKind string in ApplicationSetting to Production, and possibly DebugSequence to 1 (might be unnecessary since we don't know what it does). DemoDistribution should be commented out. Basically, make ApplicationSetting.lua look like ApplicationSettingDebug.
I remember when messing around with Shadow and NiGHTS JoD, those games do take what the build string is into consideration. Because this is a prerelease, there should be a possibility of getting the debug to work. But of course, since it's a "release" build, maybe they left the files needed out. But it's worth a try. The only problem right now is packing things up so the game can read them. This is apparently a problem for the 360 version, but might not be a problem for the PS3 version. But I doubt it, because the keys that have been released for the PS3 probably won't help with this since this is more recent.
I hope a PC demo comes out. That should make things easier.
This post has been edited by evilhamwizard: 23 June 2011 - 05:59 PM
So do we have a method of extracting and injecting to CPK files yet? I have some devious ideas I'd like to perform on my files.
The CRI Packed File Maker can extract and pack CPK files, and there are probably some tools for quickbms that'll work too. I tried CRI's tools on bb.cpk but even though it would list the contents of everything it wouldn't let me extract anything, so I had to use quickbms plus a cpk script. The music/sound cpks open and extract fine with CRI's tools though.
I remember getting Saz to use .ar files I packed with edited lua/xml files for Unleashed about a year ago and those worked out okay for him. I forget if he was using a dev 360 or not. I remember repacking the CPK file for Sonic 4 and that was okay, so maybe it could work.
So do we have a method of extracting and injecting to CPK files yet? I have some devious ideas I'd like to perform on my files.
The CRI Packed File Maker can extract and pack CPK files, and there are probably some tools for quickbms that'll work too. I tried CRI's tools on bb.cpk but even though it would list the contents of everything it wouldn't let me extract anything, so I had to use quickbms plus a cpk script. The music/sound cpks open and extract fine with CRI's tools though.
I remember getting Saz to use .ar files I packed with edited lua/xml files for Unleashed about a year ago and those worked out okay for him. I forget if he was using a dev 360 or not. I remember repacking the CPK file for Sonic 4 and that was okay, so maybe it could work.
Mind if I pester you for the QuickBMS script? Jim and I ran into the same issue earlier. Glad there's a fix for it. I assume the CRI tools can still repack bb.cpk correct?
So do we have a method of extracting and injecting to CPK files yet? I have some devious ideas I'd like to perform on my files.
The CRI Packed File Maker can extract and pack CPK files, and there are probably some tools for quickbms that'll work too. I tried CRI's tools on bb.cpk but even though it would list the contents of everything it wouldn't let me extract anything, so I had to use quickbms plus a cpk script. The music/sound cpks open and extract fine with CRI's tools though.
I remember getting Saz to use .ar files I packed with edited lua/xml files for Unleashed about a year ago and those worked out okay for him. I forget if he was using a dev 360 or not. I remember repacking the CPK file for Sonic 4 and that was okay, so maybe it could work.
Mind if I pester you for the QuickBMS script? Jim and I ran into the same issue earlier. Glad there's a fix for it. I assume the CRI tools can still repack bb.cpk correct?
Sure, you can use this script with QuickBMS to extract basically any CPK file.
You can pack a directory into a CPK file with CRI's tools. In this case, you need to pack the entire contents of bb.cpk again to create a new one. If you need to look inside the .ar files, you can find the tools needed to pack and unpack them here.