Update your Genesis/32X Toolchain!

Talk about development tools here

Moderator: BigEvilCorporation

Zontar
Very interested
Posts: 55
Joined: Fri Oct 21, 2011 8:58 pm

Post by Zontar » Wed Apr 08, 2015 12:14 am

Moon-Watcher wrote:I used noname22's script it and got this error building the MD TicTacToe on C++

Code: Select all

t800@cabronazo:~/Escritorio/TicTacToe/C++/MD$ make -f Makefile
m68k-elf-g++ -T /opt/toolchains/gen/ldscripts/md.ld -Wl,-Map=output.map -nostdlib -ffreestanding -fno-rtti crt0.o crtstuff.o main.o hw_md.o font.o -L/opt/toolchains/gen/m68k-elf/lib -L/opt/toolchains/gen/m68k-elf/m68k-elf/lib -lstdc++ -lc -lgcc -lnosys -o TicTacToe.elf
/opt/toolchains/gen/m68k-elf/m68k-elf/lib/libc.a(lib_a-closer.o): En la función `_close_r':
/home/t800/megadrive-gcc-master/build/build-newlib-m68k-elf-2.0.0/m68k-elf/newlib/libc/reent/../../../../../newlib-2.0.0/newlib/libc/reent/closer.c:53: aviso: _close is not implemented and will always fail
/opt/toolchains/gen/m68k-elf/m68k-elf/lib/libc.a(lib_a-fstatr.o): En la función `_fstat_r':
/home/t800/megadrive-gcc-master/build/build-newlib-m68k-elf-2.0.0/m68k-elf/newlib/libc/reent/../../../../../newlib-2.0.0/newlib/libc/reent/fstatr.c:62: aviso: _fstat is not implemented and will always fail
/opt/toolchains/gen/m68k-elf/m68k-elf/lib/libc.a(lib_a-signalr.o): En la función `_getpid_r':
/home/t800/megadrive-gcc-master/build/build-newlib-m68k-elf-2.0.0/m68k-elf/newlib/libc/reent/../../../../../newlib-2.0.0/newlib/libc/reent/signalr.c:96: aviso: _getpid is not implemented and will always fail
/opt/toolchains/gen/m68k-elf/m68k-elf/lib/libc.a(lib_a-isattyr.o): En la función `_isatty_r':
/home/t800/megadrive-gcc-master/build/build-newlib-m68k-elf-2.0.0/m68k-elf/newlib/libc/reent/../../../../../newlib-2.0.0/newlib/libc/reent/isattyr.c:58: aviso: _isatty is not implemented and will always fail
/opt/toolchains/gen/m68k-elf/m68k-elf/lib/libc.a(lib_a-signalr.o): En la función `_kill_r':
/home/t800/megadrive-gcc-master/build/build-newlib-m68k-elf-2.0.0/m68k-elf/newlib/libc/reent/../../../../../newlib-2.0.0/newlib/libc/reent/signalr.c:61: aviso: _kill is not implemented and will always fail
/opt/toolchains/gen/m68k-elf/m68k-elf/lib/libstdc++.a(basic_file.o): En la función `std::__basic_file<char>::seekoff(long long, std::_Ios_Seekdir)':
/home/t800/megadrive-gcc-master/build/build-gcc-m68k-elf-4.9.1/m68k-elf/libstdc++-v3/src/c++98/basic_file.cc:327: aviso: _lseek is not implemented and will always fail
/opt/toolchains/gen/m68k-elf/m68k-elf/lib/libc.a(lib_a-openr.o): En la función `_open_r':
/home/t800/megadrive-gcc-master/build/build-newlib-m68k-elf-2.0.0/m68k-elf/newlib/libc/reent/../../../../../newlib-2.0.0/newlib/libc/reent/openr.c:59: aviso: _open is not implemented and will always fail
/opt/toolchains/gen/m68k-elf/m68k-elf/lib/libstdc++.a(basic_file.o): En la función `std::__basic_file<char>::xsgetn(char*, long)':
/home/t800/megadrive-gcc-master/build/build-gcc-m68k-elf-4.9.1/m68k-elf/libstdc++-v3/src/c++98/basic_file.cc:289: aviso: _read is not implemented and will always fail
/opt/toolchains/gen/m68k-elf/m68k-elf/lib/libstdc++.a(pure.o): En la función `__cxa_pure_virtual':
/home/t800/megadrive-gcc-master/build/build-gcc-m68k-elf-4.9.1/m68k-elf/libstdc++-v3/libsupc++/../../../../gcc-4.9.1/libstdc++-v3/libsupc++/pure.cc:49: aviso: _write is not implemented and will always fail
/opt/toolchains/gen/m68k-elf/lib/gcc/m68k-elf/4.9.1/../../../../m68k-elf/bin/ld: la sección .gcc_except_table._ZNSt8ios_base4InitC2Ev.part.10 cargada en [0000000000000000,000000000000005b] sobreescribe la sección .text cargada en [0000000000000000,0000000000073e31]
collect2: error: ld devolvió el estado de salida 1
make: *** [TicTacToe.elf] Error 1

Does anyone knows how to solve this?

Code: Select all

collect2: error: ld devolvió el estado de salida 1
Ops, forgot to mention it's a Mind Debian Edition

Code: Select all

$ uname -a
Linux cabronazo 3.11-2-amd64 #1 SMP Debian 3.11.8-1 (2013-11-13) x86_64 GNU/Linux
I am trying a tweak to the toolchain (to fix the problem mentioned above) and got the C++ to compile up to this point. C should work fine if you find it an acceptable substitute.

This problem is the link script (md.ld perhaps). Something internal to GCC is larger than the space allotted to it in the link script, so it's steamrolling over space allotted to whatever "text" is. Unfortunately I don't know how to fix it, as I'm not well versed in GCC's link script feature.

Moon-Watcher
Very interested
Posts: 117
Joined: Sun Jan 02, 2011 9:14 pm
Contact:

Post by Moon-Watcher » Thu Apr 09, 2015 3:06 pm

Thanks, Zontar. Wish I had more knowledge about C++, linkers, toolchains and all these stuff.

I also tryed it in Debian 6 and 7 got the same error. Fedora didn't build it.

SONIC3D
Newbie
Posts: 6
Joined: Fri Dec 28, 2007 6:05 am
Location: Shanghai

Post by SONIC3D » Sat Jul 25, 2015 8:58 pm

kubilus1 wrote:Fantastic work. It's great to have other build options for other operating systems. That should help keep interest in our hobby.
I think you are mattkubilus :D Really thanks for your marvelous works.I just modified a little to make OS X user can easily compile it.
Stef wrote:Great ! I put a link on the main SGDK project page if you don't mind :)


Thank Stef.Sure not mind.All I want is make more and more genesis/32x dev fans who using OS X successfully build the toolchains with simple steps as linux users.Thanks for your help.




And recently I received email on failed to build my previous works.I found it is because I used to do dev works under OS X 10.8.5 with Clang 5.x.It's not the newest dev env.

I have just updated the repository to make it compilable with OS X Yosemite 10.10.3 with Command Line Tools for XCode 6.4(Clang 6.x environment).That's the most recent stable command line development environment provided by Apple so far.

So hope it will be useful to more genesis dev fans who have updated their OS X.
https://github.com/SONIC3D/gendev-macos

KillaMaaki
Very interested
Posts: 84
Joined: Sat Feb 28, 2015 9:22 pm

Re: Update your Genesis/32X Toolchain!

Post by KillaMaaki » Thu Oct 01, 2015 7:49 am

Any progress or ideas on how to get the C++ example compiling? I can compile the C version of TicTacToe and the Yeti example, but the C++ version of TicTacToe just fails with a similar error as reported a few posts ago...
If it came down to it I suppose I could make C work, but it'd be fantastic to have access to an object-oriented language.

I'm also using noname22's github project, same as the user with the error a few posts ago.

Is Chilly around to take a peek at this?

mikejmoffitt
Very interested
Posts: 86
Joined: Fri Sep 25, 2015 4:16 pm

Re: Update your Genesis/32X Toolchain!

Post by mikejmoffitt » Fri Oct 09, 2015 8:05 pm

Having trouble building the toolchain. Binutils keeps failing because --disable-werror seems to have no effect.

GeoffLedak
Interested
Posts: 16
Joined: Thu Jan 05, 2017 10:14 pm

Re: Update your Genesis/32X Toolchain!

Post by GeoffLedak » Wed Aug 23, 2017 4:31 pm

Thanks a bunch for this Chilly Willy.

I've been working with the toolchain and was able to put together an XBAND keyboard test rom using the same keyboard read and write functions from the XBAND source code.

To keep my main loop running at 60 iterations per second I wrote a WaitForVBlank function (mostly copied from SGDK) which is executed during every main loop iteration:

Code: Select all

void WaitForVBlank() {
	volatile unsigned short *pw;
	pw = (volatile unsigned short *) 0xC00004;
	while (*pw & (1 << 3));
	while (!(*pw & (1 << 3)));
}
I've been working on trying to call a C function during vblank interrupt. Glancing at the SGDK source code, the subroutine that is executed during vblank looks like this:

Code: Select all

_VINT:
        movem.l %d0-%d1/%a0-%a1,-(%sp)
        move.l  internalVIntCB, %a0
        jsr    (%a0)
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte
internalVIntCB is a C function pointer declared elsewhere in the code.

The vblank subroutine included with the Genesis tic-tac-toe demo looks like this:

Code: Select all

vblank:
        move.l  vblank_vector,-(sp)
        beq.b   1f
        rts
1:
        addq.l  #1,gTicks
        addq.l  #4,sp
        rte
I don't really know 68k assembly and I'm unsure what this code even does, and if the "1:" subroutine is part of it or not. I've tried copying the vblank subroutine from SGDK and declaring functions and function pointers in a variety of ways but so far nothing has worked.

The code for the keyboard test rom can be viewed here:
https://github.com/GeoffLedak/Sega-Gene ... board-Test

I imagine what I'm trying to do is fairly simple and I'm missing something obvious.

Grind
Very interested
Posts: 69
Joined: Fri Jun 13, 2014 1:26 pm
Location: US
Contact:

Re: Update your Genesis/32X Toolchain!

Post by Grind » Wed Aug 23, 2017 5:12 pm

Here's what I do.

Make a global byte somewhere in the assembly where you declare your variables (pasting this before ".section.keepboot" in sega.s will work).

Code: Select all

.section .data

	.globl vblank
vblank:		ds.b 1
Point the VInt vector to this. All it does is clear the byte.

Code: Select all

VerticalInt:
        clr.b	(vblank)
        rte
Then access it from C. The vsync function sets vblank and waits for it to be cleared by the interrupt.

Code: Select all

extern volatile uint8_t vblank;

void vdp_vsync() {
	vblank = 1;
	while(vblank);
}
In Chilly's code the "1:" is a local label (how GNU AS does it). Notice the line before it "beq.b 1f" (branch if equal). It jumps (f)orward to the next label "1".


EDIT: Gah of course I misread what you are looking for. Calling something after the while loop in vsync() should be the same as calling C from the interrupt most of the time, but if you need to guarantee this function runs every vblank (even if the main loop is lagging behind 60fps) we better troubleshoot whatever you have now. You get an error message compiling/assembling/linking, or the ROM does something bad?

GeoffLedak
Interested
Posts: 16
Joined: Thu Jan 05, 2017 10:14 pm

Re: Update your Genesis/32X Toolchain!

Post by GeoffLedak » Wed Aug 23, 2017 8:22 pm

I'm able to compile the rom but when I run it I just get a black screen that does nothing.

Here's my main C file:

Code: Select all

#include <stdio.h>
#include <stdlib.h>

#include "hw_md.h"

void putChar(char character);
void advanceCursor();
void putNewline();
void WaitForVBlank();
void readControllers();

char xPosition = 4;
char yPosition = 0;

char aButtonPressed = 0;
char bButtonPressed = 0;
char cButtonPressed = 0;
char startButtonPressed = 0;

char counter = 0;

void _vint_callback();
void *internalVIntCB;



int main(void)
{
    internalVIntCB = _vint_callback;
	
	// put_str("A = A, B = B, C = C, Start = newline", 0x0000, 0, 0);
	put_str("C:\\>", 0x0000, 0, 0);

    while ( 1 ) // endless loop
    {
        counter++;

        if( counter >= 120 ) {

            putChar('j');
            counter = 0;
        }

        readControllers();


		WaitForVBlank();
    }
	
	
	
    return 0;
}



void readControllers() {

    short buttons = 0;
    buttons = get_pad(0);

    // check A button
    if( buttons & SEGA_CTRL_A )
    {
        if( !aButtonPressed ) {
            putChar('A');
            aButtonPressed = 1;
        }
    }
    else
    {
        aButtonPressed = 0;
    }

    // check B button
    if ( buttons & SEGA_CTRL_B )
    {
        if( !bButtonPressed ) {
            putChar('B');
            bButtonPressed = 1;
        }
    }
    else
    {
        bButtonPressed = 0;
    }

    // check C button
    if ( buttons & SEGA_CTRL_C )
    {
        if( !cButtonPressed ) {
            putChar('C');
            cButtonPressed = 1;
        }
    }
    else
    {
        cButtonPressed = 0;
    }

    // check Start button
    if ( buttons & SEGA_CTRL_START )
    {
        if( !startButtonPressed ) {
            putNewline();
            startButtonPressed = 1;
        }
    }
    else
    {
        startButtonPressed = 0;
    }
}




void _vint_callback()
{
    putChar('m');
}




void WaitForVBlank() {
	
	
	volatile unsigned short *pw;

    pw = (volatile unsigned short *) 0xC00004;

    while (*pw & (1 << 3));
	while (!(*pw & (1 << 3)));
	
}


void advanceCursor()
{
	xPosition++;

	if( xPosition > 39 )
	{
		xPosition = 0;
		yPosition++;
		
		if( yPosition > 27 )
		{
			yPosition = 0;
		}
	}
}

void putChar(char character)
{
	put_chr(character, 0x0000, xPosition, yPosition);
	advanceCursor();
}

void putNewline()
{
	xPosition = 0;
	yPosition++;
	
	if( yPosition > 27 )
	{
		yPosition = 0;
	}
}
and here is my crt0.s file:

Code: Select all

| SEGA MegaDrive support code
| by Chilly Willy

        .text

| Initial exception vectors

        .long   0x01000000,initialize,exception,exception,exception,exception,exception,exception
        .long   exception,exception,exception,exception,exception,exception,exception,exception
        .long   exception,exception,exception,exception,exception,exception,exception,exception
        .long   exception,exception,exception,exception,hblank,exception,vblank,exception
        .long   exception,exception,exception,exception,exception,exception,exception,exception
        .long   exception,exception,exception,exception,exception,exception,exception,exception
        .long   exception,exception,exception,exception,exception,exception,exception,exception
        .long   exception,exception,exception,exception,exception,exception,exception,exception

| Standard MegaDrive ROM header at 0x100

        .ascii  "SEGA MD Example "      /* SEGA must be the first four chars for TMSS */
        .ascii  "(C)2011         "
        .ascii  "Example startup "      /* export name */
        .ascii  "code for MD     "
        .ascii  "                "
        .ascii  "Example startup "      /* domestic (Japanese) name */
        .ascii  "code for MD     "
        .ascii  "                "
        .ascii  "GM MK-0000 -00"
        .word   0x0000                  /* checksum - not needed */
        .ascii  "J6              "
        .long   0x00000000,0x0007FFFF   /* ROM start, end */
        .long   0x00FF0000,0x00FFFFFF   /* RAM start, end */

        .ifdef  HAS_SAVE_RAM
        .ascii  "RA"                    /* External RAM */
        .byte   0xF8                    /* don't clear + odd bytes */
        .byte   0x20                    /* SRAM */
        .long   0x00200001,0x0020FFFF   /* SRAM start, end */
        .else
        .ascii  "            "          /* no SRAM */
        .endif

        .ascii  "    "
        .ascii  "        "

        .ifdef  MYTH_HOMEBREW
        .ascii  "MYTH3900"              /* memo indicates Myth native executable */
        .else
        .ascii  "        "              /* memo */
        .endif

        .ascii  "                "
        .ascii  "                "
        .ascii  "F               "      /* enable any hardware configuration */


| Standard MegaDrive startup at 0x200

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

        tst.l   0xA10008                /* check CTRL1 and CTRL2 setup */
        bne.b   1f
        tst.w   0xA1000C                /* check CTRL3 setup */
1:
        bne.b   skip_tmss               /* if any controller control port is setup, skip TMSS handling */

| Check Hardware Version Number
        move.b  0xA10001,d0
        andi.b  #0x0F,d0                /* VERS */
        beq     2f                      /* 0 = original hardware, TMSS not present */
        move.l  #0x53454741,0xA14000    /* Store Sega Security Code "SEGA" to TMSS */
2:
        move.w  0xC00004,d0             /* read VDP Status reg */

skip_tmss:
        move.w  #0x8104,0xC00004        /* display off, vblank disabled */
        move.w  0xC00004,d0             /* read VDP Status reg */

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

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

        lea     0x01000000,a0
        movea.l a0,sp                   /* set stack pointer to top of Work RAM */
        link.w  a6,#-8                  /* set up initial stack frame */

        jsr     init_hardware           /* initialize the console hardware */

        jsr     __INIT_SECTION__        /* do all program initializers */
        jsr     main                    /* call program main() */
        jsr     __FINI_SECTION__        /* do all program finishers */
3:
        bra.b   3b


| put redirection vectors and gTicks at start of Work RAM

        .data

        .global exception_vector
exception_vector:
        .long   0
        .global exception_vector
hblank_vector:
        .long   0
        .global exception_vector
vblank_vector:
        .long   0
        .global gTicks
gTicks:
        .long   0

| Exception handlers

exception:
        move.l  exception_vector,-(sp)
        beq.b   1f
        rts
1:
        addq.l  #4,sp
        rte

hblank:
        move.l  hblank_vector,-(sp)
        beq.b   1f
        rts
1:
        addq.l  #4,sp
        rte

vblank:
|        move.l  vblank_vector,-(sp)
|        beq.b   1f
|        rts
|1:
|        addq.l  #1,gTicks
|        addq.l  #4,sp
|        rte

        movem.l %d0-%d1/%a0-%a1,-(%sp)
        move.l  internalVIntCB, %a0
        jsr    (%a0)
        movem.l (%sp)+,%d0-%d1/%a0-%a1
        rte



        .text
What I'm trying to make happen is every 2 seconds the character 'j' will be printed, and every 1 second the character 'm' will be printed 60 times.

I declare a C function called "void _vint_callback()" and a function pointer called "void *internalVIntCB". internalVIntCB is assigned to point to the _vint_callback() function at the beginning of the main() function.

The letter 'j' is printed from inside the main loop, and the 'm' character should be printed during vblank interrupt.

Before I added the code to print the letter 'm' during vblank, the program properly printed out the letter 'j' every 2 seconds .

I commented out what was in the vblank subroutine and replaced it with the contents of the SGDK vblank routine which I think is what is causing my problem. I imagine the stuff regarding "vblank_vector" and "gTicks" is important, but I'm unsure of what exactly it does and how it should be organized along with my internalVIntCB callback.

EDIT: or perhaps it's trying to call the internalVIntCB function before the pointer has been given a value and the program is crashing...

GeoffLedak
Interested
Posts: 16
Joined: Thu Jan 05, 2017 10:14 pm

Re: Update your Genesis/32X Toolchain!

Post by GeoffLedak » Wed Aug 23, 2017 9:16 pm

progress.

Now the program prints a single letter 'm' and then appears to hang. I changed the vblank subroutine to this:

Code: Select all

vblank:
        move.l  internalVIntCB,-(sp)
        beq.b   1f
        rts
1:
        addq.l  #1,gTicks
        addq.l  #4,sp
        rte

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

Re: Update your Genesis/32X Toolchain!

Post by Chilly Willy » Thu Aug 24, 2017 5:19 pm

The vblank int handler in my demo code is meant to be fast... hence the lack of pushing/popping regs. You'd need to push/pop all volatile registers to call a C function from it. So if you wish to wedge a C call into my demo code, it would look like this

Code: Select all

vblank:
        move.l  vblank_vector,-(sp)
        beq.b   1f
        rts
1:
        addq.l  #1,gTicks
        addq.l  #4,sp
        rte

CFunctWedge:
        movem.l d0-d1/a0-a1,-(sp)
        lea CFunct,a0
        jsr (a0)
        movem.l (sp)+, d0-d1/a0-a1
        addq.l  #1,gTicks
        rte
Then somewhere in the C code when you're ready for it to call your C code, you'd set vblank_vector to CFuntWedge, which would then call your C funtion (be sure the names match - I just put CFunct as an example), then cleanup the regs and increment gTicks. Note that CFunctWedge does NOT add 4 to sp because the rts that call it did that already.

GeoffLedak
Interested
Posts: 16
Joined: Thu Jan 05, 2017 10:14 pm

Re: Update your Genesis/32X Toolchain!

Post by GeoffLedak » Thu Aug 24, 2017 9:02 pm

Thanks! That's what I needed.

Mask Of Destiny pointed out that it can be simplified a bit with

Code: Select all

jsr	CFunct
No lea needed.

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

Re: Update your Genesis/32X Toolchain!

Post by Chilly Willy » Sun Aug 27, 2017 5:33 pm

Yeah, sorry. Too used to set variables to address, then loading them, which I simply turned into a lea of the routine. If you wanted one wedge to call any function, you'd make the lea a movea.l from a variable that you would set before setting the vblank to call the wedge. If you only have the one function, jsr func is simpler and less prone to error.

Muzzy
Interested
Posts: 23
Joined: Mon Jun 19, 2017 5:06 pm

Re: Update your Genesis/32X Toolchain!

Post by Muzzy » Thu Apr 11, 2019 5:25 pm

I guess if I can't stand how to get ROM file from code examples by using this toolchain folders/files - this is not my level of knowledge... :oops:
But for "getting started" purposes - this toolchain can be used through Code Blocks (Windows7/10), like showed in this video - https://www.youtube.com/watch?v=cDEGpLxKDK0 ? And if it can - how to set it up?

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

Re: Update your Genesis/32X Toolchain!

Post by Chilly Willy » Thu Apr 11, 2019 5:54 pm

There isn't a binary arc of a pre-built version of this toolchain (I don't think there is), so you have to build it yourself. People have done this in Windows using minGW + msys as mentioned here:

viewtopic.php?p=12858#p12858

Once you have the toolchain built, you'd set the environment variables in codeblocks much like you would for SGDK like in the video.

I really need to update this for a newer gcc, but that's easy enough - just get the latest gcc/binutils/mpfr/mpc/gmp/newlib, change the makefile for the toolchain to use the version numbers for the latest version rather than the version mentioned in the OP.

Muzzy
Interested
Posts: 23
Joined: Mon Jun 19, 2017 5:06 pm

Re: Update your Genesis/32X Toolchain!

Post by Muzzy » Thu Apr 11, 2019 6:48 pm

Chilly Willy wrote:
Thu Apr 11, 2019 5:54 pm
There isn't a binary arc of a pre-built version of this toolchain (I don't think there is)
Maybe this is the one ? -

So I need only set the environment variables in Codeblocks? And this variables I can get from env.bat file from powerofrecall package - GENDEV\bin; GENDEV\sh-elf\bin; GENDEV\m68k-elf\bin; GENDEV\UTILS :?:

Post Reply