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): include "Address Error.asm" 2) Find the label 'Vectors:' at the start of the disassembly: S2 disassembly: Find this: Code (Text): ;Vectors: dc.l System_Stack, EntryPoint, ErrorTrap, ErrorTrap; 4 and change it to this: Code (Text): ;Vectors: dc.l System_Stack, EntryPoint, BusError , AddressError; 4 S&K disassembly: Find this: Code (Text): Vectors: dc.l Vectors, EntryPoint, ErrorTrap, ErrorTrap ; 0 and change it to look like this: Code (Text): 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): ? @ [ ] \ ( ) + , - . / : ; # $ % & ! * 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): dma68kToVDP macro source,dest,length,type lea (VDP_control_port).l,a5 move.l #(($9400|((((length)>>1)&$FF00)>>8))<<16)|($9300|(((length)>>1)&$FF)),(a5) move.l #(($9600|((((source)>>1)&$FF00)>>8))<<16)|($9500|(((source)>>1)&$FF)),(a5) move.w #$9700|(((((source)>>1)&$FF0000)>>16)&$7F),(a5) move.w #((dest)&$3FFF)|((type&1)<<15)|$4000,(a5) move.w #$80|(((dest)&$C000)>>14)|((type&2)<<3),(DMA_data_thunk).w move.w (DMA_data_thunk).w,(a5) endm ; values for the type argument enum VRAM=0,CRAM=1,VSRAM=2 ; tells the VDP to fill a region of VRAM with a certain byte dmaFillVRAM macro byte,addr,length lea (VDP_control_port).l,a5 move.w #$8F01,(a5) ; VRAM pointer increment: $0001 move.l #(($9400|((((length)-1)&$FF00)>>8))<<16)|($9300|(((length)-1)&$FF)),(a5) ; DMA length ... move.w #$9780,(a5) ; VRAM fill move.l #$40000080|(((addr)&$3FFF)<<16)|(((addr)&$C000)>>14),(a5) ; Start at ... move.w #(byte)<<8,(VDP_data_port).l ; Fill with byte - move.w (a5),d1 btst #1,d1 bne.s - ; busy loop until the VDP is finished filling... move.w #$8F02,(a5) ; VRAM pointer increment: $0002 endm and replace them with this: Code (Text): vdpComm function addr,type,rwd,(((type&rwd)&3)<<30)|((addr&$3FFF)<<16)|(((type&rwd)&$FC)<<2)|((addr&$C000)>>14) ; values for the type argument VRAM = %100001 CRAM = %101011 VSRAM = %100101 ; values for the rwd argument READ = %001100 WRITE = %000111 DMA = %100111 dma68kToVDP macro source,dest,length,type lea (VDP_control_port).l,a5 move.l #(($9400|((((length)>>1)&$FF00)>>8))<<16)|($9300|(((length)>>1)&$FF)),(a5) move.l #(($9600|((((source)>>1)&$FF00)>>8))<<16)|($9500|(((source)>>1)&$FF)),(a5) move.w #$9700|(((((source)>>1)&$FF0000)>>16)&$7F),(a5) move.w #((vdpComm(dest,type,DMA)>>16)&$FFFF),(a5) move.w #(vdpComm(dest,type,DMA)&$FFFF),(DMA_data_thunk).w move.w (DMA_data_thunk).w,(a5) endm ; tells the VDP to fill a region of VRAM with a certain byte dmaFillVRAM macro byte,addr,length lea (VDP_control_port).l,a5 move.w #$8F01,(a5) ; VRAM pointer increment: $0001 move.l #(($9400|((((length)-1)&$FF00)>>8))<<16)|($9300|(((length)-1)&$FF)),(a5) ; DMA length ... move.w #$9780,(a5) ; VRAM fill move.l #$40000080|(((addr)&$3FFF)<<16)|(((addr)&$C000)>>14),(a5) ; Start at ... move.w #(byte)<<8,(VDP_data_port).l ; Fill with byte loop: loop: move.w (a5),d1 btst #1,d1 bne.s loop ; busy loop until the VDP is finished filling... move.w #$8F02,(a5) ; VRAM pointer increment: $0002 endm b) Open "Address Error Defs.asm" and replace the following lines: Code (Text): EniDec := Eni_Decomp KosDec := Kos_Decomp PlaneMapToVRAM := Plane_Map_To_VRAM with this: Code (Text): Chunk_Table := Metablock_Table 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): movea.w #$0001,a0 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: 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. Spoiler 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: 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:
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.
Cheers, just one problem: Code (Text): > > >Address Error.asm(99): error: unknown function > > > VDPCOMM > > > move.l #vdpComm($0000,VSRAM,WRITE),(a6) > > >Address Error.asm(321): error: unknown function > > > VDPCOMM > > > 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.
Add these lines to 'Address Error Defs.asm' just under the line with 'make_art_tile': Code (Text): vdpComm function addr,type,rwd,(((type&rwd)&3)<<30)|((addr&$3FFF)<<16)|(((type&rwd)&$FC)<<2)|((addr&$C000)>>14) ; values for the type argument VRAM = %100001 CRAM = %101011 VSRAM = %100101 ; values for the rwd argument READ = %001100 WRITE = %000111 DMA = %100111 Edit: you will also need to find in s2.asm the definitions of dma68kToVDP and dmaFillVRAM and replace them both by this: Code (Text): ; tells the VDP to copy a region of 68k memory to VRAM or CRAM or VSRAM dma68kToVDP macro source,dest,length,type lea (VDP_control_port).l,a5 move.l #(($9400|((((length)>>1)&$FF00)>>8))<<16)|($9300|(((length)>>1)&$FF)),(a5) move.l #(($9600|((((source)>>1)&$FF00)>>8))<<16)|($9500|(((source)>>1)&$FF)),(a5) move.w #$9700|(((((source)>>1)&$FF0000)>>16)&$7F),(a5) move.w #((vdpComm(dest,type,DMA)>>16)&$FFFF),(a5) move.w #(vdpComm(dest,type,DMA)&$FFFF),(DMA_data_thunk).w move.w (DMA_data_thunk).w,(a5) endm ; tells the VDP to fill a region of VRAM with a certain byte dmaFillVRAM macro byte,addr,length lea (VDP_control_port).l,a5 move.w #$8F01,(a5) ; VRAM pointer increment: $0001 move.l #(($9400|((((length)-1)&$FF00)>>8))<<16)|($9300|(((length)-1)&$FF)),(a5) ; DMA length ... move.w #$9780,(a5) ; VRAM fill move.l #$40000080|(((addr)&$3FFF)<<16)|(((addr)&$C000)>>14),(a5) ; Start at ... move.w #(byte)<<8,(VDP_data_port).l ; Fill with byte loop: move.w (a5),d1 btst #1,d1 bne.s loop ; busy loop until the VDP is finished filling... move.w #$8F02,(a5) ; VRAM pointer increment: $0002 endm
I now have 72 errors, something to do with VDPCOMM. Here are some typical errors: Code (Text): > > >s2.asm(985) DMA68KTOVDP(5): error: unknown function > > > VDPCOMM > > > move.w #((vdpComm($0000,CRAM,DMA)>>16)&$FFFF),(a5) > > >s2.asm(985) DMA68KTOVDP(6): error: unknown function > > > VDPCOMM > > > move.w #(vdpComm($0000,CRAM,DMA)&$FFFF),(DMA_data_thunk).w > > >s2.asm(991) DMA68KTOVDP(5): error: unknown function > > > VDPCOMM > > > move.w #((vdpComm($0000,CRAM,DMA)>>16)&$FFFF),(a5) > > >s2.asm(991) DMA68KTOVDP(6): error: unknown function > > > VDPCOMM > > > move.w #(vdpComm($0000,CRAM,DMA)&$FFFF),(DMA_data_thunk).w > > >s2.asm(1019) DMA68KTOVDP(5): error: unknown function > > > VDPCOMM > > > move.w #((vdpComm($F800,VRAM,DMA)>>16)&$FFFF),(a5) I will say, I commented the last line out here: Code (Text): ; values for the type argument ; enum VRAM=0,CRAM=1,VSRAM=2 Otherwise, I got 3 errors saying the double defined.
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): ; simplifying macros ; tells the VDP to copy a region of 68k memory to VRAM or CRAM or VSRAM dma68kToVDP macro source,dest,length,type lea (VDP_control_port).l,a5 move.l #(($9400|((((length)>>1)&$FF00)>>8))<<16)|($9300|(((length)>>1)&$FF)),(a5) move.l #(($9600|((((source)>>1)&$FF00)>>8))<<16)|($9500|(((source)>>1)&$FF)),(a5) move.w #$9700|(((((source)>>1)&$FF0000)>>16)&$7F),(a5) move.w #((vdpComm(dest,type,DMA)>>16)&$FFFF),(a5) move.w #(vdpComm(dest,type,DMA)&$FFFF),(DMA_data_thunk).w move.w (DMA_data_thunk).w,(a5) endm ; values for the type argument ; enum VRAM=0,CRAM=1,VSRAM=2 ; tells the VDP to fill a region of VRAM with a certain byte dmaFillVRAM macro byte,addr,length lea (VDP_control_port).l,a5 move.w #$8F01,(a5) ; VRAM pointer increment: $0001 move.l #(($9400|((((length)-1)&$FF00)>>8))<<16)|($9300|(((length)-1)&$FF)),(a5) ; DMA length ... move.w #$9780,(a5) ; VRAM fill move.l #$40000080|(((addr)&$3FFF)<<16)|(((addr)&$C000)>>14),(a5) ; Start at ... move.w #(byte)<<8,(VDP_data_port).l ; Fill with byte loop: move.w (a5),d1 btst #1,d1 bne.s loop ; busy loop until the VDP is finished filling... move.w #$8F02,(a5) ; VRAM pointer increment: $0002 endm
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) Spoiler > > >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)
Remove the following lines from "Address Error Defs.asm": Code (Text): EniDec := Eni_Decomp KosDec := Kos_Decomp PlaneMapToVRAM := Plane_Map_To_VRAM and add the following: Code (Text): Chunk_Table := Metablock_Table Edit: Also add this: Code (Text): PlaneMapToVRAM := ShowVDPGraphics
Awesome, almost there: Code (Text): > > >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 I uncommented PlaneMapToVRAM := Plane_Map_To_VRAM but that made more errors. How I love my disassembly =P
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: 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 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.
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:
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.
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.
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. "But it's always an even number of bytes! I don't NEED to put an 'even' after it!!" DO IT ANYWAY!!
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.
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): ; word_1E5A: word_1E7A: BINCLUDE "art/palettes/EHZ ARZ Water.bin"; Emerald Hill/Aquatic Ruin Rotating Water palette even word_1E9A: BINCLUDE "art/palettes/Hill Top Lava.bin"; Hill Top Lava palette even word_1F1A: BINCLUDE "art/palettes/Wood Conveyor.bin"; Wood Conveyor Belts palette even byte_1F2A: BINCLUDE "art/palettes/MTZ Cycle 1.bin"; Metropolis Cycle #1 palette even Or Code (Text): ; word_1E5A: word_1E7A: BINCLUDE "art/palettes/EHZ ARZ Water.bin"; Emerald Hill/Aquatic Ruin Rotating Water palette word_1E9A: BINCLUDE "art/palettes/Hill Top Lava.bin"; Hill Top Lava palette word_1F1A: BINCLUDE "art/palettes/Wood Conveyor.bin"; Wood Conveyor Belts palette byte_1F2A: BINCLUDE "art/palettes/MTZ Cycle 1.bin"; Metropolis Cycle #1 palette even
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): "win32/asw" -xx -c -A s2.asm It should look like this: Code (Text): "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).