diff --git a/doc/ophismanual.pdf b/doc/ophismanual.pdf
index c587636..f40b8f0 100644
Binary files a/doc/ophismanual.pdf and b/doc/ophismanual.pdf differ
diff --git a/doc/preface.sgm b/doc/preface.sgm
index 420776d..959b30c 100644
--- a/doc/preface.sgm
+++ b/doc/preface.sgm
@@ -106,35 +106,25 @@
Getting a copy of Ophis
- As of this writing, the Ophis assembler is hosted at Github. The
- latest downloads and documentation will be available
+ As of version 2.2, the Python Package Index offers Ophis
+ at .
+ This version may be installed on any system
+ where pip or pipx works.
+
+
+ Development is hosted at Github. The latest downloads and
+ documentation will be available
at . If
this is out-of-date, a Web search on Ophis 6502
assembler
(without the quotation marks) should yield its
page.
-
- Ophis is written entirely in Python and packaged using the
- distutils. The default installation script on Unix and Mac OS X
- systems should put the files where they need to go. If you are
- running it locally, you will need to install
- the Ophis package somewhere in your Python
- package path, and then put the ophis script
- somewhere in your path.
-
For Windows users, a prepackaged system made
with py2exe is also available. The default
Windows installer will use this. In this case, all you need to
do is have ophis.exe in your path.
-
- If you are working on a system with Python installed but to
- which you do not wish to install software, there is also a
- standalone pure-Python edition with an ophis.py script. This may
- be placed anywhere and running ophis.py will temporarily set the
- library path to point to your directory.
-
diff --git a/examples/hello_a800.oph b/examples/hello_a800.oph
index 2066dde..f9a9d34 100644
--- a/examples/hello_a800.oph
+++ b/examples/hello_a800.oph
@@ -1,13 +1,26 @@
+;;; HELLO WORLD for the Atari 800
+;;; This produces a file named "HELLO.OBJ" in the Atari DOS ("XEX")
+;;; format. Loading it into a DOS-capable disk will let it run
+;;; with the "LOAD BINARY FILE" command, and many emulators will
+;;; accept it as a boot image.
+
.outfile "hello.obj"
- .word $ffff ; Binary file
- .word start ; start of code
- .word end-1 ; end of code
- .org $0600 ; Load into page 6
-
- ;; `iostob OFFSET, VALUE
- ;; `iostow OFFSET, VALUE
- ;; Store value in OFFSET in I/O control block X>>4.
+ ;; Outputting text on the Atari is more reminiscent of modern
+ ;; Unix or Windows-based systems than like most 8-bit BIOSes.
+ ;; A series of 16-byte blocks of memory starting at $340 serve
+ ;; as "I/O channels", and writing text is a matter of
+ ;; outputting a string of bytes to the screen editor device in
+ ;; channel zero.
+ ;;
+ ;; Writing the arguments can be tedious, so this example
+ ;; includes two macros for simplifying that a bit: IOSTOB and
+ ;; IOSTOW (I/O Store Byte/Word). The first argument is the
+ ;; offset to write (0-15), and the second is the 8- or 16-bit
+ ;; value to write. The channel itself is selected by the X
+ ;; index register, and the value in .X should be the
+ ;; destination channel multiplied by 16 (so, 0 for channel 0,
+ ;; $10 for channel 1, etc.)
.macro iostob
lda #_2
sta $340+_1,x
@@ -18,17 +31,59 @@
`iostob _1+1,>_2
.macend
-start: ldx #$00 ; Channel 0 (E:)
+ ;; With that out of the way, we may start producing our
+ ;; actual file. We open with a $FFFF word to mark ourselves
+ ;; as a binary file.
+ .word $ffff
- ;; Write message with one I/O call, and exit
- `iostob 2,11 ; WRITE command
+ ;; The rest of the file is a series of blocks, marking the
+ ;; first and last addresses that the block occupies, followed
+ ;; by the data itself. These addresses are inclusive, so we
+ ;; will need to subtract one from a label placed after the
+ ;; final line of the block to get the correct value.
+ .word start
+ .word end-1
+
+ ;; The main program block begins here. The .org instruction
+ ;; sets us to assemble at the location we want the program
+ ;; to actually live; this ensures that the start and end
+ ;; labels have the correct values. For this program, we will
+ ;; load into location $0600 --- the $0600-$06FF region ("page
+ ;; six") is reserved for use by support cartridges, but BASIC
+ ;; doesn't use it and the OS is guaranteed not to.
+ .org $0600
+
+ ;; The program itself does a single write request.
+start: ldx #$00 ; I/O request on Channel 0
+ `iostob 2,11 ; request type: WRITE
`iostow 4,msg ; buffer pointer
- `iostow 8,msgend-msg ; buffer length
- jmp $e456 ; Do I/O call and quit
+ `iostow 8,msglen ; buffer length
+ jsr $e456 ; Do I/O call
+ ;; This program intends to return to DOS once it's done, so
+ ;; it returns with RTS. If this were to be a program to boot
+ ;; directly into the emulator, going into an infinite loop
+ ;; would be more polite.
+ rts ; Return to DOS
+
+ ;; The message itself. Character $9B is the new-line on the
+ ;; Atari 800. Strings are written with length arguments here
+ ;; instead of with a terminator character, so we collect the
+ ;; length of the string here as well.
msg: .byte "Hello, world!",$9b
-msgend: ; End of message
-end: ; End of code block
+ .alias msglen ^-msg
- ;; Autostart at start
+ ;; The end of the main file block. This mark lets the block
+ ;; header compute the correct address.
+end:
+
+ ;; Two memory locations are special during load. If a block
+ ;; load rewrites the word at $02E2, the load process will be
+ ;; interrupted and will call the routine at the address
+ ;; written to that location. $02E0 is similar, but the word
+ ;; written is taken to be the address of the start of the
+ ;; program, and controll will pass to that address once the
+ ;; load is complete. We don't need any intervening init
+ ;; routines, so we close by putting our entry point in $02e0
+ ;; as a two-byte block in its own right.
.word $02e0,$02e1,start
diff --git a/examples/hello_apple2.oph b/examples/hello_apple2.oph
index afec144..608a6fb 100644
--- a/examples/hello_apple2.oph
+++ b/examples/hello_apple2.oph
@@ -1,31 +1,40 @@
-;;; ----------------------------------------------------------------------
-;;; HELLO WORLD for the Apple II
-;;; This is a ProDOS 8 program. Its output should be importable by
-;;; CiderPress without incident.
-;;; ----------------------------------------------------------------------
-
- .outfile "HI.SYSTEM#ff2000"
- .org $2000
-
- ;; Write message
- ldx #$00
-* lda msg,x
- beq wait
- ora #$80 ; Disable inverse
- jsr $fded ; CHROUT
- inx
- bne -
-
- ;; Wait for keypress
-wait: bit $c000 ; Check keypress bit
- bpl wait
- bit $c010 ; Acknowledge keypress
-
- ;; Return to ProDOS
- jsr $bf00
- .byte $65
- .word +
- brk ; Unreachable
-* .byte 4, 0, 0, 0, 0, 0, 0
-
-msg: .byte "HELLO, WORLD!",13,"PRESS ANY KEY TO EXIT",0
+;;; ----------------------------------------------------------------------
+;;; HELLO WORLD for the Apple II
+;;; This is a ProDOS 8 program. Its output should be importable by
+;;; CiderPress without incident, and by CADIUS with only minor changes.
+;;; ----------------------------------------------------------------------
+
+ ;; All ProDOS 8 programs are loaded into location $2000 and
+ ;; own the memory from $0800 to $BEFF, as well as all of the
+ ;; zero page except for $30-$4F. The suffix of the output
+ ;; file is used by CiderPress to mark file type and
+ ;; attributes -- for ProDOS 8 programs this type is always
+ ;; $FF (System file) and the attribute is always $2000 (the
+ ;; load address). Be sure to set the option to infer type
+ ;; and attributes from filenames when adding files in
+ ;; CiderPress.
+ .outfile "HI.SYSTEM#ff2000"
+ .org $2000
+
+ ;; Write message
+ ldx #$00
+* lda msg,x
+ beq wait
+ ora #$80 ; Disable inverse
+ jsr $fded ; CHROUT
+ inx
+ bne -
+
+ ;; Wait for keypress
+wait: bit $c000 ; Check keypress bit
+ bpl wait
+ bit $c010 ; Acknowledge keypress
+
+ ;; Return to ProDOS with a QUIT call
+ jsr $bf00
+ .byte $65
+ .word +
+ brk ; Unreachable
+* .byte 4, 0, 0, 0, 0, 0, 0
+
+msg: .byte "HELLO, WORLD!",13,"PRESS ANY KEY TO EXIT",0