Compare commits

...

231 Commits

Author SHA1 Message Date
pm100 1b93598de9
Merge eb2acfc3e4 into b1e1c13d4b 2024-04-26 15:53:46 -04:00
Bob Andrews b1e1c13d4b
Merge pull request #2437 from bbbradsmith/sim65-examples
provide simple examples for using sim65 with C and assembly code
2024-04-25 23:52:08 +02:00
bbbradsmith 8804dc7a58 give cl65 alternative 2024-04-16 16:56:13 -04:00
bbbradsmith 4bc726ebe2 clarify the meaning of the exit code unsigned limitation 2024-04-16 16:41:00 -04:00
bbbradsmith fa1a426c29 add -t sim6502 to cc65 and ca65 examples 2024-04-16 14:06:45 -04:00
bbbradsmith 89b709c7f8 make it clearer that explicit lib is required, note that exit is from stdlib.h, exit codes are unsigned, tweak "see below" for spacing, clarify that assembly can be used with C tests as well 2024-03-28 16:55:55 -04:00
bbbradsmith 79585194e6 provide simple examples for using sim65 with C and assembly code 2024-03-28 16:33:20 -04:00
mrdudz b993d88339 second half of #2420 - don't use the loop macro. Fixes -j13 for me 2024-03-17 17:19:42 +01:00
Bob Andrews 25967e65b5
Merge pull request #2424 from acqn/Cleanup
[cc65] Cleanups in src/cc65/declare.c
2024-03-10 02:39:14 +01:00
Bob Andrews a372ead4de
Merge pull request #2334 from carlo-bramini/fix-sim65-1
[SIM65] Support undocumented opcodes for 6502
2024-03-10 00:37:18 +01:00
Bob Andrews 081d18f7d7
Merge pull request #2422 from acqn/SubFix
[cc65] Fixed potential errors with subtraction evaluation of identifiers at different memory locations
2024-03-09 13:02:27 +01:00
Bob Andrews a293920fb3
Merge pull request #2423 from acqn/BitfieldFix
[cc65] Fixed the error recovery integer type used for bit-fields
2024-03-09 12:05:20 +01:00
Bob Andrews 60c75bdb54
Merge pull request #2414 from SvenMichaelKlose/master
vic-asm.cfg: Fix size of MAIN to end at $1E00.
2024-03-09 12:00:42 +01:00
Sven Michael Klose 1fe12f112e
Merge branch 'cc65:master' into master 2024-03-08 17:41:06 +01:00
Sven Michael Klose a887b29ffb Revert "Test strtok()."
This reverts commit 3a7bd53956.
2024-03-05 07:04:59 +01:00
acqn 731f349b24 Removed ParamTypeCvt(). 2024-02-29 18:24:22 +08:00
acqn 98767741ce Reorganized stuff in src/cc65/declare.c. 2024-02-29 18:24:22 +08:00
acqn 9b2d27d1e1 Fixed the error recovery integer type used for bit-fields. 2024-02-29 18:23:04 +08:00
acqn 23aa562094 Fixed potential errors with subtraction evaluation of identifiers at different memory locations. 2024-02-24 15:34:38 +08:00
Bob Andrews 5c3ff714ae
Merge pull request #2415 from polluks/patch-13
[grc65] Fixed segv of empty resource file
2024-02-23 16:16:46 +01:00
Colin Leroy-Mira 86317711e0 IIgs SCC: Rework branches to X-indexed variables
and general cleanup/commenting
2024-02-23 01:20:47 +01:00
Colin Leroy-Mira 8b71fafb84 IIgs SCC: Allow choosing 115200bps as the card allows it
Of course, that won't work full speed with the standard
IRQ-based RX. But that will allow users to setup the port
at this speed without duplicating the setup part of the
code. Up to them to add hooks to disable IRQs and read
directly in a tight asm loop.
2024-02-23 01:20:47 +01:00
Colin Leroy-Mira 3fd78208ba Disable IRQ if opening at 115200 bps 2024-02-19 19:31:47 +01:00
Colin Leroy-Mira 7a12399b39 Allow choosing 115200bps as the card allows it
Of course, that won't work full speed with the
standard IRQ-based RX. But that will allow users
to setup the port at this speed without duplicating
the setup part of the code. Up to them to add hooks
to disable IRQs and read directly in a tight asm
loop.
2024-02-19 19:31:47 +01:00
Sven Michael Klose 294b034920 Add configuration files for expanded VICs. 2024-02-15 17:32:44 +01:00
Stefan ab0eb4fe58
oops 2024-02-15 09:03:46 +01:00
Stefan 8d4946b3f4
Fixed segv
touch /tmp/xx
grc65 /tmp/xx
2024-02-15 07:52:42 +01:00
Sven Michael Klose 3a7bd53956 Test strtok(). 2024-02-15 01:05:35 +01:00
Sven Michael Klose 8173c850fd Fix size of MAIN to end at $1E00.
Caused negative size of MAIN in cc65-contrib/quikmans2k8.
2024-02-15 00:00:46 +01:00
Bob Andrews 4bde3afd80
Merge pull request #2410 from alexthissen/serial
Improvements and fixes in serial support for Atari Lynx
2024-02-12 12:50:02 +01:00
Alex Thissen 7d6f3d24d4 Changed sta (ptr1,x) to sta (ptr1)
Reset serial status on ser_close
Fixed error for saving serial state
2024-02-11 23:12:27 +00:00
Alex Thissen 8b172e05bc Applied optimization as per review 42Bastian 2024-02-11 20:59:08 +00:00
Alex Thissen 1deb9e52ae Replaced last literal value for SERCTL 2024-02-11 15:46:23 +00:00
Alex Thissen acff429eb8 Added redeye check for SER_HS_SW handshake 2024-02-11 15:33:22 +00:00
Alex Thissen 6cf8ee8eb5 Removed baud rates from 150 and lower.
Fixed tab
Replaced uploader references to SERIAL_INTERRUPT
2024-02-10 23:19:05 +00:00
Alex Thissen 65bce9ecde Implemented mark and space checks. 2024-02-10 23:19:04 +00:00
Alex Thissen 014f85f226 Fixed baud rates 2024-02-10 23:19:04 +00:00
Alex Thissen 788ae82d30 Fixes to serial driver implementation 2024-02-10 23:19:02 +00:00
Carlo Bramini b04d79b1da [SIM65] Support undocumented opcodes for 6502
This PR is mostly a complete rewrite of the emulator for 6502/65c02 opcodes.
It provides an easier to maintain implementation of the instructions, by using few macros rather than having hand-written code for each function.
All undocumented, previously missing opcodes for 6502 are also implemented.
The patch also includes a detailed documentation of those opcodes, for reference to developers.
This PR should fix one of the milestones listed here for the next version of CC65:

https://github.com/cc65/wiki/wiki/Before-the-next-release
2024-02-08 12:13:17 +01:00
mrdudz 3dfe033000 update actions/upload-artifact@v3->actions/upload-artifact@v4, actions/cache@v3->actions/cache@v4 2024-02-03 17:02:08 +01:00
mrdudz 5acfb02794 update actions/checkout@v3 -> actions/checkout@v4 and microsoft/setup-msbuild@v1.1 -> microsoft/setup-msbuild@v2. lets see what happens :) 2024-02-03 16:20:17 +01:00
mrdudz 934de685bc this is pr #2194 - removed ramfont.o 2024-02-03 01:34:21 +01:00
Bob Andrews ce14f0f8ad
Merge pull request #2401 from colinleroy/enabled-windows-tests-on-PR
Enable Windows tests on pull requests
2024-02-02 21:59:09 +01:00
Bob Andrews a06431a8f9
Merge pull request #2402 from colinleroy/a-bit-of-65c02-optimisations
a BIT of 65C02 optimisations
2024-02-02 21:58:04 +01:00
Bob Andrews eb503cc542
Merge pull request #2390 from colinleroy/implement-shifts-by-7
Implement aslax7/shlax7/asrax7/shrax7
2024-02-02 20:17:48 +01:00
Colin Leroy-Mira 1fab179cb4 a BIT of 65C02 optimisations
Use BIT immediate instead of AND when reloading A is required
afterwards.
Add an fread unit test as the optimisation touches fread.
Sprinkle a few zero page indexed while we're at it.
2024-02-02 19:45:49 +01:00
Colin Leroy-Mira c4c6967e4a Enable Windows tests on pull requests 2024-02-02 19:45:17 +01:00
Bob Andrews 2a03e5d8c9
Merge pull request #2392 from colinleroy/asm-fputc-fputs
Asm fputc fputs
2024-02-02 19:41:23 +01:00
Bob Andrews 128f261c3a
Merge pull request #2389 from colinleroy/fix-2388
Fix #2388
2024-02-02 18:25:39 +01:00
Bob Andrews d5c84e7828
Merge pull request #2398 from acqn/OptFix
[cc65] Fixed optimization for char-size bitwise XOR/OR/AND when the rhs operand is complicated
2024-02-02 17:20:31 +01:00
Bob Andrews 54b423a99e
fix test 2024-02-02 13:13:57 +01:00
acqn 96d55e3703 Fixed optimization for char-size bitwise XOR/OR/AND when the rhs operand is complicated. 2024-02-02 19:00:33 +08:00
Bob Andrews a7ac9b7ef2
Merge pull request #2397 from colinleroy/bug-2395-test
Add test case for issue #2395
2024-02-01 23:09:12 +01:00
Colin Leroy-Mira 1e300bf768 Add test case for issue #2395 2024-02-01 22:06:56 +01:00
Colin Leroy-Mira ce606bb19e Fix tests... 2024-01-31 08:40:36 +01:00
Colin Leroy-Mira afd8ee627e Remove useless branching code in fgets 2024-01-30 19:52:48 +01:00
Colin Leroy-Mira 2b97735d5d Factorize file pointer check 2024-01-30 19:40:28 +01:00
Colin Leroy-Mira 1a5a7d67a7 Rewrite fputc in assembly
-36 bytes, -12% cycles
2024-01-30 17:19:13 +01:00
Colin Leroy-Mira ba36071022 Rewrite fputs in assembly
-28 bytes, -1% cycles
2024-01-30 17:12:52 +01:00
Colin Leroy-Mira 7594af553a Fix #2388
Reopen stdin in binary mode instead of closing/opening
2024-01-30 09:39:44 +01:00
Colin Leroy-Mira 7d7cf2d1e0 Implement aslax7/shlax7/asrax7/shrax7 2024-01-29 07:59:11 +01:00
Bob Andrews 51b946bf25
Merge pull request #2387 from colinleroy/sim65-implement-remove
Implement __sysremove for sim65
2024-01-28 16:53:29 +01:00
Colin Leroy-Mira 0dd7b0c3a5 Implement __sysremove for sim65
This will allow using unlink()/remove() in sim65 programs
Use it to unlink fgets' test output file
2024-01-28 13:58:57 +01:00
Bob Andrews 8682095f9f
Merge pull request #2384 from colinleroy/asm-realloc
Rewrite realloc in asm
2024-01-27 00:28:17 +01:00
Bob Andrews 782dad23da
Merge pull request #2382 from colinleroy/asm-gets
Rewrite gets in asm
2024-01-27 00:26:12 +01:00
Colin Leroy-Mira aa6f850b8d Rewrite gets in assembler
+19 bytes if used alone, because it pulls in fgets, but as code is
factorized, -128 bytes in programs using both fgets and gets.
2024-01-26 20:29:17 +01:00
Colin Leroy-Mira a8b870555e Rewrite realloc in asm
-80 bytes, -39% cycles
2024-01-26 20:25:59 +01:00
Bob Andrews 65937684a0
Merge pull request #2380 from colinleroy/asm-fgetc
Rewrite fgetc in asm
2024-01-26 20:12:41 +01:00
Bob Andrews ba6f9f5d3f
Merge pull request #2381 from colinleroy/asm-fgets
Rewrite fgets in asm
2024-01-26 19:36:57 +01:00
Bob Andrews 4b9bf9bb98
Merge pull request #2386 from polluks/patch-12
Added link for your interest
2024-01-25 14:36:51 +01:00
Stefan f1d95f1f07
Added link for your interest 2024-01-25 11:27:54 +01:00
Colin Leroy-Mira 476591e8b7 Rewrite fgetc in asm
-82 bytes, -20% cycles
2024-01-25 09:13:39 +01:00
Colin Leroy-Mira f7388cfb79 add fgets/fgetc test 2024-01-25 09:13:35 +01:00
Bob Andrews ee3a542539
Merge pull request #2383 from colinleroy/pmemalign-size-opt
Optimize -36 bytes out of posix_memalign
2024-01-24 21:26:50 +01:00
Bob Andrews a2d722639f
Merge pull request #2385 from polluks/master
Fixed comment
2024-01-24 21:17:19 +01:00
Bob Andrews 9ba270d97b
Merge pull request #2378 from colinleroy/fix-overflow-in-malloc-and-realloc
Fix malloc and realloc overflow
2024-01-24 21:15:31 +01:00
Stefan 34f37c873e
Fixed comment 2024-01-24 16:32:45 +01:00
Bob Andrews ebf43ddb05
Merge pull request #2379 from colinleroy/add-return-minus-1-helper
add a return -1 helper
2024-01-24 15:53:19 +01:00
Colin Leroy-Mira f0b5b02966 Swap in LC before destructors, ROM after 2024-01-24 12:28:57 +01:00
Colin Leroy-Mira b87df9e1c6 Optimize -36 bytes out of posix_memalign
And add a unit test
2024-01-24 10:23:53 +01:00
Colin Leroy-Mira 1f820d0ae8 Rewrite fgets in asm
-104 bytes, -1% cycles
2024-01-24 10:16:26 +01:00
Colin Leroy-Mira 5d49fde788 add a return -1 helper 2024-01-24 09:58:09 +01:00
Colin Leroy-Mira 3e01ac9b04 Fix malloc and realloc overflow
If user requests a size >= 65532, adding the heap admin size
overflows size. Fixes #2358.
2024-01-24 09:54:54 +01:00
Bob Andrews 57e65a6bf6
Merge pull request #2348 from colinleroy/time-functions-pass-2
Convert more time functions to asm
2024-01-23 23:45:10 +01:00
Bob Andrews 13ddd734db
Add note about contacting the devs when starting to work on huge patches 2024-01-23 23:26:26 +01:00
Colin Leroy-Mira 2ba176372e Add beep for apple2 2024-01-23 23:04:50 +01:00
Bob Andrews 6c7106c9d9
Merge pull request #2377 from acqn/Diagnostics
[cc65] Diagnosis improvements
2024-01-23 22:16:35 +01:00
Bob Andrews ea83b9fa53
Merge pull request #2347 from acqn/SrcFile
[cc65] fixes and enhancements for source file info in diagnosis and debug output
2024-01-23 22:15:31 +01:00
acqn ba75a2ac26 Added missing checks for forward declarations of the main() function.
More accurate diagnosis on implicit 'int' type specifiers.
2024-01-23 14:33:05 +08:00
Bob Andrews bea2e86210
Merge pull request #2354 from acqn/Diagnostics
[cc65] Improved diagnosis
2024-01-22 19:09:51 +01:00
Bob Andrews 998dfd6fa7
Merge pull request #2370 from acqn/VisibilityFix
[cc65] Fixed visibility of undeclared functions and objects
2024-01-22 18:31:47 +01:00
Bob Andrews deaf27d6a8
Merge pull request #2372 from acqn/C99Inline
[cc65] Added primitive support for the ISO C99 inline feature as well as the __inline__ extension
2024-01-22 17:30:09 +01:00
Colin Leroy-Mira 01ee903cdf Fixup gmtime/localtime/mktime tests with all cases 2024-01-22 16:38:39 +01:00
Bob Andrews 7a7e98d799
Merge pull request #2371 from alexthissen/lynx-upload
Lynx upload fixes for IRQ and configuration
2024-01-22 15:50:40 +01:00
Bob Andrews 6a03fda453
Merge pull request #2374 from colinleroy/save-two-bytes
Save two cycles in pushax and popptr1
2024-01-22 15:48:49 +01:00
Colin Leroy-Mira b23a7ec407 Save two bytes in pushax and popptr1
It's not because Y must equal zero on rts that we should'nt spare one byte
and one cycle.
2024-01-19 21:14:47 +01:00
Alex Thissen 83691f30c1 Missed a tab in config 2024-01-19 10:52:42 +00:00
Alex Thissen 6bab3f921b
Merge branch 'cc65:master' into lynx-upload 2024-01-19 09:49:20 +01:00
Alex Thissen ad90a3a421 Replaced references to __BLOCKSIZE__ with __BANK0BLOCKSIZE__ 2024-01-18 18:57:57 +00:00
Bob Andrews a173428fab
Merge pull request #2367 from acqn/PragmaFix
[cc65] Fixed segname pragmas right after a function definition
2024-01-18 18:44:39 +01:00
Alex Thissen 2e56dcc521 Fix for mising import 2024-01-18 18:13:39 +01:00
Alex Thissen acce24fedc Switched to __BANK0BLOCKSIZE__ instead of __BLOCKSIZE__ to make current lynx config files work 2024-01-18 18:13:02 +01:00
Alex Thissen 93f9cb6e48 Adjusted uploader configuration. Split into two MEMORY areas, so it can be just below video memory. 2024-01-18 18:06:10 +01:00
Alex Thissen d906748691 Fix uploader implementation to reset IRQ bit for timer 4 (serial) interrupt 2024-01-18 17:37:09 +01:00
Colin Leroy-Mira 166a4b25f7 Apple2: implement sleep using MONWAIT
Also publish detect_iigs(), set_iigs_speed() and get_iigs_speed(). Refactor to only store one ostype variable.
2024-01-18 16:17:10 +01:00
acqn 9471e128b5 Fixed segname pragmas right after a function definition. 2024-01-18 20:59:46 +08:00
Colin Leroy-Mira 10282a9b74 Rewrite asctime() in assembler (-7 bytes) 2024-01-18 09:09:38 +01:00
Colin Leroy-Mira 03d5e5fba0 Rewrite mktime in assembly
-415 bytes,
-39% cycles,
Unit test expanded to cover more cases (there was a bug in 2100 before!)
2024-01-18 09:09:38 +01:00
Colin Leroy-Mira 348a9048b7 Convert _time_t_to_tm to asm
46 bytes size gain, -8% cycles on the unit tests
2024-01-18 09:09:31 +01:00
Bob Andrews 92ee03f9e9
Merge pull request #2362 from colinleroy/fix-2357-bis
Add test case for bug #2357
2024-01-16 21:08:38 +01:00
Colin Leroy-Mira 0c53e7e0da Add test case for bug #2357 2024-01-16 20:55:48 +01:00
Bob Andrews 5e267ccfca
Merge pull request #2361 from colinleroy/fix-2357-bis
Cleaner instruction updating for long opt
2024-01-16 20:26:05 +01:00
Colin Leroy-Mira db8ac355cb Cleaner updating of instructions 2024-01-16 09:33:33 +01:00
Colin Leroy-Mira dec65176f0 Fix #2357 - Copy est.size and flags of op when moving it 2024-01-16 08:45:20 +01:00
Bob Andrews 43c2239e94
Merge pull request #2360 from cc65/revert-2359-fix-2357
Revert "Fix #2357 - Copy est.size and flags of op when moving it"
2024-01-15 23:04:35 +01:00
Bob Andrews 2c4ebe812c
Revert "Fix #2357 - Copy est.size and flags of op when moving it" 2024-01-15 23:03:13 +01:00
Bob Andrews 8e25a7b376
Merge pull request #2359 from colinleroy/fix-2357
Fix #2357 - Copy est.size and flags of op when moving it
2024-01-15 23:00:09 +01:00
Colin Leroy-Mira b388ca0236 Fix #2357 - Copy est.size and flags of op when moving it 2024-01-15 21:51:17 +01:00
acqn e9bd9330c0 Added warning on some code patterns of faulty attempt to declare anonymous structs/unions.
Removed unnecessary warning on tagless enum/struct/unions that would be invisible out of a function declaration.
2024-01-15 23:56:42 +08:00
acqn 07e349c517 Skipped anonymous tag names in diagnosis on empty structs/unions. 2024-01-15 23:56:39 +08:00
acqn afdf398a0b Fixed repeated diagnosis when reading EOF in certain cases. 2024-01-15 23:56:11 +08:00
acqn de3087a7e9 Removed the extra "unused parameter" warning when the parameter had an duplicated identifier error. 2024-01-14 00:19:11 +08:00
acqn 0b06c34dfc Added primitive support for the ISO C99 inline feature as well as the __inline__ extension.
No inlining is actually done but that part is not required by the standard.
2024-01-14 00:08:41 +08:00
acqn 7e80e55b6d Added a warning on implicit int in typedefs. 2024-01-13 16:40:44 +08:00
acqn 3d0dc58153 Fixed visibility of undeclared functions and objects. 2024-01-13 00:46:14 +08:00
Bob Andrews 8c329dfd1a
Merge pull request #2344 from acqn/Cleanup
[cc65] Cleanup for symbol types and flags
2024-01-12 16:02:08 +01:00
Bob Andrews 0f7d2dd818
Merge pull request #2351 from groessler/something_to_pull
mention John Dunning as original author
2024-01-11 19:46:16 +01:00
Christian Groessler 6ab3c0c75f elaborate more about Uz's contributions 2024-01-11 19:40:41 +01:00
Christian Groessler 44b2e48e3e mention John Dunning as original author 2024-01-11 17:41:17 +01:00
Bob Andrews 28f892bb3c
Merge pull request #2345 from acqn/PtrFix
[cc65] Fixed regression on comparison to null pointer
2024-01-11 16:50:49 +01:00
Bob Andrews 17c2622382
Merge pull request #2346 from acqn/Diagnostics
[cc65] Diagnosis fixes
2024-01-11 16:49:36 +01:00
acqn 38dac907e8 Cleanup for symbol types and flags. 2024-01-10 04:51:59 +08:00
acqn 2682fc0b79 Fixed regression on comparison to null pointer. 2024-01-10 04:51:20 +08:00
acqn 8e43c4706f Added hierarchy info about source file inclusion in diagnostic output.
Fixed presumed names of source files in disgnosis.
Fixed line number of source files in debug output.
2024-01-10 04:50:42 +08:00
acqn 94dfc08c0e Fixed false "Non constant initializers" error messages on wrong places, which could be resulted from failed array declarations etc. 2024-01-10 04:43:50 +08:00
acqn 2564aaa12c Refix for diagnosis on expected expressions. 2024-01-10 04:48:27 +08:00
Bob Andrews 8aa59e4af3
Merge pull request #2325 from acqn/Cleanup
[cc65] Cleanups
2024-01-08 23:02:40 +01:00
Bob Andrews 773ed23cea
Merge pull request #2326 from acqn/Diagnostics
[cc65] Diagnostics
2024-01-08 22:45:44 +01:00
Bob Andrews 2127778239
Merge pull request #2336 from colinleroy/optimize-strdup
Optimize strdup
2024-01-08 22:13:43 +01:00
Bob Andrews e1065d0c89
Merge pull request #2342 from colinleroy/rework-mktime
Rework time functions a bit
2024-01-08 22:13:05 +01:00
Bob Andrews 1e3b063b4a
Merge pull request #2320 from pm100/cl65_type
bug 2319 - dont allow -t after input files given
2024-01-08 21:59:21 +01:00
Bob Andrews a71865f6ec
Merge pull request #2331 from acqn/FuncDeclFix
[cc65] Fixed calling convention parsing in type names and function parameter types
2024-01-08 21:58:01 +01:00
Bob Andrews fa7dca5fa3
Merge pull request #2338 from colinleroy/fix-2237-keep-time-h-standard
Remove non-standard (and useless) include
2024-01-08 21:52:40 +01:00
Colin Leroy-Mira df193c0947 Rework time functions a bit
- mktime: Work unsigned as time_t's type implies (shifting Y2K38 bug to 2106)
- mktime: Add unit tests
- gmtime/localtime: factorize
- gmtime/localtime: Add unit tests
- mktime/gmtime/localtime: Size optimisation (-130 bytes wrt master)
- mktime: Speed optimisation (from 23M cycles on the unit test to 2M)
2024-01-08 18:24:13 +01:00
Colin Leroy-Mira 3a439e0e1b Little strdup optimisation
-12 bytes on disk
-20 cycles per strdup
-6 cycles per strlen called from strdup
2024-01-07 14:25:06 +01:00
Colin Leroy-Mira 7ce982cc68 Remove non-standard (and useless) include
Fixes #2337
2024-01-07 10:21:05 +01:00
mrdudz 29801a2fde remove extra format specifier, fixed #2330 2024-01-06 17:53:24 +01:00
Bob Andrews 82f01af6ec
Merge pull request #2333 from polluks/patch-11
Update README.md for new target
2024-01-06 17:41:39 +01:00
Bob Andrews c379d03dfb
Merge pull request #2332 from polluks/patch-10
Clean-up
2024-01-06 17:40:58 +01:00
Colin Leroy-Mira 169c9c0da0 Add strdup tests 2024-01-05 22:26:06 +01:00
Bob Andrews 1b5371b42d
Merge pull request #2335 from jedeoric/master
Add routine identifier for Telestrat target
2024-01-05 11:07:16 +01:00
jedeoric bcea5dfa8f
fix comment telestrat 2024-01-05 00:46:15 +01:00
jedeoric 726b70a534
add XMAINARGS and XGETARGV for Telestrat 2024-01-05 00:45:03 +01:00
Stefan dc9d2f0dbd
Update README.md 2024-01-03 16:46:07 +01:00
Stefan 075ece5faf
Clean-up
void is always fast
2024-01-03 16:35:12 +01:00
Colin Leroy-Mira 75461e1319 Apple2: implement stat(2) and statvfs(3) 2024-01-01 19:12:51 +01:00
acqn 7aab84628d Fixed calling convention parsing in type names and function parameter types. 2024-01-01 16:11:30 +08:00
acqn acbd87b576 Renamed GetUnqualTypeCode() to GetUnderlyingTypeCode() for consistency with GetUnderlyingType(). 2024-01-01 15:27:57 +08:00
acqn 88246f852d Removed RefineFuncDesc() as an unnecessary wrapper. 2024-01-01 15:04:50 +08:00
acqn 4e820677ee ED_AddrExpr() and ED_IndExpr() need no return values. 2024-01-01 15:03:45 +08:00
acqn 0b7d9d8216 Fixed missing calling convention and address size qualifiers in diagnosis on function types. 2024-01-01 14:48:05 +08:00
acqn f734f43a35 Removed extra 'const' qualifier in array-to-pointer and function-to-pointer conversions. 2024-01-01 14:48:05 +08:00
acqn f3199e4308 Fixed type name output with K&R-style functions. 2024-01-01 14:48:03 +08:00
Bob Andrews 4343eebe67
Merge pull request #2314 from acqn/PPFix
[cc65] Separated C preprocessor errors from other errors
2023-12-31 19:16:44 +01:00
Bob Andrews 9e3d1e1027
Merge pull request #2309 from acqn/Diagnostics
[cc65] Added warning on static functions that are used but not defined
2023-12-31 19:15:48 +01:00
paul moore c262929a62 doc cl65 change 2023-12-31 10:14:53 -08:00
Bob Andrews 0ece9449d7
Merge pull request #2307 from acqn/FuncDeclFix
[cc65] Fixed function declarator parser when a parameter has a function type
2023-12-31 19:11:25 +01:00
Bob Andrews 7297d2c8b6
Merge pull request #2310 from pm100/vs64
second try at fixing win64 build
2023-12-31 18:54:23 +01:00
Bob Andrews d0903ba225
Merge pull request #2311 from bbbradsmith/ca65-struct-doc-clarify
ca65 struct and union documentation improvement and feature testing.
2023-12-31 18:51:09 +01:00
Bob Andrews 98b9814692
Merge pull request #2318 from alexthissen/lynxincludes
Added SPRCTL0 and SPRCTL1  bit definitions for ca65
2023-12-31 18:46:49 +01:00
paul moore 096bd0b633 bug 2319 2023-12-29 17:02:45 -08:00
Alex Thissen 66e354961c Missed some tabs 2023-12-29 22:48:36 +01:00
Alex Thissen 061d907a11 Fixed tabs instead of spaces 2023-12-29 22:46:15 +01:00
Alex Thissen e5f9def572 Added SPRCTL0 and SPRCTL1 bit definitions for ca65 2023-12-29 22:37:18 +01:00
acqn b876a6b213 Fixed cc65 exitcode when there are only preprocessor errors. 2023-12-19 19:30:50 +08:00
acqn cd7c688dff Separated C preprocessor errors from other errors. 2023-12-18 15:30:53 +08:00
bbbradsmith 9892c8f6c4 using less generic names for the example to avoid confusion, adding cautionary example for what I think is the most error prone case 2023-12-17 05:40:00 -05:00
bbbradsmith 302c4f7409 clarify offsets of anonymous nested scope, missing quotes for names 2023-12-17 05:01:06 -05:00
bbbradsmith 0ff1b20f2a nested struct example needs a .tag 2023-12-16 19:52:57 -05:00
bbbradsmith f6838be162 missing <tt> 2023-12-16 19:32:52 -05:00
bbbradsmith 6cb8717c24 fix dangling space, mention .union in test comment 2023-12-16 19:25:21 -05:00
bbbradsmith 0d74b84ce4 Test of .struct and .union features. Update documentation with more examples, better clarity, and fixes to incorrect data. 2023-12-16 19:18:25 -05:00
paul moore 103d4b82c5 more msbuild syntax fixes 2023-12-14 14:43:58 -08:00
paul moore 269786a5ae fix msbuild syntax 2023-12-14 14:38:24 -08:00
paul moore 08341aae30 second try at fixing win64 build 2023-12-14 14:25:35 -08:00
Colin Leroy-Mira 1093d169ad Fix BSS obliteration by mliparam during exec().
Using mliparam at this time could lead to corruption at the
start of the new executed program if BSS is real full and
mliparam is over $BB00.
The fix is to open the file from the loader stub instead of doing
it before the C library shutdown.
2023-12-14 16:47:33 +01:00
acqn a5746227dc Added warning on static functions that are used but not defined. 2023-12-14 21:27:48 +08:00
acqn 1e4d1b4311 Fixed function declarator parser when a parameter has a function type.
Ensured check on parameter lists without types in non-definition declarations.
2023-12-14 02:34:03 +08:00
Bob Andrews 05aae60816
Merge pull request #2305 from acqn/FuncDeclFix
[cc65] Fixed missing diagnosis on function parameter lists with trailing commas
2023-12-13 19:17:59 +01:00
acqn f8fe1d1560 Fixed missing diagnosis on function parameter lists with trailing commas. 2023-12-13 22:57:32 +08:00
Bob Andrews bc97bce8c1
Merge pull request #2297 from acqn/WrappedCall
[cc65] Fixed wrapped call when the function was defined before its later declaration gets wrapped with the pragma
2023-12-12 17:11:47 +01:00
Bob Andrews e90e7f46de
Merge pull request #2298 from acqn/Diagnostics
[cc65] More accurate diagnostic messages on empty declarations without any type specifiers
2023-12-12 17:06:54 +01:00
mrdudz b1c1502494 MS compiler insists on those typecasts apparently 2023-12-11 00:35:07 +01:00
mrdudz 9985ee7f61 fix %hhn and %hn in the internal xvsnprintf function 2023-12-11 00:18:40 +01:00
mrdudz 6b855d562a use -std=gnu17 for the references, so the test bench will not break with GCC 14. see #2277 2023-12-10 23:18:55 +01:00
mrdudz 0b077f561f exclude test directory from some style checks - it makes no sense to enforce these things in the test bench, we need to be able to test all kinds of spaces and tabs :) 2023-12-10 22:43:47 +01:00
Bob Andrews cc5e9c38ca
Merge pull request #2296 from acqn/Diagnostics
[cc65] Fixed and improved diagnostics regarding type names and declarations
2023-12-10 22:32:33 +01:00
mrdudz b31a1c7c0c test for regression that occured after #2262 2023-12-10 22:18:59 +01:00
Bob Andrews 9634cc4d1e
Merge pull request #2295 from colinleroy/fix-2262-too-eager-opt
Fix #2262: Make sure there's no branching after the sequence
2023-12-10 19:16:38 +01:00
acqn befc9533c6 More accurate diagnostic messages on empty declarations without any type specifiers. 2023-12-10 20:21:50 +08:00
acqn bbd542fac7 Fixed missing diagnosis on extra identifiers in type names. 2023-12-10 17:01:54 +08:00
Colin Leroy-Mira 07c71541f4 Fix #2262: Make sure there's no branching after the sequence
Also better check that arguments match
2023-12-10 09:45:15 +01:00
acqn 3215d377ea More accurate diagnostic messages on wrong missing declaration specifiers. 2023-12-10 15:46:48 +08:00
acqn cadf8012f6 Improved error recovery with type cast and sizeof. 2023-12-10 15:43:24 +08:00
acqn a1a060c291 Declaration specifier flags cleanup. 2023-12-10 15:43:24 +08:00
acqn 79b4690077 Fixed missing diagnostics on empty enum/struct/union declareations without tag names.
Improved error recovery with local declarations and _Static_assert.
2023-12-10 15:43:24 +08:00
Bob Andrews a16a6298e2
Merge pull request #2287 from acqn/Diagnostics
[cc65] Minor diagnostics improvements
2023-12-09 22:16:47 +01:00
Bob Andrews 92f869cdfb
Merge pull request #2288 from acqn/TypeFix
[cc65] Fixed an iteration bug in type composition
2023-12-09 22:15:24 +01:00
Bob Andrews a956f6f9ed
Merge pull request #2289 from acqn/FuncDeclFix
[cc65] Fixed the issue that qualifiers of pointees of function parameters were ignored for type compatibility check
2023-12-09 22:14:41 +01:00
Bob Andrews 9e19a2e6a3
Merge pull request #2290 from acqn/TestFix
Updated test/misc/Makefile
2023-12-09 22:12:59 +01:00
Bob Andrews d805211002
Merge pull request #2291 from colinleroy/fix-256-minus-1
Fix bug introduced in #2260
2023-12-09 22:11:33 +01:00
acqn b66682a05b Fixed wrapped call when the function to wrap has already got defined before it is wrapped with the pragma. 2023-12-10 00:47:10 +08:00
Colin Leroy-Mira 2a2cc6cad6 Fix bug introduced in #2260
bne should have applied to A, not X, but adding a cmp #$00 before
makes the change less optimized than the existing.
2023-12-09 16:43:23 +01:00
acqn d8e61552be Removed outdated testcases no longer in the directory from test/misc/Makefile. 2023-12-09 18:04:29 +08:00
acqn d8a722b638 Improved diagnostics on multiple definition of struct/union types. 2023-12-09 17:34:01 +08:00
acqn 87f8893886 Avoided "Variable 'XXX' is defined but never used" error message resulted from an earlier error. 2023-12-09 17:33:46 +08:00
acqn 98ffc031d1 Fixed an iteration bug in type composition. 2023-12-09 14:35:00 +08:00
acqn b7e7bb7489 Fixed the issue that qualifiers of pointees of function parameters were ignored for type compatibility check. 2023-12-09 14:34:37 +08:00
Bob Andrews 519a52d92c
Merge pull request #2209 from vrubleg/linecont
ca65: `.LINECONT` as a part of `.FEATURE`
2023-12-08 02:10:45 +01:00
Bob Andrews 66bfc31988
Merge pull request #2262 from colinleroy/optimize-long-assign
Optimize static long assignment a bit
2023-12-08 01:58:01 +01:00
Bob Andrews 09735b26c5
Merge pull request #2274 from acqn/UnionFix
[cc65] Fixed initialization of union when it has an anonymous bit-field as the first member declaration
2023-12-08 01:55:06 +01:00
Bob Andrews c4575ec2c4
Merge pull request #2275 from acqn/BitfieldFix
[cc65] Fixed constness of bit-fields
2023-12-08 01:54:02 +01:00
Bob Andrews 85a15007ec
Merge pull request #2276 from acqn/Diagnostics
[cc65] Fixed diagnostics
2023-12-08 01:53:08 +01:00
Colin Leroy-Mira 63861766e1 Fix Makefile change 2023-12-01 14:22:30 +01:00
Colin Leroy-Mira d8a3938f2b Optimize a bit static long assignation 2023-12-01 14:20:00 +01:00
acqn 47e7ed2f56 Fixed wrong "Mixed declarations and code are not supported in cc65" error message when it should be "Expression expected". 2023-11-30 00:36:13 +08:00
acqn c0a2021d9a Fixed endlessly repeated disgnostics when there are some certain patterns of syntax errors in a struct/union declaration. 2023-11-30 00:35:30 +08:00
acqn 6434176909 Fixed constness of bit-fields. 2023-11-29 12:27:01 +08:00
acqn 3b7af398a9 Fixed initialization of union when it has an anonymous bit-field as the first member declaration. 2023-11-15 21:32:24 +08:00
Evgeny Vrublevsky 850007cb44 Document line_continuations feature. 2023-10-05 08:28:37 +03:00
Evgeny Vrublevsky c8df241337 Add line_continuations feature that works as .LINECONT but in a consistent way with other features. 2023-10-05 08:28:37 +03:00
237 changed files with 13393 additions and 4506 deletions

View File

@ -5,7 +5,7 @@ CHECK_PATH=.
cd $SCRIPT_PATH/../../
FILES=`find $CHECK_PATH -type f \( -name \*.inc -o -name Makefile -o -name \*.cfg -o -name \*.\[chs\] -o -name \*.mac -o -name \*.asm -o -name \*.sgml \) -print | grep -v "libwrk/" | grep -v "testwrk/" | xargs grep -l ' $'`
FILES=`find $CHECK_PATH -type f \( -name \*.inc -o -name Makefile -o -name \*.cfg -o -name \*.\[chs\] -o -name \*.mac -o -name \*.asm -o -name \*.sgml \) -print | grep -v "test/" | grep -v "libwrk/" | grep -v "testwrk/" | xargs grep -l ' $'`
cd $OLDCWD

View File

@ -5,7 +5,7 @@ CHECK_PATH=.
cd $SCRIPT_PATH/../../
FILES=`find $CHECK_PATH -type f \( \( -name \*.inc -a \! -name Makefile.inc \) -o -name \*.cfg -o -name \*.\[chs\] -o -name \*.mac -o -name \*.asm -o -name \*.sgml \) -print | grep -v "libwrk/" | grep -v "testwrk/" | xargs grep -l $'\t'`
FILES=`find $CHECK_PATH -type f \( \( -name \*.inc -a \! -name Makefile.inc \) -o -name \*.cfg -o -name \*.\[chs\] -o -name \*.mac -o -name \*.asm -o -name \*.sgml \) -print | grep -v "test/" | grep -v "libwrk/" | grep -v "testwrk/" | xargs grep -l $'\t'`
cd $OLDCWD

View File

@ -19,7 +19,7 @@ jobs:
- shell: bash
run: git config --global core.autocrlf input
- name: Checkout Source
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Do some simple style checks
shell: bash
@ -44,7 +44,7 @@ jobs:
shell: bash
run: make -j2 doc
- name: Upload a documents snapshot.
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: docs
path: ./html
@ -54,7 +54,7 @@ jobs:
make -j2 bin USER_CFLAGS=-Werror CROSS_COMPILE=x86_64-w64-mingw32-
build_windows:
name: Build (Windows)
name: Build and Test (Windows)
runs-on: windows-latest
steps:
@ -62,13 +62,31 @@ jobs:
run: git config --global core.autocrlf input
- name: Checkout Source
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2
- name: Build app (debug)
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug
- name: Build app (x86 debug)
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug -property:Platform=Win32
- name: Build app (release)
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release
- name: Build app (x86 release)
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Release -property:Platform=Win32
- name: Build app (x64 release)
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug -property:Platform=x64
- name: Build app (x64 release)
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

View File

@ -18,10 +18,10 @@ jobs:
run: git config --global core.autocrlf input
- name: Checkout Source
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2
- name: Build app (debug)
run: msbuild src\cc65.sln -t:rebuild -property:Configuration=Debug
@ -44,7 +44,7 @@ jobs:
- shell: bash
run: git config --global core.autocrlf input
- name: Checkout Source
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Do some simple style checks
shell: bash
@ -86,18 +86,18 @@ jobs:
mv cc65.zip cc65-snapshot-win32.zip
- name: Upload a 32-bit Snapshot Zip
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: cc65-snapshot-win32
path: cc65-snapshot-win32.zip
- name: Upload a 64-bit Snapshot Zip
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: cc65-snapshot-win64
path: cc65-snapshot-win64.zip
- name: Get the online documents repo.
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: cc65/doc
# 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.
run: 7z a cc65-snapshot-docs.zip ./html/*.*
- name: Upload a Documents Snapshot Zip
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: cc65-snapshot-docs
path: cc65-snapshot-docs.zip

View File

@ -30,7 +30,7 @@ jobs:
run: mkdir ~/.cache-sha
- name: Cache SHA
uses: actions/cache@v3
uses: actions/cache@v4
id: check-sha
with:
path: ~/.cache-sha
@ -43,11 +43,11 @@ jobs:
- name: Checkout source
if: steps.check-sha.outputs.cache-hit != 'true'
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Add msbuild to PATH
if: steps.check-sha.outputs.cache-hit != 'true'
uses: microsoft/setup-msbuild@v1.1
uses: microsoft/setup-msbuild@v2
- name: Build app (MSVC debug)
if: steps.check-sha.outputs.cache-hit != 'true'

View File

@ -1,4 +1,6 @@
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.)

View File

@ -7,9 +7,13 @@ For details look at the [Website](https://cc65.github.io).
## People
Project founder:
Project founders:
* Ullrich von Bassewitz
* 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:
* move the code to modern systems
* rewrite most parts of the compiler
* complete rewrite of the runtime library
Core team members:
@ -28,6 +32,7 @@ External contributors:
* [Stephan Mühlstrasser](https://github.com/smuehlst): osic1p target
* [Wayne Parham](https://github.com/WayneParham): Sym-1 target
* [Dave Plummer](https://github.com/davepl): KIM-1 target
* [rumbledethumps](https://github.com/rumbledethumps): Picocomputer target
*(The above list is incomplete, if you feel left out - please speak up or add yourself in a PR)*

View File

@ -15,7 +15,7 @@ CPU_ISET_4510 = $0400
CPU_NONE = CPU_ISET_NONE
CPU_6502 = CPU_ISET_6502
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_65C02 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02
CPU_65816 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65816

View File

@ -81,8 +81,42 @@ MATHJ = $FC6F
; Suzy Misc
SPRCTL0 = $FC80
SPRCTL0 = $FC80
; Sprite bits-per-pixel definitions
BPP_MASK = %11000000 ; Mask for settings bits per pixel
BPP_1 = %00000000
BPP_2 = %01000000
BPP_3 = %10000000
BPP_4 = %11000000
; More sprite control 0 bit definitions
HFLIP = %00100000
VFLIP = %00010000
; Sprite types - redefined to reflect the reality caused by the shadow error
TYPE_SHADOW = %00000111
TYPE_XOR = %00000110
TYPE_NONCOLL = %00000101 ; Non-colliding
TYPE_NORMAL = %00000100
TYPE_BOUNDARY = %00000011
TYPE_BSHADOW = %00000010 ; Background shadow
TYPE_BACKNONCOLL = %00000001 ; Background non-colliding
TYPE_BACKGROUND = %00000000
SPRCTL1 = $FC81
LITERAL = %10000000
PACKED = %00000000
ALGO3 = %01000000 ; Broken, do not set this bit!
; Sprite reload mask definitions
RELOAD_MASK = %00110000
RENONE = %00000000 ; Reload nothing
REHV = %00010000 ; Reload hsize, vsize
REHVS = %00100000 ; Reload hsize, vsize, stretch
REHVST = %00110000 ; Reload hsize, vsize, stretch, tilt
; More sprite control 1 bit definitions
REUSEPAL = %00001000
SKIP = %00000100
DRAWUP = %00000010
DRAWLEFT = %00000001
SPRCOLL = $FC82
SPRINIT = $FC83
SUZYHREV = $FC88
@ -225,30 +259,44 @@ SND_INTERRUPT = TIMER7_INTERRUPT
INTRST = $FD80
INTSET = $FD81
MAGRDY0 = $FD84
MAGRDY1 = $FD85
AUDIN = $FD86
SYSCTL1 = $FD87
MIKEYHREV = $FD88
MIKEYSREV = $FD89
IODIR = $FD8A
IODAT = $FD8B
TxIntEnable = %10000000
RxIntEnable = %01000000
TxParEnable = %00010000
ResetErr = %00001000
TxOpenColl = %00000100
TxBreak = %00000010
ParEven = %00000001
TxReady = %10000000
RxReady = %01000000
TxEmpty = %00100000
RxParityErr = %00010000
RxOverrun = %00001000
RxFrameErr = %00000100
RxBreak = %00000010
ParityBit = %00000001
SERCTL = $FD8C
IODIR = $FD8A
IODAT = $FD8B
; IODIR and IODAT bit definitions
AUDIN_BIT = $10 ; Note that there is also the address AUDIN
READ_ENABLE = $10 ; Same bit for AUDIN_BIT
RESTLESS = $08
NOEXP = $04 ; If set, redeye is not connected
CART_ADDR_DATA = $02
CART_POWER_OFF = $02 ; Same bit for CART_ADDR_DATA
EXTERNAL_POWER = $01
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
SDONEACK = $FD90
CPUSLEEP = $FD91

64
asminc/stat.inc Normal file
View File

@ -0,0 +1,64 @@
;****************************************************************************
;* *
;* stat.inc *
;* *
;* Stat struct *
;* *
;* *
;* *
;*(C) 2023 Colin Leroy-Mira <colin@colino.net> *
;* *
;* *
;*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.inc"
;------------------------------------------------------------------------------
; st_mode values
S_IFDIR = $01
S_IFREG = $02
;------------------------------------------------------------------------------
; struct stat
.struct stat
st_dev .dword
st_ino .dword
st_mode .byte
st_nlink .dword
st_uid .byte
st_gid .byte
st_size .dword
st_atim .tag timespec
st_ctim .tag timespec
st_mtim .tag timespec
.ifdef __APPLE2__
st_access .byte
st_type .byte
st_auxtype .word
st_storagetype .byte
st_blocks .word
st_mod_date .word
st_mod_time .word
st_create_date .word
st_create_time .word
.endif
.endstruct

46
asminc/statvfs.inc Normal file
View File

@ -0,0 +1,46 @@
;****************************************************************************
;* *
;* statvfs.inc *
;* *
;* Statvfs struct *
;* *
;* *
;* *
;*(C) 2023 Colin Leroy-Mira <colin@colino.net> *
;* *
;* *
;*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. *
;* *
;****************************************************************************
;------------------------------------------------------------------------------
; struct statvfs
.struct statvfs
f_bsize .dword
f_frsize .dword
f_blocks .dword
f_bfree .dword
f_bavail .dword
f_files .dword
f_ffree .dword
f_favail .dword
f_fsid .dword
f_flag .dword
f_namemax .dword
.endstruct

View File

@ -257,8 +257,11 @@ XBINDX = $28 ; Convert a number into hex and displays on chan
XDECIM = $29
XHEXA = $2A ; Convert a number into hex
XMAINARGS = $2C ; Only available for Orix
XEDT = $2D ; Launch editor
XINSER = $2E
XGETARGV = $2E ; Only available for Orix
XSCELG = $2F ; Search a line in editor mode
XOPEN = $30 ; Only in Orix

41
cfg/kim1-mtu60k.cfg Normal file
View 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
View 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;
}

View File

@ -5,16 +5,17 @@ SYMBOLS {
__BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size
__EXEHDR__: type = import;
__BOOTLDR__: type = import;
__DEFDIR__: type = import;
__UPLOADER__: type = import;
__UPLOADERSIZE__: type = export, value = $61;
__HEADERSIZE__: type = export, value = 64;
}
MEMORY {
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__;
DIR: file = %O, start = $0000, size = 8;
MAIN: file = %O, define = yes, start = $0200, size = $BD38 - __STACKSIZE__;
UPLDR: file = %O, define = yes, start = $BFDC, size = $005C;
DIR: file = %O, start = $0000, size = 16;
MAIN: file = %O, define = yes, start = $0200, size = $C038 - __UPLOADERSIZE__ - $200 - __STACKSIZE__;
UPLOAD: file = %O, define = yes, start = $C038 - __UPLOADERSIZE__, size = $0061;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
@ -30,8 +31,8 @@ SEGMENTS {
RODATA: load = MAIN, type = ro, define = yes;
DATA: load = MAIN, type = rw, define = yes;
BSS: load = MAIN, type = bss, define = yes;
UPCODE: load = UPLDR, type = ro, define = yes;
UPDATA: load = UPLDR, type = rw, define = yes;
UPCODE: load = UPLOAD, type = ro, define = yes;
UPDATA: load = UPLOAD, type = rw, define = yes;
}
FEATURES {
CONDES: type = constructor,

21
cfg/vic20-asm-32k.cfg Normal file
View 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
View 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;
}

View File

@ -1,3 +1,5 @@
# Assembly program configuration for unexpanded VICs.
FEATURES {
STARTADDRESS: default = $1001;
}
@ -7,7 +9,7 @@ SYMBOLS {
MEMORY {
ZP: file = "", start = $0002, size = $001A, define = yes;
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 {
ZEROPAGE: load = ZP, type = zp, optional = yes;

View File

@ -62,7 +62,7 @@ Special locations:
</descrip><p>
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
generated code. However code is never automatically placed there. Rather code
@ -321,21 +321,39 @@ Programs containing Apple&nbsp;&rsqb;&lsqb; specific code may use the
<sect1>Apple&nbsp;&rsqb;&lsqb; specific functions<p>
The functions listed below are special for the Apple&nbsp;&rsqb;&lsqb;. See
the <url url="funcref.html" name="function reference"> for declaration and
The functions and variables listed below are special for the Apple&nbsp;&rsqb;&lsqb;.
See the <url url="funcref.html" name="function reference"> for declaration and
usage.
<itemize>
<item>_auxtype
<item>_dos_type
<item>_filetype
<item>_datetime
<item>beep
<item>get_ostype
<item>gmtime_dt
<item>mktime_dt
<item>rebootafterexit
<item>ser_apple2_slot
<item>tgi_apple2_mix
</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>
There's currently no support for direct hardware access. This does not mean
@ -434,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
aren't reachable because the ROM and ProDOS IRQ handlers are too slow.
Software flow control (XON/XOFF) is not supported.
Note that because of the peculiarities of the 6551 chip transmits are not
interrupt driven, and the transceiver blocks if the receiver asserts
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
<tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/
succeeds for all Apple&nbsp;II slots, but <tt/ser_open()/ fails with
@ -569,6 +592,28 @@ program. See the discussion of the <tt/.CONDES/ feature in the <url
url="ca65.html" name="assembler manual">.
<sect1>ProDOS date/time manipulation<p>
<descrip>
The readdir and stat function return ProDOS timestamps in their file
creation/modification time attributes. You can convert them to more portable
time representations using either:
<tag/struct tm/
<tt/struct tm* __fastcall__ gmtime_dt (const struct datetime* dt);/
Converts a <tt/struct datetime/ into a <tt/struct tm/. Returns NULL in case
of error and sets errno.
<tag/time_t/
<tt/time_t __fastcall__ mktime_dt (const struct datetime* dt);/
Parses a <tt/struct datetime/ and returns a UNIX timestamp. Returns 0 on error and
sets errno.
</descrip>
<sect1>DIO<p>
<descrip>
@ -630,6 +675,16 @@ url="ca65.html" name="assembler manual">.
that can be used to set these variables. It is included in
<tt/apple2.h/.
The global variable <tt/_datetime/ allows the file creation date/time
to be set before a call to <tt/fopen()/
or <tt/open()/ that creates the file. It is defined in <tt/apple2.h/:
<tscreen>
<verb>
extern struct datetime _datetime;
</verb>
</tscreen>
<tag>Example</tag>
A text file cannot be created with just the

View File

@ -63,7 +63,7 @@ Special locations:
</descrip><p>
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
generated code. However code is never automatically placed there. Rather code
@ -322,15 +322,19 @@ Programs containing enhanced&nbsp;Apple&nbsp;//e specific code may use the
<sect1>Enhanced&nbsp;Apple&nbsp;//e specific functions<p>
The functions listed below are special for the enhanced&nbsp;Apple&nbsp;//e. See
the <url url="funcref.html" name="function reference"> for declaration and
The functions and variables listed below are special for the Apple&nbsp;&rsqb;&lsqb;.
See the <url url="funcref.html" name="function reference"> for declaration and
usage.
<itemize>
<item>_auxtype
<item>_dos_type
<item>_filetype
<item>_datetime
<item>beep
<item>get_ostype
<item>gmtime_dt
<item>mktime_dt
<item>rebootafterexit
<item>ser_apple2_slot
<item>tgi_apple2_mix
@ -339,6 +343,20 @@ usage.
</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>
There's currently no support for direct hardware access. This does not mean
@ -435,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
aren't reachable because the ROM and ProDOS IRQ handlers are too slow.
Software flow control (XON/XOFF) is not supported.
Note that because of the peculiarities of the 6551 chip transmits are not
interrupt driven, and the transceiver blocks if the receiver asserts
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
<tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/
succeeds for all Apple&nbsp;II slots, but <tt/ser_open()/ fails with
@ -575,6 +598,28 @@ program. See the discussion of the <tt/.CONDES/ feature in the <url
url="ca65.html" name="assembler manual">.
<sect1>ProDOS date/time manipulation<p>
<descrip>
The readdir and stat function return ProDOS timestamps in their file
creation/modification time attributes. You can convert them to more portable
time representations using either:
<tag/struct tm/
<tt/struct tm* __fastcall__ gmtime_dt (const struct datetime* dt);/
Converts a <tt/struct datetime/ into a <tt/struct tm/. Returns -1 in case
of error and sets errno, 0 on success.
<tag/time_t/
<tt/time_t __fastcall__ mktime_dt (const struct datetime* dt);/
Parses a <tt/struct datetime/ and returns a UNIX timestamp. Returns 0 on error and
sets errno.
</descrip>
<sect1>DIO<p>
<descrip>
@ -619,7 +664,7 @@ url="ca65.html" name="assembler manual">.
auxiliary type. Therefore, some additional mechanism for specifying
the file types is needed.
<tag>Specifying the File Type and Auxiliary Type</tag>
<tag>Specifying the File Type, Auxiliary Type and creation date</tag>
There are two global variables provided that allow the file type
and auxiliary type to be specified before a call to <tt/fopen()/
@ -636,6 +681,16 @@ url="ca65.html" name="assembler manual">.
that can be used to set these variables. It is included in
<tt/apple2.h/, which is in turn included in <tt/apple2enh.h/.
The global variable <tt/_datetime/ allows the file creation date/time
to be set before a call to <tt/fopen()/
or <tt/open()/ that creates the file. It is defined in <tt/apple2.h/:
<tscreen>
<verb>
extern struct datetime _datetime;
</verb>
</tscreen>
<tag>Example</tag>
A text file cannot be created with just the

View File

@ -2871,6 +2871,26 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH
overridden. When using this feature, you may also get into trouble if
later versions of the assembler define new keywords starting with a dot.
<tag><tt>line_continuations</tt><label id="line_continuations"></tag>
Switch on or off line continuations using the backslash character
before a newline. The option is off by default.
Note: Line continuations do not work in a comment. A backslash at the
end of a comment is treated as part of the comment and does not trigger
line continuation.
Example:
<tscreen><verb>
.feature line_continuations + ; Allow line continuations
lda \
#$20 ; This is legal now
</verb></tscreen>
For backward compatibility reasons, the <tt>.LINECONT +</tt> control command
is also supported and enables the same feature.
<tag><tt>long_jsr_jmp_rts</tt><label id="long_jsr_jmp_rts"></tag>
Affects 65816 mode only.
@ -3375,26 +3395,6 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH
the feature in more detail.
<sect1><tt>.LINECONT</tt><label id=".LINECONT"><p>
Switch on or off line continuations using the backslash character
before a newline. The option is off by default.
Note: Line continuations do not work in a comment. A backslash at the
end of a comment is treated as part of the comment and does not trigger
line continuation.
The command can be followed by a '+' or '-' character to switch the
option on or off respectively.
Example:
<tscreen><verb>
.linecont + ; Allow line continuations
lda \
#$20 ; This is legal now
</verb></tscreen>
<sect1><tt>.LIST</tt><label id=".LIST"><p>
Enable output to the listing. The command can be followed by a boolean
@ -4090,7 +4090,9 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE"
<sect1><tt>.TAG</tt><label id=".TAG"><p>
Allocate space for a struct or union.
Allocate space for a struct or union. This is equivalent to
<tt><ref id=".RES" name=".RES"></tt> with the
<tt><ref id=".SIZEOF" name=".SIZEOF"></tt> of a struct.
Example:
@ -4104,6 +4106,7 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE"
.tag Point ; Allocate 4 bytes
</verb></tscreen>
See: <ref id="structs" name="&quot;Structs and unions&quot;">
<sect1><tt>.UNDEF, .UNDEFINE</tt><label id=".UNDEFINE"><p>
@ -4493,9 +4496,9 @@ different:
<item> Macros defined with <tt><ref id=".DEFINE" name=".DEFINE"></tt> may not
span more than a line. You may use line continuation (see <tt><ref
id=".LINECONT" name=".LINECONT"></tt>) to spread the definition over
more than one line for increased readability, but the macro itself
may not contain an end-of-line token.
id="line_continuations" name="line_continuations"></tt>) to spread the
definition over more than one line for increased readability, but the
macro itself may not contain an end-of-line token.
<item> Macros defined with <tt><ref id=".DEFINE" name=".DEFINE"></tt> share
the name space with classic macros, but they are detected and replaced
@ -4869,10 +4872,15 @@ compiler, depending on the target system selected:
Structs and unions are special forms of <ref id="scopes" name="scopes">. They
are, to some degree, comparable to their C counterparts. Both have a list of
members. Each member allocates storage, and optionally may have a name whose
value, in the case of a struct, usually is the storage offset from the
beginning, and in the case of a union, doesn't change, and usually is zero.
members. Each member allocates storage, and optionally may have a name.
Each named member has a constant value equal to the storage offset from the
beginning of the structure. In the case of a union, all members are placed at
the same offset, typically 0.
Each named member also has a storage size which can be accessed with the
<tt><ref id=".SIZEOF" name=".SIZEOF"></tt> operator. The struct or union itself
also has a <tt/.SIZEOF/ indicating its total storage size.
<sect1>Declaration<p>
@ -4899,8 +4907,9 @@ A struct or union may not necessarily have a name. If it is anonymous, no
local scope is opened; the identifiers used to name the members are placed
into the current scope instead.
A struct may contain unnamed members and definitions of local structs/unions.
The storage allocators may contain a multiplier, as in the example below:
Storage allocators may contain a multiplier. A struct may also contain members
and definitions of local structs/unions. Example:
<tscreen><verb>
.struct Circle
.struct Point
@ -4909,7 +4918,8 @@ The storage allocators may contain a multiplier, as in the example below:
Radius .word
.endstruct
</verb></tscreen>
The size of the Circle struct is 6 (three words).
In this example the size of the Circle struct is 6 (three words).
<sect1>The storage allocator keywords<p>
@ -4919,7 +4929,7 @@ The size of the Circle struct is 6 (three words).
<tag/.BYTE, .RES/
Allocates multiples of 1 byte. <tt/.RES/ requires an operand.
<tag/.DBYTE, .WORD, .ADDR/
<tag/.DBYT, .WORD, .ADDR/
Allocates multiples of 2 bytes.
<tag/.FARADDR/
@ -4928,6 +4938,15 @@ The size of the Circle struct is 6 (three words).
<tag/.DWORD/
Allocates multiples of 4 bytes.
<tag/.TAG/
Allocates a previously defined struct.
<tag/.STRUCT, .UNION/
Begins a nested .struct or .union definition, and allocates it.
Note that its member offset values will begin at 0, unless this nested
structure is anonymous, in which case they will instead become members of
the enclosing scope.
</descrip>
@ -4972,13 +4991,54 @@ name=".TAG"> directive.
C: .tag Circle
</verb></tscreen>
Currently, members are just offsets from the start of the struct or union. To
Members are just offsets from the start of the struct or union. To
access a field of a struct, the member offset must be added to the address of
the struct variable itself:
<tscreen><verb>
lda C+Circle::Radius ; Load circle radius into A
lda C + Circle::Radius ; Load circle radius
lda C + Circle::Origin + Point::ycoord ; Load circle origin.ycoord
</verb></tscreen>
That may change in a future version of the assembler.
Nested structures or unions are treated differently depending on whether they
are anonymous. If named, a new structure definition is created within the
enclosing scope, with its offsets beginning at 0. If anonymous, the members of
the new structure are added to the enclosing scope instead, with offsets
continuing through that scope. Example:
<tscreen><verb>
.struct Object
id .byte ; Object::id = 0
target .struct Point ; Object::target = 1
xcoord .word ; Object::Point::xcoord = 0
ycoord .word ; Object::Point::ycoord = 2
.endstruct
cost .struct ; Object::cost = 5
price .word ; Object::price = 5
tax .word ; Object::tax = 7
.endstruct
.struct
radius .word ; Object::radius = 9
.endstruct
.endstruct
O: .tag Object
lda O + Object::target + Object::Point::ycoord ; Named struct
lda O + Object::tax ; Anonymous
lda O + Object::radius ; Anonymous
; Be careful not to use a named nested structure without also adding the
; offset to the nested structure itself.
lda O + Object::Point::ycoord ; Incorrect!
lda O + Object::target + Object::Point::ycoord ; Correct
</verb></tscreen>
In this example, the first nested structure is named "Point", and its member
offsets begin at 0. On the other hand, the two anonymous structures simply
continue to add members to the enclosing "Object" structure.
Note that an anonymous structure does not need a member name, since all of its
members become part of the enclosing structure. The "cost" member in the
example is redundantly the same offset as its first member "price".
<sect1>Limitations<p>

View File

@ -1613,13 +1613,13 @@ parameter with the <tt/#pragma/.
This pragma sets a wrapper for functions, often used for trampolines.
The name is a function returning <tt/void/, and taking no parameters.
The <tt/name/ is a wrapper function returning <tt/void/, and taking no parameters.
It must preserve the CPU's <tt/A/ and <tt/X/ registers if it wraps any
<tt/__fastcall__/ functions that have parameters. It must preserve
the <tt/Y/ register if it wraps any variadic functions (they have "<tt/.../"
in their prototypes).
The identifier is an 8-bit number that's set into <tt/tmp4/. If the identifier
The <tt/identifier/ is an 8-bit number that's set into <tt/tmp4/. If the <tt/identifier/
is "bank", then ca65's <tt><url url="ca65.html#.BANK" name=".bank"></tt> function will be used
to determine the number from the bank attribute defined in the linker config,
see <url url="ld65.html#MEMORY" name="Other MEMORY area attributes">. Note that
@ -1629,6 +1629,11 @@ parameter with the <tt/#pragma/.
The address of a wrapped function is passed in <tt/ptr4/. The wrapper can
call that function by using "<tt/jsr callptr4/".
All functions ever declared or defined when this pragma is in effect will be wrapped
when they are called explicitly by their names later in the same translation unit.
Invocation of these functions in any other ways, for example, that via a function
pointer or in inline assembly code, will not be wrapped.
This feature is useful, for example, with banked memory, to switch banks
automatically to where a wrapped function resides, and then to restore the
previous bank when it returns.

View File

@ -261,6 +261,9 @@ different options for different files on the command line. As an example.
translates main.c with full optimization and module.c with less optimization
and debug info enabled.
Note that the target system (-t , --target) must be specified before any file
unless using the default target of c64
The type of an input file is derived from its extension:
<itemize>

View File

@ -71,18 +71,21 @@ function.
<item><ref id="detect_c64dtv" name="detect_c64dtv">
<item><ref id="detect_c65" name="detect_c65">
<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_turbomaster" name="detect_turbomaster">
<item><ref id="get_c128_speed" name="get_c128_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_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_turbomaster_speed" name="get_turbomaster_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_c65_speed" name="set_c65_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_turbomaster_speed" name="set_turbomaster_speed">
</itemize>
@ -92,7 +95,10 @@ function.
<itemize>
<item>_dos_type
<item><ref id="beep" name="beep">
<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
</itemize>
@ -101,7 +107,10 @@ function.
<itemize>
<item>_dos_type
<item><ref id="beep" name="beep">
<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><ref id="videomode" name="videomode">
</itemize>
@ -846,6 +855,20 @@ communication, see also <tt>testcode/lib/ser-test.c</tt>.
(incomplete)
<sect1><tt/stat.h/<label id="sys/stat.h"><p>
<itemize>
<item><ref id="stat" name="stat">
</itemize>
<sect1><tt/statvfs.h/<label id="sys/statvfs.h"><p>
<itemize>
<item><ref id="statvfs" name="statvfs">
</itemize>
<sect1><tt/vic20.h/<label id="vic20.h"><p>
(incomplete)
@ -1750,10 +1773,11 @@ used in presence of a prototype.
<descrip>
<tag/Function/Beep sound.
<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/Description/<tt/beep/ makes a brief tone.
<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>
<tag/Availability/cc65
<tag/See also/
@ -2851,6 +2875,79 @@ setting the time may not work. See also the platform-specific information.
</quote>
<sect1>gmtime_dt<label id="gmtime_dt"><p>
<quote>
<descrip>
<tag/Function/Converts a ProDOS date to a struct tm.
<tag/Header/<tt/<ref id="apple2.h" name="apple2.h">/
<tag/Declaration/<tt/struct tm* __fastcall__ gmtime_dt (const struct datetime* dt);/
<tag/Description/The <tt/gmtime_dt/ function converts the given
proDOS date/time to a struct tm. On error, NULL is returned and <tt/errno/ is set
to an error code describing the reason for the failure.
<tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only
be used in presence of a prototype.
<item>This function is only available on Apple II.
<item>On Apple II, you can't stat() an opened file. stat() before opening.
</itemize>
<tag/Availability/cc65
<tag/Example/
<verb>
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
int main(void)
{
struct stat st;
struct tm* tm;
if (stat ("/disk/file", &amp;st) == 0) {
tm = gmtime_dt (&amp;st.st_ctime);
if (tm)
printf ("File created on %s\n", asctime(tm));
}
}
</verb>
</descrip>
</quote>
<sect1>mktime_dt<label id="mktime_dt"><p>
<quote>
<descrip>
<tag/Function/Converts a ProDOS date to a time_t.
<tag/Header/<tt/<ref id="apple2.h" name="apple2.h">/
<tag/Declaration/<tt/time_t __fastcall__ mktime_dt (const struct datetime* dt);/
<tag/Description/The <tt/mktime_dt/ function parses the given
proDOS date/time and returns a time_t timestamp. On error, 0 is returned,
and errno is set.
<tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only
be used in presence of a prototype.
<item>This function is only available on Apple II.
</itemize>
<tag/Availability/cc65
<tag/Example/
<verb>
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
int main(void)
{
struct stat st;
if (stat ("/disk/file", &amp;st) == 0) {
printf ("File created on %s\n",
localtime (mktime_dt (&amp;st.st_ctime)));
}
}
</verb>
</descrip>
</quote>
<sect1>clrscr<label id="clrscr"><p>
<quote>
@ -3364,6 +3461,26 @@ used in presence of a prototype.
</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>
<quote>
@ -4078,6 +4195,27 @@ header files define constants that can be used to check the return code.
</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>
<quote>
@ -6229,6 +6367,9 @@ be used in presence of a prototype.
<item>The returned pointer may point to a statically allocated instance of
<tt/struct dirent/, so it may get overwritten by subsequent calls to
<tt/readdir/.
<item>On the Apple II platform, the d_ctime and d_mtime returned are in the
ProDOS format. You can convert them to more portable time representations using
the ProDOS datetime conversion functions.
<item>On several platforms, namely the CBMs and the Atari, the disk drives get
confused when opening/closing files between directory reads. So for example a
program that reads the list of files on a disk, and after each call to
@ -6893,6 +7034,30 @@ clean-up when exiting the program.
</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>
<quote>
@ -7075,6 +7240,85 @@ be used in presence of a prototype.
</quote>
<sect1>stat<label id="stat"><p>
<quote>
<descrip>
<tag/Function/Get file status.
<tag/Header/<tt/<ref id="sys/stat.h" name="sys/stat.h">/
<tag/Declaration/<tt/int __fastcall__ stat (const char* pathname, struct stat* statbuf);/
<tag/Description/<tt/stat/ gets information for the file with the given name. On success,
zero is returned. On error, -1 is returned and <tt/errno/ is set to an error
code describing the reason for the failure.
<tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only
be used in presence of a prototype.
<item>On the Apple II platform, the st_ctim, st_mtim and st_atim members are left
to zero, for size and performance reasons. The ProDOS creation and modification dates
are returned in the ProDOS format in st_ctime and st_mtime. The access date does
not exist. You can convert them to POSIX-style time representations using
the <url url="apple2.html#ss9.3" name="ProDOS datetime conversion functions">.
</itemize>
<tag/Availability/POSIX 1003.1
<tag/See also/
<ref id="statvfs" name="statvfs">
<tag/Example/
<verb>
#include &lt;sys/stat.h&gt;
#define FILENAME "helloworld"
struct stat stbuf;
if (stat (FILENAME, &amp;stbuf) == 0) {
printf ("%s size is %lu bytes (created on %s)\n", FILENAME, stbuf.st_size,
#ifndef __APPLE2__
localtime (&amp;stbuf.st_ctim.tv_sec)
#else
localtime (mktime_dt (&amp;stbuf.st_ctime))
#endif
);
} else {
printf ("There was a problem stat'ing %s: %d\n", FILENAME, errno);
}
</verb>
</descrip>
</quote>
<sect1>statvfs<label id="statvfs"><p>
<quote>
<descrip>
<tag/Function/Get filesystem statistics.
<tag/Header/<tt/<ref id="sys/statvfs.h" name="sys/statvfs.h">/
<tag/Declaration/<tt/int __fastcall__ statvfs (const char* pathname, struct statvfs* buf);/
<tag/Description/<tt/statvfs/ gets information for the filesytem on which the given file
resides. On success,
zero is returned. On error, -1 is returned and <tt/errno/ is set to an error
code describing the reason for the failure.
<tag/Notes/<itemize>
<item>The function is only available as fastcall function, so it may only
be used in presence of a prototype.
<item>The function requires an absolute pathname.
</itemize>
<tag/Availability/POSIX 1003.1
<tag/See also/
<ref id="stat" name="stat">
<tag/Example/
<verb>
#include &lt;sys/statvfs.h&gt;
#define FILENAME "/disk/helloworld"
struct statvfs stvbuf;
if (statvfs (FILENAME, &amp;stvbuf) == 0) {
printf ("%s filesystem has %u blocks of %u size, %u of them free.\n", FILENAME, stvbuf.f_blocks, stvbuf.f_bsize, stvbuf.f_bfree);
} else {
printf ("There was a problem statvfs'ing %s: %d\n", FILENAME, errno);
}
</verb>
</descrip>
</quote>
<sect1>strcasecmp<label id="strcasecmp"><p>
<quote>

View File

@ -115,37 +115,78 @@ PVExit ($01)
<sect>Creating a Test in C<p>
For a C test compiled and linked with <tt/--target sim6502/ the
For a C test linked with <tt/--target sim6502/ and the <tt/sim6502.lib/ library,
command line arguments to <tt/sim65/ will be passed to <tt/main/,
and the return value from <tt/main/ will become sim65's exit code.
The <tt/exit/ function may also be used to terminate with an exit code.
The <tt/stdlib.h/ <tt/exit/ function may also be used to terminate with an exit code.
Exit codes are limited to 8 bits.
Exit codes are limited to an unsigned 8 bit value. (E.g. returning -1 will give an exit code of 255.)
The standard C library high level file input and output is functional.
A sim65 application can be written like a command line application,
providing arguments to <tt/main/ and using the <tt/stdio.h/ interfaces.
providing command line arguments to <tt/main/ and using the <tt/stdio.h/ interfaces
to interact with the console or access files.
Internally, file input and output is provided at a lower level by
a set of built-in paravirtualization functions (<ref id="paravirt-internal" name="see below">).
a set of built-in paravirtualization functions (see <ref id="paravirt-internal" name="below">).
Example:
<tscreen><verb>
#include <stdio.h>
int main()
{
printf("Hello!\n");
return 5;
}
// Build and run:
// cl65 -t sim6502 -o example.prg example.c
// sim65 example.prg
// Build and run, separate steps:
// cc65 -t sim6502 -o example.s example.c
// ca65 -t sim6502 -o example.o example.s
// ld65 -t sim6502 -o example.prg example.o sim6502.lib
// sim65 example.prg
</verb></tscreen>
<sect>Creating a Test in Assembly<p>
Assembly tests may similarly be assembled and linked with
<tt/--target sim6502/ or <tt/--target sim65c02/.
Define and export <tt/_main/ as an entry point,
Though a C test may also link with assembly code,
a pure assembly test can also be created.
Link with <tt/--target sim6502/ or <tt/--target sim65c02/ and the corresponding library,
define and export <tt/_main/ as an entry point,
and the sim65 library provides two ways to return an 8-bit exit code:
<itemize>
<item>Return from <tt/_main/ with the exit code in <tt/A/.
<item><tt/jmp exit/ with the code in <tt/A/.
<item><tt/jmp exit/ with the code in <tt/A/. (<tt/.import exit/ from the sim65 library.)
</itemize>
The binary file has a 12 byte header:
Example:
<tscreen><verb>
.export _main
_main:
lda #5
rts
; Build and run:
; cl65 -t sim6502 -o example.prg example.s
; sim65 example.prg
; Build and run, separate steps:
; ca65 -t sim6502 -o example.o example.s
; ld65 -t sim6502 -o example.prg example.o sim6502.lib
; sim65 example.prg
</verb></tscreen>
Internally, the binary program file has a 12 byte header provided by the library:
<itemize>
@ -182,6 +223,9 @@ These use cc65 calling conventions, and are intended for use with the sim65 targ
<item><tt/IRQ/ and <tt/NMI/ events will not be generated, though <tt/BRK/
can be used if the IRQ vector at <tt/$FFFE/ is manually prepared by the test code.
<item>The <tt/sim6502/ or <tt/sim65c02/ targets provide a default configuration,
but if customization is needed <tt/sim6502.cfg/ or <tt/sim65c02.cfg/ might be used as a template.
</itemize>

View File

@ -304,6 +304,36 @@ unsigned char detect_turbomaster (void);
* 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 */
#endif

View File

@ -41,6 +41,7 @@
# error This module may only be used when compiling for the Apple ][!
#endif
#include <time.h>
#include <apple2_filetype.h>
@ -142,6 +143,27 @@ extern unsigned char _dos_type;
** ProDOS 8 2.4.x - 0x24
*/
/* struct stat.st_mode values */
#define S_IFDIR 0x01
#define S_IFREG 0x02
#define S_IFBLK 0xFF
#define S_IFCHR 0xFF
#define S_IFIFO 0xFF
#define S_IFLNK 0xFF
#define S_IFSOCK 0xFF
struct datetime {
struct {
unsigned day :5;
unsigned mon :4;
unsigned year :7;
} date;
struct {
unsigned char min;
unsigned char hour;
} time;
};
/*****************************************************************************/
@ -151,20 +173,10 @@ extern unsigned char _dos_type;
/* The file stream implementation and the POSIX I/O functions will use the
** following struct to set the date and time stamp on files. This specificially
** following struct to set the date and time stamp on files. This specifically
** applies to the open and fopen functions.
*/
extern struct {
struct {
unsigned day :5;
unsigned mon :4;
unsigned year :7;
} createdate; /* Current date: 0 */
struct {
unsigned char min;
unsigned char hour;
} createtime; /* Current time: 0 */
} _datetime;
extern struct datetime _datetime;
/* The addresses of the static drivers */
#if !defined(__APPLE2ENH__)
@ -185,6 +197,9 @@ extern void a2_lo_tgi[];
void beep (void);
/* Beep beep. */
unsigned char get_ostype (void);
/* Get the machine type. Returns one of the APPLE_xxx codes. */
@ -211,6 +226,12 @@ void rebootafterexit (void);
#define _cpeekcolor() COLOR_WHITE
#define _cpeekrevers() 0
struct tm* __fastcall__ gmtime_dt (const struct datetime* dt);
/* Converts a ProDOS date/time structure to a struct tm */
time_t __fastcall__ mktime_dt (const struct datetime* dt);
/* Converts a ProDOS date/time structure to a time_t UNIX timestamp */
/* End of apple2.h */

View File

@ -33,6 +33,8 @@
#ifndef _DIRENT_H
#define _DIRENT_H
#include <target.h>
/*****************************************************************************/
@ -46,31 +48,15 @@ typedef struct DIR DIR;
#if defined(__APPLE2__)
struct dirent {
char d_name[16];
unsigned d_ino;
unsigned d_blocks;
unsigned long d_size;
unsigned char d_type;
struct {
unsigned day :5;
unsigned mon :4;
unsigned year :7;
} d_cdate;
struct {
unsigned char min;
unsigned char hour;
} d_ctime;
unsigned char d_access;
unsigned d_auxtype;
struct {
unsigned day :5;
unsigned mon :4;
unsigned year :7;
} d_mdate;
struct {
unsigned char min;
unsigned char hour;
} d_mtime;
char d_name[16];
unsigned d_ino;
unsigned d_blocks;
unsigned long d_size;
unsigned char d_type;
struct datetime d_ctime;
unsigned char d_access;
unsigned d_auxtype;
struct datetime d_mtime;
};
#define _DE_ISREG(t) ((t) != 0x0F)

View File

@ -72,8 +72,8 @@ void __fastcall__ ria_push_long (unsigned long val);
void __fastcall__ ria_push_int (unsigned int val);
#define ria_push_char(v) RIA.xstack = v
long __fastcall__ ria_pop_long (void);
int __fastcall__ ria_pop_int (void);
long ria_pop_long (void);
int ria_pop_int (void);
#define ria_pop_char() RIA.xstack
/* Set the RIA fastcall register */
@ -118,9 +118,9 @@ long __fastcall__ ria_call_long_errno (unsigned char op);
/* C API for the operating system. */
int __cdecl__ xreg (char device, char channel, unsigned char address, ...);
int __fastcall__ phi2 (void);
int __fastcall__ codepage (void);
long __fastcall__ lrand (void);
int phi2 (void);
int codepage (void);
long lrand (void);
int __fastcall__ stdin_opt (unsigned long ctrl_bits, unsigned char str_length);
int __fastcall__ read_xstack (void* buf, unsigned count, int fildes);
int __fastcall__ read_xram (unsigned buf, unsigned count, int fildes);

View File

@ -86,6 +86,10 @@ extern FILE* stderr;
# define FILENAME_MAX (80+1)
#elif defined(__TELESTRAT__)
# define FILENAME_MAX (50+1)
#elif defined(__SIM6502__)
# define FILENAME_MAX (1024+1)
#elif defined(__SIM65C02__)
# define FILENAME_MAX (1024+1)
#else
# define FILENAME_MAX (16+1)
#endif

View File

@ -2,7 +2,7 @@
/* */
/* stat.h */
/* */
/* Constants for the mode argument of open and creat */
/* stat(2) definition */
/* */
/* */
/* */
@ -11,6 +11,9 @@
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* (C) 2023 Colin Leroy-Mira */
/* EMail: colin@colino.net */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
@ -36,6 +39,10 @@
#ifndef _STAT_H
#define _STAT_H
#include <time.h>
#include <target.h>
#include <sys/types.h>
/*****************************************************************************/
@ -47,6 +54,30 @@
#define S_IREAD 0x01
#define S_IWRITE 0x02
#define S_IFMT 0x03
struct stat {
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
gid_t st_gid;
off_t st_size;
struct timespec st_atim;
struct timespec st_ctim;
struct timespec st_mtim;
#ifdef __APPLE2__
unsigned char st_access;
unsigned char st_type;
unsigned int st_auxtype;
unsigned char st_storagetype;
unsigned int st_blocks;
struct datetime st_mtime;
struct datetime st_ctime;
#endif
};
/*****************************************************************************/
@ -55,5 +86,9 @@
int __fastcall__ stat (const char* pathname, struct stat* statbuf);
/* End of stat.h */
#endif

View File

@ -1,15 +1,13 @@
/*****************************************************************************/
/* */
/* asctime.c */
/* statvfs.h */
/* */
/* Convert a broken down time into a string */
/* statvfs(3) definition */
/* */
/* */
/* */
/* (C) 2002 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* (C) 2023 Colin Leroy-Mira */
/* EMail: colin@colino.net */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@ -33,8 +31,32 @@
#include <stdio.h>
#include <time.h>
#ifndef _STATVFS_H
#define _STATVFS_H
#include <sys/types.h>
/*****************************************************************************/
/* Data */
/*****************************************************************************/
struct statvfs {
unsigned long f_bsize;
unsigned long f_frsize;
fsblkcnt_t f_blocks;
fsblkcnt_t f_bfree;
fsblkcnt_t f_bavail;
fsfilcnt_t f_files;
fsfilcnt_t f_ffree;
fsfilcnt_t f_favail;
unsigned long f_fsid;
unsigned long f_flag;
unsigned long f_namemax;
};
@ -42,18 +64,11 @@
/* 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];
int __fastcall__ statvfs (const char* pathname, struct statvfs* buf);
/* Format into given buffer and return the result */
return strftime (buf, sizeof (buf), "%c\n", timep)? buf : 0;
}
/* End of statvfs.h */
#endif

View File

@ -50,6 +50,46 @@
typedef long int off_t;
#endif
#ifndef _HAVE_dev_t
#define _HAVE_dev_t
typedef unsigned long int dev_t;
#endif
#ifndef _HAVE_ino_t
#define _HAVE_ino_t
typedef unsigned long int ino_t;
#endif
#ifndef _HAVE_nlink_t
#define _HAVE_nlink_t
typedef unsigned long int nlink_t;
#endif
#ifndef _HAVE_uid_t
#define _HAVE_uid_t
typedef unsigned char uid_t;
#endif
#ifndef _HAVE_gid_t
#define _HAVE_gid_t
typedef unsigned char gid_t;
#endif
#ifndef _HAVE_mode_t
#define _HAVE_mode_t
typedef unsigned char mode_t;
#endif
#ifndef _HAVE_fsblkcnt_t
#define _HAVE_fsblkcnt_t
typedef unsigned long int fsblkcnt_t;
#endif
#ifndef _HAVE_fsfilcnt_t
#define _HAVE_fsfilcnt_t
typedef unsigned long int fsfilcnt_t;
#endif
/*****************************************************************************/
@ -60,6 +100,3 @@ typedef long int off_t;
/* End of types.h */
#endif

View File

@ -37,6 +37,11 @@
#define _TIME_H
/* Forward declaration for target.h */
typedef unsigned long time_t;
typedef unsigned long clock_t;
/* NULL pointer */
#ifndef NULL
@ -49,9 +54,6 @@
typedef unsigned size_t;
#endif
typedef unsigned long time_t;
typedef unsigned long clock_t;
/* Structure for broken down time */
struct tm {
int tm_sec;

20
libsrc/apple2/beep.s Normal file
View 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
View 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

View File

@ -40,12 +40,15 @@ _exit: ldx #<exit
lda #>exit
jsr reset ; Setup RESET vector
; Switch in ROM, in case it wasn't already switched in by a RESET.
bit $C082
; Switch in LC bank 2 for R/O in case it was switched out by a RESET.
bit $C080
; Call the module destructors.
jsr donelib
; Switch in ROM.
bit $C082
; Restore the original RESET vector.
exit: ldx #$02
: lda rvsave,x

View 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

View File

@ -5,8 +5,8 @@
;
.export _exec
.import pushname, popname
.import popax, done, _exit
.import mli_file_info_direct
.import pushname, popname, popax, done, _exit
.include "zeropage.inc"
.include "errno.inc"
@ -17,13 +17,12 @@
typerr: lda #$4A ; "Incompatible file format"
; Cleanup name
oserr: jsr popname ; Preserves A
; Set ___oserror
jmp ___mappederrno
mlierr: jsr popname
oserr: jmp ___mappederrno
_exec:
; Save cmdline
; Store cmdline
sta ptr4
stx ptr4+1
@ -32,6 +31,9 @@ _exec:
jsr pushname
bne oserr
jsr mli_file_info_direct
bcs mlierr
; ProDOS TechRefMan, chapter 5.1.5.1:
; "The complete or partial pathname of the system program
; is stored at $280, starting with a length byte."
@ -46,18 +48,6 @@ _exec:
dey
bpl :-
; Set pushed name
lda sp
ldx sp+1
sta mliparam + MLI::INFO::PATHNAME
stx mliparam + MLI::INFO::PATHNAME+1
; Get file_type and aux_type
lda #GET_INFO_CALL
ldx #GET_INFO_COUNT
jsr callmli
bcs oserr
; If we get here the program file at least exists so we copy
; the loader stub right now and patch it later to set params
ldx #size - 1
@ -121,35 +111,9 @@ setbuf: lda #$00 ; Low byte
dex
dex
; Set I/O buffer
sta mliparam + MLI::OPEN::IO_BUFFER
stx mliparam + MLI::OPEN::IO_BUFFER+1
; PATHNAME already set
.assert MLI::OPEN::PATHNAME = MLI::INFO::PATHNAME, error
; Lower file level to avoid program file
; being closed by C library shutdown code
ldx LEVEL
stx level
beq :+
dec LEVEL
; Open file
: lda #OPEN_CALL
ldx #OPEN_COUNT
jsr callmli
; Restore file level
ldx level
stx LEVEL
bcc :+
jmp oserr
; Get and save fd
: lda mliparam + MLI::OPEN::REF_NUM
sta read_ref
sta close_ref
; Set OPEN MLI call I/O buffer parameter
sta io_buffer
stx io_buffer+1
.ifdef __APPLE2ENH__
; Calling the 80 column firmware needs the ROM switched
@ -194,14 +158,25 @@ setbuf: lda #$00 ; Low byte
; Initiate C library shutdown
jmp _exit
.bss
level : .res 1
.rodata
source:
; Open program file
; PATHNAME parameter is already set (we reuse
; the copy at $0280); IO_BUFFER has been setup
; before shutting down the C library
jsr $BF00
.byte OPEN_CALL
.word open_param
bcs error
; Copy REF_NUM to MLI READ and CLOSE parameters
lda open_ref
sta read_ref
sta close_ref
; Read whole program file
source: jsr $BF00
jsr $BF00
.byte READ_CALL
.word read_param
bcs error
@ -254,6 +229,14 @@ jump: jmp (data_buffer)
file_type = * - source + target
.byte $00
open_param = * - source + target
.byte $03 ; PARAM_COUNT
.addr $0280 ; PATHNAME
io_buffer = * - source + target
.addr $0000 ; IO_BUFFER
open_ref = * - source + target
.byte $00 ; REF_NUM
read_param = * - source + target
.byte $04 ; PARAM_COUNT
read_ref = * - source + target
@ -285,4 +268,8 @@ size = * - source
target = DOSWARM - size
; Make sure that the loader isn't too big, and
; fits in $300-$3D0
.assert target >= $300, error
dosvec: jmp quit

View File

@ -8,6 +8,7 @@
.import subysp, addysp, decsp1
.include "zeropage.inc"
.include "apple2.inc"
.include "mli.inc"
pushname:
@ -15,7 +16,7 @@ pushname:
stx ptr1+1
; Alloc pathname buffer
ldy #64+1 ; Max pathname length + zero
ldy #FILENAME_MAX
jsr subysp
; Check for full pathname
@ -71,14 +72,14 @@ copy: lda (ptr1),y
sta (sp),y
beq setlen
iny
cpy #64+1 ; Max pathname length + zero
cpy #FILENAME_MAX
bcc copy
; Load oserror code
lda #$40 ; "Invalid pathname"
; Free pathname buffer
addsp65:ldy #64+1
addsp65:ldy #FILENAME_MAX
bne addsp ; Branch always
; Alloc and set length byte
@ -93,5 +94,5 @@ setlen: tya
popname:
; Cleanup stack
ldy #1 + 64+1 ; Length byte + max pathname length + zero
addsp: jmp addysp ; Preserves A
ldy #1 + FILENAME_MAX
addsp: jmp addysp ; Preserves A and X

View 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

View File

@ -5,7 +5,7 @@
;
.constructor initostype, 9
.export _get_ostype
.export _get_ostype, ostype
; Identify machine according to:
; Apple II Miscellaneous TechNote #7, Apple II Family Identification

View File

@ -4,7 +4,8 @@
; int __fastcall__ clock_gettime (clockid_t clk_id, struct timespec *tp);
;
.import pushax, steaxspidx, incsp1, incsp3, return0
.import pushax, incsp1, incsp3, steaxspidx, return0
.import _mktime_dt
.include "time.inc"
.include "zeropage.inc"
@ -29,42 +30,12 @@ _clock_gettime:
jsr callmli
bcs oserr
; Get date
lda DATELO+1
lsr
php ; Save month msb
cmp #70 ; Year < 70?
bcs :+ ; No, leave alone
adc #100 ; Move 19xx to 20xx
: sta TM + tm::tm_year
lda DATELO
tax ; Save day
plp ; Restore month msb
ror
lsr
lsr
lsr
lsr
beq erange ; [1..12] allows for validity check
tay
dey ; Move [1..12] to [0..11]
sty TM + tm::tm_mon
txa ; Restore day
and #%00011111
sta TM + tm::tm_mday
; Convert DATELO/TIMELO to time_t
lda #<DATELO
ldx #>DATELO
jsr _mktime_dt
; Get time
lda TIMELO+1
sta TM + tm::tm_hour
lda TIMELO
sta TM + tm::tm_min
; Make time_t
lda #<TM
ldx #>TM
jsr _mktime
; Store tv_sec
; Store
ldy #timespec::tv_sec
jsr steaxspidx
@ -74,21 +45,8 @@ _clock_gettime:
; Return success
jmp return0
; Load errno code
erange: lda #ERANGE
; Cleanup stack
jsr incsp3 ; Preserves A
; Set __errno
jmp ___directerrno
; Cleanup stack
oserr: jsr incsp3 ; Preserves A
; Set ___oserror
jmp ___mappederrno
.bss
TM: .tag tm

73
libsrc/apple2/gmtime_dt.s Normal file
View File

@ -0,0 +1,73 @@
;
; Oliver Schmidt, 14.08.2018
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
; struct tm * __fastcall__ gmtime_dt(const struct datetime *dt)
;
.export _gmtime_dt, tm_buf
.include "time.inc"
.include "zeropage.inc"
.include "errno.inc"
.include "mli.inc"
; Convert ProDOS date/time to a struct tm
; source date address in AX
; on stack:
; destination struct
_gmtime_dt:
sta ptr1
stx ptr1+1
; Get time
ldy #$03
lda (ptr1),y
sta tm_buf + tm::tm_hour
dey
lda (ptr1),y
sta tm_buf + tm::tm_min
; Get date
dey
lda (ptr1),y
lsr
php ; Save month msb
cmp #70 ; Year < 70?
bcs :+ ; No, leave alone
adc #100 ; Move 19xx to 20xx
: sta tm_buf + tm::tm_year
dey
lda (ptr1),y
tax ; Save day
plp ; Restore month msb
ror
lsr
lsr
lsr
lsr
beq erange ; [1..12] allows for validity check
tay
dey ; Move [1..12] to [0..11]
sty tm_buf + tm::tm_mon
txa ; Restore day
and #%00011111
sta tm_buf + tm::tm_mday
lda #<tm_buf ; Return pointer to tm_buf
ldx #>tm_buf
rts
; Load errno code and return NULL
erange: lda #ERANGE
sta ___errno
lda #$00
tax
rts
.bss
tm_buf:
.tag tm

37
libsrc/apple2/mktime_dt.s Normal file
View File

@ -0,0 +1,37 @@
;
; Oliver Schmidt, 14.08.2018
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
; time_t __fastcall__ mktime_dt(const struct datetime *dt)
;
.import steaxspidx, pushax, incsp2, _gmtime_dt
.import tm_buf
.export _mktime_dt
.include "time.inc"
.include "zeropage.inc"
.include "errno.inc"
.include "mli.inc"
; Convert ProDOS date/time to UNIX timestamp
; source date address in AX
_mktime_dt:
; Convert to internal tm
jsr _gmtime_dt
cpx #$00
bne :+
cmp #$00
beq err
; Make time_t
: lda #<tm_buf
ldx #>tm_buf
jmp _mktime
err: lda #$00
tax
sta sreg
sta sreg+1
rts

View File

@ -83,8 +83,8 @@ EOF_COUNT = 2
AUX_TYPE .word
STORAGE_TYPE .byte
BLOCKS .word
MODE_DATE .word
MODE_TIME .word
MOD_DATE .word
MOD_TIME .word
CREATE_DATE .word
CREATE_TIME .word
.endstruct
@ -139,3 +139,6 @@ LEVEL := $BF94 ; File level: used in open, flush, close
MACHID := $BF98 ; Machine identification
PFIXPTR := $BF9A ; If = 0, no prefix active
KVERSION:= $BFFF ; Kernel version number
; Max filename length
FILENAME_MAX = 64+1

View File

@ -0,0 +1,33 @@
;
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
.export mli_file_info
.import pushname, popname, mli_file_info_direct
.import popax
.include "zeropage.inc"
.include "errno.inc"
.include "mli.inc"
; Calls ProDOS MLI GET_FILE_INFO on the filename
; stored as C string in AX at top of stack
; Returns with carry set on error, and sets errno
mli_file_info:
; Get pathname
jsr popax
jsr pushname
bne oserr
jsr mli_file_info_direct
php ; Save return status
jsr popname ; Preserves A
plp
bcs oserr
rts
oserr:
jsr ___mappederrno
sec
rts

View File

@ -0,0 +1,22 @@
;
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
.export mli_file_info_direct
.include "zeropage.inc"
.include "mli.inc"
; Calls ProDOS MLI GET_FILE_INFO on the ProDOS style
; filename stored on top of stack
; Returns with carry set on error, and sets errno
mli_file_info_direct:
; Set pushed name
lda sp
ldx sp+1
sta mliparam + MLI::INFO::PATHNAME
stx mliparam + MLI::INFO::PATHNAME+1
; Get file information
lda #GET_INFO_CALL
ldx #GET_INFO_COUNT
jmp callmli

View File

@ -18,6 +18,7 @@
.include "fcntl.inc"
.include "mli.inc"
.include "filedes.inc"
.include "time.inc"
.segment "ONCE"

View File

@ -66,34 +66,16 @@ HSType: .res 1 ; Flow-control type
RecvBuf: .res 256 ; Receive buffers: 256 bytes
SendBuf: .res 256 ; Send buffers: 256 bytes
CurClockSource: .res 1 ; Whether to use BRG or RTxC for clock
.data
Opened: .byte $00 ; 1 when opened
Channel: .byte $00 ; Channel B by default
CurChanIrqFlags:.byte INTR_PENDING_RX_EXT_B
CurChanIrqFlags:.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)
.byte %10000000 ; SER_BITS_6 (Ref page 5-7)
.byte %01000000 ; SER_BITS_7
@ -106,29 +88,65 @@ TxBitTable: .byte %00000000 ; SER_BITS_5, in WR_TX_CTRL (WR5)
.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
; Otherwise refers to the index in
; Baud(Low/High)Table
.byte $FF ; SER_BAUD_45_5
.byte $FF ; SER_BAUD_50
.byte $FF ; SER_BAUD_75
.byte $FF ; SER_BAUD_110
.byte $FF ; SER_BAUD_134_5
.byte $FF ; SER_BAUD_150
.byte $00 ; SER_BAUD_300
.byte $FF ; SER_BAUD_600
.byte $01 ; SER_BAUD_1200
.byte $FF ; SER_BAUD_1800
.byte $02 ; SER_BAUD_2400
.byte $FF ; SER_BAUD_3600
.byte $03 ; SER_BAUD_4800
.byte $FF ; SER_BAUD_7200
.byte $04 ; SER_BAUD_9600
.byte $05 ; SER_BAUD_19200
.byte $06 ; SER_BAUD_38400
.byte $07 ; SER_BAUD_57600
.byte $FF ; SER_BAUD_115200
.byte $FF ; SER_BAUD_230400
; Indexes cc65 RS232 SER_BAUD enum
; into WR12/13 register values
; (Ref page 5-18 and 5-19)
.word $FFFF ; SER_BAUD_45_5
.word $FFFF ; SER_BAUD_50
.word $FFFF ; SER_BAUD_75
.word $FFFF ; SER_BAUD_110
.word $FFFF ; SER_BAUD_134_5
.word $FFFF ; SER_BAUD_150
.word $017E ; SER_BAUD_300
.word $FFFF ; SER_BAUD_600
.word $005E ; SER_BAUD_1200
.word $FFFF ; SER_BAUD_1800
.word $002E ; SER_BAUD_2400
.word $FFFF ; SER_BAUD_3600
.word $0016 ; SER_BAUD_4800
.word $FFFF ; SER_BAUD_7200
.word $000A ; SER_BAUD_9600
.word $0004 ; SER_BAUD_19200
.word $0001 ; SER_BAUD_38400
.word $0000 ; SER_BAUD_57600
.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)
.byte %00001100 ; SER_STOP_2 (Ref page 5-8)
@ -156,6 +174,7 @@ SER_FLAG := $E10104
; ------------------------------------------------------------------------
; Channels
CHANNEL_B = 0
CHANNEL_A = 1
@ -180,7 +199,6 @@ RX_CTRL_OFF = %11111110 ; ANDed,Rx disabled
WR_TX_RX_CTRL = 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)
RR_TX_STATUS = 5 ; Corresponding status register
@ -197,15 +215,11 @@ MASTER_IRQ_MIE_RST = %00001010 ; STA'd
MASTER_IRQ_SET = %00011001 ; STA'd
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_BAUDH_CTRL = 13 ; (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)
IRQ_CLEANUP_EIRQ = %00001000
@ -220,13 +234,8 @@ IRQ_RX = %00100000
IRQ_SPECIAL = %01100000
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)
SER_FLAG_CH_A = %00111000
SER_FLAG_CH_B = %00000111
.code
; Read register value to A.
@ -329,6 +338,15 @@ IIgs:
: txa ; Promote char return value
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.
; 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
jsr readSSCReg
ldy #WR_MISC_CTRL ; Turn everything off
ldy #WR_MISC_CTRL ; WR14: Turn everything off
lda #$00
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
tay
lda StopTable,y ; Get value
@ -377,36 +397,33 @@ SER_OPEN:
ora ParityTable,y ; Get value
bmi InvParam
ora #TX_RX_CLOCK_MUL
ldy CurClockSource ; Clock multiplier
ora ClockMultiplier,y
ldy #WR_TX_RX_CTRL ; Setup stop & parity bits
jsr writeSCCReg
ldy #WR_TX_RX_CTRL
jsr writeSCCReg ; End of WR4 setup
ldy CurClockSource ; WR11 setup: clock source
cpx #CHANNEL_B
bne ClockA
ClockB:
beq SetClock
iny ; Shift to get correct ClockSource val
iny ; depending on our channel
SetClock:
lda ClockSource,y
ldy #WR_CLOCK_CTRL
lda #CLOCK_CTRL_CH_B
jsr writeSCCReg
jsr writeSCCReg ; End of WR11 setup
lda #INTR_PENDING_RX_EXT_B ; 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
lda ChanIrqFlags,x ; Store which IRQ bits we'll check
sta CurChanIrqFlags
SetBaud:
ldy #SER_PARAMS::BAUDRATE
lda (ptr1),y ; Baudrate index - cc65 value
.assert SER_PARAMS::BAUDRATE = 0, error
lda (ptr1) ; Baudrate index - cc65 value
asl
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
InvParam:
@ -415,59 +432,57 @@ InvParam:
bra SetupOut
BaudOK:
tay
lda BaudLowTable,y ; Get low byte
phy
ldy #WR_BAUDL_CTRL
jsr writeSCCReg
phy ; WR12 setup: BRG time constant, low byte
ldy #WR_BAUDL_CTRL ; Setting WR12 & 13 is useless if we're using
jsr writeSCCReg ; RTxC, but doing it anyway makes code smaller
ply
lda BaudHighTable,y ; Get high byte
iny
lda BaudTable,y ; WR13 setup: BRG time constant, high byte
ldy #WR_BAUDH_CTRL
jsr writeSCCReg
ldy CurClockSource ; WR14 setup: BRG enabling
lda BrgEnabled,y
ldy #WR_MISC_CTRL ; Time to turn this thing on
lda #MISC_CTRL_RATE_GEN_ON
jsr writeSCCReg
ldy #SER_PARAMS::DATABITS
lda (ptr1),y ; Data bits
ldy #SER_PARAMS::DATABITS ; WR3 setup: RX data bits
lda (ptr1),y
tay
lda RxBitTable,y ; Data bits for RX
ora #RX_CTRL_ON ; and turn RX on
lda RxBitTable,y
ora #RX_CTRL_ON ; and turn receiver on
phy
ldy #WR_RX_CTRL
jsr writeSCCReg
jsr writeSCCReg ; End of WR3 setup
ply
lda TxBitTable,y ; Data bits for TX
ora #TX_CTRL_ON ; and turn TX on
and #TX_DTR_ON
lda TxBitTable,y ; WR5 setup: TX data bits
ora #TX_CTRL_ON ; and turn transmitter on
and #TX_DTR_ON ; and turn DTR on
sta RtsOff ; Save value for flow control
ora #TX_RTS_ON
ora #TX_RTS_ON ; and turn RTS on
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
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
jsr writeSCCReg
jsr writeSCCReg ; Clear (write twice)
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
jsr writeSCCReg
lda SCCBREG ; Activate master IRQ
lda SCCBREG ; WR9 setup: Activate master IRQ
ldy #WR_MASTER_IRQ_RST
lda #MASTER_IRQ_SET
jsr writeSCCReg
@ -475,14 +490,7 @@ BaudOK:
lda SER_FLAG ; Get SerFlag's current value
sta SerFlagOrig ; and save it
cpx #CHANNEL_B
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:
ora ChanIrqMask,x ; Tell firmware which channel IRQs we want
sta SER_FLAG
ldy #$01 ; Mark port opened

View File

@ -121,7 +121,7 @@ BaudTable: ; Table used to translate RS232 baudrate param
.byte $0F ; SER_BAUD_19200
.byte $FF ; SER_BAUD_38400
.byte $FF ; SER_BAUD_57600
.byte $FF ; SER_BAUD_115200
.byte $00 ; SER_BAUD_115200
.byte $FF ; SER_BAUD_230400
BitTable: ; Table used to translate RS232 databits param
@ -302,6 +302,7 @@ HandshakeOK:
lda (ptr1),y ; Baudrate index
tay
lda BaudTable,y ; Get 6551 value
sta tmp2 ; Backup for IRQ setting
bpl BaudOK ; Check that baudrate is supported
lda #SER_ERR_BAUD_UNAVAIL
@ -332,8 +333,13 @@ BaudOK: sta tmp1
ora #%00000001 ; Set DTR active
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
stx Index ; Mark port as open

View 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
View 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

129
libsrc/apple2/stat.s Normal file
View File

@ -0,0 +1,129 @@
;
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
; int __fastcall__ stat(const char *pathname, struct stat *statbuf);
;
.export _stat
.import __errno, _open,_close
.import mli_file_info
.import popax, pushax, pusha0, incsp2
.include "zeropage.inc"
.include "errno.inc"
.include "fcntl.inc"
.include "filedes.inc"
.include "mli.inc"
.include "stat.inc"
_stat:
; Store statbuf pointer
sta ptr4
sta stbuf
stx ptr4+1
stx stbuf+1
; Clear statbuf
lda #$00
ldy #.sizeof(stat)-1
: sta (ptr4),y
dey
bpl :-
; Reset errno
sta ___errno
; Store pathname
jsr popax
jsr pushax ; Push it back for mli_file_info
jsr pushax ; and for open
jsr mli_file_info
bcc got_info
jmp incsp2 ; Drop filename copy for open
got_info:
; st_dev
lda DEVNUM
lsr ; Shift right to cc65 representation
lsr
lsr
lsr
ldy #stat::st_dev
sta (ptr4),y
; st_mode (S_IFDIR/S_IFREG only)
lda mliparam + MLI::INFO::FILE_TYPE
ldy #stat::st_mode
cmp #$0f
bne is_reg
lda #S_IFDIR
bne set_st_mode
is_reg: lda #S_IFREG
set_st_mode:
sta (ptr4),y
; st_access through st_create_time
ldx #MLI::INFO::ACCESS
ldy #stat::st_access
: lda mliparam,x
sta (ptr4),y
inx
iny
cpy #stat::st_create_time + .sizeof(stat::st_create_time)
bne :-
; st_size
lda #O_RDONLY
jsr pusha0
ldy #$04
jsr _open
cmp #$FF
beq done
pha ; Save file descriptor for closing
; Get ProDOS's REF_NUM from file descriptor
jsr getfd
; Get file information
sta mliparam + MLI::EOF::REF_NUM
lda #GET_EOF_CALL
ldx #EOF_COUNT
jsr callmli
bcs eoferr
; Get struct stat in ptr4 back, open destroyed it
lda stbuf
ldx stbuf+1
sta ptr4
stx ptr4+1
; Store size
ldy #stat::st_size
lda mliparam + MLI::EOF::EOF
sta (ptr4),y
lda mliparam + MLI::EOF::EOF+1
iny
sta (ptr4),y
lda mliparam + MLI::EOF::EOF+2
iny
sta (ptr4),y
; Close file
eoferr:
pla
ldx #$00
jsr _close
; Set return value if we had an error
lda ___errno
beq done
lda #$FF
done:
tax
rts
.bss
stbuf: .res 2

123
libsrc/apple2/statvfs.s Normal file
View File

@ -0,0 +1,123 @@
;
; Colin Leroy-Mira, 2023 <colin@colino.net>
;
; int __fastcall__ statvfs(const char *pathname, struct statvfs *statvfsbuf);
;
.export _statvfs
.import _dio_query_sectsize
.import mli_file_info, pushax, popax, popptr1, pushptr1
.include "zeropage.inc"
.include "apple2.inc"
.include "errno.inc"
.include "mli.inc"
.include "statvfs.inc"
_statvfs:
; Store statbuf
sta ptr4
stx ptr4+1
; Clear statbuf
lda #$00
ldy #.sizeof(statvfs)-1
: sta (ptr4),y
dey
bpl :-
; Store pathname, keeping only volume name
jsr popptr1
ldy #$00
sty vol_sep
lda (ptr1),y
cmp #'/' ; Is the path absolute?
beq :+
lda #EINVAL
jmp ___directerrno
: iny
lda (ptr1),y
beq :+ ; End of string, no other /
cpy #FILENAME_MAX
beq :+ ; Max filename length reached
cmp #'/'
bne :- ; Not a slash, keep looking
sty vol_sep ; Register '/' index
lda #$00
sta (ptr1),y ; Cut pathname at first slash
: jsr pushptr1
jsr mli_file_info
php
ldy vol_sep ; Put slash back in pathname
lda #'/'
sta (ptr1),y
plp
bcc got_info
jmp ___mappederrno
got_info:
; f_fsid
lda DEVNUM
lsr ; Shift right to cc65 representation
lsr
lsr
lsr
ldy #statvfs::f_fsid
sta (ptr4),y
; total number of blocks
lda mliparam + MLI::INFO::AUX_TYPE
ldy #statvfs::f_blocks
sta (ptr4),y
lda mliparam + MLI::INFO::AUX_TYPE+1
iny
sta (ptr4),y
; blocks free & avail
sec
lda mliparam + MLI::INFO::AUX_TYPE
sbc mliparam + MLI::INFO::BLOCKS
ldy #statvfs::f_bfree
sta (ptr4),y
ldy #statvfs::f_bavail
sta (ptr4),y
lda mliparam + MLI::INFO::AUX_TYPE+1
sbc mliparam + MLI::INFO::BLOCKS+1
iny
sta (ptr4),y
ldy #statvfs::f_bfree+1
sta (ptr4),y
; block sizes
jsr _dio_query_sectsize
; low bytes
ldy #statvfs::f_bsize
sta (ptr4),y
ldy #statvfs::f_frsize
sta (ptr4),y
; f_frsize high byte
iny
txa
sta (ptr4),y
; f_bsize high byte
ldy #statvfs::f_bsize+1
sta (ptr4),y
; f_namemax
lda #FILENAME_MAX
ldy #statvfs::f_namemax
sta (ptr4),y
lda #$00
sta ___errno
tax
rts
.bss
vol_sep:.res 1

View File

@ -108,7 +108,7 @@ static unsigned get_dir_entry(char* p_name)
}
/* Field header_pointer directly follows field last_mod */
cur_addr = *(unsigned*)(&dirent->d_mtime.hour + 1);
cur_addr = *(unsigned*)(&dirent->d_mtime.time.hour + 1);
dhandle = dio_open(getcurrentdevice());
if (!dhandle) {

20
libsrc/apple2/wait.s Normal file
View 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

View File

@ -5,21 +5,11 @@
;
.ifdef __APPLE2ENH__
.constructor initvsync
.export _waitvsync
.import _get_ostype
.import ostype
.include "apple2.inc"
.segment "ONCE"
initvsync:
jsr _get_ostype
sta ostype
rts
.code
_waitvsync:
bit ostype
bmi iigs ; $8x
@ -53,8 +43,4 @@ iic: sei
cli
rts
.segment "INIT"
ostype: .res 1
.endif ; __APPLE2ENH__

View File

@ -19,7 +19,7 @@
.import findfreeiocb
.import incsp4
.import ldaxysp,addysp
.import ___oserror
.import ___oserror, returnFFFF
.ifdef UCASE_FILENAME
.import ucase_fn
.endif
@ -39,9 +39,7 @@ parmok: jsr findfreeiocb
lda #<EMFILE ; "too many open files"
seterr: jsr ___directerrno
jsr incsp4 ; clean up stack
lda #$FF
tax
rts ; return -1
jmp returnFFFF
; process the mode argument

View File

@ -40,7 +40,7 @@
.export _cbm_read
.importzp ptr1, ptr2, ptr3, tmp1
.import popax, popa
.import popax, popa, returnFFFF
.import ___oserror
@ -107,7 +107,4 @@ _cbm_read:
; CHKIN failed
@E1: sta ___oserror
lda #$FF
tax
rts ; return -1
jmp returnFFFF

View File

@ -32,7 +32,7 @@
.export _cbm_write
.importzp ptr1, ptr2, ptr3
.import popax, popa
.import popax, popa, returnFFFF
.import ___oserror
@ -88,7 +88,4 @@ _cbm_write:
; Error entry, error code is in A
@E2: sta ___oserror
lda #$FF
tax
rts ; return -1
jmp returnFFFF

View File

@ -13,6 +13,7 @@
.import _strlower, _strlen
.macpack generic
.macpack cpu
; ----------------------------------------------------------------------------
; We will store variables into the register bank in the zeropage. Define
@ -37,7 +38,11 @@ FCount = ptr2
GetFormatChar:
ldy #0
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (Format)
.else
lda (Format),y
.endif
IncFormatPtr:
inc Format
bne @L1
@ -110,7 +115,11 @@ GetIntArg:
lda (ArgList),y
tax
dey
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (ArgList)
.else
lda (ArgList),y
.endif
rts
; ----------------------------------------------------------------------------
@ -135,9 +144,9 @@ ReadInt:
pha ; Save digit value
lda ptr1
ldx ptr1+1
asl ptr1
asl a
rol ptr1+1 ; * 2
asl ptr1
asl a
rol ptr1+1 ; * 4, assume carry clear
adc ptr1
sta ptr1
@ -265,10 +274,16 @@ Save: lda regbank,y
; Initialize the output counter in the output descriptor to zero
lda #0
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (OutData)
ldy #$01
sta (OutData),y
.else
tay
sta (OutData),y
iny
sta (OutData),y
.endif
; Get the output function from the output descriptor and remember it
@ -338,7 +353,11 @@ MainLoop:
sta (sp),y
dey
lda FCount
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (sp)
.else
sta (sp),y
.endif
jsr CallOutFunc ; Call the output function
; We're back from out(), or we didn't call it. Check for end of string.
@ -551,10 +570,16 @@ CheckCount:
jsr GetIntArg
sta ptr1
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
lda (OutData),y ; Low byte of OutData->ccount
sta (ptr1),y
iny
.endif
lda (OutData),y ; High byte of OutData->ccount
sta (ptr1),y
jmp MainLoop ; Done

View 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

81
libsrc/common/asctime.s Normal file
View 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

View 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

View File

@ -3,7 +3,7 @@
; 2002-10-22, Greg King
;
; 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 {
; int rem, quot;

View File

@ -7,7 +7,7 @@
.export _fclose
.import _close
.import _close, ___directerrno
.importzp ptr1
.include "errno.inc"
@ -31,10 +31,7 @@
; File is not open
lda #EINVAL
jsr ___seterrno
lda #$FF ; Return -1
tax
rts
jmp ___directerrno
; File is open. Reset the flags and close the file.
@ -47,4 +44,3 @@
jmp _close ; Will set errno and return an error flag
.endproc

View File

@ -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
View 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

View File

@ -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
View 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

View File

@ -5,7 +5,7 @@
;
.export _clearerr, _feof, _ferror, _fileno, _fflush
.import return0
.import return0, ___directerrno
.importzp ptr1
.include "_file.inc"
@ -78,10 +78,7 @@ err: rts
; If the file is not valid, fileno must set errno and return -1
error: lda #<EBADF
jsr ___seterrno
lda #$FF
tax
rts
jmp ___directerrno
.endproc
;
@ -89,5 +86,3 @@ error: lda #<EBADF
;
_fflush = return0

View File

@ -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
View 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

View File

@ -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
View 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

View File

@ -20,6 +20,7 @@
.include "_file.inc"
.macpack generic
.macpack cpu
; ------------------------------------------------------------------------
; Code
@ -47,13 +48,21 @@
ldy #_FILE::f_flags
lda (file),y
.if (.cpu .bitand ::CPU_ISET_65SC02)
bit #_FOPEN ; Is the file open?
.else
and #_FOPEN ; Is the file open?
.endif
beq @L1 ; Branch if no
; 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
and #_FERROR
.endif
beq @L2
; File not open or in error state
@ -65,11 +74,19 @@
; 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
and #_FPUSHBACK
.endif
beq @L3
.if (.not .cpu .bitand ::CPU_ISET_65SC02)
lda (file),y
.endif
and #<~_FPUSHBACK
sta (file),y ; file->f_flags &= ~_FPUSHBACK;
inx ; X = 1
@ -118,12 +135,20 @@
; 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.
.if (.cpu .bitand ::CPU_ISET_65SC02)
lda (sp)
sta ptr1
add #1
sta (sp)
ldy #1
.else
ldy #0
lda (sp),y
sta ptr1
add #1
sta (sp),y
iny
.endif
lda (sp),y
sta ptr1+1
adc #0
@ -134,8 +159,12 @@
ldy #_FILE::f_pushback
lda (file),y
.if (.cpu .bitand ::CPU_ISET_65SC02)
sta (ptr1) ; *buf = file->f_pushback;
.else
ldy #0
sta (ptr1),y ; *buf = file->f_pushback;
.endif
; Restore the low byte of count and decrement count by one. This may result
; in count being zero, so check for that.
@ -210,4 +239,3 @@
.bss
save: .res 2
pb: .res 1

View File

@ -8,7 +8,7 @@
.export _fwrite
.import _write
.import pushax, incsp6, addysp, ldaxysp, pushwysp, return0
.import pushax, pusha0, incsp6, addysp, ldaxysp, pushwysp, return0
.import tosumulax, tosudivax
.importzp ptr1
@ -16,6 +16,7 @@
.include "errno.inc"
.include "_file.inc"
.macpack cpu
; ------------------------------------------------------------------------
; Code
@ -33,7 +34,11 @@
ldy #_FILE::f_flags
lda (ptr1),y
.if (.cpu .bitand ::CPU_ISET_65SC02)
bit #_FOPEN
.else
and #_FOPEN ; Is the file open?
.endif
bne @L2 ; Branch if yes
; File not open
@ -45,7 +50,9 @@
; 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
bne @L1
@ -53,8 +60,7 @@
ldy #_FILE::f_fd
lda (ptr1),y
ldx #$00
jsr pushax ; file->f_fd
jsr pusha0 ; file->f_fd
ldy #9
jsr pushwysp ; buf
@ -123,4 +129,3 @@
.bss
file: .res 2

View File

@ -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
View 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

View File

@ -1,73 +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__ gmtime (const time_t* timep)
{
static struct tm timebuf;
time_t t;
/* Check the argument */
if (timep == 0 || (long) (t = *timep) < 0) {
/* Invalid arg */
return 0;
}
/* 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;
}

20
libsrc/common/gmtime.s Normal file
View File

@ -0,0 +1,20 @@
;
; Colin Leroy-Mira, 2024
;
; struct tm* __fastcall__ gmtime (const time_t* timep);
;
.export _gmtime
.import __time_t_to_tm
.import ldeaxi
_gmtime:
cpx #$00 ; Check for null pointer
bne :+
cmp #$00
beq no_pointer
: jsr ldeaxi ; Load value from pointer
jmp __time_t_to_tm ; Convert it
no_pointer:
rts ; A/X already set

29
libsrc/common/localtime.s Normal file
View File

@ -0,0 +1,29 @@
;
; Colin Leroy-Mira, 2024
;
; struct tm* __fastcall__ localtime (const time_t* timep);
;
.export _localtime
.import __time_t_to_tm, __tz
.import ldeaxi, tosaddeax, pusheax
.importzp sreg
_localtime:
cpx #$00 ; Check for null pointer
bne :+
cmp #$00
beq no_pointer
: jsr ldeaxi ; Load value
jsr pusheax ; Push it
lda __tz+1+3
sta sreg+1
lda __tz+1+2
sta sreg
ldx __tz+1+1
lda __tz+1
jsr tosaddeax ; Add _tz.timezone
jmp __time_t_to_tm ; Convert to struct tm
no_pointer:
rts ; A/X already set

View File

@ -131,6 +131,7 @@ _malloc:
sta ptr1
bcc @L1
inc ptr1+1
beq OutOfHeapSpace ; if high byte's 0, we overflowed!
@L1: ldx ptr1+1
bne @L2
cmp #HEAP_MIN_BLOCKSIZE+1
@ -336,4 +337,3 @@ RetUserPtr:
bcc @L9
inx
@L9: rts

View File

@ -1,192 +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>
/*****************************************************************************/
/* 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 */
/*****************************************************************************/
static unsigned char __fastcall__ IsLeapYear (unsigned Year)
/* Returns 1 if the given year is a leap year */
{
return (((Year % 4) == 0) && ((Year % 100) != 0 || (Year % 400) == 0));
}
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;
int Max;
unsigned DayCount;
/* Check if TM is valid */
if (TM == 0) {
/* Invalid data */
goto Error;
}
/* Adjust seconds. */
D = div (TM->tm_sec, 60);
TM->tm_sec = D.rem;
/* Adjust minutes */
if (TM->tm_min + D.quot < 0) {
goto Error;
}
TM->tm_min += D.quot;
D = div (TM->tm_min, 60);
TM->tm_min = D.rem;
/* Adjust hours */
if (TM->tm_hour + D.quot < 0) {
goto Error;
}
TM->tm_hour += D.quot;
D = div (TM->tm_hour, 24);
TM->tm_hour = D.rem;
/* Adjust days */
if (TM->tm_mday + D.quot < 0) {
goto Error;
}
TM->tm_mday += D.quot;
/* 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;
if (TM->tm_year + D.quot < 0) {
goto Error;
}
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 + 1900)) {
Max = 29;
} else {
Max = MonthLength[TM->tm_mon];
}
if (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 + 1900)) {
++TM->tm_yday;
}
/* Calculate days since 1/1/1970. In the complete epoch (1/1/1970 to
** somewhere in 2038) all years dividable by 4 are leap years, so
** dividing by 4 gives the days that must be added cause of leap years.
** (and the last leap year before 1970 was 1968)
*/
DayCount = ((unsigned) (TM->tm_year-70)) * 365U +
(((unsigned) (TM->tm_year-(68+1))) / 4) +
TM->tm_yday;
/* 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;
Error:
/* Error exit */
return (time_t) -1L;
}

476
libsrc/common/mktime.s Normal file
View 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

View File

@ -50,7 +50,6 @@
*/
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
** 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 uppersize;
size_t lowersize;
char err;
register struct usedblock* b; /* points to raw Block */
register struct usedblock* u; /* points to User block */
register struct usedblock* p; /* Points to upper block */
/* Handle requests for zero-sized blocks */
if (size == 0) {
err_einval:
err = EINVAL;
err_out:
*memptr = NULL;
return EINVAL;
return err;
}
/* Test alignment: is it a power of two? There must be only one bit set. */
if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
*memptr = NULL;
return EINVAL;
/* Test alignment: is it a power of two? There must be one and only one bit set. */
if (alignment == 0) {
goto err_einval;
}
if (alignment & (alignment - 1)) {
goto err_einval;
}
/* 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 */
if (b == NULL) {
*memptr = NULL;
return ENOMEM;
err = ENOMEM;
goto err_out;
}
/* Create (and return) a new pointer that points to the user-visible

View File

@ -10,7 +10,7 @@
.import _malloc, _free
.import searchenv, copyenvptr
.import __environ, __envcount, __envsize
.import return0
.import return0, ___directerrno
.import ptr1:zp, ptr2:zp, ptr3:zp, tmp1:zp
.include "errno.inc"
@ -169,10 +169,7 @@ addentry:
; Error entries
nomem: lda #ENOMEM
error: jsr ___seterrno
lda #$FF ; Return -1
tax
rts
error: jmp ___directerrno
.endproc
@ -184,5 +181,3 @@ error: jsr ___seterrno
name: .addr 0 ; Pointer to name
newsize: .byte 0 ; New environment size

View File

@ -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
View 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

View File

@ -7,13 +7,13 @@
.export _strcspn
.import popptr1, _strlen
.importzp ptr1, ptr2, tmp1, tmp2
.importzp ptr1, ptr4, tmp1, tmp2
_strcspn:
jsr _strlen ; get length in a/x and transfer s2 to ptr2
jsr _strlen ; get length in a/x and transfer s2 to ptr4
; Note: It does not make sense to
; have more than 255 test chars, so
; we don't support a high byte here! (ptr2+1 is
; we don't support a high byte here! (ptr4+1 is
; also unchanged in strlen then (important!))
; -> the original implementation also
; ignored this case
@ -38,7 +38,7 @@ checkNext:
iny
check: cpy tmp1 ; compare with length of test character string
beq endOfTestChars
cmp (ptr2),y ; found matching char?
cmp (ptr4),y ; found matching char?
bne checkNext
leave: txa ; restore position of finding

View File

@ -1,85 +1,62 @@
;
; Ullrich von Bassewitz, 18.07.2000
; Colin Leroy-Mira, 05.01.2024
;
; char* __fastcall__ strdup (const char* S);
;
; Note: The code knowns which zero page locations are used by malloc.
; Note: The code knowns which zero page locations are used by malloc,
; memcpy and strlen.
;
.importzp sp, tmp1, ptr4
.import pushax, decsp4, incsp4
.import _strlen, _malloc, _memcpy
.importzp ptr2, ptr3, ptr4, tmp1, tmp2, tmp3
.import _strlen_ptr4, _malloc, _memcpy, pushax
.export _strdup
.macpack cpu
.macpack generic
_strdup:
; Get length (and store source in ptr4)
sta ptr4
stx ptr4+1
stx tmp1 ; Backup high byte, which
jsr _strlen_ptr4 ; strlen may increment
; Since we need some place to store the intermediate results, allocate a
; stack frame. To make this somewhat more efficient, create the stackframe
; as needed for the final call to the memcpy function.
pha ; decsp will destroy A (but not X)
jsr decsp4 ; Target/source
; Store the pointer into the source slot
ldy #1
txa
sta (sp),y
pla
.if (.cpu .bitand CPU_ISET_65SC02)
sta (sp)
; Add null byte for terminator
.if (.cpu .bitand ::CPU_ISET_65SC02)
inc a
.else
dey
sta (sp),y
clc
adc #1
.endif
; Get length of S (which is still in a/x)
jsr _strlen
; Calculate strlen(S)+1 (the space needed)
add #1
bcc @L1
bne :+
inx
; Save the space we're about to allocate in ptr4
@L1: sta ptr4
stx ptr4+1
; Allocate memory. _malloc will not use ptr4
; Store length
: sta tmp2
stx tmp3
; Allocate memory
jsr _malloc
; Store the result into the target stack slot
ldy #2
sta (sp),y ; Store low byte
sta tmp1
txa ; Get high byte
iny
sta (sp),y ; Store high byte
; Check for a NULL pointer
ora tmp1
; Check for NULL
bne :+
cpx #$00
beq OutOfMemory
; Copy the string. memcpy will return the target string which is exactly
; what we need here. It will also drop the allocated stack frame.
; Push dest
: jsr pushax
; Push source
lda ptr4
ldx ptr4+1 ; Load size
jmp _memcpy ; Copy string, drop stackframe
ldx tmp1
jsr pushax
; Out of memory, return NULL (A = 0)
; Push length
lda tmp2
ldx tmp3
; Copy and return the dest pointer
jmp _memcpy
OutOfMemory:
tax
jmp incsp4 ; Drop stack frame
rts

View File

@ -2,19 +2,20 @@
; Ullrich von Bassewitz, 31.05.1998
;
; Note: strspn & strcspn call internally this function and rely on
; the usage of only ptr2 here! Keep in mind when appling changes
; the usage of only ptr4 here! Keep in mind when appling changes
; and check the other implementations too!
;
; size_t __fastcall__ strlen (const char* s);
;
.export _strlen
.importzp ptr2
.export _strlen, _strlen_ptr4
.importzp ptr4
.macpack cpu
_strlen:
sta ptr2 ; Save s
stx ptr2+1
sta ptr4 ; Save s
stx ptr4+1
_strlen_ptr4:
.if (.cpu .bitand ::CPU_ISET_HUC6280)
clx
cly
@ -27,11 +28,11 @@ _strlen:
.endif
.endif
L1: lda (ptr2),y
L1: lda (ptr4),y
beq L9
iny
bne L1
inc ptr2+1
inc ptr4+1
inx
bne L1

View File

@ -7,13 +7,13 @@
.export _strspn
.import popptr1, _strlen
.importzp ptr1, ptr2, tmp1, tmp2
.importzp ptr1, ptr4, tmp1, tmp2
_strspn:
jsr _strlen ; get length in a/x and transfer s2 to ptr2
jsr _strlen ; get length in a/x and transfer s2 to ptr4
; Note: It does not make sense to
; have more than 255 test chars, so
; we don't support a high byte here! (ptr2+1 is
; we don't support a high byte here! (ptr4+1 is
; also unchanged in strlen then (important!))
; -> the original implementation also
; ignored this case
@ -38,7 +38,7 @@ checkNext:
iny
check: cpy tmp1 ; compare with length of test character string
beq leave
cmp (ptr2),y ; found matching char?
cmp (ptr4),y ; found matching char?
bne checkNext
foundTestChar:

View File

@ -62,10 +62,6 @@
; File is not open or the character is invalid
error: lda #EINVAL
jsr ___seterrno
lda #$FF ; Return -1
tax
rts
jmp ___directerrno
.endproc

View File

@ -6,7 +6,7 @@
; void BitOtherClip (void *proc1, void* proc2, char skipl, char skipr, int skipy,
; 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)
; proc2 is called before reading each byte which is not pattern (code >219)

View File

@ -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.
lda #%00011101
lda #PAREN|RESETERR|TXOPEN|PAREVEN ; #%00011101
sta SERCTL
; Clear all pending interrupts.

View File

@ -18,7 +18,7 @@
.import ldeaxysp, decsp2, pushax, incsp8
.import tosandeax,decax1,tosdiveax,axlong,ldaxysp
.import lynxskip0, lynxblock,tosasreax
.import __BLOCKSIZE__
.import __BANK0BLOCKSIZE__
.importzp _FileCurrBlock
.segment "CODE"
@ -32,15 +32,15 @@
jsr ldeaxysp
jsr pusheax
ldx #$00
lda #<(__BLOCKSIZE__/1024 + 9)
lda #<(__BANK0BLOCKSIZE__/1024 + 9)
jsr tosasreax
sta _FileCurrBlock
jsr lynxblock
ldy #$05
jsr ldeaxysp
jsr pusheax
lda #<(__BLOCKSIZE__-1)
ldx #>(__BLOCKSIZE__-1)
lda #<(__BANK0BLOCKSIZE__-1)
ldx #>(__BANK0BLOCKSIZE__-1)
jsr axlong
jsr tosandeax
eor #$FF

View File

@ -17,7 +17,7 @@
.include "extzp.inc"
.export lynxskip0, lynxread0
.export lynxblock
.import __BLOCKSIZE__
.import __BANK0BLOCKSIZE__
.code
@ -88,7 +88,7 @@ lynxblock:
lda __iodat
sta IODAT
stz _FileBlockByte
lda #<($100-(>__BLOCKSIZE__))
lda #<($100-(>__BANK0BLOCKSIZE__))
sta _FileBlockByte+1
ply
plx

View File

@ -73,7 +73,12 @@ SER_UNINSTALL:
; Must return an SER_ERR_xx code in a/x.
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
lda #SER_ERR_OK
.assert SER_ERR_OK = 0, error
@ -108,17 +113,17 @@ SER_OPEN:
stz TxPtrIn
stz TxPtrOut
; clock = 8 * 15625
lda #%00011000
sta TIM4CTLA
ldy #SER_PARAMS::BAUDRATE
lda (ptr1),y
; Source period is 1 us
ldy #%00011000 ; ENABLE_RELOAD|ENABLE_COUNT|AUD_1
ldx #1
cmp #SER_BAUD_62500
beq setbaudrate
ldx #2
ldx #3
cmp #SER_BAUD_31250
beq setbaudrate
@ -134,6 +139,10 @@ SER_OPEN:
cmp #SER_BAUD_2400
beq setbaudrate
ldx #68
cmp #SER_BAUD_1800
beq setbaudrate
ldx #103
cmp #SER_BAUD_1200
beq setbaudrate
@ -142,65 +151,22 @@ SER_OPEN:
cmp #SER_BAUD_600
beq setbaudrate
; clock = 6 * 15625
ldx #%00011010
stx TIM4CTLA
; Source period is 8 us
ldy #%00011011 ; ENABLE_RELOAD|ENABLE_COUNT|AUD_8
ldx #12
cmp #SER_BAUD_7200
beq setbaudrate
ldx #25
cmp #SER_BAUD_3600
beq setbaudrate
ldx #207
stx TIM4BKUP
; clock = 4 * 15625
ldx #%00011100
ldx #51
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
lda #SER_ERR_BAUD_UNAVAIL
ldx #0 ; return value is char
rts
setprescaler:
stx TIM4CTLA
bra baudsuccess
setbaudrate:
sty TIM4CTLA
stx TIM4BKUP
baudsuccess:
ldx #TxOpenColl|ParEven
ldx #TXOPEN|PAREVEN
stx contrl
ldy #SER_PARAMS::DATABITS ; Databits
lda (ptr1),y
@ -218,15 +184,15 @@ baudsuccess:
beq checkhs
cmp #SER_PAR_SPACE
bne @L0
ldx #TxOpenColl
ldx #TXOPEN
stx contrl
bra checkhs
@L0:
ldx #TxParEnable|TxOpenColl|ParEven
ldx #PAREN|TXOPEN|PAREVEN
stx contrl
cmp #SER_PAR_EVEN
beq checkhs
ldx #TxParEnable|TxOpenColl
ldx #PAREN|TXOPEN
stx contrl
checkhs:
ldx contrl
@ -234,15 +200,27 @@ checkhs:
ldy #SER_PARAMS::HANDSHAKE ; Handshake
lda (ptr1),y
cmp #SER_HS_NONE
beq redeye_ok
cmp #SER_HS_SW ; Software handshake will check for connected redeye
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 contrl
ora #RxIntEnable|ResetErr
ora #RXINTEN|RESETERR ; Turn on interrupts for receive
sta SERCTL
lda #SER_ERR_OK
.assert SER_ERR_OK = 0, error
tax
rts
invparameter:
lda #SER_ERR_INIT_FAILED
ldx #0 ; return value is char
@ -264,8 +242,8 @@ GetByte:
ldy RxPtrOut
lda RxBuffer,y
inc RxPtrOut
sta (ptr1)
ldx #$00
sta (ptr1,x)
txa ; Return code = 0
rts
@ -279,24 +257,26 @@ SER_PUT:
ina
cmp TxPtrOut
bne PutByte
lda #SER_ERR_OVERFLOW
ldx #0 ; return value is char
rts
PutByte:
ldy TxPtrIn
txa
sta TxBuffer,y
inc TxPtrIn
bit TxDone
bmi @L1
bit TxDone ; Check bit 7 of TxDone (TXINTEN)
bmi @L1 ; Was TXINTEN already set?
php
sei
lda contrl
ora #TxIntEnable|ResetErr
sta SERCTL ; Allow TX-IRQ to hang RX-IRQ
lda contrl ; contrl does not include RXINTEN setting
ora #TXINTEN|RESETERR
sta SERCTL ; Allow TX-IRQ to hang RX-IRQ (no receive while transmitting)
sta TxDone
plp
plp ; Restore processor and interrupt enable
@L1:
lda #SER_ERR_OK
.assert SER_ERR_OK = 0, error
@ -308,9 +288,9 @@ PutByte:
; Must return an SER_ERR_xx code in a/x.
SER_STATUS:
ldy SerialStat
lda SerialStat
sta (ptr1)
ldx #$00
sta (ptr1,x)
txa ; Return code = 0
rts
@ -342,48 +322,56 @@ SER_IRQ:
@L0:
bit TxDone
bmi @tx_irq ; Transmit in progress
ldx SERDAT
lda SERCTL
and #RxParityErr|RxOverrun|RxFrameErr|RxBreak
beq @rx_irq
ldx SERDAT ; Read received data
lda contrl
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
bit #RxBreak
bit #RXBRK ; Check for break signal
beq @noBreak
stz TxPtrIn ; Break received - drop buffers
stz TxPtrOut
stz RxPtrIn
stz RxPtrOut
@noBreak:
lda contrl
ora #RxIntEnable|ResetErr
sta SERCTL
lda #$10
sta INTRST
bra @IRQexit
bra @exit0
@rx_irq:
tya
bne @2 ; Parity was enabled so no marker bit check needed
lda contrl
ora #RxIntEnable|ResetErr
sta SERCTL
eor SERCTL ; Should match current parity bit
and #PARBIT ; Check for mark or space value
bne @exit0
@2:
txa
ldx RxPtrIn
sta RxBuffer,x
txa
inx
@cont0:
cpx RxPtrOut
beq @1
stx RxPtrIn
lda #SERIAL_INTERRUPT
sta INTRST
bra @IRQexit
@1:
sta RxPtrIn
lda #$80
tsb SerialStat
bra @exit0
@tx_irq:
ldx TxPtrOut ; Has all bytes been sent?
ldx TxPtrOut ; Have all bytes been sent?
cpx TxPtrIn
beq @allSent
@ -393,24 +381,24 @@ SER_IRQ:
@exit1:
lda contrl
ora #TxIntEnable|ResetErr
ora #TXINTEN|RESETERR
sta SERCTL
lda #SERIAL_INTERRUPT
sta INTRST
bra @IRQexit
@allSent:
lda SERCTL ; All bytes sent
bit #TxEmpty
bit #TXEMPTY
beq @exit1
bvs @exit1
stz TxDone
@exit0:
lda contrl
ora #RxIntEnable|ResetErr
ora #RXINTEN|RESETERR ; Re-enable receive interrupt
sta SERCTL
@IRQexit:
lda #SERIAL_INTERRUPT
sta INTRST
@IRQexit:
clc
rts

Some files were not shown because too many files have changed in this diff Show More