Mega Drive to Mega CD?

Ask anything your want about Mega/SegaCD programming.

Moderator: Mask of Destiny

HCKTROX
Interested
Posts: 27
Joined: Wed Mar 24, 2010 1:15 am
Location: Chile

Mega Drive to Mega CD?

Post by HCKTROX » Sun Feb 06, 2011 4:21 pm

Hi guys.

I'm created a Mega drive game (very buggy, at the moment =P), but I need convert to Mega CD. My problem is, I have no a minimal idea how to do this. I want convert it to Mega CD, and make use some MP3 songs.

Anyone can/want help me?





(This post MAY contain bad grammar)
skype: hcktrox

SoullessSentinel
Interested
Posts: 24
Joined: Wed Feb 03, 2010 12:53 am
Location: Grimsby, England

Post by SoullessSentinel » Sun Feb 20, 2011 2:21 am

This is no easy task, there is very little addressable memory available.
It is possible though, you would need to split your game into 256kb modules that can be loaded into RAM from CD when needed, as well as adjust the memory map not to clash with the jump table for the bios. The details of the map can be found in the official documentation that should be floating around on the web.

Here, is an incomplete template for a Sega/MegaCD game. It currently stands as a bootloader, with programs for the main and sub cpu's.
It supports parsing the ISO filesystem, for loading files from CD, and executing them, so at this stage is very simple.

I included the CD Port of Columns, just as a test program for the bootloader. I did comment extensively though, so, I suggest giving it a read through.

A build script is included, which also calls a custom program to trim the output from MKISOFS and merge the generated filesystem with the boot code, making the compilation seamless.

Default region is JAP, but, all security sectors are included. You would need to edit IP.ASM to include the correct file for your target region

http://www.megaupload.com/?d=61UDIN52
I apologise for Megaupload, I do not have my own host at this point in time.

Warning: I am NOT an experienced coder, so things could probably be more optimised and be done in a better way, keep that in mind.

KanedaFr
Administrateur
Posts: 1139
Joined: Tue Aug 29, 2006 10:56 am
Contact:

Post by KanedaFr » Sun Feb 20, 2011 7:53 am

WOW!
congratulations, you did exactly what I was about to start ;)
very well done, and thanks for the comments
a must !
I mirrored it to http://gendev.spritesmind.net/files/mcd ... jectCD.zip

Artemio
Interested
Posts: 22
Joined: Fri Jan 07, 2011 7:04 pm
Location: Mexico
Contact:

Post by Artemio » Wed Mar 09, 2011 7:26 pm

That is awesome lukeusher123, of course the only problem is having your binary in such a format... Do you know what I would need to do to compile my binary using Stef's mini devkit to be mapped in such a way?

KanedaFr
Administrateur
Posts: 1139
Joined: Tue Aug 29, 2006 10:56 am
Contact:

Post by KanedaFr » Thu Mar 10, 2011 9:22 am

you need to create your md.ld I think....
I didn't find the time yet to test & document this

SoullessSentinel
Interested
Posts: 24
Joined: Wed Feb 03, 2010 12:53 am
Location: Grimsby, England

Post by SoullessSentinel » Thu Mar 10, 2011 9:43 am

In order to use Stef's devkit with this, you would first have to recompile the library and remove all unneccessary functions, since on the Sega CD you are limited to 256KB maximum program code loaded in RAM at once, also, the memory map is completely different.

Program code is mapped from $200000 to $23FFFF on the Megadrive side, and also the Vector table is relocated from $0 to $FFFD00-$FFFDFF in RAM, so edits are still possible, but this also means you lose this area of RAM.
The Sega CD official documents state not to use RAM about $FFFD00 for your own data storage for this reason, but, to my knowledge, using ram above the vector table shouldn't be an issue.

So, the following steps are needed to use Stef's devkit with the Sega CD:
1. Recompile the inclue library to only have essential functions, to minimise binary size
2. Prevent the Sega startup program from being linked in, it is no longer needed as the Sega CD BIOS handles this.
3. Split game program into 256KB chunks, these are your prg files, that can be loaded into RAM from CD when needed
4. Create your own md.ld file, using Stef's one as a template, altering the memory map to have your program code area defined as $200000, $23FFFF and your RAM to be at $FF0000 - $FFFD00
5. Create a new makefile to use this new information

Note: Because the game has to be in 256KB chunks but share the same ram-space, you can't rely on C's compiler to ensure the memory map matches between binarys, as they are seen as completely seperate programs. This means that you may have to just create pointers and map them directly to RAM addresses and create the memory map yourself, to ensure they are always at the same location.

That should work, however I have not yet tested this, I was thinking about doing this in the future, but at this point I have no need for it. Somebody with more experience in this area may be able to give more details, I know Fonzie has a Sega CD ld file on his site, as well as some downloadable Sega CD source code, but it's for the XGCC compiler, and not Stef's devkit.

Artemio
Interested
Posts: 22
Joined: Fri Jan 07, 2011 7:04 pm
Location: Mexico
Contact:

Post by Artemio » Thu Mar 10, 2011 8:25 pm

Thanks for all the help, I am trying it and this is what I've gotten so far. I copied the md.ld and makefile and modified them to reflect the new memory map, and remove the sega.s file.


Here's what I changed to the best of my knowledge:

Code: Select all

MEMORY
{
	rom : ORIGIN = 0x00200000, LENGTH = 0x0003ffff
	ram : ORIGIN = 0x00ff0000, LENGTH = 0x0000fcff
  }

/*
 * allocate the stack to be at the top of memory, since the stack
 * grows down
 */

PROVIDE (__stack = 0x00fffcff);
...

Code: Select all

SECTIONS
{
  .text 0x00200000:
  {
    *(.text)
...

Code: Select all

 .bss 0x00ff0000:
  {
    __bss_start = . ;
I did also removed some stuff I don't need but my ROM is way less than 128 KB for the time being, so it is not an issue yet.

I tested it, and it simply rebooted. I then went to dissassemble my code.. and figured that most probably the entry point is my issue here. I do need teh sega.s file to go to _start_entry and then jump to my main() function. So I went ahead and created a copy of sega.s and modified it...

I am getting some errors, I guess I need to understand it a bit better. So far I changed

.org 0x00000000 to .org 0x00200000

and modified the stack to 0x00fffcff, removed to the best of my knowledge the cartridge init routines... but I get a

0x41cc1e of out/romscd.out section .text is not within region rom..

I guessed that was because of the .org I changed, moved it back to 0.. but it is still rebooting. Will continue exploring this and post here if I get any positive results.

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Thu Mar 10, 2011 9:08 pm

Stack won't work at an odd address.

Try this instead:

Code: Select all

PROVIDE (__stack = 0x00fffd00);

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Thu Mar 10, 2011 11:03 pm

You want something like this:

Code: Select all

OUTPUT_ARCH(m68k)
SEARCH_DIR(.)
__DYNAMIC  =  0;

/*
 * The memory map look like this:
 * +--------------------+ <- 0x00200000
 * | .text              |
 * |        _etext      |
 * |        ctor list   | the ctor and dtor lists are for
 * |        dtor list   | C++ support
 * +--------------------+ <- 0x00240000
 * .                    .
 * .                    .
 * .                    .
 * +--------------------+ <- 0x00FF0000
 * | .data              | initialized data goes here
 * |        _edata      |
 * +--------------------+
 * | .bss               |
 * |        __bss_start | start of bss, cleared by crt0
 * |        _end        | start of heap, used by sbrk()
 * +--------------------+
 * .                    .
 * .                    .
 * .                    .
 * |        __stack     | top of stack
 * +--------------------+ <- 0x00FFFD00
 */

MEMORY
{
    wram (wx) : ORIGIN = 0x00200000, LENGTH = 0x00040000
    ram (wx) : ORIGIN = 0x00FF0000, LENGTH = 0x0000FD00
}

/*
 * Allocate the stack to be at the top of memory, since the stack
 * grows down
 */

PROVIDE (__stack = 0x00FFFD00);

SECTIONS
{
  .text 0x00200000 :
  AT ( 0x00000000 )
  {
    *(.text .text.*)
    . = ALIGN(0x4);
     __CTOR_LIST__ = .;
    ___CTOR_LIST__ = .;
    LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
    *(.ctors)
    LONG(0)
    __CTOR_END__ = .;
    __DTOR_LIST__ = .;
    ___DTOR_LIST__ = .;
    LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
    *(.dtors)
     LONG(0)
    __DTOR_END__ = .;
    *(.rodata .rodata.*)
    *(.gcc_except_table)

    . = ALIGN(0x2);
    __INIT_SECTION__ = . ;
    LONG (0x4E560000)   /* linkw %fp,#0 */
    *(.init)
    SHORT (0x4E5E)  /* unlk %fp */
    SHORT (0x4E75)  /* rts */

    __FINI_SECTION__ = . ;
    LONG (0x4E560000)   /* linkw %fp,#0 */
    *(.fini)
    SHORT (0x4E5E)  /* unlk %fp */
    SHORT (0x4E75)  /* rts */

    _etext = .;
    *(.lit)
  } > wram
  _stext = SIZEOF (.text);

  .data 0x00FF0000 :
  AT ( LOADADDR (.text) + SIZEOF (.text) )
  {
    *(.got.plt) *(.got)
    *(.shdata)
    *(.data .data.*)
    _edata = .;
  } > ram
  _sdata = SIZEOF (.data);

  .bss 0x00FF0000 + SIZEOF (.data) :
  {
    . = ALIGN(0x4);
    __bss_start = . ;
    *(.shbss)
    *(.bss .bss.*)
    *(COMMON)
    _end =  ALIGN (0x8);
    __end = _end;
    end = _end;
  } > ram

  .stab 0 (NOLOAD) :
  {
    *(.stab)
  }

  .stabstr 0 (NOLOAD) :
  {
    *(.stabstr)
  }

  .eh_frame 0 (NOLOAD) :
  {
    *(.eh_frame)
  }
}
Note that the word ram IS ram, so you could put the data and bss in word ram as well.

The

Code: Select all

  .text 0x00200000 :
  AT ( 0x00000000 )
Links the code to run at 0x200000, but it's in the file at offset 0. If you don't set the load address to 0, you get 2MB of filler at the start of the file. Same for the

Code: Select all

  .data 0x00FF0000 :
  AT ( LOADADDR (.text) + SIZEOF (.text) )
That puts initialized data right after the code, but linked to be in ram. You have to copy the data to ram as part of the crt0.s file, like this

Code: Select all

initialize:
        move    #0x2700,sr              /* interrupts disabled */

        lea     __stack,a0
        movea.l a0,sp                   /* set stack pointer to top of Work RAM */

| Clear Work RAM (0xFF0000 to 0xFFFCFF)
        lea     0xFF0000,a0
        moveq   #0,d0
        move.w  #0x3F3F,d1
1:
        move.l  d0,(a0)+
        dbra    d1,1b

| Copy initialized variables from ROM to Work RAM
        lea     _stext,a0
        adda.l  #0x00200000,a0
        lea     0xFF0000,a1
        move.l  #_sdata,d0
        lsr.l   #1,d0
        subq.w  #1,d0
2:
        move.w  (a0)+,(a1)+
        dbra    d0,2b

        jsr     main                    /* call main() */
        jmp     initialize.l
Note that if you put the data into word ram instead of work ram, you don't have to copy the data - it would already be where it needed to be. You would still have to clear the bss region.

Artemio
Interested
Posts: 22
Joined: Fri Jan 07, 2011 7:04 pm
Location: Mexico
Contact:

Post by Artemio » Fri Mar 11, 2011 5:32 am

Still experimenting, thanks for all the information Chilly Willy, I still haven't managed to make it work with all your information. The sega.s file on the Mini SDK has several more things that might be needed I guess. I did try with your asm code, but it somehow managed to go to 0x0000000 and started executing form there.

SoullessSentinel
Interested
Posts: 24
Joined: Wed Feb 03, 2010 12:53 am
Location: Grimsby, England

Post by SoullessSentinel » Fri Mar 11, 2011 6:24 am

I forgot you'd need part of Sega.s to boot the C code, Was still thinking partially in asm mode sorry.

It might help us here if you post what your modified sega.s looks like so one of us could see what exactly it is doing?

Artemio
Interested
Posts: 22
Joined: Fri Jan 07, 2011 7:04 pm
Location: Mexico
Contact:

Post by Artemio » Fri Mar 11, 2011 6:36 am

Thanks, I'll do just that. However I've gone through several versions and modifications, these are just my current tests. Here is the original one from the mini devkit:

Code: Select all

.text

*-------------------------------------------------------
*
*       Sega startup code for the GNU Assembler
*       Translated from:
*       Sega startup code for the Sozobon C compiler
*       Written by Paul W. Lee
*       Modified from Charles Coty's code
*       Modified from Stephane Dallongeville's code
*
*-------------------------------------------------------

        .org    0x00000000

_Start_Of_Rom:
_Vecteurs_68K:
        dc.l    0x00FFFE00              /* Stack address */
        dc.l    _Entry_Point            /* Program start address */
        dc.l    _Bus_Error
        dc.l    _Address_Error
        dc.l    _Illegal_Instruction
        dc.l    _Zero_Divide
        dc.l    _Chk_Instruction
        dc.l    _Trapv_Instruction
        dc.l    _Privilege_Violation
        dc.l    _Trace
        dc.l    _Line_1010_Emulation
        dc.l    _Line_1111_Emulation
        dc.l     _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
        dc.l     _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
        dc.l     _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
        dc.l    _Error_Exception, _INT, _INT, _INT
        dc.l    _HBL
        dc.l    _INT
        dc.l    _VBL
        dc.l    _INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT

_Console:
        .ascii  "SEGA MEGA DRIVE "                                  /* Console Name (16) */
_Copyright:
        .ascii  "(C)FLEMTEAM 2011"                                  /* Copyright Information (16) */
_Title_Local:
        .ascii  "SAMPLE PROGRAM                                  "  /* Domestic Name (48) */
_Title_Int:
        .ascii  "SAMPLE PROGRAM                                  "  /* Overseas Name (48) */
_Serial:
        .ascii  "GM 00000000-00"                                    /* Serial Number (2, 14) */
_Checksum:
        dc.w    0x0000                                              /* Checksum (2) */
        .ascii  "JD              "                                  /* I/O Support (16) */
_Rom_Start_Loc:
        dc.l    _Start_Of_Rom                                       /* ROM Start Address (4) */
_Rom_End_Loc:
        dc.l    0x00020000                                          /* ROM End Address (4) */
_Ram_Start_Loc:
        dc.l    0x00FF0000                                          /* Start of Backup RAM (4) */
_Ram_End_Loc:
        dc.l    0x00FFFFFF                                          /* End of Backup RAM (4) */
        .ascii  "                        "                          /* Modem Support (12) */
_Notes:
        .ascii  "DEMONSTRATION PROGRAM                   "          /* Memo (40) */
_Region:
        .ascii  "JUE             "                                  /* Country Support (16) */

_Entry_Point:
        tst.l   0xa10008
        bne.s   SkipJoyDetect
        tst.w   0xa1000c
SkipJoyDetect:
        bne.s   SkipSetup

        move    #0x2700,%sr
        lea     Table,%a5
        movem.w (%a5)+,%d5-%d7
        movem.l (%a5)+,%a0-%a4
* Check Version Number
        move.b  -0x10ff(%a1),%d0
        andi.b  #0x0f,%d0
        beq.s   WrongVersion
* Sega Security Code (SEGA)
        move.l  #0x53454741,0x2f00(%a1)
WrongVersion:
        move.w  (%a4),%d0
        moveq   #0x00,%d0
        movea.l %d0,%a6
        move    %a6,%usp
        jmp     Continue

Table:
        dc.w    0x8000,0x3fff,0x0100
        dc.l    0xA00000,0xA11100,0xA11200,0xC00000,0xC00004

SkipSetup:
        move.w  #0,%a7
        move.w  #0x2300,%sr
        jmp     _reset_entry

Continue:

* clear Genesis RAM
        lea     0xff0000,%a0
        moveq   #0,%d0
        move.w  #0x3FFF,%d1
clrram:
        move.l  %d0,(%a0)+
        dbra    %d1,clrram

        move.w  #0,%a7
        move.w  #0x2300,%sr

* Jump to initialisation process...

        jmp     _start_entry


*------------------------------------------------
*
*       interrupt functions
*
*------------------------------------------------

.text


_Bus_Error:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr     _buserror_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_Address_Error:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr     _addresserror_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_Illegal_Instruction:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr     _illegalinst_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_Zero_Divide:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr     _zerodivide_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_Chk_Instruction:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr     _chkinst_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_Trapv_Instruction:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr     _trapvinst_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_Privilege_Violation:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr     _privilegeviolation_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_Trace:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr     _trace_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_Line_1010_Emulation:
_Line_1111_Emulation:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr     _line1x1x_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_Error_Exception:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr    _errorexception_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_INT:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr    _int_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte
_HBL:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr    _hblank_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

_VBL:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        jsr    _vblank_callback
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte

*------------------------------------------------
*
* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
*    of using this software, even if they result from defects in it.
*
*------------------------------------------------

ldiv:
        move.l  4(%a7),%d0
        bpl     ld1
        neg.l   %d0
ld1:
        move.l  8(%a7),%d1
        bpl     ld2
        neg.l   %d1
        eor.b   #0x80,4(%a7)
ld2:
        bsr     i_ldiv          /* d0 = d0/d1 */
        tst.b   4(%a7)
        bpl     ld3
        neg.l   %d0
ld3:
        rts

lmul:
        move.l  4(%a7),%d0
        bpl     lm1
        neg.l   %d0
lm1:
        move.l  8(%a7),%d1
        bpl     lm2
        neg.l   %d1
        eor.b   #0x80,4(%a7)
lm2:
        bsr     i_lmul          /* d0 = d0*d1 */
        tst.b   4(%a7)
        bpl     lm3
        neg.l   %d0
lm3:
        rts

lrem:
        move.l  4(%a7),%d0
        bpl     lr1
        neg.l   %d0
lr1:
        move.l  8(%a7),%d1
        bpl     lr2
        neg.l   %d1
lr2:
        bsr     i_ldiv          /* d1 = d0%d1 */
        move.l  %d1,%d0
        tst.b   4(%a7)
        bpl     lr3
        neg.l   %d0
lr3:
        rts

ldivu:
        move.l  4(%a7),%d0
        move.l  8(%a7),%d1
        bsr     i_ldiv
        rts

lmulu:
        move.l  4(%a7),%d0
        move.l  8(%a7),%d1
        bsr     i_lmul
        rts

lremu:
        move.l  4(%a7),%d0
        move.l  8(%a7),%d1
        bsr     i_ldiv
        move.l  %d1,%d0
        rts
*
* A in d0, B in d1, return A*B in d0
*
i_lmul:
        move.l  %d3,%a2           /* save d3 */
        move.w  %d1,%d2
        mulu    %d0,%d2           /* d2 = Al * Bl */

        move.l  %d1,%d3
        swap    %d3
        mulu    %d0,%d3           /* d3 = Al * Bh */

        swap    %d0
        mulu    %d1,%d0           /* d0 = Ah * Bl */

        add.l   %d3,%d0           /* d0 = (Ah*Bl + Al*Bh) */
        swap    %d0
        clr.w   %d0               /* d0 = (Ah*Bl + Al*Bh) << 16 */

        add.l   %d2,%d0           /* d0 = A*B */
        move.l  %a2,%d3           /* restore d3 */
        rts
*
*A in d0, B in d1, return A/B in d0, A%B in d1
*
i_ldiv:
        tst.l   %d1
        bne     nz1

*       divide by zero
*       divu    #0,%d0            /* cause trap */
        move.l  #0x80000000,%d0
        move.l  %d0,%d1
        rts
nz1:
        move.l  %d3,%a2           /* save d3 */
        cmp.l   %d1,%d0
        bhi     norm
        beq     is1
*       A<B, so ret 0, rem A
        move.l  %d0,%d1
        clr.l   %d0
        move.l  %a2,%d3           /* restore d3 */
        rts
*       A==B, so ret 1, rem 0
is1:
        moveq.l #1,%d0
        clr.l   %d1
        move.l  %a2,%d3           /* restore d3 */
        rts
*       A>B and B is not 0
norm:
        cmp.l   #1,%d1
        bne     not1
*       B==1, so ret A, rem 0
        clr.l   %d1
        move.l  %a2,%d3           /* restore d3 */
        rts
*  check for A short (implies B short also)
not1:
        cmp.l   #0xffff,%d0
        bhi     slow
*  A short and B short -- use 'divu'
        divu    %d1,%d0           /* d0 = REM:ANS */
        swap    %d0               /* d0 = ANS:REM */
        clr.l   %d1
        move.w  %d0,%d1           /* d1 = REM */
        clr.w   %d0
        swap    %d0
        move.l  %a2,%d3           /* restore d3 */
        rts
* check for B short
slow:
        cmp.l   #0xffff,%d1
        bhi     slower
* A long and B short -- use special stuff from gnu
        move.l  %d0,%d2
        clr.w   %d2
        swap    %d2
        divu    %d1,%d2           /* d2 = REM:ANS of Ahi/B */
        clr.l   %d3
        move.w  %d2,%d3           /* d3 = Ahi/B */
        swap    %d3

        move.w  %d0,%d2           /* d2 = REM << 16 + Alo */
        divu    %d1,%d2           /* d2 = REM:ANS of stuff/B */

        move.l  %d2,%d1
        clr.w   %d1
        swap    %d1               /* d1 = REM */

        clr.l   %d0
        move.w  %d2,%d0
        add.l   %d3,%d0           /* d0 = ANS */
        move.l  %a2,%d3           /* restore d3 */
        rts
*       A>B, B > 1
slower:
        move.l  #1,%d2
        clr.l   %d3
moreadj:
        cmp.l   %d0,%d1
        bhs     adj
        add.l   %d2,%d2
        add.l   %d1,%d1
        bpl     moreadj
* we shifted B until its >A or sign bit set
* we shifted #1 (d2) along with it
adj:
        cmp.l   %d0,%d1
        bhi     ltuns
        or.l    %d2,%d3
        sub.l   %d1,%d0
ltuns:
        lsr.l   #1,%d1
        lsr.l   #1,%d2
        bne     adj
* d3=answer, d0=rem
        move.l  %d0,%d1
        move.l  %d3,%d0
        move.l  %a2,%d3           /* restore d3 */
        rts
Here's what my first attempt looked like:

Code: Select all

.text

*-------------------------------------------------------
*
*       Sega startup code for the GNU Assembler
*       Translated from:
*       Sega startup code for the Sozobon C compiler
*       Written by Paul W. Lee
*       Modified from Charles Coty's code
*       Modified from Stephane Dallongeville's code
*
*-------------------------------------------------------

        .org    0x00000000

_Start_Of_Rom:
_Vecteurs_68K:
        dc.l    0x00FFFE00              /* Stack address */
        dc.l    _Entry_Point            /* Program start address */
        dc.l    _Bus_Error
        dc.l    _Address_Error
        dc.l    _Illegal_Instruction
        dc.l    _Zero_Divide
        dc.l    _Chk_Instruction
        dc.l    _Trapv_Instruction
        dc.l    _Privilege_Violation
        dc.l    _Trace
        dc.l    _Line_1010_Emulation
        dc.l    _Line_1111_Emulation
        dc.l     _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
        dc.l     _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
        dc.l     _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
        dc.l    _Error_Exception, _INT, _INT, _INT
        dc.l    _HBL
        dc.l    _INT
        dc.l    _VBL
        dc.l    _INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT

_Entry_Point:
        tst.l   0xa10008
        bne.s   SkipJoyDetect
        tst.w   0xa1000c
SkipJoyDetect:
        bne.s   SkipSetup

        move    #0x2700,%sr
        lea     Table,%a5
        movem.w (%a5)+,%d5-%d7
        movem.l (%a5)+,%a0-%a4

        jmp     Continue

Table:
        dc.w    0x8000,0x3fff,0x0100
        dc.l    0xA00000,0xA11100,0xA11200,0xC00000,0xC00004

SkipSetup:
        move.w  #0,%a7
        move.w  #0x2300,%sr
        jmp     _reset_entry

Continue:

* clear Genesis RAM
        lea     0xff0000,%a0
        moveq   #0,%d0
        move.w  #0x3F3F,%d1
clrram:
        move.l  %d0,(%a0)+
        dbra    %d1,clrram

        move.w  #0,%a7
        move.w  #0x2300,%sr

* Jump to initialisation process...

        jmp     _start_entry

(I left the next lines unmodifided)

And tried also just:

Code: Select all

.text

*-------------------------------------------------------
*
*       Sega startup code for the GNU Assembler
*       Translated from:
*       Sega startup code for the Sozobon C compiler
*       Written by Paul W. Lee
*       Modified from Charles Coty's code
*       Modified from Stephane Dallongeville's code
*
*-------------------------------------------------------

        .org    0x00000000

_Start_Of_Rom:
_Vecteurs_68K:
        dc.l    0x00FFFE00              /* Stack address */
        dc.l    _Entry_Point            /* Program start address */
        dc.l    _Bus_Error
        dc.l    _Address_Error
        dc.l    _Illegal_Instruction
        dc.l    _Zero_Divide
        dc.l    _Chk_Instruction
        dc.l    _Trapv_Instruction
        dc.l    _Privilege_Violation
        dc.l    _Trace
        dc.l    _Line_1010_Emulation
        dc.l    _Line_1111_Emulation
        dc.l     _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
        dc.l     _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
        dc.l     _Error_Exception, _Error_Exception, _Error_Exception, _Error_Exception
        dc.l    _Error_Exception, _INT, _INT, _INT
        dc.l    _HBL
        dc.l    _INT
        dc.l    _VBL
        dc.l    _INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT
        dc.l    _INT,_INT,_INT,_INT,_INT,_INT,_INT,_INT

_Entry_Point:  
        move    #0x2700,%sr              /* interrupts disabled */

        lea     __stack,%a0
        movea.l %a0,%sp                   /* set stack pointer to top of Work RAM */

* Clear Work RAM (0xFF0000 to 0xFFFCFF)
        lea     0xFF0000,%a0
        moveq   #0,%d0
        move.w  #0x3F3F,%d1
cram:
        move.l  %d0,(%a0)+
        dbra    %d1,cram

* Copy initialized variables from ROM to Work RAM
        lea     _stext,%a0
        adda.l  #0x00200000,%a0
        lea     0xFF0000,%a1
        move.l  #_sdata,%d0
        lsr.l   #1,%d0
        subq.w  #1,%d0
exec:
        move.w  (%a0)+,(%a1)+
        dbra    %d0,exec

        jsr     _start_entry                    /* call main() */
        jmp     _Entry_Point       

(with the rest of the file from then on)
I must be honest, although I know some 8086 asm, I don't know 68000 and have just been guessing at it... I am interested on learning it later on.

I've used a modified md.ld and also the one posted above by Chilly Willy.

Artemio
Interested
Posts: 22
Joined: Fri Jan 07, 2011 7:04 pm
Location: Mexico
Contact:

Post by Artemio » Fri Mar 11, 2011 6:44 am

And the mcd.ld I derived from the original md.ld included on the devkit.

Code: Select all

OUTPUT_ARCH(m68k)
SEARCH_DIR(.)
/*GROUP(-lbcc -lc -lgcc)*/
__DYNAMIC  =  0;

/*
 * Setup the memory map of the SEGA Genesis.
 * stack grows down from high memory.
 *
 * The memory map look like this:
 * +--------------------+ <- low memory
 * | .text              |
 * |        _etext      |
 * |        ctor list   | the ctor and dtor lists are for
 * |        dtor list   | C++ support
 * +--------------------+
 * | .data              | initialized data goes here
 * |        _data       | 
 * |        _edata      |
 * +--------------------+
 * | .bss               |
 * |        _bstart     | start of bss, cleared by crt0
 * |        _bend       | start of heap, used by sbrk()
 * |        __bss_start | start of bss, cleared by crt0
 * |        _end        | start of heap, used by sbrk()
 * +--------------------+
 * .                    .
 * .                    .
 * .                    .
 * |        __stack     | top of stack
 * +--------------------+
 */
MEMORY
{
	rom : ORIGIN = 0x00200000, LENGTH = 0x0003FFFF
	ram : ORIGIN = 0x00ff0000, LENGTH = 0x0000FE00
  }

/*
 * allocate the stack to be at the top of memory, since the stack
 * grows down
 */

PROVIDE (__stack = 0x00fffe00);

/*
 * Initalize some symbols to be zero so we can reference them in the
 * crt0 without core dumping. These functions are all optional, but
 * we do this so we can have our crt0 always use them if they exist.
 * This is so BSPs work better when using the crt0 installed with gcc.
 * We have to initalize them twice, so we cover a.out (which prepends
 * an underscore) and coff object file formats.
 */
PROVIDE (hardware_init_hook = 0);
PROVIDE (_hardware_init_hook = 0);
PROVIDE (software_init_hook = 0);
PROVIDE (_software_init_hook = 0);

SECTIONS
{
  .text 0x00200000:
  {
    *(.text)
    . = ALIGN(0x4);
     __CTOR_LIST__ = .;
    LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
    *(.ctors)
    LONG(0)
    __CTOR_END__ = .;
    __DTOR_LIST__ = .;
    LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
    *(.dtors)
     LONG(0)
    __DTOR_END__ = .;
    *(.rodata*)
    *(.gcc_except_table)

    __INIT_SECTION__ = . ;
    *(.init)
    SHORT (0x4e75)	/* rts */

    __FINI_SECTION__ = . ;
    *(.fini)
    SHORT (0x4e75)	/* rts */

    _etext = .;
    *(.lit)
  } > rom
  _stext = SIZEOF (.text); 

  .data BLOCK (0x4) :
  {
    *(.shdata)
    *(.data)
    _edata = .;
  } > ram
  _sdata = SIZEOF (.data); 

  .bss 0xff0000 :
  {
    __bss_start = . ;
    *(.shbss)
    *(.bss)
    *(COMMON)
    *(.eh_fram)
    *(.eh_frame)
    _end =  ALIGN (0x8);
    __end = _end;
  } > ram

  .stab 0 (NOLOAD) :
  {
    *(.stab)
  }

  .stabstr 0 (NOLOAD) :
  {
    *(.stabstr)
  }
}

SoullessSentinel
Interested
Posts: 24
Joined: Wed Feb 03, 2010 12:53 am
Location: Grimsby, England

Post by SoullessSentinel » Fri Mar 11, 2011 6:58 am

You will want to remove the entire vectors section from your modified Sega.s so that the code simply starts at entry_point.
Otherwise it would try to execute that data as code.

The vector table is now located at $FFFD00 in RAM, so, directly after the _Entry_Point: line, you would have to write code to load the address of your HBL and VBL routines to this table, I can't remember the exact format, so you would have to look this up in the official Sega CD documentation.

The code will also have to be ".org"'d to 0x00200000

Artemio
Interested
Posts: 22
Joined: Fri Jan 07, 2011 7:04 pm
Location: Mexico
Contact:

Post by Artemio » Fri Mar 11, 2011 7:10 am

OK... I just removed the vector table, and ran it.. it is loading.. but I do need to load the HBL and VBL.. will figure that out then next. What i do know now is that it is executing from the correct address.

It is now loading the font and palettes, but that's all for now. Great advance anyway =)

If I moved org to 0x00200000, I was getting out of rom range again.. I assume since it is inside .text it works alright.

Thanks for the help!

EDIT:

Just checked the VDP RAM on Gens, and the font is being loaded incorrectly... If I look at the CD Word RAM the tiles are there correctly, but not on the VDP:

Image

Uploaded with ImageShack.us[/img]

Post Reply