Jump to content

Ridge Racer series (model and maps included)


UndercoverBoy833

Recommended Posts

you can post the sample file related to any Ridge Racer games till Slipstream mobile, so I'm starting with my sample model file from Ridge Racer 7 PS3. Since I was importing it with this blender addon, it gave me different errors for wheel mdl and car mdl.

car error:

Python: Traceback (most recent call last):
  File "C:\Users\Admin\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\Ridge-Racer-Blender-Addon-master\__init__.py", line 42, in execute
    return import_ridgeRacer.main(self.filepath, self.clear_scene)
  File "C:\Users\Admin\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\Ridge-Racer-Blender-Addon-master\import_ridgeRacer.py", line 283, in main
    r7c.read(bs)
  File "C:\Users\Admin\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\Ridge-Racer-Blender-Addon-master\Formats\RidgeRacer7\r7c.py", line 65, in read
    self.read_lod(binaryReader)
TypeError: R7C.read_lod() missing 1 required positional argument: 'lod_number'

wheel error:

Python: Traceback (most recent call last):
  File "C:\Users\Admin\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\Ridge-Racer-Blender-Addon-master\__init__.py", line 42, in execute
    return import_ridgeRacer.main(self.filepath, self.clear_scene)
  File "C:\Users\Admin\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\Ridge-Racer-Blender-Addon-master\import_ridgeRacer.py", line 287, in main
    r7w.read(bs)
  File "C:\Users\Admin\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\Ridge-Racer-Blender-Addon-master\Formats\RidgeRacer7\r7w.py", line 23, in read
    self.read_lods(binaryReader)
  File "C:\Users\Admin\AppData\Roaming\Blender Foundation\Blender\4.0\scripts\addons\Ridge-Racer-Blender-Addon-master\Formats\RidgeRacer7\r7w.py", line 34, in read_lods
    R7W_part = R7W.R7W_PART(binaryReader, lod_offset)
TypeError: R7W.R7W_PART.__init__() takes 1 positional argument but 3 were given

whereas the car mdl import worked for Ridge Racer 6 format.

so yeah, I may be making the same topic but for the texture sides.

raggio.zip wheel.zip

Edited by UndercoverBoy833
updated my first post and added import error codes of mdl files
Link to comment
Share on other sites

  • Engineer

just fast hach for get all meshes using MRP

edit: plugin for Noesis (with out uvs) fmt_RidgeRacer.py

image.thumb.png.3d9a408239976ce006e016d0754bba30.png

import mrp
import struct

def findall(p, s):
    i = s.find(p)
    while i != -1:
        yield i
        i = s.find(p, i+1)

bf = mrp.get_bfile('>')
data = bf.read()
result = [i for i in findall(b'R7O', data)]

all_mesh = []
for x in result:
    bf.seek(x)
    unk = [bf.readInt() for i in range(6)]
    bf.seek(x+unk[4])
    _unk = [bf.readInt() for i in range(5)]
    stride = (unk[5] - (unk[4]+20))//_unk[4]
    vpoints = []
    for i in range(_unk[4]):
        vpoints.append((bf.readHalfFloat(),bf.readHalfFloat(),bf.readHalfFloat()))
        bf.seek(stride-6,1)
    bf.seek(x+unk[5])
    _unk = [bf.readInt() for i in range(4)]
    ibuf = bf.read(_unk[3]*2)
    #fix_order
    ibuf = struct.unpack('>%iH'%_unk[3], ibuf)
    ibuf = struct.pack('<%iH'%_unk[3], *ibuf)
    #end_fix_order
    name = 'mesh_%i'%x
    all_mesh.append(name)
    Mesh = mrp.create_mesh(name)
    Mesh.set_vertices(vpoints)
    Mesh.set_faces(ibuf, fm="TStripFF", tp="Short")

mrp.render(all_mesh)

 

Edited by Durik256
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • Engineer
11 hours ago, shak-otay said:

uvs

As far as I remember, you are right, UVs are similar to half floats, but each submesh has a different stride and offset for UVs, so I didn't bother parsing the attributes and skipped UVs. (I'm lazy xD)

Edited by Durik256
Link to comment
Share on other sites

  • Engineer
1 hour ago, Durik256 said:

Насколько я помню, вы правы, UV похожи на полуфлоты, но каждая подсетка имеет разный шаг и смещение для UV, поэтому я не стал анализировать атрибуты и пропустил UV. (Мне лень xd)

Talk in english please, dont know where you quoted that russian from formerly tbh, dont see any here... But dont speak foreign languages here, thanks...

Majority of the users dont understand probably what you wrote without translator 😉

Link to comment
Share on other sites

  • Engineer
1 hour ago, wssdude said:

But dont speak foreign languages here, thanks..

the original text was in English. This was done by the browser's auto-translator while editing the post. (the translator has public access, I think this would not be a problem even if I did it intentionally)

Edited by Durik256
Link to comment
Share on other sites

  • Engineer
21 minutes ago, Durik256 said:

(the translator has public access, I think this would not be a problem even if I did it intentionally)

I didnt give you any formal warnings, dont worry 😉 Just wanted to point it out, didnt know what to make of it till I put it in the translator and would bet I was not the only one...

Anyone can use translators, true, but they are not perfect 🙂

We prefer to keep the forums in English ideally, as stated by rules. They do not explicitly forbid you from using other languages, but would be better to not break out of it for answers to posts, for better general understanding, is all. 🙂

Link to comment
Share on other sites

  • 2 months later...
On 11/4/2023 at 11:30 PM, Durik256 said:

just fast hach for get all meshes using MRP

edit: plugin for Noesis (with out uvs) fmt_RidgeRacer.py

image.thumb.png.3d9a408239976ce006e016d0754bba30.png

I can't see the line clearly "vpoints.append((bf.readHalfFloat(),bf.readHa.." so that i can try to copy them in Model researcher pro.image.png.9869e30a387f9df68ea411e9012848e2.png

 

Edited by UndercoverBoy833
existing screenshot I copied is blurry
Link to comment
Share on other sites

  • Engineer
3 hours ago, UndercoverBoy833 said:

I can't see the line clearly "vpoints.append((bf.readHalfFloat(),bf.readHa.." so that i can try to copy them in Model researcher pro.

why do you need to rewrite this? I made a noesis plugin. your file "kaszni.scx" is a completely different format and it is compressed using zlib

*I edited the old post and added all the code for mrp

**structure [*.scx]

4bytes magic//[TEPK]
int numBlock

foreach numBlock:
	int offset
    int decomSize
    int comSize

 

several submesh:

-3.png.793c6de9959979a0088e27c32b6b727b.png

 

Edited by Durik256
Link to comment
Share on other sites

16 hours ago, Durik256 said:

why do you need to rewrite this? I made a noesis plugin.

well for the first place since your noesis plugin requires to open .brs, I have to convert them from my sample file to brs using mrp before using your noesis plugin you made, so that's where it stopped to replicate your code you wrote a while ago.

 

my english is not the best atm so

Edited by UndercoverBoy833
Link to comment
Share on other sites

  • 1 month later...

was using h3x3r's RR7 texture bms script to convert raggio textures (complete machine) but some of the textures appeared to be broken looking, especially in noesis.

posting them plus with sample file

tex_RidgeRacer7alt.pytex_RidgeRacer7.py

on a side note, can you check the textures on CarGet scenes because I'm highly interested in highest manufacturer and model logo quality?

image.png

CarGetLogos.png

RidgeRacer7tex.zip sample.zip cargetsample.zip

Link to comment
Share on other sites

  • 2 months later...
  • Engineer

Try this one. I noticed that PS3 swizzle is in most cases morton oreder.

from inc_noesis import *
import noesis
import rapi
import os

def registerNoesisTypes():
   handle = noesis.register("Ridge Racer 7 - Texture", ".r7t")
   noesis.setHandlerTypeCheck(handle, noepyCheckType)
   noesis.setHandlerLoadRGBA(handle, noepyLoadRGBA)
   noesis.logPopup()
   return 1
        
def noepyCheckType(data):
   bs = NoeBitStream(data)
   if len(data) < 20:
      return 0
   if bs.readUInt() != 0x00543752:
      return 0
   return 1
   
def noepyLoadRGBA(data, texList):
    bs = NoeBitStream(data,NOE_BIGENDIAN)
    texBaseName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getInputName()))
    texMagic = bs.readUInt()
    bs.readBytes(12)
    texPixelFormat = bs.readUByte()
    bs.readBytes(7)
    texWidth = bs.readUShort()
    texHeight = bs.readUShort()
    bs.readBytes(8)
    texSize = bs.readUInt()
  
    data = bs.readBytes(texSize)
    if texPixelFormat == 136:
        data = rapi.imageDecodeDXT(data, texWidth, texHeight, noesis.NOESISTEX_DXT5)
        texFmt = noesis.NOESISTEX_RGBA32
        print("Pixel Format > DXT5")
    elif texPixelFormat == 134:
        data = rapi.imageDecodeDXT(data, texWidth, texHeight, noesis.NOESISTEX_DXT1)
        texFmt = noesis.NOESISTEX_RGBA32
        print("Pixel Format > DXT1")
    elif texPixelFormat == 133:
        data = rapi.imageFromMortonOrder(data, texWidth, texHeight, 4)
        data = rapi.imageDecodeRaw(data, texWidth, texHeight, "r8g8b8a8")
        texFmt = noesis.NOESISTEX_RGBA32
        print("Pixel Format > RGBA8 Morton")
    texList.append(NoeTexture(rapi.getInputName(), texWidth, texHeight, data, texFmt))
    return 1

 

  • Thanks 2
Link to comment
Share on other sites

Posted (edited)
14 hours ago, h3x3r said:

Try this one. I noticed that PS3 swizzle is in most cases morton oreder.

from inc_noesis import *
import noesis
import rapi
import os

def registerNoesisTypes():
   handle = noesis.register("Ridge Racer 7 - Texture", ".r7t")
   noesis.setHandlerTypeCheck(handle, noepyCheckType)
   noesis.setHandlerLoadRGBA(handle, noepyLoadRGBA)
   noesis.logPopup()
   return 1
        
def noepyCheckType(data):
   bs = NoeBitStream(data)
   if len(data) < 20:
      return 0
   if bs.readUInt() != 0x00543752:
      return 0
   return 1
   
def noepyLoadRGBA(data, texList):
    bs = NoeBitStream(data,NOE_BIGENDIAN)
    texBaseName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getInputName()))
    texMagic = bs.readUInt()
    bs.readBytes(12)
    texPixelFormat = bs.readUByte()
    bs.readBytes(7)
    texWidth = bs.readUShort()
    texHeight = bs.readUShort()
    bs.readBytes(8)
    texSize = bs.readUInt()
  
    data = bs.readBytes(texSize)
    if texPixelFormat == 136:
        data = rapi.imageDecodeDXT(data, texWidth, texHeight, noesis.NOESISTEX_DXT5)
        texFmt = noesis.NOESISTEX_RGBA32
        print("Pixel Format > DXT5")
    elif texPixelFormat == 134:
        data = rapi.imageDecodeDXT(data, texWidth, texHeight, noesis.NOESISTEX_DXT1)
        texFmt = noesis.NOESISTEX_RGBA32
        print("Pixel Format > DXT1")
    elif texPixelFormat == 133:
        data = rapi.imageFromMortonOrder(data, texWidth, texHeight, 4)
        data = rapi.imageDecodeRaw(data, texWidth, texHeight, "r8g8b8a8")
        texFmt = noesis.NOESISTEX_RGBA32
        print("Pixel Format > RGBA8 Morton")
    texList.append(NoeTexture(rapi.getInputName(), texWidth, texHeight, data, texFmt))
    return 1

 

hey h3x3r, thx for the updated noesis plugin code for Ridge racer 7 textures, it also fixes the broken shadow mask texture after previewing it. much appreciated.

I'm gonna open a new topic regarding Ridge Racer Slipstream model (.scx) since it uses Invictus Games file format.

image.png

Edited by UndercoverBoy833
EDIT: actually I won't open a new topic anyway
Link to comment
Share on other sites

  • Engineer
Posted (edited)

How did you unpack that obb file from RR Slipstream?

Nvm, i figured myself.

//------------------------------------------------
//--- 010 Editor v14.0 Binary Template
//
//      File: 
//   Authors: 
//   Version: 
//   Purpose: 
//  Category: 
// File Mask: 
//  ID Bytes: 
//   History: 
//------------------------------------------------
char Magic[8];
uint32 Unk,Hash,PathCount;

struct {
    uint32 StrLen;
    char PathName[StrLen];
}Path[PathCount]<optimize=false>;

uint32 FileCount;

struct {
    uint32 StrLen;
    char FileName[StrLen];
    uint32 FileNum,FileOffset,FileSize;
}FileInfo[FileCount]<optimize=false>;

qbms also:

#############################################
#   Ridge Racer Slipstream - *.obb dumper   #
#############################################
get BaseFileName basename

idstring "TLIBVER1"
get Unknown uint32
get Hash uint32
get PathCount uint32

for i = 0 < PathCount
	get PathStrLen uint32
	getdstring PathName PathStrLen
next i

get Files uint32

for i = 0 < Files
	get FileNameStrLen uint32
	getdstring FileName FileNameStrLen
	get Dummy uint32
	get Offset uint32
	get Size uint32
	string Name p "%s/%s" BaseFileName FileName
	log Name Offset Size
next i

And here is TEPK dumper.

##############################################
#   Ridge Racer Slipstream - *.TEPK dumper   #
##############################################
get BaseFileName basename
get FileExtension extension

idstring "TEPK"
get ChunkCount uint32

for i = 0 < ChunkCount
	get Offset uint32
	get Size uint32
	get ZSize uint32
	string Name p "%s/%s.%s" BaseFileName BaseFileName FileExtension
	append 0
	clog Name Offset ZSize Size
next i

And early 010 hex editor template for unpacked *.scx. Not sure if it works for all files. It output models in *.obj format.

//------------------------------------------------
//--- 010 Editor v14.0 Binary Template
//
//      File: 
//   Authors: 
//   Version: 
//   Purpose: 
//  Category: 
// File Mask: 
//  ID Bytes: 
//   History: 
//------------------------------------------------
LittleEndian();OutputPaneClear();
local uint32 i,j,k,l,m,n,o,p;
local string FileName=GetFileName(),FilePath=FileNameGetPath(FileName,true),BaseName=FileNameGetBase(FileName,false);

struct {
    
    typedef struct 
    {
        float VPOSX,VPOSY,VPOSZ,VNPOSX,VNPOSY,VNPOSZ,VPOSU,VPOSV;
        Printf("v %f %f %f\nvn %f %f %f\nvt %f %f\n",VPOSX,VPOSY,VPOSZ,VNPOSX,VNPOSY,VNPOSZ,VPOSU,VPOSV);
    }Stride_32;
    
    typedef struct 
    {
        int16 F1,F2,F3;
        Printf("f %d/%d/%d %d/%d/%d %d/%d/%d\n",F1+1,F1+1,F1+1,F2+1,F2+1,F2+1,F3+1,F3+1,F3+1);
    }Index;
    
    typedef struct 
    {
        char Magic[4];
        uint32 InfoCount;
        uint32 InfoOffset;
    }Header;
    
    typedef struct 
    {
        uint32 ShapeInfoFlag,ShapeInfoOffset,
               UnkInfoFlag,UnkInfoOffset,
               VertexInfoFlag,VertexInfoOffset,
               IndexInfoFlag,IndexInfoOffset;
    }Table;

    typedef struct 
    {
        for (i=0; i < header.InfoCount-1; i++)
        {
            struct 
            {
                local string ShapeNum;
                SPrintf(ShapeNum,"_shape_%04u",j++);
                
                FSeek(table[i].ShapeInfoOffset);
                struct 
                {
                    uint32 ShapeFlag,ShapeUnkOffset,Unk_0;
                    float Unk_1;
                    uint32 Unk_2;
                    float Unk_3;
                    string ShapeName;
                }ShapeInfo;
                
                FSeek(table[i].VertexInfoOffset);
                struct 
                {
                    uint32 VertexFlag,VertexDataSize,VertexCount,UnkCount;
                    Stride_32 VertexBuffer[VertexCount]<optimize=false>;
                }VtxBufferInfo;
                
                FSeek(table[i].IndexInfoOffset);
                Printf("\ng %s\n\n",ShapeInfo.ShapeName);
                struct 
                {
                    uint32 IndexFlag,IndexDataSize,IndexCount;
                    Index index[IndexCount/3]<optimize=false>;
                    Printf("\n");
                }IdxBufferInfo;
                
                OutputPaneSave(FilePath+BaseName+ShapeNum+".obj");
                OutputPaneClear();
            }Shape;
        }
    }Shapes;

    Header header;
    Table table[header.InfoCount-1];
    Shapes shapes;
}RRS_scx;

image.thumb.png.61ba97e510e07648d26eb70893c2d133.png

Edited by h3x3r
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • Engineer
Posted (edited)

Noesis python script.

from inc_noesis import *
import noesis
import rapi
import os

def registerNoesisTypes():
   handle = noesis.register("Ridge Racer Slipstream - Mesh", ".scx")
   noesis.setHandlerTypeCheck(handle, noepyCheckType)
   noesis.setHandlerLoadModel(handle, noepyLoadModel)
   noesis.logPopup()
   return 1
    
def noepyCheckType(data):
    if data[:4] != b'TEPK':
        return 0
    if decompress_zlib(data)[:4] != b'INVO':
        return 0
    return 1
    
def decompress_zlib(data):
   bs = NoeBitStream(data)
   bs.read(4)
   Chunks = bs.readUInt()
   DecompressedBuffer = b''

   for i in range(Chunks):
       ChunkOffset = bs.readUInt()
       ChunkDecSize = bs.readUInt()
       ChunkComSize = bs.readUInt()
       EoT = bs.tell()
       bs.seek(ChunkOffset, NOESEEK_ABS)
       CompData = bs.readBytes(ChunkComSize)
       DecompressedBuffer += rapi.decompInflate(CompData, ChunkDecSize)
       bs.seek(EoT, NOESEEK_ABS)
   return DecompressedBuffer

def noepyLoadModel(data, mdlList):
	bs = NoeBitStream(decompress_zlib(data))
	baseName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getInputName()))
	ctx = rapi.rpgCreateContext()
	Sign = bs.readUInt()
	Flag = bs.readUInt()
	InfoCount = bs.readUInt()
	ApproxShapeCount = int(InfoCount+3)
	ShapeCount = int(ApproxShapeCount / 4)
	print(ShapeCount);
	bs.seek(12, NOESEEK_ABS)
	
	for i in range(InfoCount):
		ElementType = bs.readUInt()
		ElementOffset = bs.readUInt()
		cPos = bs.tell()
		if ElementType == 0:
		    bs.seek(ElementOffset, NOESEEK_ABS)
		    bs.read(24)
		    ShapeName = bs.readString()
		    rapi.rpgSetName(ShapeName)
		    print(ShapeName)
		elif ElementType == 1:
		    bs.seek(ElementOffset, NOESEEK_ABS)
		    bs.read(12)
		elif ElementType == 4:
		    bs.seek(ElementOffset, NOESEEK_ABS)
		    bs.read(8)
		    VertexCount = bs.readUInt()
		    Flag_0 = bs.readByte()
		    Flag_1 = bs.readByte()
		    Flag_2 = bs.readByte()
		    Flag_3 = bs.readByte()
		    if Flag_2 == 0:
		        VertexBuffer = bs.readBytes(VertexCount*32)
		        rapi.rpgBindPositionBufferOfs(VertexBuffer, noesis.RPGEODATA_FLOAT, 32, 0)
		        rapi.rpgBindNormalBufferOfs(VertexBuffer, noesis.RPGEODATA_FLOAT, 32, 12)
		        rapi.rpgBindUV1BufferOfs(VertexBuffer, noesis.RPGEODATA_FLOAT, 32, 24)
		    elif Flag_2 == 6:
		        VertexBuffer = bs.readBytes(VertexCount*60)
		        rapi.rpgBindPositionBufferOfs(VertexBuffer, noesis.RPGEODATA_FLOAT, 60, 0)
		        rapi.rpgBindNormalBufferOfs(VertexBuffer, noesis.RPGEODATA_FLOAT, 60, 12)
		        rapi.rpgBindUV1BufferOfs(VertexBuffer, noesis.RPGEODATA_FLOAT, 60, 28)
		elif ElementType == 5:
		    bs.seek(ElementOffset, NOESEEK_ABS)
		    bs.read(8)
		    IndexCount = bs.readUInt()
		    IndexBuffer = bs.readBytes(IndexCount*2)
		    rapi.rpgCommitTriangles(IndexBuffer, noesis.RPGEODATA_SHORT, IndexCount, noesis.RPGEO_TRIANGLE, 1)
		bs.seek(cPos, NOESEEK_ABS)	
	mdl = rapi.rpgConstructModel()
	mdlList.append(mdl)
	return 1

image.thumb.png.6cdaf1be417b0197b87aba7768092cbf.png

Edited by h3x3r
  • Thanks 2
Link to comment
Share on other sites

  • Engineer

Can someone please assist me with decompression. Not sure what am i doing wrong. Thanks in advance.

def noepyCheckType(data):
   bs = NoeBitStream(data)
   if len(data) < 20:
      return 0
   if bs.readUInt() != 0x4B504554:
      return 0

   Chunks = bs.readUInt()
   data = bytearray()
   for i in range(0, Chunks):
       ChunkOffset = bs.readUInt()
       ChunkDecSize = bs.readUInt()
       ChunkComSize = bs.readUInt()
       print(ChunkOffset)
       EoT = bs.tell()
       bs.seek(ChunkOffset, NOESEEK_ABS)
       compData = bs.readBytes(ChunkComSize)
       bs.seek(EoT, NOESEEK_ABS)
       data += rapi.decompInflate(compData, ChunkDecSize)
   return data

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...