Jump to content
IGNORED

Funkheld KickC questions


Gury

Recommended Posts

19 hours ago, funkheld said:

it's not about games for me, but that kickc and millfork should clarify a few things to me.

You have to remember Kickc is still in development and lacks a number of standard C facilities,

it also strays from the K & R standards by adding extra (different ways of doing things) i.e. for/loops

 

Not saying this is wrong, just different and you need to be aware of this.

 

I believe the author is trying to create a 'C' like language that is highly optimized to create 'near machine code'

which executes very quickly without the usual overheads of a fully fledged 'C' compiler.

 

The compiled code is easy to read unlike the output from cc65

 

Link to comment
Share on other sites

Hi @funkheld!

 

There's 2 mistakes in your code.

1. you're using pragma for atascii codes, which doesn't work here. I think the atascii directive makes strings able to be printed through conio this way, you're using direct values into memory location so I think that's why it's different.

someone may be able to explain that better.

 

2. you're putting the wrong value in SDMCTL.

 

The original source version you took this from used 0x21, which if you lookup in Mapping the Atari (or any other resource on SDMCTL) is "Enable instructions to fetch DMA" (0x20) + "Narrow Playfield" (0x01)

You wanted to add the "enable Player and Missile" bits, which is 0xC (0x04 + 0x08), which makes the final value "0x2D" (45 decimal), but you were using 0x2E (46 decimal) which uses "Standard playfield" - if you want to use standard, that changes the width and thus the output.

 

Here's a fixed version of your code:
 

#pragma target(atarixl)
#pragma zp_reserve(0x00..0x7f)

#include <atari-xl.h>
#include <printf.h>
#include <conio.h>

char * const ramto = 0x6a;
char * const colorpm0 = 704;
char * const colorpm1 = 705;
char * const colorpm2 = 706;
char * const colorpm3 = 707;

const char pmdata[] = { 255,129,129,129,129,129,129,255};

void main() {
  word i, pmgmem, zahl;
  char j, px0 , py0;
  
  *SDMCTL = 45; // 0x2D = 0x21 + PM enable 
  *SDLST = DISPLAY_LIST;
  
  px0 = 100;
  py0 = 70;
  
  j = *ramto-8;
  ANTIC->PMBASE = j;

  pmgmem = j * 256;
  
  GTIA->GRACTL = 3;
  GTIA->SIZEP0 = 0; 
  *colorpm0 = 183; 
  GTIA->HPOSP0 = px0 ;  
  
  char *pmadr = pmgmem + 512 + py0;
  
  pmadr[0] = pmdata[0];
  pmadr[1] = pmdata[1];
  pmadr[2] = pmdata[2];
  pmadr[3] = pmdata[3];
  pmadr[4] = pmdata[4];
  pmadr[5] = pmdata[5];
  pmadr[6] = pmdata[6];
  pmadr[7] = pmdata[7];
 
  waitkey();
}

void waitkey() {
    while(!kbhit()) ;
    clrkb();
}

char TEXT[] = "hello atari 8bit"
              "Demonstrates ANTIC display list "
              "HELLO atari 8BIT"
            ;

char DISPLAY_LIST[] = {
   BLANK8, BLANK8, BLANK8,              
   LMS|MODE7, <TEXT, >TEXT,             
   BLANK8,BLANK8,                              
   MODE2,  
   BLANK8,BLANK8,                              
   MODE7,  
   JVB, <DISPLAY_LIST, >DISPLAY_LIST    
};

 

Edited by fenrock
clarified bits for PM
Link to comment
Share on other sites

And if you want to use "standard" playfield, here's the change:

 

// change the SDMCTL to use standard:
*SDMCTL = 46; // 0x2E = PM enable + DMA + standard playfield 

// Make the strings 20/40 width for normal. For Narrow they are 16/32 chars wide.
// I've just padded them with more space.
char TEXT[] = "  hello atari 8bit  "
              "    Demonstrates ANTIC display list     "
              "  HELLO atari 8BIT  "
            ;

 

Link to comment
Share on other sites

1 hour ago, ivop said:

Also, you have to make sure the display list doesn't cross 1kB boundaries and the screen data stays within 4kB boundaries. No idea how you influence that with KickC.

You can add the align(value) modifier to an array:

char align(0x100) DISPLAY_LIST[] = {
  // ...

Choose an appropriate alignment for the data.

 

Also, you can set specific address for an array with the __address modifier, the example from the docs is:

__address(0x2000) char SPRITES[64*10];

but this is only available for global arrays, not local (which it is in this instance).

 

However, currently, both of these will increase the output file size as there's only currently 1 contiguous segment for Code and Data in the default output targets, so if your code goes in at 0x600 and your data is at 0x2000, you'll have zeroes between the two in the output file.

 

Edited by fenrock
char
  • Thanks 1
Link to comment
Share on other sites

On 11/7/2020 at 8:22 AM, funkheld said:

 

 

 

Yes, thank you.

for me this is a problem with kickc's similarity to c.
I'm trying to implement cc65 programs.
and that doesn't work.
happens here with the pm.

greeting

I don’t know about KickC but is there a reason that you are not using CC65?

Link to comment
Share on other sites

1 hour ago, fenrock said:

char align(0x100) DISPLAY_LIST[] = { // ...

In my humble opinion, align should be preceeded by two underscores (__). That's what the C standard says if you want compiler dependant stuff (like __attribute__ with gcc and clang).

 

And large gaps of zeroes should be skipped, i.e. start a new binary load segment. Imagine this. Code at $0600 (ca. 200 bytes of code), data at $2800 (way beyond DOS). If the space inbetween is filled with zeroes, it will overwrite DOS. I think it won't even finish loading :)

 

  • Like 2
Link to comment
Share on other sites

2 minutes ago, ivop said:

And large gaps of zeroes should be skipped, i.e. start a new binary load segment. Imagine this. Code at $0600 (ca. 200 bytes of code), data at $2800 (way beyond DOS). If the space inbetween is filled with zeroes, it will overwrite DOS. I think it won't even finish loading :)

 

As I said, "currently" :)

It's certainly possible to provide your own target definitions (that setup the underlying kick assembler's output) so you can space out the code and data segments separately, but at the moment it isn't easy.

I've already raised a request for kickc to better support for segment loading, but remember this is a beta project.

At the moment, single segment xex files are supported, so you just have to be careful about your alignments.

 

Link to comment
Share on other sites

hello, thanks for all friends.

 

Quote

Also, you have to make sure the display list doesn't cross 1kB boundaries and the screen data stays within 4kB boundaries. No idea how you influence that with KickC.
 

 

I then move the screen down at $ 2000.
and the program starts at $ 3000. my disk dos stays below $ 2000. if the disk-dos is bigger you can move everything further up.

greeting

 

 


	

	#pragma target(atarixl)
	#include <atari-xl.h>	

	 	

	char* SCREEN = $2000;
	int zahl;	

	 	

	void main() {
	 *SDMCTL = 0x21; 
	 *SDLST = DISPLAY_LIST;
	    
	    for(zahl=0;zahl<3600;zahl++) {
	    SCREEN[zahl]=129; 
	  }
	  
	    while (1) ;
	}	

	char DISPLAY_LIST[] = {
	  $70 , $70 , $70 , $4D ,
	  $00 , $20 ,
	  $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D ,
	  $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , 
	  $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , 
	  $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D ,
	  $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D ,
	  $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D ,
	  $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D ,
	  $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D ,
	  $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D , $0D ,          
	  $0D , $0D , $0D , $0D , $0D , $41
	};
	
Edited by funkheld
Link to comment
Share on other sites

2 hours ago, ivop said:

In my humble opinion, align should be preceeded by two underscores (__). That's what the C standard says if you want compiler dependant stuff (like __attribute__ with gcc and clang).

 

And large gaps of zeroes should be skipped, i.e. start a new binary load segment. Imagine this. Code at $0600 (ca. 200 bytes of code), data at $2800 (way beyond DOS). If the space inbetween is filled with zeroes, it will overwrite DOS. I think it won't even finish loading :)

 

Thank you for the suggestions @ivop

I do plan to change align() to __align()in a future release. Most of the other non-standard modifiers already use the __ prefix. https://gitlab.com/camelot/kickc/-/issues/572


I also have a plan for better support for "empty" data structures, which currently generates zeros into the binary file. https://gitlab.com/camelot/kickc/-/issues/545

The Atari 8bit-platform XEX-format is unique in supporting multiple memory segments in a single binary file. It is currently possible to write your own linker definition in KickC, and by doing that and using #pragma data_seg() / #pragma code_seg() you can generate XEX-files with multiple segments.


Maybe I could find a way for the compiler to automatically generate the linker configuration needed for creating a XEX-file with multiple segments. However, I have not currently planned that feature, since I am unsure how I can find a good general solution for adding it.

/Jesper

 

  • Like 3
Link to comment
Share on other sites

18 minutes ago, JesperGravgaard said:

The Atari 8bit-platform XEX-format is unique in supporting multiple memory segments in a single binary file. It is currently possible to write your own linker definition in KickC, and by doing that and using #pragma data_seg() / #pragma code_seg() you can generate XEX-files with multiple segments.

That sounds like a workable solution already. With CC65 you also have to define your own linker files to load data at properly aligned addresses.

  • Like 1
Link to comment
Share on other sites

1 hour ago, JesperGravgaard said:

Maybe I could find a way for the compiler to automatically generate the linker configuration needed for creating a XEX-file with multiple segments. However, I have not currently planned that feature, since I am unsure how I can find a good general solution for adding it.

 

I have put some stuff together in https://gitlab.com/camelot/kickc/-/issues/571

I was going to suggest being able to tag functions with __segment(name) modifiers, which would then be linked in the "name" segment (instead of all code going to "code" and data to "data").

With that, I think I could use the example I posted to write a custom tgt file to create multiple segments and then stitch them together manually in a build script.

I just need the __segment() support added to kickc I think.

 

  • Like 1
Link to comment
Share on other sites

this kickc is a magic work.
move this pm with the keys: q / w / e / s
is only 302 bytes small as xex.

Great....
greeting

 


#pragma target(atarixl)
#pragma zp_reserve(0x00..0x7f)

#include <atari-xl.h>
#include <printf.h>
#include <conio.h>

char * const ramto = 0x6a;
char * const colorpm0 = 704;
char * const colorpm1 = 705;
char * const colorpm2 = 706;
char * const colorpm3 = 707;

word i, pmgmem, zahl;


char j, px0 , py0, y1, z;

const char pmdata[] = { 0,255,129,129,129,129,129,129,255,0};

 

void main() {
  
  *SDMCTL = 46;
  *SDLST = DISPLAY_LIST;
  
  px0 = 100;
  py0 = 70;
  
  j = *ramto-8;
  ANTIC->PMBASE = j;

  pmgmem = j * 256;
  
  GTIA->GRACTL = 3;
  GTIA->SIZEP0 = 0; 
  *colorpm0 = 183; 
  GTIA->HPOSP0 = px0 ;  
  
  schiebe();
 
     while (1) {
    *CH = 0xff;

     while(*CH == 0xff) ;
     char keyPressed = *CH;
     
     z=keyPressed ;
     if(z==$2f) {
       px0 =px0-1;
       schiebe();
     };     
     if(z==$2a) {
        px0 =px0+1;
        schiebe();
     };
     if(z==$2e) {
        py0 =py0-1;
        schiebe();
     };
     if(z==$3e) {
        py0 =py0+1;
        schiebe();
     };    
   }
}

 

void waitkey() {
    while(!kbhit()) ;
    clrkb();
}

 

char TEXT[] = "  hello atari 8bit  "
              "    Demonstrates ANTIC display list     "
              "  HELLO atari 8BIT  "
            ;

char DISPLAY_LIST[] = {
   BLANK8, BLANK8, BLANK8,              
   LMS|MODE7, <TEXT, >TEXT,             
   BLANK8,BLANK8,                              
   MODE2,  
   BLANK8,BLANK8,                              
   MODE7,  
   JVB, <DISPLAY_LIST, >DISPLAY_LIST    
};

 

void schiebe(){
  char *pmadr = pmgmem + 512 + py0;
  
   for(y1=0;y1<10;y1++) {
    pmadr[y1] = pmdata[y1];
  }
  
  GTIA->HPOSP0 = px0 ;
}  

Link to comment
Share on other sites

7 hours ago, fenrock said:

 

I have put some stuff together in https://gitlab.com/camelot/kickc/-/issues/571

I was going to suggest being able to tag functions with __segment(name) modifiers, which would then be linked in the "name" segment (instead of all code going to "code" and data to "data").

With that, I think I could use the example I posted to write a custom tgt file to create multiple segments and then stitch them together manually in a build script.

I just need the __segment() support added to kickc I think.

 

@fenrockKickC already supports putting functions into different named segments using #pragma code_seg(name).

 

Here is a tiny example where the main() function is in the default "Code" segment and the fillscreen() function in the "CodeHigh" segment.

 

https://gitlab.com/camelot/kickc/-/blob/master/src/test/kc/examples/linking/linking.c

 

You can also choose  which segment data ends up in using #pragma data_seg(name)

Edited by JesperGravgaard
Link to comment
Share on other sites

this isn't about c64/atari, it's about creating definitions for kick assembler to work with.

 

to make Jesper's example more in line with what you're expecting (an XEX format) you need to adapt the XEX version that's supplied with kickc.

e.g. here's an example that has Code, CodeHigh, CodeHigh2, Data, DataHigh, DataHigh2

// Atari XL/XE executable XEX file with a single segment
// https://www.atarimax.com/jindroush.atari.org/afmtexe.html

// Add any custom includes...

.file [name="%O", type="bin", segments="XexFile"]
.segmentdef XexFile
.segment XexFile
// Binary File Header
.byte $ff, $ff
// Program segment [start address, end address, data]
.word ProgramStart, ProgramEnd-1
.segmentout [ segments="Program" ]
// RunAd - Run Address Segment [start address, end address, data]
.word $02e0, $02e1
.word %E

.segmentdef Program [segments="ProgramStart, Code, Data, CodeHigh, DataHigh, CodeHigh2, DataHigh2, ProgramEnd"]
.segmentdef ProgramStart [start=%P]
.segment ProgramStart
ProgramStart:
.segmentdef Code [startAfter="ProgramStart"]
.segmentdef Data [startAfter="Code"]

.segmentdef CodeHigh [start=$4000]
.segmentdef DataHigh [startAfter="CodeHigh"]

.segmentdef CodeHigh2 [start=$5000]
.segmentdef DataHigh2 [startAfter="CodeHigh2"]

.segmentdef ProgramEnd [startAfter="DataHigh2"]
.segment ProgramEnd
ProgramEnd:

I haven't tested the above (I tested something similar), but it's the basic syntax of kick assembler that's changing here.

 

You can save this as "atarixlseg.ld" and then use it in your c main file with

#pragma link("atarixlseg.ld")

 

  • Like 2
Link to comment
Share on other sites

I have created a KickAssembler plugin to support the XEX file format.

You can get that here if you like to code code ASM: https://gitlab.com/jespergravgaard/kickass-plugin-atari-xex

I have also integrated the plugin into KickC. 

 

So in the next release KickC will be able to create XEX-files where each memory block is stored as a seperate segment in the XEX-file.

This will help you to get smaller XEX-files if you for instance have some code in $1000 and some data in $3000 with an empty gap in between.

  • Like 4
  • Thanks 1
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...