mirror of
https://github.com/cc65/cc65.git
synced 2024-06-19 14:29:40 +00:00
Compare commits
114 Commits
90df12f757
...
0d87fe403f
Author | SHA1 | Date | |
---|---|---|---|
|
0d87fe403f | ||
|
b993d88339 | ||
|
25967e65b5 | ||
|
a372ead4de | ||
|
081d18f7d7 | ||
|
a293920fb3 | ||
|
60c75bdb54 | ||
|
1fe12f112e | ||
|
a887b29ffb | ||
|
731f349b24 | ||
|
98767741ce | ||
|
9b2d27d1e1 | ||
|
23aa562094 | ||
|
5c3ff714ae | ||
|
86317711e0 | ||
|
8b71fafb84 | ||
|
3fd78208ba | ||
|
7a12399b39 | ||
|
294b034920 | ||
|
ab0eb4fe58 | ||
|
8d4946b3f4 | ||
|
3a7bd53956 | ||
|
8173c850fd | ||
|
4bde3afd80 | ||
|
7d6f3d24d4 | ||
|
8b172e05bc | ||
|
1deb9e52ae | ||
|
acff429eb8 | ||
|
6cf8ee8eb5 | ||
|
65bce9ecde | ||
|
014f85f226 | ||
|
788ae82d30 | ||
|
b04d79b1da | ||
|
3dfe033000 | ||
|
5acfb02794 | ||
|
934de685bc | ||
|
ce14f0f8ad | ||
|
a06431a8f9 | ||
|
eb503cc542 | ||
|
1fab179cb4 | ||
|
c4c6967e4a | ||
|
2a03e5d8c9 | ||
|
128f261c3a | ||
|
d5c84e7828 | ||
|
54b423a99e | ||
|
96d55e3703 | ||
|
a7ac9b7ef2 | ||
|
1e300bf768 | ||
|
ce606bb19e | ||
|
afd8ee627e | ||
|
2b97735d5d | ||
|
1a5a7d67a7 | ||
|
ba36071022 | ||
|
7594af553a | ||
|
7d7cf2d1e0 | ||
|
51b946bf25 | ||
|
0dd7b0c3a5 | ||
|
8682095f9f | ||
|
782dad23da | ||
|
aa6f850b8d | ||
|
a8b870555e | ||
|
65937684a0 | ||
|
ba6f9f5d3f | ||
|
4b9bf9bb98 | ||
|
f1d95f1f07 | ||
|
476591e8b7 | ||
|
f7388cfb79 | ||
|
ee3a542539 | ||
|
a2d722639f | ||
|
9ba270d97b | ||
|
34f37c873e | ||
|
ebf43ddb05 | ||
|
f0b5b02966 | ||
|
b87df9e1c6 | ||
|
1f820d0ae8 | ||
|
5d49fde788 | ||
|
3e01ac9b04 | ||
|
57e65a6bf6 | ||
|
13ddd734db | ||
|
2ba176372e | ||
|
6c7106c9d9 | ||
|
ea83b9fa53 | ||
|
ba75a2ac26 | ||
|
bea2e86210 | ||
|
998dfd6fa7 | ||
|
deaf27d6a8 | ||
|
01ee903cdf | ||
|
7a7e98d799 | ||
|
6a03fda453 | ||
|
b23a7ec407 | ||
|
83691f30c1 | ||
|
6bab3f921b | ||
|
ad90a3a421 | ||
|
a173428fab | ||
|
2e56dcc521 | ||
|
acce24fedc | ||
|
93f9cb6e48 | ||
|
d906748691 | ||
|
166a4b25f7 | ||
|
9471e128b5 | ||
|
10282a9b74 | ||
|
03d5e5fba0 | ||
|
348a9048b7 | ||
|
e9bd9330c0 | ||
|
07e349c517 | ||
|
afdf398a0b | ||
|
de3087a7e9 | ||
|
0b06c34dfc | ||
|
7e80e55b6d | ||
|
3d0dc58153 | ||
|
8e43c4706f | ||
|
91d1f43ddd | ||
|
0406441f4b | ||
|
79aff1a5b0 |
20
.github/workflows/build-on-pull-request.yml
vendored
20
.github/workflows/build-on-pull-request.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
||||||
- shell: bash
|
- shell: bash
|
||||||
run: git config --global core.autocrlf input
|
run: git config --global core.autocrlf input
|
||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Do some simple style checks
|
- name: Do some simple style checks
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -44,7 +44,7 @@ jobs:
|
||||||
shell: bash
|
shell: bash
|
||||||
run: make -j2 doc
|
run: make -j2 doc
|
||||||
- name: Upload a documents snapshot.
|
- name: Upload a documents snapshot.
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: docs
|
name: docs
|
||||||
path: ./html
|
path: ./html
|
||||||
|
@ -54,7 +54,7 @@ jobs:
|
||||||
make -j2 bin USER_CFLAGS=-Werror CROSS_COMPILE=x86_64-w64-mingw32-
|
make -j2 bin USER_CFLAGS=-Werror CROSS_COMPILE=x86_64-w64-mingw32-
|
||||||
|
|
||||||
build_windows:
|
build_windows:
|
||||||
name: Build (Windows)
|
name: Build and Test (Windows)
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -62,10 +62,10 @@ jobs:
|
||||||
run: git config --global core.autocrlf input
|
run: git config --global core.autocrlf input
|
||||||
|
|
||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Add msbuild to PATH
|
- name: Add msbuild to PATH
|
||||||
uses: microsoft/setup-msbuild@v1.1
|
uses: microsoft/setup-msbuild@v2
|
||||||
|
|
||||||
- name: Build app (x86 debug)
|
- name: Build app (x86 debug)
|
||||||
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug -property:Platform=Win32
|
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug -property:Platform=Win32
|
||||||
|
@ -79,4 +79,14 @@ jobs:
|
||||||
- name: Build app (x64 release)
|
- name: Build app (x64 release)
|
||||||
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release -property:Platform=x64
|
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release -property:Platform=x64
|
||||||
|
|
||||||
|
- name: Build utils (MinGW)
|
||||||
|
shell: cmd
|
||||||
|
run: make -j2 util SHELL=cmd
|
||||||
|
|
||||||
|
- name: Build the platform libraries (make lib)
|
||||||
|
shell: cmd
|
||||||
|
run: make -j2 lib QUIET=1 SHELL=cmd
|
||||||
|
|
||||||
|
- name: Run the regression tests (make test)
|
||||||
|
shell: cmd
|
||||||
|
run: make test QUIET=1 SHELL=cmd
|
||||||
|
|
14
.github/workflows/snapshot-on-push-master.yml
vendored
14
.github/workflows/snapshot-on-push-master.yml
vendored
|
@ -18,10 +18,10 @@ jobs:
|
||||||
run: git config --global core.autocrlf input
|
run: git config --global core.autocrlf input
|
||||||
|
|
||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Add msbuild to PATH
|
- name: Add msbuild to PATH
|
||||||
uses: microsoft/setup-msbuild@v1.1
|
uses: microsoft/setup-msbuild@v2
|
||||||
|
|
||||||
- name: Build app (debug)
|
- name: Build app (debug)
|
||||||
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug
|
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug
|
||||||
|
@ -44,7 +44,7 @@ jobs:
|
||||||
- shell: bash
|
- shell: bash
|
||||||
run: git config --global core.autocrlf input
|
run: git config --global core.autocrlf input
|
||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Do some simple style checks
|
- name: Do some simple style checks
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -86,18 +86,18 @@ jobs:
|
||||||
mv cc65.zip cc65-snapshot-win32.zip
|
mv cc65.zip cc65-snapshot-win32.zip
|
||||||
|
|
||||||
- name: Upload a 32-bit Snapshot Zip
|
- name: Upload a 32-bit Snapshot Zip
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: cc65-snapshot-win32
|
name: cc65-snapshot-win32
|
||||||
path: cc65-snapshot-win32.zip
|
path: cc65-snapshot-win32.zip
|
||||||
- name: Upload a 64-bit Snapshot Zip
|
- name: Upload a 64-bit Snapshot Zip
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: cc65-snapshot-win64
|
name: cc65-snapshot-win64
|
||||||
path: cc65-snapshot-win64.zip
|
path: cc65-snapshot-win64.zip
|
||||||
|
|
||||||
- name: Get the online documents repo.
|
- name: Get the online documents repo.
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: cc65/doc
|
repository: cc65/doc
|
||||||
# this token will expire, if it does, generate a new one as decribed in https://github.com/cc65/cc65/issues/2065
|
# this token will expire, if it does, generate a new one as decribed in https://github.com/cc65/cc65/issues/2065
|
||||||
|
@ -120,7 +120,7 @@ jobs:
|
||||||
- name: Package offline documents.
|
- name: Package offline documents.
|
||||||
run: 7z a cc65-snapshot-docs.zip ./html/*.*
|
run: 7z a cc65-snapshot-docs.zip ./html/*.*
|
||||||
- name: Upload a Documents Snapshot Zip
|
- name: Upload a Documents Snapshot Zip
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: cc65-snapshot-docs
|
name: cc65-snapshot-docs
|
||||||
path: cc65-snapshot-docs.zip
|
path: cc65-snapshot-docs.zip
|
||||||
|
|
6
.github/workflows/windows-test-scheduled.yml
vendored
6
.github/workflows/windows-test-scheduled.yml
vendored
|
@ -30,7 +30,7 @@ jobs:
|
||||||
run: mkdir ~/.cache-sha
|
run: mkdir ~/.cache-sha
|
||||||
|
|
||||||
- name: Cache SHA
|
- name: Cache SHA
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
id: check-sha
|
id: check-sha
|
||||||
with:
|
with:
|
||||||
path: ~/.cache-sha
|
path: ~/.cache-sha
|
||||||
|
@ -43,11 +43,11 @@ jobs:
|
||||||
|
|
||||||
- name: Checkout source
|
- name: Checkout source
|
||||||
if: steps.check-sha.outputs.cache-hit != 'true'
|
if: steps.check-sha.outputs.cache-hit != 'true'
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Add msbuild to PATH
|
- name: Add msbuild to PATH
|
||||||
if: steps.check-sha.outputs.cache-hit != 'true'
|
if: steps.check-sha.outputs.cache-hit != 'true'
|
||||||
uses: microsoft/setup-msbuild@v1.1
|
uses: microsoft/setup-msbuild@v2
|
||||||
|
|
||||||
- name: Build app (MSVC debug)
|
- name: Build app (MSVC debug)
|
||||||
if: steps.check-sha.outputs.cache-hit != 'true'
|
if: steps.check-sha.outputs.cache-hit != 'true'
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
This document contains all kinds of information that you should know if you want to contribute to the cc65 project. Before you start, please read all of it. If something is not clear to you, please ask - this document is an ongoing effort and may well be incomplete.
|
This document contains all kinds of information that you should know if you want to contribute to the cc65 project. Before you start, please read all of it. If something is not clear to you, please ask - this document is an ongoing effort and may well be incomplete.
|
||||||
|
|
||||||
|
Also, before you put a lot of work into implementing something you want to contribute, please get in touch with one of the developers and ask if what you are going to do is actually wanted and has a chance of being merged. Perhaps someone else is already working on it, or perhaps what you have in mind is not how we'd expect it to be - talking to us before you start might save you a lot of work in those cases.
|
||||||
|
|
||||||
(''Note:'' The word "must" indicates a requirement. The word "should" indicates a recomendation.)
|
(''Note:'' The word "must" indicates a requirement. The word "should" indicates a recomendation.)
|
||||||
|
|
||||||
*this is work in progress and is constantly updated - if in doubt, please ask*
|
*this is work in progress and is constantly updated - if in doubt, please ask*
|
||||||
|
|
|
@ -9,7 +9,7 @@ For details look at the [Website](https://cc65.github.io).
|
||||||
|
|
||||||
Project founders:
|
Project founders:
|
||||||
|
|
||||||
* John R. Dunning: original implementation of the C compiler and runtime library, Atari hosted
|
* John R. Dunning: [original implementation](https://public.websites.umich.edu/~archive/atari/8bit/Languages/Cc65/) of the C compiler and runtime library, Atari hosted
|
||||||
* Ullrich von Bassewitz:
|
* Ullrich von Bassewitz:
|
||||||
* move the code to modern systems
|
* move the code to modern systems
|
||||||
* rewrite most parts of the compiler
|
* rewrite most parts of the compiler
|
||||||
|
|
|
@ -15,7 +15,7 @@ CPU_ISET_4510 = $0400
|
||||||
CPU_NONE = CPU_ISET_NONE
|
CPU_NONE = CPU_ISET_NONE
|
||||||
CPU_6502 = CPU_ISET_6502
|
CPU_6502 = CPU_ISET_6502
|
||||||
CPU_6502X = CPU_ISET_6502|CPU_ISET_6502X
|
CPU_6502X = CPU_ISET_6502|CPU_ISET_6502X
|
||||||
CPU_6502DTV = CPU_ISET_6502|CPU_ISET_6502X|CPU_ISET_6502DTV
|
CPU_6502DTV = CPU_ISET_6502|CPU_ISET_6502DTV
|
||||||
CPU_65SC02 = CPU_ISET_6502|CPU_ISET_65SC02
|
CPU_65SC02 = CPU_ISET_6502|CPU_ISET_65SC02
|
||||||
CPU_65C02 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02
|
CPU_65C02 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02
|
||||||
CPU_65816 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65816
|
CPU_65816 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65816
|
||||||
|
|
|
@ -259,30 +259,44 @@ SND_INTERRUPT = TIMER7_INTERRUPT
|
||||||
|
|
||||||
INTRST = $FD80
|
INTRST = $FD80
|
||||||
INTSET = $FD81
|
INTSET = $FD81
|
||||||
|
|
||||||
MAGRDY0 = $FD84
|
MAGRDY0 = $FD84
|
||||||
MAGRDY1 = $FD85
|
MAGRDY1 = $FD85
|
||||||
AUDIN = $FD86
|
AUDIN = $FD86
|
||||||
SYSCTL1 = $FD87
|
SYSCTL1 = $FD87
|
||||||
MIKEYHREV = $FD88
|
MIKEYHREV = $FD88
|
||||||
MIKEYSREV = $FD89
|
MIKEYSREV = $FD89
|
||||||
|
|
||||||
IODIR = $FD8A
|
IODIR = $FD8A
|
||||||
IODAT = $FD8B
|
IODAT = $FD8B
|
||||||
TxIntEnable = %10000000
|
; IODIR and IODAT bit definitions
|
||||||
RxIntEnable = %01000000
|
AUDIN_BIT = $10 ; Note that there is also the address AUDIN
|
||||||
TxParEnable = %00010000
|
READ_ENABLE = $10 ; Same bit for AUDIN_BIT
|
||||||
ResetErr = %00001000
|
RESTLESS = $08
|
||||||
TxOpenColl = %00000100
|
NOEXP = $04 ; If set, redeye is not connected
|
||||||
TxBreak = %00000010
|
CART_ADDR_DATA = $02
|
||||||
ParEven = %00000001
|
CART_POWER_OFF = $02 ; Same bit for CART_ADDR_DATA
|
||||||
TxReady = %10000000
|
EXTERNAL_POWER = $01
|
||||||
RxReady = %01000000
|
|
||||||
TxEmpty = %00100000
|
|
||||||
RxParityErr = %00010000
|
|
||||||
RxOverrun = %00001000
|
|
||||||
RxFrameErr = %00000100
|
|
||||||
RxBreak = %00000010
|
|
||||||
ParityBit = %00000001
|
|
||||||
SERCTL = $FD8C
|
SERCTL = $FD8C
|
||||||
|
; SERCTL bit definitions for write operations
|
||||||
|
TXINTEN = $80
|
||||||
|
RXINTEN = $40
|
||||||
|
PAREN = $10
|
||||||
|
RESETERR = $08
|
||||||
|
TXOPEN = $04
|
||||||
|
TXBRK = $02
|
||||||
|
PAREVEN = $01
|
||||||
|
; SERCTL bit definitions for read operations
|
||||||
|
TXRDY = $80
|
||||||
|
RXRDY = $40
|
||||||
|
TXEMPTY = $20
|
||||||
|
PARERR = $10
|
||||||
|
OVERRUN = $08
|
||||||
|
FRAMERR = $04
|
||||||
|
RXBRK = $02
|
||||||
|
PARBIT = $01
|
||||||
|
|
||||||
SERDAT = $FD8D
|
SERDAT = $FD8D
|
||||||
SDONEACK = $FD90
|
SDONEACK = $FD90
|
||||||
CPUSLEEP = $FD91
|
CPUSLEEP = $FD91
|
||||||
|
|
41
cfg/kim1-mtu60k.cfg
Normal file
41
cfg/kim1-mtu60k.cfg
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# kim1-mtu60k.cfg (4k)
|
||||||
|
#
|
||||||
|
# for expanded KIM-1 w/ K-1008 Graphics and 60K RAM
|
||||||
|
#
|
||||||
|
# ld65 --config kim1-mtu60k.cfg -o <prog>.bin <prog>.o
|
||||||
|
|
||||||
|
FEATURES {
|
||||||
|
STARTADDRESS: default = $2000;
|
||||||
|
CONDES: segment = STARTUP,
|
||||||
|
type = constructor,
|
||||||
|
label = __CONSTRUCTOR_TABLE__,
|
||||||
|
count = __CONSTRUCTOR_COUNT__;
|
||||||
|
CONDES: segment = STARTUP,
|
||||||
|
type = destructor,
|
||||||
|
label = __DESTRUCTOR_TABLE__,
|
||||||
|
count = __DESTRUCTOR_COUNT__;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYMBOLS {
|
||||||
|
__STACKSIZE__: type = weak, value = $0080; # 128 byte program stack
|
||||||
|
__STARTADDRESS__: type = export, value = %S;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMORY {
|
||||||
|
ZP: file = %O, define = yes, start = $0000, size = $00EE;
|
||||||
|
CPUSTACK: file = "", define = yes, start = $0100, size = $0100;
|
||||||
|
RAM: file = %O, define = yes, start = %S, size = $E000 - %S - __STACKSIZE__;
|
||||||
|
MAINROM: file = "", define = yes, start = $E000, size = $1000;
|
||||||
|
TOP: file = "", define = yes, start = $F000, size = $1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp, define = yes;
|
||||||
|
STARTUP: load = RAM, type = ro, define = yes;
|
||||||
|
CODE: load = RAM, type = ro, define = yes;
|
||||||
|
RODATA: load = RAM, type = ro, define = yes;
|
||||||
|
ONCE: load = RAM, type = ro, define = yes;
|
||||||
|
DATA: load = RAM, type = rw, define = yes;
|
||||||
|
BSS: load = RAM, type = bss, define = yes;
|
||||||
|
}
|
||||||
|
|
41
cfg/kim1-mtuE000.cfg
Normal file
41
cfg/kim1-mtuE000.cfg
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# kim1-mtu60k.cfg (4k)
|
||||||
|
#
|
||||||
|
# for expanded KIM-1 w/ K-1008 Graphics and 60K RAM
|
||||||
|
#
|
||||||
|
# ld65 --config kim1-mtu60k.cfg -o <prog>.bin <prog>.o
|
||||||
|
|
||||||
|
FEATURES {
|
||||||
|
STARTADDRESS: default = $E000;
|
||||||
|
CONDES: segment = STARTUP,
|
||||||
|
type = constructor,
|
||||||
|
label = __CONSTRUCTOR_TABLE__,
|
||||||
|
count = __CONSTRUCTOR_COUNT__;
|
||||||
|
CONDES: segment = STARTUP,
|
||||||
|
type = destructor,
|
||||||
|
label = __DESTRUCTOR_TABLE__,
|
||||||
|
count = __DESTRUCTOR_COUNT__;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYMBOLS {
|
||||||
|
__STACKSIZE__: type = weak, value = $0080; # 128 byte program stack
|
||||||
|
__STARTADDRESS__: type = export, value = %S;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMORY {
|
||||||
|
ZP: file = %O, define = yes, start = $0000, size = $00EE;
|
||||||
|
CPUSTACK: file = "", define = yes, start = $0100, size = $0100;
|
||||||
|
RAM: file = %O, define = yes, start = $2000, size = $E000 - $2000 - __STACKSIZE__;
|
||||||
|
MAINROM: file = "", define = yes, start = $E000, size = $1000;
|
||||||
|
TOP: file = "", define = yes, start = $F000, size = $1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp, define = yes;
|
||||||
|
STARTUP: load = RAM, type = ro, define = yes;
|
||||||
|
CODE: load = RAM, type = ro, define = yes;
|
||||||
|
RODATA: load = RAM, type = ro, define = yes;
|
||||||
|
ONCE: load = RAM, type = ro, define = yes;
|
||||||
|
DATA: load = RAM, type = rw, define = yes;
|
||||||
|
BSS: load = RAM, type = bss, define = yes;
|
||||||
|
}
|
||||||
|
|
|
@ -5,16 +5,17 @@ SYMBOLS {
|
||||||
__BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size
|
__BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size
|
||||||
__EXEHDR__: type = import;
|
__EXEHDR__: type = import;
|
||||||
__BOOTLDR__: type = import;
|
__BOOTLDR__: type = import;
|
||||||
__DEFDIR__: type = import;
|
|
||||||
__UPLOADER__: type = import;
|
__UPLOADER__: type = import;
|
||||||
|
__UPLOADERSIZE__: type = export, value = $61;
|
||||||
|
__HEADERSIZE__: type = export, value = 64;
|
||||||
}
|
}
|
||||||
MEMORY {
|
MEMORY {
|
||||||
ZP: file = "", define = yes, start = $0000, size = $0100;
|
ZP: file = "", define = yes, start = $0000, size = $0100;
|
||||||
HEADER: file = %O, start = $0000, size = $0040;
|
HEADER: file = %O, start = $0000, size = __HEADERSIZE__;
|
||||||
BOOT: file = %O, start = $0200, size = __STARTOFDIRECTORY__;
|
BOOT: file = %O, start = $0200, size = __STARTOFDIRECTORY__;
|
||||||
DIR: file = %O, start = $0000, size = 8;
|
DIR: file = %O, start = $0000, size = 16;
|
||||||
MAIN: file = %O, define = yes, start = $0200, size = $BD38 - __STACKSIZE__;
|
MAIN: file = %O, define = yes, start = $0200, size = $C038 - __UPLOADERSIZE__ - $200 - __STACKSIZE__;
|
||||||
UPLDR: file = %O, define = yes, start = $BFDC, size = $005C;
|
UPLOAD: file = %O, define = yes, start = $C038 - __UPLOADERSIZE__, size = $0061;
|
||||||
}
|
}
|
||||||
SEGMENTS {
|
SEGMENTS {
|
||||||
ZEROPAGE: load = ZP, type = zp;
|
ZEROPAGE: load = ZP, type = zp;
|
||||||
|
@ -30,8 +31,8 @@ SEGMENTS {
|
||||||
RODATA: load = MAIN, type = ro, define = yes;
|
RODATA: load = MAIN, type = ro, define = yes;
|
||||||
DATA: load = MAIN, type = rw, define = yes;
|
DATA: load = MAIN, type = rw, define = yes;
|
||||||
BSS: load = MAIN, type = bss, define = yes;
|
BSS: load = MAIN, type = bss, define = yes;
|
||||||
UPCODE: load = UPLDR, type = ro, define = yes;
|
UPCODE: load = UPLOAD, type = ro, define = yes;
|
||||||
UPDATA: load = UPLDR, type = rw, define = yes;
|
UPDATA: load = UPLOAD, type = rw, define = yes;
|
||||||
}
|
}
|
||||||
FEATURES {
|
FEATURES {
|
||||||
CONDES: type = constructor,
|
CONDES: type = constructor,
|
||||||
|
|
21
cfg/vic20-asm-32k.cfg
Normal file
21
cfg/vic20-asm-32k.cfg
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Assembly program configuration for expanded VICs (>= +8K).
|
||||||
|
|
||||||
|
FEATURES {
|
||||||
|
STARTADDRESS: default = $1201;
|
||||||
|
}
|
||||||
|
SYMBOLS {
|
||||||
|
__LOADADDR__: type = import;
|
||||||
|
}
|
||||||
|
MEMORY {
|
||||||
|
ZP: file = "", start = $0002, size = $001A, define = yes;
|
||||||
|
LOADADDR: file = %O, start = %S - 2, size = $0002;
|
||||||
|
MAIN: file = %O, start = %S, size = $8000 - %S;
|
||||||
|
}
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
||||||
|
LOADADDR: load = LOADADDR, type = ro;
|
||||||
|
CODE: load = MAIN, type = ro;
|
||||||
|
RODATA: load = MAIN, type = ro;
|
||||||
|
DATA: load = MAIN, type = rw;
|
||||||
|
BSS: load = MAIN, type = bss, optional = yes, define = yes;
|
||||||
|
}
|
21
cfg/vic20-asm-3k.cfg
Normal file
21
cfg/vic20-asm-3k.cfg
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Assembly program configuration for expanded VICs (+3K only).
|
||||||
|
|
||||||
|
FEATURES {
|
||||||
|
STARTADDRESS: default = $0401;
|
||||||
|
}
|
||||||
|
SYMBOLS {
|
||||||
|
__LOADADDR__: type = import;
|
||||||
|
}
|
||||||
|
MEMORY {
|
||||||
|
ZP: file = "", start = $0002, size = $001A, define = yes;
|
||||||
|
LOADADDR: file = %O, start = %S - 2, size = $0002;
|
||||||
|
MAIN: file = %O, start = %S, size = $1E00 - %S;
|
||||||
|
}
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
||||||
|
LOADADDR: load = LOADADDR, type = ro;
|
||||||
|
CODE: load = MAIN, type = ro;
|
||||||
|
RODATA: load = MAIN, type = ro;
|
||||||
|
DATA: load = MAIN, type = rw;
|
||||||
|
BSS: load = MAIN, type = bss, optional = yes, define = yes;
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
# Assembly program configuration for unexpanded VICs.
|
||||||
|
|
||||||
FEATURES {
|
FEATURES {
|
||||||
STARTADDRESS: default = $1001;
|
STARTADDRESS: default = $1001;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +9,7 @@ SYMBOLS {
|
||||||
MEMORY {
|
MEMORY {
|
||||||
ZP: file = "", start = $0002, size = $001A, define = yes;
|
ZP: file = "", start = $0002, size = $001A, define = yes;
|
||||||
LOADADDR: file = %O, start = %S - 2, size = $0002;
|
LOADADDR: file = %O, start = %S - 2, size = $0002;
|
||||||
MAIN: file = %O, start = %S, size = $0DF3 - %S;
|
MAIN: file = %O, start = %S, size = $1E00 - %S;
|
||||||
}
|
}
|
||||||
SEGMENTS {
|
SEGMENTS {
|
||||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
||||||
|
|
|
@ -62,7 +62,7 @@ Special locations:
|
||||||
</descrip><p>
|
</descrip><p>
|
||||||
|
|
||||||
While running <tt/main()/ the Language Card bank 2 is enabled for read access.
|
While running <tt/main()/ the Language Card bank 2 is enabled for read access.
|
||||||
However while running module constructors/destructors the Language Card is disabled.
|
However while running module constructors the Language Card is disabled.
|
||||||
|
|
||||||
Enabling the Language Card allows to use it as additional memory for cc65
|
Enabling the Language Card allows to use it as additional memory for cc65
|
||||||
generated code. However code is never automatically placed there. Rather code
|
generated code. However code is never automatically placed there. Rather code
|
||||||
|
@ -330,13 +330,30 @@ usage.
|
||||||
<item>_dos_type
|
<item>_dos_type
|
||||||
<item>_filetype
|
<item>_filetype
|
||||||
<item>_datetime
|
<item>_datetime
|
||||||
|
<item>beep
|
||||||
<item>get_ostype
|
<item>get_ostype
|
||||||
|
<item>gmtime_dt
|
||||||
|
<item>mktime_dt
|
||||||
<item>rebootafterexit
|
<item>rebootafterexit
|
||||||
<item>ser_apple2_slot
|
<item>ser_apple2_slot
|
||||||
<item>tgi_apple2_mix
|
<item>tgi_apple2_mix
|
||||||
</itemize>
|
</itemize>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1>Apple IIgs specific functions in accelerator.h<p>
|
||||||
|
|
||||||
|
In addition to those, the <tt/accelerator.h/ header file contains three functions
|
||||||
|
to help determine whether the program is running on a IIgs, and change the IIgs
|
||||||
|
CPU speed. See the <url url="funcref.html" name="function reference"> for declaration and
|
||||||
|
usage.
|
||||||
|
|
||||||
|
<itemize>
|
||||||
|
<item>detect_iigs
|
||||||
|
<item>get_iigs_speed
|
||||||
|
<item>set_iigs_speed
|
||||||
|
</itemize>
|
||||||
|
|
||||||
|
|
||||||
<sect1>Hardware access<p>
|
<sect1>Hardware access<p>
|
||||||
|
|
||||||
There's currently no support for direct hardware access. This does not mean
|
There's currently no support for direct hardware access. This does not mean
|
||||||
|
@ -435,10 +452,15 @@ The names in the parentheses denote the symbols to be used for static linking of
|
||||||
(RTS/CTS) and does interrupt driven receives. Speeds faster than 9600 baud
|
(RTS/CTS) and does interrupt driven receives. Speeds faster than 9600 baud
|
||||||
aren't reachable because the ROM and ProDOS IRQ handlers are too slow.
|
aren't reachable because the ROM and ProDOS IRQ handlers are too slow.
|
||||||
Software flow control (XON/XOFF) is not supported.
|
Software flow control (XON/XOFF) is not supported.
|
||||||
|
|
||||||
Note that because of the peculiarities of the 6551 chip transmits are not
|
Note that because of the peculiarities of the 6551 chip transmits are not
|
||||||
interrupt driven, and the transceiver blocks if the receiver asserts
|
interrupt driven, and the transceiver blocks if the receiver asserts
|
||||||
flow control because of a full buffer.
|
flow control because of a full buffer.
|
||||||
|
|
||||||
|
Note that using the driver at SER_BAUD_115200 will disable IRQs. It will be up
|
||||||
|
to the users to use the serial port, either by re-enabling IRQs themselves,
|
||||||
|
or by directly poll-reading the ACIA DATA register without the help of ser_get().
|
||||||
|
|
||||||
The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to
|
The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to
|
||||||
<tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/
|
<tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/
|
||||||
succeeds for all Apple II slots, but <tt/ser_open()/ fails with
|
succeeds for all Apple II slots, but <tt/ser_open()/ fails with
|
||||||
|
|
|
@ -63,7 +63,7 @@ Special locations:
|
||||||
</descrip><p>
|
</descrip><p>
|
||||||
|
|
||||||
While running <tt/main()/ the Language Card bank 2 is enabled for read access.
|
While running <tt/main()/ the Language Card bank 2 is enabled for read access.
|
||||||
However while running module constructors/destructors the Language Card is disabled.
|
However while running module constructors the Language Card is disabled.
|
||||||
|
|
||||||
Enabling the Language Card allows to use it as additional memory for cc65
|
Enabling the Language Card allows to use it as additional memory for cc65
|
||||||
generated code. However code is never automatically placed there. Rather code
|
generated code. However code is never automatically placed there. Rather code
|
||||||
|
@ -331,7 +331,10 @@ usage.
|
||||||
<item>_dos_type
|
<item>_dos_type
|
||||||
<item>_filetype
|
<item>_filetype
|
||||||
<item>_datetime
|
<item>_datetime
|
||||||
|
<item>beep
|
||||||
<item>get_ostype
|
<item>get_ostype
|
||||||
|
<item>gmtime_dt
|
||||||
|
<item>mktime_dt
|
||||||
<item>rebootafterexit
|
<item>rebootafterexit
|
||||||
<item>ser_apple2_slot
|
<item>ser_apple2_slot
|
||||||
<item>tgi_apple2_mix
|
<item>tgi_apple2_mix
|
||||||
|
@ -340,6 +343,20 @@ usage.
|
||||||
</itemize>
|
</itemize>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1>Apple IIgs specific functions in accelerator.h<p>
|
||||||
|
|
||||||
|
In addition to those, the <tt/accelerator.h/ header file contains three functions
|
||||||
|
to help determine whether the program is running on a IIgs, and change the IIgs
|
||||||
|
CPU speed. See the <url url="funcref.html" name="function reference"> for declaration and
|
||||||
|
usage.
|
||||||
|
|
||||||
|
<itemize>
|
||||||
|
<item>detect_iigs
|
||||||
|
<item>get_iigs_speed
|
||||||
|
<item>set_iigs_speed
|
||||||
|
</itemize>
|
||||||
|
|
||||||
|
|
||||||
<sect1>Hardware access<p>
|
<sect1>Hardware access<p>
|
||||||
|
|
||||||
There's currently no support for direct hardware access. This does not mean
|
There's currently no support for direct hardware access. This does not mean
|
||||||
|
@ -436,10 +453,15 @@ The names in the parentheses denote the symbols to be used for static linking of
|
||||||
(RTS/CTS) and does interrupt driven receives. Speeds faster than 9600 baud
|
(RTS/CTS) and does interrupt driven receives. Speeds faster than 9600 baud
|
||||||
aren't reachable because the ROM and ProDOS IRQ handlers are too slow.
|
aren't reachable because the ROM and ProDOS IRQ handlers are too slow.
|
||||||
Software flow control (XON/XOFF) is not supported.
|
Software flow control (XON/XOFF) is not supported.
|
||||||
|
|
||||||
Note that because of the peculiarities of the 6551 chip transmits are not
|
Note that because of the peculiarities of the 6551 chip transmits are not
|
||||||
interrupt driven, and the transceiver blocks if the receiver asserts
|
interrupt driven, and the transceiver blocks if the receiver asserts
|
||||||
flow control because of a full buffer.
|
flow control because of a full buffer.
|
||||||
|
|
||||||
|
Note that using the driver at SER_BAUD_115200 will disable IRQs. It will be up
|
||||||
|
to the users to use the serial port, either by re-enabling IRQs themselves,
|
||||||
|
or by directly poll-reading the ACIA DATA register without the help of ser_get().
|
||||||
|
|
||||||
The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to
|
The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to
|
||||||
<tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/
|
<tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/
|
||||||
succeeds for all Apple II slots, but <tt/ser_open()/ fails with
|
succeeds for all Apple II slots, but <tt/ser_open()/ fails with
|
||||||
|
|
|
@ -1176,6 +1176,11 @@ if you want to access the "other" symbol <tt/bar/, you would have to write:
|
||||||
.endscope
|
.endscope
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
|
The above example also shows that to search a scope that is not yet defined in
|
||||||
|
the code above the usage, you must use the namespace token (<tt/::/) and
|
||||||
|
specify the full scope name, to allow the assembler to create the scope at the
|
||||||
|
correct place.
|
||||||
|
|
||||||
|
|
||||||
<sect>Address sizes and memory models<label id="address-sizes"><p>
|
<sect>Address sizes and memory models<label id="address-sizes"><p>
|
||||||
|
|
||||||
|
|
|
@ -71,18 +71,21 @@ function.
|
||||||
<item><ref id="detect_c64dtv" name="detect_c64dtv">
|
<item><ref id="detect_c64dtv" name="detect_c64dtv">
|
||||||
<item><ref id="detect_c65" name="detect_c65">
|
<item><ref id="detect_c65" name="detect_c65">
|
||||||
<item><ref id="detect_chameleon" name="detect_chameleon">
|
<item><ref id="detect_chameleon" name="detect_chameleon">
|
||||||
|
<item><ref id="detect_iigs" name="detect_iigs">
|
||||||
<item><ref id="detect_scpu" name="detect_scpu">
|
<item><ref id="detect_scpu" name="detect_scpu">
|
||||||
<item><ref id="detect_turbomaster" name="detect_turbomaster">
|
<item><ref id="detect_turbomaster" name="detect_turbomaster">
|
||||||
<item><ref id="get_c128_speed" name="get_c128_speed">
|
<item><ref id="get_c128_speed" name="get_c128_speed">
|
||||||
<item><ref id="get_c64dtv_speed" name="get_c64dtv_speed">
|
<item><ref id="get_c64dtv_speed" name="get_c64dtv_speed">
|
||||||
<item><ref id="get_c65_speed" name="get_c65_speed">
|
<item><ref id="get_c65_speed" name="get_c65_speed">
|
||||||
<item><ref id="get_chameleon_speed" name="get_chameleon_speed">
|
<item><ref id="get_chameleon_speed" name="get_chameleon_speed">
|
||||||
|
<item><ref id="get_iigs_speed" name="get_iigs_speed">
|
||||||
<item><ref id="get_scpu_speed" name="get_scpu_speed">
|
<item><ref id="get_scpu_speed" name="get_scpu_speed">
|
||||||
<item><ref id="get_turbomaster_speed" name="get_turbomaster_speed">
|
<item><ref id="get_turbomaster_speed" name="get_turbomaster_speed">
|
||||||
<item><ref id="set_c128_speed" name="set_c128_speed">
|
<item><ref id="set_c128_speed" name="set_c128_speed">
|
||||||
<item><ref id="set_c64dtv_speed" name="set_c64dtv_speed">
|
<item><ref id="set_c64dtv_speed" name="set_c64dtv_speed">
|
||||||
<item><ref id="set_c65_speed" name="set_c65_speed">
|
<item><ref id="set_c65_speed" name="set_c65_speed">
|
||||||
<item><ref id="set_chameleon_speed" name="set_chameleon_speed">
|
<item><ref id="set_chameleon_speed" name="set_chameleon_speed">
|
||||||
|
<item><ref id="set_iigs_speed" name="set_iigs_speed">
|
||||||
<item><ref id="set_scpu_speed" name="set_scpu_speed">
|
<item><ref id="set_scpu_speed" name="set_scpu_speed">
|
||||||
<item><ref id="set_turbomaster_speed" name="set_turbomaster_speed">
|
<item><ref id="set_turbomaster_speed" name="set_turbomaster_speed">
|
||||||
</itemize>
|
</itemize>
|
||||||
|
@ -92,6 +95,7 @@ function.
|
||||||
|
|
||||||
<itemize>
|
<itemize>
|
||||||
<item>_dos_type
|
<item>_dos_type
|
||||||
|
<item><ref id="beep" name="beep">
|
||||||
<item><ref id="get_ostype" name="get_ostype">
|
<item><ref id="get_ostype" name="get_ostype">
|
||||||
<item><ref id="gmtime_dt" name="gmtime_dt">
|
<item><ref id="gmtime_dt" name="gmtime_dt">
|
||||||
<item><ref id="mktime_dt" name="mktime_dt">
|
<item><ref id="mktime_dt" name="mktime_dt">
|
||||||
|
@ -103,7 +107,10 @@ function.
|
||||||
|
|
||||||
<itemize>
|
<itemize>
|
||||||
<item>_dos_type
|
<item>_dos_type
|
||||||
|
<item><ref id="beep" name="beep">
|
||||||
<item><ref id="get_ostype" name="get_ostype">
|
<item><ref id="get_ostype" name="get_ostype">
|
||||||
|
<item><ref id="gmtime_dt" name="gmtime_dt">
|
||||||
|
<item><ref id="mktime_dt" name="mktime_dt">
|
||||||
<item>rebootafterexit
|
<item>rebootafterexit
|
||||||
<item><ref id="videomode" name="videomode">
|
<item><ref id="videomode" name="videomode">
|
||||||
</itemize>
|
</itemize>
|
||||||
|
@ -1766,10 +1773,11 @@ used in presence of a prototype.
|
||||||
<descrip>
|
<descrip>
|
||||||
<tag/Function/Beep sound.
|
<tag/Function/Beep sound.
|
||||||
<tag/Header/<tt/<ref id="sym1.h" name="sym1.h">/
|
<tag/Header/<tt/<ref id="sym1.h" name="sym1.h">/
|
||||||
|
<tag/Header/<tt/<ref id="apple2.h" name="apple2.h">/
|
||||||
<tag/Declaration/<tt/void beep(void);/
|
<tag/Declaration/<tt/void beep(void);/
|
||||||
<tag/Description/<tt/beep/ makes a brief tone.
|
<tag/Description/<tt/beep/ makes a brief tone.
|
||||||
<tag/Notes/<itemize>
|
<tag/Notes/<itemize>
|
||||||
<item>The function is specific to the Sym-1.
|
<item>The function is specific to the Sym-1 and Apple2 platforms.
|
||||||
</itemize>
|
</itemize>
|
||||||
<tag/Availability/cc65
|
<tag/Availability/cc65
|
||||||
<tag/See also/
|
<tag/See also/
|
||||||
|
@ -3453,6 +3461,26 @@ used in presence of a prototype.
|
||||||
</quote>
|
</quote>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1>detect_iigs<label id="detect_iigs"><p>
|
||||||
|
|
||||||
|
<quote>
|
||||||
|
<descrip>
|
||||||
|
<tag/Function/Check whether we are running on an Apple IIgs..
|
||||||
|
<tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/
|
||||||
|
<tag/Declaration/<tt/unsigned char detect_iigs (void);/
|
||||||
|
<tag/Description/The function returns a 1 if running on an Apple IIgs.
|
||||||
|
<tag/Notes/<itemize>
|
||||||
|
<item>The function is specific to the Apple2 and Apple2enh platforms.
|
||||||
|
</itemize>
|
||||||
|
<tag/Availability/cc65 (not all platforms)
|
||||||
|
<tag/See also/
|
||||||
|
<ref id="get_iigs_speed" name="get_iigs_speed">,
|
||||||
|
<ref id="set_iigs_speed" name="set_iigs_speed">,
|
||||||
|
<tag/Example/None.
|
||||||
|
</descrip>
|
||||||
|
</quote>
|
||||||
|
|
||||||
|
|
||||||
<sect1>detect_scpu<label id="detect_scpu"><p>
|
<sect1>detect_scpu<label id="detect_scpu"><p>
|
||||||
|
|
||||||
<quote>
|
<quote>
|
||||||
|
@ -4167,6 +4195,27 @@ header files define constants that can be used to check the return code.
|
||||||
</quote>
|
</quote>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1>get_iigs_speed<label id="get_iigs_speed"><p>
|
||||||
|
|
||||||
|
<quote>
|
||||||
|
<descrip>
|
||||||
|
<tag/Function/Get the current speed of the Apple IIgs.
|
||||||
|
<tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/
|
||||||
|
<tag/Declaration/<tt/unsigned char get_iigs_speed (void);/
|
||||||
|
<tag/Description/The function returns the current speed of the Apple IIgs.
|
||||||
|
<tag/Notes/<itemize>
|
||||||
|
<item>The function is specific to the Apple2 and Apple2enh platforms.
|
||||||
|
<item>See the accelerator.h header for the speed definitions.
|
||||||
|
</itemize>
|
||||||
|
<tag/Availability/cc65 (not all platforms)
|
||||||
|
<tag/See also/
|
||||||
|
<ref id="detect_iigs" name="detect_iigs">,
|
||||||
|
<ref id="set_iigs_speed" name="set_iigs_speed">,
|
||||||
|
<tag/Example/None.
|
||||||
|
</descrip>
|
||||||
|
</quote>
|
||||||
|
|
||||||
|
|
||||||
<sect1>get_scpu_speed<label id="get_scpu_speed"><p>
|
<sect1>get_scpu_speed<label id="get_scpu_speed"><p>
|
||||||
|
|
||||||
<quote>
|
<quote>
|
||||||
|
@ -6985,6 +7034,30 @@ clean-up when exiting the program.
|
||||||
</quote>
|
</quote>
|
||||||
|
|
||||||
|
|
||||||
|
<sect1>set_iigs_speed<label id="set_iigs_speed"><p>
|
||||||
|
|
||||||
|
<quote>
|
||||||
|
<descrip>
|
||||||
|
<tag/Function/Set the current speed of the Apple IIgs.
|
||||||
|
<tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/
|
||||||
|
<tag/Declaration/<tt/unsigned char __fastcall__ set_iigs_speed (unsigned char speed);/
|
||||||
|
<tag/Description/The function sets the speed of the Apple IIgs CPU (and returns
|
||||||
|
the new speed).
|
||||||
|
<tag/Notes/<itemize>
|
||||||
|
<item>The function is specific to the Apple2 and Apple2enh platforms.
|
||||||
|
<item>See the accelerator.h header for the speed definitions.
|
||||||
|
<item>Accepted parameters are SPEED_SLOW and SPEED_FAST (all other values are
|
||||||
|
considered SPEED_FAST).
|
||||||
|
</itemize>
|
||||||
|
<tag/Availability/cc65 (not all platforms)
|
||||||
|
<tag/See also/
|
||||||
|
<ref id="detect_iigs" name="detect_iigs">,
|
||||||
|
<ref id="get_iigs_speed" name="get_iigs_speed">,
|
||||||
|
<tag/Example/None.
|
||||||
|
</descrip>
|
||||||
|
</quote>
|
||||||
|
|
||||||
|
|
||||||
<sect1>set_scpu_speed<label id="set_scpu_speed"><p>
|
<sect1>set_scpu_speed<label id="set_scpu_speed"><p>
|
||||||
|
|
||||||
<quote>
|
<quote>
|
||||||
|
|
|
@ -304,6 +304,36 @@ unsigned char detect_turbomaster (void);
|
||||||
* 0x01 : C64 Turbo Master cartridge present
|
* 0x01 : C64 Turbo Master cartridge present
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
unsigned char __fastcall__ set_iigs_speed (unsigned char speed);
|
||||||
|
|
||||||
|
/* Set the speed of the Apple IIgs CPU.
|
||||||
|
*
|
||||||
|
* Possible values:
|
||||||
|
* SPEED_SLOW : 1 Mhz mode
|
||||||
|
* SPEED_FAST : Fast mode (2.8MHz or more, depending on the presence of
|
||||||
|
* an accelerator)
|
||||||
|
*
|
||||||
|
* Any other value will be interpreted as SPEED_FAST.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned char get_iigs_speed (void);
|
||||||
|
|
||||||
|
/* Get the speed of the Apple IIgs CPU.
|
||||||
|
*
|
||||||
|
* Possible return values:
|
||||||
|
* SPEED_SLOW : 1 Mhz mode
|
||||||
|
* SPEED_FAST : Fast mode (2.8MHz or more, depending on the presence of
|
||||||
|
* an accelerator)
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned char detect_iigs (void);
|
||||||
|
|
||||||
|
/* Check whether we are running on an Apple IIgs.
|
||||||
|
*
|
||||||
|
* Possible return values:
|
||||||
|
* 0x00 : No
|
||||||
|
* 0x01 : Yes
|
||||||
|
*/
|
||||||
|
|
||||||
/* End of accelerator.h */
|
/* End of accelerator.h */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -197,6 +197,9 @@ extern void a2_lo_tgi[];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void beep (void);
|
||||||
|
/* Beep beep. */
|
||||||
|
|
||||||
unsigned char get_ostype (void);
|
unsigned char get_ostype (void);
|
||||||
/* Get the machine type. Returns one of the APPLE_xxx codes. */
|
/* Get the machine type. Returns one of the APPLE_xxx codes. */
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,10 @@ extern FILE* stderr;
|
||||||
# define FILENAME_MAX (80+1)
|
# define FILENAME_MAX (80+1)
|
||||||
#elif defined(__TELESTRAT__)
|
#elif defined(__TELESTRAT__)
|
||||||
# define FILENAME_MAX (50+1)
|
# define FILENAME_MAX (50+1)
|
||||||
|
#elif defined(__SIM6502__)
|
||||||
|
# define FILENAME_MAX (1024+1)
|
||||||
|
#elif defined(__SIM65C02__)
|
||||||
|
# define FILENAME_MAX (1024+1)
|
||||||
#else
|
#else
|
||||||
# define FILENAME_MAX (16+1)
|
# define FILENAME_MAX (16+1)
|
||||||
#endif
|
#endif
|
||||||
|
|
20
libsrc/apple2/beep.s
Normal file
20
libsrc/apple2/beep.s
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; void beep(void)
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _beep
|
||||||
|
.import BELL
|
||||||
|
|
||||||
|
.include "apple2.inc"
|
||||||
|
|
||||||
|
.segment "LOWCODE"
|
||||||
|
|
||||||
|
_beep:
|
||||||
|
lda CH ; Bell scrambles CH in 80col mode on IIgs, storing
|
||||||
|
pha ; it in OURCH and resetting CH to 0. Save it.
|
||||||
|
jsr BELL
|
||||||
|
pla
|
||||||
|
sta CH ; Restore CH
|
||||||
|
rts
|
20
libsrc/apple2/bell.s
Normal file
20
libsrc/apple2/bell.s
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; BELL routine
|
||||||
|
;
|
||||||
|
|
||||||
|
.export BELL
|
||||||
|
|
||||||
|
.include "apple2.inc"
|
||||||
|
|
||||||
|
.segment "LOWCODE"
|
||||||
|
|
||||||
|
BELL:
|
||||||
|
; Switch in ROM and call BELL
|
||||||
|
bit $C082
|
||||||
|
jsr $FF3A ; BELL
|
||||||
|
|
||||||
|
; Switch in LC bank 2 for R/O and return
|
||||||
|
bit $C080
|
||||||
|
rts
|
|
@ -40,12 +40,15 @@ _exit: ldx #<exit
|
||||||
lda #>exit
|
lda #>exit
|
||||||
jsr reset ; Setup RESET vector
|
jsr reset ; Setup RESET vector
|
||||||
|
|
||||||
; Switch in ROM, in case it wasn't already switched in by a RESET.
|
; Switch in LC bank 2 for R/O in case it was switched out by a RESET.
|
||||||
bit $C082
|
bit $C080
|
||||||
|
|
||||||
; Call the module destructors.
|
; Call the module destructors.
|
||||||
jsr donelib
|
jsr donelib
|
||||||
|
|
||||||
|
; Switch in ROM.
|
||||||
|
bit $C082
|
||||||
|
|
||||||
; Restore the original RESET vector.
|
; Restore the original RESET vector.
|
||||||
exit: ldx #$02
|
exit: ldx #$02
|
||||||
: lda rvsave,x
|
: lda rvsave,x
|
||||||
|
|
17
libsrc/apple2/detect_iigs.s
Normal file
17
libsrc/apple2/detect_iigs.s
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||||
|
;
|
||||||
|
; void __fastcall__ detect_iigs(void)
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _detect_iigs
|
||||||
|
.import ostype, return0, return1
|
||||||
|
|
||||||
|
.include "apple2.inc"
|
||||||
|
|
||||||
|
; Returns 1 if running on IIgs, 0 otherwise
|
||||||
|
_detect_iigs:
|
||||||
|
lda ostype
|
||||||
|
bpl :+
|
||||||
|
jmp return1
|
||||||
|
: jmp return0
|
22
libsrc/apple2/get_iigs_speed.s
Normal file
22
libsrc/apple2/get_iigs_speed.s
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||||
|
;
|
||||||
|
; unsigned char __fastcall__ get_iigs_speed(void)
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _get_iigs_speed
|
||||||
|
.import ostype, return0
|
||||||
|
|
||||||
|
.include "apple2.inc"
|
||||||
|
.include "accelerator.inc"
|
||||||
|
|
||||||
|
_get_iigs_speed:
|
||||||
|
lda ostype ; Return SLOW if not IIgs
|
||||||
|
bpl :+
|
||||||
|
lda CYAREG ; Check current setting
|
||||||
|
bpl :+
|
||||||
|
lda #SPEED_FAST
|
||||||
|
ldx #$00
|
||||||
|
rts
|
||||||
|
.assert SPEED_SLOW = 0, error
|
||||||
|
: jmp return0 ; SPEED_SLOW
|
|
@ -5,7 +5,7 @@
|
||||||
;
|
;
|
||||||
|
|
||||||
.constructor initostype, 9
|
.constructor initostype, 9
|
||||||
.export _get_ostype
|
.export _get_ostype, ostype
|
||||||
|
|
||||||
; Identify machine according to:
|
; Identify machine according to:
|
||||||
; Apple II Miscellaneous TechNote #7, Apple II Family Identification
|
; Apple II Miscellaneous TechNote #7, Apple II Family Identification
|
||||||
|
|
|
@ -66,34 +66,16 @@ HSType: .res 1 ; Flow-control type
|
||||||
RecvBuf: .res 256 ; Receive buffers: 256 bytes
|
RecvBuf: .res 256 ; Receive buffers: 256 bytes
|
||||||
SendBuf: .res 256 ; Send buffers: 256 bytes
|
SendBuf: .res 256 ; Send buffers: 256 bytes
|
||||||
|
|
||||||
|
CurClockSource: .res 1 ; Whether to use BRG or RTxC for clock
|
||||||
|
|
||||||
.data
|
.data
|
||||||
|
|
||||||
Opened: .byte $00 ; 1 when opened
|
Opened: .byte $00 ; 1 when opened
|
||||||
Channel: .byte $00 ; Channel B by default
|
Channel: .byte $00 ; Channel B by default
|
||||||
CurChanIrqFlags:.byte INTR_PENDING_RX_EXT_B
|
CurChanIrqFlags:.byte $00
|
||||||
|
|
||||||
SerFlagOrig: .byte $00
|
SerFlagOrig: .byte $00
|
||||||
|
|
||||||
; Tables used to translate cc65 RS232 params into register values
|
|
||||||
; (Ref page 5-18 and 5-19)
|
|
||||||
BaudLowTable: .byte $7E ; SER_BAUD_300
|
|
||||||
.byte $5E ; SER_BAUD_1200
|
|
||||||
.byte $2E ; SER_BAUD_2400
|
|
||||||
.byte $16 ; SER_BAUD_4800
|
|
||||||
.byte $0A ; SER_BAUD_9600
|
|
||||||
.byte $04 ; SER_BAUD_19200
|
|
||||||
.byte $01 ; SER_BAUD_38400
|
|
||||||
.byte $00 ; SER_BAUD_57600
|
|
||||||
|
|
||||||
BaudHighTable: .byte $01 ; SER_BAUD_300
|
|
||||||
.byte $00 ; SER_BAUD_1200
|
|
||||||
.byte $00 ; SER_BAUD_2400
|
|
||||||
.byte $00 ; SER_BAUD_4800
|
|
||||||
.byte $00 ; SER_BAUD_9600
|
|
||||||
.byte $00 ; SER_BAUD_19200
|
|
||||||
.byte $00 ; SER_BAUD_38400
|
|
||||||
.byte $00 ; SER_BAUD_57600
|
|
||||||
|
|
||||||
RxBitTable: .byte %00000000 ; SER_BITS_5, in WR_RX_CTRL (WR3)
|
RxBitTable: .byte %00000000 ; SER_BITS_5, in WR_RX_CTRL (WR3)
|
||||||
.byte %10000000 ; SER_BITS_6 (Ref page 5-7)
|
.byte %10000000 ; SER_BITS_6 (Ref page 5-7)
|
||||||
.byte %01000000 ; SER_BITS_7
|
.byte %01000000 ; SER_BITS_7
|
||||||
|
@ -106,29 +88,65 @@ TxBitTable: .byte %00000000 ; SER_BITS_5, in WR_TX_CTRL (WR5)
|
||||||
|
|
||||||
.rodata
|
.rodata
|
||||||
|
|
||||||
|
ClockMultiplier:.byte %01000000 ; Clock x16 (300-57600bps, WR4, ref page 5-8)
|
||||||
|
.byte %10000000 ; Clock x32 (115200bps, ref page 5-8)
|
||||||
|
|
||||||
|
ClockSource: .byte %01010000 ; Use baud rate generator (ch. B) (WR11, page 5-17)
|
||||||
|
.byte %00000000 ; Use RTxC (115200bps) (ch. B)
|
||||||
|
.byte %11010000 ; Use baud rate generator (ch. A)
|
||||||
|
.byte %10000000 ; Use RTxC (115200bps) (ch. A)
|
||||||
|
|
||||||
|
BrgEnabled: .byte %00000001 ; Baud rate generator on (WR14, page 5-19)
|
||||||
|
.byte %00000000 ; BRG Off
|
||||||
|
|
||||||
|
ChanIrqFlags: .byte %00000101 ; ANDed (RX/special IRQ, ch. B) (page 5-25)
|
||||||
|
.byte %00101000 ; ANDed (RX/special IRQ, ch. A)
|
||||||
|
|
||||||
|
ChanIrqMask: .byte %00000111 ; Ch. B IRQ flags mask
|
||||||
|
.byte %00111000 ; Ch. A IRQ flags mask
|
||||||
|
|
||||||
BaudTable: ; bit7 = 1 means setting is invalid
|
BaudTable: ; bit7 = 1 means setting is invalid
|
||||||
; Otherwise refers to the index in
|
; Indexes cc65 RS232 SER_BAUD enum
|
||||||
; Baud(Low/High)Table
|
; into WR12/13 register values
|
||||||
.byte $FF ; SER_BAUD_45_5
|
; (Ref page 5-18 and 5-19)
|
||||||
.byte $FF ; SER_BAUD_50
|
.word $FFFF ; SER_BAUD_45_5
|
||||||
.byte $FF ; SER_BAUD_75
|
.word $FFFF ; SER_BAUD_50
|
||||||
.byte $FF ; SER_BAUD_110
|
.word $FFFF ; SER_BAUD_75
|
||||||
.byte $FF ; SER_BAUD_134_5
|
.word $FFFF ; SER_BAUD_110
|
||||||
.byte $FF ; SER_BAUD_150
|
.word $FFFF ; SER_BAUD_134_5
|
||||||
.byte $00 ; SER_BAUD_300
|
.word $FFFF ; SER_BAUD_150
|
||||||
.byte $FF ; SER_BAUD_600
|
.word $017E ; SER_BAUD_300
|
||||||
.byte $01 ; SER_BAUD_1200
|
.word $FFFF ; SER_BAUD_600
|
||||||
.byte $FF ; SER_BAUD_1800
|
.word $005E ; SER_BAUD_1200
|
||||||
.byte $02 ; SER_BAUD_2400
|
.word $FFFF ; SER_BAUD_1800
|
||||||
.byte $FF ; SER_BAUD_3600
|
.word $002E ; SER_BAUD_2400
|
||||||
.byte $03 ; SER_BAUD_4800
|
.word $FFFF ; SER_BAUD_3600
|
||||||
.byte $FF ; SER_BAUD_7200
|
.word $0016 ; SER_BAUD_4800
|
||||||
.byte $04 ; SER_BAUD_9600
|
.word $FFFF ; SER_BAUD_7200
|
||||||
.byte $05 ; SER_BAUD_19200
|
.word $000A ; SER_BAUD_9600
|
||||||
.byte $06 ; SER_BAUD_38400
|
.word $0004 ; SER_BAUD_19200
|
||||||
.byte $07 ; SER_BAUD_57600
|
.word $0001 ; SER_BAUD_38400
|
||||||
.byte $FF ; SER_BAUD_115200
|
.word $0000 ; SER_BAUD_57600
|
||||||
.byte $FF ; SER_BAUD_230400
|
.word $0000 ; SER_BAUD_115200 (constant unused at that speed)
|
||||||
|
.word $FFFF ; SER_BAUD_230400
|
||||||
|
|
||||||
|
; About the speed selection: either we use the baud rate generator:
|
||||||
|
; - Load the time constants from BaudTable into WR12/WR13
|
||||||
|
; - Setup the TX/RX clock source to BRG (ClockSource into WR11)
|
||||||
|
; - Setup the clock multiplier (WR4)
|
||||||
|
; - Enable the baud rate generator (WR14)
|
||||||
|
; In this case, the baud rate will be:
|
||||||
|
; rate = crystal_clock/(2+BRG_time_constant))/(2*clock_multiplier)
|
||||||
|
; Example: (3686400/(2+0x0004)) / (2*16) = 19200 bps
|
||||||
|
;
|
||||||
|
; Or we don't use the baud rate generator:
|
||||||
|
; - Setup the TX/RX clock source to RTxC
|
||||||
|
; - Setup the clock multiplier
|
||||||
|
; - Disable the baud rate generator
|
||||||
|
; - WR12 and 13 are ignored
|
||||||
|
; In this case, the baud rate will be:
|
||||||
|
; rate = crystal_clock/clock_multiplier
|
||||||
|
; Example: 3686400/32 = 115200 bps
|
||||||
|
|
||||||
StopTable: .byte %00000100 ; SER_STOP_1, in WR_TX_RX_CTRL (WR4)
|
StopTable: .byte %00000100 ; SER_STOP_1, in WR_TX_RX_CTRL (WR4)
|
||||||
.byte %00001100 ; SER_STOP_2 (Ref page 5-8)
|
.byte %00001100 ; SER_STOP_2 (Ref page 5-8)
|
||||||
|
@ -156,6 +174,7 @@ SER_FLAG := $E10104
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
; ------------------------------------------------------------------------
|
||||||
; Channels
|
; Channels
|
||||||
|
|
||||||
CHANNEL_B = 0
|
CHANNEL_B = 0
|
||||||
CHANNEL_A = 1
|
CHANNEL_A = 1
|
||||||
|
|
||||||
|
@ -180,7 +199,6 @@ RX_CTRL_OFF = %11111110 ; ANDed,Rx disabled
|
||||||
|
|
||||||
WR_TX_RX_CTRL = 4
|
WR_TX_RX_CTRL = 4
|
||||||
RR_TX_RX_STATUS = 4
|
RR_TX_RX_STATUS = 4
|
||||||
TX_RX_CLOCK_MUL = %01000000 ; Clock x16 (Ref page 5-8)
|
|
||||||
|
|
||||||
WR_TX_CTRL = 5 ; (Ref page 5-9)
|
WR_TX_CTRL = 5 ; (Ref page 5-9)
|
||||||
RR_TX_STATUS = 5 ; Corresponding status register
|
RR_TX_STATUS = 5 ; Corresponding status register
|
||||||
|
@ -197,15 +215,11 @@ MASTER_IRQ_MIE_RST = %00001010 ; STA'd
|
||||||
MASTER_IRQ_SET = %00011001 ; STA'd
|
MASTER_IRQ_SET = %00011001 ; STA'd
|
||||||
|
|
||||||
WR_CLOCK_CTRL = 11 ; (Ref page 5-17)
|
WR_CLOCK_CTRL = 11 ; (Ref page 5-17)
|
||||||
CLOCK_CTRL_CH_A = %11010000
|
|
||||||
CLOCK_CTRL_CH_B = %01010000
|
|
||||||
|
|
||||||
WR_BAUDL_CTRL = 12 ; (Ref page 5-18)
|
WR_BAUDL_CTRL = 12 ; (Ref page 5-18)
|
||||||
WR_BAUDH_CTRL = 13 ; (Ref page 5-19)
|
WR_BAUDH_CTRL = 13 ; (Ref page 5-19)
|
||||||
|
|
||||||
WR_MISC_CTRL = 14 ; (Ref page 5-19)
|
WR_MISC_CTRL = 14 ; (Ref page 5-19)
|
||||||
MISC_CTRL_RATE_GEN_ON = %00000001 ; ORed
|
|
||||||
MISC_CTRL_RATE_GEN_OFF = %11111110 ; ANDed
|
|
||||||
|
|
||||||
WR_IRQ_CTRL = 15 ; (Ref page 5-20)
|
WR_IRQ_CTRL = 15 ; (Ref page 5-20)
|
||||||
IRQ_CLEANUP_EIRQ = %00001000
|
IRQ_CLEANUP_EIRQ = %00001000
|
||||||
|
@ -220,13 +234,8 @@ IRQ_RX = %00100000
|
||||||
IRQ_SPECIAL = %01100000
|
IRQ_SPECIAL = %01100000
|
||||||
|
|
||||||
RR_INTR_PENDING_STATUS = 3 ; (Ref page 5-25)
|
RR_INTR_PENDING_STATUS = 3 ; (Ref page 5-25)
|
||||||
INTR_PENDING_RX_EXT_A = %00101000 ; ANDed (RX or special IRQ)
|
|
||||||
INTR_PENDING_RX_EXT_B = %00000101 ; ANDed (RX or special IRQ)
|
|
||||||
INTR_IS_RX = %00100100 ; ANDed (RX IRQ, channel A or B)
|
INTR_IS_RX = %00100100 ; ANDed (RX IRQ, channel A or B)
|
||||||
|
|
||||||
SER_FLAG_CH_A = %00111000
|
|
||||||
SER_FLAG_CH_B = %00000111
|
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
|
||||||
; Read register value to A.
|
; Read register value to A.
|
||||||
|
@ -329,6 +338,15 @@ IIgs:
|
||||||
: txa ; Promote char return value
|
: txa ; Promote char return value
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
getClockSource:
|
||||||
|
.assert SER_PARAMS::BAUDRATE = 0, error
|
||||||
|
lda (ptr1) ; Baudrate index - cc65 value
|
||||||
|
cmp #SER_BAUD_115200
|
||||||
|
lda #$00
|
||||||
|
adc #$00
|
||||||
|
sta CurClockSource ; 0 = BRG, 1 = RTxC
|
||||||
|
rts
|
||||||
|
|
||||||
;----------------------------------------------------------------------------
|
;----------------------------------------------------------------------------
|
||||||
; SER_OPEN: A pointer to a ser_params structure is passed in ptr1.
|
; SER_OPEN: A pointer to a ser_params structure is passed in ptr1.
|
||||||
; Must return an SER_ERR_xx code in a/x.
|
; Must return an SER_ERR_xx code in a/x.
|
||||||
|
@ -360,11 +378,13 @@ SER_OPEN:
|
||||||
ldy #RR_INIT_STATUS ; Hit rr0 once to sync up
|
ldy #RR_INIT_STATUS ; Hit rr0 once to sync up
|
||||||
jsr readSSCReg
|
jsr readSSCReg
|
||||||
|
|
||||||
ldy #WR_MISC_CTRL ; Turn everything off
|
ldy #WR_MISC_CTRL ; WR14: Turn everything off
|
||||||
lda #$00
|
lda #$00
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg
|
||||||
|
|
||||||
ldy #SER_PARAMS::STOPBITS
|
jsr getClockSource ; Should we use BRG or RTxC?
|
||||||
|
|
||||||
|
ldy #SER_PARAMS::STOPBITS ; WR4 setup: clock mult., stop & parity
|
||||||
lda (ptr1),y ; Stop bits
|
lda (ptr1),y ; Stop bits
|
||||||
tay
|
tay
|
||||||
lda StopTable,y ; Get value
|
lda StopTable,y ; Get value
|
||||||
|
@ -377,36 +397,33 @@ SER_OPEN:
|
||||||
ora ParityTable,y ; Get value
|
ora ParityTable,y ; Get value
|
||||||
bmi InvParam
|
bmi InvParam
|
||||||
|
|
||||||
ora #TX_RX_CLOCK_MUL
|
ldy CurClockSource ; Clock multiplier
|
||||||
|
ora ClockMultiplier,y
|
||||||
|
|
||||||
ldy #WR_TX_RX_CTRL ; Setup stop & parity bits
|
ldy #WR_TX_RX_CTRL
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg ; End of WR4 setup
|
||||||
|
|
||||||
|
ldy CurClockSource ; WR11 setup: clock source
|
||||||
cpx #CHANNEL_B
|
cpx #CHANNEL_B
|
||||||
bne ClockA
|
beq SetClock
|
||||||
ClockB:
|
iny ; Shift to get correct ClockSource val
|
||||||
|
iny ; depending on our channel
|
||||||
|
|
||||||
|
SetClock:
|
||||||
|
lda ClockSource,y
|
||||||
ldy #WR_CLOCK_CTRL
|
ldy #WR_CLOCK_CTRL
|
||||||
lda #CLOCK_CTRL_CH_B
|
jsr writeSCCReg ; End of WR11 setup
|
||||||
jsr writeSCCReg
|
|
||||||
|
|
||||||
lda #INTR_PENDING_RX_EXT_B ; Store which IRQ bits we'll check
|
lda ChanIrqFlags,x ; Store which IRQ bits we'll check
|
||||||
sta CurChanIrqFlags
|
|
||||||
|
|
||||||
bra SetBaud
|
|
||||||
ClockA:
|
|
||||||
ldy #WR_CLOCK_CTRL
|
|
||||||
lda #CLOCK_CTRL_CH_A
|
|
||||||
jsr writeSCCReg
|
|
||||||
|
|
||||||
lda #INTR_PENDING_RX_EXT_A ; Store which IRQ bits we'll check
|
|
||||||
sta CurChanIrqFlags
|
sta CurChanIrqFlags
|
||||||
|
|
||||||
SetBaud:
|
SetBaud:
|
||||||
ldy #SER_PARAMS::BAUDRATE
|
.assert SER_PARAMS::BAUDRATE = 0, error
|
||||||
lda (ptr1),y ; Baudrate index - cc65 value
|
lda (ptr1) ; Baudrate index - cc65 value
|
||||||
|
asl
|
||||||
tay
|
tay
|
||||||
|
|
||||||
lda BaudTable,y ; Get chip value from Low/High tables
|
lda BaudTable,y ; Get low byte of register value
|
||||||
bpl BaudOK ; Verify baudrate is supported
|
bpl BaudOK ; Verify baudrate is supported
|
||||||
|
|
||||||
InvParam:
|
InvParam:
|
||||||
|
@ -415,59 +432,57 @@ InvParam:
|
||||||
bra SetupOut
|
bra SetupOut
|
||||||
|
|
||||||
BaudOK:
|
BaudOK:
|
||||||
tay
|
phy ; WR12 setup: BRG time constant, low byte
|
||||||
|
ldy #WR_BAUDL_CTRL ; Setting WR12 & 13 is useless if we're using
|
||||||
lda BaudLowTable,y ; Get low byte
|
jsr writeSCCReg ; RTxC, but doing it anyway makes code smaller
|
||||||
|
|
||||||
phy
|
|
||||||
ldy #WR_BAUDL_CTRL
|
|
||||||
jsr writeSCCReg
|
|
||||||
ply
|
ply
|
||||||
|
|
||||||
lda BaudHighTable,y ; Get high byte
|
iny
|
||||||
|
lda BaudTable,y ; WR13 setup: BRG time constant, high byte
|
||||||
ldy #WR_BAUDH_CTRL
|
ldy #WR_BAUDH_CTRL
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg
|
||||||
|
|
||||||
|
ldy CurClockSource ; WR14 setup: BRG enabling
|
||||||
|
lda BrgEnabled,y
|
||||||
ldy #WR_MISC_CTRL ; Time to turn this thing on
|
ldy #WR_MISC_CTRL ; Time to turn this thing on
|
||||||
lda #MISC_CTRL_RATE_GEN_ON
|
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg
|
||||||
|
|
||||||
ldy #SER_PARAMS::DATABITS
|
ldy #SER_PARAMS::DATABITS ; WR3 setup: RX data bits
|
||||||
lda (ptr1),y ; Data bits
|
lda (ptr1),y
|
||||||
tay
|
tay
|
||||||
lda RxBitTable,y ; Data bits for RX
|
lda RxBitTable,y
|
||||||
ora #RX_CTRL_ON ; and turn RX on
|
ora #RX_CTRL_ON ; and turn receiver on
|
||||||
|
|
||||||
phy
|
phy
|
||||||
ldy #WR_RX_CTRL
|
ldy #WR_RX_CTRL
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg ; End of WR3 setup
|
||||||
ply
|
ply
|
||||||
|
|
||||||
lda TxBitTable,y ; Data bits for TX
|
lda TxBitTable,y ; WR5 setup: TX data bits
|
||||||
ora #TX_CTRL_ON ; and turn TX on
|
ora #TX_CTRL_ON ; and turn transmitter on
|
||||||
and #TX_DTR_ON
|
and #TX_DTR_ON ; and turn DTR on
|
||||||
|
|
||||||
sta RtsOff ; Save value for flow control
|
sta RtsOff ; Save value for flow control
|
||||||
|
|
||||||
ora #TX_RTS_ON
|
ora #TX_RTS_ON ; and turn RTS on
|
||||||
|
|
||||||
ldy #WR_TX_CTRL
|
ldy #WR_TX_CTRL
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg ; End of WR5 setup
|
||||||
|
|
||||||
ldy #WR_IRQ_CTRL
|
ldy #WR_IRQ_CTRL ; WR15 setup: IRQ
|
||||||
lda #IRQ_CLEANUP_EIRQ
|
lda #IRQ_CLEANUP_EIRQ
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg
|
||||||
|
|
||||||
ldy #WR_INIT_CTRL ; Clear ext status (write twice)
|
ldy #WR_INIT_CTRL ; WR0 setup: clear existing IRQs
|
||||||
lda #INIT_CTRL_CLEAR_EIRQ
|
lda #INIT_CTRL_CLEAR_EIRQ
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg ; Clear (write twice)
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg
|
||||||
|
|
||||||
ldy #WR_TX_RX_MODE_CTRL ; Activate RX IRQ
|
ldy #WR_TX_RX_MODE_CTRL ; WR1 setup: Activate RX IRQ
|
||||||
lda #TX_RX_MODE_RXIRQ
|
lda #TX_RX_MODE_RXIRQ
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg
|
||||||
|
|
||||||
lda SCCBREG ; Activate master IRQ
|
lda SCCBREG ; WR9 setup: Activate master IRQ
|
||||||
ldy #WR_MASTER_IRQ_RST
|
ldy #WR_MASTER_IRQ_RST
|
||||||
lda #MASTER_IRQ_SET
|
lda #MASTER_IRQ_SET
|
||||||
jsr writeSCCReg
|
jsr writeSCCReg
|
||||||
|
@ -475,14 +490,7 @@ BaudOK:
|
||||||
lda SER_FLAG ; Get SerFlag's current value
|
lda SER_FLAG ; Get SerFlag's current value
|
||||||
sta SerFlagOrig ; and save it
|
sta SerFlagOrig ; and save it
|
||||||
|
|
||||||
cpx #CHANNEL_B
|
ora ChanIrqMask,x ; Tell firmware which channel IRQs we want
|
||||||
bne IntA
|
|
||||||
IntB:
|
|
||||||
ora #SER_FLAG_CH_B ; Inform firmware we want channel B IRQs
|
|
||||||
bra StoreFlag
|
|
||||||
IntA:
|
|
||||||
ora #SER_FLAG_CH_A ; Inform firmware we want channel A IRQs
|
|
||||||
StoreFlag:
|
|
||||||
sta SER_FLAG
|
sta SER_FLAG
|
||||||
|
|
||||||
ldy #$01 ; Mark port opened
|
ldy #$01 ; Mark port opened
|
||||||
|
|
|
@ -121,7 +121,7 @@ BaudTable: ; Table used to translate RS232 baudrate param
|
||||||
.byte $0F ; SER_BAUD_19200
|
.byte $0F ; SER_BAUD_19200
|
||||||
.byte $FF ; SER_BAUD_38400
|
.byte $FF ; SER_BAUD_38400
|
||||||
.byte $FF ; SER_BAUD_57600
|
.byte $FF ; SER_BAUD_57600
|
||||||
.byte $FF ; SER_BAUD_115200
|
.byte $00 ; SER_BAUD_115200
|
||||||
.byte $FF ; SER_BAUD_230400
|
.byte $FF ; SER_BAUD_230400
|
||||||
|
|
||||||
BitTable: ; Table used to translate RS232 databits param
|
BitTable: ; Table used to translate RS232 databits param
|
||||||
|
@ -302,6 +302,7 @@ HandshakeOK:
|
||||||
lda (ptr1),y ; Baudrate index
|
lda (ptr1),y ; Baudrate index
|
||||||
tay
|
tay
|
||||||
lda BaudTable,y ; Get 6551 value
|
lda BaudTable,y ; Get 6551 value
|
||||||
|
sta tmp2 ; Backup for IRQ setting
|
||||||
bpl BaudOK ; Check that baudrate is supported
|
bpl BaudOK ; Check that baudrate is supported
|
||||||
|
|
||||||
lda #SER_ERR_BAUD_UNAVAIL
|
lda #SER_ERR_BAUD_UNAVAIL
|
||||||
|
@ -332,8 +333,13 @@ BaudOK: sta tmp1
|
||||||
|
|
||||||
ora #%00000001 ; Set DTR active
|
ora #%00000001 ; Set DTR active
|
||||||
sta RtsOff ; Store value to easily handle flow control later
|
sta RtsOff ; Store value to easily handle flow control later
|
||||||
ora #%00001000 ; Enable receive interrupts (RTS low)
|
|
||||||
sta ACIA_CMD,x
|
ora #%00001010 ; Disable interrupts and set RTS low
|
||||||
|
|
||||||
|
ldy tmp2 ; Don't enable IRQs if 115200bps
|
||||||
|
beq :+
|
||||||
|
and #%11111101 ; Enable receive IRQs
|
||||||
|
: sta ACIA_CMD,x
|
||||||
|
|
||||||
; Done
|
; Done
|
||||||
stx Index ; Mark port as open
|
stx Index ; Mark port as open
|
||||||
|
|
29
libsrc/apple2/set_iigs_speed.s
Normal file
29
libsrc/apple2/set_iigs_speed.s
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||||
|
;
|
||||||
|
; unsigned char __fastcall__ detect_iigs(unsigned char speed)
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _set_iigs_speed
|
||||||
|
.import ostype, return0
|
||||||
|
|
||||||
|
.include "apple2.inc"
|
||||||
|
.include "accelerator.inc"
|
||||||
|
|
||||||
|
_set_iigs_speed:
|
||||||
|
tax ; Keep parameter
|
||||||
|
lda ostype ; Return if not IIgs
|
||||||
|
bmi :+
|
||||||
|
jmp return0
|
||||||
|
|
||||||
|
: lda CYAREG
|
||||||
|
cpx #SPEED_SLOW
|
||||||
|
beq :+
|
||||||
|
ora #%10000000
|
||||||
|
bne set_speed
|
||||||
|
: and #%01111111
|
||||||
|
set_speed:
|
||||||
|
sta CYAREG
|
||||||
|
txa
|
||||||
|
ldx #$00
|
||||||
|
rts
|
54
libsrc/apple2/sleep.s
Normal file
54
libsrc/apple2/sleep.s
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira <colin@colino.net>, 2024
|
||||||
|
;
|
||||||
|
; void __fastcall__ sleep(unsigned s)
|
||||||
|
;
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _sleep
|
||||||
|
.import _get_iigs_speed
|
||||||
|
.import _set_iigs_speed
|
||||||
|
.import WAIT
|
||||||
|
.importzp tmp1
|
||||||
|
|
||||||
|
.include "accelerator.inc"
|
||||||
|
|
||||||
|
; This functions uses the Apple2 WAIT ROM routine to waste a certain
|
||||||
|
; amount of cycles and returns approximately after the numbers of
|
||||||
|
; seconds passed in AX.
|
||||||
|
;
|
||||||
|
; It takes 1023730 cycles when called with AX=1 (1,0007s),
|
||||||
|
; 10236364 cycles when called with AX=10 (10,006 seconds),
|
||||||
|
; 306064298 cycles with AX=300 (299.2 seconds).
|
||||||
|
;
|
||||||
|
; Caveat: IRQs firing during calls to sleep will make the sleep longer
|
||||||
|
; by the amount of cycles it takes to handle the IRQ.
|
||||||
|
;
|
||||||
|
_sleep:
|
||||||
|
stx tmp1 ; High byte of s in X
|
||||||
|
tay ; Low byte in A
|
||||||
|
ora tmp1
|
||||||
|
bne :+
|
||||||
|
rts
|
||||||
|
: jsr _get_iigs_speed ; Save current CPU speed
|
||||||
|
pha
|
||||||
|
lda #SPEED_SLOW ; Down to 1MHz for consistency around WAIT
|
||||||
|
jsr _set_iigs_speed
|
||||||
|
sleep_1s:
|
||||||
|
ldx #$0A ; Loop 10 times
|
||||||
|
sleep_100ms:
|
||||||
|
lda #$C7 ; Sleep about 99ms
|
||||||
|
jsr WAIT
|
||||||
|
lda #$0D ; About 1ms
|
||||||
|
jsr WAIT
|
||||||
|
dex
|
||||||
|
bne sleep_100ms
|
||||||
|
dey
|
||||||
|
bne sleep_1s
|
||||||
|
dec tmp1
|
||||||
|
bmi done
|
||||||
|
dey ; Down to #$FF
|
||||||
|
bne sleep_1s
|
||||||
|
done:
|
||||||
|
pla ; Restore CPU speed
|
||||||
|
jmp _set_iigs_speed
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
.export _statvfs
|
.export _statvfs
|
||||||
.import _dio_query_sectsize
|
.import _dio_query_sectsize
|
||||||
.import mli_file_info, pushax, popax, popptr1
|
.import mli_file_info, pushax, popax, popptr1, pushptr1
|
||||||
.include "zeropage.inc"
|
.include "zeropage.inc"
|
||||||
.include "apple2.inc"
|
.include "apple2.inc"
|
||||||
.include "errno.inc"
|
.include "errno.inc"
|
||||||
|
@ -45,9 +45,7 @@ _statvfs:
|
||||||
sty vol_sep ; Register '/' index
|
sty vol_sep ; Register '/' index
|
||||||
lda #$00
|
lda #$00
|
||||||
sta (ptr1),y ; Cut pathname at first slash
|
sta (ptr1),y ; Cut pathname at first slash
|
||||||
: lda ptr1
|
: jsr pushptr1
|
||||||
ldx ptr1+1
|
|
||||||
jsr pushax
|
|
||||||
|
|
||||||
jsr mli_file_info
|
jsr mli_file_info
|
||||||
|
|
||||||
|
|
20
libsrc/apple2/wait.s
Normal file
20
libsrc/apple2/wait.s
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; WAIT routine
|
||||||
|
;
|
||||||
|
|
||||||
|
.export WAIT
|
||||||
|
|
||||||
|
.include "apple2.inc"
|
||||||
|
|
||||||
|
.segment "LOWCODE"
|
||||||
|
|
||||||
|
WAIT:
|
||||||
|
; Switch in ROM and call WAIT
|
||||||
|
bit $C082
|
||||||
|
jsr $FCA8 ; Vector to WAIT routine
|
||||||
|
|
||||||
|
; Switch in LC bank 2 for R/O and return
|
||||||
|
bit $C080
|
||||||
|
rts
|
|
@ -5,21 +5,11 @@
|
||||||
;
|
;
|
||||||
.ifdef __APPLE2ENH__
|
.ifdef __APPLE2ENH__
|
||||||
|
|
||||||
.constructor initvsync
|
|
||||||
.export _waitvsync
|
.export _waitvsync
|
||||||
.import _get_ostype
|
.import ostype
|
||||||
|
|
||||||
.include "apple2.inc"
|
.include "apple2.inc"
|
||||||
|
|
||||||
.segment "ONCE"
|
|
||||||
|
|
||||||
initvsync:
|
|
||||||
jsr _get_ostype
|
|
||||||
sta ostype
|
|
||||||
rts
|
|
||||||
|
|
||||||
.code
|
|
||||||
|
|
||||||
_waitvsync:
|
_waitvsync:
|
||||||
bit ostype
|
bit ostype
|
||||||
bmi iigs ; $8x
|
bmi iigs ; $8x
|
||||||
|
@ -53,8 +43,4 @@ iic: sei
|
||||||
cli
|
cli
|
||||||
rts
|
rts
|
||||||
|
|
||||||
.segment "INIT"
|
|
||||||
|
|
||||||
ostype: .res 1
|
|
||||||
|
|
||||||
.endif ; __APPLE2ENH__
|
.endif ; __APPLE2ENH__
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
.import findfreeiocb
|
.import findfreeiocb
|
||||||
.import incsp4
|
.import incsp4
|
||||||
.import ldaxysp,addysp
|
.import ldaxysp,addysp
|
||||||
.import ___oserror
|
.import ___oserror, returnFFFF
|
||||||
.ifdef UCASE_FILENAME
|
.ifdef UCASE_FILENAME
|
||||||
.import ucase_fn
|
.import ucase_fn
|
||||||
.endif
|
.endif
|
||||||
|
@ -39,9 +39,7 @@ parmok: jsr findfreeiocb
|
||||||
lda #<EMFILE ; "too many open files"
|
lda #<EMFILE ; "too many open files"
|
||||||
seterr: jsr ___directerrno
|
seterr: jsr ___directerrno
|
||||||
jsr incsp4 ; clean up stack
|
jsr incsp4 ; clean up stack
|
||||||
lda #$FF
|
jmp returnFFFF
|
||||||
tax
|
|
||||||
rts ; return -1
|
|
||||||
|
|
||||||
; process the mode argument
|
; process the mode argument
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
.export _cbm_read
|
.export _cbm_read
|
||||||
.importzp ptr1, ptr2, ptr3, tmp1
|
.importzp ptr1, ptr2, ptr3, tmp1
|
||||||
.import popax, popa
|
.import popax, popa, returnFFFF
|
||||||
.import ___oserror
|
.import ___oserror
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +107,4 @@ _cbm_read:
|
||||||
; CHKIN failed
|
; CHKIN failed
|
||||||
|
|
||||||
@E1: sta ___oserror
|
@E1: sta ___oserror
|
||||||
lda #$FF
|
jmp returnFFFF
|
||||||
tax
|
|
||||||
rts ; return -1
|
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
.export _cbm_write
|
.export _cbm_write
|
||||||
.importzp ptr1, ptr2, ptr3
|
.importzp ptr1, ptr2, ptr3
|
||||||
.import popax, popa
|
.import popax, popa, returnFFFF
|
||||||
.import ___oserror
|
.import ___oserror
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,7 +88,4 @@ _cbm_write:
|
||||||
; Error entry, error code is in A
|
; Error entry, error code is in A
|
||||||
|
|
||||||
@E2: sta ___oserror
|
@E2: sta ___oserror
|
||||||
lda #$FF
|
jmp returnFFFF
|
||||||
tax
|
|
||||||
rts ; return -1
|
|
||||||
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
** _is_leap_year.h
|
|
||||||
**
|
|
||||||
** (C) Copyright 2024, Colin Leroy-Mira <colin@colino.net>
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __IS_LEAP_YEAR_H
|
|
||||||
#define __IS_LEAP_YEAR_H
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned char __fastcall__ IsLeapYear (unsigned char Year);
|
|
||||||
/* Returns 1 if the given year is a leap year. Expects a year from 0 to 206,
|
|
||||||
* without 1900 added */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of _is_leap_year.h */
|
|
||||||
#endif
|
|
|
@ -1,23 +0,0 @@
|
||||||
;
|
|
||||||
; Colin Leroy-Mira, 2024
|
|
||||||
;
|
|
||||||
; unsigned char __fastcall__ IsLeapYear (unsigned char Year)
|
|
||||||
; Returns 1 in A if the given year is a leap year. Expects a year from 0 to 206,
|
|
||||||
; without 1900 added.
|
|
||||||
;
|
|
||||||
|
|
||||||
.export _IsLeapYear
|
|
||||||
|
|
||||||
_IsLeapYear:
|
|
||||||
ldx #$00 ; Prepare X for rts
|
|
||||||
cmp #$00 ; Y 0 (1900) is not a leap year
|
|
||||||
beq NotLeap
|
|
||||||
cmp #$C8 ; Y 200 (2100) is not a leap year
|
|
||||||
beq NotLeap
|
|
||||||
and #$03 ; Year % 4 == 0 means leap year
|
|
||||||
bne NotLeap
|
|
||||||
lda #$01 ; Return 1
|
|
||||||
rts
|
|
||||||
NotLeap:
|
|
||||||
lda #$00 ; Return 0
|
|
||||||
rts
|
|
|
@ -13,6 +13,7 @@
|
||||||
.import _strlower, _strlen
|
.import _strlower, _strlen
|
||||||
|
|
||||||
.macpack generic
|
.macpack generic
|
||||||
|
.macpack cpu
|
||||||
|
|
||||||
; ----------------------------------------------------------------------------
|
; ----------------------------------------------------------------------------
|
||||||
; We will store variables into the register bank in the zeropage. Define
|
; We will store variables into the register bank in the zeropage. Define
|
||||||
|
@ -37,7 +38,11 @@ FCount = ptr2
|
||||||
|
|
||||||
GetFormatChar:
|
GetFormatChar:
|
||||||
ldy #0
|
ldy #0
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
lda (Format)
|
||||||
|
.else
|
||||||
lda (Format),y
|
lda (Format),y
|
||||||
|
.endif
|
||||||
IncFormatPtr:
|
IncFormatPtr:
|
||||||
inc Format
|
inc Format
|
||||||
bne @L1
|
bne @L1
|
||||||
|
@ -110,7 +115,11 @@ GetIntArg:
|
||||||
lda (ArgList),y
|
lda (ArgList),y
|
||||||
tax
|
tax
|
||||||
dey
|
dey
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
lda (ArgList)
|
||||||
|
.else
|
||||||
lda (ArgList),y
|
lda (ArgList),y
|
||||||
|
.endif
|
||||||
rts
|
rts
|
||||||
|
|
||||||
; ----------------------------------------------------------------------------
|
; ----------------------------------------------------------------------------
|
||||||
|
@ -135,9 +144,9 @@ ReadInt:
|
||||||
pha ; Save digit value
|
pha ; Save digit value
|
||||||
lda ptr1
|
lda ptr1
|
||||||
ldx ptr1+1
|
ldx ptr1+1
|
||||||
asl ptr1
|
asl a
|
||||||
rol ptr1+1 ; * 2
|
rol ptr1+1 ; * 2
|
||||||
asl ptr1
|
asl a
|
||||||
rol ptr1+1 ; * 4, assume carry clear
|
rol ptr1+1 ; * 4, assume carry clear
|
||||||
adc ptr1
|
adc ptr1
|
||||||
sta ptr1
|
sta ptr1
|
||||||
|
@ -265,10 +274,16 @@ Save: lda regbank,y
|
||||||
; Initialize the output counter in the output descriptor to zero
|
; Initialize the output counter in the output descriptor to zero
|
||||||
|
|
||||||
lda #0
|
lda #0
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
sta (OutData)
|
||||||
|
ldy #$01
|
||||||
|
sta (OutData),y
|
||||||
|
.else
|
||||||
tay
|
tay
|
||||||
sta (OutData),y
|
sta (OutData),y
|
||||||
iny
|
iny
|
||||||
sta (OutData),y
|
sta (OutData),y
|
||||||
|
.endif
|
||||||
|
|
||||||
; Get the output function from the output descriptor and remember it
|
; Get the output function from the output descriptor and remember it
|
||||||
|
|
||||||
|
@ -338,7 +353,11 @@ MainLoop:
|
||||||
sta (sp),y
|
sta (sp),y
|
||||||
dey
|
dey
|
||||||
lda FCount
|
lda FCount
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
sta (sp)
|
||||||
|
.else
|
||||||
sta (sp),y
|
sta (sp),y
|
||||||
|
.endif
|
||||||
jsr CallOutFunc ; Call the output function
|
jsr CallOutFunc ; Call the output function
|
||||||
|
|
||||||
; We're back from out(), or we didn't call it. Check for end of string.
|
; We're back from out(), or we didn't call it. Check for end of string.
|
||||||
|
@ -551,10 +570,16 @@ CheckCount:
|
||||||
jsr GetIntArg
|
jsr GetIntArg
|
||||||
sta ptr1
|
sta ptr1
|
||||||
stx ptr1+1 ; Get user supplied pointer
|
stx ptr1+1 ; Get user supplied pointer
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
lda (OutData) ; Low byte of OutData->ccount
|
||||||
|
sta (ptr1)
|
||||||
|
ldy #1
|
||||||
|
.else
|
||||||
ldy #0
|
ldy #0
|
||||||
lda (OutData),y ; Low byte of OutData->ccount
|
lda (OutData),y ; Low byte of OutData->ccount
|
||||||
sta (ptr1),y
|
sta (ptr1),y
|
||||||
iny
|
iny
|
||||||
|
.endif
|
||||||
lda (OutData),y ; High byte of OutData->ccount
|
lda (OutData),y ; High byte of OutData->ccount
|
||||||
sta (ptr1),y
|
sta (ptr1),y
|
||||||
jmp MainLoop ; Done
|
jmp MainLoop ; Done
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*****************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* gmtime.c */
|
|
||||||
/* */
|
|
||||||
/* Convert calendar time into broken down time in UTC */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* (C) 2002 Ullrich von Bassewitz */
|
|
||||||
/* Wacholderweg 14 */
|
|
||||||
/* D-70597 Stuttgart */
|
|
||||||
/* EMail: uz@musoftware.de */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* 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 <time.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Code */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
struct tm* __fastcall__ _time_t_to_tm (const time_t t)
|
|
||||||
{
|
|
||||||
static struct tm timebuf;
|
|
||||||
/* Since our ints are just 16 bits, split the given time into seconds,
|
|
||||||
** hours and days. Each of the values will fit in a 16 bit variable.
|
|
||||||
** The mktime routine will then do the rest.
|
|
||||||
*/
|
|
||||||
timebuf.tm_sec = t % 3600;
|
|
||||||
timebuf.tm_min = 0;
|
|
||||||
timebuf.tm_hour = (t / 3600) % 24;
|
|
||||||
timebuf.tm_mday = (t / (3600UL * 24UL)) + 1;
|
|
||||||
timebuf.tm_mon = 0;
|
|
||||||
timebuf.tm_year = 70; /* Base value is 1/1/1970 */
|
|
||||||
|
|
||||||
/* Call mktime to do the final conversion */
|
|
||||||
mktime (&timebuf);
|
|
||||||
|
|
||||||
/* Return the result */
|
|
||||||
return &timebuf;
|
|
||||||
}
|
|
129
libsrc/common/_time_t_to_tm.s
Normal file
129
libsrc/common/_time_t_to_tm.s
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; struct tm* __fastcall__ _time_t_to_tm (const time_t t)
|
||||||
|
;
|
||||||
|
; Helper to gmtime and localtime. Breaks down a number of
|
||||||
|
; seconds since Jan 1, 1970 into days, hours and seconds,
|
||||||
|
; so that each of them fits in 16 bits; passes the
|
||||||
|
; result to _mktime which fixes all values in the struct,
|
||||||
|
; and returns a pointer to the struct to callers.
|
||||||
|
;
|
||||||
|
|
||||||
|
.export __time_t_to_tm
|
||||||
|
.import udiv32, _mktime
|
||||||
|
.importzp sreg, tmp3, ptr1, ptr2, ptr3, ptr4
|
||||||
|
|
||||||
|
.include "time.inc"
|
||||||
|
|
||||||
|
.macpack cpu
|
||||||
|
|
||||||
|
__time_t_to_tm:
|
||||||
|
; Divide number of seconds since epoch, in ptr1:sreg,
|
||||||
|
; by 86400 to get the number of days since epoch, and
|
||||||
|
; the number of seconds today in the remainder.
|
||||||
|
|
||||||
|
; Load t as dividend (sreg is already set by the caller)
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
|
||||||
|
; Load 86400 as divisor
|
||||||
|
lda #$80
|
||||||
|
sta ptr3
|
||||||
|
lda #$51
|
||||||
|
sta ptr3+1
|
||||||
|
lda #$01
|
||||||
|
sta ptr4
|
||||||
|
lda #$00
|
||||||
|
sta ptr4+1
|
||||||
|
|
||||||
|
; Clear TM buf while we have zero in A
|
||||||
|
ldx #.sizeof(tm)-1
|
||||||
|
: sta TM,x
|
||||||
|
dex
|
||||||
|
bpl :-
|
||||||
|
|
||||||
|
; Divide t/86400
|
||||||
|
jsr udiv32
|
||||||
|
|
||||||
|
; Store the quotient (the number of full days), and increment
|
||||||
|
; by one as epoch starts at day 1.
|
||||||
|
clc
|
||||||
|
lda ptr1
|
||||||
|
adc #1
|
||||||
|
sta TM + tm::tm_mday
|
||||||
|
lda ptr1+1
|
||||||
|
adc #0
|
||||||
|
sta TM + tm::tm_mday+1
|
||||||
|
|
||||||
|
; Now divide the number of remaining seconds by 3600,
|
||||||
|
; to get the number of hours, and the seconds in the
|
||||||
|
; current hour, in neat 16-bit integers.
|
||||||
|
|
||||||
|
; Load the previous division's remainder (in ptr2:tmp3:tmp4)
|
||||||
|
; as dividend
|
||||||
|
lda ptr2
|
||||||
|
sta ptr1
|
||||||
|
lda ptr2+1
|
||||||
|
sta ptr1+1
|
||||||
|
lda tmp3
|
||||||
|
sta sreg
|
||||||
|
; We ignore the high byte stored in tmp4 because it will be
|
||||||
|
; zero. We'll zero sreg+1 right below, when we'll have
|
||||||
|
; a convenient zero already in A.
|
||||||
|
|
||||||
|
; Load divisor
|
||||||
|
lda #<3600
|
||||||
|
sta ptr3
|
||||||
|
lda #>3600
|
||||||
|
sta ptr3+1
|
||||||
|
|
||||||
|
; Zero the two high bytes of the divisor and the high byte
|
||||||
|
; of the dividend.
|
||||||
|
.if .cpu .bitand CPU_ISET_65SC02
|
||||||
|
stz ptr4
|
||||||
|
stz ptr4+1
|
||||||
|
stz sreg+1
|
||||||
|
.else
|
||||||
|
lda #$00
|
||||||
|
sta ptr4
|
||||||
|
sta ptr4+1
|
||||||
|
sta sreg+1
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Do the division
|
||||||
|
jsr udiv32
|
||||||
|
|
||||||
|
; Store year
|
||||||
|
lda #70
|
||||||
|
sta TM + tm::tm_year
|
||||||
|
|
||||||
|
; Store hours (the quotient of the last division)
|
||||||
|
lda ptr1
|
||||||
|
sta TM + tm::tm_hour
|
||||||
|
lda ptr1+1
|
||||||
|
sta TM + tm::tm_hour+1
|
||||||
|
|
||||||
|
; Store seconds (the remainder of the last division)
|
||||||
|
lda ptr2
|
||||||
|
sta TM + tm::tm_sec
|
||||||
|
lda ptr2+1
|
||||||
|
sta TM + tm::tm_sec+1
|
||||||
|
|
||||||
|
; The rest of the struct tm fields are zero. mktime
|
||||||
|
; will take care of shifting extra seconds to minutes,
|
||||||
|
; and extra days to months and years.
|
||||||
|
|
||||||
|
; Call mktime
|
||||||
|
lda #<TM
|
||||||
|
ldx #>TM
|
||||||
|
jsr _mktime
|
||||||
|
|
||||||
|
; And return our pointer
|
||||||
|
lda #<TM
|
||||||
|
ldx #>TM
|
||||||
|
rts
|
||||||
|
|
||||||
|
.bss
|
||||||
|
|
||||||
|
TM: .tag tm
|
|
@ -1,59 +0,0 @@
|
||||||
/*****************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* asctime.c */
|
|
||||||
/* */
|
|
||||||
/* Convert a broken down time into a string */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* (C) 2002 Ullrich von Bassewitz */
|
|
||||||
/* Wacholderweg 14 */
|
|
||||||
/* D-70597 Stuttgart */
|
|
||||||
/* EMail: uz@musoftware.de */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* 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 <time.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Code */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
CAUTION: we need to reserve enough space to be able to hold the maximum
|
|
||||||
length string:
|
|
||||||
|
|
||||||
1234567890123456789012345678901234567
|
|
||||||
"Wednesday September ..1 00:00:00 1970"
|
|
||||||
*/
|
|
||||||
|
|
||||||
char* __fastcall__ asctime (const struct tm* timep)
|
|
||||||
{
|
|
||||||
static char buf[38];
|
|
||||||
|
|
||||||
/* Format into given buffer and return the result */
|
|
||||||
return strftime (buf, sizeof (buf), "%c\n", timep)? buf : 0;
|
|
||||||
}
|
|
81
libsrc/common/asctime.s
Normal file
81
libsrc/common/asctime.s
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; char* __fastcall__ asctime (const struct tm* timep)
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _asctime
|
||||||
|
.import _strftime, pushax
|
||||||
|
.importzp ptr1
|
||||||
|
.include "time.inc"
|
||||||
|
|
||||||
|
.macpack cpu
|
||||||
|
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
|
; Special values
|
||||||
|
|
||||||
|
; We need to be able to store up to 38 bytes:
|
||||||
|
; 1234567890123456789012345678901234567
|
||||||
|
; "Wednesday September ..1 00:00:00 1970"
|
||||||
|
MAX_BUF_LEN = 38
|
||||||
|
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
|
; Code
|
||||||
|
|
||||||
|
_asctime:
|
||||||
|
; Backup timep
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
pha
|
||||||
|
phx
|
||||||
|
.else
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Push buf
|
||||||
|
lda #<buf
|
||||||
|
ldx #>buf
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
; Push sizeof(buf)
|
||||||
|
lda #<MAX_BUF_LEN
|
||||||
|
ldx #>MAX_BUF_LEN
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
; Push format string
|
||||||
|
lda #<fmt
|
||||||
|
ldx #>fmt
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
; Restore timep
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
plx
|
||||||
|
pla
|
||||||
|
.else
|
||||||
|
lda ptr1
|
||||||
|
ldx ptr1+1
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Call formatter
|
||||||
|
jsr _strftime
|
||||||
|
|
||||||
|
; Check return status
|
||||||
|
bne :+
|
||||||
|
cpx #$00
|
||||||
|
bne :+
|
||||||
|
rts
|
||||||
|
|
||||||
|
: lda #<buf
|
||||||
|
ldx #>buf
|
||||||
|
rts
|
||||||
|
|
||||||
|
.data
|
||||||
|
|
||||||
|
fmt: .byte '%'
|
||||||
|
.byte 'c'
|
||||||
|
.byte $0A
|
||||||
|
.byte $00
|
||||||
|
|
||||||
|
.bss
|
||||||
|
|
||||||
|
buf: .res MAX_BUF_LEN
|
24
libsrc/common/checkferror.s
Normal file
24
libsrc/common/checkferror.s
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; Helper to check for file opened, not eof, not ferror
|
||||||
|
; Expects file pointer in ptr1,
|
||||||
|
; Returns with Z flag set if everything is OK,
|
||||||
|
; Destroys A, X, Y,
|
||||||
|
; Sets file flags in A
|
||||||
|
;
|
||||||
|
|
||||||
|
.export checkferror
|
||||||
|
.importzp ptr1
|
||||||
|
|
||||||
|
.include "_file.inc"
|
||||||
|
|
||||||
|
checkferror:
|
||||||
|
ldy #_FILE::f_flags
|
||||||
|
lda (ptr1),y
|
||||||
|
tax
|
||||||
|
and #(_FOPEN|_FERROR|_FEOF); Check for file open, error/eof
|
||||||
|
tay
|
||||||
|
txa
|
||||||
|
cpy #_FOPEN
|
||||||
|
rts
|
|
@ -3,7 +3,7 @@
|
||||||
; 2002-10-22, Greg King
|
; 2002-10-22, Greg King
|
||||||
;
|
;
|
||||||
; This signed-division function returns both the quotient and the remainder,
|
; This signed-division function returns both the quotient and the remainder,
|
||||||
; in this structure:
|
; in this structure: (quotient in sreg, remainder in AX)
|
||||||
;
|
;
|
||||||
; typedef struct {
|
; typedef struct {
|
||||||
; int rem, quot;
|
; int rem, quot;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
.export _fclose
|
.export _fclose
|
||||||
|
|
||||||
.import _close
|
.import _close, ___directerrno
|
||||||
.importzp ptr1
|
.importzp ptr1
|
||||||
|
|
||||||
.include "errno.inc"
|
.include "errno.inc"
|
||||||
|
@ -31,10 +31,7 @@
|
||||||
; File is not open
|
; File is not open
|
||||||
|
|
||||||
lda #EINVAL
|
lda #EINVAL
|
||||||
jsr ___seterrno
|
jmp ___directerrno
|
||||||
lda #$FF ; Return -1
|
|
||||||
tax
|
|
||||||
rts
|
|
||||||
|
|
||||||
; File is open. Reset the flags and close the file.
|
; File is open. Reset the flags and close the file.
|
||||||
|
|
||||||
|
@ -47,4 +44,3 @@
|
||||||
jmp _close ; Will set errno and return an error flag
|
jmp _close ; Will set errno and return an error flag
|
||||||
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
** fgetc.c
|
|
||||||
**
|
|
||||||
** (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org)
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "_file.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Code */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int __fastcall__ fgetc (register FILE* f)
|
|
||||||
{
|
|
||||||
unsigned char c;
|
|
||||||
|
|
||||||
/* Check if the file is open or if there is an error condition */
|
|
||||||
if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have a pushed back character, return it */
|
|
||||||
if (f->f_flags & _FPUSHBACK) {
|
|
||||||
f->f_flags &= ~_FPUSHBACK;
|
|
||||||
return f->f_pushback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read one byte */
|
|
||||||
switch (read (f->f_fd, &c, 1)) {
|
|
||||||
|
|
||||||
case -1:
|
|
||||||
/* Error */
|
|
||||||
f->f_flags |= _FERROR;
|
|
||||||
return EOF;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
/* EOF */
|
|
||||||
f->f_flags |= _FEOF;
|
|
||||||
return EOF;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* Char read */
|
|
||||||
return c;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
94
libsrc/common/fgetc.s
Normal file
94
libsrc/common/fgetc.s
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; int __fastcall__ fgetc (register FILE* f)
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _fgetc
|
||||||
|
.import _read, checkferror
|
||||||
|
.import pusha0, pushax, popptr1, incsp2, returnFFFF
|
||||||
|
.importzp ptr1
|
||||||
|
|
||||||
|
.include "stdio.inc"
|
||||||
|
.include "_file.inc"
|
||||||
|
|
||||||
|
.macpack cpu
|
||||||
|
|
||||||
|
_fgetc:
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
jsr pushax ; Backup our ptr
|
||||||
|
|
||||||
|
jsr checkferror
|
||||||
|
bne ret_eof
|
||||||
|
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
bit #_FPUSHBACK ; Check for pushed back char
|
||||||
|
beq do_read
|
||||||
|
.else
|
||||||
|
tax
|
||||||
|
and #_FPUSHBACK ; Check for pushed back char
|
||||||
|
beq do_read
|
||||||
|
txa
|
||||||
|
.endif
|
||||||
|
|
||||||
|
and #<(~_FPUSHBACK) ; Reset flag
|
||||||
|
sta (ptr1),y
|
||||||
|
|
||||||
|
.assert _FILE::f_pushback = _FILE::f_flags+1, error
|
||||||
|
iny
|
||||||
|
jsr incsp2 ; Drop our ptr copy
|
||||||
|
lda (ptr1),y ; Return pushed back char
|
||||||
|
ldx #$00
|
||||||
|
rts
|
||||||
|
|
||||||
|
do_read:
|
||||||
|
; Push _read parameters
|
||||||
|
ldy #_FILE::f_fd
|
||||||
|
lda (ptr1),y
|
||||||
|
jsr pusha0
|
||||||
|
|
||||||
|
lda #<c
|
||||||
|
ldx #>c
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
lda #$01
|
||||||
|
ldx #$00
|
||||||
|
|
||||||
|
; Read
|
||||||
|
jsr _read
|
||||||
|
|
||||||
|
; Check for errors
|
||||||
|
cmp #$00
|
||||||
|
beq set_feof
|
||||||
|
|
||||||
|
cmp #<(-1)
|
||||||
|
beq set_ferror
|
||||||
|
|
||||||
|
jsr incsp2
|
||||||
|
; Return char
|
||||||
|
ldx #$00
|
||||||
|
lda c
|
||||||
|
rts
|
||||||
|
|
||||||
|
ret_eof:
|
||||||
|
jsr incsp2
|
||||||
|
jmp returnFFFF
|
||||||
|
|
||||||
|
set_ferror:
|
||||||
|
lda #_FERROR
|
||||||
|
bne set_err
|
||||||
|
set_feof:
|
||||||
|
lda #_FEOF
|
||||||
|
set_err:
|
||||||
|
pha
|
||||||
|
jsr popptr1
|
||||||
|
pla
|
||||||
|
ldy #_FILE::f_flags
|
||||||
|
ora (ptr1),y
|
||||||
|
sta (ptr1),y
|
||||||
|
jmp returnFFFF
|
||||||
|
|
||||||
|
.bss
|
||||||
|
|
||||||
|
c: .res 1
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
** Ullrich von Bassewitz, 11.08.1998
|
|
||||||
**
|
|
||||||
** char* fgets (char* s, int size, FILE* f);
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "_file.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Code */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char* __fastcall__ fgets (char* s, unsigned size, register FILE* f)
|
|
||||||
{
|
|
||||||
register char* p = s;
|
|
||||||
unsigned i;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
/* Invalid size */
|
|
||||||
return (char*) _seterrno (EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read input */
|
|
||||||
i = 0;
|
|
||||||
while (--size) {
|
|
||||||
|
|
||||||
/* Get next character */
|
|
||||||
if ((c = fgetc (f)) == EOF) {
|
|
||||||
/* Error or EOF */
|
|
||||||
if ((f->f_flags & _FERROR) != 0 || i == 0) {
|
|
||||||
/* ERROR or EOF on first char */
|
|
||||||
*p = '\0';
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
/* EOF with data already read */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* One char more */
|
|
||||||
*p = c;
|
|
||||||
++p;
|
|
||||||
++i;
|
|
||||||
|
|
||||||
/* Stop at end of line */
|
|
||||||
if ((char)c == '\n') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Terminate the string */
|
|
||||||
*p = '\0';
|
|
||||||
|
|
||||||
/* Done */
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
117
libsrc/common/fgets.s
Normal file
117
libsrc/common/fgets.s
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; char* __fastcall__ fgets (char* s, unsigned size, register FILE* f)
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _fgets
|
||||||
|
.import _fgetc, popptr1, pushptr1, popax, pushax, return0, ___errno
|
||||||
|
.importzp ptr1, ptr4
|
||||||
|
|
||||||
|
.include "errno.inc"
|
||||||
|
.include "stdio.inc"
|
||||||
|
.include "_file.inc"
|
||||||
|
|
||||||
|
.macpack cpu
|
||||||
|
|
||||||
|
terminate_ptr:
|
||||||
|
lda #$00
|
||||||
|
tax
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
sta (ptr4)
|
||||||
|
.else
|
||||||
|
tay
|
||||||
|
sta (ptr4),y
|
||||||
|
.endif
|
||||||
|
rts
|
||||||
|
|
||||||
|
_fgets:
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
|
||||||
|
jsr popax
|
||||||
|
sta size
|
||||||
|
stx size+1
|
||||||
|
|
||||||
|
jsr popax
|
||||||
|
sta ptr4
|
||||||
|
stx ptr4+1
|
||||||
|
sta buf
|
||||||
|
stx buf+1
|
||||||
|
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
stz didread
|
||||||
|
.else
|
||||||
|
lda #$00 ; We have read nothing yet
|
||||||
|
sta didread
|
||||||
|
.endif
|
||||||
|
|
||||||
|
; Check size
|
||||||
|
lda size
|
||||||
|
ora size+1
|
||||||
|
bne read_loop
|
||||||
|
lda #EINVAL
|
||||||
|
sta ___errno
|
||||||
|
jmp return0
|
||||||
|
|
||||||
|
read_loop:
|
||||||
|
lda size ; Dec size
|
||||||
|
bne :+
|
||||||
|
dec size+1
|
||||||
|
: dec size
|
||||||
|
|
||||||
|
bne :+ ; Check bound
|
||||||
|
ldx size+1
|
||||||
|
beq done
|
||||||
|
|
||||||
|
: jsr pushptr1 ; Push ptr1 for backup and load it to AX for fgetc
|
||||||
|
jsr _fgetc ; Read a char
|
||||||
|
|
||||||
|
pha
|
||||||
|
jsr popptr1 ; Get ptr1 back
|
||||||
|
pla
|
||||||
|
|
||||||
|
cpx #<EOF
|
||||||
|
beq got_eof
|
||||||
|
|
||||||
|
ldy #$01
|
||||||
|
sty didread ; We read at least one char
|
||||||
|
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
sta (ptr4)
|
||||||
|
.else
|
||||||
|
dey
|
||||||
|
sta (ptr4),y
|
||||||
|
.endif
|
||||||
|
|
||||||
|
inc ptr4
|
||||||
|
bne :+
|
||||||
|
inc ptr4+1
|
||||||
|
|
||||||
|
: cmp #$0A ; Stop at \n
|
||||||
|
beq done
|
||||||
|
bne read_loop
|
||||||
|
|
||||||
|
got_eof:
|
||||||
|
lda didread
|
||||||
|
beq stopped_at_first_char
|
||||||
|
ldy #_FILE::f_flags
|
||||||
|
lda (ptr1),y
|
||||||
|
and #_FERROR
|
||||||
|
bne stopped_at_first_char
|
||||||
|
|
||||||
|
done:
|
||||||
|
jsr terminate_ptr
|
||||||
|
ldx #>buf
|
||||||
|
lda #<buf
|
||||||
|
rts
|
||||||
|
|
||||||
|
stopped_at_first_char:
|
||||||
|
jmp terminate_ptr
|
||||||
|
|
||||||
|
.bss
|
||||||
|
|
||||||
|
c: .res 1
|
||||||
|
buf: .res 2
|
||||||
|
size: .res 2
|
||||||
|
didread:.res 1
|
|
@ -5,7 +5,7 @@
|
||||||
;
|
;
|
||||||
|
|
||||||
.export _clearerr, _feof, _ferror, _fileno, _fflush
|
.export _clearerr, _feof, _ferror, _fileno, _fflush
|
||||||
.import return0
|
.import return0, ___directerrno
|
||||||
.importzp ptr1
|
.importzp ptr1
|
||||||
|
|
||||||
.include "_file.inc"
|
.include "_file.inc"
|
||||||
|
@ -78,10 +78,7 @@ err: rts
|
||||||
; If the file is not valid, fileno must set errno and return -1
|
; If the file is not valid, fileno must set errno and return -1
|
||||||
|
|
||||||
error: lda #<EBADF
|
error: lda #<EBADF
|
||||||
jsr ___seterrno
|
jmp ___directerrno
|
||||||
lda #$FF
|
|
||||||
tax
|
|
||||||
rts
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
;
|
;
|
||||||
|
@ -89,5 +86,3 @@ error: lda #<EBADF
|
||||||
;
|
;
|
||||||
|
|
||||||
_fflush = return0
|
_fflush = return0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
** fputc.c
|
|
||||||
**
|
|
||||||
** Ullrich von Bassewitz, 02.06.1998
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "_file.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Code */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int __fastcall__ fputc (int c, register FILE* f)
|
|
||||||
{
|
|
||||||
/* Check if the file is open or if there is an error condition */
|
|
||||||
if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
|
|
||||||
goto ReturnEOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the byte */
|
|
||||||
if (write (f->f_fd, &c, 1) != 1) {
|
|
||||||
/* Error */
|
|
||||||
f->f_flags |= _FERROR;
|
|
||||||
ReturnEOF:
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the byte written */
|
|
||||||
return c & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
66
libsrc/common/fputc.s
Normal file
66
libsrc/common/fputc.s
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; int __fastcall__ fputc (int c, FILE* f);
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _fputc
|
||||||
|
.importzp ptr1
|
||||||
|
.import _write, checkferror
|
||||||
|
.import pushax, pusha0, popax, incsp2
|
||||||
|
.import pushptr1, popptr1, returnFFFF
|
||||||
|
|
||||||
|
.include "stdio.inc"
|
||||||
|
.include "_file.inc"
|
||||||
|
|
||||||
|
_fputc:
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
|
||||||
|
jsr popax ; Get char, as we'll have
|
||||||
|
sta c ; to return it anyway
|
||||||
|
stx c+1
|
||||||
|
|
||||||
|
jsr checkferror
|
||||||
|
bne ret_eof
|
||||||
|
|
||||||
|
jsr pushptr1 ; Backup fp pointer
|
||||||
|
|
||||||
|
; Push _write parameters
|
||||||
|
ldy #_FILE::f_fd
|
||||||
|
lda (ptr1),y
|
||||||
|
jsr pusha0
|
||||||
|
|
||||||
|
lda #<c
|
||||||
|
ldx #>c
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
lda #$01
|
||||||
|
ldx #$00
|
||||||
|
|
||||||
|
; Write
|
||||||
|
jsr _write
|
||||||
|
|
||||||
|
; Check for errors
|
||||||
|
cmp #$01
|
||||||
|
bne set_ferror
|
||||||
|
|
||||||
|
; Return char
|
||||||
|
lda c
|
||||||
|
ldx #$00
|
||||||
|
jmp incsp2 ; Drop fp pointer copy
|
||||||
|
|
||||||
|
ret_eof:
|
||||||
|
jmp returnFFFF
|
||||||
|
|
||||||
|
set_ferror:
|
||||||
|
jsr popptr1
|
||||||
|
lda #_FERROR
|
||||||
|
ldy #_FILE::f_flags
|
||||||
|
ora (ptr1),y
|
||||||
|
sta (ptr1),y
|
||||||
|
jmp returnFFFF
|
||||||
|
|
||||||
|
.bss
|
||||||
|
|
||||||
|
c: .res 2
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
** int fputs (const char* s, FILE* f);
|
|
||||||
**
|
|
||||||
** Ullrich von Bassewitz, 11.08.1998
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "_file.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int __fastcall__ fputs (const char* s, register FILE* f)
|
|
||||||
{
|
|
||||||
/* Check if the file is open or if there is an error condition */
|
|
||||||
if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) {
|
|
||||||
return EOF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the string */
|
|
||||||
return write (f->f_fd, s, strlen (s));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
36
libsrc/common/fputs.s
Normal file
36
libsrc/common/fputs.s
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; int __fastcall__ fputs (const char* s, register FILE* f)
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _fputs
|
||||||
|
.importzp ptr1, ptr2
|
||||||
|
.import _write, _strlen, checkferror
|
||||||
|
.import swapstk, pushax, returnFFFF
|
||||||
|
|
||||||
|
.include "stdio.inc"
|
||||||
|
.include "_file.inc"
|
||||||
|
|
||||||
|
_fputs:
|
||||||
|
sta ptr1
|
||||||
|
stx ptr1+1
|
||||||
|
|
||||||
|
jsr checkferror
|
||||||
|
bne ret_eof
|
||||||
|
|
||||||
|
; Push _write parameters
|
||||||
|
ldy #_FILE::f_fd
|
||||||
|
lda (ptr1),y
|
||||||
|
ldx #$00
|
||||||
|
jsr swapstk ; Push fd, get s
|
||||||
|
|
||||||
|
jsr pushax ; Push s
|
||||||
|
|
||||||
|
jsr _strlen ; Get length
|
||||||
|
|
||||||
|
; Write
|
||||||
|
jmp _write
|
||||||
|
|
||||||
|
ret_eof:
|
||||||
|
jmp returnFFFF
|
|
@ -20,6 +20,7 @@
|
||||||
.include "_file.inc"
|
.include "_file.inc"
|
||||||
|
|
||||||
.macpack generic
|
.macpack generic
|
||||||
|
.macpack cpu
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
; ------------------------------------------------------------------------
|
||||||
; Code
|
; Code
|
||||||
|
@ -47,13 +48,21 @@
|
||||||
|
|
||||||
ldy #_FILE::f_flags
|
ldy #_FILE::f_flags
|
||||||
lda (file),y
|
lda (file),y
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
bit #_FOPEN ; Is the file open?
|
||||||
|
.else
|
||||||
and #_FOPEN ; Is the file open?
|
and #_FOPEN ; Is the file open?
|
||||||
|
.endif
|
||||||
beq @L1 ; Branch if no
|
beq @L1 ; Branch if no
|
||||||
|
|
||||||
; Check if the stream is in an error state
|
; Check if the stream is in an error state
|
||||||
|
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
bit #_FERROR
|
||||||
|
.else
|
||||||
lda (file),y ; get file->f_flags again
|
lda (file),y ; get file->f_flags again
|
||||||
and #_FERROR
|
and #_FERROR
|
||||||
|
.endif
|
||||||
beq @L2
|
beq @L2
|
||||||
|
|
||||||
; File not open or in error state
|
; File not open or in error state
|
||||||
|
@ -65,11 +74,19 @@
|
||||||
|
|
||||||
; Remember if we have a pushed back character and reset the flag.
|
; Remember if we have a pushed back character and reset the flag.
|
||||||
|
|
||||||
@L2: tax ; X = 0
|
@L2: .if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
ldx #$00
|
||||||
|
bit #_FPUSHBACK
|
||||||
|
.else
|
||||||
|
tax ; X = 0
|
||||||
lda (file),y
|
lda (file),y
|
||||||
and #_FPUSHBACK
|
and #_FPUSHBACK
|
||||||
|
.endif
|
||||||
beq @L3
|
beq @L3
|
||||||
|
|
||||||
|
.if (.not .cpu .bitand ::CPU_ISET_65SC02)
|
||||||
lda (file),y
|
lda (file),y
|
||||||
|
.endif
|
||||||
and #<~_FPUSHBACK
|
and #<~_FPUSHBACK
|
||||||
sta (file),y ; file->f_flags &= ~_FPUSHBACK;
|
sta (file),y ; file->f_flags &= ~_FPUSHBACK;
|
||||||
inx ; X = 1
|
inx ; X = 1
|
||||||
|
@ -118,12 +135,20 @@
|
||||||
; Copy the buffer pointer into ptr1, and increment the pointer value passed
|
; Copy the buffer pointer into ptr1, and increment the pointer value passed
|
||||||
; to read() by one, so read() starts to store data at buf+1.
|
; to read() by one, so read() starts to store data at buf+1.
|
||||||
|
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
lda (sp)
|
||||||
|
sta ptr1
|
||||||
|
add #1
|
||||||
|
sta (sp)
|
||||||
|
ldy #1
|
||||||
|
.else
|
||||||
ldy #0
|
ldy #0
|
||||||
lda (sp),y
|
lda (sp),y
|
||||||
sta ptr1
|
sta ptr1
|
||||||
add #1
|
add #1
|
||||||
sta (sp),y
|
sta (sp),y
|
||||||
iny
|
iny
|
||||||
|
.endif
|
||||||
lda (sp),y
|
lda (sp),y
|
||||||
sta ptr1+1
|
sta ptr1+1
|
||||||
adc #0
|
adc #0
|
||||||
|
@ -134,8 +159,12 @@
|
||||||
|
|
||||||
ldy #_FILE::f_pushback
|
ldy #_FILE::f_pushback
|
||||||
lda (file),y
|
lda (file),y
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
sta (ptr1) ; *buf = file->f_pushback;
|
||||||
|
.else
|
||||||
ldy #0
|
ldy #0
|
||||||
sta (ptr1),y ; *buf = file->f_pushback;
|
sta (ptr1),y ; *buf = file->f_pushback;
|
||||||
|
.endif
|
||||||
|
|
||||||
; Restore the low byte of count and decrement count by one. This may result
|
; Restore the low byte of count and decrement count by one. This may result
|
||||||
; in count being zero, so check for that.
|
; in count being zero, so check for that.
|
||||||
|
@ -210,4 +239,3 @@
|
||||||
.bss
|
.bss
|
||||||
save: .res 2
|
save: .res 2
|
||||||
pb: .res 1
|
pb: .res 1
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
.export _fwrite
|
.export _fwrite
|
||||||
|
|
||||||
.import _write
|
.import _write
|
||||||
.import pushax, incsp6, addysp, ldaxysp, pushwysp, return0
|
.import pushax, pusha0, incsp6, addysp, ldaxysp, pushwysp, return0
|
||||||
.import tosumulax, tosudivax
|
.import tosumulax, tosudivax
|
||||||
|
|
||||||
.importzp ptr1
|
.importzp ptr1
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
.include "errno.inc"
|
.include "errno.inc"
|
||||||
.include "_file.inc"
|
.include "_file.inc"
|
||||||
|
|
||||||
|
.macpack cpu
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
; ------------------------------------------------------------------------
|
||||||
; Code
|
; Code
|
||||||
|
@ -33,7 +34,11 @@
|
||||||
|
|
||||||
ldy #_FILE::f_flags
|
ldy #_FILE::f_flags
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
bit #_FOPEN
|
||||||
|
.else
|
||||||
and #_FOPEN ; Is the file open?
|
and #_FOPEN ; Is the file open?
|
||||||
|
.endif
|
||||||
bne @L2 ; Branch if yes
|
bne @L2 ; Branch if yes
|
||||||
|
|
||||||
; File not open
|
; File not open
|
||||||
|
@ -45,7 +50,9 @@
|
||||||
|
|
||||||
; Check if the stream is in an error state
|
; Check if the stream is in an error state
|
||||||
|
|
||||||
@L2: lda (ptr1),y ; get file->f_flags again
|
@L2: .if (.not .cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
lda (ptr1),y ; get file->f_flags again
|
||||||
|
.endif
|
||||||
and #_FERROR
|
and #_FERROR
|
||||||
bne @L1
|
bne @L1
|
||||||
|
|
||||||
|
@ -53,8 +60,7 @@
|
||||||
|
|
||||||
ldy #_FILE::f_fd
|
ldy #_FILE::f_fd
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
ldx #$00
|
jsr pusha0 ; file->f_fd
|
||||||
jsr pushax ; file->f_fd
|
|
||||||
|
|
||||||
ldy #9
|
ldy #9
|
||||||
jsr pushwysp ; buf
|
jsr pushwysp ; buf
|
||||||
|
@ -123,4 +129,3 @@
|
||||||
|
|
||||||
.bss
|
.bss
|
||||||
file: .res 2
|
file: .res 2
|
||||||
|
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
** gets.c
|
|
||||||
**
|
|
||||||
** Ullrich von Bassewitz, 11.08.1998
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "_file.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Code */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char* __fastcall__ gets (char* s)
|
|
||||||
{
|
|
||||||
register char* p = s;
|
|
||||||
int c;
|
|
||||||
unsigned i = 0;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
/* Get next character */
|
|
||||||
if ((c = fgetc (stdin)) == EOF) {
|
|
||||||
/* Error or EOF */
|
|
||||||
*p = '\0';
|
|
||||||
if (stdin->f_flags & _FERROR) {
|
|
||||||
/* ERROR */
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
/* EOF */
|
|
||||||
if (i) {
|
|
||||||
return s;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* One char more. Newline ends the input */
|
|
||||||
if ((char) c == '\n') {
|
|
||||||
*p = '\0';
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
*p = c;
|
|
||||||
++p;
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Done */
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
47
libsrc/common/gets.s
Normal file
47
libsrc/common/gets.s
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; char* __fastcall__ gets (char* s)
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _gets
|
||||||
|
.import _fgets, _stdin, popax, pushax
|
||||||
|
.importzp ptr4
|
||||||
|
|
||||||
|
_gets:
|
||||||
|
; Push buffer
|
||||||
|
sta ptr4
|
||||||
|
stx ptr4+1
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
; Push size (there's no limit!)
|
||||||
|
lda #$FF
|
||||||
|
tax
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
lda _stdin
|
||||||
|
ldx _stdin+1
|
||||||
|
|
||||||
|
jsr _fgets
|
||||||
|
|
||||||
|
; Check return value
|
||||||
|
bne :+
|
||||||
|
cpx #$00
|
||||||
|
bne :+
|
||||||
|
rts
|
||||||
|
|
||||||
|
: ; At least one byte written.
|
||||||
|
jsr pushax ; Store returned pointer
|
||||||
|
|
||||||
|
; Remove \n if there is one.
|
||||||
|
lda ptr4 ; _fgets returns with ptr4 at
|
||||||
|
bne :+ ; end of buffer
|
||||||
|
dec ptr4+1
|
||||||
|
: dec ptr4
|
||||||
|
lda (ptr4),y ; _fgets returns with Y=0
|
||||||
|
cmp #$0A
|
||||||
|
bne :+
|
||||||
|
tya
|
||||||
|
sta (ptr4),y ; Set terminator over \n
|
||||||
|
|
||||||
|
: jmp popax
|
|
@ -131,6 +131,7 @@ _malloc:
|
||||||
sta ptr1
|
sta ptr1
|
||||||
bcc @L1
|
bcc @L1
|
||||||
inc ptr1+1
|
inc ptr1+1
|
||||||
|
beq OutOfHeapSpace ; if high byte's 0, we overflowed!
|
||||||
@L1: ldx ptr1+1
|
@L1: ldx ptr1+1
|
||||||
bne @L2
|
bne @L2
|
||||||
cmp #HEAP_MIN_BLOCKSIZE+1
|
cmp #HEAP_MIN_BLOCKSIZE+1
|
||||||
|
@ -336,4 +337,3 @@ RetUserPtr:
|
||||||
bcc @L9
|
bcc @L9
|
||||||
inx
|
inx
|
||||||
@L9: rts
|
@L9: rts
|
||||||
|
|
||||||
|
|
|
@ -1,184 +0,0 @@
|
||||||
/*****************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* mktime.c */
|
|
||||||
/* */
|
|
||||||
/* Make calendar time from broken down time and cleanup */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* (C) 2002 Ullrich von Bassewitz */
|
|
||||||
/* Wacholderweg 14 */
|
|
||||||
/* D-70597 Stuttgart */
|
|
||||||
/* EMail: uz@musoftware.de */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* 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 <limits.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include "_is_leap_year.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Data */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define JANUARY 0
|
|
||||||
#define FEBRUARY 1
|
|
||||||
#define DECEMBER 11
|
|
||||||
#define JAN_1_1970 4 /* 1/1/1970 is a thursday */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const unsigned char MonthLength [] = {
|
|
||||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
|
||||||
};
|
|
||||||
static const unsigned MonthDays [] = {
|
|
||||||
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Code */
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
time_t __fastcall__ mktime (register struct tm* TM)
|
|
||||||
/* Make a time in seconds since 1/1/1970 from the broken down time in TM.
|
|
||||||
** A call to mktime does also correct the time in TM to contain correct
|
|
||||||
** values.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
register div_t D;
|
|
||||||
static int Max;
|
|
||||||
static unsigned DayCount;
|
|
||||||
|
|
||||||
/* Check if TM is valid */
|
|
||||||
if (TM == 0) {
|
|
||||||
/* Invalid data */
|
|
||||||
return (time_t) -1L;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust seconds. */
|
|
||||||
D = div (TM->tm_sec, 60);
|
|
||||||
TM->tm_sec = D.rem;
|
|
||||||
|
|
||||||
/* Adjust minutes */
|
|
||||||
TM->tm_min += D.quot;
|
|
||||||
D = div (TM->tm_min, 60);
|
|
||||||
TM->tm_min = D.rem;
|
|
||||||
|
|
||||||
/* Adjust hours */
|
|
||||||
TM->tm_hour += D.quot;
|
|
||||||
D = div (TM->tm_hour, 24);
|
|
||||||
TM->tm_hour = D.rem;
|
|
||||||
|
|
||||||
/* Adjust days */
|
|
||||||
TM->tm_mday += D.quot;
|
|
||||||
|
|
||||||
/* Adjust year */
|
|
||||||
while (1) {
|
|
||||||
Max = 365UL + IsLeapYear (TM->tm_year);
|
|
||||||
if ((unsigned int)TM->tm_mday > Max) {
|
|
||||||
++TM->tm_year;
|
|
||||||
TM->tm_mday -= Max;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust month and year. This is an iterative process, since changing
|
|
||||||
** the month will change the allowed days for this month.
|
|
||||||
*/
|
|
||||||
while (1) {
|
|
||||||
|
|
||||||
/* Make sure, month is in the range 0..11 */
|
|
||||||
D = div (TM->tm_mon, 12);
|
|
||||||
TM->tm_mon = D.rem;
|
|
||||||
TM->tm_year += D.quot;
|
|
||||||
|
|
||||||
/* Now check if mday is in the correct range, if not, correct month
|
|
||||||
** and eventually year and repeat the process.
|
|
||||||
*/
|
|
||||||
if (TM->tm_mon == FEBRUARY && IsLeapYear (TM->tm_year)) {
|
|
||||||
Max = 29;
|
|
||||||
} else {
|
|
||||||
Max = MonthLength[TM->tm_mon];
|
|
||||||
}
|
|
||||||
if ((unsigned int)TM->tm_mday > Max) {
|
|
||||||
/* Must correct month and eventually, year */
|
|
||||||
if (TM->tm_mon == DECEMBER) {
|
|
||||||
TM->tm_mon = JANUARY;
|
|
||||||
++TM->tm_year;
|
|
||||||
} else {
|
|
||||||
++TM->tm_mon;
|
|
||||||
}
|
|
||||||
TM->tm_mday -= Max;
|
|
||||||
} else {
|
|
||||||
/* Done */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ok, all time/date fields are now correct. Calculate the days in this
|
|
||||||
** year.
|
|
||||||
*/
|
|
||||||
TM->tm_yday = MonthDays[TM->tm_mon] + TM->tm_mday - 1;
|
|
||||||
if (TM->tm_mon > FEBRUARY && IsLeapYear (TM->tm_year)) {
|
|
||||||
++TM->tm_yday;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate days since 1/1/1970. In the complete epoch (1/1/1970 to
|
|
||||||
** somewhere in 2106) all years dividable by 4 are leap years(1),
|
|
||||||
** so dividing by 4 gives the days that must be added because of leap years.
|
|
||||||
** (and the last leap year before 1970 was 1968)
|
|
||||||
** (1): Exception on 2100, which is not leap, and handled just after.
|
|
||||||
*/
|
|
||||||
DayCount = ((unsigned) (TM->tm_year-70)) * 365U +
|
|
||||||
(((unsigned) (TM->tm_year-(68+1))) / 4) +
|
|
||||||
TM->tm_yday;
|
|
||||||
|
|
||||||
/* Handle the 2100 exception */
|
|
||||||
if (TM->tm_year == 200 && TM->tm_mon > FEBRUARY) {
|
|
||||||
DayCount--;
|
|
||||||
} else if (TM->tm_year > 200) {
|
|
||||||
DayCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate the weekday */
|
|
||||||
TM->tm_wday = (JAN_1_1970 + DayCount) % 7;
|
|
||||||
|
|
||||||
/* No (US) daylight saving (for now) */
|
|
||||||
TM->tm_isdst = 0;
|
|
||||||
|
|
||||||
/* Return seconds since 1970 */
|
|
||||||
return DayCount * 86400UL +
|
|
||||||
((unsigned) TM->tm_hour) * 3600UL +
|
|
||||||
((unsigned) TM->tm_min) * 60U +
|
|
||||||
((unsigned) TM->tm_sec) -
|
|
||||||
_tz.timezone;
|
|
||||||
}
|
|
476
libsrc/common/mktime.s
Normal file
476
libsrc/common/mktime.s
Normal file
|
@ -0,0 +1,476 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; time_t __fastcall__ mktime (register struct tm* TM)
|
||||||
|
;
|
||||||
|
; Converts a struct tm to a time_t timestamp, making sure
|
||||||
|
; day, month, year, hour, minute and seconds are in the
|
||||||
|
; correct range.
|
||||||
|
;
|
||||||
|
|
||||||
|
.export _mktime
|
||||||
|
.import __tz
|
||||||
|
.import pushax, pusha0, pusheax
|
||||||
|
.import shrax2, _div, tosumulax, tosumodax, tossubeax, tosaddeax, tosumuleax
|
||||||
|
.importzp ptr2, tmp3, sreg
|
||||||
|
|
||||||
|
.include "time.inc"
|
||||||
|
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
|
; Special values
|
||||||
|
|
||||||
|
FEBRUARY = 1
|
||||||
|
MARCH = 2
|
||||||
|
JAN_1_1970 = 4
|
||||||
|
N_SEC = 60
|
||||||
|
N_MIN = 60
|
||||||
|
N_HOUR = 24
|
||||||
|
N_MON = 12
|
||||||
|
N_DAY_YEAR = 365
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
|
; Helpers
|
||||||
|
|
||||||
|
; Helper to shift overflows from one field to the next
|
||||||
|
; Current field in Y, divisor in A
|
||||||
|
; Keeps remainder in current field, and adds the quotient
|
||||||
|
; to the next one
|
||||||
|
adjust_field:
|
||||||
|
pha ; Push divisor
|
||||||
|
iny ; Point to high byte of current field
|
||||||
|
lda (ptr2),y
|
||||||
|
tax
|
||||||
|
dey
|
||||||
|
sty tmp3 ; Store current field (_div will mess with
|
||||||
|
lda (ptr2),y ; tmp1 and tmp2)
|
||||||
|
jsr pushax
|
||||||
|
pla ; Load divisor
|
||||||
|
ldx #$00
|
||||||
|
|
||||||
|
jsr _div
|
||||||
|
|
||||||
|
ldy tmp3 ; Store remainder in current field
|
||||||
|
sta (ptr2),y
|
||||||
|
iny
|
||||||
|
txa
|
||||||
|
sta (ptr2),y
|
||||||
|
|
||||||
|
lda sreg ; Add quotient to next field
|
||||||
|
iny
|
||||||
|
clc
|
||||||
|
adc (ptr2),y
|
||||||
|
sta (ptr2),y
|
||||||
|
iny
|
||||||
|
lda sreg+1
|
||||||
|
adc (ptr2),y
|
||||||
|
sta (ptr2),y
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Returns 1 in A if the given year is a leap year. Expects a year
|
||||||
|
; from 0 to 206, without 1900 added.
|
||||||
|
is_leap_year:
|
||||||
|
cmp #$00 ; Y 0 (1900) is not a leap year
|
||||||
|
beq not_leap
|
||||||
|
cmp #$C8 ; Y 200 (2100) is not a leap year
|
||||||
|
beq not_leap
|
||||||
|
and #$03 ; Year % 4 == 0 means leap year
|
||||||
|
bne not_leap
|
||||||
|
lda #$01 ; Return 1
|
||||||
|
rts
|
||||||
|
not_leap:
|
||||||
|
lda #$00 ; Return 0
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Returns the number of days in the current month/year in A
|
||||||
|
get_days_in_month:
|
||||||
|
ldy #tm::tm_mon
|
||||||
|
lda (ptr2),y
|
||||||
|
tax
|
||||||
|
lda months_len,x
|
||||||
|
cpx #FEBRUARY
|
||||||
|
beq :+
|
||||||
|
rts
|
||||||
|
: tax
|
||||||
|
ldy #tm::tm_year ; Adjust for leap years
|
||||||
|
lda (ptr2),y
|
||||||
|
jsr is_leap_year
|
||||||
|
beq :+
|
||||||
|
inx
|
||||||
|
: txa
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Add AX to counter
|
||||||
|
addaxcounter:
|
||||||
|
clc
|
||||||
|
adc Counter
|
||||||
|
sta Counter ; Store in Counter
|
||||||
|
txa
|
||||||
|
adc Counter+1
|
||||||
|
sta Counter+1
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Helpers for long chain of arithmetic on day counter.
|
||||||
|
; Reload Counter and push it on the stack
|
||||||
|
load_and_push_counter:
|
||||||
|
lda Counter+3
|
||||||
|
sta sreg+1
|
||||||
|
lda Counter+2
|
||||||
|
sta sreg
|
||||||
|
lda Counter
|
||||||
|
ldx Counter+1
|
||||||
|
jsr pusheax
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Store result in AX:sreg to Counter
|
||||||
|
store_counter:
|
||||||
|
sta Counter
|
||||||
|
stx Counter+1
|
||||||
|
lda sreg
|
||||||
|
sta Counter+2
|
||||||
|
lda sreg+1
|
||||||
|
sta Counter+3
|
||||||
|
rts
|
||||||
|
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
|
; Code
|
||||||
|
|
||||||
|
_mktime:
|
||||||
|
sta ptr2 ; Store struct to ptr2, which arithmetic
|
||||||
|
stx ptr2+1 ; functions won't touch
|
||||||
|
|
||||||
|
; Check pointer validity
|
||||||
|
ora ptr2+1
|
||||||
|
bne :+
|
||||||
|
lda #$FF
|
||||||
|
tax
|
||||||
|
sta sreg
|
||||||
|
sta sreg+1
|
||||||
|
rts
|
||||||
|
|
||||||
|
; Adjust seconds
|
||||||
|
: ldy #tm::tm_sec
|
||||||
|
lda #N_SEC
|
||||||
|
jsr adjust_field
|
||||||
|
|
||||||
|
; Adjust minutes
|
||||||
|
ldy #tm::tm_min
|
||||||
|
lda #N_MIN
|
||||||
|
jsr adjust_field
|
||||||
|
|
||||||
|
; Adjust hours
|
||||||
|
ldy #tm::tm_hour
|
||||||
|
lda #N_HOUR
|
||||||
|
jsr adjust_field
|
||||||
|
|
||||||
|
;Shift one year as long as tm_mday is more than a year
|
||||||
|
ldy #tm::tm_year
|
||||||
|
lda (ptr2),y
|
||||||
|
|
||||||
|
dec_by_year:
|
||||||
|
jsr is_leap_year ; Compute max numbers of days in year
|
||||||
|
clc
|
||||||
|
adc #<N_DAY_YEAR ; No care about carry,
|
||||||
|
sta Max ; 365+1 doesn't overflow low byte
|
||||||
|
|
||||||
|
ldy #tm::tm_mday+1 ; Do we have more days in store?
|
||||||
|
lda (ptr2),y
|
||||||
|
cmp #>N_DAY_YEAR
|
||||||
|
beq :+ ; High byte equal, check low byte
|
||||||
|
bcs do_year_dec ; High byte greater, decrement
|
||||||
|
bcc dec_by_month ; Low byte lower, we're done
|
||||||
|
: dey
|
||||||
|
lda (ptr2),y
|
||||||
|
cmp Max
|
||||||
|
bcc dec_by_month
|
||||||
|
beq dec_by_month
|
||||||
|
|
||||||
|
do_year_dec:
|
||||||
|
; Decrement days
|
||||||
|
ldy #tm::tm_mday
|
||||||
|
lda (ptr2),y
|
||||||
|
sbc Max ; Carry already set
|
||||||
|
sta (ptr2),y
|
||||||
|
iny
|
||||||
|
lda (ptr2),y
|
||||||
|
sbc #>N_DAY_YEAR
|
||||||
|
sta (ptr2),y
|
||||||
|
|
||||||
|
; Increment year
|
||||||
|
ldy #tm::tm_year
|
||||||
|
lda (ptr2),y
|
||||||
|
clc
|
||||||
|
adc #1
|
||||||
|
sta (ptr2),y ; No carry possible here either
|
||||||
|
bcc dec_by_year ; bra, go check next year
|
||||||
|
|
||||||
|
dec_by_month:
|
||||||
|
; We're done decrementing days by full years, now do it
|
||||||
|
; month per month.
|
||||||
|
ldy #tm::tm_mon
|
||||||
|
lda #N_MON
|
||||||
|
jsr adjust_field
|
||||||
|
|
||||||
|
; Get max day for this month
|
||||||
|
jsr get_days_in_month
|
||||||
|
sta Max
|
||||||
|
|
||||||
|
; So, do we have more days than this month?
|
||||||
|
ldy #tm::tm_mday+1
|
||||||
|
lda (ptr2),y
|
||||||
|
bne do_month_dec ; High byte not zero, sure we do
|
||||||
|
dey
|
||||||
|
lda (ptr2),y
|
||||||
|
cmp Max
|
||||||
|
bcc calc_tm_yday ; No
|
||||||
|
beq calc_tm_yday
|
||||||
|
|
||||||
|
do_month_dec:
|
||||||
|
; Decrement days
|
||||||
|
ldy #tm::tm_mday
|
||||||
|
lda (ptr2),y
|
||||||
|
sec
|
||||||
|
sbc Max
|
||||||
|
sta (ptr2),y
|
||||||
|
iny
|
||||||
|
lda (ptr2),y
|
||||||
|
sbc #$00
|
||||||
|
sta (ptr2),y
|
||||||
|
|
||||||
|
; Increment month
|
||||||
|
ldy #tm::tm_mon
|
||||||
|
lda (ptr2),y
|
||||||
|
clc
|
||||||
|
adc #1
|
||||||
|
sta (ptr2),y
|
||||||
|
|
||||||
|
bne dec_by_month ; Check next month
|
||||||
|
|
||||||
|
calc_tm_yday:
|
||||||
|
; We finished decrementing tm_mday and have put it in the correct
|
||||||
|
; year/month range. Now compute the day of the year.
|
||||||
|
ldy #tm::tm_mday ; Get current day of month
|
||||||
|
lda (ptr2),y
|
||||||
|
sta Counter ; Store it in Counter
|
||||||
|
|
||||||
|
lda #$00 ; Init counter high bytes
|
||||||
|
sta Counter+1
|
||||||
|
sta Counter+2
|
||||||
|
sta Counter+3
|
||||||
|
|
||||||
|
ldy #tm::tm_mon ; Get current month
|
||||||
|
lda (ptr2),y
|
||||||
|
asl
|
||||||
|
tax
|
||||||
|
clc
|
||||||
|
lda yday_by_month,x ; Get yday for this month's start
|
||||||
|
adc Counter ; Add it to counter
|
||||||
|
sta Counter
|
||||||
|
inx
|
||||||
|
lda yday_by_month,x
|
||||||
|
adc Counter+1
|
||||||
|
sta Counter+1
|
||||||
|
|
||||||
|
ldy #tm::tm_year ; Adjust for leap years (if after feb)
|
||||||
|
lda (ptr2),y
|
||||||
|
jsr is_leap_year
|
||||||
|
beq dec_counter
|
||||||
|
ldy #tm::tm_mon ; Leap year, get current month
|
||||||
|
lda (ptr2),y
|
||||||
|
cmp #MARCH
|
||||||
|
bcs store_yday
|
||||||
|
|
||||||
|
dec_counter:
|
||||||
|
lda Counter ; Decrease counter by one (yday starts at 0),
|
||||||
|
bne :+ ; unless we're after february in a leap year
|
||||||
|
dec Counter+1
|
||||||
|
: dec Counter
|
||||||
|
|
||||||
|
store_yday:
|
||||||
|
ldy #tm::tm_yday ; Store tm_yday
|
||||||
|
lda Counter
|
||||||
|
sta (ptr2),y
|
||||||
|
iny
|
||||||
|
lda Counter+1
|
||||||
|
sta (ptr2),y
|
||||||
|
|
||||||
|
; Now calculate total day count since epoch with the formula:
|
||||||
|
; ((unsigned) (TM->tm_year-70)) * 365U + (number of days per year since 1970)
|
||||||
|
; (((unsigned) (TM->tm_year-(68+1))) / 4) + (one extra day per leap year since 1970)
|
||||||
|
; TM->tm_yday (number of days in this year)
|
||||||
|
|
||||||
|
ldy #tm::tm_year ; Get full years
|
||||||
|
lda (ptr2),y
|
||||||
|
sec
|
||||||
|
sbc #70
|
||||||
|
ldx #0
|
||||||
|
jsr pushax
|
||||||
|
lda #<N_DAY_YEAR
|
||||||
|
ldx #>N_DAY_YEAR
|
||||||
|
|
||||||
|
jsr tosumulax
|
||||||
|
jsr addaxcounter
|
||||||
|
|
||||||
|
; Add one day per leap year
|
||||||
|
ldy #tm::tm_year ; Get full years
|
||||||
|
lda (ptr2),y
|
||||||
|
sec
|
||||||
|
sbc #69
|
||||||
|
ldx #0
|
||||||
|
jsr shrax2 ; Divide by 4
|
||||||
|
|
||||||
|
jsr addaxcounter
|
||||||
|
|
||||||
|
; Handle the 2100 exception (which was considered leap by "Add one day
|
||||||
|
; per leap year" just before)
|
||||||
|
ldy #tm::tm_year ; Get full years
|
||||||
|
lda (ptr2),y
|
||||||
|
cmp #201
|
||||||
|
bcc finish_calc ; <= 200, nothing to do
|
||||||
|
|
||||||
|
lda Counter
|
||||||
|
bne :+
|
||||||
|
dec Counter+1
|
||||||
|
: dec Counter
|
||||||
|
|
||||||
|
finish_calc:
|
||||||
|
; Now we can compute the weekday.
|
||||||
|
lda Counter
|
||||||
|
clc
|
||||||
|
adc #JAN_1_1970
|
||||||
|
pha
|
||||||
|
lda Counter+1
|
||||||
|
adc #0
|
||||||
|
tax
|
||||||
|
pla
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
lda #7 ; Modulo 7
|
||||||
|
ldx #0
|
||||||
|
jsr tosumodax
|
||||||
|
|
||||||
|
ldy #tm::tm_wday ; Store tm_wday
|
||||||
|
sta (ptr2),y
|
||||||
|
iny
|
||||||
|
txa
|
||||||
|
sta (ptr2),y
|
||||||
|
|
||||||
|
; DST
|
||||||
|
lda #$00 ; Store tm_isdst
|
||||||
|
ldy #tm::tm_isdst
|
||||||
|
sta (ptr2),y
|
||||||
|
iny
|
||||||
|
sta (ptr2),y
|
||||||
|
|
||||||
|
; Our struct tm is all fixed and every field calculated.
|
||||||
|
; We can finally count seconds according to this formula:
|
||||||
|
; seconds = (full days since epoch) * 86400UL +
|
||||||
|
; ((unsigned) TM->tm_hour) * 3600UL +
|
||||||
|
; ((unsigned) TM->tm_min) * 60U +
|
||||||
|
; ((unsigned) TM->tm_sec) -
|
||||||
|
; _tz.timezone;
|
||||||
|
|
||||||
|
; We already have the number of days since epoch in our counter,
|
||||||
|
; from just before when we computed tm_wday. Reuse it.
|
||||||
|
jsr load_and_push_counter
|
||||||
|
lda #$00 ; Multiply by 86400
|
||||||
|
sta sreg+1
|
||||||
|
lda #$01
|
||||||
|
sta sreg
|
||||||
|
lda #$80
|
||||||
|
ldx #$51
|
||||||
|
jsr tosumuleax
|
||||||
|
jsr store_counter ; Store into counter
|
||||||
|
|
||||||
|
; Push counter to add 3600 * hours to it
|
||||||
|
jsr load_and_push_counter
|
||||||
|
|
||||||
|
ldx #$00 ; Load hours
|
||||||
|
stx sreg
|
||||||
|
stx sreg+1
|
||||||
|
ldy #tm::tm_hour
|
||||||
|
lda (ptr2),y
|
||||||
|
jsr pusheax ; Push
|
||||||
|
ldx #$00 ; Load 3600
|
||||||
|
stx sreg
|
||||||
|
stx sreg+1
|
||||||
|
lda #<3600
|
||||||
|
ldx #>3600
|
||||||
|
jsr tosumuleax ; Multiply (pops the pushed hours)
|
||||||
|
jsr tosaddeax ; Add to counter (pops the pushed counter)
|
||||||
|
jsr store_counter ; Store counter
|
||||||
|
|
||||||
|
; Push counter to add 60 * min to it
|
||||||
|
jsr load_and_push_counter
|
||||||
|
|
||||||
|
ldy #tm::tm_min ; Load minutes
|
||||||
|
lda (ptr2),y
|
||||||
|
jsr pusha0 ; Push
|
||||||
|
lda #N_MIN
|
||||||
|
ldx #0
|
||||||
|
stx sreg
|
||||||
|
stx sreg+1
|
||||||
|
jsr tosumulax ; Multiply
|
||||||
|
jsr tosaddeax ; Add to pushed counter
|
||||||
|
jsr store_counter ; Store
|
||||||
|
|
||||||
|
; Add seconds
|
||||||
|
jsr load_and_push_counter
|
||||||
|
|
||||||
|
ldy #tm::tm_sec ; Load seconds
|
||||||
|
lda (ptr2),y
|
||||||
|
ldx #0
|
||||||
|
stx sreg
|
||||||
|
stx sreg+1
|
||||||
|
jsr tosaddeax ; Simple addition there
|
||||||
|
|
||||||
|
; No need to store/load/push the counter here, simply to push it
|
||||||
|
; for the last substraction
|
||||||
|
jsr pusheax
|
||||||
|
|
||||||
|
; Substract timezone
|
||||||
|
lda __tz+1+3
|
||||||
|
sta sreg+1
|
||||||
|
lda __tz+1+2
|
||||||
|
sta sreg
|
||||||
|
ldx __tz+1+1
|
||||||
|
lda __tz+1
|
||||||
|
jsr tossubeax
|
||||||
|
|
||||||
|
; And we're done!
|
||||||
|
rts
|
||||||
|
|
||||||
|
.data
|
||||||
|
|
||||||
|
months_len:
|
||||||
|
.byte 31
|
||||||
|
.byte 28
|
||||||
|
.byte 31
|
||||||
|
.byte 30
|
||||||
|
.byte 31
|
||||||
|
.byte 30
|
||||||
|
.byte 31
|
||||||
|
.byte 31
|
||||||
|
.byte 30
|
||||||
|
.byte 31
|
||||||
|
.byte 30
|
||||||
|
.byte 31
|
||||||
|
|
||||||
|
yday_by_month:
|
||||||
|
.word 0
|
||||||
|
.word 31
|
||||||
|
.word 59
|
||||||
|
.word 90
|
||||||
|
.word 120
|
||||||
|
.word 151
|
||||||
|
.word 181
|
||||||
|
.word 212
|
||||||
|
.word 243
|
||||||
|
.word 273
|
||||||
|
.word 304
|
||||||
|
.word 334
|
||||||
|
|
||||||
|
|
||||||
|
.bss
|
||||||
|
|
||||||
|
Max: .res 1 ; We won't need a high byte
|
||||||
|
Counter:
|
||||||
|
.res 4
|
|
@ -50,7 +50,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size)
|
int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size)
|
||||||
/* Allocate a block of memory with the given "size", which is aligned to a
|
/* Allocate a block of memory with the given "size", which is aligned to a
|
||||||
** memory address that is a multiple of "alignment". "alignment" MUST NOT be
|
** memory address that is a multiple of "alignment". "alignment" MUST NOT be
|
||||||
|
@ -64,20 +63,27 @@ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size)
|
||||||
size_t rawsize;
|
size_t rawsize;
|
||||||
size_t uppersize;
|
size_t uppersize;
|
||||||
size_t lowersize;
|
size_t lowersize;
|
||||||
|
char err;
|
||||||
register struct usedblock* b; /* points to raw Block */
|
register struct usedblock* b; /* points to raw Block */
|
||||||
register struct usedblock* u; /* points to User block */
|
register struct usedblock* u; /* points to User block */
|
||||||
register struct usedblock* p; /* Points to upper block */
|
register struct usedblock* p; /* Points to upper block */
|
||||||
|
|
||||||
/* Handle requests for zero-sized blocks */
|
/* Handle requests for zero-sized blocks */
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
|
err_einval:
|
||||||
|
err = EINVAL;
|
||||||
|
err_out:
|
||||||
*memptr = NULL;
|
*memptr = NULL;
|
||||||
return EINVAL;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test alignment: is it a power of two? There must be only one bit set. */
|
/* Test alignment: is it a power of two? There must be one and only one bit set. */
|
||||||
if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
|
if (alignment == 0) {
|
||||||
*memptr = NULL;
|
goto err_einval;
|
||||||
return EINVAL;
|
}
|
||||||
|
|
||||||
|
if (alignment & (alignment - 1)) {
|
||||||
|
goto err_einval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Augment the block size up to the alignment, and allocate memory.
|
/* Augment the block size up to the alignment, and allocate memory.
|
||||||
|
@ -90,8 +96,8 @@ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size)
|
||||||
|
|
||||||
/* Handle out-of-memory */
|
/* Handle out-of-memory */
|
||||||
if (b == NULL) {
|
if (b == NULL) {
|
||||||
*memptr = NULL;
|
err = ENOMEM;
|
||||||
return ENOMEM;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create (and return) a new pointer that points to the user-visible
|
/* Create (and return) a new pointer that points to the user-visible
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
.import _malloc, _free
|
.import _malloc, _free
|
||||||
.import searchenv, copyenvptr
|
.import searchenv, copyenvptr
|
||||||
.import __environ, __envcount, __envsize
|
.import __environ, __envcount, __envsize
|
||||||
.import return0
|
.import return0, ___directerrno
|
||||||
.import ptr1:zp, ptr2:zp, ptr3:zp, tmp1:zp
|
.import ptr1:zp, ptr2:zp, ptr3:zp, tmp1:zp
|
||||||
|
|
||||||
.include "errno.inc"
|
.include "errno.inc"
|
||||||
|
@ -169,10 +169,7 @@ addentry:
|
||||||
; Error entries
|
; Error entries
|
||||||
|
|
||||||
nomem: lda #ENOMEM
|
nomem: lda #ENOMEM
|
||||||
error: jsr ___seterrno
|
error: jmp ___directerrno
|
||||||
lda #$FF ; Return -1
|
|
||||||
tax
|
|
||||||
rts
|
|
||||||
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
@ -184,5 +181,3 @@ error: jsr ___seterrno
|
||||||
|
|
||||||
name: .addr 0 ; Pointer to name
|
name: .addr 0 ; Pointer to name
|
||||||
newsize: .byte 0 ; New environment size
|
newsize: .byte 0 ; New environment size
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,112 +0,0 @@
|
||||||
/*****************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* realloc.c */
|
|
||||||
/* */
|
|
||||||
/* Change the size of an allocated memory block */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* (C) 1998-2004 Ullrich von Bassewitz */
|
|
||||||
/* Wacholderweg 14 */
|
|
||||||
/* D-70597 Stuttgart */
|
|
||||||
/* EMail: uz@musoftware.de */
|
|
||||||
/* */
|
|
||||||
/* */
|
|
||||||
/* 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 <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <_heap.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void* __fastcall__ realloc (void* block, register size_t size)
|
|
||||||
{
|
|
||||||
register struct usedblock* b;
|
|
||||||
struct usedblock* newblock;
|
|
||||||
unsigned oldsize;
|
|
||||||
unsigned newhptr;
|
|
||||||
|
|
||||||
/* Check the block parameter */
|
|
||||||
if (!block) {
|
|
||||||
/* Block is NULL, same as malloc */
|
|
||||||
return malloc (size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the size parameter */
|
|
||||||
if (size == 0) {
|
|
||||||
/* Block is not NULL, but size is: free the block */
|
|
||||||
free (block);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make the internal used size from the given size */
|
|
||||||
size += HEAP_ADMIN_SPACE;
|
|
||||||
if (size < sizeof (struct freeblock)) {
|
|
||||||
size = sizeof (struct freeblock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The word below the user block contains a pointer to the start of the
|
|
||||||
** raw memory block. The first word of this raw memory block is the full
|
|
||||||
** size of the block. Get a pointer to the real block, get the old block
|
|
||||||
** size.
|
|
||||||
*/
|
|
||||||
b = (((struct usedblock*) block) - 1)->start;
|
|
||||||
oldsize = b->size;
|
|
||||||
|
|
||||||
/* Is the block at the current heap top? */
|
|
||||||
if (((unsigned) b) + oldsize == ((unsigned) __heapptr)) {
|
|
||||||
/* Check if we've enough memory at the heap top */
|
|
||||||
newhptr = ((unsigned) __heapptr) - oldsize + size;
|
|
||||||
if (newhptr <= ((unsigned) __heapend)) {
|
|
||||||
/* Ok, there's space enough */
|
|
||||||
__heapptr = (unsigned*) newhptr;
|
|
||||||
b->size = size;
|
|
||||||
b->start = b;
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The given block was not located on top of the heap, or there's no
|
|
||||||
** room left. Try to allocate a new block and copy the data.
|
|
||||||
*/
|
|
||||||
if (newblock = malloc (size)) {
|
|
||||||
|
|
||||||
/* Adjust the old size to the user visible portion */
|
|
||||||
oldsize -= HEAP_ADMIN_SPACE;
|
|
||||||
|
|
||||||
/* If the new block is larger than the old one, copy the old
|
|
||||||
** data only
|
|
||||||
*/
|
|
||||||
if (size > oldsize) {
|
|
||||||
size = oldsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the block data */
|
|
||||||
memcpy (newblock, block, size);
|
|
||||||
free (block);
|
|
||||||
}
|
|
||||||
return newblock;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
213
libsrc/common/realloc.s
Normal file
213
libsrc/common/realloc.s
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; void* __fastcall__ realloc (void* block, register size_t size)
|
||||||
|
;
|
||||||
|
|
||||||
|
.importzp ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3, tmp4, sp
|
||||||
|
.import _malloc, _memcpy, _free
|
||||||
|
.import pushax, popptr1, return0
|
||||||
|
.import incsp2, decsp2
|
||||||
|
.export _realloc
|
||||||
|
|
||||||
|
.include "_heap.inc"
|
||||||
|
|
||||||
|
.macpack generic
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Aliases for clarity
|
||||||
|
|
||||||
|
block = ptr1
|
||||||
|
size = ptr2
|
||||||
|
ublock = ptr3
|
||||||
|
oldsize = ptr4
|
||||||
|
newblock = tmp1 ; (and tmp2)
|
||||||
|
orgblock = tmp3 ; (and tmp4)
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------------
|
||||||
|
; Code
|
||||||
|
|
||||||
|
_realloc:
|
||||||
|
sta size ; Store size
|
||||||
|
stx size+1
|
||||||
|
|
||||||
|
jsr popptr1 ; Pop block
|
||||||
|
|
||||||
|
lda block+1 ; Is block null?
|
||||||
|
tax
|
||||||
|
ora block
|
||||||
|
bne :+
|
||||||
|
|
||||||
|
lda size ; Block is null, just malloc
|
||||||
|
ldx size+1
|
||||||
|
jmp _malloc
|
||||||
|
|
||||||
|
: lda size ; Is size 0?
|
||||||
|
ora size+1
|
||||||
|
bne :+
|
||||||
|
|
||||||
|
lda block ; It is: free block (high byte already in X)
|
||||||
|
jsr _free
|
||||||
|
jmp return0
|
||||||
|
|
||||||
|
: clc ; Add internal used size
|
||||||
|
lda size
|
||||||
|
adc #HEAP_ADMIN_SPACE
|
||||||
|
sta size
|
||||||
|
bcc :+
|
||||||
|
inc size+1
|
||||||
|
bne :+
|
||||||
|
|
||||||
|
lda #$00 ; Size high byte now 0: We overflowed!
|
||||||
|
tax
|
||||||
|
rts
|
||||||
|
|
||||||
|
: ldx size+1 ; Should we round size up?
|
||||||
|
bne :+
|
||||||
|
cmp #.sizeof (freeblock)
|
||||||
|
bcs :+
|
||||||
|
|
||||||
|
lda #.sizeof (freeblock)
|
||||||
|
sta size ; (we presuppose that sizeof (freeblock) is < 256)
|
||||||
|
|
||||||
|
: lda block ; Get pointer to raw memory block
|
||||||
|
sta orgblock ; Store original pointer
|
||||||
|
sec
|
||||||
|
sbc #.sizeof(usedblock)
|
||||||
|
sta ublock
|
||||||
|
lda block+1
|
||||||
|
sta orgblock+1 ; Finish storing original pointer
|
||||||
|
sbc #0
|
||||||
|
sta ublock+1 ; We have our usedblock struct
|
||||||
|
|
||||||
|
; Get block start
|
||||||
|
ldy #usedblock::start+1
|
||||||
|
lda (ublock),y
|
||||||
|
tax ; Backup ublock high
|
||||||
|
dey
|
||||||
|
lda (ublock),y
|
||||||
|
|
||||||
|
sta ublock ; Store ublock
|
||||||
|
stx ublock+1
|
||||||
|
|
||||||
|
; Remember oldsize
|
||||||
|
ldy #usedblock::size+1
|
||||||
|
lda (ublock),y
|
||||||
|
sta oldsize+1
|
||||||
|
dey
|
||||||
|
lda (ublock),y
|
||||||
|
sta oldsize
|
||||||
|
|
||||||
|
clc ; Is the block at heap top?
|
||||||
|
adc ublock
|
||||||
|
tay
|
||||||
|
lda ublock+1
|
||||||
|
adc oldsize+1
|
||||||
|
cmp ___heapptr+1
|
||||||
|
bne must_malloc_new
|
||||||
|
cpy ___heapptr
|
||||||
|
bne must_malloc_new
|
||||||
|
|
||||||
|
tya ; Put ___heapptr back in A
|
||||||
|
sec ; Check if we have enough memory at heap top
|
||||||
|
sbc oldsize ; Substract oldsize
|
||||||
|
sta newblock
|
||||||
|
lda ___heapptr+1
|
||||||
|
sbc oldsize+1
|
||||||
|
sta newblock+1
|
||||||
|
clc
|
||||||
|
lda newblock ; And add size
|
||||||
|
adc size
|
||||||
|
sta newblock
|
||||||
|
lda newblock+1
|
||||||
|
adc size+1
|
||||||
|
sta newblock+1
|
||||||
|
bcs must_malloc_new ; If we have a carry there we overflowed
|
||||||
|
|
||||||
|
cmp ___heapend+1
|
||||||
|
bne :+
|
||||||
|
lda newblock
|
||||||
|
cmp ___heapend
|
||||||
|
: bcc :+
|
||||||
|
bne must_malloc_new
|
||||||
|
|
||||||
|
: lda newblock ; There is enough space
|
||||||
|
sta ___heapptr ; Update heapptr
|
||||||
|
lda newblock+1
|
||||||
|
sta ___heapptr+1
|
||||||
|
|
||||||
|
ldy #usedblock::start+1
|
||||||
|
lda ublock+1
|
||||||
|
sta (ublock),y ; Update block start
|
||||||
|
dey
|
||||||
|
lda ublock
|
||||||
|
sta (ublock),y
|
||||||
|
dey
|
||||||
|
|
||||||
|
.assert usedblock::size = usedblock::start-2, error
|
||||||
|
lda size+1
|
||||||
|
sta (ublock),y ; Update block size
|
||||||
|
dey
|
||||||
|
lda size
|
||||||
|
sta (ublock),y
|
||||||
|
|
||||||
|
lda orgblock ; Return original block
|
||||||
|
ldx orgblock+1
|
||||||
|
rts
|
||||||
|
|
||||||
|
must_malloc_new: ; The block is not at heap top, or too big
|
||||||
|
lda size+1
|
||||||
|
pha ; Backup new size (at this point the only ptr
|
||||||
|
tax ; we'll need after malloc). tmp* are safe
|
||||||
|
lda size ; from malloc, memcpy and free.
|
||||||
|
pha
|
||||||
|
jsr _malloc
|
||||||
|
|
||||||
|
cmp #$00 ; Did malloc succeed?
|
||||||
|
bne :+
|
||||||
|
cpx #$00
|
||||||
|
bne :+
|
||||||
|
pla ; Pop size backup and return NULL
|
||||||
|
pla
|
||||||
|
txa ; X already 0
|
||||||
|
rts ; No
|
||||||
|
|
||||||
|
: sta newblock ; Yes, store newblock
|
||||||
|
stx newblock+1
|
||||||
|
jsr pushax ; Push newblock for memcpy
|
||||||
|
|
||||||
|
lda orgblock ; Push orgblock for memcpy
|
||||||
|
ldx orgblock+1
|
||||||
|
jsr pushax
|
||||||
|
|
||||||
|
sec ; Remove admin space from oldsize
|
||||||
|
lda oldsize
|
||||||
|
sbc #<HEAP_ADMIN_SPACE
|
||||||
|
sta oldsize
|
||||||
|
lda oldsize+1
|
||||||
|
sbc #>HEAP_ADMIN_SPACE
|
||||||
|
sta oldsize+1
|
||||||
|
|
||||||
|
pla ; Restore new size to AX
|
||||||
|
tay
|
||||||
|
pla
|
||||||
|
tax
|
||||||
|
tya
|
||||||
|
|
||||||
|
cmp oldsize ; Find the smallest size
|
||||||
|
bcc :+
|
||||||
|
cpx oldsize+1
|
||||||
|
bcc :+
|
||||||
|
|
||||||
|
lda oldsize
|
||||||
|
ldx oldsize+1
|
||||||
|
|
||||||
|
: jsr _memcpy ; And copy data
|
||||||
|
|
||||||
|
lda orgblock ; Free old block
|
||||||
|
ldx orgblock+1
|
||||||
|
jsr _free
|
||||||
|
|
||||||
|
lda newblock ; Return new block
|
||||||
|
ldx newblock+1
|
||||||
|
rts
|
|
@ -62,10 +62,6 @@
|
||||||
; File is not open or the character is invalid
|
; File is not open or the character is invalid
|
||||||
|
|
||||||
error: lda #EINVAL
|
error: lda #EINVAL
|
||||||
jsr ___seterrno
|
jmp ___directerrno
|
||||||
lda #$FF ; Return -1
|
|
||||||
tax
|
|
||||||
rts
|
|
||||||
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
; void BitOtherClip (void *proc1, void* proc2, char skipl, char skipr, int skipy,
|
; void BitOtherClip (void *proc1, void* proc2, char skipl, char skipr, int skipy,
|
||||||
; struct iconpic *myGfx);
|
; struct iconpic *myGfx);
|
||||||
|
|
||||||
; both proc1, proc2 should be: char __fastcall something (void);
|
; both proc1, proc2 should be: char foo (void);
|
||||||
; proc1 is called before reading a byte (.A returns next data)
|
; proc1 is called before reading a byte (.A returns next data)
|
||||||
; proc2 is called before reading each byte which is not pattern (code >219)
|
; proc2 is called before reading each byte which is not pattern (code >219)
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ MikeyInitData: .byte $9e,$18,$68,$1f,$00,$00,$00,$00,$00,$ff,$1a,$1b,$04,$0d,$2
|
||||||
|
|
||||||
; Disable the TX/RX IRQ; set to 8E1.
|
; Disable the TX/RX IRQ; set to 8E1.
|
||||||
|
|
||||||
lda #%00011101
|
lda #PAREN|RESETERR|TXOPEN|PAREVEN ; #%00011101
|
||||||
sta SERCTL
|
sta SERCTL
|
||||||
|
|
||||||
; Clear all pending interrupts.
|
; Clear all pending interrupts.
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
.import ldeaxysp, decsp2, pushax, incsp8
|
.import ldeaxysp, decsp2, pushax, incsp8
|
||||||
.import tosandeax,decax1,tosdiveax,axlong,ldaxysp
|
.import tosandeax,decax1,tosdiveax,axlong,ldaxysp
|
||||||
.import lynxskip0, lynxblock,tosasreax
|
.import lynxskip0, lynxblock,tosasreax
|
||||||
.import __BLOCKSIZE__
|
.import __BANK0BLOCKSIZE__
|
||||||
.importzp _FileCurrBlock
|
.importzp _FileCurrBlock
|
||||||
|
|
||||||
.segment "CODE"
|
.segment "CODE"
|
||||||
|
@ -32,15 +32,15 @@
|
||||||
jsr ldeaxysp
|
jsr ldeaxysp
|
||||||
jsr pusheax
|
jsr pusheax
|
||||||
ldx #$00
|
ldx #$00
|
||||||
lda #<(__BLOCKSIZE__/1024 + 9)
|
lda #<(__BANK0BLOCKSIZE__/1024 + 9)
|
||||||
jsr tosasreax
|
jsr tosasreax
|
||||||
sta _FileCurrBlock
|
sta _FileCurrBlock
|
||||||
jsr lynxblock
|
jsr lynxblock
|
||||||
ldy #$05
|
ldy #$05
|
||||||
jsr ldeaxysp
|
jsr ldeaxysp
|
||||||
jsr pusheax
|
jsr pusheax
|
||||||
lda #<(__BLOCKSIZE__-1)
|
lda #<(__BANK0BLOCKSIZE__-1)
|
||||||
ldx #>(__BLOCKSIZE__-1)
|
ldx #>(__BANK0BLOCKSIZE__-1)
|
||||||
jsr axlong
|
jsr axlong
|
||||||
jsr tosandeax
|
jsr tosandeax
|
||||||
eor #$FF
|
eor #$FF
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
.include "extzp.inc"
|
.include "extzp.inc"
|
||||||
.export lynxskip0, lynxread0
|
.export lynxskip0, lynxread0
|
||||||
.export lynxblock
|
.export lynxblock
|
||||||
.import __BLOCKSIZE__
|
.import __BANK0BLOCKSIZE__
|
||||||
|
|
||||||
.code
|
.code
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ lynxblock:
|
||||||
lda __iodat
|
lda __iodat
|
||||||
sta IODAT
|
sta IODAT
|
||||||
stz _FileBlockByte
|
stz _FileBlockByte
|
||||||
lda #<($100-(>__BLOCKSIZE__))
|
lda #<($100-(>__BANK0BLOCKSIZE__))
|
||||||
sta _FileBlockByte+1
|
sta _FileBlockByte+1
|
||||||
ply
|
ply
|
||||||
plx
|
plx
|
||||||
|
|
|
@ -73,7 +73,12 @@ SER_UNINSTALL:
|
||||||
; Must return an SER_ERR_xx code in a/x.
|
; Must return an SER_ERR_xx code in a/x.
|
||||||
|
|
||||||
SER_CLOSE:
|
SER_CLOSE:
|
||||||
; Disable interrupts
|
; Disable interrupts and stop timer 4 (serial)
|
||||||
|
lda #TXOPEN|RESETERR
|
||||||
|
sta SERCTL
|
||||||
|
stz TIM4CTLA ; Disable count and no reload
|
||||||
|
stz SerialStat ; Reset status
|
||||||
|
|
||||||
; Done, return an error code
|
; Done, return an error code
|
||||||
lda #SER_ERR_OK
|
lda #SER_ERR_OK
|
||||||
.assert SER_ERR_OK = 0, error
|
.assert SER_ERR_OK = 0, error
|
||||||
|
@ -108,17 +113,17 @@ SER_OPEN:
|
||||||
stz TxPtrIn
|
stz TxPtrIn
|
||||||
stz TxPtrOut
|
stz TxPtrOut
|
||||||
|
|
||||||
; clock = 8 * 15625
|
|
||||||
lda #%00011000
|
|
||||||
sta TIM4CTLA
|
|
||||||
ldy #SER_PARAMS::BAUDRATE
|
ldy #SER_PARAMS::BAUDRATE
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
|
|
||||||
|
; Source period is 1 us
|
||||||
|
ldy #%00011000 ; ENABLE_RELOAD|ENABLE_COUNT|AUD_1
|
||||||
|
|
||||||
ldx #1
|
ldx #1
|
||||||
cmp #SER_BAUD_62500
|
cmp #SER_BAUD_62500
|
||||||
beq setbaudrate
|
beq setbaudrate
|
||||||
|
|
||||||
ldx #2
|
ldx #3
|
||||||
cmp #SER_BAUD_31250
|
cmp #SER_BAUD_31250
|
||||||
beq setbaudrate
|
beq setbaudrate
|
||||||
|
|
||||||
|
@ -134,6 +139,10 @@ SER_OPEN:
|
||||||
cmp #SER_BAUD_2400
|
cmp #SER_BAUD_2400
|
||||||
beq setbaudrate
|
beq setbaudrate
|
||||||
|
|
||||||
|
ldx #68
|
||||||
|
cmp #SER_BAUD_1800
|
||||||
|
beq setbaudrate
|
||||||
|
|
||||||
ldx #103
|
ldx #103
|
||||||
cmp #SER_BAUD_1200
|
cmp #SER_BAUD_1200
|
||||||
beq setbaudrate
|
beq setbaudrate
|
||||||
|
@ -142,65 +151,22 @@ SER_OPEN:
|
||||||
cmp #SER_BAUD_600
|
cmp #SER_BAUD_600
|
||||||
beq setbaudrate
|
beq setbaudrate
|
||||||
|
|
||||||
; clock = 6 * 15625
|
; Source period is 8 us
|
||||||
ldx #%00011010
|
ldy #%00011011 ; ENABLE_RELOAD|ENABLE_COUNT|AUD_8
|
||||||
stx TIM4CTLA
|
|
||||||
|
|
||||||
ldx #12
|
ldx #51
|
||||||
cmp #SER_BAUD_7200
|
|
||||||
beq setbaudrate
|
|
||||||
|
|
||||||
ldx #25
|
|
||||||
cmp #SER_BAUD_3600
|
|
||||||
beq setbaudrate
|
|
||||||
|
|
||||||
ldx #207
|
|
||||||
stx TIM4BKUP
|
|
||||||
|
|
||||||
; clock = 4 * 15625
|
|
||||||
ldx #%00011100
|
|
||||||
cmp #SER_BAUD_300
|
cmp #SER_BAUD_300
|
||||||
beq setprescaler
|
|
||||||
|
|
||||||
; clock = 6 * 15625
|
|
||||||
ldx #%00011110
|
|
||||||
cmp #SER_BAUD_150
|
|
||||||
beq setprescaler
|
|
||||||
|
|
||||||
; clock = 1 * 15625
|
|
||||||
ldx #%00011111
|
|
||||||
stx TIM4CTLA
|
|
||||||
cmp #SER_BAUD_75
|
|
||||||
beq baudsuccess
|
|
||||||
|
|
||||||
ldx #141
|
|
||||||
cmp #SER_BAUD_110
|
|
||||||
beq setbaudrate
|
|
||||||
|
|
||||||
; clock = 2 * 15625
|
|
||||||
ldx #%00011010
|
|
||||||
stx TIM4CTLA
|
|
||||||
ldx #68
|
|
||||||
cmp #SER_BAUD_1800
|
|
||||||
beq setbaudrate
|
|
||||||
|
|
||||||
; clock = 6 * 15625
|
|
||||||
ldx #%00011110
|
|
||||||
stx TIM4CTLA
|
|
||||||
ldx #231
|
|
||||||
cmp #SER_BAUD_134_5
|
|
||||||
beq setbaudrate
|
beq setbaudrate
|
||||||
|
|
||||||
lda #SER_ERR_BAUD_UNAVAIL
|
lda #SER_ERR_BAUD_UNAVAIL
|
||||||
ldx #0 ; return value is char
|
ldx #0 ; return value is char
|
||||||
rts
|
rts
|
||||||
setprescaler:
|
|
||||||
stx TIM4CTLA
|
|
||||||
bra baudsuccess
|
|
||||||
setbaudrate:
|
setbaudrate:
|
||||||
|
sty TIM4CTLA
|
||||||
stx TIM4BKUP
|
stx TIM4BKUP
|
||||||
baudsuccess:
|
|
||||||
ldx #TxOpenColl|ParEven
|
ldx #TXOPEN|PAREVEN
|
||||||
stx contrl
|
stx contrl
|
||||||
ldy #SER_PARAMS::DATABITS ; Databits
|
ldy #SER_PARAMS::DATABITS ; Databits
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
|
@ -218,15 +184,15 @@ baudsuccess:
|
||||||
beq checkhs
|
beq checkhs
|
||||||
cmp #SER_PAR_SPACE
|
cmp #SER_PAR_SPACE
|
||||||
bne @L0
|
bne @L0
|
||||||
ldx #TxOpenColl
|
ldx #TXOPEN
|
||||||
stx contrl
|
stx contrl
|
||||||
bra checkhs
|
bra checkhs
|
||||||
@L0:
|
@L0:
|
||||||
ldx #TxParEnable|TxOpenColl|ParEven
|
ldx #PAREN|TXOPEN|PAREVEN
|
||||||
stx contrl
|
stx contrl
|
||||||
cmp #SER_PAR_EVEN
|
cmp #SER_PAR_EVEN
|
||||||
beq checkhs
|
beq checkhs
|
||||||
ldx #TxParEnable|TxOpenColl
|
ldx #PAREN|TXOPEN
|
||||||
stx contrl
|
stx contrl
|
||||||
checkhs:
|
checkhs:
|
||||||
ldx contrl
|
ldx contrl
|
||||||
|
@ -234,15 +200,27 @@ checkhs:
|
||||||
ldy #SER_PARAMS::HANDSHAKE ; Handshake
|
ldy #SER_PARAMS::HANDSHAKE ; Handshake
|
||||||
lda (ptr1),y
|
lda (ptr1),y
|
||||||
cmp #SER_HS_NONE
|
cmp #SER_HS_NONE
|
||||||
|
beq redeye_ok
|
||||||
|
cmp #SER_HS_SW ; Software handshake will check for connected redeye
|
||||||
bne invparameter
|
bne invparameter
|
||||||
|
|
||||||
|
lda IODAT
|
||||||
|
and #NOEXP ; Check if redeye bit flag is unset
|
||||||
|
beq redeye_ok
|
||||||
|
lda #SER_ERR_NO_DEVICE ; ComLynx cable is not inserted
|
||||||
|
ldx #0
|
||||||
|
rts
|
||||||
|
|
||||||
|
redeye_ok:
|
||||||
lda SERDAT
|
lda SERDAT
|
||||||
lda contrl
|
lda contrl
|
||||||
ora #RxIntEnable|ResetErr
|
ora #RXINTEN|RESETERR ; Turn on interrupts for receive
|
||||||
sta SERCTL
|
sta SERCTL
|
||||||
lda #SER_ERR_OK
|
lda #SER_ERR_OK
|
||||||
.assert SER_ERR_OK = 0, error
|
.assert SER_ERR_OK = 0, error
|
||||||
tax
|
tax
|
||||||
rts
|
rts
|
||||||
|
|
||||||
invparameter:
|
invparameter:
|
||||||
lda #SER_ERR_INIT_FAILED
|
lda #SER_ERR_INIT_FAILED
|
||||||
ldx #0 ; return value is char
|
ldx #0 ; return value is char
|
||||||
|
@ -264,8 +242,8 @@ GetByte:
|
||||||
ldy RxPtrOut
|
ldy RxPtrOut
|
||||||
lda RxBuffer,y
|
lda RxBuffer,y
|
||||||
inc RxPtrOut
|
inc RxPtrOut
|
||||||
|
sta (ptr1)
|
||||||
ldx #$00
|
ldx #$00
|
||||||
sta (ptr1,x)
|
|
||||||
txa ; Return code = 0
|
txa ; Return code = 0
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
@ -279,24 +257,26 @@ SER_PUT:
|
||||||
ina
|
ina
|
||||||
cmp TxPtrOut
|
cmp TxPtrOut
|
||||||
bne PutByte
|
bne PutByte
|
||||||
|
|
||||||
lda #SER_ERR_OVERFLOW
|
lda #SER_ERR_OVERFLOW
|
||||||
ldx #0 ; return value is char
|
ldx #0 ; return value is char
|
||||||
rts
|
rts
|
||||||
|
|
||||||
PutByte:
|
PutByte:
|
||||||
ldy TxPtrIn
|
ldy TxPtrIn
|
||||||
txa
|
txa
|
||||||
sta TxBuffer,y
|
sta TxBuffer,y
|
||||||
inc TxPtrIn
|
inc TxPtrIn
|
||||||
|
|
||||||
bit TxDone
|
bit TxDone ; Check bit 7 of TxDone (TXINTEN)
|
||||||
bmi @L1
|
bmi @L1 ; Was TXINTEN already set?
|
||||||
php
|
php
|
||||||
sei
|
sei
|
||||||
lda contrl
|
lda contrl ; contrl does not include RXINTEN setting
|
||||||
ora #TxIntEnable|ResetErr
|
ora #TXINTEN|RESETERR
|
||||||
sta SERCTL ; Allow TX-IRQ to hang RX-IRQ
|
sta SERCTL ; Allow TX-IRQ to hang RX-IRQ (no receive while transmitting)
|
||||||
sta TxDone
|
sta TxDone
|
||||||
plp
|
plp ; Restore processor and interrupt enable
|
||||||
@L1:
|
@L1:
|
||||||
lda #SER_ERR_OK
|
lda #SER_ERR_OK
|
||||||
.assert SER_ERR_OK = 0, error
|
.assert SER_ERR_OK = 0, error
|
||||||
|
@ -308,9 +288,9 @@ PutByte:
|
||||||
; Must return an SER_ERR_xx code in a/x.
|
; Must return an SER_ERR_xx code in a/x.
|
||||||
|
|
||||||
SER_STATUS:
|
SER_STATUS:
|
||||||
ldy SerialStat
|
lda SerialStat
|
||||||
|
sta (ptr1)
|
||||||
ldx #$00
|
ldx #$00
|
||||||
sta (ptr1,x)
|
|
||||||
txa ; Return code = 0
|
txa ; Return code = 0
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
@ -342,48 +322,56 @@ SER_IRQ:
|
||||||
@L0:
|
@L0:
|
||||||
bit TxDone
|
bit TxDone
|
||||||
bmi @tx_irq ; Transmit in progress
|
bmi @tx_irq ; Transmit in progress
|
||||||
ldx SERDAT
|
|
||||||
lda SERCTL
|
ldx SERDAT ; Read received data
|
||||||
and #RxParityErr|RxOverrun|RxFrameErr|RxBreak
|
lda contrl
|
||||||
beq @rx_irq
|
and #PAREN ; Parity enabled implies SER_PAR_EVEN or SER_PAR_ODD
|
||||||
|
tay
|
||||||
|
ora #OVERRUN|FRAMERR|RXBRK
|
||||||
|
and SERCTL ; Check presence of relevant error flags in SERCTL
|
||||||
|
|
||||||
|
beq @rx_irq ; No errors so far
|
||||||
|
|
||||||
tsb SerialStat ; Save error condition
|
tsb SerialStat ; Save error condition
|
||||||
bit #RxBreak
|
bit #RXBRK ; Check for break signal
|
||||||
beq @noBreak
|
beq @noBreak
|
||||||
|
|
||||||
stz TxPtrIn ; Break received - drop buffers
|
stz TxPtrIn ; Break received - drop buffers
|
||||||
stz TxPtrOut
|
stz TxPtrOut
|
||||||
stz RxPtrIn
|
stz RxPtrIn
|
||||||
stz RxPtrOut
|
stz RxPtrOut
|
||||||
@noBreak:
|
@noBreak:
|
||||||
lda contrl
|
bra @exit0
|
||||||
ora #RxIntEnable|ResetErr
|
|
||||||
sta SERCTL
|
|
||||||
lda #$10
|
|
||||||
sta INTRST
|
|
||||||
bra @IRQexit
|
|
||||||
@rx_irq:
|
@rx_irq:
|
||||||
|
tya
|
||||||
|
bne @2 ; Parity was enabled so no marker bit check needed
|
||||||
|
|
||||||
lda contrl
|
lda contrl
|
||||||
ora #RxIntEnable|ResetErr
|
eor SERCTL ; Should match current parity bit
|
||||||
sta SERCTL
|
and #PARBIT ; Check for mark or space value
|
||||||
|
bne @exit0
|
||||||
|
|
||||||
|
@2:
|
||||||
txa
|
txa
|
||||||
ldx RxPtrIn
|
ldx RxPtrIn
|
||||||
sta RxBuffer,x
|
sta RxBuffer,x
|
||||||
txa
|
txa
|
||||||
inx
|
inx
|
||||||
|
|
||||||
@cont0:
|
|
||||||
cpx RxPtrOut
|
cpx RxPtrOut
|
||||||
beq @1
|
beq @1
|
||||||
stx RxPtrIn
|
stx RxPtrIn
|
||||||
lda #SERIAL_INTERRUPT
|
|
||||||
sta INTRST
|
|
||||||
bra @IRQexit
|
bra @IRQexit
|
||||||
|
|
||||||
@1:
|
@1:
|
||||||
sta RxPtrIn
|
sta RxPtrIn
|
||||||
lda #$80
|
lda #$80
|
||||||
tsb SerialStat
|
tsb SerialStat
|
||||||
|
bra @exit0
|
||||||
|
|
||||||
@tx_irq:
|
@tx_irq:
|
||||||
ldx TxPtrOut ; Has all bytes been sent?
|
ldx TxPtrOut ; Have all bytes been sent?
|
||||||
cpx TxPtrIn
|
cpx TxPtrIn
|
||||||
beq @allSent
|
beq @allSent
|
||||||
|
|
||||||
|
@ -393,24 +381,24 @@ SER_IRQ:
|
||||||
|
|
||||||
@exit1:
|
@exit1:
|
||||||
lda contrl
|
lda contrl
|
||||||
ora #TxIntEnable|ResetErr
|
ora #TXINTEN|RESETERR
|
||||||
sta SERCTL
|
sta SERCTL
|
||||||
lda #SERIAL_INTERRUPT
|
|
||||||
sta INTRST
|
|
||||||
bra @IRQexit
|
bra @IRQexit
|
||||||
|
|
||||||
@allSent:
|
@allSent:
|
||||||
lda SERCTL ; All bytes sent
|
lda SERCTL ; All bytes sent
|
||||||
bit #TxEmpty
|
bit #TXEMPTY
|
||||||
beq @exit1
|
beq @exit1
|
||||||
bvs @exit1
|
bvs @exit1
|
||||||
stz TxDone
|
stz TxDone
|
||||||
|
|
||||||
|
@exit0:
|
||||||
lda contrl
|
lda contrl
|
||||||
ora #RxIntEnable|ResetErr
|
ora #RXINTEN|RESETERR ; Re-enable receive interrupt
|
||||||
sta SERCTL
|
sta SERCTL
|
||||||
|
|
||||||
|
@IRQexit:
|
||||||
lda #SERIAL_INTERRUPT
|
lda #SERIAL_INTERRUPT
|
||||||
sta INTRST
|
sta INTRST
|
||||||
@IRQexit:
|
|
||||||
clc
|
clc
|
||||||
rts
|
rts
|
||||||
|
|
|
@ -33,21 +33,21 @@ loop1:
|
||||||
cont1:
|
cont1:
|
||||||
jsr read_byte
|
jsr read_byte
|
||||||
sta (load_ptr2),y
|
sta (load_ptr2),y
|
||||||
sta PALETTE ; feedback ;-)
|
sta PALETTE + 1 ; feedback ;-)
|
||||||
iny
|
iny
|
||||||
bne loop1
|
bne loop1
|
||||||
inc load_ptr2+1
|
inc load_ptr2+1
|
||||||
bra loop1
|
bra loop1
|
||||||
|
|
||||||
read_byte:
|
read_byte:
|
||||||
bit SERCTL
|
bit SERCTL ; Check for RXRDY ($40)
|
||||||
bvc read_byte
|
bvc read_byte
|
||||||
lda SERDAT
|
lda SERDAT
|
||||||
rts
|
rts
|
||||||
|
|
||||||
_UpLoaderIRQ:
|
_UpLoaderIRQ:
|
||||||
lda INTSET
|
lda INTSET
|
||||||
and #$10
|
and #SERIAL_INTERRUPT
|
||||||
bne @L0
|
bne @L0
|
||||||
clc
|
clc
|
||||||
rts
|
rts
|
||||||
|
@ -69,6 +69,8 @@ again:
|
||||||
; last action : clear interrupt
|
; last action : clear interrupt
|
||||||
;
|
;
|
||||||
exit:
|
exit:
|
||||||
|
lda #SERIAL_INTERRUPT
|
||||||
|
sta INTRST
|
||||||
clc
|
clc
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|
21
libsrc/runtime/aslax7.s
Normal file
21
libsrc/runtime/aslax7.s
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
;
|
||||||
|
; Miloslaw Smyk, 2024
|
||||||
|
;
|
||||||
|
; CC65 runtime: Scale the primary register by 128, unsigned
|
||||||
|
;
|
||||||
|
|
||||||
|
.export shlax7, aslax7
|
||||||
|
|
||||||
|
aslax7:
|
||||||
|
shlax7: ; XXXXXXXL AAAAAAAl
|
||||||
|
tay
|
||||||
|
txa
|
||||||
|
lsr ; XXXXXXXL -> 0XXXXXXX, L->C
|
||||||
|
tya
|
||||||
|
ror ; AAAAAAAl -> LAAAAAAA, l->C
|
||||||
|
tax
|
||||||
|
lda #$00 ; LAAAAAAA 00000000
|
||||||
|
ror ; LAAAAAAA l0000000
|
||||||
|
rts
|
||||||
|
|
||||||
|
; 10 bytes, 16 cycles + rts
|
18
libsrc/runtime/asrax7.s
Normal file
18
libsrc/runtime/asrax7.s
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
;
|
||||||
|
; Miloslaw Smyk, 2024
|
||||||
|
;
|
||||||
|
; CC65 runtime: Scale the primary register by 128, signed
|
||||||
|
;
|
||||||
|
|
||||||
|
.export asrax7
|
||||||
|
|
||||||
|
asrax7: ; HXXXXXXL hAAAAAAl
|
||||||
|
asl ; AAAAAAA0, h->C
|
||||||
|
txa
|
||||||
|
rol ; XXXXXXLh, H->C
|
||||||
|
ldx #$00 ; 00000000 XXXXXXLh
|
||||||
|
bcc :+
|
||||||
|
dex ; 11111111 XXXXXXLh if C
|
||||||
|
: rts
|
||||||
|
|
||||||
|
; 12 cycles max, 9 bytes
|
|
@ -8,12 +8,18 @@
|
||||||
.import incsp2
|
.import incsp2
|
||||||
.importzp sp, ptr1
|
.importzp sp, ptr1
|
||||||
|
|
||||||
|
.macpack cpu
|
||||||
|
|
||||||
.proc popptr1 ; 14 bytes (four usages = at least 2 bytes saved)
|
.proc popptr1 ; 14 bytes (four usages = at least 2 bytes saved)
|
||||||
ldy #1
|
ldy #1
|
||||||
lda (sp),y ; get hi byte
|
lda (sp),y ; get hi byte
|
||||||
sta ptr1+1 ; into ptr hi
|
sta ptr1+1 ; into ptr hi
|
||||||
dey ; no optimization for 65C02 here to have Y=0 at exit!
|
dey ; dey even for for 65C02 here to have Y=0 at exit!
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
lda (sp) ; get lo byte
|
||||||
|
.else
|
||||||
lda (sp),y ; get lo byte
|
lda (sp),y ; get lo byte
|
||||||
|
.endif
|
||||||
sta ptr1 ; to ptr lo
|
sta ptr1 ; to ptr lo
|
||||||
jmp incsp2
|
jmp incsp2
|
||||||
.endproc
|
.endproc
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
.export push0, pusha0, pushax
|
.export push0, pusha0, pushax
|
||||||
.importzp sp
|
.importzp sp
|
||||||
|
|
||||||
|
.macpack cpu
|
||||||
|
|
||||||
push0: lda #0
|
push0: lda #0
|
||||||
pusha0: ldx #0
|
pusha0: ldx #0
|
||||||
|
|
||||||
|
@ -29,7 +31,11 @@ pusha0: ldx #0
|
||||||
sta (sp),y ; (27)
|
sta (sp),y ; (27)
|
||||||
pla ; (31)
|
pla ; (31)
|
||||||
dey ; (33)
|
dey ; (33)
|
||||||
|
.if (.cpu .bitand ::CPU_ISET_65SC02)
|
||||||
|
sta (sp) ; (37)
|
||||||
|
.else
|
||||||
sta (sp),y ; (38)
|
sta (sp),y ; (38)
|
||||||
rts ; (44)
|
.endif
|
||||||
|
rts ; (44/43)
|
||||||
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
14
libsrc/runtime/pushptr1.s
Normal file
14
libsrc/runtime/pushptr1.s
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
;
|
||||||
|
; Colin Leroy-Mira, 2024
|
||||||
|
;
|
||||||
|
; CC65 runtime: Push ptr1 to stack.
|
||||||
|
; A/X destroyed (set to ptr1)
|
||||||
|
|
||||||
|
.export pushptr1
|
||||||
|
.import pushax
|
||||||
|
.importzp ptr1
|
||||||
|
|
||||||
|
pushptr1:
|
||||||
|
lda ptr1
|
||||||
|
ldx ptr1+1
|
||||||
|
jmp pushax
|
15
libsrc/runtime/returnFFFF.s
Normal file
15
libsrc/runtime/returnFFFF.s
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
;
|
||||||
|
; Ullrich von Bassewitz, 25.10.2000
|
||||||
|
;
|
||||||
|
; CC65 runtime: Return -1 in a/x
|
||||||
|
;
|
||||||
|
|
||||||
|
.export returnFFFF
|
||||||
|
|
||||||
|
.proc returnFFFF
|
||||||
|
|
||||||
|
lda #$FF
|
||||||
|
tax
|
||||||
|
rts
|
||||||
|
|
||||||
|
.endproc
|
18
libsrc/runtime/shrax7.s
Normal file
18
libsrc/runtime/shrax7.s
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
;
|
||||||
|
; Miloslaw Smyk, 2024
|
||||||
|
;
|
||||||
|
; CC65 runtime: Scale the primary register by 128, unsigned
|
||||||
|
;
|
||||||
|
|
||||||
|
.export shrax7
|
||||||
|
|
||||||
|
shrax7: ; HXXXXXXL hAAAAAAl
|
||||||
|
asl ; AAAAAAA0, h->C
|
||||||
|
txa
|
||||||
|
rol ; XXXXXXLh, H->C
|
||||||
|
ldx #$00 ; 00000000 XXXXXXLh
|
||||||
|
bcc :+
|
||||||
|
inx ; 0000000H XXXXXXLh if C
|
||||||
|
: rts
|
||||||
|
|
||||||
|
; 12 cycles max, 9 bytes
|
|
@ -9,11 +9,21 @@
|
||||||
.import __MAIN_START__
|
.import __MAIN_START__
|
||||||
.import startup
|
.import startup
|
||||||
|
|
||||||
|
.macpack cpu
|
||||||
|
|
||||||
.segment "EXEHDR"
|
.segment "EXEHDR"
|
||||||
|
|
||||||
.byte $73, $69, $6D, $36, $35 ; 'sim65'
|
.byte $73, $69, $6D, $36, $35 ; 'sim65'
|
||||||
.byte 2 ; header version
|
.byte 2 ; header version
|
||||||
.byte .defined(__SIM65C02__) ; CPU type
|
.if (.cpu .bitand ::CPU_ISET_6502X)
|
||||||
|
.byte 2
|
||||||
|
.elseif (.cpu .bitand ::CPU_ISET_65C02)
|
||||||
|
.byte 1
|
||||||
|
.elseif (.cpu .bitand ::CPU_ISET_6502)
|
||||||
|
.byte 0
|
||||||
|
.else
|
||||||
|
.error Unknow CPU type.
|
||||||
|
.endif
|
||||||
.byte sp ; sp address
|
.byte sp ; sp address
|
||||||
.addr __MAIN_START__ ; load address
|
.addr __MAIN_START__ ; load address
|
||||||
.addr startup ; reset address
|
.addr startup ; reset address
|
||||||
|
|
|
@ -8,10 +8,15 @@
|
||||||
;
|
;
|
||||||
|
|
||||||
.export exit, args, _open, _close, _read, _write
|
.export exit, args, _open, _close, _read, _write
|
||||||
|
.export __sysremove, ___osmaperrno
|
||||||
|
|
||||||
|
__sysremove := $FFF2
|
||||||
|
___osmaperrno := $FFF3
|
||||||
_open := $FFF4
|
_open := $FFF4
|
||||||
_close := $FFF5
|
_close := $FFF5
|
||||||
_read := $FFF6
|
_read := $FFF6
|
||||||
_write := $FFF7
|
_write := $FFF7
|
||||||
args := $FFF8
|
args := $FFF8
|
||||||
exit := $FFF9
|
exit := $FFF9
|
||||||
|
|
||||||
|
; $FFFA-FFFF are hardware vectors, extend before not after!
|
||||||
|
|
|
@ -33,7 +33,10 @@ endif
|
||||||
|
|
||||||
EXELIST_kim1 = \
|
EXELIST_kim1 = \
|
||||||
kimHello.bin \
|
kimHello.bin \
|
||||||
kimSieve.bin
|
kimSieve.bin \
|
||||||
|
kimLife.bin \
|
||||||
|
kimTest.bin \
|
||||||
|
kimGFX.bin
|
||||||
|
|
||||||
ifneq ($(EXELIST_$(SYS)),)
|
ifneq ($(EXELIST_$(SYS)),)
|
||||||
samples: $(EXELIST_$(SYS))
|
samples: $(EXELIST_$(SYS))
|
||||||
|
@ -50,13 +53,65 @@ else
|
||||||
@echo > $(NULLDEV)
|
@echo > $(NULLDEV)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
subs.o: subs.asm
|
||||||
|
$(AS) subs.asm -o subs.o
|
||||||
|
|
||||||
|
ramfont.o: ramfont.asm
|
||||||
|
$(AS) ramfont.asm -o ramfont.o
|
||||||
|
|
||||||
|
kimLife.bin: kimLife.c
|
||||||
|
$(CL) -t kim1 -C kim1-60k.cfg -Oi -o kimLife.bin kimLife.c
|
||||||
|
|
||||||
|
kimTest.bin: kimTest.c
|
||||||
|
$(CL) -t kim1 -C kim1-60k.cfg -Oi -o kimTest.bin kimTest.c
|
||||||
|
|
||||||
|
kimGFX.bin: kimGFX.c subs.o ramfont.o
|
||||||
|
$(CL) -t kim1 --listing kimGFX.lst -C kim1-mtuE000.cfg -o kimGFX.bin kimGFX.c subs.o ramfont.o -Ln kimgfx.lbl
|
||||||
|
|
||||||
kimSieve.bin: kimSieve.c
|
kimSieve.bin: kimSieve.c
|
||||||
$(CL) -t kim1 -C kim1-60k.cfg -O -o kimSieve.bin kimSieve.c
|
$(CL) -t kim1 -C kim1-60k.cfg -O -o kimSieve.bin kimSieve.c
|
||||||
|
|
||||||
kimHello.bin: kimHello.c
|
kimHello.bin: kimHello.c
|
||||||
$(CL) -t kim1 -O -o kimHello.bin kimHello.c
|
$(CL) -t kim1 -O -o kimHello.bin kimHello.c
|
||||||
|
|
||||||
|
# To build an intel-format file for the CORSHAM SD card reader
|
||||||
|
|
||||||
|
kimLife.hex: kimLife.bin
|
||||||
|
srec_cat kimLife.bin -binary -offset 0x2000 -o kimLife.hex -Intel -address-length=2
|
||||||
|
|
||||||
|
kimTest.hex: kimTest.bin
|
||||||
|
srec_cat kimTest.bin -binary -offset 0x2000 -o kimTest.hex -Intel -address-length=2
|
||||||
|
|
||||||
|
kimGFX.hex: kimGFX.bin ramfont.o
|
||||||
|
srec_cat kimGFX.bin -binary -offset 0x2000 -o kimGFX.hex -Intel -address-length=2
|
||||||
|
|
||||||
|
# To build a paper tape file for uploading to the KIM-1 via terminal
|
||||||
|
|
||||||
|
kimLife.ptp: kimLife.bin
|
||||||
|
srec_cat kimLife.bin -binary -offset 0x2000 -o kimLife.ptp -MOS_Technologies
|
||||||
|
|
||||||
|
kimGFX.ptp: kimGFX.bin
|
||||||
|
srec_cat kimGFX.bin -binary -offset 0x2000 -o kimGFX.ptp -MOS_Technologies
|
||||||
|
|
||||||
|
kimTest.ptp: kimTest.bin
|
||||||
|
srec_cat kimTest.bin -binary -offset 0x2000 -o kimTest.ptp -MOS_Technologies
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(DEL) kimSieve.bin 2>$(NULLDEV)
|
@$(DEL) kimSieve.bin 2>$(NULLDEV)
|
||||||
@$(DEL) kimHello.bin 2>$(NULLDEV)
|
@$(DEL) kimHello.bin 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimLife.bin 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimLife.ptp 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimLife.hex 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimTest.bin 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimTest.ptp 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimTest.hex 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimGFX.bin 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimGFX.ptp 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimGFX.hex 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimgfx.lbl 2>$(NULLDEV)
|
||||||
|
@$(DEL) kimGFX.lst 2>$(NULLDEV)
|
||||||
|
@$(DEL) subs.o 2>$(NULLDEV)
|
||||||
|
@$(DEL) ramfont.o 2>$(NULLDEV)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
0
samples/kim1/font.rom
Normal file
0
samples/kim1/font.rom
Normal file
290
samples/kim1/kimGFX.c
Normal file
290
samples/kim1/kimGFX.c
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Simple Graphics Test for KIM-1 with MTU Visible Memory Board
|
||||||
|
//
|
||||||
|
// Assumes the MTU Visible Memory Board mapped at 0xA000 for 8K of video RAM
|
||||||
|
//
|
||||||
|
// davepl@davepl.com
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdio.h> // For printf
|
||||||
|
#include <stdlib.h> // For rand, srand
|
||||||
|
#include <string.h> // For memcpy
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
extern void ClearScreen(void); // In subs.asm
|
||||||
|
extern void ScrollScreen(void);
|
||||||
|
extern void DrawCircle(void);
|
||||||
|
extern void SetPixel(void);
|
||||||
|
extern void ClearPixel(void);
|
||||||
|
extern void DrawChar(void);
|
||||||
|
extern void Demo(void);
|
||||||
|
extern void __fastcall__ Delay(byte loops);
|
||||||
|
extern void __fastcall__ DrawLine(byte bSet);
|
||||||
|
extern byte __fastcall__ AscToPet(byte in);
|
||||||
|
extern byte __fastcall__ PetToAsc(byte in);
|
||||||
|
extern byte __fastcall__ ReverseBits(byte in);
|
||||||
|
extern void __fastcall__ CharOut(byte asci_char);
|
||||||
|
extern byte __fastcall__ getch();
|
||||||
|
extern unsigned char font8x8_basic[256][8];
|
||||||
|
|
||||||
|
extern int x1cord;
|
||||||
|
extern int y1cord;
|
||||||
|
extern int x2cord;
|
||||||
|
extern int y2cord;
|
||||||
|
extern int cursorX;
|
||||||
|
extern int cursorY;
|
||||||
|
|
||||||
|
// If in zeropage:
|
||||||
|
//
|
||||||
|
// #pragma zpsym("x1cord")
|
||||||
|
// #pragma zpsym("x2cord")
|
||||||
|
// #pragma zpsym("y1cord")
|
||||||
|
// #pragma zpsym("y2cord")
|
||||||
|
|
||||||
|
// Screen memory is placed at A000-BFFF, 320x200 pixels, mapped right to left within each horizontal byte
|
||||||
|
|
||||||
|
byte * screen = (byte *) 0xA000;
|
||||||
|
|
||||||
|
// Cursor position
|
||||||
|
|
||||||
|
#define SCREEN_WIDTH 320
|
||||||
|
#define SCREEN_HEIGHT 200
|
||||||
|
#define CHARWIDTH 8
|
||||||
|
#define CHARHEIGHT 8
|
||||||
|
#define BYTESPERROW (SCREEN_WIDTH / 8)
|
||||||
|
#define BYTESPERCHARROW (BYTESPERROW * 8)
|
||||||
|
#define CHARSPERROW (SCREEN_WIDTH / CHARWIDTH)
|
||||||
|
#define ROWSPERCOLUMN (SCREEN_HEIGHT / CHARHEIGHT)
|
||||||
|
|
||||||
|
// SETPIXEL
|
||||||
|
//
|
||||||
|
// 0 <= x < 320
|
||||||
|
// 0 <= y < 200
|
||||||
|
//
|
||||||
|
// Draws a pixel on the screen in white or black at pixel pos x, y
|
||||||
|
|
||||||
|
void SETPIXEL(int x, int y, byte b)
|
||||||
|
{
|
||||||
|
x1cord = x;
|
||||||
|
y1cord = y;
|
||||||
|
|
||||||
|
if (b)
|
||||||
|
SetPixel();
|
||||||
|
else
|
||||||
|
ClearPixel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// DRAWPIXEL
|
||||||
|
//
|
||||||
|
// 0 <= x < 320
|
||||||
|
// 0 <= y < 200
|
||||||
|
//
|
||||||
|
// Turns on a screen pixel at pixel pos x,y
|
||||||
|
|
||||||
|
void DRAWPIXEL(int x, int y)
|
||||||
|
{
|
||||||
|
x1cord = x;
|
||||||
|
y1cord = y;
|
||||||
|
SetPixel();
|
||||||
|
}
|
||||||
|
|
||||||
|
int c;
|
||||||
|
|
||||||
|
void DrawText(char * psz)
|
||||||
|
{
|
||||||
|
while (*psz)
|
||||||
|
{
|
||||||
|
while (cursorX >= CHARSPERROW)
|
||||||
|
{
|
||||||
|
cursorX -= CHARSPERROW;
|
||||||
|
cursorY += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've gone off the bottom of the screen, we scroll the screen and back up to the last line again
|
||||||
|
|
||||||
|
if (cursorY >= ROWSPERCOLUMN)
|
||||||
|
{
|
||||||
|
cursorY = ROWSPERCOLUMN - 1;
|
||||||
|
ScrollScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we output a newline we advanced the cursor down one line and reset it to the left
|
||||||
|
|
||||||
|
if (*psz == 0x0A)
|
||||||
|
{
|
||||||
|
cursorX = 0;
|
||||||
|
cursorY++;
|
||||||
|
psz++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = *psz;
|
||||||
|
|
||||||
|
__asm__ ("ldx %v", cursorX);
|
||||||
|
__asm__ ("ldy %v", cursorY);
|
||||||
|
__asm__ ("lda %v", c);
|
||||||
|
DrawChar();
|
||||||
|
cursorX++;
|
||||||
|
psz++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTextAt(int x, int y, char * psz)
|
||||||
|
{
|
||||||
|
cursorX = x;
|
||||||
|
cursorY = y;
|
||||||
|
DrawText(psz);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something like Bresenham's algorithm for drawing a line
|
||||||
|
/*
|
||||||
|
void DrawLine(int x0, int y0, int x1, int y1, byte val)
|
||||||
|
{
|
||||||
|
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
|
||||||
|
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
|
||||||
|
int err = (dx > dy ? dx : -dy) / 2, e2;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
SETPIXEL(x0, y0, val);
|
||||||
|
|
||||||
|
if (x0 == x1 && y0 == y1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
e2 = err;
|
||||||
|
|
||||||
|
if (e2 > -dx)
|
||||||
|
{
|
||||||
|
err -= dy;
|
||||||
|
x0 += sx;
|
||||||
|
}
|
||||||
|
if (e2 < dy)
|
||||||
|
{
|
||||||
|
err += dx;
|
||||||
|
y0 += sy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// DrawCircle
|
||||||
|
//
|
||||||
|
// Draw a circle without sin, cos, or floating point!
|
||||||
|
|
||||||
|
void DrawCircleC(int x0, int y0, int radius, byte)
|
||||||
|
{
|
||||||
|
x1cord = x0;
|
||||||
|
y1cord = y0;
|
||||||
|
y2cord = radius;
|
||||||
|
DrawCircle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawLineC(int x1, int y1, int x2, int y2, byte bSet)
|
||||||
|
{
|
||||||
|
x1cord = x1;
|
||||||
|
y1cord = y1;
|
||||||
|
x2cord = x2;
|
||||||
|
y2cord = y2;
|
||||||
|
DrawLine(bSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MirrorFont
|
||||||
|
//
|
||||||
|
// RAM font is backwards left-right relative to the way memory is laid out on the KIM-1, so we swap all the
|
||||||
|
// bytes in place by reversing the order of the bits in every byte
|
||||||
|
|
||||||
|
void MirrorFont()
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
byte * pb = (byte *) font8x8_basic;
|
||||||
|
|
||||||
|
for (c = 0; c < 128 * 8; c++)
|
||||||
|
pb[c] = ReverseBits(pb[c]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DrawScreenMoire
|
||||||
|
//
|
||||||
|
// Draws a moire pattern on the screen without clearing it first
|
||||||
|
|
||||||
|
void DrawMoire(int left, int top, int right, int bottom, byte pixel)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
for (x = left; x < right; x += 6)
|
||||||
|
DrawLineC(x, top, right - x + left, bottom, pixel);
|
||||||
|
|
||||||
|
for (y = top; y < bottom; y += 6)
|
||||||
|
DrawLineC(left, y, right, bottom - y + top, pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawScreenMoire(int left, int top, int right, int bottom)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
DrawLineC(left, top, right, top, 1);
|
||||||
|
DrawLineC(left, bottom, right, bottom, 1);
|
||||||
|
DrawLineC(left, top, left, bottom, 1);
|
||||||
|
DrawLineC(right, top, right, bottom, 1);
|
||||||
|
|
||||||
|
left++; top++; right--; bottom--;
|
||||||
|
|
||||||
|
for (x = left; x < right; x += 6)
|
||||||
|
DrawLineC(x, top, right - x + left, bottom, 1);
|
||||||
|
for (y = top; y < bottom; y += 6)
|
||||||
|
DrawLineC(left, y, right, bottom - y + top, 1);
|
||||||
|
for (x = left; x < right; x += 6)
|
||||||
|
DrawLineC(x, top, right - x + left, bottom, 0);
|
||||||
|
for (y = top; y < bottom; y += 6)
|
||||||
|
DrawLineC(left, y, right, bottom - y + top, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
|
Demo();
|
||||||
|
|
||||||
|
CharOut('R');
|
||||||
|
CharOut('E');
|
||||||
|
CharOut('A');
|
||||||
|
CharOut('D');
|
||||||
|
CharOut('Y');
|
||||||
|
CharOut('.');
|
||||||
|
CharOut('\n');
|
||||||
|
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
c = toupper(getch());
|
||||||
|
if (c != EOF)
|
||||||
|
CharOut(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the screen memory
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
Demo();
|
||||||
|
DrawScreenMoire(0,30, 319, 199);
|
||||||
|
Delay(10);
|
||||||
|
|
||||||
|
Demo();
|
||||||
|
for (i = 5; i < 80; i+=5)
|
||||||
|
{
|
||||||
|
DrawCircleC(SCREEN_WIDTH/2, SCREEN_HEIGHT/2 + 20, i, 1);
|
||||||
|
DrawCircleC(SCREEN_WIDTH/4, SCREEN_HEIGHT/2 + 20, i, 1);
|
||||||
|
DrawCircleC(SCREEN_WIDTH*3/4, SCREEN_HEIGHT/2 + 20, i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Delay(10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Done, exiting...\r\n");
|
||||||
|
return 0;
|
||||||
|
}
|
144
samples/kim1/kimLife.c
Normal file
144
samples/kim1/kimLife.c
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Conway's Game of Life for KIM-1
|
||||||
|
//
|
||||||
|
// Assumes the MTU Visible Memory Board mapped at 0x8000 for 8K of video RAM
|
||||||
|
//
|
||||||
|
// Dave Plummer on a rainy Thursday
|
||||||
|
//
|
||||||
|
// davepl@davepl.com
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdio.h> // For printf
|
||||||
|
#include <stdlib.h> // For rand, srand
|
||||||
|
#include <string.h> // For memcpy
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
// World size
|
||||||
|
|
||||||
|
#define WIDTH 320
|
||||||
|
#define HEIGHT 200
|
||||||
|
#define NUMBITS 64000
|
||||||
|
#define NUMBYTES 8000
|
||||||
|
#define DENSITY 50
|
||||||
|
|
||||||
|
// Screen memory is placed at 8000, our world copy at A000, and they use the same layout so
|
||||||
|
// that we can memcpy from one to the other without translating
|
||||||
|
|
||||||
|
byte * world = (byte *) 0x8000;
|
||||||
|
byte * new_world = (byte *) 0xA000;
|
||||||
|
|
||||||
|
// BITARRAY
|
||||||
|
//
|
||||||
|
// Access individual bits in a block of memory
|
||||||
|
|
||||||
|
// Access to the screen bitmap
|
||||||
|
|
||||||
|
byte GETBIT(byte *p, int n)
|
||||||
|
{
|
||||||
|
return (p[n >> 3] & (1 << (n & 7))) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SETBIT(byte *p, int n)
|
||||||
|
{
|
||||||
|
p[n >> 3] |= (1 << (n & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLRBIT(byte *p, int n)
|
||||||
|
{
|
||||||
|
p[n >> 3] &= ~(1 << (n & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SETPIXEL(byte * p, int x, int y, byte b)
|
||||||
|
{
|
||||||
|
if (b)
|
||||||
|
SETBIT(p, y * WIDTH + x);
|
||||||
|
else
|
||||||
|
CLRBIT(p, y * WIDTH + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte GETPIXEL(byte *p, int x, int y)
|
||||||
|
{
|
||||||
|
return GETBIT(p, y * WIDTH + x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomFillWorld
|
||||||
|
//
|
||||||
|
// Populates the initial world with random cells
|
||||||
|
|
||||||
|
void RandomFillWorld()
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
// I need a better way to see the RNG or it'll be the same game every time!
|
||||||
|
srand(0);
|
||||||
|
for (x = 0; x < WIDTH; x++)
|
||||||
|
{
|
||||||
|
for (y = 0; y < HEIGHT; y++)
|
||||||
|
{
|
||||||
|
byte b = ((rand() % 100) < DENSITY) ? 1 : 0;
|
||||||
|
SETPIXEL(world, x, y, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountNeighbors
|
||||||
|
//
|
||||||
|
// Count the number of live cells around the given spot, excluding the actual spot specified
|
||||||
|
|
||||||
|
int CountNeighbors(int x, int y)
|
||||||
|
{
|
||||||
|
int i, j, nx, ny, count = 0;
|
||||||
|
|
||||||
|
for (j = -1; j <= 1; j++)
|
||||||
|
{
|
||||||
|
for (i = -1; i <= 1; i++)
|
||||||
|
{
|
||||||
|
if (i != 0 || j != 0)
|
||||||
|
{
|
||||||
|
nx = (x + i + WIDTH) % WIDTH;
|
||||||
|
ny = (y + j + HEIGHT) % HEIGHT;
|
||||||
|
count += GETPIXEL(world, nx, ny) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateWorld
|
||||||
|
//
|
||||||
|
// Applies the rules of Conway's Game of Life to the cells
|
||||||
|
|
||||||
|
void UpdateWorld()
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
for (y = 0; y < HEIGHT; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < WIDTH; x++)
|
||||||
|
{
|
||||||
|
int neighbors = CountNeighbors(x, y);
|
||||||
|
if (GETPIXEL(world, x, y))
|
||||||
|
SETPIXEL(new_world, x, y, (neighbors == 2 || neighbors == 3));
|
||||||
|
else
|
||||||
|
SETPIXEL(new_world, x, y, (neighbors == 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
printf("\r\nStarting Conway's Game of Life: Randomizing World...\r\n");
|
||||||
|
RandomFillWorld();
|
||||||
|
printf("World Ready, Running!\r\n");
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
UpdateWorld();
|
||||||
|
printf("[");
|
||||||
|
memcpy(world, new_world, NUMBYTES);
|
||||||
|
printf("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
262
samples/kim1/kimTest.c
Normal file
262
samples/kim1/kimTest.c
Normal file
|
@ -0,0 +1,262 @@
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Diagnostics Test for KIM-1
|
||||||
|
//
|
||||||
|
// Dave Plummer
|
||||||
|
// davepl@davepl.com
|
||||||
|
//
|
||||||
|
// Memory test examples by Michael Barr
|
||||||
|
//
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <stdio.h> // For printf
|
||||||
|
#include <stdlib.h> // For rand, srand
|
||||||
|
#include <string.h> // For memcpy
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
// RepeatChar
|
||||||
|
//
|
||||||
|
// Outputs a given character N times
|
||||||
|
|
||||||
|
void RepeatChar(char c, size_t count)
|
||||||
|
{
|
||||||
|
while (count--)
|
||||||
|
putc(c, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* Function: memTestDataBus()
|
||||||
|
*
|
||||||
|
* Description: Test the data bus wiring in a memory region by
|
||||||
|
* performing a walking 1's test at a fixed address
|
||||||
|
* within that region. The address (and hence the
|
||||||
|
* memory region) is selected by the caller.
|
||||||
|
*
|
||||||
|
* Returns: 0 if the test succeeds.
|
||||||
|
* A non-zero result is the first pattern that failed.
|
||||||
|
*
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
byte memTestDataBus(volatile byte * address)
|
||||||
|
{
|
||||||
|
byte pattern;
|
||||||
|
|
||||||
|
// Perform a walking 1's test at the given address.
|
||||||
|
|
||||||
|
for (pattern = 1; pattern != 0; pattern <<= 1)
|
||||||
|
{
|
||||||
|
// Write the test pattern.
|
||||||
|
*address = pattern;
|
||||||
|
|
||||||
|
// Read it back and check it
|
||||||
|
if (*address != pattern)
|
||||||
|
{
|
||||||
|
printf("\r\nmemTestDataBus: FAILED at %04x with pattern %02x\r\n", address, pattern);
|
||||||
|
return (pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* Function: memTestAddressBus()
|
||||||
|
*
|
||||||
|
* Description: Test the address bus wiring in a memory region by
|
||||||
|
* performing a walking 1's test on the relevant bits
|
||||||
|
* of the address and checking for aliasing. This test
|
||||||
|
* will find single-bit address failures such as stuck
|
||||||
|
* -high, stuck-low, and shorted pins. The base address
|
||||||
|
* and size of the region are selected by the caller.
|
||||||
|
*
|
||||||
|
* Notes: For best results, the selected base address should
|
||||||
|
* have enough LSB 0's to guarantee single address bit
|
||||||
|
* changes. For example, to test a 64-Kbyte region,
|
||||||
|
* select a base address on a 64-Kbyte boundary. Also,
|
||||||
|
* select the region size as a power-of-two--if at all
|
||||||
|
* possible.
|
||||||
|
*
|
||||||
|
* Returns: NULL if the test succeeds.
|
||||||
|
* A non-zero result is the first address at which an
|
||||||
|
* aliasing problem was uncovered. By examining the
|
||||||
|
* contents of memory, it may be possible to gather
|
||||||
|
* additional information about the problem.
|
||||||
|
*
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
byte * memTestAddressBus(volatile byte * baseAddress, unsigned long nBytes)
|
||||||
|
{
|
||||||
|
unsigned long addressMask = (nBytes/sizeof(byte) - 1);
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned long testOffset;
|
||||||
|
|
||||||
|
byte pattern = (byte) 0xAAAAAAAA;
|
||||||
|
byte antipattern = (byte) 0x55555555;
|
||||||
|
|
||||||
|
|
||||||
|
//Write the default pattern at each of the power-of-two offsets.
|
||||||
|
|
||||||
|
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
|
||||||
|
{
|
||||||
|
baseAddress[offset] = pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for address bits stuck high.
|
||||||
|
|
||||||
|
testOffset = 0;
|
||||||
|
baseAddress[testOffset] = antipattern;
|
||||||
|
|
||||||
|
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
|
||||||
|
{
|
||||||
|
if (baseAddress[offset] != pattern)
|
||||||
|
{
|
||||||
|
printf("\r\nmemTestAddressBus: FAILED at %04x with pattern %02x\r\n", baseAddress+offset, pattern);
|
||||||
|
return ((byte *) &baseAddress[offset]);
|
||||||
|
}
|
||||||
|
if (offset % 1024 == 0)
|
||||||
|
printf(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
baseAddress[testOffset] = pattern;
|
||||||
|
|
||||||
|
|
||||||
|
// Check for address bits stuck low or shorted.
|
||||||
|
|
||||||
|
for (testOffset = 1; (testOffset & addressMask) != 0; testOffset <<= 1)
|
||||||
|
{
|
||||||
|
baseAddress[testOffset] = antipattern;
|
||||||
|
|
||||||
|
if (baseAddress[0] != pattern)
|
||||||
|
{
|
||||||
|
return ((byte *) &baseAddress[testOffset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
|
||||||
|
{
|
||||||
|
if ((baseAddress[offset] != pattern) && (offset != testOffset))
|
||||||
|
{
|
||||||
|
printf("\r\nmemTestAddressBus: FAILED at %04x with pattern %02x\r\n", baseAddress+offset, pattern);
|
||||||
|
return ((byte *) &baseAddress[testOffset]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
baseAddress[testOffset] = pattern;
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* Function: memTestDevice()
|
||||||
|
*
|
||||||
|
* Description: Test the integrity of a physical memory device by
|
||||||
|
* performing an increment/decrement test over the
|
||||||
|
* entire region. In the process every storage bit
|
||||||
|
* in the device is tested as a zero and a one. The
|
||||||
|
* base address and the size of the region are
|
||||||
|
* selected by the caller.
|
||||||
|
*
|
||||||
|
* Returns: NULL if the test succeeds.
|
||||||
|
*
|
||||||
|
* A non-zero result is the first address at which an
|
||||||
|
* incorrect value was read back. By examining the
|
||||||
|
* contents of memory, it may be possible to gather
|
||||||
|
* additional information about the problem.
|
||||||
|
*
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
byte * memTestDevice(volatile byte * baseAddress, unsigned long nBytes)
|
||||||
|
{
|
||||||
|
unsigned long offset;
|
||||||
|
unsigned long nWords = nBytes / sizeof(byte);
|
||||||
|
|
||||||
|
byte pattern;
|
||||||
|
byte antipattern;
|
||||||
|
|
||||||
|
|
||||||
|
// Fill memory with a known pattern.
|
||||||
|
|
||||||
|
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
|
||||||
|
baseAddress[offset] = pattern;
|
||||||
|
|
||||||
|
// Check each location and invert it for the second pass.
|
||||||
|
|
||||||
|
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
|
||||||
|
{
|
||||||
|
if (offset % 1024 == 0)
|
||||||
|
printf("%04X ", (int) &baseAddress[offset]);
|
||||||
|
|
||||||
|
if (baseAddress[offset] != pattern)
|
||||||
|
{
|
||||||
|
printf("\r\nmemTestDevice: FAILED at %04x with pattern %02x\r\n", (int) &baseAddress[offset], pattern);
|
||||||
|
return ((byte *) &baseAddress[offset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
antipattern = ~pattern;
|
||||||
|
baseAddress[offset] = antipattern;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check each location for the inverted pattern and zero it.
|
||||||
|
|
||||||
|
for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
|
||||||
|
{
|
||||||
|
if (offset % 1024 == 0)
|
||||||
|
printf("%04X ", (int) &baseAddress[offset]);
|
||||||
|
|
||||||
|
antipattern = ~pattern;
|
||||||
|
if (baseAddress[offset] != antipattern)
|
||||||
|
{
|
||||||
|
printf("\r\nmemTestDevice: FAILED at %04x with antipattern %02x\r\n", (int) &baseAddress[offset], pattern);
|
||||||
|
return ((byte *) &baseAddress[offset]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestMemory
|
||||||
|
//
|
||||||
|
// Run all three memory tests
|
||||||
|
|
||||||
|
byte TestMemory(byte * startAddress, unsigned long size)
|
||||||
|
{
|
||||||
|
if ((memTestDataBus(startAddress) != 0) ||
|
||||||
|
(memTestAddressBus(startAddress, size) != NULL) ||
|
||||||
|
(memTestDevice(startAddress, size) != NULL))
|
||||||
|
{
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
printf("\r\nTesting KIM-1...\r\n");
|
||||||
|
RepeatChar('-', 39);
|
||||||
|
|
||||||
|
printf("\r\nTesting RIOT RAM: 1780-17BF\r\n");
|
||||||
|
if (TestMemory((byte *)0x1780, 0x17BF - 0x1780))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
printf("\r\nTesting RIOT RAM: 17C0-17E6\r\n");
|
||||||
|
if (TestMemory((byte *)0x17C0, 0x17E6 - 0x17C0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
printf("\r\nTesting Memory: 0400-13FF\r\n");
|
||||||
|
if (TestMemory((byte *)0x0400, 0x13FF - 0x0400))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
printf("\r\nTesting Memory: 4000-DFFF\r\n");
|
||||||
|
if (TestMemory((byte *)0x4000, 0xDFFF - 0x4000))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
printf("\r\nPASS!\r\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
272
samples/kim1/ramfont.asm
Normal file
272
samples/kim1/ramfont.asm
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
;-----------------------------------------------------------------------------------
|
||||||
|
; KIMGFX: Simple pixel graphics for the MOS/Commodore KIM-1
|
||||||
|
;-----------------------------------------------------------------------------------
|
||||||
|
; (c) Plummer's Software Ltd, 04/25/2023 Created
|
||||||
|
; David Plummer
|
||||||
|
;-----------------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; File: ramfont.s
|
||||||
|
; Magnetic OCR (check number style) Font data
|
||||||
|
;
|
||||||
|
;-----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.segment "CODE"
|
||||||
|
.export _font8x8_basic
|
||||||
|
|
||||||
|
_font8x8_basic:
|
||||||
|
.byte $1c, $22, $4a, $56, $4c, $20, $1e, $00 ; PETSCII code 0
|
||||||
|
.byte $3c, $24, $24, $7e, $62, $62, $62, $00 ; PETSCII code 1
|
||||||
|
.byte $78, $44, $44, $7c, $62, $62, $7e, $00 ; PETSCII code 2
|
||||||
|
.byte $7e, $42, $40, $60, $60, $62, $7e, $00 ; PETSCII code 3
|
||||||
|
.byte $7c, $46, $42, $62, $62, $66, $7c, $00 ; PETSCII code 4
|
||||||
|
.byte $7e, $40, $40, $7c, $60, $60, $7e, $00 ; PETSCII code 5
|
||||||
|
.byte $7e, $40, $40, $7e, $60, $60, $60, $00 ; PETSCII code 6
|
||||||
|
.byte $7e, $42, $40, $6e, $62, $62, $7e, $00 ; PETSCII code 7
|
||||||
|
.byte $42, $42, $42, $7e, $62, $62, $62, $00 ; PETSCII code 8
|
||||||
|
.byte $08, $08, $08, $0c, $0c, $0c, $0c, $00 ; PETSCII code 9
|
||||||
|
.byte $04, $04, $04, $06, $06, $46, $7e, $00 ; PETSCII code 10
|
||||||
|
.byte $42, $44, $48, $7c, $62, $62, $62, $00 ; PETSCII code 11
|
||||||
|
.byte $40, $40, $40, $60, $60, $60, $7e, $00 ; PETSCII code 12
|
||||||
|
.byte $7e, $4a, $4a, $6a, $6a, $6a, $6a, $00 ; PETSCII code 13
|
||||||
|
.byte $7e, $42, $42, $62, $62, $62, $62, $00 ; PETSCII code 14
|
||||||
|
.byte $7e, $46, $42, $42, $42, $42, $7e, $00 ; PETSCII code 15
|
||||||
|
.byte $7e, $42, $42, $7e, $60, $60, $60, $00 ; PETSCII code 16
|
||||||
|
.byte $7e, $42, $42, $42, $4a, $4e, $7e, $00 ; PETSCII code 17
|
||||||
|
.byte $7c, $44, $44, $7c, $62, $62, $62, $00 ; PETSCII code 18
|
||||||
|
.byte $7e, $42, $40, $7e, $06, $46, $7e, $00 ; PETSCII code 19
|
||||||
|
.byte $3e, $10, $10, $18, $18, $18, $18, $00 ; PETSCII code 20
|
||||||
|
.byte $42, $42, $42, $62, $62, $62, $7e, $00 ; PETSCII code 21
|
||||||
|
.byte $62, $62, $62, $66, $24, $24, $3c, $00 ; PETSCII code 22
|
||||||
|
.byte $4a, $4a, $4a, $6a, $6a, $6a, $7e, $00 ; PETSCII code 23
|
||||||
|
.byte $42, $42, $66, $18, $66, $62, $62, $00 ; PETSCII code 24
|
||||||
|
.byte $22, $22, $22, $3e, $18, $18, $18, $00 ; PETSCII code 25
|
||||||
|
.byte $7e, $42, $06, $18, $60, $62, $7e, $00 ; PETSCII code 26
|
||||||
|
.byte $3c, $20, $20, $20, $20, $20, $3c, $00 ; PETSCII code 27
|
||||||
|
.byte $00, $40, $20, $10, $08, $04, $02, $00 ; PETSCII code 28
|
||||||
|
.byte $3c, $04, $04, $04, $04, $04, $3c, $00 ; PETSCII code 29
|
||||||
|
.byte $00, $08, $1c, $2a, $08, $08, $14, $14 ; PETSCII code 30
|
||||||
|
.byte $00, $00, $10, $20, $7f, $20, $10, $00 ; PETSCII code 31
|
||||||
|
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 32
|
||||||
|
.byte $08, $08, $08, $0c, $0c, $00, $0c, $00 ; PETSCII code 33
|
||||||
|
.byte $6c, $24, $6c, $00, $00, $00, $00, $00 ; PETSCII code 34
|
||||||
|
.byte $24, $24, $7e, $24, $7e, $24, $24, $00 ; PETSCII code 35
|
||||||
|
.byte $08, $3e, $20, $3e, $06, $3e, $08, $00 ; PETSCII code 36
|
||||||
|
.byte $00, $62, $64, $08, $10, $26, $46, $00 ; PETSCII code 37
|
||||||
|
.byte $3c, $20, $24, $7e, $64, $64, $7c, $00 ; PETSCII code 38
|
||||||
|
.byte $1c, $18, $10, $00, $00, $00, $00, $00 ; PETSCII code 39
|
||||||
|
.byte $04, $08, $10, $10, $10, $08, $04, $00 ; PETSCII code 40
|
||||||
|
.byte $20, $10, $08, $08, $08, $10, $20, $00 ; PETSCII code 41
|
||||||
|
.byte $08, $2a, $1c, $3e, $1c, $2a, $08, $00 ; PETSCII code 42
|
||||||
|
.byte $00, $08, $08, $3e, $08, $08, $00, $00 ; PETSCII code 43
|
||||||
|
.byte $00, $00, $00, $00, $00, $18, $18, $08 ; PETSCII code 44
|
||||||
|
.byte $00, $00, $00, $7e, $00, $00, $00, $00 ; PETSCII code 45
|
||||||
|
.byte $00, $00, $00, $00, $00, $18, $18, $00 ; PETSCII code 46
|
||||||
|
.byte $00, $02, $04, $08, $10, $20, $40, $00 ; PETSCII code 47
|
||||||
|
.byte $7e, $62, $52, $4a, $46, $46, $7e, $00 ; PETSCII code 48
|
||||||
|
.byte $18, $08, $08, $18, $18, $1a, $3e, $00 ; PETSCII code 49
|
||||||
|
.byte $7e, $42, $02, $7e, $60, $60, $7e, $00 ; PETSCII code 50
|
||||||
|
.byte $7c, $44, $04, $1e, $06, $46, $7e, $00 ; PETSCII code 51
|
||||||
|
.byte $44, $44, $44, $44, $7e, $0c, $0c, $00 ; PETSCII code 52
|
||||||
|
.byte $7e, $40, $7e, $06, $06, $46, $7e, $00 ; PETSCII code 53
|
||||||
|
.byte $7e, $42, $40, $7e, $46, $46, $7e, $00 ; PETSCII code 54
|
||||||
|
.byte $7e, $02, $02, $06, $06, $06, $06, $00 ; PETSCII code 55
|
||||||
|
.byte $3c, $24, $24, $7e, $46, $46, $7e, $00 ; PETSCII code 56
|
||||||
|
.byte $7e, $42, $42, $7e, $06, $06, $06, $00 ; PETSCII code 57
|
||||||
|
.byte $00, $00, $18, $00, $00, $18, $00, $00 ; PETSCII code 58
|
||||||
|
.byte $00, $00, $18, $00, $00, $18, $18, $08 ; PETSCII code 59
|
||||||
|
.byte $0e, $18, $30, $60, $30, $18, $0e, $00 ; PETSCII code 60
|
||||||
|
.byte $00, $00, $7e, $00, $7e, $00, $00, $00 ; PETSCII code 61
|
||||||
|
.byte $70, $18, $0c, $06, $0c, $18, $70, $00 ; PETSCII code 62
|
||||||
|
.byte $7e, $02, $02, $7e, $60, $00, $60, $00 ; PETSCII code 63
|
||||||
|
.byte $00, $00, $00, $00, $ff, $00, $00, $00 ; PETSCII code 64
|
||||||
|
.byte $08, $1c, $3e, $7f, $7f, $1c, $3e, $00 ; PETSCII code 65
|
||||||
|
.byte $10, $10, $10, $10, $10, $10, $10, $10 ; PETSCII code 66
|
||||||
|
.byte $00, $00, $00, $ff, $00, $00, $00, $00 ; PETSCII code 67
|
||||||
|
.byte $00, $00, $ff, $00, $00, $00, $00, $00 ; PETSCII code 68
|
||||||
|
.byte $00, $ff, $00, $00, $00, $00, $00, $00 ; PETSCII code 69
|
||||||
|
.byte $00, $00, $00, $00, $00, $ff, $00, $00 ; PETSCII code 70
|
||||||
|
.byte $20, $20, $20, $20, $20, $20, $20, $20 ; PETSCII code 71
|
||||||
|
.byte $04, $04, $04, $04, $04, $04, $04, $04 ; PETSCII code 72
|
||||||
|
.byte $00, $00, $00, $00, $e0, $10, $08, $08 ; PETSCII code 73
|
||||||
|
.byte $08, $08, $08, $04, $03, $00, $00, $00 ; PETSCII code 74
|
||||||
|
.byte $08, $08, $08, $10, $e0, $00, $00, $00 ; PETSCII code 75
|
||||||
|
.byte $80, $80, $80, $80, $80, $80, $80, $ff ; PETSCII code 76
|
||||||
|
.byte $80, $40, $20, $10, $08, $04, $02, $01 ; PETSCII code 77
|
||||||
|
.byte $01, $02, $04, $08, $10, $20, $40, $80 ; PETSCII code 78
|
||||||
|
.byte $ff, $80, $80, $80, $80, $80, $80, $80 ; PETSCII code 79
|
||||||
|
.byte $ff, $01, $01, $01, $01, $01, $01, $01 ; PETSCII code 80
|
||||||
|
.byte $00, $3c, $7e, $7e, $7e, $7e, $3c, $00 ; PETSCII code 81
|
||||||
|
.byte $00, $00, $00, $00, $00, $00, $ff, $00 ; PETSCII code 82
|
||||||
|
.byte $36, $7f, $7f, $7f, $3e, $1c, $08, $00 ; PETSCII code 83
|
||||||
|
.byte $40, $40, $40, $40, $40, $40, $40, $40 ; PETSCII code 84
|
||||||
|
.byte $00, $00, $00, $00, $03, $04, $08, $08 ; PETSCII code 85
|
||||||
|
.byte $81, $42, $24, $18, $18, $24, $42, $81 ; PETSCII code 86
|
||||||
|
.byte $00, $3c, $42, $42, $42, $42, $3c, $00 ; PETSCII code 87
|
||||||
|
.byte $08, $1c, $2a, $77, $2a, $08, $08, $00 ; PETSCII code 88
|
||||||
|
.byte $02, $02, $02, $02, $02, $02, $02, $02 ; PETSCII code 89
|
||||||
|
.byte $08, $1c, $3e, $7f, $3e, $1c, $08, $00 ; PETSCII code 90
|
||||||
|
.byte $08, $08, $08, $08, $ff, $08, $08, $08 ; PETSCII code 91
|
||||||
|
.byte $a0, $50, $a0, $50, $a0, $50, $a0, $50 ; PETSCII code 92
|
||||||
|
.byte $08, $08, $08, $08, $08, $08, $08, $08 ; PETSCII code 93
|
||||||
|
.byte $00, $00, $01, $3e, $54, $14, $14, $00 ; PETSCII code 94
|
||||||
|
.byte $ff, $7f, $3f, $1f, $0f, $07, $03, $01 ; PETSCII code 95
|
||||||
|
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 96
|
||||||
|
.byte $f0, $f0, $f0, $f0, $f0, $f0, $f0, $f0 ; PETSCII code 97
|
||||||
|
.byte $00, $00, $00, $00, $ff, $ff, $ff, $ff ; PETSCII code 98
|
||||||
|
.byte $ff, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 99
|
||||||
|
.byte $00, $00, $00, $00, $00, $00, $00, $ff ; PETSCII code 100
|
||||||
|
.byte $80, $80, $80, $80, $80, $80, $80, $80 ; PETSCII code 101
|
||||||
|
.byte $aa, $55, $aa, $55, $aa, $55, $aa, $55 ; PETSCII code 102
|
||||||
|
.byte $01, $01, $01, $01, $01, $01, $01, $01 ; PETSCII code 103
|
||||||
|
.byte $00, $00, $00, $00, $aa, $55, $aa, $55 ; PETSCII code 104
|
||||||
|
.byte $ff, $fe, $fc, $f8, $f0, $e0, $c0, $80 ; PETSCII code 105
|
||||||
|
.byte $03, $03, $03, $03, $03, $03, $03, $03 ; PETSCII code 106
|
||||||
|
.byte $08, $08, $08, $08, $0f, $08, $08, $08 ; PETSCII code 107
|
||||||
|
.byte $00, $00, $00, $00, $0f, $0f, $0f, $0f ; PETSCII code 108
|
||||||
|
.byte $08, $08, $08, $08, $0f, $00, $00, $00 ; PETSCII code 109
|
||||||
|
.byte $00, $00, $00, $00, $f8, $08, $08, $08 ; PETSCII code 110
|
||||||
|
.byte $00, $00, $00, $00, $00, $00, $ff, $ff ; PETSCII code 111
|
||||||
|
.byte $00, $00, $00, $00, $0f, $08, $08, $08 ; PETSCII code 112
|
||||||
|
.byte $08, $08, $08, $08, $ff, $00, $00, $00 ; PETSCII code 113
|
||||||
|
.byte $00, $00, $00, $00, $ff, $08, $08, $08 ; PETSCII code 114
|
||||||
|
.byte $08, $08, $08, $08, $f8, $08, $08, $08 ; PETSCII code 115
|
||||||
|
.byte $c0, $c0, $c0, $c0, $c0, $c0, $c0, $c0 ; PETSCII code 116
|
||||||
|
.byte $e0, $e0, $e0, $e0, $e0, $e0, $e0, $e0 ; PETSCII code 117
|
||||||
|
.byte $07, $07, $07, $07, $07, $07, $07, $07 ; PETSCII code 118
|
||||||
|
.byte $ff, $ff, $00, $00, $00, $00, $00, $00 ; PETSCII code 119
|
||||||
|
.byte $ff, $ff, $ff, $00, $00, $00, $00, $00 ; PETSCII code 120
|
||||||
|
.byte $00, $00, $00, $00, $00, $ff, $ff, $ff ; PETSCII code 121
|
||||||
|
.byte $01, $01, $01, $01, $01, $01, $01, $ff ; PETSCII code 122
|
||||||
|
.byte $00, $00, $00, $00, $f0, $f0, $f0, $f0 ; PETSCII code 123
|
||||||
|
.byte $0f, $0f, $0f, $0f, $00, $00, $00, $00 ; PETSCII code 124
|
||||||
|
.byte $08, $08, $08, $08, $f8, $00, $00, $00 ; PETSCII code 125
|
||||||
|
.byte $f0, $f0, $f0, $f0, $00, $00, $00, $00 ; PETSCII code 126
|
||||||
|
.byte $f0, $f0, $f0, $f0, $0f, $0f, $0f, $0f ; PETSCII code 127
|
||||||
|
.byte $1c, $22, $4a, $56, $4c, $20, $1e, $00 ; PETSCII code 128
|
||||||
|
.byte $00, $00, $3c, $04, $7c, $64, $7c, $00 ; PETSCII code 129
|
||||||
|
.byte $40, $40, $7e, $42, $62, $62, $7e, $00 ; PETSCII code 130
|
||||||
|
.byte $00, $00, $7e, $42, $60, $62, $7e, $00 ; PETSCII code 131
|
||||||
|
.byte $02, $02, $7e, $42, $62, $62, $7e, $00 ; PETSCII code 132
|
||||||
|
.byte $00, $00, $7e, $42, $7e, $60, $7e, $00 ; PETSCII code 133
|
||||||
|
.byte $1e, $12, $10, $7c, $18, $18, $18, $00 ; PETSCII code 134
|
||||||
|
.byte $00, $00, $7e, $42, $62, $7e, $02, $7e ; PETSCII code 135
|
||||||
|
.byte $40, $40, $7e, $42, $62, $62, $62, $00 ; PETSCII code 136
|
||||||
|
.byte $18, $00, $10, $10, $18, $18, $18, $00 ; PETSCII code 137
|
||||||
|
.byte $0c, $00, $08, $0c, $0c, $0c, $44, $7c ; PETSCII code 138
|
||||||
|
.byte $40, $40, $44, $48, $78, $64, $64, $00 ; PETSCII code 139
|
||||||
|
.byte $10, $10, $10, $10, $18, $18, $18, $00 ; PETSCII code 140
|
||||||
|
.byte $00, $00, $7f, $49, $6d, $6d, $6d, $00 ; PETSCII code 141
|
||||||
|
.byte $00, $00, $7e, $42, $62, $62, $62, $00 ; PETSCII code 142
|
||||||
|
.byte $00, $00, $7e, $42, $62, $62, $7e, $00 ; PETSCII code 143
|
||||||
|
.byte $00, $00, $7e, $42, $62, $7e, $40, $40 ; PETSCII code 144
|
||||||
|
.byte $00, $00, $7e, $42, $46, $7e, $02, $02 ; PETSCII code 145
|
||||||
|
.byte $00, $00, $7e, $40, $60, $60, $60, $00 ; PETSCII code 146
|
||||||
|
.byte $00, $00, $7e, $40, $7e, $06, $7e, $00 ; PETSCII code 147
|
||||||
|
.byte $10, $10, $7c, $10, $18, $18, $18, $00 ; PETSCII code 148
|
||||||
|
.byte $00, $00, $42, $42, $62, $62, $7e, $00 ; PETSCII code 149
|
||||||
|
.byte $00, $00, $62, $62, $66, $24, $3c, $00 ; PETSCII code 150
|
||||||
|
.byte $00, $00, $49, $49, $6d, $6d, $7f, $00 ; PETSCII code 151
|
||||||
|
.byte $00, $00, $42, $42, $3c, $62, $62, $00 ; PETSCII code 152
|
||||||
|
.byte $00, $00, $62, $62, $42, $7e, $02, $7e ; PETSCII code 153
|
||||||
|
.byte $00, $00, $7e, $06, $18, $60, $7e, $00 ; PETSCII code 154
|
||||||
|
.byte $3c, $20, $20, $20, $20, $20, $3c, $00 ; PETSCII code 155
|
||||||
|
.byte $00, $40, $20, $10, $08, $04, $02, $00 ; PETSCII code 156
|
||||||
|
.byte $3c, $04, $04, $04, $04, $04, $3c, $00 ; PETSCII code 157
|
||||||
|
.byte $00, $08, $1c, $2a, $08, $08, $14, $14 ; PETSCII code 158
|
||||||
|
.byte $00, $00, $10, $20, $7f, $20, $10, $00 ; PETSCII code 159
|
||||||
|
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 160
|
||||||
|
.byte $08, $08, $08, $0c, $0c, $00, $0c, $00 ; PETSCII code 161
|
||||||
|
.byte $6c, $24, $6c, $00, $00, $00, $00, $00 ; PETSCII code 162
|
||||||
|
.byte $24, $24, $7e, $24, $7e, $24, $24, $00 ; PETSCII code 163
|
||||||
|
.byte $08, $3e, $20, $3e, $06, $3e, $08, $00 ; PETSCII code 164
|
||||||
|
.byte $00, $62, $64, $08, $10, $26, $46, $00 ; PETSCII code 165
|
||||||
|
.byte $3c, $20, $24, $7e, $64, $64, $7c, $00 ; PETSCII code 166
|
||||||
|
.byte $1c, $18, $10, $00, $00, $00, $00, $00 ; PETSCII code 167
|
||||||
|
.byte $04, $08, $10, $10, $10, $08, $04, $00 ; PETSCII code 168
|
||||||
|
.byte $20, $10, $08, $08, $08, $10, $20, $00 ; PETSCII code 169
|
||||||
|
.byte $08, $2a, $1c, $3e, $1c, $2a, $08, $00 ; PETSCII code 170
|
||||||
|
.byte $00, $08, $08, $3e, $08, $08, $00, $00 ; PETSCII code 171
|
||||||
|
.byte $00, $00, $00, $00, $00, $18, $18, $08 ; PETSCII code 172
|
||||||
|
.byte $00, $00, $00, $7e, $00, $00, $00, $00 ; PETSCII code 173
|
||||||
|
.byte $00, $00, $00, $00, $00, $18, $18, $00 ; PETSCII code 174
|
||||||
|
.byte $00, $02, $04, $08, $10, $20, $40, $00 ; PETSCII code 175
|
||||||
|
.byte $7e, $62, $52, $4a, $46, $46, $7e, $00 ; PETSCII code 176
|
||||||
|
.byte $38, $08, $08, $18, $18, $1a, $3e, $00 ; PETSCII code 177
|
||||||
|
.byte $7e, $42, $02, $7e, $60, $60, $7e, $00 ; PETSCII code 178
|
||||||
|
.byte $7c, $44, $04, $1e, $06, $46, $7e, $00 ; PETSCII code 179
|
||||||
|
.byte $44, $44, $44, $44, $7e, $0c, $0c, $00 ; PETSCII code 180
|
||||||
|
.byte $7e, $40, $7e, $06, $06, $46, $7e, $00 ; PETSCII code 181
|
||||||
|
.byte $7e, $42, $40, $7e, $46, $46, $7e, $00 ; PETSCII code 182
|
||||||
|
.byte $7e, $02, $02, $06, $06, $06, $06, $00 ; PETSCII code 183
|
||||||
|
.byte $3c, $24, $24, $7e, $46, $46, $7e, $00 ; PETSCII code 184
|
||||||
|
.byte $7e, $42, $42, $7e, $06, $06, $06, $00 ; PETSCII code 185
|
||||||
|
.byte $00, $00, $18, $00, $00, $18, $00, $00 ; PETSCII code 186
|
||||||
|
.byte $00, $00, $18, $00, $00, $18, $18, $08 ; PETSCII code 187
|
||||||
|
.byte $0e, $18, $30, $60, $30, $18, $0e, $00 ; PETSCII code 188
|
||||||
|
.byte $00, $00, $7e, $00, $7e, $00, $00, $00 ; PETSCII code 189
|
||||||
|
.byte $70, $18, $0c, $06, $0c, $18, $70, $00 ; PETSCII code 190
|
||||||
|
.byte $7e, $02, $02, $7e, $60, $00, $60, $00 ; PETSCII code 191
|
||||||
|
.byte $00, $00, $00, $00, $ff, $00, $00, $00 ; PETSCII code 192
|
||||||
|
.byte $3c, $24, $24, $7e, $62, $62, $62, $00 ; PETSCII code 193
|
||||||
|
.byte $78, $44, $44, $7c, $62, $62, $7e, $00 ; PETSCII code 194
|
||||||
|
.byte $7e, $42, $40, $60, $60, $62, $7e, $00 ; PETSCII code 195
|
||||||
|
.byte $7c, $46, $42, $62, $62, $66, $7c, $00 ; PETSCII code 196
|
||||||
|
.byte $7e, $40, $40, $78, $60, $60, $7e, $00 ; PETSCII code 197
|
||||||
|
.byte $7e, $40, $40, $7e, $60, $60, $60, $00 ; PETSCII code 198
|
||||||
|
.byte $7e, $42, $40, $6e, $62, $62, $7e, $00 ; PETSCII code 199
|
||||||
|
.byte $42, $42, $42, $7e, $62, $62, $62, $00 ; PETSCII code 200
|
||||||
|
.byte $08, $08, $08, $0c, $0c, $0c, $0c, $00 ; PETSCII code 201
|
||||||
|
.byte $04, $04, $04, $06, $06, $46, $7e, $00 ; PETSCII code 202
|
||||||
|
.byte $42, $44, $48, $7c, $62, $62, $62, $00 ; PETSCII code 203
|
||||||
|
.byte $40, $40, $40, $60, $60, $60, $7e, $00 ; PETSCII code 204
|
||||||
|
.byte $7e, $4a, $4a, $6a, $6a, $6a, $6a, $00 ; PETSCII code 205
|
||||||
|
.byte $7e, $42, $42, $62, $62, $62, $62, $00 ; PETSCII code 206
|
||||||
|
.byte $7e, $46, $42, $42, $42, $42, $7e, $00 ; PETSCII code 207
|
||||||
|
.byte $7e, $42, $42, $7e, $60, $60, $60, $00 ; PETSCII code 208
|
||||||
|
.byte $7e, $42, $42, $42, $4a, $4e, $7e, $00 ; PETSCII code 209
|
||||||
|
.byte $7c, $44, $44, $7c, $62, $62, $62, $00 ; PETSCII code 210
|
||||||
|
.byte $7e, $42, $40, $7e, $06, $46, $7e, $00 ; PETSCII code 211
|
||||||
|
.byte $3e, $10, $10, $18, $18, $18, $18, $00 ; PETSCII code 212
|
||||||
|
.byte $42, $42, $42, $62, $62, $62, $7e, $00 ; PETSCII code 213
|
||||||
|
.byte $62, $62, $62, $66, $24, $24, $3c, $00 ; PETSCII code 214
|
||||||
|
.byte $4a, $4a, $4a, $6a, $6a, $6a, $7e, $00 ; PETSCII code 215
|
||||||
|
.byte $42, $42, $66, $3c, $66, $62, $62, $00 ; PETSCII code 216
|
||||||
|
.byte $22, $22, $22, $3e, $18, $18, $18, $00 ; PETSCII code 217
|
||||||
|
.byte $7e, $42, $06, $18, $60, $62, $7e, $00 ; PETSCII code 218
|
||||||
|
.byte $08, $08, $08, $08, $ff, $08, $08, $08 ; PETSCII code 219
|
||||||
|
.byte $a0, $50, $a0, $50, $a0, $50, $a0, $50 ; PETSCII code 220
|
||||||
|
.byte $08, $08, $08, $08, $08, $08, $08, $08 ; PETSCII code 221
|
||||||
|
.byte $cc, $cc, $33, $33, $cc, $cc, $33, $33 ; PETSCII code 222
|
||||||
|
.byte $cc, $66, $33, $99, $cc, $66, $33, $99 ; PETSCII code 223
|
||||||
|
.byte $00, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 224
|
||||||
|
.byte $f0, $f0, $f0, $f0, $f0, $f0, $f0, $f0 ; PETSCII code 225
|
||||||
|
.byte $00, $00, $00, $00, $ff, $ff, $ff, $ff ; PETSCII code 226
|
||||||
|
.byte $ff, $00, $00, $00, $00, $00, $00, $00 ; PETSCII code 227
|
||||||
|
.byte $00, $00, $00, $00, $00, $00, $00, $ff ; PETSCII code 228
|
||||||
|
.byte $80, $80, $80, $80, $80, $80, $80, $80 ; PETSCII code 229
|
||||||
|
.byte $aa, $55, $aa, $55, $aa, $55, $aa, $55 ; PETSCII code 230
|
||||||
|
.byte $01, $01, $01, $01, $01, $01, $01, $01 ; PETSCII code 231
|
||||||
|
.byte $00, $00, $00, $00, $aa, $55, $aa, $55 ; PETSCII code 232
|
||||||
|
.byte $99, $33, $66, $cc, $99, $33, $66, $cc ; PETSCII code 233
|
||||||
|
.byte $03, $03, $03, $03, $03, $03, $03, $03 ; PETSCII code 234
|
||||||
|
.byte $08, $08, $08, $08, $0f, $08, $08, $08 ; PETSCII code 235
|
||||||
|
.byte $00, $00, $00, $00, $0f, $0f, $0f, $0f ; PETSCII code 236
|
||||||
|
.byte $08, $08, $08, $08, $0f, $00, $00, $00 ; PETSCII code 237
|
||||||
|
.byte $00, $00, $00, $00, $f8, $08, $08, $08 ; PETSCII code 238
|
||||||
|
.byte $00, $00, $00, $00, $00, $00, $ff, $ff ; PETSCII code 239
|
||||||
|
.byte $00, $00, $00, $00, $0f, $08, $08, $08 ; PETSCII code 240
|
||||||
|
.byte $08, $08, $08, $08, $ff, $00, $00, $00 ; PETSCII code 241
|
||||||
|
.byte $00, $00, $00, $00, $ff, $08, $08, $08 ; PETSCII code 242
|
||||||
|
.byte $08, $08, $08, $08, $f8, $08, $08, $08 ; PETSCII code 243
|
||||||
|
.byte $c0, $c0, $c0, $c0, $c0, $c0, $c0, $c0 ; PETSCII code 244
|
||||||
|
.byte $e0, $e0, $e0, $e0, $e0, $e0, $e0, $e0 ; PETSCII code 245
|
||||||
|
.byte $07, $07, $07, $07, $07, $07, $07, $07 ; PETSCII code 246
|
||||||
|
.byte $ff, $ff, $00, $00, $00, $00, $00, $00 ; PETSCII code 247
|
||||||
|
.byte $ff, $ff, $ff, $00, $00, $00, $00, $00 ; PETSCII code 248
|
||||||
|
.byte $00, $00, $00, $00, $00, $ff, $ff, $ff ; PETSCII code 249
|
||||||
|
.byte $01, $02, $44, $48, $50, $60, $40, $00 ; PETSCII code 250
|
||||||
|
.byte $00, $00, $00, $00, $f0, $f0, $f0, $f0 ; PETSCII code 251
|
||||||
|
.byte $0f, $0f, $0f, $0f, $00, $00, $00, $00 ; PETSCII code 252
|
||||||
|
.byte $08, $08, $08, $08, $f8, $00, $00, $00 ; PETSCII code 253
|
||||||
|
.byte $f0, $f0, $f0, $f0, $00, $00, $00, $00 ; PETSCII code 254
|
||||||
|
.byte $f0, $f0, $f0, $f0, $0f, $0f, $0f, $0f ; PETSCII code 255
|
1140
samples/kim1/subs.asm
Normal file
1140
samples/kim1/subs.asm
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -136,10 +136,10 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
|
||||||
SB_Append (FullName, Name);
|
SB_Append (FullName, Name);
|
||||||
|
|
||||||
/* Search for the child scope */
|
/* Search for the child scope */
|
||||||
Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING);
|
Scope = SymFindScope (Scope, Name, SYM_ALLOC_NEW);
|
||||||
if (Scope == 0) {
|
if (Scope == 0) {
|
||||||
/* Scope not found */
|
/* Scope not found */
|
||||||
Error ("No such scope: '%m%p'", FullName);
|
Error ("Can't create scope: '%m%p'", FullName);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3260,6 +3260,14 @@ void g_asr (unsigned flags, unsigned long val)
|
||||||
}
|
}
|
||||||
val -= 8;
|
val -= 8;
|
||||||
}
|
}
|
||||||
|
if (val == 7) {
|
||||||
|
if (flags & CF_UNSIGNED) {
|
||||||
|
AddCodeLine ("jsr shrax7");
|
||||||
|
} else {
|
||||||
|
AddCodeLine ("jsr asrax7");
|
||||||
|
}
|
||||||
|
val = 0;
|
||||||
|
}
|
||||||
if (val >= 4) {
|
if (val >= 4) {
|
||||||
if (flags & CF_UNSIGNED) {
|
if (flags & CF_UNSIGNED) {
|
||||||
AddCodeLine ("jsr shrax4");
|
AddCodeLine ("jsr shrax4");
|
||||||
|
@ -3402,6 +3410,14 @@ void g_asl (unsigned flags, unsigned long val)
|
||||||
AddCodeLine ("lda #$00");
|
AddCodeLine ("lda #$00");
|
||||||
val -= 8;
|
val -= 8;
|
||||||
}
|
}
|
||||||
|
if (val == 7) {
|
||||||
|
if (flags & CF_UNSIGNED) {
|
||||||
|
AddCodeLine ("jsr shlax7");
|
||||||
|
} else {
|
||||||
|
AddCodeLine ("jsr aslax7");
|
||||||
|
}
|
||||||
|
val = 0;
|
||||||
|
}
|
||||||
if (val >= 4) {
|
if (val >= 4) {
|
||||||
if (flags & CF_UNSIGNED) {
|
if (flags & CF_UNSIGNED) {
|
||||||
AddCodeLine ("jsr shlax4");
|
AddCodeLine ("jsr shlax4");
|
||||||
|
|
|
@ -99,6 +99,7 @@ static const FuncInfo FuncInfoTable[] = {
|
||||||
{ "aslax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "aslax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
{ "aslax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "aslax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
{ "aslax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "aslax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
|
{ "aslax7", REG_AX, PSTATE_ALL | REG_AXY },
|
||||||
{ "aslaxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
|
{ "aslaxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
|
||||||
{ "asleax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
{ "asleax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
||||||
{ "asleax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
{ "asleax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
||||||
|
@ -108,6 +109,7 @@ static const FuncInfo FuncInfoTable[] = {
|
||||||
{ "asrax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "asrax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
{ "asrax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "asrax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
{ "asrax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "asrax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
|
{ "asrax7", REG_AX, PSTATE_ALL | REG_AX },
|
||||||
{ "asraxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
|
{ "asraxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
|
||||||
{ "asreax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
{ "asreax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
||||||
{ "asreax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
{ "asreax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
||||||
|
@ -245,6 +247,7 @@ static const FuncInfo FuncInfoTable[] = {
|
||||||
{ "shlax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "shlax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
{ "shlax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "shlax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
{ "shlax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "shlax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
|
{ "shlax7", REG_AX, PSTATE_ALL | REG_AXY },
|
||||||
{ "shlaxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
|
{ "shlaxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
|
||||||
{ "shleax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
{ "shleax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
||||||
{ "shleax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
{ "shleax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
||||||
|
@ -254,6 +257,7 @@ static const FuncInfo FuncInfoTable[] = {
|
||||||
{ "shrax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "shrax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
{ "shrax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "shrax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
{ "shrax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
{ "shrax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
|
||||||
|
{ "shrax7", REG_AX, PSTATE_ALL | REG_AX },
|
||||||
{ "shraxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
|
{ "shraxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
|
||||||
{ "shreax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
{ "shreax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
||||||
{ "shreax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
{ "shreax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
|
||||||
|
|
|
@ -1471,7 +1471,7 @@ void CS_Output (CodeSeg* S)
|
||||||
/* Add line debug info */
|
/* Add line debug info */
|
||||||
if (DebugInfo) {
|
if (DebugInfo) {
|
||||||
WriteOutput ("\t.dbg\tline, \"%s\", %u\n",
|
WriteOutput ("\t.dbg\tline, \"%s\", %u\n",
|
||||||
GetInputName (LI), GetInputLine (LI));
|
GetActualFileName (LI), GetActualLineNum (LI));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Output the code */
|
/* Output the code */
|
||||||
|
|
|
@ -121,7 +121,7 @@ static void Parse (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the declaration specifier */
|
/* Read the declaration specifier */
|
||||||
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT, SC_NONE);
|
ParseDeclSpec (&Spec, TS_DEFAULT_TYPE_INT | TS_FUNCTION_SPEC, SC_NONE);
|
||||||
|
|
||||||
/* Don't accept illegal storage classes */
|
/* Don't accept illegal storage classes */
|
||||||
if ((Spec.StorageClass & SC_STORAGEMASK) == SC_AUTO ||
|
if ((Spec.StorageClass & SC_STORAGEMASK) == SC_AUTO ||
|
||||||
|
@ -163,6 +163,9 @@ static void Parse (void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The symbol is now visible in the file scope */
|
||||||
|
if ((Decl.StorageClass & SC_TYPEMASK) != SC_FUNC &&
|
||||||
|
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
|
||||||
/* Check if we must reserve storage for the variable. We do this,
|
/* Check if we must reserve storage for the variable. We do this,
|
||||||
**
|
**
|
||||||
** - if it is not a typedef or function,
|
** - if it is not a typedef or function,
|
||||||
|
@ -173,9 +176,6 @@ static void Parse (void)
|
||||||
** This means that "extern int i;" will not get storage allocated
|
** This means that "extern int i;" will not get storage allocated
|
||||||
** in this translation unit.
|
** in this translation unit.
|
||||||
*/
|
*/
|
||||||
if ((Decl.StorageClass & SC_TYPEMASK) != SC_FUNC &&
|
|
||||||
(Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) {
|
|
||||||
/* The variable is visible in the file scope */
|
|
||||||
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_NONE ||
|
if ((Decl.StorageClass & SC_STORAGEMASK) == SC_NONE ||
|
||||||
(Decl.StorageClass & SC_STORAGEMASK) == SC_STATIC ||
|
(Decl.StorageClass & SC_STORAGEMASK) == SC_STATIC ||
|
||||||
((Decl.StorageClass & SC_STORAGEMASK) == SC_EXTERN &&
|
((Decl.StorageClass & SC_STORAGEMASK) == SC_EXTERN &&
|
||||||
|
@ -189,7 +189,6 @@ static void Parse (void)
|
||||||
** or semicolon, it must be followed by a function body.
|
** or semicolon, it must be followed by a function body.
|
||||||
*/
|
*/
|
||||||
if ((Decl.StorageClass & SC_TYPEMASK) == SC_FUNC) {
|
if ((Decl.StorageClass & SC_TYPEMASK) == SC_FUNC) {
|
||||||
/* The function is now visible in the file scope */
|
|
||||||
if (CurTok.Tok == TOK_LCURLY) {
|
if (CurTok.Tok == TOK_LCURLY) {
|
||||||
/* A definition */
|
/* A definition */
|
||||||
Decl.StorageClass |= SC_DEF;
|
Decl.StorageClass |= SC_DEF;
|
||||||
|
@ -560,6 +559,10 @@ void Compile (const char* FileName)
|
||||||
if ((Entry->Flags & SC_STORAGEMASK) == SC_STATIC && SymIsRef (Entry)) {
|
if ((Entry->Flags & SC_STORAGEMASK) == SC_STATIC && SymIsRef (Entry)) {
|
||||||
Warning ("Static function '%s' used but never defined",
|
Warning ("Static function '%s' used but never defined",
|
||||||
Entry->Name);
|
Entry->Name);
|
||||||
|
} else if ((Entry->Flags & SC_INLINE) != 0) {
|
||||||
|
Warning ("Inline function '%s' %s but never defined",
|
||||||
|
Entry->Name,
|
||||||
|
SymIsRef (Entry) ? "used" : "declared");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1488,7 +1488,7 @@ static const OptFuncDesc FuncTable[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const OptFuncDesc FuncRegATable[] = {
|
static const OptFuncDesc FuncRegATable[] = {
|
||||||
{ "tosandax", Opt_a_tosand, REG_NONE, OP_NONE },
|
{ "tosandax", Opt_a_tosand, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
|
||||||
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
|
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
|
||||||
{ "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE },
|
{ "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE },
|
||||||
{ "tosgtax", Opt_a_tosugt, REG_NONE, OP_NONE },
|
{ "tosgtax", Opt_a_tosugt, REG_NONE, OP_NONE },
|
||||||
|
@ -1496,13 +1496,13 @@ static const OptFuncDesc FuncRegATable[] = {
|
||||||
{ "tosleax", Opt_a_tosule, REG_NONE, OP_NONE },
|
{ "tosleax", Opt_a_tosule, REG_NONE, OP_NONE },
|
||||||
{ "tosltax", Opt_a_tosult, REG_NONE, OP_NONE },
|
{ "tosltax", Opt_a_tosult, REG_NONE, OP_NONE },
|
||||||
{ "tosneax", Opt_a_tosne, REG_NONE, OP_NONE },
|
{ "tosneax", Opt_a_tosne, REG_NONE, OP_NONE },
|
||||||
{ "tosorax", Opt_a_tosor, REG_NONE, OP_NONE },
|
{ "tosorax", Opt_a_tosor, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
|
||||||
{ "tossubax", Opt_a_tossub, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
|
{ "tossubax", Opt_a_tossub, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
|
||||||
{ "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE },
|
{ "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE },
|
||||||
{ "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE },
|
{ "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE },
|
||||||
{ "tosuleax", Opt_a_tosule, REG_NONE, OP_NONE },
|
{ "tosuleax", Opt_a_tosule, REG_NONE, OP_NONE },
|
||||||
{ "tosultax", Opt_a_tosult, REG_NONE, OP_NONE },
|
{ "tosultax", Opt_a_tosult, REG_NONE, OP_NONE },
|
||||||
{ "tosxorax", Opt_a_tosxor, REG_NONE, OP_NONE },
|
{ "tosxorax", Opt_a_tosxor, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FUNC_COUNT(Table) (sizeof(Table) / sizeof(Table[0]))
|
#define FUNC_COUNT(Table) (sizeof(Table) / sizeof(Table[0]))
|
||||||
|
|
|
@ -989,6 +989,24 @@ int IsIncompleteESUType (const Type* T)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int IsAnonESUType (const Type* T)
|
||||||
|
/* Return true if this is an anonymous ESU type */
|
||||||
|
{
|
||||||
|
SymEntry* TagSym = GetESUTagSym (T);
|
||||||
|
|
||||||
|
return TagSym != 0 && SymHasAnonName (TagSym);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int IsAnonStructClass (const Type* T)
|
||||||
|
/* Return true if this is an anonymous struct or union type */
|
||||||
|
{
|
||||||
|
return IsClassStruct (T) && IsAnonESUType (T);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int IsPassByRefType (const Type* T)
|
int IsPassByRefType (const Type* T)
|
||||||
/* Return true if this is a large struct/union type that doesn't fit in the
|
/* Return true if this is a large struct/union type that doesn't fit in the
|
||||||
** primary. This returns false for the void value extension type since it is
|
** primary. This returns false for the void value extension type since it is
|
||||||
|
|
|
@ -792,6 +792,12 @@ int IsESUType (const Type* T);
|
||||||
int IsIncompleteESUType (const Type* T);
|
int IsIncompleteESUType (const Type* T);
|
||||||
/* Return true if this is an incomplete ESU type */
|
/* Return true if this is an incomplete ESU type */
|
||||||
|
|
||||||
|
int IsAnonESUType (const Type* T);
|
||||||
|
/* Return true if this is an anonymous ESU type */
|
||||||
|
|
||||||
|
int IsAnonStructClass (const Type* T);
|
||||||
|
/* Return true if this is an anonymous struct or union type */
|
||||||
|
|
||||||
int IsPassByRefType (const Type* T);
|
int IsPassByRefType (const Type* T);
|
||||||
/* Return true if this is a large struct/union type that doesn't fit in the
|
/* Return true if this is a large struct/union type that doesn't fit in the
|
||||||
** primary. This returns false for the void value extension type since it is
|
** primary. This returns false for the void value extension type since it is
|
||||||
|
|
2382
src/cc65/declare.c
2382
src/cc65/declare.c
File diff suppressed because it is too large
Load Diff
123
src/cc65/error.c
123
src/cc65/error.c
|
@ -120,13 +120,46 @@ Collection DiagnosticStrBufs;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void PrintFileInclusionInfo (const LineInfo* LI)
|
||||||
|
/* Print hierarchy of file inclusion */
|
||||||
|
{
|
||||||
|
if (LI->IncFiles != 0) {
|
||||||
|
unsigned FileCount = CollCount (LI->IncFiles);
|
||||||
|
if (FileCount > 0) {
|
||||||
|
const char* Str = "In file included from %s:%u%c\n";
|
||||||
|
|
||||||
|
while (FileCount-- > 0) {
|
||||||
|
LineInfoFile* LIF = CollAtUnchecked (LI->IncFiles, FileCount);
|
||||||
|
char C = FileCount > 0 ? ',' : ':';
|
||||||
|
|
||||||
|
fprintf (stderr, Str, LIF->Name, LIF->LineNum, C);
|
||||||
|
Str = " from %s:%u%c\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static LineInfo* GetDiagnosticLI (void)
|
||||||
|
/* Get the line info where the diagnostic info refers to */
|
||||||
|
{
|
||||||
|
if (CurTok.LI) {
|
||||||
|
return CurTok.LI;
|
||||||
|
} else {
|
||||||
|
return GetCurLineInfo ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const char* GetDiagnosticFileName (void)
|
static const char* GetDiagnosticFileName (void)
|
||||||
/* Get the source file name where the diagnostic info refers to */
|
/* Get the source file name where the diagnostic info refers to */
|
||||||
{
|
{
|
||||||
if (CurTok.LI) {
|
if (CurTok.LI) {
|
||||||
return GetInputName (CurTok.LI);
|
return GetPresumedFileName (CurTok.LI);
|
||||||
} else {
|
} else {
|
||||||
return GetCurrentFilename ();
|
return GetCurrentFileName ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +169,7 @@ static unsigned GetDiagnosticLineNum (void)
|
||||||
/* Get the source line number where the diagnostic info refers to */
|
/* Get the source line number where the diagnostic info refers to */
|
||||||
{
|
{
|
||||||
if (CurTok.LI) {
|
if (CurTok.LI) {
|
||||||
return GetInputLine (CurTok.LI);
|
return GetPresumedLineNum (CurTok.LI);
|
||||||
} else {
|
} else {
|
||||||
return GetCurrentLineNum ();
|
return GetCurrentLineNum ();
|
||||||
}
|
}
|
||||||
|
@ -199,10 +232,18 @@ void Internal (const char* Format, ...)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void IntError (errcat_t EC, const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
|
static void IntError (errcat_t EC, LineInfo* LI, const char* Msg, va_list ap)
|
||||||
/* Print an error message - internal function */
|
/* Print an error message - internal function */
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s:%u: Error: ", Filename, LineNo);
|
unsigned LineNo = GetPresumedLineNum (LI);
|
||||||
|
|
||||||
|
/* Print file inclusion if appropriate */
|
||||||
|
if (HasFileInclusionChanged (LI)) {
|
||||||
|
PrintFileInclusionInfo (LI);
|
||||||
|
}
|
||||||
|
RememberCheckedLI (LI);
|
||||||
|
|
||||||
|
fprintf (stderr, "%s:%u: Error: ", GetPresumedFileName (LI), LineNo);
|
||||||
vfprintf (stderr, Msg, ap);
|
vfprintf (stderr, Msg, ap);
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
|
|
||||||
|
@ -229,23 +270,23 @@ static void IntError (errcat_t EC, const char* Filename, unsigned LineNo, const
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Error (const char* Format, ...)
|
void LIError (errcat_t EC, LineInfo* LI, const char* Format, ...)
|
||||||
/* Print an error message */
|
/* Print an error message with the line info given explicitly */
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
IntError (EC_PARSER, GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap);
|
IntError (EC, LI, Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void LIError (errcat_t EC, const LineInfo* LI, const char* Format, ...)
|
void Error (const char* Format, ...)
|
||||||
/* Print an error message with the line info given explicitly */
|
/* Print an error message */
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
IntError (EC, GetInputName (LI), GetInputLine (LI), Format, ap);
|
IntError (EC_PARSER, GetDiagnosticLI (), Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +297,7 @@ void PPError (const char* Format, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
IntError (EC_PP, GetCurrentFilename(), GetCurrentLineNum(), Format, ap);
|
IntError (EC_PP, GetCurLineInfo (), Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,17 +309,25 @@ void PPError (const char* Format, ...)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void IntWarning (errcat_t EC, const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
|
static void IntWarning (errcat_t EC, LineInfo* LI, const char* Msg, va_list ap)
|
||||||
/* Print a warning message - internal function */
|
/* Print a warning message - internal function */
|
||||||
{
|
{
|
||||||
if (IS_Get (&WarningsAreErrors)) {
|
if (IS_Get (&WarningsAreErrors)) {
|
||||||
|
|
||||||
/* Treat the warning as an error */
|
/* Treat the warning as an error */
|
||||||
IntError (EC, Filename, LineNo, Msg, ap);
|
IntError (EC, LI, Msg, ap);
|
||||||
|
|
||||||
} else if (IS_Get (&WarnEnable)) {
|
} else if (IS_Get (&WarnEnable)) {
|
||||||
|
|
||||||
fprintf (stderr, "%s:%u: Warning: ", Filename, LineNo);
|
unsigned LineNo = GetPresumedLineNum (LI);
|
||||||
|
|
||||||
|
/* Print file inclusion if appropriate */
|
||||||
|
if (HasFileInclusionChanged (LI)) {
|
||||||
|
PrintFileInclusionInfo (LI);
|
||||||
|
}
|
||||||
|
RememberCheckedLI (LI);
|
||||||
|
|
||||||
|
fprintf (stderr, "%s:%u: Warning: ", GetPresumedFileName (LI), LineNo);
|
||||||
vfprintf (stderr, Msg, ap);
|
vfprintf (stderr, Msg, ap);
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
|
|
||||||
|
@ -297,23 +346,23 @@ static void IntWarning (errcat_t EC, const char* Filename, unsigned LineNo, cons
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Warning (const char* Format, ...)
|
void LIWarning (errcat_t EC, LineInfo* LI, const char* Format, ...)
|
||||||
/* Print a warning message */
|
/* Print a warning message with the line info given explicitly */
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
IntWarning (EC_PARSER, GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap);
|
IntWarning (EC, LI, Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void LIWarning (errcat_t EC, const LineInfo* LI, const char* Format, ...)
|
void Warning (const char* Format, ...)
|
||||||
/* Print a warning message with the line info given explicitly */
|
/* Print a warning message */
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
IntWarning (EC, GetInputName (LI), GetInputLine (LI), Format, ap);
|
IntWarning (EC_PARSER, GetDiagnosticLI (), Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +373,7 @@ void PPWarning (const char* Format, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
IntWarning (EC_PP, GetCurrentFilename(), GetCurrentLineNum(), Format, ap);
|
IntWarning (EC_PP, GetCurLineInfo (), Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,33 +414,33 @@ void ListWarnings (FILE* F)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void IntNote (const char* Filename, unsigned LineNo, const char* Msg, va_list ap)
|
static void IntNote (const LineInfo* LI, const char* Msg, va_list ap)
|
||||||
/* Print a note message - internal function */
|
/* Print a note message - internal function */
|
||||||
{
|
{
|
||||||
fprintf (stderr, "%s:%u: Note: ", Filename, LineNo);
|
fprintf (stderr, "%s:%u: Note: ", GetPresumedFileName (LI), GetPresumedLineNum (LI));
|
||||||
vfprintf (stderr, Msg, ap);
|
vfprintf (stderr, Msg, ap);
|
||||||
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Note (const char* Format, ...)
|
|
||||||
/* Print a note message */
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start (ap, Format);
|
|
||||||
IntNote (GetDiagnosticFileName (), GetDiagnosticLineNum (), Format, ap);
|
|
||||||
va_end (ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void LINote (const LineInfo* LI, const char* Format, ...)
|
void LINote (const LineInfo* LI, const char* Format, ...)
|
||||||
/* Print a note message with the line info given explicitly */
|
/* Print a note message with the line info given explicitly */
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
IntNote (GetInputName (LI), GetInputLine (LI), Format, ap);
|
IntNote (LI, Format, ap);
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Note (const char* Format, ...)
|
||||||
|
/* Print a note message */
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start (ap, Format);
|
||||||
|
IntNote (GetDiagnosticLI (), Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +451,7 @@ void PPNote (const char* Format, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
IntNote (GetCurrentFilename(), GetCurrentLineNum(), Format, ap);
|
IntNote (GetDiagnosticLI (), Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,9 @@ struct StrBuf;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void PrintFileInclusionInfo (const LineInfo* LI);
|
||||||
|
/* Print hierarchy of file inclusion */
|
||||||
|
|
||||||
void Fatal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2)));
|
void Fatal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2)));
|
||||||
/* Print a message about a fatal error and die */
|
/* Print a message about a fatal error and die */
|
||||||
|
|
||||||
|
@ -109,7 +112,7 @@ void Internal (const char* Format, ...) attribute ((noreturn, format (printf, 1,
|
||||||
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
||||||
/* Print an error message */
|
/* Print an error message */
|
||||||
|
|
||||||
void LIError (errcat_t EC, const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 3, 4)));
|
void LIError (errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 3, 4)));
|
||||||
/* Print an error message with the line info given explicitly */
|
/* Print an error message with the line info given explicitly */
|
||||||
|
|
||||||
void PPError (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
void PPError (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
||||||
|
@ -118,7 +121,7 @@ void PPError (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
||||||
void Warning (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
void Warning (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
||||||
/* Print a warning message */
|
/* Print a warning message */
|
||||||
|
|
||||||
void LIWarning (errcat_t EC, const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 3, 4)));
|
void LIWarning (errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 3, 4)));
|
||||||
/* Print a warning message with the line info given explicitly */
|
/* Print a warning message with the line info given explicitly */
|
||||||
|
|
||||||
void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2)));
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user