Megadrive and ASM68k - having trouble with absolute basics

Discussion in 'Sega Discussion' started by Headcrab, Dec 30, 2011.

  1. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    Hi,

    I'm trying to get a very small sample up and running - not even Hello World, not even initialising the VDP or Z80, just move one register to another - to make sure my toolchain is up to scratch and that my debugger of choice (MESS) is working correctly, but after a few days of trying I haven't had much luck.

    Here's my code, it's a mash of different samples and tutorials from all over the net, trimmed down to something which I can start off with:

    RomStart:

    ; ******************************************************************

    ; Sega Megadrive ROM header
    ; ******************************************************************
    dc.l 0x00FFE000 ; Initial stack pointer value
    dc.l EntryPoint ; Start of program
    dc.l Exception ; Bus error
    dc.l Exception ; Address error
    dc.l Exception ; Illegal instruction
    dc.l Exception ; Division by zero
    dc.l Exception ; CHK exception
    dc.l Exception ; TRAPV exception
    dc.l Exception ; Privilege violation
    dc.l Exception ; TRACE exception
    dc.l Exception ; Line-A emulator
    dc.l Exception ; Line-F emulator
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Spurious exception
    dc.l Exception ; IRQ level 1
    dc.l Exception ; IRQ level 2
    dc.l Exception ; IRQ level 3
    dc.l HBlankInterrupt ; IRQ level 4 (horizontal retrace interrupt)
    dc.l Exception ; IRQ level 5
    dc.l VBlankInterrupt ; IRQ level 6 (vertical retrace interrupt)
    dc.l Exception ; IRQ level 7
    dc.l Exception ; TRAP #00 exception
    dc.l Exception ; TRAP #01 exception
    dc.l Exception ; TRAP #02 exception
    dc.l Exception ; TRAP #03 exception
    dc.l Exception ; TRAP #04 exception
    dc.l Exception ; TRAP #05 exception
    dc.l Exception ; TRAP #06 exception
    dc.l Exception ; TRAP #07 exception
    dc.l Exception ; TRAP #08 exception
    dc.l Exception ; TRAP #09 exception
    dc.l Exception ; TRAP #10 exception
    dc.l Exception ; TRAP #11 exception
    dc.l Exception ; TRAP #12 exception
    dc.l Exception ; TRAP #13 exception
    dc.l Exception ; TRAP #14 exception
    dc.l Exception ; TRAP #15 exception
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)
    dc.l Exception ; Unused (reserved)

    dc.b "SEGA GENESIS "

    dc.b "(C)SEGA 1992.SEP"
    dc.b "YOUR GAME HERE "
    dc.b "YOUR GAME HERE "
    dc.b "GM XXXXXXXX-XX"
    dc.w 0
    dc.b "J "
    dc.l RomStart
    dc.l RomEnd-1
    dc.l $FF0000
    dc.l $FFFFFF
    dc.b " "
    dc.b " "
    dc.b " "
    dc.b " "
    dc.b " "
    dc.b "JUE "

    ; ******************************************************************

    ; Entry Point
    ; ******************************************************************
    EntryPoint:
    move.l d0, d1 ; Do something
    bra EntryPoint ; Do it again

    ; ******************************************************************

    ; Exception handler
    ; ******************************************************************
    Exception:
    bra Exception ; Just Loop

    ; ******************************************************************

    ; Sync interrupts
    ; ******************************************************************
    HBlankInterrupt:
    rts ; Do nothing

    VBlankInterrupt:

    rts ; Do nothing

    RomEnd:

    END


    I'm assembling and preparing the BIN using:

    C:\>asm68k.exe test2.asm,test2.bin

    SN 68k version 2.53


    Assembly completed.

    0 error(s) from 88 lines in 0.0 seconds

    C:\>rompad.exe test2.bin 255 0

    Lightning's ROM Padder

    C:\>fixheadr.exe test2.bin


    Reported Size: 20202020 Reported Checksum: 2047

    Size applied: 3FF Checksum Applied: 1C90


    and all seems well. ASM68K is my assembler of choice since SNASM68K doesn't run on Windows 7 64 bit. The other two tools are from the Sonic disassembly dump, which included everything needed to assemble, pad and fix the header.

    When I open the BIN using MESS and begin debugging, I see some invalid opcodes in the disassembly, and the program will not run:

    [​IMG]

    The disassembly doesn't seem to match any of the code I've written, although that may be because I'm just starting out and don't really know what I'm looking for yet.

    I'm not sure if it's my code, the build process or the debugger which is at fault, but loading up a Sonic ROM in MESS runs and shows correct debug info.

    Any help appreciated!
     
  2. l_oliveira

    l_oliveira Officer at Arms

    Joined:
    Nov 24, 2007
    Messages:
    3,895
    Likes Received:
    252
    Put some NOPs and see if they show up as 4E71 on MAME debugger. If they appear as 714E you're having endian-ness issues. I think MESS will want the ROM byte swapped as that's how MAME take it's ROMs.

    Byte Swapped as if it were read from an SEGA MASK ROM I mean. :nod:

    Edit, also make sure you set the ENTRY POINT after 0x0001FF. As EVERYTHING before that are vectors for the 68000 CPU, even if they're unused. There's so much room for code, a few bytes won't hurt and will save you from future headaches.
     
    Last edited: Dec 30, 2011
  3. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    Nail on the head! The NOPs show up as 714E (and way WAY further down the disassembly than I expected).

    How would I solve this? Is it as simple as an assembler option to swap the endianness?

    Also, how would I tell if my entry point is after 0x0001FF? Do I simply sum up the size of the header (since it's the first line of code after that)?
     
  4. l_oliveira

    l_oliveira Officer at Arms

    Joined:
    Nov 24, 2007
    Messages:
    3,895
    Likes Received:
    252
    Some hex editors (I use winhex for that) can byteswap files.

    Your case is 16 bit byteswap. :thumbsup:

    For setting the base address for an program, the assembler program has an pseudo instruction ".org 0x<Your desired address here in hexadecimal>".

    I suggest you read a bit about macros and pseudo instructions on assembly programs as these work with most assembler programs and they usually are the same regardless what the target CPU is.
     
    Last edited: Dec 30, 2011
  5. Calpis

    Calpis Champion of the Forum

    Joined:
    Mar 13, 2004
    Messages:
    5,906
    Likes Received:
    21
    All 16-bit ROMs can be little-endian or big-endian depending on which the the programmer software chooses, not the physical ROM layout. Little-endian is the true/logical endian and what most device programmers default to so this is just more MAME crew craziness.
     
  6. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    Ok, I've given it a shot word-swapping the whole file (with HHD Software's Hex Editor Neo), and the results still aren't as expected - it runs the following instructions in a loop:

    [​IMG]

    I've tried loading it up using Gens (with the KMod plugin) and RetroDrive but I get the same results both with and without the endian swapping, so I'm not entirely certain that it's MESS to blame. Gens correctly displays the 'YOUR GAME HERE' title, so at least it's read the ROM correctly.

    Adding .org to offset the start of the code didn't seem to change anything either, but I'll leave it in since your recommendation makes perfect sense.

    I don't suppose anybody has a working sample which assembles using ASM68K for me to test? It doesn't need to do anything fancy, just increment a register in a loop or something. Once I'm over that hurdle the rest should roll easier.
     
  7. l_oliveira

    l_oliveira Officer at Arms

    Joined:
    Nov 24, 2007
    Messages:
    3,895
    Likes Received:
    252
    Can you upload your binary file somewhere for me to have a little look ?
     
  8. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
  9. Kjell

    Kjell Member

    Joined:
    Dec 8, 2010
    Messages:
    21
    Likes Received:
    0
    The first 15 bytes of your ROM contain junk.

    [​IMG]

    Once you delete those, your ROM seems to work fine.

    [​IMG]

    [​IMG]

    You probably want to take a look at the manual of your assembler.
     
    Last edited: Dec 31, 2011
  10. Jorge Nuno

    Jorge Nuno Active Member

    Joined:
    Aug 10, 2011
    Messages:
    28
    Likes Received:
    0
    A reset vector of 0x000001FF is totally not fine, it must be an even address
     
  11. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    Perfect! That works! Thank you so much. May I ask which debugger you're using? That screenshot looks pretty fully-fledged.

    Doesn't that mean the line of code after the .org starts at byte 512? That sounds reasonable to me unless I'm missing something.
     
  12. Kjell

    Kjell Member

    Joined:
    Dec 8, 2010
    Messages:
    21
    Likes Received:
    0
    Regen

    If you want your code to start at byte 512, you need to use "org 0x200" instead of "org 0x1FF".
     
  13. l_oliveira

    l_oliveira Officer at Arms

    Joined:
    Nov 24, 2007
    Messages:
    3,895
    Likes Received:
    252
    Headcrab, when I said 0x0001FF I meant that was the last byte of the 68000 vector area. So yes, two things you need to observe:

    1- Because 68000 uses 16bit instruction encoding, it's alignment is 16 bit based, which means it will only fetch instructions from even addresses.

    If you try to jump on an odd address it will trigger an "Address Error" exception and everything will freeze (there's no vector setup for error handling, right ? lol)...

    2- 68000 does not have an A0 line so it can only see the memory as one 16bit device. When you need to use byte instructions (it has support for that and it's treated as an special case) the chip has special pins to signal that kind of memory access... :thumbsup:

    Good to see that you're progressing. It's the first step, learn how to use the tools. :nod:


    Edit:

    Forgot to say this:

    Do mind the subtle details. Now you saw why I said "after 0x0001FF"...
     
    Last edited: Dec 31, 2011
  14. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    Thanks, that makes sense. Coming from C to Assembly is quite awkward, where I only have to deal with alignment and the likes when dealing with very low level stuff.

    I intend to properly handle each error type as soon as I figure out what information I should be fetching to deal with the situation (or how to display the errors on screen, if the CPU isn't left in a confused state after the error). On Xbox, Wii and PS3 we have the luxury of displaying errors on screen inside an exception handler, is this a common practice on platforms of this era or should I limit it to a STOP op and rely on the debugger?

    Indeed, this was just my head going foggy, of course I need 0x200 to begin on byte 512.


    Thanks for the help all! I'll see what those extra bytes are and figure out how to stop my assembler putting them in. MESS seems quite happy with a file of that endianness, by the way.

    Now to initialise the thing and get a pixel on screen!
     
  15. l_oliveira

    l_oliveira Officer at Arms

    Joined:
    Nov 24, 2007
    Messages:
    3,895
    Likes Received:
    252
    About error handling, it could be something super simple as just making it reset/restart or something like this :
    [​IMG]
    (Pocket Fighter, Capcom 1997 CPS2/68000)

    or this
    [​IMG]
    (Street Fighter Zero 3, 1998 Capcom CPS2/68000)
     
  16. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    Well, after many weeks of typing away, reading articles and tearing my hair out, I finally have Hello World up and running! Thanks to everyone here who helped!

    http://www.mediafire.com/?o27lnohcco53i2o

    Here it is for critique, or in the hope that somebody else starting out finds it useful. It's by no means the fastest code in the world, I've sacrificed a lot of optimisations for code readability, and I've dissected some of the confusing bits from other samples and broken them down. Rather than load a table of registers to the 68k from the beginning, I load destination addresses as and when I need them, to group relative code together.

    I have some questions:

    1. Originally, to help me better understand how addressing the VDP works, I scrapped use of the AutoIncrement register and manually incremented addresses myself after each copy. For copying the palette, this worked a treat - I copy two bytes, I increment the address by two bytes - but for copying the tiles it all went wrong. However many bytes I incremented my address by after copying a longword, my tiles were garbled, and I had to rely on setting AutoIncrement to 2 to solve this, but I can't figure it out. What exactly does AutoIncrement increment, and by how much? How would I do the same operation manually?

    2. VDP addressing still confuses me. I've read and understand how to break down an address using the 'RRAA AAAA AAAA AAAA ---- ---- RRRR --AA' pattern, and I found a tool here to help me with the job, but the results didn't seem to work. To copy a tile to the VDP, I've been writing 0x40000000 to the VDP command port, as decribed in Marc's Realm, but if I use the calculated address using that tool, I end up with 0x40000011 for a VSRAM write, which makes sense looking at the pattern but it doesn't work. Why?

    3. How could I animate a tile? I'd like to computationally edit a tile (perhaps increment some of the colour IDs), would I edit the data live (i.e., move the changed longword lines to the correct address in VRAM) or would I keep a tile in main RAM to modify, and at regular intervals copy it to an unused area on the VDP and set the new tile ID (a double-buffered approach)?

    4. I still can't figure out what those first 15 bytes of my ROM are, I've been manually deleting them in a HEX editor. Does anyone else here use ASM68k? Any success stories? I can't find any relevant documentation. Even the Sonic2 disassemblies are set up to use ASM68k, yet I haven't found any mention of this problem anywhere else.

    Thanks in advance!
     
  17. Jorge Nuno

    Jorge Nuno Active Member

    Joined:
    Aug 10, 2011
    Messages:
    28
    Likes Received:
    0
    Replied in the quote :)
     
  18. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    Ah that explains a few things that have been gong wrong, then. Makes perfect sense! Now that I understand how writing to the ports work, I'll just be using autoincrement anyway. Doing it manually was purely an educational exercise.

    My VDP registers are set up as 0xC000 for Plane A, 0xE000 for plane B, and 0xD400 for the sprite attr. table. So to write this data I should use addresses 0x40000003, 0x60000003 and 0x54000003 respectively, correct?

    Which addresses should I use to write palette data and pattern data? I've been using 0xC0000000 and 0x40000000, but only through example - I can't find a list of the VDP's various addresses (which aren't set by the user via registers).

    I'll experiment with these after I have a working sprite. I quite like the animated background tiles in the Sonic 2 multiplayer results screen, and wanted to achieve something similar as a starting point.

    I'll have a look.

    Thanks for the answers, much appreciated!
     
  19. Kjell

    Kjell Member

    Joined:
    Dec 8, 2010
    Messages:
    21
    Likes Received:
    0
    Hmm, pretty sure I send you a PM regarding this a month ago .. anyway, did you use the "/p" option of ASM68K?
     
  20. Headcrab

    Headcrab (BigEvilCorporation)

    Joined:
    Dec 21, 2011
    Messages:
    246
    Likes Received:
    67
    I had no idea I had a PM! Just checked, and yes thank you, that worked.

    Is there a way to turn on email notifications for PMs?
     

Share This Page