don't click here

The SX Engine

Discussion in 'Engineering & Reverse Engineering' started by Uhyve, Dec 2, 2010.

Thread Status:
Not open for further replies.
  1. SANiK

    SANiK

    Tech Member
    413
    0
    16
    OpenGL just draws, nothing else. If anything look up the .obj format. It is pretty quick and painless to implement.

    Sonic X-treme has two occasions where renderflags occur. They occur at the Texture level and the Cube level.
    At the texture level things like FlipH and Rotate get applied or baked to the actual texture image.
    At the cube level they get applied to the UVs.

    Playing around with texture scrolling, it seems to be that the format is: Color(?, Velocity, Angle)
    The angle and velocity look to be both unsigned values from 0 to 256.
    The Angle must be converted to degrees. I am still tinkering with this.

    There is a couple of things to consider such as the order of operations:
    UVFlipH then UVFlipY then UVRotate then UVScroll is what I am currently using, but I still see some bad UVs.
    I will need to look into it further.

    I was looking at the ACT_Path in JADE1 like Energy was in the previous topic:
    HexDump "01 00 03 00 46 00 00 00 00 00 01 3a 80 0d 00 09 80 04 00 c0 b1 13 00 00 80 0e 00 09 80 04 00 c0 e4 46 00 00 80 10 00 0a 80 04 00 a0 ff ff 00 00 80 13 00 0e 80 01 00 40 ff ff 00 00 80 06 00 15 80 01 00 80 ff ff 00 00 80 17 00 09 80 00 00 80 ff ff"

    I split it up into header and data. There are different versions of paths, but the later one follows mostly this scheme.

    Header:
    0100 0300 4600 0000 0000 013a

    The value in red is the data size which is 70. Energy seems to have included the 013a as part of the data when it is part of the header.

    Data:
    80 0d 00 09 80 04 00 c0 b1 13 00 00
    80 0e 00 09 80 04 00 c0 e4 46 00 00
    80 10 00 0a 80 04 00 a0 ff ff 00 00
    80 13 00 0e 80 01 00 40 ff ff 00 00
    80 06 00 15 80 01 00 80 ff ff 00 00
    80 17 00 09 80 00 00 80 ff ff

    The above has a pattern, but there are a couple of things to consider:
    1) Path data and other HexDump data may be in the format:
    Instr Par0 Par1 Par2... and may not necessarily have a pattern.

    2) 00 00 is missing at the end to complete the pattern, but it might be an implied 00 00 since if the system expects to read 12 byte slices anything out of bounds may be configured to read as 00?

    3) If the data is X Y Z, it might be word word word or byte byte byte.
    Furthermore it is highly likely there is an orientation vector to specify 'up' or as physicists call it, a normal.
    This might be encoded as word word word or byte byte byte, or possibly an angle.
    There may also be a velocity value encoded as well?

    Another interesting HexDump is not a path but an action definition called "moveIO_1" in RED1
    HexDump "01 00 03 00 38 00 00 00 00 04 00 04 10 00 00 00 17 10 01 01 20 00 00 00 17 04 01 01 20 00 00 00 03 21 18 10 00 00 00 00 00 01 10 01 00 00 00 00 00 20 10 01 00 00 00 00 00 01 10 01 00 00 00 00 00 20 10 01"

    Header:
    0100 0300 3800 0000 0004 0004

    Data:
    10 00 00 00 17 10 01 01
    20 00 00 00 17 04 01 01
    20 00 00 00 03 21 18 10
    00 00 00 00 00 01 10 01 00 00 00 00 00 20 10 01
    00 00 00 00 00 01 10 01 00 00 00 00 00 20 10 01

    In the Red Sands video it is the platform going in and out at the start of the video. The format is noticeably different.
    It might have to do with the 0004 0004, changing the type of HexDump format that follows.

    Furthermore I would expect paths to be lists of connecting nodes and nothing more, whilst I expect action definitions having some type of code to them.
    The code can be something like IfEnter CreateCube Type, X, Y, Z.
    It might be possible the moveIO_1 HexDump references a path and the in/out motion may not necessarily be stored within the local HexDump.

    -------------------------------------------------------------------------------------------------------------------

    Looking at the JADE1, there is that switch that Sonic hits:
    NEW_CUBE "SWITCH_1"
    {
    Value 026,41 //Swap
    HexDump "0100030008000000000400341000000001000801" //Action Definitons
    }

    NEW_CUBE "SWITCH_1A!"
    {
    Value 026,40 //Swap
    HexDump "010003001e000000000000220f0001010002000009000801000200000100100200000000100
    001010002" //Action Definitons
    }

    "SWITCH_1" upon getting hit in the video changes to "SWITCH_1A!"
    The Swap value is probably a parameter that gets passed to an instruction in the HexDump?

    "SWITCH_1A!" being complicated most likely calls the path to be made at a certain location?
    Or might "SWITCH_1" be what creates the path?

    If we take the action definition for "SWITCH_1 and break it down:

    Header:
    0100 0300 0800 0000 0004 0034

    Data:
    10 00 00 00 01 00 08 01

    Somehow the above encodes to "Change current cube to swap cube when sonic jumps into it"
    I'm starting to think the header's 0004 0034 decides Sonic's action to activate the HexDump,
    or Sonic's action might be encoded within the HexDump itself.

    It also might be:
    aa bb cc dd ee gg hh kk
    10 00 00 00 01 00 08 01

    aa = Function to do, 0x10 = swap?
    bb = Parameter A (unused)
    cc = Parameter B (unused)
    dd = Parameter C (unused)

    eegg = When Actor/Cube

    hhkk = Jumps into front face?
     
  2. SANiK

    SANiK

    Tech Member
    413
    0
    16
    So I got the coordinate based stuff working for paths.
    [​IMG]

    0100 0300 8100 0000 0001 00fe

    xx xx yy yy zz zz
    14 00 04 80 04 00 00 b1 13 00 00 00 //Segment 0
    15 00 04 80 04 00 00 23 37 00 00 00 //Segment 1
    18 00 04 80 04 e2 d7 85 5e 00 00 00 //Segment 2
    1a 00 07 80 03 00 c0 07 7e 00 00 00 //Segment 3
    1a 00 0b 80 03 0e 8d 7a a1 00 00 00 //Segment 4
    17 00 0c 80 03 1e 68 fc c0 00 00 00 //Segment 5
    14 00 0a 80 04 00 20 8d dc 00 00 00 //Segment 6
    16 00 08 80 04 00 00 ff ff 00 00 00 //Segment 7
    19 00 08 80 04 00 00 ff ff 00 00 00 //Segment 8
    1c 00 08 80 04 1d ed ff ff 00 00 80 //Segment 9
    1c 00 07 80 04 1d ed ff ff //Segment 10, 00 00 00 seems to be implied

    The last 6 bytes are probably 3 normals in the form of bytes and 3 flags, or 3 normals in the form of fixed16.

    Coordinates are unsigned absolute fixed16 positions on the map. Values are Motorola Big Endian and not little endian.
    To convert from fixed16 to float divide by 256.0f.
     
  3. Uhyve

    Uhyve

    Master Procrastinator Member
    46
    0
    6
    Huddersfield, England
    SX Engine
    :psyduck:
    That... is amazing. You figured that out really quickly. There's not really much for me to say since it all makes perfect sense. Though I'm alittle clueless about what "swap" refers to, obviously it's in the cube definition aswell, but I don't really understand what is does there either.

    Ah, didn't realize, I've never used OpenGL, figured it would be essentially the same as DirectX. I was thinking of writing a model importer/extractor at some point, Andrew75 suggested Collada because it's an open standard.

    I only just realised you mentioned that in your code. It probably should have occurred to me, I've just been adding flags for both blocks and textures as I figure them out, didn't realise that they were the same. Another place where some sort of database would come in handy really.

    Gonna need to put some time in this week. Don't like that you've managed to get so much figured out and I've... managed to complete Mass Effect.
     
  4. SANiK

    SANiK

    Tech Member
    413
    0
    16
    Well if each cube has an ID then you can use "swap" to make a cube change to another cube upon a certain event happening.
    So if you have a ring, and an empty cube is '0', then you can set the ring's swap to 0 and have a HexDump event that triggers the swap once Sonic touches the ring cube.

    I think the way you are doing it might be best if you want to make a game, which is to generate the internal format for the map.

    Currently I load the DEF into a database and I draw directly from the database which is slow, but since the database is 1:1 with the DEF file format, I can easily test different variations when reverse engineering.
     
  5. Uhyve

    Uhyve

    Master Procrastinator Member
    46
    0
    6
    Huddersfield, England
    SX Engine
    Ohh, that makes sense. Yeah, figured it was probably something like that, just wanted to make sure.

    Cool, no reason to do extra work, heh.
     
  6. Uhyve

    Uhyve

    Master Procrastinator Member
    46
    0
    6
    Huddersfield, England
    SX Engine
    Was messing around alittle with my code today, and I got frame based animation implemented:


    The cleanup is pretty much done for now, so I'll probably start adding more features again soon. Though this animation is still kinda funky on some levels, can cause some memory access violations (Edit: fixed) and I've guessed an animation framerate of 30fps, which looks a bit fast.
     
  7. That looks AMAZING! We are so close to a playable Xtreme its not funny!

    Awesome job!
     
  8. Skeledroid

    Skeledroid

    Member
    227
    0
    0
    thiiiiiiiiiiiiiiiiiiiiiiiis. so close to playing the 3d game we've always wanted (at least for me, I'd rather play this than sonic adventure).
     
  9. Andrew75

    Andrew75

    Technical Artist Member
    2,030
    107
    43
    Project AXSX(Sonic Xtreme) + Misc Projects
    Seems our projects are working from opposite ends, you have all the visuals for the PC levels,
    and we have a playable game engine with level rotations, and some E3 level layout recreations as well as a proper fisheye. and some of the boss engine done.
    seems merging the 2 projects would be the thing to do. ^__^
     
  10. Uhyve

    Uhyve

    Master Procrastinator Member
    46
    0
    6
    Huddersfield, England
    SX Engine
    Hehe, thanks for the nice responses, it helps when programming, makes it seem less like I'm just burning time.
     
  11. Wow, is it just me, or does Sonic X-treme resemble Minecraft?

    ....

    Could someone with Minecraft begin working on converting Sonic X-treme levels over now? =P
     
  12. SANiK

    SANiK

    Tech Member
    413
    0
    16
    I see you have restructured the code. It looks nice.

    I was looking through some of it, and I wanted to say that you don't need to do the following,
    Code (Text):
    1. int renderFlag = atoi(temp.c_str());
    2.  
    3. while (renderFlag >= 1)
    4. {
    5.         int tempPower = 1;
    6.  
    7. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while (tempPower * 2 <= renderFlag)
    8. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
    9. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempPower = tempPower * 2;
    10. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
    11.  
    12. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(tempPower == 262144) // this is guessed, obviously.
    13. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
    14. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System->usedCubes[System->currentCube].innerMirror = true;
    15. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
    16.  
    17. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(tempPower == 256)
    18. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
    19. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System->usedCubes[System->currentCube].mirrored = true;
    20. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
    21.  
    22. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(tempPower == 16)
    23. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
    24. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System->usedCubes[System->currentCube].transparent = true;
    25. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
    26. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    27. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renderFlag = renderFlag - tempPower;
    28. }
    You can just do it like this,
    Code (Text):
    1. int renderFlag = atoi(temp.c_str());
    2.  
    3. if(renderFlag&nbsp;&nbsp;& 256)
    4. {
    5. &nbsp;&nbsp;System->usedCubes[System->currentCube].mirrored = true;
    6. }
    7.  
    8. if(renderFlag & 16)
    9. {
    10. &nbsp;&nbsp;System->usedCubes[System->currentCube].transparent = true;
    11. }
    & in C is the binary 'and' operator.
    0 & 0 = 0
    0 & 1 = 0
    1 & 0 = 0
    1 & 1 = 1

    It gives 1 when both sides have a 1 in the bit. So 16 in binary is 10000. If the renderflag is 11010100, and you do & 10000, you get:
    11010100 renderflags anded with
    00010000 the value 16
    ----------- gives you...
    00010000
     
  13. Ollie

    Ollie

    DIGGY DIGGY HOLE Member
    I'd love to see the playability side of things implemented recreating the full PC Version remade. How possible would that be though Andrew75? Assuming that your project isn't in the same programming language so you'd have to start pretty much from scratch right?

    Don't give me ideas like that :(
     
  14. Uhyve

    Uhyve

    Master Procrastinator Member
    46
    0
    6
    Huddersfield, England
    SX Engine
    Ohh, that's super useful. It wasn't until I started this project that I released how little I knew about programming.

    Huh, I don't remember why I had that innermirror variable... oh, it was for the trees on Crystal, I couldn't figure out how they were symmetrical, so I kinda guessed, probably should take another look at that now that you've explained the level format pretty thoroughly.

    Yeah, probably pretty difficult, seems like the best way of doing things would be for me to work on the exporting function alittle more so he could just use the levels without having to deal with the DEF and PCX files. I mean, there'd still be a fair amount of work turning the outputted models into levels but still, would be cool.

    Edit: Oh, and thank you for those clean up suggestions SANiK.
     
  15. Skeledroid

    Skeledroid

    Member
    227
    0
    0
    personally, I think it's really neat using the original DEF/PCX files -- makes it feel more official. not really the best route with modern technologies though. :P
     
  16. Uhyve

    Uhyve

    Master Procrastinator Member
    46
    0
    6
    Huddersfield, England
    SX Engine
    Hehe, I'll admit, I partially went this route because I'm useless when it comes to arty kinda stuff, so I figured it's all already there, might aswell use it. But yeah, I kinda like using all of the original files, though it'd actually be a very easy edit to make the engine check for a HD PNG file before looking for the old PCX based textures, so I suppose at least HD texture packs are a possibility.
     
  17. Skeledroid

    Skeledroid

    Member
    227
    0
    0
    well, once you've got everything down as far as loading the PCX files or whatever... you could add the hq4x or scale4x algorithm. so if the user enables a scaling algorithm, it just applies to the PCX textures (as well as texture packs). by default, I imagine everyone would prefer the original look. I know I do. :O
     
  18. Uhyve

    Uhyve

    Master Procrastinator Member
    46
    0
    6
    Huddersfield, England
    SX Engine
    Hadn't thought of that, texture scaling could be interesting. But yeah, I'd probably end up preferring the original look aswell, so used the blocky textures now.

    PS Dunno if people are interested at this point, but I've uploaded a compiled build:
    http://code.google.com/p/sx-engine/downloads/list
     
  19. Mad Echidna

    Mad Echidna

    Gone Oldbie
    5,219
    0
    0
    Brilliant, absolutely brilliant. You've done beautiful work. Finally seeing the game alive is so amazing! Finally a dream realized
     
  20. kazade

    kazade

    Member
    64
    0
    0
    A 2D Physics Engine
    If anyone wants to try this under Wine, you need to install the D3DX dlls using Winetricks. I got as far as attempting to load from the folder that I don't have. Where do I get the level files?
     
Thread Status:
Not open for further replies.