1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-05-31 18:41:30 +00:00

Compare commits

...

463 Commits

Author SHA1 Message Date
Karol Stasiak
d8c11a9c50 Minor optimizations 2023-02-03 14:46:01 +01:00
Karol Stasiak
ee47ccef5a fix z80 indexing in hardwritten assembly (#137) 2023-01-27 18:27:53 +01:00
Karol Stasiak
24de2f7530 enable tests of identity page 2023-01-27 18:19:19 +01:00
Karol Stasiak
1beb695151 more tests 2023-01-27 18:17:41 +01:00
Karol Stasiak
9229092309 random minor stuff 2023-01-27 18:16:25 +01:00
Karol Stasiak
ca7166d1ae oops 2023-01-27 18:16:02 +01:00
Karol Stasiak
1594d63a9a Add a command line flag for identity page 2023-01-27 18:15:40 +01:00
Karol Stasiak
75cc34663c Z80: fix an optimization 2023-01-27 18:15:10 +01:00
Karol Stasiak
f4d2fdd370 6502: use identity page for maths 2023-01-27 18:14:50 +01:00
Karol Stasiak
29c1e3f2a6 6502 and Z80: Optimize optimizations 2023-01-27 18:13:21 +01:00
Karol Stasiak
e9cfec54b5 Various 6502 optimization fixes 2023-01-27 17:34:09 +01:00
Karol Stasiak
1bc1ab3539 Fix some codegen bugs on 6502 2023-01-27 17:00:29 +01:00
Karol Stasiak
6f294d6dec Fix -fbounds-checking 2022-02-12 02:13:30 +01:00
Karol Stasiak
9866c974ad Don't apply Constant index offset propagation in decimal mode 2022-02-12 02:12:55 +01:00
Karol Stasiak
ef2f5b5918 Add test 2022-02-11 21:48:24 +01:00
Karol Stasiak
a70a1c0e6b Consider kernal_interrupt functions as entry points 2022-02-11 21:48:13 +01:00
Karol Stasiak
790c836771 Fix handling of non-top-level return dispatch statements 2022-02-11 21:47:39 +01:00
Karol Stasiak
6af84d1628 Optimize the optimizer 2022-02-08 14:42:30 +01:00
Karol Stasiak
7b205a2754 Allow multiple -D options 2022-02-08 13:21:26 +01:00
Karol Stasiak
d23fe1756e Switch to snapshot versioning 2022-02-08 13:20:15 +01:00
Karol Stasiak
3b3ee1bc55 Version 0.3.30 2021-12-15 16:01:46 +01:00
Karol Stasiak
fb30075ea5 Update CHANGELOG 2021-12-15 15:54:00 +01:00
Karol Stasiak
b5084cd180 More tests 2021-12-15 15:53:49 +01:00
Karol Stasiak
b1a2be5574 6809: Fix constant condition compilation 2021-11-22 01:58:09 +01:00
Karol Stasiak
a260d0a806 CBM BASIC loader should use the actual address of main (fixes #111) 2021-11-12 02:45:53 +01:00
Karol Stasiak
38ad919ed9 Show the positions of unevaluated constants 2021-11-12 02:44:58 +01:00
Karol Stasiak
34ef8b8de9 Better evaluation of the if function in constants 2021-11-12 02:44:20 +01:00
Karol Stasiak
f676e74e38 Macro improvements:
– allow local constants in macros
– allow untyped macro parameters with void
– treat the name of a function as a pointer to it
– add this.function local alias (#118)
2021-11-12 02:10:07 +01:00
Karol Stasiak
c9313e5dbe Add support for ld65 label file format (#128) 2021-11-12 00:47:12 +01:00
Karol Stasiak
73a223b9b6 Add support for Mesen label file format by tracking file-relative positions of segments (#128) 2021-11-03 21:48:45 +01:00
Karol Stasiak
b168818bab Report every hole in the output 4 bytes or larger; count total free bytes in the entire bank 2021-09-21 00:43:29 +02:00
Karol Stasiak
effa723863 Never commit .labels files again 2021-09-21 00:21:21 +02:00
Karol Stasiak
b2ab3dbeab Clean accidentally commited labels file 2021-09-21 00:20:54 +02:00
Karol Stasiak
c9ef5e636b Add raw label file format 2021-09-21 00:09:59 +02:00
Karol Stasiak
fc2f0782c5 Update Notepad++ syntax 2021-09-20 00:56:04 +02:00
Karol Stasiak
f0e22f02a6
Merge pull request #126 from mookiexl/master
Update x16_experimental.ini
2021-09-18 14:23:02 +02:00
Karol Stasiak
b2291d1cb2
Merge pull request #122 from retrac0/master
gb library code updates to current syntax
2021-09-18 13:21:15 +02:00
Karol Stasiak
166acf2b18 R800 support 2021-09-18 00:36:16 +02:00
Karol Stasiak
7530b382a8 Fix array fields in certain contexts 2021-09-17 22:19:39 +02:00
Karol Stasiak
b66435d06b Fix EasyFlash switch_hirom (fixes #121) 2021-09-13 15:10:11 +02:00
Karol Stasiak
0c8951d015 Fix unused variable elimination in for-array statements (fixes #125) 2021-09-13 09:27:34 +02:00
Karol Stasiak
84dde8589c Allow spaces after the array keyword (fixes #120) 2021-09-13 09:26:54 +02:00
Karol Stasiak
3b0aa9a425 Fixes for flag boolean types (fixes #123) 2021-09-13 09:26:27 +02:00
mookiexl
1b8de990a5 Update x16_experimental.ini 2021-08-19 14:37:20 +02:00
mookiexl
b060fc599b Update x16_experimental.ini
$00-$01 are used for bank switching.
Unintentional write to those will crash the machine.
2021-08-16 16:06:28 +02:00
Karol Stasiak
90e5360bfd Related to #119:
– Detection of simple byte overflow cases.
– Optimization of 8×8→16 multiplication on 6809.
– Multiplication optimizations on Z80.
2021-08-06 21:01:03 +02:00
Joel Heikkila
bbf430a1c7 update gb lib code to current syntax for example/ 2021-07-11 18:15:39 -04:00
Karol Stasiak
7f6a0c6b0d Fix documentation of .loword and .hiword 2021-06-29 02:39:23 +02:00
Karol Stasiak
7f0def54bc Improvements for 65CE02 assembly (fixes #116) 2021-06-29 02:29:30 +02:00
Karol Stasiak
faf97cee1f Don't call valid control characters invalid 2021-06-29 02:29:12 +02:00
Karol Stasiak
da862069a7 Fix for volatile fields 2021-06-29 02:28:32 +02:00
Karol Stasiak
431a25d325 Internal support for pointers to volatile objects; add volatile fields (closes #112) 2021-06-21 14:20:24 +02:00
Karol Stasiak
73beafd65e Support for expressions in file() (fixes #114) 2021-06-21 14:18:17 +02:00
Karol Stasiak
307ad90ecf 6809: Improve flow analysis and add few more optimizations 2021-06-21 14:15:40 +02:00
Karol Stasiak
2e592a2331 Correct address for sid_v1_sr (fixing #115) 2021-06-21 14:12:33 +02:00
Karol Stasiak
91c9b42f3d Switch to snapshot versioning 2021-06-21 14:11:56 +02:00
Karol Stasiak
144da70594 Version 0.3.28 2021-05-24 00:17:51 +02:00
Karol Stasiak
4f6eefab79 Officially deprecate old decimal operators 2021-05-23 22:31:11 +02:00
Karol Stasiak
ca35367974 Tease floating-point numbers 2021-05-16 23:32:33 +02:00
Karol Stasiak
2065c3b4ac Fix 6809 under native-image 2021-05-16 23:32:18 +02:00
Karol Stasiak
9028d55a7e Various optimization improvements and fixes, mostly for 6809 2021-05-16 23:31:52 +02:00
Karol Stasiak
21d4d3252f Remove debugging statements 2021-05-16 00:40:12 +02:00
Karol Stasiak
45ad049a51 Update CHANGELOG 2021-05-08 00:46:37 +02:00
Karol Stasiak
0172e29bb2 Underscores in numeric literals. Fix parsing of Intel hex constants starting with 0B. 2021-05-08 00:42:06 +02:00
Karol Stasiak
ffb46c4250 Optimize some bitmask operations 2021-05-05 02:58:57 +02:00
Karol Stasiak
c51c08ad56 6809: Fix and improve optimizations 2021-05-05 02:58:28 +02:00
Karol Stasiak
fcdad413b0 #110 Add a warning for comparisons between bytes and pointers. 2021-05-05 00:59:54 +02:00
Karol Stasiak
63edce28c4 Update CHANGELOG 2021-04-24 01:21:03 +02:00
Karol Stasiak
1f318a2a0e 6502: Optimize sign extension 2021-04-24 01:18:34 +02:00
Karol Stasiak
1bcb6d5010 Fix sign extension when using pointers 2021-04-24 01:18:21 +02:00
Karol Stasiak
510f85960c Fix optimizations of unused labels 2021-04-24 01:18:01 +02:00
Karol Stasiak
8412075175 Fix pointer type compatibility checks 2021-04-24 01:13:59 +02:00
Karol Stasiak
e25df3d1b3 Parser optimizations again 2021-04-19 01:06:51 +02:00
Karol Stasiak
b71d058c6a Parser optimizations 2021-04-18 23:48:23 +02:00
Karol Stasiak
bf273456a3 Fix #107 2021-03-20 01:25:27 +01:00
Karol Stasiak
062483971a Fix #107 (syntax errors in stdlib, overpanicky statement preprocessor) 2021-03-20 01:23:51 +01:00
Karol Stasiak
1e4a193741 Optimization hints 2021-03-15 00:44:14 +01:00
Karol Stasiak
2468d8cca5 Update changelog 2021-03-13 21:42:52 +01:00
Karol Stasiak
58b5b6ff28 Fix #106: the current working directory should be always included in the include path 2021-03-13 21:42:11 +01:00
Karol Stasiak
8aac3bc329 Allow character literals in preprocessor 2021-03-13 21:40:38 +01:00
Karol Stasiak
24eac6708b Fix escape sequences in many encodings 2021-03-13 21:40:18 +01:00
Karol Stasiak
66fc1d3984 Add several more encodings 2021-03-13 21:39:48 +01:00
Karol Stasiak
0bbdc348e7 Switch to snapshot versioning 2021-03-13 02:19:29 +01:00
Karol Stasiak
15a32a4caf Version 0.3.26 2021-03-01 10:25:38 +01:00
Karol Stasiak
e8f5667faa Move apple2_prodos module documentation 2021-02-28 20:53:22 +01:00
Karol Stasiak
03bc5894aa
Merge pull request #103 from retrac0/master
outlined ProDOS API in docs
2021-02-28 20:43:01 +01:00
Karol Stasiak
bd9ff2f66d Unfinished test 2021-02-28 19:38:25 +01:00
Karol Stasiak
a111af384e Unify assembly parameter evaluation 2021-02-27 00:08:31 +01:00
Karol Stasiak
6f2c8cd991 Show unused space in the middle of segments 2021-02-26 23:20:32 +01:00
Karol Stasiak
a0c2eaabcf Struct array fields performance improvements 2021-02-26 23:13:16 +01:00
Karol Stasiak
83393d49f1 Z80: optimization improvements 2021-02-26 23:12:43 +01:00
Karol Stasiak
84d707b932 Cosmetic improvements 2021-02-26 23:10:08 +01:00
Karol Stasiak
f01879e4a3 Use local labels in m6809_math 2021-02-26 23:05:29 +01:00
Joel Heikkila
efb3d3c7c9 outlined ProDOS API in docs 2021-02-25 13:19:37 -05:00
Karol Stasiak
22bd6ac443 Update changelog 2021-02-24 03:05:09 +01:00
Karol Stasiak
ffa0ffb899 Allow enabling/disabling warnings individually 2021-02-24 03:04:53 +01:00
Karol Stasiak
3155d7a571 Improve error message 2021-02-24 02:32:24 +01:00
Karol Stasiak
ba7c5b507c Optimize constant resolution 2021-02-24 02:32:13 +01:00
Karol Stasiak
196ad6542f Allow refering to labels from other functions in assembly (fixes #101) 2021-02-24 02:32:00 +01:00
Karol Stasiak
ff6106a838 Fix module name resolution (#89) 2021-02-24 02:31:20 +01:00
Karol Stasiak
9ebbbdc022 Summarize the compilation 2021-02-24 02:30:28 +01:00
Karol Stasiak
ab9cdf7ad5 Fix deduplication problems with trampolined functions 2021-02-24 02:29:47 +01:00
Karol Stasiak
4ff6120702 Warn about data not being included in the output 2021-02-24 02:28:29 +01:00
Karol Stasiak
521b73d0d3 Array fields for structs and unions (see #87) 2021-02-22 23:23:00 +01:00
Karol Stasiak
478b2eefbd Update changelog 2021-02-18 03:26:24 +01:00
Karol Stasiak
3d57421959
Merge pull request #100 from retrac0/apple2
ProDOS library + some small Apple II terminal fixes
2021-02-18 01:33:47 +01:00
Karol Stasiak
78c29c784d
Merge pull request #102 from agg23/agg23/OverflowErrors
Added position logging to overflow errors
2021-02-18 01:30:09 +01:00
Karol Stasiak
25adb05229 Fix typeof 2021-02-18 01:29:27 +01:00
Karol Stasiak
bb46b1e7e9 Update documentation 2021-02-18 00:51:07 +01:00
Karol Stasiak
7c60a89776 Signed multiplication 2021-02-18 00:39:14 +01:00
Karol Stasiak
02031da61a Correctly optimize variables around macros 2021-02-18 00:38:51 +01:00
Karol Stasiak
d20cc677bb The typeof builtin function 2021-02-18 00:38:30 +01:00
Karol Stasiak
2beabb7bed Improvements to constant folding 2021-02-18 00:36:13 +01:00
Karol Stasiak
fb71f88343 8080: Correctly compile sbytes to BC 2021-02-18 00:35:02 +01:00
Adam Gastineau
7689afb5d6 Added position logging to overflow errors 2021-02-03 11:51:41 -08:00
Karol Stasiak
958c1c09e7 #98: Warning about a missing call to init_rw_memory 2021-02-03 09:58:39 +01:00
Karol Stasiak
919f11af2e #101: Allow using local labels in all assembly instructions and all assembly expressions 2021-02-03 09:50:44 +01:00
Karol Stasiak
9c7e946f4c Allow labels in assembly on the same line (see #101) 2021-02-03 09:49:17 +01:00
Karol Stasiak
32b98750a9 Warn about non-volatile spinlocks (see #95) 2021-02-03 09:46:09 +01:00
Joel Heikkila
ef34f534f9 first attempt at a ProDOS library for the Apple II 2021-02-02 23:33:45 -05:00
Joel Heikkila
3a2e29888d some documentation of what I've tested 2021-01-25 20:29:54 -05:00
Joel Heikkila
d6deb81166 change monitor address to not print prompt 2021-01-25 20:15:18 -05:00
Joel Heikkila
394ac63805 0x80 + 0x0D is a2 newline 2021-01-25 16:13:59 -05:00
Karol Stasiak
42f6efc9bd Switch to snapshot versioning 2021-01-13 19:57:52 +01:00
Karol Stasiak
8b0c026bf7 Update changelog 2021-01-13 19:57:17 +01:00
Karol Stasiak
c1959b356f Make all constants referring to segments match their equivalents from the platform definition (see #87) 2021-01-13 19:55:11 +01:00
Karol Stasiak
499e650752 Define and document more magic suffixes and constants (see #87) 2021-01-13 19:35:11 +01:00
Karol Stasiak
fe4f0dcfd9 6502: Optimize more jumps in place 2021-01-13 19:26:17 +01:00
Karol Stasiak
c6932da6b3 Update changelog 2021-01-13 14:39:32 +01:00
Karol Stasiak
600bfce0c1 Allow new lines after = 2021-01-13 14:38:59 +01:00
Karol Stasiak
9feda54d92 Optimize word shifts by 7–12 bits 2021-01-13 14:31:20 +01:00
Karol Stasiak
91699b64c6 Less useless logging 2021-01-13 14:18:41 +01:00
Karol Stasiak
2a5933e115 6502: Fix sbyte to word promotion in some contexts 2021-01-13 14:18:28 +01:00
Karol Stasiak
bd8078cc47
Merge pull request #90 from agg23/agg23/RemovedOptimizationHintPrint
Removed optimization hint debug println statements
2021-01-02 01:06:31 +01:00
Adam Gastineau
30216d0be6 Removed optimization hint debug println statements 2021-01-01 14:52:37 -08:00
Karol Stasiak
181332e238 Version 0.3.24 2020-12-02 00:54:52 +01:00
Karol Stasiak
90a9538936 Various optimizations 2020-12-01 18:18:56 +01:00
Karol Stasiak
4a529b5ddc Fix typos/grammar 2020-12-01 14:26:47 +01:00
Karol Stasiak
7962a1d083 Point at the end of the line if the error is something missing at the end of the line 2020-12-01 03:21:04 +01:00
Karol Stasiak
52c9da36b8 Fix GraalVM NPE when getting a character name 2020-12-01 03:20:31 +01:00
Karol Stasiak
8dfad735ab Tiny formatting fix 2020-12-01 03:19:47 +01:00
Karol Stasiak
cba145d674 Better error messages for variable definitions in macros (#77) 2020-12-01 03:19:38 +01:00
Karol Stasiak
145f2ed711 Update changelog 2020-11-19 18:56:49 +01:00
Karol Stasiak
f2f53a4b28 Configurable entry point for ZX Spectrum, Z1013, TRS-80 and CoCo (#78) 2020-11-19 18:47:50 +01:00
Karol Stasiak
7e45967b0c Allow emitting addresses of labels in the output (#78) 2020-11-19 18:33:51 +01:00
Karol Stasiak
c8e32a876f Fix endaddr+N output 2020-11-19 18:21:08 +01:00
Karol Stasiak
b2d2c3e005 Don't emit labels that are not necessary; fix the __heap_start symbol. 2020-11-18 23:08:45 +01:00
Karol Stasiak
dc087ed887 Better error messages for arays without sizes 2020-11-18 23:08:09 +01:00
Karol Stasiak
97c7d0ffed Basic groundwork for optimization hint support 2020-11-18 22:37:58 +01:00
Karol Stasiak
385b2fd40b Fix function pointers (fixes #86) 2020-11-18 09:34:02 +01:00
Karol Stasiak
fc7643c416 Interrupt handler pointer types 2020-11-11 00:28:21 +01:00
Karol Stasiak
91409504fb Small inlining fix 2020-11-11 00:27:52 +01:00
Karol Stasiak
cd6b789416 Document explicit bool conversions 2020-11-11 00:27:29 +01:00
Karol Stasiak
f4a3601d6e 8080: Fix word negation 2020-11-11 00:25:39 +01:00
Karol Stasiak
f39810793b Use skipTests instead of includeTests 2020-11-02 13:47:16 +01:00
Karol Stasiak
831be03167
Merge pull request #82 from agg23/SBTIncludeTestFlags
Improved #36: Added compile flags for enabling tests
2020-11-02 13:37:58 +01:00
Adam Gastineau
af565b581a Fixed only some test dependencies being properly emitted 2020-10-30 22:14:37 -07:00
Karol Stasiak
4a7166b9e0
Merge pull request #84 from zbyti/master
A8 fixed example code
2020-10-30 23:22:42 +01:00
zbyti
45b4a5dfe3 A8 fixed code 2020-10-30 16:08:29 +01:00
Adam Gastineau
d483dd1994 Improved #36: Added compile flags for enabling tests 2020-10-27 19:52:12 -07:00
Karol Stasiak
4a09a80db0
Merge pull request #79 from zbyti/master
refactor and MPT player examble
2020-10-25 02:01:47 +01:00
zbyti
2ce1781e91 refator 2020-10-06 00:51:50 +02:00
zbyti
d76ae3ff9e refator 2020-10-06 00:50:50 +02:00
zbyti
758f0945f9 refactor 2020-10-06 00:42:19 +02:00
zbyti
d0154253ea .nfo files added 2020-10-06 00:39:20 +02:00
zbyti
85829102b8 .nfo files added 2020-10-06 00:36:41 +02:00
zbyti
8a4e65b365 A8 CMC Player with sample music 2020-10-05 23:17:35 +02:00
zbyti
838ef0d1eb refactor and MPT player examble 2020-10-05 22:33:22 +02:00
Karol Stasiak
963fae8275 Various documentation updates 2020-10-05 22:20:08 +02:00
Karol Stasiak
e94ccd164f Use POKEY for random seed on Atari 2020-09-30 01:51:36 +02:00
Karol Stasiak
a00e10382d Implement readline and readword for VIC-20 2020-09-30 01:37:00 +02:00
Karol Stasiak
24c0e8a8ee Fix typo 2020-09-30 01:36:13 +02:00
Karol Stasiak
5d09410350 Document TRS-80 and Z1013 library support 2020-09-30 01:07:56 +02:00
Karol Stasiak
70da293fce
Merge pull request #76 from zbyti/master
ANTIC Display List Instruction Set constans & some refactor
2020-09-29 23:02:34 +02:00
Karol Stasiak
c2e9acd3f3 Update CHANGELOG and READMEs 2020-09-29 22:57:48 +02:00
Karol Stasiak
d45fe42d17 Add Robotron Z1013 support 2020-09-29 22:57:27 +02:00
Karol Stasiak
889a4f94be All things mentioned in segment layouts should be considered used. 2020-09-29 22:49:15 +02:00
Karol Stasiak
c7008f4414 New output elements: literal ASCII strings and space-padded program name 2020-09-29 22:48:50 +02:00
zbyti
802424316c ANTIC Display List BASIC fix 2020-09-28 22:54:58 +02:00
zbyti
f9fc001c9a ANTIC Display List BASIC modes forrmating 2020-09-28 22:17:34 +02:00
zbyti
cc1adee4f1 ANTIC Display List BASIC modes 2020-09-28 22:15:39 +02:00
zbyti
362d682c11 ANTIC Display List Instruction Set table typo 2020-09-28 21:54:35 +02:00
zbyti
a4b27f73e7 ANTIC Display List Instruction Set constans 2020-09-28 21:49:44 +02:00
zbyti
1b6b49889b A8 landscape refactor 2020-09-28 19:19:35 +02:00
Karol Stasiak
2d7c365b20 TSR-80 newline is just 0x0D 2020-09-27 18:58:46 +02:00
Karol Stasiak
3af4fcffa9 Z80: Add SLS as an alternate mnemonic for SLL 2020-09-27 18:46:19 +02:00
Karol Stasiak
3a9be16107 Add TRS-80 Model 1 and 3 support 2020-09-26 23:52:49 +02:00
Karol Stasiak
3702002541 Fix header 2020-09-26 19:56:56 +02:00
Karol Stasiak
a15c9088ee
Merge pull request #75 from zbyti/master
A8 examples readme new arrangement
2020-09-26 19:56:10 +02:00
zbyti
6b3f43393e A8 Landscape refactor 2020-09-26 01:14:08 +02:00
zbyti
2823b7fde0 A8 examples readme new arrangement 2020-09-26 01:02:07 +02:00
Karol Stasiak
e0572fa3aa
Merge pull request #74 from zbyti/master
A8 examples
2020-09-26 00:14:17 +02:00
zbyti
3364f8ab10 Quatari Landscape refactor 2020-09-25 11:20:16 +02:00
zbyti
560ed09439 Quatari Landscape refactor 2020-09-25 09:45:48 +02:00
zbyti
dc2def7e72 A8 my last examples 2020-09-25 03:08:33 +02:00
Karol Stasiak
9f1309c119
Merge pull request #71 from zbyti/master
A8 new examples
2020-09-24 01:25:04 +02:00
Karol Stasiak
888f7a0fdb Fix documentation (fixes #72) 2020-09-23 23:21:35 +02:00
zbyti
1d046f26e3 A8 Grand Ttheft Antic refactor 2020-09-23 23:17:01 +02:00
zbyti
a4de573593 A8 Grand Ttheft Antic 2020-09-23 23:09:15 +02:00
zbyti
433066fedd comment fix 2020-09-23 20:18:04 +02:00
zbyti
7182f32032 more life in empty space 2020-09-23 00:04:22 +02:00
zbyti
86ae6de325 A8 horizontal stars done on one missile 2020-09-22 19:34:29 +02:00
Karol Stasiak
9f40fc5066 Add some trivial test case 2020-09-22 17:59:50 +02:00
Karol Stasiak
b87c40fc9c Migration from Nashorn to GraalJS 2020-09-22 17:59:32 +02:00
Karol Stasiak
1decf2f087 65816: Various codegen bugfixes 2020-09-22 17:59:14 +02:00
Karol Stasiak
c9f602b049 65816: Emulator bugfixes 2020-09-22 17:58:34 +02:00
Karol Stasiak
030531161e Update changelog 2020-09-21 09:10:50 +02:00
Karol Stasiak
7de23ddd44 Allow the : operator in const-pure functions 2020-09-21 09:08:49 +02:00
Karol Stasiak
2673a486d6
Merge pull request #68 from zbyti/master
A8 more examples
2020-09-21 00:18:14 +02:00
Karol Stasiak
c0eae29a41 Minor compilation speed optimization 2020-09-21 00:15:16 +02:00
Karol Stasiak
a92f24b280 Better detection of memset loops (fixes #59) 2020-09-20 23:39:30 +02:00
zbyti
e9d4359bc2 A8 Monte Carlo PI refactor (__mul_u16u8u16) 2020-09-20 22:58:20 +02:00
zbyti
07b6adf6bc two more benchmarks 2020-09-19 13:02:55 +02:00
zbyti
269519715b two more benchmarks 2020-09-19 12:59:14 +02:00
zbyti
3234bbd3d9 two more becnhmarks 2020-09-19 12:52:41 +02:00
zbyti
19d9e36fa5 A8 more examples 2020-09-19 01:34:29 +02:00
Karol Stasiak
fe094af912
Merge pull request #66 from zbyti/master
Atari 800 System Off example, some minor refactor and more examples
2020-09-17 16:01:00 +02:00
Karol Stasiak
11d2f1aa77 Switch to snapshot versioning 2020-09-17 15:29:37 +02:00
zbyti
81bf24b355 A8 System Off refactor 2020-09-17 12:18:00 +02:00
zbyti
0010358d08 A8 Chessboard drawing benchmark in GR.0 2020-09-17 11:13:28 +02:00
zbyti
8e550669c1 A8 system off example typo 2020-09-16 17:09:24 +02:00
zbyti
aaaae08c03 A8 system off example typo 2020-09-16 13:44:09 +02:00
zbyti
9ee9712554 A8 system off example typo 2020-09-16 12:50:31 +02:00
zbyti
4758dba89e A8 system off example minor refactor 2020-09-16 12:15:46 +02:00
zbyti
e8a50dc610 A8 system off example and some minor refactor 2020-09-16 12:04:39 +02:00
zbyti
88e74906b6 a8 examples refactor 2020-09-15 22:29:18 +02:00
Karol Stasiak
bed44cd08e Version 0.3.22 2020-09-15 17:16:47 +02:00
Karol Stasiak
0806e719ce Update CHANGELOG 2020-09-15 17:14:20 +02:00
Karol Stasiak
ca5fe5cdb0 6809: various optimizations 2020-09-15 17:08:38 +02:00
Karol Stasiak
947a84833a Make some command line options repeatable 2020-09-15 17:08:22 +02:00
Karol Stasiak
e8b1e9e391
Merge pull request #65 from zbyti/master
Details (A8 platform) for new release
2020-09-11 23:50:17 +02:00
zbyti
adf84c084d more info about a8 example 2020-09-09 02:47:07 +02:00
zbyti
a635449829 new a8 memory mapping helpers 2020-09-09 01:52:11 +02:00
Karol Stasiak
fc0171d5aa Update CHANGELOG 2020-09-09 01:49:00 +02:00
Karol Stasiak
40510dc436
Merge pull request #63 from zbyti/master
new memory mapping helpers
2020-09-09 01:47:05 +02:00
Karol Stasiak
615a0d7dc1 Interrupt functions in assembly should not have prologue (fixes #62) 2020-09-09 01:46:34 +02:00
Karol Stasiak
75c8ac19e1 Fix warning messages 2020-09-09 01:45:53 +02:00
Karol Stasiak
ae311f28ea Document new Atari examples 2020-09-09 01:45:39 +02:00
zbyti
3bbab4a126 new memory mapping helpers 2020-09-09 00:57:12 +02:00
Karol Stasiak
b7cb124706
Merge pull request #60 from zbyti/master
Simple Atari 800XL Memory Map
2020-09-08 23:46:21 +02:00
zbyti
866a9ee9d0 refactor 2020-09-08 00:17:10 +02:00
zbyti
e0b2d28a7d refactor 2020-09-08 00:08:43 +02:00
zbyti
f5fb1a6911 refactor 2020-09-07 23:56:50 +02:00
zbyti
19de4085d7 dli example 2020-09-07 01:29:53 +02:00
zbyti
06e5da4e66 endless scroll with random letters 2020-09-06 22:53:59 +02:00
zbyti
c31a2ee388 Simple Atari 800XL Memory Map 2020-09-05 11:58:02 +02:00
zbyti
4849069d39 Simple Atari 800XL Memory Map 2020-09-05 11:48:49 +02:00
zbyti
9a0176333b Simple Atari 800XL Memory Map 2020-09-05 11:47:24 +02:00
zbyti
6b0effaae6 Simple Atari 800XL Memory Map 2020-09-05 11:43:18 +02:00
zbyti
3582925cb1 Simple Atari 800XL Memory Map 2020-09-05 11:37:04 +02:00
Karol Stasiak
c12541c64d Fix the a8_os module (fixing #58) 2020-09-04 01:18:37 +02:00
Karol Stasiak
5e46e8ade9 Fix alignment of substructures 2020-09-02 00:44:24 +02:00
Karol Stasiak
3ded652a90 Add encodings: BraSCII, DEC MCS, LICS, MacRoman 2020-09-01 22:22:28 +02:00
Karol Stasiak
e09db3d132 Local labels in assembly 2020-09-01 22:00:07 +02:00
Karol Stasiak
539c27f13e Update CHANGELOG 2020-08-14 22:34:34 +02:00
Karol Stasiak
57776f7f93 8080: Optimization improvements 2020-08-14 22:29:19 +02:00
Karol Stasiak
7427231c3d Fix constant simplification 2020-08-14 22:29:06 +02:00
Karol Stasiak
b9cd18c3c8 Improve error message for multiple operators at the same priority 2020-08-14 22:28:50 +02:00
Karol Stasiak
49816d18fe Fix volatile 2020-08-14 22:28:31 +02:00
Karol Stasiak
70256e9d46 Fix evaluation of boolean expressions on all targets (#56) 2020-08-14 22:27:23 +02:00
Karol Stasiak
fccbf7df7d Add dollar syntax for decimal operators, disallow identifiers ending in a dollar sign. 2020-08-14 02:22:13 +02:00
Karol Stasiak
0913c5037c Typecheck division of large constants 2020-08-14 01:27:13 +02:00
Karol Stasiak
b5c51e48be Rename zx80next to z80next, document the typo (fixes #55) 2020-08-13 16:53:38 +02:00
Karol Stasiak
708fdab593
Merge pull request #54 from Kobrasadetin/patch-1
fix the value of vera_dc_hscale_hstop
2020-08-13 16:44:04 +02:00
Karol Stasiak
398d9b9c4e Switch to snapshot versioning 2020-08-13 16:43:34 +02:00
Mikko Karjanmaa
29018729f5
fix the value of vera_dc_hscale_hstop 2020-08-11 18:59:54 +03:00
Karol Stasiak
c8c1657521 Version 0.3.18 and undo Scala version bump 2020-08-02 00:31:32 +02:00
Karol Stasiak
8331d6a575 Bump Scala version 2020-08-01 23:07:40 +02:00
Karol Stasiak
c20b144823 CoCo: add coco_crt target 2020-08-01 22:20:52 +02:00
Karol Stasiak
a9aac4fca3 Allow omitting the .exe for the -r parameter 2020-08-01 22:20:11 +02:00
Karol Stasiak
ea04b1f6c0 Fix init_rw_memory 2020-08-01 22:19:51 +02:00
Karol Stasiak
c1224f0795 Formatting (#53) 2020-08-01 00:36:57 +02:00
Karol Stasiak
925cc29172 Let the test suite compile on targets incompatible with encconv 2020-07-31 18:43:50 +02:00
Karol Stasiak
d1c0ad6b22 Better type error reporting 2020-07-31 17:50:10 +02:00
Karol Stasiak
89ff89bc48 Some more defensive programming 2020-07-31 17:11:30 +02:00
Karol Stasiak
87d9884597 Update CHANGELOG 2020-07-31 17:09:34 +02:00
Karol Stasiak
cf707cc31f Protect against confusable non-ASCII characters 2020-07-31 17:08:44 +02:00
Karol Stasiak
7c4fb50808 Hardcode some more typo hints for things from other programming languages 2020-07-31 17:07:25 +02:00
Karol Stasiak
2382f95b5c Don't repeat warnings about identical replaced characters in the lenient mode 2020-07-31 16:08:29 +02:00
Karol Stasiak
4e1958d831 CoCo: Examples and tests 2020-07-31 16:07:49 +02:00
Karol Stasiak
d77ecba518 CoCo: encconv support 2020-07-31 16:07:10 +02:00
Karol Stasiak
2c9a3f7cbd Add ENCODING_NOLOWER 2020-07-31 13:31:07 +02:00
Karol Stasiak
2905e99521 Support local labels in macros for all instructions 2020-07-31 13:29:48 +02:00
Karol Stasiak
03a57138f0 CoCo: Improvements 2020-07-31 13:29:13 +02:00
Karol Stasiak
72dcf2342e 6809: Fix nibble-to-hex routines 2020-07-31 13:27:17 +02:00
Karol Stasiak
bce48e8e4a Support BAT files for the -r options 2020-07-31 13:26:44 +02:00
Karol Stasiak
ed55e2f081 6809: Allow explicit absolute addressing mode 2020-07-31 13:26:08 +02:00
Karol Stasiak
33d67ec932 6809: Correctly assemble STS and STY 2020-07-31 13:25:42 +02:00
Karol Stasiak
cad6f27185 Preliminary CoCo support 2020-07-31 01:58:40 +02:00
Karol Stasiak
8ec82ef520 6809: Document direct addressing mode 2020-07-31 01:57:10 +02:00
Karol Stasiak
f0b083abea 6809: Improve parameter passing for assembly subroutines 2020-07-31 01:56:03 +02:00
Karol Stasiak
d7f2b0688f Improved error reporting for constants used before definition 2020-07-31 01:53:58 +02:00
Karol Stasiak
0b7183daf2
Fix attribution 2020-07-25 22:19:13 +02:00
Karol Stasiak
42426808f5 Update CHANGELOG 2020-07-24 22:27:54 +02:00
Karol Stasiak
2ee2de62cd Don't optimize accesses to arrays of size 0 and 1 – assume that overruns are deliberate. 2020-07-24 22:25:21 +02:00
Karol Stasiak
9a67ac553d Fix and improve stdlib optimizations 2020-07-24 22:18:25 +02:00
Karol Stasiak
ff03b50668 Update documentation 2020-07-24 20:09:47 +02:00
Karol Stasiak
778fc41187
Merge pull request #52 from nippur72/patch-1
fix vic20 volume register address
2020-07-24 19:18:50 +02:00
Karol Stasiak
84483830ce Update changelog 2020-07-24 19:13:57 +02:00
Karol Stasiak
c6c021cf85 Add guides to documentation 2020-07-24 19:13:46 +02:00
Karol Stasiak
d5367cc1fe for loops over arrays 2020-07-24 19:12:19 +02:00
Karol Stasiak
9a47c66539 Update documentation on operators 2020-07-24 17:28:04 +02:00
Karol Stasiak
b24ac32932 Z80: Support IXH/IXL/IYH/IYL registers. Add Intel syntax for Z80 instructions. 2020-07-24 17:27:37 +02:00
nino-porcino
616873bbec
fix vic20 volume register address 2020-07-24 10:29:36 +02:00
Karol Stasiak
53973f081a Add various KOI-8 encodings 2020-07-20 00:13:49 +02:00
Karol Stasiak
000aede8db Do not remove constants used only as array sizes (#51) 2020-07-19 23:34:14 +02:00
Karol Stasiak
27645e93ad Add -version commandline option 2020-07-19 23:33:03 +02:00
Karol Stasiak
8a0c552762 6502: Optimize some more rarer repeated index calculations (#50) 2020-07-19 01:46:09 +02:00
Karol Stasiak
09ff184172 6502: Optimizations for certain byte additions (#50) 2020-07-19 00:56:23 +02:00
Karol Stasiak
5fe4a4e3ac Update CHANGELOG and .gitignore 2020-07-18 01:34:16 +02:00
Karol Stasiak
63aab64204 6502: Optimize array accesses for small arrays and also for repeated indices (#50) 2020-07-18 01:32:41 +02:00
Karol Stasiak
d0bf683657 Various fixes 2020-07-18 01:16:31 +02:00
Karol Stasiak
a2c49a1f89 Add manual type alignment. 6502: Optimize multiplications by constants. 2020-07-18 01:15:33 +02:00
Karol Stasiak
31a8504195 Fix raw views of typed pointers 2020-07-18 01:11:20 +02:00
Karol Stasiak
9881bc0284 Update CHANGELOG 2020-07-13 23:11:00 +02:00
Karol Stasiak
d346800590 6809: enable most unit tests 2020-07-13 23:10:38 +02:00
Karol Stasiak
fff27c59ea 6809: optimize indirect stores 2020-07-13 23:09:52 +02:00
Karol Stasiak
0b948f801d Fix PCW encoding 2020-07-13 23:09:06 +02:00
Karol Stasiak
632bb0c994 Allow modifying large things via pointers 2020-07-13 22:49:23 +02:00
Karol Stasiak
b9736f924c 6809: Fix indirect variable accesses 2020-07-13 22:10:36 +02:00
Karol Stasiak
350c5d2d5d 6809: fix indirect addressing mode 2020-07-13 22:10:04 +02:00
Karol Stasiak
a22571f60b 6809: tons of improvements:
* stack variables
* large comparisons
* pointer optimizations
* fixed constant evaluation
2020-07-09 01:50:18 +02:00
Karol Stasiak
b9bf433308 6809: implement retun dispatch statements 2020-06-24 01:18:38 +02:00
Karol Stasiak
b7a34457fb 6809: Update emulators and fix decimal subtraction 2020-06-22 01:17:42 +02:00
Karol Stasiak
e77811c67c 6809: Implement decimal operations 2020-06-21 02:25:02 +02:00
Karol Stasiak
b387ece71d 6809: Improved support for large types 2020-06-18 20:29:31 +02:00
Karol Stasiak
88b2bbd434 6809: Various improvements 2020-06-17 02:08:17 +02:00
Karol Stasiak
2b0090714c #49 Export fixed addresses to the symbol file 2020-06-17 02:07:32 +02:00
Karol Stasiak
78a680c0d6 6809: Implement +', -' and <<' operators for bytes 2020-06-11 02:39:59 +02:00
Karol Stasiak
2d19537ed3 6809: Fix writing through pointers 2020-06-09 22:56:16 +02:00
Karol Stasiak
a947946313 Fix test 2020-06-09 22:37:55 +02:00
Karol Stasiak
bfe90193fa 6809: Implement / and %% operators 2020-06-09 22:35:57 +02:00
Karol Stasiak
dd78b14c5e 6809: more optimizations 2020-06-09 21:44:22 +02:00
Karol Stasiak
4e19b1ba34 6809: Fix -= 2020-06-09 21:43:31 +02:00
Karol Stasiak
b0577270d5 6809: various assembly fixes 2020-06-09 21:43:04 +02:00
Karol Stasiak
7ba01f83e3 6809: implement * and : operators 2020-06-04 17:07:19 +02:00
Karol Stasiak
b91f259971 6809: Assembly parsing improvements 2020-06-04 17:06:29 +02:00
Karol Stasiak
718245c56a Module templates 2020-06-03 23:13:17 +02:00
Karol Stasiak
b5134dfbd1 Update CHANGELOG 2020-05-01 15:19:36 +02:00
Karol Stasiak
4b5d290d6c X16: Updated to the newest hardware design 2020-05-01 15:19:25 +02:00
Karol Stasiak
655edc35ff Allow sizeof in assembly 2020-05-01 15:18:48 +02:00
Karol Stasiak
3e33660c2e Improvements to mouse support. Added the y_coord type. Renamed x_coord module to coord. 2020-05-01 15:18:34 +02:00
Karol Stasiak
7f9bd18bdd The big text encoding overhaul 2020-05-01 01:31:54 +02:00
Karol Stasiak
a0aa9d418d Update changelog 2020-04-27 12:44:18 +02:00
Karol Stasiak
e82f51668c Document how to make an array of strings. 2020-04-27 12:42:43 +02:00
Karol Stasiak
78fe0e37bb Allow importing modules from subdirectories. Move platform definitions 2020-04-27 12:42:18 +02:00
Karol Stasiak
c8492173ee 6502: Improve index register optimizations 2020-04-27 12:02:45 +02:00
Karol Stasiak
c3b3548956 Switch to snapshot versioning 2020-04-26 21:17:13 +02:00
Karol Stasiak
5909c37166 Version 0.3.16 2020-04-08 12:10:02 +02:00
Karol Stasiak
cd5e9decac Implement readkey and readline for Apple II 2020-04-08 11:11:25 +02:00
Karol Stasiak
29335d376a 8080: Use a register pair instead of absolute addressing when the registers are loaded anyway 2020-04-08 09:26:44 +02:00
Karol Stasiak
fac5a54376 Document that the rest suite also works on BBC Micro 2020-04-08 09:04:56 +02:00
Karol Stasiak
b3fe0e9b06 Update and reorganize changelog 2020-04-08 03:20:28 +02:00
Karol Stasiak
dcf8fb2900 Add support for MkImg for making BBC micro disk images 2020-04-06 22:53:15 +02:00
Karol Stasiak
c53656aee2 Change the default load address for BBC micro 2020-04-06 22:52:49 +02:00
Karol Stasiak
4c39d5e6af Update test suite descriptions 2020-04-06 17:55:22 +02:00
Karol Stasiak
0cba2dec04 Generate .INF file for every output file 2020-04-06 17:54:59 +02:00
Karol Stasiak
eba91e26e5 Remove a debugging message 2020-04-06 13:28:23 +02:00
Karol Stasiak
49c916fea1 Improve the test suite 2020-04-06 13:27:39 +02:00
Karol Stasiak
5b3e812bb1 8080: Fix some stack-related optimizations 2020-04-06 12:00:10 +02:00
Karol Stasiak
f04f5ec111 8080: Fix string module 2020-04-06 11:54:24 +02:00
Karol Stasiak
4ea8658d5b Fix scrstring module 2020-04-06 11:54:11 +02:00
Karol Stasiak
16b83c42f3 Add pstrpaste function 2020-04-06 11:53:51 +02:00
Karol Stasiak
78346af2ef 8080: Some minor improvements 2020-04-06 11:35:14 +02:00
Karol Stasiak
b21b04efeb Some fixes to encconv. Added two more functions. 2020-04-06 03:16:51 +02:00
Karol Stasiak
320b84edb9 Add pstring module 2020-04-06 00:44:20 +02:00
Karol Stasiak
4485c9479e Minor documentation fixes 2020-04-06 00:42:52 +02:00
Karol Stasiak
017019ef5a Create independent test suite 2020-04-06 00:00:48 +02:00
Karol Stasiak
078b22869a 8080: optimize some more cases of stack use 2020-04-05 23:13:43 +02:00
Karol Stasiak
064a9d7022 Fix some NPEs 2020-04-05 23:12:59 +02:00
Karol Stasiak
5df695f2c2 Add support for Pascal-style strings 2020-04-04 00:45:09 +02:00
Karol Stasiak
7ce088514f 6502: Fix and optimize sign extension 2020-04-02 00:22:15 +02:00
Karol Stasiak
d08f7ee77c It's LUnix not Lunix 2020-03-31 21:43:36 +02:00
Karol Stasiak
ff942333bd Fix link 2020-03-31 19:12:06 +02:00
Karol Stasiak
9ffd303583 Update and reorganize documentation 2020-03-31 19:07:35 +02:00
Karol Stasiak
80018a55b4 Allow different output formats for different segments 2020-03-31 19:01:29 +02:00
Karol Stasiak
353923d3bc Add readkeytest example 2020-03-31 18:58:19 +02:00
Karol Stasiak
1f626b0666 Fix keyboard.mfk 2020-03-31 18:50:31 +02:00
Karol Stasiak
ceef57ed18 Change encodeOneChar to encodeDigit 2020-03-31 18:48:11 +02:00
Karol Stasiak
542474e920 Improve readkey on CBM targets. PET improvements. 2020-03-31 17:59:50 +02:00
Karol Stasiak
ffb9de6889 Add putsigned16 2020-03-31 17:58:59 +02:00
Karol Stasiak
742fc50ccc Don't used str2word as scrstr2word when the string terminator matches, but digits don't 2020-03-31 17:58:46 +02:00
Karol Stasiak
be21c34dc4 GB: Fix a silly warning 2020-03-31 17:27:31 +02:00
Karol Stasiak
63ff28e94e Changes to macros and parameter list syntax:
* non-asm macros can now take `const` and `call` parameters
* register parameters to asm functions and macros can be given names if annotated explicitly
2020-03-30 19:23:48 +02:00
Karol Stasiak
5cdc599b1d Avoid overflow errors when estimating memset sizes 2020-03-29 01:45:31 +01:00
Karol Stasiak
5dd3e91c2d 6502: correctly optimize code before BIT instructions 2020-03-29 01:45:02 +01:00
Karol Stasiak
dfe33c9b7a 6502: Pointers should have priority when allocating to the zeropage 2020-03-26 18:52:46 +01:00
Karol Stasiak
78070c115f Some tests that would have prevented few latest commits 2020-03-26 01:47:26 +01:00
Karol Stasiak
59882cf765 6502: Fix zp allocation 2020-03-26 01:38:54 +01:00
Karol Stasiak
2a3c9f04be Fix >32bit constants 2020-03-26 01:36:41 +01:00
Karol Stasiak
5215400cb2 Fix lookup 2020-03-26 01:36:15 +01:00
Karol Stasiak
9bc4bb949e Correctly compile assembly functions using all three registers as separate parameters 2020-03-26 01:35:44 +01:00
Karol Stasiak
842393106e Remove debugging statements 2020-03-26 01:29:26 +01:00
Karol Stasiak
8b39c59830 Update .gitignore 2020-03-25 23:55:20 +01:00
Karol Stasiak
0f235e6135 Bump Scala version 2020-03-25 23:54:23 +01:00
Karol Stasiak
3187ed155e Add signed16 and unsigned16 types 2020-03-25 23:53:26 +01:00
Karol Stasiak
b8e5e71c19 Improve performance of typing expressions 2020-03-25 23:51:53 +01:00
Karol Stasiak
e3d5ce4e81 Fix const functions of the form if c {return x} return y 2020-03-25 23:51:04 +01:00
Karol Stasiak
475496c137 Improvements to constant evaluation 2020-03-25 23:50:06 +01:00
Karol Stasiak
2a566af3da Update changelog 2020-03-19 23:53:49 +01:00
Karol Stasiak
d478f3504f Const-pure functions 2020-03-19 23:53:16 +01:00
Karol Stasiak
5acf92d4e8 Fix test 2020-03-19 21:25:08 +01:00
Karol Stasiak
769f31717d 6502: Detect pointer variables that have to be in the zeropage more accurately 2020-03-19 20:00:28 +01:00
Karol Stasiak
85030d3147 Added constant-only functions min, max, if. Improved handling of constant-only functions. 2020-03-19 19:43:24 +01:00
Karol Stasiak
9cd1e47a37 6502: Fix optimization bug 2020-03-19 18:58:49 +01:00
Karol Stasiak
17e660a2f6 Report lines with invalid short branches 2020-03-17 21:46:43 +01:00
Karol Stasiak
2eb8ef53ca Put almost all warnings behind internal flags 2020-03-17 21:08:43 +01:00
Karol Stasiak
7939b0f2c1 Optimize commutative in-place modifications using arrays and pointers 2020-03-17 12:20:55 +01:00
Karol Stasiak
128dabba3f Reorganize optimizations a bit 2020-03-17 12:20:16 +01:00
Karol Stasiak
a527eea0fc Add more binary operators for constants in assembly 2020-03-17 02:03:44 +01:00
Karol Stasiak
748aa0cf19 Assembly statements should track their source location 2020-03-17 01:59:40 +01:00
Karol Stasiak
46a523a763 Fix warnings in the c1531 module 2020-03-17 01:59:02 +01:00
Karol Stasiak
ec8f2e6a1c Add warnings for calling from one segment to another overlapping one (#42) and -Wnone flag 2020-03-16 00:03:01 +01:00
Karol Stasiak
83b85ef0fc Support breakpoints in the label file (#44) 2020-03-16 00:01:04 +01:00
Karol Stasiak
3cc9996531 update changelog 2020-03-15 01:17:45 +01:00
Karol Stasiak
f57ecc9800 Improve and optimize memset (see #47) 2020-03-15 01:06:09 +01:00
Karol Stasiak
9f128d3c35 Remove debugging code 2020-03-15 01:04:21 +01:00
Karol Stasiak
24870ae62e Detect obviously overflowing constants 2020-03-15 01:01:08 +01:00
Karol Stasiak
ab597e2dbe Fix typo 2020-02-27 02:11:38 +01:00
Karol Stasiak
21ffbfc466 Extra optimization pass over non-inlined functions (implements #43) 2020-02-27 01:33:34 +01:00
Karol Stasiak
6e65cd1902 Better error messages when failing to parse array definitions (fixes #45) 2020-02-12 01:07:14 +01:00
Karol Stasiak
259d871786 Improve syntax error reporting in tests 2020-02-12 01:06:31 +01:00
Karol Stasiak
5380eb39c7 Update changelog 2020-02-11 01:11:15 +01:00
Karol Stasiak
63d4bf2317 6502 Fix an optimization bug with the carry flag (fixes #46) 2020-02-11 01:10:49 +01:00
Karol Stasiak
fb1ad18868 #45 Link to older versions of examples 2020-02-08 22:38:06 +01:00
Karol Stasiak
8b6e89f9a4 Various improvements for macros (fixes #39 and pertains to #40) 2020-02-02 23:25:06 +01:00
Karol Stasiak
5cb4717de6 Fix fatal typos in #34 2020-02-02 22:39:01 +01:00
Karol Stasiak
b41c76c10e Fix typo 2020-01-29 14:27:13 +01:00
Karol Stasiak
de4c261987 Improve testless build instructions (see #36) 2020-01-28 16:26:53 +01:00
Karol Stasiak
08acfed907
Merge pull request #36 from agg23/no-test-without-delete
Improved build without test instructions; no file deletion necessary
2020-01-28 16:25:34 +01:00
Karol Stasiak
5c40d581c0 6502: Fix optimization bug (fixes #41) and add more optimizations involving ARR 2020-01-24 02:19:04 +01:00
Karol Stasiak
d6fd1e8b77 6809: Improve booleans 2020-01-24 02:16:19 +01:00
Karol Stasiak
f247516187 6502: Fix fatal failure when considering undocumented optimizations (fixes #38) 2020-01-18 22:06:50 +01:00
Karol Stasiak
6774c283ae 6502: Add KIL instruction (fixes #37) 2020-01-18 00:09:06 +01:00
Karol Stasiak
7672ba008d 6502: Add missing instructions SHX and LAS 2020-01-18 00:08:02 +01:00
Karol Stasiak
09359235c7 Add immediate addressing mode for short branches and BRK to support some ugly tricks 2020-01-18 00:07:26 +01:00
Karol Stasiak
b3fba658dd Use zeropage indexed adressing when possible 2020-01-18 00:06:20 +01:00
Karol Stasiak
921a59bdad More tests 2020-01-17 23:29:39 +01:00
Karol Stasiak
63866fffe3 Document limitations of operators (closes #24) 2020-01-12 20:53:11 +01:00
Adam Gastineau
ee425a0325 Improved test instructions; no file deletion 2020-01-12 09:54:37 -08:00
Karol Stasiak
49bf0d2777 6502: Correctly inlie variables that happen to be returned (fixes #32) 2020-01-11 22:20:02 +01:00
Karol Stasiak
298e94e3bc
Merge pull request #34 from bsutherland/patch-2
Add voice 3 oscillator and ADSR output registers.
2020-01-10 18:40:19 +01:00
Karol Stasiak
6f68d9e668
Merge pull request #33 from bsutherland/patch-3
Fix cia_disable_irq macro.
2020-01-10 18:39:59 +01:00
Karol Stasiak
0333b339ca Allow omitting length in file array initalizers (fixes #35) 2020-01-10 18:37:49 +01:00
Karol Stasiak
17e02b9b13 Don't commit reproduction attempts 2020-01-10 18:37:01 +01:00
Bruce Sutherland
d49e5cf022
Fix cia_disable_irq macro.
I'm fairly sure this is the correct sequence of instructions to disable irq - tested in my own project. The original macro didn't work for me.
2020-01-05 10:53:51 +08:00
Bruce Sutherland
3dab3aad6b
Add voice 3 oscillator and ADSR output registers. 2020-01-05 10:41:37 +08:00
Karol Stasiak
43b64aac21 Documentation for macros (fixes #23) 2020-01-03 23:56:37 +01:00
Karol Stasiak
df1d5421be Do not allocate variables on top of fixed-address vairables and arrays (fixes #26) 2020-01-03 23:09:20 +01:00
Karol Stasiak
6e36166af2 Never remove or inline volatile variables (fixes #27) 2020-01-03 21:28:10 +01:00
Karol Stasiak
b9cdd0ffff Fix for output directory creation (#21) 2020-01-03 16:13:54 +01:00
Karol Stasiak
5c96b7e463
Merge pull request #31 from bsutherland/patch-1
Add SID filter control registers.
2020-01-03 15:38:43 +01:00
Karol Stasiak
b421dbba4f Create output directories if needed; implements #21 2020-01-03 15:01:55 +01:00
Karol Stasiak
e69b7084bc Allow complex word-sized LHS for most compound operators, implementing #24 2020-01-03 14:52:35 +01:00
Bruce Sutherland
237985117e
Add SID filter control registers. 2020-01-01 12:51:50 +09:00
Karol Stasiak
69c82d90a8 6502: Allow assigning between two statically allocated pointers; fixes #25 2019-12-30 14:28:37 +01:00
Karol Stasiak
709d3d0fcd 6502: Correctly assign true view pointies; fixes #28 2019-12-30 14:25:46 +01:00
Karol Stasiak
b2dd4eadd4 Start work on supporting member arrays 2019-12-30 11:50:18 +01:00
Karol Stasiak
b1a76cad86 Update changelog 2019-12-15 23:51:34 +01:00
Karol Stasiak
2c8b628da9 Switch to snapshot versioning 2019-12-15 23:49:48 +01:00
Karol Stasiak
f8fc001971 6809: Enable and fix more tests 2019-12-15 23:48:22 +01:00
Karol Stasiak
f39fd67a89 6809: Implement more things 2019-12-15 23:48:02 +01:00
Karol Stasiak
6cd639a23a 6809: Fix LBRA 2019-12-15 23:47:01 +01:00
593 changed files with 25809 additions and 4475 deletions

16
.gitignore vendored
View File

@ -6,22 +6,24 @@ project/project/target/
stuff
releases
src/test/scala/experiments/
src/test/java/experiments/
# doesn't work yet
examples/lunix/
# may become a feature in the future
*.tbl
# older copies
include-*/
# hidden files
*.~
#tools
*.bat
issue*.mfk
# compiled Scala files
*.jar
*.class
*.zip
*.exe
# compiled Millfork files
*.prg
@ -29,9 +31,12 @@ examples/lunix/
*.seq
*.asm
*.lbl
*.labels
*.nl
*.fns
*.sym
*.mlb
*.dbg
*.deb
*.xex
*.nes
@ -46,12 +51,17 @@ examples/lunix/
*.com
*.gb
*.rom
*.ssd
*.o
*.cmd
*.z80
HELLO
HELLOCPC
FIZZBUZZ
__hw_bbcmicro
__hw_cpc464
tests-cpc-*
BBC-*
#heap dumps
java_pid*

View File

@ -1,6 +1,355 @@
# Change log
## 0.3.14
## 0.3.30 (2021-12-15)
* Added volatile structure fields (#112).
* Added `this.function` as the alias for the current function (#118).
* Added support for constant evaluation in `file` expressions (#114).
* Allowed declaring local constants and passing untyped parameters for macros.
* Allowed treating bare function name as a pointer to it.
* Added Mesen, ld65 and "raw" label file formats (#128).
* Commodore: the address used by SYS is now determined automatically instead of hardcoded (#111).
* C64: Fixed address for `sid_v1_sr` (#115).
* EasyFlash: Fixed address for `switch_hirom` (#121).
* GB: Fixed standard library (thanks to @retrac0).
* Commander X16: Updated platform definition file (thanks to @mookiexl).
* 65CE02: Full assembly support.
* R800: Full assembly support.
* Various miscompilation fixes (#123, #125) and parser fixes (e.g. #120).
* 6809: Various optimizations.
* Improvements related to constant evaluation.
## 0.3.28 (2021-05-24)
* Officially deprecated decimal operators with apostrophes.
* Added optimization hints.
* Added `utf32be`, `utf32le`, `cp1253`, `cp1254`, `cp1257`, `geos_de` encodings.
* Allowed for underscores in numeric literals for readability purposes, similar to several other programming languages.
* Added a warning for comparisons between bytes and pointers (#110).
* Fixed escape sequences in many encodings.
* Fixed and documented absolute module imports (#106)
* Fixed and optimized sign extension.
* Fixed optimizations involving unused labels.
* Fixed pointer types to type aliases.
* Fixed parsing of Intel hex literals of the form `0BH`, `0B0H` etc.
* 6809: Fixed flow analysis in optimization.
* Optimization of certain bitmask operations.
* Parsing optimizations.
## 0.3.26 (2021-03-01)
* Array fields in structs.
* Various Apple II-related improvements, including ProDOS support (thanks to @retrac0).
* Segment-related constants now match their equivalents from the platform definition. Missing constants have been defined.
* Constants with heap start and segment start are now generated properly.
* Signed multiplication support for `sbyte` and `signed16`.
* Heavily experimental `typeof` builtin.
* Self-modifying assembly code is now supported (#101).
* Successful compilation now prints result program size.
* Warning about data not being included in the output file.
* Warnings can now be enabled and disabled individually.
* Imported modules are now identified by their full relative path, not just the token used in the `import` statement (#89).
* 6502: Fixed sbyte to word promotions in certain contexts.
* 8080: Fixed compilation of sign extension of `sbyte` values into the BC register pair.
* Fixed negative constant folding.
* Fixed optimizations around macro invocations.
* 6502: Fixed code deduplication in presence of trampolined functions.
* Optimized word shifts for between 7 and 12 bits.
* Allowed new lines after `=`.
* Various optimization improvements.
* Improved some error messages (thanks to @agg23).
* Other fixes and improvements.
## 0.3.24 (2020-12-02)
* Preliminary support for TRS-80 Model 1 and 3 running TRS-DOS.
* Preliminary support for Robotron Z1013.
* Allowed defining entry points other than the start of the segment for Atari, ZX Spectrum, CoCo, Z1013 and TRS-80. (#78)
* Allowed the `:` operator in const-pure functions.
* Added `pointer.interrupt` and `pointer.kernal_interrupt` types.
* Implemented `readline` and `readword` for VIC-20.
* `init_rand_seed` uses the POKEY on Atari.
* Useless labels are no longer emitted into the label file.
* VIC-20: added `readline` and `readword`.
* Atari: use POKEY for randomness source.
* New output format elements: ASCII string, program name.
* Fix: Pointers to functions with parameters (#86)/
* Fix: more instances of memset loops should be detected and optimized (#59).
* Fix: things mentioned in the segment layout should not be deleted even if unused.
* Fix: `endaddr+N` output format.
* 65816: some code generation fixes.
* 8080: word negation now works.
* Various optimization improvements.
* Various other fixes.
* Improved some error messages.
* Even more new Atari examples (thanks to @zbyti).
* Build process slightly changed.
## 0.3.22 (2020-09-15)
* Added local labels in assembly.
* Added alternate decimal operators (with `$` instead of `'`).
* **Potentially breaking change!** Identifiers no longer can end with `$`.
* Added `z80next` as an alternate name for the ZX Spectrum Next's processor (#55).
* Added encodings: `brascii`, `macroman`, `dmcs`, `lics`.
* Improved some error messages.
* Fix: interrupt functions written in assembly no longer have the default prologue (#62).
* Fixed the `a8_os` module (#58).
* Fixed evaluation of division of large constants.
* Fix: Structure alignment is now respected for substructures.
* X16: Fixed the address of `vera_dc_hscale_hstop` register (#54) (thanks to @Kobrasadetin).
* Fixed evaluation of more complex boolean expressions (#56).
* Fixed accesses to volatile variables.
* 8080/Z80: Optimization improvements.
* 6809: Optimization improvements.
* Various Atari improvements (#60, #63, #65) (thanks to @zbyti).
* New Atari examples (thanks to @zbyti).
## 0.3.18 (2020-04-08)
* Support for Motorola 6809 (complete, but still experimental).
* Preliminary support for Tandy Color Computer running RS-DOS.
* Preliminary support for 16K cartridges for Tandy Color Computer.
* Added support for modifying large variables via pointers.
* Added the ability to declare structure alignment.
* `for` loops over arrays.
* Allowed defining custom text encodings.
**Potentially breaking change!**
There are no built-in encodings now, the include path needs to contain the necessary encodings.
* Fixed encodings:
`apple2`, `atasciiscr`, `iso_de`, `iso_no`, `iso_se`,
`koi7n2`, `msx_jp`,
`oldpet`, `origpet`, `petscii`, `petsciijp`, `petscr`, `petscrjp`,
`zx80`.
* Added encodings:
`apple2c`, `apple2e`, `apple2gs`,
`coco`, `cocoscr`,
`cpc_da`, `cpc_en`, `cpc_es`, `cpc_fr`,
`cp437`, `cp850`, `cp851`, `cp852`, `cp855`, `cp858`, `cp866`,
`cp1250`, `cp1251`, `cp1252`,
`ebcdic`,
`galaksija`,
`iso8859_1`, `iso8859_2`, `iso8859_3`, `iso8859_4`, `iso8859_5`,
`iso8859_7`, `iso8859_9`, `iso8859_10`, `iso8859_13`, `iso8859_14`, `iso8859_16`,
`kamenicky`,
`koi8e`, `koi8f`, `koi8r`, `koi8ru`, `koi8t`, `koi8u`,
`mazovia`, `pcw`,
`pokemon1en`, `pokemon1es`, `pokemon1fr`, `pokemon1jp`.
* Added `ENCODING_NOLOWER` preprocessor feature.
* Fixed raw views of typed pointers.
* Fixed dead code elimination (#51).
* **Potentially breaking change!** Changed default encoding for CPC to `cpc_en`.
* **Potentially breaking change!** Changed the type of `mouse_lbm` and `mouse_rbm` to `bool`. Added `mouse_mbm`
* **Potentially breaking change!** Renamed the `x_coord` module to `coord`. Added the `y_coord` type and `TALLSCREEN` preprocessor feature.
* Added `pscrstr2word` function.
* Labels with fixed addresses are now exported to the label file (#49).
* Fixed address of the VIC 20 volume register (#52) (thanks to @nippur72).
* Fixed and improved stdlib optimizations.
* Allow importing modules from subdirectories.
* Allow placing platform definitions in a dedicated subdirectory.
* Allow using Batch files with the `-r` option.
* Improved error reporting for constants used before their definitions.
* Improved typo hints.
* Typo hints for non-ASCII characters.
* Z80: Intel syntax for all Z80 instructions, based on Digital Research's Z80.LIB.
* Commander X16: Updated to support VERA 0.9 and the new joystick API. Added mouse support.
* 6502: Optimization improvements:
* Fixed index register optimization regressions.
* Small array optimizations are now available for more operations.
* Index calculations for arrays of structs with sizes divisible by an even power of two are now sometimes optimized.
* Redundant index calculations are now removed.
## 0.3.16 (2020-04-08)
* Language improvements:
* Added compile-time evaluation for user-defined functions.
* Added `breakpoint` macro (#44).
* **Potentially breaking change!** Added `min`, `max` and `if` compile-time functions.
* Added experimental `signed16` and `unsigned16` types.
* Added length-prefixed strings (Pascal strings).
* Improved operator support for word-sized arguments (#24, #25).
* **Potentially breaking change!** Various macros improvements, including the requirement of parameter types matching exactly (#23, #39, #40).
* Compiler improvements:
* 6809 improvements (no full support yet).
* Added warnings for calling from one segment to another overlapping one.
* 6502: Fixed undocumented mnemonics.
* Create output directories when needed (#21).
* Allow defining different output formats for different segments when outputting one file per segment.
* Fixed multiple optimization bugs (#32, #38, #41, #46 and others) thanks to @agg23 for detailed bug reports!
* 6502: Fix boolean arrays and pointers (#28).
* Fixed and improved memset-like loops (#47).
* Minor improvements to inline assembly.
* Improvements to constant evaluation, including more arithmetic operators.
* **Potentially breaking change!** Detect overflowing constants, like `const byte x = 256`.
* Optimization improvements.
* 6502: Memory allocation improvements for pointers.
* Support for MkImg (tool for creating BBC Micro disk images) and multiple output files on BBC Micro.
* Other minor fixes.
* Library improvements:
* Added `putsigned16` function.
* Added `pstring` module and `putpstr` function.
* Various improvements to the C64 libraries (thanks to @bsutherland).
* Added detection for various PET variants and implemented `readkey` for PET.
* Implemented `readkey` and `readline` for Apple II.
* Changed the default load address for BBC Micro.
* Multiple fixes to the `string`, `scrstring` and `encconv` modules.
* Other minor fixes.
* Other changes:
* Created a pure-Millfork test suite.
* Updated to Scala 2.12.11.
## 0.3.14 (2019-12-03)
* Full assembly support for HuC6280.
@ -16,7 +365,7 @@
* Other bug fixes.
## 0.3.12
## 0.3.12 (2019-11-06)
* **Breaking change!**
The `petscr`, `petscrjp` and `atasciiscr` encodings now use $E0, $E0 and $DB respectively as their string terminator.
@ -40,7 +389,7 @@ Changed the identifiers for various subtypes of the 65C02 processors.
* Other bugfixes
## 0.3.10
## 0.3.10 (2019-10-24)
* Preliminary support for the CPU from ZX Spectrum Next.
@ -80,7 +429,7 @@ Changed the identifiers for various subtypes of the 65C02 processors.
* Added another NES example (thanks to @Garydos).
## 0.3.8
## 0.3.8 (2019-06-21)
* `sizeof` now supports arrays.
@ -116,7 +465,7 @@ Changed the identifiers for various subtypes of the 65C02 processors.
* 6502: Inlining improvements.
## 0.3.6
## 0.3.6 (2019-08-05)
* **Breaking change!**
The `petscii` encoding now uses the $C0-$DE range for uppercase characters instead of $60-$7E.
@ -178,7 +527,7 @@ This matches both the CC65 behaviour and the return values from `readkey()`.
* Other fixes and improvements.
## 0.3.4
## 0.3.4 (2019-07-01)
* Preliminary experimental Game Boy support.
@ -275,7 +624,7 @@ can no longer be read before an explicit call to `init_rw_memory`, either add th
* Optimization improvements.
## 0.3.2
## 0.3.2 (2018-12-28)
* Almost complete support for the Zilog Z80, Intel 8080 and Sharp LR35902 microprocessors.
@ -289,7 +638,7 @@ can no longer be read before an explicit call to `init_rw_memory`, either add th
* Added enumeration types.
* Added preprocessor.
* Added the preprocessor.
* Added `for` loops over enum types and in-place lists
@ -311,7 +660,7 @@ can no longer be read before an explicit call to `init_rw_memory`, either add th
* Extra `z` at the name of the encoding means that the string is zero-terminated.
* **Potentially breaking change!** No longer allowed to define things with names that are keywords or builtins.
* **Potentially breaking change!** It's no longer allowed to define things with names that are keywords or builtins.
* **Potentially breaking change!** Curly braces in text literals are now used for escape sequences.
@ -348,7 +697,7 @@ Code that uses a custom platform definitions will cause extra warnings until fix
* Other improvements.
## 0.3.0
## 0.3.0 (2018-06-25)
* Finally faster than C.
@ -380,7 +729,7 @@ Code that uses a custom platform definitions will cause extra warnings until fix
* Other improvements.
## 0.2.2
## 0.2.2 (2018-03-19)
* Allowed adding constant words to variable bytes without the zeropage pseudoregister.
@ -392,7 +741,7 @@ Code that uses a custom platform definitions will cause extra warnings until fix
* Other improvements.
## 0.2
## 0.2 (2018-03-17)
* **Breaking change!** Renamed `inline` to `macro`.
@ -441,6 +790,6 @@ Detailed flow analysis was slow, broken, hard to maintain, and didn't even help
* Other improvements.
## 0.1
## 0.1 (2018-01-24)
* Initial numbered version.
* Initial numbered version.

View File

@ -21,23 +21,11 @@ Setting up the test suite for Millfork is tricky, so if you don't need the tests
#### Steps
* delete the `src/test` directory
* run `sbt -DskipTests compile`
to compile the project
* remove all test dependencies from `build.sbt`:
"org.scalatest" %% "scalatest"
"com.codingrodent.microprocessor" % "Z80Processor"
"NeatMonster" % "Intel8086"
"com.loomcom.symon" % "symon"
"com.grapeshot" % "halfnes"
"eu.rekawek.coffeegb" % "coffee-gb"
"roug.org.osnine" % "osnine-core"
* navigate to the project directory
* run `sbt compile` to compile the project
* run `sbt assembly` to build the executable jar file, it should appear in `target/scala-2.12`
* run `sbt -DskipTests assembly`
to build the executable jar file, it should appear in `target/scala-2.12`
### Building with tests
@ -45,7 +33,10 @@ Test suite is useful if you plan on modifying the compiler. Some test dependenci
#### Prerequisites
* JDK 1.8 with Nashorn (tests don't work on newer versions)
* JDK 1.8 or later
* Millfork up to version 0.3.22 used to require exactly JDK 1.8 with Nashorn,
as the tests didn't work on newer versions
* sbt
@ -58,7 +49,7 @@ Test suite is useful if you plan on modifying the compiler. Some test dependenci
https://github.com/sethm/symon/tree/71905fdb1998ee4f142260879504bc46cf27648f
https://github.com/andrew-hoffman/halfnes/tree/061
https://github.com/trekawek/coffee-gb/tree/coffee-gb-1.0.0
https://github.com/sorenroug/osnine-java/tree/1b4e059c5886fe01e8901c70684f7eedefe65010
https://github.com/sorenroug/osnine-java/tree/b77349a6c314e1362e69b7158c385ac6f89b7ab8
* for each of them, run `maven package` and `maven install`
@ -66,7 +57,7 @@ Test suite is useful if you plan on modifying the compiler. Some test dependenci
* run `sbt compile` to compile the project
* run `sbt assemble` to build the executable jar file, it should appear in `target/scala-2.12`
* run `sbt assembly` to build the executable jar file, it should appear in `target/scala-2.12`
### Building a native executable

View File

@ -13,7 +13,7 @@ If you want to contribute:
* make a pull request, explaining what you implemented if needed.
By making pull request, you agree for your changes to be distributed in perpetuity
under the applicable license (GPL-3 for the compiler, zlib for the stdlib, CC0 for documentation)
under the applicable license (GPL-3 for the compiler, zlib for the stdlib, CC0 for the documentation)
or any other compatible license.
You retain copyright to your contributions, you do not have to assign the copyright to anybody.

View File

@ -2,10 +2,10 @@
# Millfork
A middle-level programming language targeting 6502-based, 8080-based and Z80-based microcomputers.
A middle-level programming language targeting 6502-based, 8080-based, Z80-based and 6809-based microcomputers.
For binary releases, see: [https://github.com/KarolS/millfork/releases](https://github.com/KarolS/millfork/releases)
(latest: 0.3.14).
(latest: 0.3.30).
For build instructions, see [Build instructions](./COMPILING.md).
## Features
@ -22,19 +22,21 @@ For build instructions, see [Build instructions](./COMPILING.md).
* other 6502-based machines: Famicom/NES, Atari Lynx, Atari 8-bit computers, BBC Micro, Apple II+/IIe/Enhanced IIe, Atari 2600 (experimental), Commander X16 (experimental)
* Z80-based machines: ZX Spectrum 48k, NEC PC-88, Amstrad CPC, MSX
* Z80-based machines: ZX Spectrum 48k, NEC PC-88, Amstrad CPC, MSX, TRS-80 Model 1 and 3, Robotron Z1013
* CP/M
* Game Boy (experimental)
* Tandy Color Computer (experimental)
* MS-DOS (very experimental, via 8080-to-8086 translation)
* multiple supported target processors:
* well supported: MOS 6502, Ricoh 2A03/2A07, WDC 65C02, Intel 8080, Intel 8085, Zilog Z80
* reasonably well supported: Sharp LR35902, CSG 65CE02
* reasonably well supported: Sharp LR35902, CSG 65CE02, Motorola 6809
* partially supported: Hudson Soft HuC6280, WDC 65816, Intel 8086

View File

@ -1,8 +1,9 @@
name := "millfork"
version := "0.3.14"
version := "0.3.31-SNAPSHOT"
scalaVersion := "2.12.10"
// keep it at 2.12.11 for GraalVM native image compatibility!
scalaVersion := "2.12.11"
resolvers += Resolver.mavenLocal
@ -12,25 +13,42 @@ libraryDependencies += "org.apache.commons" % "commons-configuration2" % "2.2"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test"
libraryDependencies += "com.codingrodent.microprocessor" % "Z80Processor" % "2.0.2" % "test"
val testDependencies = Seq(
"com.codingrodent.microprocessor" % "Z80Processor" % "2.0.2" % "test",
// see: https://github.com/NeatMonster/Intel8086
"NeatMonster" % "Intel8086" % "1.0" % "test" from "https://github.com/NeatMonster/Intel8086/raw/master/IBMPC.jar",
// these three are not in Maven Central or any other public repo
// get them from the following links or just build millfork without tests:
// https://github.com/sethm/symon/tree/71905fdb1998ee4f142260879504bc46cf27648f
// https://github.com/andrew-hoffman/halfnes/tree/061
// https://github.com/trekawek/coffee-gb/tree/coffee-gb-1.0.0
// https://github.com/sorenroug/osnine-java/tree/b77349a6c314e1362e69b7158c385ac6f89b7ab8
"com.loomcom.symon" % "symon" % "1.3.0-SNAPSHOT" % "test",
"com.grapeshot" % "halfnes" % "061" % "test",
"eu.rekawek.coffeegb" % "coffee-gb" % "1.0.0" % "test",
"roug.org.osnine" % "osnine-core" % "2.0-SNAPSHOT" % "test",
"org.graalvm.sdk" % "graal-sdk" % "20.2.0" % "test",
"org.graalvm.js" % "js" % "20.2.0" % "test",
"org.graalvm.js" % "js-scriptengine" % "20.2.0" % "test"
)
// see: https://github.com/NeatMonster/Intel8086
libraryDependencies += "NeatMonster" % "Intel8086" % "1.0" % "test" from "https://github.com/NeatMonster/Intel8086/raw/master/IBMPC.jar"
val includesTests = System.getProperty("skipTests") == null
// these three are not in Maven Central or any other public repo
// get them from the following links or just build millfork without tests:
// https://github.com/sethm/symon/tree/71905fdb1998ee4f142260879504bc46cf27648f
// https://github.com/andrew-hoffman/halfnes/tree/061
// https://github.com/trekawek/coffee-gb/tree/coffee-gb-1.0.0
// https://github.com/sorenroug/osnine-java/tree/1b4e059c5886fe01e8901c70684f7eedefe65010
libraryDependencies ++=(
if (includesTests) {
println("Including test dependencies")
testDependencies
} else {
Seq[ModuleID]()
}
)
libraryDependencies += "com.loomcom.symon" % "symon" % "1.3.0-SNAPSHOT" % "test"
libraryDependencies += "com.grapeshot" % "halfnes" % "061" % "test"
libraryDependencies += "eu.rekawek.coffeegb" % "coffee-gb" % "1.0.0" % "test"
libraryDependencies += "roug.org.osnine" % "osnine-core" % "1.0-SNAPSHOT" % "test"
(if (!includesTests) {
// Disable assembling tests
sbt.internals.DslEntry.fromSettingsDef(test in assembly := {})
} else {
sbt.internals.DslEntry.fromSettingsDef(Seq[sbt.Def.Setting[_]]())
})
mainClass in Compile := Some("millfork.Main")

View File

@ -16,6 +16,8 @@
* [Preprocessor](lang/preprocessor.md)
* [Modules](lang/modules.md)
* [Syntax](lang/syntax.md)
* [Types](lang/types.md)
@ -34,6 +36,8 @@
* [Inline 8080/LR35902/Z80 assembly syntax](lang/assemblyz80.md)
* [Inline 6809 assembly syntax](lang/assembly6809.md)
* [Important guidelines regarding reentrancy](lang/reentrancy.md)
* [List of keywords](lang/keywords.md)
@ -42,27 +46,47 @@
* [`stdlib` module](stdlib/stdlib.md)
* [`string` and `scrstring` modules](stdlib/string.md)
* [`string`, `scrstring` and `pstring` modules](stdlib/string.md)
* [`stdio` module](stdlib/stdio.md)
* [Modules for reading input devices](stdlib/input.md)
* Reading input devices:
* [`joy` module](stdlib/joy.md)
* [`keyboard` module](stdlib/keyboard.md)
* [`mouse` module](stdlib/mouse.md)
* [`encconv` module](stdlib/encconv.md)
* [Other cross-platform modules (`keyboard`, `err`, `random`)](stdlib/other.md)
* [Other cross-platform modules (`err`, `random`)](stdlib/other.md)
* [Definitions available on only some platforms](stdlib/frequent.md)
* Platform-specific modules:
* [C64-only modules](stdlib/c64.md)
* [Definitions available on only some platforms](stdlib/frequent.md)
* [`cbm_file` module](stdlib/cbm_file.md)
* [C64-only modules](stdlib/c64.md)
* [PET-only modules](stdlib/cbm_pet.md)
* [`cbm_file` module](stdlib/cbm_file.md)
* [NES-only modules](stdlib/nes.md)
* [Atari Lynx-only modules](stdlib/lynx.md)
* [Game Boyonly modules](stdlib/gb.md)
* [X16only modules](stdlib/x16.md)
## Guides
* [NES-only modules](stdlib/nes.md)
* [Differences from C](various/cdiff.md)
* [Game Boyonly modules](stdlib/gb.md)
* [Differences from other assemblers](various/asmdiff.md)
* [X16only modules](stdlib/x16.md)
* [Optimization guide](various/optimization.md)
## Implementation details

View File

@ -29,7 +29,7 @@
* on 65816: callee will preserve the emulation flag
(setting the emulation flag correctly is the responsibility of the initialization code)
* on 65816 in native mode:
* on 65816 in the native mode:
* callee expects the M and X flag to be set and will leave them set
(8-bit accumulator and index registers by default)
@ -45,11 +45,11 @@
* if the function has one parameter of size two bytes, it is passed via the HL register pair
* if the function has one parameter of size three bytes,
its least significant two bytes are passed via the HL register pair
its least significant two bytes are passed via the HL register pair,
and the most significant byte is passed via the E register
* if the function has one parameter of size four bytes,
its least significant word is passed via the HL register pair
its least significant word is passed via the HL register pair,
and the most significant word is passed via the DE register pair
* otherwise, all parameters are passed via static locations
@ -61,11 +61,11 @@ and the most significant word is passed via the DE register pair
* two-byte return values are passed via the HL register pair
* in case of three-byte return values,
its least significant two bytes are passed via the HL register pair
its least significant two bytes are passed via the HL register pair,
and the most significant byte is passed via the E register
* in case of four-byte return values,
its least significant word is passed via the HL register pair
its least significant word is passed via the HL register pair,
and the most significant word is passed via the DE register pair
* otherwise, the return value is passed via a static location
@ -89,11 +89,11 @@ The DI register is not used.
* if the function has one parameter of size two bytes, it is passed via the BX register
* if the function has one parameter of size three bytes,
its least significant two bytes are passed via the BX register
its least significant two bytes are passed via the BX register,
and the most significant byte is passed via the DL register
* if the function has one parameter of size four bytes,
its least significant word is passed via the BX register
its least significant word is passed via the BX register,
and the most significant word is passed via the DX register
* otherwise, all parameters are passed via static locations
@ -105,11 +105,11 @@ and the most significant word is passed via the DX register
* two-byte return values are passed via the BX register
* in case of three-byte return values,
its least significant two bytes are passed via the BX register
its least significant two bytes are passed via the BX register,
and the most significant byte is passed via the DL register
* in case of four-byte return values,
its least significant word is passed via the BX register
its least significant word is passed via the BX register,
and the most significant word is passed via the DX register
* otherwise, the return value is passed via a static location

View File

@ -4,17 +4,136 @@
## Macros
`macro` keyword
Functions defined with the `macro` keyword are not actual functions, but they are used as syntax replacements.
It implies the following:
* macros must return `void`
* cannot be `inline`, `noinline` or `extern`
* cannot contain variable or array declarations
* but can contain scalar constant declarations; the constants are scoped to the particular macro invocation
* can be `asm` - in this case, they should **not** end with a return instruction
* do not have an address
* their invocations cannot be used as expressions
* in case of `asm` macros, the parameters:
* must be defined as either `const` (compile-time constants), `ref` (variables) or `register(XX)` (registers, where XX is the register you want to use)
* at most one parameter can be defined as a register
* in case of non-`asm` macros, the parameters
* must be defined as either `ref` (variables; default, may be omitted) `const` (compile-time constants), or `call` (expressions, which are evaluated every time they are used)
* `ref` parameters exceptionally can have their type declared as `void`; such parameters accept variables of any type
* `call` parameters exceptionally can have their type declared as `void`;
such parameters accept expressions of any type, including `void`, however, you cannot assign from those expressions
* macros do not have their own scope (they reuse the scope from their invocations) exceptions:
* the parameters
* the local labels defined in assembly
* the local constants
* control-flow statements (`break`, `continue`, `return`, `goto`, `label`) are run as if places in the caller function
When invoking a macro, you need to pass variables as arguments to parameters annotated with `ref` and constants as arguments annotated with `const`.
Invoking a non-`asm` macro requires the types of variables via `ref` parameters to match precisely.
No type conversions are performed.
Exception: parameters of type `void` can accept a variable of any type.
For parameters defined as `const`, `register(XX)` or `call`, the usual type conversions are performed.
You can invoke a macro from assembly, by preceding the invocation with `+`
Examples:
macro void inc_x() {
x += 1
}
byte add_two_1(byte x) {
inc_x()
inc_x()
return x
}
macro void inc(byte b) {
b += 1
}
byte add_two_2(byte x) {
inc(x)
inc(x)
return x
}
macro void perform_twice(void call f) {
f
f
}
byte add_two_3(byte x) {
perform_twice(inc(x))
return x
}
macro void add(byte b, byte v) {
b += v
}
macro void retu(byte result) {
return result
}
byte add_two_4(byte x) {
add(x, 2)
retu(x)
}
macro asm byte add_asm(byte ref b, byte const v) {
LDA b
CLC
ADC #v
STA b
// no RTS!
}
byte add_two_5(byte x) {
add_asm(x, 2)
return x
}
macro asm byte add_asm_2(byte ref b, byte register(x) v) {
TXA
CLC
ADC b
STA b
// no RTS!
}
byte add_two_6(byte x) {
add_asm_2(x, 2)
return x
}
## Automatic inlining
You can control inlining behavior in several ways:
* functions declared with the `const` keyword called with constant arguments will always be inlined,
with the whole invocation being converted into a single constant, regardless of `inline` and `noinline` keywords;
calls with non-constant arguments are subject to the regular rules.
* functions declared with the `inline` keyword will be inlined if possible
* functions declared with the `noinline` keyword will never be inlined
* the remaining functions may be inlined only if the `-finline` command-line option is enabled
* the remaining functions may be inlined only if the `-finline` command-line option is enabled,
and the compiler decides the function is worth doing
## Automatic subroutine extraction

View File

@ -24,6 +24,8 @@ Millfork supports multiple mnemonics per opcode. The default one is given first:
* **ISC**, INS
* **KIL**
* **LAS**
* **LAX**
@ -67,8 +69,11 @@ AHX, LAS, LXA, SHX, SHY, TAS, XAA.
## Z80
Original Z80 processors accidentally supported a bunch of extra undocumented instructions.
Millfork will not emit them.
The only exception is SLL, which will be emitted if it occurs in a handwritten assembly block.
Millfork will emit some of them if used in an assembly block:
* `SLL` supported
* instructions using the IXH, IXL, IYH, IYL registers supported (can only be used in Zilog syntax)
* instructions of the form `RLC IX(1),B` not supported
## 8085

View File

@ -4,7 +4,7 @@
Variables in Millfork can belong to one of the following storage classes:
* static: all global variables; local variables declared with `static`
* static: all global variables; local variables declared with `static` or `volatile`
* stack: local variables declared with `stack`
@ -46,6 +46,8 @@ but the main disadvantages are:
* cannot use them in inline assembly code blocks
* structs and unions containing array fields are not supported
The implementation depends on the target architecture:
* on 6502, the stack pointer is transferred into the X register and used as a base

View File

@ -1,18 +1,30 @@
[< back to index](../doc_index.md)
### A note about Apple II
## Apple II
Apple II variants other than II+/IIe/Enhanced IIe are untested;
this includes the original II, IIc and IIc+, but also later compatible computers (Apple III and IIgs).
They may or may not work.
### Model support
The current platform configuration for the Apple II targets the original Apple II with an NMOS processor.
Simple programs have been tested on the Apple II, II+, IIe and enhanced IIe. The IIc, IIc+ are untested.
The IIgs may work in compatibility mode, but this is untested. The Apple III is untested.
ProDOS support is handled by the [`apple2_prodos` module](../stdlib/apple2.md).
### Running your program
The compiler output is a raw machine code file, which then has to be put on a disk.
You can do it using [CiderPress](http://a2ciderpress.com/),
[AppleCommander](https://applecommander.github.io/),
or some other tool.
The file has to be loaded from $0C00. An example how to put such file onto a disk using AppleCommander:
The file has to be loaded from $0C00. An example how to put such a file onto a disk using AppleCommander:
java -jar AppleCommander.jar -p disk_image.dsk FILENAME B 0xc00 < compiler_output.a2
When you have placed your file on disk, boot the disk and enter this at the BASIC prompt:
] BRUN FILENAME
This has been successfully tested under DOS 3.3 and [ProDOS 2.4](https://prodos8.com/), on an Apple II+ and Apple IIe.
java -jar AppleCommander-1.3.5.jar -p disk_image.dsk FILENAME B 0xc00 < compiler_output.a2
Creating a bootable disk is beyond the scope of this document.

View File

@ -6,7 +6,9 @@ The default configuration file puts the start address for the program at $0E00.
The compiler outputs two files: a raw machine code file without an extension and a `.inf` file with file metadata.
To use the file, you need to put it on a disk or a disk image.
You can for example use tools like BBC Disk Explorer.
You can for example use tools like BBC Disk Explorer (GUI) or MkImg (command line):
MkImg disk_image.ssd output_directory
After putting it on a disk, the file can be run with:

View File

@ -0,0 +1,26 @@
[< back to index](../doc_index.md)
### A note about Color Computer
#### `coco_rsdos` target
The `coco_rsdos` target creates binary files that can run on Tandy Color Computer running RS-DOS.
The compiler output is a raw machine code file with the `.bin` extension, which then has to be put on a disk.
You can do it using `imgtool` from the [MAME project](https://www.mamedev.org/):
imgtool create coco_jvc_rsdos disk_image.dsk
imgtool put coco_jvc_rsdos disk_image.dsk compiler_output.bin CO.BIN
The resulting file can then be loaded and ran using the following commands:
LOADM"CO":EXEC
#### `coco_crt` target
The `coco_crt` target creates 16k cartridge images that can run on Tandy Color Computer or Dragon.
The program is run directly from ROM;
typical ROM programming guidelines apply, see [the ROM vs RAM guide](./rom-vs-ram.md).
The `main` function is not allowed to return.

View File

@ -31,7 +31,7 @@ no extension for BBC micro program file,
Default: If compiling one file with `.mfk` extension, the same name as the input file. Otherwise, `a`.
* `-s` Generate also the assembly output. It is not compatible with any assembler, but it serves purely informational purpose. The file has the same nam as the output file and the extension is `.asm`.
* `-s` Generate also the assembly output. It is not compatible with any assembler, but it serves purely informational purpose. The file has the same nam as the output file, and the extension is `.asm`.
* `-g` Generate also the label file. The label file contains labels with their addresses, with duplicates removed.
It can be loaded into the monitor of the emulator for debugging purposes.
@ -47,20 +47,35 @@ The extension and the file format are platform-dependent.
* `-G sym` format used by the WLA DX assembler. The extension is `.sym`.
* `-G fceux` multi-file format used by the FCEUX emulator. The extension is `.nl`.
* `-G mesen` format used by the Mesen emulator. The extension is `.mlb`.
* `-G ld65` a simplified version of the format used by the `ld65` linker (used by CC65 and CA65). The extension is `.dbg`.
* `-G raw` Millfork-specific format. The extension is '.labels'. Each row contains bank number, start address, end address (if known), object type, and Millfork-specific object identifier.
* `-fbreakpoints`, `-fno-breakpoints`
Whether the compiler should use the `breakpoint` macro.
When enabled, breakpoints become memory barriers and the label file will contain the breakpoints if the format supports them.
Currently, the only formats that supports breakpoints are `vice` and `sym`.
`.ini` equivalent: `breakpoints`. Default: yes.
* `-I <dir>;<dir>` The include directories.
Those directories are searched for modules and platform definitions.
When searching for modules, the directory containing the file currently being compiled is also searched.
When searching for platform definitions, the current working directory is also searched.
If not given, the compiler will try to detect the default include directory.
If given, then the compiler will NOT try to detect the default include directory and you will have to add it to the list yourself.
If given, then the compiler will NOT try to detect the default include directory, and you will have to add it to the list yourself.
* `-i <dir>` Add a directory to the include directories.
Unlike `-I`, this does not replace the default include directory and allows using directories with semicolons in their names.
* `-t <platform>` Target platform. It is loaded from an `.ini` file found in any of the include directories. See also [this document](target-platforms.md).
* `-r <program>` Run given program after successful compilation. Useful for automatically launching emulators without any external scripting.
* `-r <program>` Run given program after successful compilation.
Useful for automatically launching emulators without any external scripting.
The program is run with the working directory set to its own directory,
and it's passed the full path to the output file as its argument.
* `-R <param>` Adds a parameter to the command line of the program run with `-r`. All `-R` options are added in order, before the output file name.
@ -181,6 +196,14 @@ Allow using the IY register for other purposes.
Compiling to 8086 is based on translating from a mix of 8085 and Z80 instructions to 8086.
See [the 8086 support disclaimer](./../lang/x86disclaimer.md).
#### 6809-related
* `-fuse-u-for-stack`, `-fuse-y-for-stack`
Which of Z80 index registers should be used as the base pointer for accessing stack variables, if any.
`.ini` equivalent: `u_stack` and `y_stack`. Default: none.
**Warning: Currently, picking one of those two options is required!**
The compiler doesn't support accessing the stack variables via the S stack pointer register yet.
## Optimization options
* `-O0` Disable all optimizations except unused global symbol removal.
@ -189,6 +212,10 @@ See [the 8086 support disclaimer](./../lang/x86disclaimer.md).
* `-O9` Optimize code using superoptimizer (experimental). Computationally very expensive, decent results.
* `-fhints`, `-fno-hints`
Whether optimization hints should be used.
Default: yes.
* `-finline`, `-fno-inline` Whether should inline functions automatically.
See the [documentation about inlining](../abi/inlining.md). Computationally easy, can give decent gains.
`.ini` equivalent: `inline`.
@ -204,7 +231,7 @@ Default: yes.
* `-foptimize-stdlib`, `-fno-optimize-stdlib`
Whether should replace some standard library calls with constant parameters with more efficient variants.
Currently affects `putstrz` and `strzlen`, but may affect more functions in the future.
Currently affects `putstrz`, `putpstr`, `strzlen`, `scrstrlen` and `pstrlen`, but may affect more functions in the future.
`.ini` equivalent: `optimize_stdlib`.
Default: no.
@ -254,6 +281,52 @@ command line options `--inline`, `--dangerous-optimizations` `--fipo` and `--fno
## Warning options
By default, the compiler emits only some of the most important warnings.
* `-Wall` Enable extra warnings.
* `-Wnone` Disable all warnings.
* `-Wfatal` Treat warnings as errors.
You can also enable or disable warnings individually:
* `-Wbuggy`, `-Wno-buggy`
Whether should warn about code that may cause surprising behaviours or even miscompilation.
Default: enabled.
* `-Wdeprecation`, `-Wno-deprecation`
Whether should warn about deprecated aliases.
Default: enabled.
* `-Wcomparisons`, `-Wno-comparisons`
Whether should warn about comparisons between bytes and pointers.
Default: enabled.
* `-Wextra-comparisons`, `-Wno-extra-comparisons`
Whether should warn about simplifiable unsigned integer comparisons.
Default: disabled.
* `-Wfallback`, `-Wno-fallback`
Whether should warn about the use of default values by text codecs, the preprocessor, and array literals.
Default: enabled.
* `-Wmissing-output`, `-Wno-missing-output`
Whether should warn about data that is missing in output files.
Default: enabled.
* `-Woverlapping-call`, `-Wno-overlapping-call`
Whether should warn about calls to functions in a different, yet overlapping segment.
Default: enabled.
* `-Wror`, `-Wno-ror`
Whether should warn about the ROR instruction (6502 only).
Default: disabled.
* `-Wuseless`, `-Wno-useless`
Whether should warn about code that does nothing.
Default: enabled.
* `-Whints`, `-Wno-hints`
Whether should warn about unsupported optimization hints.
Default: enabled.

View File

@ -2,6 +2,11 @@
### A note about Commodore 64
#### Unusual main function location
If you're creating a prg file and your `main` function may be located at address $2710 hex (10000 decimal) or higher,
you might need to define the `DISPLACED_MAIN=1` preprocessor feature.
#### Multifile programs
A multifile program is a program stored on a disk that consists of the main program file that is executed first
@ -63,7 +68,7 @@ The default segment will be in `OUTPUT.prg`, the segment called `extra` in `OUTP
The Millfork compiler does not create Commodore disk images.
You can use a variety of tools to perform that task,
for example the `c1531` tool shipped with [the VICE emulator](http://vice-emu.sourceforge.net/).
for example the `c1541` tool shipped with [the VICE emulator](http://vice-emu.sourceforge.net/).
To create a new disk image for the last example, use:

View File

@ -8,7 +8,7 @@ You can do it using [CPCDiskXP](http://www.cpcwiki.eu/index.php/CPCDiskXP),
[iDSK](http://www.cpcwiki.eu/index.php/IDSK),
or some other tool.
The file has to be loaded from $0400. An example how to put such file onto a disk using CPCDiskXP:
The file has to be loaded from $0400. An example how to put such a file onto a disk using CPCDiskXP:
CPCDiskXP -File FILENAME -AddAmsdosHeader 0400 -AddToNewDsk disk_image.dsk

View File

@ -3,6 +3,7 @@
## Adding a custom platform
Every platform is defined in an `.ini` file with an appropriate name.
The file is looked up in the directories on the include path, first directly, then in the `platform` subdirectory.
As an extension, multiline entries are supported:
if a line ends with a backslash character, the value continues to the next line.
@ -36,8 +37,11 @@ if a line ends with a backslash character, the value continues to the next line.
* `z80` (Zilog Z80)
* `strictz80` (Z80 without illegal instructions)
* `r800` (R800)
* `z80next` (Z80 core from ZX Spectrum Next)
* `z80next` (Z80 core from ZX Spectrum Next)
Note: Millfork version 0.3.18 and earlier uses the name `zx80next` for this architecture.
* `i8080` (Intel 8080)
@ -59,7 +63,8 @@ See [the list of available encodings](../lang/text.md).
* `screen_encoding` default encoding for screencodes (literals with encoding specified as `scr`).
Default: the same as `encoding`.
* `modules` comma-separated list of modules that will be automatically imported
* `modules` comma-separated list of modules that will be automatically imported.
This list cannot contain module template instantiations.
* other compilation options (they can be overridden using commandline options):
@ -77,6 +82,8 @@ Default: the same as `encoding`.
* `emit_x80` whether the compiler should emit instructions present on Sharp LR35902 and Z80, but absent on Intel 8080, default is `true` on compatible processors and `false` elsewhere
* `emit_z80` whether the compiler should emit Zilog Z80 instructions not covered by `emit_x80`, default is `true` on compatible processors and `false` elsewhere
* `emit_r800` whether the compiler should emit R800 instructions, default is `true` on compatible processors and `false` elsewhere
* `prevent_jmp_indirect_bug` whether the compiler should try to avoid the indirect JMP bug,
default is `false` on 65C02-compatible or non-6502 processors and `true` elsewhere
@ -112,6 +119,13 @@ Default: the same as `encoding`.
* `iy_scratch` allow using the IY register for other purposes, default is `false`
* `u_stack` use the U register to access stack variables, default is `false`. Applicable only to 6809-based targets.
* `y_stack` use the Y register to access stack variables, default is `false`. Applicable only to 6809-based targets.
**Warning: Currently, picking either `u_stack` or `y_stack` is required,
unless you want to always specify this option in the compiler's command line!**
The compiler doesn't support accessing the stack variables via the S stack pointer register yet.
* `software_stack` use software stack for stack variables, default is `false`. Applicable only to 6502-based targets.
* `output_intel_syntax` use Intel syntax instead of Zilog syntax, default is `true` for Intel 8080/8085 and `false` otherwise
@ -163,7 +177,7 @@ Default: `after_code`.
* `segment_NAME_bank` the bank number the segment belongs to. Default: `0`.
For better debugging on NES, RAM segments should use bank number `$ff`.
* `segment_NAME_fill` the byte value used to fill gaps and other unused space in the bank. Default: `0`.
* `segment_NAME_fill` the byte value used to fill gaps and other unused space in the segment. Default: `0`.
* `segment_NAME_layout` a comma-separated list of object names that defines in what order the objects are laid out in the segment.
One item has to be `*`, it means "all the other objects".
@ -194,9 +208,15 @@ Default: `main,*`
* `endaddr_be` the same, but big-endian
* `startaddr+123`, `startaddr_be+123`, `endaddr+123`, `endaddr_be+123` the same, but incremented by the given number
* `addr:XXXX` little-endian 16-bit address of the symbol XXXX
* `addr_be:XXXX` the same, but big-endian
* `startaddr+123`, `startaddr_be+123`, `endaddr+123`, `endaddr_be+123`, `addr:XXXX+123`, `addr_be:XXXX+123` the same, but incremented by the given number
* `startaddr-123`, `startaddr_be-123`, `endaddr-123`, `endaddr_be-123` the same, but decremented by the given number
* the number can be decimal, hexadecimal, octal, quaternary or binary
* `startaddr-123`, `startaddr_be-123`, `endaddr-123`, `endaddr_be-123`, `addr:XXXX-123`, `addr_be:XXXX-123` the same, but decremented by the given number
* `startpage` the high byte of `startaddr`
@ -207,18 +227,30 @@ Default: `main,*`
* `length+123`, `length_be+123` the same, but incremented by the given number
* `length-123`, `length_be-123` the same, but decremented by the given number
* `programname-123` the name of the program of the given length, uppercase ASCII, padded with spaces
* `allocated` all used bytes
* `pagecount` the number of pages used by all used bytes (including partially filled pages)
* `"<string>"` literal ASCII string; commas, non-ASCII characters and escape sequences are not supported
* `<addr>:<addr>` - inclusive range of bytes
* `<segment>:<addr>:<addr>` - inclusive range of bytes in a given segment
* `d88` - a D88 floppy disk image for PC-88
* `tap` - a tape disk image for ZX Spectrum
* `tap:XXXX` - a tape image for ZX Spectrum; XXXX is the name of the entry point to the program
* `tap` equivalent to `tap:main`
* `trscmd:XXXX` - a chunked loadable executable for TRS-80 Model 1 or 3 running TRS-DOS, also known as the /CMD format; XXXX is the name of the entry point to the program
* `trscmd` - equivalent to `trscmd:main`
* `format_segment_NAME` if using the `per_segment` style, overrides the format for the given segment
* `extension` target file extension, with or without the dot
@ -235,3 +267,7 @@ Default: `main,*`
* `sym` format used by the WLA/DX assembler. The extension is `.sym`.
* `fceux` multi-file format used by the FCEUX emulator. The extension is `.nl`.
* `mesen` format used by the Mesen emulator. The extension is `.mlb`.
* `ld65` format used by the `ld65` linker. The extension is `.dbg`.

View File

@ -36,7 +36,7 @@ The minimal Famicom program thus looks like this:
To use a mapper of your choice, create a new `.ini` file with the definitions you need.
The most important ones are `[output]format` and `[allocation]segments`.
Currently, its a bit inconvenient to create programs using mappers that change the bank containing the interrupt vectors.
Currently, it's a bit inconvenient to create programs using mappers that change the bank containing the interrupt vectors.
Therefore, it's recommended to stick to mappers that have a fixed bank at the end of the address space.
Mappers that should be fine: NROM (0), CNROM (1), UxROM(2), MMC2 (9), MMC3 (4), MMC4 (10), MMC6 (4).
@ -60,7 +60,7 @@ just specify them correctly in the `[output]format` tag.
The `[output]format` tag should contain a valid iNES or NES 2.0 header of the mapper of your choice
and then all the segments in proper order (first PRGROM, then CHRROM).
See [the MMC4 example](../../include/nes_mmc4.ini) to see how it can be done.
See [the MMC4 example](https://github.com/KarolS/millfork/blob/master/include/nes_mmc4.ini) to see how it can be done.
See [the NesDev wiki](https://wiki.nesdev.com/w/index.php/NES_2.0) for more info about the NES 2.0 file format.

View File

@ -99,6 +99,18 @@ The compiler emits COM files.
* `cpm_z80` CP/M on Z80
* `z1013` Robotron Z1013. The compiler emits Z80 files.
* `trs80m1cmd` TRS-80 Model 1 running TRS-DOS. The compiler emits CMD files.
* `trs80m3cmd` TRS-80 Model 3 running TRS-DOS. The compiler emits CMD files.
* `coco_rsdos` Tandy Color Computer running RS-DOS. (very experimental)
Read [the Color Computer programming guide](./coco-programming-guide.md) for more info.
* `coco_crt` 16K cartridge for Tandy Color Computer. (very experimental)
Read [the Color Computer programming guide](./coco-programming-guide.md) for more info.
* `dos_com` a COM file for DOS on IBM PC. (very experimental)
* `x16_experimental` Commander X16; very experimental,

View File

@ -16,6 +16,8 @@
* [Preprocessor](lang/preprocessor.md)
* [Modules](lang/modules.md)
* [Syntax](lang/syntax.md)
* [Types](lang/types.md)
@ -24,8 +26,12 @@
* [Predefined constants](lang/predefined_constants.md)
* [List of magic suffixes](lang/suffixes.md)
* [List of text encodings and escape sequences](lang/text.md)
* [Defining custom encodings](lang/custom-encoding.md)
* [Operators reference](lang/operators.md)
* [Functions](lang/functions.md)
@ -38,35 +44,59 @@
* [Important guidelines regarding reentrancy](lang/reentrancy.md)
* [Optimization hints](lang/hints.md)
* [List of keywords](lang/keywords.md)
## Library reference
* [`stdlib` module](stdlib/stdlib.md)
* [`string` and `scrstring` modules](stdlib/string.md)
* [`string`, `scrstring` and `pstring` modules](stdlib/string.md)
* [`stdio` module](stdlib/stdio.md)
* [Modules for reading input devices](stdlib/input.md)
* Reading input devices:
* [`joy` module](stdlib/joy.md)
* [`keyboard` module](stdlib/keyboard.md)
* [`mouse` module](stdlib/mouse.md)
* [`encconv` module](stdlib/encconv.md)
* [Other cross-platform modules (`keyboard`, `err`, `random`)](stdlib/other.md)
* [Other cross-platform modules (`err`, `random`)](stdlib/other.md)
* [Definitions available on only some platforms](stdlib/frequent.md)
* Platform-specific modules:
* [C64-only modules](stdlib/c64.md)
* [Definitions available on only some platforms](stdlib/frequent.md)
* [`cbm_file` module](stdlib/cbm_file.md)
* [C64-only modules](stdlib/c64.md)
* [NES-only modules](stdlib/nes.md)
* [VIC-20-only modules](stdlib/vic20.md)
* [PET-only modules](stdlib/cbm_pet.md)
* [`cbm_file` module](stdlib/cbm_file.md)
* [Atari Lynx-only modules](stdlib/lynx.md)
* [Apple II-only modules](stdlib/apple2.md)
* [NES-only modules](stdlib/nes.md)
* [Atari Lynx-only modules](stdlib/lynx.md)
* [Game Boyonly modules](stdlib/gb.md)
* [X16only modules](stdlib/x16.md)
## Guides
* [Game Boyonly modules](stdlib/gb.md)
* [Differences from C](various/cdiff.md)
* [X16only modules](stdlib/x16.md)
* [Differences from other assemblers](various/asmdiff.md)
* [Optimization guide](various/optimization.md)
## Implementation details

View File

@ -33,6 +33,6 @@ Millfork is © by Karol Stasiak, and is released under the GNU Public License ve
Millfork standard include files are © by Karol Stasiak, and are released under the zlib License.
Millfork documentation is realeased under the [CC0 1.0 Universal (CC0 1.0) Public Domain Dedication](https://creativecommons.org/publicdomain/zero/1.0/).
Millfork documentation is released under the [CC0 1.0 Universal (CC0 1.0) Public Domain Dedication](https://creativecommons.org/publicdomain/zero/1.0/).
This means you are allowed to develop Millfork programs, both free and proprietary, open- and closed-source, without any extra obligations or requirements.

View File

@ -13,6 +13,9 @@ There are two ways to include raw assembly code in your Millfork programs:
Millfork inline assembly uses the same three-letter opcodes as most other 6502 assemblers.
Indexing syntax is also the same. Only instructions available on the current CPU architecture are available.
The short branching instructions and the `BRK` instruction support the immediate addressing mode,
for more control over code generation.
The `BBRn/BBSn/SMBn/RMBn` instructions cannot parameterize the tested bit. The syntax is as follows:
BBR1 $10,label
@ -36,7 +39,7 @@ Currently, some extra 65CE02/65816 instructions are not supported yet.
Undocumented instructions are supported using various opcodes.
Labels have to be followed by a colon and they can optionally be on a separate line.
Labels have to be followed by a colon, and they can optionally be on a separate line.
Indentation is not important:
first: INC x
@ -45,9 +48,20 @@ Indentation is not important:
INC z
Label names have to start with a letter and can contain digits, underscores and letters.
This means than they cannot start with a period like in many other assemblers.
Similarly, anonymous labels designated with `+` or `-` are also not supported.
Global label names have to start with a letter and can contain digits, underscores and letters.
Local label names (available since Millfork 0.3.22) start with a period and are visible only in the given function.
Anonymous labels designated with `+` or `-` are also not supported.
Referring to a global label with an offset requires wrapping it in `label(…)`:
STA .local_opcode // ok
STA label(.local_opcode) // ok
STA .local_opcode + 1 // ok
STA label(.local_opcode) + 1 // ok
STA global_opcode // ok
STA label(global_opcode) // ok
STA global_opcode + 1 // NOT OK
sta label(global_opcode) + 1 // ok
Assembly can refer to variables and constants defined in Millfork,
but you need to be careful with using absolute vs immediate addressing:
@ -67,7 +81,7 @@ but you need to be careful with using absolute vs immediate addressing:
}
Any assembly opcode can be prefixed with `?`, which allows the optimizer change it or elide it if needed.
Opcodes without that prefix will be always compiled as written.
Opcodes without that prefix will always be compiled as written.
The '!' prefix marks the statement as volatile, which means it will be a subject to certain, but not all optimizations,
in order to preserve its semantics.
@ -110,7 +124,7 @@ the return type can be any valid return type, like for Millfork functions.
If the size of the return type is one byte,
then the result is passed via the accumulator.
If the size of the return type is two bytes,
then the low byte of the result is passed via the accumulator
then the low byte of the result is passed via the accumulator,
and the high byte of the result is passed via the X register.
@ -148,9 +162,11 @@ Non-macro functions can only have their parameters passed via registers:
* `word xa`, `word ax`, `word ay`, `word ya`, `word xy`, `word yx`: a 2-byte word byte passed via given two CPU registers,
with the high byte passed through the first register and the low byte passed through the second register; any 2-byte type can be used
* the above, but written more explicitly: `byte register(a) paramname`, `byte register(x) paramname`, `word register(ax) paramname` etc.
For example, this piece of code:
asm void f(word ax) @F_ADDR extern
asm void f(word register(ax) value) @F_ADDR extern
f(5)
@ -176,7 +192,7 @@ Macro assembly functions can have maximum one parameter passed via a register.
An external function should be declared with a defined memory address
and the `extern` keyword instead of the body:
asm void putchar(byte a) @$FFD2 extern
asm void putchar(byte register(a) char) @$FFD2 extern
## Safe assembly
@ -215,7 +231,7 @@ it should abide to the following rules:
* explicitly use 16-bit immediate operands when appropriate; the assembler doesn't track flags and assumes 8-bit immediates by default (TODO: actually implement the 16-bit inline assembly correctly)
* use far jumps unless you're sure that the called function returns with an `RTS`
* use far jumps unless you are sure the called function returns with an `RTS`
* on 65CE02:

View File

@ -14,7 +14,7 @@ There are two ways to include raw assembly code in your Millfork programs:
Millfork inline assembly uses the same three-letter opcodes as most other 6809 assemblers.
Labels have to be followed by a colon and they can optionally be on a separate line.
Labels have to be followed by a colon, and they can optionally be on a separate line.
Indentation is not important:
first: INC a
@ -23,9 +23,20 @@ Indentation is not important:
INC c
Label names have to start with a letter and can contain digits, underscores and letters.
This means than they cannot start with a period like in many other assemblers.
Similarly, anonymous labels designated with `+` or `-` are also not supported.
Global label names have to start with a letter and can contain digits, underscores and letters.
Local label names (available since Millfork 0.3.22) start with a period and are visible only in the given function.
Anonymous labels designated with `+` or `-` are also not supported.
Referring to a global label with an offset requires wrapping it in `label(…)`:
STA .local_opcode // ok
STA label(.local_opcode) // ok
STA .local_opcode + 1 // ok
STA label(.local_opcode) + 1 // ok
STA global_opcode // ok
STA label(global_opcode) // ok
STA global_opcode + 1 // NOT OK
STA label(global_opcode) + 1 // ok
Assembly can refer to variables and constants defined in Millfork,
but you need to be careful with using absolute vs immediate addressing:
@ -42,9 +53,17 @@ but you need to be careful with using absolute vs immediate addressing:
}
return result
}
To use the direct addressing mode, prepend the argument with `<`:
CLR <$6f // clears the byte $6f in the direct page
CLR $6f // clears the byte $006f (absolute address!)
You can use `>` do signify the absolute addressing mode, but it is never necessary.
This option exists only for compatibility with other assemblers.
Any assembly opcode can be prefixed with `?`, which allows the optimizer change it or elide it if needed.
Opcodes without that prefix will be always compiled as written.
Opcodes without that prefix will always be compiled as written.
The '!' prefix marks the statement as volatile, which means it will be a subject to certain, but not all optimizations,
in order to preserve its semantics.
@ -120,6 +139,8 @@ Non-macro functions can only have their parameters passed via registers:
* `word d`, `word x`, `word y`: a 2-byte word byte passed via given 16-bit register; any 2-byte type can be used
* the above, but written more explicitly: `byte register(a) paramname`, `byte register(b) paramname`, `word register(x) paramname` etc.
Parameters passed via other registers (`U`, `S` etc.) or combinations of registers do not work yet.
**Work in progress**:

View File

@ -22,12 +22,17 @@ LR35902 instructions that load/store the accumulator indirectly via HL and then
LR35902 instructions for faster access to the $FFxx addresses use the `LDH` mnemonic: `LDH A,(4)`, `LDH (C),A` etc.
Only instructions available on the current CPU architecture are available.
Intel syntax does not support instructions that are unavailable on the 8080.
Undocumented Z80 instructions are not supported, except for `SLL`.
Undocumented Z80 instructions are partially supported:
* `SLL` supported
* instructions using the IXH, IXL, IYH, IYL registers supported (can only be used in Zilog syntax)
* instructions of the form `RLC IX(1),B` not supported
Not all ZX Spectrum Next are supported. `JP (C)`, `BSLA` and similar instructions are not supported.
Intel syntax supports the 8080 instructions, the documented Z80 instructions and `SLL`.
It does not support instructions that are unavailable on the Z80 or other undocumented Z80 instructions.
Labels have to be followed by a colon and they can optionally be on a separate line.
Not all ZX Spectrum Next instructions are supported. `JP (C)`, `BSLA` and similar instructions are not supported.
Labels have to be followed by a colon, and they can optionally be on a separate line.
Indentation is not important:
// Zilog syntax
@ -43,9 +48,20 @@ Indentation is not important:
INR c
Label names have to start with a letter and can contain digits, underscores and letters.
This means than they cannot start with a period like in many other assemblers.
Similarly, anonymous labels designated with `+` or `-` are also not supported.
Global label names have to start with a letter and can contain digits, underscores and letters.
Local label names (available since Millfork 0.3.22) start with a period and are visible only in the given function.
Anonymous labels designated with `+` or `-` are also not supported.
Referring to a global label with an offset requires wrapping it in `label(…)`:
LD (.local_opcode),A // ok
LD (label(.local_opcode)),A // ok
LD (.local_opcode + 1),A // ok
LD (label(.local_opcode) + 1),A // ok
LD (global_opcode),A // ok
LD (label(global_opcode)),A // ok
LD (global_opcode + 1),A // NOT OK
LD (label(global_opcode) + 1),A // ok
Assembly can refer to variables and constants defined in Millfork,
but you need to be careful with using absolute vs immediate addressing:
@ -70,7 +86,7 @@ but you need to be careful with using absolute vs immediate addressing:
}
Any assembly opcode can be prefixed with `?`, which allows the optimizer change it or elide it if needed.
Opcodes without that prefix will be always compiled as written.
Opcodes without that prefix will always be compiled as written.
The '!' prefix marks the statement as volatile, which means it will be a subject to certain, but not all optimizations,
in order to preserve its semantics.
@ -160,6 +176,8 @@ Non-macro functions can only have their parameters passed via registers:
* `word hl`, `word bc`, `word de`: a 2-byte word byte passed via given 16-bit register; any 2-byte type can be used
* the above, but written more explicitly: `byte register(a) paramname`, `byte register(b) paramname`, `word register(hl) paramname` etc.
Parameters passed via other registers (`I`, `IX`, `IY`, `IXH` etc.) or combinations of registers do not work yet.
**Work in progress**:
@ -198,3 +216,108 @@ it should abide to the following rules:
* end non-inline assembly functions with `RET`, `JP`, `RETI` or `RETN` (Zilog) / `RET` or `JMP` (Intel) as appropriate
The above list is not exhaustive.
## Z80 instructions in the Intel syntax
Millfork uses the same extensions for Intel syntax as Z80.LIB from Digital Research.
Some mnemonics from the TDL Z80 Relocating/Linking Assembler are also supported.
In the list below, `c` is a flag, `r` is a register, and `n` and `d` are parameters.
For instructions using the index registers, only the IY variant is given;
the IX variant has the same mnemonic, but with `Y` replaced with `X`.
Intel syntax | Zilog syntax
----|----
**EXAF** | **EX AF,AF'**
**JR n**, JMPR n | **JR n**
**JRc n** | **JR c,n**
**INP r** | **IN r,(C)**
**OUTP r** | **OUT r,(C)**
**CCI** | **CPI**
**CCIR** | **CPIR**
**CCD** | **CPD**
**CCDR** | **CPDR**
**OUTIR** | **OTIR**, OUTIR
**OUTDR** | **OTDR**, OUTDR
**IM0** | **IM 0**
**IM1** | **IM 1**
**IM2** | **IM 2**
**DSBC r** | **SBC HL,rr**
**DADC r** | **ADC HL,rr**
**DADY r** | **ADD IY,rr**
**INXIY**, INX IY | **INC IY**
**DCXIY**, DCX IY | **DEC IY**
**SBCD nn** | **LD (nn),BC**
**SDED nn** | **LD (nn),DE**
**SSPD nn** | **LD (nn),SP**
**SIYD nn** | **LD (nn),IY**
**LBCD nn** | **LD BC,(nn)**
**LDED nn** | **LD DE,(nn)**
**LSPD nn** | **LD SP,(nn)**
**LIYD nn** | **LD IY,(nn)**
**SETB n,r**, SET n,r | **SET n,r**
**BITY n,d** | **BIT n,IY(d)**
**SETY n,d** | **SET n,IY(d)**
**RESY n,d** | **RES n,IY(d)**
**PCIY** | **JP IY**
**RLCR r** | **RLC r**
**RALR r** | **RL r**
**RRCR r** | **RRC r**
**RARR r** | **RR r**
**SLAR r** | **SLA r**
**SRAR r** | **SRA r**
**SRLR r** | **SRL r**
**RLCX r** | **RLC r**
**RALY d** | **RL IY(d)**
**RRCY d** | **RRC IY(d)**
**RARY d** | **RR IY(d)**
**SLAY d** | **SLA IY(d)**
**SRAY d** | **SRA IY(d)**
**SRLY d** | **SRL IY(d)**
**SLLR r** | **SLL r**, SLS r
**SLLY d** | **SLL IY(d)**, SLS IY(d)
**SPIY** | **LD SP,IY**
**PUSHIY**, PUSH IY | **PUSH IY**
**POPIY**, POP IY | **POP IY**
**XTIY** | **EX (SP),IY**
**LDAI** | **LD A,I**
**LDAR** | **LD A,R**
**STAI** | **LD I,A**
**STAR** | **LD R,A**
**LXIY nn**, LXI IY,nn | **LD IY,nn**
**ADDY d** | **ADD A,IY(d)**
**ADCY d** | **ADC A,IY(d)**
**SUBY d** | **SUB IY(d)**
**SBCY d** | **SBC A,IY(d)**
**ANDY d** | **AND IY(d)**
**XORY d** | **XOR IY(d)**
**ORY d** | **OR IY(d)**
**CMPY d** | **CMP IY(d)**
**INRY d** | **INC IY(d)**
**DCRY d** | **DEC IY(d)**
**MVIY n,d** | **LD IY(d),n**
**LDY r,d** | **LD r,IY(d)**
**STY r,d** | **LD IY(d),r**
Instructions that are the same in both syntaxes:
**BIT n,r**,
**RES n,r**,
**DJNZ n**,
**EXX**,
**NEG**,
**RETI**,
**RETN**,
**RLD**,
**RRD**,
**LDI**,
**LDIR**,
**LDD**,
**LDDR**,
**INI**,
**INIR**,
**IND**,
**INDR**,
**OUTI**,
**OUTD**

View File

@ -0,0 +1,52 @@
[< back to index](../doc_index.md)
### Defining custom encodings
Every encoding is defined in an `.tbl` file with an appropriate name.
The file is looked up in the directories on the include path, first directly, then in the `encoding` subdirectory.
The file is a UTF-8 text file, with each line having a specific meaning.
In the specifications below, `<>` are not to be meant literally:
* lines starting with `#`, `;` or `//` are comments.
* `ALIAS=<another encoding name>` defines this encoding to be an alias for another encoding.
No other lines are allowed in the file.
* `NAME=<name>` defines the name for this encoding. Required.
* `BUILTIN=<internal name>` defines this encoding to be a UTF-based encoding.
`<internal name>` may be one of `UTF-8`, `UTF-16LE`, `UTF-16BE`, `UTF-32LE`, `UTF-32BE`.
If this directive is present, the only other allowed directive in the file is the `NAME` directive.
* `EOT=<xx>` where `<xx>` are two hex digits, defines the string terminator byte.
Required, unless `BUILTIN` is present.
There have to be two digits, `EOT=0` is invalid.
* lines like `<xx>=<c>` where `<xx>` are two hex digits
and `<c>` is either a **non-whitespace** character or a **BMP** Unicode codepoint written as `U+xxxx`,
define the byte `<xx>` to correspond to character `<c>`.
There have to be two digits, `0=@` is invalid.
* lines like `<xx>-<xx>=<c><c><c><c>` where `<c>` is repeated an appropriate number of times
define characters for multiple byte values.
In this kind of lines, characters cannot be represented as Unicode codepoints.
* lines like `<c>=<xx>`, `<c>=<xx><xx>` etc.
define secondary or alternate characters that are going to be represented as one or more bytes.
There have to be two digits, `@=0` is invalid.
Problematic characters (space, `=`, `#`, `;`) can be written as Unicode codepoints `U+xxxx`.
* a line like `a-z=<xx>` is equivalent to lines `a=<xx>`, `b=<xx+$01>` all the way to `z=<xx+$19>`.
* a line like `KATAKANA=>DECOMPOSE` means that katakana characters with dakuten or handakuten
should be split into the base character and the standalone dakuten/handakuten.
* similarly with `HIRAGANA=>DECOMPOSE`.
* lines like `{<escape code>}=<xx>`, `{<escape code>}=<xx><xx>` etc.
define escape codes. It's a good practice to define these when possible:
`{q}`, `{apos}`, `{n}`, `{lbrace}`, `{rbrace}`,
`{yen}`, `{pound}`, `{cent}`, `{euro}`, `{copy}`, `{pi}`,
`{nbsp}`, `{shy}`.

View File

@ -4,17 +4,17 @@
Syntax:
`[segment (<segment>)] [<modifiers>] <return_type> <name> ( <params> ) [align ( <alignment> )] [@ <address>] { <body> }`
`[segment (<segment>)] [<modifiers>] <return_type> <name> ( <params> ) [align ( <alignment> )] [<optimization hints>] [@ <address>] { <body> }`
`[segment (<segment>)] [<modifiers>] <return_type> <name> ( <params> ) [align ( <alignment> )] [@ <address>] = <expression>`
`[segment (<segment>)] [<modifiers>] <return_type> <name> ( <params> ) [align ( <alignment> )] [<optimization hints>] [@ <address>] = <expression>`
`[segment (<segment>)] asm <return_type> <name> ( <params> ) @ <address> extern`
`[segment (<segment>)] asm <return_type> <name> ( <params> ) [<optimization hints>] @ <address> extern`
Examples:
void do_nothing() { }
inline byte two() = 2
extern asm void chkout(byte a) @ $FFD2
asm void chkout(byte register(a) char) !preserves_x !preserves_y @ $FFD2 extern
segment(prgrom0) void main_loop(word w, byte x) align(fast) { // body omitted
@ -39,13 +39,23 @@ Examples:
You are not allowed to call such functions directly.
The function cannot have parameters and the return type should be `void`.
* `kernal_interrupt` the function is an interrupt handler called from a generic vendor-provider hardware interrupt handler.
* `kernal_interrupt` the function is an interrupt handler called from a generic vendor-provided hardware interrupt handler.
The hardware instruction handler is assumed to have preserved the CPU registers,
so this function only has to preserve the zeropage pseudoregisters.
An example is the Commodore 64 interrupt handler that calls the function at an address read from $314/$315.
Unlike hardware handlers with `interrupt`, you can treat functions with `kernal_interrupt` like normal functions.
On non-6502-based targets, functions marked as `kernal_interrupt` don't differ from normal functions.
* `const` the function is pure and can be used in constant expressions. `const` functions are not allowed to:
* use constants that have been declared after them
* have local variables
* call non-const functions
* contain any other statements other than return statements and conditional statements
* `<return_type>` is a valid return type, see [Types](./types.md)
* `<params>` is a comma-separated list of parameters, in form `type name`. Allowed types are the same as for local variables.
@ -58,6 +68,8 @@ For assembly functions, certain parameter names are interpreted as CPU registers
* on 6502, it means that the function will not cross a page boundary if possible
* on Z80, it is ignored
* `<optimization hints>` is a list of [optimization hints](./hints.md), separated by spaces
* `<address>` is a constant expression that defines where in the memory the function is or will be located.
* `extern` is a keyword than marks functions that are not defined in the current program,
@ -68,16 +80,19 @@ Such functions should be marked as written in assembly and should have their par
* `<expression>` is an expression. It is equivalent to a function body of form `{ return <expression> }`.
The address of an non-macro function `f` is a constant `f.addr`.
The address of a non-macro function `f` is a constant `f.addr`.
Non-macro, non-interrupt functions which have max one parameter of size max 2 bytes
and return `void` or a value of size max 2 bytes,
can be accessed via a pointer.
void f() {}
void g(byte x) {}
function.void.to.void p = f.pointer
function.byte.to.void p = g.pointer
call(p)
call(p, 13)
The value of the pointer `f.pointer` may not be the same as the value of the function address `f.addr`.

84
docs/lang/hints.md Normal file
View File

@ -0,0 +1,84 @@
[< back to index](../doc_index.md)
# Optimization hints
Optimization hints are optional annotations for functions and variables
that allow the compiler to make extra assumptions that help with code optimization.
The general idea is that removing or disabling optimization hints will not break the code,
but adding invalid optimization hints may break the code.
Every optimization hint's name starts with an exclamation mark.
Optimization hints marked with **(X)** currently do nothing and are planned to be implemented in the future.
## Hints for functions
* `!preserves_memory` the function does not write to memory
* `!idempotent` calling the function multiple times in succession has no effect
* `!hot` the function is hot and should be optimized for speed at the cost of increased size
* `!cold` **(X)** the function is cold and should be optimized for size at the cost of increased run time
* `!odd` the function returns an odd value
* `!even` the function returns an even value
## Hints for 6502 assembly functions
These hints have only effect when used on an assembly function on a 6502 target:
* `!preserves_a` the function preserves the contents of the A register
* `!preserves_x` the function preserves the contents of the X register
* `!preserves_y` the function preserves the contents of the Y register
* `!preserves_c` the function preserves the contents of the carry flag
## Hints for 8080/Z80/LR35902 assembly functions
These hints have only effect when used on an assembly function on a 8080-like target:
* `!preserves_a` the function preserves the contents of the A register
* `!preserves_bc` the function preserves the contents of the B and C registers
* `!preserves_de` the function preserves the contents of the D and E registers
* `!preserves_hl` the function preserves the contents of the H and L registers
* `!preserves_cf` the function preserves the contents of the carry flag
## Hints for 6809 assembly functions
These hints have only effect when used on an assembly function on a 6809 target:
* `!preserves_a` the function preserves the contents of the A register
* `!preserves_b` the function preserves the contents of the B register
* `!preserves_d` the function preserves the contents of the A and B register
* `!preserves_dp` **(X)** the function preserves the contents of the DP register; exceptionally this can also be used on non-assembly functions
* `!preserves_x` the function preserves the contents of the X register
* `!preserves_y` the function preserves the contents of the Y register
* `!preserves_u` the function preserves the contents of the U register
* `!preserves_c` the function preserves the contents of the carry flag
## Hints for variables
* `!odd` **(X)** the variable can only contain odd values
* `!even` **(X)** the variable can only contain even values

View File

@ -7,10 +7,10 @@
To call an external function, you need to declare it as `asm extern`. For example:
```
asm void putchar(byte a) @$FFD2 extern
asm void putchar(byte register(a) char) @$FFD2 extern
```
The function parameter will be passed via the accumulator,
In this example, the function parameter will be passed via the accumulator,
the function itself is located in ROM at $FFD2. A call like this:
```
@ -36,7 +36,7 @@ To call a function that has its address calculated dynamically,
you just need to do the same as what you would do in assembly; 6502 example:
```
asm void call_function(byte a) {
asm void call_function(byte register(a) param) {
JMP (function_address)
}
```

View File

@ -14,7 +14,14 @@ Octal: `0o172`
Hexadecimal: `$D323`, `0x2a2`
When using Intel syntax for inline assembly, another hexadecimal syntax is available: `0D323H`, `2a2h`.
Digits can be separated by underscores for readability. Underscores are also allowed between the radix prefix and the digits:
123_456
0x01_ff
0b_0101_1111__1100_0001
$___________FF
When using Intel syntax for inline assembly, another hexadecimal syntax is available: `0D323H`, `2a2h`, `3e_h`.
It is not allowed in any other places.
The type of a literal is the smallest type of undefined signedness
@ -63,13 +70,44 @@ The byte constant `nullchar` is defined to be equal to the string terminator in
and the byte constant `nullchar_scr` is defined to be equal to the string terminator in the `scr` encoding (`'{nullchar}'scr`).
You can override the values for `nullchar` and `nullchar_scr`
by defining preprocesor features `NULLCHAR` and `NULLCHAR_SCR` respectively.
by defining preprocessor features `NULLCHAR` and `NULLCHAR_SCR` respectively.
Warning: If you define UTF-16 to be you default or screen encoding, you will encounter several problems:
Warning: If you define UTF-16 or UTF-32 to be you default or screen encoding, you will encounter several problems:
* `nullchar` and `nullchar_scr` will still be bytes, equal to zero.
* the `string` module in the Millfork standard library will not work correctly
## Length-prefixed strings (Pascal strings)
You can also prepend `p` to the name of the encoding to make the string length-prefixed.
The length is measured in bytes and doesn't include the zero terminator, if present.
In all encodings except for UTF-16 and UTF-32 the prefix takes one byte,
which means that length-prefixed strings cannot be longer than 255 bytes.
In case of UTF-16, the length prefix contains the number of code units,
so the number of bytes divided by two,
which allows for strings of practically unlimited length.
The length is stored as two bytes and is always little endian,
even in case of the `utf16be` encoding or a big-endian processor.
In case of UTF-32, the length prefix contains the number of Unicode codepoints,
so the number of bytes divided by four.
The length is stored as four bytes and is always little endian,
even in case of the `utf32be` encoding or a big-endian processor.
"this is a Pascal string" pascii
"this is also a Pascal string"p
"this is a zero-terminated Pascal string"pz
Note: A string that's both length-prefixed and zero-terminated does not count as a normal zero-terminated string!
To pass it to a function that expects a zero-terminated string, add 1 (or, in case of UTF-16, 2, or UTF-32, 4):
pointer p
p = "test"pz
// putstrz(p) // won't work correctly
putstrz(p + 1) // ok
## Escape sequences and miscellaneous compatibility issues
Most characters between the quotes are interpreted literally.
@ -175,6 +213,7 @@ An array is initialized with either:
array b = "----" scr
array c = ["hello world!" ascii, 13]
array d = file("d.bin")
array d1 = file("d.bin", 128)
array e = file("d.bin", 128, 256)
array f = for x,0,until,8 [x * 3 + 5] // equivalent to [5, 8, 11, 14, 17, 20, 23, 26]
array(point) g = [point(2,3), point(5,6)]
@ -182,8 +221,19 @@ An array is initialized with either:
Trailing commas (`[1, 2,]`) are not allowed.
String literals are laid out in the arrays as-is, flat.
To have an array of pointers to strings, wrap each string in `pointer(...)`:
// a.length = 12; identical to [$48, $45, $4C, $4C, $4F, 0, $57, $4F, $52, $4C, $44, 0]
array a = [ "hello"z, "world"z ]
// b.length = 2
array(pointer) b = [ pointer("hello"z), pointer("world"z) ]
The parameters for `file` are: file path, optional start offset, optional length
(start offset and length have to be either both present or both absent).
(if only two parameters are present, then the second one is assumed to be the start offset).
The `file` expression is expanded at the compile time to an array of bytes equal to the bytes contained in the file.
If the start offset is present, then that many bytes at the start of the file are skipped.
If the length is present, then only that many bytes are taken, otherwise, all bytes until the end of the file are taken.
The `for`-style expression has a variable, a starting index, a direction, a final index,
and a parameterizable array initializer.
@ -195,7 +245,7 @@ Fields of arithmetic, pointer and enum types are declared using normal expressio
Fields of struct types are declared using struct constructors.
Fields of union types cannot be declared.
What might be useful is the fact that the compiler allows for built-in trigonometric functions
What might be useful is the fact that the compiler allows for certain built-in functions
in constant expressions only:
* `sin(x, n)` returns _n_·**sin**(*x*π/128)
@ -204,3 +254,7 @@ in constant expressions only:
* `tan(x, n)` returns _n_·**tan**(*x*π/128)
* `min(x,...)` returns the smallest argument
* `max(x,...)` returns the largest argument

98
docs/lang/modules.md Normal file
View File

@ -0,0 +1,98 @@
[< back to index](../doc_index.md)
# Program structure
A Millfork program is build from one or more modules.
Each module is stored in a single file.
All source filenames passed to the compiler are considered to be modules of that program, called _root modules_.
Each module has a name, which is its unique identifier.
A module name is a sequence of slash-separated valid Millfork identifiers.
The name also defines where the module is located:
a module named `a/b` is presumed to exist in `a/b.mfk`
and it's looked up first in the directory that contains the current source file,
then in the current working directory,
and then in the include directories.
A module can import other modules, using the `import` statement.
Importing the same module multiple times merely marks it as imported by multiple modules,
but the program will still contain only one copy of it.
Examples:
import string
import cbm_file
Usually, the imported module will undergo the first phase of compilation first.
This means that the constants in the imported module will be resolved first, allowing you to use them in the importing module.
The only exception to this rule is when the importing graph has a cycle, in which case the order of modules within the cycle is unspecified.
A platform may define starting modules using the `modules=` directive of the `[compilation]` section.
All starting modules are considered to be imported by all source files explicitly mentioned on the command line.
### Module templates
If the first line of a source file starts with the `#template` directive,
then the source is considered to be a _module template_.
Module templates are a tool for generating repetitive code, similar to COBOL copybooks or Go Generate.
The template directive contains a comma-separated list of parameters.
It's recommended that the names of parameters begin and end with non-alphanumeric characters:
#template $P1$, $P2$
A module template cannot be imported as-is.
When importing a module template, you import a concrete instantiation of it.
For example, if the file `temp.mfk` contains the `#template` from above,
you can import it by providing a list of numeric literals or identifiers:
import temp<1, 2>
This instantiates a new module named `temp<1,2>` (if it hasn't been instantiated anywhere else).
The code in that module is generated by replacing every instance of the parameter names with the actual argument content.
Parameters that are numeric literals are normalized to their decimal representations.
Your program may contain multiple modules created from the same template with different parameters. For example,
import temp<3, 4>
import temp<5, 6>
import temp<$5, $6>
instantiates and imports two similar, yet different modules: `temp<3,4>` and `temp<5,6>`.
The third import imports a module that has already been instantiated and imported, so it's redundant.
The instantiation works through simple text replacement. For example, if `temp.mfk` contains:
#template $P1$, $P2$
const byte a$P1$ = $P2$
then the `temp<1,2>` module will contain
const byte a1 = 2
This substitution is performed before preprocessing, so those substitutions are available for the preprocessor directives.
It applies to identifiers, string literals, keywords, preprocesor directives etc.
**Warning:** This mechanism provides no direct way for preventing duplicates of code
that does not depend on the template parameters, or depends on only some template parameters.
In such situations, it might be advisable to put the non-dependent definitions in another module that is not a template,
or in a module template with fewer parameters. For example, instead of writing:
#template $N$
const byte X = 50
array a$N$ [X]
(which would define duplicate `X`s if imported multiple times), consider writing two files:
#template $N$
import define_X
array a$N$ [X]
>
//define_X.mfk:
const byte X = 50

View File

@ -18,9 +18,9 @@ Millfork has different operator precedence compared to most other languages. Fro
* `->` and `[]`
* `*`, `*'`
* `*`, `$*`, `/`, `%%`
* `+`, `+'`, `-`, `-'`, `|`, `&`, `^`, `>>`, `>>'`, `<<`, `<<'`, `>>>>`
* `+`, `$+`, `-`, `$-`, `|`, `&`, `^`, `>>`, `$>>`, `<<`, `$<<`, `>>>>`
* `:`
@ -34,9 +34,18 @@ Millfork has different operator precedence compared to most other languages. Fro
You cannot use two different operators at the same precedence levels without using parentheses to disambiguate.
It is to prevent confusion about whether `a + b & c << d` means `(a + b) & (c << d)` `((a + b) & c) << d` or something else.
The only exceptions are `+` and `-`, and `+'` and `-'`.
They are interpreted as expected: `5 - 3 + 2 == 4` and `5 -' 3 +' 2 == 4`.
Note that you cannot mix `+'` and `-'` with `+` and `-`.
The only exceptions are `+` and `-`, and `$+` and `$-`.
They are interpreted as expected: `5 - 3 + 2 == 4` and `5 $- 3 $+ 2 == 4`.
Note that you cannot mix `$+` and `$-` with `+` and `-`.
Certain operators (`/`, `%%`, `<<`, `>>`, `$<<`, `$>>`, `>>>>`, `:`, `!=`) cannot have more than 2 parameters,
i.e. `x / y / z` will not compile.
The decimal operators have two different forms:
* apostrophe form (e.g. `+'`) the original one, deprecated, will be removed in Millfork 0.4
* dollar form (e.g. `$+`) available since Millfork 0.3.22
## Argument types
@ -54,6 +63,8 @@ In the descriptions below, arguments to the operators are explained as follows:
* `constant` means a compile-time constant
* `trivial` means either a constant or a non-stack variable
* `simple` means either: a constant, a non-stack variable,
a pointer indexed with a constant, a pointer indexed with a non-stack variable,
an array indexed with a constant, an array indexed with a non-stack variable,
@ -77,14 +88,14 @@ TODO
## Binary arithmetic operators
* `+`, `-`:
* `+`, `-`: addition and subtraction
`byte + byte`
`constant word + constant word`
`constant long + constant long`
`constant word + byte`
`word + word` (zpreg)
* `*`: multiplication; the size of the result is the same as the size of the arguments
* `*`: multiplication (signed or unsigned); the size of the result is the same as the size of the largest of the arguments
`byte * constant byte`
`constant byte * byte`
`constant word * constant word`
@ -124,17 +135,20 @@ These operators work using the decimal arithmetic (packed BCD).
On Ricoh-based targets (e.g. Famicom) they require the zeropage register to have size at least 4
* `+'`, `-'`: decimal addition/subtraction
`byte +' byte`
`constant word +' constant word`
`constant long +' constant long`
`word +' word` (zpreg)
* `$+`, `$-`: decimal addition/subtraction
`+'`, `-'`: (deprecated form)
`byte $+ byte`
`constant word $+ constant word`
`constant long $+ constant long`
`word $+ word` (zpreg)
* `*'`: decimal multiplication
`constant *' constant`
* `$*`: decimal multiplication
`*'`: (deprecated form)
`constant $* constant`
* `<<'`, `>>'`: decimal multiplication/division by power of two
`byte <<' constant byte`
* `$<<`, `$>>`: decimal multiplication/division by power of two
`<<'`, `>>'`: (deprecated form)
`byte $<< constant byte`
## Comparison operators
@ -187,25 +201,28 @@ An expression of form `a[f()] += b` may call `f` an undefined number of times.
`mutable word = word`
`mutable long = long`
* `+=`, `+'=`, `|=`, `^=`, `&=`: modification in place
* `+=`, `$+=`, `|=`, `^=`, `&=`: modification in place
`+'=` (deprecated form)
`mutable byte += byte`
`mutable word += word`
`mutable long += long`
`mutable trivial long += long`
* `<<=`, `>>=`: shift in place
`mutable byte <<= byte`
`mutable word <<= byte`
`mutable long <<= byte`
`mutable trivial long <<= byte`
* `<<'=`, `>>'=`: decimal shift in place
`mutable byte <<'= constant byte`
`mutable word <<'= constant byte`
`mutable long <<'= constant byte`
* `$<<=`, `$>>=`: decimal shift in place
`<<'=`, `>>'=` (deprecated form)
`mutable byte $<<= constant byte`
`mutable word $<<= constant byte`
`mutable trivial long $<<= constant byte`
* `-=`, `-'=`: subtraction in place
* `-=`, `$-=`: subtraction in place
`-'=` (deprecated form)
`mutable byte -= byte`
`mutable word -= simple word`
`mutable long -= simple long`
`mutable trivial long -= simple long`
* `*=`: multiplication in place
`mutable byte *= constant byte`
@ -213,8 +230,9 @@ An expression of form `a[f()] += b` may call `f` an undefined number of times.
`mutable word *= unsigned byte` (zpreg)
`mutable word *= word` (zpreg)
* `*'=`: decimal multiplication in place
`mutable byte *'= constant byte`
* `$*=`: decimal multiplication in place
`*'=` (deprecated form)
`mutable byte $*= constant byte`
* `/=`, `%%=`: unsigned division and modulo in place
`mutable unsigned byte /= unsigned byte` (zpreg)
@ -273,9 +291,9 @@ but you can access its fields or take its pointer:
* `nonet`: expansion of an 8-bit operation to a 9-bit operation
`nonet(byte + byte)`
`nonet(byte +' byte)`
`nonet(byte $+ byte)`
`nonet(byte << constant byte)`
`nonet(byte <<' constant byte)`
`nonet(byte $<< constant byte)`
Other kinds of expressions than the above (even `nonet(byte + byte + byte)`) will not work as expected.
* `hi`, `lo`: most/least significant byte of a word
@ -292,7 +310,16 @@ but not
some enum → `word`
* `sizeof`: size of the argument in bytes; the argument can be an expression or a type,
and the result is a constant of either `byte` or `word` type, depending on the actual value
and the result is a constant of either `byte` or `word` type, depending on the actual value.
In case of aligned types, this returns the aligned size.
* `typeof`: a word constant that identifies the type of the argument; the argument can be an expression or a type.
The argument is never evaluated.
**Warnings:**
* **This is a highly experimental feature.**
* The exact values may change in any future version of the compiler. Only compare one `typeof` to another `typeof`.
* There is no guarantee that different types will have different values of `typeof`. Indeed, it's even easy to see that a Millfork program can have more than 65536 types and values of `typeof` can clash even before that.
* In certain circumstances, pointer types and function pointer types may have different `typeof` values even if they're essentially the same.
* `call`: calls a function via a pointer;
the first argument is the pointer to the function;

View File

@ -2,7 +2,9 @@
# Predefined constants
* `byte nullchar` the null terminator for strings in the default encoding, equivalent to `""z[0]`
* `byte nullchar` the null terminator for strings in the default encoding, equivalent to `""z[0]`, can be overriden by the `NULLCHAR` feature
* `byte nullchar_scr` the null terminator for strings in the screen encoding, equivalent to `""scrz[0]`, can be overriden by the `NULLCHAR_SCR` feature
* `null$ nullptr` the invalid pointer value; the value of the `NULLPTR` feature
@ -10,6 +12,10 @@
* `pointer segment.N.start` the value of `segment_N_start` from the platform definition
* `pointer segment.N.codeend` the value of `segment_N_codeend` from the platform definition
* `pointer segment.N.datastart` the value of `segment_N_datastart` from the platform definition
* `pointer segment.N.end` the value of `segment_N_end` from the platform definition
* `pointer segment.N.heapstart` the address of the first byte in the `N` segment that was not automatically allocated
@ -17,3 +23,7 @@
* `word segment.N.length` the number of byte locations between `segment_N_start` and `segment_N_end`, inclusive
* `byte segment.N.bank` the value of `segment_N_bank` from the platform definition
* `byte segment.N.fill` the value of `segment_N_fill` from the platform definition
* `this.function` the alias of the current function (in macros, it resolves to the actual non-macro function that called the macro)

View File

@ -54,10 +54,14 @@ The following features are defined based on the chosen CPU and compilation optio
`CPUFEATURE_8080`, `CPUFEATURE_8085`, `CPUFEATURE_GAMEBOY`, `CPUFEATURE_Z80`,
`CPUFEATURE_6502_ILLEGALS`, `CPUFEATURE_8085_ILLEGALS`, `CPUFEATURE_Z80_ILLEGALS`, `CPUFEATURE_Z80_NEXT` 1 if given instruction subset is enabled, 0 otherwise
* `ENCCONV_SUPPORTED` - 1 if the module `encconv` supports the function `to_screencode` and other related funtions, 0 otherwise.
* `ENCCONV_SUPPORTED` - 1 if the module `encconv` supports the function `to_screencode` and other related functions, 0 otherwise.
* `ENCODING_SAME` - 1 if the encodings `default` and `src` are the same, 0 otherwise.
* `ENCODING_NOLOWER` 1 if the `default` encoding does not support lowercase ASCII letters.
* `DECIMALS_SAME` - 1 if the encodings `default` and `src` have the same string terminator and decimal digits `'0'`-`'9'`, 0 otherwise.
* `NULLCHAR_SAME` - 1 if the encodings `default` and `src` have the same string terminator, 0 otherwise.
* `NULLCHAR` the value of the `nullchar` constant
@ -90,40 +94,55 @@ See [the ROM vs RAM guide](../api/rom-vs-ram.md) for more information.
### Commonly used features
These features are frequently defined in the platform definition file.
Some libraries may require that some of these be defined.
* `WIDESCREEN` 1 if the horizontal screen resolution, ignoring borders, is greater than 256, 0 otherwise
* `CBM` 1 if the target is an 8-bit Commodore computer (or a compatible one), 0 otherwise
* `CBM_64_COMPAT` 1 if the target is an 8-bit Commodore computer compatible with Commodore 64, 0 otherwise
* `CBM_64_CRT` 1 if the target is a cartridge for Commodore 64, 0 otherwise
* `CBM_264` 1 if the target is an 8-bit Commodore computer from the 264 line, 0 otherwise
* `TALLSCREEN` 1 if the vertical screen resolution, ignoring borders, is greater than 256, 0 otherwise
* `KEYBOARD` 1 if the target has a keyboard, 0 otherwise
* `DISPLACED_MAIN` set this to 1 if the `main` function is in a very unusual location for the target
* `USE_MOUSE_MBM` set this to 1 if you want to enable middle button support for the mouse.
* `JOYSTICKS` the maximum number of joysticks using standard hardware configurations, may be 0
* `HAS_BITMAP_MODE` 1 if the target has a display mode with every pixel addressable, 0 otherwise
* `MOS_6510` 1 if the target uses a MOS 6510-compatible processor (with an I/O port at $0000/$0001)
* `CPM` 1 if the target is CP/M, 0 otherwise
* `IBM_PC` 1 if the target is IBM PC, 0 otherwise
* `MSX` 1 if the target is MSX, 0 otherwise
* `NTSC` 1 if the target is NTSC, 0 otherwise
* `PAL` 1 if the target is PAL, 0 otherwise
* `NULLPTR` physical value of `nullptr`, default 0
* `VERA_VERSION` on Commander X16, the version of the VERA chip: `7` for 0.7, `8` for 0.8
### Target-specific features
These features are used to identify the target machine in multiplatform programs and libraries:
* `CBM` 1 if the target is an 8-bit Commodore computer (or a compatible one), 0 otherwise
(for more Commodore-related preprocessor options, see [Preprocessor options for Commodore computer targets](./preprocessor_cbm.md))
* `AMSTRAD_CPC`, `ATARI_2600`, `ATARI_8`, `ATARI_LYNX`, `APPLE_2`, `BBC_MICRO`,
`COMMANDER_X16`, `CPM`, `GAMEBOY`, `IBM_PC`, `MSX`, `NEC_PC_88`, `NES`, `ZX_SPECTRUM`
1 if the target is the machine in question, 0 otherwise
* `VERA_VERSION` on Commander X16, the version of the VERA chip: `7` for 0.7, `8` for 0.8, `9` for 0.9
### Built-in preprocessor functions and operators
The `same` function returns 1 if given identical identifiers and 0 otherwise.
It is the only function that does not support any other kind of parameters, and it's only useful in module templates.
// prints 1:
#infoeval same(a,a)
// prints 0:
#infoeval same(a,b)
// fails to compile
#infoeval same(a,1)
The `defined` function returns 1 if the feature is defined, 0 otherwise.
All the other functions and operators treat undefined features as if they were defined as 0.
@ -134,11 +153,45 @@ The `if` function returns its second parameter if the first parameter is defined
// prints 500:
#infoeval if(0, 400, 500)
TODO
The `min` and `max` functions return the smallest or largest parameter respectively. They support any number of arguments:
// prints 400:
#infoeval min(400, 500, 600)
// prints 500:
#infoeval max(400, 500)
The following Millfork operators and functions are also available in the preprocessor:
`not`, `lo`, `hi`, `+`, `-`, `*`, `|`, `&`, `^`, `||`, `&&`, `<<`, `>>`,`==`, `!=`, `>`, `>=`, `<`, `<=`
The following Millfork operators and functions are not available in the preprocessor:
`+'`, `-'`, `*'`, `<<'`, `>>'`, `:`, `>>>>`, `nonet`, all the assignment operators
`$+`, `$-`, `$*`, `$<<`, `$>>`, `:`, `>>>>`, `nonet`, all the assignment operators
### Character literals
Preprocessor supports character literals. By default, they are interpreted in the default encoding,
but you can suffix them with other encodings.
// usually prints 97:
#infoeval 'a'
// prints 97:
#infoeval 'a'ascii
Exceptionally, you can suffix the character literal with `utf32`.
This gives the literal the value of the Unicode codepoint of the character:
// may print 94, 96, 112, 173, 176, 184, 185, 222, 227, 234, 240, something else, or even fail to compile:
#infoeval 'π'
// prints 960:
#infoeval 'π'utf32
Escape sequences are supported, as per encoding. `utf32` pseudoencoding supports the same escape sequences as `utf8`.
### `#template`
Defines the source to be a module template. See [Modules](./modules.md) for more information.
### `#if/#elseif/#else/#endif`

View File

@ -0,0 +1,38 @@
[< back to index](../doc_index.md)
# Preprocessor options for Commodore computer targets
All Commodore targets define the `CBM` feature as 1.
### Target detection
* `CBM_PET` 1 if the target is PET, 0 otherwise
* `CBM_VIC` 1 if the target is VIC-20, 0 otherwise
* `CBM_264` 1 if the target is an 8-bit Commodore computer from the 264 line, 0 otherwise
* `MOS_6510` 1 if the target uses a MOS 6510-compatible processor (with an I/O port at $0000/$0001)
* `CBM_64` 1 if the target is Commodore 64, 0 otherwise
* `CBM_64_CRT` 1 if the target is a cartridge for Commodore 64, 0 otherwise
* `LUNIX` 1 if the target is Commodore 64 running LUnix, 0 otherwise
* `CBM_128` 1 if the target is Commodore 128, 0 otherwise
* `CBM_64_COMPAT` 1 if the target is an 8-bit Commodore computer compatible with Commodore 64
(for example, C128, C65, Mega 65), but not Commodore 64 itself, 0 otherwise
### Feature enabling
Due to incompatibilities between different versions of Commodore PET,
certain libraries can be configured to support only some ROM revisions.
By default, all of these are enabled:
* `PET2000_SUPPORT` set this to 1 to enable support for PET 2001 with the original ROMs (BASIC 1.0), set it to 0 to disable it
* `PET3000_SUPPORT` set this to 1 to enable support for PET 3000 series with the upgraded ROMs (BASIC 2.0), set it to 0 to disable it
* `PET4000_SUPPORT` set this to 1 to enable support for PET 4000 with the 4.0 ROMs (BASIC 4.0), set it to 0 to disable it

52
docs/lang/suffixes.md Normal file
View File

@ -0,0 +1,52 @@
[< back to index](../doc_index.md)
# Magic suffixes
## Byte-related suffixes
These suffixes can be only applied to arithmetic or pointer variables:
* `.lo` the least significant byte of a two-byte variable (word, pointer) (use `lo(_)` for arbitrary expressions)
* `.hi` the most significant byte of a two-byte variable (word, pointer) (use `hi(_)` for arbitrary expressions)
* `.loword` the least significant word of a three- or four-byte variable
* `.hiword` the most significant word of a three- or four-byte variable
* `.b0`, `.b1` etc. the given byte of the multi-byte arithmetic variable, with `.b0` being the least significant byte
## Pointer-related suffixes:
These suffixes can be applied to variables, arrays, functions or pointable expressions (sometimes called _lvalues_):
* `.addr` returns address of the object (type `pointer`) (constant unless on Lunix)
* `.rawaddr` returns the raw address constant of the object (type `pointer`, the same as `.addr` unless on Lunix, guaranteed to be constant)
* `.pointer` returns the typed pointer to the object
This suffix is available only on expressions that have a type of a typed pointer:
* `.raw` a view of the pointer as a raw pointer
## Segment-related suffixes
These suffixes can be applied to variables, arrays, or functions:
* `.segment.bank` (or `.segment` for short) returns the bank number of the segment the object is in
* `.segment.start` returns the start address of the segment the object is in
* `.segment.codeend` returns the last address of code in the segment the object is in
* `.segment.datastart` returns the start address of data in the segment the object is in
* `.segment.heapstart` returns the start address of uninitialized data in the segment the object is in
* `.segment.end` returns the last address of the segment the object is in
* `.segment.fill` returns the byte value used to fill gaps and other unused space in the segment the object is in
See also [the list of predefined constants](./predefined_constants.md).

View File

@ -13,6 +13,26 @@ Allowed line endings are U+000A, U+000D and U+000D/U+000A.
Outside of text strings and comments, the only allowed characters are U+0009 and U+0020U+007E
(so-called printable ASCII).
## Valid identifiers
Identifiers are used for variable names, function names, array names, segment names.
Identifiers have to start with a letter or an underscore, and they can contain letters, underscores, digits and dollar signs.
An identifier cannot end with a dollar sign, nor can it contain two consecutive dollar signs.
Identifiers using dollar signs are reserved for internal use, do not use them without a good reason.
There is no hard limit on the identifier length.
a // valid
1a // invalid
a1 // valid
_1 // valid
a$1 // valid, but discouraged
a$$a // invalid
a$ // invalid
## Comments
Comments start with `//` and last until the end of line.
@ -30,7 +50,7 @@ or a top level of a function (*local* variables).
Syntax:
`[segment(<segment>)] [volatile] [<storage>] <type> <name> [@<address>] [= <initial_value>]`
`[segment(<segment>)] [volatile] [<storage>] <type> <name> [<optimization hints>] [@<address>] [= <initial_value>]`
Examples:
@ -43,11 +63,14 @@ Examples:
* `volatile` means that the variable is volatile.
The optimizer shouldn't remove or reorder accesses to volatile variables.
Volatile variables cannot be declared as `register` or `stack.
Volatile variables (unlike non-volatile ones) will not be removed or inlined by the optimizer.
Volatile variables cannot be declared as `register` or `stack`.
* `<storage>` can be only specified for local variables. It can be either `stack`, `static`, `register` or nothing.
`register` is only a hint for the optimizer.
See [the description of variable storage](../abi/variable-storage.md).
* `<optimization hints>` is a list of [optimization hints](./hints.md), separated by spaces
* `<address>` is a constant expression that defines where in the memory the variable will be located.
If not specified, it will be located according to the usual allocation rules.
@ -86,6 +109,12 @@ For every variable `x` larger than a byte, extra subvariables are defined:
* constituent bytes, from low to high: `x.b0`, `x.b1`, `x.b2`, etc.
* the lowest word: `x.loword` (=`x.b1:x.b0`)
* if `x` is a typed pointer:
* a view of as a raw pointer: `x.raw`
See also [the list of magic suffixes](./suffixes.md).
### Constant declarations
@ -217,7 +246,11 @@ is equivalent to:
import <module>
Adds a module to the program.
Adds a module to the program. The module name can be a valid identifier
or a sequence of identifiers separated by forward slashes:
import module1
import library1/module2
The module is looked up first in the current working directory, and then in the include directories.
@ -366,12 +399,18 @@ for <variable> , <start> , <direction> , <end> {
}
for <variable> : <enum type> {
}
for <variable> : <array> {
}
for <variable> , <variable2> : <array> {
}
for <variable> : [ <comma separated expressions> ] {
}
```
* `<variable>` an already defined numeric variable
* `<variable2>` an already defined numeric variable
* `<direction>` the type of range to traverse:
* `to` from `<start>` inclusive to `<end>` inclusive, in ascending order
@ -406,11 +445,34 @@ for <variable> : [ <comma separated expressions> ] {
* `<enum type>` traverse enum constants of given type, in arbitrary order
* `<array>` traverse given array, in arbitrary order,
assigning the index to `<variable>` and either the element or the pointer to the element to `<variable2>`
* `<comma separated expressions>` traverse every value in the list, in the given order.
Values do not have to be constant.
If a value is not a constant and its value changes while executing the loop, the behaviour is undefined.
Jumps using `goto` across the scope of this kind of loop are disallowed.
Examples:
struct S { ... }
pointer.S p
S s
byte i
array(str) arr [8]
enum E { E_1, E_2, E_3 }
E e
for i,0,until,8 { ... } // executes the body with i=0, i=1, ... i=7
for i,0,to,7 { ... } // executes the body with i=0, i=1, ... i=7
for i,0,paralleluntil,8 { ... } // executes the body with i=0, i=1, ... i=7 (in arbitrary order)
for i,0,parallelto,8 { ... } // executes the body with i=0, i=1, ... i=7 (in arbitrary order)
for i,7,downto,0 { ... } // executes the body with i=7, i=6, ... i=0
for i:arr { ... } // executes the body with i=0, i=1, ... i=7 (in arbitrary order)
for i,s:arr { ... } // executes the body with i=0, s=arr[0]; i=1, s=arr[1]; ... i=7, s=arr[7] (in arbitrary order)
for i,p:arr { ... } // executes the body with i=0, p=arr[0].pointer; ... i=7, p=arr[7].pointer (in arbitrary order)
for e:E { ... } // executes the body with e=E_1, e=E_2, e=E_3 (in arbitrary order)
### `break` and `continue` statements
Syntax:
@ -433,6 +495,7 @@ Labelless `break` and `continue` apply to the innermost `for`, `while` or `do-wh
`break for`, `continue do` etc. apply to the innermost loop of the given type.
`break i` and `continue i` apply to the innermost `for` loop that uses the `i` variable.
`for` loops of the form `for i,j:array` can be broken from using `break i` only, not `break j`.
### `goto` and `label`

View File

@ -1,6 +1,13 @@
[< back to index](../doc_index.md)
# Text encodings ans escape sequences
# Text encodings and escape sequences
### Defining custom encodings
Every platform is defined in an `.tbl` file with an appropriate name.
The file is looked up in the directories on the include path, first directly, then in the `encoding` subdirectory.
TODO: document the file format.
### Text encoding list
@ -11,19 +18,29 @@
* `ascii` standard ASCII
* `pet` or `petscii` PETSCII (ASCII-like character set used by Commodore machines from VIC-20 onward)
* `petscii` or `pet` PETSCII (ASCII-like character set used by Commodore machines from VIC-20 onward)
* `petjp` or `petsciijp` PETSCII as used on Japanese versions of Commodore 64
* `petsciijp` or `petjp` PETSCII as used on Japanese versions of Commodore 64
* `origpet` or `origpetscii` old PETSCII (Commodore PET with original ROMs)
* `origpetscii` or `origpet` old PETSCII (Commodore PET with original ROMs)
* `oldpet` or `oldpetscii` old PETSCII (Commodore PET with newer ROMs)
* `oldpetscii` or `oldpet` old PETSCII (Commodore PET with newer ROMs)
* `geos_de` text encoding used by the German version of GEOS for C64
* `cbmscr` or `petscr` Commodore screencodes
* `cbmscrjp` or `petscrjp` Commodore screencodes as used on Japanese versions of Commodore 64
* `apple2` Apple II charset ($A0$DF)
* `apple2` original Apple II charset ($A0$DF)
* `apple2e` Apple IIe charset
* `apple2c` alternative Apple IIc charset
* `apple2gs` Apple IIgs charset
* `macroman` Macintosh Western Latin charset
* `bbc` BBC Micro character set
@ -37,15 +54,57 @@
* `iso_de`, `iso_no`, `iso_se`, `iso_yu` various variants of ISO/IEC-646
* `iso_dk`, `iso_fi` aliases for `iso_no` and `iso_se` respectively
* `iso_dk`, `iso_fi` aliases for `iso_no` and `iso_se` respectively
* `iso15` ISO 8859-15
* `dmcs` DEC Multinational Character Set
* `latin0`, `latin9`, `iso8859_15` aliases for `iso15`
* `lics` Lotus International Character Set
* `iso8859_1`, `iso8859_2`, `iso8859_3`,
`iso8859_4`, `iso8859_5`, `iso8859_7`,
`iso8859_9`, `iso8859_10`, `iso8859_13`,
`iso8859_14`, `iso8859_15`, `iso8859_13`
ISO 8859-1, ISO 8859-2, ISO 8859-3,
ISO 8859-4, ISO 8859-5, ISO 8859-7,
ISO 8859-9, ISO 8859-10, ISO 8859-13,
ISO 8859-14, ISO 8859-15, ISO 8859-16,
* `iso1`, `latin1` aliases for `iso8859_1`
* `iso2`, `latin2` aliases for `iso8859_2`
* `iso3`, `latin3` aliases for `iso8859_3`
* `iso4`, `latin4` aliases for `iso8859_4`
* `iso5` alias for `iso8859_5`
* `iso7` alias for `iso8859_7`
* `iso9`, `latin5`, aliases for `iso8859_9`
* `iso10`, `latin6` aliases for `iso8859_10`
* `iso13`, `latin7` aliases for `iso8859_13`
* `iso14`, `latin8` aliases for `iso8859_14`
* `iso_15`, `latin9`, `latin0` aliases for `iso8859_15`
* `iso16`, `latin10` aliases for `iso8859_16`
* `brascii` BraSCII
* `cp437`, `cp850`, `cp851`, `cp852`, `cp855`, `cp858`, `cp866`
DOS codepages 437, 850, 851, 852, 855, 858, 866
* `mazovia` Mazovia encoding
* `kamenicky` Kamenický encoding
* `cp1250`, `cp1251`, `cp1252`, `cp1253`, `cp1254`, `cp1257` Windows codepages 1250, 1251, 1252, 1253, 1254, 1257
* `msx_intl`, `msx_jp`, `msx_ru`, `msx_br` MSX character encoding, International, Japanese, Russian and Brazilian respectively
* `msx_us`, `msx_uk`, `msx_fr`, `msx_de` aliases for `msx_intl`
* `msx_us`, `msx_uk`, `msx_fr`, `msx_de` aliases for `msx_intl`
* `cpc_en`, `cpc_fr`, `cpc_es`, `cpc_da` Amstrad CPC character encoding, English, French, Spanish and Danish respectively
* `pcw` or `amstrad_cpm` Amstrad CP/M encoding, the US variant (language 0), as used on PCW machines
* `pokemon1en`, `pokemon1jp`, `pokemon1es`, `pokemon1fr` text encodings used in 1st generation Pokémon games,
English, Japanese, Spanish/Italian and French/German respectively
* `pokemon1it`, `pokemon1de` aliases for `pokemon1es` and `pokemon1fr` respectively
* `atascii` or `atari` ATASCII as seen on Atari 8-bit computers
@ -53,15 +112,37 @@
* `koi7n2` or `short_koi` KOI-7 N2
* `koi8r`, `koi8u`, `koi8ru`, `koi8e`, `koi8f`, `koi8t` various variants of KOI-8
* `vectrex` built-in Vectrex font
* `galaksija` text encoding used on Galaksija computers
* `trs80m1` text encoding used on TRS-80 Model 1
* `trs80m3` text encoding used on TRS-80 Model 3
* `coco` text encoding used on Tandy Color Computer
* `cocoscr` Tandy Color Computer screencodes
* `z1013` text encodind used on Robotron Z1013
* `ebcdic` EBCDIC codepage 037 (partial coverage)
* `utf8` UTF-8
* `utf16be`, `utf16le` UTF-16BE and UTF-16LE
* `utf32be`, `utf32le` UTF-32BE and UTF-32LE
When programming for Commodore,
use `pet` for strings you're printing using standard I/O routines
and `petscr` for strings you're copying to screen memory directly.
use `petscii` for strings you're printing using standard I/O routines
and `petsciiscr` for strings you're copying to screen memory directly.
When programming for Atari,
use `atascii` for strings you're printing using standard I/O routines
and `atasciiscr` for strings you're copying to screen memory directly.
### Escape sequences
@ -71,8 +152,6 @@ Some escape sequences may expand to multiple characters. For example, in several
##### Available everywhere
* `{q}` double quote symbol
* `{x00}``{xff}` a character of the given hexadecimal value
* `{copyright_year}` this expands to the current year in digits
@ -88,13 +167,19 @@ The exact value of `{nullchar}` is encoding-dependent:
* in the `zx80` encoding it's `{x01}`,
* in the `zx81` encoding it's `{x0b}`,
* in the `petscr` and `petscrjp` encodings it's `{xe0}`,
* in the `apple2e` encoding it's `{x7f}`,
* in the `atasciiscr` encoding it's `{xdb}`,
* in the `pokemon1*` encodings it's `{x50}`,
* in the `cocoscr` encoding it's exceptionally two bytes: `{xd0}`
* in the `utf16be` and `utf16le` encodings it's exceptionally two bytes: `{x00}{x00}`
* in the `utf32be` and `utf32le` encodings it's exceptionally four bytes: `{x00}{x00}{x00}{x00}`
* in other encodings it's `{x00}` (this may be a subject to change in future versions).
##### Available only in some encodings
* `{apos}` apostrophe/single quote (available everywhere except for `zx80` and `zx81`)
* `{apos}` apostrophe/single quote (available everywhere except for `zx80`, `zx81` and `galaksija`)
* `{q}` double quote symbol (available everywhere except for `pokemon1*` encodings)
* `{n}` new line
@ -105,19 +190,25 @@ The exact value of `{nullchar}` is encoding-dependent:
* `{up}`, `{down}`, `{left}`, `{right}` control codes for moving the cursor
* `{white}`, `{black}`, `{red}`, `{green}`, `{blue}`, `{cyan}`, `{yellow}`, `{purple}`
control codes for changing the text color
control codes for changing the text color (`petscii`, `petsciijp`, `sinclair` only)
* `{bgwhite}`, `{bgblack}`, `{bgred}`, `{bggreen}`, `{bgblue}`, `{bgcyan}`, `{bgyellow}`, `{bgpurple}`
control codes for changing the text background color
control codes for changing the text background color (`sinclair` only)
* `{reverse}`, `{reverseoff}` inverted mode on/off
* `{yen}`, `{pound}`, `{cent}`, `{euro}`, `{copy}` yen symbol, pound symbol, cent symbol, euro symbol, copyright symbol
* `{nbsp}`, `{shy}` non-breaking space, soft hyphen
* `{pi}` letter π
* `{u0000}``{u1fffff}` Unicode codepoint (available in UTF encodings only)
##### Character availability
For ISO/DOS/Windows/UTF encodings, consult external sources.
Encoding | lowercase letters | backslash | currencies | intl | card suits
---------|-------------------|-----------|------------|------|-----------
`pet`, | yes¹ | no | £ | none | yes¹
@ -126,20 +217,32 @@ Encoding | lowercase letters | backslash | currencies | intl | card suits
`petscr` | yes¹ | no | £ | none | yes¹
`petjp` | no | no | ¥ | katakana³ | yes³
`petscrjp` | no | no | ¥ | katakana³ | yes³
`geos_de` | yes | no | | | no
`sinclair`, `bbc` | yes | yes | £ | none | no
`zx80`, `zx81` | no | no | £ | none | no
`apple2` | no | yes | | none | no
`atascii` | yes | yes | | none | yes
`atasciiscr` | yes | yes | | none | yes
`z1013` | yes | yes | | none | yes
`jis` | yes | no | ¥ | both kana | no
`iso15` | yes | yes | €¢£¥ | Western | no
`dmcs`,`lics` | yes | yes | ¢£¥ | Western | no
`brascii`,`macroman`| yes | yes | ¢£¥ | Western | no
`msx_intl`,`msx_br` | yes | yes | ¢£¥ | Western | yes
`msx_jp` | yes | no | ¥ | katakana | yes
`msx_ru` | yes | yes | | Russian⁴ | yes
`koi7n2` | no | yes | | Russian⁵ | no
`koi8*` | yes | yes | | Russian | no
`cpc_en` | yes | yes | £ | none | yes
`cpc_es` | yes | yes | | Spanish⁶ | yes
`cpc_fr` | yes | no | £ | French⁷ | yes
`cpc_da` | yes | no | £ | Nor/Dan. | yes
`vectrex` | no | yes | | none | no
`utf*` | yes | yes | all | all | yes
all the rest | yes | yes | | none | no
`coco`,`cocoscr` | no | yes | | none | no
`pokemon1jp` | no | no | | both kana | no
`pokemon1en` | yes | no | | none | no
`pokemon1fr` | yes | no | | Ger/Fre. | no
`pokemon1es` | yes | no | | Spa/Ita. | no
`galaksija` | no | no | | Yugoslav⁸ | no
1. `pet`, `origpet` and `petscr` cannot display card suit symbols and lowercase letters at the same time.
Card suit symbols are only available in graphics mode,
@ -155,6 +258,12 @@ Card suit symbols are only available in graphics mode, in which katakana is disp
5. Only uppercase. Letters **Ё** and **Ъ** are not available.
6. No accented vowels.
7. Some accented vowels are not available.
8. Letter **Đ** is not available.
If the encoding does not support lowercase letters (e.g. `apple2`, `petjp`, `petscrjp`, `koi7n2`, `vectrex`),
then text and character literals containing lowercase letters are automatically converted to uppercase.
Only unaccented Latin and Cyrillic letters will be converted as such.
@ -163,21 +272,30 @@ To detect if your default encoding does not support lowercase letters, test `'A'
##### Escape sequence availability
The table below may be incomplete.
Encoding | new line | braces | backspace | cursor movement | text colour | reverse | background colour
---------|----------|--------|-----------|-----------------|-------------|---------|------------------
`pet`,`petjp` | yes | no | no | yes | yes | yes | no
`origpet` | yes | no | no | yes | no | yes | no
`oldpet` | yes | no | no | yes | no | yes | no
`petscr`, `petscrjp`| no | no | no | no | no | no | no
`geos_de` | no | no | no | no | no | yes | no
`sinclair` | yes | yes | no | yes | yes | yes | yes
`zx80`,`zx81` | yes | no | yes | yes | no | no | no
`ascii`, `iso_*` | yes | yes | yes | no | no | no | no
`iso15` | yes | yes | yes | no | no | no | no
`iso8869_*`, `cp*` | yes | yes | yes | no | no | no | no
`apple2` | no | yes | no | no | no | no | no
`apple2` | no | no | no | no | no | no | no
`apple2e` | no | yes | no | no | no | no | no
`apple2gs` | no | yes | no | no | no | no | no
`atascii` | yes | no | yes | yes | no | no | no
`atasciiscr` | no | no | no | no | no | no | no
`msx_*` | yes | yes | yes | yes | no | no | no
`koi7n2` | yes | no | yes | no | no | no | no
`koi8*` | yes | yes | yes | no | no | no | no
`vectrex` | no | no | no | no | no | no | no
`coco` | yes | no | yes | no | no | no | no
`cocoscr` | no | no | no | no | no | no | no
`utf*` | yes | yes | yes | no | no | no | no
all the rest | yes | yes | no | no | no | no | no

View File

@ -20,11 +20,15 @@ Millfork puts extra limitations on which types can be used in which contexts.
* `long` 4-byte value of undefined signedness, defaulting to unsigned
(alias: `int32`)
* `int40`, `int48`,... `int128` even larger unsigned types
* `int40`, `int48`,... `int128` even larger types of undefined signedness, defaulting to unsigned
* `sbyte` signed 1-byte value
* `sbyte` signed 1-byte value (alias: `signed8`)
* `ubyte` unsigned 1-byte value
* `ubyte` unsigned 1-byte value (alias: `unsigned8`)
* `signed16` signed 2-byte value (experimental)
* `unsigned16` unsigned 2-byte value (experimental)
* `pointer` raw pointers; the same as `word`, but variables of this type default to be zero-page-allocated
and you can index `pointer`-typed expressions.
@ -65,6 +69,14 @@ or forcing zero extension or sign extension:
x = y // does zero extension and assigns value $0080
x = sbyte(y) // does sign extension and assigns value $FF80
You can also explicitly convert expressions of type `bool` to any numeric type.
`false` is converted to 0 and `true` is converted to 1.
byte a,b,c
a = 5
b = byte(a == 4) // b is now equal to 0
c = byte(a == 5) // c is now equal to 1
## Typed pointers
For every type `T`, there is a pointer type defined called `pointer.T`.
@ -78,6 +90,8 @@ You can create pointer values by suffixing `.pointer` to the name of a variable,
You can replace C-style pointer arithmetic by combining indexing and `.pointer`: C `p+5`, Millfork `p[5].pointer`.
You can use the typed pointer as a raw pointer by suffixing `.raw`.
Examples:
pointer.t p
@ -89,6 +103,7 @@ Examples:
p[i] // accessing the ith element; if 'sizeof(t) == 1', then equivalent to 't(p.raw[i])'
p->x // valid only if the type 't' has a field called 'x', accesses the field 'x' of the pointed element
p->x.y[0]->z[0][6] // you can stack it
p.raw += sizeof(t) // if p points to an element of an array, then advances it to the next element
## `nullptr`
@ -119,11 +134,33 @@ Using `call` on 6502 requires at least 4 bytes of zeropage pseudoregister.
The value of the pointer `f.pointer` may not be the same as the value of the function address `f.addr`.
## Interrupt handler pointers
Functions that are interrupt pointers have their own pointer types:
* `pointer.interrupt` for hardware interrupt handlers
* `pointer.kernal_interrupt` for kernal interrupt handlers
`pointer.kernal_interrupt` is automatically convertible to `function.void.to.void`
interrupt void handler1(){}
kernal_interrupt void handler2(){}
pointer.interrupt p1
p1 = handler1.pointer
pointer.kernal_interrupt p2
p2 = handler2.pointer
function.void.to.void p3
p3 = handler2.pointer
## Boolean types
Boolean types can be used as conditions. They have two possible values, `true` and `false`.
* `bool` a 1-byte boolean value. An uninitialized variable of type `bool` may contain an invalid value.
* `bool` a 1-byte boolean value.
An uninitialized variable of type `bool` may contain an invalid value.
The value `false` is stored as 0, `true` as 1.
* several boolean types based on the CPU flags that may be used only as a return type for a function written in assembly:
@ -139,6 +176,10 @@ Boolean types can be used as conditions. They have two possible values, `true` a
2\. LR35902 does not support these types due to the lack of appropriate flags
You can convert from a boolean type to an arithmetic type by simply casting:
byte c = byte(x >= 0x80)
Examples:
bool f() = true
@ -215,11 +256,24 @@ as there are no checks on values when converting bytes to enumeration values and
## Structs
Struct is a compound type containing multiple fields of various types:
Struct is a compound type containing multiple fields of various types.
A struct is represented in memory as a contiguous area of variables or arrays laid out one after another.
struct <name> { <field definitions (type and name), separated by commas or newlines>}
Declaration syntax:
A struct is represented in memory as a contiguous area of variables laid out one after another.
struct <name> [align (alignment)] { <field definitions, separated by commas or newlines>}
where a field definition is either:
* `<type> <name>` and defines a scalar field,
* or `array (<type>) <name> [<size>]`, which defines an array field,
where the array contains items of type `<type>`,
and either contains `<size>` elements
if `<size>` is a constant expression between 0 and 127,
or, if `<size>` is a plain enumeration type, the array is indexed by that type,
and the number of elements is equal to the number of variants in that enumeration.
`(<type>)` can be omitted and defaults to `byte`.
Struct can have a maximum size of 255 bytes. Larger structs are not supported.
@ -247,9 +301,36 @@ You can create constant expressions of struct types using so-called struct const
All arguments to the constructor must be constant.
Structures declared with an alignment are allocated at appropriate memory addresses.
The alignment has to be a power of two.
If the structs with declared alignment are in an array, they are padded with unused bytes.
If the struct is smaller that its alignment, then arrays of it are faster than if it were not aligned
struct a align(4) { byte x,byte y, byte z }
struct b { byte x,byte y, byte z }
array(a) as [4] @ $C000
array(b) bs [4] @ $C800
a[1].addr - a[0].addr // equals 4
b[1].addr - b[0].addr // equals 3
sizeof(a) // equals 16
sizeof(b) // equals 12
return a[i].x // requires 22 or 24 cycles on 6502
return b[i].x // requires 18 cycles on 6502
A struct that contains substructs or subunions with non-trivial alignments has its alignment equal
to the least common multiple of the alignments of the substructs and its own declared alignment.
**Warning:** Limitations of array fields:
* Structs containing arrays cannot be allocated on the stack.
* Struct constructors for structs with array fields are not supported.
## Unions
union <name> { <field definitions (type and name), separated by commas or newlines>}
union <name> [align (alignment)] { <field definitions, separated by commas or newlines>}
Unions are pretty similar to structs, with the difference that all fields of the union
start at the same point in memory and therefore overlap each other.
@ -265,3 +346,5 @@ start at the same point in memory and therefore overlap each other.
Offset constants are also available, but they're obviously all zero.
Unions currently do not have an equivalent of struct constructors. This may be improved on in the future.
Unions with array fields have the same limitations as structs with array fields.

91
docs/stdlib/apple2.md Normal file
View File

@ -0,0 +1,91 @@
[< back to index](../doc_index.md)
# Apple II-oriented modules
## apple2_prodos module
This module provides basic support for issuing ProDOS calls.
It assumes ProDOS has been loaded normally before your program has started.
The API closely follows the ProDOS machine language interface.
See the
[ProDOS 8 Technical Reference Manual](http://www.easy68k.com/paulrsm/6502/PDOS8TRM.HTM)
for more details, such as the error code values returned.
The following functions are currently implemented:
#### void prodos_read_block(byte unit, pointer data_buffer, word block_number)
Read the specified block from device `unit` into `data_buffer`.
`data_buffer` must be page-aligned.
#### void prodos_write_block(byte unit, pointer data_buffer, word block_number)
Write the specified block from device `unit` into `data_buffer`.
`data_buffer` must be page-aligned.
#### void prodos_close(byte rnum)
Close file referred to by reference `rnum`.
ProDOS will free the associated buffers and flush all changes to disk if necessary.
#### void prodos_flush(byte rnum)
Flush any changes to disk for file referred to by reference `rnum`.
#### void prodos_get_prefix(pointer filename)
Takes a pointer to a 64-byte buffer.
ProDOS will fill this with the current path prefix as a Pascal-style string.
#### void prodos_set_prefix(pointer filename)
Sets or modifies the ProDOS prefix.
Takes a pointer to a Pascal-style string.
#### void prodos_create(pointer filename, byte filetype)
Create a file.
`filename` is a pointer to a Pascal-style string.
`filetype` is one of the standard ProDOS file types.
See the ProDOS manual for more details.
This *must* be called before a file can be opened or written.
ProDOS does not create files implicitly.
#### void prodos_destroy(pointer filename)
Delete a file.
#### void prodos_rename(pointer filename, pointer new_filename)
Rename a file.
#### byte prodos_open (pointer filename, pointer buffer)
Open a file.
`filename` is a pointer to a Pascal-style string containing the path of file to be opened.
Buffer is a 1024 byte I/O buffer used internally by ProDOS.
The buffer must be page-aligned.
This call returns a byte which is the ProDOS file handle.
This handle is used by other calls.
A minimal example:
byte file_handle
array io_buffer [1024] align (256)
file_handle = prodos_open("myfile"p, io_buffer)
prodos_close(file_handle)
Files must exist to be opened.
Use the `prodos_create` call to create a file first if necessary.
#### void prodos_newline(byte rnum, byte mask, byte newline_char)
Set the ProDOS newline character and mask.
See ProDOS manual for details.
#### void prodos_read(byte rnum, pointer data_buffer, word read_count)
Read the number of bytes specified by `read_count` into `data_buffer` from file handle `rnum`.
#### void prodos_write(byte rnum, pointer data_buffer, word write_count)
Write the number of bytes specified by `write_count` from `data_buffer` to file handle `rnum`.

View File

@ -11,7 +11,7 @@ TODO
## c64_basic module
The `c64_basic` module provides access to Kernal routines, so it requires the Basic ROM to be enabled.
The `c64_basic` module provides access to Basic routines, so it requires the Basic ROM to be enabled.
In particular, this means that it will not work on cartridge targets without extra preparations.
TODO
@ -22,7 +22,7 @@ TODO
## c1531
The `c1531` module implements a Commodore 1531 proportional mouse driver compatible with the `mouse` module.
The `c1531` module implements a Commodore 1531 proportional mouse driver compatible with the [`mouse` module](./mouse.md).
#### `void c1531_mouse()`
@ -36,7 +36,7 @@ Defines the `c1531` module as the default module for reading mouse input.
## c64_joy
The `c64_joy` module implements a joystick driver compatible with the `joy` module.
The `c64_joy` module implements a joystick driver compatible with the [`joy` module](./joy.md).
#### `void read_joy2()`

View File

@ -31,11 +31,11 @@ Executes a CBM DOS command on the given drive.
#### void delete_file(byte device, pointer name)
Deletes given file in the given drive. (`S0:`)
Deletes the given file in the given drive. (`S0:`)
#### void rename_file(byte device, pointer old_name, pointer new_name)
Renames given file in the given drive. (`R0:`)
Renames the given file in the given drive. (`R0:`)
#### void copy_file(byte device, pointer old_name, pointer new_name)

26
docs/stdlib/cbm_pet.md Normal file
View File

@ -0,0 +1,26 @@
[< back to index](../doc_index.md)
# Commodore PET-oriented modules
## pet_kernal module
The `pet_kernal` module is imported automatically on the PET target.
It provides access to Kernal routines.
TODO
#### asm set_zero is_pet2000()
Returns true if the current machine has the original ROM (usually, the PET 2000 series).
When calling from assembly, the result is stored in the Z flag.
#### asm set_zero is_pet3000()
Returns true if the current machine has the upgraded ROM (usually, the PET 3000 series).
When calling from assembly, the result is stored in the Z flag.
#### asm set_zero is_pet4000()
Returns true if the current machine has the 4.0 ROM (usually, the PET 4000 series).
When calling from assembly, the result is stored in the Z flag.

View File

@ -31,6 +31,8 @@ Available only if one of the following is true:
* the default encoding is `atascii`, the screen encoding is `atasciiscr`, and the platform is 6502-based
* the default encoding is `coco`, the screen encoding is `cococsr`, and the platform is 6809-based
You can test for the availability of this function using the `ENCCONV_SUPPORTED` preprocessor feature.
#### byte from_screencode(byte)
@ -53,6 +55,18 @@ Destructively converts a null-terminated string from the `scr` encoding into the
Available only if `from_screencode` is available.
#### void pstr_to_screencode(pointer)
Destructively converts a length-prefixed string from the `default` encoding into the `scr` encoding.
Available only if `to_screencode` is available.
#### void pstr_from_screencode(pointer)
Destructively converts a length-prefixed string from the `scr` encoding into the `default` encoding.
Available only if `from_screencode` is available.
#### byte petscii_to_petscr(byte)
Converts a byte from PETSCII to a CBM screencode.
@ -71,7 +85,7 @@ Available only on 6502-based platforms.
#### byte atascii_to_atasciiscr(byte)
Converts a byte from ATASCII to a Atari screencode.
Converts a byte from ATASCII to an Atari screencode.
Control characters <$80 are converted to the graphical characters that share the ATASCII code.
Control characters ≥$80 are not supported.
@ -79,10 +93,24 @@ Available only on 6502-based platforms.
#### byte atasciiscr_to_atascii(byte)
Converts a byte from a Atari screencode to ATASCII.
Converts a byte from an Atari screencode to ATASCII.
Characters that share their ATASCII code with control characters are supported,
but they require to be escaped with $1B to be printed.
Reverse characters are interpreted as non-reverse characters.
Available only on 6502-based platforms.
#### byte coco_to_cocoscr(byte)
Converts a byte from Color Computer pseudo-ASCII to a Color Computer screencode.
Control characters <$20 are converted inverted punctuation.
Available only on 6809-based platforms.
#### byte cocoscr_to_coco(byte)
Converts a byte from a Color Computer screencode to Color Computer pseudo-ASCII.
Inverted punctuation is converted to control characters.
Available only on 6809-based platforms.

View File

@ -48,8 +48,12 @@ Available for:
ZX Spectrum,
NEC PC-88,
MSX,
Commodore 64 with `c64_basic` module (requires KERNAL and BASIC),
Commodore 16 or Plus/4 with `c264_basic` module (requires KERNAL and BASIC).
Apple II,
Robotron Z1013 (always trims trailing spaces),
TRS-80,
VIC-20 (except for `vic20_a000`),
Commodore 64 with `c64_basic` module (requires KERNAL and BASIC; empty input is treated like a single space),
Commodore 16 or Plus/4 with `c264_basic` module (requires KERNAL and BASIC; empty input is treated like a single space).
#### `word readword()`
@ -59,6 +63,10 @@ Available for:
ZX Spectrum,
NEC PC-88,
MSX,
Apple II,
Robotron Z1013,
TRS-80,
VIC-20 (except for `vic20_a000`),
Commodore 64 with `c64_basic` module (requires KERNAL and BASIC),
Commodore 16 or Plus/4 with `c264_basic` module (requires KERNAL and BASIC).
@ -87,11 +95,6 @@ Various colour constants.
Available for: VIC-20, C64, C128, C264 series, ZX Spectrum.
#### `macro void memory_barrier()`
Informs the optimizer that at this point arbitrary memory has been accessed and either read or written by an external device.
The optimizer should not optimize any memory accesses across that macro.
Available for: all targets.

View File

@ -15,7 +15,7 @@ It contains the default header for 32K Game Boy programs.
## gb_joy
Provides an interface for reading joypads that is compatible with the `joy` module.
Provides an interface for reading joypads that is compatible with the [`joy` module](./joy.md).
#### `alias input_a = input_btn`

View File

@ -1,73 +0,0 @@
[< back to index](../doc_index.md)
## joy
The module contains global variables representing the state of the one-button joystick.
If the program is not using any joystick driver, the state of these variables is undefined.
To actually use this module, an appropriate joystick module must be used, such as `c64_joy`, `nes_joy` or `gb_joy`.
#### `sbyte input_dx`
Horizontal joystick movement. 1 if right, -1 if left, 0 if neither.
#### `sbyte input_dy`
Vertical joystick movement. 1 if down, -1 if up, 0 if neither.
#### `byte input_btn`
1 if main button pressed, 0 if not pressed.
#### `void reset_joy()`
Resets the state variables.
The default implementation resets only the main button.
May be overridden by a strong alias on some platforms that have more buttons.
## null_joy_default
This module set the default joystick to no joystick.
#### `alias read_joy`
A reserved name for reading the default joystick.
## mouse
The `mouse` module automatically imports the `x_coord` module.
The module contains global variables representing the state of the mouse.
If the program is not using any mouse driver, the state of these variables is undefined.
To actually use this module, an appropriate mouse module must be used, such as `c1531`.
#### `x_coord mouse_x`
Mouse X position.
#### `byte mouse_y`
Mouse Y position.
#### `byte mouse_lbm`
1 if the left mouse button is being pressed, 0 otherwise
#### `byte mouse_rbm`
1 if the right mouse button is being pressed, 0 otherwise
## `x_coord` module
#### `alias x_coord`
The type for representing horizontal screen coordinates.
It's `byte` if the screen is 256 pixels wide or less,
or `word` if the screen is more that 256 pixels wide.
## null_mouse_default
This module set the default mouse to no mouse.
#### `void read_mouse()`

35
docs/stdlib/joy.md Normal file
View File

@ -0,0 +1,35 @@
[< back to index](../doc_index.md)
## joy
The module contains global variables representing the state of the one-button joystick.
If the program is not using any joystick driver, the state of these variables is undefined.
To actually use this module, an appropriate joystick module must be used,
such as [`c64_joy`](./c64.md), [`nes_joy`](./nes.md), [`gb_joy`](./gb.md) or [`x16_joy`](./x16.md).
#### `sbyte input_dx`
Horizontal joystick movement. 1 if right, -1 if left, 0 if neither.
#### `sbyte input_dy`
Vertical joystick movement. 1 if down, -1 if up, 0 if neither.
#### `byte input_btn`
1 if main button pressed, 0 if not pressed.
#### `void reset_joy()`
Resets the state variables.
The default implementation resets only the main button.
May be overridden by a strong alias on some platforms that have more buttons.
## null_joy_default
This module set the default joystick to no joystick.
#### `alias read_joy`
A reserved name for reading the default joystick.

37
docs/stdlib/keyboard.md Normal file
View File

@ -0,0 +1,37 @@
[< back to index](../doc_index.md)
## keyboard
The `keyboard` module provides support for reading keypresses from the keyboard.
Not supported on all targets.
For reading entire lines of text from the keyboard, see the `readline` and `readword` functions
in [the frequently provided definitions](./frequent.md).
#### `byte readkey()`
Waits for and reads a single keypress.
The returning values may vary between platforms:
* letters may be uppercase or lowercase
* modifier keys may be applied or ignored
Available for:
Commodore 64 (requires KERNAL),
Commodore 16 or Plus/4 (requires KERNAL),
Commodore 128 (requires KERNAL),
Commodore PET (requires KERNAL),
VIC 20 (requires KERNAL),
Atari,
Amstrad CPC,
ZX Spectrum,
NEC PC-88,
Robotron Z1013,
TRS-80,
Tandy Color Computer.
#### `const byte KEY_ENTER`
Key code for the Enter/Return key. Usually 13, but not always.

View File

@ -4,9 +4,9 @@
## atari_lynx_hardware
The `atari_lynx_hardware` module is imported automatically on NES targets.
The `atari_lynx_hardware` module is imported automatically on Atari Lynx targets.
It also implements a joystick API compatible with the `joy` module.
It also implements a joystick API compatible with the [`joy` module](./joy.md).
TODO

52
docs/stdlib/mouse.md Normal file
View File

@ -0,0 +1,52 @@
[< back to index](../doc_index.md)
## mouse
The `mouse` module automatically imports the `coord` module.
The module contains global variables representing the state of the mouse.
If the program is not using any mouse driver, the state of these variables is undefined.
To actually use this module, an appropriate mouse module must be used, such as [`c1531`](./c64.md).
#### `x_coord mouse_x`
Mouse X position.
#### `y_coord mouse_y`
Mouse Y position.
#### `bool mouse_lbm`
`true` if the left mouse button is being pressed, `false` otherwise
#### `byte mouse_mbm`
`true` if the middle mouse button is being pressed, `false` otherwise.
Available only if `USE_MOUSE_MBM` is set and non-zero.
#### `byte mouse_rbm`
`true` if the right mouse button is being pressed, `false` otherwise
## coord
#### `alias x_coord`
The type for representing horizontal screen coordinates.
It's `byte` if the screen is 256 pixels wide or less,
or `word` if the screen is more that 256 pixels wide.
#### `alias y_coord`
The type for representing vertical screen coordinates.
It's `byte` if the screen is 256 pixels tall or less,
or `word` if the screen is more that 256 pixels tall.
## null_mouse_default
This module set the default mouse to null mouse.
The null mouse has no button pressed and the cursor is fixed at coordinates (0,0).
#### `void read_mouse()`

View File

@ -26,7 +26,7 @@ Available variables:
#### `byte strobe_joypad()`
Updates joypad1 by querying for new button states.
Strobes joypads in preparation for reading new joypad states.
#### `byte read_joypad1()`
@ -41,7 +41,7 @@ Get joypad2's state as a byte.
Simulates a hardware reset by jumping to the reset vector,
which then calls main().
#### `void ppu_set_addr(word ax)`
#### `void ppu_set_addr(word register(ax) address)`
Sets the PPU to point at the VRAM address at ax, usually in preparation
for a write via ppu_write_data().
@ -50,18 +50,18 @@ for a write via ppu_write_data().
Gets the PPU status byte.
#### `void ppu_set_scroll(byte a, byte x)`
#### `void ppu_set_scroll(byte register(a) xscroll, byte register(x) yscroll)`
Sets the PPU scroll register. Parameter a defines the horizontal
(X-axis) scroll value, and parameter x defines the vertical (Y-axis)
scroll value.
#### `void ppu_write_data(byte a)`
#### `void ppu_write_data(byte register(a) data)`
Writes a byte to the PPU's VRAM at the address the PPU
is currently pointing to. Usually used after a call to ppu_set_addr().
#### `void ppu_oam_dma_write(byte a)`
#### `void ppu_oam_dma_write(byte register(a) page)`
Initiates a DMA transfer of 256 bytes from CPU memory address $xx00-$xxFF
to PPU OAM memory, where xx is the hexadecimal representation of parameter a.
@ -71,18 +71,18 @@ to PPU OAM memory, where xx is the hexadecimal representation of parameter a.
The `nes_mmc4` module is imported automatically on the NES MMC4 target
and contains routines related to MMC4 bankswitching.
#### `void set_prg_bank(byte a)`
#### `void set_prg_bank(byte register(a) bank)`
Changes the $8000-$BFFF PRG bank.
#### `void set_chr_bank0(byte a)`
#### `void set_chr_bank0(byte register(a) bank)`
Changes the CHR bank 0 ($0000-$0fff in the PPU memory space).
The high nibble (0 or 1) selects between `chrrom0` and `chrrom1` segments.
The low nibble L (0-$F) selects a 4K-aligned address in the segment ($L000).
#### `void set_chr_bank1(byte a)`
#### `void set_chr_bank1(byte register(a) bank)`
Changes the CHR bank 1 ($1000-$1fff in the PPU memory space).
@ -99,23 +99,23 @@ Switches nametable mirroring to horizontal.
## nes_joy
Provides an interface for reading joypads that is compatible with the `joy` module.
Provides an interface for reading joypads that is compatible with the [`joy` module](./joy.md).
#### `alias input_a = input_btn`
1 if A button pressed, 0 id not pressed.
1 if A button pressed, 0 if not pressed.
#### `byte input_b`
1 if B button pressed, 0 id not pressed.
1 if B button pressed, 0 if not pressed.
#### `byte input_select`
1 if Select button pressed, 0 id not pressed.
1 if Select button pressed, 0 if not pressed.
#### `byte input_start`
1 if Start button pressed, 0 id not pressed.
1 if Start button pressed, 0 if not pressed.
#### `void read_joy1()`

View File

@ -1,34 +1,5 @@
[< back to index](../doc_index.md)
## keyboard
The `keyboard` module provides support for reading keypresses from the keyboard.
Not supported on all targets.
#### `byte readkey()`
Waits for and reads a single keypress.
The returning values may vary between platforms:
* letters may be uppercase or lowercase
* modifier keys may be applied or ignored
Available for:
Commodore 64 (requires KERNAL),
Commodore 16 or Plus/4 (requires KERNAL),
Commodore 128 (requires KERNAL),
VIC 20 (requires KERNAL),
Atari,
Amstrad CPC,
ZX Spectrum,
NEC PC-88.
#### `const byte KEY_ENTER`
Key code for the Enter/Return key. Usually 13, but not always.
## err
#### `enum error_number`
@ -61,6 +32,8 @@ Current implementation:
* On C64, spends two frames reading noise data from the SID chip.
* On Atari computers, reads the POKEY random register.
* On Z80, reads the refresh register.
* On all other targets, sets the seed to 1.

View File

@ -3,9 +3,12 @@
## stdio
The `stdio` module automatically imports the `string` and `err` modules.
It requires an implementation of `void putchar(byte a)` and therefore works only on targets with console output.
It requires an implementation of `void putchar(byte a)` and therefore works only on targets with console output
(see [the frequently provided definitions](./frequent.md) for details).
On targets with idiosyncratic behaviour of `putchar`, functions in this module inherit that behaviour.
All strings are assumed to be in the default encoding.
#### `void putstr(pointer str, byte len)`
Prints a string of length `len` located at address `str`.
@ -15,11 +18,20 @@ Prints a string of length `len` located at address `str`.
Prints a null-terminated string located at address `str`.
If the string is longer than 255 bytes, then the behaviour is undefined (might even crash).
#### `void putpstr(pointer pstr)`
Prints a length-prefixed string located at address `str`.
#### `void putword(word w)`
Prints the decimal representation of the 16-bit unsigned integer `w`.
#### `void putsigned16(signed16 x)`
Prints the decimal representation of the 16-bit signed integer `x`.
#### `void ensure_mixedcase()`
On targets that have separate all-caps and mixed-case modes (like most Commodore machines), switches to the mixed-case mode.
On targets that have separate all-caps and mixed-case modes (like most Commodore machines), switches to the mixed-case mode.
On the remaining platforms, does nothing.

View File

@ -4,7 +4,7 @@
The `stdlib` module is automatically imported on most targets.
#### `macro asm void poke(word const addr, byte a)`
#### `macro asm void poke(word const addr, byte register(a) value)`
Stores a byte at given constant address. Will not be optimized away by the optimizer.
@ -20,14 +20,32 @@ Disables interrupts.
Enables interrupts.
#### `byte hi_nibble_to_hex(byte a)`
#### `byte hi_nibble_to_hex(byte register(a) value)`
Returns an ASCII representation of the upper nibble of the given byte.
#### `byte lo_nibble_to_hex(byte a)`
#### `byte lo_nibble_to_hex(byte register(a) value)`
Returns an ASCII representation of the lower nibble of the given byte.
#### `macro asm void panic()`
Crashes the program.
## Standard macros available without any import
#### `macro void memory_barrier()`
Informs the optimizer that at this point arbitrary memory has been accessed and either read or written by an external device.
The optimizer should not optimize any memory accesses across that macro.
Available for: all targets.
#### `macro void breakpoint()`
If the `-fbreakpoints` option is selected (default), then it emits a memory barrier,
and also outputs a breakpoint to the label file (if the format of the label file allows it).
If the `-fno-breakpoints` option is selected, then it does nothing.
Available for: all targets.

View File

@ -2,7 +2,7 @@
## string
The `string` module automatically imports the `err` module.
The `string` module automatically imports the [`err` module](./other.md).
All the functions are designed to work for the strings in the default encoding.
If passed a string in an encoding that has a different null terminator,
@ -40,7 +40,7 @@ Modifies the given null-terminated buffer by appending a null-terminated string
## scrstring
The `scrstring` module automatically imports the `string` and `err` modules.
The `scrstring` module automatically imports the `string` and [`err`](./other.md) modules.
It contains functions for handling strings in the screen encoding with the same semantics as the functions from the string module.
@ -51,3 +51,25 @@ It contains functions for handling strings in the screen encoding with the same
#### `word scrstrz2word(pointer str)`
#### `void scrstrzappend(pointer buffer, pointer str)`
#### `void scrstrzappendchar(pointer buffer, byte char)`
## pstring
The `pstring` module automatically imports the [`err` module](./other.md).
It contains functions for handling length-prefixed strings in any 8-bit encoding.
#### `byte pstrlen(pointer str)`
#### `sbyte pstrcmp(pointer str1, pointer str2)`
#### `void pstrcopy(pointer dest, pointer src)`
#### `void pstrpaste(pointer dest, pointer src)`
#### `void pstrappend(pointer buffer, pointer str)`
#### `void pstrappendchar(pointer buffer, byte char)`
#### `word pstr2word(pointer str)`
Converts a length-prefixed string to a number. Uses the default encoding.
Sets `errno`.
#### `word pscrstr2word(pointer str)`
Converts a length-prefixed string to a number. Uses the screen encoding.
Sets `errno`.

21
docs/stdlib/vic20.md Normal file
View File

@ -0,0 +1,21 @@
[< back to index](../doc_index.md)
# VIC-20-oriented modules
## vic20_kernal module
The `vic20_kernal` module is imported automatically on the VIC-20 target.
It provides access to Kernal routines.
TODO
## vic20_basic module
The `vic20_basic` module provides access to Basic routines.
It is imported automatically on all PRG VIC-20 targets (`vic20`, `vic20_3k`, `vic20_8k`), but not on cartridge targets (like `vic20_a000`).
TODO
## vic20_hardware
TODO

View File

@ -3,15 +3,22 @@
# Commander X16-oriented modules
**WARNING!** Commander X16 is not yet a finalised design.
Therefore, both the device itself and the modules for its support may change at any moment.
Therefore, both the device itself and the modules for its support may change at any moment.
The X16-oriented modules may be out of date and not support the current design of the device.
## x16_kernal module
## x16_kernal
The `x16_kernal` module is imported automatically on the X16 target.
Currently, it automatically imports the [`c64_kernal` module](./c64.md).
## `x16_hardware` module
#### `void mouse_config(byte register(a) enable, byte register(x) scale)`
Configures the mouse pointer.
`enable` should be `1` to enable, `0` to disable and `$ff` to enable without reconfiguration.
`scale` should be `1` on 640×480 screens, `2` on 320×240 screens, and `0` to keep the current scale.
## x16_hardware
The `x16_hardware` module is imported automatically on the X16 target.
@ -42,7 +49,7 @@ Copies `size` bytes from the RAM at address `source` into the VERA memory space
#### `struct vera_layer_setup`
Hardware register values for a video layer:
Hardware register values for a video layer. For VERA 0.7 and 0.8:
byte ctrl0
byte ctrl1
@ -50,14 +57,32 @@ Hardware register values for a video layer:
word tile_base
word hscroll
word vscroll
For VERA 0.9:
byte config
byte map_base
byte tile_base
word hscroll
word vscroll
#### `void set_vera_layer1(pointer.vera_layer_setup)`
Sets up the layer 1.
Sets up the layer 1. VERA 0.7 and 0.8 only.
On VERA 0.9, use `vera_layer0` directly.
#### `void set_vera_layer2(pointer.vera_layer_setup)`
Sets up the layer 2.
Sets up the layer 2. VERA 0.7 and 0.8 only.
On VERA 0.9, use `vera_layer1` directly.
#### `vera_layer_setup vera_layer0`
Direct access to registers for the layer 0. VERA 0.9 only.
#### `vera_layer_setup vera_layer1`
Direct access to registers for the layer 1. VERA 0.9 only.
#### `struct vera_sprite_data`
@ -69,16 +94,35 @@ Hardware register values for a sprite:
byte ctrl0
byte ctrl1
#### `const int24 VERA_COMPOSER_CTRL`
#### `void vera_upload_sprite(byte sprite_id, pointer.vera_sprite_data source)`
Uploads sprite data for given sprite id.
#### `const int24 VERA_PALETTE`
#### `const int24 VERA_LAYER_1`
#### `const int24 VERA_LAYER_2`
#### `const int24 VERA_SPRITE_CTRL`
#### `const int24 VERA_SPRITES`
Various addresses in the VERA memory space.
## `x16_joy` module
#### `const int24 VERA_COMPOSER_CTRL`
#### `const int24 VERA_LAYER_1`
#### `const int24 VERA_LAYER_2`
#### `const int24 VERA_SPRITE_CTRL`
Various addresses in the VERA memory space. VERA 0.7 and 0.8 only.
#### `void vera_reset()`
Resets the VERA.
#### `void vera_set_sprites_enable(bool enabled)`
Enables/disables sprites.
#### `void set_border(byte color)`
Changes the color of the border.
## x16_joy
The `x16_joy` module implements a joystick driver compatible with the `joy` module.
@ -117,6 +161,10 @@ Variable | SNES controller | NES controller | Keyboard (joy 1 only)
`input_b` is an alias for `input_btn`. Single-button games should use `input_btn` for compatibility.
#### `x16_joy_type joy_type`
The type of the last read joystick. One of `joy_none`, `joy_nes`, `joy_snes`, `joy_keyboard`.
## x16_joy1_default module
@ -124,3 +172,12 @@ Defines the joystick in port 1 as the default joystick.
#### `alias read_joy = read_joy1`
## x16_mouse
The `x16_mouse` module implements a mouse driver compatible with the `mouse` module.
Before using this, you may want to call `mouse_config` from the `x16_kernal` module.
#### `void read_mouse()`
Reads the state of the mouse.

36
docs/various/asmdiff.md Normal file
View File

@ -0,0 +1,36 @@
[< back to index](../doc_index.md)
# Differences in assembly
## Syntax
* High and low bytes of an 16-bit value are acquired using the `hi` and `lo` functions, not the `>` and `<` operators.
* Anonymous labels and local labels are not supported.
All labels defined in assembly are global.
Colons are required in label declarations.
* Macros are inserted using the `+` operator.
* Raw bytes are inserted using the Millfork array syntax, not with any pseudoopcode (like `!byte`, `db` or `fcb`)
* Assembly blocks cannot contain definitions of constants or variables.
* 6502: To enforce zero-page addressing, wrap the argument in the `lo` function: `lo(arg)`
* 6502: To enforce absolute addressing, add a 16-bit zero to the argument: `0000 + arg`
* GameBoy: The $FF page loads/stores are written `LDH (C),A`, not `LD ($FF00+C),A`.
* GameBoy: The loads/stores that postincrement/postdecrement HL write the HL register as `HLI` or `HLD`, not `HL+` or `HL-`
* Z80: Indexing using the index register uses the `IX(1)` syntax, not `(IX+1)` or `1(IX)`.
* Z80: Most undocumented instructions are not supported. The only one supported is `SLL`.
* 6809: `0,X` is assembled the same as `,X`.
* 6502: To enforce direct-page addressing, prepend the argument with `<`: `<arg`.

80
docs/various/cdiff.md Normal file
View File

@ -0,0 +1,80 @@
[< back to index](../doc_index.md)
# Differences from C
## Syntax
* Block comments `/* */` are not supported, use line comments `//`.
* You cannot put multiple statements on one line.
Semicolons are allowed at the end of the line, but no code can follow them.
* There are no `++` or `--` operators. Use `+= 1` and `-= 1`.
* Pointer types are declared using the `pointer.` prefix, not `*` suffix. To dereference them, use `p[0]` instead of `*p`.
* There is no unary `&` operator.
Pointers to an object are acquired using the `.pointer` suffix.
Raw addresses are acquired using the `.addr` suffix.
The numeric values of the pointer and of the raw address may differ.
* Operator precedence works differently.
Bitwise and bit-shifting operators have the same precedence as arithmetic operators,
and mixing different operators with the same precedence is usually forbidden.
This prevents most ambiguities in bit-twiddling code, but requires care when porting code from or to C.
* There is no `!` operator. The negation is expressed as the `not` function.
* The modulo operator is written `%%`. As with `/`, it's only defined for unsigned division.
* The `for` loops are range-based. Arbitrary, C-like `for` loops are not supported.
* Variable declaration and initialization have to be separate.
* Integer literals starting with zero and containing just digits are decimal, not octal.
For octal literals, use the `0o` prefix.
* String literals are not null-terminated by default. Use the `z` suffix for null-terminated strings.
Note: this is the opposite of what KickC does!
Keep this in mind when migrating KickC code to Millfork or the other way around.
* In `if`, `do/while`, `while` and `for` statements, parentheses are not required, but braces are.
The `else` branch also requires braces, unless the only statement in the `else` block is an `if` statement.
* There has to be a space between many operators and character literals,
as the parser may treat the apostrophe as a part of the operator.
## Preprocessor
* The preprocessor cannot expand symbols to something more complex than an identifier or a literal.
* The preprocessor cannot define symbols for use in other files.
* The closest to C's `#define` is `#use`.
Unlike `#define`, such definitions are not visible within the preprocessor.
* Directives like `#use` and `#pragma` affect the entire file, not just the code after the directive.
* The preprocessor cannot include files.
## Semantics
* There is no automatic integer promotion. An operation of two bytes will yield a byte. For example:
byte a
byte b
word w
w = a * b
may yield unexpected results. To prevent this, cast at least one argument:
w = word(a) * b
This issue applies mostly to the `*` and `<<` operators.
* There is no padding in structs, except before fields whose type is a struct or a union with a non-trivial alignment.

View File

@ -10,7 +10,7 @@ mostly game developers, who have little use for advanced features of C, but don'
### What was the inspiration?
The main inspirations was Atalan, but also Quetzalcoatl, Batari BASIC and NESHLA.
Sadly, Atalan has been abandoned and the compiler has been left in a non-working state.
Sadly, Atalan has been abandoned, and the compiler has been left in a non-working state.
The goal of Millfork is to succeed where Atalan failed.
### What platforms are supported?
@ -83,6 +83,10 @@ or generate a static binary and link it manually using the `file` directive.
Since the compiler is a work-in-progress, some of the mentioned issues might be improved upon in the future.
### I have experience with C and/or assembly. What should I keep in mind?
See the [differences from C](./cdiff.md) and the [differences from assembly](./asmdiff.md).
### Why is it called Millfork?
It stands for **MI**ddle **L**evel **L**anguage **FOR** **K**ommodore computers.

View File

@ -0,0 +1,107 @@
[< back to index](../doc_index.md)
# Optimization guidelines
## Command-line options
* The default options provide literally no optimizations.
Consider using at least `-O1` for quick compilation and `-O4` for release builds.
* Inlining can drastically improve performance. Add `-finline` to the command line.
* If you're not using self-modifying code or code generation,
enabling interprocedural optimizations (`-fipo`) and stdlib optimizations (`-foptimize-stdlib`) can also help.
* For convenience, all options useful for debug builds can be enabled with `-Xd`,
and for release builds with `-Xr`.
* 6502 only: If you are sure the target will have a CPU that supports so-called illegal/undocumented 6502 instructions,
consider adding the `-fillegals` option. Good examples of such targets are NES and C64.
## Alignment
* Consider adding `align(fast)` or even `align(256)` to arrays which you want to access quickly.
* 6502 only: Consider adding `align(fast)` to the hottest functions.
* If you have an array of structs, consider adding `align(X)` to the definition of the struct,
where `X` is a power of two. Even if this makes the struct 12 bytes instead of 11, it can still improve performance.
## Variables
* Use the smallest type you need. Note that Millfork supports integers of any size from 1 to 16 bytes.
* Consider using multiple arrays instead of arrays of structs.
* Avoid reusing temporary variables.
It makes it easier for the optimizer to eliminate the variable entirely.
* Mark the most frequently used local variables as `register`.
It will increase chances that those variables, and not the ones less frequently used,
are inlined into registers or put in the zeropage.
## Functions
* Write many functions with no parameters and use `-finline`.
This will simplify the job for the optimizer and increase the chances of certain powerful optimizations to apply.
* Avoid passing many parameters to functions.
Try to minimize the number of bytes passed as parameters and returned as return values.
## Loops
* For `for` loops that use a byte-sized variable and whose body does not involve function calls or further loops,
use a unique iteration variable. Such variable will have a bigger chance of being stored in a CPU register.
For example:
byte i
byte j
for i,0,until,30 { .... }
for j,0,until,40 { .... }
is usually better than:
byte i
for i,0,until,30 { .... }
for i,0,until,40 { .... }
* 8080/Z80 only: The previous tip applies also for loops using word-sized variables.
* When the iteration order is not important, use `paralleluntil` or `parallelto`.
The compiler will try to choose the optimal iteration order.
* Since 0.3.18: When the iteration order is not important,
use `for ix,ptr:array` to iterate over arrays of structs.
* 6502 only: When iterating over an array larger than 256 bytes, whose element count is a composite number,
consider splitting it into less-than-256-byte sized slices and use them within the same iteration.
For example, instead of:
word i
for i,0,paralleluntil,1000 {
screen[i] = ' 'scr
}
consider:
byte i
for i,0,paralleluntil,250 {
screen[i+000] = ' 'scr
screen[i+250] = ' 'scr
screen[i+500] = ' 'scr
screen[i+750] = ' 'scr
}
Note that the compiler might do this optimization automatically
for simpler loops with certain iteration ranges, but it is not guaranteed.
# Arithmetic
* Avoid 16-bit arithmetic. Try to keep calculations 8-bit for as long as you can.
If you can calculate the upper and lower byte of a 16-bit value separately, it's usually better to do so.
* Avoid arithmetic larger than 16-bit.
* Use `nonet` if you are sure that the result of shifting will fit into 9 bits.
Use `nonet` when doing byte addition that you want to promote to a word.

View File

@ -1,31 +1,58 @@
# Examples
The examples showcased here are designed to compile with a compiler built from the newest sources.
If you are using a release version of the compiler, consider browsing the older versions of the examples:
* [for version 0.3.28](https://github.com/KarolS/millfork/tree/v0.3.28/examples)
* [for version 0.3.26](https://github.com/KarolS/millfork/tree/v0.3.26/examples)
* [for version 0.3.24](https://github.com/KarolS/millfork/tree/v0.3.24/examples)
* [for version 0.3.22](https://github.com/KarolS/millfork/tree/v0.3.22/examples)
* [for version 0.3.18](https://github.com/KarolS/millfork/tree/v0.3.18/examples)
* [for version 0.3.16](https://github.com/KarolS/millfork/tree/v0.3.16/examples)
* [for version 0.3.14](https://github.com/KarolS/millfork/tree/v0.3.14/examples)
* [for version 0.3.12](https://github.com/KarolS/millfork/tree/v0.3.12/examples)
* [for version 0.3.10](https://github.com/KarolS/millfork/tree/v0.3.10/examples)
## Cross-platform examples
* [Hello world](crossplatform/hello_world.mfk) (C64/C16/PET/VIC-20/PET/Atari/Apple II/BBC Micro/ZX Spectrum/PC-88/Armstrad CPC/MSX) simple text output
* [Hello world](crossplatform/hello_world.mfk) (C64/C16/PET/VIC-20/Atari/Apple II/BBC Micro/ZX Spectrum/PC-88/Armstrad CPC/MSX/Z1013) simple text output
* [Fizzbuzz](crossplatform/fizzbuzz.mfk) (C64/C16/PET/VIC-20/PET/Atari/Apple II/BBC Micro/ZX Spectrum/PC-88/Armstrad CPC/MSX/X16) everyone's favourite programming task
* [Fizzbuzz 2](crossplatform/fizzbuzz2.mfk) (C64/C16/PET/VIC-20/PET/Atari/Apple II/BBC Micro/ZX Spectrum/PC-88/Armstrad CPC/MSX) an alternative, more extensible implemententation of fizzbuzz
* [Fizzbuzz 2](crossplatform/fizzbuzz2.mfk) (C64/C16/PET/VIC-20/PET/Atari/Apple II/BBC Micro/ZX Spectrum/PC-88/Armstrad CPC/MSX/CoCo) an alternative, more extensible implementation of fizzbuzz
* [Fizzbuzz JP](crossplatform/fizzbuzz_jp.mfk) (PC-88/Japanese C64) Fizzbuzz, but in Japanese
* [Text encodings](crossplatform/text_encodings.mfk) (C64/ZX Spectrum) examples of text encoding features
* [Echo](crossplatform/echo.mfk) (C64/C16/ZX Spectrum/PC-88/MSX) simple text input and output
* [Echo](crossplatform/echo.mfk) (C64/C16/VIC-20/Apple II/ZX Spectrum/PC-88/MSX) simple text input and output
* [Calculator](crossplatform/calculator.mfk) (C64/C16/ZX Spectrum/PC-88/MSX) simple numeric input and output
* [Calculator](crossplatform/calculator.mfk) (C64/C16/VIC-20/Apple II/ZX Spectrum/PC-88/MSX/TRS-80) simple numeric input and output
* [Guessing game](crossplatform/guess.mfk) (C64/C16/ZX Spectrum/PC-88/MSX) a guess-a-number game
* [Guessing game](crossplatform/guess.mfk) (C64/C16/VIC-20/Apple II/ZX Spectrum/PC-88/MSX/TRS-80/Z1013) a guess-a-number game
* [Fire effect](crossplatform/fire.mfk) (C64/C16/ZX Spectrum) a simple fire effect
* [`readkey` test](crossplatform/readkeytest.mfk) (C64/C16/PET/VIC-20/Atari/Apple II/Armstrad CPC/ZX Spectrum/PC-88/TRS-80/Z1013) keyboard reading test
* [Screen encoding test](crossplatform/screnctest.mfk) (C64/C16) default-to-screen encoding conversion test
* [Bell](crossplatform/bell.mfk) (Apple II/ZX Spectrum) a program that goes \*ding!\*
* [Life](crossplatform/life.mfk) (C64/C16/Atari/ZX Spectrum) Conway's game of life
* [Reg dump](crossplatform/regdump.mfk) (C64/C16/ZX Spectrum/CoCo) a program that simply prints the initial values of CPU registers
* [Test suite](tests) (C64/C16/Atari/Apple II/BBC Micro/Armstrad CPC/ZX Spectrum/PC-88/CoCo) the semi-official test-suite for Millfork
## Commodore 64 examples
### Graphical examples
@ -34,14 +61,14 @@
* [Softscrolling](c64/softscroll.mfk) soft-scrolling a single line of text
* [Galencia starfield](c64/galencia.mfk) a port of the starfield effect from the game *Galencia*
* [Galencia starfield](c64/galencia.mfk) a port of the starfield effect from the game *Galencia*
* [Space Poker \[external link\]](https://github.com/KarolS/spacepoker) a game made for the 2018 Reset C64 Craptastic 4KB Game Competition
### Other examples
* Multifile ([source code](c64/multifile.mfk), [platform definition](c64/multifile.ini))
how to create a program made of multiple files loaded on demand
how to create a program made of multiple files loaded on demand
* [Panic](c64/panic_test.mfk) how panic works on C64, showing the address of where it happened
@ -59,8 +86,48 @@ how to create a program made of multiple files loaded on demand
## Atari 8-bit examples
### Hardware specific examples
* [System Off example](a8/systemoff_example.mfk) programming with ROM off
* [DLI example](a8/dli_example.mfk) simple display list and display list interrupt example
* [Horizontal scroll example](a8/endless_scroll.mfk) simple horizontal scroll example
* [Vertical scroll example](a8/vertical_scroll.mfk) simple vertical scroll example
* [Horizontal stars example](a8/horizontal_stars.mfk) horizontal stars done on one missile
### Music
* [CMC Player](a8/cmcplayer.mfk) CMC player with sample music
* [MPT Player](a8/mptplayer.mfk) MPT player with sample music
### Benchmarks
* [Grand Theft Antic](a8/grand_theft_antic.mfk) ANTIC impact on CPU depending on the used graphic mode
* [GR.8 Chessboard Benchmark](a8/gr8_chessboard_benchmark.mfk) chessboard drawing benchmark in GR.8
* [FOR Countdown Benchmark](a8/countdown_for_benchmark.mfk) countdown from 1,999,999 to 0 (FOR loop)
* [WHILE Countdown Benchmark](a8/countdown_while_benchmark.mfk) countdown from 1,999,999 to 0 (WHILE loop)
* [Sieve of Eratosthenes (1899) Benchmark](a8/sieve1899.mfk) sieve of Eratosthenes, 1899 primes algorithm
* [Monte Carlo PI approximation Benchmark](a8/montecarlo_pi_benchmark.mfk) measures the efficiency of multiplication
* [Bubble Sort Benchmark](a8/bubble_sort.mfk) sort 255 elements
### Other examples
* [Test OS module](a8/a8_os_test.mfk) quick test for a8_os.mfk module
* [Rainbow example](a8/rainbow.mfk) simple scrolling rasterbars
* [Quatari Landscape](a8/landscape.mfk) part of Quatari 256B intro
## Game Boy examples
* [GB test example](gb/gbtest.mfk) a partial port of the NES example, with a rudimentary experimental text output implementation
@ -74,8 +141,10 @@ how to create a program made of multiple files loaded on demand
* [Encoding test](msx/encoding_test.mfk) text encoding test; displays three lines of text in three different languages,
no more one of which will display correctly depending on the default font of your computer.
# Commander X16 examples
## Commander X16 examples
* [Palette](x16/palette.mfk) displays the default 256-colour palette.
* [Balls](x16/balls.mfk) 16 sprites using 240 colours.
* [Joy demo](x16/joydemo.mfk) simple joystick demo.

View File

@ -0,0 +1,62 @@
pointer screen @ $84
byte i @ $80, n1 @ $81, n2 @ $82, t @ $83
array(byte) sorttable align(fast) = [for x,255,downto,1 [x]]
asm void pause() {
lda os_RTCLOK.b2
.rt_check:
cmp os_RTCLOK.b2
beq .rt_check
rts
}
// print in HEX
void printScore(byte val) {
array(byte) tmp[2]
byte iter
tmp[0] = val >> 4
tmp[1] = val & %00001111
for iter:tmp {
if tmp[iter] < 10 {
screen[0] = tmp[iter] + $10
} else {
screen[0] = tmp[iter] + $17
}
screen += 1
}
screen[0] = 0
screen += 1
}
void main(){
screen = os_SAVMSC
for i:sorttable {
printScore(sorttable[i])
}
pause()
os_RTCLOK.b2 = 0
for t,253,downto,0{
for i,0,to,253{
n1 = sorttable[i]
n2 = sorttable[i+1]
if n1>n2 {
sorttable[i] = n2
sorttable[i+1] = n1
}
}
}
t = os_RTCLOK.b2
screen = os_SAVMSC
for i:sorttable {
printScore(sorttable[i])
}
// print jiffies
printScore(t)
while true {}
}

23
examples/a8/cmcplayer.mfk Normal file
View File

@ -0,0 +1,23 @@
const word ADDRMUS = $a000
const word ADDRPLA = $b000
asm void comm(byte register(a) a, byte register(x) x, byte register(y) y) @ ADDRPLA+3 extern
asm void takt() @ ADDRPLA+6 extern
void main(){
comm($70,ADDRMUS.lo,ADDRMUS.hi)
comm(0,0,0)
while os_CH == $ff {
if antic_vcount == $10 {
antic_wsync = $e
gtia_colbk = $e
takt()
gtia_colbk = 0
}
}
comm($40,0,0)
}
const array player @ ADDRPLA = file("data/cmc_player.rep", 6)
// Music by Michal Brzezicki (Caruso) - Echo
const array music @ ADDRMUS = file("data/echo.cmc", 6)

View File

@ -0,0 +1,98 @@
byte RTCLOK @ 0
byte iter0B @ 1
word iter0W @ 2
bool run_counter @ 4
byte zpr_0 @ $24, zpr_1 @ $23, zpr_2 @ $22, zpr_3 @ $21, zpr_4 @ $20
byte zpc_0 @ $47, zpc_1 @ $46, zpc_2 @ $45, zpc_3 @ $44, zpc_4 @ $43, zpc_5 @ $42, zpc_6 @ $41
const array(byte) dl align(16) = [
$70,$70,$70,
$42,$20,0,
$41,@word[dl.addr]
]
void system_off(){
asm { sei }
antic_nmien = 0
pia_portb = $fe
os_NMIVEC = vbi.addr
run_counter = false
antic_nmien = $40
}
asm void pause() {
lda RTCLOK
.rt_check:
cmp RTCLOK
beq .rt_check
rts
}
interrupt void vbi(){
RTCLOK += 1
if run_counter{
zpr_0 += 1
if zpr_0 == 10 {
zpr_1 += 1
zpr_0 = 0
}
if zpr_1 == 10 {
zpr_2 += 1
zpr_1 = 0
}
if zpr_2 == 10 {
zpr_3 += 1
zpr_2 = 0
}
if zpr_3 == 10 {
zpr_4 += 1
zpr_3 = 0
}
}
}
void copy_block(pointer src, pointer dsc, word size){
for iter0W,0,to,size-1{
dsc[iter0W] = src[iter0W]
}
}
void set_block(pointer from, word size, byte val){
for iter0W,0,to,size-1{
from[iter0W] = val
}
}
void main(){
copy_block($e080,$4000,80)
system_off()
set_block($20,40,255)
set_block($20,5,0)
set_block($41,7,0)
pause()
antic_chbase = $40
antic_dlist = dl.addr
run_counter = true
for zpc_6,1,downto,0{
for zpc_5,9,downto,0{
for zpc_4,9,downto,0{
for zpc_3,9,downto,0{
for zpc_2,9,downto,0{
for zpc_1,9,downto,0{
for zpc_0,9,downto,0{
}
}
}
}
}
}
}
run_counter = false
while true {}
}

View File

@ -0,0 +1,119 @@
byte RTCLOK @ 0
byte iter0B @ 1
word iter0W @ 2
bool run_counter @ 4
byte zpr_0 @ $24, zpr_1 @ $23, zpr_2 @ $22, zpr_3 @ $21, zpr_4 @ $20
byte zpc_0 @ $47, zpc_1 @ $46, zpc_2 @ $45, zpc_3 @ $44, zpc_4 @ $43, zpc_5 @ $42, zpc_6 @ $41
const array(byte) dl align(16) = [
$70,$70,$70,
$42,$20,0,
$41,@word[dl.addr]
]
void system_off(){
asm { sei }
antic_nmien = 0
pia_portb = $fe
os_NMIVEC = vbi.addr
run_counter = false
antic_nmien = $40
}
asm void pause() {
lda RTCLOK
.rt_check:
cmp RTCLOK
beq .rt_check
rts
}
interrupt void vbi(){
RTCLOK += 1
if run_counter{
zpr_0 += 1
if zpr_0 == 10 {
zpr_1 += 1
zpr_0 = 0
}
if zpr_1 == 10 {
zpr_2 += 1
zpr_1 = 0
}
if zpr_2 == 10 {
zpr_3 += 1
zpr_2 = 0
}
if zpr_3 == 10 {
zpr_4 += 1
zpr_3 = 0
}
}
}
void copy_block(pointer src, pointer dsc, word size){
for iter0W,0,to,size-1{
dsc[iter0W] = src[iter0W]
}
}
void set_block(pointer from, word size, byte val){
for iter0W,0,to,size-1{
from[iter0W] = val
}
}
void main(){
copy_block($e080,$4000,80)
system_off()
set_block($20,40,255)
set_block($20,5,0)
set_block($41,7,0)
zpc_0 = 9
zpc_1 = 9
zpc_2 = 9
zpc_3 = 9
zpc_4 = 9
zpc_5 = 9
zpc_6 = 1
pause()
antic_chbase = $40
antic_dlist = dl.addr
run_counter = true
while(zpc_6 != $ff){
zpc_5 = 9
while(zpc_5 != $ff){
zpc_4 = 9
while(zpc_4 != $ff){
zpc_3 = 9
while(zpc_3 != $ff){
zpc_2 = 9
while(zpc_2 != $ff){
zpc_1 = 9
while(zpc_1 != $ff){
zpc_0 = 9
while(zpc_0 != $ff){
zpc_0 -= 1
}
zpc_1 -= 1
}
zpc_2 -= 1
}
zpc_3 -= 1
}
zpc_4 -= 1
}
zpc_5 -= 1
}
zpc_6 -= 1
}
run_counter = false
while true {}
}

Binary file not shown.

4
examples/a8/data/cmc.nfo Normal file
View File

@ -0,0 +1,4 @@
Chaos Music Composer http://atariki.krap.pl/index.php/
player modified by Marok; version 2.2 rev01-20
Example tune: Michal Brzezicki (Caruso) - Echo

Binary file not shown.

BIN
examples/a8/data/echo.cmc Normal file

Binary file not shown.

4
examples/a8/data/mpt.nfo Normal file
View File

@ -0,0 +1,4 @@
Music ProTracker http://atariki.krap.pl/index.php/Music_Protracker
player version 2.4
Example tune: Adam Bienias (SoTe): Bitter Reality - Partyland 1

Binary file not shown.

View File

@ -0,0 +1,26 @@
const word dlAddr = $3000
const word dliAddr = $3100
const array(byte) dl @ dlAddr = [
BLANK_8,BLANK_8,BLANK_8,
LMS|MODE_2,$00,$40,
MODE_2,MODE_2,MODE_2,MODE_2,
BLANK_8|DLI,
MODE_2,MODE_2,MODE_2,MODE_2,
JVB,@word[dlAddr]
]
volatile word SDLST @ $230
interrupt void dli() @ dliAddr {
gtia_colpf2 = $de
antic_wsync = 1
}
void main() {
SDLST = dl.addr
os_VDSLST = dli.addr
antic_nmien = $c0
while true {}
}

View File

@ -0,0 +1,68 @@
const word dlAddr = $3000
const word lms1Addr = $4000
const word lms2Addr = $4060
const word lms3Addr = $40c0
array(byte) dl @ dlAddr = [
$70,$70,$70,
$52, @word[lms1Addr],
$52, @word[lms2Addr],
$52, @word[lms3Addr],
$41,lo(dlAddr),hi(dlAddr)
]
noinline asm void wait(byte register(a) f) {
clc
adc os_RTCLOK.b2
.rt_check:
cmp os_RTCLOK.b2
bne .rt_check
rts
}
void main() {
word lms1 @ dlAddr + 4
word lms2 @ dlAddr + 7
word lms3 @ dlAddr + 10
byte hscroli @ $80, a, b, c
pointer screeni @ $82
hscroli = $f
screeni = lms1Addr
wait(1)
os_SDLST = dl.addr
while true {
if hscroli == $b {
a = (pokey_random & 15) + 33
b = (pokey_random & 15) + 33
c = (pokey_random & 15) + 33
screeni[0] = a
screeni[$60] = b
screeni[$c0] = c
screeni[$30] = a
screeni[$30 + $60] = b
screeni[$30 + $c0] = c
lms1 += 1
lms2 += 1
lms3 += 1
screeni += 1
if lms1 == lms1Addr + $30 {
lms1 = lms1Addr
lms2 = lms2Addr
lms3 = lms3Addr
screeni = lms1Addr
}
hscroli = $f
}
antic_hscrol = hscroli
hscroli -= 1
wait(1)
}
}

View File

@ -0,0 +1,109 @@
const word lmsAddr1 = $8400
const word lmsAddr2 = $6010
byte i@$e0, j@$e2, k@$e4, count@$e6
pointer screen@$e8
const array(byte) dl align(256) = [
$70,$70,$70,
$4f,@word[lmsAddr2],
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,
$4f,0,lmsAddr2.hi + $10,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,$0f,$0f,$0f,$0f,$0f,$0f,$0f,
$0f,
$41,@word[dl.addr]
]
const array(byte) dlPrint align(16) = [
$70,$70,$70,
$42,@word[lmsAddr1],
$41,@word[dlPrint.addr]
]
asm void pause() {
LDA os_RTCLOK.b2
.rt_check:
CMP os_RTCLOK.b2
BEQ .rt_check
RTS
}
//print HEX value
void printScore() {
array(byte) tmp[2]
byte iter
screen = lmsAddr1
os_SDLST = dlPrint.addr
tmp[0] = count >> 4
tmp[1] = count & %00001111
for iter:tmp {
if tmp[iter] < 10 {
screen[iter] = tmp[iter] + $10
} else {
screen[iter] = tmp[iter] + $17
}
}
}
void drawBoard() {
screen = lmsAddr2
os_SDLST = dl.addr
for i,7,downto,0 {
for j,23,downto,0 {
for k,3,downto,0 {
screen[0] = 255
screen[1] = 255
screen[2] = 255
screen += 6
}
screen += 16
}
if (i & 1) != 0 {
screen += 3
} else {
screen -= 3
}
}
}
void main() {
count = 0
pause()
os_RTCLOK.b2 = 0
while os_RTCLOK.b2 < 150 {
drawBoard()
count += 1
}
printScore()
while (true){}
}

View File

@ -0,0 +1,85 @@
byte i @ $b0
pointer screen @ $b2
array(word) scores[17] @ $80
asm void openmode(byte register(a) m) @ $ef9c extern
asm void pause() {
lda os_RTCLOK.b2
.rt_check:
cmp os_RTCLOK.b2
beq .rt_check
rts
}
// print in HEX
void printScore(word val) {
array(byte) tmp[4]
byte iter
tmp[0] = val.hi >> 4
tmp[1] = val.hi & %00001111
tmp[2] = val.lo >> 4
tmp[3] = val.lo & %00001111
for iter:tmp {
if tmp[iter] < 10 {
screen[iter] = tmp[iter] + $10
} else {
screen[iter] = tmp[iter] + $17
}
}
if i < 16 {
screen[4] = 0
screen[5] = 'G' atariscr
screen[6] = 'R' atariscr
screen[7] = '.' atariscr
if i < 10 {
screen[8] = i + $10
} else {
screen[8] = i + $17
}
} else {
screen[4] = 0
screen[5] = 'O' atariscr
screen[6] = 'F' atariscr
screen[7] = 'F' atariscr
}
screen += 40
}
void main(){
for i:scores {
scores[i] = 0
}
for i,0,to,15 {
openmode(i)
pause()
os_RTCLOK.b2 = 0
while os_RTCLOK.b2 < 100 {
scores[i] += 1
}
}
os_SDMCTL = 0
i = 16
pause()
os_RTCLOK.b2 = 0
while os_RTCLOK.b2 < 100 {
scores[i] += 1
}
os_SDMCTL = $22
openmode(0)
screen = os_SAVMSC
for i:scores {
printScore(scores[i])
}
while true {}
}

View File

@ -0,0 +1,23 @@
void main(){
array(byte) stars[256] align(fast)
array(byte) speed[256] align(fast)
byte i
os_PCOLR0 = $e
gtia_grafm = $e
for i:stars {
stars[i] = pokey_random
speed[i] = (pokey_random & 3) + 1
}
while true {
if antic_vcount == 0 {
for i:stars {
antic_wsync = 1
gtia_hposm0 = stars[i]
stars[i] += speed[i]
}
}
}
}

42
examples/a8/landscape.mfk Normal file
View File

@ -0,0 +1,42 @@
// idea @ilmenit
// https://demozoo.org/productions/280623
// for 8bit AtariXL, OS Rev 2
alias prev_x = os_OLDCOL.lo
alias cursor_x = os_COLCRS.lo
alias prev_y = os_OLDROW
alias cursor_y = os_ROWCRS
alias color = os_ATACHR
byte i
array(byte) color_height = [
170,150,144,144,122,122,110,110,94,94,86,86,82,80
]
asm void openmode(byte register(a) m) @ $ef9c extern
asm void drawto() @ $f9c2 extern
void main(){
openmode(9)
os_COLOR4 = $b0
for i,0,to,79 {
cursor_x = i
prev_x = i
prev_y = 1
for color,13,downto,0 {
cursor_y = color_height[color]
if pokey_random < $80 {
color_height[color] -= 1
}
if pokey_random < $80 {
color_height[color] += 1
}
drawto()
}
}
while true {}
}

View File

@ -0,0 +1,64 @@
const word probe = 9999
const word radius = 127 * 127
pointer screen @ $80
asm void pause() {
lda os_RTCLOK.b2
.rt_check:
cmp os_RTCLOK.b2
beq .rt_check
rts
}
// print in HEX
void printScore(word val) {
array(byte) tmp[4]
byte iter
tmp[0] = val.hi >> 4
tmp[1] = val.hi & %00001111
tmp[2] = val.lo >> 4
tmp[3] = val.lo & %00001111
for iter:tmp {
if tmp[iter] < 10 {
screen[iter] = tmp[iter] + $10
} else {
screen[iter] = tmp[iter] + $17
}
}
screen += 40
}
void main() {
word i@$e0, bingo@$e2
word x@$e4, y@$e6, p@$e8, t@$ea
byte n@$82
screen = os_SAVMSC
x = 0
y = 0
bingo = 0
pause()
os_RTCLOK = 0
for i,0,to,probe {
n = pokey_random & 127
x = n * word(n)
n = pokey_random & 127
y = n * word(n)
if ((x + y) <= radius) {
bingo += 1
}
}
p = 4 * bingo
t = os_RTCLOK.b2 + (os_RTCLOK.b1 * 256)
printScore(t)
printScore(p)
while true {}
}

25
examples/a8/mptplayer.mfk Normal file
View File

@ -0,0 +1,25 @@
const word ADDRMUS = $a000
const word ADDRPLA = $b000
byte stop @ ADDRPLA + $62d
asm void comm(byte register(a) a, byte register(x) x, byte register(y) y) @ ADDRPLA extern
asm void takt() @ ADDRPLA+3 extern
void main(){
comm(0,ADDRMUS.hi,ADDRMUS.lo)
comm(4,0,0)
while os_CH == $ff {
if antic_vcount == $10 {
antic_wsync = $e
gtia_colbk = $e
takt()
gtia_colbk = 0
}
}
stop = 0
}
const array player @ ADDRPLA = file("data/mpt_player.obj", 6)
// Music by Adam Bienias (SoTe): Bitter Reality - Partyland 1
const array music @ ADDRMUS = file("data/bitter_reality_4.mpt", 6)

68
examples/a8/sieve1899.mfk Normal file
View File

@ -0,0 +1,68 @@
const word size = 8192
word RTCLOK @ $13, SAVMSC @ $58
word i@$e0, prime@$e2, k@$e4, count@$e6
pointer screen@$e8
asm void pause() {
lda $14
.rt_check:
cmp $14
beq .rt_check
rts
}
// print in HEX
void printScore() {
array(byte) tmp[4]
byte iter
screen = SAVMSC
tmp[0] = RTCLOK.lo >> 4
tmp[1] = RTCLOK.lo & %00001111
tmp[2] = RTCLOK.hi >> 4
tmp[3] = RTCLOK.hi & %00001111
for iter:tmp {
if tmp[iter] < 10 {
screen[iter] = tmp[iter] + $10
} else {
screen[iter] = tmp[iter] + $17
}
}
}
void main() {
array(bool) flags[size] align(1024)
byte iter
pause()
RTCLOK = 0
for iter,9,downto,0 {
count = 0
for i:flags {
flags[i] = true
}
for i:flags {
if flags[i] {
prime = (i * 2) + 3
k = i + prime
while k <= size {
flags[k] = false
k += prime
}
count += 1
}
}
}
printScore()
while true {}
}

View File

@ -0,0 +1,137 @@
// ================================================
//
// antic_nmien = $40
//
// %01000000 $40 VBI
// %10000000 $80 DLI
// %11000000 $c0 VBI + DLI
//
// ================================================
//
// pia_portb = $fe
//
// PORTB_BASIC_OFF + PORTB_SELFTEST_OFF + %01111100
//
// PORTB_SELFTEST_OFF = %10000000; portb bit value to turn Self-Test off
// PORTB_BASIC_OFF = %00000010; portb bit value to turn Basic off
// PORTB_SYSTEM_ON = %00000001; portb bit value to turn System on
//
// ================================================
//
// Now the routine that lets you get to
// the RAM that is under the OS.
// There are actually 2 memory areas
// present:
// 4K at $C000 to $CFFF, 49152 to 53247
// 10K at $D800 to $FFFF, 55296 to 65535
//
// The last 6 bytes of the 10K area are not
// usable, since that is where the interrupt
// routines are located. Therefore do not
// use any RAM above $FFF9 (65529) or you
// will crash the system.
//
// ================================================
byte nmien = $c0
byte rti @ $15 // default routine for VBI & DLI
word vbivec @ $10 // vector for VBI
word vdslst @ $16 // vector for DLI
// simple display list; LMS = $e000
const array(byte) dl align(32) = [
$70,$70,$70,
$42,$00,$e0,2,2,$f0,2,2,2,$f0,2,2,2,
$41,@word[dl.addr]
]
// init procedure
void system_off(){
asm { sei } // turn off IRQ
antic_nmien = 0 // turn off NMI
pia_portb = $fe // turn off ROM
rti = $40 // set RTI opcode
vbivec = rti.addr // set address for VBI routine
vdslst = rti.addr // set address for DLI routine
os_NMIVEC = nmi.addr // set address for custom NMI handler
antic_nmien = nmien
}
// custom NMI handler
asm void nmi(){
bit antic_nmist // test nmist
bpl .vblclock // if 7-bit not set handle VBI
jmp (vdslst) // indirect jump to DLI routine
.vblclock: // RTCLOK maintainer
inc os_RTCLOK.b2
bne .tickend
inc os_RTCLOK.b1
bne .tickend
inc os_RTCLOK.b0
.tickend:
jmp (vbivec) // indirect jump to VBI routine
}
// example dli
interrupt asm void dli_first(){
pha
lda #$2a
sta gtia_colpf2
sta antic_wsync
lda #<dli_second.addr
sta vdslst.lo
lda #>dli_second.addr
sta vdslst.hi
pla
rti
}
// example dli
interrupt void dli_second(){
gtia_colpf2 = $de
antic_wsync = $de
vdslst = dli_first.addr
}
// wait for VBLANK
asm void pause() {
lda os_RTCLOK.b2
.rt_check:
cmp os_RTCLOK.b2
beq .rt_check
rts
}
// wait 0-255 frames
noinline asm void wait(byte register(a) f) {
clc
adc os_RTCLOK.b2
.rt_check:
cmp os_RTCLOK.b2
bne .rt_check
rts
}
// example vbi
interrupt void vbi(){
gtia_colpf2 = os_RTCLOK.b2
}
// main procedure
void main(){
system_off() // turn off OS
wait(100) // waint 2 sec on PAL for fun
antic_dlist = dl.addr // set custom display list
wait(100) // waint 2 sec on PAL for the lulz
vbivec = vbi.addr // set custom VBI
wait(100) // waint 2 sec on PAL because we can
vdslst = dli_first.addr // set custom DLI
while(true){
wait(100)
nmien ^= %10000000 // toggle DLI
antic_nmien = nmien
}
}

View File

@ -0,0 +1,37 @@
const array text align(64) = "...MILLFORK RULEZ..." atariscr
const array(byte) dl align(16) = [
$70,$70,$70,$70,
$67,@word[text.addr],
$41,@word[dl.addr]
]
noinline asm void wait(byte register(a) f) {
clc
adc os_RTCLOK.b2
.rt_check:
cmp os_RTCLOK.b2
bne .rt_check
rts
}
void main(){
byte i0B @ $80
i0B = $f
os_SDLST = dl.addr
while true {
while (i0B != 0){
i0B -= 1
antic_vscrol = i0B
wait(3)
}
wait(50)
while (i0B < $f){
i0B += 1
antic_vscrol = i0B
wait(2)
}
}
}

View File

@ -0,0 +1,37 @@
// simple demonstration of ProDOS library routines that will write
// the Disk II ROM (assuming it is in slot 6) to the file DISKII.ROM
import stdio
import apple2_prodos
void main() {
// ProDOS requires a 1K aligned page for an open file as an IO buffer
array iobuf [1024] align(256)
// you have to explicitly create a file if it doesn't exist yet
// this can fail (so you should check prodos_error
// 06 is general binary type
prodos_create("DISKII.ROM"p, $06)
if prodos_error != 0 {
// prodos error call will be returned in prodos_error so you know
// what went wrong. 0 = no error
putstrz("{n}couldn't create file"z)
panic()
}
// ProDOS file handle
byte fp
fp = prodos_open("DISKII.ROM"p, iobuf)
// should check here again for error, and after all calls
// write the disk controller ROM to the file
prodos_write(fp, $c600, 256)
// closing frees the handle and io buffer
prodos_close(fp)
putstrz("{n}DONE"z)
while true { }
}

View File

@ -37,6 +37,7 @@ HAS_BITMAP_MODE=1
; every segment should land in its own file:
style=per_segment
format=startaddr,allocated
format_segment_extra=startaddr,allocated,$ea,$ea,$ea,$ea,$ea,$ea,$ea,$ea,$ea,$ea,$ea
extension=prg

View File

@ -4,7 +4,7 @@ import stdio
import c64_basic
#elseif CBM_264
import c264_basic
#elseif ZX_SPECTRUM || NEC_PC_88
#elseif ZX_SPECTRUM || NEC_PC_88 || TRS80 || CBM_VIC
// no imports needed
#else
#error Unsupported platform

View File

@ -3,7 +3,7 @@
import c64_basic
#elseif CBM_264
import c264_basic
#elseif ZX_SPECTRUM || NEC_PC_88
#elseif CBM_VIC || ZX_SPECTRUM || NEC_PC_88
// no imports needed
#else
#error Unsupported platform
@ -15,8 +15,9 @@ void main() {
pointer line
while true {
line = readline()
// empty line is read as a single space
// empty line is read as a single space on C64
if line[0] == 32 && line[1] == 0 { return }
if line[0] == 0 { return }
putstrz(line)
new_line()
}

View File

@ -9,10 +9,17 @@ struct stage {
pointer text
}
#if ENCODING_NOLOWER
array(stage) stages = [
stage(divisible3.pointer, "FIZZ"z),
stage(divisible5.pointer, "BUZZ"z)
]
#else
array(stage) stages = [
stage(divisible3.pointer, "fizz"z),
stage(divisible5.pointer, "buzz"z)
]
#endif
void main() {
byte i, s

View File

@ -10,7 +10,7 @@ import c64_basic
import c264_basic
#endif
#define READKEY = CBM_64 | CBM_264 | ZX_SPECTRUM | NEC_PC_88
#define READKEY = CBM_64 | CBM_264 | CBM_VIC | ZX_SPECTRUM | NEC_PC_88 | APPLE_2
#if READKEY
import keyboard

View File

@ -9,7 +9,7 @@ void main() {
ensure_mixedcase()
#if CBM_64 || CBM_264
set_bg_color(green)
set_bg_color(white)
#endif
#if CBM_64 || CBM_264 || ZX_SPECTRUM
set_border(red)

View File

@ -0,0 +1,13 @@
import stdio
import keyboard
void main() {
byte c
ensure_mixedcase()
while true {
c = readkey()
putchar(c)
putchar(hi_nibble_to_hex(c))
putchar(lo_nibble_to_hex(c))
putchar(' ')
}
}

View File

@ -0,0 +1,136 @@
import stdio
struct reg {
pointer name
byte size
}
#if ARCH_6502
const array(reg) reg_defs = [reg("A"z, 1),reg("X"z, 1),reg("Y"z, 1),reg("S"z, 1),reg("P"z, 1),reg("PC"z, 2)]
macro asm void save_regs() {
JSR save_regs_inner
save_regs_inner:
STA reg_values
STX reg_values + 2
STY reg_values + 4
PHP
PLA
STA reg_values + 8
TSX
STX reg_values + 6
PLA
TAY
PLA
TAX
CPY #2
BCS save_regs_pcl_large
DEX
save_regs_pcl_large:
DEY
DEY
STY reg_values + 10
STX reg_values + 11
}
#elseif ARCH_6809
const array(reg) reg_defs = [reg("D"z, 2),reg("X"z, 2),reg("Y"z, 2),reg("U"z, 2),reg("S"z, 2),reg("CC"z, 1),reg("DP"z, 1),reg("PC"z, 2)]
macro asm void save_regs() {
PSHS PC
STD reg_values
TFR CC,B
STB reg_values+10
STB reg_values+11
STX reg_values+2
STY reg_values+4
STU reg_values+6
PULS D
SUBD #2
STD reg_values+14
STS reg_values+8
TFR DP,B
STB reg_values+12
STB reg_values+13
}
#elseif CPUFEATURE_Z80
#pragma zilog_syntax
const array(reg) reg_defs = [reg("AF"z, 2),reg("BC"z, 2),reg("DE"z, 2),reg("HL"z, 2),reg("SP"z, 2),reg("IX"z, 2),reg("IY"z, 2),reg("PC"z, 2)]
macro asm void save_regs() {
CALL save_regs_inner
save_regs_inner:
LD (reg_values+6),HL
PUSH AF
POP HL
LD (reg_values+0),HL
LD (reg_values+2),BC
LD (reg_values+3),DE
POP HL
LD B, $ff
LD C, $fd
ADD HL,BC
LD (reg_values+14),HL
LD (reg_values+10),IX
LD (reg_values+12),IY
}
#elseif ARCH_I80
#pragma intel_syntax
const array(reg) reg_defs = [reg("AF"z, 2),reg("BC"z, 2),reg("DE"z, 2),reg("HL"z, 2),reg("SP"z, 2),reg("PC"z, 2)]
macro asm void save_regs() {
CALL save_regs_inner
save_regs_inner:
LD (reg_values+6),HL
PUSH AF
POP HL
LD (reg_values+0),HL
LD H,B
LD L,C
LD (reg_values+2),HL
EX HL,DE
LD (reg_values+3),HL
POP HL
LD B, $ff
LD C, $fd
ADD HL,BC
LD (reg_values+10),HL
}
#else
#error unsupported architecture
#endif
array(word) reg_values[reg_defs.length]
void main() {
word w
byte i
pointer.reg r
save_regs()
ensure_mixedcase()
for i,r:reg_defs {
putstrz(r->name)
putchar('=')
w = reg_values[i]
if r->size == 1 {
putchar(hi_nibble_to_hex(w.lo))
putchar(lo_nibble_to_hex(w.lo))
} else {
putchar(hi_nibble_to_hex(w.hi))
putchar(lo_nibble_to_hex(w.hi))
putchar(hi_nibble_to_hex(w.lo))
putchar(lo_nibble_to_hex(w.lo))
}
new_line()
}
while true {}
}

View File

@ -627,4 +627,4 @@ const array attribute = [
// *CHARACTER ROM (GRAPHICS)*
segment(chrrom) const array graphics @ $0000 = file("tiles.chr")
segment(chrrom) const array graphics @ $0000 = file("tiles.chr", 0)

45
examples/tests/README.md Normal file
View File

@ -0,0 +1,45 @@
# The test suite
This is the semi-official test suite for Millfork standard libraries.
## Compiling
Compile the `main.mfk` file and run the resulting program.
You are advised to try various different optimization options.
millfork -t <platform> main.mfk
Supported platforms:
* Commodore 64, 128 and Plus/4, loadable program (`c64`, `c128`, `plus4`)
* Commodore PET, VIC-20, C16, loadable program (`pet`, `vic20`, `c16`)
note that support for these targets may end when the suite grows beyond their memory capacity
* ZX Spectrum (`zxspectrum`)
* NEC PC-88, bootable floppy (`pc88`)
* MSX, cartridge (`msx_crt`)
* Atari computers, loadable programs (`a8`)
* Amstrad CPC, loadable programs (`cpc464`)
* BBC Micro, loadable programs (`bbcmicro`)
* Apple II, loadable programs (`apple2`)
Compiling with the `-D PRINT_SUCCESSES` will cause the suite to print all tests, including successful ones.
Otherwise, only failed tests will be printed.
On each failed the following message will be printed:
[FAIL] <suite name> #<assertion number>
To continue, press any key (on MSX, press RETURN).
At the end of a successful run, the test suite should print
Total failures: 0

View File

@ -0,0 +1,74 @@
import stdio
pointer current_suite_name
byte current_test_number
word failure_count = 0
#if ZX_SPECTRUM || CBM || NEC_PC88 || ATARI_8 || AMSTRAD_CPC || APPLE_2 || COCO
import keyboard
alias wait_after_failure = readkey
#elseif MSX
alias wait_after_failure = readline
#else
macro void wait_after_failure() { while true {} }
#endif
void start_suite(pointer suite_name) {
putstrz("Running "z)
putstrz(suite_name)
new_line()
current_suite_name = suite_name
current_test_number = 0
}
void print_failure() {
putstrz("[FAIL]: "z)
putstrz(current_suite_name)
putstrz(" #"z)
putword(current_test_number)
new_line()
failure_count += 1
}
void print_success() {
putstrz("[ OK ]: "z)
putstrz(current_suite_name)
putstrz(" #"z)
putword(current_test_number)
new_line()
}
void assert_equal(word expected, word actual) {
current_test_number += 1
if actual != expected {
print_failure()
putstrz("Expected: "z)
putword(expected)
putstrz(" Actual: "z)
putword(actual)
new_line()
wait_after_failure()
#if PRINT_SUCCESSES
} else {
print_success()
#endif
}
}
void assert_true(bool result) {
current_test_number += 1
if not(result) {
print_failure()
readkey()
#if PRINT_SUCCESSES
} else {
print_success()
#endif
}
}

28
examples/tests/main.mfk Normal file
View File

@ -0,0 +1,28 @@
import test_fibonacci
import test_pstring
import test_string
#if ENCCONV_SUPPORTED
import test_encconv
#endif
#if MILLFORK_VERSION >= 000317
import test_template<ignored1, 1>
import test_template<ignored1, 1>
import test_template<ignored2, 2>
#endif
void main() {
ensure_mixedcase()
// readkey()
test_fibonacci()
test_string()
test_pstring()
#if ENCCONV_SUPPORTED
test_encconv()
#endif
new_line()
putstrz("Total failures: "z)
putword(failure_count)
while true {} // don't exit
}

View File

@ -0,0 +1,15 @@
import framework
import encconv
import scrstring
import string
void test_encconv() {
array buffer[16]
start_suite("encconv"z)
strzcopy(buffer, "test 132"z)
strz_to_screencode(buffer)
assert_equal(0, scrstrzcmp("test 132"scrz, buffer))
strz_from_screencode(buffer)
assert_equal(0, strzcmp("test 132"z, buffer))
}

View File

@ -0,0 +1,18 @@
import framework
word fib(byte n) {
stack byte i
i = n
if i < 2 { return 1 }
return fib(i-1) + fib(i-2)
}
void test_fibonacci() {
start_suite("Fibonacci"z)
assert_equal(1, fib(0))
assert_equal(1, fib(1))
assert_equal(2, fib(2))
assert_equal(3, fib(3))
assert_equal(5, fib(4))
}

View File

@ -0,0 +1,29 @@
import pstring
import framework
void test_pstring() {
array buffer[256]
// #1-5
start_suite("pstring"z)
assert_equal(0, pstrcmp("a"p, "a"p))
assert_equal(-1, pstrcmp("a"p, "b"p))
assert_equal(-1, pstrcmp("a"p, "ab"p))
assert_equal(1, pstrcmp("b"p, "a"p))
assert_equal(1, pstrcmp("ab"p, "a"p))
// #6-10
pstrcopy(buffer, "test"p)
assert_equal(4, pstrlen(buffer))
assert_equal(0, pstrcmp("test"p, buffer))
pstrappend(buffer, "hello"p)
assert_equal(9, pstrlen(buffer))
assert_equal(0, pstrcmp("testhello"p, buffer))
assert_equal(1234, pstr2word("1234"p))
// #11
pstrcopy(buffer, "test****test"p)
pstrpaste(buffer+5, "test"p)
assert_equal(0, pstrcmp("testtesttest"p, buffer))
}

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