DS Programming for Newbies!

Discussion in 'NDS - Tutorials & FAQs' started by Foxi4, Mar 3, 2012.

Mar 3, 2012

DS Programming for Newbies! by Foxi4 at 2:49 PM (35,376 Views / 25 Likes) 169 Comments

    • Member

    corenting Insert random cool title here

    Member Since:
    Jul 17, 2008
    Message Count:
    285
    Location:
    Paris
    Country:
    France
    The tool is grit, which is included in devkitpro tools. You can also look at NFLib tools folder, which contains nice scripts to use grit for batch converting.


    • Reporter

    Foxi4 Shotgun to the face is not a contingency plan.

    Member Since:
    Sep 13, 2009
    Message Count:
    19,532
    Location:
    Gaming Grotto
    Country:
    Poland
    Introduction to DS Hardware: OAM and 2D Sprites


    Before we jump head-first into using Sprites, it’s worth to know a little bit about how the Sprite system works on the DS. The name OAM stands for Object Attribute Memory – it’s a dedicated space in memory that the DS uses to track and control all Sprites (their current Frame or all of the Frames, depending on the code used) and their Attributes (Mosaic, Rotation, Double Size etc.). All in all, we have space for up to 128 individual Sprite data per screen, 32 of which can be freely rotated using the built-in rotation and scaling engine. The Sprite’s Graphics Data (GFX) is stored in VRAM Banks, the Sprite sheets are cut up into 8 by 8 squares, meaning tiles, similarily to the previously discussed Backgrounds. Each engine (Main and Sub, Main for the Top Screen, Sub for the Bottom one) can support up to 1024 tiles at a time. Sprites can use 16 or 256 colours palettes - do note that all sprites use the same tile data, however each individual Sprite may technically use a different palette, so Sprites created from the same tiles may have entirely different colour schemes to save space rather than add additional tiles. OAM has to be refreshed each frame so that all the on-screen Sprites (their frame, position etc.) are displayed properly. Note the word “individual” – you can in fact display more than 128 Sprites at a time! What’s meant by that is that within memory, you can store 128 *different* Sprites using different attributes – you can re-use the same Sprite as many times as your own code or the library used allows you to. In case of NightFox Lib which we’re using, it’s 256 Sprites per Screen.

    Much like in the case of backgrounds, we will be using GRIT to convert our Sprites. Sprites are a composition of frames of pre-defined size and shape on one Sprite Sheet – the shapes allowed are Square (width is the same as height), Wide (width is larger than height) and Tall (height is larger than width), while the sizes allowed are 8x8, 16x16, 32x32, 64x64, 16x8, 32x8, 32x16, 64x32, 8x16, 8x32, 16x32, 32x64 pixels. As you probably already noticed, those sizes are all divisible by 8. The way tiles are cut up is pretty simple – as with backgrounds, starting from the upper left-hand corner, 8x8 pixel big parts of the original image are converted into tiles, the conversion takes place to the right from that point, and once it reaches the edge of the image, it goes a row lower until the entire image is converted. Knowing that, you can deduce that the easiest image to convert would be a Strip with the width of the original frame.

    Once we have our Sprite Strip created, just like with Tiled Backgrounds, we put it in GRIT’s bmp folder. Once our Sprite or Sprites are in it, we run the Convert_Sprites batch file, and after the process is complete, the resulting binary files representing the Tiles and the Palette data can be recovered from the sprites folder. Alternatively, you can convert Sprites using Joint Palettes – this way, you can use several Sprites using just one Palette. Keep in mind though that it limits the total number of colours you can use to 256 rather than 256 per Sprite, however when using a large number of them, you may end up having to resort to that.

    You probably already noticed that the Sprites do not have a Map file – this is because the hardware itself calculates which Tiles are supposed to be used at any given time, copies them into VRAM if needed and OAM updates the displayed image. With the size and shape parameters pre-set, it can do it with relative ease, hence a Map is not necessary at all.
    Certain limitations mentioned above, such as the size of Sprites can be overcome by using the 3D hardware of the DS, we’ll eventually get there, but for now we’re going to focus on using the 2D hardware.

    Practical use of NightFox Lib: MODE-0 Tiled Sprites


    Now that we have some basic knowledge about how Sprites work in general, we can have a look at how the system works in NightFox Lib. By the end of this Tutorial, we will modify the previously written code to include a Sprite. First and foremost, we place our GRIT-converted Sprite in the “nitrofiles” folder. From here, we can move on to the coding. Seeing that in NightFox, Sprites are loaded from NitroFS, just like with Backgrounds, we start by Initializing the Buffers used by the library.

    NF_InitSpriteBuffers();
    NF_InitSpriteSys(Screen);


    These two are pretty self-explainatory – the first function Initializes the Buffers, the second Initializes the system that controls them for the Screen of your choice – 0 for Top Screen, 1 for the Bottom one.

    NF_LoadSpriteGfx("Sprite", RAM_Slot, Width, Height);
    NF_LoadSpritePal("Sprite", RAM_Slot);

    These two functions load the Gfx data and the Palette of our Sprite into a selected Slot in RAM memory. We have 256 (0-255) Slots for Sprites and 64 (0-63) for Palettes. We’re not ready to display it though – as we learned earlier, our resources have to be in VRAM to be displayed. To transfer them there, we will use these functions:

    NF_VramSpriteGfx(Screen, RAM_Slot, VRAM_Slot, Transfer_Flag);
    NF_VramSpritePal(Screen, RAM_Slot, VRAM_Slot);

    The Screen is self-explainatory and we already know of the RAM Slots used in NFLib, but we need to discuss the VRAM Slots and the Transfer Flag. As we already know, we can simultainously have up to 128 (0-127) Sprites in VRAM – that’s the value we are looking for then. As for Palettes, we can use one of 16 (0-15) Palette Slots for the Sprite to use. “Wait!” – you’re going to say, “You said each Sprite can use a dedicated Palette!” – that still applies, however one has to keep in mind that Palettes take space in their Bank – you can’t use more simply because you’d run out of space – this is why I mentioned that it’s often useful to use Joint Palettes for sprites with similar colour schemes. Finally, we have the Transfer_Flag – as I said, you can either transfer one Frame at a time, or you can transfer all frames into VRAM at once (the arguments are true and false depending on whether we want to transfer all the frames or not). Both options have their pro’s and con’s – using just one Frame at a time conserves more space, however this makes our Gfx Individual. If you re-use the same Gfx, all the Sprites using that Gfx will animate to the Frame currently in VRAM. If you copy all the frames into VRAM, each Sprite using that Gfx will be able to animate separately, meaning that the Gfx can be Shared. When to use which then, you ask? Well, it’s really up to you, and it’s highly-dependant on the design of your game. The general rule should be that if a given Sprite has more than one frame and the number of its occurances on-screen is higher than the number of its Frames, one should transfer all of the Frames to VRAM. It’s relatively easy to calculate why – say, you have a Sprite that has 15 Frames and it occurs on-screen 50 times. If each of these 50 instances were to be Individual, you’d use up 50 Slots in VRAM. If you transfer the entirety of Gfx data at once, regardless of whether you use it 5 or 250 times, it will use up the same amount of VRAM. On the other hand though, if you have a Sprite that has 100 Frames and it occurs 10 times on-screen, there’s no good reason as to why you’d transfer all 100 Frames – you can just as well create 10 Individual Gfx for them and use less Memory all-in-all. Always have memory in-mind – you have 128kb of VRAM for your Sprites per screen – use it wisely and strive towards conserving it.
    Now that our data is in VRAM, we’re ready to display it properly.

    NF_CreateSprite(Screen, ID, VRAM_Gfx_Slot, VRAM_Palette_Slot, X, Y);

    By now, all of those Arguments should be clear to us. This function will spawn our Sprite at the position indicated by X and Y.

    This concludes the basic tutorial – now, it’s time for some practice. Let’s have a look at some code.

    Excercises: MODE-0 2D Sprites


    Let's observe our Sample Code:

    Code:
     /*
    #############################################
    ##DS Programming Guide - From Zero To Hero!##
    ####Example #3 - MODE 0 Tiled Sprites    ####
    #############################################
    */
     
    /*
    ############
    ##Includes##
    ############
    */
     
    // Include C
    #include <stdio.h>
     
    // Include Libnds
    #include <nds.h>
     
    // Include NFLib
    #include <nf_lib.h>
     
    /*
    ###############
    ##Main(){...}##
    ###############
    */
     
    int main(int argc, char **argv) {
     
    // Turn on MODE 0 on the Top Screen
    NF_Set2D(0, 0);
     
    // Set the Root Folder
    NF_SetRootFolder("NITROFS");
     
    // Initialize the Tiled Backgrounds System on the Top Screen
    NF_InitTiledBgBuffers();
    NF_InitTiledBgSys(0);
     
    // Initialize the Tiled Sprites System on the Bottom Screen
    NF_InitSpriteBuffers();
    NF_InitSpriteSys(0);
     
     
    // Load and Create the Tiled Background
    NF_LoadTiledBg("Background", "Background", 256, 256);
    NF_CreateTiledBg(0, 3, "Background");
     
    // Load our Tiled Sprite
    NF_LoadSpriteGfx("Sprite", 0, 64, 64);// Tempy!
    NF_LoadSpritePal("Sprite", 0);
     
    // Transfer our sprite to VRAM
    NF_VramSpriteGfx(0, 0, 0, false);
    NF_VramSpritePal(0, 0, 0);
     
    // Create the Sprite!
    NF_CreateSprite(0, 0, 0, 0, 0, 0);
     
    while(1){
    swiWaitForVBlank();
    }
    return 0;
    }
    We compile the code and… the Sprite didn’t spawn! Why…? What have we forgotten? Let’s come back to OAM. To properly display our Sprites, we need to refresh its state. To do so, we will have to update our OAM contents in-between of our VBlanks:

    Code:
    //Update NF OAM Settings
    NF_SpriteOamSet(0);
    swiWaitForVBlank();
    //Update OAM!
    oamUpdate(&oamMain);
    With these lines altered at the end of our applications, it should start displaying our Sprites properly!

    EDIT: I've been informed (on good authority) that libnds has been modified to include 16 Ext.Palettes for backgrounds stock, which didn't use to be the case and I did not know that at the time of writing this guide. It used to be handled by means of setting the start adress of the Palette, now it's done by stating the Slot number. With that in mind, the sentence stating that this is a NightFox Lib limitation has been removed.
    Last edited by Foxi4, Nov 22, 2012
    • Reporter

    Foxi4 Shotgun to the face is not a contingency plan.

    Member Since:
    Sep 13, 2009
    Message Count:
    19,532
    Location:
    Gaming Grotto
    Country:
    Poland
    Excercises: Our very first game - Tic Tac Toe


    Even with our very limited knowledge of programming, we're already capable of coding our very first game! I specifically chose Tic Tac Toe because the logic rules for this game are incredibly simple. Keep in mind that the code was created with the intention of being as straight-forward as possible - it may not be up to all "coding standards" for the sake of simplicity. ;)

    In our game, we'll use these base resources:
    WARNING! Spoilers inside!


    When starting to code a game, one has to think about what rules will govern it. Our example concerns Tic Tac Toe, so let's list the rules:
    1. There are 2 players and 9 spaces for either crosses or circles
    2. Players take turns, each player can place one sign on one field per turn, then the turn changes
    3. Players cannot put their sign on the other player's sign - the space has to be blank
    4. To facilitate multiple games as well as quitting, bind a button (we will use A) to clear the playing field and reset the game
    We will concern ourselves with those two for now and as we learn more about video game logic, we will improve upon this example. We know that there are 9 spaces on the game field - this makes it convenient for us to create 9 sprites - one on each space and change their frames depending on who clicks on them. We can use a loop to facilitate even spacing of the sprites.
    Touching the screen within the boundries of the sprite will change the frame, but only when the frame is equal to 0 (blank frame, as seen above). The frame to which we change will be dependant on the turn - turns that are not divisible by 2 (1, 3, 5 and 7) belong to one player, the rest (0, 2, 4, 6, 8) to the other one.
    We know everything! Now we can begin coding, do note the Comments in code:

    Code:
    //Our Very First Game - Tic Tac Toe!
    /*
    -------------------------------------------------
    Includes block
    -------------------------------------------------
    */
     
    // Includes C
    #include <stdio.h>
     
    // Includes libnds
    #include <nds.h>
     
    // Includes NightFox Lib
    #include <nf_lib.h>
     
    // Create a Sprite data structure to hold important information
    typedef struct{
    u8 ID, X, Y, Frame;
    } Sprite_Data;
     
    Sprite_Data Sprite[9];
     
     
    /*
    -------------------------------------------------
    Main() function block
    -------------------------------------------------
    */
     
    int main(int argc, char **argv) {
     
    NF_Set2D(0, 0);//Set 2D MODE-0 to both Screens
    NF_Set2D(1, 0);
     
    NF_SetRootFolder("NITROFS");// Set the Root Directory to NITRO FS
     
    NF_InitTiledBgBuffers();// Initialize Background Buffers
    NF_InitTiledBgSys(0);// Initialize Top and Bottom Screen BgSystems
    NF_InitTiledBgSys(1);
     
    NF_InitSpriteBuffers();// Initialize Sprite Buffers
    NF_InitSpriteSys(1);// Initialize Bottom Screen SpriteSystem
     
    NF_LoadTiledBg("TopScreen", "Top", 256, 256);// Load a Background into RAM for the Top Screen
    NF_LoadTiledBg("BottomScreen", "Bottom", 256, 256);// Load a Background into RAM for the Bottom Screen
     
    NF_LoadSpriteGfx("Sprite_TicTacToe", 0, 32, 32);// Load our Sprite for the circle, cross and blank
    NF_LoadSpritePal("Sprite_TicTacToe", 0);
     
    NF_VramSpriteGfx(1, 0, 0, false);// Load the Gfx into VRAM - transfer all Sprites
    NF_VramSpritePal(1, 0, 0);// Load the Palette into VRAM
     
    NF_CreateTiledBg(0, 3, "Top");// Create the Top Background
    NF_CreateTiledBg(1, 3, "Bottom");// Create the Bottom Background
     
     
    u8 X, Y, ID = 0;// Prepare Variables necessary for the field-generating Loop
     
    for(X=55; X<190; X+=45){// Loop the X value between 55 and 190, add 45 each Loop
    for(Y=32; Y<167; Y+=45){// Loop the Y value between 32 and 167, add 45 each Loop
    NF_CreateSprite(1, ID, 0, 0, X, Y);// Create a Sprite in the designated spot
    NF_SpriteFrame(1, 3, 0);// Set its Frame to a blank one
    Sprite[ID].X = X;// Remember all the important variables for the Sprite in our Data struct
    Sprite[ID].Y = Y;
    Sprite[ID].ID = ID;
    Sprite[ID].Frame = 0;
    ID++;// Next Sprite...
    }
    }
     
    touchPosition Stylus;// Prepare a variable for Stylus data
    u8 Turn = 0;// Create a variable to count turns
     
    while(1) {
     
    scanKeys();// Scan for Input
    touchRead(&Stylus);// Read Stylus data
     
    if(KEY_TOUCH & keysDown()){// If the Touchscreen is touched...
    for(ID=0; ID<9; ID++){// Cycle through all Sprites...
    if(Stylus.px >= Sprite[ID].X && Stylus.px <= Sprite[ID].X+32){// If the Stylus position is within the bounds of a Sprite in question...
    if(Stylus.py >= Sprite[ID].Y && Stylus.py <= Sprite[ID].Y+32){// Between X and X+Width; Between Y and Y+Height...
    if(Sprite[ID].Frame == 0){// If the Sprite's Frame is 0 - meaning it is neither a cross nor a circle
    if(Turn%2){// If it's the cross's turn...
    NF_SpriteFrame(1, ID, 2);// Change the Frame of the Sprite to Frame 2 (cross)
    Sprite[ID].Frame = 2;// Save the change in our Data Struct for future reference
    }
    else{// Otherwise...
    NF_SpriteFrame(1, ID, 1);// Change the Frame of the Sprite to Frame 1 (circle)
    Sprite[ID].Frame = 1;// Save the change in our Data Struct for future reference
    }
    Turn++;// Next turn
    }
    }
    }
    }
     
    }
     
    if(KEY_A & keysDown()){// If the A button is pressed, clear the playing field
    for(ID=0; ID<9; ID++){
    Sprite[ID].Frame=0;// Clear Sprite Data
    NF_SpriteFrame(1, ID, 0);// Change Frames to blank ones.
    Turn = 0;// Reset the game
    }
    }
     
    NF_SpriteOamSet(1);// Update NFLib's Sprite OAM System
    swiWaitForVBlank();// Wait for the Vertical Blank
    oamUpdate(&oamSub);// Update the OAM of the Bottom Screen engine
     
    }
     
    return 0;
     
    }
    In this code, we learn one new function, which will be useful to us once we learn how to Animate Sprites:

    NF_SpriteFrame(Screen, Sprite_ID, Frame);

    It's relatively self-explainatory - it changes the Frame of a given Sprite on a given Screen to the one selected - easy-peasy!

    Now, analyze the code - here's the Example itself, alongside its source code, if you feel it is necessary to clarify anything, do post!

    EDIT: Alright, something is very wrong with the code field... I noticed that all my previous code samples are incomplete after importing them to the new forum system and the current one messes up indentations... I'm sorry for their lack, please refer to main.c from the included example if this is unreadable until I sort it all out.
    Last edited by Foxi4, Nov 16, 2012
    • Reporter

    Foxi4 Shotgun to the face is not a contingency plan.

    Member Since:
    Sep 13, 2009
    Message Count:
    19,532
    Location:
    Gaming Grotto
    Country:
    Poland
    WHOOPSIE!
    [IMG]
    It's official - we've got BUGS!


    Those of you who read my guide probably noticed that after the swap to xenforo which was a direct result of GBATemp's latest hacking problems, access to it was severely limited - the layout was all over the place and certain chapters actually weren't imported properly - the guide lost quite a lot of data, and all I really wanted to say in this post is that I am actively replacing the affected chapters. GBATemp's great administration staff was kind enough to remove all the old and obsolete code which prevented the chapters from being viewed (thanks, tj! You're a God amongst men!) and now it's up to me to make the guide meet its original standards yet again.

    As of now, the chapters about Operators and Looping in C have been fixed - they're only missing its original bolding, but text formatting is the last thing on my To-Do list - first and foremost I need to make sure that the guide returns to their original "integrity" as far as the content is concerned. I apologize to all those who were affected - don't worry, the guide will soon be back to its original form, if not even better!
    Last edited by Foxi4, May 24, 2014
    GPSSerbia likes this.
    • Member

    Rydian Resident Furvert™

    Member Since:
    Feb 4, 2010
    Message Count:
    27,886
    Location:
    Cave Entrance, Watching Cyan Write Letters
    Country:
    United States
    I think this is a great example of what the tutorial section should be producing, and even in the unfinished form it still contains all the critical setup/starting info that people need, so stickied.
    Foxi4 likes this.
    • Reporter

    Foxi4 Shotgun to the face is not a contingency plan.

    Member Since:
    Sep 13, 2009
    Message Count:
    19,532
    Location:
    Gaming Grotto
    Country:
    Poland
    Very encouraging words. I wish I could continue writing this guide but I'm facing certain time constraints preventing me from adding things to it in a timely fashion. :P

    For now, I've fixed the list of contents, added links to chapters and fixed the very basic formatting of the posts, but the fonts are still wonky - it will need some more work, but at least it's complete and readable. Unfortunately [ code ][ /code ] fields are still ignoring any indentations, so I suppose I'll just have to introduce spaces in them sometime (which is a huge shame - my TAB key misses me...).

    In any case, I hope the improvements made so-far will make it a more approachable read. :)
    Last edited by Foxi4, May 27, 2013
    • Newcomer

    plasturion New Member

    Member Since:
    Aug 17, 2012
    Message Count:
    18
    Country:
    Poland
    Nice tutorial, didn't read at all, but seems good one, NightFox lib seems far user friendly than libnds.
    About 1st Section - C/C++ programming it's not necessary, there's some good basic tutorials on the web.
    Maybe some stuff like table of ansi escape codes for DS console mode would be a better choice, diagrams, screenshots. (min text - max info)
    I would like to read some practical hardware capability, comparisons, tables, registers... that stuff just interesting.
    I know I'll never master that things, but it's good to know things like max resolution of bitmap, limitations, different methods of storing data.. etc.
    btw. Is there any emulator that shows contains of Vram blocks?
    XFCEu for nes had something like that.
    • Reporter

    Foxi4 Shotgun to the face is not a contingency plan.

    Member Since:
    Sep 13, 2009
    Message Count:
    19,532
    Location:
    Gaming Grotto
    Country:
    Poland
    It's a great library for programming start-ups, yeah.
    That's not the point of this tutorial and I outlined that in the introductory post. This is meant for people who have never done any programming at all and want to start specifically on the DS. ;)
    I strongly suggest reading GBATek - you'll find that kind of information there.
    I do my best to cover hardware limitations in each chapter as well as the workarounds for them. ;)
    As far as development is concerned, your best bet is NO$GBA, especially the developer edition which contains additional debug-related tools. It's sort of hard to compare the NDS and the NES as far as VRAM is concerned because with the DS the VRAM Banks do not have static functions - you declare those yourself (at least in libnds you do - with NightFox such things are done for you).
    • Member

    Wolfgange New Member

    Member Since:
    Feb 9, 2012
    Message Count:
    135
    Country:
    United States
    Thank you for such a great tutorial (as well as introducing me to Nightfox lib). I got everything to work of what I wanted except I can only find one way to clear a layer of the screen (One of the tiled background screen). As far as I can tell, Nightfox has no function for this. Is there any more efficient method of clearing just one layer than (using 2 for statements and) setting all the tiles to 0?
    Last edited by Wolfgange, Jul 30, 2013. Reason: Typo
    • Member

    Wolfgange New Member

    Member Since:
    Feb 9, 2012
    Message Count:
    135
    Country:
    United States
    Double Post.
    • Reporter

    Foxi4 Shotgun to the face is not a contingency plan.

    Member Since:
    Sep 13, 2009
    Message Count:
    19,532
    Location:
    Gaming Grotto
    Country:
    Poland
    According to the documentation, you can use NF_DeleteTiledBg(u8 screen, u8 layer); - this will remove the background from both RAM and VRAM. If you want to keep it in memory, use NF_HideBg(u8 screen, u8 layer); instead - the background will continue to occupy the layer, but it won't be visible to the user. :)

    If by "clearing" you mean altering all the tiles to show a transparent one then using NF_HideBg would be what I'd do - it's less resource-heavy than altering the tiles there and then and you can still manipulate the map without actually showing it to the user.
    Last edited by Foxi4, Jul 31, 2013
    Wolfgange likes this.
    • Member

    Wolfgange New Member

    Member Since:
    Feb 9, 2012
    Message Count:
    135
    Country:
    United States
    Thank you for all the help you've done with simple things so far :).

    What I mean is to clear all the tiles of a background (or set them to transparent) and then draw a different tile layout on it (meaning I do not need to preserve the old tiles).

    For example, I draw out 3 buttons on a tiled background. If the user taps "Options", there are only 2 buttons to draw, so to center them they would be drawn in different spots. To do this, I need to clear the tiles on the screen, and draw new buttons in a different location on the screen.

    I thought since no changes would be shown until NF_UpdateVramMap is called, hiding the background would not reduce resource usage.

    So, which would be less resource heavy:
    1. To hide the Bg, set every tile to transparent, and then show it (Like you said), or
    2. To just set every tile to transparent without , and use NF_UpdateVramMap(screen,layer) at the end
    • Reporter

    Foxi4 Shotgun to the face is not a contingency plan.

    Member Since:
    Sep 13, 2009
    Message Count:
    19,532
    Location:
    Gaming Grotto
    Country:
    Poland
    Setting every tile to transparent and then setting it to the tile you actually want equates to setting it up twice wheras hiding the background and setting them is only doing so once, so I personally think option #1 is the more efficient one.
    • Member

    Wolfgange New Member

    Member Since:
    Feb 9, 2012
    Message Count:
    135
    Country:
    United States
    Ok, I get what your saying :).
    • Member

    relminator New Member

    Member Since:
    May 28, 2010
    Message Count:
    333
    Country:
    Philippines
    Nice tutes! btw, the 256 limit on sprites probably refers to sprites drawn using the 3d engine( you could blit more than that but nf probably limited it to 256). The 2d engine is limited to 128 but theoretically, with some hblank techs, you could blit more like the nes. I haven't tried it yet though.
    • Reporter

    Foxi4 Shotgun to the face is not a contingency plan.

    Member Since:
    Sep 13, 2009
    Message Count:
    19,532
    Location:
    Gaming Grotto
    Country:
    Poland
    Out of the box the limit is 128 OBJ's in OAM as you say, yes. The 256 sprites on-screen does refer to the 3D engine - I'll correct that error when I get some spare time. ;)
    Last edited by Foxi4, Aug 1, 2013
    • Reporter

    Foxi4 Shotgun to the face is not a contingency plan.

    Member Since:
    Sep 13, 2009
    Message Count:
    19,532
    Location:
    Gaming Grotto
    Country:
    Poland
    I see that people are still reading the guide since I am seeing some likes and page views - I'm really greatful for that. Please keep in mind that I haven't really contributed to it in quite some time and the editing in some parts is atrocious. The guide was posted in my pre-Reporter status days and requires a complete overhaul, which I hoped would happen soon, but I'm yet to find some spare time to get around to doing it. I'm sorry if some things are either incomplete or hard to understand or if the language used often has you scratch your heads - most of this was written at night when my brain wasn't exactly functioning at top gear. If you find anything confusing, requiring editing or some additional clarification, please feel free to post here as usual with questions. Again, thanks for reading the guide and showing interest in homebrew development - the more aspiring developers there are the brighter the future of the scene! :)
    Swauny Jones likes this.
    • Newcomer

    Swauny Jones New Member

    Member Since:
    Mar 25, 2014
    Message Count:
    12
    Location:
    T.O.
    Country:
    Canada
    This is my first time on this site and I find all of this stuff pretty amazing. I can already feel the sleepness nights ahead playing around with this.
    Foxi4 likes this.
    • Reporter

    Foxi4 Shotgun to the face is not a contingency plan.

    Member Since:
    Sep 13, 2009
    Message Count:
    19,532
    Location:
    Gaming Grotto
    Country:
    Poland
    There's going to be plenty since things never work out quite the way we originally imagined them. :rofl2:

    I'm glad to hear that you're interested - stick around, I'm sure you'll find even more content relevant to your interest. ;)
    Swauny Jones likes this.
    • Member

    Coto Challenge Taken.

    Member Since:
    Jun 4, 2010
    Message Count:
    2,088
    Country:
    Chile
    good job again, foxi.
    Foxi4 likes this.
    • Newcomer

    agentalexandre New Member

    Member Since:
    Sep 12, 2009
    Message Count:
    6
    Country:
    United States
    Anyone know if it's possible to use extended palettes with tiled backgrounds? I'm looking to use some fairly high quality tiles and they always lose a lot of colour when I save them as 256 colour bitmaps.

    I've seen the example for extended palettes in the example folder but it's not very helpful in explaining how you actually generate extended palettes.
    Last edited by agentalexandre, Apr 6, 2014

SPONSORED LINKS
 

Share This Page