Meerjel01 Posted March 19 Report Share Posted March 19 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. 4 Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted March 20 Author Report Share Posted March 20 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! 1 Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted March 20 Author Report Share Posted March 20 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. 1 Quote Link to comment Share on other sites More sharing options...
antonic901 Posted March 21 Report Share Posted March 21 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. Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted March 21 Author Report Share Posted March 21 Scissor Test This topic is mostly for me to speak out what I know and share what I can. I don't know how to implement this but I guess you need to write a couple of new functions. Quote Link to comment Share on other sites More sharing options...
antonic901 Posted March 21 Report Share Posted March 21 Thanks! Well my knowledge to graphic is limited, almost not existing so I'll see what I could figure out. 1 Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted March 23 Author Report Share Posted March 23 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. 1 Quote Link to comment Share on other sites More sharing options...
KaosEngineer Posted March 23 Report Share Posted March 23 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. 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. Quote Link to comment Share on other sites More sharing options...
antonic901 Posted March 23 Report Share Posted March 23 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.. Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted April 8 Author Report Share Posted April 8 Note: This is what you can do with DirectX. Quote Link to comment Share on other sites More sharing options...
KaosEngineer Posted April 9 Report Share Posted April 9 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. Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted April 29 Author Report Share Posted April 29 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. Quote Link to comment Share on other sites More sharing options...
Bowlsnapper Posted April 29 Report Share Posted April 29 On 3/19/2023 at 8:54 AM, Meerjel01 said: I’m not gonna instruct you on the process of getting the DevKit to work or where to get it. Damn Jel, what is this, 2004? Lol. I respect the topic though. I would love to see as much of this material as possible. Thank you! 1 Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted June 4 Author Report Share Posted June 4 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. 1 Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted June 16 Author Report Share Posted June 16 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. 1 Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted June 23 Author Report Share Posted June 23 I got myself into the nxdk since it's cross platform. But there's very little tutorials about it so I don't know if it'll be a hit or not. It's also legal apparently. 1 Quote Link to comment Share on other sites More sharing options...
Bowlsnapper Posted June 23 Report Share Posted June 23 2 hours ago, Meerjel01 said: I got myself into the nxdk since it's cross platform. But there's very little tutorials about it so I don't know if it'll be a hit or not. It's also legal apparently. Right on! Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted July 7 Author Report Share Posted July 7 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) Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted July 15 Author Report Share Posted July 15 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. Quote Link to comment Share on other sites More sharing options...
Meerjel01 Posted August 25 Author Report Share Posted August 25 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.