Cross-Human68k toolchain

Started by lydux, April 30, 2012, 07:09:20 AM

Previous topic - Next topic

lydux

Hi x68000 users !

I've finally decided to release my human68k target toolchain.
A way to develop for X68000 using your Linux or Windows box.
My github page : https://github.com/Lydux

Notes:
Actually, newlib lacks of some important low-level functions. I haven't time to maintain it actually. So, any help will be highly appreciated. (Codes/bugs/documentation/...)

Lastest updates:
Sources : 11/23/2012
Windows binaries : 11/26/2012

Setup for Unix like OS
1 - Environment settings
(change as your needs)

# export HUMAN68K_TC=/opt/human68k
# export HUMAN68K_TC_SRC=$HUMAN68K_TC/src
# export PATH=$PATH:$HUMAN68K_TC/bin
# mkdir $HUMAN68K_TC $HUMAN68K_TC_SRC


2 - Binutils
Binutils provide an assembler/disassembler and various tools for executables manipulation.

# cd $HUMAN68K_TC_SRC
# git clone git://github.com/Lydux/binutils-2.22-human68k.git
# mkdir binutils-build
# cd binutils-build
# ../binutils-2.22-human68k/configure --prefix=$HUMAN68K_TC --target=human68k --disable-nls
# make all install


3 - GCC
C compiler. Handle some specificities of the X68000.

# cd $HUMAN68K_TC_SRC
# git clone git://github.com/Lydux/gcc-4.6.2-human68k.git
# mkdir gcc-build
# cd gcc-build
# ../gcc-4.6.2-human68k/configure \
--prefix=$HUMAN68K_TC \
--target=human68k \
--disable-nls \
--disable-libssp \
--with-newlib \
--without-headers \
--enable-languages=c
# make all install


4 - Newlib
Provides common functions for programming in C and does all startup code for communication with human68k kernel.
Provides also system call functions (IPLROM = iocscall, Human68K = doscall)

# cd $HUMAN68K_TC_SRC
# git clone git://github.com/Lydux/newlib-1.19.0-human68k.git
# mkdir newlib-build
# cd newlib-build
# ../newlib-1.19.0-human68k/configure --prefix=$HUMAN68K_TC --target=human68k
# make all install


5 - GDB (optional)
A debugger. It can control the rom monitor embedded inside the IPLROM via a null modem cable.

# cd $HUMAN68K_TC_SRC
# git clone git@github.com:Lydux/gdb-7.4-human68k.git
# mkdir gdb-build
# cd gdb-build
# ../gdb-7.4-human68k/configure --prefix=$HUMAN68K_TC --target=human68k --disable-nls
# make all install



Notes
By default, the toolchain will create an ELF binary file, which is not directly compatible with human68k.
The objcopy tool from binutils provide a way to convert your file easily.

Assuming a simple hello.c source code :
For XFile :

# human68k-gcc hello.c -o hello.elf
# human68k-objcopy -O xfile hello.elf HELLO.X

Or for RFile (can also be used for pc relative SRAM target binary) :

# human68k-gcc -mpcrel hello.c -o hello.elf
# human68k-objcopy -O binary hello.elf HELLO.R


The toolchain also allow you to disassemble an XFile (Usefull for reverse engineering !) :

# human68k-objdump -D ANYFILE.X

Objdump can also show symbols and relocations (relocations does not point to the correct symbol actually)

# human68k-objdump -x ANYFILE.X


Setup for Windows

1 - Download the necessary packages

Download the lastest Windows binary version of Code::Blocks from official website : http://www.codeblocks.org

Download the cross-Human68K toolchain packages for Windows :
Binutils-2.22 : http://nfggames.com/X68000/Development/toolchain/binutils-2.21-human68k-win32-3.zip
Gcc-4.6.2 : http://nfggames.com/X68000/Development/toolchain/gcc-4.6.2-human68k-win32-1.zip
Newlib-1.4.0 : http://nfggames.com/X68000/Development/libraries/newlib-1.19.0-human68k-1.zip
Make-3.82 : http://nfggames.com/X68000/Development/toolchain/make-3.82.zip

Download the Human68K Wizard for Code::Blocks : http://nfggames.com/X68000/Development/toolchain/codeblocks-wizard-human68k-1.zip

2 - Installing the toolchain :
Just extract all toolchain packages into a directory of your choice. (Ex : C:\X68000\DEV)

3 - Installing and configuring Code::Blocks :

Install Code::Blocks like any other application and start it.

Go to "Settings->Compiler and debugger" menu.
Make a copy of the "GNU GCC Compile" (should be selected by default) by clicking on the "Copy" button. Name this new compiler "Human68K GCC".

Now go into the "Toolchain executables" tab, and change all values by these one :


Note : The debugger is not available yet, I have to figure out how to to use it for remote debugging a real x68000 or an emulator.

Of course, change the "Compiler's installation directory" by the one you have choosen.

Now, extract the "Human68k Wizard for Code::Blocks" archive into the directory "share\CodeBlocks\templates\wizard" of your Code::Blocks installation directory (by default, it should be "C:\Program Files\CodeBlocks")
Stay in this wizard directory and edit the file "config.script" (using windows notepad is ok).
Search for these lines :

    RegisterWizard(wizProject,     _T("arm"),          _T("ARM Project"),           _T("Embedded Systems"));
    RegisterWizard(wizProject,     _T("avr"),          _T("AVR Project"),           _T("Embedded Systems"));
    RegisterWizard(wizProject,     _T("tricore"),      _T("TriCore Project"),       _T("Embedded Systems"));
    RegisterWizard(wizProject,     _T("ppc"),          _T("PowerPC Project"),       _T("Embedded Systems"));


and add this one after :


    RegisterWizard(wizProject,     _T("human68k"),      _T("Human68K Project"),      _T("Embedded Systems"));




Restart Code::Blocks, this is now a template "Human68K Project" with a familiar icon when you create a new project.


It will create a simple "hello world" application, you can try building it in order to check that your toolchain is correctly working.

You can also create a new library for Human68K by choosing "Static Library" instead of "Human68K Project".

Happy coding ! :)

neko68k


lydux

Good !  ;)

I see you are on windows, this toolchain should compile as well under MSYS or cygwin.
I also have a ready to use native packages of binutils, gcc, gdb and make for windows which I should drop here for the code::block tutorial. But I can eventually upload them now if you need...


neko68k

Doesn't matter. I run both windows and linux pretty regularly.

trap15

Excellent toolchain, just installed with minor problems (I didn't know I needed Bison and Flex, and the configure for binutils didn't yell at me about it).

I should make a simple bash script to install this for easy automation ;)

AnimaInCorpore

Great work. Many thanks for that.

However, I have a problem assembling the following simple source code ("test.asm"):

.global main

.text

main:
   move   #33,%d0
   lea    hello,%a1
   trap   #15

   clr.w  -(%sp)
   dc.w   0xff4c   

.data

hello:
   .asciz   "Hello World!"

.end


It's been assembled with

human68k-as test.asm -o test.elf

and converted to an executable format using

human68k-objcopy -O xfile test.elf test.x

It seems that the address of the text label "hello" cannot be resolved.

A disassembly of the ELF output via

human68k-objdump -D test.elf

gives

test.elf:     file format elf32-m68k


Disassembly of section .text:

00000000 <main>:
   0:   303c 0021         movew #33,%d0
   4:   43f9 0000 0000    lea 0 <main>,%a1
   a:   4e4f              trap #15
   c:   4267              clrw %sp@-
   e:   ff4c              Address 0x0000000000000010 is out of bounds.
.short 0xff4c

Disassembly of section .data:

00000000 <hello>:
   0:   4865              .short 0x4865
   2:   6c6c              bges 70 <hello+0x70>
   4:   6f20              bles 26 <hello+0x26>
   6:   576f 726c         subqw #3,%sp@(29292)
   a:   6421              bccs 2d <hello+0x2d>
   ...


As you can see the "lea" loads the wrong address. So does anyone know what's wrong?

TIA
Sascha

lydux

Hi AnimaInCorpore !

Nothing is wrong ! You have just assembled your source, and converting it to an XFile. But not created an executable !
So, the result of AS will produce a relocatable elf32-m68k object. Which is expected.

Take a look :

$ human68k-objdump -tr test.o

test.o:     file format elf32-m68k

SYMBOL TABLE:
00000000 l    d  .text 00000000 .text
00000000 l    d  .data 00000000 .data
00000000 l    d  .bss 00000000 .bss
00000000 g       .text 00000000 main
00000000 g       .data 00000000 hello


RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
00000006 R_68K_32          hello



See ? There is a relocation inside your text section, at offset 0x00000006 and does point to the symbol "hello" which is in the data section.
This is because at this stage, the object have absolutly no clues about the futur size and loading address for the text and data sections. Chances are they will grow up. And only the LINKER will know them !

That's said, while your code is (almost) good, you are missing some things if you want to go into pure assembler with Human68k. A startup code in fact (crt0) and a linker script. Both are provided within the toolchain and are directly used by gcc at link time.

So, just use GCC instead of AS :

# human68k-gcc test.S -o test.elf

This way you will get a working executable.
Note : use .S extension with assembler sources. GCC does not know about .asm, and will complain about the file format.


One last thing, take it as an advice : avoid using iocscall functions if a superset is available as doscalls.

So :

.global main
.global hello

.text

main:
   move.l  hello, %sp@-
   .word   0xff09 | _DOS_PRINT

   clr.w   %sp@-
   .word   0xff4c    | _DOS_EXIT2

.data

hello:
   .asciz   "Hello World!"

.end

Might be better, because IOCS_B_PRINT does not necessary know the current cursor location, while DOS_PRINT does. Iocscalls are more suitable to SRAM based programs.


Have fun ! :)

AnimaInCorpore

Hello lydux,

thanks a lot for the help and suggestions.

For my dirty source I have just taken two snippets from a disassembled program to see if the reassembling would work so this was no real "programming" attempt.

Finally using GCC works perfect and the resulting output can be executed after being converted to the xfile format.

I suppose that you have some experience in programming for the X68000? Have you been a developer on the X68000? I was active in the Atari ST scene many years ago and have written some demos for it.

Cheers
Sascha

lydux

Quote from: AnimaInCorpore on September 07, 2012, 07:27:36 AM
I suppose that you have some experience in programming for the X68000? Have you been a developer on the X68000?
Not at all ! I'm just an hobbyist with knowledges into various domains, and (very) interested into this machine. I study it since about 2 years now. What I have done for the x68000 is an application of what I've learned here and there.
It still remains many things I don't know yet !

Quote from: AnimaInCorpore on September 07, 2012, 07:27:36 AM
I was active in the Atari ST scene many years ago and have written some demos for it.
I don't know the ST very well on software side (more about the hardware), but I'm pretty sure development is simplier on x68000 because of more supportive devices and many more or less powerfull syscalls provided by the bios (iocscalls) that simplify a lot the development process. We really would like to see homebrew applications here you know ! ;) At least, something that could be more interesting than an "hello world".

Quote from: AnimaInCorpore on September 07, 2012, 07:27:36 AM
For my dirty source I have just taken two snippets from a disassembled program to see if the reassembling would work so this was no real "programming" attempt.
It's not that "dirty", it totally reflects how it could be simple to get into x68000 programming ! With 4 lines of simple asm code, you initiate an executable, print an "hello world" string on screen, and exit to the OS shell properly.
And what I've modified in your code is just an advice, not necessary the way to go. As is, it will work as it should.


Anyway, if you want to go further, a must have for development is the punigrammer manual. The lastest known one is the 5.1 :
http://nfggames.com/X68000/Mirrors/x68pub/x68tools/PROGRAM/ETC/PUNI5_1.ZIP
Files are in japanese (encoded as Shift-JIS) but easy to understand using a translator. The archive contains almost all that have to be known about the x68000. Especially those "iocscall.txt" and "doscall.txt" files.

"Inside X68000" is also a good litterature :
http://nfggames.com/X68000/Pic/Inside%20X68000/
Unfortunatly as JPG scan. So translation is a bit difficult. I use an OCR scanner to get the text, this gives me good results.

Have Fun !

lydux

#9
Finally !
Here is the tutorial for using the toolchain for Windows users.

Setup for Windows

1 - Download the necessary packages

Download the lastest Windows binary version of Code::Blocks from official website : http://www.codeblocks.org

Download the cross-Human68K toolchain packages for Windows :
Binutils-2.22 : http://nfggames.com/X68000/Development/toolchain/binutils-2.21-human68k-win32-2.zip
Gcc-4.6.2 : http://nfggames.com/X68000/Development/toolchain/gcc-4.6.2-human68k-win32-1.zip
Newlib-1.4.0 : http://nfggames.com/X68000/Development/libraries/newlib-1.19.0-human68k-1.zip
Make-3.82 : http://nfggames.com/X68000/Development/toolchain/make-3.82.zip

Download the Human68K Wizard for Code::Blocks : http://nfggames.com/X68000/Development/toolchain/codeblocks-wizard-human68k-1.zip

2 - Installing the toolchain :
Just extract all toolchain packages into a directory of your choice. (Ex : C:\X68000\DEV)

3 - Installing and configuring Code::Blocks :

Install Code::Blocks like any other application and start it.

Go to "Settings->Compiler and debugger" menu.
Make a copy of the "GNU GCC Compile" (should be selected by default) by clicking on the "Copy" button. Name this new compiler "Human68K GCC".

Now go into the "Toolchain executables" tab, and change all values by these one :


Note : The debugger is not available yet, I have to figure out how to to use it for remote debugging a real x68000 or an emulator.

Of course, change the "Compiler's installation directory" by the one you have choosen.

Now, extract the "Human68k Wizard for Code::Blocks" archive into the directory "share\CodeBlocks\templates\wizard" of your Code::Blocks installation directory (by default, it should be "C:\Program Files\CodeBlocks")
Stay in this wizard directory and edit the file "config.script" (using windows notepad is ok).
Search for these lines :

    RegisterWizard(wizProject,     _T("arm"),          _T("ARM Project"),           _T("Embedded Systems"));
    RegisterWizard(wizProject,     _T("avr"),          _T("AVR Project"),           _T("Embedded Systems"));
    RegisterWizard(wizProject,     _T("tricore"),      _T("TriCore Project"),       _T("Embedded Systems"));
    RegisterWizard(wizProject,     _T("ppc"),          _T("PowerPC Project"),       _T("Embedded Systems"));


and add this one after :


    RegisterWizard(wizProject,     _T("human68k"),      _T("Human68K Project"),      _T("Embedded Systems"));




Restart Code::Blocks, this is now a template "Human68K Project" with a familiar icon when you create a new project.


It will create a simple "hello world" application, you can try building it in order to check that your toolchain is correctly working.

You can also create a new library for Human68K by choosing "Static Library" instead of "Human68K Project".

Happy coding ! :)

caius

This is a great day for the X68K.Thanks you, master Lydux!

eidis

Master Lydux, this is out of this world ! Keep up the good work !

Eidis
X68000 personal computer is called, "X68K" or "no good good" is called, is the PC that are loved by many people today.

AnimaInCorpore

Quote from: lydux on September 09, 2012, 09:10:10 AM
Anyway, if you want to go further, a must have for development is the punigrammer manual. The lastest known one is the 5.1 :
[...]
"Inside X68000" is also a good litterature :
[...]

Thanks for the links to the documentation. I am not sure if the first is much different from the one I have found so far here:

http://datacrystal.romhacking.net/wiki/Sharp_X68000

So unfortunately it seems that there's no official english documentation. :(

Anyway, thanks for your effort and advice.

Cheers
Sascha

neko68k

#13
I also very highly recommend Inside X68000, it's the best resource available in any language.
Also check this. http://daifukkat.su/wiki/index.php/X68000

There is also source available for many old things here http://nfggames.com/X68000/Mirrors/x68pub/ Most(some, many, all? I'm not really sure...) will not build in the new toolchain without some work.

AnimaInCorpore

FYI: thanks to the Human68k toolchain the following project has become a reality:

The X68000 games porting experiment

Cheers
Sascha

caius

#15
Quote from: AnimaInCorpore on November 12, 2012, 04:12:52 AM
FYI: thanks to the Human68k toolchain the following project has become a reality:

The X68000 games porting experiment

Cheers
Sascha
Impressive work, congratulations!And what about porting games to X68000 instead?Obviously I mean arcade games which use 68000 CPU

P.S.
I'm wondering if this software can be useful to make also some porting to Amiga:

http://aminet.net/search?query=x68000

AnimaInCorpore

Quote from: caius on November 12, 2012, 08:43:57 AMImpressive work, congratulations!And what about porting games to X68000 instead?Obviously I mean arcade games which use 68000 CPU

P.S.
I'm wondering if this software can be useful to make also some porting to Amiga:

http://aminet.net/search?query=x68000

Thanks.

In fact, I was already thinking about porting from/to every M68000 system (like Atari ST, Amiga, X68000, Sega Saturn, NeoGeo, Arcade). Due to the fact that I have an Atari Falcon the current porting experiment goes this way first. Also I was in doubt that it will work anyway but luckily it does. ;)

Cheers
Sascha

lydux

Nice job Anima !

I would like to know more. Any plan on release some source code of your tools ?

I guess you have written for Mint a human68k/iocs emulation layer for some syscalls and graphics chips, and if I understand correctly a human68k decompiler ?

It reminds me that I may have somewhere a patch for the x68k toolchain that add a new processor called "human68k" which add those bastards syscalls instructions using the lineF exception. So when disassembling an XFile, it will show "dos_#####" instead of ".short 0xff##". Interested ?

trap15

#18
Hey lydux!
neko and I just ran into a problem while working on some code. Whenever I use .set, it seems that the symbol it creates isn't marked as "absolute", so when Human68k dynamically links it, it relocates the symbol even though it''s not supposed to. Example:

.set OBJTYPE_COUNT, 2

LEA.L (objinit_lut), A0
MOVE.L #OBJTYPE_COUNT-1, D0
1:
MOVEA.L (A0), A1
JSR (A1)
ADDQ.L #4, A0
DBRA D0, 1b


Instead of loading 1 into D0, it'll load VMA + 1 (which in a lot of cases is like $5F801), which is obviously completely wrong.

I tried messing around with the source in the BFD folder, but I have no idea how BFD really works, so I was unable to fix the problem. Any help would be appreciated!

EDIT: Also, if anyone wants me to add more documentation to the daifukkat.su wiki, let me know. I translate things as I need them and add them there, but if there's any information anyone wants, I can do them anyways.

lydux

Hello Trap15 !

Well, I have tried to reproduce your problem but was unable to.

Here is the asm code I used, based on your, GAS style :


.extern objinit_lut
.set OBJTYPE_COUNT, 2

lea.l objinit_lut, %a0
move.l #OBJTYPE_COUNT-1, %d0
1:
movea.l %a0@, %a1
jsr %a1@
addq.l #4, %a0
dbra %d0, 1b


Correct ?


$ human68k-as test.S -o test.o
$ human68k-objdump -t test.o

test.o:     file format elf32-m68k
test.o
architecture: m68k, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
private flags = 0:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000012  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  00000000  00000000  00000048  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  00000048  2**2
                  ALLOC
SYMBOL TABLE:
00000000 l    d  .text 00000000 .text
00000000 l    d  .data 00000000 .data
00000000 l    d  .bss 00000000 .bss
00000002 l       *ABS* 00000000 OBJTYPE_COUNT
00000000         *UND* 00000000 objinit_lut


RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
00000002 R_68K_32          objinit_lut


The OBJTYPE_COUNT symbol is effectivelly marked as absolute, and no relocation against it, as expected.
At this time, nothing is used related to the xfile backend.

Now, convert to xfile (it will use bfd)

$ human68k-objcopy -O xfile test.o test.X
$ human68k-objdump -x test.X

test.X:     file format xfile
test.X
architecture: m68k, flags 0x00000003:
HAS_RELOC, EXEC_P
start address 0x00000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000012  00000000  00000000  00000040  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
SYMBOL TABLE:
no symbols


RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
00000002 R_68K_32          .text

$ human68k-objdump -D test.X

test.X:     file format xfile


Disassembly of section .text:

00000000 <.text>:
   0: 41f9 0000 0000 lea 0x0,%a0
   6: 7001            moveq #1,%d0
   8: 2250            moveal %a0@,%a1
   a: 4e91            jsr %a1@
   c: 5888            addql #4,%a0
   e: 51c8 fff8      dbf %d0,0x8


Off topic : there is a bug here. I shouldn't be able to do this, as test.o is not marked as executable, objcopy shouldn't allow converting it to xfile.

Only one relocation in .text section at offset 2 which should normally be the external symbol "objinit_lut". And the "move.l #OBJTYPE_COUNT-1, %d0" remains a 16 bits opcodes, so no relocation possible.


I have missed something ?

trap15

Hm that's interesting. It seems like it only causes the bug if the .set is in another file and it's marked .global maybe?
So try doing two source files:

.global OBJTYPE_COUNT
.set OBJTYPE_COUNT, 2



LEA.L (objinit_lut), A0
MOVE.L #OBJTYPE_COUNT-1, D0
1:
MOVEA.L (A0), A1
JSR (A1)
ADDQ.L #4, A0
DBRA D0, 1b


Link them together into an elf, then copy that to an xfile. I think that'll manifest the bug?

lydux

Hum well... That's different !



test:     file format elf32-m68k
test
architecture: m68k, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
private flags = 0:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000018  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  00000018  00000018  0000004c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000018  00000018  0000004c  2**2
                  ALLOC
SYMBOL TABLE:
00000000 l    d  .text 00000000 .text
00000018 l    d  .data 00000000 .data
00000018 l    d  .bss 00000000 .bss
00000000         *UND* 00000000 objinit_lut
00000002 g       *ABS* 00000000 OBJTYPE_COUNT


RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
00000008 R_68K_32          OBJTYPE_COUNT+0xffffffff
00000002 R_68K_32          objinit_lut



test:     file format elf32-m68k


Disassembly of section .text:

00000000 <.text>:
   0: 41f9 0000 0000 lea 0 <.text>,%a0
   6: 203c 0000 0000 movel #0,%d0
   c: 2250            moveal %a0@,%a1
   e: 4e91            jsr %a1@
  10: 5888            addql #4,%a0
  12: 51c8 fff8      dbf %d0,c <.text+0xc>
...


The output is correct. This is the use of this symbol which seems wrong to me here !

I feel a misunderstand about the purpose of a symbol.

At compile time, it does not know nothing about OBJTYPE_COUNT and will mark it as an undefined symbol, assuming this refer to something available later at linking time. So, the assembler have no other choice than creating a 32 bits relocation here.

Now, the purpose of the .set directive is to create an arbitrary symbol, and assign a value to it. By definition, a symbol is an information used by linkers and debuggers to reference something within the address space. At runtime, a symbol means nothing, as it have no allocated space, its own address is just 0 !

So, by using an immediate addressing to OBJTYPE_COUNT, you will get 0 and keep the relocation at linking time.

I think what you want is the value of the symbol :

LEA.L (objinit_lut), A0
MOVE.L OBJTYPE_COUNT-1, D0
1:
MOVEA.L (A0), A1
JSR (A1)
ADDQ.L #4, A0
DBRA D0, 1b



Obvious he ? :)

trap15

Nope, that doesn't work because then it tries to read a long from VMA+1, which not only is also incorrect, but causes an address error.

The issue is that the relocation should be marked as "absolute", so when Human68k tries to load it, it doesn't try to relocate it. Going from the xfile.c source in bfd/, I'm guessing you need to add support for the absolute section, or something along those lines.

lydux

#23
Edit : Urgh.... I have written a large message here, but I've probably said shit ! You're probably right, there maybe a bug with relocations to an absolute symbols. Forgive me, let me some times to check carefully.

lydux

For those who wants to go with pure assembler code with this toolchain, here is a simple skeletton of code you can start to work with.
It contains a minimal startup code that will initialize the program environment and a ready to use Makefile that will compile all assembler files, and create the final XFile.
Also, it does not use the libc at all, so you are on your own.

All you have to do is to modify the user source code (main.S), and 2 top lines of the Makefile to your needs.
Then, go to this directory and type "make".

Note to Windows users : This should work for you as well, you just have to add the directory which contains binaries of the toolchain in your environment variable "PATH".


Links : http://nfggames.com/X68000/Development/samples/x68k-asm-skel.zip

Happy coding !

caius

Thank you as always, Master, au revoir!

lydux

#26
To trap15 and neko68k : you got me guys ! :)

I finally understand your problem. The fact is that ld when resolving all symbols on final link, will rewrite the content needed by a relocation with the address of the value it point to. But in your case, you're using an arbitrary defined and external symbol, later marked absolute, like a constant, not an address like a normal symbol should be.
I were wondering is this is legal... Of course it could be, why not ? I personnally never do this, because the toolchain provides a preprocessor, which is much more powerfull in this way.

But because the symbol were totally resolved, I saw no point why ld continue to emit this relocation !
I finally went to binutils mailing list, and found a thread with a similar issue. (with a shared library on an x86)
According to binutils developper, this is not really wanted, but as they said an "historical mistake". Such behavior is sometimes needed.


So yes, something is wrong here. Here is the fix :
https://github.com/Lydux/binutils-2.22-human68k/commit/2dabd9fa7bab0abaa9e5502087ad48efec9c6678


I guess I have to thanks you, and hope it will work now.

trap15

Hee hee, I do seem to have a habit of breaking things ;)

That patch works perfect, no problem now.

I preferred to not use the preprocessor because then I'd have to #include files, and it's a lot more friendly to just make everything global symbols that don't require any dependencies.

kamiboy

For the windows setup what distribution of GCC do you have installed? You need one to get the include header files like "stdio.h", right?

I went with MinGW.

Right now when I try to build I get a long string of warnings if stdio.h is included and used. If I remove that and try to build basically an empty main{} program I get the following error and no object file:


-------------- Clean: default in FDR68K (compiler: Human68K GCC)---------------

Cleaned "FDR68K - default"

-------------- Build: default in FDR68K (compiler: Human68K GCC)---------------

human68k-gcc.exe  -g     -c E:\X68K\DEV\projects\FDR68K\main.c -o .objs\main.o
as: unrecognized option `-m68000'
Process terminated with status 1 (0 minutes, 22 seconds)
0 errors, 0 warnings (0 minutes, 22 seconds)


lydux

All windows binaries packages have been cross-compiled from my linux workstation using a personnal toolchain relying on mingw32 C runtimes.
I'm not very familiar with windows, but I guess if you wish to use this toolchain under mingw, you will have to use msys and compile each packages like you will do under linux (see first post of this thread).

Quote
For the windows setup what distribution of GCC do you have installed? You need one to get the include header files like "stdio.h", right?
Those headers are part of the C library (newlib in our case). GCC does not provide headers (or very few, which are used internally).

Quote
human68k-gcc.exe  -g     -c E:\X68K\DEV\projects\FDR68K\main.c -o .objs\main.o
as: unrecognized option `-m68000'
Process terminated with status 1 (0 minutes, 22 seconds)
0 errors, 0 warnings (0 minutes, 22 seconds)
Something is wrong here... human68k-gcc try to use the host AS (i386) as assembler ! That's why you get an "unrecognized option `-m68000'" error.You should see "human68k-as" instead here.


What have you done exactly ?

kamiboy

What I did was I dowloaded all the windows packages that you linked to. Dumped them all in a folder, then followed your guide to setup Code::Blocks.

Finally I created a new x68k project and tried to compile. At first I got error messages regarding stdio.h missing, so I figured that is because my include folder being empty since I had no proper GCC distribution installed.

So I downloaded mingw and installed it to the same folder so as to populate the include folder. I then added the include folder to the list of project search folders and tried to recompile.

I got a bunch of warnings about the contents of stdio.h this time and still no binary. So I opted to remove stdio.h and printf from main.c and tried to recompile and I got the message that you saw.

I suppose I could just move the contents of your setup code to an emulator and just use the C compiler for Human68K.

All this linux setup stuff goes way, way above my head. I am used to more userfriendly compilers that do everything for you like VC and Xcode.

lydux

Quote
All this linux setup stuff goes way, way above my head. I am used to more userfriendly compilers that do everything for you like VC and Xcode.
I'm aware of this, that's why I've created a mostly ready-to-go windows toolchain.


Ok. First of all, you normally do not need to change anything within the toolchain. Just extract all packages into a single directory and that's all.
Your problem is a path issue : the c compiler (gcc) does not use the correct assembler (as) not even the correct post-processor (cc1, the one that will deal with headers files).

So, make sure :
- All packages are unzipped into the same directory (without subdirectories).
- Your "Human68K GCC" compiler settings in Code::Blocks point to the correct directory.
- Your Windows environment variable "PATH" does not contains a directory that point to another toolchain. To check for this, just open a command prompt, and type "as -v". It should not find anything.

kamiboy

#32
Okay, the main issue seemed to have been that a few important lib and include header items were unzipped in the human68k folder.

I am not sure whether you did this on intention or not but I moved them to the project folder.

I am talking about the contents of newlib-1.19.0-human68k-1.zip and binutils-2.21-human68k-win32-3.zip

Once I did that and added the "lib" and "include" folders to the "Human68K GCC" compiler the build process got a bit further. But then ld would complain about not finding crt0.o.

No idea why that is. Perhaps it is due to my moving the aforementioned items. Anyway I awkwardly solved that issue by copying crt0.o around into different folder until the build process completed. In the end it had to be present in my project root folder.

Now that I can build a valid "Hello world" program I can finally start to look at some more advanced stuff.

Are there any good sample codes for how to place DOS and IOCS calls in C?

lydux

Quote
Okay, the main issue seemed to have been that a few important lib and include header items were unzipped in the human68k folder.

I am not sure whether you did this on intention or not but I moved them to the project folder.
That's normal and not my decision. The idea behind this is to let you use multiple c runtimes/libraries for differents target but sharing the same processor, so using the same compiler.

Quote
Once I did that and added the "lib" and "include" folders to the "Human68K GCC" compiler the build process got a bit further. But then ld would complain about not finding crt0.o.

No idea why that is. Perhaps it is due to my moving the aforementioned items. Anyway I awkwardly solved that issue by copying crt0.o around into different folder until the build process completed. In the end it had to be present in my project root folder.

Now that I can build a valid "Hello world" program I can finally start to look at some more advanced stuff.

Again, it's highly probable that your c compiler use a wrong preprocessor ! Compiling a simple "hello world" might work actually, but you will get troubles for more advanced sources (like operations that involve cpu endianness, or specific target definition : "#ifdef HUMAN68K") .

Quote
Are there any good sample codes for how to place DOS and IOCS calls in C?
Unfortunatly not really... I lack of time for trully testing the newlib port and provide samples as I personnally not use Human68K very often.
But anything you can provide this way is highly welcome ! (bugs, demos, documentations, ...)

All I can tell you actually is to check headers files "iocs.h" and "dos.h" which contains all prototypes you need and look for the corresponding description in japanese inside the punigrammer manual (iocscall.txt and doscall.txt)

As a sample, here is a quick simple ROM dumper that will use 3 doscalls  :

/*
* Simple bios dumper for Human68K
*
* Various ROM locations in address space :
* CGROM : 0xf00000 --> 0xfbffff  (768KB)
* Internal SCSI ROM (X68000 only) : 0xfc0000 --> 0xfdffff (128KB)
* IPLROM :
*  X68000 : 0xfe0000 --> 0xffffff (128KB)
*  X68030 : 0xfc0000 --> 0xffffff (256KB)
*/

#include <stdio.h>
#include <dos.h>

#define IPLADR  ((const char *) 0xFE0000)
#define IPLSIZE (128 * 1024)

int main (int argc, char **argv)
{
  const char *filename;
  int fd;

  printf ("Simple X68000 IPLROM dumper by Lydux\n");

  if (argc != 2)
  {
    printf ("Usage : %s output_file\n", argv[0]);
    return -1;
  }

  filename = (const char *) argv[1];

  /* Create a newer empty file */
  fd = _dos_create (filename, 0);   /* Normal mode (erase if existing) */
  if (fd < 0)
  {
    printf ("Error while creating file \"%s\" !\n", filename);
    return -1;
  }
  /* Write to the file */
  _dos_write (fd, IPLADR, IPLSIZE);
  /* Close handle */
  _dos_close (fd);

  printf ("Done !\n");

  return 0;
}

kamiboy

Okay, that seems pretty straight forward.

I have begun to identify the IOCS calls that are relevant to my purpose. Trouble is all I have to go on is this: http://datacrystal.romhacking.net/wiki/X68k:IOCS

The above is fine if you plan on doing assembly coding but quickly become inadequate when trying to place the same calls through C. There should be some sort of resource that documents the input/output parameters of the C IOCS function calls.

Does not matter whether it is in English or Japanese, as long as I can dump the text into a translator.

If that is not possible then could someone explain to me whether I understand the following correctly.

If I understand correctly d1 and d2 are both registers often used for passing/receiving DOS/IOCS function call parameters.

Now, in the doc I often see things like d1.hb and d1.b. Does that refer to the high and low byte area of said register (assuming that it is a 16 bit register of course)

neko68k

The Sharp C books will have what you are looking for. There are other books with similar overviews. They're pretty common on y!j. Otherwise, just realize that you're doing the asm anyway, just called through a func that inlined the asm. Realistically if you need any kind of performance at all you should be writing asm anyway ;D

kamiboy

Yeah, I figured all the IOCS and DOS function calls did were to pass their parameters into the right registers, but it seemed that the two first parameters in that particular case were being packed into the same resister.

Anywaste, after a bit of experimentation I figured it out. The "hb" part just needed to be shifted up << 8 bits and ored together with the "b" part. Pretty much as I figured it would be.

As for assembly, no thank you. As much as I enjoy programming for old school systems assembly is where I draw the line.

I have no experience at all with 68000 assembly, but once long, long ago I wrote a simple breakout game prototype in x86 assembly, that is it as far my assembly experience goes.

Takes too damn long to even do the simplest stuff in assembly. I am lazy, hard to motivate and the rare supply of enthusiasm that I can muster burns out fast. Sticking to C means I can at least get to finish a program with a level of complexity a notch or two above "Hello World".

For tools and such it is not necessary to do anything but C anyway. Hell, you might even get away with going the Basic route. For game projects on the other hand, well, I can certainly see the argument for coding some inner loops in assembly. But I think you could still get away with keeping most of the project coded in C.

neko68k

Do what makes you happy I guess :) FWIW I've seen very little C at all in the wild. Even the simplest tools were written in asm. Remember, you've only got 10mhz and maybe 2MB of ram to work with :)

kamiboy

#38
Questions, questions.

Master lydux, your arcane knowledge is needed.

First an inquiry regarding accessing memory in old fashioned C.

Is is possible to use regular old C pointers to access areas of interest in the X68000 memory at whim?

Say, for an example, that I wanted to mess around with the Sprite Data memory area, which is located at 0xEB0000.

Could I just:

unsigned char *sp = 0xEB0000;

then start reading and writing ala:

sp[0] = 0x01; //etc. etc.?

It would seem that I cannot do as such as I get bus errors when I try. Any way to do that correctly other than using appropriate IOCS function calls to manipulate the Sprite Data bits in memory in addition to other areas of interest?

I ask because using IOCS function calls is slow as opposed to just raw access.

In any regard, I've noticed an discrepancy between the IOCS call _iocs_sp_regst in the cross-chain and the definition of said function as found here: http://daifukkat.su/wiki/index.php/X68000/IOCS/SP_REGST

In the cross-chain that function has 6 input parameters whereas that website only claims there to be 5. Calling the function with different parameters and keeping an eye on how they change X68000 memory I've come to the conclusion that in the cross-chain the second parameters seems to be doing naught.

It is thus I find:

_iocs_sp_regst(spriteID, ?, x, y, info, priority)

Where does this discrepancy come from? Is that website's definition of IOCS C function calls obsolete or what? Are there any sources up to date with the calls in the cross-chain?

kamiboy

#39
More questions.

Say for a simple game, how does the render cycle look like?

I am currently trying to get a single sprite to show up on screen and have had no luck.

I assume one first changes the video mode, then calls the init sprite function call and sets sprites to ON so they are visible.

Then one uploads the sprite graphic data to PCG, and updates the sprite register so there is a sprite with the desired location whose data references the graphic in PCG.

I've gotten that far, but I have nothing on the screen so there must be more to it?

Does one have to call a certain function to have the system rasterize sprites?

How does one wait for vertical retrace and all that jazz by the way. There are way too many unknowns and reading through IOCS calls I do not seem to be able to find that I am looking for.