]> git.sur5r.net Git - cc65/commitdiff
Add C support for Atari 2600 (VCS)
authorFlorent Flament <contact@florentflament.com>
Sun, 8 Jan 2017 18:12:55 +0000 (19:12 +0100)
committerFlorent Flament <contact@florentflament.com>
Fri, 13 Jan 2017 20:12:22 +0000 (21:12 +0100)
13 files changed:
cfg/atari2600.cfg [new file with mode: 0644]
include/_riot.h [new file with mode: 0644]
include/_tia.h [new file with mode: 0644]
include/atari2600.h [new file with mode: 0644]
libsrc/Makefile
libsrc/atari2600/crt0.s [new file with mode: 0644]
libsrc/atari2600/ctype.s [new file with mode: 0644]
samples/Makefile
samples/atari2600hello.c [new file with mode: 0644]
src/ca65/main.c
src/cc65/main.c
src/common/target.c
src/common/target.h

diff --git a/cfg/atari2600.cfg b/cfg/atari2600.cfg
new file mode 100644 (file)
index 0000000..106edeb
--- /dev/null
@@ -0,0 +1,22 @@
+# Atari VCS 2600 linker configuration file for cc65
+#
+# Florent Flament (contact@florentflament.com), 2017
+
+SYMBOLS {
+    __STACKSIZE__: type = weak, value = $0010;   # 16 Bytes system stack
+}
+
+MEMORY {
+    RAM: file = "", start = $0080, size = $0080 - __STACKSIZE__, define = yes;
+    ROM: file = %O, start = $F000, size = $1000, fill = yes, fillval = $FF;
+}
+
+SEGMENTS {
+    ZEROPAGE: load = RAM,            type = zp;
+    STARTUP:  load = ROM,            type = ro;
+    CODE:     load = ROM,            type = ro;
+    RODATA:   load = ROM,            type = ro,  optional = yes;
+    DATA:     load = ROM, run = RAM, type = rw,  optional = yes, define = yes;
+    BSS:      load = RAM,            type = bss, optional = yes;
+    VECTORS:  load = ROM,            type = ro,                                start = $FFFA;
+}
diff --git a/include/_riot.h b/include/_riot.h
new file mode 100644 (file)
index 0000000..7c43112
--- /dev/null
@@ -0,0 +1,26 @@
+/*****************************************************************************/
+/*                                                                           */
+/* Atari VCS 2600 RIOT registers addresses                                   */
+/*                                                                           */
+/* Source: DASM - vcs.h                                                      */
+/*                                                                           */
+/* Florent Flament (contact@florentflament.com), 2017                        */
+/*                                                                           */
+/*****************************************************************************/
+
+/* RIOT registers */
+struct __riot {
+    unsigned char swcha;
+    unsigned char swacnt;
+    unsigned char swchb;
+    unsigned char swbcnt;
+    unsigned char intim;
+    unsigned char timint;
+
+    unsigned char unused[14];
+
+    unsigned char tim1t;
+    unsigned char tim8t;
+    unsigned char tim64t;
+    unsigned char t1024t;
+};
diff --git a/include/_tia.h b/include/_tia.h
new file mode 100644 (file)
index 0000000..c89c04d
--- /dev/null
@@ -0,0 +1,100 @@
+/*****************************************************************************/
+/*                                                                           */
+/* Atari VCS 2600 TIA registers addresses                                    */
+/*                                                                           */
+/* Source: DASM - vcs.h                                                      */
+/*                                                                           */
+/* Florent Flament (contact@florentflament.com), 2017                        */
+/*                                                                           */
+/*****************************************************************************/
+
+/* TIA write / read registers */
+struct __tia {
+    union {
+       unsigned char vsync;
+       unsigned char cxm0p;
+    };
+    union {
+       unsigned char vblank;
+       unsigned char cxm1p;
+    };
+    union {
+       unsigned char wsync;
+       unsigned char cxp0fb;
+    };
+    union {
+       unsigned char rsync;
+       unsigned char cxp1fb;
+    };
+    union {
+       unsigned char nusiz0;
+       unsigned char cxm0fb;
+    };
+    union {
+       unsigned char nusiz1;
+       unsigned char cxm1fb;
+    };
+    union {
+       unsigned char colup0;
+       unsigned char cxblpf;
+    };
+    union {
+       unsigned char colup1;
+       unsigned char cxppmm;
+    };
+    union {
+       unsigned char colupf;
+       unsigned char inpt0;
+    };
+    union {
+       unsigned char colubk;
+       unsigned char inpt1;
+    };
+    union {
+       unsigned char ctrlpf;
+       unsigned char inpt2;
+    };
+    union {
+       unsigned char refp0;
+       unsigned char inpt3;
+    };
+    union {
+       unsigned char refp1;
+       unsigned char inpt4;
+    };
+    union {
+       unsigned char pf0;
+       unsigned char inpt5;
+    };
+    unsigned char pf1;
+    unsigned char pf2;
+    unsigned char resp0;
+    unsigned char resp1;
+    unsigned char resm0;
+    unsigned char resm1;
+    unsigned char resbl;
+    unsigned char audc0;
+    unsigned char audc1;
+    unsigned char audf0;
+    unsigned char audf1;
+    unsigned char audv0;
+    unsigned char audv1;
+    unsigned char grp0;
+    unsigned char grp1;
+    unsigned char enam0;
+    unsigned char enam1;
+    unsigned char enabl;
+    unsigned char hmp0;
+    unsigned char hmp1;
+    unsigned char hmm0;
+    unsigned char hmm1;
+    unsigned char hmbl;
+    unsigned char vdelp0;
+    unsigned char vdelp1;
+    unsigned char vdelbl;
+    unsigned char resmp0;
+    unsigned char resmp1;
+    unsigned char hmove;
+    unsigned char hmclr;
+    unsigned char cxclr;
+};
diff --git a/include/atari2600.h b/include/atari2600.h
new file mode 100644 (file)
index 0000000..1eb51a2
--- /dev/null
@@ -0,0 +1,26 @@
+/*****************************************************************************/
+/*                                                                           */
+/* Atari VCS 2600 TIA & RIOT registers addresses                             */
+/*                                                                           */
+/* Source: DASM Version 1.05 - vcs.h                                         */
+/*                                                                           */
+/* Florent Flament (contact@florentflament.com), 2017                        */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef _ATARI2600_H
+#define _ATARI2600_H
+
+/* Check for errors */
+#if !defined(__ATARI2600__)
+#  error This module may only be used when compiling for the Atari 2600!
+#endif
+
+#include <_tia.h>
+#define TIA (*(struct __tia*)0x0000)
+
+#include <_riot.h>
+#define RIOT (*(struct __riot*)0x0280)
+
+/* End of atari2600.h */
+#endif /* #ifndef _ATARI2600_H */
index 99f120f3afdcbf81e0e6588d2c4ca41a8634da4d..6b6a8fce8b3bee0f5024f2cafb393268b683434a 100644 (file)
@@ -19,6 +19,7 @@ TARGETS = apple2    \
           apple2enh \
           atari     \
           atarixl   \
+          atari2600 \
           atari5200 \
           atmos     \
           $(CBMS)   \
diff --git a/libsrc/atari2600/crt0.s b/libsrc/atari2600/crt0.s
new file mode 100644 (file)
index 0000000..4f09a0a
--- /dev/null
@@ -0,0 +1,49 @@
+; Atari VCS 2600 startup code for cc65
+;
+; Florent Flament (contact@florentflament.com), 2017
+
+        .export         _exit
+        .export         __STARTUP__ : absolute = 1
+
+        .import         __RAM_START__, __RAM_SIZE__
+        .import         copydata
+        .import         _main
+
+        .include        "zeropage.inc"
+
+
+.segment "STARTUP"
+start:
+; Clear decimal mode
+        cld
+
+; Initialization Loop:
+; * Clears Atari 2600 whole memory (128 bytes) including BSS segment
+; * Clears TIA registers
+; * Sets system stack pointer to $ff (i.e top of zero-page)
+        ldx     #0
+        txa
+clearLoop:
+        dex
+        txs
+        pha
+        bne     clearLoop
+
+; Initialize data
+        jsr     copydata
+
+; Initialize C stack pointer
+        lda     #<(__RAM_START__ + __RAM_SIZE__)
+        ldx     #>(__RAM_START__ + __RAM_SIZE__)
+        sta     sp
+        stx     sp+1
+
+; Call main
+        jsr     _main
+_exit:  jmp     _exit
+
+
+.segment "VECTORS"
+.word   start                   ; NMI
+.word   start                   ; Reset
+.word   start                   ; IRQ
diff --git a/libsrc/atari2600/ctype.s b/libsrc/atari2600/ctype.s
new file mode 100644 (file)
index 0000000..1892554
--- /dev/null
@@ -0,0 +1,162 @@
+;
+; Ullrich von Bassewitz, 2003-10-10
+;
+; Character specification table.
+;
+
+        .include        "ctype.inc"
+
+; The tables are readonly, put them into the rodata segment
+
+.rodata
+
+; The following 256 byte wide table specifies attributes for the isxxx type
+; of functions. Doing it by a table means some overhead in space, but it
+; has major advantages:
+;
+;   * It is fast. If it weren't for the slow parameter passing of cc65, one
+;     could even define macros for the isxxx functions (this is usually
+;     done on other platforms).
+;
+;   * It is highly portable. The only unportable part is the table itself,
+;     all real code goes into the common library.
+;
+;   * We save some code in the isxxx functions.
+
+
+__ctype:
+        .byte   CT_CTRL                 ;   0/00 ___ctrl_@___
+        .byte   CT_CTRL                 ;   1/01 ___ctrl_A___
+        .byte   CT_CTRL                 ;   2/02 ___ctrl_B___
+        .byte   CT_CTRL                 ;   3/03 ___ctrl_C___
+        .byte   CT_CTRL                 ;   4/04 ___ctrl_D___
+        .byte   CT_CTRL                 ;   5/05 ___ctrl_E___
+        .byte   CT_CTRL                 ;   6/06 ___ctrl_F___
+        .byte   CT_CTRL                 ;   7/07 ___ctrl_G___
+        .byte   CT_CTRL                 ;   8/08 ___ctrl_H___
+        .byte   CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB
+                                        ;   9/09 ___ctrl_I___
+        .byte   CT_CTRL | CT_OTHER_WS   ;  10/0a ___ctrl_J___
+        .byte   CT_CTRL | CT_OTHER_WS   ;  11/0b ___ctrl_K___
+        .byte   CT_CTRL | CT_OTHER_WS   ;  12/0c ___ctrl_L___
+        .byte   CT_CTRL | CT_OTHER_WS   ;  13/0d ___ctrl_M___
+        .byte   CT_CTRL                 ;  14/0e ___ctrl_N___
+        .byte   CT_CTRL                 ;  15/0f ___ctrl_O___
+        .byte   CT_CTRL                 ;  16/10 ___ctrl_P___
+        .byte   CT_CTRL                 ;  17/11 ___ctrl_Q___
+        .byte   CT_CTRL                 ;  18/12 ___ctrl_R___
+        .byte   CT_CTRL                 ;  19/13 ___ctrl_S___
+        .byte   CT_CTRL                 ;  20/14 ___ctrl_T___
+        .byte   CT_CTRL                 ;  21/15 ___ctrl_U___
+        .byte   CT_CTRL                 ;  22/16 ___ctrl_V___
+        .byte   CT_CTRL                 ;  23/17 ___ctrl_W___
+        .byte   CT_CTRL                 ;  24/18 ___ctrl_X___
+        .byte   CT_CTRL                 ;  25/19 ___ctrl_Y___
+        .byte   CT_CTRL                 ;  26/1a ___ctrl_Z___
+        .byte   CT_CTRL                 ;  27/1b ___ctrl_[___
+        .byte   CT_CTRL                 ;  28/1c ___ctrl_\___
+        .byte   CT_CTRL                 ;  29/1d ___ctrl_]___
+        .byte   CT_CTRL                 ;  30/1e ___ctrl_^___
+        .byte   CT_CTRL                 ;  31/1f ___ctrl_____
+        .byte   CT_SPACE | CT_SPACE_TAB ;  32/20 ___SPACE___
+        .byte   CT_NONE                 ;  33/21 _____!_____
+        .byte   CT_NONE                 ;  34/22 _____"_____
+        .byte   CT_NONE                 ;  35/23 _____#_____
+        .byte   CT_NONE                 ;  36/24 _____$_____
+        .byte   CT_NONE                 ;  37/25 _____%_____
+        .byte   CT_NONE                 ;  38/26 _____&_____
+        .byte   CT_NONE                 ;  39/27 _____'_____
+        .byte   CT_NONE                 ;  40/28 _____(_____
+        .byte   CT_NONE                 ;  41/29 _____)_____
+        .byte   CT_NONE                 ;  42/2a _____*_____
+        .byte   CT_NONE                 ;  43/2b _____+_____
+        .byte   CT_NONE                 ;  44/2c _____,_____
+        .byte   CT_NONE                 ;  45/2d _____-_____
+        .byte   CT_NONE                 ;  46/2e _____._____
+        .byte   CT_NONE                 ;  47/2f _____/_____
+        .byte   CT_DIGIT | CT_XDIGIT    ;  48/30 _____0_____
+        .byte   CT_DIGIT | CT_XDIGIT    ;  49/31 _____1_____
+        .byte   CT_DIGIT | CT_XDIGIT    ;  50/32 _____2_____
+        .byte   CT_DIGIT | CT_XDIGIT    ;  51/33 _____3_____
+        .byte   CT_DIGIT | CT_XDIGIT    ;  52/34 _____4_____
+        .byte   CT_DIGIT | CT_XDIGIT    ;  53/35 _____5_____
+        .byte   CT_DIGIT | CT_XDIGIT    ;  54/36 _____6_____
+        .byte   CT_DIGIT | CT_XDIGIT    ;  55/37 _____7_____
+        .byte   CT_DIGIT | CT_XDIGIT    ;  56/38 _____8_____
+        .byte   CT_DIGIT | CT_XDIGIT    ;  57/39 _____9_____
+        .byte   CT_NONE                 ;  58/3a _____:_____
+        .byte   CT_NONE                 ;  59/3b _____;_____
+        .byte   CT_NONE                 ;  60/3c _____<_____
+        .byte   CT_NONE                 ;  61/3d _____=_____
+        .byte   CT_NONE                 ;  62/3e _____>_____
+        .byte   CT_NONE                 ;  63/3f _____?_____
+
+        .byte   CT_NONE                 ;  64/40 _____@_____
+        .byte   CT_UPPER | CT_XDIGIT    ;  65/41 _____A_____
+        .byte   CT_UPPER | CT_XDIGIT    ;  66/42 _____B_____
+        .byte   CT_UPPER | CT_XDIGIT    ;  67/43 _____C_____
+        .byte   CT_UPPER | CT_XDIGIT    ;  68/44 _____D_____
+        .byte   CT_UPPER | CT_XDIGIT    ;  69/45 _____E_____
+        .byte   CT_UPPER | CT_XDIGIT    ;  70/46 _____F_____
+        .byte   CT_UPPER                ;  71/47 _____G_____
+        .byte   CT_UPPER                ;  72/48 _____H_____
+        .byte   CT_UPPER                ;  73/49 _____I_____
+        .byte   CT_UPPER                ;  74/4a _____J_____
+        .byte   CT_UPPER                ;  75/4b _____K_____
+        .byte   CT_UPPER                ;  76/4c _____L_____
+        .byte   CT_UPPER                ;  77/4d _____M_____
+        .byte   CT_UPPER                ;  78/4e _____N_____
+        .byte   CT_UPPER                ;  79/4f _____O_____
+        .byte   CT_UPPER                ;  80/50 _____P_____
+        .byte   CT_UPPER                ;  81/51 _____Q_____
+        .byte   CT_UPPER                ;  82/52 _____R_____
+        .byte   CT_UPPER                ;  83/53 _____S_____
+        .byte   CT_UPPER                ;  84/54 _____T_____
+        .byte   CT_UPPER                ;  85/55 _____U_____
+        .byte   CT_UPPER                ;  86/56 _____V_____
+        .byte   CT_UPPER                ;  87/57 _____W_____
+        .byte   CT_UPPER                ;  88/58 _____X_____
+        .byte   CT_UPPER                ;  89/59 _____Y_____
+        .byte   CT_UPPER                ;  90/5a _____Z_____
+        .byte   CT_NONE                 ;  91/5b _____[_____
+        .byte   CT_NONE                 ;  92/5c _____\_____
+        .byte   CT_NONE                 ;  93/5d _____]_____
+        .byte   CT_NONE                 ;  94/5e _____^_____
+        .byte   CT_NONE                 ;  95/5f _UNDERLINE_
+        .byte   CT_NONE                 ;  96/60 ___grave___
+        .byte   CT_LOWER | CT_XDIGIT    ;  97/61 _____a_____
+        .byte   CT_LOWER | CT_XDIGIT    ;  98/62 _____b_____
+        .byte   CT_LOWER | CT_XDIGIT    ;  99/63 _____c_____
+        .byte   CT_LOWER | CT_XDIGIT    ; 100/64 _____d_____
+        .byte   CT_LOWER | CT_XDIGIT    ; 101/65 _____e_____
+        .byte   CT_LOWER | CT_XDIGIT    ; 102/66 _____f_____
+        .byte   CT_LOWER                ; 103/67 _____g_____
+        .byte   CT_LOWER                ; 104/68 _____h_____
+        .byte   CT_LOWER                ; 105/69 _____i_____
+        .byte   CT_LOWER                ; 106/6a _____j_____
+        .byte   CT_LOWER                ; 107/6b _____k_____
+        .byte   CT_LOWER                ; 108/6c _____l_____
+        .byte   CT_LOWER                ; 109/6d _____m_____
+        .byte   CT_LOWER                ; 110/6e _____n_____
+        .byte   CT_LOWER                ; 111/6f _____o_____
+        .byte   CT_LOWER                ; 112/70 _____p_____
+        .byte   CT_LOWER                ; 113/71 _____q_____
+        .byte   CT_LOWER                ; 114/72 _____r_____
+        .byte   CT_LOWER                ; 115/73 _____s_____
+        .byte   CT_LOWER                ; 116/74 _____t_____
+        .byte   CT_LOWER                ; 117/75 _____u_____
+        .byte   CT_LOWER                ; 118/76 _____v_____
+        .byte   CT_LOWER                ; 119/77 _____w_____
+        .byte   CT_LOWER                ; 120/78 _____x_____
+        .byte   CT_LOWER                ; 121/79 _____y_____
+        .byte   CT_LOWER                ; 122/7a _____z_____
+        .byte   CT_NONE                 ; 123/7b _____{_____
+        .byte   CT_NONE                 ; 124/7c _____|_____
+        .byte   CT_NONE                 ; 125/7d _____}_____
+        .byte   CT_NONE                 ; 126/7e _____~_____
+        .byte   CT_OTHER_WS             ; 127/7f ____DEL____
+
+        .res    128, CT_NONE            ; 128-255
+
+
+
index 3a60798dafeee75ed608e6f6a32f6f96472ba786..abd304b143cf6c414c6366c1fb92cb62bd19ffb8 100644 (file)
@@ -147,6 +147,9 @@ EXELIST_atari =    \
 
 EXELIST_atarixl = $(EXELIST_atari)
 
+EXELIST_atari2600 =    \
+        atari2600hello
+
 # --------------------------------------------------------------------------
 # Rules to make the binaries and the disk
 
diff --git a/samples/atari2600hello.c b/samples/atari2600hello.c
new file mode 100644 (file)
index 0000000..e4f7893
--- /dev/null
@@ -0,0 +1,56 @@
+/*****************************************************************************/
+/*                                                                           */
+/* Atari VCS 2600 sample C program                                           */
+/*                                                                           */
+/* Florent Flament (contact@florentflament.com), 2017                        */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <atari2600.h>
+
+// PAL Timings
+// Roughly computed based on Stella Programmer's guide (Steve Wright)
+// scanlines count per section.
+#define VBLANK_TIM64 51 // 45 lines * 76 cycles/line / 64 cycles/tick
+#define KERNAL_T1024 17 // 228 lines * 76 cycles/line / 1024 cycles/tick
+#define OVERSCAN_TIM64 42 // 36 lines * 76 cycles/line / 64 cycles/tick
+
+// Testing memory zones
+const unsigned char rodata_v[] = "Hello!";
+unsigned char data_v = 0x77;
+unsigned char bss_v;
+
+void main(void) {
+    unsigned char color = 0x79; // Stack variable
+    bss_v = 0x88; // Testing BSS variable
+
+    for/*ever*/(;;) {
+       // Vertical Sync signal
+       TIA.vsync = 0x02;
+       TIA.wsync = 0x00;
+       TIA.wsync = 0x00;
+       TIA.wsync = 0x00;
+       TIA.vsync = 0x00;
+
+       // Vertical Blank timer setting
+       RIOT.tim64t = VBLANK_TIM64;
+
+       // Doing frame computation during blank
+       TIA.colubk = color++; // Update color
+
+       // Wait for end of Vertical Blank
+       while (RIOT.timint == 0) {}
+       TIA.wsync = 0x00;
+       TIA.vblank = 0x00; // Turn on beam
+
+       // Display frame
+       RIOT.t1024t = KERNAL_T1024;
+       while (RIOT.timint == 0) {}
+       TIA.wsync = 0x00;
+       TIA.vblank = 0x02; // Turn off beam
+
+       // Overscan
+       RIOT.tim64t = OVERSCAN_TIM64;
+       while (RIOT.timint == 0) {}
+    }
+}
index d6c364e4b7c16dda27b387c46b260556c8373ceb..1317f26cc9330dbb55c06f62510f8ae0f109cc37 100644 (file)
@@ -205,6 +205,10 @@ static void SetSys (const char* Sys)
             AbEnd ("Cannot use `module' as a target for the assembler");
             break;
 
+        case TGT_ATARI2600:
+            NewSymbol ("__ATARI2600__", 1);
+            break;
+
         case TGT_ATARI5200:
             NewSymbol ("__ATARI5200__", 1);
             break;
index afbec43d74872ee9040efeaa42aa61c9d2eb268e..2a82e53025f82d617054e07b64084435f7f489fd 100644 (file)
@@ -161,6 +161,10 @@ static void SetSys (const char* Sys)
             AbEnd ("Cannot use `module' as a target for the compiler");
             break;
 
+        case TGT_ATARI2600:
+            DefineNumericMacro ("__ATARI2600__", 1);
+            break;
+
         case TGT_ATARI5200:
             DefineNumericMacro ("__ATARI5200__", 1);
             break;
index 99a134c43bc7aa92be692a8085248435562d43ed..42db5dee3928c9718ae8540aa8213be3f7beaed3 100644 (file)
@@ -145,6 +145,7 @@ static const TargetEntry TargetMap[] = {
     {   "apple2",       TGT_APPLE2      },
     {   "apple2enh",    TGT_APPLE2ENH   },
     {   "atari",        TGT_ATARI       },
+    {   "atari2600",    TGT_ATARI2600   },
     {   "atari5200",    TGT_ATARI5200   },
     {   "atarixl",      TGT_ATARIXL     },
     {   "atmos",        TGT_ATMOS       },
@@ -181,6 +182,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
     { "none",           CPU_6502,       BINFMT_BINARY,      CTNone  },
     { "module",         CPU_6502,       BINFMT_O65,         CTNone  },
     { "atari",          CPU_6502,       BINFMT_BINARY,      CTAtari },
+    { "atari2600",      CPU_6502,       BINFMT_BINARY,      CTNone  },
     { "atari5200",      CPU_6502,       BINFMT_BINARY,      CTAtari },
     { "atarixl",        CPU_6502,       BINFMT_BINARY,      CTAtari },
     { "vic20",          CPU_6502,       BINFMT_BINARY,      CTPET   },
index 4115ae21a9d17593dab190bb8a47bacffa2e273e..a5cb44b98e1b4cda44d3e6cf4c451c8ac3cf041d 100644 (file)
@@ -55,6 +55,7 @@ typedef enum {
     TGT_NONE,
     TGT_MODULE,
     TGT_ATARI,
+    TGT_ATARI2600,
     TGT_ATARI5200,
     TGT_ATARIXL,
     TGT_VIC20,