Page 1 of 3

xa and o65 format (and CC65)

Posted: Wed Apr 12, 2017 11:04 am
by jede
Hello,

I am trying to link xa source file with cc65 linker. I was thinking that the best way was to use o65 in order to link with others .o from cc65.

Anyway, o65 format from XA is not recognized by cc65 . A Fachat explains at this page (http://6502.org/users/andre/o65/) that cc65 don't use o65 as an object file : We can't import o65 format into cc65 tools

Except converting xa source into ca65, is there a way to link or a trick to link xa65 source or o65 to cc65 ?

http://www.cc65.org/doc/co65-2.html could load o65 to convert it into ca65 assembly file, but o65 format from xa is not recognized.

Re: xa and o65 format (and CC65)

Posted: Wed Apr 12, 2017 2:36 pm
by christian
Hello,

So you want to convert a file from o65 to xo65 and use it with cc65/cl65, right?

Maybe you can try with co65 which can do some conversion, but you have to modify the byte at offset 7 from $10 to $08 in the object file created by xa for co65 to recognize the file (it's the mode type)
co65 create an assembler source file so you can re-assemble it with ca65 (it is basically some kind of dump file).

Example:
xa source code (dummy code):

Code: Select all

;.fopt 0, "testco65.a65"
;.fopt 1,3                                ; os code (1 = OS/A65, 2 = Lunix, 3 = cc65 module, other/default = unknown)
;.fopt 2, "xa"

.text
test:
	lda #$02
	jsr test2
	sty work
	rts

test2:
	ldy #$02
	lda table,y
	rts

.data
table:
.word $12,$13

.bss
work:
.dsb 10,0
assembly with command xa -v -c -R testco65.a65, then modify the byte at offset 7 of the resulting object file a.o65 with vi (or some binary file editor):

Code: Select all

modify this byte---------------\/
00000000  01 00 6f 36 35 00 00 10  00 b0 0f 00 00 04 04 00  |..o65...........|
00000010  00 40 0a 00 04 00 00 00  00 00 00 a9 02 20 09 b0  |.@........... ..|
finally convert with command co65 a.o65

resulting file a.s (default name: base name of the input file and .s extension)

Code: Select all

;
; File generated by co65 v 2.15 - Git 6878ede using model `none'
;
.fopt		compiler,"co65 v 2.15 - Git 6878ede"
.case		on
.debuginfo	off

test = CODE+0
.export	test
test2 = CODE+9
.export	test2
work = BSS+0
.export	work
table = DATA+0
.export	table

;
; CODE SEGMENT
;
.segment	"CODE"
CODE:
	.byte	$A9
	.byte	$02
	.byte	$20
	.word	CODE+9
	.byte	$8C
	.word	BSS+0
	.byte	$60
	.byte	$A0
	.byte	$02
	.byte	$B9
	.word	DATA+0
	.byte	$60

;
; DATA SEGMENT
;
.segment	"DATA"
DATA:
	.byte	$12
	.byte	$00
	.byte	$13
	.byte	$00

;
; BSS SEGMENT
;
.segment	"BSS"
BSS:
	.res	10

;
; ZEROPAGE SEGMENT
;
.segment	"ZEROPAGE": zeropage
ZEROPAGE:
	.res	0

.end
The only noticeable effect of the os code is with .fopt 1,3, in this case the zero page segment is:

Code: Select all

;
; ZEROPAGE SEGMENT
;
.import	__ZP_START__		; Linker generated symbol
ZEROPAGE = __ZP_START__

With some of my o65 files, co65 stop with error "Cannot handle this segment reference in reloc entry" but I don't know why...

Hope, this can help you

Re: xa and o65 format (and CC65)

Posted: Wed Apr 12, 2017 6:46 pm
by iss
WOW, this is good, Thanks christian! This will simplify my cc65 based toolchain.
Now I'm using a script file to convert XA syntax to CA65 compatible source.
It works but not all possible cases are handled properly.

Re: xa and o65 format (and CC65)

Posted: Wed Apr 12, 2017 8:12 pm
by Dbug
Maybe it would make sense to investigate in the XA source code if we can change the mode to make it compatible without any manual patching :) ?

Re: xa and o65 format (and CC65)

Posted: Wed Apr 12, 2017 8:53 pm
by christian
In co65 source file o65.h is

Code: Select all

/* The mode word as generated by the ld65 linker */
#define O65_MODE_CC65           (O65_CPU_6502    |      \
                                 O65_RELOC_BYTE  |      \
                                 O65_SIZE_16BIT  |      \
                                 O65_FTYPE_EXE   |      \
                                 O65_ADDR_SIMPLE |      \
                                 O65_ALIGN_1)

which is 0x0800 (in fact the value of O65_ADDR_SIMPLE as all flags are 0x0000)

xa defines mode as:

Code: Select all

	mode.15 :	CPU	0= 6502 	1= 65816 
	mode.14	:	reloc	0= bytewise... 	1= page(256byte)wise relocation
						   allowed
	mode.13	:	size	0= size=16 bit,	1= size=32 bit
	mode.12 :	obj	0= executable	1= object file
	mode.11 :	simple	0= (ignored)	1= simple file addresses
	mode.10 :	chain	0= (ignored)	1= another file follows this one
	mode.9  :	bsszero 0= (ignored)	1= the bss segment must be zeroed out for this file

	mode.4-7 :	CPU2	0000 = 6502 core (no undocumented opcodes)
				0001 = 65C02 /w some bugfix, no illegal opcodes
				0010 = 65SC02 (enhanced 65C02), some new opcodes
				0011 = 65CE02 some 16bit ops/branches, Z register is modifiable
				0100 = NMOS 6502 (including undocumented opcodes)
				0101 = 65816 in 6502 emulation mode
				011x = reserved
				1xxx = reserved
				^^^^ 
				|||+- Bit 4
				||+-- Bit 5
				|+--- Bit 6
				+---- Bit 7

	mode.0-1:	align	0= byte align,	
				1= word (i.e. 2 byte) align
				2= long (4 byte) align
				3= block (256 byte) align
The xa documentation says
The simple bit signals the loader that the load addresses have a specific form. This form fulfills the following conditions:

dbase = tbase + tlen
bbase = dbase + dlen
I don't know how to tell xa to set the bit11 without modifying xa.

Re: xa and o65 format (and CC65)

Posted: Thu Apr 13, 2017 8:08 am
by jede
Thank a lot for the trick i will have a look :)

I think it should be better to correct XA :)

Re: xa and o65 format (and CC65)

Posted: Thu Apr 13, 2017 8:27 am
by Dbug
I added an issue on the OSDK page for that: http://osdk.org/index.php?page=issues

Re: xa and o65 format (and CC65)

Posted: Thu Apr 13, 2017 10:56 am
by Dbug
So, I looked at the code in XA, and in xar.cpp we have that:

Code: Select all

// Write header for relocatable output format
int FileData::WriteRelocatableHeader(FILE *fp,int mode,int tlen,int dlen,int blen,int zlen,int stack) 
{
	m_len[eSEGMENT_TEXT] = tlen;
	m_len[eSEGMENT_DATA] = dlen;
	m_len[eSEGMENT_BSS ] = blen;
	m_len[eSEGMENT_ZERO] = zlen;

	fputc(1, fp);							// version byte 
	fputc(0, fp);							// hi address 0 -> no C64 
	fputc('o', fp);
	fputc('6', fp);
	fputc('5', fp);
	fputc(0, fp);							// format version 
	fputw(mode, fp);						// file mode 
	fputw(m_base[eSEGMENT_TEXT],fp);		// text base 
	fputw(tlen,fp);							// text length 
	fputw(m_base[eSEGMENT_DATA],fp);		// data base 
	fputw(dlen,fp);							// data length 
	fputw(m_base[eSEGMENT_BSS],fp);			// bss base 
	fputw(blen,fp);							// bss length 
	fputw(m_base[eSEGMENT_ZERO],fp);		// zerop base 
	fputw(zlen,fp);							// zerop length 
	fputw(stack,fp);						// needed stack size 

	m_options.o_write(fp);

	return 0;
}
The value we are interested in is the 16bit "mode" variable, which is passed by the caller, xa.cpp:

Code: Select all

	 if (gFlag_n65816>0)
		 fmode |= 0x8000;

	 switch (align)
	 {
	 case 1:
		 break;
	 case 2:
		 fmode |= 1;
		 break;
	 case 4:
		 fmode |= 2;
		 break;
	 case 256:
		 fmode |=3;
		 break;
	 }

	 if ((!er) && relmode)
	 {
		 afile->WriteRelocatableHeader(gOutputFileHandle, fmode,SectionTextLenght,SectionDataLenght,SectionBssLenght,SectionZeroLenght, 0);
	 }
The value exported with the example you gave is 0x1000 and you are suggesting that it should have been 0x0800 (the information is written in little endian, lower part first).

So apparently the difference is in the bits 11 and 12, which respectively mean:
- mode.12 : obj 0= executable 1= object file
- mode.11 : simple 0= (ignored) 1= simple file addresses

The value XA writes comes from this snippet of code:

Code: Select all

#define	  FM_OBJ    0x1000

			case 'c':
				fmode |= FM_OBJ;
				break;
As far as I can see, there's nothing wrong in writing "object file", so maybe the only problem is that the bit 11 is zero instead of "simple file address".
Could you check if writing 0x1800 also works, if that's the case, then I could just change the value of FM_OBJ from 0x1000 to 0x1800 and that should be minimally disruptive :)

Re: xa and o65 format (and CC65)

Posted: Thu Apr 13, 2017 11:21 am
by christian
It will not work, in co65 source code (co65/convert.c)

Code: Select all

    /* For now, we do only accept o65 files generated by the ld65 linker which
    ** have a specific format.
    */
    if (!Debug && D->Header.mode != O65_MODE_CC65) {
        Error ("Cannot convert o65 files of this type");
    }
So Header.mode must be 0x0800

Xa may be modified in 3 ways:
  1. Add a function to check if the conditons are raised (dbase = tbase + tlen
    bbase = dbase + dlen) and set bit11
    May need 2 try to create an object file: 1 to create the object file and check those values with file65, and another to set the right values with options -bd and -bb
  2. Add an option which enforce dbase = tbase + tlen and bbase = dbase + dlen and set bit11
  3. Add an option to set bit11 without any check

Re: xa and o65 format (and CC65)

Posted: Thu Apr 13, 2017 11:39 am
by christian
We can also fork co65, modify 1 line and we get a new tool for xa

Re: xa and o65 format (and CC65)

Posted: Thu Apr 13, 2017 12:08 pm
by Dbug
christian wrote: Thu Apr 13, 2017 11:39 am We can also fork co65, modify 1 line and we get a new tool for xa
What would be the actual benefits of having co65 in the OSDK?

I'm still not quite sure why Jede is mixing XA and CC65, what about you? You seem to know CC65 quite well, are you also doing some mix and match of the two systems?

I'm aiming at having the OSDK be a self-sufficient system, adding things here and there for the occasional person who need interoperability with other systems.

I'm perfectly ok to add a new option, that seems to be the simpler way of doing it, it solves the issue and guarantees we get no compatibility issues with the existing code.

Maybe just extend the existing '-c' with a secondary value, like '-cc'?

Re: xa and o65 format (and CC65)

Posted: Thu Apr 13, 2017 12:20 pm
by iss
IMHO, having option '-cc' is the best solution for everyone!
The change in 'xa.c' is minimal and easy: ;)

Code: Select all

	  case 'c':
		/* fmode |= FM_OBJ; */
		fmode |= ((argv[i][2]=='c')? 0x0800 : FM_OBJ);
		break;

Re: xa and o65 format (and CC65)

Posted: Thu Apr 13, 2017 12:42 pm
by Dbug
Could somebody try this new version?
xa_2.2.5.zip
XA 2.2.5 Added the -cc option, similar to -c, but compatible with CC65 tools
(77.39 KiB) Downloaded 614 times
Use -cc instead of -c

If that works, it will be in the next version of the OSDK sometimes this week.

Re: xa and o65 format (and CC65)

Posted: Thu Apr 13, 2017 1:10 pm
by iss
XA 2.2.5 works for me as expected.

Re: xa and o65 format (and CC65)

Posted: Thu Apr 13, 2017 1:34 pm
by christian
The '-cc' option is probably the best and easiest solution but it should be noticed this does not guarantee that dbase = tbase + tlen and
bbase = dbase + dlen as required by the simple address format (I don't know the impact)

I don't know why Jede need to mix XA and CC65.

@Dbug: I'm used to use XA and I'm now testing CA65 due to the lack of a real macros support with XA.
I'm only using assembly language and personal tools when programming for Oric.