Malevolence's Object Tutorials

Discussion in 'Tutorials Archive' started by Malevolence, Jul 22, 2009.

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

    Malevolence Well-Known Member Member

    Joined:
    Jul 29, 2008
    Messages:
    97
    Today I decided I wanted to start some tutorials on objects because there aren't too many hacks with new objects. I figure I can start off with the really basic things then move on to more intricate subjects such as bosses. For now here is the first tutorial on very basic object concepts:


    Lesson 1: The Basic Object


    Section A: Overview



    So, you want to start creating objects using the sonic engine? (We'll be using S1's but most of the ideas cover S1 and S2) Let's see firstly how most objects start out. I'll be using Hivebrain's 2005 disassembly for these examples:



    ; ---------------------------------------------------------------------------
    ; Object 18 - platforms (GHZ, SYZ, SLZ)


    ; ---------------------------------------------------------------------------


    Obj18: ; XREF: Obj_Index


    moveq #0,d0


    move.b $24(a0),d0


    move.w Obj18_Index(pc,d0.w),d1


    jmp Obj18_Index(pc,d1.w)



    First you see a little description of the object (commented out of course), followed by the object's code itself. It starts off by making sure there is currently no value in d0. After that it puts the value of the routine counter into d0 (whatever's in $24(a0) is in d0 such as 0, 2, 4, ect...). From there it moves the index's value with the value of d0 into d1, followed by jumping to the correct routine based on d1.

    Section B: Routines



    Routines are used to organize where certain code is and to be able to branch to those sections easily. Most objects used $24(a0) as the main routine counter and $25 as a secondary, but any scratch ram (ram not used by the object) can be used as a routine counter. The value in the routine counter needs to be even in order to work.



    ;==========================================================================
    =


    Obj18_Index: dc.w Obj18_Main-Obj18_Index; Jumped to if #0 is in $24(a0)


    dc.w Obj18_Solid-Obj18_Index; Jumped to if #2 is in $24(a0)


    dc.w Obj18_Action2-Obj18_Index; Jumped to if #4 is in $24(a0)


    dc.w Obj18_Delete-Obj18_Index; Jumped to if #6 is in $24(a0)


    dc.w Obj18_Action-Obj18_Index; Jumped to if #8 is in $24(a0)


    ; ===========================================================================



    So, when this section is run (as soon as the object is loaded):



    Obj18_Main: ; XREF: Obj18_Index
    addq.b #2,$24(a0)



    when it gets to the next rts instead of going to Obj18_Main again, it will skip over that code and go to Obj18_Solid. Be warned if you put an odd value into the routine counter it won't work properly or if you put a number greater then the amount of routines, your game will crash.

    Section C: Displaying/Basic SSTs



    Alright, so you know the basis of routines, now where should we go? Well, some of the basic building blocks in objects are what are called SSTs. Every object in S1 and S2 is allotted $40 bytes of RAM to do whatever they want with, but some SSTs are already used for certain things (the game engine checks a few of the object's SSTs once each frame). Let's see an example:



    Obj18_Main: ; XREF: Obj18_Index
    addq.b #2,$24(a0) ; adds to the routine so this isn't run again


    move.w #$4000,2(a0); moves #$4000 to the art tile's SST (it's 2 in S1 and S2)


    move.l #Map_obj18,4(a0); moves the mappings into the mapping's SST


    move.b #$20,$19(a0) ; width of object in pixels


    cmpi.b #4,($FFFFFE10).w ; check if level is SYZ


    bne.s Obj18_NotSYZ


    move.l #Map_obj18a,4(a0) ; SYZ specific code (use different mappings)


    move.b #$20,$19(a0) ; this really isn't needed since $19(a0) already has #$20 in it from the code before



    What this basically does is define the width of the object in pixels and loads the starting art tile and palette and mappings. Down more in the code you'll see:



    Obj18_NotSLZ:
    move.b #4,1(a0); use screen coordinates (such as the ones you see in debug mode)


    move.b #4,$18(a0); set priority (if other objects have a priority of a number less then 4 then the other object will be seen over this one if they interact)


    move.w $C(a0),$2C(a0); store a copy of the y coordinate ($C(a0) is y coordingate in S1 and S2 and $2C(a0) is scratch ram)


    move.w $C(a0),$34(a0); store another copy of the y coordinate


    move.w 8(a0),$32(a0); store a copy of the x coordinate


    move.w #$80,$26(a0); move #$80 into $26(a0) (to be used later)



    This is a continuation of the loading of the object (the priority and using screen coordinates) and it saves the x and y pos and a value which will be used later. All you need to do to display an object it to fill in 1(a0), 2(a0), 4(a0) and jump to DisplaySprite. That's the end of the first tutorial of a few for basic object creation. If you have any problems or notice any errors, please mention them.
     
    Last edited by a moderator: Jul 23, 2009
  2. Armada

    Armada DID SOMEONE SAY WEEABOO? Member

    Joined:
    Aug 17, 2007
    Messages:
    98
    This is an excellent read. It's helped me more with understanding everything in the object code. I suggest adding something about object subtypes (like in monitors) and passing information between two object (Monitor subtype -> monitor contents subtype).


    EDIT: It's sort of covered in the SST section, though.
     
    Last edited by a moderator: Jul 22, 2009
  3. Malevolence

    Malevolence Well-Known Member Member

    Joined:
    Jul 29, 2008
    Messages:
    97
    Thank you, and I plan on adding more details about objects and how to do various things with them in the next tutorial.
     
  4. bareirito

    bareirito Well-Known Member Member

    Joined:
    Nov 17, 2008
    Messages:
    87
    Location:
    Argentina
    Malevolence, this is awesome, it's so well explained, now ASM it's turning a bit more clearly. Are you doing more tutorials of this?
     
  5. Malevolence

    Malevolence Well-Known Member Member

    Joined:
    Jul 29, 2008
    Messages:
    97
    Yes I plan on showing how to do various things with objects next such as making subtypes and perhaps making an object id more then one object (you'll see). Then I want to go into badniks and then perhaps bosses.
     
  6. Selbi

    Selbi The Euphonic Mess Member

    Joined:
    Jul 20, 2008
    Messages:
    2,429
    Location:
    Northern Germany
    I have a very very small question:

    Why do we need that moveq line? I mean, d0 is going to be overwritten with the next line anyway. So why do we need to clear d0 first?


    Thanks for this guide though. :)
     
  7. Malevolence

    Malevolence Well-Known Member Member

    Joined:
    Jul 29, 2008
    Messages:
    97
    If you see in the next line d0 gets treated as a word and the move.b only replaces the byte.
     
Thread Status:
Not open for further replies.