don't click here

Basic Questions & Answers thread

Discussion in 'Engineering & Reverse Engineering' started by Tweaker, May 29, 2008.

  1. Brainulator


    Regular garden-variety member Member
    You're welcome... I figured since I saw no updates, then...
    I should have mentioned that the second instruction given may have to be changed to a JSR, depending on how far it is.

    Can I take a closer look at the code you've created for that bit of the monitor icon item? I just want to make sure that nothing's gone with what I said.
  2. RazorKillBen


    Benny the Hog Member
    London, UK
    Sonic Seasons
    Sure - it's literally ironically, exactly what you'd typed too:

    Code (Text):
    1. Pow_ChkRings:
    2.     cmpi.b   #6,d0        ; does monitor contain 10 rings?
    3.     bne.s    Pow_ChkS
    5.     moveq    #palid_GHZ_Alt,d0; Load alternative level palette
    6.     jsr      (PalLoad1).l
    It doesn't seem to matter what palette is loaded into memory with moveq - even if I don't add the command it crashes when hitting the monitor displaying either a LINE EMULATOR 1111 error or mostly ILLEGAL INSTRUCTION. Essentially, when the monitor is broken, I wanted the level palette to change (I removed the whiteout fade code to make it as simple as possible for the example!). Not sure what I'm missing as I assumed it would be as easy as load palette into memory, run sub routine, deep joy was had by all.
  3. Brainulator


    Regular garden-variety member Member
    I think I figured it out: it's the same problem that afflicts the Chemical Plant Zone boss in Sonic 2: PalLoad1 writes to register d7, but d7 is used as a loop counter so that the object execution routine knows what to process. Thankfully, d1 is unused past the initial routine jump code, so we can use that to our advantage. To fix this, do either of the following:

    Fairly simple. I guess you could use the stack pointer or d2/d3/d4/d5/d6 for this, too, but d1 works well enough for our purposes.
    Code (Text):
    1. Pow_ChkRings:
    2.     cmpi.b  #6,d0   ; does monitor contain 10 rings?
    3.     bne.s   Pow_ChkS
    5.     moveq   #palid_GHZ_Alt,d0   ; Load alternative level palette
    6.     move.b  d7,d1   ; Back up d7
    7.     jsr (PalLoad1).l
    8.     move.b  d1,d7   ; Restore d7
    A bit lengthier, but just as suitable:
    Code (Text):
    1. Pow_ChkRings:
    2.     cmpi.b  #6,d0   ; does monitor contain 10 rings?
    3.     bne.s   Pow_ChkS
    5.     moveq   #palid_GHZ_Alt,d0   ; Load alternative level palette
    6.     lea (PalPointers).l,a1
    7.     lsl.w   #3,d0
    8.     adda.w  d0,a1
    9.     movea.l (a1)+,a2    ; get palette data address
    10.     movea.w (a1)+,a3    ; get target RAM address
    11.     adda.w  #v_pal_dry_dup-v_pal_dry,a3     ; skip to "main" RAM address
    12.     move.w  (a1)+,d1    ; get length of palette data
    14. @loop:
    15.     move.l  (a2)+,(a3)+ ; move data to RAM
    16.     dbf d1,@loop
    Note that if you optimize things and are only using the one palette, you can replace the four lines (not counting the space) after the BNE instruction with this:
    Code (Text):
    1. lea (PalPointers+(palid_GHZ_Alt<<3)).l,a1

    This is, of course, assuming you made sure to put an RTS at the end of your code... right? Either way, let me know if this fixes the problem!
  4. RazorKillBen


    Benny the Hog Member
    London, UK
    Sonic Seasons
    Thanks so much, genuinely, for trying to get this resolved. I really appreciate it.

    So I did try exactly what you'd mentioned (albeit, I copied into the d6 register) previously, but I still got the crash. So I tried copying your code word-for-word in-case I was overwriting an important data register, but it's still crashing in-game. Freezes with a small graphical tear, although the ILLEGAL INSTRUCTION and any error messages are not present now. On one occasion, there was a slight screen flash (almost like a special stage entry flash) before crash but can't seem to replicate it since.

    EDIT: The ILLEGAL INSTRUCTION error is still present, it was just off screen...

    I tried copying the second code block and this doesn't crash the game! However, it also doesn't seem to have any effect at all either. I've also tried using alternate palettes (SBZ for example) just to ensure it's not an issue with the palette code, but it isn't. No palette swaps, no graphical changes at all. I'm at a bit of a loss as to what's causing the problem!
    Last edited: Nov 12, 2021
  5. Brainulator


    Regular garden-variety member Member
    I made two mistakes, it turns out. First of all, those move.b instructions in the first method should be move.w instructions. Second, for both methods, the jump should be changed to point to PalLoad2 instead. Hopefully, this should do it.
  6. In the Nick Arcade prototype, Green Hill Zone uses this code to load level layouts.
    Code (Text):
    1. LevelLayoutLoad_GHZ:
    2.         move.w    (Current_ZoneAndAct).w,d0
    3.         lsl.b    #6,d0
    4.         lsr.w    #5,d0
    5.         move.w    d0,d2
    6.         add.w    d0,d0
    7.         add.w    d2,d0
    8.         add.w    d1,d0
    9.         lea    (LevelLayout_Index).l,a1
    10.         move.w    (a1,d0.w),d0
    11.         lea    (a1,d0.w),a1
    12.         moveq    #0,d1
    13.         move.w    d1,d2
    14.         move.b    (a1)+,d1
    15.         move.b    (a1)+,d2
    17. loc_7426:
    18.         move.w    d1,d0
    19.         movea.l    a3,a0
    21. loc_742A:
    22.         move.b    (a1)+,d3
    23.         subq.b    #1,d3
    24.         bcc.s    loc_7440
    25.         moveq    #0,d3
    26.         move.b    d3,(a0)+
    27.         move.b    d3,(a0)+
    28.         move.b    d3,$FE(a0)
    29.         move.b    d3,$FF(a0)
    30.         bra.s    loc_7456
    31. ; ===========================================================================
    33. loc_7440:
    34.         lsl.b    #2,d3
    35.         addq.b    #1,d3
    36.         move.b    d3,(a0)+
    37.         addq.b    #1,d3
    38.         move.b    d3,(a0)+
    39.         addq.b    #1,d3
    40.         move.b    d3,$FE(a0)
    41.         addq.b    #1,d3
    42.         move.b    d3,$FF(a0)
    44. loc_7456:
    45.         dbf    d0,loc_742A
    46.         lea    $200(a3),a3
    47.         dbf    d2,loc_7426
    48.         rts
    49. ; End of function LevelLayoutLoad_GHZ
    Not sure what it does though; best I can tell it loads four chunks instead of one (probably since the GHZ layout data is the same as Sonic 1's), but I'm not sure about that.
  7. RazorKillBen


    Benny the Hog Member
    London, UK
    Sonic Seasons
    We're so close! So the move.w instructions has fixed the crashing - PalLoad2 does change the palette, but applies it to the object layer, so Sonic, Rings, HUD and Badniks and not the level layer. PalLoad1 does not change anything.
  8. MainMemory


    Kate the Wolf Tech Member
    It is dynamically converting the layout data from 256x256 chunks to 128x128 by multiplying the source ID by 4 and copying it into four adjacent slots in the layout buffer, incrementing by one each time. Except for the 0 chunk, which just writes four 0s. So, given the value $14, it subtracts 1 ($13), multiplies by 4 ($4C), adds 1 ($4D), then fills in a 4-chunk section of the layout, giving you:
    Code (Text):
    1. 4D 4E
    2. 4F 50
  9. Brainulator


    Regular garden-variety member Member
    You'll have to modify or duplicate the palette pointers themselves.
  10. Cioss


    idk if it'd fit here, but idk where else

    ok so my friend and i are trying to figure out how we'd be able to use gradients (aka hblank), and we have no clue how, for example, the gradient flickers, and when we want to make for example a gradient that goes from fluo yellow purple it turns into this monstrosity
    so, my question here is basically, how do i properly use hblank to make a cool gradient without screwing it up
  11. PhyChris


    Could someone point me out some Sonic 1 and 2 art editing and inserting tutorials?
    what do you use for reading, editing ASM?
  12. E-122-Psi



    Some of these are a bit dated, but are a decent way of getting a start at editing the games.
  13. PhyChris


    Terribly dated, A HUGE deterrent. Time is of the essence for some.

    Thanks tho :)
  14. TheInvisibleSun


    Buffalo, NY, USA
    The Water
    I'm super late, but several years ago, I found a much more flexible method to changing palettes, courtesy of Gardeguey/GenesisFan64.

    Place this new subroutine right after PalLoad2:

    Code (Text):
    1. ; ||||||||||||||| S U B    R O U T    I N E |||||||||||||||||||||||||||||||||||||||
    4. PalLoad_Loop: ;Quick load
    6.         move.w    (a1)+,(a2)+              ;Copy palette data to RAM
    7.         dbf    d0,PalLoad_Loop               ;Loop d0 (length)
    8.         rts
    and then call for it like this, in your monitor code:

    Code (Text):
    1. move.w #$F,d0                ;Length ($F = full line)
    2. lea    (Pal_Sonic),a1  ;Palette location
    3. lea    ($FFFFFB00),a2        ;RAM location ($FB00 = line 1,$FA80 underwater)
    4. jsr    PalLoad_Loop
    This allows you to almost fully control the palette change (without dealing with the pointers), by dictating how many colors to change (in the first line), and where the change starts by changing the RAM location (meaning, you could specifically change Sonic's blues if you wanted to). Each color represents $2 in ram, so each line of 16 colors accounts for $20. If you want the change to start on the second palette line for example, then you would load the given palette to '$FFFFFB20'.
  15. Hivebrain


    53.4N, 1.5W
    What does the stack contain? At first I thought it was just a list of addresses for keeping track of subroutine branches (plus anything the programmer adds manually), but there seems to be more to it.

    This code that displays Sonic 1's crash error messages has me puzzled:
    Code (Text):
    2. loc_43A:
    3.        disable_ints
    4.        addq.w   #2,sp
    5.        move.l   (sp)+,(v_sp_buffer).w
    6.        addq.w   #2,sp
    7.        movem.l   d0-a7,(v_reg_buffer).w
    8.        bsr.w   ShowErrorMessage
    9.        move.l   2(sp),d0
    10.        bsr.w   ShowErrorValue
    11.        move.l   (v_sp_buffer).w,d0
    12.        bsr.w   ShowErrorValue
    13.        bra.s   loc_478
    If it was just a list of 32-bit addresses, you'd never add 2 to the stack pointer.
  16. Brainulator


    Regular garden-variety member Member
    Given the nature of the RTE instruction, I am going to guess (please, someone make sure I'm thinking correctly!) that it's dealing with the status register.
  17. MarkeyJester


    Original, No substitute Resident Jester
    The stack contents for a BUS/Address error in reverse order:
    • +0 (word) Current state.
    • +2 (long) Error address.
    • +6 (word) Opcode word.
    • +8 (word) sr/ccr (Status Register/Condition Code Register).
    • +A (long) pc (Program Counter).
    As an example of an instruction which will trigger an address error (and it's binary version):
    Code (Text):
    1.         move.w  (1).w,(2).w
    Code (Text):
    1.         31F8 0001 0002
    +0 (word) Current state.

    The current state format in binary: 0000 0000 000R IFFF

    R = R/W - The state of the current cycle (1 = Read | 0 = Write).

    I = I/N - Not sure, though I'm to believe it's "processor activity".

    Basically if the exception is instruction based or not. Now I know, you can argue that almost all exceptions are instruction based, to be clear about what this means; instructions that have their own unique exceptions FOR THAT INSTRUCTION.

    TRAP, TRAPV, CHK, and DIVU/DIVS are such instructions, as they uniquely trigger an exception solely for their circumstance.

    All of the documents I've read over the years have been incredibly vague or seem to overly complicate the explanation but; here is how they define it:
    • "The processor is processing an instruction if it is in the normal state or processing a group 2 exception."
    • "The processor is not processing an instruction if it is processing a group 0 or a group 1 exception."
    For the record, these are the groups:
    • Group 0 exceptions are reset, bus error, and address error.
    • Group 1 exceptions are trace and interrupt, privilege violations, and illegal instructions.
    • Group 2 exceptions are instruction specific based interrupts such as TRAP, TRAPV, CHK, and zero divide.
    Again, because of the vagueness, I can only assume I/N is 0 for group 0 or 1, and 1 for group 2, based on my own testing.

    F = Function Code (FC0, FC1, FC2).
    • 000 = Undefined, Reserved.
    • 001 = User Data.
    • 010 = User Program.
    • 011 = Undefined, Reserved.
    • 100 = Undefined, Reserved.
    • 101 = Supervisor Data.
    • 110 = Supervisor Program.
    • 111 = CPU Space (or "Interrupt acknowledge").
    +2 (long) Error address.

    This will hold the address that triggered the error, so in our example, the instruction would trigger an address error due to read from odd address (1).w, and so the long-word in this stack space would be 00000001.

    +6 (word) Opcode word.

    This will hold the opcode of the instruction that caused the exception; in our case it'll be 31F8 (move.w (ae).w,(ae).w).

    +8 (word) sr/ccr (Status Register/Condition Code Register).

    This will hold a copy of the SR (which also holds the CCR on the lower byte/lowest 5 bits), which can be for returning from the exception routine and resuming, as the previous instruction condition and the status is preserved.

    +A (long) pc (Program Counter).

    This will be the address of the PC when it encountered the error, for our example it'll be pointing to 0002 of our instruction, as it encountered the error on 0001 when attempting to read a word from (1).w address. It should be noted this address can be up to 5 words ahead of the instruction, and does not represent the return address of the next instruction. So when Sonic games allow you to resume by pressing "C", the CPU may not be aligned to the next instruction properly, in our example; the Sonic game will return and the CPU will process the 0002 as if it were an instruction. This reading of garbage can lead to either an immediate second crash, or it'll resume by luck but have processed unintended opcode behavior leading to potential problems further down.

    You do however have access to the opcode, so it is possible to work the ending return address and resume successfully, but Sonic games haven't been written to handle that properly.
    • Like Like x 1
    • Informative Informative x 1
    • Useful Useful x 1
    • List
  18. Foxeh


    Animator Member
    In the Walls
    Sonic AGES and Writing a documentation for Realms
    About the PSP titles, Sonic Rivals and Sonic Rivals 2...

    i know we've gotten far as to extract UMD data from the games, but has anyone ever figured out how to decompile the model/scene/character data so they are viewable?
    you know the characters and stages that sit inside of the STREAM folder with the file extension .STR ?
  19. Mystical Ninja

    Mystical Ninja

    For old time's sake. Oldbie
    New Castle, Delaware
    Nothing that concerns this place in the least.
    So, I've brought a new computer recently, and one of the first things on my list was trying out some Steam games and mods that would not run on my previous one. Just as I was making progress, this error screen popped up:

    As the message says, the program was unable to find the directory where it's supposed to load the game with the mods installed. Since it did not come with a "readme.txt" of any sort, and because I'm pretty new to this in general, I have no idea what I'm supposed to do in order to get this to load properly. Would someone lend me a hand, please?
  20. MainMemory


    Kate the Wolf Tech Member
    You need to extract the mod loader's 7z directly into the "Sonic CD" folder.
    • Informative Informative x 1
    • List