Jump to content
ShadowDog

TiberianSharp (formerly Luftballon) research thread

Recommended Posts

ShadowDog    0

The other day I was trying to get a decent map editor for Pokemon Blue. I also needed the tilesets for the game, which the map editor loaded from the ROM rather than a .png file. So I tried to figure out how to get it to output the tilesets. My final code wound up being:

 

if (pTileset.Image != null)
{
    Rectangle temprect = new Rectangle(0, 0, 32, (selectedTile * 32) + 32);
    Image tempimg = cropImage(pTileset.Image, temprect); //selectedTile
    tempimg.Save("C:\\Pokemon\\ClassicMap\\tileset" + mapLoader.mapHeader.Tileset + ".png");
}

 

Seriously? That's all it took? I was amazed. I looked into C# a little more, and the more I tried stuff out, the more I liked it. Progress on Luftballon has been halted for a long time, but now I've got the motivation to get back to work on it.

 

Here's where the problem comes: I'm not one of the original developers, nor am I Nyerguds. I know the gist of pretty much everything except accuracy in this game, but I don't know the specifics. The first step, as far as I'm concerned, is to implement some obvious datatypes. For some other games, this might be a problem, but it's not for TD. I know that this is how the basic object chain goes:

 

TechnoType

|->BuildingType

|->UnitType

|->InfantryType

|->AircraftType

 

There may be a few more, but I've forgotten them and they're not extremely important at this stage in the game (though if you know, say, that OverlayType(?) is under technotype, please tell me). What I do need to know is exactly what is defined under each. Also, if you have any information that should be kept in mind in this critical early phase, let me know.

 

Tidbits:

Harvesters follow "All to Hunt".

Share this post


Link to post
Share on other sites
ShadowDog    0

CnC clone. Preferably one that can read the data out of the mix files, but I'll just hardcode versions of the .shps in meantime. I figure by the time I've gotten far enough to where the actual accuracy data matters, either someone will have found it or I'll just beg SubDrag or scarboy to look at the N64 and PS1 versions, respectively, to see if they can figure it out. Of course, I don't know SubDrag that well and barely even know of scarboy, but I'm in the mindset of crossing bridges when I get there rather than before. Basically, I want the TechnoTypes accurate so that I can go: TechnoTypes -> basic map loading -> building upon that, rather than trying to figure out what goes where the whole way through. I could just go with the TibEd data for what each TechnoType descendant has, but I figure I might as well ask where each variable comes from. Though now that I think about, it's not likely very easy to tell where a class inherits it's variables and routines from in ASM, is it?

 

That's the downside to the crossing-the-bridge mentality: you forget simple things because they aren't directly between points A and B.

 

An open note to myself:

When I finally get around to implementing .mix reading support and .shp reading support, first off remember to mimic TD's reading of .mix files (perhaps have a list that checks if a file with that name is already in the list before adding, then actually dynamically adds the resources?), first reading the folder, then the mixes (ask Nyerguds for the order). Then, store the map's "terrain" (I forgot what the game call's it; temperat, desert, snow, winter, and the non-existent "jungle") as an

Image

wherein each "major byte" is the y value and the "minor byte" is the x value. Then use a modified version of my own

BasicClass

's frame drawing code to draw the tile.

Share this post


Link to post
Share on other sites
Nyerguds    43
Though now that I think about, it's not likely very easy to tell where a class inherits it's variables and routines from in ASM, is it?

Well, that's not too hard to see from its table of functions, but I'm not all that familiar with the class names; Hyper knows a lot more about that.

Share this post


Link to post
Share on other sites
ShadowDog    0

I've been trying to contact him, but he never got back to me. I've looked through his past posts here, though, and it seems he frequents PPM. And hasn't been here since last year. So I guess I'll send him a PM over there.

 

By the way:

Oh, and Revo, the xcc map fix doesn't repair maps that got damaged, it's just a conversion fix between the way XCC saves open terrain on maps and the way the original C&C maps have it saved. Older map editors have trouble with the XCC way, that's all. (the original maps use one general code for all open terrain. XCC actually saves all different cells of the "open terrain" 4x5 template)

I don't quite understand this. Could you explain this in a bit more depth?

 

Also, what would the filename be for the heightmaps be in the N64 ROM? Are they just the normal filename, only with a different extension? I'm probably just going to wind up asking SubDrag about CnC64 today. (Yes, I am planning on implementing N64 heightmap support; the only problems I can see with it are that I'll have to implement them into my

BasicClass

, which is no problem, I'll be hardpressed to figure out how to make the cursor go up and down with the terrain (unless it's just a texture, in which case implementing it into

BasicClass

might be less feasible without some creative constructor overload), and how to figure out where a TechnoType should be z-wise).

 

Just wondering, do you actually know what overloading is, Nyer? I just realized that in assembly, an overload of a function would probably be considered a separate function entirely (it's only really the "same" function as far as the name goes). I honestly sort of have a hard time understanding what happens inbetween a high level language and the ASM code.

Share this post


Link to post
Share on other sites
Nyerguds    43

I've been trying to contact him, but he never got back to me. I've looked through his past posts here, though, and it seems he frequents PPM. And hasn't been here since last year. So I guess I'll send him a PM over there.

He hangs around on the IRC chat (freenode.net#cncnet) and on cncnz.

 

By the way:

Oh, and Revo, the xcc map fix doesn't repair maps that got damaged, it's just a conversion fix between the way XCC saves open terrain on maps and the way the original C&C maps have it saved. Older map editors have trouble with the XCC way, that's all. (the original maps use one general code for all open terrain. XCC actually saves all different cells of the "open terrain" 4x5 template)

I don't quite understand this. Could you explain this in a bit more depth?

Right. Map cells in the .bin file are byte pairs that quite simply say [tileset ID, cell from the set]. However, for clear terrain this isn't needed; there's a special code ([FF,00] I think) that can be used for all clear terrain, and the game will automatically tile the entire 4x5 clear terrain block over it (rather than repeating one cell, as you'd expect from repeating the same byte pair).

 

XCC Editor ignores this special 'clear' value though, and actually paves the map with the real tile codes of the clear terrain, cell by cell.

 

Now, the reason I made the tool. The old cc-scen editor I still use from time to time doesn't show map graphics, but just colours each cell according to its terrain type. The problem is that it expects clear terrain to be the special code, and only diplays those as 'green', whereas the actual clear tileset's tiles are shown as white, just like it shows roads, ruins, dirt patches and rivers.

 

This obviously means that maps saved with XCC are displayed completely white (besides the rocks), making it impossible to discern the details of the map.

 

cc-scen.png

This is the editor. Even with roads and rivers in the same colour, it's still quite easy to see the layout. Now imagine that but with all the green turned white :P

So the only thing my tool does is go over all the bytes and replace the actual cells of the Clear terrain by the general code for "nothing".

 

Now you might wonder why I still use this... the answer is simple: it's the only editor available that allows single cell manipulation, and actually shows the bytes for each cell. (in fact, I think this editor was my first encounter with hexadecimal numbers, ever)

 

Also, what would the filename be for the heightmaps be in the N64 ROM? Are they just the normal filename, only with a different extension? I'm probably just going to wind up asking SubDrag about CnC64 today. (Yes, I am planning on implementing N64 heightmap support; the only problems I can see with it are that I'll have to implement them into my
BasicClass

, which is no problem, I'll be hardpressed to figure out how to make the cursor go up and down with the terrain (unless it's just a texture, in which case implementing it into

BasicClass

might be less feasible without some creative constructor overload), and how to figure out where a TechnoType should be z-wise).

Extracting files from a ROM is a huge mess though, involving memory state (emulator 'quick save') dumps.

As you can see in this folder, there's 2 images showing the map and the height map (roughly converted to ascii)

http://nyerguds.arsaneus-design.com/N64Project/editing/

The names of these 2 images are the actual filenames inside the ROM: SCB21EA.IMG for the height map, and SCB21EA.MAP for the map file. I think they used .map for the maps to avoid confusion, because their normal extension, .bin, was already used for the music files.

 

Do note that you can't just extract all height maps and expect them to work anyway; some of the maps were edited for the N64 version of the game, usually to make them easier, to compensate for the harder controls. (I know of 1 so far, but never looked deeper into it, so there could be more.)

 

Also note that the height maps work differently than the normal maps; the heights are put on the corners of the cells, meaning a height map is 65x65.

 

Just wondering, do you actually know what overloading is, Nyer? I just realized that in assembly, an overload of a function would probably be considered a separate function entirely (it's only really the "same" function as far as the name goes). I honestly sort of have a hard time understanding what happens inbetween a high level language and the ASM code.

I program Java  and C# for a living, so yes, I'm all too aware of the systems of OO programming. ASM is really just a hobby :P

Share this post


Link to post
Share on other sites
ShadowDog    0

You program in C#? I could have sworn you said you didn't know how to program. Maybe I was confusing another ASM hacker? I know a surprising amount of them. Also, I'm glad you know C#, because that means if I run into a brick wall (as in, can't get something to work and internet tutorials aren't helping), I can ask you.

 

Speaking of which, certain sections of scb30ea.ini (Nod Spec. Ops. 2, the level I grew up with, thus why it's being used for testing) has keys like "001" rather than "1" in some parts. Do you know of any way to load a key where those two would be treated the same without checking for "1", then "01", then "001"?

 

Also, any clue why [briefing] is 1-indexed while everything else is 0-indexed?

 

I'm working on an API for opening TD/RA stuff, so when I get a bit farther, I'll work on some sort of amalgamation of XCC Editor and CC-Scen. I might even integrate it into TiberianSharp.

 

I PMed SubDrag and asked him to look into the accuracy in the N64 version. He said he'll check in out in a few weeks (he has quite the backlog).

 

P.S. Is creating an unreferenced Vector2 every time you draw a frame a bad idea in C#? I can't think of any other way, but it sort of hurts inside to know I'm creating x number of objects every frame that'll be garbage collected next frame. In my current tests, I'm having no problems, but a remake of Pokemon Blue is hardly a stress test. :P

 

Edit: Nyer, could you send me your database? I have an older copy from about five seconds before I gave up on learning ASM (I'm amazed computers have gotten this far seeing as everything still goes back to X and Y registers or something. Lord). Also, I keep calling you Nyer. Is that annoying? I was listening to the Top Gear Rally theme song for most of this, and that can boost my self confidence a little too high sometimes.

 

Edit2: Nyerguds, where is the accuracy data most likely stored/what would load it? I assume it would be the projectile, because that's how it works in the newer games and makes sense seeing as when I give an inaccurate weapon user and accurate weapon, it's accurate. Then again, it could be on the Weapon (which TibEd lacks data on). I'm going to ask SubDrag to post in this topic so he can get some accurate information rather than just decently-informed speculation.

Share this post


Link to post
Share on other sites
Nyerguds    43

You program in C#? I could have sworn you said you didn't know how to program. Maybe I was confusing another ASM hacker? I know a surprising amount of them. Also, I'm glad you know C#, because that means if I run into a brick wall (as in, can't get something to work and internet tutorials aren't helping), I can ask you.

You must be thinking of Hyper. He's a graphics designer in real life.

 

Speaking of which, certain sections of scb30ea.ini (Nod Spec. Ops. 2, the level I grew up with, thus why it's being used for testing) has keys like "001" rather than "1" in some parts. Do you know of any way to load a key where those two would be treated the same without checking for "1", then "01", then "001"?

Heh. If you're talking about the unit lists and such, the answer to that is actually very simple. They're NOT indexed at all. The game simply reads all keys. So the only requirement there is having a unique key. You could even put both "1" and "001" in there, and it'll still read them both.

 

Also, any clue why [briefing] is 1-indexed while everything else is 0-indexed?

I kinda just answered that... the rest isn't indexed at all. Except for the [base] section. Though I do believe the [base] section is indeed 0-indexed.

 

I'm working on an API for opening TD/RA stuff, so when I get a bit farther, I'll work on some sort of amalgamation of XCC Editor and CC-Scen. I might even integrate it into TiberianSharp.

Fun fact... the original game actually still contains some leftovers of an inbuilt map editor mode :)

 

I PMed SubDrag and asked him to look into the accuracy in the N64 version. He said he'll check in out in a few weeks (he has quite the backlog).

Accuracy?

 

P.S. Is creating an unreferenced Vector2 every time you draw a frame a bad idea in C#? I can't think of any other way, but it sort of hurts inside to know I'm creating x number of objects every frame that'll be garbage collected next frame. In my current tests, I'm having no problems, but a remake of Pokemon Blue is hardly a stress test. :P

To do what, exactly? As far as I know, most stuff in C&C can simply be kept in one global list in the Map object.

 

Edit: Nyer, could you send me your database? I have an older copy from about five seconds before I gave up on learning ASM

Sure. I'll send a PM. Do note that the exe that goes with it is the 1.06c revision 2 one, which will probably not run on the currently released version. I could always give you a full beta though.

 

(I'm amazed computers have gotten this far seeing as everything still goes back to X and Y registers or something. Lord).

Well, chips may have gotten faster, but the CPU still executes exactly the same commands as the first 8086 computer :P

 

Also, I keep calling you Nyer. Is that annoying? I was listening to the Top Gear Rally theme song for most of this, and that can boost my self confidence a little too high sometimes.

lol, no problems there. It's what everybody calls me :)

 

Edit2: Nyerguds, where is the accuracy data most likely stored/what would load it? I assume it would be the projectile, because that's how it works in the newer games and makes sense seeing as when I give an inaccurate weapon user and accurate weapon, it's accurate. Then again, it could be on the Weapon (which TibEd lacks data on). I'm going to ask SubDrag to post in this topic so he can get some accurate information rather than just decently-informed speculation.

I know the projectiles (Bullet class) contain a flag to make them inaccurate, but that's all I know. And it's just a boolean, not an inaccuracy value.

Share this post


Link to post
Share on other sites
ShadowDog    0

The Vector2 thing is about drawing the sprites.

 

I remember you saying something about knowing how the accuracy or the shooting or something works. Is there anything you don't have the slightest clue about and need a little help with?

Share this post


Link to post
Share on other sites
Nyerguds    43

umm... the only thing I know about the accuracy is that the randomization algorithms for them are pseudo-randoms that work in such a way that they're the same on all players in a multiplayer game without needing to send any information about them. Which is kinda scary :P

 

As for the vector thing, do you mean for storing unit frames? As far as I know, the game doesn't store them. It just reads the correct frame from preloaded files at the moment it needs it. So basically the equivalent of

 

unit.getSHPFile().readFrame(12);

 

Share this post


Link to post
Share on other sites
ShadowDog    0

So are all inaccurate weapons just as inaccurate?

 

Also, what I'm referring to is how I display all my sprites:

        public void draw_sprite(int X, int Y, Texture2D tex)
        {
            spriteBatch.Draw(tex, new Vector2(X, Y)], Color.White);
        }
        public void draw_sprite(int X, int Y, Texture2D tex, int frame)
        {
            draw_sprite(X, Y, default_size_x, default_size_y, default_size_x, default_size_y, tex, frame);
        }
        public void draw_sprite(int X, int Y, int W, int H, Texture2D tex, int frame)
        {
            draw_sprite(X, Y, W, H, W, H, tex, frame);
        }
        public void draw_sprite(int X, int Y, int W, int H, int W2, int H2, Texture2D tex, int frame)
        {
            int Y2 = frame / (tex.Width / W);
            int X2 = frame % (tex.Width / W);
            spriteBatch.Draw(
                tex,
                new Rectangle(X, Y, W2, H2), //Destination
                new Rectangle(X2 * W, Y2 * H, W, H), //Source
                Color.White
            );
        }

 

This isn't horrible code, is it? Also, I know I could probably get a miniscule speed up by not making two of those overloads redirects to another overload, but I don't think I'd get anything noticeable unless I had a lot of things to draw.

 

Anyway, my main bottleneck right now is remembering how much of a PITA it was to make that tileset for Luftballon/DesertFox, and knowing how much of a PITA it will be to write a .mix reader.

 

A quick note on implementation: I'm planning on allowing indefinitely-sized (so long as it's a square) maps. This is so I don't have to tell the difference between a Sole Survivor and a TD map (since TD conforms to that anyway). I'm also making maps an instanced class just in case I think of a use for having 2 maps loaded. I'm going to eventually put in a SS mode (which would also work in RA mode). As such, I'm planning on implementing 32-player matches, and having the UI limit it to 2-4/6 (depending on the map) for TD/RA and 32 for SS. The idea being that SS shouldn't be treated that differently from TD/RA's standard multiplayer.

 

In fact, I should probably define the engine's goals:

[*]Accurately play TD/RA/SS/Dune 2 (TD and aspects of RA and SS for first release)

[*]Modernize what should be modernized; ie. load square maps of arbitrary size rather than just 64x64, allow (not force) use of better AI; load data from .ini files rather than executable; not randomly deciding that x-gameplay-aspect is outdated or that the sidebar should be on the bottom.

[*]Act as a general Westwood-style RTS engine

[*]Be compatible with mods (to a sane degree; executable-hack-requiring mods don't count)

[*]Stuff. Specifically, stuff not feasible via pure x86 ASM.

[*]Fuck "CnC" 4.

Share this post


Link to post
Share on other sites
Nyerguds    43

I really don't get what this code is or does without any references. What exactly is this used for? What type is that "spritebatch"? Is that Draw() function your own function or something of an existing object type?

 

Also, I don't really know what a Vector2 is. I never used vectors, except in assembler... don't even know what the difference with a normal (Array)List would be, or the difference between Vector and Vector2. If it just needs an IEnumerable, a normal array should suffice.

 

btw, I think there's an error in that "new Vector2(X, Y)]". I can't imagine any syntax with just a closing bracket :P

 

 

oh, and as for "stuff not feasible via pure x86 ASM", actually, adding a rules.ini is perfectly feasible :P

Share this post


Link to post
Share on other sites
ShadowDog    0

You don't know what SpriteBatch is? I assume you generally use WinForms (I love WinForms). I'm using XNA Framework 4.0. The bracket is from when I was trying to bold some code, but the code tag doesn't parse other tags inside of it.

 

I was thinking more about the changing the units' stats via the mission's .ini file when I said that. Do you know if it's possible to use WWLib via C#? I retrospect, I'm probably not going to use it, but I'm interested in whether it's possible.

Share this post


Link to post
Share on other sites
Nyerguds    43

Nope, not a clue what SpriteBatch is, and seeing as the only occurence of the word there is a VARIABLE and not a class, I had no way of knowing there was even a class called that.

 

And no, I've never worked with XNA (or, anything else than backend and forms, for that matter) on C#.

 

As for WWLib, um, I dunno, where would you get it? As far as I know it's built into the games, and never as external library. Though if you got it as dll (I heard somewhere that a lot of it is in some leaked Renegade code, so it's possible to make a dll from that), I don't see why not. I think it's possible to combine different programming languages in the same project anyway.

Share this post


Link to post
Share on other sites
ShadowDog    0

What do you do in C#? I want to know so I quit assuming you know what I'm referring to whenever it's something that's XNA/WinForms specific.

 

Also, there's leaked Renegade code? I'll have to investigate that (first thing to investigate: Does EA care?)

 

Edit: Legal problems. Natch.

 

Edit2: Firefox, quit acting stupid and actually send the edit. Now Hyper ninja'd me.

Share this post


Link to post
Share on other sites
CCHyper    0

WWLib -> Westwood Library. Was Westwoods base code for every game they wrote. It contains file handling, memory management, vector and maths algo's, network code, basic behavior and so on.

 

There was some Renegade source code released by someone who worked on the Tiberian Technologies project for Renegade. The project was given some source code from the game to help understand how the game worked and in turn, develop new rendering and network code to replace the existing engines.

 

But we cant really talk about this publicly, as EA got there knickers in a twist when it was leaked out of the project.

 

Can you read ASM well? Or perhaps understand pseudo enough to rewrite? Aswell as common compiler optimizations, you should be able to recreate such classes without the source, this is what we do with the Ares and Orca projects for Yuris Revenge and Tiberian Sun respectfully.

Share this post


Link to post
Share on other sites
ShadowDog    0

Orca? There's an Ares for TS? Cool.

 

Wait, memory management? TD, RA, SS, TS, RA2, even Renegade were written in C? They never went to C++? Is that why it runs so fast?

Share this post


Link to post
Share on other sites
CCHyper    0

Orca is what im working on for Tiberian Sun, its my injection project based on the Syringe package

 

Share this post


Link to post
Share on other sites
Nyerguds    43

Well, my thesis/internship project for university college was a C# desktop app that automatically scanned content from Word documents and uploaded it to an online platform. More specifically, it is a tool for teachers to automate the creation of assessments on the school's online platform.

 

Besides that, I've also completely rewritten CCSetup in C#, and this rewrite includes my very own ini file reading and writing system. I've recently ported that code to Java too. There's quite some pics of the new ccsetup on the ModDB site of the 1.06 patch. I've also made a radar colour editor for TS/RA2 SHP files, and, just for fun, a program to unlock protected mixfiles (but I never released or even announced I made such a thing :P )

 

At this moment though, I'm working to make a Java program to be the successor of my internship project (they hired me :) ), and at the moment that's mostly made up of GUI and database (SQLite) operations. I've also been working again on a java game which was originally made as big project in my first year at the university college. I made a thread about it here. The topic on cncnz I linked to also has a link to the source of that game, though it's mostly in Dutch :dry:

 

[edit]

 

Oh, I also wrote a Dune II game data editor in Pascal. With a text UI :D

Share this post


Link to post
Share on other sites
ShadowDog    0

I'm glad that you mentioned Pascal, because the file format guide I'm using refers to a Pascal longint. I know that an x86 int and long are the same size, so I'm wondering if Pascal has self-imposed sizes, or if the person just arbitrarily put longint instead of int. Honestly all this file format reading can be confusing when people say, for example, word instead of 2 bytes.

 

Hyper, do you have a Bug Tracker? If not, I'll set up Mantis on my site.

Share this post


Link to post
Share on other sites
Nyerguds    43

Well, basically, in assembler

-byte = 1 byte

-word = 2 bytes

-dword ('double word') = 4 bytes.

 

As for longint, I think the name comes from the specific 32-bit "longer" int at the moment the standard for int (on 16-bit architecture) was still 16 bit.

 

Just googled it. "LongInt is a Borland Pascal extension. Borland Pascal defines LongInt as a 32-bit signed integer type." However, some more recent compilers like GNU Pascal or Freepascal may use it as 64-bit integer. It's basically a problem with evolution... on 16-bit architectures the standard "int" is 2 bytes, on 32-bit it became 4 bytes, and on 64-bit it'll become 8 bytes. It's simply a matter of how much the standard CPU registers hold. I'm just glad they finally got actual bit-specified types (Int16, Int32, Int64) in modern programming languages.

 

In old references, the Borland standard holds though, and you can safely assume longint simply means 32-bit.

Share this post


Link to post
Share on other sites
ShadowDog    0

Of course, I forgot CnC was 16-bit. IIRC, 8-bits make up one byte, 16-bits would be 2 bytes, and 32 would be 4. Makes sense now. Thank you, Nyer.

 

Oh, and I just realized that qword = quad-word. Obvious, but not as obvious when you don't know what a dword is. :)

 

Edit:

 

public class MultiString
{
    public string Eng = ""; //!HACK
    public string Ger = ""; //!HACK
    public string Spa = ""; //!HACK
    public string Fre = ""; //!HACK
    public string String
    {
        get
        {
            string aaa = "";
            BasicClass.Languages.ForEach(delegate(String lang)
            {
                string bbb = GetStringLang(lang);
                if (bbb != "")
                {
                    aaa = bbb;
                }
            });
            if (aaa != "")
            {
                return GetStringLang(aaa);
            }
            if (BasicClass.Production)
            {
                return "";
            }
            else
            {
                return "*INVALID*";
            }
        }
    }
    public string GetStringLang(string lang)
    {
        if (lang == "Eng")
        {
            return Eng;
        }
        else if (lang == "Ger")
        {
            return Ger;
        }
        else if (lang == "Spa")
        {
            return Spa;
        }
        else if (lang == "Fre")
        {
            return Fre;
        }
        if (BasicClass.Production)
        {
            return "";
        }
        else
        {
            return "*INVALID*";
        }
    }
}

 

That get{} construct (is that the term?) seems really handy, though admittedly I see no point in it as opposed to a procedure. However, what I really want is some way to have a list formatted like this:

 

"Eng" = "Hi!",

"Ger" = "Guten tag or whatever",

"Fre" = "However the heck those Fremen say hello",

"Spa" = "iHola senior!" //As you can tell, I got a D in Spanish. Mainly because I can't remember where that darn... "marky thing" goes...

 

And return the later part based off the former. In BYOND, you make the list like this:

var whatever = list("a" = "c","b" = "d")

and access the later part by either going:

whatever[1] //1-indexed, IIRC

or:

whatever["a"]

with it returning null whenever you try to access something that isn't there. Is there anything that easy to use in C#, or am I going to have to have 2 lists, loop through the first list hoping to find string A, and if it's there, return the string at the same position in list B? Because if not, I'll make an API for that (in the last couple of days, I've done lots of stuff under the hood, but it's mainly been stuff like making my APIs easier to use and more child-proof; defensive programming is the way to go, because you never know when you'll be reduced to the intelligence level of a garden hose).

 

Edit2: Are all the mouse cursors displayed from the center with the exception of the generic mouse, or is there some sort of table I'll need to mimic?

 

Edit3: This is what I'm getting for conquer.mix

NumFiles: 266

DataSize: 50690

 

But it should be 2459769 instead of 50690. Can you figure out what's wrong? This is conquer.mix, by the way.

 

int NumFiles  = (mixfile[1] * 256) + mixfile[0];
Console.WriteLine("NumFiles: " + NumFiles);
int DataSize = (mixfile[5] * (256 * 3)) + (mixfile[4] * (256 * 2)) + (mixfile[3] * 256) + mixfile[2];
Console.WriteLine("DataSize: " + DataSize);

Share this post


Link to post
Share on other sites
Nyerguds    43

C&C isn't 16 bit. Has never been 16 bit either. But most programs written for it back in those days were.

Share this post


Link to post
Share on other sites
ShadowDog    0

Wasn't the DOS version (or was that just the installer)? Or am I confusing what 16-bit actually means?

 

Edit: I figured out the problem with the MIX headers: I was multiplying 256 by 2, 3, etc, instead of exponential...ing it by that much.

 

For the record (in case future peoples of the futures want something to reference when they discuss TD's .mix file format, because you know that'll be all the rage in A.D. 2101), TD has it's high bytes last. Which was that, big endian or little endian? I also get those two mixed up, no pun intended.

 

Edit2:

 

What are those last 3191 bytes in conquer.mix that supposedly aren't data for? 6 bytes for the header, 2456578 for the data, and the total file size is 2459775 bytes. Odd, isn't it?

Share this post


Link to post
Share on other sites
Nyerguds    43

As for your data stuff:

 

-In the language system I built into C&C95 I don't have an internal list of languages. I parse the 3-character language string from the ini straight into the strings "lang_???.mix" and "lang_???.ini" to read a bunch of file REPLACEMENTS. Meaning that if you start in french, the English version of the strings file, sidebar buttons and game icons are simply not read at all. There is no list, and no language detection logic in the game.

Have you looked into the indexing system used in the conquer.eng file? It's pretty straightforward. I think it was four lines of assembler to get the string position if you got the start of the file and the string index.

 

-I haven't really looked into mix headers, except briefly into the TS ones, and that was only to fix them if they were broken as "mix protection".

 

-mouse cursors: Not a clue, really. I've never really looked into that. I kinda expect that to all be hardcoded in the cursor code, setting the click point at the moment it loads the cursor.

 

[edit]

 

I mess up big and little endian too, but it's actually pretty simple... look at the number "123". The "1" at the front is "100", so it's the largest number. The "3" at the end is the smallest number. So the end (since we read from left to right) is the smallest (least significant) number, which makes it little-endian.

 

C&C uses big-endian, where a hexadecimal number 12345678 becomes bytes 78 56 34 12

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.

  • Recently Browsing   0 members

    No registered users viewing this page.

×