diff --git a/README.md b/README.md index a396a6d..d16a403 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,10 @@ SixtyPical _Version 0.21. Work-in-progress, everything is subject to change._ +**SixtyPical** brings [extended static checking][] to the [6502][]. + **SixtyPical** is a [low-level](#low-level) programming language -supporting a sophisticated [static analysis](#static-analysis). +supporting some advanced [static analysis](#static-analysis) methods. Its reference compiler can generate [efficient code](#efficient-code) for several 6502-based [target platforms](#target-platforms) while catching many common mistakes at compile-time, reducing the time spent in debugging. @@ -124,7 +126,9 @@ Documentation * [Output formats supported by `sixtypical`](doc/Output%20Formats.md) * [TODO](TODO.md) +[6502]: https://en.wikipedia.org/wiki/MOS_Technology_6502 [MOS Technology 6502]: https://en.wikipedia.org/wiki/MOS_Technology_6502 +[extended static checking]: https://en.wikipedia.org/wiki/Extended_static_checking [effect system]: https://en.wikipedia.org/wiki/Effect_system [abstractly interprets]: https://en.wikipedia.org/wiki/Abstract_interpretation [calling conventions]: https://en.wikipedia.org/wiki/Calling_convention diff --git a/TODO.md b/TODO.md index 7b08e56..8be7282 100644 --- a/TODO.md +++ b/TODO.md @@ -55,6 +55,14 @@ What happens if a routine calls itself, directly or indirectly? Many constraints might be violated in this case. We should probably disallow recursion by default. (Which means assembling the callgraph in all cases.) +However note, it's okay for a routine to goto itself. It's a common +pattern for implementing a state machine, for a routine to tail-goto a +vector, which might contain the address of the same routine. + +The problems only come up, I think, when a routine calls itself re-entrantly. + +So the callgraph would need to distinguish between these two cases. + ### Analyze memory usage If you define two variables that occupy the same address, an analysis error ought @@ -83,6 +91,23 @@ Implementation For analysis errors, there is a line number, but it's the line of the routine after the routine in which the analysis error occurred. Fix this. +### Better selection of options + +`-O` should turn on the standard optimizations. + +There should maybe be a flag to turn off tail-call optimization. + +Some options should automatically add the appropriate architecture include +directory to the path. + +Distribution +------------ + +### Demo game + +Seems you're not be able to get killed unless you go off the top or bottom of +the screen? In particular, you cannot collide with a bar? + Blue-skying ----------- diff --git a/eg/README.md b/eg/README.md index 9268429..289839c 100644 --- a/eg/README.md +++ b/eg/README.md @@ -13,24 +13,8 @@ to serve as manual integration test cases. See In the [c64](c64/) directory are programs that run on the Commodore 64. The directory itself contains some simple demos, for example [hearts.60p](c64/hearts.60p), while there are subdirectories for more -elaborate demos: - -* [demo-game](c64/demo-game/): a little game-like program written as a - "can we write something you'd see in practice?" test case for SixtyPical. - -* [ribos](c64/ribos/): a well-commented example of a C64 raster interrupt - routine. Originally written with the P65 assembler (which has since - been reborn as [Ophis][]). - - The second version of Ribos has been translated to SixtyPical. - -* [petulant](c64/petulant/): "The PETulant Cursor", a tiny (44 bytes) - "display hack". Originally written in the late 80's. Rewritten with - the P65 assembler (now Ophis) and re-released on April 1st, 2008 (a - hint as to its nature). - - Translated to SixtyPical (in 2018), after adding some optimizations - to the SixtyPical compiler, the resulting executable is still 44 bytes! +elaborate demos, like the flagship demo game. See +[the README in that directory](c64/README.md) for details. ### vic20 diff --git a/eg/c64/README.md b/eg/c64/README.md index a953e06..b63c514 100644 --- a/eg/c64/README.md +++ b/eg/c64/README.md @@ -1,5 +1,23 @@ This directory contains SixtyPical example programs specifically for the Commodore 64. -See the [README in the parent directory](../README.md) for -more information on these example programs. +There are subdirectories for more elaborate demos: + +* [demo-game](demo-game/): a little game-like program written as a + "can we write something you'd see in practice?" test case for SixtyPical. + +* [ribos](ribos/): a well-commented example of a C64 raster interrupt + routine. Originally written with the P65 assembler (which has since + been reborn as [Ophis][]). + + The second version of Ribos has been translated to SixtyPical. + +* [petulant](petulant/): "The PETulant Cursor", a tiny (44 bytes) + "display hack". Originally written in the late 80's. Rewritten with + the P65 assembler (now Ophis) and re-released on April 1st, 2008 (a + hint as to its nature). + + Translated to SixtyPical (in 2018), after adding some optimizations + to the SixtyPical compiler, the resulting executable is still 44 bytes! + +[Ophis]: http://michaelcmartin.github.io/Ophis/ diff --git a/eg/c64/demo-game/demo-game.60p b/eg/c64/demo-game/demo-game.60p index 027f2cc..11fcc8d 100644 --- a/eg/c64/demo-game/demo-game.60p +++ b/eg/c64/demo-game/demo-game.60p @@ -2,7 +2,7 @@ // * Demo Game for SixtyPical * // **************************** -include "joy2delta.60p" +include "joystick.60p" // ---------------------------------------------------------------- // Type Definitions @@ -103,38 +103,6 @@ vector game_state_routine // Utility Routines // ---------------------------------------------------------------- -// You can repeatedly (i.e. as part of actor logic or an IRQ handler) -// call this routine. -// Upon return, if carry is set, the button was pressed then released. - -define check_button routine - inputs joy2 - outputs c - trashes a, z, n - static byte button_down : 0 -{ - ld a, button_down - if z { - ld a, joy2 - and a, $10 - if z { - ld a, 1 - st a, button_down - } - st off, c - } else { - ld a, joy2 - and a, $10 - if not z { - ld a, 0 - st a, button_down - st on, c - } else { - st off, c - } - } -} - define clear_screen routine outputs screen, colormap trashes a, y, c, n, z diff --git a/eg/c64/demo-game/run.sh b/eg/c64/demo-game/run.sh new file mode 100755 index 0000000..1086985 --- /dev/null +++ b/eg/c64/demo-game/run.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# This script builds and runs the demo game. You need +# the VICE emulatore installed, in particular VICE's x64. + +# You might want a `vicerc` file like the following: +# [C64] +# VICIIDoubleScan=0 +# VICIIDoubleSize=0 +# KeySet1NorthWest=0 +# KeySet1North=273 +# KeySet1NorthEast=0 +# KeySet1East=275 +# KeySet1SouthEast=0 +# KeySet1South=274 +# KeySet1SouthWest=0 +# KeySet1West=276 +# KeySet1Fire=306 +# KeySetEnable=1 +# JoyDevice1=0 +# JoyDevice2=2 + +../../../bin/sixtypical --run-on x64 -I ../../../include/c64/ demo-game.60p diff --git a/eg/c64/joystick.60p b/eg/c64/joystick-demo.60p similarity index 89% rename from eg/c64/joystick.60p rename to eg/c64/joystick-demo.60p index 0558426..faeb949 100644 --- a/eg/c64/joystick.60p +++ b/eg/c64/joystick-demo.60p @@ -1,4 +1,4 @@ -include "joy2delta.60p" +include "joystick.60p" word screen @ 1024 diff --git a/include/c64/joy2delta.60p b/include/c64/joy2delta.60p deleted file mode 100644 index ff1b583..0000000 --- a/include/c64/joy2delta.60p +++ /dev/null @@ -1,36 +0,0 @@ -byte joy2 @ $dc00 - -word delta - -define read_stick routine - inputs joy2 - outputs delta - trashes a, x, z, n -{ - ld x, joy2 - ld a, x - and a, 1 // up - if z { - copy $ffd8, delta // -40 - } else { - ld a, x - and a, 2 // down - if z { - copy word 40, delta - } else { - ld a, x - and a, 4 // left - if z { - copy $ffff, delta // -1 - } else { - ld a, x - and a, 8 // right - if z { - copy word 1, delta - } else { - copy word 0, delta - } - } - } - } -} diff --git a/include/c64/joystick.60p b/include/c64/joystick.60p new file mode 100644 index 0000000..faf41c1 --- /dev/null +++ b/include/c64/joystick.60p @@ -0,0 +1,71 @@ +byte joy2 @ $dc00 + +word delta + +// Read the joystick and compute the delta it represents +// in a row-based 40-column grid like the C64's screen. + +define read_stick routine + inputs joy2 + outputs delta + trashes a, x, z, n +{ + ld x, joy2 + ld a, x + and a, 1 // up + if z { + copy $ffd8, delta // -40 + } else { + ld a, x + and a, 2 // down + if z { + copy word 40, delta + } else { + ld a, x + and a, 4 // left + if z { + copy $ffff, delta // -1 + } else { + ld a, x + and a, 8 // right + if z { + copy word 1, delta + } else { + copy word 0, delta + } + } + } + } +} + +// You can repeatedly (i.e. as part of actor logic or an IRQ handler) +// call this routine. +// Upon return, if carry is set, the button was pressed then released. + +define check_button routine + inputs joy2 + outputs c + trashes a, z, n + static byte button_down : 0 +{ + ld a, button_down + if z { + ld a, joy2 + and a, $10 + if z { + ld a, 1 + st a, button_down + } + st off, c + } else { + ld a, joy2 + and a, $10 + if not z { + ld a, 0 + st a, button_down + st on, c + } else { + st off, c + } + } +}