Pengwin Posted July 11, 2007 Share Posted July 11, 2007 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 prototypetripods.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 Quote Link to comment Share on other sites More sharing options...
dwhyte Posted July 11, 2007 Share Posted July 11, 2007 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 prototypetripods.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... Quote Link to comment Share on other sites More sharing options...
Pengwin Posted July 11, 2007 Author Share Posted July 11, 2007 Looks like your include/lib directories aren't in XCode's search path... Sorry, I didn't make myself clear. The compilation results are from command line, not XCode Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted July 11, 2007 Share Posted July 11, 2007 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 Quote Link to comment Share on other sites More sharing options...
Pengwin Posted July 11, 2007 Author Share Posted July 11, 2007 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 Quote Link to comment Share on other sites More sharing options...
Pengwin Posted July 11, 2007 Author Share Posted July 11, 2007 just had a read of Atari.h. I must have competely missed the line that read: #ifdef ATARI_COMPAT_PRE_2_11 DOH! :dunce: Quote Link to comment Share on other sites More sharing options...
Wrathchild Posted July 11, 2007 Share Posted July 11, 2007 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 Quote Link to comment Share on other sites More sharing options...
Pengwin Posted July 11, 2007 Author Share Posted July 11, 2007 (edited) Thanks for the simple explanation Mark 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 July 11, 2007 by Pengwin Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.