xa and o65 format (and CC65)
xa and o65 format (and CC65)
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.
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)
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):
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):
finally convert with command co65 a.o65
resulting file a.s (default name: base name of the input file and .s extension)
The only noticeable effect of the os code is with .fopt 1,3, in this case the zero page segment is:
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
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
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 |.@........... ..|
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
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)
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.
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)
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)
In co65 source file o65.h is
which is 0x0800 (in fact the value of O65_ADDR_SIMPLE as all flags are 0x0000)
xa defines mode as:
The xa documentation says
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)
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
I don't know how to tell xa to set the bit11 without modifying xa.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
Re: xa and o65 format (and CC65)
Thank a lot for the trick i will have a look 
I think it should be better to correct XA

I think it should be better to correct XA

Re: xa and o65 format (and CC65)
I added an issue on the OSDK page for that: http://osdk.org/index.php?page=issues
Re: xa and o65 format (and CC65)
So, I looked at the code in XA, and in xar.cpp we have that:
The value we are interested in is the 16bit "mode" variable, which is passed by the caller, xa.cpp:
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:
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
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;
}
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);
}
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;
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)
It will not work, in co65 source code (co65/convert.c)
So Header.mode must be 0x0800
Xa may be modified in 3 ways:
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");
}
Xa may be modified in 3 ways:
- 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 - Add an option which enforce dbase = tbase + tlen and bbase = dbase + dlen and set bit11
- Add an option to set bit11 without any check
Re: xa and o65 format (and CC65)
We can also fork co65, modify 1 line and we get a new tool for xa
Re: xa and o65 format (and CC65)
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)
IMHO, having option '-cc' is the best solution for everyone!
The change in 'xa.c' is minimal and easy:
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)
Could somebody try this new version?
If that works, it will be in the next version of the OSDK sometimes this week.
Use -cc instead of -cIf that works, it will be in the next version of the OSDK sometimes this week.
Re: xa and o65 format (and CC65)
XA 2.2.5 works for me as expected.
Re: xa and o65 format (and CC65)
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.
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.