KickC - Optimizing C-compiler for 6502 platforms (released on https://gitlab.com/camelot/kickc by Jesper Gravgaard )

Ensure a fairly modern version of java is installed (I use Temurin JDK 25-LTS) download: https://adoptium.net/temurin/releases/)

KickC is a C-compiler for 6502-based platforms creating optimized and readable assembler code.
The language is 95% standard C99 with a few limitations, and a few extensions to ensure an optimal fit for creating 6502 assembler code.
The KickC-compiler includes all necessary linker and header files to makes it easy to create and test binaries for the following 6502-based platforms out-of-the-box:

    Commodore VIC 20
    Commodore 64
    Commodore Plus/4 (Commodore 16 , Commodore 116)
    Atari 2600
    Atari XL/XE
    Nintendo NES
    MEGA65
    Commander X16
    C1P (added by Thomas in 2025/26)

KickC uses the very versatile Kick Assembler. The KickC Compiler produces assembler code for the MOS Technology 6502 processor family. Specifically the compiler supports 6502, 65C02, 65CE02 and 45GS02 CPUs.


KickC compile-time directives for code generation

| Pragma                       | Purpose                  | Short explanation                                                                                      |
| ---------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------ |
| `#pragma var_model(mem)`     | Variable memory model    | Stores variables as normal RAM-resident memory (predictable addressing, minimal special optimization). |
| `#pragma var_model(zp)`      | Zero-page variable model | Tries to place variables in 6502 zero-page for faster access.                                          |
| `#pragma data_seg("name")`   | Data segment selection   | Places variables into a named linker/data segment.                                                     |
| `#pragma code_seg("name")`   | Code segment selection   | Places functions into a named code segment.                                                            |
| `#pragma zp(var)`            | Zero-page placement hint | Forces a variable into zero-page memory (when supported).                                              |
| `#pragma align(n)`           | Memory alignment         | Aligns variables/structures to `n` byte boundaries.                                                    |
| `#pragma inline`             | Force inline             | Suggests or forces function inlining at call sites.                                                    |
| `#pragma noinline`           | Disable inlining         | Prevents a function from being inlined.                                                                |
| `#pragma opt(on/off)`        | Optimization control     | Enables or disables compiler optimizations locally.                                                    |
| `#pragma optimize(level)`    | Optimization level       | Sets optimization intensity (e.g., size vs speed).                                                     |
| `#pragma register`           | Register allocation hint | Suggests keeping variable in CPU register if possible.                                                 |
| `#pragma calling convention` | ABI control              | Controls parameter passing / return conventions (useful for assembly interop).                         |
| `#pragma bank(n)`            | Memory banking           | Places code/data into a specific memory bank (for banked systems).                                     |
| `#pragma section("name")`    | Section grouping         | Groups code/data into linker sections.                                                                 |
| `#pragma push`               | Save pragma state        | Saves current pragma configuration state.                                                              |
| `#pragma pop`                | Restore pragma state     | Restores previously saved pragma state.                                                                |
| `#pragma map(...)`           | Symbol mapping           | Maps symbols/variables to specific addresses or labels (low-level control).                            |

KickC versions do not support every pragma above.
The most commonly used in real projects are:

var_model
data_seg
code_seg
zp
inline / noinline
opt


Comments:

KickC uses #pragma constructor_for in some libraries as a way to build initialization dependencies for subsystems, especially for things like conio.
#pragma constructor_for(...) in KickC is a special compilation directive used to automatically run initialization code before main() starts


#pragma var_model(mem)

$0000 ┌──────────────────────────────┐
      │ Zero Page (unused or minimal)│
$00FF ├──────────────────────────────┤
      │ Stack                 │
$01FF ├──────────────────────────────┤
      │                       │
      │  VARIABLES (mem model)│  ← e.g. $0800, $1000, etc.
      │  - globals            │
      │  - arrays             │
      │  - structs            │
      │                       │
      │  CODE / DATA          │
      │                       │
$FFFF └──────────────────────────────┘


#pragma zp(...)  Zero Page model
 	
$0000 ┌──────────────────────────────┐
      │ ZERO PAGE VARIABLES   │  ← FAST ACCESS
      │  A, B, temp, pointers │
      │  (KickC may allocate here)│
$00FF ├──────────────────────────────┤
      │ Stack ($0100–$01FF)   │
$01FF ├──────────────────────────────┤
      │ General RAM           │
      │ - globals (non-zp)    │
      │ - arrays              │
      │                       │
$FFFF └──────────────────────────────┘
