Basic Questions and Answers Thread

Discussion in 'Discussion & Q&A' started by Malevolence, Jul 7, 2009.

  1. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    394
    Location:
    Russia
    Objects usually don't load art themselves, they just store art pointer and mappings offset to display sprite. Objects expect tiles to be loaded already at specified VRAM offset. There is only one exception in Sonic 1, the Sonic's object. It has a routine that loads his tiles dynamically, only ones for the current frame (sprite). I'd add Spin Dust object (Obj05) here, in case you added it with the Spin Dash guide.


    Most of art is loaded during title cards sequence and another part of it is loaded afterwards, overwriting title cards tiles (VRAM space is usually not enough to keep everything, so art is dynamically loaded in certain moments of game). Loading Nemesis compressed art is mainly held by Pattern Load Cues system, there are data blocks telling what to load. Check out _incPattern Load Cues.asm.


    I assume you want to load static uncompressed art on level's init. You can't change the existing code to load some art as uncompressed as there is no 'system' besides PLC to handle this. You need to write a new code for your needs. Actually, it's not a hard thing to do and it doesn't take too much lines.


    First off, you need to set VRAM access at the offset you want to write to. This requires a special request to be sent to the VDP Control Port, format can be found here: http://sonicresearch.org/forums/index.php?showtopic=2199. Dealing with it is a real pain, so I'd suggest using a special macro here:



    ; =============================================================
    ; Macro to set VRAM write access


    ; Arguments: 1 - raw VRAM offset


    ; 2 - register to write access bitfield in (Optional)


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


    vram macro


    if (narg=1)


    move.l #($40000000+((1&$3FFF)<<16)+((1&$C000)>>14)),($C00004).l


    else


    move.l #($40000000+((1&$3FFF)<<16)+((1&$C000)>>14)),2


    endc


    endm



    This macro was taken from SVN disassembly and slightly edited by me. If you are using SVN diasm, it's already there, called vramLoc.


    Now, the code:



    move #$2700,sr ; 68K => disable interrupts
    lea ($C00000).l,a6 ; a6 => VDP Data Port


    vram $XXXX ; VDP => set VRAM access


    lea (YOUR_UNC_ART).l,a1 ; a1 => Uncompressed art


    moveq #XX,d1 ; d1 -> Number of tiles to load minus one


    jsr LoadTiles



    This code should be placed somewhere in "Level:" routine, after 'jsr Hud_Base' line is a good place for it.


    The code uses standard 'LoadTiles' subroutine, which is just designed to load uncompressed tiles. This subroutine needs art offset to be loaded in A1 and number of tiles in D1. Disabling interrupts in the first line will pervert art from being spoiled occasionally, if LoadTiles gets interrupted (interrupt routines set VDP to write to many other locations, breaking the current VRAM offset).
     
    Last edited by a moderator: Feb 7, 2012
  2. Kensou

    Kensou Well-Known Member Member

    Joined:
    Aug 19, 2010
    Messages:
    59
    @Vladikcomper: hey! Thanks! very well explained. :)


    What I want exactly is change the code of one object of the game (the giant ring flash object), and load it as uncompressed art. I'm a little lost yet...
     
    Last edited by a moderator: Feb 7, 2012
  3. Pokepunch

    Pokepunch That guy who posts on occasion Member

    Joined:
    Aug 7, 2009
    Messages:
    270
    Location:
    UK
    Ok. This is annoying the shit out of me now, I have started porting Super Sonic to Sonic 1. The only thing that doesn't work is the ring loss. Here is my code ported from Sonic 2.




    Sonic_Super:


    tst.b ($FFFFFE19).w


    beq.w loc_1AC3C


    tst.b ($FFFFFE1E).w


    beq.s Sonic_RevertToNormal


    tst.b ($FFFFFE1E).w


    beq.s loc_1AC3C


    tst.w ($FFFFFE20).w


    beq.s Sonic_RevertToNormal


    ori.b #1,($FFFFFE1D).w


    cmpi.w #1,($FFFFFE20).w


    beq.s Sonic_SuperRingLoss1


    cmpi.w #10,($FFFFFE20).w


    beq.s Sonic_SuperRingLoss1


    cmpi.w #100,($FFFFFE20).w


    bne.s Sonic_SuperRingLoss2


    Sonic_SuperRingLoss1:


    subq.w #1,($FFFFFE20).w


    ori.b #$80,($FFFFFE1D).w


    Sonic_SuperRingLoss2:


    subq.b #1,($FFFFFE20).w


    loc_1AC3C:


    rts



    I just dont get why it doesn't work.
     
  4. Animemaster

    Animemaster Lets get to work! Member

    Joined:
    Mar 20, 2009
    Messages:
    1,229
    Location:
    UK
    Well I notice that your subq needs to be a word. The subq in SuperRingloss2 is byte rather than word. I know it sounds like it couldn't do anything, but try it, you never know. I've never had any problems with the decreaseing in the past, but its been awhile.
     
  5. Kensou

    Kensou Well-Known Member Member

    Joined:
    Aug 19, 2010
    Messages:
    59
    Well, I make it as you said and it works fine, but sometimes, when the ring is loaded, I can see a red flash on the screen that I don't like nothing... any other way to do this preventing this?
     
  6. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    394
    Location:
    Russia

    From what you said, I'm not able to guess what could cause this issue. If you want to get a proper help, please provide more information on your problem.


    Describe the flash, how it looks, if it covers the whole screen or just some part of it. Show the code itself, and tell me, where did you place it exactly?

    As Animemaster said, you have a wrong type here:



    Sonic_SuperRingLoss2:
    subq.b #1,($FFFFFE20).w



    The fact is, after such a subtraction, the rings counter will be decreased by $100 instead of 1, because you subtract from only the first byte of it.


    For example, if you rings counter was: $000B (11 rings), after subtraction it will become $FF0B (65291 rings).


    Also, according to the original code 'subq.w #1,($FFFFFE20).w' in 'Sonic_SuperRingLoss1' is odd. You will subtract a ring twice, if branch to 'Sonic_SuperRingLoss1' will work. In original code, its purpose was to set a special flag when the ring counter decreases from 100 to 99, 10 to 9 or 1 to 0. This is done to update the rings counter on HUD properly.


    Another odd thing in you code:



    tst.b ($FFFFFE1E).w
    beq.s Sonic_RevertToNormal


    tst.b ($FFFFFE1E).w


    beq.s loc_1AC3C



    Duplicate branch. I guess you don't need the last one (it will never work btw).


    In Sonic 2, this branch was to undo transformation when timer on HUD is stopped. This happens once you finished the level, so Sonic will revert to normal form then.


    Also, you didn't port a frame counter part from the original code. It was meant to decrease rings in every second. Without it, it will be done every frame.
     
  7. Kensou

    Kensou Well-Known Member Member

    Joined:
    Aug 19, 2010
    Messages:
    59
    Well, I haven't the code here, so I will post later to show it to you. I think the problem has somthing to be with the interrupts, is not a perfect red flash, it change the pallete to rare colors (but the most is red) for about a frame or so.


    I'm using your s1hs v2 disassembly if it helps.
     
  8. Kensou

    Kensou Well-Known Member Member

    Joined:
    Aug 19, 2010
    Messages:
    59
    Here is the code:


    I put it in "SignpostArtLoad:" just before these two lines:



    moveq #$12,d0
    bra.w LoadPLC2 ; load signpost patterns



    and the code itself to load the art:



    move #$2700,sr
    lea ($C00000).l,a6


    vram $8C40


    lea (ArtUnc_RngFlash).l,a1


    moveq #83,d1


    jsr LoadTiles



    What do you think?
     
  9. Pokepunch

    Pokepunch That guy who posts on occasion Member

    Joined:
    Aug 7, 2009
    Messages:
    270
    Location:
    UK
    I have edited my code to match it closer to Sonic 2's, But it still wont work:




    Sonic_Super:


    tst.b ($FFFFFE19).w


    beq.w return_1AC3C


    tst.b ($FFFFFE1E).w


    beq.s Sonic_RevertToNormal


    subq.w #1,($FFFFF670).w


    bpl.w return_1AC3C


    move.w #60,($FFFFF670).w ; Reset frame counter to 60


    tst.w ($FFFFFE20).w


    beq.s Sonic_RevertToNormal


    ori.b #1,($FFFFFE1D).w


    cmpi.w #1,($FFFFFE20).w


    beq.s Sonic_SuperRingLoss1


    cmpi.w #10,($FFFFFE20).w


    beq.s Sonic_SuperRingLoss1


    cmpi.w #100,($FFFFFE20).w


    bne.s Sonic_SuperRingLoss2


    Sonic_SuperRingLoss1:


    move.b #$80,($FFFFFE1D).w


    Sonic_SuperRingLoss2:


    subq.w #1,($FFFFFE20).w


    bne.s return_1AC3C
     
  10. Animemaster

    Animemaster Lets get to work! Member

    Joined:
    Mar 20, 2009
    Messages:
    1,229
    Location:
    UK
    Why did you change this: ori.b #$80,($FFFFFE1D).w, to this move.b #$80,($FFFFFE1D).w.


    .
     
    Last edited by a moderator: Feb 9, 2012
  11. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    394
    Location:
    Russia
    @cookietheguineapig: The address $FFFFF670 you used for the frame counter overlaps with some palette cycling vars in Sonic 1. This can be one of the reasons this code won't work. And yes, there was nothing wrong with ORI, no reason to change it. It will work either way though.

    Well, you did this part absolutely right. The code is in correct place, it will run once, along with PLC loading code. So, the problem sits somewhere else.


    Check out your 'Pattern Load Cues.asm':



    PLC_Signpost: dc.w 2
    dc.l Nem_SignPost ; signpost


    dc.w $D000


    dc.l Nem_Bonus ; hidden bonus points


    dc.w $96C0


    dc.l Nem_BigFlash ; giant ring flash effect


    dc.w $8C40



    If you removed ring flash art from here, be sure to change 'dc.w 2' line. This one tells how many cues are in this block. Once you delete something, you have to decrease this number, or else odd/corrupted art will be loaded. This may cause game crash or graphical artifacts.
     
  12. Kensou

    Kensou Well-Known Member Member

    Joined:
    Aug 19, 2010
    Messages:
    59
    @Vladikcomper: Yes, I know about PLC and I did it right. I don't know why that happens. I even try with queque transfer but it interfierce with other objects I created that uses that technique... I really don't know what to do to make it work fine. The bug I told you is noticeable in LZ...
     
  13. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    394
    Location:
    Russia
    Is it seen in LZ only? If yes, it's probably interrupts issue. LZ uses a horizontal interrupt to change palette to an underwater one. The interrupt can occur anytime and anywhere, interrupting currently running code. The higher water line is, the sooner interrupt will occur after starting a new frame.


    If you code runs before interrupt occurs, then after disabling interrupts, it won't occur at all, until all the routines in 'Level_MainLoop' are launched and 'DelayProgram' is reached (it's better be called 'WaitForVBlank' or something like this). This means, the palette won't change when it should and you will see screen flash with all dry palette.


    I'm not sure if it can cause the red flash you're describing. However, this interrupt problem can happen in LZ anyways. Loading tiles during frame displaying takes too long, covering a huge part of screen, on which interrupts can't occur.


    You see the solution right. The best way would be to use DMA transferring system, then you won't have to disable interrupts and waste time on loading art during frame displaying. As art will be loaded during VBlank, it won't conflict with anything.


    What do you mean about interfering with other objects? Have you overloaded DMA queue, so it overflows or what?
     
  14. Kensou

    Kensou Well-Known Member Member

    Joined:
    Aug 19, 2010
    Messages:
    59
    Thanks for your explanation, very useful info.

    I have another object that follows Sonic and is loaded by DMA queque and when the signpost art and the big ring was loaded by DMA queque, that other object is showed as garbage :S
     
  15. Pokepunch

    Pokepunch That guy who posts on occasion Member

    Joined:
    Aug 7, 2009
    Messages:
    270
    Location:
    UK
    Well I changed the address and it still wont work.




    Sonic_Super:


    tst.b ($FFFFFE19).w


    beq.w return_1AC3C


    tst.b ($FFFFFE1E).w


    beq.s Sonic_RevertToNormal


    subq.w #1,($FFFFFFAC).w


    bpl.w return_1AC3C


    move.w #60,($FFFFFFAC).w ; Reset frame counter to 60


    tst.w ($FFFFFE20).w


    beq.s Sonic_RevertToNormal


    ori.b #1,($FFFFFE1D).w


    cmpi.w #1,($FFFFFE20).w


    beq.s Sonic_SuperRingLoss1


    cmpi.w #10,($FFFFFE20).w


    beq.s Sonic_SuperRingLoss1


    cmpi.w #100,($FFFFFE20).w


    bne.s Sonic_SuperRingLoss2


    Sonic_SuperRingLoss1:


    ori.b #$80,($FFFFFE1D).w


    Sonic_SuperRingLoss2:


    subq.w #1,($FFFFFE20).w


    bne.s return_1AC3C
     
  16. Irixion

    Irixion Well-Known Member Member

    Joined:
    Aug 11, 2007
    Messages:
    670
    Location:
    Ontario, Canada
    Well what about those RAM addresses? :p
     
  17. Kensou

    Kensou Well-Known Member Member

    Joined:
    Aug 19, 2010
    Messages:
    59
    It was my mistake, it has been fixed and it's fully working. Thanks!
     
  18. Pokepunch

    Pokepunch That guy who posts on occasion Member

    Joined:
    Aug 7, 2009
    Messages:
    270
    Location:
    UK
    I made sure that they weren't used.
     
  19. Irixion

    Irixion Well-Known Member Member

    Joined:
    Aug 11, 2007
    Messages:
    670
    Location:
    Ontario, Canada
    Your frame counter RAM address, is it correct? I mean that's the only thing that I can think of that would prevent it from working, your code seems perfectly fine (at this moment anyway, I'm really tired :<)
     
  20. Psycho RFG

    Psycho RFG Well-Known Member Member

    Joined:
    Feb 22, 2011
    Messages:
    233
    I don't know what is happening wiht SonMapEd... It always give problems but I always find a way to make it work but this time it looks I can't do it. I'm adding new sprites to Sonic, but when I import my images, the bg color appears wrong :S so it looks that it doesn't take the transparency color...


    I have tried saving my images in diferent formats, copy and paste in another that works, and even exporting the sprites with SonMaPed (because I already added this sprites many time ago to a rom project to test), editing the palette of the image to fit the colors with original Sonic 1... but now it looks it's impossible... any idea of what can I try?


    Edit: Nevermind, it works fine now :S
     
    Last edited by a moderator: Feb 13, 2012