don't click here

Debugging misaligned read/write

Discussion in 'Engineering & Reverse Engineering' started by flamewing, Mar 10, 2011.

  1. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    Inside the spoiler tag below is the original post, which I am preserving; here is the new version.

    An address error happens on real hardware (or in good emulators such as Regen) whenever a word- or long-sized read or write happens at an odd address. So, for example, if you try to read the contents of address $FFFF0001 as if it were a word or a long, an address error will happen. Sonic 1 displays a simple error message; Sonic 2 locks up; Sonic 3 and Sonic & Knuckles reset the game. None of these scenarios are useful for finding out what caused the error, which is usually what prevents hacks from working on real hardware.

    I decided to include the bus error in the debugger solely because it has the same data available for debugging as an address error does; the changes were minor enough that I had no real reason not to include it, but I have doubts anyone will need it.

    Here is the debugger: address/bus error debugger; I explain below how it is used. I have tried it with the Hg disassemblies of S2 and S&K; I think it will work on Xenowhirl's 2007 disassembly for all those masochistic enough to insist on using an outdated disassembly; if it doesn't, I would appreciate knowing what errors are printed when assembling so I can fix them. At present, only AS is supported.

    To use the debugger, proceed as follows:

    1) Extract all files to the base directory on your disassembly. At any point (for example, at the end of the disassembly), add the following line:
    Code (Text):
    1.     include "Address Error.asm"
    2) Find the label 'Vectors:' at the start of the disassembly:
    S2 disassembly:
    Find this:
    Code (Text):
    1. ;Vectors:
    2.     dc.l System_Stack, EntryPoint, ErrorTrap, ErrorTrap; 4
    and change it to this:
    Code (Text):
    1. ;Vectors:
    2.     dc.l System_Stack, EntryPoint, BusError , AddressError; 4
    S&K disassembly:
    Find this:
    Code (Text):
    1. Vectors:    dc.l Vectors, EntryPoint, ErrorTrap, ErrorTrap  ; 0
    and change it to look like this:
    Code (Text):
    1. Vectors:    dc.l Vectors, EntryPoint, BusError, AddressError    ; 0
    3) Open the file "Address Error.asm". Locate the labels 'HackerName' and 'EMailmsg' and edit them to your heart's content; if 'EMailmsg' is empty, the entire line containing it will be eliminated (see image below). The text must be in all-capitals, and can include letters, numbers, spaces or the following symbols:
    Code (Text):
    1. ? @ [ ] \ ( ) + , - . / : ; # $ % & ! *
    4) Find the 'Revision' equate and change the number. This is so you can give an internal identifier to any build of the hack.

    5) When building the hack for testing, add '-g MAP' to the line invoking asw/asl. This will generate a file '*.map' file that associates each file/line of the source file(s) to an address on the final ROM. The build will be a lot slower, though.

    6)
    If you are using the Hg disassemblies, you are done. If you are using the S2 2007 disassembly, you still have to do a few things:

    a) Find the following lines in s2.asm:
    Code (Text):
    1. dma68kToVDP macro source,dest,length,type
    2.     lea (VDP_control_port).l,a5
    3.     move.l  #(($9400|((((length)>>1)&$FF00)>>8))<<16)|($9300|(((length)>>1)&$FF)),(a5)
    4.     move.l  #(($9600|((((source)>>1)&$FF00)>>8))<<16)|($9500|(((source)>>1)&$FF)),(a5)
    5.     move.w  #$9700|(((((source)>>1)&$FF0000)>>16)&$7F),(a5)
    6.     move.w  #((dest)&$3FFF)|((type&1)<<15)|$4000,(a5)
    7.     move.w  #$80|(((dest)&$C000)>>14)|((type&2)<<3),(DMA_data_thunk).w
    8.     move.w  (DMA_data_thunk).w,(a5)
    9.     endm
    10.     ; values for the type argument
    11.     enum VRAM=0,CRAM=1,VSRAM=2
    12.  
    13. ; tells the VDP to fill a region of VRAM with a certain byte
    14. dmaFillVRAM macro byte,addr,length
    15.     lea (VDP_control_port).l,a5
    16.     move.w  #$8F01,(a5) ; VRAM pointer increment: $0001
    17.     move.l  #(($9400|((((length)-1)&$FF00)>>8))<<16)|($9300|(((length)-1)&$FF)),(a5) ; DMA length ...
    18.     move.w  #$9780,(a5) ; VRAM fill
    19.     move.l  #$40000080|(((addr)&$3FFF)<<16)|(((addr)&$C000)>>14),(a5) ; Start at ...
    20.     move.w  #(byte)<<8,(VDP_data_port).l ; Fill with byte
    21. -   move.w  (a5),d1
    22.     btst    #1,d1
    23.     bne.s   - ; busy loop until the VDP is finished filling...
    24.     move.w  #$8F02,(a5) ; VRAM pointer increment: $0002
    25.     endm
    and replace them with this:
    Code (Text):
    1. vdpComm function addr,type,rwd,(((type&rwd)&3)<<30)|((addr&$3FFF)<<16)|(((type&rwd)&$FC)<<2)|((addr&$C000)>>14)
    2. ; values for the type argument
    3. VRAM = %100001
    4. CRAM = %101011
    5. VSRAM = %100101
    6. ; values for the rwd argument
    7. READ = %001100
    8. WRITE = %000111
    9. DMA = %100111
    10. dma68kToVDP macro source,dest,length,type
    11.     lea (VDP_control_port).l,a5
    12.     move.l  #(($9400|((((length)>>1)&$FF00)>>8))<<16)|($9300|(((length)>>1)&$FF)),(a5)
    13.     move.l  #(($9600|((((source)>>1)&$FF00)>>8))<<16)|($9500|(((source)>>1)&$FF)),(a5)
    14.     move.w  #$9700|(((((source)>>1)&$FF0000)>>16)&$7F),(a5)
    15.     move.w  #((vdpComm(dest,type,DMA)>>16)&$FFFF),(a5)
    16.     move.w  #(vdpComm(dest,type,DMA)&$FFFF),(DMA_data_thunk).w
    17.     move.w  (DMA_data_thunk).w,(a5)
    18.     endm
    19. ; tells the VDP to fill a region of VRAM with a certain byte
    20. dmaFillVRAM macro byte,addr,length
    21.     lea (VDP_control_port).l,a5
    22.     move.w  #$8F01,(a5) ; VRAM pointer increment: $0001
    23.     move.l  #(($9400|((((length)-1)&$FF00)>>8))<<16)|($9300|(((length)-1)&$FF)),(a5) ; DMA length ...
    24.     move.w  #$9780,(a5) ; VRAM fill
    25.     move.l  #$40000080|(((addr)&$3FFF)<<16)|(((addr)&$C000)>>14),(a5) ; Start at ...
    26.     move.w  #(byte)<<8,(VDP_data_port).l ; Fill with byte loop:
    27. loop:
    28.     move.w  (a5),d1
    29.     btst    #1,d1
    30.     bne.s   loop ; busy loop until the VDP is finished filling...
    31.     move.w  #$8F02,(a5) ; VRAM pointer increment: $0002
    32.     endm
    b) Open "Address Error Defs.asm" and replace the following lines:
    Code (Text):
    1. EniDec := Eni_Decomp KosDec := Kos_Decomp PlaneMapToVRAM := Plane_Map_To_VRAM
    with this:
    Code (Text):
    1. Chunk_Table := Metablock_Table
    2. PlaneMapToVRAM := ShowVDPGraphics
    Once all of this is done, the screen is ready for use. To test it and see if it is working, you can add this code anywhere you are sure will execute:
    Code (Text):
    1.     movea.w #$0001,a0
    2.     jmp (a0)
    Of course, the disassembler does not initialize the z80 or the VDP, instead assuming that they have been initialized already; so the test code must go after the initialization code for them both, or you will get a black screen. Here is a sample of the output:
    [​IMG]
    It has a readable version of all data saved on a bus/address error, all registers, and a disassembly of the instruction that caused the address error. The disassembler was hand-coded, and recovers as much information as possible. Jumps, branches and loops usually do not allow full recovery, with jsr, bsr, and being exceptions. Nevertheless, only jmp will be an issue because all the others are caught by the assembler when building the ROM. The disassembler also warns when the disassembly could not retrieve all information.

    Being in possession of all this data and of the map file allows you to quickly find where the error happened and give you an idea why.

    I would appreciate if anyone could test this on real hardware; I know it works on Regen, but I don't know if Regen works the same way as real hardware does with respect to the behavior of the program counter.

    For those that got this earlier in another thread: this version has a bug fix on the disassembler, and does not need separate versions for S2 and S&K disassemblies; you should grab this version.

    I will start by saying that this tutorial was made using the S2 SVN Disassembly; it can be adapted to other disassemblies (may need to change constant and function names) or other Genesis Sonic games (may need to change constant and function names, layout of attached Enigma mappings).

    One thing that frequently pops up in hacks is that they crash on Regen, Kega or on real hardware, but work on other emulators (such as the Gens family). This is more often than not caused by a misaligned read or write of a word-sized or larger chunk of data; this is usually bad because it is a pain to debug using available tools. As a result, afflicted hacks will usually remain unplayable in real hardware or Regen or Kega.

    In this tutorial, I will explain how to use the "address error" interrupt to make debugging easier in these cases.

    If you don't know what an interrupt is, you should read a bit about them here.

    The address error interrupt is triggered when there is a misaligned read or write of a word-sized or larger chunk of data. Normally, Sonic games have a generic useless error trap for all interrupts -- with V-Int and H-Int being the sole exceptions -- which either locks up the game (as in S2) or resets the game (as in S3&K). So we have to edit the interrupt table and add a handler for this interrupt.

    So open up your s2.asm and find this:
    Syntax Highlighted Code: ASMStartOfRom:
    if * <> 0
    fatal "StartOfRom was $\{*} but it should be 0"
    endif
    ;Vectors:
    dc.l System_Stack, EntryPoint, ErrorTrap, ErrorTrap; 4

    This is the start of the interrupt table. The first two interrupts (the ErrorTrap's shown) are for bus error ("access fault") and address error interrupts. Both of these interrupts have the same stack layout when they are triggered:
    CODEBit 15 5 4 3 2 0
    SP ->[ |R/W|I/N|code]
    ---------------------------
    [ Access HIGH ] \_ the address that was read/written to
    [ address LOW ] /
    ---------------------------
    [ Instruction register ]
    ---------------------------
    [ Status register ]
    ---------------------------
    [ Program HIGH ] \_ the code that triggered the read/write
    [ counter LOW ] /
    R/W: if 0, write; if 1, read
    I/N: if 0, instruction; if 1, not instruction
    This is all the information we need to debug the hack. In this tutorial, I care only about the address error interrupt; so go ahead and change the interrupt table to this:
    Syntax Highlighted Code: ASMStartOfRom:
    if * <> 0
    fatal "StartOfRom was $\{*} but it should be 0"
    endif
    ;Vectors:
    dc.l System_Stack, EntryPoint, ErrorTrap, AddressError; 4
    We now have to define a useful handler for it. The most basic one is this:
    Syntax Highlighted Code: ASMAddressError:
    nop
    nop
    bra.s AddressError
    It is also not that useful unless you want to dig through the 68000 debugger and RAM viewer of a debug-enabled build of Regen; so lets make it more useful.

    Start by getting the attached file. These are Enigma mappings for an error screen. Put them into the mappings/misc directory of your disassembly (or somewhere else you prefer). Then, add the following code somewhere in your disassembly:
    Syntax Highlighted Code: ASMdebugAddressError = 1
    if debugAddressError
    ;---------------------------------------------------------------------------------------
    ; Enigma compressed mappings
    even
    MapEng_AddressError: BINCLUDE "mappings/misc/AddressError.bin"
    even

    ; ===========================================================================
    ; Crash/Freeze the 68000 and display error message. Note that the Z80 continues to run, so the music keeps playing.
    AddressError:
    movem.l d0-a6,-(sp)
    lea (VDP_control_port).l,a6
    move.w #$8B03,(a6) ; EXT-INT disabled, V scroll by screen, H scroll by line
    move.w #$8230,(a6) ; PNT A base: $C000
    move.w #$8407,(a6) ; PNT B base: $E000
    move.w #$857C,(a6) ; Sprite attribute table base: $F800
    move.w #$9001,(a6) ; Scroll table size: 64x32
    move.w #$8004,(a6) ; H-INT disabled
    move.w #$8720,(a6) ; Background palette/color: 2/0
    move.w #$8C81,(a6) ; H res 40 cells, no interlace
    move.w #$8ADF,(Hint_counter_reserve).w ; H-INT every 223rd scanline
    dmaFillVRAM 0,$0000,$10000

    moveq #PalID_BGND,d0
    bsr.w PalLoad1 ; load Sonic's palette line

    move.w (VDP_Reg1_val).w,d0
    ori.b #$40,d0
    move.w d0,(VDP_control_port).l
    bsr.w Pal_FadeTo

    move.l #vdpComm(tiles_to_bytes(ArtTile_ArtNem_FontStuff),VRAM,WRITE),(VDP_control_port).l
    lea (ArtNem_FontStuff).l,a0
    bsr.w NemDec

    lea (Chunk_Table).l,a1
    lea (MapEng_AddressError).l,a0
    move.w #make_art_tile($0000,0,0),d0
    bsr.w EniDec

    lea (Chunk_Table + 12 * 2 + $50 * 3).l,a6

    lea $3C(sp),a0
    move.w (a0)+,d0
    move.w #make_block_tile($0034,0,0,0,0), d1 ;W
    btst #4,d0
    beq.s +
    move.w #make_block_tile($002F,0,0,0,0), d1 ;R
    +
    move.w d1,(a6)+
    move.w #make_block_tile($0026,0,0,0,0), d1 ;I

    btst #3,d0
    beq.s +
    move.w #make_block_tile($002B,0,0,0,0), d1 ;N
    +
    move.w d1,(a6)

    move.w (a0)+,d0
    swap d0
    move.w (a0)+,d0
    lea (Chunk_Table + 21 * 2 + $50 * 5).l,a1
    move.w #7,d2
    bsr.s HexDump

    move.w (a0)+,d0
    swap d0
    move.w (a0)+,d0
    lea (Chunk_Table + 27 * 2 + $50 * 7).l,a1
    move.w #3,d2
    bsr.s HexDump
    nop
    nop

    lea (Chunk_Table + 22 * 2 + $50 * 9).l,a1
    move.w #3,d2
    bsr.s HexDump

    move.w (a0)+,d0
    swap d0
    move.w (a0)+,d0
    lea (Chunk_Table + 22 * 2 + $50 * 11).l,a1
    move.w #7,d2
    bsr.s HexDump

    lea (Chunk_Table).l,a1
    move.l #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0
    moveq #$27,d1 ; 40 cells wide
    moveq #$1B,d2 ; 28 cells tall
    bsr.w PlaneMapToVRAM

    movem.l (sp)+,d0-a6
    -
    move.b #4,(Vint_routine).w
    bsr.w WaitForVint
    nop
    nop
    bra.s -

    HexDump:
    moveq #0,d3
    -
    rol.l #4,d0
    move.b d0,d3
    andi.b #$F,d3
    cmpi.b #$9,d3
    bls.s +
    addi.b #4,d3
    +
    addi.w #make_block_tile($0010,0,0,0,0),d3
    move.w d3,(a1)+
    dbra d2,-
    rts
    else
    AddressError:
    nop
    nop
    bra.s AddressError
    endif
    If you want to build a version without the debug code, just change the line
    Syntax Highlighted Code: ASMdebugAddressError = 1
    to
    Syntax Highlighted Code: ASMdebugAddressError = 0
    Now we have all of this wonderful information:
    • Access address: where is the data that was read/written which triggered the interrupt;
    • Program counter: what instruction triggered the interrupt.
    In order to use this information, we have to create a debug file. Open build.bat and find the line
    CODEIF "%1"=="-pe" ( "win32/asw" -xx -c -A s2.asm ) ELSE "win32/asw" -xx -c -E -A s2.asm
    Replace it with this:
    CODEIF "%1"=="-pe" ( "win32/asw" -xx -c -g MAP -A s2.asm ) ELSE "win32/asw" -xx -c -E -g MAP -A s2.asm
    This instructs AS to create a s2.map file. The format of this file is detailed in the AS user manual. This file can be used with the information above to pinpoint the line which triggered the address error interrupt, as well as the code that triggered it. Fixing the error should be academic.

    All you have to do now is build your ROM and test.

    Here is a screenshot showing the result of the above code:
    [​IMG]
    For this test, I changed the line
    Syntax Highlighted Code: ASMObj0E_MapUnc_136A8: BINCLUDE "mappings/sprite/obj0E.bin"
    into
    Syntax Highlighted Code: ASM dc.b 0
    Obj0E_MapUnc_136A8: BINCLUDE "mappings/sprite/obj0E.bin"
    even
    which causes the error to pop up as soon as the title screen loads. (I also tested it in my Sonic 2 Heroes hack, so your addresses will probably be different from what is in the screenshot).

    Please ignore this attachment, it is of the older version:
     

    Attached Files:

  2. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    I updated the address error with a vastly superior version that includes a hand-coded disassembler. Look at the post above for details on how to use it and the download link.
     
  3. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Cheers, just one problem:

    Code (Text):
    1. > > >Address Error.asm(99): error: unknown function
    2. > > > VDPCOMM
    3. > > >   move.l  #vdpComm($0000,VSRAM,WRITE),(a6)
    4. > > >Address Error.asm(321): error: unknown function
    5. > > > VDPCOMM
    6. > > >   move.l  #vdpComm(VRAM_Plane_A_Name_Table,VRAM,WRITE),d0
    Probably because I'm using xenowhirls 2007.


    I now know why my hack is freezing too, just not sure how to solve it so hopefully this will help once in.
     
  4. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    Add these lines to 'Address Error Defs.asm' just under the line with 'make_art_tile':
    Code (Text):
    1. vdpComm function addr,type,rwd,(((type&rwd)&3)<<30)|((addr&$3FFF)<<16)|(((type&rwd)&$FC)<<2)|((addr&$C000)>>14)
    2. ; values for the type argument
    3. VRAM = %100001
    4. CRAM = %101011
    5. VSRAM = %100101
    6.  
    7. ; values for the rwd argument
    8. READ = %001100
    9. WRITE = %000111
    10. DMA = %100111
    11.  
    Edit: you will also need to find in s2.asm the definitions of dma68kToVDP and dmaFillVRAM and replace them both by this:
    Code (Text):
    1. ; tells the VDP to copy a region of 68k memory to VRAM or CRAM or VSRAM
    2. dma68kToVDP macro source,dest,length,type
    3.     lea (VDP_control_port).l,a5
    4.     move.l  #(($9400|((((length)>>1)&$FF00)>>8))<<16)|($9300|(((length)>>1)&$FF)),(a5)
    5.     move.l  #(($9600|((((source)>>1)&$FF00)>>8))<<16)|($9500|(((source)>>1)&$FF)),(a5)
    6.     move.w  #$9700|(((((source)>>1)&$FF0000)>>16)&$7F),(a5)
    7.     move.w  #((vdpComm(dest,type,DMA)>>16)&$FFFF),(a5)
    8.     move.w  #(vdpComm(dest,type,DMA)&$FFFF),(DMA_data_thunk).w
    9.     move.w  (DMA_data_thunk).w,(a5)
    10.     endm
    11.  
    12. ; tells the VDP to fill a region of VRAM with a certain byte
    13. dmaFillVRAM macro byte,addr,length
    14.     lea (VDP_control_port).l,a5
    15.     move.w  #$8F01,(a5) ; VRAM pointer increment: $0001
    16.     move.l  #(($9400|((((length)-1)&$FF00)>>8))<<16)|($9300|(((length)-1)&$FF)),(a5) ; DMA length ...
    17.     move.w  #$9780,(a5) ; VRAM fill
    18.     move.l  #$40000080|(((addr)&$3FFF)<<16)|(((addr)&$C000)>>14),(a5) ; Start at ...
    19.     move.w  #(byte)<<8,(VDP_data_port).l ; Fill with byte
    20. loop:   move.w  (a5),d1
    21.     btst    #1,d1
    22.     bne.s   loop ; busy loop until the VDP is finished filling...
    23.     move.w  #$8F02,(a5) ; VRAM pointer increment: $0002
    24.     endm
     
  5. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    I now have 72 errors, something to do with VDPCOMM. Here are some typical errors:

    Code (Text):
    1. > > >s2.asm(985) DMA68KTOVDP(5): error: unknown function
    2. > > > VDPCOMM
    3. > > >         move.w  #((vdpComm($0000,CRAM,DMA)>>16)&$FFFF),(a5)
    4. > > >s2.asm(985) DMA68KTOVDP(6): error: unknown function
    5. > > > VDPCOMM
    6. > > >         move.w  #(vdpComm($0000,CRAM,DMA)&$FFFF),(DMA_data_thunk).w
    7. > > >s2.asm(991) DMA68KTOVDP(5): error: unknown function
    8. > > > VDPCOMM
    9. > > >         move.w  #((vdpComm($0000,CRAM,DMA)>>16)&$FFFF),(a5)
    10. > > >s2.asm(991) DMA68KTOVDP(6): error: unknown function
    11. > > > VDPCOMM
    12. > > >         move.w  #(vdpComm($0000,CRAM,DMA)&$FFFF),(DMA_data_thunk).w
    13. > > >s2.asm(1019) DMA68KTOVDP(5): error: unknown function
    14. > > > VDPCOMM
    15. > > >         move.w  #((vdpComm($F800,VRAM,DMA)>>16)&$FFFF),(a5)


    I will say, I commented the last line out here:

    Code (Text):
    1.     ; values for the type argument
    2. ;    enum VRAM=0,CRAM=1,VSRAM=2
    Otherwise, I got 3 errors saying the double defined.
     
  6. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    Move the vdpComm definition (and the constants below) to right above the dma68kToVDP definition.
     
  7. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    I'm not sure what you mean. If you mean not to have them to the very left hand side as labels, that's already so:

    Code (Text):
    1. ; simplifying macros
    2.  
    3. ; tells the VDP to copy a region of 68k memory to VRAM or CRAM or VSRAM
    4. dma68kToVDP macro source,dest,length,type
    5.     lea (VDP_control_port).l,a5
    6.     move.l  #(($9400|((((length)>>1)&$FF00)>>8))<<16)|($9300|(((length)>>1)&$FF)),(a5)
    7.     move.l  #(($9600|((((source)>>1)&$FF00)>>8))<<16)|($9500|(((source)>>1)&$FF)),(a5)
    8.     move.w  #$9700|(((((source)>>1)&$FF0000)>>16)&$7F),(a5)
    9.     move.w  #((vdpComm(dest,type,DMA)>>16)&$FFFF),(a5)
    10.     move.w  #(vdpComm(dest,type,DMA)&$FFFF),(DMA_data_thunk).w
    11.     move.w  (DMA_data_thunk).w,(a5)
    12.     endm
    13.     ; values for the type argument
    14. ;    enum VRAM=0,CRAM=1,VSRAM=2
    15.  
    16. ; tells the VDP to fill a region of VRAM with a certain byte
    17. dmaFillVRAM macro byte,addr,length
    18.     lea (VDP_control_port).l,a5
    19.     move.w  #$8F01,(a5) ; VRAM pointer increment: $0001
    20.     move.l  #(($9400|((((length)-1)&$FF00)>>8))<<16)|($9300|(((length)-1)&$FF)),(a5) ; DMA length ...
    21.     move.w  #$9780,(a5) ; VRAM fill
    22.     move.l  #$40000080|(((addr)&$3FFF)<<16)|(((addr)&$C000)>>14),(a5) ; Start at ...
    23.     move.w  #(byte)<<8,(VDP_data_port).l ; Fill with byte
    24. loop:  
    25.   move.w    (a5),d1
    26.     btst    #1,d1
    27.     bne.s   loop ; busy loop until the VDP is finished filling...
    28.     move.w  #$8F02,(a5) ; VRAM pointer increment: $0002
    29.     endm
     
  8. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    I meant this:
     
  9. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Okay, that's bit is fixed, it passed the first one, 2nd pass, failed. 83 errors. I'm really sorry, I feel like I'm annoying you =P


    Here's the errors (spoiler as quite big)

    > > >Address Error Defs.asm(18): error: symbol undefined
    > > > Eni_Decomp
    > > > EniDec := Eni_Decomp
    > > >Address Error Defs.asm(19): error: symbol undefined
    > > > Kos_Decomp
    > > > KosDec := Kos_Decomp
    > > >Address Error Defs.asm(20): error: symbol undefined
    > > > Plane_Map_To_VRAM
    > > > PlaneMapToVRAM := Plane_Map_To_VRAM
    > > >Address Error.asm(108): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table).l,a1
    > > >Address Error.asm(108): error: addressing mode not allowed here
    > > > lea (Chunk_Table).l,a1
    > > >Address Error.asm(110) DMA68KTOVDP(3): error: symbol undefined
    > > > CHUNK_TABLE
    > > > move.l #(($9600|((((CHUNK_TABLE)>>1)&$FF00)>>8))<<16)|($9500|(((CHUNK_TABLE)>>1)&$FF)),(a5)
    > > >Address Error.asm(110) DMA68KTOVDP(3): error: symbol undefined
    > > > CHUNK_TABLE
    > > > move.l #(($9600|((((CHUNK_TABLE)>>1)&$FF00)>>8))<<16)|($9500|(((CHUNK_TABLE)>>1)&$FF)),(a5)
    > > >Address Error.asm(110) DMA68KTOVDP(4): error: symbol undefined
    > > > CHUNK_TABLE
    > > > move.w #$9700|(((((CHUNK_TABLE)>>1)&$FF0000)>>16)&$7F),(a5)
    > > >Address Error.asm(113): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table).l,a1
    > > >Address Error.asm(113): error: addressing mode not allowed here
    > > > lea (Chunk_Table).l,a1
    > > >Address Error.asm(120): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(5, 0)).l,a5
    > > >Address Error.asm(120): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(5, 0)).l,a5
    > > >Address Error.asm(125): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(28, 8)).l,a5
    > > >Address Error.asm(125): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(28, 8)).l,a5
    > > >Address Error.asm(131): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(1, 9)).l,a5
    > > >Address Error.asm(131): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(1, 9)).l,a5
    > > >Address Error.asm(142): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(8, 11)).l,a2
    > > >Address Error.asm(142): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(8, 11)).l,a2
    > > >Address Error.asm(153): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(13, 1)).l,a5
    > > >Address Error.asm(153): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(13, 1)).l,a5
    > > >Address Error.asm(181): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(24, 1)).l,a1
    > > >Address Error.asm(181): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(24, 1)).l,a1
    > > >Address Error.asm(184): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(31, 11)).l,a1
    > > >Address Error.asm(184): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(31, 11)).l,a1
    > > >Address Error.asm(194): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(5, 12)).l,a1
    > > >Address Error.asm(194): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(5, 12)).l,a1
    > > >Address Error.asm(198): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(18, 12)).l,a1
    > > >Address Error.asm(198): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(18, 12)).l,a1
    > > >Address Error.asm(207): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(31, 12)).l,a1
    > > >Address Error.asm(207): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(31, 12)).l,a1
    > > >Address Error.asm(212): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(DisassemblyAlign, 4)).l,a5
    > > >Address Error.asm(212): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(DisassemblyAlign, 4)).l,a5
    > > >Address Error.asm(224): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(2, 3)).l,a1
    > > >Address Error.asm(224): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(2, 3)).l,a1
    > > >Address Error.asm(237): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(1, 6)).l,a5
    > > >Address Error.asm(237): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(1, 6)).l,a5
    > > >Address Error.asm(242): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(11, 13)).l,a1
    > > >Address Error.asm(242): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(11, 13)).l,a1
    > > >Address Error.asm(249): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(31, 13)).l,a1
    > > >Address Error.asm(249): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(31, 13)).l,a1
    > > >Address Error.asm(257): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(5, 16)).l,a2
    > > >Address Error.asm(257): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(5, 16)).l,a2
    > > >Address Error.asm(274): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table + AddressLoc(4, 24)).l,a2
    > > >Address Error.asm(274): error: addressing mode not allowed here
    > > > lea (Chunk_Table + AddressLoc(4, 24)).l,a2
    > > >Address Error.asm(320): error: symbol undefined
    > > > Chunk_Table
    > > > lea (Chunk_Table).l,a1
    > > >Address Error.asm(320): error: addressing mode not allowed here
    > > > lea (Chunk_Table).l,a1
    > > >Address Error.asm(324): error: symbol undefined
    > > > PlaneMapToVRAM
    > > > jsr (PlaneMapToVRAM).l
    > > >Address Error.asm(324): warning: address is not properly aligned
    > > > jsr (PlaneMapToVRAM).l
    > > >Address Error.asm(324): error: addressing mode not allowed here
    > > > jsr (PlaneMapToVRAM).l
    > > >Address Error.asm(371): error: addressing mode not allowed on 68000
    > > > move.w OpCodeMap(pc,d0.w),d0
    > > >Address Error.asm(371): error: addressing mode not allowed here
    > > > move.w OpCodeMap(pc,d0.w),d0
    > > >Address Error.asm(372): error: addressing mode not allowed on 68000
    > > > jmp OpCodeMap(pc,d0.w)
    > > >Address Error.asm(372): error: addressing mode not allowed here
    > > > jmp OpCodeMap(pc,d0.w)
    > > >Address Error.asm(535): error: addressing mode not allowed on 68000
    > > > move.l Immed_Msgs(pc,d1.w),a1
    > > >Address Error.asm(535): error: addressing mode not allowed here
    > > > move.l Immed_Msgs(pc,d1.w),a1
    > > >Address Error.asm(543): error: addressing mode not allowed on 68000
    > > > move.l Immed_to_CCR_SR_Msgs+8(pc,d4.w),a1 ; +8 because table is reused.
    > > >Address Error.asm(543): error: addressing mode not allowed here
    > > > move.l Immed_to_CCR_SR_Msgs+8(pc,d4.w),a1 ; +8 because table is reused.
    > > >Address Error.asm(594): error: addressing mode not allowed on 68000
    > > > move.b MoveSizeMsgs(pc,d4.w),d4
    > > >Address Error.asm(594): error: addressing mode not allowed here
    > > > move.b MoveSizeMsgs(pc,d4.w),d4
    > > >Address Error.asm(628): error: addressing mode not allowed on 68000
    > > > move.w MiscOpCodeMap(pc,d0.w),d0
    > > >Address Error.asm(628): error: addressing mode not allowed here
    > > > move.w MiscOpCodeMap(pc,d0.w),d0
    > > >Address Error.asm(629): error: addressing mode not allowed on 68000
    > > > jmp MiscOpCodeMap(pc,d0.w)
    > > >Address Error.asm(629): error: addressing mode not allowed here
    > > > jmp MiscOpCodeMap(pc,d0.w)
    > > >Address Error.asm(1811): error: addressing mode not allowed on 68000
    > > > move.l ShiftMessages(pc,d2.w),a1
    > > >Address Error.asm(1811): error: addressing mode not allowed here
    > > > move.l ShiftMessages(pc,d2.w),a1
    > > >Address Error.asm(1922): error: addressing mode not allowed on 68000
    > > > move.w EACodeMap(pc,d0.w),d0
    > > >Address Error.asm(1922): error: addressing mode not allowed here
    > > > move.w EACodeMap(pc,d0.w),d0
    > > >Address Error.asm(1923): error: addressing mode not allowed on 68000
    > > > jmp EACodeMap(pc,d0.w)
    > > >Address Error.asm(1923): error: addressing mode not allowed here
    > > > jmp EACodeMap(pc,d0.w)
    > > >Address Error.asm(2010): error: addressing mode not allowed on 68000
    > > > move.w MiscEACodeMap(pc,d1.w),d1
    > > >Address Error.asm(2010): error: addressing mode not allowed here
    > > > move.w MiscEACodeMap(pc,d1.w),d1
    > > >Address Error.asm(2011): error: addressing mode not allowed on 68000
    > > > jmp MiscEACodeMap(pc,d1.w)
    > > >Address Error.asm(2011): error: addressing mode not allowed here
    > > > jmp MiscEACodeMap(pc,d1.w)
    > > >Address Error.asm(2128): error: addressing mode not allowed on 68000
    > > > move.w jmp_EA_CodeMap(pc,d0.w),d0
    > > >Address Error.asm(2128): error: addressing mode not allowed here
    > > > move.w jmp_EA_CodeMap(pc,d0.w),d0
    > > >Address Error.asm(2129): error: addressing mode not allowed on 68000
    > > > jmp jmp_EA_CodeMap(pc,d0.w)
    > > >Address Error.asm(2129): error: addressing mode not allowed here
    > > > jmp jmp_EA_CodeMap(pc,d0.w)
    > > >Address Error.asm(2174): error: addressing mode not allowed on 68000
    > > > move.w jmp_Misc_EACodeMap(pc,d1.w),d1
    > > >Address Error.asm(2174): error: addressing mode not allowed here
    > > > move.w jmp_Misc_EACodeMap(pc,d1.w),d1
    > > >Address Error.asm(2175): error: addressing mode not allowed on 68000
    > > > jmp jmp_Misc_EACodeMap(pc,d1.w)
    > > >Address Error.asm(2175): error: addressing mode not allowed here
    > > > jmp jmp_Misc_EACodeMap(pc,d1.w)
     
  10. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    Remove the following lines from "Address Error Defs.asm":
    Code (Text):
    1. EniDec := Eni_Decomp
    2. KosDec := Kos_Decomp
    3. PlaneMapToVRAM := Plane_Map_To_VRAM
    and add the following:
    Code (Text):
    1. Chunk_Table := Metablock_Table
    Edit: Also add this:
    Code (Text):
    1. PlaneMapToVRAM := ShowVDPGraphics
     
  11. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Awesome, almost there:

    Code (Text):
    1. > > >Address Error.asm(324): error: symbol undefined
    2. > > > PlaneMapToVRAM
    3. > > >   jsr (PlaneMapToVRAM).l
    4. > > >Address Error.asm(324): warning: address is not properly aligned
    5. > > >   jsr (PlaneMapToVRAM).l
    6. > > >Address Error.asm(324): error: addressing mode not allowed here
    7. > > >   jsr (PlaneMapToVRAM).l
    I uncommented PlaneMapToVRAM := Plane_Map_To_VRAM but that made more errors.


    How I love my disassembly =P
     
  12. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    See the edit in my last post; it took me too long to make it :v:
     
  13. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    HOORAY! No more errors! Cheers, mate, greatly appreciated. I know I am a pain in the arse! At least people with the 2007 disassembly can do it too now =P


    By doing this again (it always triggers it), I got this:

    [​IMG]

    I've added this picture to my thread.


    I might be mistaken, but did you say it generates an error file when this happens? Or am I dreaming? =P

    Also, just to let you know, music no longer continues when displaying this screen, not like I give a shit though =P


    EDIT: I made it freeze in a different location in a different level, and it was the same error message "move.w (a1)+,d1" but the address read was $FFFFFFFF, so it's this line in my ASM that's causing the touble I guess?


    EDIT2: Here's another

    [​IMG]

    It is definately respawn_index. Some objects do NOT respawn when you leave and re-enter the area if you haven't destroyed them. This can happen to badniks, springs, anything. Then when you go to touch where they originally were, BOOM, error. (1st picture error you see).


    In the RARE case that it doesn't freeze when you touch their location where they should be, this triggers something else. As soon as you next get hurt, it will freeze. (2nd error picture you see).


    Thanks, mate, this has really helped. I will get on to looking at moving respawn_index elsewhere.


    To anyone else, I recommend putting this neat feature in your hack.
     
  14. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    Time now to build the ROM generating the map file (as I mentioned earlier) and use it to find out where the thing that causes the error is. In the first screen, you want to find out what is at address $536B9; unless I am mistaken, $17760 is in BuildSprites (near label 'loc_166CC'), meaning $536B9 is in a mappings file that is located at an odd address. If I am right about the first error, then the second error (reading from $FFFFFFFF in the same line) is caused by an object that either does not have his mappings set, or one that calls DisplaySprite/DisplaySprite2/DisplaySprite3 before calling DeleteObject/DeleteObject2 (the latter possibly being called through MarkObjGone/MarkObjGone2/MarkObjGone3. And yes, I got rid of lots of errors like this in my hack :-)

    The third error looks like the start of an object's code; it seems like the routine of the object is being set to an odd value (note d0 is 3). Good luck squashing them all :v:
     
  15. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    I built it without putting the "-g MAP" code at first and triggered to get these results. Then adding -g MAP" whilst building again then triggering it in the same place gave me the same results, so I'm not sure what I am meant to do here.


    As for you mentioning the markobjgone, that will explain why suddenly they decide not to appear every now and then, and when you run into them, it locks up.


    Will give this ago tomorrow as it's 1am now and I can't think anymore =P


    Thanks again, mate.
     
  16. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    When building with -g MAP, a file called s2.map is generated (for S2 hacks). You open it in a text editor and search for the addresses mentioned in the error screen; the map file will give you the line in s2.asm corresponding to the address in question.
     
  17. Chilly Willy

    Chilly Willy

    Tech Member
    751
    11
    18
    Doom 32X
    Why do people have so much trouble with odd address errors? The "fix" is simple - find every place you have byte data (actual bytes or strings or byte arrays), and then ALWAYS follow the last one with an "even" directive. PROBLEM SOLVED. :eng101:

    "But it's always an even number of bytes! I don't NEED to put an 'even' after it!!"

    DO IT ANYWAY!! :argh:
     
  18. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    This is more-or-less what I have been doing myself. But I still get the (increasingly less frequent) address error for other causes -- for example, the case I mentioned where an object calling DisplaySprite first and then calling DeleteObject afterwards due to its logic. Interestingly, I find that this is usually an S1 object.
     
  19. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    I put "build -g MAP", then triggered the error, but no s2.map (or s2built.map) was created.




    I know you're meant to put it after all bytes like dc.b's and etc, but does that include all BINCLUDES and INCLUDES? Like:

    Code (Text):
    1. ; word_1E5A:
    2. word_1E7A: BINCLUDE "art/palettes/EHZ ARZ Water.bin"; Emerald Hill/Aquatic Ruin Rotating Water palette
    3.  even
    4. word_1E9A: BINCLUDE "art/palettes/Hill Top Lava.bin"; Hill Top Lava palette
    5.  even
    6. word_1F1A: BINCLUDE "art/palettes/Wood Conveyor.bin"; Wood Conveyor Belts palette
    7.  even
    8. byte_1F2A: BINCLUDE "art/palettes/MTZ Cycle 1.bin"; Metropolis Cycle #1 palette
    9.  even
    Or

    Code (Text):
    1. ; word_1E5A:
    2. word_1E7A: BINCLUDE "art/palettes/EHZ ARZ Water.bin"; Emerald Hill/Aquatic Ruin Rotating Water palette
    3. word_1E9A: BINCLUDE "art/palettes/Hill Top Lava.bin"; Hill Top Lava palette
    4. word_1F1A: BINCLUDE "art/palettes/Wood Conveyor.bin"; Wood Conveyor Belts palette
    5. byte_1F2A: BINCLUDE "art/palettes/MTZ Cycle 1.bin"; Metropolis Cycle #1 palette
    6.  even
     
  20. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    Then you are putting it in the wrong place. Where you are supposed to put the "-g MAP" is in this line in build.bat:
    Code (Text):
    1. "win32/asw" -xx -c -A s2.asm
    It should look like this:
    Code (Text):
    1. "win32/asw" -xx -c -g MAP -A s2.asm
    (the line is different in the Hg disassembly, by the way)

    Ideally, it must also be placed after all bincludes; also, after every include that has anything other than code (but if you are paranoid, even if it only has code).