Jump to content
OGXbox.com

Meerjel01’s XTL Tutorials


Meerjel01
 Share

Recommended Posts

This topic is gonna be about programming for the Original Xbox using the official Xbox Developer Kit! Using DirectX 8. Since I’m capable of it I decided to make my own tutorial series for people to learn from. Let’s begin!

First you’ll need to download and install the tools. I’m not gonna instruct you on the process of getting the DevKit to work or where to get it. This is just a C++ tutorial. After you’ve opened VS2003, make a new project. There’s a preset for Xbox developers in the New Project window, use it, make it an empty game application and create a .cpp file. In the file, include the xtl library.

 

#inlcude <xtl.h>

The main method should also look like this.

Void __cdecl main() { }

There’s a site dedicated to DirectX/C++ development so use that first if you don’t know how the basics of the XTL works.

https://xbdev.net/tuts/tuts.php

 

After that, I’m gonna tell you how I do things.

  • Like 5
Link to comment
Share on other sites

When you’re about to program a game engine, make it as organized as you can. Make a lot of classes. This time I’m gonna tell you to make a game class that’ll contain the data for the actual gameplay. It’s recommended to do that. Make a game.h file and a class called CGame (Or how you like it to be called). It’s gonna contain the necessities for your game to run like update functions (EarlyUpdate(), Update(), LateUpdate()) and the render function(You probably only need one).

You can keep the actual game loop in the main.cpp file but you can decide if you want the game’s functions to be called in the while loop in main or inside the actual game.

 

Example on calling game funcs in main.cpp (You can find the DirectX draw methods in the website I linked)

While(true)

{

game.EarlyUpdate();



game.Update();

(DirectX Draw Start)



game.Render();



(DirectX Draw End)



game.LateUpdate();

}

 

Example on calling game funcs on the actual game.

While(true)

{

if(game->loop() == 0)

break;

}

The draw functions is in the CGame class so the main.cpp method is highly still valid here.

Also keep making functions and variables for everything needed because that’s what makes a game run good enough OR great. Don't repeat code, use static methods!

  • Like 1
Link to comment
Share on other sites

When making a game from it’s own source code, it is viable to have some prebuilt functions to go with it so you don’t repeat unnecessarily. Classes is a thing you can use a lot but not a function if it already exists. Don’t invent the wheel when it’s already made.

For example. A non-void function.

float clamp(float v, float low, float high)
{
	return v <= low ? low : v <= high ? v : high;
}

 

Use this when you want to stop a floating value from going above or below a certain value. This can be useful in many cases when needed. Also

float distance(D3DXVECTOR3 a, D3DXVECTOR3 b)
{
	return D3DXVec3Length(&(b - a));
}

 

Use this to get the distance between 2 points. You could use the code after ”return” but it’ll be wiser not to since that would add more unnecessary space to the program. Even when you think it’s not worth doing it, it’s still important to work hard for something to work the best.

  • Like 1
Link to comment
Share on other sites

Hi, sorry for bothering you. I'm currently backporting Dirty Regions rendering from Kodi to XBMC4Xbox and I had a greate success in markin what part of screen needs re-rendering. The part which I don't know how to reimplement is part where I should tell GPU which part of screen needs to be re-rendered. On the picture below you can see 4 commented lines. Things which DX8 is missing are:

  • D3DRS_SCISSORTESTENABLE
  • SetScissorRect()

Do you maybe know how could I reimplement these two lines in DX8? Code from Kodi is using DX9.

Screenshot_20230321_012708.png

Link to comment
Share on other sites

Word of advice. When you want to draw something on the screen and are using multiple classes that shares Direct3DDevice, like this.

bool Init(IDirect3DDevice8** device)
{
	directDevice = *device;
  	
  	// Rest of the code
  
  	return true;
}

It is important to use the more global variable (directDevice) later on. Not the one specific for the function (device). This would make the object unusable since the device isn't used by the application fully. It's like feeding someone an extinct animal. It won't come back.

I say this cause I've had this issue lately. Remember to look closely at your code before compiling/test it.

  • Like 1
Link to comment
Share on other sites

On 3/20/2023 at 7:34 PM, antonic901 said:

Hi, sorry for bothering you. I'm currently backporting Dirty Regions rendering from Kodi to XBMC4Xbox and I had a greate success in markin what part of screen needs re-rendering. The part which I don't know how to reimplement is part where I should tell GPU which part of screen needs to be re-rendered. On the picture below you can see 4 commented lines. Things which DX8 is missing are:

  • D3DRS_SCISSORTESTENABLE
  • SetScissorRect()

Do you maybe know how could I reimplement these two lines in DX8? Code from Kodi is using DX9.

Screenshot_20230321_012708.png

How many calls are made to these two subroutines?

 

I don't think there is an equivalent operation available with a GPU that supports DirectX 8. It is a hardware operation supported only on GPUs that support version 9 or later.

Link to comment
Share on other sites

7 hours ago, KaosEngineer said:

How many calls are made to these two subroutines?

 

I don't think there is an equivalent operation available with a GPU that supports DirectX 8. It is a hardware operation supported only on GPUs that support version 9 or later.

Well basically all the time, whenever something on screen has chagned. Before Dirty Regions, when something changes on screen a whole viewport was re-rendered. So when you are appying animations for each anim frame a whole viewport was re-rendering. That's the reason why CPU usage is always high even if there aren't any changes on screen. You can find more info here. With dirty regions, when something has changed there is a algorithm which calculates which part of screen has changed and needs re-rendering (that is represented with CRect instance). So you pass that CRect instance (which is basically 2d square of screen which needs re-rendering) and GPU only re-render that area. So right know I have implemented all that logic and algorithms and now I "only" need a way to tell GPU to render only that part of screen. But yeah, maybe you are right, D3DRS_SCISSORTESTENABLE is hardware feature rather then software and maybe it's not possible to use this feature. I'm wondering does Xbox 360's DX9 supports this..

Link to comment
Share on other sites

  • 3 weeks later...
On 3/23/2023 at 5:54 PM, antonic901 said:

But yeah, maybe you are right, D3DRS_SCISSORTESTENABLE is hardware feature rather then software and maybe it's not possible to use this feature. I'm wondering does Xbox 360's DX9 supports this..

Yes, DX9 supports SCISSORTESTENABLE.  It was added to DirectX starting with DX9.

Link to comment
Share on other sites

  • 3 weeks later...

I admit. I haven't gotten around to make an importer for skinned meshes with armatures yet. I was using the code from the example engine in the Xbox homebrew site. But I've added some extra features to it that was shown in the video above which was multiplying a matrix to a bone. Even getting the bone by name and set an index for it was programmed as well. So no I'm not the one to be credited for the whole code but the additions for it.

Link to comment
Share on other sites

  • 1 month later...

I think I'll bring some of my time with 2D angular sprites in 3D now. I made a system that I wish to use called 4-Angular-Directional-Sprites in the past that only uses 2 textures for a single frame. It's used in my game Atmo but I want to implement it to the original Xbox as well.image.thumb.png.6aa3a2bb053891a7cf2425ef698fe457.png

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

You can use the std library to create std::vector<Object> list variables if you feel like it. But I've found it to take up some space than a simple array. Sure std::vector is easier to use but it can't be that good for the Xbox for some reason other than increasing the size of the xbe. But I know a method to increase array size easily.

It's to take the array you want to expand, place all of it's elements in a temporary array by for-looping, empty the first array, fill it with 1 more element, place a new object at the end of the array and put everything else from the temporary array back to the first one. Then delete the temporary array for memory's sake.

I suggest that you make an int with the number of elements on an array for this like a "int numObjects" variable.

numObjects++;
CObjects* newList = new CObjects[numObjects];
for(int t=0; t < numObjects; t++)
{
	newList[t] = objectList[t];
}
newList[numObjects] = tempObject; // Add the new Object
objectList = new CObjects[numObjects];
for(int i=0; i < numObjects; i++)
{
	objectList[i] = newList[i];
}
delete newList;

You can make a func that takes an existing array and add something to it if you wish but that depends if it works for multiple types somehow.

  • Thanks 1
Link to comment
Share on other sites

  • 2 weeks later...

I'm going for the XTL in the mean time the nxdk gets easier to work with. Also do this

 

std::ifstream fin("file.txt");

if(!fin)
  return false;

Not

std::ifstream fin("file.txt");

if(fin)
  return false;

Everyone needs to remember to look through the code after these problems or it'll not do what it's supposed to do. Also "!fin" means "fin == NULL" if wanted to know.

 

Another thing. I will try to make my own skinned mesh renderer code so I can have full control over it. (Like vertex data and animation blending)

Link to comment
Share on other sites

Can't edit an old post so here's the how to add to an array code made proper.

numObjects++;
CObjects* newList = new CObjects[numObjects];
for(int t=0; t < numObjects - 1; t++)
{
	newList[t] = objectList[t];
}
newList[numObjects - 1] = tempObject; // Add the new Object
objectList = new CObjects[numObjects];
for(int i=0; i < numObjects; i++)
{
	objectList[i] = newList[i];
}
delete newList;

The - 1 was needed to properly get an element from an array using the maximum size of it.

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Bump*

Now I'm gonna talk about how I make the geometry for levels. I struggled with getting X file based geometry to work with UV2 (Lightmap UV) so I made my own technique to load a level.

Using code similar to this made me able to load a level and learn custom file format programming. For the file I used to copy/paste data from an .x file with a text editor but now when I made a Blender export script it got easier to work with. I suggest using multiple files during development and then copy them over to a single map file. And using a texture container I can take a single-copy texture and place it on a surface without using up memory.

This is a trial and error scenario. You need patience and skill for it to work.

Link to comment
Share on other sites

  • 1 month later...

I don't know if the array method I posted will work anymore cause of recent discoveries. So let's say that you need to call all texture files for the map from a file by text and put them in an array of DirectX textures. I'm sorry if I disappointed anyone but hopefully it's understandable.

Still, I've did some progress.

image.png.3915dec7f6bba1efe36b6d8f8c51ee01.png

I've figured how to make a sprite system. Haven't tested animation yet but will eventually do that now when I've gotten this engine running properly.

Link to comment
Share on other sites

21 hours ago, Meerjel01 said:

I don't know if the array method I posted will work anymore cause of recent discoveries. So let's say that you need to call all texture files for the map from a file by text and put them in an array of DirectX textures. I'm sorry if I disappointed anyone but hopefully it's understandable.

Still, I've did some progress.

image.png.3915dec7f6bba1efe36b6d8f8c51ee01.png

I've figured how to make a sprite system. Haven't tested animation yet but will eventually do that now when I've gotten this engine running properly.

Cool :)

Link to comment
Share on other sites

  • 4 weeks later...
  • 1 month later...

Well I can't teach by words but I can give code I guess.

static bool PointIntersectAABB(D3DXVECTOR3 point, Caabb box)
{
	return (point.x > box.center.x - box.extents.x && point.x < box.center.x + box.extents.x
		&& point.y > box.center.y - box.extents.y && point.y < box.center.y + box.extents.y
		&& point.z > box.center.z - box.extents.z && point.z < box.center.z + box.extents.z);
}
static bool AABBIntersectAABB(Caabb box1, Caabb box2)
{
	return (abs(box1.center.x - box2.center.x) < (box1.extents.x + box2.extents.x)
		&& abs(box1.center.y - box2.center.y) < (box1.extents.y + box2.extents.y)
		&& abs(box1.center.z - box2.center.z) < (box1.extents.z + box2.extents.z));		
}

These are from my Physics functions class.

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

Board Life Status


Board startup date: April 23, 2017 12:45:48
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.