]> git.sur5r.net Git - cc65/commitdiff
Merge pull request #834 from jedeoric/master
authorOliver Schmidt <ol.sc@web.de>
Tue, 12 Feb 2019 16:51:24 +0000 (17:51 +0100)
committerGitHub <noreply@github.com>
Tue, 12 Feb 2019 16:51:24 +0000 (17:51 +0100)
Update telestrat target doc, add tgi_clear support for telestrat target, stratsed & telemon 2.4 vars added

42 files changed:
asminc/mouse-kernel.inc
asminc/smc.inc
asminc/telestrat.inc
cfg/atari-xex.cfg [new file with mode: 0644]
cfg/telestrat.cfg
doc/atari.sgml
doc/ca65.sgml
doc/ld65.sgml
include/_tia.h
include/c64_screen_charmap.h [new file with mode: 0644]
libsrc/atari/mou/atrst.s
libsrc/atari/mouseref.s
libsrc/atari/shadow_ram_timerirq2.s [new file with mode: 0644]
libsrc/common/getcpu.s
libsrc/telestrat/cgetc.s
libsrc/telestrat/close.s
libsrc/telestrat/clrscr.s
libsrc/telestrat/gotox.s
libsrc/telestrat/gotoy.s
libsrc/telestrat/mainargs.s
libsrc/telestrat/open.s
libsrc/telestrat/read.s
libsrc/telestrat/wherex.s
libsrc/telestrat/wherey.s
libsrc/telestrat/write.s
samples/atari2600hello.c
src/cc65/codegen.c
src/cc65/pragma.c
src/common/intptrstack.h
src/common/target.h
src/ld65.vcxproj
src/ld65/binfmt.c
src/ld65/config.c
src/ld65/scanner.h
src/ld65/xex.c [new file with mode: 0644]
src/ld65/xex.h [new file with mode: 0644]
src/sim65/6502.c
testcode/lib/atari/asm-xex.s [new file with mode: 0644]
testcode/lib/atari/multi-xex.cfg [new file with mode: 0644]
testcode/lib/atari/multi-xex.s [new file with mode: 0644]
testcode/lib/gamate/lcdtest.s
testcode/lib/mouse-test.c

index 3eebca244d201cbb74a1783204ea1043dd96bf2a..ab4790d1dd6444c0930c3883979d2f019a21d0d7 100644 (file)
 ;------------------------------------------------------------------------------
 ; The mouse API version, stored in MOUSE_HDR::VERSION
 
-MOUSE_API_VERSION       = $05
+MOUSE_API_VERSION       = $06
 
 ;------------------------------------------------------------------------------
 ; Bitmapped mouse driver flags, stored in MOUSE_HDR::FLAGS.
index 0583f79e0ba97a3eea7e0e7b2cf9b033fedb1a70..137c2d49a6667616f1140357250d34d229005f5c 100644 (file)
@@ -63,7 +63,7 @@ _SMCDesignator: statement
         ldy #opcode
         sty _SMCDesignator
 .else
-       .error "Invalid usage of macro 'SMC_TransferOpcode'"
+        .error "Invalid usage of macro 'SMC_TransferOpcode'"
 .endif
 .endmacro
 
@@ -75,7 +75,7 @@ _SMCDesignator: statement
 .elseif .match ({register}, y)
         ldy _SMCDesignator
 .else
-       .error "Invalid usage of macro 'SMC_LoadOpcode'"
+        .error "Invalid usage of macro 'SMC_LoadOpcode'"
 .endif
 .endmacro
 
@@ -87,7 +87,7 @@ _SMCDesignator: statement
 .elseif .match ({register}, y)
         sty _SMCDesignator
 .else
-       .error "Invalid usage of macro 'SMC_StoreOpcode'"
+        .error "Invalid usage of macro 'SMC_StoreOpcode'"
 .endif
 .endmacro
 
@@ -102,7 +102,7 @@ _SMCDesignator: statement
         ldy #(<(destination - _SMCDesignator - 2))
         sty _SMCDesignator+1
 .else
-       .error "Invalid usage of macro 'SMC_ChangeBranch'"
+        .error "Invalid usage of macro 'SMC_ChangeBranch'"
 .endif
 .endmacro
 
@@ -117,7 +117,7 @@ _SMCDesignator: statement
         ldy value
         sty _SMCDesignator+1
 .else
-       .error "Invalid usage of macro 'SMC_TransferValue'"
+        .error "Invalid usage of macro 'SMC_TransferValue'"
 .endif
 .endmacro
 
@@ -129,7 +129,7 @@ _SMCDesignator: statement
 .elseif .match ({register}, y)
         ldy _SMCDesignator+1
 .else
-       .error "Invalid usage of macro 'SMC_LoadValue'"
+        .error "Invalid usage of macro 'SMC_LoadValue'"
 .endif
 .endmacro
 
@@ -141,7 +141,7 @@ _SMCDesignator: statement
 .elseif .match ({register}, y)
         sty _SMCDesignator+1
 .else
-       .error "Invalid usage of macro 'SMC_StoreValue'"
+        .error "Invalid usage of macro 'SMC_StoreValue'"
 .endif
 .endmacro
 
@@ -169,7 +169,7 @@ SMC_StoreValue label, register
         ldy value
         sty _SMCDesignator+2
 .else
-       .error "Invalid usage of macro 'SMC_TransferHighByte'"
+        .error "Invalid usage of macro 'SMC_TransferHighByte'"
 .endif
 .endmacro
 
@@ -181,7 +181,7 @@ SMC_StoreValue label, register
 .elseif .match ({register}, y)
         ldy _SMCDesignator+2
 .else
-       .error "Invalid usage of macro 'SMC_LoadHighByte'"
+        .error "Invalid usage of macro 'SMC_LoadHighByte'"
 .endif
 .endmacro
 
@@ -193,7 +193,7 @@ SMC_StoreValue label, register
 .elseif .match ({register}, y)
         sty _SMCDesignator+2
 .else
-       .error "Invalid usage of macro 'SMC_StoreHighByte'"
+        .error "Invalid usage of macro 'SMC_StoreHighByte'"
 .endif
 .endmacro
 
@@ -241,7 +241,7 @@ SMC_StoreValue label, register
                 sty _SMCDesignator+2
         .endif
 .else
-       .error "Invalid usage of macro 'SMC_TransferAddressSingle'"
+        .error "Invalid usage of macro 'SMC_TransferAddressSingle'"
 .endif
 .endmacro
 
index 8d2e9afc19b6079acb26885e8ecd8cc1dfa41cf5..f2eb42ff473d521ee5b04fb66255c110270b0baa 100644 (file)
@@ -472,5 +472,5 @@ XRWTS            := $FFAA
 ; MACRO 
 
 .macro  BRK_TELEMON   value
-       .byte $00,value
+        .byte $00,value
 .endmacro
diff --git a/cfg/atari-xex.cfg b/cfg/atari-xex.cfg
new file mode 100644 (file)
index 0000000..f0a6291
--- /dev/null
@@ -0,0 +1,24 @@
+FEATURES {
+    STARTADDRESS: default = $2E00;
+}
+SYMBOLS {
+    __STARTADDRESS__: type = export, value = %S;
+}
+MEMORY {
+    ZP:      file = "", define = yes, start = $0082, size = $007E;
+    MAIN:    file = %O, define = yes, start = %S,    size = $BC20 - %S;
+}
+FILES {
+    %O: format = atari;
+}
+FORMATS {
+    atari: runad = start;
+}
+SEGMENTS {
+    ZEROPAGE: load = ZP,      type = zp,  optional = yes;
+    EXTZP:    load = ZP,      type = zp,  optional = yes; # to enable modules to be able to link to C and assembler programs
+    CODE:     load = MAIN,    type = rw,                  define = yes;
+    RODATA:   load = MAIN,    type = ro   optional = yes;
+    DATA:     load = MAIN,    type = rw   optional = yes;
+    BSS:      load = MAIN,    type = bss, optional = yes, define = yes;
+}
index 14ae303111cad8dca0d0275f01ec92a60a24cbc9..db897133eb6208675487cb9a2d8057227e411e3f 100644 (file)
@@ -2,7 +2,7 @@ SYMBOLS {
     __ORIXHDR__:   type = import;
     __STACKSIZE__: type = weak, value = $0800; # 2K stack
     __GRAB__:      type = weak, value = 0;     # 0=don't grab graphics RAM, 1=grab graphics RAM
-    __RAMEND__:    type = weak, value = $9800 + $1C00 * __GRAB__;              
+    __RAMEND__:    type = weak, value = $9800 + $1C00 * __GRAB__;
 }
 MEMORY {
     ZP:      file = "", define = yes, start = $00B0,            size = $003A;
index 80293d82f6df41b40310e686cedf45187c1caabb..346377b36493519e48a5ff477de9253ae1d818e1 100644 (file)
@@ -203,6 +203,18 @@ is <it/left out/, keep this in mind.
 The values you assign to the two symbols <tt/__AUTOSTART__/ and <tt/__EXEHDR__/
 don't matter.
 
+<sect2><tt/atari-xex.cfg/<p>
+
+This config file allows writing multi segment binaries easily, without having to
+write the header explicitly on each segment.
+
+It is similar to the <tt/atari-asm.cfg/ above, but uses the ATARI (xex) file
+format support on LD65 instead of the standard binary output, so it does not
+have the <tt/__AUTOSTART/ nor the <tt/__EXEHDR__/ symbols.
+
+Note that each <tt/MEMORY/ area in the configuration file will have it's own
+segment in the output file with the correct headers.
+
 <sect2><tt/atari-cart.cfg/<p>
 
 This config file can be used to create 8K or 16K cartridges. It's suited both
index e0566fda4ca09cfe6348916dade11cc10ff4ad8f..25c46c4c2604e61cd91d40ae1e02d1a356e1aca4 100644 (file)
@@ -2835,19 +2835,18 @@ Here's a list of all control commands and a description, what they do:
 
     Allow C-style backslash escapes within string constants to embed
     special characters. The following escapes are accepted:
-
-<itemize>
-<item><tt>\\</tt> backslash (<tt>$5C</tt>)
-<item><tt>\'</tt> single quote (<tt>$27</tt>)
-<item><tt>\&quot;</tt> double quote (<tt>$22</tt>)
-<item><tt>\t</tt> tab (<tt>$09</tt>)
-<item><tt>\r</tt> carriage return (<tt>$0D</tt>)
-<item><tt>\n</tt> newline (<tt>$0A</tt>)
-<item><tt>\xNN</tt>  (<tt>$NN</tt>)
-</itemize>
-
-    Note that <tt>\n</tt> maps to ASCII <tt>$0A</tt>, not a platform specific
-    line ending character.
+    <itemize>
+    <item><tt>\\</tt> backslash (<tt>$5C</tt>)
+    <item><tt>\'</tt> single quote (<tt>$27</tt>)
+    <item><tt>\&quot;</tt> double quote (<tt>$22</tt>)
+    <item><tt>\t</tt> tab (<tt>$09</tt>)
+    <item><tt>\r</tt> carriage return (<tt>$0D</tt>)
+    <item><tt>\n</tt> newline (<tt>$0A</tt>)
+    <item><tt>\xNN</tt>  (<tt>$NN</tt>)
+    </itemize>
+
+    Note that string escapes are converted to platform-specific characters in
+    the same way that other characters are converted.
 
   <tag><tt>ubiquitous_idents</tt><label id="ubiquitous_idents"></tag>
 
index beb2144bfa728e21023763b4a84e26db20a0fe04..0230b517fbc4969c148b91e44ef9672bd7aefe35 100644 (file)
@@ -894,7 +894,7 @@ look like this:
         }
 </verb></tscreen>
 
-The only other available output format is the o65 format specified by Andre
+There are two other available formats, one is the o65 format specified by Andre
 Fachat (see the <url url="http://www.6502.org/users/andre/o65/fileformat.html"
 name="6502 binary relocation format specification">). It is defined like this:
 
@@ -904,7 +904,20 @@ name="6502 binary relocation format specification">). It is defined like this:
         }
 </verb></tscreen>
 
-The necessary o65 attributes are defined in a special section labeled
+The other format available is the Atari (xex) segmented file format, this is
+the standard format used by Atari DOS 2.0 and upward file managers in the Atari
+8-bit computers, and it is defined like this:
+
+<tscreen><verb>
+        FILES {
+            %O: format = atari;
+        }
+</verb></tscreen>
+
+In the Atari segmented file format, the linker will write each <tt/MEMORY/ area
+as a new segment, including a header with the start and end address.
+
+The necessary o65 or Atari attributes are defined in a special section labeled
 <ref id="FORMAT" name="FORMAT">.
 
 
@@ -925,6 +938,15 @@ has several attributes that may be defined here.
     }
 </verb></tscreen>
 
+The Atari file format has only one attribute, <tt/RUNAD/ that allows to specify
+a symbol as the run address of the binary. If the attribute is omiteed, no run
+address is specified.
+
+<tscreen><verb>
+    FORMATS {
+        atari: runad = _start;
+    }
+</verb></tscreen>
 
 
 <sect1>The FEATURES section<label id="FEATURES"><p>
index c89c04d6cb93d34e41b128577ef4faaff8a50ce4..67c08ea182d9997219a0d4409a4cd356bb1e9371 100644 (file)
 /* TIA write / read registers */
 struct __tia {
     union {
-       unsigned char vsync;
-       unsigned char cxm0p;
+        unsigned char vsync;
+        unsigned char cxm0p;
     };
     union {
-       unsigned char vblank;
-       unsigned char cxm1p;
+        unsigned char vblank;
+        unsigned char cxm1p;
     };
     union {
-       unsigned char wsync;
-       unsigned char cxp0fb;
+        unsigned char wsync;
+        unsigned char cxp0fb;
     };
     union {
-       unsigned char rsync;
-       unsigned char cxp1fb;
+        unsigned char rsync;
+        unsigned char cxp1fb;
     };
     union {
-       unsigned char nusiz0;
-       unsigned char cxm0fb;
+        unsigned char nusiz0;
+        unsigned char cxm0fb;
     };
     union {
-       unsigned char nusiz1;
-       unsigned char cxm1fb;
+        unsigned char nusiz1;
+        unsigned char cxm1fb;
     };
     union {
-       unsigned char colup0;
-       unsigned char cxblpf;
+        unsigned char colup0;
+        unsigned char cxblpf;
     };
     union {
-       unsigned char colup1;
-       unsigned char cxppmm;
+        unsigned char colup1;
+        unsigned char cxppmm;
     };
     union {
-       unsigned char colupf;
-       unsigned char inpt0;
+        unsigned char colupf;
+        unsigned char inpt0;
     };
     union {
-       unsigned char colubk;
-       unsigned char inpt1;
+        unsigned char colubk;
+        unsigned char inpt1;
     };
     union {
-       unsigned char ctrlpf;
-       unsigned char inpt2;
+        unsigned char ctrlpf;
+        unsigned char inpt2;
     };
     union {
-       unsigned char refp0;
-       unsigned char inpt3;
+        unsigned char refp0;
+        unsigned char inpt3;
     };
     union {
-       unsigned char refp1;
-       unsigned char inpt4;
+        unsigned char refp1;
+        unsigned char inpt4;
     };
     union {
-       unsigned char pf0;
-       unsigned char inpt5;
+        unsigned char pf0;
+        unsigned char inpt5;
     };
     unsigned char pf1;
     unsigned char pf2;
diff --git a/include/c64_screen_charmap.h b/include/c64_screen_charmap.h
new file mode 100644 (file)
index 0000000..861ad27
--- /dev/null
@@ -0,0 +1,290 @@
+/*****************************************************************************/
+/*                                                                           */
+/* c64_screen_charmap.h                                                      */
+/*                                                                           */
+/* (c) Copyright 2019, Gerhard W. Gruber (sparhawk@gmx.at)                   */
+/*                                                                           */
+/* When using C64 mode, this include converts the characters                 */
+/* from PETSCII to screen mapping, so you can write directly to              */
+/* the screen memory.                                                        */
+/*                                                                           */
+/* If this include is used, no additional macros are needed                  */
+/*                                                                           */
+/*****************************************************************************/
+
+/* No include guard here! Multiple use in one file may be intentional. */
+
+// Char $00 ... $1F -> c + 128
+#pragma warn (remap-zero, push, off)
+#pragma charmap ($00, $80)
+#pragma warn (remap-zero, pop)
+
+#pragma charmap ($01, $81)
+#pragma charmap ($02, $82)
+#pragma charmap ($03, $83)
+#pragma charmap ($04, $84)
+#pragma charmap ($05, $85)
+#pragma charmap ($06, $86)
+#pragma charmap ($07, $87)
+#pragma charmap ($08, $88)
+#pragma charmap ($09, $89)
+#pragma charmap ($0A, $8A)
+#pragma charmap ($0B, $8B)
+#pragma charmap ($0C, $8C)
+#pragma charmap ($0D, $8D)
+#pragma charmap ($0E, $8E)
+#pragma charmap ($0F, $8F)
+#pragma charmap ($10, $90)
+#pragma charmap ($11, $91)
+#pragma charmap ($12, $92)
+#pragma charmap ($13, $93)
+#pragma charmap ($14, $94)
+#pragma charmap ($15, $95)
+#pragma charmap ($16, $96)
+#pragma charmap ($17, $97)
+#pragma charmap ($18, $98)
+#pragma charmap ($19, $99)
+#pragma charmap ($1A, $9A)
+#pragma charmap ($1B, $9B)
+#pragma charmap ($1C, $9C)
+#pragma charmap ($1D, $9D)
+#pragma charmap ($1E, $9E)
+#pragma charmap ($1F, $9F)
+
+// Char $20 ... $3F -> c = c
+#pragma charmap ($20, $20)
+#pragma charmap ($21, $21)
+#pragma charmap ($22, $22)
+#pragma charmap ($23, $23)
+#pragma charmap ($24, $24)
+#pragma charmap ($25, $25)
+#pragma charmap ($26, $26)
+#pragma charmap ($27, $27)
+#pragma charmap ($28, $28)
+#pragma charmap ($29, $29)
+#pragma charmap ($2A, $2A)
+#pragma charmap ($2B, $2B)
+#pragma charmap ($2C, $2C)
+#pragma charmap ($2D, $2D)
+#pragma charmap ($2E, $2E)
+#pragma charmap ($2F, $2F)
+#pragma charmap ($30, $30)
+#pragma charmap ($31, $31)
+#pragma charmap ($32, $32)
+#pragma charmap ($33, $33)
+#pragma charmap ($34, $34)
+#pragma charmap ($35, $35)
+#pragma charmap ($36, $36)
+#pragma charmap ($37, $37)
+#pragma charmap ($38, $38)
+#pragma charmap ($39, $39)
+#pragma charmap ($3A, $3A)
+#pragma charmap ($3B, $3B)
+#pragma charmap ($3C, $3C)
+#pragma charmap ($3D, $3D)
+#pragma charmap ($3E, $3E)
+#pragma charmap ($3F, $3F)
+
+// Char $40 ... $5F -> c - 64
+#pragma charmap ($40, $00)
+#pragma charmap ($41, $01)
+#pragma charmap ($42, $02)
+#pragma charmap ($43, $03)
+#pragma charmap ($44, $04)
+#pragma charmap ($45, $05)
+#pragma charmap ($46, $06)
+#pragma charmap ($47, $07)
+#pragma charmap ($48, $08)
+#pragma charmap ($49, $09)
+#pragma charmap ($4A, $0A)
+#pragma charmap ($4B, $0B)
+#pragma charmap ($4C, $0C)
+#pragma charmap ($4D, $0D)
+#pragma charmap ($4E, $0E)
+#pragma charmap ($4F, $0F)
+#pragma charmap ($50, $10)
+#pragma charmap ($51, $11)
+#pragma charmap ($52, $12)
+#pragma charmap ($53, $13)
+#pragma charmap ($54, $14)
+#pragma charmap ($55, $15)
+#pragma charmap ($56, $16)
+#pragma charmap ($57, $17)
+#pragma charmap ($58, $18)
+#pragma charmap ($59, $19)
+#pragma charmap ($5A, $1A)
+#pragma charmap ($5B, $1B)
+#pragma charmap ($5C, $1C)
+#pragma charmap ($5D, $1D)
+#pragma charmap ($5E, $1E)
+#pragma charmap ($5F, $1F)
+
+// Char $60 ... $7F -> c - 32
+#pragma charmap ($60, $40)
+#pragma charmap ($61, $41)
+#pragma charmap ($62, $42)
+#pragma charmap ($63, $43)
+#pragma charmap ($64, $44)
+#pragma charmap ($65, $45)
+#pragma charmap ($66, $46)
+#pragma charmap ($67, $47)
+#pragma charmap ($68, $48)
+#pragma charmap ($69, $49)
+#pragma charmap ($6A, $4A)
+#pragma charmap ($6B, $4B)
+#pragma charmap ($6C, $4C)
+#pragma charmap ($6D, $4D)
+#pragma charmap ($6E, $4E)
+#pragma charmap ($6F, $4F)
+#pragma charmap ($70, $50)
+#pragma charmap ($71, $51)
+#pragma charmap ($72, $52)
+#pragma charmap ($73, $53)
+#pragma charmap ($74, $54)
+#pragma charmap ($75, $55)
+#pragma charmap ($76, $56)
+#pragma charmap ($77, $57)
+#pragma charmap ($78, $58)
+#pragma charmap ($79, $59)
+#pragma charmap ($7A, $5A)
+#pragma charmap ($7B, $5B)
+#pragma charmap ($7C, $5C)
+#pragma charmap ($7D, $5D)
+#pragma charmap ($7E, $5E)
+#pragma charmap ($7F, $5F)
+
+// Char $80 ... $9F -> c + 64
+#pragma charmap ($80, $C0)
+#pragma charmap ($81, $C1)
+#pragma charmap ($82, $C2)
+#pragma charmap ($83, $C3)
+#pragma charmap ($84, $C4)
+#pragma charmap ($85, $C5)
+#pragma charmap ($86, $C6)
+#pragma charmap ($87, $C7)
+#pragma charmap ($88, $C8)
+#pragma charmap ($89, $C9)
+#pragma charmap ($8A, $CA)
+#pragma charmap ($8B, $CB)
+#pragma charmap ($8C, $CC)
+#pragma charmap ($8D, $CD)
+#pragma charmap ($8E, $CE)
+#pragma charmap ($8F, $CF)
+#pragma charmap ($90, $D0)
+#pragma charmap ($91, $D1)
+#pragma charmap ($92, $D2)
+#pragma charmap ($93, $D3)
+#pragma charmap ($94, $D4)
+#pragma charmap ($95, $D5)
+#pragma charmap ($96, $D6)
+#pragma charmap ($97, $D7)
+#pragma charmap ($98, $D8)
+#pragma charmap ($99, $D9)
+#pragma charmap ($9A, $DA)
+#pragma charmap ($9B, $DB)
+#pragma charmap ($9C, $DC)
+#pragma charmap ($9D, $DD)
+#pragma charmap ($9E, $DE)
+#pragma charmap ($9F, $DF)
+
+// Char $A0 ... $BF -> c - 64
+#pragma charmap ($A0, $60)
+#pragma charmap ($A1, $61)
+#pragma charmap ($A2, $62)
+#pragma charmap ($A3, $63)
+#pragma charmap ($A4, $64)
+#pragma charmap ($A5, $65)
+#pragma charmap ($A6, $66)
+#pragma charmap ($A7, $67)
+#pragma charmap ($A8, $68)
+#pragma charmap ($A9, $69)
+#pragma charmap ($AA, $6A)
+#pragma charmap ($AB, $6B)
+#pragma charmap ($AC, $6C)
+#pragma charmap ($AD, $6D)
+#pragma charmap ($AE, $6E)
+#pragma charmap ($AF, $6F)
+#pragma charmap ($B0, $70)
+#pragma charmap ($B1, $71)
+#pragma charmap ($B2, $72)
+#pragma charmap ($B3, $73)
+#pragma charmap ($B4, $74)
+#pragma charmap ($B5, $75)
+#pragma charmap ($B6, $76)
+#pragma charmap ($B7, $77)
+#pragma charmap ($B8, $78)
+#pragma charmap ($B9, $79)
+#pragma charmap ($BA, $7A)
+#pragma charmap ($BB, $7B)
+#pragma charmap ($BC, $7C)
+#pragma charmap ($BD, $7D)
+#pragma charmap ($BE, $7E)
+#pragma charmap ($BF, $7F)
+
+// Char $C0 ... $DF -> c - 128
+#pragma charmap ($C0, $40)
+#pragma charmap ($C1, $41)
+#pragma charmap ($C2, $42)
+#pragma charmap ($C3, $43)
+#pragma charmap ($C4, $44)
+#pragma charmap ($C5, $45)
+#pragma charmap ($C6, $46)
+#pragma charmap ($C7, $47)
+#pragma charmap ($C8, $48)
+#pragma charmap ($C9, $49)
+#pragma charmap ($CA, $4A)
+#pragma charmap ($CB, $4B)
+#pragma charmap ($CC, $4C)
+#pragma charmap ($CD, $4D)
+#pragma charmap ($CE, $4E)
+#pragma charmap ($CF, $4F)
+#pragma charmap ($D0, $50)
+#pragma charmap ($D1, $51)
+#pragma charmap ($D2, $52)
+#pragma charmap ($D3, $53)
+#pragma charmap ($D4, $54)
+#pragma charmap ($D5, $55)
+#pragma charmap ($D6, $56)
+#pragma charmap ($D7, $57)
+#pragma charmap ($D8, $58)
+#pragma charmap ($D9, $59)
+#pragma charmap ($DA, $5A)
+#pragma charmap ($DB, $5B)
+#pragma charmap ($DC, $5C)
+#pragma charmap ($DD, $5D)
+#pragma charmap ($DE, $5E)
+#pragma charmap ($DF, $5F)
+
+// Char $E0 ... $FE -> c - 128
+#pragma charmap ($E0, $60)
+#pragma charmap ($E1, $61)
+#pragma charmap ($E2, $62)
+#pragma charmap ($E3, $63)
+#pragma charmap ($E4, $64)
+#pragma charmap ($E5, $65)
+#pragma charmap ($E6, $66)
+#pragma charmap ($E7, $67)
+#pragma charmap ($E8, $68)
+#pragma charmap ($E9, $69)
+#pragma charmap ($EA, $6A)
+#pragma charmap ($EB, $6B)
+#pragma charmap ($EC, $6C)
+#pragma charmap ($ED, $6D)
+#pragma charmap ($EE, $6E)
+#pragma charmap ($EF, $6F)
+#pragma charmap ($F0, $70)
+#pragma charmap ($F1, $71)
+#pragma charmap ($F2, $72)
+#pragma charmap ($F3, $73)
+#pragma charmap ($F4, $74)
+#pragma charmap ($F5, $75)
+#pragma charmap ($F6, $76)
+#pragma charmap ($F7, $77)
+#pragma charmap ($F8, $78)
+#pragma charmap ($F9, $79)
+#pragma charmap ($FA, $7A)
+#pragma charmap ($FB, $7B)
+#pragma charmap ($FC, $7C)
+#pragma charmap ($FD, $7D)
+#pragma charmap ($FE, $7E)
+#pragma charmap ($FF, $5E)
index f8ba24551200207bae0b2adf09f3f64d16a0fbb6..5d8a5cd121d01f27745a16d8b6c1abcdfc62b8b9 100644 (file)
@@ -134,6 +134,7 @@ YPosWrk:        .res    2
 irq_enabled:    .res    1               ; flag indicating that the high frequency polling interrupt is enabled
 old_porta_vbi:  .res    1               ; previous PORTA value of the VBI interrupt (IRQ)
 how_long:       .res    1               ; counter for how many VBI interrupts the mouse hasn't been moved
+in_irq:         .res    1               ; flag indicating high-frequency polling interrupt is active
 
 .if .defined (AMIGA_MOUSE) .or .defined (ST_MOUSE)
 dumx:           .res    1
@@ -145,11 +146,11 @@ oldval:         .res    1
 .endif
 
 .ifndef __ATARIXL__
-OldT1:          .res    2
+OldT2:          .res    2
 .else
 
 .data
-set_VTIMR1_handler:
+set_VTIMR2_handler:
                 .byte   $4C, 0, 0
 .endif
 
@@ -226,29 +227,29 @@ INSTALL:
 
         ; Setup pointer to wrapper install/deinstall function.
         lda     libref
-        sta     set_VTIMR1_handler+1
+        sta     set_VTIMR2_handler+1
         lda     libref+1
-        sta     set_VTIMR1_handler+2
+        sta     set_VTIMR2_handler+2
 
         ; Install my handler.
         sec
-        lda     #<T1Han
-        ldx     #>T1Han
-        jsr     set_VTIMR1_handler
+        lda     #<T2Han
+        ldx     #>T2Han
+        jsr     set_VTIMR2_handler
 
 .else
 
-        lda     VTIMR1
-        sta     OldT1
-        lda     VTIMR1+1
-        sta     OldT1+1
+        lda     VTIMR2
+        sta     OldT2
+        lda     VTIMR2+1
+        sta     OldT2+1
 
         php
         sei
-        lda     #<T1Han
-        sta     VTIMR1
-        lda     #>T1Han
-        sta     VTIMR1+1
+        lda     #<T2Han
+        sta     VTIMR2
+        lda     #>T2Han
+        sta     VTIMR2+1
         plp
 
 .endif
@@ -257,20 +258,12 @@ INSTALL:
         sta     AUDCTL
 
         lda     #0
-        sta     AUDC1
+        sta     AUDC2
 
         lda     #15
-        sta     AUDF1
+        sta     AUDF2
         sta     STIMER
 
-.if 0   ; the IRQ will now be dynamically enabled when the mouse is moved
-        lda     POKMSK
-        ora     #%00000001              ; timer 1 enable
-        sta     POKMSK
-        sta     IRQEN
-        sta     irq_enabled
-.endif
-
         lda     PORTA
         and     #$0f
         sta     old_porta_vbi
@@ -290,23 +283,23 @@ UNINSTALL:
 ; uninstall timer irq routine
 
         lda     POKMSK
-        and     #%11111110              ; timer 1 disable
+        and     #%11111101              ; timer 2 disable
         sta     IRQEN
         sta     POKMSK
 
 .ifdef __ATARIXL__
 
         clc
-        jsr     set_VTIMR1_handler
+        jsr     set_VTIMR2_handler
 
 .else
 
         php
         sei
-        lda     OldT1
-        sta     VTIMR1
-        lda     OldT1+1
-        sta     VTIMR1+1
+        lda     OldT2
+        sta     VTIMR2
+        lda     OldT2+1
+        sta     VTIMR2+1
         plp
 
 .endif
@@ -503,7 +496,7 @@ IRQ:    lda     PORTA                   ; mouse port contents
 ; Turn mouse polling IRQ back on
 
         lda     POKMSK
-        ora     #%00000001              ; timer 1 enable
+        ora     #%00000010              ; timer 2 enable
         sta     POKMSK
         sta     IRQEN
         sta     irq_enabled
@@ -533,7 +526,7 @@ IRQ:    lda     PORTA                   ; mouse port contents
 
         sta     irq_enabled
         lda     POKMSK
-        and     #%11111110              ; timer 1 disable
+        and     #%11111101              ; timer 2 disable
         sta     IRQEN
         sta     POKMSK
 
@@ -620,13 +613,18 @@ IRQ:    lda     PORTA                   ; mouse port contents
 
 
 ;----------------------------------------------------------------------------
-; T1Han: Local IRQ routine to poll mouse
+; T2Han: Local IRQ routine to poll mouse
 ;
 
-T1Han:  lda     CRITIC                  ; if CRITIC flag is set, disable the
+T2Han:  lda     CRITIC                  ; if CRITIC flag is set, disable the
         bne     disable_me              ; high frequency polling IRQ, in order
                                         ; not to interfere with SIO I/O (e.g.
-                                        ; floppy access)
+                                        ; floppy access or serial I/O)
+
+        lda     in_irq                  ; handler entered again?
+        bne     skip                    ; yes, ignore this interrupt
+        inc     in_irq
+        cli                             ; enable IRQs so that we don't block them for too long
 
         tya
         pha
@@ -803,6 +801,8 @@ mmexit: sty     oldval
         tax
         pla
         tay
+        dec     in_irq
+skip:
 .ifdef  __ATARIXL__
         rts
 .else
@@ -819,7 +819,7 @@ mmexit: sty     oldval
 
 disable_me:
         lda     POKMSK
-        and     #%11111110              ; timer 1 disable
+        and     #%11111101              ; timer 2 disable
         sta     IRQEN
         sta     POKMSK
         lda     #0
index b75df93d1177065603d46787ed99e73f9d26417d..ac99d36fad2d2a006905ccae1cbd83e8698b4e72 100644 (file)
@@ -5,8 +5,8 @@
         .export         mouse_libref
 
 .ifdef __ATARIXL__
-        .import set_VTIMR1_handler
-mouse_libref    := set_VTIMR1_handler
+        .import set_VTIMR2_handler
+mouse_libref    := set_VTIMR2_handler
 .else
         .import _exit
 mouse_libref    := _exit
diff --git a/libsrc/atari/shadow_ram_timerirq2.s b/libsrc/atari/shadow_ram_timerirq2.s
new file mode 100644 (file)
index 0000000..b2cdaec
--- /dev/null
@@ -0,0 +1,81 @@
+;
+; Atari XL shadow RAM timer IRQ #2 handler
+;
+; Christian Groessler, chris@groessler.org, 2019
+;
+
+;DEBUG           =       1
+
+.ifdef __ATARIXL__
+
+SHRAM_HANDLERS  =       1
+                .include        "atari.inc"
+                .include        "romswitch.inc"
+                .export         set_VTIMR2_handler
+
+
+.segment "LOWBSS"
+
+VTIMR2_handler: .res    3
+
+
+.segment "BSS"
+
+old_VTIMR2_handler:
+                .res    2
+
+
+.segment "LOWCODE"
+
+; timer interrupt handler:
+; disable ROM, call user handler, enable ROM again
+
+my_VTIMR2_handler:
+                disable_rom_quick
+                jsr     VTIMR2_handler
+                enable_rom_quick
+                pla
+                rti
+
+.segment "CODE"
+
+; install or remove VTIMR2 handler
+; input: CF - 0/1 for remove/install handler
+;        AX - pointer to handler (if CF=1)
+; registers destroyed
+
+set_VTIMR2_handler:
+
+                bcc     @remove
+
+; install vector
+
+                stx     VTIMR2_handler+2
+                sta     VTIMR2_handler+1        ; save passed vector in low memory
+                lda     #$4C                    ; "JMP" opcode
+                sta     VTIMR2_handler
+
+                lda     VTIMR2
+                sta     old_VTIMR2_handler
+                lda     VTIMR2+1
+                sta     old_VTIMR2_handler+1
+
+                lda     #<my_VTIMR2_handler
+                php
+                sei
+                sta     VTIMR2
+                lda     #>my_VTIMR2_handler
+                sta     VTIMR2+1
+                plp
+                rts
+
+@remove:        php
+                sei
+                lda     old_VTIMR2_handler
+                sta     VTIMR2
+                lda     old_VTIMR2_handler+1
+                sta     VTIMR2+1
+                plp
+                rts
+
+.endif  ; .ifdef __ATARIXL__
index 51ccd5a4a1174e732c9d33c33c5277ef3ddc6919..ab6a8aef91909386823010c25f6b4b6ddb648862 100644 (file)
@@ -3,7 +3,7 @@
 ;
 ; unsigned char getcpu (void);
 ;
-       .include        "zeropage.inc"
+        .include        "zeropage.inc"
         .export         _getcpu
 
 ; ---------------------------------------------------------------------------
index 6a6b23318ab436eb3a2238ff271d716c31d43b6c..cad8814af241a706085763554835127ef0f009c0 100644 (file)
@@ -2,27 +2,27 @@
 ; jede jede@oric.org 2017-10-01
 ;
     .export    _cgetc
-   
+
     .import    cursor
-    
+
     .include   "telestrat.inc"
 
 .proc _cgetc
-        ; this routine could be quicker if we wrote in page 2 variables, 
+        ; this routine could be quicker if we wrote in page 2 variables,
         ; but it's better to use telemon routine in that case, because telemon can manage 4 I/O
         ldx     cursor       ; if cursor equal to 0, then switch off cursor
         beq     switchoff_cursor
-       
+
         ldx     #$00         ; x is the first screen
         BRK_TELEMON(XCSSCR)  ; display cursor
         jmp     loop         ; could be replaced by a bne/beq but 'jmp' is cleaner than a bne/beq which could expect some matters
-        
-switchoff_cursor:        
+
+switchoff_cursor:
         ; at this step X is equal to $00, X must be set, because it's the id of the screen (telestrat can handle 4 virtuals screen)
-        BRK_TELEMON(XCOSCR)  ; switch off cursor        
-        
-loop:   
+        BRK_TELEMON(XCOSCR)  ; switch off cursor
+
+loop:
         BRK_TELEMON XRD0     ; waits until key is pressed
         bcs     loop
         rts
-.endproc       
+.endproc
index 40e2c10b39722a89b445854c8602390ac9788e17..17f6327f0af31a0aecdbaa5cdec527aff7a4559a 100644 (file)
@@ -1,16 +1,16 @@
 ; jede jede@oric.org 2017-01-22
 
     .export         _close
-        
-    .import            addysp,popax
-        
-    .include        "zeropage.inc"             
+
+    .import         addysp,popax
+
+    .include        "zeropage.inc"
     .include        "telestrat.inc"
     .include        "errno.inc"
-    .include        "fcntl.inc"        
-       
+    .include        "fcntl.inc"
+
 ; int open (const char* name, int flags, ...);    /* May take a mode argument */
 .proc _close
-    BRK_TELEMON XCLOSE ; launch primitive ROM
+    BRK_TELEMON XCLOSE  ; launch primitive ROM
     rts
 .endproc
index 31c8ee205a790abc7226e0e5cd5b2e3baf7fa712..1f90a7ca59bcb067a3bf75edd9b4f3f3a75a1209 100644 (file)
@@ -1,16 +1,16 @@
 ;
 ; jede jede@oric.org 2017-02-25
-; 
+;
 
     .export    _clrscr
-       
+
     .importzp  sp
-       
+
     .include   "telestrat.inc"
 
 .proc _clrscr
     ; Switch to text mode
-    BRK_TELEMON(XTEXT) 
+    BRK_TELEMON(XTEXT)
 
     lda     #<SCREEN
     ldy     #>SCREEN
     ldx     #>(SCREEN+SCREEN_XSIZE*SCREEN_YSIZE)
     lda     #' '
     BRK_TELEMON XFILLM
-       
-       
+
+
     ; reset prompt position
     lda     #<(SCREEN+40)
     sta     ADSCRL
     lda     #>(SCREEN+40)
     sta     ADSCRH
-       
+
     ; reset display position
     lda     #$01
     sta     SCRY
     lda     #$00
-    sta     SCRX       
+    sta     SCRX
     rts
-.endproc       
+.endproc
index d6af0e4ddb1a26082c496ac28ccd05ff7a138294..f16c05b716a94e6c5399417f8cd14690c5dc7e3f 100644 (file)
@@ -2,9 +2,9 @@
 ; jede jede@oric.org 2017-02-25
 ;
     .export    _gotox
-       
+
     .import    popa
-       
+
     .importzp  sp
 
     .include   "telestrat.inc"
@@ -13,4 +13,4 @@
 .proc _gotox
    sta    SCRX
    rts
-.endproc       
+.endproc
index ed7101c802437ae6304fc3f8bf39b5fcb1d86f67..05ed71de7bc1399577a96ec76b7bc0a48886dc7f 100644 (file)
@@ -10,4 +10,4 @@
 .proc _gotoy
    sta     SCRY
    rts
-.endproc       
+.endproc
index 0c9e799dade03bfbeadb630343154f6327e079fa..b7ffb4ec7310151510cc122ed3361bebe79f95da 100644 (file)
@@ -24,28 +24,28 @@ initmainargs:
 
         ldx     #0      ; Limit the length
 L0:     lda     BUFEDT,x
-        beq    L3
-        cmp    #' '
-        bne    L1
-        lda    #0
-        beq    L3
+        beq     L3
+        cmp     #' '
+        bne     L1
+        lda     #0
+        beq     L3
 L1:     sta     name,x
         inx
-        cpx    #FNAME_LEN
+        cpx     #FNAME_LEN
         bne     L0
-        lda    #0
-L3:            
-        sta    name,x
+        lda     #0
+L3:
+        sta     name,x
         inc     __argc          ; argc always is equal to, at least, 1
 
-               
+
         ldy     #1 * 2          ; Point to second argv slot
-               
+
 next:   lda     BUFEDT,x
         beq     done            ; End of line reached
         inx
         cmp     #' '            ; Skip leading spaces
-        beq     next           
+        beq     next
 
 found:  cmp     #'"'            ; Is the argument quoted?
         beq     setterm         ; Jump if so
@@ -58,12 +58,12 @@ setterm:sta     term            ; Set end of argument marker
 
         txa                     ; Get low byte
         clc
-        adc    #<BUFEDT
-        bcc    L4
-        inc    L5+1
+        adc     #<BUFEDT
+        bcc     L4
+        inc     L5+1
 L4:
         sta     argv,y          ; argv[y]=&arg
-L5:            
+L5:
         lda     #>BUFEDT
         sta     argv+1,y
         iny
@@ -92,16 +92,16 @@ argloop:lda     BUFEDT,x
 
         lda     __argc          ; Get low byte of argument count
         cmp     #MAXARGS        ; Maximum number of arguments reached?
-        bcc     next            ; Parse next one if not                
-               
-               
+        bcc     next            ; Parse next one if not
+
+
 done:   lda     #<argv
         ldx     #>argv
         sta     __argv
         stx     __argv + 1
         rts
-               
-               
+
+
 .segment        "INIT"
 
 term:   .res    1
@@ -113,8 +113,8 @@ name:   .res    FNAME_LEN + 1
 args:   .res    SCREEN_XSIZE * 2 - 1
 
 param_found:
-               .res 1
+                .res 1
 ; char* argv[MAXARGS+1]={name};
-argv:  
-               .addr   name
+argv:
+                .addr   name
         .res    MAXARGS * 2
index 08910f4f2c4a98ccb2d7cb1bb36221509569633c..f59d3d31a126320c716f6aa178cc18e819d3d0e0 100644 (file)
@@ -1,13 +1,13 @@
     .export    _open
-       
+
     .import    addysp,popax
-       
+
     .importzp  sp,tmp2,tmp3,tmp1
-       
-       
+
+
     .include   "telestrat.inc"
     .include   "errno.inc"
-    .include   "fcntl.inc"     
+    .include   "fcntl.inc"
 
 ; int open (const char* name, int flags, ...);    /* May take a mode argument */
 .proc _open
@@ -17,8 +17,8 @@
     dey                     ; ...checked (it generates a c compiler warning)
     dey
     dey
-    beq        parmok      ; Branch if parameter count ok
-    jsr        addysp      ; Fix stack, throw away unused parameters
+    beq         parmok      ; Branch if parameter count ok
+    jsr         addysp      ; Fix stack, throw away unused parameters
 
 ; Parameters ok. Pop the flags and save them into tmp3
 
@@ -26,8 +26,8 @@ parmok:
     jsr         popax       ; Get flagss
     sta         tmp3        ; save flags
 ; Get the filename from stack and parse it. Bail out if is not ok
-    jsr        popax       ; Get name
-    ldy         tmp3       ; Get flags again
-    BRK_TELEMON XOPEN      ; launch primitive ROM
+    jsr         popax       ; Get name
+    ldy         tmp3        ; Get flags again
+    BRK_TELEMON XOPEN       ; launch primitive ROM
     rts
 .endproc
index 75766cda22e44a5f7bc5efee99cdc9f824010f10..76de9d0acd2739bd1a07905eb71379c98e3ba292 100644 (file)
@@ -8,7 +8,7 @@
 
     .include        "zeropage.inc"
     .include        "telestrat.inc"
-               
+
 ;int read (int fd, void* buf, unsigned count);
 
 .proc   _read
     stx     PTR_READ_DEST+1
     sta     ptr2 ; in order to calculate nb of bytes read
     stx     ptr2+1 ;
-    
+
     ; jsr popax ; fp pointer don't care in this version
 
-    lda     ptr1 ; 
+    lda     ptr1 ;
     ldy     ptr1+1 ;
     BRK_TELEMON     XFREAD ; calls telemon30 routine
     ;  compute nb of bytes read
     lda     PTR_READ_DEST+1
     sec
     sbc     ptr2+1
-    tax                        
+    tax
     lda     PTR_READ_DEST
     sec
     sbc     ptr2
     ; Here A and X contains number of bytes read
     rts
 .endproc
-
-
index 0dd5139e131b998b9a7e615746acfcf0e3133cd0..8616003c840b72a13858abf1f741ab439dd9d136 100644 (file)
@@ -2,7 +2,7 @@
 ; jede jede@oric.org 2017-02-25
 ;
     .export    _wherex
-       
+
     .importzp  sp
 
     .include   "telestrat.inc"
@@ -11,4 +11,4 @@
     ldx    #$00
     lda    SCRX
     rts
-.endproc       
+.endproc
index 962608ca2997794be2323e5a4d3ffcd55b49251e..c05b5f5c8f8f6b027ca41fe7ec70b4f20d3d182f 100644 (file)
@@ -1,12 +1,12 @@
 ;
 ; jede jede@oric.org 2017-02-25
-; 
+;
     .export    _wherey
-       
+
     .include   "telestrat.inc"
 
 .proc _wherey
     ldx    #$00
     lda    SCRY
     rts
-.endproc       
+.endproc
index 6498283fba87fe02b9e6fe9947979973f6ae0c1a..68aef42d6cd1c680f7a1f94821206e01adf2ea77 100644 (file)
         jsr     popax           ; get fd and discard
 
         ; if fd=0001 then it stdout
-        cpx    #0
-        beq    next
-        jmp    L1
-next:          
-        cmp    #1
-        beq    L1              
-               
+        cpx     #0
+        beq     next
+        jmp     L1
+next:
+        cmp     #1
+        beq     L1
+
         ; here it's a file opened
-        lda    ptr1
-        sta    PTR_READ_DEST
-        lda    ptr1+1
-        sta    PTR_READ_DEST+1
-        lda    ptr3
-        ldy    ptr3+1
+        lda     ptr1
+        sta     PTR_READ_DEST
+        lda     ptr1+1
+        sta     PTR_READ_DEST+1
+        lda     ptr3
+        ldy     ptr3+1
         BRK_TELEMON  XFWRITE
         ;  compute nb of bytes written
-       
+
 
         lda     PTR_READ_DEST+1
         sec
         sbc     ptr1+1
-        tax                    
+        tax
         lda     PTR_READ_DEST
         sec
         sbc     ptr1
         rts
-               
-               
+
+
 L1:     inc     ptr2
         bne     L2
         inc     ptr2+1
@@ -63,10 +63,10 @@ L2:     ldy     #0
         BRK_TELEMON  XWR0       ; macro send char to screen (channel 0 in telemon terms)
         lda     #$0D            ; return to the beggining of the line
         BRK_TELEMON  XWR0       ; macro
-       
+
 
         ldx     #$0D
-L3:     
+L3:
         BRK_TELEMON  XWR0       ; macro
 
         inc     ptr1
@@ -81,5 +81,3 @@ L9:     lda     ptr3
         rts
 
 .endproc
-
-
index e4f7893b7870550bddb88cb6fec2fc444add4802..4785ad90b7f6eaa0fb3fbd601cee1e25ad295fc5 100644 (file)
@@ -25,32 +25,32 @@ void main(void) {
     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) {}
+        // 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 0f7b459680031a7988876f245b3afba3acf96a32..a611f4f6a809ec0789c5c975bfc7876104e10b8e 100644 (file)
@@ -4256,7 +4256,7 @@ void g_initauto (unsigned Label, unsigned Size)
         AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
         AddCodeLine ("sta (sp),y");
         AddCodeLine ("iny");
-       AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size);
+        AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size);
         AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
     }
 }
@@ -4281,7 +4281,7 @@ void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size)
         AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
         AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
         AddCodeLine ("iny");
-       AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size);
+        AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size);
         AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
     } else {
         /* Use the easy way here: memcpy() */
index 1a24a08d990792cc1e43df1bb6362d184b0e5141..b05ef6122bb4fce4efc24bd4f649999e395f16cc 100644 (file)
@@ -898,9 +898,9 @@ static void ParsePragma (void)
             FlagPragma (&B, &StaticLocals);
             break;
 
-       case PRAGMA_WRAPPED_CALL:
-           WrappedCallPragma(&B);
-           break;
+        case PRAGMA_WRAPPED_CALL:
+            WrappedCallPragma(&B);
+            break;
 
         case PRAGMA_WARN:
             WarnPragma (&B);
index a7b1c668356fec428d9b23e3bb9fc9b3cd84521b..4e9cf08f44a7a783f2c3ea007fa5861b96176cf7 100644 (file)
@@ -47,8 +47,8 @@
 
 typedef struct IntPtrStack IntPtrStack;
 struct IntPtrInner {
-       long val;
-       void *ptr;
+        long val;
+        void *ptr;
 };
 struct IntPtrStack {
     unsigned    Count;
index c8e2472d3062283ab9721435ef0207c4e668270d..5b086e40c9bd93effe80886dc9dda0e39220d166 100644 (file)
@@ -103,6 +103,7 @@ extern target_t         Target;
 #define BINFMT_DEFAULT          0       /* Default (binary) */
 #define BINFMT_BINARY           1       /* Straight binary format */
 #define BINFMT_O65              2       /* Andre Fachats o65 format */
+#define BINFMT_ATARIEXE         3       /* Standard Atari binary load */
 
 
 
index f98da6119031be76357c590e5f58c43e41ef1759..a78f3128bc0f874752a818d9fac0d07dc0954c0c 100644 (file)
     <ClInclude Include="ld65\span.h" />
     <ClInclude Include="ld65\spool.h" />
     <ClInclude Include="ld65\tpool.h" />
+    <ClInclude Include="ld65\xex.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="ld65\asserts.c" />
     <ClCompile Include="ld65\span.c" />
     <ClCompile Include="ld65\spool.c" />
     <ClCompile Include="ld65\tpool.c" />
+    <ClCompile Include="ld65\xex.c" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
index a510f94b7d12ef94d8061ae8395c0a795b950f5d..f4f2678feb8219c106c46efdcf909e473b9040b7 100644 (file)
@@ -73,6 +73,7 @@ int RelocatableBinFmt (unsigned Format)
     switch (Format) {
 
         case BINFMT_BINARY:
+        case BINFMT_ATARIEXE:
             Reloc = 0;
             break;
 
index 099617ba0b84a797e64701f1d20cc92c08bd0058..fafbed290bf06c18cb4d9a5b57ebc9c212d8ab1f 100644 (file)
@@ -68,6 +68,7 @@
 #include "objdata.h"
 #include "scanner.h"
 #include "spool.h"
+#include "xex.h"
 
 
 
@@ -149,6 +150,7 @@ static Collection       CfgSymbols = STATIC_COLLECTION_INITIALIZER;
 /* Descriptor holding information about the binary formats */
 static BinDesc* BinFmtDesc      = 0;
 static O65Desc* O65FmtDesc      = 0;
+static XexDesc* XexFmtDesc      = 0;
 
 
 
@@ -543,6 +545,7 @@ static void ParseFiles (void)
         {   "FORMAT",   CFGTOK_FORMAT   },
     };
     static const IdentTok Formats [] = {
+        {   "ATARI",    CFGTOK_ATARIEXE },
         {   "O65",      CFGTOK_O65      },
         {   "BIN",      CFGTOK_BIN      },
         {   "BINARY",   CFGTOK_BIN      },
@@ -607,6 +610,10 @@ static void ParseFiles (void)
                             F->Format = BINFMT_O65;
                             break;
 
+                        case CFGTOK_ATARIEXE:
+                            F->Format = BINFMT_ATARIEXE;
+                            break;
+
                         default:
                             Error ("Unexpected format token");
                     }
@@ -995,6 +1002,66 @@ static void ParseO65 (void)
 
 
 
+static void ParseXex (void)
+/* Parse the o65 format section */
+{
+    static const IdentTok Attributes [] = {
+        {   "RUNAD",    CFGTOK_RUNAD            },
+    };
+
+    /* Remember the attributes read */
+    /* Bitmask to remember the attributes we got already */
+    enum {
+        atNone          = 0x0000,
+        atRunAd         = 0x0001,
+    };
+    unsigned AttrFlags = atNone;
+    Import *RunAd = 0;
+
+    /* Read the attributes */
+    while (CfgTok == CFGTOK_IDENT) {
+
+        /* Map the identifier to a token */
+        cfgtok_t AttrTok;
+        CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
+        AttrTok = CfgTok;
+
+        /* An optional assignment follows */
+        CfgNextTok ();
+        CfgOptionalAssign ();
+
+        /* Check which attribute was given */
+        switch (AttrTok) {
+
+            case CFGTOK_RUNAD:
+                /* Cannot have this attribute twice */
+                FlagAttr (&AttrFlags, atRunAd, "RUNAD");
+                /* We expect an identifier */
+                CfgAssureIdent ();
+                /* Generate an import for the symbol */
+                RunAd = InsertImport (GenImport (GetStrBufId (&CfgSVal), ADDR_SIZE_ABS));
+                /* Remember the file position */
+                CollAppend (&RunAd->RefLines, GenLineInfo (&CfgErrorPos));
+                /* Eat the identifier token */
+                CfgNextTok ();
+                break;
+
+            default:
+                FAIL ("Unexpected attribute token");
+
+        }
+
+        /* Skip an optional comma */
+        CfgOptionalComma ();
+    }
+
+    /* Set the RUNAD import if we have one */
+    if ( RunAd )
+        XexSetRunAd (XexFmtDesc, RunAd);
+}
+
+
+
 static void ParseFormats (void)
 /* Parse a target format section */
 {
@@ -1002,6 +1069,7 @@ static void ParseFormats (void)
         {   "O65",      CFGTOK_O65      },
         {   "BIN",      CFGTOK_BIN      },
         {   "BINARY",   CFGTOK_BIN      },
+        {   "ATARI",    CFGTOK_ATARIEXE },
     };
 
     while (CfgTok == CFGTOK_IDENT) {
@@ -1022,6 +1090,10 @@ static void ParseFormats (void)
                 ParseO65 ();
                 break;
 
+            case CFGTOK_ATARIEXE:
+                ParseXex ();
+                break;
+
             case CFGTOK_BIN:
                 /* No attribibutes available */
                 break;
@@ -1559,6 +1631,7 @@ void CfgRead (void)
     /* Create the descriptors for the binary formats */
     BinFmtDesc = NewBinDesc ();
     O65FmtDesc = NewO65Desc ();
+    XexFmtDesc = NewXexDesc ();
 
     /* If we have a config name given, open the file, otherwise we will read
     ** from a buffer.
@@ -2098,6 +2171,10 @@ void CfgWriteTarget (void)
                         O65WriteTarget (O65FmtDesc, F);
                         break;
 
+                    case BINFMT_ATARIEXE:
+                        XexWriteTarget (XexFmtDesc, F);
+                        break;
+
                     default:
                         Internal ("Invalid binary format: %u", F->Format);
 
index 2df952ebbb6aa8be7813437152e08e955cbb8601..77fa91da81a3031a2b54f61d04d6dd3e2d070f57 100644 (file)
@@ -93,6 +93,7 @@ typedef enum {
     CFGTOK_ID,
     CFGTOK_VERSION,
     CFGTOK_FORMAT,
+    CFGTOK_RUNAD,
 
     CFGTOK_LOAD,
     CFGTOK_RUN,
@@ -107,6 +108,7 @@ typedef enum {
     CFGTOK_ZP,
     CFGTOK_OVERWRITE,
 
+    CFGTOK_ATARIEXE,
     CFGTOK_O65,
     CFGTOK_BIN,
 
diff --git a/src/ld65/xex.c b/src/ld65/xex.c
new file mode 100644 (file)
index 0000000..18190c0
--- /dev/null
@@ -0,0 +1,391 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                   xex.c                                   */
+/*                                                                           */
+/*               Module to handle the Atari XEX binary format                */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2018 Daniel Serpell                                                   */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+/* common */
+#include "alignment.h"
+#include "print.h"
+#include "xmalloc.h"
+
+/* ld65 */
+#include "xex.h"
+#include "config.h"
+#include "exports.h"
+#include "expr.h"
+#include "error.h"
+#include "global.h"
+#include "fileio.h"
+#include "lineinfo.h"
+#include "memarea.h"
+#include "segments.h"
+#include "spool.h"
+
+
+
+/*****************************************************************************/
+/*                                   Data                                    */
+/*****************************************************************************/
+
+
+
+struct XexDesc {
+    unsigned    Undef;          /* Count of undefined externals */
+    FILE*       F;              /* Output file */
+    const char* Filename;       /* Name of output file */
+    Import*     RunAd;          /* Run Address */
+    unsigned long HeadPos;      /* Position in the file of current header */
+    unsigned long HeadEnd;      /* End address of current header */
+    unsigned long HeadSize;     /* Last header size, can be removed if zero */
+};
+
+
+
+/*****************************************************************************/
+/*                                   Code                                    */
+/*****************************************************************************/
+
+
+
+XexDesc* NewXexDesc (void)
+/* Create a new XEX format descriptor */
+{
+    /* Allocate memory for a new XexDesc struct */
+    XexDesc* D = xmalloc (sizeof (XexDesc));
+
+    /* Initialize the fields */
+    D->Undef    = 0;
+    D->F        = 0;
+    D->Filename = 0;
+    D->RunAd    = 0;
+    D->HeadPos  = 0;
+    D->HeadEnd  = 0;
+    D->HeadSize = 0;
+
+    /* Return the created struct */
+    return D;
+}
+
+
+
+void FreeXexDesc (XexDesc* D)
+/* Free a XEX format descriptor */
+{
+    xfree (D);
+}
+
+
+
+void XexSetRunAd (XexDesc* D, Import *RunAd)
+/* Set the RUNAD export */
+{
+    D->RunAd = RunAd;
+}
+
+
+
+static unsigned XexWriteExpr (ExprNode* E, int Signed, unsigned Size,
+                              unsigned long Offs attribute ((unused)),
+                              void* Data)
+/* Called from SegWrite for an expression. Evaluate the expression, check the
+** range and write the expression value to the file.
+*/
+{
+    /* There's a predefined function to handle constant expressions */
+    return SegWriteConstExpr (((XexDesc*)Data)->F, E, Signed, Size);
+}
+
+
+
+static void PrintNumVal (const char* Name, unsigned long V)
+/* Print a numerical value for debugging */
+{
+    Print (stdout, 2, "      %s = 0x%lx\n", Name, V);
+}
+
+
+
+static void XexStartSegment (XexDesc *D, unsigned long Addr, unsigned long Size)
+{
+    /* Skip segment without size */
+    if (!Size)
+        return;
+
+    /* Store current position */
+    unsigned long Pos = ftell (D->F);
+    unsigned long End = Addr + Size - 1;
+
+    /* See if last header can be expanded into this one */
+    if (D->HeadPos && ((D->HeadEnd + 1) == Addr)) {
+        /* Expand current header */
+        D->HeadEnd = End;
+        D->HeadSize += Size;
+        fseek (D->F, D->HeadPos + 2, SEEK_SET);
+        Write16 (D->F, End);
+        /* Seek to old position */
+        fseek (D->F, Pos, SEEK_SET);
+    }
+    else
+    {
+        if (D->HeadSize == 0) {
+            /* Last header had no data, replace */
+            Pos = D->HeadPos;
+            fseek (D->F, Pos, SEEK_SET);
+        }
+
+        /* If we are at start of file, write XEX heder */
+        if (Pos == 0)
+            Write16 (D->F, 0xFFFF);
+
+        /* Writes a new segment header */
+        D->HeadPos = ftell (D->F);
+        D->HeadEnd = End;
+        D->HeadSize = Size;
+        Write16 (D->F, Addr);
+        Write16 (D->F, End);
+    }
+}
+
+
+
+static void XexFakeSegment (XexDesc *D, unsigned long Addr)
+{
+    /* See if last header can be expanded into this one, we are done */
+    if (D->HeadPos && ((D->HeadEnd + 1) == Addr))
+        return;
+
+    /* If we are at start of file, write XEX heder */
+    if (ftell (D->F) == 0)
+        Write16 (D->F, 0xFFFF);
+
+    /* Writes a new (invalid) segment header */
+    D->HeadPos = ftell (D->F);
+    D->HeadEnd = Addr - 1;
+    D->HeadSize = 0;
+    Write16 (D->F, Addr);
+    Write16 (D->F, D->HeadEnd);
+}
+
+
+
+static void XexWriteMem (XexDesc* D, MemoryArea* M)
+/* Write the segments of one memory area to a file */
+{
+    unsigned I;
+
+    /* Always write a segment header for each memory area */
+    D->HeadPos = 0;
+
+    /* Get the start address and size of this memory area */
+    unsigned long Addr = M->Start;
+
+    /* Walk over all segments in this memory area */
+    for (I = 0; I < CollCount (&M->SegList); ++I) {
+
+        int DoWrite;
+
+        /* Get the segment */
+        SegDesc* S = CollAtUnchecked (&M->SegList, I);
+
+        /* Keep the user happy */
+        Print (stdout, 1, "    ATARI EXE Writing `%s'\n", GetString (S->Name));
+
+        /* Writes do only occur in the load area and not for BSS segments */
+        DoWrite = (S->Flags & SF_BSS) == 0      &&      /* No BSS segment */
+                   S->Load == M                 &&      /* LOAD segment */
+                   S->Seg->Dumped == 0;                 /* Not already written */
+
+        /* If this is the run memory area, we must apply run alignment. If
+        ** this is not the run memory area but the load memory area (which
+        ** means that both are different), we must apply load alignment.
+        ** Beware: DoWrite may be true even if this is the run memory area,
+        ** because it may be also the load memory area.
+        */
+        if (S->Run == M) {
+
+            /* Handle ALIGN and OFFSET/START */
+            if (S->Flags & SF_ALIGN) {
+                /* Align the address */
+                unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment);
+                if (DoWrite || (M->Flags & MF_FILL) != 0) {
+                    XexStartSegment (D, Addr, NewAddr - Addr);
+                    WriteMult (D->F, M->FillVal, NewAddr - Addr);
+                    PrintNumVal ("SF_ALIGN", NewAddr - Addr);
+                }
+                Addr = NewAddr;
+            } else if (S->Flags & (SF_OFFSET | SF_START)) {
+                unsigned long NewAddr = S->Addr;
+                if (S->Flags & SF_OFFSET) {
+                    /* It's an offset, not a fixed address, make an address */
+                    NewAddr += M->Start;
+                }
+                if (DoWrite || (M->Flags & MF_FILL) != 0) {
+                    /* "overwrite" segments are not supported */
+                    if (S->Flags & SF_OVERWRITE) {
+                        Error ("ATARI file format does not support overwrite for segment '%s'.",
+                               GetString (S->Name));
+                    } else {
+                        XexStartSegment (D, Addr, NewAddr - Addr);
+                        WriteMult (D->F, M->FillVal, NewAddr-Addr);
+                        PrintNumVal ("SF_OFFSET", NewAddr - Addr);
+                    }
+                }
+                Addr = NewAddr;
+            }
+
+        } else if (S->Load == M) {
+
+            /* Handle ALIGN_LOAD */
+            if (S->Flags & SF_ALIGN_LOAD) {
+                /* Align the address */
+                unsigned long NewAddr = AlignAddr (Addr, S->LoadAlignment);
+                if (DoWrite || (M->Flags & MF_FILL) != 0) {
+                    XexStartSegment (D, Addr, NewAddr - Addr);
+                    WriteMult (D->F, M->FillVal, NewAddr - Addr);
+                    PrintNumVal ("SF_ALIGN_LOAD", NewAddr - Addr);
+                }
+                Addr = NewAddr;
+            }
+
+        }
+
+        /* Now write the segment to disk if it is not a BSS type segment and
+        ** if the memory area is the load area.
+        */
+        if (DoWrite) {
+            /* Start a segment with only one byte, will fix later */
+            XexFakeSegment (D, Addr);
+            unsigned long P = ftell (D->F);
+            SegWrite (D->Filename, D->F, S->Seg, XexWriteExpr, D);
+            unsigned long Size = ftell (D->F) - P;
+            /* Fix segment size */
+            XexStartSegment (D, Addr, Size);
+            PrintNumVal ("Wrote", Size);
+        } else if (M->Flags & MF_FILL) {
+            XexStartSegment (D, Addr, S->Seg->Size);
+            WriteMult (D->F, S->Seg->FillVal, S->Seg->Size);
+            PrintNumVal ("Filled", (unsigned long) S->Seg->Size);
+        }
+
+        /* If this was the load memory area, mark the segment as dumped */
+        if (S->Load == M) {
+            S->Seg->Dumped = 1;
+        }
+
+        /* Calculate the new address */
+        Addr += S->Seg->Size;
+    }
+
+    /* If a fill was requested, fill the remaining space */
+    if ((M->Flags & MF_FILL) != 0 && M->FillLevel < M->Size) {
+        unsigned long ToFill = M->Size - M->FillLevel;
+        Print (stdout, 2, "    Filling 0x%lx bytes with 0x%02x\n",
+               ToFill, M->FillVal);
+        XexStartSegment (D, Addr, ToFill);
+        WriteMult (D->F, M->FillVal, ToFill);
+        M->FillLevel = M->Size;
+    }
+
+    /* If the last segment is empty, remove */
+    if (D->HeadSize == 0 && D->HeadPos) {
+        fseek (D->F, D->HeadPos, SEEK_SET);
+    }
+}
+
+
+
+static int XexUnresolved (unsigned Name attribute ((unused)), void* D)
+/* Called if an unresolved symbol is encountered */
+{
+    /* Unresolved symbols are an error in XEX format. Bump the counter
+    ** and return zero telling the caller that the symbol is indeed
+    ** unresolved.
+    */
+    ((XexDesc*) D)->Undef++;
+    return 0;
+}
+
+
+
+void XexWriteTarget (XexDesc* D, struct File* F)
+/* Write a XEX output file */
+{
+    unsigned I;
+
+    /* Place the filename in the control structure */
+    D->Filename = GetString (F->Name);
+
+    /* Check for unresolved symbols. The function XexUnresolved is called
+    ** if we get an unresolved symbol.
+    */
+    D->Undef = 0;               /* Reset the counter */
+    CheckUnresolvedImports (XexUnresolved, D);
+    if (D->Undef > 0) {
+        /* We had unresolved symbols, cannot create output file */
+        Error ("%u unresolved external(s) found - cannot create output file", D->Undef);
+    }
+
+    /* Open the file */
+    D->F = fopen (D->Filename, "wb");
+    if (D->F == 0) {
+        Error ("Cannot open `%s': %s", D->Filename, strerror (errno));
+    }
+
+    /* Keep the user happy */
+    Print (stdout, 1, "Opened `%s'...\n", D->Filename);
+
+    /* Dump all memory areas */
+    for (I = 0; I < CollCount (&F->MemoryAreas); ++I) {
+        /* Get this entry */
+        MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I);
+        Print (stdout, 1, "  ATARI EXE Dumping `%s'\n", GetString (M->Name));
+        XexWriteMem (D, M);
+    }
+
+    /* Write RUNAD at file end */
+    if (D->RunAd) {
+        Write16 (D->F, 0x2E0);
+        Write16 (D->F, 0x2E1);
+        Write16 (D->F, GetExportVal (D->RunAd->Exp));
+    }
+
+    /* Close the file */
+    if (fclose (D->F) != 0) {
+        Error ("Cannot write to `%s': %s", D->Filename, strerror (errno));
+    }
+
+    /* Reset the file and filename */
+    D->F        = 0;
+    D->Filename = 0;
+}
diff --git a/src/ld65/xex.h b/src/ld65/xex.h
new file mode 100644 (file)
index 0000000..c74f78e
--- /dev/null
@@ -0,0 +1,75 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                   xex.h                                   */
+/*                                                                           */
+/*               Module to handle the Atari EXE binary format                */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2018 Daniel Serpell                                                   */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef XEX_H
+#define XEX_H
+
+
+
+#include "config.h"
+#include "exports.h"
+
+
+
+/*****************************************************************************/
+/*                                   Data                                    */
+/*****************************************************************************/
+
+
+
+/* Structure describing the format */
+typedef struct XexDesc XexDesc;
+
+
+
+/*****************************************************************************/
+/*                                   Code                                    */
+/*****************************************************************************/
+
+
+
+XexDesc* NewXexDesc (void);
+/* Create a new XEX format descriptor */
+
+void FreeXexDesc (XexDesc* D);
+/* Free a XEX format descriptor */
+
+void XexWriteTarget (XexDesc* D, File* F);
+/* Write a XEX output file */
+
+void XexSetRunAd (XexDesc* D, Import *RunAd);
+/* Set the RUNAD export */
+
+
+/* End of xex.h */
+
+#endif
index bfbfbd78ce8b15e3475e5401e25ea5566c25d214..b3c06293a3f1cab3802df239dbd78e09f824cd21 100644 (file)
@@ -37,8 +37,6 @@
    BBRx, BBSx, RMBx, SMBx, WAI, and STP are unsupported
  * BCD flag handling equals 6502 (unchecked if bug is simulated or wrong for
    6502)
- * one cycle win for fetch-modify-write instructions ignored
-   (e.g., ROL abs,x takes only 6 cycles if no page break occurs)
 */
 
 #include "memory.h"
@@ -629,6 +627,8 @@ static void OPC_6502_1E (void)
     unsigned Val;
     Cycles = 7;
     Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+    if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
+        --Cycles;
     Val = MemReadByte (Addr) << 1;
     MemWriteByte (Addr, (unsigned char) Val);
     TEST_ZF (Val & 0xFF);
@@ -898,6 +898,8 @@ static void OPC_6502_3E (void)
     unsigned Val;
     Cycles = 7;
     Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+    if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
+        --Cycles;
     Val = MemReadByte (Addr);
     ROL (Val);
     MemWriteByte (Addr, Val);
@@ -1132,6 +1134,8 @@ static void OPC_6502_5E (void)
     unsigned char Val;
     Cycles = 7;
     Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+    if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
+        --Cycles;
     Val = MemReadByte (Addr);
     SET_CF (Val & 0x01);
     Val >>= 1;
@@ -1462,6 +1466,8 @@ static void OPC_6502_7E (void)
     unsigned Val;
     Cycles = 7;
     Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+    if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
+        --Cycles;
     Val = MemReadByte (Addr);
     ROR (Val);
     MemWriteByte (Addr, Val);
diff --git a/testcode/lib/atari/asm-xex.s b/testcode/lib/atari/asm-xex.s
new file mode 100644 (file)
index 0000000..d2a8d03
--- /dev/null
@@ -0,0 +1,51 @@
+; Sample using ATARI file format, by "atari-xex.cfg" linker configuration.
+;
+; This is a very simple example, shows a message to the screen, waits and
+; returns to DOS.
+;
+; Compile with:
+;    cl65 -tatari -Catari-xex.cfg asm-xex.s -o prog.xex
+
+        .include        "atari.inc"
+
+; Default RUNAD is "start", export that:
+        .export         start
+
+
+; Write string to screen
+.proc   puts
+        sta     ICBAL
+        stx     ICBAH
+        lda     #PUTREC
+        sta     ICCOM
+        ldx     #$FF
+        stx     ICBLL
+        inx
+        stx     ICBLH
+        jsr     CIOV
+        rts
+.endproc
+
+
+; Write a message and exit
+
+.proc   start
+        lda     #<msg
+        ldx     #>msg
+        jsr     puts
+
+
+        ; Delay before returning to DOS
+        lda     #0
+        tax
+loop:
+        inx
+        cpx     #$FF
+        adc     #0
+        bcc     loop
+
+        rts
+.endproc
+
+msg:    .byte   "Hello world", ATEOL
+
diff --git a/testcode/lib/atari/multi-xex.cfg b/testcode/lib/atari/multi-xex.cfg
new file mode 100644 (file)
index 0000000..18dfff8
--- /dev/null
@@ -0,0 +1,31 @@
+FEATURES {
+    STARTADDRESS: default = $2E00;
+}
+MEMORY {
+    ZP:      file = "", define = yes, start = $0082, size = $007E;
+    # First memory segment in file, load over COLOR registers:
+    COLOR:   file = %O, start = $2C4, size = 5;
+    # Second memory segment, load at page 6:
+    PAGE6:   file = %O, start = $600, size = 256;
+    # Third memory segment in file, load over SDLST register:
+    SDLST:   file = %O, start = $230, size = 2;
+    # Main segment, load at "STARTADDRESS"
+    MAIN:    file = %O, start = %S,   size = $BC20 - %S;
+}
+FILES {
+    %O: format = atari;
+}
+FORMATS {
+    atari: runad = start;
+}
+SEGMENTS {
+    ZEROPAGE: load = ZP,      type = zp,  optional = yes;
+    # Place segments in memory areas:
+    COLOR:    load = COLOR,   type = rw;
+    PAGE6:    load = PAGE6,   type = rw;
+    SDLST:    load = SDLST,   type = rw;
+    CODE:     load = MAIN,    type = rw;
+    RODATA:   load = MAIN,    type = ro   optional = yes;
+    DATA:     load = MAIN,    type = rw   optional = yes;
+    BSS:      load = MAIN,    type = bss, optional = yes, define = yes;
+}
diff --git a/testcode/lib/atari/multi-xex.s b/testcode/lib/atari/multi-xex.s
new file mode 100644 (file)
index 0000000..7957ddf
--- /dev/null
@@ -0,0 +1,63 @@
+; Multiple segment ATARI file format sample, using custom linker script.
+;
+; This sample defines a custom display-list screen with no code, writing all
+; memory areas directly.
+;
+; See the linker script (multi-xex.cfg) for the definition of memory areas and
+; segments.
+;
+; Compile with:
+;    cl65 -tatari -Cmulti-xex.cfg multi-xex.s -o prog.xex
+
+        .include        "atari.inc"
+
+        .macpack        atari
+
+; Default RUNAD is "start", export that:
+        .export         start
+
+
+; We load color values directly into registers
+        .segment        "COLOR"
+
+        .byte           $16     ; COLOR0
+        .byte           $46     ; COLOR1
+        .byte           $00     ; COLOR2
+        .byte           $6A     ; COLOR3
+        .byte           $82     ; COLOR4
+
+; We load our display list over page 6
+        .segment        "PAGE6"
+
+display_list:
+        .byte   DL_BLK8
+        .byte   DL_BLK8
+        .byte   DL_BLK8
+        .byte   DL_BLK8
+        .byte   DL_BLK8
+        .byte   DL_BLK8
+        .byte   DL_CHR20x8x2 | DL_LMS
+        .word   screen_memory
+        .byte   DL_CHR40x8x1
+        .byte   DL_JVB
+        .word   display_list
+
+screen_memory:
+        ; first text line: 20 bytes
+        scrcode   "    HeLlO wOrLd!    "
+        ; second text line, 40 bytes
+        .byte    0, 0, 0, 0, 0, 0, 0, 0,70,71,70,71,70,71,70,71,70,71,70,71
+        .byte   70,71,70,71,70,71,70,71,70,71,70,71, 0, 0, 0, 0, 0, 0, 0, 0
+
+; We write directly to the display list pointer
+        .segment        "SDLST"
+        .word   display_list
+
+; And we load our main program
+        .code
+
+.proc   start
+        ; Jump forever
+        jmp     start
+.endproc
+
index 3a8d72226eddaa0b530c1c32f3a68ace17e0dd83..56ed82a794be4ea372be5a9f535e6f285b355980 100644 (file)
@@ -13,7 +13,7 @@ psa:            .word 0
         .bss
 temp_x:         .byte 0
 temp_y:         .byte 0
-temp_a:                .byte 0
+temp_a:         .byte 0
 irq_count:      .byte 0
 nmi_count:      .byte 0
 psx:            .byte 0
@@ -419,4 +419,3 @@ printsign1:
         ldy     temp_y
         rts
 .endproc
-
index 2e316c4c6dceb5ca58ffb24ed3ed87e926868e51..ea8311d1925b1bc0e415530730c7c7cd74786674 100644 (file)
@@ -7,7 +7,7 @@
 **
 ** Compile with "-DSTATIC_MOUSE" to statically link all available drivers.
 ** Compile with "-DMOUSE_DRIVER=<driver_sym>" to statically link the given driver.
-**     E.g., -DMOUSE_DRIVER=atrsts_mou to just link with the Atari ST mouse driver.
+**     E.g., -DMOUSE_DRIVER=atrst_mou to just link with the Atari ST mouse driver.
 */