Re: [cc65] Atari: Loading code with DOS 2.0 help?

From: Christian Groessler <chris1groessler.org>
Date: 2004-08-31 20:04:34
On Wed, 4 Aug 2004, Christian Groessler wrote:
>
> On Tue, 3 Aug 2004, Ullrich von Bassewitz wrote:
>
> > How about adding this information to the platform specific documentation
> > (atari.sgml)? I'm pretty sure this is useful for more people.
>
> Hmm, yes, good idea.
> I'll write a draft and post it here for review.

I've added a chapter to the Atari specific cc65 docs. You can find the
new docs on

   ftp://ftp.groessler.org/pub/chris/cc65/atari.txt   and
   ftp://ftp.groessler.org/pub/chris/cc65/atari.html.

Maybe a native English speaker should proof read it so we can get all
the German English phrases fixed :-)

I've appended the relevant chapter to this mail for quick access

regards,
chris



  7.2.  Reserving a memory area inside the program


  The Atari 130XE maps its additional memory into CPU memory in 16K
  chunks at address $4000 to $7FFF. One might want to prevent this
  memory area from being used by cc65. Other reasons to prevent the use
  of some memory area could be the buffers for display lists and screen
  memory.

  The Atari executable format allows holes inside a program, e.g. one
  part loads into $2E00 to $3FFF, going below the reserved memory area
  (assuming a reserved area from $4000 to $7FFF), and another part loads
  into $8000 to $BC1F.

  Each load chunk of the executable starts with a 4 byte header which
  defines its load address and size.


  7.2.1.  Low code and high data example

  Create an executable with 2 load chunks which doesn't use the memory
  area from $4000 to $7FFF. The CODE segment of the program should go
  below $4000 and the DATA and RODATA segments should go above $7FFF.

  The main problem is that the EXE header generated by the cc65 runtine
  lib is wrong. It defines a single load chunk with the sizes/addresses
  of the CODE, RODATA, and DATA segments (the whole user program).

  The contents of the EXE header come from the EXEHDR segment, which is
  defined in crt0.s. This cannot be changed w/o modifiying and
  recompiling the cc65 atari runtime lib. Therefore the original EXE
  header must be discarded. It will be replaced by a user created one.

  The user needs to create a customized linker config file which adds
  new memory areas and segments to hold the new EXE header and added
  load chunk header data. Also an assembly source file needs to be
  created which defines the contents of the new EXE header and the
  second load chunk header.


  This is a modified cc65 Atari linker configuration file (split.cfg):



  MEMORY {
      ZP: start = $82, size = $7E, type = rw, define = yes;

      HEADER: start = $0000, size = $6, file = %O;        # first load chunk
      RAMLO: start = $2E00, size = $1200, file = %O;

      BANK: start = $4000, size = $4000, file = "";

      SECHDR: start = $0000, size = $4, file = %O;        # second load chunk
      RAM: start = $8000, size = $3C20, file = %O;        # $3C20: matches upper bound $BC1F
  }
  SEGMENTS {
      EXEHDR: load = BANK, type = wprot;

      NEXEHDR: load = HEADER, type = wprot;               # first load chunk
      CODE: load = RAMLO, type = wprot, define = yes;

      CHKHDR: load = SECHDR, type = wprot;                # second load chunk
      RODATA: load = RAM, type = wprot, define = yes;
      DATA: load = RAM, type = rw, define = yes;
      BSS: load = RAM, type = bss, define = yes;

      ZEROPAGE: load = ZP, type = zp;
      AUTOSTRT: load = RAM, type = wprot;                 # defines program entry point
  }
  FEATURES {
      CONDES: segment = RODATA,
              type = constructor,
              label = __CONSTRUCTOR_TABLE__,
              count = __CONSTRUCTOR_COUNT__;
      CONDES: segment = RODATA,
              type = destructor,
              label = __DESTRUCTOR_TABLE__,
              count = __DESTRUCTOR_COUNT__;
  }
  SYMBOLS {
      __STACKSIZE__ = $800;       # 2K stack
  }



  A new memory area BANK was added which describes the reserved area.
  It gets loaded with the contents of the old EXEHDR segment. But the
  memory area isn't written to the output file. This way the contents of
  the EXEHDR segment get discarded.

  The added NEXEHDR segment defines the correct EXE header. It puts only
  the CODE segment into load chunk #1 (RAMLO memory area).

  The header for the second load chunk comes from the new CHKHDR
  segment. It puts the RODATA and DATA segments into load chunk #2 (RAM
  memory area).


  The contents of the new NEXEHDR and CHKHDR segments come from this
  file (split.s):



          .import __CODE_LOAD__, __BSS_LOAD__, __CODE_SIZE__
          .import __DATA_LOAD__, __RODATA_LOAD__

          .segment "NEXEHDR"
          .word    $FFFF          ; EXE file magic number
          ; 1st load chunk
          .word    __CODE_LOAD__
          .word    __CODE_LOAD__ + __CODE_SIZE__ - 1

          .segment "CHKHDR"
          ; 2nd load chunk (contains with AUTOSTRT in fact a 3rd load chunk)
          .word    __RODATA_LOAD__
          .word    __BSS_LOAD__ - 1



  Compile with


       cl65 -t atari -C split.cfg -o prog.com prog.c split.s



  7.2.2.  Low data and high code example



  Put RODATA and DATA into low memory and CODE with BSS into high memory
  (split2.cfg):



  MEMORY {
      ZP: start = $82, size = $7E, type = rw, define = yes;

      HEADER: start = $0000, size = $6, file = %O;        # first load chunk
      RAMLO: start = $2E00, size = $1200, file = %O;

      BANK: start = $4000, size = $4000, file = "";

      SECHDR: start = $0000, size = $4, file = %O;        # second load chunk
      RAM: start = $8000, size = $3C20, file = %O;        # $3C20: matches upper bound $BC1F
  }
  SEGMENTS {
      EXEHDR: load = BANK, type = wprot;                  # discarded old EXE header

      NEXEHDR: load = HEADER, type = wprot;               # first load chunk
      RODATA: load = RAMLO, type = wprot, define = yes;
      DATA: load = RAMLO, type = rw, define = yes;

      CHKHDR: load = SECHDR, type = wprot;                # second load chunk
      CODE: load = RAM, type = wprot, define = yes;
      BSS: load = RAM, type = bss, define = yes;

      ZEROPAGE: load = ZP, type = zp;
      AUTOSTRT: load = RAM, type = wprot;                 # defines program entry point
  }
  FEATURES {
      CONDES: segment = RODATA,
              type = constructor,
              label = __CONSTRUCTOR_TABLE__,
              count = __CONSTRUCTOR_COUNT__;
      CONDES: segment = RODATA,
              type = destructor,
              label = __DESTRUCTOR_TABLE__,
              count = __DESTRUCTOR_COUNT__;
  }
  SYMBOLS {
      __STACKSIZE__ = $800;       # 2K stack
  }



  New contents for NEXEHDR and CHKHDR are needed (split2.s):


               .import __CODE_LOAD__, __BSS_LOAD__, __DATA_SIZE__
               .import __DATA_LOAD__, __RODATA_LOAD__

               .segment "NEXEHDR"
               .word    $FFFF
               .word    __RODATA_LOAD__
               .word    __DATA_LOAD__ + __DATA_SIZE__ - 1

               .segment "CHKHDR"
               .word    __CODE_LOAD__
               .word    __BSS_LOAD__ - 1



  Compile with


       cl65 -t atari -C split2.cfg -o prog.com prog.c split2.s


  7.2.3.  Final note


  There are two other memory areas which don't appear directly in the
  linker script. They are the stack and the heap.

  The cc65 runtime lib places the stack location at the end of available
  memory. This is dynamically set from the MEMTOP system variable at
  startup. The heap is located in the area between the end of the BSS
  segment and the top of the stack as defined by __STACKSIZE__.

  If BSS and/or the stack shouldn't stay at the end of the program, some
  parts of the cc65 runtime lib need to be replaced/modified.

  runtime/_heap.s defines the location of the heap and atari/crt0.s
  defines the location of the stack by initializing sp.


----------------------------------------------------------------------
To unsubscribe from the list send mail to majordomo@musoftware.de with
the string "unsubscribe cc65" in the body(!) of the mail.
Received on Wed Sep 1 01:34:57 2004

This archive was generated by hypermail 2.1.8 : 2004-09-01 01:35:06 CEST