Jump to content
IGNORED

CC65 and XCode


Pengwin

Recommended Posts

I'm sure this must have been asked before, but is there a way to integrate CC65 into the XCode environment on MacOSX?

 

Also, when I compile and link the following code, I get an error, which I will quote at the end. Any ideas to the cause? As far as I know, everything appears to be installed correctly.

 

#include <stdlib.h>
#include <string.h>
#include <atari.h>
#include <peekpoke.h>
#include "tripods.h"

void init(void)
{
graphics(8);
POKE(709,1);
POKE(710,191);
}

void startup(void)
{
unsigned char c, d;
unsigned char* s;

cleartext();
ppos=1;
cmp=0;

do
{
	outtext(1,"DO YOU WANT TO CONTINUE YOUR");
	outtext(2,"LAST GAME OR START A NEW ONE?");
	outtext(4,"PRESS S - START A NEW GAME");
	outtext(5,"	  C - RELOAD AN OLD GAME");
	outtext(7,"	  ENTER YOUR CHOICE");
	dispscreen();
	while(!kbhit())
	{
		/* NULL assignment */
	}
} while(1==1);
	
}

void dispscreen(void)
{

}

void outtext(const unsigned char x, const char* s)
{
strcpy(h1[x-1],s);
}

void cleartext(void)
{
unsigned char x;
for(x = 1; x <10; x++)
{
	outtext(x,BLANK);
}
}

int main(void)
{
 init(); 
while(!kbhit())
{
	startup();
}

/* Done */
return EXIT_SUCCESS;
}

 

tripods.c(9): Warning: Function call without a prototype

tripods.c(31): Warning: Function call without a prototype

tripods.c(37): Warning: `c' is defined but never used

tripods.c(37): Warning: `d' is defined but never used

tripods.c(37): Warning: `s' is defined but never used

Unresolved external `_graphics' referenced in:

tripods.s(21)

ld65: Error: 1 unresolved external(s) found - cannot create output file

Link to comment
Share on other sites

I'm sure this must have been asked before, but is there a way to integrate CC65 into the XCode environment on MacOSX?

 

Also, when I compile and link the following code, I get an error, which I will quote at the end. Any ideas to the cause? As far as I know, everything appears to be installed correctly.

 

#include <stdlib.h>
#include <string.h>
#include <atari.h>
#include <peekpoke.h>
#include "tripods.h"

void init(void)
{
graphics(8);
POKE(709,1);
POKE(710,191);
}

void startup(void)
{
unsigned char c, d;
unsigned char* s;

cleartext();
ppos=1;
cmp=0;

do
{
	outtext(1,"DO YOU WANT TO CONTINUE YOUR");
	outtext(2,"LAST GAME OR START A NEW ONE?");
	outtext(4,"PRESS S - START A NEW GAME");
	outtext(5,"	  C - RELOAD AN OLD GAME");
	outtext(7,"	  ENTER YOUR CHOICE");
	dispscreen();
	while(!kbhit())
	{
		/* NULL assignment */
	}
} while(1==1);
	
}

void dispscreen(void)
{

}

void outtext(const unsigned char x, const char* s)
{
strcpy(h1[x-1],s);
}

void cleartext(void)
{
unsigned char x;
for(x = 1; x <10; x++)
{
	outtext(x,BLANK);
}
}

int main(void)
{
 init(); 
while(!kbhit())
{
	startup();
}

/* Done */
return EXIT_SUCCESS;
}

 

tripods.c(9): Warning: Function call without a prototype

tripods.c(31): Warning: Function call without a prototype

tripods.c(37): Warning: `c' is defined but never used

tripods.c(37): Warning: `d' is defined but never used

tripods.c(37): Warning: `s' is defined but never used

Unresolved external `_graphics' referenced in:

tripods.s(21)

ld65: Error: 1 unresolved external(s) found - cannot create output file

 

 

Looks like your include/lib directories aren't in XCode's search path...

Link to comment
Share on other sites

Hi Pengwin,

 

The header file "atari.h" declares the function as _graphics

and has a #define for replacing 'graphics' with '_graphics'

but only when ATARI_COMPAT_PRE_2_11 is defined.

 

Probably best of if you change your call to:

	_graphics(8);

rather than enable the compatability.

 

Regards,

Mark

Link to comment
Share on other sites

Hi Pengwin,

 

The header file "atari.h" declares the function as _graphics

and has a #define for replacing 'graphics' with '_graphics'

but only when ATARI_COMPAT_PRE_2_11 is defined.

 

Probably best of if you change your call to:

	_graphics(8);

rather than enable the compatability.

 

Regards,

Mark

 

Thanks Mark. I'll have a read through the header files and check the statements I need.

 

Another quick question...how does the speed of compiled programs compare to assembly, Action!, Quick, etc

Link to comment
Share on other sites

Nice easy question... not! :)

 

Not having looked into the code produced by the others,

so going on picked up insights posted here and elsewhere

along with my own playing with CC65, I'd say it should

hold up quite well. As you use it more you tend to learn

ways of coding more effectively for the 6502 target.

Let me expand on that.

 

The plain compilation of C source to its intermediate

assembly language file (.s) is not too bad on its own.

This code produced, I imagine, is typically not as efficient

as Action or Quick generated code and so could run

slower due to the overheads of parameter stack usage

which is accessed through indirect addressing.

 

However it is once you start enabling the various optimizer

features that you see what a good job the optimizer does

of whittling down the code to what is closer to what you'd

have written in assembly. Generally you end up learning

the patterns to use to produce more optimal code.

 

What I like to do is take an small program in 'C' first

and then see the effects of tweaking it, e.g.:

 

#include <atari.h>
#include <peekpoke.h>

static char TestFn(register char h, register char l)
{
register char v;
v = h & 0xF0;
v |= l & 0x0F;
POKE(712,v);
return v;
}

void main(void)
{
char x;
x = POKEY_READ.random;
POKE(710,x);
x = TestFn(x,4);
}

 

Compiling this with "cl65 -t atari -S -T test.c" gives us:

 

;
; File generated by cc65 v 2.11.0
;
.fopt		compiler,"cc65 v 2.11.0"
.setcpu		"6502"
.smart		on
.autoimport	on
.case		on
.debuginfo	off
.importzp	sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
.macpack	longbranch
.export		_main

; ---------------------------------------------------------------
; unsigned char __near__ TestFn (unsigned char, unsigned char)
; ---------------------------------------------------------------

.segment	"CODE"

.proc	_TestFn: near

.segment	"CODE"

;
; v = h & 0xF0;
;
jsr	 decsp1
ldy	 #$02
ldx	 #$00
lda	 (sp),y
ldx	 #$00
and	 #$F0
ldy	 #$00
sta	 (sp),y
;
; v |= l & 0x0F;
;
ldy	 #$00
ldx	 #$00
lda	 (sp),y
jsr	 pushax
ldy	 #$03
ldx	 #$00
lda	 (sp),y
ldx	 #$00
and	 #$0F
jsr	 tosorax
ldy	 #$00
sta	 (sp),y
;
; POKE(712,v);
;
ldy	 #$00
ldx	 #$00
lda	 (sp),y
sta	 $02C8
;
; return v;
;
ldy	 #$00
ldx	 #$00
lda	 (sp),y
jmp	 L0002
;
; }
;
L0002:	jsr	 incsp3
rts

.endproc

; ---------------------------------------------------------------
; void __near__ main (void)
; ---------------------------------------------------------------

.segment	"CODE"

.proc	_main: near

.segment	"CODE"

;
; x = POKEY_READ.random;
;
jsr	 decsp1
ldx	 #$00
lda	 $D20A
ldy	 #$00
sta	 (sp),y
;
; POKE(710,x);
;
ldy	 #$00
ldx	 #$00
lda	 (sp),y
sta	 $02C6
;
; x = TestFn(x,4);
;
ldy	 #$00
lda	 (sp),y
jsr	 pusha
lda	 #$04
jsr	 pusha
jsr	 _TestFn
ldy	 #$00
sta	 (sp),y
;
; }
;
jsr	 incsp1
rts

.endproc

 

And compiling it with "cl65 -t atari -S -T -Oi test.c" gives us:

 

;
; File generated by cc65 v 2.11.0
;
.fopt		compiler,"cc65 v 2.11.0"
.setcpu		"6502"
.smart		on
.autoimport	on
.case		on
.debuginfo	off
.importzp	sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
.macpack	longbranch
.export		_main

; ---------------------------------------------------------------
; unsigned char __near__ TestFn (unsigned char, unsigned char)
; ---------------------------------------------------------------

.segment	"CODE"

.proc	_TestFn: near

.segment	"CODE"

;
; v = h & 0xF0;
;
jsr	 decsp1
ldy	 #$02
lda	 (sp),y
and	 #$F0
ldy	 #$00
sta	 (sp),y
;
; v |= l & 0x0F;
;
ldx	 #$00
iny
lda	 (sp),y
and	 #$0F
dey
ora	 (sp),y
sta	 (sp),y
;
; POKE(712,v);
;
sta	 $02C8
;
; return v;
;
lda	 (sp),y
;
; }
;
jmp	 incsp3

.endproc

; ---------------------------------------------------------------
; void __near__ main (void)
; ---------------------------------------------------------------

.segment	"CODE"

.proc	_main: near

.segment	"CODE"

;
; x = POKEY_READ.random;
;
jsr	 decsp1
lda	 $D20A
ldy	 #$00
sta	 (sp),y
;
; POKE(710,x);
;
sta	 $02C6
;
; x = TestFn(x,4);
;
jsr	 decsp2
ldy	 #$02
lda	 (sp),y
dey
sta	 (sp),y
lda	 #$04
dey
sta	 (sp),y
jsr	 _TestFn
ldy	 #$00
sta	 (sp),y
;
; }
;
jmp	 incsp1

.endproc

 

You'll spot the tidy-ups where a register value has not changed

and so it does not need reloaded (e.g. dropped "ldy #0")

 

Finally if we can enable the 'register' keyword to have code

generated to place variables into zeropage. This can have

an advantage of generating quicker runtime code but has

to be balanced against the overheads of saving and restoring

the register bank. E.g. "cl65 -t atari -S -T -Oir test.c" gives us:

 

;
; File generated by cc65 v 2.11.0
;
.fopt		compiler,"cc65 v 2.11.0"
.setcpu		"6502"
.smart		on
.autoimport	on
.case		on
.debuginfo	off
.importzp	sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
.macpack	longbranch
.export		_main

; ---------------------------------------------------------------
; unsigned char __near__ TestFn (register unsigned char, register unsigned char)
; ---------------------------------------------------------------

.segment	"CODE"

.proc	_TestFn: near

.segment	"CODE"

;
; {
;
ldy	 #$01
lda	 (sp),y
ldx	 regbank+5
sta	 regbank+5
txa
sta	 (sp),y
dey
lda	 (sp),y
ldx	 regbank+4
sta	 regbank+4
txa
sta	 (sp),y
;
; register char v;
;
lda	 regbank+3
jsr	 pusha
;
; v = h & 0xF0;
;
lda	 regbank+5
and	 #$F0
sta	 regbank+3
;
; v |= l & 0x0F;
;
ldx	 #$00
lda	 regbank+4
and	 #$0F
ora	 regbank+3
sta	 regbank+3
;
; POKE(712,v);
;
sta	 $02C8
;
; return v;
;
lda	 regbank+3
;
; }
;
pha
ldy	 #$00
lda	 (sp),y
sta	 regbank+3
iny
lda	 (sp),y
sta	 regbank+4
iny
lda	 (sp),y
sta	 regbank+5
pla
jmp	 incsp3

.endproc

; ---------------------------------------------------------------
; void __near__ main (void)
; ---------------------------------------------------------------

.segment	"CODE"

.proc	_main: near

.segment	"CODE"

;
; x = POKEY_READ.random;
;
jsr	 decsp1
lda	 $D20A
ldy	 #$00
sta	 (sp),y
;
; POKE(710,x);
;
sta	 $02C6
;
; x = TestFn(x,4);
;
jsr	 decsp2
ldy	 #$02
lda	 (sp),y
dey
sta	 (sp),y
lda	 #$04
dey
sta	 (sp),y
jsr	 _TestFn
ldy	 #$00
sta	 (sp),y
;
; }
;
jmp	 incsp1

.endproc

 

Try experimenting by dropping the register keywords one

by one to see the effect on the code generated.

 

Regards,

Mark

Link to comment
Share on other sites

Thanks for the simple explanation Mark :D

 

I'll look again tomorrow, after the Merlot has worn off.

 

I think using CC65 will be beneficial to expediting the development process, although it may mean a small compromise in performance.

 

However, as I also develop for the Oric Atmos, CC65 is looking more and more desirable.

Edited by Pengwin
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...