ZenHAX

Free Game Research Forum | Official QuickBMS support | twitter @zenhax | SSL HTTPS://zenhax.com
It is currently Wed Sep 26, 2018 3:24 am

All times are UTC




Post new topic  Reply to topic  [ 13 posts ] 
Author Message
PostPosted: Fri Jun 08, 2018 11:51 am 

Joined: Fri Jun 08, 2018 11:37 am
Posts: 7
Here is Recolove Model Importer for Noesis.
It loads mesh data (vertex, face, normals and UVs) from a *.fed model.

fmt_recolove_fed.py:
Code:
# v2: Fixed face direction and UV
import math
from inc_noesis import *


def registerNoesisTypes():
    """ register plugin
    """
    handle = noesis.register("Recolove Model", ".fed")
    noesis.setHandlerTypeCheck(handle, fedCheckType)
    noesis.setHandlerLoadModel(handle, fedLoadModel)

    # noesis.logPopup()  # show console
    return 1


def fedCheckType(data):
    """ check header
    """
    FED_HEADER = 0x43415046  # FPAC
    bs = NoeBitStream(data)
    bs.seek(0)
    if bs.readInt() != FED_HEADER:
        return 0
    return 1


def fedLoadModel(data, mdlList):
    """ load model (mesh and UV)
    """
    bs = NoeBitStream(data)
    meshes = []
    myMeshes = []

    # find face sets. eg. (0, 1, 2)
    bs.seek(0)
    while not bs.checkEOF():
        firstFace = (bs.readUShort(), bs.readUShort(), bs.readUShort())
        tailVals = (bs.readUShort(), bs.readUShort(), bs.readUShort(),
                    bs.readUShort(), bs.readUShort())
        if (firstFace == (0, 1, 2) and sum(tailVals) < 30):
            myMeshes.append({"faceOffset": bs.tell() - 16})
    if len(myMeshes) == 0:
        print("no face sets.")
        return 0

    # find face counts
    for myMesh in myMeshes:
        isFound = False
        ofs = myMesh["faceOffset"]
        while True:
            ofs -= 16  # go up
            if isFound:
                break
            if ofs < 0:
                print("face count not found.")
                return 0
            bs.seek(ofs)
            numFaceX3 = bs.readUShort()
            bs.readUShort()  # unknown
            magic1C = bs.readInt()
            magicZero1 = bs.readInt64()
            numVert = bs.readInt()
            magicZero2 = bs.readInt()
            magicZero3 = bs.readInt64()
            if (numFaceX3 % 3 == 0 and magic1C == 0x1C and magicZero1 == 0 and magicZero2 == 0 and magicZero3 == 0):
                isFound = True
                myMesh["numFace"] = numFaceX3 // 3
                myMesh["numVert"] = numVert
                myMesh["vertOffset"] = bs.tell()

    for myMesh in myMeshes:
        print(myMesh)

        verts = []
        bs.seek(myMesh["vertOffset"])
        for i in range(myMesh["numVert"]):
            x = _getFloat(bs)
            y = _getFloat(bs)
            z = _getFloat(bs)
            verts.append(NoeVec3((x, y, z)))
        _padding(bs)

        normals = []
        for i in range(myMesh["numVert"]):
            x = _getFloat(bs)
            y = _getFloat(bs)
            z = _getFloat(bs)
            normals.append(NoeVec3((x, y, z)))
        _padding(bs)

        if bs.readBytes(4)[3] == 0xFF:  # Skip, may be weights
            bs.seek(-4, NOESEEK_REL)
            bs.readBytes(myMesh["numVert"] * 4)
            _padding(bs)

        uvs = []
        for i in range(myMesh["numVert"]):
            u = _getFloat(bs)
            v = _getFloat(bs) + 1.0
            uvs.append(NoeVec3((u, v, 0.0)))
        _padding(bs)

        if bs.tell() != myMesh["faceOffset"]:
            print("  SKIP: UV exceeds faceOffset: %d" % bs.tell())
            continue

        idxList = []
        for i in range(myMesh["numFace"]):
            indices = (bs.readUShort(), bs.readUShort(), bs.readUShort())
            idxList.append(indices[2])
            idxList.append(indices[1])
            idxList.append(indices[0])
        _padding(bs)

        meshName = "mesh_%08X" % myMesh["vertOffset"]
        mesh = NoeMesh(idxList, verts, meshName)
        mesh.setNormals(normals)
        mesh.setUVs(uvs)
        meshes.append(mesh)

    mdlList.append(NoeModel(meshes))
    return 1


def _getFloat(bs: NoeBitStream):
    """ get float value, skipping NaN
    """
    val = bs.readFloat()
    if not math.isnan(val):
        return val
    else:
        return bs.readFloat()


def _padding(bs: NoeBitStream):
    """ padding by 16 bytes
    """
    mod = bs.tell() % 16
    if mod != 0:
        bs.readBytes(16 - mod)


You will also need to use the following tools.

1. CPK Unpacker (to obtain fed files):
https://github.com/esperknight/CriPakTo ... ster/Build

2. QuickBMS and this script (to extract *.tex files):
http://aluigi.altervista.org/bms/fpactex.bms

3. Texture Unpacker (to convert textures):
https://github.com/xdanieldzd/GXTConvert/releases


Last edited by kana4567 on Fri Jun 22, 2018 7:32 am, edited 3 times in total.

Top
   
PostPosted: Sat Jun 16, 2018 12:44 pm 

Joined: Sat Jun 16, 2018 12:31 pm
Posts: 2
I got recolove dumped data.
When I tried to expand. cpk with cripaktools, I could not extract it by saying cannnot find ALL.
https://imgur.com/a/uiwQ6pB
Is it necessary to decrypt it?
This is the .cpk file i got.
https://mega.nz/#!kIFDSIQI!x-CBWFLmHYyu ... QZDmAJC5JY


Top
   
PostPosted: Mon Jun 18, 2018 11:13 am 

Joined: Fri Jun 08, 2018 11:37 am
Posts: 7
Yes, you have to decrypt game files by using a tool like this:
https://github.com/motoharu-gosuto/psvpfstools/releases


Top
   
PostPosted: Wed Jun 20, 2018 1:19 pm 

Joined: Wed Jun 20, 2018 1:18 pm
Posts: 7
It doesn't work.

i get this

"Successfully decompressed zRIF from provided license string.
failed to find unicv.db file or icv.db in folder"


Top
   
PostPosted: Thu Jun 21, 2018 3:27 pm 

Joined: Fri Jun 08, 2018 11:37 am
Posts: 7
Make sure that you are using the latest dump tool.
https://github.com/TheOfficialFloW/NoNpDrm

I'm not a professional of decryption,
but Reddit or gbatemp forums may help you.


Top
   
PostPosted: Fri Jun 22, 2018 7:24 am 

Joined: Fri Jun 08, 2018 11:37 am
Posts: 7
Here is a little guide to decrypt files. A retail game is needed.

Install h-encore on PS Vita 3.68.
https://github.com/TheOfficialFloW/h-encore

Install AntiBlacklist (in case of VitaTV).
https://vitadb.rinnegatamante.it/#/info/11

Install NoNpDrm and reboot device.
https://github.com/TheOfficialFloW/NoNpDrm#installation
https://github.com/TheOfficialFloW/NoNp ... ke-license

When you first launch the game, a file "6488b73b912a753a492e2714e9b38bc7.rif" will be created.
Open it by hex editor and you will see the license key at 0x50.

Copy "gro0:app/TITLE_ID" folder to your PC via FTP, then decrypt files using psvpfsparser.
Note that the license key corresponds "--klicensee" parameter.
https://github.com/motoharu-gosuto/psvpfstools/releases


Last edited by kana4567 on Fri Jul 06, 2018 2:45 pm, edited 2 times in total.

Top
   
PostPosted: Fri Jun 22, 2018 10:25 am 

Joined: Sat Jun 16, 2018 12:31 pm
Posts: 2
kana4567,Thank you!
I appreciate your help.
I was able to obtain it.
https://imgur.com/a/Y868rsA
However, it seems that some files are not expanded correctly.
https://imgur.com/a/Meg0sBK
Are you planning to solve this problem?


Top
   
PostPosted: Fri Jun 22, 2018 6:32 pm 

Joined: Fri Jun 08, 2018 11:37 am
Posts: 7
beargood, congrats!

> it seems that some files are not expanded correctly

You don't have to worry about that.
Some head models contains strange triangle meshes between the face (top) and hairs (bottom).
Please delete those meshes at the middle, after exporting.

One more thing, the original filenames (*.fed, *.tex) are listed in the following files:
- TITLE_ID/media/afs/CharaModel.als
- TITLE_ID/media/afs/CharaTex.als


Last edited by kana4567 on Thu Jun 28, 2018 2:24 pm, edited 1 time in total.

Top
   
PostPosted: Fri Jun 22, 2018 7:54 pm 

Joined: Wed Jun 20, 2018 1:18 pm
Posts: 7
Ah, thats cool i hope it will work for me too once i get my 3.60 vita

thank you for the tutorial, finger crossed, as they say


Top
   
PostPosted: Wed Jun 27, 2018 1:01 pm 

Joined: Wed Jun 20, 2018 1:18 pm
Posts: 7
Edit:
Well i did it, tho all the models seem to miss the ears, do you know by any chance where they are ?


Top
   
PostPosted: Thu Jun 28, 2018 3:34 pm 

Joined: Fri Jun 08, 2018 11:37 am
Posts: 7
> all the models seem to miss the ears

Wow, I never realized it, as most girls in this game have hairs which covers ears!
Unfortunately, my script can't load (find) those sub-meshes.

But I guess ears should exist in the same *.fed file, because the file has string like "EAR" or "EARShape".


Top
   
PostPosted: Thu Jun 28, 2018 4:41 pm 

Joined: Wed Jun 20, 2018 1:18 pm
Posts: 7
Yeah also some of them miss some hair accessories like bows


Top
   
PostPosted: Fri Jun 29, 2018 2:19 pm 

Joined: Fri Jun 08, 2018 11:37 am
Posts: 7
Sorry but I don't have enough time and information (about file format) to fix that.
For now, I recommend you to create your own sub-meshes if there were some missing parts.

All I did is just finding chunks of floating-point numbers, by viewing file in Hex Workshop like this:
Attachment:
bit-image-fed.png [63.53 KiB]
Not downloaded yet


Anyway, If anyone knows similar 3D model format (by CRIWARE), please let me know!
I believe that *.fed files also contain bones, weights and blendshapes.


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 13 posts ] 

All times are UTC


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Limited